kernel/0216-release-1230.patch
2025-01-02 22:30:57 -05:00

13026 lines
353 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 7825407dbf0d143b0ee2538d9821594103693654 Mon Sep 17 00:00:00 2001
From: linmin <linmin@eswincomputing.com>
Date: Fri, 27 Dec 2024 16:54:16 +0800
Subject: [PATCH 216/222] release-1230
Changelogs:
1.fix:improve numa-node-id of each module
2.fix:npu die1 clock miss
3.feat:clk support set default cpu freq
4.fix:dsp pm devfreq bug fix
5.feat:fix bug for z530 reboot Strange noise
6.feat:fix 96k palyback error
7.fix:Resolve the issue of abnormal stack in audio.
8.fix:buffer overflow by print info
9.feat:change mode 0660
10.fix:7702 interleave can not display issue
11.feat:Select cipher as default
12.feat:adapt eth dly params to 7702 interleave dts.
13.fix:Delete HDMI Audio error printing.
14.fix:fix the DSP issue of perf function on die1.
15.chore:disable IPA adjust with target
16.feat:hdmi support 2880x1800@90 output.
17.feat:audio perf for rtc processing
18.fix: npu devfeq bug fix
19.feat: DMA memcopy kernel driver.
20.feat:add interleave dts
21.fix:fix the issue of no pcm node on die1.
22.feat:modify sdio's delay to adapt to z530.
23.fix:DSP driver add switch for perf function.
24.fix:NPU driver add switch for perf function.
25.fix:fix the issue of audio recording.
26.feat:adapt eth driver to board z530.
27.feat:support z530 board
28.fix:audio driver add 24 bits support.
29.feat:Add API for remapping malloc buffer
30.fix : remove error message when try lock failed Changelogs:
31.fix:adjust HDMI phy voltage.
32.feat:audio add sof func
Signed-off-by: linmin <linmin@eswincomputing.com>
---
arch/riscv/boot/dts/eswin/Makefile | 5 +-
arch/riscv/boot/dts/eswin/eic7700-d314.dts | 335 ++++
arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts | 10 +-
arch/riscv/boot/dts/eswin/eic7700-evb-a3.dts | 3 +-
arch/riscv/boot/dts/eswin/eic7700-evb.dts | 10 +-
.../dts/eswin/eic7700-hifive-premier-p550.dts | 10 +-
.../boot/dts/eswin/eic7700-som260-a1.dtsi | 724 ++++++++
arch/riscv/boot/dts/eswin/eic7700-som314.dtsi | 688 ++++++++
arch/riscv/boot/dts/eswin/eic7700-z530.dts | 198 +++
.../boot/dts/eswin/eic7702-evb-a1-d0.dts | 10 +-
.../boot/dts/eswin/eic7702-evb-a1-d1.dts | 10 +-
.../dts/eswin/eic7702-evb-a1-interleave.dts | 1560 +++++++++++++++++
arch/riscv/boot/dts/eswin/eic7702-evb-a1.dts | 18 +-
.../boot/dts/eswin/eic770x-ooptable.dtsi | 185 ++
.../dts/eswin/eswin-win2030-arch-d2d.dtsi | 18 +-
.../boot/dts/eswin/eswin-win2030-arch.dtsi | 27 +-
.../dts/eswin/eswin-win2030-die0-noc.dtsi | 5 +
.../dts/eswin/eswin-win2030-die0-soc.dtsi | 218 ++-
.../dts/eswin/eswin-win2030-die1-noc.dtsi | 6 +-
.../dts/eswin/eswin-win2030-die1-soc.dtsi | 182 +-
arch/riscv/configs/eic7700_defconfig | 5 +-
arch/riscv/configs/eic7702_defconfig | 5 +-
arch/riscv/configs/win2030_defconfig | 1 +
drivers/clk/eswin/clk-win2030.c | 41 +-
drivers/clocksource/timer-eswin.c | 97 +-
drivers/dma-buf/dma-heap.c | 1 +
drivers/gpu/drm/eswin/Makefile | 2 +-
drivers/gpu/drm/eswin/dw-hdmi.c | 7 +-
drivers/gpu/drm/eswin/dw-hdmi.h | 2 +-
drivers/gpu/drm/eswin/dw_hdmi_audio.h | 2 +-
drivers/gpu/drm/eswin/dw_hdmi_cec.c | 2 +-
drivers/gpu/drm/eswin/dw_hdmi_cec.h | 2 +-
drivers/gpu/drm/eswin/dw_hdmi_hdcp.c | 2 +-
drivers/gpu/drm/eswin/dw_hdmi_hdcp.h | 2 +-
drivers/gpu/drm/eswin/dw_hdmi_hdcp2.c | 2 +-
drivers/gpu/drm/eswin/dw_hdmi_i2s_audio.c | 2 +-
drivers/gpu/drm/eswin/es_dc.c | 38 +-
drivers/gpu/drm/eswin/es_dc.h | 3 +
drivers/gpu/drm/eswin/es_drv.c | 11 +-
.../eswin/{eswin_dw_hdmi.c => es_dw_hdmi.c} | 16 +-
drivers/interconnect/eswin/noc.c | 2 +-
drivers/memory/eswin/Kconfig | 1 +
drivers/memory/eswin/Makefile | 1 +
drivers/memory/eswin/codacache/llc_spram.c | 252 ++-
drivers/memory/eswin/es_dma_memcp/Kconfig | 6 +
drivers/memory/eswin/es_dma_memcp/Makefile | 1 +
.../memory/eswin/es_dma_memcp/es_dma_memcp.c | 604 +++++++
.../dmabuf-heap-import-helper.c | 187 ++
.../ethernet/stmicro/stmmac/dwmac-win2030.c | 87 +-
drivers/regulator/es5340.c | 2 -
drivers/soc/eswin/ai_driver/Kconfig | 10 +
drivers/soc/eswin/ai_driver/dsp/Makefile | 4 +
drivers/soc/eswin/ai_driver/dsp/dsp_main.c | 158 +-
.../soc/eswin/ai_driver/dsp/dsp_platform.c | 17 +-
.../soc/eswin/ai_driver/dsp/dsp_platform.h | 2 +-
.../eswin/ai_driver/dsp/dsp_platform_sim.c | 2 +-
drivers/soc/eswin/ai_driver/npu/Makefile | 5 +-
drivers/soc/eswin/ai_driver/npu/dla_driver.h | 10 +-
drivers/soc/eswin/ai_driver/npu/npu_main.c | 215 ++-
drivers/soc/eswin/ai_driver/npu/nvdla_hw.c | 91 +-
.../soc/eswin/ai_driver/npu/nvdla_lowlevel.h | 1 +
.../soc/eswin/ai_driver/npu/user_context.c | 29 +-
.../media/eswin/dewarp/vvcam_dwe_driver.c | 78 +
.../os/linux/kernel/gc_hal_kernel_driver.c | 7 +-
.../eswin/gc_hal_kernel_platform_win2030.c | 87 +-
drivers/staging/media/eswin/vdec/hantro_dec.c | 77 +
.../staging/media/eswin/venc/vc8000e_driver.c | 79 +
include/linux/dmabuf-heap-import-helper.h | 2 +
include/uapi/linux/dma_memcp.h | 62 +
sound/soc/codecs/eswin/es8328.c | 55 +-
sound/soc/codecs/eswin/es8328.h | 24 +-
sound/soc/eswin/Kconfig | 7 +-
sound/soc/eswin/Makefile | 2 +-
sound/soc/eswin/esw-audio-proc.c | 26 +-
sound/soc/eswin/esw-dai.h | 62 +
sound/soc/eswin/esw-dma.c | 485 +++++
sound/soc/eswin/esw-i2s.c | 405 +++--
sound/soc/eswin/esw-i2s.h | 53 +-
sound/soc/eswin/esw-sof-dai.c | 299 ++++
sound/soc/sof/Kconfig | 1 +
sound/soc/sof/Makefile | 1 +
sound/soc/sof/eswin/Kconfig | 34 +
sound/soc/sof/eswin/Makefile | 6 +
sound/soc/sof/eswin/es-common.c | 591 +++++++
sound/soc/sof/eswin/es-common.h | 137 ++
sound/soc/sof/eswin/es-sof-dsp.c | 614 +++++++
86 files changed, 8682 insertions(+), 664 deletions(-)
create mode 100644 arch/riscv/boot/dts/eswin/eic7700-d314.dts
create mode 100644 arch/riscv/boot/dts/eswin/eic7700-som260-a1.dtsi
create mode 100644 arch/riscv/boot/dts/eswin/eic7700-som314.dtsi
create mode 100644 arch/riscv/boot/dts/eswin/eic7700-z530.dts
create mode 100644 arch/riscv/boot/dts/eswin/eic7702-evb-a1-interleave.dts
create mode 100644 arch/riscv/boot/dts/eswin/eic770x-ooptable.dtsi
rename drivers/gpu/drm/eswin/{eswin_dw_hdmi.c => es_dw_hdmi.c} (99%)
create mode 100644 drivers/memory/eswin/es_dma_memcp/Kconfig
create mode 100644 drivers/memory/eswin/es_dma_memcp/Makefile
create mode 100644 drivers/memory/eswin/es_dma_memcp/es_dma_memcp.c
create mode 100644 include/uapi/linux/dma_memcp.h
create mode 100644 sound/soc/eswin/esw-dai.h
create mode 100644 sound/soc/eswin/esw-dma.c
create mode 100644 sound/soc/eswin/esw-sof-dai.c
create mode 100644 sound/soc/sof/eswin/Kconfig
create mode 100644 sound/soc/sof/eswin/Makefile
create mode 100644 sound/soc/sof/eswin/es-common.c
create mode 100644 sound/soc/sof/eswin/es-common.h
create mode 100644 sound/soc/sof/eswin/es-sof-dsp.c
diff --git a/arch/riscv/boot/dts/eswin/Makefile b/arch/riscv/boot/dts/eswin/Makefile
index b3925240449f..4f8d4275c021 100644
--- a/arch/riscv/boot/dts/eswin/Makefile
+++ b/arch/riscv/boot/dts/eswin/Makefile
@@ -4,5 +4,8 @@ dtb-$(CONFIG_SOC_SIFIVE) += eswin-win2030.dtb \
eic7700-evb-a2.dtb \
eic7700-evb-a3.dtb \
eic7700-hifive-premier-p550.dtb \
- eic7702-evb-a1.dtb
+ eic7702-evb-a1.dtb \
+ eic7700-z530.dtb \
+ eic7700-d314.dtb \
+ eic7702-evb-a1-interleave.dtb
obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
diff --git a/arch/riscv/boot/dts/eswin/eic7700-d314.dts b/arch/riscv/boot/dts/eswin/eic7700-d314.dts
new file mode 100644
index 000000000000..f8bfb293fcfa
--- /dev/null
+++ b/arch/riscv/boot/dts/eswin/eic7700-d314.dts
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for Eswin EIC7700 SoC.
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+
+#include "eic7700-som314.dtsi"
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "ESWIN 7700D314";
+};
+
+&pcie {
+ /* GPIO12 PCIE PRSNT input */
+};
+
+&d0_usbdrd_dwc3_1 {
+ usb-hub {
+ gpio-hog;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio43_default>;
+ gpios = <&portb 11 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "usb-hub-reset";
+ };
+};
+
+&dsi_panel {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio82_default &pinctrl_gpio85_default>;
+ backlight0-gpios = <&portc 18 GPIO_ACTIVE_HIGH>;
+ rst-gpios = <&portc 21 GPIO_ACTIVE_HIGH>;
+};
+
+&d0_i2s1 {
+ status = "okay";
+ d0_i2s1_port: port {
+ d0_i2s1_endpoint: endpoint {
+ remote-endpoint = <&d0_codec0_endpoint>;
+ dai-format = "i2s";
+ };
+ };
+};
+
+&d0_i2s2 {
+ /* connect WIFI module */
+ status = "disabled";
+};
+
+&d0_graphcard1 {
+ status = "okay";
+ label = "Analog Audio";
+ dais = <&d0_i2s1_port>;
+};
+
+&d0_graphcard2 {
+ status = "disabled";
+};
+
+&isp_0 {
+ status = "disabled";
+};
+
+&isp_1 {
+ status = "disabled";
+};
+
+&sdio0 {
+ /* sd card */
+ status = "okay";
+ delay_code = <0x55>;
+ drive-impedance-ohm = <33>;
+ enable-cmd-pullup;
+ enable-data-pullup;
+ no-sdio;
+ no-mmc;
+};
+
+&sdio1 {
+ /* wifi module */
+ status = "okay";
+ delay_code = <0x29>;
+ drive-impedance-ohm = <33>;
+ enable-cmd-pullup;
+ enable-data-pullup;
+ non-removable;
+ keep-power-in-suspend;
+ no-sd;
+ no-mmc;
+ aw3155:wifi_aw3155@0 {
+ compatible = "aml_w1_sdio";
+ reg = <0x0>;
+ interrupt-parent = <&porta>;
+ interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&pinctrl_gpio15_default>;
+ pinctrl-1 = <&pinctrl_gpio79_default>;
+ irq-gpios = <&porta 15 GPIO_ACTIVE_HIGH>;
+ rst-gpios = <&portc 15 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&d0_sata {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sata_act_led_default>;
+};
+
+&d0_uart1 {
+ /* M.2 KEY E */
+ status = "disabled";
+};
+
+&d0_uart2 {
+ /* connect MCU */
+ status = "okay";
+};
+
+&d0_uart3 {
+ /* pin header mux with GPIO 92,93 */
+ status = "disabled";
+};
+
+&d0_uart4 {
+ /* unused */
+ status = "disabled";
+};
+
+&ssi0 {
+ /* pin header mux with GPIO 35,36,37,38,39,40 */
+ status = "disabled";
+};
+
+&ssi1 {
+ /* unused */
+ status = "disabled";
+};
+
+&d0_i2c0 {
+ /* codec es8388 */
+ status = "okay";
+ d0_es8388_0: es8388-0@11 {
+ compatible = "eswin,es8388";
+ reg = <0x11>;
+ #sound-dai-cells = <0>;
+ eswin-plat = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio0_default &pinctrl_gpio28_default>;
+ front-jack-gpios = <&porta 0 GPIO_ACTIVE_HIGH>;
+ back-jack-gpios = <&porta 28 GPIO_ACTIVE_HIGH>;
+ port {
+ d0_codec0_endpoint: endpoint {
+ system-clock-frequency = <12288000>;
+ remote-endpoint = <&d0_i2s1_endpoint>;
+ };
+ };
+ };
+};
+
+&d0_i2c1 {
+ /* pin header mux with GPIO 46,47 */
+ status = "disabled";
+};
+
+&d0_i2c2 {
+ /* mipi dsi touch ctrl con */
+ status = "disabled";
+};
+
+&d0_i2c3 {
+ /* FUSB303B cc logic */
+ status = "okay";
+ fusb303b@21 {
+ compatible = "fcs,fusb303b";
+ status = "okay";
+ reg = <0x21>;
+ eswin,syscfg = <&d0_sys_con 0x3C0 12>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio5_default>;
+ int-gpios = <&porta 5 GPIO_ACTIVE_HIGH>;
+ connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ data-role = "host";
+ };
+ };
+
+};
+
+&d0_i2c4 {
+ /* unused */
+ status = "disabled";
+};
+
+&d0_i2c5 {
+ /* PCA9548 */
+ status = "okay";
+};
+
+&d0_i2c6 {
+ /* unused */
+ status = "disabled";
+};
+
+&d0_i2c7 {
+ /* unused */
+ status = "disabled";
+};
+
+&d0_i2c8 {
+ /* unused */
+ status = "disabled";
+};
+
+&d0_i2c9 {
+ /* unused */
+ status = "disabled";
+};
+
+&d0_aon_i2c0 {
+ /* AT24C02C EEPROM */
+ status = "okay";
+ eswin,syscfg = <&d0_sys_con 0x3C0 16>;
+ aon_eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+ };
+};
+
+&d0_aon_i2c1 {
+ /* PCA9450 & SiC451 & INA226 & PAC1934 */
+ status = "okay";
+ eswin,syscfg = <&d0_sys_con 0x3C0 15>;
+ i2c-sda-hold-time-ns = <0x40>;
+ pac1934:pmic@10 {
+ compatible = "microchip,pac1934";
+ /*update all register data*/
+ update_time_ms = <1000>;
+ eswin,chan_label = "som vdd", "soc vdd", "cpu vdd", "ddr lpvdd";
+ label = "som_info";
+ /*The update number of times the energy accumulates*/
+ energy_acc_count = <0>;
+ shunt_resistors=<1 1 1 1>;
+ reg = <0x10>;
+ };
+
+ sys_power:ina226@44 {
+ compatible = "ti,ina226";
+ #io-channel-cells = <1>;
+ label = "sys_power";
+ reg = <0x44>;
+ shunt-resistor = <1000>;
+ };
+
+ mpq8785@12 {
+ compatible = "mps,mpq8785";
+ reg = <0x12>;
+ eswin,regulator_default-microvolt=<1000000>;
+ eswin,regulator_label = "supply vdd1", "npu vdd1", "npu current1", "npu temperature1";
+ label = "npu_vdd";
+ regulators{
+ npu_vcc1:npu_svcc{
+ regulator-name="NPU_SVCC";
+ regulator-min-microvolt=<700000>;
+ regulator-max-microvolt=<1100000>;
+ regulator-min-microamp=<20000000>;
+ regulator-max-microamp=<40000000>;
+ regulator-ov-protection-microvolt=<1100000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&pinctrl {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio6_default &pinctrl_gpio7_default &pinctrl_gpio8_default &pinctrl_gpio9_default
+ &pinctrl_gpio10_default &pinctrl_gpio17_default &pinctrl_gpio35_default &pinctrl_gpio36_default
+ &pinctrl_gpio37_default &pinctrl_gpio38_default &pinctrl_gpio39_default &pinctrl_gpio40_default
+ &pinctrl_gpio41_default &pinctrl_gpio46_default &pinctrl_gpio52_default
+ &pinctrl_gpio53_default &pinctrl_gpio64_default &pinctrl_gpio65_default &pinctrl_gpio66_default
+ &pinctrl_gpio67_default &pinctrl_gpio70_default &pinctrl_gpio73_default &pinctrl_gpio83_default
+ &pinctrl_gpio86_default &pinctrl_gpio87_default &pinctrl_gpio92_default &pinctrl_gpio93_default
+ &pinctrl_gpio94_default>;
+
+ /* pin header default function for GPIO
+ SPI1 (CS0,SCLK,MOSI,MISO,D2,D3): GPIO 35,36,37,38,39,40
+ I2C1 (SCL,SDA): GPIO 46,47
+ UART3(TX,RX): GPIO 92,93
+ */
+};
+
+/*
+GPIO USED ON CarrierBoard:
+ gpio0 : FP Audio Jack Sense(I), active low
+ gpio5 : TYPE C cc logic interrupt(I), active low
+ gpio11 : BT WAKE HOST(I), active low
+ gpio12 : PCIE present(I), active low
+ gpio14 : DSI FPC CON CTRL(J10&J11)
+ gpio15 : Wlan wake host(I), active low
+ gpio28 : RP audio jack sense(I), active low
+ gpio29 : EMMC active led ctrl(O)
+
+ gpio43 : USB3.2 Gen1 hub Resetn(O), active low
+ gpio71 : CSI fpc con ctrl(O)
+ gpio74 : CSI fpc con ctrl(O)
+ gpio77 : CSI fpc con ctrl(O)
+ gpio76 : HOST WAKE BT(O), active low
+ gpio79 : WLAN POWER ON(O), active high
+ gpio80 : CSI fpc con ctrl(O)
+ gpio82 : DSI FPC CON CTRL(J10)
+ gpio85 : DSI FPC CON CTRL(J11)
+ gpio84 : GPIO LED CTRL(O), active high
+*/
diff --git a/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts b/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts
index 1ea82a170c60..42a2eb700568 100644
--- a/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts
+++ b/arch/riscv/boot/dts/eswin/eic7700-evb-a2.dts
@@ -285,6 +285,7 @@ &pcie {
&d0_npu{
status = "okay";
+ npu-supply=<&npu_vcc1>;
};
&d0_dsp_subsys {
@@ -507,7 +508,9 @@ &d0_gmac0 {
rst-gpios = <&portc 30 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x290 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
-
+ dly-param-1000m = <0x23232323 0x800c8023 0x0c0c0c0c>;
+ dly-param-100m = <0x50505050 0x803f8050 0x3f3f3f3f>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
@@ -517,7 +520,9 @@ &d0_gmac1 {
rst-gpios = <&porta 16 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x294 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
-
+ dly-param-1000m = <0x25252525 0x80268025 0x26262626>;
+ dly-param-100m = <0x48484848 0x80588048 0x58585858>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
@@ -727,7 +732,6 @@ npu_vcc1:npu_svcc{
regulator-min-microamp=<20000000>;
regulator-max-microamp=<40000000>;
regulator-ov-protection-microvolt=<1100000>;
- regulator-always-on;
};
};
};
diff --git a/arch/riscv/boot/dts/eswin/eic7700-evb-a3.dts b/arch/riscv/boot/dts/eswin/eic7700-evb-a3.dts
index 47b490f8c6c1..bfc99f105556 100644
--- a/arch/riscv/boot/dts/eswin/eic7700-evb-a3.dts
+++ b/arch/riscv/boot/dts/eswin/eic7700-evb-a3.dts
@@ -29,9 +29,10 @@ &d0_clock {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio95_default>;
cpu-voltage-gpios = <&portc 31 GPIO_ACTIVE_HIGH>;
+ cpu-default-frequency = <CLK_FREQ_1600M>;
};
-&d0_cpu_opp_table {
+&cpu_opp_table {
opp-1500000000 {
opp-hz = /bits/ 64 <CLK_FREQ_1500M>;
opp-microvolt = <900000>;
diff --git a/arch/riscv/boot/dts/eswin/eic7700-evb.dts b/arch/riscv/boot/dts/eswin/eic7700-evb.dts
index fe56de5b1699..a6226cc932b6 100644
--- a/arch/riscv/boot/dts/eswin/eic7700-evb.dts
+++ b/arch/riscv/boot/dts/eswin/eic7700-evb.dts
@@ -246,6 +246,7 @@ &pcie {
&d0_npu{
status = "okay";
+ npu-supply=<&npu_vcc1>;
};
&d0_dsp_subsys {
@@ -466,7 +467,9 @@ &d0_gmac0 {
rst-gpios = <&portc 30 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x290 0x3>;
eswin,led-cfgs = <0x6251 0x6251 0x6251>;
-
+ dly-param-1000m = <0x23232323 0x800c8023 0x0c0c0c0c>;
+ dly-param-100m = <0x50505050 0x803f8050 0x3f3f3f3f>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
@@ -476,7 +479,9 @@ &d0_gmac1 {
rst-gpios = <&porta 16 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x294 0x3>;
eswin,led-cfgs = <0x6251 0x6251 0x6251>;
-
+ dly-param-1000m = <0x25252525 0x80268025 0x26262626>;
+ dly-param-100m = <0x48484848 0x80588048 0x58585858>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
@@ -770,7 +775,6 @@ npu_vcc1:npu_svcc{
regulator-min-microamp=<20000000>;
regulator-max-microamp=<40000000>;
regulator-ov-protection-microvolt=<1100000>;
- regulator-always-on;
};
};
};
diff --git a/arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts b/arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts
index d4225cf45d5b..ca2edb1eb7e5 100644
--- a/arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts
+++ b/arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dts
@@ -240,6 +240,7 @@ &pcie {
&d0_npu{
status = "okay";
+ npu-supply=<&npu_vcc1>;
};
&d0_dsp_subsys {
@@ -456,6 +457,9 @@ &d0_gmac0 {
rst-gpios = <&portd 10 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x290 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
+ dly-param-1000m = <0x23232323 0x800c8023 0x0c0c0c0c>;
+ dly-param-100m = <0x50505050 0x803f8050 0x3f3f3f3f>;
+ dly-param-10m = <0 0 0>;
};
&d0_gmac1 {
@@ -465,6 +469,9 @@ &d0_gmac1 {
rst-gpios = <&portd 15 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x294 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
+ dly-param-1000m = <0x25252525 0x80268025 0x26262626>;
+ dly-param-100m = <0x48484848 0x80588048 0x58585858>;
+ dly-param-10m = <0 0 0>;
};
&d0_sata {
@@ -838,6 +845,7 @@ gpio111 : gphy1 resern(O), active low
&gpio0 {
status = "okay";
};
+
&dev_llc_d0{
/* apply_npu_1G_freq; */
npu-supply=<&npu_vcc1>;
@@ -849,7 +857,7 @@ &d0_clock {
cpu-voltage-gpios = <&portc 30 GPIO_ACTIVE_HIGH>;
};
-&d0_cpu_opp_table {
+&cpu_opp_table {
opp-1500000000 {
opp-hz = /bits/ 64 <CLK_FREQ_1500M>;
opp-microvolt = <900000>;
diff --git a/arch/riscv/boot/dts/eswin/eic7700-som260-a1.dtsi b/arch/riscv/boot/dts/eswin/eic7700-som260-a1.dtsi
new file mode 100644
index 000000000000..8975632b0325
--- /dev/null
+++ b/arch/riscv/boot/dts/eswin/eic7700-som260-a1.dtsi
@@ -0,0 +1,724 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for Eswin EIC7700 SoC.
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+
+#define RTCCLK_FREQ 1000000
+#define LSPCLK_FREQ 200000000
+
+/* If wanna enable ECC capability of DDR, should reserve highest zone of 1/8 all space for it */
+#define MEMORY_SIZE_H 0x4
+#define MEMORY_SIZE_L 0x0
+#define CMA_SIZE 0x20000000
+
+#include "eswin-win2030-die0-soc.dtsi"
+#include "eic7700-pinctrl.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/* Clock frequency (in Hz) of the PCB crystal for rtcclk */
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "ESWIN 7700S260";
+ compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000",
+ "sifive,fu740", "eswin,eic7700";
+
+ aliases {
+ serial0 = &d0_uart0;
+ ethernet0 = &d0_gmac0;
+ ethernet1 = &d0_gmac1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ opensbi_domain_config: domain-config {
+ compatible = "opensbi,domain,config";
+ system-suspend-test;
+ };
+ };
+
+ cpus {
+ timebase-frequency = <RTCCLK_FREQ>;
+ };
+
+ memory@59000000 {
+ device_type = "memory";
+ reg = <0x0 0x59000000 0x0 0x400000>;
+ numa-node-id = <0>;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 MEMORY_SIZE_H MEMORY_SIZE_L>;
+ numa-node-id = <0>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 CMA_SIZE>;
+ alignment = <0x0 0x1000>;
+ alloc-ranges = <0x0 0x80000000 MEMORY_SIZE_H MEMORY_SIZE_L>;
+ linux,cma-default;
+ };
+
+ npu0_reserved: sprammemory@59000000 {
+ no-map;
+ reg = <0x0 0x59000000 0x0 0x400000>;
+ };
+
+ g2d_4GB_boundary_reserved_4k {
+ no-map;
+ reg = <0x0 0xfffff000 0x0 0x1000>;
+ };
+
+ g2d_8GB_boundary_reserved_4k {
+ no-map;
+ reg = <0x1 0xfffff000 0x0 0x1000>;
+ };
+
+ g2d_12GB_boundary_reserved_4k {
+ no-map;
+ reg = <0x2 0xfffff000 0x0 0x1000>;
+ };
+
+ mmz_nid_0_part_0 {
+ compatible = "eswin-reserve-memory";
+ reg = <0x3 0x0 0x1 0x80000000>;
+ no-map;
+ };
+ };
+};
+
+/****************************************************
+ Carrier board device capability, need be adapted by user according to the carrier board implemented.
+ All of below modules are configured to okay by default, and need be reconfigured by user in dts of carrier board.
+ pcie
+ d0_sata
+ d0_usbdrd3_0
+ d0_usbdrd3_1
+ dw_hdmi
+ mipi csi(2 lanes) x4
+ mipi dsi(4 lanes)
+ sdio0
+ sdio1
+ d0_i2c0
+ d0_i2c1
+ d0_i2c2
+ aon_i2c0
+ d0_uart0
+ d0_uart1
+ d0_uart2
+ d0_uart4
+ ssi0
+ ssi1
+ pwm1
+ pwm2
+ gpio
+ d0_gmac0
+ d0_gmac1
+****************************************************/
+
+&cpu_opp_table {
+ opp-1500000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1500M>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-1600000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1600M>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-1700000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1700M>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1800M>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <70000>;
+ };
+};
+
+&d0_clock {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio94_default>;
+ cpu-voltage-gpios = <&portc 30 GPIO_ACTIVE_HIGH>;
+};
+
+&d0_reset {
+ status = "okay";
+};
+
+&d0_pmu {
+ status = "okay";
+};
+
+&ddr0 {
+ status = "okay";
+};
+
+&ddr1 {
+ status = "okay";
+};
+
+&smmu0 {
+ status = "okay";
+};
+
+&smmu_pmu0 {
+ status = "disabled";
+};
+
+&dev_foo_a {
+ status = "okay";
+};
+
+&d0_cfg_noc {
+ status = "okay";
+};
+
+&d0_llc_noc {
+ status = "okay";
+ stat,0 = "TracePort:ddr0_p0_req";
+ stat,1 = "TracePort:ddr1_p0_req";
+ //latency,0 = "TracePort:llcnoc_trans_probe";
+ //pending,0 = "TracePort:llcnoc_trans_probe";
+};
+
+&d0_sys_noc {
+ status = "okay";
+
+ //eswin,DSPT-qos-owner;
+ //eswin,NPU-qos-owner;
+ //eswin,SPISLV_TBU3-qos-owner;
+
+#if 0
+ stat,0 = "TracePort:ddr0_p1_req",
+ "InitFlow:mcput_snoc_mp/I/0";
+
+ stat,1 = "TracePort:ddr0_p2_req",
+ "InitFlow:dspt_snoc/I/0",
+ "AddrBase:0x81000000", "AddrSize:0x30",
+ "Opcode:RdWrLockUrg", "Status:ReqRsp", "Length:0x8000", "Urgency:0x0";
+
+ stat,2 = "TracePort:ddr1_p1_req",
+ "Status:Req", "AddrSize:0x28";
+
+ stat,3 = "TracePort:ddr1_p2_req";
+#else
+ stat,0 = "TracePort:ddr0_p1_req";
+
+ stat,1 = "TracePort:ddr0_p2_req";
+
+ stat,2 = "TracePort:ddr1_p1_req";
+
+ stat,3 = "TracePort:ddr1_p2_req";
+#endif
+
+ latency,0 = "TracePort:sysnoc_trans_probe_0", "AddrSize:0x0";
+ latency,1 = "TracePort:sysnoc_trans_probe_1","Mode:latency","AddrBase:0x82000000","AddrSize:0x28","Opcode:RdWr";
+ //latency,2 = "TracePort:sysnoc_trans_probe_2";
+
+ //pending,0 = "TracePort:sysnoc_trans_probe_0";
+ //pending,1 = "TracePort:sysnoc_trans_probe_1","Mode:latency","AddrBase:0x82000000","AddrSize:0x0","Opcode:RdWr";
+ pending,0 = "TracePort:sysnoc_trans_probe_2", "AddrSize:0x3";
+};
+
+&d0_media_noc {
+ status = "okay";
+
+ //eswin,GPU-qos-owner;
+ //eswin,TBU2-qos-owner;
+ //eswin,VC-qos-owner;
+
+ stat,0 = "TracePort:ddr0_p3_req";
+ stat,1 = "TracePort:ddr1_p3_req";
+ //latency,0 = "TracePort:mnoc_trans_probe";
+ //pending,0 = "TracePort:mnoc_trans_probe";
+};
+
+&d0_realtime_noc {
+ status = "okay";
+
+ //eswin,TBU0-qos-owner;
+ //eswin,VO-qos-owner;
+
+ stat,0 = "TracePort:ddr0_p4_req";
+ stat,1 = "TracePort:ddr1_p4_req";
+ //latency,0 = "TracePort:rnoc_trans_probe";
+ //pending,0 = "TracePort:rnoc_trans_probe";
+};
+
+&d0_noc_wdt {
+ status = "okay";
+};
+
+&d0_ipc_scpu {
+ status = "okay";
+};
+
+&d0_lpcpu {
+ status = "okay";
+};
+
+&pcie {
+ status = "okay";
+};
+
+&d0_npu{
+ status = "okay";
+};
+
+&d0_dsp_subsys {
+ status = "okay";
+};
+
+&d0_dsp0 {
+ status = "okay";
+};
+
+&d0_dsp1 {
+ status = "okay";
+};
+
+&d0_dsp2 {
+ status = "okay";
+};
+
+&d0_dsp3 {
+ status = "okay";
+};
+
+&gpu0 {
+ status = "okay";
+};
+
+&gc820 {
+ status = "okay";
+};
+
+&vdec0 {
+ status = "okay";
+};
+
+&venc0 {
+ status = "okay";
+};
+
+&video_output {
+ status = "okay";
+};
+
+&dc {
+ status = "okay";
+};
+
+&dc_test {
+ status = "disabled";
+};
+
+&virtual_display {
+ status = "okay";
+};
+
+&dsi_output {
+ status = "okay";
+};
+
+&dsi_controller {
+ status = "okay";
+};
+
+&dsi_panel {
+ /* backlight0-gpios, rst-gpios */
+ status = "okay";
+};
+
+&dw_hdmi {
+ status = "okay";
+ ports {
+ port@2 {
+ reg = <2>;
+ hdmi_in_i2s: endpoint@1 {
+ system-clock-frequency = <12288000>;
+ remote-endpoint = <&d0_i2s0_endpoint>;
+ };
+ };
+ };
+};
+
+&dw_hdmi_hdcp2 {
+ status = "okay";
+};
+
+&d0_i2s0 {
+ status = "okay";
+ d0_i2s0_port: port {
+ d0_i2s0_endpoint: endpoint {
+ remote-endpoint = <&hdmi_in_i2s>;
+ dai-format = "i2s";
+ };
+ };
+};
+
+&d0_graphcard0 {
+ status = "okay";
+ label = "HDMI Audio";
+ dais = <&d0_i2s0_port>;
+};
+
+&isp_0 {
+ status = "okay";
+};
+
+&isp_1 {
+ status = "okay";
+};
+
+&dewarp {
+ status = "okay";
+};
+
+&mipi_dphy_rx {
+ status = "okay";
+};
+
+&csi_dma0 {
+ status = "okay";
+};
+
+&csi_dma1 {
+ status = "disabled";
+};
+
+&csi2_0 {
+ status = "okay";
+};
+
+&csi2_1 {
+ status = "disabled";
+};
+
+&sdhci_emmc {
+ /* emmc */
+ status = "okay";
+ delay_code = <0x17>;
+ drive-impedance-ohm = <50>;
+ enable-cmd-pullup;
+ enable-data-pullup;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_emmc_led_control_default>;
+ no-sdio;
+ no-sd;
+};
+
+&sdio0 {
+ status = "okay";
+};
+
+&sdio1 {
+ status = "okay";
+};
+
+&d0_gmac0 {
+ pinctrl-names = "default";
+ eswin,rgmiisel = <&pinctrl 0x290 0x3>;
+ eswin,led-cfgs = <0x6100 0xa40 0x420>;
+ status = "okay";
+};
+
+&d0_gmac1 {
+ pinctrl-names = "default";
+ eswin,rgmiisel = <&pinctrl 0x294 0x3>;
+ eswin,led-cfgs = <0x6100 0xa40 0x420>;
+ status = "okay";
+};
+
+&d0_sata {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sata_act_led_default>;
+};
+
+&d0_usbdrd3_0 {
+ status = "okay";
+};
+
+&d0_usbdrd_dwc3_0 {
+ status = "okay";
+ dr_mode = "host";
+ maximum-speed = "super-speed";
+};
+
+&d0_usbdrd3_1 {
+ status = "okay";
+};
+
+&d0_usbdrd_dwc3_1 {
+ status = "okay";
+ dr_mode = "host";
+ maximum-speed = "super-speed";
+};
+
+&d0_dmac0 {
+ status = "okay";
+};
+
+&d0_aon_dmac {
+ status = "okay";
+};
+
+&d0_uart0 {
+ /* debug */
+ status = "okay";
+};
+
+&d0_uart1 {
+ status = "okay";
+};
+
+&d0_uart2 {
+ status = "okay";
+};
+
+&d0_uart3 {
+ /* no provide */
+ status = "disabled";
+};
+
+&d0_uart4 {
+ status = "okay";
+};
+
+&ssi0 {
+ status = "okay";
+};
+
+&ssi1 {
+ status = "disabled";
+};
+
+&bootspi {
+ /* spi flash */
+ status = "okay";
+ num-cs = <1>;
+ cs-gpios = <&portd 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&portd 4 GPIO_ACTIVE_LOW>;
+ spi-flash@0 {
+ compatible = "winbond,w25q128jw",
+ "jedec,spi-nor";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <4800000>;
+ rx-sample-delay-ns = <10>;
+ };
+};
+
+&d0_mbox0 {
+ status = "okay";
+};
+
+&d0_mbox1 {
+ status = "okay";
+};
+
+&d0_mbox2 {
+ status = "okay";
+};
+
+&d0_mbox3 {
+ status = "okay";
+};
+
+&d0_mbox4 {
+ status = "okay";
+};
+
+&d0_mbox5 {
+ status = "okay";
+};
+
+&d0_mbox6 {
+ status = "okay";
+};
+
+&d0_mbox7 {
+ status = "okay";
+};
+
+&fan_control {
+ status = "okay";
+ eswin,pwm_inverted;
+};
+
+&d0_i2c0 {
+ status = "okay";
+};
+
+&d0_i2c1 {
+ status = "okay";
+};
+
+&d0_i2c2 {
+ status = "okay";
+};
+
+&d0_i2c3 {
+ /* no provide */
+ status = "disabled";
+};
+
+&d0_i2c4 {
+ /* no provide */
+ status = "disabled";
+};
+
+&d0_i2c5 {
+ /* tmp102 */
+ status = "okay";
+ tmp102@48 {
+ compatible = "ti,tmp102";
+ reg = <0x48>;
+ label = "d0_board_tmp";
+ #thermal-sensor-cells = <1>;
+ };
+};
+
+&d0_i2c6 {
+ /* no provide */
+ status = "disabled";
+};
+
+&d0_i2c7 {
+ /* no provide */
+ status = "disabled";
+};
+
+&d0_i2c8 {
+ /* no provide */
+ status = "disabled";
+};
+
+&d0_i2c9 {
+ /* no provide */
+ status = "disabled";
+};
+
+&d0_aon_i2c0 {
+ status = "okay";
+};
+
+&d0_aon_i2c1 {
+ /* pmic es5340 */
+ status = "okay";
+ es5340@f {
+ compatible = "einno,es5340";
+ reg = <0xf>;
+ eswin,regulator_default-microvolt=<1000000>;
+ eswin,regulator_label = "supply vdd1", "npu vdd1", "npu current1", "npu temperature1";
+ label = "npu_vdd";
+ regulators{
+ npu_vcc1:npu_svcc{
+ regulator-name="NPU_SVCC";
+ regulator-min-microvolt=<700000>;
+ regulator-max-microvolt=<1100000>;
+ regulator-min-microamp=<20000000>;
+ regulator-max-microamp=<40000000>;
+ regulator-ov-protection-microvolt=<1100000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&pwm0 {
+ /* fan */
+ status = "okay";
+};
+
+&pvt0 {
+ status = "okay";
+};
+
+&pvt1 {
+ status = "okay";
+};
+
+&wdt0 {
+ status = "disabled";
+};
+
+&wdt1 {
+ status = "disabled";
+};
+
+&wdt2 {
+ status = "disabled";
+};
+
+&wdt3 {
+ status = "disabled";
+};
+
+&die0_rtc {
+ status = "okay";
+};
+
+&timer0 {
+ status = "okay";
+};
+
+&timer1 {
+ status = "okay";
+};
+
+&timer2 {
+ status = "okay";
+};
+
+&timer3 {
+ status = "okay";
+};
+
+&pinctrl {
+ status = "okay";
+};
+
+&gpio0 {
+ status = "okay";
+};
+&dev_llc_d0{
+ /* apply_npu_1G_freq; */
+ npu-supply=<&npu_vcc1>;
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/eswin/eic7700-som314.dtsi b/arch/riscv/boot/dts/eswin/eic7700-som314.dtsi
new file mode 100644
index 000000000000..79a885bb2c62
--- /dev/null
+++ b/arch/riscv/boot/dts/eswin/eic7700-som314.dtsi
@@ -0,0 +1,688 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for Eswin EIC7700 SoC.
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+
+#define RTCCLK_FREQ 1000000
+#define LSPCLK_FREQ 200000000
+
+/* If wanna enable ECC capability of DDR, should reserve highest zone of 1/8 all space for it */
+#define MEMORY_SIZE_H 0x4
+#define MEMORY_SIZE_L 0x0
+#define CMA_SIZE 0x20000000
+
+#include "eswin-win2030-die0-soc.dtsi"
+#include "eic7700-pinctrl.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/* Clock frequency (in Hz) of the PCB crystal for rtcclk */
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "ESWIN 7700S314";
+ compatible = "eswin,eic7700";
+
+ aliases {
+ serial0 = &d0_uart0;
+ ethernet0 = &d0_gmac0;
+ ethernet1 = &d0_gmac1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ opensbi_domain_config: domain-config {
+ compatible = "opensbi,domain,config";
+ system-suspend-test;
+ };
+ };
+
+ cpus {
+ timebase-frequency = <RTCCLK_FREQ>;
+ };
+
+ memory@59000000 {
+ device_type = "memory";
+ reg = <0x0 0x59000000 0x0 0x400000>;
+ numa-node-id = <0>;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 MEMORY_SIZE_H MEMORY_SIZE_L>;
+ numa-node-id = <0>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 CMA_SIZE>;
+ alignment = <0x0 0x1000>;
+ alloc-ranges = <0x0 0x80000000 MEMORY_SIZE_H MEMORY_SIZE_L>;
+ linux,cma-default;
+ };
+
+ npu0_reserved: sprammemory@59000000 {
+ no-map;
+ reg = <0x0 0x59000000 0x0 0x400000>;
+ };
+
+ g2d_4GB_boundary_reserved_4k {
+ no-map;
+ reg = <0x0 0xfffff000 0x0 0x1000>;
+ };
+
+ g2d_8GB_boundary_reserved_4k {
+ no-map;
+ reg = <0x1 0xfffff000 0x0 0x1000>;
+ };
+
+ g2d_12GB_boundary_reserved_4k {
+ no-map;
+ reg = <0x2 0xfffff000 0x0 0x1000>;
+ };
+
+ mmz_nid_0_part_0 {
+ compatible = "eswin-reserve-memory";
+ reg = <0x3 0x0 0x1 0x80000000>;
+ no-map;
+ };
+ };
+};
+
+&d0_clock {
+ status = "okay";
+};
+
+&d0_reset {
+ status = "okay";
+};
+
+&d0_pmu {
+ status = "okay";
+};
+
+&ddr0 {
+ status = "okay";
+};
+
+&ddr1 {
+ status = "okay";
+};
+
+&smmu0 {
+ status = "okay";
+};
+
+&smmu_pmu0 {
+ status = "disabled";
+};
+
+&dev_foo_a {
+ status = "okay";
+};
+
+&d0_cfg_noc {
+ status = "okay";
+};
+
+&d0_llc_noc {
+ status = "okay";
+ stat,0 = "TracePort:ddr0_p0_req";
+ stat,1 = "TracePort:ddr1_p0_req";
+ //latency,0 = "TracePort:llcnoc_trans_probe";
+ //pending,0 = "TracePort:llcnoc_trans_probe";
+};
+
+&d0_sys_noc {
+ status = "okay";
+
+ //eswin,DSPT-qos-owner;
+ //eswin,NPU-qos-owner;
+ //eswin,SPISLV_TBU3-qos-owner;
+
+#if 0
+ stat,0 = "TracePort:ddr0_p1_req",
+ "InitFlow:mcput_snoc_mp/I/0";
+
+ stat,1 = "TracePort:ddr0_p2_req",
+ "InitFlow:dspt_snoc/I/0",
+ "AddrBase:0x81000000", "AddrSize:0x30",
+ "Opcode:RdWrLockUrg", "Status:ReqRsp", "Length:0x8000", "Urgency:0x0";
+
+ stat,2 = "TracePort:ddr1_p1_req",
+ "Status:Req", "AddrSize:0x28";
+
+ stat,3 = "TracePort:ddr1_p2_req";
+#else
+ stat,0 = "TracePort:ddr0_p1_req";
+
+ stat,1 = "TracePort:ddr0_p2_req";
+
+ stat,2 = "TracePort:ddr1_p1_req";
+
+ stat,3 = "TracePort:ddr1_p2_req";
+#endif
+
+ latency,0 = "TracePort:sysnoc_trans_probe_0", "AddrSize:0x0";
+ latency,1 = "TracePort:sysnoc_trans_probe_1","Mode:latency","AddrBase:0x82000000","AddrSize:0x28","Opcode:RdWr";
+ //latency,2 = "TracePort:sysnoc_trans_probe_2";
+
+ //pending,0 = "TracePort:sysnoc_trans_probe_0";
+ //pending,1 = "TracePort:sysnoc_trans_probe_1","Mode:latency","AddrBase:0x82000000","AddrSize:0x0","Opcode:RdWr";
+ pending,0 = "TracePort:sysnoc_trans_probe_2", "AddrSize:0x3";
+};
+
+&d0_media_noc {
+ status = "okay";
+
+ //eswin,GPU-qos-owner;
+ //eswin,TBU2-qos-owner;
+ //eswin,VC-qos-owner;
+
+ stat,0 = "TracePort:ddr0_p3_req";
+ stat,1 = "TracePort:ddr1_p3_req";
+ //latency,0 = "TracePort:mnoc_trans_probe";
+ //pending,0 = "TracePort:mnoc_trans_probe";
+};
+
+&d0_realtime_noc {
+ status = "okay";
+
+ //eswin,TBU0-qos-owner;
+ //eswin,VO-qos-owner;
+
+ stat,0 = "TracePort:ddr0_p4_req";
+ stat,1 = "TracePort:ddr1_p4_req";
+ //latency,0 = "TracePort:rnoc_trans_probe";
+ //pending,0 = "TracePort:rnoc_trans_probe";
+};
+
+&d0_noc_wdt {
+ status = "okay";
+};
+
+&d0_ipc_scpu {
+ status = "okay";
+};
+
+&d0_lpcpu {
+ status = "okay";
+};
+
+&pcie {
+ status = "okay";
+};
+
+&d0_npu{
+ status = "okay";
+};
+
+&d0_dsp_subsys {
+ status = "okay";
+};
+
+&d0_dsp0 {
+ status = "okay";
+};
+
+&d0_dsp1 {
+ status = "okay";
+};
+
+&d0_dsp2 {
+ status = "okay";
+};
+
+&d0_dsp3 {
+ status = "okay";
+};
+
+&gpu0 {
+ status = "okay";
+};
+
+&gc820 {
+ status = "okay";
+};
+
+&vdec0 {
+ status = "okay";
+};
+
+&venc0 {
+ status = "okay";
+};
+
+&video_output {
+ status = "okay";
+};
+
+&dc {
+ status = "okay";
+};
+
+&dc_test {
+ status = "disabled";
+};
+
+&virtual_display {
+ status = "okay";
+};
+
+&dsi_output {
+ status = "okay";
+};
+
+&dsi_controller {
+ status = "okay";
+};
+
+&dsi_panel {
+ status = "okay";
+};
+
+&dw_hdmi {
+ status = "okay";
+ ports {
+ port@2 {
+ reg = <2>;
+ hdmi_in_i2s: endpoint@1 {
+ system-clock-frequency = <12288000>;
+ remote-endpoint = <&d0_i2s0_endpoint>;
+ };
+ };
+ };
+};
+
+&dw_hdmi_hdcp2 {
+ status = "okay";
+};
+
+&d0_i2s0 {
+ status = "okay";
+ d0_i2s0_port: port {
+ d0_i2s0_endpoint: endpoint {
+ remote-endpoint = <&hdmi_in_i2s>;
+ dai-format = "i2s";
+ };
+ };
+};
+
+&d0_i2s1 {
+ status = "okay";
+};
+
+&d0_i2s2 {
+ status = "okay";
+};
+
+&d0_graphcard0 {
+ status = "okay";
+ label = "HDMI Audio";
+ dais = <&d0_i2s0_port>;
+};
+
+&isp_0 {
+ status = "okay";
+};
+
+&isp_1 {
+ status = "okay";
+};
+
+&dewarp {
+ status = "okay";
+};
+
+&mipi_dphy_rx {
+ status = "disabled";
+};
+
+&csi_dma0 {
+ status = "disabled";
+};
+
+&csi_dma1 {
+ status = "disabled";
+};
+
+&csi2_0 {
+ status = "disabled";
+};
+
+&csi2_1 {
+ status = "disabled";
+};
+
+&sdhci_emmc {
+ /* emmc */
+ status = "okay";
+ delay_code = <0x17>;
+ drive-impedance-ohm = <50>;
+ enable-cmd-pullup;
+ enable-data-pullup;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_emmc_led_control_default>;
+ no-sdio;
+ no-sd;
+};
+
+&sdio0 {
+ status = "okay";
+};
+
+&sdio1 {
+ status = "okay";
+};
+
+&d0_gmac0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio106_default>;
+ rst-gpios = <&portd 10 GPIO_ACTIVE_LOW>;
+ eswin,rgmiisel = <&pinctrl 0x290 0x3>;
+ eswin,led-cfgs = <0x6100 0xa40 0x420>;
+ dly-param-1000m = <0x23232323 0x800c8023 0x0c0c0c0c>;
+ dly-param-100m = <0x50505050 0x803f8050 0x3f3f3f3f>;
+ dly-param-10m = <0 0 0>;
+};
+
+&d0_gmac1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio111_default>;
+ rst-gpios = <&portd 15 GPIO_ACTIVE_LOW>;
+ eswin,rgmiisel = <&pinctrl 0x294 0x3>;
+ eswin,led-cfgs = <0x6100 0xa40 0x420>;
+ dly-param-1000m = <0x25252525 0x80268025 0x26262626>;
+ dly-param-100m = <0x48484848 0x80588048 0x58585858>;
+ dly-param-10m = <0 0 0>;
+};
+
+&d0_sata {
+ status = "okay";
+};
+
+&d0_usbdrd3_0 {
+ status = "okay";
+};
+
+&d0_usbdrd_dwc3_0 {
+ status = "okay";
+ dr_mode = "host";
+ maximum-speed = "super-speed";
+};
+
+&d0_usbdrd3_1 {
+ status = "okay";
+};
+
+&d0_usbdrd_dwc3_1 {
+ status = "okay";
+ dr_mode = "host";
+ maximum-speed = "super-speed";
+};
+
+&d0_dmac0 {
+ status = "okay";
+};
+
+&d0_aon_dmac {
+ status = "okay";
+};
+
+&d0_uart0 {
+ /* debug */
+ status = "okay";
+};
+
+&d0_uart1 {
+ status = "okay";
+};
+
+&d0_uart2 {
+ status = "okay";
+};
+
+&d0_uart3 {
+ status = "okay";
+};
+
+&d0_uart4 {
+ status = "okay";
+};
+
+&ssi0 {
+ status = "okay";
+};
+
+&ssi1 {
+ status = "okay";
+};
+
+&bootspi {
+ /* spi flash */
+ status = "okay";
+ num-cs = <1>;
+ cs-gpios = <&portd 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&portd 4 GPIO_ACTIVE_LOW>;
+ spi-flash@0 {
+ compatible = "winbond,w25q128jw",
+ "jedec,spi-nor";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <4800000>;
+ rx-sample-delay-ns = <10>;
+ };
+};
+
+&d0_mbox0 {
+ status = "okay";
+};
+
+&d0_mbox1 {
+ status = "okay";
+};
+
+&d0_mbox2 {
+ status = "okay";
+};
+
+&d0_mbox3 {
+ status = "okay";
+};
+
+&d0_mbox4 {
+ status = "okay";
+};
+
+&d0_mbox5 {
+ status = "okay";
+};
+
+&d0_mbox6 {
+ status = "okay";
+};
+
+&d0_mbox7 {
+ status = "okay";
+};
+
+&fan_control {
+ status = "okay";
+ eswin,pwm_inverted;
+};
+
+&d0_i2c0 {
+ status = "okay";
+};
+
+&d0_i2c1 {
+ status = "okay";
+};
+
+&d0_i2c2 {
+ status = "okay";
+};
+
+&d0_i2c3 {
+ status = "okay";
+};
+
+&d0_i2c4 {
+ status = "okay";
+};
+
+&d0_i2c5 {
+ status = "okay";
+};
+
+&d0_i2c6 {
+ status = "okay";
+};
+
+&d0_i2c7 {
+ status = "okay";
+};
+
+&d0_i2c8 {
+ status = "okay";
+};
+
+&d0_i2c9 {
+ status = "okay";
+};
+
+&d0_aon_i2c0 {
+ status = "okay";
+};
+
+&d0_aon_i2c1 {
+ status = "okay";
+};
+
+&pwm0 {
+ /* fan */
+ status = "okay";
+};
+
+&pvt0 {
+ status = "okay";
+};
+
+&pvt1 {
+ status = "okay";
+};
+
+&wdt0 {
+ status = "disabled";
+};
+
+&wdt1 {
+ status = "disabled";
+};
+
+&wdt2 {
+ status = "disabled";
+};
+
+&wdt3 {
+ status = "disabled";
+};
+
+&die0_rtc {
+ status = "okay";
+};
+
+&timer0 {
+ status = "okay";
+};
+
+&timer1 {
+ status = "okay";
+};
+
+&timer2 {
+ status = "okay";
+};
+
+&timer3 {
+ status = "okay";
+};
+
+&pinctrl {
+ status = "okay";
+};
+
+/*
+ GPIO USED ON SOM:
+ gpio18 : HOST WAKE WLAN(O), active low
+ gpio19 : HOST WAKE BT(O), active low
+ gpio20 : WLAN WAKE HOST(I), active low
+ gpio21 : BT WAKE HOST(I), active low
+ gpio106 : gphy0 resern(O), active low
+ gpio111 : gphy1 resern(O), active low
+
+*/
+
+&gpio0 {
+ status = "okay";
+};
+&dev_llc_d0{
+ /* apply_npu_1G_freq; */
+ npu-supply=<&npu_vcc1>;
+ status = "okay";
+};
+
+&d0_clock {
+ status = "okay";
+ cpu-voltage-gpios = <&portc 30 GPIO_ACTIVE_HIGH>;
+};
+
+&cpu_opp_table {
+ opp-1500000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1500M>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-1600000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1600M>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-1700000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1700M>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1800M>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <70000>;
+ };
+};
diff --git a/arch/riscv/boot/dts/eswin/eic7700-z530.dts b/arch/riscv/boot/dts/eswin/eic7700-z530.dts
new file mode 100644
index 000000000000..d9dc8a8afd6a
--- /dev/null
+++ b/arch/riscv/boot/dts/eswin/eic7700-z530.dts
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for Eswin EIC7700 SoC.
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "eic7700-som260-a1.dtsi"
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "ESWIN EIC7700 Z530";
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ ap_backup {
+ label = "ap-backup";
+ linux,code = <KEY_OK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio26_default>;
+ gpios = <&porta 26 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&d0_gmac0 {
+ dly-param-1000m = <0x23232323 0xa0209023 0x20202020>;
+ dly-param-100m = <0x50505050 0x803f8050 0x3f3f3f3f>;
+ dly-param-10m = <0 0 0>;
+};
+
+&d0_gmac1 {
+ dly-param-1000m = <0x00000000 0xe002e000 0x04040404>;
+ dly-param-100m = <0x48484848 0x80588048 0x58585858>;
+ dly-param-10m = <0 0 0>;
+};
+
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio10_default>;
+ pci-prsnt = <&porta 10 GPIO_ACTIVE_LOW>;
+};
+
+&sdio0 {
+ /* sd card */
+ delay_code = <0x3b>;
+ drive-impedance-ohm = <33>;
+ enable-cmd-pullup;
+ enable-data-pullup;
+ no-sdio;
+ no-mmc;
+};
+
+&sdio1 {
+ /* wifi module */
+ delay_code = <0x32>;
+ drive-impedance-ohm = <33>;
+ enable-cmd-pullup;
+ enable-data-pullup;
+ keep-power-in-suspend;
+ non-removable;
+ no-sd;
+ no-mmc;
+ aw3155:wifi_aw3155@0 {
+ compatible = "aml_w1_sdio";
+ reg = <0x0>;
+ interrupt-parent = <&porta>;
+ interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&pinctrl_gpio15_default>;
+ pinctrl-1 = <&pinctrl_gpio79_default>;
+ irq-gpios = <&porta 15 GPIO_ACTIVE_HIGH>;
+ rst-gpios = <&portc 15 GPIO_ACTIVE_HIGH>;
+
+ };
+};
+
+&ssi0 {
+ /* lora */
+};
+
+&ssi1 {
+ /* unused */
+ status = "disabled";
+};
+
+&dsi_panel {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio7_default &pinctrl_gpio92_default>;
+ backlight0-gpios = <&porta 7 GPIO_ACTIVE_HIGH>;
+ rst-gpios = <&portc 28 GPIO_ACTIVE_HIGH>;
+};
+
+&d0_graphcard1 {
+ status = "okay";
+ label = "Analog Audio-0";
+ dais = <&d0_i2s1_port>;
+};
+
+&d0_graphcard2 {
+ status = "disabled";
+};
+
+&d0_i2s1 {
+ status = "okay";
+ d0_i2s1_port: port {
+ d0_i2s1_endpoint: endpoint {
+ remote-endpoint = <&d0_codec0_endpoint>;
+ dai-format = "i2s";
+ };
+ };
+};
+
+&d0_i2s2 {
+ status = "disabled";
+};
+
+&d0_i2c0 {
+ /* codec es8388 */
+ d0_es8388_0: es8388-0@10 {
+ compatible = "eswin,es8388";
+ reg = <0x10>;
+ #sound-dai-cells = <0>;
+ eswin-plat = <3>;
+ port {
+ d0_codec0_endpoint: endpoint {
+ system-clock-frequency = <12288000>;
+ remote-endpoint = <&d0_i2s1_endpoint>;
+ };
+ };
+ };
+};
+
+&d0_i2c1 {
+ /* rtc rs4c411 & mipi dsi */
+
+};
+
+&d0_i2c2 {
+ /* touch screen*/
+ gt911:touchscreen@14 {
+ compatible = "goodix,gt911";
+ reg = <0x14>;
+ interrupt-parent = <&porta>;
+ interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio0_default &pinctrl_gpio92_default>;
+ irq-gpios = <&porta 0 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&portc 28 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&d0_aon_i2c0 {
+ /* rk628f x2 */
+
+};
+
+/* GPIO Function Description
+ gpio0 : touch int(I)
+ gpio5 : 5g wake on host(I)
+ gpio6 : 5g disable2(O)
+ gpio7 : mipi dsi ctrl(O)
+ gpio8 : 5g disable1(O)
+ gpio9 : rk628 plugin detect(I)
+ gpio10 : pcie prsnt(I)
+ gpio12 : bt wake host(I)
+ gpio15 : wlan wake host(I)
+ gpio26 : ap backup(I)
+ gpio39 : lora busy(I)
+ gpio41 : host wake bt(I)
+ gpio70 : rk628 int(I)
+ gpio71 : rk628 reset(O)
+ gpio73 : rk628 power enable(O)
+ gpio74 : 5g pwren(O)
+ gpio76 : eth rset(O)
+ gpio77 : lora nreset(O)
+ gpio79 : m2 power on(O)
+ gpio80 : lora ctrl2(O)
+ gpio81 : lora ctrl1(O)
+ gpio92 : touch rstn(O)
+ gpio93 : 5g reset(O)
+*/
\ No newline at end of file
diff --git a/arch/riscv/boot/dts/eswin/eic7702-evb-a1-d0.dts b/arch/riscv/boot/dts/eswin/eic7702-evb-a1-d0.dts
index 1bacf33dd7c0..cbfeadae5c8e 100644
--- a/arch/riscv/boot/dts/eswin/eic7702-evb-a1-d0.dts
+++ b/arch/riscv/boot/dts/eswin/eic7702-evb-a1-d0.dts
@@ -228,6 +228,7 @@ &pcie {
&d0_npu{
status = "okay";
+ npu-supply=<&npu_vcc1>;
};
&d0_dsp_subsys {
@@ -428,7 +429,9 @@ &d0_gmac0 {
rst-gpios = <&porta 15 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x290 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
-
+ dly-param-1000m = <0x23232323 0x800c8023 0x0c0c0c0c>;
+ dly-param-100m = <0x50505050 0x803f8050 0x3f3f3f3f>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
@@ -438,7 +441,9 @@ &d0_gmac1 {
rst-gpios = <&porta 14 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x294 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
-
+ dly-param-1000m = <0x25252525 0x80268025 0x26262626>;
+ dly-param-100m = <0x48484848 0x80588048 0x58585858>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
@@ -624,7 +629,6 @@ npu_vcc1:npu_svcc{
regulator-min-microamp=<20000000>;
regulator-max-microamp=<40000000>;
regulator-ov-protection-microvolt=<1100000>;
- regulator-always-on;
};
};
};
diff --git a/arch/riscv/boot/dts/eswin/eic7702-evb-a1-d1.dts b/arch/riscv/boot/dts/eswin/eic7702-evb-a1-d1.dts
index 4154b2da9d22..0b2d07df055c 100644
--- a/arch/riscv/boot/dts/eswin/eic7702-evb-a1-d1.dts
+++ b/arch/riscv/boot/dts/eswin/eic7702-evb-a1-d1.dts
@@ -240,6 +240,7 @@ &pcie {
&d0_npu{
status = "okay";
+ npu-supply=<&npu_vcc1>;
};
&d0_dsp_subsys {
@@ -442,7 +443,9 @@ &d0_gmac0 {
rst-gpios = <&porta 13 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x290 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
-
+ dly-param-1000m = <0x23232323 0x800c8023 0x0c0c0c0c>;
+ dly-param-100m = <0x50505050 0x803f8050 0x3f3f3f3f>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
@@ -452,7 +455,9 @@ &d0_gmac1 {
rst-gpios = <&porta 14 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x294 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
-
+ dly-param-1000m = <0x25252525 0x80268025 0x26262626>;
+ dly-param-100m = <0x48484848 0x80588048 0x58585858>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
@@ -638,7 +643,6 @@ npu_vcc1:npu_svcc{
regulator-min-microamp=<20000000>;
regulator-max-microamp=<40000000>;
regulator-ov-protection-microvolt=<1100000>;
- regulator-always-on;
};
};
};
diff --git a/arch/riscv/boot/dts/eswin/eic7702-evb-a1-interleave.dts b/arch/riscv/boot/dts/eswin/eic7702-evb-a1-interleave.dts
new file mode 100644
index 000000000000..8e38dc5e7f59
--- /dev/null
+++ b/arch/riscv/boot/dts/eswin/eic7702-evb-a1-interleave.dts
@@ -0,0 +1,1560 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for Eswin EIC7700 SoC.
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+
+#define RTCCLK_FREQ 1000000
+#define LSPCLK_FREQ 200000000
+
+/* If wanna enable ECC capability of DDR, should reserve highest zone of 1/8 all space for it */
+#define CMA_SIZE 0x20000000
+
+#include "eswin-win2030-die0-soc.dtsi"
+#include "eswin-win2030-die1-soc.dtsi"
+
+#include "eic7x-die0-pinctrl.dtsi"
+#include "eic7x-die1-pinctrl.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/* Clock frequency (in Hz) of the PCB crystal for rtcclk */
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "ESWIN EIC7700";
+ compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000",
+ "sifive,fu740", "eswin,eic7700";
+
+ aliases {
+ serial0 = &d0_uart0;
+ ethernet0 = &d0_gmac0;
+ ethernet1 = &d0_gmac1;
+ ethernet2 = &d1_gmac0;
+ ethernet3 = &d1_gmac1;
+ rtc0 = &die0_rtc;
+ rtc1 = &d1_rtc;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ cpus {
+ timebase-frequency = <RTCCLK_FREQ>;
+ };
+
+ memory@59000000 {
+ device_type = "memory";
+ reg = <0x0 0x59000000 0x0 0x400000>;
+ numa-node-id = <0>;
+ };
+
+ memory@79000000 {
+ device_type = "memory";
+ reg = <0x0 0x79000000 0x0 0x400000>;
+ numa-node-id = <1>;
+ };
+
+ memory@4000000000 {
+ device_type = "memory";
+ reg = <0x40 0x00000000 0x0 0x80000000>;
+ numa-node-id = <0>;
+ };
+ memory@4100000000 {
+ device_type = "memory";
+ reg = <0x41 0x00000000 0x1 0xe0000000>;
+ numa-node-id = <0>;
+ };
+ memory@42e0000000 {
+ device_type = "memory";
+ reg = <0x42 0xe0000000 0x1 0xe0000000>;
+ numa-node-id = <1>;
+ };
+ memory@c0000000 {
+ device_type = "memory";
+ reg = <0x00 0xc0000000 0x0 0x40000000>;
+ numa-node-id = <0>;
+ };
+ memory@2040000000 {
+ device_type = "memory";
+ reg = <0x20 0x40000000 0x0 0x40000000>;
+ numa-node-id = <1>;
+ };
+ memory@300000000 {
+ device_type = "memory";
+ reg = <0x3 0x0 0x1 0x80000000>;
+ numa-node-id = <0>;
+ };
+ memory@2280000000 {
+ device_type = "memory";
+ reg = <0x22 0x80000000 0x1 0x80000000>;
+ numa-node-id = <1>;
+ };
+ memory@2e00000000 {
+ device_type = "memory";
+ reg = <0x2 0xe0000000 0x0 0x20000000>;
+ numa-node-id = <0>;
+ };
+ memory@2260000000 {
+ device_type = "memory";
+ reg = <0x22 0x60000000 0x0 0x20000000>;
+ numa-node-id = <1>;
+ };
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ linux,cma {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0x0 CMA_SIZE>;
+ alignment = <0x0 0x1000>;
+ alloc-ranges = <0x41 0x00000000 0x1 0x0>,<0x43 0x00000000 0x1 0x0>;
+ linux,cma-default;
+ };
+ mmz_nid_0_part_0 {
+ compatible = "eswin-reserve-memory";
+ reg = <0x3 0x0 0x1 0x80000000>;
+ no-map;
+ };
+ mmz_nid_1_part_0 {
+ compatible = "eswin-reserve-memory";
+ reg = <0x22 0x80000000 0x1 0x80000000>;
+ no-map;
+ };
+ npu0_reserved: sprammemory@59000000 {
+ no-map;
+ reg = <0x0 0x59000000 0x0 0x400000>;
+ };
+
+ npu1_reserved: sprammemory@79000000 {
+ no-map;
+ reg = <0x0 0x79000000 0x0 0x400000>;
+ };
+
+ d0_dc_reserved: d0_dc_reserved@2e00000000 {
+ compatible = "shared-dma-pool";
+ reusable;
+ reg = <0x2 0xe0000000 0x0 0x20000000>;
+ };
+
+ d1_dc_reserved: d1_dc_reserved@2260000000 {
+ compatible = "shared-dma-pool";
+ reusable;
+ reg = <0x22 0x60000000 0x0 0x20000000>;
+ };
+
+ // g2d_4GB_boundary_reserved_4k {
+ // no-map;
+ // reg = <0x0 0xfffff000 0x0 0x1000>;
+ // };
+
+ // g2d_8GB_boundary_reserved_4k {
+ // no-map;
+ // reg = <0x1 0xfffff000 0x0 0x1000>;
+ // };
+
+ // g2d_12GB_boundary_reserved_4k {
+ // no-map;
+ // reg = <0x2 0xfffff000 0x0 0x1000>;
+ // };
+
+
+ // d1_g2d_4GB_boundary_reserved_4k {
+ // no-map;
+ // reg = <0x20 0xfffff000 0x0 0x1000>;
+ // };
+
+ // d1_g2d_8GB_boundary_reserved_4k {
+ // no-map;
+ // reg = <0x21 0xfffff000 0x0 0x1000>;
+ // };
+
+
+ };
+
+ distance-map {
+ compatible = "numa-distance-map-v1";
+ distance-matrix = <0 0 10>,
+ <0 1 100>,
+ <1 0 100>,
+ <1 1 10>;
+ };
+
+ /* die1 gpio68 system led */
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_die1_gpio68_default>;
+
+ gpio-68 {
+ gpios = <&d1_portc 4 GPIO_ACTIVE_LOW>;
+ label = "heartbeat";
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+};
+
+&d0_clock {
+ status = "okay";
+};
+&d1_clock {
+ status = "okay";
+};
+
+&d0_reset {
+ status = "okay";
+};
+&d1_reset {
+ status = "okay";
+};
+
+&d0_pmu {
+ status = "okay";
+};
+&d1_pmu {
+ status = "disabled";
+};
+
+&ddr0 {
+ status = "okay";
+};
+
+&ddr1 {
+ status = "okay";
+};
+
+&d1_ddr0 {
+ status = "okay";
+};
+
+&d1_ddr1 {
+ status = "okay";
+};
+
+&smmu0 {
+ status = "okay";
+};
+&smmu1 {
+ status = "okay";
+};
+
+&smmu_pmu0 {
+ status = "disabled";
+};
+&smmu_pmu1 {
+ status = "disabled";
+};
+
+
+&dev_foo_a {
+ status = "okay";
+};
+
+&d0_cfg_noc {
+ status = "okay";
+};
+
+&d0_llc_noc {
+ status = "okay";
+ stat,0 = "TracePort:ddr0_p0_req";
+ stat,1 = "TracePort:ddr1_p0_req";
+ //latency,0 = "TracePort:llcnoc_trans_probe";
+ //pending,0 = "TracePort:llcnoc_trans_probe";
+};
+
+&d0_sys_noc {
+ status = "okay";
+
+ //eswin,DSPT-qos-owner;
+ //eswin,NPU-qos-owner;
+ //eswin,SPISLV_TBU3-qos-owner;
+
+ stat,0 = "TracePort:ddr0_p1_req",
+ "InitFlow:mcput_snoc_mp/I/0";
+
+ stat,1 = "TracePort:ddr0_p2_req",
+ "InitFlow:dspt_snoc/I/0",
+ "AddrBase:0x81000000", "AddrSize:0x30",
+ "Opcode:RdWrLockUrg", "Status:ReqRsp", "Length:0x8000", "Urgency:0x0";
+
+ stat,2 = "TracePort:ddr1_p1_req",
+ "Status:Req", "AddrSize:0x28";
+
+ stat,3 = "TracePort:ddr1_p2_req";
+
+ latency,0 = "TracePort:sysnoc_trans_probe_0", "AddrSize:0x0";
+ latency,1 = "TracePort:sysnoc_trans_probe_1","Mode:latency","AddrBase:0x82000000","AddrSize:0x28","Opcode:RdWr";
+ //latency,2 = "TracePort:sysnoc_trans_probe_2";
+
+ //pending,0 = "TracePort:sysnoc_trans_probe_0";
+ //pending,1 = "TracePort:sysnoc_trans_probe_1","Mode:latency","AddrBase:0x82000000","AddrSize:0x0","Opcode:RdWr";
+ pending,0 = "TracePort:sysnoc_trans_probe_2", "AddrSize:0x3";
+};
+
+&d0_media_noc {
+ status = "okay";
+
+ //eswin,GPU-qos-owner;
+ //eswin,TBU2-qos-owner;
+ //eswin,VC-qos-owner;
+
+ stat,0 = "TracePort:ddr0_p3_req";
+ stat,1 = "TracePort:ddr1_p3_req";
+ //latency,0 = "TracePort:mnoc_trans_probe";
+ //pending,0 = "TracePort:mnoc_trans_probe";
+};
+
+&d0_realtime_noc {
+ status = "okay";
+
+ //eswin,TBU0-qos-owner;
+ //eswin,VO-qos-owner;
+
+ stat,0 = "TracePort:ddr0_p4_req";
+ stat,1 = "TracePort:ddr1_p4_req";
+ //latency,0 = "TracePort:rnoc_trans_probe";
+ //pending,0 = "TracePort:rnoc_trans_probe";
+};
+
+&d0_noc_wdt {
+ status = "okay";
+};
+
+&d1_cfg_noc {
+ status = "okay";
+};
+
+&d1_llc_noc {
+ status = "okay";
+ stat,0 = "TracePort:ddr0_p0_req";
+ stat,1 = "TracePort:ddr1_p0_req";
+ //latency,0 = "TracePort:llcnoc_trans_probe";
+ //pending,0 = "TracePort:llcnoc_trans_probe";
+};
+
+&d1_sys_noc {
+ status = "okay";
+
+ //eswin,DSPT-qos-owner;
+ //eswin,NPU-qos-owner;
+ //eswin,SPISLV_TBU3-qos-owner;
+
+ stat,0 = "TracePort:ddr0_p1_req",
+ "InitFlow:mcput_snoc_mp/I/0";
+
+ stat,1 = "TracePort:ddr0_p2_req",
+ "InitFlow:dspt_snoc/I/0",
+ "AddrBase:0x81000000", "AddrSize:0x30",
+ "Opcode:RdWrLockUrg", "Status:ReqRsp", "Length:0x8000", "Urgency:0x0";
+
+ stat,2 = "TracePort:ddr1_p1_req",
+ "Status:Req", "AddrSize:0x28";
+
+ stat,3 = "TracePort:ddr1_p2_req";
+
+ latency,0 = "TracePort:sysnoc_trans_probe_0", "AddrSize:0x0";
+ latency,1 = "TracePort:sysnoc_trans_probe_1","Mode:latency","AddrBase:0x82000000","AddrSize:0x28","Opcode:RdWr";
+ //latency,2 = "TracePort:sysnoc_trans_probe_2";
+
+ //pending,0 = "TracePort:sysnoc_trans_probe_0";
+ //pending,1 = "TracePort:sysnoc_trans_probe_1","Mode:latency","AddrBase:0x82000000","AddrSize:0x0","Opcode:RdWr";
+ pending,0 = "TracePort:sysnoc_trans_probe_2", "AddrSize:0x3";
+};
+
+&d1_media_noc {
+ status = "okay";
+
+ //eswin,GPU-qos-owner;
+ //eswin,TBU2-qos-owner;
+ //eswin,VC-qos-owner;
+
+ stat,0 = "TracePort:ddr0_p3_req";
+ stat,1 = "TracePort:ddr1_p3_req";
+ //latency,0 = "TracePort:mnoc_trans_probe";
+ //pending,0 = "TracePort:mnoc_trans_probe";
+};
+
+&d1_realtime_noc {
+ status = "okay";
+
+ //eswin,TBU0-qos-owner;
+ //eswin,VO-qos-owner;
+
+ stat,0 = "TracePort:ddr0_p4_req";
+ stat,1 = "TracePort:ddr1_p4_req";
+ //latency,0 = "TracePort:rnoc_trans_probe";
+ //pending,0 = "TracePort:rnoc_trans_probe";
+};
+
+&d1_noc_wdt {
+ status = "okay";
+};
+
+&d0_ipc_scpu {
+ status = "okay";
+};
+&d1_ipc_scpu {
+ status = "okay";
+};
+
+&d0_lpcpu {
+ status = "okay";
+};
+&d1_lpcpu {
+ status = "disabled";
+};
+
+&pcie {
+ status = "okay";
+};
+&d1_pcie {
+ status = "okay";
+};
+
+&d0_npu{
+ status = "okay";
+};
+&d1_npu {
+ status = "okay";
+};
+
+&d0_dsp_subsys {
+ status = "okay";
+};
+&d1_dsp_subsys {
+ status = "okay";
+};
+
+&d0_dsp0 {
+ status = "okay";
+};
+&d1_dsp0 {
+ status = "okay";
+};
+
+&d0_dsp1 {
+ status = "okay";
+};
+&d1_dsp1 {
+ status = "okay";
+};
+
+&d0_dsp2 {
+ status = "okay";
+};
+&d1_dsp2 {
+ status = "okay";
+};
+
+&d0_dsp3 {
+ status = "okay";
+};
+&d1_dsp3 {
+ status = "okay";
+};
+
+&gpu0 {
+ status = "okay";
+};
+&d1_gpu {
+ status = "disabled";
+};
+
+&gc820 {
+ status = "okay";
+};
+&d1_gc820 {
+ status = "okay";
+};
+
+&vdec0 {
+ status = "okay";
+};
+&vdec1 {
+ status = "okay";
+};
+
+&venc0 {
+ status = "okay";
+};
+&venc1 {
+ status = "okay";
+};
+
+&video_output {
+ status = "okay";
+ memory-region = <&d0_dc_reserved>;
+};
+
+&d1_video_output {
+ status = "okay";
+ memory-region = <&d1_dc_reserved>;
+};
+
+&dc {
+ status = "okay";
+};
+
+&d1_dc {
+ status = "okay";
+};
+
+&dc_test {
+ status = "disabled";
+};
+&d1_dc_test {
+ status = "disabled";
+};
+
+&virtual_display {
+ status = "okay";
+};
+
+&d1_virtual_display {
+ status = "okay";
+};
+
+&dsi_controller {
+ status = "okay";
+};
+&d1_dsi_controller {
+ status = "okay";
+};
+
+&dsi_panel {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_die0_gpio27_default &pinctrl_die0_gpio106_default>;
+ backlight0-gpios = <&porta 27 GPIO_ACTIVE_HIGH>;
+ rst-gpios = <&portd 10 GPIO_ACTIVE_HIGH>;
+};
+&d1_dsi_panel {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_die1_gpio69_default &pinctrl_die1_gpio21_default>;
+ backlight0-gpios = <&d1_portc 5 GPIO_ACTIVE_HIGH>;
+ rst-gpios = <&d1_porta 21 GPIO_ACTIVE_HIGH>;
+};
+
+&dw_hdmi {
+ status = "okay";
+ ports {
+ port@2 {
+ reg = <2>;
+ hdmi_in_i2s: endpoint@1 {
+ system-clock-frequency = <12288000>;
+ remote-endpoint = <&d0_i2s0_endpoint>;
+ };
+ };
+ };
+};
+&d1_dw_hdmi {
+ status = "okay";
+ ports {
+ port@2 {
+ reg = <2>;
+ d1_hdmi_in_i2s: endpoint@1 {
+ system-clock-frequency = <12288000>;
+ remote-endpoint = <&d1_i2s0_endpoint>;
+ };
+ };
+ };
+};
+
+&dw_hdmi_hdcp2 {
+ status = "okay";
+};
+&d1_dw_hdmi_hdcp2 {
+ status = "disabled";
+};
+
+
+&d0_i2s0 {
+ status = "okay";
+ numa-node-id = <0>;
+ d0_i2s0_port: port {
+ d0_i2s0_endpoint: endpoint {
+ remote-endpoint = <&hdmi_in_i2s>;
+ dai-format = "i2s";
+ };
+ };
+};
+
+&d1_i2s0 {
+ status = "okay";
+ numa-node-id = <1>;
+ d1_i2s0_port: port {
+ d1_i2s0_endpoint: endpoint {
+ remote-endpoint = <&d1_hdmi_in_i2s>;
+ dai-format = "i2s";
+ };
+ };
+};
+
+&d0_i2s1 {
+ status = "okay";
+ numa-node-id = <0>;
+ d0_i2s1_port: port {
+ d0_i2s1_endpoint: endpoint {
+ remote-endpoint = <&d0_codec0_endpoint>;
+ dai-format = "i2s";
+ };
+ };
+};
+
+&d1_i2s1 {
+ status = "okay";
+ numa-node-id = <1>;
+ d1_i2s1_port: port {
+ d1_i2s1_endpoint: endpoint {
+ remote-endpoint = <&d1_codec0_endpoint>;
+ dai-format = "i2s";
+ };
+ };
+};
+
+&d0_i2s2 {
+ status = "okay";
+ numa-node-id = <0>;
+ d0_i2s2_port: port {
+ d0_i2s2_endpoint: endpoint {
+ remote-endpoint = <&d0_codec1_endpoint>;
+ dai-format = "i2s";
+ };
+ };
+};
+
+&d1_i2s2 {
+ status = "okay";
+ numa-node-id = <1>;
+ d1_i2s2_port: port {
+ d1_i2s2_endpoint: endpoint {
+ remote-endpoint = <&d1_codec1_endpoint>;
+ dai-format = "i2s";
+ };
+ };
+};
+
+&d0_graphcard0 {
+ status = "okay";
+ label = "Analog Audio-0";
+ dais = <&d0_i2s1_port>;
+};
+
+&d0_graphcard1 {
+ status = "okay";
+ label = "Analog Audio-1";
+ dais = <&d0_i2s2_port>;
+};
+
+&d0_graphcard2 {
+ status = "okay";
+ label = "HDMI Audio-0";
+ dais = <&d0_i2s0_port>;
+};
+
+&d1_graphcard0 {
+ status = "okay";
+ label = "Analog Audio-2";
+ dais = <&d1_i2s1_port>;
+};
+
+&d1_graphcard1 {
+ status = "okay";
+ label = "Analog Audio-3";
+ dais = <&d1_i2s2_port>;
+};
+
+&d1_graphcard2 {
+ status = "okay";
+ label = "HDMI Audio-1";
+ dais = <&d1_i2s0_port>;
+};
+
+&isp_0 {
+ status = "okay";
+};
+&d1_isp_0 {
+ status = "disabled";
+};
+
+&isp_1 {
+ status = "okay";
+};
+&d1_isp_1 {
+ status = "disabled";
+};
+
+&dewarp {
+ status = "okay";
+};
+&d1_dewarp {
+ status = "okay";
+};
+
+&mipi_dphy_rx {
+ status = "okay";
+};
+&d1_mipi_dphy_rx {
+ status = "disabled";
+};
+
+&csi_dma0 {
+ status = "okay";
+};
+&d1_csi_dma0 {
+ status = "disabled";
+};
+
+&csi_dma1 {
+ status = "disabled";
+};
+&d1_csi_dma1 {
+ status = "disabled";
+};
+
+&csi2_0 {
+ status = "okay";
+};
+&d1_csi2_0 {
+ status = "disabled";
+};
+
+&csi2_1 {
+ status = "disabled";
+};
+&d1_csi2_1 {
+ status = "disabled";
+};
+
+&sdhci_emmc {
+ /* emmc */
+ status = "okay";
+ delay_code = <0x17>;
+ drive-impedance-ohm = <50>;
+ enable-cmd-pullup;
+ enable-data-pullup;
+ no-sdio;
+ no-sd;
+};
+
+&d1_sdhci_emmc {
+ /* emmc */
+ status = "okay";
+ delay_code = <0x17>;
+ drive-impedance-ohm = <50>;
+ enable-cmd-pullup;
+ enable-data-pullup;
+ no-sdio;
+ no-sd;
+};
+
+&sdio0 {
+ /* sd card */
+ status = "okay";
+ delay_code = <0x55>;
+ drive-impedance-ohm = <33>;
+ enable-cmd-pullup;
+ enable-data-pullup;
+ no-sdio;
+ no-mmc;
+};
+
+&d1_sdio0 {
+ /* wifi module */
+ status = "okay";
+ delay_code = <0x29>;
+ drive-impedance-ohm = <33>;
+ enable-cmd-pullup;
+ enable-data-pullup;
+ keep-power-in-suspend;
+ non-removable;
+ no-sd;
+ no-mmc;
+ aw315:wifi_aw3155@0 {
+ compatible = "aml_w1_sdio";
+ reg = <0x0>;
+ interrupt-parent = <&d1_porta>;
+ interrupts = <18 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default", "default";
+ pinctrl-0 = <&pinctrl_die1_gpio18_default>;
+ pinctrl-1 = <&pinctrl_die1_gpio16_default>;
+ irq-gpios = <&d1_porta 18 GPIO_ACTIVE_HIGH>;
+ rst-gpios = <&d1_porta 16 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&sdio1 {
+ status = "disabled";
+};
+
+&d1_sdio1 {
+ status = "disabled";
+};
+
+&d0_gmac0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_die0_gpio15_default>;
+ rst-gpios = <&porta 15 GPIO_ACTIVE_LOW>;
+ eswin,rgmiisel = <&pinctrl 0x290 0x3>;
+ eswin,led-cfgs = <0x6100 0xa40 0x420>;
+ dly-param-1000m = <0x23232323 0x800c8023 0x0c0c0c0c>;
+ dly-param-100m = <0x50505050 0x803f8050 0x3f3f3f3f>;
+ dly-param-10m = <0 0 0>;
+ status = "okay";
+};
+
+&d1_gmac0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_die1_gpio13_default>;
+ rst-gpios = <&d1_porta 13 GPIO_ACTIVE_LOW>;
+ eswin,rgmiisel = <&d1_pinctrl 0x290 0x3>;
+ eswin,led-cfgs = <0x6100 0xa40 0x420>;
+ dly-param-1000m = <0x23232323 0x800c8023 0x0c0c0c0c>;
+ dly-param-100m = <0x50505050 0x803f8050 0x3f3f3f3f>;
+ dly-param-10m = <0 0 0>;
+ status = "okay";
+};
+
+&d0_gmac1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_die0_gpio14_default>;
+ rst-gpios = <&porta 14 GPIO_ACTIVE_LOW>;
+ eswin,rgmiisel = <&pinctrl 0x294 0x3>;
+ eswin,led-cfgs = <0x6100 0xa40 0x420>;
+ dly-param-1000m = <0x25252525 0x80268025 0x26262626>;
+ dly-param-100m = <0x48484848 0x80588048 0x58585858>;
+ dly-param-10m = <0 0 0>;
+ status = "okay";
+};
+
+&d1_gmac1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_die1_gpio14_default>;
+ rst-gpios = <&d1_porta 14 GPIO_ACTIVE_LOW>;
+ eswin,rgmiisel = <&d1_pinctrl 0x294 0x3>;
+ eswin,led-cfgs = <0x6100 0xa40 0x420>;
+ dly-param-1000m = <0x25252525 0x80268025 0x26262626>;
+ dly-param-100m = <0x48484848 0x80588048 0x58585858>;
+ dly-param-10m = <0 0 0>;
+ status = "okay";
+};
+
+&d0_sata {
+ status = "okay";
+};
+
+&d1_sata {
+ status = "okay";
+};
+
+&d0_usbdrd3_0 {
+ status = "okay";
+};
+&d1_usbdrd3_0 {
+ status = "okay";
+};
+
+&d0_usbdrd_dwc3_0 {
+ status = "okay";
+ dr_mode = "host";
+ maximum-speed = "super-speed";
+};
+
+&d1_usbdrd_dwc3_0 {
+ status = "okay";
+ dr_mode = "host";
+ maximum-speed = "super-speed";
+};
+
+&d0_usbdrd3_1 {
+ status = "okay";
+};
+
+&d1_usbdrd3_1 {
+ status = "okay";
+};
+
+&d0_usbdrd_dwc3_1 {
+ status = "okay";
+ dr_mode = "host";
+ maximum-speed = "super-speed";
+};
+
+&d1_usbdrd_dwc3_1 {
+ status = "okay";
+ dr_mode = "host";
+ maximum-speed = "super-speed";
+};
+
+&d0_dmac0 {
+ status = "okay";
+};
+
+&d1_dmac0 {
+ status = "disabled";
+};
+
+&d0_aon_dmac {
+ status = "okay";
+};
+
+&d1_aon_dmac {
+ status = "okay";
+};
+
+&d0_uart0 {
+ /* debug */
+ status = "okay";
+};
+
+&d1_uart0 {
+ status = "okay";
+};
+
+&d0_uart1 {
+ /* RS232 DB9 */
+ status = "okay";
+};
+
+&d1_uart1 {
+ /* BT M.2 KEY-E */
+ status = "okay";
+};
+
+&d0_uart2 {
+ /* pin header */
+ status = "okay";
+};
+
+&d1_uart2 {
+ /* pin header */
+ status = "okay";
+};
+
+&d0_uart3 {
+ /* unused */
+ status = "disabled";
+};
+
+&d1_uart3 {
+ /* unused */
+ status = "disabled";
+};
+
+&d0_uart4 {
+ /* unused */
+ status = "disabled";
+};
+
+&d1_uart4 {
+ /* unused */
+ status = "disabled";
+};
+
+&ssi0 {
+ /* spi flash */
+ status = "okay";
+ num-cs = <2>;
+ spi-flash@0 {
+ compatible = "winbond,w25q128fw",
+ "jedec,spi-nor";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <4800000>;
+ rx-sample-delay-ns = <10>;
+ };
+ spi-flash@1 {
+ compatible = "winbond,w25q128fw",
+ "jedec,spi-nor";
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <4800000>;
+ rx-sample-delay-ns = <10>;
+ };
+};
+&d1_ssi0 {
+ /* spi flash */
+ status = "okay";
+ num-cs = <2>;
+ spi-flash@0 {
+ compatible = "winbond,w25q128fw",
+ "jedec,spi-nor";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <4800000>;
+ rx-sample-delay-ns = <10>;
+ };
+ spi-flash@1 {
+ compatible = "winbond,w25q128fw",
+ "jedec,spi-nor";
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <4800000>;
+ rx-sample-delay-ns = <10>;
+ };
+};
+
+&ssi1 {
+ /* unused */
+ status = "disabled";
+};
+
+&d1_ssi1 {
+ /* unused */
+ status = "disabled";
+};
+
+&bootspi {
+ /* spi flash */
+ status = "disabled";
+ num-cs = <1>;
+ cs-gpios = <&portd 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&portd 4 GPIO_ACTIVE_LOW>;
+ spi-flash@0 {
+ compatible = "winbond,w25q128jw",
+ "jedec,spi-nor";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <4800000>;
+ rx-sample-delay-ns = <10>;
+ };
+};
+
+&d1_bootspi {
+ /* spi flash */
+ status = "disabled";
+ num-cs = <1>;
+ cs-gpios = <&d1_portd 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&d1_portd 4 GPIO_ACTIVE_LOW>;
+ spi-flash@0 {
+ compatible = "winbond,w25q128jw",
+ "jedec,spi-nor";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <4800000>;
+ rx-sample-delay-ns = <10>;
+ };
+};
+
+&d0_mbox0 {
+ status = "okay";
+};
+&d1_mbox0 {
+ status = "okay";
+};
+
+&d0_mbox1 {
+ status = "okay";
+};
+&d1_mbox1 {
+ status = "okay";
+};
+
+&d0_mbox2 {
+ status = "okay";
+};
+&d1_mbox2 {
+ status = "okay";
+};
+
+&d0_mbox3 {
+ status = "okay";
+};
+&d1_mbox3 {
+ status = "okay";
+};
+
+&d0_mbox4 {
+ status = "okay";
+};
+&d1_mbox4 {
+ status = "okay";
+};
+
+&d0_mbox5 {
+ status = "okay";
+};
+&d1_mbox5 {
+ status = "okay";
+};
+
+&d0_mbox6 {
+ status = "okay";
+};
+&d1_mbox6 {
+ status = "okay";
+};
+
+&d0_mbox7 {
+ status = "okay";
+};
+&d1_mbox7 {
+ status = "okay";
+};
+
+&fan_control {
+ status = "okay";
+};
+&d1_fan_control {
+ status = "disabled";
+};
+
+&d0_i2c0 {
+ /* codec es8388 */
+ status = "okay";
+ d0_es8388_0: es8388-0@10 {
+ compatible = "eswin,es8388";
+ reg = <0x10>;
+ #sound-dai-cells = <0>;
+ port {
+ d0_codec0_endpoint: endpoint {
+ system-clock-frequency = <12288000>;
+ remote-endpoint = <&d0_i2s1_endpoint>;
+ };
+ };
+ };
+ d0_es8388_1: es8388-1@11 {
+ compatible = "eswin,es8388";
+ reg = <0x11>;
+ #sound-dai-cells = <0>;
+ port {
+ d0_codec1_endpoint: endpoint {
+ system-clock-frequency = <12288000>;
+ remote-endpoint = <&d0_i2s2_endpoint>;
+ };
+ };
+ };
+};
+
+&d1_i2c0 {
+ /* codec es8388 */
+ status = "okay";
+ d1_es8388_0: es8388-0@10 {
+ compatible = "eswin,es8388";
+ reg = <0x10>;
+ #sound-dai-cells = <0>;
+ port {
+ d1_codec0_endpoint: endpoint {
+ system-clock-frequency = <12288000>;
+ remote-endpoint = <&d1_i2s1_endpoint>;
+ };
+ };
+ };
+ d1_es8388_1: es8388-1@11 {
+ compatible = "eswin,es8388";
+ reg = <0x11>;
+ #sound-dai-cells = <0>;
+ port {
+ d1_codec1_endpoint: endpoint {
+ system-clock-frequency = <12288000>;
+ remote-endpoint = <&d1_i2s2_endpoint>;
+ };
+ };
+ };
+};
+
+&d0_i2c1 {
+ status = "okay";
+ es5430@f {
+ compatible = "einno,es5340";
+ reg = <0xf>;
+ eswin,regulator_default-microvolt=<1000000>;
+ eswin,regulator_label = "supply vdd1", "npu vdd1", "npu current1", "npu temperature1";
+ label = "npu_vdd";
+ regulators{
+ d0_npu_vcc:npu_svcc{
+ regulator-name="NPU_SVCC";
+ regulator-min-microvolt=<700000>;
+ regulator-max-microvolt=<1100000>;
+ regulator-min-microamp=<20000000>;
+ regulator-max-microamp=<40000000>;
+ regulator-ov-protection-microvolt=<1100000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+&d1_i2c1 {
+ status = "okay";
+ es5430@f {
+ compatible = "einno,es5340";
+ reg = <0xf>;
+ eswin,regulator_default-microvolt=<1000000>;
+ eswin,regulator_label = "supply vdd1", "npu vdd1", "npu current1", "npu temperature1";
+ label = "d1_npu_vdd";
+ regulators{
+ d1_npu_vcc:npu_svcc{
+ regulator-name="NPU_SVCC2";
+ regulator-min-microvolt=<700000>;
+ regulator-max-microvolt=<1100000>;
+ regulator-min-microamp=<20000000>;
+ regulator-max-microamp=<40000000>;
+ regulator-ov-protection-microvolt=<1100000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&d0_i2c2 {
+ /* touch screen*/
+ status = "okay";
+ d0_gt911:touchscreen@14 {
+ compatible = "goodix,gt911";
+ reg = <0x14>;
+ interrupt-parent = <&porta>;
+ interrupts = <20 IRQ_TYPE_EDGE_RISING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_die0_gpio20_default>;
+ irq-gpios = <&porta 20 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&portd 15 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&d1_i2c2 {
+ /* touch screen*/
+ status = "okay";
+ d1_gt911:touchscreen@14 {
+ compatible = "goodix,gt911";
+ reg = <0x14>;
+ interrupt-parent = <&d1_porta>;
+ interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_die1_gpio0_default>;
+ irq-gpios = <&d1_porta 0 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&d1_portd 15 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&d0_i2c3 {
+ /* mipi csi0/csi1 */
+ status = "okay";
+};
+&d1_i2c3 {
+ status = "disabled";
+};
+
+&d0_i2c4 {
+ /* mipi csi2/csi3 */
+ status = "disabled";
+};
+&d1_i2c4 {
+ status = "disabled";
+};
+
+&d0_i2c5 {
+ /* mipi csi4/csi5 */
+ status = "disabled";
+};
+&d1_i2c5 {
+ status = "disabled";
+};
+
+&d0_i2c6 {
+ /* unused */
+ status = "disabled";
+};
+&d1_i2c6 {
+ status = "disabled";
+};
+
+&d0_i2c7 {
+ /* unused */
+ status = "disabled";
+};
+&d1_i2c7 {
+ status = "disabled";
+};
+
+&d0_i2c8 {
+ /* io extended for mipi csi */
+ status = "okay";
+ tca6416_0: gpio@20 {
+ compatible = "ti,tca6416";
+ reg = <0x20>;
+ gpio-controller; /* IRQ not connected */
+ #gpio-cells = <2>;
+ gpio-line-names = "MIPI_CSI0_PWDN", "MIPI_CSI0_RESET", "MIPI_CSI1_FBC", "MIPI_CSI1_ENB",
+ "MIPI_CSI1_RESET", "MIPI_CSI1_PWDN", "FREX_GP0", "",
+ "MIPI_CSI0_ENB", "MIPI_CSI0_FBC", "FREX_GP2", "MIPI_CSI2_FBC",
+ "MIPI_CSI2_ENB", "FREX_GP1", "MIPI_CSI2_RESET", "MIPI_CSI2_PWDN";
+ };
+ tca6416_1: gpio@21 {
+ compatible = "ti,tca6416";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ /* IRQ not connected */
+ gpio-line-names = "MIPI_CSI3_PWDN", "MIPI_CSI3_RESET", "MIPI_CSI3_ENB", "MIPI_CSI3_FBC",
+ "MIPI_CSI4_PWDN", "MIPI_CSI4_RESET", "MIPI_CSI4_ENB", "MIPI_CSI4_FBC",
+ "MIPI_CSI5_FBC", "MIPI_CSI5_ENB", "MIPI_CSI5_RESET", "MIPI_CSI5_PWDN",
+ "", "", "", "";
+ };
+};
+&d1_i2c8 {
+ status = "disabled";
+};
+
+&d0_i2c9 {
+ /* unused */
+ status = "disabled";
+};
+&d1_i2c9 {
+ status = "disabled";
+};
+
+&d0_aon_i2c0 {
+ /* ina226x3 */
+ status = "okay";
+ i2c-sda-hold-time-ns = <0x40>;
+ ina226@40 {
+ compatible = "ti,ina226";
+ #io-channel-cells = <1>;
+ label = "cpu_vdd";
+ reg = <0x40>;
+ shunt-resistor = <1000>;
+ };
+ ina226@41 {
+ compatible = "ti,ina226";
+ #io-channel-cells = <1>;
+ label = "d0_lpddr_vdd";
+ reg = <0x41>;
+ shunt-resistor = <1000>;
+ };
+ ina226@44 {
+ compatible = "ti,ina226";
+ #io-channel-cells = <1>;
+ label = "d0_soc_vdd";
+ reg = <0x44>;
+ shunt-resistor = <1000>;
+ };
+ tmp102@48 {
+ compatible = "ti,tmp102";
+ reg = <0x48>;
+ label = "d0_board_tmp";
+ #thermal-sensor-cells = <1>;
+ };
+};
+
+
+&d1_aon_i2c0 {
+ /* ina226x4 */
+ status = "okay";
+ i2c-sda-hold-time-ns = <0x40>;
+ ina226@40 {
+ compatible = "ti,ina226";
+ #io-channel-cells = <1>;
+ label = "vdd_dc_in";
+ reg = <0x40>;
+ shunt-resistor = <1000>;
+ };
+ ina226@41 {
+ compatible = "ti,ina226";
+ #io-channel-cells = <1>;
+ label = "d1_lpddr_vdd";
+ reg = <0x41>;
+ shunt-resistor = <1000>;
+ };
+ ina226@44 {
+ compatible = "ti,ina226";
+ #io-channel-cells = <1>;
+ label = "d1_soc_vdd";
+ reg = <0x44>;
+ shunt-resistor = <1000>;
+ };
+ tmp102@48 {
+ compatible = "ti,tmp102";
+ reg = <0x48>;
+ label = "d1_board_tmp";
+ #thermal-sensor-cells = <1>;
+ };
+};
+&d1_aon_i2c1 {
+ status = "disabled";
+};
+
+&pwm0 {
+ /* fan */
+ status = "okay";
+};
+&d1_pwm0 {
+ status = "disabled";
+};
+
+&pvt0 {
+ status = "okay";
+};
+&d1_pvt0 {
+ status = "okay";
+};
+
+&pvt1 {
+ status = "okay";
+};
+&d1_pvt1 {
+ status = "okay";
+};
+
+&wdt0 {
+ status = "disabled";
+};
+&d1_wdt0 {
+ status = "disabled";
+};
+
+&wdt1 {
+ status = "disabled";
+};
+&d1_wdt1 {
+ status = "disabled";
+};
+
+&wdt2 {
+ status = "disabled";
+};
+&d1_wdt2 {
+ status = "disabled";
+};
+
+&wdt3 {
+ status = "disabled";
+};
+&d1_wdt3 {
+ status = "disabled";
+};
+
+&die0_rtc {
+ status = "okay";
+};
+&d1_rtc {
+ status = "okay";
+};
+
+&timer0 {
+ status = "okay";
+};
+&d1_timer0 {
+ status = "okay";
+};
+
+&timer1 {
+ status = "okay";
+};
+&d1_timer1 {
+ status = "okay";
+};
+
+&timer2 {
+ status = "okay";
+};
+&d1_timer2 {
+ status = "okay";
+};
+
+&timer3 {
+ status = "okay";
+};
+&d1_timer3 {
+ status = "okay";
+};
+
+&pinctrl {
+ status = "okay";
+};
+&d1_pinctrl {
+ status = "okay";
+};
+
+&gpio0 {
+ status = "okay";
+};
+&d1_gpio0 {
+ status = "okay";
+};
+
+&dev_llc_d0{
+ /* apply_npu_1G_freq; */
+ npu-supply=<&d0_npu_vcc>;
+ status = "okay";
+};
+&d1_llc_dev{
+ /* apply_npu_1G_freq; */
+ npu-supply=<&d1_npu_vcc>;
+ status = "okay";
+};
+
+&d2d {
+ status = "okay";
+};
+
+&d1_d2d {
+ status = "okay";
+};
+
+/* die0 GPIO Function Description
+
+ gpio0 : pcie prstn(I)
+ gpio11 : tmp alert(I)
+ gpio13 : tf card detect(I)
+ gpio14 : gphy1 resetn(O)
+ gpio15 : gphy0 resetn(O)
+ gpio18 : ina226 alert(I)
+ gpio20 : lcd touch int(I)
+ gpio21 : head phone plug/unplug detection2(I)
+ gpio27 : black light pwr_en(O)
+ gpio28 : head phone plug/unplug detection1(I)
+ gpio68 : fan pwm(O)
+ gpio69 : fan touch(I)
+ gpio92 : frex gp0(O)
+ gpio93 : frex gp1(O)
+ gpio106 : mipi dsi resetn(O)
+ gpio111 : lcd touch resetn(O)
+*/
+/* die1 GPIO Function Description
+
+ gpio0 : lcd touch int(I)
+ gpio13 : gphy0 resetn(O)
+ gpio14 : gphy1 resetn(O)
+ gpio15 : bt wake host(I)
+ gpio16 : sdio wifi disable(O)
+ gpio18 : sdio wifi wake host(I)
+ gpio19 : pcie prstn(I)
+ gpio20 : head phone plug/unplug detection2(I)
+ gpio21 : mipi dsi resetn(O)
+ gpio27 : tmp alert(I)
+ gpio28 : head phone plug/unplug detection1(I)
+ gpio68 : system led(O)
+ gpio69 : black light pwr_en(O)
+ gpio92 : frex gp0(O)
+ gpio93 : frex gp1(O)
+ gpio106 : host wak bt(O)
+ gpio111 : lcd touch resetn(O)
+*/
diff --git a/arch/riscv/boot/dts/eswin/eic7702-evb-a1.dts b/arch/riscv/boot/dts/eswin/eic7702-evb-a1.dts
index dfb0f03463bc..2fa3f5441fbb 100644
--- a/arch/riscv/boot/dts/eswin/eic7702-evb-a1.dts
+++ b/arch/riscv/boot/dts/eswin/eic7702-evb-a1.dts
@@ -373,7 +373,7 @@ &d0_ipc_scpu {
status = "okay";
};
&d1_ipc_scpu {
- status = "disabled";
+ status = "okay";
};
&d0_lpcpu {
@@ -775,7 +775,9 @@ &d0_gmac0 {
rst-gpios = <&porta 15 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x290 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
-
+ dly-param-1000m = <0x23232323 0x800c8023 0x0c0c0c0c>;
+ dly-param-100m = <0x50505050 0x803f8050 0x3f3f3f3f>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
@@ -785,7 +787,9 @@ &d1_gmac0 {
rst-gpios = <&d1_porta 13 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&d1_pinctrl 0x290 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
-
+ dly-param-1000m = <0x23232323 0x800c8023 0x0c0c0c0c>;
+ dly-param-100m = <0x50505050 0x803f8050 0x3f3f3f3f>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
@@ -795,7 +799,9 @@ &d0_gmac1 {
rst-gpios = <&porta 14 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&pinctrl 0x294 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
-
+ dly-param-1000m = <0x25252525 0x80268025 0x26262626>;
+ dly-param-100m = <0x48484848 0x80588048 0x58585858>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
@@ -805,7 +811,9 @@ &d1_gmac1 {
rst-gpios = <&d1_porta 14 GPIO_ACTIVE_LOW>;
eswin,rgmiisel = <&d1_pinctrl 0x294 0x3>;
eswin,led-cfgs = <0x6100 0xa40 0x420>;
-
+ dly-param-1000m = <0x25252525 0x80268025 0x26262626>;
+ dly-param-100m = <0x48484848 0x80588048 0x58585858>;
+ dly-param-10m = <0 0 0>;
status = "okay";
};
diff --git a/arch/riscv/boot/dts/eswin/eic770x-ooptable.dtsi b/arch/riscv/boot/dts/eswin/eic770x-ooptable.dtsi
new file mode 100644
index 000000000000..471984153c44
--- /dev/null
+++ b/arch/riscv/boot/dts/eswin/eic770x-ooptable.dtsi
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Include file for pin control of Eswin EIC770x family SoC.
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <dt-bindings/clock/win2030-clock.h>
+/ {
+ cpu_opp_table: opp-table@cpu {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-24000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_24M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-100000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_100M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-200000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_200M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-400000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_400M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-500000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_500M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-600000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_600M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-700000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_700M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-800000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_800M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-900000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_900M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1000M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1200M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-1300000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1300M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ opp-1400000000 {
+ opp-hz = /bits/ 64 <CLK_FREQ_1400M>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <70000>;
+ };
+ };
+
+ dsp_opp_table: opp-table@dsp {
+ compatible = "operating-points-v2";
+ opp@520000000 {
+ opp-hz = /bits/ 64 <520000000>;
+ opp-microvolt = <800000>;
+ };
+ opp@1040000000 {
+ opp-hz = /bits/ 64 <1040000000>;
+ opp-microvolt = <800000>;
+ };
+ };
+ npu_opp_table: opp-table@npu {
+ compatible = "operating-points-v2";
+ opp@1040000000 {
+ opp-hz = /bits/ 64 <1040000000>;
+ opp-microvolt = <900000>;
+ };
+ opp@1500000000 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-microvolt = <1050000>;
+ };
+
+ };
+
+ g2d_opp_table: opp-table@g2d {
+ compatible = "operating-points-v2";
+ opp@260000000 {
+ opp-hz = /bits/ 64 <260000000>;
+ opp-microvolt = <800000>;
+ };
+ opp@520000000 {
+ opp-hz = /bits/ 64 <520000000>;
+ opp-microvolt = <800000>;
+ };
+ opp@693333334 {
+ opp-hz = /bits/ 64 <693333334>;
+ opp-microvolt = <800000>;
+ };
+ opp@1040000000 {
+ opp-hz = /bits/ 64 <1040000000>;
+ opp-microvolt = <800000>;
+ };
+ };
+
+ vi_opp_table: opp-table@vi {
+ compatible = "operating-points-v2";
+ opp@800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <800000>;
+ };
+ opp@400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <800000>;
+ };
+ opp@200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <800000>;
+ };
+ };
+
+ venc_opp_table: opp-table@venc {
+ compatible = "operating-points-v2";
+ opp@800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <800000>;
+ };
+ opp@400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <800000>;
+ };
+ opp@200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <800000>;
+ };
+ };
+
+ vdec_opp_table: opp-table@vdec {
+ compatible = "operating-points-v2";
+ opp@800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <800000>;
+ };
+ opp@400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <800000>;
+ };
+ opp@200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <800000>;
+ };
+ };
+};
diff --git a/arch/riscv/boot/dts/eswin/eswin-win2030-arch-d2d.dtsi b/arch/riscv/boot/dts/eswin/eswin-win2030-arch-d2d.dtsi
index c9afd60d2434..5847de53a516 100644
--- a/arch/riscv/boot/dts/eswin/eswin-win2030-arch-d2d.dtsi
+++ b/arch/riscv/boot/dts/eswin/eswin-win2030-arch-d2d.dtsi
@@ -20,6 +20,7 @@
#define CHIPLET_AND_DIE (0x2)
#include "eswin-win2030-arch.dtsi"
+#include "eic770x-ooptable.dtsi"
&L64 {
@@ -105,7 +106,7 @@ cpu_4: cpu@4 {
tlb-split;
numa-node-id = <1>;
clocks = <&d1_clock WIN2030_CLK_CPU_EXT_SRC_CORE_CLK_0>;
- operating-points-v2 = <&d1_cpu_opp_table>;
+ operating-points-v2 = <&cpu_opp_table>;
cpu-idle-states = <&CPU_RET>;
cpu4_intc: interrupt-controller {
#interrupt-cells = <1>;
@@ -153,7 +154,7 @@ cpu_5: cpu@5 {
tlb-split;
numa-node-id = <1>;
clocks = <&d1_clock WIN2030_CLK_CPU_EXT_SRC_CORE_CLK_1>;
- operating-points-v2 = <&d1_cpu_opp_table>;
+ operating-points-v2 = <&cpu_opp_table>;
cpu-idle-states = <&CPU_RET>;
cpu5_intc: interrupt-controller {
#interrupt-cells = <1>;
@@ -200,7 +201,7 @@ cpu_6: cpu@6 {
tlb-split;
numa-node-id = <1>;
clocks = <&d1_clock WIN2030_CLK_CPU_EXT_SRC_CORE_CLK_2>;
- operating-points-v2 = <&d1_cpu_opp_table>;
+ operating-points-v2 = <&cpu_opp_table>;
cpu-idle-states = <&CPU_RET>;
cpu6_intc: interrupt-controller {
#interrupt-cells = <1>;
@@ -247,7 +248,7 @@ cpu_7: cpu@7 {
tlb-split;
numa-node-id = <1>;
clocks = <&d1_clock WIN2030_CLK_CPU_EXT_SRC_CORE_CLK_3>;
- operating-points-v2 = <&d1_cpu_opp_table>;
+ operating-points-v2 = <&cpu_opp_table>;
cpu-idle-states = <&CPU_RET>;
cpu7_intc: interrupt-controller {
#interrupt-cells = <1>;
@@ -272,6 +273,7 @@ PMU1: pmu@1 {
riscv,event-to-mhpmevent = <0x4 0x0 0x202 0x5 0x0 0x4000 0x6 0x0 0x2001 0x10009 0x0 0x102 0x10019 0x0 0x1002 0x10021 0x0 0x802>;
compatible = "riscv,pmu0", "riscv,pmu";
interrupts-extended = <&cpu4_intc 13 &cpu5_intc 13 &cpu6_intc 13 &cpu7_intc 13>;
+ numa-node-id = <1>;
};
d1_bus_err0: bus-error-unit@21700000 {
@@ -280,6 +282,7 @@ d1_bus_err0: bus-error-unit@21700000 {
interrupts = <517>;
reg = <0x0 0x21700000 0x0 0x1000>;
reg-names = "control";
+ numa-node-id = <1>;
};
d1_bus_err1: bus-error-unit@21701000 {
compatible = "sifive,buserror";
@@ -287,6 +290,7 @@ d1_bus_err1: bus-error-unit@21701000 {
interrupts = <518>;
reg = <0x0 0x21701000 0x0 0x1000>;
reg-names = "control";
+ numa-node-id = <1>;
};
d1_bus_err2: bus-error-unit@21702000 {
compatible = "sifive,buserror";
@@ -294,6 +298,7 @@ d1_bus_err2: bus-error-unit@21702000 {
interrupts = <519>;
reg = <0x0 0x21702000 0x0 0x1000>;
reg-names = "control";
+ numa-node-id = <1>;
};
d1_bus_err3: bus-error-unit@21703000 {
compatible = "sifive,buserror";
@@ -301,6 +306,7 @@ d1_bus_err3: bus-error-unit@21703000 {
interrupts = <520>;
reg = <0x0 0x21703000 0x0 0x1000>;
reg-names = "control";
+ numa-node-id = <1>;
};
D1CACHE: cache-controller@22010000 {
@@ -356,6 +362,7 @@ d1_l2_cache_0: pl2@20104000 {
reg-names = "control";
sifive,ecc-granularity = <16>;
sifive,perfmon-counters = <6>;
+ numa-node-id = <1>;
};
d1_l2_cache_1: pl2@20108000 {
cache-block-size = <64>;
@@ -369,6 +376,7 @@ d1_l2_cache_1: pl2@20108000 {
reg-names = "control";
sifive,ecc-granularity = <16>;
sifive,perfmon-counters = <6>;
+ numa-node-id = <1>;
};
d1_l2_cache_2: pl2@2010c000 {
cache-block-size = <64>;
@@ -382,6 +390,7 @@ d1_l2_cache_2: pl2@2010c000 {
reg-names = "control";
sifive,ecc-granularity = <16>;
sifive,perfmon-counters = <6>;
+ numa-node-id = <1>;
};
d1_l2_cache_3: pl2@20110000 {
cache-block-size = <64>;
@@ -395,6 +404,7 @@ d1_l2_cache_3: pl2@20110000 {
reg-names = "control";
sifive,ecc-granularity = <16>;
sifive,perfmon-counters = <6>;
+ numa-node-id = <1>;
};
};
diff --git a/arch/riscv/boot/dts/eswin/eswin-win2030-arch.dtsi b/arch/riscv/boot/dts/eswin/eswin-win2030-arch.dtsi
index 64671ff693e3..1bcfba13d1a3 100644
--- a/arch/riscv/boot/dts/eswin/eswin-win2030-arch.dtsi
+++ b/arch/riscv/boot/dts/eswin/eswin-win2030-arch.dtsi
@@ -19,6 +19,7 @@
*/
#include <dt-bindings/clock/win2030-clock.h>
+#include "eic770x-ooptable.dtsi"
#define UART0_INT 100
#define UART1_INT 101
@@ -84,7 +85,7 @@ cpu_0: cpu@0 {
tlb-split;
numa-node-id = <0>;
clocks = <&d0_clock WIN2030_CLK_CPU_EXT_SRC_CORE_CLK_0>;
- operating-points-v2 = <&d0_cpu_opp_table>;
+ operating-points-v2 = <&cpu_opp_table>;
#cooling-cells = <2>;
dynamic-power-coefficient = <324>;
cpu-idle-states = <&CPU_RET>;
@@ -130,7 +131,7 @@ cpu_1: cpu@1 {
tlb-split;
numa-node-id = <0>;
clocks = <&d0_clock WIN2030_CLK_CPU_EXT_SRC_CORE_CLK_1>;
- operating-points-v2 = <&d0_cpu_opp_table>;
+ operating-points-v2 = <&cpu_opp_table>;
#cooling-cells = <2>;
dynamic-power-coefficient = <324>;
cpu-idle-states = <&CPU_RET>;
@@ -176,7 +177,7 @@ cpu_2: cpu@2 {
tlb-split;
numa-node-id = <0>;
clocks = <&d0_clock WIN2030_CLK_CPU_EXT_SRC_CORE_CLK_2>;
- operating-points-v2 = <&d0_cpu_opp_table>;
+ operating-points-v2 = <&cpu_opp_table>;
#cooling-cells = <2>;
dynamic-power-coefficient = <324>;
cpu-idle-states = <&CPU_RET>;
@@ -222,7 +223,7 @@ cpu_3: cpu@3 {
tlb-split;
numa-node-id = <0>;
clocks = <&d0_clock WIN2030_CLK_CPU_EXT_SRC_CORE_CLK_3>;
- operating-points-v2 = <&d0_cpu_opp_table>;
+ operating-points-v2 = <&cpu_opp_table>;
#cooling-cells = <2>;
dynamic-power-coefficient = <324>;
cpu-idle-states = <&CPU_RET>;
@@ -233,12 +234,7 @@ cpu3_intc: interrupt-controller {
};
};
};
- L50: memory@80000000 {
- compatible = "sifive,axi4-mem-port", "sifive,axi4-port", "sifive,mem-port";
- device_type = "memory";
- reg = <0x0 0x80000000 0x7f 0x80000000>;
- sifive,port-width-bytes = <32>;
- };
+
SOC: soc {
#address-cells = <2>;
#size-cells = <2>;
@@ -252,6 +248,7 @@ PMU0: pmu@0 {
riscv,event-to-mhpmevent = <0x4 0x0 0x202 0x5 0x0 0x4000 0x6 0x0 0x2001 0x10009 0x0 0x102 0x10019 0x0 0x1002 0x10021 0x0 0x802>;
compatible = "riscv,pmu0", "riscv,pmu";
interrupts-extended = <&cpu0_intc 13 &cpu1_intc 13 &cpu2_intc 13 &cpu3_intc 13>;
+ numa-node-id = <0>;
};
L40: authentication-controller {
compatible = "sifive,authentication0";
@@ -297,6 +294,7 @@ d0_bus_err0: bus-error-unit@hart0 {
interrupts = <517>;
reg = <0x0 0x1700000 0x0 0x1000>;
reg-names = "control";
+ numa-node-id = <0>;
};
d0_bus_err1: bus-error-unit@hart1 {
compatible = "sifive,buserror";
@@ -304,6 +302,7 @@ d0_bus_err1: bus-error-unit@hart1 {
interrupts = <518>;
reg = <0x0 0x1701000 0x0 0x1000>;
reg-names = "control";
+ numa-node-id = <0>;
};
d0_bus_err2: bus-error-unit@hart2 {
compatible = "sifive,buserror";
@@ -311,6 +310,7 @@ d0_bus_err2: bus-error-unit@hart2 {
interrupts = <519>;
reg = <0x0 0x1702000 0x0 0x1000>;
reg-names = "control";
+ numa-node-id = <0>;
};
d0_bus_err3: bus-error-unit@hart3 {
compatible = "sifive,buserror";
@@ -318,6 +318,7 @@ d0_bus_err3: bus-error-unit@hart3 {
interrupts = <520>;
reg = <0x0 0x1703000 0x0 0x1000>;
reg-names = "control";
+ numa-node-id = <0>;
};
D0CACHE: cache-controller@2010000 {
cache-block-size = <64>;
@@ -328,7 +329,7 @@ D0CACHE: cache-controller@2010000 {
compatible = "sifive,ccache1", "cache", "sifive,fu740-c000-ccache";
interrupt-parent = <&plic0>;
interrupts = <1>, <3>, <4>, <2>;
- next-level-cache = <&L9 &L10 &L11 &L50>;
+ next-level-cache = <&L9 &L10 &L11>;
reg = <0x0 0x2010000 0x0 0x4000 0x0 0x8000000 0x0 0x400000>;
reg-names = "control", "sideband";
sifive,a-mshr-count = <60>;
@@ -386,6 +387,7 @@ d0_l2_cache_0: pl2@104000 {
reg-names = "control";
sifive,ecc-granularity = <16>;
sifive,perfmon-counters = <6>;
+ numa-node-id = <0>;
};
d0_l2_cache_1: pl2@108000 {
cache-block-size = <64>;
@@ -399,6 +401,7 @@ d0_l2_cache_1: pl2@108000 {
reg-names = "control";
sifive,ecc-granularity = <16>;
sifive,perfmon-counters = <6>;
+ numa-node-id = <0>;
};
d0_l2_cache_2: pl2@10c000 {
cache-block-size = <64>;
@@ -412,6 +415,7 @@ d0_l2_cache_2: pl2@10c000 {
reg-names = "control";
sifive,ecc-granularity = <16>;
sifive,perfmon-counters = <6>;
+ numa-node-id = <0>;
};
d0_l2_cache_3: pl2@110000 {
cache-block-size = <64>;
@@ -425,6 +429,7 @@ d0_l2_cache_3: pl2@110000 {
reg-names = "control";
sifive,ecc-granularity = <16>;
sifive,perfmon-counters = <6>;
+ numa-node-id = <0>;
};
L10: rom@1a000000 {
compatible = "ucbbar,cacheable-zero0";
diff --git a/arch/riscv/boot/dts/eswin/eswin-win2030-die0-noc.dtsi b/arch/riscv/boot/dts/eswin/eswin-win2030-die0-noc.dtsi
index fe81f8e622e6..77243ae1b93f 100644
--- a/arch/riscv/boot/dts/eswin/eswin-win2030-die0-noc.dtsi
+++ b/arch/riscv/boot/dts/eswin/eswin-win2030-die0-noc.dtsi
@@ -24,6 +24,7 @@ d0_cfg_noc:d0_cfg_noc{
#size-cells = <2>;
ranges;
reg = <0 0x52060000 0 0x4000>;
+ numa-node-id = <0>;
interrupts = <446>;
interrupt-names = "error";
@@ -273,6 +274,7 @@ d0_llc_noc:d0_llc_noc@52081400 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ numa-node-id = <0>;
reg = <0 0x52081400 0 0x4000>;
interrupts = <441>;
interrupt-names = "error";
@@ -548,6 +550,7 @@ d0_sys_noc:d0_sys_noc@52002C00 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ numa-node-id = <0>;
reg = <0 0x52002C00 0 0x4000>;
interrupts = <431>;
interrupt-names = "error";
@@ -2220,6 +2223,7 @@ d0_media_noc:d0_media_noc@52021400 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ numa-node-id = <0>;
reg = <0 0x52021400 0 0x4000>;
interrupts = <454>;
interrupt-names = "error";
@@ -2530,6 +2534,7 @@ d0_realtime_noc:d0_realtime_noc@52041400 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ numa-node-id = <0>;
reg = <0 0x52041400 0 0x4000>;
interrupts = <448>;
interrupt-names = "error";
diff --git a/arch/riscv/boot/dts/eswin/eswin-win2030-die0-soc.dtsi b/arch/riscv/boot/dts/eswin/eswin-win2030-die0-soc.dtsi
index 7df6029a9451..8858283c1e68 100644
--- a/arch/riscv/boot/dts/eswin/eswin-win2030-die0-soc.dtsi
+++ b/arch/riscv/boot/dts/eswin/eswin-win2030-die0-soc.dtsi
@@ -32,77 +32,6 @@
/ {
compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000","sifive,fu740";
- d0_cpu_opp_table: opp-table0 {
- compatible = "operating-points-v2";
- opp-shared;
-
- opp-24000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_24M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-100000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_100M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-200000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_200M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-400000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_400M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-500000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_500M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-600000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_600M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-700000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_700M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-800000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_800M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-900000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_900M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-1000000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_1000M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-1200000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_1200M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-1300000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_1300M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-1400000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_1400M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- };
-
thermal-zones {
thermal0 {
polling-delay-passive = <500>; /*ms*/
@@ -111,9 +40,10 @@ thermal0 {
thermal-sensors = <&pvt0>;
trips {
+ /*
threshold: trip-point0 {
- temperature = <60000>; /* DC*1000 */
- hysteresis = <1000>; /* DC*1000 */
+ temperature = <60000>;
+ hysteresis = <1000>;
type = "passive";
};
target: trip-point1 {
@@ -121,14 +51,16 @@ target: trip-point1 {
hysteresis = <1000>;
type = "passive";
};
+ */
crit: trip-point2 {
- temperature = <110000>;
+ temperature = <88000>;
hysteresis = <0>;
type = "critical";
};
};
cooling-maps {
+ /*
map0 {
trip = <&target>;
contribution = <1024>;
@@ -140,14 +72,15 @@ map0 {
};
map1 {
trip = <&target>;
- contribution = <1024>; /*TBD*/
+ contribution = <1024>;
cooling-device = <&d0_npu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map2 {
trip = <&target>;
- contribution = <1024>; /*TBD*/
+ contribution = <1024>;
cooling-device = <&gpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
+ */
};
};
};
@@ -241,10 +174,12 @@ d0_sys_crg: sys-crg@51828000 {
d0_reset: reset-controller {
compatible = "eswin,win2030-reset";
#reset-cells = <2>;
+ numa-node-id = <0>;
};
d0_clock: clock-controller {
compatible = "eswin,win2030-clock";
#clock-cells = <1>;
+ numa-node-id = <0>;
};
};
@@ -253,10 +188,12 @@ hfclk: hfclk {
compatible = "fixed-clock";
clock-frequency = <LSPCLK_FREQ>;
clock-output-names = "hfclk";
+ numa-node-id = <0>;
};
d0_hsp_sp_csr: hsp_sp_top_csr@0x50440000 {
compatible = "eswin,win2030-hsp-sp-csr", "syscon";
+ numa-node-id = <0>;
#size-cells = <2>;
reg = <0x0 0x50440000 0x0 0x2000>;
};
@@ -482,11 +419,12 @@ d0_gmac0: ethernet@50400000 {
clock-names = "app", "stmmaceth","tx";
resets = <&d0_reset HSPDMA_RST_CTRL SW_HSP_ETH0_ARSTN>;
reset-names = "ethrst";
- iommus = <&smmu0 WIN2030_SID_ETH0>;
+ //iommus = <&smmu0 WIN2030_SID_ETH0>;
tbus = <WIN2030_TBUID_ETH>;
dma-noncoherent;
eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x1030 0x100 0x108>;
eswin,syscrg_csr = <&d0_sys_crg 0x148 0x14c>;
+ eswin,dly_hsp_reg = <0x114 0x118 0x11c>;
snps,axi-config = <&d0_stmmac_axi_setup>;
d0_stmmac_axi_setup: stmmac-axi-config {
snps,blen = <0 0 0 0 16 8 4>;
@@ -512,11 +450,12 @@ d0_gmac1: ethernet@50410000 {
clock-names = "app", "stmmaceth","tx";
resets = <&d0_reset HSPDMA_RST_CTRL SW_HSP_ETH1_ARSTN>;
reset-names = "ethrst";
- iommus = <&smmu0 WIN2030_SID_ETH1>;
+ //iommus = <&smmu0 WIN2030_SID_ETH1>;
tbus = <WIN2030_TBUID_ETH>;
dma-noncoherent;
eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x1034 0x200 0x208>;
eswin,syscrg_csr = <&d0_sys_crg 0x148 0x14c>;
+ eswin,dly_hsp_reg = <0x214 0x218 0x21c>;
snps,axi-config = <&d0_stmmac_axi_setup_gmac1>;
d0_stmmac_axi_setup_gmac1: stmmac-axi-config {
snps,blen = <0 0 0 0 16 8 4>;
@@ -530,6 +469,7 @@ noc {
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ numa-node-id = <0>;
#include "eswin-win2030-die0-noc.dtsi"
};
@@ -549,11 +489,17 @@ d0_npu: eswin-npu@51c00000 {
clocks = <&d0_clock WIN2030_CLK_NPU_ACLK>,
<&d0_clock WIN2030_CLK_NPU_CFG_CLK>,
<&d0_clock WIN2030_CLK_NPU_CLK>,
- <&d0_clock WIN2030_CLK_NPU_E31_CLK>;
- clock-names = "aclk", "cfg_clk", "core_clk", "e31_core_clk";
+ <&d0_clock WIN2030_CLK_NPU_E31_CLK>,
+ <&d0_clock WIN2030_MUX_U_NPU_CORE_3MUX1_GFREE>,
+ <&d0_clock WIN2030_SPLL2_FOUT2>,
+ <&d0_clock WIN2030_SPLL1_FOUT1>;
+
+ clock-names = "aclk", "cfg_clk", "core_clk", "e31_core_clk", "mux_u_npu_core_3mux1_gfree", "fixed_rate_clk_spll2_fout2",
+ "fixed_rate_clk_spll1_fout1";
resets = <&d0_reset NPU_RST_CTRL SW_NPU_E31CORE_RSTN>;
reset-names = "e31_core";
+ operating-points-v2 = <&npu_opp_table>;
numa-node-id = <0>;
firmware-name = "eic7700_die0_e31_fw";
@@ -593,6 +539,7 @@ d0_dsp_subsys:dsp_subsys@52280400 {
reg = <0x0 0x52280400 0x0 0x10000>,
<0x0 0x51810000 0x0 0x8000>;
ranges;
+ numa-node-id = <0>;
dma-ranges = <0x0 0x30000000 0x0 0xc0000000 0x0 0xce000000>;
compatible = "es-dsp-subsys", "simple-bus";
clocks = <&d0_clock WIN2030_CLK_DSPT_CFG_CLK>, <&d0_clock WIN2030_CLK_DSPT_ACLK>;
@@ -614,6 +561,7 @@ d0_dsp0:es_dsp@0 {
0x28120000 0 0x5b120000 0x20000>;
clocks = <&d0_clock WIN2030_CLK_DSP_ACLK_0>;
clock-names = "aclk";
+ operating-points-v2 = <&dsp_opp_table>;
dsp_mbox = <&d0_mbox4>;
device-irq = <11
ESWIN_MAILBOX_DSP_0_TO_U84_REG_BASE
@@ -644,6 +592,7 @@ d0_dsp1:es_dsp@1 {
0x28120000 0 0x5b160000 0x20000>;
clocks = <&d0_clock WIN2030_CLK_DSP_ACLK_1>;
clock-names = "aclk";
+ operating-points-v2 = <&dsp_opp_table>;
dsp_mbox = <&d0_mbox5>;
device-irq = <13
ESWIN_MAILBOX_DSP_1_TO_U84_REG_BASE
@@ -673,6 +622,7 @@ d0_dsp2:es_dsp@2 {
0x28120000 0 0x5b1a0000 0x20000>;
clocks = <&d0_clock WIN2030_CLK_DSP_ACLK_2>;
clock-names = "aclk";
+ operating-points-v2 = <&dsp_opp_table>;
dsp_mbox = <&d0_mbox6>;
device-irq = <15
ESWIN_MAILBOX_DSP_2_TO_U84_REG_BASE
@@ -702,6 +652,7 @@ d0_dsp3:es_dsp@3 {
0x28120000 0 0x5b1e0000 0x20000>;
clocks = <&d0_clock WIN2030_CLK_DSP_ACLK_3>;
clock-names = "aclk";
+ operating-points-v2 = <&dsp_opp_table>;
dsp_mbox = <&d0_mbox7>;
device-irq = <17
ESWIN_MAILBOX_DSP_3_TO_U84_REG_BASE
@@ -722,6 +673,27 @@ ESWIN_MAIBOX_U84_IRQ_BIT
dsp@0 {
};
};
+ d0_sofdsp3: sofdsp@4 {
+ #sound-dai-cells = <1>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "eswin,sof-dsp";
+ reg = <0x0 0x5b018000 0x0 0x8000>,
+ <0x0 0x5b1c0000 0x0 0x40000>;
+ mbox-names = "dsp-mbox";
+ mboxes = <&d0_mbox7 0>;
+ clocks = <&d0_clock WIN2030_CLK_DSP_ACLK_3>;
+ clock-names = "aclk";
+ process-id = <3>;
+ iommus = <&smmu0 WIN2030_SID_DSP_3>;
+ tbus = <WIN2030_TBUID_DSP3>;
+ dma-noncoherent;
+ mailbox-dsp-to-u84-addr = <ESWIN_MAILBOX_DSP_3_TO_U84_REG_BASE>;
+ mailbox-u84-to-dsp-addr = <ESWIN_MAILBOX_U84_TO_DSP_3_REG_BASE>;
+ dsp-uart = <&d0_uart0>;
+ device-uart-mutex = <0x51820000>;
+ numa-node-id = <0>;
+ };
};
gc820: g2d@50140000 {
@@ -751,6 +723,7 @@ gc820: g2d@50140000 {
contiguous-size = <0xa00000>;
recovery = <0>;
dma-noncoherent;
+ operating-points-v2 = <&g2d_opp_table>;
numa-node-id = <0>;
};
@@ -772,6 +745,7 @@ gpu0: gpu@51400000 {
interrupt-parent = <&plic0>;
interrupts = <15>;
dma-noncoherent;
+ numa-node-id = <0>;
#cooling-cells = <2>;
dynamic-power-coefficient = <0>; /*TBD*/
@@ -893,6 +867,7 @@ bootspi: spi@51800000 {
reset-names = "rst";
spi-max-frequency = <4800000>;
reg-io-width = <4>;
+ numa-node-id = <0>;
status = "disabled";
};
sdhci_emmc: mmc@50450000 {
@@ -1024,6 +999,7 @@ vdec0: video-decoder0@50100000 {
<&d0_reset VD_RST_CTRL SW_VD_AXI_RSTN>;
reset-names = "axi", "cfg", "moncfg", "jd_cfg", "jd_axi", "vd_cfg", "vd_axi";
eswin,syscfg = <&d0_sys_con 0x0 0x4>;
+ operating-points-v2 = <&vdec_opp_table>;
vcmd-core = <0 0x6c>;
axife-core = <0x200 0x100>;
@@ -1072,6 +1048,7 @@ venc0: video-encoder@50110000 {
<&d0_reset VE_RST_CTRL SW_VE_AXI_RSTN>;
reset-names = "axi", "cfg", "moncfg", "je_cfg", "je_axi", "ve_cfg", "ve_axi";
eswin,syscfg = <&d0_sys_con 0x0 0x4>;
+ operating-points-v2 = <&venc_opp_table>;
vcmd-core = <0 0x6c>;
axife-core = <0x2000 0x7d0>;
@@ -1115,6 +1092,7 @@ d0_mbox0: mbox@50a00000 {
reset-names = "rst", "rst_device";
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_SCPU_IRQ_BIT>;
+ numa-node-id = <0>;
dma-noncoherent;
};
@@ -1134,6 +1112,7 @@ d0_mbox1: mbox@50a20000 {
reset-names = "rst", "rst_device";
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_LPCPU_IRQ_BIT>;
+ numa-node-id = <0>;
dma-noncoherent;
};
@@ -1153,6 +1132,7 @@ d0_mbox2: mbox@50a40000 {
reset-names = "rst", "rst_device";
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_NPU_0_IRQ_BIT>;
+ numa-node-id = <0>;
dma-noncoherent;
};
@@ -1172,6 +1152,7 @@ d0_mbox3: mbox@50a60000 {
reset-names = "rst", "rst_device";
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_NPU_1_IRQ_BIT>;
+ numa-node-id = <0>;
dma-noncoherent;
};
@@ -1191,6 +1172,7 @@ d0_mbox4: mbox@50a80000 {
reset-names = "rst", "rst_device";
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_DSP_0_IRQ_BIT>;
+ numa-node-id = <0>;
dma-noncoherent;
};
@@ -1210,6 +1192,7 @@ d0_mbox5: mbox@50aa0000 {
reset-names = "rst", "rst_device";
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_DSP_1_IRQ_BIT>;
+ numa-node-id = <0>;
dma-noncoherent;
};
@@ -1229,6 +1212,7 @@ d0_mbox6: mbox@50ac0000 {
reset-names = "rst", "rst_device";
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_DSP_2_IRQ_BIT>;
+ numa-node-id = <0>;
dma-noncoherent;
};
@@ -1248,6 +1232,7 @@ d0_mbox7: mbox@50ae0000 {
reset-names = "rst", "rst_device";
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_DSP_3_IRQ_BIT>;
+ numa-node-id = <0>;
dma-noncoherent;
};
@@ -1303,6 +1288,7 @@ pvt0: pvt@0x50b00000 {
#thermal-sensor-cells = <0>;
status = "disabled";
label = "pvt0";
+ numa-node-id = <0>;
};
pvt1: pvt@0x52360000 {
compatible = "eswin,eswin-pvt-ddr";
@@ -1317,6 +1303,7 @@ pvt1: pvt@0x52360000 {
interrupt-parent = <&plic0>;
status = "disabled";
label = "pvt1";
+ numa-node-id = <0>;
};
fan_control: fan_control@50b50000 {
@@ -1333,9 +1320,10 @@ fan_control: fan_control@50b50000 {
pwm-minimum-period = <1000>;
pwms = <&pwm0 0 100000>;
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_die0_fan_tach_default>;
+ pinctrl-0 = <&pinctrl_die0_fan_tach_default &pinctrl_die0_pwm0_default>;
status = "disabled";
label = "fan_control";
+ numa-node-id = <0>;
};
d0_i2c0: i2c@50950000 {
@@ -1350,6 +1338,7 @@ d0_i2c0: i2c@50950000 {
reg = <0x0 0x50950000 0x0 0x8000>;
interrupts = <105>;
interrupt-parent = <&plic0>;
+ numa-node-id = <0>;
};
d0_i2c1: i2c@50960000 {
compatible = "snps,designware-i2c";
@@ -1363,6 +1352,7 @@ d0_i2c1: i2c@50960000 {
reg = <0x0 0x50960000 0x0 0x10000>;
interrupts = <106>;
interrupt-parent = <&plic0>;
+ numa-node-id = <0>;
};
d0_i2c2: i2c@50970000 {
compatible = "snps,designware-i2c";
@@ -1376,6 +1366,7 @@ d0_i2c2: i2c@50970000 {
reg = <0x0 0x50970000 0x0 0x8000>;
interrupts = <107>;
interrupt-parent = <&plic0>;
+ numa-node-id = <0>;
};
d0_i2c3: i2c@50980000 {
compatible = "snps,designware-i2c";
@@ -1389,6 +1380,7 @@ d0_i2c3: i2c@50980000 {
reg = <0x0 0x50980000 0x0 0x8000>;
interrupts = <108>;
interrupt-parent = <&plic0>;
+ numa-node-id = <0>;
};
d0_i2c4: i2c@50990000 {
compatible = "snps,designware-i2c";
@@ -1402,6 +1394,7 @@ d0_i2c4: i2c@50990000 {
reg = <0x0 0x50990000 0x0 0x8000>;
interrupts = <109>;
interrupt-parent = <&plic0>;
+ numa-node-id = <0>;
};
d0_i2c5: i2c@509a0000 {
compatible = "snps,designware-i2c";
@@ -1415,6 +1408,7 @@ d0_i2c5: i2c@509a0000 {
reg = <0x0 0x509a0000 0x0 0x8000>;
interrupts = <110>;
interrupt-parent = <&plic0>;
+ numa-node-id = <0>;
};
d0_i2c6: i2c@509b0000 {
compatible = "snps,designware-i2c";
@@ -1428,6 +1422,7 @@ d0_i2c6: i2c@509b0000 {
reg = <0x0 0x509b0000 0x0 0x8000>;
interrupts = <111>;
interrupt-parent = <&plic0>;
+ numa-node-id = <0>;
};
d0_i2c7: i2c@509c0000 {
compatible = "snps,designware-i2c";
@@ -1441,6 +1436,7 @@ d0_i2c7: i2c@509c0000 {
reg = <0x0 0x509c0000 0x0 0x8000>;
interrupts = <112>;
interrupt-parent = <&plic0>;
+ numa-node-id = <0>;
};
d0_i2c8: i2c@509d0000 {
compatible = "snps,designware-i2c";
@@ -1454,6 +1450,7 @@ d0_i2c8: i2c@509d0000 {
reg = <0x0 0x509d0000 0x0 0x8000>;
interrupts = <113>;
interrupt-parent = <&plic0>;
+ numa-node-id = <0>;
};
d0_i2c9: i2c@509e0000 {
compatible = "snps,designware-i2c";
@@ -1467,6 +1464,7 @@ d0_i2c9: i2c@509e0000 {
reg = <0x0 0x509e0000 0x0 0x8000>;
interrupts = <114>;
interrupt-parent = <&plic0>;
+ numa-node-id = <0>;
};
d0_aon_i2c0: i2c@51830000 {
compatible = "snps,designware-i2c";
@@ -1489,6 +1487,7 @@ d0_aon_i2c0: i2c@51830000 {
* 0xff : no need to select to dma controller
*/
dmas = <&d0_aon_dmac 41 0xff>, <&d0_aon_dmac 42 0xff>;
+ numa-node-id = <0>;
};
d0_aon_i2c1: i2c@51838000 {
compatible = "snps,designware-i2c";
@@ -1502,10 +1501,12 @@ d0_aon_i2c1: i2c@51838000 {
reg = <0x0 0x51838000 0x0 0x8000>;
interrupts = <291>;
interrupt-parent = <&plic0>;
+ numa-node-id = <0>;
};
pinctrl: pinctrl@0x51600080 {
compatible = "eswin,eic7x-pinctrl";
reg = <0x0 0x51600080 0x0 0x1FFF80>;
+ numa-node-id = <0>;
status = "disabled";
pinctrl_die0_pwm0_default: pwm0-default{
mux {
@@ -1526,6 +1527,7 @@ gpio0: gpio@51600000 {
#size-cells = <0>;
compatible = "snps,dw-apb-gpio";
reg = <0x0 0x51600000 0x0 0x80>;
+ numa-node-id = <0>;
porta: gpio-port@0 {
compatible = "snps,dw-apb-gpio-port";
@@ -1574,9 +1576,8 @@ pwm0: pwm@0x50818000 {
clock-frequency = <200000000>;
resets = <&d0_reset TIMER_RST_CTRL SW_TIMER_RST_N>;
reset-names = "rst";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_die0_pwm0_default>;
status = "disabled";
+ numa-node-id = <0>;
};
wdt0: watchdog@0x50800000 {
@@ -1589,6 +1590,7 @@ wdt0: watchdog@0x50800000 {
interrupts = <87>;
interrupt-parent = <&plic0>;
status = "disabled";
+ numa-node-id = <0>;
};
wdt1: watchdog@0x50804000 {
@@ -1601,6 +1603,7 @@ wdt1: watchdog@0x50804000 {
interrupts = <88>;
interrupt-parent = <&plic0>;
status = "disabled";
+ numa-node-id = <0>;
};
wdt2: watchdog@0x50808000 {
@@ -1613,6 +1616,7 @@ wdt2: watchdog@0x50808000 {
interrupts = <89>;
interrupt-parent = <&plic0>;
status = "disabled";
+ numa-node-id = <0>;
};
wdt3: watchdog@0x5080c000 {
@@ -1625,6 +1629,7 @@ wdt3: watchdog@0x5080c000 {
interrupts = <90>;
interrupt-parent = <&plic0>;
status = "disabled";
+ numa-node-id = <0>;
};
timer0: timer@0x51840000 {
@@ -1633,6 +1638,7 @@ timer0: timer@0x51840000 {
#size-cells = <2>;
reg = <0x0 0x51840000 0x0 0x8000>;
perf_count = <7>;
+ numa-node-id = <0>;
interrupt-parent = <&plic0>;
interrupts = <345>;
clock-names = "pclk","timer_aclk";
@@ -1655,6 +1661,7 @@ timer1: timer@0x51848000 {
#address-cells = <2>;
#size-cells = <2>;
reg = <0x0 0x51848000 0x0 0x8000>;
+ numa-node-id = <0>;
interrupt-parent = <&plic0>;
interrupts = <346>;
clock-names = "pclk","timer_aclk";
@@ -1677,6 +1684,7 @@ timer2: timer@0x51850000 {
#address-cells = <2>;
#size-cells = <2>;
reg = <0x0 0x51850000 0x0 0x8000>;
+ numa-node-id = <0>;
interrupt-parent = <&plic0>;
interrupts = <347>;
clock-names = "pclk","timer_aclk";
@@ -1699,6 +1707,7 @@ timer3: timer@0x51858000 {
#address-cells = <2>;
#size-cells = <2>;
reg = <0x0 0x51858000 0x0 0x8000>;
+ numa-node-id = <0>;
interrupt-parent = <&plic0>;
interrupts = <348>;
clock-names = "pclk","timer_aclk","timer3_clk8";
@@ -1729,12 +1738,14 @@ die0_rtc: rtc@51818000 {
resets = <&d0_reset RTC_RST_CTRL SW_RTC_RSTN>;
reset-names = "rtcrst";
status = "disabled";
+ numa-node-id = <0>;
};
d0_i2s0: i2s0@50200000 {
compatible = "snps,i2s";
- clocks = <&d0_clock WIN2030_CLK_VO_I2S_MCLK>;
- clock-names = "mclk";
+ clocks = <&d0_clock WIN2030_CLK_VO_I2S_MCLK>,
+ <&d0_clock WIN2030_APLL_FOUT1>;
+ clock-names = "mclk", "apll";
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <0x00000000>;
@@ -1747,12 +1758,14 @@ d0_i2s0: i2s0@50200000 {
<&d0_reset VO_PHYRST_CTRL SW_VO_PRSTN>;
reset-names = "i2srst", "i2sprst", "voprst";
dma-noncoherent;
+ numa-node-id = <0>;
};
d0_i2s1: i2s1@50210000 {
compatible = "snps,i2s";
- clocks = <&d0_clock WIN2030_CLK_VO_I2S_MCLK>;
- clock-names = "mclk";
+ clocks = <&d0_clock WIN2030_CLK_VO_I2S_MCLK>,
+ <&d0_clock WIN2030_APLL_FOUT1>;
+ clock-names = "mclk", "apll";
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <0x00000000>;
@@ -1765,12 +1778,14 @@ d0_i2s1: i2s1@50210000 {
<&d0_reset VO_PHYRST_CTRL SW_VO_PRSTN>;
reset-names = "i2srst", "i2sprst", "voprst";
dma-noncoherent;
+ numa-node-id = <0>;
};
d0_i2s2: i2s2@50220000 {
compatible = "snps,i2s";
- clocks = <&d0_clock WIN2030_CLK_VO_I2S_MCLK>;
- clock-names = "mclk";
+ clocks = <&d0_clock WIN2030_CLK_VO_I2S_MCLK>,
+ <&d0_clock WIN2030_APLL_FOUT1>;
+ clock-names = "mclk", "apll";
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <0x00000000>;
@@ -1783,18 +1798,28 @@ d0_i2s2: i2s2@50220000 {
<&d0_reset VO_PHYRST_CTRL SW_VO_PRSTN>;
reset-names = "i2srst", "i2sprst", "voprst";
dma-noncoherent;
+ numa-node-id = <0>;
+ };
+
+ d0_soundcard: soundcard {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "Eswin sound card";
+ numa-node-id = <0>;
};
d0_graphcard0: graphcard0 {
compatible = "audio-graph-card";
+ numa-node-id = <0>;
};
d0_graphcard1: graphcard1 {
compatible = "audio-graph-card";
+ numa-node-id = <0>;
};
d0_graphcard2: graphcard2 {
compatible = "audio-graph-card";
+ numa-node-id = <0>;
};
video_output: display-subsystem@0 {
@@ -1807,6 +1832,7 @@ video_output: display-subsystem@0 {
dvb_widgets: dvb-subsystem {
compatible = "amlogic,dvb_widgets";
status = "disabled";
+ numa-node-id = <0>;
};
dc: display_control@502c0000 {
@@ -1819,8 +1845,12 @@ dc: display_control@502c0000 {
<&d0_clock WIN2030_CLK_VO_PIXEL_CLK>,
<&d0_clock WIN2030_CLK_VO_ACLK>,
<&d0_clock WIN2030_SPLL0_FOUT1>,
- <&d0_clock WIN2030_MUX_U_VO_ACLK_ROOT_2MUX1_GFREE>;
- clock-names = "cfg_clk", "pix_clk", "axi_clk", "spll0_fout1", "vo_mux";
+ <&d0_clock WIN2030_MUX_U_VO_ACLK_ROOT_2MUX1_GFREE>,
+ <&d0_clock WIN2030_MUX_U_VO_PIXEL_ROOT_2MUX1>,
+ <&d0_clock WIN2030_SPLL2_FOUT2>,
+ <&d0_clock WIN2030_VPLL_FOUT1>;
+ clock-names = "cfg_clk", "pix_clk", "axi_clk", "spll0_fout1", "vo_mux",
+ "pix_mux", "spll2_fout2", "vpll_fout1";
resets = <&d0_reset VO_RST_CTRL SW_VO_AXI_RSTN>,
<&d0_reset VO_RST_CTRL SW_VO_CFG_RSTN>,
<&d0_reset VO_RST_CTRL SW_VO_DC_RSTN>,
@@ -1926,6 +1956,7 @@ dc_test: dctest@502c0000 {
reg = <0x0 0x502c0000 0x0 0x10000>;
interrupt-parent = <&plic0>;
interrupts = <238>;
+ numa-node-id = <0>;
};
dw_hdmi: hdmi@502a0000 {
@@ -1985,6 +2016,7 @@ d0_usbdrd3_0: usb0@50480000 {
resets = <&d0_reset HSPDMA_RST_CTRL SW_USB0_VAUX_RSTN>;
reset-names = "vaux";
ranges;
+ numa-node-id = <0>;
status = "disabled";
d0_usbdrd_dwc3_0: dwc3@50480000 {
compatible = "snps,dwc3";
@@ -2024,6 +2056,7 @@ d0_usbdrd3_1: usb1@50490000 {
resets = <&d0_reset HSPDMA_RST_CTRL SW_USB1_VAUX_RSTN>;
reset-names = "vaux";
ranges;
+ numa-node-id = <0>;
status = "disabled";
d0_usbdrd_dwc3_1: dwc3@50490000 {
compatible = "snps,dwc3";
@@ -2090,6 +2123,7 @@ vi_top_csr: vi_common_top_csr@0x51030000 {
id = <0>;
#size-cells = <2>;
reg = <0x0 0x51030000 0x0 0x10000>;
+ numa-node-id = <0>;
};
@@ -2140,6 +2174,7 @@ dewarp: dewarp@51020000 {
<&d0_reset VI_RST_CTRL SW_VI_DWE_RSTN>;
reset-names = "axi", "cfg", "dwe";
+ operating-points-v2 = <&vi_opp_table>;
interrupt-parent = <&plic0>;
interrupts = <26 25>;
#size-cells = <2>;
@@ -2297,6 +2332,7 @@ dc_test: dctest@502c0000 {
reg = <0x0 0x502c0000 0x0 0x10000>;
interrupt-parent = <&plic0>;
interrupts = <238>;
+ numa-node-id = <0>;
};
d0_numa_sample:numa_sample@0 {
diff --git a/arch/riscv/boot/dts/eswin/eswin-win2030-die1-noc.dtsi b/arch/riscv/boot/dts/eswin/eswin-win2030-die1-noc.dtsi
index e1f621d9889e..1f4a1a693b45 100644
--- a/arch/riscv/boot/dts/eswin/eswin-win2030-die1-noc.dtsi
+++ b/arch/riscv/boot/dts/eswin/eswin-win2030-die1-noc.dtsi
@@ -29,7 +29,7 @@ d1_cfg_noc:d1_cfg_noc{
interrupt-names = "error";
interrupt-parent = <&plic1>;
errlogger,idx = <0 1 3 5>;
-
+ numa-node-id = <1>;
sideband_manager@72061000{
compatible = "eswin,win2xxx-noc-sideband-manager";
reg = <0 0x72061000 0 0x10>;
@@ -273,6 +273,7 @@ d1_llc_noc:d1_llc_noc@72081400 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ numa-node-id = <1>;
reg = <0 0x72081400 0 0x4000>;
interrupts = <441>;
interrupt-names = "error";
@@ -548,6 +549,7 @@ d1_sys_noc:d1_sys_noc@72002C00 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ numa-node-id = <1>;
reg = <0 0x72002C00 0 0x4000>;
interrupts = <431>;
interrupt-names = "error";
@@ -2220,6 +2222,7 @@ d1_media_noc:d1_media_noc@72021400 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ numa-node-id = <1>;
reg = <0 0x72021400 0 0x4000>;
interrupts = <454>;
interrupt-names = "error";
@@ -2530,6 +2533,7 @@ d1_realtime_noc:d1_realtime_noc@72041400 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ numa-node-id = <1>;
reg = <0 0x72041400 0 0x4000>;
interrupts = <448>;
interrupt-names = "error";
diff --git a/arch/riscv/boot/dts/eswin/eswin-win2030-die1-soc.dtsi b/arch/riscv/boot/dts/eswin/eswin-win2030-die1-soc.dtsi
index 7ef1be2f7a36..725e811f0825 100644
--- a/arch/riscv/boot/dts/eswin/eswin-win2030-die1-soc.dtsi
+++ b/arch/riscv/boot/dts/eswin/eswin-win2030-die1-soc.dtsi
@@ -31,77 +31,6 @@
#include <dt-bindings/thermal/thermal.h>
/ {
- d1_cpu_opp_table: opp-table1 {
- compatible = "operating-points-v2";
- opp-shared;
-
- opp-24000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_24M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-100000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_100M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-200000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_200M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-400000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_400M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-500000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_500M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-600000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_600M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-700000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_700M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-800000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_800M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-900000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_900M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-1000000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_1000M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-1200000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_1200M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-1300000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_1300M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- opp-1400000000 {
- opp-hz = /bits/ 64 <CLK_FREQ_1400M>;
- opp-microvolt = <800000>;
- clock-latency-ns = <70000>;
- };
- };
-
thermal-zones {
d1_thermal0 {
polling-delay-passive = <500>; /*ms*/
@@ -110,9 +39,10 @@ d1_thermal0 {
thermal-sensors = <&d1_pvt0>;
trips {
+ /*
d1_threshold: trip-point0 {
- temperature = <60000>; /* DC*1000 */
- hysteresis = <1000>; /* DC*1000 */
+ temperature = <60000>;
+ hysteresis = <1000>;
type = "passive";
};
d1_target: trip-point1 {
@@ -120,14 +50,16 @@ d1_target: trip-point1 {
hysteresis = <1000>;
type = "passive";
};
+ */
d1_crit: trip-point2 {
- temperature = <110000>;
+ temperature = <88000>;
hysteresis = <0>;
type = "critical";
};
};
cooling-maps {
+ /*
map0 {
trip = <&d1_target>;
contribution = <1024>;
@@ -139,14 +71,15 @@ map0 {
};
map1 {
trip = <&d1_target>;
- contribution = <1024>; /*TBD*/
+ contribution = <1024>;
cooling-device = <&d1_npu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
map2 {
trip = <&d1_target>;
- contribution = <1024>; /*TBD*/
+ contribution = <1024>;
cooling-device = <&d1_gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
+ */
};
};
};
@@ -229,6 +162,7 @@ d1_noc_wdt:noc@71810324 {
<421>, <422>, <423>, <424>, <425>,
<426>;
eswin,syscrg_csr = <&d1_sys_crg 0x100 0xffff>; //timeout paramerter
+ numa-node-id = <1>;
};
};
@@ -239,10 +173,12 @@ d1_sys_crg: sys-crg@71828000 {
d1_reset: reset-controller {
compatible = "eswin,win2030-reset";
#reset-cells = <2>;
+ numa-node-id = <1>;
};
d1_clock: clock-controller {
compatible = "eswin,win2030-clock";
#clock-cells = <1>;
+ numa-node-id = <1>;
};
};
@@ -250,6 +186,7 @@ d1_hsp_sp_csr: hsp_sp_top_csr@0x70440000 {
compatible = "eswin,win2030-hsp-sp-csr", "syscon";
#size-cells = <2>;
reg = <0x0 0x70440000 0x0 0x2000>;
+ numa-node-id = <1>;
};
smmu1: iommu@70c00000 {
@@ -441,6 +378,7 @@ noc {
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ numa-node-id = <1>;
#include "eswin-win2030-die1-noc.dtsi"
};
vdec1: video-decoder1@70100000 {
@@ -556,6 +494,7 @@ d1_mbox0: mbox@70a00000 {
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_SCPU_IRQ_BIT>;
dma-noncoherent;
+ numa-node-id = <1>;
};
/*mailbox between u84 & lpcpu*/
@@ -575,6 +514,7 @@ d1_mbox1: mbox@70a20000 {
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_LPCPU_IRQ_BIT>;
dma-noncoherent;
+ numa-node-id = <1>;
};
/*mailbox between u84 & npu_0*/
@@ -594,6 +534,7 @@ d1_mbox2: mbox@70a40000 {
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_NPU_0_IRQ_BIT>;
dma-noncoherent;
+ numa-node-id = <1>;
};
/*mailbox between u84 & npu_1*/
@@ -613,6 +554,7 @@ d1_mbox3: mbox@70a60000 {
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_NPU_1_IRQ_BIT>;
dma-noncoherent;
+ numa-node-id = <1>;
};
/*mailbox between u84 & dsp_0*/
@@ -632,6 +574,7 @@ d1_mbox4: mbox@70a80000 {
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_DSP_0_IRQ_BIT>;
dma-noncoherent;
+ numa-node-id = <1>;
};
/*mailbox between u84 & dsp_1*/
@@ -651,6 +594,7 @@ d1_mbox5: mbox@70aa0000 {
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_DSP_1_IRQ_BIT>;
dma-noncoherent;
+ numa-node-id = <1>;
};
/*mailbox between u84 & dsp_2*/
@@ -670,6 +614,7 @@ d1_mbox6: mbox@70ac0000 {
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_DSP_2_IRQ_BIT>;
dma-noncoherent;
+ numa-node-id = <1>;
};
/*mailbox between u84 & dsp_3*/
@@ -689,6 +634,7 @@ d1_mbox7: mbox@70ae0000 {
lock-bit = <ESWIN_MAILBOX_WR_LOCK_BIT_U84>;
irq-bit = <ESWIN_MAIBOX_DSP_3_IRQ_BIT>;
dma-noncoherent;
+ numa-node-id = <1>;
};
d1_ipc_scpu:ipc@1 {
@@ -742,6 +688,7 @@ d1_pvt0: pvt@0x70b00000 {
#thermal-sensor-cells = <0>;
status = "disabled";
label = "d1_pvt0";
+ numa-node-id = <1>;
};
d1_pvt1: pvt@0x72360000 {
compatible = "eswin,eswin-pvt-ddr";
@@ -756,6 +703,7 @@ d1_pvt1: pvt@0x72360000 {
interrupt-parent = <&plic1>;
status = "disabled";
label = "d1_pvt1";
+ numa-node-id = <1>;
};
d1_fan_control: fan_control@70b50000 {
@@ -773,6 +721,7 @@ d1_fan_control: fan_control@70b50000 {
pwms = <&d1_pwm0 0 100000>;
status = "disabled";
label = "d1_fan_control";
+ numa-node-id = <1>;
};
d1_i2c0: i2c@70950000 {
@@ -797,6 +746,7 @@ d1_i2c0: i2c@70950000 {
* 6 : i2c0 dma controller sel bit in sys_son dma_cfg reg(offset 0x370)
*/
dmas = <&d1_aon_dmac 24 6>, <&d1_aon_dmac 25 6>;
+ numa-node-id = <1>;
};
d1_i2c1: i2c@70960000 {
compatible = "snps,designware-i2c";
@@ -811,6 +761,7 @@ d1_i2c1: i2c@70960000 {
interrupts = <106>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_i2c2: i2c@70970000 {
compatible = "snps,designware-i2c";
@@ -825,6 +776,7 @@ d1_i2c2: i2c@70970000 {
interrupts = <107>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_i2c3: i2c@70980000 {
compatible = "snps,designware-i2c";
@@ -839,6 +791,7 @@ d1_i2c3: i2c@70980000 {
interrupts = <108>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_i2c4: i2c@70990000 {
compatible = "snps,designware-i2c";
@@ -853,6 +806,7 @@ d1_i2c4: i2c@70990000 {
interrupts = <109>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_i2c5: i2c@709a0000 {
compatible = "snps,designware-i2c";
@@ -867,6 +821,7 @@ d1_i2c5: i2c@709a0000 {
interrupts = <110>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_i2c6: i2c@709b0000 {
compatible = "snps,designware-i2c";
@@ -881,6 +836,7 @@ d1_i2c6: i2c@709b0000 {
interrupts = <111>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_i2c7: i2c@709c0000 {
compatible = "snps,designware-i2c";
@@ -895,6 +851,7 @@ d1_i2c7: i2c@709c0000 {
interrupts = <112>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_i2c8: i2c@709d0000 {
compatible = "snps,designware-i2c";
@@ -909,6 +866,7 @@ d1_i2c8: i2c@709d0000 {
interrupts = <113>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_i2c9: i2c@709e0000 {
compatible = "snps,designware-i2c";
@@ -923,6 +881,7 @@ d1_i2c9: i2c@709e0000 {
interrupts = <114>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_aon_i2c0: i2c@71830000 {
@@ -946,6 +905,7 @@ d1_aon_i2c0: i2c@71830000 {
* 0xff : no need to select to dma controller
*/
dmas = <&d1_aon_dmac 41 0xff>, <&d1_aon_dmac 42 0xff>;
+ numa-node-id = <1>;
};
d1_aon_i2c1: i2c@71838000 {
compatible = "snps,designware-i2c";
@@ -959,6 +919,7 @@ d1_aon_i2c1: i2c@71838000 {
reg = <0x0 0x71838000 0x0 0x10000>;
interrupts = <291>;
interrupt-parent = <&plic1>;
+ numa-node-id = <1>;
};
d1_npu: eswin-npu@71c00000 {
@@ -966,7 +927,7 @@ d1_npu: eswin-npu@71c00000 {
reg = <0x0 0x71c00000 0x0 0x400000>;
interrupt-parent = <&plic1>;
interrupts = <387 16>;
- spram-region = <&npu1_reserved>;
+ /* spram-region = <&npu1_reserved>;*/
#size-cells = <2>;
dma-ranges = <0x1 0x0 0x0 0xc0000000 0x1ff 0x0>;
iommus = <&smmu1 WIN2030_SID_NPU_DMA>;
@@ -977,11 +938,17 @@ d1_npu: eswin-npu@71c00000 {
clocks = <&d1_clock WIN2030_CLK_NPU_ACLK>,
<&d1_clock WIN2030_CLK_NPU_CFG_CLK>,
<&d1_clock WIN2030_CLK_NPU_CLK>,
- <&d1_clock WIN2030_CLK_NPU_E31_CLK>;
- clock-names = "aclk", "cfg_clk", "core_clk", "e31_core_clk";
+ <&d1_clock WIN2030_CLK_NPU_E31_CLK>,
+ <&d1_clock WIN2030_MUX_U_NPU_CORE_3MUX1_GFREE>,
+ <&d1_clock WIN2030_SPLL2_FOUT2>,
+ <&d1_clock WIN2030_SPLL1_FOUT1>;
+
+ clock-names = "aclk", "cfg_clk", "core_clk", "e31_core_clk", "mux_u_npu_core_3mux1_gfree", "fixed_rate_clk_spll2_fout2",
+ "fixed_rate_clk_spll1_fout1";
resets = <&d1_reset NPU_RST_CTRL SW_NPU_E31CORE_RSTN>;
reset-names = "e31_core";
+ operating-points-v2 = <&npu_opp_table>;
numa-node-id = <1>;
firmware-name = "eic7700_die1_e31_fw";
@@ -1033,6 +1000,7 @@ d1_gpu: gpu@71400000 {
interrupt-parent = <&plic1>;
interrupts = <15>;
dma-noncoherent;
+ numa-node-id = <1>;
#cooling-cells = <2>;
dynamic-power-coefficient = <0>; /*TBD*/
@@ -1061,6 +1029,7 @@ d1_pinctrl: pinctrl@0x71600080 {
compatible = "eswin,eic7x-pinctrl";
reg = <0x0 0x71600080 0x0 0x1FFF80>;
status = "disabled";
+ numa-node-id = <1>;
d1_pinctrl_pwm0_default: pwm0-default{
mux{
groups = "pwm0_group";
@@ -1104,6 +1073,7 @@ d1_gpio0: gpio@71600000 {
#size-cells = <0>;
compatible = "snps,dw-apb-gpio";
reg = <0x0 0x71600000 0x0 0x80>;
+ numa-node-id = <1>;
d1_porta: gpio-port@0 {
compatible = "snps,dw-apb-gpio-port";
@@ -1148,6 +1118,8 @@ d1_timer0: timer@0x71840000 {
#address-cells = <2>;
#size-cells = <2>;
reg = <0x0 0x71840000 0x0 0x8000>;
+ perf_count = <7>;
+ numa-node-id = <1>;
interrupt-parent = <&plic1>;
interrupts = <345>;
clock-names = "pclk","timer_aclk";
@@ -1170,6 +1142,7 @@ d1_timer1: timer@0x71848000 {
#address-cells = <2>;
#size-cells = <2>;
reg = <0x0 0x71848000 0x0 0x8000>;
+ numa-node-id = <1>;
interrupt-parent = <&plic1>;
interrupts = <346>;
clock-names = "pclk","timer_aclk";
@@ -1193,6 +1166,7 @@ d1_timer2: timer@0x71850000 {
#address-cells = <2>;
#size-cells = <2>;
reg = <0x0 0x71850000 0x0 0x8000>;
+ numa-node-id = <1>;
interrupt-parent = <&plic1>;
interrupts = <347>;
clock-names = "pclk","timer_aclk";
@@ -1215,6 +1189,7 @@ d1_timer3: timer@0x71858000 {
#address-cells = <2>;
#size-cells = <2>;
reg = <0x0 0x71858000 0x0 0x8000>;
+ numa-node-id = <1>;
interrupt-parent = <&plic1>;
interrupts = <348>;
clock-names = "pclk","timer_aclk","timer3_clk8";
@@ -1245,12 +1220,14 @@ d1_pwm0: pwm@0x70818000 {
pinctrl-names = "default";
pinctrl-0 = <&d1_pinctrl_pwm0_default &d1_pinctrl_pwm1_default &d1_pinctrl_pwm2_default>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_i2s0: i2s0@70200000 {
compatible = "snps,i2s";
- clocks = <&d1_clock WIN2030_CLK_VO_I2S_MCLK>;
- clock-names = "mclk";
+ clocks = <&d1_clock WIN2030_CLK_VO_I2S_MCLK>,
+ <&d1_clock WIN2030_APLL_FOUT1>;
+ clock-names = "mclk", "apll";
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <0x00000000>;
@@ -1263,12 +1240,14 @@ d1_i2s0: i2s0@70200000 {
<&d1_reset VO_PHYRST_CTRL SW_VO_PRSTN>;
reset-names = "i2srst", "i2sprst", "voprst";
dma-noncoherent;
+ numa-node-id = <1>;
};
d1_i2s1: i2s1@70210000 {
compatible = "snps,i2s";
- clocks = <&d1_clock WIN2030_CLK_VO_I2S_MCLK>;
- clock-names = "mclk";
+ clocks = <&d1_clock WIN2030_CLK_VO_I2S_MCLK>,
+ <&d1_clock WIN2030_APLL_FOUT1>;
+ clock-names = "mclk", "apll";
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <0x00000000>;
@@ -1281,12 +1260,14 @@ d1_i2s1: i2s1@70210000 {
<&d1_reset VO_PHYRST_CTRL SW_VO_PRSTN>;
reset-names = "i2srst", "i2sprst", "voprst";
dma-noncoherent;
+ numa-node-id = <1>;
};
d1_i2s2: i2s@70220000 {
compatible = "snps,i2s";
- clocks = <&d1_clock WIN2030_CLK_VO_I2S_MCLK>;
- clock-names = "mclk";
+ clocks = <&d1_clock WIN2030_CLK_VO_I2S_MCLK>,
+ <&d1_clock WIN2030_APLL_FOUT1>;
+ clock-names = "mclk", "apll";
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <0x00000000>;
@@ -1299,18 +1280,22 @@ d1_i2s2: i2s@70220000 {
<&d1_reset VO_PHYRST_CTRL SW_VO_PRSTN>;
reset-names = "i2srst", "i2sprst", "voprst";
dma-noncoherent;
+ numa-node-id = <1>;
};
d1_graphcard0: graphcard4 {
compatible = "audio-graph-card";
+ numa-node-id = <1>;
};
d1_graphcard1: graphcard5 {
compatible = "audio-graph-card";
+ numa-node-id = <1>;
};
d1_graphcard2: graphcard6 {
compatible = "audio-graph-card";
+ numa-node-id = <1>;
};
d1_dsp_subsys:dsp_subsys@72280400 {
@@ -1331,6 +1316,7 @@ d1_dsp_subsys:dsp_subsys@72280400 {
<&d1_reset DSP_RST_CTRL SW_DSP_DIV_RSTN_2>,
<&d1_reset DSP_RST_CTRL SW_DSP_DIV_RSTN_3>;
reset-names = "axi", "cfg", "div4", "div_0", "div_1", "div_2","div_3";
+ numa-node-id = <1>;
d1_dsp0:es_dsp@0 {
#address-cells = <1>;
#size-cells = <1>;
@@ -1460,6 +1446,7 @@ d1_rtc: rtc@71818000 {
resets = <&d1_reset RTC_RST_CTRL SW_RTC_RSTN>;
reset-names = "rtcrst";
status = "disabled";
+ numa-node-id = <1>;
};
d1_pcie: pcie@0x74000000 {
@@ -1527,11 +1514,12 @@ d1_gmac0: ethernet@70400000 {
clock-names = "app", "stmmaceth","tx";
resets = <&d1_reset HSPDMA_RST_CTRL SW_HSP_ETH0_ARSTN>;
reset-names = "ethrst";
- iommus = <&smmu1 WIN2030_SID_ETH0>;
+ //iommus = <&smmu1 WIN2030_SID_ETH0>;
tbus = <WIN2030_TBUID_ETH>;
dma-noncoherent;
eswin,hsp_sp_csr = <&d1_hsp_sp_csr 0x1030 0x100 0x108>;
eswin,syscrg_csr = <&d1_sys_crg 0x148 0x14c>;
+ eswin,dly_hsp_reg = <0x114 0x118 0x11c>;
snps,axi-config = <&d1_stmmac_axi_setup>;
d1_stmmac_axi_setup: stmmac-axi-config {
snps,blen = <0 0 0 0 16 8 4>;
@@ -1557,11 +1545,12 @@ d1_gmac1: ethernet@70410000 {
clock-names = "app", "stmmaceth","tx";
resets = <&d1_reset HSPDMA_RST_CTRL SW_HSP_ETH1_ARSTN>;
reset-names = "ethrst";
- iommus = <&smmu1 WIN2030_SID_ETH1>;
+ //iommus = <&smmu1 WIN2030_SID_ETH1>;
tbus = <WIN2030_TBUID_ETH>;
dma-noncoherent;
eswin,hsp_sp_csr = <&d1_hsp_sp_csr 0x1034 0x200 0x208>;
eswin,syscrg_csr = <&d1_sys_crg 0x148 0x14c>;
+ eswin,dly_hsp_reg = <0x214 0x218 0x21c>;
snps,axi-config = <&d1_stmmac_axi_setup_gmac1>;
d1_stmmac_axi_setup_gmac1: stmmac-axi-config {
snps,blen = <0 0 0 0 16 8 4>;
@@ -1725,6 +1714,7 @@ d1_bootspi: spi@71800000 {
spi-max-frequency = <4800000>;
reg-io-width = <4>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_video_output: display-subsystem@1 {
@@ -1744,8 +1734,12 @@ d1_dc: display_control@702c0000 {
<&d1_clock WIN2030_CLK_VO_PIXEL_CLK>,
<&d1_clock WIN2030_CLK_VO_ACLK>,
<&d1_clock WIN2030_SPLL0_FOUT1>,
- <&d1_clock WIN2030_MUX_U_VO_ACLK_ROOT_2MUX1_GFREE>;
- clock-names = "cfg_clk", "pix_clk", "axi_clk", "spll0_fout1", "vo_mux";
+ <&d1_clock WIN2030_MUX_U_VO_ACLK_ROOT_2MUX1_GFREE>,
+ <&d1_clock WIN2030_MUX_U_VO_PIXEL_ROOT_2MUX1>,
+ <&d1_clock WIN2030_SPLL2_FOUT2>,
+ <&d1_clock WIN2030_VPLL_FOUT1>;
+ clock-names = "cfg_clk", "pix_clk", "axi_clk", "spll0_fout1", "vo_mux",
+ "pix_mux", "spll2_fout2", "vpll_fout1";
resets = <&d1_reset VO_RST_CTRL SW_VO_AXI_RSTN>,
<&d1_reset VO_RST_CTRL SW_VO_CFG_RSTN>,
<&d1_reset VO_RST_CTRL SW_VO_DC_RSTN>,
@@ -1852,6 +1846,7 @@ d1_dc_test: dctest@702c0000 {
reg = <0x0 0x702c0000 0x0 0x10000>;
interrupt-parent = <&plic1>;
interrupts = <238>;
+ numa-node-id = <1>;
};
d1_dw_hdmi: hdmi@702a0000 {
@@ -1909,6 +1904,7 @@ d1_wdt0: watchdog@0x70800000 {
interrupts = <87>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_wdt1: watchdog@0x70804000 {
@@ -1921,6 +1917,7 @@ d1_wdt1: watchdog@0x70804000 {
interrupts = <88>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_wdt2: watchdog@0x70808000 {
@@ -1933,6 +1930,7 @@ d1_wdt2: watchdog@0x70808000 {
interrupts = <89>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_wdt3: watchdog@0x7080c000 {
@@ -1945,6 +1943,7 @@ d1_wdt3: watchdog@0x7080c000 {
interrupts = <90>;
interrupt-parent = <&plic1>;
status = "disabled";
+ numa-node-id = <1>;
};
d1_gc820: g2d@70140000 {
@@ -2016,6 +2015,7 @@ d1_sdhci_emmc: mmc@70450000 {
d1_graphcard: graphcard {
compatible = "audio-graph-card";
+ numa-node-id = <1>;
};
d1_usbdrd3_0: usb0@70480000 {
@@ -2031,6 +2031,7 @@ d1_usbdrd3_0: usb0@70480000 {
reset-names = "vaux";
ranges;
status = "disabled";
+ numa-node-id = <1>;
d1_usbdrd_dwc3_0: dwc3@70480000 {
compatible = "snps,dwc3";
reg = <0x0 0x70480000 0x0 0x10000>;
@@ -2070,6 +2071,7 @@ d1_usbdrd3_1: usb1@70490000 {
reset-names = "vaux";
ranges;
status = "disabled";
+ numa-node-id = <1>;
d1_usbdrd_dwc3_1: dwc3@70490000 {
compatible = "snps,dwc3";
reg = <0x0 0x70490000 0x0 0x10000>;
@@ -2134,6 +2136,7 @@ d1_vi_top_csr: vi_common_top_csr@0x71030000 {
id = <0>;
#size-cells = <2>;
reg = <0x0 0x71030000 0x0 0x10000>;
+ numa-node-id = <1>;
};
d1_isp_0: isp@0x71000000 {
@@ -2334,6 +2337,7 @@ d1_dc_test: dctest@702c0000 {
reg = <0x0 0x702c0000 0x0 0x10000>;
interrupt-parent = <&plic1>;
interrupts = <238>;
+ numa-node-id = <1>;
};
d1_numa_sample:numa_sample@1 {
diff --git a/arch/riscv/configs/eic7700_defconfig b/arch/riscv/configs/eic7700_defconfig
index cb9f99ea41b6..e85ffec6ac9f 100644
--- a/arch/riscv/configs/eic7700_defconfig
+++ b/arch/riscv/configs/eic7700_defconfig
@@ -476,6 +476,7 @@ CONFIG_THERMAL_EMULATION=y
CONFIG_WATCHDOG=y
CONFIG_DW_WATCHDOG=y
CONFIG_REGULATOR=y
+CONFIG_REGULATOR_ES5340=y
CONFIG_REGULATOR_MPQ8785=y
CONFIG_REGULATOR_PCA9450=y
CONFIG_MEDIA_SUPPORT=y
@@ -754,7 +755,8 @@ CONFIG_ARCH_ESWIN_EIC770X_SOC_FAMILY=y
CONFIG_ESWIN_DSP=m
CONFIG_ESWIN_NPU=m
CONFIG_PM_DEVFREQ=y
-CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
+CONFIG_DEVFREQ_GOV_USERSPACE=y
+CONFIG_PM_DEVFREQ_EVENT=y
CONFIG_EXTCON=y
CONFIG_MEMORY=y
CONFIG_ESWIN_BUDDY=y
@@ -763,6 +765,7 @@ CONFIG_ESWIN_RSVMEM_HEAP=y
CONFIG_ESWIN_MMZ_VB=y
CONFIG_ESWIN_DEV_DMA_BUF=y
CONFIG_ESWIN_IOMMU_RSV=y
+CONFIG_ESWIN_DMA_MEMCP=y
CONFIG_PWM=y
CONFIG_PWM_ESWIN=y
CONFIG_RESET_ESWIN_WIN2030=y
diff --git a/arch/riscv/configs/eic7702_defconfig b/arch/riscv/configs/eic7702_defconfig
index 830481fffc7e..3cecf50b5503 100644
--- a/arch/riscv/configs/eic7702_defconfig
+++ b/arch/riscv/configs/eic7702_defconfig
@@ -10,6 +10,7 @@ CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_NUMA_BALANCING=y
+# CONFIG_NUMA_BALANCING_DEFAULT_ENABLED is not set
CONFIG_CGROUPS=y
CONFIG_MEMCG=y
CONFIG_BLK_CGROUP=y
@@ -632,9 +633,9 @@ CONFIG_DRM_SIMPLE_BRIDGE=y
CONFIG_DRM_TOSHIBA_TC358768=m
CONFIG_DRM_SIMPLEDRM=m
CONFIG_DRM_ESWIN=y
+CONFIG_ESWIN_VIRTUAL_DISPLAY=y
CONFIG_ESWIN_MMU=y
CONFIG_ESWIN_DW_HDMI=y
-CONFIG_ESWIN_VIRTUAL_DISPLAY=y
CONFIG_DW_HDMI_I2S_AUDIO=y
CONFIG_DW_HDMI_CEC=y
CONFIG_DRM_IMG_VOLCANIC=m
@@ -809,6 +810,7 @@ CONFIG_CRYPTO_HMAC=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_DEV_VIRTIO=y
+CONFIG_CRYPTO_DEV_ESWIN_EIC770x=y
CONFIG_CRC_ITU_T=y
CONFIG_CRC7=y
CONFIG_XZ_DEC=y
@@ -819,7 +821,6 @@ CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15
CONFIG_CONSOLE_LOGLEVEL_QUIET=15
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7
CONFIG_DYNAMIC_DEBUG=y
-CONFIG_DEBUG_FS=y
CONFIG_DEBUG_PAGEALLOC=y
CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_DEBUG_VM=y
diff --git a/arch/riscv/configs/win2030_defconfig b/arch/riscv/configs/win2030_defconfig
index c2c4f5a620b7..25cac9c13b62 100644
--- a/arch/riscv/configs/win2030_defconfig
+++ b/arch/riscv/configs/win2030_defconfig
@@ -748,6 +748,7 @@ CONFIG_ESWIN_RSVMEM_HEAP=y
CONFIG_ESWIN_MMZ_VB=y
CONFIG_ESWIN_DEV_DMA_BUF=y
CONFIG_ESWIN_IOMMU_RSV=y
+CONFIG_ESWIN_DMA_MEMCP=y
CONFIG_PWM=y
CONFIG_PWM_ESWIN=y
CONFIG_RESET_ESWIN_WIN2030=y
diff --git a/drivers/clk/eswin/clk-win2030.c b/drivers/clk/eswin/clk-win2030.c
index ccb7dade5475..93cb6c6c8507 100755
--- a/drivers/clk/eswin/clk-win2030.c
+++ b/drivers/clk/eswin/clk-win2030.c
@@ -24,7 +24,7 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_device.h>
-
+#include <linux/clk.h>
#include <dt-bindings/reset/eswin,win2030-syscrg.h>
#include <dt-bindings/clock/win2030-clock.h>
@@ -1170,6 +1170,42 @@ static void special_div_table_init(struct clk_div_table *table, int table_size)
return;
}
+
+static int eswin_cpu_clk_init(struct platform_device *pdev)
+{
+ struct clk *cpu_clk;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ u32 default_freq;
+ int ret = 0;
+ int numa_id;
+ char name[128] = {0};
+
+ ret = of_property_read_u32(np, "cpu-default-frequency", &default_freq);
+ if (ret) {
+ dev_info(dev, "cpu-default-frequency not set\n");
+ return ret;
+ }
+ numa_id = dev_to_node(dev->parent);
+ if (numa_id < 0) {
+ sprintf(name, "%s", "clk_cpu_ext_src_core_clk_0");
+ } else {
+ sprintf(name, "d%d_%s", numa_id, "clk_cpu_ext_src_core_clk_0");
+ }
+ cpu_clk = __clk_lookup(name);
+ if (!cpu_clk) {
+ dev_err(dev, "Failed to lookup CPU clock\n");
+ return -EINVAL;
+ }
+ ret = clk_set_rate(cpu_clk, default_freq);
+ if (ret) {
+ dev_err(dev, "Failed to set CPU frequency: %d\n", ret);
+ return ret;
+ }
+ dev_info(dev, "CPU frequency set to %u Hz\n", default_freq);
+ return 0;
+}
+
static int eswin_clk_probe(struct platform_device *pdev)
{
struct eswin_clock_data *clk_data;
@@ -1207,6 +1243,9 @@ static int eswin_clk_probe(struct platform_device *pdev)
eswin_clk_register_gate(win2030_gate_clks, ARRAY_SIZE(win2030_gate_clks),
clk_data);
eswin_clk_register_clk(win2030_clks, ARRAY_SIZE(win2030_clks), clk_data);
+
+ eswin_cpu_clk_init(pdev);
+
return 0;
}
diff --git a/drivers/clocksource/timer-eswin.c b/drivers/clocksource/timer-eswin.c
index a00a686bc0ec..f7003459da04 100644
--- a/drivers/clocksource/timer-eswin.c
+++ b/drivers/clocksource/timer-eswin.c
@@ -1,8 +1,22 @@
-// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Copyright (C) ESWIN Electronics Co.Ltd
+ * ESWIN timer driver
*
- * Eswin timer driver
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: Xuxiang <xuxiang@eswincomputing.com>
*/
#include <linux/clk.h>
@@ -44,10 +58,11 @@ struct eswin_timer {
struct resource *mem;
void __iomem *mmio_base;
u32 perf_count;
+ u32 numa_id;
};
-static struct eswin_timer *perf_timer = NULL;
-static void __iomem *perf_cnt_base = NULL;
+static struct eswin_timer *perf_timer[2] = {NULL, NULL};
+static void __iomem *perf_cnt_base[2] = {NULL, NULL};
static inline u32 eswin_readl(struct eswin_timer *timer, unsigned long offs)
{
@@ -163,27 +178,56 @@ static int timer_mmap(struct file *file, struct vm_area_struct *vma)
{
struct resource *res;
u64 base;
- if (perf_timer == NULL) {
+ if (perf_timer[0] == NULL) {
return -EIO;
}
- res = perf_timer->mem;
+ res = perf_timer[0]->mem;
- base = res->start + perf_timer->perf_count * 0x14;
+ base = res->start + perf_timer[0]->perf_count * 0x14;
remap_pfn_range(vma, vma->vm_start, base >> 12,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
return 0;
}
-static struct file_operations timer_fops = {
- .owner = THIS_MODULE,
- .mmap = timer_mmap,
+static int timer_mmap_die1(struct file *file, struct vm_area_struct *vma)
+{
+ struct resource *res;
+ u64 base;
+ if (perf_timer[1] == NULL) {
+ return -EIO;
+ }
+
+ res = perf_timer[1]->mem;
+
+ base = res->start + perf_timer[1]->perf_count * 0x14;
+ remap_pfn_range(vma, vma->vm_start, base >> 12,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+ return 0;
+}
+
+static struct file_operations timer_fops[2] = {
+ {
+ .owner = THIS_MODULE,
+ .mmap = timer_mmap,
+ },
+ {
+ .owner = THIS_MODULE,
+ .mmap = timer_mmap_die1,
+ },
};
-static struct miscdevice timer_misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "perf_count",
- .fops = &timer_fops,
+static struct miscdevice timer_misc[2] = {
+ {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "perf_count",
+ .fops = &timer_fops[0],
+ },
+ {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "perf_count_die1",
+ .fops = &timer_fops[1],
+ },
};
/*
@@ -195,9 +239,9 @@ static struct miscdevice timer_misc = {
* resolution: about 42ns per cnt. So the max time that will not overflow is 42 * 0xFFFF_FFFF ~= 180s
*/
-u32 get_perf_timer_cnt(void)
+u32 get_perf_timer_cnt(u32 numa_id)
{
- return APBTMR_MAX_CNT - readl(perf_cnt_base);
+ return APBTMR_MAX_CNT - readl(perf_cnt_base[numa_id]);
}
EXPORT_SYMBOL(get_perf_timer_cnt);
@@ -208,22 +252,21 @@ static int init_timer_perf_counter(struct eswin_timer *time, u32 chan)
time->perf_count = chan;
eswin_writel(time, APBTMR_MAX_CNT, chan * APBTMR_EACH_OFS + APBTMR_N_LOAD_COUNT);
eswin_writel(time, 0x7, chan * APBTMR_EACH_OFS + APBTMR_N_CONTROL);
- ret = misc_register(&timer_misc);
- perf_timer = time;
- perf_cnt_base = perf_timer->mmio_base + chan * APBTMR_EACH_OFS + APBTMR_N_CURRENT_VALUE;
+ ret = misc_register(&timer_misc[time->numa_id]);
+ perf_timer[time->numa_id] = time;
+ perf_cnt_base[time->numa_id] = perf_timer[time->numa_id]->mmio_base + chan * APBTMR_EACH_OFS + APBTMR_N_CURRENT_VALUE;
return 0;
}
static int eswin_timer_probe(struct platform_device *pdev)
{
- struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
+ struct device_node *np = pdev->dev.of_node;
struct eswin_timer *time;
struct resource *res;
int error, irq, ret;
u32 val;
- dev_err(&pdev->dev, "eswin_timer_probe\n");
+ dev_info(&pdev->dev, "eswin_timer_probe\n");
/*add eswin timer*/
time = devm_kzalloc(&pdev->dev, sizeof(struct eswin_timer), GFP_KERNEL);
if (!time)
@@ -236,6 +279,12 @@ static int eswin_timer_probe(struct platform_device *pdev)
}
time->mem = res;
+ ret = device_property_read_u32(&pdev->dev, "numa-node-id", &time->numa_id);
+ if (0 != ret) {
+ dev_err(&pdev->dev, "failed to get numa node id\n");
+ return ret;
+ }
+
time->mmio_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(time->mmio_base))
return PTR_ERR(time->mmio_base);
@@ -262,7 +311,7 @@ static int eswin_timer_probe(struct platform_device *pdev)
init_timer_perf_counter(time, val);
}
- dev_err(&pdev->dev, "eswin_timer_probe success\n");
+ dev_info(&pdev->dev, "eswin_timer_probe success\n");
return 0;
}
diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
index 84ae708fafe7..c5634708c9a4 100644
--- a/drivers/dma-buf/dma-heap.c
+++ b/drivers/dma-buf/dma-heap.c
@@ -300,6 +300,7 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
kfree(heap);
return err_ret;
}
+EXPORT_SYMBOL(dma_heap_add);
static char *dma_heap_devnode(const struct device *dev, umode_t *mode)
{
diff --git a/drivers/gpu/drm/eswin/Makefile b/drivers/gpu/drm/eswin/Makefile
index 09cb7092e2e5..b96f169eedfe 100644
--- a/drivers/gpu/drm/eswin/Makefile
+++ b/drivers/gpu/drm/eswin/Makefile
@@ -13,7 +13,7 @@ es_drm-objs := es_dc_hw.o \
es_drm-$(CONFIG_ESWIN_VIRTUAL_DISPLAY) += es_virtual.o
es_drm-$(CONFIG_ESWIN_MMU) += es_dc_mmu.o
-es_drm-$(CONFIG_ESWIN_DW_HDMI) += eswin_dw_hdmi.o dw-hdmi.o
+es_drm-$(CONFIG_ESWIN_DW_HDMI) += es_dw_hdmi.o dw-hdmi.o
es_drm-$(CONFIG_DW_HDMI_I2S_AUDIO) += dw_hdmi_i2s_audio.o
es_drm-$(CONFIG_DW_HDMI_CEC) += dw_hdmi_cec.o
diff --git a/drivers/gpu/drm/eswin/dw-hdmi.c b/drivers/gpu/drm/eswin/dw-hdmi.c
index c301d589a508..82a3cc3f69aa 100644
--- a/drivers/gpu/drm/eswin/dw-hdmi.c
+++ b/drivers/gpu/drm/eswin/dw-hdmi.c
@@ -22,7 +22,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
- * Authors: Eswin Driver team
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#include <linux/clk.h>
#include <linux/delay.h>
@@ -2549,6 +2549,9 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi,
dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic);
}
+ dev_dbg(hdmi->dev, "mode clock:%d, hdisplay:%d, htotal:%d, vdisplay:%d, vtotal:%d\n",
+ mode->clock, mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal);
+
if (hdmi->plat_data->get_enc_out_encoding)
hdmi->hdmi_data.enc_out_encoding =
hdmi->plat_data->get_enc_out_encoding(data);
@@ -3370,7 +3373,7 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
if (mode->clock != 594000 && mode->clock != 297000 &&
mode->clock != 148500 && mode->clock != 108000 &&
mode->clock != 74250 && mode->clock != 54000 &&
- mode->clock != 27000) {
+ mode->clock != 27000 && mode->clock != 513820) {
return MODE_NOCLOCK;
}
diff --git a/drivers/gpu/drm/eswin/dw-hdmi.h b/drivers/gpu/drm/eswin/dw-hdmi.h
index dcfeaada7f1d..9304c5865aee 100644
--- a/drivers/gpu/drm/eswin/dw-hdmi.h
+++ b/drivers/gpu/drm/eswin/dw-hdmi.h
@@ -18,7 +18,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
- * Authors: Eswin Driver team
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#ifndef __DW_HDMI_H__
#define __DW_HDMI_H__
diff --git a/drivers/gpu/drm/eswin/dw_hdmi_audio.h b/drivers/gpu/drm/eswin/dw_hdmi_audio.h
index 97e0d9f02490..105f5e71babd 100644
--- a/drivers/gpu/drm/eswin/dw_hdmi_audio.h
+++ b/drivers/gpu/drm/eswin/dw_hdmi_audio.h
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
- * Authors: Eswin Driver team
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#ifndef DW_HDMI_AUDIO_H
diff --git a/drivers/gpu/drm/eswin/dw_hdmi_cec.c b/drivers/gpu/drm/eswin/dw_hdmi_cec.c
index 56553d1d4abd..90e8c973ef06 100644
--- a/drivers/gpu/drm/eswin/dw_hdmi_cec.c
+++ b/drivers/gpu/drm/eswin/dw_hdmi_cec.c
@@ -20,7 +20,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
- * Authors: Eswin Driver team
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#include <linux/interrupt.h>
diff --git a/drivers/gpu/drm/eswin/dw_hdmi_cec.h b/drivers/gpu/drm/eswin/dw_hdmi_cec.h
index 3ea45a7af644..a43854725d88 100644
--- a/drivers/gpu/drm/eswin/dw_hdmi_cec.h
+++ b/drivers/gpu/drm/eswin/dw_hdmi_cec.h
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
- * Authors: Eswin Driver team
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#ifndef DW_HDMI_CEC_H
diff --git a/drivers/gpu/drm/eswin/dw_hdmi_hdcp.c b/drivers/gpu/drm/eswin/dw_hdmi_hdcp.c
index 12933da6568b..8147044d12c9 100644
--- a/drivers/gpu/drm/eswin/dw_hdmi_hdcp.c
+++ b/drivers/gpu/drm/eswin/dw_hdmi_hdcp.c
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
- * Authors: Eswin Driver team
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#include <linux/clk.h>
#include <linux/delay.h>
diff --git a/drivers/gpu/drm/eswin/dw_hdmi_hdcp.h b/drivers/gpu/drm/eswin/dw_hdmi_hdcp.h
index 20fd169b387c..8d8c386515f4 100644
--- a/drivers/gpu/drm/eswin/dw_hdmi_hdcp.h
+++ b/drivers/gpu/drm/eswin/dw_hdmi_hdcp.h
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
- * Authors: Eswin Driver team
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#ifndef DW_HDMI_HDCP_H
diff --git a/drivers/gpu/drm/eswin/dw_hdmi_hdcp2.c b/drivers/gpu/drm/eswin/dw_hdmi_hdcp2.c
index 6c3b0af804f8..aa71bc7cce8e 100644
--- a/drivers/gpu/drm/eswin/dw_hdmi_hdcp2.c
+++ b/drivers/gpu/drm/eswin/dw_hdmi_hdcp2.c
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
- * Authors: Eswin Driver team
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/gpu/drm/eswin/dw_hdmi_i2s_audio.c b/drivers/gpu/drm/eswin/dw_hdmi_i2s_audio.c
index 80229c128eeb..33af4db6fa4c 100644
--- a/drivers/gpu/drm/eswin/dw_hdmi_i2s_audio.c
+++ b/drivers/gpu/drm/eswin/dw_hdmi_i2s_audio.c
@@ -21,7 +21,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
- * Authors: Eswin Driver team
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#include <linux/dma-mapping.h>
diff --git a/drivers/gpu/drm/eswin/es_dc.c b/drivers/gpu/drm/eswin/es_dc.c
index daf98bda2105..80538ae9aa9e 100644
--- a/drivers/gpu/drm/eswin/es_dc.c
+++ b/drivers/gpu/drm/eswin/es_dc.c
@@ -345,6 +345,7 @@ static void es_dc_enable(struct device *dev, struct drm_crtc *crtc)
struct es_crtc_state *crtc_state = to_es_crtc_state(crtc->state);
struct drm_display_mode *mode = &crtc->state->adjusted_mode;
struct dc_hw_display display;
+ int ret;
display.bus_format = crtc_state->output_fmt;
display.h_active = mode->hdisplay;
@@ -373,7 +374,20 @@ static void es_dc_enable(struct device *dev, struct drm_crtc *crtc)
es_dc_clk_configs(dev, true);
if (dc->pix_clk_rate != mode->clock) {
- clk_set_rate(dc->pix_clk, mode->clock * 1000);
+ if (mode->clock == 513820) {
+ ret = clk_set_parent(dc->pix_mux, dc->spll2_fout2);
+ if (ret < 0) {
+ dev_err(dev, "failed to set pix mux parent spll2, err:%d\n", ret);
+ }
+ /* set mode (2880*1800@90hz) clock to 520M */
+ clk_set_rate(dc->pix_clk, 520000000);
+ } else {
+ ret = clk_set_parent(dc->pix_mux, dc->vpll_fout1);
+ if (ret < 0) {
+ dev_err(dev, "failed to set pix mux parent vpll, err:%d\n", ret);
+ }
+ clk_set_rate(dc->pix_clk, mode->clock * 1000);
+ }
dc->pix_clk_rate = mode->clock;
}
@@ -412,6 +426,10 @@ static bool es_dc_mode_fixup(struct device *dev,
struct es_dc *dc = dev_get_drvdata(dev);
long clk_rate;
+ dev_dbg(dev, "adjust mode clock:%d\n", adjusted_mode->clock);
+ if (adjusted_mode->clock == 513820)
+ return true;
+
if (dc->pix_clk) {
clk_rate = clk_round_rate(dc->pix_clk,
adjusted_mode->clock * 1000);
@@ -1083,6 +1101,24 @@ static int dc_probe(struct platform_device *pdev)
return PTR_ERR(dc->axi_clk);
}
+ dc->pix_mux = devm_clk_get_optional(dev, "pix_mux");
+ if (IS_ERR(dc->pix_mux)) {
+ dev_err(dev, "failed to get pix mux clk source\n");
+ return PTR_ERR(dc->pix_mux);
+ }
+
+ dc->spll2_fout2 = devm_clk_get_optional(dev, "spll2_fout2");
+ if (IS_ERR(dc->spll2_fout2)) {
+ dev_err(dev, "failed to get spll2 fout2 clk source\n");
+ return PTR_ERR(dc->spll2_fout2);
+ }
+
+ dc->vpll_fout1 = devm_clk_get_optional(dev, "vpll_fout1");
+ if (IS_ERR(dc->vpll_fout1)) {
+ dev_err(dev, "failed to get vpll fout1 clk source\n");
+ return PTR_ERR(dc->vpll_fout1);
+ }
+
dc->vo_arst = devm_reset_control_get_optional(dev, "vo_arst");
if (IS_ERR_OR_NULL(dc->vo_arst)) {
dev_err(dev, "Failed to vo_arst handle\n");
diff --git a/drivers/gpu/drm/eswin/es_dc.h b/drivers/gpu/drm/eswin/es_dc.h
index 89b203eebc98..63c5c8d79aa4 100644
--- a/drivers/gpu/drm/eswin/es_dc.h
+++ b/drivers/gpu/drm/eswin/es_dc.h
@@ -47,6 +47,9 @@ struct es_dc {
struct clk *cfg_clk;
struct clk *pix_clk;
struct clk *axi_clk;
+ struct clk *pix_mux;
+ struct clk *spll2_fout2;
+ struct clk *vpll_fout1;
unsigned int pix_clk_rate; /* in KHz */
struct reset_control *vo_arst;
diff --git a/drivers/gpu/drm/eswin/es_drv.c b/drivers/gpu/drm/eswin/es_drv.c
index 1c588106e39c..d29c3572857c 100644
--- a/drivers/gpu/drm/eswin/es_drv.c
+++ b/drivers/gpu/drm/eswin/es_drv.c
@@ -25,6 +25,9 @@
#include <linux/version.h>
#include <linux/of_address.h>
#include <linux/dma-map-ops.h>
+#include <linux/of.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
@@ -367,10 +370,16 @@ static int es_drm_of_component_probe(struct device *dev,
int i;
bool found = false;
bool matched = false;
+ int ret;
if (!dev->of_node)
return -EINVAL;
+ ret = of_reserved_mem_device_init(dev);
+ if (ret) {
+ dev_info(dev, "No memory-region specified, use system cma, ret:%d\n", ret);
+ }
+
/*
* Bind the crtc's ports first, so that drm_of_find_possible_crtcs()
* called from encoder's .bind callbacks works as expected
@@ -465,7 +474,7 @@ static int es_drm_of_component_probe(struct device *dev,
compare_of, remote);
matched = false;
dev_dbg(dev, "matched: %pOF, remote->name:%s\n",
- remote, remote->name);
+ remote, remote->name);
}
of_node_put(remote);
diff --git a/drivers/gpu/drm/eswin/eswin_dw_hdmi.c b/drivers/gpu/drm/eswin/es_dw_hdmi.c
similarity index 99%
rename from drivers/gpu/drm/eswin/eswin_dw_hdmi.c
rename to drivers/gpu/drm/eswin/es_dw_hdmi.c
index 19f7cccdca33..84f75833aa62 100644
--- a/drivers/gpu/drm/eswin/eswin_dw_hdmi.c
+++ b/drivers/gpu/drm/eswin/es_dw_hdmi.c
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
- * Authors: Eswin Driver team
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#include <linux/component.h>
@@ -151,6 +151,14 @@ static const struct dw_hdmi_mpll_config eswin_mpll_cfg[] = {
{ 0x2648, 0x020f },
},
},
+ {
+ 513820000,
+ {
+ { 0x0640, 0x0005 },
+ { 0x1658, 0x0019 },
+ { 0x2648, 0x000f },
+ },
+ },
{
594000000,
{
@@ -195,6 +203,10 @@ static const struct dw_hdmi_curr_ctrl eswin_cur_ctr[] = {
297000000,
{ 0x3041, 0x3182, 0x3100 },
},
+ {
+ 513820000,
+ { 0x3080, 0x31c0, 0x3100 },
+ },
{
594000000,
{ 0x3080, 0x31c0, 0x3100 },
@@ -209,7 +221,7 @@ static struct dw_hdmi_phy_config eswin_phy_config[] = {
/*pixelclk symbol term vlev*/
{ 165000000, 0x8088, 0x0007, 0x0180 },
{ 297000000, 0x80c8, 0x0004, 0x0180 },
- { 594000000, 0x80f8, 0x0000, 0x0180 },
+ { 594000000, 0x80f3, 0x0000, 0x0180 },
{ ~0UL, 0x0000, 0x0000, 0x0000 }
};
diff --git a/drivers/interconnect/eswin/noc.c b/drivers/interconnect/eswin/noc.c
index 2bcbe3f48f59..cc232396f842 100644
--- a/drivers/interconnect/eswin/noc.c
+++ b/drivers/interconnect/eswin/noc.c
@@ -515,7 +515,7 @@ static int win2030_noc_get_error(struct win2030_noc_device *noc_device)
struct win2030_noc_error *noc_err;
unsigned long flags;
int i;
- char buf[1024] = {'\0'};
+ char buf[2048] = {'\0'};
struct device *mydev = noc_device->dev;
diff --git a/drivers/memory/eswin/Kconfig b/drivers/memory/eswin/Kconfig
index 3078936326e4..c187f1c0ac0a 100644
--- a/drivers/memory/eswin/Kconfig
+++ b/drivers/memory/eswin/Kconfig
@@ -31,5 +31,6 @@ source "drivers/memory/eswin/es_rsvmem_heap/Kconfig"
source "drivers/memory/eswin/es_mmz_vb/Kconfig"
source "drivers/memory/eswin/es_dev_buf/Kconfig"
source "drivers/memory/eswin/es_iommu_rsv/Kconfig"
+source "drivers/memory/eswin/es_dma_memcp/Kconfig"
endif
diff --git a/drivers/memory/eswin/Makefile b/drivers/memory/eswin/Makefile
index c07fadc64d44..e6e57575ccb8 100644
--- a/drivers/memory/eswin/Makefile
+++ b/drivers/memory/eswin/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_ESWIN_RSVMEM_HEAP) += es_rsvmem_heap/
obj-$(CONFIG_ESWIN_RSVMEM_HEAP) += es_mmz_vb/
obj-$(CONFIG_ESWIN_DEV_DMA_BUF) += es_dev_buf/
obj-$(CONFIG_ESWIN_IOMMU_RSV) += es_iommu_rsv/
+obj-$(CONFIG_ESWIN_DMA_MEMCP) += es_dma_memcp/
ES_MEM_HEADER := drivers/memory/eswin/
diff --git a/drivers/memory/eswin/codacache/llc_spram.c b/drivers/memory/eswin/codacache/llc_spram.c
index ed71d83c3060..8ef878c0abef 100644
--- a/drivers/memory/eswin/codacache/llc_spram.c
+++ b/drivers/memory/eswin/codacache/llc_spram.c
@@ -42,6 +42,7 @@
#include <linux/eswin_npu.h>
#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
#include "llc_spram.h"
#define HAVE_LLC_HARDWARE 1
@@ -102,6 +103,8 @@ struct spram_dev {
struct reset_control *rstc_cfg;
struct reset_control *rstc_core;
struct reset_control *rstc_llc;
+ struct regulator *npu_regulator;
+ u8 is_low_freq;
};
#define dma_buf_map iosys_map
@@ -671,9 +674,8 @@ static int llc_clk_init(struct platform_device *pdev)
return 0;
}
-static int llc_clk_enable(struct platform_device *pdev)
+static int llc_clk_enable(struct spram_dev *spram)
{
- struct spram_dev *spram = platform_get_drvdata(pdev);
int ret = 0;
if (spram == NULL)
@@ -682,29 +684,41 @@ static int llc_clk_enable(struct platform_device *pdev)
/*enable clk*/
ret = clk_prepare_enable(spram->aclk);
if (ret) {
- dev_err(&pdev->dev, "failed to enable aclk: %d\n", ret);
+ dev_err(spram->dev, "failed to enable aclk: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(spram->cfg_clk);
if (ret) {
- dev_err(&pdev->dev, "failed to enable cfg_clk: %d\n", ret);
+ dev_err(spram->dev, "failed to enable cfg_clk: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(spram->llc_clk);
if (ret) {
- dev_err(&pdev->dev, "failed to enable llc_clk: %d\n", ret);
+ dev_err(spram->dev, "failed to enable llc_clk: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(spram->core_clk);
if (ret) {
- dev_err(&pdev->dev, "failed to enable core_clk: %d\n", ret);
+ dev_err(spram->dev, "failed to enable core_clk: %d\n", ret);
return ret;
}
return 0;
}
+static int llc_clk_disable(struct spram_dev *spram)
+{
+ if (spram == NULL)
+ return -EINVAL;
+ clk_disable_unprepare(spram->aclk);
+ clk_disable_unprepare(spram->cfg_clk);
+ clk_disable_unprepare(spram->llc_clk);
+ clk_disable_unprepare(spram->core_clk);
+
+ return 0;
+}
+
static int llc_rst_init(struct platform_device *pdev)
{
struct spram_dev *spram = platform_get_drvdata(pdev);
@@ -739,56 +753,42 @@ static int llc_rst_init(struct platform_device *pdev)
return 0;
}
-static int llc_clk_set_parent(struct platform_device *pdev, u8 *is_low_freq)
+static int llc_clk_set_parent(struct platform_device *pdev)
{
int ret;
struct spram_dev *spram = platform_get_drvdata(pdev);
-
struct device_node *np;
- struct regulator *npu_regulator;
struct device *dev = &pdev->dev;
+ spram->is_low_freq = 0;
if (spram == NULL)
return -EINVAL;
np = of_node_get(dev->of_node);
- npu_regulator = devm_regulator_get_exclusive(dev, "npu");
-
- if ((NULL == npu_regulator) || (IS_ERR(npu_regulator)))
+ spram->npu_regulator = devm_regulator_get(dev, "npu");
+ ret = regulator_get_voltage(spram->npu_regulator);
+ if (ret < 0)
{
dev_warn(dev, "failed to get npu regulator,the npu freq will set to 1G\n");
- *is_low_freq = 1;
- //return -ENODEV;
+ spram->is_low_freq = 1;
}
else
{
- *is_low_freq = (of_property_read_bool(np, "apply_npu_1G_freq"));
+ spram->is_low_freq = (of_property_read_bool(np, "apply_npu_1G_freq"));
dev_dbg(dev, "success to get npu regulator,apply_npu_1G_freq:%d\n",
- *is_low_freq);
- }
-
- if (0 == *is_low_freq)
- {
- ret = regulator_set_voltage(npu_regulator, NPU_1P5G_VOLTAGE, NPU_1P5G_VOLTAGE);
- dev_dbg(dev,"name:%s,volt:%d,ret:%d\n",pdev->name,NPU_1P5G_VOLTAGE,ret);
- if(0 != ret)
+ spram->is_low_freq);
+ ret = regulator_enable(spram->npu_regulator);
+ if (ret < 0)
{
- dev_err(dev, "set volt:%duV ret:%d\n", NPU_1P5G_VOLTAGE,ret);
- return -EINVAL;
+ return ret;
}
- /* devm_regulator_put(npu_regulator); */
- mdelay(10);
+ }
+ if (0 == spram->is_low_freq)
+ {
ret = clk_set_parent(spram->mux_u_npu_core_3mux1_gfree,
spram->fixed_rate_clk_spll1_fout1);
}
else
{
- if (((NULL != npu_regulator)) && (!IS_ERR(npu_regulator)))
- {
- regulator_set_voltage(npu_regulator, NPU_DEFAULT_VOLTAGE, NPU_DEFAULT_VOLTAGE);
- dev_dbg(dev,"name:%s,volt:%d,ret:%d\n", pdev->name,NPU_DEFAULT_VOLTAGE,ret);
- /* devm_regulator_put(npu_regulator); */
- mdelay(10);
- }
ret = clk_set_parent(spram->mux_u_npu_core_3mux1_gfree,
spram->fixed_rate_clk_spll2_fout2);
}
@@ -798,10 +798,9 @@ static int llc_clk_set_parent(struct platform_device *pdev, u8 *is_low_freq)
ret);
return ret;
}
-
return 0;
}
-static int llc_clk_set_frq(struct platform_device *pdev, u8 is_low_freq)
+static int llc_clk_set_frq(struct platform_device *pdev)
{
int ret;
unsigned long rate = 0;
@@ -818,7 +817,7 @@ static int llc_clk_set_frq(struct platform_device *pdev, u8 is_low_freq)
return ret;
}
- if (0 == is_low_freq)
+ if (0 == spram->is_low_freq)
{
rate = clk_round_rate(spram->llc_clk, NPU_LLC_CLK_1P5G_RATE);
ret = clk_set_rate(spram->llc_clk, rate);
@@ -858,10 +857,9 @@ static int llc_clk_set_frq(struct platform_device *pdev, u8 is_low_freq)
return 0;
}
-static int llc_rst_deassert(struct platform_device *pdev)
+static int llc_rst_deassert(struct spram_dev *spram)
{
int ret = 0;
- struct spram_dev *spram = platform_get_drvdata(pdev);
if (spram == NULL)
return -EINVAL;
@@ -885,6 +883,25 @@ static int llc_rst_deassert(struct platform_device *pdev)
return 0;
}
+
+static int llc_rst_assert(struct spram_dev *spram)
+{
+ int ret = 0;
+
+ if (spram == NULL)
+ return -EINVAL;
+ ret = reset_control_assert(spram->rstc_axi);
+ WARN_ON(0 != ret);
+ ret = reset_control_assert(spram->rstc_core);
+ WARN_ON(0 != ret);
+ ret = reset_control_assert(spram->rstc_llc);
+ WARN_ON(0 != ret);
+ ret = reset_control_assert(spram->rstc_cfg);
+ WARN_ON(0 != ret);
+
+ return 0;
+}
+
static int llc_clk_rst_print(struct platform_device *pdev)
{
uint32_t regval[5];
@@ -944,8 +961,9 @@ static int llc_clk_rst_print(struct platform_device *pdev)
static int llc_clk_rst_init(struct platform_device *pdev)
{
int ret = 0;
- u8 is_low_freq = 0;
+ struct spram_dev *spram = platform_get_drvdata(pdev);
+ spram->is_low_freq = 0;
dev_dbg(&pdev->dev, "---%s\n", __func__);
ret = llc_clk_init(pdev);
@@ -954,7 +972,7 @@ static int llc_clk_rst_init(struct platform_device *pdev)
return ret;
}
- ret = llc_clk_set_parent(pdev, &is_low_freq);
+ ret = llc_clk_set_parent(pdev);
if(ret != 0){
dev_err(&pdev->dev, "llc_clk_set_parent error: %d\n", ret);
return ret;
@@ -966,19 +984,19 @@ static int llc_clk_rst_init(struct platform_device *pdev)
return ret;
}
- ret = llc_clk_set_frq(pdev, is_low_freq);
+ ret = llc_clk_set_frq(pdev);
if(ret != 0){
dev_err(&pdev->dev, "llc_clk_set_frq error: %d\n", ret);
return ret;
}
- ret = llc_clk_enable(pdev);
+ ret = llc_clk_enable(spram);
if(ret != 0){
dev_err(&pdev->dev, "llc_clk_enable error: %d\n", ret);
return ret;
}
- llc_rst_deassert(pdev);
+ llc_rst_deassert(spram);
llc_clk_rst_print(pdev);
dev_dbg(&pdev->dev, "%s done successfully!\n", __func__);
@@ -1438,6 +1456,101 @@ static int spram_contiguous_alloc(struct spram_dev *spram, size_t len, struct sg
}
#endif
+#ifdef CONFIG_PM
+static int __maybe_unused llc_suspend(struct device *dev)
+{
+
+ struct spram_dev *spram = dev_get_drvdata(dev);
+
+ llc_rst_assert(spram);
+ if (!pm_runtime_status_suspended(dev))
+ {
+ llc_clk_disable(spram);
+ }
+ if ((NULL != spram->npu_regulator) && (!IS_ERR(spram->npu_regulator)))
+ {
+ regulator_disable(spram->npu_regulator);
+ }
+
+ return 0;
+}
+
+static int __maybe_unused llc_resume(struct device *dev)
+{
+ int ret = 0;
+ int is_enable = 0;
+ struct spram_dev *spram = dev_get_drvdata(dev);
+
+ if ((NULL != spram->npu_regulator) && (!IS_ERR(spram->npu_regulator)))
+ {
+ is_enable = regulator_is_enabled(spram->npu_regulator);
+ if(0 == is_enable)
+ {
+ mdelay(20);
+ }
+ ret = regulator_enable(spram->npu_regulator);
+ if (ret < 0)
+ {
+ dev_err(spram->dev, "regulator_enable error: %d\n", ret);
+ return ret;
+ }
+ if(0 == is_enable)
+ {
+ mdelay(20);
+ }
+ }
+
+ ret = llc_clk_enable(spram);
+ if(ret != 0){
+ dev_err(spram->dev, "llc_clk_enable error: %d\n", ret);
+ return ret;
+ }
+ ret = llc_rst_deassert(spram);
+ if (ret)
+ return ret;
+
+ ret = llc_spram_init(spram);
+ if (ret) {
+ return ret;
+ }
+
+ return ret;
+}
+
+
+static int __maybe_unused llc_runtime_suspend(struct device *dev)
+{
+ struct spram_dev *spram = dev_get_drvdata(dev);
+
+ llc_clk_disable(spram);
+
+ return 0;
+}
+
+static int __maybe_unused llc_runtime_resume(struct device *dev)
+{
+ struct spram_dev *spram = dev_get_drvdata(dev);
+ int ret = 0;
+
+ ret = llc_clk_enable(spram);
+ if(ret != 0){
+ dev_err(spram->dev, "llc_clk_enable error: %d\n", ret);
+ }
+
+ return ret;
+}
+
+static const struct dev_pm_ops llc_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(llc_suspend, llc_resume)
+ SET_RUNTIME_PM_OPS(llc_runtime_suspend,
+ llc_runtime_resume, NULL)
+};
+
+#define DEV_PM_OPS (&llc_dev_pm_ops)
+#else
+#define DEV_PM_OPS NULL
+#endif /* CONFIG_PM */
+
static struct dma_buf *spram_heap_allocate(struct dma_heap *heap,
unsigned long len,
unsigned long fd_flags,
@@ -1555,6 +1668,51 @@ static int __add_spram_heap(struct spram_dev *spram, void *data)
return 0;
}
+static ssize_t npu_regulator_show(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct spram_dev *spram = dev_get_drvdata(device);
+
+ return sprintf(buf, "%d\n",regulator_is_enabled(spram->npu_regulator));
+
+}
+
+static ssize_t npu_regulator_store(struct device *device,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ int ret = 0;
+ struct spram_dev *spram = dev_get_drvdata(device);
+
+ if (!strncmp(buf, "0", 1))
+ {
+ regulator_disable(spram->npu_regulator);
+ }
+ else
+ {
+ ret = regulator_enable(spram->npu_regulator);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(npu_regulator);
+
+static struct attribute *llc_attrs[] = {
+ &dev_attr_npu_regulator.attr,
+ NULL,
+};
+
+static struct attribute_group llc_attr_group = {
+ .name = NULL, /* we want them in the same directory */
+ .attrs = llc_attrs,
+};
+
static int llc_probe(struct platform_device *pdev)
{
struct spram_dev *spram;
@@ -1651,7 +1809,9 @@ static int llc_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "%s Done!\n", __func__);
pdevs[spram->nid] = pdev;
-
+ ret = sysfs_create_group(&pdev->dev.kobj, &llc_attr_group);
+ if (ret)
+ dev_err(&pdev->dev, "failed to create sysfs group: %d\n", ret);
return 0;
}
@@ -1666,6 +1826,7 @@ static struct platform_driver llc_driver = {
.driver = {
.name = DEVICE_NAME,
.of_match_table = llc_dt_ids,
+ .pm = DEV_PM_OPS,
},
.probe = llc_probe,
};
@@ -1674,3 +1835,4 @@ builtin_platform_driver(llc_driver);
MODULE_DESCRIPTION("ESWIN LLC driver");
MODULE_AUTHOR("Lin MIn <linmin@eswincomputing.com>");
MODULE_LICENSE("GPL");
+
diff --git a/drivers/memory/eswin/es_dma_memcp/Kconfig b/drivers/memory/eswin/es_dma_memcp/Kconfig
new file mode 100644
index 000000000000..deff4abf37de
--- /dev/null
+++ b/drivers/memory/eswin/es_dma_memcp/Kconfig
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ESWIN_DMA_MEMCP
+ tristate "ESWIN DMA memory copy"
+ help
+ ESWIN DMA memory copy device.
diff --git a/drivers/memory/eswin/es_dma_memcp/Makefile b/drivers/memory/eswin/es_dma_memcp/Makefile
new file mode 100644
index 000000000000..615375e6b476
--- /dev/null
+++ b/drivers/memory/eswin/es_dma_memcp/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ESWIN_DMA_MEMCP) += es_dma_memcp.o
diff --git a/drivers/memory/eswin/es_dma_memcp/es_dma_memcp.c b/drivers/memory/eswin/es_dma_memcp/es_dma_memcp.c
new file mode 100644
index 000000000000..7d0772bf03cd
--- /dev/null
+++ b/drivers/memory/eswin/es_dma_memcp/es_dma_memcp.c
@@ -0,0 +1,604 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESWIN DMA MEMCP Driver
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: Zonglin Geng <gengzonglin@eswincomputing.com>
+ * Yuyang Cong <congyuyang@eswincomputing.com>
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <linux/version.h>
+#include <linux/dmaengine.h>
+#include <linux/uaccess.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-buf.h>
+#include <linux/workqueue.h>
+#include <uapi/linux/dma_memcp.h>
+
+#define DRIVER_NAME "es_memcp"
+
+#define MAX_NUM_USED_DMA_CH (4)
+
+static struct device *esw_memcp_dev;
+
+struct esw_memcp_dma_buf_info {
+ struct dma_buf *dma_buf;
+ int mem_nid;
+ struct dma_buf_attachment *attach;
+ struct sg_table *sgt;
+};
+
+struct cmdq {
+ struct workqueue_struct *wq;
+ struct mutex lock;
+ atomic_t total_tasks;
+ atomic_t completed_tasks;
+};
+
+struct esw_cmdq_task {
+ struct cmdq *cmdq;
+ struct esw_memcp_f2f_cmd f2f_cmd;
+ struct esw_memcp_dma_buf_info src_buf;
+ struct esw_memcp_dma_buf_info dst_buf;
+ struct work_struct work;
+ struct dma_chan *dma_ch; /* pointer to the dma channel. */
+ struct completion dma_finished;
+};
+
+#ifdef CONFIG_NUMA
+static int memcp_attach_dma_buf(struct device *dma_dev, struct esw_memcp_dma_buf_info *buf_info);
+static int memcp_detach_dma_buf(struct dma_buf_attachment *attach, struct sg_table *sgt);
+#define PAGE_IN_SPRAM_DIE0(page) ((page_to_phys(page)>=0x59000000) && (page_to_phys(page)<0x59400000))
+#define PAGE_IN_SPRAM_DIE1(page) ((page_to_phys(page)>=0x79000000) && (page_to_phys(page)<0x79400000))
+static int esw_memcp_get_mem_nid(struct esw_memcp_dma_buf_info *buf_info)
+{
+ int ret = 0;
+ struct page *page = NULL;
+ int nid = -1;
+
+ ret = memcp_attach_dma_buf(esw_memcp_dev, buf_info);
+ if(ret) {
+ pr_err("Failed to attach DMA buffer, ret=%d\n", ret);
+ return ret;
+ }
+
+ page = sg_page(buf_info->sgt->sgl);
+ if (unlikely(PAGE_IN_SPRAM_DIE0(page))) {
+ nid = 0;
+ }
+ else if(unlikely(PAGE_IN_SPRAM_DIE1(page))) {
+ nid = 1;
+ }
+ else {
+ nid = page_to_nid(page);
+ }
+
+ ret = memcp_detach_dma_buf(buf_info->attach, buf_info->sgt);
+ if(ret) {
+ pr_err("Failed to detach DMA buffer, , ret=%d\n", ret);
+ return ret;
+ }
+
+ buf_info->mem_nid = nid;
+
+ return ret;
+}
+#else
+static int esw_memcp_get_mem_nid(struct esw_memcp_dma_buf_info *buf_info)
+{
+ buf_info->mem_nid = 0;
+ return 0;
+}
+#endif
+
+static bool filter(struct dma_chan *chan, void *param)
+{
+#ifdef CONFIG_NUMA
+ if((*(int *)param) == 2)
+ return true;
+ else
+ return (*(int *)param) == dev_to_node(chan->device->dev);
+#else
+ return true;
+#endif
+}
+
+
+int esw_memcp_alloc_dma(struct esw_cmdq_task *task)
+{
+ int ret = 0;
+ dma_cap_mask_t mask;
+ struct dma_chan *dma_ch = NULL;
+
+ ret = esw_memcp_get_mem_nid(&task->src_buf);
+ if(ret) {
+ return ret;
+ }
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_MEMCPY, mask);
+
+ dma_ch = dma_request_channel(mask, filter, &task->src_buf.mem_nid);
+ if (IS_ERR(dma_ch)) {
+ pr_warn("dma request channel failed, Try using any of them.\n");
+ dma_ch = dma_request_channel(mask, NULL, NULL);
+ }
+
+ if (IS_ERR(dma_ch)) {
+ pr_err("dma request channel failed\n");
+ return -ENODEV;
+ }
+
+ task->dma_ch = dma_ch;
+ return 0;
+}
+
+static int memcp_attach_dma_buf(struct device *dma_dev, struct esw_memcp_dma_buf_info *buf_info)
+{
+ int ret = 0;
+ struct dma_buf *dma_buf;
+ struct dma_buf_attachment *attach;
+ struct sg_table *sgt;
+
+ if (!buf_info || !dma_dev) {
+ pr_err("Invalid parameters: buf_info or dma_dev is NULL\n");
+ return -EINVAL;
+ }
+
+ dma_buf = buf_info->dma_buf;
+ if (IS_ERR(dma_buf)) {
+ return PTR_ERR(dma_buf);
+ }
+ /* Ref + 1 */
+ attach = dma_buf_attach(dma_buf, dma_dev);
+ if (IS_ERR(attach)) {
+ ret = PTR_ERR(attach);
+ return ret;
+ }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
+ sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
+#else
+ sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+#endif
+ if (IS_ERR(sgt)) {
+ ret = PTR_ERR(sgt);
+ dma_buf_detach(dma_buf, attach);
+ return ret;
+ }
+#ifdef DMA_MEMCP_DEBUG_EN
+ struct scatterlist *sg = NULL;
+ u64 addr;
+ int len;
+ int i = 0;
+ for_each_sgtable_dma_sg(sgt, sg, i) {
+ addr = sg_dma_address(sg);
+ len = sg_dma_len(sg);
+ }
+#endif
+
+ buf_info->attach = attach;
+ buf_info->sgt = sgt;
+ return ret;
+}
+
+static int memcp_detach_dma_buf(struct dma_buf_attachment *attach, struct sg_table *sgt)
+{
+ int ret = 0;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
+ dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
+#else
+ dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+#endif
+ /* detach attach->dma_buf*/
+ dma_buf_detach(attach->dmabuf, attach);
+ return ret;
+}
+
+static int memcp_detach_dma_buf_check(struct esw_memcp_dma_buf_info *buf_info)
+{
+ int ret = 0;
+ if(buf_info->attach) {
+ ret = memcp_detach_dma_buf(buf_info->attach, buf_info->sgt);
+ buf_info->attach = NULL;
+ }
+ return ret;
+}
+
+static int esw_memcp_release_cmdq_task(struct esw_cmdq_task *cmdq_task)
+{
+ memcp_detach_dma_buf_check(&cmdq_task->src_buf);
+ memcp_detach_dma_buf_check(&cmdq_task->dst_buf);
+
+ if (cmdq_task->src_buf.dma_buf) {
+ dma_buf_put(cmdq_task->src_buf.dma_buf);
+ cmdq_task->src_buf.dma_buf = NULL;
+ }
+ if (cmdq_task->dst_buf.dma_buf) {
+ dma_buf_put(cmdq_task->dst_buf.dma_buf);
+ cmdq_task->dst_buf.dma_buf = NULL;
+ }
+
+ if (cmdq_task->dma_ch) {
+ dma_release_channel(cmdq_task->dma_ch);
+ cmdq_task->dma_ch = NULL;
+ }
+
+ kfree(cmdq_task);
+ return 0;
+}
+
+
+static void esw_memcp_complete_func(void *cb_param)
+{
+ struct esw_cmdq_task *cmdq_task = (struct esw_cmdq_task *)cb_param;
+
+ complete(&cmdq_task->dma_finished);
+}
+
+static int esw_memcp_start_dma_f2f_trans(struct esw_cmdq_task *cmdq_task)
+{
+ int ret = 0;
+ struct esw_memcp_f2f_cmd *f2f_cmd;
+ struct dma_buf_attachment *attach;
+ struct sg_table *sgt;
+ struct dma_buf *dma_buf;
+ struct dma_chan *dma_ch;
+ struct device *dma_dev;
+ enum dma_ctrl_flags flags;
+ dma_cookie_t cookie; //used for judge whether trans has been completed.
+ struct dma_async_tx_descriptor *tx = NULL;
+ dma_addr_t src_buf_addr, dst_buf_addr;
+ size_t src_size, dst_size;
+
+ ret = esw_memcp_alloc_dma(cmdq_task);
+ if(ret) {
+ goto release_cmdq_task;
+ }
+
+ f2f_cmd = &cmdq_task->f2f_cmd;
+ dma_ch = cmdq_task->dma_ch;
+ dma_dev = dmaengine_get_dma_device(dma_ch);
+
+ ret = memcp_attach_dma_buf(dma_dev, &cmdq_task->src_buf);
+ if(ret) {
+ goto release_cmdq_task;
+ }
+ attach = cmdq_task->src_buf.attach;
+ sgt = cmdq_task->src_buf.sgt;
+ src_buf_addr = sg_dma_address(sgt->sgl) + f2f_cmd->src_offset;
+ dma_buf = attach->dmabuf;
+ src_size = dma_buf->size;
+
+ ret = memcp_attach_dma_buf(dma_dev, &cmdq_task->dst_buf);
+ if(ret) {
+ goto release_cmdq_task;
+ }
+ attach = cmdq_task->dst_buf.attach;
+ sgt = cmdq_task->dst_buf.sgt;
+ dst_buf_addr = sg_dma_address(sgt->sgl) + f2f_cmd->dst_offset;
+ dma_buf = attach->dmabuf;
+ dst_size = dma_buf->size;
+
+ init_completion(&cmdq_task->dma_finished);
+ dma_ch = cmdq_task->dma_ch;
+ flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+ tx = dmaengine_prep_dma_memcpy(dma_ch, dst_buf_addr, src_buf_addr, f2f_cmd->len, flags);
+ if(!tx){
+ pr_err("Failed to prepare DMA memcp\n");
+ ret = -EFAULT;
+ goto release_cmdq_task;
+ }
+
+ tx->callback = esw_memcp_complete_func;
+ tx->callback_param = cmdq_task;
+
+ cookie = dmaengine_submit(tx);
+ if(dma_submit_error(cookie)){
+ pr_err("Failed to dma tx_submit\n");
+ ret = -EFAULT;
+ goto release_cmdq_task;
+ }
+
+ dma_async_issue_pending(dma_ch);
+ if (wait_for_completion_interruptible_timeout(&cmdq_task->dma_finished,
+ msecs_to_jiffies(cmdq_task->f2f_cmd.timeout)) == 0) {
+ pr_err("DMA transfer timeout.\n");
+ ret = -ETIMEDOUT;
+ dmaengine_terminate_sync(dma_ch);
+ goto release_cmdq_task;
+ }
+
+release_cmdq_task:
+ esw_memcp_release_cmdq_task(cmdq_task);
+ return ret;
+}
+
+
+static void cmdq_task_worker(struct work_struct *work) {
+ struct esw_cmdq_task *task = container_of(work, struct esw_cmdq_task, work);
+ struct cmdq *q = task->cmdq;
+ int ret;
+
+ if (!task) {
+ pr_err("cmdq_task_worker: Invalid task pointer\n");
+ return;
+ }
+
+ // Start DMA Transfer
+ ret = esw_memcp_start_dma_f2f_trans(task);
+
+ if (ret) {
+ pr_err("cmdq_task_worker: DMA transfer failed with error code %d\n", ret);
+ }
+ atomic_inc(&q->completed_tasks);
+
+}
+
+static int esw_cmdq_add_task(struct file *filp, void __user *user_arg) {
+ struct cmdq *q = (struct cmdq *)filp->private_data;
+ struct esw_cmdq_task *cmdq_task;
+ struct esw_memcp_f2f_cmd memcp_f2f_cmd;
+ int ret;
+
+ if (!q || !q->wq) {
+ pr_err("CMDQ or workqueue is NULL\n");
+ return -EINVAL;
+ }
+
+ cmdq_task = kzalloc(sizeof(struct esw_cmdq_task), GFP_KERNEL);
+ if (!cmdq_task) {
+ pr_err("Failed to allocate cmdq_task\n");
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(&memcp_f2f_cmd, user_arg, sizeof(struct esw_memcp_f2f_cmd))) {
+ pr_err("Failed to copy data from user space\n");
+ kfree(cmdq_task);
+ return -EFAULT;
+ }
+
+ cmdq_task->cmdq = q;
+ cmdq_task->f2f_cmd = memcp_f2f_cmd;
+
+ cmdq_task->src_buf.dma_buf = dma_buf_get(memcp_f2f_cmd.src_fd);
+ if (IS_ERR(cmdq_task->src_buf.dma_buf)) {
+ pr_err("Failed to get src dma_buf, src_fd=%d, err=%ld\n",
+ memcp_f2f_cmd.src_fd, PTR_ERR(cmdq_task->src_buf.dma_buf));
+ kfree(cmdq_task);
+ return PTR_ERR(cmdq_task->src_buf.dma_buf);
+ }
+
+ if ((memcp_f2f_cmd.src_offset + memcp_f2f_cmd.len) > cmdq_task->src_buf.dma_buf->size) {
+ pr_err("Source buffer overflow: src_offset=%d, len=%lu, buf_size=%lu\n",
+ memcp_f2f_cmd.src_offset, memcp_f2f_cmd.len, cmdq_task->src_buf.dma_buf->size);
+ dma_buf_put(cmdq_task->src_buf.dma_buf);
+ kfree(cmdq_task);
+ return -EINVAL;
+ }
+
+ cmdq_task->dst_buf.dma_buf = dma_buf_get(memcp_f2f_cmd.dst_fd);
+ if (IS_ERR(cmdq_task->dst_buf.dma_buf)) {
+ pr_err("Failed to get dst dma_buf, dst_fd=%d, err=%ld\n",
+ memcp_f2f_cmd.dst_fd, PTR_ERR(cmdq_task->dst_buf.dma_buf));
+ dma_buf_put(cmdq_task->src_buf.dma_buf);
+ kfree(cmdq_task);
+ return PTR_ERR(cmdq_task->dst_buf.dma_buf);
+ }
+
+ if ((memcp_f2f_cmd.dst_offset + memcp_f2f_cmd.len) > cmdq_task->dst_buf.dma_buf->size) {
+ pr_err("Destination buffer overflow: dst_offset=%d, len=%lu, buf_size=%lu\n",
+ memcp_f2f_cmd.dst_offset, memcp_f2f_cmd.len, cmdq_task->dst_buf.dma_buf->size);
+ dma_buf_put(cmdq_task->src_buf.dma_buf);
+ dma_buf_put(cmdq_task->dst_buf.dma_buf);
+ kfree(cmdq_task);
+ return -EINVAL;
+ }
+
+ INIT_WORK(&cmdq_task->work, cmdq_task_worker);
+ ret = queue_work(cmdq_task->cmdq->wq, &cmdq_task->work);
+ if (!ret) {
+ pr_err("Failed to queue work\n");
+ dma_buf_put(cmdq_task->src_buf.dma_buf);
+ dma_buf_put(cmdq_task->dst_buf.dma_buf);
+ kfree(cmdq_task);
+ return -EFAULT;
+ }
+
+ atomic_inc(&q->total_tasks);
+
+ return 0;
+}
+
+static int esw_cmdq_sync(struct file *filp) {
+ struct cmdq *q = (struct cmdq *)filp->private_data;
+
+ if (!q) {
+ pr_err("esw_cmdq_sync: Invalid cmdq\n");
+ return -EINVAL;
+ }
+
+ flush_workqueue(q->wq);
+
+ return 0;
+}
+
+
+
+static int esw_cmdq_query(struct file *file, void __user *user_arg)
+{
+ struct cmdq *q;
+ struct esw_cmdq_query query;
+
+ if (!file || !user_arg) {
+ pr_err("esw_cmdq_query: Invalid arguments\n");
+ return -EINVAL;
+ }
+
+ q = file->private_data;
+ if (!q) {
+ pr_err("esw_cmdq_query: No cmdq associated with this file descriptor\n");
+ return -EINVAL;
+ }
+
+ int total = atomic_read(&q->total_tasks);
+ int completed = atomic_read(&q->completed_tasks);
+
+ query.status = (total == completed) ? 0 : 1; // 0 FREE1 BUSY
+ query.task_count = total - completed;
+
+ if (copy_to_user(user_arg, &query, sizeof(query))) {
+ pr_err("esw_cmdq_query: Failed to copy data to user space\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static long esw_memcp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+
+ switch (cmd) {
+ case (ESW_CMDQ_ADD_TASK):
+ ret = esw_cmdq_add_task(filp, (void *)arg);
+ break;
+
+ case (ESW_CMDQ_SYNC):
+ ret = esw_cmdq_sync(filp);
+ break;
+
+ case (ESW_CMDQ_QUERY):
+ ret = esw_cmdq_query(filp, (void *)arg);
+ break;
+
+ default:
+ dev_err(esw_memcp_dev, "invalid cmd! cmd=0x%x, arg=0x%lx\n", cmd, arg);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static ssize_t esw_memcp_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
+{
+ dev_info(esw_memcp_dev, "Write: operation not supported\n");
+ return -EINVAL;
+}
+
+static int esw_memcp_open(struct inode *inode, struct file *filp)
+{
+ struct cmdq *q;
+
+ q = kzalloc(sizeof(struct cmdq), GFP_KERNEL);
+ if (!q) {
+ pr_err("Failed to allocate cmdq\n");
+ return -ENOMEM;
+ }
+
+ q->wq = alloc_workqueue("cmdq_wq", WQ_UNBOUND | WQ_FREEZABLE | WQ_MEM_RECLAIM, 0);
+ if (!q->wq) {
+ pr_err("Failed to allocate workqueue\n");
+ kfree(q);
+ return -ENOMEM;
+ }
+
+ atomic_set(&q->total_tasks, 0);
+ atomic_set(&q->completed_tasks, 0);
+
+ filp->private_data = q;
+
+ return 0;
+}
+
+
+
+static int esw_memcp_release(struct inode *inode, struct file *filp)
+{
+ struct cmdq *q = (struct cmdq *)filp->private_data;
+
+ if (q) {
+ if (q->wq) {
+ destroy_workqueue(q->wq);
+ }
+
+ kfree(q);
+ }
+
+ return 0;
+}
+
+
+static struct file_operations esw_memcp_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = esw_memcp_write,
+ .unlocked_ioctl = esw_memcp_ioctl,
+ .open = esw_memcp_open,
+ .release = esw_memcp_release,
+};
+
+static struct miscdevice esw_memcp_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DRIVER_NAME,
+ .mode = 0666,
+ .fops = &esw_memcp_fops,
+};
+
+static int __init esw_memcp_init(void)
+{
+ int ret = 0;
+
+ ret = misc_register(&esw_memcp_miscdev);
+ if (ret) {
+ pr_err("%s: Failed to register misc device, err=%d\n", __func__, ret);
+ return ret;
+ }
+
+ esw_memcp_dev = esw_memcp_miscdev.this_device;
+
+ if (!esw_memcp_dev->dma_mask) {
+ esw_memcp_dev->dma_mask = &esw_memcp_dev->coherent_dma_mask;
+ }
+ ret = dma_set_mask_and_coherent(esw_memcp_dev, DMA_BIT_MASK(64));
+ if (ret)
+ dev_err(esw_memcp_dev, "Failed to set coherent mask.\n");
+ return ret;
+}
+
+static void __exit esw_memcp_exit(void)
+{
+ misc_deregister(&esw_memcp_miscdev);
+}
+module_init(esw_memcp_init);
+module_exit(esw_memcp_exit);
+
+MODULE_AUTHOR("Geng Zonglin <gengzonglin@eswincomputing.com>");
+MODULE_AUTHOR("Yuyang Cong <congyuyang@eswincomputing.com>");
+MODULE_DESCRIPTION("ESW DMA MEMCP Driver");
+MODULE_LICENSE("GPL v2");
\ No newline at end of file
diff --git a/drivers/memory/eswin/es_rsvmem_heap/dmabuf-heap-import-helper.c b/drivers/memory/eswin/es_rsvmem_heap/dmabuf-heap-import-helper.c
index d9ba68d918ef..283fbdfb1c07 100644
--- a/drivers/memory/eswin/es_rsvmem_heap/dmabuf-heap-import-helper.c
+++ b/drivers/memory/eswin/es_rsvmem_heap/dmabuf-heap-import-helper.c
@@ -1169,3 +1169,190 @@ static void __exit split_dmabuf_exit(void)
module_init(split_dmabuf_init);
module_exit(split_dmabuf_exit);
+
+
+static int vmf_replace_pages(struct vm_area_struct *vma, unsigned long addr,
+ struct page **pages, unsigned long num, pgprot_t prot)
+{
+ struct mm_struct *const mm = vma->vm_mm;
+ unsigned long remaining_pages_total = num;
+ unsigned long pfn;
+ pte_t *pte, entry;
+ spinlock_t *ptl;
+ unsigned long newprot_val = pgprot_val(prot);
+ pgprot_t new_prot;
+ u32 i = 0;
+
+ while (remaining_pages_total) {
+ pte = get_locked_pte(mm, addr, &ptl);
+ if (!pte)
+ return VM_FAULT_OOM;
+
+ entry = ptep_get(pte);
+ pfn = page_to_pfn(pages[i]);
+ pr_debug("page_to_pfn(pages[%d])=0x%lx, pte_pfn(entry)=0x%lx, pte_val(entry)=0x%lx\n",
+ i, pfn, pte_pfn(entry), pte_val(entry));
+
+ newprot_val = (pte_val(entry) & (~_PAGE_PFN_MASK)) | newprot_val;
+ if (newprot_val == (pte_val(entry) & (~_PAGE_PFN_MASK)))
+ goto SKIP_PAGE;
+
+ new_prot = __pgprot(newprot_val);
+ entry = mk_pte(pages[i], new_prot);
+ pr_debug("page_to_pfn(pages[%d])=0x%lx, pte_pfn(entry)=0x%lx, modified pte_val(entry)=0x%lx\n",
+ i, page_to_pfn(pages[i]), pte_pfn(entry), pte_val(entry));
+ set_pte_at(vma->vm_mm, addr, pte, entry);
+ update_mmu_cache(vma, addr, pte);
+
+SKIP_PAGE:
+ addr += PAGE_SIZE;
+ pte_unmap_unlock(pte, ptl);
+ remaining_pages_total--;
+ i++;
+ }
+
+ return 0;
+}
+
+static int zap_and_replace_pages(struct vm_area_struct *vma, u64 addr, size_t len, pgprot_t prot)
+{
+ struct page **pages;
+ u32 offset;
+ unsigned long nr_pages;
+ u64 first, last;
+ u64 addr_aligned = ALIGN_DOWN(addr, PAGE_SIZE);
+ u32 i;
+ int ret = -ENOMEM;
+
+ if (!len) {
+ pr_err("invalid userptr size.\n");
+ return -EINVAL;
+ }
+ /* offset into first page */
+ offset = offset_in_page(addr);
+
+ /* Calculate number of pages */
+ first = (addr & PAGE_MASK) >> PAGE_SHIFT;
+ last = ((addr + len - 1) & PAGE_MASK) >> PAGE_SHIFT;
+ nr_pages = last - first + 1;
+ pr_debug("%s:%d, addr=0x%llx(addr_aligned=0x%llx), len=0x%lx, nr_pages=0x%lx(fist:0x%llx,last:0x%llx)\n",
+ __func__, __LINE__, addr, addr_aligned, len, nr_pages, first, last);
+
+ /* alloc array to storing the pages */
+ pages = kvmalloc_array(nr_pages,
+ sizeof(struct page *),
+ GFP_KERNEL);
+ if (!pages)
+ return -ENOMEM;
+
+ ret = get_user_pages_fast(addr_aligned,
+ nr_pages,
+ FOLL_FORCE | FOLL_WRITE,
+ pages);
+
+ if (ret != nr_pages) {
+ nr_pages = (ret >= 0) ? ret : 0;
+ pr_err("get_user_pages_fast, err=%d [0x%lx]\n",
+ ret, nr_pages);
+ ret = ret < 0 ? ret : -EINVAL;
+ goto free_pages_list;
+ }
+ #if 0
+ for (i = 0; i < nr_pages; i++) {
+ pr_debug("page_to_pfn(pages[%i])=0x%lx\n", i, page_to_pfn(pages[i]));
+ }
+ #endif
+
+ pr_debug("%s, vma->vm_start 0x%lx, vma->vm_end 0x%lx, (vm_end - vm_start) 0x%lx, vma->vm_pgoff 0x%lx, user_va 0x%llx, len 0x%lx, nr_pages 0x%lx\n",
+ __func__, vma->vm_start, vma->vm_end,
+ (vma->vm_end - vma->vm_start), vma->vm_pgoff, addr, len, nr_pages);
+
+ /* construct new page table entry for the pages*/
+ ret = vmf_replace_pages(vma, addr_aligned,
+ pages, nr_pages, prot);
+ if (ret) {
+ pr_err("err %d, failed to vmf_replace_pages!!!\n", ret);
+ ret = -EFAULT;
+ goto free_user_pages;
+ }
+
+ /* Flush cache if the access to the user virtual address is uncached. */
+ if (pgprot_val(prot) & _PAGE_UNCACHE) {
+ for (i = 0; i < nr_pages; i++) {
+ /* flush cache*/
+ arch_sync_dma_for_device(page_to_phys(pages[i]), PAGE_SIZE, DMA_BIDIRECTIONAL);
+ /* put page back */
+ put_page(pages[i]);
+ }
+ }
+ else {
+ for (i = 0; i < nr_pages; i++) {
+ /* put page back */
+ put_page(pages[i]);
+ }
+ }
+
+ kvfree(pages);
+
+ return 0;
+
+free_user_pages:
+ for (i = 0; i < nr_pages; i++) {
+ /* put page back */
+ put_page(pages[i]);
+ }
+free_pages_list:
+ kvfree(pages);
+
+ return ret;
+}
+
+/**
+ * remap_malloc_buf - remap a range of memory allocated by malloc() API from user space.
+ * Normally, the CPU access to the user virtual address which is allocated by mallc() API is
+ * through cache. This remap_malloc_buf() API is to re-construct the pte table entry for the
+ * corresponding pages of the user virtual address as uncached memory, so that CPU access to
+ * the virtual address is uncached.
+ * @addr: virtual address which is got by malloc API from user space
+ * @len: the length of the memory allocated by malloc API
+ * @uncaced: if true, remap the memory as uncached, otherwise cached
+ *
+ * Return 0 if success.
+ *
+ * If uncached flag is true, the memory range of this virtual address will be flushed to make
+ * sure all the dirty data is evicted.
+ *
+ */
+int remap_malloc_buf(unsigned long addr, size_t len, bool uncaced)
+{
+ struct vm_area_struct *vma = NULL;
+ struct mm_struct *mm = current->mm;
+ pgprot_t prot;
+ int ret = 0;
+
+ if (!len) {
+ pr_err("Invalid userptr size!!!\n");
+ return -EINVAL;
+ }
+
+ mmap_read_lock(mm);
+ vma = vma_lookup(mm, addr);
+ if (!vma) {
+ pr_err("%s, vma_lookup failed!\n", __func__);
+ mmap_read_unlock(mm);
+ return -EFAULT;
+ }
+
+ pgprot_val(prot) = 0;
+ /* If true, add uncached property so that pfn_pte will use the pfn of system port to
+ constructs the page table entry.
+ Be carefull, do NOT change the value of the original vma->vm_page_prot*/
+ if (uncaced)
+ prot = pgprot_dmacoherent(prot);
+
+ ret = zap_and_replace_pages(vma, addr, len, prot);
+ mmap_read_unlock(mm);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(remap_malloc_buf);
\ No newline at end of file
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-win2030.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-win2030.c
index e3b6c28394b6..6ae7b0ecfb86 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-win2030.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-win2030.c
@@ -1,6 +1,22 @@
-// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-License-Identifier: GPL-2.0
/*
* Eswin DWC Ethernet linux driver
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: iangshuang <liangshuang@eswincomputing.com>
*/
#include <linux/clk.h>
@@ -66,6 +82,10 @@ struct dwc_qos_priv {
struct gpio_desc *phy_reset;
struct stmmac_priv *stmpriv;
int phyled_cfgs[3];
+ unsigned int dly_hsp_reg[3];
+ unsigned int dly_param_1000m[3];
+ unsigned int dly_param_100m[3];
+ unsigned int dly_param_10m[3];
};
static int dwc_eth_dwmac_config_dt(struct platform_device *pdev,
@@ -198,21 +218,15 @@ static int eswin_eth_sid_cfg(struct device *dev)
static void dwc_qos_fix_speed(void *priv, unsigned int speed, unsigned int mode)
{
unsigned long rate = 125000000;
- int err, data = 0;
+ int i, err, data = 0;
struct dwc_qos_priv *dwc_priv = (struct dwc_qos_priv *)priv;
switch (speed) {
case SPEED_1000:
rate = 125000000;
- if ((dwc_priv->dev_id & 0x1) == 0) {
- regmap_write(dwc_priv->hsp_regmap, 0x118, 0x800c8023);
- regmap_write(dwc_priv->hsp_regmap, 0x11c, 0x0c0c0c0c);
- regmap_write(dwc_priv->hsp_regmap, 0x114, 0x23232323);
- } else {
- regmap_write(dwc_priv->hsp_regmap, 0x218, 0x80268025);
- regmap_write(dwc_priv->hsp_regmap, 0x21c, 0x26262626);
- regmap_write(dwc_priv->hsp_regmap, 0x214, 0x25252525);
+ for (i = 0; i < 3; i++) {
+ regmap_write(dwc_priv->hsp_regmap, dwc_priv->dly_hsp_reg[i], dwc_priv->dly_param_1000m[i]);
}
if (dwc_priv->stmpriv) {
@@ -226,14 +240,8 @@ static void dwc_qos_fix_speed(void *priv, unsigned int speed, unsigned int mode)
case SPEED_100:
rate = 25000000;
- if ((dwc_priv->dev_id & 0x1) == 0) {
- regmap_write(dwc_priv->hsp_regmap, 0x118, 0x803f8050);
- regmap_write(dwc_priv->hsp_regmap, 0x11c, 0x3f3f3f3f);
- regmap_write(dwc_priv->hsp_regmap, 0x114, 0x50505050);
- } else {
- regmap_write(dwc_priv->hsp_regmap, 0x218, 0x80588048);
- regmap_write(dwc_priv->hsp_regmap, 0x21c, 0x58585858);
- regmap_write(dwc_priv->hsp_regmap, 0x214, 0x48484848);
+ for (i = 0; i < 3; i++) {
+ regmap_write(dwc_priv->hsp_regmap, dwc_priv->dly_hsp_reg[i], dwc_priv->dly_param_100m[i]);
}
if (dwc_priv->stmpriv) {
@@ -247,14 +255,8 @@ static void dwc_qos_fix_speed(void *priv, unsigned int speed, unsigned int mode)
case SPEED_10:
rate = 2500000;
- if ((dwc_priv->dev_id & 0x1) == 0) {
- regmap_write(dwc_priv->hsp_regmap, 0x118, 0x0);
- regmap_write(dwc_priv->hsp_regmap, 0x11c, 0x0);
- regmap_write(dwc_priv->hsp_regmap, 0x114, 0x0);
- } else {
- regmap_write(dwc_priv->hsp_regmap, 0x218, 0x0);
- regmap_write(dwc_priv->hsp_regmap, 0x21c, 0x0);
- regmap_write(dwc_priv->hsp_regmap, 0x214, 0x0);
+ for (i = 0; i < 3; i++) {
+ regmap_write(dwc_priv->hsp_regmap, dwc_priv->dly_hsp_reg[i], dwc_priv->dly_param_10m[i]);
}
if (dwc_priv->stmpriv) {
@@ -342,11 +344,11 @@ static int dwc_qos_probe(struct platform_device *pdev,
dwc_priv->dev = &pdev->dev;
dwc_priv->phy_reset = devm_gpiod_get(&pdev->dev, "rst", GPIOD_OUT_LOW);
if (IS_ERR(dwc_priv->phy_reset)) {
- dev_err(&pdev->dev, "Reset gpio not specified\n");
- return -EINVAL;
+ dev_info(&pdev->dev, "Reset gpio not specified\n");
}
- gpiod_set_value(dwc_priv->phy_reset, 0);
+ if (dwc_priv->phy_reset)
+ gpiod_set_value(dwc_priv->phy_reset, 0);
dwc_priv->rgmii_sel = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "eswin,rgmiisel");
if (IS_ERR(dwc_priv->rgmii_sel)){
@@ -369,6 +371,30 @@ static int dwc_qos_probe(struct platform_device *pdev,
dev_warn(&pdev->dev, "can't get led cfgs for 10Mbps mode (%d)\n", ret);
}
+ ret = of_property_read_variable_u32_array(pdev->dev.of_node, "eswin,dly_hsp_reg", &dwc_priv->dly_hsp_reg[0], 3, 0);
+ if (ret != 3) {
+ dev_err(&pdev->dev, "can't get delay hsp reg.ret(%d)\n", ret);
+ return ret;
+ }
+
+ ret = of_property_read_variable_u32_array(pdev->dev.of_node, "dly-param-1000m", &dwc_priv->dly_param_1000m[0], 3, 0);
+ if (ret != 3) {
+ dev_err(&pdev->dev, "can't get delay param for 1Gbps mode (%d)\n", ret);
+ return ret;
+ }
+
+ ret = of_property_read_variable_u32_array(pdev->dev.of_node, "dly-param-100m", &dwc_priv->dly_param_100m[0], 3, 0);
+ if (ret != 3) {
+ dev_err(&pdev->dev, "can't get delay param for 100Mbps mode (%d)\n", ret);
+ return ret;
+ }
+
+ ret = of_property_read_variable_u32_array(pdev->dev.of_node, "dly-param-10m", &dwc_priv->dly_param_10m[0], 3, 0);
+ if (ret != 3) {
+ dev_err(&pdev->dev, "can't get delay param for 10Mbps mode (%d)\n", ret);
+ return ret;
+ }
+
ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,rgmiisel", 1, &rgmiisel_offset);
if (ret) {
dev_err(&pdev->dev, "can't get rgmiisel_offset (%d)\n", ret);
@@ -487,7 +513,8 @@ static int dwc_qos_remove(struct platform_device *pdev)
reset_control_assert(dwc_priv->rst);
dwc_clks_config(dwc_priv, false);
- devm_gpiod_put(&pdev->dev, dwc_priv->phy_reset);
+ if (dwc_priv->phy_reset)
+ devm_gpiod_put(&pdev->dev, dwc_priv->phy_reset);
return 0;
}
diff --git a/drivers/regulator/es5340.c b/drivers/regulator/es5340.c
index 30696296b210..e077fa2658bf 100644
--- a/drivers/regulator/es5340.c
+++ b/drivers/regulator/es5340.c
@@ -712,9 +712,7 @@ static struct regulator_desc es5340_regulator_desc = {
static s32 es5340_init_data(struct ES5340_DRIVER_DATA *data,
const struct regulation_constraints *constraints, u32 default_voltage)
{
- u8 value = 0;
s32 ret = 0;
- u16 new_value = 0;
struct device *dev = &data->client->dev;
dev_info(dev,
diff --git a/drivers/soc/eswin/ai_driver/Kconfig b/drivers/soc/eswin/ai_driver/Kconfig
index 84a135ee3d69..0044a4be10e5 100644
--- a/drivers/soc/eswin/ai_driver/Kconfig
+++ b/drivers/soc/eswin/ai_driver/Kconfig
@@ -2,6 +2,11 @@ config ESWIN_DSP
tristate "Eswin DSP"
default n
+config DSP_PERF
+ bool "DSP PERF"
+ default n
+ depends on ESWIN_DSP
+
config ESWIN_NPU
tristate "Eswin NPU"
default n
@@ -9,3 +14,8 @@ config ESWIN_NPU
select ESWIN_DEV_DMA_BUF
select ESWIN_IOMMU_RSV
select ESWIN_RSVMEM_HEAP
+
+config NPU_PERF
+ bool "NPU PERF"
+ default n
+ depends on ESWIN_NPU
\ No newline at end of file
diff --git a/drivers/soc/eswin/ai_driver/dsp/Makefile b/drivers/soc/eswin/ai_driver/dsp/Makefile
index e433e1af883b..d9fb51b3c14d 100755
--- a/drivers/soc/eswin/ai_driver/dsp/Makefile
+++ b/drivers/soc/eswin/ai_driver/dsp/Makefile
@@ -50,4 +50,8 @@ eic7700_dsp-y += dsp_platform.o dsp_sram.o dsp_firmware.o dsp_pool.o \
endif
+ifeq ($(CONFIG_DSP_PERF),y)
+ BUILD_RELEASE = 2
+endif
+
ccflags-y += -DDSP_ENV_SIM=${DSP_ENV_SIM} -DBUILD_RELEASE=${BUILD_RELEASE} -DDEBUG_LEVEL=${DEBUG_LEVEL} -w
diff --git a/drivers/soc/eswin/ai_driver/dsp/dsp_main.c b/drivers/soc/eswin/ai_driver/dsp/dsp_main.c
index b32ffba9dcc8..5a2f3e97d9d8 100644
--- a/drivers/soc/eswin/ai_driver/dsp/dsp_main.c
+++ b/drivers/soc/eswin/ai_driver/dsp/dsp_main.c
@@ -58,6 +58,9 @@
#include <uapi/asm-generic/siginfo.h>
#include <linux/mailbox/eswin-mailbox.h>
#include <linux/dma-mapping.h>
+#include <linux/devfreq.h>
+#include <linux/pm_opp.h>
+
#include "eswin-khandle.h"
#include "dsp_main.h"
@@ -682,11 +685,16 @@ static inline void dsp_release(struct es_dsp *dsp)
es_dsp_release(dsp->hw_arg);
}
-static inline int dsp_set_rate(struct es_dsp *dsp, unsigned long rate)
+static inline int dsp_set_rate(struct es_dsp *dsp, unsigned long *rate)
{
return es_dsp_set_rate(dsp->hw_arg, rate);
}
+static inline int dsp_get_rate(struct es_dsp *dsp)
+{
+ return es_dsp_get_rate(dsp->hw_arg);
+}
+
static int dsp_synchronize(struct es_dsp *dsp)
{
return es_dsp_sync(dsp);
@@ -852,95 +860,6 @@ int __maybe_unused dsp_runtime_resume(struct device *dev)
}
EXPORT_SYMBOL(dsp_runtime_resume);
-/**
- * Called when opening rate file
- * @param inode
- * @param file
- * @return
- */
-static int dsp_rate_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
-/**
- * Called when reading rate file
- */
-static ssize_t dsp_rate_read(struct file *flip, char __user *ubuf, size_t cnt,
- loff_t *ppos)
-{
-#define RUN_STR_SIZE 11
- struct es_dsp *dsp = flip->private_data;
- char buf[RUN_STR_SIZE];
- int r;
-
- r = snprintf(buf, RUN_STR_SIZE, "%ld\n", dsp->rate);
-
- return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
-}
-/**
- * Called when writing rate file
- */
-static ssize_t dsp_rate_write(struct file *flip, const char __user *ubuf,
- size_t cnt, loff_t *ppos)
-{
-#define SIZE_SMALL_BUF 256
- struct es_dsp *dsp = flip->private_data;
- char buf[SIZE_SMALL_BUF] = { 0 };
- unsigned ret;
-
- if (cnt > SIZE_SMALL_BUF)
- cnt = SIZE_SMALL_BUF - 1;
-
- if (copy_from_user(&buf, ubuf, cnt))
- return -EFAULT;
-
- if (0 == strncmp(buf, "5200000", strlen("5200000"))) {
- dsp->rate = DSP_SUBSYS_LOWLOAD_CLK; /* FIXME spinlock? */
- } else if (0 == strncmp(buf, "1040000000", strlen("1040000000"))) {
- dsp->rate = DSP_SUBSYS_HILOAD_CLK;
- } else {
- dev_err(dsp->dev, "invalid rate para %s\n", buf);
- return -EFAULT;
- }
- ret = dsp_set_rate(dsp, dsp->rate);
- if (0 != ret) {
- dev_err(dsp->dev, "failed to set rate to %ldHZ", dsp->rate);
- } else {
- dev_info(dsp->dev, "set rate to %ldHZ", dsp->rate);
- }
- *ppos += cnt;
-
- return cnt;
-}
-
-static const struct file_operations dsp_rate_fops = {
- .open = dsp_rate_open,
- .read = dsp_rate_read,
- .write = dsp_rate_write,
- .llseek = generic_file_llseek,
-};
-static int dsp_debug_init(struct es_dsp *dsp)
-{
- struct dentry *dir, *d;
- char name[32];
-
- scnprintf(name, ARRAY_SIZE(name), "dsp_%d", dsp->nodeid);
-
- dir = debugfs_create_dir(name, NULL);
- if (IS_ERR(dir))
- return PTR_ERR(dir);
-
- d = debugfs_create_file("rate", S_IRUGO | S_IWUSR, dir, dsp,
- &dsp_rate_fops);
- if (IS_ERR(d))
- return PTR_ERR(d);
-
- dsp->debug_dentry = dir;
- return 0;
-}
-
#ifdef CONFIG_OF
static const struct of_device_id es_dsp_hw_match[] = {
{
@@ -965,13 +884,48 @@ static void dsp_init_prio_array(struct es_dsp *dsp)
set_bit(DSP_MAX_PRIO, array->bitmap);
}
-static int32_t dsp_probe_result = 0;
+#if defined(CONFIG_PM_DEVFREQ)
+/* devfreq target function to set frequency */
+static int dsp_devfreq_target(struct device *dev, unsigned long *freq, u32 flags)
+{
+ struct es_dsp *dsp = dev_get_drvdata(dev);
+
+ return dsp_set_rate(dsp, freq);
+}
+
+static int dsp_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
+{
+ struct es_dsp *dsp = dev_get_drvdata(dev);
+ unsigned long rate;
+
+ rate = dsp_get_rate(dsp);
+ if (rate <= 0) {
+ dev_err(dsp->dev, "failed to get aclk: %d\n", rate);
+ return rate;
+ }
+ *freq = rate;
+ return 0;
+}
+
+/* devfreq profile */
+static struct devfreq_dev_profile dsp_devfreq_profile = {
+ .initial_freq = DSP_SUBSYS_HILOAD_CLK,
+ .timer = DEVFREQ_TIMER_DELAYED,
+ .polling_ms = 1000, /* Poll every 1000ms to monitor load */
+ .target = dsp_devfreq_target,
+ .get_cur_freq = dsp_devfreq_get_cur_freq,
+};
+#endif
+static int32_t dsp_probe_result = 0;
static int es_dsp_hw_probe(struct platform_device *pdev)
{
int ret;
char nodename[sizeof("es-dsp") + 3 * sizeof(int)];
struct es_dsp *dsp;
+#if defined(CONFIG_PM_DEVFREQ)
+ struct devfreq *df;
+#endif
dsp = devm_kzalloc(&pdev->dev,
sizeof(*dsp) + sizeof(struct es_dsp_stats) +
@@ -1038,6 +992,23 @@ static int es_dsp_hw_probe(struct platform_device *pdev)
__LINE__, ret);
goto err_mbox_clk;
}
+
+#if defined(CONFIG_PM_DEVFREQ)
+ /* Add OPP table from device tree */
+ ret = dev_pm_opp_of_add_table(&pdev->dev);
+ if (ret) {
+ dsp_err("%s, %d, Failed to add OPP table\n", __func__, __LINE__);
+ goto err_dsp_devfreq;
+ }
+
+ df = devm_devfreq_add_device(&pdev->dev, &dsp_devfreq_profile, "userspace", NULL);
+ if (IS_ERR(df)) {
+ dsp_err("%s, %d, add devfreq failed\n", __func__, __LINE__);
+ ret = PTR_ERR(df);
+ goto err_dsp_devfreq;
+ }
+#endif
+
ret = es_dsp_clk_enable(dsp);
if (ret) {
dsp_err("%s, %d, clock enbale error.\n", __func__, __LINE__,
@@ -1081,7 +1052,6 @@ static int es_dsp_hw_probe(struct platform_device *pdev)
g_es_dsp[dsp->numa_id][dsp->process_id] = dsp;
- dsp_debug_init(dsp);
pm_runtime_mark_last_busy(dsp->dev);
pm_runtime_put_autosuspend(dsp->dev);
@@ -1100,6 +1070,10 @@ static int es_dsp_hw_probe(struct platform_device *pdev)
err_tbu_power:
es_dsp_clk_disable(dsp);
err_dsp_clk:
+#if defined(CONFIG_PM_DEVFREQ)
+ devm_devfreq_remove_device(dsp->dev, df);
+err_dsp_devfreq:
+#endif
dsp_disable_mbox_clock(dsp);
err_mbox_clk:
es_dsp_unmap_resource(dsp);
diff --git a/drivers/soc/eswin/ai_driver/dsp/dsp_platform.c b/drivers/soc/eswin/ai_driver/dsp/dsp_platform.c
index 45c8bda644cc..342bdb20baae 100644
--- a/drivers/soc/eswin/ai_driver/dsp/dsp_platform.c
+++ b/drivers/soc/eswin/ai_driver/dsp/dsp_platform.c
@@ -318,7 +318,7 @@ int es_dsp_clk_enable(struct es_dsp *dsp)
return 0;
}
-int es_dsp_set_rate(struct es_dsp_hw *hw, unsigned long rate)
+int es_dsp_set_rate(struct es_dsp_hw *hw, unsigned long *rate)
{
struct es_dsp *dsp = hw->es_dsp;
int ret;
@@ -327,18 +327,24 @@ int es_dsp_set_rate(struct es_dsp_hw *hw, unsigned long rate)
dsp_err("%s %d: failed to get device\n", __func__, __LINE__);
return -ENXIO;
}
- rate = clk_round_rate(hw->aclk, rate);
- if (rate > 0) {
- ret = clk_set_rate(hw->aclk, rate);
+
+ *rate = clk_round_rate(hw->aclk, *rate);
+ if (*rate > 0) {
+ ret = clk_set_rate(hw->aclk, *rate);
if (ret) {
dev_err(dsp->dev, "failed to set aclk: %d\n", ret);
return ret;
}
}
- dev_info(dsp->dev, "set device rate to %ldHZ\n", rate);
+ dev_info(dsp->dev, "set dev rate to %ldHZ\n", *rate);
return 0;
}
+int es_dsp_get_rate(struct es_dsp_hw *hw)
+{
+ return clk_get_rate(hw->aclk);
+}
+
void es_dsp_halt(struct es_dsp_hw *hw)
{
struct es_dsp *dsp = hw->es_dsp;
@@ -1269,7 +1275,6 @@ int es_dsp_hw_init(struct es_dsp *dsp)
hw->pts_iova = 0;
goto err;
}
- es_dsp_set_rate(hw, dsp->rate);
dev_dbg(dsp->dev, "firmware-name:%s.\n", dsp->firmware_name);
return 0;
err:
diff --git a/drivers/soc/eswin/ai_driver/dsp/dsp_platform.h b/drivers/soc/eswin/ai_driver/dsp/dsp_platform.h
index d538a9727242..40740cdfe21e 100644
--- a/drivers/soc/eswin/ai_driver/dsp/dsp_platform.h
+++ b/drivers/soc/eswin/ai_driver/dsp/dsp_platform.h
@@ -30,7 +30,7 @@ int es_dsp_send_irq(struct es_dsp_hw *, dsp_request_t *);
int es_dsp_reboot_core(struct es_dsp_hw *);
int es_dsp_enable(struct es_dsp_hw *);
void es_dsp_disable(struct es_dsp_hw *);
-int es_dsp_set_rate(struct es_dsp_hw *, unsigned long rate);
+int es_dsp_set_rate(struct es_dsp_hw *, unsigned long *rate);
void es_dsp_reset(struct es_dsp_hw *);
void es_dsp_halt(struct es_dsp_hw *);
void es_dsp_release(struct es_dsp_hw *);
diff --git a/drivers/soc/eswin/ai_driver/dsp/dsp_platform_sim.c b/drivers/soc/eswin/ai_driver/dsp/dsp_platform_sim.c
index ea9471381e02..2a7ba4077a99 100644
--- a/drivers/soc/eswin/ai_driver/dsp/dsp_platform_sim.c
+++ b/drivers/soc/eswin/ai_driver/dsp/dsp_platform_sim.c
@@ -262,7 +262,7 @@ void es_dsp_halt(struct es_dsp_hw *hw)
void es_dsp_release(struct es_dsp_hw *hw)
{
}
-long es_dsp_set_rate(struct es_dsp_hw *hw, unsigned long rate)
+long es_dsp_set_rate(struct es_dsp_hw *hw, unsigned long *rate)
{
return 0;
}
diff --git a/drivers/soc/eswin/ai_driver/npu/Makefile b/drivers/soc/eswin/ai_driver/npu/Makefile
index 29cbe78dd026..630aa94bc05f 100644
--- a/drivers/soc/eswin/ai_driver/npu/Makefile
+++ b/drivers/soc/eswin/ai_driver/npu/Makefile
@@ -3,6 +3,9 @@ LOG_LEVEL ?= 0
NPU_DEV_SIM ?= 0
SMALL_PEC_MAT ?= 0
+ifeq ($(CONFIG_NPU_PERF),y)
+ NPU_PERF_STATS = 2
+endif
ccflags-y += -I$(src)
ccflags-y += -I$(srctree)/drivers/soc/eswin
ccflags-y += -I$(srctree)/drivers/memory/eswin/codacache/
@@ -22,7 +25,7 @@ ccflags-y += -DNPU_DBG
#ccflags-y += -DCONV_DUMP
ccflags-y += -DLOG_LEVEL=$(LOG_LEVEL)
ccflags-y += -Wno-unused-function
-ccflags-y += -Werror
+#ccflags-y += -Werror
ccflags-y += -Wno-int-to-pointer-cast
obj-$(CONFIG_ESWIN_NPU) += eic7700_npu.o
diff --git a/drivers/soc/eswin/ai_driver/npu/dla_driver.h b/drivers/soc/eswin/ai_driver/npu/dla_driver.h
index 2101ccd1766e..11f22de8920b 100644
--- a/drivers/soc/eswin/ai_driver/npu/dla_driver.h
+++ b/drivers/soc/eswin/ai_driver/npu/dla_driver.h
@@ -31,7 +31,7 @@
#include <linux/wait.h>
#include <linux/clk.h>
#include <linux/mailbox_controller.h>
-
+#include <linux/regulator/consumer.h>
#include "dla_interface.h"
#include "hetero_common.h"
@@ -67,6 +67,11 @@ struct nvdla_device {
struct reset_control *rstc_e31_core;
struct clk *e31_core_clk;
+ struct clk *core_clk;
+ struct clk *cfg_clk;
+ struct clk *mux_u_npu_core_3mux1_gfree;
+ struct clk *fixed_rate_clk_spll2_fout2;
+ struct clk *fixed_rate_clk_spll1_fout1;
struct clk *mbox_pclk_device;
struct clk *mbox_pclk;
@@ -78,8 +83,11 @@ struct nvdla_device {
u32 mbox_tx_lock_bit;
u32 mbox_tx_irq_bit;
spinlock_t mbox_lock;
+ unsigned long rate, volt;
+ struct mutex devfreq_lock;
uint16_t *pause_op_list;
+ struct regulator *npu_regulator;
};
void dla_reg_write(struct nvdla_device *dev, uint32_t addr, uint32_t value);
diff --git a/drivers/soc/eswin/ai_driver/npu/npu_main.c b/drivers/soc/eswin/ai_driver/npu/npu_main.c
index a742cbc58452..f6970d560605 100644
--- a/drivers/soc/eswin/ai_driver/npu/npu_main.c
+++ b/drivers/soc/eswin/ai_driver/npu/npu_main.c
@@ -73,9 +73,17 @@
#include "dla_buffer.h"
#include "mailbox_regs.h"
#include "nvdla_proc.h"
+#include <linux/eswin_npu.h>
+
+#if defined(CONFIG_PM_DEVFREQ)
+#include <linux/devfreq.h>
+#include <linux/pm_opp.h>
+#endif
+
MODULE_IMPORT_NS(DMA_BUF);
#define DRIVER_NAME "eswin_npu"
+#define NPU_CORE_CLK_HIGHEST 1500000000
int64_t dla_get_time_us(void)
{
@@ -324,6 +332,113 @@ struct nvdla_device *get_nvdla_dev(int i)
return static_nvdla_dev[i];
}
+#if defined(CONFIG_PM_DEVFREQ)
+static int npu_devfreq_target(struct device *dev, unsigned long *freq, u32 flags)
+{
+ struct nvdla_device *nvdla_dev = dev_get_drvdata(dev);
+ struct dev_pm_opp *opp;
+ unsigned long target_volt, target_rate;
+ unsigned long rate;
+ int ret;
+
+ opp = devfreq_recommended_opp(dev, freq, flags);
+ if (IS_ERR(opp)) {
+ return PTR_ERR(opp);
+ }
+
+ target_rate = dev_pm_opp_get_freq(opp);
+ target_volt = dev_pm_opp_get_voltage(opp);
+ dev_pm_opp_put(opp);
+ if (target_rate == nvdla_dev->rate) {
+ return 0;
+ }
+ mutex_lock(&nvdla_dev->devfreq_lock);
+
+ if (target_rate > nvdla_dev->rate) { // rise freq
+ ret = regulator_set_voltage(nvdla_dev->npu_regulator, target_volt, target_volt);
+ if (ret) {
+ dev_err(dev, "Cannot set voltage %lu uV\n", target_volt);
+ goto out;
+ }
+
+ ret = clk_set_parent(nvdla_dev->mux_u_npu_core_3mux1_gfree, nvdla_dev->fixed_rate_clk_spll1_fout1);
+ if (ret) {
+ dev_err(dev, "Cannot set target voltage %lu parent, (%d)\n", target_rate, ret);
+ goto err_parent;
+ }
+ mdelay(10);
+ rate = clk_round_rate(nvdla_dev->core_clk, target_rate);
+ ret = clk_set_rate(nvdla_dev->core_clk, rate);
+ if (ret != 0)
+ {
+ dev_err(dev, "failed to set core_clk: %d\n", ret);
+ goto err_rate;
+
+ }
+
+ } else { // lower freq
+ ret = clk_set_parent(nvdla_dev->mux_u_npu_core_3mux1_gfree, nvdla_dev->fixed_rate_clk_spll2_fout2);
+ if (ret) {
+ dev_err(dev, "Cannot set target voltage %lu parent, (%d)\n", target_rate, ret);
+ goto out;
+ }
+
+ rate = clk_round_rate(nvdla_dev->core_clk, target_rate);
+ ret = clk_set_rate(nvdla_dev->core_clk, rate);
+ if (ret != 0)
+ {
+ dev_err(dev, "failed to set core_clk: %d\n", ret);
+ goto err_rate;
+
+ }
+
+
+ ret = regulator_set_voltage(nvdla_dev->npu_regulator, target_volt, target_volt);
+ if (ret) {
+ dev_err(dev, "Cannot set voltage %lu uV\n", target_volt);
+ goto err_rate;
+ }
+ mdelay(10);
+
+ }
+
+ nvdla_dev->rate = clk_get_rate(nvdla_dev->core_clk);
+ if (nvdla_dev->rate != target_rate) {
+ dev_err(dev, "Got wrong frequency, Request %lu, Current %lu.\n", target_rate, nvdla_dev->rate);
+ ret = -EIO;
+ goto err_rate;
+ }
+ nvdla_dev->rate = target_rate;
+ nvdla_dev->volt = target_volt;
+ mutex_unlock(&nvdla_dev->devfreq_lock);
+ return 0;
+
+err_rate:
+ clk_set_parent(nvdla_dev->mux_u_npu_core_3mux1_gfree, nvdla_dev->fixed_rate_clk_spll1_fout1);
+err_parent:
+ regulator_set_voltage(nvdla_dev->npu_regulator, nvdla_dev->volt, nvdla_dev->volt);
+out:
+ mutex_unlock(&nvdla_dev->devfreq_lock);
+ return ret;
+}
+
+static int npu_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
+{
+ struct nvdla_device *nvdla_dev = dev_get_drvdata(dev);
+
+ *freq = nvdla_dev->rate;
+ return 0;
+}
+
+static struct devfreq_dev_profile npu_devfreq_profile = {
+ .initial_freq = NPU_CORE_CLK_HIGHEST,
+ .timer = DEVFREQ_TIMER_DELAYED,
+ .polling_ms = 1000,
+ .target = npu_devfreq_target,
+ .get_cur_freq = npu_devfreq_get_cur_freq,
+};
+#endif
+
static int32_t npu_probe_result = 0;
static int32_t edla_probe(struct platform_device *pdev)
@@ -333,6 +448,10 @@ static int32_t edla_probe(struct platform_device *pdev)
struct nvdla_device *nvdla_dev;
struct device *dev = &pdev->dev;
uint32_t version;
+#if defined(CONFIG_PM_DEVFREQ)
+ struct devfreq *df = NULL;
+ struct dev_pm_opp *opp;
+#endif
dla_debug("%s enter.\n", __FUNCTION__);
#if SMALL_PEC_MAT
@@ -352,10 +471,23 @@ static int32_t edla_probe(struct platform_device *pdev)
spin_lock_init(&nvdla_dev->nvdla_lock);
mutex_init(&nvdla_dev->task_mutex);
init_waitqueue_head(&nvdla_dev->event_wq);
+ mutex_init(&nvdla_dev->devfreq_lock);
+
+ nvdla_dev->npu_regulator = devm_regulator_get(dev, "npu");
+ err = regulator_enable(nvdla_dev->npu_regulator);
+ if (err < 0)
+ {
+ dla_error("npu_regulator enble error:%d\n\r", err);
+ regulator_put(nvdla_dev->npu_regulator);
+ nvdla_dev->npu_regulator = NULL;
+ return err;
+ }
+
err = npu_dt_node_resources(nvdla_dev);
if (err) {
dla_error("error, get hw resource, ret=%d\n", err);
platform_set_drvdata(pdev, NULL);
+ regulator_disable(nvdla_dev->npu_regulator);
return -EINVAL;
}
@@ -366,6 +498,7 @@ static int32_t edla_probe(struct platform_device *pdev)
goto err_mem0;
}
+
//npu configuration space, start from 0x51c00000
nvdla_dev->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(nvdla_dev->base)) {
@@ -415,6 +548,36 @@ static int32_t edla_probe(struct platform_device *pdev)
goto err_iomap_program;
}
+#if defined(CONFIG_PM_DEVFREQ)
+ /* Add OPP table from device tree */
+ err = devm_pm_opp_of_add_table(dev);
+ if (err) {
+ dev_err(dev, "%s, %d, Failed to add OPP table, ret = %d.\n", __func__, __LINE__, err);
+ goto err_init_reset;
+ }
+ nvdla_dev->rate = clk_get_rate(nvdla_dev->core_clk);
+ opp = devfreq_recommended_opp(dev, &nvdla_dev->rate, 0);
+ if (IS_ERR(opp)) {
+ err = PTR_ERR(opp);
+ goto err_init_reset;
+ }
+
+ nvdla_dev->rate = dev_pm_opp_get_freq(opp);
+ nvdla_dev->volt = dev_pm_opp_get_voltage(opp);
+
+ regulator_set_voltage(nvdla_dev->npu_regulator, nvdla_dev->volt, nvdla_dev->volt);
+
+ dev_pm_opp_put(opp);
+
+ df = devm_devfreq_add_device(dev, &npu_devfreq_profile, "userspace", NULL);
+ if (IS_ERR(df)) {
+ err = PTR_ERR(df);
+ dev_err(dev, "%s, %d, Failed to add devfreq device, ret=%d.\n", __func__, __LINE__, err);
+ goto err_init_reset;
+ }
+#endif
+
+
pm_runtime_set_autosuspend_delay(dev, 5000);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_active(dev);
@@ -513,6 +676,7 @@ static int32_t edla_probe(struct platform_device *pdev)
err_iomap_emission:
release_mem_region(E31_EMISSION_DTIM_BASE + nvdla_dev->numa_id * NPU_DIE_REG_OFFSET, E31_EMISSION_DTIM_SIZE);
err_mem0:
+ regulator_disable(nvdla_dev->npu_regulator);
npu_put_dt_resources(nvdla_dev);
npu_probe_result = err;
return err;
@@ -556,6 +720,8 @@ static int32_t __exit edla_remove(struct platform_device *pdev)
ret = npu_disable_clock(nvdla_dev);
npu_put_dt_resources(nvdla_dev);
npu_remove_sysfs(pdev);
+ regulator_disable(nvdla_dev->npu_regulator);
+
if (nvdla_dev->pause_op_list) {
vfree(nvdla_dev->pause_op_list);
nvdla_dev->pause_op_list = NULL;
@@ -625,19 +791,45 @@ int __maybe_unused npu_suspend(struct device *dev)
npu_tbu_power(dev, false);
npu_disable_clock(nvdla_dev);
+
+ npu_dev_assert(nvdla_dev);
+ if ((NULL != nvdla_dev->npu_regulator) && (!IS_ERR(nvdla_dev->npu_regulator)))
+ {
+ regulator_disable(nvdla_dev->npu_regulator);
+ }
+
return 0;
}
int __maybe_unused npu_resume(struct device *dev)
{
int ret;
- struct nvdla_device *ndev = dev_get_drvdata(dev);
+ int is_enable = 0;
- ret = npu_enable_clock(ndev);
+ struct nvdla_device *nvdla_dev = dev_get_drvdata(dev);
+
+ if ((NULL != nvdla_dev->npu_regulator) && (!IS_ERR(nvdla_dev->npu_regulator)))
+ {
+ is_enable = regulator_is_enabled(nvdla_dev->npu_regulator);
+ if(0 == is_enable)
+ {
+ mdelay(20);
+ }
+ ret = regulator_enable(nvdla_dev->npu_regulator);
+ if(ret < 0)
+ {
+ dla_error("%s, %d regulator_enable eror\n", __func__, __LINE__);
+ }
+ if(0 == is_enable)
+ {
+ mdelay(20);
+ }
+ }
+ ret = npu_enable_clock(nvdla_dev);
if (ret < 0) {
return ret;
}
- ret = npu_hardware_reset(ndev);
+ ret = npu_hardware_reset(nvdla_dev);
if (ret) {
dla_error("hardware reset error, ret=%d.\n", ret);
return -EIO;
@@ -645,11 +837,11 @@ int __maybe_unused npu_resume(struct device *dev)
pm_runtime_get_noresume(dev);
- ret = npu_init_reset(ndev);
+ ret = npu_init_reset(nvdla_dev);
if (ret < 0) {
goto err_reset;
}
- ret = npu_init_mbox(ndev);
+ ret = npu_init_mbox(nvdla_dev);
if (ret) {
dev_err(dev, "npu init mailbox error, ret = %d.\n", ret);
goto err_reset;
@@ -657,14 +849,14 @@ int __maybe_unused npu_resume(struct device *dev)
npu_tbu_power(dev, true);
/* config streamID of NPU_DMA */
- ret = npu_e31_load_fw(ndev);
+ ret = npu_e31_load_fw(nvdla_dev);
if (ret) {
dev_err(dev, "load e31 fw error.\n");
goto err_load_firm;
}
- npu_dma_sid_cfg(ndev->base, WIN2030_SID_NPU_DMA);
- npu_hw_init(ndev);
- ret = npu_init_ipc(ndev);
+ npu_dma_sid_cfg(nvdla_dev->base, WIN2030_SID_NPU_DMA);
+ npu_hw_init(nvdla_dev);
+ ret = npu_init_ipc(nvdla_dev);
if (ret) {
dev_err(dev, "npu init ipc error.\n");
goto err_ipc;
@@ -672,14 +864,15 @@ int __maybe_unused npu_resume(struct device *dev)
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
+
return 0;
err_ipc:
- npu_init_reset(ndev);
+ npu_init_reset(nvdla_dev);
err_load_firm:
npu_tbu_power(dev, false);
err_reset:
- npu_disable_clock(ndev);
+ npu_disable_clock(nvdla_dev);
return ret;
}
diff --git a/drivers/soc/eswin/ai_driver/npu/nvdla_hw.c b/drivers/soc/eswin/ai_driver/npu/nvdla_hw.c
index 096bcde3bcad..923b8e36175e 100644
--- a/drivers/soc/eswin/ai_driver/npu/nvdla_hw.c
+++ b/drivers/soc/eswin/ai_driver/npu/nvdla_hw.c
@@ -260,6 +260,35 @@ int npu_dev_reset(struct nvdla_device *nvdla_dev)
return 0;
}
+
+int npu_dev_assert(struct nvdla_device *nvdla_dev)
+{
+ int ret = 0;
+
+ ret = reset_control_assert(nvdla_dev->rstc_e31_core);
+ WARN_ON(0 != ret);
+
+ /*reset npu core*/
+ ret = npu_core_rst(0, false);
+ if (ret) {
+ dev_err(&nvdla_dev->pdev->dev, "npu_core_rst fail,error: %d.\n",
+ ret);
+ return ret;
+ }
+
+ /*reset npu cfg*/
+ ret = npu_cfg_rst(0, false);
+ if (ret) {
+ dev_err(&nvdla_dev->pdev->dev, "npu_core_rst fail,error: %d.\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+
+
int npu_init_reset(struct nvdla_device *nvdla_dev)
{
struct platform_device *pdev = nvdla_dev->pdev;
@@ -826,6 +855,44 @@ int npu_dt_node_resources(struct nvdla_device *nvdla_dev)
dev_err(&pdev->dev, "failed to get core_clk: %d\n", ret);
return ret;
}
+ nvdla_dev->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(nvdla_dev->core_clk)) {
+ ret = PTR_ERR(nvdla_dev->core_clk);
+ nvdla_dev->core_clk = NULL;
+ dev_err(&pdev->dev, "failed to get core clk: %d.\n", ret);
+ return ret;
+ }
+ nvdla_dev->cfg_clk = devm_clk_get(&pdev->dev, "cfg_clk");
+ if (IS_ERR(nvdla_dev->cfg_clk)) {
+ ret = PTR_ERR(nvdla_dev->cfg_clk);
+ nvdla_dev->cfg_clk = NULL;
+ dev_err(&pdev->dev, "failed to get cfg clk: %d.\n", ret);
+ return ret;
+ }
+ nvdla_dev->mux_u_npu_core_3mux1_gfree = devm_clk_get(&pdev->dev, "mux_u_npu_core_3mux1_gfree");
+ if (IS_ERR(nvdla_dev->mux_u_npu_core_3mux1_gfree)) {
+ ret = PTR_ERR(nvdla_dev->mux_u_npu_core_3mux1_gfree);
+ nvdla_dev->mux_u_npu_core_3mux1_gfree = NULL;
+ dev_err(&pdev->dev, "failed to get mux_u_npu_core_3mux1_gfree clk: %d.\n", ret);
+ return ret;
+ }
+
+ nvdla_dev->fixed_rate_clk_spll2_fout2 = devm_clk_get(&pdev->dev, "fixed_rate_clk_spll2_fout2");
+ if (IS_ERR(nvdla_dev->fixed_rate_clk_spll2_fout2)) {
+ ret = PTR_ERR(nvdla_dev->fixed_rate_clk_spll2_fout2);
+ nvdla_dev->fixed_rate_clk_spll2_fout2 = NULL;
+ dev_err(&pdev->dev, "failed to get fixed_rate_clk_spll2_fout2 clk: %d.\n", ret);
+ return ret;
+ }
+
+ nvdla_dev->fixed_rate_clk_spll1_fout1 = devm_clk_get(&pdev->dev, "fixed_rate_clk_spll1_fout1");
+ if (IS_ERR(nvdla_dev->fixed_rate_clk_spll1_fout1)) {
+ ret = PTR_ERR(nvdla_dev->fixed_rate_clk_spll1_fout1);
+ nvdla_dev->fixed_rate_clk_spll1_fout1 = NULL;
+ dev_err(&pdev->dev, "failed to get fixed_rate_clk_spll1_fout1 clk: %d.\n", ret);
+ return ret;
+ }
+
//nvdla_dev->rstc_e31_core = devm_reset_control_get_optional_exclusive(
nvdla_dev->rstc_e31_core = devm_reset_control_get_optional(
&pdev->dev, "e31_core");
@@ -976,17 +1043,29 @@ int npu_disable_clock(struct nvdla_device *ndev)
{
npu_disable_mbox_clock(ndev);
clk_disable_unprepare(ndev->e31_core_clk);
- return npu_clk_gate_set(ndev->numa_id, false);
+
+ clk_disable_unprepare(ndev->core_clk);
+
+ clk_disable_unprepare(ndev->cfg_clk);
+ return 0;
}
int npu_enable_clock(struct nvdla_device *ndev)
{
int ret;
- ret = npu_clk_gate_set(ndev->numa_id, true);
- if (ret < 0) {
- dla_error("npu_clk_gate_set failed.\n");
+
+ ret = clk_prepare_enable(ndev->cfg_clk);
+ if (ret) {
+ dla_error("failed to enable cfg_clk: %d\n", ret);
return ret;
}
+
+ ret = clk_prepare_enable(ndev->core_clk);
+ if (ret) {
+ dla_error("failed to enable core_clk: %d\n", ret);
+ goto core_clk;
+ }
+
ret = clk_prepare_enable(ndev->e31_core_clk);
if (ret < 0) {
dla_error("npu enable e31 core clk err.\n");
@@ -1001,7 +1080,9 @@ int npu_enable_clock(struct nvdla_device *ndev)
err_mbox_clk:
clk_disable_unprepare(ndev->e31_core_clk);
err_e31_clk:
- npu_clk_gate_set(ndev->numa_id, false);
+ clk_disable_unprepare(ndev->core_clk);
+core_clk:
+ clk_disable_unprepare(ndev->cfg_clk);
return ret;
}
diff --git a/drivers/soc/eswin/ai_driver/npu/nvdla_lowlevel.h b/drivers/soc/eswin/ai_driver/npu/nvdla_lowlevel.h
index 6d26b9470152..a5d3ab9b088e 100644
--- a/drivers/soc/eswin/ai_driver/npu/nvdla_lowlevel.h
+++ b/drivers/soc/eswin/ai_driver/npu/nvdla_lowlevel.h
@@ -42,6 +42,7 @@ int npu_create_sysfs(struct platform_device *pdev);
int npu_hardware_reset(struct nvdla_device *nvdla_dev);
int npu_dev_reset(struct nvdla_device *nvdla_dev);
+int npu_dev_assert(struct nvdla_device *nvdla_dev);
int npu_init_reset(struct nvdla_device *nvdla_dev);
void npu_dma_sid_cfg(void __iomem *npu_subsys_base, u32 sid);
diff --git a/drivers/soc/eswin/ai_driver/npu/user_context.c b/drivers/soc/eswin/ai_driver/npu/user_context.c
index 47dadc142fed..6679f371b06b 100644
--- a/drivers/soc/eswin/ai_driver/npu/user_context.c
+++ b/drivers/soc/eswin/ai_driver/npu/user_context.c
@@ -600,6 +600,20 @@ static int commit_new_io_tensor(struct user_context *uctx, void *arg)
static struct win_engine *get_engine_from_file(struct file *file);
+static int runtime_try_lock(struct user_context *uctx, struct file *file)
+{
+ struct win_engine *engine;
+ engine = get_engine_from_file(file);
+
+ if (down_trylock(&engine->runtime_sem)) {
+ return -EINTR;
+ }
+ BUG_ON(atomic_read(&uctx->lock_status) != NPU_RT_MUTX_IDLE);
+ atomic_set(&uctx->lock_status, NPU_RT_MUTX_LOCKED);
+ dla_debug("try %s, %d locked\n", __func__, __LINE__);
+ return 0;
+}
+
static int runtime_lock_request(struct user_context *uctx, struct file *file,
unsigned int cmd)
{
@@ -607,15 +621,7 @@ static int runtime_lock_request(struct user_context *uctx, struct file *file,
struct win_engine *engine;
engine = get_engine_from_file(file);
- if (cmd == ES_NPU_IOCTL_MUTEX_TRYLOCK) {
- if (down_trylock(&engine->runtime_sem)) {
- return -EINTR;
- }
- BUG_ON(atomic_read(&uctx->lock_status) != NPU_RT_MUTX_IDLE);
- atomic_set(&uctx->lock_status, NPU_RT_MUTX_LOCKED);
- dla_debug("try %s, %d locked\n", __func__, __LINE__);
-
- } else if (cmd == ES_NPU_IOCTL_MUTEX_LOCK) {
+ if (cmd == ES_NPU_IOCTL_MUTEX_LOCK) {
if (down_interruptible(&engine->runtime_sem)) {
return -EINTR;
}
@@ -893,9 +899,10 @@ static long npu_dev_ioctl(struct file *file, unsigned int cmd,
case ES_NPU_IOCTL_TASK_SUBMIT:
ret = commit_new_io_tensor(uctx, &win_arg);
break;
- case ES_NPU_IOCTL_MUTEX_LOCK:
- case ES_NPU_IOCTL_MUTEX_UNLOCK:
case ES_NPU_IOCTL_MUTEX_TRYLOCK:
+ return runtime_try_lock(uctx, file);
+ case ES_NPU_IOCTL_MUTEX_UNLOCK:
+ case ES_NPU_IOCTL_MUTEX_LOCK:
ret = runtime_lock_request(uctx, file, cmd);
break;
case ES_NPU_IOCTL_HETERO_CMD:
diff --git a/drivers/staging/media/eswin/dewarp/vvcam_dwe_driver.c b/drivers/staging/media/eswin/dewarp/vvcam_dwe_driver.c
index f1ab8835ceac..d462277fecc6 100644
--- a/drivers/staging/media/eswin/dewarp/vvcam_dwe_driver.c
+++ b/drivers/staging/media/eswin/dewarp/vvcam_dwe_driver.c
@@ -74,6 +74,8 @@
#include <linux/eswin-win2030-sid-cfg.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
+#include <linux/devfreq.h>
+#include <linux/pm_opp.h>
#include "dw200_fe.h"
#include "dw200_ioctl.h"
@@ -1041,6 +1043,66 @@ static int vvcam_sys_reset_release(dw_clk_rst_t *dw_crg)
} \
} while (0)
+int dewarp_set_aclk_rate(dw_clk_rst_t *dw_crg, unsigned long *rate)
+{
+ int ret;
+
+ *rate = clk_round_rate(dw_crg->aclk, *rate);
+ if (*rate > 0) {
+ ret = clk_set_rate(dw_crg->aclk, *rate);
+ if (ret) {
+ dev_err(dw_crg->dev, "failed to set aclk: %d\n", ret);
+ return ret;
+ }
+ dev_info(dw_crg->dev, "set dev rate to %ldHZ\n", *rate);
+ }
+ return 0;
+}
+
+int dewarp_get_aclk_rate(dw_clk_rst_t *dw_crg)
+{
+ unsigned long rate;
+ rate = clk_get_rate(dw_crg->aclk);
+ dev_info(dw_crg->dev, "get dev rate %ldHZ\n", rate);
+ return rate;
+}
+
+/* devfreq target function to set frequency */
+static int dewarp_devfreq_target(struct device *dev, unsigned long *freq, u32 flags)
+{
+ struct es_dewarp_driver_dev *pdriver_dev = dev_get_drvdata(dev);
+ struct dw200_subdev *pdwe_dev;
+
+ pdwe_dev = &pdriver_dev->hw_dev;
+ return dewarp_set_aclk_rate(&pdwe_dev->dw_crg, freq);
+}
+
+static int dewarp_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
+{
+ struct es_dewarp_driver_dev *pdriver_dev = dev_get_drvdata(dev);
+ struct dw200_subdev *pdwe_dev;
+
+ pdwe_dev = &pdriver_dev->hw_dev;
+ unsigned long rate;
+
+ rate = dewarp_get_aclk_rate(&pdwe_dev->dw_crg);
+ if (rate <= 0) {
+ dev_err(dev, "failed to get aclk: %ld\n", rate);
+ return rate;
+ }
+ *freq = rate;
+ return 0;
+}
+
+/* devfreq profile */
+static struct devfreq_dev_profile dewarp_devfreq_profile = {
+ .initial_freq = VVCAM_AXI_CLK_HIGHEST,
+ .timer = DEVFREQ_TIMER_DELAYED,
+ .polling_ms = 1000, /* Poll every 1000ms to monitor load */
+ .target = dewarp_devfreq_target,
+ .get_cur_freq = dewarp_devfreq_get_cur_freq,
+};
+
static int vvcam_sys_clk_config(dw_clk_rst_t *dw_crg)
{
int ret = 0;
@@ -1212,6 +1274,7 @@ static int es_dewarp_probe(struct platform_device *pdev)
struct es_dewarp_driver_dev *pdriver_dev;
struct dw200_subdev *pdwe_dev;
char debug_dw200_reset[64] = "dw200_reset";
+ struct devfreq *df;
int id = 0;
if (pdev->id >= NUM_DEVICES) {
@@ -1246,6 +1309,19 @@ static int es_dewarp_probe(struct platform_device *pdev)
return ret;
}
+ /* Add OPP table from device tree */
+ ret = dev_pm_opp_of_add_table(&pdev->dev);
+ if (ret) {
+ pr_err("%s, %d, Failed to add OPP table\n", __func__, __LINE__);
+ return ret;
+ }
+
+ df = devm_devfreq_add_device(&pdev->dev, &dewarp_devfreq_profile, "userspace", NULL);
+ if (IS_ERR(df)) {
+ pr_err("%s, %d, add devfreq failed\n", __func__, __LINE__);
+ return ret;
+ }
+
pdwe_dev->dw_crg.dev = &pdev->dev;
ret = vvcam_sys_clk_prepare(&pdwe_dev->dw_crg);
if (ret) {
@@ -1387,6 +1463,7 @@ static int es_dewarp_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
static int dewarp_runtime_suspend(struct device *dev)
{
struct es_dewarp_driver_dev *pdriver_dev = dev_get_drvdata(dev);
@@ -1462,6 +1539,7 @@ static int dewarp_resume(struct device *dev)
return ret;
}
+#endif
static const struct dev_pm_ops dewarp_pm_ops = {
SET_RUNTIME_PM_OPS(dewarp_runtime_suspend, dewarp_runtime_resume, NULL)
diff --git a/drivers/staging/media/eswin/hae/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/staging/media/eswin/hae/hal/os/linux/kernel/gc_hal_kernel_driver.c
index a428dcd84af5..91d7c78566d5 100644
--- a/drivers/staging/media/eswin/hae/hal/os/linux/kernel/gc_hal_kernel_driver.c
+++ b/drivers/staging/media/eswin/hae/hal/os/linux/kernel/gc_hal_kernel_driver.c
@@ -1393,11 +1393,16 @@ static int __devinit viv_dev_probe(struct platform_device *pdev)
if (platform->ops->adjustParam) {
/* Override default module param. */
+ gceSTATUS status;
activeDeviceCount++;
- if(gcvSTATUS_MORE_DATA == platform->ops->adjustParam(platform, &platform->params)){
+ status = platform->ops->adjustParam(platform, &platform->params);
+ if(gcvSTATUS_MORE_DATA == status){
gcmkPRINT("hae loaded first device, waiting for another...");
_SyncModuleParam(&platform->params);
return 0;
+ } else if (!gcmIS_SUCCESS(status)){
+ gcmkPRINT("hae adjust param error, status=%d", status);
+ return -1;
}
}
diff --git a/drivers/staging/media/eswin/hae/hal/os/linux/kernel/platform/eswin/gc_hal_kernel_platform_win2030.c b/drivers/staging/media/eswin/hae/hal/os/linux/kernel/platform/eswin/gc_hal_kernel_platform_win2030.c
index 580267770992..f2cebd459f41 100644
--- a/drivers/staging/media/eswin/hae/hal/os/linux/kernel/platform/eswin/gc_hal_kernel_platform_win2030.c
+++ b/drivers/staging/media/eswin/hae/hal/os/linux/kernel/platform/eswin/gc_hal_kernel_platform_win2030.c
@@ -90,6 +90,9 @@
# include <linux/clk.h>
# include <linux/reset.h>
#endif
+#include <linux/devfreq.h>
+#include <linux/pm_opp.h>
+#define G2D_HILOAD_CLK 1040000000
/* Disable MSI for internal FPGA build except PPC */
#if gcdFPGA_BUILD
@@ -159,7 +162,10 @@ struct gpu_power_domain {
int num_domains;
struct device **power_dev;
struct clk *clks[gcdDEVICE_COUNT][gcvCLKS_COUNT];
+ struct device *dev[gcdDEVICE_COUNT];
+ struct devfreq *df[gcdDEVICE_COUNT];
};
+static struct gpu_power_domain gpd;
static struct _gpu_reset {
struct reset_control *rsts[gcdDEVICE_COUNT][gcvRST_COUNT];
@@ -217,7 +223,57 @@ static void show_clk_status(int dieIndex)
iounmap(g2d_top_ptr);
}
-struct gpu_power_domain gpd;
+#if defined(CONFIG_PM_DEVFREQ)
+static int g2d_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) {
+ int i, j;
+ unsigned long rate = *freq;
+ int ret = -1;
+ struct clk *aclk;
+
+ for (i = 0; i < gpd.num_domains; i++) {
+ if (gpd.dev[i] != dev) continue;
+ for (j = 0; j < nc_of_clks; j++) {
+ if (strcmp("g2d_clk", clk_names[j]) && strcmp("g2d_aclk", clk_names[j])) continue;
+ aclk = gpd.clks[i][j];
+ rate = clk_round_rate(aclk, rate);
+ if (rate > 0) {
+ ret = clk_set_rate(aclk, rate);
+ if (ret) {
+ dev_err(dev, "failed to set %s clk: %d\n", clk_names[j], ret);
+ return ret;
+ }
+ }
+ dev_info(dev, "set %s rate to %ldHZ\n", clk_names[j], rate);
+ }
+ }
+ if (!ret) {
+ *freq = rate;
+ return 0;
+ } else {
+ dev_err(dev, "set rate to %ldHZ\n failed", rate);
+ return -1;
+ }
+}
+static int g2d_devfreq_get_cur_freq(struct device *dev, unsigned long *freq) {
+ int i, j;
+ for (i = 0; i < gpd.num_domains; i++) {
+ if (gpd.dev[i] != dev) continue;
+ for (j = 0; j < nc_of_clks; j++) {
+ if (!strcmp("g2d_clk", clk_names[j])) {
+ return clk_get_rate(gpd.clks[i][j]);
+ }
+ }
+ }
+ return 0;
+}
+static struct devfreq_dev_profile g2d_devfreq_profile = {
+ .initial_freq = G2D_HILOAD_CLK,
+ .timer = DEVFREQ_TIMER_DELAYED,
+ .polling_ms = 1000, /* Poll every 1000ms to monitor load */
+ .target = g2d_devfreq_target,
+ .get_cur_freq = g2d_devfreq_get_cur_freq,
+};
+#endif
gceSTATUS
_set_clock(gcsPLATFORM *Platform, gctUINT32 DevIndex, gceCORE GPU, gctBOOL Enable)
@@ -411,6 +467,9 @@ static int gpu_parse_dt(struct platform_device *pdev, gcsMODULE_PARAMETERS *para
const char *str;
int dieIndex = 0;
int peerDieIndex;
+#if defined(CONFIG_PM_DEVFREQ)
+ struct devfreq *df;
+#endif
gcmSTATIC_ASSERT(gcvCORE_COUNT == gcmCOUNTOF(core_names),
"core_names array does not match core types");
@@ -548,7 +607,18 @@ static int gpu_parse_dt(struct platform_device *pdev, gcsMODULE_PARAMETERS *para
}
g2d_reset(&pdev->dev, dieIndex, 1);
-
+#if defined(CONFIG_PM_DEVFREQ)
+ if (dev_pm_opp_of_add_table(&pdev->dev)) {
+ gcmkPRINT("%s, %d, Failed to add OPP table", __func__, __LINE__);
+ return gcvSTATUS_INVALID_OBJECT;
+ }
+ df = devm_devfreq_add_device(&pdev->dev, &g2d_devfreq_profile, "userspace", NULL);
+ if (IS_ERR(df)) {
+ gcmkPRINT("%s, %d, add devfreq failed", __func__, __LINE__);
+ return gcvSTATUS_INVALID_OBJECT;
+ }
+ gpd.df[dieIndex] = df;
+#endif
show_clk_status(dieIndex);
params->devCount++;
@@ -775,10 +845,18 @@ gceSTATUS
_AdjustParam(gcsPLATFORM *Platform, gcsMODULE_PARAMETERS *Args)
{
int ret;
+#if defined(CONFIG_PM_DEVFREQ)
+ int i;
+#endif
#if gcdSUPPORT_DEVICE_TREE_SOURCE
ret = gpu_parse_dt(Platform->device, Args);
- if(!ret){
+ if(gcmIS_SUCCESS(ret)){
gpu_add_power_domains(Platform->device, Args);
+#if defined(CONFIG_PM_DEVFREQ)
+ for (i = 0; i < gcdDEVICE_COUNT; i++) {
+ gpd.dev[i] = Args->devices[i];
+ }
+#endif
}
#elif USE_LINUX_PCIE
struct _gcsPLATFORM_PCIE *pcie_platform = (struct _gcsPLATFORM_PCIE *)Platform;
@@ -1204,6 +1282,9 @@ gceSTATUS _DmaExit(gcsPLATFORM *Platform)
struct device *dev = Platform->params.devices[i];
if (!dev) continue;
g2d_reset(dev, i, 0);
+#if defined(CONFIG_PM_DEVFREQ)
+ devm_devfreq_remove_device(dev, gpd.df[i]);
+#endif
show_clk_status(i);
}
return gcvSTATUS_OK;
diff --git a/drivers/staging/media/eswin/vdec/hantro_dec.c b/drivers/staging/media/eswin/vdec/hantro_dec.c
index 7c4de300d6e6..780b2561ab20 100644
--- a/drivers/staging/media/eswin/vdec/hantro_dec.c
+++ b/drivers/staging/media/eswin/vdec/hantro_dec.c
@@ -106,6 +106,11 @@
#include "dts_parser.h"
#include "vdec_allocator.h"
+#if defined(CONFIG_PM_DEVFREQ)
+#include <linux/devfreq.h>
+#include <linux/pm_opp.h>
+#endif
+
#define LOG_TAG DEC_DEV_NAME ":main"
#include "vc_drv_log.h"
@@ -3945,10 +3950,68 @@ int d1_clk_reset_init(void)
return 0;
}
+#if defined(CONFIG_PM_DEVFREQ)
+static int vdec_devfreq_target(struct device *dev, unsigned long *freq, u32 flags)
+{
+ int ret;
+ vdec_clk_rst_t *vcrt = dev_get_drvdata(dev);
+
+ LOG_DBG("%s:%d, dev = %p, freq = %lu\n", __func__, __LINE__, dev, *freq);
+ *freq = clk_round_rate(vcrt->jd_clk, *freq);
+ if (*freq > 0) {
+ ret = clk_set_rate(vcrt->jd_clk, *freq);
+ if (ret) {
+ LOG_ERR("%d: failed to set jd_clk: %d\n", __LINE__, ret);
+ return ret;
+ }
+ LOG_DBG("set jd_clk to %ldHZ\n", *freq);
+ } else {
+ LOG_ERR("%d: failed to round rate for jd_clk %ld\n", __LINE__, *freq);
+ return -1;
+ }
+
+ *freq = clk_round_rate(vcrt->vd_clk, *freq);
+ if (*freq > 0) {
+ ret = clk_set_rate(vcrt->vd_clk, *freq);
+ if (ret) {
+ LOG_ERR("%d: failed to set vd_clk: %d\n", __LINE__, ret);
+ return ret;
+ }
+ LOG_DBG("set vd_clk to %ldHZ\n", *freq);
+ } else {
+ LOG_ERR("%d: failed to round rate for vd_clk %ld\n", __LINE__, *freq);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int vdec_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
+{
+ vdec_clk_rst_t *vcrt = dev_get_drvdata(dev);
+
+ *freq = clk_get_rate(vcrt->vd_clk);
+
+ return 0;
+}
+
+/** devfreq profile */
+static struct devfreq_dev_profile vdec_devfreq_profile = {
+ .initial_freq = VDEC_SYS_CLK_HIGHEST,
+ .timer = DEVFREQ_TIMER_DELAYED,
+ .polling_ms = 1000, /** Poll every 1000ms to monitor load */
+ .target = vdec_devfreq_target,
+ .get_cur_freq = vdec_devfreq_get_cur_freq,
+};
+#endif /** CONFIG_PM_DEVFREQ*/
+
static int hantro_vdec_probe(struct platform_device *pdev)
{
int numa_id;
int ret, vdec_dev_num = 0;
+#if defined(CONFIG_PM_DEVFREQ)
+ struct devfreq *df = NULL;
+#endif
vdec_clk_rst_t *vcrt = devm_kzalloc(&pdev->dev, sizeof(vdec_clk_rst_t), GFP_KERNEL);
if (!vcrt) {
LOG_ERR("malloc drvdata failed\n");
@@ -3970,6 +4033,20 @@ static int hantro_vdec_probe(struct platform_device *pdev)
LOG_INFO("initializing vdec, numa id %d\n", numa_id);
+#if defined(CONFIG_PM_DEVFREQ)
+ /* Add OPP table from device tree */
+ ret = dev_pm_opp_of_add_table(&pdev->dev);
+ if (ret) {
+ LOG_ERR("%s, %d, failed to add OPP table\n", __func__, __LINE__);
+ return -1;
+ }
+ df = devm_devfreq_add_device(&pdev->dev, &vdec_devfreq_profile, "userspace", NULL);
+ if (IS_ERR(df)) {
+ LOG_ERR("%s, %d, add devfreq failed\n", __func__, __LINE__);
+ return -1;
+ }
+#endif /** CONFIG_PM_DEVFREQ*/
+
ret = vdec_sys_reset_init(pdev, vcrt);
if (ret < 0) {
LOG_ERR("vdec: reset initialization failed");
diff --git a/drivers/staging/media/eswin/venc/vc8000e_driver.c b/drivers/staging/media/eswin/venc/vc8000e_driver.c
index 97743c8172cd..0244069626c1 100644
--- a/drivers/staging/media/eswin/venc/vc8000e_driver.c
+++ b/drivers/staging/media/eswin/venc/vc8000e_driver.c
@@ -15,6 +15,11 @@
#include <linux/dma-mapping.h>
#include <linux/eswin-win2030-sid-cfg.h>
+#if defined(CONFIG_PM_DEVFREQ)
+#include <linux/devfreq.h>
+#include <linux/pm_opp.h>
+#endif
+
#include "vc8000_driver.h"
#define LOG_TAG VENC_DEV_NAME ":main"
@@ -821,12 +826,72 @@ int enc_reset_system(u32 core_id) {
}
/** end of interface functions*/
+#if defined(CONFIG_PM_DEVFREQ)
+static int venc_devfreq_target(struct device *dev, unsigned long *freq, u32 flags)
+{
+ int ret;
+ venc_dev_prvdata *prvdata = dev_get_drvdata(dev);
+ venc_clk_rst_t *vcrt = &prvdata->vcrt;
+
+ LOG_DBG("%s:%d, dev = %p, freq = %lu\n", __func__, __LINE__, dev, *freq);
+ *freq = clk_round_rate(vcrt->je_clk, *freq);
+ if (*freq > 0) {
+ ret = clk_set_rate(vcrt->je_clk, *freq);
+ if (ret) {
+ LOG_ERR("Video encoder: failed to set je_clk: %d\n", ret);
+ return ret;
+ }
+ LOG_DBG("VE set je_clk to %ldHZ\n", *freq);
+ } else {
+ LOG_ERR("Video encoder: failed to round rate for je_clk %ld\n", *freq);
+ return -1;
+ }
+
+ *freq = clk_round_rate(vcrt->ve_clk, *freq);
+ if (*freq > 0) {
+ ret = clk_set_rate(vcrt->ve_clk, *freq);
+ if (ret) {
+ LOG_ERR("Video encoder: failed to set ve_clk: %d\n", ret);
+ return ret;
+ }
+ LOG_DBG("VE set ve_clk to %ldHZ\n", *freq);
+ } else {
+ LOG_ERR("Video encoder: failed to round rate for ve_clk %ld\n", *freq);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int venc_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
+{
+ venc_dev_prvdata *prvdata = dev_get_drvdata(dev);
+ venc_clk_rst_t *vcrt = &prvdata->vcrt;
+
+ *freq = clk_get_rate(vcrt->ve_clk);
+
+ return 0;
+}
+
+/** devfreq profile */
+static struct devfreq_dev_profile venc_devfreq_profile = {
+ .initial_freq = VENC_SYS_CLK_HIGHEST,
+ .timer = DEVFREQ_TIMER_DELAYED,
+ .polling_ms = 1000, /** Poll every 1000ms to monitor load */
+ .target = venc_devfreq_target,
+ .get_cur_freq = venc_devfreq_get_cur_freq,
+};
+#endif /** CONFIG_PM_DEVFREQ*/
+
static int hantro_venc_probe(struct platform_device *pdev)
{
static int pdev_count = 0;
int ret, numa_id, venc_dev_num = 0;
venc_dev_prvdata *prvdata = devm_kzalloc(&pdev->dev, sizeof(venc_dev_prvdata), GFP_KERNEL);
venc_clk_rst_t *vcrt = &prvdata->vcrt;
+#if defined(CONFIG_PM_DEVFREQ)
+ struct devfreq *df = NULL;
+#endif
venc_dev_num = venc_device_nodes_check();
if (venc_dev_num <= 0) {
@@ -842,6 +907,20 @@ static int hantro_venc_probe(struct platform_device *pdev)
LOG_INFO("initializing venc, numa id %d\n", numa_id);
+#if defined(CONFIG_PM_DEVFREQ)
+ /* Add OPP table from device tree */
+ ret = dev_pm_opp_of_add_table(&pdev->dev);
+ if (ret) {
+ LOG_ERR("%s, %d, Failed to add OPP table\n", __func__, __LINE__);
+ return -1;
+ }
+ df = devm_devfreq_add_device(&pdev->dev, &venc_devfreq_profile, "userspace", NULL);
+ if (IS_ERR(df)) {
+ LOG_ERR("%s, %d, add devfreq failed\n", __func__, __LINE__);
+ return -1;
+ }
+#endif /** CONFIG_PM_DEVFREQ*/
+
if (!numa_id) {
ret = venc_sys_reset_init(pdev, vcrt);
if (ret < 0) {
diff --git a/include/linux/dmabuf-heap-import-helper.h b/include/linux/dmabuf-heap-import-helper.h
index 9a474f6594e7..d4acd7c5177c 100644
--- a/include/linux/dmabuf-heap-import-helper.h
+++ b/include/linux/dmabuf-heap-import-helper.h
@@ -132,4 +132,6 @@ struct heap_mem *common_dmabuf_heap_rsv_iova_map(struct heap_root *root, int fd,
void common_dmabuf_heap_rsv_iova_unmap(struct heap_mem *heap_obj);
void common_dmabuf_heap_rsv_iova_uninit(struct heap_root *root);
+int remap_malloc_buf(unsigned long addr, size_t len, bool uncaced);
+
#endif
diff --git a/include/uapi/linux/dma_memcp.h b/include/uapi/linux/dma_memcp.h
new file mode 100644
index 000000000000..3cb75a348ba8
--- /dev/null
+++ b/include/uapi/linux/dma_memcp.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * ESWIN DMA MEMCP Driver
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: Zonglin Geng <gengzonglin@eswincomputing.com>
+ * Yuyang Cong <congyuyang@eswincomputing.com>
+ */
+
+#ifndef ES_DMA_MEMCP_H
+#define ES_DMA_MEMCP_H
+
+/**
+ * struct esw_memcp_f2f_cmd - Represents a memory copy command from source to destination.
+ *
+ * @src_fd: File descriptor of the source buffer.
+ * @src_offset: Offset in the source buffer from which data copy starts.
+ * @dst_fd: File descriptor of the destination buffer.
+ * @dst_offset: Offset in the destination buffer where data will be copied to.
+ * @len: Length of the data to be copied, in bytes.
+ * @timeout: Timeout for the memory copy operation, in milliseconds.
+ */
+struct esw_memcp_f2f_cmd {
+ int src_fd;
+ int src_offset;
+ int dst_fd;
+ int dst_offset;
+ size_t len;
+ int timeout;
+};
+
+/**
+ * struct esw_cmdq_query - Represents the command queue status structure.
+ *
+ * @status: Status of the queue, 0 indicates idle, 1 indicates busy.
+ * @task_count: Current number of tasks in the queue.
+ */
+struct esw_cmdq_query {
+ int status;
+ int task_count;
+};
+
+#define ESW_MEMCP_MAGIC 'M'
+#define ESW_CMDQ_ADD_TASK _IOW(ESW_MEMCP_MAGIC, 1, struct esw_memcp_f2f_cmd)
+#define ESW_CMDQ_SYNC _IO(ESW_MEMCP_MAGIC, 2)
+#define ESW_CMDQ_QUERY _IOR(ESW_MEMCP_MAGIC, 3, struct esw_cmdq_query)
+
+#endif
diff --git a/sound/soc/codecs/eswin/es8328.c b/sound/soc/codecs/eswin/es8328.c
index 29d7c5f0c612..26aedb86a7c9 100644
--- a/sound/soc/codecs/eswin/es8328.c
+++ b/sound/soc/codecs/eswin/es8328.c
@@ -6,20 +6,24 @@
*
* Author: Sean Cross <xobs@kosagi.com>
*/
-
-/*
- * Copyright (C) 2021 ESWIN, Inc. All rights reserved.
+/*****************************************************************************
+ * ESWIN codec driver
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
+ * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation, version 2.
*
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
@@ -94,8 +98,13 @@ static const char * const supply_names[ES8328_SUPPLY_NUM] = {
SNDRV_PCM_FMTBIT_S18_3LE | \
SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S24_3LE | \
SNDRV_PCM_FMTBIT_S32_LE)
+#define EVB_BOARD 1
+#define DVB_BOARD 2
+#define Z530_BOARD 3
+
struct es8328_priv {
struct regmap *regmap;
struct clk *clk;
@@ -691,6 +700,10 @@ static const struct snd_soc_dapm_route es8328_dapm_routes[] = {
static int es8328_mute(struct snd_soc_dai *dai, int mute, int direction)
{
+ if ((mute == 1) && (direction == 0)) {
+ snd_soc_component_write(dai->component, ES8328_DACPOWER, 0xc0);
+ }
+
return snd_soc_component_update_bits(dai->component, ES8328_DACCONTROL3,
ES8328_DACCONTROL3_DACMUTE,
mute ? ES8328_DACCONTROL3_DACMUTE : 0);
@@ -785,6 +798,13 @@ static int es8328_hw_params(struct snd_pcm_substream *substream,
ES8328_ADCCONTROL4_ADCWL_MASK,
wl << ES8328_ADCCONTROL4_ADCWL_SHIFT);
+ if (params_rate(params) <= 48000) {
+ snd_soc_component_update_bits(component, reg, ES8328_DACCONTROL2_DOUBLESPEED, 0);
+ } else {
+ snd_soc_component_update_bits(component, reg,
+ ES8328_DACCONTROL2_DOUBLESPEED, ES8328_DACCONTROL2_DOUBLESPEED);
+ }
+
return snd_soc_component_update_bits(component, reg, ES8328_RATEMASK, ratio);
}
@@ -894,7 +914,7 @@ static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai,
/* Set MIC PGA Volume */
snd_soc_component_write(component, ES8328_ADCCONTROL1, 0x88);
- if (es8328->eswin_plat == 2) {
+ if (es8328->eswin_plat == DVB_BOARD) {
if (gpiod_get_value(es8328->front_jack_gpio) == 1 && gpiod_get_value(es8328->back_jack_gpio) == 0) {
/* Select default capture path ---> LIN1 */
snd_soc_component_write(component, ES8328_ADCCONTROL2, 0);
@@ -902,6 +922,9 @@ static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai,
/* Select default capture path ---> LIN2 */
snd_soc_component_write(component, ES8328_ADCCONTROL2, 0x50);
}
+ } else if (es8328->eswin_plat == Z530_BOARD) {
+ /* Select default capture path ---> LIN1 */
+ snd_soc_component_write(component, ES8328_ADCCONTROL2, 0);
} else {
/* Select default capture path ---> phone mic */
snd_soc_component_write(component, ES8328_ADCCONTROL2, 0xf0);
@@ -967,6 +990,7 @@ static int es8328_set_bias_level(struct snd_soc_component *component,
0);
break;
}
+
return 0;
}
@@ -981,7 +1005,7 @@ static const struct snd_soc_dai_ops es8328_dai_ops = {
static struct snd_soc_dai_driver es8328_dai[3] = {
{
- .name = "es8328-0-hifi-analog",
+ .name = "es8328-0",
.playback = {
.stream_name = "Playback",
.channels_min = MIN_CHANNEL_NUM,
@@ -1000,7 +1024,7 @@ static struct snd_soc_dai_driver es8328_dai[3] = {
.symmetric_rate = 1,
},
{
- .name = "es8328-1-hifi-analog",
+ .name = "es8328-1",
.playback = {
.stream_name = "Playback",
.channels_min = MIN_CHANNEL_NUM,
@@ -1019,7 +1043,7 @@ static struct snd_soc_dai_driver es8328_dai[3] = {
.symmetric_rate = 1,
},
{
- .name = "es8328-2-hifi-analog",
+ .name = "es8328-2",
.playback = {
.stream_name = "Playback",
.channels_min = MIN_CHANNEL_NUM,
@@ -1117,6 +1141,7 @@ static int es8328_open(struct snd_soc_component *component,
}
static const struct snd_soc_component_driver es8328_component_driver = {
+ .name = "es8388",
.probe = es8328_component_probe,
.remove = es8328_remove,
.suspend = es8328_suspend,
@@ -1184,7 +1209,7 @@ int es8328_probe(struct device *dev, struct regmap *regmap)
}
dev_info(dev, "eswin platform:%d\n", es8328->eswin_plat);
- if (es8328->eswin_plat == 2) {
+ if (es8328->eswin_plat == DVB_BOARD) {
es8328->front_jack_gpio = devm_gpiod_get(dev, "front-jack", GPIOD_IN);
ret = IS_ERR(es8328->front_jack_gpio);
if(ret) {
diff --git a/sound/soc/codecs/eswin/es8328.h b/sound/soc/codecs/eswin/es8328.h
index 70515466a4b2..fb7068f8f794 100644
--- a/sound/soc/codecs/eswin/es8328.h
+++ b/sound/soc/codecs/eswin/es8328.h
@@ -2,20 +2,24 @@
/*
* es8328.h -- ES8328 ALSA SoC Audio driver
*/
-
-/*
- * Copyright (C) 2021 ESWIN, Inc. All rights reserved.
+/*****************************************************************************
+ * ESWIN codec driver
*
- * This program is free software; you can redistribute it and/or modify
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
*
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#ifndef _ES8328_H
diff --git a/sound/soc/eswin/Kconfig b/sound/soc/eswin/Kconfig
index 7c930a329daa..0b25aa84a586 100644
--- a/sound/soc/eswin/Kconfig
+++ b/sound/soc/eswin/Kconfig
@@ -1,11 +1,8 @@
-menu "SND ESWIN SOC"
-
+# SPDX-License-Identifier: GPL-2.0-only
config SND_ESWIN_DW_I2S
tristate "Eswin Dw I2S Device Driver"
select SND_SOC_GENERIC_DMAENGINE_PCM
help
Say Y or M if you want to add support for I2S driver for
Eswin dw I2S device. The device supports up to
- a maximum of 8 channels each for play and record.
-
-endmenu
+ a maximum of 8 channels each for play and record.
\ No newline at end of file
diff --git a/sound/soc/eswin/Makefile b/sound/soc/eswin/Makefile
index 2c133c695dbe..469d77a9732d 100644
--- a/sound/soc/eswin/Makefile
+++ b/sound/soc/eswin/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
# ESWIN Platform Support
-snd-soc-i2s-objs := esw-i2s.o esw-audio-proc.o
+snd-soc-i2s-objs := esw-i2s.o esw-audio-proc.o esw-sof-dai.o esw-dma.o
obj-$(CONFIG_SND_ESWIN_DW_I2S) += snd-soc-i2s.o
\ No newline at end of file
diff --git a/sound/soc/eswin/esw-audio-proc.c b/sound/soc/eswin/esw-audio-proc.c
index 17b7c21f7b69..f21e269af657 100644
--- a/sound/soc/eswin/esw-audio-proc.c
+++ b/sound/soc/eswin/esw-audio-proc.c
@@ -46,9 +46,7 @@ typedef enum
AENC_SEND_FRAME,
AENC_GET_STREAM,
AENC_ENCODE_FRAME,
- AGC_PROCESS,
- ANS_PROCESS,
- AEC_PROCESS,
+ RTC_PROCESS, //rtc processing for aec, ans, agc
DRC_PROCESS,
EQ_PROCESS,
DCBLOCK_PROCESS,
@@ -142,15 +140,15 @@ static void show_ao_data(struct seq_file *m)
seq_printf(m, "-----------------------------------------------------------------------------"
"-----------------------------------------------------\n");
seq_printf(m, "audio argorithm performance(ns/1ms):\n");
- seq_printf(m, "%-14s%-14s%-14s%-14s%-14s%-14s%-14s%-14s%-14s\n", "agc", "ans", "eq", "hpf",
+ seq_printf(m, "%-14s%-14s%-14s%-14s%-14s%-14s%-14s%-14s\n", "rtc", "eq", "hpf",
"volume", "src-host","src-dai", "host", "dai");
seq_printf(m, "------------------------------------------------------------------------------"
"----------------------------------------------------\n");
- seq_printf(m, "%-14d%-14d%-14d%-14d%-14d%-14d%-14d%-14d%-14d\n", g_perf_data[AO][AGC_PROCESS],
- g_perf_data[AO][ANS_PROCESS],g_perf_data[AO][EQ_PROCESS],
- g_perf_data[AO][DCBLOCK_PROCESS],g_perf_data[AO][VOLUME_PROCESS],
- g_perf_data[AO][SRC_HOST_PROCESS],g_perf_data[AO][SRC_DAI_PROCESS],
- g_perf_data[AO][HOST_PROCESS], g_perf_data[AO][DAI_PROCESS]);
+ seq_printf(m, "%-14d%-14d%-14d%-14d%-14d%-14d%-14d%-14d\n", g_perf_data[AO][RTC_PROCESS],
+ g_perf_data[AO][EQ_PROCESS],g_perf_data[AO][DCBLOCK_PROCESS],
+ g_perf_data[AO][VOLUME_PROCESS],g_perf_data[AO][SRC_HOST_PROCESS],
+ g_perf_data[AO][SRC_DAI_PROCESS],g_perf_data[AO][HOST_PROCESS],
+ g_perf_data[AO][DAI_PROCESS]);
seq_printf(m, "\n");
seq_printf(m,"-----------------------------------------------------AO PERF STATISTIC END"
"-----------------------------------------------------\n");
@@ -173,14 +171,14 @@ static void show_ai_data(struct seq_file *m)
seq_printf(m, "-----------------------------------------------------------------------------"
"-----------------------------------------------------\n");
seq_printf(m, "audio argorithm performance(ns/1ms):\n");
- seq_printf(m, "%-14s%-14s%-14s%-14s%-14s%-14s%-14s%-14s%-14s%-14s\n", "agc", "ans", "drc", "eq",
+ seq_printf(m, "%-14s%-14s%-14s%-14s%-14s%-14s%-14s%-14s%-14s\n", "rtc", "drc", "eq",
"hpf", "volume","src-host", "src-dai", "host", "dai");
seq_printf(m, "------------------------------------------------------------------------------"
"----------------------------------------------------\n");
- seq_printf(m, "%-14d%-14d%-14d%-14d%-14d%-14d%-14d%-14d%-14d%-14d\n", g_perf_data[AI][AGC_PROCESS],
- g_perf_data[AI][ANS_PROCESS],g_perf_data[AI][DRC_PROCESS], g_perf_data[AI][EQ_PROCESS],
- g_perf_data[AI][DCBLOCK_PROCESS], g_perf_data[AI][VOLUME_PROCESS],g_perf_data[AI][SRC_HOST_PROCESS],
- g_perf_data[AI][SRC_DAI_PROCESS], g_perf_data[AI][HOST_PROCESS], g_perf_data[AI][DAI_PROCESS]);
+ seq_printf(m, "%-14d%-14d%-14d%-14d%-14d%-14d%-14d%-14d%-14d\n", g_perf_data[AI][RTC_PROCESS],
+ g_perf_data[AI][DRC_PROCESS], g_perf_data[AI][EQ_PROCESS], g_perf_data[AI][DCBLOCK_PROCESS],
+ g_perf_data[AI][VOLUME_PROCESS], g_perf_data[AI][SRC_HOST_PROCESS], g_perf_data[AI][SRC_DAI_PROCESS],
+ g_perf_data[AI][HOST_PROCESS], g_perf_data[AI][DAI_PROCESS]);
seq_printf(m, "\n");
seq_printf(m,"-----------------------------------------------------AI PERF STATISTIC END"
"-----------------------------------------------------\n");
diff --git a/sound/soc/eswin/esw-dai.h b/sound/soc/eswin/esw-dai.h
new file mode 100644
index 000000000000..dfe49c950de0
--- /dev/null
+++ b/sound/soc/eswin/esw-dai.h
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESWIN audio driver
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: DengLei <denglei@eswincomputing.com>
+ */
+
+#ifndef __ESWIN_DAI_H__
+#define __ESWIN_DAI_H__
+
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include "esw-i2s.h"
+
+struct esw_ring_buffer {
+ uint64_t write;
+ uint64_t read;
+ uint64_t buffer_size;
+};
+
+/* ringbuffer total size 2M
+ * |<--comp p 512k-->|<--comp c 512k-->|<--pcm p 512k-->|<--pcm c 512k-->|
+ */
+#define DSP_RB_COMP_SIZE 0x100000
+#define DSP_RB_PCM_P_SZIE 0x80000
+#define DSP_RB_PCM_C_SZIE 0x80000
+#define DSP_RB_POS_SZIE sizeof(struct esw_ring_buffer)
+#define DSP_RB_DATA_SZIE (DSP_RB_PCM_P_SZIE - DSP_RB_POS_SZIE)
+
+#define DSP_RING_BUFFER_IOVA 0xff600000
+
+int esw_sof_dma_init(struct i2s_dev *chip);
+int esw_sof_dma_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream);
+
+int esw_sof_dma_trigger(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream, int cmd);
+
+int esw_sof_dma_hw_params(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params);
+
+int esw_sof_dma_close(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream);
+
+int esw_pcm_dma_dai_register(struct i2s_dev *chip);
+
+#endif
\ No newline at end of file
diff --git a/sound/soc/eswin/esw-dma.c b/sound/soc/eswin/esw-dma.c
new file mode 100644
index 000000000000..387974d16270
--- /dev/null
+++ b/sound/soc/eswin/esw-dma.c
@@ -0,0 +1,485 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESWIN audio driver
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: DengLei <denglei@eswincomputing.com>
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <sound/pcm_params.h>
+#include <linux/dma-map-ops.h>
+#include "esw-i2s.h"
+#include "esw-dai.h"
+
+
+static void esw_pcm_dma_complete(void *arg)
+{
+ unsigned int new_pos;
+ struct snd_pcm_substream *substream = arg;
+ struct i2s_dev *chip = substream->runtime->private_data;
+
+ new_pos = chip->pcm_pos[substream->stream] + snd_pcm_lib_period_bytes(substream);
+ if (new_pos >= snd_pcm_lib_buffer_bytes(substream))
+ new_pos = 0;
+ chip->pcm_pos[substream->stream] = new_pos;
+
+ snd_pcm_period_elapsed(substream);
+}
+
+static int esw_pcm_dma_prepare_and_submit(struct i2s_dev *chip,
+ struct snd_pcm_substream *substream)
+{
+ struct dma_chan *chan = chip->chan[substream->stream];
+ struct dma_async_tx_descriptor *desc;
+ enum dma_transfer_direction direction;
+ unsigned long flags = DMA_CTRL_ACK;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ direction = DMA_MEM_TO_DEV;
+ else
+ direction = DMA_DEV_TO_MEM;
+
+ if (!substream->runtime->no_period_wakeup)
+ flags |= DMA_PREP_INTERRUPT;
+
+ chip->pcm_pos[substream->stream] = 0;
+ desc = dmaengine_prep_dma_cyclic(chan,
+ substream->runtime->dma_addr,
+ snd_pcm_lib_buffer_bytes(substream) * 64 / substream->runtime->frame_bits,
+ snd_pcm_lib_period_bytes(substream) * 64 / substream->runtime->frame_bits,
+ direction, flags);
+
+ if (!desc)
+ return -ENOMEM;
+
+ desc->callback = esw_pcm_dma_complete;
+ desc->callback_param = substream;
+ chip->cookie[substream->stream] = dmaengine_submit(desc);
+
+ return 0;
+}
+
+
+int esw_pcm_dma_refine_runtime_hwparams(
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hardware *hw, struct dma_chan *chan)
+{
+ struct dma_slave_caps dma_caps;
+ u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+ snd_pcm_format_t i;
+ int ret = 0;
+
+ if (!hw || !chan)
+ return -EINVAL;
+
+ ret = dma_get_slave_caps(chan, &dma_caps);
+ if (ret == 0) {
+ if (dma_caps.cmd_pause && dma_caps.cmd_resume)
+ hw->info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
+ if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT)
+ hw->info |= SNDRV_PCM_INFO_BATCH;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ addr_widths = dma_caps.dst_addr_widths;
+ else
+ addr_widths = dma_caps.src_addr_widths;
+ }
+
+ pcm_for_each_format(i) {
+ int bits = snd_pcm_format_physical_width(i);
+
+ /*
+ * Enable only samples with DMA supported physical
+ * widths
+ */
+ switch (bits) {
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ case 64:
+ if (addr_widths & (1 << (bits / 8)))
+ hw->formats |= pcm_format_to_bits(i);
+ break;
+ default:
+ /* Unsupported types */
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int esw_pcm_dma_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct i2s_dev *chip = dev_get_drvdata(component->dev);
+ struct snd_pcm_hardware hw;
+ struct dma_chan *chan = chip->chan[substream->stream];
+ struct device *dma_dev = chan->device->dev;
+ struct esw_i2s_dma_data *dma_data;
+
+ dev_dbg(chip->dev, "%s\n", __func__);
+
+ dma_data = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream);
+
+ memset(&hw, 0, sizeof(hw));
+ hw.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED;
+ hw.periods_min = 2;
+ hw.periods_max = 16;
+ hw.period_bytes_min = dma_data->max_burst * DMA_SLAVE_BUSWIDTH_8_BYTES;
+ if (!hw.period_bytes_min)
+ hw.period_bytes_min = 256;
+ hw.period_bytes_max = dma_get_max_seg_size(dma_dev);
+ hw.buffer_bytes_max = hw.period_bytes_max * 16;
+ hw.fifo_size = dma_data->fifo_size;
+ hw.info |= SNDRV_PCM_INFO_BATCH;
+
+ esw_pcm_dma_refine_runtime_hwparams(substream, &hw, chan);
+
+ substream->runtime->hw = hw;
+ substream->runtime->private_data = chip;
+
+ return 0;
+}
+
+static int esw_pcm_dma_prepare_slave_config(struct i2s_dev *chip,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct dma_slave_config *slave_config)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct esw_i2s_dma_data *dma_data;
+ enum dma_slave_buswidth buswidth;
+ int bits;
+
+ if (rtd->dai_link->num_cpus > 1) {
+ dev_err(rtd->dev,
+ "%s doesn't support Multi CPU yet\n", __func__);
+ return -EINVAL;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dma_data = &chip->play_dma_data;
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ dma_data = &chip->capture_dma_data;
+
+ bits = params_physical_width(params);
+ if (bits < 8 || bits > 64)
+ return -EINVAL;
+ else if (bits == 8)
+ buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ else if (bits == 16)
+ buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ else if (bits == 24)
+ buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES;
+ else if (bits <= 32)
+ buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ else
+ buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ slave_config->direction = DMA_MEM_TO_DEV;
+ slave_config->dst_addr_width = buswidth;
+ } else {
+ slave_config->direction = DMA_DEV_TO_MEM;
+ slave_config->src_addr_width = buswidth;
+ }
+
+ slave_config->device_fc = false;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ slave_config->dst_addr = dma_data->addr;
+ slave_config->dst_maxburst = dma_data->max_burst;
+ if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
+ slave_config->dst_addr_width = dma_data->addr_width;
+ } else {
+ slave_config->src_addr = dma_data->addr;
+ slave_config->src_maxburst = dma_data->max_burst;
+ if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
+ slave_config->src_addr_width = dma_data->addr_width;
+ }
+
+ return 0;
+}
+
+int esw_pcm_dma_hw_params(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct i2s_dev *chip = dev_get_drvdata(component->dev);
+ struct dma_slave_config slave_config;
+ int ret;
+
+ dev_dbg(chip->dev, "%s, period size:%d, period cnt:%d\n", __func__,
+ params_period_size(params), params_periods(params));
+
+ memset(&slave_config, 0, sizeof(slave_config));
+
+ ret = esw_pcm_dma_prepare_slave_config(chip, substream, params, &slave_config);
+ if (ret)
+ return ret;
+
+ ret = dmaengine_slave_config(chip->chan[substream->stream], &slave_config);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int esw_pcm_dma_close(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct i2s_dev *chip = dev_get_drvdata(component->dev);
+
+ dev_dbg(chip->dev, "%s\n", __func__);
+
+ dmaengine_synchronize(chip->chan[substream->stream]);
+
+ return 0;
+}
+
+int esw_pcm_dma_trigger(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream, int cmd)
+{
+ struct i2s_dev *chip = dev_get_drvdata(component->dev);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct dma_chan *chan = chip->chan[substream->stream];
+ int ret;
+
+ dev_dbg(chip->dev, "%s, cmd:%d, sample bits:%d\n", __func__, cmd, runtime->sample_bits);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ ret = esw_pcm_dma_prepare_and_submit(chip, substream);
+ if (ret) {
+ dev_err(chip->dev, "dma prepare and submit error\n");
+ return ret;
+ }
+ dma_async_issue_pending(chan);
+ break;
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ dmaengine_resume(chan);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (runtime->info & SNDRV_PCM_INFO_PAUSE)
+ dmaengine_pause(chan);
+ else
+ dmaengine_terminate_async(chan);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ dmaengine_pause(chan);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ dmaengine_terminate_async(chan);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+snd_pcm_uframes_t esw_pcm_dma_pointer(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct i2s_dev *chip = substream->runtime->private_data;
+ return bytes_to_frames(substream->runtime, chip->pcm_pos[substream->stream]);
+}
+
+static int esw_pcm_dma_process(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ int channel, unsigned long hwoff,
+ struct iov_iter *iter, unsigned long bytes)
+{
+ struct i2s_dev *chip = container_of(component, struct i2s_dev, pcm_component);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ char *dma_ptr = (char *)runtime->dma_area + hwoff * 64 / runtime->frame_bits +
+ channel * (runtime->dma_bytes / runtime->channels);
+ snd_pcm_uframes_t frames;
+ u16 *ptr_16;
+ u8 *ptr_24_raw;
+ u32 *ptr_24;
+ u32 *ptr_32;
+ int i;
+
+ if (is_playback) {
+ if (runtime->sample_bits == 32) {
+ if (copy_from_iter(dma_ptr, bytes, iter) != bytes)
+ return -EFAULT;
+ } else {
+ if (copy_from_iter(chip->conv_buf[0], bytes, iter) != bytes)
+ return -EFAULT;
+ if (runtime->sample_bits == 16) {
+ ptr_16 = (u16 *)chip->conv_buf[0];
+ ptr_32 = (u32 *)dma_ptr;
+ frames = bytes_to_frames(runtime, bytes);
+ for (i = 0; i < 2 * frames; i++) {
+ ptr_32[i] = (u32)ptr_16[i];
+ }
+ } else if (runtime->sample_bits == 24) {
+ ptr_24_raw = (u8 *)chip->conv_buf[0];
+ ptr_32 = (u32 *)dma_ptr;
+ for (i = 0; i < bytes / 3; i++) {
+ ptr_24 = (u32 *)(ptr_24_raw + i * 3);
+ ptr_32[i] = (*ptr_24) & 0xffffff;
+ }
+ }
+ }
+ } else {
+ if (runtime->sample_bits == 32) {
+ if (copy_to_iter(dma_ptr, bytes, iter) != bytes)
+ return -EFAULT;
+ } else {
+ if (runtime->sample_bits == 16) {
+ frames = bytes_to_frames(runtime, bytes);
+ ptr_16 = (u16 *)chip->conv_buf[1];
+ ptr_32 = (u32 *)dma_ptr;
+ for (i = 0; i < 2 * frames; i++) {
+ ptr_16[i] = ptr_32[i];
+ }
+ } else if (runtime->sample_bits == 24) {
+ ptr_24_raw = (u8 *)chip->conv_buf[1];
+ ptr_32 = (u32 *)dma_ptr;
+ for (i = 0; i < bytes / 3; i++) {
+ memcpy(&ptr_24_raw[i * 3], &ptr_32[i], 3);
+ }
+ }
+ if (copy_to_iter(chip->conv_buf[1], bytes, iter) != bytes)
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+static int esw_pcm_dma_new(struct snd_soc_component *component,
+ struct snd_soc_pcm_runtime *rtd)
+{
+ struct i2s_dev *chip = container_of(component, struct i2s_dev, pcm_component);
+ size_t prealloc_buffer_size;
+ size_t max_buffer_size;
+ unsigned int i;
+
+ prealloc_buffer_size = 512 * 1024;
+ max_buffer_size = SIZE_MAX;
+
+ for_each_pcm_streams(i) {
+ struct snd_pcm_substream *substream = rtd->pcm->streams[i].substream;
+ if (!substream)
+ continue;
+
+ snd_pcm_set_managed_buffer(substream,
+ SNDRV_DMA_TYPE_DEV_IRAM,
+ chip->chan[substream->stream]->device->dev,
+ prealloc_buffer_size,
+ max_buffer_size);
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver esw_pcm_component_driver = {
+ .name = "esw-dma",
+ .probe_order = SND_SOC_COMP_ORDER_LATE,
+ .open = esw_pcm_dma_open,
+ .close = esw_pcm_dma_close,
+ .hw_params = esw_pcm_dma_hw_params,
+ .trigger = esw_pcm_dma_trigger,
+ .pointer = esw_pcm_dma_pointer,
+ .copy = esw_pcm_dma_process,
+ .pcm_construct = esw_pcm_dma_new,
+};
+
+int esw_pcm_dma_dai_register(struct i2s_dev *chip)
+{
+ struct dma_chan *chan0;
+ struct dma_chan *chan1;
+ const char *channel_names0 = "tx";
+ const char *channel_names1 = "rx";
+ int ret;
+ u32 period_bytes_max;
+
+ dev_dbg(chip->dev, "%s\n", __func__);
+
+ chan0 = dma_request_chan(chip->dev, channel_names0);
+ if (IS_ERR(chan0)) {
+ if (PTR_ERR(chan0) == -EPROBE_DEFER) {
+ dev_err(chip->dev, "request dma channel[%s] failed\n", channel_names0);
+ return -EPROBE_DEFER;
+ }
+ dev_err(chip->dev, "dma channel[%s] is NULL\n", channel_names0);
+ } else {
+ chip->chan[SNDRV_PCM_STREAM_PLAYBACK] = chan0;
+ period_bytes_max = dma_get_max_seg_size(chan0->device->dev);
+ chip->conv_buf[SNDRV_PCM_STREAM_PLAYBACK] = kzalloc(period_bytes_max, GFP_KERNEL);
+ if (!chip->conv_buf[SNDRV_PCM_STREAM_PLAYBACK]) {
+ ret = -ENOMEM;
+ dev_err(chip->dev, "alloc conv buf0 err:%d\n", ret);
+ goto release_chan0;
+ }
+ }
+
+ chan1 = dma_request_chan(chip->dev, channel_names1);
+ if (IS_ERR(chan1)) {
+ if (PTR_ERR(chan1) == -EPROBE_DEFER) {
+ dev_err(chip->dev, "request dma channel[%s] failed\n", channel_names1);
+ ret = -EPROBE_DEFER;
+ goto release_buf0;
+ }
+ dev_err(chip->dev, "dma channel[%s] is NULL\n", channel_names1);
+ } else {
+ chip->chan[SNDRV_PCM_STREAM_CAPTURE] = chan1;
+ period_bytes_max = dma_get_max_seg_size(chan1->device->dev);
+ chip->conv_buf[SNDRV_PCM_STREAM_CAPTURE] = kzalloc(period_bytes_max, GFP_KERNEL);
+ if (!chip->conv_buf[SNDRV_PCM_STREAM_CAPTURE]) {
+ dev_err(chip->dev, "alloc conv buf0 err:%d\n", ret);
+ ret = -ENOMEM;
+ goto release_chan1;
+ }
+ }
+
+ ret = snd_soc_component_initialize(&chip->pcm_component, &esw_pcm_component_driver, chip->dev);
+ if (ret)
+ goto release_buf1;
+
+ ret = snd_soc_add_component(&chip->pcm_component, NULL, 0);
+ if (ret) {
+ dev_err(chip->dev, "add pcm component failed\n");
+ goto release_buf1;
+ }
+
+ return 0;
+
+release_buf1:
+ kfree(chip->conv_buf[1]);
+release_chan1:
+ dma_release_channel(chip->chan[1]);
+release_buf0:
+ kfree(chip->conv_buf[0]);
+release_chan0:
+ dma_release_channel(chip->chan[0]);
+
+ return ret;
+}
\ No newline at end of file
diff --git a/sound/soc/eswin/esw-i2s.c b/sound/soc/eswin/esw-i2s.c
index efae45ee2f31..0d40aee31f87 100755
--- a/sound/soc/eswin/esw-i2s.c
+++ b/sound/soc/eswin/esw-i2s.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* ALSA SoC Synopsys I2S Audio Layer
*
@@ -11,20 +12,24 @@
* warranty of any kind, whether express or implied.
*
*/
-
-/*
- * Copyright (C) 2021 ESWIN, Inc. All rights reserved.
+/*****************************************************************************
+ * ESWIN i2s driver
*
- * This program is free software; you can redistribute it and/or modify
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
*
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#include <sound/pcm.h>
@@ -50,8 +55,10 @@
#include <linux/mfd/syscon.h>
#include <linux/reset.h>
#include <linux/dma-map-ops.h>
+#include <linux/of_address.h>
#include "esw-i2s.h"
#include "esw-audio-proc.h"
+#include "esw-dai.h"
#define VO_MCLK_DIVSOR_MASK 0xff0
#define VO_MCLK_DIVSOR_OFFSET 4
@@ -69,10 +76,14 @@
#define ESW_I2S_RATES (SNDRV_PCM_RATE_192000 | \
SNDRV_PCM_RATE_96000 | \
SNDRV_PCM_RATE_48000 | \
+ SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_8000)
-#define ESW_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+#define ESW_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | \
+ SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S24_3LE)
#define DIE0_I2S0_IO_ADDR 0x51600124
#define DIE1_I2S0_IO_ADDR 0x71600124
@@ -80,9 +91,14 @@
#define DIE0_DAI_DRIVER_OFFSET 0
#define DIE1_DAI_DRIVER_OFFSET 4
-#define HDMI_DAI_NAME "i2s0-hdmi"
+#define APLL_HIGH_FREQ 983040000
+#define APLL_LOW_FREQ 225792000
-static struct clk *g_mclk;
+#define D0_HDMI_DAI_NAME "i2s0-hdmi"
+#define D1_HDMI_DAI_NAME "d1-i2s0-hdmi"
+
+static int enable_441k[2] = {0, 0};
+static int i2s_enable_cnt[2] = {0, 0};
static u32 dmaen_txch[] = {
DMAEN_TXCH_0,
@@ -129,35 +145,39 @@ int i2s_get_nid(struct device *dev)
return nid;
}
-static int set_mclk(struct device *dev, struct clk **i2s_clk)
+static int set_mclk(struct device *dev, struct i2s_dev *i2s_drvdata)
{
- const char *clk_id = "mclk";
- struct clk *clk = NULL;
int ret;
- clk = devm_clk_get(dev, clk_id);
- if (IS_ERR(clk)) {
- dev_err(dev, "Failed to get clock: %ld\n", PTR_ERR(clk));
- return PTR_ERR(clk);
+ i2s_drvdata->mclk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(i2s_drvdata->mclk)) {
+ dev_err(dev, "Failed to get mclock: %ld\n", PTR_ERR(i2s_drvdata->mclk));
+ return PTR_ERR(i2s_drvdata->mclk);
}
- ret = clk_prepare_enable(clk);
+ ret = clk_prepare_enable(i2s_drvdata->mclk);
if (ret < 0) {
- dev_err(dev, "Failed to enable clock: %d\n", ret);
+ dev_err(dev, "Failed to enable mclock: %d\n", ret);
return ret;
}
/* only set once */
if (of_node_name_prefix(dev->of_node, "i2s0")) {
- ret = clk_set_rate(clk, MAX_SAMPLE_RATE_CLK);
+ ret = clk_set_rate(i2s_drvdata->mclk, MAX_SAMPLE_RATE_CLK);
if (ret) {
- dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
- clk_disable_unprepare(clk);
+ dev_err(dev, "Can't set I2S mclock rate: %d\n", ret);
+ clk_disable_unprepare(i2s_drvdata->mclk);
return ret;
}
}
- *i2s_clk = clk;
+ i2s_drvdata->apll_clk = devm_clk_get(dev, "apll");
+ if (IS_ERR(i2s_drvdata->apll_clk)) {
+ dev_err(dev, "Failed to get apll clock: %ld\n", PTR_ERR(i2s_drvdata->apll_clk));
+ clk_disable_unprepare(i2s_drvdata->mclk);
+ return PTR_ERR(i2s_drvdata->apll_clk);
+ }
+
return 0;
}
@@ -360,8 +380,6 @@ static void i2s_stop(struct i2s_dev *i2s_drvdata,
static int i2s_configure_res_by_dt(struct i2s_dev *dev,
struct resource *res)
{
- struct snd_soc_component *component;
- struct dmaengine_pcm *pcm;
u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1);
u32 comp2 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_2);
u32 fifo_depth;
@@ -386,13 +404,6 @@ static int i2s_configure_res_by_dt(struct i2s_dev *dev,
}
dev->fifo_th = fifo_depth / 2;
- component = snd_soc_lookup_component(dev->dev, SND_DMAENGINE_PCM_DRV_NAME);
- if (!component) {
- dev_err(dev->dev, "Can not find snd_soc_component\n");
- return -1;
- }
-
- pcm = soc_component_to_pcm(component);
if (COMP1_TX_ENABLED(comp1)) {
idx2 = COMP1_TX_WORDSIZE_0(comp1);
dev->capability |= DWC_I2S_PLAY;
@@ -401,7 +412,7 @@ static int i2s_configure_res_by_dt(struct i2s_dev *dev,
dev->play_dma_data.fifo_size = fifo_depth *
(fifo_width[idx2]) >> 3;
dev->play_dma_data.addr = res->start + TXDMA_CH(0);
- dev->play_dma_data.maxburst = 16;
+ dev->play_dma_data.max_burst = 16;
}
if (COMP1_RX_ENABLED(comp1)) {
idx2 = COMP2_RX_WORDSIZE_0(comp2);
@@ -411,8 +422,9 @@ static int i2s_configure_res_by_dt(struct i2s_dev *dev,
dev->capture_dma_data.fifo_size = fifo_depth *
(fifo_width[idx2]) >> 3;
dev->capture_dma_data.addr = res->start + RXDMA_CH(0);
- dev->capture_dma_data.maxburst = 16;
+ dev->capture_dma_data.max_burst = 16;
}
+
return 0;
}
@@ -424,10 +436,6 @@ static int i2s_startup(struct snd_pcm_substream *substream,
dai_link->trigger_stop = SND_SOC_TRIGGER_ORDER_LDC;
- if (!strcmp(cpu_dai->name, HDMI_DAI_NAME)) {
- dai_link->playback_only = 1;
- }
-
return 0;
}
@@ -438,6 +446,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
struct i2s_clk_config_data *config = &i2s_drvdata->config;
uint32_t div_num = 0;
uint32_t div_num_reg;
+ int ret;
dev_dbg(i2s_drvdata->dev, "sample rate:%d, chan:%d, width:%d\n",
params_rate(params), params_channels(params), params_width(params));
@@ -449,6 +458,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
i2s_drvdata->xfer_resolution = RESOLUTION_16_BIT;
break;
case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S24_3LE:
config->data_width = 24;
i2s_drvdata->ccr = CLOCK_CYCLES_32 << CCR_WSS_POS |
NO_CLOCK_GATING;
@@ -476,25 +486,74 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
i2s_write_reg(i2s_drvdata->i2s_base, CCR, i2s_drvdata->ccr);
config->sample_rate = params_rate(params);
if (i2s_drvdata->capability & DW_I2S_MASTER) {
- if (MAX_SAMPLE_RATE_SUPPORT % config->sample_rate != 0) {
- dev_err(i2s_drvdata->dev, "Not support sample rate: %d\n", config->sample_rate);
- return -EINVAL;
- }
-
- div_num = MAX_SAMPLE_RATE_SUPPORT / config->sample_rate - 1;
-
- if (i2s_drvdata->active) {
- if (i2s_drvdata->i2s_div_num != div_num) {
- dev_err(i2s_drvdata->dev, "Not support the playback and capture clocks are different\n");
- return -EINVAL;
+ if (config->sample_rate == 44100) {
+ if (!enable_441k[i2s_drvdata->nid]) {
+ if (!i2s_enable_cnt[i2s_drvdata->nid]) {
+ ret = clk_set_rate(i2s_drvdata->mclk, MAX_SAMPLE_RATE_CLK * 2);
+ if (ret) {
+ dev_err(i2s_drvdata->dev, "Can't set I2S mclock rate: %d\n", ret);
+ return ret;
+ }
+ ret = clk_set_rate(i2s_drvdata->apll_clk, APLL_LOW_FREQ);
+ if (ret) {
+ dev_err(i2s_drvdata->dev, "Can't set I2S apll clock rate: %d\n", ret);
+ return ret;
+ }
+ enable_441k[i2s_drvdata->nid] = 1;
+ div_num_reg = i2s_read_reg(i2s_drvdata->i2s_div_base, 0) & ~DIV_NUM_MASK;
+ div_num_reg |= 1;
+ i2s_write_reg(i2s_drvdata->i2s_div_base, 0, div_num_reg);
+ i2s_drvdata->i2s_div_num = 1;
+ dev_dbg(i2s_drvdata->dev, "apll rate:%ld\n", clk_get_rate(i2s_drvdata->apll_clk));
+ } else {
+ dev_err(i2s_drvdata->dev, "Other sample rate audio is playing.\n");
+ return -EINVAL;
+ }
+ } else {
+ div_num_reg = i2s_read_reg(i2s_drvdata->i2s_div_base, 0) & ~DIV_NUM_MASK;
+ div_num_reg |= 1;
+ i2s_write_reg(i2s_drvdata->i2s_div_base, 0, div_num_reg);
+ i2s_drvdata->i2s_div_num = 1;
}
} else {
- div_num_reg = i2s_read_reg(i2s_drvdata->i2s_div_base, 0) & ~DIV_NUM_MASK;
- div_num_reg |= div_num;
+ if (enable_441k[i2s_drvdata->nid]) {
+ if (!i2s_enable_cnt[i2s_drvdata->nid]) {
+ ret = clk_set_rate(i2s_drvdata->apll_clk, APLL_HIGH_FREQ);
+ if (ret) {
+ dev_err(i2s_drvdata->dev, "Can't set I2S apll clock rate: %d\n", ret);
+ return ret;
+ }
+ ret = clk_set_rate(i2s_drvdata->mclk, MAX_SAMPLE_RATE_CLK);
+ if (ret) {
+ dev_err(i2s_drvdata->dev, "Can't set I2S mclock rate: %d\n", ret);
+ return ret;
+ }
+ enable_441k[i2s_drvdata->nid] = 0;
+ dev_dbg(i2s_drvdata->dev, "apll rate:%ld\n", clk_get_rate(i2s_drvdata->apll_clk));
+ } else {
+ dev_err(i2s_drvdata->dev, "44.1khz audio is playing.\n");
+ return -EINVAL;
+ }
+ }
+ if (MAX_SAMPLE_RATE_SUPPORT % config->sample_rate != 0) {
+ dev_err(i2s_drvdata->dev, "Not support sample rate: %d\n", config->sample_rate);
+ return -EINVAL;
+ }
- dev_dbg(i2s_drvdata->dev, "div num:0x%x\n", div_num);
- i2s_drvdata->i2s_div_num = div_num;
- i2s_write_reg(i2s_drvdata->i2s_div_base, 0, div_num_reg);
+ div_num = MAX_SAMPLE_RATE_SUPPORT / config->sample_rate - 1;
+
+ if (i2s_drvdata->active) {
+ if (i2s_drvdata->i2s_div_num != div_num) {
+ dev_err(i2s_drvdata->dev, "Not support the playback and capture clocks are different\n");
+ return -EINVAL;
+ }
+ } else {
+ div_num_reg = i2s_read_reg(i2s_drvdata->i2s_div_base, 0) & ~DIV_NUM_MASK;
+ div_num_reg |= div_num;
+ dev_dbg(i2s_drvdata->dev, "div num:0x%x\n", div_num);
+ i2s_drvdata->i2s_div_num = div_num;
+ i2s_write_reg(i2s_drvdata->i2s_div_base, 0, div_num_reg);
+ }
}
}
@@ -518,6 +577,8 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
{
struct i2s_dev *i2s_drvdata = snd_soc_dai_get_drvdata(dai);
int ret = 0;
+
+ dev_dbg(i2s_drvdata->dev, "%s\n", __func__);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
@@ -529,6 +590,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
} else {
i2s_drvdata->capture_active = true;
}
+ i2s_enable_cnt[i2s_drvdata->nid]++;
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -540,6 +602,7 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
} else {
i2s_drvdata->capture_active = false;
}
+ i2s_enable_cnt[i2s_drvdata->nid]--;
break;
default:
ret = -EINVAL;
@@ -598,7 +661,7 @@ static const struct snd_soc_dai_ops i2s_dai_ops = {
static int i2s_runtime_suspend(struct device *dev)
{
struct i2s_dev *i2s_drvdata = dev_get_drvdata(dev);
- struct clk *clk = i2s_drvdata->clk;
+ struct clk *clk = i2s_drvdata->mclk;
dev_dbg(i2s_drvdata->dev, "%s\n", __func__);
@@ -610,7 +673,7 @@ static int i2s_runtime_suspend(struct device *dev)
static int i2s_runtime_resume(struct device *dev)
{
struct i2s_dev *i2s_drvdata = dev_get_drvdata(dev);
- struct clk *clk = i2s_drvdata->clk;
+ struct clk *clk = i2s_drvdata->mclk;
dev_dbg(i2s_drvdata->dev, "%s\n", __func__);
clk_enable(clk);
@@ -621,7 +684,7 @@ static int i2s_runtime_resume(struct device *dev)
static int i2s_suspend(struct snd_soc_component *component)
{
struct i2s_dev *i2s_drvdata = snd_soc_component_get_drvdata(component);
- struct clk *clk = i2s_drvdata->clk;
+ struct clk *clk = i2s_drvdata->mclk;
dev_dbg(i2s_drvdata->dev, "%s\n", __func__);
if(!pm_runtime_suspended(i2s_drvdata->dev)) {
@@ -636,7 +699,7 @@ static int i2s_resume(struct snd_soc_component *component)
{
struct i2s_dev *i2s_drvdata = snd_soc_component_get_drvdata(component);
struct snd_soc_dai *dai = NULL;
- struct clk *clk = i2s_drvdata->clk;
+ struct clk *clk = i2s_drvdata->mclk;
int stream;
dev_dbg(i2s_drvdata->dev, "%s\n", __func__);
@@ -662,7 +725,8 @@ static int i2s_reset(struct platform_device *pdev, struct i2s_dev *i2s)
struct reset_control *rst;
struct reset_control *prst;
struct reset_control *voprst;
- int ret;
+ void __iomem *i2s0_io_base;
+ int ret, reg_val;
rst = devm_reset_control_get_optional_exclusive(&pdev->dev, "i2srst");
if (IS_ERR(rst)) {
@@ -690,6 +754,32 @@ static int i2s_reset(struct platform_device *pdev, struct i2s_dev *i2s)
ret = reset_control_deassert(voprst);
WARN_ON(0 != ret);
+ if (!of_property_read_bool(pdev->dev.of_node, "io_reuse_enable")) {
+ i2s0_io_base = devm_ioremap(&pdev->dev, DIE0_I2S0_IO_ADDR, 12);
+ if (!i2s0_io_base) {
+ dev_err(&pdev->dev, "failed to remap i2s0 io ctl\n");
+ return -ENOMEM;
+ }
+
+ /* set the i2s0 WCLK io to GPIO func */
+ reg_val = readl((char *)i2s0_io_base);
+ reg_val &= 0xfff8ffff;
+ reg_val |= 0x20000;
+ writel(reg_val, (char *)i2s0_io_base);
+
+ /* set the i2s0 SDI io to GPIO func */
+ reg_val = readl((char *)i2s0_io_base + 4);
+ reg_val &= 0xfff8ffff;
+ reg_val |= 0x20000;
+ writel(reg_val, (char *)i2s0_io_base + 4);
+
+ /* set the i2s0 SDO io to GPIO func */
+ reg_val = readl((char *)i2s0_io_base + 8);
+ reg_val &= 0xfff8ffff;
+ reg_val |= 0x20000;
+ writel(reg_val, (char *)i2s0_io_base + 8);
+ }
+
return 0;
}
@@ -708,15 +798,21 @@ static int i2s_open(struct snd_soc_component *component,
}
static const struct snd_soc_component_driver i2s_component = {
- .name = "i2s0",
.open = i2s_open,
.suspend = i2s_suspend,
.resume = i2s_resume,
};
+static const struct snd_soc_component_driver i2s_sof_component = {
+ .open = esw_sof_dma_open,
+ .close = esw_sof_dma_close,
+ .hw_params = esw_sof_dma_hw_params,
+ .trigger = esw_sof_dma_trigger,
+};
+
static struct snd_soc_dai_driver i2s_dai[8] = {
{
- .name = HDMI_DAI_NAME,
+ .name = D0_HDMI_DAI_NAME,
.id = 0,
.ops = &i2s_dai_ops,
.playback = {
@@ -751,14 +847,12 @@ static struct snd_soc_dai_driver i2s_dai[8] = {
.id = 0,
.ops = &i2s_dai_ops,
.playback = {
- .stream_name = "Playback",
.channels_min = MIN_CHANNEL_NUM,
.channels_max = MAX_CHANNEL_NUM,
.rates = ESW_I2S_RATES,
.formats = ESW_I2S_FORMATS,
},
.capture = {
- .stream_name = "Capture",
.channels_min = MIN_CHANNEL_NUM,
.channels_max = MAX_CHANNEL_NUM,
.rates = ESW_I2S_RATES,
@@ -770,14 +864,12 @@ static struct snd_soc_dai_driver i2s_dai[8] = {
.id = 0,
.ops = &i2s_dai_ops,
.playback = {
- .stream_name = "Playback",
.channels_min = MIN_CHANNEL_NUM,
.channels_max = MAX_CHANNEL_NUM,
.rates = ESW_I2S_RATES,
.formats = ESW_I2S_FORMATS,
},
.capture = {
- .stream_name = "Capture",
.channels_min = MIN_CHANNEL_NUM,
.channels_max = MAX_CHANNEL_NUM,
.rates = ESW_I2S_RATES,
@@ -785,18 +877,10 @@ static struct snd_soc_dai_driver i2s_dai[8] = {
},
},
{
- .name = "d1-i2s0-hdmi",
+ .name = D1_HDMI_DAI_NAME,
.id = 0,
.ops = &i2s_dai_ops,
.playback = {
- .stream_name = "Playback",
- .channels_min = MIN_CHANNEL_NUM,
- .channels_max = MAX_CHANNEL_NUM,
- .rates = ESW_I2S_RATES,
- .formats = ESW_I2S_FORMATS,
- },
- .capture = {
- .stream_name = "Capture",
.channels_min = MIN_CHANNEL_NUM,
.channels_max = MAX_CHANNEL_NUM,
.rates = ESW_I2S_RATES,
@@ -808,14 +892,12 @@ static struct snd_soc_dai_driver i2s_dai[8] = {
.id = 1,
.ops = &i2s_dai_ops,
.playback = {
- .stream_name = "Playback",
.channels_min = MIN_CHANNEL_NUM,
.channels_max = MAX_CHANNEL_NUM,
.rates = ESW_I2S_RATES,
.formats = ESW_I2S_FORMATS,
},
.capture = {
- .stream_name = "Capture",
.channels_min = MIN_CHANNEL_NUM,
.channels_max = MAX_CHANNEL_NUM,
.rates = ESW_I2S_RATES,
@@ -827,14 +909,12 @@ static struct snd_soc_dai_driver i2s_dai[8] = {
.id = 0,
.ops = &i2s_dai_ops,
.playback = {
- .stream_name = "Playback",
.channels_min = MIN_CHANNEL_NUM,
.channels_max = MAX_CHANNEL_NUM,
.rates = ESW_I2S_RATES,
.formats = ESW_I2S_FORMATS,
},
.capture = {
- .stream_name = "Capture",
.channels_min = MIN_CHANNEL_NUM,
.channels_max = MAX_CHANNEL_NUM,
.rates = ESW_I2S_RATES,
@@ -846,14 +926,12 @@ static struct snd_soc_dai_driver i2s_dai[8] = {
.id = 0,
.ops = &i2s_dai_ops,
.playback = {
- .stream_name = "Playback",
.channels_min = MIN_CHANNEL_NUM,
.channels_max = MAX_CHANNEL_NUM,
.rates = ESW_I2S_RATES,
.formats = ESW_I2S_FORMATS,
},
.capture = {
- .stream_name = "Capture",
.channels_min = MIN_CHANNEL_NUM,
.channels_max = MAX_CHANNEL_NUM,
.rates = ESW_I2S_RATES,
@@ -862,6 +940,65 @@ static struct snd_soc_dai_driver i2s_dai[8] = {
},
};
+static int i2s_sof_ringbuffer_init(struct i2s_dev *i2s_drvdata)
+{
+ struct resource res_sram;
+ int ret;
+ struct device_node *rb_node;
+ u32 ringbuffer_in_addr;
+ u32 ringbuffer_out_addr;
+
+ rb_node = of_parse_phandle(i2s_drvdata->dev->of_node, "ringbuffer-region", 0);
+ if (IS_ERR(rb_node)) {
+ dev_err(i2s_drvdata->dev, "Get phandle dsp-sram error\n");
+ return -ENODEV;
+ }
+ of_node_put(i2s_drvdata->dev->of_node);
+
+ ret = of_address_to_resource(rb_node, 0, &res_sram);
+ if (ret) {
+ dev_err(i2s_drvdata->dev, "failed to get ring buffer address\n");
+ return ret;
+ }
+ of_node_put(rb_node);
+
+ ringbuffer_in_addr = res_sram.start + DSP_RB_COMP_SIZE + DSP_RB_PCM_P_SZIE;
+ ringbuffer_out_addr = res_sram.start + DSP_RB_COMP_SIZE;
+
+ i2s_drvdata->pos[0] = devm_ioremap(i2s_drvdata->dev, ringbuffer_out_addr, DSP_RB_PCM_C_SZIE + DSP_RB_PCM_P_SZIE);
+ if(!i2s_drvdata->pos[0]) {
+ dev_err(i2s_drvdata->dev, "failed to remap stream out pos\n");
+ return -ENOMEM;
+ }
+ i2s_drvdata->pos[1] = i2s_drvdata->pos[0] + DSP_RB_PCM_P_SZIE;
+
+ memset(i2s_drvdata->pos[0], 0, (DSP_RB_PCM_P_SZIE + DSP_RB_PCM_C_SZIE));
+
+ i2s_drvdata->rb_out_iova = dma_map_page_attrs(i2s_drvdata->chan[0]->device->dev,
+ phys_to_page(ringbuffer_out_addr + DSP_RB_POS_SZIE),
+ offset_in_page(ringbuffer_out_addr + DSP_RB_POS_SZIE),
+ DSP_RB_DATA_SZIE, DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC);
+ if (dma_mapping_error(i2s_drvdata->chan[0]->device->dev, i2s_drvdata->rb_out_iova)) {
+ dev_err(i2s_drvdata->dev, "dma mapping failed\n");
+ return -ENOMEM;
+ }
+ dev_dbg(i2s_drvdata->dev, "rb out iova_addr:0x%llx\n", i2s_drvdata->rb_out_iova);
+
+ i2s_drvdata->rb_in_iova = dma_map_page_attrs(i2s_drvdata->chan[1]->device->dev,
+ phys_to_page(ringbuffer_in_addr + DSP_RB_POS_SZIE),
+ offset_in_page(ringbuffer_in_addr + DSP_RB_POS_SZIE),
+ DSP_RB_DATA_SZIE, DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC);
+ if (dma_mapping_error(i2s_drvdata->chan[1]->device->dev, i2s_drvdata->rb_in_iova)) {
+ dev_err(i2s_drvdata->dev, "dma mapping failed\n");
+ dma_unmap_page_attrs(i2s_drvdata->chan[0]->device->dev, i2s_drvdata->rb_out_iova, DSP_RB_DATA_SZIE,
+ DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC);
+ return -ENOMEM;
+ }
+ dev_dbg(i2s_drvdata->dev, "rb in iova_addr:0x%llx\n", i2s_drvdata->rb_in_iova);
+
+ return 0;
+}
+
static int i2s_probe(struct platform_device *pdev)
{
struct i2s_dev *i2s_drvdata;
@@ -869,25 +1006,13 @@ static int i2s_probe(struct platform_device *pdev)
int ret = 0;
int nid = 0;
unsigned long vo_top_csr;
- unsigned long i2s0_io_addr;
int dai_offset = 0;
- struct snd_dmaengine_pcm_config *config;
- void __iomem *i2s0_io_base;
- int reg_val;
dev_info(&pdev->dev, "dev name:%s\n", pdev->dev.of_node->name);
i2s_drvdata = devm_kzalloc(&pdev->dev, sizeof(*i2s_drvdata), GFP_KERNEL);
if (!i2s_drvdata)
return -ENOMEM;
- config = devm_kzalloc(&pdev->dev,
- sizeof(struct snd_dmaengine_pcm_config), GFP_KERNEL);
- if (!config)
- return -ENOMEM;
- config->chan_names[SNDRV_PCM_STREAM_PLAYBACK] = "tx";
- config->chan_names[SNDRV_PCM_STREAM_CAPTURE] = "rx";
- config->prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config;
-
res = platform_get_resource(pdev,IORESOURCE_MEM, 0);
i2s_drvdata->i2s_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(i2s_drvdata->i2s_base)) {
@@ -905,8 +1030,9 @@ static int i2s_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "%s:%d, NUMA_NO_NODE\n", __func__, __LINE__);
return -EFAULT;
}
+ i2s_drvdata->nid = nid;
- ret = set_mclk(&pdev->dev, &i2s_drvdata->clk);
+ ret = set_mclk(&pdev->dev, i2s_drvdata);
if (ret < 0) {
return ret;
}
@@ -917,33 +1043,6 @@ static int i2s_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "i2s_reset failed\n");
goto err_probe;
}
-
- if (!of_property_read_bool(pdev->dev.of_node, "io_reuse_enable")) {
- i2s0_io_addr = get_i2s0_io_addr(nid);
- i2s0_io_base = devm_ioremap(&pdev->dev, i2s0_io_addr, 12);
- if (!i2s0_io_base) {
- dev_err(i2s_drvdata->dev, "failed to remap i2s0 io ctl\n");
- return -ENOMEM;
- }
-
- /* set the i2s0 WCLK io to GPIO func */
- reg_val = readl((char *)i2s0_io_base);
- reg_val &= 0xfff8ffff;
- reg_val |= 0x20000;
- writel(reg_val, (char *)i2s0_io_base);
-
- /* set the i2s0 SDI io to GPIO func */
- reg_val = readl((char *)i2s0_io_base + 4);
- reg_val &= 0xfff8ffff;
- reg_val |= 0x20000;
- writel(reg_val, (char *)i2s0_io_base + 4);
-
- /* set the i2s0 SDO io to GPIO func */
- reg_val = readl((char *)i2s0_io_base + 8);
- reg_val &= 0xfff8ffff;
- reg_val |= 0x20000;
- writel(reg_val, (char *)i2s0_io_base + 8);
- }
}
dev_set_drvdata(&pdev->dev, i2s_drvdata);
@@ -956,7 +1055,11 @@ static int i2s_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto err_probe;
}
- ret = devm_snd_soc_register_component(&pdev->dev, &i2s_component, &i2s_dai[dai_offset], 2);
+ if (of_property_read_bool(pdev->dev.of_node, "dsp_sof_enable")) {
+ ret = devm_snd_soc_register_component(&pdev->dev, &i2s_sof_component, &i2s_dai[dai_offset], 2);
+ } else {
+ ret = devm_snd_soc_register_component(&pdev->dev, &i2s_component, &i2s_dai[dai_offset], 2);
+ }
} else if (of_node_name_prefix(pdev->dev.of_node, "i2s1")) {
i2s_drvdata->i2s_div_base = devm_ioremap(i2s_drvdata->dev, vo_top_csr + VO_I2S1_DIV_NUM, 4);
if (!i2s_drvdata->i2s_div_base) {
@@ -964,7 +1067,11 @@ static int i2s_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto err_probe;
}
- ret = devm_snd_soc_register_component(&pdev->dev, &i2s_component, &i2s_dai[2 + dai_offset], 1);
+ if (of_property_read_bool(pdev->dev.of_node, "dsp_sof_enable")) {
+ ret = devm_snd_soc_register_component(&pdev->dev, &i2s_sof_component, &i2s_dai[2 + dai_offset], 1);
+ } else {
+ ret = devm_snd_soc_register_component(&pdev->dev, &i2s_component, &i2s_dai[2 + dai_offset], 1);
+ }
} else {
i2s_drvdata->i2s_div_base = devm_ioremap(i2s_drvdata->dev, vo_top_csr + VO_I2S2_DIV_NUM, 4);
if (!i2s_drvdata->i2s_div_base) {
@@ -972,7 +1079,11 @@ static int i2s_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto err_probe;
}
- ret = devm_snd_soc_register_component(&pdev->dev, &i2s_component, &i2s_dai[3 + dai_offset], 1);
+ if (of_property_read_bool(pdev->dev.of_node, "dsp_sof_enable")) {
+ ret = devm_snd_soc_register_component(&pdev->dev, &i2s_sof_component, &i2s_dai[3 + dai_offset], 1);
+ } else {
+ ret = devm_snd_soc_register_component(&pdev->dev, &i2s_component, &i2s_dai[3 + dai_offset], 1);
+ }
}
if (ret != 0) {
dev_err(&pdev->dev, "not able to register dai\n");
@@ -980,10 +1091,24 @@ static int i2s_probe(struct platform_device *pdev)
}
i2s_drvdata->use_pio = false;
- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, config, 0);
- if (ret) {
- dev_err(&pdev->dev, "could not register pcm: %d\n", ret);
- goto err_probe;
+
+ if (of_property_read_bool(pdev->dev.of_node, "dsp_sof_enable")) {
+ ret = esw_sof_dma_init(i2s_drvdata);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "pcm dma init failed\n");
+ goto err_probe;
+ }
+ ret = i2s_sof_ringbuffer_init(i2s_drvdata);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "pcm ringbuffer init failed\n");
+ goto err_probe;
+ }
+ } else {
+ ret = esw_pcm_dma_dai_register(i2s_drvdata);
+ if (ret) {
+ dev_err(&pdev->dev, "could not register pcm: %d\n", ret);
+ goto err_probe;
+ }
}
i2s_drvdata->i2s_reg_comp1 = I2S_COMP_PARAM_1;
@@ -999,11 +1124,11 @@ static int i2s_probe(struct platform_device *pdev)
audio_proc_module_init();
#ifdef CONFIG_PM
- clk_disable(i2s_drvdata->clk);
+ clk_disable(i2s_drvdata->mclk);
#endif
return 0;
err_probe:
- clk_disable_unprepare(i2s_drvdata->clk);
+ clk_disable_unprepare(i2s_drvdata->mclk);
return ret;
}
@@ -1012,12 +1137,22 @@ static int i2s_remove(struct platform_device *pdev)
{
struct i2s_dev *i2s_drvdata = dev_get_drvdata(&pdev->dev);
- clk_disable_unprepare(i2s_drvdata->clk);
+ dev_info(&pdev->dev, "dev name:%s\n", pdev->dev.of_node->name);
+ clk_disable_unprepare(i2s_drvdata->mclk);
pm_runtime_disable(&pdev->dev);
-
audio_proc_module_exit();
+ if (of_property_read_bool(pdev->dev.of_node, "dsp_sof_enable")) {
+ dma_unmap_page_attrs(i2s_drvdata->chan[0]->device->dev, i2s_drvdata->rb_out_iova, DSP_RB_DATA_SZIE,
+ DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC);
+ dma_unmap_page_attrs(i2s_drvdata->chan[1]->device->dev, i2s_drvdata->rb_in_iova, DSP_RB_DATA_SZIE,
+ DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC);
+ } else {
+ kfree(i2s_drvdata->conv_buf[0]);
+ kfree(i2s_drvdata->conv_buf[1]);
+ }
+
return 0;
}
@@ -1038,7 +1173,7 @@ static struct platform_driver i2s_driver = {
.probe = i2s_probe,
.remove = i2s_remove,
.driver = {
- .name = "i2s",
+ .name = "es-i2s",
.of_match_table = of_match_ptr(i2s_of_match),
.pm = &i2s_pm_ops,
},
diff --git a/sound/soc/eswin/esw-i2s.h b/sound/soc/eswin/esw-i2s.h
index 6c1a243223a4..63f12992236f 100644
--- a/sound/soc/eswin/esw-i2s.h
+++ b/sound/soc/eswin/esw-i2s.h
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (ST) 2012 Rajeev Kumar (rajeevkumar.linux@gmail.com)
*
@@ -5,21 +6,24 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
-/*
+/*****************************************************************************
+ * ESWIN i2s driver
*
- * Copyright (C) 2021 ESWIN, Inc. All rights reserved.
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
+ * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation, version 2.
*
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: DengLei <denglei@eswincomputing.com>
*/
#ifndef __I2S_H
@@ -32,7 +36,6 @@
#include <sound/soc.h>
#include <linux/clk.h>
#include <linux/types.h>
-#include <sound/dmaengine_pcm.h>
#include <sound/designware_i2s.h>
@@ -145,9 +148,20 @@ enum {
RESOLUTION_32_BIT
};
+
+struct esw_i2s_dma_data {
+ void *data;
+ dma_addr_t addr;
+ u32 max_burst;
+ unsigned int fifo_size;
+ enum dma_slave_buswidth addr_width;
+ bool (*filter)(struct dma_chan *chan, void *slave);
+};
+
struct i2s_dev {
void __iomem *i2s_base;
- struct clk *clk;
+ struct clk *mclk;
+ struct clk *apll_clk;
struct device *dev;
unsigned int i2s_reg_comp1;
unsigned int i2s_reg_comp2;
@@ -155,8 +169,8 @@ struct i2s_dev {
u32 fifo_th;
bool use_pio;
/* data related to DMA transfers b/w i2s and DMAC */
- struct snd_dmaengine_dai_dma_data play_dma_data;
- struct snd_dmaengine_dai_dma_data capture_dma_data;
+ struct esw_i2s_dma_data play_dma_data;
+ struct esw_i2s_dma_data capture_dma_data;
struct i2s_clk_config_data config;
struct snd_pcm_substream __rcu *tx_substream;
struct snd_pcm_substream __rcu *rx_substream;
@@ -175,6 +189,17 @@ struct i2s_dev {
u32 i2s_div_num;
bool playback_active;
bool capture_active;
+ int nid;
+
+ struct dma_chan *chan[2];
+ dma_cookie_t cookie[2];
+ void *pos[2];
+ dma_addr_t rb_in_iova;
+ dma_addr_t rb_out_iova;
+
+ unsigned int pcm_pos[2];
+ struct snd_soc_component pcm_component;
+ void *conv_buf[2];
};
#endif /* __I2S_H */
diff --git a/sound/soc/eswin/esw-sof-dai.c b/sound/soc/eswin/esw-sof-dai.c
new file mode 100644
index 000000000000..214487ec1d44
--- /dev/null
+++ b/sound/soc/eswin/esw-sof-dai.c
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESWIN audio driver
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: DengLei <denglei@eswincomputing.com>
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <sound/pcm_params.h>
+#include <linux/dma-map-ops.h>
+#include "esw-dai.h"
+
+static void esw_sof_dma_tx_callback(void *arg)
+{
+ struct i2s_dev *chip = arg;
+ struct esw_ring_buffer *rb = (struct esw_ring_buffer *)chip->pos[0];
+ struct snd_pcm_substream *substream = chip->tx_substream;
+ int count = 0;
+
+ if (!rb) {
+ dev_err(chip->dev, "pos addr is NULL\n");
+ return;
+ }
+
+ while(1) {
+ if (rb->read + snd_pcm_lib_period_bytes(substream) <= rb->write) {
+ rb->read += snd_pcm_lib_period_bytes(substream);
+ dev_dbg(chip->dev, "read pos:%lld, write pos:%lld, buffer size:%lld\n",
+ rb->read, rb->write, rb->buffer_size);
+ break;
+ }
+ if (count++ == 10000) {
+ dev_warn(chip->dev, "dsp update pos timeout, read pos:%lld, write pos:%lld, buffer size:%lld\n",
+ rb->read, rb->write, rb->buffer_size);
+ break;
+ }
+ }
+}
+
+static void esw_sof_dma_rx_callback(void *arg)
+{
+ struct i2s_dev *chip = arg;
+ struct esw_ring_buffer *rb = (struct esw_ring_buffer *)chip->pos[1];
+ struct snd_pcm_substream *substream = chip->rx_substream;
+
+ if (!rb) {
+ dev_err(chip->dev, "pos addr is NULL\n");
+ return;
+ }
+
+ rb->write += snd_pcm_lib_period_bytes(substream);
+ dev_dbg(chip->dev, "read pos:%lld, write pos:%lld, buffer size:%lld\n",
+ rb->read, rb->write, rb->buffer_size);
+}
+
+static int esw_sof_dma_prepare_and_submit(struct i2s_dev *chip,
+ struct snd_pcm_substream *substream)
+{
+ struct dma_chan *chan = chip->chan[substream->stream];
+ struct dma_async_tx_descriptor *desc;
+ enum dma_transfer_direction direction;
+ unsigned long flags = DMA_CTRL_ACK;
+ dma_addr_t dma_addr;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ direction = DMA_MEM_TO_DEV;
+ dma_addr = chip->rb_out_iova;
+ } else {
+ direction = DMA_DEV_TO_MEM;
+ dma_addr = chip->rb_in_iova;
+ }
+
+ if (!substream->runtime->no_period_wakeup)
+ flags |= DMA_PREP_INTERRUPT;
+
+ desc = dmaengine_prep_dma_cyclic(chan, dma_addr,
+ snd_pcm_lib_buffer_bytes(substream),
+ snd_pcm_lib_period_bytes(substream),
+ direction, flags);
+
+ if (!desc)
+ return -ENOMEM;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ desc->callback = esw_sof_dma_tx_callback;
+ } else {
+ desc->callback = esw_sof_dma_rx_callback;
+ }
+
+ desc->callback_param = chip;
+ chip->cookie[substream->stream] = dmaengine_submit(desc);
+
+ return 0;
+}
+
+int esw_sof_dma_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct i2s_dev *chip = dev_get_drvdata(component->dev);
+ struct dma_chan *chan = chip->chan[substream->stream];
+
+ if (!chan) {
+ dev_err(component->dev, "%s dma channel is null\n", __func__);
+ return -ENXIO;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ chip->tx_substream = substream;
+ memset(chip->pos[0], 0, 8);
+ } else {
+ chip->rx_substream = substream;
+ memset(chip->pos[1], 0, 8);
+ }
+
+ return 0;
+}
+
+static int esw_sof_dma_prepare_slave_config(struct i2s_dev *chip,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct dma_slave_config *slave_config)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct esw_i2s_dma_data *dma_data;
+ enum dma_slave_buswidth buswidth;
+ int bits;
+
+ if (rtd->dai_link->num_cpus > 1) {
+ dev_err(rtd->dev,
+ "%s doesn't support Multi CPU yet\n", __func__);
+ return -EINVAL;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dma_data = &chip->play_dma_data;
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ dma_data = &chip->capture_dma_data;
+
+ bits = params_physical_width(params);
+ if (bits < 8 || bits > 64)
+ return -EINVAL;
+ else if (bits == 8)
+ buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ else if (bits == 16)
+ buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ else if (bits == 24)
+ buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES;
+ else if (bits <= 32)
+ buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ else
+ buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ slave_config->direction = DMA_MEM_TO_DEV;
+ slave_config->dst_addr_width = buswidth;
+ } else {
+ slave_config->direction = DMA_DEV_TO_MEM;
+ slave_config->src_addr_width = buswidth;
+ }
+
+ slave_config->device_fc = false;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ slave_config->dst_addr = dma_data->addr;
+ slave_config->dst_maxburst = dma_data->max_burst;
+ if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
+ slave_config->dst_addr_width = dma_data->addr_width;
+ } else {
+ slave_config->src_addr = dma_data->addr;
+ slave_config->src_maxburst = dma_data->max_burst;
+ if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED)
+ slave_config->src_addr_width = dma_data->addr_width;
+ }
+
+ return 0;
+}
+
+int esw_sof_dma_hw_params(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct i2s_dev *chip = dev_get_drvdata(component->dev);
+ struct dma_slave_config slave_config;
+ int ret;
+
+ dev_dbg(chip->dev, "%s\n", __func__);
+
+ memset(&slave_config, 0, sizeof(slave_config));
+
+ ret = esw_sof_dma_prepare_slave_config(chip, substream, params, &slave_config);
+ if (ret)
+ return ret;
+
+ ret = dmaengine_slave_config(chip->chan[substream->stream], &slave_config);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int esw_sof_dma_close(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct i2s_dev *chip = dev_get_drvdata(component->dev);
+
+ dmaengine_synchronize(chip->chan[substream->stream]);
+ return 0;
+}
+
+int esw_sof_dma_trigger(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream, int cmd)
+{
+ struct i2s_dev *chip = dev_get_drvdata(component->dev);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct dma_chan *chan = chip->chan[substream->stream];
+ int ret;
+
+ dev_dbg(chip->dev, "%s, cmd:%d\n", __func__, cmd);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ ret = esw_sof_dma_prepare_and_submit(chip, substream);
+ if (ret) {
+ dev_err(chip->dev, "dma prepare and submit error\n");
+ return ret;
+ }
+ dma_async_issue_pending(chan);
+ break;
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ dmaengine_resume(chan);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ if (runtime->info & SNDRV_PCM_INFO_PAUSE)
+ dmaengine_pause(chan);
+ else
+ dmaengine_terminate_async(chan);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ dmaengine_pause(chan);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ dmaengine_terminate_async(chan);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int esw_sof_dma_init(struct i2s_dev *chip)
+{
+ struct dma_chan *chan0;
+ struct dma_chan *chan1;
+ const char *channel_names0 = "rx";
+ const char *channel_names1 = "tx";
+
+ dev_dbg(chip->dev, "%s\n", __func__);
+
+ chan0 = dma_request_chan(chip->dev, channel_names0);
+ if (IS_ERR(chan0)) {
+ if (PTR_ERR(chan0) == -EPROBE_DEFER) {
+ dev_err(chip->dev, "request dma channel[%d] failed\n", SNDRV_PCM_STREAM_CAPTURE);
+ return -EPROBE_DEFER;
+ }
+ dev_err(chip->dev, "dma channel[%d] is NULL\n", SNDRV_PCM_STREAM_CAPTURE);
+ } else {
+ chip->chan[SNDRV_PCM_STREAM_CAPTURE] = chan0;
+ }
+
+ chan1 = dma_request_chan(chip->dev, channel_names1);
+ if (IS_ERR(chan1)) {
+ if (PTR_ERR(chan1) == -EPROBE_DEFER) {
+ dev_err(chip->dev, "request dma channel[%d] failed\n", SNDRV_PCM_STREAM_PLAYBACK);
+ return -EPROBE_DEFER;
+ }
+ dev_err(chip->dev, "dma channel[%d] is NULL\n", SNDRV_PCM_STREAM_PLAYBACK);
+ } else {
+ chip->chan[SNDRV_PCM_STREAM_PLAYBACK] = chan1;
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig
index 80361139a49a..92e66354e117 100644
--- a/sound/soc/sof/Kconfig
+++ b/sound/soc/sof/Kconfig
@@ -291,5 +291,6 @@ source "sound/soc/sof/imx/Kconfig"
source "sound/soc/sof/intel/Kconfig"
source "sound/soc/sof/mediatek/Kconfig"
source "sound/soc/sof/xtensa/Kconfig"
+source "sound/soc/sof/eswin/Kconfig"
endif
diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile
index 744d40bd8c8b..df2cbbd9dbb0 100644
--- a/sound/soc/sof/Makefile
+++ b/sound/soc/sof/Makefile
@@ -58,3 +58,4 @@ obj-$(CONFIG_SND_SOC_SOF_IMX_TOPLEVEL) += imx/
obj-$(CONFIG_SND_SOC_SOF_AMD_TOPLEVEL) += amd/
obj-$(CONFIG_SND_SOC_SOF_XTENSA) += xtensa/
obj-$(CONFIG_SND_SOC_SOF_MTK_TOPLEVEL) += mediatek/
+obj-$(CONFIG_SND_SOC_SOF_ESWIN_TOPLEVEL) += eswin/
\ No newline at end of file
diff --git a/sound/soc/sof/eswin/Kconfig b/sound/soc/sof/eswin/Kconfig
new file mode 100644
index 000000000000..273e28dcb67b
--- /dev/null
+++ b/sound/soc/sof/eswin/Kconfig
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+
+config SND_SOC_SOF_ESWIN_TOPLEVEL
+ bool "SOF support for ESWIN win2030 audio DSPs"
+ depends on SND_SOC_SOF_OF
+ default n
+ help
+ This adds support for Sound Open Firmware for ESWIN win2030 platforms.
+ Say Y if you have such a device.
+ If unsure select "N".
+
+if SND_SOC_SOF_ESWIN_TOPLEVEL
+
+config SND_SOC_SOF_ESWIN_COMMON
+ bool
+ select SND_SOC_SOF_OF_DEV
+ select SND_SOC_SOF
+ select SND_SOC_SOF_IPC3
+ select SND_SOC_SOF_XTENSA
+ select SND_SOC_SOF_COMPRESS
+ help
+ This option is not user-selectable but automagically handled by
+ 'select' statements at a higher level.
+
+config SND_SOC_SOF_ESWIN
+ tristate "SOF support for eswin"
+ select SND_SOC_SOF_ESWIN_COMMON
+ default n
+ help
+ This adds support for Sound Open Firmware for ESWIN win2030 platforms.
+ Say Y if you have such a device.
+ If unsure select "N".
+
+endif ## SND_SOC_SOF_ESWIN_TOPLEVEL
diff --git a/sound/soc/sof/eswin/Makefile b/sound/soc/sof/eswin/Makefile
new file mode 100644
index 000000000000..dcb9c540b37b
--- /dev/null
+++ b/sound/soc/sof/eswin/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+ccflags-y += -I$(srctree)/drivers/soc/eswin/
+
+snd-sof-eswin-dsp-objs := es-sof-dsp.o es-common.o
+
+obj-$(CONFIG_SND_SOC_SOF_ESWIN) += snd-sof-eswin-dsp.o
diff --git a/sound/soc/sof/eswin/es-common.c b/sound/soc/sof/eswin/es-common.c
new file mode 100644
index 000000000000..22228f4b840e
--- /dev/null
+++ b/sound/soc/sof/eswin/es-common.c
@@ -0,0 +1,591 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESWIN audio sof driver
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: DengLei <denglei@eswincomputing.com>
+ */
+
+#include <linux/module.h>
+#include <sound/sof/xtensa.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/firmware.h>
+#include "../ops.h"
+
+#include "es-common.h"
+
+#define DSP_SUBSYS_HILOAD_CLK 1040000000 //1G
+#define DSP_SUBSYS_LOWLOAD_CLK 5200000
+struct xtensa_exception_cause {
+ u32 id;
+ const char *msg;
+ const char *description;
+};
+
+/*
+ * From 4.4.1.5 table 4-64 Exception Causes of Xtensa
+ * Instruction Set Architecture (ISA) Reference Manual
+ */
+static const struct xtensa_exception_cause xtensa_exception_causes[] = {
+ {0, "IllegalInstructionCause", "Illegal instruction"},
+ {1, "SyscallCause", "SYSCALL instruction"},
+ {2, "InstructionFetchErrorCause",
+ "Processor internal physical address or data error during instruction fetch"},
+ {3, "LoadStoreErrorCause",
+ "Processor internal physical address or data error during load or store"},
+ {4, "Level1InterruptCause",
+ "Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT register"},
+ {5, "AllocaCause",
+ "MOVSP instruction, if callers registers are not in the register file"},
+ {6, "IntegerDivideByZeroCause",
+ "QUOS, QUOU, REMS, or REMU divisor operand is zero"},
+ {8, "PrivilegedCause",
+ "Attempt to execute a privileged operation when CRING ? 0"},
+ {9, "LoadStoreAlignmentCause", "Load or store to an unaligned address"},
+ {12, "InstrPIFDataErrorCause",
+ "PIF data error during instruction fetch"},
+ {13, "LoadStorePIFDataErrorCause",
+ "Synchronous PIF data error during LoadStore access"},
+ {14, "InstrPIFAddrErrorCause",
+ "PIF address error during instruction fetch"},
+ {15, "LoadStorePIFAddrErrorCause",
+ "Synchronous PIF address error during LoadStore access"},
+ {16, "InstTLBMissCause", "Error during Instruction TLB refill"},
+ {17, "InstTLBMultiHitCause",
+ "Multiple instruction TLB entries matched"},
+ {18, "InstFetchPrivilegeCause",
+ "An instruction fetch referenced a virtual address at a ring level less than CRING"},
+ {20, "InstFetchProhibitedCause",
+ "An instruction fetch referenced a page mapped with an attribute that does not permit instruction fetch"},
+ {24, "LoadStoreTLBMissCause",
+ "Error during TLB refill for a load or store"},
+ {25, "LoadStoreTLBMultiHitCause",
+ "Multiple TLB entries matched for a load or store"},
+ {26, "LoadStorePrivilegeCause",
+ "A load or store referenced a virtual address at a ring level less than CRING"},
+ {28, "LoadProhibitedCause",
+ "A load referenced a page mapped with an attribute that does not permit loads"},
+ {32, "Coprocessor0Disabled",
+ "Coprocessor 0 instruction when cp0 disabled"},
+ {33, "Coprocessor1Disabled",
+ "Coprocessor 1 instruction when cp1 disabled"},
+ {34, "Coprocessor2Disabled",
+ "Coprocessor 2 instruction when cp2 disabled"},
+ {35, "Coprocessor3Disabled",
+ "Coprocessor 3 instruction when cp3 disabled"},
+ {36, "Coprocessor4Disabled",
+ "Coprocessor 4 instruction when cp4 disabled"},
+ {37, "Coprocessor5Disabled",
+ "Coprocessor 5 instruction when cp5 disabled"},
+ {38, "Coprocessor6Disabled",
+ "Coprocessor 6 instruction when cp6 disabled"},
+ {39, "Coprocessor7Disabled",
+ "Coprocessor 7 instruction when cp7 disabled"},
+};
+
+/* only need xtensa atm */
+static void xtensa_dsp_oops(struct snd_sof_dev *sdev, const char *level, void *oops)
+{
+ struct sof_ipc_dsp_oops_xtensa *xoops = oops;
+ int i;
+
+ dev_printk(level, sdev->dev, "error: DSP Firmware Oops\n");
+ for (i = 0; i < ARRAY_SIZE(xtensa_exception_causes); i++) {
+ if (xtensa_exception_causes[i].id == xoops->exccause) {
+ dev_printk(level, sdev->dev,
+ "error: Exception Cause: %s, %s\n",
+ xtensa_exception_causes[i].msg,
+ xtensa_exception_causes[i].description);
+ }
+ }
+ dev_printk(level, sdev->dev,
+ "EXCCAUSE 0x%8.8x EXCVADDR 0x%8.8x PS 0x%8.8x SAR 0x%8.8x\n",
+ xoops->exccause, xoops->excvaddr, xoops->ps, xoops->sar);
+ dev_printk(level, sdev->dev,
+ "EPC1 0x%8.8x EPC2 0x%8.8x EPC3 0x%8.8x EPC4 0x%8.8x",
+ xoops->epc1, xoops->epc2, xoops->epc3, xoops->epc4);
+ dev_printk(level, sdev->dev,
+ "EPC5 0x%8.8x EPC6 0x%8.8x EPC7 0x%8.8x DEPC 0x%8.8x",
+ xoops->epc5, xoops->epc6, xoops->epc7, xoops->depc);
+ dev_printk(level, sdev->dev,
+ "EPS2 0x%8.8x EPS3 0x%8.8x EPS4 0x%8.8x EPS5 0x%8.8x",
+ xoops->eps2, xoops->eps3, xoops->eps4, xoops->eps5);
+ dev_printk(level, sdev->dev,
+ "EPS6 0x%8.8x EPS7 0x%8.8x INTENABL 0x%8.8x INTERRU 0x%8.8x",
+ xoops->eps6, xoops->eps7, xoops->intenable, xoops->interrupt);
+}
+
+static void xtensa_stack(struct snd_sof_dev *sdev, const char *level, void *oops,
+ u32 *stack, u32 stack_words)
+{
+ struct sof_ipc_dsp_oops_xtensa *xoops = oops;
+ u32 stack_ptr = xoops->plat_hdr.stackptr;
+ /* 4 * 8chars + 3 ws + 1 terminating NUL */
+ unsigned char buf[4 * 8 + 3 + 1];
+ int i;
+
+ dev_printk(level, sdev->dev, "stack dump from 0x%8.8x\n", stack_ptr);
+
+ /*
+ * example output:
+ * 0x0049fbb0: 8000f2d0 0049fc00 6f6c6c61 00632e63
+ */
+ for (i = 0; i < stack_words; i += 4) {
+ hex_dump_to_buffer(stack + i, 16, 16, 4,
+ buf, sizeof(buf), false);
+ dev_printk(level, sdev->dev, "0x%08x: %s\n", stack_ptr + i * 4, buf);
+ }
+}
+
+const struct dsp_arch_ops es_sof_xtensa_arch_ops = {
+ .dsp_oops = xtensa_dsp_oops,
+ .dsp_stack = xtensa_stack,
+};
+
+/**
+ * eswin_get_registers() - This function is called in case of DSP oops
+ * in order to gather information about the registers, filename and
+ * linenumber and stack.
+ * @sdev: SOF device
+ * @xoops: Stores information about registers.
+ * @panic_info: Stores information about filename and line number.
+ * @stack: Stores the stack dump.
+ * @stack_words: Size of the stack dump.
+ */
+static void eswin_dsp_get_registers(struct snd_sof_dev *sdev,
+ struct sof_ipc_dsp_oops_xtensa *xoops,
+ struct sof_ipc_panic_info *panic_info,
+ u32 *stack, size_t stack_words)
+{
+ u32 offset = sdev->dsp_oops_offset;
+
+ /* first read registers */
+ sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
+
+ /* then get panic info */
+ if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
+ dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
+ xoops->arch_hdr.totalsize);
+ return;
+ }
+ offset += xoops->arch_hdr.totalsize;
+ sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
+
+ /* then get the stack */
+ offset += sizeof(*panic_info);
+ sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
+}
+
+/**
+ * es_dsp_dump() - This function is called when a panic message is
+ * received from the firmware.
+ * @sdev: SOF device
+ * @flags: parameter not used but required by ops prototype
+ */
+void es_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
+{
+ struct sof_ipc_dsp_oops_xtensa xoops;
+ struct sof_ipc_panic_info panic_info;
+ u32 stack[ESWIN_DSP_STACK_DUMP_SIZE];
+ u32 status;
+
+ /* Get information about the panic status from the debug box area.
+ * Compute the trace point based on the status.
+ */
+ sof_mailbox_read(sdev, sdev->debug_box.offset + 0x4, &status, 4);
+
+ /* Get information about the registers, the filename and line
+ * number and the stack.
+ */
+ eswin_dsp_get_registers(sdev, &xoops, &panic_info, stack,
+ ESWIN_DSP_STACK_DUMP_SIZE);
+
+ /* Print the information to the console */
+ sof_print_oops_and_stack(sdev, KERN_ERR, status, status, &xoops,
+ &panic_info, stack, ESWIN_DSP_STACK_DUMP_SIZE);
+}
+
+int es_dsp_ring_doorbell(struct es_dsp_ipc *ipc, void *msg)
+{
+ int ret;
+ struct es_dsp_chan *dsp_chan;
+
+ dsp_chan = &ipc->chan;
+ ret = mbox_send_message(dsp_chan->ch, msg);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void es_dsp_handle_rx(struct mbox_client *c, void *msg)
+{
+ struct es_dsp_chan *chan = container_of(c, struct es_dsp_chan, cl);
+ u32 dsp_msg = *(u32 *)msg;
+
+ if (dsp_msg == IPC_MSG_RP_FLAG) {
+ chan->ipc->ops->handle_reply(chan->ipc);
+ } else {
+ chan->ipc->ops->handle_request(chan->ipc);
+ }
+}
+
+static void es_dsp_tx_done(struct mbox_client *cl, void *mssg, int r)
+{
+ if (mssg)
+ kfree(mssg);
+}
+
+struct mbox_chan *es_dsp_request_channel(struct es_dsp_ipc *dsp_ipc)
+{
+ struct es_dsp_chan *dsp_chan;
+
+ dsp_chan = &dsp_ipc->chan;
+ dsp_chan->ch = mbox_request_channel_byname(&dsp_chan->cl, dsp_chan->name);
+ return dsp_chan->ch;
+}
+
+void es_dsp_free_channel(struct es_dsp_ipc *dsp_ipc)
+{
+ struct es_dsp_chan *dsp_chan;
+
+ dsp_chan = &dsp_ipc->chan;
+ mbox_free_channel(dsp_chan->ch);
+}
+
+static int es_dsp_setup_channels(struct es_dsp_ipc *dsp_ipc)
+{
+ struct device *dev = dsp_ipc->dev;
+ struct es_dsp_chan *dsp_chan;
+ struct mbox_client *cl;
+ char *chan_name;
+ int ret;
+
+ chan_name = "dsp-mbox";
+
+ dsp_chan = &dsp_ipc->chan;
+ dsp_chan->name = chan_name;
+ cl = &dsp_chan->cl;
+ cl->dev = dev;
+ cl->tx_block = false;
+ cl->knows_txdone = false;
+ cl->rx_callback = es_dsp_handle_rx;
+ cl->tx_done = es_dsp_tx_done;
+
+ dsp_chan->ipc = dsp_ipc;
+ dsp_chan->ch = mbox_request_channel_byname(cl, chan_name);
+ if (IS_ERR(dsp_chan->ch)) {
+ ret = PTR_ERR(dsp_chan->ch);
+ dev_err(dev, "Failed to request mbox chan %s ret %d\n", chan_name, ret);
+ return ret;
+ }
+
+ dev_info(dev, "request mbox chan %s\n", chan_name);
+
+ return 0;
+}
+
+struct es_dsp_ipc *es_ipc_init(struct snd_sof_dev *sdev)
+{
+ struct es_dsp_ipc *dsp_ipc;
+ int ret;
+
+ dsp_ipc = devm_kzalloc(sdev->dev, sizeof(*dsp_ipc), GFP_KERNEL);
+ if (!dsp_ipc)
+ return NULL;
+
+ dsp_ipc->dev = sdev->dev;
+
+ ret = es_dsp_setup_channels(dsp_ipc);
+ if (ret < 0)
+ return NULL;
+
+ dev_info(sdev->dev, "ESW DSP IPC initialized\n");
+
+ return dsp_ipc;
+}
+
+int es_get_hw_res(struct snd_sof_dev *sdev)
+{
+ struct es_sof_priv *priv = (struct es_sof_priv *)sdev->pdata->hw_pdata;
+ struct device_node *nd;
+ struct resource res;
+ int ret;
+
+ ret = of_address_to_resource(sdev->dev->of_node, 0, &res);
+ if (ret) {
+ dev_err(sdev->dev, "failed to get dsp iram address\n");
+ return ret;
+ }
+ of_node_put(sdev->dev->of_node);
+ priv->dsp_iram_phyaddr = res.start;
+ priv->dsp_iram_size = resource_size(&res);
+
+
+ ret = of_address_to_resource(sdev->dev->of_node, 1, &res);
+ if (ret) {
+ dev_err(sdev->dev, "failed to get dsp dram address\n");
+ return ret;
+ }
+ of_node_put(sdev->dev->of_node);
+ priv->dsp_dram_phyaddr = res.start;
+ priv->dsp_dram_size = resource_size(&res);
+
+ ret = device_property_read_u32(sdev->dev, "process-id", &(priv->process_id));
+ if (0 != ret) {
+ dev_err(sdev->dev, "Failed to get process id\n");
+ return ret;
+ }
+
+ ret = device_property_read_u32(sdev->dev, "mailbox-dsp-to-u84-addr", &priv->mbox_rx_phyaddr);
+ if (0 != ret) {
+ dev_err(sdev->dev, "failed to get mailbox rx addr\n");
+ return ret;
+ }
+
+ ret = device_property_read_u32(sdev->dev, "mailbox-u84-to-dsp-addr", &priv->mbox_tx_phyaddr);
+ if (0 != ret) {
+ dev_err(sdev->dev, "failed to get mailbox tx addr\n");
+ return ret;
+ }
+
+ /* get aclk */
+ priv->aclk = devm_clk_get(sdev->dev, "aclk");
+ if (IS_ERR(priv->aclk)) {
+ ret = PTR_ERR(priv->aclk);
+ dev_err(sdev->dev, "failed to get aclk: %d\n", ret);
+ return ret;
+ }
+
+ nd = of_parse_phandle(sdev->dev->of_node, "dsp-uart", 0);
+ if (!nd) {
+ dev_err(sdev->dev, "failed to get uart node\n");
+ return -ENODEV;
+ }
+ of_node_put(sdev->dev->of_node);
+
+ ret = of_address_to_resource(nd, 0, &res);
+ if (ret) {
+ dev_err(sdev->dev, "failed to get dsp uart address\n");
+ return ret;
+ }
+ of_node_put(nd);
+ priv->uart_phyaddr = res.start;
+ priv->uart_reg_size = resource_size(&res);
+
+ ret = device_property_read_u32(sdev->dev, "device-uart-mutex", &priv->uart_mutex_phyaddr);
+ if (0 != ret) {
+ dev_err(sdev->dev, "Failed to get uart mutex reg base\n");
+ return ret;
+ }
+
+ nd = of_parse_phandle(sdev->dev->of_node, "ringbuffer-region", 0);
+ if (!nd) {
+ dev_err(sdev->dev, "failed to get ringbuffer region node\n");
+ return -ENODEV;
+ }
+ of_node_put(sdev->dev->of_node);
+
+ ret = of_address_to_resource(nd, 0, &res);
+ if (ret) {
+ dev_err(sdev->dev, "failed to get ring buffer address\n");
+ return ret;
+ }
+ of_node_put(nd);
+
+ priv->ringbuffer_phyaddr = res.start;
+ priv->ringbuffer_size = resource_size(&res);
+
+ return ret;
+}
+
+int es_dsp_get_subsys(struct snd_sof_dev *sdev)
+{
+ struct device *parent;
+ struct es_dsp_subsys *subsys;
+ struct es_sof_priv *priv = (struct es_sof_priv *)sdev->pdata->hw_pdata;
+
+ parent = priv->dev->parent;
+ subsys = dev_get_drvdata(parent);
+ if (IS_ERR_OR_NULL(subsys)) {
+ return -EPROBE_DEFER;
+ }
+ if (!try_module_get(subsys->pdev->dev.driver->owner)) {
+ dev_err(sdev->dev, "error try get dsp subsys module.\n");
+ return -EIO;
+ }
+
+ get_device(&subsys->pdev->dev);
+ priv->dsp_subsys = subsys;
+ return 0;
+}
+
+void es_dsp_put_subsys(struct snd_sof_dev *sdev)
+{
+ struct es_dsp_subsys *subsys;
+ struct es_sof_priv *priv = (struct es_sof_priv *)sdev->pdata->hw_pdata;
+
+ subsys = priv->dsp_subsys;
+ put_device(&subsys->pdev->dev);
+ module_put(subsys->pdev->dev.driver->owner);
+ return;
+}
+
+static int es_dsp_set_rate(struct es_sof_priv *priv, unsigned long rate)
+{
+ int ret;
+
+ rate = clk_round_rate(priv->aclk, rate);
+ if (rate > 0) {
+ ret = clk_set_rate(priv->aclk, rate);
+ if (ret) {
+ dev_err(priv->dev, "failed to set aclk: %d\n", ret);
+ return ret;
+ }
+ }
+ dev_info(priv->dev, "set device rate to %ldHZ\n", rate);
+ return 0;
+}
+
+int es_dsp_hw_init(struct snd_sof_dev *sdev)
+{
+ int ret;
+ struct es_sof_priv *priv = (struct es_sof_priv *)sdev->pdata->hw_pdata;
+
+ ret = iommu_map_rsv_iova_with_phys(sdev->dev,
+ (dma_addr_t)DSP_UART_IOVA,
+ priv->uart_reg_size,
+ priv->uart_phyaddr, IOMMU_MMIO);
+ if (ret != 0) {
+ dev_err(sdev->dev, "uart iommu map error\n");
+ return ret;
+ }
+ priv->uart_dev_addr = DSP_UART_IOVA;
+
+ ret = iommu_map_rsv_iova_with_phys(
+ sdev->dev, (dma_addr_t)DSP_UART_MUTEX_IOVA,
+ DSP_UART_MUTEX_IOVA_SIZE, priv->uart_mutex_phyaddr,
+ IOMMU_MMIO);
+ if (ret != 0) {
+ dev_err(sdev->dev, "uart mutex iommu map error\n");
+ ret = -ENOMEM;
+ goto err_map_uart;
+ }
+ priv->uart_mutex_dev_addr = DSP_UART_MUTEX_IOVA;
+
+ ret = iommu_map_rsv_iova_with_phys(sdev->dev,
+ (dma_addr_t)DSP_MBOX_TX_IOVA,
+ DSP_MBOX_IOVA_SIZE,
+ priv->mbox_tx_phyaddr, IOMMU_MMIO);
+ if (ret != 0) {
+ dev_err(sdev->dev, "mailbox tx iommu map error\n");
+ ret = -ENOMEM;
+ goto err_map_uart_mutex;
+ }
+ priv->mbox_tx_dev_addr = DSP_MBOX_TX_IOVA;
+
+ ret = iommu_map_rsv_iova_with_phys(sdev->dev,
+ (dma_addr_t)DSP_MBOX_RX_IOVA,
+ DSP_MBOX_IOVA_SIZE,
+ priv->mbox_rx_phyaddr, IOMMU_MMIO);
+ if (ret != 0) {
+ dev_err(sdev->dev, "mailbox rx iommu map error\n");
+ ret = -ENOMEM;
+ goto err_map_mbox_tx;
+ }
+ priv->mbox_rx_dev_addr = DSP_MBOX_RX_IOVA;
+
+ priv->firmware_addr =
+ iommu_map_rsv_iova(sdev->dev, (dma_addr_t)DSP_FIRMWARE_IOVA,
+ DSP_FIRMWARE_IOVA_SIZE, GFP_KERNEL, 0);
+ if (IS_ERR_OR_NULL(priv->firmware_addr)) {
+ dev_err(sdev->dev, "failed to alloc firmware memory\n");
+ ret = -ENOMEM;
+ goto err_map_mbox_rx;
+ }
+ priv->firmware_dev_addr = DSP_FIRMWARE_IOVA;
+ sdev->bar[SOF_FW_BLK_TYPE_SRAM] = priv->firmware_addr;
+
+ ret = iommu_map_rsv_iova_with_phys(sdev->dev, (dma_addr_t)DSP_RING_BUFFER_IOVA,
+ priv->ringbuffer_size, priv->ringbuffer_phyaddr, IOMMU_MMIO);
+ if (ret != 0) {
+ dev_err(sdev->dev, "failed to map ringbuffer memory\n");
+ ret = -ENOMEM;
+ goto err_map_fw;
+ }
+ priv->ringbuffer_dev_addr = DSP_RING_BUFFER_IOVA;
+
+ if (request_mem_region(priv->dsp_iram_phyaddr, priv->dsp_iram_size,
+ "DSP_IRAM_BASE") == NULL) {
+ dev_err(sdev->dev, "request dsp iram mem region error\n");
+ ret = -EBUSY;
+ goto err_map_rb;
+ }
+ sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev, priv->dsp_iram_phyaddr,
+ priv->dsp_iram_size);
+ if (IS_ERR_OR_NULL(sdev->bar[SOF_FW_BLK_TYPE_IRAM])) {
+ dev_err(sdev->dev, "failed to remap dsp iram\n");
+ ret = -ENOMEM;
+ goto err_map_iram_region;
+ }
+ sdev->mmio_bar = SOF_FW_BLK_TYPE_IRAM;
+
+ if (request_mem_region(priv->dsp_dram_phyaddr, priv->dsp_dram_size,
+ "DSP_DRAM_BASE") == NULL) {
+ dev_err(sdev->dev, "request dsp dram mem region error\n");
+ ret = -EBUSY;
+ goto err_map_iram_region;
+ }
+ sdev->bar[SOF_FW_BLK_TYPE_DRAM] = devm_ioremap(sdev->dev, priv->dsp_dram_phyaddr,
+ priv->dsp_dram_size);
+ if (IS_ERR_OR_NULL(sdev->bar[SOF_FW_BLK_TYPE_DRAM])) {
+ dev_err(sdev->dev, "failed to remap dsp dram\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ es_dsp_set_rate(priv, DSP_SUBSYS_HILOAD_CLK);
+
+ return 0;
+err:
+ release_mem_region(priv->dsp_dram_phyaddr, priv->dsp_dram_size);
+err_map_iram_region:
+ release_mem_region(priv->dsp_iram_phyaddr, priv->dsp_iram_size);
+err_map_rb:
+ iommu_unmap_rsv_iova(sdev->dev, NULL,
+ priv->ringbuffer_dev_addr, priv->ringbuffer_size);
+err_map_fw:
+ iommu_unmap_rsv_iova(sdev->dev, priv->firmware_addr,
+ priv->firmware_dev_addr, DSP_FIRMWARE_IOVA_SIZE);
+ priv->firmware_addr = NULL;
+err_map_mbox_rx:
+ iommu_unmap_rsv_iova(sdev->dev, NULL, priv->mbox_rx_dev_addr,
+ DSP_MBOX_IOVA_SIZE);
+err_map_mbox_tx:
+ iommu_unmap_rsv_iova(sdev->dev, NULL, priv->mbox_tx_dev_addr,
+ DSP_MBOX_IOVA_SIZE);
+err_map_uart_mutex:
+ iommu_unmap_rsv_iova(sdev->dev, NULL, priv->uart_mutex_dev_addr,
+ DSP_UART_MUTEX_IOVA_SIZE);
+err_map_uart:
+ iommu_unmap_rsv_iova(sdev->dev, NULL, priv->uart_dev_addr,
+ priv->uart_reg_size);
+ return ret;
+}
\ No newline at end of file
diff --git a/sound/soc/sof/eswin/es-common.h b/sound/soc/sof/eswin/es-common.h
new file mode 100644
index 000000000000..415ccb866d74
--- /dev/null
+++ b/sound/soc/sof/eswin/es-common.h
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESWIN audio sof driver
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: DengLei <denglei@eswincomputing.com>
+ */
+
+#ifndef __ES_COMMON_H__
+#define __ES_COMMON_H__
+
+#include <linux/clk.h>
+#include <linux/mailbox_client.h>
+#include <linux/es_iommu_rsv.h>
+#include <linux/iommu.h>
+#include "eswin-dsp-subsys.h"
+
+#define EXCEPT_MAX_HDR_SIZE 0x400
+#define ESWIN_DSP_STACK_DUMP_SIZE 32
+
+#define DSP_UART_MUTEX_IOVA 0xff5c0000
+#define DSP_UART_IOVA 0xff5d0000
+#define DSP_MBOX_TX_IOVA 0xff5e0000
+#define DSP_MBOX_RX_IOVA 0xff5f0000
+#define DSP_RING_BUFFER_IOVA 0xff600000
+#define DSP_FIRMWARE_IOVA 0xff800000
+
+#define DSP_UART_MUTEX_IOVA_SIZE 0x10000
+#define DSP_MBOX_IOVA_SIZE 0x10000
+#define DSP_FIRMWARE_IOVA_SIZE 0x800000
+
+#define UART_MUTEX_BASE_ADDR 0x51820000
+#define UART_MUTEX_UNIT_OFFSET 4
+
+#define IPC_MSG_RQ_FLAG 1
+#define IPC_MSG_RP_FLAG 2
+
+struct es_dsp_chan {
+ struct es_dsp_ipc *ipc;
+ struct mbox_client cl;
+ struct mbox_chan *ch;
+ char *name;
+};
+
+struct es_dsp_ops {
+ void (*handle_reply)(struct es_dsp_ipc *ipc);
+ void (*handle_request)(struct es_dsp_ipc *ipc);
+};
+
+struct es_dsp_ipc {
+ /* Host <-> DSP communication uses 2 txdb and 2 rxdb channels */
+ struct es_dsp_chan chan;
+ struct device *dev;
+ struct es_dsp_ops *ops;
+ void *private_data;
+};
+
+struct es_sof_priv {
+ struct device *dev;
+ struct snd_sof_dev *sdev;
+
+ /* DSP IPC handler */
+ struct es_dsp_ipc *dsp_ipc;
+ struct es_dsp_subsys *dsp_subsys;
+ struct clk *aclk;
+
+ u32 process_id;
+ u32 dsp_iram_phyaddr;
+ u64 dsp_iram_size;
+ u32 dsp_dram_phyaddr;
+ u64 dsp_dram_size;
+ u32 uart_phyaddr;
+ u64 uart_reg_size;
+ u32 uart_mutex_phyaddr;
+ u32 mbox_tx_phyaddr;
+ u32 mbox_rx_phyaddr;
+ u32 ringbuffer_phyaddr;
+ u32 ringbuffer_size;
+ void *firmware_addr;
+ dma_addr_t firmware_dev_addr;
+ dma_addr_t ringbuffer_dev_addr;
+ dma_addr_t uart_dev_addr;
+ dma_addr_t uart_mutex_dev_addr;
+ dma_addr_t mbox_tx_dev_addr;
+ dma_addr_t mbox_rx_dev_addr;
+ bool dsp_hw_init_done;
+};
+
+static inline void es_dsp_set_data(struct es_dsp_ipc *ipc, void *data)
+{
+ if (!ipc)
+ return;
+
+ ipc->private_data = data;
+}
+
+static inline void *es_dsp_get_data(struct es_dsp_ipc *ipc)
+{
+ if (!ipc)
+ return NULL;
+
+ return ipc->private_data;
+}
+
+void es_dsp_put_subsys(struct snd_sof_dev *sdev);
+
+int es_dsp_get_subsys(struct snd_sof_dev *sdev);
+
+int es_dsp_ring_doorbell(struct es_dsp_ipc *dsp, void *msg);
+
+struct mbox_chan *es_dsp_request_channel(struct es_dsp_ipc *ipc);
+void es_dsp_free_channel(struct es_dsp_ipc *ipc);
+
+void es_dsp_dump(struct snd_sof_dev *sdev, u32 flags);
+
+struct es_dsp_ipc *es_ipc_init(struct snd_sof_dev *sdev);
+
+int es_get_hw_res(struct snd_sof_dev *sdev);
+
+int es_dsp_hw_init(struct snd_sof_dev *sdev);
+
+extern const struct dsp_arch_ops es_sof_xtensa_arch_ops;
+
+#endif
diff --git a/sound/soc/sof/eswin/es-sof-dsp.c b/sound/soc/sof/eswin/es-sof-dsp.c
new file mode 100644
index 000000000000..41cb55ba8d71
--- /dev/null
+++ b/sound/soc/sof/eswin/es-sof-dsp.c
@@ -0,0 +1,614 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESWIN audio sof driver
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * Authors: DengLei <denglei@eswincomputing.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/firmware.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/dma-map-ops.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <sound/sof.h>
+#include <sound/sof/xtensa.h>
+#include <linux/reset.h>
+#include <linux/eswin-win2030-sid-cfg.h>
+#include <linux/of_reserved_mem.h>
+#include <dt-bindings/memory/eswin-win2030-sid.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#include "../ops.h"
+#include "../sof-of-dev.h"
+#include "es-common.h"
+
+#define MBOX_OFFSET 0x600000
+#define MBOX_SIZE 0x1000
+
+#define REG_OFFSET_DSP_START 0x00
+#define REG_OFFSET_DSP_STAT 0x04
+#define REG_OFFSET_DSP_PRID 0x08
+#define REG_OFFSET_DSP_RESET 0x18
+#define REG_OFFSET_DSP_DYARID 0x504
+#define REG_OFFSET_DSP_DYAWID 0x508
+#define REG_OFFSET_USR_CONF0 0x1c
+
+//bit definitions for REG_OFFSET_DSP_STAT
+#define DSP_STAT_REG_BIT_STAT_VECTOR_SEL BIT_ULL(0)
+#define DSP_STAT_REG_BIT_ARID_DYNM_EN BIT_ULL(4)
+#define DSP_STAT_REG_BITS_ARMMUSID GENMASK_ULL(23, 16)
+
+//bit definitions for REG_OFFSET_DSP_PRID
+#define DSP_PRID_REG_BIT_PRID_MASK GENMASK_ULL(15, 0)
+
+//bit definitions for REG_OFFSET_DSP_RESET
+#define DSP_RESET_REG_BIT_RUNSTALL_ON_RESET BIT_ULL(0)
+#define DSP_RESET_REG_BIT_CORE_RESET BIT_ULL(1)
+#define DSP_RESET_REG_BIT_DEBUG_RESET BIT_ULL(2)
+
+#define FIRMWARE_SIZE_MAX 0x800000 // 8M
+
+//bit definitions for REG_OFFSET_DSP_DYAWID
+#define DSP_DYAWID_REG_BITS_ARMMUSID_MASK GENMASK(23, 16)
+#define DSP_DYAWID_REG_BITS_AWMMUSID_MASK GENMASK(23, 16)
+#define REG_DEFAULT_SIZE 0x10000
+#define REG_OFFSET_SIZE 0x20
+#define REG_OFFSET_SIZE_8 0x8
+
+#define REG_OFFSET(reg, pro_id) (reg + (REG_OFFSET_SIZE * pro_id))
+#define REG_OFFSET_8(reg, pro_id) (reg + (REG_OFFSET_SIZE_8 * pro_id))
+
+static int es_sof_get_mailbox_offset(struct snd_sof_dev *sdev)
+{
+ return MBOX_OFFSET;
+}
+
+static int es_sof_get_window_offset(struct snd_sof_dev *sdev, u32 id)
+{
+ return MBOX_OFFSET;
+}
+
+static void es_sof_handle_reply(struct es_dsp_ipc *ipc)
+{
+ struct es_sof_priv *priv = es_dsp_get_data(ipc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->sdev->ipc_lock, flags);
+ snd_sof_ipc_process_reply(priv->sdev, 0);
+ spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags);
+}
+
+static void es_sof_handle_request(struct es_dsp_ipc *ipc)
+{
+ struct es_sof_priv *priv = es_dsp_get_data(ipc);
+ u32 p; /* Panic code */
+ unsigned long flags;
+ spin_lock_irqsave(&priv->sdev->ipc_lock, flags);
+
+ /* Read the message from the debug box. */
+ sof_mailbox_read(priv->sdev, priv->sdev->debug_box.offset + 4, &p, sizeof(p));
+
+ /* Check to see if the message is a panic code (0x0dead***) */
+ if ((p & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC){
+ snd_sof_dsp_panic(priv->sdev, p, true);
+ }
+ else
+ snd_sof_ipc_msgs_rx(priv->sdev);
+
+ spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags);
+}
+
+static struct es_dsp_ops dsp_ops = {
+ .handle_reply = es_sof_handle_reply,
+ .handle_request = es_sof_handle_request,
+};
+
+static int es_sof_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
+{
+ struct es_sof_priv *priv = sdev->pdata->hw_pdata;
+ u64 *msg_flag = kzalloc(sizeof(u64), GFP_ATOMIC);
+ if (!msg_flag)
+ return -ENOMEM;
+
+ *msg_flag = IPC_MSG_RQ_FLAG;
+
+ sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
+ msg->msg_size);
+ es_dsp_ring_doorbell(priv->dsp_ipc, msg_flag);
+ return 0;
+}
+
+/*
+ * DSP control.
+ */
+
+static int es_dsp_run(struct snd_sof_dev *sdev)
+{
+ int ret;
+ struct es_sof_priv *priv = (struct es_sof_priv *)sdev->pdata->hw_pdata;
+
+ dev_info(sdev->dev, "%s\n", __func__);
+
+ dma_sync_single_for_device(sdev->dev, priv->firmware_dev_addr, DSP_FIRMWARE_IOVA_SIZE,
+ DMA_BIDIRECTIONAL);
+
+ /*dereset dsp core*/
+ ret = regmap_clear_bits(priv->dsp_subsys->map,
+ REG_OFFSET(REG_OFFSET_DSP_RESET, priv->process_id),
+ DSP_RESET_REG_BIT_RUNSTALL_ON_RESET);
+ WARN_ON(0 != ret);
+
+ return ret;
+}
+
+static int es_dsp_reset(struct snd_sof_dev *sdev)
+{
+ int ret;
+ struct es_sof_priv *priv = (struct es_sof_priv *)sdev->pdata->hw_pdata;
+
+ dev_info(sdev->dev, "%s\n", __func__);
+
+ //halt
+ ret = regmap_set_bits(priv->dsp_subsys->map,
+ REG_OFFSET(REG_OFFSET_DSP_RESET, priv->process_id),
+ DSP_RESET_REG_BIT_RUNSTALL_ON_RESET);
+ WARN_ON(0 != ret);
+ /*reset dsp core*/
+ ret = regmap_set_bits(priv->dsp_subsys->map,
+ REG_OFFSET(REG_OFFSET_DSP_RESET,
+ priv->process_id),
+ DSP_RESET_REG_BIT_DEBUG_RESET);
+ WARN_ON(0 != ret);
+ ret = regmap_set_bits(priv->dsp_subsys->map,
+ REG_OFFSET(REG_OFFSET_DSP_RESET, priv->process_id),
+ DSP_RESET_REG_BIT_CORE_RESET);
+ WARN_ON(0 != ret);
+ mdelay(20);
+ /*set processer id*/
+ ret = regmap_write_bits(priv->dsp_subsys->map,
+ REG_OFFSET(REG_OFFSET_DSP_PRID, priv->process_id),
+ DSP_PRID_REG_BIT_PRID_MASK, priv->process_id);
+ WARN_ON(0 != ret);
+ /*set reset vector*/
+ ret = regmap_write(priv->dsp_subsys->map, REG_OFFSET(REG_OFFSET_DSP_START, priv->process_id),
+ priv->firmware_dev_addr);
+ WARN_ON(0 != ret);
+ ret = regmap_set_bits(priv->dsp_subsys->map, REG_OFFSET(REG_OFFSET_DSP_STAT, priv->process_id),
+ DSP_STAT_REG_BIT_STAT_VECTOR_SEL);
+ WARN_ON(0 != ret);
+ /*dereset dsp core*/
+ ret = regmap_clear_bits(priv->dsp_subsys->map, REG_OFFSET(REG_OFFSET_DSP_RESET, priv->process_id),
+ DSP_RESET_REG_BIT_CORE_RESET);
+
+ /*set smmu id*/
+ ret = regmap_write_bits(priv->dsp_subsys->map, REG_OFFSET_8(REG_OFFSET_DSP_DYAWID, priv->process_id),
+ DSP_DYAWID_REG_BITS_AWMMUSID_MASK, (WIN2030_SID_DSP_0 + priv->process_id) << 16);
+ WARN_ON(0 != ret);
+
+ ret = regmap_write_bits(priv->dsp_subsys->map, REG_OFFSET_8(REG_OFFSET_DSP_DYARID, priv->process_id),
+ DSP_DYAWID_REG_BITS_ARMMUSID_MASK, (WIN2030_SID_DSP_0 + priv->process_id) << 16);
+ WARN_ON(0 != ret);
+
+ ret = win2030_dynm_sid_enable(dev_to_node(sdev->dev));
+ WARN_ON(0 != ret);
+
+ /*enable jtag*/
+ ret = regmap_write(priv->dsp_subsys->con_map, 0x330, 0xF0F0);
+ WARN_ON(0 != ret);
+
+ /*dereset dsp debug*/
+ ret = regmap_clear_bits(priv->dsp_subsys->map, REG_OFFSET(REG_OFFSET_DSP_RESET, priv->process_id),
+ DSP_RESET_REG_BIT_DEBUG_RESET);
+ WARN_ON(0 != ret);
+
+ return 0;
+}
+
+static int es_dsp_clk_enable(struct es_sof_priv *priv)
+{
+ int ret;
+ u32 val;
+ bool enabled;
+
+ ret = clk_prepare_enable(priv->dsp_subsys->cfg_clk);
+ if (ret) {
+ dev_err(priv->dev, "failed to enable cfg clk, ret=%d.\n", ret);
+ return ret;
+ }
+ enabled = __clk_is_enabled(priv->dsp_subsys->aclk);
+ if (!enabled) {
+ ret = clk_prepare_enable(priv->dsp_subsys->aclk);
+ if (ret) {
+ dev_err(priv->dev, "failed to enable aclk: %d\n", ret);
+ return ret;
+ }
+ }
+
+ regmap_read(priv->dsp_subsys->map, REG_OFFSET_USR_CONF0, &val);
+ val |= (3 << (priv->process_id * 2));
+ ret = regmap_write(priv->dsp_subsys->map, REG_OFFSET_USR_CONF0, val);
+ regmap_read(priv->dsp_subsys->map, REG_OFFSET_USR_CONF0, &val);
+ dev_info(priv->dev, "%s, %d, val=0x%x.\n", __func__, __LINE__, val);
+
+ return 0;
+}
+
+static int es_dsp_probe(struct snd_sof_dev *sdev)
+{
+ struct es_sof_priv *priv;
+ int ret = 0;
+
+ dev_info(sdev->dev, "%s\n", __func__);
+
+ priv = devm_kzalloc(sdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ return -ENOMEM;
+ }
+ sdev->num_cores = 1;
+ sdev->pdata->hw_pdata = priv;
+ priv->dev = sdev->dev;
+ priv->sdev = sdev;
+
+ ret = es_dsp_get_subsys(sdev);
+ if (ret) {
+ dev_err(sdev->dev, "get dsp subsys err, ret=%d.\n", ret);
+ return -ENXIO;
+ }
+
+ ret = es_get_hw_res(sdev);
+ if (ret) {
+ dev_err(sdev->dev, "get hw res error.\n");
+ goto err_release_subsys;
+ }
+
+ /* setting for DMA check */
+ ret = dma_set_mask(sdev->dev, DMA_BIT_MASK(32));
+ if (ret) {
+ WARN_ON_ONCE(sdev->dev->dma_mask);
+ goto err_release_subsys;
+ }
+
+ priv->dsp_ipc = es_ipc_init(sdev);
+ if (!priv->dsp_ipc) {
+ /* DSP IPC driver not probed yet, try later */
+ dev_err(sdev->dev, "Failed to init ipc channel\n");
+ goto err_release_subsys;
+ }
+ es_dsp_set_data(priv->dsp_ipc, priv);
+ priv->dsp_ipc->ops = &dsp_ops;
+
+ ret = es_dsp_clk_enable(priv);
+ if (0 != ret) {
+ dev_err(sdev->dev, "Failed to enable subsys clk\n");
+ goto err_release_ipc;
+ }
+
+ ret = win2030_tbu_power(sdev->dev, true);
+ if (ret) {
+ dev_err(sdev->dev, "tbu power failed\n");
+ goto err;
+ }
+
+ sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM;
+ /* set default mailbox offset for FW ready message */
+ sdev->dsp_box.offset = MBOX_OFFSET;
+
+ ret = es_dsp_hw_init(sdev);
+ if (ret) {
+ goto err;
+ }
+ priv->dsp_hw_init_done = true;
+
+ return 0;
+
+err:
+ clk_disable_unprepare(priv->aclk);
+err_release_ipc:
+ es_dsp_free_channel(priv->dsp_ipc);
+err_release_subsys:
+ es_dsp_put_subsys(sdev);
+ return ret;
+}
+
+static int es_dsp_remove(struct snd_sof_dev *sdev)
+{
+ dev_info(sdev->dev, "%s\n", __func__);
+ struct es_sof_priv *priv = (struct es_sof_priv *)sdev->pdata->hw_pdata;
+
+ if (!priv || !priv->dsp_hw_init_done) {
+ return 0;
+ }
+
+ iommu_unmap_rsv_iova(sdev->dev, NULL, priv->ringbuffer_dev_addr,
+ priv->ringbuffer_size);
+ iommu_unmap_rsv_iova(sdev->dev, priv->firmware_addr,
+ priv->firmware_dev_addr, DSP_FIRMWARE_IOVA_SIZE);
+ priv->firmware_addr = NULL;
+ iommu_unmap_rsv_iova(sdev->dev, NULL, priv->mbox_rx_dev_addr,
+ DSP_MBOX_IOVA_SIZE);
+ iommu_unmap_rsv_iova(sdev->dev, NULL, priv->mbox_tx_dev_addr,
+ DSP_MBOX_IOVA_SIZE);
+ iommu_unmap_rsv_iova(sdev->dev, NULL, priv->uart_mutex_dev_addr,
+ DSP_UART_MUTEX_IOVA_SIZE);
+ iommu_unmap_rsv_iova(sdev->dev, NULL, priv->uart_dev_addr,
+ priv->uart_reg_size);
+ release_mem_region(priv->dsp_iram_phyaddr, priv->dsp_iram_size);
+ release_mem_region(priv->dsp_dram_phyaddr, priv->dsp_dram_size);
+
+ es_dsp_free_channel(priv->dsp_ipc);
+ es_dsp_put_subsys(sdev);
+ return 0;
+}
+
+static int es_sof_get_bar_index(struct snd_sof_dev *sdev, u32 type)
+{
+ /* Only IRAM and SRAM bars are valid */
+ switch (type) {
+ case SOF_FW_BLK_TYPE_IRAM:
+ case SOF_FW_BLK_TYPE_DRAM:
+ case SOF_FW_BLK_TYPE_SRAM:
+ return type;
+ default:
+ dev_err(sdev->dev, "error type:%d\n", type);
+ return -EINVAL;
+ }
+}
+
+static struct snd_soc_dai_driver es_sof_dai[] = {
+{
+ .name = "dsp_port",
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+},
+{
+ .name = "dsp_port2",
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+},
+{
+ .name = "dsp_port3",
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+},
+};
+
+static int es_sof_dsp_set_power_state(struct snd_sof_dev *sdev,
+ const struct sof_dsp_power_state *target_state)
+{
+ sdev->dsp_power_state = *target_state;
+
+ return 0;
+}
+
+static int es_sof_resume(struct snd_sof_dev *sdev)
+{
+ struct es_sof_priv *priv = (struct es_sof_priv *)sdev->pdata->hw_pdata;
+
+ es_dsp_request_channel(priv->dsp_ipc);
+ return 0;
+}
+
+static void es_sof_suspend(struct snd_sof_dev *sdev)
+{
+ struct es_sof_priv *priv = (struct es_sof_priv *)sdev->pdata->hw_pdata;
+
+ es_dsp_free_channel(priv->dsp_ipc);
+}
+
+static int es_sof_dsp_runtime_resume(struct snd_sof_dev *sdev)
+{
+ int ret;
+ const struct sof_dsp_power_state target_dsp_state = {
+ .state = SOF_DSP_PM_D0,
+ };
+
+ ret = es_sof_resume(sdev);
+ if (ret < 0)
+ return ret;
+
+ return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
+}
+
+static int es_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev)
+{
+ const struct sof_dsp_power_state target_dsp_state = {
+ .state = SOF_DSP_PM_D3,
+ };
+
+ es_sof_suspend(sdev);
+
+ return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
+}
+
+static int es_sof_dsp_resume(struct snd_sof_dev *sdev)
+{
+ int ret;
+ const struct sof_dsp_power_state target_dsp_state = {
+ .state = SOF_DSP_PM_D0,
+ };
+
+ ret = es_sof_resume(sdev);
+ if (ret < 0)
+ return ret;
+
+ if (pm_runtime_suspended(sdev->dev)) {
+ pm_runtime_disable(sdev->dev);
+ pm_runtime_set_active(sdev->dev);
+ pm_runtime_mark_last_busy(sdev->dev);
+ pm_runtime_enable(sdev->dev);
+ pm_runtime_idle(sdev->dev);
+ }
+
+ return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
+}
+
+static int es_sof_dsp_suspend(struct snd_sof_dev *sdev, unsigned int target_state)
+{
+ const struct sof_dsp_power_state target_dsp_state = {
+ .state = target_state,
+ };
+
+ if (!pm_runtime_suspended(sdev->dev))
+ es_sof_suspend(sdev);
+
+ return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
+}
+
+static struct snd_soc_acpi_mach *es_sof_machine_select(struct snd_sof_dev *sdev)
+{
+ struct snd_sof_pdata *sof_pdata = sdev->pdata;
+ struct snd_soc_acpi_mach *mach;
+
+ mach = devm_kmalloc(sdev->dev, sizeof(struct snd_soc_acpi_mach), GFP_KERNEL);
+ if (!mach) {
+ dev_warn(sdev->dev, "warning: alloc machine info failed\n");
+ return NULL;
+ }
+
+ sof_pdata->tplg_filename = "sof-esw-es8388.tplg";
+ mach->sof_tplg_filename = "sof-esw-es8388.tplg";
+ mach->drv_name = "asoc-simple-card";
+
+ return mach;
+}
+
+
+static struct snd_sof_dsp_ops sof_es_sof_ops = {
+ /* probe and remove */
+ .probe = es_dsp_probe,
+ .remove = es_dsp_remove,
+ /* DSP core boot */
+ .run = es_dsp_run,
+ .reset = es_dsp_reset,
+
+ /* Block IO */
+ .block_read = sof_block_read,
+ .block_write = sof_block_write,
+
+ /* Mailbox IO */
+ .mailbox_read = sof_mailbox_read,
+ .mailbox_write = sof_mailbox_write,
+
+ /* ipc */
+ .send_msg = es_sof_send_msg,
+
+ .get_mailbox_offset = es_sof_get_mailbox_offset,
+ .get_window_offset = es_sof_get_window_offset,
+
+ .ipc_msg_data = sof_ipc_msg_data,
+ .set_stream_data_offset = sof_set_stream_data_offset,
+
+ .get_bar_index = es_sof_get_bar_index,
+ /* firmware loading */
+ .load_firmware = snd_sof_load_firmware_memcpy,
+
+ /* Debug information */
+ .dbg_dump = es_dsp_dump,
+ .debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
+
+ /* stream callbacks */
+ .pcm_open = sof_stream_pcm_open,
+ .pcm_close = sof_stream_pcm_close,
+ /* Firmware ops */
+ .dsp_arch_ops = &es_sof_xtensa_arch_ops,
+
+ /* machine driver */
+ .machine_select = es_sof_machine_select,
+
+ /* DAI drivers */
+ .drv = es_sof_dai,
+ .num_drv = ARRAY_SIZE(es_sof_dai),
+
+ .suspend = es_sof_dsp_suspend,
+ .resume = es_sof_dsp_resume,
+
+ .runtime_suspend = es_sof_dsp_runtime_suspend,
+ .runtime_resume = es_sof_dsp_runtime_resume,
+
+ .set_power_state = es_sof_dsp_set_power_state,
+
+ .hw_info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
+};
+
+static struct sof_dev_desc sof_of_es_sof_desc = {
+ .ipc_supported_mask = BIT(SOF_IPC),
+ .ipc_default = SOF_IPC,
+ .ipc_timeout = 3000,
+ .boot_timeout = 5000,
+ .default_fw_path = {
+ [SOF_IPC] = "eswin",
+ },
+ .default_tplg_path = {
+ [SOF_IPC] = "eswin",
+ },
+ .default_fw_filename = {
+ [SOF_IPC] = "sof-2030.ri",
+ },
+ .nocodec_tplg_filename = "sof-esw-es8388.tplg",
+ .ops = &sof_es_sof_ops,
+};
+
+static const struct of_device_id sof_of_es_sof_ids[] = {
+ { .compatible = "eswin,sof-dsp", .data = &sof_of_es_sof_desc},
+ { }
+};
+MODULE_DEVICE_TABLE(of, sof_of_es_sof_ids);
+
+/* DT driver definition */
+static struct platform_driver snd_sof_of_es_sof_driver = {
+ .probe = sof_of_probe,
+ .remove = sof_of_remove,
+ .driver = {
+ .name = "sof-audio-of-es-dsp",
+ .of_match_table = sof_of_es_sof_ids,
+ },
+};
+module_platform_driver(snd_sof_of_es_sof_driver);
+
+MODULE_AUTHOR("DengLei <denglei@eswincomputing.com>");
+MODULE_DESCRIPTION("ESWIN I2S SoC Interface");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:eswin dsp driver");
--
2.47.0