From e86b6b67e2a590d11e1602a5f6692979357f9468 Mon Sep 17 00:00:00 2001 From: linmin Date: Mon, 29 Jul 2024 16:22:35 +0530 Subject: [PATCH 01/38] dts: eswin: Add dts and dtsi files for HiFive Premier P550 board dts, dtsi and include files for HiFive Premier P550 boards based on EIC7700 SoC. Signed-off-by: linmin Signed-off-by: Pinkesh Vaghela --- arch/riscv/boot/dts/Makefile | 1 + arch/riscv/boot/dts/eswin/Makefile | 3 + arch/riscv/boot/dts/eswin/eic7700-arch.dtsi | 539 ++++ arch/riscv/boot/dts/eswin/eic7700-noc.dtsi | 2620 +++++++++++++++++ arch/riscv/boot/dts/eswin/eic7700.dtsi | 2200 ++++++++++++++ .../eswin/hifive-premier-p550-pinctrl.dtsi | 1339 +++++++++ .../boot/dts/eswin/hifive-premier-p550.dts | 766 +++++ include/dt-bindings/clock/eic7700-clock.h | 623 ++++ include/dt-bindings/interconnect/eic7700.h | 141 + include/dt-bindings/mailbox/eswin-mailbox.h | 88 + include/dt-bindings/memory/eic7700-sid.h | 138 + include/dt-bindings/reset/eic7700-syscrg.h | 693 +++++ 12 files changed, 9151 insertions(+) create mode 100644 arch/riscv/boot/dts/eswin/Makefile create mode 100644 arch/riscv/boot/dts/eswin/eic7700-arch.dtsi create mode 100644 arch/riscv/boot/dts/eswin/eic7700-noc.dtsi create mode 100644 arch/riscv/boot/dts/eswin/eic7700.dtsi create mode 100644 arch/riscv/boot/dts/eswin/hifive-premier-p550-pinctrl.dtsi create mode 100644 arch/riscv/boot/dts/eswin/hifive-premier-p550.dts create mode 100755 include/dt-bindings/clock/eic7700-clock.h create mode 100644 include/dt-bindings/interconnect/eic7700.h create mode 100755 include/dt-bindings/mailbox/eswin-mailbox.h create mode 100644 include/dt-bindings/memory/eic7700-sid.h create mode 100755 include/dt-bindings/reset/eic7700-syscrg.h diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile index f60a280abb157..a0889f1b13750 100644 --- a/arch/riscv/boot/dts/Makefile +++ b/arch/riscv/boot/dts/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 subdir-y += allwinner subdir-y += canaan +subdir-y += eswin subdir-y += microchip subdir-y += renesas subdir-y += sifive diff --git a/arch/riscv/boot/dts/eswin/Makefile b/arch/riscv/boot/dts/eswin/Makefile new file mode 100644 index 0000000000000..b386475d14f23 --- /dev/null +++ b/arch/riscv/boot/dts/eswin/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_SOC_SIFIVE) += hifive-premier-p550.dtb +obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y)) diff --git a/arch/riscv/boot/dts/eswin/eic7700-arch.dtsi b/arch/riscv/boot/dts/eswin/eic7700-arch.dtsi new file mode 100644 index 0000000000000..0ffbfd21e8ec0 --- /dev/null +++ b/arch/riscv/boot/dts/eswin/eic7700-arch.dtsi @@ -0,0 +1,539 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Include file for Eswin EIC7700 SoC's cpu. + * + * 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 . + */ + +#include + +#define UART0_INT 100 +#define UART1_INT 101 +#define UART2_INT 102 +#define UART3_INT 103 +#define UART4_INT 104 + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "eic7700-dev"; + + L64: cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = ; + L17: cpu@0 { + clock-frequency = <0>; + compatible = "eswin,eic770x", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <128>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + hardware-exec-breakpoint-count = <4>; + hwpf-distanceBits = <6>; + hwpf-hitCacheThrdBits = <5>; + hwpf-hitMSHRThrdBits = <4>; + hwpf-l2pfPoolSize = <10>; + hwpf-nIssQEnt = <6>; + hwpf-nPrefetchQueueEntries = <8>; + hwpf-nStreams = <16>; + hwpf-qFullnessThrdBits = <4>; + hwpf-windowBits = <6>; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv48"; + next-level-cache = <&L15>; + reg = <0x0>; + riscv,isa = "rv64imafdc_h_zicsr_zifencei_zba_zbb_sscofpmf"; + riscv,pmpgranularity = <4096>; + riscv,pmpregions = <8>; + sifive,buserror = <&L16>; + status = "okay"; + timebase-frequency = ; + tlb-split; + clocks = <&d0_clock EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_0>; + operating-points-v2 = <&d0_cpu_opp_table>; + L14: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + L13: pmu { + riscv,raw-event-to-mhpmcounters = <0x0 0x0 0xffffffff 0xff 0x78 + 0x0 0x1 0xffffffff 0xfffe07ff 0x78 + 0x0 0x2 0xffffffff 0xfffe00ff 0x78 + 0x0 0x3 0xfffffffc 0xff 0x78 + 0x0 0x4 0xffffffc0 0xff 0x78 + 0x0 0x5 0xffffffff 0xfffffdff 0x78 + 0x0 0x6 0xfffffe00 0x110204ff 0x78 + 0x0 0x7 0xffffffff 0xf00000ff 0x78 + 0x0 0x8 0xfffffe04 0xff 0x78 + 0x0 0x9 0xffffffff 0xffffc0ff 0x78 + 0x0 0xa 0xffffffff 0xf00000ff 0x78 + 0x0 0xb 0xffffffff 0xfffffcff 0x78 + 0x0 0xc 0xfffffff0 0xff 0x78 + 0x0 0xd 0xffffffff 0x800000ff 0x78 + 0x0 0xe 0xffffffff 0xf80000ff 0x78 + 0x0 0xf 0xfffffffc 0xff 0x78>; + riscv,event-to-mhpmcounters = <0x01 0x01 0x01 0x02 0x02 0x02 0x4 0x6 0x78 0x10009 0x10009 0x78 0x10019 0x10019 0x78 0x10021 0x10021 0x78>; + 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 = <&L14 13>; + }; + }; + L22: cpu@1 { + clock-frequency = <0>; + compatible = "eswin,eic770x", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <128>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + hardware-exec-breakpoint-count = <4>; + hwpf-distanceBits = <6>; + hwpf-hitCacheThrdBits = <5>; + hwpf-hitMSHRThrdBits = <4>; + hwpf-l2pfPoolSize = <10>; + hwpf-nIssQEnt = <6>; + hwpf-nPrefetchQueueEntries = <8>; + hwpf-nStreams = <16>; + hwpf-qFullnessThrdBits = <4>; + hwpf-windowBits = <6>; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv48"; + next-level-cache = <&L20>; + reg = <0x1>; + riscv,isa = "rv64imafdc_h_zicsr_zifencei_zba_zbb_sscofpmf"; + riscv,pmpgranularity = <4096>; + riscv,pmpregions = <8>; + sifive,buserror = <&L21>; + status = "okay"; + timebase-frequency = ; + tlb-split; + clocks = <&d0_clock EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_1>; + operating-points-v2 = <&d0_cpu_opp_table>; + L19: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + L18: pmu { + riscv,raw-event-to-mhpmcounters = <0x0 0x0 0xffffffff 0xff 0x78 + 0x0 0x1 0xffffffff 0xfffe07ff 0x78 + 0x0 0x2 0xffffffff 0xfffe00ff 0x78 + 0x0 0x3 0xfffffffc 0xff 0x78 + 0x0 0x4 0xffffffc0 0xff 0x78 + 0x0 0x5 0xffffffff 0xfffffdff 0x78 + 0x0 0x6 0xfffffe00 0x110204ff 0x78 + 0x0 0x7 0xffffffff 0xf00000ff 0x78 + 0x0 0x8 0xfffffe04 0xff 0x78 + 0x0 0x9 0xffffffff 0xffffc0ff 0x78 + 0x0 0xa 0xffffffff 0xf00000ff 0x78 + 0x0 0xb 0xffffffff 0xfffffcff 0x78 + 0x0 0xc 0xfffffff0 0xff 0x78 + 0x0 0xd 0xffffffff 0x800000ff 0x78 + 0x0 0xe 0xffffffff 0xf80000ff 0x78 + 0x0 0xf 0xfffffffc 0xff 0x78>; + riscv,event-to-mhpmcounters = <0x01 0x01 0x01 0x02 0x02 0x02 0x4 0x6 0x78 0x10009 0x10009 0x78 0x10019 0x10019 0x78 0x10021 0x10021 0x78>; + 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 = <&L19 13>; + }; + }; + L27: cpu@2 { + clock-frequency = <0>; + compatible = "eswin,eic770x", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <128>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + hardware-exec-breakpoint-count = <4>; + hwpf-distanceBits = <6>; + hwpf-hitCacheThrdBits = <5>; + hwpf-hitMSHRThrdBits = <4>; + hwpf-l2pfPoolSize = <10>; + hwpf-nIssQEnt = <6>; + hwpf-nPrefetchQueueEntries = <8>; + hwpf-nStreams = <16>; + hwpf-qFullnessThrdBits = <4>; + hwpf-windowBits = <6>; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv48"; + next-level-cache = <&L25>; + reg = <0x2>; + riscv,isa = "rv64imafdc_h_zicsr_zifencei_zba_zbb_sscofpmf"; + riscv,pmpgranularity = <4096>; + riscv,pmpregions = <8>; + sifive,buserror = <&L26>; + status = "okay"; + timebase-frequency = ; + tlb-split; + clocks = <&d0_clock EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_2>; + operating-points-v2 = <&d0_cpu_opp_table>; + L24: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + L23: pmu { + riscv,raw-event-to-mhpmcounters = <0x0 0x0 0xffffffff 0xff 0x78 + 0x0 0x1 0xffffffff 0xfffe07ff 0x78 + 0x0 0x2 0xffffffff 0xfffe00ff 0x78 + 0x0 0x3 0xfffffffc 0xff 0x78 + 0x0 0x4 0xffffffc0 0xff 0x78 + 0x0 0x5 0xffffffff 0xfffffdff 0x78 + 0x0 0x6 0xfffffe00 0x110204ff 0x78 + 0x0 0x7 0xffffffff 0xf00000ff 0x78 + 0x0 0x8 0xfffffe04 0xff 0x78 + 0x0 0x9 0xffffffff 0xffffc0ff 0x78 + 0x0 0xa 0xffffffff 0xf00000ff 0x78 + 0x0 0xb 0xffffffff 0xfffffcff 0x78 + 0x0 0xc 0xfffffff0 0xff 0x78 + 0x0 0xd 0xffffffff 0x800000ff 0x78 + 0x0 0xe 0xffffffff 0xf80000ff 0x78 + 0x0 0xf 0xfffffffc 0xff 0x78>; + riscv,event-to-mhpmcounters = <0x01 0x01 0x01 0x02 0x02 0x02 0x4 0x6 0x78 0x10009 0x10009 0x78 0x10019 0x10019 0x78 0x10021 0x10021 0x78>; + 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 = <&L24 13>; + }; + }; + L32: cpu@3 { + clock-frequency = <0>; + compatible = "eswin,eic770x", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <128>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + hardware-exec-breakpoint-count = <4>; + hwpf-distanceBits = <6>; + hwpf-hitCacheThrdBits = <5>; + hwpf-hitMSHRThrdBits = <4>; + hwpf-l2pfPoolSize = <10>; + hwpf-nIssQEnt = <6>; + hwpf-nPrefetchQueueEntries = <8>; + hwpf-nStreams = <16>; + hwpf-qFullnessThrdBits = <4>; + hwpf-windowBits = <6>; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv48"; + next-level-cache = <&L30>; + reg = <0x3>; + riscv,isa = "rv64imafdc_h_zicsr_zifencei_zba_zbb_sscofpmf"; + riscv,pmpgranularity = <4096>; + riscv,pmpregions = <8>; + sifive,buserror = <&L31>; + status = "okay"; + timebase-frequency = ; + tlb-split; + clocks = <&d0_clock EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_3>; + operating-points-v2 = <&d0_cpu_opp_table>; + L29: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + L28: pmu { + riscv,raw-event-to-mhpmcounters = <0x0 0x0 0xffffffff 0xff 0x78 + 0x0 0x1 0xffffffff 0xfffe07ff 0x78 + 0x0 0x2 0xffffffff 0xfffe00ff 0x78 + 0x0 0x3 0xfffffffc 0xff 0x78 + 0x0 0x4 0xffffffc0 0xff 0x78 + 0x0 0x5 0xffffffff 0xfffffdff 0x78 + 0x0 0x6 0xfffffe00 0x110204ff 0x78 + 0x0 0x7 0xffffffff 0xf00000ff 0x78 + 0x0 0x8 0xfffffe04 0xff 0x78 + 0x0 0x9 0xffffffff 0xffffc0ff 0x78 + 0x0 0xa 0xffffffff 0xf00000ff 0x78 + 0x0 0xb 0xffffffff 0xfffffcff 0x78 + 0x0 0xc 0xfffffff0 0xff 0x78 + 0x0 0xd 0xffffffff 0x800000ff 0x78 + 0x0 0xe 0xffffffff 0xf80000ff 0x78 + 0x0 0xf 0xfffffffc 0xff 0x78>; + riscv,event-to-mhpmcounters = <0x01 0x01 0x01 0x02 0x02 0x02 0x4 0x6 0x78 0x10009 0x10009 0x78 0x10019 0x10019 0x78 0x10021 0x10021 0x78>; + 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 = <&L29 13>; + }; + }; + }; + 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>; + compatible = "SiFive,FU800-soc", "fu800-soc", "sifive-soc", "simple-bus"; + ranges; + L40: authentication-controller { + compatible = "sifive,authentication0"; + sifive,auth-types = "fuse"; + }; + L51: axi4-sys-port@40000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "sifive,axi4-sys-port", "sifive,axi4-port", "sifive,sys-port", "simple-external-bus", "simple-bus"; + ranges = <0x40000000 0x0 0x40000000 0x40000000>; + sifive,port-width-bytes = <16>; + }; + L52: axi4-sys-port@8000000000 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sifive,axi4-sys-port", "sifive,axi4-port", "sifive,sys-port", "simple-external-bus", "simple-bus"; + ranges = <0x80 0x0 0x80 0x0 0x180 0x0>; + sifive,port-width-bytes = <16>; + }; + L46: basic-bus-blocker@200000 { + compatible = "sifive,basic-bus-blocker1"; + reg = <0x0 0x200000 0x0 0x1000>; + reg-names = "control"; + }; + L43: basic-bus-blocker@202000 { + compatible = "sifive,basic-bus-blocker1"; + reg = <0x0 0x202000 0x0 0x1000>; + reg-names = "control"; + }; + L48: basic-bus-blocker@204000 { + compatible = "sifive,basic-bus-blocker1"; + reg = <0x0 0x204000 0x0 0x1000>; + reg-names = "control"; + }; + L54: burst-bundler@10010000 { + compatible = "sifive,burst-bundler0"; + reg = <0x0 0x10010000 0x0 0x1000>; + reg-names = "control"; + }; + L16: bus-error-unit@hart0 { + compatible = "sifive,buserror"; + interrupt-parent = <&plic0>; + interrupts = <517>; + reg = <0x0 0x1700000 0x0 0x1000>; + reg-names = "control"; + }; + L21: bus-error-unit@hart1 { + compatible = "sifive,buserror"; + interrupt-parent = <&plic0>; + interrupts = <518>; + reg = <0x0 0x1701000 0x0 0x1000>; + reg-names = "control"; + }; + L26: bus-error-unit@hart2 { + compatible = "sifive,buserror"; + interrupt-parent = <&plic0>; + interrupts = <519>; + reg = <0x0 0x1702000 0x0 0x1000>; + reg-names = "control"; + }; + L31: bus-error-unit@hart3 { + compatible = "sifive,buserror"; + interrupt-parent = <&plic0>; + interrupts = <520>; + reg = <0x0 0x1703000 0x0 0x1000>; + reg-names = "control"; + }; + L7: cache-controller@2010000 { + cache-block-size = <64>; + cache-level = <3>; + cache-sets = <4096>; + cache-size = <4194304>; + cache-unified; + compatible = "sifive,eic7700"; + interrupt-parent = <&plic0>; + interrupts = <1>, <3>, <4>, <2>; + next-level-cache = <&L9 &L10 &L11 &L50>; + reg = <0x0 0x2010000 0x0 0x4000 0x0 0x8000000 0x0 0x400000>; + reg-names = "control", "sideband"; + sifive,a-mshr-count = <60>; + sifive,bank-count = <4>; + sifive,ecc-granularity = <8>; + sifive,max-master-id = <13>; + sifive,perfmon-counters = <6>; + numa-node-id = <0>; + }; + + L34: debug-controller@0 { + compatible = "sifive,debug-100", "riscv,debug-100"; + debug-attach = "jtag"; + reg = <0x0 0x0 0x0 0x1000>; + reg-names = "control"; + }; + L8: error-device@1000 { + compatible = "sifive,error0"; + reg = <0x0 0x1000 0x0 0x3000 0x0 0x5000 0x0 0x13000 0x0 0x19000 0x0 0xe7000 0x0 0x114000 0x0 0xec000 0x0 0x201000 0x0 0x1000 0x0 0x203000 0x0 0x1000 0x0 0x205000 0x0 0x14fb000 0x0 0x1704000 0x0 0x8fc000 0x0 0x2014000 0x0 0x5fec000 0x0 0x8400000 0x0 0x3c00000 0x0 0x10000000 0x0 0x3000 0x0 0x10004000 0x0 0xc000 0x0 0x10011000 0x0 0x1f000 0x0 0x10034000 0x0 0x9fcc000 0x0 0x1a400000 0x0 0x5c00000>; + }; + L9: error-device@10003000 { + compatible = "sifive,error0"; + reg = <0x0 0x10003000 0x0 0x1000>; + }; + + plic0: interrupt-controller@c000000 { + #interrupt-cells = <1>; + compatible = "sifive,plic-1.0.0"; + interrupt-controller; + interrupts-extended = < + &L14 0xffffffff &L14 9 + &L19 0xffffffff &L19 9 + &L24 0xffffffff &L24 9 + &L29 0xffffffff &L29 9>; + reg = <0x0 0xc000000 0x0 0x4000000>; + reg-names = "control"; + riscv,max-priority = <7>; + riscv,ndev = <520>; + }; + L53: order-obliterator@10030000 { + compatible = "sifive,order-obliterator0"; + interrupt-parent = <&plic0>; + interrupts = <516>; + reg = <0x0 0x10030000 0x0 0x4000>; + reg-names = "control"; + }; + L15: pl2@104000 { + cache-block-size = <64>; + cache-level = <2>; + cache-sets = <512>; + cache-size = <262144>; + cache-unified; + compatible = "sifive,pL2Cache0", "cache"; + next-level-cache = <&L7>; + reg = <0x0 0x104000 0x0 0x4000>; + reg-names = "control"; + sifive,ecc-granularity = <16>; + sifive,perfmon-counters = <6>; + }; + L20: pl2@108000 { + cache-block-size = <64>; + cache-level = <2>; + cache-sets = <512>; + cache-size = <262144>; + cache-unified; + compatible = "sifive,pL2Cache0", "cache"; + next-level-cache = <&L7>; + reg = <0x0 0x108000 0x0 0x4000>; + reg-names = "control"; + sifive,ecc-granularity = <16>; + sifive,perfmon-counters = <6>; + }; + L25: pl2@10c000 { + cache-block-size = <64>; + cache-level = <2>; + cache-sets = <512>; + cache-size = <262144>; + cache-unified; + compatible = "sifive,pL2Cache0", "cache"; + next-level-cache = <&L7>; + reg = <0x0 0x10c000 0x0 0x4000>; + reg-names = "control"; + sifive,ecc-granularity = <16>; + sifive,perfmon-counters = <6>; + }; + L30: pl2@110000 { + cache-block-size = <64>; + cache-level = <2>; + cache-sets = <512>; + cache-size = <262144>; + cache-unified; + compatible = "sifive,pL2Cache0", "cache"; + next-level-cache = <&L7>; + reg = <0x0 0x110000 0x0 0x4000>; + reg-names = "control"; + sifive,ecc-granularity = <16>; + sifive,perfmon-counters = <6>; + }; + L10: rom@1a000000 { + compatible = "ucbbar,cacheable-zero0"; + reg = <0x0 0x1a000000 0x0 0x400000>; + }; + L11: rom@3a000000 { + compatible = "ucbbar,cacheable-zero0"; + reg = <0x0 0x3a000000 0x0 0x400000>; + }; + L6: subsystem_pbus_clock { + #clock-cells = <0>; + clock-frequency = <10000000>; + clock-output-names = "subsystem_pbus_clock"; + compatible = "fixed-clock"; + }; + L61: teststatus@4000 { + compatible = "sifive,test0"; + reg = <0x0 0x4000 0x0 0x1000>; + reg-names = "control"; + }; + L45: tl-address-adjuster@20000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "sifive,tl-inter-sys-port", "sifive,tl-port", "simple-external-bus", "simple-bus"; + ranges = <0x20000000 0x0 0x20000000 0x1a000000 0x3a400000 0x0 0x3a400000 0x5c00000>; + sifive,port-width-bytes = <8>; + }; + L42: tl-inter-mem-master-port@80000000 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sifive,tl-inter-mem-master-port", "sifive,tl-port", "sifive,inter-mem-master-port", "simple-external-bus", "simple-bus"; + ranges = <0x0 0x80000000 0x0 0x80000000 0x7f 0x80000000>; + sifive,port-width-bytes = <32>; + }; + L55: trace-encoder-0@100000 { + compatible = "sifive,trace0"; + reg = <0x0 0x100000 0x0 0x1000>; + reg-names = "control"; + }; + L56: trace-encoder-1@101000 { + compatible = "sifive,trace0"; + reg = <0x0 0x101000 0x0 0x1000>; + reg-names = "control"; + }; + L57: trace-encoder-2@102000 { + compatible = "sifive,trace0"; + reg = <0x0 0x102000 0x0 0x1000>; + reg-names = "control"; + }; + L58: trace-encoder-3@103000 { + compatible = "sifive,trace0"; + reg = <0x0 0x103000 0x0 0x1000>; + reg-names = "control"; + }; + L59: trace-funnel-0@18000 { + compatible = "sifive,trace0"; + reg = <0x0 0x18000 0x0 0x1000>; + reg-names = "control"; + }; + }; +}; diff --git a/arch/riscv/boot/dts/eswin/eic7700-noc.dtsi b/arch/riscv/boot/dts/eswin/eic7700-noc.dtsi new file mode 100644 index 0000000000000..a4e1435488329 --- /dev/null +++ b/arch/riscv/boot/dts/eswin/eic7700-noc.dtsi @@ -0,0 +1,2620 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Include file for Die0 NOC monitor 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 . + */ + +d0_cfg_noc:d0_cfg_noc{ + compatible = "eswin,eic7700-noc"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + reg = <0 0x52060000 0 0x4000>; + + interrupts = <446>; + interrupt-names = "error"; + interrupt-parent = <&plic0>; + errlogger,idx = <0 1 3 5>; + + sideband_manager@52061000{ + compatible = "eswin,win2xxx-noc-sideband-manager"; + reg = <0 0x52061000 0 0x10>; + SenseIn0 = + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + bf-name = + "SBM_CLMM", + "SBM_CNOC_AON", + "SBM_CNOC_DDRT0_CTRL", + "SBM_CNOC_DDRT0_PHY ", + "SBM_CNOC_DDRT1_CTRL", + "SBM_CNOC_DDRT1_PHY", + "SBM_CNOC_DSPT", + "SBM_CNOC_GPU", + "SBM_CNOC_HSP", + "SBM_CNOC_LSP_APB2", + "SBM_CNOC_LSP_APB3", + "SBM_CNOC_LSP_APB4", + "SBM_CNOC_LSP_APB6", + "SBM_CNOC_MCPUT_D2D", + "SBM_CNOC_NPU", + "SBM_CNOC_PCIET_P", + "SBM_CNOC_PCIET_X", + "SBM_CNOC_TCU", + "SBM_CNOC_VC", + "SBM_CNOC_VI", + "SBM_CNOC_VO"; + }; + ErrorLogger0 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x14 32 >; + description = "Register 0 to log errors"; + lock { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0 1>; + lut = "Not Locked", "Locked"; + }; + OpCode { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 1 4>; + lut = "RD: data read with incrementing address", + "RDW: data read with wrapping address", + "RDL: allocates monitor in the Target with incrementing address", + "RDX: exclusive read with incrementing address", + "WR: data write with incrementing address", + "WRW: data write with wrapping address", + "WRC: conditional write if matching monitor in Target is found", + "RSV: reserved", + "PRE: preamble packet of linked sequence (locked sequence)", + "URG: urgency packet used for QoS (status must be REQ)"; + }; + ErrCode { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 8 3 >; + lut = "SLV (error source: Target): error detected by the Slave without any information or no Error", + "DEC (error source: Initiator NIU): decode error", + "UNS (error source: Target NIU): unsupported access type", + "DISC (error source: Power Disconnect): disconnected Target or NoC domain", + "SEC (error source: Initiator NIU or Firewall): security error", + "HIDE (error source: Firewall): hidden security error. Will be reported as OK to the initiator", + "TMO (error source: Target NIU): time-out", + "RSV: reserved"; + + }; + Len1 { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 16 12 >; + }; + Format { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 31 1 >; + lut = "NTTP v3.0 (Invalid)", "NTTP v3.5 (Ok)"; + }; + }; + + ErrorLogger1 { + compatible = "eswin,eic7700,register", "eswin,eic7700,noc,filter,routeid"; + offset,length = < 0x18 32>; + description = "Register 1 to log errors"; + InitFlow { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 15 1 >; /*bit 15 will aloways be 0, then we will always get "snoc_cnoc/I/0"*/ + lut = + "snoc_cnoc/I/0"; + }; + + TargetFlow { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 10 5 >; + lut = + "clmm/T/0", + "cnoc_aon/T/0", + "cnoc_ddrt0_ctrl/T/0", + "cnoc_ddrt0_phy/T/0", + "cnoc_ddrt1_ctrl/T/0", + "cnoc_ddrt1_phy/T/0", + "cnoc_dspt/T/0", + "cnoc_gpu/T/0", + "cnoc_hsp/T/0", + "cnoc_lsp_apb2/T/0", + "cnoc_lsp_apb3/T/0", + "cnoc_lsp_apb4/T/0", + "cnoc_lsp_apb6/T/0", + "cnoc_mcput_d2d/T/0", + "cnoc_npu/T/0", + "cnoc_pciet_p/T/0", + "cnoc_pciet_x/T/0", + "cnoc_service/T/0", + "cnoc_tcu/T/0", + "cnoc_vc/T/0", + "cnoc_vi/T/0", + "cnoc_vo/T/0", + "RESERVED", + "RESERVED", + "RESERVED", + "RESERVED", + "RESERVED", + "RESERVED", + "RESERVED", + "RESERVED", + "RESERVED", + "RESERVED"; + }; + + TargetSubRange { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 8 2 >; + }; + + SeqId { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0 8 >; + }; + }; + + ErrorLogger3 { + /* This register does not really include a bitfield or its bitfield is 32 bits and it provides an offset address */ + /* To calculate the absolute address, you must use the initflow:targetflow:subrange from ErrorLogger1 register */ + /* And use it as an index in the aperture table. Then you must add the value of this register to the value given */ + /* by the table to get the absolute address. */ + compatible = "eswin,eic7700,register"; + offset,length = <0x20 32>; + description = "Register 3 to log errors"; + aperture-link = <1>; /* link to ErrorLogger1 whose information are required to calculate real absolute address */ + AbsoluteAddress { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 8 8 >; /* bitfield initflow:targeflow:subrange from aperture-link register */ + aperture-size= < 46 >; /* Number of line in the aperture table below */ + aperture-idx,aperture-base = /* Aperture_idx is concatenation of initflow:targetflow:subrange bitfield from ErrorLogger1 */ + /bits/ 64 <0x0 0x0 0x0 0x51600000>, + /bits/ 64 <0x0 0x0 0x1 0x71600000>, + /bits/ 64 <0x0 0x1 0x0 0x51800000>, + /bits/ 64 <0x0 0x1 0x1 0x71800000>, + /bits/ 64 <0x0 0x1 0x2 0x0 >, + /bits/ 64 <0x0 0x1 0x3 0x0 >, + /bits/ 64 <0x0 0x2 0x0 0x52300000>, + /bits/ 64 <0x0 0x2 0x1 0x72300000>, + /bits/ 64 <0x0 0x3 0x0 0x53000000>, + /bits/ 64 <0x0 0x3 0x1 0x73000000>, + /bits/ 64 <0x0 0x4 0x0 0x52380000>, + /bits/ 64 <0x0 0x4 0x1 0x72380000>, + /bits/ 64 <0x0 0x5 0x0 0x53800000>, + /bits/ 64 <0x0 0x5 0x1 0x73800000>, + /bits/ 64 <0x0 0x6 0x0 0x52200000>, + /bits/ 64 <0x0 0x6 0x1 0x72200000>, + /bits/ 64 <0x0 0x7 0x0 0x51400000>, + /bits/ 64 <0x0 0x7 0x1 0x71400000>, + /bits/ 64 <0x0 0x8 0x0 0x50400000>, + /bits/ 64 <0x0 0x8 0x1 0x70400000>, + /bits/ 64 <0x0 0x9 0x0 0x50800000>, + /bits/ 64 <0x0 0x9 0x1 0x70800000>, + /bits/ 64 <0x0 0xa 0x0 0x50900000>, + /bits/ 64 <0x0 0xa 0x1 0x70900000>, + /bits/ 64 <0x0 0xb 0x0 0x50a00000>, + /bits/ 64 <0x0 0xb 0x1 0x70a00000>, + /bits/ 64 <0x0 0xc 0x0 0x50b00000>, + /bits/ 64 <0x0 0xc 0x1 0x70b00000>, + /bits/ 64 <0x0 0xd 0x0 0x52100000>, + /bits/ 64 <0x0 0xd 0x1 0x72100000>, + /bits/ 64 <0x0 0xe 0x0 0x51c00000>, + /bits/ 64 <0x0 0xe 0x1 0x71c00000>, + /bits/ 64 <0x0 0xf 0x0 0x50000000>, + /bits/ 64 <0x0 0xf 0x1 0x70000000>, + /bits/ 64 <0x0 0x10 0x0 0x54000000>, + /bits/ 64 <0x0 0x10 0x1 0x74000000>, + /bits/ 64 <0x0 0x11 0x0 0x52060000>, + /bits/ 64 <0x0 0x11 0x1 0x72060000>, + /bits/ 64 <0x0 0x12 0x0 0x50c00000>, + /bits/ 64 <0x0 0x12 0x1 0x70c00000>, + /bits/ 64 <0x0 0x13 0x0 0x50100000>, + /bits/ 64 <0x0 0x13 0x1 0x70100000>, + /bits/ 64 <0x0 0x14 0x0 0x51000000>, + /bits/ 64 <0x0 0x14 0x1 0x71000000>, + /bits/ 64 <0x0 0x15 0x0 0x50200000>, + /bits/ 64 <0x0 0x15 0x1 0x70200000>; + }; + }; + + ErrorLogger5 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x28 32>; + description = "Register 5 to log errors"; + + User_flag { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0x0 7 >; + lut = + "Cache_0", + "Cache_1", + "Cache_2", + "Cache_3", + "Prot_0", + "Prot_1", + "Prot_2"; + }; + }; +}; + +d0_llc_noc:d0_llc_noc@52081400 { + compatible = "eswin,eic7700-noc"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + reg = <0 0x52081400 0 0x4000>; + interrupts = <441>; + interrupt-names = "error"; + interrupt-parent = <&plic0>; + errlogger,idx = <0 1 3 4 5>; + sideband_manager@52082000 { + compatible = "eswin,win2xxx-noc-sideband-manager"; + reg = <0 0x52082000 0 0x10>; + SenseIn0 = + , + , + , + ; + bf-name = + "SBM_LNOC_NPU_LLC0", + "SBM_LNOC_NPU_LLC1", + "SBM_LNOC_DDRT0_P0", + "SBM_LNOC_DDRT1_P0"; + }; + + llcnoc_packet_ddr0_p0_req_probe@52080000 { + compatible = "eswin,win2xxx-noc-packet-probe"; + reg = <0 0x52080000 0 0x4000>; + clocks = <&d0_clock EIC7700_CLK_DDRT0_P0_ACLK>; + clock-names = "clk"; + interrupts = <445>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <1>; + counter,nr = <2>; + portsel = "ddr0_p0_req"; + }; + llcnoc_packet_ddr1_p0_req_probe@52080800 { + compatible = "eswin,win2xxx-noc-packet-probe"; + reg = <0 0x52080800 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_DDRT1_P0_ACLK>; + clock-names = "clk"; + interrupts = <443>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <1>; + counter,nr = <2>; + portsel = "ddr1_p0_req"; + }; + llcnoc_trans_probe@52081000 { + #address-cells = <2>; + #size-cells = <2>; + ranges; + compatible = "eswin,win2xxx-noc-trans-probe"; + reg = <0 0x52081000 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_NOC_NSP_CLK>; + clock-names = "clk"; + interrupts = <441>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <2>; + counter,nr = <8>; + profiler,nr = <1>; + portsel = "npu_llc0", "npu_llc1"; + llcnoc_trans_npu_llc0_filter@52081480 { + status = "disabled"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52081480 0 0x80>; + }; + llcnoc_trans_npu_llc1_filter@52081500 { + status = "disabled"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52081500 0 0x80>; + }; + llcnoc_trans_profiler@52081580 { + compatible = "eswin,win2xxx-noc-trans-profiler"; + reg = <0 0x52081580 0 0x80>; + }; + }; + ErrorLogger0 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x14 32 >; + description = "Register 0 to log errors"; + lock { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0 1 >; + lut = "Not Locked", "Locked"; + }; + OpCode { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 1 4 >; + lut = "RD: data read with incrementing address", + "RDW: data read with wrapping address", + "RDL: allocates monitor in the Target with incrementing address", + "RDX: exclusive read with incrementing address", + "WR: data write with incrementing address", + "WRW: data write with wrapping address", + "WRC: conditional write if matching monitor in Target is found", + "RSV: reserved", + "PRE: preamble packet of linked sequence (locked sequence)", + "URG: urgency packet used for QoS (status must be REQ)"; + }; + ErrCode { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 8 3 >; + lut = "SLV (error source: Target): error detected by the Slave without any information or no Error", + "DEC (error source: Initiator NIU): decode error", + "UNS (error source: Target NIU): unsupported access type", + "DISC (error source: Power Disconnect): disconnected Target or NoC domain", + "SEC (error source: Initiator NIU or Firewall): security error", + "HIDE (error source: Firewall): hidden security error. Will be reported as OK to the initiator", + "TMO (error source: Target NIU): time-out", + "RSV: reserved"; + + }; + Len1 { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 16 12 >; + }; + Format { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 31 1 >; + lut = "NTTP v3.0 (Invalid)", "NTTP v3.5 (Ok)"; + }; + }; + + ErrorLogger1 { + compatible = "eswin,eic7700,register", "eswin,eic7700,noc,filter,routeid"; + offset,length = < 0x18 32>; + description = "Register 1 to log errors"; + InitFlow { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 14 2 >; + lut = + "npu_lnoc_llc0/I/0", + "npu_lnoc_llc1/I/0", + "snoc_lnoc/I/0", + "RESERVED"; + }; + + TargetFlow { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 12 2 >; + lut = + "lnoc_ddrt0_p0/T/0", + "lnoc_ddrt1_p0/T/0", + "lnoc_service/T/0", + "RESERVED"; + }; + + TargetSubRange { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 8 4 >; + }; + + SeqId { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0 8 >; + }; + }; + + ErrorLogger3 { + /* This register does not really include a bitfield or its bitfield is 32 bits and it provides an offset address */ + /* To calculate the absolute address, you must use the initflow:targetflow:subrange from ErrorLogger1 register */ + /* And use it as an index in the aperture table. Then you must add the value of this register to the value given */ + /* by the table to get the absolute address. */ + compatible = "eswin,eic7700,register"; + offset,length = <0x20 32>; + description = "Register 3 to log errors"; + aperture-link = <1>; /* link to ErrorLogger whose information are required to calculate real absolute address */ + msb-link = <4>; /*indicate which ErrorLogger contains the msb addrs, -1 means no*/ + AbsoluteAddress { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 8 8 >; /* bitfield initflow:targeflow:subrange from aperture-link register */ + aperture-size= < 53 >; /* Number of line in the aperture table below */ + aperture-idx,aperture-base = /* Aperture_idx is concatenation of initflow:targetflow:subrange bitfield from ErrorLogger1 */ + /bits/ 64 <0x0 0x0 0x0 0x80000000 >, + /bits/ 64 <0x0 0x0 0x1 0x100000000 >, + /bits/ 64 <0x0 0x0 0x2 0x200000000 >, + /bits/ 64 <0x0 0x0 0x3 0x400000000 >, + /bits/ 64 <0x0 0x0 0x4 0x800000000 >, + /bits/ 64 <0x0 0x0 0x5 0x2000000000 >, + /bits/ 64 <0x0 0x0 0x6 0xc000000000 >, + /bits/ 64 <0x0 0x0 0x7 0xe000000000 >, + /bits/ 64 <0x0 0x0 0x8 0x4000000000 >, + /bits/ 64 <0x0 0x0 0x9 0x4000000100 >, + /bits/ 64 <0x0 0x0 0xa 0x10000000000 >, + /bits/ 64 <0x0 0x0 0xb 0x10000000100 >, + /bits/ 64 <0x0 0x0 0xc 0x0 >, + /bits/ 64 <0x0 0x1 0x0 0x80000080 >, + /bits/ 64 <0x0 0x1 0x1 0x100000080 >, + /bits/ 64 <0x0 0x1 0x2 0x200000080 >, + /bits/ 64 <0x0 0x1 0x3 0x400000080 >, + /bits/ 64 <0x0 0x1 0x4 0x800000080 >, + /bits/ 64 <0x0 0x1 0x5 0x2000000080 >, + /bits/ 64 <0x0 0x1 0x6 0xc000000080 >, + /bits/ 64 <0x0 0x1 0x7 0xe000000080 >, + /bits/ 64 <0x0 0x1 0x8 0x4000000080 >, + /bits/ 64 <0x0 0x1 0x9 0x4000000180 >, + /bits/ 64 <0x0 0x1 0xa 0x10000000080 >, + /bits/ 64 <0x0 0x1 0xb 0x10000000180 >, + /bits/ 64 <0x1 0x0 0x0 0x80000000 >, + /bits/ 64 <0x1 0x0 0x1 0x100000000 >, + /bits/ 64 <0x1 0x0 0x2 0x200000000 >, + /bits/ 64 <0x1 0x0 0x3 0x400000000 >, + /bits/ 64 <0x1 0x0 0x4 0x800000000 >, + /bits/ 64 <0x1 0x0 0x5 0x2000000000 >, + /bits/ 64 <0x1 0x0 0x6 0xc000000000 >, + /bits/ 64 <0x1 0x0 0x7 0xe000000000 >, + /bits/ 64 <0x1 0x0 0x8 0x4000000000 >, + /bits/ 64 <0x1 0x0 0x9 0x4000000100 >, + /bits/ 64 <0x1 0x0 0xa 0x10000000000 >, + /bits/ 64 <0x1 0x0 0xb 0x10000000100 >, + /bits/ 64 <0x1 0x0 0xc 0x0 >, + /bits/ 64 <0x1 0x1 0x0 0x80000080 >, + /bits/ 64 <0x1 0x1 0x1 0x100000080 >, + /bits/ 64 <0x1 0x1 0x2 0x200000080 >, + /bits/ 64 <0x1 0x1 0x3 0x400000080 >, + /bits/ 64 <0x1 0x1 0x4 0x800000080 >, + /bits/ 64 <0x1 0x1 0x5 0x2000000080 >, + /bits/ 64 <0x1 0x1 0x6 0xc000000080 >, + /bits/ 64 <0x1 0x1 0x7 0xe000000080 >, + /bits/ 64 <0x1 0x1 0x8 0x4000000080 >, + /bits/ 64 <0x1 0x1 0x9 0x4000000180 >, + /bits/ 64 <0x1 0x1 0xa 0x10000000080 >, + /bits/ 64 <0x1 0x1 0xb 0x10000000180 >, + /bits/ 64 <0x2 0x2 0x0 0x52080000 >, + /bits/ 64 <0x2 0x2 0x1 0x72080000 >, + /bits/ 64 <0x2 0x2 0x2 0x0 >; + }; + }; + + ErrorLogger4 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x24 32>; + description = "Register 4 to log errors"; + addr_msb { + compatible = "eswin,eic7700,bitfield"; + description = "Stores NTTP packet header field Addr (MSBs) of the logged error"; + offset,length = < 0 9 >; + }; + }; + + ErrorLogger5 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x28 32 >; + description = "Register 5 to log errors"; + + User_flag { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0x0 16 >; + lut = + "Cache_0", + "Cache_1", + "Cache_2", + "Cache_3", + "Prot_0", + "Prot_1", + "Prot_2", + "Qos_0", + "Qos_1", + "Qos_2", + "Qos_3", + "User_0", + "User_1", + "User_2", + "User_3", + "User_4"; + }; + }; +}; + +d0_sys_noc:d0_sys_noc@52002C00 { + compatible = "eswin,eic7700-noc"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + reg = <0 0x52002C00 0 0x4000>; + interrupts = <431>; + interrupt-names = "error"; + interrupt-parent = <&plic0>; + errlogger,idx = <0 1 3 4 5>; + + eswin,qos-configs = "DSPT", "NPU", "SPISLV_TBU3"; + eswin,DSPT-qos-base = <0x52002C80>; + eswin,DSPT-qos-settings = < + 0x8 0x4 /* prio */ + 0xC 0x2 /* mode 0:fixed 1:limiter 2:bypass 3:regulator*/ + /* a number of (1/256)th of Bytes/cycle. + Ex:zebu zdfi design feature, dsp AXI Clk=1040MHz, BW=12.1875MB/s, register value = (9.375/1040)*256 = 0x03 + */ + 0x10 0x03 /* bandwidth. 12.1875MB/s */ + /* + Saturation(B) = ((Requried Bandwidth)*(Windows Time of Bandwidth Calculation))/16 + Ex:16 byte saturation for BW=12.1875MB/s means 1.313us window time. + The desired value is number of saturation bytes divided by 16(ex,1 for 16byte B) + */ + 0x14 0x1 /* saturation, 1.313us*/ + 0x18 0x1>; /* QoSEn */ + + eswin,NPU-qos-base = <0x52002D00>; + eswin,NPU-qos-settings = < + 0x8 0x4 /* prio */ + 0xC 0x2 /* mode */ + 0x10 0x18 /* bandwidth */ + 0x14 0x10 /* saturation */ + 0x18 0x1>; /* QoSEn */ + + eswin,SPISLV_TBU3-qos-base = <0x52002D80>; + eswin,SPISLV_TBU3-qos-settings = < + 0x8 0x4 /* prio */ + 0xC 0x2 /* mode */ + 0x10 0x18 /* bandwidth */ + 0x14 0x10 /* saturation */ + 0x18 0x1>; /* QoSEn */ + sideband_manager@52004000 { + compatible = "eswin,win2xxx-noc-sideband-manager"; + reg = <0 0x52004000 0 0x10>; + SenseIn0 = + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + bf-name = + "SBM_AON_SNOC_SP0", + "SBM_DSPT_SNOC", + "SBM_JTAG_SNOC", + "SBM_MCPUT_SNOC_D2D ", + "SBM_MCPUT_SNOC_MP", + "SBM_MCPUT_SNOC_SP0", + "SBM_MCPUT_SNOC_SP1", + "SBM_NPU_SNOC_SP0", + "SBM_NPU_SNOC_SP1", + "SBM_PCIET_SNOC_P", + "SBM_SPISLV_PCIET_SNOC", + "SBM_TBU4_SNOC", + "SBM_TCU_SNOC", + "SBM_SNOC_AON", + "SBM_SNOC_DDR0_P1", + "SBM_SNOC_DDR0_P2", + "SBM_SNOC_DDR1_P1", + "SBM_SNOC_DDR1_P2", + "SBM_SNOC_DSPT", + "SBM_SNOC_MCPUT_D2D", + "SBM_SNOC_NPU", + "SBM_SNOC_PCIET"; + }; + sysnoc_packet_ddr0_p1_req_probe@52000000 { + compatible = "eswin,win2xxx-noc-packet-probe"; + reg = <0 0x52000000 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_DDRT0_P1_ACLK>; + clock-names = "clk"; + interrupts = <439>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <1>; + counter,nr = <2>; + portsel = "ddr0_p1_req"; + }; + sysnoc_packet_ddr0_p2_req_probe@52000800 { + compatible = "eswin,win2xxx-noc-packet-probe"; + reg = <0 0x52000800 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_DDRT0_P2_ACLK>; + clock-names = "clk"; + interrupts = <437>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <1>; + counter,nr = <2>; + portsel = "ddr0_p2_req"; + }; + sysnoc_packet_ddr1_p1_req_probe@52001000 { + compatible = "eswin,win2xxx-noc-packet-probe"; + reg = <0 0x52001000 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_DDRT1_P1_ACLK>; + clock-names = "clk"; + interrupts = <435>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <1>; + counter,nr = <2>; + portsel = "ddr1_p1_req"; + }; + sysnoc_packet_ddr1_p2_req_probe@52001800 { + compatible = "eswin,win2xxx-noc-packet-probe"; + reg = <0 0x52001800 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_DDRT1_P2_ACLK>; + clock-names = "clk"; + interrupts = <433>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <1>; + counter,nr = <2>; + portsel = "ddr1_p2_req"; + }; + sysnoc_trans_probe_0@52002000 { + #address-cells = <2>; + #size-cells = <2>; + ranges; + compatible = "eswin,win2xxx-noc-trans-probe"; + reg = <0 0x52002000 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_NOC_NSP_CLK>; + clock-names = "clk"; + interrupts = <430>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <2>; + counter,nr = <8>; + profiler,nr = <1>; + portsel = "dspt_snoc", "npu_sp1"; + sysnoc_trans_dspt_filter@52002E00 { + status = "disabled"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52002E00 0 0x80>; + }; + sysnoc_trans_npu_sp1_filter@52002F80 { + status = "disabled"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52002F80 0 0x80>; + }; + sysnoc_trans_profiler@52003180 { + compatible = "eswin,win2xxx-noc-trans-profiler"; + reg = <0 0x52003180 0 0x80>; + }; + }; + sysnoc_trans_probe_1@52002400 { + #address-cells = <2>; + #size-cells = <2>; + ranges; + compatible = "eswin,win2xxx-noc-trans-probe"; + reg = <0 0x52002400 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_NOC_NSP_CLK>; + clock-names = "clk"; + interrupts = <429>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <3>; + counter,nr = <12>; + profiler,nr = <1>; + portsel = "mcput_mp", "mcput_sp1", "tcu"; + sysnoc_trans_mcput_mp_filter@52002E80 { + status = "okay"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52002E80 0 0x80>; + }; + sysnoc_trans_mcput_sp1_filter@52002F00 { + status = "okay"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52002F00 0 0x80>; + }; + sysnoc_trans_tcu_filter@52003100 { + status = "okay"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52003100 0 0x80>; + }; + sysnoc_trans_profiler@52003200 { + compatible = "eswin,win2xxx-noc-trans-profiler"; + reg = <0 0x52003200 0 0x80>; + }; + }; + sysnoc_trans_probe_2@52002800 { + #address-cells = <2>; + #size-cells = <2>; + ranges; + compatible = "eswin,win2xxx-noc-trans-probe"; + reg = <0 0x52002800 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_NOC_NSP_CLK>; + clock-names = "clk"; + interrupts = <428>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <2>; + counter,nr = <8>; + profiler,nr = <1>; + portsel = "spislv_tbu3", "tbu4_snoc"; + sysnoc_trans_spislv_tbu3_filter@52003000 { /*pcie subsys*/ + status = "disabled"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52003000 0 0x80>; + }; + sysnoc_trans_tbu4_filter@52003080 { /*aon subsys*/ + status = "disabled"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52003080 0 0x80>; + }; + sysnoc_trans_profiler@52003280 { + compatible = "eswin,win2xxx-noc-trans-profiler"; + reg = <0 0x52003280 0 0x80>; + }; + }; + ErrorLogger0 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x14 32 >; + description = "Register 0 to log errors"; + lock { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0 1>; + lut = "Not Locked", "Locked"; + }; + OpCode { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 1 4>; + lut = "RD: data read with incrementing address", + "RDW: data read with wrapping address", + "RDL: allocates monitor in the Target with incrementing address", + "RDX: exclusive read with incrementing address", + "WR: data write with incrementing address", + "WRW: data write with wrapping address", + "WRC: conditional write if matching monitor in Target is found", + "RSV: reserved", + "PRE: preamble packet of linked sequence (locked sequence)", + "URG: urgency packet used for QoS (status must be REQ)"; + }; + ErrCode { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 8 3 >; + lut = "SLV (error source: Target): error detected by the Slave without any information or no Error", + "DEC (error source: Initiator NIU): decode error", + "UNS (error source: Target NIU): unsupported access type", + "DISC (error source: Power Disconnect): disconnected Target or NoC domain", + "SEC (error source: Initiator NIU or Firewall): security error", + "HIDE (error source: Firewall): hidden security error. Will be reported as OK to the initiator", + "TMO (error source: Target NIU): time-out", + "RSV: reserved"; + + }; + Len1 { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 16 12 >; + }; + Format { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 31 1 >; + lut = "NTTP v3.0 (Invalid)", "NTTP v3.5 (Ok)"; + }; + }; + + ErrorLogger1 { + compatible = "eswin,eic7700,register", "eswin,eic7700,noc,filter,routeid"; + offset,length = < 0x18 32>; + description = "Register 1 to log errors"; + InitFlow { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 19 4 >; + lut = + "aon_snoc_sp0/I/0", + "dspt_snoc/I/0", + "jtag_snoc/I/0", + "mcput_snoc_d2d/I/0", + "mcput_snoc_mp/I/0", + "mcput_snoc_sp0/I/0", + "mcput_snoc_sp1/I/0", + "mnoc_snoc/I/0", + "npu_snoc_sp0/I/0", + "npu_snoc_sp1/I/0", + "pciet_snoc_p/I/0", + "rnoc_snoc/I/0", + "spislv_tbu3_snoc/I/0", + "tbu4_snoc/I/0", + "tcu_snoc/I/0", + "RESERVED0"; + }; + + TargetFlow { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 15 4 >; + lut = + "snoc_aon/T/0", + "snoc_cnoc/T/0", + "snoc_ddrt0_p1/T/0", + "snoc_ddrt0_p2/T/0", + "snoc_ddrt1_p1/T/0", + "snoc_ddrt1_p2/T/0", + "snoc_dspt/T/0", + "snoc_lnoc/T/0", + "snoc_mcput_d2d/T/0", + "snoc_mnoc/T/0", + "snoc_npu/T/0", + "snoc_pciet/T/0", + "snoc_rnoc/T/0", + "snoc_service/T/0", + "RESERVED1", + "RESERVED2"; + }; + + TargetSubRange { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 9 6 >; + }; + + SeqId { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0 9 >; + }; + }; + + ErrorLogger3 { + /* This register does not really include a bitfield or its bitfield is 32 bits and it provides an offset address */ + /* To calculate the absolute address, you must use the initflow:targetflow:subrange from ErrorLogger1 register */ + /* And use it as an index in the aperture table. Then you must add the value of this register to the value given */ + /* by the table to get the absolute address. */ + compatible = "eswin,eic7700,register"; + offset,length = <0x20 32>; + description = "Register 3 to log errors"; + aperture-link = <1>; /* link to ErrorLogger whose information are required to calculate real absolute address */ + msb-link = <4>; /*indicate which ErrorLogger contains the msb addrs, -1 means no*/ + AbsoluteAddress { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 9 14 >; /* bitfield initflow:targeflow:subrange from aperture-link register */ + aperture-size= < 1181 >; /* Number of line in the aperture table below */ + aperture-idx,aperture-base = /* Aperture_idx is concatenation of initflow:targetflow:subrange bitfield from ErrorLogger1 */ + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 , + /bits/ 64 ; + }; + }; + + ErrorLogger4 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x24 32>; + description = "Register 4 to log errors"; + addr_msb { + compatible = "eswin,eic7700,bitfield"; + description = "Stores NTTP packet header field Addr (MSBs) of the logged error"; + offset,length = < 0 9 >; + }; + }; + + ErrorLogger5 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x28 32>; + description = "Register 5 to log errors"; + + User_flag { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0x0 18 >; + lut = + "Cache_0", + "Cache_1", + "Cache_2", + "Cache_3", + "Prot_0 ", + "Prot_1 ", + "Prot_2 ", + "User_0 ", + "User_1 ", + "User_2 ", + "User_3 ", + "User_4 ", + "User_5 ", + "User_6 ", + "qos0", + "qos1", + "qos2", + "qos3"; + }; + }; +}; + +d0_media_noc:d0_media_noc@52021400 { + compatible = "eswin,eic7700-noc"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + reg = <0 0x52021400 0 0x4000>; + interrupts = <454>; + interrupt-names = "error"; + interrupt-parent = <&plic0>; + errlogger,idx = <0 1 3 4 5>; + eswin,qos-configs = "GPU", "TBU2", "VC"; + eswin,GPU-qos-base = <0x52021480>; + eswin,GPU-qos-settings = < + 0x8 0x4 /* prio */ + 0xC 0x2 /* mode */ + 0x10 0x1E0 /* bandwidth*/ + 0x14 0x1 /* saturation*/ + 0x18 0x1>; /* QoSEn */ + + eswin,TBU2-qos-base = <0x52021500>; + eswin,TBU2-qos-settings = < + 0x8 0x4 /* prio */ + 0xC 0x2 /* mode */ + 0x10 0x18 /* bandwidth */ + 0x14 0x10 /* saturation */ + 0x18 0x1>; /* QoSEn */ + + eswin,VC-qos-base = <0x52021580>; + eswin,VC-qos-settings = < + 0x8 0x4 /* prio */ + 0xC 0x2 /* mode */ + 0x10 0x18 /* bandwidth */ + 0x14 0x10 /* saturation */ + 0x18 0x1>; /* QoSEn */ + sideband_manager@52022000 { + compatible = "eswin,win2xxx-noc-sideband-manager"; + reg = <0 0x52022000 0 0x10>; + SenseIn0 = + , + , + , + , + ; + bf-name = + "SBM_MNOC_GPU", + "SBM_MNOC_TBU2", + "SBM_MNOC_VC", + "SBM_MNOC_DDRT0_P3", + "SBM_MNOC_DDRT1_P3"; + }; + + mnoc_packet_ddr0_p3_req_probe@52020000 { + compatible = "eswin,win2xxx-noc-packet-probe"; + reg = <0 0x52020000 0 0x4000>; + clocks = <&d0_clock EIC7700_CLK_DDRT0_P3_ACLK>; + clock-names = "clk"; + interrupts = <458>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <1>; + counter,nr = <2>; + portsel = "ddr0_p3_req"; + }; + mnoc_packet_ddr1_p3_req_probe@52020800 { + compatible = "eswin,win2xxx-noc-packet-probe"; + reg = <0 0x52020800 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_DDRT1_P3_ACLK>; + clock-names = "clk"; + interrupts = <456>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <1>; + counter,nr = <2>; + portsel = "ddr1_p3_req"; + }; + mnoc_trans_probe@52021000 { + #address-cells = <2>; + #size-cells = <2>; + ranges; + compatible = "eswin,win2xxx-noc-trans-probe"; + reg = <0 0x52021000 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_NOC_NSP_CLK>; + clock-names = "clk"; + interrupts = <453>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <3>; + counter,nr = <12>; + profiler,nr = <1>; + portsel = "gpu", "tbu2", "vc"; + mnoc_trans_gpu_filter@52021600 { + status = "disabled"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52021600 0 0x80>; + }; + mnoc_trans_tbu2_filter@52021680 { /*hsp subsys*/ + status = "disabled"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52021680 0 0x80>; + }; + mnoc_trans_vc_filter@52021700 { + status = "disabled"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52021700 0 0x80>; + }; + mnoc_trans_profiler@52021780 { + compatible = "eswin,win2xxx-noc-trans-profiler"; + reg = <0 0x52021780 0 0x80>; + }; + }; + ErrorLogger0 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x14 32 >; + description = "Register 0 to log errors"; + lock { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0 1 >; + lut = "Not Locked", "Locked"; + }; + OpCode { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 1 4 >; + lut = "RD: data read with incrementing address", + "RDW: data read with wrapping address", + "RDL: allocates monitor in the Target with incrementing address", + "RDX: exclusive read with incrementing address", + "WR: data write with incrementing address", + "WRW: data write with wrapping address", + "WRC: conditional write if matching monitor in Target is found", + "RSV: reserved", + "PRE: preamble packet of linked sequence (locked sequence)", + "URG: urgency packet used for QoS (status must be REQ)"; + }; + ErrCode { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 8 3 >; + lut = "SLV (error source: Target): error detected by the Slave without any information or no Error", + "DEC (error source: Initiator NIU): decode error", + "UNS (error source: Target NIU): unsupported access type", + "DISC (error source: Power Disconnect): disconnected Target or NoC domain", + "SEC (error source: Initiator NIU or Firewall): security error", + "HIDE (error source: Firewall): hidden security error. Will be reported as OK to the initiator", + "TMO (error source: Target NIU): time-out", + "RSV: reserved"; + + }; + Len1 { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 16 12 >; + }; + Format { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 31 1 >; + lut = "NTTP v3.0 (Invalid)", "NTTP v3.5 (Ok)"; + }; + }; + + ErrorLogger1 { + compatible = "eswin,eic7700,register", "eswin,eic7700,noc,filter,routeid"; + offset,length = < 0x18 32>; + description = "Register 1 to log errors"; + InitFlow { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 14 2 >; + lut = + "gpu_mnoc/I/0", + "snoc_mnoc/I/0", + "tbu2_mnoc/I/0", + "vc_mnoc/I/0"; + }; + + TargetFlow { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 12 2 >; + lut = + "mnoc_ddrt0_p3/T/0", + "mnoc_ddrt1_p3/T/0", + "mnoc_service/T/0", + "mnoc_snoc/T/0"; + }; + + TargetSubRange { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 9 3 >; + }; + + SeqId { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0 9 >; + }; + }; + + ErrorLogger3 { + /* This register does not really include a bitfield or its bitfield is 32 bits and it provides an offset address */ + /* To calculate the absolute address, you must use the initflow:targetflow:subrange from ErrorLogger1 register */ + /* And use it as an index in the aperture table. Then you must add the value of this register to the value given */ + /* by the table to get the absolute address. */ + compatible = "eswin,eic7700,register"; + offset,length = <0x20 32>; + description = "Register 3 to log errors"; + aperture-link = <1>; /* link to ErrorLogger whose information are required to calculate real absolute address */ + msb-link = <4>; /*indicate which ErrorLogger contains the msb addrs, -1 means no*/ + AbsoluteAddress { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 9 7 >; /* bitfield initflow:targeflow:subrange from aperture-link register */ + aperture-size= < 55 >; /* Number of line in the aperture table below */ + aperture-idx,aperture-base = /* Aperture_idx is concatenation of initflow:targetflow:subrange bitfield from ErrorLogger1 */ + /bits/ 64 <0x0 0x0 0x0 0x80000000 >, + /bits/ 64 <0x0 0x0 0x1 0x100000000 >, + /bits/ 64 <0x0 0x0 0x2 0x200000000 >, + /bits/ 64 <0x0 0x0 0x3 0x400000000 >, + /bits/ 64 <0x0 0x0 0x4 0x800000000 >, + /bits/ 64 <0x0 0x0 0x5 0x2000000000 >, + /bits/ 64 <0x0 0x0 0x6 0x4000000000 >, + /bits/ 64 <0x0 0x0 0x7 0x4000000100 >, + /bits/ 64 <0x0 0x1 0x0 0x80000080 >, + /bits/ 64 <0x0 0x1 0x1 0x100000080 >, + /bits/ 64 <0x0 0x1 0x2 0x200000080 >, + /bits/ 64 <0x0 0x1 0x3 0x400000080 >, + /bits/ 64 <0x0 0x1 0x4 0x800000080 >, + /bits/ 64 <0x0 0x1 0x5 0x2000000080 >, + /bits/ 64 <0x0 0x1 0x6 0x4000000080 >, + /bits/ 64 <0x0 0x1 0x7 0x4000000180 >, + /bits/ 64 <0x0 0x3 0x0 0x0 >, + /bits/ 64 <0x1 0x2 0x0 0x52020000 >, + /bits/ 64 <0x1 0x2 0x1 0x72020000 >, + /bits/ 64 <0x1 0x2 0x2 0x0 >, + /bits/ 64 <0x1 0x2 0x3 0x0 >, + /bits/ 64 <0x2 0x0 0x0 0x80000000 >, + /bits/ 64 <0x2 0x0 0x1 0x100000000 >, + /bits/ 64 <0x2 0x0 0x2 0x200000000 >, + /bits/ 64 <0x2 0x0 0x3 0x400000000 >, + /bits/ 64 <0x2 0x0 0x4 0x800000000 >, + /bits/ 64 <0x2 0x0 0x5 0x2000000000 >, + /bits/ 64 <0x2 0x0 0x6 0x4000000000 >, + /bits/ 64 <0x2 0x0 0x7 0x4000000100 >, + /bits/ 64 <0x2 0x1 0x0 0x80000080 >, + /bits/ 64 <0x2 0x1 0x1 0x100000080 >, + /bits/ 64 <0x2 0x1 0x2 0x200000080 >, + /bits/ 64 <0x2 0x1 0x3 0x400000080 >, + /bits/ 64 <0x2 0x1 0x4 0x800000080 >, + /bits/ 64 <0x2 0x1 0x5 0x2000000080 >, + /bits/ 64 <0x2 0x1 0x6 0x4000000080 >, + /bits/ 64 <0x2 0x1 0x7 0x4000000180 >, + /bits/ 64 <0x2 0x3 0x0 0x0 >, + /bits/ 64 <0x3 0x0 0x0 0x80000000 >, + /bits/ 64 <0x3 0x0 0x1 0x100000000 >, + /bits/ 64 <0x3 0x0 0x2 0x200000000 >, + /bits/ 64 <0x3 0x0 0x3 0x400000000 >, + /bits/ 64 <0x3 0x0 0x4 0x800000000 >, + /bits/ 64 <0x3 0x0 0x5 0x2000000000 >, + /bits/ 64 <0x3 0x0 0x6 0x4000000000 >, + /bits/ 64 <0x3 0x0 0x7 0x4000000100 >, + /bits/ 64 <0x3 0x1 0x0 0x80000080 >, + /bits/ 64 <0x3 0x1 0x1 0x100000080 >, + /bits/ 64 <0x3 0x1 0x2 0x200000080 >, + /bits/ 64 <0x3 0x1 0x3 0x400000080 >, + /bits/ 64 <0x3 0x1 0x4 0x800000080 >, + /bits/ 64 <0x3 0x1 0x5 0x2000000080 >, + /bits/ 64 <0x3 0x1 0x6 0x4000000080 >, + /bits/ 64 <0x3 0x1 0x7 0x4000000180 >, + /bits/ 64 <0x3 0x3 0x0 0x0 >; + }; + }; + + ErrorLogger4 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x24 32>; + description = "Register 4 to log errors"; + addr_msb { + compatible = "eswin,eic7700,bitfield"; + description = "Stores NTTP packet header field Addr (MSBs) of the logged error"; + offset,length = < 0 9 >; + }; + }; + + ErrorLogger5 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x28 32 >; + description = "Register 5 to log errors"; + + User_flag { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0x0 18 >; + lut = + "Cache_0", + "Cache_1", + "Cache_2", + "Cache_3", + "Prot_0 ", + "Prot_1 ", + "Prot_2 ", + "User_0 ", + "User_1 ", + "User_2 ", + "User_3 ", + "User_4 ", + "User_5 ", + "User_6 ", + "qos0", + "qos1", + "qos2", + "qos3"; + }; + }; +}; + +d0_realtime_noc:d0_realtime_noc@52041400 { + compatible = "eswin,eic7700-noc"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + reg = <0 0x52041400 0 0x4000>; + interrupts = <448>; + interrupt-names = "error"; + interrupt-parent = <&plic0>; + errlogger,idx = <0 1 3 4 5>; + eswin,qos-configs = "TBU0", "VO"; + eswin,TBU0-qos-base = <0x52041480>; + eswin,TBU0-qos-settings = < + 0x8 0x4 /* prio */ + 0xC 0x2 /* mode */ + 0x10 0x1E0 /* bandwidth */ + 0x14 0x1 /* saturation */ + 0x18 0x1>; /* QoSEn */ + + eswin,VO-qos-base = <0x52041500>; + eswin,VO-qos-settings = < + 0x8 0x4 /* prio */ + 0xC 0x2 /* mode */ + 0x10 0x18 /* bandwidth */ + 0x14 0x10 /* saturation */ + 0x18 0x1>; /* QoSEn */ + sideband_manager@52042000 { + compatible = "eswin,win2xxx-noc-sideband-manager"; + reg = <0 0x52042000 0 0x10>; + SenseIn0 = + , + , + , + ; + bf-name = + "SBM_RNOC_TBU0", + "SBM_RNOC_VO", + "SBM_RNOC_DDRT0_P4", + "SBM_RNOC_DDRT1_P4"; + }; + + rnoc_packet_ddr0_p4_req_probe@52040000 { + compatible = "eswin,win2xxx-noc-packet-probe"; + reg = <0 0x52040000 0 0x4000>; + clocks = <&d0_clock EIC7700_CLK_DDRT0_P4_ACLK>; + clock-names = "clk"; + interrupts = <452>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <1>; + counter,nr = <2>; + portsel = "ddr0_p4_req"; + }; + rnoc_packet_ddr1_p4_req_probe@52040800 { + compatible = "eswin,win2xxx-noc-packet-probe"; + reg = <0 0x52040800 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_DDRT1_P4_ACLK>; + clock-names = "clk"; + interrupts = <450>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <1>; + counter,nr = <2>; + portsel = "ddr1_p4_req"; + }; + rnoc_trans_probe@52041000 { + #address-cells = <2>; + #size-cells = <2>; + ranges; + compatible = "eswin,win2xxx-noc-trans-probe"; + reg = <0 0x52041000 0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_NOC_NSP_CLK>; + clock-names = "clk"; + interrupts = <447>; + interrupt-names = "stat"; + interrupt-parent = <&plic0>; + filter,nr = <2>; + counter,nr = <8>; + profiler,nr = <1>; + portsel = "tbu0", "vo"; + rnoc_trans_tbu0_filter@52041580 { /*vi subsys*/ + status = "disabled"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52041580 0 0x80>; + }; + rnoc_trans_vo_filter@52041600 { + status = "disabled"; + compatible = "eswin,win2xxx-noc-trans-filter"; + reg = <0 0x52041600 0 0x80>; + }; + rnoc_trans_profiler@52041680 { + compatible = "eswin,win2xxx-noc-trans-profiler"; + reg = <0 0x52041680 0 0x80>; + }; + }; + ErrorLogger0 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x14 32 >; + description = "Register 0 to log errors"; + lock { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0 1 >; + lut = "Not Locked", "Locked"; + }; + OpCode { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 1 4 >; + lut = "RD: data read with incrementing address", + "RDW: data read with wrapping address", + "RDL: allocates monitor in the Target with incrementing address", + "RDX: exclusive read with incrementing address", + "WR: data write with incrementing address", + "WRW: data write with wrapping address", + "WRC: conditional write if matching monitor in Target is found", + "RSV: reserved", + "PRE: preamble packet of linked sequence (locked sequence)", + "URG: urgency packet used for QoS (status must be REQ)"; + }; + ErrCode { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 8 3 >; + lut = "SLV (error source: Target): error detected by the Slave without any information or no Error", + "DEC (error source: Initiator NIU): decode error", + "UNS (error source: Target NIU): unsupported access type", + "DISC (error source: Power Disconnect): disconnected Target or NoC domain", + "SEC (error source: Initiator NIU or Firewall): security error", + "HIDE (error source: Firewall): hidden security error. Will be reported as OK to the initiator", + "TMO (error source: Target NIU): time-out", + "RSV: reserved"; + + }; + Len1 { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 16 12 >; + }; + Format { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 31 1 >; + lut = "NTTP v3.0 (Invalid)", "NTTP v3.5 (Ok)"; + }; + }; + + ErrorLogger1 { + compatible = "eswin,eic7700,register", "eswin,eic7700,noc,filter,routeid"; + offset,length = < 0x18 32>; + description = "Register 1 to log errors"; + InitFlow { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 14 2 >; + lut = + "snoc_rnoc/I/0", + "tbu0_rnoc/I/0", + "vo_rnoc/I/0", + "RESERVED0"; + }; + + TargetFlow { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 12 2 >; + lut = + "rnoc_ddrt0_p4/T/0", + "rnoc_ddrt1_p4/T/0", + "rnoc_service/T/0", + "rnoc_snoc/T/0"; + }; + + TargetSubRange { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 9 3 >; + }; + + SeqId { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0 9 >; + }; + }; + + ErrorLogger3 { + /* This register does not really include a bitfield or its bitfield is 32 bits and it provides an offset address */ + /* To calculate the absolute address, you must use the initflow:targetflow:subrange from ErrorLogger1 register */ + /* And use it as an index in the aperture table. Then you must add the value of this register to the value given */ + /* by the table to get the absolute address. */ + compatible = "eswin,eic7700,register"; + offset,length = <0x20 32>; + description = "Register 3 to log errors"; + aperture-link = <1>; /* link to ErrorLogger whose information are required to calculate real absolute address */ + msb-link = <4>; /*indicate which ErrorLogger contains the msb addrs, -1 means no*/ + AbsoluteAddress { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 9 7 >; /* bitfield initflow:targeflow:subrange from aperture-link register */ + aperture-size= < 40 >; /* Number of line in the aperture table below */ + aperture-idx,aperture-base = /* Aperture_idx is concatenation of initflow:targetflow:subrange bitfield from ErrorLogger1 */ + /bits/ 64 <0x0 0x2 0x0 0x52040000 >, + /bits/ 64 <0x0 0x2 0x1 0x72040000 >, + /bits/ 64 <0x0 0x2 0x2 0x0 >, + /bits/ 64 <0x0 0x2 0x3 0x0 >, + /bits/ 64 <0x1 0x0 0x0 0x80000000 >, + /bits/ 64 <0x1 0x0 0x1 0x100000000 >, + /bits/ 64 <0x1 0x0 0x2 0x200000000 >, + /bits/ 64 <0x1 0x0 0x3 0x400000000 >, + /bits/ 64 <0x1 0x0 0x4 0x800000000 >, + /bits/ 64 <0x1 0x0 0x5 0x2000000000 >, + /bits/ 64 <0x1 0x1 0x0 0x80000080 >, + /bits/ 64 <0x1 0x1 0x1 0x100000080 >, + /bits/ 64 <0x1 0x1 0x2 0x200000080 >, + /bits/ 64 <0x1 0x1 0x3 0x400000080 >, + /bits/ 64 <0x1 0x1 0x4 0x800000080 >, + /bits/ 64 <0x1 0x1 0x5 0x2000000080 >, + /bits/ 64 <0x1 0x3 0x0 0x59000000 >, + /bits/ 64 <0x1 0x3 0x1 0x79000000 >, + /bits/ 64 <0x1 0x3 0x2 0x14001000000 >, + /bits/ 64 <0x1 0x3 0x3 0x14009000000 >, + /bits/ 64 <0x1 0x3 0x4 0x0 >, + /bits/ 64 <0x1 0x3 0x5 0x0 >, + /bits/ 64 <0x2 0x0 0x0 0x80000000 >, + /bits/ 64 <0x2 0x0 0x1 0x100000000 >, + /bits/ 64 <0x2 0x0 0x2 0x200000000 >, + /bits/ 64 <0x2 0x0 0x3 0x400000000 >, + /bits/ 64 <0x2 0x0 0x4 0x800000000 >, + /bits/ 64 <0x2 0x0 0x5 0x2000000000 >, + /bits/ 64 <0x2 0x1 0x0 0x80000080 >, + /bits/ 64 <0x2 0x1 0x1 0x100000080 >, + /bits/ 64 <0x2 0x1 0x2 0x200000080 >, + /bits/ 64 <0x2 0x1 0x3 0x400000080 >, + /bits/ 64 <0x2 0x1 0x4 0x800000080 >, + /bits/ 64 <0x2 0x1 0x5 0x2000000080 >, + /bits/ 64 <0x2 0x3 0x0 0x59000000 >, + /bits/ 64 <0x2 0x3 0x1 0x79000000 >, + /bits/ 64 <0x2 0x3 0x2 0x14001000000 >, + /bits/ 64 <0x2 0x3 0x3 0x14009000000 >, + /bits/ 64 <0x2 0x3 0x4 0x0 >, + /bits/ 64 <0x2 0x3 0x5 0x0 >; + }; + }; + + ErrorLogger4 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x24 32>; + description = "Register 4 to log errors"; + addr_msb { + compatible = "eswin,eic7700,bitfield"; + description = "Stores NTTP packet header field Addr (MSBs) of the logged error"; + offset,length = < 0 9 >; + }; + }; + + ErrorLogger5 { + compatible = "eswin,eic7700,register"; + offset,length = < 0x28 32 >; + description = "Register 5 to log errors"; + + User_flag { + compatible = "eswin,eic7700,bitfield"; + offset,length = < 0x0 16 >; + lut = + "Cache_0", + "Cache_1", + "Cache_2", + "Cache_3", + "Prot_0 ", + "Prot_1 ", + "Prot_2 ", + "User_0 ", + "User_1 ", + "User_2 ", + "User_3 ", + "User_4 ", + "qos0", + "qos1", + "qos2", + "qos3"; + }; + }; +}; diff --git a/arch/riscv/boot/dts/eswin/eic7700.dtsi b/arch/riscv/boot/dts/eswin/eic7700.dtsi new file mode 100644 index 0000000000000..01be763cdf5ef --- /dev/null +++ b/arch/riscv/boot/dts/eswin/eic7700.dtsi @@ -0,0 +1,2200 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Include file for Die0 System peripherals 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 . + */ + +#include "eic7700-arch.dtsi" +#include +#include +#include +#include +#include + +/ { + compatible = "eswin,eic7700"; + d0_cpu_opp_table: opp-table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp-24000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-100000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-200000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-400000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-500000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-600000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-700000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-800000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-900000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-1000000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-1200000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-1300000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-1400000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-1500000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-1600000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-1700000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + opp-1800000000 { + opp-hz = /bits/ 64 ; + opp-microvolt = <800000>; + clock-latency-ns = <70000>; + }; + }; +}; + +&SOC { + d0_uart0: serial@0x50900000 { + compatible = "snps,dw-apb-uart"; + reg = <0x0 0x50900000 0x0 0x10000>; + clock-frequency = ; + interrupt-parent = <&plic0>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + numa-node-id = <0>; + }; + + d0_uart1: serial@0x50910000 { + compatible = "snps,dw-apb-uart"; + reg = <0x0 0x50910000 0x0 0x10000>; + clock-frequency = ; + interrupt-parent = <&plic0>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + numa-node-id = <0>; + }; + + d0_uart2: serial@0x50920000 { + compatible = "snps,dw-apb-uart"; + reg = <0x0 0x50920000 0x0 0x10000>; + clock-frequency = ; + interrupt-parent = <&plic0>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + numa-node-id = <0>; + status = "disabled"; + }; + + d0_uart3: serial@0x50930000 { + compatible = "snps,dw-apb-uart"; + reg = <0x0 0x50930000 0x0 0x10000>; + clock-frequency = ; + interrupt-parent = <&plic0>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + numa-node-id = <0>; + status = "disabled"; + }; + + d0_uart4: serial@0x50940000 { + compatible = "snps,dw-apb-uart"; + reg = <0x0 0x50940000 0x0 0x10000>; + clock-frequency = ; + interrupt-parent = <&plic0>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + numa-node-id = <0>; + status = "disabled"; + }; + + d0_sys_con: scu_sys_con@0x51810000 { + compatible = "eswin,eic7700-scu-sys-con", "syscon", "simple-mfd"; + #syscon-cells = <2>; + #size-cells = <2>; + reg = <0x0 0x51810000 0x0 0x8000>; + numa-node-id = <0>; + d0_noc_wdt:noc@51810324 { + compatible = "eswin,eic7700-noc-wdt"; + interrupt-parent = <&plic0>; + interrupts = <392>, <393>, <394>, <395>, + <396>, <397>, <398>, <399>, <400>, + <401>, <402>, <403>, <404>, <405>, + <406>, <407>, <408>, <409>, <410>, + <411>, <412>, <413>, <414>, <415>, + <416>, <417>, <418>, <419>, <420>, + <421>, <422>, <423>, <424>, <425>, + <426>; + eswin,syscrg_csr = <&d0_sys_crg 0x100 0xffff>; //timeout paramerter + status = "disabled"; + }; + }; + + d0_sys_crg: sys-crg@51828000 { + compatible = "eswin,eic7700-sys-crg", "syscon", "simple-mfd"; + reg = <0x000000 0x51828000 0x000000 0x80000>; + numa-node-id = <0>; + d0_reset: reset-controller { + compatible = "eswin,eic7700-reset"; + #reset-cells = <2>; + }; + d0_clock: clock-controller { + compatible = "eswin,eic7700-clock"; + #clock-cells = <1>; + }; + }; + + hfclk: hfclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + clock-output-names = "hfclk"; + }; + + d0_hsp_sp_csr: hsp_sp_top_csr@0x50440000 { + compatible = "eswin,eic7700-hsp-sp-csr", "syscon"; + #size-cells = <2>; + reg = <0x0 0x50440000 0x0 0x2000>; + }; + + smmu0: iommu@50c00000 { + compatible = "arm,smmu-v3"; + reg = <0x0 0x50c00000 0x0 0x100000>; + eswin,syscfg = <&d0_sys_con 0x3fc>; + interrupt-parent = <&plic0>; + interrupts = <356>, + <360>, + <357>, + <358>; + interrupt-names = "eventq", "gerror", "priq", "cmdq-sync"; + #iommu-cells = <1>; + resets = <&d0_reset TCU_RST_CTRL SW_TCU_AXI_RSTN>, + <&d0_reset TCU_RST_CTRL SW_TCU_CFG_RSTN>, + <&d0_reset TCU_RST_CTRL TBU_RSTN_0>, + <&d0_reset TCU_RST_CTRL TBU_RSTN_1>, + <&d0_reset TCU_RST_CTRL TBU_RSTN_2>, + <&d0_reset TCU_RST_CTRL TBU_RSTN_3>, + <&d0_reset TCU_RST_CTRL TBU_RSTN_4>, + <&d0_reset TCU_RST_CTRL TBU_RSTN_5>, + <&d0_reset TCU_RST_CTRL TBU_RSTN_6>, + <&d0_reset TCU_RST_CTRL TBU_RSTN_7>; + reset-names = "axi_rst", "cfg_rst", "tbu0_rst", "tbu1_rst", "tbu2_rst", "tbu3_rst", + "tbu4_rst", "tbu5_rst", "tbu6_rst", "tbu7_rst"; + status = "disabled"; + numa-node-id = <0>; + }; + + smmu_pmu0: pmu@50c02000 { + compatible = "arm,smmu-v3-pmcg"; + reg = <0x0 0x50c02000 0x0 0x1000>, + <0x0 0x50c22000 0x0 0x1000>; + eswin,syscfg = <&d0_sys_con 0x3fc>; + interrupt-parent = <&plic0>; + interrupts = <363>; + status = "disabled"; + numa-node-id = <0>; + }; + + d0_pmu: power-controller@51808000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "eswin,eic7700-pmu-controller"; + reg = <0x0 0x51808000 0x0 0x8000>; + numa-node-id = <0>; + d0_pmu_pcie: eic7700-pmu-controller-port@0 { + compatible = "eswin,eic7700-pmu-controller-port"; + reg_base = <0x0>; + power_status = <1>; + power_delay = <6 6 3 3>; + clock_delay = <4 2 2 2>; + reset_delay = <2 4 2 2>; + clamp_delay = <3 3 2 2>; + label = "D0_PCIE"; + tbus = ; + }; + d0_pmu_dsp1: eic7700-pmu-controller-port@40 { + compatible = "eswin,eic7700-pmu-controller-port"; + reg_base = <0x40>; + power_status = <1>; + power_delay = <6 6 3 3>; + clock_delay = <4 2 2 2>; + reset_delay = <2 4 2 2>; + clamp_delay = <3 3 2 2>; + tbus = ; + label = "D0_DSP1"; + }; + d0_pmu_vi: eic7700-pmu-controller-port@80 { + compatible = "eswin,eic7700-pmu-controller-port"; + reg_base = <0x80>; + power_status = <1>; + power_delay = <6 6 3 3>; + clock_delay = <4 2 2 2>; + reset_delay = <2 4 2 2>; + clamp_delay = <3 3 2 2>; + tbus = ,; + label = "D0_VI"; + }; + d0_pmu_vo: eic7700-pmu-controller-port@c0 { + compatible = "eswin,eic7700-pmu-controller-port"; + reg_base = <0xc0>; + power_status = <1>; + power_delay = <6 6 3 3>; + clock_delay = <4 2 2 2>; + reset_delay = <2 4 2 2>; + clamp_delay = <3 3 2 2>; + label = "D0_VO"; + }; + d0_pmu_codec: eic7700-pmu-controller-port@140 { + compatible = "eswin,eic7700-pmu-controller-port"; + reg_base = <0x140>; + power_status = <1>; + power_delay = <6 6 3 3>; + clock_delay = <4 2 2 2>; + reset_delay = <2 4 2 2>; + clamp_delay = <3 3 2 2>; + tbus = , ,, ; + label = "D0_CODEC"; + }; + d0_pmu_dsp2: eic7700-pmu-controller-port@200 { + compatible = "eswin,eic7700-pmu-controller-port"; + reg_base = <0x200>; + power_status = <1>; + power_delay = <6 6 3 3>; + clock_delay = <4 2 2 2>; + reset_delay = <2 4 2 2>; + clamp_delay = <3 3 2 2>; + tbus = ; + label = "D0_DSP2"; + }; + d0_pmu_dsp3: eic7700-pmu-controller-port@240 { + compatible = "eswin,eic7700-pmu-controller-port"; + reg_base = <0x240>; + power_status = <1>; + power_delay = <6 6 3 3>; + clock_delay = <4 2 2 2>; + reset_delay = <2 4 2 2>; + clamp_delay = <3 3 2 2>; + tbus = ; + label = "D0_DSP3"; + }; + }; + + d0_dmac0: dma-controller-hsp@0x50430000 { + compatible = "snps,axi-dma-1.01a"; + reg = <0x0 0x50430000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <57>; + #dma-cells = <2>; // change dma-cells value <1> to <2>, to support peripheral selection dma-controller,See the parameter dmas for details; + clocks = <&d0_clock EIC7700_CLK_HSP_DMA0_CLK>; + clock-names = "core-clk"; + resets = <&d0_reset HSPDMA_RST_CTRL SW_HSP_DMA0_RSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_HSP_DMA_PRSTN>; + reset-names = "arst", "prst"; + dma-channels = <12>; + snps,dma-masters = <1>; + snps,priority = <0 1 2 3 4 5 6 7 8 9 10 11>; + snps,data-width = <2>; + snps,block-size = <0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000>; + snps,axi-max-burst-len = <16>; + snps,max-msize = <64>; + iommus = <&smmu0 EIC7700_SID_DMA0>; + tbus = ; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x104c>; + eswin,syscfg = <&d0_sys_con DMA1_SID_REG_OFFSET 0x370>; + numa-node-id = <0>; + }; + + d0_aon_dmac: dma-controller-aon@0x518c0000 { + compatible = "snps,axi-dma-1.01a"; + reg = <0x0 0x518c0000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <289>; + #dma-cells = <2>; // change dma-cells value <1> to <2>, to support peripheral selection dma-controller,See the parameter dmas for details; + clocks = <&d0_clock EIC7700_CLK_AONDMA_ACLK>; + clock-names = "core-clk"; + resets = <&d0_reset DMA1_RST_CTRL SW_DMA1_ARSTN>, + <&d0_reset DMA1_RST_CTRL SW_DMA1_HRSTN>; + reset-names = "arst", "prst"; + dma-channels = <16>; + snps,dma-masters = <2>; + snps,priority = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; + snps,data-width = <3>; + snps,block-size = <0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000>; + snps,axi-max-burst-len = <32>; + snps,max-msize = <64>; + #size-cells = <2>; + #address-cells = <2>; + dma-ranges = <0x0 0x80000000 0x0 0x80000000 0x100 0x0>; + iommus = <&smmu0 EIC7700_SID_DMA1>; + tbus = ; + eswin,syscfg = <&d0_sys_con DMA1_SID_REG_OFFSET 0x370>; + numa-node-id = <0>; + }; + + d0_gmac0: ethernet@50400000 { + compatible = "eswin,eic7700-qos-eth"; + reg = <0x0 0x50400000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupt-names = "macirq"; + interrupts = <61>; + phy-mode = "rgmii"; + numa-node-id = <0>; + id = <0>; + status = "disabled"; + clocks = <&d0_clock EIC7700_CLK_HSP_ETH_APP_CLK>, + <&d0_clock EIC7700_CLK_HSP_ETH_CSR_CLK>, + <&d0_clock EIC7700_CLK_HSP_ETH0_CORE_CLK>; + clock-names = "app", "csr","tx"; + resets = <&d0_reset HSPDMA_RST_CTRL SW_HSP_ETH0_ARSTN>; + reset-names = "ethrst"; + tbus = ; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x1030 0x100 0x108>; + eswin,syscrg_csr = <&d0_sys_crg 0x148 0x14c>; + snps,axi-config = <&d0_stmmac_axi_setup>; + d0_stmmac_axi_setup: stmmac-axi-config { + snps,blen = <0 0 0 0 16 8 4>; + snps,rd_osr_lmt = <2>; + snps,wr_osr_lmt = <2>; + snps,lpi_en = <0>; + }; + }; + + d0_gmac1: ethernet@50410000 { + compatible = "eswin,eic7700-qos-eth"; + reg = <0x0 0x50410000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupt-names = "macirq"; + interrupts = <70>; + phy-mode = "rgmii"; + numa-node-id = <0>; + id = <1>; + status = "disabled"; + clocks = <&d0_clock EIC7700_CLK_HSP_ETH_APP_CLK>, + <&d0_clock EIC7700_CLK_HSP_ETH_CSR_CLK>, + <&d0_clock EIC7700_CLK_HSP_ETH1_CORE_CLK>; + clock-names = "app", "csr","tx"; + resets = <&d0_reset HSPDMA_RST_CTRL SW_HSP_ETH1_ARSTN>; + reset-names = "ethrst"; + tbus = ; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x1034 0x200 0x208>; + eswin,syscrg_csr = <&d0_sys_crg 0x148 0x14c>; + 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>; + snps,rd_osr_lmt = <2>; + snps,wr_osr_lmt = <2>; + snps,lpi_en = <0>; + }; + }; + noc { + compatible = "eswin,noc","simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + #include "eic7700-noc.dtsi" + }; + + d0_npu: eswin-npu@51c00000 { + compatible = "eswin,npu0"; + reg = <0x0 0x51c00000 0x0 0x400000>; + interrupt-parent = <&plic0>; + interrupts = <387 16>; + /*spram-region = <&npu0_reserved>;*/ + #size-cells = <2>; + dma-ranges = <0x1 0x0 0x0 0xc0000000 0x1ff 0x0>; + iommus = <&smmu0 EIC7700_SID_NPU_DMA>; + tbus = ; + dsp-avail-num = <1>; + spram-size = <0x400000>; + npu_mbox = <&d0_mbox2>; + resets = <&d0_reset NPU_RST_CTRL SW_NPU_E31CORE_RSTN>; + reset-names = "e31_core"; + numa-node-id = <0>; + }; + + dev_llc_d0: llc@51c00000 { + compatible = "eswin,llc"; + reg = <0x0 0x51c00000 0x0 0x400000>; + eswin,syscfg = <&d0_sys_con 0x324>; + eswin,syscrg_csr = <&d0_sys_crg>; + clocks = <&d0_clock EIC7700_CLK_NPU_ACLK>, + <&d0_clock EIC7700_CLK_NPU_CFG_CLK>, + <&d0_clock EIC7700_CLK_NPU_LLC_ACLK>, + <&d0_clock EIC7700_CLK_NPU_CLK>, + <&d0_clock EIC7700_MUX_U_NPU_CORE_3MUX1_GFREE>, + <&d0_clock EIC7700_SPLL2_FOUT2>; + clock-names = "aclk", "cfg_clk", "llc_clk", "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_AXI_RSTN>, + <&d0_reset NPU_RST_CTRL SW_NPU_CFG_RSTN>, + <&d0_reset NPU_RST_CTRL SW_NPU_CORE_RSTN>, + <&d0_reset NPU_RST_CTRL SW_NPU_LLC_RSTN>; + reset-names = "axi", "cfg", "core", "llc"; + numa-node-id = <0>; + spram-region = <&npu0_reserved>; + }; + + d0_dsp_subsys:dsp_subsys@52280400 { + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0x52280400 0x0 0x10000>, + <0x0 0x51810000 0x0 0x8000>; + ranges; + compatible = "es-dsp-subsys", "simple-bus"; + clocks = <&d0_clock EIC7700_CLK_DSPT_CFG_CLK>; + clock-names = "cfg_clk"; + resets = <&d0_reset DSP_RST_CTRL SW_DSP_AXI_RSTN>, + <&d0_reset DSP_RST_CTRL SW_DSP_CFG_RSTN>, + <&d0_reset DSP_RST_CTRL SW_DSP_DIV4_RSTN>, + <&d0_reset DSP_RST_CTRL SW_DSP_DIV_RSTN_0>, + <&d0_reset DSP_RST_CTRL SW_DSP_DIV_RSTN_1>, + <&d0_reset DSP_RST_CTRL SW_DSP_DIV_RSTN_2>, + <&d0_reset DSP_RST_CTRL SW_DSP_DIV_RSTN_3>; + reset-names = "axi", "cfg", "div4", "div_0", "div_1", "div_2","div_3"; + d0_dsp0:es_dsp@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "eswin-dsp", "cdns,xrp-hw-eswin"; + ranges = <0x28000000 0 0x5b000000 0x8000 + 0x28100000 0 0x5b100000 0x20000 + 0x28120000 0 0x5b120000 0x20000>; + clocks = <&d0_clock EIC7700_CLK_DSP_ACLK_0>; + clock-names = "aclk"; + dsp_mbox = <&d0_mbox4>; + device-irq = <11 + ESWIN_MAILBOX_DSP_0_TO_U84_REG_BASE + ESWIN_MAILBOX_WR_LOCK_BIT_DSP_0 + ESWIN_MAILBOX_U84_TO_DSP_0_REG_BASE + ESWIN_MAIBOX_U84_IRQ_BIT + ESWIN_MAILBOX_U84_TO_NPU_0_REG_BASE>; + + device-uart = <0x50900000>; + device-irq-mode = <1>; + host-irq-mode = <1>; + firmware-name = "eic7700_dsp_fw"; + process-id = <0>; + dma-ranges = <0x30000000 0x0 0xc0000000 0xce000000>; + iommus = <&smmu0 EIC7700_SID_DSP_0>; + tbus = ; + numa-node-id = <0>; + aux-e31-dtim = <0x5a110000>; + dsp@0 { + }; + }; + d0_dsp1:es_dsp@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "eswin-dsp", "cdns,xrp-hw-eswin"; + ranges = <0x28000000 0 0x5b008000 0x8000 + 0x28100000 0 0x5b140000 0x20000 + 0x28120000 0 0x5b160000 0x20000>; + clocks = <&d0_clock EIC7700_CLK_DSP_ACLK_1>; + clock-names = "aclk"; + dsp_mbox = <&d0_mbox5>; + device-irq = <13 + ESWIN_MAILBOX_DSP_1_TO_U84_REG_BASE + ESWIN_MAILBOX_WR_LOCK_BIT_DSP_1 + ESWIN_MAILBOX_U84_TO_DSP_1_REG_BASE + ESWIN_MAIBOX_U84_IRQ_BIT + ESWIN_MAILBOX_U84_TO_NPU_0_REG_BASE>; + device-uart = <0x50900000>; + device-irq-mode = <1>; + host-irq-mode = <1>; + firmware-name = "eic7700_dsp_fw"; + process-id = <1>; + dma-ranges = <0x30000000 0x0 0xc0000000 0xce000000>; + iommus = <&smmu0 EIC7700_SID_DSP_1>; + tbus = ; + numa-node-id = <0>; + aux-e31-dtim = <0x5a110000>; + dsp@0 { + }; + }; + d0_dsp2:es_dsp@2 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "eswin-dsp", "cdns,xrp-hw-eswin"; + ranges = <0x28000000 0 0x5b010000 0x8000 + 0x28100000 0 0x5b180000 0x20000 + 0x28120000 0 0x5b1a0000 0x20000>; + clocks = <&d0_clock EIC7700_CLK_DSP_ACLK_2>; + clock-names = "aclk"; + dsp_mbox = <&d0_mbox6>; + device-irq = <15 + ESWIN_MAILBOX_DSP_2_TO_U84_REG_BASE + ESWIN_MAILBOX_WR_LOCK_BIT_DSP_2 + ESWIN_MAILBOX_U84_TO_DSP_2_REG_BASE + ESWIN_MAIBOX_U84_IRQ_BIT + ESWIN_MAILBOX_U84_TO_NPU_0_REG_BASE>; + device-uart = <0x50900000>; + device-irq-mode = <1>; + host-irq-mode = <1>; + firmware-name = "eic7700_dsp_fw"; + process-id = <2>; + dma-ranges = <0x30000000 0x0 0xc0000000 0xce000000>; + iommus = <&smmu0 EIC7700_SID_DSP_2>; + tbus = ; + numa-node-id = <0>; + aux-e31-dtim = <0x5a110000>; + dsp@0 { + }; + }; + d0_dsp3:es_dsp@3 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "eswin-dsp", "cdns,xrp-hw-eswin"; + ranges = <0x28000000 0 0x5b018000 0x8000 + 0x28100000 0 0x5b1c0000 0x20000 + 0x28120000 0 0x5b1e0000 0x20000>; + clocks = <&d0_clock EIC7700_CLK_DSP_ACLK_3>; + clock-names = "aclk"; + dsp_mbox = <&d0_mbox7>; + device-irq = <17 + ESWIN_MAILBOX_DSP_3_TO_U84_REG_BASE + ESWIN_MAILBOX_WR_LOCK_BIT_DSP_3 + ESWIN_MAILBOX_U84_TO_DSP_3_REG_BASE + ESWIN_MAIBOX_U84_IRQ_BIT + ESWIN_MAILBOX_U84_TO_NPU_0_REG_BASE>; + device-uart = <0x50900000>; + device-irq-mode = <1>; + host-irq-mode = <1>; + firmware-name = "eic7700_dsp_fw"; + process-id = <3>; + dma-ranges = <0x30000000 0x0 0xc0000000 0xce000000>; + iommus = <&smmu0 EIC7700_SID_DSP_3>; + tbus = ; + numa-node-id = <0>; + aux-e31-dtim = <0x5a110000>; + dsp@0 { + }; + }; + }; + + gc820: g2d@50140000 { + compatible = "eswin,galcore_d0"; + clocks = <&d0_clock EIC7700_CLK_VC_ACLK>, + <&d0_clock EIC7700_CLK_VC_CFG_CLK>, + <&d0_clock EIC7700_CLK_G2D_CFG_CLK>, + <&d0_clock EIC7700_CLK_CLK_G2D_ST2>, + <&d0_clock EIC7700_CLK_G2D_CLK>, + <&d0_clock EIC7700_CLK_G2D_ACLK>, + <&d0_clock EIC7700_CLK_VC_MON_PCLK>; + clock-names = "vc_aclk", "vc_cfg", "g2d_cfg", "g2d_st2", "g2d_clk", "g2d_aclk", "mon_pclk"; + resets = <&d0_reset VC_RST_CTRL SW_VC_AXI_RSTN>, + <&d0_reset VC_RST_CTRL SW_VC_CFG_RSTN>, + <&d0_reset VC_RST_CTRL SW_VC_MONCFG_RSTN>, + <&d0_reset G2D_RST_CTRL SW_G2D_CORE_RSTN>, + <&d0_reset G2D_RST_CTRL SW_G2D_CFG_RSTN>, + <&d0_reset G2D_RST_CTRL SW_G2D_AXI_RSTN>; + reset-names = "axi", "cfg", "moncfg", "g2d_core", "g2d_cfg", "g2d_axi"; + reg = <0 0x50140000 0 0x40000>, <0 0x50180000 0 0x40000>; + reg-names = "core_2d", "core_2d1"; + fe-apb-offset = <0x800>; + interrupt-parent = <&plic0>; + interrupts = <49>, <50>; + interrupt-names = "core_2d", "core_2d1"; + enable-mmu = <1>; + contiguous-size = <0xa00000>; + recovery = <0>; + }; + + gpu0: gpu@51400000 { + compatible = "img,gpu"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0x51400000 0x0 0xFFFFF>; + clocks = <&d0_clock EIC7700_CLK_GPU_ACLK>, + <&d0_clock EIC7700_CLK_GPU_GRAY_CLK>, + <&d0_clock EIC7700_CLK_GPU_CFG_CLK>; + clock-names = "aclk", "gray_clk", "cfg_clk"; + resets =<&d0_reset GPU_RST_CTRL SW_GPU_AXI_RSTN>, + <&d0_reset GPU_RST_CTRL SW_GPU_CFG_RSTN>, + <&d0_reset GPU_RST_CTRL SW_GPU_GRAY_RSTN>, + <&d0_reset GPU_RST_CTRL SW_GPU_JONES_RSTN>, + <&d0_reset GPU_RST_CTRL SW_GPU_SPU_RSTN>; + reset-names = "axi", "cfg", "gray", "jones","spu"; + interrupt-parent = <&plic0>; + interrupts = <15>; + }; + + d0_sata: sata@0x50420000{ + compatible = "snps,eswin-ahci"; + reg = <0x0 0x50420000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupt-names = "intrq", "msi", "pme"; + interrupts = <58>, <59>, <60>; + ports-implemented = <0x1>; + resets = <&d0_reset HSPDMA_RST_CTRL SW_SATA_ASIC0_RSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_SATA_OOB_RSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_SATA_PMALIVE_RSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_SATA_RBC_RSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_HSP_SATA_ARSTN>; + reset-names = "asic0", "oob", "pmalive", "rbc", "apb"; + #size-cells = <2>; + iommus = <&smmu0 EIC7700_SID_SATA>; + tbus = ; + dma-ranges = <0x0 0x0 0x0 0xc0000000 0x200 0x0>; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x1050>; + eswin,syscrg_csr = <&d0_sys_crg 0x41c>; + numa-node-id = <0>; + }; + + pcie: pcie@0x54000000 { + compatible = "eswin,eic7700-pcie"; + clocks = <&d0_clock EIC7700_CLK_PCIET_ACLK>, + <&d0_clock EIC7700_CLK_PCIET_CFG_CLK>, + <&d0_clock EIC7700_CLK_PCIET_CR_CLK>, + <&d0_clock EIC7700_CLK_PCIET_AUX_CLK>; + clock-names = "pcie_aclk", "pcie_cfg_clk", "pcie_cr_clk", "pcie_aux_clk"; + + reset-names = "pcie_cfg", "pcie_powerup", "pcie_pwren"; + resets = <&d0_reset PCIE_RST_CTRL SW_PCIE_CFG_RSTN>, + <&d0_reset PCIE_RST_CTRL SW_PCIE_POWERUP_RSTN>, + <&d0_reset PCIE_RST_CTRL SW_PCIE_PERST_N>; + + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + reg = <0x0 0x54000000 0x0 0x4000000>, /* IP registers */ + <0x0 0x40000000 0x0 0x800000>, /* Configuration space */ + <0x0 0x50000000 0x0 0x100000>; + reg-names = "dbi", "config", "mgmt"; + device_type = "pci"; + /* dma-coherent; */ + bus-range = <0x0 0xff>; + + ranges = <0x81000000 0x0 0x40800000 0x0 0x40800000 0x0 0x800000>, /* I/O */ + <0x82000000 0x0 0x41000000 0x0 0x41000000 0x0 0xf000000>, /* mem */ + <0xc3000000 0x80 0x00000000 0x80 0x00000000 0x02 0x00000000>; /* mem prefetchable */ + + /* num-lanes = <0x4>; */ + /********************************** + msi_ctrl_io[0~31] : 188~219 + msi_ctrl_int : 220 + **********************************/ + interrupts = <220>; + interrupt-names = "msi"; + interrupt-parent = <&plic0>; + iommus = <&smmu0 0xfe0000>; + iommu-map = <0x0 &smmu0 0xff0000 0xffffff>; + gen-x = <3>; + lane-x = <4>; + tbus = ; + status = "disabled"; + numa-node-id = <0>; + }; + + ssi0: spi@50810000 { + compatible = "snps,eic7700-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x50810000 0x0 0x4000>; + spi-max-frequency = <4800000>; + clocks = <&d0_clock EIC7700_CLK_LSP_SSI0_PCLK>; + clock-names = "clk"; + interrupt-parent = <&plic0>; + interrupts = <91>; + resets = <&d0_reset SSI_RST_CTRL SW_SSI_RST_N_0>; + reset-names = "spi"; + eswin,spi_dma = <&d0_aon_dmac>; + dmas = <&d0_aon_dmac 38 3>, <&d0_aon_dmac 39 3>; + dma-names = "rx", "tx"; + numa-node-id = <0>; + status = "disabled"; + }; + + ssi1: spi@50814000 { + compatible = "snps,eic7700-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x50814000 0x0 0x4000>; + spi-max-frequency = <4800000>; + clocks = <&d0_clock EIC7700_CLK_LSP_SSI1_PCLK>; + clock-names = "clk"; + interrupt-parent = <&plic0>; + interrupts = <92>; + resets = <&d0_reset SSI_RST_CTRL SW_SSI_RST_N_1>; + reset-names = "spi"; + eswin,spi_dma = <&d0_aon_dmac>; + dmas = <&d0_aon_dmac 36 4>, <&d0_aon_dmac 37 4>; + dma-names = "rx", "tx"; + numa-node-id = <0>; + status = "disabled"; + }; + + bootspi: spi@51800000 { + compatible = "eswin,bootspi"; + reg = <0x0 0x51800000 0x0 0x8000>, + <0x0 0x51828000 0x0 0x8000>, + <0x0 0x5c000000 0x0 0x8000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&d0_clock EIC7700_CLK_CLK_BOOTSPI_CFG>, + <&d0_clock EIC7700_CLK_CLK_BOOTSPI>; + clock-names = "cfg_clk", "clk"; + resets = <&d0_reset BOOTSPI_RST_CTRL SW_BOOTSPI_RSTN>; + reset-names = "rst"; + spi-max-frequency = <4800000>; + reg-io-width = <4>; + status = "disabled"; + }; + + sdhci_emmc: mmc@50450000 { + compatible = "eswin,emmc-sdhci-5.1"; + reg = <0x0 0x50450000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <79>; + assigned-clocks = <&d0_clock EIC7700_CLK_HSP_MSHC0_CORE_CLK>; + assigned-clock-rates = <200000000>; + clocks = <&d0_clock EIC7700_CLK_HSP_MSHC0_CORE_CLK>, <&d0_clock EIC7700_CLK_HSP_CFG_CLK>; + clock-names = "clk_xin", "clk_ahb"; + clock-output-names = "emmc_cardclock"; + #clock-cells = <0>; + + resets = <&d0_reset HSPDMA_RST_CTRL SW_MSHC0_TXRX_RSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_MSHC0_PHY_RSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_HSP_EMMC_PRSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_HSP_EMMC_ARSTN>; + reset-names = "txrx_rst", "phy_rst", "prstn", "arstn"; + + disable-cqe-dcmd; + bus-width = <8>; + non-removable; + /*mmc-ddr-1_8v;*/ + mmc-hs400-1_8v; + max-frequency = <200000000>; + /* sdhci-caps-mask = <0x0 0x3200000>; */ + /* sdhci-caps-mask = <0x2 0x3000000>; */ + /* smmu */ + #size-cells = <2>; + iommus = <&smmu0 EIC7700_SID_EMMC0>; + tbus = ; + dma-ranges = <0x0 0x00000000 0x0 0xc0000000 0x1 0x0>; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x1038>; + status = "disabled"; + numa-node-id = <0>; + }; + + sdio0: mmc@0x50460000{ + compatible = "eswin,sdhci-sdio"; + reg = <0x0 0x50460000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <81>; + clocks =<&d0_clock EIC7700_CLK_HSP_MSHC1_CORE_CLK>, + <&d0_clock EIC7700_CLK_HSP_CFG_CLK>, + <&d0_clock EIC7700_SPLL2_FOUT3>, + <&d0_clock EIC7700_MUX_U_MSHCORE_ROOT_3MUX1_1>; + clock-names ="clk_xin","clk_ahb","clk_spll2_fout3","clk_mux1_1"; + clock-output-names = "sdio0_cardclock"; + #clock-cells = <0>; + resets = <&d0_reset HSPDMA_RST_CTRL SW_MSHC1_TXRX_RSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_MSHC1_PHY_RSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_HSP_SD0_PRSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_HSP_SD0_ARSTN>; + reset-names = "txrx_rst","phy_rst","prstn","arstn"; + + core-clk-reg = <0x51828164>; + clock-frequency = <208000000>; + max-frequency = <208000000>; + #size-cells = <2>; + dma-ranges = <0x0 0x20000000 0x0 0xc0000000 0x0 0x40000000>; + iommus = <&smmu0 EIC7700_SID_SD0>; + tbus = ; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x103c>; + bus-width = <4>; + sdio-id = <0>; + numa-node-id = <0>; + status = "disabled"; + }; + + sdio1: mmc@0x50470000{ + compatible = "eswin,sdhci-sdio"; + reg = <0x0 0x50470000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <83>; + clocks =<&d0_clock EIC7700_CLK_HSP_MSHC2_CORE_CLK>, + <&d0_clock EIC7700_CLK_HSP_CFG_CLK>, + <&d0_clock EIC7700_SPLL2_FOUT3>, + <&d0_clock EIC7700_MUX_U_MSHCORE_ROOT_3MUX1_1>; + clock-names ="clk_xin","clk_ahb","clk_spll2_fout3","clk_mux1_1"; + clock-output-names = "sdio1_cardclock"; + #clock-cells = <0>; + resets = <&d0_reset HSPDMA_RST_CTRL SW_MSHC2_TXRX_RSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_MSHC2_PHY_RSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_HSP_SD1_PRSTN>, + <&d0_reset HSPDMA_RST_CTRL SW_HSP_SD1_ARSTN>; + reset-names = "txrx_rst","phy_rst","prstn","arstn"; + + core-clk-reg = <0x51828168>; + clock-frequency = <208000000>; + max-frequency = <208000000>; + #size-cells = <2>; + dma-ranges = <0x0 0x20000000 0x0 0xc0000000 0x0 0x40000000>; + iommus = <&smmu0 EIC7700_SID_SD1>; + tbus = ; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x1040>; + bus-width = <4>; + sdio-id = <1>; + numa-node-id = <0>; + status = "disabled"; + }; + + vdec0: video-decoder0@50100000 { + compatible = "eswin,video-decoder0"; + clocks = <&d0_clock EIC7700_CLK_VC_ACLK>, + <&d0_clock EIC7700_CLK_VC_CFG_CLK>, + <&d0_clock EIC7700_CLK_VC_JD_CLK>, + <&d0_clock EIC7700_CLK_VC_VD_CLK>, + <&d0_clock EIC7700_MUX_U_VCACLK_ROOT_2MUX1_GFREE>, + <&d0_clock EIC7700_SPLL0_FOUT1>, + <&d0_clock EIC7700_SPLL2_FOUT1>, + <&d0_clock EIC7700_CLK_VC_JD_PCLK>, + <&d0_clock EIC7700_CLK_VC_VD_PCLK>, + <&d0_clock EIC7700_CLK_VC_MON_PCLK>; + clock-names = "aclk", "cfg_clk", "jd_clk", "vd_clk", "vc_mux", "spll0_fout1", "spll2_fout1", "jd_pclk", "vd_pclk", "mon_pclk"; + resets = <&d0_reset VC_RST_CTRL SW_VC_AXI_RSTN>, + <&d0_reset VC_RST_CTRL SW_VC_CFG_RSTN>, + <&d0_reset VC_RST_CTRL SW_VC_MONCFG_RSTN>, + <&d0_reset JD_RST_CTRL SW_JD_CFG_RSTN>, + <&d0_reset JD_RST_CTRL SW_JD_AXI_RSTN>, + <&d0_reset VD_RST_CTRL SW_VD_CFG_RSTN>, + <&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>; + + vcmd-core = <0 0x6c>; + axife-core = <0x200 0x100>; + vdec-core = <0x800 0xc00>; + interrupt-parent = <&plic0>; + #size-cells = <2>; + dma-ranges = <0x0 0x0 0x0 0x80000000 0x200 0x0>; + //iommus = <&smmu0 EIC7700_SID_VDEC>; + vccsr-reg = <0x0 0x501c0000 0x0 0x1000>; + numa-node-id = <0>; + tbus = , ; + + vdec_0: vdec0@50100000 { + core-name = "video-dec0"; + base-addr = <0x50100000>; + interrupts = <236>; + }; + + jdec_0: jdec0@50120000 { + core-name = "jpeg-dec0"; + base-addr = <0x50120000>; + interrupts = <237>; + }; + }; + + venc0: video-encoder@50110000 { + compatible = "eswin,video-encoder0"; + clocks = <&d0_clock EIC7700_CLK_VC_ACLK>, + <&d0_clock EIC7700_CLK_VC_CFG_CLK>, + <&d0_clock EIC7700_CLK_VC_JE_CLK>, + <&d0_clock EIC7700_CLK_VC_VE_CLK>, + <&d0_clock EIC7700_MUX_U_VCACLK_ROOT_2MUX1_GFREE>, + <&d0_clock EIC7700_SPLL0_FOUT1>, + <&d0_clock EIC7700_SPLL2_FOUT1>, + <&d0_clock EIC7700_CLK_VC_JE_PCLK>, + <&d0_clock EIC7700_CLK_VC_VE_PCLK>, + <&d0_clock EIC7700_CLK_VC_MON_PCLK>; + clock-names = "aclk", "cfg_clk", "je_clk", "ve_clk", "vc_mux", "spll0_fout1", "spll2_fout1", "je_pclk", "ve_pclk", "mon_pclk"; + resets = <&d0_reset VC_RST_CTRL SW_VC_AXI_RSTN>, + <&d0_reset VC_RST_CTRL SW_VC_CFG_RSTN>, + <&d0_reset VC_RST_CTRL SW_VC_MONCFG_RSTN>, + <&d0_reset JE_RST_CTRL SW_JE_CFG_RSTN>, + <&d0_reset JE_RST_CTRL SW_JE_AXI_RSTN>, + <&d0_reset VE_RST_CTRL SW_VE_CFG_RSTN>, + <&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>; + + vcmd-core = <0 0x6c>; + axife-core = <0x2000 0x7d0>; + venc-core = <0x1000 0x87c>; + interrupt-parent = <&plic0>; + #size-cells = <2>; + dma-ranges = <0x0 0x0 0x0 0x80000000 0x200 0x0>; + //iommus = <&smmu0 EIC7700_SID_VENC>; + vccsr-reg = <0x0 0x501c0000 0x0 0x1000>; + numa-node-id = <0>; + tbus = , ; + + venc_0: venc0@50110000 { + core-name = "video-enc0"; + base-addr = <0x50110000>; + interrupts = <229>; + }; + + jenc_0: jenc0@50130000 { + core-name = "jpeg-enc0"; + base-addr = <0x50130000>; + interrupts = <232>; + }; + }; + + /*mailbox between u84 & scpu*/ + d0_mbox0: mbox@50a00000 { + compatible = "eswin,eic7700-mailbox"; + reg = <0 ESWIN_MAILBOX_U84_TO_SCPU_REG_BASE 0 0x10000>, + <0 ESWIN_MAILBOX_SCPU_TO_U84_REG_BASE 0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <117>; + #mbox-cells = <1>; + clocks = <&d0_clock EIC7700_CLK_MAILBOX_0>, + <&d0_clock EIC7700_CLK_MAILBOX_1>; + clock-names = "pclk_mailbox_host", "pclk_mailbox_device"; + resets = <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_0>, + <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_1>; + reset-names = "rst", "rst_device"; + lock-bit = ; + irq-bit = ; + }; + + /*mailbox between u84 & lpcpu*/ + d0_mbox1: mbox@50a20000 { + compatible = "eswin,eic7700-mailbox"; + reg = <0 ESWIN_MAILBOX_U84_TO_LPCPU_REG_BASE 0 0x10000>, + <0 ESWIN_MAILBOX_LPCPU_TO_U84_REG_BASE 0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <119>; + #mbox-cells = <1>; + clocks = <&d0_clock EIC7700_CLK_MAILBOX_2>, + <&d0_clock EIC7700_CLK_MAILBOX_3>; + clock-names = "pclk_mailbox_host", "pclk_mailbox_device"; + resets = <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_2>, + <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_3>; + reset-names = "rst", "rst_device"; + lock-bit = ; + irq-bit = ; + }; + + /*mailbox between u84 & npu_0*/ + d0_mbox2: mbox@50a40000 { + compatible = "eswin,npu0-mailbox"; + reg = <0 ESWIN_MAILBOX_U84_TO_NPU_0_REG_BASE 0 0x10000>, + <0 ESWIN_MAILBOX_NPU_0_TO_U84_REG_BASE 0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <121>; + #mbox-cells = <1>; + clocks = <&d0_clock EIC7700_CLK_MAILBOX_4>, + <&d0_clock EIC7700_CLK_MAILBOX_5>; + clock-names = "pclk_mailbox_host", "pclk_mailbox_device"; + resets = <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_4>, + <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_5>; + reset-names = "rst", "rst_device"; + lock-bit = ; + irq-bit = ; + }; + + /*mailbox between u84 & npu_1*/ + d0_mbox3: mbox@50a60000 { + compatible = "eswin,eic7700-mailbox"; + reg = <0 ESWIN_MAILBOX_U84_TO_NPU_1_REG_BASE 0 0x10000>, + <0 ESWIN_MAILBOX_NP1_0_TO_U84_REG_BASE 0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <123>; + #mbox-cells = <1>; + clocks = <&d0_clock EIC7700_CLK_MAILBOX_6>, + <&d0_clock EIC7700_CLK_MAILBOX_7>; + clock-names = "pclk_mailbox_host", "pclk_mailbox_device"; + resets = <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_6>, + <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_7>; + reset-names = "rst", "rst_device"; + lock-bit = ; + irq-bit = ; + }; + + /*mailbox between u84 & dsp_0*/ + d0_mbox4: mbox@50a80000 { + compatible = "eswin,dsp0-mailbox"; + reg = <0 ESWIN_MAILBOX_U84_TO_DSP_0_REG_BASE 0 0x10000>, + <0 ESWIN_MAILBOX_DSP_0_TO_U84_REG_BASE 0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <125>; + #mbox-cells = <1>; + clocks = <&d0_clock EIC7700_CLK_MAILBOX_8>, + <&d0_clock EIC7700_CLK_MAILBOX_9>; + clock-names = "pclk_mailbox_host", "pclk_mailbox_device"; + resets = <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_8>, + <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_9>; + reset-names = "rst", "rst_device"; + lock-bit = ; + irq-bit = ; + }; + + /*mailbox between u84 & dsp_1*/ + d0_mbox5: mbox@50aa0000 { + compatible = "eswin,dsp1-mailbox"; + reg = <0 ESWIN_MAILBOX_U84_TO_DSP_1_REG_BASE 0 0x10000>, + <0 ESWIN_MAILBOX_DSP_1_TO_U84_REG_BASE 0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <127>; + #mbox-cells = <1>; + clocks = <&d0_clock EIC7700_CLK_MAILBOX_10>, + <&d0_clock EIC7700_CLK_MAILBOX_11>; + clock-names = "pclk_mailbox_host", "pclk_mailbox_device"; + resets = <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_10>, + <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_11>; + reset-names = "rst", "rst_device"; + lock-bit = ; + irq-bit = ; + }; + + /*mailbox between u84 & dsp_2*/ + d0_mbox6: mbox@50ac0000 { + compatible = "eswin,dsp2-mailbox"; + reg = <0 ESWIN_MAILBOX_U84_TO_DSP_2_REG_BASE 0 0x10000>, + <0 ESWIN_MAILBOX_DSP_2_TO_U84_REG_BASE 0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <129>; + #mbox-cells = <1>; + clocks = <&d0_clock EIC7700_CLK_MAILBOX_12>, + <&d0_clock EIC7700_CLK_MAILBOX_13>; + clock-names = "pclk_mailbox_host", "pclk_mailbox_device"; + resets = <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_12>, + <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_13>; + reset-names = "rst", "rst_device"; + lock-bit = ; + irq-bit = ; + }; + + /*mailbox between u84 & dsp_3*/ + d0_mbox7: mbox@50ae0000 { + compatible = "eswin,dsp3-mailbox"; + reg = <0 ESWIN_MAILBOX_U84_TO_DSP_3_REG_BASE 0 0x10000>, + <0 ESWIN_MAILBOX_DSP_3_TO_U84_REG_BASE 0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <131>; + #mbox-cells = <1>; + clocks = <&d0_clock EIC7700_CLK_MAILBOX_14>, + <&d0_clock EIC7700_CLK_MAILBOX_15>; + clock-names = "pclk_mailbox_host", "pclk_mailbox_device"; + resets = <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_14>, + <&d0_reset MBOX_RST_CTRL SW_MBOX_RST_N_15>; + reset-names = "rst", "rst_device"; + lock-bit = ; + irq-bit = ; + }; + + d0_ipc_scpu:ipc@0 { + compatible = "eswin,eic7700-ipc"; + #size-cells = <2>; + dma-ranges = <0x0 0x80000000 0x0 0xc0000000 0x0 0x80000000>; + iommus = <&smmu0 EIC7700_SID_SCPU>; + tbus = ; + eswin,syscfg = <&d0_sys_con SCPU_SID_REG_OFFSET 0>, + <&d0_sys_con CRYPT_SID_REG_OFFSET 0>; + mboxes = <&d0_mbox0 0>; + mbox-names = "u84_scpu"; + numa-node-id = <0>; + }; + + d0_lpcpu:lpcpu@0 { + compatible = "eswin,eic7700-lpcpu"; + fw-region = <&lpcpu0_reserved>; + clocks = <&d0_clock EIC7700_CLK_CLK_LPCPU_CORE>, + <&d0_clock EIC7700_CLK_CLK_LPCPU_BUS>; + clock-names = "core_clk", "bus_clk"; + + reset-names = "core_rst", "bus_rst", "dbg_rst"; + resets = <&d0_reset LPCPU_RST_CTRL SW_LPCPU_CORE_RSTN>, + <&d0_reset LPCPU_RST_CTRL SW_LPCPU_BUS_RSTN>, + <&d0_reset LPCPU_RST_CTRL SW_LPCPU_DBG_RSTN>; + #size-cells = <2>; + + dma-ranges = <0x0 0xb0000000 0x0 0xc0000000 0x0 0x50000000>; + iommus = <&smmu0 EIC7700_SID_LCPU>; + eswin,syscfg = <&d0_sys_con LCPU_SID_REG_OFFSET 0>; + tbus = ; + mboxes = <&d0_mbox1 0>; + mbox-names = "u84_lpcpu"; + numa-node-id = <0>; + status = "disabled"; + }; + + pvt0: pvt@0x50b00000 { + compatible = "eswin,eswin-pvt"; + clocks = <&d0_clock EIC7700_CLK_PVT_CLK_0>; + clock-names = "pvt_clk"; + resets = <&d0_reset PVT_RST_CTRL SW_PVT_RST_N_0>; + reset-names = "pvt_rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x50b00000 0x0 0x10000>; + interrupts = <349>; + interrupt-parent = <&plic0>; + status = "disabled"; + }; + pvt1: pvt@0x52360000 { + compatible = "eswin,eswin-pvt"; + clocks = <&d0_clock EIC7700_CLK_PVT_CLK_1>; + clock-names = "pvt_clk"; + resets = <&d0_reset PVT_RST_CTRL SW_PVT_RST_N_1>; + reset-names = "pvt_rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x52360000 0x0 0x20000>; + interrupts = <350>; + interrupt-parent = <&plic0>; + status = "disabled"; + }; + + fan_control: fan_control@50b50000 { + compatible = "eswin-fan-control"; + reg = <0x0 0x50b50000 0x0 0x10000>; + clocks = <&d0_clock EIC7700_CLK_LSP_FAN_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset FAN_RST_CTRL SW_FAN_RST_N>; + reset-names = "fan_rst"; + interrupt-parent = <&plic0>; + interrupt-names = "fanirq"; + interrupts = <354>; + pulses-per-revolution = <2>; + pwm-minimum-period = <1000>; + pwms = <&pwm0 0 100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fan_tach_default>; + status = "disabled"; + }; + + d0_i2c0: i2c@50950000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_LSP_I2C0_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C_RST_CTRL SW_I2C_RST_N_0>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x50950000 0x0 0x8000>; + interrupts = <105>; + interrupt-parent = <&plic0>; + }; + d0_i2c1: i2c@50960000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_LSP_I2C1_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C_RST_CTRL SW_I2C_RST_N_1>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x50960000 0x0 0x10000>; + interrupts = <106>; + interrupt-parent = <&plic0>; + }; + d0_i2c2: i2c@50970000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_LSP_I2C2_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C_RST_CTRL SW_I2C_RST_N_2>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x50970000 0x0 0x8000>; + interrupts = <107>; + interrupt-parent = <&plic0>; + }; + d0_i2c3: i2c@50980000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_LSP_I2C3_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C_RST_CTRL SW_I2C_RST_N_3>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x50980000 0x0 0x8000>; + interrupts = <108>; + interrupt-parent = <&plic0>; + }; + d0_i2c4: i2c@50990000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_LSP_I2C4_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C_RST_CTRL SW_I2C_RST_N_4>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x50990000 0x0 0x8000>; + interrupts = <109>; + interrupt-parent = <&plic0>; + }; + d0_i2c5: i2c@509a0000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_LSP_I2C5_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C_RST_CTRL SW_I2C_RST_N_5>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x509a0000 0x0 0x8000>; + interrupts = <110>; + interrupt-parent = <&plic0>; + }; + d0_i2c6: i2c@509b0000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_LSP_I2C6_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C_RST_CTRL SW_I2C_RST_N_6>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x509b0000 0x0 0x8000>; + interrupts = <111>; + interrupt-parent = <&plic0>; + }; + d0_i2c7: i2c@509c0000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_LSP_I2C7_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C_RST_CTRL SW_I2C_RST_N_7>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x509c0000 0x0 0x8000>; + interrupts = <112>; + interrupt-parent = <&plic0>; + }; + d0_i2c8: i2c@509d0000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_LSP_I2C8_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C_RST_CTRL SW_I2C_RST_N_8>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x509d0000 0x0 0x8000>; + interrupts = <113>; + interrupt-parent = <&plic0>; + }; + d0_i2c9: i2c@509e0000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_LSP_I2C9_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C_RST_CTRL SW_I2C_RST_N_9>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x509e0000 0x0 0x8000>; + interrupts = <114>; + interrupt-parent = <&plic0>; + }; + d0_aon_i2c0: i2c@51830000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_AON_I2C0_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C0_RST_CTRL SW_I2C0_PRSTN>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x51830000 0x0 0x8000>; + interrupts = <290>; + interrupt-parent = <&plic0>; + eswin,i2c_dma = <&d0_aon_dmac>; + dma-names = "rx", "tx"; + /* + * dmas : DMA specifiers + * &d0_aon_dmac : dma controller + * 41 : i2c0 aon dma handshake number + * 0xff : no need to select to dma controller + */ + dmas = <&d0_aon_dmac 41 0xff>, <&d0_aon_dmac 42 0xff>; + }; + d0_aon_i2c1: i2c@51838000 { + compatible = "snps,designware-i2c"; + clock-frequency = <100000>; + clocks = <&d0_clock EIC7700_CLK_AON_I2C1_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset I2C1_RST_CTRL SW_I2C1_PRSTN>; + reset-names = "rst"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x51838000 0x0 0x8000>; + interrupts = <291>; + interrupt-parent = <&plic0>; + }; + pinctrl: pinctrl@0x51600080 { + compatible = "eswin,eic7700-pinctrl"; + reg = <0x0 0x51600080 0x0 0x1FFF80>; + status = "disabled"; + }; + + gpio0: gpio@51600000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dw-apb-gpio"; + reg = <0x0 0x51600000 0x0 0x80>; + + porta: gpio-port@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <0>; + interrupt-parent = <&plic0>; + interrupts = <303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 + 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334>; + }; + + portb: gpio-port@1 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <1>; + }; + + portc: gpio-port@2 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + reg = <2>; + }; + + portd: gpio-port@3 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + reg = <3>; + }; + }; + + pwm0: pwm@0x50818000 { + compatible = "eswin,pwm-eswin"; + #pwm-cells = <2>; + reg = <0x0 0x50818000 0x0 0x4000>; + clock-names = "pwm","pclk"; + clocks = <&d0_clock EIC7700_CLK_LSP_TIMER_PCLK>; + clock-frequency = <200000000>; + resets = <&d0_reset TIMER_RST_CTRL SW_TIMER_RST_N>; + reset-names = "pwmrst"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm0_default>; + status = "disabled"; + }; + + wdt0: watchdog@0x50800000 { + compatible = "snps,dw-wdt"; + reg = <0x0 0x50800000 0x0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_LSP_WDT0_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset WDT_RST_CTRL SW_WDT_RST_N_0>; + reset-names = "rst"; + interrupts = <87>; + interrupt-parent = <&plic0>; + status = "disabled"; + }; + + wdt1: watchdog@0x50804000 { + compatible = "snps,dw-wdt"; + reg = <0x0 0x50804000 0x0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_LSP_WDT1_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset WDT_RST_CTRL SW_WDT_RST_N_1>; + reset-names = "rst"; + interrupts = <88>; + interrupt-parent = <&plic0>; + status = "disabled"; + }; + + wdt2: watchdog@0x50808000 { + compatible = "snps,dw-wdt"; + reg = <0x0 0x50808000 0x0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_LSP_WDT2_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset WDT_RST_CTRL SW_WDT_RST_N_2>; + reset-names = "rst"; + interrupts = <89>; + interrupt-parent = <&plic0>; + status = "disabled"; + }; + + wdt3: watchdog@0x5080c000 { + compatible = "snps,dw-wdt"; + reg = <0x0 0x5080c000 0x0 0x4000>; + clocks =<&d0_clock EIC7700_CLK_LSP_WDT3_PCLK>; + clock-names = "pclk"; + resets = <&d0_reset WDT_RST_CTRL SW_WDT_RST_N_3>; + reset-names = "rst"; + interrupts = <90>; + interrupt-parent = <&plic0>; + status = "disabled"; + }; + + timer0: timer@0x51840000 { + compatible = "eswin,eswin-timer"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0x51840000 0x0 0x8000>; + perf_count = <7>; + interrupt-parent = <&plic0>; + interrupts = <345>; + clock-names = "pclk","timer_aclk"; + clocks = <&d0_clock EIC7700_CLK_TIMER_PCLK_0>, + <&d0_clock EIC7700_CLK_TIMER_CLK_0>; + resets = <&d0_reset TIMER0_RST_CTRL SW_TIMER0_RSTN_0>, + <&d0_reset TIMER0_RST_CTRL SW_TIMER0_RSTN_1>, + <&d0_reset TIMER0_RST_CTRL SW_TIMER0_RSTN_2>, + <&d0_reset TIMER0_RST_CTRL SW_TIMER0_RSTN_3>, + <&d0_reset TIMER0_RST_CTRL SW_TIMER0_RSTN_4>, + <&d0_reset TIMER0_RST_CTRL SW_TIMER0_RSTN_5>, + <&d0_reset TIMER0_RST_CTRL SW_TIMER0_RSTN_6>, + <&d0_reset TIMER0_RST_CTRL SW_TIMER0_RSTN_7>, + <&d0_reset TIMER0_RST_CTRL SW_TIMER0_PRSTN>; + reset-names = "trst0","trst1","trst2","trst3","trst4","trst5","trst6","trst7","prst"; + }; + + timer1: timer@0x51848000 { + compatible = "eswin,eswin-timer"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0x51848000 0x0 0x8000>; + interrupt-parent = <&plic0>; + interrupts = <346>; + clock-names = "pclk","timer_aclk"; + clocks = <&d0_clock EIC7700_CLK_TIMER_PCLK_1>, + <&d0_clock EIC7700_CLK_TIMER_CLK_1>; + resets = <&d0_reset TIMER1_RST_CTRL SW_TIMER1_RSTN_0>, + <&d0_reset TIMER1_RST_CTRL SW_TIMER1_RSTN_1>, + <&d0_reset TIMER1_RST_CTRL SW_TIMER1_RSTN_2>, + <&d0_reset TIMER1_RST_CTRL SW_TIMER1_RSTN_3>, + <&d0_reset TIMER1_RST_CTRL SW_TIMER1_RSTN_4>, + <&d0_reset TIMER1_RST_CTRL SW_TIMER1_RSTN_5>, + <&d0_reset TIMER1_RST_CTRL SW_TIMER1_RSTN_6>, + <&d0_reset TIMER1_RST_CTRL SW_TIMER1_RSTN_7>, + <&d0_reset TIMER1_RST_CTRL SW_TIMER1_PRSTN>; + reset-names = "trst0","trst1","trst2","trst3","trst4","trst5","trst6","trst7","prst"; + }; + + timer2: timer@0x51850000 { + compatible = "eswin,eswin-timer"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0x51850000 0x0 0x8000>; + interrupt-parent = <&plic0>; + interrupts = <347>; + clock-names = "pclk","timer_aclk"; + clocks = <&d0_clock EIC7700_CLK_TIMER_PCLK_2>, + <&d0_clock EIC7700_CLK_TIMER_CLK_2>; + resets = <&d0_reset TIMER2_RST_CTRL SW_TIMER2_RSTN_0>, + <&d0_reset TIMER2_RST_CTRL SW_TIMER2_RSTN_1>, + <&d0_reset TIMER2_RST_CTRL SW_TIMER2_RSTN_2>, + <&d0_reset TIMER2_RST_CTRL SW_TIMER2_RSTN_3>, + <&d0_reset TIMER2_RST_CTRL SW_TIMER2_RSTN_4>, + <&d0_reset TIMER2_RST_CTRL SW_TIMER2_RSTN_5>, + <&d0_reset TIMER2_RST_CTRL SW_TIMER2_RSTN_6>, + <&d0_reset TIMER2_RST_CTRL SW_TIMER2_RSTN_7>, + <&d0_reset TIMER2_RST_CTRL SW_TIMER2_PRSTN>; + reset-names = "trst0","trst1","trst2","trst3","trst4","trst5","trst6","trst7","prst"; + }; + + timer3: timer@0x51858000 { + compatible = "eswin,eswin-timer"; + #address-cells = <2>; + #size-cells = <2>; + reg = <0x0 0x51858000 0x0 0x8000>; + interrupt-parent = <&plic0>; + interrupts = <348>; + clock-names = "pclk","timer_aclk","timer3_clk8"; + clocks = <&d0_clock EIC7700_CLK_TIMER_PCLK_3>, + <&d0_clock EIC7700_CLK_TIMER_CLK_3>, + <&d0_clock EIC7700_CLK_TIMER3_CLK8>; + resets = <&d0_reset TIMER3_RST_CTRL SW_TIMER3_RSTN_0>, + <&d0_reset TIMER3_RST_CTRL SW_TIMER3_RSTN_1>, + <&d0_reset TIMER3_RST_CTRL SW_TIMER3_RSTN_2>, + <&d0_reset TIMER3_RST_CTRL SW_TIMER3_RSTN_3>, + <&d0_reset TIMER3_RST_CTRL SW_TIMER3_RSTN_4>, + <&d0_reset TIMER3_RST_CTRL SW_TIMER3_RSTN_5>, + <&d0_reset TIMER3_RST_CTRL SW_TIMER3_RSTN_6>, + <&d0_reset TIMER3_RST_CTRL SW_TIMER3_RSTN_7>, + <&d0_reset TIMER3_RST_CTRL SW_TIMER3_PRSTN>; + reset-names = "trst0","trst1","trst2","trst3","trst4","trst5","trst6","trst7","prst"; + }; + + die0_rtc: rtc@51818000 { + compatible = "eswin,eic7700-rtc"; + reg = <0x0 0x51818000 0x0 0x400>; + eswin,syscfg = <&d0_sys_con 0x3c0>; + interrupt-parent = <&plic0>; + interrupts = <292>; + clocks = <&d0_clock EIC7700_CLK_CLK_RTC>; + clock-names = "rtcclk"; + clock-frequency = <15625>; + resets = <&d0_reset RTC_RST_CTRL SW_RTC_RSTN>; + reset-names = "rtcrst"; + status = "disabled"; + }; + + d0_i2s0: i2s0@50200000 { + compatible = "snps,i2s"; + clocks = <&d0_clock EIC7700_CLK_VO_I2S_MCLK>; + clock-names = "mclk"; + #address-cells = <1>; + #size-cells = <0>; + #sound-dai-cells = <0x00000000>; + reg = <0x0 0x50200000 0x0 0x10000>; + dma-names = "rx", "tx"; + dmas = <&d0_aon_dmac 4 0>, <&d0_aon_dmac 5 0>; + vo_mclk_sel,syscrg = <&d0_sys_crg 0x1bc>; + resets = <&d0_reset VO_I2SRST_CTRL SW_VO_I2S_RSTN>, + <&d0_reset VO_I2SRST_CTRL SW_VO_I2S_PRSTN>, + <&d0_reset VO_PHYRST_CTRL SW_VO_PRSTN>; + reset-names = "i2srst", "i2sprst", "voprst"; + }; + + d0_i2s1: i2s1@50210000 { + compatible = "snps,i2s"; + clocks = <&d0_clock EIC7700_CLK_VO_I2S_MCLK>; + clock-names = "mclk"; + #address-cells = <1>; + #size-cells = <0>; + #sound-dai-cells = <0x00000000>; + reg = <0x0 0x50210000 0x0 0x10000>; + dma-names = "rx", "tx"; + dmas = <&d0_aon_dmac 2 1>, <&d0_aon_dmac 3 1>; + vo_mclk_sel,syscrg = <&d0_sys_crg 0x1bc>; + resets = <&d0_reset VO_I2SRST_CTRL SW_VO_I2S_RSTN>, + <&d0_reset VO_I2SRST_CTRL SW_VO_I2S_PRSTN>, + <&d0_reset VO_PHYRST_CTRL SW_VO_PRSTN>; + reset-names = "i2srst", "i2sprst", "voprst"; + }; + + d0_i2s2: i2s2@50220000 { + compatible = "snps,i2s"; + clocks = <&d0_clock EIC7700_CLK_VO_I2S_MCLK>; + clock-names = "mclk"; + #address-cells = <1>; + #size-cells = <0>; + #sound-dai-cells = <0x00000000>; + reg = <0x0 0x50220000 0x0 0x10000>; + dma-names = "rx", "tx"; + dmas = <&d0_aon_dmac 0 2>, <&d0_aon_dmac 1 2>; + vo_mclk_sel,syscrg = <&d0_sys_crg 0x1bc>; + resets = <&d0_reset VO_I2SRST_CTRL SW_VO_I2S_RSTN>, + <&d0_reset VO_I2SRST_CTRL SW_VO_I2S_PRSTN>, + <&d0_reset VO_PHYRST_CTRL SW_VO_PRSTN>; + reset-names = "i2srst", "i2sprst", "voprst"; + }; + + d0_graphcard0: graphcard0 { + compatible = "audio-graph-card"; + }; + + d0_graphcard1: graphcard1 { + compatible = "audio-graph-card"; + }; + + d0_graphcard2: graphcard2 { + compatible = "audio-graph-card"; + }; + + video_output: display-subsystem { + compatible = "eswin,display-subsystem"; + ports = <&dc_out>; + }; + + dvb_widgets: dvb-subsystem { + compatible = "amlogic,dvb_widgets"; + status = "disabled"; + }; + + dc: display_control@502c0000 { + compatible = "eswin,dc"; + reg = <0x0 0x502c0000 0x0 0x100>, <0x0 0x502c0180 0x0 0x700>, <0x0 0x502c1400 0x0 0x1400>; + interrupt-parent = <&plic0>; + interrupts = <238>; + + clocks = <&d0_clock EIC7700_CLK_VO_CFG_CLK>, + <&d0_clock EIC7700_CLK_VO_PIXEL_CLK>, + <&d0_clock EIC7700_CLK_VO_ACLK>, + <&d0_clock EIC7700_SPLL0_FOUT1>, + <&d0_clock EIC7700_MUX_U_VO_ACLK_ROOT_2MUX1_GFREE>; + clock-names = "cfg_clk", "pix_clk", "axi_clk", "spll0_fout1", "vo_mux"; + 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>, + <&d0_reset VO_RST_CTRL SW_VO_DC_PRSTN>; + reset-names = "vo_arst", "vo_prst", "dc_arst", "dc_prst"; + + dc_out: port { + #address-cells = <1>; + #size-cells = <0>; + + dc_out_dpi0: endpoint@0 { + reg = <0>; + remote-endpoint = <&dsi_input0>; + }; + + dc_out_dpi1: endpoint@1 { + reg = <1>; + remote-endpoint = <&vd_input>; + }; + + dc_out_hdmi: endpoint@2 { + reg = <2>; + remote-endpoint = <&hdmi_in_dc>; + }; + }; + }; + + virtual_display: es_wb { + compatible = "eswin,virtual_display"; + bpp = /bits/ 8 <8>; + + port { + vd_input: endpoint { + remote-endpoint = <&dc_out_dpi1>; + }; + }; + }; + + dsi_output: dsi-output { + compatible = "eswin,dsi-encoder"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + /* input */ + port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + dsi_input0: endpoint@0 { + reg = <0>; + remote-endpoint = <&dc_out_dpi0>; + }; + }; + + /* output */ + port@1 { + reg = <1>; + dsi_out:endpoint { + remote-endpoint = <&mipi_dsi_in>; + }; + }; + }; + }; + + dsi_controller: mipi_dsi@50270000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "eswin,dw-mipi-dsi"; + reg = <0x0 0x50270000 0x0 0x10000>; + clocks = <&d0_clock EIC7700_CLK_CLK_MIPI_TXESC>; + clock-names = "pclk"; + resets = <&d0_reset VO_PHYRST_CTRL SW_VO_MIPI_PRSTN>; + reset-names ="phyrstn"; + /* + phys = <&dphy>; + phy-names = "dphy"; + */ + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + mipi_dsi_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + + port@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + mipi_dsi_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; + + dsi_panel:dsi_panel@0 { + compatible = "eswin,generic-panel"; + reg = <0>; + + port { + panel_in: endpoint { + remote-endpoint = <&mipi_dsi_out>; + }; + }; + }; + }; + + dc_test: dctest@502c0000 { + compatible = "eswin,dc"; + reg = <0x0 0x502c0000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <238>; + }; + + dw_hdmi: hdmi@502a0000 { + compatible = "eswin,eswin-dw-hdmi"; + reg = <0x0 0x502a0000 0x0 0x20000>; + pinctrl-names = "default"; + //pinctrl-0 = <&hdmi_i2c_xfer>; + interrupt-parent = <&plic0>; + interrupts = <274>; + clocks = <&d0_clock EIC7700_CLK_VO_CFG_CLK>, <&d0_clock EIC7700_CLK_VO_PIXEL_CLK>, + <&d0_clock EIC7700_CLK_VO_CEC_CLK>, <&d0_clock EIC7700_CLK_VO_CR_CLK>; + clock-names = "iahb", "vpll", "cec", "isfr"; + //power-domains = <&power EIC7700_PD_HDCP>; + reg-io-width = <4>; + ddc-i2c-scl-high-time-ns = <4708>; + ddc-i2c-scl-low-time-ns = <4916>; + #sound-dai-cells = <0>; + resets = <&d0_reset VO_PHYRST_CTRL SW_VO_HDMI_PRSTN>, + <&d0_reset VO_PHYRST_CTRL SW_HDMI_PHYCTRL_RSTN>, + <&d0_reset VO_PHYRST_CTRL SW_VO_HDMI_RSTN>; + reset-names = "prstn", "phyrstn", "rstn"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + hdmi_in_dc: endpoint@0 { + remote-endpoint = <&dc_out_hdmi>; + }; + }; + }; + }; + + dw_hdmi_hdcp2: hdmi-hdcp2@50290000 { + compatible = "eswin,dw-hdmi-hdcp2"; + reg = <0x0 0x50290000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <275>; + clocks = <&d0_clock EIC7700_CLK_VO_CFG_CLK>, + <&d0_clock EIC7700_CLK_VO_HDMI_IESMCLK>; + clock-names ="pclk_hdcp2", "hdcp2_clk_hdmi"; + }; + + d0_usbdrd3_0: usb0@50480000 { + compatible = "eswin,eic7700-dwc3"; + #address-cells = <2>; + #size-cells = <2>; + clocks =<&d0_clock EIC7700_GATE_HSP_USB0_SUSPEND_CLK>; + clock-names = "suspend"; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x800 0x808 0x83c 0x840>; + resets = <&d0_reset HSPDMA_RST_CTRL SW_USB0_VAUX_RSTN>; + reset-names = "vaux"; + ranges; + status = "disabled"; + d0_usbdrd_dwc3_0: dwc3@50480000 { + compatible = "snps,dwc3"; + reg = <0x0 0x50480000 0x0 0x10000>; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&plic0>; + interrupts = <85>; + interrupt-names = "peripheral"; + dr_mode = "peripheral"; + phy_type = "utmi"; + maximum-speed = "high-speed"; + iommus = <&smmu0 EIC7700_SID_USB0>; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x1044>; + dma-ranges = <0x0 0x0 0x0 0xc0000000 0x200 0x0>; + snps,dis_enblslpm_quirk; + snps,dis-u2-freeclk-exists-quirk; + snps,dis_u2_susphy_quirk; + snps,dis-del-phy-power-chg-quirk; + snps,tx-ipgap-linecheck-dis-quirk; + snps,xhci-slow-suspend-quirk; + snps,xhci-trb-ent-quirk; + snps,usb3-warm-reset-on-resume-quirk; + status = "disabled"; + numa-node-id = <0>; + tbus = ; + }; + }; + + d0_usbdrd3_1: usb1@50490000 { + compatible = "eswin,eic7700-dwc3"; + #address-cells = <2>; + #size-cells = <2>; + clocks =<&d0_clock EIC7700_GATE_HSP_USB1_SUSPEND_CLK>; + clock-names = "suspend"; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x900 0x908 0x93c 0x940>; + resets = <&d0_reset HSPDMA_RST_CTRL SW_USB1_VAUX_RSTN>; + reset-names = "vaux"; + ranges; + status = "disabled"; + d0_usbdrd_dwc3_1: dwc3@50490000 { + compatible = "snps,dwc3"; + reg = <0x0 0x50490000 0x0 0x10000>; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&plic0>; + interrupts = <86>; + interrupt-names = "host"; + dr_mode = "host"; + phy_type = "utmi"; + maximum-speed = "high-speed"; + iommus = <&smmu0 EIC7700_SID_USB1>; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x1048>; + dma-ranges = <0x0 0x0 0x0 0xc0000000 0x200 0x0>; + snps,dis_enblslpm_quirk; + snps,dis-u2-freeclk-exists-quirk; + snps,dis_u2_susphy_quirk; + snps,dis-del-phy-power-chg-quirk; + snps,tx-ipgap-linecheck-dis-quirk; + snps,xhci-slow-suspend-quirk; + snps,xhci-trb-ent-quirk; + snps,usb3-warm-reset-on-resume-quirk; + status = "disabled"; + numa-node-id = <0>; + tbus = ; + }; + }; + + vi_top_csr: vi_common_top_csr@0x51030000 { + compatible = "esw,vi-common-csr", "syscon"; + clocks = <&d0_clock EIC7700_CLK_VI_ACLK>, + <&d0_clock EIC7700_CLK_VI_CFG_CLK>, + <&d0_clock EIC7700_CLK_VI_DIG_ISP_CLK>, + <&d0_clock EIC7700_CLK_VI_DVP_CLK>, + <&d0_clock EIC7700_CLK_VI_PHY_CFG>, + <&d0_clock EIC7700_CLK_VI_PHY_TXCLKESC>, + <&d0_clock EIC7700_CLK_VI_SHUTTER_0>, + <&d0_clock EIC7700_CLK_VI_SHUTTER_1>, + <&d0_clock EIC7700_CLK_VI_SHUTTER_2>, + <&d0_clock EIC7700_CLK_VI_SHUTTER_3>, + <&d0_clock EIC7700_CLK_VI_SHUTTER_4>, + <&d0_clock EIC7700_CLK_VI_SHUTTER_5>, + <&d0_clock EIC7700_MUX_U_VI_ACLK_ROOT_2MUX1_GFREE>, + <&d0_clock EIC7700_MUX_U_VI_DVP_ROOT_2MUX1_GFREE>, + <&d0_clock EIC7700_MUX_U_VI_DIG_ISP_ROOT_2MUX1_GFREE>, + <&d0_clock EIC7700_SPLL0_FOUT1>, + <&d0_clock EIC7700_VPLL_FOUT1>; + clock-names = "aclk", "cfg_clk", "isp_aclk", "dvp_clk", "phy_cfg", + "phy_escclk", "sht0", "sht1", "sht2", "sht3", "sht4", + "sht5", "aclk_mux", "dvp_mux", "isp_mux", "spll0_fout1", "vpll_fout1"; + resets = <&d0_reset VI_RST_CTRL SW_VI_AXI_RSTN>, + <&d0_reset VI_RST_CTRL SW_VI_CFG_RSTN>, + <&d0_reset ISP0_RST_CTRL SW_VI_ISP0_RSTN>, + <&d0_reset ISP1_RST_CTRL SW_VI_ISP1_RSTN>, + <&d0_reset DVP_RST_CTRL SW_VI_DVP_RSTN>, + <&d0_reset SHUTTER_RST_CTRL SW_VI_SHUTTER_RSTN_0>, + <&d0_reset SHUTTER_RST_CTRL SW_VI_SHUTTER_RSTN_1>, + <&d0_reset SHUTTER_RST_CTRL SW_VI_SHUTTER_RSTN_2>, + <&d0_reset SHUTTER_RST_CTRL SW_VI_SHUTTER_RSTN_3>, + <&d0_reset SHUTTER_RST_CTRL SW_VI_SHUTTER_RSTN_4>, + <&d0_reset SHUTTER_RST_CTRL SW_VI_SHUTTER_RSTN_5>; + reset-names = "axi", "cfg", "isp0", "isp1", "dvp", "sht0", "sht1", "sht2", "sht3", "sht4", "sht5"; + + id = <0>; + #size-cells = <2>; + reg = <0x0 0x51030000 0x0 0x10000>; + }; + + isp_0: isp@0x51000000 { + compatible = "esw,eic7700-isp"; + + reg = <0x0 0x51000000 0x0 0x10000>; + interrupts = <21 19 20>; + interrupt-parent = <&plic0>; + id = <0>; + #size-cells = <2>; + dma-ranges = <0x0 0x20000000 0x0 0x80000000 0x0 0x40000000>; + iommus = <&smmu0 EIC7700_SID_ISP0>; + tbus = ; + eswin,vi_top_csr = <&vi_top_csr 0x1000>; + numa-node-id = <0>; + }; + + isp_1: isp@0x51010000 { + compatible = "esw,eic7700-isp"; + + reg = <0x0 0x51010000 0x0 0x10000>; + interrupts = <24 22 23>; + interrupt-parent = <&plic0>; + id = <1>; + #size-cells = <2>; + dma-ranges = <0x0 0x20000000 0x0 0x80000000 0x0 0x40000000>; + //iommus = <&smmu0 EIC7700_SID_ISP1>; + tbus = ; + eswin,vi_top_csr = <&vi_top_csr 0x1004>; + numa-node-id = <0>; + }; + + dewarp: dewarp@51020000 { + compatible = "eswin,dewarp"; + clocks = <&d0_clock EIC7700_CLK_VI_ACLK>, + <&d0_clock EIC7700_CLK_VI_CFG_CLK>, + <&d0_clock EIC7700_CLK_VI_DIG_DW_CLK>, + <&d0_clock EIC7700_MUX_U_VI_ACLK_ROOT_2MUX1_GFREE>, + <&d0_clock EIC7700_MUX_U_VI_DW_ROOT_2MUX1>, + <&d0_clock EIC7700_SPLL0_FOUT1>, + <&d0_clock EIC7700_VPLL_FOUT1>; + clock-names = "aclk", "cfg_clk", "dw_aclk", "aclk_mux", "dw_mux", "spll0_fout1", "vpll_fout1"; + resets = <&d0_reset VI_RST_CTRL SW_VI_AXI_RSTN>, + <&d0_reset VI_RST_CTRL SW_VI_CFG_RSTN>, + <&d0_reset VI_RST_CTRL SW_VI_DWE_RSTN>; + reset-names = "axi", "cfg", "dwe"; + + interrupt-parent = <&plic0>; + interrupts = <26 25>; + #size-cells = <2>; + dma-ranges = <0x0 0x20000000 0x0 0x80000000 0x0 0x40000000>; + iommus = <&smmu0 EIC7700_SID_DW>; + tbus = ; + eswin,vi_top_csr = <&vi_top_csr 0x1008>; + reg = <0x0 0x51020000 0x0 0xc00>, <0x0 0x51020c00 0x0 0x120>; + numa-node-id = <0>; + }; + + mipi_dphy_rx: dphy@510c0000 { + compatible = "snps,dw-dphy-rx"; + #phy-cells = <1>; + bus-width = <8>; + snps,dphy-frequency = <300000>; + snps,phy_type = <8>; + reg = <0x0 0x510c0000 0x0 0x20000>; + numa-node-id = <0>; + }; + + csi_dma0: csidma@0x52048000 { + compatible = "eswin,csi-video"; + interrupt-parent = <&plic0>; + interrupts = <29>; + reg = <0x0 0x52048000 0x0 0x1000>; + numa-node-id = <0>; + + port { + #address-cells = <1>; + #size-cells = <0>; + + csi_dmar_0: endpoint@0 { + reg = <0>; + bus-type = <4>; + remote-endpoint = <&csi2_dma_0_3>; + }; + }; + }; + + csi_dma1: csidma@0x52058000 { + compatible = "eswin,csi-video"; + interrupt-parent = <&plic0>; + interrupts = <30>; + reg = <0x0 0x52058000 0x0 0x1000>; + numa-node-id = <0>; + + port { + #address-cells = <1>; + #size-cells = <0>; + + csi_dmar_1: endpoint@0 { + reg = <0>; + bus-type = <4>; + remote-endpoint = <&csi2_dma_1_3>; + }; + }; + }; + + csi2_0: csi2@51050000 { + compatible = "snps,dw-csi"; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <&plic0>; + interrupts = <29>; + snps,output-type = <0>; + reg = <0x0 0x51050000 0x0 0x1000>; + /*phys = <&mipi_dphy_rx 1>;*/ + numa-node-id = <0>; + + /* MIPI CONFIG */ + snps,en-ppi-width = <0>;/* 0: ppi8, 1: ppi16 */ + snps,en-phy-mode = <0>;/* 0: D-PHY, 1: C-PHY */ + + ipi2_en = <0>;/* for virtual channel */ + ipi2_vcid = <0>;/* virtual channel id */ + ipi3_en = <0>; + ipi3_vcid = <0>; + + #ifdef MIPI_CSI2_IMX290_ENBALE + port@1 { + reg = <1>; + csi2_0_1: endpoint { + bus-type = <4>; + clock-lanes = <0>; + #ifdef MIPI_CSI2_2LINE_ENABLE + data-lanes = <1 2>; + #else + data-lanes = <1 2 3 4>; + #endif + //remote-endpoint = <&imx290_csi2>; + }; + }; + #endif + + port@2 { + reg = <2>; + csi2_dma_0_3: endpoint { + bus-type = <5>; + remote-endpoint = <&csi_dmar_0>; + }; + }; + }; + + csi2_1: csi2@51060000 { + compatible = "snps,dw-csi"; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <&plic0>; + interrupts = <30>; + snps,output-type = <0>; + reg = <0x0 0x51060000 0x0 0x1000>; + /*phys = <&mipi_dphy_rx 1>;*/ + numa-node-id = <0>; + + /* MIPI CONFIG */ + snps,en-ppi-width = <0>;/* 0: ppi8, 1: ppi16 */ + snps,en-phy-mode = <0>;/* 0: D-PHY, 1: C-PHY */ + + ipi2_en = <0>;/* for virtual channel */ + ipi2_vcid = <0>;/* virtual channel id */ + ipi3_en = <0>; + ipi3_vcid = <0>; + + #ifdef MIPI_CSI2_IMX290_ENBALE + port@1 { + reg = <1>; + csi2_1_1: endpoint { + bus-type = <4>; + clock-lanes = <0>; + #ifdef MIPI_CSI2_2LINE_ENABLE + data-lanes = <1 2>; + #else + data-lanes = <1 2 3 4>; + #endif + //remote-endpoint = <&imx290_csi2>; + }; + }; + #endif + + port@2 { + reg = <2>; + csi2_dma_1_3: endpoint { + bus-type = <5>; + remote-endpoint = <&csi_dmar_1>; + }; + }; + }; + + dc_test: dctest@502c0000 { + compatible = "eswin,dc"; + reg = <0x0 0x502c0000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupts = <238>; + }; + + ddr0: ddr-controller@0 { + compatible = "eswin,ddrc-1.20a"; + interrupt-parent = <&plic0>; + interrupts = <10>; + interrupt-names = "ddr-ecc"; + reg = <0x0 0x52300000 0x0 0x40000>; + ctrl-id = <0>; + status = "disabled"; + }; + + ddr1: ddr-controller@1 { + compatible = "eswin,ddrc-1.20a"; + interrupt-parent = <&plic0>; + interrupts = <299>; + interrupt-names = "ddr-ecc"; + reg = <0x0 0x52380000 0x0 0x40000>; + ctrl-id = <1>; + status = "disabled"; + }; +}; diff --git a/arch/riscv/boot/dts/eswin/hifive-premier-p550-pinctrl.dtsi b/arch/riscv/boot/dts/eswin/hifive-premier-p550-pinctrl.dtsi new file mode 100644 index 0000000000000..9b0e18db1d2be --- /dev/null +++ b/arch/riscv/boot/dts/eswin/hifive-premier-p550-pinctrl.dtsi @@ -0,0 +1,1339 @@ +#include "eic7700.dtsi" +#include + +/ { + #address-cells = <2>; + #size-cells = <2>; + soc { + pinctrl: pinctrl@0x51600080 { + compatible = "eswin,eic7700-pinctrl", "syscon"; + reg = <0x0 0x51600080 0x0 0x1FFF80>; + status = "disabled"; + //func0 + pinctrl_sdio0_default: sdio0-default{ + mux { + groups = "sdio0_group"; + function = "sdio0_func"; + }; + }; + pinctrl_sdio1_default: sdio1-default{ + mux { + groups = "sdio1_group"; + function = "sdio1_func"; + }; + }; + pinctrl_por_sel_default: por_sel-default{ + mux { + groups = "por_sel_group"; + function = "por_sel_func"; + }; + }; + pinctrl_jtag0_default: jtag0-default{ + mux { + groups = "jtag0_group"; + function = "jtag0_func"; + }; + }; + pinctrl_jtag1_default: jtag1-default{ + mux { + groups = "jtag1_group"; + function = "jtag1_func"; + }; + }; + pinctrl_jtag2_default: jtag2-default{ + mux { + groups = "jtag2_group"; + function = "jtag2_func"; + }; + }; + pinctrl_pcie_default: pcie-default{ + mux{ + groups = "pcie_group"; + function = "pcie_func"; + }; + }; + pinctrl_hdmi_default: hdmi-default{ + mux{ + groups = "hdmi_group"; + function = "hdmi_func"; + }; + }; + pinctrl_rgmii0_default: rgmii0-default{ + mux { + groups = "rgmii0_group"; + function = "rgmii0_func"; + }; + }; + pinctrl_rgmii1_default: rgmii1-default{ + mux{ + groups = "rgmii1_group"; + function = "rgmii1_func"; + }; + }; + pinctrl_spi0_default: spi0-default{ + mux { + groups = "spi0_group"; + function = "spi0_func"; + }; + }; + pinctrl_spi1_default: spi1-default{ + mux{ + groups = "spi1_group"; + function = "spi1_func"; + }; + }; + pinctrl_spi3_default: spi3-default{ + mux { + groups = "spi3_group"; + function = "spi3_func"; + }; + }; + pinctrl_por_time_sel0_default: por_time_sel0-default{ + mux { + groups = "por_time_sel0_group"; + function = "por_time_sel0_func"; + }; + }; + pinctrl_por_time_sel1_default: por_time_sel1-default{ + mux { + groups = "por_time_sel1_group"; + function = "por_time_sel1_func"; + }; + }; + pinctrl_i2s0_default: i2s0-default{ + mux { + groups = "i2s0_group"; + function = "i2s0_func"; + }; + }; + pinctrl_i2s1_default: i2s1-default{ + mux { + groups = "i2s1_group"; + function = "i2s1_func"; + }; + }; + pinctrl_i2s2_default: i2s2-default{ + mux { + groups = "i2s2_group"; + function = "i2s2_func"; + }; + }; + pinctrl_usb0_pwren_default: usb0_pwren-default{ + mux { + groups = "usb0_pwren_group"; + function = "usb0_pwren_func"; + }; + }; + pinctrl_usb1_pwren_default: usb1_pwren-default{ + mux { + groups = "usb1_pwren_group"; + function = "usb1_pwren_func"; + }; + }; + pinctrl_i2c0_default: i2c0-default{ + mux { + groups = "i2c0_group"; + function = "i2c0_func"; + }; + }; + pinctrl_i2c1_default: i2c1-default{ + mux { + groups = "i2c1_group"; + function = "i2c1_func"; + }; + }; + pinctrl_i2c2_default: i2c2-default{ + mux { + groups = "i2c2_group"; + function = "i2c2_func"; + }; + }; + pinctrl_i2c3_default: i2c3-default{ + mux { + groups = "i2c3_group"; + function = "i2c3_func"; + }; + }; + pinctrl_i2c4_default: i2c4-default{ + mux { + groups = "i2c4_group"; + function = "i2c4_func"; + }; + }; + pinctrl_i2c5_default: i2c5-default{ + mux { + groups = "i2c5_group"; + function = "i2c5_func"; + }; + }; + pinctrl_i2c8_default: i2c8-default{ + mux { + groups = "i2c8_group"; + function = "i2c8_func"; + }; + }; + pinctrl_i2c10_default: i2c10-default{ + mux { + groups = "i2c10_group"; + function = "i2c10_func"; + }; + }; + pinctrl_i2c11_default: i2c11-default{ + mux { + groups = "i2c11_group"; + function = "i2c11_func"; + }; + }; + pinctrl_uart0_default: uart0-default{ + mux { + groups = "uart0_group"; + function = "uart0_func"; + }; + }; + pinctrl_uart1_default: uart1-default{ + mux { + groups = "uart1_group"; + function = "uart1_func"; + }; + }; + pinctrl_uart2_default: uart2-default{ + mux { + groups = "uart2_group"; + function = "uart2_func"; + }; + }; + pinctrl_pwm0_default: pwm0-default{ + mux { + groups = "pwm0_group"; + function = "pwm0_func"; + }; + }; + pinctrl_fan_tach_default: fan_tach-default{ + mux { + groups = "fan_tach_group"; + function = "fan_tach_func"; + }; + }; + pinctrl_mipi_csi0_default: mipi_csi0-default{ + mux { + groups = "mipi_csi0_group"; + function = "mipi_csi0_func"; + }; + }; + pinctrl_mipi_csi1_default: mipi_csi1-default{ + mux { + groups = "mipi_csi1_group"; + function = "mipi_csi1_func"; + }; + }; + pinctrl_mipi_csi2_default: mipi_csi2-default{ + mux { + groups = "mipi_csi2_group"; + function = "mipi_csi2_func"; + }; + }; + pinctrl_mipi_csi3_default: mipi_csi3-default{ + mux { + groups = "mipi_csi3_group"; + function = "mipi_csi3_func"; + }; + }; + pinctrl_mipi_csi4_default: mipi_csi4-default{ + mux { + groups = "mipi_csi4_group"; + function = "mipi_csi4_func"; + }; + }; + pinctrl_mipi_csi5_default: mipi_csi5-default{ + mux { + groups = "mipi_csi5_group"; + function = "mipi_csi5_func"; + }; + }; + pinctrl_s_mode_default: s_mode-default{ + mux { + groups = "s_mode_group"; + function = "s_mode_func"; + }; + }; + pinctrl_pinmux_ddr_refclk_sel_default: pinmux_ddr_refclk_sel-default{ + mux { + groups = "pinmux_ddr_refclk_sel_group"; + function = "pinmux_ddr_refclk_sel_func"; + }; + }; + pinctrl_boot_sel_default: boot_sel-default{ + mux { + groups = "boot_sel_group"; + function = "boot_sel_func"; + }; + }; + pinctrl_lpddr_ref_clk_default: lpddr_ref_clk-default{ + mux { + groups = "lpddr_ref_clk_group"; + function = "lpddr_ref_clk_func"; + }; + }; + + //func1 + pinctrl_spi2_default: spi2-default{ + mux1 { + groups = "spi2_clk_group"; + function = "spi2_clk_func"; + }; + conf1 { + groups = "spi2_clk_group"; + input-enable = <1>; + bias-pull-up = <1>; + bias-pull-down = <0>; + }; + mux2 { + groups = "spi2_d0_group"; + function = "spi2_d0_func"; + }; + conf2 { + groups = "spi2_d0_group"; + input-enable = <1>; + bias-pull-up = <1>; + bias-pull-down = <0>; + }; + mux3 { + groups = "spi2_d1_d2_d3_group"; + function = "spi2_d1_d2_d3_func"; + }; + conf3 { + groups = "spi2_d1_d2_d3_group"; + input-enable = <1>; + bias-pull-up = <1>; + bias-pull-down = <0>; + }; + mux4 { + groups = "spi2_cs_group"; + function = "spi2_cs_func"; + }; + }; + + pinctrl_sata_act_led_default: sata_act_led-default{ + mux { + groups = "sata_act_led_group"; + function = "sata_act_led_func"; + }; + conf { + groups = "sata_act_led_group"; + input-enable = <0>; + bias-pull-down = <1>; + }; + }; + pinctrl_emmc_led_control_default: emmc_led_control-default{ + mux { + groups = "emmc_led_control_group"; + function = "emmc_led_control_func"; + }; + conf { + groups = "emmc_led_control_group"; + input-enable = <0>; + bias-pull-down = <1>; + }; + }; + pinctrl_sd0_led_control_default: sd0_led_control-default{ + mux { + groups = "sd0_led_control_group"; + function = "sd0_led_control_func"; + }; + }; + pinctrl_sd1_led_control_default: sd1_led_control-default{ + mux { + groups = "sd1_led_control_group"; + function = "sd1_led_control_func"; + }; + }; + pinctrl_i2c6_default: i2c6-default{ + mux { + groups = "i2c6_group"; + function = "i2c6_func"; + }; + }; + pinctrl_i2c7_default: i2c7-default{ + mux { + groups = "i2c7_group"; + function = "i2c7_func"; + }; + }; + pinctrl_i2c9_default: i2c9-default{ + mux { + groups = "i2c9_group"; + function = "i2c9_func"; + }; + }; + pinctrl_pwm1_default: pwm1-default{ + mux { + groups = "pwm1_group"; + function = "pwm1_func"; + }; + }; + pinctrl_pwm2_default: pwm2-default{ + mux { + groups = "pwm2_group"; + function = "pwm2_func"; + }; + }; + pinctrl_mipi_csi_xtrig_default: mipi_csi_xtrig-default{ + mux { + groups = "mipi_csi_xtrig_group"; + function = "mipi_csi_xtrig_func"; + }; + }; + + //func3 + pinctrl_uart3_default: uart3-default{ + mux { + groups = "uart3_group"; + function = "uart3_func"; + }; + }; + pinctrl_uart4_default: uart4-default{ + mux { + groups = "uart4_group"; + function = "uart4_func"; + }; + }; + + //gpio + pinctrl_gpio0_default: gpio0-default{ + mux { + groups = "gpio0_group"; + function = "gpio0_func"; + }; + conf { + groups = "gpio0_group"; + input-enable = <1>; + bias-pull-up = <1>; + }; + }; + pinctrl_gpio1_default: gpio1-default{ + mux { + groups = "gpio1_group"; + function = "gpio1_func"; + }; + }; + pinctrl_gpio2_default: gpio2-default{ + mux { + groups = "gpio2_group"; + function = "gpio2_func"; + }; + }; + pinctrl_gpio3_default: gpio3-default{ + mux { + groups = "gpio3_group"; + function = "gpio3_func"; + }; + }; + pinctrl_gpio4_default: gpio4-default{ + mux { + groups = "gpio4_group"; + function = "gpio4_func"; + }; + }; + pinctrl_gpio5_default: gpio5-default{ + mux { + groups = "gpio5_group"; + function = "gpio5_func"; + }; + conf { + groups = "gpio5_group"; + input-enable = <1>; + bias-pull-up = <1>; + }; + }; + pinctrl_gpio6_default: gpio6-default{ + mux { + groups = "gpio6_group"; + function = "gpio6_func"; + }; + conf { + groups = "gpio6_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio7_default: gpio7-default{ + mux { + groups = "gpio7_group"; + function = "gpio7_func"; + }; + conf { + groups = "gpio7_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio8_default: gpio8-default{ + mux { + groups = "gpio8_group"; + function = "gpio8_func"; + }; + conf { + groups = "gpio8_group"; + input-enable = <1>; + bias-pull-up = <1>; + }; + }; + pinctrl_gpio9_default: gpio9-default{ + mux { + groups = "gpio9_group"; + function = "gpio9_func"; + }; + conf { + groups = "gpio9_group"; + input-enable = <1>; + bias-pull-up = <1>; + }; + }; + pinctrl_gpio10_default: gpio10-default{ + mux { + groups = "gpio10_group"; + function = "gpio10_func"; + }; + conf { + groups = "gpio10_group"; + input-enable = <1>; + bias-pull-up = <1>; + }; + }; + pinctrl_gpio11_default: gpio11-default{ + mux { + groups = "gpio11_group"; + function = "gpio11_func"; + }; + conf { + groups = "gpio11_group"; + input-enable = <1>; + bias-pull-up = <1>; + }; + }; + pinctrl_gpio12_default: gpio12-default{ + mux { + groups = "gpio12_group"; + function = "gpio12_func"; + }; + }; + pinctrl_gpio13_default: gpio13-default{ + mux { + groups = "gpio13_group"; + function = "gpio13_func"; + }; + }; + pinctrl_gpio14_default: gpio14-default{ + mux { + groups = "gpio14_group"; + function = "gpio14_func"; + }; + }; + pinctrl_gpio15_default: gpio15-default{ + mux { + groups = "gpio15_group"; + function = "gpio15_func"; + }; + }; + pinctrl_gpio16_default: gpio16-default{ + mux { + groups = "gpio16_group"; + function = "gpio16_func"; + }; + conf { + groups = "gpio16_group"; + input-enable = <0>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio17_default: gpio17-default{ + mux { + groups = "gpio17_group"; + function = "gpio17_func"; + }; + conf { + groups = "gpio17_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio18_default: gpio18-default{ + mux { + groups = "gpio18_group"; + function = "gpio18_func"; + }; + conf { + groups = "gpio18_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio19_default: gpio19-default{ + mux { + groups = "gpio19_group"; + function = "gpio19_func"; + }; + conf { + groups = "gpio19_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio20_default: gpio20-default{ + mux { + groups = "gpio20_group"; + function = "gpio20_func"; + }; + conf { + groups = "gpio20_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio21_default: gpio21-default{ + mux { + groups = "gpio21_group"; + function = "gpio21_func"; + }; + conf { + groups = "gpio21_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio22_default: gpio22-default{ + mux { + groups = "gpio22_group"; + function = "gpio22_func"; + }; + }; + pinctrl_gpio23_default: gpio23-default{ + mux { + groups = "gpio23_group"; + function = "gpio23_func"; + }; + }; + pinctrl_gpio24_default: gpio24-default{ + mux { + groups = "gpio24_group"; + function = "gpio24_func"; + }; + }; + pinctrl_gpio25_default: gpio25-default{ + mux { + groups = "gpio25_group"; + function = "gpio25_func"; + }; + }; + pinctrl_gpio26_default: gpio26-default{ + mux { + groups = "gpio26_group"; + function = "gpio26_func"; + }; + }; + pinctrl_gpio27_default: gpio27-default{ + mux { + groups = "gpio27_group"; + function = "gpio27_func"; + }; + }; + pinctrl_gpio28_default: gpio28-default{ + mux { + groups = "gpio28_group"; + function = "gpio28_func"; + }; + conf { + groups = "gpio28_group"; + input-enable = <1>; + bias-pull-up = <1>; + }; + }; + pinctrl_gpio29_default: gpio29-default{ + mux { + groups = "gpio29_group"; + function = "gpio29_func"; + }; + }; + pinctrl_gpio30_default: gpio30-default{ + mux { + groups = "gpio30_group"; + function = "gpio30_func"; + }; + }; + pinctrl_gpio31_default: gpio31-default{ + mux { + groups = "gpio31_group"; + function = "gpio31_func"; + }; + }; + pinctrl_gpio32_default: gpio32-default{ + mux { + groups = "gpio32_group"; + function = "gpio32_func"; + }; + }; + pinctrl_gpio33_default: gpio33-default{ + mux { + groups = "gpio33_group"; + function = "gpio33_func"; + }; + }; + pinctrl_gpio34_default: gpio34-default{ + mux { + groups = "gpio34_group"; + function = "gpio34_func"; + }; + }; + pinctrl_gpio35_default: gpio35-default{ + mux { + groups = "gpio35_group"; + function = "gpio35_func"; + }; + conf { + groups = "gpio35_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio36_default: gpio36-default{ + mux { + groups = "gpio36_group"; + function = "gpio36_func"; + }; + conf { + groups = "gpio36_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio37_default: gpio37-default{ + mux { + groups = "gpio37_group"; + function = "gpio37_func"; + }; + conf { + groups = "gpio37_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio38_default: gpio38-default{ + mux { + groups = "gpio38_group"; + function = "gpio38_func"; + }; + conf { + groups = "gpio38_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio39_default: gpio39-default{ + mux { + groups = "gpio39_group"; + function = "gpio39_func"; + }; + conf { + groups = "gpio39_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio40_default: gpio40-default{ + mux { + groups = "gpio40_group"; + function = "gpio40_func"; + }; + conf { + groups = "gpio40_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio41_default: gpio41-default{ + mux { + groups = "gpio41_group"; + function = "gpio41_func"; + }; + }; + pinctrl_gpio42_default: gpio42-default{ + mux { + groups = "gpio42_group"; + function = "gpio42_func"; + }; + conf { + groups = "gpio42_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio43_default: gpio43-default{ + mux { + groups = "gpio43_group"; + function = "gpio43_func"; + }; + }; + pinctrl_gpio44_default: gpio44-default{ + mux { + groups = "gpio44_group"; + function = "gpio44_func"; + }; + }; + pinctrl_gpio45_default: gpio45-default{ + mux { + groups = "gpio45_group"; + function = "gpio45_func"; + }; + }; + pinctrl_gpio46_default: gpio46-default{ + mux { + groups = "gpio46_group"; + function = "gpio46_func"; + }; + conf { + groups = "gpio46_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio47_default: gpio47-default{ + mux { + groups = "gpio47_group"; + function = "gpio47_func"; + }; + conf { + groups = "gpio47_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio48_default: gpio48-default{ + mux { + groups = "gpio48_group"; + function = "gpio48_func"; + }; + }; + pinctrl_gpio49_default: gpio49-default{ + mux { + groups = "gpio49_group"; + function = "gpio49_func"; + }; + }; + pinctrl_gpio50_default: gpio50-default{ + mux { + groups = "gpio50_group"; + function = "gpio50_func"; + }; + }; + pinctrl_gpio51_default: gpio51-default{ + mux { + groups = "gpio51_group"; + function = "gpio51_func"; + }; + }; + pinctrl_gpio52_default: gpio52-default{ + mux { + groups = "gpio52_group"; + function = "gpio52_func"; + }; + conf { + groups = "gpio52_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio53_default: gpio53-default{ + mux { + groups = "gpio53_group"; + function = "gpio53_func"; + }; + conf { + groups = "gpio53_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio54_default: gpio54-default{ + mux { + groups = "gpio54_group"; + function = "gpio54_func"; + }; + }; + pinctrl_gpio55_default: gpio55-default{ + mux { + groups = "gpio55_group"; + function = "gpio55_func"; + }; + }; + pinctrl_gpio56_default: gpio56-default{ + mux { + groups = "gpio56_group"; + function = "gpio56_func"; + }; + }; + pinctrl_gpio57_default: gpio57-default{ + mux { + groups = "gpio57_group"; + function = "gpio57_func"; + }; + }; + pinctrl_gpio58_default: gpio58-default{ + mux { + groups = "gpio58_group"; + function = "gpio58_func"; + }; + }; + pinctrl_gpio59_default: gpio59-default{ + mux { + groups = "gpio59_group"; + function = "gpio59_func"; + }; + }; + pinctrl_gpio60_default: gpio60-default{ + mux { + groups = "gpio60_group"; + function = "gpio60_func"; + }; + }; + pinctrl_gpio61_default: gpio61-default{ + mux { + groups = "gpio61_group"; + function = "gpio61_func"; + }; + }; + pinctrl_gpio62_default: gpio62-default{ + mux { + groups = "gpio62_group"; + function = "gpio62_func"; + }; + }; + pinctrl_gpio63_default: gpio63-default{ + mux { + groups = "gpio63_group"; + function = "gpio63_func"; + }; + }; + pinctrl_gpio64_default: gpio64-default{ + mux { + groups = "gpio64_group"; + function = "gpio64_func"; + }; + conf { + groups = "gpio64_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio65_default: gpio65-default{ + mux { + groups = "gpio65_group"; + function = "gpio65_func"; + }; + conf { + groups = "gpio65_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio66_default: gpio66-default{ + mux { + groups = "gpio66_group"; + function = "gpio66_func"; + }; + conf { + groups = "gpio66_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio67_default: gpio67-default{ + mux { + groups = "gpio67_group"; + function = "gpio67_func"; + }; + conf { + groups = "gpio67_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio68_default: gpio68-default{ + mux { + groups = "gpio68_group"; + function = "gpio68_func"; + }; + }; + pinctrl_gpio69_default: gpio69-default{ + mux { + groups = "gpio69_group"; + function = "gpio69_func"; + }; + }; + pinctrl_gpio70_default: gpio70-default{ + mux { + groups = "gpio70_group"; + function = "gpio70_func"; + }; + }; + pinctrl_gpio71_default: gpio71-default{ + mux { + groups = "gpio71_group"; + function = "gpio71_func"; + }; + }; + pinctrl_gpio72_default: gpio72-default{ + mux { + groups = "gpio72_group"; + function = "gpio72_func"; + }; + }; + pinctrl_gpio73_default: gpio73-default{ + mux { + groups = "gpio73_group"; + function = "gpio73_func"; + }; + }; + pinctrl_gpio74_default: gpio74-default{ + mux { + groups = "gpio74_group"; + function = "gpio74_func"; + }; + }; + pinctrl_gpio75_default: gpio75-default{ + mux { + groups = "gpio75_group"; + function = "gpio75_func"; + }; + }; + pinctrl_gpio76_default: gpio76-default{ + mux { + groups = "gpio76_group"; + function = "gpio76_func"; + }; + }; + pinctrl_gpio77_default: gpio77-default{ + mux { + groups = "gpio77_group"; + function = "gpio77_func"; + }; + }; + pinctrl_gpio78_default: gpio78-default{ + mux { + groups = "gpio78_group"; + function = "gpio78_func"; + }; + }; + pinctrl_gpio79_default: gpio79-default{ + mux { + groups = "gpio79_group"; + function = "gpio79_func"; + }; + }; + pinctrl_gpio80_default: gpio80-default{ + mux { + groups = "gpio80_group"; + function = "gpio80_func"; + }; + }; + pinctrl_gpio81_default: gpio81-default{ + mux { + groups = "gpio81_group"; + function = "gpio81_func"; + }; + }; + pinctrl_gpio82_default: gpio82-default{ + mux { + groups = "gpio82_group"; + function = "gpio82_func"; + }; + }; + pinctrl_gpio83_default: gpio83-default{ + mux { + groups = "gpio83_group"; + function = "gpio83_func"; + }; + }; + pinctrl_gpio84_default: gpio84-default{ + mux { + groups = "gpio84_group"; + function = "gpio84_func"; + }; + }; + pinctrl_gpio85_default: gpio85-default{ + mux { + groups = "gpio85_group"; + function = "gpio85_func"; + }; + }; + pinctrl_gpio86_default: gpio86-default{ + mux { + groups = "gpio86_group"; + function = "gpio86_func"; + }; + }; + pinctrl_gpio87_default: gpio87-default{ + mux { + groups = "gpio87_group"; + function = "gpio87_func"; + }; + }; + pinctrl_gpio88_default: gpio88-default{ + mux { + groups = "gpio88_group"; + function = "gpio88_func"; + }; + }; + pinctrl_gpio89_default: gpio89-default{ + mux { + groups = "gpio89_group"; + function = "gpio89_func"; + }; + }; + pinctrl_gpio90_default: gpio90-default{ + mux { + groups = "gpio90_group"; + function = "gpio90_func"; + }; + }; + pinctrl_gpio91_default: gpio91-default{ + mux { + groups = "gpio91_group"; + function = "gpio91_func"; + }; + }; + pinctrl_gpio92_default: gpio92-default{ + mux { + groups = "gpio92_group"; + function = "gpio92_func"; + }; + conf { + groups = "gpio92_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio93_default: gpio93-default{ + mux { + groups = "gpio93_group"; + function = "gpio93_func"; + }; + conf { + groups = "gpio93_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio94_default: gpio94-default{ + mux { + groups = "gpio94_group"; + function = "gpio94_func"; + }; + conf { + groups = "gpio94_group"; + input-enable = <0>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio95_default: gpio95-default{ + mux { + groups = "gpio95_group"; + function = "gpio95_func"; + }; + }; + pinctrl_gpio96_default: gpio96-default{ + mux { + groups = "gpio96_group"; + function = "gpio96_func"; + }; + }; + pinctrl_gpio97_default: gpio97-default{ + mux { + groups = "gpio97_group"; + function = "gpio97_func"; + }; + }; + pinctrl_gpio98_default: gpio98-default{ + mux { + groups = "gpio98_group"; + function = "gpio98_func"; + }; + }; + pinctrl_gpio99_default: gpio99-default{ + mux { + groups = "gpio99_group"; + function = "gpio99_func"; + }; + }; + pinctrl_gpio100_default: gpio100-default{ + mux { + groups = "gpio100_group"; + function = "gpio100_func"; + }; + }; + pinctrl_gpio101_default: gpio101-default{ + mux { + groups = "gpio101_group"; + function = "gpio101_func"; + }; + }; + pinctrl_gpio102_default: gpio102-default{ + mux { + groups = "gpio102_group"; + function = "gpio102_func"; + }; + }; + pinctrl_gpio103_default: gpio103-default{ + mux { + groups = "gpio103_group"; + function = "gpio103_func"; + }; + }; + pinctrl_gpio104_default: gpio104-default{ + mux { + groups = "gpio104_group"; + function = "gpio104_func"; + }; + }; + pinctrl_gpio105_default: gpio105-default{ + mux { + groups = "gpio105_group"; + function = "gpio105_func"; + }; + }; + pinctrl_gpio106_default: gpio106-default{ + mux { + groups = "gpio106_group"; + function = "gpio106_func"; + }; + conf { + groups = "gpio106_group"; + input-enable = <0>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio107_default: gpio107-default{ + mux { + groups = "gpio107_group"; + function = "gpio107_func"; + }; + conf { + groups = "gpio107_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio108_default: gpio108-default{ + mux { + groups = "gpio108_group"; + function = "gpio108_func"; + }; + conf { + groups = "gpio108_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio109_default: gpio109-default{ + mux { + groups = "gpio109_group"; + function = "gpio109_func"; + }; + conf { + groups = "gpio109_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio110_default: gpio110-default{ + mux { + groups = "gpio110_group"; + function = "gpio110_func"; + }; + conf { + groups = "gpio110_group"; + input-enable = <1>; + bias-pull-down = <1>; + }; + }; + pinctrl_gpio111_default: gpio111-default{ + mux { + groups = "gpio111_group"; + function = "gpio111_func"; + }; + conf { + groups = "gpio111_group"; + input-enable = <0>; + bias-pull-up = <1>; + }; + }; + + //func6 + pinctrl_csi_mon_out_default: csi_mon_out-default{ + mux { + groups = "csi_mon_out_group"; + function = "csi_mon_out_func"; + }; + }; + pinctrl_csi_ocla_clk_default: csi_ocla_clk-default{ + mux { + groups = "csi_ocla_clk_group"; + function = "csi_ocla_clk_func"; + }; + }; + pinctrl_csi_mon_out_valid_default: csi_mon_out_valid-default{ + mux { + groups = "csi_mon_out_valid_group"; + function = "csi_mon_out_valid_func"; + }; + }; + pinctrl_csi_parity_error_default: csi_parity_error-default{ + mux { + groups = "csi_parity_error_group"; + function = "csi_parity_error_func"; + }; + }; + pinctrl_csi_dtb_out_default: csi_dtb_out-default{ + mux { + groups = "csi_dtb_out_group"; + function = "csi_dtb_out_func"; + }; + }; + pinctrl_csi_phy_sel_default: csi_phy_sel-default{ + mux { + groups = "csi_phy_sel_group"; + function = "csi_phy_sel_func"; + }; + }; + pinctrl_vc_g2d0_debug_out_default: vc_g2d0_debug_out-default{ + mux { + groups = "vc_g2d0_debug_out_group"; + function = "vc_g2d0_debug_out_func"; + }; + }; + pinctrl_vc_g2d1_debug_out_default: vc_g2d1_debug_out-default{ + mux { + groups = "vc_g2d1_debug_out_group"; + function = "vc_g2d1_debug_out_func"; + }; + }; + pinctrl_sata_mpll_clk_default: sata_mpll_clk-default{ + mux { + groups = "sata_mpll_clk_group"; + function = "sata_mpll_clk_func"; + }; + }; + pinctrl_sata_ref_repeat_clk_m_default: sata_ref_repeat_clk_m-default{ + mux { + groups = "sata_ref_repeat_clk_m_group"; + function = "sata_ref_repeat_clk_m_func"; + }; + }; + pinctrl_sata_ref_repeat_clk_p_default: sata_ref_repeat_clk_p-default{ + mux { + groups = "sata_ref_repeat_clk_p_group"; + function = "sata_ref_repeat_clk_p_func"; + }; + }; + }; + }; +}; diff --git a/arch/riscv/boot/dts/eswin/hifive-premier-p550.dts b/arch/riscv/boot/dts/eswin/hifive-premier-p550.dts new file mode 100644 index 0000000000000..e2f9c2ce62a21 --- /dev/null +++ b/arch/riscv/boot/dts/eswin/hifive-premier-p550.dts @@ -0,0 +1,766 @@ +// 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 . + */ + +/dts-v1/; + +#define RTCCLK_FREQ 1000000 +#define LSPCLK_FREQ 200000000 + +/* Currently, not reserving any DDR for ECC capability. Also, ECC must be disabled in U-Boot + * 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 0x10000000 + +#include "eic7700.dtsi" +#include "hifive-premier-p550-pinctrl.dtsi" +#include +#include + +/* Clock frequency (in Hz) of the PCB crystal for rtcclk */ + +/ { + #address-cells = <2>; + #size-cells = <2>; + model = "SiFive HiFive Premier P550"; + compatible = "sifive,hifive-premier-p550"; + + aliases { + serial0 = &d0_uart0; + ethernet0 = &d0_gmac0; + ethernet1 = &d0_gmac1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + cpus { + timebase-frequency = ; + }; + + 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>; + }; + + lpcpu0_reserved: lpcpu@a0000000 { + no-map; + reg = <0x0 0xa0000000 0x0 0x100000>; + }; + + g2d_4GB_boundary_reserved_4k { + no-map; + reg = <0x0 0xfffff000 0x0 0x1000>; + }; + }; + + soc { + reset_test@1e00e000 { + compatible = "reset_test"; + resets = <&d0_reset SCPU_RST_CTRL SW_SCPU_BUS_RSTN>, + <&d0_reset SCPU_RST_CTRL SW_SCPU_CORE_RSTN>, + <&d0_reset SCPU_RST_CTRL SW_SCPU_DBG_RSTN>; + reset-names = "bus", "core", "dbg"; + }; + }; +}; + +&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"; +}; + +&d0_cfg_noc { + status = "okay"; +}; + +&d0_llc_noc { + status = "okay"; + stat,0 = "TracePort:ddr0_p0_req"; + stat,1 = "TracePort:ddr1_p0_req"; +}; + +&d0_sys_noc { + status = "okay"; + + 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"; + + pending,0 = "TracePort:sysnoc_trans_probe_2", "AddrSize:0x3"; +}; + +&d0_media_noc { + status = "okay"; + + stat,0 = "TracePort:ddr0_p3_req"; + stat,1 = "TracePort:ddr1_p3_req"; +}; + +&d0_realtime_noc { + status = "okay"; + + stat,0 = "TracePort:ddr0_p4_req"; + stat,1 = "TracePort:ddr1_p4_req"; +}; + +&d0_noc_wdt { + status = "okay"; +}; + +&d0_ipc_scpu { + status = "okay"; +}; + +&d0_lpcpu { + status = "disabled"; +}; + +&pcie { + /* GPIO12 PCIE PRSNT input */ + 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"; + 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>; +}; + +&dw_hdmi { + status = "okay"; + eswin-plat = <1>; + 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"; + eswin-plat = <1>; + d0_i2s0_port: port { + d0_i2s0_endpoint: endpoint { + remote-endpoint = <&hdmi_in_i2s>; + dai-format = "i2s"; + }; + }; +}; + +&d0_i2s1 { + status = "okay"; + eswin-plat = <1>; + d0_i2s1_port: port { + d0_i2s1_endpoint: endpoint { + remote-endpoint = <&d0_codec0_endpoint>; + dai-format = "i2s"; + }; + }; +}; + +&d0_i2s2 { + /* connect WIFI module */ + status = "disabled"; +}; + +&d0_graphcard0 { + status = "okay"; + dais = <&d0_i2s1_port>; +}; + +&d0_graphcard1 { + status = "okay"; + dais = <&d0_i2s0_port>; +}; + +&d0_graphcard2 { + status = "disabled"; +}; + +&isp_0 { + status = "disabled"; +}; + +&isp_1 { + status = "disabled"; +}; + +&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>; +}; + +&sdio0 { + /* sd card */ + status = "okay"; + delay_code = <0x29>; + drive-impedance-ohm = <33>; + enable-cmd-pullup; + enable-data-pullup; + no-sdio; + no-mmc; +}; + +&sdio1 { + /* wifi module */ + status = "disabled"; + delay_code = <0x29>; + drive-impedance-ohm = <33>; + enable-cmd-pullup; + enable-data-pullup; + non-removable; + no-sd; + no-mmc; +}; + +&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>; +}; + +&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>; +}; + +&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"; + 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"; + }; +}; + +&d0_dmac0 { + status = "okay"; +}; + +&d0_aon_dmac { + status = "okay"; +}; + +&d0_uart0 { + /* debug */ + status = "okay"; +}; + +&d0_uart1 { + /* M.2 KEY E */ + status = "okay"; +}; + +&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"; +}; + +&bootspi { + /* spi flash */ + status = "okay"; + num-cs = <1>; + cs-gpios = <&portd 0 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"; +}; + +&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>; + iic_hold_time = <0x40>; + pac1934:pac1934@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>; + }; +}; + +&pwm0 { + /* fan */ + status = "okay"; +}; + +&pvt0 { + status = "okay"; +}; + +&pvt1 { + status = "okay"; +}; + +&wdt0 { + status = "okay"; +}; + +&wdt1 { + status = "okay"; +}; + +&wdt2 { + status = "okay"; +}; + +&wdt3 { + status = "okay"; +}; + +&die0_rtc { + status = "okay"; +}; + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&timer2 { + status = "okay"; +}; + +&timer3 { + status = "okay"; +}; + +&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>; + + /* 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 + + 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"; +}; diff --git a/include/dt-bindings/clock/eic7700-clock.h b/include/dt-bindings/clock/eic7700-clock.h new file mode 100755 index 0000000000000..8665074988767 --- /dev/null +++ b/include/dt-bindings/clock/eic7700-clock.h @@ -0,0 +1,623 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Clk Provider 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 . + * + * Authors: HuangYiFeng + */ + +#ifndef __DTS_EIC7700_CLOCK_H +#define __DTS_EIC7700_CLOCK_H + +#define EIC7700_NONE_CLOCK 0 + +/* fixed rate */ +#define EIC7700_XTAL_24M 1 +#define EIC7700_XTAL_32K 2 +#define EIC7700_PLL_CPU 3 /*for cpu clk*/ +#define EIC7700_SPLL0_FOUT1 4 +#define EIC7700_SPLL0_FOUT2 5 +#define EIC7700_SPLL0_FOUT3 6 +#define EIC7700_SPLL1_FOUT1 7 +#define EIC7700_SPLL1_FOUT2 8 +#define EIC7700_SPLL1_FOUT3 9 +#define EIC7700_SPLL2_FOUT1 10 +#define EIC7700_SPLL2_FOUT2 11 +#define EIC7700_SPLL2_FOUT3 12 +#define EIC7700_VPLL_FOUT1 13 +#define EIC7700_VPLL_FOUT2 14 +#define EIC7700_VPLL_FOUT3 15 +#define EIC7700_APLL_FOUT1 16 +#define EIC7700_APLL_FOUT2 17 +#define EIC7700_APLL_FOUT3 18 +#define EIC7700_EXT_MCLK 19 +#define EIC7700_PLL_DDR 20 +#define EIC7700_LPDDR_REF_BAK 21 + + +/* mux clocks */ +#define EIC7700_MUX_U_CPU_ROOT_3MUX1_GFREE 30 /*for cpu clk*/ +#define EIC7700_MUX_U_CPU_ACLK_2MUX1_GFREE 31 /*for cpu clk*/ +#define EIC7700_MUX_U_DSP_ACLK_ROOT_2MUX1_GFREE 32 +#define EIC7700_MUX_U_D2D_ACLK_ROOT_2MUX1_GFREE 33 +#define EIC7700_MUX_U_MSHCORE_ROOT_3MUX1_0 34 +#define EIC7700_MUX_U_MSHCORE_ROOT_3MUX1_1 35 +#define EIC7700_MUX_U_MSHCORE_ROOT_3MUX1_2 36 +#define EIC7700_MUX_U_NPU_LLCLK_3MUX1_GFREE 37 +#define EIC7700_MUX_U_NPU_CORE_3MUX1_GFREE 38 +#define EIC7700_MUX_U_VI_ACLK_ROOT_2MUX1_GFREE 39 +#define EIC7700_MUX_U_VI_DVP_ROOT_2MUX1_GFREE 40 +#define EIC7700_MUX_U_VI_DIG_ISP_ROOT_2MUX1_GFREE 41 +#define EIC7700_MUX_U_VO_ACLK_ROOT_2MUX1_GFREE 42 +#define EIC7700_MUX_U_VO_PIXEL_ROOT_2MUX1 43 +#define EIC7700_MUX_U_VO_CEC_2MUX1 44 +#define EIC7700_MUX_U_VCDEC_ROOT_2MUX1_GFREE 45 +#define EIC7700_MUX_U_VCACLK_ROOT_2MUX1_GFREE 46 +#define EIC7700_MUX_U_RTC_2MUX1 47 +#define EIC7700_MUX_U_SYSCFG_CLK_ROOT_2MUX1_GFREE 48 +#define EIC7700_MUX_U_NOCNSP_XTAL_2MUX1 49 +#define EIC7700_MUX_U_BOOTSPI_CLK_2MUX1_GFREE 50 +#define EIC7700_MUX_U_SCPU_CORE_CLK_2MUX1_GFREE 51 +#define EIC7700_MUX_U_LPCPU_CORE_CLK_2MUX1_GFREE 52 +#define EIC7700_MUX_GPU_ACLK_XTAL_2MUX1 53 +#define EIC7700_MUX_U_DSP_ACLK_XTAL_2MUX1 54 +#define EIC7700_MUX_U_D2D_ACLK_XTAL_2MUX1 55 +#define EIC7700_MUX_U_HSP_ACLK_XTAL_2MUX1 56 +#define EIC7700_MUX_U_PCIE_ACLK_XTAL_2MUX1 57 +#define EIC7700_MUX_U_NPU_ACLK_XTAL_2MUX1 58 +#define EIC7700_MUX_U_NPU_LLC_XTAL_2MUX1 59 +#define EIC7700_MUX_U_NPU_CORE_XTAL_2MUX1 60 +#define EIC7700_MUX_U_VI_ACLK_XTAL_2MUX1 61 +#define EIC7700_MUX_U_VI_DVP_XTAL_2MUX1 62 +#define EIC7700_MUX_U_VI_DIG_ISP_XTAL_2MUX1 63 +#define EIC7700_MUX_U_VI_SHUTTER_XTAL_2MUX1_0 64 +#define EIC7700_MUX_U_VI_SHUTTER_XTAL_2MUX1_1 65 +#define EIC7700_MUX_U_VI_SHUTTER_XTAL_2MUX1_2 66 +#define EIC7700_MUX_U_VI_SHUTTER_XTAL_2MUX1_3 67 +#define EIC7700_MUX_U_VI_SHUTTER_XTAL_2MUX1_4 68 +#define EIC7700_MUX_U_VI_SHUTTER_XTAL_2MUX1_5 69 +#define EIC7700_MUX_U_VO_ACLK_XTAL_2MUX1 70 +#define EIC7700_MUX_U_IESMCLK_XTAL_2MUX1 71 +#define EIC7700_MUX_U_VO_PIXEL_XTAL_2MUX1 72 +#define EIC7700_MUX_U_VO_MCLK_2MUX_EXT_MCLK 73 +#define EIC7700_MUX_U_VC_ACLK_XTAL_2MUX1 74 +#define EIC7700_MUX_U_JD_XTAL_2MUX1 75 +#define EIC7700_MUX_U_JE_XTAL_2MUX1 76 +#define EIC7700_MUX_U_VE_XTAL_2MUX1 77 +#define EIC7700_MUX_U_VD_XTAL_2MUX1 78 +#define EIC7700_MUX_U_SATA_PHY_2MUX1 79 +#define EIC7700_MUX_U_AONDMA_AXI2MUX1_GFREE 80 +#define EIC7700_MUX_U_CRYPTO_XTAL_2MUX1 81 +#define EIC7700_MUX_U_RMII_REF_2MUX 82 +#define EIC7700_MUX_U_ETH_CORE_2MUX1 83 +#define EIC7700_MUX_U_VI_DW_ROOT_2MUX1 84 +#define EIC7700_MUX_U_VI_DW_XTAL_2MUX1 85 +#define EIC7700_MUX_U_NPU_E31_3MUX1_GFREE 86 +#define EIC7700_MUX_U_DDR_ACLK_ROOT_2MUX1_GFREE 87 + +/* divider clocks */ +#define EIC7700_DIVDER_U_SYS_CFG_DIV_DYNM 100 +#define EIC7700_DIVDER_U_NOC_NSP_DIV_DYNM 101 +#define EIC7700_DIVDER_U_BOOTSPI_DIV_DYNM 102 +#define EIC7700_DIVDER_U_SCPU_CORE_DIV_DYNM 103 +#define EIC7700_DIVDER_U_LPCPU_CORE_DIV_DYNM 104 +#define EIC7700_DIVDER_U_GPU_ACLK_DIV_DYNM 105 +#define EIC7700_DIVDER_U_DSP_ACLK_DIV_DYNM 106 +#define EIC7700_DIVDER_U_D2D_ACLK_DIV_DYNM 107 +#define EIC7700_DIVDER_U_HSP_ACLK_DIV_DYNM 108 +#define EIC7700_DIVDER_U_ETH_TXCLK_DIV_DYNM_0 109 +#define EIC7700_DIVDER_U_ETH_TXCLK_DIV_DYNM_1 110 +#define EIC7700_DIVDER_U_MSHC_CORE_DIV_DYNM_0 111 +#define EIC7700_DIVDER_U_MSHC_CORE_DIV_DYNM_1 112 +#define EIC7700_DIVDER_U_MSHC_CORE_DIV_DYNM_2 113 +#define EIC7700_DIVDER_U_PCIE_ACLK_DIV_DYNM 114 +#define EIC7700_DIVDER_U_NPU_ACLK_DIV_DYNM 115 +#define EIC7700_DIVDER_U_NPU_LLC_SRC0_DIV_DYNM 116 +#define EIC7700_DIVDER_U_NPU_LLC_SRC1_DIV_DYNM 117 +#define EIC7700_DIVDER_U_NPU_CORECLK_DIV_DYNM 118 +#define EIC7700_DIVDER_U_VI_ACLK_DIV_DYNM 119 +#define EIC7700_DIVDER_U_VI_DVP_DIV_DYNM 120 +#define EIC7700_DIVDER_U_VI_DIG_ISP_DIV_DYNM 121 +#define EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_0 122 +#define EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_1 123 +#define EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_2 124 +#define EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_3 125 +#define EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_4 126 +#define EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_5 127 +#define EIC7700_DIVDER_U_VO_ACLK_DIV_DYNM 128 +#define EIC7700_DIVDER_U_IESMCLK_DIV_DYNM 129 +#define EIC7700_DIVDER_U_VO_PIXEL_DIV_DYNM 130 +#define EIC7700_DIVDER_U_VO_MCLK_DIV_DYNM 131 +#define EIC7700_DIVDER_U_VC_ACLK_DIV_DYNM 132 +#define EIC7700_DIVDER_U_JD_DIV_DYNM 133 +#define EIC7700_DIVDER_U_JE_DIV_DYNM 134 +#define EIC7700_DIVDER_U_VE_DIV_DYNM 135 +#define EIC7700_DIVDER_U_VD_DIV_DYNM 136 +#define EIC7700_DIVDER_U_G2D_DIV_DYNM 137 +#define EIC7700_DIVDER_U_AONDMA_AXI_DIV_DYNM 138 +#define EIC7700_DIVDER_U_CRYPTO_DIV_DYNM 139 +#define EIC7700_DIVDER_U_VI_DW_DIV_DYNM 140 +#define EIC7700_DIVDER_U_NPU_E31_DIV_DYNM 141 +#define EIC7700_DIVDER_U_SATA_PHY_REF_DIV_DYNM 142 +#define EIC7700_DIVDER_U_DSP_0_ACLK_DIV_DYNM 143 +#define EIC7700_DIVDER_U_DSP_1_ACLK_DIV_DYNM 144 +#define EIC7700_DIVDER_U_DSP_2_ACLK_DIV_DYNM 145 +#define EIC7700_DIVDER_U_DSP_3_ACLK_DIV_DYNM 146 +#define EIC7700_DIVDER_U_DDR_ACLK_DIV_DYNM 147 +#define EIC7700_DIVDER_U_AON_RTC_DIV_DYNM 148 +#define EIC7700_DIVDER_U_U84_RTC_TOGGLE_DIV_DYNM 149 +#define EIC7700_DIVDER_U_VO_CEC_DIV_DYNM 150 + +/* gate clocks */ +#define EIC7700_GATE_CLK_CPU_EXT_SRC_CORE_CLK_0 200 +#define EIC7700_GATE_CLK_CPU_EXT_SRC_CORE_CLK_1 201 +#define EIC7700_GATE_CLK_CPU_EXT_SRC_CORE_CLK_2 202 +#define EIC7700_GATE_CLK_CPU_EXT_SRC_CORE_CLK_3 203 +#define EIC7700_GATE_CLK_CPU_TRACE_CLK_0 204 +#define EIC7700_GATE_CLK_CPU_TRACE_CLK_1 205 +#define EIC7700_GATE_CLK_CPU_TRACE_CLK_2 206 +#define EIC7700_GATE_CLK_CPU_TRACE_CLK_3 207 +#define EIC7700_GATE_CLK_CPU_DEBUG_CLK 208 +#define EIC7700_GATE_CLK_CPU_TRACE_COM_CLK 209 +#define EIC7700_GATE_CLK_CPU_CLK 210 +#define EIC7700_GATE_CLK_SPLL0_FOUT2 211 +#define EIC7700_GATE_CLK_VPLL_FOUT2 212 +#define EIC7700_GATE_CLK_VPLL_FOUT3 213 +#define EIC7700_GATE_CLK_APLL_FOUT1 214 +#define EIC7700_GATE_CLK_APLL_FOUT2 215 +#define EIC7700_GATE_CLK_APLL_FOUT3 216 +#define EIC7700_GATE_EXT_MCLK 217 +#define EIC7700_GATE_CLK_1M 218 +#define EIC7700_GATE_CLK_SYS_CFG 219 +#define EIC7700_GATE_CLK_MIPI_TXESC 220 +#define EIC7700_GATE_NOC_CFG_CLK 221 +#define EIC7700_GATE_NOC_NSP_CLK 222 +#define EIC7700_GATE_CLK_BOOTSPI 223 +#define EIC7700_GATE_CLK_BOOTSPI_CFG 224 +#define EIC7700_GATE_CLK_U84_CORE_LP 225 +#define EIC7700_GATE_CLK_SCPU_CORE 226 +#define EIC7700_GATE_CLK_SCPU_BUS 227 +#define EIC7700_GATE_CLK_LPCPU_CORE 228 +#define EIC7700_GATE_CLK_LPCPU_BUS 229 +#define EIC7700_GATE_GPU_ACLK 230 +#define EIC7700_GATE_GPU_GRAY_CLK 231 +#define EIC7700_GATE_GPU_CFG_CLK 232 +#define EIC7700_GATE_CLK_DSP_ROOT 233 +#define EIC7700_GATE_DSPT_ACLK 234 +#define EIC7700_GATE_DSPT_CFG_CLK 235 +#define EIC7700_GATE_CLK_D2DDR_ACLK 236 +#define EIC7700_GATE_D2D_ACLK 237 +#define EIC7700_GATE_D2D_CFG_CLK 238 +#define EIC7700_GATE_CLK_HSP_ACLK 239 +#define EIC7700_GATE_CLK_HSP_CFGCLK 240 +#define EIC7700_GATE_TCU_ACLK 241 +#define EIC7700_GATE_TCU_CFG_CLK 242 +#define EIC7700_GATE_DDRT_CFG_CLK 243 +#define EIC7700_GATE_DDRT1_CFG_CLK 244 +#define EIC7700_GATE_DDRT0_P0_ACLK 245 +#define EIC7700_GATE_DDRT0_P1_ACLK 246 +#define EIC7700_GATE_DDRT0_P2_ACLK 247 +#define EIC7700_GATE_DDRT0_P3_ACLK 248 +#define EIC7700_GATE_DDRT0_P4_ACLK 249 +#define EIC7700_GATE_DDRT1_P0_ACLK 250 +#define EIC7700_GATE_DDRT1_P1_ACLK 251 +#define EIC7700_GATE_DDRT1_P2_ACLK 252 +#define EIC7700_GATE_DDRT1_P3_ACLK 253 +#define EIC7700_GATE_DDRT1_P4_ACLK 254 +#define EIC7700_GATE_HSP_ACLK 255 +#define EIC7700_GATE_HSP_CFG_CLK 256 +#define EIC7700_GATE_HSP_SATA_RBC_CLK 257 +#define EIC7700_GATE_HSP_SATA_OOB_CLK 258 +#define EIC7700_GATE_HSP_SATA_PMALIVE_CLK 259 +#define EIC7700_GATE_HSP_ETH_APP_CLK 260 +#define EIC7700_GATE_HSP_ETH_CSR_CLK 261 +#define EIC7700_GATE_HSP_ETH0_CORE_CLK 262 +#define EIC7700_GATE_HSP_ETH1_CORE_CLK 263 +#define EIC7700_GATE_HSP_MSHC0_CORE_CLK 264 +#define EIC7700_GATE_HSP_MSHC1_CORE_CLK 265 +#define EIC7700_GATE_HSP_MSHC2_CORE_CLK 266 +#define EIC7700_GATE_HSP_MSHC0_TMR_CLK 267 +#define EIC7700_GATE_HSP_MSHC1_TMR_CLK 268 +#define EIC7700_GATE_HSP_MSHC2_TMR_CLK 269 +#define EIC7700_GATE_HSP_USB0_SUSPEND_CLK 270 +#define EIC7700_GATE_HSP_USB1_SUSPEND_CLK 271 +#define EIC7700_GATE_PCIET_ACLK 272 +#define EIC7700_GATE_PCIET_CFG_CLK 273 +#define EIC7700_GATE_PCIET_CR_CLK 274 +#define EIC7700_GATE_PCIET_AUX_CLK 275 +#define EIC7700_GATE_NPU_ACLK 276 +#define EIC7700_GATE_NPU_CFG_CLK 277 +#define EIC7700_GATE_CLK_NPU_LLC_SRC0 278 +#define EIC7700_GATE_CLK_NPU_LLC_SRC1 279 +#define EIC7700_GATE_NPU_LLC_ACLK 280 +#define EIC7700_GATE_CLK_NPU_CORE_ST1 281 +#define EIC7700_GATE_NPU_CLK 282 +#define EIC7700_GATE_NPU_E31_CLK 283 +#define EIC7700_GATE_CLK_VI_ACLK_ST1 284 +#define EIC7700_GATE_VI_ACLK 285 +#define EIC7700_GATE_VI_DVP_CLK 286 +#define EIC7700_GATE_VI_CFG_CLK 287 +#define EIC7700_GATE_VI_DIG_DW_CLK 288 +#define EIC7700_GATE_VI_DIG_ISP_CLK 289 +#define EIC7700_GATE_VI_SHUTTER_0 290 +#define EIC7700_GATE_VI_SHUTTER_1 291 +#define EIC7700_GATE_VI_SHUTTER_2 292 +#define EIC7700_GATE_VI_SHUTTER_3 293 +#define EIC7700_GATE_VI_SHUTTER_4 294 +#define EIC7700_GATE_VI_SHUTTER_5 295 +#define EIC7700_GATE_VI_PHY_TXCLKESC 296 +#define EIC7700_GATE_VI_PHY_CFG 297 +#define EIC7700_GATE_VO_ACLK 298 +#define EIC7700_GATE_VO_CFG_CLK 299 +#define EIC7700_GATE_VO_HDMI_IESMCLK 300 +#define EIC7700_GATE_VO_PIXEL_CLK 301 +#define EIC7700_GATE_VO_I2S_MCLK 302 +#define EIC7700_GATE_VO_CR_CLK 303 +#define EIC7700_GATE_VO_CEC_CLK 304 +#define EIC7700_GATE_CLK_VC_ROOT 305 +#define EIC7700_GATE_VC_ACLK 306 +#define EIC7700_GATE_VC_CFG_CLK 307 +#define EIC7700_GATE_VC_JE_CLK 308 +#define EIC7700_GATE_VC_JD_CLK 309 +#define EIC7700_GATE_VC_VE_CLK 310 +#define EIC7700_GATE_VC_VD_CLK 311 +#define EIC7700_GATE_G2D_CFG_CLK 312 +#define EIC7700_GATE_CLK_G2D_ST2 313 +#define EIC7700_GATE_G2D_CLK 314 +#define EIC7700_GATE_G2D_ACLK 315 +#define EIC7700_GATE_CLK_PVT_INNER 316 +#define EIC7700_GATE_PVT_CLK_0 317 +#define EIC7700_GATE_PVT_CLK_1 318 +#define EIC7700_GATE_PVT_CLK_2 319 +#define EIC7700_GATE_PVT_CLK_3 320 +#define EIC7700_GATE_PVT_CLK_4 321 +#define EIC7700_GATE_CLK_AONDMA_CFG 322 +#define EIC7700_GATE_CLK_AONDMA_AXI_ST3 323 +#define EIC7700_GATE_AONDMA_ACLK 324 +#define EIC7700_GATE_AON_ACLK 325 +#define EIC7700_GATE_TIMER_CLK_0 326 +#define EIC7700_GATE_TIMER_CLK_1 327 +#define EIC7700_GATE_TIMER_CLK_2 328 +#define EIC7700_GATE_TIMER_CLK_3 329 +#define EIC7700_GATE_TIMER_PCLK_0 330 +#define EIC7700_GATE_TIMER_PCLK_1 331 +#define EIC7700_GATE_TIMER_PCLK_2 332 +#define EIC7700_GATE_TIMER_PCLK_3 333 +#define EIC7700_GATE_TIMER3_CLK8 334 +#define EIC7700_GATE_CLK_RTC_CFG 335 +#define EIC7700_GATE_CLK_RTC 336 +#define EIC7700_GATE_HSP_RMII_REF_0 337 +#define EIC7700_GATE_HSP_RMII_REF_1 338 +#define EIC7700_GATE_CLK_PKA_CFG 339 +#define EIC7700_GATE_CLK_SPACC_CFG 340 +#define EIC7700_GATE_CLK_CRYPTO 341 +#define EIC7700_GATE_CLK_TRNG_CFG 342 +#define EIC7700_GATE_CLK_OTP_CFG 343 +#define EIC7700_GATE_CLMM_CFG_CLK 344 +#define EIC7700_GATE_CLMM_DEB_CLK 345 +#define EIC7700_GATE_CLK_MAILBOX_0 346 +#define EIC7700_GATE_CLK_MAILBOX_1 347 +#define EIC7700_GATE_CLK_MAILBOX_2 348 +#define EIC7700_GATE_CLK_MAILBOX_3 349 +#define EIC7700_GATE_CLK_MAILBOX_4 350 +#define EIC7700_GATE_CLK_MAILBOX_5 351 +#define EIC7700_GATE_CLK_MAILBOX_6 352 +#define EIC7700_GATE_CLK_MAILBOX_7 353 +#define EIC7700_GATE_CLK_MAILBOX_8 354 +#define EIC7700_GATE_CLK_MAILBOX_9 355 +#define EIC7700_GATE_CLK_MAILBOX_10 356 +#define EIC7700_GATE_CLK_MAILBOX_11 357 +#define EIC7700_GATE_CLK_MAILBOX_12 358 +#define EIC7700_GATE_CLK_MAILBOX_13 359 +#define EIC7700_GATE_CLK_MAILBOX_14 360 +#define EIC7700_GATE_CLK_MAILBOX_15 361 +#define EIC7700_GATE_CLK_APLL_TEST_OUT 362 +#define EIC7700_GATE_CLK_CPLL_TEST_OUT 363 +#define EIC7700_GATE_CLK_HSP_DFT150M 364 +#define EIC7700_GATE_CLK_HSP_DFT300M 365 +#define EIC7700_GATE_CLK_HSP_DFT600M 366 +#define EIC7700_GATE_CLK_VI_DFT400M 367 +#define EIC7700_GATE_CLK_VI_DFT500M 368 +#define EIC7700_GATE_CLK_VO_DFT300M 369 +#define EIC7700_GATE_CLK_VO_DFT600M 370 +#define EIC7700_GATE_CLK_D2D_DFT300M 371 +#define EIC7700_GATE_CLK_D2D_DFT600M 372 +#define EIC7700_GATE_CLK_PCIE_DFT125M 373 +#define EIC7700_GATE_CLK_PCIE_DFT200M 374 +#define EIC7700_GATE_CLK_DDR_PLL_BYP_CLK 375 +#define EIC7700_GATE_CLK_DDR_RX_TEST_CLK 376 +#define EIC7700_GATE_LSP_I2C0_PCLK 377 +#define EIC7700_GATE_LSP_I2C1_PCLK 378 +#define EIC7700_GATE_LSP_I2C2_PCLK 379 +#define EIC7700_GATE_LSP_I2C3_PCLK 380 +#define EIC7700_GATE_LSP_I2C4_PCLK 381 +#define EIC7700_GATE_LSP_I2C5_PCLK 382 +#define EIC7700_GATE_LSP_I2C6_PCLK 383 +#define EIC7700_GATE_LSP_I2C7_PCLK 384 +#define EIC7700_GATE_LSP_I2C8_PCLK 385 +#define EIC7700_GATE_LSP_I2C9_PCLK 386 +#define EIC7700_GATE_LSP_WDT0_PCLK 387 +#define EIC7700_GATE_LSP_WDT1_PCLK 388 +#define EIC7700_GATE_LSP_WDT2_PCLK 389 +#define EIC7700_GATE_LSP_WDT3_PCLK 390 +#define EIC7700_GATE_LSP_SSI0_PCLK 391 +#define EIC7700_GATE_LSP_SSI1_PCLK 392 +#define EIC7700_GATE_LSP_PVT_PCLK 393 +#define EIC7700_GATE_AON_I2C0_PCLK 394 +#define EIC7700_GATE_AON_I2C1_PCLK 395 +#define EIC7700_GATE_LSP_UART0_PCLK 396 +#define EIC7700_GATE_LSP_UART1_PCLK 397 +#define EIC7700_GATE_LSP_UART2_PCLK 398 +#define EIC7700_GATE_LSP_UART3_PCLK 399 +#define EIC7700_GATE_LSP_UART4_PCLK 400 +#define EIC7700_GATE_LSP_TIMER_PCLK 401 +#define EIC7700_GATE_LSP_FAN_PCLK 402 +#define EIC7700_GATE_LSP_PVT0_CLK 403 +#define EIC7700_GATE_LSP_PVT1_CLK 404 +#define EIC7700_GATE_RESERVED_1 405 +#define EIC7700_GATE_RESERVED_2 406 +#define EIC7700_GATE_RESERVED_3 407 +#define EIC7700_GATE_VC_JE_PCLK 408 +#define EIC7700_GATE_VC_JD_PCLK 409 +#define EIC7700_GATE_VC_VE_PCLK 410 +#define EIC7700_GATE_VC_VD_PCLK 411 +#define EIC7700_GATE_VC_MON_PCLK 412 +#define EIC7700_GATE_HSP_DMA0_CLK 413 + +/*fixed factor clocks*/ +#define EIC7700_FIXED_FACTOR_U_CPU_DIV2 450 +#define EIC7700_FIXED_FACTOR_U_CLK_1M_DIV24 451 +#define EIC7700_FIXED_FACTOR_U_MIPI_TXESC_DIV10 452 +#define EIC7700_FIXED_FACTOR_U_U84_CORE_LP_DIV2 453 +#define EIC7700_FIXED_FACTOR_U_SCPU_BUS_DIV2 454 +#define EIC7700_FIXED_FACTOR_U_LPCPU_BUS_DIV2 455 +#define EIC7700_FIXED_FACTOR_U_PCIE_CR_DIV2 456 +#define EIC7700_FIXED_FACTOR_U_PCIE_AUX_DIV4 457 +#define EIC7700_FIXED_FACTOR_U_PVT_DIV20 458 +#define EIC7700_FIXED_FACTOR_U_DFT100M_DIV4 459 +#define EIC7700_FIXED_FACTOR_U_DFT125M_DIV2 460 +#define EIC7700_FIXED_FACTOR_U_DFT150M_DIV2 461 +#define EIC7700_FIXED_FACTOR_U_DFT100M_DIV2 462 +#define EIC7700_FIXED_FACTOR_U_DFT500M_DIV3 463 +#define EIC7700_FIXED_FACTOR_U_DFT500M_DIV2 464 +#define EIC7700_FIXED_FACTOR_SPLL0_TEST_DIV8 465 +#define EIC7700_FIXED_FACTOR_SPLL1_TEST_DIV6 466 +#define EIC7700_FIXED_FACTOR_SPLL2_TEST_DIV4 467 +#define EIC7700_FIXED_FACTOR_U_HSP_RMII_REF_DIV6 468 +#define EIC7700_FIXED_FACTOR_U_DRR_DIV8 469 + + +/*clocks list for consumer*/ +#define EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_0 500 +#define EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_1 501 +#define EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_2 502 +#define EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_3 503 +#define EIC7700_CLK_CPU_TRACE_CLK_0 504 +#define EIC7700_CLK_CPU_TRACE_CLK_1 505 +#define EIC7700_CLK_CPU_TRACE_CLK_2 506 +#define EIC7700_CLK_CPU_TRACE_CLK_3 507 +#define EIC7700_CLK_CPU_DEBUG_CLK 508 +#define EIC7700_CLK_CPU_TRACE_COM_CLK 509 +#define EIC7700_CLK_CPU_CLK 510 +#define EIC7700_CLK_CLK_1M 511 +#define EIC7700_CLK_CLK_SYS_CFG 512 +#define EIC7700_CLK_CLK_MIPI_TXESC 513 +#define EIC7700_CLK_NOC_CFG_CLK 514 +#define EIC7700_CLK_NOC_NSP_CLK 515 +#define EIC7700_CLK_CLK_BOOTSPI 516 +#define EIC7700_CLK_CLK_BOOTSPI_CFG 517 +#define EIC7700_CLK_CLK_U84_CORE_LP 518 +#define EIC7700_CLK_CLK_SCPU_CORE 519 +#define EIC7700_CLK_CLK_SCPU_BUS 520 +#define EIC7700_CLK_CLK_LPCPU_CORE 521 +#define EIC7700_CLK_CLK_LPCPU_BUS 522 +#define EIC7700_CLK_GPU_ACLK 523 +#define EIC7700_CLK_GPU_GRAY_CLK 524 +#define EIC7700_CLK_GPU_CFG_CLK 525 +#define EIC7700_CLK_CLK_DSP_ROOT 526 +#define EIC7700_CLK_DSPT_ACLK 527 +#define EIC7700_CLK_DSPT_CFG_CLK 528 +#define EIC7700_CLK_CLK_D2DDR_ACLK 529 +#define EIC7700_CLK_D2D_ACLK 530 +#define EIC7700_CLK_D2D_CFG_CLK 531 +#define EIC7700_CLK_TCU_ACLK 532 +#define EIC7700_CLK_TCU_CFG_CLK 533 +#define EIC7700_CLK_DDRT_CFG_CLK 534 +#define EIC7700_CLK_DDRT0_P0_ACLK 535 +#define EIC7700_CLK_DDRT0_P1_ACLK 536 +#define EIC7700_CLK_DDRT0_P2_ACLK 537 +#define EIC7700_CLK_DDRT0_P3_ACLK 538 +#define EIC7700_CLK_DDRT0_P4_ACLK 539 +#define EIC7700_CLK_DDRT1_P0_ACLK 540 +#define EIC7700_CLK_DDRT1_P1_ACLK 541 +#define EIC7700_CLK_DDRT1_P2_ACLK 542 +#define EIC7700_CLK_DDRT1_P3_ACLK 543 +#define EIC7700_CLK_DDRT1_P4_ACLK 544 +#define EIC7700_CLK_HSP_ACLK 545 +#define EIC7700_CLK_HSP_CFG_CLK 546 +#define EIC7700_CLK_HSP_SATA_RBC_CLK 547 +#define EIC7700_CLK_HSP_SATA_OOB_CLK 548 +#define EIC7700_CLK_HSP_SATA_PMALIVE_CLK 549 +#define EIC7700_CLK_HSP_ETH_APP_CLK 550 +#define EIC7700_CLK_HSP_ETH_CSR_CLK 551 +#define EIC7700_CLK_HSP_ETH0_CORE_CLK 552 +#define EIC7700_CLK_HSP_ETH1_CORE_CLK 553 +#define EIC7700_CLK_HSP_MSHC0_CORE_CLK 554 +#define EIC7700_CLK_HSP_MSHC1_CORE_CLK 555 +#define EIC7700_CLK_HSP_MSHC2_CORE_CLK 556 +#define EIC7700_CLK_HSP_MSHC0_TMR_CLK 557 +#define EIC7700_CLK_HSP_MSHC1_TMR_CLK 558 +#define EIC7700_CLK_HSP_MSHC2_TMR_CLK 559 +#define EIC7700_CLK_HSP_USB0_SUSPEND_CLK 560 +#define EIC7700_CLK_HSP_USB1_SUSPEND_CLK 561 +#define EIC7700_CLK_PCIET_ACLK 562 +#define EIC7700_CLK_PCIET_CFG_CLK 563 +#define EIC7700_CLK_PCIET_CR_CLK 564 +#define EIC7700_CLK_PCIET_AUX_CLK 565 +#define EIC7700_CLK_NPU_ACLK 566 +#define EIC7700_CLK_NPU_CFG_CLK 567 +#define EIC7700_CLK_CLK_NPU_LLC_SRC0 568 +#define EIC7700_CLK_CLK_NPU_LLC_SRC1 569 +#define EIC7700_CLK_NPU_LLC_ACLK 570 +#define EIC7700_CLK_CLK_NPU_CORE_ST1 571 +#define EIC7700_CLK_NPU_CLK 572 +#define EIC7700_CLK_NPU_E31_CLK 573 +#define EIC7700_CLK_CLK_VI_ACLK_ST1 574 +#define EIC7700_CLK_VI_ACLK 575 +#define EIC7700_CLK_VI_DVP_CLK 576 +#define EIC7700_CLK_VI_CFG_CLK 577 +#define EIC7700_CLK_VI_DIG_DW_CLK 578 +#define EIC7700_CLK_VI_DIG_ISP_CLK 579 +#define EIC7700_CLK_VI_SHUTTER_0 580 +#define EIC7700_CLK_VI_SHUTTER_1 581 +#define EIC7700_CLK_VI_SHUTTER_2 582 +#define EIC7700_CLK_VI_SHUTTER_3 583 +#define EIC7700_CLK_VI_SHUTTER_4 584 +#define EIC7700_CLK_VI_SHUTTER_5 585 +#define EIC7700_CLK_VI_PHY_TXCLKESC 586 +#define EIC7700_CLK_VI_PHY_CFG 587 +#define EIC7700_CLK_VO_ACLK 588 +#define EIC7700_CLK_VO_CFG_CLK 589 +#define EIC7700_CLK_VO_HDMI_IESMCLK 590 +#define EIC7700_CLK_VO_PIXEL_CLK 591 +#define EIC7700_CLK_VO_I2S_MCLK 592 +#define EIC7700_CLK_VO_CR_CLK 593 +#define EIC7700_CLK_VO_CEC_CLK 594 +#define EIC7700_CLK_CLK_VC_ROOT 595 +#define EIC7700_CLK_VC_ACLK 596 +#define EIC7700_CLK_VC_CFG_CLK 597 +#define EIC7700_CLK_VC_JE_CLK 598 +#define EIC7700_CLK_VC_JD_CLK 599 +#define EIC7700_CLK_VC_VE_CLK 600 +#define EIC7700_CLK_VC_VD_CLK 601 +#define EIC7700_CLK_G2D_CFG_CLK 602 +#define EIC7700_CLK_CLK_G2D_ST2 603 +#define EIC7700_CLK_G2D_CLK 604 +#define EIC7700_CLK_G2D_ACLK 605 +#define EIC7700_CLK_CLK_RESERVED 606 +#define EIC7700_CLK_PVT_CLK_0 607 +#define EIC7700_CLK_PVT_CLK_1 608 +#define EIC7700_CLK_HSP_RMII_REF_0 609 +#define EIC7700_CLK_HSP_RMII_REF_1 610 +#define EIC7700_CLK_HSP_SATA_PHY_REF 611 +#define EIC7700_CLK_AONDMA_CFG 612 +#define EIC7700_CLK_CLK_AONDMA_AXI_ST3 613 +#define EIC7700_CLK_AONDMA_ACLK 614 +#define EIC7700_CLK_AON_ACLK 615 +#define EIC7700_CLK_TIMER_CLK_0 616 //AON timer +#define EIC7700_CLK_TIMER_CLK_1 617 +#define EIC7700_CLK_TIMER_CLK_2 618 +#define EIC7700_CLK_TIMER_CLK_3 619 +#define EIC7700_CLK_TIMER_PCLK_0 620 +#define EIC7700_CLK_TIMER_PCLK_1 621 +#define EIC7700_CLK_TIMER_PCLK_2 622 +#define EIC7700_CLK_TIMER_PCLK_3 623 +#define EIC7700_CLK_TIMER3_CLK8 624 +#define EIC7700_CLK_CLK_RTC_CFG 625 // AON rtc +#define EIC7700_CLK_CLK_RTC 626 // AON rtc +#define EIC7700_CLK_CLK_U84_RTC_TOGGLE 627 +#define EIC7700_CLK_UNUSED_1 628 +#define EIC7700_CLK_CLK_PKA_CFG 629 +#define EIC7700_CLK_CLK_SPACC_CFG 630 +#define EIC7700_CLK_CLK_CRYPTO 631 +#define EIC7700_CLK_CLK_TRNG_CFG 632 +#define EIC7700_CLK_CLK_OTP_CFG 633 +#define EIC7700_CLK_CLMM_CFG_CLK 634 +#define EIC7700_CLK_CLMM_DEB_CLK 635 +#define EIC7700_CLK_DDR_PLL_BYP_CLK 636 +#define EIC7700_CLK_DDR_PLL_REF_AND_DFI_CLK 637 +#define EIC7700_CLK_DDR_RX_TEST_CLK 638 +#define EIC7700_CLK_MAILBOX_0 638 +#define EIC7700_CLK_MAILBOX_1 639 +#define EIC7700_CLK_MAILBOX_2 640 +#define EIC7700_CLK_MAILBOX_3 641 +#define EIC7700_CLK_MAILBOX_4 642 +#define EIC7700_CLK_MAILBOX_5 643 +#define EIC7700_CLK_MAILBOX_6 644 +#define EIC7700_CLK_MAILBOX_7 645 +#define EIC7700_CLK_MAILBOX_8 646 +#define EIC7700_CLK_MAILBOX_9 647 +#define EIC7700_CLK_MAILBOX_10 648 +#define EIC7700_CLK_MAILBOX_11 649 +#define EIC7700_CLK_MAILBOX_12 650 +#define EIC7700_CLK_MAILBOX_13 651 +#define EIC7700_CLK_MAILBOX_14 652 +#define EIC7700_CLK_MAILBOX_15 653 +#define EIC7700_CLK_LSP_I2C0_PCLK 654 +#define EIC7700_CLK_LSP_I2C1_PCLK 655 +#define EIC7700_CLK_LSP_I2C2_PCLK 656 +#define EIC7700_CLK_LSP_I2C3_PCLK 657 +#define EIC7700_CLK_LSP_I2C4_PCLK 658 +#define EIC7700_CLK_LSP_I2C5_PCLK 659 +#define EIC7700_CLK_LSP_I2C6_PCLK 660 +#define EIC7700_CLK_LSP_I2C7_PCLK 661 +#define EIC7700_CLK_LSP_I2C8_PCLK 662 +#define EIC7700_CLK_LSP_I2C9_PCLK 663 +#define EIC7700_CLK_LSP_WDT0_PCLK 664 +#define EIC7700_CLK_LSP_WDT1_PCLK 665 +#define EIC7700_CLK_LSP_WDT2_PCLK 666 +#define EIC7700_CLK_LSP_WDT3_PCLK 667 +#define EIC7700_CLK_LSP_SSI0_PCLK 668 +#define EIC7700_CLK_LSP_SSI1_PCLK 669 +#define EIC7700_CLK_LSP_PVT_PCLK 670 +#define EIC7700_CLK_AON_I2C0_PCLK 671 +#define EIC7700_CLK_AON_I2C1_PCLK 672 +#define EIC7700_CLK_LSP_UART0_PCLK 673 +#define EIC7700_CLK_LSP_UART1_PCLK 674 +#define EIC7700_CLK_LSP_UART2_PCLK 675 +#define EIC7700_CLK_LSP_UART3_PCLK 676 +#define EIC7700_CLK_LSP_UART4_PCLK 677 +#define EIC7700_CLK_LSP_TIMER_PCLK 678 //LSP timer +#define EIC7700_CLK_LSP_FAN_PCLK 679 +#define EIC7700_CLK_DSP_ACLK_0 680 +#define EIC7700_CLK_DSP_ACLK_1 681 +#define EIC7700_CLK_DSP_ACLK_2 682 +#define EIC7700_CLK_DSP_ACLK_3 683 + +#define EIC7700_CLK_VC_JE_PCLK 685 +#define EIC7700_CLK_VC_JD_PCLK 686 +#define EIC7700_CLK_VC_VE_PCLK 687 +#define EIC7700_CLK_VC_VD_PCLK 688 +#define EIC7700_CLK_VC_MON_PCLK 689 + +#define EIC7700_CLK_HSP_DMA0_CLK 690 + +#define EIC7700_NR_CLKS 700 + +/* run frquency */ +#define CLK_FREQ_1800M 1800000000 +#define CLK_FREQ_1700M 1700000000 +#define CLK_FREQ_1600M 1600000000 +#define CLK_FREQ_1500M 1500000000 +#define CLK_FREQ_1400M 1400000000 +#define CLK_FREQ_1300M 1300000000 +#define CLK_FREQ_1200M 1200000000 +#define CLK_FREQ_1000M 1000000000 +#define CLK_FREQ_900M 900000000 +#define CLK_FREQ_800M 800000000 +#define CLK_FREQ_700M 700000000 +#define CLK_FREQ_600M 600000000 +#define CLK_FREQ_500M 500000000 +#define CLK_FREQ_400M 400000000 +#define CLK_FREQ_200M 200000000 +#define CLK_FREQ_100M 100000000 +#define CLK_FREQ_24M 24000000 + +#define APLL_HIGH_FREQ 983040000 +#define APLL_LOW_FREQ 225792000 + +#endif /*endif __DTS_EIC7700_CLOCK_H*/ diff --git a/include/dt-bindings/interconnect/eic7700.h b/include/dt-bindings/interconnect/eic7700.h new file mode 100644 index 0000000000000..984b7cc0840f9 --- /dev/null +++ b/include/dt-bindings/interconnect/eic7700.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Interconnect driver for Eswin EIC7700 SoC + * + * Copyright (C) 2022 Beiging Eswin Co. Ltd + * Author: Huangyifeng + */ + +#ifndef _DT_BINDINGS_INTERCONNECT_EIC7700_H_ +#define _DT_BINDINGS_INTERCONNECT_EIC7700_H_ + +#define OFFSET0 (0) +#define OFFSET1 (1) +#define OFFSET2 (2) +#define OFFSET3 (3) +#define OFFSET4 (4) +#define OFFSET5 (5) +#define OFFSET6 (6) +#define OFFSET7 (7) +#define OFFSET8 (8) +#define OFFSET9 (9) +#define OFFSET10 (10) +#define OFFSET11 (11) +#define OFFSET12 (12) +#define OFFSET13 (13) +#define OFFSET14 (14) +#define OFFSET15 (15) +#define OFFSET16 (16) +#define OFFSET17 (17) +#define OFFSET18 (18) +#define OFFSET19 (19) +#define OFFSET20 (20) +#define OFFSET21 (21) +#define OFFSET22 (22) +#define OFFSET23 (23) + +#define OFFSET31 (31) + +/*sideband manager module id defination*/ +/*sys noc*/ +#define SBM_AON_SNOC_SP0 0 +#define SBM_DSPT_SNOC 1 +#define SBM_JTAG_SNOC 2 +#define SBM_MCPUT_SNOC_D2D 3 +#define SBM_MCPUT_SNOC_MP 4 +#define SBM_MCPUT_SNOC_SP0 5 +#define SBM_MCPUT_SNOC_SP1 6 +#define SBM_NPU_SNOC_SP0 7 +#define SBM_NPU_SNOC_SP1 8 +#define SBM_PCIET_SNOC_P 9 +#define SBM_SPISLV_PCIET_SNOC 10 +#define SBM_TBU4_SNOC 11 +#define SBM_TCU_SNOC 12 +#define SBM_SNOC_AON 13 +#define SBM_SNOC_DDR0_P1 14 +#define SBM_SNOC_DDR0_P2 15 +#define SBM_SNOC_DDR1_P1 16 +#define SBM_SNOC_DDR1_P2 17 +#define SBM_SNOC_DSPT 18 +#define SBM_SNOC_MCPUT_D2D 19 +#define SBM_SNOC_NPU 20 +#define SBM_SNOC_PCIET 21 + +/*cfg noc*/ +#define SBM_CLMM 30 +#define SBM_CNOC_AON 31 +#define SBM_CNOC_DDRT0_CTRL 32 +#define SBM_CNOC_DDRT0_PHY 33 +#define SBM_CNOC_DDRT1_CTRL 34 +#define SBM_CNOC_DDRT1_PHY 35 +#define SBM_CNOC_DSPT 36 +#define SBM_CNOC_GPU 37 +#define SBM_CNOC_HSP 38 +#define SBM_CNOC_LSP_APB2 39 +#define SBM_CNOC_LSP_APB3 40 +#define SBM_CNOC_LSP_APB4 41 +#define SBM_CNOC_LSP_APB6 42 +#define SBM_CNOC_MCPUT_D2D 43 +#define SBM_CNOC_NPU 44 +#define SBM_CNOC_PCIET_P 45 +#define SBM_CNOC_PCIET_X 46 +#define SBM_CNOC_TCU 47 +#define SBM_CNOC_VC 48 +#define SBM_CNOC_VI 49 +#define SBM_CNOC_VO 50 + +/*llc noc*/ +#define SBM_LNOC_NPU_LLC0 60 +#define SBM_LNOC_NPU_LLC1 61 +#define SBM_LNOC_DDRT0_P0 62 +#define SBM_LNOC_DDRT1_P0 63 + +/*media noc*/ +#define SBM_MNOC_GPU 70 +#define SBM_MNOC_TBU2 71 +#define SBM_MNOC_VC 72 +#define SBM_MNOC_DDRT0_P3 73 +#define SBM_MNOC_DDRT1_P3 74 + +/*realtime noc*/ +#define SBM_RNOC_TBU0 80 +#define SBM_RNOC_VO 81 +#define SBM_RNOC_DDRT0_P4 82 +#define SBM_RNOC_DDRT1_P4 83 + +/*RouteID defination*/ +#define aon_snoc_sp0_I_O 0x0 +#define dspt_snoc_I_O 0x1 +#define jtag_snoc_I_O 0x2 +#define mcput_snoc_d2d_I_O 0x3 +#define mcput_snoc_mp_I_O 0x4 +#define mcput_snoc_sp0_I_O 0x5 +#define mcput_snoc_sp1_I_O 0x6 +#define mnoc_snoc_I_O 0x7 +#define npu_snoc_sp0_I_O 0x8 +#define npu_snoc_sp1_I_O 0x9 +#define pciet_snoc_p_I_O 0xA +#define rnoc_snoc_I_O 0xB +#define spislv_tbu3_snoc_I_O 0xC +#define tbu4_snoc_I_O 0xD +#define tcu_snoc_I_O 0xE +#define RESERVED0 0xF + +#define snoc_aon_T_O 0x0 +#define snoc_cnoc_T_O 0x1 +#define snoc_ddrt0_p1_T_O 0x2 +#define snoc_ddrt0_p2_T_O 0x3 +#define snoc_ddrt1_p1_T_O 0x4 +#define snoc_ddrt1_p2_T_O 0x5 +#define snoc_dspt_T_O 0x6 +#define snoc_lnoc_T_O 0x7 +#define snoc_mcput_d2d_T_O 0x8 +#define snoc_mnoc_T_O 0x9 +#define snoc_npu_T_O 0xA +#define snoc_pciet_T_O 0xB +#define snoc_rnoc_T_O 0xC +#define snoc_service_T_O 0xD +#define RESERVED1 0xE +#define RESERVED2 0xF + +#endif /* _DT_BINDINGS_INTERCONNECT_EIC7700_H_ */ diff --git a/include/dt-bindings/mailbox/eswin-mailbox.h b/include/dt-bindings/mailbox/eswin-mailbox.h new file mode 100755 index 0000000000000..1c82418dbadc0 --- /dev/null +++ b/include/dt-bindings/mailbox/eswin-mailbox.h @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Mailbox 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 . + * + * Authors: HuangYiFeng + */ + +#ifndef _DTS_ESWIN_MAILBOX_H_ +#define _DTS_ESWIN_MAILBOX_H_ + +#define ESWIN_MAILBOX_U84_TO_SCPU_REG_BASE 0x50a00000 /*maibox 0*/ +#define ESWIN_MAILBOX_SCPU_TO_U84_REG_BASE 0x50a10000 /*maibox 1*/ + +#define ESWIN_MAILBOX_U84_TO_LPCPU_REG_BASE 0x50a20000 /*maibox 2*/ +#define ESWIN_MAILBOX_LPCPU_TO_U84_REG_BASE 0x50a30000 /*maibox 3*/ + +#define ESWIN_MAILBOX_U84_TO_NPU_0_REG_BASE 0x50a40000 /*maibox 4*/ +#define ESWIN_MAILBOX_NPU_0_TO_U84_REG_BASE 0x50a50000 /*maibox 5*/ + +#define ESWIN_MAILBOX_U84_TO_NPU_1_REG_BASE 0x50a60000 /*maibox 6*/ +#define ESWIN_MAILBOX_NP1_0_TO_U84_REG_BASE 0x50a70000 /*maibox 7*/ + +#define ESWIN_MAILBOX_U84_TO_DSP_0_REG_BASE 0x50a80000 /*maibox 8*/ +#define ESWIN_MAILBOX_DSP_0_TO_U84_REG_BASE 0x50a90000 /*maibox 9*/ + +#define ESWIN_MAILBOX_U84_TO_DSP_1_REG_BASE 0x50aa0000 /*maibox 10*/ +#define ESWIN_MAILBOX_DSP_1_TO_U84_REG_BASE 0x50ab0000 /*maibox 11*/ + +#define ESWIN_MAILBOX_U84_TO_DSP_2_REG_BASE 0x50ac0000 /*maibox 12*/ +#define ESWIN_MAILBOX_DSP_2_TO_U84_REG_BASE 0x50ad0000 /*maibox 13*/ + +#define ESWIN_MAILBOX_U84_TO_DSP_3_REG_BASE 0x50ae0000 /*maibox 14*/ +#define ESWIN_MAILBOX_DSP_3_TO_U84_REG_BASE 0x50af0000 /*maibox 15*/ + +#define BIT0 (1 << 0) +#define BIT1 (1 << 1) +#define BIT2 (1 << 2) +#define BIT3 (1 << 3) +#define BIT4 (1 << 4) +#define BIT5 (1 << 5) +#define BIT6 (1 << 6) +#define BIT7 (1 << 7) +#define BIT8 (1 << 8) +#define BIT9 (1 << 9) +#define BIT10 (1 << 10) +#define BIT11 (1 << 11) +#define BIT12 (1 << 12) +#define BIT13 (1 << 13) +#define BIT14 (1 << 14) +#define BIT31 (1 << 31) + +#define ESWIN_MAILBOX_WR_LOCK_BIT_U84 BIT0 +#define ESWIN_MAILBOX_WR_LOCK_BIT_SCPU BIT1 +#define ESWIN_MAILBOX_WR_LOCK_BIT_LPCPU BIT2 +#define ESWIN_MAILBOX_WR_LOCK_BIT_NPU_0 BIT3 +#define ESWIN_MAILBOX_WR_LOCK_BIT_NPU_1 BIT4 +#define ESWIN_MAILBOX_WR_LOCK_BIT_DSP_0 BIT5 +#define ESWIN_MAILBOX_WR_LOCK_BIT_DSP_1 BIT6 +#define ESWIN_MAILBOX_WR_LOCK_BIT_DSP_2 BIT7 +#define ESWIN_MAILBOX_WR_LOCK_BIT_DSP_3 BIT8 + + +#define ESWIN_MAIBOX_U84_IRQ_BIT BIT0 +#define ESWIN_MAIBOX_SCPU_IRQ_BIT BIT1 +#define ESWIN_MAIBOX_LPCPU_IRQ_BIT BIT2 +#define ESWIN_MAIBOX_NPU_0_IRQ_BIT BIT3 +#define ESWIN_MAIBOX_NPU_1_IRQ_BIT BIT4 +#define ESWIN_MAIBOX_DSP_0_IRQ_BIT BIT5 +#define ESWIN_MAIBOX_DSP_1_IRQ_BIT BIT6 +#define ESWIN_MAIBOX_DSP_2_IRQ_BIT BIT7 +#define ESWIN_MAIBOX_DSP_3_IRQ_BIT BIT8 + +#endif /* _DTS_ESWIN_MAILBOX_H_ */ diff --git a/include/dt-bindings/memory/eic7700-sid.h b/include/dt-bindings/memory/eic7700-sid.h new file mode 100644 index 0000000000000..0fa589ec93b19 --- /dev/null +++ b/include/dt-bindings/memory/eic7700-sid.h @@ -0,0 +1,138 @@ +#ifndef DT_BINDINGS_MEMORY_EIC7700_SID_H +#define DT_BINDINGS_MEMORY_EIC7700_SID_H + +#define EIC7700_SID_DMA0 1 + +#define EIC7700_SID_JDEC 2 + +#define EIC7700_SID_JENC 3 + +/* NPU DMA*/ +#define EIC7700_SID_NPU_DMA 4 + +/* NPU-E31 */ +#define EIC7700_SID_NPU_E31 5 + +/* Video In */ +#define EIC7700_SID_ISP0 6 + +//#define EIC7700_SID_ISP1 EIC7700_SID_ISP0 + +#define EIC7700_SID_DW 8 + +#define EIC7700_SID_DVP 9 + +/* High Speed */ +#define EIC7700_SID_USB0 10 + +#define EIC7700_SID_USB1 11 + +#define EIC7700_SID_ETH0 12 + +#define EIC7700_SID_ETH1 13 + +#define EIC7700_SID_SATA 14 + +#define EIC7700_SID_EMMC0 15 + +#define EIC7700_SID_SD0 16 + +#define EIC7700_SID_SD1 17 + + +/* DSP */ +#define EIC7700_SID_DSP_0 18 +#define EIC7700_SID_DSP_1 19 +#define EIC7700_SID_DSP_2 20 +#define EIC7700_SID_DSP_3 21 + +/* CODEC */ +//#define EIC7700_SID_VDEC EIC7700_SID_JDEC + +//#define EIC7700_SID_VENC EIC7700_SID_JENC + +/*** AON subsystem ***/ +/* Secure CPU */ +#define EIC7700_SID_SCPU 24 +#define SCPU_SID_REG_OFFSET 0x1004 + +/* Low power CPU */ +#define EIC7700_SID_LCPU 25 +#define LCPU_SID_REG_OFFSET 0x2004 + +/* Always on, DMA1 */ +#define EIC7700_SID_DMA1 26 +#define DMA1_SID_REG_OFFSET 0x3004 + +/* crypt */ +//#define EIC7700_SID_CRYPT EIC7700_SID_SCPU +#define CRYPT_SID_REG_OFFSET 0x4004 + +///*** for iova mapping test ***/ +//#define EIC7700_SID_DEV_FOO_A 28 +//#define EIC7700_SID_DEV_FOO_B 29 +//#define EIC7700_SID_DEV_FOO_FOR_DIE1 30 + + +/*** tbu id ***/ +/* tbu_id: bit[3:0] is for major, bit[7:4] is for minor; + For example, tbu of dsp3 is tbu7_3, the bu 0x73. It measn tbu7_3 +*/ +#define EIC7700_TBUID_0x0 0x0 + +#define EIC7700_TBUID_0x10 0x10 +#define EIC7700_TBUID_0x11 0x11 +#define EIC7700_TBUID_0x12 0x12 +#define EIC7700_TBUID_0x13 0x13 + +#define EIC7700_TBUID_0x2 0x2 + +#define EIC7700_TBUID_0x3 0x3 + +#define EIC7700_TBUID_0x4 0x4 + +#define EIC7700_TBUID_0x5 0x5 + +#define EIC7700_TBUID_0x70 0x70 +#define EIC7700_TBUID_0x71 0x71 +#define EIC7700_TBUID_0x72 0x72 +#define EIC7700_TBUID_0x73 0x73 + +#define EIC7700_TBUID_0xF00 0xF00 // simulation for EIC7700_SID_DEV_FOO_A/B, No real tbu attached infact + + +/* For better use by devices in dts, create tbu alias for devices*/ +#define EIC7700_TBUID_ISP EIC7700_TBUID_0x0 +#define EIC7700_TBUID_DW EIC7700_TBUID_ISP + +#define EIC7700_TBUID_VDEC EIC7700_TBUID_0x10 +#define EIC7700_TBUID_VENC EIC7700_TBUID_0x11 +#define EIC7700_TBUID_JENC EIC7700_TBUID_0x12 +#define EIC7700_TBUID_JDEC EIC7700_TBUID_0x13 + +//high speed modules share the same tbu2 +#define EIC7700_TBUID_DMA0 EIC7700_TBUID_0x2 +#define EIC7700_TBUID_USB EIC7700_TBUID_DMA0 +#define EIC7700_TBUID_ETH EIC7700_TBUID_DMA0 +#define EIC7700_TBUID_SATA EIC7700_TBUID_DMA0 +#define EIC7700_TBUID_EMMC EIC7700_TBUID_DMA0 +#define EIC7700_TBUID_SD EIC7700_TBUID_DMA0 + +#define EIC7700_TBUID_PCIE EIC7700_TBUID_0x3 + +//scpu, crypto, lpcpu, dma1 share the same tbu4 +#define EIC7700_TBUID_SCPU EIC7700_TBUID_0x4 +#define EIC7700_TBUID_CRYPT EIC7700_TBUID_SCPU +#define EIC7700_TBUID_DMA1 EIC7700_TBUID_SCPU +#define EIC7700_TBUID_LPCPU EIC7700_TBUID_SCPU + +//npu +#define EIC7700_TBUID_NPU EIC7700_TBUID_0x5 + +//dsp +#define EIC7700_TBUID_DSP0 EIC7700_TBUID_0x70 +#define EIC7700_TBUID_DSP1 EIC7700_TBUID_0x71 +#define EIC7700_TBUID_DSP2 EIC7700_TBUID_0x72 +#define EIC7700_TBUID_DSP3 EIC7700_TBUID_0x73 + +#endif diff --git a/include/dt-bindings/reset/eic7700-syscrg.h b/include/dt-bindings/reset/eic7700-syscrg.h new file mode 100755 index 0000000000000..ea1ff1874a853 --- /dev/null +++ b/include/dt-bindings/reset/eic7700-syscrg.h @@ -0,0 +1,693 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN SysCrg Definition + * + * 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 . + * + * Authors: HuangYiFeng + */ + +#ifndef __DT_ESWIN_EIC7700_SYSCRG_H__ +#define __DT_ESWIN_EIC7700_SYSCRG_H__ + +/*REG OFFSET OF SYS-CRG*/ + +#define EIC7700_REG_OFFSET_SPLL0_CFG_0 0X0000 +#define EIC7700_REG_OFFSET_SPLL0_CFG_1 0X0004 +#define EIC7700_REG_OFFSET_SPLL0_CFG_2 0X0008 +#define EIC7700_REG_OFFSET_SPLL0_DSKEWCAL 0X000C +#define EIC7700_REG_OFFSET_SPLL0_SSC 0X0010 +#define EIC7700_REG_OFFSET_SPLL1_CFG_0 0X0014 +#define EIC7700_REG_OFFSET_SPLL1_CFG_1 0X0018 +#define EIC7700_REG_OFFSET_SPLL1_CFG_2 0X001C +#define EIC7700_REG_OFFSET_SPLL1_DSKEWCAL 0X0020 +#define EIC7700_REG_OFFSET_SPLL1_SSC 0X0024 +#define EIC7700_REG_OFFSET_SPLL2_CFG_0 0X0028 +#define EIC7700_REG_OFFSET_SPLL2_CFG_1 0X002C +#define EIC7700_REG_OFFSET_SPLL2_CFG_2 0X0030 +#define EIC7700_REG_OFFSET_SPLL2_DSKEWCAL 0X0034 +#define EIC7700_REG_OFFSET_SPLL2_SSC 0X0038 +#define EIC7700_REG_OFFSET_VPLL_CFG_0 0X003C +#define EIC7700_REG_OFFSET_VPLL_CFG_1 0X0040 +#define EIC7700_REG_OFFSET_VPLL_CFG_2 0X0044 +#define EIC7700_REG_OFFSET_VPLL_DSKEWCAL 0X0048 +#define EIC7700_REG_OFFSET_VPLL_SSC 0X004C +#define EIC7700_REG_OFFSET_APLL_CFG_0 0X0050 +#define EIC7700_REG_OFFSET_APLL_CFG_1 0X0054 +#define EIC7700_REG_OFFSET_APLL_CFG_2 0X0058 +#define EIC7700_REG_OFFSET_APLL_DSKEWCAL 0X005C +#define EIC7700_REG_OFFSET_APLL_SSC 0X0060 +#define EIC7700_REG_OFFSET_MCPUT_PLL_CFG_0 0X0064 +#define EIC7700_REG_OFFSET_MCPUT_PLL_CFG_1 0X0068 +#define EIC7700_REG_OFFSET_MCPUT_PLL_CFG_2 0X006C +#define EIC7700_REG_OFFSET_MCPUT_PLL_DSKEWCAL 0X0070 +#define EIC7700_REG_OFFSET_MCPUT_PLL_SSC 0X0074 +#define EIC7700_REG_OFFSET_DDRT_PLL_CFG_0 0X0078 +#define EIC7700_REG_OFFSET_DDRT_PLL_CFG_1 0X007C +#define EIC7700_REG_OFFSET_DDRT_PLL_CFG_2 0X0080 +#define EIC7700_REG_OFFSET_DDRT_PLL_DSKEWCAL 0X0084 +#define EIC7700_REG_OFFSET_DDRT_PLL_SSC 0X0088 +#define EIC7700_REG_OFFSET_PLL_STATUS 0X00A4 +#define EIC7700_REG_OFFSET_NOC_CLK_CTRL 0X100 +#define EIC7700_REG_OFFSET_BOOTSPI_CLK_CTRL 0X104 +#define EIC7700_REG_OFFSET_BOOTSPI_CFGCLK_CTRL 0X108 +#define EIC7700_REG_OFFSET_SCPU_CORECLK_CTRL 0X10C +#define EIC7700_REG_OFFSET_SCPU_BUSCLK_CTRL 0X110 +#define EIC7700_REG_OFFSET_LPCPU_CORECLK_CTRL 0X114 +#define EIC7700_REG_OFFSET_LPCPU_BUSCLK_CTRL 0X118 +#define EIC7700_REG_OFFSET_TCU_ACLK_CTRL 0X11C +#define EIC7700_REG_OFFSET_TCU_CFG_CTRL 0X120 +#define EIC7700_REG_OFFSET_DDR_CLK_CTRL 0X124 +#define EIC7700_REG_OFFSET_DDR1_CLK_CTRL 0X128 +#define EIC7700_REG_OFFSET_GPU_ACLK_CTRL 0X12C +#define EIC7700_REG_OFFSET_GPU_CFG_CTRL 0X130 +#define EIC7700_REG_OFFSET_GPU_GRAY_CTRL 0X134 +#define EIC7700_REG_OFFSET_DSP_ACLK_CTRL 0X138 +#define EIC7700_REG_OFFSET_DSP_CFG_CTRL 0X13C +#define EIC7700_REG_OFFSET_D2D_ACLK_CTRL 0X140 +#define EIC7700_REG_OFFSET_D2D_CFG_CTRL 0X144 +#define EIC7700_REG_OFFSET_HSP_ACLK_CTRL 0X148 +#define EIC7700_REG_OFFSET_HSP_CFG_CTRL 0X14C +#define EIC7700_REG_OFFSET_SATA_RBC_CTRL 0X150 +#define EIC7700_REG_OFFSET_SATA_OOB_CTRL 0X154 +#define EIC7700_REG_OFFSET_ETH0_CTRL 0X158 +#define EIC7700_REG_OFFSET_ETH1_CTRL 0X15C +#define EIC7700_REG_OFFSET_MSHC0_CORECLK_CTRL 0X160 +#define EIC7700_REG_OFFSET_MSHC1_CORECLK_CTRL 0X164 +#define EIC7700_REG_OFFSET_MSHC2_CORECLK_CTRL 0X168 +#define EIC7700_REG_OFFSET_MSHC_USB_SLWCLK 0X16C +#define EIC7700_REG_OFFSET_PCIE_ACLK_CTRL 0X170 +#define EIC7700_REG_OFFSET_PCIE_CFG_CTRL 0X174 +#define EIC7700_REG_OFFSET_NPU_ACLK_CTRL 0X178 +#define EIC7700_REG_OFFSET_NPU_LLC_CTRL 0X17C +#define EIC7700_REG_OFFSET_NPU_CORE_CTRL 0X180 +#define EIC7700_REG_OFFSET_VI_DWCLK_CTRL 0X184 +#define EIC7700_REG_OFFSET_VI_ACLK_CTRL 0X188 +#define EIC7700_REG_OFFSET_VI_DIG_ISP_CLK_CTRL 0X18C +#define EIC7700_REG_OFFSET_VI_DVP_CLK_CTRL 0X190 +#define EIC7700_REG_OFFSET_VI_SHUTTER0 0X194 +#define EIC7700_REG_OFFSET_VI_SHUTTER1 0X198 +#define EIC7700_REG_OFFSET_VI_SHUTTER2 0X19C +#define EIC7700_REG_OFFSET_VI_SHUTTER3 0X1A0 +#define EIC7700_REG_OFFSET_VI_SHUTTER4 0X1A4 +#define EIC7700_REG_OFFSET_VI_SHUTTER5 0X1A8 +#define EIC7700_REG_OFFSET_VI_PHY_CLKCTRL 0X1AC +#define EIC7700_REG_OFFSET_VO_ACLK_CTRL 0X1B0 +#define EIC7700_REG_OFFSET_VO_IESMCLK_CTRL 0X1B4 +#define EIC7700_REG_OFFSET_VO_PIXEL_CTRL 0X1B8 +#define EIC7700_REG_OFFSET_VO_MCLK_CTRL 0X1BC +#define EIC7700_REG_OFFSET_VO_PHY_CLKCTRL 0X1C0 +#define EIC7700_REG_OFFSET_VC_ACLK_CTRL 0X1C4 +#define EIC7700_REG_OFFSET_VCDEC_ROOTCLK_CTRL 0X1C8 +#define EIC7700_REG_OFFSET_G2D_CTRL 0X1CC +#define EIC7700_REG_OFFSET_VC_CLKEN_CTRL 0X1D0 +#define EIC7700_REG_OFFSET_JE_CLK_CTRL 0X1D4 +#define EIC7700_REG_OFFSET_JD_CLK_CTRL 0X1D8 +#define EIC7700_REG_OFFSET_VD_CLK_CTRL 0X1DC +#define EIC7700_REG_OFFSET_VE_CLK_CTRL 0X1E0 +#define EIC7700_REG_OFFSET_AON_DMA_CLK_CTRL 0X1E4 +#define EIC7700_REG_OFFSET_TIMER_CLK_CTRL 0X1E8 +#define EIC7700_REG_OFFSET_RTC_CLK_CTRL 0X1EC +#define EIC7700_REG_OFFSET_PKA_CLK_CTRL 0X1F0 +#define EIC7700_REG_OFFSET_SPACC_CLK_CTRL 0X1F4 +#define EIC7700_REG_OFFSET_TRNG_CLK_CTRL 0X1F8 +#define EIC7700_REG_OFFSET_OTP_CLK_CTRL 0X1FC +#define EIC7700_REG_OFFSET_LSP_CLK_EN0 0X200 +#define EIC7700_REG_OFFSET_LSP_CLK_EN1 0X204 +#define EIC7700_REG_OFFSET_U84_CLK_CTRL 0X208 +#define EIC7700_REG_OFFSET_SYSCFG_CLK_CTRL 0X20C +#define EIC7700_REG_OFFSET_I2C0_CLK_CTRL 0X210 +#define EIC7700_REG_OFFSET_I2C1_CLK_CTRL 0X214 +#define EIC7700_REG_OFFSET_DFT_CLK_CTRL 0X280 +#define EIC7700_REG_OFFSET_SYS_SWRST_VALUE 0X300 +#define EIC7700_REG_OFFSET_CLR_RST_STATUS 0X304 +#define EIC7700_REG_OFFSET_DIE_STATUS 0X308 +#define EIC7700_REG_OFFSET_CLR_BOOT_INFO 0X30C +#define EIC7700_REG_OFFSET_SCPU_BOOT_ADDRESS 0X310 +#define EIC7700_REG_OFFSET_LPCPU_BOOT_ADDRESS 0X314 +#define EIC7700_REG_OFFSET_NPUE31_BOOT_ADDRESS 0X318 +#define EIC7700_REG_OFFSET_U84_BOOT_ADDRESS0_HI 0X31C +#define EIC7700_REG_OFFSET_U84_BOOT_ADDRESS0_LOW 0X320 +#define EIC7700_REG_OFFSET_U84_BOOT_ADDRESS1_HI 0X324 +#define EIC7700_REG_OFFSET_U84_BOOT_ADDRESS1_LOW 0X328 +#define EIC7700_REG_OFFSET_U84_BOOT_ADDRESS2_HI 0X32C +#define EIC7700_REG_OFFSET_U84_BOOT_ADDRESS2_LOW 0X330 +#define EIC7700_REG_OFFSET_U84_BOOT_ADDRESS3_HI 0X334 +#define EIC7700_REG_OFFSET_U84_BOOT_ADDRESS3_LOW 0X338 +#define EIC7700_REG_OFFSET_BOOT_SEL_STAT 0X33C +#define EIC7700_REG_OFFSET_BOOT_SPI_CFG 0X340 +#define EIC7700_REG_OFFSET_SNOC_RST_CTRL 0X400 +#define EIC7700_REG_OFFSET_GPU_RST_CTRL 0X404 +#define EIC7700_REG_OFFSET_DSP_RST_CTRL 0X408 +#define EIC7700_REG_OFFSET_D2D_RST_CTRL 0X40C +#define EIC7700_REG_OFFSET_DDR_RST_CTRL 0X410 +#define EIC7700_REG_OFFSET_TCU_RST_CTRL 0X414 +#define EIC7700_REG_OFFSET_NPU_RST_CTRL 0X418 +#define EIC7700_REG_OFFSET_HSPDMA_RST_CTRL 0X41C +#define EIC7700_REG_OFFSET_PCIE_RST_CTRL 0X420 +#define EIC7700_REG_OFFSET_I2C_RST_CTRL 0X424 +#define EIC7700_REG_OFFSET_FAN_RST_CTRL 0X428 +#define EIC7700_REG_OFFSET_PVT_RST_CTRL 0X42C +#define EIC7700_REG_OFFSET_MBOX_RST_CTRL 0X430 +#define EIC7700_REG_OFFSET_UART_RST_CTRL 0X434 +#define EIC7700_REG_OFFSET_GPIO_RST_CTRL 0X438 +#define EIC7700_REG_OFFSET_TIMER_RST_CTRL 0X43C +#define EIC7700_REG_OFFSET_SSI_RST_CTRL 0X440 +#define EIC7700_REG_OFFSET_WDT_RST_CTRL 0X444 +#define EIC7700_REG_OFFSET_LSP_CFGRST_CTRL 0X448 +#define EIC7700_REG_OFFSET_U84_RST_CTRL 0X44C +#define EIC7700_REG_OFFSET_SCPU_RST_CTRL 0X450 +#define EIC7700_REG_OFFSET_LPCPU_RST_CTRL 0X454 +#define EIC7700_REG_OFFSET_VC_RST_CTRL 0X458 +#define EIC7700_REG_OFFSET_JD_RST_CTRL 0X45C +#define EIC7700_REG_OFFSET_JE_RST_CTRL 0X460 +#define EIC7700_REG_OFFSET_VD_RST_CTRL 0X464 +#define EIC7700_REG_OFFSET_VE_RST_CTRL 0X468 +#define EIC7700_REG_OFFSET_G2D_RST_CTRL 0X46C +#define EIC7700_REG_OFFSET_VI_RST_CTRL 0X470 +#define EIC7700_REG_OFFSET_DVP_RST_CTRL 0X474 +#define EIC7700_REG_OFFSET_ISP0_RST_CTRL 0X478 +#define EIC7700_REG_OFFSET_ISP1_RST_CTRL 0X47C +#define EIC7700_REG_OFFSET_SHUTTER_RST_CTRL 0X480 +#define EIC7700_REG_OFFSET_VO_PHYRST_CTRL 0X484 +#define EIC7700_REG_OFFSET_VO_I2SRST_CTRL 0X488 +#define EIC7700_REG_OFFSET_VO_RST_CTRL 0X48C +#define EIC7700_REG_OFFSET_BOOTSPI_RST_CTRL 0X490 +#define EIC7700_REG_OFFSET_I2C1_RST_CTRL 0X494 +#define EIC7700_REG_OFFSET_I2C0_RST_CTRL 0X498 +#define EIC7700_REG_OFFSET_DMA1_RST_CTRL 0X49C +#define EIC7700_REG_OFFSET_FPRT_RST_CTRL 0X4A0 +#define EIC7700_REG_OFFSET_HBLOCK_RST_CTRL 0X4A4 +#define EIC7700_REG_OFFSET_SECSR_RST_CTRL 0X4A8 +#define EIC7700_REG_OFFSET_OTP_RST_CTRL 0X4AC +#define EIC7700_REG_OFFSET_PKA_RST_CTRL 0X4B0 +#define EIC7700_REG_OFFSET_SPACC_RST_CTRL 0X4B4 +#define EIC7700_REG_OFFSET_TRNG_RST_CTRL 0X4B8 +#define EIC7700_REG_OFFSET_TIMER0_RST_CTRL 0X4C0 +#define EIC7700_REG_OFFSET_TIMER1_RST_CTRL 0X4C4 +#define EIC7700_REG_OFFSET_TIMER2_RST_CTRL 0X4C8 +#define EIC7700_REG_OFFSET_TIMER3_RST_CTRL 0X4CC +#define EIC7700_REG_OFFSET_RTC_RST_CTRL 0X4D0 +#define EIC7700_REG_OFFSET_MNOC_RST_CTRL 0X4D4 +#define EIC7700_REG_OFFSET_RNOC_RST_CTRL 0X4D8 +#define EIC7700_REG_OFFSET_CNOC_RST_CTRL 0X4DC +#define EIC7700_REG_OFFSET_LNOC_RST_CTRL 0X4E0 + +/* + * RESET DEV ID FOR EACH RESET CONSUMER + * + */ +#define SNOC_RST_CTRL 0X00 +#define GPU_RST_CTRL 0X01 +#define DSP_RST_CTRL 0X02 +#define D2D_RST_CTRL 0X03 +#define DDR_RST_CTRL 0X04 +#define TCU_RST_CTRL 0X05 +#define NPU_RST_CTRL 0X06 +#define HSPDMA_RST_CTRL 0X07 +#define PCIE_RST_CTRL 0X08 +#define I2C_RST_CTRL 0X09 +#define FAN_RST_CTRL 0X0A +#define PVT_RST_CTRL 0X0B +#define MBOX_RST_CTRL 0X0C +#define UART_RST_CTRL 0X0D +#define GPIO_RST_CTRL 0X0E +#define TIMER_RST_CTRL 0X0F +#define SSI_RST_CTRL 0X10 +#define WDT_RST_CTRL 0X11 +#define LSP_CFGRST_CTRL 0X12 +#define U84_RST_CTRL 0X13 +#define SCPU_RST_CTRL 0X14 +#define LPCPU_RST_CTRL 0X15 +#define VC_RST_CTRL 0X16 +#define JD_RST_CTRL 0X17 +#define JE_RST_CTRL 0X18 +#define VD_RST_CTRL 0X19 +#define VE_RST_CTRL 0X1A +#define G2D_RST_CTRL 0X1B +#define VI_RST_CTRL 0X1C +#define DVP_RST_CTRL 0X1D +#define ISP0_RST_CTRL 0X1E +#define ISP1_RST_CTRL 0X1F +#define SHUTTER_RST_CTRL 0X20 +#define VO_PHYRST_CTRL 0X21 +#define VO_I2SRST_CTRL 0X22 +#define VO_RST_CTRL 0X23 +#define BOOTSPI_RST_CTRL 0X24 +#define I2C1_RST_CTRL 0X25 +#define I2C0_RST_CTRL 0X26 +#define DMA1_RST_CTRL 0X27 +#define FPRT_RST_CTRL 0X28 +#define HBLOCK_RST_CTRL 0X29 +#define SECSR_RST_CTRL 0X2A +#define OTP_RST_CTRL 0X2B +#define PKA_RST_CTRL 0X2C +#define SPACC_RST_CTRL 0X2D +#define TRNG_RST_CTRL 0X2E +#define RESERVED 0X2F +#define TIMER0_RST_CTRL 0X30 +#define TIMER1_RST_CTRL 0X31 +#define TIMER2_RST_CTRL 0X32 +#define TIMER3_RST_CTRL 0X33 +#define RTC_RST_CTRL 0X34 +#define MNOC_RST_CTRL 0X35 +#define RNOC_RST_CTRL 0X36 +#define CNOC_RST_CTRL 0X37 +#define LNOC_RST_CTRL 0X38 + +#define BIT0 (1 << 0) +#define BIT1 (1 << 1) +#define BIT2 (1 << 2) +#define BIT3 (1 << 3) +#define BIT4 (1 << 4) +#define BIT5 (1 << 5) +#define BIT6 (1 << 6) +#define BIT7 (1 << 7) +#define BIT8 (1 << 8) +#define BIT9 (1 << 9) +#define BIT10 (1 << 10) +#define BIT11 (1 << 11) +#define BIT12 (1 << 12) +#define BIT13 (1 << 13) +#define BIT14 (1 << 14) +#define BIT15 (1 << 15) +#define BIT16 (1 << 16) +#define BIT17 (1 << 17) +#define BIT18 (1 << 18) +#define BIT19 (1 << 19) +#define BIT20 (1 << 20) +#define BIT21 (1 << 21) +#define BIT22 (1 << 22) +#define BIT23 (1 << 23) +#define BIT24 (1 << 24) +#define BIT25 (1 << 25) +#define BIT26 (1 << 26) +#define BIT27 (1 << 27) +#define BIT28 (1 << 28) +#define BIT29 (1 << 29) +#define BIT30 (1 << 30) +#define BIT31 (1 << 31) + +/* + CONSUMER RESET CONTROL BIT +*/ +/*SNOC*/ +#define SW_NOC_NSP_RSTN BIT0 +#define SW_NOC_CFG_RSTN BIT1 +#define SW_RNOC_NSP_RSTN BIT2 +#define SW_SNOC_TCU_ARSTN BIT3 +#define SW_SNOC_U84_ARSTN BIT4 +#define SW_SNOC_PCIET_XSRSTN BIT5 +#define SW_SNOC_PCIET_XMRSTN BIT6 +#define SW_SNOC_PCIET_PRSTN BIT7 +#define SW_SNOC_NPU_ARSTN BIT8 +#define SW_SNOC_JTAG_ARSTN BIT9 +#define SW_SNOC_DSPT_ARSTN BIT10 +#define SW_SNOC_DDRC1_P2_ARSTN BIT11 +#define SW_SNOC_DDRC1_P1_ARSTN BIT12 +#define SW_SNOC_DDRC0_P2_ARSTN BIT13 +#define SW_SNOC_DDRC0_P1_ARSTN BIT14 +#define SW_SNOC_D2D_ARSTN BIT15 +#define SW_SNOC_AON_ARSTN BIT16 + +/*GPU*/ +#define SW_GPU_AXI_RSTN BIT0 +#define SW_GPU_CFG_RSTN BIT1 +#define SW_GPU_GRAY_RSTN BIT2 +#define SW_GPU_JONES_RSTN BIT3 +#define SW_GPU_SPU_RSTN BIT4 + +/*DSP*/ +#define SW_DSP_AXI_RSTN BIT0 +#define SW_DSP_CFG_RSTN BIT1 +#define SW_DSP_DIV4_RSTN BIT2 +#define SW_DSP_DIV_RSTN_0 BIT4 +#define SW_DSP_DIV_RSTN_1 BIT5 +#define SW_DSP_DIV_RSTN_2 BIT6 +#define SW_DSP_DIV_RSTN_3 BIT7 + +/*D2D*/ +#define SW_D2D_AXI_RSTN BIT0 +#define SW_D2D_CFG_RSTN BIT1 +#define SW_D2D_PRST_N BIT2 +#define SW_D2D_RAW_PCS_RST_N BIT4 +#define SW_D2D_RX_RST_N BIT5 +#define SW_D2D_TX_RST_N BIT6 +#define SW_D2D_CORE_RST_N BIT7 + +/*TCU*/ +#define SW_TCU_AXI_RSTN BIT0 +#define SW_TCU_CFG_RSTN BIT1 +#define TBU_RSTN_0 BIT4 +#define TBU_RSTN_1 BIT5 +#define TBU_RSTN_2 BIT6 +#define TBU_RSTN_3 BIT7 +#define TBU_RSTN_4 BIT8 +#define TBU_RSTN_5 BIT9 +#define TBU_RSTN_6 BIT10 +#define TBU_RSTN_7 BIT11 +#define TBU_RSTN_8 BIT12 +#define TBU_RSTN_9 BIT13 +#define TBU_RSTN_10 BIT14 +#define TBU_RSTN_11 BIT15 +#define TBU_RSTN_12 BIT16 +#define TBU_RSTN_13 BIT17 +#define TBU_RSTN_14 BIT18 +#define TBU_RSTN_15 BIT19 +#define TBU_RSTN_16 BIT20 + +/*NPU*/ +#define SW_NPU_AXI_RSTN BIT0 +#define SW_NPU_CFG_RSTN BIT1 +#define SW_NPU_CORE_RSTN BIT2 +#define SW_NPU_E31CORE_RSTN BIT3 +#define SW_NPU_E31BUS_RSTN BIT4 +#define SW_NPU_E31DBG_RSTN BIT5 +#define SW_NPU_LLC_RSTN BIT6 + +/*HSP DMA*/ +#define SW_HSP_AXI_RSTN BIT0 +#define SW_HSP_CFG_RSTN BIT1 +#define SW_HSP_POR_RSTN BIT2 +#define SW_MSHC0_PHY_RSTN BIT3 +#define SW_MSHC1_PHY_RSTN BIT4 +#define SW_MSHC2_PHY_RSTN BIT5 +#define SW_MSHC0_TXRX_RSTN BIT6 +#define SW_MSHC1_TXRX_RSTN BIT7 +#define SW_MSHC2_TXRX_RSTN BIT8 +#define SW_SATA_ASIC0_RSTN BIT9 +#define SW_SATA_OOB_RSTN BIT10 +#define SW_SATA_PMALIVE_RSTN BIT11 +#define SW_SATA_RBC_RSTN BIT12 +#define SW_DMA0_RST_N BIT13 +#define SW_HSP_DMA0_RSTN BIT14 +#define SW_USB0_VAUX_RSTN BIT15 +#define SW_USB1_VAUX_RSTN BIT16 +#define SW_HSP_SD1_PRSTN BIT17 +#define SW_HSP_SD0_PRSTN BIT18 +#define SW_HSP_EMMC_PRSTN BIT19 +#define SW_HSP_DMA_PRSTN BIT20 +#define SW_HSP_SD1_ARSTN BIT21 +#define SW_HSP_SD0_ARSTN BIT22 +#define SW_HSP_EMMC_ARSTN BIT23 +#define SW_HSP_DMA_ARSTN BIT24 +#define SW_HSP_ETH1_ARSTN BIT25 +#define SW_HSP_ETH0_ARSTN BIT26 +#define SW_HSP_SATA_ARSTN BIT27 + +/*PCIE*/ +#define SW_PCIE_CFG_RSTN BIT0 +#define SW_PCIE_POWERUP_RSTN BIT1 +#define SW_PCIE_PERST_N BIT2 + +/*I2C*/ +#define SW_I2C_RST_N_0 BIT0 +#define SW_I2C_RST_N_1 BIT1 +#define SW_I2C_RST_N_2 BIT2 +#define SW_I2C_RST_N_3 BIT3 +#define SW_I2C_RST_N_4 BIT4 +#define SW_I2C_RST_N_5 BIT5 +#define SW_I2C_RST_N_6 BIT6 +#define SW_I2C_RST_N_7 BIT7 +#define SW_I2C_RST_N_8 BIT8 +#define SW_I2C_RST_N_9 BIT9 + +/*FAN*/ +#define SW_FAN_RST_N BIT0 + +/*PVT*/ +#define SW_PVT_RST_N_0 BIT0 +#define SW_PVT_RST_N_1 BIT1 + +/*MBOX*/ +#define SW_MBOX_RST_N_0 BIT0 +#define SW_MBOX_RST_N_1 BIT1 +#define SW_MBOX_RST_N_2 BIT2 +#define SW_MBOX_RST_N_3 BIT3 +#define SW_MBOX_RST_N_4 BIT4 +#define SW_MBOX_RST_N_5 BIT5 +#define SW_MBOX_RST_N_6 BIT6 +#define SW_MBOX_RST_N_7 BIT7 +#define SW_MBOX_RST_N_8 BIT8 +#define SW_MBOX_RST_N_9 BIT9 +#define SW_MBOX_RST_N_10 BIT10 +#define SW_MBOX_RST_N_11 BIT11 +#define SW_MBOX_RST_N_12 BIT12 +#define SW_MBOX_RST_N_13 BIT13 +#define SW_MBOX_RST_N_14 BIT14 +#define SW_MBOX_RST_N_15 BIT15 + +/*UART*/ +#define SW_UART_RST_N_0 BIT0 +#define SW_UART_RST_N_1 BIT1 +#define SW_UART_RST_N_2 BIT2 +#define SW_UART_RST_N_3 BIT3 +#define SW_UART_RST_N_4 BIT4 + +/*GPIO*/ +/* +#define SW_GPIO_RST_N_0 BIT0 +#define SW_GPIO_RST_N_1 BIT1 +*/ + +/*TIMER*/ +#define SW_TIMER_RST_N BIT0 + +/*SSI*/ +#define SW_SSI_RST_N_0 BIT0 +#define SW_SSI_RST_N_1 BIT1 + +/*WDT*/ +#define SW_WDT_RST_N_0 BIT0 +#define SW_WDT_RST_N_1 BIT1 +#define SW_WDT_RST_N_2 BIT2 +#define SW_WDT_RST_N_3 BIT3 + +/*LSP CFG*/ +#define SW_LSP_CFG_RSTN BIT0 + +/*U84 CFG*/ +#define SW_U84_CORE_RSTN_0 BIT0 +#define SW_U84_CORE_RSTN_1 BIT1 +#define SW_U84_CORE_RSTN_2 BIT2 +#define SW_U84_CORE_RSTN_3 BIT3 +#define SW_U84_BUS_RSTN BIT4 +#define SW_U84_DBG_RSTN BIT5 +#define SW_U84_TRACECOM_RSTN BIT6 +#define SW_U84_TRACE_RSTN_0 BIT8 +#define SW_U84_TRACE_RSTN_1 BIT9 +#define SW_U84_TRACE_RSTN_2 BIT10 +#define SW_U84_TRACE_RSTN_3 BIT11 + +/*SCPU*/ +#define SW_SCPU_CORE_RSTN BIT0 +#define SW_SCPU_BUS_RSTN BIT1 +#define SW_SCPU_DBG_RSTN BIT2 + +/*LPCPU*/ +#define SW_LPCPU_CORE_RSTN BIT0 +#define SW_LPCPU_BUS_RSTN BIT1 +#define SW_LPCPU_DBG_RSTN BIT2 + +/*VC*/ +#define SW_VC_CFG_RSTN BIT0 +#define SW_VC_AXI_RSTN BIT1 +#define SW_VC_MONCFG_RSTN BIT2 + +/*JD*/ +#define SW_JD_CFG_RSTN BIT0 +#define SW_JD_AXI_RSTN BIT1 + +/*JE*/ +#define SW_JE_CFG_RSTN BIT0 +#define SW_JE_AXI_RSTN BIT1 + +/*VD*/ +#define SW_VD_CFG_RSTN BIT0 +#define SW_VD_AXI_RSTN BIT1 + +/*VE*/ +#define SW_VE_AXI_RSTN BIT0 +#define SW_VE_CFG_RSTN BIT1 + +/*G2D*/ +#define SW_G2D_CORE_RSTN BIT0 +#define SW_G2D_CFG_RSTN BIT1 +#define SW_G2D_AXI_RSTN BIT2 + +/*VI*/ +#define SW_VI_AXI_RSTN BIT0 +#define SW_VI_CFG_RSTN BIT1 +#define SW_VI_DWE_RSTN BIT2 + +/*DVP*/ +#define SW_VI_DVP_RSTN BIT0 + +/*ISP0*/ +#define SW_VI_ISP0_RSTN BIT0 + +/*ISP1*/ +#define SW_VI_ISP1_RSTN BIT0 + +/*SHUTTR*/ +#define SW_VI_SHUTTER_RSTN_0 BIT0 +#define SW_VI_SHUTTER_RSTN_1 BIT1 +#define SW_VI_SHUTTER_RSTN_2 BIT2 +#define SW_VI_SHUTTER_RSTN_3 BIT3 +#define SW_VI_SHUTTER_RSTN_4 BIT4 +#define SW_VI_SHUTTER_RSTN_5 BIT5 + +/*VO PHY*/ +#define SW_VO_MIPI_PRSTN BIT0 +#define SW_VO_PRSTN BIT1 +#define SW_VO_HDMI_PRSTN BIT3 +#define SW_HDMI_PHYCTRL_RSTN BIT4 +#define SW_VO_HDMI_RSTN BIT5 + +/*VO I2S*/ +#define SW_VO_I2S_RSTN BIT0 +#define SW_VO_I2S_PRSTN BIT1 + +/*VO*/ +#define SW_VO_AXI_RSTN BIT0 +#define SW_VO_CFG_RSTN BIT1 +#define SW_VO_DC_RSTN BIT2 +#define SW_VO_DC_PRSTN BIT3 + +/*BOOTSPI*/ +#define SW_BOOTSPI_HRSTN BIT0 +#define SW_BOOTSPI_RSTN BIT1 + +/*I2C1*/ +#define SW_I2C1_PRSTN BIT0 + +/*I2C0*/ +#define SW_I2C0_PRSTN BIT0 + +/*DMA1*/ +#define SW_DMA1_ARSTN BIT0 +#define SW_DMA1_HRSTN BIT1 + +/*FPRT*/ +#define SW_FP_PRT_HRSTN BIT0 + +/*HBLOCK*/ +#define SW_HBLOCK_HRSTN BIT0 + +/*SECSR*/ +#define SW_SECSR_HRSTN BIT0 + +/*OTP*/ +#define SW_OTP_PRSTN BIT0 + +/*PKA*/ +#define SW_PKA_HRSTN BIT0 + +/*SPACC*/ +#define SW_SPACC_RSTN BIT0 + +/*TRNG*/ +#define SW_TRNG_HRSTN BIT0 + +/*TIMER0*/ +#define SW_TIMER0_RSTN_0 BIT0 +#define SW_TIMER0_RSTN_1 BIT1 +#define SW_TIMER0_RSTN_2 BIT2 +#define SW_TIMER0_RSTN_3 BIT3 +#define SW_TIMER0_RSTN_4 BIT4 +#define SW_TIMER0_RSTN_5 BIT5 +#define SW_TIMER0_RSTN_6 BIT6 +#define SW_TIMER0_RSTN_7 BIT7 +#define SW_TIMER0_PRSTN BIT8 + +/*TIMER1*/ +#define SW_TIMER1_RSTN_0 BIT0 +#define SW_TIMER1_RSTN_1 BIT1 +#define SW_TIMER1_RSTN_2 BIT2 +#define SW_TIMER1_RSTN_3 BIT3 +#define SW_TIMER1_RSTN_4 BIT4 +#define SW_TIMER1_RSTN_5 BIT5 +#define SW_TIMER1_RSTN_6 BIT6 +#define SW_TIMER1_RSTN_7 BIT7 +#define SW_TIMER1_PRSTN BIT8 + +/*TIMER2*/ +#define SW_TIMER2_RSTN_0 BIT0 +#define SW_TIMER2_RSTN_1 BIT1 +#define SW_TIMER2_RSTN_2 BIT2 +#define SW_TIMER2_RSTN_3 BIT3 +#define SW_TIMER2_RSTN_4 BIT4 +#define SW_TIMER2_RSTN_5 BIT5 +#define SW_TIMER2_RSTN_6 BIT6 +#define SW_TIMER2_RSTN_7 BIT7 +#define SW_TIMER2_PRSTN BIT8 + +/*TIMER3*/ +#define SW_TIMER3_RSTN_0 BIT0 +#define SW_TIMER3_RSTN_1 BIT1 +#define SW_TIMER3_RSTN_2 BIT2 +#define SW_TIMER3_RSTN_3 BIT3 +#define SW_TIMER3_RSTN_4 BIT4 +#define SW_TIMER3_RSTN_5 BIT5 +#define SW_TIMER3_RSTN_6 BIT6 +#define SW_TIMER3_RSTN_7 BIT7 +#define SW_TIMER3_PRSTN BIT8 + +/*RTC*/ +#define SW_RTC_RSTN BIT0 + +/*MNOC*/ +#define SW_MNOC_SNOC_NSP_RSTN BIT0 +#define SW_MNOC_VC_ARSTN BIT1 +#define SW_MNOC_CFG_RSTN BIT2 +#define SW_MNOC_HSP_ARSTN BIT3 +#define SW_MNOC_GPU_ARSTN BIT4 +#define SW_MNOC_DDRC1_P3_ARSTN BIT5 +#define SW_MNOC_DDRC0_P3_ARSTN BIT6 + +/*RNOC*/ +#define SW_RNOC_VO_ARSTN BIT0 +#define SW_RNOC_VI_ARSTN BIT1 +#define SW_RNOC_SNOC_NSP_RSTN BIT2 +#define SW_RNOC_CFG_RSTN BIT3 +#define SW_MNOC_DDRC1_P4_ARSTN BIT4 +#define SW_MNOC_DDRC0_P4_ARSTN BIT5 + +/*CNOC*/ +#define SW_CNOC_VO_CFG_RSTN BIT0 +#define SW_CNOC_VI_CFG_RSTN BIT1 +#define SW_CNOC_VC_CFG_RSTN BIT2 +#define SW_CNOC_TCU_CFG_RSTN BIT3 +#define SW_CNOC_PCIET_CFG_RSTN BIT4 +#define SW_CNOC_NPU_CFG_RSTN BIT5 +#define SW_CNOC_LSP_CFG_RSTN BIT6 +#define SW_CNOC_HSP_CFG_RSTN BIT7 +#define SW_CNOC_GPU_CFG_RSTN BIT8 +#define SW_CNOC_DSPT_CFG_RSTN BIT9 +#define SW_CNOC_DDRT1_CFG_RSTN BIT10 +#define SW_CNOC_DDRT0_CFG_RSTN BIT11 +#define SW_CNOC_D2D_CFG_RSTN BIT12 +#define SW_CNOC_CFG_RSTN BIT13 +#define SW_CNOC_CLMM_CFG_RSTN BIT14 +#define SW_CNOC_AON_CFG_RSTN BIT15 + +/*LNOC*/ +#define SW_LNOC_CFG_RSTN BIT0 +#define SW_LNOC_NPU_LLC_ARSTN BIT1 +#define SW_LNOC_DDRC1_P0_ARSTN BIT2 +#define SW_LNOC_DDRC0_P0_ARSTN BIT3 + +#endif /*endif __DT_ESWIN_EIC7700_SYSCRG_H__*/ From c732c7134f562b9ac024b2239ecf3a099ce2b81d Mon Sep 17 00:00:00 2001 From: linmin Date: Mon, 29 Jul 2024 16:49:31 +0530 Subject: [PATCH 02/38] riscv: Kconfig: Added configs related to EIC7700 Signed-off-by: linmin Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- arch/riscv/Kconfig | 73 +++++++++++++++++++++++++++++++++++++++-- arch/riscv/Kconfig.socs | 7 ++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index c785a02005738..6817e86fffd9f 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -14,7 +14,7 @@ config RISCV def_bool y select ACPI_GENERIC_GSI if ACPI select ACPI_REDUCED_HARDWARE_ONLY if ACPI - select ARCH_DMA_DEFAULT_COHERENT + select ARCH_DMA_DEFAULT_COHERENT if !SOC_SIFIVE_EIC7700 select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2 select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE @@ -36,9 +36,11 @@ config RISCV select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL select ARCH_HAS_SYSCALL_WRAPPER + select ARCH_HAS_TEARDOWN_DMA_OPS if IOMMU_SUPPORT && SOC_SIFIVE_EIC7700 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_HAS_UBSAN_SANITIZE_ALL select ARCH_HAS_VDSO_DATA + select ARCH_KEEP_MEMBLOCK select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT select ARCH_STACKWALK @@ -64,6 +66,7 @@ config RISCV select CLONE_BACKWARDS select COMMON_CLK select CPU_PM if CPU_IDLE || HIBERNATION + select DMA_DIRECT_REMAP if SOC_SIFIVE_EIC7700 select EDAC_SUPPORT select FRAME_POINTER if PERF_EVENTS || (FUNCTION_TRACER && !DYNAMIC_FTRACE) select GENERIC_ARCH_TOPOLOGY @@ -141,6 +144,7 @@ config RISCV select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU + select IOMMU_DMA if IOMMU_SUPPORT && SOC_SIFIVE_EIC7700 select IRQ_DOMAIN select IRQ_FORCED_THREADING select KASAN_VMALLOC if KASAN @@ -268,12 +272,77 @@ config LOCKDEP_SUPPORT config RISCV_DMA_NONCOHERENT bool + select ARCH_HAS_DMA_CLEAR_UNCACHED if SOC_SIFIVE_EIC7700 select ARCH_HAS_DMA_PREP_COHERENT + select ARCH_HAS_DMA_SET_UNCACHED if SOC_SIFIVE_EIC7700 select ARCH_HAS_SETUP_DMA_OPS select ARCH_HAS_SYNC_DMA_FOR_CPU select ARCH_HAS_SYNC_DMA_FOR_DEVICE select DMA_BOUNCE_UNALIGNED_KMALLOC if SWIOTLB +config RISCV_DIE0_CACHED_OFFSET + hex "DIE0 memory port addr of U84" + depends on RISCV && ARCH_HAS_DMA_SET_UNCACHED + default 0x80000000 + help + Access to DDR memory through U84 memory port is cached. + +config RISCV_DIE0_MEM_MAX_SIZE + hex "DIE0 memory size, default 32GB" + depends on RISCV && ARCH_HAS_DMA_SET_UNCACHED + default 0x800000000 + +config RISCV_DIE0_UNCACHED_OFFSET + hex "DIE0 system port addr of U84" + depends on RISCV && ARCH_HAS_DMA_SET_UNCACHED + default 0xc000000000 + help + Access to DDR memory through U84 system port is uncached. + Add this offset when allocating memory from memory port(0x80000000~), + then memremap to virtual address. + +config RISCV_DIE1_CACHED_OFFSET + hex "DIE1 memory port addr of U84" + depends on RISCV && ARCH_HAS_DMA_SET_UNCACHED + default 0x2000000000 + help + Access to DIE1 DDR memory through U84 memory port is cached. + +config RISCV_DIE1_MEM_MAX_SIZE + hex "DIE1 memory size, default 32GB" + depends on RISCV && ARCH_HAS_DMA_SET_UNCACHED + default 0x800000000 + +config RISCV_DIE1_UNCACHED_OFFSET + hex "DIE1 system port addr of U84" + depends on RISCV && ARCH_HAS_DMA_SET_UNCACHED + default 0xe000000000 + help + Access to DIE1 DDR memory through U84 system port is uncached. + Add this offset when allocating memory from memory port(0x2000000000~), + then memremap to virtual address. + +config RISCV_INTERLEAVE_CACHED_OFFSET + hex "memory port addr of interleave" + depends on RISCV && ARCH_HAS_DMA_SET_UNCACHED + default 0x4000000000 + help + Access to DDR memory through U84 memory port with interleave is cached. + +config RISCV_INTERLEAVE_MEM_MAX_SIZE + hex "Interleaving memory size, default 64GB" + depends on RISCV && ARCH_HAS_DMA_SET_UNCACHED + default 0x1000000000 + +config RISCV_INTERLEAVE_UNCACHED_OFFSET + hex "system port addr of interleave" + depends on RISCV && ARCH_HAS_DMA_SET_UNCACHED + default 0x10000000000 + help + Access to DDR memory through U84 system port with interleave is uncached. + Add this offset when allocating memory from memory port(0x4000000000~), + then memremap to virtual address. + config RISCV_NONSTANDARD_CACHE_OPS bool help @@ -328,7 +397,7 @@ config ARCH_RV64I bool "RV64I" select 64BIT select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 - select SWIOTLB if MMU + select SWIOTLB if MMU && !SOC_SIFIVE_EIC7700 endchoice diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 30fd6a5128285..bad861ecdcd39 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -16,9 +16,16 @@ config ARCH_RENESAS config ARCH_SIFIVE def_bool SOC_SIFIVE +config SOC_SIFIVE_EIC7700 + bool "SiFive eic7700 SoC" + select RISCV_NONSTANDARD_CACHE_OPS + help + This enables support for SiFive EIC7700 platform hardware. + config SOC_SIFIVE bool "SiFive SoCs" select ERRATA_SIFIVE if !XIP_KERNEL + select RISCV_DMA_NONCOHERENT if SOC_SIFIVE_EIC7700 help This enables support for SiFive SoC platform hardware. From 3efb2540e87dc0da63cfafec5129b3e49cebffb1 Mon Sep 17 00:00:00 2001 From: huangyifeng Date: Mon, 29 Jul 2024 16:58:46 +0530 Subject: [PATCH 03/38] drivers: clk: eswin: added clock driver for eic7700 Signed-off-by: huangyifeng Signed-off-by: Pinkesh Vaghela --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/eswin/Kconfig | 6 + drivers/clk/eswin/Makefile | 8 + drivers/clk/eswin/clk-eic7700.c | 1187 +++++++++++++++++++++++++++++++ drivers/clk/eswin/clk.c | 915 ++++++++++++++++++++++++ drivers/clk/eswin/clk.h | 198 ++++++ 7 files changed, 2316 insertions(+) create mode 100755 drivers/clk/eswin/Kconfig create mode 100755 drivers/clk/eswin/Makefile create mode 100755 drivers/clk/eswin/clk-eic7700.c create mode 100755 drivers/clk/eswin/clk.c create mode 100755 drivers/clk/eswin/clk.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c30099866174d..151de7e16525b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -471,6 +471,7 @@ source "drivers/clk/actions/Kconfig" source "drivers/clk/analogbits/Kconfig" source "drivers/clk/baikal-t1/Kconfig" source "drivers/clk/bcm/Kconfig" +source "drivers/clk/eswin/Kconfig" source "drivers/clk/hisilicon/Kconfig" source "drivers/clk/imgtec/Kconfig" source "drivers/clk/imx/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 18969cbd4bb1e..1d36e1ef74df3 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -91,6 +91,7 @@ obj-$(CONFIG_CLK_BAIKAL_T1) += baikal-t1/ obj-y += bcm/ obj-$(CONFIG_ARCH_BERLIN) += berlin/ obj-$(CONFIG_ARCH_DAVINCI) += davinci/ +obj-$(CONFIG_SOC_SIFIVE_EIC7700) += eswin/ obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-y += imgtec/ obj-y += imx/ diff --git a/drivers/clk/eswin/Kconfig b/drivers/clk/eswin/Kconfig new file mode 100755 index 0000000000000..cc906e4b2343f --- /dev/null +++ b/drivers/clk/eswin/Kconfig @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config COMMON_CLK_EIC7700 + bool "EIC7700 Clock Driver" + help + Build the Eswin EIC7700 clock driver based on the common clock framework. diff --git a/drivers/clk/eswin/Makefile b/drivers/clk/eswin/Makefile new file mode 100755 index 0000000000000..a3139e34ee226 --- /dev/null +++ b/drivers/clk/eswin/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Eswin Clock specific Makefile +# + +obj-y += clk.o + +obj-$(CONFIG_COMMON_CLK_EIC7700) += clk-eic7700.o diff --git a/drivers/clk/eswin/clk-eic7700.c b/drivers/clk/eswin/clk-eic7700.c new file mode 100755 index 0000000000000..1b6c0b9e04509 --- /dev/null +++ b/drivers/clk/eswin/clk-eic7700.c @@ -0,0 +1,1187 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Clk Provider 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 . + * + * Authors: HuangYiFeng + */ + +#include +#include +#include +#include + +#include +#include + +#include "clk.h" + +/* clock parent list */ +static const char *const mux_u_cpu_root_3mux1_gfree_p[] = {"clk_pll_cpu", "clk_clk_u84_core_lp", "fixed_rate_clk_xtal_24m"}; +static u32 mux_u_cpu_root_3mux1_gfree_p_table[] = {0x000000, 0x000001, 0x000002}; + +static const char *const mux_u_cpu_aclk_2mux1_gfree_p[] = {"fixed_factor_u_cpu_div2", "mux_u_cpu_root_3mux1_gfree"}; + +static const char *const dsp_aclk_root_2mux1_gfree_mux_p[] = {"fixed_rate_clk_spll2_fout1", "fixed_rate_clk_spll0_fout1"}; + +static const char *const d2d_aclk_root_2mux1_gfree_mux_p[] = { "fixed_rate_clk_spll2_fout1", "fixed_rate_clk_spll0_fout1", }; + +static const char *const ddr_aclk_root_2mux1_gfree_mux_p[] = { "fixed_rate_clk_spll2_fout1", "fixed_rate_clk_spll0_fout1", }; + +static const char *const mshcore_root_3mux1_0_mux_p[] = {"fixed_rate_clk_spll0_fout3", "fixed_rate_clk_spll2_fout3", "fixed_rate_clk_xtal_24m"}; +static u32 mshcore_root_3mux1_0_mux_p_table[] = {0x000000, 0x000001, 0x100000}; + +static const char *const mshcore_root_3mux1_1_mux_p[] = {"fixed_rate_clk_spll0_fout3", "fixed_rate_clk_spll2_fout3", "fixed_rate_clk_xtal_24m"}; +static u32 mshcore_root_3mux1_1_mux_p_table[] = {0x000000, 0x000001, 0x100000}; + +static const char *const mshcore_root_3mux1_2_mux_p[] = {"fixed_rate_clk_spll0_fout3", "fixed_rate_clk_spll2_fout3", "fixed_rate_clk_xtal_24m"}; +static u32 mshcore_root_3mux1_2_mux_p_table[] = {0x000000, 0x000001, 0x100000}; + +static const char *const npu_llclk_3mux1_gfree_mux_p[] = { "clk_clk_npu_llc_src0", "clk_clk_npu_llc_src1", "fixed_rate_clk_vpll_fout1"}; +static u32 npu_llclk_3mux1_gfree_mux_p_table[] = {0x000000, 0x000001, 0x000002}; + +static const char *const npu_core_3mux1_gfree_mux_p[] = { "fixed_rate_clk_spll1_fout1", "fixed_rate_clk_vpll_fout1", "fixed_rate_clk_spll2_fout2"}; +static u32 npu_core_3mux1_gfree_mux_p_table[] = {0x000000, 0x000001, 0x000002}; + +static const char *const npu_e31_3mux1_gfree_mux_p[] = { "fixed_rate_clk_spll1_fout1", "fixed_rate_clk_vpll_fout1", "fixed_rate_clk_spll2_fout2"}; +static u32 npu_e31_3mux1_gfree_mux_p_table[] = {0x000000, 0x000100, 0x000200}; + +static const char *const vi_aclk_root_2mux1_gfree_mux_p[] = { "fixed_rate_clk_spll0_fout1", "fixed_rate_clk_spll2_fout1"}; + +static const char *const mux_u_vi_dw_root_2mux1_p[] = { "fixed_rate_clk_vpll_fout1", "fixed_rate_clk_spll0_fout1"}; + +static const char *const mux_u_vi_dvp_root_2mux1_gfree_p[] = { "fixed_rate_clk_vpll_fout1", "fixed_rate_clk_spll0_fout1"}; + +static const char *const mux_u_vi_dig_isp_root_2mux1_gfree_p[] = { "fixed_rate_clk_vpll_fout1", "fixed_rate_clk_spll0_fout1"}; + +static const char *const mux_u_vo_aclk_root_2mux1_gfree_p[] = { "fixed_rate_clk_spll0_fout1", "fixed_rate_clk_spll2_fout1"}; + +static const char *const mux_u_vo_pixel_root_2mux1_p[] = { "fixed_rate_clk_vpll_fout1", "fixed_rate_clk_spll2_fout2"}; + +static const char *const mux_u_vcdec_root_2mux1_gfree_p[] = { "fixed_rate_clk_spll0_fout1", "fixed_rate_clk_spll2_fout1"}; + +static const char *const mux_u_vcaclk_root_2mux1_gfree_p[] = { "fixed_rate_clk_spll0_fout1", "fixed_rate_clk_spll2_fout1"}; + +static const char *const mux_u_syscfg_clk_root_2mux1_gfree_p[] = { "divder_u_sys_cfg_div_dynm", "fixed_rate_clk_xtal_24m"}; + +static const char *const mux_u_bootspi_clk_2mux1_gfree_p[] = { "divder_u_bootspi_div_dynm", "fixed_rate_clk_xtal_24m"}; + +static const char *const mux_u_scpu_core_clk_2mux1_gfree_p[] = { "divder_u_scpu_core_div_dynm", "fixed_rate_clk_xtal_24m"}; + +static const char *const mux_u_lpcpu_core_clk_2mux1_gfree_p[] = {"divder_u_lpcpu_core_div_dynm", "fixed_rate_clk_xtal_24m"}; + +static const char *const mux_u_vo_mclk_2mux_ext_mclk_p[] = {"divder_u_vo_mclk_div_dynm", "fixed_rate_ext_mclk"}; + +static const char *const mux_u_aondma_axi2mux1_gfree_p[] = { "divder_u_aondma_axi_div_dynm", "fixed_rate_clk_xtal_24m"}; + +static const char *const mux_u_rmii_ref_2mux1_p[] = { "fixed_factor_u_hsp_rmii_ref_div6", "fixed_rate_lpddr_ref_bak"}; + +static const char *const mux_u_eth_core_2mux1_p[] = { "fixed_rate_clk_spll1_fout3", "fixed_rate_lpddr_ref_bak"}; + +static const char *const mux_u_sata_phy_2mux1_p[] = { "divder_u_sata_phy_ref_div_dynm", "fixed_rate_lpddr_ref_bak"}; + +/* fixed rate clocks */ +static struct eswin_fixed_rate_clock eic7700_fixed_rate_clks[] = { + { EIC7700_XTAL_24M, "fixed_rate_clk_xtal_24m", NULL, 0, 24000000, }, + { EIC7700_XTAL_32K, "fixed_rate_clk_xtal_32k", NULL, 0, 32768, }, + { EIC7700_SPLL0_FOUT1, "fixed_rate_clk_spll0_fout1", NULL, 0, 1600000000, }, + { EIC7700_SPLL0_FOUT2, "fixed_rate_clk_spll0_fout2", NULL, 0, 800000000, }, + { EIC7700_SPLL0_FOUT3, "fixed_rate_clk_spll0_fout3", NULL, 0, 400000000, }, + { EIC7700_SPLL1_FOUT1, "fixed_rate_clk_spll1_fout1", NULL, 0, 1500000000, }, + { EIC7700_SPLL1_FOUT2, "fixed_rate_clk_spll1_fout2", NULL, 0, 300000000, }, + { EIC7700_SPLL1_FOUT3, "fixed_rate_clk_spll1_fout3", NULL, 0, 250000000, }, + { EIC7700_SPLL2_FOUT1, "fixed_rate_clk_spll2_fout1", NULL, 0, 2080000000, }, + { EIC7700_SPLL2_FOUT2, "fixed_rate_clk_spll2_fout2", NULL, 0, 1040000000, }, + { EIC7700_SPLL2_FOUT3, "fixed_rate_clk_spll2_fout3", NULL, 0, 416000000, }, + { EIC7700_VPLL_FOUT1, "fixed_rate_clk_vpll_fout1", NULL, 0, 1188000000, }, + { EIC7700_VPLL_FOUT2, "fixed_rate_clk_vpll_fout2", NULL, 0, 594000000, }, + { EIC7700_VPLL_FOUT3, "fixed_rate_clk_vpll_fout3", NULL, 0, 49500000, }, + { EIC7700_APLL_FOUT2, "fixed_rate_clk_apll_fout2", NULL, 0, 0, }, + { EIC7700_APLL_FOUT3, "fixed_rate_clk_apll_fout3", NULL, 0, 0, }, + { EIC7700_EXT_MCLK, "fixed_rate_ext_mclk", NULL, 0, 0, }, + { EIC7700_LPDDR_REF_BAK, "fixed_rate_lpddr_ref_bak", NULL, 0, 50000000, }, +}; + +static struct eswin_pll_clock eic7700_pll_clks[] = { + { + EIC7700_APLL_FOUT1, "clk_apll_fout1", NULL, + EIC7700_REG_OFFSET_APLL_CFG_0, 0, 1, 12,6, 20,12, + EIC7700_REG_OFFSET_APLL_CFG_1, 4,24, + EIC7700_REG_OFFSET_APLL_CFG_2, 1,3, 16, 3, + EIC7700_REG_OFFSET_PLL_STATUS, 4, 1, + }, + { + EIC7700_PLL_CPU, "clk_pll_cpu", NULL, + EIC7700_REG_OFFSET_MCPUT_PLL_CFG_0, 0,1, 12,6, 20,12, + EIC7700_REG_OFFSET_MCPUT_PLL_CFG_1, 4, 24, + EIC7700_REG_OFFSET_MCPUT_PLL_CFG_2, 1,3, 16,3, + EIC7700_REG_OFFSET_PLL_STATUS, 5, 1, + }, +}; + +/* fixed factor clocks */ +static struct eswin_fixed_factor_clock eic7700_fixed_factor_clks[] = { + { EIC7700_FIXED_FACTOR_U_CPU_DIV2, "fixed_factor_u_cpu_div2", "mux_u_cpu_root_3mux1_gfree", 1, 2, 0, }, + + { EIC7700_FIXED_FACTOR_U_CLK_1M_DIV24, "fixed_factor_u_clk_1m_div24", "fixed_rate_clk_xtal_24m", 1, 24, 0, }, + + { EIC7700_FIXED_FACTOR_U_MIPI_TXESC_DIV10, "fixed_factor_u_mipi_txesc_div10", "clk_clk_sys_cfg", 1, 10, 0, }, + + { EIC7700_FIXED_FACTOR_U_U84_CORE_LP_DIV2, "fixed_factor_u_u84_core_lp_div2", "gate_clk_spll0_fout2", 1, 2, 0, }, + + { EIC7700_FIXED_FACTOR_U_SCPU_BUS_DIV2, "fixed_factor_u_scpu_bus_div2", "mux_u_scpu_core_clk_2mux1_gfree", 1, 2, 0, }, + + { EIC7700_FIXED_FACTOR_U_LPCPU_BUS_DIV2, "fixed_factor_u_lpcpu_bus_div2", "mux_u_lpcpu_core_clk_2mux1_gfree", 1, 2, 0, }, + + { EIC7700_FIXED_FACTOR_U_PCIE_CR_DIV2, "fixed_factor_u_pcie_cr_div2", "clk_clk_sys_cfg", 1, 2, 0, }, + + { EIC7700_FIXED_FACTOR_U_PCIE_AUX_DIV4, "fixed_factor_u_pcie_aux_div4", "clk_clk_sys_cfg", 1, 4, 0, }, + + { EIC7700_FIXED_FACTOR_U_PVT_DIV20, "fixed_factor_u_pvt_div20", "fixed_rate_clk_xtal_24m", 1, 20, 0, }, + + { EIC7700_FIXED_FACTOR_U_HSP_RMII_REF_DIV6, "fixed_factor_u_hsp_rmii_ref_div6", "fixed_rate_clk_spll1_fout2", 1, 6, 0, }, +}; + +static struct eswin_mux_clock eic7700_mux_clks[] = { + { EIC7700_MUX_U_CPU_ROOT_3MUX1_GFREE, "mux_u_cpu_root_3mux1_gfree", mux_u_cpu_root_3mux1_gfree_p, + ARRAY_SIZE(mux_u_cpu_root_3mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_U84_CLK_CTRL, + 0, BIT_MASK(0) | BIT_MASK(1), 0, mux_u_cpu_root_3mux1_gfree_p_table, }, + + { EIC7700_MUX_U_CPU_ACLK_2MUX1_GFREE, "mux_u_cpu_aclk_2mux1_gfree", mux_u_cpu_aclk_2mux1_gfree_p, + ARRAY_SIZE(mux_u_cpu_aclk_2mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_U84_CLK_CTRL, + 20, 1, 0,}, + + { EIC7700_MUX_U_DSP_ACLK_ROOT_2MUX1_GFREE, "mux_u_dsp_aclk_root_2mux1_gfree", dsp_aclk_root_2mux1_gfree_mux_p, + ARRAY_SIZE(dsp_aclk_root_2mux1_gfree_mux_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_DSP_ACLK_CTRL, + 0, 1, 0,}, + + { EIC7700_MUX_U_D2D_ACLK_ROOT_2MUX1_GFREE, "mux_u_d2d_aclk_root_2mux1_gfree", d2d_aclk_root_2mux1_gfree_mux_p, + ARRAY_SIZE(d2d_aclk_root_2mux1_gfree_mux_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_D2D_ACLK_CTRL, + 0, 1, 0,}, + + { EIC7700_MUX_U_DDR_ACLK_ROOT_2MUX1_GFREE, "mux_u_ddr_aclk_root_2mux1_gfree", ddr_aclk_root_2mux1_gfree_mux_p, + ARRAY_SIZE(ddr_aclk_root_2mux1_gfree_mux_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_DDR_CLK_CTRL, + 16, 1, 0,}, + + { EIC7700_MUX_U_MSHCORE_ROOT_3MUX1_0, "mux_u_mshcore_root_3mux1_0", mshcore_root_3mux1_0_mux_p, + ARRAY_SIZE(mshcore_root_3mux1_0_mux_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_MSHC0_CORECLK_CTRL, + 0, BIT_MASK(0) | BIT_MASK(20), 0, mshcore_root_3mux1_0_mux_p_table}, + + { EIC7700_MUX_U_MSHCORE_ROOT_3MUX1_1, "mux_u_mshcore_root_3mux1_1", mshcore_root_3mux1_1_mux_p, + ARRAY_SIZE(mshcore_root_3mux1_1_mux_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_MSHC1_CORECLK_CTRL, + 0, BIT_MASK(0) | BIT_MASK(20), 0, mshcore_root_3mux1_1_mux_p_table, }, + + { EIC7700_MUX_U_MSHCORE_ROOT_3MUX1_2, "mux_u_mshcore_root_3mux1_2", mshcore_root_3mux1_2_mux_p, + ARRAY_SIZE(mshcore_root_3mux1_2_mux_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_MSHC2_CORECLK_CTRL, + 0, BIT_MASK(0) | BIT_MASK(20), 0, mshcore_root_3mux1_2_mux_p_table }, + + { EIC7700_MUX_U_NPU_LLCLK_3MUX1_GFREE, "mux_u_npu_llclk_3mux1_gfree", npu_llclk_3mux1_gfree_mux_p, + ARRAY_SIZE(npu_llclk_3mux1_gfree_mux_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_NPU_LLC_CTRL, + 0, BIT_MASK(0) | BIT_MASK(1), 0, npu_llclk_3mux1_gfree_mux_p_table}, + + { EIC7700_MUX_U_NPU_CORE_3MUX1_GFREE, "mux_u_npu_core_3mux1_gfree", npu_core_3mux1_gfree_mux_p, + ARRAY_SIZE(npu_core_3mux1_gfree_mux_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_NPU_CORE_CTRL, + 0, BIT_MASK(0) | BIT_MASK(1), 0, npu_core_3mux1_gfree_mux_p_table}, + + { EIC7700_MUX_U_NPU_E31_3MUX1_GFREE, "mux_u_npu_e31_3mux1_gfree", npu_e31_3mux1_gfree_mux_p, + ARRAY_SIZE(npu_e31_3mux1_gfree_mux_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_NPU_CORE_CTRL, + 0, BIT_MASK(8) | BIT_MASK(9), 0, npu_e31_3mux1_gfree_mux_p_table}, + + { EIC7700_MUX_U_VI_ACLK_ROOT_2MUX1_GFREE, "mux_u_vi_aclk_root_2mux1_gfree", vi_aclk_root_2mux1_gfree_mux_p, + ARRAY_SIZE(vi_aclk_root_2mux1_gfree_mux_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_VI_ACLK_CTRL, + 0, 1, 0,}, + + { EIC7700_MUX_U_VI_DW_ROOT_2MUX1, "mux_u_vi_dw_root_2mux1", mux_u_vi_dw_root_2mux1_p, + ARRAY_SIZE(mux_u_vi_dw_root_2mux1_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_VI_DWCLK_CTRL, + 0, 1, 0,}, + + { EIC7700_MUX_U_VI_DVP_ROOT_2MUX1_GFREE, "mux_u_vi_dvp_root_2mux1_gfree", mux_u_vi_dvp_root_2mux1_gfree_p, + ARRAY_SIZE(mux_u_vi_dvp_root_2mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_VI_DVP_CLK_CTRL, + 0, 1, 0, }, + + { EIC7700_MUX_U_VI_DIG_ISP_ROOT_2MUX1_GFREE, "mux_u_vi_dig_isp_root_2mux1_gfree", mux_u_vi_dig_isp_root_2mux1_gfree_p, + ARRAY_SIZE(mux_u_vi_dig_isp_root_2mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_VI_DIG_ISP_CLK_CTRL, + 0, 1, 0, }, + + { EIC7700_MUX_U_VO_ACLK_ROOT_2MUX1_GFREE, "mux_u_vo_aclk_root_2mux1_gfree", mux_u_vo_aclk_root_2mux1_gfree_p, + ARRAY_SIZE(mux_u_vo_aclk_root_2mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_VO_ACLK_CTRL, + 0, 1, 0, }, + + { EIC7700_MUX_U_VO_PIXEL_ROOT_2MUX1, "mux_u_vo_pixel_root_2mux1", mux_u_vo_pixel_root_2mux1_p, + ARRAY_SIZE(mux_u_vo_pixel_root_2mux1_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_VO_PIXEL_CTRL, + 0, 1, 0, }, + + { EIC7700_MUX_U_VCDEC_ROOT_2MUX1_GFREE, "mux_u_vcdec_root_2mux1_gfree", mux_u_vcdec_root_2mux1_gfree_p, + ARRAY_SIZE(mux_u_vcdec_root_2mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_VCDEC_ROOTCLK_CTRL, + 0, 1, 0, }, + + { EIC7700_MUX_U_VCACLK_ROOT_2MUX1_GFREE, "mux_u_vcaclk_root_2mux1_gfree", mux_u_vcaclk_root_2mux1_gfree_p, + ARRAY_SIZE(mux_u_vcaclk_root_2mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_VC_ACLK_CTRL, + 0, 1, 0, }, + + { EIC7700_MUX_U_SYSCFG_CLK_ROOT_2MUX1_GFREE, "mux_u_syscfg_clk_root_2mux1_gfree", mux_u_syscfg_clk_root_2mux1_gfree_p, + ARRAY_SIZE(mux_u_syscfg_clk_root_2mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_SYSCFG_CLK_CTRL, + 0, 1, 0, }, + + { EIC7700_MUX_U_BOOTSPI_CLK_2MUX1_GFREE, "mux_u_bootspi_clk_2mux1_gfree", mux_u_bootspi_clk_2mux1_gfree_p, + ARRAY_SIZE(mux_u_bootspi_clk_2mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_BOOTSPI_CLK_CTRL, + 0, 1, 0, }, + + { EIC7700_MUX_U_SCPU_CORE_CLK_2MUX1_GFREE, "mux_u_scpu_core_clk_2mux1_gfree", mux_u_scpu_core_clk_2mux1_gfree_p, + ARRAY_SIZE(mux_u_scpu_core_clk_2mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_SCPU_CORECLK_CTRL, + 0, 1, 0, }, + + { EIC7700_MUX_U_LPCPU_CORE_CLK_2MUX1_GFREE, "mux_u_lpcpu_core_clk_2mux1_gfree", mux_u_lpcpu_core_clk_2mux1_gfree_p, + ARRAY_SIZE(mux_u_lpcpu_core_clk_2mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_LPCPU_CORECLK_CTRL, + 0, 1, 0, }, + + { EIC7700_MUX_U_VO_MCLK_2MUX_EXT_MCLK, "mux_u_vo_mclk_2mux_ext_mclk", mux_u_vo_mclk_2mux_ext_mclk_p, + ARRAY_SIZE(mux_u_vo_mclk_2mux_ext_mclk_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_VO_MCLK_CTRL, + 0, 1, 0, }, + + { EIC7700_MUX_U_AONDMA_AXI2MUX1_GFREE, "mux_u_aondma_axi2mux1_gfree", mux_u_aondma_axi2mux1_gfree_p, + ARRAY_SIZE(mux_u_aondma_axi2mux1_gfree_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_AON_DMA_CLK_CTRL, + 20, 1, 0, }, + + { EIC7700_MUX_U_RMII_REF_2MUX, "mux_u_rmii_ref_2mux1", mux_u_rmii_ref_2mux1_p, + ARRAY_SIZE(mux_u_rmii_ref_2mux1_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_ETH0_CTRL, + 2, 1, 0, }, + + { EIC7700_MUX_U_ETH_CORE_2MUX1, "mux_u_eth_core_2mux1", mux_u_eth_core_2mux1_p, + ARRAY_SIZE(mux_u_eth_core_2mux1_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_ETH0_CTRL, + 1, 1, 0, }, + + { EIC7700_MUX_U_SATA_PHY_2MUX1, "mux_u_sata_phy_2mux1", mux_u_sata_phy_2mux1_p, + ARRAY_SIZE(mux_u_sata_phy_2mux1_p), CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_SATA_OOB_CTRL, + 9, 1, 0, }, + +}; + +/*The hardware decides vaule 0, 1 and 2 both means 2 divsor, so we have to add these ugly tables*/ +static struct clk_div_table u_3_bit_special_div_table[8]; +static struct clk_div_table u_4_bit_special_div_table[16]; +static struct clk_div_table u_6_bit_special_div_table[64]; +static struct clk_div_table u_7_bit_special_div_table[128]; +static struct clk_div_table u_8_bit_special_div_table[256]; +static struct clk_div_table u_11_bit_special_div_table[2048]; +static struct clk_div_table u_16_bit_special_div_table[65536]; + +static struct eswin_divider_clock eic7700_div_clks[] = { + { EIC7700_DIVDER_U_SYS_CFG_DIV_DYNM, "divder_u_sys_cfg_div_dynm", "fixed_rate_clk_spll0_fout3", 0, + EIC7700_REG_OFFSET_SYSCFG_CLK_CTRL, 4, 3, CLK_DIVIDER_ROUND_CLOSEST, u_3_bit_special_div_table}, + + { EIC7700_DIVDER_U_NOC_NSP_DIV_DYNM, "divder_u_noc_nsp_div_dynm", "fixed_rate_clk_spll2_fout1", 0, + EIC7700_REG_OFFSET_NOC_CLK_CTRL, 0, 3, CLK_DIVIDER_ROUND_CLOSEST, u_3_bit_special_div_table}, + + { EIC7700_DIVDER_U_BOOTSPI_DIV_DYNM, "divder_u_bootspi_div_dynm", "gate_clk_spll0_fout2", 0, + EIC7700_REG_OFFSET_BOOTSPI_CLK_CTRL, 4, 6, CLK_DIVIDER_ROUND_CLOSEST, u_6_bit_special_div_table}, + + { EIC7700_DIVDER_U_SCPU_CORE_DIV_DYNM, "divder_u_scpu_core_div_dynm", "fixed_rate_clk_spll0_fout1", 0, + EIC7700_REG_OFFSET_SCPU_CORECLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_LPCPU_CORE_DIV_DYNM, "divder_u_lpcpu_core_div_dynm", "fixed_rate_clk_spll0_fout1", 0, + EIC7700_REG_OFFSET_LPCPU_CORECLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_GPU_ACLK_DIV_DYNM, "divder_u_gpu_aclk_div_dynm", "fixed_rate_clk_spll0_fout1", 0, + EIC7700_REG_OFFSET_GPU_ACLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_DSP_ACLK_DIV_DYNM, "divder_u_dsp_aclk_div_dynm", "clk_clk_dsp_root", 0, + EIC7700_REG_OFFSET_DSP_ACLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_D2D_ACLK_DIV_DYNM, "divder_u_d2d_aclk_div_dynm", "mux_u_d2d_aclk_root_2mux1_gfree", 0, + EIC7700_REG_OFFSET_D2D_ACLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_DDR_ACLK_DIV_DYNM, "divder_u_ddr_aclk_div_dynm", "mux_u_ddr_aclk_root_2mux1_gfree", 0, + EIC7700_REG_OFFSET_DDR_CLK_CTRL, 20, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_HSP_ACLK_DIV_DYNM, "divder_u_hsp_aclk_div_dynm", "fixed_rate_clk_spll0_fout1", 0, + EIC7700_REG_OFFSET_HSP_ACLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_ETH_TXCLK_DIV_DYNM_0, "divder_u_eth_txclk_div_dynm_0", "mux_u_eth_core_2mux1", 0, + EIC7700_REG_OFFSET_ETH0_CTRL, 4, 7, CLK_DIVIDER_ROUND_CLOSEST, u_7_bit_special_div_table}, + + { EIC7700_DIVDER_U_ETH_TXCLK_DIV_DYNM_1, "divder_u_eth_txclk_div_dynm_1", "mux_u_eth_core_2mux1", 0, + EIC7700_REG_OFFSET_ETH1_CTRL, 4, 7, CLK_DIVIDER_ROUND_CLOSEST, u_7_bit_special_div_table}, + + { EIC7700_DIVDER_U_MSHC_CORE_DIV_DYNM_0, "divder_u_mshc_core_div_dynm_0", "mux_u_mshcore_root_3mux1_0", 0, + EIC7700_REG_OFFSET_MSHC0_CORECLK_CTRL, 4, 12, CLK_DIVIDER_ONE_BASED}, + + { EIC7700_DIVDER_U_MSHC_CORE_DIV_DYNM_1, "divder_u_mshc_core_div_dynm_1", "mux_u_mshcore_root_3mux1_1", 0, + EIC7700_REG_OFFSET_MSHC1_CORECLK_CTRL, 4, 12, CLK_DIVIDER_ONE_BASED}, + + { EIC7700_DIVDER_U_MSHC_CORE_DIV_DYNM_2, "divder_u_mshc_core_div_dynm_2", "mux_u_mshcore_root_3mux1_2", 0, + EIC7700_REG_OFFSET_MSHC2_CORECLK_CTRL, 4, 12, CLK_DIVIDER_ONE_BASED}, + + { EIC7700_DIVDER_U_PCIE_ACLK_DIV_DYNM, "divder_u_pcie_aclk_div_dynm", "fixed_rate_clk_spll2_fout2", 0, + EIC7700_REG_OFFSET_PCIE_ACLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_NPU_ACLK_DIV_DYNM, "divder_u_npu_aclk_div_dynm", "fixed_rate_clk_spll0_fout1", 0, + EIC7700_REG_OFFSET_NPU_ACLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_NPU_LLC_SRC0_DIV_DYNM, "divder_u_npu_llc_src0_div_dynm", "fixed_rate_clk_spll0_fout1", 0, + EIC7700_REG_OFFSET_NPU_LLC_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_NPU_LLC_SRC1_DIV_DYNM, "divder_u_npu_llc_src1_div_dynm", "fixed_rate_clk_spll2_fout1", 0, + EIC7700_REG_OFFSET_NPU_LLC_CTRL, 8, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_NPU_CORECLK_DIV_DYNM, "divder_u_npu_coreclk_div_dynm", "mux_u_npu_core_3mux1_gfree", 0, + EIC7700_REG_OFFSET_NPU_CORE_CTRL, 4, 4, CLK_DIVIDER_ONE_BASED}, + + { EIC7700_DIVDER_U_NPU_E31_DIV_DYNM, "divder_u_npu_e31_div_dynm", "mux_u_npu_e31_3mux1_gfree", 0, + EIC7700_REG_OFFSET_NPU_CORE_CTRL, 12, 4, CLK_DIVIDER_ONE_BASED}, + + { EIC7700_DIVDER_U_VI_ACLK_DIV_DYNM, "divder_u_vi_aclk_div_dynm", "mux_u_vi_aclk_root_2mux1_gfree", 0, + EIC7700_REG_OFFSET_VI_ACLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_VI_DW_DIV_DYNM, "divder_u_vi_dw_div_dynm", "mux_u_vi_dw_root_2mux1", 0, + EIC7700_REG_OFFSET_VI_DWCLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_VI_DVP_DIV_DYNM, "divder_u_vi_dvp_div_dynm", "mux_u_vi_dig_root_2mux1_gfree", 0, + EIC7700_REG_OFFSET_VI_DVP_CLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_VI_DIG_ISP_DIV_DYNM, "divder_u_vi_dig_isp_div_dynm", "mux_u_vi_dig_isp_root_2mux1_gfree", 0, + EIC7700_REG_OFFSET_VI_DIG_ISP_CLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_0, "divder_u_vi_shutter_div_dynm_0", "fixed_rate_clk_vpll_fout2",0, + EIC7700_REG_OFFSET_VI_SHUTTER0, 4, 7, CLK_DIVIDER_ROUND_CLOSEST, u_7_bit_special_div_table}, + + { EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_1, "divder_u_vi_shutter_div_dynm_1", "fixed_rate_clk_vpll_fout2", 0, + EIC7700_REG_OFFSET_VI_SHUTTER1, 4, 7, CLK_DIVIDER_ROUND_CLOSEST, u_7_bit_special_div_table}, + + { EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_2, "divder_u_vi_shutter_div_dynm_2", "fixed_rate_clk_vpll_fout2", 0, + EIC7700_REG_OFFSET_VI_SHUTTER2, 4, 7, CLK_DIVIDER_ROUND_CLOSEST, u_7_bit_special_div_table}, + + { EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_3, "divder_u_vi_shutter_div_dynm_3", "fixed_rate_clk_vpll_fout2", 0, + EIC7700_REG_OFFSET_VI_SHUTTER3, 4, 7, CLK_DIVIDER_ROUND_CLOSEST, u_7_bit_special_div_table}, + + { EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_4, "divder_u_vi_shutter_div_dynm_4", "fixed_rate_clk_vpll_fout2", 0, + EIC7700_REG_OFFSET_VI_SHUTTER4, 4, 7, CLK_DIVIDER_ROUND_CLOSEST, u_7_bit_special_div_table}, + + { EIC7700_DIVDER_U_VI_SHUTTER_DIV_DYNM_5, "divder_u_vi_shutter_div_dynm_5", "fixed_rate_clk_vpll_fout2", 0, + EIC7700_REG_OFFSET_VI_SHUTTER5, 4, 7, CLK_DIVIDER_ROUND_CLOSEST, u_7_bit_special_div_table}, + + { EIC7700_DIVDER_U_VO_ACLK_DIV_DYNM, "divder_u_vo_aclk_div_dynm", "mux_u_vo_aclk_root_2mux1_gfree", 0, + EIC7700_REG_OFFSET_VO_ACLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_IESMCLK_DIV_DYNM, "divder_u_iesmclk_div_dynm", "fixed_rate_clk_spll0_fout3", 0, + EIC7700_REG_OFFSET_VO_IESMCLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_VO_PIXEL_DIV_DYNM, "divder_u_vo_pixel_div_dynm", "mux_u_vo_pixel_root_2mux1", 0, + EIC7700_REG_OFFSET_VO_PIXEL_CTRL, 4, 6, CLK_DIVIDER_ROUND_CLOSEST, u_6_bit_special_div_table}, + + { EIC7700_DIVDER_U_VO_MCLK_DIV_DYNM, "divder_u_vo_mclk_div_dynm", "clk_apll_fout1", 0, + EIC7700_REG_OFFSET_VO_MCLK_CTRL, 4, 8, CLK_DIVIDER_ROUND_CLOSEST, u_8_bit_special_div_table}, + + { EIC7700_DIVDER_U_VO_CEC_DIV_DYNM, "divder_u_vo_cec_div_dynm", "fixed_rate_clk_vpll_fout2", 0, + EIC7700_REG_OFFSET_VO_PHY_CLKCTRL, 16, 16, CLK_DIVIDER_ROUND_CLOSEST, u_16_bit_special_div_table}, + + { EIC7700_DIVDER_U_VC_ACLK_DIV_DYNM, "divder_u_vc_aclk_div_dynm", "mux_u_vcaclk_root_2mux1_gfree", 0, + EIC7700_REG_OFFSET_VC_ACLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_JD_DIV_DYNM, "divder_u_jd_div_dynm", "clk_clk_vc_root", 0, + EIC7700_REG_OFFSET_JD_CLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_JE_DIV_DYNM, "divder_u_je_div_dynm", "clk_clk_vc_root", 0, + EIC7700_REG_OFFSET_JE_CLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_VE_DIV_DYNM, "divder_u_ve_div_dynm", "clk_clk_vc_root", 0, + EIC7700_REG_OFFSET_VE_CLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_VD_DIV_DYNM, "divder_u_vd_div_dynm", "clk_clk_vc_root", 0, + EIC7700_REG_OFFSET_VD_CLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_G2D_DIV_DYNM, "divder_u_g2d_div_dynm", "clk_clk_dsp_root", 0, + EIC7700_REG_OFFSET_G2D_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_AONDMA_AXI_DIV_DYNM, "divder_u_aondma_axi_div_dynm", "fixed_rate_clk_spll0_fout1", 0, + EIC7700_REG_OFFSET_AON_DMA_CLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_CRYPTO_DIV_DYNM, "divder_u_crypto_div_dynm", "fixed_rate_clk_spll0_fout1", 0, + EIC7700_REG_OFFSET_SPACC_CLK_CTRL, 4, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_SATA_PHY_REF_DIV_DYNM, "divder_u_sata_phy_ref_div_dynm", "fixed_rate_clk_spll1_fout2", 0, + EIC7700_REG_OFFSET_SATA_OOB_CTRL, 0, 4, CLK_DIVIDER_ROUND_CLOSEST, u_4_bit_special_div_table}, + + { EIC7700_DIVDER_U_DSP_0_ACLK_DIV_DYNM, "divder_u_dsp_0_aclk_div_dynm", "gate_dspt_aclk", 0, + EIC7700_REG_OFFSET_DSP_CFG_CTRL, 19, 1, }, + + { EIC7700_DIVDER_U_DSP_1_ACLK_DIV_DYNM, "divder_u_dsp_1_aclk_div_dynm", "gate_dspt_aclk", 0, + EIC7700_REG_OFFSET_DSP_CFG_CTRL, 20, 1, }, + + { EIC7700_DIVDER_U_DSP_2_ACLK_DIV_DYNM, "divder_u_dsp_2_aclk_div_dynm", "gate_dspt_aclk", 0, + EIC7700_REG_OFFSET_DSP_CFG_CTRL, 21, 1, }, + + { EIC7700_DIVDER_U_DSP_3_ACLK_DIV_DYNM, "divder_u_dsp_3_aclk_div_dynm", "gate_dspt_aclk", 0, + EIC7700_REG_OFFSET_DSP_CFG_CTRL, 22, 1, }, + + { EIC7700_DIVDER_U_AON_RTC_DIV_DYNM, "divder_u_aon_rtc_div_dynm", "clk_clk_1m", 0, + EIC7700_REG_OFFSET_RTC_CLK_CTRL, 21, 11, CLK_DIVIDER_ROUND_CLOSEST, u_11_bit_special_div_table}, + + { EIC7700_DIVDER_U_U84_RTC_TOGGLE_DIV_DYNM, "divder_u_u84_rtc_toggle_dynm", "fixed_rate_clk_xtal_24m", 0, + EIC7700_REG_OFFSET_RTC_CLK_CTRL, 16, 5, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST}, + +}; + +/* + these clks should init early to cost down the whole clk module init time +*/ +static struct eswin_clock eic7700_clks_early_0[] = { + { EIC7700_CLK_CLK_DSP_ROOT , "clk_clk_dsp_root", "mux_u_dsp_aclk_root_2mux1_gfree", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_VC_ROOT, "clk_clk_vc_root", "mux_u_vcdec_root_2mux1_gfree", CLK_SET_RATE_PARENT,}, +}; + +static struct eswin_clock eic7700_clks_early_1[] = { + { EIC7700_CLK_CLK_SYS_CFG ,"clk_clk_sys_cfg", "mux_u_syscfg_clk_root_2mux1_gfree", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_D2DDR_ACLK ,"clk_clk_d2ddr_aclk", "divder_u_ddr_aclk_div_dynm", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_AONDMA_AXI_ST3,"clk_clk_aondma_axi_st3","mux_u_aondma_axi2mux1_gfree", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_G2D_ST2 ,"clk_clk_g2d_st2", "divder_u_g2d_div_dynm", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_MIPI_TXESC ,"clk_clk_mipi_txesc", "fixed_factor_u_mipi_txesc_div10", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_VI_ACLK_ST1 ,"clk_clk_vi_aclk_st1", "divder_u_vi_aclk_div_dynm", CLK_SET_RATE_PARENT,}, +}; + +static struct eswin_gate_clock eic7700_gate_clks[] = { + + { EIC7700_GATE_CLK_CPU_EXT_SRC_CORE_CLK_0 , "gate_clk_cpu_ext_src_core_clk_0", "mux_u_cpu_root_3mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_U84_CLK_CTRL, 28, 0, }, + + { EIC7700_GATE_CLK_CPU_EXT_SRC_CORE_CLK_1 , "gate_clk_cpu_ext_src_core_clk_1", "mux_u_cpu_root_3mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_U84_CLK_CTRL, 29, 0, }, + + { EIC7700_GATE_CLK_CPU_EXT_SRC_CORE_CLK_2 , "gate_clk_cpu_ext_src_core_clk_2", "mux_u_cpu_root_3mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_U84_CLK_CTRL, 30, 0, }, + + { EIC7700_GATE_CLK_CPU_EXT_SRC_CORE_CLK_3 , "gate_clk_cpu_ext_src_core_clk_3", "mux_u_cpu_root_3mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_U84_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_CPU_TRACE_CLK_0 , "gate_clk_cpu_trace_clk_0", "mux_u_cpu_root_3mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_U84_CLK_CTRL, 24, 0, }, + + { EIC7700_GATE_CLK_CPU_TRACE_CLK_1 , "gate_clk_cpu_trace_clk_1", "mux_u_cpu_root_3mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_U84_CLK_CTRL, 25, 0, }, + + { EIC7700_GATE_CLK_CPU_TRACE_CLK_2 , "gate_clk_cpu_trace_clk_2", "mux_u_cpu_root_3mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_U84_CLK_CTRL, 26, 0, }, + + { EIC7700_GATE_CLK_CPU_TRACE_CLK_3 , "gate_clk_cpu_trace_clk_3", "mux_u_cpu_root_3mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_U84_CLK_CTRL, 27, 0, }, + + { EIC7700_GATE_CLK_CPU_TRACE_COM_CLK , "gate_clk_cpu_trace_com_clk", "mux_u_cpu_aclk_2mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_U84_CLK_CTRL, 23, 0, }, + + { EIC7700_GATE_CLK_CPU_CLK , "gate_clk_cpu_clk", "mux_u_cpu_aclk_2mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_U84_CLK_CTRL, 28, 0, }, /*same as EIC7700_GATE_CLK_CPU_EXT_SRC_CORE_CLK_0 */ + + { EIC7700_GATE_CLK_SPLL0_FOUT2 , "gate_clk_spll0_fout2", "fixed_rate_clk_spll0_fout2", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_SPLL0_CFG_2, 31, 0, }, + + { EIC7700_GATE_NOC_NSP_CLK , "gate_noc_nsp_clk", "divder_u_noc_nsp_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_NOC_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_BOOTSPI , "gate_clk_bootspi", "mux_u_bootspi_clk_2mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_BOOTSPI_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_BOOTSPI_CFG , "gate_clk_bootspi_cfg", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_BOOTSPI_CFGCLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_SCPU_CORE , "gate_clk_scpu_core", "mux_u_scpu_core_clk_2mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_SCPU_CORECLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_SCPU_BUS ,"gate_clk_scpu_bus", "fixed_factor_u_scpu_bus_div2", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_SCPU_BUSCLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_LPCPU_CORE ,"gate_clk_lpcpu_core", "mux_u_lpcpu_core_clk_2mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LPCPU_CORECLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_LPCPU_BUS ,"gate_clk_lpcpu_bus", "fixed_factor_u_lpcpu_bus_div2", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LPCPU_BUSCLK_CTRL, 31, 0, }, + + { EIC7700_GATE_GPU_ACLK ,"gate_gpu_aclk", "divder_u_gpu_aclk_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_GPU_ACLK_CTRL, 31, 0, }, + + { EIC7700_GATE_GPU_GRAY_CLK ,"gate_gpu_gray_clk", "fixed_rate_clk_xtal_24m", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_GPU_GRAY_CTRL, 31, 0, }, + + { EIC7700_GATE_GPU_CFG_CLK ,"gate_gpu_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_GPU_CFG_CTRL, 31, 0, }, + + { EIC7700_GATE_DSPT_ACLK ,"gate_dspt_aclk", "divder_u_dsp_aclk_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DSP_ACLK_CTRL, 31, 0, }, + + { EIC7700_GATE_DSPT_CFG_CLK ,"gate_dspt_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DSP_CFG_CTRL, 31, 0, }, + + { EIC7700_GATE_D2D_ACLK ,"gate_d2d_aclk", "divder_u_d2d_aclk_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_D2D_ACLK_CTRL, 31, 0, }, + + { EIC7700_GATE_D2D_CFG_CLK ,"gate_d2d_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_D2D_CFG_CTRL, 31, 0, }, + + { EIC7700_GATE_TCU_ACLK ,"gate_tcu_aclk", "clk_clk_d2ddr_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TCU_ACLK_CTRL, 31, 0, }, + + { EIC7700_GATE_TCU_CFG_CLK ,"gate_tcu_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TCU_CFG_CTRL, 31, 0, }, + + { EIC7700_GATE_DDRT_CFG_CLK ,"gate_ddrt_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DDR_CLK_CTRL, 9, 0, }, + + { EIC7700_GATE_DDRT0_P0_ACLK ,"gate_ddrt0_p0_aclk", "clk_clk_d2ddr_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DDR_CLK_CTRL, 4, 0, }, + + { EIC7700_GATE_DDRT0_P1_ACLK ,"gate_ddrt0_p1_aclk", "clk_clk_d2ddr_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DDR_CLK_CTRL, 5, 0, }, + + { EIC7700_GATE_DDRT0_P2_ACLK ,"gate_ddrt0_p2_aclk", "clk_clk_d2ddr_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DDR_CLK_CTRL, 6, 0, }, + + { EIC7700_GATE_DDRT0_P3_ACLK ,"gate_ddrt0_p3_aclk", "clk_clk_d2ddr_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DDR_CLK_CTRL, 7, 0, }, + + { EIC7700_GATE_DDRT0_P4_ACLK ,"gate_ddrt0_p4_aclk", "clk_clk_d2ddr_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DDR_CLK_CTRL, 8, 0, }, + + { EIC7700_GATE_DDRT1_P0_ACLK ,"gate_ddrt1_p0_aclk", "clk_clk_d2ddr_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DDR1_CLK_CTRL, 4, 0, }, + + { EIC7700_GATE_DDRT1_P1_ACLK ,"gate_ddrt1_p1_aclk", "clk_clk_d2ddr_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DDR1_CLK_CTRL, 5, 0, }, + + { EIC7700_GATE_DDRT1_P2_ACLK ,"gate_ddrt1_p2_aclk", "clk_clk_d2ddr_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DDR1_CLK_CTRL, 6, 0, }, + + { EIC7700_GATE_DDRT1_P3_ACLK ,"gate_ddrt1_p3_aclk", "clk_clk_d2ddr_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DDR1_CLK_CTRL, 7, 0, }, + + { EIC7700_GATE_DDRT1_P4_ACLK ,"gate_ddrt1_p4_aclk", "clk_clk_d2ddr_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_DDR1_CLK_CTRL, 8, 0, }, + + { EIC7700_GATE_CLK_HSP_ACLK ,"gate_clk_hsp_aclk", "divder_u_hsp_aclk_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_HSP_ACLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_HSP_CFGCLK ,"gate_clk_hsp_cfgclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_HSP_CFG_CTRL, 31, 0, }, + + { EIC7700_GATE_PCIET_ACLK ,"gate_pciet_aclk", "divder_u_pcie_aclk_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_PCIE_ACLK_CTRL, 31, 0, }, + + { EIC7700_GATE_PCIET_CFG_CLK ,"gate_pciet_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_PCIE_CFG_CTRL, 31, 0, }, + + { EIC7700_GATE_PCIET_CR_CLK ,"gate_pciet_cr_clk", "fixed_factor_u_pcie_cr_div2", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_PCIE_CFG_CTRL, 0, 0, }, + + { EIC7700_GATE_PCIET_AUX_CLK ,"gate_pciet_aux_clk", "fixed_factor_u_pcie_aux_div4", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_PCIE_CFG_CTRL, 1, 0, }, + + { EIC7700_GATE_NPU_ACLK ,"gate_npu_aclk", "divder_u_npu_aclk_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_NPU_ACLK_CTRL, 31, 0, }, + + { EIC7700_GATE_NPU_CFG_CLK ,"gate_npu_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_NPU_ACLK_CTRL, 30, 0, }, + + { EIC7700_GATE_NPU_LLC_ACLK ,"gate_npu_llc_aclk", "mux_u_npu_llclk_3mux1_gfree", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_NPU_LLC_CTRL, 31, 0, }, + + { EIC7700_GATE_NPU_CLK ,"gate_npu_clk", "divder_u_npu_coreclk_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_NPU_CORE_CTRL, 31, 0, }, + + { EIC7700_GATE_NPU_E31_CLK ,"gate_npu_e31_clk", "divder_u_npu_e31_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_NPU_CORE_CTRL, 30, 0, }, + + { EIC7700_GATE_VI_ACLK ,"gate_vi_aclk", "clk_clk_vi_aclk_st1", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_ACLK_CTRL, 31, 0, }, + + { EIC7700_GATE_VI_CFG_CLK ,"gate_vi_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_ACLK_CTRL, 30, 0, }, + + { EIC7700_GATE_VI_DIG_DW_CLK ,"gate_vi_dig_dw_clk", "divder_u_vi_dw_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_DWCLK_CTRL, 31, 0, }, + + { EIC7700_GATE_VI_DVP_CLK ,"gate_vi_dvp_clk", "divder_u_vi_dvp_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_DVP_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_VI_DIG_ISP_CLK ,"gate_vi_dig_isp_clk", "divder_u_vi_dig_isp_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_DIG_ISP_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_VI_SHUTTER_0 ,"gate_vi_shutter_0", "divder_u_vi_shutter_div_dynm_0", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_SHUTTER0, 31, 0, }, + + { EIC7700_GATE_VI_SHUTTER_1 ,"gate_vi_shutter_1", "divder_u_vi_shutter_div_dynm_1", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_SHUTTER1, 31, 0, }, + + { EIC7700_GATE_VI_SHUTTER_2 ,"gate_vi_shutter_2", "divder_u_vi_shutter_div_dynm_2", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_SHUTTER2, 31, 0, }, + + { EIC7700_GATE_VI_SHUTTER_3 ,"gate_vi_shutter_3", "divder_u_vi_shutter_div_dynm_3", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_SHUTTER3, 31, 0, }, + + { EIC7700_GATE_VI_SHUTTER_4 ,"gate_vi_shutter_4", "divder_u_vi_shutter_div_dynm_4", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_SHUTTER4, 31, 0, }, + + { EIC7700_GATE_VI_SHUTTER_5 ,"gate_vi_shutter_5", "divder_u_vi_shutter_div_dynm_5", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_SHUTTER5, 31, 0, }, + + { EIC7700_GATE_VI_PHY_TXCLKESC ,"gate_vi_phy_txclkesc", "clk_clk_mipi_txesc", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_PHY_CLKCTRL, 0, 0, }, + + { EIC7700_GATE_VI_PHY_CFG ,"gate_vi_phy_cfg", "fixed_rate_clk_xtal_24m", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VI_PHY_CLKCTRL, 1, 0, }, + + { EIC7700_GATE_VO_ACLK ,"gate_vo_aclk", "divder_u_vo_aclk_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VO_ACLK_CTRL, 31, 0, }, + + { EIC7700_GATE_VO_CFG_CLK ,"gate_vo_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VO_ACLK_CTRL, 30, 0, }, + + { EIC7700_GATE_VO_HDMI_IESMCLK ,"gate_vo_hdmi_iesmclk", "divder_u_iesmclk_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VO_IESMCLK_CTRL, 31, 0, }, + + { EIC7700_GATE_VO_PIXEL_CLK ,"gate_vo_pixel_clk", "divder_u_vo_pixel_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VO_PIXEL_CTRL, 31, 0, }, + + { EIC7700_GATE_VO_I2S_MCLK ,"gate_vo_i2s_mclk", "mux_u_vo_mclk_2mux_ext_mclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VO_MCLK_CTRL, 31, 0, }, + + { EIC7700_GATE_VO_CR_CLK ,"gate_vo_cr_clk", "clk_clk_mipi_txesc", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VO_PHY_CLKCTRL, 1, 0, }, + + { EIC7700_GATE_VC_ACLK ,"gate_vc_aclk", "divder_u_vc_aclk_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VC_ACLK_CTRL, 31, 0, }, + + { EIC7700_GATE_VC_CFG_CLK ,"gate_vc_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VC_CLKEN_CTRL, 0, 0, }, + + { EIC7700_GATE_VC_JE_CLK ,"gate_vc_je_clk", "divder_u_je_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_JE_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_VC_JD_CLK ,"gate_vc_jd_clk", "divder_u_jd_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_JD_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_VC_VE_CLK ,"gate_vc_ve_clk", "divder_u_ve_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VE_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_VC_VD_CLK ,"gate_vc_vd_clk", "divder_u_vd_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VD_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_G2D_CFG_CLK ,"gate_g2d_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_G2D_CTRL, 28, 0, }, + + { EIC7700_GATE_G2D_CLK ,"gate_g2d_clk", "clk_clk_g2d_st2", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_G2D_CTRL, 30, 0, }, + + { EIC7700_GATE_G2D_ACLK ,"gate_g2d_aclk", "clk_clk_g2d_st2", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_G2D_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_AONDMA_CFG ,"gate_clk_aondma_cfg", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_AON_DMA_CLK_CTRL, 30, 0, }, + + { EIC7700_GATE_AONDMA_ACLK ,"gate_aondma_aclk", "clk_clk_aondma_axi_st3", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_AON_DMA_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_AON_ACLK ,"gate_aon_aclk", "clk_clk_aondma_axi_st3", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_AON_DMA_CLK_CTRL, 29, 0, }, + + { EIC7700_GATE_TIMER_CLK_0 ,"gate_time_clk_0", "fixed_rate_clk_xtal_24m", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TIMER_CLK_CTRL, 0, 0, }, + + { EIC7700_GATE_TIMER_CLK_1 ,"gate_time_clk_1", "fixed_rate_clk_xtal_24m", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TIMER_CLK_CTRL, 1, 0, }, + + { EIC7700_GATE_TIMER_CLK_2 ,"gate_time_clk_2", "fixed_rate_clk_xtal_24m", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TIMER_CLK_CTRL, 2, 0, }, + + { EIC7700_GATE_TIMER_CLK_3 ,"gate_time_clk_3", "fixed_rate_clk_xtal_24m", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TIMER_CLK_CTRL, 3, 0, }, + + { EIC7700_GATE_TIMER_PCLK_0 ,"gate_timer_pclk_0", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TIMER_CLK_CTRL, 4, 0, }, + + { EIC7700_GATE_TIMER_PCLK_1 ,"gate_timer_pclk_1", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TIMER_CLK_CTRL, 5, 0, }, + + { EIC7700_GATE_TIMER_PCLK_2 ,"gate_timer_pclk_2", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TIMER_CLK_CTRL, 6, 0, }, + + { EIC7700_GATE_TIMER_PCLK_3 ,"gate_timer_pclk_3", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TIMER_CLK_CTRL, 7, 0, }, + + { EIC7700_GATE_TIMER3_CLK8 ,"gate_timer3_clk8", "fixed_rate_clk_vpll_fout3", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TIMER_CLK_CTRL, 8, 0, }, + + { EIC7700_GATE_CLK_RTC_CFG ,"gate_clk_rtc_cfg", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_RTC_CLK_CTRL, 2, 0, }, + + { EIC7700_GATE_CLK_RTC ,"gate_clk_rtc", "divder_u_aon_rtc_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_RTC_CLK_CTRL, 1, 0, }, + + { EIC7700_GATE_CLK_PKA_CFG ,"gate_clk_pka_cfg", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_PKA_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_SPACC_CFG ,"gate_clk_spacc_cfg", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_SPACC_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_CRYPTO ,"gate_clk_crypto", "divder_u_crypto_div_dynm", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_SPACC_CLK_CTRL, 30, 0, }, + + { EIC7700_GATE_CLK_TRNG_CFG ,"gate_clk_trng_cfg", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_TRNG_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_OTP_CFG ,"gate_clk_otp_cfg", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_OTP_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_0 ,"gate_clk_mailbox_0", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 0, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_1 ,"gate_clk_mailbox_1", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 1, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_2 ,"gate_clk_mailbox_2", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 2, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_3 ,"gate_clk_mailbox_3", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 3, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_4 ,"gate_clk_mailbox_4", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 4, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_5 ,"gate_clk_mailbox_5", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 5, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_6 ,"gate_clk_mailbox_6", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 6, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_7 ,"gate_clk_mailbox_7", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 7, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_8 ,"gate_clk_mailbox_8", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 8, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_9 ,"gate_clk_mailbox_9", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 9, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_10 ,"gate_clk_mailbox_10", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 10, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_11 ,"gate_clk_mailbox_11", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 11, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_12 ,"gate_clk_mailbox_12", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 12, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_13 ,"gate_clk_mailbox_13", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 13, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_14 ,"gate_clk_mailbox_14", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 14, 0, }, + + { EIC7700_GATE_CLK_MAILBOX_15 ,"gate_clk_mailbox_15", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 15, 0, }, + + { EIC7700_GATE_LSP_I2C0_PCLK ,"gate_i2c0_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 7, 0, }, + + { EIC7700_GATE_LSP_I2C1_PCLK ,"gate_i2c1_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 8, 0, }, + + { EIC7700_GATE_LSP_I2C2_PCLK ,"gate_i2c2_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 9, 0, }, + + { EIC7700_GATE_LSP_I2C3_PCLK ,"gate_i2c3_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 10, 0, }, + + { EIC7700_GATE_LSP_I2C4_PCLK ,"gate_i2c4_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 11, 0, }, + + { EIC7700_GATE_LSP_I2C5_PCLK ,"gate_i2c5_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 12, 0, }, + + { EIC7700_GATE_LSP_I2C6_PCLK ,"gate_i2c6_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 13, 0, }, + + { EIC7700_GATE_LSP_I2C7_PCLK ,"gate_i2c7_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 14, 0, }, + + { EIC7700_GATE_LSP_I2C8_PCLK ,"gate_i2c8_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 15, 0, }, + + { EIC7700_GATE_LSP_I2C9_PCLK ,"gate_i2c9_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 16, 0, }, + + { EIC7700_GATE_LSP_WDT0_PCLK ,"gate_lsp_wdt0_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 28, 0, }, + + { EIC7700_GATE_LSP_WDT1_PCLK ,"gate_lsp_wdt1_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 29, 0, }, + + { EIC7700_GATE_LSP_WDT2_PCLK ,"gate_lsp_wdt2_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 30, 0, }, + + { EIC7700_GATE_LSP_WDT3_PCLK ,"gate_lsp_wdt3_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 31, 0, }, + + { EIC7700_GATE_LSP_SSI0_PCLK ,"gate_lsp_ssi0_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 26, 0, }, + + { EIC7700_GATE_LSP_SSI1_PCLK ,"gate_lsp_ssi1_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 27, 0, }, + + { EIC7700_GATE_LSP_UART0_PCLK ,"gate_lsp_uart0_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 17, 0, }, + + { EIC7700_GATE_LSP_UART1_PCLK ,"gate_lsp_uart1_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 18, 0, }, + + { EIC7700_GATE_LSP_UART2_PCLK ,"gate_lsp_uart2_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 19, 0, }, + + { EIC7700_GATE_LSP_UART3_PCLK ,"gate_lsp_uart3_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 20, 0, }, + + { EIC7700_GATE_LSP_UART4_PCLK ,"gate_lsp_uart4_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 21, 0, }, + + { EIC7700_GATE_LSP_TIMER_PCLK ,"gate_lsp_timer_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 25, 0, }, + + { EIC7700_GATE_LSP_FAN_PCLK ,"gate_lsp_fan_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 0, 0, }, + + { EIC7700_GATE_LSP_PVT_PCLK ,"gate_lsp_pvt_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN0, 1, 0, }, + + { EIC7700_GATE_LSP_PVT0_CLK ,"gate_pvt0_clk", "fixed_factor_u_pvt_div20", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 16, 0, }, + + { EIC7700_GATE_LSP_PVT1_CLK ,"gate_pvt1_clk", "fixed_factor_u_pvt_div20", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_LSP_CLK_EN1, 17, 0, }, + + { EIC7700_GATE_VC_JE_PCLK ,"gate_vc_je_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VC_CLKEN_CTRL, 2, 0, }, + + { EIC7700_GATE_VC_JD_PCLK ,"gate_vc_jd_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VC_CLKEN_CTRL, 1, 0, }, + + { EIC7700_GATE_VC_VE_PCLK ,"gate_vc_ve_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VC_CLKEN_CTRL, 5, 0, }, + + { EIC7700_GATE_VC_VD_PCLK ,"gate_vc_vd_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VC_CLKEN_CTRL, 4, 0, }, + + { EIC7700_GATE_VC_MON_PCLK ,"gate_vc_mon_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_VC_CLKEN_CTRL, 3, 0, }, + + { EIC7700_GATE_HSP_MSHC0_CORE_CLK ,"gate_hsp_mshc0_core_clk", "divder_u_mshc_core_div_dynm_0", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_MSHC0_CORECLK_CTRL, 16, 0, }, + + { EIC7700_GATE_HSP_MSHC1_CORE_CLK ,"gate_hsp_mshc1_core_clk", "divder_u_mshc_core_div_dynm_1", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_MSHC1_CORECLK_CTRL, 16, 0, }, + + { EIC7700_GATE_HSP_MSHC2_CORE_CLK ,"gate_hsp_mshc2_core_clk", "divder_u_mshc_core_div_dynm_2", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_MSHC2_CORECLK_CTRL, 16, 0, }, + + { EIC7700_GATE_HSP_SATA_RBC_CLK ,"gate_hsp_sata_rbc_clk", "fixed_rate_clk_spll1_fout2", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_SATA_RBC_CTRL, 0, 0, }, + + { EIC7700_GATE_HSP_SATA_OOB_CLK ,"gate_hsp_sata_oob_clk", "mux_u_sata_phy_2mux1", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_SATA_OOB_CTRL, 31, 0, }, + + { EIC7700_GATE_HSP_DMA0_CLK ,"gate_hsp_dma0_clk", "gate_clk_hsp_aclk", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_HSP_ACLK_CTRL, 0, 0, }, + + { EIC7700_GATE_HSP_ETH0_CORE_CLK ,"gate_hsp_eth0_core_clk", "divder_u_eth_txclk_div_dynm_0", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_ETH0_CTRL, 0, 0, }, + + { EIC7700_GATE_HSP_ETH1_CORE_CLK ,"gate_hsp_eth1_core_clk", "divder_u_eth_txclk_div_dynm_1", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_ETH1_CTRL, 0, 0, }, + + { EIC7700_GATE_HSP_RMII_REF_0 ,"gate_hsp_rmii_ref_0", "mux_u_rmii_ref_2mux1", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_ETH0_CTRL, 31, 0, }, + + { EIC7700_GATE_HSP_RMII_REF_1 ,"gate_hsp_rmii_ref_1", "mux_u_rmii_ref_2mux1", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_ETH1_CTRL, 31, 0, }, + + { EIC7700_GATE_AON_I2C0_PCLK ,"gate_aon_i2c0_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_I2C0_CLK_CTRL, 31, 0, }, + + { EIC7700_GATE_AON_I2C1_PCLK ,"gate_aon_i2c1_pclk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT, + EIC7700_REG_OFFSET_I2C1_CLK_CTRL, 31, 0, }, +}; + +/* eic7700 clocks */ +static struct eswin_clock eic7700_clks[] = { + { EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_0 ,"clk_cpu_ext_src_core_clk_0", "gate_clk_cpu_ext_src_core_clk_0", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_1 ,"clk_cpu_ext_src_core_clk_1", "gate_clk_cpu_ext_src_core_clk_1", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_2 ,"clk_cpu_ext_src_core_clk_2", "gate_clk_cpu_ext_src_core_clk_2", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CPU_EXT_SRC_CORE_CLK_3 ,"clk_cpu_ext_src_core_clk_3", "gate_clk_cpu_ext_src_core_clk_3", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CPU_TRACE_CLK_0 ,"clk_cpu_trace_clk_0", "gate_clk_cpu_trace_clk_0", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CPU_TRACE_CLK_1 ,"clk_cpu_trace_clk_1", "gate_clk_cpu_trace_clk_1", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CPU_TRACE_CLK_2 ,"clk_cpu_trace_clk_2", "gate_clk_cpu_trace_clk_2", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CPU_TRACE_CLK_3 ,"clk_cpu_trace_clk_3", "gate_clk_cpu_trace_clk_3", CLK_SET_RATE_PARENT,}, + + { EIC7700_CLK_CPU_TRACE_COM_CLK ,"clk_cpu_trace_com_clk", "gate_clk_cpu_trace_com_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CPU_CLK ,"clk_cpu_clk", "gate_clk_cpu_clk", CLK_SET_RATE_PARENT,}, + + { EIC7700_CLK_CLK_1M ,"clk_clk_1m", "fixed_factor_u_clk_1m_div24", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_NOC_CFG_CLK ,"clk_noc_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_NOC_NSP_CLK ,"clk_noc_nsp_clk", "gate_noc_nsp_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_BOOTSPI ,"clk_clk_bootspi", "gate_clk_bootspi", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_BOOTSPI_CFG ,"clk_clk_bootspi_cfg", "gate_clk_bootspi_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_U84_CORE_LP ,"clk_clk_u84_core_lp", "fixed_factor_u_u84_core_lp_div2", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_SCPU_CORE ,"clk_clk_scpu_core", "gate_clk_scpu_core", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_SCPU_BUS ,"clk_clk_scpu_bus", "gate_clk_scpu_bus", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_LPCPU_CORE ,"clk_clk_lpcpu_core", "gate_clk_lpcpu_core", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_LPCPU_BUS ,"clk_clk_lpcpu_bus", "gate_clk_lpcpu_bus", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_GPU_ACLK ,"clk_gpu_aclk", "gate_gpu_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_GPU_GRAY_CLK ,"clk_gpu_gray_clk", "gate_gpu_gray_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_GPU_CFG_CLK ,"clk_gpu_cfg_clk", "gate_gpu_cfg_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DSPT_ACLK ,"clk_dspt_aclk", "gate_dspt_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DSPT_CFG_CLK ,"clk_dspt_cfg_clk", "gate_dspt_cfg_clk", CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,}, + { EIC7700_CLK_D2D_ACLK ,"clk_d2d_aclk", "gate_d2d_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_D2D_CFG_CLK ,"clk_d2d_cfg_clk", "gate_d2d_cfg_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_TCU_ACLK ,"clk_tcu_aclk", "gate_tcu_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_TCU_CFG_CLK ,"clk_tcu_cfg_clk", "gate_tcu_cfg_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DDRT_CFG_CLK ,"clk_ddrt_cfg_clk", "gate_ddrt_cfg_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DDRT0_P0_ACLK ,"clk_ddrt0_p0_aclk", "gate_ddrt0_p0_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DDRT0_P1_ACLK ,"clk_ddrt0_p1_aclk", "gate_ddrt0_p1_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DDRT0_P2_ACLK ,"clk_ddrt0_p2_aclk", "gate_ddrt0_p2_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DDRT0_P3_ACLK ,"clk_ddrt0_p3_aclk", "gate_ddrt0_p3_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DDRT0_P4_ACLK ,"clk_ddrt0_p4_aclk", "gate_ddrt0_p4_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DDRT1_P0_ACLK ,"clk_ddrt1_p0_aclk", "gate_ddrt1_p0_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DDRT1_P1_ACLK ,"clk_ddrt1_p1_aclk", "gate_ddrt1_p1_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DDRT1_P2_ACLK ,"clk_ddrt1_p2_aclk", "gate_ddrt1_p2_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DDRT1_P3_ACLK ,"clk_ddrt1_p3_aclk", "gate_ddrt1_p3_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DDRT1_P4_ACLK ,"clk_ddrt1_p4_aclk", "gate_ddrt1_p4_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_ACLK ,"clk_hsp_aclk", "gate_clk_hsp_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_CFG_CLK ,"clk_hsp_cfg_clk", "gate_clk_hsp_cfgclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_SATA_RBC_CLK ,"clk_hsp_sata_rbc_clk", "gate_hsp_sata_rbc_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_SATA_OOB_CLK ,"clk_hsp_sata_oob_clk", "gate_hsp_sata_oob_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_SATA_PHY_REF ,"clk_hsp_sata_phy_ref", "gate_hsp_sata_oob_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_SATA_PMALIVE_CLK ,"clk_hsp_sata_pmalive_clk", "gate_hsp_sata_oob_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_ETH_APP_CLK ,"clk_hsp_eth_app_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_ETH_CSR_CLK ,"clk_hsp_eth_csr_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_ETH0_CORE_CLK ,"clk_hsp_eth0_core_clk", "gate_hsp_eth0_core_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_ETH1_CORE_CLK ,"clk_hsp_eth1_core_clk", "gate_hsp_eth1_core_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_MSHC0_CORE_CLK ,"clk_hsp_mshc0_core_clk", "gate_hsp_mshc0_core_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_MSHC1_CORE_CLK ,"clk_hsp_mshc1_core_clk", "gate_hsp_mshc1_core_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_MSHC2_CORE_CLK ,"clk_hsp_mshc2_core_clk", "gate_hsp_mshc2_core_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_MSHC0_TMR_CLK ,"clk_hsp_mshc0_tmr_clk", "clk_clk_1m", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_MSHC1_TMR_CLK ,"clk_hsp_mshc1_tmr_clk", "clk_clk_1m", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_MSHC2_TMR_CLK ,"clk_hsp_mshc2_tmr_clk", "clk_clk_1m", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_USB0_SUSPEND_CLK ,"clk_hsp_usb0_suspend_clk", "clk_clk_1m", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_USB1_SUSPEND_CLK ,"clk_hsp_usb1_suspend_clk", "clk_clk_1m", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_PCIET_ACLK ,"clk_pciet_aclk", "gate_pciet_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_PCIET_CFG_CLK ,"clk_pciet_cfg_clk", "gate_pciet_cfg_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_PCIET_CR_CLK ,"clk_pciet_cr_clk", "gate_pciet_cr_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_PCIET_AUX_CLK ,"clk_pciet_aux_clk", "gate_pciet_aux_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_NPU_ACLK ,"clk_npu_aclk", "gate_npu_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_NPU_CFG_CLK ,"clk_npu_cfg_clk", "gate_npu_cfg_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_NPU_LLC_SRC0 ,"clk_clk_npu_llc_src0", "divder_u_npu_llc_src0_div_dynm", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_NPU_LLC_SRC1 ,"clk_clk_npu_llc_src1", "divder_u_npu_llc_src1_div_dynm", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_NPU_LLC_ACLK ,"clk_npu_llc_aclk", "gate_npu_llc_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_NPU_CLK ,"clk_npu_clk", "gate_npu_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_NPU_E31_CLK ,"clk_npu_e31_clk", "gate_npu_e31_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_ACLK ,"clk_vi_aclk", "gate_vi_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_DIG_DW_CLK ,"clk_vi_dig_dw_clk", "gate_vi_dig_dw_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_CFG_CLK ,"clk_vi_cfg_clk", "gate_vi_cfg_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_DVP_CLK ,"clk_vi_dvp_clk", "gate_vi_dvp_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_DIG_ISP_CLK ,"clk_vi_dig_isp_clk", "gate_vi_dig_isp_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_SHUTTER_0 ,"clk_vi_shutter_0", "gate_vi_shutter_0", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_SHUTTER_1 ,"clk_vi_shutter_1", "gate_vi_shutter_1", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_SHUTTER_2 ,"clk_vi_shutter_2", "gate_vi_shutter_2", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_SHUTTER_3 ,"clk_vi_shutter_3", "gate_vi_shutter_3", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_SHUTTER_4 ,"clk_vi_shutter_4", "gate_vi_shutter_4", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_SHUTTER_5 ,"clk_vi_shutter_5", "gate_vi_shutter_5", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_PHY_TXCLKESC ,"clk_vi_phy_txclkesc", "gate_vi_phy_txclkesc", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VI_PHY_CFG ,"clk_vi_phy_cfg", "gate_vi_phy_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VO_ACLK ,"clk_vo_aclk", "gate_vo_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VO_CFG_CLK ,"clk_vo_cfg_clk", "gate_vo_cfg_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VO_HDMI_IESMCLK ,"clk_vo_hdmi_iesmclk", "gate_vo_hdmi_iesmclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VO_PIXEL_CLK ,"clk_vo_pixel_clk", "gate_vo_pixel_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VO_I2S_MCLK ,"clk_vo_i2s_mclk", "gate_vo_i2s_mclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VO_CR_CLK ,"clk_vo_cr_clk", "gate_vo_cr_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VO_CEC_CLK ,"clk_vo_cec_clk", "divder_u_vo_cec_div_dynm", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VC_ACLK ,"clk_vc_aclk", "gate_vc_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VC_CFG_CLK ,"clk_vc_cfg_clk", "gate_vc_cfg_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VC_JE_CLK ,"clk_vc_je_clk", "gate_vc_je_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VC_JD_CLK ,"clk_vc_jd_clk", "gate_vc_jd_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VC_VE_CLK ,"clk_vc_ve_clk", "gate_vc_ve_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VC_VD_CLK ,"clk_vc_vd_clk", "gate_vc_vd_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_G2D_CFG_CLK ,"clk_g2d_cfg_clk", "gate_g2d_cfg_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_G2D_CLK ,"clk_g2d_clk", "gate_g2d_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_G2D_ACLK ,"clk_g2d_aclk", "gate_g2d_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_AONDMA_CFG ,"clk_aondma_cfg", "gate_clk_aondma_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_AONDMA_ACLK ,"clk_aondma_aclk", "gate_aondma_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_AON_ACLK ,"clk_aon_aclk", "gate_aon_aclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_TIMER_CLK_0 ,"clk_timer_clk_0", "gate_time_clk_0", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_TIMER_CLK_1 ,"clk_timer_clk_1", "gate_time_clk_1", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_TIMER_CLK_2 ,"clk_timer_clk_2", "gate_time_clk_2", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_TIMER_CLK_3 ,"clk_timer_clk_3", "gate_time_clk_3", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_TIMER_PCLK_0 ,"clk_timer_pclk_0", "gate_timer_pclk_0", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_TIMER_PCLK_1 ,"clk_timer_pclk_1", "gate_timer_pclk_1", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_TIMER_PCLK_2 ,"clk_timer_pclk_2", "gate_timer_pclk_2", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_TIMER_PCLK_3 ,"clk_timer_pclk_3", "gate_timer_pclk_3", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_TIMER3_CLK8 ,"clk_timer3_clk8", "gate_timer3_clk8", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_RTC_CFG ,"clk_clk_rtc_cfg", "gate_clk_rtc_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_RTC ,"clk_clk_rtc", "gate_clk_rtc", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_PKA_CFG ,"clk_clk_pka_cfg", "gate_clk_pka_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_SPACC_CFG ,"clk_clk_spacc_cfg", "gate_clk_spacc_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_CRYPTO ,"clk_clk_crypto", "gate_clk_crypto", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_TRNG_CFG ,"clk_clk_trng_cfg", "gate_clk_trng_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_OTP_CFG ,"clk_clk_otp_cfg", "gate_clk_otp_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLMM_CFG_CLK ,"clk_clmm_cfg_clk", "clk_clk_sys_cfg", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLMM_DEB_CLK ,"clk_clmm_deb_clk", "clk_clk_1m", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_0 ,"clk_mailbox0", "gate_clk_mailbox_0", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_1 ,"clk_mailbox1", "gate_clk_mailbox_1", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_2 ,"clk_mailbox2", "gate_clk_mailbox_2", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_3 ,"clk_mailbox3", "gate_clk_mailbox_3", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_4 ,"clk_mailbox4", "gate_clk_mailbox_4", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_5 ,"clk_mailbox5", "gate_clk_mailbox_5", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_6 ,"clk_mailbox6", "gate_clk_mailbox_6", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_7 ,"clk_mailbox7", "gate_clk_mailbox_7", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_8 ,"clk_mailbox8", "gate_clk_mailbox_8", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_9 ,"clk_mailbox9", "gate_clk_mailbox_9", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_10 ,"clk_mailbox10", "gate_clk_mailbox_10", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_11 ,"clk_mailbox11", "gate_clk_mailbox_11", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_12 ,"clk_mailbox12", "gate_clk_mailbox_12", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_13 ,"clk_mailbox13", "gate_clk_mailbox_13", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_14 ,"clk_mailbox14", "gate_clk_mailbox_14", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_MAILBOX_15 ,"clk_mailbox15", "gate_clk_mailbox_15", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_I2C0_PCLK ,"clk_i2c0_pclk", "gate_i2c0_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_I2C1_PCLK ,"clk_i2c1_pclk", "gate_i2c1_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_I2C2_PCLK ,"clk_i2c2_pclk", "gate_i2c2_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_I2C3_PCLK ,"clk_i2c3_pclk", "gate_i2c3_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_I2C4_PCLK ,"clk_i2c4_pclk", "gate_i2c4_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_I2C5_PCLK ,"clk_i2c5_pclk", "gate_i2c5_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_I2C6_PCLK ,"clk_i2c6_pclk", "gate_i2c6_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_I2C7_PCLK ,"clk_i2c7_pclk", "gate_i2c7_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_I2C8_PCLK ,"clk_i2c8_pclk", "gate_i2c8_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_I2C9_PCLK ,"clk_i2c9_pclk", "gate_i2c9_pclk", CLK_SET_RATE_PARENT,}, + + { EIC7700_CLK_LSP_WDT0_PCLK ,"clk_lsp_wdt0_pclk", "gate_lsp_wdt0_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_WDT1_PCLK ,"clk_lsp_wdt1_pclk", "gate_lsp_wdt1_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_WDT2_PCLK ,"clk_lsp_wdt2_pclk", "gate_lsp_wdt2_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_WDT3_PCLK ,"clk_lsp_wdt3_pclk", "gate_lsp_wdt3_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_SSI0_PCLK ,"clk_lsp_ssi0_pclk", "gate_lsp_ssi0_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_SSI1_PCLK ,"clk_lsp_ssi1_pclk", "gate_lsp_ssi1_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_UART0_PCLK ,"clk_lsp_uart0_pclk", "gate_lsp_uart0_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_UART1_PCLK ,"clk_lsp_uart1_pclk", "gate_lsp_uart1_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_UART2_PCLK ,"clk_lsp_uart2_pclk", "gate_lsp_uart2_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_UART3_PCLK ,"clk_lsp_uart3_pclk", "gate_lsp_uart3_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_UART4_PCLK ,"clk_lsp_uart4_pclk", "gate_lsp_uart4_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_TIMER_PCLK ,"clk_lsp_timer_pclk", "gate_lsp_timer_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_FAN_PCLK ,"clk_lsp_fan_pclk", "gate_lsp_fan_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_LSP_PVT_PCLK ,"clk_lsp_pvt_pclk", "gate_lsp_pvt_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_PVT_CLK_0 ,"clk_pvt0_clk", "gate_pvt0_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_PVT_CLK_1 ,"clk_pvt1_clk", "gate_pvt1_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VC_JE_PCLK ,"clk_vc_je_pclk", "gate_vc_je_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VC_JD_PCLK ,"clk_vc_jd_pclk", "gate_vc_jd_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VC_VE_PCLK ,"clk_vc_ve_pclk", "gate_vc_ve_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VC_VD_PCLK ,"clk_vc_vd_pclk", "gate_vc_vd_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_VC_MON_PCLK ,"clk_vc_mon_pclk", "gate_vc_mon_pclk", CLK_SET_RATE_PARENT,}, + + { EIC7700_CLK_HSP_DMA0_CLK ,"clk_hsp_dma0_clk", "gate_hsp_dma0_clk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_RMII_REF_0 ,"clk_hsp_rmii_ref_0", "gate_hsp_rmii_ref_0", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_HSP_RMII_REF_1 ,"clk_hsp_rmii_ref_1", "gate_hsp_rmii_ref_1", CLK_SET_RATE_PARENT,}, + + { EIC7700_CLK_DSP_ACLK_0 ,"clk_dsp_aclk_0", "divder_u_dsp_0_aclk_div_dynm", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DSP_ACLK_1 ,"clk_dsp_aclk_1", "divder_u_dsp_1_aclk_div_dynm", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DSP_ACLK_2 ,"clk_dsp_aclk_2", "divder_u_dsp_2_aclk_div_dynm", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_DSP_ACLK_3 ,"clk_dsp_aclk_3", "divder_u_dsp_3_aclk_div_dynm", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_CLK_U84_RTC_TOGGLE ,"clk_clk_u84_rtc_toggle", "divder_u_u84_rtc_toggle_dynm", CLK_SET_RATE_PARENT,}, + + { EIC7700_CLK_AON_I2C0_PCLK ,"clk_aon_i2c0_pclk", "gate_aon_i2c0_pclk", CLK_SET_RATE_PARENT,}, + { EIC7700_CLK_AON_I2C1_PCLK ,"clk_aon_i2c1_pclk", "gate_aon_i2c1_pclk", CLK_SET_RATE_PARENT,}, +}; + +static void special_div_table_init(struct clk_div_table *table, int table_size) +{ + int i; + + if (table_size < 3) { + return; + } + if (!table) { + return; + } + /*The hardware decides vaule 0, 1 and 2 both means 2 divsor*/ + for (i = 0; i < 3; i++) { + table[i].val = i; + table[i].div = 2; + } + for (i = 3; i < table_size; i++) { + table[i].val = i; + table[i].div = i; + } + return; +} + +static int eswin_clk_probe(struct platform_device *pdev) +{ + struct eswin_clock_data *clk_data; + + clk_data = eswin_clk_init(pdev, EIC7700_NR_CLKS); + if (!clk_data) + return -EAGAIN; + + special_div_table_init(u_3_bit_special_div_table, ARRAY_SIZE(u_3_bit_special_div_table)); + special_div_table_init(u_4_bit_special_div_table, ARRAY_SIZE(u_4_bit_special_div_table)); + special_div_table_init(u_6_bit_special_div_table, ARRAY_SIZE(u_6_bit_special_div_table)); + special_div_table_init(u_7_bit_special_div_table, ARRAY_SIZE(u_7_bit_special_div_table)); + special_div_table_init(u_8_bit_special_div_table, ARRAY_SIZE(u_8_bit_special_div_table)); + special_div_table_init(u_11_bit_special_div_table, ARRAY_SIZE(u_11_bit_special_div_table)); + special_div_table_init(u_16_bit_special_div_table, ARRAY_SIZE(u_16_bit_special_div_table)); + + eswin_clk_register_fixed_rate(eic7700_fixed_rate_clks, + ARRAY_SIZE(eic7700_fixed_rate_clks), + clk_data); + eswin_clk_register_pll(eic7700_pll_clks, + ARRAY_SIZE(eic7700_pll_clks), clk_data, &pdev->dev); + + eswin_clk_register_fixed_factor(eic7700_fixed_factor_clks, + ARRAY_SIZE(eic7700_fixed_factor_clks), + clk_data); + eswin_clk_register_mux(eic7700_mux_clks, ARRAY_SIZE(eic7700_mux_clks), + clk_data); + eswin_clk_register_clk(eic7700_clks_early_0, ARRAY_SIZE(eic7700_clks_early_0), + clk_data); + eswin_clk_register_divider(eic7700_div_clks, ARRAY_SIZE(eic7700_div_clks), + clk_data); + eswin_clk_register_clk(eic7700_clks_early_1, ARRAY_SIZE(eic7700_clks_early_1), + clk_data); + eswin_clk_register_gate(eic7700_gate_clks, ARRAY_SIZE(eic7700_gate_clks), + clk_data); + eswin_clk_register_clk(eic7700_clks, ARRAY_SIZE(eic7700_clks), clk_data); + return 0; +} + +static const struct of_device_id eswin_clock_dt_ids[] = { + { .compatible = "eswin,eic7700-clock", }, + { /* sentinel */ }, +}; + +static struct platform_driver eswin_clock_driver = { + .probe = eswin_clk_probe, + .driver = { + .name = "eswin-clock", + .of_match_table = eswin_clock_dt_ids, + }, +}; +static int __init eic7700_clk_init(void) +{ + return platform_driver_register(&eswin_clock_driver); +} +arch_initcall(eic7700_clk_init); diff --git a/drivers/clk/eswin/clk.c b/drivers/clk/eswin/clk.c new file mode 100755 index 0000000000000..62bd09700a009 --- /dev/null +++ b/drivers/clk/eswin/clk.c @@ -0,0 +1,915 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Clk Provider 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 . + * + * Authors: HuangYiFeng + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +struct clk_hw *eswin_clk_find_parent(struct eswin_clock_data *data, char *parent_name) +{ + int i; + struct clk *clks; + + for (i = 0; i < data->clk_data.clk_num; i++) { + clks = data->clk_data.clks[i]; + if (NULL == clks) { + continue; + } + if (!strcmp(__clk_get_name(clks), parent_name)) { + return __clk_get_hw(clks); + } + } + return NULL; +} + +struct eswin_clock_data *eswin_clk_init(struct platform_device *pdev, + int nr_clks) +{ + struct eswin_clock_data *clk_data; + struct clk **clk_table; + void __iomem *base; + struct device *parent; + + parent = pdev->dev.parent; + if (!parent) { + dev_err(&pdev->dev, "no parent\n"); + goto err; + } + + base = of_iomap(parent->of_node, 0); + if (!base) { + dev_err(&pdev->dev,"failed to map clock registers\n"); + goto err; + } + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + goto err; + + clk_data->base = base; + clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL); + if (!clk_table) + goto err_data; + + clk_data->clk_data.clks = clk_table; + clk_data->clk_data.clk_num = nr_clks; + clk_data->numa_id = dev_to_node(parent); + spin_lock_init(&clk_data->lock); + + of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, &clk_data->clk_data); + return clk_data; + +err_data: + kfree(clk_data); +err: + return NULL; +} +EXPORT_SYMBOL_GPL(eswin_clk_init); + +int eswin_clk_register_fixed_rate(const struct eswin_fixed_rate_clock *clks, + int nums, struct eswin_clock_data *data) +{ + struct clk *clk; + int i; + + for (i = 0; i < nums; i++) { + char *name = kzalloc(strlen(clks[i].name) + 2 * sizeof(char) + sizeof(int), + GFP_KERNEL ); + if (data->numa_id < 0) { + sprintf(name, "%s", clks[i].name); + } else { + sprintf(name, "d%d_%s", data->numa_id, clks[i].name); + } + clk = clk_register_fixed_rate(NULL, name, clks[i].parent_name, + clks[i].flags, clks[i].fixed_rate); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", __func__, name); + kfree(name); + goto err; + } + data->clk_data.clks[clks[i].id] = clk; + kfree(name); + } + + return 0; +err: + while (i--) + clk_unregister_fixed_rate(data->clk_data.clks[clks[i].id]); + + return PTR_ERR(clk); +} +EXPORT_SYMBOL_GPL(eswin_clk_register_fixed_rate); + +static int eswin_calc_pll(u32 *frac_val, u32 *postdiv1_val, + u32 *fbdiv_val, u32 *refdiv_val, u64 rate, + const struct eswin_clk_pll *clk) +{ + int ret = 0; + + switch (clk->id) { + case EIC7700_APLL_FOUT1: + switch (rate) { + case APLL_LOW_FREQ: + *frac_val = 10603200; + *postdiv1_val = 0; + *fbdiv_val = 37; + *refdiv_val = 1; + break; + case APLL_HIGH_FREQ: + default: + *frac_val = 14092861; + *postdiv1_val = 0; + *fbdiv_val = 163; + *refdiv_val = 1; + break; + } + break; + case EIC7700_PLL_CPU: + switch (rate) { + case CLK_FREQ_1800M: + *frac_val = 0; + *postdiv1_val = 0; + *fbdiv_val = 300; + *refdiv_val = 1; + break; + case CLK_FREQ_1700M: + *frac_val = 5592405; + *postdiv1_val = 0; + *fbdiv_val = 283; + *refdiv_val = 1; + break; + case CLK_FREQ_1600M: + *frac_val = 11184810; + *postdiv1_val = 0; + *fbdiv_val = 266; + *refdiv_val = 1; + break; + case CLK_FREQ_1500M: + *frac_val = 0; + *postdiv1_val = 0; + *fbdiv_val = 250; + *refdiv_val = 1; + break; + case CLK_FREQ_1300M: + *frac_val = 11184810; + *postdiv1_val = 0; + *fbdiv_val = 216; + *refdiv_val = 1; + break; + case CLK_FREQ_1200M: + *frac_val = 0; + *postdiv1_val = 0; + *fbdiv_val = 200; + *refdiv_val = 1; + break; + case CLK_FREQ_1000M: + *frac_val = 11184810; + *postdiv1_val = 0; + *fbdiv_val = 166; + *refdiv_val = 1; + break; + case CLK_FREQ_900M: + *frac_val = 0; + *postdiv1_val = 0; + *fbdiv_val = 150; + *refdiv_val = 1; + break; + case CLK_FREQ_800M: + *frac_val = 5592405; + *postdiv1_val = 0; + *fbdiv_val = 133; + *refdiv_val = 1; + break; + case CLK_FREQ_700M: + *frac_val = 11184810; + *postdiv1_val = 0; + *fbdiv_val = 116; + *refdiv_val = 1; + break; + case CLK_FREQ_600M: + *frac_val = 0; + *postdiv1_val = 0; + *fbdiv_val = 100; + *refdiv_val = 1; + break; + case CLK_FREQ_500M: + *frac_val = 5592405; + *postdiv1_val = 0; + *fbdiv_val = 83; + *refdiv_val = 1; + break; + case CLK_FREQ_400M: + *frac_val = 11184810; + *postdiv1_val = 0; + *fbdiv_val = 66; + *refdiv_val = 1; + break; + case CLK_FREQ_200M: + *frac_val = 5592405; + *postdiv1_val = 0; + *fbdiv_val = 33; + *refdiv_val = 1; + break; + case CLK_FREQ_100M: + *frac_val = 11184810; + *postdiv1_val = 0; + *fbdiv_val = 16; + *refdiv_val = 1; + break; + case CLK_FREQ_1400M: + default: + *frac_val = 5592405; + *postdiv1_val = 0; + *fbdiv_val = 233; + *refdiv_val = 1; + break; + } + break; + default: + ret = -EINVAL; + pr_err("%s %d, Invalid pll set req, rate %lld, clk id %d\n", __func__, __LINE__, rate, clk->id); + break; + } + return ret; +} + +#define to_pll_clk(_hw) container_of(_hw, struct eswin_clk_pll, hw) +static int clk_pll_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct eswin_clk_pll *clk = to_pll_clk(hw); + u32 frac_val = 0, postdiv1_val, fbdiv_val, refdiv_val; + u32 val; + int ret; + struct clk *clk_cpu_mux = NULL; + struct clk *clk_cpu_lp_pll = NULL; + struct clk *clk_cpu_pll = NULL; + int try_count = 0; + bool lock_flag = false; + char clk_cpu_mux_name[50] = {0}; + char clk_cpu_lp_pll_name[50] = {0}; + char clk_cpu_pll_name[50] = {0}; + + ret = eswin_calc_pll(&frac_val, &postdiv1_val, &fbdiv_val, &refdiv_val, (u64)rate, clk); + if (ret) { + return ret; + } + + /* + we must switch the cpu to other clk before we change the cpu pll + */ + if (EIC7700_PLL_CPU == clk->id) { + if (clk->numa_id < 0) { + sprintf(clk_cpu_mux_name, "%s", "mux_u_cpu_root_3mux1_gfree"); + sprintf(clk_cpu_lp_pll_name, "%s", "clk_clk_u84_core_lp"); + sprintf(clk_cpu_pll_name, "%s", "clk_pll_cpu"); + } else { + sprintf(clk_cpu_mux_name, "d%d_%s", clk->numa_id, "mux_u_cpu_root_3mux1_gfree"); + sprintf(clk_cpu_lp_pll_name, "d%d_%s", clk->numa_id, "clk_clk_u84_core_lp"); + sprintf(clk_cpu_pll_name, "d%d_%s", clk->numa_id, "clk_pll_cpu"); + } + + clk_cpu_mux = __clk_lookup(clk_cpu_mux_name); + if (!clk_cpu_mux) { + pr_err("%s %d, failed to get %s\n",__func__,__LINE__, clk_cpu_mux_name); + return -EINVAL; + } + clk_cpu_lp_pll = __clk_lookup(clk_cpu_lp_pll_name); + if (!clk_cpu_lp_pll) { + pr_err("%s %d, failed to get %s\n",__func__,__LINE__, clk_cpu_lp_pll_name); + return -EINVAL; + } + clk_cpu_pll = __clk_lookup(clk_cpu_pll_name); + if (!clk_cpu_pll) { + pr_err("%s %d, failed to get %s\n",__func__,__LINE__, clk_cpu_pll_name); + return -EINVAL; + } + + ret = clk_set_parent(clk_cpu_mux, clk_cpu_lp_pll); + if (ret) { + pr_err("%s %d, faild to switch %s to %s, ret %d\n",__func__,__LINE__, clk_cpu_mux_name, + clk_cpu_lp_pll_name, ret); + return -EPERM; + } + } + + /*first disable pll */ + val = readl_relaxed(clk->ctrl_reg0); + val &= ~(((1 << clk->pllen_width) - 1) << clk->pllen_shift); + val |= 0 << clk->pllen_shift; + writel_relaxed(val, clk->ctrl_reg0); + + val = readl_relaxed(clk->ctrl_reg0); + val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift); + val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift); + val |= refdiv_val << clk->refdiv_shift; + val |= fbdiv_val << clk->fbdiv_shift; + writel_relaxed(val, clk->ctrl_reg0); + + val = readl_relaxed(clk->ctrl_reg1); + val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift); + val |= frac_val << clk->frac_shift; + writel_relaxed(val, clk->ctrl_reg1); + + val = readl_relaxed(clk->ctrl_reg2); + val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift); + val |= postdiv1_val << clk->postdiv1_shift; + writel_relaxed(val, clk->ctrl_reg2); + + /*at last, enable pll */ + val = readl_relaxed(clk->ctrl_reg0); + val &= ~(((1 << clk->pllen_width) - 1) << clk->pllen_shift); + val |= 1 << clk->pllen_shift; + writel_relaxed(val, clk->ctrl_reg0); + + /* + usually the pll wil lock in 50us + */ + do { + usleep_range(refdiv_val * 80, refdiv_val * 80 * 2); + val = readl_relaxed(clk->status_reg); + if (val & 1 << clk->lock_shift) { + lock_flag = true; + break; + } + } while (try_count++ < 10); + + if (false == lock_flag) { + pr_err("%s %d, faild to lock the cpu pll, cpu will work on low power pll\n",__func__,__LINE__); + return -EBUSY; + } + if (EIC7700_PLL_CPU == clk->id) { + ret = clk_set_parent(clk_cpu_mux, clk_cpu_pll); + if (ret) { + pr_err("%s %d, faild to switch %s to %s, ret %d\n",__func__,__LINE__, + clk_cpu_mux_name, clk_cpu_pll_name, ret); + return -EPERM; + } + } + return 0; +} + +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct eswin_clk_pll *clk = to_pll_clk(hw); + u64 frac_val, fbdiv_val, refdiv_val; + u32 postdiv1_val; + u32 val; + u64 rate; + + val = readl_relaxed(clk->ctrl_reg0); + val = val >> clk->fbdiv_shift; + val &= ((1 << clk->fbdiv_width) - 1); + fbdiv_val = val; + + val = readl_relaxed(clk->ctrl_reg0); + val = val >> clk->refdiv_shift; + val &= ((1 << clk->refdiv_width) - 1); + refdiv_val = val; + + val = readl_relaxed(clk->ctrl_reg1); + val = val >> clk->frac_shift; + val &= ((1 << clk->frac_width) - 1); + frac_val = val; + + val = readl_relaxed(clk->ctrl_reg2); + val = val >> clk->postdiv1_shift; + val &= ((1 << clk->postdiv1_width) - 1); + postdiv1_val = val; + + switch (clk->id) { + case EIC7700_APLL_FOUT1: + switch (frac_val) { + case 14092861: + rate = APLL_HIGH_FREQ; + break; + case 10603200: + rate = APLL_LOW_FREQ; + break; + default: + pr_err("%s %d, clk id %d, unknow frac_val %llu\n", __func__, __LINE__, clk->id, frac_val); + rate = 0; + break; + } + break; + case EIC7700_PLL_CPU: + switch (fbdiv_val) { + case 300: + rate = CLK_FREQ_1800M; + break; + case 283: + rate = CLK_FREQ_1700M; + break; + case 266: + rate = CLK_FREQ_1600M; + break; + case 250: + rate = CLK_FREQ_1500M; + break; + case 216: + rate = CLK_FREQ_1300M; + break; + case 200: + rate = CLK_FREQ_1200M; + break; + case 166: + rate = CLK_FREQ_1000M; + break; + case 150: + rate = CLK_FREQ_900M; + break; + case 133: + rate = CLK_FREQ_800M; + break; + case 116: + rate = CLK_FREQ_700M; + break; + case 100: + rate = CLK_FREQ_600M; + break; + case 83: + rate = CLK_FREQ_500M; + break; + case 66: + rate = CLK_FREQ_400M; + break; + case 33: + rate = CLK_FREQ_200M; + break; + case 16: + rate = CLK_FREQ_100M; + break; + case 233: + rate = CLK_FREQ_1400M; + break; + default: + pr_err("%s %d, clk id %d, unknow fbdiv_val %llu\n", __func__, __LINE__, clk->id, fbdiv_val); + rate = 0; + break; + } + break; + default: + pr_err("%s %d, unknow clk id %d\n", __func__, __LINE__, clk->id); + rate = 0; + break; + } + return rate; +} + +static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct eswin_clk_pll *clk = to_pll_clk(hw); + int index; + u64 round_rate = 0; + + /*Must be sorted in ascending order*/ + u64 apll_clk[] = {APLL_LOW_FREQ, APLL_HIGH_FREQ}; + u64 cpu_pll_clk[] = {CLK_FREQ_100M, CLK_FREQ_200M, CLK_FREQ_400M, CLK_FREQ_500M, CLK_FREQ_600M, CLK_FREQ_700M, + CLK_FREQ_800M, CLK_FREQ_900M, CLK_FREQ_1000M, CLK_FREQ_1200M, CLK_FREQ_1300M, + CLK_FREQ_1400M, CLK_FREQ_1500M, CLK_FREQ_1600M, CLK_FREQ_1700M, CLK_FREQ_1800M}; + + switch (clk->id) { + case EIC7700_APLL_FOUT1: + index = find_closest(rate, apll_clk, ARRAY_SIZE(apll_clk)); + round_rate = apll_clk[index]; + break; + case EIC7700_PLL_CPU: + index = find_closest(rate, cpu_pll_clk, ARRAY_SIZE(cpu_pll_clk)); + round_rate = cpu_pll_clk[index]; + break; + default: + pr_err("%s %d, unknow clk id %d\n", __func__, __LINE__, clk->id); + round_rate = 0; + break; + } + return round_rate; +} + +static const struct clk_ops eswin_clk_pll_ops = { + .set_rate = clk_pll_set_rate, + .recalc_rate = clk_pll_recalc_rate, + .round_rate = clk_pll_round_rate, +}; + +void eswin_clk_register_pll(struct eswin_pll_clock *clks, + int nums, struct eswin_clock_data *data, struct device *dev) +{ + void __iomem *base = data->base; + struct eswin_clk_pll *p_clk = NULL; + struct clk *clk = NULL; + struct clk_init_data init; + int i; + + p_clk = devm_kzalloc(dev, sizeof(*p_clk) * nums, GFP_KERNEL); + + if (!p_clk) + return; + + for (i = 0; i < nums; i++) { + char *name = kzalloc(strlen(clks[i].name) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL); + const char *parent_name = clks[i].parent_name ? kzalloc(strlen(clks[i].parent_name) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL) : NULL; + if (data->numa_id < 0) { + sprintf(name, "%s", clks[i].name); + if (parent_name) { + sprintf((char *)parent_name, "%s", clks[i].parent_name); + } + } else { + sprintf(name, "d%d_%s", data->numa_id, clks[i].name); + if (parent_name) { + sprintf((char *)parent_name, "d%d_%s", data->numa_id, clks[i].parent_name); + } + } + + init.name = name; + init.flags = 0; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.ops = &eswin_clk_pll_ops; + + p_clk->id = clks[i].id; + p_clk->numa_id = data->numa_id; + p_clk->ctrl_reg0 = base + clks[i].ctrl_reg0; + p_clk->pllen_shift = clks[i].pllen_shift; + p_clk->pllen_width = clks[i].pllen_width; + p_clk->refdiv_shift = clks[i].refdiv_shift; + p_clk->refdiv_width = clks[i].refdiv_width; + p_clk->fbdiv_shift = clks[i].fbdiv_shift; + p_clk->fbdiv_width = clks[i].fbdiv_width; + + p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1; + p_clk->frac_shift = clks[i].frac_shift; + p_clk->frac_width = clks[i].frac_width; + + p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2; + p_clk->postdiv1_shift = clks[i].postdiv1_shift; + p_clk->postdiv1_width = clks[i].postdiv1_width; + p_clk->postdiv2_shift = clks[i].postdiv2_shift; + p_clk->postdiv2_width = clks[i].postdiv2_width; + + p_clk->status_reg = base + clks[i].status_reg; + p_clk->lock_shift = clks[i].lock_shift; + p_clk->lock_width = clks[i].lock_width; + + p_clk->hw.init = &init; + + clk = clk_register(dev, &p_clk->hw); + if (IS_ERR(clk)) { + devm_kfree(dev, p_clk); + dev_err(dev, "%s: failed to register clock %s\n", __func__, clks[i].name); + continue; + } + + data->clk_data.clks[clks[i].id] = clk; + p_clk++; + kfree(name); + if (parent_name) { + kfree(parent_name); + } + } +} +EXPORT_SYMBOL_GPL(eswin_clk_register_pll); + +int eswin_clk_register_fixed_factor(const struct eswin_fixed_factor_clock *clks, + int nums, + struct eswin_clock_data *data) +{ + struct clk *clk; + int i; + + for (i = 0; i < nums; i++) { + char *name = kzalloc(strlen(clks[i].name) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL ); + char *parent_name = kzalloc(strlen(clks[i].parent_name) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL ); + if (data->numa_id < 0) { + sprintf(name, "%s", clks[i].name); + sprintf(parent_name, "%s", clks[i].parent_name); + } else { + sprintf(name, "d%d_%s", data->numa_id, clks[i].name); + sprintf(parent_name, "d%d_%s", data->numa_id, clks[i].parent_name); + } + + clk = clk_register_fixed_factor(NULL, name, + parent_name, + clks[i].flags, clks[i].mult, + clks[i].div); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", __func__, name); + kfree(name); + kfree(parent_name); + goto err; + } + data->clk_data.clks[clks[i].id] = clk; + + kfree(name); + kfree(parent_name); + } + + return 0; + +err: + while (i--) + clk_unregister_fixed_factor(data->clk_data.clks[clks[i].id]); + + return PTR_ERR(clk); +} +EXPORT_SYMBOL_GPL(eswin_clk_register_fixed_factor); + +int eswin_clk_register_mux(const struct eswin_mux_clock *clks, + int nums, struct eswin_clock_data *data) +{ + struct clk *clk; + void __iomem *base = data->base; + int i; + int j; + + for (i = 0; i < nums; i++) { + char *name = kzalloc(strlen(clks[i].name) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL ); + + char **parent_names = kzalloc(sizeof(char *) * clks[i].num_parents, + GFP_KERNEL ); + if (data->numa_id < 0) { + sprintf(name, "%s", clks[i].name); + } else { + sprintf(name, "d%d_%s", data->numa_id, clks[i].name); + } + for (j = 0; j < clks[i].num_parents; j++) { + parent_names[j] = kzalloc(strlen(clks[i].parent_names[j]) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL ); + if (data->numa_id < 0) { + sprintf(parent_names[j], "%s", clks[i].parent_names[j]); + } else { + sprintf(parent_names[j], "d%d_%s", + data->numa_id, clks[i].parent_names[j]); + } + } + clk = clk_register_mux_table(NULL, name, + (const char * const*)parent_names, + clks[i].num_parents, clks[i].flags, + base + clks[i].offset, clks[i].shift, + clks[i].mask, clks[i].mux_flags, + clks[i].table, &data->lock); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); + kfree(name); + for (j = 0; j < clks[i].num_parents; j++) { + kfree(parent_names[j]); + } + kfree(parent_names); + goto err; + } + + if (clks[i].alias) + clk_register_clkdev(clk, clks[i].alias, NULL); + + data->clk_data.clks[clks[i].id] = clk; + + kfree(name); + for (j = 0; j < clks[i].num_parents; j++) { + kfree(parent_names[j]); + } + kfree(parent_names); + } + return 0; + +err: + while (i--) + clk_unregister_mux(data->clk_data.clks[clks[i].id]); + + return PTR_ERR(clk); +} +EXPORT_SYMBOL_GPL(eswin_clk_register_mux); + +int eswin_clk_register_divider(const struct eswin_divider_clock *clks, + int nums, struct eswin_clock_data *data) +{ + struct clk *clk; + void __iomem *base = data->base; + int i; + struct clk_hw *clk_hw; + struct clk_hw *parent_hw; + struct clk_parent_data parent_data; + + for (i = 0; i < nums; i++) { + char *name = kzalloc(strlen(clks[i].name) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL ); + char *parent_name = kzalloc(strlen(clks[i].parent_name) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL ); + if (data->numa_id < 0) { + sprintf(name, "%s", clks[i].name); + sprintf(parent_name, "%s", clks[i].parent_name); + } else { + sprintf(name, "d%d_%s", data->numa_id, clks[i].name); + sprintf(parent_name, "d%d_%s", data->numa_id, clks[i].parent_name); + } + parent_hw = eswin_clk_find_parent(data, parent_name); + parent_data.name = parent_name; + parent_data.hw = parent_hw; + parent_data.fw_name = NULL; + clk_hw = clk_hw_register_divider_table_parent_data(NULL, name, + &parent_data, + clks[i].flags, + base + clks[i].offset, + clks[i].shift, clks[i].width, + clks[i].div_flags, + clks[i].table, + &data->lock); + if (IS_ERR(clk_hw)) { + pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); + kfree(name); + kfree(parent_name); + goto err; + } + clk = clk_hw->clk; + if (clks[i].alias) + clk_register_clkdev(clk, clks[i].alias, NULL); + + data->clk_data.clks[clks[i].id] = clk; + kfree(name); + kfree(parent_name); + } + return 0; + +err: + while (i--) + clk_unregister_divider(data->clk_data.clks[clks[i].id]); + + return PTR_ERR(clk); +} +EXPORT_SYMBOL_GPL(eswin_clk_register_divider); + +int eswin_clk_register_gate(const struct eswin_gate_clock *clks, + int nums, struct eswin_clock_data *data) +{ + struct clk *clk; + void __iomem *base = data->base; + int i; + struct clk_hw *clk_hw; + struct clk_hw *parent_hw; + struct clk_parent_data parent_data; + + for (i = 0; i < nums; i++) { + char *name = kzalloc(strlen(clks[i].name) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL); + char *parent_name = kzalloc(strlen(clks[i].parent_name) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL); + if (data->numa_id < 0) { + sprintf(name, "%s", clks[i].name); + sprintf(parent_name, "%s", clks[i].parent_name); + } else { + sprintf(name, "d%d_%s", data->numa_id, clks[i].name); + sprintf(parent_name, "d%d_%s", data->numa_id, clks[i].parent_name); + } + parent_hw = eswin_clk_find_parent(data, parent_name); + parent_data.name = parent_name; + parent_data.hw = parent_hw; + parent_data.fw_name = NULL; + clk_hw = clk_hw_register_gate_parent_data(NULL, name, + &parent_data, + clks[i].flags, + base + clks[i].offset, + clks[i].bit_idx, + clks[i].gate_flags, + &data->lock); + if (IS_ERR(clk_hw)) { + pr_err("%s: failed to register clock %s\n",__func__, clks[i].name); + kfree(name); + kfree(parent_name); + goto err; + } + clk = clk_hw->clk; + if (clks[i].alias) + clk_register_clkdev(clk, clks[i].alias, NULL); + + data->clk_data.clks[clks[i].id] = clk; + kfree(name); + kfree(parent_name); + } + return 0; + +err: + while (i--) + clk_unregister_gate(data->clk_data.clks[clks[i].id]); + + return PTR_ERR(clk); +} +EXPORT_SYMBOL_GPL(eswin_clk_register_gate); + +static const struct clk_ops clk_dummpy_ops = { + +}; + +struct clk *eswin_register_clk(struct eswin_clock_data *data, + struct device *dev, const char *name, + const char *parent_name, + unsigned long flags, + spinlock_t *lock) +{ + struct eswin_clock *eclk; + struct clk *clk; + struct clk_init_data init; + struct clk_parent_data parent_data; + struct clk_hw *parent_hw; + + eclk = kzalloc(sizeof(*eclk), GFP_KERNEL ); + if (!eclk) + return ERR_PTR(-ENOMEM); + + init.ops = &clk_dummpy_ops; + + init.name = name; + init.flags = flags; + init.parent_names = NULL; + init.num_parents = (parent_name ? 1 : 0); + init.parent_data = &parent_data; + + parent_hw = eswin_clk_find_parent(data, (char *)parent_name); + parent_data.name = parent_name; + parent_data.hw = parent_hw; + parent_data.fw_name = NULL; + + eclk->hw.init = &init; + + clk = clk_register(dev, &eclk->hw); + if (IS_ERR(clk)) + kfree(eclk); + + return clk; +} + +int eswin_clk_register_clk(const struct eswin_clock *clks, + int nums, struct eswin_clock_data *data) +{ + struct clk *clk; + int i; + + for (i = 0; i < nums; i++) { + char *name = kzalloc(strlen(clks[i].name) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL ); + char *parent_name = kzalloc(strlen(clks[i].parent_name) + + 2 * sizeof(char) + sizeof(int), GFP_KERNEL ); + if (data->numa_id < 0) { + sprintf(name, "%s", clks[i].name); + sprintf(parent_name, "%s", clks[i].parent_name); + } else { + sprintf(name, "d%d_%s", data->numa_id, clks[i].name); + sprintf(parent_name, "d%d_%s", data->numa_id, clks[i].parent_name); + } + clk = eswin_register_clk(data, NULL, name, parent_name, + clks[i].flags, &data->lock); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); + kfree(name); + kfree(parent_name); + goto err; + } + + if (clks[i].alias) + clk_register_clkdev(clk, clks[i].alias, NULL); + + data->clk_data.clks[clks[i].id] = clk; + kfree(name); + kfree(parent_name); + } + return 0; +err: + while (i--) + clk_unregister_gate(data->clk_data.clks[clks[i].id]); + + return PTR_ERR(clk); +} +EXPORT_SYMBOL_GPL(eswin_clk_register_clk); diff --git a/drivers/clk/eswin/clk.h b/drivers/clk/eswin/clk.h new file mode 100755 index 0000000000000..c5906c4207693 --- /dev/null +++ b/drivers/clk/eswin/clk.h @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Clk Provider 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 . + * + * Authors: HuangYiFeng + */ + +#ifndef __ESWIN_CLK_H +#define __ESWIN_CLK_H + +#include +#include +#include + +struct platform_device; + +struct eswin_clock_data { + struct clk_onecell_data clk_data; + void __iomem *base; + int numa_id; + spinlock_t lock; +}; + +struct eswin_clock { + unsigned int id; + char *name; + const char *parent_name; + unsigned long flags; + struct clk_hw hw; + const char *alias; +}; + +struct eswin_fixed_rate_clock { + unsigned int id; + char *name; + const char *parent_name; + unsigned long flags; + unsigned long fixed_rate; +}; + +struct eswin_fixed_factor_clock { + unsigned int id; + char *name; + const char *parent_name; + unsigned long mult; + unsigned long div; + unsigned long flags; +}; + +struct eswin_mux_clock { + unsigned int id; + const char *name; + const char *const *parent_names; + u8 num_parents; + unsigned long flags; + unsigned long offset; + u8 shift; + u32 mask; + u8 mux_flags; + u32 *table; + const char *alias; +}; + + +struct eswin_divider_clock { + unsigned int id; + const char *name; + const char *parent_name; + unsigned long flags; + unsigned long offset; + u8 shift; + u8 width; + u8 div_flags; + struct clk_div_table *table; + const char *alias; +}; + +struct eswin_gate_clock { + unsigned int id; + const char *name; + const char *parent_name; + unsigned long flags; + unsigned long offset; + u8 bit_idx; + u8 gate_flags; + const char *alias; +}; + +struct eswin_pll_clock { + u32 id; + const char *name; + const char *parent_name; + const u32 ctrl_reg0; + const u8 pllen_shift; + const u8 pllen_width; + const u8 refdiv_shift; + const u8 refdiv_width; + const u8 fbdiv_shift; + const u8 fbdiv_width; + + const u32 ctrl_reg1; + const u8 frac_shift; + const u8 frac_width; + + const u32 ctrl_reg2; + const u8 postdiv1_shift; + const u8 postdiv1_width; + const u8 postdiv2_shift; + const u8 postdiv2_width; + + const u32 status_reg; + const u8 lock_shift; + const u8 lock_width; +}; + +struct eswin_clk_pll { + struct clk_hw hw; + u32 id; + int numa_id; + void __iomem *ctrl_reg0; + u8 pllen_shift; + u8 pllen_width; + u8 refdiv_shift; + u8 refdiv_width; + u8 fbdiv_shift; + u8 fbdiv_width; + + void __iomem *ctrl_reg1; + u8 frac_shift; + u8 frac_width; + + void __iomem *ctrl_reg2; + u8 postdiv1_shift; + u8 postdiv1_width; + u8 postdiv2_shift; + u8 postdiv2_width; + + void __iomem *status_reg; + u8 lock_shift; + u8 lock_width; +}; + +struct eswin_clock_data *eswin_clk_init(struct platform_device *, int); +int eswin_clk_register_fixed_rate(const struct eswin_fixed_rate_clock *, + int, struct eswin_clock_data *); + +void eswin_clk_register_pll(struct eswin_pll_clock *clks, + int nums, struct eswin_clock_data *data, struct device *dev); + +int eswin_clk_register_fixed_factor(const struct eswin_fixed_factor_clock *, + int, struct eswin_clock_data *); +int eswin_clk_register_mux(const struct eswin_mux_clock *, int, + struct eswin_clock_data *); + +int eswin_clk_register_divider(const struct eswin_divider_clock *, + int, struct eswin_clock_data *); +int eswin_clk_register_gate(const struct eswin_gate_clock *, + int, struct eswin_clock_data *); + +int eswin_clk_register_clk(const struct eswin_clock *, + int , struct eswin_clock_data *); + +#define eswin_clk_unregister(type) \ +static inline \ +void eswin_clk_unregister_##type(const struct eswin_##type##_clock *clks, \ + int nums, struct eswin_clock_data *data) \ +{ \ + struct clk **clocks = data->clk_data.clks; \ + int i; \ + for (i = 0; i < nums; i++) { \ + int id = clks[i].id; \ + if (clocks[id]) \ + clk_unregister_##type(clocks[id]); \ + } \ +} + +eswin_clk_unregister(fixed_rate) +eswin_clk_unregister(fixed_factor) +eswin_clk_unregister(mux) +eswin_clk_unregister(divider) +eswin_clk_unregister(gate) + +#endif /* __ESWIN_CLK_H */ From 9ba2d7f74e596169bfdac7e4b7c098aed8eeef3b Mon Sep 17 00:00:00 2001 From: linmin Date: Mon, 29 Jul 2024 17:05:36 +0530 Subject: [PATCH 04/38] riscv: asm: Added changes to asm header files - Added wfe and iomb functions for riscv - Added memory port to system port and system port to memory port conversion macros to access uncached memory through system port - Modified pte_pfn and pfn_pte functions To access uncache memory, we need to remap physical address to system port address. System port pfn address will be stored in pte if uncached bit is set. Signed-off-by: linmin Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- arch/riscv/include/asm/barrier.h | 2 + arch/riscv/include/asm/io.h | 1 + arch/riscv/include/asm/pgtable-bits.h | 1 + arch/riscv/include/asm/pgtable.h | 78 ++++++++++++++++++++++++--- 4 files changed, 76 insertions(+), 6 deletions(-) diff --git a/arch/riscv/include/asm/barrier.h b/arch/riscv/include/asm/barrier.h index 110752594228e..ca07d68c70a29 100644 --- a/arch/riscv/include/asm/barrier.h +++ b/arch/riscv/include/asm/barrier.h @@ -71,6 +71,8 @@ do { \ */ #define smp_mb__after_spinlock() RISCV_FENCE(iorw,iorw) +#define wfe() do { } while (0) + #include #endif /* __ASSEMBLY__ */ diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h index 42497d487a174..d1f0453c65806 100644 --- a/arch/riscv/include/asm/io.h +++ b/arch/riscv/include/asm/io.h @@ -51,6 +51,7 @@ #define __io_par(v) __asm__ __volatile__ ("fence i,ior" : : : "memory"); #define __io_pbw() __asm__ __volatile__ ("fence iow,o" : : : "memory"); #define __io_paw() __asm__ __volatile__ ("fence o,io" : : : "memory"); +#define __iomb() mb() /* * Accesses from a single hart to a single I/O address must be ordered. This diff --git a/arch/riscv/include/asm/pgtable-bits.h b/arch/riscv/include/asm/pgtable-bits.h index f896708e83312..0a8abaf664f2e 100644 --- a/arch/riscv/include/asm/pgtable-bits.h +++ b/arch/riscv/include/asm/pgtable-bits.h @@ -17,6 +17,7 @@ #define _PAGE_ACCESSED (1 << 6) /* Set by hardware on any access */ #define _PAGE_DIRTY (1 << 7) /* Set by hardware on any write */ #define _PAGE_SOFT (1 << 8) /* Reserved for software */ +#define _PAGE_UNCACHE (1 << 9) /* Map to uncached system port */ #define _PAGE_SPECIAL _PAGE_SOFT #define _PAGE_TABLE _PAGE_PRESENT diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index c00bd5377db9a..77a739ab0e80d 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -84,7 +84,7 @@ * Define vmemmap for pfn_to_page & page_to_pfn calls. Needed if kernel * is configured with CONFIG_SPARSEMEM_VMEMMAP enabled. */ -#define vmemmap ((struct page *)VMEMMAP_START - (phys_ram_base >> PAGE_SHIFT)) +#define vmemmap ((struct page *)VMEMMAP_START) #define PCI_IO_SIZE SZ_16M #define PCI_IO_END VMEMMAP_START @@ -208,6 +208,54 @@ extern struct pt_alloc_ops pt_ops __initdata; #define _PAGE_IOREMAP ((_PAGE_KERNEL & ~_PAGE_MTMASK) | _PAGE_IO) #define PAGE_KERNEL_IO __pgprot(_PAGE_IOREMAP) +#if defined(CONFIG_SOC_SIFIVE_EIC7700) +#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_UNCACHE) +#define pgprot_writecombine(prot) pgprot_noncached(prot) +#define pgprot_dmacoherent(prot) pgprot_noncached(prot) + +/* DIE0 */ +#define DIE0_MEM_PORT_PFN_START (CONFIG_RISCV_DIE0_CACHED_OFFSET >> PAGE_SHIFT) +#define DIE0_MEM_PORT_PFN_END ((CONFIG_RISCV_DIE0_CACHED_OFFSET + CONFIG_RISCV_DIE0_MEM_MAX_SIZE) >> PAGE_SHIFT) + +#define DIE0_SYS_PORT_PFN_START (CONFIG_RISCV_DIE0_UNCACHED_OFFSET >> PAGE_SHIFT) +#define DIE0_MEM_TO_SYS_PFN_ADDRESS(a) (DIE0_SYS_PORT_PFN_START + ((u64)(a) - DIE0_MEM_PORT_PFN_START)) +#define DIE0_SYS_TO_MEM_PFN_ADDRESS(a) (DIE0_MEM_PORT_PFN_START + ((u64)(a) - DIE0_SYS_PORT_PFN_START)) +#define DIE0_SYS_PORT_PFN_END ((CONFIG_RISCV_DIE0_UNCACHED_OFFSET + CONFIG_RISCV_DIE0_MEM_MAX_SIZE) >> PAGE_SHIFT) + +/* DIE1 */ +#define DIE1_MEM_PORT_PFN_START (CONFIG_RISCV_DIE1_CACHED_OFFSET >> PAGE_SHIFT) +#define DIE1_MEM_PORT_PFN_END ((CONFIG_RISCV_DIE1_CACHED_OFFSET + CONFIG_RISCV_DIE1_MEM_MAX_SIZE) >> PAGE_SHIFT) + +#define DIE1_SYS_PORT_PFN_START (CONFIG_RISCV_DIE1_UNCACHED_OFFSET >> PAGE_SHIFT) +#define DIE1_MEM_TO_SYS_PFN_ADDRESS(a) (DIE1_SYS_PORT_PFN_START + ((u64)(a) - DIE1_MEM_PORT_PFN_START)) +#define DIE1_SYS_TO_MEM_PFN_ADDRESS(a) (DIE1_MEM_PORT_PFN_START + ((u64)(a) - DIE1_SYS_PORT_PFN_START)) +#define DIE1_SYS_PORT_PFN_END ((CONFIG_RISCV_DIE1_UNCACHED_OFFSET + CONFIG_RISCV_DIE1_MEM_MAX_SIZE) >> PAGE_SHIFT) + +/* interleave */ +#define INTERLEAVE_MEM_PORT_PFN_START (CONFIG_RISCV_INTERLEAVE_CACHED_OFFSET >> PAGE_SHIFT) +#define INTERLEAVE_MEM_PORT_PFN_END ((CONFIG_RISCV_INTERLEAVE_CACHED_OFFSET + CONFIG_RISCV_INTERLEAVE_MEM_MAX_SIZE) >> PAGE_SHIFT) + +#define INTERLEAVE_SYS_PORT_PFN_START (CONFIG_RISCV_INTERLEAVE_UNCACHED_OFFSET >> PAGE_SHIFT) +#define INTERLEAVE_MEM_TO_SYS_PFN_ADDRESS(a) (INTERLEAVE_SYS_PORT_PFN_START + ((u64)(a) - INTERLEAVE_MEM_PORT_PFN_START)) +#define INTERLEAVE_SYS_TO_MEM_PFN_ADDRESS(a) (INTERLEAVE_MEM_PORT_PFN_START + ((u64)(a) - INTERLEAVE_SYS_PORT_PFN_START)) +#define INTERLEAVE_SYS_PORT_PFN_END ((CONFIG_RISCV_INTERLEAVE_UNCACHED_OFFSET + CONFIG_RISCV_INTERLEAVE_MEM_MAX_SIZE) >> PAGE_SHIFT) + +/* pha conversion between mem port and sys port */ +#define convert_pfn_from_mem_to_sys_port(pfn) \ + ((pfn < DIE0_MEM_PORT_PFN_END)?DIE0_MEM_TO_SYS_PFN_ADDRESS(pfn): \ + ((pfn >= DIE1_MEM_PORT_PFN_START && pfn < DIE1_MEM_PORT_PFN_END)?DIE1_MEM_TO_SYS_PFN_ADDRESS(pfn): \ + ((pfn >= INTERLEAVE_MEM_PORT_PFN_START && pfn < INTERLEAVE_MEM_PORT_PFN_END) ? INTERLEAVE_MEM_TO_SYS_PFN_ADDRESS(pfn) : (pfn)))) + +#define convert_pfn_from_sys_to_mem_port(pfn) \ + ((pfn < DIE0_SYS_PORT_PFN_END)?DIE0_SYS_TO_MEM_PFN_ADDRESS(pfn): \ + ((pfn >= DIE1_SYS_PORT_PFN_START && pfn < DIE1_SYS_PORT_PFN_END)?DIE1_SYS_TO_MEM_PFN_ADDRESS(pfn): \ + ((pfn >= INTERLEAVE_SYS_PORT_PFN_START && pfn < INTERLEAVE_SYS_PORT_PFN_END) ? INTERLEAVE_SYS_TO_MEM_PFN_ADDRESS(pfn) : (pfn)))) + +#define convert_pha_from_mem_to_sys_port(pha) \ + (convert_pfn_from_mem_to_sys_port(pha >> PAGE_SHIFT) << PAGE_SHIFT) + +#endif + extern pgd_t swapper_pg_dir[]; extern pgd_t trampoline_pg_dir[]; extern pgd_t early_pg_dir[]; @@ -327,6 +375,15 @@ static inline unsigned long pte_pfn(pte_t pte) { unsigned long res = __page_val_to_pfn(pte_val(pte)); +#if defined(CONFIG_SOC_SIFIVE_EIC7700) + unsigned long pfn_new; + if (unlikely(pte_val(pte) & _PAGE_UNCACHE)) + { + pr_debug("pte_pfn:pfn_sys 0x%lx to pfn_mport 0x%lx\n", (pte_val(pte) >> _PAGE_PFN_SHIFT), pfn_new); + return convert_pfn_from_sys_to_mem_port(pte_val(pte) >> _PAGE_PFN_SHIFT); + } +#endif + if (has_svnapot() && pte_napot(pte)) res = res & (res - 1UL); @@ -340,6 +397,17 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) { unsigned long prot_val = pgprot_val(prot); +#if defined(CONFIG_SOC_SIFIVE_EIC7700) + unsigned long pfn_new; + + if (unlikely(_PAGE_UNCACHE == (pgprot_val(prot) & _PAGE_UNCACHE))) + { + pfn_new = convert_pfn_from_mem_to_sys_port(pfn); + pr_debug("pfn_pte:pfn_mport 0x%lx to pfn_sysport 0x%lx\n", pfn, pfn_new); + return __pte((pfn_new << _PAGE_PFN_SHIFT) | pgprot_val(prot)); + } +#endif + ALT_THEAD_PMA(prot_val); return __pte((pfn << _PAGE_PFN_SHIFT) | prot_val); @@ -438,10 +506,6 @@ static inline pte_t pte_mkhuge(pte_t pte) return pte; } -#define pte_leaf_size(pte) (pte_napot(pte) ? \ - napot_cont_size(napot_cont_order(pte)) :\ - PAGE_SIZE) - #ifdef CONFIG_NUMA_BALANCING /* * See the comment in include/asm-generic/pgtable.h @@ -611,6 +675,7 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma, return ptep_test_and_clear_young(vma, address, ptep); } +#if !defined(CONFIG_SOC_SIFIVE_EIC7700) #define pgprot_noncached pgprot_noncached static inline pgprot_t pgprot_noncached(pgprot_t _prot) { @@ -632,6 +697,7 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _prot) return __pgprot(prot); } +#endif /* * THP functions @@ -884,7 +950,7 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte) #define TASK_SIZE_MIN (PGDIR_SIZE_L3 * PTRS_PER_PGD / 2) #ifdef CONFIG_COMPAT -#define TASK_SIZE_32 (_AC(0x80000000, UL)) +#define TASK_SIZE_32 (_AC(0x80000000, UL) - PAGE_SIZE) #define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \ TASK_SIZE_32 : TASK_SIZE_64) #else From 78bf3d2494d95ccaef8e302e1c64d13a0c1c7a73 Mon Sep 17 00:00:00 2001 From: linmin Date: Mon, 29 Jul 2024 14:19:28 +0000 Subject: [PATCH 05/38] riscv: mm: dma-noncoherent: Add arch_dma_set_uncached Add arch_dma_set_uncached and arch_dma_clear_uncached Signed-off-by: linmin Signed-off-by: Pritesh Patel --- arch/riscv/mm/dma-noncoherent.c | 82 +++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c index 341bd6706b4c5..39b2bea86960e 100644 --- a/arch/riscv/mm/dma-noncoherent.c +++ b/arch/riscv/mm/dma-noncoherent.c @@ -10,6 +10,10 @@ #include #include #include +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +#include +#include +#endif static bool noncoherent_supported __ro_after_init; int dma_cache_alignment __ro_after_init = ARCH_DMA_MINALIGN; @@ -128,6 +132,13 @@ void arch_dma_prep_coherent(struct page *page, size_t size) ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size); } +#ifdef CONFIG_IOMMU_DMA +void arch_teardown_dma_ops(struct device *dev) +{ + dev->dma_ops = NULL; +} +#endif + void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, const struct iommu_ops *iommu, bool coherent) { @@ -137,11 +148,18 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, dev_driver_string(dev), dev_name(dev), ARCH_DMA_MINALIGN, riscv_cbom_block_size); +#ifndef CONFIG_SOC_SIFIVE_EIC7700 WARN_TAINT(!coherent && !noncoherent_supported, TAINT_CPU_OUT_OF_SPEC, "%s %s: device non-coherent but no non-coherent operations supported", dev_driver_string(dev), dev_name(dev)); +#endif dev->dma_coherent = coherent; + +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + if (iommu) + iommu_setup_dma_ops(dev, dma_base, size); +#endif } void riscv_noncoherent_supported(void) @@ -156,3 +174,67 @@ void __init riscv_set_dma_cache_alignment(void) if (!noncoherent_supported) dma_cache_alignment = 1; } +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +static struct page **__iommu_dma_common_find_pages(void *cpu_addr) +{ + struct vm_struct *area = find_vm_area(cpu_addr); + + if (!area || area->flags != VM_DMA_COHERENT) + return NULL; + return area->pages; +} + +void arch_dma_clear_uncached(void *addr, size_t size) +{ + struct page **pages = NULL; + + pages = __iommu_dma_common_find_pages(addr); + if (!pages) { // todo: supposed to handle this error + pr_err( "smmu_dbg, fail to find pages\n"); + + return; + } + kvfree(pages); + memunmap(addr); +} + +void *arch_dma_set_uncached(void *addr, size_t size) +{ + struct page **pages = NULL; + static struct page *page = NULL; + struct vm_struct *area = NULL; + phys_addr_t phys_addr = convert_pha_from_mem_to_sys_port(__pa(addr)); + void *mem_base = NULL; + + mem_base = memremap(phys_addr, size, MEMREMAP_WT); + if (!mem_base) { + pr_err("%s memremap failed for addr %px\n", __func__, addr); + return ERR_PTR(-EINVAL); + } + + pages = kvzalloc(sizeof(*pages), GFP_KERNEL); + if (!pages) { + pr_err("smmu_dbg, failed to alloc memory!\n"); + goto err_pages_alloc; + } + page = virt_to_page(addr); + area = find_vm_area(mem_base); + if (!area) { + pr_err("smmu_dbg, failed to find vm area!\n"); + goto err_find_vm_area; + } + pages[0] = page; + area->pages = pages; + area->flags = VM_DMA_COHERENT; + + return mem_base; + +err_find_vm_area: + kvfree(pages); + +err_pages_alloc: + memunmap(mem_base); + + return NULL; +} +#endif From 8c57a92357010dfe4031ed9ba932910d0bd7382f Mon Sep 17 00:00:00 2001 From: Pinkesh Vaghela Date: Mon, 29 Jul 2024 17:12:50 +0530 Subject: [PATCH 06/38] iommu: Kconfig: Enable ARM SMMU V3 for RISCV Signed-off-by: linmin Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/iommu/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 2b12b583ef4b1..fd7dac2003c66 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -28,7 +28,7 @@ config IOMMU_IO_PGTABLE config IOMMU_IO_PGTABLE_LPAE bool "ARMv7/v8 Long Descriptor Format" select IOMMU_IO_PGTABLE - depends on ARM || ARM64 || COMPILE_TEST + depends on ARM || ARM64 || RISCV || COMPILE_TEST depends on !GENERIC_ATOMIC64 # for cmpxchg64() help Enable support for the ARM long descriptor pagetable format. @@ -389,7 +389,7 @@ config ARM_SMMU_QCOM_DEBUG config ARM_SMMU_V3 tristate "ARM Ltd. System MMU Version 3 (SMMUv3) Support" - depends on ARM64 + depends on ARM64 || RISCV select IOMMU_API select IOMMU_IO_PGTABLE_LPAE select GENERIC_MSI_IRQ From 5edbc64288bd06346ab9d60982dd3fb050c8a7a9 Mon Sep 17 00:00:00 2001 From: Pinkesh Vaghela Date: Mon, 29 Jul 2024 17:31:16 +0530 Subject: [PATCH 07/38] drivers: smmu: Add changes for EIC7700 to arm smmu driver Clearing interrupt bits from interrupt handler because interrupt mode of smmu is oneshot but plic only support high level mode Signed-off-by: linmin Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 85 ++++++++++++++++++++- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 5 ++ 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index bd0a596f9863a..32a4039c9c2be 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -30,8 +30,24 @@ #include "arm-smmu-v3.h" #include "../../dma-iommu.h" #include "../../iommu-sva.h" +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +#include +#include +#include +#define ESWIN_SMMU_IRQ_CLEAR_REG 1 + +/* smmu interrupt clear bits */ +#define TCU_U84_EVENT_Q_IRPT_NS_CLR_BIT 9 +#define TCU_U84_PRI_Q_IRPT_NS_CLR_BIT 10 +#define TCU_U84_GLOBAL_IRPT_NS_CLR_BIT 13 +#endif + +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +static bool disable_bypass = false; +#else static bool disable_bypass = true; +#endif module_param(disable_bypass, bool, 0444); MODULE_PARM_DESC(disable_bypass, "Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU."); @@ -1349,6 +1365,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid, STRTAB_STE_1_STRW_EL2 : STRTAB_STE_1_STRW_NSEL1; BUG_ON(ste_live); + dst[1] = cpu_to_le64( FIELD_PREP(STRTAB_STE_1_S1DSS, STRTAB_STE_1_S1DSS_SSID0) | FIELD_PREP(STRTAB_STE_1_S1CIR, STRTAB_STE_1_S1C_CACHE_WBRA) | @@ -1560,6 +1577,33 @@ static int arm_smmu_handle_evt(struct arm_smmu_device *smmu, u64 *evt) return ret; } +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +static void eswin_smmu_irq_clear(struct arm_smmu_device *smmu, int clearbit) +{ + int bitmask; + bitmask = BIT(clearbit); + + regmap_write(smmu->regmap, smmu->smmu_irq_clear_reg, bitmask); +} + +static irqreturn_t eswin_smmu_irq_clear_handler(int irq, void *dev) +{ + struct arm_smmu_device *smmu = dev; + + if (irq == smmu->evtq.q.irq) { + eswin_smmu_irq_clear(smmu, TCU_U84_EVENT_Q_IRPT_NS_CLR_BIT); + } + else if (irq == smmu->priq.q.irq) { + eswin_smmu_irq_clear(smmu, TCU_U84_PRI_Q_IRPT_NS_CLR_BIT); + } + else { + return IRQ_NONE; + } + + return IRQ_WAKE_THREAD; +} +#endif + static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev) { int i, ret; @@ -1664,6 +1708,10 @@ static irqreturn_t arm_smmu_gerror_handler(int irq, void *dev) u32 gerror, gerrorn, active; struct arm_smmu_device *smmu = dev; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + eswin_smmu_irq_clear(smmu, TCU_U84_GLOBAL_IRPT_NS_CLR_BIT); +#endif + gerror = readl_relaxed(smmu->base + ARM_SMMU_GERROR); gerrorn = readl_relaxed(smmu->base + ARM_SMMU_GERRORN); @@ -2402,6 +2450,7 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master) master->domain = NULL; master->ats_enabled = false; + arm_smmu_install_ste_for_dev(master); } @@ -2453,7 +2502,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) ret = -EINVAL; goto out_unlock; } - master->domain = smmu_domain; /* @@ -2617,7 +2665,6 @@ static int arm_smmu_insert_master(struct arm_smmu_device *smmu, } if (ret) break; - rb_link_node(&new_stream->node, parent_node, new_node); rb_insert_color(&new_stream->node, &smmu->streams); } @@ -3205,10 +3252,17 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu) /* Request interrupt lines */ irq = smmu->evtq.q.irq; if (irq) { +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + ret = devm_request_threaded_irq(smmu->dev, irq, eswin_smmu_irq_clear_handler, + arm_smmu_evtq_thread, + IRQF_ONESHOT, + "arm-smmu-v3-evtq", smmu); +#else ret = devm_request_threaded_irq(smmu->dev, irq, NULL, arm_smmu_evtq_thread, IRQF_ONESHOT, "arm-smmu-v3-evtq", smmu); +#endif if (ret < 0) dev_warn(smmu->dev, "failed to enable evtq irq\n"); } else { @@ -3228,11 +3282,19 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu) if (smmu->features & ARM_SMMU_FEAT_PRI) { irq = smmu->priq.q.irq; if (irq) { +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + ret = devm_request_threaded_irq(smmu->dev, irq, eswin_smmu_irq_clear_handler, + arm_smmu_priq_thread, + IRQF_ONESHOT, + "arm-smmu-v3-priq", + smmu); +#else ret = devm_request_threaded_irq(smmu->dev, irq, NULL, arm_smmu_priq_thread, IRQF_ONESHOT, "arm-smmu-v3-priq", smmu); +#endif if (ret < 0) dev_warn(smmu->dev, "failed to enable priq irq\n"); @@ -3523,8 +3585,10 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) if (reg & IDR0_HYP) { smmu->features |= ARM_SMMU_FEAT_HYP; + #ifdef CONFIG_ARM64 if (cpus_have_cap(ARM64_HAS_VIRT_HOST_EXTN)) smmu->features |= ARM_SMMU_FEAT_E2H; + #endif } /* @@ -3849,8 +3913,23 @@ static int arm_smmu_device_probe(struct platform_device *pdev) smmu->page1 = smmu->base; } - /* Interrupt lines */ +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + /* eswin, syscon devie is used for clearing the smmu interrupt */ + smmu->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,syscfg"); + if (IS_ERR(smmu->regmap)) { + dev_err(smmu->dev, "No syscfg phandle specified\n"); + return PTR_ERR(smmu->regmap); + } + ret = of_property_read_u32_index(dev->of_node, "eswin,syscfg", ESWIN_SMMU_IRQ_CLEAR_REG, + &smmu->smmu_irq_clear_reg); + if (ret) { + dev_err(dev, "can't get SMMU irq clear reg offset (%d)\n", ret); + return ret; + } +#endif + + /* Interrupt lines */ irq = platform_get_irq_byname_optional(pdev, "combined"); if (irq > 0) smmu->combined_irq = irq; diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h index 9915850dd4dbf..36da241ec165a 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -682,6 +682,11 @@ struct arm_smmu_device { struct rb_root streams; struct mutex streams_mutex; + +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + struct regmap *regmap; + int smmu_irq_clear_reg; +#endif }; struct arm_smmu_stream { From a4b572ceb549526e01cb0878db14210d0d6394f0 Mon Sep 17 00:00:00 2001 From: linmin Date: Mon, 29 Jul 2024 14:34:51 +0000 Subject: [PATCH 08/38] driver: iommu: Add IOMMU driver for EIC7700 Signed-off-by: linmin Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/iommu/Kconfig | 6 + drivers/iommu/Makefile | 1 + drivers/iommu/eswin/Makefile | 2 + drivers/iommu/eswin/eic7700-sid.c | 663 ++++++++++++++++++++++++++++++ include/linux/eic7700-sid-cfg.h | 8 + 5 files changed, 680 insertions(+) create mode 100644 drivers/iommu/eswin/Makefile create mode 100644 drivers/iommu/eswin/eic7700-sid.c create mode 100644 include/linux/eic7700-sid-cfg.h diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index fd7dac2003c66..2556a82997449 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -7,6 +7,12 @@ config IOMMU_IOVA config IOMMU_API bool +config IOMMU_ESWIN + bool "IOMMU EIC7700 Support" + help + Say Y here if you want to compile device drivers for IO Memory + management implementation for EIC7700 + menuconfig IOMMU_SUPPORT bool "IOMMU Hardware Support" depends on MMU diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 769e43d780ce8..91c3ed52daf91 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += amd/ intel/ arm/ iommufd/ +obj-$(CONFIG_IOMMU_ESWIN) += eswin/ obj-$(CONFIG_IOMMU_API) += iommu.o obj-$(CONFIG_IOMMU_API) += iommu-traces.o obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o diff --git a/drivers/iommu/eswin/Makefile b/drivers/iommu/eswin/Makefile new file mode 100644 index 0000000000000..d63610d53d4ff --- /dev/null +++ b/drivers/iommu/eswin/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_IOMMU_ESWIN) += eic7700-sid.o diff --git a/drivers/iommu/eswin/eic7700-sid.c b/drivers/iommu/eswin/eic7700-sid.c new file mode 100644 index 0000000000000..f45e3c1d793e1 --- /dev/null +++ b/drivers/iommu/eswin/eic7700-sid.c @@ -0,0 +1,663 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 ESWIN. All rights reserved. + * Author: Lin Min + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DYMN_CSR_EN_REG_OFFSET 0x0 +#define DYMN_CSR_GNT_REG_OFFSET 0x4 + +#define MCPU_SP0_DYMN_CSR_EN_BIT 3 +#define MCPU_SP0_DYMN_CSR_GNT_BIT 3 + +#define AWSMMUSID GENMASK(31, 24) // The sid of write operation +#define AWSMMUSSID GENMASK(23, 16) // The ssid of write operation +#define ARSMMUSID GENMASK(15, 8) // The sid of read operation +#define ARSMMUSSID GENMASK(7, 0) // The ssid of read operation + +struct eic7700_sid_client { + const char *name; + unsigned int sid; + unsigned int reg_offset; +}; + +struct eic7700_sid_soc { + const struct eic7700_sid_client *clients; + unsigned int num_clients; +}; + +/* The syscon registers for tbu power up(down) must be configured so that + tcu can be aware of tbu up and down. + + */ +struct tbu_reg_cfg_info { + unsigned int reg_offset; + unsigned int qreqn_pd_bit; + unsigned int qacceptn_pd_bit; +}; + +struct tbu_priv { + atomic_t refcount; + int nid; + const struct eic7700_tbu_client *tbu_client_p; + struct mutex tbu_priv_lock; +}; + +struct eic7700_tbu_client { + /* tbu_id: bit[3:0] is for major ID, bit[7:4] is for minor ID; + For example, tbu of dsp3 is tbu7_3, the tbu_ID is 0x73. It measn tbu7_3 + */ + u32 tbu_id; + struct tbu_reg_cfg_info tbu_reg_info; + int (*tbu_power_ctl_register) (int nid, struct tbu_priv *tbu_priv_p, bool is_powerUp); +}; + +struct eic7700_tbu_soc { + const struct eic7700_tbu_client *tbu_clients; + unsigned int num_tbuClients; +}; + + + +struct tbu_power_soc { + struct tbu_priv *tbu_priv_array; + unsigned int num_tbuClients; +}; + +struct eic7700_sid { + void __iomem *regs; + resource_size_t start; + const struct eic7700_sid_soc *soc; + struct mutex eswin_dynm_sid_cfg_en_lock; + struct tbu_power_soc *tbu_power_soc; + struct mutex tbu_reg_lock; +}; +struct eic7700_sid *syscon_sid_cfg[MAX_NUMNODES] = {NULL}; + +static int eic7700_tbu_power_ctl_register(int nid, struct tbu_priv *tbu_priv_p, bool is_powerUp); + +static int eic7700_tbu_powr_priv_init(struct tbu_power_soc **tbu_power_soc_pp, int nid); + +int eic7700_dynm_sid_enable(int nid) +{ + unsigned long reg_val; + struct eic7700_sid *mc = NULL; + + if (nid == NUMA_NO_NODE) { + #ifdef CONFIG_NUMA + pr_err("%s:%d, NUMA_NO_NODE\n", __func__, __LINE__); + return -EFAULT; + #else + pr_info("%s:%d, NUMA_NO_NODE, single DIE\n", __func__, __LINE__); + nid = 0; + #endif + } + + mc = syscon_sid_cfg[nid]; + if (mc == NULL) + return -EFAULT; + + mutex_lock(&mc->eswin_dynm_sid_cfg_en_lock); + reg_val = readl(mc->regs + DYMN_CSR_EN_REG_OFFSET); + set_bit(MCPU_SP0_DYMN_CSR_EN_BIT, ®_val); + writel(reg_val, mc->regs + DYMN_CSR_EN_REG_OFFSET); + + while(1) { + reg_val = readl(mc->regs + DYMN_CSR_GNT_REG_OFFSET) & (1 << MCPU_SP0_DYMN_CSR_GNT_BIT); + if (reg_val) + break; + + msleep(10); + } + reg_val = readl(mc->regs + DYMN_CSR_EN_REG_OFFSET); + clear_bit(MCPU_SP0_DYMN_CSR_EN_BIT, ®_val); + writel(reg_val, mc->regs + DYMN_CSR_EN_REG_OFFSET); + mutex_unlock(&mc->eswin_dynm_sid_cfg_en_lock); + + return 0; +} +EXPORT_SYMBOL(eic7700_dynm_sid_enable); + +int eic7700_aon_sid_cfg(struct device *dev) +{ + int ret = 0; + struct regmap *regmap; + int aon_sid_reg; + u32 rdwr_sid_ssid; + u32 sid; + int i,sid_count; + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + struct device_node *np_syscon; + int syscon_cell_size = 0; + + /* not behind smmu, use the default reset value(0x0) of the reg as streamID*/ + if (fwspec == NULL) { + dev_info(dev, "dev is not behind smmu, skip configuration of sid\n"); + return 0; + } + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,syscfg"); + if (IS_ERR(regmap)) { + dev_err(dev, "No eswin,syscfg phandle specified\n"); + return -1; + } + + np_syscon = of_parse_phandle(dev->of_node, "eswin,syscfg", 0); + if (np_syscon) { + if (of_property_read_u32(np_syscon, "#syscon-cells", &syscon_cell_size)) { + of_node_put(np_syscon); + dev_err(dev, "failed to get #syscon-cells of sys_con\n"); + return -1; + } + of_node_put(np_syscon); + } + + sid_count = of_count_phandle_with_args(dev->of_node, + "eswin,syscfg", "#syscon-cells"); + + dev_dbg(dev, "sid_count=%d, fwspec->num_ids=%d, syscon_cell_size=%d\n", + sid_count, fwspec->num_ids, syscon_cell_size); + + if (sid_count < 0) { + dev_err(dev, "failed to parse eswin,syscfg property!\n"); + return -1; + } + + if (fwspec->num_ids != sid_count) { + dev_err(dev, "num_ids(%d) is NOT equal to num of sid regs(%d)!\n", + fwspec->num_ids, sid_count); + return -1; + } + + for (i = 0; i < sid_count; i++) { + sid = fwspec->ids[i]; + ret = of_property_read_u32_index(dev->of_node, "eswin,syscfg", (syscon_cell_size + 1)*i+1, + &aon_sid_reg); + if (ret) { + dev_err(dev, "can't get sid cfg reg offset in sys_con(errno:%d)\n", ret); + return ret; + } + + /* make the reading sid the same as writing sid, ssid is fixed to zero */ + rdwr_sid_ssid = FIELD_PREP(AWSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(AWSMMUSSID, 0); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSSID, 0); + regmap_write(regmap, aon_sid_reg, rdwr_sid_ssid); + + ret = eic7700_dynm_sid_enable(dev_to_node(dev)); + if (ret < 0) + dev_err(dev, "failed to config streamID(%d) for %s!\n", sid, of_node_full_name(dev->of_node)); + else + dev_info(dev, "success to config dma streamID(%d) for %s!\n", sid, of_node_full_name(dev->of_node)); + } + + return ret; +} +EXPORT_SYMBOL(eic7700_aon_sid_cfg); + +static int of_parse_syscon_nodes(struct device_node *np, int *nid_p) +{ + #ifdef CONFIG_NUMA + int nid; + int r; + + r = of_property_read_u32(np, "numa-node-id", &nid); + if (r) + return -EINVAL; + + pr_debug("Syscon on %u\n", nid); + if (nid >= MAX_NUMNODES) { + pr_warn("Node id %u exceeds maximum value\n", nid); + return -EINVAL; + } + else + *nid_p = nid; + #else + *nid_p = 0; + #endif + + pr_debug("%s, nid = %d\n", __func__, *nid_p); + + return 0; +} + +#if defined(CONFIG_RISCV) +static const struct eic7700_sid_client eic7700_sid_clients[] = { + { + .name = "scpu", + .sid = EIC7700_SID_SCPU, + .reg_offset = SCPU_SID_REG_OFFSET, + }, + { + .name = "dma1", + .sid = EIC7700_SID_DMA1, + .reg_offset = DMA1_SID_REG_OFFSET, + }, + //{ + // .name = "crypt", + // .sid = EIC7700_SID_CRYPT, + // .reg_offset = CRYPT_SID_REG_OFFSET, + //} +}; + +static const struct eic7700_sid_soc eic7700_sid_soc = { + .num_clients = ARRAY_SIZE(eic7700_sid_clients), + .clients = eic7700_sid_clients, +}; +#endif + +static const struct of_device_id eic7700_sid_of_match[] = { + { .compatible = "eswin,eic7700-scu-sys-con", .data = &eic7700_sid_soc }, + { /* sentinel */ } +}; + +static int __init eic7700_init_streamID(void) +{ + const struct of_device_id *match; + struct device_node *root, *child = NULL; + struct resource regs; + struct eic7700_sid *mc = NULL; + int nid; + int ret = 0; + + root = of_find_node_by_name(NULL, "soc"); + for_each_child_of_node(root, child) { + match = of_match_node(eic7700_sid_of_match, child); + if (match && of_node_get(child)) { + if (of_address_to_resource(child, 0, ®s) < 0) { + pr_err("failed to get scu register\n"); + of_node_put(child); + ret = -ENXIO; + break; + } + if (of_parse_syscon_nodes(child, &nid) < 0) { + pr_err("failed to get numa-node-id\n"); + of_node_put(child); + ret = -ENXIO; + break; + } + + /* program scu sreamID related registers */ + mc = kzalloc(sizeof(*mc), GFP_KERNEL); + if (!mc) { + of_node_put(child); + pr_err("failed to kzalloc\n"); + ret = -ENOMEM; + break; + } + + mc->soc = match->data; + mc->regs = ioremap(regs.start, resource_size(®s)); + if (IS_ERR(mc->regs)) { + pr_err("failed to ioremap scu reges\n"); + of_node_put(child); + ret = PTR_ERR(mc->regs); + kfree(mc); + break; + } + mc->start = regs.start; + mutex_init(&mc->eswin_dynm_sid_cfg_en_lock); + + if (eic7700_tbu_powr_priv_init(&mc->tbu_power_soc, nid)) { + pr_err("failed to kzalloc for tbu_power_priv_arry\n"); + of_node_put(child); + iounmap(mc->regs); + kfree(mc); + ret = -ENOMEM; + WARN_ON(1); + break; + } + mutex_init(&mc->tbu_reg_lock); + + syscon_sid_cfg[nid] = mc; + pr_debug("%s, syscon_sid_cfg[%d] addr is 0x%px\n", __func__, nid, syscon_sid_cfg[nid]); + + of_node_put(child); + } + } + of_node_put(root); + + return ret; +} + +early_initcall(eic7700_init_streamID); + + + +static const struct eic7700_tbu_client eic7700_tbu_clients[] = { + { + .tbu_id = EIC7700_TBUID_0x0, // ISP, DW200 share the tbu0 + .tbu_reg_info = {0x3d8, 7, 6}, + .tbu_power_ctl_register = eic7700_tbu_power_ctl_register, + }, + { + .tbu_id = EIC7700_TBUID_0x10, // tbu1_0 is only for video decoder + .tbu_reg_info = {0x3d4, 31, 30}, + .tbu_power_ctl_register = NULL, + }, + { + .tbu_id = EIC7700_TBUID_0x11, // tbu1_1 is only video encoder + .tbu_reg_info = {0x3d4, 23, 22}, + .tbu_power_ctl_register = NULL, + }, + { + .tbu_id = EIC7700_TBUID_0x12, // tbu1_2 is only Jpeg encoder + .tbu_reg_info = {0x3d4, 7, 6}, + .tbu_power_ctl_register = NULL, + }, + { + .tbu_id = EIC7700_TBUID_0x13, // tbu1_3 is only Jpeg decoder + .tbu_reg_info = {0x3d4, 15, 14}, + .tbu_power_ctl_register = NULL, + }, + { + .tbu_id = EIC7700_TBUID_0x2, // Ethernet, sata, usb, dma0, emmc, sd, sdio share the tbu2 + .tbu_reg_info = {0x3d8, 15, 14}, + .tbu_power_ctl_register = eic7700_tbu_power_ctl_register, + }, + { + .tbu_id = EIC7700_TBUID_0x3, // tbu3 is only for pcie + .tbu_reg_info = {0x3d8, 23, 22}, + .tbu_power_ctl_register = NULL, + }, + { + .tbu_id = EIC7700_TBUID_0x4, // scpu, crypto, lpcpu, dma1 share the tbu4 + .tbu_reg_info = {0x3d8, 31, 30}, + .tbu_power_ctl_register = eic7700_tbu_power_ctl_register, + }, + { + .tbu_id = EIC7700_TBUID_0x5, // tbu5 is only NPU + .tbu_reg_info = {0x3d0, 15, 14}, + .tbu_power_ctl_register = NULL, + }, + { + .tbu_id = EIC7700_TBUID_0x70, // tbu7_0 is only dsp0 + .tbu_reg_info = {0x3f8, 7, 6}, + .tbu_power_ctl_register = NULL, + }, + { + .tbu_id = EIC7700_TBUID_0x71, // tbu7_1 is only dsp1 + .tbu_reg_info = {0x3f8, 15, 14}, + .tbu_power_ctl_register = NULL, + }, + { + .tbu_id = EIC7700_TBUID_0x72, // tbu7_2 is only dsp2 + .tbu_reg_info = {0x3f8, 23, 22}, + .tbu_power_ctl_register = NULL, + }, + { + .tbu_id = EIC7700_TBUID_0x73, // tbu7_3 is only dsp3 + .tbu_reg_info = {0x3f8, 31, 30}, + .tbu_power_ctl_register = NULL, + }, +}; + +static const struct eic7700_tbu_soc eic7700_tbu_soc = { + .num_tbuClients = ARRAY_SIZE(eic7700_tbu_clients), + .tbu_clients = eic7700_tbu_clients, +}; + +static int __do_eic7700_tbu_power_ctl(int nid, bool is_powerUp, const struct tbu_reg_cfg_info *tbu_reg_info_p) +{ + int ret = 0; + unsigned long reg_val; + struct eic7700_sid *mc = NULL; + int loop_cnt = 0; + mc = syscon_sid_cfg[nid]; + if (mc == NULL) + return -EFAULT; + + mutex_lock(&mc->tbu_reg_lock); + if (is_powerUp) { + reg_val = readl(mc->regs + tbu_reg_info_p->reg_offset); + set_bit(tbu_reg_info_p->qreqn_pd_bit, ®_val); + writel(reg_val, mc->regs + tbu_reg_info_p->reg_offset); + pr_debug("reg_offset=0x%03x, tbu_val=0x%x\n", + tbu_reg_info_p->reg_offset, readl(mc->regs + tbu_reg_info_p->reg_offset)); + pr_debug("%s, power up!\n", __func__); + } + else { + reg_val = readl(mc->regs + tbu_reg_info_p->reg_offset); + clear_bit(tbu_reg_info_p->qreqn_pd_bit, ®_val); + writel(reg_val, mc->regs + tbu_reg_info_p->reg_offset); + do { + reg_val = readl(mc->regs + tbu_reg_info_p->reg_offset); + pr_debug("reg_offset=0x%03x, tbu_val=0x%lx, BIT(qacceptn_pd_bit)=0x%lx\n", + tbu_reg_info_p->reg_offset, reg_val, BIT(tbu_reg_info_p->qacceptn_pd_bit)); + if ((reg_val & BIT(tbu_reg_info_p->qacceptn_pd_bit)) == 0) { + pr_debug("%s, power down!\n", __func__); + break; + } + mdelay(10); + loop_cnt++; + if (loop_cnt > 10) { + WARN_ON(1); // it should never happen. + break; + } + }while (1); + + if(loop_cnt > 10) { + ret = -1; + } + } + mutex_unlock(&mc->tbu_reg_lock); + + return ret; +} + +#define do_eic7700_tbu_power_up(nid, tbu_reg_info_p) __do_eic7700_tbu_power_ctl(nid, true, tbu_reg_info_p) +#define do_eic7700_tbu_power_down(nid, tbu_reg_info_p) __do_eic7700_tbu_power_ctl(nid, false, tbu_reg_info_p) + +static int tbu_power_down_ref_release(atomic_t *ref) +{ + int ret = 0; + struct tbu_priv *tbu_priv_p = container_of(ref, struct tbu_priv, refcount); + int nid = tbu_priv_p->nid; + const struct tbu_reg_cfg_info *tbu_reg_info_p = &tbu_priv_p->tbu_client_p->tbu_reg_info; + + WARN_ON(!tbu_priv_p); + if (!tbu_priv_p) + return -1; + + ret = do_eic7700_tbu_power_down(nid, tbu_reg_info_p); + + return ret; +} + +static int eic7700_tbu_power_ctl_register(int nid, struct tbu_priv *tbu_priv_p, bool is_powerUp) +{ + int ret = 0; + const struct eic7700_tbu_client *tbu_client_p = tbu_priv_p->tbu_client_p; + const struct tbu_reg_cfg_info *tbu_reg_info_p = &tbu_priv_p->tbu_client_p->tbu_reg_info; + unsigned int old_refcount; + + mutex_lock(&tbu_priv_p->tbu_priv_lock); + old_refcount = atomic_read(&tbu_priv_p->refcount); + + pr_debug("%s, nid=%d, is_powerUp=%d, tbu_priv_p addr is 0x%px\n", + __func__, nid, is_powerUp, tbu_priv_p); + if (is_powerUp == false) { //power down + if (unlikely(0 == old_refcount)) { + pr_debug("%s, tbu_id 0x%02x is down already!\n", __func__, tbu_client_p->tbu_id); + goto tbu_finish; + } + + if (atomic_sub_return(1, &tbu_priv_p->refcount) == 0) { + ret = tbu_power_down_ref_release(&tbu_priv_p->refcount); + } + else { + pr_debug("Can't power down tbu 0x%02x, it's used by other modules right now!\n", + tbu_client_p->tbu_id); + } + + } + else { //power up + if (0 == old_refcount) { + ret = do_eic7700_tbu_power_up(nid, tbu_reg_info_p); + } + else { + pr_debug("tbu 0x%02x is already power up!", tbu_client_p->tbu_id); + } + atomic_add(1, &tbu_priv_p->refcount); + } + +tbu_finish: + mutex_unlock(&tbu_priv_p->tbu_priv_lock); + + return ret; + +} + +static int eic7700_tbu_powr_priv_init(struct tbu_power_soc **tbu_power_soc_pp, int nid) +{ + int ret = 0; + int i; + unsigned int num_tbuClients = eic7700_tbu_soc.num_tbuClients; + struct tbu_power_soc *tbu_power_soc_p; + struct tbu_priv *tbu_priv_p; + unsigned int alloc_size; + + pr_debug("%s:%d\n", __func__, __LINE__); + + tbu_power_soc_p = kzalloc(sizeof(struct tbu_power_soc), GFP_KERNEL); + if (!tbu_power_soc_p) + return -ENOMEM; + pr_debug("%s:%d, tbu_power_soc_p(0x%px)\n", __func__, __LINE__, tbu_power_soc_p); + + alloc_size = num_tbuClients * sizeof(struct tbu_priv); + tbu_priv_p = kzalloc(alloc_size, GFP_KERNEL); + if (!tbu_priv_p) { + ret = -ENOMEM; + goto err_tbu_priv_p; + } + tbu_power_soc_p->tbu_priv_array = tbu_priv_p; + pr_debug("%s:%d, num_tbu=%d,sizeof(struct tbu_priv)=0x%lx, alloc_size=0x%x, tbu_priv_p=0x%px\n", + __func__, __LINE__, num_tbuClients, sizeof(struct tbu_priv), alloc_size, tbu_priv_p); + + for (i = 0; i < eic7700_tbu_soc.num_tbuClients; i++) { + tbu_priv_p->nid = nid; + atomic_set(&tbu_priv_p->refcount, 0); + tbu_priv_p->tbu_client_p = &eic7700_tbu_soc.tbu_clients[i]; + mutex_init(&tbu_priv_p->tbu_priv_lock); + pr_debug("%s, nid %d, tbu 0x%02x, tbu_priv_p(0x%px), sizeof(struct tbu_priv)=0x%lx\n", __func__, nid, tbu_priv_p->tbu_client_p->tbu_id, tbu_priv_p, sizeof(struct tbu_priv)); + tbu_priv_p++; + } + tbu_power_soc_p->num_tbuClients = num_tbuClients; + + *tbu_power_soc_pp = tbu_power_soc_p; + + return 0; + +err_tbu_priv_p: + kfree(tbu_power_soc_p); + + return ret; + +} + +static int eic7700_get_tbu_priv(int nid, u32 tbu_id, struct tbu_priv **tbu_priv_pp) +{ + int i; + struct eic7700_sid *mc = syscon_sid_cfg[nid]; + struct tbu_power_soc *tbu_power_soc_p = mc->tbu_power_soc; + struct tbu_priv *tbu_priv_p = tbu_power_soc_p->tbu_priv_array; + + pr_debug("%s, syscon_sid_cfg[%d] addr is 0x%px, tbu_id=0x%02x, tbu_power_soc_p is 0x%px\n", + __func__, nid, syscon_sid_cfg[nid], tbu_id, tbu_power_soc_p); + + for (i = 0; i < tbu_power_soc_p->num_tbuClients; i++) { + if (tbu_id == tbu_priv_p->tbu_client_p->tbu_id) { + *tbu_priv_pp = tbu_priv_p; + pr_debug("%s, found tbu_id 0x%02x, tbu_priv_array[%d] tbu_priv_p is 0x%px\n", + __func__, tbu_id, i, tbu_priv_p); + return 0; + } + tbu_priv_p++; + } + + return -1; +} + +/*********************************************************************************************** + eic7700_tbu_power(struct device *dev, bool is_powerUp) is for powering up or down + the tbus of the device module which is under smmu. + Drivers should call eic7700_tbu_power(dev, true) when probing afer clk of the tbu is on, + and call call eic7700_tbu_power(dev, false) when removing driver before clk of the tbu is off. + + Input: + struct device *dev The struct device of the driver that calls this API. + bool is_powerUp true: power up the tbus; false: power down the tbus. + Return: + zero: successfully power up/down + none zero: faild to power up/down +***********************************************************************************************/ +int eic7700_tbu_power(struct device *dev, bool is_powerUp) +{ + int ret = 0; + struct device_node *node = dev->of_node; + int nid = dev_to_node(dev); + u32 tbu_id; + const struct eic7700_tbu_client *tbu_client_p = NULL; + struct tbu_priv *tbu_priv_p; + struct property *prop; + const __be32 *cur; + int tbu_num = 0; + + if (nid == NUMA_NO_NODE) { + #ifdef CONFIG_NUMA + pr_err("%s:%d, NUMA_NO_NODE\n", __func__, __LINE__); + return -EFAULT; + #else + pr_info("%s:%d, NUMA_NO_NODE, single DIE\n", __func__, __LINE__); + nid = 0; + #endif + } + + pr_debug("%s called!\n", __func__); + of_property_for_each_u32(node, "tbus", prop, cur, tbu_id) { + pr_debug("tbus = <0x%02x>\n", tbu_id); + if (0 == eic7700_get_tbu_priv(nid, tbu_id, &tbu_priv_p)) { + tbu_client_p = tbu_priv_p->tbu_client_p; + if (tbu_client_p->tbu_power_ctl_register) { + ret = tbu_client_p->tbu_power_ctl_register(nid, tbu_priv_p, is_powerUp); + if (ret) + return ret; + } + else { + ret = __do_eic7700_tbu_power_ctl(nid, is_powerUp, &tbu_client_p->tbu_reg_info); + if (ret) + return ret; + } + tbu_num++; + } + else if (tbu_id == EIC7700_TBUID_0xF00) { + tbu_num++; + } + else { + pr_err("tbu power ctl failed!, Couldn't find tbu 0x%x\n", tbu_id); + return -1; + } + } + + if (tbu_num == 0) { + pr_err("Err,tbu NOT defined in dts!!!!\n"); + WARN_ON(1); + } + + return ret; +} +EXPORT_SYMBOL(eic7700_tbu_power); diff --git a/include/linux/eic7700-sid-cfg.h b/include/linux/eic7700-sid-cfg.h new file mode 100644 index 0000000000000..60f47630b8c82 --- /dev/null +++ b/include/linux/eic7700-sid-cfg.h @@ -0,0 +1,8 @@ +#ifndef EIC7700_SID_CFG_H +#define EIC7700_SID_CFG_H + +int eic7700_dynm_sid_enable(int nid); +int eic7700_aon_sid_cfg(struct device *dev); +int eic7700_tbu_power(struct device *dev, bool is_powerUp); + +#endif From 08e9d3541adc2131ae847be082ff80c18d97a755 Mon Sep 17 00:00:00 2001 From: Pinkesh Vaghela Date: Fri, 19 Jul 2024 06:42:01 +0000 Subject: [PATCH 09/38] drivers: sifive_ccache: Add riscv nonstd cache ops The EIC7700 has non-coherent DMAs but predate the standard RISC-V Zicbom extension, so instead we need to use this cache controller for non-standard cache management operations Reference: https://github.com/torvalds/linux/commit/0d5701dc9cd653ae757cc06e39b3a39272863395 Signed-off-by: Emil Renner Berthing Signed-off-by: Conor Dooley Signed-off-by: Pinkesh Vaghela --- drivers/soc/sifive/sifive_ccache.c | 57 ++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/drivers/soc/sifive/sifive_ccache.c b/drivers/soc/sifive/sifive_ccache.c index 3684f5b40a80e..a0bf6d3747e65 100644 --- a/drivers/soc/sifive/sifive_ccache.c +++ b/drivers/soc/sifive/sifive_ccache.c @@ -8,13 +8,16 @@ #define pr_fmt(fmt) "CCACHE: " fmt +#include #include #include #include #include #include #include +#include #include +#include #include #define SIFIVE_CCACHE_DIRECCFIX_LOW 0x100 @@ -44,6 +47,10 @@ #define SIFIVE_CCACHE_MAX_ECCINTR 4 +#define SIFIVE_CCACHE_FLUSH64 0x200 +#define SIFIVE_CCACHE_FLUSH32 0x240 +#define SIFIVE_CCACHE_LINE_SIZE 64 + static void __iomem *ccache_base; static int g_irq[SIFIVE_CCACHE_MAX_ECCINTR]; static struct riscv_cacheinfo_ops ccache_cache_ops; @@ -56,6 +63,10 @@ enum { DIR_UNCORR, }; +enum { + QUIRK_NONSTANDARD_CACHE_OPS = BIT(0), +}; + #ifdef CONFIG_DEBUG_FS static struct dentry *sifive_test; @@ -107,11 +118,41 @@ static const struct of_device_id sifive_ccache_ids[] = { { .compatible = "sifive,fu540-c000-ccache" }, { .compatible = "sifive,fu740-c000-ccache" }, { .compatible = "sifive,ccache0" }, + { .compatible = "sifive,eic7700", + .data = (void *)(QUIRK_NONSTANDARD_CACHE_OPS) }, { /* end of table */ } }; static ATOMIC_NOTIFIER_HEAD(ccache_err_chain); +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS +static void ccache_flush_range(phys_addr_t start, size_t len) +{ + phys_addr_t end = start + len; + phys_addr_t line; + + if (!len) + return; + + mb(); + for (line = ALIGN_DOWN(start, SIFIVE_CCACHE_LINE_SIZE); line < end; + line += SIFIVE_CCACHE_LINE_SIZE) { +#ifdef CONFIG_32BIT + writel(line >> 4, ccache_base + SIFIVE_CCACHE_FLUSH32); +#else + writeq(line, ccache_base + SIFIVE_CCACHE_FLUSH64); +#endif + mb(); + } +} + +static const struct riscv_nonstd_cache_ops ccache_mgmt_ops __initconst = { + .wback = &ccache_flush_range, + .inv = &ccache_flush_range, + .wback_inv = &ccache_flush_range, +}; +#endif /* CONFIG_RISCV_NONSTANDARD_CACHE_OPS */ + int register_sifive_ccache_error_notifier(struct notifier_block *nb) { return atomic_notifier_chain_register(&ccache_err_chain, nb); @@ -210,11 +251,15 @@ static int __init sifive_ccache_init(void) struct device_node *np; struct resource res; int i, rc, intr_num; + const struct of_device_id *match; + unsigned long quirks; - np = of_find_matching_node(NULL, sifive_ccache_ids); + np = of_find_matching_node_and_match(NULL, sifive_ccache_ids, &match); if (!np) return -ENODEV; + quirks = (uintptr_t)match->data; + if (of_address_to_resource(np, 0, &res)) { rc = -ENODEV; goto err_node_put; @@ -249,6 +294,14 @@ static int __init sifive_ccache_init(void) } of_node_put(np); +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS + if (quirks & QUIRK_NONSTANDARD_CACHE_OPS) { + riscv_cbom_block_size = SIFIVE_CCACHE_LINE_SIZE; + riscv_noncoherent_supported(); + riscv_noncoherent_register_cache_ops(&ccache_mgmt_ops); + } +#endif + ccache_config_read(); ccache_cache_ops.get_priv_group = ccache_get_priv_group; @@ -269,4 +322,4 @@ static int __init sifive_ccache_init(void) return rc; } -device_initcall(sifive_ccache_init); +arch_initcall(sifive_ccache_init); From 411b0bce201aa443e18b95576b91706601ed5a6a Mon Sep 17 00:00:00 2001 From: Pritesh Patel Date: Fri, 19 Jul 2024 06:45:16 +0000 Subject: [PATCH 10/38] drivers: eswin: Enable ways for ccache Enabled all available cache ways to be used as cache. This change is required for CPU performance improvement. Out of reset, only way 0 is enabled and the disabled ways are addressable in L2-LIM(Loosely Integrated Memory). Signed-off-by: Pritesh Patel --- drivers/soc/sifive/sifive_ccache.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/soc/sifive/sifive_ccache.c b/drivers/soc/sifive/sifive_ccache.c index a0bf6d3747e65..928ab5dcd3c34 100644 --- a/drivers/soc/sifive/sifive_ccache.c +++ b/drivers/soc/sifive/sifive_ccache.c @@ -253,6 +253,9 @@ static int __init sifive_ccache_init(void) int i, rc, intr_num; const struct of_device_id *match; unsigned long quirks; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + unsigned int config, ways; +#endif np = of_find_matching_node_and_match(NULL, sifive_ccache_ids, &match); if (!np) @@ -294,6 +297,12 @@ static int __init sifive_ccache_init(void) } of_node_put(np); +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + config = readl(ccache_base + SIFIVE_CCACHE_CONFIG); + ways = (config >> 8) & 0xff; + writel(ways-1, ccache_base + SIFIVE_CCACHE_WAYENABLE); +#endif + #ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS if (quirks & QUIRK_NONSTANDARD_CACHE_OPS) { riscv_cbom_block_size = SIFIVE_CCACHE_LINE_SIZE; From 244a0c852665d0b214e372ed3620b58009f4a5f9 Mon Sep 17 00:00:00 2001 From: xuxiang Date: Tue, 30 Jul 2024 04:54:27 +0000 Subject: [PATCH 11/38] drivers: dw-axi-dmac: DMA driver changes for EIC7700 - Removed cfgr clock as aon dma has separate cfg clk register bit while dma0 havn't. Since dma cfg clk is default on we do not need to control it - Add arst and prst reset control - Power on tbu and configure sid from hw init Signed-off-by: xuxiang Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- .../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 292 +++++++++++++++++- drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 28 +- 2 files changed, 312 insertions(+), 8 deletions(-) diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index dd02f84e404d0..0d73bebaadbee 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -32,6 +32,13 @@ #include "dw-axi-dmac.h" #include "../dmaengine.h" #include "../virt-dma.h" +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +#include +#include +#include +#include +#include +#endif /* * The set of bus widths supported by the DMA controller. DW AXI DMAC supports @@ -51,6 +58,15 @@ #define AXI_DMA_FLAG_HAS_RESETS BIT(1) #define AXI_DMA_FLAG_USE_CFG2 BIT(2) +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +#define AWSMMUSID GENMASK(31, 24) // The sid of write operation +#define AWSMMUSSID GENMASK(23, 16) // The ssid of write operation +#define ARSMMUSID GENMASK(15, 8) // The sid of read operation +#define ARSMMUSSID GENMASK(7, 0) // The ssid of read operation + +static int eswin_dma_sid_cfg(struct device *dev); +#endif + static inline void axi_dma_iowrite32(struct axi_dma_chip *chip, u32 reg, u32 val) { @@ -98,14 +114,26 @@ static inline void axi_chan_config_write(struct axi_dma_chan *chan, config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS | config->src_per << CH_CFG_H_SRC_PER_POS | config->dst_per << CH_CFG_H_DST_PER_POS | +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + config->prior << CH_CFG_H_PRIORITY_POS | + 0xF <prior << CH_CFG_H_PRIORITY_POS; +#endif } else { cfg_lo |= config->src_per << CH_CFG2_L_SRC_PER_POS | config->dst_per << CH_CFG2_L_DST_PER_POS; cfg_hi = config->tt_fc << CH_CFG2_H_TT_FC_POS | config->hs_sel_src << CH_CFG2_H_HS_SEL_SRC_POS | config->hs_sel_dst << CH_CFG2_H_HS_SEL_DST_POS | +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + config->prior << CH_CFG2_H_PRIORITY_POS | + 0xF <prior << CH_CFG2_H_PRIORITY_POS; +#endif } axi_chan_iowrite32(chan, CH_CFG_L, cfg_lo); axi_chan_iowrite32(chan, CH_CFG_H, cfg_hi); @@ -228,6 +256,20 @@ static void axi_dma_hw_init(struct axi_dma_chip *chip) ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64)); if (ret) dev_warn(chip->dev, "Unable to set coherent mask\n"); + +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + if (of_node_name_prefix(chip->dev->of_node, "dma-controller-hsp")) + { + eswin_dma_sid_cfg(chip->dev); + } + else + { + eic7700_aon_sid_cfg(chip->dev); + } + + /* TBU power up */ + eic7700_tbu_power(chip->dev, true); +#endif } static u32 axi_chan_get_xfer_width(struct axi_dma_chan *chan, dma_addr_t src, @@ -332,7 +374,12 @@ dma_chan_tx_status(struct dma_chan *dchan, dma_cookie_t cookie, completed_length = completed_blocks * len; bytes = length - completed_length; } - +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + else + { + bytes = vd_to_axi_desc(vdesc)->length; + } +#endif spin_unlock_irqrestore(&chan->vc.lock, flags); dma_set_residue(txstate, bytes); @@ -454,6 +501,9 @@ static void dma_chan_issue_pending(struct dma_chan *dchan) unsigned long flags; spin_lock_irqsave(&chan->vc.lock, flags); +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + chan->trigger = true; +#endif if (vchan_issue_pending(&chan->vc)) axi_chan_start_first_queued(chan); spin_unlock_irqrestore(&chan->vc.lock, flags); @@ -574,25 +624,60 @@ static void write_desc_dar(struct axi_dma_hw_desc *desc, dma_addr_t adr) desc->lli->dar = cpu_to_le64(adr); } +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +static void set_desc_src_master(struct axi_dma_hw_desc *desc, struct axi_dma_chan *chan) +#else static void set_desc_src_master(struct axi_dma_hw_desc *desc) +#endif { u32 val; /* Select AXI0 for source master */ val = le32_to_cpu(desc->lli->ctl_lo); +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + if (chan->chip->dw->hdata->nr_masters > 1) + { + if(DMA_DEV_TO_MEM == chan->direction || DMA_DEV_TO_DEV == chan->direction) { + val |= CH_CTL_L_SRC_MAST; + } + else + { + val &= ~CH_CTL_L_SRC_MAST; + } + } + else + val &= ~CH_CTL_L_SRC_MAST; +#else val &= ~CH_CTL_L_SRC_MAST; +#endif desc->lli->ctl_lo = cpu_to_le32(val); } +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +static void set_desc_dest_master(struct axi_dma_hw_desc *hw_desc, + struct axi_dma_chan *chan) +#else static void set_desc_dest_master(struct axi_dma_hw_desc *hw_desc, struct axi_dma_desc *desc) +#endif { u32 val; /* Select AXI1 for source master if available */ val = le32_to_cpu(hw_desc->lli->ctl_lo); +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + if (chan->chip->dw->hdata->nr_masters > 1) + { + if(DMA_MEM_TO_DEV == chan->direction || DMA_DEV_TO_DEV == chan->direction) { + val |= CH_CTL_L_DST_MAST; + } + else + val &= ~CH_CTL_L_DST_MAST; + } +#else if (desc->chan->chip->dw->hdata->nr_masters > 1) val |= CH_CTL_L_DST_MAST; +#endif else val &= ~CH_CTL_L_DST_MAST; @@ -611,6 +696,10 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, size_t block_ts; u32 ctllo, ctlhi; u32 burst_len; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + u32 src_maxburst; + u32 dst_maxburst; +#endif axi_block_ts = chan->chip->dw->hdata->block_size[chan->id]; @@ -623,6 +712,11 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, return -EINVAL; } +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + src_maxburst = chan->chip->dw->hdata->max_msize; + dst_maxburst = chan->chip->dw->hdata->max_msize; +#endif + switch (chan->direction) { case DMA_MEM_TO_DEV: reg_width = __ffs(chan->config.dst_addr_width); @@ -631,6 +725,9 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, mem_width << CH_CTL_L_SRC_WIDTH_POS | DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_DST_INC_POS | DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + dst_maxburst = chan->config.dst_maxburst; +#endif block_ts = len >> mem_width; break; case DMA_DEV_TO_MEM: @@ -640,6 +737,9 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, mem_width << CH_CTL_L_DST_WIDTH_POS | DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS | DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_SRC_INC_POS; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + src_maxburst = chan->config.src_maxburst; +#endif block_ts = len >> reg_width; break; default: @@ -673,12 +773,27 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, } hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1); - +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + if(is_power_of_2(dst_maxburst) && is_power_of_2(src_maxburst)) + { + dst_maxburst = order_base_2(dst_maxburst)? order_base_2(dst_maxburst) - 1 : 0; + src_maxburst = order_base_2(src_maxburst)? order_base_2(src_maxburst) - 1 : 0; + }else + dev_err(chan->chip->dev, "dst_burst or src_burst error!\n"); + ctllo |= dst_maxburst << CH_CTL_L_DST_MSIZE_POS | + src_maxburst << CH_CTL_L_SRC_MSIZE_POS; +#else ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | - DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS; + DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS; +#endif hw_desc->lli->ctl_lo = cpu_to_le32(ctllo); +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + set_desc_src_master(hw_desc, chan); + set_desc_dest_master(hw_desc, chan); +#else set_desc_src_master(hw_desc); +#endif hw_desc->len = len; return 0; @@ -879,6 +994,9 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr, struct axi_dma_hw_desc *hw_desc = NULL; struct axi_dma_desc *desc = NULL; u32 xfer_width, reg, num; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + u32 max_burst_len; +#endif u64 llp = 0; u8 lms = 0; /* Select AXI0 master for LLI fetching */ @@ -886,6 +1004,12 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr, axi_chan_name(chan), &src_adr, &dst_adr, len, flags); max_block_ts = chan->chip->dw->hdata->block_size[chan->id]; + +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + max_burst_len = chan->chip->dw->hdata->max_msize; + max_burst_len = order_base_2(max_burst_len)? order_base_2(max_burst_len) - 1 : 0; +#endif + xfer_width = axi_chan_get_xfer_width(chan, src_adr, dst_adr, len); num = DIV_ROUND_UP(len, max_block_ts << xfer_width); desc = axi_desc_alloc(num); @@ -936,17 +1060,26 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr, } hw_desc->lli->ctl_hi = cpu_to_le32(reg); +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + reg = (max_burst_len << CH_CTL_L_DST_MSIZE_POS | + max_burst_len << CH_CTL_L_SRC_MSIZE_POS | +#else reg = (DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS | +#endif xfer_width << CH_CTL_L_DST_WIDTH_POS | xfer_width << CH_CTL_L_SRC_WIDTH_POS | DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS | DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS); hw_desc->lli->ctl_lo = cpu_to_le32(reg); +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + set_desc_src_master(hw_desc, chan); + set_desc_dest_master(hw_desc, chan); +#else set_desc_src_master(hw_desc); set_desc_dest_master(hw_desc, desc); - +#endif hw_desc->len = xfer_len; desc->length += hw_desc->len; /* update the length and addresses for the next loop cycle */ @@ -1159,7 +1292,9 @@ static int dma_chan_terminate_all(struct dma_chan *dchan) spin_lock_irqsave(&chan->vc.lock, flags); vchan_get_all_descriptors(&chan->vc, &head); - +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + chan->trigger = false; +#endif chan->cyclic = false; spin_unlock_irqrestore(&chan->vc.lock, flags); @@ -1248,8 +1383,9 @@ static int axi_dma_suspend(struct axi_dma_chip *chip) axi_dma_disable(chip); clk_disable_unprepare(chip->core_clk); +#ifndef CONFIG_SOC_SIFIVE_EIC7700 clk_disable_unprepare(chip->cfgr_clk); - +#endif return 0; } @@ -1257,9 +1393,11 @@ static int axi_dma_resume(struct axi_dma_chip *chip) { int ret; +#ifndef CONFIG_SOC_SIFIVE_EIC7700 ret = clk_prepare_enable(chip->cfgr_clk); if (ret < 0) return ret; +#endif ret = clk_prepare_enable(chip->core_clk); if (ret < 0) @@ -1285,6 +1423,43 @@ static int __maybe_unused axi_dma_runtime_resume(struct device *dev) return axi_dma_resume(chip); } +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +int eic7700_dma_sel_cfg(struct axi_dma_chan *chan, u32 val) +{ + struct axi_dma_chip *chip = chan->chip; + struct device *dev = chan->chip->dev; + int ret = 0; + struct regmap *regmap; + int dma_sel_reg; + u32 dma_sel = 0; + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,syscfg"); + if (IS_ERR(regmap)) { + dev_err(dev, "No eswin,syscfg phandle specified\n"); + return -1; + } + + ret = of_property_read_u32_index(dev->of_node, "eswin,syscfg", 2, + &dma_sel_reg); + if (ret) { + dev_err(dev, "can't get sid cfg reg offset in sys_con(errno:%d)\n", ret); + return ret; + } + regmap_read(regmap, dma_sel_reg, &dma_sel); + + if (of_node_name_prefix(chip->dev->of_node, "dma-controller-hsp")) { + if (val < 32) + dma_sel &= ~(1 << val); + } + else { + if (val < 32) + dma_sel |= (1 << val); + } + regmap_write(regmap, dma_sel_reg, dma_sel); + return 0; +} +#endif + static struct dma_chan *dw_axi_dma_of_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) { @@ -1298,6 +1473,10 @@ static struct dma_chan *dw_axi_dma_of_xlate(struct of_phandle_args *dma_spec, chan = dchan_to_axi_dma_chan(dchan); chan->hw_handshake_num = dma_spec->args[0]; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + if (dma_spec->args_count > 1) + eic7700_dma_sel_cfg(chan, dma_spec->args[1]); +#endif return dchan; } @@ -1368,6 +1547,20 @@ static int parse_device_properties(struct axi_dma_chip *chip) chip->dw->hdata->axi_rw_burst_len = tmp; } +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + /* max-size is optional property */ + ret = device_property_read_u32(dev, "snps,max-msize", &tmp); + if (!ret) { + if (tmp > 1024) + return -EINVAL; + if (tmp < 1) + return -EINVAL; + + chip->dw->hdata->max_msize = tmp; + }else + chip->dw->hdata->max_msize = 4; +#endif + return 0; } @@ -1428,10 +1621,31 @@ static int dw_probe(struct platform_device *pdev) if (IS_ERR(chip->core_clk)) return PTR_ERR(chip->core_clk); +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + chip->arst = devm_reset_control_get_optional(&pdev->dev, "arst"); + if (IS_ERR_OR_NULL(chip->arst)) { + dev_err(chip->dev, "Failed to get axi reset handle\n"); + return -EFAULT; + } + reset_control_deassert(chip->arst); + + chip->prst = devm_reset_control_get_optional(&pdev->dev, "prst"); + if (IS_ERR_OR_NULL(chip->prst)) { + dev_err(chip->dev, "Failed to get ahb reset handle\n"); + return -EFAULT; + } + reset_control_deassert(chip->prst); +#endif + + /* + For EIC7700 SoC, aon dma has separate cfg clk register bit while dma0 havn't. + Since dma cfg clk is default on, so we don't control it + */ +#ifndef CONFIG_SOC_SIFIVE_EIC7700 chip->cfgr_clk = devm_clk_get(chip->dev, "cfgr-clk"); if (IS_ERR(chip->cfgr_clk)) return PTR_ERR(chip->cfgr_clk); - +#endif ret = parse_device_properties(chip); if (ret) return ret; @@ -1465,7 +1679,12 @@ static int dw_probe(struct platform_device *pdev) dma_cap_set(DMA_CYCLIC, dw->dma.cap_mask); /* DMA capabilities */ +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + dw->dma.chancnt = hdata->nr_channels; + dw->dma.max_burst = hdata->max_msize; +#else dw->dma.max_burst = hdata->axi_rw_burst_len; +#endif dw->dma.src_addr_widths = AXI_DMA_BUSWIDTHS; dw->dma.dst_addr_widths = AXI_DMA_BUSWIDTHS; dw->dma.directions = BIT(DMA_MEM_TO_MEM); @@ -1535,6 +1754,53 @@ static int dw_probe(struct platform_device *pdev) return ret; } +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +static int eswin_dma_sid_cfg(struct device *dev) +{ + int ret; + struct regmap *regmap; + int hsp_mmu_dma_reg; + u32 rdwr_sid_ssid; + u32 sid; + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + + /* not behind smmu, use the default reset value(0x0) of the reg as streamID*/ + if (fwspec == NULL) { + dev_dbg(dev, "dev is not behind smmu, skip configuration of sid\n"); + return 0; + } + sid = fwspec->ids[0]; + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,hsp_sp_csr"); + if (IS_ERR(regmap)) { + dev_dbg(dev, "No hsp_sp_csr phandle specified\n"); + return 0; + } + + ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 1, + &hsp_mmu_dma_reg); + if (ret) { + dev_err(dev, "can't get dma sid cfg reg offset (%d)\n", ret); + return ret; + } + + /* make the reading sid the same as writing sid, ssid is fixed to zero */ + rdwr_sid_ssid = FIELD_PREP(AWSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(AWSMMUSSID, 0); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSSID, 0); + regmap_write(regmap, hsp_mmu_dma_reg, rdwr_sid_ssid); + + ret = eic7700_dynm_sid_enable(dev_to_node(dev)); + if (ret < 0) + dev_err(dev, "failed to config dma streamID(%d)!\n", sid); + else + dev_dbg(dev, "success to config dma streamID(%d)!\n", sid); + + return ret; +} +#endif + static int dw_remove(struct platform_device *pdev) { struct axi_dma_chip *chip = platform_get_drvdata(pdev); @@ -1543,7 +1809,9 @@ static int dw_remove(struct platform_device *pdev) u32 i; /* Enable clk before accessing to registers */ +#ifndef CONFIG_SOC_SIFIVE_EIC7700 clk_prepare_enable(chip->cfgr_clk); +#endif clk_prepare_enable(chip->core_clk); axi_dma_irq_disable(chip); for (i = 0; i < dw->hdata->nr_channels; i++) { @@ -1561,10 +1829,20 @@ static int dw_remove(struct platform_device *pdev) list_for_each_entry_safe(chan, _chan, &dw->dma.channels, vc.chan.device_node) { +#ifndef CONFIG_SOC_SIFIVE_EIC7700 list_del(&chan->vc.chan.device_node); +#endif tasklet_kill(&chan->vc.task); } +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + /* TBU power down before reset */ + eic7700_tbu_power(chip->dev, false); + + reset_control_assert(chip->arst); + reset_control_assert(chip->prst); +#endif + return 0; } diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h index eb267cb24f670..b38672ecf73a2 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h @@ -15,7 +15,9 @@ #include #include #include - +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +#include +#endif #include "../virt-dma.h" #define DMAC_MAX_CHANNELS 16 @@ -30,6 +32,9 @@ struct dw_axi_dma_hcfg { u32 priority[DMAC_MAX_CHANNELS]; /* maximum supported axi burst length */ u32 axi_rw_burst_len; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + u32 max_msize; +#endif /* Register map for DMAX_NUM_CHANNELS <= 8 */ bool reg_map_8_channels; bool restrict_axi_burst_len; @@ -52,6 +57,9 @@ struct axi_dma_chan { bool cyclic; /* these other elements are all protected by vc.lock */ bool is_paused; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + bool trigger; +#endif }; struct dw_axi_dma { @@ -71,6 +79,10 @@ struct axi_dma_chip { struct clk *core_clk; struct clk *cfgr_clk; struct dw_axi_dma *dw; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + struct reset_control *arst; + struct reset_control *prst; +#endif }; /* LLI == Linked List Item */ @@ -202,7 +214,11 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan) #define UNUSED_CHANNEL 0x3F /* Set unused DMA channel to 0x3F */ #define DMA_APB_HS_SEL_BIT_SIZE 0x08 /* HW handshake bits per channel */ #define DMA_APB_HS_SEL_MASK 0xFF /* HW handshake select masks */ +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +#define MAX_BLOCK_SIZE 0x80000 /* 1024 blocks * 512 bytes data width */ +#else #define MAX_BLOCK_SIZE 0x1000 /* 1024 blocks * 4 bytes data width */ +#endif #define DMA_REG_MAP_CH_REF 0x08 /* Channel count to choose register map */ /* DMAC_CFG */ @@ -282,6 +298,10 @@ enum { #define CH_CTL_L_SRC_MAST BIT(0) /* CH_CFG_H */ +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +#define CH_CFG_H_DST_OSR_LMT_POS 27 +#define CH_CFG_H_SRC_OSR_LMT_POS 23 +#endif #define CH_CFG_H_PRIORITY_POS 17 #define CH_CFG_H_DST_PER_POS 12 #define CH_CFG_H_SRC_PER_POS 7 @@ -321,7 +341,13 @@ enum { #define CH_CFG2_H_TT_FC_POS 0 #define CH_CFG2_H_HS_SEL_SRC_POS 3 #define CH_CFG2_H_HS_SEL_DST_POS 4 +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +#define CH_CFG2_H_PRIORITY_POS 15 +#define CH_CFG2_H_SRC_OSR_LMT_POS 23 +#define CH_CFG2_H_DST_OSR_LMT_POS 27 +#else #define CH_CFG2_H_PRIORITY_POS 20 +#endif /** * DW AXI DMA channel interrupts From efdaea41c39fb9f2c500c27da7f8f8c57d699ba2 Mon Sep 17 00:00:00 2001 From: liangshuang Date: Tue, 30 Jul 2024 05:03:58 +0000 Subject: [PATCH 12/38] driver: mmc: Add ESWIN mmc drivers Signed-off-by: liangshuang Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/mmc/host/Kconfig | 28 + drivers/mmc/host/Makefile | 4 + drivers/mmc/host/sdhci-eswin.c | 301 +++++++ drivers/mmc/host/sdhci-eswin.h | 237 +++++ drivers/mmc/host/sdhci-of-eswin-sdio.c | 1079 +++++++++++++++++++++++ drivers/mmc/host/sdhci-of-eswin.c | 1104 ++++++++++++++++++++++++ 6 files changed, 2753 insertions(+) create mode 100644 drivers/mmc/host/sdhci-eswin.c create mode 100644 drivers/mmc/host/sdhci-eswin.h create mode 100644 drivers/mmc/host/sdhci-of-eswin-sdio.c create mode 100644 drivers/mmc/host/sdhci-of-eswin.c diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index bc7e2ad370021..5aa588dba2d8f 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -214,6 +214,34 @@ config MMC_SDHCI_OF_ESDHC If unsure, say N. +config MMC_SDHCI_OF_ESWIN + tristate "SDHCI OF support for the Eswin SDHCI controllers" + depends on MMC_SDHCI_PLTFM + depends on OF + depends on COMMON_CLK + select MMC_CQHCI + help + This selects the Eswin Secure Digital Host Controller Interface + (SDHCI). + + If you have a controller with this interface, say Y or M here. + + If unsure, say N. + +config MMC_SDHCI_OF_SDIO_ESWIN + tristate "SDHCI OF SDIO support for the Eswin SDHCI controllers" + depends on MMC_SDHCI_PLTFM + depends on OF + depends on COMMON_CLK + select MMC_CQHCI + help + This selects the Eswin Secure Digital Host Controller Interface + (SDHCI-SDIO). + + If you have a controller with this interface, say Y or M here. + + If unsure, say N. + config MMC_SDHCI_OF_HLWD tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers" depends on MMC_SDHCI_PLTFM diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index a693fa3d3f1cc..2c7167dfdaaca 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -84,6 +84,10 @@ obj-$(CONFIG_MMC_SDHCI_OF_ARASAN) += sdhci-of-arasan.o obj-$(CONFIG_MMC_SDHCI_OF_ASPEED) += sdhci-of-aspeed.o obj-$(CONFIG_MMC_SDHCI_OF_AT91) += sdhci-of-at91.o obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o +eswin-sdhci-emmc-objs := sdhci-of-eswin.o sdhci-eswin.o +obj-$(CONFIG_MMC_SDHCI_OF_ESWIN) += eswin-sdhci-emmc.o +eswin-sdhci-sdio-objs := sdhci-of-eswin-sdio.o sdhci-eswin.o +obj-$(CONFIG_MMC_SDHCI_OF_SDIO_ESWIN) += eswin-sdhci-sdio.o obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o obj-$(CONFIG_MMC_SDHCI_OF_DWCMSHC) += sdhci-of-dwcmshc.o obj-$(CONFIG_MMC_SDHCI_OF_SPARX5) += sdhci-of-sparx5.o diff --git a/drivers/mmc/host/sdhci-eswin.c b/drivers/mmc/host/sdhci-eswin.c new file mode 100644 index 0000000000000..b941fa90f7103 --- /dev/null +++ b/drivers/mmc/host/sdhci-eswin.c @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Emmc 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 . + * + * Authors: liangshuang + */ +#include +#include +#include "sdhci-eswin.h" + +static void eswin_mshc_coreclk_config(struct sdhci_host *host, uint16_t divisor, + unsigned int flag_sel) +{ + struct sdhci_pltfm_host *pltfm_host; + struct eswin_sdhci_data *eswin_sdhci; + u32 val = 0; + u32 delay = 0xfffff; + + pltfm_host = sdhci_priv(host); + eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + + val = readl(eswin_sdhci->core_clk_reg); + val &= ~MSHC_CORE_CLK_ENABLE; + writel(val, eswin_sdhci->core_clk_reg); + while (delay--) + ; + val &= ~(MSHC_CORE_CLK_FREQ_BIT_MASK << MSHC_CORE_CLK_FREQ_BIT_SHIFT); + val |= (divisor & MSHC_CORE_CLK_FREQ_BIT_MASK) + << MSHC_CORE_CLK_FREQ_BIT_SHIFT; + val &= ~(MSHC_CORE_CLK_SEL_BIT); + val |= flag_sel; + writel(val, eswin_sdhci->core_clk_reg); + + udelay(100); + val |= MSHC_CORE_CLK_ENABLE; + writel(val, eswin_sdhci->core_clk_reg); + mdelay(1); +} + +static void eswin_mshc_coreclk_disable(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host; + struct eswin_sdhci_data *eswin_sdhci; + u32 val = 0; + + pltfm_host = sdhci_priv(host); + eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + + val = readl(eswin_sdhci->core_clk_reg); + val &= ~MSHC_CORE_CLK_ENABLE; + writel(val, eswin_sdhci->core_clk_reg); +} + +void eswin_sdhci_disable_card_clk(struct sdhci_host *host) +{ + unsigned int clk; + + /* Reset SD Clock Enable */ + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + clk &= ~SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); +} + +void eswin_sdhci_enable_card_clk(struct sdhci_host *host) +{ + ktime_t timeout; + unsigned int clk; + + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + + clk |= SDHCI_CLOCK_INT_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + + /* Wait max 150 ms */ + timeout = ktime_add_ms(ktime_get(), 150); + while (1) { + bool timedout = ktime_after(ktime_get(), timeout); + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + if (clk & SDHCI_CLOCK_INT_STABLE) + break; + if (timedout) { + pr_err("%s: Internal clock never stabilised.\n", + mmc_hostname(host->mmc)); + return; + } + udelay(10); + } + + clk |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + mdelay(1); +} + +void eswin_sdhci_set_core_clock(struct sdhci_host *host, + unsigned int clock) +{ + unsigned int div, divide; + unsigned int flag_sel, max_clk; + + if (clock == 0) { + eswin_mshc_coreclk_disable(host); + return; + } + + if (SDHCI_CLK_208M % clock == 0) { + flag_sel = 1; + max_clk = SDHCI_CLK_208M; + } else { + flag_sel = 0; + max_clk = SDHCI_CLK_200M; + } + + for (div = 1; div <= MAX_CORE_CLK_DIV; div++) { + if ((max_clk / div) <= clock) + break; + } + div--; + + if (div == 0 || div == 1) { + divide = 2; + } else { + divide = (div + 1) * 2; + } + pr_debug("%s: clock:%d timing:%d\n", mmc_hostname(host->mmc), clock, host->timing); + + eswin_sdhci_disable_card_clk(host); + eswin_mshc_coreclk_config(host, divide, flag_sel); + eswin_sdhci_enable_card_clk(host); + mdelay(2); +} + +static void eswin_sdhci_set_clk_delays(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + struct eswin_sdhci_clk_data *clk_data = &eswin_sdhci->clk_data; + + clk_set_phase(clk_data->sampleclk, + clk_data->clk_phase_in[host->timing]); + clk_set_phase(clk_data->sdcardclk, + clk_data->clk_phase_out[host->timing]); +} + +static void eswin_sdhci_dt_read_clk_phase(struct device *dev, + struct eswin_sdhci_clk_data *clk_data, + unsigned int timing, const char *prop) +{ + struct device_node *np = dev->of_node; + + int clk_phase[2] = { 0 }; + + /* + * Read Tap Delay values from DT, if the DT does not contain the + * Tap Values then use the pre-defined values. + */ + if (of_property_read_variable_u32_array(np, prop, &clk_phase[0], 2, + 0)) { + dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n", + prop, clk_data->clk_phase_in[timing], + clk_data->clk_phase_out[timing]); + return; + } + + /* The values read are Input and Output Clock Delays in order */ + clk_data->clk_phase_in[timing] = clk_phase[0]; + clk_data->clk_phase_out[timing] = clk_phase[1]; +} + +/** + * eswin_dt_parse_clk_phases - Read Clock Delay values from DT + * + * @dev: Pointer to our struct device. + * @clk_data: Pointer to the Clock Data structure + * + * Called at initialization to parse the values of Clock Delays. + */ +void eswin_sdhci_dt_parse_clk_phases(struct device *dev, + struct eswin_sdhci_clk_data *clk_data) +{ + clk_data->set_clk_delays = eswin_sdhci_set_clk_delays; + + eswin_sdhci_dt_read_clk_phase(dev, clk_data, MMC_TIMING_LEGACY, + "clk-phase-legacy"); + eswin_sdhci_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS, + "clk-phase-mmc-hs"); + eswin_sdhci_dt_read_clk_phase(dev, clk_data, MMC_TIMING_SD_HS, + "clk-phase-sd-hs"); + eswin_sdhci_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR12, + "clk-phase-uhs-sdr12"); + eswin_sdhci_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR25, + "clk-phase-uhs-sdr25"); + eswin_sdhci_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR50, + "clk-phase-uhs-sdr50"); + eswin_sdhci_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR104, + "clk-phase-uhs-sdr104"); + eswin_sdhci_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_DDR50, + "clk-phase-uhs-ddr50"); + eswin_sdhci_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_DDR52, + "clk-phase-mmc-ddr52"); + eswin_sdhci_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS200, + "clk-phase-mmc-hs200"); + eswin_sdhci_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS400, + "clk-phase-mmc-hs400"); +} + +unsigned int eswin_convert_drive_impedance_ohm(struct platform_device *pdev, + unsigned int dr_ohm) +{ + switch (dr_ohm) { + case 100: + return PHYCTRL_DR_100OHM; + case 66: + return PHYCTRL_DR_66OHM; + case 50: + return PHYCTRL_DR_50OHM; + case 40: + return PHYCTRL_DR_40OHM; + case 33: + return PHYCTRL_DR_33OHM; + } + + dev_warn(&pdev->dev, "Invalid value %u for drive-impedance-ohm.\n", + dr_ohm); + return PHYCTRL_DR_50OHM; +} + +static void eswin_sdhci_do_reset(struct eswin_sdhci_data *eswin_sdhci) +{ + int ret; + + ret = reset_control_assert(eswin_sdhci->txrx_rst); + WARN_ON(0 != ret); + ret = reset_control_assert(eswin_sdhci->phy_rst); + WARN_ON(0 != ret); + ret = reset_control_assert(eswin_sdhci->prstn); + WARN_ON(0 != ret); + ret = reset_control_assert(eswin_sdhci->arstn); + WARN_ON(0 != ret); + + mdelay(2); + + ret = reset_control_deassert(eswin_sdhci->txrx_rst); + WARN_ON(0 != ret); + ret = reset_control_deassert(eswin_sdhci->phy_rst); + WARN_ON(0 != ret); + ret = reset_control_deassert(eswin_sdhci->prstn); + WARN_ON(0 != ret); + ret = reset_control_deassert(eswin_sdhci->arstn); + WARN_ON(0 != ret); +} + +int eswin_sdhci_reset_init(struct device *dev, + struct eswin_sdhci_data *eswin_sdhci) +{ + int ret = 0; + eswin_sdhci->txrx_rst = devm_reset_control_get_optional(dev, "txrx_rst"); + if (IS_ERR_OR_NULL(eswin_sdhci->txrx_rst)) { + dev_err_probe(dev, PTR_ERR(eswin_sdhci->txrx_rst), + "txrx_rst reset not found.\n"); + return -EFAULT; + } + + eswin_sdhci->phy_rst = devm_reset_control_get_optional(dev, "phy_rst"); + if (IS_ERR_OR_NULL(eswin_sdhci->phy_rst)) { + dev_err_probe(dev, PTR_ERR(eswin_sdhci->phy_rst), + "phy_rst reset not found.\n"); + return -EFAULT; + } + + eswin_sdhci->prstn = devm_reset_control_get_optional(dev, "prstn"); + if (IS_ERR_OR_NULL(eswin_sdhci->prstn)) { + dev_err_probe(dev, PTR_ERR(eswin_sdhci->prstn), + "prstn reset not found.\n"); + return -EFAULT; + } + + eswin_sdhci->arstn = devm_reset_control_get_optional(dev, "arstn"); + if (IS_ERR_OR_NULL(eswin_sdhci->arstn)) { + dev_err_probe(dev, PTR_ERR(eswin_sdhci->arstn), + "arstn reset not found.\n"); + return -EFAULT; + } + eswin_sdhci_do_reset(eswin_sdhci); + + return ret; +} diff --git a/drivers/mmc/host/sdhci-eswin.h b/drivers/mmc/host/sdhci-eswin.h new file mode 100644 index 0000000000000..5274766f0501b --- /dev/null +++ b/drivers/mmc/host/sdhci-eswin.h @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN SDHCI 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 . + * + * Authors: liangshuang + */ +#ifndef _DRIVERS_MMC_SDHCI_ESWIN_H +#define _DRIVERS_MMC_SDHCI_ESWIN_H + +#include +#include +#include "sdhci-pltfm.h" + +#define MSHC_CARD_CLK_STABLE BIT(28) +#define MSHC_INT_BCLK_STABLE BIT(16) +#define MSHC_INT_ACLK_STABLE BIT(8) +#define MSHC_INT_TMCLK_STABLE BIT(0) +#define MSHC_INT_CLK_STABLE \ + (MSHC_CARD_CLK_STABLE | MSHC_INT_ACLK_STABLE | \ + MSHC_INT_BCLK_STABLE | MSHC_INT_TMCLK_STABLE) +#define MSHC_HOST_VAL_STABLE BIT(0) +#define EMMC0_CARD_DETECT BIT(9) +#define EMMC0_CARD_WRITE_PROT BIT(8) + +#define MSHC_CORE_CLK_ENABLE BIT(16) +#define MSHC_CORE_CLK_FREQ_BIT_SHIFT 4 +#define MSHC_CORE_CLK_FREQ_BIT_MASK 0xfffu +#define MSHC_CORE_CLK_SEL_BIT BIT(0) + +/* Controller does not have CD wired and will not function normally without */ +#define SDHCI_ESWIN_QUIRK_FORCE_CDTEST BIT(0) +/* Controller immediately reports SDHCI_CLOCK_INT_STABLE after enabling the + * internal clock even when the clock isn't stable */ +#define SDHCI_ESWIN_QUIRK_CLOCK_UNSTABLE BIT(1) + +#define ESWIN_SDHCI_CTRL_HS400 0x0007 // Non-standard, for eswin,these bits are 0x7 + +#define SDHCI_CLK_208M 208000000 +#define SDHCI_CLK_200M 200000000 + +#define AWSMMUSID GENMASK(31, 24) // The sid of write operation +#define AWSMMUSSID GENMASK(23, 16) // The ssid of write operation +#define ARSMMUSID GENMASK(15, 8) // The sid of read operation +#define ARSMMUSSID GENMASK(7, 0) // The ssid of read operation + +/* DWC_mshc_map/DWC_mshc_phy_block register */ +#define DWC_MSHC_PTR_PHY_R 0x300 +#define PHY_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x00) +#define PHY_CMDPAD_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x04) +#define PHY_DATAPAD_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x06) +#define PHY_CLKPAD_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x08) +#define PHY_STBPAD_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x0a) +#define PHY_RSTNPAD_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x0c) +#define PHY_PADTEST_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x0e) +#define PHY_PADTEST_OUT_R (DWC_MSHC_PTR_PHY_R + 0x10) +#define PHY_PADTEST_IN_R (DWC_MSHC_PTR_PHY_R + 0x12) +#define PHY_PRBS_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x18) +#define PHY_PHYLBK_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x1a) +#define PHY_COMMDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x1c) +#define PHY_SDCLKDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x1d) +#define PHY_SDCLKDL_DC_R (DWC_MSHC_PTR_PHY_R + 0x1e) +#define PHY_SMPLDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x20) +#define PHY_ATDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x21) +#define PHY_DLL_CTRL_R (DWC_MSHC_PTR_PHY_R + 0x24) +#define PHY_DLL_CNFG1_R (DWC_MSHC_PTR_PHY_R + 0x25) +#define PHY_DLL_CNFG2_R (DWC_MSHC_PTR_PHY_R + 0x26) +#define PHY_DLLDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x28) +#define PHY_DLL_OFFST_R (DWC_MSHC_PTR_PHY_R + 0x29) +#define PHY_DLLMST_TSTDC_R (DWC_MSHC_PTR_PHY_R + 0x2a) +#define PHY_DLLBT_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x2c) +#define PHY_DLL_STATUS_R (DWC_MSHC_PTR_PHY_R + 0x2e) +#define PHY_DLLDBG_MLKDC_R (DWC_MSHC_PTR_PHY_R + 0x30) +#define PHY_DLLDBG_SLKDC_R (DWC_MSHC_PTR_PHY_R + 0x32) + +#define ENABLE 1 +#define DISABLE 0 +/* strength definition */ +#define PHYCTRL_DR_33OHM 0xee +#define PHYCTRL_DR_40OHM 0xcc +#define PHYCTRL_DR_50OHM 0x88 +#define PHYCTRL_DR_66OHM 0x44 +#define PHYCTRL_DR_100OHM 0x00 + +#define PHY_PAD_MAX_DRIVE_STRENGTH 0xf +#define PHY_CLK_MAX_DELAY_MASK 0x7f +#define PHY_PAD_SP_DRIVE_SHIF 16 +#define PHY_PAD_SN_DRIVE_SHIF 20 + +#define PHY_RSTN BIT(0) +#define PHY_UPDATE_DELAY_CODE BIT(4) + +#define VENDOR_EMMC_CTRL_R 0x52c +#define EMMC_CRAD_PRESENT BIT(0) +#define EMMC_RST_N_OE BIT(3) +#define EMMC_RST_N BIT(2) + +#define PHY_SLEW_0 0x0 +#define PHY_SLEW_1 0x1 +#define PHY_SLEW_2 0x2 +#define PHY_SLEW_3 0x3 +#define PHY_TX_SLEW_CTRL_P_BIT_SHIFT 5 +#define PHY_TX_SLEW_CTRL_N_BIT_SHIFT 9 + +#define PHY_PULL_BIT_SHIF 0x3 +#define PHY_PULL_DISABLED 0x0 +#define PHY_PULL_UP 0x1 +#define PHY_PULL_DOWN 0x2 +#define PHY_PULL_MASK 0x3 + +#define PHY_PAD_RXSEL_0 0x0 +#define PHY_PAD_RXSEL_1 0x1 + +#define VENDOR_AT_CTRL_R 0x540 +#define LATENCY_LT_BIT_OFFSET 19 +#define LATENCY_LT_MASK 0x3 + +#define LATENCY_LT_1 0x0 +#define LATENCY_LT_2 0x1 +#define LATENCY_LT_3 0x2 +#define LATENCY_LT_4 0x3 +#define SW_TUNE_ENABLE BIT(4) + +#define VENDOR_AT_SATA_R 0x544 +#define MAX_PHASE_CODE 0xff + +#define DLL_ENABEL BIT(0) +#define DLL_LOCK_STS BIT(0) +#define DLL_ERROR_STS BIT(1) +#define PHY_DELAY_CODE_MASK 0x7f +#define PHY_DELAY_CODE_MAX 0x7f + +#define MAX_CORE_CLK_DIV 0xfff + +/** + * struct eswin_sdhci_clk_ops - Clock Operations for eswin SD controller + * + * @sdcardclk_ops: The output clock related operations + * @sampleclk_ops: The sample clock related operations + */ +struct eswin_sdhci_clk_ops { + const struct clk_ops *sdcardclk_ops; + const struct clk_ops *sampleclk_ops; +}; + +/** + * struct eswin_sdhci_clk_data - ESWIN Controller Clock Data. + * + * @sdcardclk_hw: Struct for the clock we might provide to a PHY. + * @sdcardclk: Pointer to normal 'struct clock' for sdcardclk_hw. + * @sampleclk_hw: Struct for the clock we might provide to a PHY. + * @sampleclk: Pointer to normal 'struct clock' for sampleclk_hw. + * @clk_phase_in: Array of Input Clock Phase Delays for all speed modes + * @clk_phase_out: Array of Output Clock Phase Delays for all speed modes + * @set_clk_delays: Function pointer for setting Clock Delays + * @clk_of_data: Platform specific runtime clock data storage pointer + */ +struct eswin_sdhci_clk_data { + struct clk_hw sdcardclk_hw; + struct clk *sdcardclk; + struct clk_hw sampleclk_hw; + struct clk *sampleclk; + int clk_phase_in[MMC_TIMING_MMC_HS400 + 1]; + int clk_phase_out[MMC_TIMING_MMC_HS400 + 1]; + void (*set_clk_delays)(struct sdhci_host *host); + void *clk_of_data; +}; + +struct eswin_sdhci_phy_data { + unsigned int drive_impedance; + unsigned int enable_strobe_pulldown; + unsigned int enable_data_pullup; + unsigned int enable_cmd_pullup; + unsigned int delay_code; +}; + +/** + * struct eswin_sdhci_data - ESWIN Controller Data + * + * @host: Pointer to the main SDHCI host structure. + * @clk_ahb: Pointer to the AHB clock + * @has_cqe: True if controller has command queuing engine. + * @clk_data: Struct for the ESWIN Controller Clock Data. + * @clk_ops: Struct for the ESWIN Controller Clock Operations. + * @soc_ctl_base: Pointer to regmap for syscon for soc_ctl registers. + * @soc_ctl_map: Map to get offsets into soc_ctl registers. + * @quirks: ESWIN deviations from spec. + * @phy: ESWIN sdhci phy configs. + * @private: private for spec driver. + */ +struct eswin_sdhci_data { + struct sdhci_host *host; + struct clk *clk_ahb; + bool has_cqe; + struct eswin_sdhci_clk_data clk_data; + const struct eswin_sdhci_clk_ops *clk_ops; + unsigned int quirks; + void __iomem *core_clk_reg; + struct reset_control *txrx_rst; + struct reset_control *phy_rst; + struct reset_control *prstn; + struct reset_control *arstn; + struct eswin_sdhci_phy_data phy; + unsigned long private[] ____cacheline_aligned; +}; + +struct eswin_sdhci_of_data { + const struct sdhci_pltfm_data *pdata; + const struct eswin_sdhci_clk_ops *clk_ops; +}; + +void eswin_sdhci_set_core_clock(struct sdhci_host *host, + unsigned int clock); +void eswin_sdhci_disable_card_clk(struct sdhci_host *host); +void eswin_sdhci_enable_card_clk(struct sdhci_host *host); +void eswin_sdhci_dt_parse_clk_phases(struct device *dev, + struct eswin_sdhci_clk_data *clk_data); +unsigned int eswin_convert_drive_impedance_ohm(struct platform_device *pdev, + unsigned int dr_ohm); +int eswin_sdhci_reset_init(struct device *dev, + struct eswin_sdhci_data *eswin_sdhci); + +#endif /* _DRIVERS_MMC_SDHCI_ESWIN_H */ diff --git a/drivers/mmc/host/sdhci-of-eswin-sdio.c b/drivers/mmc/host/sdhci-of-eswin-sdio.c new file mode 100644 index 0000000000000..c69e5f10f2400 --- /dev/null +++ b/drivers/mmc/host/sdhci-of-eswin-sdio.c @@ -0,0 +1,1079 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN sdio 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 . + * + * Authors: liangshuang + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cqhci.h" +#include "sdhci-pltfm.h" + +#include +#include +#include +#include "sdhci-eswin.h" + + +#define ESWIN_SDHCI_SD_CQE_BASE_ADDR 0x180 +#define ESWIN_SDHCI_SD0_INT_STATUS 0x608 +#define ESWIN_SDHCI_SD0_PWR_CTRL 0x60c +#define ESWIN_SDHCI_SD1_INT_STATUS 0x708 +#define ESWIN_SDHCI_SD1_PWR_CTRL 0x70c + +#define DELAY_RANGE_THRESHOLD 20 + +struct eswin_sdio_private { + int phase_code; + unsigned int enable_sw_tuning; +}; + +static inline void *sdhci_sdio_priv(struct eswin_sdhci_data *sdio) +{ + return sdio->private; +} + +static void eswin_sdhci_sdio_set_clock(struct sdhci_host *host, + unsigned int clock) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci_sdio = + sdhci_pltfm_priv(pltfm_host); + struct eswin_sdhci_clk_data *clk_data = + &eswin_sdhci_sdio->clk_data; + + /* Set the Input and Output Clock Phase Delays */ + if (clk_data->set_clk_delays) { + clk_data->set_clk_delays(host); + } + + eswin_sdhci_set_core_clock(host, clock); + sdhci_set_clock(host, clock); + + if (eswin_sdhci_sdio->quirks & SDHCI_ESWIN_QUIRK_CLOCK_UNSTABLE) + /* + * Some controllers immediately report SDHCI_CLOCK_INT_STABLE + * after enabling the clock even though the clock is not + * stable. Trying to use a clock without waiting here results + * in EILSEQ while detecting some older/slower cards. The + * chosen delay is the maximum delay from sdhci_set_clock. + */ + msleep(20); +} + +static void eswin_sdhci_sdio_config_phy_delay(struct sdhci_host *host, + int delay) +{ + delay &= PHY_CLK_MAX_DELAY_MASK; + + /*phy clk delay line config*/ + sdhci_writeb(host, PHY_UPDATE_DELAY_CODE, PHY_SDCLKDL_CNFG_R); + sdhci_writeb(host, delay, PHY_SDCLKDL_DC_R); + sdhci_writeb(host, 0x0, PHY_SDCLKDL_CNFG_R); +} + +static void eswin_sdhci_sdio_config_phy(struct sdhci_host *host) +{ + unsigned int val = 0; + unsigned int drv = 0; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci = + sdhci_pltfm_priv(pltfm_host); + struct eswin_sdhci_phy_data *phy = &eswin_sdhci->phy; + + drv = phy->drive_impedance << PHY_PAD_SP_DRIVE_SHIF; + pr_debug("%s: phy drv=0x%x \n",mmc_hostname(host->mmc), drv); + + eswin_sdhci_disable_card_clk(host); + + /* reset phy,config phy's pad */ + sdhci_writel(host, drv | (~PHY_RSTN), PHY_CNFG_R); + /*CMDPAD_CNFS*/ + val = (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_P_BIT_SHIFT) | + (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_N_BIT_SHIFT) | + (phy->enable_cmd_pullup << PHY_PULL_BIT_SHIF) | PHY_PAD_RXSEL_1; + sdhci_writew(host, val, PHY_CMDPAD_CNFG_R); + pr_debug("%s: phy cmd=0x%x\n",mmc_hostname(host->mmc), val); + + /*DATA PAD CNFG*/ + val = (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_P_BIT_SHIFT) | + (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_N_BIT_SHIFT) | + (phy->enable_data_pullup << PHY_PULL_BIT_SHIF) | PHY_PAD_RXSEL_1; + sdhci_writew(host, val, PHY_DATAPAD_CNFG_R); + pr_debug("%s: phy data=0x%x\n",mmc_hostname(host->mmc), val); + + /*Clock PAD Setting*/ + val = (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_P_BIT_SHIFT) | + (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_N_BIT_SHIFT) | PHY_PAD_RXSEL_0; + sdhci_writew(host, val, PHY_CLKPAD_CNFG_R); + pr_debug("%s: phy clk=0x%x\n",mmc_hostname(host->mmc), val); + mdelay(2); + + /*PHY RSTN PAD setting*/ + val = (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_P_BIT_SHIFT) | + (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_N_BIT_SHIFT) | + (PHY_PULL_UP << PHY_PULL_BIT_SHIF) | PHY_PAD_RXSEL_1; + sdhci_writew(host, val, PHY_RSTNPAD_CNFG_R); + + sdhci_writel(host, drv | PHY_RSTN, PHY_CNFG_R); + + eswin_sdhci_sdio_config_phy_delay(host, phy->delay_code); + + eswin_sdhci_enable_card_clk(host); +} + +static void eswin_sdhci_sdio_reset(struct sdhci_host *host, u8 mask) +{ + u8 ctrl; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci_sdio = + sdhci_pltfm_priv(pltfm_host); + + /* Disable signal and interrupts before resetting the phy. + * Doing this avoids ISR to serve any undesired interrupts during + * reset and avoid producing the fake register dump during probe. + */ + sdhci_writel(host, 0, SDHCI_INT_ENABLE); + sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); + sdhci_reset(host, mask); + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + + if (eswin_sdhci_sdio->quirks & SDHCI_ESWIN_QUIRK_FORCE_CDTEST) { + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); + ctrl |= SDHCI_CTRL_CDTEST_INS | SDHCI_CTRL_CDTEST_EN; + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + } + if (mask == SDHCI_RESET_ALL) { // after reset all,the phy`s config will be clear. + eswin_sdhci_sdio_config_phy(host); + } +} + +static int eswin_sdhci_sdio_delay_tuning(struct sdhci_host *host, u32 opcode) +{ + int ret; + int delay = -1; + int i = 0; + int delay_min = -1; + int delay_max = -1; + int delay_range = -1; + + int cmd_error = 0; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci = + sdhci_pltfm_priv(pltfm_host); + + for (i = 0; i <= PHY_DELAY_CODE_MAX; i++) { + eswin_sdhci_disable_card_clk(host); + eswin_sdhci_sdio_config_phy_delay(host, i); + eswin_sdhci_enable_card_clk(host); + ret = mmc_send_tuning(host->mmc, opcode, &cmd_error); + if (ret) { + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + udelay(200); + if (delay_min != -1 && delay_max != -1) { + if (delay_max - delay_min > delay_range) { + delay_range = delay_max - delay_min; + delay = (delay_min + delay_max) / 2; + if (delay_range > DELAY_RANGE_THRESHOLD) + break; + } + delay_min = -1; + delay_max = -1; + } + } else { + if (delay_min == -1) { + delay_min = i; + continue; + } else { + delay_max = i; + continue; + } + } + } + if (delay == -1) { + pr_err("%s: delay code tuning failed!\n", + mmc_hostname(host->mmc)); + eswin_sdhci_disable_card_clk(host); + eswin_sdhci_sdio_config_phy_delay(host, + eswin_sdhci->phy.delay_code); + eswin_sdhci_enable_card_clk(host); + + return ret; + } + + pr_info("%s: set delay:0x%x\n", mmc_hostname(host->mmc), delay); + eswin_sdhci_disable_card_clk(host); + eswin_sdhci_sdio_config_phy_delay(host, delay); + eswin_sdhci_enable_card_clk(host); + + return 0; +} + +static int eswin_sdhci_sdio_phase_code_tuning(struct sdhci_host *host, + u32 opcode) +{ + int cmd_error = 0; + int ret = 0; + int phase_code = 0; + int code_min = -1; + int code_max = -1; + + for (phase_code = 0; phase_code <= MAX_PHASE_CODE; phase_code++) { + eswin_sdhci_disable_card_clk(host); + sdhci_writew(host, phase_code, VENDOR_AT_SATA_R); + eswin_sdhci_enable_card_clk(host); + + ret = mmc_send_tuning(host->mmc, opcode, &cmd_error); + if (ret) { + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + udelay(200); + if (code_min != -1 && code_max != -1) + break; + } else { + if (code_min == -1) { + code_min = phase_code; + continue; + } else { + code_max = phase_code; + continue; + } + } + } + if (code_min == -1 && code_max == -1) { + pr_err("%s: phase code tuning failed!\n", + mmc_hostname(host->mmc)); + eswin_sdhci_disable_card_clk(host); + sdhci_writew(host, 0, VENDOR_AT_SATA_R); + eswin_sdhci_enable_card_clk(host); + return -EIO; + } + + phase_code = (code_min + code_max) / 2; + pr_info("%s: set phase_code:0x%x\n", mmc_hostname(host->mmc), phase_code); + + eswin_sdhci_disable_card_clk(host); + sdhci_writew(host, phase_code, VENDOR_AT_SATA_R); + eswin_sdhci_enable_card_clk(host); + + return 0; +} + +static int eswin_sdhci_sdio_executing_tuning(struct sdhci_host *host, + u32 opcode) +{ + u32 ctrl; + u32 val; + int ret = 0; + struct sdhci_pltfm_host *pltfm_host; + struct eswin_sdhci_data *eswin_sdhci_sdio; + struct eswin_sdio_private *eswin_sdio_priv; + + pltfm_host = sdhci_priv(host); + eswin_sdhci_sdio = sdhci_pltfm_priv(pltfm_host); + eswin_sdio_priv = sdhci_sdio_priv(eswin_sdhci_sdio); + + if (!eswin_sdio_priv->enable_sw_tuning) { + if (eswin_sdio_priv->phase_code != -1) { + eswin_sdhci_disable_card_clk(host); + sdhci_writew(host, eswin_sdio_priv->phase_code, VENDOR_AT_SATA_R); + eswin_sdhci_enable_card_clk(host); + } + return 0; + } + + eswin_sdhci_disable_card_clk(host); + + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); + ctrl &= ~SDHCI_CTRL_TUNED_CLK; + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); + + val = sdhci_readl(host, VENDOR_AT_CTRL_R); + val |= SW_TUNE_ENABLE; + sdhci_writew(host, val, VENDOR_AT_CTRL_R); + sdhci_writew(host, 0, VENDOR_AT_SATA_R); + + eswin_sdhci_enable_card_clk(host); + + sdhci_writew(host, 0x0, SDHCI_CMD_DATA); + + ret = eswin_sdhci_sdio_delay_tuning(host, opcode); + if (ret < 0) { + return ret; + } + + ret = eswin_sdhci_sdio_phase_code_tuning(host, opcode); + if (ret < 0) { + return ret; + } + + return 0; +} + +static u32 eswin_sdhci_sdio_cqhci_irq(struct sdhci_host *host, u32 intmask) +{ + int cmd_error = 0; + int data_error = 0; + + if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) + return intmask; + + cqhci_irq(host->mmc, intmask, cmd_error, data_error); + + return 0; +} + +static void eswin_sdhci_sdio_dumpregs(struct mmc_host *mmc) +{ + sdhci_dumpregs(mmc_priv(mmc)); +} + +static void eswin_sdhci_sdio_cqe_enable(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + u32 reg; + + reg = sdhci_readl(host, SDHCI_PRESENT_STATE); + while (reg & SDHCI_DATA_AVAILABLE) { + sdhci_readl(host, SDHCI_BUFFER); + reg = sdhci_readl(host, SDHCI_PRESENT_STATE); + } + + sdhci_cqe_enable(mmc); +} + +static const struct cqhci_host_ops eswin_sdhci_sdio_cqhci_ops = { + .enable = eswin_sdhci_sdio_cqe_enable, + .disable = sdhci_cqe_disable, + .dumpregs = eswin_sdhci_sdio_dumpregs, +}; + +static const struct sdhci_ops eswin_sdhci_sdio_cqe_ops = { + .set_clock = eswin_sdhci_sdio_set_clock, + .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .get_timeout_clock = sdhci_pltfm_clk_get_max_clock, + .set_bus_width = sdhci_set_bus_width, + .reset = eswin_sdhci_sdio_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, + .set_power = sdhci_set_power_and_bus_voltage, + .irq = eswin_sdhci_sdio_cqhci_irq, + .platform_execute_tuning = eswin_sdhci_sdio_executing_tuning, + +}; + +static const struct sdhci_pltfm_data eswin_sdhci_sdio_cqe_pdata = { + .ops = &eswin_sdhci_sdio_cqe_ops, + .quirks = SDHCI_QUIRK_BROKEN_CQE | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN, +}; + +#ifdef CONFIG_PM_SLEEP +/** + * eswin_sdhci_sdio_suspend- Suspend method for the driver + * @dev: Address of the device structure + * + * Put the device in a low power state. + * + * Return: 0 on success and error value on error + */ +static int eswin_sdhci_sdio_suspend(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci_sdio = + sdhci_pltfm_priv(pltfm_host); + int ret; + + if (host->tuning_mode != SDHCI_TUNING_MODE_3) + mmc_retune_needed(host->mmc); + + if (eswin_sdhci_sdio->has_cqe) { + ret = cqhci_suspend(host->mmc); + if (ret) + return ret; + } + + ret = sdhci_suspend_host(host); + if (ret) + return ret; + + clk_disable(pltfm_host->clk); + clk_disable(eswin_sdhci_sdio->clk_ahb); + + return 0; +} + +/** + * eswin_sdhci_sdio_resume- Resume method for the driver + * @dev: Address of the device structure + * + * Resume operation after suspend + * + * Return: 0 on success and error value on error + */ +static int eswin_sdhci_sdio_resume(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci_sdio = + sdhci_pltfm_priv(pltfm_host); + int ret; + + ret = clk_enable(eswin_sdhci_sdio->clk_ahb); + if (ret) { + dev_err(dev, "Cannot enable AHB clock.\n"); + return ret; + } + + ret = clk_enable(pltfm_host->clk); + if (ret) { + dev_err(dev, "Cannot enable SD clock.\n"); + return ret; + } + + ret = sdhci_resume_host(host); + if (ret) { + dev_err(dev, "Cannot resume host.\n"); + return ret; + } + + if (eswin_sdhci_sdio->has_cqe) + return cqhci_resume(host->mmc); + + return 0; +} +#endif /* ! CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(eswin_sdhci_sdio_dev_pm_ops, eswin_sdhci_sdio_suspend, + eswin_sdhci_sdio_resume); + +/** + * eswin_sdhci_sdio_sdcardclk_recalc_rate- Return the card clock rate + * + * @hw: Pointer to the hardware clock structure. + * @parent_rate: The parent rate (should be rate of clk_xin). + * + * Return the current actual rate of the SD card clock. This can be used + * to communicate with out PHY. + * + * Return: The card clock rate. + */ +static unsigned long +eswin_sdhci_sdio_sdcardclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct eswin_sdhci_clk_data *clk_data = container_of( + hw, struct eswin_sdhci_clk_data, sdcardclk_hw); + struct eswin_sdhci_data *eswin_sdhci_sdio = + container_of(clk_data, struct eswin_sdhci_data, clk_data); + struct sdhci_host *host = eswin_sdhci_sdio->host; + + return host->mmc->actual_clock; +} + +static const struct clk_ops eswin_sdio_sdcardclk_ops = { + .recalc_rate = eswin_sdhci_sdio_sdcardclk_recalc_rate, +}; + +/** + * eswin_sdhci_sdio_sampleclk_recalc_rate- Return the sampling clock rate + * + * @hw: Pointer to the hardware clock structure. + * @parent_rate: The parent rate (should be rate of clk_xin). + * + * Return the current actual rate of the sampling clock. This can be used + * to communicate with out PHY. + * + * Return: The sample clock rate. + */ +static unsigned long +eswin_sdhci_sdio_sampleclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct eswin_sdhci_clk_data *clk_data = container_of( + hw, struct eswin_sdhci_clk_data, sampleclk_hw); + struct eswin_sdhci_data *eswin_sdhci_sdio = + container_of(clk_data, struct eswin_sdhci_data, clk_data); + struct sdhci_host *host = eswin_sdhci_sdio->host; + + return host->mmc->actual_clock; +} + +static const struct clk_ops eswin_sdio_sampleclk_ops = { + .recalc_rate = eswin_sdhci_sdio_sampleclk_recalc_rate, +}; + +static const struct eswin_sdhci_clk_ops eswin_sdio_clk_ops = { + .sdcardclk_ops = &eswin_sdio_sdcardclk_ops, + .sampleclk_ops = &eswin_sdio_sampleclk_ops, +}; + +static struct eswin_sdhci_of_data eswin_sdhci_fu800_sdio_data = { + .pdata = &eswin_sdhci_sdio_cqe_pdata, + .clk_ops = &eswin_sdio_clk_ops, +}; + +static const struct of_device_id eswin_sdhci_sdio_of_match[] = { + /* SoC-specific compatible strings*/ + { + .compatible = "eswin,sdhci-sdio", + .data = &eswin_sdhci_fu800_sdio_data, + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, eswin_sdhci_sdio_of_match); + +/** + * eswin_sdhci_sdio_register_sdcardclk- Register the sdcardclk for a PHY to use + * + * @sdhci_arasan: Our private data structure. + * @clk_xin: Pointer to the functional clock + * @dev: Pointer to our struct device. + * + * Some PHY devices need to know what the actual card clock is. In order for + * them to find out, we'll provide a clock through the common clock framework + * for them to query. + * + * Return: 0 on success and error value on error + */ +static int eswin_sdhci_sdio_register_sdcardclk( + struct eswin_sdhci_data *eswin_sdhci_sdio, struct clk *clk_xin, + struct device *dev) +{ + struct eswin_sdhci_clk_data *clk_data = + &eswin_sdhci_sdio->clk_data; + struct device_node *np = dev->of_node; + struct clk_init_data sdcardclk_init; + const char *parent_clk_name; + int ret; + + ret = of_property_read_string_index(np, "clock-output-names", 0, + &sdcardclk_init.name); + if (ret) { + dev_err(dev, "DT has #clock-cells but no clock-output-names\n"); + return ret; + } + + parent_clk_name = __clk_get_name(clk_xin); + sdcardclk_init.parent_names = &parent_clk_name; + sdcardclk_init.num_parents = 1; + sdcardclk_init.flags = CLK_GET_RATE_NOCACHE; + sdcardclk_init.ops = eswin_sdhci_sdio->clk_ops->sdcardclk_ops; + + clk_data->sdcardclk_hw.init = &sdcardclk_init; + clk_data->sdcardclk = devm_clk_register(dev, &clk_data->sdcardclk_hw); + if (IS_ERR(clk_data->sdcardclk)) + return PTR_ERR(clk_data->sdcardclk); + clk_data->sdcardclk_hw.init = NULL; + + ret = of_clk_add_provider(np, of_clk_src_simple_get, + clk_data->sdcardclk); + if (ret) + dev_err(dev, "Failed to add sdcard clock provider\n"); + + return ret; +} + +/** + * eswin_sdhci_sdio_register_sampleclk - Register the sampleclk for a PHY to use + * + * @sdhci_arasan: Our private data structure. + * @clk_xin: Pointer to the functional clock + * @dev: Pointer to our struct device. + * + * Some PHY devices need to know what the actual card clock is. In order for + * them to find out, we'll provide a clock through the common clock framework + * for them to query. + * + * Return: 0 on success and error value on error + */ +static int eswin_sdhci_sdio_register_sampleclk( + struct eswin_sdhci_data *eswin_sdhci_sdio, struct clk *clk_xin, + struct device *dev) +{ + struct eswin_sdhci_clk_data *clk_data = + &eswin_sdhci_sdio->clk_data; + struct device_node *np = dev->of_node; + struct clk_init_data sampleclk_init; + const char *parent_clk_name; + int ret; + + ret = of_property_read_string_index(np, "clock-output-names", 1, + &sampleclk_init.name); + if (ret) { + dev_err(dev, "DT has #clock-cells but no clock-output-names\n"); + return ret; + } + + parent_clk_name = __clk_get_name(clk_xin); + sampleclk_init.parent_names = &parent_clk_name; + sampleclk_init.num_parents = 1; + sampleclk_init.flags = CLK_GET_RATE_NOCACHE; + sampleclk_init.ops = eswin_sdhci_sdio->clk_ops->sampleclk_ops; + + clk_data->sampleclk_hw.init = &sampleclk_init; + clk_data->sampleclk = devm_clk_register(dev, &clk_data->sampleclk_hw); + if (IS_ERR(clk_data->sampleclk)) + return PTR_ERR(clk_data->sampleclk); + clk_data->sampleclk_hw.init = NULL; + + ret = of_clk_add_provider(np, of_clk_src_simple_get, + clk_data->sampleclk); + if (ret) + dev_err(dev, "Failed to add sample clock provider\n"); + + return ret; +} + +/** + * eswin_sdhci_sdio_unregister_sdclk- Undoes sdhci_arasan_register_sdclk() + * + * @dev: Pointer to our struct device. + * + * Should be called any time we're exiting and sdhci_arasan_register_sdclk() + * returned success. + */ +static void eswin_sdhci_sdio_unregister_sdclk(struct device *dev) +{ + struct device_node *np = dev->of_node; + + if (!of_find_property(np, "#clock-cells", NULL)) + return; + + of_clk_del_provider(dev->of_node); +} + +/** + * eswin_sdhci_sdio_register_sdclk- Register the sdcardclk for a PHY to use + * + * @eswin_sdhci_sdio: Our private data structure. + * @clk_xin: Pointer to the functional clock + * @dev: Pointer to our struct device. + * + * Some PHY devices need to know what the actual card clock is. In order for + * them to find out, we'll provide a clock through the common clock framework + * for them to query. + * + * Note: without seriously re-architecting SDHCI's clock code and testing on + * all platforms, there's no way to create a totally beautiful clock here + * with all clock ops implemented. Instead, we'll just create a clock that can + * be queried and set the CLK_GET_RATE_NOCACHE attribute to tell common clock + * framework that we're doing things behind its back. This should be sufficient + * to create nice clean device tree bindings and later (if needed) we can try + * re-architecting SDHCI if we see some benefit to it. + * + * Return: 0 on success and error value on error + */ +static int +eswin_sdhci_sdio_register_sdclk(struct eswin_sdhci_data *eswin_sdhci_sdio, + struct clk *clk_xin, struct device *dev) +{ + struct device_node *np = dev->of_node; + u32 num_clks = 0; + int ret; + + /* Providing a clock to the PHY is optional; no error if missing */ + if (of_property_read_u32(np, "#clock-cells", &num_clks) < 0) + return 0; + + ret = eswin_sdhci_sdio_register_sdcardclk(eswin_sdhci_sdio, clk_xin, + dev); + if (ret) + return ret; + + if (num_clks) { + ret = eswin_sdhci_sdio_register_sampleclk(eswin_sdhci_sdio, + clk_xin, dev); + if (ret) { + eswin_sdhci_sdio_unregister_sdclk(dev); + return ret; + } + } + + return 0; +} + +static int +eswin_sdhci_sdio_add_host(struct eswin_sdhci_data *eswin_sdhci_sdio) +{ + struct sdhci_host *host = eswin_sdhci_sdio->host; + struct cqhci_host *cq_host; + bool dma64; + int ret; + + if (!eswin_sdhci_sdio->has_cqe) + return sdhci_add_host(host); + + ret = sdhci_setup_host(host); + if (ret) + return ret; + + cq_host = devm_kzalloc(host->mmc->parent, sizeof(*cq_host), GFP_KERNEL); + if (!cq_host) { + ret = -ENOMEM; + goto cleanup; + } + + cq_host->mmio = host->ioaddr + ESWIN_SDHCI_SD_CQE_BASE_ADDR; + cq_host->ops = &eswin_sdhci_sdio_cqhci_ops; + + dma64 = host->flags & SDHCI_USE_64_BIT_DMA; + if (dma64) + cq_host->caps |= CQHCI_TASK_DESC_SZ_128; + + ret = cqhci_init(cq_host, host->mmc, dma64); + if (ret) + goto cleanup; + + ret = __sdhci_add_host(host); + if (ret) + goto cleanup; + + return 0; + +cleanup: + sdhci_cleanup_host(host); + return ret; +} + +static int eswin_sdhci_sdio_sid_cfg(struct device *dev) +{ + int ret; + struct regmap *regmap; + int hsp_mmu_sdio_reg; + u32 rdwr_sid_ssid; + u32 sid; + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + + /* not behind smmu, use the default reset value(0x0) of the reg as streamID*/ + if (fwspec == NULL) { + dev_dbg(dev, + "dev is not behind smmu, skip configuration of sid\n"); + return 0; + } + sid = fwspec->ids[0]; + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, + "eswin,hsp_sp_csr"); + if (IS_ERR(regmap)) { + dev_dbg(dev, "No hsp_sp_csr phandle specified\n"); + return 0; + } + + ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 1, + &hsp_mmu_sdio_reg); + if (ret) { + dev_err(dev, "can't get sdio sid cfg reg offset (%d)\n", ret); + return ret; + } + + /* make the reading sid the same as writing sid, ssid is fixed to zero */ + rdwr_sid_ssid = FIELD_PREP(AWSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(AWSMMUSSID, 0); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSSID, 0); + regmap_write(regmap, hsp_mmu_sdio_reg, rdwr_sid_ssid); + + ret = eic7700_dynm_sid_enable(dev_to_node(dev)); + if (ret < 0) + dev_err(dev, "failed to config sdio streamID(%d)!\n", sid); + else + dev_dbg(dev, "success to config sdio streamID(%d)!\n", sid); + + return ret; +} + +static int eswin_sdhci_sdio_probe(struct platform_device *pdev) +{ + int ret; + struct clk *clk_xin; + struct clk *clk_spll2_fout3; + struct clk *clk_mux; + struct sdhci_host *host; + struct sdhci_pltfm_host *pltfm_host; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct eswin_sdhci_data *eswin_sdhci_sdio; + struct eswin_sdio_private *eswin_sdio_priv; + struct regmap *regmap; + const struct eswin_sdhci_of_data *data; + unsigned int sdio_id = 0; + unsigned int val = 0; + + data = of_device_get_match_data(dev); + host = sdhci_pltfm_init(pdev, data->pdata, sizeof(*eswin_sdhci_sdio) + sizeof(*eswin_sdio_priv)); + + if (IS_ERR(host)) + return PTR_ERR(host); + + pltfm_host = sdhci_priv(host); + eswin_sdhci_sdio = sdhci_pltfm_priv(pltfm_host); + eswin_sdhci_sdio->host = host; + eswin_sdhci_sdio->has_cqe = false; + eswin_sdio_priv = sdhci_sdio_priv(eswin_sdhci_sdio); + + ret = of_property_read_u32(dev->of_node, "core-clk-reg", &val); + if (ret) { + dev_err(dev, "get core clk reg failed.\n"); + goto err_pltfm_free; + } + + eswin_sdhci_sdio->core_clk_reg = ioremap(val, 0x4); + if (!eswin_sdhci_sdio->core_clk_reg) { + dev_err(dev, "ioremap core clk reg failed.\n"); + goto err_pltfm_free; + } + + ret = of_property_read_u32(dev->of_node, "sdio-id", &sdio_id); + if (ret) { + dev_err(dev, "get sdio-id failed.\n"); + goto err_pltfm_free; + } + + sdhci_get_of_property(pdev); + + eswin_sdhci_sdio->clk_ops = data->clk_ops; + eswin_sdhci_sdio->clk_ahb = devm_clk_get(dev, "clk_ahb"); + if (IS_ERR(eswin_sdhci_sdio->clk_ahb)) { + ret = dev_err_probe(dev, PTR_ERR(eswin_sdhci_sdio->clk_ahb), + "clk_ahb clock not found.\n"); + goto err_pltfm_free; + } + + clk_xin = devm_clk_get(dev, "clk_xin"); + if (IS_ERR(clk_xin)) { + ret = dev_err_probe(dev, PTR_ERR(clk_xin), + "clk_xin clock not found.\n"); + goto err_pltfm_free; + } + + clk_spll2_fout3 = devm_clk_get(dev, "clk_spll2_fout3"); + + if (IS_ERR(clk_spll2_fout3)) { + ret = dev_err_probe(dev, PTR_ERR(clk_spll2_fout3), + "clk_spll2_fout3 clock not found.\n"); + goto err_pltfm_free; + } + + if (of_device_is_compatible(np, "eswin,sdhci-sdio")) { + clk_mux = devm_clk_get(dev, "clk_mux1_1"); + if (IS_ERR(clk_mux)) { + ret = dev_err_probe(dev, PTR_ERR(clk_mux), + "clk_mux1_1 clock not found.\n"); + goto err_pltfm_free; + } + /*switch the core clk source*/ + clk_set_parent(clk_mux, clk_spll2_fout3); + } + + ret = clk_prepare_enable(eswin_sdhci_sdio->clk_ahb); + if (ret) { + dev_err(dev, "Unable to enable AHB clock.\n"); + goto err_pltfm_free; + } + /* If clock-frequency property is set, use the provided value */ + if (pltfm_host->clock && pltfm_host->clock != clk_get_rate(clk_xin)) { + ret = clk_set_rate(clk_xin, pltfm_host->clock); + if (ret) { + dev_err(&pdev->dev, "Failed to set SD clock rate\n"); + goto clk_dis_ahb; + } + } + + ret = clk_prepare_enable(clk_xin); + if (ret) { + dev_err(dev, "Unable to enable SD clock.\n"); + goto clk_dis_ahb; + } + + pltfm_host->clk = clk_xin; + ret = eswin_sdhci_sdio_register_sdclk(eswin_sdhci_sdio, clk_xin, dev); + if (ret) + goto clk_disable_all; + + ret = eswin_sdhci_reset_init(dev, eswin_sdhci_sdio); + if (ret < 0) { + dev_err(dev, "failed to reset\n"); + goto clk_disable_all; + } + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, + "eswin,hsp_sp_csr"); + if (IS_ERR(regmap)) { + dev_dbg(dev, "No hsp_sp_csr phandle specified\n"); + return 0; + } + + if (sdio_id == 0) { + regmap_write(regmap, ESWIN_SDHCI_SD0_INT_STATUS, + MSHC_INT_CLK_STABLE); + regmap_write(regmap, ESWIN_SDHCI_SD0_PWR_CTRL, MSHC_HOST_VAL_STABLE); + } else { + regmap_write(regmap, ESWIN_SDHCI_SD1_INT_STATUS, + MSHC_INT_CLK_STABLE); + regmap_write(regmap, ESWIN_SDHCI_SD1_PWR_CTRL, MSHC_HOST_VAL_STABLE); + } + + ret = eswin_sdhci_sdio_sid_cfg(dev); + if (ret < 0) { + dev_err(dev, "failed to use smmu\n"); + goto clk_disable_all; + } + + if (!of_property_read_u32(dev->of_node, "delay_code", &val)) { + eswin_sdhci_sdio->phy.delay_code = val; + } + + if (!of_property_read_u32(dev->of_node, "drive-impedance-ohm", &val)) + eswin_sdhci_sdio->phy.drive_impedance = + eswin_convert_drive_impedance_ohm(pdev, val); + + if (of_property_read_bool(dev->of_node, "enable-cmd-pullup")) + eswin_sdhci_sdio->phy.enable_cmd_pullup = ENABLE; + else + eswin_sdhci_sdio->phy.enable_cmd_pullup = DISABLE; + + if (of_property_read_bool(dev->of_node, "enable-data-pullup")) + eswin_sdhci_sdio->phy.enable_data_pullup = ENABLE; + else + eswin_sdhci_sdio->phy.enable_data_pullup = DISABLE; + + if (of_property_read_bool(dev->of_node, "enable_sw_tuning")) + eswin_sdio_priv->enable_sw_tuning = ENABLE; + else + eswin_sdio_priv->enable_sw_tuning = DISABLE; + + if (!of_property_read_u32(dev->of_node, "phase_code", &val)) { + eswin_sdio_priv->phase_code = val; + } else { + eswin_sdio_priv->phase_code = -1; + } + + eswin_sdhci_dt_parse_clk_phases(dev, &eswin_sdhci_sdio->clk_data); + ret = mmc_of_parse(host->mmc); + if (ret) { + ret = dev_err_probe(dev, ret, "parsing dt failed.\n"); + goto unreg_clk; + } + + eic7700_tbu_power(&pdev->dev, true); + + ret = eswin_sdhci_sdio_add_host(eswin_sdhci_sdio); + if (ret) + goto unreg_clk; + + return 0; + +unreg_clk: + eswin_sdhci_sdio_unregister_sdclk(dev); +clk_disable_all: + clk_disable_unprepare(clk_xin); +clk_dis_ahb: + clk_disable_unprepare(eswin_sdhci_sdio->clk_ahb); +err_pltfm_free: + if (eswin_sdhci_sdio->core_clk_reg) + iounmap(eswin_sdhci_sdio->core_clk_reg); + + sdhci_pltfm_free(pdev); + return ret; +} + +static int eswin_sdhci_sdio_remove(struct platform_device *pdev) +{ + int ret; + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci_sdio = + sdhci_pltfm_priv(pltfm_host); + struct clk *clk_ahb = eswin_sdhci_sdio->clk_ahb; + void __iomem *core_clk_reg = eswin_sdhci_sdio->core_clk_reg; + + sdhci_pltfm_remove(pdev); + eic7700_tbu_power(&pdev->dev, false); + + if (eswin_sdhci_sdio->txrx_rst) { + ret = reset_control_assert(eswin_sdhci_sdio->txrx_rst); + WARN_ON(0 != ret); + } + + if (eswin_sdhci_sdio->phy_rst) { + ret = reset_control_assert(eswin_sdhci_sdio->phy_rst); + WARN_ON(0 != ret); + } + + if (eswin_sdhci_sdio->prstn) { + ret = reset_control_assert(eswin_sdhci_sdio->prstn); + WARN_ON(0 != ret); + } + + if (eswin_sdhci_sdio->arstn) { + ret = reset_control_assert(eswin_sdhci_sdio->arstn); + WARN_ON(0 != ret); + } + + eswin_sdhci_sdio_unregister_sdclk(&pdev->dev); + clk_disable_unprepare(clk_ahb); + iounmap(core_clk_reg); + + return 0; +} + +static struct platform_driver eswin_sdhci_sdio_driver = { + .driver = { + .name = "eswin-sdhci-sdio", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + .of_match_table = eswin_sdhci_sdio_of_match, + .pm = &eswin_sdhci_sdio_dev_pm_ops, + }, + .probe = eswin_sdhci_sdio_probe, + .remove = eswin_sdhci_sdio_remove, +}; + +static __init int eswin_sdhci_sdio_init(void) +{ + int ret; + + ret = platform_driver_register(&eswin_sdhci_sdio_driver); + if (ret) { + pr_err("%s: failed to register platform driver\n", + __func__); + } + + return ret; +} + +static void __exit eswin_sdhci_sdio_exit(void) +{ + platform_driver_unregister(&eswin_sdhci_sdio_driver); +} + +/*Cause EMMC is often used as a system disk(mmc0), we need the SD driver to run later than the EMMC driver*/ +late_initcall(eswin_sdhci_sdio_init); +module_exit(eswin_sdhci_sdio_exit); + +MODULE_DESCRIPTION("Driver for the Eswin SDHCI Controller"); +MODULE_AUTHOR("Eswin"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mmc/host/sdhci-of-eswin.c b/drivers/mmc/host/sdhci-of-eswin.c new file mode 100644 index 0000000000000..008b243dff324 --- /dev/null +++ b/drivers/mmc/host/sdhci-of-eswin.c @@ -0,0 +1,1104 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Emmc 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 . + * + * Authors: liangshuang + */ + +#include +#include +#include +#include +#include +#include +#include +#include "cqhci.h" +#include "sdhci-pltfm.h" +#include +#include +#include +#include +#include +#include "sdhci-eswin.h" + +#define SDHCI_EMMC0_INT_STATUS 0x508 +#define SDHCI_EMMC0_PWR_CLEAR 0x50c + +//EMMC_DWC_MSHC_CRYPTO_CFG_PTR 8 -- parameter +#define eswin_sdhci_VENDOR_REGISTER_BASEADDR 0x800 +#define eswin_sdhci_VENDOR_EMMC_CTRL_REGISTER 0x2c +#define VENDOR_ENHANCED_STROBE BIT(8) + +#define eswin_sdhci_CQE_BASE_ADDR eswin_sdhci_VENDOR_REGISTER_BASEADDR + +/* Controller does not have CD wired and will not function normally without */ +#define eswin_sdhci_QUIRK_FORCE_CDTEST BIT(0) +/* Controller immediately reports SDHCI_CLOCK_INT_STABLE after enabling the + * internal clock even when the clock isn't stable */ +#define eswin_sdhci_QUIRK_CLOCK_UNSTABLE BIT(1) + +/* + * On some SoCs the syscon area has a feature where the upper 16-bits of + * each 32-bit register act as a write mask for the lower 16-bits. This allows + * atomic updates of the register without locking. This macro is used on SoCs + * that have that feature. + */ +#define HIWORD_UPDATE(val, mask, shift) \ + ((val) << (shift) | (mask) << ((shift) + 16)) + +#define ESWIN_EMMC_CORE_CLK_REG 0x51828160 + +static void eswin_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + struct eswin_sdhci_clk_data *clk_data = &eswin_sdhci->clk_data; + + /* Set the Input and Output Clock Phase Delays */ + if (clk_data->set_clk_delays) + clk_data->set_clk_delays(host); + + eswin_sdhci_set_core_clock(host, clock); + sdhci_set_clock(host, clock); + + /* + * Some controllers immediately report SDHCI_CLOCK_INT_STABLE + * after enabling the clock even though the clock is not + * stable. Trying to use a clock without waiting here results + * in EILSEQ while detecting some older/slower cards. The + * chosen delay is the maximum delay from sdhci_set_clock. + */ + if (eswin_sdhci->quirks & SDHCI_ESWIN_QUIRK_CLOCK_UNSTABLE) + msleep(20); +} + +#if !defined(__FPGA) && !defined(__ZEBU) +static void eswin_sdhci_hs400_enhanced_strobe(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + u32 vendor; + struct sdhci_host *host = mmc_priv(mmc); + + vendor = sdhci_readl(host, eswin_sdhci_VENDOR_EMMC_CTRL_REGISTER); + if (ios->enhanced_strobe) + vendor |= VENDOR_ENHANCED_STROBE; + else + vendor &= ~VENDOR_ENHANCED_STROBE; + + sdhci_writel(host, vendor, eswin_sdhci_VENDOR_EMMC_CTRL_REGISTER); +} +#endif + +static void eswin_sdhci_config_phy_delay(struct sdhci_host *host, int delay) +{ + delay &= PHY_CLK_MAX_DELAY_MASK; + + /*phy clk delay line config*/ + sdhci_writeb(host, PHY_UPDATE_DELAY_CODE, PHY_SDCLKDL_CNFG_R); + sdhci_writeb(host, delay, PHY_SDCLKDL_DC_R); + sdhci_writeb(host, 0x0, PHY_SDCLKDL_CNFG_R); +} + +static void eswin_sdhci_config_phy(struct sdhci_host *host) +{ + unsigned int val = 0; + unsigned int drv = 0; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + struct eswin_sdhci_phy_data *phy = &eswin_sdhci->phy; + + drv = phy->drive_impedance << PHY_PAD_SP_DRIVE_SHIF; + + pr_debug("%s: phy drv=0x%x\n", mmc_hostname(host->mmc), drv); + + val = sdhci_readw(host, VENDOR_EMMC_CTRL_R); + val |= EMMC_CRAD_PRESENT; // emmc card + sdhci_writew(host, val, VENDOR_EMMC_CTRL_R); + + eswin_sdhci_disable_card_clk(host); + + /* reset phy,config phy's pad */ + sdhci_writel(host, drv | (~PHY_RSTN), PHY_CNFG_R); + /*CMDPAD_CNFS*/ + val = (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_P_BIT_SHIFT) | + (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_N_BIT_SHIFT) | + (phy->enable_cmd_pullup << PHY_PULL_BIT_SHIF) | PHY_PAD_RXSEL_1; + sdhci_writew(host, val, PHY_CMDPAD_CNFG_R); + pr_debug("%s: phy cmd=0x%x\n", mmc_hostname(host->mmc), val); + + /*DATA PAD CNFG*/ + val = (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_P_BIT_SHIFT) | + (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_N_BIT_SHIFT) | + (phy->enable_data_pullup << PHY_PULL_BIT_SHIF) | PHY_PAD_RXSEL_1; + sdhci_writew(host, val, PHY_DATAPAD_CNFG_R); + pr_debug("%s: phy data=0x%x\n", mmc_hostname(host->mmc), val); + + /*Clock PAD Setting*/ + val = (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_P_BIT_SHIFT) | + (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_N_BIT_SHIFT) | PHY_PAD_RXSEL_0; + sdhci_writew(host, val, PHY_CLKPAD_CNFG_R); + pr_debug("%s: phy clk=0x%x\n", mmc_hostname(host->mmc), val); + + /*PHY strobe PAD setting*/ + val = (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_P_BIT_SHIFT) | + (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_N_BIT_SHIFT) | + ((phy->enable_strobe_pulldown * PHY_PULL_DOWN) << PHY_PULL_BIT_SHIF) | + PHY_PAD_RXSEL_1; + sdhci_writew(host, val, PHY_STBPAD_CNFG_R); + pr_debug("%s: phy strobe=0x%x\n", mmc_hostname(host->mmc), val); + mdelay(2); + + /*PHY RSTN PAD setting*/ + val = (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_P_BIT_SHIFT) | + (PHY_SLEW_2 << PHY_TX_SLEW_CTRL_N_BIT_SHIFT) | + (PHY_PULL_UP << PHY_PULL_BIT_SHIF) | PHY_PAD_RXSEL_1; + sdhci_writew(host, val, PHY_RSTNPAD_CNFG_R); + pr_debug("%s: phy rstn=0x%x\n", mmc_hostname(host->mmc), val); + + sdhci_writel(host, drv | PHY_RSTN, PHY_CNFG_R); + + eswin_sdhci_config_phy_delay(host, phy->delay_code); + + eswin_sdhci_enable_card_clk(host); +} + +static void eswin_sdhci_reset(struct sdhci_host *host, u8 mask) +{ + u8 ctrl; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + + /* Disable signal and interrupts before resetting the phy. + * Doing this avoids ISR to serve any undesired interrupts during + * reset and avoid producing the fake register dump during probe. + */ + sdhci_writel(host, 0, SDHCI_INT_ENABLE); + sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); + sdhci_reset(host, mask); + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + + if (eswin_sdhci->quirks & SDHCI_ESWIN_QUIRK_FORCE_CDTEST) { + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); + ctrl |= SDHCI_CTRL_CDTEST_INS | SDHCI_CTRL_CDTEST_EN; + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + } + + if (mask == SDHCI_RESET_ALL) { // after reset all,the phy`s config will be clear. + eswin_sdhci_config_phy(host); + } +} + +static u32 eswin_sdhci_cqhci_irq(struct sdhci_host *host, u32 intmask) +{ + int cmd_error = 0; + int data_error = 0; + + if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) + return intmask; + + cqhci_irq(host->mmc, intmask, cmd_error, data_error); + + return 0; +} + +static void eswin_sdhci_dumpregs(struct mmc_host *mmc) +{ + sdhci_dumpregs(mmc_priv(mmc)); +} + +static void eswin_sdhci_cqe_enable(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + u32 reg; + + reg = sdhci_readl(host, SDHCI_PRESENT_STATE); + while (reg & SDHCI_DATA_AVAILABLE) { + sdhci_readl(host, SDHCI_BUFFER); + reg = sdhci_readl(host, SDHCI_PRESENT_STATE); + } + + sdhci_cqe_enable(mmc); +} + +static int eswin_sdhci_delay_tuning(struct sdhci_host *host, u32 opcode) +{ + int ret; + int delay = 0; + int i = 0; + int delay_min = -1; + int delay_max = -1; + int cmd_error = 0; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + + for (i = 0; i <= PHY_DELAY_CODE_MAX; i++) { + eswin_sdhci_disable_card_clk(host); + eswin_sdhci_config_phy_delay(host, i); + eswin_sdhci_enable_card_clk(host); + ret = mmc_send_tuning(host->mmc, opcode, &cmd_error); + if (ret) { + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + udelay(200); + if (delay_min != -1 && delay_max != -1) + break; + } else { + if (delay_min == -1) { + delay_min = i; + continue; + } else { + delay_max = i; + continue; + } + } + } + if (delay_min == -1 && delay_max == -1) { + pr_err("%s: delay code tuning failed!\n", + mmc_hostname(host->mmc)); + eswin_sdhci_disable_card_clk(host); + eswin_sdhci_config_phy_delay(host, eswin_sdhci->phy.delay_code); + eswin_sdhci_enable_card_clk(host); + + return ret; + } + + delay = (delay_min + delay_max) / 2; + pr_info("%s: set delay:0x%x\n", mmc_hostname(host->mmc), delay); + eswin_sdhci_disable_card_clk(host); + eswin_sdhci_config_phy_delay(host, delay); + eswin_sdhci_enable_card_clk(host); + + return 0; +} + +static int eswin_sdhci_phase_code_tuning(struct sdhci_host *host, u32 opcode) +{ + int cmd_error = 0; + int ret = 0; + int phase_code = 0; + int code_min = -1; + int code_max = -1; + + for (phase_code = 0; phase_code <= MAX_PHASE_CODE; phase_code++) { + eswin_sdhci_disable_card_clk(host); + sdhci_writew(host, phase_code, VENDOR_AT_SATA_R); + eswin_sdhci_enable_card_clk(host); + + ret = mmc_send_tuning(host->mmc, opcode, &cmd_error); + if (ret) { + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + udelay(200); + if (code_min != -1 && code_max != -1) + break; + } else { + if (code_min == -1) { + code_min = phase_code; + continue; + } else { + code_max = phase_code; + continue; + } + } + } + if (code_min == -1 && code_max == -1) { + pr_err("%s: phase code tuning failed!\n", + mmc_hostname(host->mmc)); + eswin_sdhci_disable_card_clk(host); + sdhci_writew(host, 0, VENDOR_AT_SATA_R); + eswin_sdhci_enable_card_clk(host); + return -EIO; + } + + phase_code = (code_min + code_max) / 2; + pr_info("%s: set phase_code:0x%x\n", mmc_hostname(host->mmc), phase_code); + + eswin_sdhci_disable_card_clk(host); + sdhci_writew(host, phase_code, VENDOR_AT_SATA_R); + eswin_sdhci_enable_card_clk(host); + + return 0; +} + +static int eswin_sdhci_executing_tuning(struct sdhci_host *host, u32 opcode) +{ + u32 ctrl; + u32 val; + int ret = 0; + + eswin_sdhci_disable_card_clk(host); + + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); + ctrl &= ~SDHCI_CTRL_TUNED_CLK; + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); + + val = sdhci_readl(host, VENDOR_AT_CTRL_R); + val |= SW_TUNE_ENABLE; + sdhci_writew(host, val, VENDOR_AT_CTRL_R); + sdhci_writew(host, 0, VENDOR_AT_SATA_R); + + eswin_sdhci_enable_card_clk(host); + + sdhci_writew(host, 0x0, SDHCI_CMD_DATA); + + ret = eswin_sdhci_delay_tuning(host, opcode); + if (ret < 0) { + return ret; + } + ret = eswin_sdhci_phase_code_tuning(host, opcode); + if (ret < 0) { + return ret; + } + + return 0; +} + +void eswin_sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) +{ + u32 val; + u32 status; + u32 timeout = 0; + u16 ctrl_2; + + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + /* Select Bus Speed Mode for host */ + ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; + if ((timing == MMC_TIMING_MMC_HS200) || + (timing == MMC_TIMING_UHS_SDR104)) + ctrl_2 |= SDHCI_CTRL_UHS_SDR104; + else if (timing == MMC_TIMING_UHS_SDR12) + ctrl_2 |= SDHCI_CTRL_UHS_SDR12; + else if (timing == MMC_TIMING_UHS_SDR25) + ctrl_2 |= SDHCI_CTRL_UHS_SDR25; + else if (timing == MMC_TIMING_UHS_SDR50) + ctrl_2 |= SDHCI_CTRL_UHS_SDR50; + else if ((timing == MMC_TIMING_UHS_DDR50) || + (timing == MMC_TIMING_MMC_DDR52)) + ctrl_2 |= SDHCI_CTRL_UHS_DDR50; + else if (timing == MMC_TIMING_MMC_HS400) + ctrl_2 |= ESWIN_SDHCI_CTRL_HS400; /* Non-standard */ + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); + + + /* + * here need make dll locked when in hs400 at 200MHz + */ + if ((timing == MMC_TIMING_MMC_HS400) && (host->clock == 200000000)) { + eswin_sdhci_disable_card_clk(host); + + val = sdhci_readl(host, VENDOR_AT_CTRL_R); + val &= ~(LATENCY_LT_MASK << LATENCY_LT_BIT_OFFSET); + val |= (LATENCY_LT_3 << LATENCY_LT_MASK); + sdhci_writel(host, val, VENDOR_AT_CTRL_R); + + sdhci_writeb(host, 0x23, PHY_DLL_CNFG1_R); + sdhci_writeb(host, 0x02, PHY_DLL_CNFG2_R); + sdhci_writeb(host, 0x60, PHY_DLLDL_CNFG_R); + sdhci_writeb(host, 0x00, PHY_DLL_OFFST_R); + sdhci_writew(host, 0xffff, PHY_DLLBT_CNFG_R); + + eswin_sdhci_enable_card_clk(host); + sdhci_writeb(host, DLL_ENABEL, PHY_DLL_CTRL_R); + udelay(100); + + while (1) { + status = sdhci_readb(host, PHY_DLL_STATUS_R); + if (status & DLL_LOCK_STS) { + pr_debug("%s: locked status:0x%x\n", mmc_hostname(host->mmc), status); + break; + } + timeout++; + udelay(100); + if (timeout > 10000) { + pr_err("%s: DLL lock failed!status:0x%x\n", + mmc_hostname(host->mmc), status); + return; + } + } + + status = sdhci_readb(host, PHY_DLL_STATUS_R); + if (status & DLL_ERROR_STS) { + pr_err("%s: DLL lock failed!err_status:0x%x\n", + mmc_hostname(host->mmc), status); + } else { + pr_debug("%s: DLL lock is success\n", mmc_hostname(host->mmc)); + } + } +} + +static const struct cqhci_host_ops eswin_sdhci_cqhci_ops = { + .enable = eswin_sdhci_cqe_enable, + .disable = sdhci_cqe_disable, + .dumpregs = eswin_sdhci_dumpregs, +}; + +static const struct sdhci_ops eswin_sdhci_cqe_ops = { + .set_clock = eswin_sdhci_set_clock, + .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .get_timeout_clock = sdhci_pltfm_clk_get_max_clock, + .set_bus_width = sdhci_set_bus_width, + .reset = eswin_sdhci_reset, + .set_uhs_signaling = eswin_sdhci_set_uhs_signaling, + .set_power = sdhci_set_power_and_bus_voltage, + .irq = eswin_sdhci_cqhci_irq, + .platform_execute_tuning = eswin_sdhci_executing_tuning, +}; + +static const struct sdhci_pltfm_data eswin_sdhci_cqe_pdata = { + .ops = &eswin_sdhci_cqe_ops, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | +#if defined(__DISABLE_HS200) + SDHCI_QUIRK2_BROKEN_HS200 | +#endif + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN, +}; + +#ifdef CONFIG_PM_SLEEP +/** + * eswin_sdhci_suspend - Suspend method for the driver + * @dev: Address of the device structure + * + * Put the device in a low power state. + * + * Return: 0 on success and error value on error + */ +static int eswin_sdhci_suspend(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + int ret; + + if (host->tuning_mode != SDHCI_TUNING_MODE_3) + mmc_retune_needed(host->mmc); + + if (eswin_sdhci->has_cqe) { + ret = cqhci_suspend(host->mmc); + if (ret) + return ret; + } + + ret = sdhci_suspend_host(host); + if (ret) + return ret; + + clk_disable(pltfm_host->clk); + clk_disable(eswin_sdhci->clk_ahb); + + return 0; +} + +/** + * eswin_sdhci_resume - Resume method for the driver + * @dev: Address of the device structure + * + * Resume operation after suspend + * + * Return: 0 on success and error value on error + */ +static int eswin_sdhci_resume(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + int ret; + + ret = clk_enable(eswin_sdhci->clk_ahb); + if (ret) { + dev_err(dev, "Cannot enable AHB clock.\n"); + return ret; + } + + ret = clk_enable(pltfm_host->clk); + if (ret) { + dev_err(dev, "Cannot enable SD clock.\n"); + return ret; + } + + ret = sdhci_resume_host(host); + if (ret) { + dev_err(dev, "Cannot resume host.\n"); + return ret; + } + + if (eswin_sdhci->has_cqe) + return cqhci_resume(host->mmc); + + return 0; +} +#endif /* ! CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(eswin_sdhci_dev_pm_ops, eswin_sdhci_suspend, + eswin_sdhci_resume); + +/** + * eswin_sdhci_sdcardclk_recalc_rate - Return the card clock rate + * + * @hw: Pointer to the hardware clock structure. + * @parent_rate: The parent rate (should be rate of clk_xin). + * + * Return the current actual rate of the SD card clock. This can be used + * to communicate with out PHY. + * + * Return: The card clock rate. + */ +static unsigned long +eswin_sdhci_sdcardclk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct eswin_sdhci_clk_data *clk_data = + container_of(hw, struct eswin_sdhci_clk_data, sdcardclk_hw); + struct eswin_sdhci_data *eswin_sdhci = + container_of(clk_data, struct eswin_sdhci_data, clk_data); + struct sdhci_host *host = eswin_sdhci->host; + + return host->mmc->actual_clock; +} + +static const struct clk_ops eswin_sdcardclk_ops = { + .recalc_rate = eswin_sdhci_sdcardclk_recalc_rate, +}; + +/** + * eswin_sdhci_sampleclk_recalc_rate - Return the sampling clock rate + * + * @hw: Pointer to the hardware clock structure. + * @parent_rate: The parent rate (should be rate of clk_xin). + * + * Return the current actual rate of the sampling clock. This can be used + * to communicate with out PHY. + * + * Return: The sample clock rate. + */ +static unsigned long +eswin_sdhci_sampleclk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct eswin_sdhci_clk_data *clk_data = + container_of(hw, struct eswin_sdhci_clk_data, sampleclk_hw); + struct eswin_sdhci_data *eswin_sdhci = + container_of(clk_data, struct eswin_sdhci_data, clk_data); + struct sdhci_host *host = eswin_sdhci->host; + + return host->mmc->actual_clock; +} + +static const struct clk_ops eswin_sampleclk_ops = { + .recalc_rate = eswin_sdhci_sampleclk_recalc_rate, +}; + +static const struct eswin_sdhci_clk_ops eswin_clk_ops = { + .sdcardclk_ops = &eswin_sdcardclk_ops, + .sampleclk_ops = &eswin_sampleclk_ops, +}; + +static struct eswin_sdhci_of_data eswin_sdhci_fu800_data = { + .pdata = &eswin_sdhci_cqe_pdata, + .clk_ops = &eswin_clk_ops, +}; + +static const struct of_device_id eswin_sdhci_of_match[] = { + { + .compatible = "eswin,emmc-sdhci-5.1", + .data = &eswin_sdhci_fu800_data, + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, eswin_sdhci_of_match); + +/** + * eswin_sdhci_register_sdcardclk - Register the sdcardclk for a PHY to use + * + * @eswin_sdhci: Our private data structure. + * @clk_xin: Pointer to the functional clock + * @dev: Pointer to our struct device. + * + * Some PHY devices need to know what the actual card clock is. In order for + * them to find out, we'll provide a clock through the common clock framework + * for them to query. + * + * Return: 0 on success and error value on error + */ +static int eswin_sdhci_register_sdcardclk(struct eswin_sdhci_data *eswin_sdhci, + struct clk *clk_xin, struct device *dev) +{ + struct eswin_sdhci_clk_data *clk_data = &eswin_sdhci->clk_data; + struct device_node *np = dev->of_node; + struct clk_init_data sdcardclk_init; + const char *parent_clk_name; + int ret; + + ret = of_property_read_string_index(np, "clock-output-names", 0, + &sdcardclk_init.name); + if (ret) { + dev_err(dev, "DT has #clock-cells but no clock-output-names\n"); + return ret; + } + + parent_clk_name = __clk_get_name(clk_xin); + sdcardclk_init.parent_names = &parent_clk_name; + sdcardclk_init.num_parents = 1; + sdcardclk_init.flags = CLK_GET_RATE_NOCACHE; + sdcardclk_init.ops = eswin_sdhci->clk_ops->sdcardclk_ops; + + clk_data->sdcardclk_hw.init = &sdcardclk_init; + clk_data->sdcardclk = devm_clk_register(dev, &clk_data->sdcardclk_hw); + if (IS_ERR(clk_data->sdcardclk)) + return PTR_ERR(clk_data->sdcardclk); + clk_data->sdcardclk_hw.init = NULL; + + ret = of_clk_add_provider(np, of_clk_src_simple_get, + clk_data->sdcardclk); + if (ret) + dev_err(dev, "Failed to add sdcard clock provider\n"); + + return ret; +} + +/** + * eswin_sdhci_register_sampleclk - Register the sampleclk for a PHY to use + * + * @eswin_sdhci: Our private data structure. + * @clk_xin: Pointer to the functional clock + * @dev: Pointer to our struct device. + * + * Some PHY devices need to know what the actual card clock is. In order for + * them to find out, we'll provide a clock through the common clock framework + * for them to query. + * + * Return: 0 on success and error value on error + */ +static int eswin_sdhci_register_sampleclk(struct eswin_sdhci_data *eswin_sdhci, + struct clk *clk_xin, struct device *dev) +{ + struct eswin_sdhci_clk_data *clk_data = &eswin_sdhci->clk_data; + struct device_node *np = dev->of_node; + struct clk_init_data sampleclk_init; + const char *parent_clk_name; + int ret; + + ret = of_property_read_string_index(np, "clock-output-names", 1, + &sampleclk_init.name); + if (ret) { + dev_err(dev, "DT has #clock-cells but no clock-output-names\n"); + return ret; + } + + parent_clk_name = __clk_get_name(clk_xin); + sampleclk_init.parent_names = &parent_clk_name; + sampleclk_init.num_parents = 1; + sampleclk_init.flags = CLK_GET_RATE_NOCACHE; + sampleclk_init.ops = eswin_sdhci->clk_ops->sampleclk_ops; + + clk_data->sampleclk_hw.init = &sampleclk_init; + clk_data->sampleclk = devm_clk_register(dev, &clk_data->sampleclk_hw); + if (IS_ERR(clk_data->sampleclk)) + return PTR_ERR(clk_data->sampleclk); + clk_data->sampleclk_hw.init = NULL; + + ret = of_clk_add_provider(np, of_clk_src_simple_get, + clk_data->sampleclk); + if (ret) + dev_err(dev, "Failed to add sample clock provider\n"); + + return ret; +} + +/** + * eswin_sdhci_unregister_sdclk - Undoes eswin_sdhci_register_sdclk() + * + * @dev: Pointer to our struct device. + * + * Should be called any time we're exiting and eswin_sdhci_register_sdclk() + * returned success. + */ +static void eswin_sdhci_unregister_sdclk(struct device *dev) +{ + struct device_node *np = dev->of_node; + + if (!of_find_property(np, "#clock-cells", NULL)) + return; + + of_clk_del_provider(dev->of_node); +} + +/** + * eswin_sdhci_register_sdclk - Register the sdcardclk for a PHY to use + * + * @eswin_sdhci: Our private data structure. + * @clk_xin: Pointer to the functional clock + * @dev: Pointer to our struct device. + * + * Some PHY devices need to know what the actual card clock is. In order for + * them to find out, we'll provide a clock through the common clock framework + * for them to query. + * + * Note: without seriously re-architecting SDHCI's clock code and testing on + * all platforms, there's no way to create a totally beautiful clock here + * with all clock ops implemented. Instead, we'll just create a clock that can + * be queried and set the CLK_GET_RATE_NOCACHE attribute to tell common clock + * framework that we're doing things behind its back. This should be sufficient + * to create nice clean device tree bindings and later (if needed) we can try + * re-architecting SDHCI if we see some benefit to it. + * + * Return: 0 on success and error value on error + */ +static int eswin_sdhci_register_sdclk(struct eswin_sdhci_data *eswin_sdhci, + struct clk *clk_xin, struct device *dev) +{ + struct device_node *np = dev->of_node; + u32 num_clks = 0; + int ret; + + /* Providing a clock to the PHY is optional; no error if missing */ + if (of_property_read_u32(np, "#clock-cells", &num_clks) < 0) + return 0; + + ret = eswin_sdhci_register_sdcardclk(eswin_sdhci, clk_xin, dev); + if (ret) + return ret; + + if (num_clks) { + ret = eswin_sdhci_register_sampleclk(eswin_sdhci, clk_xin, dev); + if (ret) { + eswin_sdhci_unregister_sdclk(dev); + return ret; + } + } + + return 0; +} + +static int eswin_sdhci_add_host(struct eswin_sdhci_data *eswin_sdhci) +{ + struct sdhci_host *host = eswin_sdhci->host; + struct cqhci_host *cq_host; + bool dma64; + int ret; + + if (!eswin_sdhci->has_cqe) + return sdhci_add_host(host); + + ret = sdhci_setup_host(host); + if (ret) + return ret; + + cq_host = devm_kzalloc(host->mmc->parent, sizeof(*cq_host), GFP_KERNEL); + if (!cq_host) { + ret = -ENOMEM; + goto cleanup; + } + + cq_host->mmio = host->ioaddr + eswin_sdhci_CQE_BASE_ADDR; + cq_host->ops = &eswin_sdhci_cqhci_ops; + + dma64 = host->flags & SDHCI_USE_64_BIT_DMA; + if (dma64) + cq_host->caps |= CQHCI_TASK_DESC_SZ_128; + + ret = cqhci_init(cq_host, host->mmc, dma64); + if (ret) + goto cleanup; + + ret = __sdhci_add_host(host); + if (ret) + goto cleanup; + + return 0; + +cleanup: + sdhci_cleanup_host(host); + return ret; +} + +static int eswin_emmc_sid_cfg(struct device *dev) +{ + int ret; + struct regmap *regmap; + int hsp_mmu_emmc_reg; + u32 rdwr_sid_ssid; + u32 sid; + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + + /* not behind smmu, use the default reset value(0x0) of the reg as streamID*/ + if (fwspec == NULL) { + dev_dbg(dev, + "dev is not behind smmu, skip configuration of sid\n"); + return 0; + } + sid = fwspec->ids[0]; + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, + "eswin,hsp_sp_csr"); + if (IS_ERR(regmap)) { + dev_dbg(dev, "No hsp_sp_csr phandle specified\n"); + return 0; + } + + ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 1, + &hsp_mmu_emmc_reg); + if (ret) { + dev_err(dev, "can't get emmc sid cfg reg offset (%d)\n", ret); + return ret; + } + + /* make the reading sid the same as writing sid, ssid is fixed to zero */ + rdwr_sid_ssid = FIELD_PREP(AWSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(AWSMMUSSID, 0); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSSID, 0); + regmap_write(regmap, hsp_mmu_emmc_reg, rdwr_sid_ssid); + + ret = eic7700_dynm_sid_enable(dev_to_node(dev)); + if (ret < 0) + dev_err(dev, "failed to config emmc streamID(%d)!\n", sid); + else + dev_dbg(dev, "success to config emmc streamID(%d)!\n", sid); + + return ret; +} + +static int eswin_sdhci_probe(struct platform_device *pdev) +{ + int ret; + struct clk *clk_xin; + struct sdhci_host *host; + struct sdhci_pltfm_host *pltfm_host; + struct device *dev = &pdev->dev; + struct eswin_sdhci_data *eswin_sdhci; + const struct eswin_sdhci_of_data *data; + struct regmap *regmap; + unsigned int val = 0; + + data = of_device_get_match_data(dev); + host = sdhci_pltfm_init(pdev, data->pdata, sizeof(*eswin_sdhci)); + if (IS_ERR(host)) + return PTR_ERR(host); + + pltfm_host = sdhci_priv(host); + eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + eswin_sdhci->host = host; + eswin_sdhci->clk_ops = data->clk_ops; + + eswin_sdhci->core_clk_reg = ioremap(ESWIN_EMMC_CORE_CLK_REG, 0x4); + if (!eswin_sdhci->core_clk_reg) { + dev_err(dev, "ioremap core clk reg failed.\n"); + goto err_pltfm_free; + } + + eswin_sdhci->clk_ahb = devm_clk_get(dev, "clk_ahb"); + if (IS_ERR(eswin_sdhci->clk_ahb)) { + ret = dev_err_probe(dev, PTR_ERR(eswin_sdhci->clk_ahb), + "clk_ahb clock not found.\n"); + goto err_pltfm_free; + } + + clk_xin = devm_clk_get(dev, "clk_xin"); + if (IS_ERR(clk_xin)) { + ret = dev_err_probe(dev, PTR_ERR(clk_xin), + "clk_xin clock not found.\n"); + goto err_pltfm_free; + } + + ret = clk_prepare_enable(eswin_sdhci->clk_ahb); + if (ret) { + dev_err(dev, "Unable to enable AHB clock.\n"); + goto err_pltfm_free; + } + + ret = clk_prepare_enable(clk_xin); + if (ret) { + dev_err(dev, "Unable to enable SD clock.\n"); + goto clk_dis_ahb; + } + + ret = eswin_sdhci_reset_init(dev, eswin_sdhci); + if (ret < 0) { + dev_err(dev, "failed to reset\n"); + goto clk_disable_all; + } + + eic7700_tbu_power(dev, true); + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, + "eswin,hsp_sp_csr"); + if (IS_ERR(regmap)) { + dev_dbg(dev, "No hsp_sp_csr phandle specified\n"); + goto clk_disable_all; + } + + regmap_write(regmap, SDHCI_EMMC0_INT_STATUS, MSHC_INT_CLK_STABLE); + regmap_write(regmap, SDHCI_EMMC0_PWR_CLEAR, MSHC_HOST_VAL_STABLE); + + /* smmu */ + eswin_emmc_sid_cfg(dev); + + if (!of_property_read_u32(dev->of_node, "delay_code", &val)) { + eswin_sdhci->phy.delay_code = val; + } + + if (!of_property_read_u32(dev->of_node, "drive-impedance-ohm", &val)) + eswin_sdhci->phy.drive_impedance = + eswin_convert_drive_impedance_ohm(pdev, val); + + if (of_property_read_bool(dev->of_node, "enable-cmd-pullup")) + eswin_sdhci->phy.enable_cmd_pullup = ENABLE; + else + eswin_sdhci->phy.enable_cmd_pullup = DISABLE; + + if (of_property_read_bool(dev->of_node, "enable-data-pullup")) + eswin_sdhci->phy.enable_data_pullup = ENABLE; + else + eswin_sdhci->phy.enable_data_pullup = DISABLE; + + if (of_property_read_bool(dev->of_node, "enable-strobe-pulldown")) + eswin_sdhci->phy.enable_strobe_pulldown = ENABLE; + else + eswin_sdhci->phy.enable_strobe_pulldown = DISABLE; + + sdhci_get_of_property(pdev); + + pltfm_host->clk = clk_xin; + + ret = eswin_sdhci_register_sdclk(eswin_sdhci, clk_xin, dev); + if (ret) + goto clk_disable_all; + + eswin_sdhci_dt_parse_clk_phases(dev, &eswin_sdhci->clk_data); + + ret = mmc_of_parse(host->mmc); + if (ret) { + ret = dev_err_probe(dev, ret, "parsing dt failed.\n"); + goto unreg_clk; + } + +#if !defined(__FPGA) && !defined(__ZEBU) + if (of_device_is_compatible(dev->of_node, "eswin,sdhci-5.1")) { + host->mmc_host_ops.hs400_enhanced_strobe = + eswin_sdhci_hs400_enhanced_strobe; + eswin_sdhci->has_cqe = true; + host->mmc->caps2 |= MMC_CAP2_CQE; + + if (!of_property_read_bool(dev->of_node, "disable-cqe-dcmd")) + host->mmc->caps2 |= MMC_CAP2_CQE_DCMD; + } +#endif + +#if !defined(__ADMA3_DISABLE) + sdhci_enable_v4_mode(eswin_sdhci->host); +#endif + + ret = eswin_sdhci_add_host(eswin_sdhci); + if (ret) + goto unreg_clk; + + return 0; + +unreg_clk: + eswin_sdhci_unregister_sdclk(dev); +clk_disable_all: + clk_disable_unprepare(clk_xin); +clk_dis_ahb: + clk_disable_unprepare(eswin_sdhci->clk_ahb); +err_pltfm_free: + if (eswin_sdhci->core_clk_reg) + iounmap(eswin_sdhci->core_clk_reg); + sdhci_pltfm_free(pdev); + return ret; +} + +static int eswin_sdhci_remove(struct platform_device *pdev) +{ + int ret; + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct eswin_sdhci_data *eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + struct clk *clk_ahb = eswin_sdhci->clk_ahb; + void __iomem *core_clk_reg = eswin_sdhci->core_clk_reg; + + sdhci_pltfm_remove(pdev); + eic7700_tbu_power(&pdev->dev, false); + + if (eswin_sdhci->txrx_rst) { + ret = reset_control_assert(eswin_sdhci->txrx_rst); + WARN_ON(0 != ret); + } + + if (eswin_sdhci->phy_rst) { + ret = reset_control_assert(eswin_sdhci->phy_rst); + WARN_ON(0 != ret); + } + + if (eswin_sdhci->prstn) { + ret = reset_control_assert(eswin_sdhci->prstn); + WARN_ON(0 != ret); + } + + if (eswin_sdhci->arstn) { + ret = reset_control_assert(eswin_sdhci->arstn); + WARN_ON(0 != ret); + } + eswin_sdhci_unregister_sdclk(&pdev->dev); + clk_disable_unprepare(clk_ahb); + iounmap(core_clk_reg); + + return 0; +} + +static void emmc_hard_reset(struct sdhci_host *host) +{ + unsigned int val; + + val = sdhci_readw(host, VENDOR_EMMC_CTRL_R); + val |= EMMC_RST_N_OE; + sdhci_writew(host, val, VENDOR_EMMC_CTRL_R); + val &= ~EMMC_RST_N; + sdhci_writew(host, val, VENDOR_EMMC_CTRL_R); + mdelay(20); + val |= EMMC_RST_N; + sdhci_writew(host, val, VENDOR_EMMC_CTRL_R); +} + +static void eswin_sdhci_shutdown(struct platform_device *pdev) +{ + struct sdhci_host *host = platform_get_drvdata(pdev); + + if (!host) + return; + + emmc_hard_reset(host); + host->ops->reset(host, SDHCI_RESET_ALL); + platform_set_drvdata(pdev, NULL); +} + +static struct platform_driver eswin_sdhci_driver = +{ + .driver = { + .name = "sdhci-eswin", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + .of_match_table = eswin_sdhci_of_match, + .pm = &eswin_sdhci_dev_pm_ops, + }, + .probe = eswin_sdhci_probe, + .remove = eswin_sdhci_remove, + .shutdown = eswin_sdhci_shutdown, +}; + +module_platform_driver(eswin_sdhci_driver); + +MODULE_DESCRIPTION("Driver for the ESWIN SDHCI Controller"); +MODULE_AUTHOR("liangshuang@eswin.com"); +MODULE_LICENSE("GPL v2"); From 29c7837f6d48e14532cef6171a1c5926d7340de9 Mon Sep 17 00:00:00 2001 From: huangyifeng Date: Tue, 30 Jul 2024 05:07:25 +0000 Subject: [PATCH 13/38] driver: reset: Add eswin reset driver Signed-off-by: huangyifeng Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/reset/Kconfig | 6 + drivers/reset/Makefile | 1 + drivers/reset/reset-eswin.c | 257 ++++++++++++++++++++++++++++++++++++ 3 files changed, 264 insertions(+) create mode 100755 drivers/reset/reset-eswin.c diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index ccd59ddd76100..f84d0a674eb71 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -66,6 +66,12 @@ config RESET_BRCMSTB_RESCAL This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on BCM7216. +config RESET_ESWIN_EIC7700 + tristate "Eswin EIC7700 Reset Driver" + default n + help + This enables the reset controller driver for Eswin EIC7700 SoCs. + config RESET_HSDK bool "Synopsys HSDK Reset Driver" depends on HAS_IOMEM diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 8270da8a4baa6..d4d4dfe96c65e 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o +obj-$(CONFIG_RESET_ESWIN_EIC7700) += reset-eswin.o obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o diff --git a/drivers/reset/reset-eswin.c b/drivers/reset/reset-eswin.c new file mode 100755 index 0000000000000..8bd01ac892039 --- /dev/null +++ b/drivers/reset/reset-eswin.c @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Reset 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 . + * + * Authors: HuangYiFeng + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SYSCRG_CLEAR_BOOT_INFO_OFFSET (0x30C) +#define CLEAR_BOOT_FLAG_BIT BIT_ULL(0) +#define SYSCRG_RESET_OFFSET (0x400) + +/** + * struct eswin_reset_data - reset controller information structure + * @rcdev: reset controller entity + * @dev: reset controller device pointer + * @idr: idr structure for mapping ids to reset control structures + */ +struct eswin_reset_data { + struct reset_controller_dev rcdev; + struct device *dev; + struct idr idr; + struct regmap *regmap; +}; + +/** + * struct eswin_reset_control - reset control structure + * @dev_id: SoC-specific device identifier + * @reset_bit: reset mask to use for toggling reset + */ +struct eswin_reset_control { + u32 dev_id; + u32 reset_bit; +}; + +#define to_eswin_reset_data(p) \ + container_of((p), struct eswin_reset_data, rcdev) + +/** + * eswin_reset_set() - program a device's reset + * @rcdev: reset controller entity + * @id: ID of the reset to toggle + * @assert: boolean flag to indicate assert or deassert + * + * This is a common internal function used to assert or deassert a device's + * reset by clear and set the reset bit. The device's reset is asserted if the + * @assert argument is true, or deasserted if @assert argument is false. + * + * Return: 0 for successful request, else a corresponding error value + */ +static int eswin_reset_set(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) +{ + struct eswin_reset_data *data = to_eswin_reset_data(rcdev); + struct eswin_reset_control *control; + int ret; + + control = idr_find(&data->idr, id); + + dev_dbg(rcdev->dev, "dev_id 0x%x reset_bit 0x%x assert 0x%x\r\n", + control->dev_id, control->reset_bit, assert); + + if (!control) + return -EINVAL; + + if (assert) { + ret = regmap_clear_bits(data->regmap, SYSCRG_RESET_OFFSET + control->dev_id * sizeof(u32), + control->reset_bit); + } else { + ret = regmap_set_bits(data->regmap, SYSCRG_RESET_OFFSET + control->dev_id * sizeof(u32), + control->reset_bit); + } + + return ret; +} + +static int eswin_reset_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + int ret; + + ret = eswin_reset_set(rcdev, id, true); + if (0 != ret) { + return ret; + } + usleep_range(10, 15); + ret = eswin_reset_set(rcdev, id, false); + if (0 != ret) { + return ret; + } + + return 0; +} + +static int eswin_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return eswin_reset_set(rcdev, id, true); +} + +static int eswin_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return eswin_reset_set(rcdev, id, false); +} + +static const struct reset_control_ops eswin_reset_ops = { + .reset = eswin_reset_reset, + .assert = eswin_reset_assert, + .deassert = eswin_reset_deassert, +}; + +static int eswin_reset_of_xlate_lookup_id(int id, void *p, void *data) +{ + struct of_phandle_args *reset_spec = (struct of_phandle_args *)data; + struct eswin_reset_control *slot_control = (struct eswin_reset_control *)p; + + if (reset_spec->args[0] == slot_control->dev_id + && reset_spec->args[1] == slot_control->reset_bit) { + return id; + } else { + return 0; + } +} + +/** + * eswin_reset_of_xlate() - translate a set of OF arguments to a reset ID + * @rcdev: reset controller entity + * @reset_spec: OF reset argument specifier + * + * This function performs the translation of the reset argument specifier + * values defined in a reset consumer device node. The function allocates a + * reset control structure for that device reset, and will be used by the + * driver for performing any reset functions on that reset. An idr structure + * is allocated and used to map to the reset control structure. This idr + * is used by the driver to do reset lookups. + * + * Return: 0 for successful request, else a corresponding error value + */ +static int eswin_reset_of_xlate(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) +{ + struct eswin_reset_data *data = to_eswin_reset_data(rcdev); + struct eswin_reset_control *control; + int ret; + + if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) + return -EINVAL; + + ret = idr_for_each(&data->idr, eswin_reset_of_xlate_lookup_id, (void *)reset_spec); + if (0 != ret) { + return ret; + } + + control = devm_kzalloc(data->dev, sizeof(*control), GFP_KERNEL); + if (!control) + return -ENOMEM; + + control->dev_id = reset_spec->args[0]; + control->reset_bit = reset_spec->args[1]; + + return idr_alloc(&data->idr, control, 0, 0, GFP_KERNEL); +} + +static const struct of_device_id eswin_reset_dt_ids[] = { + { .compatible = "eswin,eic7700-reset", }, + { /* sentinel */ }, +}; + +static int eswin_reset_probe(struct platform_device *pdev) +{ + struct eswin_reset_data *data; + struct device *parent; + + parent = pdev->dev.parent; + if (!parent) { + dev_err(&pdev->dev, "no parent\n"); + return -ENODEV; + } + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->regmap = syscon_node_to_regmap(parent->of_node); + if (IS_ERR(data->regmap)) { + dev_err(&pdev->dev, "failed to get parent regmap\n"); + return PTR_ERR(data->regmap); + } + + platform_set_drvdata(pdev, data); + + data->rcdev.owner = THIS_MODULE; + data->rcdev.ops = &eswin_reset_ops; + data->rcdev.of_node = pdev->dev.of_node; + data->rcdev.of_reset_n_cells = 2; + data->rcdev.of_xlate = eswin_reset_of_xlate; + data->rcdev.dev = &pdev->dev; + data->dev = &pdev->dev; + idr_init(&data->idr); + + /*clear boot flag so u84 and scpu could be reseted by software*/ + regmap_set_bits(data->regmap, SYSCRG_CLEAR_BOOT_INFO_OFFSET, CLEAR_BOOT_FLAG_BIT); + msleep(50); + + platform_set_drvdata(pdev, data); + + return devm_reset_controller_register(&pdev->dev, &data->rcdev); +} + +static int eswin_reset_remove(struct platform_device *pdev) +{ + struct eswin_reset_data *data = platform_get_drvdata(pdev); + + idr_destroy(&data->idr); + + return 0; +} + +static struct platform_driver eswin_reset_driver = { + .probe = eswin_reset_probe, + .remove = eswin_reset_remove, + .driver = { + .name = "eswin-reset", + .of_match_table = eswin_reset_dt_ids, + }, +}; + +static int __init eic7700_reset_init(void) +{ + return platform_driver_register(&eswin_reset_driver); +} +arch_initcall(eic7700_reset_init); From 68d29dfc718a90c8da1d9282570778a713cea9a2 Mon Sep 17 00:00:00 2001 From: ningyu Date: Tue, 30 Jul 2024 08:09:50 +0000 Subject: [PATCH 14/38] driver: PCIe: Add PCIe driver for EIC7700 Signed-off-by: ningyu Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/pci/controller/dwc/Kconfig | 8 + drivers/pci/controller/dwc/Makefile | 1 + drivers/pci/controller/dwc/pcie-eswin.c | 436 ++++++++++++++++++++++++ 3 files changed, 445 insertions(+) create mode 100644 drivers/pci/controller/dwc/pcie-eswin.c diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index ab96da43e0c2e..09f44434f8547 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -415,4 +415,12 @@ config PCIE_VISCONTI_HOST Say Y here if you want PCIe controller support on Toshiba Visconti SoC. This driver supports TMPV7708 SoC. +config PCIE_ESWIN + tristate "ESWIN PCIe host controller" + depends on PCI_MSI + depends on SOC_SIFIVE || COMPILE_TEST + select PCIE_DW_HOST + help + Say Y here if you want PCIe controller support for the ESWIN. + endmenu diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile index bf5c311875a1e..927459a28dc7e 100644 --- a/drivers/pci/controller/dwc/Makefile +++ b/drivers/pci/controller/dwc/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_PCIE_TEGRA194) += pcie-tegra194.o obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o obj-$(CONFIG_PCIE_UNIPHIER_EP) += pcie-uniphier-ep.o obj-$(CONFIG_PCIE_VISCONTI_HOST) += pcie-visconti.o +obj-$(CONFIG_PCIE_ESWIN) += pcie-eswin.o # The following drivers are for devices that use the generic ACPI # pci_root.c driver but don't support standard ECAM config access. diff --git a/drivers/pci/controller/dwc/pcie-eswin.c b/drivers/pci/controller/dwc/pcie-eswin.c new file mode 100644 index 0000000000000..6d142f2287d35 --- /dev/null +++ b/drivers/pci/controller/dwc/pcie-eswin.c @@ -0,0 +1,436 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN PCIe root complex 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 . + * + * Authors: Yu Ning + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pcie-designware.h" + +#define _writel_relaxed(v, p) writel_relaxed(v, p) +#define to_eswin_pcie(x) dev_get_drvdata((x)->dev) + +struct eswin_pcie { + struct dw_pcie pci; + void __iomem *mgmt_base; + struct gpio_desc *reset; + struct clk *pcie_aux; + struct clk *pcie_cfg; + struct clk *pcie_cr; + struct clk *pcie_aclk; + struct reset_control *powerup_rst; + struct reset_control *cfg_rst; + struct reset_control *perst; + int gen_x; + int lane_x; +}; + +#define PCIEMGMT_ACLK_CTRL 0x170 +#define PCIEMGMT_ACLK_CLKEN BIT(31) +#define PCIEMGMT_XTAL_SEL BIT(20) +#define PCIEMGMT_DIVSOR 0xf0 + +#define PCIEMGMT_CFG_CTRL 0x174 +#define PCIEMGMT_CFG_CLKEN BIT(31) +#define PCIEMGMT_AUX_CLKEN BIT(1) +#define PCIEMGMT_CR_CLKEN BIT(0) + +#define PCIEMGMT_RST_CTRL 0x420 +#define PCIEMGMT_PERST_N BIT(2) +#define PCIEMGMT_POWERUP_RST_N BIT(1) +#define PCIEMGMT_CFG_RST_N BIT(0) + +#define PCIE_PM_SEL_AUX_CLK BIT(16) + +#define PCIEMGMT_APP_HOLD_PHY_RST BIT(6) +#define PCIEMGMT_APP_LTSSM_ENABLE BIT(5) +#define PCIEMGMT_DEVICE_TYPE_MASK 0xf + +#define PCIEMGMT_LINKUP_STATE_VALIDATE ((0x11<<2)|0x3) +#define PCIEMGMT_LINKUP_STATE_MASK 0xff + +static void eswin_pcie_shutdown(struct platform_device *pdev) +{ + struct eswin_pcie *pcie = platform_get_drvdata(pdev); + + /* Bring down link, so bootloader gets clean state in case of reboot */ + reset_control_assert(pcie->perst); +} + +static int eswin_pcie_start_link(struct dw_pcie *pci) +{ + struct device *dev = pci->dev; + struct eswin_pcie *pcie = dev_get_drvdata(dev); + u32 val; + + /* Enable LTSSM */ + val = readl_relaxed(pcie->mgmt_base); + val |= PCIEMGMT_APP_LTSSM_ENABLE; + _writel_relaxed(val, pcie->mgmt_base); + return 0; +} + +static int eswin_pcie_link_up(struct dw_pcie *pci) +{ + struct device *dev = pci->dev; + struct eswin_pcie *pcie = dev_get_drvdata(dev); + u32 val; + + val = readl_relaxed(pcie->mgmt_base + 0x100); + if ((val & PCIEMGMT_LINKUP_STATE_MASK) == PCIEMGMT_LINKUP_STATE_VALIDATE) + return 1; + else + return 0; +} + +static int eswin_pcie_clk_enable(struct eswin_pcie *pcie) +{ + int ret; + + ret = clk_prepare_enable(pcie->pcie_cr); + if (ret) { + pr_err("PCIe: failed to enable cr clk: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(pcie->pcie_aclk); + if (ret) { + pr_err("PCIe: failed to enable aclk: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(pcie->pcie_cfg); + if (ret) { + pr_err("PCIe: failed to enable cfg_clk: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(pcie->pcie_aux); + if (ret) { + pr_err("PCIe: failed to enable aux_clk: %d\n", ret); + return ret; + } + + return 0; +} + +static int eswin_pcie_clk_disable(struct eswin_pcie *eswin_pcie) +{ + clk_disable_unprepare(eswin_pcie->pcie_aux); + clk_disable_unprepare(eswin_pcie->pcie_cfg); + clk_disable_unprepare(eswin_pcie->pcie_cr); + clk_disable_unprepare(eswin_pcie->pcie_aclk); + + return 0; +} + +static int eswin_pcie_power_on(struct eswin_pcie *pcie) +{ + int ret = 0; + + /* pciet_cfg_rstn */ + ret = reset_control_reset(pcie->cfg_rst); + WARN_ON(0 != ret); + + /* pciet_powerup_rstn */ + ret = reset_control_reset(pcie->powerup_rst); + WARN_ON(0 != ret); + + return ret; +} + +static int eswin_pcie_power_off(struct eswin_pcie *eswin_pcie) +{ + reset_control_assert(eswin_pcie->perst); + + reset_control_assert(eswin_pcie->powerup_rst); + + reset_control_assert(eswin_pcie->cfg_rst); + + return 0; +} + +/* TODO: Check socket gpio number in actual board and + * change if necessary + */ +int eswin_evb_socket_power_on(struct device *dev) +{ + int err_desc=0; + struct gpio_desc *gpio; + gpio = devm_gpiod_get(dev, "pci-socket", GPIOD_OUT_LOW); + err_desc = IS_ERR(gpio); + + if (err_desc) { + pr_err("No power control gpio found, maybe not needed\n"); + return 0; + } + + gpiod_set_value(gpio,1); + + return err_desc; +} + +static int eswin_pcie_host_init(struct dw_pcie_rp *pp) +{ + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct eswin_pcie *pcie = to_eswin_pcie(pci); + int ret; + u32 val; + + /* pciet_aux_clken, pcie_cfg_clken */ + ret = eswin_pcie_clk_enable(pcie); + if (ret) + return ret; + + ret = eswin_pcie_power_on(pcie); + if (ret) + return ret; + + ret = eic7700_tbu_power(pcie->pci.dev, true); + if (ret) + return ret; + + /* set device type : rc */ + val = readl_relaxed(pcie->mgmt_base); + val &= 0xfffffff0; + _writel_relaxed(val|0x4, pcie->mgmt_base); + + ret = reset_control_assert(pcie->perst); + WARN_ON(0 != ret); + + eswin_evb_socket_power_on(pcie->pci.dev); + msleep(100); + ret = reset_control_deassert(pcie->perst); + WARN_ON(0 != ret); + + /* app_hold_phy_rst */ + val = readl_relaxed(pcie->mgmt_base); + val &= ~(0x40); + _writel_relaxed(val, pcie->mgmt_base); + + /* wait pm_sel_aux_clk to 0 */ + while (1) { + val = readl_relaxed(pcie->mgmt_base + 0x100); + if (!(val & PCIE_PM_SEL_AUX_CLK)) { + break; + } + msleep(1); + } + + /* TODO: All hardcoded values such as register addresses and the values written to then + * to be replaced with macros. + */ + /* config eswin vendor id and EIC7700 device id */ + dw_pcie_writel_dbi(pci, 0, 0x20301fe1); + + if (pcie->gen_x == 3) { + /* GEN3 */ + dw_pcie_writel_dbi(pci, 0xa0, 0x00010003); + + /* LINK_CAPABILITIES_REG : PCIE_CAP_BASE + 0xc */ + val = dw_pcie_readl_dbi(pci, 0x7c); + val &= 0xfffffff0; + /* GEN3 */ + val |= 0x3; + dw_pcie_writel_dbi(pci, 0x7c, val); + } else if (pcie->gen_x == 2) { + /* GEN2 */ + dw_pcie_writel_dbi(pci, 0xa0, 0x00010002); + + /* LINK_CAPABILITIES_REG : PCIE_CAP_BASE + 0xc */ + val = dw_pcie_readl_dbi(pci, 0x7c); + val &= 0xfffffff0; + val |= 0x2; + dw_pcie_writel_dbi(pci, 0x7c, val); + }else { + /* GEN1 */ + dw_pcie_writel_dbi(pci, 0xa0, 0x00010001); + + /* LINK_CAPABILITIES_REG : PCIE_CAP_BASE + 0xc */ + val = dw_pcie_readl_dbi(pci, 0x7c); + val &= 0xfffffff0; + val |= 0x1; + dw_pcie_writel_dbi(pci, 0x7c, val); + } + + /* LINK_CAPABILITIES_REG : PCIE_CAP_BASE + 0xc : laneX */ + val = dw_pcie_readl_dbi(pci, 0x7c); + val &= 0xfffffc0f; + if (pcie->lane_x == 4) { + val |= 0x40; + } else if (pcie->lane_x == 2) { + val |= 0x20; + } else { + val |= 0x10; + } + + dw_pcie_writel_dbi(pci, 0x7c, val); + + /* lane fix config, real driver NOT need, default x4 */ + val = dw_pcie_readl_dbi(pci, 0x8c0); + val &= 0xffffff80; + if (pcie->lane_x == 4) { + val |= 0x44; + } else if (pcie->lane_x == 2) { + val |= 0x42; + } else { + val |= 0x41; + } + dw_pcie_writel_dbi(pci, 0x8c0, val); + + /* config msix table size to 0 in RC mode because our RC not support msix */ + val = dw_pcie_readl_dbi(pci, 0xb0); + val &= ~(0x7ff<<16); + dw_pcie_writel_dbi(pci, 0xb0, val); + + /* config support 32 msi vectors */ + dw_pcie_writel_dbi(pci, 0x50, 0x018a7005); + + return 0; +} + +static const struct dw_pcie_host_ops eswin_pcie_host_ops = { + .host_init = eswin_pcie_host_init, +}; + +static const struct dw_pcie_ops dw_pcie_ops = { + .start_link = eswin_pcie_start_link, + .link_up = eswin_pcie_link_up, +}; + +static int __exit eswin_pcie_remove(struct platform_device *pdev) +{ + struct eswin_pcie *pcie = platform_get_drvdata(pdev); + + dw_pcie_host_deinit(&pcie->pci.pp); + + eic7700_tbu_power(&pdev->dev, false); + eswin_pcie_power_off(pcie); + eswin_pcie_clk_disable(pcie); + + return 0; +} + +static int eswin_pcie_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct dw_pcie *pci; + struct eswin_pcie *pcie; + + pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); + if (!pcie) + return -ENOMEM; + pci = &pcie->pci; + pci->dev = dev; + pci->ops = &dw_pcie_ops; + pci->pp.ops = &eswin_pcie_host_ops; + + /* SiFive specific region: mgmt */ + pcie->mgmt_base = devm_platform_ioremap_resource_byname(pdev, "mgmt"); + if (IS_ERR(pcie->mgmt_base)) + return PTR_ERR(pcie->mgmt_base); + + /* Fetch clocks */ + pcie->pcie_aux = devm_clk_get(dev, "pcie_aux_clk"); + if (IS_ERR(pcie->pcie_aux)) { + dev_err(dev, "pcie_aux clock source missing or invalid\n"); + return PTR_ERR(pcie->pcie_aux); + } + + pcie->pcie_cfg = devm_clk_get(dev, "pcie_cfg_clk"); + if (IS_ERR(pcie->pcie_cfg)) { + dev_err(dev, "pcie_cfg_clk clock source missing or invalid\n"); + return PTR_ERR(pcie->pcie_cfg); + } + + pcie->pcie_cr = devm_clk_get(dev, "pcie_cr_clk"); + if (IS_ERR(pcie->pcie_cr)) { + dev_err(dev, "pcie_cr_clk clock source missing or invalid\n"); + return PTR_ERR(pcie->pcie_cr); + } + + pcie->pcie_aclk = devm_clk_get(dev, "pcie_aclk"); + if (IS_ERR(pcie->pcie_aclk)) { + dev_err(dev, "pcie_aclk clock source missing or invalid\n"); + return PTR_ERR(pcie->pcie_aclk); + } + + /* Fetch reset */ + pcie->powerup_rst = devm_reset_control_get_optional(&pdev->dev, "pcie_powerup"); + if (IS_ERR_OR_NULL(pcie->powerup_rst)) { + dev_err_probe(dev, PTR_ERR(pcie->powerup_rst), "unable to get powerup reset\n"); + } + + pcie->cfg_rst = devm_reset_control_get_optional(&pdev->dev, "pcie_cfg"); + if (IS_ERR_OR_NULL(pcie->cfg_rst)) { + dev_err_probe(dev, PTR_ERR(pcie->cfg_rst), "unable to get cfg reset\n"); + } + + pcie->perst = devm_reset_control_get_optional(&pdev->dev, "pcie_pwren"); + if (IS_ERR_OR_NULL(pcie->perst)) { + dev_err_probe(dev, PTR_ERR(pcie->perst), "unable to get perst\n"); + } + + device_property_read_u32(&pdev->dev, "gen-x", &pcie->gen_x); + device_property_read_u32(&pdev->dev, "lane-x", &pcie->lane_x); + + platform_set_drvdata(pdev, pcie); + + return dw_pcie_host_init(&pci->pp); +} + +static const struct of_device_id eswin_pcie_of_match[] = { + { .compatible = "eswin,eic7700-pcie", }, + {}, +}; + +static struct platform_driver eswin_pcie_driver = { + .driver = { + .name = "eswin-pcie", + .of_match_table = eswin_pcie_of_match, + .suppress_bind_attrs = true, + }, + .probe = eswin_pcie_probe, + .remove = __exit_p(eswin_pcie_remove), + .shutdown = eswin_pcie_shutdown, +}; + +module_platform_driver(eswin_pcie_driver); + +MODULE_DEVICE_TABLE(of, eswin_pcie_of_match); +MODULE_DESCRIPTION("PCIe host controller driver for ESWIN EIC77xx SoCs"); +MODULE_AUTHOR("Ning Yu "); +MODULE_LICENSE("GPL v2"); From 3b9e9a92a969e4a6e6e4dd3e42c174aa3a49b92b Mon Sep 17 00:00:00 2001 From: luyulin Date: Tue, 30 Jul 2024 09:22:56 +0000 Subject: [PATCH 15/38] driver: pinctrl: Add pincontrol driver for EIC7700 Signed-off-by: luyulin Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/pinctrl/Kconfig | 10 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-eic7700.c | 1360 +++++++++++++++++++++++++++++ 3 files changed, 1371 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-eic7700.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 7dfb7190580ef..fc0f01e31bcc4 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -195,6 +195,16 @@ config PINCTRL_EQUILIBRIUM desired pin functions, configure GPIO attributes for LGM SoC pins. Pin muxing and pin config settings are retrieved from device tree. +config PINCTRL_EIC7700 + tristate "EIC7700 PINCTRL driver" + select GENERIC_PINCONF + select PINMUX + select PINCONF + select GENERIC_PINCTRL_GROUPS + select GENERIC_PINMUX_FUNCTIONS + help + say Y here to add pinctrl eic7700 driver + config PINCTRL_GEMINI bool depends on ARCH_GEMINI diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index dd6cda2702949..3e51b32bd1613 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o obj-$(CONFIG_PINCTRL_DA9062) += pinctrl-da9062.o obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o obj-$(CONFIG_PINCTRL_EQUILIBRIUM) += pinctrl-equilibrium.o +obj-$(CONFIG_PINCTRL_EIC7700) += pinctrl-eic7700.o obj-$(CONFIG_PINCTRL_GEMINI) += pinctrl-gemini.o obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o obj-$(CONFIG_PINCTRL_K210) += pinctrl-k210.o diff --git a/drivers/pinctrl/pinctrl-eic7700.c b/drivers/pinctrl/pinctrl-eic7700.c new file mode 100644 index 0000000000000..8db8b8d1877aa --- /dev/null +++ b/drivers/pinctrl/pinctrl-eic7700.c @@ -0,0 +1,1360 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Pinctrl Controller Platform Device 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 . + * + * Authors: Yulin Lu + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pinctrl-utils.h" +#include "core.h" + +#define ESWIN_MIO_NUM 164 + +#define ESWIN_PINCONF_IE BIT(0) +#define ESWIN_PINCONF_PULLUP BIT(1) +#define ESWIN_PINCONF_PULLDOWN BIT(2) +#define ESWIN_PINCONF_DRIVER_STRENGTH_MASK 0xf // 0111 1000 +#define ESWIN_PINCONF_DRIVER_SHIFT 3 +#define ESWIN_PINCONF_SMT BIT(7) + +struct eswin_function_desc { + const char *name; + const char * const *groups; + int ngroups; + u32 mux_val; + u32 mux_mask; +}; + +struct eswin_group_desc{ + const char *name; + const unsigned int *pins; + const unsigned int npins; + +}; + +struct eswin_pinctrl { + struct pinctrl_dev *pctrl; + void __iomem *base; + const struct eswin_group_desc *groups; + unsigned int ngroups; + const struct eswin_function_desc *funcs; + unsigned int nfuncs; +}; + +static const struct pinctrl_pin_desc eswin_pins[] = { + + PINCTRL_PIN(0, "CHIP_MODE"), + PINCTRL_PIN(1, "MODE_SET0"), + PINCTRL_PIN(2, "MODE_SET1"), + PINCTRL_PIN(3, "MODE_SET2"), + PINCTRL_PIN(4, "MODE_SET3"), + PINCTRL_PIN(5, "XIN"), + PINCTRL_PIN(6, "RTC_XIN"), + PINCTRL_PIN(7, "RST_OUT_N"), + PINCTRL_PIN(8,"KEY_RESET_N"), + PINCTRL_PIN(9,"RST_IN_N"), + PINCTRL_PIN(10,"POR_IN_N"), + PINCTRL_PIN(11,"POR_OUT_N"), + PINCTRL_PIN(12,"GPIO0"), + PINCTRL_PIN(13,"POR_SEL"), + PINCTRL_PIN(14,"JTAG0_TCK"), + PINCTRL_PIN(15,"JTAG0_TMS"), + PINCTRL_PIN(16,"JTAG0_TDI"), + PINCTRL_PIN(17,"JTAG0_TDO"), + PINCTRL_PIN(18,"JTAG0_TRST"), + PINCTRL_PIN(19,"SPI2_CS0_N"), + PINCTRL_PIN(20,"JTAG1_TCK"), + PINCTRL_PIN(21,"JTAG1_TMS"), + PINCTRL_PIN(22,"JTAG1_TDI"), + PINCTRL_PIN(23,"JTAG1_TDO"), + PINCTRL_PIN(24,"JTAG1_TRST"), + PINCTRL_PIN(25,"SPI2_CS1_N"), + PINCTRL_PIN(26,"PCIE_CLKREQ_N"), + PINCTRL_PIN(27,"PCIE_WAKE_N"), + PINCTRL_PIN(28,"PCIE_PERST_N"), + PINCTRL_PIN(29,"HDMI_SCL"), + PINCTRL_PIN(30,"HDMI_SDA"), + PINCTRL_PIN(31,"HDMI_CEC"), + PINCTRL_PIN(32,"JTAG2_TRST"), + PINCTRL_PIN(33,"RGMII0_CLK_125"), + PINCTRL_PIN(34,"RGMII0_TXEN"), + PINCTRL_PIN(35,"RGMII0_TXCLK"), + PINCTRL_PIN(36,"RGMII0_TXD0"), + PINCTRL_PIN(37,"RGMII0_TXD1"), + PINCTRL_PIN(38,"RGMII0_TXD2"), + PINCTRL_PIN(39,"RGMII0_TXD3"), + PINCTRL_PIN(40,"I2S0_BCLK"), + PINCTRL_PIN(41,"I2S0_WCLK"), + PINCTRL_PIN(42,"I2S0_SDI"), + PINCTRL_PIN(43,"I2S0_SDO"), + PINCTRL_PIN(44,"I2S_MCLK"), + PINCTRL_PIN(45,"RGMII0_RXCLK"), + PINCTRL_PIN(46,"RGMII0_RXDV"), + PINCTRL_PIN(47,"RGMII0_RXD0"), + PINCTRL_PIN(48,"RGMII0_RXD1"), + PINCTRL_PIN(49,"RGMII0_RXD2"), + PINCTRL_PIN(50,"RGMII0_RXD3"), + PINCTRL_PIN(51,"I2S2_BCLK"), + PINCTRL_PIN(52,"I2S2_WCLK"), + PINCTRL_PIN(53,"I2S2_SDI"), + PINCTRL_PIN(54,"I2S2_SDO"), + PINCTRL_PIN(55,"GPIO27"), + PINCTRL_PIN(56,"GPIO28"), + PINCTRL_PIN(57,"GPIO29"), + PINCTRL_PIN(58,"RGMII0_MDC"), + PINCTRL_PIN(59,"RGMII0_MDIO"), + PINCTRL_PIN(60,"RGMII0_INTB"), + PINCTRL_PIN(61,"RGMII1_CLK_125"), + PINCTRL_PIN(62,"RGMII1_TXEN"), + PINCTRL_PIN(63,"RGMII1_TXCLK"), + PINCTRL_PIN(64,"RGMII1_TXD0"), + PINCTRL_PIN(65,"RGMII1_TXD1"), + PINCTRL_PIN(66,"RGMII1_TXD2"), + PINCTRL_PIN(67,"RGMII1_TXD3"), + PINCTRL_PIN(68,"I2S1_BCLK"), + PINCTRL_PIN(69,"I2S1_WCLK"), + PINCTRL_PIN(70,"I2S1_SDI"), + PINCTRL_PIN(71,"I2S1_SDO"), + PINCTRL_PIN(72,"GPIO34"), + PINCTRL_PIN(73,"RGMII1_RXCLK"), + PINCTRL_PIN(74,"RGMII1_RXDV"), + PINCTRL_PIN(75,"RGMII1_RXD0"), + PINCTRL_PIN(76,"RGMII1_RXD1"), + PINCTRL_PIN(77,"RGMII1_RXD2"), + PINCTRL_PIN(78,"RGMII1_RXD3"), + PINCTRL_PIN(79,"SPI1_CS0_N"), + PINCTRL_PIN(80,"SPI1_CLK"), + PINCTRL_PIN(81,"SPI1_D0"), + PINCTRL_PIN(82,"SPI1_D1"), + PINCTRL_PIN(83,"SPI1_D2"), + PINCTRL_PIN(84,"SPI1_D3"), + PINCTRL_PIN(85,"SPI1_CS1_N"), + PINCTRL_PIN(86,"RGMII1_MDC"), + PINCTRL_PIN(87,"RGMII1_MDIO"), + PINCTRL_PIN(88,"RGMII1_INTB"), + PINCTRL_PIN(89,"USB0_PWREN"), + PINCTRL_PIN(90,"USB1_PWREN"), + PINCTRL_PIN(91,"I2C0_SCL"), + PINCTRL_PIN(92,"I2C0_SDA"), + PINCTRL_PIN(93,"I2C1_SCL"), + PINCTRL_PIN(94,"I2C1_SDA"), + PINCTRL_PIN(95,"I2C2_SCL"), + PINCTRL_PIN(96,"I2C2_SDA"), + PINCTRL_PIN(97,"I2C3_SCL"), + PINCTRL_PIN(98,"I2C3_SDA"), + PINCTRL_PIN(99,"I2C4_SCL"), + PINCTRL_PIN(100,"I2C4_SDA"), + PINCTRL_PIN(101,"I2C5_SCL"), + PINCTRL_PIN(102,"I2C5_SDA"), + PINCTRL_PIN(103,"UART0_TX"), + PINCTRL_PIN(104,"UART0_RX"), + PINCTRL_PIN(105,"UART1_TX"), + PINCTRL_PIN(106,"UART1_RX"), + PINCTRL_PIN(107,"UART1_CTS"), + PINCTRL_PIN(108,"UART1_RTS"), + PINCTRL_PIN(109,"UART2_TX"), + PINCTRL_PIN(110,"UART2_RX"), + PINCTRL_PIN(111,"JTAG2_TCK"), + PINCTRL_PIN(112,"JTAG2_TMS"), + PINCTRL_PIN(113,"JTAG2_TDI"), + PINCTRL_PIN(114,"JTAG2_TDO"), + PINCTRL_PIN(115,"FAN_PWM"), + PINCTRL_PIN(116,"FAN_TACH"), + PINCTRL_PIN(117,"MIPI_CSI0_XVS"), + PINCTRL_PIN(118,"MIPI_CSI0_XHS"), + PINCTRL_PIN(119,"MIPI_CSI0_MCLK"), + PINCTRL_PIN(120,"MIPI_CSI1_XVS"), + PINCTRL_PIN(121,"MIPI_CSI1_XHS"), + PINCTRL_PIN(122,"MIPI_CSI1_MCLK"), + PINCTRL_PIN(123,"MIPI_CSI2_XVS"), + PINCTRL_PIN(124,"MIPI_CSI2_XHS"), + PINCTRL_PIN(125,"MIPI_CSI2_MCLK"), + PINCTRL_PIN(126,"MIPI_CSI3_XVS"), + PINCTRL_PIN(127,"MIPI_CSI3_XHS"), + PINCTRL_PIN(128,"MIPI_CSI3_MCLK"), + PINCTRL_PIN(129,"MIPI_CSI4_XVS"), + PINCTRL_PIN(130,"MIPI_CSI4_XHS"), + PINCTRL_PIN(131,"MIPI_CSI4_MCLK"), + PINCTRL_PIN(132,"MIPI_CSI5_XVS"), + PINCTRL_PIN(133,"MIPI_CSI5_XHS"), + PINCTRL_PIN(134,"MIPI_CSI5_MCLK"), + PINCTRL_PIN(135,"SPI3_CS_N"), + PINCTRL_PIN(136,"SPI3_CLK"), + PINCTRL_PIN(137,"SPI3_DI"), + PINCTRL_PIN(138,"SPI3_DO"), + PINCTRL_PIN(139,"GPIO92"), + PINCTRL_PIN(140,"GPIO93"), + PINCTRL_PIN(141,"S_MODE"), + PINCTRL_PIN(142,"GPIO95"), + PINCTRL_PIN(143,"SPI0_CS_N"), + PINCTRL_PIN(144,"SPI0_CLK"), + PINCTRL_PIN(145,"SPI0_D0"), + PINCTRL_PIN(146,"SPI0_D1"), + PINCTRL_PIN(147,"SPI0_D2"), + PINCTRL_PIN(148,"SPI0_D3"), + PINCTRL_PIN(149,"I2C10_SCL"), + PINCTRL_PIN(150,"I2C10_SDA"), + PINCTRL_PIN(151,"I2C11_SCL"), + PINCTRL_PIN(152,"I2C11_SDA"), + PINCTRL_PIN(153,"GPIO106"), + PINCTRL_PIN(154,"BOOT_SEL0"), + PINCTRL_PIN(155,"BOOT_SEL1"), + PINCTRL_PIN(156,"BOOT_SEL2"), + PINCTRL_PIN(157,"BOOT_SEL3"), + PINCTRL_PIN(158,"GPIO111"), + PINCTRL_PIN(159,"D2D_SERDES_STATUS_IN"), + PINCTRL_PIN(160,"D2D_SERDES_STATUS_OUT"), + PINCTRL_PIN(161,"LPDDR_REF_CLK"), + +}; + +#define ESWIN_PINCTRL_GRP(_name) \ + { \ + .name = #_name "_group", \ + .pins = _name ## _pins, \ + .npins = ARRAY_SIZE(_name ## _pins), \ + } + +//func0 +static const char * const sdio0_group[] = {"sdio0_group"}; +static const char * const sdio1_group[] = {"sdio1_group"}; +static const char * const por_sel_group[] = {"por_sel_group"}; +static const char * const jtag0_group[] = {"jtag0_group"}; +static const char * const jtag1_group[] = {"jtag1_group"}; +static const char * const spi2_cs_group[] = {"spi2_cs_group"}; +static const char * const pcie_group[] = {"pcie_group"}; +static const char * const hdmi_group[] = {"hdmi_group"}; +static const char * const jtag2_group[] = {"jtag2_group"}; +static const char * const rgmii0_group[] = {"rgmii0_group"}; +static const char * const i2s0_group[] = {"i2s0_group"}; +static const char * const i2s1_group[] = {"i2s1_group"}; +static const char * const i2s2_group[] = {"i2s2_group"}; +static const char * const por_time_sel0_group[] = {"por_time_sel0_group"}; +static const char * const por_time_sel1_group[] = {"por_time_sel1_group"}; +static const char * const rgmii1_group[] = {"rgmii1_group"}; +static const char * const spi1_group[] = {"spi1_group"}; +static const char * const usb0_pwren_group[] = {"usb0_pwren_group"}; +static const char * const usb1_pwren_group[] = {"usb1_pwren_group"}; +static const char * const i2c0_group[] = {"i2c0_group"}; +static const char * const i2c1_group[] = {"i2c1_group"}; +static const char * const i2c2_group[] = {"i2c2_group"}; +static const char * const i2c3_group[] = {"i2c3_group"}; +static const char * const i2c4_group[] = {"i2c4_group"}; +static const char * const i2c5_group[] = {"i2c5_group"}; +static const char * const uart0_group[] = {"uart0_group"}; +static const char * const uart1_group[] = {"uart1_group"}; +static const char * const uart2_group[] = {"uart2_group"}; + +static const char * const pwm0_group[] = {"pwm0_group"}; +static const char * const fan_tach_group[] = {"fan_tach_group"}; +static const char * const mipi_csi0_group[] = {"mipi_csi0_group"}; +static const char * const mipi_csi1_group[] = {"mipi_csi1_group"}; +static const char * const mipi_csi2_group[] = {"mipi_csi2_group"}; +static const char * const mipi_csi3_group[] = {"mipi_csi3_group"}; +static const char * const mipi_csi4_group[] = {"mipi_csi4_group"}; +static const char * const mipi_csi5_group[] = {"mipi_csi5_group"}; +static const char * const spi3_group[] = {"spi3_group"}; +static const char * const i2c8_group[] = {"i2c8_group"}; +static const char * const s_mode_group[] = {"s_mode_group"}; +static const char * const pinmux_ddr_refclk_sel_group[] = {"pinmux_ddr_refclk_sel_group"}; +static const char * const spi0_group[] = {"spi0_group"}; +static const char * const i2c10_group[] = {"i2c10_group"}; +static const char * const i2c11_group[] = {"i2c11_group"}; +static const char * const boot_sel_group[] = {"boot_sel_group"}; +static const char * const lpddr_ref_clk_group[] = {"lpddr_ref_clk_group"}; + +//func1 +static const char * const spi2_clk_group[] = {"spi2_clk_group"}; +static const char * const spi2_d0_group[] = {"spi2_d0_group"}; +static const char * const spi2_d1_d2_d3_group[] = {"spi2_d1_d2_d3_group"}; + +static const char * const sata_act_led_group[] = {"sata_act_led_group"}; +static const char * const emmc_led_control_group[] = {"emmc_led_control_group"}; +static const char * const sd0_led_control_group[] = {"sd0_led_control_group"}; +static const char * const i2c9_group[] = {"i2c9_group"}; +static const char * const sd1_led_control_group[] = {"sd1_led_control_group"}; +static const char * const pwm1_group[] = {"pwm1_group"}; +static const char * const pwm2_group[] = {"pwm2_group"}; +static const char * const i2c6_group[] = {"i2c6_group"}; +static const char * const i2c7_group[] = {"i2c7_group"}; +static const char * const mipi_csi_xtrig_group[] = {"mipi_csi_xtrig_group"}; + +//gpio +static const char * const gpio0_group[] = {"gpio0_group"}; +static const char * const gpio1_group[] = {"gpio1_group"}; +static const char * const gpio2_group[] = {"gpio2_group"}; +static const char * const gpio3_group[] = {"gpio3_group"}; +static const char * const gpio4_group[] = {"gpio4_group"}; +static const char * const gpio5_group[] = {"gpio5_group"}; +static const char * const gpio6_group[] = {"gpio6_group"}; +static const char * const gpio7_group[] = {"gpio7_group"}; +static const char * const gpio8_group[] = {"gpio8_group"}; +static const char * const gpio9_group[] = {"gpio9_group"}; +static const char * const gpio10_group[] = {"gpio10_group"}; +static const char * const gpio11_group[] = {"gpio11_group"}; +static const char * const gpio12_group[] = {"gpio12_group"}; +static const char * const gpio13_group[] = {"gpio13_group"}; +static const char * const gpio14_group[] = {"gpio14_group"}; +static const char * const gpio15_group[] = {"gpio15_group"}; +static const char * const gpio16_group[] = {"gpio16_group"}; +static const char * const gpio17_group[] = {"gpio17_group"}; +static const char * const gpio18_group[] = {"gpio18_group"}; +static const char * const gpio19_group[] = {"gpio19_group"}; +static const char * const gpio20_group[] = {"gpio20_group"}; +static const char * const gpio21_group[] = {"gpio21_group"}; +static const char * const gpio22_group[] = {"gpio22_group"}; +static const char * const gpio23_group[] = {"gpio23_group"}; +static const char * const gpio24_group[] = {"gpio24_group"}; +static const char * const gpio25_group[] = {"gpio25_group"}; +static const char * const gpio26_group[] = {"gpio26_group"}; +static const char * const gpio27_group[] = {"gpio27_group"}; +static const char * const gpio28_group[] = {"gpio28_group"}; +static const char * const gpio29_group[] = {"gpio29_group"}; +static const char * const gpio30_group[] = {"gpio30_group"}; +static const char * const gpio31_group[] = {"gpio31_group"}; +static const char * const gpio32_group[] = {"gpio32_group"}; +static const char * const gpio33_group[] = {"gpio33_group"}; +static const char * const gpio34_group[] = {"gpio34_group"}; +static const char * const gpio35_group[] = {"gpio35_group"}; +static const char * const gpio36_group[] = {"gpio36_group"}; +static const char * const gpio37_group[] = {"gpio37_group"}; +static const char * const gpio38_group[] = {"gpio38_group"}; +static const char * const gpio39_group[] = {"gpio39_group"}; +static const char * const gpio40_group[] = {"gpio40_group"}; +static const char * const gpio41_group[] = {"gpio41_group"}; +static const char * const gpio42_group[] = {"gpio42_group"}; +static const char * const gpio43_group[] = {"gpio43_group"}; +static const char * const gpio44_group[] = {"gpio44_group"}; +static const char * const gpio45_group[] = {"gpio45_group"}; +static const char * const gpio46_group[] = {"gpio46_group"}; +static const char * const gpio47_group[] = {"gpio47_group"}; +static const char * const gpio48_group[] = {"gpio48_group"}; +static const char * const gpio49_group[] = {"gpio49_group"}; + +static const char * const gpio50_group[] = {"gpio50_group"}; +static const char * const gpio51_group[] = {"gpio51_group"}; +static const char * const gpio52_group[] = {"gpio52_group"}; +static const char * const gpio53_group[] = {"gpio53_group"}; +static const char * const gpio54_group[] = {"gpio54_group"}; +static const char * const gpio55_group[] = {"gpio55_group"}; +static const char * const gpio56_group[] = {"gpio56_group"}; +static const char * const gpio57_group[] = {"gpio57_group"}; +static const char * const gpio58_group[] = {"gpio58_group"}; +static const char * const gpio59_group[] = {"gpio59_group"}; + +static const char * const gpio60_group[] = {"gpio60_group"}; +static const char * const gpio61_group[] = {"gpio61_group"}; +static const char * const gpio62_group[] = {"gpio62_group"}; +static const char * const gpio63_group[] = {"gpio63_group"}; +static const char * const gpio64_group[] = {"gpio64_group"}; +static const char * const gpio65_group[] = {"gpio65_group"}; +static const char * const gpio66_group[] = {"gpio66_group"}; +static const char * const gpio67_group[] = {"gpio67_group"}; +static const char * const gpio68_group[] = {"gpio68_group"}; +static const char * const gpio69_group[] = {"gpio69_group"}; + +static const char * const gpio70_group[] = {"gpio70_group"}; +static const char * const gpio71_group[] = {"gpio71_group"}; +static const char * const gpio72_group[] = {"gpio72_group"}; +static const char * const gpio73_group[] = {"gpio73_group"}; +static const char * const gpio74_group[] = {"gpio74_group"}; +static const char * const gpio75_group[] = {"gpio75_group"}; +static const char * const gpio76_group[] = {"gpio76_group"}; +static const char * const gpio77_group[] = {"gpio77_group"}; +static const char * const gpio78_group[] = {"gpio78_group"}; +static const char * const gpio79_group[] = {"gpio79_group"}; + +static const char * const gpio80_group[] = {"gpio80_group"}; +static const char * const gpio81_group[] = {"gpio81_group"}; +static const char * const gpio82_group[] = {"gpio82_group"}; +static const char * const gpio83_group[] = {"gpio83_group"}; +static const char * const gpio84_group[] = {"gpio84_group"}; +static const char * const gpio85_group[] = {"gpio85_group"}; +static const char * const gpio86_group[] = {"gpio86_group"}; +static const char * const gpio87_group[] = {"gpio87_group"}; +static const char * const gpio88_group[] = {"gpio88_group"}; +static const char * const gpio89_group[] = {"gpio89_group"}; + +static const char * const gpio90_group[] = {"gpio90_group"}; +static const char * const gpio91_group[] = {"gpio91_group"}; +static const char * const gpio92_group[] = {"gpio92_group"}; +static const char * const gpio93_group[] = {"gpio93_group"}; +static const char * const gpio94_group[] = {"gpio94_group"}; +static const char * const gpio95_group[] = {"gpio95_group"}; +static const char * const gpio96_group[] = {"gpio96_group"}; +static const char * const gpio97_group[] = {"gpio97_group"}; +static const char * const gpio98_group[] = {"gpio98_group"}; +static const char * const gpio99_group[] = {"gpio99_group"}; + +static const char * const gpio100_group[] = {"gpio100_group"}; +static const char * const gpio101_group[] = {"gpio101_group"}; +static const char * const gpio102_group[] = {"gpio102_group"}; +static const char * const gpio103_group[] = {"gpio103_group"}; +static const char * const gpio104_group[] = {"gpio104_group"}; +static const char * const gpio105_group[] = {"gpio105_group"}; +static const char * const gpio106_group[] = {"gpio106_group"}; +static const char * const gpio107_group[] = {"gpio107_group"}; +static const char * const gpio108_group[] = {"gpio108_group"}; +static const char * const gpio109_group[] = {"gpio109_group"}; +static const char * const gpio110_group[] = {"gpio110_group"}; +static const char * const gpio111_group[] = {"gpio111_group"}; + +//func3 +static const char * const uart4_group[] = {"uart4_group"}; +static const char * const uart3_group[] = {"uart3_group"}; + +//func6 +static const char * const csi_mon_out_group[] = {"csi_mon_out_group"}; +static const char * const csi_ocla_clk_group[] = {"csi_ocla_clk_group"}; +static const char * const csi_mon_out_valid_group[] = {"csi_mon_out_valid_group"}; +static const char * const csi_parity_error_group[] = {"csi_parity_error_group"}; +static const char * const csi_dtb_out_group[] = {"csi_dtb_out_group"}; +static const char * const csi_phy_sel_group[] = {"csi_phy_sel_group"}; +static const char * const vc_g2d0_debug_out_group[] = {"vc_g2d0_debug_out_group"}; +static const char * const vc_g2d1_debug_out_group[] = {"vc_g2d1_debug_out_group"}; +static const char * const sata_mpll_clk_group[] = {"sata_mpll_clk_group"}; +static const char * const sata_ref_repeat_clk_m_group[] = {"sata_ref_repeat_clk_m_group"}; +static const char * const sata_ref_repeat_clk_p_group[] = {"sata_ref_repeat_clk_p_group"}; + +//func0 +static const unsigned int sdio0_pins[] = {1,2}; +static const unsigned int sdio1_pins[] = {3,4}; +static const unsigned int por_sel_pins[] = {13}; +static const unsigned int jtag0_pins[] = {14,15,16,17}; +static const unsigned int jtag1_pins[] = {20,21,22,23}; +static const unsigned int spi2_cs_pins[] = {19,25}; +static const unsigned int pcie_pins[] = {26,27,28}; +static const unsigned int hdmi_pins[] = {29,30,31}; +static const unsigned int jtag2_pins[] = {32,111,112,113,114}; +static const unsigned int rgmii0_pins[] = {33,34,35,36,37,38,39,45,46,47,48,49,50,58,59,60}; +static const unsigned int i2s0_pins[] = {40,41,42,43,44}; +static const unsigned int i2s1_pins[] = {68,69,70,71,44}; +static const unsigned int i2s2_pins[] = {51,52,53,54,44}; +static const unsigned int por_time_sel0_pins[] = {57}; +static const unsigned int por_time_sel1_pins[] = {72}; +static const unsigned int rgmii1_pins[] = {61,62,63,64,65,66,67,73,74,75,76,77,78,86,87,88}; +static const unsigned int spi1_pins[] = {79,80,81,82,83,84,85}; +static const unsigned int usb0_pwren_pins[] = {89}; +static const unsigned int usb1_pwren_pins[] = {90}; +static const unsigned int i2c0_pins[] = {91,92}; +static const unsigned int i2c1_pins[] = {93,94}; +static const unsigned int i2c2_pins[] = {95,96}; +static const unsigned int i2c3_pins[] = {97,98}; +static const unsigned int i2c4_pins[] = {99,100}; +static const unsigned int i2c5_pins[] = {101,102}; +static const unsigned int uart0_pins[] = {103,104}; +static const unsigned int uart1_pins[] = {105,106,107,108}; +static const unsigned int uart2_pins[] = {109,110}; +static const unsigned int pwm0_pins[] = {115}; +static const unsigned int fan_tach_pins[] = {116}; +static const unsigned int mipi_csi0_pins[] = {117,118,119}; +static const unsigned int mipi_csi1_pins[] = {120,121,122}; +static const unsigned int mipi_csi2_pins[] = {123,124,125}; +static const unsigned int mipi_csi3_pins[] = {126,127,128}; +static const unsigned int mipi_csi4_pins[] = {129,130,131}; +static const unsigned int mipi_csi5_pins[] = {132,133,134}; +static const unsigned int spi3_pins[] = {135,136,137,138}; +static const unsigned int i2c8_pins[] = {139,140}; +static const unsigned int s_mode_pins[] = {141}; +static const unsigned int pinmux_ddr_refclk_sel_pins[] = {142}; +static const unsigned int spi0_pins[] = {143,144,145,146,147,148}; +static const unsigned int i2c10_pins[] = {149,150}; +static const unsigned int i2c11_pins[] = {151,152}; +static const unsigned int boot_sel_pins[] = {154,155,156,157}; +static const unsigned int lpddr_ref_clk_pins[] = {158}; + +//func1 +static const unsigned int spi2_clk_pins[] = {14}; +static const unsigned int spi2_d0_pins[] = {15}; +static const unsigned int spi2_d1_d2_d3_pins[] = {16,17,18}; + +static const unsigned int sata_act_led_pins[] = {55}; +static const unsigned int emmc_led_control_pins[] = {57}; +static const unsigned int sd0_led_control_pins[] = {72}; +static const unsigned int i2c9_pins[] = {81,82}; +static const unsigned int sd1_led_control_pins[] = {83}; +static const unsigned int pwm1_pins[] = {84}; +static const unsigned int pwm2_pins[] = {85}; +static const unsigned int i2c6_pins[] = {107,108}; +static const unsigned int i2c7_pins[] = {109,110}; +static const unsigned int mipi_csi_xtrig_pins[] = {139,140}; + +//gpio +static const unsigned int gpio0_pins[] = {12}; +static const unsigned int gpio1_pins[] = {14}; +static const unsigned int gpio2_pins[] = {15}; +static const unsigned int gpio3_pins[] = {16}; +static const unsigned int gpio4_pins[] = {17}; +static const unsigned int gpio5_pins[] = {18}; +static const unsigned int gpio6_pins[] = {19}; +static const unsigned int gpio7_pins[] = {20}; +static const unsigned int gpio8_pins[] = {21}; +static const unsigned int gpio9_pins[] = {22}; + +static const unsigned int gpio10_pins[] = {23}; +static const unsigned int gpio11_pins[] = {24}; +static const unsigned int gpio12_pins[] = {25}; +static const unsigned int gpio13_pins[] = {1}; +static const unsigned int gpio14_pins[] = {2}; +static const unsigned int gpio15_pins[] = {3}; +static const unsigned int gpio16_pins[] = {4}; +static const unsigned int gpio17_pins[] = {32}; +static const unsigned int gpio18_pins[] = {40}; +static const unsigned int gpio19_pins[] = {41}; + +static const unsigned int gpio20_pins[] = {42}; +static const unsigned int gpio21_pins[] = {43}; +static const unsigned int gpio22_pins[] = {44}; +static const unsigned int gpio23_pins[] = {51}; +static const unsigned int gpio24_pins[] = {52}; +static const unsigned int gpio25_pins[] = {53}; +static const unsigned int gpio26_pins[] = {54}; +static const unsigned int gpio27_pins[] = {55}; +static const unsigned int gpio28_pins[] = {56}; +static const unsigned int gpio29_pins[] = {57}; + +static const unsigned int gpio30_pins[] = {68}; +static const unsigned int gpio31_pins[] = {69}; +static const unsigned int gpio32_pins[] = {70}; +static const unsigned int gpio33_pins[] = {71}; +static const unsigned int gpio34_pins[] = {72}; +static const unsigned int gpio35_pins[] = {79}; +static const unsigned int gpio36_pins[] = {80}; +static const unsigned int gpio37_pins[] = {81}; +static const unsigned int gpio38_pins[] = {82}; +static const unsigned int gpio39_pins[] = {83}; + +static const unsigned int gpio40_pins[] = {84}; +static const unsigned int gpio41_pins[] = {85}; +static const unsigned int gpio42_pins[] = {89}; +static const unsigned int gpio43_pins[] = {90}; +static const unsigned int gpio44_pins[] = {91}; +static const unsigned int gpio45_pins[] = {92}; +static const unsigned int gpio46_pins[] = {93}; +static const unsigned int gpio47_pins[] = {94}; +static const unsigned int gpio48_pins[] = {95}; +static const unsigned int gpio49_pins[] = {96}; + +static const unsigned int gpio50_pins[] = {97}; +static const unsigned int gpio51_pins[] = {98}; +static const unsigned int gpio52_pins[] = {99}; +static const unsigned int gpio53_pins[] = {100}; +static const unsigned int gpio54_pins[] = {101}; +static const unsigned int gpio55_pins[] = {102}; +static const unsigned int gpio56_pins[] = {103}; +static const unsigned int gpio57_pins[] = {104}; +static const unsigned int gpio58_pins[] = {105}; +static const unsigned int gpio59_pins[] = {106}; + +static const unsigned int gpio60_pins[] = {107}; +static const unsigned int gpio61_pins[] = {108}; +static const unsigned int gpio62_pins[] = {109}; +static const unsigned int gpio63_pins[] = {110}; +static const unsigned int gpio64_pins[] = {111}; +static const unsigned int gpio65_pins[] = {112}; +static const unsigned int gpio66_pins[] = {113}; +static const unsigned int gpio67_pins[] = {114}; +static const unsigned int gpio68_pins[] = {115}; +static const unsigned int gpio69_pins[] = {116}; + +static const unsigned int gpio70_pins[] = {117}; +static const unsigned int gpio71_pins[] = {118}; +static const unsigned int gpio72_pins[] = {119}; +static const unsigned int gpio73_pins[] = {120}; +static const unsigned int gpio74_pins[] = {121}; +static const unsigned int gpio75_pins[] = {122}; +static const unsigned int gpio76_pins[] = {123}; +static const unsigned int gpio77_pins[] = {124}; +static const unsigned int gpio78_pins[] = {125}; +static const unsigned int gpio79_pins[] = {126}; + +static const unsigned int gpio80_pins[] = {127}; +static const unsigned int gpio81_pins[] = {128}; +static const unsigned int gpio82_pins[] = {129}; +static const unsigned int gpio83_pins[] = {130}; +static const unsigned int gpio84_pins[] = {131}; +static const unsigned int gpio85_pins[] = {132}; +static const unsigned int gpio86_pins[] = {133}; +static const unsigned int gpio87_pins[] = {134}; +static const unsigned int gpio88_pins[] = {135}; +static const unsigned int gpio89_pins[] = {136}; + +static const unsigned int gpio90_pins[] = {137}; +static const unsigned int gpio91_pins[] = {138}; +static const unsigned int gpio92_pins[] = {139}; +static const unsigned int gpio93_pins[] = {140}; +static const unsigned int gpio94_pins[] = {141}; +static const unsigned int gpio95_pins[] = {142}; +static const unsigned int gpio96_pins[] = {143}; +static const unsigned int gpio97_pins[] = {144}; +static const unsigned int gpio98_pins[] = {145}; +static const unsigned int gpio99_pins[] = {146}; + +static const unsigned int gpio100_pins[] = {147}; +static const unsigned int gpio101_pins[] = {148}; +static const unsigned int gpio102_pins[] = {149}; +static const unsigned int gpio103_pins[] = {150}; +static const unsigned int gpio104_pins[] = {151}; +static const unsigned int gpio105_pins[] = {152}; +static const unsigned int gpio106_pins[] = {153}; +static const unsigned int gpio107_pins[] = {154}; +static const unsigned int gpio108_pins[] = {155}; +static const unsigned int gpio109_pins[] = {156}; +static const unsigned int gpio110_pins[] = {157}; +static const unsigned int gpio111_pins[] = {158}; + +//func3 +static const unsigned int uart4_pins[] = {81,82}; +static const unsigned int uart3_pins[] = {139,140}; + +//func6 +static const unsigned int csi_mon_out_pins[] = {32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55}; +static const unsigned int csi_ocla_clk_pins[] = {96}; +static const unsigned int csi_mon_out_valid_pins[] = {97}; +static const unsigned int csi_parity_error_pins[] = {98}; +static const unsigned int csi_dtb_out_pins[] = {99,100,101,102,129,130,131,132}; +static const unsigned int csi_phy_sel_pins[] = {133,134,109}; +static const unsigned int vc_g2d0_debug_out_pins[] = {110,111,112,113,114,115,116,117}; +static const unsigned int vc_g2d1_debug_out_pins[] = {118,119,120,121,122,123,124,125}; +static const unsigned int sata_mpll_clk_pins[] = {126}; +static const unsigned int sata_ref_repeat_clk_m_pins[] = {127}; +static const unsigned int sata_ref_repeat_clk_p_pins[] = {128}; + +static const struct eswin_group_desc eswin_pinctrl_groups[] = +{ + //func0 + ESWIN_PINCTRL_GRP(sdio0), + ESWIN_PINCTRL_GRP(sdio1), + ESWIN_PINCTRL_GRP(por_sel), + ESWIN_PINCTRL_GRP(jtag0), + ESWIN_PINCTRL_GRP(jtag1), + ESWIN_PINCTRL_GRP(spi2_cs), + ESWIN_PINCTRL_GRP(pcie), + ESWIN_PINCTRL_GRP(hdmi), + ESWIN_PINCTRL_GRP(jtag2), + ESWIN_PINCTRL_GRP(rgmii0), + ESWIN_PINCTRL_GRP(i2s0), + ESWIN_PINCTRL_GRP(i2s1), + ESWIN_PINCTRL_GRP(i2s2), + ESWIN_PINCTRL_GRP(por_time_sel0), + ESWIN_PINCTRL_GRP(por_time_sel1), + ESWIN_PINCTRL_GRP(rgmii1), + ESWIN_PINCTRL_GRP(spi1), + ESWIN_PINCTRL_GRP(usb0_pwren), + ESWIN_PINCTRL_GRP(usb1_pwren), + ESWIN_PINCTRL_GRP(i2c0), + ESWIN_PINCTRL_GRP(i2c1), + ESWIN_PINCTRL_GRP(i2c2), + ESWIN_PINCTRL_GRP(i2c3), + ESWIN_PINCTRL_GRP(i2c4), + ESWIN_PINCTRL_GRP(i2c5), + ESWIN_PINCTRL_GRP(uart0), + ESWIN_PINCTRL_GRP(uart1), + ESWIN_PINCTRL_GRP(uart2), + ESWIN_PINCTRL_GRP(pwm0), + ESWIN_PINCTRL_GRP(fan_tach), + ESWIN_PINCTRL_GRP(mipi_csi0), + ESWIN_PINCTRL_GRP(mipi_csi1), + ESWIN_PINCTRL_GRP(mipi_csi2), + ESWIN_PINCTRL_GRP(mipi_csi3), + ESWIN_PINCTRL_GRP(mipi_csi4), + ESWIN_PINCTRL_GRP(mipi_csi5), + ESWIN_PINCTRL_GRP(spi3), + ESWIN_PINCTRL_GRP(i2c8), + ESWIN_PINCTRL_GRP(s_mode), + ESWIN_PINCTRL_GRP(pinmux_ddr_refclk_sel), + ESWIN_PINCTRL_GRP(spi0), + ESWIN_PINCTRL_GRP(i2c10), + ESWIN_PINCTRL_GRP(i2c11), + ESWIN_PINCTRL_GRP(boot_sel), + ESWIN_PINCTRL_GRP(lpddr_ref_clk), + + //func1 + ESWIN_PINCTRL_GRP(spi2_clk), + ESWIN_PINCTRL_GRP(spi2_d0), + ESWIN_PINCTRL_GRP(spi2_d1_d2_d3), + + ESWIN_PINCTRL_GRP(sata_act_led), + ESWIN_PINCTRL_GRP(emmc_led_control), + ESWIN_PINCTRL_GRP(sd0_led_control), + ESWIN_PINCTRL_GRP(i2c9), + ESWIN_PINCTRL_GRP(sd1_led_control), + ESWIN_PINCTRL_GRP(pwm1), + ESWIN_PINCTRL_GRP(pwm2), + ESWIN_PINCTRL_GRP(i2c6), + ESWIN_PINCTRL_GRP(i2c7), + ESWIN_PINCTRL_GRP(mipi_csi_xtrig), + + //gpio + ESWIN_PINCTRL_GRP(gpio0), + ESWIN_PINCTRL_GRP(gpio1), + ESWIN_PINCTRL_GRP(gpio2), + ESWIN_PINCTRL_GRP(gpio3), + ESWIN_PINCTRL_GRP(gpio4), + ESWIN_PINCTRL_GRP(gpio5), + ESWIN_PINCTRL_GRP(gpio6), + ESWIN_PINCTRL_GRP(gpio7), + ESWIN_PINCTRL_GRP(gpio8), + ESWIN_PINCTRL_GRP(gpio9), + ESWIN_PINCTRL_GRP(gpio10), + ESWIN_PINCTRL_GRP(gpio11), + ESWIN_PINCTRL_GRP(gpio12), + ESWIN_PINCTRL_GRP(gpio13), + ESWIN_PINCTRL_GRP(gpio14), + ESWIN_PINCTRL_GRP(gpio15), + ESWIN_PINCTRL_GRP(gpio16), + ESWIN_PINCTRL_GRP(gpio17), + ESWIN_PINCTRL_GRP(gpio18), + ESWIN_PINCTRL_GRP(gpio19), + ESWIN_PINCTRL_GRP(gpio20), + ESWIN_PINCTRL_GRP(gpio21), + ESWIN_PINCTRL_GRP(gpio22), + ESWIN_PINCTRL_GRP(gpio23), + ESWIN_PINCTRL_GRP(gpio24), + ESWIN_PINCTRL_GRP(gpio25), + ESWIN_PINCTRL_GRP(gpio26), + ESWIN_PINCTRL_GRP(gpio27), + ESWIN_PINCTRL_GRP(gpio28), + ESWIN_PINCTRL_GRP(gpio29), + ESWIN_PINCTRL_GRP(gpio30), + ESWIN_PINCTRL_GRP(gpio31), + ESWIN_PINCTRL_GRP(gpio32), + ESWIN_PINCTRL_GRP(gpio33), + ESWIN_PINCTRL_GRP(gpio34), + ESWIN_PINCTRL_GRP(gpio35), + ESWIN_PINCTRL_GRP(gpio36), + ESWIN_PINCTRL_GRP(gpio37), + ESWIN_PINCTRL_GRP(gpio38), + ESWIN_PINCTRL_GRP(gpio39), + ESWIN_PINCTRL_GRP(gpio40), + ESWIN_PINCTRL_GRP(gpio41), + ESWIN_PINCTRL_GRP(gpio42), + ESWIN_PINCTRL_GRP(gpio43), + ESWIN_PINCTRL_GRP(gpio44), + ESWIN_PINCTRL_GRP(gpio45), + ESWIN_PINCTRL_GRP(gpio46), + ESWIN_PINCTRL_GRP(gpio47), + ESWIN_PINCTRL_GRP(gpio48), + ESWIN_PINCTRL_GRP(gpio49), + + ESWIN_PINCTRL_GRP(gpio50), + ESWIN_PINCTRL_GRP(gpio51), + ESWIN_PINCTRL_GRP(gpio52), + ESWIN_PINCTRL_GRP(gpio53), + ESWIN_PINCTRL_GRP(gpio54), + ESWIN_PINCTRL_GRP(gpio55), + ESWIN_PINCTRL_GRP(gpio56), + ESWIN_PINCTRL_GRP(gpio57), + ESWIN_PINCTRL_GRP(gpio58), + ESWIN_PINCTRL_GRP(gpio59), + + ESWIN_PINCTRL_GRP(gpio60), + ESWIN_PINCTRL_GRP(gpio61), + ESWIN_PINCTRL_GRP(gpio62), + ESWIN_PINCTRL_GRP(gpio63), + ESWIN_PINCTRL_GRP(gpio64), + ESWIN_PINCTRL_GRP(gpio65), + ESWIN_PINCTRL_GRP(gpio66), + ESWIN_PINCTRL_GRP(gpio67), + ESWIN_PINCTRL_GRP(gpio68), + ESWIN_PINCTRL_GRP(gpio69), + + ESWIN_PINCTRL_GRP(gpio70), + ESWIN_PINCTRL_GRP(gpio71), + ESWIN_PINCTRL_GRP(gpio72), + ESWIN_PINCTRL_GRP(gpio73), + ESWIN_PINCTRL_GRP(gpio74), + ESWIN_PINCTRL_GRP(gpio75), + ESWIN_PINCTRL_GRP(gpio76), + ESWIN_PINCTRL_GRP(gpio77), + ESWIN_PINCTRL_GRP(gpio78), + ESWIN_PINCTRL_GRP(gpio79), + + ESWIN_PINCTRL_GRP(gpio80), + ESWIN_PINCTRL_GRP(gpio81), + ESWIN_PINCTRL_GRP(gpio82), + ESWIN_PINCTRL_GRP(gpio83), + ESWIN_PINCTRL_GRP(gpio84), + ESWIN_PINCTRL_GRP(gpio85), + ESWIN_PINCTRL_GRP(gpio86), + ESWIN_PINCTRL_GRP(gpio87), + ESWIN_PINCTRL_GRP(gpio88), + ESWIN_PINCTRL_GRP(gpio89), + + ESWIN_PINCTRL_GRP(gpio90), + ESWIN_PINCTRL_GRP(gpio91), + ESWIN_PINCTRL_GRP(gpio92), + ESWIN_PINCTRL_GRP(gpio93), + ESWIN_PINCTRL_GRP(gpio94), + ESWIN_PINCTRL_GRP(gpio95), + ESWIN_PINCTRL_GRP(gpio96), + ESWIN_PINCTRL_GRP(gpio97), + ESWIN_PINCTRL_GRP(gpio98), + ESWIN_PINCTRL_GRP(gpio99), + + ESWIN_PINCTRL_GRP(gpio100), + ESWIN_PINCTRL_GRP(gpio101), + ESWIN_PINCTRL_GRP(gpio102), + ESWIN_PINCTRL_GRP(gpio103), + ESWIN_PINCTRL_GRP(gpio104), + ESWIN_PINCTRL_GRP(gpio105), + ESWIN_PINCTRL_GRP(gpio106), + ESWIN_PINCTRL_GRP(gpio107), + ESWIN_PINCTRL_GRP(gpio108), + ESWIN_PINCTRL_GRP(gpio109), + ESWIN_PINCTRL_GRP(gpio110), + ESWIN_PINCTRL_GRP(gpio111), + + //func3 + ESWIN_PINCTRL_GRP(uart4), + ESWIN_PINCTRL_GRP(uart3), + + //func6 + ESWIN_PINCTRL_GRP(csi_mon_out), + ESWIN_PINCTRL_GRP(csi_ocla_clk), + ESWIN_PINCTRL_GRP(csi_mon_out_valid), + ESWIN_PINCTRL_GRP(csi_parity_error), + ESWIN_PINCTRL_GRP(csi_dtb_out), + ESWIN_PINCTRL_GRP(csi_phy_sel), + ESWIN_PINCTRL_GRP(vc_g2d0_debug_out), + ESWIN_PINCTRL_GRP(vc_g2d1_debug_out), + ESWIN_PINCTRL_GRP(sata_mpll_clk), + ESWIN_PINCTRL_GRP(sata_ref_repeat_clk_m), + ESWIN_PINCTRL_GRP(sata_ref_repeat_clk_p), +}; + +#define ESWIN_PINMUX_FUNCTION(_func_name, _mux_val, _mask)\ + { \ + .name = #_func_name"_func", \ + .groups = _func_name##_group, \ + .ngroups = ARRAY_SIZE(_func_name##_group), \ + .mux_val = _mux_val, \ + .mux_mask = _mask, \ + } + +#define ESWIN_PINMUX_SHIFT 16 +#define ESWIN_PINMUX_MASK (0x07 << ESWIN_PINMUX_SHIFT) + +static const struct eswin_function_desc eswin_pinmux_functions[] = { + + //func0 + ESWIN_PINMUX_FUNCTION(sdio0, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(sdio1, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(por_sel, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(jtag0, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(jtag1, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(spi2_cs, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(pcie, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(hdmi, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(jtag2, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(rgmii0, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2s0, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2s1, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2s2, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(por_time_sel0, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(por_time_sel1, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(rgmii1, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(spi1, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(usb0_pwren, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(usb1_pwren, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c0, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c1, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c2, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c3, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c4, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c5, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(uart0, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(uart1, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(uart2, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(pwm0, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(fan_tach, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(mipi_csi0, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(mipi_csi1, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(mipi_csi2, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(mipi_csi3, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(mipi_csi4, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(mipi_csi5, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(spi3, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c8, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(s_mode, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(pinmux_ddr_refclk_sel, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(spi0, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c10, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c11, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(boot_sel, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(lpddr_ref_clk, 0, ESWIN_PINMUX_MASK), + + //func1 + ESWIN_PINMUX_FUNCTION(spi2_clk, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(spi2_d0, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(spi2_d1_d2_d3, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(sata_act_led, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(emmc_led_control, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(sd0_led_control, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c9, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(sd1_led_control, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(pwm1, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(pwm2, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c6, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(i2c7, 1, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(mipi_csi_xtrig, 1, ESWIN_PINMUX_MASK), + + //gpio + ESWIN_PINMUX_FUNCTION(gpio0, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio1, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio2, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio3, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio4, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio5, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio6, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio7, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio8, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio9, 2, ESWIN_PINMUX_MASK), + + ESWIN_PINMUX_FUNCTION(gpio10, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio11, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio12, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio13, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio14, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio15, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio16, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio17, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio18, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio19, 2, ESWIN_PINMUX_MASK), + + ESWIN_PINMUX_FUNCTION(gpio20, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio21, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio22, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio23, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio24, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio25, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio26, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio27, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio28, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio29, 2, ESWIN_PINMUX_MASK), + + ESWIN_PINMUX_FUNCTION(gpio30, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio31, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio32, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio33, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio34, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio35, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio36, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio37, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio38, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio39, 2, ESWIN_PINMUX_MASK), + + ESWIN_PINMUX_FUNCTION(gpio40, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio41, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio42, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio43, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio44, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio45, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio46, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio47, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio48, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio49, 2, ESWIN_PINMUX_MASK), + + ESWIN_PINMUX_FUNCTION(gpio50, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio51, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio52, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio53, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio54, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio55, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio56, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio57, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio58, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio59, 2, ESWIN_PINMUX_MASK), + + ESWIN_PINMUX_FUNCTION(gpio60, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio61, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio62, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio63, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio64, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio65, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio66, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio67, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio68, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio69, 2, ESWIN_PINMUX_MASK), + + ESWIN_PINMUX_FUNCTION(gpio70, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio71, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio72, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio73, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio74, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio75, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio76, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio77, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio78, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio79, 2, ESWIN_PINMUX_MASK), + + ESWIN_PINMUX_FUNCTION(gpio80, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio81, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio82, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio83, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio84, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio85, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio86, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio87, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio88, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio89, 2, ESWIN_PINMUX_MASK), + + ESWIN_PINMUX_FUNCTION(gpio90, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio91, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio92, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio93, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio94, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio95, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio96, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio97, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio98, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio99, 2, ESWIN_PINMUX_MASK), + + ESWIN_PINMUX_FUNCTION(gpio100, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio101, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio102, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio103, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio104, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio105, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio106, 0, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio107, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio108, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio109, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio110, 2, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(gpio111, 0, ESWIN_PINMUX_MASK), + + //func3 + ESWIN_PINMUX_FUNCTION(uart4, 3, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(uart3, 3, ESWIN_PINMUX_MASK), + + //func6 + ESWIN_PINMUX_FUNCTION(csi_mon_out, 6, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(csi_ocla_clk, 6, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(csi_mon_out_valid, 6, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(csi_parity_error, 6, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(csi_dtb_out, 6, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(csi_phy_sel, 6, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(vc_g2d0_debug_out, 6, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(vc_g2d1_debug_out, 6, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(sata_mpll_clk, 6, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(sata_ref_repeat_clk_m, 6, ESWIN_PINMUX_MASK), + ESWIN_PINMUX_FUNCTION(sata_ref_repeat_clk_p, 6, ESWIN_PINMUX_MASK), +}; + +/* pinctrl */ +static int eswin_pctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct eswin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + return pctrl->ngroups; +} + +static const char *eswin_pctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct eswin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + return pctrl->groups[selector].name; +} + +static int eswin_pctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + struct eswin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + *pins = pctrl->groups[selector].pins; + *num_pins = pctrl->groups[selector].npins; + return 0; +} + +static const struct pinctrl_ops eswin_pinctrl_ops = { + .get_groups_count = eswin_pctrl_get_groups_count, + .get_group_name = eswin_pctrl_get_group_name, + .get_group_pins = eswin_pctrl_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinctrl_utils_free_map, +}; + +/* pinmux */ +static int eswin_pmux_get_functions_count(struct pinctrl_dev *pctldev) +{ + struct eswin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->nfuncs; +} + +static const char *eswin_pmux_get_function_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct eswin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->funcs[selector].name; +} + +static int eswin_pmux_get_function_groups(struct pinctrl_dev *pctldev, + unsigned int selector, + const char * const **groups, + unsigned * const num_groups) +{ + struct eswin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + *groups = pctrl->funcs[selector].groups; + *num_groups = pctrl->funcs[selector].ngroups; + return 0; +} + +static int eswin_pinmux_set_mux(struct pinctrl_dev *pctldev, + unsigned int function, + unsigned int group) +{ + int i ; + struct eswin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct eswin_group_desc *pgrp = &pctrl->groups[group]; + const struct eswin_function_desc *func = &pctrl->funcs[function]; + + for(i = 0 ;i< pgrp->npins;i++){ + u32 reg ; + unsigned int pin = pgrp->pins[i]; + reg = readl(pctrl->base + 4*pin); + reg &= ~ESWIN_PINMUX_MASK; + reg |= (func->mux_val << ESWIN_PINMUX_SHIFT); + writel(reg,pctrl->base + 4*pin); + } + return 0; +} + +static const struct pinmux_ops eswin_pinmux_ops = { + .get_functions_count = eswin_pmux_get_functions_count, + .get_function_name = eswin_pmux_get_function_name, + .get_function_groups = eswin_pmux_get_function_groups, + .set_mux = eswin_pinmux_set_mux, +}; + +/* pinconfig */ +static int eswin_pinconf_cfg_get(struct pinctrl_dev *pctldev, + unsigned pin, + unsigned long *config) +{ + u32 reg=0; + int ret=0; + unsigned int arg = 0; + unsigned int param = pinconf_to_config_param(*config); + struct eswin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + if (pin >= ESWIN_MIO_NUM){ + return -ENOTSUPP; + } + reg = readl(pctrl->base + 4*pin); + if (ret) + return -EIO; + + switch (param) { + case PIN_CONFIG_BIAS_PULL_UP: + if (!(arg=(reg & ESWIN_PINCONF_PULLUP))){ + return -EINVAL;} + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + if (!(arg = (reg & ESWIN_PINCONF_PULLDOWN))){ + return -EINVAL;} + break; + case PIN_CONFIG_DRIVE_STRENGTH: + arg = (reg & (ESWIN_PINCONF_DRIVER_STRENGTH_MASK + <= ESWIN_MIO_NUM) + return -ENOTSUPP; + reg = readl(pctrl->base + 4*pin); + + if (ret) + return -EIO; + + for (i = 0; i < num_configs; i++) { + unsigned int param = pinconf_to_config_param(configs[i]); + unsigned int arg = pinconf_to_config_argument(configs[i]); + + switch (param) { + case PIN_CONFIG_INPUT_ENABLE: + reg &=~ESWIN_PINCONF_IE; + reg |= (arg<<0); + break; + case PIN_CONFIG_BIAS_PULL_UP: + reg &=~ESWIN_PINCONF_PULLUP; + reg |= (arg<<1); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + reg &=~ESWIN_PINCONF_PULLDOWN; + reg |= (arg<<2); + break; + case PIN_CONFIG_DRIVE_STRENGTH: + reg &= ~(ESWIN_PINCONF_DRIVER_STRENGTH_MASK<<3); + reg |= (arg<<3); + break; + case PIN_CONFIG_INPUT_SCHMITT: + reg &= ~ESWIN_PINCONF_SMT; + reg |= (arg<<7); + break; + default: + dev_warn(pctldev->dev, + "unsupported configuration parameter '%u'\n", + param); + continue; + } + + + } + writel(reg,pctrl->base + 4*pin); + + if (ret) + return -EIO; + return 0; +} + +static int eswin_pinconf_group_set(struct pinctrl_dev *pctldev, + unsigned selector, + unsigned long *configs, + unsigned num_configs) + +{ + int i=0, ret=0; + struct eswin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct eswin_group_desc *pgrp = &pctrl->groups[selector]; + + for (i = 0; i < pgrp->npins; i++) { + ret = eswin_pinconf_cfg_set(pctldev, pgrp->pins[i], configs, + num_configs); + if (ret) + return ret; + } + return 0; +} + +static const struct pinconf_ops eswin_pinconf_ops = { + .is_generic = true, + .pin_config_get = eswin_pinconf_cfg_get, + .pin_config_set = eswin_pinconf_cfg_set, + .pin_config_group_set = eswin_pinconf_group_set, +}; + +static struct pinctrl_desc eswin_desc = { + .name = "eswin_pinctrl", + .pins = eswin_pins, + .npins = ARRAY_SIZE(eswin_pins), + .pctlops = &eswin_pinctrl_ops, + .pmxops = &eswin_pinmux_ops, + .confops = &eswin_pinconf_ops, + .owner = THIS_MODULE, +}; + +static int eswin_pinctrl_probe(struct platform_device *pdev) +{ + struct resource *res; + struct eswin_pinctrl *pctrl; + pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) + return -ENOMEM; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + pctrl->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pctrl->base)) + return PTR_ERR(pctrl->base); + + pctrl->groups = eswin_pinctrl_groups; + pctrl->ngroups = ARRAY_SIZE(eswin_pinctrl_groups); + pctrl->funcs = eswin_pinmux_functions; + pctrl->nfuncs = ARRAY_SIZE(eswin_pinmux_functions); + + pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &eswin_desc, pctrl); + if (IS_ERR(pctrl->pctrl)){ + return PTR_ERR(pctrl->pctrl); + } + + platform_set_drvdata(pdev, pctrl); + + dev_info(&pdev->dev, "eswin pinctrl initialized\n"); + + return 0; +} + +static int eswin_pinctrl_remove(struct platform_device *platform_dev) +{ + struct eswin_pinctrl *eswin_pinctrl_ptr = platform_get_drvdata(platform_dev); + pinctrl_unregister(eswin_pinctrl_ptr->pctrl); + return 0; +} + +static const struct of_device_id eswin_pinctrl_of_match[] = { + { .compatible = "eswin,eic7700-pinctrl" }, + { } +}; + +static struct platform_driver eswin_pinctrl_driver = { + .driver = { + .name = "eswin-pinctrl", + .of_match_table = eswin_pinctrl_of_match, + }, + .probe = eswin_pinctrl_probe, + .remove = eswin_pinctrl_remove, +}; + +static int __init eswin_pinctrl_init(void) +{ + return platform_driver_register(&eswin_pinctrl_driver); +} +postcore_initcall(eswin_pinctrl_init); + +static void __exit eswin_pinctrl_exit(void) +{ + platform_driver_unregister(&eswin_pinctrl_driver); +} +module_exit(eswin_pinctrl_exit); + +MODULE_DESCRIPTION("ESWIN Pinctrl Controller Platform Device Drivers"); +MODULE_AUTHOR("luyulin@eswincomputing.com"); +MODULE_LICENSE("GPL"); From a757b739da86b7c612389c68471d0fba2898f65f Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Tue, 30 Jul 2024 09:44:55 +0000 Subject: [PATCH 16/38] driver: usb: Add Support for eswin dwc3 USB Signed-off-by: Yang Wei Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/usb/dwc3/Kconfig | 9 + drivers/usb/dwc3/Makefile | 1 + drivers/usb/dwc3/dwc3-eswin.c | 673 ++++++++++++++++++++++++++++++++++ 3 files changed, 683 insertions(+) create mode 100755 drivers/usb/dwc3/dwc3-eswin.c diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 98efcbb76c882..3571543e83483 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -118,6 +118,15 @@ config USB_DWC3_OF_SIMPLE Currently supports Xilinx and Qualcomm DWC USB3 IP. Say 'Y' or 'M' if you have one such device. +config USB_DWC3_ESWIN + tristate "Eswin Platforms" + depends on OF + depends on USB=y || USB=USB_DWC3 + default USB_DWC3 + help + Support of USB2/3 functionality in Eswin platforms. + say 'Y' or 'M' if you have one such device. + config USB_DWC3_ST tristate "STMicroelectronics Platforms" depends on (ARCH_STI || COMPILE_TEST) && OF diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index fe1493d4bbe58..d75a79bb453c8 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -55,3 +55,4 @@ obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o obj-$(CONFIG_USB_DWC3_IMX8MP) += dwc3-imx8mp.o obj-$(CONFIG_USB_DWC3_XILINX) += dwc3-xilinx.o obj-$(CONFIG_USB_DWC3_OCTEON) += dwc3-octeon.o +obj-$(CONFIG_USB_DWC3_ESWIN) += dwc3-eswin.o diff --git a/drivers/usb/dwc3/dwc3-eswin.c b/drivers/usb/dwc3/dwc3-eswin.c new file mode 100755 index 0000000000000..7536bd282340e --- /dev/null +++ b/drivers/usb/dwc3/dwc3-eswin.c @@ -0,0 +1,673 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * eswin Specific Glue layer + * + * 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 . + * + * Authors: Han Min + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core.h" +#include "io.h" + +#define AWSMMUSID GENMASK(31, 24) // The sid of write operation +#define AWSMMUSSID GENMASK(23, 16) // The ssid of write operation +#define ARSMMUSID GENMASK(15, 8) // The sid of read operation +#define ARSMMUSSID GENMASK(7, 0) // The ssid of read operation + +#define HSP_USB_VBUS_FSEL 0x2a +#define HSP_USB_MPLL_DEFAULT 0x0 + +#define HSP_USB_BUS_FILTER_EN (0x1 << 0) +#define HSP_USB_BUS_CLKEN_GM (0x1 << 9) +#define HSP_USB_BUS_CLKEN_GS (0x1 << 16) +#define HSP_USB_BUS_SW_RST (0x1 << 24) +#define HSP_USB_BUS_CLK_EN (0x1 << 28) + +#define HSP_USB_AXI_LP_XM_CSYSREQ (0x1 << 0) +#define HSP_USB_AXI_LP_XS_CSYSREQ (0x1 << 16) + +struct dwc3_eswin { + int num_clocks; + bool connected; + bool suspended; + bool force_mode; + bool is_phy_on; + struct device *dev; + struct clk **clks; + struct dwc3 *dwc; + struct extcon_dev *edev; + struct usb_hcd *hcd; + struct notifier_block device_nb; + struct notifier_block host_nb; + struct work_struct otg_work; + struct mutex lock; + struct reset_control *vaux_rst; + struct device *child_dev; + enum usb_role new_usb_role; +}; + +static ssize_t dwc3_mode_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct dwc3_eswin *eswin = dev_get_drvdata(device); + struct dwc3 *dwc = eswin->dwc; + int ret; + + switch (dwc->current_dr_role) { + case USB_DR_MODE_HOST: + ret = sprintf(buf, "host\n"); + break; + case USB_DR_MODE_PERIPHERAL: + ret = sprintf(buf, "peripheral\n"); + break; + case USB_DR_MODE_OTG: + ret = sprintf(buf, "otg\n"); + break; + default: + ret = sprintf(buf, "UNKNOWN\n"); + } + + return ret; +} + +static ssize_t dwc3_mode_store(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct dwc3_eswin *eswin = dev_get_drvdata(device); + struct dwc3 *dwc = eswin->dwc; + enum usb_role new_role; + struct usb_role_switch *role_sw = dwc->role_sw; + + if (!strncmp(buf, "1", 1) || !strncmp(buf, "host", 4)) { + new_role = USB_ROLE_HOST; + } else if (!strncmp(buf, "0", 1) || !strncmp(buf, "peripheral", 10)) { + new_role = USB_ROLE_DEVICE; + } else { + dev_info(eswin->dev, "illegal dr_mode\n"); + return count; + } + eswin->force_mode = true; + + mutex_lock(&eswin->lock); + usb_role_switch_set_role(role_sw, new_role); + mutex_unlock(&eswin->lock); + + return count; +} + +static DEVICE_ATTR_RW(dwc3_mode); + +static struct attribute *dwc3_eswin_attrs[] = { + &dev_attr_dwc3_mode.attr, + NULL, +}; + +static struct attribute_group dwc3_eswin_attr_group = { + .name = NULL, /* we want them in the same directory */ + .attrs = dwc3_eswin_attrs, +}; + +static int dwc3_eswin_device_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct dwc3_eswin *eswin = + container_of(nb, struct dwc3_eswin, device_nb); + + mutex_lock(&eswin->lock); + eswin->new_usb_role = USB_ROLE_DEVICE; + mutex_unlock(&eswin->lock); + if (!eswin->suspended) + schedule_work(&eswin->otg_work); + + return NOTIFY_DONE; +} + +static int dwc3_eswin_host_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct dwc3_eswin *eswin = container_of(nb, struct dwc3_eswin, host_nb); + mutex_lock(&eswin->lock); + eswin->new_usb_role = USB_ROLE_HOST; + mutex_unlock(&eswin->lock); + if (!eswin->suspended) + schedule_work(&eswin->otg_work); + + return NOTIFY_DONE; +} + +static void dwc3_eswin_otg_extcon_evt_work(struct work_struct *work) +{ + struct dwc3_eswin *eswin = + container_of(work, struct dwc3_eswin, otg_work); + struct usb_role_switch *role_sw = eswin->dwc->role_sw; + if (true == eswin->force_mode) { + return; + } + mutex_lock(&eswin->lock); + usb_role_switch_set_role(role_sw, eswin->new_usb_role); + mutex_unlock(&eswin->lock); +} + +static int dwc3_eswin_get_extcon_dev(struct dwc3_eswin *eswin) +{ + struct device *dev = eswin->dev; + struct extcon_dev *edev; + s32 ret = 0; + + if (device_property_read_bool(dev, "extcon")) { + edev = extcon_get_edev_by_phandle(dev, 0); + if (IS_ERR(edev)) { + if (PTR_ERR(edev) != -EPROBE_DEFER) + dev_err(dev, "couldn't get extcon device\n"); + return PTR_ERR(edev); + } + eswin->edev = edev; + eswin->device_nb.notifier_call = dwc3_eswin_device_notifier; + ret = devm_extcon_register_notifier(dev, edev, EXTCON_USB, + &eswin->device_nb); + if (ret < 0) + dev_err(dev, "failed to register notifier for USB\n"); + + eswin->host_nb.notifier_call = dwc3_eswin_host_notifier; + ret = devm_extcon_register_notifier(dev, edev, EXTCON_USB_HOST, + &eswin->host_nb); + if (ret < 0) + dev_err(dev, "failed to register notifier for USB-HOST\n"); + } + + return 0; +} + +static int __init dwc3_eswin_deassert(struct dwc3_eswin *eswin) +{ + int rc; + + if (eswin->vaux_rst) { + rc = reset_control_deassert(eswin->vaux_rst); + WARN_ON(0 != rc); + } + + return 0; +} + +static int dwc3_eswin_assert(struct dwc3_eswin *eswin) +{ + int rc = 0; + + if (eswin->vaux_rst) { + rc = reset_control_assert(eswin->vaux_rst); + WARN_ON(0 != rc); + } + + return 0; +} + +static int dwc_usb_clk_init(struct device *dev) +{ + struct regmap *regmap; + u32 hsp_usb_bus; + u32 hsp_usb_axi_lp; + u32 hsp_usb_vbus_freq; + u32 hsp_usb_mpll; + int ret; + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,hsp_sp_csr"); + if (IS_ERR(regmap)) { + dev_dbg(dev, "No hsp_sp_csr phandle specified\n"); + return -1; + } + ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 1, + &hsp_usb_bus); + if (ret) { + dev_err(dev, "can't get usb sid cfg reg offset (%d)\n", ret); + return ret; + } + ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 2, + &hsp_usb_axi_lp); + if (ret) { + dev_err(dev, "can't get usb sid cfg reg offset (%d)\n", ret); + return ret; + } + ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 3, + &hsp_usb_vbus_freq); + if (ret) { + dev_err(dev, "can't get usb sid cfg reg offset (%d)\n", ret); + return ret; + } + ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 4, + &hsp_usb_mpll); + if (ret) { + dev_err(dev, "can't get usb sid cfg reg offset (%d)\n", ret); + return ret; + } + + /* + * usb1 clock init + * ref clock is 24M, below need to be set to satisfy usb phy requirement(125M) + */ + regmap_write(regmap, hsp_usb_vbus_freq, HSP_USB_VBUS_FSEL); + regmap_write(regmap, hsp_usb_mpll, HSP_USB_MPLL_DEFAULT); + + /* + * reset usb core and usb phy + */ + regmap_write(regmap, hsp_usb_bus, + HSP_USB_BUS_FILTER_EN | HSP_USB_BUS_CLKEN_GM | + HSP_USB_BUS_CLKEN_GS | HSP_USB_BUS_SW_RST | + HSP_USB_BUS_CLK_EN); + regmap_write(regmap, hsp_usb_axi_lp, + HSP_USB_AXI_LP_XM_CSYSREQ | HSP_USB_AXI_LP_XS_CSYSREQ); + + return 0; +} + +int dwc3_sid_cfg(struct device *dev) +{ + int ret; + struct regmap *regmap; + int hsp_mmu_usb_reg; + u32 rdwr_sid_ssid; + u32 sid; + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + + /* not behind smmu, use the default reset value(0x0) of the reg as streamID*/ + if (fwspec == NULL) { + dev_dbg(dev, "dev is not behind smmu, skip configuration of sid\n"); + return 0; + } + sid = fwspec->ids[0]; + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,hsp_sp_csr"); + if (IS_ERR(regmap)) { + dev_dbg(dev, "No hsp_sp_csr phandle specified\n"); + return 0; + } + + ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 1, + &hsp_mmu_usb_reg); + if (ret) { + dev_err(dev, "can't get usb sid cfg reg offset (%d)\n", ret); + return ret; + } + + /* make the reading sid the same as writing sid, ssid is fixed to zero */ + rdwr_sid_ssid = FIELD_PREP(AWSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(AWSMMUSSID, 0); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSSID, 0); + regmap_write(regmap, hsp_mmu_usb_reg, rdwr_sid_ssid); + + ret = eic7700_dynm_sid_enable(dev_to_node(dev)); + if (ret < 0) + { + dev_err(dev, "failed to config usb streamID(%d)!\n", sid); + } + else + { + dev_dbg(dev, "success to config usb streamID(%d)!\n", sid); + } + + return ret; +} + +static int dwc3_eswin_probe(struct platform_device *pdev) +{ + struct dwc3_eswin *eswin; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node, *child; + struct platform_device *child_pdev; + unsigned int count; + int ret; + int i; + int err_desc = 0; + struct gpio_desc *hub_gpio; + + hub_gpio = devm_gpiod_get(dev, "hub-rst", GPIOD_OUT_HIGH); + err_desc = IS_ERR(hub_gpio); + + if (!err_desc) { + gpiod_set_raw_value(hub_gpio, 1); + } + + eswin = devm_kzalloc(dev, sizeof(*eswin), GFP_KERNEL); + if (!eswin) + return -ENOMEM; + + count = of_clk_get_parent_count(np); + if (!count) + return -ENOENT; + + eswin->num_clocks = count; + eswin->force_mode = false; + eswin->clks = devm_kcalloc(dev, eswin->num_clocks, sizeof(struct clk *), + GFP_KERNEL); + if (!eswin->clks) + return -ENOMEM; + + platform_set_drvdata(pdev, eswin); + + mutex_init(&eswin->lock); + + eswin->dev = dev; + + mutex_lock(&eswin->lock); + + for (i = 0; i < eswin->num_clocks; i++) { + struct clk *clk; + clk = of_clk_get(np, i); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + goto err0; + } + ret = clk_prepare_enable(clk); + if (ret < 0) { + clk_put(clk); + goto err0; + } + + eswin->clks[i] = clk; + } + + eswin->vaux_rst = devm_reset_control_get(dev, "vaux"); + if (IS_ERR_OR_NULL(eswin->vaux_rst)) { + dev_err(dev, "Failed to asic0_rst handle\n"); + return -EFAULT; + } + + dwc3_eswin_deassert(eswin); + dwc_usb_clk_init(dev); + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "get_sync failed with err %d\n", ret); + goto err1; + } + + child = of_get_child_by_name(np, "dwc3"); + if (!child) { + dev_err(dev, "failed to find dwc3 core node\n"); + ret = -ENODEV; + goto err1; + } + + /* Allocate and initialize the core */ + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) { + dev_err(dev, "failed to create dwc3 core\n"); + goto err1; + } + + INIT_WORK(&eswin->otg_work, dwc3_eswin_otg_extcon_evt_work); + + child_pdev = of_find_device_by_node(child); + if (!child_pdev) { + dev_err(dev, "failed to find dwc3 core device\n"); + ret = -ENODEV; + goto err2; + } + + eswin->dwc = platform_get_drvdata(child_pdev); + if (!eswin->dwc) { + dev_err(dev, "failed to get drvdata dwc3\n"); + ret = -EPROBE_DEFER; + goto err2; + } + eswin->child_dev = &child_pdev->dev; + + ret = eic7700_tbu_power(eswin->child_dev, true); + if (ret) + { + dev_err(dev, "tbu power on failed %d\n", ret); + goto err2; + } + + ret = dwc3_sid_cfg(&child_pdev->dev); + if (ret) + goto err3; + + ret = dwc3_eswin_get_extcon_dev(eswin); + if (ret < 0) + goto err3; + + mutex_unlock(&eswin->lock); + ret = sysfs_create_group(&dev->kobj, &dwc3_eswin_attr_group); + if (ret) + dev_err(dev, "failed to create sysfs group: %d\n", ret); + + return ret; + +err3: + ret = eic7700_tbu_power(eswin->child_dev, false); + if (ret) + { + dev_err(dev, "tbu power2 off failed %d\n", ret); + } + +err2: + cancel_work_sync(&eswin->otg_work); + of_platform_depopulate(dev); + +err1: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + dwc3_eswin_assert(eswin); + +err0: + for (i = 0; i < eswin->num_clocks && eswin->clks[i]; i++) { + if (!pm_runtime_status_suspended(dev)) + clk_disable(eswin->clks[i]); + clk_unprepare(eswin->clks[i]); + clk_put(eswin->clks[i]); + } + + mutex_unlock(&eswin->lock); + + return ret; +} + +static int dwc3_eswin_remove(struct platform_device *pdev) +{ + struct dwc3_eswin *eswin = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + int i = 0; + int ret = 0; + cancel_work_sync(&eswin->otg_work); + + sysfs_remove_group(&dev->kobj, &dwc3_eswin_attr_group); + + /* Restore hcd state before unregistering xhci */ + if (eswin->edev && !eswin->connected) { + struct usb_hcd *hcd = dev_get_drvdata(&eswin->dwc->xhci->dev); + + pm_runtime_get_sync(dev); + + /* + * The xhci code does not expect that HCDs have been removed. + * It will unconditionally call usb_remove_hcd() when the xhci + * driver is unloaded in of_platform_depopulate(). This results + * in a crash if the HCDs were already removed. To avoid this + * crash, add the HCDs here as dummy operation. + * This code should be removed after pm runtime support + * has been added to xhci. + */ + if (hcd->state == HC_STATE_HALT) { + usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); + usb_add_hcd(hcd->shared_hcd, hcd->irq, IRQF_SHARED); + } + } + + of_platform_depopulate(dev); + + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + + ret = eic7700_tbu_power(eswin->child_dev, false); + if (ret) + { + dev_err(dev, "tbu power off failed %d\n", ret); + } + + dwc3_eswin_assert(eswin); + for (i = 0; i < eswin->num_clocks; i++) { + if (!pm_runtime_status_suspended(dev)) + clk_disable(eswin->clks[i]); + clk_unprepare(eswin->clks[i]); + clk_put(eswin->clks[i]); + } + + return 0; +} + +#ifdef CONFIG_PM +static int dwc3_eswin_runtime_suspend(struct device *dev) +{ + struct dwc3_eswin *eswin = dev_get_drvdata(dev); + int i; + + for (i = 0; i < eswin->num_clocks; i++) + clk_disable(eswin->clks[i]); + + device_init_wakeup(dev, false); + + return 0; +} + +static int dwc3_eswin_runtime_resume(struct device *dev) +{ + struct dwc3_eswin *eswin = dev_get_drvdata(dev); + int i; + + for (i = 0; i < eswin->num_clocks; i++) + clk_enable(eswin->clks[i]); + + device_init_wakeup(dev, true); + + return 0; +} + +static int __maybe_unused dwc3_eswin_suspend(struct device *dev) +{ + struct dwc3_eswin *eswin = dev_get_drvdata(dev); + struct dwc3 *dwc = eswin->dwc; + + eswin->suspended = true; + cancel_work_sync(&eswin->otg_work); + + /* + * The flag of is_phy_on is only true if + * the DWC3 is in Host mode. + */ + if (eswin->is_phy_on) { + phy_power_off(dwc->usb2_generic_phy); + + /* + * If link state is Rx.Detect, it means that + * no usb device is connecting with the DWC3 + * Host, and need to power off the USB3 PHY. + */ + dwc->link_state = dwc3_gadget_get_link_state(dwc); + if (dwc->link_state == DWC3_LINK_STATE_RX_DET) + phy_power_off(dwc->usb3_generic_phy); + } + + return 0; +} + +static int __maybe_unused dwc3_eswin_resume(struct device *dev) +{ + struct dwc3_eswin *eswin = dev_get_drvdata(dev); + struct dwc3 *dwc = eswin->dwc; + + eswin->suspended = false; + + if (eswin->is_phy_on) { + phy_power_on(dwc->usb2_generic_phy); + + if (dwc->link_state == DWC3_LINK_STATE_RX_DET) + phy_power_on(dwc->usb3_generic_phy); + } + + if (eswin->edev) + schedule_work(&eswin->otg_work); + + return 0; +} + +static const struct dev_pm_ops dwc3_eswin_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(dwc3_eswin_suspend, dwc3_eswin_resume) + SET_RUNTIME_PM_OPS(dwc3_eswin_runtime_suspend, + dwc3_eswin_runtime_resume, NULL) +}; + +#define DEV_PM_OPS (&dwc3_eswin_dev_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM */ + +static const struct of_device_id eswin_dwc3_match[] = { + { .compatible = "eswin,eic7700-dwc3" }, + { /* Sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, eswin_dwc3_match); + +static struct platform_driver dwc3_eswin_driver = { + .probe = dwc3_eswin_probe, + .remove = dwc3_eswin_remove, + .driver = { + .name = "eswin-dwc3", + .pm = DEV_PM_OPS, + .of_match_table = eswin_dwc3_match, + }, +}; + +module_platform_driver(dwc3_eswin_driver); + +MODULE_ALIAS("platform:eswin-dwc3"); +MODULE_AUTHOR("Han Min "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("DesignWare USB3 ESWIN Glue Layer"); From 8f37ad1444b788c32517b0435f52df9a5ca00803 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Tue, 30 Jul 2024 09:52:16 +0000 Subject: [PATCH 17/38] drivers: usb: typec: Add driver for FUSB303B type C controller Signed-off-by: Yang Wei Signed-off-by: Pritesh Patel --- drivers/usb/typec/tcpm/Kconfig | 9 + drivers/usb/typec/tcpm/Makefile | 1 + drivers/usb/typec/tcpm/fusb303b.c | 810 ++++++++++++++++++++++++++++++ 3 files changed, 820 insertions(+) create mode 100644 drivers/usb/typec/tcpm/fusb303b.c diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig index 0b2993fef564b..760fd03fc751e 100644 --- a/drivers/usb/typec/tcpm/Kconfig +++ b/drivers/usb/typec/tcpm/Kconfig @@ -63,6 +63,15 @@ config TYPEC_FUSB302 Type-C Port Controller Manager to provide USB PD and USB Type-C functionalities. +config TYPEC_FUSB303B + tristate "Onsemi FUSB303B Type-C chip driver" + depends on I2C + depends on EXTCON || !EXTCON + help + The Onsemi FUSB303B Type-C chip driver that works with + Type-C Port Controller Manager to provide USB + Type-C functionalities. + config TYPEC_WCOVE tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver" depends on ACPI diff --git a/drivers/usb/typec/tcpm/Makefile b/drivers/usb/typec/tcpm/Makefile index 7a8cad0c0bdb4..d2b501e320122 100644 --- a/drivers/usb/typec/tcpm/Makefile +++ b/drivers/usb/typec/tcpm/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_TYPEC_TCPM) += tcpm.o obj-$(CONFIG_TYPEC_FUSB302) += fusb302.o +obj-$(CONFIG_TYPEC_FUSB303B) += fusb303b.o obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o typec_wcove-y := wcove.o obj-$(CONFIG_TYPEC_TCPCI) += tcpci.o diff --git a/drivers/usb/typec/tcpm/fusb303b.c b/drivers/usb/typec/tcpm/fusb303b.c new file mode 100644 index 0000000000000..3d6ddf4a5d5f0 --- /dev/null +++ b/drivers/usb/typec/tcpm/fusb303b.c @@ -0,0 +1,810 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Onsemi FUSB303B Type-C Chip 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 . + * + * Authors: Yang Wei + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define FUSB303B_REG_DEVICE_ID 0X1 +#define FUSB303B_REG_DEVICE_TYPE 0X2 +#define FUSB303B_REG_PORTROLE 0X3 +#define FUSB303B_REG_CONTROL 0X4 +#define FUSB303B_REG_CONTROL1 0X5 +#define FUSB303B_REG_MANUAL 0X9 +#define FUSB303B_REG_RESET 0XA +#define FUSB303B_REG_MASK 0XE +#define FUSB303B_REG_MASK1 0XF +#define FUSB303B_REG_STATUS 0X11 +#define FUSB303B_REG_STATUS1 0X12 +#define FUSB303B_REG_TYPE 0X13 +#define FUSB303B_REG_INTERRUPT 0X14 +#define FUSB303B_REG_INTERRUPT1 0X15 + +#define FUSB303B_PORTROLE_DRP BIT(2) +#define FUSB303B_PORTROLE_SINK BIT(1) +#define FUSB303B_PORTROLE_SOURCE BIT(0) + +#define FUSB303B_CONTROL_T_DRP BIT(6) +#define FUSB303B_CONTROL_DRPTOGGLE BIT(4) +#define FUSB303B_CONTROL_DCABLE_EN BIT(3) +#define FUSB303B_CONTROL_HOST_CUR BIT(1) +#define FUSB303B_CONTROL_INT_MASK BIT(0) + +#define FUSB303B_CONTROL1_REMEDY_EN BIT(7) +#define FUSB303B_CONTROL1_AUTO_SNK_TH BIT(5) +#define FUSB303B_CONTROL1_AUTO_SNK_EN BIT(4) +#define FUSB303B_CONTROL1_ENABLE BIT(3) +#define FUSB303B_CONTROL1_TCCDEB BIT(0) + +#define FUSB303B_STATUS_AUTOSNK BIT(7) +#define FUSB303B_STATUS_VSAFE0V BIT(6) +#define FUSB303B_STATUS_ORIENT BIT(4) +#define FUSB303B_STATUS_VBUSOK BIT(3) +#define FUSB303B_STATUS_BC_LVL BIT(1) +#define FUSB303B_STATUS_BC_LVL_MASK 0X6 +#define FUSB303B_STATUS_ATTACH BIT(0) + +#define FUSB303B_STATUS_MASK 0X30 + +#define FUSB303B_BC_LVL_SINK_OR_RA 0 +#define FUSB303B_BC_LVL_SINK_DEFAULT 1 +#define FUSB303B_BC_LVL_SINK_1_5A 2 +#define FUSB303B_BC_LVL_SINK_3A 3 + +#define FUSB303B_INT_I_ORIENT BIT(6) +#define FUSB303B_INT_I_FAULT BIT(5) +#define FUSB303B_INT_I_VBUS_CHG BIT(4) +#define FUSB303B_INT_I_AUTOSNK BIT(3) +#define FUSB303B_INT_I_BC_LVL BIT(2) +#define FUSB303B_INT_I_DETACH BIT(1) +#define FUSB303B_INT_I_ATTACH BIT(0) + +#define FUSB303B_INT1_I_REM_VBOFF BIT(6) +#define FUSB303B_INT1_I_REM_VBON BIT(5) +#define FUSB303B_INT1_I_REM_FAIL BIT(3) +#define FUSB303B_INT1_I_FRC_FAIL BIT(2) +#define FUSB303B_INT1_I_FRC_SUCC BIT(1) +#define FUSB303B_INT1_I_REMEDY BIT(0) + +#define FUSB303B_TYPE_SINK BIT(4) +#define FUSB303B_TYPE_SOURCE BIT(3) + +#define FUSB_REG_MASK_M_VBUS_CHG BIT(4) + +#define LOG_BUFFER_ENTRIES 1024 +#define LOG_BUFFER_ENTRY_SIZE 128 + +struct fusb303b_chip { + struct device *dev; + struct i2c_client *i2c_client; + struct tcpm_port *tcpm_port; + struct tcpc_dev tcpc_dev; + + spinlock_t irq_lock; + struct work_struct irq_work; + bool irq_suspended; + bool irq_while_suspended; + struct gpio_desc *gpio_int_n; + int gpio_int_n_irq; + + /* lock for sharing chip states */ + struct mutex lock; + + /* port status */ + bool vconn_on; + bool vbus_on; + bool charge_on; + bool vbus_present; + enum typec_cc_polarity cc_polarity; + enum typec_cc_status cc1; + enum typec_cc_status cc2; + + struct task_struct *stat_task; +#ifdef CONFIG_DEBUG_FS + struct dentry *dentry; + /* lock for log buffer access */ + struct mutex logbuffer_lock; + int logbuffer_head; + int logbuffer_tail; + u8 *logbuffer[LOG_BUFFER_ENTRIES]; +#endif +}; + +#ifdef CONFIG_DEBUG_FS +static bool fusb303b_log_full(struct fusb303b_chip *chip) +{ + return chip->logbuffer_tail == + (chip->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; +} + +__printf(2, 0) static void _fusb303b_log(struct fusb303b_chip *chip, + const char *fmt, va_list args) +{ + char tmpbuffer[LOG_BUFFER_ENTRY_SIZE]; + u64 ts_nsec = local_clock(); + unsigned long rem_nsec; + + if (!chip->logbuffer[chip->logbuffer_head]) { + chip->logbuffer[chip->logbuffer_head] = + kzalloc(LOG_BUFFER_ENTRY_SIZE, GFP_KERNEL); + if (!chip->logbuffer[chip->logbuffer_head]) + return; + } + + vsnprintf(tmpbuffer, sizeof(tmpbuffer), fmt, args); + + mutex_lock(&chip->logbuffer_lock); + + if (fusb303b_log_full(chip)) { + chip->logbuffer_head = max(chip->logbuffer_head - 1, 0); + strlcpy(tmpbuffer, "overflow", sizeof(tmpbuffer)); + } + + if (chip->logbuffer_head < 0 || + chip->logbuffer_head >= LOG_BUFFER_ENTRIES) { + dev_warn(chip->dev, "Bad log buffer index %d\n", + chip->logbuffer_head); + goto abort; + } + + if (!chip->logbuffer[chip->logbuffer_head]) { + dev_warn(chip->dev, "Log buffer index %d is NULL\n", + chip->logbuffer_head); + goto abort; + } + + rem_nsec = do_div(ts_nsec, 1000000000); + scnprintf(chip->logbuffer[chip->logbuffer_head], LOG_BUFFER_ENTRY_SIZE, + "[%5lu.%06lu] %s", (unsigned long)ts_nsec, rem_nsec / 1000, + tmpbuffer); + chip->logbuffer_head = (chip->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; + +abort: + mutex_unlock(&chip->logbuffer_lock); +} + +__printf(2, 3) static void fusb303b_log(struct fusb303b_chip *chip, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + _fusb303b_log(chip, fmt, args); + va_end(args); +} + +static int fusb303b_debug_show(struct seq_file *s, void *v) +{ + struct fusb303b_chip *chip = (struct fusb303b_chip *)s->private; + int tail; + + mutex_lock(&chip->logbuffer_lock); + tail = chip->logbuffer_tail; + while (tail != chip->logbuffer_head) { + seq_printf(s, "%s\n", chip->logbuffer[tail]); + tail = (tail + 1) % LOG_BUFFER_ENTRIES; + } + if (!seq_has_overflowed(s)) + chip->logbuffer_tail = tail; + mutex_unlock(&chip->logbuffer_lock); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(fusb303b_debug); + +static void fusb303b_debugfs_init(struct fusb303b_chip *chip) +{ + char name[NAME_MAX]; + + mutex_init(&chip->logbuffer_lock); + snprintf(name, NAME_MAX, "fusb303b-%s", dev_name(chip->dev)); + chip->dentry = debugfs_create_dir(name, usb_debug_root); + debugfs_create_file("log", S_IFREG | 0444, chip->dentry, chip, + &fusb303b_debug_fops); +} + +static void fusb303b_debugfs_exit(struct fusb303b_chip *chip) +{ + debugfs_remove(chip->dentry); +} + +#else + +static void fusb303b_log(const struct fusb303b_chip *chip, const char *fmt, ...) +{ +} +static void fusb303b_debugfs_init(const struct fusb303b_chip *chip) +{ +} +static void fusb303b_debugfs_exit(const struct fusb303b_chip *chip) +{ +} + +#endif + +static int fusb303b_i2c_write(struct fusb303b_chip *chip, u8 address, u8 data) +{ + int ret = 0; + + ret = i2c_smbus_write_byte_data(chip->i2c_client, address, data); + if (ret < 0) + fusb303b_log(chip, "cannot write 0x%02x to 0x%02x, ret=%d", + data, address, ret); + + return ret; +} + +static int fusb303b_i2c_read(struct fusb303b_chip *chip, u8 address, u8 *data) +{ + int ret = 0; + + ret = i2c_smbus_read_byte_data(chip->i2c_client, address); + *data = (u8)ret; + if (ret < 0) + fusb303b_log(chip, "cannot read %02x, ret=%d", address, ret); + + return ret; +} + +static int fusb303b_i2c_mask_write(struct fusb303b_chip *chip, u8 address, + u8 mask, u8 value) +{ + int ret = 0; + u8 data; + + ret = fusb303b_i2c_read(chip, address, &data); + if (ret < 0) + return ret; + data &= ~mask; + data |= value; + ret = fusb303b_i2c_write(chip, address, data); + if (ret < 0) + return ret; + + return ret; +} + +static int fusb303b_i2c_clear_bits(struct fusb303b_chip *chip, u8 address, + u8 clear_bits) +{ + return fusb303b_i2c_mask_write(chip, address, clear_bits, 0x00); +} + +static int fusb303b_sw_reset(struct fusb303b_chip *chip) +{ + int ret = 0; + + ret = fusb303b_i2c_write(chip, FUSB303B_REG_RESET, 1); + if (ret < 0) + fusb303b_log(chip, "cannot sw reset the chip, ret=%d", ret); + else + fusb303b_log(chip, "sw reset"); + + return ret; +} + +/* + * initialize interrupt on the chip + * - unmasked interrupt: VBUS_OK + */ +static int fusb303b_init_interrupt(struct fusb303b_chip *chip) +{ + int ret = 0; + + ret = fusb303b_i2c_write(chip, FUSB303B_REG_MASK, + 0xFF & ~FUSB_REG_MASK_M_VBUS_CHG); + if (ret < 0) + return ret; + ret = fusb303b_i2c_write(chip, FUSB303B_REG_MASK1, 0xFF); + if (ret < 0) + return ret; + + ret = fusb303b_i2c_clear_bits(chip, FUSB303B_REG_CONTROL, + FUSB303B_CONTROL_INT_MASK); + if (ret < 0) + return ret; + + return ret; +} + +static int tcpm_init(struct tcpc_dev *dev) +{ + struct fusb303b_chip *chip = + container_of(dev, struct fusb303b_chip, tcpc_dev); + int ret = 0; + u8 data; + + ret = fusb303b_sw_reset(chip); + if (ret < 0) + return ret; + fusb303b_i2c_read(chip, FUSB303B_REG_STATUS, &data); + fusb303b_i2c_mask_write(chip, FUSB303B_REG_CONTROL1, + FUSB303B_CONTROL1_ENABLE, + FUSB303B_CONTROL1_ENABLE); + ret = fusb303b_init_interrupt(chip); + if (ret < 0) + return ret; + + ret = fusb303b_i2c_read(chip, FUSB303B_REG_STATUS, &data); + if (ret < 0) + return ret; + chip->vbus_present = !!(data & FUSB303B_STATUS_VBUSOK); + ret = fusb303b_i2c_read(chip, FUSB303B_REG_DEVICE_ID, &data); + if (ret < 0) + return ret; + fusb303b_log(chip, "fusb303b device ID: 0x%02x", data); + + ret = fusb303b_i2c_read(chip, FUSB303B_REG_DEVICE_TYPE, &data); + if (ret < 0) + return ret; + fusb303b_log(chip, "fusb303b type:0x%02x", data); + + return ret; +} + +static int tcpm_get_vbus(struct tcpc_dev *dev) +{ + struct fusb303b_chip *chip = + container_of(dev, struct fusb303b_chip, tcpc_dev); + int ret = 0; + + mutex_lock(&chip->lock); + ret = chip->vbus_present ? 1 : 0; + mutex_unlock(&chip->lock); + fusb303b_log(chip, "%s.%d vbus_present:%d\n", __FUNCTION__, __LINE__, + ret); + return ret; +} + +static const char *const typec_cc_status_name[] = { + [TYPEC_CC_OPEN] = "Open", [TYPEC_CC_RA] = "Ra", + [TYPEC_CC_RD] = "Rd", [TYPEC_CC_RP_DEF] = "Rp-def", + [TYPEC_CC_RP_1_5] = "Rp-1.5", [TYPEC_CC_RP_3_0] = "Rp-3.0", +}; + +static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) +{ + struct fusb303b_chip *chip = + container_of(dev, struct fusb303b_chip, tcpc_dev); + fusb303b_log(chip, "%s.%d cc:%s\n", __FUNCTION__, __LINE__, + typec_cc_status_name[cc]); + + return 0; +} + +static int tcpm_get_cc(struct tcpc_dev *dev, enum typec_cc_status *cc1, + enum typec_cc_status *cc2) +{ + struct fusb303b_chip *chip = + container_of(dev, struct fusb303b_chip, tcpc_dev); + + mutex_lock(&chip->lock); + *cc1 = chip->cc1; + *cc2 = chip->cc2; + fusb303b_log(chip, "%s.%d,cc1=%s, cc2=%s", __FUNCTION__, __LINE__, + typec_cc_status_name[*cc1], typec_cc_status_name[*cc2]); + mutex_unlock(&chip->lock); + + return 0; +} + +static int tcpm_set_polarity(struct tcpc_dev *dev, + enum typec_cc_polarity polarity) +{ + struct fusb303b_chip *chip = + container_of(dev, struct fusb303b_chip, tcpc_dev); + fusb303b_log(chip, "%s.%d polarity:%d\n", __FUNCTION__, __LINE__, + polarity); + return 0; +} + +static int tcpm_set_vconn(struct tcpc_dev *dev, bool on) +{ + struct fusb303b_chip *chip = + container_of(dev, struct fusb303b_chip, tcpc_dev); + int ret = 0; + + fusb303b_log(chip, "%s.%d on:%d\n", __FUNCTION__, __LINE__, on); + chip->vconn_on = on; + + return ret; +} + +static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) +{ + struct fusb303b_chip *chip = + container_of(dev, struct fusb303b_chip, tcpc_dev); + + fusb303b_log(chip, "%s.%d on:%d,charge:%d\n", __FUNCTION__, __LINE__, + on, charge); + chip->vbus_on = on; + chip->charge_on = charge; + + return 0; +} + +static int tcpm_set_pd_rx(struct tcpc_dev *dev, bool on) +{ + struct fusb303b_chip *chip = + container_of(dev, struct fusb303b_chip, tcpc_dev); + + fusb303b_log(chip, "%s.%d\n", __FUNCTION__, __LINE__); + + return 0; +} + +static const char *const typec_role_name[] = { + [TYPEC_SINK] = "Sink", + [TYPEC_SOURCE] = "Source", +}; + +static const char *const typec_data_role_name[] = { + [TYPEC_DEVICE] = "Device", + [TYPEC_HOST] = "Host", +}; + +static int tcpm_set_roles(struct tcpc_dev *dev, bool attached, + enum typec_role pwr, enum typec_data_role data) +{ + struct fusb303b_chip *chip = + container_of(dev, struct fusb303b_chip, tcpc_dev); + fusb303b_log(chip, "%s.%d pwr:%d,%s data:%d,%s\n", __FUNCTION__, + __LINE__, pwr, typec_role_name[data], data, + typec_data_role_name[data]); + + return 0; +} + +static s32 tcpm_start_toggling(struct tcpc_dev *dev, + enum typec_port_type port_type, + enum typec_cc_status cc) +{ + struct fusb303b_chip *chip = + container_of(dev, struct fusb303b_chip, tcpc_dev); + s32 ret = 0; + + fusb303b_log(chip, "%s.%d port_type:%d cc:%d\n", __FUNCTION__, __LINE__, + port_type, cc); + switch (port_type) { + case TYPEC_PORT_DRP: + ret = fusb303b_i2c_write(chip, FUSB303B_REG_PORTROLE, + FUSB303B_PORTROLE_DRP); + break; + case TYPEC_PORT_SRC: + ret = fusb303b_i2c_write(chip, FUSB303B_REG_PORTROLE, + FUSB303B_PORTROLE_SOURCE); + break; + default: + ret = fusb303b_i2c_write(chip, FUSB303B_REG_PORTROLE, + FUSB303B_PORTROLE_SINK); + break; + } + + return ret; +} + +static int tcpm_pd_transmit(struct tcpc_dev *dev, enum tcpm_transmit_type type, + const struct pd_message *msg, + unsigned int negotiated_rev) +{ + struct fusb303b_chip *chip = + container_of(dev, struct fusb303b_chip, tcpc_dev); + + fusb303b_log(chip, "%s.%d negotiated_rev:%d\n", __FUNCTION__, __LINE__, + negotiated_rev); + + return 0; +} + +static void init_tcpc_dev(struct tcpc_dev *fusb303b_tcpc_dev) +{ + fusb303b_tcpc_dev->init = tcpm_init; + fusb303b_tcpc_dev->get_vbus = tcpm_get_vbus; + fusb303b_tcpc_dev->set_cc = tcpm_set_cc; + fusb303b_tcpc_dev->get_cc = tcpm_get_cc; + fusb303b_tcpc_dev->set_polarity = tcpm_set_polarity; + fusb303b_tcpc_dev->set_vconn = tcpm_set_vconn; + fusb303b_tcpc_dev->set_vbus = tcpm_set_vbus; + fusb303b_tcpc_dev->set_pd_rx = tcpm_set_pd_rx; + fusb303b_tcpc_dev->set_roles = tcpm_set_roles; + fusb303b_tcpc_dev->start_toggling = tcpm_start_toggling; + fusb303b_tcpc_dev->pd_transmit = tcpm_pd_transmit; +} + +enum fusb_cc_status { + CC_NO_CONN, + CC_CONN_CC1, + CC_CONN_CC2, + CC_CONN_FAULT, +}; + +static irqreturn_t fusb303b_irq(int irq, void *dev_id) +{ + struct fusb303b_chip *chip = dev_id; + int ret = 0; + u8 interrupt = 0, interrupt1; + u8 status = 0; + bool vbus_present = 0; + u8 cc_status = 0; + + mutex_lock(&chip->lock); + /* grab a snapshot of intr flags */ + + ret = fusb303b_i2c_read(chip, FUSB303B_REG_INTERRUPT, &interrupt); + if (ret < 0) + goto done; + ret = fusb303b_i2c_read(chip, FUSB303B_REG_INTERRUPT, &interrupt1); + if (ret < 0) + goto done; + ret = fusb303b_i2c_read(chip, FUSB303B_REG_STATUS, &status); + if (ret < 0) + goto done; + + fusb303b_log(chip, "IRQ: 0x%02x, status: 0x%02x\n", interrupt, status); + + if (interrupt & FUSB303B_INT_I_VBUS_CHG) { + vbus_present = !!(status & FUSB303B_STATUS_VBUSOK); + fusb303b_log(chip, "IRQ: VBUS_OK, vbus=%s", + vbus_present ? "On" : "Off"); + if (vbus_present != chip->vbus_present) { + chip->vbus_present = vbus_present; + tcpm_vbus_change(chip->tcpm_port); + } + } + cc_status = (status & FUSB303B_STATUS_MASK) >> 4; + + if (CC_CONN_CC1 == cc_status) { + chip->cc_polarity = TYPEC_POLARITY_CC1; + tcpm_cc_change(chip->tcpm_port); + } else if (CC_CONN_CC2 == cc_status) { + chip->cc_polarity = TYPEC_POLARITY_CC2; + tcpm_cc_change(chip->tcpm_port); + } + + if (0 != interrupt) + fusb303b_i2c_write(chip, FUSB303B_REG_INTERRUPT, interrupt); + if (0 != interrupt1) + fusb303b_i2c_write(chip, FUSB303B_REG_INTERRUPT1, interrupt1); +done: + mutex_unlock(&chip->lock); + return IRQ_HANDLED; +} + +static int init_gpio(struct fusb303b_chip *chip) +{ + struct device *dev = chip->dev; + int ret = 0; + + chip->gpio_int_n = devm_gpiod_get(dev, "int", GPIOD_IN); + if (IS_ERR(chip->gpio_int_n)) { + dev_err(dev, "failed to request gpio_int_n\n"); + return PTR_ERR(chip->gpio_int_n); + } + ret = gpiod_to_irq(chip->gpio_int_n); + if (ret < 0) { + dev_err(dev, "cannot request IRQ for GPIO Int_N, ret=%d", ret); + return ret; + } + chip->gpio_int_n_irq = ret; + + return 0; +} + +static const struct property_entry port_props[] = { + PROPERTY_ENTRY_STRING("data-role", "dual"), + PROPERTY_ENTRY_STRING("power-role", "dual"), + PROPERTY_ENTRY_STRING("try-power-role", "sink"), + {} +}; + +static struct fwnode_handle *fusb303b_fwnode_get(struct device *dev) +{ + struct fwnode_handle *fwnode; + fwnode = device_get_named_child_node(dev, "connector"); + if (!fwnode) + fwnode = fwnode_create_software_node(port_props, NULL); + + return fwnode; +} + +static int fusb303b_probe(struct i2c_client *client) +{ + struct fusb303b_chip *chip; + struct device *dev = &client->dev; + int ret = 0; + struct regmap *regmap; + int irq_sel_reg; + int irq_sel_bit; + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,syscfg"); + if (!IS_ERR(regmap)) { + ret = of_property_read_u32_index(dev->of_node, "eswin,syscfg", + 1, &irq_sel_reg); + if (ret) { + dev_err(dev, + "can't get irq cfg reg offset in sys_con(errno:%d)\n", + ret); + return ret; + } + ret = of_property_read_u32_index(dev->of_node, "eswin,syscfg", + 2, &irq_sel_bit); + if (ret) { + dev_err(dev, + "can't get irq cfg bit offset in sys_con(errno:%d)\n", + ret); + return ret; + } + regmap_clear_bits(regmap, irq_sel_reg, BIT_ULL(irq_sel_bit)); + } + + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + chip->i2c_client = client; + chip->dev = &client->dev; + mutex_init(&chip->lock); + spin_lock_init(&chip->irq_lock); + init_tcpc_dev(&chip->tcpc_dev); + fusb303b_debugfs_init(chip); + if (client->irq) { + chip->gpio_int_n_irq = client->irq; + } else { + ret = init_gpio(chip); + if (ret < 0) + goto destroy_workqueue; + } + chip->tcpc_dev.fwnode = fusb303b_fwnode_get(dev); + if (IS_ERR(chip->tcpc_dev.fwnode)) { + ret = PTR_ERR(chip->tcpc_dev.fwnode); + goto destroy_workqueue; + } + chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev); + if (IS_ERR(chip->tcpm_port)) { + fwnode_handle_put(chip->tcpc_dev.fwnode); + ret = PTR_ERR(chip->tcpm_port); + if (ret != -EPROBE_DEFER) + dev_err(dev, "cannot register tcpm port, ret=%d", ret); + goto destroy_workqueue; + } + + ret = devm_request_threaded_irq(dev, chip->gpio_int_n_irq, NULL, + fusb303b_irq, + IRQF_ONESHOT | IRQF_TRIGGER_LOW, + "fusb303b_interrupt_int_n", chip); + if (ret < 0) { + dev_err(dev, "cannot request IRQ for GPIO Int_N, ret=%d", ret); + goto tcpm_unregister_port; + } + + enable_irq_wake(chip->gpio_int_n_irq); + i2c_set_clientdata(client, chip); + + fusb303b_log(chip, "Kernel thread created successfully\n"); + return ret; + +tcpm_unregister_port: + tcpm_unregister_port(chip->tcpm_port); + fwnode_handle_put(chip->tcpc_dev.fwnode); +destroy_workqueue: + fusb303b_debugfs_exit(chip); + + return ret; +} + +static void fusb303b_remove(struct i2c_client *client) +{ + struct fusb303b_chip *chip = i2c_get_clientdata(client); + + disable_irq_wake(chip->gpio_int_n_irq); + free_irq(chip->gpio_int_n_irq, chip); + cancel_work_sync(&chip->irq_work); + tcpm_unregister_port(chip->tcpm_port); + fwnode_handle_put(chip->tcpc_dev.fwnode); + fusb303b_debugfs_exit(chip); +} + +static int fusb303b_pm_suspend(struct device *dev) +{ + struct fusb303b_chip *chip = dev->driver_data; + unsigned long flags; + + spin_lock_irqsave(&chip->irq_lock, flags); + chip->irq_suspended = true; + spin_unlock_irqrestore(&chip->irq_lock, flags); + + flush_work(&chip->irq_work); + return 0; +} + +static int fufusb303b_pm_resume(struct device *dev) +{ + struct fusb303b_chip *chip = dev->driver_data; + unsigned long flags; + + spin_lock_irqsave(&chip->irq_lock, flags); + if (chip->irq_while_suspended) { + schedule_work(&chip->irq_work); + chip->irq_while_suspended = false; + } + chip->irq_suspended = false; + spin_unlock_irqrestore(&chip->irq_lock, flags); + + return 0; +} + +static const struct of_device_id fusb303b_dt_match[] = { + { .compatible = "fcs,fusb303b" }, + {}, +}; +MODULE_DEVICE_TABLE(of, fusb303b_dt_match); + +static const struct i2c_device_id fusb303b_i2c_device_id[] = { + { "typec_fusb303b", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, fusb303b_i2c_device_id); + +static const struct dev_pm_ops fusb303b_pm_ops = { + .suspend = fusb303b_pm_suspend, + .resume = fufusb303b_pm_resume, +}; + +static struct i2c_driver fusb303b_driver = { + .driver = { + .name = "typec_fusb303b", + .pm = &fusb303b_pm_ops, + .of_match_table = of_match_ptr(fusb303b_dt_match), + }, + .probe = fusb303b_probe, + .remove = fusb303b_remove, + .id_table = fusb303b_i2c_device_id, +}; +module_i2c_driver(fusb303b_driver); + +MODULE_AUTHOR("Yang Wei "); +MODULE_DESCRIPTION("Onsemi FUSB303B Type-C Chip Driver"); +MODULE_LICENSE("GPL"); From 2372b2638ad433b2190ea8edf28fc93e0e034996 Mon Sep 17 00:00:00 2001 From: fanglifei Date: Tue, 30 Jul 2024 10:03:12 +0000 Subject: [PATCH 18/38] drivers: ethernet: Added ethernet driver for EIC7700 Signed-off-by: fanglifei Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/net/ethernet/stmicro/stmmac/Kconfig | 8 + drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + .../ethernet/stmicro/stmmac/dwmac-eic7700.c | 597 ++++++++++++++++++ 3 files changed, 606 insertions(+) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 25f2d42de406d..555268970c7db 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -66,6 +66,14 @@ config DWMAC_ANARION This selects the Anarion SoC glue layer support for the stmmac driver. +config DWMAC_EIC7700 + tristate "Support for Eswin EIC77xx ethernet driver" + select CRC32 + select MII + depends on OF && HAS_DMA + help + Support for Eswin EIC7700 ethernet driver. + config DWMAC_INGENIC tristate "Ingenic MAC support" default MACH_INGENIC diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 5b57aee19267f..9ea190bf67521 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -14,6 +14,7 @@ stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o # Ordering matters. Generic driver must be last. obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o obj-$(CONFIG_DWMAC_ANARION) += dwmac-anarion.o +obj-$(CONFIG_DWMAC_EIC7700) += dwmac-eic7700.o obj-$(CONFIG_DWMAC_INGENIC) += dwmac-ingenic.o obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c new file mode 100644 index 0000000000000..1e8ce3a13d17b --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c @@ -0,0 +1,597 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Eswin DWC Ethernet linux driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stmmac_platform.h" +#include "dwmac4.h" +#include +#include +#include +#include +#include + +/* eth_phy_ctrl_offset eth0:0x100; eth1:0x200 */ +#define ETH_TX_CLK_SEL BIT(16) +#define ETH_PHY_INTF_SELI BIT(0) + +/* eth_axi_lp_ctrl_offset eth0:0x108; eth1:0x208 */ +#define ETH_CSYSREQ_VAL BIT(0) + +/* hsp_aclk_ctrl_offset (0x148) */ +#define HSP_ACLK_CLKEN BIT(31) +#define HSP_ACLK_DIVSOR (0x2 << 4) + +/* hsp_cfg_ctrl_offset (0x14c) */ +#define HSP_CFG_CLKEN BIT(31) +#define SCU_HSP_PCLK_EN BIT(30) +#define HSP_CFG_CTRL_REGSET (HSP_CFG_CLKEN | SCU_HSP_PCLK_EN) + +/* RTL8211F PHY Configurations for LEDs */ +#define PHY_ADDR 0 +#define PHY_PAGE_SWITCH_REG 31 +#define PHY_LED_CFG_REG 16 +#define PHY_LED_PAGE_CFG 0xd04 + +#define AWSMMUSID GENMASK(31, 24) // The sid of write operation +#define AWSMMUSSID GENMASK(23, 16) // The ssid of write operation +#define ARSMMUSID GENMASK(15, 8) // The sid of read operation +#define ARSMMUSSID GENMASK(7, 0) // The ssid of read operation + +struct dwc_qos_priv { + struct device *dev; + int dev_id; + struct regmap *crg_regmap; + struct regmap *hsp_regmap; + struct reset_control *rst; + struct clk *clk_app; + struct clk *clk_csr; + struct clk *clk_tx; + struct regmap *rgmii_sel; + struct gpio_desc *phy_reset; + struct stmmac_priv *stmpriv; + int phyled_cfgs[3]; +}; + +static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, + struct plat_stmmacenet_data *plat_dat) +{ + struct device *dev = &pdev->dev; + u32 burst_map = 0; + u32 bit_index = 0; + u32 a_index = 0; + + if (!plat_dat->axi) { + plat_dat->axi = kzalloc(sizeof(struct stmmac_axi), GFP_KERNEL); + + if (!plat_dat->axi) + return -ENOMEM; + } + + plat_dat->axi->axi_lpi_en = device_property_read_bool(dev, + "snps,en-lpi"); + if (device_property_read_u32(dev, "snps,write-requests", + &plat_dat->axi->axi_wr_osr_lmt)) { + /** + * Since the register has a reset value of 1, if property + * is missing, default to 1. + */ + plat_dat->axi->axi_wr_osr_lmt = 1; + } else { + /** + * If property exists, to keep the behavior from dwc_eth_qos, + * subtract one after parsing. + */ + plat_dat->axi->axi_wr_osr_lmt--; + } + + if (device_property_read_u32(dev, "snps,read-requests", + &plat_dat->axi->axi_rd_osr_lmt)) { + /** + * Since the register has a reset value of 1, if property + * is missing, default to 1. + */ + plat_dat->axi->axi_rd_osr_lmt = 1; + } else { + /** + * If property exists, to keep the behavior from dwc_eth_qos, + * subtract one after parsing. + */ + plat_dat->axi->axi_rd_osr_lmt--; + } + device_property_read_u32(dev, "snps,burst-map", &burst_map); + + /* converts burst-map bitmask to burst array */ + for (bit_index = 0; bit_index < 7; bit_index++) { + if (burst_map & (1 << bit_index)) { + switch (bit_index) { + case 0: + plat_dat->axi->axi_blen[a_index] = 4; break; + case 1: + plat_dat->axi->axi_blen[a_index] = 8; break; + case 2: + plat_dat->axi->axi_blen[a_index] = 16; break; + case 3: + plat_dat->axi->axi_blen[a_index] = 32; break; + case 4: + plat_dat->axi->axi_blen[a_index] = 64; break; + case 5: + plat_dat->axi->axi_blen[a_index] = 128; break; + case 6: + plat_dat->axi->axi_blen[a_index] = 256; break; + default: + break; + } + a_index++; + } + } + + /* dwc-qos needs GMAC4, AAL, TSO and PMT */ + plat_dat->has_gmac4 = 1; + plat_dat->dma_cfg->aal = 1; + plat_dat->flags |= STMMAC_FLAG_TSO_EN; + plat_dat->pmt = 1; + + return 0; +} + +static int eswin_eth_sid_cfg(struct device *dev) +{ + int ret; + struct regmap *regmap; + int hsp_mmu_eth_reg; + u32 rdwr_sid_ssid; + u32 sid; + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + + /* not behind smmu, use the default reset value(0x0) of the reg as streamID*/ + if (fwspec == NULL) { + dev_dbg(dev, "dev is not behind smmu, skip configuration of sid\n"); + return 0; + } + sid = fwspec->ids[0]; + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,hsp_sp_csr"); + if (IS_ERR(regmap)) { + dev_dbg(dev, "No hsp_sp_csr phandle specified\n"); + return 0; + } + + ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 1, + &hsp_mmu_eth_reg); + if (ret) { + dev_err(dev, "can't get eth sid cfg reg offset (%d)\n", ret); + return ret; + } + + /* make the reading sid the same as writing sid, ssid is fixed to zero */ + rdwr_sid_ssid = FIELD_PREP(AWSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(AWSMMUSSID, 0); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSSID, 0); + regmap_write(regmap, hsp_mmu_eth_reg, rdwr_sid_ssid); + + ret = eic7700_dynm_sid_enable(dev_to_node(dev)); + if (ret < 0) + dev_err(dev, "failed to config eth streamID(%d)!\n", sid); + else + dev_dbg(dev, "success to config eth streamID(%d)!\n", sid); + + return ret; +} + +static void dwc_qos_fix_speed(void *priv, unsigned int speed, unsigned int mode) +{ + unsigned long rate = 125000000; + int 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 == 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); + } + + if (dwc_priv->stmpriv) { + data = mdiobus_read(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_PAGE_SWITCH_REG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_PAGE_SWITCH_REG, PHY_LED_PAGE_CFG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_LED_CFG_REG, dwc_priv->phyled_cfgs[0]); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_PAGE_SWITCH_REG, data); + } + + break; + case SPEED_100: + rate = 25000000; + + if (dwc_priv->dev_id == 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); + } + + if (dwc_priv->stmpriv) { + data = mdiobus_read(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_PAGE_SWITCH_REG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_PAGE_SWITCH_REG, PHY_LED_PAGE_CFG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_LED_CFG_REG, dwc_priv->phyled_cfgs[1]); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_PAGE_SWITCH_REG, data); + } + + break; + case SPEED_10: + rate = 2500000; + + if (dwc_priv->dev_id == 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); + } + + if (dwc_priv->stmpriv) { + data = mdiobus_read(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_PAGE_SWITCH_REG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_PAGE_SWITCH_REG, PHY_LED_PAGE_CFG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_LED_CFG_REG, dwc_priv->phyled_cfgs[2]); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, PHY_PAGE_SWITCH_REG, data); + } + + break; + default: + dev_err(dwc_priv->dev, "invalid speed %u\n", speed); + break; + } + + err = clk_set_rate(dwc_priv->clk_tx, rate); + if (err < 0) + { + dev_err(dwc_priv->dev, "failed to set TX rate: %d\n", err); + } +} + +static int dwc_qos_probe(struct platform_device *pdev, + struct plat_stmmacenet_data *plat_dat, + struct stmmac_resources *stmmac_res) +{ + struct dwc_qos_priv *dwc_priv; + int ret; + int err; + u32 hsp_aclk_ctrl_offset; + u32 hsp_aclk_ctrl_regset; + u32 hsp_cfg_ctrl_offset; + u32 eth_axi_lp_ctrl_offset; + u32 eth_phy_ctrl_offset; + u32 eth_phy_ctrl_regset; + u32 rgmiisel_offset; + u32 rgmiisel_regset; + + dwc_priv = devm_kzalloc(&pdev->dev, sizeof(*dwc_priv), GFP_KERNEL); + if (!dwc_priv) + return -ENOMEM; + + if (device_property_read_u32(&pdev->dev, "id", &dwc_priv->dev_id)) { + dev_err(&pdev->dev, "Can not read device id!\n"); + return -EINVAL; + } + + 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; + } + + 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)){ + dev_dbg(&pdev->dev, "rgmiisel not specified\n"); + return -EINVAL; + } + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,led-cfgs", 0, &dwc_priv->phyled_cfgs[0]); + if (ret) { + dev_warn(&pdev->dev, "can't get led cfgs for 1Gbps mode (%d)\n", ret); + } + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,led-cfgs", 1, &dwc_priv->phyled_cfgs[1]); + if (ret) { + dev_warn(&pdev->dev, "can't get led cfgs for 100Mbps mode (%d)\n", ret); + } + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,led-cfgs", 2, &dwc_priv->phyled_cfgs[2]); + if (ret) { + dev_warn(&pdev->dev, "can't get led cfgs for 10Mbps mode (%d)\n", 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); + return ret; + } + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,rgmiisel", 2, &rgmiisel_regset); + if (ret) { + dev_err(&pdev->dev, "can't get rgmiisel_regset (%d)\n", ret); + return ret; + } + + regmap_write(dwc_priv->rgmii_sel, rgmiisel_offset, rgmiisel_regset); + + dwc_priv->crg_regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "eswin,syscrg_csr"); + if (IS_ERR(dwc_priv->crg_regmap)){ + dev_dbg(&pdev->dev, "No syscrg_csr phandle specified\n"); + return 0; + } + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,syscrg_csr", 1, + &hsp_aclk_ctrl_offset); + if (ret) { + dev_err(&pdev->dev, "can't get hsp_aclk_ctrl_offset (%d)\n", ret); + return ret; + } + regmap_read(dwc_priv->crg_regmap, hsp_aclk_ctrl_offset, &hsp_aclk_ctrl_regset); + hsp_aclk_ctrl_regset |= (HSP_ACLK_CLKEN | HSP_ACLK_DIVSOR); + regmap_write(dwc_priv->crg_regmap, hsp_aclk_ctrl_offset, hsp_aclk_ctrl_regset); + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,syscrg_csr", 2, + &hsp_cfg_ctrl_offset); + if (ret) { + dev_err(&pdev->dev, "can't get hsp_cfg_ctrl_offset (%d)\n", ret); + return ret; + } + regmap_write(dwc_priv->crg_regmap, hsp_cfg_ctrl_offset, HSP_CFG_CTRL_REGSET); + + dwc_priv->hsp_regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "eswin,hsp_sp_csr"); + if (IS_ERR(dwc_priv->hsp_regmap)){ + dev_dbg(&pdev->dev, "No hsp_sp_csr phandle specified\n"); + return 0; + } + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,hsp_sp_csr", 2, + ð_phy_ctrl_offset); + if (ret) { + dev_err(&pdev->dev, "can't get eth_phy_ctrl_offset (%d)\n", ret); + return ret; + } + regmap_read(dwc_priv->hsp_regmap, eth_phy_ctrl_offset, ð_phy_ctrl_regset); + eth_phy_ctrl_regset |= (ETH_TX_CLK_SEL | ETH_PHY_INTF_SELI); + regmap_write(dwc_priv->hsp_regmap, eth_phy_ctrl_offset, eth_phy_ctrl_regset); + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,hsp_sp_csr", 3, + ð_axi_lp_ctrl_offset); + if (ret) { + dev_err(&pdev->dev, "can't get eth_axi_lp_ctrl_offset (%d)\n", ret); + return ret; + } + regmap_write(dwc_priv->hsp_regmap, eth_axi_lp_ctrl_offset, ETH_CSYSREQ_VAL); + + dwc_priv->clk_app = devm_clk_get(&pdev->dev, "app"); + if (IS_ERR(dwc_priv->clk_app)) { + dev_err(&pdev->dev, "app clock not found.\n"); + return PTR_ERR(dwc_priv->clk_app); + } + + err = clk_prepare_enable(dwc_priv->clk_app); + if (err < 0) { + dev_err(&pdev->dev, "failed to enable app clock: %d\n", + err); + return err; + } + + dwc_priv->clk_csr = devm_clk_get(&pdev->dev, "csr"); + if (IS_ERR(dwc_priv->clk_csr)) { + dev_err(&pdev->dev, "csr clock not found.\n"); + return PTR_ERR(dwc_priv->clk_csr); + } + + err = clk_prepare_enable(dwc_priv->clk_csr); + if (err < 0) { + dev_err(&pdev->dev, "failed to enable csr clock: %d\n", + err); + return err; + } + + dwc_priv->clk_tx = devm_clk_get(&pdev->dev, "tx"); + if (IS_ERR(plat_dat->pclk)) { + dev_err(&pdev->dev, "tx clock not found.\n"); + return PTR_ERR(dwc_priv->clk_tx); + } + + err = clk_prepare_enable(dwc_priv->clk_tx); + if (err < 0) { + dev_err(&pdev->dev, "failed to enable tx clock: %d\n", + err); + return err; + } + dwc_priv->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, "ethrst"); + if (IS_ERR(dwc_priv->rst)) { + return PTR_ERR(dwc_priv->rst); + } + + ret = reset_control_assert(dwc_priv->rst); + WARN_ON(0 != ret); + ret = reset_control_deassert(dwc_priv->rst); + WARN_ON(0 != ret); + + ret = eic7700_tbu_power(&pdev->dev, true); + if (ret) { + dev_err(&pdev->dev, "failed to power on tbu\n"); + return ret; + } + + plat_dat->fix_mac_speed = dwc_qos_fix_speed; + plat_dat->bsp_priv = dwc_priv; + plat_dat->phy_addr = PHY_ADDR; + + return 0; +} + +static int dwc_qos_remove(struct platform_device *pdev) +{ + int ret; + struct dwc_qos_priv *dwc_priv = get_stmmac_bsp_priv(&pdev->dev); + + ret = eic7700_tbu_power(&pdev->dev, false); + if (ret) { + dev_err(&pdev->dev, "failed to power down tbu\n"); + return ret; + } + + reset_control_assert(dwc_priv->rst); + clk_disable_unprepare(dwc_priv->clk_tx); + clk_disable_unprepare(dwc_priv->clk_csr); + clk_disable_unprepare(dwc_priv->clk_app); + + devm_gpiod_put(&pdev->dev, dwc_priv->phy_reset); + + return 0; +} + +struct dwc_eth_dwmac_data { + int (*probe)(struct platform_device *pdev, + struct plat_stmmacenet_data *data, + struct stmmac_resources *res); + int (*remove)(struct platform_device *pdev); +}; + +static const struct dwc_eth_dwmac_data dwc_qos_data = { + .probe = dwc_qos_probe, + .remove = dwc_qos_remove, +}; + +static int dwc_eth_dwmac_probe(struct platform_device *pdev) +{ + const struct dwc_eth_dwmac_data *data; + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; + struct net_device *ndev = NULL; + struct stmmac_priv *stmpriv = NULL; + struct dwc_qos_priv *dwc_priv = NULL; + int ret; + + data = device_get_match_data(&pdev->dev); + + memset(&stmmac_res, 0, sizeof(struct stmmac_resources)); + + /** + * Since stmmac_platform supports name IRQ only, basic platform + * resource initialization is done in the glue logic. + */ + stmmac_res.irq = platform_get_irq(pdev, 0); + if (stmmac_res.irq < 0) + return stmmac_res.irq; + stmmac_res.wol_irq = stmmac_res.irq; + stmmac_res.addr = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(stmmac_res.addr)) + return PTR_ERR(stmmac_res.addr); + + plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + + ret = data->probe(pdev, plat_dat, &stmmac_res); + if (ret < 0) { + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to probe subdriver: %d\n", + ret); + + goto remove_config; + } + + ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); + if (ret) + goto remove; + + ret = eswin_eth_sid_cfg(&pdev->dev); + if (ret) + goto remove; + + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (ret) + goto remove; + + ndev = dev_get_drvdata(&pdev->dev); + stmpriv = netdev_priv(ndev); + dwc_priv = (struct dwc_qos_priv *)plat_dat->bsp_priv; + dwc_priv->stmpriv = stmpriv; + + return ret; + +remove: + data->remove(pdev); +remove_config: + stmmac_remove_config_dt(pdev, plat_dat); + + return ret; +} + +static int dwc_eth_dwmac_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(ndev); + const struct dwc_eth_dwmac_data *data; + int err; + + data = device_get_match_data(&pdev->dev); + + stmmac_dvr_remove(&pdev->dev); + + err = data->remove(pdev); + if (err < 0) + dev_err(&pdev->dev, "failed to remove subdriver: %d\n", err); + + stmmac_remove_config_dt(pdev, priv->plat); + + return err; +} + +static const struct of_device_id dwc_eth_dwmac_match[] = { + { .compatible = "eswin,eic7700-qos-eth", .data = &dwc_qos_data }, + { } +}; +MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match); + +static struct platform_driver eic7700_eth_dwmac_driver = { + .probe = dwc_eth_dwmac_probe, + .remove = dwc_eth_dwmac_remove, + .driver = { + .name = "eic7700-eth-dwmac", + .pm = &stmmac_pltfr_pm_ops, + .of_match_table = dwc_eth_dwmac_match, + }, +}; +module_platform_driver(eic7700_eth_dwmac_driver); + +MODULE_AUTHOR("Eswin"); +MODULE_DESCRIPTION("Eswin eic7700 qos ethernet driver"); +MODULE_LICENSE("GPL v2"); From 2917741f82c644915db436fb9536db7f6510ebdc Mon Sep 17 00:00:00 2001 From: xuxiang Date: Tue, 30 Jul 2024 11:17:08 +0000 Subject: [PATCH 19/38] drivers: rtc: Added EIC7700 Internal RTC driver Signed-off-by: xuxiang Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/rtc/Kconfig | 9 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-eswin.c | 322 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 332 insertions(+) create mode 100644 drivers/rtc/rtc-eswin.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index d7502433c78aa..5b417410b6313 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -306,6 +306,15 @@ config RTC_DRV_DS1672 This driver can also be built as a module. If so, the module will be called rtc-ds1672. +config RTC_DRV_ESWIN + tristate "eswin EIC7700 RTC" + help + If you say yes here you get support for the eswin EIC7700 real time + clock. + + This driver can also be built as a module, if so, the module + will be called "rtc-eswin". + config RTC_DRV_HYM8563 tristate "Haoyu Microelectronics HYM8563" depends on OF diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index fd209883ee2ef..9a53a6b929900 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_RTC_DRV_DS3232) += rtc-ds3232.o obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o obj-$(CONFIG_RTC_DRV_EM3027) += rtc-em3027.o obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o +obj-$(CONFIG_RTC_DRV_ESWIN) += rtc-eswin.o obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o obj-$(CONFIG_RTC_DRV_FSL_FTM_ALARM) += rtc-fsl-ftm-alarm.o obj-$(CONFIG_RTC_DRV_FTRTC010) += rtc-ftrtc010.o diff --git a/drivers/rtc/rtc-eswin.c b/drivers/rtc/rtc-eswin.c new file mode 100644 index 0000000000000..e83f43baa60de --- /dev/null +++ b/drivers/rtc/rtc-eswin.c @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN rtc 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 . + * + * Author: zhangpengcheng@eswincomputing.com + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RTC_INT_TO_U84 0xffff9fff +/* RTC CSR Registers */ +#define RTC_CCVR 0x00 +#define RTC_CMR 0x04 +#define RTC_CLR 0x08 +#define RTC_CCR 0x0C +#define RTC_CCR_IE BIT(0) +#define RTC_CCR_MASK BIT(1) +#define RTC_CCR_EN BIT(2) +#define RTC_CCR_WEN BIT(3) +#define RTC_CCR_PEN BIT(4) +#define RTC_STAT 0x10 +#define RTC_STAT_BIT BIT(0) +#define RTC_RSTAT 0x14 +#define RTC_EOI 0x18 +#define RTC_VER 0x1C +#define RTC_CPSR 0x20 +#define RTC_CPCVR 0x24 + +struct eswin_rtc_dev { + struct rtc_device *rtc; + struct device *dev; + unsigned long alarm_time; + void __iomem *csr_base; + struct clk *clk; + unsigned int irq_wake; + struct reset_control *rst_rtc; +}; + +static int eswin_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct eswin_rtc_dev *pdata = dev_get_drvdata(dev); + rtc_time64_to_tm(readl(pdata->csr_base + RTC_CCVR), tm); + return rtc_valid_tm(tm); +} + +static int eswin_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct eswin_rtc_dev *pdata = dev_get_drvdata(dev); + unsigned long tr; + + tr = rtc_tm_to_time64(tm); + writel(tr, pdata->csr_base + RTC_CLR); + readl(pdata->csr_base + RTC_CLR); /* Force a barrier */ + + return 0; +} + +static int eswin_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct eswin_rtc_dev *pdata = dev_get_drvdata(dev); + rtc_time64_to_tm(pdata->alarm_time, &alrm->time); + alrm->enabled = readl(pdata->csr_base + RTC_CCR) & RTC_CCR_IE; + + return 0; +} + +static int eswin_rtc_alarm_irq_enable(struct device *dev, u32 enabled) +{ + struct eswin_rtc_dev *pdata = dev_get_drvdata(dev); + u32 ccr; + + ccr = readl(pdata->csr_base + RTC_CCR); + if (enabled) { + ccr &= ~RTC_CCR_MASK; + ccr |= RTC_CCR_IE; + } else { + ccr &= ~RTC_CCR_IE; + ccr |= RTC_CCR_MASK; + } + writel(ccr, pdata->csr_base + RTC_CCR); + + return 0; +} + +static int eswin_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct eswin_rtc_dev *pdata = dev_get_drvdata(dev); + unsigned long rtc_time; + unsigned long alarm_time; + rtc_time = readl(pdata->csr_base + RTC_CCVR); + alarm_time = rtc_tm_to_time64(&alrm->time); + + pdata->alarm_time = alarm_time; + writel((u32) pdata->alarm_time, pdata->csr_base + RTC_CMR); + + eswin_rtc_alarm_irq_enable(dev, alrm->enabled); + + return 0; +} + +static const struct rtc_class_ops eswin_rtc_ops = { + .read_time = eswin_rtc_read_time, + .set_time = eswin_rtc_set_time, + .read_alarm = eswin_rtc_read_alarm, + .set_alarm = eswin_rtc_set_alarm, + .alarm_irq_enable = eswin_rtc_alarm_irq_enable, +}; + +static irqreturn_t eswin_rtc_interrupt(int irq, void *id) +{ + struct eswin_rtc_dev *pdata = (struct eswin_rtc_dev *) id; + /* Check if interrupt asserted */ + if (!(readl(pdata->csr_base + RTC_STAT) & RTC_STAT_BIT)) + return IRQ_NONE; + + /* Clear interrupt */ + readl(pdata->csr_base + RTC_EOI); + + rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF); + + return IRQ_HANDLED; +} + +static int eswin_rtc_probe(struct platform_device *pdev) +{ + struct eswin_rtc_dev *pdata; + struct resource *res; + int ret; + int irq; + unsigned int reg_val; + unsigned int int_off; + unsigned int clk_freq; + struct regmap *regmap; + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + platform_set_drvdata(pdev, pdata); + pdata->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pdata->csr_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pdata->csr_base)) + return PTR_ERR(pdata->csr_base); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "No IRQ resource\n"); + return irq; + } + ret = devm_request_irq(&pdev->dev, irq, eswin_rtc_interrupt, 0, + dev_name(&pdev->dev), pdata); + if (ret) { + dev_err(&pdev->dev, "Could not request IRQ\n"); + return ret; + } + + /* update RTC interrupt to u84 */ + regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "eswin,syscfg"); + if (IS_ERR(regmap)) { + dev_err(&pdev->dev, "No syscfg phandle specified\n"); + return PTR_ERR(regmap); + } + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,syscfg", 1, &int_off); + if (ret) { + dev_err(&pdev->dev, "No rtc interrupt offset found\n"); + return -1; + } + regmap_read(regmap, int_off, ®_val); + reg_val &= (RTC_INT_TO_U84); + regmap_write(regmap, int_off, reg_val); + + ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", &clk_freq); + if (ret) { + dev_err(&pdev->dev, "No rtc clock-frequency found\n"); + } + /* rtc reset init*/ + pdata->rst_rtc = devm_reset_control_get_optional(&pdev->dev, "rtcrst"); + if (IS_ERR_OR_NULL(pdata->rst_rtc)) { + dev_err(&pdev->dev, "Failed to get rtcrst reset handle\n"); + return -EFAULT; + } + + /* get RTC clock */ + pdata->clk = devm_clk_get(&pdev->dev, "rtcclk"); + if (IS_ERR(pdata->clk)) { + dev_err(&pdev->dev, "Couldn't get the clock for RTC\n"); + return -ENODEV; + } + /* Enable the clock */ + clk_prepare_enable(pdata->clk); + if (ret) { + dev_err(&pdev->dev, "failed to enable RTC clock: %d\n", ret); + return -ENODEV; + } + /* reset rtc */ + ret = reset_control_assert(pdata->rst_rtc); + WARN_ON(0 != ret); + ret = reset_control_deassert(pdata->rst_rtc); + WARN_ON(0 != ret); + + /* Turn on the clock and the crystal */ + reg_val = readl(pdata->csr_base + RTC_CCR); + writel(RTC_CCR_EN | reg_val, pdata->csr_base + RTC_CCR); + + /* Turn on the prescaler and set the value */ + writel(clk_freq, pdata->csr_base + RTC_CPSR); + reg_val = readl(pdata->csr_base + RTC_CCR); + writel(RTC_CCR_PEN | reg_val, pdata->csr_base + RTC_CCR); + + device_init_wakeup(&pdev->dev, 1); + + pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, + &eswin_rtc_ops, THIS_MODULE); + if (IS_ERR(pdata->rtc)) { + clk_disable_unprepare(pdata->clk); + return PTR_ERR(pdata->rtc); + } + + return 0; +} + +static int eswin_rtc_remove(struct platform_device *pdev) +{ + struct eswin_rtc_dev *pdata = platform_get_drvdata(pdev); + + eswin_rtc_alarm_irq_enable(&pdev->dev, 0); + device_init_wakeup(&pdev->dev, 0); + clk_disable_unprepare(pdata->clk); + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int eswin_rtc_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct eswin_rtc_dev *pdata = platform_get_drvdata(pdev); + int irq; + + irq = platform_get_irq(pdev, 0); + if (device_may_wakeup(&pdev->dev)) { + if (!enable_irq_wake(irq)) + pdata->irq_wake = 1; + } else { + eswin_rtc_alarm_irq_enable(dev, 0); + clk_disable(pdata->clk); + } + + return 0; +} + +static int eswin_rtc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct eswin_rtc_dev *pdata = platform_get_drvdata(pdev); + int irq; + + irq = platform_get_irq(pdev, 0); + if (device_may_wakeup(&pdev->dev)) { + if (pdata->irq_wake) { + disable_irq_wake(irq); + pdata->irq_wake = 0; + } + } else { + clk_enable(pdata->clk); + eswin_rtc_alarm_irq_enable(dev, 1); + } + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(eswin_rtc_pm_ops, eswin_rtc_suspend, eswin_rtc_resume); + +#ifdef CONFIG_OF +static const struct of_device_id eswin_rtc_of_match[] = { + {.compatible = "eswin,eic7700-rtc" }, + { } +}; +MODULE_DEVICE_TABLE(of, eswin_rtc_of_match); +#endif + +static struct platform_driver eswin_rtc_driver = { + .probe = eswin_rtc_probe, + .remove = eswin_rtc_remove, + .driver = { + .name = "eswin-rtc", + .pm = &eswin_rtc_pm_ops, + .of_match_table = of_match_ptr(eswin_rtc_of_match), + }, +}; + +module_platform_driver(eswin_rtc_driver); + +MODULE_DESCRIPTION("eswin eic7700 RTC driver"); +MODULE_AUTHOR("zhangpengcheng@eswin.com>"); +MODULE_LICENSE("GPL"); From 470c369ba78d5e6bc77ba4190e4c087c90e746f5 Mon Sep 17 00:00:00 2001 From: ningyu Date: Tue, 30 Jul 2024 11:21:30 +0000 Subject: [PATCH 20/38] drivers: bus-error: Added SiFive Bus Error driver Signed-off-by: ningyu Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- arch/riscv/kernel/Makefile | 1 + arch/riscv/kernel/bus_error.c | 132 ++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 arch/riscv/kernel/bus_error.c diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index 03968c06258ce..7a1afa40c69e3 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -59,6 +59,7 @@ obj-y += stacktrace.o obj-y += cacheinfo.o obj-y += patch.o obj-y += probes/ +obj-y += bus_error.o obj-$(CONFIG_MMU) += vdso.o vdso/ obj-$(CONFIG_RISCV_M_MODE) += traps_misaligned.o diff --git a/arch/riscv/kernel/bus_error.c b/arch/riscv/kernel/bus_error.c new file mode 100644 index 0000000000000..67ea83094fed6 --- /dev/null +++ b/arch/riscv/kernel/bus_error.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * BUS error monitor of core 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 . + * + * Authors: Yu Ning + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief Bus error unit register map + * 0x00 : cause of error event + * 0x08 : physical address of error event + * 0x10 : event enable mask + * 0x18 : platform-level interrupt enable mask + * 0x20 : accrued event mask + * 0x28 : hart-local interrupt enable mask + */ + +struct bus_error_device { + struct device *dev; + void __iomem *control; + int plic_irq; +}; + +static irqreturn_t bus_error_handle(int irq, void *dev_id) +{ + struct bus_error_device *bus_err = dev_id; + void __iomem *base = bus_err->control; + + printk(KERN_ERR "bus error of cause event: %d, accrued: 0x%x, physical address: 0x%llx\n", + readl(base),readl(base+0x20),readq(base+0x8)); + + /* clean interrupt */ + writel(0,base); + writel(0,base+0x20); + + return IRQ_HANDLED; +} + +static const struct of_device_id eswin_bus_error_of_match[] = { + {.compatible = "sifive,buserror", }, + { /* sentinel */ } +}; + +static int bus_error_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = pdev->dev.of_node; + struct bus_error_device *bus_err_dev; + int ret; + struct resource *res; + + bus_err_dev = devm_kcalloc(dev, 1, + sizeof(struct bus_error_device), GFP_KERNEL); + if (!bus_err_dev) + return -ENOMEM; + + bus_err_dev->dev = dev; + dev_set_drvdata(dev, bus_err_dev); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "Error while get mem resource\n"); + return -ENODEV; + } + bus_err_dev->control = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR_OR_NULL(bus_err_dev->control)) { + dev_err(dev, "Fail to get resource %s from 0x%llx!\n", + node->name, res->start); + ret = -EINVAL; + goto free_bus_err_dev; + } + bus_err_dev->plic_irq = platform_get_irq(pdev, 0); + ret = devm_request_irq(dev, bus_err_dev->plic_irq, bus_error_handle, + IRQF_SHARED, dev_name(dev), bus_err_dev); + if (ret) { + dev_err(dev, "Fail to request irq %d \n", + (int)bus_err_dev->plic_irq); + return ret; + } + + /* clean any interrupt before */ + writel(0,bus_err_dev->control); + writel(0,bus_err_dev->control+0x20); + + /* enable interrupt */ + writel(0xee2,bus_err_dev->control+0x18); + writel(0xee2,bus_err_dev->control+0x10); + dev_dbg(dev, "Bus-err unit init OK\n"); + return 0; + +free_bus_err_dev: + return ret; + +} + +static struct platform_driver bus_error_driver = { + .probe = bus_error_probe, + .driver = { + .name = "buserror", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(eswin_bus_error_of_match),}, +}; + +static int __init init_bus_error_unit(void) +{ + return platform_driver_register(&bus_error_driver); +} + +subsys_initcall(init_bus_error_unit); From 2fd4fff4e513ae11f672b357edfa669bf0e49668 Mon Sep 17 00:00:00 2001 From: luyulin Date: Tue, 30 Jul 2024 11:27:26 +0000 Subject: [PATCH 21/38] drivers: ata: Add ESWIN sata driver Signed-off-by: luyulin Signed-off-by: Pritesh Patel --- drivers/ata/Kconfig | 9 + drivers/ata/Makefile | 1 + drivers/ata/ahci_eswin.c | 344 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+) create mode 100644 drivers/ata/ahci_eswin.c diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 42b51c9812a0e..4761bf0d39d14 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -216,6 +216,15 @@ config AHCI_CEVA If unsure, say N. +config AHCI_ESWIN + tristate "Eswin AHCI SATA support" + select SATA_HOST + help + This option enables support for Eswin AHCI Serial ATA + controllers. + + If unsure, say N. + config AHCI_MTK tristate "MediaTek AHCI SATA support" depends on ARCH_MEDIATEK || COMPILE_TEST diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 20e6645ab7371..515e62a23ae7e 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_AHCI_CEVA) += ahci_ceva.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_DA850) += ahci_da850.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_DM816) += ahci_dm816.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_DWC) += ahci_dwc.o libahci.o libahci_platform.o +obj-$(CONFIG_AHCI_ESWIN) += ahci_eswin.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_MTK) += ahci_mtk.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o libahci.o libahci_platform.o diff --git a/drivers/ata/ahci_eswin.c b/drivers/ata/ahci_eswin.c new file mode 100644 index 0000000000000..0bc04cd2d8ba0 --- /dev/null +++ b/drivers/ata/ahci_eswin.c @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN AHCI SATA 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 . + * + * Authors: Yulin Lu + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ahci.h" + +#define DRV_NAME "ahci" + +#define AWSMMUSID GENMASK(31, 24) // The sid of write operation +#define AWSMMUSSID GENMASK(23, 16) // The ssid of write operation +#define ARSMMUSID GENMASK(15, 8) // The sid of read operation +#define ARSMMUSSID GENMASK(7, 0) // The ssid of read operation +#define SATA_REF_CTRL1 0x338 +#define SATA_PHY_CTRL0 0x328 +#define SATA_PHY_CTRL1 0x32c +#define SATA_LOS_IDEN 0x33c +#define SATA_AXI_LP_CTRL 0x308 +#define SATA_REG_CTRL 0x334 +#define SATA_MPLL_CTRL 0x320 +#define SATA_RESET_CTRL 0x340 +#define SATA_RESET_CTRL_ASSERT 0x3 +#define SATA_RESET_CTRL_DEASSERT 0x0 +#define SATA_PHY_RESET BIT(0) +#define SATA_P0_RESET BIT(1) +#define SATA_LOS_LEVEL 0x9 +#define SATA_LOS_BIAS (0x02 << 16) +#define SATA_REF_REPEATCLK_EN BIT(0) +#define SATA_REF_USE_PAD BIT(20) +#define SATA_P0_AMPLITUDE_GEN1 0x42 +#define SATA_P0_AMPLITUDE_GEN2 (0x46 << 8) +#define SATA_P0_AMPLITUDE_GEN3 (0x73 << 16) +#define SATA_P0_PHY_TX_PREEMPH_GEN1 0x05 +#define SATA_P0_PHY_TX_PREEMPH_GEN2 (0x05 << 8) +#define SATA_P0_PHY_TX_PREEMPH_GEN3 (0x23 << 16) +#define SATA_MPLL_MULTIPLIER (0x3c << 16) +#define SATA_M_CSYSREQ BIT(0) +#define SATA_S_CSYSREQ BIT(16) +#define HSPDME_RST_CTRL 0x41C +#define SW_HSP_SATA_ARSTN BIT(27) +#define SW_SATA_RSTN (0xf << 9) + +static const struct ata_port_info ahci_port_info = { + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_platform_ops, +}; + +static const struct ata_port_info ahci_port_info_nolpm = { + .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_LPM, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_platform_ops, +}; + +static struct scsi_host_template ahci_platform_sht = { + AHCI_SHT(DRV_NAME), +}; + +static int eswin_sata_sid_cfg(struct device *dev) +{ + int ret; + struct regmap *regmap; + int hsp_mmu_sata_reg; + u32 rdwr_sid_ssid; + u32 sid; + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + + /* not behind smmu, use the default reset value(0x0) of the reg as streamID*/ + if (fwspec == NULL) { + dev_dbg(dev, "dev is not behind smmu, skip configuration of sid\n"); + return 0; + } + sid = fwspec->ids[0]; + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,hsp_sp_csr"); + if (IS_ERR(regmap)) { + dev_dbg(dev, "No hsp_sp_csr phandle specified\n"); + return 0; + } + ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 1, + &hsp_mmu_sata_reg); + if (ret) { + dev_err(dev, "can't get sata sid cfg reg offset (%d)\n", ret); + return ret; + } + + /* make the reading sid the same as writing sid, ssid is fixed to zero */ + rdwr_sid_ssid = FIELD_PREP(AWSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(AWSMMUSSID, 0); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSSID, 0); + regmap_write(regmap, hsp_mmu_sata_reg, rdwr_sid_ssid); + + ret = eic7700_dynm_sid_enable(dev_to_node(dev)); + if (ret < 0) + dev_err(dev, "failed to config sata streamID(%d)!\n", sid); + else + dev_dbg(dev, "success to config sata streamID(%d)!\n", sid); + pr_err("eswin_sata_sid_cfg success\n"); + + return ret; +} + +static int eswin_sata_init(struct device *dev) +{ + struct regmap *regmap; + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,hsp_sp_csr"); + if (IS_ERR(regmap)) { + dev_dbg(dev, "No hsp_sp_csr phandle specified\n"); + return -1; + } + regmap_write(regmap, SATA_REF_CTRL1, 0x1); + regmap_write(regmap, SATA_PHY_CTRL0, (SATA_P0_AMPLITUDE_GEN1|SATA_P0_AMPLITUDE_GEN2|SATA_P0_AMPLITUDE_GEN3)); + regmap_write(regmap, SATA_PHY_CTRL1, (SATA_P0_PHY_TX_PREEMPH_GEN1|SATA_P0_PHY_TX_PREEMPH_GEN2|SATA_P0_PHY_TX_PREEMPH_GEN3)); + regmap_write(regmap, SATA_LOS_IDEN, SATA_LOS_LEVEL|SATA_LOS_BIAS); + regmap_write(regmap, SATA_AXI_LP_CTRL, (SATA_M_CSYSREQ|SATA_S_CSYSREQ)); + regmap_write(regmap, SATA_REG_CTRL, (SATA_REF_REPEATCLK_EN|SATA_REF_USE_PAD)); + regmap_write(regmap, SATA_MPLL_CTRL, SATA_MPLL_MULTIPLIER); + regmap_write(regmap, SATA_RESET_CTRL, 0x0); + + return 0; +} + +static int __init eswin_reset(struct device *dev) +{ + struct reset_control *asic0_rst; + struct reset_control *oob_rst; + struct reset_control *pmalive_rst; + struct reset_control *rbc_rst; + struct reset_control *apb_rst; + int rc; + + asic0_rst = devm_reset_control_get_shared(dev, "asic0"); + if (IS_ERR_OR_NULL(asic0_rst)) { + dev_err(dev, "Failed to asic0_rst handle\n"); + return -EFAULT; + } + oob_rst = devm_reset_control_get_shared(dev, "oob"); + if (IS_ERR_OR_NULL(oob_rst)) { + dev_err(dev, "Failed to oob_rst handle\n"); + return -EFAULT; + } + pmalive_rst = devm_reset_control_get_shared(dev, "pmalive"); + if (IS_ERR_OR_NULL(pmalive_rst)) { + dev_err(dev, "Failed to pmalive_rst handle\n"); + return -EFAULT; + } + rbc_rst = devm_reset_control_get_shared(dev, "rbc"); + if (IS_ERR_OR_NULL(rbc_rst)) { + dev_err(dev, "Failed to rbc_rst handle\n"); + return -EFAULT; + } + apb_rst = devm_reset_control_get_shared(dev, "apb"); + if (IS_ERR_OR_NULL(apb_rst)) { + dev_err(dev, "Failed to apb_rst handle\n"); + return -EFAULT; + } + + if (asic0_rst) { + rc = reset_control_deassert(asic0_rst); + WARN_ON(0 != rc); + } + if (oob_rst) { + rc = reset_control_deassert(oob_rst); + WARN_ON(0 != rc); + } + if (pmalive_rst) { + rc = reset_control_deassert(pmalive_rst); + WARN_ON(0 != rc); + } + if (rbc_rst) { + rc = reset_control_deassert(rbc_rst); + WARN_ON(0 != rc); + } + if (apb_rst) { + rc = reset_control_deassert(apb_rst); + WARN_ON(0 != rc); + } + + return 0; +} + + +static int eswin_unreset(struct device *dev) +{ + struct reset_control *asic0_rst; + struct reset_control *oob_rst; + struct reset_control *pmalive_rst; + struct reset_control *rbc_rst; + int rc; + + asic0_rst = devm_reset_control_get_shared(dev, "asic0"); + if (IS_ERR_OR_NULL(asic0_rst)) { + dev_err(dev, "Failed to asic0_rst handle\n"); + return -EFAULT; + } + oob_rst = devm_reset_control_get_shared(dev, "oob"); + if (IS_ERR_OR_NULL(oob_rst)) { + dev_err(dev, "Failed to oob_rst handle\n"); + return -EFAULT; + } + pmalive_rst = devm_reset_control_get_shared(dev, "pmalive"); + if (IS_ERR_OR_NULL(pmalive_rst)) { + dev_err(dev, "Failed to pmalive_rst handle\n"); + return -EFAULT; + } + rbc_rst = devm_reset_control_get_shared(dev, "rbc"); + if (IS_ERR_OR_NULL(rbc_rst)) { + dev_err(dev, "Failed to rbc_rst handle\n"); + return -EFAULT; + } + if (asic0_rst) { + rc = reset_control_assert(asic0_rst); + WARN_ON(0 != rc); + } + if (oob_rst) { + rc = reset_control_assert(oob_rst); + WARN_ON(0 != rc); + } + if (pmalive_rst) { + rc = reset_control_assert(pmalive_rst); + WARN_ON(0 != rc); + } + if (rbc_rst) { + rc = reset_control_assert(rbc_rst); + WARN_ON(0 != rc); + } + +return 0; +} + +static int ahci_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct ahci_host_priv *hpriv; + const struct ata_port_info *port; + int rc; + + hpriv = ahci_platform_get_resources(pdev, + 0); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + + rc = eswin_reset(dev); + if (rc) + return rc; + eswin_sata_init(dev); + eswin_sata_sid_cfg(dev); + eic7700_tbu_power(&pdev->dev, true); + rc = dma_set_mask_and_coherent(dev,DMA_BIT_MASK(64)); + + if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci")) + hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ; + + port = acpi_device_get_match_data(dev); + if (!port){ + port = &ahci_port_info; + } + rc = ahci_platform_init_host(pdev, hpriv, port, + &ahci_platform_sht); + if (rc) + goto disable_resources; + + return 0; + +disable_resources: + ahci_platform_disable_resources(hpriv); + return rc; +} + +static void ahci_remove(struct platform_device *pdev) +{ + eic7700_tbu_power(&pdev->dev, false); + eswin_unreset(&pdev->dev); + + ata_platform_remove_one(pdev); +} + +static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, + ahci_platform_resume); + +static const struct of_device_id ahci_of_match[] = { + { .compatible = "snps,eswin-ahci", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ahci_of_match); + +static const struct acpi_device_id ahci_acpi_match[] = { + { "APMC0D33", (unsigned long)&ahci_port_info_nolpm }, + { ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, ahci_acpi_match); + +static struct platform_driver ahci_driver = { + .probe = ahci_probe, + .remove_new = ahci_remove, + .shutdown = ahci_platform_shutdown, + .driver = { + .name = DRV_NAME, + .of_match_table = ahci_of_match, + .acpi_match_table = ahci_acpi_match, + .pm = &ahci_pm_ops, + }, +}; +module_platform_driver(ahci_driver); + +MODULE_DESCRIPTION("ESWIN AHCI SATA driver"); +MODULE_AUTHOR("Lu Yulin "); +MODULE_LICENSE("GPL"); From e96b2c307f2113690df51a99c36b71b8ead27e9f Mon Sep 17 00:00:00 2001 From: denglei Date: Tue, 30 Jul 2024 11:57:29 +0000 Subject: [PATCH 22/38] drivers: audio: Added audio drivers Add custom ES8328 audio codec driver for hifive premier p550 board Add eswin i2s driver Signed-off-by: denglei Signed-off-by: Pinkesh Vaghela --- include/sound/dmaengine_pcm.h | 3 + sound/core/pcm_dmaengine.c | 9 +- sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/codecs/Kconfig | 1 + sound/soc/codecs/Makefile | 1 + sound/soc/codecs/eswin/Kconfig | 20 + sound/soc/codecs/eswin/Makefile | 3 + sound/soc/codecs/eswin/es8328-i2c.c | 64 ++ sound/soc/codecs/eswin/es8328.c | 1005 ++++++++++++++++++++++++ sound/soc/codecs/eswin/es8328.h | 301 +++++++ sound/soc/eswin/Kconfig | 10 + sound/soc/eswin/Makefile | 5 + sound/soc/eswin/es-audio-proc.c | 488 ++++++++++++ sound/soc/eswin/es-audio-proc.h | 23 + sound/soc/eswin/i2s-stereo.c | 1036 +++++++++++++++++++++++++ sound/soc/eswin/i2s.h | 216 ++++++ sound/soc/generic/audio-graph-card.c | 3 + sound/soc/soc-generic-dmaengine-pcm.c | 88 +++ 19 files changed, 3277 insertions(+), 1 deletion(-) create mode 100755 sound/soc/codecs/eswin/Kconfig create mode 100755 sound/soc/codecs/eswin/Makefile create mode 100644 sound/soc/codecs/eswin/es8328-i2c.c create mode 100644 sound/soc/codecs/eswin/es8328.c create mode 100644 sound/soc/codecs/eswin/es8328.h create mode 100644 sound/soc/eswin/Kconfig create mode 100644 sound/soc/eswin/Makefile create mode 100644 sound/soc/eswin/es-audio-proc.c create mode 100644 sound/soc/eswin/es-audio-proc.h create mode 100755 sound/soc/eswin/i2s-stereo.c create mode 100644 sound/soc/eswin/i2s.h diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index d70c55f17df7c..81eb124231d80 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -171,6 +171,9 @@ struct dmaengine_pcm { const struct snd_dmaengine_pcm_config *config; struct snd_soc_component component; unsigned int flags; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + void *tmp_buf[2]; +#endif }; static inline struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p) diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 494ec0c207fad..cb13314f3ac06 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -159,11 +159,18 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) flags |= DMA_PREP_INTERRUPT; prtd->pos = 0; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + 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); +#else desc = dmaengine_prep_dma_cyclic(chan, substream->runtime->dma_addr, snd_pcm_lib_buffer_bytes(substream), snd_pcm_lib_period_bytes(substream), direction, flags); - +#endif if (!desc) return -ENOMEM; diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 439fa631c342a..24ee3416d6a67 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -85,6 +85,7 @@ source "sound/soc/au1x/Kconfig" source "sound/soc/bcm/Kconfig" source "sound/soc/cirrus/Kconfig" source "sound/soc/dwc/Kconfig" +source "sound/soc/eswin/Kconfig" source "sound/soc/fsl/Kconfig" source "sound/soc/google/Kconfig" source "sound/soc/hisilicon/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 8376fdb217ed1..d36d824db893f 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_SND_SOC) += au1x/ obj-$(CONFIG_SND_SOC) += bcm/ obj-$(CONFIG_SND_SOC) += cirrus/ obj-$(CONFIG_SND_SOC) += dwc/ +obj-$(CONFIG_SND_SOC) += eswin/ obj-$(CONFIG_SND_SOC) += fsl/ obj-$(CONFIG_SND_SOC) += google/ obj-$(CONFIG_SND_SOC) += hisilicon/ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index f1e1dbc509f6e..319d894772798 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2404,4 +2404,5 @@ config SND_SOC_LPASS_TX_MACRO select SND_SOC_LPASS_MACRO_COMMON tristate "Qualcomm TX Macro in LPASS(Low Power Audio SubSystem)" +source "sound/soc/codecs/eswin/Kconfig" endmenu diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index a87e56938ce58..6205558e39fe9 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -772,3 +772,4 @@ obj-$(CONFIG_SND_SOC_LPASS_TX_MACRO) += snd-soc-lpass-tx-macro.o # Mux obj-$(CONFIG_SND_SOC_SIMPLE_MUX) += snd-soc-simple-mux.o +obj-$(CONFIG_ESWIN_SND_SOC_CODECS) += eswin/ diff --git a/sound/soc/codecs/eswin/Kconfig b/sound/soc/codecs/eswin/Kconfig new file mode 100755 index 0000000000000..1c4a45508d64b --- /dev/null +++ b/sound/soc/codecs/eswin/Kconfig @@ -0,0 +1,20 @@ +menuconfig ESWIN_SND_SOC_CODECS + bool "ESWIN CODEC drivers" + default n + help + Say Y or M if you want to add support for codecs attached to + the ESWIN Asoc interface. You will also need + to select the audio interfaces to support below. + +#if ESWIN_SND_SOC_CODECS + +config ESWIN_SND_ES8388_CODEC + bool "ESWIN Audio es8388 codec" + depends on ESWIN_SND_SOC_CODECS + default n + help + ESWIN Audio codec, + es8388 codec, + this codec is internal + +#endif #ESWIN_SND_SOC_CODECS diff --git a/sound/soc/codecs/eswin/Makefile b/sound/soc/codecs/eswin/Makefile new file mode 100755 index 0000000000000..a4ec4f0a622be --- /dev/null +++ b/sound/soc/codecs/eswin/Makefile @@ -0,0 +1,3 @@ +esw_es8328_codec-objs := es8328-i2c.o es8328.o + +obj-$(CONFIG_ESWIN_SND_ES8388_CODEC) += esw_es8328_codec.o diff --git a/sound/soc/codecs/eswin/es8328-i2c.c b/sound/soc/codecs/eswin/es8328-i2c.c new file mode 100644 index 0000000000000..d62627ec2dae0 --- /dev/null +++ b/sound/soc/codecs/eswin/es8328-i2c.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Codec root complex 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 . + * + * Authors: Lei Deng + */ + +#include +#include +#include + +#include + +#include "es8328.h" + +static const struct i2c_device_id es8328_id[] = { + { "es8328", 0 }, + { "es8388", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, es8328_id); + +static const struct of_device_id es8328_of_match[] = { + { .compatible = "eswin,es8388", }, + { } +}; +MODULE_DEVICE_TABLE(of, es8328_of_match); + +static int es8328_i2c_probe(struct i2c_client *i2c) +{ + dev_info(&i2c->dev, "dev name:%s\n", i2c->dev.of_node->name); + return es8328_probe(&i2c->dev, + devm_regmap_init_i2c(i2c, &es8328_regmap_config)); +} + +static struct i2c_driver es8328_i2c_driver = { + .driver = { + .name = "es8328", + .of_match_table = es8328_of_match, + }, + .probe = es8328_i2c_probe, + .id_table = es8328_id, +}; + +module_i2c_driver(es8328_i2c_driver); + +MODULE_DESCRIPTION("ASoC ES8328 audio CODEC I2C driver"); +MODULE_AUTHOR("Sean Cross "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/eswin/es8328.c b/sound/soc/codecs/eswin/es8328.c new file mode 100644 index 0000000000000..1c89066df7311 --- /dev/null +++ b/sound/soc/codecs/eswin/es8328.c @@ -0,0 +1,1005 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Codec root complex 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 . + * + * Authors: Lei Deng + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "es8328.h" + +static const unsigned int rates_12288[] = { + 8000, 12000, 16000, 24000, 32000, 48000, 96000, +}; + +static const int ratios_12288[] = { + 10, 7, 6, 4, 3, 2, 0, +}; + +static const struct snd_pcm_hw_constraint_list constraints_12288 = { + .count = ARRAY_SIZE(rates_12288), + .list = rates_12288, +}; + +static const unsigned int rates_11289[] = { + 8018, 11025, 22050, 44100, 88200, +}; + +static const int ratios_11289[] = { + 9, 7, 4, 2, 0, +}; + +static const struct snd_pcm_hw_constraint_list constraints_11289 = { + .count = ARRAY_SIZE(rates_11289), + .list = rates_11289, +}; + +/* regulator supplies for sgtl5000, VDDD is an optional external supply */ +enum sgtl5000_regulator_supplies { + DVDD, + AVDD, + PVDD, + HPVDD, + ES8328_SUPPLY_NUM +}; + +#define ES8328_RATES (SNDRV_PCM_RATE_192000 | \ + SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_88200 | \ + SNDRV_PCM_RATE_8000_48000) +#define ES8328_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S18_3LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +struct es8328_priv { + struct regmap *regmap; + struct clk *clk; + int playback_fs; + bool deemph; + int mclkdiv2; + const struct snd_pcm_hw_constraint_list *sysclk_constraints; + const int *mclk_ratios; + bool provider; + struct regulator_bulk_data supplies[ES8328_SUPPLY_NUM]; +}; + +/* + * ES8328 Controls + */ + +static const char * const adcpol_txt[] = {"Normal", "L Invert", "R Invert", + "L + R Invert"}; +static SOC_ENUM_SINGLE_DECL(adcpol, + ES8328_ADCCONTROL6, 6, adcpol_txt); + +static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0); +static const DECLARE_TLV_DB_SCALE(dac_adc_tlv, -9600, 50, 0); +static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); +static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0); + +static const struct { + int rate; + unsigned int val; +} deemph_settings[] = { + { 0, ES8328_DACCONTROL6_DEEMPH_OFF }, + { 32000, ES8328_DACCONTROL6_DEEMPH_32k }, + { 44100, ES8328_DACCONTROL6_DEEMPH_44_1k }, + { 48000, ES8328_DACCONTROL6_DEEMPH_48k }, +}; + +static int es8328_set_deemph(struct snd_soc_component *component) +{ + struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component); + int val, i, best; + + /* + * If we're using deemphasis select the nearest available sample + * rate. + */ + if (es8328->deemph) { + best = 0; + for (i = 1; i < ARRAY_SIZE(deemph_settings); i++) { + if (abs(deemph_settings[i].rate - es8328->playback_fs) < + abs(deemph_settings[best].rate - es8328->playback_fs)) + best = i; + } + + val = deemph_settings[best].val; + } else { + val = ES8328_DACCONTROL6_DEEMPH_OFF; + } + + dev_dbg(component->dev, "Set deemphasis %d\n", val); + + return snd_soc_component_update_bits(component, ES8328_DACCONTROL6, + ES8328_DACCONTROL6_DEEMPH_MASK, val); +} + +static int es8328_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = es8328->deemph; + return 0; +} + +static int es8328_put_deemph(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component); + unsigned int deemph = ucontrol->value.integer.value[0]; + int ret; + + if (deemph > 1) + return -EINVAL; + + if (es8328->deemph == deemph) + return 0; + ret = es8328_set_deemph(component); + if (ret < 0) + return ret; + + es8328->deemph = deemph; + + return 1; +} +static int dump_flag = 0; +static u32 g_reg = 1; +static u32 g_get_cnt = 0; +static u32 g_put_cnt = 0; + +int esw_codec_dump_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = dump_flag; + return 0; +} + +int esw_codec_dump_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +int esw_codec_dump_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int dump_onoff = ucontrol->value.integer.value[0]; + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + u32 reg, ret, i; + + printk("codec dump onoff:%d\n", dump_onoff); + dump_flag = dump_onoff; + if (dump_onoff == true) { + printk("statr codec dump\n"); + for (i = 0; i < 53; i++) { + ret = regmap_read(component->regmap, i, ®); + if (ret != 0) { + printk("reag reg[%d] failed!\n", i); + } + printk("reg[%d]:0x%x\n", i, reg); + } + } + return 0; +} + +int esw_codec_reg_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + u32 val; + int ret; + + g_get_cnt++; + + if (g_get_cnt == 1) { + ucontrol->value.integer.value[0] = g_reg; + } else { + ret = regmap_read(component->regmap, g_reg, &val); + if (ret != 0) { + printk("read reg[%d] failed!\n", g_reg); + } + printk("codec read reg[%d]:0x%x\n", g_reg, val); + ucontrol->value.integer.value[1] = val; + g_get_cnt = 0; + } + return 0; +} + +int esw_codec_reg_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 256; + return 0; +} + +int esw_codec_reg_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret; + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + + g_put_cnt++; + + if (g_put_cnt == 1) { + g_reg = ucontrol->value.integer.value[0]; + } else { + printk("codec write reg:%d, val:0x%x\n", g_reg, (u32)ucontrol->value.integer.value[1]); + ret = regmap_write(component->regmap, g_reg, (u32)ucontrol->value.integer.value[1]); + if (ret != 0) { + printk("write reg[%d] failed!\n", g_reg); + } + g_put_cnt = 0; + } + + return 0; +} + +static const struct snd_kcontrol_new es8328_snd_controls[] = { + SOC_DOUBLE_R_TLV("Capture Digital Volume", + ES8328_ADCCONTROL8, ES8328_ADCCONTROL9, + 0, 0xc0, 1, dac_adc_tlv), + SOC_SINGLE("Capture ZC Switch", ES8328_ADCCONTROL7, 5, 1, 0), + + SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, + es8328_get_deemph, es8328_put_deemph), + + SOC_ENUM("Capture Polarity", adcpol), + + SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", + ES8328_DACCONTROL17, 3, 7, 1, bypass_tlv), + SOC_SINGLE_TLV("Left Mixer Right Bypass Volume", + ES8328_DACCONTROL19, 3, 7, 1, bypass_tlv), + SOC_SINGLE_TLV("Right Mixer Left Bypass Volume", + ES8328_DACCONTROL18, 3, 7, 1, bypass_tlv), + SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", + ES8328_DACCONTROL20, 3, 7, 1, bypass_tlv), + + SOC_DOUBLE_R_TLV("PCM Volume", + ES8328_LDACVOL, ES8328_RDACVOL, + 0, ES8328_LDACVOL_MAX, 1, dac_adc_tlv), + + SOC_DOUBLE_R_TLV("Output 1 Playback Volume", + ES8328_LOUT1VOL, ES8328_ROUT1VOL, + 0, ES8328_OUT1VOL_MAX, 0, play_tlv), + + SOC_DOUBLE_R_TLV("Output 2 Playback Volume", + ES8328_LOUT2VOL, ES8328_ROUT2VOL, + 0, ES8328_OUT2VOL_MAX, 0, play_tlv), + + SOC_DOUBLE_TLV("Mic PGA Volume", ES8328_ADCCONTROL1, + 4, 0, 8, 0, mic_tlv), + { + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .name = "Reg Dump", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = esw_codec_dump_info, + .get = esw_codec_dump_get, + .put = esw_codec_dump_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Reg Write", + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = esw_codec_reg_info, + .get = esw_codec_reg_get, + .put = esw_codec_reg_put, + } +}; + +/* + * DAPM Controls + */ + +static const char * const es8328_line_texts[] = { + "Line 1", "Line 2", "PGA", "Differential"}; + +static const struct soc_enum es8328_lline_enum = + SOC_ENUM_SINGLE(ES8328_DACCONTROL16, 3, + ARRAY_SIZE(es8328_line_texts), + es8328_line_texts); +static const struct snd_kcontrol_new es8328_left_line_controls = + SOC_DAPM_ENUM("Route", es8328_lline_enum); + +static const struct soc_enum es8328_rline_enum = + SOC_ENUM_SINGLE(ES8328_DACCONTROL16, 0, + ARRAY_SIZE(es8328_line_texts), + es8328_line_texts); +static const struct snd_kcontrol_new es8328_right_line_controls = + SOC_DAPM_ENUM("Route", es8328_rline_enum); + +/* Left Mixer */ +static const struct snd_kcontrol_new es8328_left_mixer_controls[] = { + SOC_DAPM_SINGLE("Playback Switch", ES8328_DACCONTROL17, 7, 1, 0), + SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL17, 6, 1, 0), + SOC_DAPM_SINGLE("Right Playback Switch", ES8328_DACCONTROL18, 7, 1, 0), + SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL18, 6, 1, 0), +}; + +/* Right Mixer */ +static const struct snd_kcontrol_new es8328_right_mixer_controls[] = { + SOC_DAPM_SINGLE("Left Playback Switch", ES8328_DACCONTROL19, 7, 1, 0), + SOC_DAPM_SINGLE("Left Bypass Switch", ES8328_DACCONTROL19, 6, 1, 0), + SOC_DAPM_SINGLE("Playback Switch", ES8328_DACCONTROL20, 7, 1, 0), + SOC_DAPM_SINGLE("Right Bypass Switch", ES8328_DACCONTROL20, 6, 1, 0), +}; + +static const char * const es8328_pga_sel[] = { + "Line 1", "Line 2", "Line 3", "Differential"}; + +/* Left PGA Mux */ +static const struct soc_enum es8328_lpga_enum = + SOC_ENUM_SINGLE(ES8328_ADCCONTROL2, 6, + ARRAY_SIZE(es8328_pga_sel), + es8328_pga_sel); +static const struct snd_kcontrol_new es8328_left_pga_controls = + SOC_DAPM_ENUM("Route", es8328_lpga_enum); + +/* Right PGA Mux */ +static const struct soc_enum es8328_rpga_enum = + SOC_ENUM_SINGLE(ES8328_ADCCONTROL2, 4, + ARRAY_SIZE(es8328_pga_sel), + es8328_pga_sel); +static const struct snd_kcontrol_new es8328_right_pga_controls = + SOC_DAPM_ENUM("Route", es8328_rpga_enum); + +/* Differential Mux */ +static const char * const es8328_diff_sel[] = {"Line 1", "Line 2"}; +static SOC_ENUM_SINGLE_DECL(diffmux, + ES8328_ADCCONTROL3, 7, es8328_diff_sel); +static const struct snd_kcontrol_new es8328_diffmux_controls = + SOC_DAPM_ENUM("Route", diffmux); + +/* Mono ADC Mux */ +static const char * const es8328_mono_mux[] = {"Stereo", "Mono (Left)", + "Mono (Right)", "Digital Mono"}; +static SOC_ENUM_SINGLE_DECL(monomux, + ES8328_ADCCONTROL3, 3, es8328_mono_mux); +static const struct snd_kcontrol_new es8328_monomux_controls = + SOC_DAPM_ENUM("Route", monomux); + +static const struct snd_soc_dapm_widget es8328_dapm_widgets[] = { + SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, + &es8328_diffmux_controls), + SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0, + &es8328_monomux_controls), + SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0, + &es8328_monomux_controls), + + SND_SOC_DAPM_MUX("Left PGA Mux", ES8328_ADCPOWER, + ES8328_ADCPOWER_AINL_OFF, 1, + &es8328_left_pga_controls), + SND_SOC_DAPM_MUX("Right PGA Mux", ES8328_ADCPOWER, + ES8328_ADCPOWER_AINR_OFF, 1, + &es8328_right_pga_controls), + + SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0, + &es8328_left_line_controls), + SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0, + &es8328_right_line_controls), + + SND_SOC_DAPM_ADC("Right ADC", "Right Capture", ES8328_ADCPOWER, + ES8328_ADCPOWER_ADCR_OFF, 1), + SND_SOC_DAPM_ADC("Left ADC", "Left Capture", ES8328_ADCPOWER, + ES8328_ADCPOWER_ADCL_OFF, 1), + + SND_SOC_DAPM_SUPPLY("Mic Bias", ES8328_ADCPOWER, + ES8328_ADCPOWER_MIC_BIAS_OFF, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY("Mic Bias Gen", ES8328_ADCPOWER, + ES8328_ADCPOWER_ADC_BIAS_GEN_OFF, 1, NULL, 0), + + SND_SOC_DAPM_SUPPLY("DAC STM", ES8328_CHIPPOWER, + ES8328_CHIPPOWER_DACSTM_RESET, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC STM", ES8328_CHIPPOWER, + ES8328_CHIPPOWER_ADCSTM_RESET, 1, NULL, 0), + + SND_SOC_DAPM_SUPPLY("DAC DIG", ES8328_CHIPPOWER, + ES8328_CHIPPOWER_DACDIG_OFF, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC DIG", ES8328_CHIPPOWER, + ES8328_CHIPPOWER_ADCDIG_OFF, 1, NULL, 0), + + SND_SOC_DAPM_SUPPLY("DAC DLL", ES8328_CHIPPOWER, + ES8328_CHIPPOWER_DACDLL_OFF, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC DLL", ES8328_CHIPPOWER, + ES8328_CHIPPOWER_ADCDLL_OFF, 1, NULL, 0), + + SND_SOC_DAPM_SUPPLY("ADC Vref", ES8328_CHIPPOWER, + ES8328_CHIPPOWER_ADCVREF_OFF, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC Vref", ES8328_CHIPPOWER, + ES8328_CHIPPOWER_DACVREF_OFF, 1, NULL, 0), + + SND_SOC_DAPM_DAC("Right DAC", "Right Playback", ES8328_DACPOWER, + ES8328_DACPOWER_RDAC_OFF, 1), + SND_SOC_DAPM_DAC("Left DAC", "Left Playback", ES8328_DACPOWER, + ES8328_DACPOWER_LDAC_OFF, 1), + + SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, + &es8328_left_mixer_controls[0], + ARRAY_SIZE(es8328_left_mixer_controls)), + SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0, + &es8328_right_mixer_controls[0], + ARRAY_SIZE(es8328_right_mixer_controls)), + + SND_SOC_DAPM_PGA("Right Out 2", ES8328_DACPOWER, + ES8328_DACPOWER_ROUT2_ON, 0, NULL, 0), + SND_SOC_DAPM_PGA("Left Out 2", ES8328_DACPOWER, + ES8328_DACPOWER_LOUT2_ON, 0, NULL, 0), + SND_SOC_DAPM_PGA("Right Out 1", ES8328_DACPOWER, + ES8328_DACPOWER_ROUT1_ON, 0, NULL, 0), + SND_SOC_DAPM_PGA("Left Out 1", ES8328_DACPOWER, + ES8328_DACPOWER_LOUT1_ON, 0, NULL, 0), + + SND_SOC_DAPM_OUTPUT("LOUT1"), + SND_SOC_DAPM_OUTPUT("ROUT1"), + SND_SOC_DAPM_OUTPUT("LOUT2"), + SND_SOC_DAPM_OUTPUT("ROUT2"), + + SND_SOC_DAPM_INPUT("LINPUT1"), + SND_SOC_DAPM_INPUT("LINPUT2"), + SND_SOC_DAPM_INPUT("RINPUT1"), + SND_SOC_DAPM_INPUT("RINPUT2"), +}; + +static const struct snd_soc_dapm_route es8328_dapm_routes[] = { + + { "Left Line Mux", "Line 1", "LINPUT1" }, + { "Left Line Mux", "Line 2", "LINPUT2" }, + { "Left Line Mux", "PGA", "Left PGA Mux" }, + { "Left Line Mux", "Differential", "Differential Mux" }, + + { "Right Line Mux", "Line 1", "RINPUT1" }, + { "Right Line Mux", "Line 2", "RINPUT2" }, + { "Right Line Mux", "PGA", "Right PGA Mux" }, + { "Right Line Mux", "Differential", "Differential Mux" }, + + { "Left PGA Mux", "Line 1", "LINPUT1" }, + { "Left PGA Mux", "Line 2", "LINPUT2" }, + { "Left PGA Mux", "Differential", "Differential Mux" }, + + { "Right PGA Mux", "Line 1", "RINPUT1" }, + { "Right PGA Mux", "Line 2", "RINPUT2" }, + { "Right PGA Mux", "Differential", "Differential Mux" }, + + { "Differential Mux", "Line 1", "LINPUT1" }, + { "Differential Mux", "Line 1", "RINPUT1" }, + { "Differential Mux", "Line 2", "LINPUT2" }, + { "Differential Mux", "Line 2", "RINPUT2" }, + + { "Left ADC Mux", "Stereo", "Left PGA Mux" }, + { "Left ADC Mux", "Mono (Left)", "Left PGA Mux" }, + { "Left ADC Mux", "Digital Mono", "Left PGA Mux" }, + + { "Right ADC Mux", "Stereo", "Right PGA Mux" }, + { "Right ADC Mux", "Mono (Right)", "Right PGA Mux" }, + { "Right ADC Mux", "Digital Mono", "Right PGA Mux" }, + + { "Left ADC", NULL, "Left ADC Mux" }, + { "Right ADC", NULL, "Right ADC Mux" }, + + { "ADC DIG", NULL, "ADC STM" }, + { "ADC DIG", NULL, "ADC Vref" }, + { "ADC DIG", NULL, "ADC DLL" }, + + { "Left ADC", NULL, "ADC DIG" }, + { "Right ADC", NULL, "ADC DIG" }, + + { "Mic Bias", NULL, "Mic Bias Gen" }, + + { "Left ADC", NULL, "Mic Bias" }, + { "Right ADC", NULL, "Mic Bias" }, + + { "Left Line Mux", "Line 1", "LINPUT1" }, + { "Left Line Mux", "Line 2", "LINPUT2" }, + { "Left Line Mux", "PGA", "Left PGA Mux" }, + { "Left Line Mux", "Differential", "Differential Mux" }, + + { "Right Line Mux", "Line 1", "RINPUT1" }, + { "Right Line Mux", "Line 2", "RINPUT2" }, + { "Right Line Mux", "PGA", "Right PGA Mux" }, + { "Right Line Mux", "Differential", "Differential Mux" }, + + { "Left Out 1", NULL, "Left DAC" }, + { "Right Out 1", NULL, "Right DAC" }, + { "Left Out 2", NULL, "Left DAC" }, + { "Right Out 2", NULL, "Right DAC" }, + + { "Left Mixer", "Playback Switch", "Left DAC" }, + { "Left Mixer", "Left Bypass Switch", "Left Line Mux" }, + { "Left Mixer", "Right Playback Switch", "Right DAC" }, + { "Left Mixer", "Right Bypass Switch", "Right Line Mux" }, + + { "Right Mixer", "Left Playback Switch", "Left DAC" }, + { "Right Mixer", "Left Bypass Switch", "Left Line Mux" }, + { "Right Mixer", "Playback Switch", "Right DAC" }, + { "Right Mixer", "Right Bypass Switch", "Right Line Mux" }, + + { "DAC DIG", NULL, "DAC STM" }, + { "DAC DIG", NULL, "DAC Vref" }, + { "DAC DIG", NULL, "DAC DLL" }, + + { "Left DAC", NULL, "DAC DIG" }, + { "Right DAC", NULL, "DAC DIG" }, + + { "Left Out 1", NULL, "Left Mixer" }, + { "LOUT1", NULL, "Left Out 1" }, + { "Right Out 1", NULL, "Right Mixer" }, + { "ROUT1", NULL, "Right Out 1" }, + + { "Left Out 2", NULL, "Left Mixer" }, + { "LOUT2", NULL, "Left Out 2" }, + { "Right Out 2", NULL, "Right Mixer" }, + { "ROUT2", NULL, "Right Out 2" }, +}; + +static int es8328_mute(struct snd_soc_dai *dai, int mute, int direction) +{ + return snd_soc_component_update_bits(dai->component, ES8328_DACCONTROL3, + ES8328_DACCONTROL3_DACMUTE, + mute ? ES8328_DACCONTROL3_DACMUTE : 0); +} + +static int es8328_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component); + + if (es8328->provider && es8328->sysclk_constraints) + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + es8328->sysclk_constraints); + + return 0; +} + +static int es8328_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component); + int i; + int reg; + int wl; + int ratio; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + reg = ES8328_DACCONTROL2; + else + reg = ES8328_ADCCONTROL5; + + if (es8328->provider) { + if (!es8328->sysclk_constraints) { + dev_err(component->dev, "No MCLK configured\n"); + return -EINVAL; + } + + for (i = 0; i < es8328->sysclk_constraints->count; i++) + if (es8328->sysclk_constraints->list[i] == + params_rate(params)) + break; + + if (i == es8328->sysclk_constraints->count) { + dev_err(component->dev, + "LRCLK %d unsupported with current clock\n", + params_rate(params)); + return -EINVAL; + } + ratio = es8328->mclk_ratios[i]; + } else { + ratio = 0; + es8328->mclkdiv2 = 0; + } + + snd_soc_component_update_bits(component, ES8328_MASTERMODE, + ES8328_MASTERMODE_MCLKDIV2, + es8328->mclkdiv2 ? ES8328_MASTERMODE_MCLKDIV2 : 0); + + switch (params_width(params)) { + case 16: + wl = 3; + break; + case 18: + wl = 2; + break; + case 20: + wl = 1; + break; + case 24: + wl = 0; + break; + case 32: + wl = 4; + break; + default: + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + snd_soc_component_update_bits(component, ES8328_DACCONTROL1, + ES8328_DACCONTROL1_DACWL_MASK, + wl << ES8328_DACCONTROL1_DACWL_SHIFT); + + es8328->playback_fs = params_rate(params); + es8328_set_deemph(component); + } else + snd_soc_component_update_bits(component, ES8328_ADCCONTROL4, + ES8328_ADCCONTROL4_ADCWL_MASK, + wl << ES8328_ADCCONTROL4_ADCWL_SHIFT); + + return snd_soc_component_update_bits(component, reg, ES8328_RATEMASK, ratio); +} + +static int es8328_set_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_component *component = codec_dai->component; + struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component); + int mclkdiv2 = 0; + + switch (freq) { + case 0: + es8328->sysclk_constraints = NULL; + es8328->mclk_ratios = NULL; + break; + case 22579200: + mclkdiv2 = 1; + fallthrough; + case 11289600: + es8328->sysclk_constraints = &constraints_11289; + es8328->mclk_ratios = ratios_11289; + break; + case 24576000: + mclkdiv2 = 1; + fallthrough; + case 12288000: + es8328->sysclk_constraints = &constraints_12288; + es8328->mclk_ratios = ratios_12288; + break; + default: + return -EINVAL; + } + + es8328->mclkdiv2 = mclkdiv2; + return 0; +} + +static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_component *component = codec_dai->component; + struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component); + u8 dac_mode = 0; + u8 adc_mode = 0; + + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: + /* Master serial port mode, with BCLK generated automatically */ + snd_soc_component_update_bits(component, ES8328_MASTERMODE, + ES8328_MASTERMODE_MSC, + ES8328_MASTERMODE_MSC); + es8328->provider = true; + break; + case SND_SOC_DAIFMT_CBC_CFC: + /* Slave serial port mode */ + snd_soc_component_update_bits(component, ES8328_MASTERMODE, + ES8328_MASTERMODE_MSC, 0); + es8328->provider = false; + break; + default: + return -EINVAL; + } + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + dac_mode |= ES8328_DACCONTROL1_DACFORMAT_I2S; + adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + dac_mode |= ES8328_DACCONTROL1_DACFORMAT_RJUST; + adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_RJUST; + break; + case SND_SOC_DAIFMT_LEFT_J: + dac_mode |= ES8328_DACCONTROL1_DACFORMAT_LJUST; + adc_mode |= ES8328_ADCCONTROL4_ADCFORMAT_LJUST; + break; + default: + return -EINVAL; + } + + /* clock inversion */ + if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) + return -EINVAL; + + snd_soc_component_update_bits(component, ES8328_DACCONTROL1, + ES8328_DACCONTROL1_DACFORMAT_MASK, dac_mode); + snd_soc_component_update_bits(component, ES8328_ADCCONTROL4, + ES8328_ADCCONTROL4_ADCFORMAT_MASK, adc_mode); + snd_soc_component_update_bits(component, ES8328_DACCONTROL21, + ES8328_DACCONTROL21_SLRCK, ES8328_DACCONTROL21_SLRCK); + + /* Set Capture Digital Volume */ + snd_soc_component_write(component, ES8328_ADCCONTROL8, 0); + snd_soc_component_write(component, ES8328_ADCCONTROL9, 0); + + /* Set PCM Volume */ + snd_soc_component_write(component, ES8328_LDACVOL, 0); + snd_soc_component_write(component, ES8328_RDACVOL, 0); + + /* Set L/R Out Volume */ + snd_soc_component_write(component, ES8328_LOUT1VOL, 0x1e); + snd_soc_component_write(component, ES8328_ROUT1VOL, 0x1e); + snd_soc_component_write(component, ES8328_LOUT2VOL, 0x1e); + snd_soc_component_write(component, ES8328_ROUT2VOL, 0x1e); + + /* Set MIC PGA Volume */ + snd_soc_component_write(component, ES8328_ADCCONTROL1, 0x88); + + /* Select Capture path ---> phone mic */ + snd_soc_component_write(component, ES8328_ADCCONTROL2, 0xf0); + snd_soc_component_update_bits(component, ES8328_ADCCONTROL3, + ES8328_ADCCONTROL3_DS, 0); + + /* Select Playback path */ + snd_soc_component_update_bits(component, ES8328_DACCONTROL17, + ES8328_DACCONTROL17_LD2LO, ES8328_DACCONTROL17_LD2LO); + snd_soc_component_update_bits(component, ES8328_DACCONTROL20, + ES8328_DACCONTROL20_RD2RO, ES8328_DACCONTROL20_RD2RO); + + return 0; +} + +static int es8328_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + /* VREF, VMID=2x50k, digital enabled */ + snd_soc_component_write(component, ES8328_CHIPPOWER, 0); + snd_soc_component_update_bits(component, ES8328_CONTROL1, + ES8328_CONTROL1_VMIDSEL_MASK | + ES8328_CONTROL1_ENREF, + ES8328_CONTROL1_VMIDSEL_50k | + ES8328_CONTROL1_ENREF); + break; + + case SND_SOC_BIAS_STANDBY: + if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { + snd_soc_component_update_bits(component, ES8328_CONTROL1, + ES8328_CONTROL1_VMIDSEL_MASK | + ES8328_CONTROL1_ENREF, + ES8328_CONTROL1_VMIDSEL_5k | + ES8328_CONTROL1_ENREF); + + /* Charge caps */ + msleep(100); + } + + snd_soc_component_write(component, ES8328_CONTROL2, + ES8328_CONTROL2_OVERCURRENT_ON | + ES8328_CONTROL2_THERMAL_SHUTDOWN_ON); + + /* VREF, VMID=2*500k, digital stopped */ + snd_soc_component_update_bits(component, ES8328_CONTROL1, + ES8328_CONTROL1_VMIDSEL_MASK | + ES8328_CONTROL1_ENREF, + ES8328_CONTROL1_VMIDSEL_500k | + ES8328_CONTROL1_ENREF); + break; + + case SND_SOC_BIAS_OFF: + snd_soc_component_update_bits(component, ES8328_CONTROL1, + ES8328_CONTROL1_VMIDSEL_MASK | + ES8328_CONTROL1_ENREF, + 0); + break; + } + return 0; +} + +static const struct snd_soc_dai_ops es8328_dai_ops = { + .startup = es8328_startup, + .hw_params = es8328_hw_params, + .mute_stream = es8328_mute, + .set_sysclk = es8328_set_sysclk, + .set_fmt = es8328_set_dai_fmt, + .no_capture_mute = 1, +}; + +static struct snd_soc_dai_driver es8328_dai[3] = { + { + .name = "es8328-0-hifi-analog", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = ES8328_RATES, + .formats = ES8328_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = ES8328_RATES, + .formats = ES8328_FORMATS, + }, + .ops = &es8328_dai_ops, + .symmetric_rate = 1, + }, + { + .name = "es8328-1-hifi-analog", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = ES8328_RATES, + .formats = ES8328_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = ES8328_RATES, + .formats = ES8328_FORMATS, + }, + .ops = &es8328_dai_ops, + .symmetric_rate = 1, + }, + { + .name = "es8328-2-hifi-analog", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = ES8328_RATES, + .formats = ES8328_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = ES8328_RATES, + .formats = ES8328_FORMATS, + }, + .ops = &es8328_dai_ops, + .symmetric_rate = 1, + }, +}; + +static int es8328_suspend(struct snd_soc_component *component) +{ + return 0; +} + +static int es8328_resume(struct snd_soc_component *component) +{ + struct regmap *regmap = dev_get_regmap(component->dev, NULL); + int ret; + + regcache_mark_dirty(regmap); + ret = regcache_sync(regmap); + if (ret) { + dev_err(component->dev, "unable to sync regcache\n"); + return ret; + } + + return 0; +} + +static int es8328_component_probe(struct snd_soc_component *component) +{ + return 0; +} + +static void es8328_remove(struct snd_soc_component *component) +{ +} + +const struct regmap_config es8328_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = ES8328_REG_MAX, + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; +EXPORT_SYMBOL_GPL(es8328_regmap_config); + +static const struct snd_soc_component_driver es8328_component_driver = { + .probe = es8328_component_probe, + .remove = es8328_remove, + .suspend = es8328_suspend, + .resume = es8328_resume, + .set_bias_level = es8328_set_bias_level, + .controls = es8328_snd_controls, + .num_controls = ARRAY_SIZE(es8328_snd_controls), + .dapm_widgets = es8328_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(es8328_dapm_widgets), + .dapm_routes = es8328_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(es8328_dapm_routes), + .suspend_bias_off = 1, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, +}; + +int es8328_probe(struct device *dev, struct regmap *regmap) +{ + struct es8328_priv *es8328; + int ret; + + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + es8328 = devm_kzalloc(dev, sizeof(*es8328), GFP_KERNEL); + if (es8328 == NULL) + return -ENOMEM; + + es8328->regmap = regmap; + + dev_set_drvdata(dev, es8328); + + if (of_node_name_prefix(dev->of_node, "es8388-0")) { + ret = devm_snd_soc_register_component(dev, + &es8328_component_driver, &es8328_dai[0], 1); + } else if (of_node_name_prefix(dev->of_node, "es8388-1")) { + ret = devm_snd_soc_register_component(dev, + &es8328_component_driver, &es8328_dai[1], 1); + } else { + ret = devm_snd_soc_register_component(dev, + &es8328_component_driver, &es8328_dai[2], 1); + } + + return ret; +} +EXPORT_SYMBOL_GPL(es8328_probe); + +MODULE_DESCRIPTION("ASoC ES8328 driver"); +MODULE_AUTHOR("Sean Cross "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/eswin/es8328.h b/sound/soc/codecs/eswin/es8328.h new file mode 100644 index 0000000000000..249ed26d16f8b --- /dev/null +++ b/sound/soc/codecs/eswin/es8328.h @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN Codec root complex 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 . + * + * Authors: Lei Deng + */ + +#ifndef _ES8328_H +#define _ES8328_H + +#include + +struct device; + +extern const struct regmap_config es8328_regmap_config; +int es8328_probe(struct device *dev, struct regmap *regmap); + +#define ES8328_DACLVOL 46 +#define ES8328_DACRVOL 47 +#define ES8328_DACCTL 28 +#define ES8328_RATEMASK (0x1f << 0) + +#define ES8328_CONTROL1 0x00 +#define ES8328_CONTROL1_VMIDSEL_OFF (0 << 0) +#define ES8328_CONTROL1_VMIDSEL_50k (1 << 0) +#define ES8328_CONTROL1_VMIDSEL_500k (2 << 0) +#define ES8328_CONTROL1_VMIDSEL_5k (3 << 0) +#define ES8328_CONTROL1_VMIDSEL_MASK (3 << 0) +#define ES8328_CONTROL1_ENREF (1 << 2) +#define ES8328_CONTROL1_SEQEN (1 << 3) +#define ES8328_CONTROL1_SAMEFS (1 << 4) +#define ES8328_CONTROL1_DACMCLK_ADC (0 << 5) +#define ES8328_CONTROL1_DACMCLK_DAC (1 << 5) +#define ES8328_CONTROL1_LRCM (1 << 6) +#define ES8328_CONTROL1_SCP_RESET (1 << 7) + +#define ES8328_CONTROL2 0x01 +#define ES8328_CONTROL2_VREF_BUF_OFF (1 << 0) +#define ES8328_CONTROL2_VREF_LOWPOWER (1 << 1) +#define ES8328_CONTROL2_IBIASGEN_OFF (1 << 2) +#define ES8328_CONTROL2_ANALOG_OFF (1 << 3) +#define ES8328_CONTROL2_VREF_BUF_LOWPOWER (1 << 4) +#define ES8328_CONTROL2_VCM_MOD_LOWPOWER (1 << 5) +#define ES8328_CONTROL2_OVERCURRENT_ON (1 << 6) +#define ES8328_CONTROL2_THERMAL_SHUTDOWN_ON (1 << 7) + +#define ES8328_CHIPPOWER 0x02 +#define ES8328_CHIPPOWER_DACVREF_OFF 0 +#define ES8328_CHIPPOWER_ADCVREF_OFF 1 +#define ES8328_CHIPPOWER_DACDLL_OFF 2 +#define ES8328_CHIPPOWER_ADCDLL_OFF 3 +#define ES8328_CHIPPOWER_DACSTM_RESET 4 +#define ES8328_CHIPPOWER_ADCSTM_RESET 5 +#define ES8328_CHIPPOWER_DACDIG_OFF 6 +#define ES8328_CHIPPOWER_ADCDIG_OFF 7 + +#define ES8328_ADCPOWER 0x03 +#define ES8328_ADCPOWER_INT1_LOWPOWER 0 +#define ES8328_ADCPOWER_FLASH_ADC_LOWPOWER 1 +#define ES8328_ADCPOWER_ADC_BIAS_GEN_OFF 2 +#define ES8328_ADCPOWER_MIC_BIAS_OFF 3 +#define ES8328_ADCPOWER_ADCR_OFF 4 +#define ES8328_ADCPOWER_ADCL_OFF 5 +#define ES8328_ADCPOWER_AINR_OFF 6 +#define ES8328_ADCPOWER_AINL_OFF 7 + +#define ES8328_DACPOWER 0x04 +#define ES8328_DACPOWER_OUT3_ON 0 +#define ES8328_DACPOWER_MONO_ON 1 +#define ES8328_DACPOWER_ROUT2_ON 2 +#define ES8328_DACPOWER_LOUT2_ON 3 +#define ES8328_DACPOWER_ROUT1_ON 4 +#define ES8328_DACPOWER_LOUT1_ON 5 +#define ES8328_DACPOWER_RDAC_OFF 6 +#define ES8328_DACPOWER_LDAC_OFF 7 + +#define ES8328_CHIPLOPOW1 0x05 +#define ES8328_CHIPLOPOW2 0x06 +#define ES8328_ANAVOLMANAG 0x07 + +#define ES8328_MASTERMODE 0x08 +#define ES8328_MASTERMODE_BCLKDIV (0 << 0) +#define ES8328_MASTERMODE_BCLK_INV (1 << 5) +#define ES8328_MASTERMODE_MCLKDIV2 (1 << 6) +#define ES8328_MASTERMODE_MSC (1 << 7) + +#define ES8328_ADCCONTROL1 0x09 +#define ES8328_ADCCONTROL2 0x0a +#define ES8328_ADCCONTROL3 0x0b +#define ES8328_ADCCONTROL3_DS (1 << 7) + +#define ES8328_ADCCONTROL4 0x0c +#define ES8328_ADCCONTROL4_ADCFORMAT_MASK (3 << 0) +#define ES8328_ADCCONTROL4_ADCFORMAT_I2S (0 << 0) +#define ES8328_ADCCONTROL4_ADCFORMAT_LJUST (1 << 0) +#define ES8328_ADCCONTROL4_ADCFORMAT_RJUST (2 << 0) +#define ES8328_ADCCONTROL4_ADCFORMAT_PCM (3 << 0) +#define ES8328_ADCCONTROL4_ADCWL_SHIFT 2 +#define ES8328_ADCCONTROL4_ADCWL_MASK (7 << 2) +#define ES8328_ADCCONTROL4_ADCLRP_I2S_POL_NORMAL (0 << 5) +#define ES8328_ADCCONTROL4_ADCLRP_I2S_POL_INV (1 << 5) +#define ES8328_ADCCONTROL4_ADCLRP_PCM_MSB_CLK2 (0 << 5) +#define ES8328_ADCCONTROL4_ADCLRP_PCM_MSB_CLK1 (1 << 5) + +#define ES8328_ADCCONTROL5 0x0d +#define ES8328_ADCCONTROL5_RATEMASK (0x1f << 0) + +#define ES8328_ADCCONTROL6 0x0e + +#define ES8328_ADCCONTROL7 0x0f +#define ES8328_ADCCONTROL7_ADC_MUTE (1 << 2) +#define ES8328_ADCCONTROL7_ADC_LER (1 << 3) +#define ES8328_ADCCONTROL7_ADC_ZERO_CROSS (1 << 4) +#define ES8328_ADCCONTROL7_ADC_SOFT_RAMP (1 << 5) +#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_4 (0 << 6) +#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_8 (1 << 6) +#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_16 (2 << 6) +#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_32 (3 << 6) + +#define ES8328_ADCCONTROL8 0x10 +#define ES8328_ADCCONTROL9 0x11 +#define ES8328_ADCCONTROL10 0x12 +#define ES8328_ADCCONTROL11 0x13 +#define ES8328_ADCCONTROL12 0x14 +#define ES8328_ADCCONTROL13 0x15 +#define ES8328_ADCCONTROL14 0x16 + +#define ES8328_DACCONTROL1 0x17 +#define ES8328_DACCONTROL1_DACFORMAT_MASK (3 << 1) +#define ES8328_DACCONTROL1_DACFORMAT_I2S (0 << 1) +#define ES8328_DACCONTROL1_DACFORMAT_LJUST (1 << 1) +#define ES8328_DACCONTROL1_DACFORMAT_RJUST (2 << 1) +#define ES8328_DACCONTROL1_DACFORMAT_PCM (3 << 1) +#define ES8328_DACCONTROL1_DACWL_SHIFT 3 +#define ES8328_DACCONTROL1_DACWL_MASK (7 << 3) +#define ES8328_DACCONTROL1_DACLRP_I2S_POL_NORMAL (0 << 6) +#define ES8328_DACCONTROL1_DACLRP_I2S_POL_INV (1 << 6) +#define ES8328_DACCONTROL1_DACLRP_PCM_MSB_CLK2 (0 << 6) +#define ES8328_DACCONTROL1_DACLRP_PCM_MSB_CLK1 (1 << 6) +#define ES8328_DACCONTROL1_LRSWAP (1 << 7) + +#define ES8328_DACCONTROL2 0x18 +#define ES8328_DACCONTROL2_RATEMASK (0x1f << 0) +#define ES8328_DACCONTROL2_DOUBLESPEED (1 << 5) + +#define ES8328_DACCONTROL3 0x19 +#define ES8328_DACCONTROL3_AUTOMUTE (1 << 2) +#define ES8328_DACCONTROL3_DACMUTE (1 << 2) +#define ES8328_DACCONTROL3_LEFTGAINVOL (1 << 3) +#define ES8328_DACCONTROL3_DACZEROCROSS (1 << 4) +#define ES8328_DACCONTROL3_DACSOFTRAMP (1 << 5) +#define ES8328_DACCONTROL3_DACRAMPRATE (3 << 6) + +#define ES8328_LDACVOL 0x1a +#define ES8328_LDACVOL_MASK (0 << 0) +#define ES8328_LDACVOL_MAX (0xc0) + +#define ES8328_RDACVOL 0x1b +#define ES8328_RDACVOL_MASK (0 << 0) +#define ES8328_RDACVOL_MAX (0xc0) + +#define ES8328_DACCONTROL6 0x1c +#define ES8328_DACCONTROL6_CLICKFREE (1 << 3) +#define ES8328_DACCONTROL6_DAC_INVR (1 << 4) +#define ES8328_DACCONTROL6_DAC_INVL (1 << 5) +#define ES8328_DACCONTROL6_DEEMPH_MASK (3 << 6) +#define ES8328_DACCONTROL6_DEEMPH_OFF (0 << 6) +#define ES8328_DACCONTROL6_DEEMPH_32k (1 << 6) +#define ES8328_DACCONTROL6_DEEMPH_44_1k (2 << 6) +#define ES8328_DACCONTROL6_DEEMPH_48k (3 << 6) + +#define ES8328_DACCONTROL7 0x1d +#define ES8328_DACCONTROL7_VPP_SCALE_3p5 (0 << 0) +#define ES8328_DACCONTROL7_VPP_SCALE_4p0 (1 << 0) +#define ES8328_DACCONTROL7_VPP_SCALE_3p0 (2 << 0) +#define ES8328_DACCONTROL7_VPP_SCALE_2p5 (3 << 0) +#define ES8328_DACCONTROL7_SHELVING_STRENGTH (1 << 2) /* In eights */ +#define ES8328_DACCONTROL7_MONO (1 << 5) +#define ES8328_DACCONTROL7_ZEROR (1 << 6) +#define ES8328_DACCONTROL7_ZEROL (1 << 7) + +/* Shelving filter */ +#define ES8328_DACCONTROL8 0x1e +#define ES8328_DACCONTROL9 0x1f +#define ES8328_DACCONTROL10 0x20 +#define ES8328_DACCONTROL11 0x21 +#define ES8328_DACCONTROL12 0x22 +#define ES8328_DACCONTROL13 0x23 +#define ES8328_DACCONTROL14 0x24 +#define ES8328_DACCONTROL15 0x25 + +#define ES8328_DACCONTROL16 0x26 +#define ES8328_DACCONTROL16_RMIXSEL_RIN1 (0 << 0) +#define ES8328_DACCONTROL16_RMIXSEL_RIN2 (1 << 0) +#define ES8328_DACCONTROL16_RMIXSEL_RIN3 (2 << 0) +#define ES8328_DACCONTROL16_RMIXSEL_RADC (3 << 0) +#define ES8328_DACCONTROL16_LMIXSEL_LIN1 (0 << 3) +#define ES8328_DACCONTROL16_LMIXSEL_LIN2 (1 << 3) +#define ES8328_DACCONTROL16_LMIXSEL_LIN3 (2 << 3) +#define ES8328_DACCONTROL16_LMIXSEL_LADC (3 << 3) + +#define ES8328_DACCONTROL17 0x27 +#define ES8328_DACCONTROL17_LI2LOVOL (7 << 3) +#define ES8328_DACCONTROL17_LI2LO (1 << 6) +#define ES8328_DACCONTROL17_LD2LO (1 << 7) + +#define ES8328_DACCONTROL18 0x28 +#define ES8328_DACCONTROL18_RI2LOVOL (7 << 3) +#define ES8328_DACCONTROL18_RI2LO (1 << 6) +#define ES8328_DACCONTROL18_RD2LO (1 << 7) + +#define ES8328_DACCONTROL19 0x29 +#define ES8328_DACCONTROL19_LI2ROVOL (7 << 3) +#define ES8328_DACCONTROL19_LI2RO (1 << 6) +#define ES8328_DACCONTROL19_LD2RO (1 << 7) + +#define ES8328_DACCONTROL20 0x2a +#define ES8328_DACCONTROL20_RI2ROVOL (7 << 3) +#define ES8328_DACCONTROL20_RI2RO (1 << 6) +#define ES8328_DACCONTROL20_RD2RO (1 << 7) + +#define ES8328_DACCONTROL21 0x2b +#define ES8328_DACCONTROL21_SLRCK (1 << 7) + +#define ES8328_DACCONTROL22 0x2c +#define ES8328_DACCONTROL22_RI2MOVOL (7 << 3) +#define ES8328_DACCONTROL22_RI2MO (1 << 6) +#define ES8328_DACCONTROL22_RD2MO (1 << 7) + +#define ES8328_DACCONTROL23 0x2d +#define ES8328_DACCONTROL23_MOUTINV (1 << 1) +#define ES8328_DACCONTROL23_HPSWPOL (1 << 2) +#define ES8328_DACCONTROL23_HPSWEN (1 << 3) +#define ES8328_DACCONTROL23_VROI_1p5k (0 << 4) +#define ES8328_DACCONTROL23_VROI_40k (1 << 4) +#define ES8328_DACCONTROL23_OUT3_VREF (0 << 5) +#define ES8328_DACCONTROL23_OUT3_ROUT1 (1 << 5) +#define ES8328_DACCONTROL23_OUT3_MONOOUT (2 << 5) +#define ES8328_DACCONTROL23_OUT3_RIGHT_MIXER (3 << 5) +#define ES8328_DACCONTROL23_ROUT2INV (1 << 7) + +/* LOUT1 Amplifier */ +#define ES8328_LOUT1VOL 0x2e +#define ES8328_LOUT1VOL_MASK (0 << 5) +#define ES8328_LOUT1VOL_MAX (0x24) + +/* ROUT1 Amplifier */ +#define ES8328_ROUT1VOL 0x2f +#define ES8328_ROUT1VOL_MASK (0 << 5) +#define ES8328_ROUT1VOL_MAX (0x24) + +#define ES8328_OUT1VOL_MAX (0x24) + +/* LOUT2 Amplifier */ +#define ES8328_LOUT2VOL 0x30 +#define ES8328_LOUT2VOL_MASK (0 << 5) +#define ES8328_LOUT2VOL_MAX (0x24) + +/* ROUT2 Amplifier */ +#define ES8328_ROUT2VOL 0x31 +#define ES8328_ROUT2VOL_MASK (0 << 5) +#define ES8328_ROUT2VOL_MAX (0x24) + +#define ES8328_OUT2VOL_MAX (0x24) + +/* Mono Out Amplifier */ +#define ES8328_MONOOUTVOL 0x32 +#define ES8328_MONOOUTVOL_MASK (0 << 5) +#define ES8328_MONOOUTVOL_MAX (0x24) + +#define ES8328_DACCONTROL29 0x33 +#define ES8328_DACCONTROL30 0x34 + +#define ES8328_SYSCLK 0 + +#define ES8328_REG_MAX 0x35 + +#define ES8328_1536FS 1536 +#define ES8328_1024FS 1024 +#define ES8328_768FS 768 +#define ES8328_512FS 512 +#define ES8328_384FS 384 +#define ES8328_256FS 256 +#define ES8328_128FS 128 + +#endif diff --git a/sound/soc/eswin/Kconfig b/sound/soc/eswin/Kconfig new file mode 100644 index 0000000000000..7eaebda84b6a1 --- /dev/null +++ b/sound/soc/eswin/Kconfig @@ -0,0 +1,10 @@ +menu "SND ESWIN SOC" + +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 diff --git a/sound/soc/eswin/Makefile b/sound/soc/eswin/Makefile new file mode 100644 index 0000000000000..c293a0c767220 --- /dev/null +++ b/sound/soc/eswin/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only +# ESWIN Platform Support +snd-soc-i2s-objs := i2s-stereo.o es-audio-proc.o + +obj-$(CONFIG_SND_ESWIN_DW_I2S) += snd-soc-i2s.o diff --git a/sound/soc/eswin/es-audio-proc.c b/sound/soc/eswin/es-audio-proc.c new file mode 100644 index 0000000000000..daad20324ac93 --- /dev/null +++ b/sound/soc/eswin/es-audio-proc.c @@ -0,0 +1,488 @@ +/* + * + * Copyright (C) 2021 ESWIN, Inc. 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. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// proc data definition +typedef enum +{ + ADEC_CREATE_CHN, + ADEC_SEND_STREAM, + ADEC_GET_FRAME, + ADEC_PARSE_PACKET, + ADEC_DECODE_STREAM, + AENC_CREATE_CHN, + AENC_SEND_FRAME, + AENC_GET_STREAM, + AENC_ENCODE_FRAME, + AGC_PROCESS, + ANS_PROCESS, + AEC_PROCESS, + DRC_PROCESS, + EQ_PROCESS, + DCBLOCK_PROCESS, + VOLUME_PROCESS, + SRC_HOST_PROCESS, + SRC_DAI_PROCESS, + HOST_PROCESS, + DAI_PROCESS, + AO_START, + AO_PROCESS_FRAME, + AO_WRITE_FRAME, + AO_STOP, + AI_START, + AI_READ_FRAME, + AI_PROCESS_FRAME, + AI_STOP, +} PERF_MARK; + +static struct proc_dir_entry *proc_esaudio; +static int g_switch = 0; + +// Device data definition +#define MAX_PERF_SIZE 1024 +enum DEVICES_ID{ + INVALID_DEVICE = -1, + AO = 0, + AI, + AENC, + ADEC, + NUM_DEVICES, +}; +static const char *device_names[NUM_DEVICES] = {"ao", "ai", "aenc", "adec"}; +static int audio_proc_major[NUM_DEVICES] = {0}; +static struct class *audio_proc_class = NULL; +static struct device *audio_proc_device[NUM_DEVICES] = {NULL}; +static int32_t *g_perf_data[NUM_DEVICES] = {NULL}; + +static void show_aenc_data(struct seq_file *m) +{ + seq_printf(m,"----------------------------------------------------AENC PERF STATISTIC BEGIN" + "----------------------------------------------------\n"); + seq_printf(m, "\n"); + seq_printf(m, "------------------------------------------------------------------------" + "----------------------------------------------------------\n"); + seq_printf(m, "audio encoder performance(us):\n"); + seq_printf(m, "%-14s%-14s%-14s%-14s\n", "create_chn", "send_frame", "get_stream", "encode_frame"); + seq_printf(m, "----------------------------------------------------------------------------------" + "------------------------------------------------\n"); + seq_printf(m, "%-14d%-14d%-14d%-14d\n", g_perf_data[AENC][AENC_CREATE_CHN], g_perf_data[AENC][AENC_SEND_FRAME], + g_perf_data[AENC][AENC_GET_STREAM], g_perf_data[AENC][AENC_ENCODE_FRAME]); + seq_printf(m, "\n"); + seq_printf(m, "-----------------------------------------------------AENC PERF STATISTIC END" + "-----------------------------------------------------\n"); +} + +static void show_adec_data(struct seq_file *m) +{ + seq_printf(m, "----------------------------------------------------ADEC PERF STATISTIC BEGIN" + "----------------------------------------------------\n"); + seq_printf(m, "\n"); + seq_printf(m, "--------------------------------------------------------------------------" + "--------------------------------------------------------\n"); + seq_printf(m, "audio decoder performance(us):\n"); + seq_printf(m, "%-14s%-14s%-14s%-14s%-14s\n", "create_chn", "send_stream", "get_frame", + "parse_packet", "decode_stream"); + seq_printf(m, "------------------------------------------------------------------------------------" + "----------------------------------------------\n"); + seq_printf(m, "%-14d%-14d%-14d%-14d%-14d\n", g_perf_data[ADEC][ADEC_CREATE_CHN], + g_perf_data[ADEC][ADEC_SEND_STREAM], g_perf_data[ADEC][ADEC_GET_FRAME], + g_perf_data[ADEC][ADEC_PARSE_PACKET], g_perf_data[ADEC][ADEC_DECODE_STREAM]); + seq_printf(m, "\n"); + seq_printf(m,"-----------------------------------------------------ADEC PERF STATISTIC END" + "-----------------------------------------------------\n"); +} + +static void show_ao_data(struct seq_file *m) +{ + seq_printf(m,"----------------------------------------------------AO PERF STATISTIC BEGIN" + "----------------------------------------------------\n"); + seq_printf(m, "\n"); + seq_printf(m, "---------------------------------------------------------------------------" + "-------------------------------------------------------\n"); + seq_printf(m, "audio output performance(us):\n"); + seq_printf(m, "%-14s%-24s%-24s\n", "ao_start", "ao_process_frame", "ao_write_frame"); + seq_printf(m, "----------------------------------------------------------------------------" + "------------------------------------------------------\n"); + seq_printf(m, "%-14d%-24d%-24d\n", g_perf_data[AO][AO_START], g_perf_data[AO][AO_PROCESS_FRAME], + g_perf_data[AO][AO_WRITE_FRAME]); + seq_printf(m, "\n"); + 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", + "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, "\n"); + seq_printf(m,"-----------------------------------------------------AO PERF STATISTIC END" + "-----------------------------------------------------\n"); +} + +static void show_ai_data(struct seq_file *m) +{ + seq_printf(m,"----------------------------------------------------AI PERF STATISTIC BEGIN" + "----------------------------------------------------\n"); + seq_printf(m, "\n"); + seq_printf(m, "---------------------------------------------------------------------------" + "-------------------------------------------------------\n"); + seq_printf(m, "audio input performance(us):\n"); + seq_printf(m, "%-14s%-24s%-24s\n", "ai_start", "ai_read_frame", "ai_process_frame"); + seq_printf(m, "----------------------------------------------------------------------------" + "------------------------------------------------------\n"); + seq_printf(m, "%-14d%-24d%-24d\n", g_perf_data[AI][AI_START], g_perf_data[AI][AI_READ_FRAME], + g_perf_data[AI][AI_PROCESS_FRAME]); + seq_printf(m, "\n"); + 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", + "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, "\n"); + seq_printf(m,"-----------------------------------------------------AI PERF STATISTIC END" + "-----------------------------------------------------\n"); +} + + +static int audio_info_show(struct seq_file *m, void *p) +{ + int i; + const char *fileName = m->file->f_path.dentry->d_name.name; + enum DEVICES_ID deviceID = INVALID_DEVICE; + + pr_info("audio_info_show:%s\n", m->file->f_path.dentry->d_name.name); + + for (i = 0; i < NUM_DEVICES; ++i) { + if (strcmp(fileName, device_names[i]) == 0) { + deviceID = i; + break; + } + } + + if (deviceID == INVALID_DEVICE) { + pr_err("deviceID is INVALID\n"); + return -EINVAL; + } + + if (g_switch == 0) { + seq_printf(m, "The switch is not turned on, pls first turn on the switch.\n"); + return 0; + } + + switch (deviceID) { + case AI: + show_ai_data(m); + break; + case AO: + show_ao_data(m); + break; + case AENC: + show_aenc_data(m); + break; + case ADEC: + show_adec_data(m); + break; + default: + pr_err("deviceID is INVALID\n"); + break; + } + return 0; +} + +static int info_open(struct inode *inode, struct file *flip) +{ + return single_open(flip, audio_info_show, NULL); +} + +static int switch_show(struct seq_file *m, void *p) +{ + seq_printf(m, "--------------------AUDIO Performance Switch--------------------\n"); + seq_printf(m, "\n"); + seq_printf(m, "AUDIO Performance Switch Status Value:%d\n", g_switch); + seq_printf(m, "\n"); + return 0; +} + +static int switch_open(struct inode *inode, struct file *flip) +{ + return single_open(flip, switch_show, NULL); +} + +static ssize_t switch_write(struct file *flip, const char __user *buf, size_t size, loff_t *pos) +{ + u16 data; + u8 value; + + if (size > 2) { + return -EINVAL; + } + if (copy_from_user(&data, buf, size)) { + return -EFAULT; + } + value = data & 0xff; + + value -= '0'; + if (!(value == 1 || value == 0)) { + printk("%s, %d, data=%d is not correct, pls use 1 or 0.\n", __func__, __LINE__, value); + return -EINVAL; + } + + g_switch = value ? 1 : 0; + + return size; +} + +static struct proc_ops proc_info_fops = { + .proc_open = info_open, + .proc_read = seq_read, + .proc_release = single_release, +}; + +static struct proc_ops proc_switch_fops = { + .proc_open = switch_open, + .proc_read = seq_read, + .proc_release = single_release, + .proc_write = switch_write, +}; + +int audio_create_procfs(void) +{ + proc_esaudio = proc_mkdir("es_audio", NULL); + if (proc_esaudio == NULL) { + pr_err("create es_audio dir err.\n"); + return -ENOMEM; + } + + if (!proc_create("ao", 0644, proc_esaudio, &proc_info_fops)) { + pr_err("error create proc ao file.\n"); + goto err_ao; + } + + if (!proc_create("ai", 0644, proc_esaudio, &proc_info_fops)) { + pr_err("error create proc ai file.\n"); + goto err_ai; + } + + if (!proc_create("aenc", 0644, proc_esaudio, &proc_info_fops)) { + pr_err("error create proc aenc file.\n"); + goto err_aenc; + } + + if (!proc_create("adec", 0644, proc_esaudio, &proc_info_fops)) { + pr_err("error create proc adec file.\n"); + goto err_adec; + } + + if (!proc_create("switch", 0644, proc_esaudio, &proc_switch_fops)) { + pr_err("error create proc switch file.\n"); + goto err_switch; + } + + return 0; + +err_switch: + remove_proc_entry("adec", proc_esaudio); +err_adec: + remove_proc_entry("aenc", proc_esaudio); +err_aenc: + remove_proc_entry("ai", proc_esaudio); +err_ai: + remove_proc_entry("ao", proc_esaudio); +err_ao: + remove_proc_entry("es_audio", NULL); + return -1; +} + +void audio_remove_procfs(void) +{ + remove_proc_entry("switch", proc_esaudio); + + remove_proc_entry("adec", proc_esaudio); + + remove_proc_entry("aenc", proc_esaudio); + + remove_proc_entry("ai", proc_esaudio); + + remove_proc_entry("ao", proc_esaudio); + + remove_proc_entry("es_audio", NULL); +} + + +/////////////////////////////////////////////////////////////////////////////// +// audio dev implementation +static int audio_dev_mmap(struct file *file, struct vm_area_struct *vma) +{ + int i; + const char *fileName = file->f_path.dentry->d_name.name; + enum DEVICES_ID deviceID = INVALID_DEVICE; + unsigned long size = vma->vm_end - vma->vm_start; + + pr_info("audio_dev_mmap:%s\n", file->f_path.dentry->d_name.name); + + pr_info("vma->vm_end:%ld,vma->vm_start:%ld\n",vma->vm_end, vma->vm_start); + + if (size > (MAX_PERF_SIZE * sizeof(int32_t))) { + pr_err("audio_dev_mmap: size:%ld > %ld.\n", size, MAX_PERF_SIZE * sizeof(int32_t)); + return -EINVAL; + } + + for (i = 0; i < NUM_DEVICES; ++i) { + if (strcmp(fileName, device_names[i]) == 0) { + deviceID = i; + break; + } + } + + if (deviceID == INVALID_DEVICE) { + pr_err("deviceID is INVALID\n"); + return -EINVAL; + } + + // Remap the shared memory into the process's address space + if (remap_pfn_range(vma, vma->vm_start, virt_to_phys(g_perf_data[deviceID]) >> PAGE_SHIFT, + size, vma->vm_page_prot)) { + pr_err("Failed to remap shared memory.\n"); + return -EAGAIN; + } + + return 0; +} + +static const struct file_operations dev_fops = { + .owner = THIS_MODULE, + .mmap = audio_dev_mmap, +}; + +static bool g_proc_initialized = false; + +int audio_proc_module_init(void) +{ + int i, ret; + struct device *dev; + + if (g_proc_initialized) { + return 0; + } + + pr_info("audio_proc_module_init enter.\n"); + + audio_proc_class = class_create("audio_proc_class"); + if (IS_ERR(audio_proc_class)) { + pr_err("Failed to create audio_proc_class\n"); + return PTR_ERR(audio_proc_class); + } + + for (i = 0; i < NUM_DEVICES; ++i) { + g_perf_data[i] = kmalloc(MAX_PERF_SIZE * sizeof(int32_t), GFP_KERNEL); + if (!g_perf_data[i]) { + pr_err("Failed to allocate shared memory for '%s'\n", device_names[i]); + goto cleanup; + } + + memset(g_perf_data[i], 0, MAX_PERF_SIZE * sizeof(int32_t)); + + ret = register_chrdev(0, device_names[i], &dev_fops); + if (ret < 0) { + pr_err("Failed to register character device '%s'\n", device_names[i]); + goto cleanup; + } + + audio_proc_major[i] = ret; + + dev = device_create(audio_proc_class, NULL, MKDEV(audio_proc_major[i], 0), NULL, device_names[i]); + if (IS_ERR(dev)) { + pr_err("Failed to create device node '%s'\n", device_names[i]); + goto cleanup; + } + + audio_proc_device[i] = dev; + } + + audio_create_procfs(); + + g_proc_initialized = true; + + pr_info("es_audio_proc: initialized\n"); + return 0; + +cleanup: + for (i = 0; i < NUM_DEVICES; ++i) { + if (g_perf_data[i]) { + kfree(g_perf_data[i]); + g_perf_data[i] = NULL; + } + + if (audio_proc_major[i]) { + unregister_chrdev(audio_proc_major[i], device_names[i]); + } + + if (audio_proc_device[i]) { + device_destroy(audio_proc_class, MKDEV(audio_proc_major[i], 0)); + } + } + + class_destroy(audio_proc_class); + return ret; +} + +static bool g_proc_uninitialized = false; + +void audio_proc_module_exit(void) +{ + int i; + + if (g_proc_uninitialized) { + return; + } + + audio_remove_procfs(); + for (i = 0; i < NUM_DEVICES; ++i) { + device_destroy(audio_proc_class, MKDEV(audio_proc_major[i], 0)); + unregister_chrdev(audio_proc_major[i], device_names[i]); + kfree(g_perf_data[i]); + g_perf_data[i] = NULL; + } + + class_destroy(audio_proc_class); + + g_proc_uninitialized = true; + + pr_info("es_audio_proc: uninitialized\n"); +} diff --git a/sound/soc/eswin/es-audio-proc.h b/sound/soc/eswin/es-audio-proc.h new file mode 100644 index 0000000000000..1fd3f377671d9 --- /dev/null +++ b/sound/soc/eswin/es-audio-proc.h @@ -0,0 +1,23 @@ +/* + * + * Copyright (C) 2021 ESWIN, Inc. 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. + * + * 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. + * + */ + +#ifndef _ES_AUDIO_PROC_H_ +#define _ES_AUDIO_PROC_H_ + +int audio_proc_module_init(void); +void audio_proc_module_exit(void); + +#endif diff --git a/sound/soc/eswin/i2s-stereo.c b/sound/soc/eswin/i2s-stereo.c new file mode 100755 index 0000000000000..fcd51cdbd7caf --- /dev/null +++ b/sound/soc/eswin/i2s-stereo.c @@ -0,0 +1,1036 @@ +/* + * + * Copyright (C) 2021 ESWIN, Inc. 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. + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2s.h" +#include "es-audio-proc.h" + +#define VO_MCLK_DIVSOR_MASK 0xff0 +#define VO_MCLK_DIVSOR_OFFSET 4 + +#define MAX_SAMPLE_RATE_SUPPORT (192000UL) +#define MAX_SAMPLE_RATE_CLK (MAX_SAMPLE_RATE_SUPPORT * 32 * 2) // 32 bits, 2channels + +#define VO_TOP_CSR 0x50280000UL +#define VO_I2S0_DIV_NUM 0x2000 +#define VO_I2S1_DIV_NUM 0x2004 +#define VO_I2S2_DIV_NUM 0x2008 +#define DIV_NUM_MASK 0x1f + +#define ESW_I2S_RATES (SNDRV_PCM_RATE_192000 | \ + SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_8000) +#define ESW_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +static u32 dmaen_txch[] = { + DMAEN_TXCH_0, + DMAEN_TXCH_1, + DMAEN_TXCH_2, + DMAEN_TXCH_3 +}; + +static u32 dmaen_rxch[] = { + DMAEN_RXCH_0, + DMAEN_RXCH_1, + DMAEN_RXCH_2, + DMAEN_RXCH_3 +}; + +/* Maximum bit resolution of a channel - not uniformly spaced */ +static const u32 fifo_width[COMP_MAX_WORDSIZE] = { + 12, 16, 20, 24, 32, 0, 0, 0 +}; + +/* Width of (DMA) bus */ +static const u32 bus_widths[COMP_MAX_DATA_WIDTH] = { + DMA_SLAVE_BUSWIDTH_1_BYTE, + DMA_SLAVE_BUSWIDTH_2_BYTES, + DMA_SLAVE_BUSWIDTH_4_BYTES, + DMA_SLAVE_BUSWIDTH_UNDEFINED +}; + +static inline u32 i2s_read_reg(void *io_base, int reg) +{ + return readl((char *)io_base + reg); +} + +static inline void i2s_write_reg(void *io_base, int reg, u32 val) +{ + writel(val, (char *)io_base + reg); +} + +static inline void i2s_disable_channels(struct i2s_dev *i2s_drvdata, u32 stream) +{ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + i2s_write_reg(i2s_drvdata->i2s_base, TER(0), 0); + } else { + i2s_write_reg(i2s_drvdata->i2s_base, RER(0), 0); + } +} + +static void i2s_config(struct i2s_dev *i2s_drvdata, int stream) +{ + u32 ch_reg; + struct i2s_clk_config_data *config = &i2s_drvdata->config; + i2s_disable_channels(i2s_drvdata, stream); + for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) { + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + i2s_write_reg(i2s_drvdata->i2s_base, TCR(ch_reg), + i2s_drvdata->xfer_resolution); + i2s_write_reg(i2s_drvdata->i2s_base, TFCR(ch_reg), + i2s_drvdata->fifo_th - 1); + i2s_write_reg(i2s_drvdata->i2s_base, TER(ch_reg), 1); + } else { + i2s_write_reg(i2s_drvdata->i2s_base, RCR(ch_reg), + i2s_drvdata->xfer_resolution); + i2s_write_reg(i2s_drvdata->i2s_base, RFCR(ch_reg), + i2s_drvdata->fifo_th - 1); + i2s_write_reg(i2s_drvdata->i2s_base, RER(ch_reg), 1); + } + } +} + +static inline void i2s_enable_irqs(struct i2s_dev *i2s_drvdata, u32 stream, + int chan_nr) +{ + u32 i, irq; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + for (i = 0; i < (chan_nr / 2); i++) { + irq = i2s_read_reg(i2s_drvdata->i2s_base, IMR(i)); + i2s_write_reg(i2s_drvdata->i2s_base, IMR(i), irq & ~0x30); + } + } else { + for (i = 0; i < (chan_nr / 2); i++) { + irq = i2s_read_reg(i2s_drvdata->i2s_base, IMR(i)); + i2s_write_reg(i2s_drvdata->i2s_base, IMR(i), irq & ~0x03); + } + } +} + +static inline void i2s_enable_dedicated_dma(struct i2s_dev *i2s_drvdata, u32 stream, + int chan_nr) +{ + u32 i, dmacr; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + for (i = 0; i < (chan_nr / 2); i++) { + dmacr = i2s_read_reg(i2s_drvdata->i2s_base, DMACR); + i2s_write_reg(i2s_drvdata->i2s_base, DMACR, dmacr | dmaen_txch[i]); + } + } else { + for (i = 0; i < (chan_nr / 2); i++) { + dmacr = i2s_read_reg(i2s_drvdata->i2s_base, DMACR); + i2s_write_reg(i2s_drvdata->i2s_base, DMACR, dmacr | dmaen_rxch[i]); + } + } +} + +static inline void i2s_disable_dedicated_dma(struct i2s_dev *i2s_drvdata, u32 stream, + int chan_nr) +{ + u32 i, dmacr; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + for (i = 0; i < (chan_nr / 2); i++) { + dmacr = i2s_read_reg(i2s_drvdata->i2s_base, DMACR); + i2s_write_reg(i2s_drvdata->i2s_base, DMACR, dmacr & ~dmaen_txch[i]); + } + } else { + for (i = 0; i < (chan_nr / 2); i++) { + dmacr = i2s_read_reg(i2s_drvdata->i2s_base, DMACR); + i2s_write_reg(i2s_drvdata->i2s_base, DMACR, dmacr & ~dmaen_rxch[i]); + } + } +} + +static inline void i2s_enable_combined_dma(struct i2s_dev *i2s_drvdata, u32 stream) +{ + u32 dmacr; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + dmacr = i2s_read_reg(i2s_drvdata->i2s_base, DMACR); + i2s_write_reg(i2s_drvdata->i2s_base, DMACR, dmacr | DMAEN_TXBLOCK); + + } else { + dmacr = i2s_read_reg(i2s_drvdata->i2s_base, DMACR); + i2s_write_reg(i2s_drvdata->i2s_base, DMACR, dmacr | DMAEN_RXBLOCK); + } +} + +static inline void i2s_disable_combined_dma(struct i2s_dev *i2s_drvdata, u32 stream) +{ + u32 dmacr; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + dmacr = i2s_read_reg(i2s_drvdata->i2s_base, DMACR); + i2s_write_reg(i2s_drvdata->i2s_base, DMACR, dmacr & ~DMAEN_TXBLOCK); + + } else { + dmacr = i2s_read_reg(i2s_drvdata->i2s_base, DMACR); + i2s_write_reg(i2s_drvdata->i2s_base, DMACR, dmacr & ~DMAEN_RXBLOCK); + } +} + +static void i2s_start(struct i2s_dev *i2s_drvdata, + struct snd_pcm_substream *substream) +{ + struct i2s_clk_config_data *config = &i2s_drvdata->config; + i2s_write_reg(i2s_drvdata->i2s_base, IER, 1); + if (i2s_drvdata->use_pio) { + i2s_enable_irqs(i2s_drvdata, substream->stream, config->chan_nr); + } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + i2s_write_reg(i2s_drvdata->i2s_base, ITER, 1); + } else { + i2s_write_reg(i2s_drvdata->i2s_base, IRER, 1); + } + if (!i2s_drvdata->use_pio) { + i2s_enable_dedicated_dma(i2s_drvdata, substream->stream, config->chan_nr); + } + i2s_write_reg(i2s_drvdata->i2s_base, CER, 1); +} + +static inline void i2s_clear_irqs(struct i2s_dev *i2s_drvdata, u32 stream) +{ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + i2s_read_reg(i2s_drvdata->i2s_base, TOR(0)); + } else { + i2s_read_reg(i2s_drvdata->i2s_base, ROR(0)); + } +} + +static inline void i2s_disable_irqs(struct i2s_dev *i2s_drvdata, u32 stream, + int chan_nr) +{ + u32 i, irq; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + for (i = 0; i < (chan_nr / 2); i++) { + irq = i2s_read_reg(i2s_drvdata->i2s_base, IMR(i)); + i2s_write_reg(i2s_drvdata->i2s_base, IMR(i), irq | 0x30); + } + } else { + for (i = 0; i < (chan_nr / 2); i++) { + irq = i2s_read_reg(i2s_drvdata->i2s_base, IMR(i)); + i2s_write_reg(i2s_drvdata->i2s_base, IMR(i), irq | 0x03); + } + } +} + +static void i2s_stop(struct i2s_dev *i2s_drvdata, + struct snd_pcm_substream *substream) +{ + if (i2s_drvdata->use_pio) { + i2s_clear_irqs(i2s_drvdata, substream->stream); + } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + i2s_write_reg(i2s_drvdata->i2s_base, ITER, 0); + } else { + i2s_write_reg(i2s_drvdata->i2s_base, IRER, 0); + } + if (i2s_drvdata->use_pio) { + i2s_disable_irqs(i2s_drvdata, substream->stream, 2); + } else { + i2s_disable_dedicated_dma(i2s_drvdata, substream->stream, 2); + } + if (!i2s_drvdata->active) { + i2s_write_reg(i2s_drvdata->i2s_base, CER, 0); + i2s_write_reg(i2s_drvdata->i2s_base, IER, 0); + } +} + +static irqreturn_t i2s_irq_handler(int irq, void *dev_id) +{ + struct i2s_dev *i2s_drvdata = dev_id; + bool irq_valid = false; + u32 isr; + + isr = i2s_read_reg(i2s_drvdata->i2s_base, ISR(0)); + i2s_clear_irqs(i2s_drvdata, SNDRV_PCM_STREAM_PLAYBACK); + i2s_clear_irqs(i2s_drvdata, SNDRV_PCM_STREAM_CAPTURE); + if ((isr & ISR_TXFE)&& i2s_drvdata->use_pio) { + i2s_pcm_push_tx(i2s_drvdata, STEREO); + irq_valid = true; + } + if ((isr & ISR_RXDA)&& i2s_drvdata->use_pio) { + i2s_pcm_pop_rx(i2s_drvdata, STEREO); + irq_valid = true; + } + if (isr & ISR_TXFO) { + dev_err(i2s_drvdata->dev, "TX overrun (ch_id=%d)\n", 0); + irq_valid = true; + } + if (isr & ISR_RXFO) { + dev_err(i2s_drvdata->dev, "RX overrun (ch_id=%d)\n", 0); + irq_valid = true; + } + + if (irq_valid) { + return IRQ_HANDLED; + } + else { + return IRQ_NONE; + } +} + +#define COMP1_MAX_WORDSIZE 5 +static const u32 i2s_formats[COMP1_MAX_WORDSIZE] = { + SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE +}; + +static int i2s_configure_dai(struct i2s_dev *i2s_drvdata, + struct snd_soc_dai_driver *i2s_dai, + unsigned int rates) +{ + u32 idx; + u32 fifo_depth; + u32 comp1, comp2; + + comp1 = i2s_read_reg(i2s_drvdata->i2s_base, i2s_drvdata->i2s_reg_comp1); + comp2 = i2s_read_reg(i2s_drvdata->i2s_base, i2s_drvdata->i2s_reg_comp2); + fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1)); + + if (COMP1_TX_ENABLED(comp1)) { + dev_dbg(i2s_drvdata->dev, " i2s: play supported\n"); + idx = COMP1_TX_WORDSIZE_0(comp1); + if (WARN_ON(idx >= ARRAY_SIZE(i2s_formats))) + return -EINVAL; + i2s_dai->playback.formats = i2s_formats[idx]; + i2s_dai->playback.channels_min = MIN_CHANNEL_NUM; + i2s_dai->playback.channels_max = + (COMP1_TX_CHANNELS(comp1) + 1) << 1; + i2s_dai->playback.rates = rates; + } + + if (COMP1_RX_ENABLED(comp1)){ + dev_dbg(i2s_drvdata->dev, "i2s: record supported\n"); + idx = COMP2_RX_WORDSIZE_0(comp2); + if (WARN_ON(idx >= ARRAY_SIZE(i2s_formats))) + return -EINVAL; + i2s_dai->capture.formats = i2s_formats[idx]; + i2s_dai->capture.channels_min = MIN_CHANNEL_NUM; + i2s_dai->capture.channels_max = + (COMP1_RX_CHANNELS(comp1) + 1) << 1; + i2s_dai->capture.rates = rates; + } + + if (COMP1_MODE_EN(comp1)) { + dev_dbg(i2s_drvdata->dev, "eswin: i2s master mode supported\n"); + i2s_drvdata->capability |= DW_I2S_MASTER; + } else { + dev_dbg(i2s_drvdata->dev, "eswin: i2s slave mode supported\n"); + i2s_drvdata->capability |= DW_I2S_SLAVE; + } + i2s_drvdata->fifo_th = fifo_depth / 2; + return 0; +} + +static int i2s_configure_dai_by_dt(struct i2s_dev *dev, + struct snd_soc_dai_driver *i2s_dai, + 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; + u32 idx; + u32 idx2; + int ret; + + dev_info(dev->dev, "comp1:0x%x, comp2:0x%x\n", comp1, comp2); + fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1)); + idx = COMP1_APB_DATA_WIDTH(comp1); + + if (WARN_ON(idx >= ARRAY_SIZE(bus_widths))) { + dev_err(dev->dev, "idx:%d inval\n", idx); + return -EINVAL; + } + ret = i2s_configure_dai(dev, i2s_dai, SNDRV_PCM_RATE_8000_192000); + if (ret < 0) { + dev_err(dev->dev, "i2s_configure_dai failed: %d\n", ret); + return ret; + } + 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; + /* only configure Combined DMA addr, Our scenario is not Dedicated DMA case */ + dev->play_dma_data.addr_width = bus_widths[idx]; + dev->play_dma_data.fifo_size = fifo_depth * + (fifo_width[idx2]) >> 3; + if (of_node_name_prefix(pcm->chan[SNDRV_PCM_STREAM_PLAYBACK]->device->dev->of_node, + "dma-controller-hsp")) { + dev->play_dma_data.addr = dma_map_resource( + pcm->chan[SNDRV_PCM_STREAM_PLAYBACK]->device->dev, + res->start + TXDMA_CH(0), + dev->play_dma_data.fifo_size, + DMA_BIDIRECTIONAL, + DMA_ATTR_SKIP_CPU_SYNC); + } else { + dev->play_dma_data.addr = res->start + TXDMA_CH(0); + } + dev->play_dma_data.maxburst = 16; + } + if (COMP1_RX_ENABLED(comp1)) { + idx2 = COMP2_RX_WORDSIZE_0(comp2); + dev->capability |= DWC_I2S_RECORD; + /* only configure Combined DMA addr, Our scenario is not Dedicated DMA case */ + dev->capture_dma_data.addr_width = bus_widths[idx]; + dev->capture_dma_data.fifo_size = fifo_depth * + (fifo_width[idx2]) >> 3; + if (of_node_name_prefix(pcm->chan[SNDRV_PCM_STREAM_CAPTURE]->device->dev->of_node, + "dma-controller-hsp")) { + dev->capture_dma_data.addr = dma_map_resource( + pcm->chan[SNDRV_PCM_STREAM_CAPTURE]->device->dev, + res->start + RXDMA_CH(0), + dev->capture_dma_data.fifo_size, + DMA_BIDIRECTIONAL, + DMA_ATTR_SKIP_CPU_SYNC); + } else { + dev->capture_dma_data.addr = res->start + RXDMA_CH(0); + } + dev->capture_dma_data.maxburst = 16; + } + return 0; +} + +static int i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); + struct snd_dmaengine_dai_dma_data *dma_data = NULL; + + if (!(dev->capability & DWC_I2S_RECORD) && + (substream->stream == SNDRV_PCM_STREAM_CAPTURE)) + return -EINVAL; + + if (!(dev->capability & DWC_I2S_PLAY) && + (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) + return -EINVAL; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dma_data = &dev->play_dma_data; + else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + dma_data = &dev->capture_dma_data; + + snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data); + return 0; +} + + +static int i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct i2s_dev *i2s_drvdata = snd_soc_dai_get_drvdata(dai); + struct i2s_clk_config_data *config = &i2s_drvdata->config; + struct device_node *node = i2s_drvdata->dev->of_node; + struct regmap *vo_mclk_sel_regmap; + uint32_t vo_mclk_sel_reg; + uint32_t vo_mclk_sel; + int ret; + uint32_t div_num = 0; + uint32_t div_num_reg; + + dev_info(i2s_drvdata->dev, "sample rate:%d, chan:%d, width:%d\n", + params_rate(params), params_channels(params), params_width(params)); + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + config->data_width = 16; + i2s_drvdata->ccr = CLOCK_CYCLES_32 << CCR_WSS_POS | + NO_CLOCK_GATING; + i2s_drvdata->xfer_resolution = RESOLUTION_16_BIT; + break; + case SNDRV_PCM_FORMAT_S24_LE: + config->data_width = 24; + i2s_drvdata->ccr = CLOCK_CYCLES_32 << CCR_WSS_POS | + NO_CLOCK_GATING; + i2s_drvdata->xfer_resolution = RESOLUTION_24_BIT; + break; + case SNDRV_PCM_FORMAT_S32_LE: + config->data_width = 32; + i2s_drvdata->ccr = CLOCK_CYCLES_32 << CCR_WSS_POS | + NO_CLOCK_GATING; + i2s_drvdata->xfer_resolution = RESOLUTION_32_BIT; + break; + default: + dev_err(i2s_drvdata->dev, "eswin-i2s: unsupported PCM fmt"); + return -EINVAL; + } + config->chan_nr = params_channels(params); + switch (config->chan_nr) { + case TWO_CHANNEL_SUPPORT: + break; + default: + dev_err(i2s_drvdata->dev, "channel not supported\n"); + return -EINVAL; + } + i2s_config(i2s_drvdata, substream->stream); + 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 (!i2s_drvdata->eswin_plat) { + vo_mclk_sel_regmap = + syscon_regmap_lookup_by_phandle(node, "vo_mclk_sel,syscrg"); + if (IS_ERR(vo_mclk_sel_regmap)) { + dev_err(i2s_drvdata->dev, "No vo_mclk_sel,syscrg phandle specified\n"); + return PTR_ERR(vo_mclk_sel_regmap); + } + ret = of_property_read_u32_index(node, "vo_mclk_sel,syscrg", 1, + &vo_mclk_sel_reg); + if (ret) { + dev_err(i2s_drvdata->dev, "can't get vo_mclk_sel_reg offset (%d)\n", ret); + return ret; + } + regmap_read(vo_mclk_sel_regmap, vo_mclk_sel_reg, &vo_mclk_sel); + vo_mclk_sel &= ~VO_MCLK_DIVSOR_MASK; + + switch (config->sample_rate) { + case 96000: + vo_mclk_sel |= (0x10 << VO_MCLK_DIVSOR_OFFSET); + break; + case 48000: + vo_mclk_sel |= (0x12 << VO_MCLK_DIVSOR_OFFSET); + break; + case 44100: + vo_mclk_sel |= (0x11 << VO_MCLK_DIVSOR_OFFSET); + break; + default: + dev_err(i2s_drvdata->dev, "Can't support sample rate: %d\n", + config->sample_rate); + return -EINVAL; + } + regmap_write(vo_mclk_sel_regmap, vo_mclk_sel_reg, vo_mclk_sel); + } else { + 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; + } + } else { + div_num_reg = i2s_read_reg(i2s_drvdata->i2s_div_base, 0) & ~DIV_NUM_MASK; + div_num_reg |= div_num; + + dev_info(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); + } + } + } + + return 0; +} + +static int i2s_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct i2s_dev *i2s_drvdata = snd_soc_dai_get_drvdata(dai); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + i2s_write_reg(i2s_drvdata->i2s_base, TXFFR, 1); + else + i2s_write_reg(i2s_drvdata->i2s_base, RXFFR, 1); + + return 0; +} + +static int i2s_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct i2s_dev *i2s_drvdata = snd_soc_dai_get_drvdata(dai); + int ret = 0; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + i2s_drvdata->active++; + i2s_start(i2s_drvdata, substream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + i2s_drvdata->playback_active = true; + } else { + i2s_drvdata->capture_active = true; + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + i2s_drvdata->active--; + i2s_stop(i2s_drvdata, substream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + i2s_drvdata->playback_active = false; + } else { + i2s_drvdata->capture_active = false; + } + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static int i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) +{ + struct i2s_dev *i2s_drvdata = snd_soc_dai_get_drvdata(cpu_dai); + int ret = 0; + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: + if (i2s_drvdata->capability & DW_I2S_SLAVE) + ret = 0; + else + ret = -EINVAL; + break; + case SND_SOC_DAIFMT_BP_FP: + if (i2s_drvdata->capability & DW_I2S_MASTER) + ret = 0; + else + ret = -EINVAL; + break; + case SND_SOC_DAIFMT_BC_FP: + case SND_SOC_DAIFMT_BP_FC: + ret = -EINVAL; + break; + default: + dev_dbg(i2s_drvdata->dev, "dwc : Invalid master/slave format\n"); + ret = -EINVAL; + break; + } + return ret; +} + +static int i2s_pcm_dai_probe(struct snd_soc_dai *dai) +{ + struct i2s_dev *i2s_drvdata = snd_soc_dai_get_drvdata(dai); + snd_soc_dai_init_dma_data(dai, &i2s_drvdata->play_dma_data, &i2s_drvdata->capture_dma_data); + + return 0; +} + +static const struct snd_soc_dai_ops i2s_dai_ops = { + .startup = i2s_startup, + .hw_params = i2s_hw_params, + .prepare = i2s_prepare, + .trigger = i2s_trigger, + .set_fmt = i2s_set_fmt, + .probe = i2s_pcm_dai_probe, +}; + +#ifdef CONFIG_PM +static int i2s_runtime_suspend(struct device *dev) +{ + struct i2s_dev *i2s_drvdata = dev_get_drvdata(dev); + if (i2s_drvdata->capability & DW_I2S_MASTER) + clk_disable(i2s_drvdata->clk); + + return 0; +} + +static int i2s_runtime_resume(struct device *dev) +{ + struct i2s_dev *i2s_drvdata = dev_get_drvdata(dev); + if (i2s_drvdata->capability & DW_I2S_MASTER) + clk_enable(i2s_drvdata->clk); + + return 0; +} + +static int i2s_suspend(struct snd_soc_component *component) +{ + struct i2s_dev *i2s_drvdata = snd_soc_component_get_drvdata(component); + if (i2s_drvdata->capability & DW_I2S_MASTER) { + clk_disable(i2s_drvdata->clk); + } + return 0; +} + +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; + int stream; + + if (i2s_drvdata->capability & DW_I2S_MASTER) + clk_enable(i2s_drvdata->clk); + + for_each_component_dais(component, dai) { + for_each_pcm_streams(stream) + if (snd_soc_dai_stream_active(dai, stream)) + i2s_config(i2s_drvdata, stream); + } + return 0; +} + +#else +#define i2s_suspend NULL +#define i2s_resume NULL +#endif + +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; + + rst = devm_reset_control_get_optional_exclusive(&pdev->dev, "i2srst"); + if (IS_ERR(rst)) { + return PTR_ERR(rst); + } + + prst = devm_reset_control_get_optional_exclusive(&pdev->dev, "i2sprst"); + if (IS_ERR(prst)) { + return PTR_ERR(prst); + } + + voprst = devm_reset_control_get_optional_exclusive(&pdev->dev, "voprst"); + if (IS_ERR(prst)) { + return PTR_ERR(prst); + } + + ret = reset_control_assert(rst); + WARN_ON(0 != ret); + ret = reset_control_assert(prst); + WARN_ON(0 != ret); + ret = reset_control_deassert(rst); + WARN_ON(0 != ret); + ret = reset_control_deassert(prst); + WARN_ON(0 != ret); + ret = reset_control_deassert(voprst); + WARN_ON(0 != ret); + + return 0; +} +struct snd_kcontrol_new snd_dump_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .name = "Audio Dump Control", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + } +}; + +static int i2s_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct i2s_dev *i2s_drvdata = snd_soc_component_get_drvdata(component); + + if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK && i2s_drvdata->playback_active == true) || + (substream->stream == SNDRV_PCM_STREAM_CAPTURE && i2s_drvdata->capture_active == true)) { + dev_err(i2s_drvdata->dev, "i2s is busying\n"); + return -EBUSY; + } + return 0; +} + +static const struct snd_soc_component_driver i2s0_component = { + .name = "i2s0", + .open = i2s_open, + .suspend = i2s_suspend, + .resume = i2s_resume, + .controls = snd_dump_controls, + .num_controls = ARRAY_SIZE(snd_dump_controls), +}; + +static const struct snd_soc_component_driver i2s_component = { + .name = "i2s", + .suspend = i2s_suspend, + .resume = i2s_resume, +}; + +static struct snd_soc_dai_driver i2s_dai[4] = { + { + .name = "i2s0-hdmi", + .id = 0, + .ops = &i2s_dai_ops, + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = ESW_I2S_RATES, + .formats = ESW_I2S_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = ESW_I2S_RATES, + .formats = ESW_I2S_FORMATS, + }, + }, + { + .name = "i2s0", + .id = 1, + .ops = &i2s_dai_ops, + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = ESW_I2S_RATES, + .formats = ESW_I2S_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = ESW_I2S_RATES, + .formats = ESW_I2S_FORMATS, + }, + }, + { + .name = "i2s1", + .id = 0, + .ops = &i2s_dai_ops, + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = ESW_I2S_RATES, + .formats = ESW_I2S_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = ESW_I2S_RATES, + .formats = ESW_I2S_FORMATS, + }, + }, + { + .name = "i2s2", + .id = 0, + .ops = &i2s_dai_ops, + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = ESW_I2S_RATES, + .formats = ESW_I2S_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 2, + .rates = ESW_I2S_RATES, + .formats = ESW_I2S_FORMATS, + }, + }, +}; + +static int i2s_probe(struct platform_device *pdev) +{ + struct i2s_dev *i2s_drvdata; + struct resource *res; + int ret, irq; + const char *clk_id; + struct snd_dmaengine_pcm_config *config; + + 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)) { + dev_err(&pdev->dev, "devm_ioremap_resource failed\n"); + return PTR_ERR(i2s_drvdata->i2s_base); + } + i2s_drvdata->dev = &pdev->dev; + + clk_id = "mclk"; + if (of_node_name_prefix(pdev->dev.of_node, "i2s0")) { + i2s_drvdata->clk = devm_clk_get(&pdev->dev, clk_id); + if (IS_ERR(i2s_drvdata->clk)) + return PTR_ERR(i2s_drvdata->clk); + ret = clk_prepare_enable(i2s_drvdata->clk); + if (ret < 0) + return ret; + ret = clk_set_rate(i2s_drvdata->clk, MAX_SAMPLE_RATE_CLK); + if (ret) { + dev_err(i2s_drvdata->dev, "Can't set I2S clock rate: %d\n", ret); + } + + ret = i2s_reset(pdev, i2s_drvdata); + if (ret != 0) { + dev_err(&pdev->dev, "i2s_reset failed\n"); + goto err_probe; + } + } + + dev_set_drvdata(&pdev->dev, i2s_drvdata); + irq = platform_get_irq(pdev,0); + if (irq >= 0) { + ret = devm_request_irq(&pdev->dev, irq, i2s_irq_handler, 0, pdev->name, i2s_drvdata); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request irq\n"); + return ret; + } + } + + if (of_node_name_prefix(pdev->dev.of_node, "i2s0")) { + i2s_drvdata->i2s_div_base = devm_ioremap(i2s_drvdata->dev, VO_TOP_CSR + VO_I2S0_DIV_NUM, 4); + if (!i2s_drvdata->i2s_div_base) { + dev_err(&pdev->dev, "failed to remap i2s0 div config\n"); + return -ENOMEM; + } + ret = devm_snd_soc_register_component(&pdev->dev, &i2s0_component, + &i2s_dai[0], 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) { + dev_err(&pdev->dev, "failed to remap i2s1 div config\n"); + return -ENOMEM; + } + ret = devm_snd_soc_register_component(&pdev->dev, &i2s_component, + &i2s_dai[2], 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) { + dev_err(&pdev->dev, "failed to remap i2s2 div config\n"); + return -ENOMEM; + } + ret = devm_snd_soc_register_component(&pdev->dev, &i2s_component, + &i2s_dai[3], 1); + } + if (ret != 0) { + dev_err(&pdev->dev, "not able to register dai\n"); + goto err_probe; + } + + if (irq >= 0) { + ret = i2s_pcm_register(pdev); + i2s_drvdata->use_pio = true; + } else { + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, config, 0); + i2s_drvdata->use_pio = false; + } + 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; + i2s_drvdata->i2s_reg_comp2 = I2S_COMP_PARAM_2; + ret = i2s_configure_dai_by_dt(i2s_drvdata, &i2s_dai[0], res); + if (ret < 0) { + dev_err(&pdev->dev, "i2s_configure_dai_by_dt failed\n"); + return ret; + } + + ret = device_property_read_u32(&pdev->dev, "eswin-plat", &i2s_drvdata->eswin_plat); + if (0 != ret) { + dev_warn(&pdev->dev, "Failed to get eswin platform\n"); + i2s_drvdata->eswin_plat = 0; + } + dev_info(&pdev->dev, "eswin platform:%d\n", i2s_drvdata->eswin_plat); + + pm_runtime_enable(&pdev->dev); + + audio_proc_module_init(); + + return 0; +err_probe: + if (i2s_drvdata->capability & DW_I2S_MASTER) + clk_disable_unprepare(i2s_drvdata->clk); + return ret; +} + +static int i2s_remove(struct platform_device *pdev) +{ + struct i2s_dev *i2s_drvdata = dev_get_drvdata(&pdev->dev); + if (i2s_drvdata->capability & DW_I2S_MASTER) + clk_disable_unprepare(i2s_drvdata->clk); + + pm_runtime_disable(&pdev->dev); + + audio_proc_module_exit(); + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id i2s_of_match[] = { + { .compatible = "snps,i2s", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, i2s_of_match); +#endif + +static const struct dev_pm_ops i2s_pm_ops = { + SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume, NULL) +}; + +static struct platform_driver i2s_driver = { + .probe = i2s_probe, + .remove = i2s_remove, + .driver = { + .name = "i2s", + .of_match_table = of_match_ptr(i2s_of_match), + .pm = &i2s_pm_ops, + }, +}; + +module_platform_driver(i2s_driver); + +MODULE_AUTHOR("ESWIN, INC."); +MODULE_DESCRIPTION("I2S driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/eswin/i2s.h b/sound/soc/eswin/i2s.h new file mode 100644 index 0000000000000..6a59a7d335e6b --- /dev/null +++ b/sound/soc/eswin/i2s.h @@ -0,0 +1,216 @@ +/* + * + * Copyright (C) 2021 ESWIN, Inc. 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. + * + * 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. + * + */ + +#ifndef __I2S_H +#define __I2S_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* defaults */ +#define MAX_BUFFER_SIZE (64*1024) +#define MIN_PERIOD_SIZE 64 +#define MAX_PERIOD_SIZE MAX_BUFFER_SIZE +#define USE_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) +#define USE_RATE SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000 +#define USE_RATE_MIN 5500 +#define USE_RATE_MAX 48000 +#define USE_CHANNELS_MIN 1 +#define USE_CHANNELS_MAX 2 +#define USE_PERIODS_MIN 1 +#define USE_PERIODS_MAX 1024 + +/* common register for all channel */ +#define IER 0x000 +#define IRER 0x004 +#define ITER 0x008 +#define CER 0x00C +#define CCR 0x010 +#define RXFFR 0x014 +#define TXFFR 0x018 + +/* DMA Control Register Offset */ +#define DMACR 0x200 +/* DMA Control Register fields */ +#define DMAEN_TXBLOCK BIT(17) +#define DMAEN_RXBLOCK BIT(16) +#define DMAEN_TXCH_3 BIT(11) +#define DMAEN_TXCH_2 BIT(10) +#define DMAEN_TXCH_1 BIT(9) +#define DMAEN_TXCH_0 BIT(8) +#define DMAEN_RXCH_3 BIT(3) +#define DMAEN_RXCH_2 BIT(2) +#define DMAEN_RXCH_1 BIT(1) +#define DMAEN_RXCH_0 BIT(0) + +/* Interrupt status register fields */ +#define ISR_TXFO BIT(5) +#define ISR_TXFE BIT(4) +#define ISR_RXFO BIT(1) +#define ISR_RXDA BIT(0) + +/* I2STxRxRegisters for all channels */ +#define LRBR_LTHR(x) (0x40 * x + 0x020) +#define RRBR_RTHR(x) (0x40 * x + 0x024) +#define RER(x) (0x40 * x + 0x028) +#define TER(x) (0x40 * x + 0x02C) +#define RCR(x) (0x40 * x + 0x030) +#define TCR(x) (0x40 * x + 0x034) +#define ISR(x) (0x40 * x + 0x038) +#define IMR(x) (0x40 * x + 0x03C) +#define ROR(x) (0x40 * x + 0x040) +#define TOR(x) (0x40 * x + 0x044) +#define RFCR(x) (0x40 * x + 0x048) +#define TFCR(x) (0x40 * x + 0x04C) +#define RFF(x) (0x40 * x + 0x050) +#define TFF(x) (0x40 * x + 0x054) + +/* I2SCOMPRegisters */ +#define I2S_COMP_PARAM_2 0x01F0 +#define I2S_COMP_PARAM_1 0x01F4 +#define I2S_COMP_VERSION 0x01F8 +#define I2S_COMP_TYPE 0x01FC + +/* I2S DMA registers */ +#define RXDMA_CH(x) (0x4 * x + 0x204) +#define TXDMA_CH(x) (0x4 * x + 0x214) + +/* + * Component parameter register fields - define the I2S block's + * configuration. + */ +#define COMP1_TX_WORDSIZE_3(r) (((r) & GENMASK(27, 25)) >> 25) +#define COMP1_TX_WORDSIZE_2(r) (((r) & GENMASK(24, 22)) >> 22) +#define COMP1_TX_WORDSIZE_1(r) (((r) & GENMASK(21, 19)) >> 19) +#define COMP1_TX_WORDSIZE_0(r) (((r) & GENMASK(18, 16)) >> 16) +#define COMP1_TX_CHANNELS(r) (((r) & GENMASK(10, 9)) >> 9) +#define COMP1_RX_CHANNELS(r) (((r) & GENMASK(8, 7)) >> 7) +#define COMP1_RX_ENABLED(r) (((r) & BIT(6)) >> 6) +#define COMP1_TX_ENABLED(r) (((r) & BIT(5)) >> 5) +#define COMP1_MODE_EN(r) (((r) & BIT(4)) >> 4) +#define COMP1_FIFO_DEPTH_GLOBAL(r) (((r) & GENMASK(3, 2)) >> 2) +#define COMP1_APB_DATA_WIDTH(r) (((r) & GENMASK(1, 0)) >> 0) +#define COMP2_RX_WORDSIZE_3(r) (((r) & GENMASK(12, 10)) >> 10) +#define COMP2_RX_WORDSIZE_2(r) (((r) & GENMASK(9, 7)) >> 7) +#define COMP2_RX_WORDSIZE_1(r) (((r) & GENMASK(5, 3)) >> 3) +#define COMP2_RX_WORDSIZE_0(r) (((r) & GENMASK(2, 0)) >> 0) + +/* Number of entries in WORDSIZE and DATA_WIDTH parameter registers */ +#define COMP_MAX_WORDSIZE (1 << 3) +#define COMP_MAX_DATA_WIDTH (1 << 2) +#define MAX_CHANNEL_NUM 8 +#define MIN_CHANNEL_NUM 2 +#define STEREO 0 +#define TDM 1 + +#define CCR_SCLKG_POS 0 +#define CCR_WSS_POS 3 + +enum { + CLOCK_CYCLES_16, + CLOCK_CYCLES_24, + CLOCK_CYCLES_32 +}; + +enum { + NO_CLOCK_GATING, + GATE_CLOCK_CYCLES_12, + GATE_CLOCK_CYCLES_16, + GATE_CLOCK_CYCLES_20, + GATE_CLOCK_CYCLES_24 +}; + +enum { + IGNORE_WORD_LENGTH, + RESOLUTION_12_BIT, + RESOLUTION_16_BIT, + RESOLUTION_20_BIT, + RESOLUTION_24_BIT, + RESOLUTION_32_BIT +}; + +struct i2s_dev { + void __iomem *i2s_base; + struct clk *clk; + struct device *dev; + unsigned int i2s_reg_comp1; + unsigned int i2s_reg_comp2; + unsigned int capability; + 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 i2s_clk_config_data config; + struct snd_pcm_substream __rcu *tx_substream; + struct snd_pcm_substream __rcu *rx_substream; + unsigned int (*tx_fn)(struct i2s_dev *dev, + struct snd_pcm_runtime *runtime, unsigned int tx_ptr, + bool *period_elapsed,int type); + unsigned int (*rx_fn)(struct i2s_dev *dev, + struct snd_pcm_runtime *runtime, unsigned int rx_ptr, + bool *period_elapsed,int type); + unsigned int tx_ptr; + unsigned int rx_ptr; + u32 xfer_resolution; + int active; + u32 ccr; + void __iomem *i2s_div_base; + u32 i2s_div_num; + bool playback_active; + bool capture_active; + u32 eswin_plat; +}; + +static const struct snd_pcm_hardware pcm_hardware = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_MMAP_VALID), + .formats = USE_FORMATS, + .rates = USE_RATE, + .rate_min = USE_RATE_MIN, + .rate_max = USE_RATE_MAX, + .channels_min = USE_CHANNELS_MIN, + .channels_max = USE_CHANNELS_MAX, + .buffer_bytes_max = MAX_BUFFER_SIZE, + .period_bytes_min = MIN_PERIOD_SIZE, + .period_bytes_max = MAX_PERIOD_SIZE, + .periods_min = USE_PERIODS_MIN, + .periods_max = USE_PERIODS_MAX, + .fifo_size = 0, +}; + +#if IS_ENABLED(CONFIG_SND_ESWIN_DW_PCM) +void i2s_pcm_push_tx(struct i2s_dev *i2s_drvdata,int type); +void i2s_pcm_pop_rx(struct i2s_dev *i2s_drvdata,int type); +int i2s_pcm_register(struct platform_device *pdev); +#else +static inline void i2s_pcm_push_tx(struct i2s_dev *i2s_drvdata,int type) { } +static inline void i2s_pcm_pop_rx(struct i2s_dev *i2s_drvdata,int type) { } +static inline int i2s_pcm_register(struct platform_device *pdev) +{ + return -EINVAL; +} +#endif +#endif /* __I2S_H */ diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 844a2ef15948c..5e4ab738d4c96 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -161,6 +161,9 @@ static int graph_link_init(struct asoc_simple_priv *priv, if (priv->ops) dai_link->ops = priv->ops; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + dai_link->trigger_stop = SND_SOC_TRIGGER_ORDER_LDC; +#endif return asoc_simple_set_dailink_name(dev, dai_link, name); } diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index cad222eb9a293..150d682637580 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -15,7 +15,12 @@ #include +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +static unsigned int prealloc_buffer_size_kbytes = 1024; +#else static unsigned int prealloc_buffer_size_kbytes = 512; +#endif + module_param(prealloc_buffer_size_kbytes, uint, 0444); MODULE_PARM_DESC(prealloc_buffer_size_kbytes, "Preallocate DMA buffer size (KB)."); @@ -152,6 +157,13 @@ static int dmaengine_pcm_open(struct snd_soc_component *component, struct dma_chan *chan = pcm->chan[substream->stream]; int ret; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + pcm->tmp_buf[substream->stream] = + kzalloc(prealloc_buffer_size_kbytes * 1024, GFP_KERNEL); + if (!pcm->tmp_buf[substream->stream]) { + return -ENOMEM; + } +#endif ret = dmaengine_pcm_set_runtime_hwparams(component, substream); if (ret) return ret; @@ -162,6 +174,13 @@ static int dmaengine_pcm_open(struct snd_soc_component *component, static int dmaengine_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + struct dmaengine_pcm *pcm = soc_component_to_pcm(component); + + if (pcm->tmp_buf[substream->stream]) { + kfree(pcm->tmp_buf[substream->stream]); + } +#endif return snd_dmaengine_pcm_close(substream); } @@ -287,6 +306,72 @@ static snd_pcm_uframes_t dmaengine_pcm_pointer( return snd_dmaengine_pcm_pointer(substream); } +#ifdef CONFIG_SOC_SIFIVE_EIC7700 +static int dmaengine_pcm_process(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + struct iov_iter *buf, unsigned long bytes) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct dmaengine_pcm *pcm = soc_component_to_pcm(component); + 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; + unsigned int lc_size = runtime->frame_bits / 8 / 2; + unsigned int rc_size = runtime->frame_bits / 8 / 2; + char *tb_ptr; + + if (is_playback) { + if (runtime->sample_bits != 32) { + if (copy_from_iter(pcm->tmp_buf[0], bytes, buf) != bytes) { + return -EFAULT; + } + + frames = bytes_to_frames(runtime, bytes); + tb_ptr = pcm->tmp_buf[0]; + while (frames) { + memcpy(dma_ptr, tb_ptr, lc_size); + memset(dma_ptr + lc_size, 0, (4 - lc_size)); + dma_ptr += 4; + tb_ptr += lc_size; + memcpy(dma_ptr, tb_ptr, rc_size); + memset(dma_ptr + rc_size, 0, (4 - rc_size)); + dma_ptr += 4; + tb_ptr += rc_size; + frames--; + } + } else { + if (copy_from_iter(dma_ptr, bytes, buf) != bytes) { + return -EFAULT; + } + } + } else { + if (runtime->sample_bits != 32) { + frames = bytes_to_frames(runtime, bytes); + tb_ptr = pcm->tmp_buf[1]; + while (frames) { + memcpy(tb_ptr, dma_ptr, lc_size); + tb_ptr += lc_size; + dma_ptr += 4; + memcpy(tb_ptr, dma_ptr, rc_size); + tb_ptr += rc_size; + dma_ptr += 4; + frames--; + } + if (copy_to_iter(pcm->tmp_buf[1], bytes, buf) != bytes) { + return -EFAULT; + } + } else { + if (copy_to_iter(dma_ptr, bytes, buf) != bytes) { + return -EFAULT; + } + } + } + return 0; +} +#endif + static int dmaengine_copy(struct snd_soc_component *component, struct snd_pcm_substream *substream, int channel, unsigned long hwoff, @@ -326,6 +411,9 @@ static const struct snd_soc_component_driver dmaengine_pcm_component = { .hw_params = dmaengine_pcm_hw_params, .trigger = dmaengine_pcm_trigger, .pointer = dmaengine_pcm_pointer, +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + .copy = dmaengine_pcm_process, +#endif .pcm_construct = dmaengine_pcm_new, }; From 919c69264333b734c8a0b73879cd6c5b6cde467c Mon Sep 17 00:00:00 2001 From: xuxiang Date: Tue, 30 Jul 2024 13:42:40 +0000 Subject: [PATCH 23/38] drivers: pwm: Added ESWIN pwm driver Signed-off-by: xuxiang Signed-off-by: Pinkesh Vaghela Signed-off-by: Pritesh Patel --- drivers/pwm/Kconfig | 6 + drivers/pwm/Makefile | 1 + drivers/pwm/pwm-eswin.c | 326 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 333 insertions(+) create mode 100644 drivers/pwm/pwm-eswin.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 8ebcddf91f7b7..a7c9ac6c78704 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -205,6 +205,12 @@ config PWM_EP93XX To compile this driver as a module, choose M here: the module will be called pwm-ep93xx. +config PWM_ESWIN + tristate "ESWIN PWM support" + help + Generic PWM framework driver for the PWM controller found on + ESWIN SoCs. + config PWM_FSL_FTM tristate "Freescale FlexTimer Module (FTM) PWM support" depends on HAS_IOMEM diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index c822389c2a24c..f3619959f5084 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_PWM_CRC) += pwm-crc.o obj-$(CONFIG_PWM_CROS_EC) += pwm-cros-ec.o obj-$(CONFIG_PWM_DWC) += pwm-dwc.o obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o +obj-$(CONFIG_PWM_ESWIN) += pwm-eswin.o obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o obj-$(CONFIG_PWM_IMG) += pwm-img.o diff --git a/drivers/pwm/pwm-eswin.c b/drivers/pwm/pwm-eswin.c new file mode 100644 index 0000000000000..1d15a3e06c8b5 --- /dev/null +++ b/drivers/pwm/pwm-eswin.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2022, ESWIN, Inc. + * Author: zhangchunyun@eswincomputing.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ESWIN_TIM_LD_CNT(n) ((n) * 0x14) +#define ESWIN_TIM_LD_CNT2(n) (((n) * 4) + 0xb0) +#define ESWIN_TIM_CUR_VAL(n) (((n) * 0x14) + 0x04) +#define ESWIN_TIM_CTRL(n) (((n) * 0x14) + 0x08) +#define ESWIN_TIM_EOI(n) (((n) * 0x14) + 0x0c) +#define ESWIN_TIM_INT_STS(n) (((n) * 0x14) + 0x10) + +#define ESWIN_TIMERS_INT_STS 0xa0 +#define ESWIN_TIMERS_EOI 0xa4 +#define ESWIN_TIMERS_RAW_INT_STS 0xa8 +#define ESWIN_TIMERS_COMP_VERSION 0xac + +#define ESWIN_TIMERS_TOTAL 8 +#define NSEC_TO_SEC 1000000000 + +/* Timer Control Register */ +#define ESWIN_TIM_CTRL_EN BIT(0) +#define ESWIN_TIM_CTRL_MODE BIT(1) +#define ESWIN_TIM_CTRL_MODE_FREE (0 << 1) +#define ESWIN_TIM_CTRL_MODE_USER (1 << 1) +#define ESWIN_TIM_CTRL_INT_MASK BIT(2) +#define ESWIN_TIM_CTRL_PWM BIT(3) + +struct eswin_pwm_ctx { + u32 cnt; + u32 cnt2; + u32 ctrl; +}; + +struct eswin_pwm { + struct pwm_chip chip; + void __iomem *base; + struct clk *clk; + struct clk *pclk; + struct eswin_pwm_ctx ctx[ESWIN_TIMERS_TOTAL]; + struct reset_control * pwm_rst; + u32 clk_period_ns; +}; + +#define to_eswin_pwm(p) (container_of((p), struct eswin_pwm, chip)) + +static inline u32 eswin_pwm_readl(struct eswin_pwm *eswin, u32 offset) +{ + return readl(eswin->base + offset); +} + +static inline void eswin_pwm_writel(struct eswin_pwm *eswin, u32 value, u32 offset) +{ + writel(value, eswin->base + offset); +} + +static void __eswin_pwm_set_enable(struct eswin_pwm *eswin, int pwm, int enabled) +{ + u32 reg; + + reg = eswin_pwm_readl(eswin, ESWIN_TIM_CTRL(pwm)); + + if (enabled) + reg |= ESWIN_TIM_CTRL_EN; + else + reg &= ~ESWIN_TIM_CTRL_EN; + + eswin_pwm_writel(eswin, reg, ESWIN_TIM_CTRL(pwm)); + reg = eswin_pwm_readl(eswin, ESWIN_TIM_CTRL(pwm)); +} + +static int __eswin_pwm_configure_timer(struct eswin_pwm *eswin, + struct pwm_device *pwm, + const struct pwm_state *state) +{ + u64 tmp; + u32 ctrl; + u32 high; + u32 low; + + /* + ¦* Calculate width of low and high period in terms of input clock + ¦* periods and check are the result within HW limits between 1 and + ¦* 2^32 periods. + ¦*/ + + tmp = DIV_ROUND_CLOSEST_ULL(state->duty_cycle, eswin->clk_period_ns); + if (tmp < 1 || tmp > (1ULL << 32)) + return -ERANGE; + high = tmp - 1; + + tmp = DIV_ROUND_CLOSEST_ULL(state->period - state->duty_cycle, + eswin->clk_period_ns); + if (tmp < 1 || tmp > (1ULL << 32)) + return -ERANGE; + low = tmp - 1; + /* + ¦* Specification says timer usage flow is to disable timer, then + ¦* program it followed by enable. It also says Load Count is loaded + ¦* into timer after it is enabled - either after a disable or + ¦* a reset. Based on measurements it happens also without disable + ¦* whenever Load Count is updated. But follow the specification. + ¦*/ + __eswin_pwm_set_enable(eswin, pwm->hwpwm, false); + + /* + ¦* Write Load Count and Load Count 2 registers. Former defines the + ¦* width of low period and latter the width of high period in terms + ¦* multiple of input clock periods: + ¦* Width = ((Count + 1) * input clock period). + ¦*/ + eswin_pwm_writel(eswin, low, ESWIN_TIM_LD_CNT(pwm->hwpwm)); + eswin_pwm_writel(eswin, high, ESWIN_TIM_LD_CNT2(pwm->hwpwm)); + + /* + ¦* Set user-defined mode, timer reloads from Load Count registers + ¦* when it counts down to 0. + ¦* Set PWM mode, it makes output to toggle and width of low and high + ¦* periods are set by Load Count registers. + ¦*/ + ctrl = ESWIN_TIM_CTRL_MODE_USER | ESWIN_TIM_CTRL_PWM; + eswin_pwm_writel(eswin, ctrl, ESWIN_TIM_CTRL(pwm->hwpwm)); + + /* + ¦* Enable timer. Output starts from low period. + ¦*/ + __eswin_pwm_set_enable(eswin, pwm->hwpwm, state->enabled); + + return 0; +} + +static int eswin_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct eswin_pwm *eswin = to_eswin_pwm(chip); + struct pwm_state curstate; + int ret = 0; + + ret = clk_enable(eswin->pclk); + + ret = clk_enable(eswin->clk); + + pwm_get_state(pwm, &curstate); + + __eswin_pwm_configure_timer(eswin, pwm, state); + + return 0; +} + +static int eswin_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct eswin_pwm *eswin = to_eswin_pwm(chip); + u64 duty, period; + + pm_runtime_get_sync(chip->dev); + + state->enabled = !!(eswin_pwm_readl(eswin, + ESWIN_TIM_CTRL(pwm->hwpwm)) & ESWIN_TIM_CTRL_EN); + + duty = eswin_pwm_readl(eswin, ESWIN_TIM_LD_CNT(pwm->hwpwm)); + duty += 1; + duty *= eswin->clk_period_ns; + state->duty_cycle = duty; + + period = eswin_pwm_readl(eswin, ESWIN_TIM_LD_CNT2(pwm->hwpwm)); + period += 1; + period *= eswin->clk_period_ns; + period += duty; + state->period = period; + + state->polarity = PWM_POLARITY_INVERSED; + + pm_runtime_put_sync(chip->dev); + + return 0; +} + + +static const struct pwm_ops eswin_pwm_ops = { + .get_state = eswin_pwm_get_state, + .apply = eswin_pwm_apply, + .owner = THIS_MODULE, +}; + +static const struct of_device_id eswin_pwm_dt_ids[] = { + { .compatible = "eswin,pwm-eswin", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, eswin_pwm_dt_ids); + +static int eswin_pwm_probe(struct platform_device *pdev) +{ + struct eswin_pwm *pc; + int ret, count; + struct resource *res; + int clk_rate; + + pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); + if (!pc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + pc->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pc->base)) + return PTR_ERR(pc->base); + + pc->clk = devm_clk_get(&pdev->dev, "pwm"); + if (IS_ERR(pc->clk)) { + pc->clk = devm_clk_get(&pdev->dev, "pclk"); + if (IS_ERR(pc->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk), + "Can't get PWM clk\n"); + } + + count = of_count_phandle_with_args(pdev->dev.of_node, + "clocks", "#clock-cells"); + if (count == 2) + pc->pclk = devm_clk_get(&pdev->dev, "pclk"); + else + pc->pclk = pc->clk; + + if (IS_ERR(pc->pclk)) { + ret = PTR_ERR(pc->pclk); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Can't get APB clk: %d\n", ret); + return ret; + } + + clk_rate = clk_get_rate(pc->pclk); + pc->clk_period_ns = DIV_ROUND_CLOSEST_ULL(NSEC_TO_SEC, clk_rate); + + /* pwm reset init */ + pc->pwm_rst = devm_reset_control_get_optional(&pdev->dev, "pwmrst"); + if(IS_ERR_OR_NULL(pc->pwm_rst)) { + dev_err(&pdev->dev, "Failed to get pwmrst reset handle\n"); + return -EFAULT; + } + + ret = clk_prepare_enable(pc->clk); + if (ret) { + dev_err(&pdev->dev, "Can't prepare enable PWM clk: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(pc->pclk); + if (ret) { + dev_err(&pdev->dev, "Can't prepare enable APB clk: %d\n", ret); + goto err_clk; + } + + /* reset pwm */ + ret = reset_control_assert(pc->pwm_rst); + WARN_ON(0 != ret); + ret = reset_control_deassert(pc->pwm_rst); + WARN_ON(0 != ret); + + platform_set_drvdata(pdev, pc); + + pc->chip.dev = &pdev->dev; + pc->chip.ops = &eswin_pwm_ops; + pc->chip.npwm = 3; + + ret = pwmchip_add(&pc->chip); + if (ret < 0) { + dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); + goto err_pclk; + } + + return 0; + +err_pclk: + clk_disable_unprepare(pc->pclk); +err_clk: + clk_disable_unprepare(pc->clk); + + return ret; +} + +static int eswin_pwm_remove(struct platform_device *pdev) +{ + struct eswin_pwm *pc = platform_get_drvdata(pdev); + + pwmchip_remove(&pc->chip); + + clk_disable_unprepare(pc->pclk); + clk_disable_unprepare(pc->clk); + + return 0; +} + +static struct platform_driver eswin_pwm_driver = { + .driver = { + .name = "eswin-pwm", + .of_match_table = eswin_pwm_dt_ids, + }, + .probe = eswin_pwm_probe, + .remove = eswin_pwm_remove, +}; +module_platform_driver(eswin_pwm_driver); + +MODULE_DESCRIPTION("eswin SoC PWM driver"); +MODULE_AUTHOR("zhangchunyun@eswincomputing.com"); +MODULE_LICENSE("GPL"); + From 132c616af83916c9280fbaa9eb7c1d6e999f2d75 Mon Sep 17 00:00:00 2001 From: luyulin Date: Tue, 30 Jul 2024 14:07:16 +0000 Subject: [PATCH 24/38] drivers: hwmon: fan-control: Add ESWIN fancontrol driver Signed-off-by: luyulin Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/hwmon/Kconfig | 9 + drivers/hwmon/Makefile | 1 + drivers/hwmon/eswin-fan-control.c | 493 ++++++++++++++++++++++++++++++ 3 files changed, 503 insertions(+) create mode 100644 drivers/hwmon/eswin-fan-control.c diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index ec38c88921589..c59531ae55148 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -310,6 +310,15 @@ config SENSORS_AXI_FAN_CONTROL This driver can also be built as a module. If so, the module will be called axi-fan-control +config SENSORS_ESWIN_FAN_CONTROL + tristate "ESWIN FAN Control Core driver" + help + If you say yes here you get support for the Analog Devices + ESWIN FAN monitoring core. + + This driver can also be built as a module. If so, the module + will be called eswin-fan-control + config SENSORS_K8TEMP tristate "AMD Athlon64/FX or Opteron temperature sensor" depends on X86 && PCI diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 4ac9452b54304..3a9663090c3f0 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -72,6 +72,7 @@ obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o obj-$(CONFIG_SENSORS_EMC2305) += emc2305.o obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o +obj-$(CONFIG_SENSORS_ESWIN_FAN_CONTROL) += eswin-fan-control.o obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o obj-$(CONFIG_SENSORS_F75375S) += f75375s.o diff --git a/drivers/hwmon/eswin-fan-control.c b/drivers/hwmon/eswin-fan-control.c new file mode 100644 index 0000000000000..5b7311cc9d6d7 --- /dev/null +++ b/drivers/hwmon/eswin-fan-control.c @@ -0,0 +1,493 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Fan Control CORE driver + * + * Copyright 2022 ESWIN Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FAN_PWM_DUTY 0x0 +#define FAN_PWM_PERIOD 0x1 +#define FAN_PWM_FREE 0x2 + +/* register map */ +#define REG_FAN_INT 0x0 +#define REG_FAN_RPM 0x4 + +/* wait for 50 times pwm period to trigger read interrupt */ +#define TIMEOUT(period) nsecs_to_jiffies(50*(period)) + +struct eswin_fan_control_data { + struct reset_control *fan_rst; + struct clk *clk; + void __iomem *base; + struct device *hdev; + unsigned long clk_rate; + int pwm_id; + struct pwm_device *pwm; + wait_queue_head_t wq; + bool wait_flag; + int irq; + /* pwm minimum period */ + u32 min_period; + /* pulses per revolution */ + u32 ppr; + /* revolutions per minute */ + u32 rpm; +}; + +static inline void fan_iowrite(const u32 val, const u32 reg, + const struct eswin_fan_control_data *ctl) +{ + iowrite32(val, ctl->base + reg); +} + +static inline u32 fan_ioread(const u32 reg, + const struct eswin_fan_control_data *ctl) +{ + return ioread32(ctl->base + reg); +} + +static ssize_t eswin_fan_pwm_ctl_show(struct device *dev, struct device_attribute *da, char *buf) +{ + struct eswin_fan_control_data *ctl = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + long temp = 0; + + if (FAN_PWM_DUTY == attr->index) { + temp = pwm_get_duty_cycle(ctl->pwm); + } + else if (FAN_PWM_PERIOD == attr->index) { + temp = pwm_get_period(ctl->pwm); + } + else { + dev_err(dev, "get error attr index 0x%x\n", attr->index); + } + + return sprintf(buf, "%lu\n", temp); +} + +static ssize_t eswin_fan_pwm_ctl_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct eswin_fan_control_data *ctl = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct pwm_state state; + int ret; + + pwm_get_state(ctl->pwm, &state); + + if (FAN_PWM_DUTY == attr->index) { + long val = 0; + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + state.duty_cycle = val; + } + else if (FAN_PWM_PERIOD == attr->index) { + long val = 0; + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + if (val >= ctl->min_period) + state.period = val; + else + dev_err(dev, "invalid pwm period!\n"); + } + else { + dev_err(dev, "get error attr index 0x%x\n", attr->index); + } + + pwm_apply_state(ctl->pwm, &state); + + return count; +} + +static ssize_t eswin_fan_pwm_free_store(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct eswin_fan_control_data *ctl = dev_get_drvdata(dev); + long val; + int ret; + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + if (val) { + pwm_put(ctl->pwm); + } + + return count; +} + +static long eswin_fan_control_get_pwm_duty(const struct eswin_fan_control_data *ctl) +{ + struct pwm_state state; + int duty; + + pwm_get_state(ctl->pwm, &state); + duty = pwm_get_relative_duty_cycle(&state, 100); + + return duty; +} + +static long eswin_fan_control_get_fan_rpm(struct eswin_fan_control_data *ctl) +{ + unsigned int val; + long period, timeout; + int ret; + + ctl->wait_flag = false; + period = pwm_get_period(ctl->pwm); + timeout = TIMEOUT(period); + if(!timeout) + timeout = TIMEOUT(ctl->min_period); + + val = fan_ioread(REG_FAN_INT, ctl); + val = val | 0x1; + fan_iowrite(val, REG_FAN_INT, ctl); + + /* wait read interrupt */ + ret = wait_event_interruptible_timeout(ctl->wq, + ctl->wait_flag, + timeout); + + if (!ret){ + /* timeout, set rpm to 0 */ + ctl->rpm = 0; + } + + if(ctl->rpm) + ctl->rpm = DIV_ROUND_CLOSEST(60 * ctl->clk_rate, ctl->ppr * ctl->rpm); + + return ret; +} + +static int eswin_fan_control_read_fan(struct device *dev, u32 attr, long *val) +{ + struct eswin_fan_control_data *ctl = dev_get_drvdata(dev); + + switch (attr) { + case hwmon_fan_input: + if(!eswin_fan_control_get_fan_rpm(ctl)){ + dev_err(dev, "wait read interrupt timeout!\n"); + } + *val = ctl->rpm; + return 0; + default: + return -ENOTSUPP; + } +} + +static int eswin_fan_control_read_pwm(struct device *dev, u32 attr, long *val) +{ + struct eswin_fan_control_data *ctl = dev_get_drvdata(dev); + + switch (attr) { + case hwmon_pwm_input: + *val = eswin_fan_control_get_pwm_duty(ctl); + return 0; + default: + return -ENOTSUPP; + } +} + +static int eswin_fan_control_set_pwm_duty(const long val, struct eswin_fan_control_data *ctl) +{ + struct pwm_state state; + + pwm_get_state(ctl->pwm, &state); + pwm_set_relative_duty_cycle(&state, val, 100); + pwm_apply_state(ctl->pwm, &state); + + return 0; +} + +static int eswin_fan_control_write_pwm(struct device *dev, u32 attr, long val) +{ + struct eswin_fan_control_data *ctl = dev_get_drvdata(dev); + + switch (attr) { + case hwmon_pwm_input: + if((val < 0)||(val > 100)) + return -EINVAL; + else + return eswin_fan_control_set_pwm_duty(val, ctl); + default: + return -ENOTSUPP; + } + + return 0; +} + +static int eswin_fan_control_read_labels(struct device *dev, + enum hwmon_sensor_types type, + u32 attr, int channel, const char **str) +{ + switch (type) { + case hwmon_fan: + *str = "FAN"; + return 0; + default: + return -ENOTSUPP; + } +} + +static int eswin_fan_control_read(struct device *dev, + enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + switch (type) { + case hwmon_fan: + return eswin_fan_control_read_fan(dev, attr, val); + case hwmon_pwm: + return eswin_fan_control_read_pwm(dev, attr, val); + default: + return -ENOTSUPP; + } +} + +static int eswin_fan_control_write(struct device *dev, + enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + switch (type) { + case hwmon_pwm: + return eswin_fan_control_write_pwm(dev, attr, val); + default: + return -ENOTSUPP; + } +} + +static umode_t eswin_fan_control_fan_is_visible(const u32 attr) +{ + switch (attr) { + case hwmon_fan_input: + case hwmon_fan_label: + return 0444; + default: + return 0; + } +} + +static umode_t eswin_fan_control_pwm_is_visible(const u32 attr) +{ + switch (attr) { + case hwmon_pwm_input: + return 0644; + default: + return 0; + } +} + +static umode_t eswin_fan_control_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int channel) +{ + switch (type) { + case hwmon_fan: + return eswin_fan_control_fan_is_visible(attr); + case hwmon_pwm: + return eswin_fan_control_pwm_is_visible(attr); + default: + return 0; + } +} + +static irqreturn_t eswin_fan_control_irq_handler(int irq, void *data) +{ + struct eswin_fan_control_data *ctl = (struct eswin_fan_control_data *)data; + u32 status = 0; + + status = fan_ioread(REG_FAN_INT, ctl); + if (0x3 == (status & 0x3)){ + ctl->rpm = fan_ioread(REG_FAN_RPM, ctl); + + /* clear interrupt */ + fan_iowrite(0x5, REG_FAN_INT, ctl); + + /* wake up fan_rpm read */ + ctl->wait_flag = true; + wake_up_interruptible(&ctl->wq); + } + + return IRQ_HANDLED; +} + +static int eswin_fan_control_init(struct eswin_fan_control_data *ctl, + const struct device_node *np) +{ + int ret; + /* get fan pulses per revolution */ + ret = of_property_read_u32(np, "pulses-per-revolution", &ctl->ppr); + if (ret) + return ret; + + /* 1, 2 and 4 are the typical and accepted values */ + if (ctl->ppr != 1 && ctl->ppr != 2 && ctl->ppr != 4) + return -EINVAL; + + /* get pwm minimum period */ + ret = of_property_read_u32(np, "pwm-minimum-period", &ctl->min_period); + if (ret) + return ret; + + return ret; +} + +static void eswin_fan_control_remove(void *data) +{ + int ret; + struct eswin_fan_control_data *ctl = data; + pwm_put(ctl->pwm); + ret = reset_control_assert(ctl->fan_rst); + WARN_ON(0 != ret); + clk_disable_unprepare(ctl->clk); +} + +static const struct hwmon_channel_info *eswin_fan_control_info[] = { + HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT), + HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_LABEL), + NULL +}; + +static const struct hwmon_ops eswin_fan_control_hwmon_ops = { + .is_visible = eswin_fan_control_is_visible, + .read = eswin_fan_control_read, + .write = eswin_fan_control_write, + .read_string = eswin_fan_control_read_labels, +}; + +static const struct hwmon_chip_info eswin_chip_info = { + .ops = &eswin_fan_control_hwmon_ops, + .info = eswin_fan_control_info, +}; + +static SENSOR_DEVICE_ATTR_RW(fan_pwm_duty, eswin_fan_pwm_ctl, FAN_PWM_DUTY); +static SENSOR_DEVICE_ATTR_RW(fan_pwm_period, eswin_fan_pwm_ctl, FAN_PWM_PERIOD); +static SENSOR_DEVICE_ATTR_WO(fan_pwm_free, eswin_fan_pwm_free, FAN_PWM_FREE); + +static struct attribute *eswin_fan_control_attrs[] = { + &sensor_dev_attr_fan_pwm_duty.dev_attr.attr, + &sensor_dev_attr_fan_pwm_period.dev_attr.attr, + &sensor_dev_attr_fan_pwm_free.dev_attr.attr, + NULL, +}; +ATTRIBUTE_GROUPS(eswin_fan_control); + +static const struct of_device_id eswin_fan_control_of_match[] = { + { .compatible = "eswin-fan-control"}, + {} +}; +MODULE_DEVICE_TABLE(of, eswin_fan_control_of_match); + +static int eswin_fan_control_probe(struct platform_device *pdev) +{ + struct eswin_fan_control_data *ctl; + const struct of_device_id *id; + const char *name = "eswin_fan_control"; + int ret; + + id = of_match_node(eswin_fan_control_of_match, pdev->dev.of_node); + if (!id) + return -EINVAL; + + ctl = devm_kzalloc(&pdev->dev, sizeof(*ctl), GFP_KERNEL); + if (!ctl) + return -ENOMEM; + + ctl->base = devm_platform_ioremap_resource(pdev, 0); + + if (IS_ERR(ctl->base)) + return PTR_ERR(ctl->base); + + ctl->clk = devm_clk_get(&pdev->dev, "pclk"); + if (IS_ERR(ctl->clk)) { + dev_err(&pdev->dev, "Couldn't get the clock for fan-controller\n"); + return -ENODEV; + } + + ret = clk_prepare_enable(ctl->clk); + if (ret) { + dev_err(&pdev->dev, "Failed to enable clock for fan-controller\n"); + return ret; + } + + ctl->clk_rate = clk_get_rate(ctl->clk); + if (!ctl->clk_rate) + return -EINVAL; + + ctl->fan_rst = devm_reset_control_get_optional(&pdev->dev, "fan_rst"); + if (IS_ERR_OR_NULL(ctl->fan_rst)) { + dev_err(&pdev->dev, "Failed to get fan_rst reset handle\n"); + return -EFAULT; + } + ret = reset_control_reset(ctl->fan_rst); + WARN_ON(0 != ret); + + init_waitqueue_head(&ctl->wq); + + ctl->irq = platform_get_irq(pdev, 0); + if (ctl->irq < 0) + return ctl->irq; + + ret = devm_request_threaded_irq(&pdev->dev, ctl->irq, + eswin_fan_control_irq_handler, NULL, + IRQF_ONESHOT | IRQF_TRIGGER_HIGH, + pdev->driver_override, ctl); + if (ret) { + dev_err(&pdev->dev, "Failed to request an irq, %d", ret); + return ret; + } + + ret = eswin_fan_control_init(ctl, pdev->dev.of_node); + if (ret) { + dev_err(&pdev->dev, "Failed to initialize device\n"); + return ret; + } + + ctl->pwm = pwm_get(&pdev->dev, NULL); + if (IS_ERR(ctl->pwm)) { + ret = PTR_ERR(ctl->pwm); + dev_err(&pdev->dev, "Failed to request pwm device: %d\n", ret); + return ret; + } + pwm_enable(ctl->pwm); + + ret = devm_add_action_or_reset(&pdev->dev, eswin_fan_control_remove, ctl); + if (ret) + return ret; + + ctl->hdev = devm_hwmon_device_register_with_info(&pdev->dev, + name, + ctl, + &eswin_chip_info, + eswin_fan_control_groups); + return PTR_ERR_OR_ZERO(ctl->hdev); +} + +static struct platform_driver eswin_fan_control_driver = { + .driver = { + .name = "eswin_fan_control_driver", + .of_match_table = eswin_fan_control_of_match, + }, + .probe = eswin_fan_control_probe, +}; +module_platform_driver(eswin_fan_control_driver); + +MODULE_AUTHOR("Han Min "); +MODULE_DESCRIPTION("ESWIN Fan Control CORE driver"); +MODULE_LICENSE("GPL"); From 724aacc15fce42bdafbc5678b5d9e2d3b89139ba Mon Sep 17 00:00:00 2001 From: luyulin Date: Tue, 30 Jul 2024 14:13:13 +0000 Subject: [PATCH 25/38] drivers: hwmon: pvt: Add ESWIN PVT driver Signed-off-by: luyulin Signed-off-by: Darshan Prajapati Signed-off-by: Pinkesh Vaghela --- drivers/hwmon/Kconfig | 6 + drivers/hwmon/Makefile | 1 + drivers/hwmon/eswin_pvt.c | 874 ++++++++++++++++++++++++++++++++++++++ drivers/hwmon/eswin_pvt.h | 227 ++++++++++ 4 files changed, 1108 insertions(+) create mode 100644 drivers/hwmon/eswin_pvt.c create mode 100644 drivers/hwmon/eswin_pvt.h diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index c59531ae55148..78c456251902d 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -566,6 +566,12 @@ config SENSORS_DA9055 This driver can also be built as a module. If so, the module will be called da9055-hwmon. +config SENSORS_ESWIN_PVT + tristate "Eswin Process, Voltage, Temperature sensor driver" + depends on HWMON + help + If you say yes here you get support for Eswin PVT sensor. + config SENSORS_I5K_AMB tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets" depends on PCI diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 3a9663090c3f0..f7b1e2c58131f 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o obj-$(CONFIG_SENSORS_EMC2305) += emc2305.o obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o obj-$(CONFIG_SENSORS_ESWIN_FAN_CONTROL) += eswin-fan-control.o +obj-$(CONFIG_SENSORS_ESWIN_PVT) += eswin_pvt.o obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o obj-$(CONFIG_SENSORS_F75375S) += f75375s.o diff --git a/drivers/hwmon/eswin_pvt.c b/drivers/hwmon/eswin_pvt.c new file mode 100644 index 0000000000000..6436330fde1c8 --- /dev/null +++ b/drivers/hwmon/eswin_pvt.c @@ -0,0 +1,874 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN PVT Device 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 . + * + * Authors: Bingzheng Yu + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "eswin_pvt.h" + +/* + * For the sake of the code simplification we created the sensors info table + * with the sensor names, activation modes, threshold registers base address + * and the thresholds bit fields. + */ +static const struct pvt_sensor_info pvt_info[] = { + PVT_SENSOR_INFO(0, "CPU Core Temperature", hwmon_temp, TEMP, TTHRES), + PVT_SENSOR_INFO(0, "CPU Core Voltage", hwmon_in, VOLT, VTHRES), + PVT_SENSOR_INFO(1, "CPU Core Low-Vt", hwmon_in, LVT, LTHRES), + PVT_SENSOR_INFO(2, "CPU Core UltraLow-Vt", hwmon_in, ULVT, ULTHRES), + PVT_SENSOR_INFO(3, "CPU Core Standard-Vt", hwmon_in, SVT, STHRES), +}; + +/* + * The original translation formulae of the temperature (in degrees of Celsius) + * to PVT data and vice-versa are following: + * N = 6.0818e-8*(T^4) +1.2873e-5*(T^3) + 7.2244e-3*(T^2) + 3.6484*(T^1) + + * 1.6198e2, + * T = -1.8439e-11*(N^4) + 8.0705e-8*(N^3) + -1.8501e-4*(N^2) + + * 3.2843e-1*(N^1) - 4.8690e1, + * where T = [-40, 125]C and N = [27, 771]. + * They must be accordingly altered to be suitable for the integer arithmetics. + * The technique is called 'factor redistribution', which just makes sure the + * multiplications and divisions are made so to have a result of the operations + * within the integer numbers limit. In addition we need to translate the + * formulae to accept millidegrees of Celsius. Here what they look like after + * the alterations: + * N = (60818e-20*(T^4) + 12873e-14*(T^3) + 72244e-9*(T^2) + 36484e-3*T + + * 16198e2) / 1e4, + * T = -18439e-12*(N^4) + 80705e-9*(N^3) - 185010e-6*(N^2) + 328430e-3*N - + * 48690, + * where T = [-40000, 125000] mC and N = [27, 771]. + */ +static const struct pvt_poly __maybe_unused poly_temp_to_N = { + .total_divider = 10000, + .terms = { + {4, 60818, 10000, 10000}, + {3, 12873, 10000, 100}, + {2, 72244, 10000, 10}, + {1, 36484, 1000, 1}, + {0, 1619800, 1, 1} + } +}; + +static const struct pvt_poly poly_N_to_temp = { + .total_divider = 1, + .terms = { + {4, -18439, 1000, 1}, + {3, 80705, 1000, 1}, + {2, -185010, 1000, 1}, + {1, 328430, 1000, 1}, + {0, -48690, 1, 1} + } +}; + +/* + * Similar alterations are performed for the voltage conversion equations. + * The original formulae are: + * N = 1.3905e3*V - 5.7685e2, + * V = (N + 5.7685e2) / 1.3905e3, + * where V = [0.72, 0.88] V and N = [424, 646]. + * After the optimization they looks as follows: + * N = (13905e-3*V - 5768.5) / 10, + * V = (N * 10^5 / 13905 + 57685 * 10^3 / 13905) / 10. + * where V = [720, 880] mV and N = [424, 646]. + */ +static const struct pvt_poly __maybe_unused poly_volt_to_N = { + .total_divider = 10, + .terms = { + {1, 13905, 1000, 1}, + {0, -57685, 1, 10} + } +}; + +static const struct pvt_poly poly_N_to_volt = { + .total_divider = 10, + .terms = { + {1, 100000, 13905, 1}, + {0, 57685000, 1, 13905} + } +}; + +/* + * Here is the polynomial calculation function, which performs the + * redistributed terms calculations. It's pretty straightforward. We walk + * over each degree term up to the free one, and perform the redistributed + * multiplication of the term coefficient, its divider (as for the rationale + * fraction representation), data power and the rational fraction divider + * leftover. Then all of this is collected in a total sum variable, which + * value is normalized by the total divider before being returned. + */ +static long eswin_pvt_calc_poly(const struct pvt_poly *poly, long data) +{ + const struct pvt_poly_term *term = poly->terms; + long tmp, ret = 0; + int deg; + do { + tmp = term->coef; + for (deg = 0; deg < term->deg; ++deg) + tmp = mult_frac(tmp, data, term->divider); + ret += tmp / term->divider_leftover; + } while ((term++)->deg); + + return ret / poly->total_divider; +} + +static inline u32 eswin_pvt_update(void __iomem *reg, u32 mask, u32 data) +{ + u32 old; + + old = readl_relaxed(reg); + writel((old & ~mask) | (data & mask), reg); + + return old & mask; +} + +static inline void eswin_pvt_set_mode(struct pvt_hwmon *pvt, u32 mode) +{ + u32 old; + + mode = FIELD_PREP(PVT_MODE_MASK, mode); + + old = eswin_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, 0); + eswin_pvt_update(pvt->regs + PVT_MODE, PVT_MODE_MASK, mode); + eswin_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, old); +} + +static inline u32 eswin_pvt_calc_trim(long temp) +{ + temp = clamp_val(temp, 0, PVT_TRIM_TEMP); + + return DIV_ROUND_UP(temp, PVT_TRIM_STEP); +} + +static inline void eswin_pvt_set_trim(struct pvt_hwmon *pvt, u32 val) +{ + u32 old; + + old = eswin_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, 0); + writel(val, pvt->regs + PVT_TRIM); + eswin_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, old); +} + +static irqreturn_t eswin_pvt_hard_isr(int irq, void *data) +{ + struct pvt_hwmon *pvt = data; + struct pvt_cache *cache; + u32 val; + + eswin_pvt_update(pvt->regs + PVT_INT, PVT_INT_CLR, PVT_INT_CLR); + + /* + * Nothing special for alarm-less driver. Just read the data, update + * the cache and notify a waiter of this event. + */ + + val = readl(pvt->regs + PVT_DATA); + + cache = &pvt->cache[pvt->sensor]; + + WRITE_ONCE(cache->data, FIELD_GET(PVT_DATA_OUT, val)); + + complete(&cache->conversion); + + return IRQ_HANDLED; +} + +static inline umode_t eswin_pvt_limit_is_visible(enum pvt_sensor_type type) +{ + return 0; +} + +static inline umode_t eswin_pvt_pvt_alarm_is_visible(enum pvt_sensor_type type) +{ + return 0; +} + +static int eswin_pvt_read_data(struct pvt_hwmon *pvt, enum pvt_sensor_type type, + long *val) +{ + struct pvt_cache *cache = &pvt->cache[type]; + unsigned long timeout; + u32 data; + int ret; + + /* + * Lock PVT conversion interface until data cache is updated. The + * data read procedure is following: set the requested PVT sensor + * mode, enable IRQ and conversion, wait until conversion is finished, + * then disable conversion and IRQ, and read the cached data. + */ + ret = mutex_lock_interruptible(&pvt->iface_mtx); + if (ret) + return ret; + + pvt->sensor = type; + eswin_pvt_set_mode(pvt, pvt_info[type].mode); + + eswin_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, PVT_ENA_EN); + + /* + * Wait with timeout since in case if the sensor is suddenly powered + * down the request won't be completed and the caller will hang up on + * this procedure until the power is back up again. Multiply the + * timeout by the factor of two to prevent a false timeout. + */ + timeout = 2 * usecs_to_jiffies(ktime_to_us(pvt->timeout)); + if(type==PVT_TEMP){ + timeout = 20 * usecs_to_jiffies(ktime_to_us(pvt->timeout)); + } + ret = wait_for_completion_timeout(&cache->conversion, timeout); + + eswin_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, 0); + eswin_pvt_update(pvt->regs + PVT_INT, PVT_INT_CLR, PVT_INT_CLR); + + data = READ_ONCE(cache->data); + + mutex_unlock(&pvt->iface_mtx); + + if (!ret) + return -ETIMEDOUT; + + if (type == PVT_TEMP) + *val = eswin_pvt_calc_poly(&poly_N_to_temp, data); + else if (type == PVT_VOLT) + *val = eswin_pvt_calc_poly(&poly_N_to_volt, data); + else + *val = data; + + return 0; +} + +static int eswin_pvt_read_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type, + bool is_low, long *val) +{ + return -EOPNOTSUPP; +} + +static int eswin_pvt_write_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type, + bool is_low, long val) +{ + return -EOPNOTSUPP; +} + +static int eswin_pvt_read_alarm(struct pvt_hwmon *pvt, enum pvt_sensor_type type, + bool is_low, long *val) +{ + return -EOPNOTSUPP; +} + +static const struct hwmon_channel_info *pvt_channel_info[] = { + HWMON_CHANNEL_INFO(chip, + HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL), + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | HWMON_T_TYPE | HWMON_T_LABEL | + HWMON_T_OFFSET), + HWMON_CHANNEL_INFO(in, + HWMON_I_INPUT | HWMON_I_LABEL, + HWMON_I_INPUT | HWMON_I_LABEL, + HWMON_I_INPUT | HWMON_I_LABEL, + HWMON_I_INPUT | HWMON_I_LABEL), + NULL +}; + +static inline bool eswin_pvt_hwmon_channel_is_valid(enum hwmon_sensor_types type, + int ch) +{ + switch (type) { + case hwmon_temp: + if (ch < 0 || ch >= PVT_TEMP_CHS) + return false; + break; + case hwmon_in: + if (ch < 0 || ch >= PVT_VOLT_CHS) + return false; + break; + default: + break; + } + + /* The rest of the types are independent from the channel number. */ + return true; +} + +static umode_t eswin_pvt_hwmon_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int ch) +{ + if (!eswin_pvt_hwmon_channel_is_valid(type, ch)) + return 0; + + switch (type) { + case hwmon_chip: + switch (attr) { + case hwmon_chip_update_interval: + return 0644; + } + break; + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + case hwmon_temp_type: + case hwmon_temp_label: + return 0444; + case hwmon_temp_min: + case hwmon_temp_max: + return eswin_pvt_limit_is_visible(ch); + case hwmon_temp_min_alarm: + case hwmon_temp_max_alarm: + return eswin_pvt_pvt_alarm_is_visible(ch); + case hwmon_temp_offset: + return 0644; + } + break; + case hwmon_in: + switch (attr) { + case hwmon_in_input: + case hwmon_in_label: + return 0444; + case hwmon_in_min: + case hwmon_in_max: + return eswin_pvt_limit_is_visible(PVT_VOLT + ch); + case hwmon_in_min_alarm: + case hwmon_in_max_alarm: + return eswin_pvt_pvt_alarm_is_visible(PVT_VOLT + ch); + } + break; + default: + break; + } + + return 0; +} + +static int eswin_pvt_read_trim(struct pvt_hwmon *pvt, long *val) +{ + u32 data; + + data = readl(pvt->regs + PVT_TRIM); + *val = data; + + return 0; +} + +static int eswin_pvt_write_trim(struct pvt_hwmon *pvt, long val) +{ + int ret; + /* + * Serialize trim update, since a part of the register is changed and + * the controller is supposed to be disabled during this operation. + */ + ret = mutex_lock_interruptible(&pvt->iface_mtx); + if (ret) + return ret; + + eswin_pvt_set_trim(pvt, val); + + mutex_unlock(&pvt->iface_mtx); + + return 0; +} + +static int eswin_pvt_read_timeout(struct pvt_hwmon *pvt, long *val) +{ + int ret; + + ret = mutex_lock_interruptible(&pvt->iface_mtx); + if (ret) + return ret; + + /* Return the result in msec as hwmon sysfs interface requires. */ + *val = ktime_to_ms(pvt->timeout); + + mutex_unlock(&pvt->iface_mtx); + + return 0; +} + +static int eswin_pvt_write_timeout(struct pvt_hwmon *pvt, long val) +{ + unsigned long rate; + ktime_t kt, cache; + u32 data; + int ret; + + rate = clk_get_rate(pvt->clk); + if (!rate) + return -ENODEV; + + /* + * If alarms are enabled, the requested timeout must be divided + * between all available sensors to have the requested delay + * applicable to each individual sensor. + */ + cache = kt = ms_to_ktime(val); + + /* + * Subtract a constant lag, which always persists due to the limited + * PVT sampling rate. Make sure the timeout is not negative. + */ + kt = ktime_sub_ns(kt, PVT_TOUT_MIN); + if (ktime_to_ns(kt) < 0) + kt = ktime_set(0, 0); + + /* + * Finally recalculate the timeout in terms of the reference clock + * period. + */ + data = ktime_divns(kt * rate, NSEC_PER_SEC); + + /* + * Update the measurements delay, but lock the interface first, since + * we have to disable PVT in order to have the new delay actually + * updated. + */ + ret = mutex_lock_interruptible(&pvt->iface_mtx); + if (ret) + return ret; + + pvt->timeout = cache; + + mutex_unlock(&pvt->iface_mtx); + + return 0; +} + +static int eswin_pvt_hwmon_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int ch, long *val) +{ + struct pvt_hwmon *pvt = dev_get_drvdata(dev); + + if (!eswin_pvt_hwmon_channel_is_valid(type, ch)) + return -EINVAL; + + switch (type) { + case hwmon_chip: + switch (attr) { + case hwmon_chip_update_interval: + return eswin_pvt_read_timeout(pvt, val); + } + break; + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + return eswin_pvt_read_data(pvt, ch, val); + case hwmon_temp_type: + *val = 1; + return 0; + case hwmon_temp_min: + return eswin_pvt_read_limit(pvt, ch, true, val); + case hwmon_temp_max: + return eswin_pvt_read_limit(pvt, ch, false, val); + case hwmon_temp_min_alarm: + return eswin_pvt_read_alarm(pvt, ch, true, val); + case hwmon_temp_max_alarm: + return eswin_pvt_read_alarm(pvt, ch, false, val); + case hwmon_temp_offset: + return eswin_pvt_read_trim(pvt, val); + } + break; + case hwmon_in: + switch (attr) { + case hwmon_in_input: + return eswin_pvt_read_data(pvt, PVT_VOLT + ch, val); + case hwmon_in_min: + return eswin_pvt_read_limit(pvt, PVT_VOLT + ch, true, val); + case hwmon_in_max: + return eswin_pvt_read_limit(pvt, PVT_VOLT + ch, false, val); + case hwmon_in_min_alarm: + return eswin_pvt_read_alarm(pvt, PVT_VOLT + ch, true, val); + case hwmon_in_max_alarm: + return eswin_pvt_read_alarm(pvt, PVT_VOLT + ch, false, val); + } + break; + default: + break; + } + + return -EOPNOTSUPP; +} + +static int eswin_pvt_hwmon_read_string(struct device *dev, + enum hwmon_sensor_types type, + u32 attr, int ch, const char **str) +{ + if (!eswin_pvt_hwmon_channel_is_valid(type, ch)) + return -EINVAL; + + switch (type) { + case hwmon_temp: + switch (attr) { + case hwmon_temp_label: + *str = pvt_info[ch].label; + return 0; + } + break; + case hwmon_in: + switch (attr) { + case hwmon_in_label: + *str = pvt_info[PVT_VOLT + ch].label; + return 0; + } + break; + default: + break; + } + + return -EOPNOTSUPP; +} + +static int eswin_pvt_hwmon_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int ch, long val) +{ + struct pvt_hwmon *pvt = dev_get_drvdata(dev); + + if (!eswin_pvt_hwmon_channel_is_valid(type, ch)) + return -EINVAL; + + switch (type) { + case hwmon_chip: + switch (attr) { + case hwmon_chip_update_interval: + return eswin_pvt_write_timeout(pvt, val); + } + break; + case hwmon_temp: + switch (attr) { + case hwmon_temp_min: + return eswin_pvt_write_limit(pvt, ch, true, val); + case hwmon_temp_max: + return eswin_pvt_write_limit(pvt, ch, false, val); + case hwmon_temp_offset: + return eswin_pvt_write_trim(pvt, val); + } + break; + case hwmon_in: + switch (attr) { + case hwmon_in_min: + return eswin_pvt_write_limit(pvt, PVT_VOLT + ch, true, val); + case hwmon_in_max: + return eswin_pvt_write_limit(pvt, PVT_VOLT + ch, false, val); + } + break; + default: + break; + } + + return -EOPNOTSUPP; +} + +static const struct hwmon_ops pvt_hwmon_ops = { + .is_visible = eswin_pvt_hwmon_is_visible, + .read = eswin_pvt_hwmon_read, + .read_string = eswin_pvt_hwmon_read_string, + .write = eswin_pvt_hwmon_write +}; + +static const struct hwmon_chip_info pvt_hwmon_info = { + .ops = &pvt_hwmon_ops, + .info = pvt_channel_info +}; + +static void pvt_clear_data(void *data) +{ + struct pvt_hwmon *pvt = data; + int idx; + + for (idx = 0; idx < PVT_SENSORS_NUM; ++idx) + complete_all(&pvt->cache[idx].conversion); + + mutex_destroy(&pvt->iface_mtx); +} + +static struct pvt_hwmon *eswin_pvt_create_data(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pvt_hwmon *pvt; + int ret, idx; + + pvt = devm_kzalloc(dev, sizeof(*pvt), GFP_KERNEL); + if (!pvt) + return ERR_PTR(-ENOMEM); + + ret = devm_add_action(dev, pvt_clear_data, pvt); + if (ret) { + dev_err(dev, "Can't add PVT data clear action\n"); + return ERR_PTR(ret); + } + + pvt->dev = dev; + pvt->sensor = PVT_SENSOR_FIRST; + mutex_init(&pvt->iface_mtx); + + for (idx = 0; idx < PVT_SENSORS_NUM; ++idx) + init_completion(&pvt->cache[idx].conversion); + + return pvt; +} + +static int eswin_pvt_request_regs(struct pvt_hwmon *pvt) +{ + struct platform_device *pdev = to_platform_device(pvt->dev); + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(pvt->dev, "Couldn't find PVT memresource\n"); + return -EINVAL; + } + + pvt->regs = devm_ioremap_resource(pvt->dev, res); + if (IS_ERR(pvt->regs)) + return PTR_ERR(pvt->regs); + + return 0; +} + +static void eswin_pvt_remove(void *data) +{ + int ret; + struct pvt_hwmon *pvt = data; + ret = reset_control_assert(pvt->pvt_rst); + WARN_ON(0 != ret); + clk_disable_unprepare(pvt->clk); +} + +static int eswin_pvt_request_clks(struct pvt_hwmon *pvt) +{ + int ret; + + pvt->clk = devm_clk_get(pvt->dev, "pvt_clk"); + if (IS_ERR(pvt->clk)) { + dev_err(pvt->dev, "Couldn't get PVT clock\n"); + return -ENODEV; + } + + ret = clk_prepare_enable(pvt->clk); + if (ret) { + dev_err(pvt->dev, "Couldn't enable the PVT clocks\n"); + return ret; + } + + return 0; +} + +static int eswin_pvt_request_rst(struct pvt_hwmon *pvt) +{ + int ret; + pvt->pvt_rst = devm_reset_control_get_optional(pvt->dev, "pvt_rst"); + if(IS_ERR_OR_NULL(pvt->pvt_rst)){ + dev_err(pvt->dev, "Couldn't get PVT reset\n"); + } + ret = reset_control_reset(pvt->pvt_rst); + WARN_ON(0 != ret); + return 0; +} + +static int eswin_pvt_check_pwr(struct pvt_hwmon *pvt) +{ + unsigned long tout; + int ret = 0; + u32 data; + + /* + * Test out the sensor conversion functionality. If it is not done on + * time then the domain must have been unpowered and we won't be able + * to use the device later in this driver. + * Note If the power source is lost during the normal driver work the + * data read procedure will either return -ETIMEDOUT (for the + * alarm-less driver configuration) or just stop the repeated + * conversion. In the later case alas we won't be able to detect the + * problem. + */ + + eswin_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, PVT_ENA_EN); + readl(pvt->regs + PVT_DATA); + + tout = PVT_TOUT_MIN / NSEC_PER_USEC; + usleep_range(tout, 2 * tout); + + data = readl(pvt->regs + PVT_DATA); + + eswin_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, 0); + eswin_pvt_update(pvt->regs + PVT_INT, PVT_INT_CLR, PVT_INT_CLR); + + return ret; +} + +static int eswin_pvt_init_iface(struct pvt_hwmon *pvt) +{ + unsigned long rate; + + rate = clk_get_rate(pvt->clk); + if (!rate) { + dev_err(pvt->dev, "Invalid reference clock rate\n"); + return -ENODEV; + } + + /* + * Make sure all interrupts and controller are disabled so not to + * accidentally have ISR executed before the driver data is fully + * initialized. Clear the IRQ status as well. + */ + eswin_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, 0); + eswin_pvt_update(pvt->regs + PVT_INT, PVT_INT_CLR, PVT_INT_CLR); + + readl(pvt->regs + PVT_DATA); + + /* Setup default sensor mode, timeout and temperature trim. */ + eswin_pvt_set_mode(pvt, pvt_info[pvt->sensor].mode); + + /* + * Preserve the current ref-clock based delay (Ttotal) between the + * sensors data samples in the driver data so not to recalculate it + * each time on the data requests and timeout reads. It consists of the + * delay introduced by the internal ref-clock timer (N / Fclk) and the + * constant timeout caused by each conversion latency (Tmin): + * Ttotal = N / Fclk + Tmin + * If alarms are enabled the sensors are polled one after another and + * in order to get the next measurement of a particular sensor the + * caller will have to wait for at most until all the others are + * polled. In that case the formulae will look a bit different: + * Ttotal = 5 * (N / Fclk + Tmin) + */ + + pvt->timeout = ktime_set(PVT_TOUT_DEF, 0); + pvt->timeout = ktime_divns(pvt->timeout, rate); + pvt->timeout = ktime_add_ns(pvt->timeout, PVT_TOUT_MIN); + + return 0; +} + +static int eswin_pvt_request_irq(struct pvt_hwmon *pvt) +{ + struct platform_device *pdev = to_platform_device(pvt->dev); + int ret; + + pvt->irq = platform_get_irq(pdev, 0); + if (pvt->irq < 0) + return pvt->irq; + + ret = devm_request_threaded_irq(pvt->dev, pvt->irq, + eswin_pvt_hard_isr, NULL, + IRQF_SHARED | IRQF_TRIGGER_HIGH, + "pvt", pvt); + if (ret) { + dev_err(pvt->dev, "Couldn't request PVT IRQ\n"); + return ret; + } + + return 0; +} + +static int eswin_pvt_create_hwmon(struct pvt_hwmon *pvt) +{ + pvt->hwmon = devm_hwmon_device_register_with_info(pvt->dev, "pvt", pvt, + &pvt_hwmon_info, NULL); + if (IS_ERR(pvt->hwmon)) { + dev_err(pvt->dev, "Couldn't create hwmon device\n"); + return PTR_ERR(pvt->hwmon); + } + + return 0; +} + +static int eswin_pvt_probe(struct platform_device *pdev) +{ + struct pvt_hwmon *pvt; + int ret; + + pvt = eswin_pvt_create_data(pdev); + if (IS_ERR(pvt)) + return PTR_ERR(pvt); + + ret = eswin_pvt_request_regs(pvt); + if (ret) + return ret; + + ret = eswin_pvt_request_clks(pvt); + if (ret) + return ret; + + ret = eswin_pvt_request_rst(pvt); + if (ret) + return ret; + + ret = eswin_pvt_check_pwr(pvt); + if (ret) + return ret; + + ret = eswin_pvt_init_iface(pvt); + if (ret) + return ret; + + ret = eswin_pvt_request_irq(pvt); + if (ret) + return ret; + + ret = eswin_pvt_create_hwmon(pvt); + if (ret) + return ret; + + ret = devm_add_action_or_reset(pvt->dev, eswin_pvt_remove, pvt); + if (ret) { + dev_err(pvt->dev, "Can't add PVT clocks disable action\n"); + return ret; + } + + return 0; +} + +static const struct of_device_id pvt_of_match[] = { + { .compatible = "eswin,eswin-pvt" }, + { } +}; +MODULE_DEVICE_TABLE(of, pvt_of_match); + +static struct platform_driver pvt_driver = { + .probe = eswin_pvt_probe, + .driver = { + .name = "eswin-pvt", + .of_match_table = pvt_of_match + }, +}; +module_platform_driver(pvt_driver); + +MODULE_DESCRIPTION("Eswin PVT driver"); +MODULE_AUTHOR("Yu Bingzheng "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/hwmon/eswin_pvt.h b/drivers/hwmon/eswin_pvt.h new file mode 100644 index 0000000000000..1c0c9252317c5 --- /dev/null +++ b/drivers/hwmon/eswin_pvt.h @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) ESWIN Electronics Co.Ltd + * + * Eswin Process, Voltage, Temperature sensor driver + */ +#ifndef __HWMON_ESWIN_PVT_H__ +#define __HWMON_ESWIN_PVT_H__ + +#include +#include +#include +#include +#include +#include + +/* Eswin PVT registers and their bitfields */ +#define PVT_DIV 0x00 +#define PVT_TRIM 0x04 +#define PVT_TRIM_G GENMASK(4,0) +#define PVT_TRIM_O GENMASK(13,8) +#define PVT_MODE 0x08 +#define PVT_MODE_MASK GENMASK(2, 0) +#define PVT_CTRL_MODE_TEMP 0x0 +#define PVT_CTRL_MODE_VOLT 0x4 +#define PVT_CTRL_MODE_LVT 0x1 +#define PVT_CTRL_MODE_ULVT 0x2 +#define PVT_CTRL_MODE_SVT 0x3 +#define PVT_MODE_PSAMPLE_0 BIT(0) +#define PVT_MODE_PSAMPLE_1 BIT(1) +#define PVT_MODE_VSAMPLE BIT(2) +#define PVT_ENA 0x0c +#define PVT_ENA_EN BIT(0) +#define PVT_INT 0x10 +#define PVT_INT_CLR BIT(1) +#define PVT_DATA 0x14 +#define PVT_DATA_OUT GENMASK(9,0) + +/* alarm related */ +#define PVT_TTHRES 0x08 +#define PVT_VTHRES 0x0C +#define PVT_LTHRES 0x10 +#define PVT_ULTHRES 0x14 +#define PVT_STHRES 0x18 +#define PVT_INTR_DVALID BIT(0) +#define PVT_INTR_TTHRES_LO BIT(1) +#define PVT_INTR_TTHRES_HI BIT(2) +#define PVT_INTR_VTHRES_LO BIT(3) +#define PVT_INTR_VTHRES_HI BIT(4) +#define PVT_INTR_LTHRES_LO BIT(5) +#define PVT_INTR_LTHRES_HI BIT(6) +#define PVT_INTR_ULTHRES_LO BIT(7) +#define PVT_INTR_ULTHRES_HI BIT(8) +#define PVT_INTR_STHRES_LO BIT(9) +#define PVT_INTR_STHRES_HI BIT(10) + +/* + * PVT sensors-related limits and default values + * @PVT_TEMP_MIN: Minimal temperature in millidegrees of Celsius. + * @PVT_TEMP_MAX: Maximal temperature in millidegrees of Celsius. + * @PVT_TEMP_CHS: Number of temperature hwmon channels. + * @PVT_VOLT_MIN: Minimal voltage in mV. + * @PVT_VOLT_MAX: Maximal voltage in mV. + * @PVT_VOLT_CHS: Number of voltage hwmon channels. + * @PVT_DATA_MIN: Minimal PVT raw data value. + * @PVT_DATA_MAX: Maximal PVT raw data value. + * @PVT_TRIM_MIN: Minimal temperature sensor trim value. + * @PVT_TRIM_MAX: Maximal temperature sensor trim value. + * @PVT_TRIM_DEF: Default temperature sensor trim value (set a proper value + * when one is determined for ESWIN SoC). + * @PVT_TRIM_TEMP: Maximum temperature encoded by the trim factor. + * @PVT_TRIM_STEP: Temperature stride corresponding to the trim value. + * @PVT_TOUT_MIN: Minimal timeout between samples in nanoseconds. + * @PVT_TOUT_DEF: Default data measurements timeout. In case if alarms are + * activated the PVT IRQ is enabled to be raised after each + * conversion in order to have the thresholds checked and the + * converted value cached. Too frequent conversions may cause + * the system CPU overload. Lets set the 50ms delay between + * them by default to prevent this. + */ +#define PVT_TEMP_MIN -40000L +#define PVT_TEMP_MAX 125000L +#define PVT_TEMP_CHS 1 +#define PVT_VOLT_MIN 720L +#define PVT_VOLT_MAX 880L +#define PVT_VOLT_CHS 4 +#define PVT_DATA_MIN 0 +#define PVT_DATA_DATA_FLD 0 +#define PVT_CTRL_TRIM_FLD 4 +#define PVT_CTRL_TRIM_MASK GENMASK(8,4) +#define PVT_DATA_MAX (PVT_DATA_DATA_MASK >> PVT_DATA_DATA_FLD) +#define PVT_TRIM_MIN 0 +#define PVT_TRIM_MAX (PVT_CTRL_TRIM_MASK >> PVT_CTRL_TRIM_FLD) +#define PVT_TRIM_TEMP 7130 +#define PVT_TRIM_STEP (PVT_TRIM_TEMP / PVT_TRIM_MAX) +#define PVT_TRIM_DEF 0 +#define PVT_TOUT_MIN (NSEC_PER_SEC / 3000) +# define PVT_TOUT_DEF 0 + +/* + * enum pvt_sensor_type - ESWIN PVT sensor types (correspond to each PVT + * sampling mode) + * @PVT_SENSOR*: helpers to traverse the sensors in loops. + * @PVT_TEMP: PVT Temperature sensor. + * @PVT_VOLT: PVT Voltage sensor. + * @PVT_LVT: PVT Low-Voltage threshold sensor. + * @PVT_HVT: PVT High-Voltage threshold sensor. + * @PVT_SVT: PVT Standard-Voltage threshold sensor. + */ +enum pvt_sensor_type { + PVT_SENSOR_FIRST, + PVT_TEMP = PVT_SENSOR_FIRST, + PVT_VOLT, + PVT_LVT, + PVT_ULVT, + PVT_SVT, + PVT_SENSOR_LAST = PVT_SVT, + PVT_SENSORS_NUM +}; + +/* + * struct pvt_sensor_info - ESWIN PVT sensor informational structure + * @channel: Sensor channel ID. + * @label: hwmon sensor label. + * @mode: PVT mode corresponding to the channel. + * @thres_base: upper and lower threshold values of the sensor. + * @thres_sts_lo: low threshold status bitfield. + * @thres_sts_hi: high threshold status bitfield. + * @type: Sensor type. + * @attr_min_alarm: Min alarm attribute ID. + * @attr_min_alarm: Max alarm attribute ID. + */ +struct pvt_sensor_info { + int channel; + const char *label; + u32 mode; + unsigned long thres_base; + u32 thres_sts_lo; + u32 thres_sts_hi; + enum hwmon_sensor_types type; + u32 attr_min_alarm; + u32 attr_max_alarm; +}; + +#define PVT_SENSOR_INFO(_ch, _label, _type, _mode, _thres) \ + { \ + .channel = _ch, \ + .label = _label, \ + .mode = PVT_CTRL_MODE_ ##_mode, \ + .thres_base = PVT_ ##_thres, \ + .thres_sts_lo = PVT_INTR_ ##_thres## _LO, \ + .thres_sts_hi = PVT_INTR_ ##_thres## _HI, \ + .type = _type, \ + .attr_min_alarm = _type## _min, \ + .attr_max_alarm = _type## _max, \ + } + +/* + * struct pvt_cache - PVT sensors data cache + * @data: data cache in raw format. + * @thres_sts_lo: low threshold status saved on the previous data conversion. + * @thres_sts_hi: high threshold status saved on the previous data conversion. + * @data_seqlock: cached data seq-lock. + * @conversion: data conversion completion. + */ +struct pvt_cache { + u32 data; + struct completion conversion; +}; + +/* + * struct pvt_hwmon - Eswin PVT private data + * @dev: device structure of the PVT platform device. + * @hwmon: hwmon device structure. + * @regs: pointer to the Eswin PVT registers region. + * @irq: PVT events IRQ number. + * @clk: PVT core clock (1.2MHz). + * @pvt_rst: pointer to the reset descriptor. + * @iface_mtx: Generic interface mutex (used to lock the alarm registers + * when the alarms enabled, or the data conversion interface + * if alarms are disabled). + * @sensor: current PVT sensor the data conversion is being performed for. + * @cache: data cache descriptor. + * @timeout: conversion timeout cache. + */ +struct pvt_hwmon { + struct device *dev; + struct device *hwmon; + + void __iomem *regs; + int irq; + + struct clk *clk; + struct reset_control *pvt_rst; + struct mutex iface_mtx; + enum pvt_sensor_type sensor; + struct pvt_cache cache[PVT_SENSORS_NUM]; + ktime_t timeout; +}; + +/* + * struct pvt_poly_term - a term descriptor of the PVT data translation + * polynomial + * @deg: degree of the term. + * @coef: multiplication factor of the term. + * @divider: distributed divider per each degree. + * @divider_leftover: divider leftover, which couldn't be redistributed. + */ +struct pvt_poly_term { + unsigned int deg; + long coef; + long divider; + long divider_leftover; +}; + +/* + * struct pvt_poly - PVT data translation polynomial descriptor + * @total_divider: total data divider. + * @terms: polynomial terms up to a free one. + */ +struct pvt_poly { + long total_divider; + struct pvt_poly_term terms[]; +}; + +#endif /* __HWMON_ESWIN_PVT_H__ */ + From df86ed4f28be3e66245f72756a93439a3688a06e Mon Sep 17 00:00:00 2001 From: Pritesh Patel Date: Tue, 30 Jul 2024 14:17:25 +0000 Subject: [PATCH 26/38] drivers: kvm: vcpu: Disabled writing HENVCFG reg HENVCFG register is not present in EIC7700 SOC. So disabled writing this register Signed-off-by: Pritesh Patel --- arch/riscv/kvm/vcpu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c index 82229db1ce73f..9f1c1f887da27 100644 --- a/arch/riscv/kvm/vcpu.c +++ b/arch/riscv/kvm/vcpu.c @@ -487,7 +487,10 @@ static void kvm_riscv_vcpu_update_config(const unsigned long *isa) if (riscv_isa_extension_available(isa, ZICBOZ)) henvcfg |= ENVCFG_CBZE; +#ifndef CONFIG_SOC_SIFIVE_EIC7700 csr_write(CSR_HENVCFG, henvcfg); +#endif + #ifdef CONFIG_32BIT csr_write(CSR_HENVCFGH, henvcfg >> 32); #endif From c5edff5b22b60ff3b66499ded560d489d8971a3e Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Tue, 30 Jul 2024 15:10:52 +0000 Subject: [PATCH 27/38] drivers: hwmon: PAC1934: Add PAC1934 driver Signed-off-by: Yang Wei Signed-off-by: Pritesh Patel --- drivers/hwmon/Kconfig | 7 + drivers/hwmon/Makefile | 1 + drivers/hwmon/pac193x.c | 818 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 826 insertions(+) create mode 100644 drivers/hwmon/pac193x.c diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 78c456251902d..4f1939f839f0e 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1500,6 +1500,13 @@ config SENSORS_LM95245 This driver can also be built as a module. If so, the module will be called lm95245. +config SENSORS_PAC1934 + tristate "microchip PAC193X Hardware Monitoring" + depends on I2C + help + If you say yes here you get support for microchip PAC193X + Single/Multi-Channel DC Power/Energy Monitor with Accumulator. + config SENSORS_PC87360 tristate "National Semiconductor PC87360 family" depends on !PPC diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index f7b1e2c58131f..e32c22b616229 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -175,6 +175,7 @@ obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o obj-$(CONFIG_SENSORS_NZXT_KRAKEN2) += nzxt-kraken2.o obj-$(CONFIG_SENSORS_NZXT_SMART2) += nzxt-smart2.o obj-$(CONFIG_SENSORS_OXP) += oxp-sensors.o +obj-$(CONFIG_SENSORS_PAC1934) += pac193x.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PC87427) += pc87427.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o diff --git a/drivers/hwmon/pac193x.c b/drivers/hwmon/pac193x.c new file mode 100644 index 0000000000000..8a9ca9ec07b5f --- /dev/null +++ b/drivers/hwmon/pac193x.c @@ -0,0 +1,818 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for microchip pac1931,pac1932,pac1933,pac1934 power monitor chips + * + * 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 . + * + * Authors: Yang Wei + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PAC193X_MAX_CHAN_CNT 4 + +#define PAC193X_REGISTERS 0x27 +#define PAC193X_VPOWERN_ACC_LEN 6 +#define PAC193X_VOLT_VALUE_LEN 2 +#define PAC193X_VPOWERN_VALUE_LEN 4 +#define PAC193X_ACC_COUNT_LEN 3 + +#define PAC193X_CMD_REFRESH 0x0 +#define PAC193X_CMD_CTRL 0x1 +#define PAC193X_CMD_ACC_COUNT 0x2 +#define PAC193X_CMD_VPOWER1_ACC 0x3 +#define PAC193X_CMD_VPOWER2_ACC 0x4 +#define PAC193X_CMD_VPOWER3_ACC 0x5 +#define PAC193X_CMD_VPOWER4_ACC 0x6 +#define PAC193X_CMD_VBUS1 0x7 +#define PAC193X_CMD_VBUS2 0x8 +#define PAC193X_CMD_VBUS3 0x9 +#define PAC193X_CMD_VBUS4 0xa +#define PAC193X_CMD_VSENSE1 0xb +#define PAC193X_CMD_VSENSE2 0xc +#define PAC193X_CMD_VSENSE3 0xd +#define PAC193X_CMD_VSENSE4 0xe +#define PAC193X_CMD_VBUS1_AVG 0xf +#define PAC193X_CMD_VBUS2_AVG 0x10 +#define PAC193X_CMD_VBUS3_AVG 0x11 +#define PAC193X_CMD_VBUS4_AVG 0x12 +#define PAC193X_CMD_VSENSE1_AVG 0x13 +#define PAC193X_CMD_VSENSE2_AVG 0x14 +#define PAC193X_CMD_VSENSE3_AVG 0x15 +#define PAC193X_CMD_VSENSE4_AVG 0x16 +#define PAC193X_CMD_VPOWER1 0x17 +#define PAC193X_CMD_VPOWER2 0x18 +#define PAC193X_CMD_VPOWER3 0x19 +#define PAC193X_CMD_VPOWER4 0x1a +#define PAC193X_CMD_CHANNEL_SMBUS 0x1c +#define PAC193X_CMD_NEG_PWR 0x1D +#define PAC193X_CMD_REFRESH_G 0x1E +#define PAC193X_CMD_REFRESH_V 0x1F +#define PAC193X_CMD_SLOW 0x1F +#define PAC193X_CMD_CTRL_ACT 0x21 +#define PAC193X_CMD_DIS_ACT 0x22 +#define PAC193X_CMD_NEG_PWR_ACT 0x23 +#define PAC193X_CMD_CTRL_LAT 0x24 +#define PAC193X_CMD_DIS_LAT 0x25 +#define PAC193X_CMD_NEG_PWR_LAT 0x26 +#define PAC193X_CMD_PID 0xFD +#define PAC193X_CMD_MID 0xFE +#define PAC193X_CMD_REVERSION_ID 0xFF + +#define PAC1932X_COSTANT_PWR_M 3200000000ull /* 3.2V^2*1000mO*/ +#define PAC1932X_COSTANT_CURRENT_M 100000 /* 100mv*1000mO*/ + +struct pac193x_data { + struct mutex config_lock; + struct i2c_client *client; + u32 update_time_ms; + u32 energy_acc_count; + struct workqueue_struct *update_workqueue; + struct delayed_work update_work; + u32 vbus_denominator[PAC193X_MAX_CHAN_CNT]; + u32 vsense_denominator[PAC193X_MAX_CHAN_CNT]; + u32 vpower_denominator[PAC193X_MAX_CHAN_CNT]; + u32 sense_resistances[PAC193X_MAX_CHAN_CNT]; + u32 sample_rate; +}; + +enum PAC193X_CHAN_INDEX { + pac1931_index = 0, + pac1932_index, + pac1933_index, + pac1934_index +}; + +static int pac193x_get_energy(struct device *dev, u8 commmd, u8 chan, long *val) +{ + struct pac193x_data *data = dev_get_drvdata(dev); + int ret; + u64 cache = 0; + u8 *pcache = (u8 *)&cache; + u64 energy_value = 0; + + commmd = commmd + chan; + dev_dbg(dev, "%s.%d,chan:%d,commad:%d,LEN:%ld\n", __FUNCTION__, + __LINE__, chan, commmd, sizeof(cache)); + mutex_lock(&data->config_lock); + ret = i2c_smbus_read_i2c_block_data(data->client, commmd, + PAC193X_VPOWERN_ACC_LEN, pcache); + mutex_unlock(&data->config_lock); + + energy_value = ((cache & 0xff) << 40) | (((cache >> 8) & 0xff) << 32) | + (((cache >> 16) & 0xff) << 24) | + (((cache >> 24) & 0xff) << 16) | + (((cache >> 32) & 0xff) << 8) | (((cache >> 40) & 0xff)); + energy_value = energy_value & 0xffffffffffffULL; + dev_dbg(dev, + "%s.%d,commd:0x%x,value:%lld,ret:%d,resistances:%u,denominator:%u,sample_rate:%u\n", + __FUNCTION__, __LINE__, commmd, energy_value, ret, + data->sense_resistances[chan], data->vpower_denominator[chan], + data->sample_rate); + + /* energy=3200000*Vpower/(Rsense*denominator*sample_rate) */ + energy_value = ((energy_value / (u64)data->vpower_denominator[chan]) * + (PAC1932X_COSTANT_PWR_M / + (data->sense_resistances[chan] * data->sample_rate))); + + *val = energy_value; + + return 0; +} + +static u16 pac193x_get_word(struct pac193x_data *data, u8 commmd) +{ + int ret; + u16 cache = 0; + + mutex_lock(&data->config_lock); + ret = i2c_smbus_read_word_data(data->client, commmd); + mutex_unlock(&data->config_lock); + cache = ((ret & 0xff) << 8) | ((ret >> 8) & 0xff); + dev_dbg(&data->client->dev, "%s.%d,commd:0x%x,value:0x%x,ret:0x%x\n", + __FUNCTION__, __LINE__, commmd, cache, ret); + + return cache; +} + +static int pac193x_get_volt(struct device *dev, u8 commmd, u8 chan, long *val) +{ + struct pac193x_data *data = dev_get_drvdata(dev); + u16 cache = 0; + + commmd = commmd + chan; + dev_dbg(dev, "%s.%d,commd:0x%x,chan:%d,vbus_denominator:%d\n", + __FUNCTION__, __LINE__, commmd, chan, + data->vbus_denominator[chan]); + cache = pac193x_get_word(data, commmd); + /*to mV*/ + cache = cache * 1000 / data->vbus_denominator[chan]; + *val = cache; + return 0; +} + +static int pac193x_get_current(struct device *dev, u8 commmd, u8 chan, + long *val) +{ + struct pac193x_data *data = dev_get_drvdata(dev); + u16 cache = 0; + + commmd = commmd + chan; + dev_dbg(dev, + "%s.%d,commd:0x%x,chan:%d,vbus_denominator:%d,resistances:%d\n", + __FUNCTION__, __LINE__, commmd, chan, + data->vsense_denominator[chan], data->sense_resistances[chan]); + cache = pac193x_get_word(data, commmd); + /* I=Vsense*100/(Rsense*denominator) */ + cache = cache * PAC1932X_COSTANT_CURRENT_M / + (data->vsense_denominator[chan] * + data->sense_resistances[chan]); + *val = cache; + return 0; +} + +static int pac193x_get_power(struct device *dev, u8 commmd, u8 chan, long *val) +{ + struct pac193x_data *data = dev_get_drvdata(dev); + int ret; + u32 cache = 0; + u8 *pcache = (u8 *)&cache; + u64 pwr_value = 0; + + commmd = commmd + chan; + mutex_lock(&data->config_lock); + ret = i2c_smbus_read_i2c_block_data(data->client, commmd, + PAC193X_VPOWERN_VALUE_LEN, pcache); + mutex_unlock(&data->config_lock); + pwr_value = ((cache & 0xff) << 24) | (((cache >> 8) & 0xff) << 16) | + (((cache >> 16) & 0xff) << 8) | ((cache >> 24) & 0xff); + pwr_value = pwr_value >> 4; + dev_dbg(dev, + "%s.%d,commd:0x%x,chan:%d,value:0x%x,pwr_value:0x%llx,%llu,ret:%d,resistances:%u,denominator:%u\n", + __FUNCTION__, __LINE__, commmd, chan, cache, pwr_value, + pwr_value, ret, data->sense_resistances[chan], + data->vpower_denominator[chan]); + /* pwr=3200000*Vpower/Rsense*denominator */ + pwr_value = pwr_value * PAC1932X_COSTANT_PWR_M / + ((u64)data->sense_resistances[chan] * + (u64)data->vpower_denominator[chan]); + *val = pwr_value; + return 0; +} + +static int pac193x_send_refresh_cmd(struct pac193x_data *data, u8 command) +{ + int ret = 0; + + mutex_lock(&data->config_lock); + ret = i2c_smbus_write_byte(data->client, command); + mutex_unlock(&data->config_lock); + dev_dbg(&data->client->dev, "%s.%d,commd:0x%x,ret:%d\n", __FUNCTION__, + __LINE__, command, ret); + return ret; +} + +static ssize_t pac193x_refresh_store(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(da); + struct pac193x_data *data = dev_get_drvdata(dev); + + pac193x_send_refresh_cmd(data, (u8)sensor_attr->index); + return count; +} + +static struct sensor_device_attribute pac1934_refreshs[] = { + SENSOR_ATTR_WO(refresh_clear_acc, pac193x_refresh, PAC193X_CMD_REFRESH), + SENSOR_ATTR_WO(refresh_all_193x, pac193x_refresh, + PAC193X_CMD_REFRESH_G), + SENSOR_ATTR_WO(refresh_updata_value, pac193x_refresh, + PAC193X_CMD_REFRESH_V), +}; + +static u8 pac193x_read_byte_data(struct pac193x_data *data, u8 command) +{ + int cache = 0; + int cnt = 0; + while (1) { + mutex_lock(&data->config_lock); + cache = i2c_smbus_read_byte_data(data->client, command); + mutex_unlock(&data->config_lock); + if (0xff != cache) { + break; + } + cnt++; + if (cnt > 100) { + dev_err(&data->client->dev, + "get command:%d value error\n", command); + return 0xff; + } + } + return (u8)cache; +} + +static ssize_t pac193x_ctrl_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pac193x_data *data = dev_get_drvdata(dev); + u8 set_val = 0, act_val = 0, lat_val = 0; + + set_val = pac193x_read_byte_data(data, PAC193X_CMD_CTRL); + act_val = pac193x_read_byte_data(data, PAC193X_CMD_CTRL_ACT); + lat_val = pac193x_read_byte_data(data, PAC193X_CMD_CTRL_LAT); + + return sprintf(buf, + "%16s:%6s,%6s,%6s\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n", + "", "set", "act", "latch", + "sample_rate",(set_val >> 6) & 0x3, (act_val >> 6) & 0x3, (lat_val >> 6) & 0x3, + "SLEEP", (set_val >> 5) & 0x1,(act_val >> 5) & 0x1, (lat_val >> 5) & 0x1, + "SING", (set_val >> 4) & 0x1, (act_val >> 4) & 0x1, (lat_val >> 4) & 0x1, + "ALERT_PIN", (set_val >> 3) & 0x1, (act_val >> 3) & 0x1, (lat_val >> 3) & 0x1, + "ALERT_CC", (set_val >> 2) & 0x1, (act_val >> 2) & 0x1, (lat_val >> 2) & 0x1, + "OVF ALERT", (set_val >> 1) & 0x1, (act_val >> 1) & 0x1, (lat_val >> 1) & 0x1, + "OVF", (set_val >> 0) & 0x1, (act_val >> 0) & 0x1, (lat_val >> 0) & 0x1); +} + +int pac193x_common_reg_set(struct device *dev, const char *buf, u8 commad) +{ + struct pac193x_data *data = dev_get_drvdata(dev); + unsigned long val; + int status; + int ret = 0; + + status = kstrtoul(buf, 10, &val); + if (status < 0) + return status; + mutex_lock(&data->config_lock); + ret = i2c_smbus_write_byte_data(data->client, commad, (u8)val); + mutex_unlock(&data->config_lock); + return ret; +} + +static ssize_t pac193x_ctrl_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return pac193x_common_reg_set(dev, buf, PAC193X_CMD_CTRL); +} + +DEVICE_ATTR(control, S_IWUSR | S_IRUGO, pac193x_ctrl_show, pac193x_ctrl_store); + +static ssize_t pac193x_acc_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pac193x_data *data = dev_get_drvdata(dev); + int ret; + u32 cache = 0; + u8 *pcache = (u8 *)&cache; + u32 acc_cnt = 0; + mutex_lock(&data->config_lock); + ret = i2c_smbus_read_i2c_block_data(data->client, PAC193X_CMD_ACC_COUNT, + PAC193X_ACC_COUNT_LEN, pcache); + mutex_unlock(&data->config_lock); + + acc_cnt = ((cache & 0xff) << 16) | (((cache >> 8) & 0xff) << 8) | + ((cache >> 16) & 0xff); + acc_cnt = acc_cnt & 0xffffff; + + ret = sysfs_emit(buf, "%u\n", acc_cnt); + return ret; +} + +DEVICE_ATTR(acc_count, 0400, pac193x_acc_count_show, NULL); + +static ssize_t pac193x_dis_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pac193x_data *data = dev_get_drvdata(dev); + u8 set_val = 0, act_val = 0, lat_val = 0; + + set_val = pac193x_read_byte_data(data, PAC193X_CMD_CHANNEL_SMBUS); + act_val = pac193x_read_byte_data(data, PAC193X_CMD_DIS_ACT); + lat_val = pac193x_read_byte_data(data, PAC193X_CMD_DIS_LAT); + + return sprintf(buf, + "%16s:%6s,%6s,%6s\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n", + "", "set", "act", "latch", + "CH1_OFF", (set_val >> 7) & 0x1, (act_val >> 7) & 0x1, (lat_val >> 7) & 0x1, + "CH2_OFF", (set_val >> 6) & 0x1, (act_val >> 6) & 0x1, (lat_val >> 6) & 0x1, + "CH3_OFF", (set_val >> 5) & 0x1, (act_val >> 5) & 0x1, (lat_val >> 5) & 0x1, + "CH4_OFF", (set_val >> 4) & 0x1, (act_val >> 4) & 0x1, (lat_val >> 4) & 0x1, + "TIMEOUT", (set_val >> 3) & 0x1, (act_val >> 3) & 0x1, (lat_val >> 3) & 0x1, + "BYTE COUNT", (set_val >> 2) & 0x1, (act_val >> 2) & 0x1, (lat_val >> 2) & 0x1, + "NO SKIP", (set_val >> 1) & 0x1, (act_val >> 1) & 0x1, (lat_val >> 1) & 0x1); +} + +static ssize_t pac193x_dis_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + return pac193x_common_reg_set(dev, buf, PAC193X_CMD_CHANNEL_SMBUS); +} + +DEVICE_ATTR(disable_chan_pmbus, S_IWUSR | S_IRUGO, pac193x_dis_show, + pac193x_dis_store); + +static ssize_t pac193x_neg_pwr_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pac193x_data *data = dev_get_drvdata(dev); + u8 set_val = 0, act_val = 0, lat_val = 0; + + set_val = pac193x_read_byte_data(data, PAC193X_CMD_NEG_PWR); + act_val = pac193x_read_byte_data(data, PAC193X_CMD_NEG_PWR_ACT); + lat_val = pac193x_read_byte_data(data, PAC193X_CMD_NEG_PWR_LAT); + + return sprintf(buf, + "%16s:%6s,%6s,%6s\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n" + "%16s:%6d,%6d,%6d\n", + "", "set", "act", "latch", + "CH1_BIDI", (set_val >> 7) & 0x1, (act_val >> 7) & 0x1, (lat_val >> 7) & 0x1, + "CH2_BIDI", (set_val >> 6) & 0x1, (act_val >> 6) & 0x1, (lat_val >> 6) & 0x1, + "CH3_BIDI", (set_val >> 5) & 0x1, (act_val >> 5) & 0x1, (lat_val >> 5) & 0x1, + "CH4_BIDI", (set_val >> 4) & 0x1, (act_val >> 4) & 0x1, (lat_val >> 5) & 0x1, + "CH1_BIDV", (set_val >> 3) & 0x1, (act_val >> 3) & 0x1, (lat_val >> 3) & 0x1, + "CH2_BIDV", (set_val >> 2) & 0x1, (act_val >> 2) & 0x1, (lat_val >> 2) & 0x1, + "CH3_BIDV", (set_val >> 1) & 0x1, (act_val >> 1) & 0x1, (lat_val >> 1) & 0x1, + "CH4_BIDV", (set_val >> 0) & 0x1, (act_val >> 0) & 0x1, (lat_val >> 0) & 0x1); +} + +static ssize_t pac193x_neg_pwr_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return pac193x_common_reg_set(dev, buf, PAC193X_CMD_NEG_PWR); +} + +DEVICE_ATTR(neg_pwr, S_IWUSR | S_IRUGO, pac193x_neg_pwr_show, + pac193x_neg_pwr_store); + +static ssize_t pac193x_slow_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pac193x_data *data = dev_get_drvdata(dev); + u8 set_val = 0; + + set_val = pac193x_read_byte_data(data, PAC193X_CMD_SLOW); + + return sprintf(buf, + "SLOW:%d,SLOW-LH:%d,SLOW-HL:%d, R_RISE:%d," + "R_V_RISE:%d,R_FALL:%d,R_V_FALL:%d,POR:%d\n", + (set_val >> 7) & 0x1, (set_val >> 6) & 0x1, + (set_val >> 5) & 0x1, (set_val >> 4) & 0x1, + (set_val >> 3) & 0x1, (set_val >> 2) & 0x1, + (set_val >> 1) & 0x1, (set_val >> 0) & 0x1); +} + +static ssize_t pac193x_slow_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return pac193x_common_reg_set(dev, buf, PAC193X_CMD_SLOW); +} + +DEVICE_ATTR(slow_ctrl, S_IWUSR | S_IRUGO, pac193x_slow_show, + pac193x_slow_store); + +static ssize_t pac193x_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pac193x_data *data = dev_get_drvdata(dev); + int ret; + u8 pid = 0, mid = 0, rid = 0; + + pid = pac193x_read_byte_data(data, PAC193X_CMD_PID); + mid = pac193x_read_byte_data(data, PAC193X_CMD_MID); + rid = pac193x_read_byte_data(data, PAC193X_CMD_REVERSION_ID); + + ret = sysfs_emit(buf, "PID:0x%x,MID:0x%x,RID:0x%x\n", pid, mid, rid); + return ret; +} +DEVICE_ATTR(pac193x_version, 0400, pac193x_version_show, NULL); + +static struct attribute *pac193x_attrs[] = { + &dev_attr_control.attr, + &dev_attr_acc_count.attr, + &dev_attr_neg_pwr.attr, + &dev_attr_disable_chan_pmbus.attr, + &dev_attr_slow_ctrl.attr, + &dev_attr_pac193x_version.attr, + &pac1934_refreshs[0].dev_attr.attr, + &pac1934_refreshs[1].dev_attr.attr, + &pac1934_refreshs[2].dev_attr.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(pac193x); + +static const struct hwmon_channel_info *pac1931_info[] = { + HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_AVERAGE, + HWMON_I_INPUT | HWMON_I_AVERAGE), + HWMON_CHANNEL_INFO(curr, HWMON_C_INPUT | HWMON_C_AVERAGE), + HWMON_CHANNEL_INFO(power, HWMON_P_INPUT), + HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT), NULL +}; +static const struct hwmon_channel_info *pac1932_info[] = { + HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_AVERAGE, + HWMON_I_INPUT | HWMON_I_AVERAGE, + HWMON_I_INPUT | HWMON_I_AVERAGE), + HWMON_CHANNEL_INFO(curr, HWMON_C_INPUT | HWMON_C_AVERAGE, + HWMON_C_INPUT | HWMON_C_AVERAGE), + HWMON_CHANNEL_INFO(power, HWMON_P_INPUT, HWMON_P_INPUT), + HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT, HWMON_E_INPUT), NULL +}; +static const struct hwmon_channel_info *pac1933_info[] = { + HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_AVERAGE, + HWMON_I_INPUT | HWMON_I_AVERAGE, + HWMON_I_INPUT | HWMON_I_AVERAGE, + HWMON_I_INPUT | HWMON_I_AVERAGE), + HWMON_CHANNEL_INFO(curr, HWMON_C_INPUT | HWMON_C_AVERAGE, + HWMON_C_INPUT | HWMON_C_AVERAGE, + HWMON_C_INPUT | HWMON_C_AVERAGE), + HWMON_CHANNEL_INFO(power, HWMON_P_INPUT, HWMON_P_INPUT, HWMON_P_INPUT), + HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT, HWMON_E_INPUT, HWMON_E_INPUT), + NULL +}; +static const struct hwmon_channel_info *pac1934_info[] = { + HWMON_CHANNEL_INFO(in, + HWMON_I_INPUT | HWMON_I_AVERAGE, + HWMON_I_INPUT | HWMON_I_AVERAGE, + HWMON_I_INPUT | HWMON_I_AVERAGE, + HWMON_I_INPUT | HWMON_I_AVERAGE, + HWMON_I_INPUT | HWMON_I_AVERAGE), + HWMON_CHANNEL_INFO(curr, + HWMON_C_INPUT | HWMON_C_AVERAGE, + HWMON_C_INPUT | HWMON_C_AVERAGE, + HWMON_C_INPUT | HWMON_C_AVERAGE, + HWMON_C_INPUT | HWMON_C_AVERAGE), + HWMON_CHANNEL_INFO(power, HWMON_P_INPUT, HWMON_P_INPUT, HWMON_P_INPUT, + HWMON_P_INPUT), + HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT, HWMON_E_INPUT, HWMON_E_INPUT, + HWMON_E_INPUT), + NULL +}; + +static umode_t pac1934x_is_visible(const void *_data, + enum hwmon_sensor_types type, u32 attr, + int channel) +{ + switch (type) { + case hwmon_in: + switch (attr) { + case hwmon_in_input: + case hwmon_in_average: + if(channel == 0) + { + return 0; + } + else + { + return S_IRUGO; + } + } + break; + case hwmon_curr: + switch (attr) { + case hwmon_curr_input: + case hwmon_curr_average: + return S_IRUGO; + } + break; + case hwmon_power: + switch (attr) { + case hwmon_power_input: + return S_IRUGO; + } + break; + case hwmon_energy: + switch (attr) { + case hwmon_energy_input: + return S_IRUGO; + } + break; + default: + break; + } + return 0; +} + +static int pac193x_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + switch (type) { + case hwmon_in: + switch (attr) { + case hwmon_in_input: + return pac193x_get_volt(dev, PAC193X_CMD_VBUS1, channel - 1, + val); + case hwmon_in_average: + return pac193x_get_volt(dev, PAC193X_CMD_VBUS1_AVG, + channel - 1, val); + } + break; + case hwmon_curr: + switch (attr) { + case hwmon_curr_input: + return pac193x_get_current(dev, PAC193X_CMD_VSENSE1, + channel, val); + case hwmon_curr_average: + return pac193x_get_current(dev, PAC193X_CMD_VSENSE1_AVG, + channel, val); + } + break; + case hwmon_power: + switch (attr) { + case hwmon_power_input: + return pac193x_get_power(dev, PAC193X_CMD_VPOWER1, + channel, val); + } + break; + case hwmon_energy: + switch (attr) { + case hwmon_energy_input: + return pac193x_get_energy(dev, PAC193X_CMD_VPOWER1_ACC, + channel, val); + } + break; + default: + break; + } + return 0; +} + +static const struct hwmon_ops pac193x_hwmon_ops = { + .is_visible = pac1934x_is_visible, + .read = pac193x_read, +}; + +static struct hwmon_chip_info pac193x_chip_info = { + .ops = &pac193x_hwmon_ops, + .info = NULL, +}; + +static void update_reg_data(struct work_struct *work) +{ + static u32 updata_cnt = 0; + struct pac193x_data *data; + int act_val = 0, ctrl_val = 0, slow_val = 0; + int num = 0; + bool is_neg = false; + + data = container_of(work, struct pac193x_data, update_work.work); + if ((data->energy_acc_count == 0)||(updata_cnt < data->energy_acc_count)) { + pac193x_send_refresh_cmd(data, PAC193X_CMD_REFRESH_V); + updata_cnt++; + } else { + pac193x_send_refresh_cmd(data, PAC193X_CMD_REFRESH); + updata_cnt = 0; + } + + act_val = pac193x_read_byte_data(data, PAC193X_CMD_NEG_PWR_ACT); + + for (num = 0; num < PAC193X_MAX_CHAN_CNT; num++) { + is_neg = false; + if (0x1 == ((act_val >> num) & 0x1)) { + /* Vsource=32*Vbus/2^15 = Vbus/2^10=Vbus/1024 */ + data->vbus_denominator[3 - num] = 1024; + is_neg = true; + } else { + /* Vsource=32*Vbus/2^16 = Vbus/2^10=Vbus/1024 */ + data->vbus_denominator[3 - num] = 2048; + } + + if (0x1 == ((act_val >> (num + 4)) & 0x1)) { + /* 2^15 */ + data->vsense_denominator[3 - num] = 32768; + is_neg = true; + } else { + /*2^16 */ + data->vsense_denominator[3 - num] = 65536; + } + if (true == is_neg) { + /* 2^28 */ + data->vpower_denominator[3 - num] = 134217728; + } else { + /* 2^29 */ + data->vpower_denominator[3 - num] = 268435456; + } + } + + slow_val = pac193x_read_byte_data(data, PAC193X_CMD_SLOW); + ctrl_val = pac193x_read_byte_data(data, PAC193X_CMD_CTRL_ACT); + if ((0x1 == ((slow_val >> 7) & 0x1)) && + (0x0 == ((ctrl_val >> 3) & 0x1))) { + data->sample_rate = 8; + } else { + switch ((ctrl_val >> 6) & 0x3) { + case 0: + data->sample_rate = 1024; + break; + case 1: + data->sample_rate = 256; + break; + case 2: + data->sample_rate = 64; + break; + case 3: + data->sample_rate = 8; + break; + default: + break; + } + } + queue_delayed_work(data->update_workqueue, &data->update_work, + msecs_to_jiffies(data->update_time_ms)); +} + +static int pac193x_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct pac193x_data *data; + struct device *hwmon_dev; + int ret = 0; + int num = 0; + enum PAC193X_CHAN_INDEX chan_index = + (enum PAC193X_CHAN_INDEX)of_device_get_match_data(&client->dev); + + switch (chan_index) { + case pac1931_index: + pac193x_chip_info.info = pac1931_info; + break; + case pac1932_index: + pac193x_chip_info.info = pac1932_info; + break; + case pac1933_index: + pac193x_chip_info.info = pac1933_info; + break; + case pac1934_index: + pac193x_chip_info.info = pac1934_info; + break; + default: + break; + } + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + for (num = 0; num < PAC193X_MAX_CHAN_CNT; num++) { + data->vbus_denominator[num] = 1; + data->vsense_denominator[num] = 1; + data->sense_resistances[num] = 1; + } + + ret = of_property_read_u32(dev->of_node, "update_time_ms", + &data->update_time_ms); + if (0 != ret) { + dev_err(dev, "can not get update_time_ms:%d\n", ret); + data->update_time_ms = 100; + } + + ret = of_property_read_u32(dev->of_node, "energy_acc_count", + &data->energy_acc_count); + if (0 != ret) { + dev_err(dev, "can not get energy_acc_count:%d\n", ret); + data->energy_acc_count = 0; + } + ret = of_property_read_u32_array(dev->of_node, "sense_resistances", + data->sense_resistances, + PAC193X_MAX_CHAN_CNT); + if (0 != ret) { + dev_err(dev, "can not get sense_resistances:%d\n", ret); + } + + dev_info(dev, + "update_time:%d,energy_acc_count:%d,resistances:%d,%d,%d,%dmOhm\n", + data->update_time_ms, data->energy_acc_count, + data->sense_resistances[0], data->sense_resistances[1], + data->sense_resistances[2], data->sense_resistances[3]); + mutex_init(&data->config_lock); + data->client = client; + mutex_lock(&data->config_lock); + i2c_smbus_write_byte_data(data->client, PAC193X_CMD_CTRL, 0x8); + mutex_unlock(&data->config_lock); + pac193x_send_refresh_cmd(data, PAC193X_CMD_REFRESH); + + hwmon_dev = devm_hwmon_device_register_with_info( + dev, client->name, data, &pac193x_chip_info, pac193x_groups); + if (IS_ERR(hwmon_dev)) + return PTR_ERR(hwmon_dev); + + data->update_workqueue = create_workqueue("update_workqueue"); + + INIT_DELAYED_WORK(&data->update_work, update_reg_data); + queue_delayed_work(data->update_workqueue, &data->update_work, + msecs_to_jiffies(0)); + + return 0; +} + +static const struct of_device_id __maybe_unused pac193x_of_match[] = { + { .compatible = "microchip,pac1931", .data = (void *)pac1931_index }, + { .compatible = "microchip,pac1932", .data = (void *)pac1932_index }, + { .compatible = "microchip,pac1933", .data = (void *)pac1933_index }, + { .compatible = "microchip,pac1934", .data = (void *)pac1934_index }, + {}, +}; +MODULE_DEVICE_TABLE(of, pac193x_of_match); + +static struct i2c_driver pac193x_driver = { + .driver = { + .name = "pac193x", + .of_match_table = of_match_ptr(pac193x_of_match), + }, + .probe = pac193x_probe, +}; + +module_i2c_driver(pac193x_driver); + +MODULE_AUTHOR("Yang Wei Date: Tue, 30 Jul 2024 15:18:03 +0000 Subject: [PATCH 28/38] drivers: spi: Add bootspi flash driver for EIC7700 Signed-off-by: huangyifeng Signed-off-by: Pritesh Patel --- drivers/spi/Kconfig | 6 + drivers/spi/Makefile | 1 + drivers/spi/spi-eswin-bootspi.c | 658 ++++++++++++++++++++++++++++++++ 3 files changed, 665 insertions(+) create mode 100644 drivers/spi/spi-eswin-bootspi.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3ce0fd5df8e9c..07e874de0ebfc 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -360,6 +360,12 @@ config SPI_EP93XX This enables using the Cirrus EP93xx SPI controller in master mode. +config SPI_ESWIN_BOOTSPI + tristate "Eswin Computing Boot SPI controller" + help + This enables using the Eswin Computing Boot SPI controller in master + mode. + config SPI_FALCON bool "Falcon SPI controller support" depends on SOC_FALCON diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 6af54842b9fa4..0dc6ae53485b6 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_SPI_DW_BT1) += spi-dw-bt1.o obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o obj-$(CONFIG_SPI_DW_PCI) += spi-dw-pci.o obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o +obj-$(CONFIG_SPI_ESWIN_BOOTSPI) += spi-eswin-bootspi.o obj-$(CONFIG_SPI_FALCON) += spi-falcon.o obj-$(CONFIG_SPI_FSI) += spi-fsi.o obj-$(CONFIG_SPI_FSL_CPM) += spi-fsl-cpm.o diff --git a/drivers/spi/spi-eswin-bootspi.c b/drivers/spi/spi-eswin-bootspi.c new file mode 100644 index 0000000000000..c8fbc1b3fc919 --- /dev/null +++ b/drivers/spi/spi-eswin-bootspi.c @@ -0,0 +1,658 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN BootSpi 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 . + * + * Authors: HuangYiFeng + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register offsets */ +#define ES_SPI_CSR_00 0x00 /*WRITE_STATUS_REG_TIME*/ +#define ES_SPI_CSR_01 0x04 /*SPI_BUS_MODE*/ +#define ES_SPI_CSR_02 0x08 /*ERASE_COUNTER_TAP*/ +#define ES_SPI_CSR_03 0x0c /*DMA_EN_HCLK_STATUS*/ +#define ES_SPI_CSR_04 0x10 /*FAST_READ_CONTROL*/ +#define ES_SPI_CSR_05 0x14 /*SPI_FLASH_WR_NUM*/ +#define ES_SPI_CSR_06 0x18 /*SPI_FLASH_COMMAND*/ +#define ES_SPI_CSR_07 0x1c /*INTERRUPT_CONTROL*/ +#define ES_SPI_CSR_08 0x20 /*DMA_REQUEST_TAP*/ +#define ES_SPI_CSR_09 0x24 /*SPI_FLASH_WR_ADDRESS*/ +#define ES_SPI_CSR_10 0x28 /*PAGE_PROGRAM_TIME*/ +#define ES_SPI_CSR_11 0x2c /*SECTOR_ERASE_TIME*/ +#define ES_SPI_CSR_12 0x30 /*SMALL_BLOCK_ERASE_TIME*/ +#define ES_SPI_CSR_13 0x34 /*LARGE_BLOCK_ERASE_TIME*/ +#define ES_SPI_CSR_14 0x38 /*CHIP_ERASE_TIME*/ +#define ES_SPI_CSR_15 0x3c /*CHIP_DESELECT_TIME*/ +#define ES_SPI_CSR_16 0x40 /*POWER_DOWN_TIME*/ + +#define ES_SYSCSR_SPIMODECFG 0x340 + +#define ES_CONCSR_SPI_INTSEL 0x3c0 + +#define SPI_COMMAND_VALID 0x01 +#define SPI_COMMAND_MOVE_VALUE 0x00 +#define SPI_COMMAND_CODE_FIELD_POSITION 0X06 +#define SPI_COMMAND_MOVE_FIELD_POSITION 0X05 +#define SPI_COMMAND_TYPE_FIELD_POSITION 0X01 + +/* Bit fields in CTRLR0 */ +/* + * Only present when SSI_MAX_XFER_SIZE=16. This is the default, and the only + * option before version 3.23a. + */ +#define SPI_INTSEL_MASK GENMASK(11, 10) +#define INT_ROUTED_U84 0x0 +#define INT_ROUTED_LPCPU 0x1 +#define INT_ROUTED_SCPU 0x3u + +#define RX_TIMEOUT 5000 /* timeout in ms */ + +#define SPI_COMMAND_INIT_VALUE 0XFFFFC000 +#define FLASH_PAGE_SIZE 0x100 + +typedef enum { + SPI_FLASH_WR_BYTE = 1, + SPI_FLASH_WR_2BYTE = 2, + SPI_FLASH_WR_WORD = 4, +} SPI_FLASH_WR_NUM_T; + +typedef enum { + SPI_FAST_READ_DEFAULT = 0, + SPI_FAST_READ_ENABLE = 3 /*WHEN SPI QUAD0 OR DUAL MODE*/ +} SPI_FAST_READ_CTL_T; + +typedef enum { STANDARD_SPI = 0, DUAL_SPI, QUAD_SPI } SPI_BUS_MODE_T; + +typedef enum { + SPIC_CMD_TYPE_SPI_PROGRAM = 0, + SPIC_CMD_TYPE_WRITE_STATUS_REGISTER, + SPIC_CMD_TYPE_READ_STATUS_REGISTER, + SPIC_CMD_TYPE_SECTOR_ERASE, + SPIC_CMD_TYPE_BLOCK_ERASE_TYPE1, + SPIC_CMD_TYPE_BLOCK_ERASE_TYPE2, + SPIC_CMD_TYPE_CHIP_ERASE, + SPIC_CMD_TYPE_POWER_DOWN, + SPIC_CMD_TYPE_RELEASE_POWER_DOWM, + SPIC_CMD_TYPE_ENTER_OR_EXIT_32BIT_MODE, + SPIC_CMD_TYPE_READ_SECURITY_REG, + SPIC_CMD_TYPE_ERASE_SECURITY_REG, + SPIC_CMD_TYPE_WRITE_SECURITY_REG, + SPIC_CMD_TYPE_READ_DATA, + SPIC_CMD_TYPE_READ_MANUFACTURED_ID, + SPIC_CMD_TYPE_READ_JEDEC_ID +} SPI_FLASH_COMMAND_TYPE_T; + +#define SPIC_CMD_CODE_POWER_DOWN 0xb9 +#define SPIC_CMD_CODE_RELEASE_POWER_DOWN 0xab +#define SPIC_CMD_CODE_ENABLE_RESET 0x66 +#define SPIC_CMD_CODE_RESET 0x99 + +struct es_spi_priv { + struct clk *cfg_clk; + struct clk *clk; + struct reset_control *rstc; + struct gpio_desc *cs_gpio; /* External chip-select gpio */ + + void __iomem *regs; + void __iomem *sys_regs; + void __iomem *flash_base; + unsigned int freq; /* Default frequency */ + unsigned int mode; + + const void *tx; + u32 opcode; + u32 cmd_type; + u64 addr; + void *rx; + u32 fifo_len; /* depth of the FIFO buffer */ + u32 max_xfer; /* Maximum transfer size (in bits) */ + + int bits_per_word; + int len; + u8 cs; /* chip select pin */ + u8 tmode; /* TR/TO/RO/EEPROM */ + u8 type; /* SPI/SSP/MicroWire */ + struct spi_controller *master; + struct device *dev; + int irq; +}; + +static inline u32 eswin_bootspi_read(struct es_spi_priv *priv, u32 offset) +{ + return readl(priv->regs + offset); +} + +static inline void eswin_bootspi_write(struct es_spi_priv *priv, u32 offset, u32 val) +{ + writel(val, priv->regs + offset); +} + +static inline u32 eswin_bootspi_data_read(struct es_spi_priv *priv, u32 offset) +{ + return readl(priv->flash_base + offset); +} + +static inline void eswin_bootspi_data_write(struct es_spi_priv *priv, u32 offset, u32 val) +{ + writel(val, priv->flash_base + offset); +} + +static int eswin_bootspi_wait_over(struct es_spi_priv *priv) +{ + u32 val; + struct device *dev = priv->dev; + + if (readl_poll_timeout(priv->regs + ES_SPI_CSR_06, val, + (!(val & 0x1)), 10, RX_TIMEOUT * 1000)) { + dev_err(dev, "eswin_bootspi_wait_over : timeout!!\n"); + return -ETIMEDOUT; + } + return 0; +} + +/** + * @brief spi read and write cfg + */ +static void eswin_bootspi_read_write_cfg(struct es_spi_priv *priv, u32 byte, u32 addr) +{ + eswin_bootspi_write(priv, ES_SPI_CSR_09, addr); + eswin_bootspi_write(priv, ES_SPI_CSR_05, byte); + eswin_bootspi_write(priv, ES_SPI_CSR_04, SPI_FAST_READ_DEFAULT); + eswin_bootspi_write(priv, ES_SPI_CSR_01, STANDARD_SPI); +} + +/** + * @brief write data from dest address to flash + */ +static void eswin_bootspi_send_data(struct es_spi_priv *priv, + const u8 *dest, u32 size) +{ + u32 offset = 0; + u8 *buff = (u8 *)dest; + u32 data = 0; + int i; + struct device *dev = priv->dev; + + dev_dbg(dev,"wrtie spi data\n"); + while (size >= SPI_FLASH_WR_WORD) { + data = (buff[0]) | (buff[1] << 8) |(buff[2] << 16) | (buff[3] << 24); + for (i = 0; i < 4; i++) { + dev_dbg(dev,"0x%x ", buff[i]); + } + dev_dbg(dev,"0x%x ", data); + eswin_bootspi_data_write(priv, offset, data); + offset = offset + SPI_FLASH_WR_WORD; + size = size - SPI_FLASH_WR_WORD; + buff = buff + SPI_FLASH_WR_WORD; + } + data = 0; + if (size != 0) { + for (i = 0; i < size; i++) { + data |=buff[i] << (8 * i); + dev_dbg(dev,"0x%x ", buff[i]); + } + dev_dbg(dev,"0x%x ", data); + eswin_bootspi_data_write(priv, offset, data); + } +} + +/** + * @brief Read data from flash to dest address + */ +static void eswin_bootspi_recv_data(struct es_spi_priv *priv, u8 *dest, u32 size) +{ + u32 offset = 0; + u8 *buff = NULL; + u32 data = 0xFFFFFFFF; + int i; + struct device *dev = priv->dev; + + dev_dbg(dev,"read spi data\n"); + while (size >= SPI_FLASH_WR_WORD) { + buff = (u8 *)dest; + data = eswin_bootspi_data_read(priv, offset); + dev_dbg(dev,"0x%x ", data); + for (i = 0; i < SPI_FLASH_WR_WORD; i++) { + *buff = (u8)(data >> (8 * i)); + dev_dbg(dev,"0x%x ", *buff); + buff++; + } + dest = dest + SPI_FLASH_WR_WORD; + offset = offset + SPI_FLASH_WR_WORD; + size = size - SPI_FLASH_WR_WORD; + } + if (size != 0) { + buff = (u8 *)dest; + data = eswin_bootspi_data_read(priv, offset); + for (i = 0; i < size; i++) { + *buff = (u8)(data >> (8 * i)); + dev_dbg(dev,"0x%x ", *buff); + buff++; + } + } + dev_dbg(dev,"\n"); +} + + +/** + * @brief spi send command + */ +static void eswin_bootspi_cmd_cfg(struct es_spi_priv *priv, u32 code, u32 type) +{ + u32 command = eswin_bootspi_read(priv, ES_SPI_CSR_06); + struct device *dev = priv->dev; + + command &= ~((0xFF << 6) | (0x1 << 5) | (0xF << 1) | 0x1); + command |= ((code << SPI_COMMAND_CODE_FIELD_POSITION) | + (SPI_COMMAND_MOVE_VALUE << SPI_COMMAND_MOVE_FIELD_POSITION) | + (type << SPI_COMMAND_TYPE_FIELD_POSITION) | SPI_COMMAND_VALID); + + eswin_bootspi_write(priv, ES_SPI_CSR_06, command); + dev_dbg(dev, "[%s %d]: write command 0x%x, read back command 0x%x\n", + __func__,__LINE__, command, eswin_bootspi_read(priv, ES_SPI_CSR_06)); +} +/** + * @brief spi write flash + * @param [in] offset: address of flash to be write + * @param [in] wr_dest: Address of data to be sent + * @param [in] size: size of flash to be write + */ +void eswin_bootspi_writer(struct es_spi_priv *priv) +{ + u32 write_size = 0, offset, cmd_code; + u32 cmd_type = priv->cmd_type; + const u8 *wr_dest = priv->tx; + int size = priv->len; + + offset = priv->addr; + cmd_code = priv->opcode; + + if (size == 0) { + // if(SPIC_CMD_TYPE_SECTOR_ERASE == cmd_type) + { + eswin_bootspi_read_write_cfg(priv, write_size, offset); + eswin_bootspi_cmd_cfg(priv, cmd_code, cmd_type); + eswin_bootspi_wait_over(priv); + } + } + while (size > 0) { + write_size = size; + if (write_size > FLASH_PAGE_SIZE) { + write_size = FLASH_PAGE_SIZE; + } + eswin_bootspi_read_write_cfg(priv, write_size, offset); + eswin_bootspi_send_data(priv, wr_dest, write_size); + eswin_bootspi_cmd_cfg(priv, cmd_code, cmd_type); + eswin_bootspi_wait_over(priv); + wr_dest += write_size; + offset += write_size; + size = size - write_size; + } +} + +static void eswin_bootspi_reader(struct es_spi_priv *priv) +{ + int read_size = 0; + u32 offset = priv->addr; + u32 cmd_code = priv->opcode; + u32 cmd_type = priv->cmd_type; + u8 *mem_dest = priv->rx; + int size = priv->len; + + while (size > 0) { + read_size = size; + if (read_size > FLASH_PAGE_SIZE) { + read_size = FLASH_PAGE_SIZE; + } + + eswin_bootspi_read_write_cfg(priv, read_size, offset); + eswin_bootspi_cmd_cfg(priv, cmd_code, cmd_type); + eswin_bootspi_wait_over(priv); + eswin_bootspi_recv_data(priv, mem_dest, read_size); + mem_dest += read_size; + offset += read_size; + size = size - read_size; + } +} + +/* + * We define external_cs_manage function as 'weak' as some targets + * (like MSCC Ocelot) don't control the external CS pin using a GPIO + * controller. These SoCs use specific registers to control by + * software the SPI pins (and especially the CS). + */ + +static void external_cs_manage(struct es_spi_priv *priv, bool on) +{ + gpiod_set_value(priv->cs_gpio, on ? 1 : 0); +} + +/* The size of ctrl1 limits data transfers to 64K */ +static int eswin_bootspi_adjust_op_size(struct spi_mem *mem, + struct spi_mem_op *op) +{ + op->data.nbytes = min(op->data.nbytes, (unsigned int)SZ_64K); + + return 0; +} + +/* + * The controller only supports Standard SPI mode, Duall mode and + * Quad mode. Double sanitize the ops here to avoid OOB access. + */ +static bool eswin_bootspi_supports_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + return spi_mem_default_supports_op(mem, op); +} + +static int eswin_bootspi_exec_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + bool read = op->data.dir == SPI_MEM_DATA_IN; + int ret = 0; + struct es_spi_priv *priv = spi_master_get_devdata(mem->spi->master); + struct device *dev = priv->dev; + + priv->addr = op->addr.val; + priv->opcode = op->cmd.opcode; + + dev_dbg(dev, "\n[%s %d]: addr=0x%llx opcode=0x%x\n", __func__,__LINE__, + priv->addr, priv->opcode); + + if ( priv->opcode == SPINOR_OP_WREN + || priv->opcode == SPINOR_OP_WRDI) + return 0; + + switch(priv->opcode) { + case SPINOR_OP_RDID: + case SPINOR_OP_RDSFDP: + priv->cmd_type = SPIC_CMD_TYPE_READ_JEDEC_ID; + break; + case SPINOR_OP_BE_4K: + case SPINOR_OP_BE_4K_PMC: + priv->opcode = SPINOR_OP_BE_4K; + priv->cmd_type = SPIC_CMD_TYPE_SECTOR_ERASE; + break; + case SPINOR_OP_BE_32K: + priv->cmd_type = SPIC_CMD_TYPE_BLOCK_ERASE_TYPE1; + break; + case SPINOR_OP_SE: + priv->cmd_type = SPIC_CMD_TYPE_BLOCK_ERASE_TYPE2; + break; + case SPINOR_OP_CHIP_ERASE: + priv->cmd_type = SPIC_CMD_TYPE_CHIP_ERASE; + break; + case SPINOR_OP_PP: + case SPINOR_OP_PP_1_1_4: + case SPINOR_OP_PP_1_4_4: + case SPINOR_OP_PP_1_1_8: + case SPINOR_OP_PP_1_8_8: + priv->opcode = SPINOR_OP_PP; + priv->cmd_type = SPIC_CMD_TYPE_SPI_PROGRAM; + break; + case SPINOR_OP_READ: + case SPINOR_OP_READ_FAST: + case SPINOR_OP_READ_1_1_2: + case SPINOR_OP_READ_1_2_2: + case SPINOR_OP_READ_1_1_4: + case SPINOR_OP_READ_1_4_4: + case SPINOR_OP_READ_1_1_8: + case SPINOR_OP_READ_1_8_8: + priv->opcode = SPINOR_OP_READ; + priv->cmd_type = SPIC_CMD_TYPE_READ_DATA; + break; + case SPINOR_OP_RDSR: + case SPINOR_OP_RDSR2: + priv->cmd_type = SPIC_CMD_TYPE_READ_STATUS_REGISTER; + break; + case SPINOR_OP_WRSR: + case SPINOR_OP_WRSR2: + priv->cmd_type = SPIC_CMD_TYPE_WRITE_STATUS_REGISTER; + break; + case SPIC_CMD_CODE_POWER_DOWN: + priv->cmd_type = SPIC_CMD_TYPE_POWER_DOWN; + break; + case SPIC_CMD_CODE_RELEASE_POWER_DOWN: + priv->cmd_type = SPIC_CMD_TYPE_RELEASE_POWER_DOWM; + break; + case SPIC_CMD_CODE_ENABLE_RESET: + case SPIC_CMD_CODE_RESET: + priv->cmd_type = SPIC_CMD_TYPE_SPI_PROGRAM; + break; + default: + dev_warn(dev, "[%s %d]: unsupport opcode = 0x%x, return sucess directly!\n", + __func__,__LINE__, priv->opcode); + return 0; + } + + dev_dbg(dev, "[%s %d]: data direction=%d, opcode = 0x%x, cmd_type 0x%x\n", + __func__,__LINE__, op->data.dir, priv->opcode, priv->cmd_type); + external_cs_manage(priv, false); + + if (read) { + priv->rx = op->data.buf.in; + priv->len = op->data.nbytes; + dev_dbg(dev, "[%s %d]: read len = %u\n", __func__,__LINE__, op->data.nbytes); + eswin_bootspi_reader(priv); + } else { + priv->tx = op->data.buf.out; + priv->len = op->data.nbytes; + /* Fill up the write fifo before starting the transfer */ + dev_dbg(dev, "[%s %d]: write len = 0x%x tx_addr 0x%px\n", __func__,__LINE__, + op->data.nbytes, priv->tx); + eswin_bootspi_writer(priv); + if (eswin_bootspi_wait_over(priv) < 0) { + dev_err(dev, "eswin_bootspi_wait_over ETIMEDOUT\n"); + ret = -ETIMEDOUT; + } + } + external_cs_manage(priv, true); + dev_dbg(dev, "%u bytes xfered\n", op->data.nbytes); + return ret; +} + +static const struct spi_controller_mem_ops eswin_bootspi_mem_ops = { + .adjust_op_size = eswin_bootspi_adjust_op_size, + .supports_op = eswin_bootspi_supports_op, + .exec_op = eswin_bootspi_exec_op, +}; + +static int eswin_bootspi_setup(struct spi_device *spi) +{ + struct es_spi_priv *priv = spi_master_get_devdata(spi->master); + struct device *dev = priv->dev; + int vaule = 0; + int ret; + + ret = clk_prepare_enable(priv->cfg_clk); + if (ret) { + dev_err(dev, "could not enable cfg clock: %d\n", ret); + goto err_cfg_clk; + } + + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(dev, "could not enable clock: %d\n", ret); + goto err_clk; + } + /* set rate to 50M*/ + ret = clk_set_rate(priv->clk, 50000000); + if (ret) { + dev_err(dev, "could not enable clock: %d\n", ret); + goto err_clk; + } + + reset_control_deassert(priv->rstc); + + /* switch bootspi to cpu mode*/ + vaule = readl(priv->sys_regs + ES_SYSCSR_SPIMODECFG); + vaule |= 0x1; + writel(vaule, priv->sys_regs + ES_SYSCSR_SPIMODECFG); + + /* Basic HW init */ + eswin_bootspi_write(priv, ES_SPI_CSR_08, 0x0); + return ret; + +err_clk: + clk_disable(priv->cfg_clk); +err_cfg_clk: + return ret; +} + +static int eswin_bootspi_probe(struct platform_device *pdev) +{ + struct es_spi_priv *priv; + struct spi_controller *master; + int ret = 0; + struct device *dev = &pdev->dev; + + master = spi_alloc_master(&pdev->dev, sizeof(*priv)); + if (!master) + return -ENOMEM; + + master->mode_bits = SPI_CPOL | SPI_CPHA; + master->flags = SPI_MASTER_HALF_DUPLEX; + master->setup = eswin_bootspi_setup; + master->dev.of_node = pdev->dev.of_node; + master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) | + SPI_BPW_MASK(8); + master->mem_ops = &eswin_bootspi_mem_ops; + master->num_chipselect = 1; + + priv = spi_master_get_devdata(master); + priv->master = master; + priv->dev = &pdev->dev; + platform_set_drvdata(pdev, priv); + + priv->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->regs)) { + dev_err(dev, "%s %d: failed to map registers\n", __func__,__LINE__); + return PTR_ERR(priv->regs); + } + + priv->sys_regs = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(priv->sys_regs)) { + dev_err(dev,"%s %d: failed to map sys registers\n", __func__, __LINE__); + return PTR_ERR(priv->sys_regs); + } + + priv->flash_base = devm_platform_ioremap_resource(pdev, 2); + if (IS_ERR(priv->flash_base)) { + dev_err(dev,"%s %d: failed to map sys registers\n", __func__, __LINE__); + return PTR_ERR(priv->flash_base); + } + + priv->cfg_clk = devm_clk_get(dev, "cfg_clk"); + if (IS_ERR(priv->cfg_clk)) { + dev_err(dev, "%s %d:could not get cfg clk: %ld\n", __func__,__LINE__, + PTR_ERR(priv->cfg_clk)); + return PTR_ERR(priv->cfg_clk); + } + + priv->clk = devm_clk_get(dev, "clk"); + if (IS_ERR(priv->clk)) { + dev_err(dev, "%s %d:could not get clk: %ld\n",__func__,__LINE__, PTR_ERR(priv->rstc)); + return PTR_ERR(priv->clk); + } + priv->rstc = devm_reset_control_get_optional_exclusive(dev, "rst"); + if (IS_ERR(priv->rstc)) { + dev_err(dev, "%s %d:could not get rst: %ld\n", __func__,__LINE__, PTR_ERR(priv->rstc)); + return PTR_ERR(priv->rstc); + } + + priv->cs_gpio = devm_gpiod_get(dev, "cs", GPIOD_OUT_LOW); + if (IS_ERR(priv->cs_gpio)) { + dev_err(dev, "%s %d: couldn't request gpio! (error %ld)\n", __func__,__LINE__, + PTR_ERR(priv->cs_gpio)); + return PTR_ERR(priv->cs_gpio); + } + + priv->max_xfer = 32; + dev_info(dev, "ssi_max_xfer_size=%u\n", priv->max_xfer); + + /* Currently only bits_per_word == 8 supported */ + priv->bits_per_word = 8; + priv->tmode = 0; /* Tx & Rx */ + + if (!priv->fifo_len) { + priv->fifo_len = 256; + } + ret = devm_spi_register_controller(dev, master); + if (ret) + goto err_put_master; + + dev_info(&pdev->dev, "fifo_len %d, %s mode.\n", priv->fifo_len, priv->irq ? "irq" : "polling"); + return 0; + +err_put_master: + spi_master_put(master); + return ret; +} + +static int eswin_bootspi_remove(struct platform_device *pdev) +{ + struct es_spi_priv *priv = platform_get_drvdata(pdev); + struct spi_controller *master = priv->master; + + spi_master_put(master); + return 0; +} + +static const struct of_device_id eswin_bootspi_of_match[] = { + { .compatible = "eswin,bootspi", .data = NULL}, + { /* end of table */} +}; +MODULE_DEVICE_TABLE(of, eswin_bootspi_of_match); + +#ifdef CONFIG_ACPI +static const struct acpi_device_id eswin_bootspi_acpi_match[] = { + {"eswin,bootspi", 0}, + {} +}; +MODULE_DEVICE_TABLE(acpi, eswin_bootspi_acpi_match); +#endif + +static struct platform_driver eswin_bootspi_driver = { + .probe = eswin_bootspi_probe, + .remove = eswin_bootspi_remove, + .driver = { + .name = "eswin-bootspi", + .of_match_table = eswin_bootspi_of_match, +#ifdef CONFIG_ACPI + .acpi_match_table = eswin_bootspi_acpi_match, +#endif + }, +}; +module_platform_driver(eswin_bootspi_driver); + +MODULE_AUTHOR("Huangyifeng "); +MODULE_DESCRIPTION("Eswin Boot SPI Controller Driver for EIC770X SoCs"); +MODULE_LICENSE("GPL v2"); From eab052fe39d88ac7b01b84a7bca9bc1d581d78ae Mon Sep 17 00:00:00 2001 From: Eric Lin Date: Tue, 16 Jul 2024 10:32:03 +0000 Subject: [PATCH 29/38] perf vendor events riscv: Add SiFive P550 events The SiFive Performance P550 core features an out-of-order microarchitecture which exposes the same PMU events as Bullet, plus events for UTLB hits and PTE cache misses/hits. Signed-off-by: Eric Lin Co-developed-by: Samuel Holland Signed-off-by: Samuel Holland --- tools/perf/pmu-events/arch/riscv/mapfile.csv | 1 + .../p550/cycle-and-instruction-count.json | 12 +++ .../arch/riscv/sifive/p550/firmware.json | 68 ++++++++++++++ .../arch/riscv/sifive/p550/instruction.json | 92 +++++++++++++++++++ .../arch/riscv/sifive/p550/memory.json | 47 ++++++++++ .../arch/riscv/sifive/p550/microarch.json | 57 ++++++++++++ 6 files changed, 277 insertions(+) create mode 100644 tools/perf/pmu-events/arch/riscv/sifive/p550/cycle-and-instruction-count.json create mode 100644 tools/perf/pmu-events/arch/riscv/sifive/p550/firmware.json create mode 100644 tools/perf/pmu-events/arch/riscv/sifive/p550/instruction.json create mode 100644 tools/perf/pmu-events/arch/riscv/sifive/p550/memory.json create mode 100644 tools/perf/pmu-events/arch/riscv/sifive/p550/microarch.json diff --git a/tools/perf/pmu-events/arch/riscv/mapfile.csv b/tools/perf/pmu-events/arch/riscv/mapfile.csv index c61b3d6ef6166..6328fd3f45ee3 100644 --- a/tools/perf/pmu-events/arch/riscv/mapfile.csv +++ b/tools/perf/pmu-events/arch/riscv/mapfile.csv @@ -15,3 +15,4 @@ # #MVENDORID-MARCHID-MIMPID,Version,Filename,EventType 0x489-0x8000000000000007-0x[[:xdigit:]]+,v1,sifive/u74,core +0x489-0x8000000000000008-0x[[:xdigit:]]+,v1,sifive/p550,core diff --git a/tools/perf/pmu-events/arch/riscv/sifive/p550/cycle-and-instruction-count.json b/tools/perf/pmu-events/arch/riscv/sifive/p550/cycle-and-instruction-count.json new file mode 100644 index 0000000000000..b530032994d9e --- /dev/null +++ b/tools/perf/pmu-events/arch/riscv/sifive/p550/cycle-and-instruction-count.json @@ -0,0 +1,12 @@ +[ + { + "EventName": "CORE_CLOCK_CYCLES", + "EventCode": "0x165", + "BriefDescription": "Counts core clock cycles" + }, + { + "EventName": "INSTRUCTIONS_RETIRED", + "EventCode": "0x265", + "BriefDescription": "Counts instructions retired" + } +] diff --git a/tools/perf/pmu-events/arch/riscv/sifive/p550/firmware.json b/tools/perf/pmu-events/arch/riscv/sifive/p550/firmware.json new file mode 100644 index 0000000000000..9b4a032186a7b --- /dev/null +++ b/tools/perf/pmu-events/arch/riscv/sifive/p550/firmware.json @@ -0,0 +1,68 @@ +[ + { + "ArchStdEvent": "FW_MISALIGNED_LOAD" + }, + { + "ArchStdEvent": "FW_MISALIGNED_STORE" + }, + { + "ArchStdEvent": "FW_ACCESS_LOAD" + }, + { + "ArchStdEvent": "FW_ACCESS_STORE" + }, + { + "ArchStdEvent": "FW_ILLEGAL_INSN" + }, + { + "ArchStdEvent": "FW_SET_TIMER" + }, + { + "ArchStdEvent": "FW_IPI_SENT" + }, + { + "ArchStdEvent": "FW_IPI_RECEIVED" + }, + { + "ArchStdEvent": "FW_FENCE_I_SENT" + }, + { + "ArchStdEvent": "FW_FENCE_I_RECEIVED" + }, + { + "ArchStdEvent": "FW_SFENCE_VMA_SENT" + }, + { + "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED" + }, + { + "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED" + }, + { + "ArchStdEvent": "FW_SFENCE_VMA_ASID_RECEIVED" + }, + { + "ArchStdEvent": "FW_HFENCE_GVMA_SENT" + }, + { + "ArchStdEvent": "FW_HFENCE_GVMA_RECEIVED" + }, + { + "ArchStdEvent": "FW_HFENCE_GVMA_VMID_SENT" + }, + { + "ArchStdEvent": "FW_HFENCE_GVMA_VMID_RECEIVED" + }, + { + "ArchStdEvent": "FW_HFENCE_VVMA_SENT" + }, + { + "ArchStdEvent": "FW_HFENCE_VVMA_RECEIVED" + }, + { + "ArchStdEvent": "FW_HFENCE_VVMA_ASID_SENT" + }, + { + "ArchStdEvent": "FW_HFENCE_VVMA_ASID_RECEIVED" + } +] diff --git a/tools/perf/pmu-events/arch/riscv/sifive/p550/instruction.json b/tools/perf/pmu-events/arch/riscv/sifive/p550/instruction.json new file mode 100644 index 0000000000000..284e4c1566e03 --- /dev/null +++ b/tools/perf/pmu-events/arch/riscv/sifive/p550/instruction.json @@ -0,0 +1,92 @@ +[ + { + "EventName": "EXCEPTION_TAKEN", + "EventCode": "0x100", + "BriefDescription": "Counts exceptions taken" + }, + { + "EventName": "INTEGER_LOAD_RETIRED", + "EventCode": "0x200", + "BriefDescription": "Counts integer load instructions retired" + }, + { + "EventName": "INTEGER_STORE_RETIRED", + "EventCode": "0x400", + "BriefDescription": "Counts integer store instructions retired" + }, + { + "EventName": "ATOMIC_MEMORY_RETIRED", + "EventCode": "0x800", + "BriefDescription": "Counts atomic memory instructions retired" + }, + { + "EventName": "SYSTEM_INSTRUCTION_RETIRED", + "EventCode": "0x1000", + "BriefDescription": "Counts system instructions retired (CSR, WFI, MRET, etc.)" + }, + { + "EventName": "INTEGER_ARITHMETIC_RETIRED", + "EventCode": "0x2000", + "BriefDescription": "Counts integer arithmetic instructions retired" + }, + { + "EventName": "CONDITIONAL_BRANCH_RETIRED", + "EventCode": "0x4000", + "BriefDescription": "Counts conditional branch instructions retired" + }, + { + "EventName": "JAL_INSTRUCTION_RETIRED", + "EventCode": "0x8000", + "BriefDescription": "Counts jump-and-link instructions retired" + }, + { + "EventName": "JALR_INSTRUCTION_RETIRED", + "EventCode": "0x10000", + "BriefDescription": "Counts indirect jump instructions (JALR) retired" + }, + { + "EventName": "INTEGER_MULTIPLICATION_RETIRED", + "EventCode": "0x20000", + "BriefDescription": "Counts integer multiplication instructions retired" + }, + { + "EventName": "INTEGER_DIVISION_RETIRED", + "EventCode": "0x40000", + "BriefDescription": "Counts integer division instructions retired" + }, + { + "EventName": "FP_LOAD_RETIRED", + "EventCode": "0x80000", + "BriefDescription": "Counts floating-point load instructions retired" + }, + { + "EventName": "FP_STORE_RETIRED", + "EventCode": "0x100000", + "BriefDescription": "Counts floating-point store instructions retired" + }, + { + "EventName": "FP_ADD_RETIRED", + "EventCode": "0x200000", + "BriefDescription": "Counts floating-point add instructions retired" + }, + { + "EventName": "FP_MUL_RETIRED", + "EventCode": "0x400000", + "BriefDescription": "Counts floating-point multiply instructions retired" + }, + { + "EventName": "FP_MULADD_RETIRED", + "EventCode": "0x800000", + "BriefDescription": "Counts floating-point fused multiply-add instructions retired" + }, + { + "EventName": "FP_DIV_SQRT_RETIRED", + "EventCode": "0x1000000", + "BriefDescription": "Counts floating point divide or square root instructions retired" + }, + { + "EventName": "OTHER_FP_RETIRED", + "EventCode": "0x2000000", + "BriefDescription": "Counts other floating-point instructions retired" + } +] diff --git a/tools/perf/pmu-events/arch/riscv/sifive/p550/memory.json b/tools/perf/pmu-events/arch/riscv/sifive/p550/memory.json new file mode 100644 index 0000000000000..9351c9074ed70 --- /dev/null +++ b/tools/perf/pmu-events/arch/riscv/sifive/p550/memory.json @@ -0,0 +1,47 @@ +[ + { + "EventName": "ICACHE_MISS", + "EventCode": "0x102", + "BriefDescription": "Counts instruction cache misses" + }, + { + "EventName": "DCACHE_MISS", + "EventCode": "0x202", + "BriefDescription": "Counts data cache misses" + }, + { + "EventName": "DCACHE_RELEASE", + "EventCode": "0x402", + "BriefDescription": "Counts writeback requests from the data cache" + }, + { + "EventName": "ITLB_MISS", + "EventCode": "0x802", + "BriefDescription": "Counts Instruction TLB misses caused by instruction address translation requests" + }, + { + "EventName": "DTLB_MISS", + "EventCode": "0x1002", + "BriefDescription": "Counts Data TLB misses caused by data address translation requests" + }, + { + "EventName": "UTLB_MISS", + "EventCode": "0x2002", + "BriefDescription": "Counts Unified TLB misses caused by address translation requests" + }, + { + "EventName": "UTLB_HIT", + "EventCode": "0x4002", + "BriefDescription": "Counts Unified TLB hits for address translation requests" + }, + { + "EventName": "PTE_CACHE_MISS", + "EventCode": "0x8002", + "BriefDescription": "Counts Page Table Entry cache misses" + }, + { + "EventName": "PTE_CACHE_HIT", + "EventCode": "0x10002", + "BriefDescription": "Counts Page Table Entry cache hits" + } +] diff --git a/tools/perf/pmu-events/arch/riscv/sifive/p550/microarch.json b/tools/perf/pmu-events/arch/riscv/sifive/p550/microarch.json new file mode 100644 index 0000000000000..d9cdb7d747eed --- /dev/null +++ b/tools/perf/pmu-events/arch/riscv/sifive/p550/microarch.json @@ -0,0 +1,57 @@ +[ + { + "EventName": "ADDRESSGEN_INTERLOCK", + "EventCode": "0x101", + "BriefDescription": "Counts cycles with an address-generation interlock" + }, + { + "EventName": "LONGLATENCY_INTERLOCK", + "EventCode": "0x201", + "BriefDescription": "Counts cycles with a long-latency interlock" + }, + { + "EventName": "CSR_INTERLOCK", + "EventCode": "0x401", + "BriefDescription": "Counts cycles with a CSR interlock" + }, + { + "EventName": "ICACHE_BLOCKED", + "EventCode": "0x801", + "BriefDescription": "Counts cycles in which the instruction cache was not able to provide an instruction" + }, + { + "EventName": "DCACHE_BLOCKED", + "EventCode": "0x1001", + "BriefDescription": "Counts cycles in which the data cache blocked an instruction" + }, + { + "EventName": "BRANCH_DIRECTION_MISPREDICTION", + "EventCode": "0x2001", + "BriefDescription": "Counts mispredictions of conditional branch direction (taken/not taken)" + }, + { + "EventName": "BRANCH_TARGET_MISPREDICTION", + "EventCode": "0x4001", + "BriefDescription": "Counts mispredictions of the target PC of control-flow instructions" + }, + { + "EventName": "PIPELINE_FLUSH", + "EventCode": "0x8001", + "BriefDescription": "Counts flushes of the core pipeline. Common causes include fence.i and CSR accesses" + }, + { + "EventName": "REPLAY", + "EventCode": "0x10001", + "BriefDescription": "Counts instruction replays" + }, + { + "EventName": "INTEGER_MUL_DIV_INTERLOCK", + "EventCode": "0x20001", + "BriefDescription": "Counts cycles with a multiply or divide interlock" + }, + { + "EventName": "FP_INTERLOCK", + "EventCode": "0x40001", + "BriefDescription": "Counts cycles with a floating-point interlock" + } +] From a5f7868dffdc1560fe9d2b4de8eee88fab4cb461 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Wed, 31 Jul 2024 03:52:40 +0000 Subject: [PATCH 30/38] ttm: disallow cached mapping Signed-off-by: Icenowy Zheng --- drivers/gpu/drm/drm_gem_vram_helper.c | 4 ++++ drivers/gpu/drm/ttm/ttm_bo_util.c | 7 +++++++ drivers/gpu/drm/ttm/ttm_module.c | 3 ++- drivers/gpu/drm/ttm/ttm_resource.c | 12 +++++++++++- drivers/gpu/drm/ttm/ttm_tt.c | 4 ++++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index b67eafa557159..aaf97dde9b731 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -870,7 +870,11 @@ static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo, if (!tt) return NULL; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + ret = ttm_tt_init(tt, bo, page_flags, ttm_write_combined, 0); +#else ret = ttm_tt_init(tt, bo, page_flags, ttm_cached, 0); +#endif if (ret < 0) goto err_ttm_tt_init; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index fd9fd3d15101c..9c2ba0a430aa9 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -346,6 +346,7 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, if (ret) return ret; +#ifndef CONFIG_SOC_SIFIVE_EIC7700 if (num_pages == 1 && ttm->caching == ttm_cached) { /* * We're mapping a single page, and the desired @@ -365,6 +366,12 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, map->virtual = vmap(ttm->pages + start_page, num_pages, 0, prot); } +#else + prot = ttm_io_prot(bo, mem, PAGE_KERNEL); + map->bo_kmap_type = ttm_bo_map_vmap; + map->virtual = vmap(ttm->pages + start_page, num_pages, + 0, prot); +#endif return (!map->virtual) ? -ENOMEM : 0; } diff --git a/drivers/gpu/drm/ttm/ttm_module.c b/drivers/gpu/drm/ttm/ttm_module.c index b3fffe7b5062a..aa137ead5cc59 100644 --- a/drivers/gpu/drm/ttm/ttm_module.c +++ b/drivers/gpu/drm/ttm/ttm_module.c @@ -74,7 +74,8 @@ pgprot_t ttm_prot_from_caching(enum ttm_caching caching, pgprot_t tmp) #endif /* CONFIG_UML */ #endif /* __i386__ || __x86_64__ */ #if defined(__ia64__) || defined(__arm__) || defined(__aarch64__) || \ - defined(__powerpc__) || defined(__mips__) || defined(__loongarch__) + defined(__powerpc__) || defined(__mips__) || defined(__loongarch__) || \ + defined(__riscv) if (caching == ttm_write_combined) tmp = pgprot_writecombine(tmp); else diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 46ff9c75bb124..7b097ccb51427 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -187,7 +187,11 @@ void ttm_resource_init(struct ttm_buffer_object *bo, res->bus.addr = NULL; res->bus.offset = 0; res->bus.is_iomem = false; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + res->bus.caching = ttm_write_combined; +#else res->bus.caching = ttm_cached; +#endif res->bo = bo; man = ttm_manager_type(bo->bdev, place->mem_type); @@ -670,6 +674,7 @@ ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io, } else { iter_io->needs_unmap = true; memset(&iter_io->dmap, 0, sizeof(iter_io->dmap)); +#ifndef CONFIG_SOC_SIFIVE_EIC7700 if (mem->bus.caching == ttm_write_combined) iosys_map_set_vaddr_iomem(&iter_io->dmap, ioremap_wc(mem->bus.offset, @@ -680,7 +685,12 @@ ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io, MEMREMAP_WB | MEMREMAP_WT | MEMREMAP_WC)); - +#else + if (mem->bus.caching == ttm_write_combined || mem->bus.caching == ttm_cached) + iosys_map_set_vaddr_iomem(&iter_io->dmap, + ioremap_wc(mem->bus.offset, + mem->size)); +#endif /* If uncached requested or if mapping cached or wc failed */ if (iosys_map_is_null(&iter_io->dmap)) iosys_map_set_vaddr_iomem(&iter_io->dmap, diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index e0a77671edd6c..ad1a7eefe7505 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -141,7 +141,11 @@ static void ttm_tt_init_fields(struct ttm_tt *ttm, ttm->dma_address = NULL; ttm->swap_storage = NULL; ttm->sg = bo->sg; +#ifdef CONFIG_SOC_SIFIVE_EIC7700 + ttm->caching = ttm_write_combined; +#else ttm->caching = caching; +#endif } int ttm_tt_init(struct ttm_tt *ttm, struct ttm_buffer_object *bo, From 71892b48832ed234d8999b8798b0874965a863f9 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Fri, 22 Jul 2022 18:54:54 +0530 Subject: [PATCH 31/38] RISC-V: Add defines for SBI debug console extension We add SBI debug console extension related defines/enum to the asm/sbi.h header. Signed-off-by: Anup Patel Reviewed-by: Andrew Jones Signed-off-by: Anup Patel --- arch/riscv/include/asm/sbi.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index b79d0228144f4..0892f4421bc4a 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -30,6 +30,7 @@ enum sbi_ext_id { SBI_EXT_HSM = 0x48534D, SBI_EXT_SRST = 0x53525354, SBI_EXT_PMU = 0x504D55, + SBI_EXT_DBCN = 0x4442434E, /* Experimentals extensions must lie within this range */ SBI_EXT_EXPERIMENTAL_START = 0x08000000, @@ -236,6 +237,12 @@ enum sbi_pmu_ctr_type { /* Flags defined for counter stop function */ #define SBI_PMU_STOP_FLAG_RESET (1 << 0) +enum sbi_ext_dbcn_fid { + SBI_EXT_DBCN_CONSOLE_WRITE = 0, + SBI_EXT_DBCN_CONSOLE_READ = 1, + SBI_EXT_DBCN_CONSOLE_WRITE_BYTE = 2, +}; + #define SBI_SPEC_VERSION_DEFAULT 0x1 #define SBI_SPEC_VERSION_MAJOR_SHIFT 24 #define SBI_SPEC_VERSION_MAJOR_MASK 0x7f From 98380b2bcdb13cea99195f990bd999f87e133f5a Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Fri, 24 Nov 2023 12:39:02 +0530 Subject: [PATCH 32/38] RISC-V: Add SBI debug console helper routines Let us provide SBI debug console helper routines which can be shared by serial/earlycon-riscv-sbi.c and hvc/hvc_riscv_sbi.c. Signed-off-by: Anup Patel Reviewed-by: Andrew Jones Link: https://lore.kernel.org/r/20231124070905.1043092-3-apatel@ventanamicro.com Signed-off-by: Palmer Dabbelt --- arch/riscv/include/asm/sbi.h | 5 +++ arch/riscv/kernel/sbi.c | 66 ++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index 0892f4421bc4a..acbe0a700745f 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -329,6 +329,11 @@ static inline unsigned long sbi_mk_version(unsigned long major, } int sbi_err_map_linux_errno(int err); + +extern bool sbi_debug_console_available; +int sbi_debug_console_write(const char *bytes, unsigned int num_bytes); +int sbi_debug_console_read(char *bytes, unsigned int num_bytes); + #else /* CONFIG_RISCV_SBI */ static inline int sbi_remote_fence_i(const struct cpumask *cpu_mask) { return -1; } static inline void sbi_init(void) {} diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c index 5a62ed1da4533..e66e0999a8005 100644 --- a/arch/riscv/kernel/sbi.c +++ b/arch/riscv/kernel/sbi.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -571,6 +572,66 @@ long sbi_get_mimpid(void) } EXPORT_SYMBOL_GPL(sbi_get_mimpid); +bool sbi_debug_console_available; + +int sbi_debug_console_write(const char *bytes, unsigned int num_bytes) +{ + phys_addr_t base_addr; + struct sbiret ret; + + if (!sbi_debug_console_available) + return -EOPNOTSUPP; + + if (is_vmalloc_addr(bytes)) + base_addr = page_to_phys(vmalloc_to_page(bytes)) + + offset_in_page(bytes); + else + base_addr = __pa(bytes); + if (PAGE_SIZE < (offset_in_page(bytes) + num_bytes)) + num_bytes = PAGE_SIZE - offset_in_page(bytes); + + if (IS_ENABLED(CONFIG_32BIT)) + ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE, + num_bytes, lower_32_bits(base_addr), + upper_32_bits(base_addr), 0, 0, 0); + else + ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE, + num_bytes, base_addr, 0, 0, 0, 0); + + if (ret.error == SBI_ERR_FAILURE) + return -EIO; + return ret.error ? sbi_err_map_linux_errno(ret.error) : ret.value; +} + +int sbi_debug_console_read(char *bytes, unsigned int num_bytes) +{ + phys_addr_t base_addr; + struct sbiret ret; + + if (!sbi_debug_console_available) + return -EOPNOTSUPP; + + if (is_vmalloc_addr(bytes)) + base_addr = page_to_phys(vmalloc_to_page(bytes)) + + offset_in_page(bytes); + else + base_addr = __pa(bytes); + if (PAGE_SIZE < (offset_in_page(bytes) + num_bytes)) + num_bytes = PAGE_SIZE - offset_in_page(bytes); + + if (IS_ENABLED(CONFIG_32BIT)) + ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ, + num_bytes, lower_32_bits(base_addr), + upper_32_bits(base_addr), 0, 0, 0); + else + ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ, + num_bytes, base_addr, 0, 0, 0, 0); + + if (ret.error == SBI_ERR_FAILURE) + return -EIO; + return ret.error ? sbi_err_map_linux_errno(ret.error) : ret.value; +} + void __init sbi_init(void) { int ret; @@ -612,6 +673,11 @@ void __init sbi_init(void) sbi_srst_reboot_nb.priority = 192; register_restart_handler(&sbi_srst_reboot_nb); } + if ((sbi_spec_version >= sbi_mk_version(2, 0)) && + (sbi_probe_extension(SBI_EXT_DBCN) > 0)) { + pr_info("SBI DBCN extension detected\n"); + sbi_debug_console_available = true; + } } else { __sbi_set_timer = __sbi_set_timer_v01; __sbi_send_ipi = __sbi_send_ipi_v01; From db4aa2a514664b5668c74e6897e33481d645f615 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Fri, 24 Nov 2023 12:39:03 +0530 Subject: [PATCH 33/38] tty/serial: Add RISC-V SBI debug console based earlycon We extend the existing RISC-V SBI earlycon support to use the new RISC-V SBI debug console extension. Signed-off-by: Anup Patel Reviewed-by: Andrew Jones Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20231124070905.1043092-4-apatel@ventanamicro.com Signed-off-by: Palmer Dabbelt --- drivers/tty/serial/Kconfig | 2 +- drivers/tty/serial/earlycon-riscv-sbi.c | 27 ++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index bdc568a4ab669..cec46091a7163 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -87,7 +87,7 @@ config SERIAL_EARLYCON_SEMIHOST config SERIAL_EARLYCON_RISCV_SBI bool "Early console using RISC-V SBI" - depends on RISCV_SBI_V01 + depends on RISCV_SBI select SERIAL_CORE select SERIAL_CORE_CONSOLE select SERIAL_EARLYCON diff --git a/drivers/tty/serial/earlycon-riscv-sbi.c b/drivers/tty/serial/earlycon-riscv-sbi.c index 27afb0b74ea70..0162155f0c839 100644 --- a/drivers/tty/serial/earlycon-riscv-sbi.c +++ b/drivers/tty/serial/earlycon-riscv-sbi.c @@ -15,17 +15,38 @@ static void sbi_putc(struct uart_port *port, unsigned char c) sbi_console_putchar(c); } -static void sbi_console_write(struct console *con, - const char *s, unsigned n) +static void sbi_0_1_console_write(struct console *con, + const char *s, unsigned int n) { struct earlycon_device *dev = con->data; uart_console_write(&dev->port, s, n, sbi_putc); } +static void sbi_dbcn_console_write(struct console *con, + const char *s, unsigned int n) +{ + int ret; + + while (n) { + ret = sbi_debug_console_write(s, n); + if (ret < 0) + break; + + s += ret; + n -= ret; + } +} + static int __init early_sbi_setup(struct earlycon_device *device, const char *opt) { - device->con->write = sbi_console_write; + if (sbi_debug_console_available) + device->con->write = sbi_dbcn_console_write; + else if (IS_ENABLED(CONFIG_RISCV_SBI_V01)) + device->con->write = sbi_0_1_console_write; + else + return -ENODEV; + return 0; } EARLYCON_DECLARE(sbi, early_sbi_setup); From 8a7e461fd5b37d2793831fe5bcfb4bf8e34251b6 Mon Sep 17 00:00:00 2001 From: Pritesh Patel Date: Tue, 13 Aug 2024 14:38:08 +0000 Subject: [PATCH 34/38] hifive-premier-p550: add defconfig Signed-off-by: Pritesh Patel --- .../configs/hifive-premier-p550_defconfig | 413 ++++++++++++++++++ 1 file changed, 413 insertions(+) create mode 100644 arch/riscv/configs/hifive-premier-p550_defconfig diff --git a/arch/riscv/configs/hifive-premier-p550_defconfig b/arch/riscv/configs/hifive-premier-p550_defconfig new file mode 100644 index 0000000000000..7e99e46146ad0 --- /dev/null +++ b/arch/riscv/configs/hifive-premier-p550_defconfig @@ -0,0 +1,413 @@ +CONFIG_SYSVIPC=y +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BPF_SYSCALL=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_BPF=y +CONFIG_NAMESPACES=y +CONFIG_USER_NS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_EXPERT=y +# CONFIG_SYSFS_SYSCALL is not set +CONFIG_PERF_EVENTS=y +CONFIG_SOC_SIFIVE_EIC7700=y +CONFIG_SOC_SIFIVE=y +CONFIG_SOC_VIRT=y +CONFIG_SMP=y +# CONFIG_RISCV_BOOT_SPINWAIT is not set +CONFIG_CMDLINE="earlycon=sbi console=ttyS0,115200n8 clk_ignore_unused cma_pernuma=0x2000000 disable_bypass=false" +CONFIG_CMDLINE_EXTEND=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPUFREQ_DT=y +CONFIG_VIRTUALIZATION=y +CONFIG_KVM=y +CONFIG_JUMP_LABEL=y +# CONFIG_GCC_PLUGINS is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_CMA=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_SCHED=y +CONFIG_NET_CLS_ACT=y +CONFIG_CFG80211=m +CONFIG_NL80211_TESTMODE=y +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +CONFIG_CFG80211_CERTIFICATION_ONUS=y +CONFIG_CFG80211_REG_CELLULAR_HINTS=y +CONFIG_CFG80211_REG_RELAX_NO_IR=y +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_DEBUGFS=y +CONFIG_MAC80211_MESSAGE_TRACING=y +CONFIG_MAC80211_DEBUG_MENU=y +CONFIG_PCI=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM_PERFORMANCE=y +CONFIG_PCIE_PTM=y +# CONFIG_PCI_QUIRKS is not set +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y +CONFIG_PCIE_ESWIN=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_MTD=y +CONFIG_MTD_SPI_NOR=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=2 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_VIRTIO_BLK=y +CONFIG_BLK_DEV_NVME=y +CONFIG_NVME_MULTIPATH=y +CONFIG_EEPROM_AT24=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +CONFIG_SATA_AHCI=y +CONFIG_AHCI_ESWIN=y +CONFIG_NETDEVICES=y +CONFIG_VIRTIO_NET=y +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ASIX is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_ENGLEDER is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_LITEX is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_MICROSOFT is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +CONFIG_STMMAC_ETH=y +# CONFIG_DWMAC_GENERIC is not set +CONFIG_DWMAC_EIC7700=y +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VERTEXCOM is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_RTW88=m +CONFIG_RTW88_8822BU=m +CONFIG_RTW88_DEBUG=y +CONFIG_RTW88_DEBUGFS=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_EARLYCON_RISCV_SBI=y +CONFIG_HVC_RISCV_SBI=y +CONFIG_VIRTIO_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_VIRTIO=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_DESIGNWARE_SLAVE=y +CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_I2C_SLAVE_EEPROM=y +CONFIG_SPI=y +CONFIG_SPI_DESIGNWARE=y +CONFIG_SPI_DW_DMA=y +CONFIG_SPI_DW_MMIO=y +CONFIG_SPI_ESWIN_BOOTSPI=y +# CONFIG_PTP_1588_CLOCK is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_EIC7700=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_DWAPB=y +CONFIG_SENSORS_ESWIN_FAN_CONTROL=y +CONFIG_SENSORS_ESWIN_PVT=y +CONFIG_SENSORS_PAC1934=y +CONFIG_PMBUS=y +CONFIG_SENSORS_INA2XX=y +CONFIG_WATCHDOG=y +CONFIG_DW_WATCHDOG=y +CONFIG_REGULATOR=y +# CONFIG_MEDIA_CEC_SUPPORT is not set +CONFIG_MEDIA_SUPPORT=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_DRM=y +CONFIG_DRM_DEBUG_MM=y +CONFIG_DRM_I2C_NXP_TDA9950=y +CONFIG_DRM_RADEON=m +CONFIG_DRM_RADEON_USERPTR=y +CONFIG_DRM_AMDGPU=m +CONFIG_DRM_AST=y +CONFIG_DRM_DISPLAY_CONNECTOR=y +CONFIG_DRM_SIMPLE_BRIDGE=y +CONFIG_DRM_TOSHIBA_TC358768=m +CONFIG_DRM_LEGACY=y +CONFIG_FB=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SOC=y +CONFIG_SND_ESWIN_DW_I2S=y +CONFIG_ESWIN_SND_SOC_CODECS=y +CONFIG_ESWIN_SND_ES8388_CODEC=y +CONFIG_SND_AUDIO_GRAPH_CARD=y +CONFIG_USB_ULPI_BUS=y +CONFIG_USB_CONN_GPIO=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +# CONFIG_USB_DEFAULT_PERSIST is not set +CONFIG_USB_MON=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DBGCAP=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_ACM=y +CONFIG_USB_WDM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_UAS=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_ULPI=y +CONFIG_USB_DWC2=y +CONFIG_USB_SERIAL=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_CP210X=y +CONFIG_USB_SERIAL_FTDI_SIO=y +CONFIG_USB_SERIAL_KEYSPAN=y +CONFIG_USB_SERIAL_PL2303=y +CONFIG_USB_SERIAL_OTI6858=y +CONFIG_USB_SERIAL_QUALCOMM=y +CONFIG_USB_SERIAL_OPTION=y +CONFIG_USB_TEST=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_LB_SS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_ZERO=m +CONFIG_USB_G_NCM=y +CONFIG_USB_MASS_STORAGE=m +CONFIG_TYPEC=y +CONFIG_TYPEC_TCPM=y +CONFIG_TYPEC_TCPCI=y +CONFIG_TYPEC_FUSB303B=y +CONFIG_MMC=y +CONFIG_MMC_TEST=y +CONFIG_MMC_DEBUG=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_ESWIN=y +CONFIG_MMC_SDHCI_OF_SDIO_ESWIN=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_EDAC=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_ESWIN=y +CONFIG_RTC_DRV_PCF8563=y +CONFIG_DMADEVICES=y +CONFIG_DW_AXI_DMAC=y +CONFIG_DMATEST=y +CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DMABUF_HEAPS_CMA=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_INPUT=y +CONFIG_VIRTIO_MMIO=y +CONFIG_STAGING=y +CONFIG_COMMON_CLK_EIC7700=y +CONFIG_MAILBOX=y +CONFIG_IOMMU_ESWIN=y +CONFIG_ARM_SMMU_V3=y +CONFIG_RPMSG_VIRTIO=y +CONFIG_SIFIVE_CCACHE=y +CONFIG_EXTCON=y +CONFIG_EXTCON_USB_GPIO=y +CONFIG_MEMORY=y +CONFIG_PWM=y +CONFIG_PWM_ESWIN=y +CONFIG_RESET_ESWIN_EIC7700=y +CONFIG_INTERCONNECT=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_V4_1=y +CONFIG_NFS_V4_2=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_DEV_VIRTIO=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC7=y +CONFIG_XZ_DEC=y +CONFIG_DMA_CMA=y +CONFIG_PRINTK_TIME=y +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 +CONFIG_DEBUG_VM_PGFLAGS=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DEBUG_PER_CPU_MAPS=y +CONFIG_SOFTLOCKUP_DETECTOR=y +CONFIG_WQ_WATCHDOG=y +CONFIG_DEBUG_TIMEKEEPING=y +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_RWSEMS=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_DEBUG_LIST=y +CONFIG_DEBUG_PLIST=y +CONFIG_DEBUG_SG=y +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_EQS_DEBUG=y +# CONFIG_RUNTIME_TESTING_MENU is not set +CONFIG_MEMTEST=y +CONFIG_TRACEPOINTS=y +CONFIG_UPROBES=y +CONFIG_NOP_TRACER=y +CONFIG_TRACE_CLOCK=y +CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_TRACING=y +CONFIG_FTRACE=y +CONFIG_BRANCH_PROFILE_NONE=y +CONFIG_UPROBE_EVENTS=y +CONFIG_BPF_EVENTS=y +CONFIG_DYNAMIC_EVENTS=y +CONFIG_PROBE_EVENTS=y +CONFIG_RTW88_SDIO=m +CONFIG_RTW88_8822C=m +CONFIG_RTW88_8822CS=m + +# Ubuntu +CONFIG_CGROUP_HUGETLB=y +CONFIG_HUGETLBFS=y +CONFIG_SECURITY=y +CONFIG_DEFAULT_SECURITY_APPARMOR=y +CONFIG_SECURITY_APPARMOR=y +CONFIG_SECURITY_APPARMOR_DEBUG=n +CONFIG_SECURITY_APPARMOR_EXPORT_BINARY=y +CONFIG_SECURITY_APPARMOR_HASH=y +CONFIG_SECURITY_APPARMOR_HASH_DEFAULT=y +CONFIG_SECURITY_APPARMOR_INTROSPECT_POLICY=y +CONFIG_SECURITY_APPARMOR_PARANOID_LOAD=y +CONFIG_SECURITY_SAFESETID=y +CONFIG_MD=y +CONFIG_DAX=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_MULTIPATH=m +CONFIG_DM_UEVENT=y +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_4K_DEVBLK_SIZE=n +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_ZSTD=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y +CONFIG_SQUASHFS_DECOMP_MULTI=y +CONFIG_SQUASHFS_DECOMP_SINGLE=y +CONFIG_SQUASHFS_EMBEDDED=n +CONFIG_SQUASHFS_FILE_CACHE=n +CONFIG_SQUASHFS_FILE_DIRECT=y +CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS=y +CONFIG_NETFILTER=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_NF_CONNTRACK=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_NETFILTER_XTABLES=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_NETFILTER_ADVANCED=y +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_LSM="landlock,lockdown,yama,integrity,apparmor" +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_MISC=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_RDMA=y From 748332321e9ad5f683f489b4eca4f85d91309dd3 Mon Sep 17 00:00:00 2001 From: Pinkesh Vaghela Date: Tue, 13 Aug 2024 21:46:31 +0530 Subject: [PATCH 35/38] hifive-premier-p550: Remove 1.5GHz to 1.8GHz cpu freq Removed 1.5GHz to 1.8GHz cpu freq from opp-table as the max supported freq for CPU is 1.4GHz Signed-off-by: Pinkesh Vaghela --- arch/riscv/boot/dts/eswin/eic7700.dtsi | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/arch/riscv/boot/dts/eswin/eic7700.dtsi b/arch/riscv/boot/dts/eswin/eic7700.dtsi index 01be763cdf5ef..82b62135ebea9 100644 --- a/arch/riscv/boot/dts/eswin/eic7700.dtsi +++ b/arch/riscv/boot/dts/eswin/eic7700.dtsi @@ -96,26 +96,6 @@ opp-microvolt = <800000>; clock-latency-ns = <70000>; }; - opp-1500000000 { - opp-hz = /bits/ 64 ; - opp-microvolt = <800000>; - clock-latency-ns = <70000>; - }; - opp-1600000000 { - opp-hz = /bits/ 64 ; - opp-microvolt = <800000>; - clock-latency-ns = <70000>; - }; - opp-1700000000 { - opp-hz = /bits/ 64 ; - opp-microvolt = <800000>; - clock-latency-ns = <70000>; - }; - opp-1800000000 { - opp-hz = /bits/ 64 ; - opp-microvolt = <800000>; - clock-latency-ns = <70000>; - }; }; }; From 081fb3f3f593861cbb98ece130b45f7a90140b10 Mon Sep 17 00:00:00 2001 From: Pritesh Patel Date: Fri, 23 Aug 2024 10:46:29 +0530 Subject: [PATCH 36/38] riscv: defconfig: hifive-premier-p550: Update command line Updated kernel command line - Removed stale command lines - Moved serial console configs to extlinux conf file Signed-off-by: Pritesh Patel --- arch/riscv/configs/hifive-premier-p550_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/configs/hifive-premier-p550_defconfig b/arch/riscv/configs/hifive-premier-p550_defconfig index 7e99e46146ad0..e371ee83d3822 100644 --- a/arch/riscv/configs/hifive-premier-p550_defconfig +++ b/arch/riscv/configs/hifive-premier-p550_defconfig @@ -20,7 +20,7 @@ CONFIG_SOC_SIFIVE=y CONFIG_SOC_VIRT=y CONFIG_SMP=y # CONFIG_RISCV_BOOT_SPINWAIT is not set -CONFIG_CMDLINE="earlycon=sbi console=ttyS0,115200n8 clk_ignore_unused cma_pernuma=0x2000000 disable_bypass=false" +CONFIG_CMDLINE="clk_ignore_unused" CONFIG_CMDLINE_EXTEND=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT=y From 77ac94268ff07a0788bea66b5e1fec44c9018d71 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 23 Aug 2024 19:42:35 +0200 Subject: [PATCH 37/38] configs: refresh hifive-premier-p550_defconfig Use savedefconfig to create a true defconfig. Signed-off-by: Heinrich Schuchardt --- .../configs/hifive-premier-p550_defconfig | 119 ++++++------------ 1 file changed, 39 insertions(+), 80 deletions(-) diff --git a/arch/riscv/configs/hifive-premier-p550_defconfig b/arch/riscv/configs/hifive-premier-p550_defconfig index e371ee83d3822..943c63eb14a14 100644 --- a/arch/riscv/configs/hifive-premier-p550_defconfig +++ b/arch/riscv/configs/hifive-premier-p550_defconfig @@ -7,8 +7,15 @@ CONFIG_IKCONFIG_PROC=y CONFIG_CGROUPS=y CONFIG_CGROUP_SCHED=y CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_RDMA=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_HUGETLB=y CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y CONFIG_CGROUP_BPF=y +CONFIG_CGROUP_MISC=y CONFIG_NAMESPACES=y CONFIG_USER_NS=y CONFIG_CHECKPOINT_RESTORE=y @@ -19,7 +26,6 @@ CONFIG_SOC_SIFIVE_EIC7700=y CONFIG_SOC_SIFIVE=y CONFIG_SOC_VIRT=y CONFIG_SMP=y -# CONFIG_RISCV_BOOT_SPINWAIT is not set CONFIG_CMDLINE="clk_ignore_unused" CONFIG_CMDLINE_EXTEND=y CONFIG_CPU_FREQ=y @@ -34,7 +40,6 @@ CONFIG_CPUFREQ_DT=y CONFIG_VIRTUALIZATION=y CONFIG_KVM=y CONFIG_JUMP_LABEL=y -# CONFIG_GCC_PLUGINS is not set CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_SPARSEMEM_MANUAL=y @@ -46,6 +51,16 @@ CONFIG_INET=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m CONFIG_NET_SCHED=y CONFIG_NET_CLS_ACT=y CONFIG_CFG80211=m @@ -89,6 +104,10 @@ CONFIG_BLK_DEV_SD=y CONFIG_ATA=y CONFIG_SATA_AHCI=y CONFIG_AHCI_ESWIN=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_MULTIPATH=m +CONFIG_DM_UEVENT=y CONFIG_NETDEVICES=y CONFIG_VIRTIO_NET=y # CONFIG_NET_VENDOR_ALACRITECH is not set @@ -133,6 +152,7 @@ CONFIG_DWMAC_EIC7700=y # CONFIG_NET_VENDOR_XILINX is not set CONFIG_RTW88=m CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822CS=m CONFIG_RTW88_DEBUG=y CONFIG_RTW88_DEBUGFS=y CONFIG_INPUT_EVDEV=y @@ -145,7 +165,6 @@ CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_EARLYCON_RISCV_SBI=y -CONFIG_HVC_RISCV_SBI=y CONFIG_VIRTIO_CONSOLE=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_VIRTIO=y @@ -287,13 +306,26 @@ CONFIG_MEMORY=y CONFIG_PWM=y CONFIG_PWM_ESWIN=y CONFIG_RESET_ESWIN_EIC7700=y +CONFIG_DAX=y CONFIG_INTERCONNECT=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y +CONFIG_HUGETLBFS=y +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_DIRECT=y +CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZSTD=y CONFIG_NFS_FS=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y @@ -302,11 +334,14 @@ CONFIG_NFS_V4_2=y CONFIG_ROOT_NFS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=m +CONFIG_SECURITY=y +CONFIG_SECURITY_APPARMOR=y +CONFIG_SECURITY_SAFESETID=y +CONFIG_LSM="landlock,lockdown,yama,integrity,apparmor" CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_DEV_VIRTIO=y CONFIG_CRC_ITU_T=y CONFIG_CRC7=y -CONFIG_XZ_DEC=y CONFIG_DMA_CMA=y CONFIG_PRINTK_TIME=y CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 @@ -335,79 +370,3 @@ CONFIG_DEBUG_SG=y CONFIG_RCU_EQS_DEBUG=y # CONFIG_RUNTIME_TESTING_MENU is not set CONFIG_MEMTEST=y -CONFIG_TRACEPOINTS=y -CONFIG_UPROBES=y -CONFIG_NOP_TRACER=y -CONFIG_TRACE_CLOCK=y -CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y -CONFIG_TRACING=y -CONFIG_FTRACE=y -CONFIG_BRANCH_PROFILE_NONE=y -CONFIG_UPROBE_EVENTS=y -CONFIG_BPF_EVENTS=y -CONFIG_DYNAMIC_EVENTS=y -CONFIG_PROBE_EVENTS=y -CONFIG_RTW88_SDIO=m -CONFIG_RTW88_8822C=m -CONFIG_RTW88_8822CS=m - -# Ubuntu -CONFIG_CGROUP_HUGETLB=y -CONFIG_HUGETLBFS=y -CONFIG_SECURITY=y -CONFIG_DEFAULT_SECURITY_APPARMOR=y -CONFIG_SECURITY_APPARMOR=y -CONFIG_SECURITY_APPARMOR_DEBUG=n -CONFIG_SECURITY_APPARMOR_EXPORT_BINARY=y -CONFIG_SECURITY_APPARMOR_HASH=y -CONFIG_SECURITY_APPARMOR_HASH_DEFAULT=y -CONFIG_SECURITY_APPARMOR_INTROSPECT_POLICY=y -CONFIG_SECURITY_APPARMOR_PARANOID_LOAD=y -CONFIG_SECURITY_SAFESETID=y -CONFIG_MD=y -CONFIG_DAX=y -CONFIG_BLK_DEV_DM=y -CONFIG_DM_MULTIPATH=m -CONFIG_DM_UEVENT=y -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_SQUASHFS=y -CONFIG_SQUASHFS_4K_DEVBLK_SIZE=n -CONFIG_SQUASHFS_LZ4=y -CONFIG_SQUASHFS_LZO=y -CONFIG_SQUASHFS_XATTR=y -CONFIG_SQUASHFS_XZ=y -CONFIG_SQUASHFS_ZLIB=y -CONFIG_SQUASHFS_ZSTD=y -CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y -CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y -CONFIG_SQUASHFS_DECOMP_MULTI=y -CONFIG_SQUASHFS_DECOMP_SINGLE=y -CONFIG_SQUASHFS_EMBEDDED=n -CONFIG_SQUASHFS_FILE_CACHE=n -CONFIG_SQUASHFS_FILE_DIRECT=y -CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS=y -CONFIG_NETFILTER=y -CONFIG_IP_NF_IPTABLES=y -CONFIG_NF_CONNTRACK=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IPV6=y -CONFIG_IP6_NF_IPTABLES=y -CONFIG_IP6_NF_NAT=m -CONFIG_IP6_NF_TARGET_MASQUERADE=m -CONFIG_NETFILTER_XTABLES=y -CONFIG_IP_NF_MANGLE=y -CONFIG_IP6_NF_MANGLE=y -CONFIG_NETFILTER_ADVANCED=y -CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -CONFIG_NETFILTER_XT_MATCH_COMMENT=m -CONFIG_LSM="landlock,lockdown,yama,integrity,apparmor" -CONFIG_CGROUP_CPUACCT=y -CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_MISC=y -CONFIG_CGROUP_PERF=y -CONFIG_CGROUP_PIDS=y -CONFIG_CGROUP_RDMA=y From a7e4aa8541b73a6199636a1fc945923c7e5a7088 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 23 Aug 2024 19:45:41 +0200 Subject: [PATCH 38/38] configs: improve hifive-premier-p550_defconfig distro compatibility With the changes Docker and the Ubuntu Firewall are functional. Signed-off-by: Heinrich Schuchardt --- .../configs/hifive-premier-p550_defconfig | 516 +++++++++++++++++- 1 file changed, 509 insertions(+), 7 deletions(-) diff --git a/arch/riscv/configs/hifive-premier-p550_defconfig b/arch/riscv/configs/hifive-premier-p550_defconfig index 943c63eb14a14..455ff0f26232a 100644 --- a/arch/riscv/configs/hifive-premier-p550_defconfig +++ b/arch/riscv/configs/hifive-premier-p550_defconfig @@ -1,10 +1,23 @@ +CONFIG_LOCALVERSION="-35-g29ac17434e52-eswin" CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_BPF_SYSCALL=y +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_PSI=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_CGROUPS=y +CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y CONFIG_CGROUP_SCHED=y CONFIG_CFS_BANDWIDTH=y CONFIG_CGROUP_PIDS=y @@ -12,6 +25,7 @@ CONFIG_CGROUP_RDMA=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_HUGETLB=y CONFIG_CPUSETS=y +CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_PERF=y CONFIG_CGROUP_BPF=y @@ -19,6 +33,7 @@ CONFIG_CGROUP_MISC=y CONFIG_NAMESPACES=y CONFIG_USER_NS=y CONFIG_CHECKPOINT_RESTORE=y +CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y # CONFIG_SYSFS_SYSCALL is not set CONFIG_PERF_EVENTS=y @@ -42,27 +57,364 @@ CONFIG_KVM=y CONFIG_JUMP_LABEL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y +CONFIG_BLK_DEV_ZONED=y +CONFIG_BLK_DEV_THROTTLING=y CONFIG_SPARSEMEM_MANUAL=y CONFIG_CMA=y CONFIG_NET=y CONFIG_PACKET=y +CONFIG_PACKET_DIAG=m CONFIG_UNIX=y +CONFIG_UNIX_DIAG=m +CONFIG_TLS=m +CONFIG_TLS_DEVICE=y +CONFIG_XFRM_USER=m +CONFIG_XFRM_INTERFACE=m +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=m +CONFIG_XDP_SOCKETS=y +CONFIG_XDP_SOCKETS_DIAG=m CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_NET_IPVTI=m +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m +CONFIG_INET_ESPINTCP=y +CONFIG_INET_IPCOMP=m +CONFIG_INET_DIAG=m +CONFIG_INET_UDP_DIAG=m +CONFIG_INET_RAW_DIAG=m +CONFIG_INET_DIAG_DESTROY=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_NV=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_DCTCP=m +CONFIG_TCP_CONG_CDG=m +CONFIG_TCP_CONG_BBR=m +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m +CONFIG_INET6_ESPINTCP=y +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_ILA=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_IPV6_SEG6_LWTUNNEL=y +CONFIG_IPV6_SEG6_HMAC=y +CONFIG_IPV6_RPL_LWTUNNEL=y +CONFIG_NETLABEL=y +CONFIG_MPTCP=y +CONFIG_NETWORK_PHY_TIMESTAMPING=y CONFIG_NETFILTER=y -CONFIG_NF_CONNTRACK=y +CONFIG_BRIDGE_NETFILTER=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_GLUE_CT=y +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=y +CONFIG_NF_TABLES_NETDEV=y +CONFIG_NFT_NUMGEN=m +CONFIG_NFT_CT=m +CONFIG_NFT_CONNLIMIT=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_TUNNEL=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_QUOTA=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_COMPAT=m +CONFIG_NFT_HASH=m +CONFIG_NFT_XFRM=m +CONFIG_NFT_SOCKET=m +CONFIG_NFT_OSF=m +CONFIG_NFT_TPROXY=m +CONFIG_NFT_SYNPROXY=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m +CONFIG_NFT_REJECT_NETDEV=m +CONFIG_NF_FLOW_TABLE_INET=m +CONFIG_NF_FLOW_TABLE=m +CONFIG_NETFILTER_XTABLES_COMPAT=y +CONFIG_NETFILTER_XT_TARGET_AUDIT=m CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m CONFIG_NETFILTER_XT_MATCH_COMMENT=m -CONFIG_IP_NF_IPTABLES=y -CONFIG_IP_NF_MANGLE=y -CONFIG_IP6_NF_IPTABLES=y -CONFIG_IP6_NF_MANGLE=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_IPMAC=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_MH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_TWOS=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_PE_SIP=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NFT_FIB_IPV4=m +CONFIG_NF_TABLES_ARP=y +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_SECURITY=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NFT_FIB_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_SRH=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_SECURITY=m CONFIG_IP6_NF_NAT=m CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_CONNTRACK_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_IP_DCCP=y +# CONFIG_IP_DCCP_CCID3 is not set +CONFIG_SCTP_COOKIE_HMAC_SHA1=y +CONFIG_RDS=m +CONFIG_RDS_TCP=m +CONFIG_TIPC=m +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +CONFIG_L2TP=m +CONFIG_L2TP_DEBUGFS=m +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_BRIDGE_MRP=y +CONFIG_BRIDGE_CFM=y +CONFIG_NET_DSA=m +CONFIG_NET_DSA_TAG_NONE=m +CONFIG_NET_DSA_TAG_AR9331=m +CONFIG_NET_DSA_TAG_BRCM=m +CONFIG_NET_DSA_TAG_BRCM_LEGACY=m +CONFIG_NET_DSA_TAG_BRCM_PREPEND=m +CONFIG_NET_DSA_TAG_HELLCREEK=m +CONFIG_NET_DSA_TAG_GSWIP=m +CONFIG_NET_DSA_TAG_DSA=m +CONFIG_NET_DSA_TAG_EDSA=m +CONFIG_NET_DSA_TAG_MTK=m +CONFIG_NET_DSA_TAG_KSZ=m +CONFIG_NET_DSA_TAG_OCELOT=m +CONFIG_NET_DSA_TAG_OCELOT_8021Q=m +CONFIG_NET_DSA_TAG_QCA=m +CONFIG_NET_DSA_TAG_RTL4_A=m +CONFIG_NET_DSA_TAG_RTL8_4=m +CONFIG_NET_DSA_TAG_RZN1_A5PSW=m +CONFIG_NET_DSA_TAG_LAN9303=m +CONFIG_NET_DSA_TAG_SJA1105=m +CONFIG_NET_DSA_TAG_TRAILER=m +CONFIG_NET_DSA_TAG_XRS700X=m +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +CONFIG_LLC2=m +CONFIG_ATALK=y +CONFIG_X25=m +CONFIG_LAPB=m +CONFIG_PHONET=m +CONFIG_6LOWPAN=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m CONFIG_NET_SCHED=y +CONFIG_NET_CLS_CGROUP=m CONFIG_NET_CLS_ACT=y +CONFIG_DCB=y +CONFIG_BATMAN_ADV=m +# CONFIG_BATMAN_ADV_BATMAN_V is not set +CONFIG_OPENVSWITCH=m +CONFIG_VSOCKETS=m +CONFIG_VIRTIO_VSOCKETS=m +CONFIG_NETLINK_DIAG=m +CONFIG_HSR=m +CONFIG_QRTR=m +CONFIG_QRTR_SMD=m +CONFIG_QRTR_TUN=m +CONFIG_NET_NCSI=y +CONFIG_NCSI_OEM_CMD_GET_MAC=y +CONFIG_CGROUP_NET_PRIO=y +CONFIG_BPF_STREAM_PARSER=y +CONFIG_NET_PKTGEN=m +CONFIG_NET_DROP_MONITOR=m CONFIG_CFG80211=m CONFIG_NL80211_TESTMODE=y CONFIG_CFG80211_DEVELOPER_WARNINGS=y @@ -87,6 +439,8 @@ CONFIG_PCI_PASID=y CONFIG_PCIE_ESWIN=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y +CONFIG_FW_LOADER_COMPRESS=y +CONFIG_FW_LOADER_COMPRESS_ZSTD=y CONFIG_MTD=y CONFIG_MTD_SPI_NOR=y CONFIG_BLK_DEV_LOOP=y @@ -105,11 +459,91 @@ CONFIG_ATA=y CONFIG_SATA_AHCI=y CONFIG_AHCI_ESWIN=y CONFIG_MD=y +CONFIG_MD_CLUSTER=m +CONFIG_BCACHE=m +CONFIG_BCACHE_ASYNC_REGISTRATION=y CONFIG_BLK_DEV_DM=y +CONFIG_DM_UNSTRIPED=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_DM_CACHE=m +CONFIG_DM_WRITECACHE=m +CONFIG_DM_EBS=m +CONFIG_DM_ERA=m +CONFIG_DM_CLONE=m +CONFIG_DM_MIRROR=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_RAID=m +CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_QL=m +CONFIG_DM_MULTIPATH_ST=m +CONFIG_DM_MULTIPATH_HST=m +CONFIG_DM_MULTIPATH_IOA=m +CONFIG_DM_DELAY=m +CONFIG_DM_INIT=y CONFIG_DM_UEVENT=y +CONFIG_DM_FLAKEY=m +CONFIG_DM_VERITY=m +CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y +CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING=y +CONFIG_DM_SWITCH=m +CONFIG_DM_LOG_WRITES=m +CONFIG_DM_INTEGRITY=m +CONFIG_DM_ZONED=m +CONFIG_TARGET_CORE=m +CONFIG_TCM_IBLOCK=m +CONFIG_TCM_FILEIO=m +CONFIG_TCM_PSCSI=m +CONFIG_LOOPBACK_TARGET=m +CONFIG_ISCSI_TARGET=m +CONFIG_REMOTE_TARGET=m +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LOGGING=y CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_WIREGUARD=m +CONFIG_EQUALIZER=m +CONFIG_NET_FC=y +CONFIG_IFB=m +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_RANDOM=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +CONFIG_IPVLAN=m +CONFIG_IPVTAP=m +CONFIG_VXLAN=m +CONFIG_GENEVE=m +CONFIG_BAREUDP=m +CONFIG_GTP=m +CONFIG_MACSEC=m +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_TUN=y +CONFIG_VETH=m CONFIG_VIRTIO_NET=y +CONFIG_NLMON=m +CONFIG_NET_VRF=m +CONFIG_ATM_DUMMY=m +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +CONFIG_ATM_NICSTAR=m +CONFIG_ATM_IDT77252=m +CONFIG_ATM_IA=m +CONFIG_ATM_FORE200E=m +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y +CONFIG_ATM_SOLOS=m # CONFIG_NET_VENDOR_ALACRITECH is not set # CONFIG_NET_VENDOR_AMAZON is not set # CONFIG_NET_VENDOR_AQUANTIA is not set @@ -308,16 +742,69 @@ CONFIG_PWM_ESWIN=y CONFIG_RESET_ESWIN_EIC7700=y CONFIG_DAX=y CONFIG_INTERCONNECT=y +CONFIG_VALIDATE_FS_PARSER=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_JFS_STATISTICS=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +CONFIG_GFS2_FS=m +CONFIG_OCFS2_FS=m +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_NILFS2_FS=m +CONFIG_F2FS_FS=m +CONFIG_F2FS_FS_SECURITY=y +CONFIG_F2FS_FS_COMPRESSION=y +# CONFIG_F2FS_IOSTAT is not set +CONFIG_F2FS_UNFAIR_RWSEM=y +CONFIG_EXPORTFS_BLOCK_OPS=y +CONFIG_FS_ENCRYPTION=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y +CONFIG_FANOTIFY=y +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_AUTOFS_FS=m +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_VIRTIO_FS=m +CONFIG_OVERLAY_FS=m +CONFIG_OVERLAY_FS_XINO_AUTO=y +CONFIG_FSCACHE=y +CONFIG_FSCACHE_STATS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_ERROR_INJECTION=y CONFIG_ISO9660_FS=m CONFIG_JOLIET=y CONFIG_ZISOFS=y +CONFIG_UDF_FS=m CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y +CONFIG_EXFAT_FS=m +CONFIG_NTFS_FS=m +CONFIG_NTFS3_FS=m +CONFIG_NTFS3_LZX_XPRESS=y +CONFIG_NTFS3_FS_POSIX_ACL=y +CONFIG_PROC_KCORE=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_INODE64=y +CONFIG_TMPFS_QUOTA=y CONFIG_HUGETLBFS=y +CONFIG_EFIVAR_FS=y CONFIG_SQUASHFS=y CONFIG_SQUASHFS_FILE_DIRECT=y CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT=y @@ -333,15 +820,30 @@ CONFIG_NFS_V4_1=y CONFIG_NFS_V4_2=y CONFIG_ROOT_NFS=y CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_1=y +CONFIG_DLM=m +CONFIG_UNICODE=y CONFIG_SECURITY=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_SECURITY_APPARMOR=y CONFIG_SECURITY_SAFESETID=y +CONFIG_DEFAULT_SECURITY_APPARMOR=y CONFIG_LSM="landlock,lockdown,yama,integrity,apparmor" -CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CBC=m +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_XTS is not set +CONFIG_CRYPTO_AEGIS128=m +CONFIG_CRYPTO_CHACHA20POLY1305=m +CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_DEV_VIRTIO=y +CONFIG_SYSTEM_EXTRA_CERTIFICATE=y +CONFIG_SECONDARY_TRUSTED_KEYRING=y CONFIG_CRC_ITU_T=y CONFIG_CRC7=y +CONFIG_LIBCRC32C=y CONFIG_DMA_CMA=y CONFIG_PRINTK_TIME=y CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15