13026 lines
353 KiB
Diff
13026 lines
353 KiB
Diff
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 FREE,1 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 caller’s 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
|
||
|