Compare commits

...

39 Commits

Author SHA1 Message Date
hongyi
218862ffdd Release develop 260205 2026-02-05 10:48:51 +08:00
hongyi
95d169caeb Release develop 260203 2026-02-03 05:09:43 +08:00
hongyi
d1a0fed7aa Release develop 260131 2026-01-31 14:47:59 +08:00
hongyi
006816cce1 Release develop 260130 2026-01-30 17:09:03 +08:00
hongyi
b56f19ed96 Release develop 260120 2026-01-20 10:49:13 +08:00
hongyi
7a3477fcec Release develop 260116 2026-01-16 19:29:06 +08:00
hongyi
2ac7095ee6 Release develop 260115 2026-01-15 11:06:49 +08:00
hongyi
1225339fca Release develop 260114 2026-01-14 11:49:10 +08:00
hongyi
434ae3d5fc Release develop 260113 2026-01-13 12:29:09 +08:00
hongyi
1479e89f14 Release develop 260109 2026-01-09 14:44:14 +08:00
hongyi
0a484b1703 Release develop 260106 2026-01-06 21:56:05 +08:00
hongyi
4b10ff3937 Release develop 260105 2026-01-05 19:44:14 +08:00
hongyi
8cf766e6cf Release develop 260104 2026-01-04 12:22:11 +08:00
hongyi
52d25821d3 Release develop 251230 2025-12-30 09:58:10 +08:00
hongyi
8add2b4251 Release develop 251227 2025-12-27 14:21:38 +08:00
hongyi
ca4f09cd41 Release develop 251226 2025-12-26 11:41:00 +08:00
hongyi
e31acb1b2d Release develop 251225 2025-12-25 15:40:45 +08:00
hongyi
876ebfd3c5 Release develop 251224 2025-12-24 12:22:59 +08:00
hongyi
4b8bcc0c64 Release develop 251218 2025-12-18 14:27:13 +08:00
hongyi
0cf5473f0f Release develop 251217 2025-12-17 12:17:54 +08:00
hongyi
841a1afde6 Release develop 251213 2025-12-13 16:39:36 +08:00
hongyi
ef98ee35f2 Release develop 251213 2025-12-13 03:02:36 +08:00
hongyi
f071dc9a24 Release develop 251204 2025-12-04 13:15:59 +08:00
hongyi
a2e0345a70 Release develop 251125 2025-11-25 09:54:20 +08:00
hongyi
30cc0ef619 Release develop 251124 2025-11-24 11:44:04 +08:00
hongyi
e3942b9ebf Release develop 251121 2025-11-21 14:24:33 +08:00
hongyi
e081635272 Release develop 251119 2025-11-19 21:14:48 +08:00
hongyi
c4dc112896 Release develop 251119 2025-11-19 13:52:37 +08:00
hongyi
941845bf9a Release develop 251118 2025-11-18 14:49:48 +08:00
hongyi
2447ff7f93 Release develop 251117 2025-11-17 17:43:31 +08:00
hongyi
5d591b1b36 Release develop 251115 2025-11-15 00:17:19 +08:00
hongyi
47c96ca1c2 Release develop 251114 2025-11-14 16:33:50 +08:00
hongyi
b37a325037 Release develop 251112 2025-11-12 09:58:12 +08:00
hongyi
9ae3173e35 Release develop 251111 2025-11-11 22:47:57 +08:00
hongyi
194010441d Release develop 251108 2025-11-08 12:11:19 +08:00
hongyi
3dd1665eea Release develop 251107 2025-11-07 09:18:07 +08:00
hongyi
0e5056b0cb Release develop 251105 2025-11-05 14:27:31 +08:00
hongyi
7d0c524a3d Release develop 251101 2025-11-01 11:32:38 +08:00
hongyi
76402bcd1b Release develop 251030 2025-10-30 12:22:17 +08:00
173 changed files with 19943 additions and 7146 deletions

View File

@@ -1,93 +0,0 @@
stages:
- init
- build
- test
- deploy
- cleanup
mr-code-review:
stage: build
script:
- zb gitlab review
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
mr-build-virt:
stage: build
script:
- zb diskimage -ekernel:source-path=$PWD -osubsystem=test -odistro=debian -oboard=virt --tar
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
mr-build-a200-evb:
stage: build
script:
- zb diskimage -ekernel:source-path=$PWD -osubsystem=test -odistro=debian -oboard=a200-evb --tar
- zb gitlab upload build/Release/*.tar.gz # 上传到临时 mr artifactory
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
mr-build-a210-evb:
stage: build
script:
- zb diskimage -ekernel:source-path=$PWD -osubsystem=test -odistro=debian -oboard=a210-evb --tar
- zb gitlab upload build/Release/*.tar.gz # 上传到临时 mr artifactory
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
mr-test-virt:
stage: test
script:
- echo "无需测试"
dependencies:
- mr-build-virt
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
mr-test-a200-evb:
stage: test
script:
- zb gitlab run --timeout 600 --board "p1-*" .cicd/runtest-a200-evb.sh
dependencies:
- mr-build-a200-evb
tags:
- a200-board-runner
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
mr-test-a210-evb:
stage: test
script:
- zb gitlab run --timeout 600 --board "a210-evb-3-*" .cicd/runtest-a210-evb.sh
dependencies:
- mr-build-a210-evb
tags:
- a210-board-runner
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
mr-deploy:
stage: deploy
script:
- zb kernel -f -esource-path=$PWD -oboard=a210-evb
- zb kernel -f -esource-path=$PWD -oboard=a200-evb
- zb kernel -f -esource-path=$PWD -oboard=virt
- zb upload kernel --all
rules:
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
before_script:
- .cicd/version.sh
- export ZB_CACHE_PATH=$HOME/download_cache
- export SDK_VERSION=${CI_COMMIT_BRANCH:-$CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
- export DISK_IMAGE=diskimage_${SDK_VERSION//\//_}
- export VIRT_TARGZ=${DISK_IMAGE}_virt-release_test.tar.gz
- export A200_EVB_IMAGE=${DISK_IMAGE}_a200-evb-release_test_debian.tar.gz
- export A210_EVB_IMAGE=${DISK_IMAGE}_a210-evb-release_test_debian.tar.gz
- export
variables:
CONAN_USER_HOME: $CI_BUILDS_DIR/$CI_JOB_ID
MERGE_REQUEST_URL: $CI_MERGE_REQUEST_PROJECT_URL/-/merge_requests/$CI_MERGE_REQUEST_IID

View File

@@ -1,25 +0,0 @@
#!/bin/bash
set -e
SOCAT_FILE=$(mktemp /tmp/socat_XXXXXX)
export SOCAT_FILE
zb diskimage
zb run --socat=$SOCAT_FILE &
pid=$!
# 定义清理函数
cleanup() {
set +e
kill $pid 2>/dev/null
wait $pid 2>/dev/null
rm -rf $SOCAT_FILE
exit 0
}
# 设置陷阱,在接收到信号时调用清理函数
trap 'cleanup' EXIT
# 不支持并行测试
pytest $(dirname "$0")/tests -sv --durations=0 -x

View File

@@ -1,18 +0,0 @@
#!/bin/sh
BRANCH=${CI_COMMIT_BRANCH:-$CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
if [ -n "${BRANCH}" ]; then
case "$BRANCH" in
develop|master) zb version _/_ ;;
*) zbuild version $BRANCH ;;
esac
else
zb version _/_
fi
zbuild build zbuild -f || true
# 删除一天前的遗留目录
find $CI_BUILDS_DIR -maxdepth 1 -type d -name "[0-9]*" -mtime +1 -exec rm -r {} \; || true

View File

@@ -40,6 +40,7 @@ void dma_cache_wback(phys_addr_t start, unsigned long sz);
/* TBD: optimize this */ /* TBD: optimize this */
#define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vmap(start, end) flush_cache_all()
#define flush_cache_vmap_early(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all()
#define flush_cache_dup_mm(mm) /* called on fork (VIVT only) */ #define flush_cache_dup_mm(mm) /* called on fork (VIVT only) */

View File

@@ -340,6 +340,8 @@ static inline void flush_cache_vmap(unsigned long start, unsigned long end)
dsb(ishst); dsb(ishst);
} }
#define flush_cache_vmap_early(start, end) do { } while (0)
static inline void flush_cache_vunmap(unsigned long start, unsigned long end) static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
{ {
if (!cache_is_vipt_nonaliasing()) if (!cache_is_vipt_nonaliasing())

View File

@@ -43,6 +43,7 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
*/ */
extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
#define flush_cache_vmap(start, end) cache_wbinv_all() #define flush_cache_vmap(start, end) cache_wbinv_all()
#define flush_cache_vmap_early(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) cache_wbinv_all() #define flush_cache_vunmap(start, end) cache_wbinv_all()
#define flush_icache_range(start, end) cache_wbinv_range(start, end) #define flush_icache_range(start, end) cache_wbinv_range(start, end)

View File

@@ -41,6 +41,7 @@ void flush_icache_mm_range(struct mm_struct *mm,
void flush_icache_deferred(struct mm_struct *mm); void flush_icache_deferred(struct mm_struct *mm);
#define flush_cache_vmap(start, end) do { } while (0) #define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vmap_early(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0) #define flush_cache_vunmap(start, end) do { } while (0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ #define copy_to_user_page(vma, page, vaddr, dst, src, len) \

View File

@@ -191,6 +191,7 @@ extern void cache_push_v(unsigned long vaddr, int len);
#define flush_cache_all() __flush_cache_all() #define flush_cache_all() __flush_cache_all()
#define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vmap(start, end) flush_cache_all()
#define flush_cache_vmap_early(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all()
static inline void flush_cache_mm(struct mm_struct *mm) static inline void flush_cache_mm(struct mm_struct *mm)

View File

@@ -97,6 +97,8 @@ static inline void flush_cache_vmap(unsigned long start, unsigned long end)
__flush_cache_vmap(); __flush_cache_vmap();
} }
#define flush_cache_vmap_early(start, end) do { } while (0)
extern void (*__flush_cache_vunmap)(void); extern void (*__flush_cache_vunmap)(void);
static inline void flush_cache_vunmap(unsigned long start, unsigned long end) static inline void flush_cache_vunmap(unsigned long start, unsigned long end)

View File

@@ -38,6 +38,7 @@ void flush_icache_pages(struct vm_area_struct *vma, struct page *page,
#define flush_icache_pages flush_icache_pages #define flush_icache_pages flush_icache_pages
#define flush_cache_vmap(start, end) flush_dcache_range(start, end) #define flush_cache_vmap(start, end) flush_dcache_range(start, end)
#define flush_cache_vmap_early(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) flush_dcache_range(start, end) #define flush_cache_vunmap(start, end) flush_dcache_range(start, end)
extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page, extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page,

View File

@@ -41,6 +41,7 @@ void flush_kernel_vmap_range(void *vaddr, int size);
void invalidate_kernel_vmap_range(void *vaddr, int size); void invalidate_kernel_vmap_range(void *vaddr, int size);
#define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vmap(start, end) flush_cache_all()
#define flush_cache_vmap_early(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all()
void flush_dcache_folio(struct folio *folio); void flush_dcache_folio(struct folio *folio);

View File

@@ -127,6 +127,7 @@ config RISCV
select HAVE_FUNCTION_ERROR_INJECTION select HAVE_FUNCTION_ERROR_INJECTION
select HAVE_GCC_PLUGINS select HAVE_GCC_PLUGINS
select HAVE_GENERIC_VDSO if MMU && 64BIT select HAVE_GENERIC_VDSO if MMU && 64BIT
select HAVE_HW_BREAKPOINT if PERF_EVENTS
select HAVE_IRQ_TIME_ACCOUNTING select HAVE_IRQ_TIME_ACCOUNTING
select HAVE_KPROBES if !XIP_KERNEL select HAVE_KPROBES if !XIP_KERNEL
select HAVE_KPROBES_ON_FTRACE if !XIP_KERNEL select HAVE_KPROBES_ON_FTRACE if !XIP_KERNEL

View File

@@ -34,6 +34,7 @@ config SOC_STARFIVE
config ARCH_ZHIHE config ARCH_ZHIHE
bool "ZhiHe SoCs" bool "ZhiHe SoCs"
select CLOCKSOURCE_VALIDATE_LAST_CYCLE
help help
This enables support for ZhiHe SoC platform hardware. This enables support for ZhiHe SoC platform hardware.

View File

@@ -5,3 +5,4 @@ dtb-$(CONFIG_ARCH_XUANTIE) += th1520-a-val.dtb th1520-a-val-sec.dtb
dtb-$(CONFIG_ARCH_XUANTIE) += th1520-a-val-audio.dtb th1520-a-val-audio-i2s-8ch.dtb th1520-a-val-audio-tdm.dtb th1520-a-val-audio-spdif.dtb th1520-a-val-crash.dtb dtb-$(CONFIG_ARCH_XUANTIE) += th1520-a-val-audio.dtb th1520-a-val-audio-i2s-8ch.dtb th1520-a-val-audio-tdm.dtb th1520-a-val-audio-spdif.dtb th1520-a-val-crash.dtb
dtb-$(CONFIG_ARCH_XUANTIE) += th1520-a-val-dsi0-dsi1.dtb th1520-a-val-dsi0-hdmi.dtb dtb-$(CONFIG_ARCH_XUANTIE) += th1520-a-val-dsi0-dsi1.dtb th1520-a-val-dsi0-hdmi.dtb
dtb-$(CONFIG_ARCH_XUANTIE) += th1520-rvbook-product.dtb th1520-rvbook-product-sec.dtb dtb-$(CONFIG_ARCH_XUANTIE) += th1520-rvbook-product.dtb th1520-rvbook-product-sec.dtb
dtb-$(CONFIG_ARCH_XUANTIE) += a200-evb.dtb a200-dev.dtb

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,125 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (C) 2021-2024 Alibaba Group Holding Limited.
*/
/dts-v1/;
#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "A200 HAPS";
compatible = "sipeed,lichee-pi-4a", "sipeed,lichee-module-4a", "thead,th1520", "thead,light";
#address-cells = <2>;
#size-cells = <2>;
aliases {
serial0 = &uart0;
};
chosen {
stdout-path = "serial0:115200n8";
};
memory@0 {
device_type = "memory";
reg = <0x0 0x200000 0x0 0xffe00000>;
numa-node-id = <0>;
};
cpus: cpus {
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <3000000>;
c910_0: cpu@0 {
compatible = "thead,c910", "riscv";
device_type = "cpu";
riscv,isa = "rv64imafdcv";
reg = <0>;
i-cache-block-size = <64>;
i-cache-size = <65536>;
i-cache-sets = <512>;
d-cache-block-size = <64>;
d-cache-size = <65536>;
d-cache-sets = <512>;
next-level-cache = <&l2_cache>;
mmu-type = "riscv,sv39";
video-4k-minfreq = <1848000000>;
qos-mid-minfreq = <750000000>;
#cooling-cells = <2>;
dynamic-power-coefficient = <500>;
cpu0_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
interrupt-controller;
#interrupt-cells = <1>;
};
};
l2_cache: l2-cache {
compatible = "cache";
cache-block-size = <64>;
cache-level = <2>;
cache-size = <1048576>;
cache-sets = <1024>;
cache-unified;
};
};
uart_sclk: uart-sclk-clock {
compatible = "fixed-clock";
clock-frequency = <50000000>;
clock-output-names = "uart_sclk";
#clock-cells = <0>;
};
soc {
compatible = "simple-bus";
interrupt-parent = <&plic>;
#address-cells = <2>;
#size-cells = <2>;
dma-noncoherent;
ranges;
uart0: serial@ffe7014000 {
compatible = "snps,dw-apb-uart", "light,uart0";
reg = <0xff 0xe7014000 0x0 0x100>;
interrupts = <36 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&uart_sclk>;
reg-shift = <2>;
reg-io-width = <4>;
current-speed = <115200>; /* OpenSBI */
status = "okay";
};
/* OpenSBI */
reset: reset-sample {
compatible = "thead,reset-sample";
plic-delegate = <0xff 0xd81ffffc>;
entry-reg = <0xff 0xff019050>;
entry-cnt = <4>;
control-reg = <0xff 0xff015004>;
control-val = <0x1c>;
csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc 0x7ce>;
};
plic: interrupt-controller@ffd8000000 {
compatible = "thead,th1520-plic", "thead,c900-plic", "riscv,plic0";
reg = <0xff 0xd8000000 0x0 0x01000000>;
interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>;
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
riscv,ndev = <240>;
};
clint: timer@ffdc000000 {
compatible = "thead,th1520-clint", "thead,c900-clint", "riscv,clint0";
reg = <0xff 0xdc000000 0x0 0x0000d000>;
interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>;
clint,has-no-64bit-mmio;
};
};
};

View File

@@ -429,7 +429,7 @@
}; };
key-sleep { key-sleep {
label = "Sleep Wake Key"; label = "Sleep Wake Key";
wakeup-source; //wakeup-source;
linux,code = <KEY_SLEEP>; linux,code = <KEY_SLEEP>;
debounce-interval = <1>; debounce-interval = <1>;
gpios = <&aogpio 2 GPIO_ACTIVE_LOW>; gpios = <&aogpio 2 GPIO_ACTIVE_LOW>;
@@ -1213,7 +1213,7 @@
broken-cd; broken-cd;
io_fixed_1v8; io_fixed_1v8;
non-removable; non-removable;
post-power-on-delay-ms = <200>; post-power-on-delay-ms = <1000>;
wprtn_ignore; wprtn_ignore;
cap-sd-highspeed; cap-sd-highspeed;
wakeup-source; wakeup-source;

View File

@@ -1158,7 +1158,7 @@
compatible = "snps,dw-apb-gpio-port"; compatible = "snps,dw-apb-gpio-port";
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
ngpios = <31>; ngpios = <32>;
gpio-ranges = <&padctrl0_apsys 0 0 32>; gpio-ranges = <&padctrl0_apsys 0 0 32>;
reg = <0>; reg = <0>;
interrupt-controller; interrupt-controller;
@@ -1180,7 +1180,7 @@
compatible = "snps,dw-apb-gpio-port"; compatible = "snps,dw-apb-gpio-port";
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
ngpios = <32>; ngpios = <23>;
gpio-ranges = <&padctrl0_apsys 0 32 23>; gpio-ranges = <&padctrl0_apsys 0 32 23>;
reg = <0>; reg = <0>;
interrupt-controller; interrupt-controller;
@@ -1219,7 +1219,7 @@
compatible = "snps,dw-apb-gpio-port"; compatible = "snps,dw-apb-gpio-port";
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
ngpios = <23>; ngpios = <32>;
gpio-ranges = <&padctrl1_apsys 0 0 32>; gpio-ranges = <&padctrl1_apsys 0 0 32>;
reg = <0>; reg = <0>;
interrupt-controller; interrupt-controller;
@@ -1241,7 +1241,7 @@
compatible = "snps,dw-apb-gpio-port"; compatible = "snps,dw-apb-gpio-port";
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
ngpios = <32>; ngpios = <31>;
gpio-ranges = <&padctrl1_apsys 0 32 31>; gpio-ranges = <&padctrl1_apsys 0 32 31>;
reg = <0>; reg = <0>;
interrupt-controller; interrupt-controller;
@@ -1468,7 +1468,7 @@
compatible = "snps,dw-apb-gpio-port"; compatible = "snps,dw-apb-gpio-port";
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
ngpios = <23>; ngpios = <16>;
gpio-ranges = <&padctrl_aosys 0 9 16>; gpio-ranges = <&padctrl_aosys 0 9 16>;
reg = <0>; reg = <0>;
interrupt-controller; interrupt-controller;
@@ -1514,7 +1514,7 @@
compatible = "snps,dw-apb-gpio-port"; compatible = "snps,dw-apb-gpio-port";
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
ngpios = <16>; ngpios = <23>;
gpio-ranges = <&padctrl_aosys 0 25 22>, <&padctrl_aosys 22 7 1>; gpio-ranges = <&padctrl_aosys 0 25 22>, <&padctrl_aosys 22 7 1>;
reg = <0>; reg = <0>;
interrupt-controller; interrupt-controller;
@@ -1880,6 +1880,11 @@
status = "okay"; status = "okay";
}; };
watchdog_aon: watchdog-aon {
compatible = "xuantie,th1520-aon-wdt";
status = "okay";
};
regdump: th1520-regdump { regdump: th1520-regdump {
compatible = "xuantie,th1520-regdump"; compatible = "xuantie,th1520-regdump";
status = "disabled"; status = "disabled";

View File

@@ -1,3 +1,5 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_ZHIHE) += a210-emu.dtb a210-emu-d2d.dtb a210-som-v1.dtb a210-evb.dtb a210-dev.dtb a210-evb-d2d.dtb dtb-$(CONFIG_ARCH_ZHIHE) += a210-evb.dtb a210-dev.dtb a210-evb-d2d.dtb
dtb-$(CONFIG_ARCH_ZHIHE) += a210-evb-sec.dtb a210-dev-sec.dtb
dtb-$(CONFIG_ARCH_ZHIHE) += a210-som-v1.dtb a210-usb-aistick.dtb

View File

@@ -0,0 +1,2 @@
#include "a210-dev.dts"
#include "a210-sec-tee.dtsi"

View File

@@ -1,6 +1,8 @@
/dts-v1/; /dts-v1/;
#include <dt-bindings/gpio/gpio.h> #include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/usb/pd.h>
#include <dt-bindings/input/linux-event-codes.h>
#include "a210-soc-core.dtsi" #include "a210-soc-core.dtsi"
#include "a210-soc-peri.dtsi" #include "a210-soc-peri.dtsi"
#include "a210-platform-dev.dtsi" #include "a210-platform-dev.dtsi"
@@ -24,11 +26,15 @@
ethernet0 = &gmac0; ethernet0 = &gmac0;
ethernet1 = &gmac1; ethernet1 = &gmac1;
gpio0 = &gpio0; gpio0 = &ao_gpio0;
gpio1 = &gpio1; gpio1 = &ao_gpio1;
gpio2 = &gpio2; gpio2 = &gpio0;
gpio3 = &gpio3; gpio3 = &gpio1;
gpio4 = &gpio4; gpio4 = &gpio2;
gpio5 = &gpio3;
gpio6 = &gpio4;
gpio7 = &aw9535_0;
gpio8 = &aw9535_1;
i2c0 = &i2c0; i2c0 = &i2c0;
i2c1 = &i2c1; i2c1 = &i2c1;
@@ -38,7 +44,7 @@
i2c5 = &i2c5; i2c5 = &i2c5;
i2c6 = &i2c6; i2c6 = &i2c6;
i2c7 = &i2c7; i2c7 = &i2c7;
aoi2c1 = &aoi2c1; i2c8 = &aoi2c1;
can0 = &can0; can0 = &can0;
can1 = &can1; can1 = &can1;
@@ -62,6 +68,8 @@
spi3 = &spi1; spi3 = &spi1;
pcie3x4 = &dm3x4; pcie3x4 = &dm3x4;
pcie3x1 = &rp3x1; pcie3x1 = &rp3x1;
vi_sensor0 = &mipicsi0_4lane_port;
vi_sensor1 = &mipi1csi1_a_port;
}; };
/* The actual capacity will be adjusted through SPL */ /* The actual capacity will be adjusted through SPL */
@@ -105,6 +113,11 @@
}; };
}; };
/* The bootargs in U-Boot will override the configuration set here. */
chosen {
stdout-path = "serial4";
};
Sound_Card@0 { Sound_Card@0 {
compatible = "simple-audio-card"; compatible = "simple-audio-card";
simple-audio-card,name = "Sound-Card-I2S0"; simple-audio-card,name = "Sound-Card-I2S0";
@@ -125,33 +138,296 @@
simple-audio-card,widgets = "Speaker", "Speaker"; simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing = simple-audio-card,routing =
"Speaker", "AW87565_PA2 VO", "Speaker", "AW87565_PA2 VO",
"AW87565_PA2 IN", "ES8156_DAC1 LOUT"; "AW87565_PA2 IN", "ES8156_DAC1 LOUT";
simple-audio-card,aux-devs = <&audio_aw87565_pa2>; simple-audio-card,aux-devs = <&audio_aw87565_pa2>;
SOUND_CARD_LINK(0, i2s, i2s1, 0, es8156_dac1, 0); SOUND_CARD_LINK(0, i2s, i2s1, 0, es8156_dac1, 0);
SOUND_CARD_LINK(1, i2s, i2s1, 0, es7210_adc1, 0); SOUND_CARD_LINK(1, i2s, i2s1, 0, es7210_adc1, 0);
}; };
wcn_wifi: wireless-wlan { lcd0_backlight: pwm-backlight@0 {
compatible = "wlan-platdata"; compatible = "pwm-backlight";
WIFI,poweren-gpios = <&aw9535_1 11 GPIO_ACTIVE_HIGH>, status = "okay";
<&aw9535_1 12 GPIO_ACTIVE_HIGH>, pwms = <&pwm1 2 100000 0>;
<&gpio0_porta 14 GPIO_ACTIVE_HIGH>; brightness-levels = <0 4 8 16 32 64 128 255>;
power_on_after_init; default-brightness-level = <7>;
power_on_when_resume; enable-gpios = <&aw9535_1 15 GPIO_ACTIVE_HIGH>;
status = "okay"; };
};
wcn_bt: wireless-bluetooth { reg_vdd33_lcd0: regulator-vdd33-lcd0 {
compatible = "bluetooth-platdata"; compatible = "regulator-fixed";
BT,power-gpios = <&ao_gpio1_porta 4 GPIO_ACTIVE_HIGH>, regulator-name = "lcd0_vdd33";
<&aw9535_1 15 GPIO_ACTIVE_HIGH>; regulator-min-microvolt = <3300000>;
status = "okay"; regulator-max-microvolt = <3300000>;
}; gpio = <&aw9535_1 5 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
/* The bootargs in U-Boot will override the configuration set here. */ reg_vddtp33_lcd0: regulator-vddtp33-lcd0 {
chosen { compatible = "regulator-fixed";
stdout-path = "serial4"; regulator-name = "lcd0_vddtp33";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&aw9535_1 14 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
mipicsi0_4lane_port: mipicsi0_4lane_port@0 {
compatible = "zhihe,vi_sensor";
clocks = <&clk SW_TOP_PAD_SENSOR_VCLK0_EN>;
clock-names = "core_clk";
clock-frequency = <24000000>;
pinctrl-names = "default";
pinctrl-0 = <&sen_vclk_pin0>;
sensor_pdn = <&aw9535_0 3 GPIO_ACTIVE_HIGH>;
sensor_rst = <&aw9535_0 4 GPIO_ACTIVE_HIGH>;
sensor_regulators = "DVDD1", "DVDD2", "AVDD1", "AVDD2";
DVDD1-supply = <&dvdd1_mipicsi0_reg>;
DVDD2-supply = <&dvdd2_mipicsi0_reg>;
AVDD1-supply = <&avdd1_mipicsi0_reg>;
AVDD2-supply = <&avdd2_mipicsi0_reg>;
status = "okay";
};
mipi1csi1_a_port: mipi1csi1_a_port@0 {
compatible = "zhihe,vi_sensor";
clocks = <&clk SW_TOP_PAD_SENSOR_VCLK1_EN>;
clock-names = "core_clk";
clock-frequency = <24000000>;
pinctrl-names = "default";
pinctrl-0 = <&sen_vclk_pin1>;
sensor_pdn = <&aw9535_0 0 GPIO_ACTIVE_HIGH>;
sensor_rst = <&aw9535_0 1 GPIO_ACTIVE_HIGH>;
sensor_regulators = "DVDD1", "DVDD2", "AVDD1", "AVDD2";
DVDD1-supply = <&dvdd1_mipicsi1_reg>;
DVDD2-supply = <&dvdd2_mipicsi1_reg>;
AVDD1-supply = <&avdd1_mipicsi1_reg>;
AVDD2-supply = <&avdd2_mipicsi1_reg>;
status = "okay";
};
reg_usb_typec_vbus: regulator-typec-vbus {
compatible = "regulator-fixed";
regulator-name = "usb_typec_vbus";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio0 27 GPIO_ACTIVE_HIGH>;
enable-active-high;
status = "okay";
};
wifi_vdd_3v3: wifi-3v3-regulator {
compatible = "regulator-fixed";
regulator-name = "wifi_vdd_3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&aw9535_1 11 GPIO_ACTIVE_HIGH>;
enable-active-high;
startup-delay-us = <1000>;
};
wifi_vdd_1v8: wifi-1v8-regulator {
compatible = "regulator-fixed";
regulator-name = "wifi_vdd_1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
gpio = <&aw9535_1 12 GPIO_ACTIVE_HIGH>;
enable-active-high;
startup-delay-us = <1000>;
};
wifi_pwrseq: wifi-pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
post-power-on-delay-ms = <200>;
};
gpio-keys {
compatible = "gpio-keys";
key-sleep {
label = "KEY_SLEEP";
linux,code = <KEY_SLEEP>;
debounce-interval = <1>;
gpios = <&ao_gpio0 1 GPIO_ACTIVE_LOW>;
};
};
};
&ao_gpio0 {
power-5v-en-hog {
gpio-hog;
gpios = <29 GPIO_ACTIVE_HIGH>;
output-high;
line-name = "power_5v_en";
};
power-3v3-en-hog {
gpio-hog;
gpios = <26 GPIO_ACTIVE_HIGH>;
output-high;
line-name = "power_3v3_en";
};
};
&aon {
regulators {
compatible = "zhihe,a210-aon-regulator";
avdd33_emmc_reg: avdd33_emmc {
regulator-name = "avdd33_emmc";
regulator-type = "voltage";
regulator-always-on;
};
avdd33_usb2_reg: avdd33_usb2 {
regulator-name = "avdd33_usb2";
regulator-type = "voltage";
regulator-always-on;
};
dvdd08_aon_reg: dvdd08_aon {
regulator-name = "dvdd08_aon";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_aon_reg: avdd18_aon {
regulator-name = "avdd18_aon";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_emmc_usb2_reg: avdd18_emmc_usb2 {
regulator-name = "avdd18_emmc_usb2";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_emmc_peri_reg: avdd18_emmc_peri {
regulator-name = "avdd18_emmc_peri";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_top_reg: avdd18_top {
regulator-name = "avdd18_top";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_pll_reg: avdd18_pll {
regulator-name = "avdd18_pll";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_reg: avdd18 {
regulator-name = "avdd18";
regulator-type = "voltage";
regulator-always-on;
};
dvdd18_ddr_vaa_reg: dvdd18_ddr_vaa {
regulator-name = "dvdd18_ddr_vaa";
regulator-type = "voltage";
regulator-always-on;
};
p3v3_reg: p3v3 {
regulator-name = "p3v3";
regulator-type = "voltage";
regulator-always-on;
};
dvdd08_top_reg: dvdd08_top {
regulator-name = "dvdd08_top";
regulator-type = "voltage";
regulator-always-on;
};
dvdd06_ddr_vddqlp_reg: dvdd06_ddr_vddqlp {
regulator-name = "dvdd06_ddr_vddqlp";
regulator-type = "voltage";
regulator-always-on;
};
dvdd08_ddr_reg: dvdd08_ddr {
regulator-name = "dvdd08_ddr";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <800000>;
regulator-always-on;
};
dvdd_cpu_reg: dvdd_cpu {
regulator-name = "dvdd_cpu";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-enable-ramp-delay = <2000>;
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
};
dvddm_cpu_reg: dvddm_cpu {
regulator-name = "dvddm_cpu";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-enable-ramp-delay = <2000>;
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
};
dvdd_vp_reg: dvdd_vp {
regulator-name = "dvdd_vp";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-enable-ramp-delay = <2000>;
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <800000>;
};
dvdd_npu_vip_reg: dvdd_npu_vip {
regulator-name = "dvdd_npu_vip";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-enable-ramp-delay = <2000>;
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <1000000>;
};
dvdd_cpu_p_reg: dvdd_cpu_p {
regulator-name = "dvdd_cpu_p";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-enable-ramp-delay = <2000>;
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
};
dvdd_gpu_reg: dvdd_gpu {
regulator-name = "dvdd_gpu";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-enable-ramp-delay = <2000>;
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <800000>;
};
};
cpufreq: a210_cpufreq {
compatible = "zhihe,a210-cpufreq";
clocks = <&clk TOP_CPUSYS_BUS_CLK_DIV>,
<&clk TOP_CPUSYS_PIC_CLK_DIV>,
<&clk TOP_CPUSYS_CFG_ACLK_DIV>,
<&clk TOP_CPUSYS_COM_APB_CLK_DIV>,
<&clk TOP_CPUSYS_APB_CLK_DIV>;
clock-names = "bus_clk", "pic_clk", "cfg_clk", "com_clk", "apb_clk";
status = "okay";
}; };
}; };
@@ -172,6 +448,37 @@
pins = "AOI2C1_SCL", "AOI2C1_SDA"; pins = "AOI2C1_SCL", "AOI2C1_SDA";
function = "aoi2c1"; function = "aoi2c1";
bias-disable; bias-disable;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <1>;
};
};
usbc0_int: usbc0-int {
usbcc-int-pins {
pins = "AOGPIO0_28";
function = "aogpio0";
bias-pull-up;
drive-strength = <13>;
input-enable;
input-schmitt-enable; /* 启用施密特触发器以稳定低电平中断信号 */
slew-rate = <0>;
};
};
bt_aogpios {
bt_reset: bt-reset {
pins = "AOGPIO1_4"; /* enable-gpios */
function = "aogpio0";
bias-pull-up;
drive-strength = <7>;
input-disable;
input-schmitt-enable;
slew-rate = <0>;
};
bt_wake_host: bt-wake-host {
pins = "AOGPIO0_30"; /* host-wake-gpios */
function = "aogpio0";
bias-pull-up;
drive-strength = <7>; drive-strength = <7>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
@@ -234,30 +541,9 @@
slew-rate = <0>; slew-rate = <0>;
}; };
}; };
can0_pins: can0-0 {
tx-pins {
pins = "GPIO0_25";
function = "can0";
bias-disable;
drive-strength = <5>;
input-disable;
input-schmitt-disable;
slew-rate = <1>;
};
rx-pins {
pins = "GPIO0_24";
function = "can0";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
pcie_x1_pins: pcie_x1-1 { pcie_x1_pins: pcie_x1-1 {
pcie_x1-pins { pcie_x1-pins {
pins = "GPIO0_24", "GPIO0_25", "GPIO0_26", "GPIO0_27"; pins = "GPIO0_25";
function = "pcie_x1"; function = "pcie_x1";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <7>;
@@ -268,7 +554,7 @@
}; };
pcie_x4_pins: pcie_x4-1 { pcie_x4_pins: pcie_x4-1 {
pcie_x4-pins { pcie_x4-pins {
pins = "GPIO0_28", "GPIO0_29", "GPIO0_31"; pins = "GPIO0_29";
function = "pcie_x4"; function = "pcie_x4";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <7>;
@@ -339,14 +625,14 @@
slew-rate = <0>; slew-rate = <0>;
}; };
}; };
usb3_pins: usb3-1 { bt_gpios {
usb3-pins { bt_wake_dev: bt-wake-dev {
pins = "GPIO0_27"; pins = "GPIO0_17"; /* device-wake-gpios */
function = "gpio0"; function = "gpio0";
bias-disable; bias-pull-up;
drive-strength = <13>; drive-strength = <7>;
input-disable; input-disable;
input-schmitt-disable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <0>;
}; };
}; };
@@ -379,10 +665,10 @@
pins = "GPIO2_28", "GPIO2_29"; pins = "GPIO2_28", "GPIO2_29";
function = "i2c5"; function = "i2c5";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
uart5_pins: uart5-1 { uart5_pins: uart5-1 {
@@ -411,10 +697,10 @@
pins = "GPIO2_8", "GPIO2_9"; pins = "GPIO2_8", "GPIO2_9";
function = "i2c6"; function = "i2c6";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
i2s1_pins: i2s1-0 { i2s1_pins: i2s1-0 {
@@ -432,10 +718,10 @@
pins = "GPIO2_10", "GPIO2_11"; pins = "GPIO2_10", "GPIO2_11";
function = "i2c7"; function = "i2c7";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
i2c4_pins: i2c4-2 { i2c4_pins: i2c4-2 {
@@ -443,10 +729,10 @@
pins = "GPIO2_26", "GPIO2_27"; pins = "GPIO2_26", "GPIO2_27";
function = "i2c4"; function = "i2c4";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
pwm1_pins: pwm1-1 { pwm1_pins: pwm1-1 {
@@ -471,9 +757,20 @@
slew-rate = <0>; slew-rate = <0>;
}; };
}; };
sen_vclk_pins: sen_vclk-1 { sen_vclk_pin0: sen_vclk0 {
sen_vclk-pins { sen_vclk0-pins {
pins = "GPIO3_0", "GPIO3_1"; pins = "GPIO3_0";
function = "sen_vclk";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
sen_vclk_pin1: sen_vclk1 {
sen_vclk1-pins {
pins = "GPIO3_1";
function = "sen_vclk"; function = "sen_vclk";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <7>;
@@ -534,16 +831,17 @@
}; };
&qspi0 { &qspi0 {
cs-gpios = <&gpio0_porta 19 0>; cs-gpios = <&gpio0 19 0>;
rx-sample-dly = <2>; rx-sample-dly = <2>;
spi-swap-data = <1>; spi-swap-data = <1>;
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>; pinctrl-0 = <&qspi0_pins>;
status = "disabled";
spi_norflash@0 { spi_norflash@0 {
compatible = "jedec,spi-nor"; compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
spi-tx-bus-width = <4>; spi-tx-bus-width = <4>;
@@ -563,6 +861,9 @@
pinctrl-0 = <&rtc_pins>; pinctrl-0 = <&rtc_pins>;
compatible = "nxp,pcf8563"; compatible = "nxp,pcf8563";
reg = <0x51>; reg = <0x51>;
interrupt-parent = <&ao_gpio0>;
interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
wakeup-source;
}; };
}; };
@@ -627,12 +928,76 @@
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&i2c6_pins>; pinctrl-0 = <&i2c6_pins>;
clock-frequency = <400000>; clock-frequency = <400000>;
pmic_wl2866d_0:wl2866d_0@28 {
compatible = "willsemi,wl2866d";
reg = <0x28>;
status = "okay";
regulators {
dvdd1_mipicsi0_reg: dvdd1_mipicsi0 {
regulator-name = "dvdd1_mipicsi0";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1300000>;
};
dvdd2_mipicsi0_reg: dvdd2_mipicsi0 {
regulator-name = "dvdd2_mipicsi0";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
avdd1_mipicsi0_reg: avdd1_mipicsi0 {
regulator-name = "avdd1_mipicsi0";
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <3300000>;
};
avdd2_mipicsi0_reg: avdd2_mipicsi0 {
regulator-name = "avdd2_mipicsi0";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
};
};
}; };
&i2c7 { &i2c7 {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&i2c7_pins>; pinctrl-0 = <&i2c7_pins>;
clock-frequency = <400000>; clock-frequency = <400000>;
pmic_wl2866d_1:wl2866d_1@28 {
compatible = "willsemi,wl2866d";
reg = <0x28>;
status = "okay";
regulators {
dvdd1_mipicsi1_reg: dvdd1_mipicsi1 {
regulator-name = "dvdd1_mipicsi1";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1300000>;
};
dvdd2_mipicsi1_reg: dvdd2_mipicsi1 {
regulator-name = "dvdd2_mipicsi1";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
avdd1_mipicsi1_reg: avdd1_mipicsi1 {
regulator-name = "avdd1_mipicsi1";
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <3300000>;
};
avdd2_mipicsi1_reg: avdd2_mipicsi1 {
regulator-name = "avdd2_mipicsi1";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
};
};
}; };
&aoi2c1 { &aoi2c1 {
@@ -641,33 +1006,99 @@
clock-frequency = <400000>; clock-frequency = <400000>;
status = "okay"; status = "okay";
aw9535_0: gpio@20 { aw9535_0: gpio@20 {
compatible = "awinic,aw9535"; compatible = "awinic,aw9535";
reg = <0x20>; reg = <0x20>;
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
ngpios = <16>; ngpios = <16>;
interrupt-parent = <&ao_gpio1>; interrupt-parent = <&ao_gpio1>;
interrupts = <2 IRQ_TYPE_LEVEL_LOW>; interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
gpio-line-names = gpio-line-names =
"CSI1_PWDN_IO0", "CSI1_RST_IO1", "CSI1_FSIN_IO2", "CSI0_PWDN_IO3", // index 0..3 "CSI1_PWDN_IO0", "CSI1_RST_IO1", "CSI1_FSIN_IO2", "CSI0_PWDN_IO3", // index 0..3
"CSI0_RST_IO4", "CSI0_FSIN_IO5", "MINPCIE_1V5POWER_EN_I06", "MINPCIE_3V3_PWREN_I07",// index 4..7 "CSI0_RST_IO4", "CSI0_FSIN_IO5", "MINPCIE_1V5POWER_EN_I06", "MINPCIE_3V3_PWREN_I07",// index 4..7
"NULL_I08", "M2_SATA_EN_IO9", "AUDIO_ADC0_INT_IO10", "HP_CTL_H_IO11", // index 8..11 "NULL_I08", "M2_SATA_EN_IO9", "AUDIO_ADC0_INT_IO10", "HP_CTL_H_IO11", // index 8..11
"PI6C557_EN_IO12","DISP_RST_IO13","M2_SATA_3V3_PWREN_IO14","MINPCIE_PERST_IO15"; // index 12..15 "PI6C557_EN_IO12","DISP_RST_IO13","M2_SATA_3V3_PWREN_IO14","MINPCIE_PERST_IO15"; // index 12..15
}; };
aw9535_1: gpio@21 { aw9535_1: gpio@21 {
compatible = "awinic,aw9535"; compatible = "awinic,aw9535";
reg = <0x21>; reg = <0x21>;
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
ngpios = <16>; ngpios = <16>;
gpio-line-names = gpio-line-names =
"PCIE_ETH_PERSTB_IO0", "AUDIO_3V3_PWREN_IO1", "AUDIO_1V8_PWREN_IO2", "MIPI_CSI0_PWREN_IO3", // index 0..3 "PCIE_ETH_PERSTB_IO0", "AUDIO_3V3_PWREN_IO1", "AUDIO_1V8_PWREN_IO2", "MIPI_CSI0_PWREN_IO3", // index 0..3
"MIPI_CSI1_PWREN_IO4", "MIPI_TP_PWREN_IO5", "PCIE_ETH_3V3_PWREN_IO6", "NULL_IO7", // index 4..7 "MIPI_CSI1_PWREN_IO4", "MIPI_TP_PWREN_IO5", "PCIE_ETH_3V3_PWREN_IO6", "NULL_IO7", // index 4..7
"USBCON_PWREN_IO8", "USBCON1_PWREN_IO9", "NULL_IO10", "SDIO_3V3_PWREN_IO11", // index 8..11 "USBCON_PWREN_IO8", "USBCON1_PWREN_IO9", "NULL_IO10", "SDIO_3V3_PWREN_IO11", // index 8..11
"SDIO_1V8_PWREN_IO12","PI6C557_PWREN_IO13","MIPI_DSI_PWREN_IO14","BL_EN_IO15"; // index 12..15 "SDIO_1V8_PWREN_IO12","PI6C557_PWREN_IO13","MIPI_DSI_PWREN_IO14","BL_EN_IO15"; // index 12..15
}; };
fusb302: typec-portc@22 {
compatible = "fcs,fusb302";
reg = <0x22>;
interrupt-parent = <&ao_gpio0>;
interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&usbc0_int>;
vbus-supply = <&reg_usb_typec_vbus>;
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
usbc0_role_sw: endpoint@0 {
remote-endpoint = <&dwc3_0_role_switch>;
};
};
};
connector {
compatible = "usb-c-connector";
label = "USB-C";
data-role = "dual";
power-role = "dual";
try-power-role = "sink";
op-sink-microwatt = <1000000>;
sink-pdos =
<PDO_FIXED(5000, 1000, PDO_FIXED_USB_COMM)>;
source-pdos =
<PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
altmodes {
#address-cells = <1>;
#size-cells = <0>;
altmode@0 {
reg = <0>;
svid = <0xff01>;
vdo = <0xffffffff>;
};
};
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
usbc0_orien_sw: endpoint {
remote-endpoint = <&usbdp_phy0_orientation_switch>;
};
};
port@1 {
reg = <1>;
dp_altmode_mux: endpoint {
remote-endpoint = <&usbdp_phy0_dp_altmode_mux>;
};
};
};
};
};
}; };
&uart4 { &uart4 {
@@ -678,6 +1109,16 @@
&uart5 { &uart5 {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&uart5_pins>; pinctrl-0 = <&uart5_pins>;
/*
bluetooth {
compatible = "realtek,rtl8822cs-bt";
pinctrl-names = "default";
pinctrl-0 = <&bt_reset>, <&bt_wake_host>, <&bt_wake_dev>;
enable-gpios = <&ao_gpio1 4 GPIO_ACTIVE_HIGH>;
host-wake-gpios = <&ao_gpio0 30 GPIO_ACTIVE_HIGH>;
device-wake-gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
};
*/
}; };
&uart8 { &uart8 {
@@ -688,6 +1129,7 @@
&rp3x1 { &rp3x1 {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pcie_x1_pins>; pinctrl-0 = <&pcie_x1_pins>;
status = "okay";
}; };
&dm3x4 { &dm3x4 {
@@ -717,11 +1159,6 @@
pinctrl-0 = <&pwm1_pins>; pinctrl-0 = <&pwm1_pins>;
}; };
&can0 {
pinctrl-names = "default";
pinctrl-0 = <&can0_pins>;
};
&hdmi_tx { &hdmi_tx {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&hdmi_pins>; pinctrl-0 = <&hdmi_pins>;
@@ -734,16 +1171,15 @@
&emmc { &emmc {
max-frequency = <196608000>; max-frequency = <196608000>;
non-removable; non-removable;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v; mmc-hs400-1_8v;
cap-mmc-highspeed; mmc-hs200-1_8v;
io_fixed_1v8; io_fixed_1v8;
is_emmc; is_emmc;
no-sdio; no-sdio;
no-sd; no-sd;
pull_up; pull_up;
bus-width = <8>; bus-width = <8>;
cap-mmc-highspeed;
}; };
&sdhci0 { &sdhci0 {
@@ -761,15 +1197,170 @@
post-power-on-delay-ms = <200>; post-power-on-delay-ms = <200>;
wprtn_ignore; wprtn_ignore;
wakeup-source; wakeup-source;
vmmc-supply = <&wifi_vdd_3v3>;
vqmmc-supply = <&wifi_vdd_1v8>;
mmc-pwrseq = <&wifi_pwrseq>;
rtl8822cs: wifi@1 {
interrupt-parent = <&ao_gpio1>;
interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "host-wake";
};
}; };
&usb20_zhihe { &usb20phy0 {
usb21-pwren-gpios = <&aw9535_1 8 GPIO_ACTIVE_HIGH>; pwren-gpios = <&aw9535_1 8 GPIO_ACTIVE_HIGH>;
usb20-pwren-gpios = <&aw9535_1 9 GPIO_ACTIVE_HIGH>; };
&usb20phy1 {
pwren-gpios = <&aw9535_1 9 GPIO_ACTIVE_HIGH>;
};
&sata {
status = "okay";
};
&e16phy {
init-seq-select = "pcie_dmx1_rpx1_satax2";
base-en-gpios = <&aw9535_0 12 GPIO_ACTIVE_HIGH>, // pcie-clk, sata-clk
<&aw9535_1 13 GPIO_ACTIVE_HIGH>; // pcie-clk-pwren, sata-clk-pwren
sata-en-gpios = <&aw9535_0 14 GPIO_ACTIVE_HIGH>, // m2-sata-3v3-pwren
<&aw9535_0 9 GPIO_ACTIVE_HIGH>; // m2-sata-en
pcie-en-gpios = <&aw9535_0 6 GPIO_ACTIVE_HIGH>, // minipcie-1v5-pwren
<&aw9535_0 7 GPIO_ACTIVE_HIGH>, // minipcie-3v3-pwren
<&aw9535_0 15 GPIO_ACTIVE_HIGH>; // minipcie-perst
};
&mipi0_csi0 {
status = "disabled";
};
&mipi0_csi1 {
//combination 4lane mode: host addr; aphy ctrl addr; bphy ctrl addr; mipi_ctrl addr
reg = < 0x00 0x06310000 0x0 0x10000
0x00 0x063a0020 0x0 0x4
0x00 0x063a0024 0x0 0x4
0x00 0x063a0028 0x0 0x4>;
phy_name = "CSI_4LANE"; //combination 4lane
};
//config dsi display: dpu_disp0->dup_enc0->dsi0->lcd_plane
&dsi_enc_out {
remote-endpoint = <&dsi0_in>;
};
&dsi_host0 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi0_in: endpoint {
remote-endpoint = <&dsi_enc_out>;
};
};
port@1 {
reg = <1>;
dsi0_out: endpoint {
remote-endpoint = <&panel0_in>;
};
};
};
panel0@0 {
compatible = "jadard,jd9365da-h3";
reg = <0>;
backlight = <&lcd0_backlight>;
reset-gpio = <&aw9535_0 13 0>; /* active low */
hsvcc-supply = <&reg_vdd33_lcd0>;
vspn3v3-supply = <&reg_vddtp33_lcd0>;
port {
panel0_in: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
&c920_4 {
dvdd-cpu-p-supply = <&dvdd_cpu_p_reg>;
};
&c908_0 {
dvdd-cpu-supply = <&dvdd_cpu_reg>;
dvddm-cpu-supply = <&dvddm_cpu_reg>;
};
&power_gpu {
pmic-supply = <&dvdd_gpu_reg>;
};
&power_npu_wrapper {
pmic-supply = <&dvdd_npu_vip_reg>;
};
&power_vp_wrapper {
pmic-supply = <&dvdd_vp_reg>;
};
&venc {
dvdd-supply = <&dvdd_vp_reg>;
};
&vdec {
dvdd-supply = <&dvdd_vp_reg>;
};
&g2d {
dvdd-supply = <&dvdd_vp_reg>;
};
&gpu {
dvdd-supply = <&dvdd_gpu_reg>;
}; };
&usb3 { &usb3 {
pinctrl-names = "default"; dr_mode = "otg";
pinctrl-0 = <&usb3_pins>; usb-role-switch;
typec-pwren-gpios = <&gpio0_porta 27 GPIO_ACTIVE_HIGH>;
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
dwc3_0_role_switch: endpoint@0 {
reg = <0>;
remote-endpoint = <&usbc0_role_sw>;
};
};
};
&dp0 {
force-hpd = <1>;
extcon = <&usb31_c10phy>;
};
/* USB3.1/DP Combo PHY0 */
&usb31_c10phy {
orientation-switch;
mode-switch;
status = "okay";
svid = <0xff01>;
#extcon-cells = <0>;
port {
#address-cells = <1>;
#size-cells = <0>;
usbdp_phy0_orientation_switch: endpoint@0 {
reg = <0>;
remote-endpoint = <&usbc0_orien_sw>;
};
usbdp_phy0_dp_altmode_mux: endpoint@1 {
reg = <1>;
remote-endpoint = <&dp_altmode_mux>;
};
};
}; };

View File

@@ -70,7 +70,7 @@
}; };
&clk { &clk {
compatible = "zhihe,p100-clk-emu"; compatible = "zhihe,a210-clk-emu";
}; };
&vidmem { &vidmem {
@@ -78,62 +78,6 @@
memory-region = <&framebuffer>; memory-region = <&framebuffer>;
}; };
&vp_dfmu_iommu {
status = "disabled";
};
&vp_dfmu_mt {
status = "disabled";
};
&npu_dfmu_iommu {
status = "disabled";
};
&npu_dfmu_mt {
status = "disabled";
};
&vi_dfmu_iommu {
status = "disabled";
};
&vi_dfmu_mt {
status = "disabled";
};
&vo_dfmu_iommu {
status = "disabled";
};
&vo_dfmu_mt {
status = "disabled";
};
&peri1_dfmu_iommu {
status = "okay";
};
&peri1_dfmu_mt {
status = "disabled";
};
&pcie_dfmu_iommu {
status = "okay";
};
&pcie_dfmu_mt {
status = "disabled";
};
&usb_dfmu_iommu {
status = "okay";
};
&usb_dfmu_mt {
status = "disabled";
};
/* /*
* The reference frequency of the serial is limited and cannot be modified. * The reference frequency of the serial is limited and cannot be modified.
* To ensure normal printing through the serial port, * To ensure normal printing through the serial port,

View File

@@ -1,844 +0,0 @@
/dts-v1/;
#include "a210-soc-core.dtsi"
#include "a210-soc-peri.dtsi"
#include "a210-platform-evb.dtsi"
#define SOUND_CARD_LINK(REG, FMT, CPU, M, CODEC, N) \
simple-audio-card,dai-link@##REG { \
reg = <REG>; \
format = #FMT; \
cpu { \
sound-dai = <&audio_##CPU M>; \
}; \
codec { \
sound-dai = <&codec_##CODEC N>; \
}; \
}
/ {
model = "A210 EVB configuration";
aliases {
ethernet0 = &gmac0;
ethernet1 = &gmac1;
gpio0 = &gpio0;
gpio1 = &gpio1;
gpio2 = &gpio2;
gpio3 = &gpio3;
gpio4 = &gpio4;
i2c0 = &i2c0;
i2c1 = &i2c1;
i2c2 = &i2c2;
i2c3 = &i2c3;
i2c4 = &i2c4;
i2c5 = &i2c5;
i2c6 = &i2c6;
i2c7 = &i2c7;
can0 = &can0;
can1 = &can1;
can2 = &can2;
mmc0 = &emmc;
mmc1 = &sdhci0;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
serial3 = &uart3;
serial4 = &uart4;
serial5 = &uart5;
serial6 = &uart6;
serial7 = &uart7;
serial8 = &uart8;
serial9 = &uart9;
spi0 = &qspi0;
spi1 = &qspi1;
spi2 = &spi0;
spi3 = &spi1;
pcie3x4 = &dm3x4;
pcie3x1 = &rp3x1;
};
/* The first 2M will be reserved in the Kernel, and the entire available range is set here */
memory@0 {
device_type = "memory";
reg = <0x00 0x80000000 0x01 0x00000000>; /* 4G - 64MB */
numa-node-id = <0>;
};
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0x00 0x4000000>;
alloc-ranges = <0x00 0x90000000 0x00 0x4000000>;
linux,cma-default;
};
memory@1c000000 {
reg = <0x00 0x1c000000 0x00 0x2000000>;
no-map;
};
framebuffer: framebuffer@10000000 {
reg = <0x01 0x00 0x00 0x20000000>;
no-map;
};
zh_videomem@100000000 {
reg = <0x01 0x00 0x00 0x20000000>;
no-map;
};
npu_mmu_memory@130000000 {
reg = <0x01 0x30000000 0x00 0x04000000>;
no-map;
};
memblock-memory@17b800000 {
reg = <0x01 0x7b800000 0x00 0x04000000>;
no-map;
};
};
/* The bootargs in U-Boot will override the configuration set here. */
chosen {
stdout-path = "serial4";
};
};
&peri1_padctrl {
gmac0_pins: gmac0-0 {
tx-pins {
pins = "GPIO0_0", /* GMAC0_TX_CLK */
"GPIO0_2", /* GMAC0_TXEN */
"GPIO0_3", /* GMAC0_TXD0 */
"GPIO0_4", /* GMAC0_TXD1 */
"GPIO0_5", /* GMAC0_TXD2 */
"GPIO0_6"; /* GMAC0_TXD3 */
function = "gmac0";
bias-disable;
drive-strength = <25>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO0_1", /* GMAC0_RX_CLK */
"GPIO0_7", /* GMAC0_RXDV */
"GPIO0_8", /* GMAC0_RXD0 */
"GPIO0_9", /* GMAC0_RXD1 */
"GPIO0_10", /* GMAC0_RXD2 */
"GPIO0_11"; /* GMAC0_RXD3 */
function = "gmac0";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-disable;
slew-rate = <0>;
};
};
mdio0_pins: mdio0-0 {
mdc-pins {
pins = "GPIO0_12"; /* GMAC0_MDC */
function = "gmac0";
bias-disable;
drive-strength = <13>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
mdio-pins {
pins = "GPIO0_13"; /* GMAC0_MDIO */
function = "gmac0";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c0_pins: i2c0-1 {
i2c-pins {
pins = "GPIO0_24", "GPIO0_25";
function = "i2c0";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c1_pins: i2c1-1 {
i2c-pins {
pins = "GPIO0_26", "GPIO0_27";
function = "i2c1";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
pcie_x1_pins: pcie_x1-1 {
pcie_x1-pins {
pins = "GPIO0_24", "GPIO0_25", "GPIO0_26", "GPIO0_27";
function = "pcie_x1";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
pcie_x4_pins: pcie_x4-1 {
pcie_x4-pins {
pins = "GPIO0_28", "GPIO0_29", "GPIO0_30", "GPIO0_31";
function = "pcie_x4";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
gmac1_pins: gmac1-0 {
tx-pins {
pins = "GPIO1_2", /* GMAC1_TX_CLK */
"GPIO1_4", /* GMAC1_TXEN */
"GPIO1_5", /* GMAC1_TXD0 */
"GPIO1_6", /* GMAC1_TXD1 */
"GPIO1_7", /* GMAC1_TXD2 */
"GPIO1_8"; /* GMAC1_TXD3 */
function = "gmac1";
bias-disable;
drive-strength = <25>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO1_3", /* GMAC1_RX_CLK */
"GPIO1_9", /* GMAC1_RXDV */
"GPIO1_10", /* GMAC1_RXD0 */
"GPIO1_11", /* GMAC1_RXD1 */
"GPIO1_12", /* GMAC1_RXD2 */
"GPIO1_13"; /* GMAC1_RXD3 */
function = "gmac1";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-disable;
slew-rate = <0>;
};
};
mdio1_pins: mdio1-0 {
mdc-pins {
pins = "GPIO1_14"; /* GMAC1_MDC */
function = "gmac1";
bias-disable;
drive-strength = <13>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
mdio-pins {
pins = "GPIO1_15"; /* GMAC1_MDIO */
function = "gmac1";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
};
&peri2_padctrl {
uart4_pins: uart4-0 {
tx-pins {
pins = "GPIO2_0";
function = "uart4";
bias-disable;
drive-strength = <3>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO2_1";
function = "uart4";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c5_pins: i2c5-0 {
i2c-pins {
pins = "GPIO2_2", "GPIO2_3";
function = "i2c5";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
uart5_pins: uart5-0 {
tx-pins {
pins = "GPIO2_2";
function = "uart5";
bias-disable;
drive-strength = <3>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO2_3";
function = "uart5";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c6_pins: i2c6-0 {
i2c-pins {
pins = "GPIO2_4", "GPIO2_5";
function = "i2c6";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
uart7_pins: uart7-0 {
tx-pins {
pins = "GPIO2_6";
function = "uart7";
bias-disable;
drive-strength = <3>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO2_7";
function = "uart7";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
// i2c4_pins: i2c4-0 {
// i2c-pins {
// pins = "GPIO2_6", "GPIO2_7";
// function = "i2c4";
// bias-disable;
// drive-strength = <7>;
// input-enable;
// input-schmitt-enable;
// slew-rate = <0>;
// };
// };
i2c7_pins: i2c7-0 {
i2c-pins {
pins = "GPIO2_10", "GPIO2_11";
function = "i2c7";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
spi1_pins: spi1-1 {
spi-pins {
pins = "GPIO2_17", "GPIO2_21", "GPIO2_22";
function = "spi1";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c4_pins: i2c4-2 {
i2c-pins {
pins = "GPIO2_26", "GPIO2_27";
function = "i2c4";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
hdmi_pins: hdmi-0 {
hdmi-pins {
pins = "GPIO2_25", "GPIO2_30", "GPIO2_31";
function = "hdmi";
bias-disable;
drive-strength = <3>;
input-enable;
input-schmitt-disable;
slew-rate = <0>;
};
};
sen_vclk_pins: sen_vclk-1 {
sen_vclk-pins {
pins = "GPIO3_0", "GPIO3_2";
function = "sen_vclk";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
qspi1_pins: qspi1-1 {
qspi-pins {
pins = "GPIO3_2", "GPIO3_5", "GPIO3_6", "GPIO3_7", "GPIO3_8";
function = "qspi1";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
qspi0_pins: qspi0-0 {
qspi-pins {
pins = "GPIO0_18", "GPIO0_20", "GPIO0_21", "GPIO0_22", "GPIO0_23";
function = "qspi0";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c7_smb_pins: i2c7-smb-0 {
i2c-pins {
pins = "GPIO3_6", "GPIO3_7", "GPIO3_8", "GPIO3_9", "GPIO3_10";
function = "i2c7_smb";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
usb31_pins: usb31-0 {
usb31-pins {
pins = "GPIO3_10";
function = "usb31";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
};
&gmac0 {
phy-mode = "rgmii-id";
pinctrl-names = "default";
pinctrl-0 = <&gmac0_pins>;
rx-clk-delay = <0x00>; /* for RGMII */
tx-clk-delay = <0x00>; /* for RGMII */
phy-handle = <&phy0>;
};
&mdio0 {
pinctrl-names = "default";
pinctrl-0 = <&mdio0_pins>;
phy0: ethernet-phy@0 {
reg = <0x0>;
};
};
&gmac1 {
phy-mode = "rgmii-id";
pinctrl-names = "default";
pinctrl-0 = <&gmac1_pins>;
rx-clk-delay = <0x00>; /* for RGMII */
tx-clk-delay = <0x00>; /* for RGMII */
phy-handle = <&phy1>;
status = "okay";
};
&mdio1 {
pinctrl-names = "default";
pinctrl-0 = <&mdio1_pins>;
phy1: ethernet-phy@0 {
reg = <0x0>;
};
};
&spi1 {
cs-gpios = <&gpio2_porta 18 0>;
rx-sample-delay-ns = <10>;
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
status = "okay";
spi_norflash@0 {
status = "disabled";
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <50000000>;
w25q,fast-read;
};
};
&qspi0 {
cs-gpios = <&gpio0_porta 15 0>; // QSPI0_CSN1
// cs-gpios = <&gpio0_porta 19 0>; // QSPI0_CSN0
rx-sample-dly = <4>;
pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
spi-max-frequency = <50000000>;
reg = <0>;
status = "disabled";
};
spi-nandflash@1 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "spi-nand";
spi-max-frequency = <100000000>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reg = <1>;
status = "disabled";
partition@0 {
label = "nand1";
reg = <0x00000000 0x08000000>;
};
};
};
&qspi1 {
cs-gpios = <&gpio2_porta 29 0>;
rx-sample-dly = <4>;
pinctrl-names = "default";
pinctrl-0 = <&qspi1_pins>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
spi-max-frequency = <50000000>;
reg = <0>;
status = "okay";
};
spi-nandflash@1 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "spi-nand";
spi-max-frequency = <100000000>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reg = <1>;
status = "disabled";
partition@0 {
label = "nand1";
reg = <0x00000000 0x08000000>;
};
};
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
clock-frequency = <400000>;
eeprom@50 {
status = "okay";
compatible = "atmel,24c02";
reg = <0x50>;
pagesize = <16>;
};
codec_es8156_dac0: es8156@8 {
compatible = "everest,es8156";
reg = <0x8>;
#sound-dai-cells = <1>;
sound-name-prefix = "ES8156_DAC0";
mclk-sclk-ratio = <4>;
status = "disabled";
};
codec_es7210_adc0: es7210@40 {
compatible = "MicArray_0";
reg = <0x40>;
#sound-dai-cells = <1>;
work-mode = "ES7210_NORMAL_I2S";
channels-max = <2>;
mclk-sclk-ratio = <4>;
sound-name-prefix = "ES7210_ADC0";
status = "disabled";
};
audio_aw87565_pa0: audio_pa0@58 {
compatible = "awinic,aw87565_pa";
reg = <0x58>;
sound-name-prefix = "AW87565_PA0";
status = "disabled";
};
audio_aw87565_pa1: audio_pa1@5b {
compatible = "awinic,aw87565_pa";
reg = <0x5b>;
sound-name-prefix = "AW87565_PA1";
status = "disabled";
};
};
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
clock-frequency = <400000>;
codec_es8156_dac1: es8156@8 {
compatible = "everest,es8156";
reg = <0x8>;
#sound-dai-cells = <1>;
sound-name-prefix = "ES8156_DAC1";
mclk-sclk-ratio = <4>;
status = "disabled";
};
codec_es7210_adc1: es7210@40 {
compatible = "MicArray_1";
reg = <0x40>;
#sound-dai-cells = <1>;
work-mode = "ES7210_NORMAL_I2S";
channels-max = <2>;
mclk-sclk-ratio = <4>;
sound-name-prefix = "ES7210_ADC1";
status = "disabled";
};
audio_aw87565_pa2: audio_pa2@58 {
compatible = "awinic,aw87565_pa";
reg = <0x58>;
sound-name-prefix = "AW87565_PA2";
status = "disabled";
};
audio_aw87565_pa3: audio_pa3@5b {
compatible = "awinic,aw87565_pa";
reg = <0x5b>;
sound-name-prefix = "AW87565_PA3";
status = "disabled";
};
};
&i2c4 {
pinctrl-names = "default";
pinctrl-0 = <&i2c4_pins>;
clock-frequency = <400000>;
};
&i2c5 {
pinctrl-names = "default";
pinctrl-0 = <&i2c5_pins>;
clock-frequency = <400000>;
};
&i2c6 {
pinctrl-names = "default";
pinctrl-0 = <&i2c6_pins>;
clock-frequency = <400000>;
};
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins>;
};
&uart7 {
pinctrl-names = "default";
pinctrl-0 = <&uart7_pins>;
};
&emmc {
max-frequency = <196608000>;
non-removable;
mmc-hs200-1_8v;
io_fixed_1v8;
is_emmc;
no-sdio;
no-sd;
pull_up;
bus-width = <8>;
};
&sdhci0 {
max-frequency = <196608000>;
bus-width = <4>;
pull_up;
wprtn_ignore;
};
&vp_dfmu_iommu {
status = "disabled";
};
&vp_dfmu_mt {
status = "disabled";
};
&npu_dfmu_iommu {
status = "disabled";
};
&npu_dfmu_mt {
status = "disabled";
};
&vi_dfmu_iommu {
status = "disabled";
};
&vi_dfmu_mt {
status = "disabled";
};
&vo_dfmu_iommu {
status = "disabled";
};
&vo_dfmu_mt {
status = "disabled";
};
&peri1_dfmu_iommu {
status = "okay";
};
&peri1_dfmu_mt {
status = "disabled";
};
&pcie_dfmu_iommu {
status = "okay";
};
&pcie_dfmu_mt {
status = "disabled";
};
&usb_dfmu_iommu {
status = "okay";
};
&usb_dfmu_mt {
status = "disabled";
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* FIXME: clk stages overlay to be selected for real SOC. */
/* bringup stage 3: full subsys + high freq */
/* refer to maximum clk freq in p100-soc-core.dtsi */
/* bringup stage 2: full subsys + medium freq*/
&clk_peri {
peri1_spi_ssi_clk_frequency = <220000000>;
peri2_spi_ssi_clk_frequency = <220000000>;
peri1_qspi_ssi_clk_frequency = <220000000>;
peri2_qspi_ssi_clk_frequency = <220000000>;
uart_sclk_frequency = <24000000>;
emmc_ref_clk_frequency = <203076924>;
tee_clk_frequency = <200000000>;
};
&clk_pcie {
pcie_ss_axi_m_aclk_frequency = <240000000>;
};
&clk_npu {
npu_cclk_frequency = <600000000>;
npu_aclk_frequency = <600000000>;
};
&emmc {
max-frequency = <49152000>;
};
&sdhci0 {
max-frequency = <49152000>;
};
/* bringup stage 1: minisys + low freq */
&clk {
top_cfg_aclk_frequency = <165000000>;
top_pclk_frequency = <82500000>;
top_amux_clk_frequency = <240000000>;
iommu_ptw_aclk_frequency = <165000000>;
noc_cclk_frequency = <240000000>;
top_cpusys_bus_clk_frequency = <220000000>;
top_cpusys_pic_clk_frequency = <250000000>;
};
&clk_peri {
peri1_spi_ssi_clk_frequency = <220000000>;
peri2_spi_ssi_clk_frequency = <220000000>;
peri1_qspi_ssi_clk_frequency = <220000000>;
peri2_qspi_ssi_clk_frequency = <220000000>;
uart_sclk_frequency = <24000000>;
emmc_ref_clk_frequency = <203076924>;
peri1_mst_aclk_frequency = <165000000>;
peri3_mst_aclk_frequency = <220000000>;
tee_clk_frequency = <200000000>;
};
&emmc {
max-frequency = <49152000>;
};
&sdhci0 {
max-frequency = <49152000>;
};

View File

@@ -3,13 +3,49 @@
#include "a210-soc-core.dtsi" #include "a210-soc-core.dtsi"
#include "a210-soc-core-die1.dtsi" #include "a210-soc-core-die1.dtsi"
#include "a210-soc-peri.dtsi" #include "a210-soc-peri.dtsi"
#include "a210-soc-peri-die1.dtsi"
#include "a210-platform-d2d.dtsi"
/ { / {
model = "A210 EVB D2D configuration"; model = "A210 EVB D2D configuration";
aliases { aliases {
ethernet0 = &gmac0;
ethernet1 = &gmac1;
gpio0 = &ao_gpio0;
gpio1 = &ao_gpio1;
gpio2 = &gpio0;
gpio3 = &gpio1;
gpio4 = &gpio2;
gpio5 = &gpio3;
gpio6 = &gpio4;
gpio7 = &gpio0_die1;
gpio8 = &gpio1_die1;
gpio9 = &gpio2_die1;
gpio10 = &gpio3_die1;
mmc0 = &emmc; mmc0 = &emmc;
mmc1 = &sdhci0;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
serial3 = &uart3;
serial4 = &uart4; serial4 = &uart4;
serial5 = &uart5;
serial6 = &uart6;
serial7 = &uart7;
serial8 = &uart8;
serial9 = &uart9;
serial14 = &uart4_die1;
spi0 = &qspi0;
spi1 = &qspi1;
spi2 = &spi0;
spi3 = &spi1;
spi4 = &qspi0_die1;
spi5 = &qspi1_die1;
}; };
/* The first 2M will be reserved in the Kernel, and the entire available range is set here */ /* The first 2M will be reserved in the Kernel, and the entire available range is set here */
@@ -58,6 +94,11 @@
no-map; no-map;
}; };
npu1_mmu_memory@2130000000 {
reg = <0x21 0x30000000 0x00 0x04000000>;
no-map;
};
memblock-memory@17b800000 { memblock-memory@17b800000 {
reg = <0x01 0x7b800000 0x00 0x04000000>; reg = <0x01 0x7b800000 0x00 0x04000000>;
no-map; no-map;
@@ -70,330 +111,306 @@
}; };
}; };
&uart0 { /* DIE0 */
status = "disabled"; &peri1_padctrl {
gmac0_pins: gmac0-0 {
txclk-pins {
pins = "GPIO0_0", /* GMAC0_TX_CLK */
"GPIO0_12"; /* GMAC0_MDC */
function = "gmac0";
bias-disable;
drive-strength = <13>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
tx-pins {
pins = "GPIO0_2", /* GMAC0_TXEN */
"GPIO0_3", /* GMAC0_TXD0 */
"GPIO0_4", /* GMAC0_TXD1 */
"GPIO0_5", /* GMAC0_TXD2 */
"GPIO0_6"; /* GMAC0_TXD3 */
function = "gmac0";
bias-disable;
drive-strength = <20>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO0_1", /* GMAC0_RX_CLK */
"GPIO0_7", /* GMAC0_RXDV */
"GPIO0_8", /* GMAC0_RXD0 */
"GPIO0_9", /* GMAC0_RXD1 */
"GPIO0_10", /* GMAC0_RXD2 */
"GPIO0_11", /* GMAC0_RXD3 */
"GPIO0_13"; /* GMAC0_MDIO */
function = "gmac0";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-disable;
slew-rate = <0>;
};
};
qspi0_pins: qspi0-0 {
qspi-pins {
pins = "GPIO0_18", "GPIO0_20", "GPIO0_21", "GPIO0_22", "GPIO0_23";
function = "qspi0";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
sdhci_pins: sdhci0-1 {
sd-pins {
pins = "GPIO1_0";
function = "sdio";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
}; };
&uart1 { &peri2_padctrl {
status = "disabled"; uart4_pins: uart4-0 {
tx-pins {
pins = "GPIO2_0";
function = "uart4";
bias-disable;
drive-strength = <3>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO2_1";
function = "uart4";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
hdmi_pins: hdmi-0 {
hdmi-pins {
pins = "GPIO2_25", "GPIO2_30", "GPIO2_31";
function = "hdmi";
bias-disable;
drive-strength = <3>;
input-enable;
input-schmitt-disable;
slew-rate = <0>;
};
};
qspi1_pins: qspi1-1 {
qspi-pins {
pins = "GPIO3_2", "GPIO3_5", "GPIO3_6", "GPIO3_7", "GPIO3_8";
function = "qspi1";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
}; };
&uart3 { &gmac0 {
status = "disabled"; phy-mode = "rgmii-id";
pinctrl-names = "default";
pinctrl-0 = <&gmac0_pins>;
rx-clk-delay = <0x00>; /* for RGMII */
tx-clk-delay = <0x00>; /* for RGMII */
phy-handle = <&phy0>;
};
&mdio0 {
phy0: ethernet-phy@0 {
reg = <0x0>;
};
};
&qspi0 {
cs-gpios = <&gpio0 19 0>;
rx-sample-dly = <2>;
spi-swap-data = <1>;
spi-max-frequency = <42000000>;
pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <42000000>;
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reg = <0>;
status = "okay";
};
};
&qspi1 {
cs-gpios = <&gpio2 29 0>;
rx-sample-dly = <2>;
spi-swap-data = <1>;
spi-max-frequency = <42000000>;
pinctrl-names = "default";
pinctrl-0 = <&qspi1_pins>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <42000000>;
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reg = <0>;
status = "okay";
};
}; };
&uart4 { &uart4 {
current-speed = <115200>; /* OpenSBI */ current-speed = <115200>; /* OpenSBI */
}; pinctrl-names = "default";
pinctrl-0 = <&uart4_pins>;
&uart5 {
status = "disabled";
};
&uart6 {
status = "disabled";
};
&uart7 {
status = "disabled";
};
&uart8 {
status = "disabled";
};
&uart9 {
status = "disabled";
};
&spi0 {
status = "disabled";
};
&qspi0 {
status = "disabled";
};
&i2c1 {
status = "disabled";
};
&i2c2 {
status = "disabled";
};
&i2c3 {
status = "disabled";
};
&i2c5 {
status = "disabled";
};
&i2c6 {
status = "disabled";
};
&i2c7 {
status = "disabled";
};
&pwm0 {
status = "disabled";
};
&pwm2 {
status = "disabled";
};
&audio_i2s2 {
status = "disabled";
};
&audio_i2s_8ch_sd1 {
status = "disabled";
};
&audio_i2s_8ch_sd2 {
status = "disabled";
};
&audio_i2s_8ch_sd3 {
status = "disabled";
};
&peri3_padctrl {
status = "disabled";
};
&gpio4 {
status = "disabled";
};
&gmac1 {
status = "disabled";
};
/* FIXME: Disabled non-critical peripherals in the bringup phase */
&can0 {
status = "disabled";
};
&can1 {
status = "disabled";
};
&can2 {
status = "disabled";
};
&dmac1 {
status = "disabled";
};
&uart2 {
status = "disabled";
};
&timer0 {
status = "disabled";
};
&timer1 {
status = "disabled";
};
&timer3 {
status = "disabled";
};
&timer4 {
status = "disabled";
};
&timer5 {
status = "disabled";
};
&timer6 {
status = "disabled";
};
&timer7 {
status = "disabled";
};
&i2c4 {
status = "disabled";
};
&audio_i2s0 {
status = "disabled";
};
&dm3x4 {
status = "disabled";
};
&rp3x1 {
status = "disabled";
};
&usb31_zhihe {
status = "disabled";
};
&gmac0 {
status = "disabled";
};
&mdio0 {
status = "disabled";
};
&gmac1 {
status = "disabled";
};
&mdio1 {
status = "disabled";
};
&audio_i2s0 {
status = "disabled";
};
&spi0 {
status = "disabled";
};
&spi1 {
status = "disabled";
};
&rp3x1 {
status = "disabled";
};
&audio_i2s2 {
status = "disabled";
};
&audio_pdm0 { // Load the module using insmod
status = "disabled";
};
&pwm1 {
status = "disabled";
};
&sata {
status = "disabled";
}; };
&hdmi_tx { &hdmi_tx {
status = "disabled"; pinctrl-names = "default";
pinctrl-0 = <&hdmi_pins>;
}; };
&emmc { &emmc {
max-frequency = <196608000>; max-frequency = <196608000>;
non-removable; non-removable;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v; mmc-hs400-1_8v;
cap-mmc-highspeed; mmc-hs200-1_8v;
io_fixed_1v8; io_fixed_1v8;
is_emmc; is_emmc;
no-sdio; no-sdio;
no-sd; no-sd;
pull_up; pull_up;
bus-width = <8>; bus-width = <8>;
cap-mmc-highspeed;
clk-delay-mmc-hs200 = <60>;
}; };
&sdhci0 { &sdhci0 {
status = "disabled"; pinctrl-names = "default";
pinctrl-0 = <&sdhci_pins>;
max-frequency = <196608000>;
cap-sd-highspeed;
bus-width = <4>;
sd-uhs-sdr104;
no-sdio;
pull_up;
wprtn_ignore;
}; };
&adc { /* DIE1 */
status = "disabled"; &peri1_padctrl_die1 {
qspi0_pins_die1: qspi0-0 {
qspi-pins {
pins = "GPIO0_18", "GPIO0_20", "GPIO0_21", "GPIO0_22", "GPIO0_23";
function = "qspi0";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
}; };
&vp_dfmu_iommu { &peri2_padctrl_die1 {
status = "disabled"; uart4_pins_die1: uart4-0 {
tx-pins {
pins = "GPIO2_0";
function = "uart4";
bias-disable;
drive-strength = <3>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO2_1";
function = "uart4";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
qspi1_pins_die1: qspi1-1 {
qspi-pins {
pins = "GPIO3_2", "GPIO3_5", "GPIO3_6", "GPIO3_7", "GPIO3_8";
function = "qspi1";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
}; };
&vp_dfmu_mt { &qspi0_die1 {
status = "disabled"; cs-gpios = <&gpio0_die1 19 0>;
rx-sample-dly = <2>;
spi-swap-data = <1>;
spi-max-frequency = <42000000>;
pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins_die1>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <42000000>;
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reg = <0>;
status = "okay";
};
}; };
&npu_dfmu_iommu { &qspi1_die1 {
status = "disabled"; cs-gpios = <&gpio2_die1 29 0>;
rx-sample-dly = <2>;
spi-swap-data = <1>;
spi-max-frequency = <42000000>;
pinctrl-names = "default";
pinctrl-0 = <&qspi1_pins_die1>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <42000000>;
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reg = <0>;
status = "okay";
};
}; };
&npu_dfmu_mt { &uart4_die1 {
status = "disabled"; current-speed = <115200>;
}; pinctrl-names = "default";
pinctrl-0 = <&uart4_pins_die1>;
&vi_dfmu_iommu {
status = "disabled";
};
&vi_dfmu_mt {
status = "disabled";
};
&vo_dfmu_iommu {
status = "disabled";
};
&vo_dfmu_mt {
status = "disabled";
};
&peri1_dfmu_iommu {
status = "okay";
};
&peri1_dfmu_mt {
status = "disabled";
};
&pcie_dfmu_iommu {
status = "disabled";
};
&pcie_dfmu_mt {
status = "disabled";
};
&usb_dfmu_iommu {
status = "okay";
};
&usb_dfmu_mt {
status = "disabled";
};
&vidmem {
status = "disabled";
};
&usb2_0 {
status = "disabled";
};
&gpio0 {
status = "disabled";
};
&gpio1 {
status = "disabled";
};
&gpio2 {
status = "disabled";
};
&gpio3 {
status = "disabled";
};
&gpio4 {
status = "disabled";
}; };

View File

@@ -1,820 +0,0 @@
/dts-v1/;
#include "a210-soc-core.dtsi"
#include "a210-soc-peri.dtsi"
#include "a210-platform-evb.dtsi"
#define SOUND_CARD_LINK(REG, FMT, CPU, M, CODEC, N) \
simple-audio-card,dai-link@##REG { \
reg = <REG>; \
format = #FMT; \
cpu { \
sound-dai = <&audio_##CPU M>; \
}; \
codec { \
sound-dai = <&codec_##CODEC N>; \
}; \
}
/ {
model = "A210 EVB configuration";
aliases {
ethernet0 = &gmac0;
ethernet1 = &gmac1;
mmc0 = &emmc;
mmc1 = &sdhci0;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
serial3 = &uart3;
serial4 = &uart4;
serial5 = &uart5;
serial6 = &uart6;
serial7 = &uart7;
serial8 = &uart8;
serial9 = &uart9;
spi0 = &qspi0;
spi1 = &qspi1;
spi2 = &spi0;
spi3 = &spi1;
pcie3x4 = &dm3x4;
pcie3x1 = &rp3x1;
};
/* The first 2M will be reserved in the Kernel, and the entire available range is set here */
memory@0 {
device_type = "memory";
reg = <0x00 0x80000000 0x01 0x00000000>; /* 4G - 64MB */
numa-node-id = <0>;
};
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0x00 0x4000000>;
alloc-ranges = <0x00 0x90000000 0x00 0x4000000>;
linux,cma-default;
};
memory@1c000000 {
reg = <0x00 0x1c000000 0x00 0x2000000>;
no-map;
};
framebuffer: framebuffer@10000000 {
reg = <0x01 0x00 0x00 0x20000000>;
no-map;
};
zh_videomem@100000000 {
reg = <0x01 0x00 0x00 0x20000000>;
no-map;
};
npu_mmu_memory@130000000 {
reg = <0x01 0x30000000 0x00 0x04000000>;
no-map;
};
memblock-memory@17b800000 {
reg = <0x01 0x7b800000 0x00 0x04000000>;
no-map;
};
};
/* The bootargs in U-Boot will override the configuration set here. */
chosen {
stdout-path = "serial4";
};
};
&peri1_padctrl {
gmac0_pins: gmac0-0 {
tx-pins {
pins = "GPIO0_0", /* GMAC0_TX_CLK */
"GPIO0_2", /* GMAC0_TXEN */
"GPIO0_3", /* GMAC0_TXD0 */
"GPIO0_4", /* GMAC0_TXD1 */
"GPIO0_5", /* GMAC0_TXD2 */
"GPIO0_6"; /* GMAC0_TXD3 */
function = "gmac0";
bias-disable;
drive-strength = <25>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO0_1", /* GMAC0_RX_CLK */
"GPIO0_7", /* GMAC0_RXDV */
"GPIO0_8", /* GMAC0_RXD0 */
"GPIO0_9", /* GMAC0_RXD1 */
"GPIO0_10", /* GMAC0_RXD2 */
"GPIO0_11"; /* GMAC0_RXD3 */
function = "gmac0";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-disable;
slew-rate = <0>;
};
};
mdio0_pins: mdio0-0 {
mdc-pins {
pins = "GPIO0_12"; /* GMAC0_MDC */
function = "gmac0";
bias-disable;
drive-strength = <13>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
mdio-pins {
pins = "GPIO0_13"; /* GMAC0_MDIO */
function = "gmac0";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
qspi0_pins: qspi0-0 {
qspi-pins {
pins = "GPIO0_18", "GPIO0_20", "GPIO0_21", "GPIO0_22", "GPIO0_23";
function = "qspi0";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
can0_pins: can0-0 {
can-pins {
pins = "GPIO0_24", "GPIO0_25";
function = "can0";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
can1_pins: can1-0 {
can-pins {
pins = "GPIO0_26", "GPIO0_27";
function = "can1";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
spi0_pins: spi0-0 {
spi-pins {
pins = "GPIO0_28", "GPIO0_29", "GPIO1_1";
function = "spi0";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
gmac1_pins: gmac1-0 {
tx-pins {
pins = "GPIO1_2", /* GMAC1_TX_CLK */
"GPIO1_4", /* GMAC1_TXEN */
"GPIO1_5", /* GMAC1_TXD0 */
"GPIO1_6", /* GMAC1_TXD1 */
"GPIO1_7", /* GMAC1_TXD2 */
"GPIO1_8"; /* GMAC1_TXD3 */
function = "gmac1";
bias-disable;
drive-strength = <25>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO1_3", /* GMAC1_RX_CLK */
"GPIO1_9", /* GMAC1_RXDV */
"GPIO1_10", /* GMAC1_RXD0 */
"GPIO1_11", /* GMAC1_RXD1 */
"GPIO1_12", /* GMAC1_RXD2 */
"GPIO1_13"; /* GMAC1_RXD3 */
function = "gmac1";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-disable;
slew-rate = <0>;
};
};
mdio1_pins: mdio1-0 {
mdc-pins {
pins = "GPIO1_14"; /* GMAC1_MDC */
function = "gmac1";
bias-disable;
drive-strength = <13>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
mdio-pins {
pins = "GPIO1_15"; /* GMAC1_MDIO */
function = "gmac1";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
};
&peri2_padctrl {
i2c4_pins: i2c4-2 {
i2c-pins {
pins = "GPIO0_26", "GPIO0_27";
function = "i2c4";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
uart4_pins: uart4-0 {
uart-pins {
pins = "GPIO2_0", "GPIO2_1";
function = "uart4";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
uart5_pins: uart5-0 {
uart-pins {
pins = "GPIO2_2", "GPIO2_3";
function = "uart5";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c5_pins: i2c5-0 {
i2c-pins {
pins = "GPIO2_2", "GPIO2_3";
function = "i2c5";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
uart6_pins: uart6-0 {
uart-pins {
pins = "GPIO2_4", "GPIO2_5", "GPIO2_8", "GPIO2_9"; // TXD/RXD/CTSN/RTSN
function = "uart6";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c6_pins: i2c6-0 {
i2c-pins {
pins = "GPIO2_4", "GPIO2_5";
function = "i2c6";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
uart7_pins: uart7-0 {
uart-pins {
pins = "GPIO2_6", "GPIO2_7";
function = "uart7";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
uart9_pins: uart9-0 {
uart-pins {
pins = "GPIO2_10", "GPIO2_11";
function = "uart9";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c7_pins: i2c7-0 {
i2c-pins {
pins = "GPIO2_10", "GPIO2_11";
function = "i2c7";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
pwm1_pins: pwm1 {
pwm-pins {
pins = "GPIO2_12", "GPIO2_28"; // PWM1_CH2-0/PWM1_CH0-1
function = "pwm1";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
spi1_pins: spi1-1 {
spi-pins {
pins = "GPIO2_17", "GPIO2_21", "GPIO2_22";
function = "spi1";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
hdmi_pins: hdmi-0 {
hdmi-pins {
pins = "GPIO2_25", "GPIO2_30", "GPIO2_31";
function = "hdmi";
bias-disable;
drive-strength = <3>;
input-enable;
input-schmitt-disable;
slew-rate = <0>;
};
};
can2_pins: can2-0 {
can-pins {
pins = "GPIO3_0", "GPIO3_1";
function = "can2";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
qspi1_pins: qspi1-1 {
qspi-pins {
pins = "GPIO3_2", "GPIO3_5", "GPIO3_6", "GPIO3_7", "GPIO3_8";
function = "qspi1";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
dptx_pins: dptx-1 {
dptx-pins {
pins = "GPIO3_9";
function = "dptx";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
usb31_pins: usb31-0 {
usb31-pins {
pins = "GPIO3_10";
function = "usb31";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
};
&spi0 {
cs-gpios = <&gpio0_porta 30 0>;
rx-sample-delay-ns = <10>;
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
spi_norflash@0 {
status = "okay";
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <50000000>;
w25q,fast-read;
};
spidev@1 {
status = "disabled";
compatible = "spidev";
#address-cells = <0x1>;
#size-cells = <0x1>;
reg = <0x1>;
spi-max-frequency = <50000000>;
};
};
&spi1 {
cs-gpios = <&gpio2_porta 18 0>;
rx-sample-delay-ns = <10>;
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
spi_norflash@0 {
status = "disabled";
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <50000000>;
w25q,fast-read;
};
};
&qspi0 {
cs-gpios = <&gpio0_porta 19 0>;
rx-sample-dly = <4>;
pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>;
spi_norflash@0 {
status = "disabled";
compatible = "jedec,spi-nor";
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
spi-max-frequency = <50000000>;
};
spi-nandflash@1 {
status = "disabled";
#address-cells = <1>;
#size-cells = <1>;
compatible = "spi-nand";
spi-max-frequency = <100000000>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reg = <1>;
partition@0 {
label = "nand0";
reg = <0x00000000 0x08000000>;
};
};
};
&qspi1 {
cs-gpios = <&gpio2_porta 29 0>;
rx-sample-dly = <4>;
pinctrl-names = "default";
pinctrl-0 = <&qspi1_pins>;
spi_norflash@0 {
status = "okay";
compatible = "jedec,spi-nor";
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
spi-max-frequency = <50000000>;
};
spi-nandflash@1 {
status = "disabled";
#address-cells = <1>;
#size-cells = <1>;
compatible = "spi-nand";
spi-max-frequency = <100000000>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reg = <1>;
partition@0 {
label = "nand1";
reg = <0x00000000 0x08000000>;
};
};
};
&emmc {
max-frequency = <196608000>;
non-removable;
mmc-hs200-1_8v;
io_fixed_1v8;
is_emmc;
no-sdio;
no-sd;
pull_up;
bus-width = <8>;
};
&sdhci0 {
max-frequency = <196608000>;
bus-width = <4>;
pull_up;
wprtn_ignore;
};
&gmac0 {
phy-mode = "rgmii-id";
pinctrl-names = "default";
pinctrl-0 = <&gmac0_pins>;
rx-clk-delay = <0x00>; /* for RGMII */
tx-clk-delay = <0x00>; /* for RGMII */
phy-handle = <&phy0>;
};
&mdio0 {
pinctrl-names = "default";
pinctrl-0 = <&mdio0_pins>;
phy0: ethernet-phy@0 {
reg = <0x0>;
};
};
&gmac1 {
phy-mode = "rgmii-id";
pinctrl-names = "default";
pinctrl-0 = <&gmac1_pins>;
rx-clk-delay = <0x00>; /* for RGMII */
tx-clk-delay = <0x00>; /* for RGMII */
phy-handle = <&phy1>;
};
&mdio1 {
pinctrl-names = "default";
pinctrl-0 = <&mdio1_pins>;
phy1: ethernet-phy@1 {
reg = <0x0>;
};
};
&i2c4 {
pinctrl-names = "default";
pinctrl-0 = <&i2c4_pins>;
clock-frequency = <400000>;
};
&i2c5 {
pinctrl-names = "default";
pinctrl-0 = <&i2c5_pins>;
clock-frequency = <400000>;
};
&i2c6 {
pinctrl-names = "default";
pinctrl-0 = <&i2c6_pins>;
clock-frequency = <400000>;
};
&i2c7 {
pinctrl-names = "default";
pinctrl-0 = <&i2c7_pins>;
clock-frequency = <400000>;
};
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins>;
};
&uart5 {
pinctrl-names = "default";
pinctrl-0 = <&uart5_pins>;
};
&uart6 {
pinctrl-names = "default";
pinctrl-0 = <&uart6_pins>;
};
&uart7 {
pinctrl-names = "default";
pinctrl-0 = <&uart7_pins>;
};
&uart9 {
pinctrl-names = "default";
pinctrl-0 = <&uart9_pins>;
};
&pwm1 {
pinctrl-names = "default";
pinctrl-0 = <&pwm1_pins>;
};
&can0 {
pinctrl-names = "default";
pinctrl-0 = <&can0_pins>;
};
&can1 {
pinctrl-names = "default";
pinctrl-0 = <&can1_pins>;
};
&can2 {
pinctrl-names = "default";
pinctrl-0 = <&can2_pins>;
};
&vp_dfmu_iommu {
status = "disabled";
};
&vp_dfmu_mt {
status = "disabled";
};
&npu_dfmu_iommu {
status = "disabled";
};
&npu_dfmu_mt {
status = "disabled";
};
&vi_dfmu_iommu {
status = "disabled";
};
&vi_dfmu_mt {
status = "disabled";
};
&vo_dfmu_iommu {
status = "disabled";
};
&vo_dfmu_mt {
status = "disabled";
};
&peri1_dfmu_iommu {
status = "disabled";
};
&peri1_dfmu_mt {
status = "disabled";
};
&pcie_dfmu_iommu {
status = "disabled";
};
&pcie_dfmu_mt {
status = "disabled";
};
&usb_dfmu_iommu {
status = "disabled";
};
&usb_dfmu_mt {
status = "disabled";
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* FIXME: clk stages overlay to be selected for real SOC. */
/* bringup stage 3: full subsys + high freq */
/* refer to maximum clk freq in p100-soc-core.dtsi */
/* bringup stage 2: full subsys + medium freq*/
&clk_peri {
peri1_spi_ssi_clk_frequency = <220000000>;
peri2_spi_ssi_clk_frequency = <220000000>;
peri1_qspi_ssi_clk_frequency = <220000000>;
peri2_qspi_ssi_clk_frequency = <220000000>;
uart_sclk_frequency = <24000000>;
emmc_ref_clk_frequency = <203076924>;
tee_clk_frequency = <200000000>;
};
&clk_pcie {
pcie_ss_axi_m_aclk_frequency = <240000000>;
};
&clk_npu {
npu_cclk_frequency = <600000000>;
npu_aclk_frequency = <600000000>;
};
&emmc {
max-frequency = <49152000>;
};
&sdhci0 {
max-frequency = <49152000>;
};
/* bringup stage 1: minisys + low freq */
&clk {
top_cfg_aclk_frequency = <165000000>;
top_pclk_frequency = <82500000>;
top_amux_clk_frequency = <240000000>;
iommu_ptw_aclk_frequency = <165000000>;
noc_cclk_frequency = <240000000>;
top_cpusys_bus_clk_frequency = <220000000>;
top_cpusys_pic_clk_frequency = <250000000>;
};
&clk_peri {
peri1_spi_ssi_clk_frequency = <220000000>;
peri2_spi_ssi_clk_frequency = <220000000>;
peri1_qspi_ssi_clk_frequency = <220000000>;
peri2_qspi_ssi_clk_frequency = <220000000>;
uart_sclk_frequency = <24000000>;
emmc_ref_clk_frequency = <203076924>;
peri1_mst_aclk_frequency = <165000000>;
peri3_mst_aclk_frequency = <220000000>;
tee_clk_frequency = <200000000>;
};
&emmc {
max-frequency = <49152000>;
};
&sdhci0 {
max-frequency = <49152000>;
};
&clk_gpu {
status = "disabled";
};
&clk_pcie {
status = "disabled";
};
&clk_usb {
status = "disabled";
};
&clk_vi {
status = "disabled";
};
&clk_vp {
status = "disabled";
};
&clk_vo {
status = "disabled";
};
&clk_npu {
status = "disabled";
};
&clk_d2d {
status = "disabled";
};
&vidmem {
status = "okay";
memory-region = <&framebuffer>;
};

View File

@@ -0,0 +1,2 @@
#include "a210-evb.dts"
#include "a210-sec-tee.dtsi"

View File

@@ -60,6 +60,9 @@
spi3 = &spi1; spi3 = &spi1;
pcie3x4 = &dm3x4; pcie3x4 = &dm3x4;
pcie3x1 = &rp3x1; pcie3x1 = &rp3x1;
vi_sensor0 = &mipicsi0_4lane_port;
vi_sensor1 = &mipi1csi0_b_port;
vi_sensor2 = &mipi1csi1_a_port;
}; };
/* The actual capacity will be adjusted through SPL */ /* The actual capacity will be adjusted through SPL */
@@ -140,76 +143,10 @@
status = "okay"; status = "okay";
}; };
codec_dummy_pdm0: codec_dummy_pdm0 { codec_dmic: dmic-codec {
compatible = "zhihe,dummy-pcm-pdm"; compatible = "dmic-codec";
sound-name-prefix = "DMIC0"; num-channels = <8>;
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>; #sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm1: codec_dummy_pdm1 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC1";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm2: codec_dummy_pdm2 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC2";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm3: codec_dummy_pdm3 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC3";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm4: codec_dummy_pdm4 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC4";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm5: codec_dummy_pdm5 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC5";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm6: codec_dummy_pdm6 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC6";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm7: codec_dummy_pdm7 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC7";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
}; };
Sound_Card@0 { Sound_Card@0 {
@@ -221,10 +158,10 @@
simple-audio-card,widgets = "Speaker", "Speaker"; simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing = simple-audio-card,routing =
"Speaker", "AW87565_PA0 VO", "Speaker", "AW87565_PA0 VO",
"Speaker", "AW87565_PA1 VO", "Speaker", "AW87565_PA1 VO",
"AW87565_PA0 IN", "ES8156_DAC0 LOUT", "AW87565_PA0 IN", "ES8156_DAC0 LOUT",
"AW87565_PA1 IN", "ES8156_DAC0 ROUT"; "AW87565_PA1 IN", "ES8156_DAC0 ROUT";
simple-audio-card,aux-devs = <&audio_aw87565_pa0>, <&audio_aw87565_pa1>; simple-audio-card,aux-devs = <&audio_aw87565_pa0>, <&audio_aw87565_pa1>;
SOUND_CARD_LINK(0, i2s, i2s1, 0, es8156_dac0, 0); /* I2S1 <-> es8156_dac0 */ SOUND_CARD_LINK(0, i2s, i2s1, 0, es8156_dac0, 0); /* I2S1 <-> es8156_dac0 */
SOUND_CARD_LINK(1, i2s, i2s1, 0, es7210_adc0, 0); /* I2S1 <-> es7210_adc0 */ SOUND_CARD_LINK(1, i2s, i2s1, 0, es7210_adc0, 0); /* I2S1 <-> es7210_adc0 */
@@ -239,10 +176,10 @@
simple-audio-card,widgets = "Speaker", "Speaker"; simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing = simple-audio-card,routing =
"Speaker", "AW87565_PA2 VO", "Speaker", "AW87565_PA2 VO",
"Speaker", "AW87565_PA3 VO", "Speaker", "AW87565_PA3 VO",
"AW87565_PA2 IN", "ES8156_DAC1 LOUT", "AW87565_PA2 IN", "ES8156_DAC1 LOUT",
"AW87565_PA3 IN", "ES8156_DAC1 ROUT"; "AW87565_PA3 IN", "ES8156_DAC1 ROUT";
simple-audio-card,aux-devs = <&audio_aw87565_pa2>, <&audio_aw87565_pa3>; simple-audio-card,aux-devs = <&audio_aw87565_pa2>, <&audio_aw87565_pa3>;
SOUND_CARD_LINK(0, i2s, i2s2, 0, es8156_dac1, 0); /* I2S2 <-> es8156_dac1 */ SOUND_CARD_LINK(0, i2s, i2s2, 0, es8156_dac1, 0); /* I2S2 <-> es8156_dac1 */
SOUND_CARD_LINK(1, i2s, i2s2, 0, es7210_adc1, 0); /* I2S2 <-> es7210_adc1 */ SOUND_CARD_LINK(1, i2s, i2s2, 0, es7210_adc1, 0); /* I2S2 <-> es7210_adc1 */
@@ -250,7 +187,7 @@
Sound_Card@2 { Sound_Card@2 {
compatible = "simple-audio-card"; compatible = "simple-audio-card";
simple-audio-card,name = "Sound-Card-I2S3"; simple-audio-card,name = "Sound-Card-HDMI";
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
status = "okay"; status = "okay";
@@ -259,6 +196,19 @@
}; };
Sound_Card@3 { Sound_Card@3 {
compatible = "simple-audio-card";
simple-audio-card,name = "Sound-Card-I2S3";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
SOUND_CARD_LINK(0, left_j, i2s_8ch_sd0, 0, dummy_i2s_8ch, 0); /* I2S3-SD0 <-> HW-Codec */
SOUND_CARD_LINK(1, left_j, i2s_8ch_sd1, 0, dummy_i2s_8ch, 0); /* I2S3-SD1 <-> HW-Codec */
SOUND_CARD_LINK(2, left_j, i2s_8ch_sd2, 0, dummy_i2s_8ch, 0); /* I2S3-SD2 <-> HW-Codec */
SOUND_CARD_LINK(3, left_j, i2s_8ch_sd3, 0, dummy_i2s_8ch, 0); /* I2S3-SD3 <-> HW-Codec */
};
Sound_Card@4 {
compatible = "simple-audio-card"; compatible = "simple-audio-card";
simple-audio-card,name = "Sound-Card-TDM"; simple-audio-card,name = "Sound-Card-TDM";
#address-cells = <1>; #address-cells = <1>;
@@ -266,30 +216,64 @@
status = "okay"; status = "okay";
SOUND_CARD_LINK(0, dsp_b, tdm_slot0, 0, es7210_adc2, 0); /* TDM_SLOT0 <-> es7210_adc2 */ SOUND_CARD_LINK(0, dsp_b, tdm_slot0, 0, es7210_adc2, 0); /* TDM_SLOT0 <-> es7210_adc2 */
SOUND_CARD_LINK(1, dsp_b, tdm_slot1, 0, es7210_adc2, 0); /* TDM_SLOT1 <-> es7210_adc2 */ SOUND_CARD_LINK(1, dsp_b, tdm_slot1, 0, dummy_tdm, 0); /* TDM_SLOT1 <-> es7210_adc2 */
SOUND_CARD_LINK(2, dsp_b, tdm_slot2, 0, es7210_adc2, 0); /* TDM_SLOT2 <-> es7210_adc2 */ SOUND_CARD_LINK(2, dsp_b, tdm_slot2, 0, dummy_tdm, 0); /* TDM_SLOT2 <-> es7210_adc2 */
SOUND_CARD_LINK(3, dsp_b, tdm_slot3, 0, es7210_adc2, 0); /* TDM_SLOT3 <-> es7210_adc2 */ SOUND_CARD_LINK(3, dsp_b, tdm_slot3, 0, dummy_tdm, 0); /* TDM_SLOT3 <-> es7210_adc2 */
SOUND_CARD_LINK(4, dsp_b, tdm_slot4, 0, es7210_adc3, 0); /* TDM_SLOT4 <-> es7210_adc3 */ SOUND_CARD_LINK(4, dsp_b, tdm_slot4, 0, dummy_tdm, 0); /* TDM_SLOT4 <-> es7210_adc3 */
SOUND_CARD_LINK(5, dsp_b, tdm_slot5, 0, es7210_adc3, 0); /* TDM_SLOT5 <-> es7210_adc3 */ SOUND_CARD_LINK(5, dsp_b, tdm_slot5, 0, dummy_tdm, 0); /* TDM_SLOT5 <-> es7210_adc3 */
SOUND_CARD_LINK(6, dsp_b, tdm_slot6, 0, es7210_adc3, 0); /* TDM_SLOT6 <-> es7210_adc3 */ SOUND_CARD_LINK(6, dsp_b, tdm_slot6, 0, dummy_tdm, 0); /* TDM_SLOT6 <-> es7210_adc3 */
SOUND_CARD_LINK(7, dsp_b, tdm_slot7, 0, es7210_adc3, 0); /* TDM_SLOT7 <-> es7210_adc3 */ SOUND_CARD_LINK(7, dsp_b, tdm_slot7, 0, dummy_tdm, 0); /* TDM_SLOT7 <-> es7210_adc3 */
}; };
Sound_Card@4 { Sound_Card@5 {
compatible = "simple-audio-card"; compatible = "simple-audio-card";
simple-audio-card,name = "Sound-Card-PDM"; simple-audio-card,name = "Sound-Card-PDM";
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
status = "okay"; status = "okay";
SOUND_CARD_LINK(0, pdm, pdm0, 0, dummy_pdm0, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(0, pdm, pdm0, 0, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(1, pdm, pdm1, 1, dummy_pdm1, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(1, pdm, pdm1, 1, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(2, pdm, pdm2, 2, dummy_pdm2, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(2, pdm, pdm2, 2, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(3, pdm, pdm3, 3, dummy_pdm3, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(3, pdm, pdm3, 3, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(4, pdm, pdm4, 4, dummy_pdm4, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(4, pdm, pdm4, 4, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(5, pdm, pdm5, 5, dummy_pdm5, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(5, pdm, pdm5, 5, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(6, pdm, pdm6, 6, dummy_pdm6, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(6, pdm, pdm6, 6, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(7, pdm, pdm7, 7, dummy_pdm7, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(7, pdm, pdm7, 7, dmic, 0); /* PDM <-> Dmic */
};
lcd0_backlight: pwm-backlight@0 {
compatible = "pwm-backlight";
status = "disabled";
pwms = <&pwm1 0 100000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <7>;
};
mipicsi0_4lane_port: mipicsi0_4lane_port@0 {
compatible = "zhihe,vi_sensor";
clocks = <&clk SW_TOP_PAD_SENSOR_VCLK0_EN>;
clock-names = "core_clk";
clock-frequency = <24000000>;
pinctrl-names = "default";
pinctrl-0 = <&sen_vclk_pin0>;
status = "okay";
};
mipi1csi0_b_port: mipi1csi0_b_port@0 {
compatible = "zhihe,vi_sensor";
clock-frequency = <24000000>;
status = "okay";
};
mipi1csi1_a_port: mipi1csi1_a_port@0 {
compatible = "zhihe,vi_sensor";
clocks = <&clk SW_TOP_PAD_SENSOR_VCLK1_EN>;
clock-names = "core_clk";
clock-frequency = <24000000>;
pinctrl-names = "default";
pinctrl-0 = <&sen_vclk_pin1>;
status = "okay";
}; };
}; };
@@ -362,14 +346,14 @@
pins = "GPIO0_14", "GPIO0_15", "GPIO0_16", "GPIO0_17", "GPIO0_18"; pins = "GPIO0_14", "GPIO0_15", "GPIO0_16", "GPIO0_17", "GPIO0_18";
function = "i2s0"; function = "i2s0";
bias-disable; bias-disable;
drive-strength = <13>; drive-strength = <20>;
input-schmitt-disable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <0>;
}; };
}; };
sata_p1_pins: sata_p1-0 { sata_p1_pins: sata_p1-0 {
sata_p1-pins { sata_p1-pins {
pins = "GPIO0_14", "GPIO0_15", "GPIO0_16", "GPIO0_17", "GPIO0_18"; pins = "GPIO0_14", "GPIO0_15", "GPIO0_16", "GPIO0_17", "GPIO1_5"; // DEVSLP, MP_SWITCH, CP_DET, CP_POD, ACT_LED
function = "sata_p1"; function = "sata_p1";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <7>;
@@ -412,7 +396,7 @@
}; };
sata_p0_pins: sata_p0-0 { sata_p0_pins: sata_p0-0 {
sata_p0-pins { sata_p0-pins {
pins = "GPIO0_19", "GPIO0_20", "GPIO0_21", "GPIO0_22", "GPIO0_23"; pins = "GPIO0_19", "GPIO0_20", "GPIO0_21", "GPIO0_22", "GPIO0_23"; // DEVSLP, MP_SWITCH, CP_DET, CP_POD, ACT_LED
function = "sata_p0"; function = "sata_p0";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <7>;
@@ -426,10 +410,10 @@
pins = "GPIO0_22", "GPIO0_23"; pins = "GPIO0_22", "GPIO0_23";
function = "i2c2"; function = "i2c2";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
tdm_pins: tdm-0 { tdm_pins: tdm-0 {
@@ -437,7 +421,7 @@
pins = "GPIO0_19", "GPIO0_20", "GPIO0_21"; pins = "GPIO0_19", "GPIO0_20", "GPIO0_21";
function = "tdm"; function = "tdm";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <0>;
@@ -448,10 +432,10 @@
pins = "GPIO0_24", "GPIO0_25"; pins = "GPIO0_24", "GPIO0_25";
function = "i2c0"; function = "i2c0";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
can0_pins: can0-0 { can0_pins: can0-0 {
@@ -480,10 +464,10 @@
pins = "GPIO0_26", "GPIO0_27"; pins = "GPIO0_26", "GPIO0_27";
function = "i2c1"; function = "i2c1";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
can1_pins: can1-0 { can1_pins: can1-0 {
@@ -509,7 +493,7 @@
}; };
pcie_x1_pins: pcie_x1-1 { pcie_x1_pins: pcie_x1-1 {
pcie_x1-pins { pcie_x1-pins {
pins = "GPIO0_24", "GPIO0_25", "GPIO0_26", "GPIO0_27"; pins = "GPIO0_24", "GPIO0_25", "GPIO0_26", "GPIO0_27"; // BTN_RSTN, LKREQN, PERSTN, WAKEN
function = "pcie_x1"; function = "pcie_x1";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <7>;
@@ -555,7 +539,7 @@
pins = "GPIO0_28", "GPIO0_29", "GPIO1_1"; pins = "GPIO0_28", "GPIO0_29", "GPIO1_1";
function = "spi0"; function = "spi0";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <13>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <0>;
@@ -635,7 +619,7 @@
}; };
pdm_pins: pdm-0 { pdm_pins: pdm-0 {
pdm-pins { pdm-pins {
pins = "GPIO1_12", "GPIO1_13", "GPIO1_14", "GPIO1_15"; // PDM_SDIN3(GPIO1_8) conflicts with CHIP_DBG_RXD pins = "GPIO1_8", "GPIO1_12", "GPIO1_13", "GPIO1_14", "GPIO1_15"; // PDM_SDIN3(GPIO1_8) conflicts with CHIP_DBG_RXD
function = "pdm"; function = "pdm";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <7>;
@@ -673,10 +657,10 @@
pins = "GPIO2_2", "GPIO2_3"; pins = "GPIO2_2", "GPIO2_3";
function = "i2c5"; function = "i2c5";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
uart5_pins: uart5-0 { uart5_pins: uart5-0 {
@@ -705,10 +689,10 @@
pins = "GPIO2_4", "GPIO2_5"; pins = "GPIO2_4", "GPIO2_5";
function = "i2c6"; function = "i2c6";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
uart6_pins: uart6-0 { uart6_pins: uart6-0 {
@@ -738,7 +722,7 @@
function = "i2s1"; function = "i2s1";
bias-disable; bias-disable;
drive-strength = <13>; drive-strength = <13>;
input-schmitt-disable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <0>;
}; };
}; };
@@ -800,10 +784,10 @@
// pins = "GPIO2_6", "GPIO2_7"; // pins = "GPIO2_6", "GPIO2_7";
// function = "i2c4"; // function = "i2c4";
// bias-disable; // bias-disable;
// drive-strength = <7>; // drive-strength = <25>;
// input-enable; // input-enable;
// input-schmitt-enable; // input-schmitt-enable;
// slew-rate = <0>; // slew-rate = <1>;
// }; // };
// }; // };
i2s2_pins: i2s2-0 { i2s2_pins: i2s2-0 {
@@ -812,7 +796,7 @@
function = "i2s2"; function = "i2s2";
bias-disable; bias-disable;
drive-strength = <13>; drive-strength = <13>;
input-schmitt-disable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <0>;
}; };
}; };
@@ -842,10 +826,10 @@
pins = "GPIO2_10", "GPIO2_11"; pins = "GPIO2_10", "GPIO2_11";
function = "i2c7"; function = "i2c7";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
spi1_pins: spi1-1 { spi1_pins: spi1-1 {
@@ -853,7 +837,7 @@
pins = "GPIO2_17", "GPIO2_21", "GPIO2_22"; pins = "GPIO2_17", "GPIO2_21", "GPIO2_22";
function = "spi1"; function = "spi1";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <13>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <0>;
@@ -866,7 +850,7 @@
function = "i2s3"; function = "i2s3";
bias-disable; bias-disable;
drive-strength = <13>; drive-strength = <13>;
input-schmitt-disable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <0>;
}; };
}; };
@@ -875,10 +859,10 @@
pins = "GPIO2_26", "GPIO2_27"; pins = "GPIO2_26", "GPIO2_27";
function = "i2c4"; function = "i2c4";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
pwm1_pins: pwm1-1 { pwm1_pins: pwm1-1 {
@@ -897,10 +881,10 @@
pins = "GPIO2_24", "GPIO2_25"; pins = "GPIO2_24", "GPIO2_25";
function = "i2c3"; function = "i2c3";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <25>;
input-enable; input-enable;
input-schmitt-enable; input-schmitt-enable;
slew-rate = <0>; slew-rate = <1>;
}; };
}; };
hdmi_pins: hdmi-0 { hdmi_pins: hdmi-0 {
@@ -914,9 +898,20 @@
slew-rate = <0>; slew-rate = <0>;
}; };
}; };
sen_vclk_pins: sen_vclk-1 { sen_vclk_pin0: sen_vclk0 {
sen_vclk-pins { sen_vclk0-pins {
pins = "GPIO3_0", "GPIO3_1"; pins = "GPIO3_0";
function = "sen_vclk";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
sen_vclk_pin1: sen_vclk1 {
sen_vclk1-pins {
pins = "GPIO3_1";
function = "sen_vclk"; function = "sen_vclk";
bias-disable; bias-disable;
drive-strength = <7>; drive-strength = <7>;
@@ -1047,13 +1042,13 @@
}; };
&spi0 { &spi0 {
cs-gpios = <&gpio0_porta 30 0>; cs-gpios = <&gpio0 30 0>;
rx-sample-delay-ns = <4>; rx-sample-delay-ns = <4>;
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
spi_norflash@0 { spi_norflash@0 {
compatible = "jedec,spi-nor"; compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
reg = <0>; reg = <0>;
@@ -1062,15 +1057,15 @@
}; };
&spi1 { &spi1 {
cs-gpios = <&gpio2_porta 18 0>; cs-gpios = <&gpio2 18 0>;
rx-sample-delay-ns = <4>; rx-sample-delay-ns = <4>;
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>; pinctrl-0 = <&spi1_pins>;
spi_norflash@0 { spi_norflash@0 {
compatible = "jedec,spi-nor"; compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
reg = <0>; reg = <0>;
@@ -1079,16 +1074,16 @@
}; };
&qspi0 { &qspi0 {
cs-gpios = <&gpio0_porta 19 0>; cs-gpios = <&gpio0 19 0>;
rx-sample-dly = <2>; rx-sample-dly = <2>;
spi-swap-data = <1>; spi-swap-data = <1>;
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>; pinctrl-0 = <&qspi0_pins>;
spi_norflash@0 { spi_norflash@0 {
compatible = "jedec,spi-nor"; compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
spi-tx-bus-width = <4>; spi-tx-bus-width = <4>;
@@ -1099,16 +1094,16 @@
}; };
&qspi1 { &qspi1 {
cs-gpios = <&gpio2_porta 29 0>; cs-gpios = <&gpio2 29 0>;
rx-sample-dly = <2>; rx-sample-dly = <2>;
spi-swap-data = <1>; spi-swap-data = <1>;
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&qspi1_pins>; pinctrl-0 = <&qspi1_pins>;
spi_norflash@0 { spi_norflash@0 {
compatible = "jedec,spi-nor"; compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
spi-tx-bus-width = <4>; spi-tx-bus-width = <4>;
@@ -1233,7 +1228,7 @@
work-mode = "ES7210_TDM_1LRCK_DSPB"; work-mode = "ES7210_TDM_1LRCK_DSPB";
channels-max = <8>; channels-max = <8>;
sound-name-prefix = "ES7210_ADC2"; sound-name-prefix = "ES7210_ADC2";
status = "disabled"; status = "okay";
}; };
codec_es7210_adc3: es7210@43 { codec_es7210_adc3: es7210@43 {
@@ -1243,7 +1238,7 @@
work-mode = "ES7210_TDM_1LRCK_DSPB"; work-mode = "ES7210_TDM_1LRCK_DSPB";
channels-max = <8>; channels-max = <8>;
sound-name-prefix = "ES7210_ADC3"; sound-name-prefix = "ES7210_ADC3";
status = "disabled"; status = "okay";
}; };
}; };
@@ -1251,11 +1246,16 @@
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&i2c4_pins>; pinctrl-0 = <&i2c4_pins>;
clock-frequency = <400000>; clock-frequency = <400000>;
status = "okay";
lt8911i2c: lt8911i2c@29{
compatible = "i2c,lt8911";
reg = <0x29>;
};
usbc: fusb302@0 { usbc: fusb302@0 {
compatible = "fcs,fusb302"; compatible = "fcs,fusb302";
reg = <0x0>; reg = <0x0>;
interrupt-parent = <&ao_gpio1_porta>; interrupt-parent = <&ao_gpio1>;
interrupts = <4 IRQ_TYPE_EDGE_FALLING>; interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
pinctrl-names = "default"; pinctrl-names = "default";
status = "disabled"; status = "disabled";
@@ -1290,7 +1290,7 @@
remote-endpoint = <&typec_con_usb>; remote-endpoint = <&typec_con_usb>;
}; };
}; };
}; };
}; };
&i2c5 { &i2c5 {
@@ -1305,11 +1305,6 @@
clock-frequency = <400000>; clock-frequency = <400000>;
}; };
&dm3x4 {
pinctrl-names = "default";
pinctrl-0 = <&pcie_x4_pins>;
};
&uart2 { &uart2 {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>; pinctrl-0 = <&uart2_pins>;
@@ -1340,7 +1335,6 @@
pinctrl-0 = <&can2_pins>; pinctrl-0 = <&can2_pins>;
}; };
&audio_i2s2 { &audio_i2s2 {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&i2s2_pins>; pinctrl-0 = <&i2s2_pins>;
@@ -1365,6 +1359,7 @@
&sata { &sata {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&sata_p0_pins>; pinctrl-0 = <&sata_p0_pins>;
status = "okay";
}; };
&hdmi_tx { &hdmi_tx {
@@ -1375,16 +1370,15 @@
&emmc { &emmc {
max-frequency = <196608000>; max-frequency = <196608000>;
non-removable; non-removable;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v; mmc-hs400-1_8v;
cap-mmc-highspeed; mmc-hs200-1_8v;
io_fixed_1v8; io_fixed_1v8;
is_emmc; is_emmc;
no-sdio; no-sdio;
no-sd; no-sd;
pull_up; pull_up;
bus-width = <8>; bus-width = <8>;
cap-mmc-highspeed;
}; };
&sdhci0 { &sdhci0 {
@@ -1406,62 +1400,6 @@
resolution = <12>; resolution = <12>;
}; };
&vp_dfmu_iommu {
status = "disabled";
};
&vp_dfmu_mt {
status = "disabled";
};
&npu_dfmu_iommu {
status = "disabled";
};
&npu_dfmu_mt {
status = "disabled";
};
&vi_dfmu_iommu {
status = "disabled";
};
&vi_dfmu_mt {
status = "disabled";
};
&vo_dfmu_iommu {
status = "disabled";
};
&vo_dfmu_mt {
status = "disabled";
};
&peri1_dfmu_iommu {
status = "okay";
};
&peri1_dfmu_mt {
status = "disabled";
};
&pcie_dfmu_iommu {
status = "disabled";
};
&pcie_dfmu_mt {
status = "disabled";
};
&usb_dfmu_iommu {
status = "okay";
};
&usb_dfmu_mt {
status = "disabled";
};
/* FIXME: Default EVB board expansion IO configuration */ /* FIXME: Default EVB board expansion IO configuration */
/* /*
@@ -1483,10 +1421,10 @@
GPMUX_SEL_04 -> 1 GPMUX_SEL_04 -> 1
GPMUX_SEL_11 -> 1 GPMUX_SEL_11 -> 1
*/ */
// &audio_i2s_8ch_sd0 { &audio_i2s_8ch_sd0 {
// pinctrl-names = "default"; pinctrl-names = "default";
// pinctrl-0 = <&i2s3_pins>; pinctrl-0 = <&i2s3_pins>;
// }; };
/* /*
expansion IO: audio_tdm expansion IO: audio_tdm
@@ -1519,10 +1457,22 @@
GPMUX_SEL_10 -> 0 GPMUX_SEL_10 -> 0
通过J206跳线切换到pcie x1 通过J206跳线切换到pcie x1
*/ */
// &rp3x1 { &rp3x1 {
// pinctrl-names = "default"; pinctrl-names = "default";
// pinctrl-0 = <&pcie_x1_pins>; pinctrl-0 = <&pcie_x1_pins>;
// }; status = "disabled";
};
&dm3x4 {
pinctrl-names = "default";
pinctrl-0 = <&pcie_x4_pins>;
num-lanes = <1>;
status = "okay";
};
&e16phy {
init-seq-select = "pcie_dmx1_rpx1_satax2";
};
/* /*
expansion IO: i2c2-0 expansion IO: i2c2-0
@@ -1682,3 +1632,105 @@
&usb2_0 { &usb2_0 {
status = "disabled"; status = "disabled";
}; };
&mipi0_csi0 {
status = "disabled";
};
&mipi0_csi1 {
//combination 4lane mode: host addr; aphy ctrl addr; bphy ctrl addr; mipi_ctrl addr
reg = < 0x00 0x06310000 0x0 0x10000
0x00 0x063a0020 0x0 0x4
0x00 0x063a0024 0x0 0x4
0x00 0x063a0028 0x0 0x4>;
phy_name = "CSI_4LANE"; //combination 4lane
};
//config dsi display: auxdisp->enc0->dsi0->lcd_lt8819_plane
&dsi_enc_out {
remote-endpoint = <&dsi0_in>;
};
&dsi_host0 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi0_in: endpoint {
remote-endpoint = <&dsi_enc_out>;
};
};
port@1 {
reg = <1>;
dsi0_out: endpoint {
remote-endpoint = <&panel0_in>;
};
};
};
panel0@0 {
compatible = "i2c_dsi,lt8911";
reg = <0>;
lt8911,rst-delay-ms = <10>;
lt8911,edp-lane-cnt = <2>;
lt8911,mipi-lane-cnt = <4>;
lt8911,edp-depth = <8>; /* 6 or 8 */
backlight = <&lcd0_backlight>;
port {
panel0_in: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
};
};
&aon {
cpufreq: a210_cpufreq {
compatible = "zhihe,a210-cpufreq";
clocks = <&clk TOP_CPUSYS_BUS_CLK_DIV>,
<&clk TOP_CPUSYS_PIC_CLK_DIV>,
<&clk TOP_CPUSYS_CFG_ACLK_DIV>,
<&clk TOP_CPUSYS_COM_APB_CLK_DIV>,
<&clk TOP_CPUSYS_APB_CLK_DIV>;
clock-names = "bus_clk", "pic_clk", "cfg_clk", "com_clk", "apb_clk";
status = "okay";
};
};
&cluster0_opp {
opp0-500000000 {
opp-microvolt = <1000000>;
};
opp0-1200000000 {
opp-microvolt = <1000000>;
};
opp0-1500000000 {
opp-microvolt = <1000000>;
};
opp0-1698000000 {
opp-microvolt = <1000000>;
};
opp0-1896000000 {
opp-microvolt = <1000000>;
};
};
&cluster1_opp {
opp1-500000000 {
opp-microvolt = <1000000>;
};
opp1-1698000000 {
opp-microvolt = <1000000>;
};
opp1-1896000000 {
opp-microvolt = <1000000>;
};
opp1-2298000000 {
opp-microvolt = <1000000>;
};
};
&dp0 {
force-hpd = <1>;
};

View File

@@ -134,76 +134,10 @@
status = "okay"; status = "okay";
}; };
codec_dummy_pdm0: codec_dummy_pdm0 { codec_dmic: dmic-codec {
compatible = "zhihe,dummy-pcm-pdm"; compatible = "dmic-codec";
sound-name-prefix = "DMIC0"; num-channels = <8>;
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>; #sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm1: codec_dummy_pdm1 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC1";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm2: codec_dummy_pdm2 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC2";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm3: codec_dummy_pdm3 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC3";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm4: codec_dummy_pdm4 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC4";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm5: codec_dummy_pdm5 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC5";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm6: codec_dummy_pdm6 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC6";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
};
codec_dummy_pdm7: codec_dummy_pdm7 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC7";
#address-cells = <0>;
#size-cells = <0>;
#sound-dai-cells = <1>;
status = "okay";
}; };
sound_i2s { sound_i2s {
@@ -255,19 +189,19 @@
#size-cells = <0>; #size-cells = <0>;
status = "okay"; status = "okay";
SOUND_CARD_LINK(0, pdm, pdm0, 0, dummy_pdm0, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(0, pdm, pdm0, 0, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(1, pdm, pdm1, 1, dummy_pdm1, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(1, pdm, pdm1, 1, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(2, pdm, pdm2, 2, dummy_pdm2, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(2, pdm, pdm2, 2, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(3, pdm, pdm3, 3, dummy_pdm3, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(3, pdm, pdm3, 3, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(4, pdm, pdm4, 4, dummy_pdm4, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(4, pdm, pdm4, 4, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(5, pdm, pdm5, 5, dummy_pdm5, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(5, pdm, pdm5, 5, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(6, pdm, pdm6, 6, dummy_pdm6, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(6, pdm, pdm6, 6, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(7, pdm, pdm7, 7, dummy_pdm7, 0); /* PDM <-> Dmic */ SOUND_CARD_LINK(7, pdm, pdm7, 7, dmic, 0); /* PDM <-> Dmic */
}; };
}; };
&clk { &clk {
compatible = "zhihe,p100-clk-haps"; compatible = "zhihe,a210-clk-haps";
/* pll */ /* pll */
audio0_pll_foutvco_frequency = <150000000>; audio0_pll_foutvco_frequency = <150000000>;
audio1_pll_foutvco_frequency = <80000000>; audio1_pll_foutvco_frequency = <80000000>;
@@ -319,7 +253,7 @@
}; };
&spi0 { &spi0 {
cs-gpios = <&gpio1_porta 7 0>; cs-gpios = <&gpio1 7 0>;
rx-sample-delay-ns = <10>; rx-sample-delay-ns = <10>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>; pinctrl-0 = <&spi0_pins>;
@@ -345,7 +279,7 @@
}; };
&spi1 { &spi1 {
// cs-gpios = <&gpio2_porta 15 0>; // cs-gpios = <&gpio2 15 0>;
rx-sample-delay-ns = <10>; rx-sample-delay-ns = <10>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>; pinctrl-0 = <&spi1_pins>;
@@ -362,7 +296,7 @@
}; };
&qspi0 { &qspi0 {
cs-gpios = <&gpio0_porta 19 0>; cs-gpios = <&gpio0 19 0>;
rx-sample-dly = <4>; rx-sample-dly = <4>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>; pinctrl-0 = <&qspi0_pins>;
@@ -396,7 +330,7 @@
}; };
&qspi1 { &qspi1 {
cs-gpios = <&gpio2_porta 29 0>; cs-gpios = <&gpio2 29 0>;
rx-sample-dly = <4>; rx-sample-dly = <4>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&qspi1_pins>; pinctrl-0 = <&qspi1_pins>;
@@ -579,62 +513,6 @@
}; };
}; };
&vp_dfmu_iommu {
status = "disabled";
};
&vp_dfmu_mt {
status = "disabled";
};
&npu_dfmu_iommu {
status = "disabled";
};
&npu_dfmu_mt {
status = "disabled";
};
&vi_dfmu_iommu {
status = "disabled";
};
&vi_dfmu_mt {
status = "disabled";
};
&vo_dfmu_iommu {
status = "disabled";
};
&vo_dfmu_mt {
status = "disabled";
};
&peri1_dfmu_iommu {
status = "disabled";
};
&peri1_dfmu_mt {
status = "disabled";
};
&pcie_dfmu_iommu {
status = "disabled";
};
&pcie_dfmu_mt {
status = "disabled";
};
&usb_dfmu_iommu {
status = "disabled";
};
&usb_dfmu_mt {
status = "disabled";
};
&bmu0 { &bmu0 {
status = "okay"; status = "okay";
}; };

View File

@@ -0,0 +1,328 @@
/ {
soc {
d2d: d2d@0 {
compatible = "zhihe,d2d";
#address-cells = <2>;
#size-cells = <2>;
ranges;
nr_dies = <4>;
status = "okay";
d2d_ctrl0: d2d_ctrl@9080000 {
compatible = "zhihe,d2d-ctrl";
reg = <0x00 0x09080000 0x0 0x400>;
interrupt-parent = <&intc>;
interrupts = <47>;
};
d2d_ctrl1: d2d_ctrl@90c0000 {
compatible = "zhihe,d2d-ctrl";
reg = <0x00 0x090c0000 0x0 0x400>;
interrupt-parent = <&intc>;
interrupts = <48>;
};
d2d_phy0: d2d_phy@9100000 {
compatible = "zhihe,d2d-phy";
reg = <0x00 0x09100000 0x0 0x2000>;
clocks = <&clk TOP_D2D_REF_CLK_MUX>;
};
d2d_phy1: d2d_phy@9140000 {
compatible = "zhihe,d2d-phy";
reg = <0x00 0x09140000 0x0 0x2000>;
};
};
d2d_die1: d2d@2000000000 {
compatible = "zhihe,d2d";
#address-cells = <2>;
#size-cells = <2>;
ranges;
status = "okay";
die1_d2d_ctrl0: die1_d2d_ctrl@2009080000 {
compatible = "zhihe,d2d-ctrl";
reg = <0x20 0x09080000 0x0 0x400>;
interrupt-parent = <&intc_die1>;
interrupts = <47>;
};
die1_d2d_ctrl1: die1_d2d_ctrl@20090c0000 {
compatible = "zhihe,d2d-ctrl";
reg = <0x20 0x090c0000 0x0 0x400>;
interrupt-parent = <&intc_die1>;
interrupts = <48>;
};
die1_d2d_phy0: die1_d2d_phy@2009100000 {
compatible = "zhihe,d2d-phy";
reg = <0x20 0x09100000 0x0 0x2000>;
clocks = <&clk_die1 TOP_D2D_REF_CLK_MUX>;
};
die1_d2d_phy1: die1_d2d_phy@2009140000 {
compatible = "zhihe,d2d-phy";
reg = <0x20 0x09140000 0x0 0x2000>;
};
};
};
};
/* DIE0 */
&uart0 {
status = "disabled";
};
&uart1 {
status = "disabled";
};
&uart2 {
status = "disabled";
};
&uart3 {
status = "disabled";
};
&uart5 {
status = "disabled";
};
&uart6 {
status = "disabled";
};
&uart7 {
status = "disabled";
};
&uart8 {
status = "disabled";
};
&uart9 {
status = "disabled";
};
&spi0 {
status = "disabled";
};
&spi1 {
status = "disabled";
};
&i2c0 {
status = "disabled";
};
&i2c1 {
status = "disabled";
};
&i2c2 {
status = "disabled";
};
&i2c3 {
status = "disabled";
};
&i2c4 {
status = "disabled";
};
&i2c5 {
status = "disabled";
};
&i2c6 {
status = "disabled";
};
&i2c7 {
status = "disabled";
};
&pwm0 {
status = "disabled";
};
&pwm1 {
status = "disabled";
};
&pwm2 {
status = "disabled";
};
&audio_i2s0 {
status = "disabled";
};
&audio_i2s1 {
status = "disabled";
};
&audio_i2s2 {
status = "disabled";
};
&audio_i2s_8ch_sd1 {
status = "disabled";
};
&audio_i2s_8ch_sd2 {
status = "disabled";
};
&audio_i2s_8ch_sd3 {
status = "disabled";
};
&audio_pdm0 {
status = "disabled";
};
&peri3_padctrl {
status = "disabled";
};
&gpio1 {
status = "disabled";
};
&gpio4 {
status = "disabled";
};
&gmac1 {
status = "disabled";
};
&mdio1 {
status = "disabled";
};
&can0 {
status = "disabled";
};
&can1 {
status = "disabled";
};
&can2 {
status = "disabled";
};
&dmac1 {
status = "disabled";
};
&timer0 {
status = "disabled";
};
&timer1 {
status = "disabled";
};
&timer3 {
status = "disabled";
};
&timer4 {
status = "disabled";
};
&timer5 {
status = "disabled";
};
&timer6 {
status = "disabled";
};
&timer7 {
status = "disabled";
};
&dm3x4 {
status = "disabled";
};
&rp3x1 {
status = "disabled";
};
&usb2_0 {
status = "disabled";
};
&usb31 {
status = "disabled";
};
&sata {
status = "disabled";
};
&dsi_host0 {
status = "disabled";
};
&adc {
status = "disabled";
};
&rtc {
status = "disabled";
};
&dfmu_mt_vp {
status = "disabled";
};
&dfmu_mt_npu {
status = "disabled";
};
&dfmu_mt_vi {
status = "disabled";
};
&dfmu_mt_vo {
status = "disabled";
};
&dfmu_mt_peri1 {
status = "disabled";
};
&dfmu_mt_pcie {
status = "disabled";
};
&dfmu_mt_usb {
status = "disabled";
};
&vidmem {
status = "disabled";
};
/* DIE1 */
&uart4_die1 {
status = "disabled";
};
&auxdisp {
status = "disabled";
};
&dpu_enc0 {
status = "disabled";
};

View File

@@ -14,10 +14,6 @@
status = "disabled"; status = "disabled";
}; };
&uart4 {
current-speed = <115200>; /* OpenSBI */
};
&uart6 { &uart6 {
status = "disabled"; status = "disabled";
}; };
@@ -58,6 +54,10 @@
status = "disabled"; status = "disabled";
}; };
&can0 {
status = "disabled";
};
&can1 { &can1 {
status = "disabled"; status = "disabled";
}; };
@@ -106,6 +106,14 @@
status = "okay"; status = "okay";
}; };
&auxdisp {
status = "disabled";
};
&dpu_enc0 {
status = "disabled";
};
&audio_i2s0 { &audio_i2s0 {
status = "disabled"; status = "disabled";
}; };
@@ -179,60 +187,36 @@
}; };
/* dfmu/iommu */ /* dfmu/iommu */
&vp_dfmu_iommu { &iommu {
status = "disabled"; status = "okay";
}; };
&vp_dfmu_mt { &dfmu_mt_vp {
status = "disabled"; status = "disabled";
}; };
&npu_dfmu_iommu { &dfmu_mt_npu {
status = "disabled"; status = "disabled";
}; };
&npu_dfmu_mt { &dfmu_mt_vi {
status = "disabled"; status = "disabled";
}; };
&vi_dfmu_iommu { &dfmu_mt_vo {
status = "disabled"; status = "disabled";
}; };
&vi_dfmu_mt { &dfmu_mt_peri1 {
status = "disabled"; status = "disabled";
}; };
&vo_dfmu_iommu { &dfmu_mt_pcie {
status = "disabled"; status = "disabled";
}; };
&vo_dfmu_mt { &dfmu_mt_usb {
status = "disabled"; status = "disabled";
};
&peri1_dfmu_iommu {
status = "okay";
};
&peri1_dfmu_mt {
status = "disabled";
};
&pcie_dfmu_iommu {
status = "disabled";
};
&pcie_dfmu_mt {
status = "disabled";
};
&usb_dfmu_iommu {
status = "okay";
};
&usb_dfmu_mt {
status = "disabled";
}; };
&bmu9 { &bmu9 {

View File

@@ -89,10 +89,6 @@
status = "disabled"; status = "disabled";
}; };
&uart4 {
current-speed = <115200>; /* OpenSBI */
};
&uart5 { &uart5 {
status = "disabled"; status = "disabled";
}; };
@@ -266,6 +262,14 @@
status = "disabled"; status = "disabled";
}; };
&auxdisp {
status = "disabled";
};
&dpu_enc0 {
status = "disabled";
};
&audio_i2s0 { &audio_i2s0 {
status = "disabled"; status = "disabled";
}; };
@@ -441,3 +445,31 @@
&power_npu_ip { &power_npu_ip {
status = "disabled"; status = "disabled";
}; };
&dfmu_mt_vp {
status = "disabled";
};
&dfmu_mt_npu {
status = "disabled";
};
&dfmu_mt_vi {
status = "disabled";
};
&dfmu_mt_vo {
status = "disabled";
};
&dfmu_mt_peri1 {
status = "disabled";
};
&dfmu_mt_pcie {
status = "disabled";
};
&dfmu_mt_usb {
status = "disabled";
};

View File

@@ -1,8 +1,3 @@
&c908_0 {
// status = "disabled";
};
// &c908_1 { // &c908_1 {
// status = "disabled"; // status = "disabled";
// }; // };
@@ -39,12 +34,12 @@
status = "disabled"; status = "disabled";
}; };
&uart3 { &uart2 {
status = "disabled"; status = "disabled";
}; };
&uart4 { &uart3 {
current-speed = <115200>; /* OpenSBI */ status = "disabled";
}; };
&uart5 { &uart5 {
@@ -71,10 +66,18 @@
status = "disabled"; status = "disabled";
}; };
&spi1 {
status = "disabled";
};
&qspi0 { &qspi0 {
status = "disabled"; status = "disabled";
}; };
&qspi1 {
status = "okay";
};
&i2c1 { &i2c1 {
status = "disabled"; status = "disabled";
}; };
@@ -87,6 +90,10 @@
status = "disabled"; status = "disabled";
}; };
&i2c4 {
status = "disabled";
};
&i2c5 { &i2c5 {
status = "disabled"; status = "disabled";
}; };
@@ -99,30 +106,6 @@
status = "disabled"; status = "disabled";
}; };
&pwm0 {
status = "disabled";
};
&pwm2 {
status = "disabled";
};
&audio_i2s2 {
status = "disabled";
};
&audio_i2s_8ch_sd1 {
status = "disabled";
};
&audio_i2s_8ch_sd2 {
status = "disabled";
};
&audio_i2s_8ch_sd3 {
status = "disabled";
};
&peri3_padctrl { &peri3_padctrl {
status = "disabled"; status = "disabled";
}; };
@@ -152,10 +135,6 @@
status = "disabled"; status = "disabled";
}; };
&uart2 {
status = "disabled";
};
&timer0 { &timer0 {
status = "disabled"; status = "disabled";
}; };
@@ -184,7 +163,23 @@
status = "disabled"; status = "disabled";
}; };
&i2c4 { &rp3x1 {
status = "disabled";
};
&dm3x4 {
status = "disabled";
};
&sata {
status = "disabled";
};
&auxdisp {
status = "disabled";
};
&dpu_enc0 {
status = "disabled"; status = "disabled";
}; };
@@ -192,18 +187,47 @@
status = "disabled"; status = "disabled";
}; };
&dm3x4 { &audio_i2s1 {
status = "okay"; status = "okay";
}; };
&rp3x1 { &audio_i2s2 {
status = "disabled"; status = "disabled";
}; };
// &usb31_zhihe { &pwm0 {
// status = "disabled"; status = "disabled";
// }; };
// &sata { &pwm2 {
// status = "disabled"; status = "disabled";
// }; };
&dfmu_mt_vp {
status = "disabled";
};
&dfmu_mt_npu {
status = "disabled";
};
&dfmu_mt_vi {
status = "disabled";
};
&dfmu_mt_vo {
status = "disabled";
};
&dfmu_mt_peri1 {
status = "disabled";
};
&dfmu_mt_pcie {
status = "disabled";
};
&dfmu_mt_usb {
status = "disabled";
};

View File

@@ -89,10 +89,6 @@
status = "disabled"; status = "disabled";
}; };
&uart4 {
current-speed = <115200>; /* OpenSBI */
};
&uart5 { &uart5 {
status = "disabled"; status = "disabled";
}; };
@@ -190,6 +186,14 @@
status = "disabled"; status = "disabled";
}; };
&auxdisp {
status = "disabled";
};
&dpu_enc0 {
status = "disabled";
};
&clk_gpu { &clk_gpu {
status = "disabled"; status = "disabled";
}; };
@@ -221,3 +225,31 @@
&clk_d2d { &clk_d2d {
status = "disabled"; status = "disabled";
}; };
&dfmu_mt_vp {
status = "disabled";
};
&dfmu_mt_npu {
status = "disabled";
};
&dfmu_mt_vi {
status = "disabled";
};
&dfmu_mt_vo {
status = "disabled";
};
&dfmu_mt_peri1 {
status = "disabled";
};
&dfmu_mt_pcie {
status = "disabled";
};
&dfmu_mt_usb {
status = "disabled";
};

View File

@@ -0,0 +1,323 @@
//sec-tee.dtsi
/ {
//compatible = "zhihe,a210,tee";//update dst compatible value for tee
chosen {
opensbi-domains {
compatible = "opensbi,domain,config";
tmem0: tmem0 {
compatible = "opensbi,domain,memregion";
base = <0x0 0x20000000>;
order = <28>; // 256MiB tee device io
};
tmem1: tmem1 {
compatible = "opensbi,domain,memregion";
base = <0x0 0x30000000>;
order = <27>; // 128MiB tee device io
};
teeosmem: teeosmem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x88000000>;
order = <25>; // 32MiB, optee-os
};
teess_mem0: teess_mem0 {
compatible = "opensbi,domain,memregion";
base = <0x0 0x27500000>;
order = <19>; // 512KB, EIP+TEE_DMAC+TEE_OCRAM
};
teess_mem1: teess_mem1 {
compatible = "opensbi,domain,memregion";
base = <0x0 0x27410000>;
order = <12>; // 4KB, EFUSE
};
iopmp_vpmem: iopmp_vpmem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x27500000>;
order = <12>; // 4KB
};
iopmp_vimem: iopmp_vimem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x26372000>;
order = <12>; // 4KB
};
iopmp_npumem: iopmp_npumem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x27102000>;
order = <12>; // 4KB
};
iopmp_vomem: iopmp_vomem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x26712000>;
order = <12>; // 4KB
};
iopmp_peri1mem: iopmp_peri1mem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x22032000>;
order = <12>; // 4KB
};
iopmp_pciemem: iopmp_pciemem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x2A012000>;
order = <12>; // 4KB
};
iopmp_usbmem: iopmp_usbmem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x28022000>;
order = <12>; // 4KB
};
iopmp_gpumem: iopmp_gpumem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x26D12000>;
order = <12>; // 4KB
};
uart4mem: uart4mem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x08401000>;
order = <12>;
mmio;
};
plicmem: plicem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x18000000>;
order = <22>;
mmio;
};
reemem1: reemem1 {
compatible = "opensbi,domain,memregion";
base = <0x0 0x80000000>;
order = <27>; // 128MiB, linux-os, {0x80000000~0x87ffffff}
};
allmem: allmem {
compatible = "opensbi,domain,memregion";
base = <0x0 0x0>;
order = <64>;
};
tdomain: tee-domain {
compatible = "opensbi,domain,instance";
regions =<&plicmem 0x1b>, <&uart4mem 0x1b>, <&allmem 0x38>;
possible-harts = <&c908_0 &c908_1 &c908_2 &c908_3 &c920_4 &c920_5 &c920_6 &c920_7>;
next-addr = <0x0 0x88000000>; /* optee_os: CFG_TDDRAM_START */
next-mode = <0x1>;
system-reset-allowed;
system-suspend-allowed;
};
udomain: ree-domain {
compatible = "opensbi,domain,instance";
regions = <&teeosmem 0x0>,
<&teess_mem0 0x0>,
<&teess_mem1 0x0>,
<&plicmem 0x1b>,
<&allmem 0x38>;
possible-harts = <&c908_0 &c908_1 &c908_2 &c908_3 &c920_4 &c920_5 &c920_6 &c920_7>;
boot-hart = <&c908_0>;
next-addr = <0x0 0x90000000>; /* u-boot: CONFIG_TEXT_BASE */
next-mode = <0x1>;
system-reset-allowed;
system-suspend-allowed;
};
};
};
firmware {
optee {
compatible = "linaro,optee-tz";
method = "smc";
};
};
reserved-memory {
optee_mem: optee@88000000 {
reg = <0x0 0x88000000 0x0 0x04000000>;
no-map;
};
};
};
&eip_28 {
status = "disabled";
};
&nvmem_controller {
status = "disabled";
};
&c908_0 {
opensbi-domain = <&tdomain>;
};
&c908_1 {
opensbi-domain = <&udomain>;
};
&c908_2 {
opensbi-domain = <&udomain>;
};
&c908_3 {
opensbi-domain = <&udomain>;
};
&c920_4 {
opensbi-domain = <&udomain>;
};
&c920_5 {
opensbi-domain = <&udomain>;
};
&c920_6 {
opensbi-domain = <&udomain>;
};
&c920_7 {
opensbi-domain = <&udomain>;
};
/* PCIE iopmp*/
&device_pcie_mt_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_pcie_0_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_pcie_1_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_sata_0_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_dmac_ap_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_sd_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_emmc_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_pcie_iommu_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
/* VP iopmp*/
&device_vp_mt_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_venc_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_vdec_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_g2d_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_vp_iommu_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
/* VI iopmp*/
&device_vi_mt_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_isp_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_vipre_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_dw200_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_vi_comp_decomp_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_vi_iommu_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
/* NPU iopmp*/
&device_npu_mt_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_npu_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_npu_iommu_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
/* VO iopmp */
&device_vo_mt_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_display_0_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_display_1_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_auxdisp_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_vo_iommu_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
/* PERI1 iopmp */
&device_peri1_mt_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_gmac_0_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_gmac_1_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_gmac_2_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_chip_dbg_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_aon_iopmp {
iopmp-regions = <&bypass_region>;
};
&device_peri1_iommu_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
/* USB iopmp*/
&device_usb_mt_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_usb3_0_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_usb2_1_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_usb2_2_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_usb_iommu_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
/* GPU iopmp*/
&device_gpu_mt_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
&device_gpu_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
/* D2D RX iopmp*/
&device_d2d_rx_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};
/* D2D CPU iopmp*/
&device_d2d_cpu_iopmp {
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
};

View File

@@ -22,11 +22,14 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf"; riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39"; mmu-type = "riscv,sv39";
cpu-freq = "2Ghz"; cpu-freq = "2Ghz";
cpu-icache = "32KB"; i-cache-block-size = <64>;
cpu-dcache = "32KB"; i-cache-size = <32768>;
cpu-l2cache = "512KB"; i-cache-sets = <256>;
d-cache-block-size = <64>;
d-cache-size = <32768>;
d-cache-sets = <256>;
next-level-cache = <&c2_l2_cache>;
cpu-tlb = "1024 4-ways"; cpu-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0"; cpu-vector = "1.0";
capacity-dmips-mhz = <768>; capacity-dmips-mhz = <768>;
#cooling-cells = <2>; #cooling-cells = <2>;
@@ -46,11 +49,14 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf"; riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39"; mmu-type = "riscv,sv39";
cpu-freq = "2Ghz"; cpu-freq = "2Ghz";
cpu-icache = "32KB"; i-cache-block-size = <64>;
cpu-dcache = "32KB"; i-cache-size = <32768>;
cpu-l2cache = "512KB"; i-cache-sets = <256>;
d-cache-block-size = <64>;
d-cache-size = <32768>;
d-cache-sets = <256>;
next-level-cache = <&c2_l2_cache>;
cpu-tlb = "1024 4-ways"; cpu-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0"; cpu-vector = "1.0";
capacity-dmips-mhz = <768>; capacity-dmips-mhz = <768>;
#cooling-cells = <2>; #cooling-cells = <2>;
@@ -70,11 +76,14 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf"; riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39"; mmu-type = "riscv,sv39";
cpu-freq = "2Ghz"; cpu-freq = "2Ghz";
cpu-icache = "32KB"; i-cache-block-size = <64>;
cpu-dcache = "32KB"; i-cache-size = <32768>;
cpu-l2cache = "512KB"; i-cache-sets = <256>;
d-cache-block-size = <64>;
d-cache-size = <32768>;
d-cache-sets = <256>;
next-level-cache = <&c2_l2_cache>;
cpu-tlb = "1024 4-ways"; cpu-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0"; cpu-vector = "1.0";
capacity-dmips-mhz = <768>; capacity-dmips-mhz = <768>;
#cooling-cells = <2>; #cooling-cells = <2>;
@@ -94,11 +103,15 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf"; riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39"; mmu-type = "riscv,sv39";
cpu-freq = "2Ghz"; cpu-freq = "2Ghz";
cpu-icache = "32KB"; i-cache-block-size = <64>;
cpu-dcache = "32KB"; i-cache-size = <32768>;
i-cache-sets = <256>;
d-cache-block-size = <64>;
d-cache-size = <32768>;
d-cache-sets = <256>;
next-level-cache = <&c2_l2_cache>;
cpu-l2cache = "512KB"; cpu-l2cache = "512KB";
cpu-tlb = "1024 4-ways"; cpu-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0"; cpu-vector = "1.0";
capacity-dmips-mhz = <768>; capacity-dmips-mhz = <768>;
#cooling-cells = <2>; #cooling-cells = <2>;
@@ -119,11 +132,15 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf"; riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39"; mmu-type = "riscv,sv39";
cpu-freq = "2.6Ghz"; cpu-freq = "2.6Ghz";
cpu-icache = "32KB";
cpu-dcache = "32KB";
cpu-l2cache = "512KB"; cpu-l2cache = "512KB";
i-cache-block-size = <64>;
i-cache-size = <65536>;
i-cache-sets = <512>;
d-cache-block-size = <64>;
d-cache-size = <65536>;
d-cache-sets = <512>;
next-level-cache = <&c3_l2_cache>;
cpu-tlb = "1024 4-ways"; cpu-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0"; cpu-vector = "1.0";
capacity-dmips-mhz = <1024>; capacity-dmips-mhz = <1024>;
#cooling-cells = <2>; #cooling-cells = <2>;
@@ -143,11 +160,14 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf"; riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39"; mmu-type = "riscv,sv39";
cpu-freq = "2.6Ghz"; cpu-freq = "2.6Ghz";
cpu-icache = "32KB"; i-cache-block-size = <64>;
cpu-dcache = "32KB"; i-cache-size = <65536>;
cpu-l2cache = "512KB"; i-cache-sets = <512>;
d-cache-block-size = <64>;
d-cache-size = <65536>;
d-cache-sets = <512>;
next-level-cache = <&c3_l2_cache>;
cpu-tlb = "1024 4-ways"; cpu-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0"; cpu-vector = "1.0";
capacity-dmips-mhz = <1024>; capacity-dmips-mhz = <1024>;
#cooling-cells = <2>; #cooling-cells = <2>;
@@ -167,11 +187,14 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf"; riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39"; mmu-type = "riscv,sv39";
cpu-freq = "2.6Ghz"; cpu-freq = "2.6Ghz";
cpu-icache = "32KB"; i-cache-block-size = <64>;
cpu-dcache = "32KB"; i-cache-size = <65536>;
cpu-l2cache = "512KB"; i-cache-sets = <512>;
d-cache-block-size = <64>;
d-cache-size = <65536>;
d-cache-sets = <512>;
next-level-cache = <&c3_l2_cache>;
cpu-tlb = "1024 4-ways"; cpu-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0"; cpu-vector = "1.0";
capacity-dmips-mhz = <1024>; capacity-dmips-mhz = <1024>;
#cooling-cells = <2>; #cooling-cells = <2>;
@@ -191,11 +214,14 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf"; riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39"; mmu-type = "riscv,sv39";
cpu-freq = "2.6Ghz"; cpu-freq = "2.6Ghz";
cpu-icache = "32KB"; i-cache-block-size = <64>;
cpu-dcache = "32KB"; i-cache-size = <65536>;
cpu-l2cache = "512KB"; i-cache-sets = <512>;
d-cache-block-size = <64>;
d-cache-size = <65536>;
d-cache-sets = <512>;
next-level-cache = <&c3_l2_cache>;
cpu-tlb = "1024 4-ways"; cpu-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0"; cpu-vector = "1.0";
capacity-dmips-mhz = <1024>; capacity-dmips-mhz = <1024>;
#cooling-cells = <2>; #cooling-cells = <2>;
@@ -207,6 +233,23 @@
}; };
}; };
c2_l2_cache: c2_l2-cache {
compatible = "cache";
cache-block-size = <64>;
cache-level = <2>;
cache-size = <524288>;
cache-sets = <512>;
cache-unified;
};
c3_l2_cache: c3_l2-cache {
compatible = "cache";
cache-block-size = <64>;
cache-level = <2>;
cache-size = <1048576>;
cache-sets = <1024>;
cache-unified;
};
cpu-map { cpu-map {
cluster2 { cluster2 {
core0 { core0 {
@@ -251,11 +294,7 @@
#size-cells = <2>; #size-cells = <2>;
ranges; ranges;
d2d: d2d { /* OPENSBI */
compatible = "zhihe,d2d";
nr_dies = <2>;
};
/* OPENSBI */
reset: reset-sample { reset: reset-sample {
compatible = "zhihe,reset-sample"; compatible = "zhihe,reset-sample";
reg = <0x00 0x00 0x00 0x00>; reg = <0x00 0x00 0x00 0x00>;
@@ -310,8 +349,595 @@
reg = <0x00 0x1a000000 0x0 0x02000000>; reg = <0x00 0x1a000000 0x0 0x02000000>;
reg-names = "control"; reg-names = "control";
riscv,max-priority = <7>; riscv,max-priority = <7>;
riscv,ndev = <400>; riscv,ndev = <351>;
cpu-id = <8>; };
clocks1 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
osc_32k_die1: clock-osc-32k {
compatible = "fixed-clock";
clock-frequency = <32768>;
clock-output-names = "osc_32k_die1";
#clock-cells = <0>;
};
osc_24m_die1: clock-osc-24m {
compatible = "fixed-clock";
clock-frequency = <24000000>;
clock-output-names = "osc_24m_die1";
#clock-cells = <0>;
};
aon_110m_die1: clock-osc-110m {
compatible = "fixed-clock";
clock-frequency = <110000000>;
clock-output-names = "aon_110m_die1";
#clock-cells = <0>;
};
rc_24m_die1: clock-rc-24m {
compatible = "fixed-clock";
clock-frequency = <24000000>;
clock-output-names = "rc_24m_die1";
#clock-cells = <0>;
};
apb_clk_die1: apb-clk-clock {
compatible = "fixed-clock";
clock-frequency = <62500000>;
clock-output-names = "apb_clk_die1";
#clock-cells = <0>;
};
};
clk_die1: clock-controller@10 {
compatible = "zhihe,a210-clk-die1";
reg = <0x20 0x00260000 0x0 0x1000>,<0x20 0x00250000 0x0 0x1000>,
<0x20 0x10141600 0x0 0x100>,<0x20 0x10141400 0x0 0x100>,
<0x20 0x04810000 0x0 0x1000>,<0x20 0x05810000 0x0 0x1000>,
<0x20 0x04900000 0x0 0x1000>,<0x20 0x20250000 0x0 0x1000>,
<0x20 0x10140000 0x0 0xE00>;
reg-names = "PLL_WRAP","TOP_CRG","CPU_SS_CLK_SYSREG","CPU_SS_CPU_PLL",
"DDR0_SYSREG","DDR1_SYSREG","SLC_DUAL_SYSREG","TOP_CRG_T","CPU_SS_CCU";
#clock-cells = <1>;
clocks = <&osc_32k_die1>, <&osc_24m_die1>, <&rc_24m_die1>;
clock-names = "osc_32k", "osc_24m", "rc_24m";
assigned-clocks = <&clk_die1 AUDIO0_PLL_FOUTVCO>, <&clk_die1 AUDIO1_PLL_FOUTVCO>,
<&clk_die1 VIDEO_PLL_FOUTVCO>, <&clk_die1 GMAC_PLL_FOUTVCO>,
<&clk_die1 DVFS_PLL_FOUTVCO>, <&clk_die1 DPU0_PLL_FOUTVCO>,
<&clk_die1 DPU1_PLL_FOUTVCO>, <&clk_die1 DPU2_PLL_FOUTVCO>,
<&clk_die1 TOP_CFG_ACLK_DIV>, <&clk_die1 TOP_PCLK_DIV>,
<&clk_die1 SW_AMUX_660_CLK_EN>, <&clk_die1 SW_IOMMU_PTW_330_ACLK_EN>,
<&clk_die1 SW_NOC_CCLK_EN>, <&clk_die1 TOP_CPUSYS_BUS_CLK_DIV>,
<&clk_die1 TOP_CPUSYS_PIC_CLK_DIV>;
assigned-clock-rates = <2359296000>, <2528870400>, /* audio0_pll_foutvco,audio1_pll_foutvco */
<2640000000>, <3000000000>, /* video_pll_foutvco,gmac_pll_foutvco */
<1920000000>, <2376000000>, /* dvfs_pll_foutvco,dpu0_pll_foutvco */
<2376000000>, <2376000000>, /* dpu1_pll_foutvco,dpu2_pll_foutvco */
<330000000>, <165000000>, /* top_cfg_aclk,top_pclk */
<660000000>, <330000000>, /* top_amux_clk,iommu_ptw_aclk */
<950000000>, <1320000000>, /* noc_cclk,top_cpusys_bus_clk */
<1000000000>; /* top_cpusys_pic_clk */
status = "okay";
};
clk_gpu_die1: clock-controller@11 {
compatible = "zhihe,a210-gpu-clk-die1";
reg = <0x20 0x06D02200 0x0 0x200>, <0x20 0x06E06200 0x0 0x200>;
reg-names = "GPU_SS_PWRAP_CLK_EN","GPU_SS_TOP_CLK_EN";
#clock-cells = <1>;
assigned-clocks = <&clk_die1 TOP_GPU_CORE_CLK_DIV>;
assigned-clock-rates = <792000000>;
status = "okay";
};
clk_pcie_die1: clock-controller@12 {
compatible = "zhihe,a210-pcie-clk-die1";
reg = <0x20 0x0a000000 0x0 0x28>;
reg-names = "PCIE_CLK_EN";
#clock-cells = <1>;
assigned-clocks = <&clk_die1 TOP_PCIE_SCAN_REF_CLK0_DIV>, <&clk_die1 TOP_PCIE_SCAN_REF_CLK1_DIV>,
<&clk_die1 TOP_PCIE_AXI_M_ACLK_DIV>;
assigned-clock-rates = <396000000>, <1000000000>,
<786432000>;
status = "okay";
};
clk_usb_die1: clock-controller@13 {
compatible = "zhihe,a210-usb-clk-die1";
reg = <0x20 0x08000000 0x0 0x24>;
reg-names = "USB_CLK_EN";
#clock-cells = <1>;
assigned-clocks = <&clk_die1 TOP_USB_USB20_SCAN_REF_CLK_DIV>, <&clk_die1 TOP_USB_SCAN_REF_CLK3_DIV>,
<&clk_die1 TOP_USB_SCAN_REF_CLK2_DIV>, <&clk_die1 TOP_USB_SCAN_REF_CLK1_DIV>,
<&clk_die1 TOP_USB_SCAN_REF_CLK0_DIV>, <&clk_die1 TOP_USB_BUS_ACLK_DIV>,
<&clk_die1 TOP_USB_DP_AUX_CLK_DIV>;
assigned-clock-rates = <475200000>, <792000000>,
<600000000>, <500000000>,
<396000000>, <330000000>,
<16000000>;
status = "okay";
};
clk_vi_die1: clock-controller@14 {
compatible = "zhihe,a210-vi-clk-die1";
reg = <0x20 0x063a0200 0x0 0x200>;
reg-names = "VI_CLK";
#clock-cells = <1>;
status = "okay";
};
clk_vp_die1: clock-controller@15 {
compatible = "zhihe,a210-vp-clk-die1";
reg = <0x20 0x06b20200 0x0 0x200>;
reg-names = "VP_CLK";
#clock-cells = <1>;
assigned-clocks = <&clk_die1 TOP_VP_ACLK_DIV>, <&clk_die1 TOP_VP_VDEC_CCLK_DIV>,
<&clk_die1 TOP_VP_VENC_CCLK_DIV>, <&clk_die1 TOP_VP_G2D_CCLK_DIV>;
assigned-clock-rates = <880000000>, <786432000>,
<600000000>, <786432000>;
status = "okay";
};
clk_vo_die1: clock-controller@16 {
compatible = "zhihe,a210-vo-clk-die1";
reg = <0x20 0x06720048 0x0 0x4>, <0x20 0x06720200 0x0 0xc>;
reg-names = "VO_PATH_CTRL","VO_CLK";
#clock-cells = <1>;
assigned-clocks = <&clk_vo_die1 VO_DPUC_CLK_EN>, <&clk_vo_die1 VO_CH0_PIXCLK_EN>,
<&clk_vo_die1 VO_CH1_PIXCLK_EN>, <&clk_vo_die1 VO_CH2_PIXCLK_EN>,
<&clk_vo_die1 VO_DPU_ACLK_EN>, <&clk_vo_die1 VO_HDMI_PCLK_EN>,
<&clk_vo_die1 VO_DECOMP0_CLK_EN>, <&clk_vo_die1 VO_DECOMP1_CLK_EN>;
assigned-clock-rates = <880000000>, <594000000>,
<594000000>, <594000000>,
<880000000>, <165000000>,
<220000000>, <220000000>;
status = "okay";
};
clk_npu_die1: clock-controller@17 {
compatible = "zhihe,a210-npu-clk-die1";
reg = <0x20 0x07112210 0x0 0x4>,<0x20 0x07301050 0x0 0x4>;
reg-names = "NPU_CLK","NPU_TOP_CLK";
#clock-cells = <1>;
assigned-clocks = <&clk_die1 TOP_NPU_CCLK_DIV>, <&clk_die1 TOP_NPU_ACLK_DIV>;
assigned-clock-rates = <880000000>, <880000000>;
status = "okay";
};
clk_d2d_die1: clock-controller@18 {
compatible = "zhihe,a210-d2d-clk-die1";
reg = <0x20 0x09010000 0x0 0x4>;
reg-names = "D2D_CRG_REG";
#clock-cells = <1>;
assigned-clocks = <&clk_die1 TOP_D2D_ACLK_DIV>, <&clk_die1 TOP_D2D_REF_CLK_MUX>;
assigned-clock-rates = <950000000>, <100000000>;
status = "okay";
};
clk_peri_die1: clock-controller@19 {
compatible = "zhihe,a210-peri-clk-die1";
reg = <0x20 0x00300200 0x0 0x4>,
<0x20 0x02010200 0x0 0x8>,<0x20 0x08400200 0x0 0x8>,
<0x20 0x00540200 0x0 0x4>,<0x20 0x27420200 0x0 0x200>;
reg-names = "PERI0_SYSREG","PERI1_SYSREG","PERI2_SYSREG",
"PERI3_SYSREG","TEE_CRG";
#clock-cells = <1>;
assigned-clocks = <&clk_die1 TOP_PERI_TIMER_CLK_MUX>, <&clk_die1 TOP_PERI_I2S_2CH0_SRC_CLK_MUX>,
<&clk_die1 TOP_PERI_I2S_2CH1_SRC_CLK_MUX>, <&clk_die1 TOP_PERI_I2S_2CH2_SRC_CLK_MUX>,
<&clk_die1 TOP_PERI_I2S_8CH0_SRC_CLK_MUX>, <&clk_die1 TOP_PERI_SPI_SSI_CLK0_DIV>,
<&clk_die1 TOP_PERI_SPI_SSI_CLK1_DIV>, <&clk_die1 TOP_PERI_QSPI_SSI_CLK_MUX0>,
<&clk_die1 TOP_PERI_QSPI_SSI_CLK_MUX1>, <&clk_die1 TOP_PERI_PDM_MCLK_DIV>,
<&clk_die1 TOP_PERI_TDM_SRC_CLK_MUX>, <&clk_die1 TOP_PAD_SENSOR_VCLK0_DIV>,
<&clk_die1 TOP_PAD_SENSOR_VCLK1_DIV>, <&clk_die1 TOP_PERI_HIRES_CLK0_DIV>,
<&clk_die1 TOP_PERI_HIRES_CLK1_DIV>, <&clk_die1 TOP_PERI_EMMC_REF_CLK_DIV>,
<&clk_die1 TOP_PERI_MST_ACLK0_DIV>, <&clk_die1 TOP_PERI_MST_CLK1_DIV>,
<&clk_die1 TOP_TEE_CLK_DIV>;
assigned-clock-rates = <24000000>, <316108800>, /* peri0_timer_clk,peri1_i2s0_src_clk */
<316108800>, <316108800>, /* peri2_i2s1_src_clk,peri2_i2s2_src_clk */
<316108800>, <421478400>, /* peri2_i2s3_src_clk,peri1_spi_ssi_clk */
<421478400>, <421478400>, /* peri2_spi_ssi_clk,peri1_qspi_ssi_clk */
<421478400>, <31610880>, /* peri2_qspi_ssi_clk,peri1_pdm_mclk */
<316108800>, <74250000>, /* peri1_tdm_src_clk,top_pad_sensor_vclk0_div */
<148500000>, <80000000>, /* top_pad_sensor_vclk1,peri1_hires_clk */
<80000000>, <786432000>, /* peri2_hires_clk,emmc_ref_clk */
<330000000>, <440000000>, /* peri1_mst_aclk,peri3_mst_aclk */
<377142858>; /* tee_clk */
status = "okay";
};
clocks2 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
osc_32k_die2: clock-osc-32k {
compatible = "fixed-clock";
clock-frequency = <32768>;
clock-output-names = "osc_32k_die2";
#clock-cells = <0>;
};
osc_24m_die2: clock-osc-24m {
compatible = "fixed-clock";
clock-frequency = <24000000>;
clock-output-names = "osc_24m_die2";
#clock-cells = <0>;
};
aon_110m_die2: clock-osc-110m {
compatible = "fixed-clock";
clock-frequency = <110000000>;
clock-output-names = "aon_110m_die2";
#clock-cells = <0>;
};
rc_24m_die2: clock-rc-24m {
compatible = "fixed-clock";
clock-frequency = <24000000>;
clock-output-names = "rc_24m_die2";
#clock-cells = <0>;
};
apb_clk_die2: apb-clk-clock {
compatible = "fixed-clock";
clock-frequency = <62500000>;
clock-output-names = "apb_clk_die2";
#clock-cells = <0>;
};
};
clk_die2: clock-controller@20 {
compatible = "zhihe,a210-clk-die2";
reg = <0x40 0x00260000 0x0 0x1000>,<0x40 0x00250000 0x0 0x1000>,
<0x40 0x10141600 0x0 0x100>,<0x40 0x10141400 0x0 0x100>,
<0x40 0x04810000 0x0 0x1000>,<0x40 0x05810000 0x0 0x1000>,
<0x40 0x04900000 0x0 0x1000>,<0x40 0x20250000 0x0 0x1000>,
<0x40 0x10140000 0x0 0xE00>;
reg-names = "PLL_WRAP","TOP_CRG","CPU_SS_CLK_SYSREG","CPU_SS_CPU_PLL",
"DDR0_SYSREG","DDR1_SYSREG","SLC_DUAL_SYSREG","TOP_CRG_T","CPU_SS_CCU";
#clock-cells = <1>;
clocks = <&osc_32k_die2>, <&osc_24m_die2>, <&rc_24m_die2>;
clock-names = "osc_32k", "osc_24m", "rc_24m";
assigned-clocks = <&clk_die2 AUDIO0_PLL_FOUTVCO>, <&clk_die2 AUDIO1_PLL_FOUTVCO>,
<&clk_die2 VIDEO_PLL_FOUTVCO>, <&clk_die2 GMAC_PLL_FOUTVCO>,
<&clk_die2 DVFS_PLL_FOUTVCO>, <&clk_die2 DPU0_PLL_FOUTVCO>,
<&clk_die2 DPU1_PLL_FOUTVCO>, <&clk_die2 DPU2_PLL_FOUTVCO>,
<&clk_die2 TOP_CFG_ACLK_DIV>, <&clk_die2 TOP_PCLK_DIV>,
<&clk_die2 SW_AMUX_660_CLK_EN>, <&clk_die2 SW_IOMMU_PTW_330_ACLK_EN>,
<&clk_die2 SW_NOC_CCLK_EN>, <&clk_die2 TOP_CPUSYS_BUS_CLK_DIV>,
<&clk_die2 TOP_CPUSYS_PIC_CLK_DIV>;
assigned-clock-rates = <2359296000>, <2528870400>, /* audio0_pll_foutvco,audio1_pll_foutvco */
<2640000000>, <3000000000>, /* video_pll_foutvco,gmac_pll_foutvco */
<1920000000>, <2376000000>, /* dvfs_pll_foutvco,dpu0_pll_foutvco */
<2376000000>, <2376000000>, /* dpu1_pll_foutvco,dpu2_pll_foutvco */
<330000000>, <165000000>, /* top_cfg_aclk,top_pclk */
<660000000>, <330000000>, /* top_amux_clk,iommu_ptw_aclk */
<950000000>, <1320000000>, /* noc_cclk,top_cpusys_bus_clk */
<1000000000>; /* top_cpusys_pic_clk */
status = "okay";
};
clk_gpu_die2: clock-controller@21 {
compatible = "zhihe,a210-gpu-clk-die2";
reg = <0x40 0x06D02200 0x0 0x200>, <0x40 0x06E06200 0x0 0x200>;
reg-names = "GPU_SS_PWRAP_CLK_EN","GPU_SS_TOP_CLK_EN";
#clock-cells = <1>;
assigned-clocks = <&clk_die2 TOP_GPU_CORE_CLK_DIV>;
assigned-clock-rates = <792000000>;
status = "okay";
};
clk_pcie_die2: clock-controller@22 {
compatible = "zhihe,a210-pcie-clk-die2";
reg = <0x40 0x0a000000 0x0 0x28>;
reg-names = "PCIE_CLK_EN";
#clock-cells = <1>;
assigned-clocks = <&clk_die2 TOP_PCIE_SCAN_REF_CLK0_DIV>, <&clk_die2 TOP_PCIE_SCAN_REF_CLK1_DIV>,
<&clk_die2 TOP_PCIE_AXI_M_ACLK_DIV>;
assigned-clock-rates = <396000000>, <1000000000>,
<786432000>;
status = "okay";
};
clk_usb_die2: clock-controller@23 {
compatible = "zhihe,a210-usb-clk-die2";
reg = <0x40 0x08000000 0x0 0x24>;
reg-names = "USB_CLK_EN";
#clock-cells = <1>;
assigned-clocks = <&clk_die2 TOP_USB_USB20_SCAN_REF_CLK_DIV>, <&clk_die2 TOP_USB_SCAN_REF_CLK3_DIV>,
<&clk_die2 TOP_USB_SCAN_REF_CLK2_DIV>, <&clk_die2 TOP_USB_SCAN_REF_CLK1_DIV>,
<&clk_die2 TOP_USB_SCAN_REF_CLK0_DIV>, <&clk_die2 TOP_USB_BUS_ACLK_DIV>,
<&clk_die2 TOP_USB_DP_AUX_CLK_DIV>;
assigned-clock-rates = <475200000>, <792000000>,
<600000000>, <500000000>,
<396000000>, <330000000>,
<16000000>;
status = "okay";
};
clk_vi_die2: clock-controller@24 {
compatible = "zhihe,a210-vi-clk-die2";
reg = <0x40 0x063a0200 0x0 0x200>;
reg-names = "VI_CLK";
#clock-cells = <1>;
status = "okay";
};
clk_vp_die2: clock-controller@25 {
compatible = "zhihe,a210-vp-clk-die2";
reg = <0x40 0x06b20200 0x0 0x200>;
reg-names = "VP_CLK";
#clock-cells = <1>;
assigned-clocks = <&clk_die2 TOP_VP_ACLK_DIV>, <&clk_die2 TOP_VP_VDEC_CCLK_DIV>,
<&clk_die2 TOP_VP_VENC_CCLK_DIV>, <&clk_die2 TOP_VP_G2D_CCLK_DIV>;
assigned-clock-rates = <880000000>, <786432000>,
<600000000>, <786432000>;
status = "okay";
};
clk_vo_die2: clock-controller@26 {
compatible = "zhihe,a210-vo-clk-die2";
reg = <0x40 0x06720048 0x0 0x4>, <0x40 0x06720200 0x0 0xc>;
reg-names = "VO_PATH_CTRL","VO_CLK";
#clock-cells = <1>;
assigned-clocks = <&clk_vo_die2 VO_DPUC_CLK_EN>, <&clk_vo_die2 VO_CH0_PIXCLK_EN>,
<&clk_vo_die2 VO_CH1_PIXCLK_EN>, <&clk_vo_die2 VO_CH2_PIXCLK_EN>,
<&clk_vo_die2 VO_DPU_ACLK_EN>, <&clk_vo_die2 VO_HDMI_PCLK_EN>,
<&clk_vo_die2 VO_DECOMP0_CLK_EN>, <&clk_vo_die2 VO_DECOMP1_CLK_EN>;
assigned-clock-rates = <880000000>, <594000000>,
<594000000>, <594000000>,
<880000000>, <165000000>,
<220000000>, <220000000>;
status = "okay";
};
clk_npu_die2: clock-controller@27 {
compatible = "zhihe,a210-npu-clk-die2";
reg = <0x40 0x07112210 0x0 0x4>,<0x40 0x07301050 0x0 0x4>;
reg-names = "NPU_CLK","NPU_TOP_CLK";
#clock-cells = <1>;
assigned-clocks = <&clk_die2 TOP_NPU_CCLK_DIV>, <&clk_die2 TOP_NPU_ACLK_DIV>;
assigned-clock-rates = <880000000>, <880000000>;
status = "okay";
};
clk_d2d_die2: clock-controller@28 {
compatible = "zhihe,a210-d2d-clk-die2";
reg = <0x40 0x09010000 0x0 0x4>;
reg-names = "D2D_CRG_REG";
#clock-cells = <1>;
assigned-clocks = <&clk_die2 TOP_D2D_ACLK_DIV>, <&clk_die2 TOP_D2D_REF_CLK_MUX>;
assigned-clock-rates = <950000000>, <100000000>;
status = "okay";
};
clk_peri_die2: clock-controller@29 {
compatible = "zhihe,a210-peri-clk-die2";
reg = <0x40 0x00300200 0x0 0x4>,
<0x40 0x02010200 0x0 0x8>,<0x40 0x08400200 0x0 0x8>,
<0x40 0x00540200 0x0 0x4>,<0x40 0x27420200 0x0 0x200>;
reg-names = "PERI0_SYSREG","PERI1_SYSREG","PERI2_SYSREG",
"PERI3_SYSREG","TEE_CRG";
#clock-cells = <1>;
assigned-clocks = <&clk_die2 TOP_PERI_TIMER_CLK_MUX>, <&clk_die2 TOP_PERI_I2S_2CH0_SRC_CLK_MUX>,
<&clk_die2 TOP_PERI_I2S_2CH1_SRC_CLK_MUX>, <&clk_die2 TOP_PERI_I2S_2CH2_SRC_CLK_MUX>,
<&clk_die2 TOP_PERI_I2S_8CH0_SRC_CLK_MUX>, <&clk_die2 TOP_PERI_SPI_SSI_CLK0_DIV>,
<&clk_die2 TOP_PERI_SPI_SSI_CLK1_DIV>, <&clk_die2 TOP_PERI_QSPI_SSI_CLK_MUX0>,
<&clk_die2 TOP_PERI_QSPI_SSI_CLK_MUX1>, <&clk_die2 TOP_PERI_PDM_MCLK_DIV>,
<&clk_die2 TOP_PERI_TDM_SRC_CLK_MUX>, <&clk_die2 TOP_PAD_SENSOR_VCLK0_DIV>,
<&clk_die2 TOP_PAD_SENSOR_VCLK1_DIV>, <&clk_die2 TOP_PERI_HIRES_CLK0_DIV>,
<&clk_die2 TOP_PERI_HIRES_CLK1_DIV>, <&clk_die2 TOP_TEE_CLK_DIV>,
<&clk_die2 TOP_PERI_EMMC_REF_CLK_DIV>, <&clk_die2 TOP_PERI_MST_ACLK0_DIV>,
<&clk_die2 TOP_PERI_MST_CLK1_DIV>;
assigned-clock-rates = <24000000>, <316108800>, /* peri0_timer_clk,peri1_i2s0_src_clk */
<316108800>, <316108800>, /* peri2_i2s1_src_clk,peri2_i2s2_src_clk */
<316108800>, <421478400>, /* peri2_i2s3_src_clk,peri1_spi_ssi_clk */
<421478400>, <421478400>, /* peri2_spi_ssi_clk,peri1_qspi_ssi_clk */
<421478400>, <31610880>, /* peri2_qspi_ssi_clk,peri1_pdm_mclk */
<316108800>, <74250000>, /* peri1_tdm_src_clk,top_pad_sensor_vclk0_div */
<148500000>, <80000000>, /* top_pad_sensor_vclk1,peri1_hires_clk */
<80000000>, <786432000>, /* peri2_hires_clk,emmc_ref_clk */
<330000000>, <440000000>, /* peri1_mst_aclk,peri3_mst_aclk */
<377142858>; /* tee_clk */
status = "okay";
};
clocks3 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
osc_32k_die3: clock-osc-32k {
compatible = "fixed-clock";
clock-frequency = <32768>;
clock-output-names = "osc_32k_die3";
#clock-cells = <0>;
};
osc_24m_die3: clock-osc-24m {
compatible = "fixed-clock";
clock-frequency = <24000000>;
clock-output-names = "osc_24m_die3";
#clock-cells = <0>;
};
aon_110m_die3: clock-osc-110m {
compatible = "fixed-clock";
clock-frequency = <110000000>;
clock-output-names = "aon_110m_die3";
#clock-cells = <0>;
};
rc_24m_die3: clock-rc-24m {
compatible = "fixed-clock";
clock-frequency = <24000000>;
clock-output-names = "rc_24m_die3";
#clock-cells = <0>;
};
apb_clk_die3: apb-clk-clock {
compatible = "fixed-clock";
clock-frequency = <62500000>;
clock-output-names = "apb_clk_die3";
#clock-cells = <0>;
};
};
clk_die3: clock-controller@30 {
compatible = "zhihe,a210-clk-die3";
reg = <0x60 0x00260000 0x0 0x1000>,<0x60 0x00250000 0x0 0x1000>,
<0x60 0x10141600 0x0 0x100>,<0x60 0x10141400 0x0 0x100>,
<0x60 0x04810000 0x0 0x1000>,<0x60 0x05810000 0x0 0x1000>,
<0x60 0x04900000 0x0 0x1000>,<0x60 0x20250000 0x0 0x1000>,
<0x60 0x10140000 0x0 0xE00>;
reg-names = "PLL_WRAP","TOP_CRG","CPU_SS_CLK_SYSREG","CPU_SS_CPU_PLL",
"DDR0_SYSREG","DDR1_SYSREG","SLC_DUAL_SYSREG","TOP_CRG_T","CPU_SS_CCU";
#clock-cells = <1>;
clocks = <&osc_32k_die3>, <&osc_24m_die3>, <&rc_24m_die3>;
clock-names = "osc_32k", "osc_24m", "rc_24m";
assigned-clocks = <&clk_die3 AUDIO0_PLL_FOUTVCO>, <&clk_die3 AUDIO1_PLL_FOUTVCO>,
<&clk_die3 VIDEO_PLL_FOUTVCO>, <&clk_die3 GMAC_PLL_FOUTVCO>,
<&clk_die3 DVFS_PLL_FOUTVCO>, <&clk_die3 DPU0_PLL_FOUTVCO>,
<&clk_die3 DPU1_PLL_FOUTVCO>, <&clk_die3 DPU2_PLL_FOUTVCO>,
<&clk_die3 TOP_CFG_ACLK_DIV>, <&clk_die3 TOP_PCLK_DIV>,
<&clk_die3 SW_AMUX_660_CLK_EN>, <&clk_die3 SW_IOMMU_PTW_330_ACLK_EN>,
<&clk_die3 SW_NOC_CCLK_EN>, <&clk_die3 TOP_CPUSYS_BUS_CLK_DIV>,
<&clk_die3 TOP_CPUSYS_PIC_CLK_DIV>;
assigned-clock-rates = <2359296000>, <2528870400>, /* audio0_pll_foutvco,audio1_pll_foutvco */
<2640000000>, <3000000000>, /* video_pll_foutvco,gmac_pll_foutvco */
<1920000000>, <2376000000>, /* dvfs_pll_foutvco,dpu0_pll_foutvco */
<2376000000>, <2376000000>, /* dpu1_pll_foutvco,dpu2_pll_foutvco */
<330000000>, <165000000>, /* top_cfg_aclk,top_pclk */
<660000000>, <330000000>, /* top_amux_clk,iommu_ptw_aclk */
<950000000>, <1320000000>, /* noc_cclk,top_cpusys_bus_clk */
<1000000000>; /* top_cpusys_pic_clk */
status = "okay";
};
clk_gpu_die3: clock-controller@31 {
compatible = "zhihe,a210-gpu-clk-die3";
reg = <0x60 0x06D02200 0x0 0x200>, <0x60 0x06E06200 0x0 0x200>;
reg-names = "GPU_SS_PWRAP_CLK_EN","GPU_SS_TOP_CLK_EN";
#clock-cells = <1>;
assigned-clocks = <&clk_die3 TOP_GPU_CORE_CLK_DIV>;
assigned-clock-rates = <792000000>;
status = "okay";
};
clk_pcie_die3: clock-controller@32 {
compatible = "zhihe,a210-pcie-clk-die3";
reg = <0x60 0x0a000000 0x0 0x28>;
reg-names = "PCIE_CLK_EN";
#clock-cells = <1>;
assigned-clocks = <&clk_die3 TOP_PCIE_SCAN_REF_CLK0_DIV>, <&clk_die3 TOP_PCIE_SCAN_REF_CLK1_DIV>,
<&clk_die3 TOP_PCIE_AXI_M_ACLK_DIV>;
assigned-clock-rates = <396000000>, <1000000000>,
<786432000>;
status = "okay";
};
clk_usb_die3: clock-controller@33 {
compatible = "zhihe,a210-usb-clk-die3";
reg = <0x60 0x08000000 0x0 0x24>;
reg-names = "USB_CLK_EN";
#clock-cells = <1>;
assigned-clocks = <&clk_die3 TOP_USB_USB20_SCAN_REF_CLK_DIV>, <&clk_die3 TOP_USB_SCAN_REF_CLK3_DIV>,
<&clk_die3 TOP_USB_SCAN_REF_CLK2_DIV>, <&clk_die3 TOP_USB_SCAN_REF_CLK1_DIV>,
<&clk_die3 TOP_USB_SCAN_REF_CLK0_DIV>, <&clk_die3 TOP_USB_BUS_ACLK_DIV>,
<&clk_die3 TOP_USB_DP_AUX_CLK_DIV>;
assigned-clock-rates = <475200000>, <792000000>,
<600000000>, <500000000>,
<396000000>, <330000000>,
<16000000>;
status = "okay";
};
clk_vi_die3: clock-controller@34 {
compatible = "zhihe,a210-vi-clk-die3";
reg = <0x60 0x063a0200 0x0 0x200>;
reg-names = "VI_CLK";
#clock-cells = <1>;
status = "okay";
};
clk_vp_die3: clock-controller@35 {
compatible = "zhihe,a210-vp-clk-die3";
reg = <0x60 0x06b20200 0x0 0x200>;
reg-names = "VP_CLK";
#clock-cells = <1>;
assigned-clocks = <&clk_die3 TOP_VP_ACLK_DIV>, <&clk_die3 TOP_VP_VDEC_CCLK_DIV>,
<&clk_die3 TOP_VP_VENC_CCLK_DIV>, <&clk_die3 TOP_VP_G2D_CCLK_DIV>;
assigned-clock-rates = <880000000>, <786432000>,
<600000000>, <786432000>;
status = "okay";
};
clk_vo_die3: clock-controller@36 {
compatible = "zhihe,a210-vo-clk-die3";
reg = <0x60 0x06720048 0x0 0x4>, <0x60 0x06720200 0x0 0xc>;
reg-names = "VO_PATH_CTRL","VO_CLK";
#clock-cells = <1>;
assigned-clocks = <&clk_vo_die3 VO_DPUC_CLK_EN>, <&clk_vo_die3 VO_CH0_PIXCLK_EN>,
<&clk_vo_die3 VO_CH1_PIXCLK_EN>, <&clk_vo_die3 VO_CH2_PIXCLK_EN>,
<&clk_vo_die3 VO_DPU_ACLK_EN>, <&clk_vo_die3 VO_HDMI_PCLK_EN>,
<&clk_vo_die3 VO_DECOMP0_CLK_EN>, <&clk_vo_die3 VO_DECOMP1_CLK_EN>;
assigned-clock-rates = <880000000>, <594000000>,
<594000000>, <594000000>,
<880000000>, <165000000>,
<220000000>, <220000000>;
status = "okay";
};
clk_npu_die3: clock-controller@37 {
compatible = "zhihe,a210-npu-clk-die3";
reg = <0x60 0x07112210 0x0 0x4>,<0x60 0x07301050 0x0 0x4>;
reg-names = "NPU_CLK","NPU_TOP_CLK";
#clock-cells = <1>;
assigned-clocks = <&clk_die3 TOP_NPU_CCLK_DIV>, <&clk_die3 TOP_NPU_ACLK_DIV>;
assigned-clock-rates = <880000000>, <880000000>;
status = "okay";
};
clk_d2d_die3: clock-controller@38 {
compatible = "zhihe,a210-d2d-clk-die3";
reg = <0x60 0x09010000 0x0 0x4>;
reg-names = "D2D_CRG_REG";
#clock-cells = <1>;
assigned-clocks = <&clk_die3 TOP_D2D_ACLK_DIV>, <&clk_die3 TOP_D2D_REF_CLK_MUX>;
assigned-clock-rates = <950000000>, <100000000>;
status = "okay";
};
clk_peri_die3: clock-controller@39 {
compatible = "zhihe,a210-peri-clk-die3";
reg = <0x60 0x00300200 0x0 0x4>,
<0x60 0x02010200 0x0 0x8>,<0x60 0x08400200 0x0 0x8>,
<0x60 0x00540200 0x0 0x4>,<0x60 0x27420200 0x0 0x200>;
reg-names = "PERI0_SYSREG","PERI1_SYSREG","PERI2_SYSREG",
"PERI3_SYSREG","TEE_CRG";
#clock-cells = <1>;
assigned-clocks = <&clk_die3 TOP_PERI_TIMER_CLK_MUX>, <&clk_die3 TOP_PERI_I2S_2CH0_SRC_CLK_MUX>,
<&clk_die3 TOP_PERI_I2S_2CH1_SRC_CLK_MUX>, <&clk_die3 TOP_PERI_I2S_2CH2_SRC_CLK_MUX>,
<&clk_die3 TOP_PERI_I2S_8CH0_SRC_CLK_MUX>, <&clk_die3 TOP_PERI_SPI_SSI_CLK0_DIV>,
<&clk_die3 TOP_PERI_SPI_SSI_CLK1_DIV>, <&clk_die3 TOP_PERI_QSPI_SSI_CLK_MUX0>,
<&clk_die3 TOP_PERI_QSPI_SSI_CLK_MUX1>, <&clk_die3 TOP_PERI_PDM_MCLK_DIV>,
<&clk_die3 TOP_PERI_TDM_SRC_CLK_MUX>, <&clk_die3 TOP_PAD_SENSOR_VCLK0_DIV>,
<&clk_die3 TOP_PAD_SENSOR_VCLK1_DIV>, <&clk_die3 TOP_PERI_HIRES_CLK0_DIV>,
<&clk_die3 TOP_PERI_HIRES_CLK1_DIV>, <&clk_die3 TOP_TEE_CLK_DIV>,
<&clk_die3 TOP_PERI_EMMC_REF_CLK_DIV>, <&clk_die3 TOP_PERI_MST_ACLK0_DIV>,
<&clk_die3 TOP_PERI_MST_CLK1_DIV>;
assigned-clock-rates = <24000000>, <316108800>, /* peri0_timer_clk,peri1_i2s0_src_clk */
<316108800>, <316108800>, /* peri2_i2s1_src_clk,peri2_i2s2_src_clk */
<316108800>, <421478400>, /* peri2_i2s3_src_clk,peri1_spi_ssi_clk */
<421478400>, <421478400>, /* peri2_spi_ssi_clk,peri1_qspi_ssi_clk */
<421478400>, <31610880>, /* peri2_qspi_ssi_clk,peri1_pdm_mclk */
<316108800>, <74250000>, /* peri1_tdm_src_clk,top_pad_sensor_vclk0_div */
<148500000>, <80000000>, /* top_pad_sensor_vclk1,peri1_hires_clk */
<80000000>, <786432000>, /* peri2_hires_clk,emmc_ref_clk */
<330000000>, <440000000>, /* peri1_mst_aclk,peri3_mst_aclk */
<377142858>; /* tee_clk */
status = "okay";
}; };
}; };
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -21,99 +21,226 @@
status = "okay"; status = "okay";
}; };
uart0_die1: serial@2002014000 { peri1_padctrl_die1: peri1-padctrl@2002026000 {
compatible = "snps,dw-apb-uart", "ns16550"; compatible = "zhihe,a210-group1-pinctrl";
reg = <0x20 0x02014000 0x0 0x400>; reg = <0x20 0x02026000 0x0 0x1000>;
interrupt-parent = <&intc_die1>; clocks = <&clk_peri_die1 PERI1_PAD_CTRL_PCLK_EN>;
interrupts = <321>; clock-names = "pclk";
clock-names = "baudclk";
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay"; status = "okay";
}; };
uart1_die1: serial@2002015000 { peri2_padctrl_die1: peri2-padctrl@2008411000 {
compatible = "snps,dw-apb-uart"; compatible = "zhihe,a210-group2-pinctrl";
reg = <0x20 0x02015000 0x0 0x1000>; reg = <0x20 0x08411000 0x0 0x1000>;
interrupt-parent = <&intc_die1>; clocks = <&clk_peri_die1 PERI2_PAD_CTRL_PCLK_EN>;
interrupts = <322>; clock-names = "pclk";
clocks = <&clk PERI1_UART1_SCLK_EN>; status = "okay";
clock-names = "baudclk";
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "disabled";
}; };
uart2_die1: serial@2002016000 { gpio@2002012000 {
compatible = "snps,dw-apb-uart"; compatible = "snps,dw-apb-gpio";
reg = <0x20 0x02016000 0x0 0x1000>; reg = <0x20 0x02012000 0x0 0x1000>;
interrupt-parent = <&intc_die1>; #address-cells = <1>;
interrupts = <323>; #size-cells = <0>;
clocks = <&clk PERI1_UART2_SCLK_EN>; clocks = <&clk_peri_die1 PERI1_GPIO0_PCLK_EN>,
clock-names = "baudclk"; <&clk_peri_die1 PERI1_GPIO0_DBCLK_EN>;
reg-shift = <2>; clock-names = "bus", "db";
reg-io-width = <4>; status = "okay";
hw-flow-control = "unsupport";
status = "disabled"; gpio0_die1: gpio0-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
ngpios = <32>;
gpio-ranges = <&peri1_padctrl_die1 0 0 32>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc_die1>;
interrupts = <289>;
};
}; };
uart3_die1: serial@2002017000 { gpio@2002013000 {
compatible = "snps,dw-apb-uart"; compatible = "snps,dw-apb-gpio";
reg = <0x20 0x02017000 0x0 0x1000>; reg = <0x20 0x02013000 0x0 0x1000>;
interrupt-parent = <&intc_die1>; #address-cells = <1>;
interrupts = <37>; #size-cells = <0>;
clocks = <&clk PERI1_UART3_SCLK_EN>; clocks = <&clk_peri_die1 PERI1_GPIO1_PCLK_EN>,
clock-names = "baudclk"; <&clk_peri_die1 PERI1_GPIO1_DBCLK_EN>;
reg-shift = <2>; clock-names = "bus", "db";
reg-io-width = <4>; status = "okay";
hw-flow-control = "unsupport";
status = "disabled"; gpio1_die1: gpio1-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
ngpios = <18>;
gpio-ranges = <&peri1_padctrl_die1 0 32 18>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc_die1>;
interrupts = <290>;
};
}; };
uart4_die1: serial@200008401000 { gpio@2008410000 {
compatible = "snps,dw-apb-gpio";
reg = <0x20 0x08410000 0x0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clk_peri_die1 PERI2_GPIO2_PCLK_EN>,
<&clk_peri_die1 PERI2_GPIO2_DBCLK_EN>;
clock-names = "bus", "db";
status = "okay";
gpio2_die1: gpio2-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
ngpios = <32>;
gpio-ranges = <&peri2_padctrl_die1 0 0 32>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc_die1>;
interrupts = <291>;
};
};
gpio@2008412000 {
compatible = "snps,dw-apb-gpio";
reg = <0x20 0x08412000 0x0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clk_peri_die1 PERI2_GPIO3_PCLK_EN>,
<&clk_peri_die1 PERI2_GPIO3_DBCLK_EN>;
clock-names = "bus", "db";
status = "okay";
gpio3_die1: gpio3-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
ngpios = <11>;
gpio-ranges = <&peri2_padctrl_die1 0 32 11>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc_die1>;
interrupts = <292>;
};
};
qspi0_die1: spi@2001000000 {
compatible = "snps,dw-apb-ssi-quad";
reg = <0x20 0x01000000 0x0 0x4000>;
interrupt-parent = <&intc_die1>;
interrupts = <308>;
clocks = <&clk_peri_die1 PERI1_QSPI0_SSI_CLK_EN>;
clock-names = "sclk";
num-cs = <2>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
};
qspi1_die1: spi@2008428000 {
compatible = "snps,dw-apb-ssi-quad";
reg = <0x20 0x08428000 0x0 0x4000>;
interrupt-parent = <&intc_die1>;
interrupts = <309>;
clocks = <&clk_peri_die1 PERI2_QSPI1_SSI_CLK_EN>;
clock-names = "sclk";
num-cs = <2>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
};
uart4_die1: serial@2008401000 {
compatible = "snps,dw-apb-uart"; compatible = "snps,dw-apb-uart";
reg = <0x20 0x0008401000 0x0 0x400>; reg = <0x20 0x08401000 0x0 0x400>;
interrupt-parent = <&intc_die1>; interrupt-parent = <&intc_die1>;
interrupts = <325>; interrupts = <325>;
clocks = <&clk PERI2_UART4_SCLK_EN>; clocks = <&clk_peri_die1 PERI2_UART4_PCLK_EN>, <&clk_peri_die1 PERI2_UART4_SCLK_EN>;
clock-names = "baudclk"; clock-names = "apb_pclk", "baudclk";
reg-shift = <2>; reg-shift = <2>;
reg-io-width = <4>; reg-io-width = <4>;
hw-flow-control = "unsupport"; hw-flow-control = "unsupport";
status = "okay"; status = "okay";
}; };
mbox_920_die1: mbox@2000320000 { mbox_920_die1: mbox@2000320000 {
compatible = "zhihe,a210-mbox"; compatible = "zhihe,mailbox";
reg = <0x20 0x00321000 0x0 0x1000>, //mailbox1的中断通道 reg = <0x20 0x00321000 0x0 0x1000>,
<0x20 0x00320000 0x0 0x1000>, <0x20 0x00320000 0x0 0x1000>,
<0x20 0x00322000 0x0 0x1000>, <0x20 0x00311000 0x0 0x1000>;
<0x00 0x00312000 0x0 0x1000>,
<0x20 0x00312000 0x0 0x1000>;
reg-names = "interrupt_addr", reg-names = "interrupt_addr",
"local_addr0", "local_addr0",
"local_addr1", "remote_icu0";
"remote_icu0",
"remote_icu1";
interrupt-parent = <&intc_die1>; interrupt-parent = <&intc_die1>;
interrupts = <336 IRQ_TYPE_LEVEL_HIGH>; interrupts = <336 IRQ_TYPE_LEVEL_HIGH>;
icu_cpu_id = <1>; icu_cpu_id = <1>;
#mbox-cells = <2>; #mbox-cells = <2>;
version = <1>;
status = "okay"; status = "okay";
}; };
aon_die1_to_die0: aon_subsys_die1_to_die0 {
compatible = "zhihe,a210-aon"; aon_die1: aon_subsys1@20308f8000 {
mbox-names = "aon2"; compatible = "zhihe,aon";
mboxes = <&mbox_920_die1 1 0>; //parent / channel / type reg = <0x20 0x308f8000 0x0 0x10000>,
<0x20 0x30842018 0x0 0x4>,
<0x20 0x30846144 0x0 0x4>;
reg-names = "aon_base_addr",
"aon_reset_reg",
"aon_sync_reg";
firmware-name = "a210-aon.bin";
mboxes = <&mbox_920_die1 1 0>; //parent / channel / type
mbox-names = "aon1";
#mbox-cells = <2>; #mbox-cells = <2>;
version = <1>;
status = "okay"; status = "okay";
}; };
aon_die1_to_die1: aon_subsys_die1_to_die1 {
compatible = "zhihe,a210-aon"; npu1: vipcore1@0x2007000000 {
mbox-names = "aon3"; compatible = "verisilicon,vipcore1";
mboxes = <&mbox_920_die1 1 0>; reg = <0x20 0x07000000 0x00 0x10000>;
#mbox-cells = <2>; interrupt-parent = <&intc>;
interrupts = <71>;
clocks = <&clk_die1 TOP_NPU_CCLK_DIV>,
<&clk_die1 TOP_NPU_ACLK_DIV>;
clock-names = "npu_cclk", "npu_aclk";
power-domains = <&power_npu_ip>;
status = "okay";
};
npu2: vipcore2@0x4007000000 {
compatible = "verisilicon,vipcore2";
reg = <0x40 0x07000000 0x00 0x10000>;
interrupt-parent = <&intc>;
interrupts = <71>;
clocks = <&clk_die2 TOP_NPU_CCLK_DIV>,
<&clk_die2 TOP_NPU_ACLK_DIV>;
clock-names = "npu_cclk", "npu_aclk";
power-domains = <&power_npu_ip>;
status = "okay";
};
npu3: vipcore3@0x6007000000 {
compatible = "verisilicon,vipcore3";
reg = <0x60 0x07000000 0x00 0x10000>;
interrupt-parent = <&intc>;
interrupts = <71>;
clocks = <&clk_die3 TOP_NPU_CCLK_DIV>,
<&clk_die3 TOP_NPU_ACLK_DIV>;
clock-names = "npu_cclk", "npu_aclk";
power-domains = <&power_npu_ip>;
status = "okay"; status = "okay";
}; };
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -125,8 +125,8 @@
simple-audio-card,widgets = "Speaker", "Speaker"; simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing = simple-audio-card,routing =
"Speaker", "AW87565_PA2 VO", "Speaker", "AW87565_PA2 VO",
"AW87565_PA2 IN", "ES8156_DAC1 LOUT"; "AW87565_PA2 IN", "ES8156_DAC1 LOUT";
simple-audio-card,aux-devs = <&audio_aw87565_pa2>; simple-audio-card,aux-devs = <&audio_aw87565_pa2>;
SOUND_CARD_LINK(0, i2s, i2s1, 0, es8156_dac1, 0); SOUND_CARD_LINK(0, i2s, i2s1, 0, es8156_dac1, 0);
SOUND_CARD_LINK(1, i2s, i2s1, 0, es7210_adc1, 0); SOUND_CARD_LINK(1, i2s, i2s1, 0, es7210_adc1, 0);
@@ -505,16 +505,16 @@
}; };
&qspi0 { &qspi0 {
cs-gpios = <&gpio0_porta 19 0>; cs-gpios = <&gpio0 19 0>;
rx-sample-dly = <2>; rx-sample-dly = <2>;
spi-swap-data = <1>; spi-swap-data = <1>;
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>; pinctrl-0 = <&qspi0_pins>;
spi_norflash@0 { spi_norflash@0 {
compatible = "jedec,spi-nor"; compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>; spi-max-frequency = <42000000>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
spi-tx-bus-width = <4>; spi-tx-bus-width = <4>;

View File

@@ -0,0 +1,635 @@
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include "a210-soc-core.dtsi"
#include "a210-soc-peri.dtsi"
#include "a210-platform-dev.dtsi"
#define SOUND_CARD_LINK(REG, FMT, CPU, M, CODEC, N) \
simple-audio-card,dai-link@##REG { \
reg = <REG>; \
format = #FMT; \
cpu { \
sound-dai = <&audio_##CPU M>; \
}; \
codec { \
sound-dai = <&codec_##CODEC N>; \
}; \
}
/ {
model = "A210 DEV configuration";
aliases {
ethernet0 = &gmac0;
ethernet1 = &gmac1;
gpio0 = &ao_gpio0;
gpio1 = &ao_gpio1;
gpio2 = &gpio0;
gpio3 = &gpio1;
gpio4 = &gpio2;
gpio5 = &gpio3;
gpio6 = &gpio4;
i2c0 = &i2c0;
i2c1 = &i2c1;
i2c2 = &i2c2;
i2c3 = &i2c3;
i2c4 = &i2c4;
i2c5 = &i2c5;
i2c6 = &i2c6;
i2c7 = &i2c7;
i2c8 = &aoi2c1;
can0 = &can0;
can1 = &can1;
can2 = &can2;
mmc0 = &emmc;
mmc1 = &sdhci0;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
serial3 = &uart3;
serial4 = &uart4;
serial5 = &uart5;
serial6 = &uart6;
serial7 = &uart7;
serial8 = &uart8;
serial9 = &uart9;
spi0 = &qspi0;
spi1 = &qspi1;
spi2 = &spi0;
spi3 = &spi1;
pcie3x4 = &dm3x4;
pcie3x1 = &rp3x1;
};
/* The actual capacity will be adjusted through SPL */
memory@0 {
device_type = "memory";
reg = <0x00 0x80000000 0x01 0x00000000>; /* 4G */
numa-node-id = <0>;
};
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0x00 0x40000000>;
alloc-ranges = <0x00 0x90000000 0x00 0x40000000>;
linux,cma-default;
};
memory@1c000000 {
reg = <0x00 0x1c000000 0x00 0x2000000>;
no-map;
};
framebuffer: framebuffer@10000000 {
reg = <0x01 0x00 0x00 0x5000000>;
no-map;
};
npu_mmu_memory@130000000 {
reg = <0x01 0x30000000 0x00 0x04000000>;
no-map;
};
memblock-memory@17b800000 {
reg = <0x01 0x7b800000 0x00 0x04000000>;
no-map;
};
};
/* The bootargs in U-Boot will override the configuration set here. */
chosen {
stdout-path = "serial4";
};
};
&aon {
regulators {
compatible = "zhihe,a210-aon-regulator";
avdd33_emmc_reg: avdd33_emmc {
regulator-name = "avdd33_emmc";
regulator-type = "voltage";
regulator-always-on;
};
avdd33_usb2_reg: avdd33_usb2 {
regulator-name = "avdd33_usb2";
regulator-type = "voltage";
regulator-always-on;
};
dvdd08_aon_reg: dvdd08_aon {
regulator-name = "dvdd08_aon";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_aon_reg: avdd18_aon {
regulator-name = "avdd18_aon";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_emmc_usb2_reg: avdd18_emmc_usb2 {
regulator-name = "avdd18_emmc_usb2";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_emmc_peri_reg: avdd18_emmc_peri {
regulator-name = "avdd18_emmc_peri";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_top_reg: avdd18_top {
regulator-name = "avdd18_top";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_pll_reg: avdd18_pll {
regulator-name = "avdd18_pll";
regulator-type = "voltage";
regulator-always-on;
};
avdd18_reg: avdd18 {
regulator-name = "avdd18";
regulator-type = "voltage";
regulator-always-on;
};
dvdd18_ddr_vaa_reg: dvdd18_ddr_vaa {
regulator-name = "dvdd18_ddr_vaa";
regulator-type = "voltage";
regulator-always-on;
};
p3v3_reg: p3v3 {
regulator-name = "p3v3";
regulator-type = "voltage";
regulator-always-on;
};
dvdd08_top_reg: dvdd08_top {
regulator-name = "dvdd08_top";
regulator-type = "voltage";
regulator-always-on;
};
dvdd06_ddr_vddqlp_reg: dvdd06_ddr_vddqlp {
regulator-name = "dvdd06_ddr_vddqlp";
regulator-type = "voltage";
regulator-always-on;
};
dvdd08_ddr_reg: dvdd08_ddr {
regulator-name = "dvdd08_ddr";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <800000>;
regulator-always-on;
};
dvdd_cpu_reg: dvdd_cpu {
regulator-name = "dvdd_cpu";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
};
dvddm_cpu_reg: dvddm_cpu {
regulator-name = "dvddm_cpu";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
};
dvdd_vp_reg: dvdd_vp {
regulator-name = "dvdd_vp";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <800000>;
regulator-always-on;
};
dvdd_npu_vip_reg: dvdd_npu_vip {
regulator-name = "dvdd_npu_vip";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
};
dvdd_cpu_p_reg: dvdd_cpu_p {
regulator-name = "dvdd_cpu_p";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
};
dvdd_gpu_reg: dvdd_gpu {
regulator-name = "dvdd_gpu";
regulator-type = "voltage";
regulator-ramp-delay = <100>;
regulator-min-microvolt = <750000>;
regulator-max-microvolt = <800000>;
regulator-always-on;
};
};
cpufreq: a210_cpufreq {
compatible = "zhihe,a210-cpufreq";
clocks = <&clk TOP_CPUSYS_BUS_CLK_DIV>,
<&clk TOP_CPUSYS_PIC_CLK_DIV>,
<&clk TOP_CPUSYS_CFG_ACLK_DIV>,
<&clk TOP_CPUSYS_COM_APB_CLK_DIV>,
<&clk TOP_CPUSYS_APB_CLK_DIV>;
clock-names = "bus_clk", "pic_clk", "cfg_clk", "com_clk", "apb_clk";
status = "okay";
};
};
&aon_padctrl {
rtc_pins: rtc {
rtc-pins {
pins = "AOGPIO0_27";
function = "aogpio0";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-disable;
slew-rate = <0>;
};
};
aoi2c1_pins: aoi2c1-0 {
i2c-pins {
pins = "AOI2C1_SCL", "AOI2C1_SDA";
function = "aoi2c1";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
};
&peri1_padctrl {
sdhci_pins: sdhci0-1 {
sd-pins {
pins = "GPIO1_1";
function = "sdio";
bias-disable;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
usb3_pins: usb3-1 {
usb3-pins {
pins = "GPIO0_27";
function = "gpio0";
bias-disable;
drive-strength = <13>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
};
};
&peri2_padctrl {
uart4_pins: uart4-0 {
tx-pins {
pins = "GPIO2_0";
function = "uart4";
bias-disable;
drive-strength = <3>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO2_1";
function = "uart4";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c5_pins: i2c5-1 {
i2c-pins {
pins = "GPIO2_28", "GPIO2_29";
function = "i2c5";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
uart5_pins: uart5-1 {
tx-pins {
pins = "GPIO2_18", "GPIO3_10"; // TXD, RTSN
function = "uart5";
bias-disable;
drive-strength = <3>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO2_19", "GPIO3_9"; // RXD, CTSN
function = "uart5";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c6_pins: i2c6-1 {
i2c-pins {
pins = "GPIO2_8", "GPIO2_9";
function = "i2c6";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2s1_pins: i2s1-0 {
i2s-pins {
pins = "GPIO2_2", "GPIO2_3", "GPIO2_4", "GPIO2_5", "GPIO2_6";
function = "i2s1";
bias-disable;
drive-strength = <13>;
input-schmitt-disable;
slew-rate = <0>;
};
};
i2c7_pins: i2c7-0 {
i2c-pins {
pins = "GPIO2_10", "GPIO2_11";
function = "i2c7";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
i2c4_pins: i2c4-2 {
i2c-pins {
pins = "GPIO2_26", "GPIO2_27";
function = "i2c4";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
sen_vclk_pin0: sen_vclk0 {
sen_vclk0-pins {
pins = "GPIO3_0";
function = "sen_vclk";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
sen_vclk_pin1: sen_vclk1 {
sen_vclk1-pins {
pins = "GPIO3_1";
function = "sen_vclk";
bias-disable;
drive-strength = <7>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
uart8_pins: uart8-1 {
tx-pins {
pins = "GPIO3_2"; // TXD
function = "uart8";
bias-disable;
drive-strength = <3>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO3_3"; // RXD
function = "uart8";
bias-disable;
drive-strength = <1>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
};
};
};
&gmac0 {
status = "disabled";
};
&mdio0 {
status = "disabled";
};
&gmac1 {
status = "disabled";
};
&mdio1 {
status = "disabled";
};
&qspi0 {
status = "disabled";
};
&i2c4 {
pinctrl-names = "default";
pinctrl-0 = <&i2c4_pins>;
clock-frequency = <400000>;
};
&i2c5 {
pinctrl-names = "default";
pinctrl-0 = <&i2c5_pins>;
clock-frequency = <400000>;
};
&i2c6 {
pinctrl-names = "default";
pinctrl-0 = <&i2c6_pins>;
clock-frequency = <400000>;
};
&i2c7 {
pinctrl-names = "default";
pinctrl-0 = <&i2c7_pins>;
clock-frequency = <400000>;
};
&aoi2c1 {
pinctrl-names = "default";
pinctrl-0 = <&aoi2c1_pins>;
clock-frequency = <400000>;
status = "okay";
};
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins>;
};
&uart5 {
pinctrl-names = "default";
pinctrl-0 = <&uart5_pins>;
};
&uart8 {
pinctrl-names = "default";
pinctrl-0 = <&uart8_pins>;
};
&rp3x1 {
status = "disabled";
};
&dm3x4 {
status = "disabled";
};
&audio_i2s1 {
status = "disabled";
};
&adc {
status = "disabled";
};
&pwm0 {
status = "disabled";
};
&pwm1 {
status = "disabled";
};
&can0 {
status = "disabled";
};
&hdmi_tx {
status = "disabled";
};
&vidmem {
memory-region = <&framebuffer>;
};
&emmc {
max-frequency = <196608000>;
non-removable;
mmc-hs400-1_8v;
mmc-hs200-1_8v;
io_fixed_1v8;
is_emmc;
no-sdio;
no-sd;
pull_up;
bus-width = <8>;
cap-mmc-highspeed;
};
&sdhci0 {
pinctrl-names = "default";
pinctrl-0 = <&sdhci_pins>;
max-frequency = <196608000>;
cap-sd-highspeed;
bus-width = <4>;
sd-uhs-sdr104;
pull_up;
no-sd;
no-mmc;
non-removable;
io_fixed_1v8;
post-power-on-delay-ms = <200>;
wprtn_ignore;
wakeup-source;
};
&usb3 {
pinctrl-names = "default";
pinctrl-0 = <&usb3_pins>;
typec-pwren-gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>;
};
&sata {
status = "disabled";
};
&mipi0_csi0 {
status = "disabled";
};
&mipi0_csi1 {
status = "disabled";
};
//config dsi display: dpu_disp0->dup_enc0->dsi0->lcd_plane
&dpu_enc0 {
status = "disabled";
};
&dsi_host0 {
status = "disabled";
};
&c920_4 {
dvdd-cpu-p-supply = <&dvdd_cpu_p_reg>;
};
&c908_0 {
dvdd-cpu-supply = <&dvdd_cpu_reg>;
dvddm-cpu-supply = <&dvddm_cpu_reg>;
};

199
arch/riscv/configs/a210_evb_defconfig Executable file → Normal file
View File

@@ -1,12 +1,11 @@
# CONFIG_LOCALVERSION_AUTO is not set # CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y CONFIG_BPF_JIT=y
CONFIG_PREEMPT=y CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_TASKSTATS=y CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y CONFIG_TASK_XACCT=y
@@ -17,6 +16,7 @@ CONFIG_NUMA_BALANCING=y
CONFIG_CGROUPS=y CONFIG_CGROUPS=y
CONFIG_MEMCG=y CONFIG_MEMCG=y
CONFIG_CGROUP_SCHED=y CONFIG_CGROUP_SCHED=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y CONFIG_CPUSETS=y
@@ -38,17 +38,29 @@ CONFIG_PERF_EVENTS=y
CONFIG_CRASH_DUMP=y CONFIG_CRASH_DUMP=y
CONFIG_ARCH_ZHIHE=y CONFIG_ARCH_ZHIHE=y
CONFIG_XUANTIE_SSTC=y CONFIG_XUANTIE_SSTC=y
CONFIG_ERRATA_THEAD=y CONFIG_ARCH_THEAD=y
# CONFIG_ERRATA_THEAD_PBMT is not set CONFIG_ARCH_XUANTIE=y
CONFIG_SOC_VIRT=y
CONFIG_NONPORTABLE=y CONFIG_NONPORTABLE=y
CONFIG_SMP=y CONFIG_SMP=y
CONFIG_NR_CPUS=16 CONFIG_NR_CPUS=16
CONFIG_NUMA=y CONFIG_NUMA=y
CONFIG_XUANTIE_ISA=y CONFIG_XUANTIE_ISA=y
CONFIG_RISCV_SBI_V01=y
# CONFIG_SUSPEND is not set # CONFIG_SUSPEND is not set
CONFIG_PM=y CONFIG_PM=y
CONFIG_PM_DEBUG=y CONFIG_PM_DEBUG=y
CONFIG_PM_ADVANCED_DEBUG=y CONFIG_PM_ADVANCED_DEBUG=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_RISCV_XUANTIE_TH1520_CPUFREQ=y
CONFIG_RISCV_ZHIHE_CPUFREQ=y
CONFIG_KPROBES=y CONFIG_KPROBES=y
CONFIG_MODULES=y CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_UNLOAD=y
@@ -60,8 +72,6 @@ CONFIG_CMA_SYSFS=y
CONFIG_CMA_AREAS=16 CONFIG_CMA_AREAS=16
CONFIG_NET=y CONFIG_NET=y
CONFIG_PACKET=y CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_PNP=y CONFIG_IP_PNP=y
@@ -74,46 +84,68 @@ CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=y CONFIG_NF_TABLES_INET=y
CONFIG_BPFILTER=y CONFIG_BPFILTER=y
CONFIG_BRIDGE=y CONFIG_BRIDGE=y
CONFIG_VLAN_8021Q=m
CONFIG_DNS_RESOLVER=y CONFIG_DNS_RESOLVER=y
CONFIG_NETLINK_DIAG=y
CONFIG_CAN=m CONFIG_CAN=m
CONFIG_CAN_J1939=m CONFIG_CAN_J1939=m
CONFIG_CAN_ISOTP=m CONFIG_CAN_ISOTP=m
CONFIG_CFG80211=y CONFIG_BT=y
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=y
CONFIG_BT_HIDP=y
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_RTL3WIRE=y
CONFIG_CFG80211=m
CONFIG_CFG80211_WEXT=y CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=y CONFIG_MAC80211=m
CONFIG_RFKILL=y CONFIG_RFKILL=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
# CONFIG_ETHTOOL_NETLINK is not set # CONFIG_ETHTOOL_NETLINK is not set
CONFIG_PCI=y CONFIG_PCI=y
CONFIG_PCIE_ZH=m CONFIG_PCIE_ZH=m
CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TH1520_AON_PD=y
CONFIG_TH1520_PROC_DEBUG=y
CONFIG_ZHIHE_PROC_DEBUG=y CONFIG_ZHIHE_PROC_DEBUG=y
CONFIG_MTD=y CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_OF_PARTS=m CONFIG_MTD_OF_PARTS=m
CONFIG_MTD_BLOCK=y CONFIG_MTD_BLOCK=y
CONFIG_MTD_SLRAM=m
CONFIG_MTD_PHRAM=m
CONFIG_MTD_SPI_NAND=y CONFIG_MTD_SPI_NAND=y
CONFIG_MTD_SPI_NOR=y CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_UBI=y CONFIG_MTD_UBI=y
CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=1 CONFIG_BLK_DEV_RAM_COUNT=1
CONFIG_VIRTIO_BLK=y
CONFIG_PA_BLK_DEV=y CONFIG_PA_BLK_DEV=y
CONFIG_BLK_DEV_NVME=m CONFIG_BLK_DEV_NVME=m
CONFIG_TH1520_DSMART_CARD=y
CONFIG_IO_EVENT_WRAPER=y CONFIG_IO_EVENT_WRAPER=y
CONFIG_EEPROM_AT24=m CONFIG_EEPROM_AT24=y
CONFIG_BLK_DEV_SD=m CONFIG_BLK_DEV_SD=m
CONFIG_ATA=m CONFIG_ATA=m
CONFIG_AHCI_DWC=m CONFIG_AHCI_DWC=m
CONFIG_MD=y CONFIG_MD=y
CONFIG_BLK_DEV_MD=m CONFIG_BLK_DEV_MD=y
CONFIG_MD_RAID0=m CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m CONFIG_MD_RAID1=m
CONFIG_MD_RAID456=m CONFIG_MD_RAID456=m
CONFIG_BLK_DEV_DM=y CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y CONFIG_NETDEVICES=y
CONFIG_MACVLAN=y CONFIG_MACVLAN=y
CONFIG_IPVLAN=y CONFIG_IPVLAN=y
CONFIG_VETH=y CONFIG_VETH=y
CONFIG_VIRTIO_NET=y
CONFIG_NLMON=y CONFIG_NLMON=y
# CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_ADAPTEC is not set # CONFIG_NET_VENDOR_ADAPTEC is not set
@@ -175,6 +207,7 @@ CONFIG_NLMON=y
# CONFIG_NET_VENDOR_SOCIONEXT is not set # CONFIG_NET_VENDOR_SOCIONEXT is not set
CONFIG_STMMAC_ETH=y CONFIG_STMMAC_ETH=y
# CONFIG_DWMAC_GENERIC is not set # CONFIG_DWMAC_GENERIC is not set
CONFIG_DWMAC_THEAD=y
CONFIG_DWMAC_ZHIHE=y CONFIG_DWMAC_ZHIHE=y
# CONFIG_NET_VENDOR_SUN is not set # CONFIG_NET_VENDOR_SUN is not set
# CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_SYNOPSYS is not set
@@ -185,17 +218,30 @@ CONFIG_DWMAC_ZHIHE=y
# CONFIG_NET_VENDOR_WANGXUN is not set # CONFIG_NET_VENDOR_WANGXUN is not set
# CONFIG_NET_VENDOR_WIZNET is not set # CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_NET_VENDOR_XILINX is not set # CONFIG_NET_VENDOR_XILINX is not set
CONFIG_MICROSEMI_PHY=y
CONFIG_MOTORCOMM_PHY=y
CONFIG_REALTEK_PHY=y CONFIG_REALTEK_PHY=y
CONFIG_CAN_FLEXCAN=m CONFIG_CAN_FLEXCAN=m
CONFIG_USB_RTL8152=m
CONFIG_USB_USBNET=m
# CONFIG_USB_NET_AX8817X is not set
# CONFIG_USB_NET_AX88179_178A is not set
# CONFIG_USB_NET_NET1080 is not set
CONFIG_IWLWIFI=m CONFIG_IWLWIFI=m
CONFIG_IWLMVM=m CONFIG_IWLMVM=m
CONFIG_HOSTAP=y
CONFIG_HOSTAP_FIRMWARE=y
CONFIG_HOSTAP_FIRMWARE_NVRAM=y
# CONFIG_RTL_CARDS is not set # CONFIG_RTL_CARDS is not set
CONFIG_RTW88=m CONFIG_RTW88=m
CONFIG_RTW88_8822CS=m CONFIG_RTW88_8822CS=m
CONFIG_INPUT_EVDEV=m CONFIG_RTW88_8723DS=m
# CONFIG_INPUT_KEYBOARD is not set CONFIG_INPUT_MOUSEDEV=y
# CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_EVDEV=y
# CONFIG_SERIO is not set CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250=y
# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_CONSOLE=y
@@ -203,7 +249,12 @@ CONFIG_SERIAL_8250_NR_UARTS=10
CONFIG_SERIAL_8250_RUNTIME_UARTS=10 CONFIG_SERIAL_8250_RUNTIME_UARTS=10
CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS_SPI=y
CONFIG_I2C_CHARDEV=y CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_HELPER_AUTO is not set # CONFIG_I2C_HELPER_AUTO is not set
CONFIG_I2C_SMBUS=m CONFIG_I2C_SMBUS=m
@@ -215,13 +266,20 @@ CONFIG_SPI_DW_MMIO=y
CONFIG_SPI_SPIDEV=y CONFIG_SPI_SPIDEV=y
# CONFIG_PTP_1588_CLOCK is not set # CONFIG_PTP_1588_CLOCK is not set
CONFIG_PINCTRL=y CONFIG_PINCTRL=y
CONFIG_PINCTRL_TH1520=y
CONFIG_PINCTRL_A210=y CONFIG_PINCTRL_A210=y
CONFIG_GPIO_SYSFS=y CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_DWAPB=y CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_PCA953X=y CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_SENSORS_MR75203=y CONFIG_BATTERY_CW2015=m
CONFIG_SENSORS_MR75203=m
CONFIG_SENSORS_PWM_FAN=m
CONFIG_SENSORS_TMP102=m CONFIG_SENSORS_TMP102=m
CONFIG_THERMAL=y
CONFIG_THERMAL_STATISTICS=y
CONFIG_CPU_THERMAL=y
CONFIG_THERMAL_EMULATION=y
CONFIG_WATCHDOG=y CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_NOWAYOUT=y CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_WATCHDOG_OPEN_TIMEOUT=32 CONFIG_WATCHDOG_OPEN_TIMEOUT=32
@@ -231,20 +289,71 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=m
CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=m CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=m
CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP=y CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP=y
CONFIG_DW_WATCHDOG=y CONFIG_DW_WATCHDOG=y
CONFIG_TH1520_PMIC_WATCHDOG=y
CONFIG_ZHIHE_WATCHDOG=y CONFIG_ZHIHE_WATCHDOG=y
CONFIG_REGULATOR=y CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_WL2866D=y
# CONFIG_MEDIA_CEC_SUPPORT is not set # CONFIG_MEDIA_CEC_SUPPORT is not set
CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_SUPPORT=y
# CONFIG_DVB_CORE is not set
CONFIG_MEDIA_USB_SUPPORT=y CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m CONFIG_USB_VIDEO_CLASS=m
# CONFIG_RADIO_ADAPTERS is not set
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
# CONFIG_MEDIA_TUNER_E4000 is not set
# CONFIG_MEDIA_TUNER_FC0011 is not set
# CONFIG_MEDIA_TUNER_FC0012 is not set
# CONFIG_MEDIA_TUNER_FC0013 is not set
# CONFIG_MEDIA_TUNER_FC2580 is not set
# CONFIG_MEDIA_TUNER_IT913X is not set
# CONFIG_MEDIA_TUNER_M88RS6000T is not set
# CONFIG_MEDIA_TUNER_MAX2165 is not set
# CONFIG_MEDIA_TUNER_MC44S803 is not set
# CONFIG_MEDIA_TUNER_MSI001 is not set
# CONFIG_MEDIA_TUNER_MT2060 is not set
# CONFIG_MEDIA_TUNER_MT2063 is not set
# CONFIG_MEDIA_TUNER_MT20XX is not set
# CONFIG_MEDIA_TUNER_MT2131 is not set
# CONFIG_MEDIA_TUNER_MT2266 is not set
# CONFIG_MEDIA_TUNER_MXL301RF is not set
# CONFIG_MEDIA_TUNER_MXL5005S is not set
# CONFIG_MEDIA_TUNER_MXL5007T is not set
# CONFIG_MEDIA_TUNER_QM1D1B0004 is not set
# CONFIG_MEDIA_TUNER_QM1D1C0042 is not set
# CONFIG_MEDIA_TUNER_QT1010 is not set
# CONFIG_MEDIA_TUNER_R820T is not set
# CONFIG_MEDIA_TUNER_SI2157 is not set
# CONFIG_MEDIA_TUNER_SIMPLE is not set
# CONFIG_MEDIA_TUNER_TDA18212 is not set
# CONFIG_MEDIA_TUNER_TDA18218 is not set
# CONFIG_MEDIA_TUNER_TDA18250 is not set
# CONFIG_MEDIA_TUNER_TDA18271 is not set
# CONFIG_MEDIA_TUNER_TDA827X is not set
# CONFIG_MEDIA_TUNER_TDA8290 is not set
# CONFIG_MEDIA_TUNER_TDA9887 is not set
# CONFIG_MEDIA_TUNER_TEA5761 is not set
# CONFIG_MEDIA_TUNER_TEA5767 is not set
# CONFIG_MEDIA_TUNER_TUA9001 is not set
# CONFIG_MEDIA_TUNER_XC2028 is not set
# CONFIG_MEDIA_TUNER_XC4000 is not set
# CONFIG_MEDIA_TUNER_XC5000 is not set
CONFIG_DRM=y CONFIG_DRM=y
CONFIG_DRM_LOAD_EDID_FIRMWARE=y CONFIG_DRM_LOAD_EDID_FIRMWARE=y
CONFIG_DRM_DP_AUX_CHARDEV=y CONFIG_DRM_DP_AUX_CHARDEV=y
CONFIG_TYPEC_DP_ALTMODE=m
CONFIG_DRM_PANEL_SIMPLE=m
CONFIG_DRM_PANEL_ILITEK_ILI9881C=m
CONFIG_DRM_PANEL_JADARD_JD9365DA_H3=y
CONFIG_DRM_PANEL_LT8911=y
CONFIG_DRM_VERISILICON=m CONFIG_DRM_VERISILICON=m
CONFIG_VERISILICON_DW_DP_P100=y CONFIG_VERISILICON_DW_DP_P100=y
CONFIG_ZHIHE_AUXDISP=y
CONFIG_FB=y CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y CONFIG_FIRMWARE_EDID=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_PWM=y
# CONFIG_VGA_CONSOLE is not set # CONFIG_VGA_CONSOLE is not set
CONFIG_LOGO=y CONFIG_LOGO=y
CONFIG_SOUND=m CONFIG_SOUND=m
@@ -252,33 +361,52 @@ CONFIG_SND=m
CONFIG_SND_USB_AUDIO=m CONFIG_SND_USB_AUDIO=m
CONFIG_SND_USB_AUDIO_MIDI_V2=y CONFIG_SND_USB_AUDIO_MIDI_V2=y
CONFIG_SND_SOC=m CONFIG_SND_SOC=m
CONFIG_SND_SOC_XUANTIE=m
CONFIG_SND_SOC_XUANTIE_TH1520_I2S_CH8=m
CONFIG_SND_SOC_XUANTIE_TH1520_HDMI_PCM=m
CONFIG_SND_SOC_XUANTIE_TH1520_TDM=m
CONFIG_SND_SOC_XUANTIE_TH1520_SPDIF=m
CONFIG_SND_SOC_ZHIHE_I2S=m CONFIG_SND_SOC_ZHIHE_I2S=m
CONFIG_SND_SOC_ZHIHE_TDM=m CONFIG_SND_SOC_ZHIHE_TDM=m
CONFIG_SND_SOC_ZHIHE_PDM=m CONFIG_SND_SOC_ZHIHE_PDM=m
CONFIG_SND_SOC_AW87519=m
CONFIG_SND_SOC_AW87565=m CONFIG_SND_SOC_AW87565=m
CONFIG_SND_SOC_ES7210=m CONFIG_SND_SOC_ES7210=m
CONFIG_SND_SOC_ES8156=m CONFIG_SND_SOC_ES8156=m
CONFIG_SND_SOC_ES8323=m
CONFIG_SND_SIMPLE_CARD=m CONFIG_SND_SIMPLE_CARD=m
CONFIG_USB=m CONFIG_USB=m
CONFIG_USB_XHCI_HCD=m CONFIG_USB_XHCI_HCD=m
CONFIG_USB_EHCI_HCD=m CONFIG_USB_EHCI_HCD=m
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_PRINTER=m CONFIG_USB_PRINTER=m
CONFIG_USB_WDM=m CONFIG_USB_WDM=m
CONFIG_USB_STORAGE=m CONFIG_USB_STORAGE=m
CONFIG_USB_STORAGE_SDDR09=m
CONFIG_USB_STORAGE_SDDR55=m
CONFIG_USB_DWC3=m CONFIG_USB_DWC3=m
# CONFIG_USB_DWC3_HAPS is not set
# CONFIG_USB_DWC3_OF_SIMPLE is not set # CONFIG_USB_DWC3_OF_SIMPLE is not set
CONFIG_USB_DWC2=m CONFIG_USB_DWC2=m
CONFIG_USB_ONBOARD_HUB=m
CONFIG_USB_GADGET=m CONFIG_USB_GADGET=m
CONFIG_USB_CONFIGFS=m CONFIG_USB_CONFIGFS=m
CONFIG_USB_CONFIGFS_RNDIS=y CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m CONFIG_USB_ETH=m
CONFIG_USB_ETH_EEM=y
CONFIG_USB_GADGETFS=m CONFIG_USB_GADGETFS=m
CONFIG_USB_FUNCTIONFS=m CONFIG_USB_FUNCTIONFS=m
CONFIG_USB_FUNCTIONFS_RNDIS=y CONFIG_USB_FUNCTIONFS_RNDIS=y
CONFIG_USB_FUNCTIONFS_GENERIC=y CONFIG_USB_FUNCTIONFS_GENERIC=y
CONFIG_USB_MASS_STORAGE=m CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_MULTI=m
CONFIG_USB_G_MULTI_CDC=y
CONFIG_TYPEC=m CONFIG_TYPEC=m
CONFIG_TYPEC_TCPM=m CONFIG_TYPEC_TCPM=m
CONFIG_TYPEC_TCPCI=m
CONFIG_TYPEC_FUSB302=m CONFIG_TYPEC_FUSB302=m
CONFIG_MMC=y CONFIG_MMC=y
CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI=y
@@ -286,29 +414,49 @@ CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_OF_DWCMSHC=y CONFIG_MMC_SDHCI_OF_DWCMSHC=y
CONFIG_NEW_LEDS=y CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_RTC_CLASS=y CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PCF8563=m
CONFIG_RTC_DRV_XGENE=y
CONFIG_DMADEVICES=y CONFIG_DMADEVICES=y
CONFIG_DW_AXI_DMAC=y CONFIG_DW_AXI_DMAC=y
CONFIG_DMATEST=m CONFIG_DMATEST=m
CONFIG_SW_SYNC=y CONFIG_SW_SYNC=y
CONFIG_UDMABUF=y CONFIG_UDMABUF=y
CONFIG_DMABUF_SELFTESTS=m CONFIG_DMABUF_SELFTESTS=m
# CONFIG_VIRTIO_MENU is not set CONFIG_VIRTIO_MMIO=y
# CONFIG_VIRTIO_VDMABUF is not set
# CONFIG_VHOST_MENU is not set # CONFIG_VHOST_MENU is not set
CONFIG_CLK_TH1520_FM=y
CONFIG_CLK_A210=y CONFIG_CLK_A210=y
CONFIG_HWSPINLOCK=y CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_TH1520=y
CONFIG_MAILBOX=y CONFIG_MAILBOX=y
CONFIG_RISCV_IOMMU=y CONFIG_RISCV_IOMMU=y
CONFIG_RPMSG_CHAR=y
CONFIG_RPMSG_CTRL=y
CONFIG_RPMSG_TH1520=y
CONFIG_RPMSG_VIRTIO=y
CONFIG_A210_BMU=y CONFIG_A210_BMU=y
CONFIG_A210_D2D=m
CONFIG_EXTCON=y CONFIG_EXTCON=y
CONFIG_IIO=y CONFIG_IIO=y
CONFIG_IIO_SW_DEVICE=y
CONFIG_PWM=y CONFIG_PWM=y
CONFIG_PWM_THEAD=y CONFIG_PWM_THEAD=y
CONFIG_PHY_DW_DPHY=y
CONFIG_PHY_ZHIHE_SNPS_PCIE3=m
CONFIG_PHY_ZHIHE_SNPS_USB2=m
CONFIG_PHY_ZHIHE_SNPS_C10PHY=m
CONFIG_NVMEM_XUANTIE_TH1520_EFUSE=y
CONFIG_NVMEM_ZH_EFUSE=y CONFIG_NVMEM_ZH_EFUSE=y
CONFIG_TEE=m
CONFIG_OPTEE=m
CONFIG_IOPMP=y CONFIG_IOPMP=y
CONFIG_ZH_IOPMP=y CONFIG_ZH_IOPMP=y
CONFIG_EXT4_FS=y CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_F2FS_FS=m
CONFIG_EXPORTFS_BLOCK_OPS=y CONFIG_EXPORTFS_BLOCK_OPS=y
CONFIG_QUOTA=y CONFIG_QUOTA=y
CONFIG_AUTOFS_FS=y CONFIG_AUTOFS_FS=y
@@ -323,7 +471,7 @@ CONFIG_NTFS3_FS=m
CONFIG_TMPFS=y CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y CONFIG_HUGETLBFS=y
CONFIG_CONFIGFS_FS=y CONFIG_JFFS2_FS=y
CONFIG_UBIFS_FS=y CONFIG_UBIFS_FS=y
CONFIG_EROFS_FS=y CONFIG_EROFS_FS=y
CONFIG_NFS_FS=y CONFIG_NFS_FS=y
@@ -339,7 +487,19 @@ CONFIG_NFS_USE_LEGACY_DNS=y
CONFIG_NLS_CODEPAGE_437=m CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_ISO8859_1=m CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_UTF8=m CONFIG_NLS_UTF8=m
CONFIG_CRYPTO_USER=y
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
CONFIG_CRYPTO_DH=y
CONFIG_CRYPTO_CURVE25519=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_OFB=y
CONFIG_CRYPTO_XTS=y
CONFIG_CRYPTO_CHACHA20POLY1305=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=y
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_CRYPTO_DEV_ZHIHE=m CONFIG_CRYPTO_DEV_ZHIHE=m
CONFIG_DMA_CMA=y CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32 CONFIG_CMA_SIZE_MBYTES=32
@@ -349,8 +509,11 @@ CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y CONFIG_DEBUG_FS=y
CONFIG_DETECT_HUNG_TASK=y CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_SCHEDSTATS=y
CONFIG_DEBUG_ATOMIC_SLEEP=y CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_LOCK_TORTURE_TEST=m
CONFIG_RCU_TORTURE_TEST=m
# CONFIG_RCU_TRACE is not set # CONFIG_RCU_TRACE is not set
CONFIG_FTRACE_SYSCALLS=y CONFIG_FTRACE_SYSCALLS=y
CONFIG_BPF_KPROBE_OVERRIDE=y CONFIG_BPF_KPROBE_OVERRIDE=y

View File

@@ -5,7 +5,7 @@ CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y CONFIG_BPF_JIT=y
CONFIG_PREEMPT=y CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_TASKSTATS=y CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y CONFIG_TASK_XACCT=y
@@ -71,6 +71,11 @@ CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y CONFIG_IP_PNP_RARP=y
CONFIG_NETFILTER=y
CONFIG_BRIDGE_NETFILTER=y
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=y
CONFIG_BPFILTER=y
CONFIG_BRIDGE=y CONFIG_BRIDGE=y
CONFIG_NETLINK_DIAG=y CONFIG_NETLINK_DIAG=y
CONFIG_BT=y CONFIG_BT=y
@@ -81,7 +86,7 @@ CONFIG_BT_HIDP=y
CONFIG_BT_HCIUART=y CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_RTL3WIRE=y CONFIG_BT_HCIUART_RTL3WIRE=y
CONFIG_CFG80211=y CONFIG_CFG80211=m
CONFIG_CFG80211_WEXT=y CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=y CONFIG_MAC80211=y
CONFIG_RFKILL=y CONFIG_RFKILL=y
@@ -188,6 +193,7 @@ CONFIG_SUNXI_WATCHDOG=y
CONFIG_TH1520_PMIC_WATCHDOG=y CONFIG_TH1520_PMIC_WATCHDOG=y
CONFIG_REGULATOR=y CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_WL2866D=m
CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_SUPPORT=y
# CONFIG_DVB_CORE is not set # CONFIG_DVB_CORE is not set
CONFIG_MEDIA_USB_SUPPORT=y CONFIG_MEDIA_USB_SUPPORT=y

View File

@@ -73,7 +73,6 @@ static bool errata_probe_pmu(unsigned int stage,
if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PMU)) if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PMU))
return false; return false;
out:
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
return false; return false;

View File

@@ -26,8 +26,8 @@
#include <asm/iomb.h> #include <asm/iomb.h>
/* p100-specific barrier to enforce ordering on devices, don't use in portable drivers*/ /* p100-specific barrier to enforce ordering on devices, don't use in portable drivers*/
#define dma_mb() p100_iomb() #define dma_mb() a210_iomb()
#define dma_wmb() p100_iowmb() #define dma_wmb() a210_iowmb()
/* These barriers do not need to enforce ordering on devices, just memory. */ /* These barriers do not need to enforce ordering on devices, just memory. */
#define __smp_mb() RISCV_FENCE(rw,rw) #define __smp_mb() RISCV_FENCE(rw,rw)

View File

@@ -37,7 +37,8 @@ static inline void flush_dcache_page(struct page *page)
flush_icache_mm(vma->vm_mm, 0) flush_icache_mm(vma->vm_mm, 0)
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
#define flush_cache_vmap(start, end) flush_tlb_kernel_range(start, end) #define flush_cache_vmap(start, end) flush_tlb_kernel_range(start, end)
#define flush_cache_vmap_early(start, end) local_flush_tlb_kernel_range(start, end)
#endif #endif
#ifndef CONFIG_SMP #ifndef CONFIG_SMP

View File

@@ -0,0 +1,317 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2025 Ventana Micro Systems Inc.
*/
#ifndef __RISCV_HW_BREAKPOINT_H
#define __RISCV_HW_BREAKPOINT_H
struct task_struct;
#ifdef CONFIG_HAVE_HW_BREAKPOINT
#include <uapi/linux/hw_breakpoint.h>
#if __riscv_xlen == 64
#define cpu_to_le cpu_to_le64
#define le_to_cpu le64_to_cpu
#elif __riscv_xlen == 32
#define cpu_to_le cpu_to_le32
#define le_to_cpu le32_to_cpu
#else
#error "Unexpected __riscv_xlen"
#endif
#define RV_DBTR_BIT(_prefix, _name) \
RV_DBTR_##_prefix##_##_name##_BIT
#define RV_DBTR_BIT_MASK(_prefix, _name) \
RV_DBTR_##_prefix##_name##_BIT_MASK
#define RV_DBTR_BIT_MASK_VAL(_prefix, _name, _width) \
(((1UL << _width) - 1) << RV_DBTR_BIT(_prefix, _name))
#define CLEAR_DBTR_BIT(_target, _prefix, _bit_name) \
__clear_bit(RV_DBTR_BIT(_prefix, _bit_name), &_target)
#define SET_DBTR_BIT(_target, _prefix, _bit_name) \
__set_bit(RV_DBTR_BIT(_prefix, _bit_name), &_target)
enum {
RV_DBTR_BP = 0,
RV_DBTR_WP = 1,
};
enum {
RV_DBTR_TRIG_NONE = 0,
RV_DBTR_TRIG_LEGACY,
RV_DBTR_TRIG_MCONTROL,
RV_DBTR_TRIG_ICOUNT,
RV_DBTR_TRIG_ITRIGGER,
RV_DBTR_TRIG_ETRIGGER,
RV_DBTR_TRIG_MCONTROL6,
};
/* Trigger Data 1 */
enum {
RV_DBTR_BIT(TDATA1, DATA) = 0,
#if __riscv_xlen == 64
RV_DBTR_BIT(TDATA1, DMODE) = 59,
RV_DBTR_BIT(TDATA1, TYPE) = 60,
#elif __riscv_xlen == 32
RV_DBTR_BIT(TDATA1, DMODE) = 27,
RV_DBTR_BIT(TDATA1, TYPE) = 28,
#else
#error "Unknown __riscv_xlen"
#endif
};
enum {
#if __riscv_xlen == 64
RV_DBTR_BIT_MASK(TDATA1, DATA) = RV_DBTR_BIT_MASK_VAL(TDATA1, DATA, 59),
#elif __riscv_xlen == 32
RV_DBTR_BIT_MASK(TDATA1, DATA) = RV_DBTR_BIT_MASK_VAL(TDATA1, DATA, 27),
#else
#error "Unknown __riscv_xlen"
#endif
RV_DBTR_BIT_MASK(TDAT1, DMODE) = RV_DBTR_BIT_MASK_VAL(TDATA1, DMODE, 1),
RV_DBTR_BIT_MASK(TDATA1, TYPE) = RV_DBTR_BIT_MASK_VAL(TDATA1, TYPE, 4),
};
/* MC - Match Control Type Register */
enum {
RV_DBTR_BIT(MC, LOAD) = 0,
RV_DBTR_BIT(MC, STORE) = 1,
RV_DBTR_BIT(MC, EXEC) = 2,
RV_DBTR_BIT(MC, U) = 3,
RV_DBTR_BIT(MC, S) = 4,
RV_DBTR_BIT(MC, RES2) = 5,
RV_DBTR_BIT(MC, M) = 6,
RV_DBTR_BIT(MC, MATCH) = 7,
RV_DBTR_BIT(MC, CHAIN) = 11,
RV_DBTR_BIT(MC, ACTION) = 12,
RV_DBTR_BIT(MC, SIZELO) = 16,
RV_DBTR_BIT(MC, TIMING) = 18,
RV_DBTR_BIT(MC, SELECT) = 19,
RV_DBTR_BIT(MC, HIT) = 20,
#if __riscv_xlen >= 64
RV_DBTR_BIT(MC, SIZEHI) = 21,
#endif
#if __riscv_xlen == 64
RV_DBTR_BIT(MC, MASKMAX) = 53,
RV_DBTR_BIT(MC, DMODE) = 59,
RV_DBTR_BIT(MC, TYPE) = 60,
#elif __riscv_xlen == 32
RV_DBTR_BIT(MC, MASKMAX) = 21,
RV_DBTR_BIT(MC, DMODE) = 27,
RV_DBTR_BIT(MC, TYPE) = 28,
#else
#error "Unknown riscv xlen"
#endif
};
enum {
RV_DBTR_BIT_MASK(MC, LOAD) = RV_DBTR_BIT_MASK_VAL(MC, LOAD, 1),
RV_DBTR_BIT_MASK(MC, STORE) = RV_DBTR_BIT_MASK_VAL(MC, STORE, 1),
RV_DBTR_BIT_MASK(MC, EXEC) = RV_DBTR_BIT_MASK_VAL(MC, EXEC, 1),
RV_DBTR_BIT_MASK(MC, U) = RV_DBTR_BIT_MASK_VAL(MC, U, 1),
RV_DBTR_BIT_MASK(MC, S) = RV_DBTR_BIT_MASK_VAL(MC, S, 1),
RV_DBTR_BIT_MASK(MC, RES2) = RV_DBTR_BIT_MASK_VAL(MC, RES2, 1),
RV_DBTR_BIT_MASK(MC, M) = RV_DBTR_BIT_MASK_VAL(MC, M, 1),
RV_DBTR_BIT_MASK(MC, MATCH) = RV_DBTR_BIT_MASK_VAL(MC, MATCH, 4),
RV_DBTR_BIT_MASK(MC, CHAIN) = RV_DBTR_BIT_MASK_VAL(MC, CHAIN, 1),
RV_DBTR_BIT_MASK(MC, ACTION) = RV_DBTR_BIT_MASK_VAL(MC, ACTION, 4),
RV_DBTR_BIT_MASK(MC, SIZELO) = RV_DBTR_BIT_MASK_VAL(MC, SIZELO, 2),
RV_DBTR_BIT_MASK(MC, TIMING) = RV_DBTR_BIT_MASK_VAL(MC, TIMING, 1),
RV_DBTR_BIT_MASK(MC, SELECT) = RV_DBTR_BIT_MASK_VAL(MC, SELECT, 1),
RV_DBTR_BIT_MASK(MC, HIT) = RV_DBTR_BIT_MASK_VAL(MC, HIT, 1),
#if __riscv_xlen >= 64
RV_DBTR_BIT_MASK(MC, SIZEHI) = RV_DBTR_BIT_MASK_VAL(MC, SIZEHI, 2),
#endif
RV_DBTR_BIT_MASK(MC, MASKMAX) = RV_DBTR_BIT_MASK_VAL(MC, MASKMAX, 6),
RV_DBTR_BIT_MASK(MC, DMODE) = RV_DBTR_BIT_MASK_VAL(MC, DMODE, 1),
RV_DBTR_BIT_MASK(MC, TYPE) = RV_DBTR_BIT_MASK_VAL(MC, TYPE, 4),
};
/* MC6 - Match Control 6 Type Register */
enum {
RV_DBTR_BIT(MC6, LOAD) = 0,
RV_DBTR_BIT(MC6, STORE) = 1,
RV_DBTR_BIT(MC6, EXEC) = 2,
RV_DBTR_BIT(MC6, U) = 3,
RV_DBTR_BIT(MC6, S) = 4,
RV_DBTR_BIT(MC6, RES2) = 5,
RV_DBTR_BIT(MC6, M) = 6,
RV_DBTR_BIT(MC6, MATCH) = 7,
RV_DBTR_BIT(MC6, CHAIN) = 11,
RV_DBTR_BIT(MC6, ACTION) = 12,
RV_DBTR_BIT(MC6, SIZE) = 16,
RV_DBTR_BIT(MC6, TIMING) = 20,
RV_DBTR_BIT(MC6, SELECT) = 21,
RV_DBTR_BIT(MC6, HIT) = 22,
RV_DBTR_BIT(MC6, VU) = 23,
RV_DBTR_BIT(MC6, VS) = 24,
#if __riscv_xlen == 64
RV_DBTR_BIT(MC6, DMODE) = 59,
RV_DBTR_BIT(MC6, TYPE) = 60,
#elif __riscv_xlen == 32
RV_DBTR_BIT(MC6, DMODE) = 27,
RV_DBTR_BIT(MC6, TYPE) = 28,
#else
#error "Unknown riscv xlen"
#endif
};
enum {
RV_DBTR_BIT_MASK(MC6, LOAD) = RV_DBTR_BIT_MASK_VAL(MC6, LOAD, 1),
RV_DBTR_BIT_MASK(MC6, STORE) = RV_DBTR_BIT_MASK_VAL(MC6, STORE, 1),
RV_DBTR_BIT_MASK(MC6, EXEC) = RV_DBTR_BIT_MASK_VAL(MC6, EXEC, 1),
RV_DBTR_BIT_MASK(MC6, U) = RV_DBTR_BIT_MASK_VAL(MC6, U, 1),
RV_DBTR_BIT_MASK(MC6, S) = RV_DBTR_BIT_MASK_VAL(MC6, S, 1),
RV_DBTR_BIT_MASK(MC6, RES2) = RV_DBTR_BIT_MASK_VAL(MC6, RES2, 1),
RV_DBTR_BIT_MASK(MC6, M) = RV_DBTR_BIT_MASK_VAL(MC6, M, 1),
RV_DBTR_BIT_MASK(MC6, MATCH) = RV_DBTR_BIT_MASK_VAL(MC6, MATCH, 4),
RV_DBTR_BIT_MASK(MC6, CHAIN) = RV_DBTR_BIT_MASK_VAL(MC6, CHAIN, 1),
RV_DBTR_BIT_MASK(MC6, ACTION) = RV_DBTR_BIT_MASK_VAL(MC6, ACTION, 4),
RV_DBTR_BIT_MASK(MC6, SIZE) = RV_DBTR_BIT_MASK_VAL(MC6, SIZE, 4),
RV_DBTR_BIT_MASK(MC6, TIMING) = RV_DBTR_BIT_MASK_VAL(MC6, TIMING, 1),
RV_DBTR_BIT_MASK(MC6, SELECT) = RV_DBTR_BIT_MASK_VAL(MC6, SELECT, 1),
RV_DBTR_BIT_MASK(MC6, HIT) = RV_DBTR_BIT_MASK_VAL(MC6, HIT, 1),
RV_DBTR_BIT_MASK(MC6, VU) = RV_DBTR_BIT_MASK_VAL(MC6, VU, 1),
RV_DBTR_BIT_MASK(MC6, VS) = RV_DBTR_BIT_MASK_VAL(MC6, VS, 1),
#if __riscv_xlen == 64
RV_DBTR_BIT_MASK(MC6, DMODE) = RV_DBTR_BIT_MASK_VAL(MC6, DMODE, 1),
RV_DBTR_BIT_MASK(MC6, TYPE) = RV_DBTR_BIT_MASK_VAL(MC6, TYPE, 4),
#elif __riscv_xlen == 32
RV_DBTR_BIT_MASK(MC6, DMODE) = RV_DBTR_BIT_MASK_VAL(MC6, DMODE, 1),
RV_DBTR_BIT_MASK(MC6, TYPE) = RV_DBTR_BIT_MASK_VAL(MC6, TYPE, 4),
#else
#error "Unknown riscv xlen"
#endif
};
#define RV_DBTR_SET_TDATA1_TYPE(_t1, _type) \
do { \
_t1 &= ~RV_DBTR_BIT_MASK(TDATA1, TYPE); \
_t1 |= (((unsigned long)_type \
<< RV_DBTR_BIT(TDATA1, TYPE)) \
& RV_DBTR_BIT_MASK(TDATA1, TYPE)); \
} while (0)
#define RV_DBTR_SET_MC_TYPE(_t1, _type) \
do { \
_t1 &= ~RV_DBTR_BIT_MASK(MC, TYPE); \
_t1 |= (((unsigned long)_type \
<< RV_DBTR_BIT(MC, TYPE)) \
& RV_DBTR_BIT_MASK(MC, TYPE)); \
} while (0)
#define RV_DBTR_SET_MC6_TYPE(_t1, _type) \
do { \
_t1 &= ~RV_DBTR_BIT_MASK(MC6, TYPE); \
_t1 |= (((unsigned long)_type \
<< RV_DBTR_BIT(MC6, TYPE)) \
& RV_DBTR_BIT_MASK(MC6, TYPE)); \
} while (0)
#define RV_DBTR_SET_MC_EXEC(_t1) \
SET_DBTR_BIT(_t1, MC, EXEC)
#define RV_DBTR_SET_MC_LOAD(_t1) \
SET_DBTR_BIT(_t1, MC, LOAD)
#define RV_DBTR_SET_MC_STORE(_t1) \
SET_DBTR_BIT(_t1, MC, STORE)
#define RV_DBTR_SET_MC_SIZELO(_t1, _val) \
do { \
_t1 &= ~RV_DBTR_BIT_MASK(MC, SIZELO); \
_t1 |= ((_val << RV_DBTR_BIT(MC, SIZELO)) \
& RV_DBTR_BIT_MASK(MC, SIZELO)); \
} while (0)
#define RV_DBTR_SET_MC_SIZEHI(_t1, _val) \
do { \
_t1 &= ~RV_DBTR_BIT_MASK(MC, SIZEHI); \
_t1 |= ((_val << RV_DBTR_BIT(MC, SIZEHI)) \
& RV_DBTR_BIT_MASK(MC, SIZEHI)); \
} while (0)
#define RV_DBTR_SET_MC6_EXEC(_t1) \
SET_DBTR_BIT(_t1, MC6, EXEC)
#define RV_DBTR_SET_MC6_LOAD(_t1) \
SET_DBTR_BIT(_t1, MC6, LOAD)
#define RV_DBTR_SET_MC6_STORE(_t1) \
SET_DBTR_BIT(_t1, MC6, STORE)
#define RV_DBTR_SET_MC6_SIZE(_t1, _val) \
do { \
_t1 &= ~RV_DBTR_BIT_MASK(MC6, SIZE); \
_t1 |= ((_val << RV_DBTR_BIT(MC6, SIZE)) \
& RV_DBTR_BIT_MASK(MC6, SIZE)); \
} while (0)
struct arch_hw_breakpoint {
unsigned long addr;
unsigned long type;
unsigned long len;
/* Trigger configuration data */
unsigned long tdata1;
unsigned long tdata2;
unsigned long tdata3;
};
struct perf_event_attr;
struct notifier_block;
struct perf_event;
struct pt_regs;
int hw_breakpoint_slots(int type);
int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw);
int hw_breakpoint_arch_parse(struct perf_event *bp,
const struct perf_event_attr *attr,
struct arch_hw_breakpoint *hw);
int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
unsigned long val, void *data);
void arch_enable_hw_breakpoint(struct perf_event *bp);
void arch_update_hw_breakpoint(struct perf_event *bp);
void arch_disable_hw_breakpoint(struct perf_event *bp);
int arch_install_hw_breakpoint(struct perf_event *bp);
void arch_uninstall_hw_breakpoint(struct perf_event *bp);
void hw_breakpoint_pmu_read(struct perf_event *bp);
void clear_ptrace_hw_breakpoint(struct task_struct *tsk);
void flush_ptrace_hw_breakpoint(struct task_struct *tsk);
#else
int hw_breakpoint_slots(int type)
{
return 0;
}
static inline void clear_ptrace_hw_breakpoint(struct task_struct *tsk)
{
}
static inline void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
{
}
void arch_enable_hw_breakpoint(struct perf_event *bp)
{
}
void arch_update_hw_breakpoint(struct perf_event *bp)
{
}
void arch_disable_hw_breakpoint(struct perf_event *bp)
{
}
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
#endif /* __RISCV_HW_BREAKPOINT_H */

View File

@@ -4,10 +4,10 @@
*/ */
#ifndef P100_IOMB_H #ifndef A210_IOMB_H
#define P100_IOMB_H #define A210_IOMB_H
inline void p100_iomb(void); inline void a210_iomb(void);
inline void p100_iowmb(void); inline void a210_iowmb(void);
#endif #endif

View File

@@ -6,7 +6,8 @@
enum die_val { enum die_val {
DIE_UNUSED, DIE_UNUSED,
DIE_TRAP, DIE_TRAP,
DIE_OOPS DIE_OOPS,
DIE_DEBUG
}; };
#endif #endif

View File

@@ -12,6 +12,7 @@
#include <vdso/processor.h> #include <vdso/processor.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/hw_breakpoint.h>
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
#define DEFAULT_MAP_WINDOW (UL(1) << (MMAP_VA_BITS - 1)) #define DEFAULT_MAP_WINDOW (UL(1) << (MMAP_VA_BITS - 1))
@@ -70,6 +71,7 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
struct task_struct; struct task_struct;
struct perf_event;
struct pt_regs; struct pt_regs;
/* CPU-specific state of a task */ /* CPU-specific state of a task */
@@ -83,6 +85,11 @@ struct thread_struct {
unsigned long vstate_ctrl; unsigned long vstate_ctrl;
struct __riscv_v_ext_state vstate; struct __riscv_v_ext_state vstate;
struct __riscv_m_ext_state mstate; struct __riscv_m_ext_state mstate;
#ifdef CONFIG_HAVE_HW_BREAKPOINT
struct perf_event *ptrace_bps[HW_BP_NUM_MAX];
struct arch_hw_breakpoint hbp_break[HW_BP_NUM_MAX];
struct arch_hw_breakpoint hbp_watch[HW_BP_NUM_MAX];
#endif
}; };
/* Whitelist the fstate from the task_struct for hardened usercopy */ /* Whitelist the fstate from the task_struct for hardened usercopy */

View File

@@ -57,7 +57,7 @@ struct pt_regs {
#define PTRACE_SYSEMU_SINGLESTEP 0x20 #define PTRACE_SYSEMU_SINGLESTEP 0x20
#if __riscv_xlen == 64 #if __riscv_xlen == 64
#define REG_FMT "%016llx" #define REG_FMT "%016lx"
#else #else
#define REG_FMT "%08x" #define REG_FMT "%08x"
#endif #endif

View File

@@ -32,6 +32,7 @@ enum sbi_ext_id {
SBI_EXT_SUSP = 0x53555350, SBI_EXT_SUSP = 0x53555350,
SBI_EXT_PMU = 0x504D55, SBI_EXT_PMU = 0x504D55,
SBI_EXT_CONFIG_IOPMP = 0x5A5A5A5A, SBI_EXT_CONFIG_IOPMP = 0x5A5A5A5A,
SBI_EXT_DBTR = 0x44425452,
/* Experimentals extensions must lie within this range */ /* Experimentals extensions must lie within this range */
SBI_EXT_EXPERIMENTAL_START = 0x08000000, SBI_EXT_EXPERIMENTAL_START = 0x08000000,
@@ -47,6 +48,34 @@ enum sbi_ext_config_iopmp_fid {
SBI_EXT_CONFIG_IOPMP_REMOVE_RULE, SBI_EXT_CONFIG_IOPMP_REMOVE_RULE,
}; };
/* SBI debug triggers function IDs */
enum sbi_ext_dbtr_fid {
SBI_EXT_DBTR_NUM_TRIGGERS = 0,
SBI_EXT_DBTR_SETUP_SHMEM,
SBI_EXT_DBTR_TRIG_READ,
SBI_EXT_DBTR_TRIG_INSTALL,
SBI_EXT_DBTR_TRIG_UPDATE,
SBI_EXT_DBTR_TRIG_UNINSTALL,
SBI_EXT_DBTR_TRIG_ENABLE,
SBI_EXT_DBTR_TRIG_DISABLE,
};
struct sbi_dbtr_data_msg {
unsigned long tstate;
unsigned long tdata1;
unsigned long tdata2;
unsigned long tdata3;
};
struct sbi_dbtr_id_msg {
unsigned long idx;
};
union sbi_dbtr_shmem_entry {
struct sbi_dbtr_data_msg data;
struct sbi_dbtr_id_msg id;
};
enum sbi_ext_base_fid { enum sbi_ext_base_fid {
SBI_EXT_BASE_GET_SPEC_VERSION = 0, SBI_EXT_BASE_GET_SPEC_VERSION = 0,
SBI_EXT_BASE_GET_IMP_ID, SBI_EXT_BASE_GET_IMP_ID,
@@ -288,9 +317,6 @@ void sbi_set_timer(uint64_t stime_value);
void sbi_shutdown(void); void sbi_shutdown(void);
void sbi_send_ipi(unsigned int cpu); void sbi_send_ipi(unsigned int cpu);
int sbi_remote_fence_i(const struct cpumask *cpu_mask); int sbi_remote_fence_i(const struct cpumask *cpu_mask);
int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
unsigned long start,
unsigned long size);
int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask, int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,

View File

@@ -15,7 +15,13 @@ static void tlb_flush(struct mmu_gather *tlb);
static inline void tlb_flush(struct mmu_gather *tlb) static inline void tlb_flush(struct mmu_gather *tlb)
{ {
flush_tlb_mm(tlb->mm); #ifdef CONFIG_MMU
if (tlb->fullmm || tlb->need_flush_all)
flush_tlb_mm(tlb->mm);
else
flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end,
tlb_get_unmap_size(tlb));
#endif
} }
#endif /* _ASM_RISCV_TLB_H */ #endif /* _ASM_RISCV_TLB_H */

View File

@@ -11,6 +11,9 @@
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/errata_list.h> #include <asm/errata_list.h>
#define FLUSH_TLB_MAX_SIZE ((unsigned long)-1)
#define FLUSH_TLB_NO_ASID ((unsigned long)-1)
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
extern unsigned long asid_mask; extern unsigned long asid_mask;
@@ -32,9 +35,13 @@ static inline void local_flush_tlb_page(unsigned long addr)
#if defined(CONFIG_SMP) && defined(CONFIG_MMU) #if defined(CONFIG_SMP) && defined(CONFIG_MMU)
void flush_tlb_all(void); void flush_tlb_all(void);
void flush_tlb_mm(struct mm_struct *mm); void flush_tlb_mm(struct mm_struct *mm);
void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
unsigned long end, unsigned int page_size);
void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr); void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end); unsigned long end);
void flush_tlb_kernel_range(unsigned long start, unsigned long end);
void local_flush_tlb_kernel_range(unsigned long start, unsigned long end);
#ifdef CONFIG_TRANSPARENT_HUGEPAGE #ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE #define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
@@ -51,14 +58,15 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
local_flush_tlb_all(); local_flush_tlb_all();
} }
#define flush_tlb_mm(mm) flush_tlb_all()
#endif /* !CONFIG_SMP || !CONFIG_MMU */
/* Flush a range of kernel pages */ /* Flush a range of kernel pages */
static inline void flush_tlb_kernel_range(unsigned long start, static inline void flush_tlb_kernel_range(unsigned long start,
unsigned long end) unsigned long end)
{ {
flush_tlb_all(); local_flush_tlb_all();
} }
#define flush_tlb_mm(mm) flush_tlb_all()
#define flush_tlb_mm_range(mm, start, end, page_size) flush_tlb_all()
#endif /* !CONFIG_SMP || !CONFIG_MMU */
#endif /* _ASM_RISCV_TLBFLUSH_H */ #endif /* _ASM_RISCV_TLBFLUSH_H */

View File

@@ -15,6 +15,9 @@
#define PTRACE_GETFDPIC_EXEC 0 #define PTRACE_GETFDPIC_EXEC 0
#define PTRACE_GETFDPIC_INTERP 1 #define PTRACE_GETFDPIC_INTERP 1
/* Maximum number of hardware breakpoints supported */
#define HW_BP_NUM_MAX 16
/* /*
* User-mode register state for core dumps, ptrace, sigcontext * User-mode register state for core dumps, ptrace, sigcontext
* *
@@ -134,6 +137,15 @@ struct __riscv_m_ext_state {
*/ */
#define RISCV_MAX_VLENB (8192) #define RISCV_MAX_VLENB (8192)
struct user_hwdebug_state {
__u64 dbg_slots;
struct {
__u64 addr;
__u64 type;
__u64 len;
} dbg_regs[HW_BP_NUM_MAX];
};
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* _UAPI_ASM_RISCV_PTRACE_H */ #endif /* _UAPI_ASM_RISCV_PTRACE_H */

View File

@@ -81,6 +81,7 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_RISCV_SBI) += sbi.o obj-$(CONFIG_RISCV_SBI) += sbi.o
ifeq ($(CONFIG_RISCV_SBI), y) ifeq ($(CONFIG_RISCV_SBI), y)
obj-$(CONFIG_SMP) += sbi-ipi.o obj-$(CONFIG_SMP) += sbi-ipi.o

View File

@@ -0,0 +1,663 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2025 Ventana Micro Systems Inc.
*/
#include <linux/hw_breakpoint.h>
#include <linux/perf_event.h>
#include <linux/spinlock.h>
#include <linux/percpu.h>
#include <linux/kdebug.h>
#include <linux/bitops.h>
#include <linux/cpu.h>
#include <linux/cpuhotplug.h>
#include <asm/sbi.h>
/* Registered per-cpu bp/wp */
static DEFINE_PER_CPU(struct perf_event *, pcpu_hw_bp_events[HW_BP_NUM_MAX]);
static DEFINE_PER_CPU(unsigned long, ecall_lock_flags);
static DEFINE_PER_CPU(raw_spinlock_t, ecall_lock);
/* Per-cpu shared memory between S and M mode */
static union sbi_dbtr_shmem_entry __percpu *sbi_dbtr_shmem;
/* number of debug triggers on this cpu . */
static int dbtr_total_num __ro_after_init;
static int dbtr_type __ro_after_init;
static int dbtr_init __ro_after_init;
#if __riscv_xlen == 64
#define MEM_HI(_m) 0
#define MEM_LO(_m) ((u64)_m)
#elif __riscv_xlen == 32
#define MEM_HI(_m) ((u64)_m >> 32)
#define MEM_LO(_m) ((u64)_m & 0xFFFFFFFFUL)
#else
#error "Unknown __riscv_xlen"
#endif
static int arch_smp_setup_sbi_shmem(unsigned int cpu)
{
union sbi_dbtr_shmem_entry *dbtr_shmem;
unsigned long shmem_pa;
struct sbiret ret;
int rc = 0;
dbtr_shmem = per_cpu_ptr(sbi_dbtr_shmem, cpu);
if (!dbtr_shmem) {
pr_err("Invalid per-cpu shared memory for debug triggers\n");
return -ENODEV;
}
shmem_pa = __pa(dbtr_shmem);
ret = sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_SETUP_SHMEM,
MEM_LO(shmem_pa), MEM_HI(shmem_pa), 0, 0, 0, 0);
if (ret.error) {
switch (ret.error) {
case SBI_ERR_DENIED:
pr_warn("%s: Access denied for shared memory at %lx\n",
__func__, shmem_pa);
rc = -EPERM;
break;
case SBI_ERR_INVALID_PARAM:
case SBI_ERR_INVALID_ADDRESS:
pr_warn("%s: Invalid address parameter (%lu)\n",
__func__, ret.error);
rc = -EINVAL;
break;
case SBI_ERR_ALREADY_AVAILABLE:
pr_warn("%s: Shared memory is already set\n",
__func__);
rc = -EADDRINUSE;
break;
case SBI_ERR_FAILURE:
pr_err("%s: Internal sdtrig state error\n",
__func__);
rc = -ENXIO;
break;
default:
pr_warn("%s: Unknown error %lu\n", __func__, ret.error);
rc = -ENXIO;
break;
}
}
return rc;
}
static int arch_smp_teardown_sbi_shmem(unsigned int cpu)
{
struct sbiret ret;
/* Disable shared memory */
ret = sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_SETUP_SHMEM,
-1UL, -1UL, 0, 0, 0, 0);
if (ret.error) {
switch (ret.error) {
case SBI_ERR_DENIED:
pr_err("%s: Access denied for shared memory.\n",
__func__);
break;
case SBI_ERR_INVALID_PARAM:
case SBI_ERR_INVALID_ADDRESS:
pr_err("%s: Invalid address parameter (%lu)\n",
__func__, ret.error);
break;
case SBI_ERR_ALREADY_AVAILABLE:
pr_err("%s: Shared memory is already set\n",
__func__);
break;
case SBI_ERR_FAILURE:
pr_err("%s: Internal sdtrig state error\n",
__func__);
break;
default:
pr_err("%s: Unknown error %lu\n", __func__, ret.error);
break;
}
}
pr_warn("CPU %d: HW Breakpoint shared memory disabled.\n", cpu);
return 0;
}
static void init_sbi_dbtr(void)
{
unsigned long tdata1;
struct sbiret ret;
if (sbi_probe_extension(SBI_EXT_DBTR) <= 0) {
pr_warn("%s: SBI_EXT_DBTR is not supported\n", __func__);
dbtr_total_num = 0;
goto done;
}
ret = sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_NUM_TRIGGERS,
0, 0, 0, 0, 0, 0);
if (ret.error) {
pr_warn("%s: Failed to detect triggers\n", __func__);
dbtr_total_num = 0;
goto done;
}
tdata1 = 0;
RV_DBTR_SET_TDATA1_TYPE(tdata1, RV_DBTR_TRIG_MCONTROL6);
ret = sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_NUM_TRIGGERS,
tdata1, 0, 0, 0, 0, 0);
if (ret.error) {
pr_warn("%s: failed to detect mcontrol6 triggers\n", __func__);
} else if (!ret.value) {
pr_warn("%s: type 6 triggers not available\n", __func__);
} else {
dbtr_total_num = ret.value;
dbtr_type = RV_DBTR_TRIG_MCONTROL6;
pr_warn("%s: mcontrol6 trigger available.\n", __func__);
goto done;
}
/* fallback to type 2 triggers if type 6 is not available */
tdata1 = 0;
RV_DBTR_SET_TDATA1_TYPE(tdata1, RV_DBTR_TRIG_MCONTROL);
ret = sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_NUM_TRIGGERS,
tdata1, 0, 0, 0, 0, 0);
if (ret.error) {
pr_warn("%s: failed to detect mcontrol triggers\n", __func__);
} else if (!ret.value) {
pr_warn("%s: type 2 triggers not available\n", __func__);
} else {
dbtr_total_num = ret.value;
dbtr_type = RV_DBTR_TRIG_MCONTROL;
goto done;
}
done:
dbtr_init = 1;
}
int hw_breakpoint_slots(int type)
{
/*
* We can be called early, so don't rely on
* static variables being initialised.
*/
if (!dbtr_init)
init_sbi_dbtr();
return dbtr_total_num;
}
int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw)
{
unsigned int len;
unsigned long va;
va = hw->addr;
len = hw->len;
return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
}
static int rv_init_mcontrol_trigger(const struct perf_event_attr *attr,
struct arch_hw_breakpoint *hw)
{
switch (attr->bp_type) {
case HW_BREAKPOINT_X:
hw->type = RV_DBTR_BP;
RV_DBTR_SET_MC_EXEC(hw->tdata1);
break;
case HW_BREAKPOINT_R:
hw->type = RV_DBTR_WP;
RV_DBTR_SET_MC_LOAD(hw->tdata1);
break;
case HW_BREAKPOINT_W:
hw->type = RV_DBTR_WP;
RV_DBTR_SET_MC_STORE(hw->tdata1);
break;
case HW_BREAKPOINT_RW:
hw->type = RV_DBTR_WP;
RV_DBTR_SET_MC_LOAD(hw->tdata1);
RV_DBTR_SET_MC_STORE(hw->tdata1);
break;
default:
return -EINVAL;
}
RV_DBTR_SET_MC_SIZELO(hw->tdata1, 0);
// switch (attr->bp_len) {
// case HW_BREAKPOINT_LEN_1:
// hw->len = 1;
// RV_DBTR_SET_MC_SIZELO(hw->tdata1, 1);
// break;
// case HW_BREAKPOINT_LEN_2:
// hw->len = 2;
// RV_DBTR_SET_MC_SIZELO(hw->tdata1, 2);
// break;
// case HW_BREAKPOINT_LEN_4:
// hw->len = 4;
// RV_DBTR_SET_MC_SIZELO(hw->tdata1, 3);
// break;
// #if __riscv_xlen >= 64
// case HW_BREAKPOINT_LEN_8:
// hw->len = 8;
// RV_DBTR_SET_MC_SIZELO(hw->tdata1, 1);
// RV_DBTR_SET_MC_SIZEHI(hw->tdata1, 1);
// break;
// #endif
// default:
// return -EINVAL;
// }
RV_DBTR_SET_MC_TYPE(hw->tdata1, RV_DBTR_TRIG_MCONTROL);
CLEAR_DBTR_BIT(hw->tdata1, MC, DMODE);
CLEAR_DBTR_BIT(hw->tdata1, MC, TIMING);
CLEAR_DBTR_BIT(hw->tdata1, MC, SELECT);
CLEAR_DBTR_BIT(hw->tdata1, MC, ACTION);
CLEAR_DBTR_BIT(hw->tdata1, MC, CHAIN);
CLEAR_DBTR_BIT(hw->tdata1, MC, MATCH);
CLEAR_DBTR_BIT(hw->tdata1, MC, M);
SET_DBTR_BIT(hw->tdata1, MC, S);
SET_DBTR_BIT(hw->tdata1, MC, U);
return 0;
}
static int rv_init_mcontrol6_trigger(const struct perf_event_attr *attr,
struct arch_hw_breakpoint *hw)
{
switch (attr->bp_type) {
case HW_BREAKPOINT_X:
hw->type = RV_DBTR_BP;
RV_DBTR_SET_MC6_EXEC(hw->tdata1);
break;
case HW_BREAKPOINT_R:
hw->type = RV_DBTR_WP;
RV_DBTR_SET_MC6_LOAD(hw->tdata1);
break;
case HW_BREAKPOINT_W:
hw->type = RV_DBTR_WP;
RV_DBTR_SET_MC6_STORE(hw->tdata1);
break;
case HW_BREAKPOINT_RW:
hw->type = RV_DBTR_WP;
RV_DBTR_SET_MC6_STORE(hw->tdata1);
RV_DBTR_SET_MC6_LOAD(hw->tdata1);
break;
default:
return -EINVAL;
}
RV_DBTR_SET_MC6_SIZE(hw->tdata1, 0);
// switch (attr->bp_len) {
// case HW_BREAKPOINT_LEN_1:
// hw->len = 1;
// RV_DBTR_SET_MC6_SIZE(hw->tdata1, 1);
// break;
// case HW_BREAKPOINT_LEN_2:
// hw->len = 2;
// RV_DBTR_SET_MC6_SIZE(hw->tdata1, 2);
// break;
// case HW_BREAKPOINT_LEN_4:
// hw->len = 4;
// RV_DBTR_SET_MC6_SIZE(hw->tdata1, 3);
// break;
// case HW_BREAKPOINT_LEN_8:
// hw->len = 8;
// RV_DBTR_SET_MC6_SIZE(hw->tdata1, 5);
// break;
// default:
// return -EINVAL;
// }
RV_DBTR_SET_MC6_TYPE(hw->tdata1, RV_DBTR_TRIG_MCONTROL6);
CLEAR_DBTR_BIT(hw->tdata1, MC6, DMODE);
CLEAR_DBTR_BIT(hw->tdata1, MC6, TIMING);
CLEAR_DBTR_BIT(hw->tdata1, MC6, SELECT);
CLEAR_DBTR_BIT(hw->tdata1, MC6, ACTION);
CLEAR_DBTR_BIT(hw->tdata1, MC6, CHAIN);
CLEAR_DBTR_BIT(hw->tdata1, MC6, MATCH);
CLEAR_DBTR_BIT(hw->tdata1, MC6, M);
CLEAR_DBTR_BIT(hw->tdata1, MC6, VS);
CLEAR_DBTR_BIT(hw->tdata1, MC6, VU);
SET_DBTR_BIT(hw->tdata1, MC6, S);
SET_DBTR_BIT(hw->tdata1, MC6, U);
return 0;
}
int hw_breakpoint_arch_parse(struct perf_event *bp,
const struct perf_event_attr *attr,
struct arch_hw_breakpoint *hw)
{
int ret;
/* Breakpoint address */
hw->addr = attr->bp_addr;
hw->tdata2 = attr->bp_addr;
hw->tdata3 = 0x0;
switch (dbtr_type) {
case RV_DBTR_TRIG_MCONTROL:
ret = rv_init_mcontrol_trigger(attr, hw);
break;
case RV_DBTR_TRIG_MCONTROL6:
ret = rv_init_mcontrol6_trigger(attr, hw);
break;
default:
pr_warn("unsupported trigger type\n");
ret = -EOPNOTSUPP;
break;
}
return ret;
}
/*
* HW Breakpoint/watchpoint handler
*/
static int hw_breakpoint_handler(struct die_args *args)
{
int ret = NOTIFY_DONE;
struct arch_hw_breakpoint *bp;
struct perf_event *event;
int i;
for (i = 0; i < dbtr_total_num; i++) {
event = this_cpu_read(pcpu_hw_bp_events[i]);
if (!event)
continue;
bp = counter_arch_bp(event);
switch (bp->type) {
/* Breakpoint */
case RV_DBTR_BP:
if (bp->addr == args->regs->epc) {
perf_bp_event(event, args->regs);
ret = NOTIFY_STOP;
}
break;
/* Watchpoint */
case RV_DBTR_WP:
if (bp->addr == csr_read(CSR_STVAL)) {
perf_bp_event(event, args->regs);
ret = NOTIFY_STOP;
}
break;
default:
pr_warn("%s: Unknown type: %ld\n", __func__, bp->type);
break;
}
}
return ret;
}
int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
unsigned long val, void *data)
{
if (val != DIE_DEBUG)
return NOTIFY_DONE;
return hw_breakpoint_handler(data);
}
/* atomic: counter->ctx->lock is held */
int arch_install_hw_breakpoint(struct perf_event *event)
{
struct arch_hw_breakpoint *bp = counter_arch_bp(event);
union sbi_dbtr_shmem_entry *shmem = this_cpu_ptr(sbi_dbtr_shmem);
struct sbi_dbtr_data_msg *xmit;
struct sbi_dbtr_id_msg *recv;
struct perf_event **slot;
unsigned long idx;
struct sbiret ret;
int err = 0;
raw_spin_lock_irqsave(this_cpu_ptr(&ecall_lock),
*this_cpu_ptr(&ecall_lock_flags));
xmit = &shmem->data;
recv = &shmem->id;
xmit->tdata1 = cpu_to_le(bp->tdata1);
xmit->tdata2 = cpu_to_le(bp->tdata2);
xmit->tdata3 = cpu_to_le(bp->tdata3);
ret = sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_TRIG_INSTALL,
1, 0, 0, 0, 0, 0);
if (ret.error) {
pr_warn("%s: failed to install trigger\n", __func__);
err = -EIO;
goto done;
}
idx = le_to_cpu(recv->idx);
if (idx >= dbtr_total_num) {
pr_warn("%s: invalid trigger index %lu\n", __func__, idx);
err = -EINVAL;
goto done;
}
slot = this_cpu_ptr(&pcpu_hw_bp_events[idx]);
if (*slot) {
pr_warn("%s: slot %lu is in use\n", __func__, idx);
err = -EBUSY;
goto done;
}
pr_debug("Trigger %lu installed at index 0x%lx\n", bp->tdata2, idx);
/* Save the event - to be looked up in handler */
*slot = event;
done:
raw_spin_unlock_irqrestore(this_cpu_ptr(&ecall_lock),
*this_cpu_ptr(&ecall_lock_flags));
return err;
}
/* atomic: counter->ctx->lock is held */
void arch_uninstall_hw_breakpoint(struct perf_event *event)
{
struct sbiret ret;
int i;
for (i = 0; i < dbtr_total_num; i++) {
struct perf_event **slot = this_cpu_ptr(&pcpu_hw_bp_events[i]);
if (*slot == event) {
*slot = NULL;
break;
}
}
if (i == dbtr_total_num) {
pr_warn("%s: Breakpoint not installed.\n", __func__);
return;
}
ret = sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_TRIG_UNINSTALL,
i, 1, 0, 0, 0, 0);
if (ret.error)
pr_warn("%s: Failed to uninstall trigger %d.\n", __func__, i);
}
void arch_enable_hw_breakpoint(struct perf_event *event)
{
struct sbiret ret;
int i;
struct perf_event **slot;
for (i = 0; i < dbtr_total_num; i++) {
slot = this_cpu_ptr(&pcpu_hw_bp_events[i]);
if (*slot == event)
break;
}
if (i == dbtr_total_num) {
pr_warn("%s: Breakpoint not installed.\n", __func__);
return;
}
ret = sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_TRIG_ENABLE,
i, 1, 0, 0, 0, 0);
if (ret.error) {
pr_warn("%s: Failed to install trigger %d\n", __func__, i);
return;
}
}
EXPORT_SYMBOL_GPL(arch_enable_hw_breakpoint);
void arch_update_hw_breakpoint(struct perf_event *event)
{
struct arch_hw_breakpoint *bp = counter_arch_bp(event);
union sbi_dbtr_shmem_entry *shmem = this_cpu_ptr(sbi_dbtr_shmem);
struct sbi_dbtr_data_msg *xmit;
struct perf_event **slot;
struct sbiret ret;
int i;
for (i = 0; i < dbtr_total_num; i++) {
slot = this_cpu_ptr(&pcpu_hw_bp_events[i]);
if (*slot == event)
break;
}
if (i == dbtr_total_num) {
pr_warn("%s: Breakpoint not installed.\n", __func__);
return;
}
raw_spin_lock_irqsave(this_cpu_ptr(&ecall_lock),
*this_cpu_ptr(&ecall_lock_flags));
xmit = &shmem->data;
xmit->tdata1 = cpu_to_le(bp->tdata1);
xmit->tdata2 = cpu_to_le(bp->tdata2);
xmit->tdata3 = cpu_to_le(bp->tdata3);
ret = sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_TRIG_UPDATE,
i, 1, 0, 0, 0, 0);
if (ret.error)
pr_warn("%s: Failed to update trigger %d.\n", __func__, i);
raw_spin_unlock_irqrestore(this_cpu_ptr(&ecall_lock),
*this_cpu_ptr(&ecall_lock_flags));
}
EXPORT_SYMBOL_GPL(arch_update_hw_breakpoint);
void arch_disable_hw_breakpoint(struct perf_event *event)
{
struct sbiret ret;
int i;
for (i = 0; i < dbtr_total_num; i++) {
struct perf_event **slot = this_cpu_ptr(&pcpu_hw_bp_events[i]);
if (*slot == event)
break;
}
if (i == dbtr_total_num) {
pr_warn("%s: Breakpoint not installed.\n", __func__);
return;
}
ret = sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_TRIG_DISABLE,
i, 1, 0, 0, 0, 0);
if (ret.error) {
pr_warn("%s: Failed to uninstall trigger %d.\n", __func__, i);
return;
}
}
EXPORT_SYMBOL_GPL(arch_disable_hw_breakpoint);
void hw_breakpoint_pmu_read(struct perf_event *bp)
{
/* TODO */
}
void clear_ptrace_hw_breakpoint(struct task_struct *tsk)
{
/* TODO */
}
void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
{
int i;
struct thread_struct *t = &tsk->thread;
for (i = 0; i < HW_BP_NUM_MAX; i++) {
unregister_hw_breakpoint(t->ptrace_bps[i]);
t->ptrace_bps[i] = NULL;
}
}
static int __init arch_hw_breakpoint_init(void)
{
unsigned int cpu;
int rc = 0;
for_each_possible_cpu(cpu)
raw_spin_lock_init(&per_cpu(ecall_lock, cpu));
if (!dbtr_init)
init_sbi_dbtr();
if (dbtr_total_num) {
pr_info("%s: total number of type %d triggers: %u\n",
__func__, dbtr_type, dbtr_total_num);
} else {
pr_info("%s: No hardware triggers available\n", __func__);
goto out;
}
/* Allocate per-cpu shared memory */
sbi_dbtr_shmem = __alloc_percpu(sizeof(*sbi_dbtr_shmem) * dbtr_total_num,
PAGE_SIZE);
if (!sbi_dbtr_shmem) {
pr_warn("%s: Failed to allocate shared memory.\n", __func__);
rc = -ENOMEM;
goto out;
}
/* Hotplug handler to register/unregister shared memory with SBI */
rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"riscv/hw_breakpoint:prepare",
arch_smp_setup_sbi_shmem,
arch_smp_teardown_sbi_shmem);
if (rc < 0) {
pr_warn("%s: Failed to setup CPU hotplug state\n", __func__);
free_percpu(sbi_dbtr_shmem);
return rc;
}
out:
return rc;
}
arch_initcall(arch_hw_breakpoint_init);

View File

@@ -8,88 +8,88 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
DEFINE_PER_CPU(struct page *, p100_iomb_page); DEFINE_PER_CPU(struct page *, a210_iomb_page);
DEFINE_PER_CPU(void *, p100_iomb_flag0); DEFINE_PER_CPU(void *, a210_iomb_flag0);
DEFINE_PER_CPU(void *, p100_iomb_flag1); DEFINE_PER_CPU(void *, a210_iomb_flag1);
DEFINE_PER_CPU(void *, p100_iomb_flag2); DEFINE_PER_CPU(void *, a210_iomb_flag2);
DEFINE_PER_CPU(void *, p100_iomb_flag3); DEFINE_PER_CPU(void *, a210_iomb_flag3);
DEFINE_PER_CPU(u32, p100_iomb_data); DEFINE_PER_CPU(u32, a210_iomb_data);
inline void p100_iomb(void) inline void a210_iomb(void)
{ {
unsigned long flags; unsigned long flags;
unsigned int cpu; unsigned int cpu;
local_irq_save(flags); local_irq_save(flags);
cpu = smp_processor_id(); cpu = smp_processor_id();
mb(); mb();
*(unsigned int *)per_cpu(p100_iomb_flag0, cpu) = per_cpu(p100_iomb_data, cpu); *(unsigned int *)per_cpu(a210_iomb_flag0, cpu) = per_cpu(a210_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag1, cpu) = per_cpu(p100_iomb_data, cpu); *(unsigned int *)per_cpu(a210_iomb_flag1, cpu) = per_cpu(a210_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag2, cpu) = per_cpu(p100_iomb_data, cpu); *(unsigned int *)per_cpu(a210_iomb_flag2, cpu) = per_cpu(a210_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag3, cpu) = per_cpu(p100_iomb_data, cpu); *(unsigned int *)per_cpu(a210_iomb_flag3, cpu) = per_cpu(a210_iomb_data, cpu);
mb(); mb();
while (*(unsigned int *)per_cpu(p100_iomb_flag0, cpu) != per_cpu(p100_iomb_data, cpu)) {;} while (*(unsigned int *)per_cpu(a210_iomb_flag0, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag1, cpu) != per_cpu(p100_iomb_data, cpu)) {;} while (*(unsigned int *)per_cpu(a210_iomb_flag1, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag2, cpu) != per_cpu(p100_iomb_data, cpu)) {;} while (*(unsigned int *)per_cpu(a210_iomb_flag2, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag3, cpu) != per_cpu(p100_iomb_data, cpu)) {;} while (*(unsigned int *)per_cpu(a210_iomb_flag3, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
per_cpu(p100_iomb_data, cpu)++; per_cpu(a210_iomb_data, cpu)++;
mb(); mb();
local_irq_restore(flags); local_irq_restore(flags);
} }
EXPORT_SYMBOL(p100_iomb); EXPORT_SYMBOL(a210_iomb);
inline void p100_iowmb(void) inline void a210_iowmb(void)
{ {
unsigned long flags; unsigned long flags;
unsigned int cpu; unsigned int cpu;
local_irq_save(flags); local_irq_save(flags);
cpu = smp_processor_id(); cpu = smp_processor_id();
wmb(); wmb();
*(unsigned int *)per_cpu(p100_iomb_flag0, cpu) = per_cpu(p100_iomb_data, cpu); *(unsigned int *)per_cpu(a210_iomb_flag0, cpu) = per_cpu(a210_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag1, cpu) = per_cpu(p100_iomb_data, cpu); *(unsigned int *)per_cpu(a210_iomb_flag1, cpu) = per_cpu(a210_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag2, cpu) = per_cpu(p100_iomb_data, cpu); *(unsigned int *)per_cpu(a210_iomb_flag2, cpu) = per_cpu(a210_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag3, cpu) = per_cpu(p100_iomb_data, cpu); *(unsigned int *)per_cpu(a210_iomb_flag3, cpu) = per_cpu(a210_iomb_data, cpu);
wmb(); wmb();
while (*(unsigned int *)per_cpu(p100_iomb_flag0, cpu) != per_cpu(p100_iomb_data, cpu)) {;} while (*(unsigned int *)per_cpu(a210_iomb_flag0, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag1, cpu) != per_cpu(p100_iomb_data, cpu)) {;} while (*(unsigned int *)per_cpu(a210_iomb_flag1, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag2, cpu) != per_cpu(p100_iomb_data, cpu)) {;} while (*(unsigned int *)per_cpu(a210_iomb_flag2, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag3, cpu) != per_cpu(p100_iomb_data, cpu)) {;} while (*(unsigned int *)per_cpu(a210_iomb_flag3, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
per_cpu(p100_iomb_data, cpu)++; per_cpu(a210_iomb_data, cpu)++;
wmb(); wmb();
local_irq_restore(flags); local_irq_restore(flags);
} }
EXPORT_SYMBOL(p100_iowmb); EXPORT_SYMBOL(a210_iowmb);
static int __init p100_iomb_init(void) static int __init a210_iomb_init(void)
{ {
unsigned int cpu; unsigned int cpu;
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
per_cpu(p100_iomb_page, cpu) = alloc_page(GFP_KERNEL); per_cpu(a210_iomb_page, cpu) = alloc_page(GFP_KERNEL);
if (!per_cpu(p100_iomb_page, cpu)) if (!per_cpu(a210_iomb_page, cpu))
return -ENOMEM; return -ENOMEM;
per_cpu(p100_iomb_flag0, cpu) = vmap(&per_cpu(p100_iomb_page, cpu), 1, per_cpu(a210_iomb_flag0, cpu) = vmap(&per_cpu(a210_iomb_page, cpu), 1,
VM_DMA_COHERENT, pgprot_writecombine(PAGE_KERNEL)); VM_DMA_COHERENT, pgprot_writecombine(PAGE_KERNEL));
per_cpu(p100_iomb_flag1, cpu) = per_cpu(p100_iomb_flag0, cpu) + 128; per_cpu(a210_iomb_flag1, cpu) = per_cpu(a210_iomb_flag0, cpu) + 128;
per_cpu(p100_iomb_flag2, cpu) = per_cpu(p100_iomb_flag1, cpu) + 128; per_cpu(a210_iomb_flag2, cpu) = per_cpu(a210_iomb_flag1, cpu) + 128;
per_cpu(p100_iomb_flag3, cpu) = per_cpu(p100_iomb_flag2, cpu) + 128; per_cpu(a210_iomb_flag3, cpu) = per_cpu(a210_iomb_flag2, cpu) + 128;
per_cpu(p100_iomb_data, cpu) = 1; per_cpu(a210_iomb_data, cpu) = 1;
} }
return 0; return 0;
} }
pure_initcall(p100_iomb_init); pure_initcall(a210_iomb_init);
MODULE_AUTHOR("dong.yan <yand@zhcomputing.com>"); MODULE_AUTHOR("dong.yan <yand@zhcomputing.com>");
MODULE_DESCRIPTION("Memory barrier work around for p100 ncore bug"); MODULE_DESCRIPTION("Memory barrier work around for a210 ncore");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");

View File

@@ -15,6 +15,7 @@
#include <linux/tick.h> #include <linux/tick.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/hw_breakpoint.h>
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/processor.h> #include <asm/processor.h>
@@ -154,6 +155,9 @@ void flush_thread(void)
kfree(current->thread.vstate.datap); kfree(current->thread.vstate.datap);
memset(&current->thread.vstate, 0, sizeof(struct __riscv_v_ext_state)); memset(&current->thread.vstate, 0, sizeof(struct __riscv_v_ext_state));
#endif #endif
#ifdef CONFIG_HAVE_HW_BREAKPOINT
flush_ptrace_hw_breakpoint(current);
#endif
} }
void arch_release_task_struct(struct task_struct *tsk) void arch_release_task_struct(struct task_struct *tsk)
@@ -180,6 +184,10 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
unsigned long tls = args->tls; unsigned long tls = args->tls;
struct pt_regs *childregs = task_pt_regs(p); struct pt_regs *childregs = task_pt_regs(p);
#ifdef CONFIG_HAVE_HW_BREAKPOINT
clear_ptrace_hw_breakpoint(p);
#endif
memset(&p->thread.s, 0, sizeof(p->thread.s)); memset(&p->thread.s, 0, sizeof(p->thread.s));
/* p->thread holds context to be restored by __switch_to() */ /* p->thread holds context to be restored by __switch_to() */

View File

@@ -19,6 +19,7 @@
#include <linux/regset.h> #include <linux/regset.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sched/task_stack.h> #include <linux/sched/task_stack.h>
#include <linux/hw_breakpoint.h>
enum riscv_regset { enum riscv_regset {
REGSET_X, REGSET_X,
@@ -28,6 +29,10 @@ enum riscv_regset {
#ifdef CONFIG_RISCV_ISA_V #ifdef CONFIG_RISCV_ISA_V
REGSET_V, REGSET_V,
#endif #endif
#ifdef CONFIG_HAVE_HW_BREAKPOINT
REGSET_HW_BREAK,
REGSET_HW_WATCH,
#endif
}; };
static int riscv_gpr_get(struct task_struct *target, static int riscv_gpr_get(struct task_struct *target,
@@ -159,6 +164,218 @@ static int riscv_vr_set(struct task_struct *target,
} }
#endif #endif
#ifdef CONFIG_HAVE_HW_BREAKPOINT
static void ptrace_hbptriggered(struct perf_event *bp,
struct perf_sample_data *data,
struct pt_regs *regs)
{
struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
force_sig_fault(SIGTRAP, TRAP_HWBKPT, (void __user *)bkpt->addr);
}
static int hw_break_get(struct task_struct *target,
const struct user_regset *regset,
struct membuf to)
{
/* send total number of h/w debug triggers */
struct user_hwdebug_state hw_state;
hw_state.dbg_slots = hw_breakpoint_slots(regset->core_note_type);
membuf_write(&to, &hw_state, sizeof(hw_state));
return 0;
}
static inline int hw_break_empty(u64 addr, u64 type, u64 len)
{
/* TODO: for now adjusted to current riscv-gdb behavior */
return (!addr && !len);
}
static int hw_break_cache_trigger(struct task_struct *target, u32 note_type,
u64 addr, u64 type, u64 len, u32 idx)
{
struct arch_hw_breakpoint *bp;
u64 bp_type;
u64 bp_len;
// pr_info("%s:[%d] note_type=%d addr=%llx type=%lld len=%lld\n", __func__, idx, note_type, addr, type, len);
if (!hw_break_empty(addr, type, len)) {
/* bp len: gdb to kernel */
switch (len) {
case 2:
bp_len = HW_BREAKPOINT_LEN_2;
break;
case 4:
bp_len = HW_BREAKPOINT_LEN_4;
break;
case 8:
bp_len = HW_BREAKPOINT_LEN_8;
break;
default:
pr_warn("%s: unsupported len: %llu\n", __func__, len);
return -EINVAL;
}
/* bp type: gdb to kernel */
switch (type) {
case 0:
bp_type = HW_BREAKPOINT_X;
break;
case 1:
bp_type = HW_BREAKPOINT_R;
break;
case 2:
bp_type = HW_BREAKPOINT_W;
break;
case 3:
bp_type = HW_BREAKPOINT_RW;
break;
default:
pr_warn("%s: unsupported type: %llu\n", __func__, type);
return -EINVAL;
}
}
if (note_type == NT_RISCV_HW_BREAK)
bp = &(target->thread.hbp_break[idx]);
if (note_type == NT_RISCV_HW_WATCH)
bp = &(target->thread.hbp_watch[idx]);
bp->addr = addr;
bp->type = bp_type;
bp->len = bp_len;
return 0;
}
static int hw_break_register_trigger(struct task_struct *target, u32 note_type,
u64 addr, u64 type, u64 len, u32 idx)
{
struct perf_event *bp = ERR_PTR(-EINVAL);
struct perf_event_attr attr;
// pr_info("%s:[%d] note_type=%d addr=%llx type=%lld len=%lld\n", __func__, idx, note_type, addr, type, len);
bp = target->thread.ptrace_bps[idx];
if (bp) {
attr = bp->attr;
if (hw_break_empty(addr, type, len)) {
attr.disabled = 1;
} else {
attr.bp_addr = addr;
attr.bp_type = type;
attr.bp_len = len;
attr.disabled = 0;
}
return modify_user_hw_breakpoint(bp, &attr);
}
ptrace_breakpoint_init(&attr);
attr.bp_addr = addr;
attr.bp_type = type;
attr.bp_len = len;
bp = register_user_hw_breakpoint(&attr, ptrace_hbptriggered,
NULL, target);
if (IS_ERR(bp)) {
pr_err("%s failed! ret=%ld\n", __func__, PTR_ERR(bp));
return PTR_ERR(bp);
}
target->thread.ptrace_bps[idx] = bp;
return 0;
}
static int hw_break_setup_trigger(struct task_struct *target)
{
u32 i, idx = 0;
flush_ptrace_hw_breakpoint(target);
for (i = 0; i < HW_BP_NUM_MAX; i++) {
if (target->thread.hbp_break[i].addr) {
hw_break_register_trigger(target, NT_RISCV_HW_BREAK, target->thread.hbp_break[i].addr, target->thread.hbp_break[i].type, target->thread.hbp_break[i].len, idx);
idx++;
}
}
for (i = 0; i < HW_BP_NUM_MAX; i++) {
if (target->thread.hbp_watch[i].addr) {
hw_break_register_trigger(target, NT_RISCV_HW_WATCH, target->thread.hbp_watch[i].addr, target->thread.hbp_watch[i].type, target->thread.hbp_watch[i].len, idx);
idx++;
}
}
return idx;
}
static int hw_break_set(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
{
int ret, idx = 0, offset, limit, note_type;
u64 addr;
u64 type;
u64 size;
#define PTRACE_HBP_ADDR_SZ sizeof(u64)
#define PTRACE_HBP_TYPE_SZ sizeof(u64)
#define PTRACE_HBP_SIZE_SZ sizeof(u64)
note_type = regset->core_note_type; // NT_RISCV_HW_BREAK(0x904) | NT_RISCV_HW_WATCH(0x905)
/* Resource info and pad */
offset = offsetof(struct user_hwdebug_state, dbg_regs);
user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
// pr_info("%s: core_note_type=%d count=%d offset=%d regset.n=%d regset.size=%d\n", __func__, regset->core_note_type, count, offset, regset->n, regset->size);
/* trigger settings */
limit = regset->n * regset->size;
while (count && offset < limit) {
if (count <= PTRACE_HBP_ADDR_SZ)
return -EINVAL;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
offset, offset + PTRACE_HBP_ADDR_SZ);
if (ret)
return ret;
offset += PTRACE_HBP_ADDR_SZ;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &type,
offset, offset + PTRACE_HBP_TYPE_SZ);
if (ret)
return ret;
offset += PTRACE_HBP_TYPE_SZ;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &size,
offset, offset + PTRACE_HBP_SIZE_SZ);
if (ret)
return ret;
offset += PTRACE_HBP_SIZE_SZ;
ret = hw_break_cache_trigger(target, note_type, addr, type, size, idx);
if (ret)
return ret;
idx++;
}
// pr_info("%s: count=%d offset=%d\n", __func__, count, offset);
hw_break_setup_trigger(target);
return 0;
}
#endif
static const struct user_regset riscv_user_regset[] = { static const struct user_regset riscv_user_regset[] = {
[REGSET_X] = { [REGSET_X] = {
.core_note_type = NT_PRSTATUS, .core_note_type = NT_PRSTATUS,
@@ -189,6 +406,24 @@ static const struct user_regset riscv_user_regset[] = {
.set = riscv_vr_set, .set = riscv_vr_set,
}, },
#endif #endif
#ifdef CONFIG_HAVE_HW_BREAKPOINT
[REGSET_HW_BREAK] = {
.core_note_type = NT_RISCV_HW_BREAK,
.n = sizeof(struct user_hwdebug_state) / sizeof(u32),
.size = sizeof(u32),
.align = sizeof(u32),
.regset_get = hw_break_get,
.set = hw_break_set,
},
[REGSET_HW_WATCH] = {
.core_note_type = NT_RISCV_HW_WATCH,
.n = sizeof(struct user_hwdebug_state) / sizeof(u32),
.size = sizeof(u32),
.align = sizeof(u32),
.regset_get = hw_break_get,
.set = hw_break_set,
},
#endif
}; };
static const struct user_regset_view riscv_user_native_view = { static const struct user_regset_view riscv_user_native_view = {

View File

@@ -11,6 +11,7 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <asm/sbi.h> #include <asm/sbi.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/tlbflush.h>
/* default SBI version is 0.1 */ /* default SBI version is 0.1 */
unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT; unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
@@ -376,32 +377,15 @@ int sbi_remote_fence_i(const struct cpumask *cpu_mask)
} }
EXPORT_SYMBOL(sbi_remote_fence_i); EXPORT_SYMBOL(sbi_remote_fence_i);
/**
* sbi_remote_sfence_vma() - Execute SFENCE.VMA instructions on given remote
* harts for the specified virtual address range.
* @cpu_mask: A cpu mask containing all the target harts.
* @start: Start of the virtual address
* @size: Total size of the virtual address range.
*
* Return: 0 on success, appropriate linux error code otherwise.
*/
int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
unsigned long start,
unsigned long size)
{
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
cpu_mask, start, size, 0, 0);
}
EXPORT_SYMBOL(sbi_remote_sfence_vma);
/** /**
* sbi_remote_sfence_vma_asid() - Execute SFENCE.VMA instructions on given * sbi_remote_sfence_vma_asid() - Execute SFENCE.VMA instructions on given
* remote harts for a virtual address range belonging to a specific ASID. * remote harts for a virtual address range belonging to a specific ASID or not.
* *
* @cpu_mask: A cpu mask containing all the target harts. * @cpu_mask: A cpu mask containing all the target harts.
* @start: Start of the virtual address * @start: Start of the virtual address
* @size: Total size of the virtual address range. * @size: Total size of the virtual address range.
* @asid: The value of address space identifier (ASID). * @asid: The value of address space identifier (ASID), or FLUSH_TLB_NO_ASID
* for flushing all address spaces.
* *
* Return: 0 on success, appropriate linux error code otherwise. * Return: 0 on success, appropriate linux error code otherwise.
*/ */
@@ -410,8 +394,12 @@ int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask,
unsigned long size, unsigned long size,
unsigned long asid) unsigned long asid)
{ {
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID, if (asid == FLUSH_TLB_NO_ASID)
cpu_mask, start, size, asid, 0); return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
cpu_mask, start, size, 0, 0);
else
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
cpu_mask, start, size, asid, 0);
} }
EXPORT_SYMBOL(sbi_remote_sfence_vma_asid); EXPORT_SYMBOL(sbi_remote_sfence_vma_asid);

View File

@@ -239,6 +239,7 @@ asmlinkage __visible void smp_callin(void)
mmgrab(mm); mmgrab(mm);
current->active_mm = mm; current->active_mm = mm;
rcu_cpu_starting(curr_cpuid);
store_cpu_topology(curr_cpuid); store_cpu_topology(curr_cpuid);
notify_cpu_starting(curr_cpuid); notify_cpu_starting(curr_cpuid);

View File

@@ -271,6 +271,12 @@ void handle_break(struct pt_regs *regs)
if (probe_breakpoint_handler(regs)) if (probe_breakpoint_handler(regs))
return; return;
#ifdef CONFIG_HAVE_HW_BREAKPOINT
if (notify_die(DIE_DEBUG, "EBREAK", regs, 0, regs->cause, SIGTRAP)
== NOTIFY_STOP)
return;
#endif
current->thread.bad_cause = regs->cause; current->thread.bad_cause = regs->cause;
if (user_mode(regs)) if (user_mode(regs))

View File

@@ -20,7 +20,6 @@
DEFINE_STATIC_KEY_FALSE(use_asid_allocator); DEFINE_STATIC_KEY_FALSE(use_asid_allocator);
static unsigned long asid_bits;
static unsigned long num_asids; static unsigned long num_asids;
unsigned long asid_mask; unsigned long asid_mask;
@@ -159,7 +158,7 @@ static void set_mm_asid(struct mm_struct *mm, unsigned int cpu)
* *
* - We get a zero back from the cmpxchg and end up waiting on the * - We get a zero back from the cmpxchg and end up waiting on the
* lock. Taking the lock synchronises with the rollover and so * lock. Taking the lock synchronises with the rollover and so
* we are forced to see the updated verion. * we are forced to see the updated version.
* *
* - We get a valid context back from the cmpxchg then we continue * - We get a valid context back from the cmpxchg then we continue
* using old ASID because __flush_context() would have marked ASID * using old ASID because __flush_context() would have marked ASID
@@ -238,8 +237,7 @@ static inline void set_mm(struct mm_struct *prev,
static int __init asids_init(void) static int __init asids_init(void)
{ {
#if 0 unsigned long asid_bits, old;
unsigned long old;
/* Figure-out number of ASID bits in HW */ /* Figure-out number of ASID bits in HW */
old = csr_read(CSR_SATP); old = csr_read(CSR_SATP);
@@ -283,7 +281,6 @@ static int __init asids_init(void)
} else { } else {
pr_info("ASID allocator disabled (%lu bits)\n", asid_bits); pr_info("ASID allocator disabled (%lu bits)\n", asid_bits);
} }
#endif
return 0; return 0;
} }
early_initcall(asids_init); early_initcall(asids_init);

View File

@@ -3,34 +3,56 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/hugetlb.h>
#include <asm/sbi.h> #include <asm/sbi.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
static inline void local_flush_tlb_all_asid(unsigned long asid) static inline void local_flush_tlb_all_asid(unsigned long asid)
{ {
__asm__ __volatile__ ("sfence.vma sp, x0\n ld x0, (sp)\n" ::: "memory"); if (asid != FLUSH_TLB_NO_ASID)
__asm__ __volatile__ ("sfence.vma x0, %0" __asm__ __volatile__ ("sfence.vma x0, %0"
: :
: "r" (asid) : "r" (asid)
: "memory"); : "memory");
else
local_flush_tlb_all();
} }
static inline void local_flush_tlb_page_asid(unsigned long addr, static inline void local_flush_tlb_page_asid(unsigned long addr,
unsigned long asid) unsigned long asid)
{ {
__asm__ __volatile__ ("sfence.vma %0, %1" if (asid != FLUSH_TLB_NO_ASID)
: __asm__ __volatile__ ("sfence.vma %0, %1"
: "r" (addr), "r" (asid) :
: "memory"); : "r" (addr), "r" (asid)
: "memory");
else
local_flush_tlb_page(addr);
} }
static inline void local_flush_tlb_range(unsigned long start, /*
unsigned long size, unsigned long stride) * Flush entire TLB if number of entries to be flushed is greater
* than the threshold below.
*/
static unsigned long tlb_flush_all_threshold __read_mostly = 64;
static void local_flush_tlb_range_threshold_asid(unsigned long start,
unsigned long size,
unsigned long stride,
unsigned long asid)
{ {
if (size <= stride) unsigned long nr_ptes_in_range = DIV_ROUND_UP(size, stride);
local_flush_tlb_page(start); int i;
else
local_flush_tlb_all(); if (nr_ptes_in_range > tlb_flush_all_threshold) {
local_flush_tlb_all_asid(asid);
return;
}
for (i = 0; i < nr_ptes_in_range; ++i) {
local_flush_tlb_page_asid(start, asid);
start += stride;
}
} }
static inline void local_flush_tlb_range_asid(unsigned long start, static inline void local_flush_tlb_range_asid(unsigned long start,
@@ -38,8 +60,15 @@ static inline void local_flush_tlb_range_asid(unsigned long start,
{ {
if (size <= stride) if (size <= stride)
local_flush_tlb_page_asid(start, asid); local_flush_tlb_page_asid(start, asid);
else else if (size == FLUSH_TLB_MAX_SIZE)
local_flush_tlb_all_asid(asid); local_flush_tlb_all_asid(asid);
else
local_flush_tlb_range_threshold_asid(start, size, stride, asid);
}
void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
local_flush_tlb_range_asid(start, end, PAGE_SIZE, FLUSH_TLB_NO_ASID);
} }
static void __ipi_flush_tlb_all(void *info) static void __ipi_flush_tlb_all(void *info)
@@ -52,7 +81,7 @@ void flush_tlb_all(void)
if (riscv_use_ipi_for_rfence()) if (riscv_use_ipi_for_rfence())
on_each_cpu(__ipi_flush_tlb_all, NULL, 1); on_each_cpu(__ipi_flush_tlb_all, NULL, 1);
else else
sbi_remote_sfence_vma(NULL, 0, -1); sbi_remote_sfence_vma_asid(NULL, 0, FLUSH_TLB_MAX_SIZE, FLUSH_TLB_NO_ASID);
} }
struct flush_tlb_range_data { struct flush_tlb_range_data {
@@ -69,68 +98,62 @@ static void __ipi_flush_tlb_range_asid(void *info)
local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid); local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
} }
static void __ipi_flush_tlb_range(void *info)
{
struct flush_tlb_range_data *d = info;
local_flush_tlb_range(d->start, d->size, d->stride);
}
static void __flush_tlb_range(struct mm_struct *mm, unsigned long start, static void __flush_tlb_range(struct mm_struct *mm, unsigned long start,
unsigned long size, unsigned long stride) unsigned long size, unsigned long stride)
{ {
struct flush_tlb_range_data ftd; struct flush_tlb_range_data ftd;
struct cpumask *cmask = mm_cpumask(mm); const struct cpumask *cmask;
unsigned int cpuid; unsigned long asid = FLUSH_TLB_NO_ASID;
bool broadcast; bool broadcast;
if (cpumask_empty(cmask)) if (mm) {
return; unsigned int cpuid;
cpuid = get_cpu(); cmask = mm_cpumask(mm);
/* check if the tlbflush needs to be sent to other CPUs */ if (cpumask_empty(cmask))
broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids; return;
if (static_branch_unlikely(&use_asid_allocator)) {
unsigned long asid = atomic_long_read(&mm->context.id) & asid_mask;
if (broadcast) { cpuid = get_cpu();
if (riscv_use_ipi_for_rfence()) { /* check if the tlbflush needs to be sent to other CPUs */
ftd.asid = asid; broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids;
ftd.start = start;
ftd.size = size; if (static_branch_unlikely(&use_asid_allocator))
ftd.stride = stride; asid = atomic_long_read(&mm->context.id) & asid_mask;
on_each_cpu_mask(cmask,
__ipi_flush_tlb_range_asid,
&ftd, 1);
} else
sbi_remote_sfence_vma_asid(cmask,
start, size, asid);
} else {
local_flush_tlb_range_asid(start, size, stride, asid);
}
} else { } else {
if (broadcast) { cmask = cpu_online_mask;
if (riscv_use_ipi_for_rfence()) { broadcast = true;
ftd.asid = 0;
ftd.start = start;
ftd.size = size;
ftd.stride = stride;
on_each_cpu_mask(cmask,
__ipi_flush_tlb_range,
&ftd, 1);
} else
sbi_remote_sfence_vma(cmask, start, size);
} else {
local_flush_tlb_range(start, size, stride);
}
} }
put_cpu(); if (broadcast) {
if (riscv_use_ipi_for_rfence()) {
ftd.asid = asid;
ftd.start = start;
ftd.size = size;
ftd.stride = stride;
on_each_cpu_mask(cmask,
__ipi_flush_tlb_range_asid,
&ftd, 1);
} else
sbi_remote_sfence_vma_asid(cmask,
start, size, asid);
} else {
local_flush_tlb_range_asid(start, size, stride, asid);
}
if (mm)
put_cpu();
} }
void flush_tlb_mm(struct mm_struct *mm) void flush_tlb_mm(struct mm_struct *mm)
{ {
__flush_tlb_range(mm, 0, -1, PAGE_SIZE); __flush_tlb_range(mm, 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE);
}
void flush_tlb_mm_range(struct mm_struct *mm,
unsigned long start, unsigned long end,
unsigned int page_size)
{
__flush_tlb_range(mm, start, end - start, page_size);
} }
void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
@@ -141,8 +164,40 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end) unsigned long end)
{ {
__flush_tlb_range(vma->vm_mm, start, end - start, PAGE_SIZE); unsigned long stride_size;
if (!is_vm_hugetlb_page(vma)) {
stride_size = PAGE_SIZE;
} else {
stride_size = huge_page_size(hstate_vma(vma));
/*
* As stated in the privileged specification, every PTE in a
* NAPOT region must be invalidated, so reset the stride in that
* case.
*/
if (has_svnapot()) {
if (stride_size >= PGDIR_SIZE)
stride_size = PGDIR_SIZE;
else if (stride_size >= P4D_SIZE)
stride_size = P4D_SIZE;
else if (stride_size >= PUD_SIZE)
stride_size = PUD_SIZE;
else if (stride_size >= PMD_SIZE)
stride_size = PMD_SIZE;
else
stride_size = PAGE_SIZE;
}
}
__flush_tlb_range(vma->vm_mm, start, end - start, stride_size);
} }
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
__flush_tlb_range(NULL, start, end - start, PAGE_SIZE);
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE #ifdef CONFIG_TRANSPARENT_HUGEPAGE
void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end) unsigned long end)

View File

@@ -90,6 +90,7 @@ extern void copy_from_user_page(struct vm_area_struct *vma,
unsigned long len); unsigned long len);
#define flush_cache_vmap(start, end) local_flush_cache_all(NULL) #define flush_cache_vmap(start, end) local_flush_cache_all(NULL)
#define flush_cache_vmap_early(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) local_flush_cache_all(NULL) #define flush_cache_vunmap(start, end) local_flush_cache_all(NULL)
#define flush_dcache_mmap_lock(mapping) do { } while (0) #define flush_dcache_mmap_lock(mapping) do { } while (0)

View File

@@ -48,6 +48,7 @@ static inline void flush_dcache_page(struct page *page)
#define flush_dcache_mmap_unlock(mapping) do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vmap(start, end) flush_cache_all()
#define flush_cache_vmap_early(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all()
/* When a context switch happens we must flush all user windows so that /* When a context switch happens we must flush all user windows so that

View File

@@ -75,6 +75,7 @@ void flush_ptrace_access(struct vm_area_struct *, struct page *,
#define flush_dcache_mmap_unlock(mapping) do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0) #define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vmap_early(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0) #define flush_cache_vunmap(start, end) do { } while (0)
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

View File

@@ -116,8 +116,9 @@ void flush_cache_page(struct vm_area_struct*,
#define flush_cache_mm(mm) flush_cache_all() #define flush_cache_mm(mm) flush_cache_all()
#define flush_cache_dup_mm(mm) flush_cache_mm(mm) #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
#define flush_cache_vmap(start,end) flush_cache_all() #define flush_cache_vmap(start,end) flush_cache_all()
#define flush_cache_vunmap(start,end) flush_cache_all() #define flush_cache_vmap_early(start,end) do { } while (0)
#define flush_cache_vunmap(start,end) flush_cache_all()
void flush_dcache_folio(struct folio *folio); void flush_dcache_folio(struct folio *folio);
#define flush_dcache_folio flush_dcache_folio #define flush_dcache_folio flush_dcache_folio
@@ -140,6 +141,7 @@ void local_flush_cache_page(struct vm_area_struct *vma,
#define flush_cache_dup_mm(mm) do { } while (0) #define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_vmap(start,end) do { } while (0) #define flush_cache_vmap(start,end) do { } while (0)
#define flush_cache_vmap_early(start,end) do { } while (0)
#define flush_cache_vunmap(start,end) do { } while (0) #define flush_cache_vunmap(start,end) do { } while (0)
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0

View File

@@ -683,6 +683,7 @@ void ahci_start_engine(struct ata_port *ap)
u32 tmp; u32 tmp;
/* start DMA */ /* start DMA */
dma_mb();
tmp = readl(port_mmio + PORT_CMD); tmp = readl(port_mmio + PORT_CMD);
tmp |= PORT_CMD_START; tmp |= PORT_CMD_START;
writel(tmp, port_mmio + PORT_CMD); writel(tmp, port_mmio + PORT_CMD);

View File

@@ -108,7 +108,6 @@ static int __init memblk_init(void)
// Initialize the memory // Initialize the memory
reserved_memory_node = of_find_node_by_name(NULL, "memblock-memory"); reserved_memory_node = of_find_node_by_name(NULL, "memblock-memory");
if (!reserved_memory_node) { if (!reserved_memory_node) {
pr_err("Failed to find reserved memory node\n");
memblk->size = DEVICE_SIZE; memblk->size = DEVICE_SIZE;
memblk->data = vmalloc(memblk->size); memblk->data = vmalloc(memblk->size);
memblk->start = (phys_addr_t)memblk->data; memblk->start = (phys_addr_t)memblk->data;

View File

@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_ZHIHE_CLK) += \ obj-$(CONFIG_ZHIHE_CLK) += \
clk-helper.o clk-helper.o \
clk-pll.o
obj-$(CONFIG_CLK_A210) += clk-a210.o obj-$(CONFIG_CLK_A210) += clk-a210.o

View File

@@ -12,15 +12,66 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/types.h> #include <linux/types.h>
#include <dt-bindings/clock/a210-clock.h> #include <dt-bindings/clock/a210-clock.h>
#include "clk-helper.h" #include "clk-helper.h"
/* top reg idx */
#define PLL_WRAP 0
#define TOP_CRG 1
#define CPU_SS_CLK_SYSREG 2
#define CPU_SS_CPU_PLL 3
#define DDR0_SYSREG 4
#define DDR1_SYSREG 5
#define SLC_DUAL_SYSREG 6
#define TOP_CRG_T 7
#define CPU_SS_CCU 8
/* gpu reg idx */
#define GPU_SS_PWRAP_CLK_EN 0
#define GPU_SS_TOP_CLK_EN 1
/* pcie reg idx */
#define PCIE_CLK_EN 0
/* usb reg idx */
#define USB_CLK_EN 0
/* vi reg idx */
#define VI_CLK 0
#define VI_MISC_CTRL 1
/* vp reg idx */
#define VP_CLK 0
/* vo reg idx */
#define VO_CLK 0
#define VO_PATH_CTRL 1
/* npu reg idx */
#define NPU_CLK 0
#define NPU_TOP_CLK 1
/* d2d reg idx */
#define D2D_CRG_REG 0
/* peri reg idx */
#define PERI0_SYSREG 0
#define PERI1_SYSREG 1
#define PERI2_SYSREG 2
#define PERI3_SYSREG 3
#define TEE_CRG 4
static u32 share_cnt_ddr_pll_clk_en; static u32 share_cnt_ddr_pll_clk_en;
static u32 share_cnt_peri3_clkgen_sdio_ref_clk; static u32 share_cnt_peri3_clkgen_sdio_ref_clk;
enum a210_pll_clktype {
AUDIO0_PLL,
AUDIO1_PLL,
VIDEO_PLL,
GMAC_PLL,
DVFS_PLL,
DPU0_PLL,
DPU1_PLL,
DPU2_PLL,
TEE_PLL,
DDR_PLL,
C920_PLL,
C908_PLL,
};
static const char * const noc_cclk_mux_parents[] = {"dpu1_pll_foutvco", "video_pll_foutvco", "gmac_pll_foutvco"}; static const char * const noc_cclk_mux_parents[] = {"dpu1_pll_foutvco", "video_pll_foutvco", "gmac_pll_foutvco"};
static const char * const top_cpu_ddr1_aclk_parents[] = {"cbus2ddr_aclk1", "gmac_pll_foutpostdiv"}; static const char * const top_cpu_ddr1_aclk_parents[] = {"cbus2ddr_aclk1", "gmac_pll_foutpostdiv"};
static const char * const top_cpu_ddr0_aclk_parents[] = {"cbus2ddr_aclk0", "gmac_pll_foutpostdiv"}; static const char * const top_cpu_ddr0_aclk_parents[] = {"cbus2ddr_aclk0", "gmac_pll_foutpostdiv"};
@@ -79,82 +130,82 @@ static const char * const vo_mipi_pixclk_mux_parents[] = {"dpu0_pixclk", "dpu1_p
static const char * const vo_hdmi_pixclk_mux_parents[] = {"dpu0_pixclk", "dpu1_pixclk", "dpu2_pixclk"}; static const char * const vo_hdmi_pixclk_mux_parents[] = {"dpu0_pixclk", "dpu1_pixclk", "dpu2_pixclk"};
static const char * const vo_dptx_pixclk_mux_parents[] = {"dpu0_pixclk", "dpu1_pixclk", "dpu2_pixclk"}; static const char * const vo_dptx_pixclk_mux_parents[] = {"dpu0_pixclk", "dpu1_pixclk", "dpu2_pixclk"};
static struct p100_pll_rate_table p100_teepll_tbl[] = { static struct zhihe_pll_rate_table a210_teepll_tbl[] = {
PLL_RATE(2400000000, 800000000U, 1, 100, 0, 3, 1), PLL_RATE(2400000000, 800000000U, 1, 100, 0, 3, 1),
}; };
static struct p100_pll_rate_table p100_dpu2pll_tbl[] = { static struct zhihe_pll_rate_table a210_dpu2pll_tbl[] = {
PLL_RATE(2376000000, 1188000000U, 1, 99, 0, 2, 1), PLL_RATE(2376000000, 1188000000U, 1, 99, 0, 2, 1),
}; };
static struct p100_pll_rate_table p100_dpu1pll_tbl[] = { static struct zhihe_pll_rate_table a210_dpu1pll_tbl[] = {
PLL_RATE(2376000000, 1188000000U, 1, 99, 0, 2, 1), PLL_RATE(2376000000, 1188000000U, 1, 99, 0, 2, 1),
}; };
static struct p100_pll_rate_table p100_dpu0pll_tbl[] = { static struct zhihe_pll_rate_table a210_dpu0pll_tbl[] = {
PLL_RATE(2376000000, 1188000000U, 1, 99, 0, 2, 1), PLL_RATE(2376000000, 1188000000U, 1, 99, 0, 2, 1),
}; };
static struct p100_pll_rate_table p100_dvfspll_tbl[] = { static struct zhihe_pll_rate_table a210_dvfspll_tbl[] = {
PLL_RATE(1920000000, 960000000U, 1, 80, 0, 2, 1), PLL_RATE(1920000000, 960000000U, 1, 80, 0, 2, 1),
}; };
static struct p100_pll_rate_table p100_gmacpll_tbl[] = { static struct zhihe_pll_rate_table a210_gmacpll_tbl[] = {
PLL_RATE(3000000000, 1000000000U, 1, 125, 0, 3, 1), PLL_RATE(3000000000, 1000000000U, 1, 125, 0, 3, 1),
}; };
static struct p100_pll_rate_table p100_videopll_tbl[] = { static struct zhihe_pll_rate_table a210_videopll_tbl[] = {
PLL_RATE(2640000000U, 1320000000U, 1, 110, 0, 2, 1), PLL_RATE(2640000000U, 1320000000U, 1, 110, 0, 2, 1),
}; };
static struct p100_pll_rate_table p100_audio0pll_tbl[] = { static struct zhihe_pll_rate_table a210_audio0pll_tbl[] = {
PLL_RATE(2359296000U, 1179648000U, 1, 98, 5100274, 2, 1), PLL_RATE(2359296000U, 1179648000U, 1, 98, 5100274, 2, 1),
}; };
static struct p100_pll_rate_table p100_audio1pll_tbl[] = { static struct zhihe_pll_rate_table a210_audio1pll_tbl[] = {
PLL_RATE(2528870400U, 1264435200U, 1, 105, 6200859, 2, 1), PLL_RATE(2528870400U, 1264435200U, 1, 105, 6200859, 2, 1),
}; };
static struct p100_pll_rate_table p100_c908pll_tbl[] = { static struct zhihe_pll_rate_table a210_c908pll_tbl[] = {
PLL_RATE(1200000000U, 1200000000U, 1, 50, 0, 1, 1), PLL_RATE(1200000000U, 1200000000U, 1, 50, 0, 1, 1),
PLL_RATE(1500000000U, 1500000000U, 2, 125, 0, 1, 1), PLL_RATE(1500000000U, 1500000000U, 2, 125, 0, 1, 1),
PLL_RATE(1698000000U, 1698000000U, 4, 283, 0, 1, 1), PLL_RATE(1698000000U, 1698000000U, 4, 283, 0, 1, 1),
PLL_RATE(1896000000U, 1896000000U, 1, 79, 0, 1, 1), PLL_RATE(1896000000U, 1896000000U, 1, 79, 0, 1, 1),
}; };
static struct p100_pll_rate_table p100_c920pll_tbl[] = { static struct zhihe_pll_rate_table a210_c920pll_tbl[] = {
PLL_RATE(1500000000U, 1500000000U, 2, 125, 0, 1, 1), PLL_RATE(1500000000U, 1500000000U, 2, 125, 0, 1, 1),
PLL_RATE(1698000000U, 1698000000U, 4, 283, 0, 1, 1), PLL_RATE(1698000000U, 1698000000U, 4, 283, 0, 1, 1),
PLL_RATE(1896000000U, 1896000000U, 1, 79, 0, 1, 1), PLL_RATE(1896000000U, 1896000000U, 1, 79, 0, 1, 1),
PLL_RATE(2298000000U, 2298000000U, 4, 383, 0, 1, 1), PLL_RATE(2298000000U, 2298000000U, 4, 383, 0, 1, 1),
}; };
static struct p100_clk_info_pll plls_top[] = { static struct zhihe_clk_info_pll plls_top[] = {
PLL_PARAM(TEE_PLL, P100_PLL_VCO, p100_teepll_tbl, ARRAY_SIZE(p100_teepll_tbl), 0x160, 0x170, PLL_PARAM(TEE_PLL, ZHIHE_PLL_VCO, a210_teepll_tbl, ARRAY_SIZE(a210_teepll_tbl), 0x160, 0x170,
BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "tee_pll_foutvco_frequency"), BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "tee_pll_foutvco_frequency"),
PLL_PARAM(DPU2_PLL, P100_PLL_VCO, p100_dpu2pll_tbl, ARRAY_SIZE(p100_dpu2pll_tbl), 0x120, 0x130, PLL_PARAM(DPU2_PLL, ZHIHE_PLL_VCO, a210_dpu2pll_tbl, ARRAY_SIZE(a210_dpu2pll_tbl), 0x120, 0x130,
BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "dpu2_pll_foutvco_frequency"), BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "dpu2_pll_foutvco_frequency"),
PLL_PARAM(DPU1_PLL, P100_PLL_VCO, p100_dpu1pll_tbl, ARRAY_SIZE(p100_dpu1pll_tbl), 0x100, 0x110, PLL_PARAM(DPU1_PLL, ZHIHE_PLL_VCO, a210_dpu1pll_tbl, ARRAY_SIZE(a210_dpu1pll_tbl), 0x100, 0x110,
BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "dpu1_pll_foutvco_frequency"), BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "dpu1_pll_foutvco_frequency"),
PLL_PARAM(DPU0_PLL, P100_PLL_VCO, p100_dpu0pll_tbl, ARRAY_SIZE(p100_dpu0pll_tbl), 0x80, 0x90, PLL_PARAM(DPU0_PLL, ZHIHE_PLL_VCO, a210_dpu0pll_tbl, ARRAY_SIZE(a210_dpu0pll_tbl), 0x80, 0x90,
BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "dpu0_pll_foutvco_frequency"), BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "dpu0_pll_foutvco_frequency"),
PLL_PARAM(DVFS_PLL, P100_PLL_VCO, p100_dvfspll_tbl, ARRAY_SIZE(p100_dvfspll_tbl), 0x60, 0x70, PLL_PARAM(DVFS_PLL, ZHIHE_PLL_VCO, a210_dvfspll_tbl, ARRAY_SIZE(a210_dvfspll_tbl), 0x60, 0x70,
BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "dvfs_pll_foutvco_frequency"), BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "dvfs_pll_foutvco_frequency"),
PLL_PARAM(AUDIO0_PLL, P100_PLL_VCO, p100_audio0pll_tbl, ARRAY_SIZE(p100_audio0pll_tbl), 0x0, 0x10, PLL_PARAM(AUDIO0_PLL, ZHIHE_PLL_VCO, a210_audio0pll_tbl, ARRAY_SIZE(a210_audio0pll_tbl), 0x0, 0x10,
BIT(0), BIT(31), BIT(30), PLL_MODE_FRAC, "audio0_pll_foutvco_frequency"), BIT(0), BIT(31), BIT(30), PLL_MODE_FRAC, "audio0_pll_foutvco_frequency"),
PLL_PARAM(AUDIO1_PLL, P100_PLL_VCO, p100_audio1pll_tbl, ARRAY_SIZE(p100_audio1pll_tbl), 0x20, 0x30, PLL_PARAM(AUDIO1_PLL, ZHIHE_PLL_VCO, a210_audio1pll_tbl, ARRAY_SIZE(a210_audio1pll_tbl), 0x20, 0x30,
BIT(0), BIT(31), BIT(30), PLL_MODE_FRAC, "audio1_pll_foutvco_frequency"), BIT(0), BIT(31), BIT(30), PLL_MODE_FRAC, "audio1_pll_foutvco_frequency"),
PLL_PARAM(GMAC_PLL, P100_PLL_VCO, p100_gmacpll_tbl, ARRAY_SIZE(p100_gmacpll_tbl), 0x40, 0x50, PLL_PARAM(GMAC_PLL, ZHIHE_PLL_VCO, a210_gmacpll_tbl, ARRAY_SIZE(a210_gmacpll_tbl), 0x40, 0x50,
BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "gmac_pll_foutvco_frequency"), BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "gmac_pll_foutvco_frequency"),
PLL_PARAM(VIDEO_PLL, P100_PLL_VCO, p100_videopll_tbl, ARRAY_SIZE(p100_videopll_tbl), 0x140, 0x150, PLL_PARAM(VIDEO_PLL, ZHIHE_PLL_VCO, a210_videopll_tbl, ARRAY_SIZE(a210_videopll_tbl), 0x140, 0x150,
BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "video_pll_foutvco_frequency"), BIT(0), BIT(31), BIT(30), PLL_MODE_INT, "video_pll_foutvco_frequency"),
PLL_PARAM(C908_PLL, P100_PLL_VCO, p100_c908pll_tbl, ARRAY_SIZE(p100_c908pll_tbl), 0x0, 0x10, PLL_PARAM(C908_PLL, ZHIHE_PLL_VCO, a210_c908pll_tbl, ARRAY_SIZE(a210_c908pll_tbl), 0x0, 0x10,
BIT(0), BIT(31), BIT(30), PLL_MODE_INT, ""), BIT(0), BIT(31), BIT(30), PLL_MODE_INT, ""),
PLL_PARAM(C920_PLL, P100_PLL_VCO, p100_c920pll_tbl, ARRAY_SIZE(p100_c920pll_tbl), 0x40, 0x50, PLL_PARAM(C920_PLL, ZHIHE_PLL_VCO, a210_c920pll_tbl, ARRAY_SIZE(a210_c920pll_tbl), 0x40, 0x50,
BIT(0), BIT(31), BIT(30), PLL_MODE_INT, ""), BIT(0), BIT(31), BIT(30), PLL_MODE_INT, ""),
}; };
static struct p100_clk_reg regs_top[] = { static struct zhihe_clk_reg regs_top[] = {
REG(PLL_WRAP), REG(PLL_WRAP),
REG(TOP_CRG), REG(TOP_CRG),
REG(CPU_SS_CLK_SYSREG), REG(CPU_SS_CLK_SYSREG),
@@ -166,42 +217,43 @@ static struct p100_clk_reg regs_top[] = {
REG(CPU_SS_CCU), REG(CPU_SS_CCU),
}; };
static struct p100_clk_reg regs_gpu[] = { static struct zhihe_clk_reg regs_gpu[] = {
REG(GPU_SS_PWRAP_CLK_EN), REG(GPU_SS_PWRAP_CLK_EN),
REG(GPU_SS_TOP_CLK_EN), REG(GPU_SS_TOP_CLK_EN),
}; };
static struct p100_clk_reg regs_pcie[] = { static struct zhihe_clk_reg regs_pcie[] = {
REG(PCIE_CLK_EN), REG(PCIE_CLK_EN),
}; };
static struct p100_clk_reg regs_usb[] = { static struct zhihe_clk_reg regs_usb[] = {
REG(USB_CLK_EN), REG(USB_CLK_EN),
}; };
static struct p100_clk_reg regs_vi[] = { static struct zhihe_clk_reg regs_vi[] = {
REG(VI_CLK), REG(VI_CLK),
REG(VI_MISC_CTRL),
}; };
static struct p100_clk_reg regs_vp[] = { static struct zhihe_clk_reg regs_vp[] = {
REG(VP_CLK), REG(VP_CLK),
}; };
static struct p100_clk_reg regs_vo[] = { static struct zhihe_clk_reg regs_vo[] = {
REG(VO_CLK), REG(VO_CLK),
REG(VO_PATH_CTRL), REG(VO_PATH_CTRL),
}; };
static struct p100_clk_reg regs_npu[] = { static struct zhihe_clk_reg regs_npu[] = {
REG(NPU_CLK), REG(NPU_CLK),
REG(NPU_TOP_CLK), REG(NPU_TOP_CLK),
}; };
static struct p100_clk_reg regs_d2d[] = { static struct zhihe_clk_reg regs_d2d[] = {
REG(D2D_CRG_REG), REG(D2D_CRG_REG),
}; };
static struct p100_clk_reg regs_peri[] = { static struct zhihe_clk_reg regs_peri[] = {
REG(PERI0_SYSREG), REG(PERI0_SYSREG),
REG(PERI1_SYSREG), REG(PERI1_SYSREG),
REG(PERI2_SYSREG), REG(PERI2_SYSREG),
@@ -209,7 +261,7 @@ static struct p100_clk_reg regs_peri[] = {
REG(TEE_CRG), REG(TEE_CRG),
}; };
static struct p100_clk_info info_top[] = { static struct zhihe_clk_info info_top[] = {
/* FIXED */ /* FIXED */
FIXED(AON_OSC_CLK_PHY, "aon_osc_clk_phy", "osc_24m", 24000000), FIXED(AON_OSC_CLK_PHY, "aon_osc_clk_phy", "osc_24m", 24000000),
FIXED(AON_OSC_CLK_LOGIC, "aon_osc_clk_logic", "osc_24m", 24000000), FIXED(AON_OSC_CLK_LOGIC, "aon_osc_clk_logic", "osc_24m", 24000000),
@@ -345,13 +397,13 @@ static struct p100_clk_info info_top[] = {
FIXED_FACTOR(TOP_PERI_TIMER_CLK_100M, "peri0_timer_clk_100M", "gmac_pll_foutpostdiv", 1, 10), FIXED_FACTOR(TOP_PERI_TIMER_CLK_100M, "peri0_timer_clk_100M", "gmac_pll_foutpostdiv", 1, 10),
MUX(TOP_PERI_TIMER_CLK_MUX, "peri0_timer_clk", TOP_CRG, 0x20, 15, 1, MUX(TOP_PERI_TIMER_CLK_MUX, "peri0_timer_clk", TOP_CRG, 0x20, 15, 1,
peri0_timer_clk_parents, ARRAY_SIZE(peri0_timer_clk_parents), CLK_SET_RATE_PARENT), peri0_timer_clk_parents, ARRAY_SIZE(peri0_timer_clk_parents), CLK_SET_RATE_PARENT),
MUX(TOP_PERI_I2S_8CH0_SRC_CLK_MUX, "peri2_i2s3_src_clk", TOP_CRG, 0x20, 14, 1, MUX(TOP_PERI_I2S_8CH0_SRC_CLK_MUX, "peri2_i2s3_src_clk", TOP_CRG, 0x28, 21, 1,
peri2_i2s3_src_clk_parents, ARRAY_SIZE(peri2_i2s3_src_clk_parents), CLK_SET_RATE_PARENT), peri2_i2s3_src_clk_parents, ARRAY_SIZE(peri2_i2s3_src_clk_parents), CLK_SET_RATE_PARENT),
MUX(TOP_PERI_I2S_2CH0_SRC_CLK_MUX, "peri1_i2s0_src_clk", TOP_CRG, 0x20, 13, 1, MUX(TOP_PERI_I2S_2CH0_SRC_CLK_MUX, "peri1_i2s0_src_clk", TOP_CRG, 0x20, 13, 1,
peri1_i2s0_src_clk_parents, ARRAY_SIZE(peri1_i2s0_src_clk_parents), CLK_SET_RATE_PARENT), peri1_i2s0_src_clk_parents, ARRAY_SIZE(peri1_i2s0_src_clk_parents), CLK_SET_RATE_PARENT),
MUX(TOP_PERI_I2S_2CH1_SRC_CLK_MUX, "peri2_i2s1_src_clk", TOP_CRG, 0x28, 23, 1, MUX(TOP_PERI_I2S_2CH1_SRC_CLK_MUX, "peri2_i2s1_src_clk", TOP_CRG, 0x20, 14, 1,
peri2_i2s1_src_clk_parents, ARRAY_SIZE(peri2_i2s1_src_clk_parents), CLK_SET_RATE_PARENT), peri2_i2s1_src_clk_parents, ARRAY_SIZE(peri2_i2s1_src_clk_parents), CLK_SET_RATE_PARENT),
MUX(TOP_PERI_I2S_2CH2_SRC_CLK_MUX, "peri2_i2s2_src_clk", TOP_CRG, 0x28, 21, 1, MUX(TOP_PERI_I2S_2CH2_SRC_CLK_MUX, "peri2_i2s2_src_clk", TOP_CRG, 0x28, 23, 1,
peri2_i2s2_src_clk_parents, ARRAY_SIZE(peri2_i2s2_src_clk_parents), CLK_SET_RATE_PARENT), peri2_i2s2_src_clk_parents, ARRAY_SIZE(peri2_i2s2_src_clk_parents), CLK_SET_RATE_PARENT),
DIV(TOP_PERI_QSPI0_SSI_CLK_DIV0, "peri1_qspi_ssi_clk_div0", "video_pll_foutvco", TOP_CRG, 0x20, 8, 4, DIV(TOP_PERI_QSPI0_SSI_CLK_DIV0, "peri1_qspi_ssi_clk_div0", "video_pll_foutvco", TOP_CRG, 0x20, 8, 4,
NO_DIV_EN, MUX_TYPE_DIV, 2, 15), NO_DIV_EN, MUX_TYPE_DIV, 2, 15),
@@ -461,7 +513,7 @@ static struct p100_clk_info info_top[] = {
ddr_pll_clkout_parents, ARRAY_SIZE(ddr_pll_clkout_parents), CLK_SET_RATE_PARENT), ddr_pll_clkout_parents, ARRAY_SIZE(ddr_pll_clkout_parents), CLK_SET_RATE_PARENT),
}; };
static struct p100_clk_info info_gpu[] = { static struct zhihe_clk_info info_gpu[] = {
FIXED_FACTOR(GPU_TOP_SYS_CLK, "gpu_top_sys_clk", "top_cfg_aclk", 1, 1), FIXED_FACTOR(GPU_TOP_SYS_CLK, "gpu_top_sys_clk", "top_cfg_aclk", 1, 1),
FIXED_FACTOR(GPU_PCLK_CDT, "gpu_pclk_cdt", "gpu_top_sys_clk", 1, 2), FIXED_FACTOR(GPU_PCLK_CDT, "gpu_pclk_cdt", "gpu_top_sys_clk", 1, 2),
GATE(SW_PWR_WRAP_DFMU_PCLK_EN, "gpu_top_pclk", "gpu_pclk_cdt", GPU_SS_PWRAP_CLK_EN, 0, 7), GATE(SW_PWR_WRAP_DFMU_PCLK_EN, "gpu_top_pclk", "gpu_pclk_cdt", GPU_SS_PWRAP_CLK_EN, 0, 7),
@@ -469,7 +521,7 @@ static struct p100_clk_info info_gpu[] = {
GATE(SW_PWR_WRAP_GPU_CORE_CLK_EN, "gpu_core_clk", "top_gpu_core_clk", GPU_SS_PWRAP_CLK_EN, 0, 0), GATE(SW_PWR_WRAP_GPU_CORE_CLK_EN, "gpu_core_clk", "top_gpu_core_clk", GPU_SS_PWRAP_CLK_EN, 0, 0),
}; };
static struct p100_clk_info info_pcie[] = { static struct zhihe_clk_info info_pcie[] = {
FIXED_FACTOR(PCIE_SS_APB_CLK, "pcie_ss_apb_clk", "gmac_pll_foutpostdiv", 1, 10), FIXED_FACTOR(PCIE_SS_APB_CLK, "pcie_ss_apb_clk", "gmac_pll_foutpostdiv", 1, 10),
GATE(E16PHY_PCLK_EN, "e16phy_apbs_pclk", "pcie_ss_apb_clk", PCIE_CLK_EN, 0x8, 0), GATE(E16PHY_PCLK_EN, "e16phy_apbs_pclk", "pcie_ss_apb_clk", PCIE_CLK_EN, 0x8, 0),
GATE(SATA_PMALIVE_CLK_EN, "sata_pmalive_clk", "aon_osc_clk_logic", PCIE_CLK_EN, 0x14, 0), GATE(SATA_PMALIVE_CLK_EN, "sata_pmalive_clk", "aon_osc_clk_logic", PCIE_CLK_EN, 0x14, 0),
@@ -486,7 +538,7 @@ static struct p100_clk_info info_pcie[] = {
GATE(PCIE_RP_GEN3X1_PCLK_EN, "pcie_rp_gen3x1_pclk", "pcie_ss_apb_clk", PCIE_CLK_EN, 0x24, 4), GATE(PCIE_RP_GEN3X1_PCLK_EN, "pcie_rp_gen3x1_pclk", "pcie_ss_apb_clk", PCIE_CLK_EN, 0x24, 4),
}; };
static struct p100_clk_info info_usb[] = { static struct zhihe_clk_info info_usb[] = {
GATE(DPTX_I2S_CLK_EN, "usb_dptx_i2s_clk", "audio0_pll_foutvco", USB_CLK_EN, 0x4, 16), GATE(DPTX_I2S_CLK_EN, "usb_dptx_i2s_clk", "audio0_pll_foutvco", USB_CLK_EN, 0x4, 16),
GATE(DPTX_IPI_CLK_EN, "usb_dptx_ipi_clk", "usb_ss_gtc_clk", USB_CLK_EN, 0x4, 12), GATE(DPTX_IPI_CLK_EN, "usb_dptx_ipi_clk", "usb_ss_gtc_clk", USB_CLK_EN, 0x4, 12),
GATE(DPTX_AUX_CLK_EN, "usb_dptx_aux_clk", "clkgen_usb_ss_aux_clk", USB_CLK_EN, 0x4, 8), GATE(DPTX_AUX_CLK_EN, "usb_dptx_aux_clk", "clkgen_usb_ss_aux_clk", USB_CLK_EN, 0x4, 8),
@@ -506,7 +558,7 @@ static struct p100_clk_info info_usb[] = {
GATE(USB_SS_PERI2_CFG_ACLK_EN, "usb_peri2_cfg_aclk", "aon_osc_clk_logic", USB_CLK_EN, 0x20, 4), GATE(USB_SS_PERI2_CFG_ACLK_EN, "usb_peri2_cfg_aclk", "aon_osc_clk_logic", USB_CLK_EN, 0x20, 4),
}; };
static struct p100_clk_info info_vi[] = { static struct zhihe_clk_info info_vi[] = {
GATE(VI_VSE_CLK_EN, "dw200_vseclk", "vi_pre_vse_clk_div", VI_CLK, 0, 29), GATE(VI_VSE_CLK_EN, "dw200_vseclk", "vi_pre_vse_clk_div", VI_CLK, 0, 29),
GATE(VI_VSEOUT_CLK_EN, "dw200_vseout_clk", "vi_pre_vse_clk_div", VI_CLK, 0, 22), GATE(VI_VSEOUT_CLK_EN, "dw200_vseout_clk", "vi_pre_vse_clk_div", VI_CLK, 0, 22),
DIV(VI_PRE_VSE_CLK_DIV_NUM, "vi_pre_vse_clk_div", "gmac_pll_foutpostdiv", VI_CLK, 0xc, 4, 4, DIV(VI_PRE_VSE_CLK_DIV_NUM, "vi_pre_vse_clk_div", "gmac_pll_foutpostdiv", VI_CLK, 0xc, 4, 4,
@@ -532,8 +584,8 @@ static struct p100_clk_info info_vi[] = {
GATE(VI_MIPI0CSI0_PCLK_EN, "mipi0_csi0_pclk", "vi_pclk", VI_CLK, 0, 0), GATE(VI_MIPI0CSI0_PCLK_EN, "mipi0_csi0_pclk", "vi_pclk", VI_CLK, 0, 0),
GATE(VI_MIPI0CSI1_PCLK_EN, "mipi0_csi1_pclk", "vi_pclk", VI_CLK, 0, 1), GATE(VI_MIPI0CSI1_PCLK_EN, "mipi0_csi1_pclk", "vi_pclk", VI_CLK, 0, 1),
GATE(VI_MIPI1CSI0_PCLK_EN, "mipi1_csi0_pclk", "vi_pclk", VI_CLK, 0, 6), GATE(VI_MIPI1CSI0_PCLK_EN, "mipi1_csi0_pclk", "vi_pclk", VI_CLK, 0, 6),
GATE(VI_MIPI1CSI1_PCLK_EN, "mipi1_csi1_pclk", "vi_pclk", VI_CLK, 0, 12), GATE(VI_MIPI1CSI1_PCLK_EN, "mipi1_csi1_pclk", "vi_pclk", VI_CLK, 0, 7),
GATE(VI_VIPRE_PCLK_EN, "vipre_pclk", "vi_pclk", VI_CLK, 0, 7), GATE(VI_VIPRE_PCLK_EN, "vipre_pclk", "vi_pclk", VI_CLK, 0, 12),
GATE(VI_DFMU_PCLK_EN, "dfmu_pclk", "vi_pclk", VI_CLK, 0x4, 0), GATE(VI_DFMU_PCLK_EN, "dfmu_pclk", "vi_pclk", VI_CLK, 0x4, 0),
GATE(VI_MIPI0CSI0_FPCLK_EN, "mipi0_csi0_fpclk", "vi_pclk", VI_CLK, 0x4, 8), GATE(VI_MIPI0CSI0_FPCLK_EN, "mipi0_csi0_fpclk", "vi_pclk", VI_CLK, 0x4, 8),
GATE(VI_MIPI0CSI1_FPCLK_EN, "mipi0_csi1_fpclk", "vi_pclk", VI_CLK, 0x4, 9), GATE(VI_MIPI0CSI1_FPCLK_EN, "mipi0_csi1_fpclk", "vi_pclk", VI_CLK, 0x4, 9),
@@ -564,10 +616,10 @@ static struct p100_clk_info info_vi[] = {
25, MUX_TYPE_DIV, 3, 15), 25, MUX_TYPE_DIV, 3, 15),
MUX(VI_MIPI1_PIX_REF_SWITCH_SEL, "vi_preocc_mipi1_ifclk_mux", VI_CLK, 0x8, 21, 1, MUX(VI_MIPI1_PIX_REF_SWITCH_SEL, "vi_preocc_mipi1_ifclk_mux", VI_CLK, 0x8, 21, 1,
vi_preocc_mipi1_ifclk_mux_parents, ARRAY_SIZE(vi_preocc_mipi1_ifclk_mux_parents), CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), vi_preocc_mipi1_ifclk_mux_parents, ARRAY_SIZE(vi_preocc_mipi1_ifclk_mux_parents), CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
GATE(VI_MIPI1B_CFGCLK_EN, "mipi1_csi1_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 9), GATE(VI_MIPI1B_CFGCLK_EN, "mipi1_csi0_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 9),
GATE(VI_MIPI1A_CFGCLK_EN, "mipi1_csi0_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 8), GATE(VI_MIPI1A_CFGCLK_EN, "mipi1_csi1_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 8),
GATE(VI_MIPI0B_CFGCLK_EN, "mipi0_csi1_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 3), GATE(VI_MIPI0B_CFGCLK_EN, "mipi0_csi0_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 3),
GATE(VI_MIPI0A_CFGCLK_EN, "mipi0_csi0_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 2), GATE(VI_MIPI0A_CFGCLK_EN, "mipi0_csi1_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 2),
GATE(VI_DFMU_ACLK_EN, "dfmu_aclk", "vi_preocc_aclk", VI_CLK, 0x4, 1), GATE(VI_DFMU_ACLK_EN, "dfmu_aclk", "vi_preocc_aclk", VI_CLK, 0x4, 1),
GATE(VI_PTW_ACLK_EN, "dfmu_ptw_aclk", "iommu_ptw_aclk", VI_CLK, 0x4, 2), GATE(VI_PTW_ACLK_EN, "dfmu_ptw_aclk", "iommu_ptw_aclk", VI_CLK, 0x4, 2),
GATE(VI_ARB_PCLK_EN, "vi_arb_pclk", "top_cfg_aclk", VI_CLK, 0x4, 3), GATE(VI_ARB_PCLK_EN, "vi_arb_pclk", "top_cfg_aclk", VI_CLK, 0x4, 3),
@@ -578,9 +630,20 @@ static struct p100_clk_info info_vi[] = {
GATE(VI_FENCE_ACLK_EN, "vi_fence_aclk", "top_cfg_aclk", VI_CLK, 0x4, 12), GATE(VI_FENCE_ACLK_EN, "vi_fence_aclk", "top_cfg_aclk", VI_CLK, 0x4, 12),
GATE(VI_REC_PCLK_EN, "vi_rec_pclk", "top_cfg_aclk", VI_CLK, 0x4, 13), GATE(VI_REC_PCLK_EN, "vi_rec_pclk", "top_cfg_aclk", VI_CLK, 0x4, 13),
GATE(VI_REC_ACLK_EN, "vi_rec_aclk", "top_cfg_aclk", VI_CLK, 0x4, 14), GATE(VI_REC_ACLK_EN, "vi_rec_aclk", "top_cfg_aclk", VI_CLK, 0x4, 14),
GATE(VI_MISC_CTRL_H0CLK_CLK_EN, "vi_misc_ctrl_h0clk", "top_cfg_aclk", VI_MISC_CTRL, 0x0, 1),
GATE(VI_MISC_CTRL_H1CLK_CLK_EN, "vi_misc_ctrl_h1clk", "top_cfg_aclk", VI_MISC_CTRL, 0x0, 2),
GATE(VI_MISC_CTRL_ISP_ACLK_CLK_EN, "vi_misc_ctrl_isp_aclk", "top_cfg_aclk", VI_MISC_CTRL, 0x0, 3),
GATE(VI_MISC_CTRL_ISP_SCLK_CLK0_EN, "vi_misc_ctrl_isp_sclk0", "top_cfg_aclk", VI_MISC_CTRL, 0x0, 4),
GATE(VI_MISC_CTRL_ISP_SCLK_CLK1_EN, "vi_misc_ctrl_isp_sclk1", "top_cfg_aclk", VI_MISC_CTRL, 0x0, 5),
GATE(VI_MISC_CTRL_ISP_SCLK_CLK2_EN, "vi_misc_ctrl_isp_sclk2", "top_cfg_aclk", VI_MISC_CTRL, 0x0, 6),
GATE(VI_MISC_CTRL_ISP_SCLK_CLK3_EN, "vi_misc_ctrl_isp_sclk3", "top_cfg_aclk", VI_MISC_CTRL, 0x0, 7),
GATE(VI_MISC_CTRL_ISP_CORE_CLK_EN, "vi_misc_ctrl_isp_core_clk", "isp_core_clk", VI_MISC_CTRL, 0x0, 8),
GATE(VI_MISC_CTRL_ISP_FLEXA_CLK_EN, "vi_misc_ctrl_isp_flexa_clk", "isp_core_clk", VI_MISC_CTRL, 0x0, 9),
GATE(VI_MISC_CTRL_ISP_MCM_CLK_EN, "vi_misc_ctrl_isp_mcm_clk", "isp_core_clk", VI_MISC_CTRL, 0x0, 10),
GATE(VI_MISC_CTRL_BUS_CLK_GT_DISABLE, "vi_misc_ctrl_bus_clk", "isp_core_clk", VI_MISC_CTRL, 0x0, 11),
}; };
static struct p100_clk_info info_vp[] = { static struct zhihe_clk_info info_vp[] = {
GATE(VP_DECOMP_EXTPCLK_EN, "vp_decomp_extpclk", "top_cfg_aclk", VP_CLK, 0, 23), GATE(VP_DECOMP_EXTPCLK_EN, "vp_decomp_extpclk", "top_cfg_aclk", VP_CLK, 0, 23),
GATE(VP_COMP_EXTPCLK_EN, "vp_comp_extpclk", "top_cfg_aclk", VP_CLK, 0, 22), GATE(VP_COMP_EXTPCLK_EN, "vp_comp_extpclk", "top_cfg_aclk", VP_CLK, 0, 22),
GATE(VP_VENC_RS_ACLK_EN, "vp_venc_rs_aclk", "vp_aclk", VP_CLK, 0, 21), GATE(VP_VENC_RS_ACLK_EN, "vp_venc_rs_aclk", "vp_aclk", VP_CLK, 0, 21),
@@ -611,7 +674,7 @@ static struct p100_clk_info info_vp[] = {
12, MUX_TYPE_DIV, 2, 15), 12, MUX_TYPE_DIV, 2, 15),
}; };
static struct p100_clk_info info_vo[] = { static struct zhihe_clk_info info_vo[] = {
GATE(VO_X2H1_CLK_EN, "vo_x2h1_clk", "top_cfg_aclk", VO_CLK, 0, 24), GATE(VO_X2H1_CLK_EN, "vo_x2h1_clk", "top_cfg_aclk", VO_CLK, 0, 24),
GATE(VO_X2H0_CLK_EN, "vo_x2h0_clk", "top_cfg_aclk", VO_CLK, 0, 23), GATE(VO_X2H0_CLK_EN, "vo_x2h0_clk", "top_cfg_aclk", VO_CLK, 0, 23),
GATE(VO_PTW_ACLK_EN, "vo_ptw_aclk", "iommu_ptw_aclk", VO_CLK, 0, 22), GATE(VO_PTW_ACLK_EN, "vo_ptw_aclk", "iommu_ptw_aclk", VO_CLK, 0, 22),
@@ -658,7 +721,7 @@ static struct p100_clk_info info_vo[] = {
vo_dptx_pixclk_mux_parents, ARRAY_SIZE(vo_dptx_pixclk_mux_parents), CLK_SET_RATE_PARENT|CLK_SET_RATE_NO_REPARENT), vo_dptx_pixclk_mux_parents, ARRAY_SIZE(vo_dptx_pixclk_mux_parents), CLK_SET_RATE_PARENT|CLK_SET_RATE_NO_REPARENT),
}; };
static struct p100_clk_info info_npu[] = { static struct zhihe_clk_info info_npu[] = {
GATE(SW_SEMA_PCLK_EN, "npu_clkgen_sema_pclk", "top_cfg_aclk", NPU_CLK, 0, 23), GATE(SW_SEMA_PCLK_EN, "npu_clkgen_sema_pclk", "top_cfg_aclk", NPU_CLK, 0, 23),
GATE(SW_SEMA_ACLK_EN, "npu_clkgen_sema_aclk", "npu_aclk", NPU_CLK, 0, 22), GATE(SW_SEMA_ACLK_EN, "npu_clkgen_sema_aclk", "npu_aclk", NPU_CLK, 0, 22),
GATE(SW_NPU_X2P_ACLK_EN, "npu_x2p_aclk", "top_cfg_aclk", NPU_CLK, 0, 21), GATE(SW_NPU_X2P_ACLK_EN, "npu_x2p_aclk", "top_cfg_aclk", NPU_CLK, 0, 21),
@@ -668,12 +731,12 @@ static struct p100_clk_info info_npu[] = {
GATE(SW_NPU_IP_ACLK_EN, "npu_ip_aclk", "npu_aclk", NPU_CLK, 0, 10), GATE(SW_NPU_IP_ACLK_EN, "npu_ip_aclk", "npu_aclk", NPU_CLK, 0, 10),
}; };
static struct p100_clk_info info_d2d[] = { static struct zhihe_clk_info info_d2d[] = {
GATE(D2D_SS_CTRL0_CLK_EN, "d2d_ss_ctrl0_cg_aclk", "top_d2d_aclk", D2D_CRG_REG, 0, 1), GATE(D2D_SS_CTRL0_CLK_EN, "d2d_ss_ctrl0_cg_aclk", "top_d2d_aclk", D2D_CRG_REG, 0, 1),
GATE(D2D_SS_CTRL1_CLK_EN, "d2d_ss_ctrl1_cg_aclk", "top_d2d_aclk", D2D_CRG_REG, 0, 0), GATE(D2D_SS_CTRL1_CLK_EN, "d2d_ss_ctrl1_cg_aclk", "top_d2d_aclk", D2D_CRG_REG, 0, 0),
}; };
static struct p100_clk_info info_peri[] = { static struct zhihe_clk_info info_peri[] = {
/* PERI0 SS */ /* PERI0 SS */
GATE(PERI0_MBOX1_PCLK_EN, "peri0_mbox1_pclk", "top_cfg_aclk", PERI0_SYSREG, 0, 6), GATE(PERI0_MBOX1_PCLK_EN, "peri0_mbox1_pclk", "top_cfg_aclk", PERI0_SYSREG, 0, 6),
GATE(PERI0_MBOX0_PCLK_EN, "peri0_mbox0_pclk", "top_cfg_aclk", PERI0_SYSREG, 0, 5), GATE(PERI0_MBOX0_PCLK_EN, "peri0_mbox0_pclk", "top_cfg_aclk", PERI0_SYSREG, 0, 5),
@@ -828,112 +891,203 @@ static struct p100_clk_info info_peri[] = {
GATE(TEE_KEYRAM_CLKEN, "tee_keyram_clk", "tee_pclk", TEE_CRG, 0, 0), GATE(TEE_KEYRAM_CLKEN, "tee_keyram_clk", "tee_pclk", TEE_CRG, 0, 0),
}; };
static struct p100_clk_subsys top_clk = CLK_SUBSYS("top clk", regs_top, ARRAY_SIZE(regs_top), static struct zhihe_clk_subsys top_clk = CLK_SUBSYS("top clk", regs_top, ARRAY_SIZE(regs_top),
info_top, ARRAY_SIZE(info_top), plls_top, ARRAY_SIZE(plls_top), false); info_top, ARRAY_SIZE(info_top), plls_top, ARRAY_SIZE(plls_top), false, 0);
static struct p100_clk_subsys top_clk_fpga = CLK_SUBSYS("top clk fpga", regs_top, ARRAY_SIZE(regs_top), static struct zhihe_clk_subsys top_clk_fpga = CLK_SUBSYS("top clk fpga", regs_top, ARRAY_SIZE(regs_top),
info_top, ARRAY_SIZE(info_top), plls_top, ARRAY_SIZE(plls_top), true); info_top, ARRAY_SIZE(info_top), plls_top, ARRAY_SIZE(plls_top), true, 0);
static struct p100_clk_subsys gpu_clk = CLK_SUBSYS("gpu clk", regs_gpu, ARRAY_SIZE(regs_gpu), static struct zhihe_clk_subsys gpu_clk = CLK_SUBSYS("gpu clk", regs_gpu, ARRAY_SIZE(regs_gpu),
info_gpu, ARRAY_SIZE(info_gpu), NULL, 0, false); info_gpu, ARRAY_SIZE(info_gpu), NULL, 0, false, 0);
static struct p100_clk_subsys pcie_clk = CLK_SUBSYS("pcie clk", regs_pcie, ARRAY_SIZE(regs_pcie), static struct zhihe_clk_subsys pcie_clk = CLK_SUBSYS("pcie clk", regs_pcie, ARRAY_SIZE(regs_pcie),
info_pcie, ARRAY_SIZE(info_pcie), NULL, 0, false); info_pcie, ARRAY_SIZE(info_pcie), NULL, 0, false, 0);
static struct p100_clk_subsys usb_clk = CLK_SUBSYS("usb clk", regs_usb, ARRAY_SIZE(regs_usb), static struct zhihe_clk_subsys usb_clk = CLK_SUBSYS("usb clk", regs_usb, ARRAY_SIZE(regs_usb),
info_usb, ARRAY_SIZE(info_usb), NULL, 0, false); info_usb, ARRAY_SIZE(info_usb), NULL, 0, false, 0);
static struct p100_clk_subsys vi_clk = CLK_SUBSYS("vi clk", regs_vi, ARRAY_SIZE(regs_vi), static struct zhihe_clk_subsys vi_clk = CLK_SUBSYS("vi clk", regs_vi, ARRAY_SIZE(regs_vi),
info_vi, ARRAY_SIZE(info_vi), NULL, 0, false); info_vi, ARRAY_SIZE(info_vi), NULL, 0, false, 0);
static struct p100_clk_subsys vp_clk = CLK_SUBSYS("vp clk", regs_vp, ARRAY_SIZE(regs_vp), static struct zhihe_clk_subsys vp_clk = CLK_SUBSYS("vp clk", regs_vp, ARRAY_SIZE(regs_vp),
info_vp, ARRAY_SIZE(info_vp), NULL, 0, false); info_vp, ARRAY_SIZE(info_vp), NULL, 0, false, 0);
static struct p100_clk_subsys vo_clk = CLK_SUBSYS("vo clk", regs_vo, ARRAY_SIZE(regs_vo), static struct zhihe_clk_subsys vo_clk = CLK_SUBSYS("vo clk", regs_vo, ARRAY_SIZE(regs_vo),
info_vo, ARRAY_SIZE(info_vo), NULL, 0, false); info_vo, ARRAY_SIZE(info_vo), NULL, 0, false, 0);
static struct p100_clk_subsys npu_clk = CLK_SUBSYS("npu clk", regs_npu, ARRAY_SIZE(regs_npu), static struct zhihe_clk_subsys npu_clk = CLK_SUBSYS("npu clk", regs_npu, ARRAY_SIZE(regs_npu),
info_npu, ARRAY_SIZE(info_npu), NULL, 0, false); info_npu, ARRAY_SIZE(info_npu), NULL, 0, false, 0);
static struct p100_clk_subsys d2d_clk = CLK_SUBSYS("d2d clk", regs_d2d, ARRAY_SIZE(regs_d2d), static struct zhihe_clk_subsys d2d_clk = CLK_SUBSYS("d2d clk", regs_d2d, ARRAY_SIZE(regs_d2d),
info_d2d, ARRAY_SIZE(info_d2d), NULL, 0, false); info_d2d, ARRAY_SIZE(info_d2d), NULL, 0, false, 0);
static struct p100_clk_subsys peri_clk = CLK_SUBSYS("peri clk", regs_peri, ARRAY_SIZE(regs_peri), static struct zhihe_clk_subsys peri_clk = CLK_SUBSYS("peri clk", regs_peri, ARRAY_SIZE(regs_peri),
info_peri, ARRAY_SIZE(info_peri), NULL, 0, false); info_peri, ARRAY_SIZE(info_peri), NULL, 0, false, 0);
static struct zhihe_clk_subsys top_clk_die1 = CLK_SUBSYS("top clk", regs_top, ARRAY_SIZE(regs_top),
info_top, ARRAY_SIZE(info_top), plls_top, ARRAY_SIZE(plls_top), false, 1);
static struct zhihe_clk_subsys gpu_clk_die1 = CLK_SUBSYS("gpu clk", regs_gpu, ARRAY_SIZE(regs_gpu),
info_gpu, ARRAY_SIZE(info_gpu), NULL, 0, false, 1);
static struct zhihe_clk_subsys pcie_clk_die1 = CLK_SUBSYS("pcie clk", regs_pcie, ARRAY_SIZE(regs_pcie),
info_pcie, ARRAY_SIZE(info_pcie), NULL, 0, false, 1);
static struct zhihe_clk_subsys usb_clk_die1 = CLK_SUBSYS("usb clk", regs_usb, ARRAY_SIZE(regs_usb),
info_usb, ARRAY_SIZE(info_usb), NULL, 0, false, 1);
static struct zhihe_clk_subsys vi_clk_die1 = CLK_SUBSYS("vi clk", regs_vi, ARRAY_SIZE(regs_vi),
info_vi, ARRAY_SIZE(info_vi), NULL, 0, false, 1);
static struct zhihe_clk_subsys vp_clk_die1 = CLK_SUBSYS("vp clk", regs_vp, ARRAY_SIZE(regs_vp),
info_vp, ARRAY_SIZE(info_vp), NULL, 0, false, 1);
static struct zhihe_clk_subsys vo_clk_die1 = CLK_SUBSYS("vo clk", regs_vo, ARRAY_SIZE(regs_vo),
info_vo, ARRAY_SIZE(info_vo), NULL, 0, false, 1);
static struct zhihe_clk_subsys npu_clk_die1 = CLK_SUBSYS("npu clk", regs_npu, ARRAY_SIZE(regs_npu),
info_npu, ARRAY_SIZE(info_npu), NULL, 0, false, 1);
static struct zhihe_clk_subsys d2d_clk_die1 = CLK_SUBSYS("d2d clk", regs_d2d, ARRAY_SIZE(regs_d2d),
info_d2d, ARRAY_SIZE(info_d2d), NULL, 0, false, 1);
static struct zhihe_clk_subsys peri_clk_die1 = CLK_SUBSYS("peri clk", regs_peri, ARRAY_SIZE(regs_peri),
info_peri, ARRAY_SIZE(info_peri), NULL, 0, false, 1);
static struct zhihe_clk_subsys top_clk_die2 = CLK_SUBSYS("top clk", regs_top, ARRAY_SIZE(regs_top),
info_top, ARRAY_SIZE(info_top), plls_top, ARRAY_SIZE(plls_top), false, 2);
static struct zhihe_clk_subsys gpu_clk_die2 = CLK_SUBSYS("gpu clk", regs_gpu, ARRAY_SIZE(regs_gpu),
info_gpu, ARRAY_SIZE(info_gpu), NULL, 0, false, 2);
static struct zhihe_clk_subsys pcie_clk_die2 = CLK_SUBSYS("pcie clk", regs_pcie, ARRAY_SIZE(regs_pcie),
info_pcie, ARRAY_SIZE(info_pcie), NULL, 0, false, 2);
static struct zhihe_clk_subsys usb_clk_die2 = CLK_SUBSYS("usb clk", regs_usb, ARRAY_SIZE(regs_usb),
info_usb, ARRAY_SIZE(info_usb), NULL, 0, false, 2);
static struct zhihe_clk_subsys vi_clk_die2 = CLK_SUBSYS("vi clk", regs_vi, ARRAY_SIZE(regs_vi),
info_vi, ARRAY_SIZE(info_vi), NULL, 0, false, 2);
static struct zhihe_clk_subsys vp_clk_die2 = CLK_SUBSYS("vp clk", regs_vp, ARRAY_SIZE(regs_vp),
info_vp, ARRAY_SIZE(info_vp), NULL, 0, false, 2);
static struct zhihe_clk_subsys vo_clk_die2 = CLK_SUBSYS("vo clk", regs_vo, ARRAY_SIZE(regs_vo),
info_vo, ARRAY_SIZE(info_vo), NULL, 0, false, 2);
static struct zhihe_clk_subsys npu_clk_die2 = CLK_SUBSYS("npu clk", regs_npu, ARRAY_SIZE(regs_npu),
info_npu, ARRAY_SIZE(info_npu), NULL, 0, false, 2);
static struct zhihe_clk_subsys d2d_clk_die2 = CLK_SUBSYS("d2d clk", regs_d2d, ARRAY_SIZE(regs_d2d),
info_d2d, ARRAY_SIZE(info_d2d), NULL, 0, false, 2);
static struct zhihe_clk_subsys peri_clk_die2 = CLK_SUBSYS("peri clk", regs_peri, ARRAY_SIZE(regs_peri),
info_peri, ARRAY_SIZE(info_peri), NULL, 0, false, 2);
static struct zhihe_clk_subsys top_clk_die3 = CLK_SUBSYS("top clk", regs_top, ARRAY_SIZE(regs_top),
info_top, ARRAY_SIZE(info_top), plls_top, ARRAY_SIZE(plls_top), false, 3);
static struct zhihe_clk_subsys gpu_clk_die3 = CLK_SUBSYS("gpu clk", regs_gpu, ARRAY_SIZE(regs_gpu),
info_gpu, ARRAY_SIZE(info_gpu), NULL, 0, false, 3);
static struct zhihe_clk_subsys pcie_clk_die3 = CLK_SUBSYS("pcie clk", regs_pcie, ARRAY_SIZE(regs_pcie),
info_pcie, ARRAY_SIZE(info_pcie), NULL, 0, false, 3);
static struct zhihe_clk_subsys usb_clk_die3 = CLK_SUBSYS("usb clk", regs_usb, ARRAY_SIZE(regs_usb),
info_usb, ARRAY_SIZE(info_usb), NULL, 0, false, 3);
static struct zhihe_clk_subsys vi_clk_die3 = CLK_SUBSYS("vi clk", regs_vi, ARRAY_SIZE(regs_vi),
info_vi, ARRAY_SIZE(info_vi), NULL, 0, false, 3);
static struct zhihe_clk_subsys vp_clk_die3 = CLK_SUBSYS("vp clk", regs_vp, ARRAY_SIZE(regs_vp),
info_vp, ARRAY_SIZE(info_vp), NULL, 0, false, 3);
static struct zhihe_clk_subsys vo_clk_die3 = CLK_SUBSYS("vo clk", regs_vo, ARRAY_SIZE(regs_vo),
info_vo, ARRAY_SIZE(info_vo), NULL, 0, false, 3);
static struct zhihe_clk_subsys npu_clk_die3 = CLK_SUBSYS("npu clk", regs_npu, ARRAY_SIZE(regs_npu),
info_npu, ARRAY_SIZE(info_npu), NULL, 0, false, 3);
static struct zhihe_clk_subsys d2d_clk_die3 = CLK_SUBSYS("d2d clk", regs_d2d, ARRAY_SIZE(regs_d2d),
info_d2d, ARRAY_SIZE(info_d2d), NULL, 0, false, 3);
static struct zhihe_clk_subsys peri_clk_die3 = CLK_SUBSYS("peri clk", regs_peri, ARRAY_SIZE(regs_peri),
info_peri, ARRAY_SIZE(info_peri), NULL, 0, false, 3);
static struct clk_onecell_data clk_data; static int a210_clocks_probe(struct platform_device *pdev)
static int p100_clocks_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct p100_clk_subsys *priv; struct zhihe_clk_subsys *priv;
int ret; int ret;
if (clk_data.clks == NULL) { struct clk_onecell_data *clk_data = devm_kzalloc(dev, sizeof(*clk_data), GFP_KERNEL);
clk_data.clks = devm_kcalloc(dev, CLK_END, sizeof(*clk_data.clks), if (!clk_data) {
GFP_KERNEL); ret = -ENOMEM;
if (!clk_data.clks) goto fail;
return -ENOMEM;
clk_data.clk_num = CLK_END;
for (int i = 0; i < CLK_END; i++)
clk_data.clks[i] = ERR_PTR(-ENOENT);
} }
priv = (struct p100_clk_subsys *)device_get_match_data(&pdev->dev); clk_data->clks = devm_kcalloc(dev, CLK_END, sizeof(*clk_data->clks),
GFP_KERNEL);
if (!clk_data->clks) {
ret = -ENOMEM;
goto fail;
}
clk_data->clk_num = CLK_END;
for (int i = 0; i < CLK_END; i++)
clk_data->clks[i] = ERR_PTR(-ENOENT);
priv = (struct zhihe_clk_subsys *)device_get_match_data(&pdev->dev);
if (priv->is_fpga) { if (priv->is_fpga) {
zhihe_p100_clk_fake_pll_fixed_ops(); zhihe_clk_fake_pll_fixed_ops();
} }
priv->clk_data = &clk_data;
priv->clk_data = clk_data;
dev_set_drvdata(dev, priv); dev_set_drvdata(dev, priv);
ret = p100_parse_regbase(pdev); ret = zhihe_parse_regbase(pdev);
if (ret) { if (ret) {
dev_err(dev, "fail to parse reg base"); dev_err(dev, "fail to parse reg base");
return ret; ret = -EINVAL;
goto fail;
} }
p100_register_clock(pdev); zhihe_register_clock(pdev);
ret = of_clk_add_provider(np, of_clk_src_onecell_get, priv->clk_data); ret = of_clk_add_provider(np, of_clk_src_onecell_get, priv->clk_data);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to register clks for p100\n"); dev_err(dev, "failed to register clks for a210\n");
goto unregister_clks; goto unregister_clks;
} }
ret = zhihe_clk_of_bulk_init(dev, priv->clk_data->clks); dev_info(dev, "succeed to register a210 %s driver on die%d\n", priv->name, priv->die_num);
if (ret < 0) {
dev_err(dev, "failed to init clks for p100\n");
goto unregister_clks;
}
dev_info(dev, "succeed to register p100 %s driver\n", priv->name);
return 0; return 0;
unregister_clks: unregister_clks:
zhihe_unregister_clocks(priv->clk_data->clks, CLK_END); zhihe_unregister_clocks(priv->clk_data->clks, CLK_END);
fail:
return ret; return ret;
} }
static const struct of_device_id p100_clk_of_match[] = { static const struct of_device_id a210_clk_of_match[] = {
{ .compatible = "zhihe,p100-clk", .data = (const void *)&top_clk}, { .compatible = "zhihe,a210-clk", .data = (const void *)&top_clk},
{ .compatible = "zhihe,p100-clk-emu", .data = (const void *)&top_clk_fpga}, { .compatible = "zhihe,a210-gpu-clk", .data = (const void *)&gpu_clk},
{ .compatible = "zhihe,p100-clk-haps", .data = (const void *)&top_clk_fpga}, { .compatible = "zhihe,a210-pcie-clk", .data = (const void *)&pcie_clk},
{ .compatible = "zhihe,p100-gpu-clk", .data = (const void *)&gpu_clk}, { .compatible = "zhihe,a210-usb-clk", .data = (const void *)&usb_clk},
{ .compatible = "zhihe,p100-pcie-clk", .data = (const void *)&pcie_clk}, { .compatible = "zhihe,a210-vi-clk", .data = (const void *)&vi_clk},
{ .compatible = "zhihe,p100-usb-clk", .data = (const void *)&usb_clk}, { .compatible = "zhihe,a210-vp-clk", .data = (const void *)&vp_clk},
{ .compatible = "zhihe,p100-vi-clk", .data = (const void *)&vi_clk}, { .compatible = "zhihe,a210-vo-clk", .data = (const void *)&vo_clk},
{ .compatible = "zhihe,p100-vp-clk", .data = (const void *)&vp_clk}, { .compatible = "zhihe,a210-npu-clk", .data = (const void *)&npu_clk},
{ .compatible = "zhihe,p100-vo-clk", .data = (const void *)&vo_clk}, { .compatible = "zhihe,a210-d2d-clk", .data = (const void *)&d2d_clk},
{ .compatible = "zhihe,p100-npu-clk", .data = (const void *)&npu_clk}, { .compatible = "zhihe,a210-peri-clk", .data = (const void *)&peri_clk},
{ .compatible = "zhihe,p100-d2d-clk", .data = (const void *)&d2d_clk}, { .compatible = "zhihe,a210-clk-emu", .data = (const void *)&top_clk_fpga},
{ .compatible = "zhihe,p100-peri-clk", .data = (const void *)&peri_clk}, { .compatible = "zhihe,a210-clk-haps", .data = (const void *)&top_clk_fpga},
{ .compatible = "zhihe,a210-clk-die1", .data = (const void *)&top_clk_die1},
{ .compatible = "zhihe,a210-gpu-clk-die1", .data = (const void *)&gpu_clk_die1},
{ .compatible = "zhihe,a210-pcie-clk-die1", .data = (const void *)&pcie_clk_die1},
{ .compatible = "zhihe,a210-usb-clk-die1", .data = (const void *)&usb_clk_die1},
{ .compatible = "zhihe,a210-vi-clk-die1", .data = (const void *)&vi_clk_die1},
{ .compatible = "zhihe,a210-vp-clk-die1", .data = (const void *)&vp_clk_die1},
{ .compatible = "zhihe,a210-vo-clk-die1", .data = (const void *)&vo_clk_die1},
{ .compatible = "zhihe,a210-npu-clk-die1", .data = (const void *)&npu_clk_die1},
{ .compatible = "zhihe,a210-d2d-clk-die1", .data = (const void *)&d2d_clk_die1},
{ .compatible = "zhihe,a210-peri-clk-die1", .data = (const void *)&peri_clk_die1},
{ .compatible = "zhihe,a210-clk-die2", .data = (const void *)&top_clk_die2},
{ .compatible = "zhihe,a210-gpu-clk-die2", .data = (const void *)&gpu_clk_die2},
{ .compatible = "zhihe,a210-pcie-clk-die2", .data = (const void *)&pcie_clk_die2},
{ .compatible = "zhihe,a210-usb-clk-die2", .data = (const void *)&usb_clk_die2},
{ .compatible = "zhihe,a210-vi-clk-die2", .data = (const void *)&vi_clk_die2},
{ .compatible = "zhihe,a210-vp-clk-die2", .data = (const void *)&vp_clk_die2},
{ .compatible = "zhihe,a210-vo-clk-die2", .data = (const void *)&vo_clk_die2},
{ .compatible = "zhihe,a210-npu-clk-die2", .data = (const void *)&npu_clk_die2},
{ .compatible = "zhihe,a210-d2d-clk-die2", .data = (const void *)&d2d_clk_die2},
{ .compatible = "zhihe,a210-peri-clk-die2", .data = (const void *)&peri_clk_die2},
{ .compatible = "zhihe,a210-clk-die3", .data = (const void *)&top_clk_die3},
{ .compatible = "zhihe,a210-gpu-clk-die3", .data = (const void *)&gpu_clk_die3},
{ .compatible = "zhihe,a210-pcie-clk-die3", .data = (const void *)&pcie_clk_die3},
{ .compatible = "zhihe,a210-usb-clk-die3", .data = (const void *)&usb_clk_die3},
{ .compatible = "zhihe,a210-vi-clk-die3", .data = (const void *)&vi_clk_die3},
{ .compatible = "zhihe,a210-vp-clk-die3", .data = (const void *)&vp_clk_die3},
{ .compatible = "zhihe,a210-vo-clk-die3", .data = (const void *)&vo_clk_die3},
{ .compatible = "zhihe,a210-npu-clk-die3", .data = (const void *)&npu_clk_die3},
{ .compatible = "zhihe,a210-d2d-clk-die3", .data = (const void *)&d2d_clk_die3},
{ .compatible = "zhihe,a210-peri-clk-die3", .data = (const void *)&peri_clk_die3},
{ /* Sentinel */ }, { /* Sentinel */ },
}; };
MODULE_DEVICE_TABLE(of, p100_clk_of_match); MODULE_DEVICE_TABLE(of, a210_clk_of_match);
static struct platform_driver p100_clk_driver = { static struct platform_driver a210_clk_driver = {
.probe = p100_clocks_probe, .probe = a210_clocks_probe,
.driver = { .driver = {
.name = "p100-clk", .name = "a210-clk",
.of_match_table = of_match_ptr(p100_clk_of_match), .of_match_table = of_match_ptr(a210_clk_of_match),
}, },
}; };
module_platform_driver(p100_clk_driver); module_platform_driver(a210_clk_driver);
MODULE_AUTHOR("dong.yan <yand@zhcomputing.com>"); MODULE_AUTHOR("dong.yan <yand@zhihecomputing.com>");
MODULE_DESCRIPTION("Zhihe P100 clock driver"); MODULE_DESCRIPTION("Zhihe A210 clock driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");

View File

@@ -15,32 +15,10 @@
#include "clk-helper.h" #include "clk-helper.h"
#define P100_PLL_CFG0 0x0
#define P100_PLL_CFG1 0x04
#define P100_PLL_CFG2 0x8
#define P100_POSTDIV2_SHIFT 24
#define P100_POSTDIV2_MASK GENMASK(26, 24)
#define P100_POSTDIV1_SHIFT 20
#define P100_POSTDIV1_MASK GENMASK(22, 20)
#define P100_FBDIV_SHIFT 8
#define P100_FBDIV_MASK GENMASK(19, 8)
#define P100_REFDIV_SHIFT 0
#define P100_REFDIV_MASK GENMASK(5, 0)
#define P100_BYPASS_MASK BIT(30)
#define P100_RST_MASK BIT(29)
#define P100_DSMPD_MASK BIT(24)
#define P100_DACPD_MASK BIT(25)
#define P100_FRAC_MASK GENMASK(23, 0)
#define P100_FRAC_SHIFT 0
#define P100_FRAC_DIV BIT(24)
#define LOCK_TIMEOUT_US 10000
#define div_mask(d) ((1 << (d->width)) - 1) #define div_mask(d) ((1 << (d->width)) - 1)
DEFINE_SPINLOCK(zhihe_p100_clk_lock); DEFINE_SPINLOCK(zhihe_clk_lock);
#define to_clk_p100pll(_hw) container_of(_hw, struct clk_p100pll, hw)
void zhihe_unregister_clocks(struct clk *clks[], unsigned int count) void zhihe_unregister_clocks(struct clk *clks[], unsigned int count)
{ {
@@ -50,296 +28,6 @@ void zhihe_unregister_clocks(struct clk *clks[], unsigned int count)
clk_unregister(clks[i]); clk_unregister(clks[i]);
} }
static int clk_p100_pll_wait_lock(struct clk_p100pll *pll)
{
u32 val;
return readl_poll_timeout(pll->base + pll->pll_sts_off, val,
val & pll->pll_lock_bit, 0,
LOCK_TIMEOUT_US);
}
static int clk_p100_pll_prepare(struct clk_hw *hw)
{
struct clk_p100pll *pll = to_clk_p100pll(hw);
void __iomem *cfg1_off;
u32 val;
int ret;
cfg1_off = pll->base + pll->cfg0_reg_off + P100_PLL_CFG1;
val = readl_relaxed(cfg1_off);
if (!(val & pll->pll_rst_bit))
return 0;
/* Enable RST */
val |= pll->pll_rst_bit;
writel_relaxed(val, cfg1_off);
udelay(3);
/* Disable RST */
val &= ~pll->pll_rst_bit;
writel_relaxed(val, cfg1_off);
ret = clk_p100_pll_wait_lock(pll);
if (ret)
return ret;
return 0;
}
static int clk_p100_pll_fake_prepare(struct clk_hw *hw)
{
return 0;
}
static int clk_p100_pll_is_prepared(struct clk_hw *hw)
{
struct clk_p100pll *pll = to_clk_p100pll(hw);
u32 val;
val = readl_relaxed(pll->base + pll->cfg0_reg_off + P100_PLL_CFG1);
return (val & pll->pll_rst_bit) ? 0 : 1;
}
static void clk_p100_pll_unprepare(struct clk_hw *hw)
{
struct clk_p100pll *pll = to_clk_p100pll(hw);
u32 val;
val = readl_relaxed(pll->base + pll->cfg0_reg_off + P100_PLL_CFG1);
val |= pll->pll_rst_bit;
writel_relaxed(val, pll->base + pll->cfg0_reg_off + P100_PLL_CFG1);
}
static unsigned long clk_p100_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_p100pll *pll = to_clk_p100pll(hw);
u32 refdiv, fbdiv, postdiv1, postdiv2, frac;
u32 pll_cfg0, pll_cfg1;
u64 fvco = 0;
pll_cfg0 = readl_relaxed(pll->base + pll->cfg0_reg_off);
pll_cfg1 = readl_relaxed(pll->base + pll->cfg0_reg_off + P100_PLL_CFG1);
refdiv = (pll_cfg0 & P100_REFDIV_MASK) >> P100_REFDIV_SHIFT;
fbdiv = (pll_cfg0 & P100_FBDIV_MASK) >> P100_FBDIV_SHIFT;
postdiv1 = (pll_cfg0 & P100_POSTDIV1_MASK) >> P100_POSTDIV1_SHIFT;
postdiv2 = (pll_cfg0 & P100_POSTDIV2_MASK) >> P100_POSTDIV2_SHIFT;
frac = (pll_cfg1 & P100_FRAC_MASK) >> P100_FRAC_SHIFT;
/* rate calculation:
* INT mode: FOUTVCO = FREE * FBDIV / REFDIV
* FRAC mode:FOUTVCO = (FREE * FBDIV + FREE * FRAC/BIT(24)) / REFDIV
*/
if (pll->pll_mode == PLL_MODE_FRAC)
fvco = (parent_rate * frac) / P100_FRAC_DIV;
fvco += (parent_rate * fbdiv);
do_div(fvco, refdiv);
if (pll->out_type == P100_PLL_DIV)
do_div(fvco, postdiv1 * postdiv2);
return fvco;
}
/* Zhihe P100 Pll recalc rate bypass for HAPS and EMU*/
static unsigned long clk_p100_pll_recalc_rate_fake_pll(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_p100pll *pll = to_clk_p100pll(hw);
const struct p100_pll_rate_table *rate_table = pll->rate_table;
/* return minimum supported value */
if (pll->out_type == P100_PLL_DIV)
return rate_table[0].rate;
return rate_table[0].vco_rate;
}
static const struct p100_pll_rate_table *p100_get_pll_div_settings(
struct clk_p100pll *pll, unsigned long rate)
{
const struct p100_pll_rate_table *rate_table = pll->rate_table;
int i;
for (i = 0; i < pll->rate_count; i++)
if (rate == rate_table[i].rate)
return &rate_table[i];
return NULL;
}
static const struct p100_pll_rate_table *p100_get_pll_vco_settings(
struct clk_p100pll *pll, unsigned long rate)
{
const struct p100_pll_rate_table *rate_table = pll->rate_table;
int i;
for (i = 0; i < pll->rate_count; i++)
if (rate == rate_table[i].vco_rate)
return &rate_table[i];
return NULL;
}
static inline bool clk_p100_pll_change(struct clk_p100pll *pll,
const struct p100_pll_rate_table *rate)
{
u32 refdiv_old, fbdiv_old, postdiv1_old, postdiv2_old, frac_old;
u32 cfg0, cfg1;
bool pll_changed;
cfg0 = readl_relaxed(pll->base + pll->cfg0_reg_off);
cfg1 = readl_relaxed(pll->base + pll->cfg0_reg_off + P100_PLL_CFG1);
refdiv_old = (cfg0 & P100_REFDIV_MASK) >> P100_REFDIV_SHIFT;
fbdiv_old = (cfg0 & P100_FBDIV_MASK) >> P100_FBDIV_SHIFT;
postdiv1_old = (cfg0 & P100_POSTDIV1_MASK) >> P100_POSTDIV1_SHIFT;
postdiv2_old = (cfg0 & P100_POSTDIV2_MASK) >> P100_POSTDIV2_SHIFT;
frac_old = (cfg1 & P100_FRAC_MASK) >> P100_FRAC_SHIFT;
pll_changed = rate->refdiv != refdiv_old || rate->fbdiv != fbdiv_old ||
rate->postdiv1 != postdiv1_old || rate->postdiv2 != postdiv2_old;
if (pll->pll_mode == PLL_MODE_FRAC)
pll_changed |= (rate->frac != frac_old);
return pll_changed;
}
static int clk_p100_pll_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
{
struct clk_p100pll *pll = to_clk_p100pll(hw);
const struct p100_pll_rate_table *rate;
void __iomem *cfg1_off;
u32 tmp, div_val;
int ret;
if (pll->out_type == P100_PLL_VCO) {
rate = p100_get_pll_vco_settings(pll, drate);
if (!rate) {
pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
drate, clk_hw_get_name(hw));
return -EINVAL;
}
} else {
rate = p100_get_pll_div_settings(pll, drate);
if (!rate) {
pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
drate, clk_hw_get_name(hw));
return -EINVAL;
}
}
if (!clk_p100_pll_change(pll, rate))
return 0;
/* Enable RST */
cfg1_off = pll->base + pll->cfg0_reg_off + P100_PLL_CFG1;
tmp = readl_relaxed(cfg1_off);
tmp |= pll->pll_rst_bit;
writel_relaxed(tmp, cfg1_off);
div_val = (rate->refdiv << P100_REFDIV_SHIFT) |
(rate->fbdiv << P100_FBDIV_SHIFT) |
(rate->postdiv1 << P100_POSTDIV1_SHIFT) |
(rate->postdiv2 << P100_POSTDIV2_SHIFT);
writel_relaxed(div_val, pll->base + pll->cfg0_reg_off);
if (pll->pll_mode == PLL_MODE_FRAC) {
tmp &= ~(P100_FRAC_MASK << P100_FRAC_SHIFT);
tmp |= rate->frac;
writel_relaxed(tmp, cfg1_off);
}
udelay(3);
/* Disable RST */
tmp &= ~pll->pll_rst_bit;
writel_relaxed(tmp, cfg1_off);
/* Wait Lock, ~20us cost */
ret = clk_p100_pll_wait_lock(pll);
if (ret)
return ret;
/* HW requires 30us for pll stable */
udelay(30);
return 0;
}
static long clk_p100_pllvco_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_p100pll *pll = to_clk_p100pll(hw);
const struct p100_pll_rate_table *rate_table = pll->rate_table;
unsigned long best = 0, now = 0;
unsigned int i, best_i = 0;
for (i = 0; i < pll->rate_count; i++) {
now = rate_table[i].vco_rate;
if (rate == now) {
return rate_table[i].vco_rate;
} else if (abs(now - rate) < abs(best - rate)) {
best = now;
best_i = i;
}
}
/* return minimum supported value */
return rate_table[best_i].vco_rate;
}
static long clk_p100_plldiv_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_p100pll *pll = to_clk_p100pll(hw);
const struct p100_pll_rate_table *rate_table = pll->rate_table;
unsigned long best = 0, now = 0;
unsigned int i, best_i = 0;
for (i = 0; i < pll->rate_count; i++) {
now = rate_table[i].rate;
if (rate == now) {
return rate_table[i].rate;
} else if (abs(now - rate) < abs(best - rate)) {
best = now;
best_i = i;
}
}
/* return minimum supported value */
return rate_table[best_i].rate;
}
static struct clk_ops clk_p100_pll_def_ops = {
.recalc_rate = clk_p100_pll_recalc_rate,
};
static struct clk_ops clk_p100_pllvco_ops = {
.prepare = clk_p100_pll_prepare,
.unprepare = clk_p100_pll_unprepare,
.is_prepared = clk_p100_pll_is_prepared,
.recalc_rate = clk_p100_pll_recalc_rate,
.round_rate = clk_p100_pllvco_round_rate,
.set_rate = clk_p100_pll_set_rate,
};
static struct clk_ops clk_p100_plldiv_ops = {
.prepare = clk_p100_pll_prepare,
.unprepare = clk_p100_pll_unprepare,
.is_prepared = clk_p100_pll_is_prepared,
.recalc_rate = clk_p100_pll_recalc_rate,
.round_rate = clk_p100_plldiv_round_rate,
.set_rate = clk_p100_pll_set_rate,
};
int zhihe_clk_set_round_rate(struct device *dev, struct clk *clk, unsigned int freq) int zhihe_clk_set_round_rate(struct device *dev, struct clk *clk, unsigned int freq)
{ {
unsigned long r; unsigned long r;
@@ -358,112 +46,33 @@ int zhihe_clk_set_round_rate(struct device *dev, struct clk *clk, unsigned int f
return ret; return ret;
} }
void zhihe_p100_clk_fake_pll_fixed_ops(void) static inline struct clk_zhihediv *to_clk_zhihediv(struct clk_hw *hw)
{
clk_p100_pll_def_ops.recalc_rate = clk_p100_pll_recalc_rate_fake_pll;
clk_p100_pllvco_ops.recalc_rate = clk_p100_pll_recalc_rate_fake_pll;
clk_p100_pllvco_ops.prepare = clk_p100_pll_fake_prepare;
clk_p100_plldiv_ops.recalc_rate = clk_p100_pll_recalc_rate_fake_pll;
clk_p100_plldiv_ops.prepare = clk_p100_pll_fake_prepare;
return;
}
struct clk *zhihe_p100_pll(const char *name, const char *parent_name,
void __iomem *base,
const struct p100_clk_info_pll *pll_clk)
{
struct clk_p100pll *pll;
struct clk *clk;
struct clk_init_data init;
u32 val;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
init.name = name;
init.flags = pll_clk->flags;
init.parent_names = &parent_name;
init.num_parents = 1;
switch (pll_clk->out_type) {
case P100_PLL_VCO:
if (pll_clk->rate_table)
init.ops = &clk_p100_pllvco_ops;
break;
case P100_PLL_DIV:
if (pll_clk->rate_table)
init.ops = &clk_p100_plldiv_ops;
break;
default:
pr_err("%s: Unknown pll out type for pll clk %s\n",
__func__, name);
};
if (!pll_clk->rate_table)
init.ops = &clk_p100_pll_def_ops;
pll->base = base;
pll->hw.init = &init;
pll->out_type = pll_clk->out_type;
pll->clk_type = pll_clk->clk_type;
pll->rate_table = pll_clk->rate_table;
pll->rate_count = pll_clk->rate_count;
pll->cfg0_reg_off = pll_clk->cfg0_reg_off;
pll->pll_sts_off = pll_clk->pll_sts_off;
pll->pll_lock_bit = pll_clk->pll_lock_bit;
pll->pll_bypass_bit = pll_clk->pll_bypass_bit;
pll->pll_rst_bit = pll_clk->pll_rst_bit;
pll->pll_mode = pll_clk->pll_mode;
val = readl_relaxed(pll->base + pll->cfg0_reg_off + P100_PLL_CFG1);
val &= ~pll->pll_bypass_bit;
val |= P100_DACPD_MASK;
val |= P100_DSMPD_MASK;
if (pll->pll_mode == PLL_MODE_FRAC) {
val &= ~P100_DSMPD_MASK;
val &= ~P100_DACPD_MASK;
}
writel_relaxed(val, pll->base + pll->cfg0_reg_off + P100_PLL_CFG1);
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll %s %lu\n",
__func__, name, PTR_ERR(clk));
kfree(pll);
}
return clk;
}
static inline struct clk_p100div *to_clk_p100div(struct clk_hw *hw)
{ {
struct clk_divider *divider = to_clk_divider(hw); struct clk_divider *divider = to_clk_divider(hw);
return container_of(divider, struct clk_p100div, divider); return container_of(divider, struct clk_zhihediv, divider);
} }
static unsigned long clk_p100div_recalc_rate(struct clk_hw *hw, static unsigned long clk_zhihediv_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate) unsigned long parent_rate)
{ {
struct clk_p100div *p100_div = to_clk_p100div(hw); struct clk_zhihediv *zhihe_div = to_clk_zhihediv(hw);
return p100_div->ops->recalc_rate(&p100_div->divider.hw, parent_rate); return zhihe_div->ops->recalc_rate(&zhihe_div->divider.hw, parent_rate);
} }
static long clk_p100div_round_rate(struct clk_hw *hw, unsigned long rate, static long clk_zhihediv_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate) unsigned long *prate)
{ {
struct clk_p100div *p100_div = to_clk_p100div(hw); struct clk_zhihediv *zhihe_div = to_clk_zhihediv(hw);
return p100_div->ops->round_rate(&p100_div->divider.hw, rate, prate); return zhihe_div->ops->round_rate(&zhihe_div->divider.hw, rate, prate);
} }
static int clk_p100div_set_rate(struct clk_hw *hw, unsigned long rate, static int clk_zhihediv_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate) unsigned long parent_rate)
{ {
struct clk_p100div *p100_div = to_clk_p100div(hw); struct clk_zhihediv *zhihe_div = to_clk_zhihediv(hw);
struct clk_divider *div = to_clk_divider(hw); struct clk_divider *div = to_clk_divider(hw);
unsigned int divider, value; unsigned int divider, value;
unsigned long flags = 0; unsigned long flags = 0;
@@ -477,23 +86,23 @@ static int clk_p100div_set_rate(struct clk_hw *hw, unsigned long rate,
divider = DIV64_U64_ROUND_CLOSEST(parent_rate, rate); divider = DIV64_U64_ROUND_CLOSEST(parent_rate, rate);
/* DIV is zero based divider, but CDE is not */ /* DIV is zero based divider, but CDE is not */
if (p100_div->div_type == MUX_TYPE_DIV) if (zhihe_div->div_type == MUX_TYPE_DIV)
value = divider; value = divider;
else else
value = divider - 1; value = divider - 1;
/* handle the div valid range */ /* handle the div valid range */
if (value > p100_div->max_div) if (value > zhihe_div->max_div)
value = p100_div->max_div; value = zhihe_div->max_div;
if (value < p100_div->min_div) if (value < zhihe_div->min_div)
value = p100_div->min_div; value = zhihe_div->min_div;
spin_lock_irqsave(div->lock, flags); spin_lock_irqsave(div->lock, flags);
val = readl(div->reg); val = readl(div->reg);
if (p100_div->sync_en != NO_DIV_EN) { if (zhihe_div->sync_en != NO_DIV_EN) {
val &= ~BIT(p100_div->sync_en); val &= ~BIT(zhihe_div->sync_en);
writel(val, div->reg); writel(val, div->reg);
udelay(1); udelay(1);
} }
@@ -502,9 +111,9 @@ static int clk_p100div_set_rate(struct clk_hw *hw, unsigned long rate,
val |= value << div->shift; val |= value << div->shift;
writel(val, div->reg); writel(val, div->reg);
if (p100_div->sync_en != NO_DIV_EN) { if (zhihe_div->sync_en != NO_DIV_EN) {
udelay(1); udelay(1);
val |= BIT(p100_div->sync_en); val |= BIT(zhihe_div->sync_en);
writel(val, div->reg); writel(val, div->reg);
} }
@@ -513,168 +122,168 @@ static int clk_p100div_set_rate(struct clk_hw *hw, unsigned long rate,
return 0; return 0;
} }
static const struct clk_ops clk_p100div_ops = { static const struct clk_ops clk_zhihediv_ops = {
.recalc_rate = clk_p100div_recalc_rate, .recalc_rate = clk_zhihediv_recalc_rate,
.round_rate = clk_p100div_round_rate, .round_rate = clk_zhihediv_round_rate,
.set_rate = clk_p100div_set_rate, .set_rate = clk_zhihediv_set_rate,
}; };
static struct clk *zhihe_clk_p100_divider_internal(const char *name, const char *parent, static struct clk *zhihe_clk_divider_internal(struct device *dev, const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
u8 sync, enum p100_div_type div_type, u8 sync, enum zhihe_div_type div_type,
u16 min, u16 max, bool closest) u16 min, u16 max, bool closest)
{ {
struct clk_p100div *p100_div; struct clk_zhihediv *zhihe_div;
struct clk_hw *hw; struct clk_hw *hw;
struct clk_init_data init; struct clk_init_data init;
int ret; int ret;
p100_div = kzalloc(sizeof(*p100_div), GFP_KERNEL); zhihe_div = kzalloc(sizeof(*zhihe_div), GFP_KERNEL);
if (!p100_div) if (!zhihe_div)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
init.name = name; init.name = name;
init.ops = &clk_p100div_ops; init.ops = &clk_zhihediv_ops;
init.flags = CLK_SET_RATE_PARENT; init.flags = CLK_SET_RATE_PARENT;
init.parent_names = parent ? &parent : NULL; init.parent_names = parent ? &parent : NULL;
init.num_parents = parent ? 1 : 0; init.num_parents = parent ? 1 : 0;
p100_div->divider.reg = reg; zhihe_div->divider.reg = reg;
p100_div->divider.shift = shift; zhihe_div->divider.shift = shift;
p100_div->divider.width = width; zhihe_div->divider.width = width;
p100_div->divider.lock = &zhihe_p100_clk_lock; zhihe_div->divider.lock = &zhihe_clk_lock;
p100_div->divider.hw.init = &init; zhihe_div->divider.hw.init = &init;
p100_div->ops = &clk_divider_ops; zhihe_div->ops = &clk_divider_ops;
p100_div->sync_en = sync; zhihe_div->sync_en = sync;
p100_div->div_type = div_type; zhihe_div->div_type = div_type;
if (p100_div->div_type == MUX_TYPE_DIV) if (zhihe_div->div_type == MUX_TYPE_DIV)
p100_div->divider.flags = CLK_DIVIDER_ONE_BASED; zhihe_div->divider.flags = CLK_DIVIDER_ONE_BASED;
if (closest) if (closest)
p100_div->divider.flags |= CLK_DIVIDER_ROUND_CLOSEST; zhihe_div->divider.flags |= CLK_DIVIDER_ROUND_CLOSEST;
p100_div->min_div = min > ((1 << width) - 1) ? zhihe_div->min_div = min > ((1 << width) - 1) ?
((1 << width) - 1) : min; ((1 << width) - 1) : min;
p100_div->max_div = max > ((1 << width) - 1) ? zhihe_div->max_div = max > ((1 << width) - 1) ?
((1 << width) - 1) : max; ((1 << width) - 1) : max;
hw = &p100_div->divider.hw; hw = &zhihe_div->divider.hw;
ret = clk_hw_register(NULL, hw); ret = clk_hw_register(dev, hw);
if (ret) { if (ret) {
kfree(p100_div); kfree(zhihe_div);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
return hw->clk; return hw->clk;
} }
struct clk *zhihe_clk_p100_divider(const char *name, const char *parent, struct clk *zhihe_clk_divider(struct device *dev, const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
u8 sync, enum p100_div_type div_type, u8 sync, enum zhihe_div_type div_type,
u16 min, u16 max) u16 min, u16 max)
{ {
return zhihe_clk_p100_divider_internal(name, parent, reg, shift, width, return zhihe_clk_divider_internal(dev, name, parent, reg, shift, width,
sync, div_type, min, max, false); sync, div_type, min, max, false);
} }
struct clk *zhihe_clk_p100_divider_closest(const char *name, const char *parent, struct clk *zhihe_clk_divider_closest(struct device *dev, const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
u8 sync, enum p100_div_type div_type, u8 sync, enum zhihe_div_type div_type,
u16 min, u16 max) u16 min, u16 max)
{ {
return zhihe_clk_p100_divider_internal(name, parent, reg, shift, width, return zhihe_clk_divider_internal(dev, name, parent, reg, shift, width,
sync, div_type, min, max, true); sync, div_type, min, max, true);
} }
static inline struct clk_p100gate *to_clk_p100gate(struct clk_hw *hw) static inline struct clk_zhihegate *to_clk_zhihegate(struct clk_hw *hw)
{ {
struct clk_gate *gate = to_clk_gate(hw); struct clk_gate *gate = to_clk_gate(hw);
return container_of(gate, struct clk_p100gate, gate); return container_of(gate, struct clk_zhihegate, gate);
} }
static int clk_p100_gate_share_is_enabled(struct clk_hw *hw) static int clk_zhihe_gate_share_is_enabled(struct clk_hw *hw)
{ {
struct clk_p100gate *p100_gate = to_clk_p100gate(hw); struct clk_zhihegate *zhihe_gate = to_clk_zhihegate(hw);
return p100_gate->ops->is_enabled(hw); return zhihe_gate->ops->is_enabled(hw);
} }
static int clk_p100_gate_share_enable(struct clk_hw *hw) static int clk_zhihe_gate_share_enable(struct clk_hw *hw)
{ {
struct clk_p100gate *p100_gate = to_clk_p100gate(hw); struct clk_zhihegate *zhihe_gate = to_clk_zhihegate(hw);
if (p100_gate->share_count && (*p100_gate->share_count)++ > 0) { if (zhihe_gate->share_count && (*zhihe_gate->share_count)++ > 0) {
return 0; return 0;
} }
return p100_gate->ops->enable(hw); return zhihe_gate->ops->enable(hw);
} }
static void clk_p100_gate_share_disable(struct clk_hw *hw) static void clk_zhihe_gate_share_disable(struct clk_hw *hw)
{ {
struct clk_p100gate *p100_gate = to_clk_p100gate(hw); struct clk_zhihegate *zhihe_gate = to_clk_zhihegate(hw);
if (p100_gate->share_count) { if (zhihe_gate->share_count) {
if (WARN_ON(*p100_gate->share_count == 0)) if (WARN_ON(*zhihe_gate->share_count == 0))
return; return;
else if (--(*p100_gate->share_count) > 0) { else if (--(*zhihe_gate->share_count) > 0) {
return; return;
} }
} }
p100_gate->ops->disable(hw); zhihe_gate->ops->disable(hw);
} }
static void clk_p100_gate_share_disable_unused(struct clk_hw *hw) static void clk_zhihe_gate_share_disable_unused(struct clk_hw *hw)
{ {
struct clk_p100gate *p100_gate = to_clk_p100gate(hw); struct clk_zhihegate *zhihe_gate = to_clk_zhihegate(hw);
if (!p100_gate->share_count || *p100_gate->share_count == 0) if (!zhihe_gate->share_count || *zhihe_gate->share_count == 0)
return p100_gate->ops->disable(hw); return zhihe_gate->ops->disable(hw);
} }
static const struct clk_ops clk_p100gate_share_ops = { static const struct clk_ops clk_zhihegate_share_ops = {
.enable = clk_p100_gate_share_enable, .enable = clk_zhihe_gate_share_enable,
.disable = clk_p100_gate_share_disable, .disable = clk_zhihe_gate_share_disable,
.disable_unused = clk_p100_gate_share_disable_unused, .disable_unused = clk_zhihe_gate_share_disable_unused,
.is_enabled = clk_p100_gate_share_is_enabled, .is_enabled = clk_zhihe_gate_share_is_enabled,
}; };
struct clk *zhihe_clk_p100_register_gate_shared(const char *name, const char *parent, struct clk *zhihe_clk_register_gate_shared(struct device *dev, const char *name, const char *parent,
unsigned long flags, void __iomem *reg, unsigned long flags, void __iomem *reg,
u8 shift, spinlock_t *lock, u8 shift, spinlock_t *lock,
unsigned int *share_count) unsigned int *share_count)
{ {
struct clk_p100gate *p100_gate; struct clk_zhihegate *zhihe_gate;
struct clk_hw *hw; struct clk_hw *hw;
struct clk_init_data init; struct clk_init_data init;
int ret; int ret;
p100_gate = kzalloc(sizeof(*p100_gate), GFP_KERNEL); zhihe_gate = kzalloc(sizeof(*zhihe_gate), GFP_KERNEL);
if (!p100_gate) if (!zhihe_gate)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
p100_gate->gate.reg = reg; zhihe_gate->gate.reg = reg;
p100_gate->gate.bit_idx = shift; zhihe_gate->gate.bit_idx = shift;
p100_gate->gate.flags = 0; zhihe_gate->gate.flags = 0;
p100_gate->gate.lock = lock; zhihe_gate->gate.lock = lock;
p100_gate->gate.hw.init = &init; zhihe_gate->gate.hw.init = &init;
p100_gate->ops = &clk_gate_ops; zhihe_gate->ops = &clk_gate_ops;
p100_gate->share_count = share_count; zhihe_gate->share_count = share_count;
init.name = name; init.name = name;
init.ops = &clk_p100gate_share_ops; init.ops = &clk_zhihegate_share_ops;
init.flags = flags; init.flags = flags;
init.parent_names = parent ? &parent : NULL; init.parent_names = parent ? &parent : NULL;
init.num_parents = parent ? 1 : 0; init.num_parents = parent ? 1 : 0;
hw = &p100_gate->gate.hw; hw = &zhihe_gate->gate.hw;
ret = clk_hw_register(NULL, hw); ret = clk_hw_register(dev, hw);
if (ret) { if (ret) {
kfree(p100_gate); kfree(zhihe_gate);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
@@ -708,7 +317,6 @@ static int is_frequency_name(const char *name)
static struct clk *zhihe_clk_match_clk(struct clk **clks, char *name) static struct clk *zhihe_clk_match_clk(struct clk **clks, char *name)
{ {
int i; int i;
for (i = 0; i < CLK_END; i++) { for (i = 0; i < CLK_END; i++) {
if (clks[i] == ERR_PTR(-ENOENT)) if (clks[i] == ERR_PTR(-ENOENT))
continue; continue;
@@ -748,10 +356,10 @@ int zhihe_clk_of_bulk_init(struct device *dev, struct clk **clks)
return 0; return 0;
} }
int p100_parse_regbase(struct platform_device *pdev) int zhihe_parse_regbase(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct p100_clk_subsys *priv = dev_get_drvdata(dev); struct zhihe_clk_subsys *priv = dev_get_drvdata(dev);
int ret = 0; int ret = 0;
for (int i = 0; i < priv->num_regs; i++) { for (int i = 0; i < priv->num_regs; i++) {
@@ -765,12 +373,51 @@ int p100_parse_regbase(struct platform_device *pdev)
return ret; return ret;
} }
void p100_register_clock(struct platform_device *pdev) static char *str_die_suffix(struct device *dev, const char *name, int id)
{
char *new_name = devm_kzalloc(dev, ZHIHE_CLK_NAME_SIZE, GFP_KERNEL);
if (new_name)
snprintf(new_name, ZHIHE_CLK_NAME_SIZE, "%s_die%d", name, id);
return new_name;
}
static const char * const * zhihe_add_mux_suffix(struct platform_device *pdev, int i)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct p100_clk_subsys *priv = dev_get_drvdata(dev); struct zhihe_clk_subsys *priv = dev_get_drvdata(dev);
const char * const *original_parents = priv->info[i].mux.parents;
u8 num_parents = priv->info[i].mux.num_parents;
const char **new_parents;
if (priv->die_num == 0)
return original_parents;
new_parents = devm_kzalloc(dev, sizeof(char *) * num_parents, GFP_KERNEL);
if (!new_parents) {
dev_err(dev, "Failed to allocate memory for new mux parents\n");
return ERR_PTR(-ENOMEM);
}
for (int j = 0; j < num_parents; j++) {
const char *original_name = original_parents[j];
char *suffix_name = str_die_suffix(dev, original_name, priv->die_num);
if (!suffix_name) {
dev_err(dev, "Failed to allocate memory for suffix_name\n");
return ERR_PTR(-ENOMEM);
}
new_parents[j] = suffix_name;
}
return new_parents;
}
void zhihe_register_clock(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct zhihe_clk_subsys *priv = dev_get_drvdata(dev);
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
unsigned int freq; unsigned int freq;
char *name, *parent;
int ret; int ret;
/* update pll freq if defined in dts */ /* update pll freq if defined in dts */
@@ -783,9 +430,14 @@ void p100_register_clock(struct platform_device *pdev)
} }
for (int i = 0; i < priv->num_info; i++) { for (int i = 0; i < priv->num_info; i++) {
enum p100_clk_types type = priv->info[i].type; enum zhihe_clk_types type = priv->info[i].type;
char *name = priv->info[i].name; if (priv->die_num != 0) {
char *parent = priv->info[i].parent; name = str_die_suffix(dev, priv->info[i].name, priv->die_num);
parent = str_die_suffix(dev, priv->info[i].parent, priv->die_num);
} else {
name = priv->info[i].name;
parent = priv->info[i].parent;
}
u32 id = priv->info[i].id; u32 id = priv->info[i].id;
void __iomem *base = priv->regs[priv->info[i].reg].base + void __iomem *base = priv->regs[priv->info[i].reg].base +
priv->info[i].shift; priv->info[i].shift;
@@ -794,35 +446,36 @@ void p100_register_clock(struct platform_device *pdev)
switch (type) { switch (type) {
case CLK_TYPE_FIXED: case CLK_TYPE_FIXED:
priv->clk_data->clks[id] = zhihe_clk_fixed(name, parent, priv->info[i].fixed.freq); priv->clk_data->clks[id] = zhihe_clk_fixed(dev, name, parent, priv->info[i].fixed.freq);
break; break;
case CLK_TYPE_FIXED_FACTOR: case CLK_TYPE_FIXED_FACTOR:
priv->clk_data->clks[id] = zhihe_p100_clk_fixed_factor(name, parent, priv->clk_data->clks[id] = zhihe_clk_fixed_factor(dev, name, parent,
priv->info[i].fixed_factor.mult, priv->info[i].fixed_factor.div); priv->info[i].fixed_factor.mult, priv->info[i].fixed_factor.div);
break; break;
case CLK_TYPE_PLL: case CLK_TYPE_PLL:
priv->clk_data->clks[id] = zhihe_p100_pll(name, parent, base, priv->info[i].pll); priv->clk_data->clks[id] = zhihe_pll(dev, name, parent, base, priv->info[i].pll);
break; break;
case CLK_TYPE_DIVIDER: case CLK_TYPE_DIVIDER:
priv->clk_data->clks[id] = zhihe_clk_p100_divider(name, parent, base, bit_idx, width, priv->clk_data->clks[id] = zhihe_clk_divider(dev, name, parent, base, bit_idx, width,
priv->info[i].divider.sync, priv->info[i].divider.div_type, priv->info[i].divider.sync, priv->info[i].divider.div_type,
priv->info[i].divider.min, priv->info[i].divider.max); priv->info[i].divider.min, priv->info[i].divider.max);
break; break;
case CLK_TYPE_DIVIDER_CLOSEST: case CLK_TYPE_DIVIDER_CLOSEST:
priv->clk_data->clks[id] = zhihe_clk_p100_divider_closest(name, parent, base, bit_idx, width, priv->clk_data->clks[id] = zhihe_clk_divider_closest(dev, name, parent, base, bit_idx, width,
priv->info[i].divider.sync, priv->info[i].divider.div_type, priv->info[i].divider.sync, priv->info[i].divider.div_type,
priv->info[i].divider.min, priv->info[i].divider.max); priv->info[i].divider.min, priv->info[i].divider.max);
break; break;
case CLK_TYPE_GATE: case CLK_TYPE_GATE:
priv->clk_data->clks[id] = zhihe_clk_p100_gate(name, parent, base, bit_idx); priv->clk_data->clks[id] = zhihe_clk_gate(dev, name, parent, base, bit_idx);
break; break;
case CLK_TYPE_GATE_SHARED: case CLK_TYPE_GATE_SHARED:
priv->clk_data->clks[id] = zhihe_clk_p100_gate_shared(name, parent, base, bit_idx, priv->clk_data->clks[id] = zhihe_clk_gate_shared(dev, name, parent, base, bit_idx,
priv->info[i].gate_shared.share_count); priv->info[i].gate_shared.share_count);
break; break;
case CLK_TYPE_MUX: case CLK_TYPE_MUX:
priv->clk_data->clks[id] = zhihe_p100_clk_mux_flags(name, base, bit_idx, width, const char * const *parents = zhihe_add_mux_suffix(pdev, i);
priv->info[i].mux.parents, priv->info[i].mux.num_parents, priv->clk_data->clks[id] = zhihe_clk_mux_flags(dev, name, base, bit_idx, width,
parents, priv->info[i].mux.num_parents,
priv->info[i].mux.flags); priv->info[i].mux.flags);
break; break;
default: default:

View File

@@ -11,45 +11,9 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <dt-bindings/clock/a210-clock.h> #include <dt-bindings/clock/a210-clock.h>
extern spinlock_t zhihe_p100_clk_lock; extern spinlock_t zhihe_clk_lock;
#define P100_CLK_NAME_SIZE 30 #define ZHIHE_CLK_NAME_SIZE 40
/* top reg idx */
#define PLL_WRAP 0
#define TOP_CRG 1
#define CPU_SS_CLK_SYSREG 2
#define CPU_SS_CPU_PLL 3
#define DDR0_SYSREG 4
#define DDR1_SYSREG 5
#define SLC_DUAL_SYSREG 6
#define TOP_CRG_T 7
#define CPU_SS_CCU 8
/* gpu reg idx */
#define GPU_SS_PWRAP_CLK_EN 0
#define GPU_SS_TOP_CLK_EN 1
/* pcie reg idx */
#define PCIE_CLK_EN 0
/* usb reg idx */
#define USB_CLK_EN 0
/* vi reg idx */
#define VI_CLK 0
/* vp reg idx */
#define VP_CLK 0
/* vo reg idx */
#define VO_CLK 0
#define VO_PATH_CTRL 1
/* npu reg idx */
#define NPU_CLK 0
#define NPU_TOP_CLK 1
/* d2d reg idx */
#define D2D_CRG_REG 0
/* peri reg idx */
#define PERI0_SYSREG 0
#define PERI1_SYSREG 1
#define PERI2_SYSREG 2
#define PERI3_SYSREG 3
#define TEE_CRG 4
#define PLL_RATE(_vco, _rate, _r, _b, _f, _p, _k) \ #define PLL_RATE(_vco, _rate, _r, _b, _f, _p, _k) \
{ \ { \
@@ -144,7 +108,7 @@ extern spinlock_t zhihe_p100_clk_lock;
.name = (_name), \ .name = (_name), \
} }
#define CLK_SUBSYS(_name, _regs, _num_reg, _info, _num_info, _pll, _num_pll, _is_fpga) { \ #define CLK_SUBSYS(_name, _regs, _num_reg, _info, _num_info, _pll, _num_pll, _is_fpga, _die_num) { \
.name = (_name), \ .name = (_name), \
.regs = (_regs), \ .regs = (_regs), \
.num_regs = (_num_reg), \ .num_regs = (_num_reg), \
@@ -153,38 +117,24 @@ extern spinlock_t zhihe_p100_clk_lock;
.plls = (_pll), \ .plls = (_pll), \
.num_plls = (_num_pll), \ .num_plls = (_num_pll), \
.is_fpga = (_is_fpga), \ .is_fpga = (_is_fpga), \
.die_num = (_die_num), \
} }
enum p100_pll_outtype { enum zhihe_pll_outtype {
P100_PLL_VCO, ZHIHE_PLL_VCO,
P100_PLL_DIV, ZHIHE_PLL_DIV,
}; };
enum p100_div_type { enum zhihe_div_type {
MUX_TYPE_DIV, MUX_TYPE_DIV,
MUX_TYPE_CDE, MUX_TYPE_CDE,
}; };
enum p100_div_sync_type { enum zhihe_div_sync_type {
NO_DIV_EN = 255, NO_DIV_EN = 255,
}; };
enum p100_pll_clktype { enum zhihe_clk_types {
AUDIO0_PLL,
AUDIO1_PLL,
VIDEO_PLL,
GMAC_PLL,
DVFS_PLL,
DPU0_PLL,
DPU1_PLL,
DPU2_PLL,
TEE_PLL,
DDR_PLL,
C920_PLL,
C908_PLL,
};
enum p100_clk_types {
CLK_TYPE_FIXED, CLK_TYPE_FIXED,
CLK_TYPE_PLL, CLK_TYPE_PLL,
CLK_TYPE_FIXED_FACTOR, CLK_TYPE_FIXED_FACTOR,
@@ -195,36 +145,37 @@ enum p100_clk_types {
CLK_TYPE_MUX, CLK_TYPE_MUX,
}; };
enum p100_pll_mode { enum zhihe_pll_mode {
PLL_MODE_FRAC, PLL_MODE_FRAC,
PLL_MODE_INT, PLL_MODE_INT,
}; };
struct p100_clk_reg { struct zhihe_clk_reg {
void __iomem *base; void __iomem *base;
char name[P100_CLK_NAME_SIZE]; char name[ZHIHE_CLK_NAME_SIZE];
}; };
/* clk summary info at subsys level */ /* clk summary info at subsys level */
struct p100_clk_subsys { struct zhihe_clk_subsys {
char name[P100_CLK_NAME_SIZE]; char name[ZHIHE_CLK_NAME_SIZE];
struct p100_clk_reg *regs; struct zhihe_clk_reg *regs;
u32 num_regs; u32 num_regs;
struct p100_clk_info *info; struct zhihe_clk_info *info;
u32 num_info; u32 num_info;
struct p100_clk_info_pll *plls; struct zhihe_clk_info_pll *plls;
u32 num_plls; u32 num_plls;
bool is_fpga; bool is_fpga;
struct clk_onecell_data *clk_data; struct clk_onecell_data *clk_data;
char die_num;
}; };
struct clk_p100pll { struct clk_zhihepll {
struct clk_hw hw; struct clk_hw hw;
void __iomem *base; void __iomem *base;
enum p100_pll_clktype clk_type; unsigned int clk_type;
enum p100_pll_outtype out_type; enum zhihe_pll_outtype out_type;
enum p100_pll_mode pll_mode; enum zhihe_pll_mode pll_mode;
const struct p100_pll_rate_table *rate_table; const struct zhihe_pll_rate_table *rate_table;
int rate_count; int rate_count;
u32 cfg0_reg_off; u32 cfg0_reg_off;
@@ -234,22 +185,22 @@ struct clk_p100pll {
int pll_bypass_bit; int pll_bypass_bit;
}; };
struct clk_p100div { struct clk_zhihediv {
struct clk_divider divider; struct clk_divider divider;
enum p100_div_type div_type; enum zhihe_div_type div_type;
u16 min_div; u16 min_div;
u16 max_div; u16 max_div;
u8 sync_en; u8 sync_en;
const struct clk_ops *ops; const struct clk_ops *ops;
}; };
struct clk_p100gate { struct clk_zhihegate {
struct clk_gate gate; struct clk_gate gate;
unsigned int *share_count; unsigned int *share_count;
const struct clk_ops *ops; const struct clk_ops *ops;
}; };
struct p100_pll_rate_table { struct zhihe_pll_rate_table {
unsigned long vco_rate; unsigned long vco_rate;
unsigned long rate; unsigned long rate;
unsigned int refdiv; unsigned int refdiv;
@@ -261,132 +212,133 @@ struct p100_pll_rate_table {
/* detailed clk info for each clk */ /* detailed clk info for each clk */
struct p100_clk_info_pll { struct zhihe_clk_info_pll {
enum p100_pll_outtype out_type; enum zhihe_pll_outtype out_type;
enum p100_pll_clktype clk_type; unsigned int clk_type;
struct p100_pll_rate_table *rate_table; struct zhihe_pll_rate_table *rate_table;
int rate_count; int rate_count;
int flags; int flags;
char name[P100_CLK_NAME_SIZE]; char name[ZHIHE_CLK_NAME_SIZE];
u32 cfg0_reg_off; u32 cfg0_reg_off;
u32 pll_sts_off; u32 pll_sts_off;
int pll_lock_bit; int pll_lock_bit;
int pll_rst_bit; int pll_rst_bit;
int pll_bypass_bit; int pll_bypass_bit;
enum p100_pll_mode pll_mode; enum zhihe_pll_mode pll_mode;
}; };
struct p100_clk_info_fixed { struct zhihe_clk_info_fixed {
unsigned int freq; unsigned int freq;
}; };
struct p100_clk_info_fixed_factor { struct zhihe_clk_info_fixed_factor {
unsigned int mult; unsigned int mult;
unsigned int div; unsigned int div;
}; };
struct p100_clk_info_divider { struct zhihe_clk_info_divider {
u8 sync; u8 sync;
enum p100_div_type div_type; enum zhihe_div_type div_type;
u16 min; u16 min;
u16 max; u16 max;
}; };
struct p100_clk_info_gate_shared { struct zhihe_clk_info_gate_shared {
unsigned int *share_count; unsigned int *share_count;
}; };
struct p100_clk_info_mux { struct zhihe_clk_info_mux {
const char * const *parents; const char * const *parents;
int num_parents; int num_parents;
unsigned long flags; unsigned long flags;
}; };
struct p100_clk_info { struct zhihe_clk_info {
enum p100_clk_types type; enum zhihe_clk_types type;
u32 id; u32 id;
char name[P100_CLK_NAME_SIZE]; char name[ZHIHE_CLK_NAME_SIZE];
char parent[P100_CLK_NAME_SIZE]; char parent[ZHIHE_CLK_NAME_SIZE];
u8 reg; u8 reg;
u32 shift; u32 shift;
u8 width; u8 width;
u8 bit_idx; u8 bit_idx;
union { union {
struct p100_clk_info_fixed fixed; struct zhihe_clk_info_fixed fixed;
struct p100_clk_info_fixed_factor fixed_factor; struct zhihe_clk_info_fixed_factor fixed_factor;
struct p100_clk_info_pll *pll; struct zhihe_clk_info_pll *pll;
struct p100_clk_info_divider divider; struct zhihe_clk_info_divider divider;
struct p100_clk_info_gate_shared gate_shared; struct zhihe_clk_info_gate_shared gate_shared;
struct p100_clk_info_mux mux; struct zhihe_clk_info_mux mux;
}; };
}; };
static inline struct clk *zhihe_p100_clk_fixed_factor(const char *name, static inline struct clk *zhihe_clk_fixed_factor(struct device *dev, const char *name,
const char *parent, unsigned int mult, unsigned int div) const char *parent, unsigned int mult, unsigned int div)
{ {
return clk_register_fixed_factor(NULL, name, parent, return clk_register_fixed_factor(dev, name, parent,
CLK_SET_RATE_PARENT, mult, div); CLK_SET_RATE_PARENT, mult, div);
} }
struct clk *zhihe_p100_pll(const char *name, const char *parent_name, struct clk *zhihe_pll(struct device *dev, const char *name, const char *parent_name,
void __iomem *base, void __iomem *base,
const struct p100_clk_info_pll *pll_clk); const struct zhihe_clk_info_pll *pll_clk);
static inline struct clk *zhihe_clk_p100_gate(const char *name, const char *parent, static inline struct clk *zhihe_clk_gate(struct device *dev, const char *name, const char *parent,
void __iomem *reg, u8 shift) void __iomem *reg, u8 shift)
{ {
return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg, return clk_register_gate(dev, name, parent, CLK_SET_RATE_PARENT, reg,
shift, 0, &zhihe_p100_clk_lock); shift, 0, &zhihe_clk_lock);
} }
struct clk *zhihe_clk_p100_register_gate_shared(const char *name, const char *parent, struct clk *zhihe_clk_register_gate_shared(struct device *dev, const char *name, const char *parent,
unsigned long flags, void __iomem *reg, unsigned long flags, void __iomem *reg,
u8 shift, spinlock_t *lock, u8 shift, spinlock_t *lock,
unsigned int *share_count); unsigned int *share_count);
struct clk *zhihe_clk_p100_divider(const char *name, const char *parent, struct clk *zhihe_clk_divider(struct device *dev, const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
u8 sync, enum p100_div_type div_type, u8 sync, enum zhihe_div_type div_type,
u16 min, u16 max); u16 min, u16 max);
/** /**
* By default, the clk framework calculates frequency by rounding downwards. * By default, the clk framework calculates frequency by rounding downwards.
* This function is to achieve closest frequency. * This function is to achieve closest frequency.
*/ */
struct clk *zhihe_clk_p100_divider_closest(const char *name, const char *parent, struct clk *zhihe_clk_divider_closest(struct device *dev, const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
u8 sync, enum p100_div_type div_type, u8 sync, enum zhihe_div_type div_type,
u16 min, u16 max); u16 min, u16 max);
void zhihe_unregister_clocks(struct clk *clks[], unsigned int count);
static inline struct clk *zhihe_clk_fixed(const char *name, const char *parent, unsigned long rate) static inline struct clk *zhihe_clk_fixed(struct device *dev, const char *name, const char *parent, unsigned long rate)
{ {
return clk_register_fixed_rate(NULL, name, parent, 0, rate); return clk_register_fixed_rate(dev, name, parent, 0, rate);
} }
static inline struct clk *zhihe_clk_p100_gate_shared(const char *name, const char *parent, static inline struct clk *zhihe_clk_gate_shared(struct device *dev, const char *name, const char *parent,
void __iomem *reg, u8 shift, void __iomem *reg, u8 shift,
unsigned int *share_count) unsigned int *share_count)
{ {
return zhihe_clk_p100_register_gate_shared(name, parent, CLK_SET_RATE_PARENT, reg, return zhihe_clk_register_gate_shared(dev, name, parent, CLK_SET_RATE_PARENT, reg,
shift, &zhihe_p100_clk_lock, share_count); shift, &zhihe_clk_lock, share_count);
} }
static inline struct clk *zhihe_p100_clk_mux_flags(const char *name, static inline struct clk *zhihe_clk_mux_flags(struct device *dev, const char *name,
void __iomem *reg, u8 shift, u8 width, void __iomem *reg, u8 shift, u8 width,
const char * const *parents, int num_parents, const char * const *parents, int num_parents,
unsigned long flags) unsigned long flags)
{ {
return clk_register_mux(NULL, name, parents, num_parents, return clk_register_mux(dev, name, parents, num_parents,
flags , reg, shift, width, 0, flags , reg, shift, width, 0,
&zhihe_p100_clk_lock); &zhihe_clk_lock);
} }
void zhihe_p100_clk_fake_pll_fixed_ops(void); void zhihe_clk_fake_pll_fixed_ops(void);
int zhihe_clk_set_round_rate(struct device *dev, struct clk *clk, unsigned int freq); int zhihe_clk_set_round_rate(struct device *dev, struct clk *clk, unsigned int freq);
int zhihe_clk_of_bulk_init(struct device *dev, struct clk **clks); int zhihe_clk_of_bulk_init(struct device *dev, struct clk **clks);
int p100_parse_regbase(struct platform_device *pdev); int add_die_suffix(struct platform_device *pdev);
void p100_register_clock(struct platform_device *pdev); void zhihe_register_clock(struct platform_device *pdev);
void zhihe_unregister_clocks(struct clk *clks[], unsigned int count);
int zhihe_parse_regbase(struct platform_device *pdev);
#endif #endif

408
drivers/clk/zhihe/clk-pll.c Normal file
View File

@@ -0,0 +1,408 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2025 Zhihe Computing Limited.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/device.h>
#include "clk-helper.h"
#define ZHIHE_PLL_CFG0 0x0
#define ZHIHE_PLL_CFG1 0x04
#define ZHIHE_PLL_CFG2 0x8
#define ZHIHE_POSTDIV2_SHIFT 24
#define ZHIHE_POSTDIV2_MASK GENMASK(26, 24)
#define ZHIHE_POSTDIV1_SHIFT 20
#define ZHIHE_POSTDIV1_MASK GENMASK(22, 20)
#define ZHIHE_FBDIV_SHIFT 8
#define ZHIHE_FBDIV_MASK GENMASK(19, 8)
#define ZHIHE_REFDIV_SHIFT 0
#define ZHIHE_REFDIV_MASK GENMASK(5, 0)
#define ZHIHE_BYPASS_MASK BIT(30)
#define ZHIHE_RST_MASK BIT(29)
#define ZHIHE_DSMPD_MASK BIT(24)
#define ZHIHE_DACPD_MASK BIT(25)
#define ZHIHE_FRAC_MASK GENMASK(23, 0)
#define ZHIHE_FRAC_SHIFT 0
#define ZHIHE_FRAC_DIV BIT(24)
#define LOCK_TIMEOUT_US 10000
#define to_clk_zhihepll(_hw) container_of(_hw, struct clk_zhihepll, hw)
static int clk_zhihe_pll_wait_lock(struct clk_zhihepll *pll)
{
u32 val;
return readl_poll_timeout(pll->base + pll->pll_sts_off, val,
val & pll->pll_lock_bit, 0,
LOCK_TIMEOUT_US);
}
static int clk_zhihe_pll_prepare(struct clk_hw *hw)
{
struct clk_zhihepll *pll = to_clk_zhihepll(hw);
void __iomem *cfg1_off;
u32 val;
int ret;
cfg1_off = pll->base + pll->cfg0_reg_off + ZHIHE_PLL_CFG1;
val = readl_relaxed(cfg1_off);
if (!(val & pll->pll_rst_bit))
return 0;
/* Enable RST */
val |= pll->pll_rst_bit;
writel_relaxed(val, cfg1_off);
udelay(3);
/* Disable RST */
val &= ~pll->pll_rst_bit;
writel_relaxed(val, cfg1_off);
ret = clk_zhihe_pll_wait_lock(pll);
if (ret)
return ret;
return 0;
}
static int clk_zhihe_pll_fake_prepare(struct clk_hw *hw)
{
return 0;
}
static int clk_zhihe_pll_is_prepared(struct clk_hw *hw)
{
struct clk_zhihepll *pll = to_clk_zhihepll(hw);
u32 val;
val = readl_relaxed(pll->base + pll->cfg0_reg_off + ZHIHE_PLL_CFG1);
return (val & pll->pll_rst_bit) ? 0 : 1;
}
static void clk_zhihe_pll_unprepare(struct clk_hw *hw)
{
struct clk_zhihepll *pll = to_clk_zhihepll(hw);
u32 val;
val = readl_relaxed(pll->base + pll->cfg0_reg_off + ZHIHE_PLL_CFG1);
val |= pll->pll_rst_bit;
writel_relaxed(val, pll->base + pll->cfg0_reg_off + ZHIHE_PLL_CFG1);
}
static unsigned long clk_zhihe_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_zhihepll *pll = to_clk_zhihepll(hw);
u32 refdiv, fbdiv, postdiv1, postdiv2, frac;
u32 pll_cfg0, pll_cfg1;
u64 fvco = 0;
pll_cfg0 = readl_relaxed(pll->base + pll->cfg0_reg_off);
pll_cfg1 = readl_relaxed(pll->base + pll->cfg0_reg_off + ZHIHE_PLL_CFG1);
refdiv = (pll_cfg0 & ZHIHE_REFDIV_MASK) >> ZHIHE_REFDIV_SHIFT;
fbdiv = (pll_cfg0 & ZHIHE_FBDIV_MASK) >> ZHIHE_FBDIV_SHIFT;
postdiv1 = (pll_cfg0 & ZHIHE_POSTDIV1_MASK) >> ZHIHE_POSTDIV1_SHIFT;
postdiv2 = (pll_cfg0 & ZHIHE_POSTDIV2_MASK) >> ZHIHE_POSTDIV2_SHIFT;
frac = (pll_cfg1 & ZHIHE_FRAC_MASK) >> ZHIHE_FRAC_SHIFT;
/* rate calculation:
* INT mode: FOUTVCO = FREE * FBDIV / REFDIV
* FRAC mode:FOUTVCO = (FREE * FBDIV + FREE * FRAC/BIT(24)) / REFDIV
*/
if (pll->pll_mode == PLL_MODE_FRAC)
fvco = (parent_rate * frac) / ZHIHE_FRAC_DIV;
fvco += (parent_rate * fbdiv);
do_div(fvco, refdiv);
if (pll->out_type == ZHIHE_PLL_DIV)
do_div(fvco, postdiv1 * postdiv2);
return fvco;
}
/* Zhihe ZHIHE Pll recalc rate bypass for HAPS and EMU*/
static unsigned long clk_zhihe_pll_recalc_rate_fake_pll(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_zhihepll *pll = to_clk_zhihepll(hw);
const struct zhihe_pll_rate_table *rate_table = pll->rate_table;
/* return minimum supported value */
if (pll->out_type == ZHIHE_PLL_DIV)
return rate_table[0].rate;
return rate_table[0].vco_rate;
}
static const struct zhihe_pll_rate_table *zhihe_get_pll_div_settings(
struct clk_zhihepll *pll, unsigned long rate)
{
const struct zhihe_pll_rate_table *rate_table = pll->rate_table;
int i;
for (i = 0; i < pll->rate_count; i++)
if (rate == rate_table[i].rate)
return &rate_table[i];
return NULL;
}
static const struct zhihe_pll_rate_table *zhihe_get_pll_vco_settings(
struct clk_zhihepll *pll, unsigned long rate)
{
const struct zhihe_pll_rate_table *rate_table = pll->rate_table;
int i;
for (i = 0; i < pll->rate_count; i++)
if (rate == rate_table[i].vco_rate)
return &rate_table[i];
return NULL;
}
static inline bool clk_zhihe_pll_change(struct clk_zhihepll *pll,
const struct zhihe_pll_rate_table *rate)
{
u32 refdiv_old, fbdiv_old, postdiv1_old, postdiv2_old, frac_old;
u32 cfg0, cfg1;
bool pll_changed;
cfg0 = readl_relaxed(pll->base + pll->cfg0_reg_off);
cfg1 = readl_relaxed(pll->base + pll->cfg0_reg_off + ZHIHE_PLL_CFG1);
refdiv_old = (cfg0 & ZHIHE_REFDIV_MASK) >> ZHIHE_REFDIV_SHIFT;
fbdiv_old = (cfg0 & ZHIHE_FBDIV_MASK) >> ZHIHE_FBDIV_SHIFT;
postdiv1_old = (cfg0 & ZHIHE_POSTDIV1_MASK) >> ZHIHE_POSTDIV1_SHIFT;
postdiv2_old = (cfg0 & ZHIHE_POSTDIV2_MASK) >> ZHIHE_POSTDIV2_SHIFT;
frac_old = (cfg1 & ZHIHE_FRAC_MASK) >> ZHIHE_FRAC_SHIFT;
pll_changed = rate->refdiv != refdiv_old || rate->fbdiv != fbdiv_old ||
rate->postdiv1 != postdiv1_old || rate->postdiv2 != postdiv2_old;
if (pll->pll_mode == PLL_MODE_FRAC)
pll_changed |= (rate->frac != frac_old);
return pll_changed;
}
static int clk_zhihe_pll_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
{
struct clk_zhihepll *pll = to_clk_zhihepll(hw);
const struct zhihe_pll_rate_table *rate;
void __iomem *cfg1_off;
u32 tmp, div_val;
int ret;
if (pll->out_type == ZHIHE_PLL_VCO) {
rate = zhihe_get_pll_vco_settings(pll, drate);
if (!rate) {
pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
drate, clk_hw_get_name(hw));
return -EINVAL;
}
} else {
rate = zhihe_get_pll_div_settings(pll, drate);
if (!rate) {
pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
drate, clk_hw_get_name(hw));
return -EINVAL;
}
}
if (!clk_zhihe_pll_change(pll, rate))
return 0;
/* Enable RST */
cfg1_off = pll->base + pll->cfg0_reg_off + ZHIHE_PLL_CFG1;
tmp = readl_relaxed(cfg1_off);
tmp |= pll->pll_rst_bit;
writel_relaxed(tmp, cfg1_off);
div_val = (rate->refdiv << ZHIHE_REFDIV_SHIFT) |
(rate->fbdiv << ZHIHE_FBDIV_SHIFT) |
(rate->postdiv1 << ZHIHE_POSTDIV1_SHIFT) |
(rate->postdiv2 << ZHIHE_POSTDIV2_SHIFT);
writel_relaxed(div_val, pll->base + pll->cfg0_reg_off);
if (pll->pll_mode == PLL_MODE_FRAC) {
tmp &= ~(ZHIHE_FRAC_MASK << ZHIHE_FRAC_SHIFT);
tmp |= rate->frac;
writel_relaxed(tmp, cfg1_off);
}
udelay(3);
/* Disable RST */
tmp &= ~pll->pll_rst_bit;
writel_relaxed(tmp, cfg1_off);
/* Wait Lock, ~20us cost */
ret = clk_zhihe_pll_wait_lock(pll);
if (ret)
return ret;
/* HW requires 30us for pll stable */
udelay(30);
return 0;
}
static long clk_zhihe_pllvco_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_zhihepll *pll = to_clk_zhihepll(hw);
const struct zhihe_pll_rate_table *rate_table = pll->rate_table;
unsigned long best = 0, now = 0;
unsigned int i, best_i = 0;
for (i = 0; i < pll->rate_count; i++) {
now = rate_table[i].vco_rate;
if (rate == now) {
return rate_table[i].vco_rate;
} else if (abs(now - rate) < abs(best - rate)) {
best = now;
best_i = i;
}
}
/* return minimum supported value */
return rate_table[best_i].vco_rate;
}
static long clk_zhihe_plldiv_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_zhihepll *pll = to_clk_zhihepll(hw);
const struct zhihe_pll_rate_table *rate_table = pll->rate_table;
unsigned long best = 0, now = 0;
unsigned int i, best_i = 0;
for (i = 0; i < pll->rate_count; i++) {
now = rate_table[i].rate;
if (rate == now) {
return rate_table[i].rate;
} else if (abs(now - rate) < abs(best - rate)) {
best = now;
best_i = i;
}
}
/* return minimum supported value */
return rate_table[best_i].rate;
}
static struct clk_ops clk_zhihe_pll_def_ops = {
.recalc_rate = clk_zhihe_pll_recalc_rate,
};
static struct clk_ops clk_zhihe_pllvco_ops = {
.prepare = clk_zhihe_pll_prepare,
.unprepare = clk_zhihe_pll_unprepare,
.is_prepared = clk_zhihe_pll_is_prepared,
.recalc_rate = clk_zhihe_pll_recalc_rate,
.round_rate = clk_zhihe_pllvco_round_rate,
.set_rate = clk_zhihe_pll_set_rate,
};
static struct clk_ops clk_zhihe_plldiv_ops = {
.prepare = clk_zhihe_pll_prepare,
.unprepare = clk_zhihe_pll_unprepare,
.is_prepared = clk_zhihe_pll_is_prepared,
.recalc_rate = clk_zhihe_pll_recalc_rate,
.round_rate = clk_zhihe_plldiv_round_rate,
.set_rate = clk_zhihe_pll_set_rate,
};
void zhihe_clk_fake_pll_fixed_ops(void)
{
clk_zhihe_pll_def_ops.recalc_rate = clk_zhihe_pll_recalc_rate_fake_pll;
clk_zhihe_pllvco_ops.recalc_rate = clk_zhihe_pll_recalc_rate_fake_pll;
clk_zhihe_pllvco_ops.prepare = clk_zhihe_pll_fake_prepare;
clk_zhihe_plldiv_ops.recalc_rate = clk_zhihe_pll_recalc_rate_fake_pll;
clk_zhihe_plldiv_ops.prepare = clk_zhihe_pll_fake_prepare;
return;
}
struct clk *zhihe_pll(struct device *dev, const char *name, const char *parent_name,
void __iomem *base,
const struct zhihe_clk_info_pll *pll_clk)
{
struct clk_zhihepll *pll;
struct clk *clk;
struct clk_init_data init;
u32 val;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
init.name = name;
init.flags = pll_clk->flags;
init.parent_names = &parent_name;
init.num_parents = 1;
switch (pll_clk->out_type) {
case ZHIHE_PLL_VCO:
if (pll_clk->rate_table)
init.ops = &clk_zhihe_pllvco_ops;
break;
case ZHIHE_PLL_DIV:
if (pll_clk->rate_table)
init.ops = &clk_zhihe_plldiv_ops;
break;
default:
pr_err("%s: Unknown pll out type for pll clk %s\n",
__func__, name);
};
if (!pll_clk->rate_table)
init.ops = &clk_zhihe_pll_def_ops;
pll->base = base;
pll->hw.init = &init;
pll->out_type = pll_clk->out_type;
pll->clk_type = pll_clk->clk_type;
pll->rate_table = pll_clk->rate_table;
pll->rate_count = pll_clk->rate_count;
pll->cfg0_reg_off = pll_clk->cfg0_reg_off;
pll->pll_sts_off = pll_clk->pll_sts_off;
pll->pll_lock_bit = pll_clk->pll_lock_bit;
pll->pll_bypass_bit = pll_clk->pll_bypass_bit;
pll->pll_rst_bit = pll_clk->pll_rst_bit;
pll->pll_mode = pll_clk->pll_mode;
val = readl_relaxed(pll->base + pll->cfg0_reg_off + ZHIHE_PLL_CFG1);
val &= ~pll->pll_bypass_bit;
val |= ZHIHE_DACPD_MASK;
val |= ZHIHE_DSMPD_MASK;
if (pll->pll_mode == PLL_MODE_FRAC) {
val &= ~ZHIHE_DSMPD_MASK;
val &= ~ZHIHE_DACPD_MASK;
}
writel_relaxed(val, pll->base + pll->cfg0_reg_off + ZHIHE_PLL_CFG1);
clk = clk_register(dev, &pll->hw);
if (IS_ERR(clk)) {
pr_err("failed to register pll %s %ld\n",
name, PTR_ERR(clk));
kfree(pll);
}
return clk;
}

View File

@@ -321,5 +321,13 @@ config RISCV_XUANTIE_TH1520_CPUFREQ
This adds the CPUFreq driver support for XuanTie th1520 SoCs This adds the CPUFreq driver support for XuanTie th1520 SoCs
which are capable of changing the CPU's frequency dynamically. which are capable of changing the CPU's frequency dynamically.
config RISCV_ZHIHE_CPUFREQ
bool "CPU frequency scaling driver for zhihe riscv SoCs"
depends on OF && COMMON_CLK && ZHIHE_AON
select PM_OPP
help
This adds the CPUFreq driver support for Zhihe riscv A210 SoCs
which are capable of changing the CPU's frequency dynamically.
endif endif
endmenu endmenu

View File

@@ -108,3 +108,4 @@ obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o
obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o
obj-$(CONFIG_SPARC_US3_CPUFREQ) += sparc-us3-cpufreq.o obj-$(CONFIG_SPARC_US3_CPUFREQ) += sparc-us3-cpufreq.o
obj-$(CONFIG_RISCV_XUANTIE_TH1520_CPUFREQ) += th1520-cpufreq.o obj-$(CONFIG_RISCV_XUANTIE_TH1520_CPUFREQ) += th1520-cpufreq.o
obj-$(CONFIG_RISCV_ZHIHE_CPUFREQ) += zhihe-cpufreq.o

View File

@@ -0,0 +1,505 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2025 Zhihe Computing Limited.
*
* Dong Yan <yand@zhcomputing.com>
*/
#define pr_fmt(fmt)KBUILD_MODNAME ": " fmt
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_opp.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/thermal.h>
#include <linux/mutex.h>
#define ZH_DVFS_MAX_REGULATORS 2
/* SOC specific data */
struct zh_cpufreq_bus_opp {
unsigned long long bus_clk_freq;
unsigned long long pic_clk_freq;
unsigned long long cfg_clk_freq;
unsigned long long com_clk_freq;
unsigned long long apb_clk_freq;
};
struct zh_cpufreq_soc_data {
struct device *dev;
struct clk *bus_clk;
struct clk *pic_clk;
struct clk *cfg_clk;
struct clk *com_clk;
struct clk *apb_clk;
struct zh_cpufreq_bus_opp *bus_opp;
unsigned int num_bus_opp;
};
/* cluster specific data */
struct zh_cpufreq_cluster_data {
cpumask_var_t cpus;
struct device *cpu_dev;
struct regulator *dvdd_cpu;
struct regulator *dvddm_cpu;
struct regulator *dvdd_cpu_p;
struct list_head node;
int opp_token;
struct cpufreq_frequency_table *freq_table;
struct clk *pll_mux;
struct zh_cpufreq_soc_data *soc;
unsigned int num_opps;
};
static LIST_HEAD(info_list);
static struct freq_attr *zh_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL, /* Extra space for boost-attr if required */
NULL,
};
static struct zh_cpufreq_cluster_data *zh_cpufreq_cluster_data_lookup(int cpu)
{
struct zh_cpufreq_cluster_data *cluster;
list_for_each_entry(cluster, &info_list, node) {
if (cpumask_test_cpu(cpu, cluster->cpus))
return cluster;
}
return NULL;
}
static int zh_cpufreq_online(struct cpufreq_policy *policy)
{
/* TODO: hotplug specific actions */
return 0;
}
static int zh_cpufreq_offline(struct cpufreq_policy *policy)
{
/* TODO: hotplug specific actions */
return 0;
}
static int zh_cpufreq_init(struct cpufreq_policy *policy)
{
struct zh_cpufreq_cluster_data *cluster;
struct device *cpu_dev;
unsigned int transition_latency;
int ret;
cluster = zh_cpufreq_cluster_data_lookup(policy->cpu);
if (!cluster) {
pr_err("failed to find data for cpu%d\n", policy->cpu);
return -ENODEV;
}
cpu_dev = cluster->cpu_dev;
transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
if (!transition_latency)
transition_latency = CPUFREQ_ETERNAL;
cpumask_copy(policy->cpus, cluster->cpus);
policy->driver_data = cluster;
policy->clk = cluster->pll_mux;
policy->freq_table = cluster->freq_table;
policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000;
policy->cpuinfo.transition_latency = transition_latency;
policy->dvfs_possible_from_any_cpu = true;
/* Support turbo/boost mode */
if (policy_has_boost_freq(policy)) {
/* This gets disabled by core on driver unregister */
ret = cpufreq_enable_boost_support();
if (ret)
return ret;
zh_cpufreq_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;
}
return 0;
}
static int zh_cpufreq_exit(struct cpufreq_policy *policy)
{
clk_put(policy->clk);
return 0;
}
static int zh_set_target(struct cpufreq_policy *policy, unsigned int index)
{
struct zh_cpufreq_cluster_data *cluster = policy->driver_data;
struct zh_cpufreq_soc_data *soc = cluster->soc;
unsigned long target_freq = policy->freq_table[index].frequency;
unsigned int current_freq = policy->cur;
if (target_freq < current_freq && policy->cpu == 0) {
clk_set_rate(soc->bus_clk, soc->bus_opp[index].bus_clk_freq);
clk_set_rate(soc->pic_clk, soc->bus_opp[index].pic_clk_freq);
clk_set_rate(soc->cfg_clk, soc->bus_opp[index].cfg_clk_freq);
clk_set_rate(soc->com_clk, soc->bus_opp[index].com_clk_freq);
clk_set_rate(soc->apb_clk, soc->bus_opp[index].apb_clk_freq);
}
clk_set_rate(cluster->pll_mux, 1000000000);
dev_pm_opp_set_rate(cluster->cpu_dev, target_freq * 1000);
if (target_freq > current_freq && policy->cpu == 0) {
clk_set_rate(soc->bus_clk, soc->bus_opp[index].bus_clk_freq);
clk_set_rate(soc->pic_clk, soc->bus_opp[index].pic_clk_freq);
clk_set_rate(soc->cfg_clk, soc->bus_opp[index].cfg_clk_freq);
clk_set_rate(soc->com_clk, soc->bus_opp[index].com_clk_freq);
clk_set_rate(soc->apb_clk, soc->bus_opp[index].apb_clk_freq);
}
return 0;
}
static struct cpufreq_driver zh_cpufreq_driver = {
.flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK | CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
CPUFREQ_IS_COOLING_DEV,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = zh_set_target,
.get = cpufreq_generic_get,
.init = zh_cpufreq_init,
.exit = zh_cpufreq_exit,
.online = zh_cpufreq_online,
.offline = zh_cpufreq_offline,
.register_em = cpufreq_register_em_with_opp,
.name = "zh-cpufreq",
.attr = zh_cpufreq_attr,
.suspend = cpufreq_generic_suspend,
};
static int find_supply_name(struct device *dev, struct device_node *cpu_np, const char ***reg_names_out)
{
struct property *prop;
const char *prop_name;
size_t len;
int count = 0;
const char **names_array;
if (!cpu_np)
return -EINVAL;
names_array = devm_kzalloc(dev, (ZH_DVFS_MAX_REGULATORS + 1) * sizeof(char *), GFP_KERNEL);
if (!names_array)
return -ENOMEM;
for_each_property_of_node(cpu_np, prop) {
prop_name = prop->name;
len = strlen(prop_name);
if (len > 7 && strcmp(prop_name + len - 7, "-supply") == 0) {
if (count >= ZH_DVFS_MAX_REGULATORS) {
pr_err("Too many regulators defined!\n");
return -ENOMEM;
}
char *reg_name_buf = devm_kzalloc(dev, len - 7 + 1, GFP_KERNEL);
if (!reg_name_buf)
return -ENOMEM;
strncpy(reg_name_buf, prop_name, len - 7);
reg_name_buf[len - 7] = '\0';
names_array[count] = reg_name_buf;
count++;
}
}
*reg_names_out = names_array;
return count;
}
static int zh_opp_config_regulators(struct device *dev,
struct dev_pm_opp *old_opp, struct dev_pm_opp *new_opp,
struct regulator **regulators, unsigned int count)
{
int ret;
struct dev_pm_opp_supply new_supplies[2];
/* We must have two regulators here */
WARN_ON(count != 2);
/* Fetch supplies and freq information from OPP core */
ret = dev_pm_opp_get_supplies(new_opp, new_supplies);
WARN_ON(ret);
for (int i = 0; i < count; i++) {
if (IS_ERR(regulators[i])) {
dev_dbg(dev, "%s: regulator not available: %ld\n", __func__,
PTR_ERR(regulators[i]));
return 0;
}
ret = regulator_set_voltage_triplet(regulators[i], new_supplies[i].u_volt_min,
new_supplies[i].u_volt, new_supplies[i].u_volt_max);
if (ret)
dev_err(dev, "%s: failed to set voltage (%lu %lu %lu mV): %d\n",
__func__, new_supplies[i].u_volt_min, new_supplies[i].u_volt,
new_supplies[i].u_volt_max, ret);
}
return 0;
}
static int find_bus_info(struct zh_cpufreq_soc_data *soc)
{
struct device_node *cpu_np = NULL;
struct device_node *opp_table_np = NULL;
struct device_node *opp_np = NULL;
struct device *cpu_dev = get_cpu_device(0);
struct device *dev = soc->dev;
int i = 0;
soc->bus_clk = clk_get(dev, "bus_clk");
if (IS_ERR(soc->bus_clk)) {
dev_err(dev, "failed to get bus_clk\n");
return PTR_ERR(soc->bus_clk);
}
soc->pic_clk = clk_get(dev, "pic_clk");
if (IS_ERR(soc->pic_clk)) {
dev_err(dev, "failed to get pic_clk\n");
return PTR_ERR(soc->pic_clk);
}
soc->cfg_clk = clk_get(dev, "cfg_clk");
if (IS_ERR(soc->cfg_clk)) {
dev_err(dev, "failed to get cfg_clk\n");
return PTR_ERR(soc->cfg_clk);
}
soc->com_clk = clk_get(dev, "com_clk");
if (IS_ERR(soc->com_clk)) {
dev_err(dev, "failed to get com_clk\n");
return PTR_ERR(soc->com_clk);
}
soc->apb_clk = clk_get(dev, "apb_clk");
if (IS_ERR(soc->apb_clk)) {
dev_err(dev, "failed to get apb_clk\n");
return PTR_ERR(soc->apb_clk);
}
cpu_np = of_get_cpu_node(0, NULL);
if (!cpu_np) {
dev_err(dev, "Failed to get CPU device node\n");
return -ENODEV;
}
opp_table_np = of_parse_phandle(cpu_np, "operating-points-v2", 0);
if (!opp_table_np) {
dev_err(dev, "Failed to get CPU opp_table\n");
return -ENODEV;
}
soc->num_bus_opp = dev_pm_opp_get_opp_count(cpu_dev);
if (!soc->num_bus_opp) {
dev_err(dev, "No OPPs found\n");
return -ENODEV;
}
soc->bus_opp = devm_kzalloc(dev, sizeof(struct zh_cpufreq_bus_opp) * soc->num_bus_opp, GFP_KERNEL);
if (!soc->bus_opp)
return -ENOMEM;
for_each_child_of_node(opp_table_np, opp_np) {
if (of_property_read_u64(opp_np, "bus-clk-hz", &soc->bus_opp[i].bus_clk_freq))
dev_warn(dev, "Missing 'bus-clk-hz' for OPP%d\n", i);
if (of_property_read_u64(opp_np, "pic-clk-hz", &soc->bus_opp[i].pic_clk_freq))
dev_warn(dev, "Missing 'pic-clk-hz' for OPP%d\n", i);
if (of_property_read_u64(opp_np, "cfg-clk-hz", &soc->bus_opp[i].cfg_clk_freq))
dev_warn(dev, "Missing 'cfg-clk-hz' for OPP%d\n", i);
if (of_property_read_u64(opp_np, "com-clk-hz", &soc->bus_opp[i].com_clk_freq))
dev_warn(dev, "Missing 'com-clk-hz' for OPP%d\n", i);
if (of_property_read_u64(opp_np, "apb-clk-hz", &soc->bus_opp[i].apb_clk_freq))
dev_warn(dev, "Missing 'apb-clk-hz' for OPP%d\n", i);
i++;
}
return 0;
}
static int zh_cpufreq_prepare_cluster(struct device *dev, int cpu)
{
struct zh_cpufreq_cluster_data *cluster;
struct device *cpu_dev;
const char **reg_names = NULL;
int num_regulators;
int ret;
cluster = zh_cpufreq_cluster_data_lookup(cpu);
if (cluster)
return 0; // dvfs cluster of this cpu already existed in case of hotplug.
cpu_dev = get_cpu_device(cpu);
if (!cpu_dev)
return -EPROBE_DEFER;
cluster = devm_kzalloc(dev, sizeof(*cluster), GFP_KERNEL);
if (!cluster) {
return -ENOMEM;
}
cluster->soc = dev_get_drvdata(dev);
cluster->cpu_dev = cpu_dev;
cluster->pll_mux = clk_get(cpu_dev, NULL);
if (IS_ERR(cluster->pll_mux)) {
ret = PTR_ERR(cluster->pll_mux);
dev_err(cpu_dev, "%s: failed to get clk: %d\n", __func__, ret);
return ret;
}
if (!alloc_cpumask_var(&cluster->cpus, GFP_KERNEL))
return -ENOMEM;
/*
* OPP layer will be taking care of regulators now, but it needs to know
* the name of the regulator first.
*/
num_regulators = find_supply_name(dev, of_get_cpu_node(cpu, NULL), &reg_names);
if (num_regulators > 0) {
cluster->opp_token = dev_pm_opp_set_regulators(cpu_dev, reg_names);
if (cluster->opp_token < 0) {
ret = dev_err_probe(dev, cluster->opp_token,
"failed to set regulators\n");
goto free_cpumask;
}
ret = dev_pm_opp_set_config_regulators(cpu_dev, zh_opp_config_regulators);
if (ret < 0) {
dev_err(dev, "failed to set config_regulators callback ret=%d\n", ret);
goto free_cpumask;
}
}
/* Get OPP-sharing information from "operating-points-v2" bindings .
* After this point, cpumask will include all cpus within the same cluster.
*/
ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, cluster->cpus);
if (ret) {
goto out_regulator;
}
/*
* Initialize OPP tables for all priv->cpus from device tree. They will be shared by
* all CPUs which have marked their CPUs shared with OPP bindings.
*/
ret = dev_pm_opp_of_cpumask_add_table(cluster->cpus);
if (ret) {
goto out_table;
}
/*
* The OPP table must be initialized by this point.
*/
cluster->num_opps = dev_pm_opp_get_opp_count(cpu_dev);
if (cluster->num_opps <= 0) {
dev_err(cpu_dev, "OPP table can't be empty\n");
ret = -ENODEV;
goto out_table;
}
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &cluster->freq_table);
if (ret) {
dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
goto out_table;
}
list_add(&cluster->node, &info_list);
return 0;
out_table:
dev_pm_opp_of_cpumask_remove_table(cluster->cpus);
out_regulator:
dev_pm_opp_put_regulators(cluster->opp_token);
free_cpumask:
free_cpumask_var(cluster->cpus);
return ret;
}
static void zh_cpufreq_release(void)
{
struct zh_cpufreq_cluster_data *cluster, *tmp;
list_for_each_entry_safe(cluster, tmp, &info_list, node) {
dev_pm_opp_free_cpufreq_table(cluster->cpu_dev, &cluster->freq_table);
dev_pm_opp_of_cpumask_remove_table(cluster->cpus);
dev_pm_opp_put_regulators(cluster->opp_token);
free_cpumask_var(cluster->cpus);
list_del(&cluster->node);
}
}
static int zh_cpufreq_probe(struct platform_device *pdev)
{
struct zh_cpufreq_soc_data *soc;
struct device *dev = &pdev->dev;
int cpu, ret;
soc = devm_kzalloc(dev, sizeof(*soc), GFP_KERNEL);
if (!soc)
return -ENOMEM;
soc->dev = dev;
dev_set_drvdata(dev, soc);
for_each_possible_cpu(cpu) {
ret = zh_cpufreq_prepare_cluster(dev, cpu);
if (ret)
goto err;
}
ret = find_bus_info(soc);
if (ret < 0) {
dev_err(dev, "failed to find bus clk opp %d\n", ret);
goto err;
}
ret = cpufreq_register_driver(&zh_cpufreq_driver);
if (ret) {
dev_err(dev, "failed register driver: %d\n", ret);
goto err;
}
return 0;
err:
zh_cpufreq_release();
return ret;
}
static const struct of_device_id zh_cpufreq_of_match[] = {
{ .compatible = "zhihe,a210-cpufreq"},
{}
};
MODULE_DEVICE_TABLE(of, zh_cpufreq_of_match);
static struct platform_driver zh_cpufreq_platdrv = {
.driver = {
.name = "zh-cpufreq",
.of_match_table = of_match_ptr(zh_cpufreq_of_match),
},
.probe = zh_cpufreq_probe,
};
module_platform_driver(zh_cpufreq_platdrv);
MODULE_AUTHOR("Dong Yan <yand@zhcomputing.com>");
MODULE_DESCRIPTION("Zhihe cpufreq driver");
MODULE_LICENSE("GPL v2");

View File

@@ -616,7 +616,7 @@ static void set_desc_dest_master(struct axi_dma_hw_desc *hw_desc,
* dma_burst_len_to_enum - Convert burst length value to AXI DMA burst length enum * dma_burst_len_to_enum - Convert burst length value to AXI DMA burst length enum
* @burst_len: Burst length value to convert * @burst_len: Burst length value to convert
* *
* This function maps a numeric burst length value to the corresponding * This function maps a numeric burst length value to the corresponding
* DWAXIDMAC_BURST_TRANS_LEN_* enumeration constant used in the DesignWare AXI DMA controller. * DWAXIDMAC_BURST_TRANS_LEN_* enumeration constant used in the DesignWare AXI DMA controller.
* *
* Return: * Return:
@@ -1728,7 +1728,7 @@ static const struct of_device_id dw_dma_of_id_table[] = {
.compatible = "xuantie,th1520-axi-dma", .compatible = "xuantie,th1520-axi-dma",
.data = (void *)(AXI_DMA_FLAG_USE_CFG2), .data = (void *)(AXI_DMA_FLAG_USE_CFG2),
}, { }, {
.compatible = "zhihe,p100-axi-dma", .compatible = "zhihe,a210-axi-dma",
.data = (void *)(AXI_DMA_FLAG_USE_CFG2), .data = (void *)(AXI_DMA_FLAG_USE_CFG2),
}, },
{} {}

View File

@@ -210,7 +210,7 @@ out:
} }
EXPORT_SYMBOL(th1520_aon_call_rpc); EXPORT_SYMBOL(th1520_aon_call_rpc);
int get_aon_log_mem(struct device *dev, phys_addr_t *mem, size_t *mem_size) static int get_aon_log_mem(struct device *dev, phys_addr_t *mem, size_t *mem_size)
{ {
struct resource r; struct resource r;
struct device_node *node; struct device_node *node;

View File

@@ -17,6 +17,14 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/zhihe_proc_debug.h> #include <linux/zhihe_proc_debug.h>
#include <linux/init.h>
#include <linux/firmware.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/delay.h>
#define ZHIHE_AON_SYNC_VAL 0xfeabdeff
#define ZHIHE_AON_RESET_VAL 0x3
#define ZHIHE_AON_V1 0x0 #define ZHIHE_AON_V1 0x0
#define ZHIHE_AON_V2 0x1 #define ZHIHE_AON_V2 0x1
@@ -211,7 +219,7 @@ out:
} }
EXPORT_SYMBOL(zhihe_aon_call_rpc); EXPORT_SYMBOL(zhihe_aon_call_rpc);
int get_aon_log_mem(struct device *dev, phys_addr_t *mem, size_t *mem_size) static int get_aon_log_mem(struct device *dev, phys_addr_t *mem, size_t *mem_size)
{ {
struct resource r; struct resource r;
struct device_node *node; struct device_node *node;
@@ -237,6 +245,78 @@ int get_aon_log_mem(struct device *dev, phys_addr_t *mem, size_t *mem_size)
return 0; return 0;
} }
static int zhihe_aon_boot_img_by_name(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = pdev->dev.of_node;
const struct firmware *zhihe_aon_fw = NULL;
void __iomem *base_addr;
void __iomem *reset_reg;
void __iomem *sync_reg;
unsigned int reset_val = ZHIHE_AON_RESET_VAL;
unsigned int sync_val = ZHIHE_AON_SYNC_VAL;
unsigned int sync_read = 0;
const char *bin_name = NULL;
unsigned int timeout_ms = 50;
unsigned long timeout;
int ret;
base_addr = devm_platform_ioremap_resource_byname(pdev, "aon_base_addr");
if (IS_ERR(base_addr)) {
dev_err(dev, "Failed to map base_addr\n");
return PTR_ERR(base_addr);
}
reset_reg = devm_platform_ioremap_resource_byname(pdev, "aon_reset_reg");
if (IS_ERR(reset_reg)) {
dev_err(dev, "Failed to map aon_reset_reg\n");
return PTR_ERR(reset_reg);
}
sync_reg = devm_platform_ioremap_resource_byname(pdev, "aon_sync_reg");
if (IS_ERR(sync_reg)) {
dev_err(dev, "Failed to map aon_sync_reg\n");
return PTR_ERR(sync_reg);
}
ret = of_property_read_string(node, "firmware-name", &bin_name);
if (ret) {
dev_err(dev, "Failed to get aon-bin-names property: %d\n", ret);
return ret;
}
ret = request_firmware(&zhihe_aon_fw, bin_name, NULL);
if (ret) {
dev_err(dev, "Failed to load firmware: %s (ret=%d)\n",
bin_name, ret);
return ret;
}
dev_info(dev, "firmware loaded, size = %zu bytes\n", zhihe_aon_fw->size);
memset(base_addr, 0, zhihe_aon_fw->size);
memcpy(base_addr, zhihe_aon_fw->data, zhihe_aon_fw->size);
iowrite32(reset_val, reset_reg);
timeout = jiffies + msecs_to_jiffies(timeout_ms);
while(ioread32(sync_reg) != sync_val) {
if (time_after(jiffies, timeout)) {
dev_err(dev, "AON bringup timeout! sync_reg=0x%x, expected=0x%x\n",
sync_read, sync_val);
release_firmware(zhihe_aon_fw);
return -ETIMEDOUT;
}
usleep_range(1000, 2000);
}
release_firmware(zhihe_aon_fw);
return 0;
}
static int zhihe_aon_probe(struct platform_device *pdev) static int zhihe_aon_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
@@ -246,6 +326,17 @@ static int zhihe_aon_probe(struct platform_device *pdev)
struct device_node *np; struct device_node *np;
char dir_name[32] = { 0x0 }; char dir_name[32] = { 0x0 };
int ret; int ret;
ret = zhihe_aon_boot_img_by_name(pdev);
if (ret == -ETIMEDOUT) {
dev_warn(dev, "AON sync timeout, retrying...\n");
ret = zhihe_aon_boot_img_by_name(pdev);
if (ret) {
dev_err(dev, "AON bringup failed after retry (ret=%d)\n", ret);
return ret;
}
}
aon_ipc = devm_kzalloc(dev, sizeof(*aon_ipc), GFP_KERNEL); aon_ipc = devm_kzalloc(dev, sizeof(*aon_ipc), GFP_KERNEL);
if (!aon_ipc) if (!aon_ipc)
return -ENOMEM; return -ENOMEM;
@@ -323,7 +414,7 @@ static int __maybe_unused zhihe_aon_resume_noirq(struct device *dev)
aon_chan = &zhihe_aon_ipc_handle->chans; aon_chan = &zhihe_aon_ipc_handle->chans;
complete(&aon_chan->tx_done); complete(&aon_chan->tx_done);
#endif #endif
return 0; return 0;
} }
@@ -344,4 +435,3 @@ MODULE_AUTHOR("hongkun.xu <xuhongkun@zhcomputing.com>");
MODULE_AUTHOR("xionglue.huang <huangxionglue@zhcomputing.com>"); MODULE_AUTHOR("xionglue.huang <huangxionglue@zhcomputing.com>");
MODULE_DESCRIPTION("ZHIHE firmware protocol driver"); MODULE_DESCRIPTION("ZHIHE firmware protocol driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");

View File

@@ -283,13 +283,15 @@ static void dwapb_irq_enable(struct irq_data *d)
{ {
struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct dwapb_gpio *gpio = to_dwapb_gpio(gc); struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
irq_hw_number_t hwirq = irqd_to_hwirq(d);
unsigned long flags; unsigned long flags;
u32 val; u32 val;
raw_spin_lock_irqsave(&gc->bgpio_lock, flags); raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
val = dwapb_read(gpio, GPIO_INTEN); val = dwapb_read(gpio, GPIO_INTEN) | BIT(hwirq);
val |= BIT(irqd_to_hwirq(d));
dwapb_write(gpio, GPIO_INTEN, val); dwapb_write(gpio, GPIO_INTEN, val);
val = dwapb_read(gpio, GPIO_INTMASK) & ~BIT(hwirq);
dwapb_write(gpio, GPIO_INTMASK, val);
raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
} }
@@ -297,12 +299,14 @@ static void dwapb_irq_disable(struct irq_data *d)
{ {
struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct dwapb_gpio *gpio = to_dwapb_gpio(gc); struct dwapb_gpio *gpio = to_dwapb_gpio(gc);
irq_hw_number_t hwirq = irqd_to_hwirq(d);
unsigned long flags; unsigned long flags;
u32 val; u32 val;
raw_spin_lock_irqsave(&gc->bgpio_lock, flags); raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
val = dwapb_read(gpio, GPIO_INTEN); val = dwapb_read(gpio, GPIO_INTMASK) | BIT(hwirq);
val &= ~BIT(irqd_to_hwirq(d)); dwapb_write(gpio, GPIO_INTMASK, val);
val = dwapb_read(gpio, GPIO_INTEN) & ~BIT(hwirq);
dwapb_write(gpio, GPIO_INTEN, val); dwapb_write(gpio, GPIO_INTEN, val);
raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
} }

View File

@@ -22,6 +22,14 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#ifdef CONFIG_ZHIHE_AUXDISP
#include <linux/of.h>
#include <linux/of_device.h>
#include <drm/drm_bridge.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#endif
#include <media/cec-notifier.h> #include <media/cec-notifier.h>
#include <uapi/linux/media-bus-format.h> #include <uapi/linux/media-bus-format.h>
@@ -41,6 +49,10 @@
#include "dw-hdmi-cec.h" #include "dw-hdmi-cec.h"
#include "dw-hdmi.h" #include "dw-hdmi.h"
#ifdef CONFIG_ZHIHE_AUXDISP
#define AUXDISP_DT_COMPATIBLE "zhihe,auxdisp"
#endif
#define DDC_CI_ADDR 0x37 #define DDC_CI_ADDR 0x37
#define DDC_SEGMENT_ADDR 0x30 #define DDC_SEGMENT_ADDR 0x30
@@ -1033,6 +1045,10 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
case MEDIA_BUS_FMT_YUV8_1X24: case MEDIA_BUS_FMT_YUV8_1X24:
case MEDIA_BUS_FMT_UYYVYY8_0_5X24: case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
color_format = 0x09; color_format = 0x09;
#ifdef CONFIG_ZHIHE_AUXDISP
/* auxdisp 输出的NV12 AVI值为28 */
color_format = 0x1c;
#endif
break; break;
case MEDIA_BUS_FMT_YUV10_1X30: case MEDIA_BUS_FMT_YUV10_1X30:
case MEDIA_BUS_FMT_UYYVYY10_0_5X30: case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
@@ -1115,7 +1131,7 @@ static int is_color_space_interpolation(struct dw_hdmi *hdmi)
return 0; return 0;
} }
static bool is_csc_needed(struct dw_hdmi *hdmi) static bool __maybe_unused is_csc_needed(struct dw_hdmi *hdmi)
{ {
return is_color_space_conversion(hdmi) || return is_color_space_conversion(hdmi) ||
is_color_space_decimation(hdmi) || is_color_space_decimation(hdmi) ||
@@ -2325,7 +2341,7 @@ static void hdmi_check_scrambling_status(struct dw_hdmi *hdmi,
} }
static int dw_hdmi_setup(struct dw_hdmi *hdmi, static int dw_hdmi_setup(struct dw_hdmi *hdmi,
const struct drm_connector *connector, struct drm_connector *connector,
const struct drm_display_mode *mode) const struct drm_display_mode *mode)
{ {
int ret; int ret;
@@ -2697,6 +2713,162 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* DRM Bridge Operations * DRM Bridge Operations
*/ */
#ifdef CONFIG_ZHIHE_AUXDISP
static u32 *get_bus_input_format_for_auxdisp(struct drm_crtc_state *crtc_state, u32 *input_fmts, unsigned int *num_input_fmts){
struct device_node *crtc_port;
struct drm_plane_state *plane_state;
struct drm_framebuffer *fb = NULL;
struct drm_crtc *crtc = crtc_state->crtc;
/* 判断是哪个 CRTC */
if (crtc && crtc->port) {
crtc_port = crtc->port->parent;
if (crtc_port) {
/* 检查是否是 auxdisp */
if (!of_device_is_compatible(crtc_port, AUXDISP_DT_COMPATIBLE)) {
*num_input_fmts = 0;
return NULL;
}
}
}
/*
* AuxDisp CRTC framebuffer bus_format
*/
/* 获取 primary plane 的 framebuffer */
if (crtc_state->crtc && crtc_state->crtc->primary) {
plane_state = drm_atomic_get_new_plane_state(crtc_state->state,
crtc_state->crtc->primary);
if (plane_state)
fb = plane_state->fb;
}
/* 根据 framebuffer 的格式确定 bus_format */
if (!fb) {
*num_input_fmts = 0;
return NULL;
}
switch (fb->format->format) {
/* RGB 8bit 格式 */
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
break;
/* RGB 10bit 格式 */
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010:
input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
break;
/* RGB565 格式 */
case DRM_FORMAT_RGB565:
case DRM_FORMAT_BGR565:
input_fmts[0] = MEDIA_BUS_FMT_RGB565_1X16;
break;
/* YUV420 8bit 格式 */
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV21:
input_fmts[0] = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
break;
/* YUV420 10bit 格式 */
case DRM_FORMAT_P010:
input_fmts[0] = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
break;
default:
input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
break;
}
*num_input_fmts = 1;
return input_fmts;
}
static u32 *get_bus_output_format_for_auxdisp(struct drm_crtc_state *crtc_state, u32 *output_fmts, unsigned int *num_output_fmts){
struct device_node *crtc_port;
struct drm_plane_state *plane_state;
struct drm_framebuffer *fb = NULL;
struct drm_crtc *crtc = crtc_state->crtc;
if (crtc && crtc->port) {
crtc_port = crtc->port->parent;
if (crtc_port) {
/* 检查是否是 auxdisp */
if (!of_device_is_compatible(crtc_port, AUXDISP_DT_COMPATIBLE)) {
*num_output_fmts = 0;
return NULL;
}
}
}
/*
* AuxDisp CRTC framebuffer bus_format
*/
/* 获取 primary plane 的 framebuffer */
if (crtc_state->crtc && crtc_state->crtc->primary) {
plane_state = drm_atomic_get_new_plane_state(crtc_state->state,
crtc_state->crtc->primary);
if (plane_state)
fb = plane_state->fb;
}
if (!fb) {
*num_output_fmts = 0;
return NULL;
}
switch (fb->format->format) {
/* RGB 8bit 格式 */
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
output_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
break;
/* RGB 10bit 格式 */
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ABGR2101010:
output_fmts[0] = MEDIA_BUS_FMT_FIXED;
break;
/* RGB565 格式 */
case DRM_FORMAT_RGB565:
case DRM_FORMAT_BGR565:
output_fmts[0] = MEDIA_BUS_FMT_RGB565_1X16;
break;
/* YUV420 8bit 格式 */
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV21:
output_fmts[0] = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
break;
/* YUV420 10bit 格式 */
case DRM_FORMAT_P010:
output_fmts[0] = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
break;
default:
output_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
break;
}
*num_output_fmts = 1;
return output_fmts;
}
#endif
/* /*
* Possible output formats : * Possible output formats :
@@ -2742,6 +2914,11 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
if (!output_fmts) if (!output_fmts)
return NULL; return NULL;
#ifdef CONFIG_ZHIHE_AUXDISP
if(get_bus_output_format_for_auxdisp(crtc_state, output_fmts, num_output_fmts)){
return output_fmts;
}
#endif
/* If dw-hdmi is the first or only bridge, avoid negociating with ourselves */ /* If dw-hdmi is the first or only bridge, avoid negociating with ourselves */
if (list_is_singular(&bridge->encoder->bridge_chain) || if (list_is_singular(&bridge->encoder->bridge_chain) ||
list_is_first(&bridge->chain_node, &bridge->encoder->bridge_chain)) { list_is_first(&bridge->chain_node, &bridge->encoder->bridge_chain)) {
@@ -2866,6 +3043,12 @@ static u32 *dw_hdmi_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
if (!input_fmts) if (!input_fmts)
return NULL; return NULL;
#ifdef CONFIG_ZHIHE_AUXDISP
if(get_bus_input_format_for_auxdisp(crtc_state, input_fmts, num_input_fmts)){
return input_fmts;
}
#endif
switch (output_fmt) { switch (output_fmt) {
/* If MEDIA_BUS_FMT_FIXED is tested, return default bus format */ /* If MEDIA_BUS_FMT_FIXED is tested, return default bus format */
case MEDIA_BUS_FMT_FIXED: case MEDIA_BUS_FMT_FIXED:

View File

@@ -3,35 +3,35 @@
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#define ILI9881_PAGE(_page) DSI_DCS_WRITE(dsi, 0xff, 0x98, 0x81, _page) #define ILI9881_PAGE(_page) DSI_DCS_WRITE(dsi, 0xff, 0x98, 0x81, _page)
#define IILI9881_COMMAND(_cmd, _data...) DSI_DCS_WRITE(dsi, _cmd, _data) #define IILI9881_COMMAND(_cmd, _data...) DSI_DCS_WRITE(dsi, _cmd, _data)
#define DCS_CMD_READ_ID1 0xDA #define DCS_CMD_READ_ID1 0xDA
#define LT_8911_I2C_ADAPTER 3 #define LT_8911_I2C_ADAPTER 3
#define LT_8911_I2C_ADDR 0x45 #define LT_8911_I2C_ADDR 0x45
static struct i2c_mipi_dsi g_lt8911_mipi_dsi; static struct i2c_mipi_dsi g_lt8911_mipi_dsi;
static bool g_is_std_suspend __nosavedata; static bool g_is_std_suspend __nosavedata;
static const struct drm_display_mode lt8911_default_mode = { static const struct drm_display_mode lt8911_default_mode = {
.clock = 152840, .clock = 152840,
.hdisplay = 1920, .hdisplay = 1920,
.hsync_start = 1920 + 140, .hsync_start = 1920 + 140,
.hsync_end = 1920 + 140 + 160, .hsync_end = 1920 + 140 + 160,
.htotal = 1920 + 140 + 160 + 30, .htotal = 1920 + 140 + 160 + 30,
.vdisplay = 1080, .vdisplay = 1080,
.vsync_start = 1080 + 18, .vsync_start = 1080 + 18,
.vsync_end = 1080 + 18 + 28, .vsync_end = 1080 + 18 + 28,
.vtotal = 1080 + 18 + 28 + 6, .vtotal = 1080 + 18 + 28 + 6,
.width_mm = 110, .width_mm = 110,
.height_mm = 62, .height_mm = 62,
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
}; };
static struct panel_data lt8911_panel_data = { static struct panel_data lt8911_panel_data = {
.display_mode = &lt8911_default_mode, .display_mode = (struct drm_display_mode *)&lt8911_default_mode,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO_BURST, .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO_BURST,
.format = MIPI_DSI_FMT_RGB888, .format = MIPI_DSI_FMT_RGB888,
.lanes = 4, .lanes = 4,
@@ -65,8 +65,7 @@ static int mipi_timing[] = {
15284 /* pixel_clk / 10000 */ 15284 /* pixel_clk / 10000 */
}; };
static int lt8911_i2c_write(struct i2c_client *client, static int lt8911_i2c_write(struct i2c_client *client, uint8_t reg, uint8_t val)
uint8_t reg, uint8_t val)
{ {
int ret = -1; int ret = -1;
int retries = 0; int retries = 0;
@@ -121,6 +120,9 @@ static int lt8911_i2c_read(struct i2c_client *client, uint8_t reg)
static void lt8911_reset(struct i2c_mipi_dsi *md) static void lt8911_reset(struct i2c_mipi_dsi *md)
{ {
if (!gpio_is_valid(md->reset_pin))
return;
gpio_set_value(md->reset_pin, 0); gpio_set_value(md->reset_pin, 0);
msleep(md->rst_delay_ms); msleep(md->rst_delay_ms);
gpio_set_value(md->reset_pin, 1); gpio_set_value(md->reset_pin, 1);
@@ -503,24 +505,29 @@ static int panel_prepare(struct drm_panel *panel)
DBG_FUNC("lt8911exb enter\n"); DBG_FUNC("lt8911exb enter\n");
if(g_is_std_suspend){ if (md->prepared)
return 0;
if (g_is_std_suspend) {
DBG_FUNC("lt8911exb prepare under std mode, do not prepare\n"); DBG_FUNC("lt8911exb prepare under std mode, do not prepare\n");
return 0; return 0;
} }
if(md->client == NULL){ if (md->client == NULL) {
DBG_FUNC("lt8911exb i2c client still not ready\n"); DBG_FUNC("lt8911exb i2c client still not ready\n");
return 0; return 0;
} }
ret = regulator_enable(md->vspn3v3); if (md->vspn3v3) {
if(ret){ ret = regulator_enable(md->vspn3v3);
goto fail; if (ret)
goto fail;
} }
ret = regulator_enable(md->hsvcc); if (md->hsvcc) {
if(ret){ ret = regulator_enable(md->hsvcc);
goto fail; if (ret)
goto fail;
} }
//msleep(200); //msleep(200);
@@ -536,12 +543,18 @@ static int panel_prepare(struct drm_panel *panel)
lt8911_i2c_read(client, 0x01), lt8911_i2c_read(client, 0x01),
lt8911_i2c_read(client, 0x02)); lt8911_i2c_read(client, 0x02));
md->prepared = true;
return 0; return 0;
fail: fail:
gpio_set_value(md->reset_pin, 0); dev_err(&md->client->dev, "lt8911exb prepare failed: %d\n", ret);
regulator_disable(md->hsvcc); if (gpio_is_valid(md->reset_pin))
regulator_disable(md->vspn3v3); gpio_set_value(md->reset_pin, 0);
if (md->hsvcc)
regulator_disable(md->hsvcc);
if (md->vspn3v3)
regulator_disable(md->vspn3v3);
return ret; return ret;
} }
@@ -550,12 +563,19 @@ static int panel_unprepare(struct drm_panel *panel)
int ret = 0; int ret = 0;
struct i2c_mipi_dsi *md = panel_to_md(panel); struct i2c_mipi_dsi *md = panel_to_md(panel);
if (!md->prepared)
return 0;
DBG_FUNC("panel_unprepare enter\n"); DBG_FUNC("panel_unprepare enter\n");
gpio_set_value(md->reset_pin, 0); if (gpio_is_valid(md->reset_pin))
gpio_set_value(md->reset_pin, 0);
regulator_disable(md->hsvcc); if (md->hsvcc)
regulator_disable(md->vspn3v3); regulator_disable(md->hsvcc);
if (md->vspn3v3)
regulator_disable(md->vspn3v3);
md->prepared = false;
return ret; return ret;
} }
@@ -571,7 +591,8 @@ static int panel_enable(struct drm_panel *panel)
return 0; return 0;
} }
gpio_set_value(md->backlight_pin, 1); if (gpio_is_valid(md->backlight_pin))
gpio_set_value(md->backlight_pin, 1);
lt8911exb_cfg_set_mipi_timing(md); lt8911exb_cfg_set_mipi_timing(md);
lt8911exb_cfg_set_edp_timing(md); lt8911exb_cfg_set_edp_timing(md);
@@ -590,7 +611,8 @@ static int panel_disable(struct drm_panel *panel)
DBG_FUNC("panel_disable enter\n"); DBG_FUNC("panel_disable enter\n");
gpio_set_value(md->backlight_pin, 0); if (gpio_is_valid(md->backlight_pin))
gpio_set_value(md->backlight_pin, 0);
return ret; return ret;
} }
@@ -637,6 +659,11 @@ static int backlight_update(struct backlight_device *bd)
struct i2c_mipi_dsi *md = bl_get_data(bd); struct i2c_mipi_dsi *md = bl_get_data(bd);
int brightness = bd->props.brightness; int brightness = bd->props.brightness;
if (!md->prepared) {
dev_dbg(&bd->dev, "lcd not ready yet for setting its backlight!\n");
return -ENXIO;
}
if (bd->props.power != FB_BLANK_UNBLANK || if (bd->props.power != FB_BLANK_UNBLANK ||
bd->props.fb_blank != FB_BLANK_UNBLANK || bd->props.fb_blank != FB_BLANK_UNBLANK ||
(bd->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))) { (bd->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))) {
@@ -656,9 +683,6 @@ static const struct backlight_ops backlight_ops = {
static int lt8911_pm_notify(struct notifier_block *notify_block, static int lt8911_pm_notify(struct notifier_block *notify_block,
unsigned long mode, void *unused) unsigned long mode, void *unused)
{ {
struct i2c_mipi_dsi *ctx = container_of(
notify_block, struct i2c_mipi_dsi, pm_notify);
DBG_FUNC("pm_notify: mode (%ld)\n", mode); DBG_FUNC("pm_notify: mode (%ld)\n", mode);
switch (mode) { switch (mode) {
@@ -706,7 +730,6 @@ static int backlight_init(struct i2c_mipi_dsi *md)
static int i2c_md_probe(struct i2c_client *client) static int i2c_md_probe(struct i2c_client *client)
{ {
struct device *dev = &client->dev;
struct i2c_mipi_dsi *md = &g_lt8911_mipi_dsi; struct i2c_mipi_dsi *md = &g_lt8911_mipi_dsi;
DBG_FUNC("start"); DBG_FUNC("start");
@@ -746,52 +769,64 @@ static int lt8911_parse_dt(struct i2c_mipi_dsi *md)
struct mipi_dsi_device *dsi = md->dsi; struct mipi_dsi_device *dsi = md->dsi;
struct device_node *np = dsi->dev.of_node; struct device_node *np = dsi->dev.of_node;
md->hsvcc = devm_regulator_get(&dsi->dev, "hsvcc"); md->hsvcc = devm_regulator_get_optional(&dsi->dev, "hsvcc");
if (IS_ERR(md->hsvcc)) if (IS_ERR(md->hsvcc)) {
return dev_err_probe(&dsi->dev, PTR_ERR(md->hsvcc), if (PTR_ERR(md->hsvcc) == -ENODEV) {
"Failed to request hsvcc regulator\n"); DBG_FUNC("%s: hsvcc regulator not defined, continue without it\n", __func__);
md->hsvcc = NULL;
} else {
return dev_err_probe(&dsi->dev, PTR_ERR(md->hsvcc),
"Failed to request hsvcc regulator\n");
}
}
md->vspn3v3 = devm_regulator_get(&dsi->dev, "vspn3v3"); md->vspn3v3 = devm_regulator_get_optional(&dsi->dev, "vspn3v3");
if (IS_ERR(md->vspn3v3)) if (IS_ERR(md->vspn3v3)) {
return dev_err_probe(&dsi->dev, PTR_ERR(md->vspn3v3), if (PTR_ERR(md->vspn3v3) == -ENODEV) {
"Failed to request vspn3v3 regulator\n"); DBG_FUNC("%s: vspn3v3 regulator not defined, continue without it\n", __func__);
md->vspn3v3 = NULL;
} else {
return dev_err_probe(&dsi->dev, PTR_ERR(md->vspn3v3),
"Failed to request vspn3v3 regulator\n");
}
}
md->backlight_pin = of_get_named_gpio(np, md->backlight_pin = of_get_named_gpio(np,
"lt8911,backlight-gpio", "lt8911,backlight-gpio",
0); 0);
if (!gpio_is_valid(md->backlight_pin)) { if (!gpio_is_valid(md->backlight_pin)) {
DBG_FUNC("%s: backlight-gpio is invalid\n", __func__); DBG_FUNC("%s: backlight-gpio is invalid, continue without it\n", __func__);
return -EINVAL; md->backlight_pin = -EINVAL;
} else {
ret = devm_gpio_request_one(&dsi->dev,
md->backlight_pin,
GPIOF_DIR_OUT, NULL);
if (ret) {
DBG_FUNC("%s: failed to request backlight gpio\n",
__func__);
return ret;
}
gpio_set_value(md->backlight_pin, 0);
DBG_FUNC("%s: succeed to init backlight gpio\n", __func__);
} }
ret = devm_gpio_request_one(&dsi->dev,
md->backlight_pin,
GPIOF_DIR_OUT, NULL);
if (ret) {
DBG_FUNC("%s: failed to request backlight gpio\n",
__func__);
return ret;
}
gpio_set_value(md->backlight_pin, 0);
DBG_FUNC("%s: succeed to init backlight gpio\n", __func__);
md->irq_pin = of_get_named_gpio(np, md->irq_pin = of_get_named_gpio(np,
"lt8911,irq-gpio", 0); "lt8911,irq-gpio", 0);
if (!gpio_is_valid(md->irq_pin)) { if (!gpio_is_valid(md->irq_pin)) {
DBG_FUNC("%s: irq-gpio is invalid\n", __func__); DBG_FUNC("%s: irq-gpio is invalid, continue without it\n", __func__);
return -EINVAL; md->irq_pin = -EINVAL;
} else {
ret = devm_gpio_request_one(&dsi->dev,
md->irq_pin,
GPIOF_DIR_IN, NULL);
if (ret) {
DBG_FUNC("%s: failed to request irq gpio\n",
__func__);
return ret;
}
DBG_FUNC("%s: succeed to init irq gpio\n", __func__);
} }
ret = devm_gpio_request_one(&dsi->dev,
md->irq_pin,
GPIOF_DIR_IN, NULL);
if (ret) {
DBG_FUNC("%s: failed to request irq gpio\n",
__func__);
return ret;
}
DBG_FUNC("%s: succeed to init irq gpio\n", __func__);
ret = of_property_read_u32(np, "lt8911,rst-delay-ms", ret = of_property_read_u32(np, "lt8911,rst-delay-ms",
&md->rst_delay_ms); &md->rst_delay_ms);
if (ret < 0) { if (ret < 0) {
@@ -803,21 +838,21 @@ static int lt8911_parse_dt(struct i2c_mipi_dsi *md)
md->reset_pin = of_get_named_gpio(np, md->reset_pin = of_get_named_gpio(np,
"lt8911,reset-gpio", 0); "lt8911,reset-gpio", 0);
if (!gpio_is_valid(md->reset_pin)) { if (!gpio_is_valid(md->reset_pin)) {
DBG_FUNC("%s: reset-gpio is invalid\n", __func__); DBG_FUNC("%s: reset-gpio is invalid, continue without it\n", __func__);
return -EINVAL; md->reset_pin = -EINVAL;
} else {
ret = devm_gpio_request_one(&dsi->dev,
md->reset_pin,
GPIOF_DIR_OUT, NULL);
if (ret) {
DBG_FUNC("%s: failed to request reset gpio\n",
__func__);
return ret;
}
gpio_set_value(md->reset_pin, 0);
DBG_FUNC("%s: succeed to init reset gpio\n", __func__);
} }
ret = devm_gpio_request_one(&dsi->dev,
md->reset_pin,
GPIOF_DIR_OUT, NULL);
if (ret) {
DBG_FUNC("%s: failed to request reset gpio\n",
__func__);
return ret;
}
gpio_set_value(md->reset_pin, 0);
DBG_FUNC("%s: succeed to init reset gpio\n", __func__);
if (of_property_read_u32(np, "lt8911,edp-lane-cnt", if (of_property_read_u32(np, "lt8911,edp-lane-cnt",
&md->edp_lane_cnt)) { &md->edp_lane_cnt)) {
DBG_FUNC("%s: miss edp-lane-cnt property in dts\n", DBG_FUNC("%s: miss edp-lane-cnt property in dts\n",
@@ -837,20 +872,17 @@ static int lt8911_parse_dt(struct i2c_mipi_dsi *md)
* 6 bit: 262K colors * 6 bit: 262K colors
* 8 bit: 16.7M colors * 8 bit: 16.7M colors
*/ */
if (of_property_read_u32(np, "lt8911,edp-depth", if (of_property_read_u32(np, "lt8911,edp-depth", &md->edp_depth)) {
&md->edp_depth)) {
DBG_FUNC("%s: miss edp-depth property in dts\n", DBG_FUNC("%s: miss edp-depth property in dts\n",
__func__); __func__);
md->edp_depth = 8; md->edp_depth = 8;
} }
return ret; return ret;
} }
static const struct of_device_id i2c_md_of_ids[] = { static const struct of_device_id i2c_md_of_ids[] = {
{ { .compatible = "i2c,lt8911", },
.compatible = "i2c,lt8911",
},
{ } { }
}; };
MODULE_DEVICE_TABLE(of, i2c_md_of_ids); MODULE_DEVICE_TABLE(of, i2c_md_of_ids);
@@ -868,8 +900,7 @@ static int edpi2c_resume(struct device *dev)
} }
static const struct dev_pm_ops edpi2c_pm_ops = { static const struct dev_pm_ops edpi2c_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(edpi2c_suspend, SET_LATE_SYSTEM_SLEEP_PM_OPS(edpi2c_suspend, edpi2c_resume)
edpi2c_resume)
}; };
#define EDPI2C_PM_OPS &edpi2c_pm_ops #define EDPI2C_PM_OPS &edpi2c_pm_ops
@@ -891,8 +922,6 @@ static struct i2c_driver i2c_md_driver = {
.shutdown = i2c_md_shutdown, .shutdown = i2c_md_shutdown,
}; };
module_i2c_driver(i2c_md_driver);
static int lt8911_dsi_probe(struct mipi_dsi_device *dsi) static int lt8911_dsi_probe(struct mipi_dsi_device *dsi)
{ {
int ret; int ret;
@@ -900,21 +929,19 @@ static int lt8911_dsi_probe(struct mipi_dsi_device *dsi)
ctx = &g_lt8911_mipi_dsi; ctx = &g_lt8911_mipi_dsi;
if(ctx == NULL){ if (ctx == NULL)
return -ENOMEM; return -ENOMEM;
}
if(ctx->client == NULL){ if (ctx->client == NULL)
return -EPROBE_DEFER; return -EPROBE_DEFER;
}
g_is_std_suspend = false; g_is_std_suspend = false;
ctx->dsi = dsi; ctx->dsi = dsi;
ctx->desc = &lt8911_panel_data; ctx->desc = &lt8911_panel_data;
ret = lt8911_parse_dt(ctx); ret = lt8911_parse_dt(ctx);
if (ret) { if (ret) {
DBG_FUNC("%s: failed to parse device tree\n", __func__); dev_err(&dsi->dev, "%s: failed to parse device tree\n", __func__);
return ret; return ret;
} }
@@ -927,9 +954,7 @@ static int lt8911_dsi_probe(struct mipi_dsi_device *dsi)
//ctx->panel_data->set_dsi(ctx->dsi); //ctx->panel_data->set_dsi(ctx->dsi);
drm_panel_init(&ctx->panel, &dsi->dev, &panel_funcs, DRM_MODE_CONNECTOR_DSI); drm_panel_init(&ctx->panel, &dsi->dev, &panel_funcs, DRM_MODE_CONNECTOR_DSI);
ret = drm_panel_of_backlight(&ctx->panel); drm_panel_of_backlight(&ctx->panel);
if (ret)
return ret;
drm_panel_add(&ctx->panel); drm_panel_add(&ctx->panel);
@@ -940,11 +965,10 @@ static int lt8911_dsi_probe(struct mipi_dsi_device *dsi)
ret = register_pm_notifier(&ctx->pm_notify); ret = register_pm_notifier(&ctx->pm_notify);
if (ret) if (ret)
DBG_FUNC("register_pm_notifier failed: %d\n", ret); dev_err(&dsi->dev, "register_pm_notifier failed: %d\n", ret);
ret = mipi_dsi_attach(dsi); ret = mipi_dsi_attach(dsi);
if (ret < 0) if (ret < 0) {
{
drm_panel_remove(&ctx->panel); drm_panel_remove(&ctx->panel);
} }
@@ -959,8 +983,6 @@ static void lt8911_dsi_remove(struct mipi_dsi_device *dsi)
mipi_dsi_detach(dsi); mipi_dsi_detach(dsi);
drm_panel_remove(&ctx->panel); drm_panel_remove(&ctx->panel);
return;
} }
static void lt8911_dsi_shutdown(struct mipi_dsi_device *dsi) static void lt8911_dsi_shutdown(struct mipi_dsi_device *dsi)
@@ -975,15 +997,47 @@ static const struct of_device_id lt8911_of_match[] = {
MODULE_DEVICE_TABLE(of, lt8911_of_match); MODULE_DEVICE_TABLE(of, lt8911_of_match);
static struct mipi_dsi_driver lt8911_dsi_driver = { static struct mipi_dsi_driver lt8911_dsi_driver = {
.probe = lt8911_dsi_probe, .probe = lt8911_dsi_probe,
.remove = lt8911_dsi_remove, .remove = lt8911_dsi_remove,
.shutdown = lt8911_dsi_shutdown, .shutdown = lt8911_dsi_shutdown,
.driver = { .driver = {
.name = "panel-lt8911", .name = "panel-lt8911",
.of_match_table = lt8911_of_match, .of_match_table = lt8911_of_match,
}, },
}; };
module_mipi_dsi_driver(lt8911_dsi_driver);
static int __init lt8911_drivers_init(void)
{
int ret;
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
ret = mipi_dsi_driver_register(&lt8911_dsi_driver);
if (ret) {
pr_err("lt8911: failed to add dsi driver: %d\n", ret);
return ret;
}
}
ret = i2c_add_driver(&i2c_md_driver);
if (ret) {
pr_err("lt8911: failed to add i2c driver: %d\n", ret);
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
mipi_dsi_driver_unregister(&lt8911_dsi_driver);
}
return ret;
}
static void __exit lt8911_drivers_exit(void)
{
i2c_del_driver(&i2c_md_driver);
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
mipi_dsi_driver_unregister(&lt8911_dsi_driver);
}
module_init(lt8911_drivers_init);
module_exit(lt8911_drivers_exit);
MODULE_DESCRIPTION("LT8911 Controller Driver"); MODULE_DESCRIPTION("LT8911 Controller Driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");

View File

@@ -82,6 +82,7 @@ struct i2c_mipi_dsi {
// backlight // backlight
int brightness; int brightness;
bool prepared;
}; };
#define panel_to_md(_p) container_of(_p, struct i2c_mipi_dsi, panel) #define panel_to_md(_p) container_of(_p, struct i2c_mipi_dsi, panel)

View File

@@ -69,3 +69,13 @@ config VERISILICON_DEC
This is a decompression function which reads compressed pixels from This is a decompression function which reads compressed pixels from
external memory (DDR or SRAM) under DPU's control, then it decompress external memory (DDR or SRAM) under DPU's control, then it decompress
comprssed pixels before returing these pixels to DPU. comprssed pixels before returing these pixels to DPU.
config ZHIHE_AUXDISP
bool "Auxiliary Display CRTC support"
depends on DRM_VERISILICON
help
Enable support for auxiliary display CRTC device.
This CRTC can connect to HDMI and DisplayPort outputs,
providing additional display pipeline for external monitors.
It supports up to 10-bit color depth and multiple color formats
including RGB444, YCbCr444, and YCbCr422.

View File

@@ -15,5 +15,6 @@ vs_drm-$(CONFIG_VERISILICON_DW_HDMI_TH1520) += dw_hdmi-th1520.o
vs_drm-$(CONFIG_VERISILICON_DW_DP_P100) += dw_dp.o vs_drm-$(CONFIG_VERISILICON_DW_DP_P100) += dw_dp.o
vs_drm-$(CONFIG_VERISILICON_MMU) += vs_dc_mmu.o vs_drm-$(CONFIG_VERISILICON_MMU) += vs_dc_mmu.o
vs_drm-$(CONFIG_VERISILICON_DEC) += vs_dc_dec.o vs_drm-$(CONFIG_VERISILICON_DEC) += vs_dc_dec.o
vs_drm-$(CONFIG_ZHIHE_AUXDISP) += auxdisp_crtc.o
obj-$(CONFIG_DRM_VERISILICON) += vs_drm.o obj-$(CONFIG_DRM_VERISILICON) += vs_drm.o

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/extcon-provider.h> #include <linux/extcon-provider.h>
#include <linux/extcon.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/of_device.h> #include <linux/of_device.h>
@@ -47,9 +48,6 @@
#include <sound/hdmi-codec.h> #include <sound/hdmi-codec.h>
#include <uapi/linux/videodev2.h> #include <uapi/linux/videodev2.h>
#define NO_PHY 1
#define MAX_FREQ 540000
#define LANES_NUM 4
#define RK_IF_PROP_COLOR_DEPTH "color_depth" #define RK_IF_PROP_COLOR_DEPTH "color_depth"
#define RK_IF_PROP_COLOR_FORMAT "color_format" #define RK_IF_PROP_COLOR_FORMAT "color_format"
@@ -530,7 +528,7 @@ struct dw_dp_compliance {
bool test_active; bool test_active;
}; };
struct p100_drm_sub_dev { struct a210_drm_sub_dev {
struct list_head list; struct list_head list;
struct drm_connector *connector; struct drm_connector *connector;
struct device_node *of_node; struct device_node *of_node;
@@ -561,7 +559,9 @@ struct dw_dp {
bool force_hpd; bool force_hpd;
struct dw_dp_hotplug hotplug; struct dw_dp_hotplug hotplug;
struct mutex irq_lock; struct mutex irq_lock;
struct extcon_dev *extcon; struct extcon_dev *extcon; /* Extcon provider for audio/userspace */
struct extcon_dev *phy_extcon; /* Extcon consumer from PHY */
struct notifier_block phy_extcon_nb; /* Notifier for PHY extcon events */
struct drm_bridge bridge; struct drm_bridge bridge;
struct drm_connector connector; struct drm_connector connector;
@@ -589,7 +589,7 @@ struct dw_dp {
struct drm_property *hdr_panel_metadata_property; struct drm_property *hdr_panel_metadata_property;
struct drm_property_blob *hdr_panel_blob_ptr; struct drm_property_blob *hdr_panel_blob_ptr;
struct p100_drm_sub_dev sub_dev; struct a210_drm_sub_dev sub_dev;
struct dw_dp_hdcp hdcp; struct dw_dp_hdcp hdcp;
int eotf_type; int eotf_type;
@@ -696,15 +696,6 @@ static const struct dw_dp_output_format possible_output_fmts[] = {
DPTX_VM_RGB_6BIT, 6, 18 }, DPTX_VM_RGB_6BIT, 6, 18 },
}; };
static unsigned long g_init_threshold = 0;
static unsigned long g_freqs = 0;
//void rockchip_drm_register_sub_dev(struct rockchip_drm_sub_dev *sub_dev)
//{
// mutex_lock(&rockchip_drm_sub_dev_lock);
// list_add_tail(&sub_dev->list, &rockchip_drm_sub_dev_list);
// mutex_unlock(&rockchip_drm_sub_dev_lock);
//}
uint32_t rockchip_drm_of_find_possible_crtcs(struct drm_device *dev, uint32_t rockchip_drm_of_find_possible_crtcs(struct drm_device *dev,
struct device_node *port) struct device_node *port)
{ {
@@ -884,7 +875,7 @@ static int dw_dp_hdcp2_auth_check(struct dw_dp *dp)
dp->hdcp.hdcp2_encrypted = true; dp->hdcp.hdcp2_encrypted = true;
dev_err(dp->dev, "HDCP2 authentication succeed\n"); dev_dbg(dp->dev, "HDCP2 authentication succeed\n");
return ret; return ret;
} }
@@ -961,7 +952,7 @@ static int __maybe_unused dw_dp_hdcp_auth_check(struct dw_dp *dp)
} else { } else {
regmap_write(dp->regmap, DPTX_HDCPAPIINTCLR, HDCP_ENGAGED); regmap_write(dp->regmap, DPTX_HDCPAPIINTCLR, HDCP_ENGAGED);
dp->hdcp.hdcp_encrypted = true; dp->hdcp.hdcp_encrypted = true;
dev_err(dp->dev, "HDCP authentication succeed\n"); dev_dbg(dp->dev, "HDCP authentication succeed\n");
} }
return ret; return ret;
@@ -1611,7 +1602,7 @@ static int dw_dp_connector_atomic_check(struct drm_connector *conn,
dp_old_state = connector_to_dp_state(old_state); dp_old_state = connector_to_dp_state(old_state);
dp_new_state = connector_to_dp_state(new_state); dp_new_state = connector_to_dp_state(new_state);
//dw_dp_hdcp_atomic_check(conn, state); dw_dp_hdcp_atomic_check(conn, state);
if (!new_state->crtc) if (!new_state->crtc)
return 0; return 0;
@@ -1636,7 +1627,7 @@ static int dw_dp_connector_atomic_check(struct drm_connector *conn,
if ((dp_old_state->bpc != dp_new_state->bpc) || if ((dp_old_state->bpc != dp_new_state->bpc) ||
(dp_old_state->color_format != dp_new_state->color_format)) { (dp_old_state->color_format != dp_new_state->color_format)) {
if ((dp_old_state->bpc == 0) && (dp_new_state->bpc == 0)) if ((dp_old_state->bpc == 0) && (dp_new_state->bpc == 0))
dev_err(dp->dev, "still auto set color mode\n"); dev_dbg(dp->dev, "still auto set color mode\n");
else else
crtc_state->mode_changed = true; crtc_state->mode_changed = true;
} }
@@ -1758,18 +1749,12 @@ static int dw_dp_link_probe(struct dw_dp *dp)
!!(dpcd & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED); !!(dpcd & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
link->revision = link->dpcd[DP_DPCD_REV]; link->revision = link->dpcd[DP_DPCD_REV];
#if NO_PHY
//link->rate = MAX_FREQ;
//link->lanes = LANES_NUM;
link->rate = drm_dp_max_link_rate(link->dpcd);
link->lanes = min_t(u8, LANES_NUM, drm_dp_max_lane_count(link->dpcd));
#else
link->rate = min_t(u32, min(dp->max_link_rate, dp->phy->attrs.max_link_rate * 100), link->rate = min_t(u32, min(dp->max_link_rate, dp->phy->attrs.max_link_rate * 100),
drm_dp_max_link_rate(link->dpcd)); drm_dp_max_link_rate(link->dpcd));
link->lanes = min_t(u8, phy_get_bus_width(dp->phy), link->lanes = min_t(u8, phy_get_bus_width(dp->phy),
drm_dp_max_lane_count(link->dpcd)); drm_dp_max_lane_count(link->dpcd));
#endif
link->caps.enhanced_framing = drm_dp_enhanced_frame_cap(link->dpcd); link->caps.enhanced_framing = drm_dp_enhanced_frame_cap(link->dpcd);
link->caps.tps3_supported = drm_dp_tps3_supported(link->dpcd); link->caps.tps3_supported = drm_dp_tps3_supported(link->dpcd);
link->caps.tps4_supported = drm_dp_tps4_supported(link->dpcd); link->caps.tps4_supported = drm_dp_tps4_supported(link->dpcd);
@@ -1786,9 +1771,7 @@ static int dw_dphy_set_voltage_pre_level(struct dw_dp *dp, int lane_id, int leve
static int dw_dp_phy_update_vs_emph(struct dw_dp *dp, unsigned int rate, unsigned int lanes, static int dw_dp_phy_update_vs_emph(struct dw_dp *dp, unsigned int rate, unsigned int lanes,
struct drm_dp_link_train_set *train_set) struct drm_dp_link_train_set *train_set)
{ {
#if !NO_PHY
union phy_configure_opts phy_cfg; union phy_configure_opts phy_cfg;
#endif
unsigned int *vs, *pe; unsigned int *vs, *pe;
u8 buf[4]; u8 buf[4];
int i, ret; int i, ret;
@@ -1796,19 +1779,11 @@ static int dw_dp_phy_update_vs_emph(struct dw_dp *dp, unsigned int rate, unsigne
vs = train_set->voltage_swing; vs = train_set->voltage_swing;
pe = train_set->pre_emphasis; pe = train_set->pre_emphasis;
// unsigned int phy_ctl_val;
// regmap_read(dp->regmap, DPTX_PHYIF_CTRL, &phy_ctl_val);
// regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_POWERDOWN,
// FIELD_PREP(PHY_POWERDOWN, 0x3));
//
for (i = 0; i < lanes; i++) { for (i = 0; i < lanes; i++) {
dw_dphy_set_voltage_sw_level(dp, i, vs[i]); dw_dphy_set_voltage_sw_level(dp, i, vs[i]);
dw_dphy_set_voltage_pre_level(dp, i, pe[i]); dw_dphy_set_voltage_pre_level(dp, i, pe[i]);
} }
// regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_POWERDOWN,
// FIELD_PREP(PHY_POWERDOWN, 0x0));
#if !NO_PHY
for (i = 0; i < lanes; i++) { for (i = 0; i < lanes; i++) {
phy_cfg.dp.voltage[i] = vs[i]; phy_cfg.dp.voltage[i] = vs[i];
phy_cfg.dp.pre[i] = pe[i]; phy_cfg.dp.pre[i] = pe[i];
@@ -1821,9 +1796,9 @@ static int dw_dp_phy_update_vs_emph(struct dw_dp *dp, unsigned int rate, unsigne
phy_cfg.dp.set_voltages = true; phy_cfg.dp.set_voltages = true;
ret = phy_configure(dp->phy, &phy_cfg); ret = phy_configure(dp->phy, &phy_cfg);
if (ret) if (ret) {
return ret; return ret;
#endif }
for (i = 0; i < lanes; i++) { for (i = 0; i < lanes; i++) {
buf[i] = (vs[i] << DP_TRAIN_VOLTAGE_SWING_SHIFT) | buf[i] = (vs[i] << DP_TRAIN_VOLTAGE_SWING_SHIFT) |
@@ -1866,7 +1841,7 @@ static int dw_dphy_set_rate(struct dw_dp *dp, unsigned int rate)
val = 3; val = 3;
break; break;
default: default:
dev_err(dp->dev, "%s, %d, Error, dp unsopport rate %u\n", __func__, __LINE__, rate); dev_err(dp->dev, "Error, dp unsopport rate %u\n", rate);
return -1; return -1;
} }
@@ -1877,7 +1852,6 @@ static int dw_dphy_set_rate(struct dw_dp *dp, unsigned int rate)
static int dw_dphy_set_voltage_sw_level(struct dw_dp *dp, int lane_id, int level) static int dw_dphy_set_voltage_sw_level(struct dw_dp *dp, int lane_id, int level)
{ {
if (level < 0 || level > 3) { if (level < 0 || level > 3) {
dev_err(dp->dev, "%s, %d, Error, dp sw unsopport level %d\n", __func__, __LINE__, level);
return -1; return -1;
} }
@@ -1897,7 +1871,7 @@ static int dw_dphy_set_voltage_sw_level(struct dw_dp *dp, int lane_id, int level
static int dw_dphy_set_voltage_pre_level(struct dw_dp *dp, int lane_id, int level) static int dw_dphy_set_voltage_pre_level(struct dw_dp *dp, int lane_id, int level)
{ {
if (level < 0 || level > 3) { if (level < 0 || level > 3) {
dev_err(dp->dev, "%s, %d, Error, dp pre unsopport level%d\n", __func__, __LINE__, level); dev_err(dp->dev, "Error, dp pre unsopport level%d\n", level);
return -1; return -1;
} }
@@ -1918,26 +1892,11 @@ static int dw_dp_phy_configure(struct dw_dp *dp, unsigned int rate,
unsigned int lanes, bool ssc) unsigned int lanes, bool ssc)
{ {
/* Move PHY to P3 */ /* Move PHY to P3 */
unsigned int phy_ctl_val = 0, count = 10;
regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_POWERDOWN, regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_POWERDOWN,
FIELD_PREP(PHY_POWERDOWN, 0x3)); FIELD_PREP(PHY_POWERDOWN, 0x3));
regmap_read(dp->regmap, DPTX_PHYIF_CTRL, &phy_ctl_val);
while((PHY_BUSY & phy_ctl_val) && count) {
regmap_read(dp->regmap, DPTX_PHYIF_CTRL, &phy_ctl_val);
count--;
dev_dbg(dp->dev, "dp wait phy busy 0x%lx\n", (PHY_BUSY & phy_ctl_val));
udelay(100);
}
if (PHY_BUSY & phy_ctl_val) {
dev_err(dp->dev, "%s, %d, Error, phy is busy\n", __func__, __LINE__);
}
dw_dphy_set_rate(dp, rate); dw_dphy_set_rate(dp, rate);
#if !NO_PHY
union phy_configure_opts phy_cfg; union phy_configure_opts phy_cfg;
int ret; int ret;
phy_cfg.dp.lanes = lanes; phy_cfg.dp.lanes = lanes;
@@ -1949,7 +1908,6 @@ static int dw_dp_phy_configure(struct dw_dp *dp, unsigned int rate,
ret = phy_configure(dp->phy, &phy_cfg); ret = phy_configure(dp->phy, &phy_cfg);
if (ret) if (ret)
return ret; return ret;
#endif
regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_LANES, regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_LANES,
FIELD_PREP(PHY_LANES, lanes / 2)); FIELD_PREP(PHY_LANES, lanes / 2));
@@ -2066,7 +2024,6 @@ static int dw_dp_link_train_set_pattern(struct dw_dp *dp, u32 pattern)
ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
buf | pattern); buf | pattern);
if (ret < 0) { if (ret < 0) {
dev_err(dp->dev, "%s, %d, dpct write error %d\n", __func__, __LINE__, ret);
return ret; return ret;
} }
@@ -2238,6 +2195,7 @@ static int dw_dp_link_downgrade(struct dw_dp *dp)
{ {
struct dw_dp_link *link = &dp->link; struct dw_dp_link *link = &dp->link;
struct dw_dp_video *video = &dp->video; struct dw_dp_video *video = &dp->video;
u32 rate = link->rate;
switch (link->rate) { switch (link->rate) {
case 162000: case 162000:
@@ -2253,9 +2211,11 @@ static int dw_dp_link_downgrade(struct dw_dp *dp)
break; break;
} }
/*If the downgrade fails, retry using the previous rate. */
if (!dw_dp_bandwidth_ok(dp, &video->mode, video->bpp, link->lanes, if (!dw_dp_bandwidth_ok(dp, &video->mode, video->bpp, link->lanes,
link->rate)) link->rate)) {
return -E2BIG; link->rate = rate;
}
return 0; return 0;
} }
@@ -2267,6 +2227,10 @@ static int dw_dp_link_train_full(struct dw_dp *dp)
retry: retry:
dw_dp_link_train_init(&link->train); dw_dp_link_train_init(&link->train);
dev_dbg(dp->dev, "full-training link: %u lane%s at %u MHz\n",
link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
ret = dw_dp_link_configure(dp); ret = dw_dp_link_configure(dp);
if (ret < 0) { if (ret < 0) {
dev_err(dp->dev, "failed to configure DP link: %d\n", ret); dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
@@ -2280,11 +2244,10 @@ retry:
} }
if (!link->train.clock_recovered) { if (!link->train.clock_recovered) {
dev_err(dp->dev, "clock recovery failed, downgrading link\n"); dev_info(dp->dev, "clock recovery failed, downgrading link, retry\n");
ret = dw_dp_link_downgrade(dp); ret = dw_dp_link_downgrade(dp);
if (ret < 0) { if (ret < 0) {
dev_err(dp->dev, "downgrade failed, goto out\n");
goto out; goto out;
} else } else
goto retry; goto retry;
@@ -2319,6 +2282,9 @@ static int dw_dp_link_train_fast(struct dw_dp *dp)
dw_dp_link_train_init(&link->train); dw_dp_link_train_init(&link->train);
dev_dbg(dp->dev, "fast-training link: %u lane%s at %u MHz\n",
link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
ret = dw_dp_link_configure(dp); ret = dw_dp_link_configure(dp);
if (ret < 0) { if (ret < 0) {
dev_err(dp->dev, "failed to configure DP link: %d\n", ret); dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
@@ -2665,12 +2631,11 @@ static int dw_dp_video_enable(struct dw_dp *dp)
u8 color_format = video->color_format; u8 color_format = video->color_format;
u8 bpc = video->bpc; u8 bpc = video->bpc;
u8 pixel_mode = video->pixel_mode; u8 pixel_mode = video->pixel_mode;
u8 bpp = video->bpp, vic; u8 bpp = video->bpp, init_threshold, vic;
u32 init_threshold;
u32 hactive, hblank, h_sync_width, h_front_porch; u32 hactive, hblank, h_sync_width, h_front_porch;
u32 vactive, vblank, v_sync_width, v_front_porch; u32 vactive, vblank, v_sync_width, v_front_porch;
u32 vstart = mode->vsync_end- mode->vdisplay; u32 vstart = mode->vtotal - mode->vsync_start;
u32 hstart = mode->hsync_end- mode->hdisplay; u32 hstart = mode->htotal - mode->hsync_start;
u32 peak_stream_bandwidth, link_bandwidth; u32 peak_stream_bandwidth, link_bandwidth;
u32 average_bytes_per_tu, average_bytes_per_tu_frac; u32 average_bytes_per_tu, average_bytes_per_tu_frac;
u32 ts, hblank_interval; u32 ts, hblank_interval;
@@ -2697,7 +2662,6 @@ static int dw_dp_video_enable(struct dw_dp *dp)
regmap_write(dp->regmap, DPTX_VINPUT_POLARITY_CTRL, value); regmap_write(dp->regmap, DPTX_VINPUT_POLARITY_CTRL, value);
/* Configure DPTX_VIDEO_CONFIG1 register */ /* Configure DPTX_VIDEO_CONFIG1 register */
hactive = mode->hdisplay; hactive = mode->hdisplay;
hblank = mode->htotal - mode->hdisplay; hblank = mode->htotal - mode->hdisplay;
value = FIELD_PREP(HACTIVE, hactive) | FIELD_PREP(HBLANK, hblank); value = FIELD_PREP(HACTIVE, hactive) | FIELD_PREP(HBLANK, hblank);
@@ -2717,7 +2681,6 @@ static int dw_dp_video_enable(struct dw_dp *dp)
/* Configure DPTX_VIDEO_CONFIG2 register */ /* Configure DPTX_VIDEO_CONFIG2 register */
vblank = mode->vtotal - mode->vdisplay; vblank = mode->vtotal - mode->vdisplay;
vactive = mode->vdisplay; vactive = mode->vdisplay;
regmap_write(dp->regmap, DPTX_VIDEO_CONFIG2, regmap_write(dp->regmap, DPTX_VIDEO_CONFIG2,
FIELD_PREP(VBLANK, vblank) | FIELD_PREP(VACTIVE, vactive)); FIELD_PREP(VBLANK, vblank) | FIELD_PREP(VACTIVE, vactive));
@@ -2734,16 +2697,15 @@ static int dw_dp_video_enable(struct dw_dp *dp)
regmap_write(dp->regmap, DPTX_VIDEO_CONFIG4, regmap_write(dp->regmap, DPTX_VIDEO_CONFIG4,
FIELD_PREP(V_SYNC_WIDTH, v_sync_width) | FIELD_PREP(V_SYNC_WIDTH, v_sync_width) |
FIELD_PREP(V_FRONT_PORCH, v_front_porch)); FIELD_PREP(V_FRONT_PORCH, v_front_porch));
/* Configure DPTX_VIDEO_CONFIG5 register */ /* Configure DPTX_VIDEO_CONFIG5 register */
peak_stream_bandwidth = mode->clock * bpp / 8; peak_stream_bandwidth = mode->clock * bpp / 8;
link_bandwidth = (link->rate / 1000) * link->lanes; link_bandwidth = (link->rate / 1000) * link->lanes;
ts = peak_stream_bandwidth * 64 / link_bandwidth; ts = peak_stream_bandwidth * 64 / link_bandwidth;
average_bytes_per_tu = ts / 1000; average_bytes_per_tu = ts / 1000;
average_bytes_per_tu_frac = ts - average_bytes_per_tu * 1000; average_bytes_per_tu_frac = ts / 100 - average_bytes_per_tu * 10;
average_bytes_per_tu_frac = average_bytes_per_tu_frac / 100;
if (pixel_mode == DPTX_MP_SINGLE_PIXEL) { if (pixel_mode == DPTX_MP_SINGLE_PIXEL) {
if (average_bytes_per_tu < 16) if (average_bytes_per_tu < 6)
init_threshold = 32; init_threshold = 32;
else if (hblank <= 80 && color_format != DRM_COLOR_FORMAT_YCBCR420) else if (hblank <= 80 && color_format != DRM_COLOR_FORMAT_YCBCR420)
init_threshold = 12; init_threshold = 12;
@@ -2751,13 +2713,64 @@ static int dw_dp_video_enable(struct dw_dp *dp)
init_threshold = 3; init_threshold = 3;
else else
init_threshold = 16; init_threshold = 16;
} } else {
u32 t1 = 0, t2 = 0, t3 = 0;
if (g_init_threshold) { switch (bpc) {
init_threshold = g_init_threshold; case 6:
t1 = (4 * 1000 / 9) * link->lanes;
break;
case 8:
if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
t1 = (1000 / 2) * link->lanes;
} else {
if (pixel_mode == DPTX_MP_DUAL_PIXEL)
t1 = (1000 / 3) * link->lanes;
else
t1 = (3000 / 16) * link->lanes;
}
break;
case 10:
if (color_format == DRM_COLOR_FORMAT_YCBCR422)
t1 = (2000 / 5) * link->lanes;
else
t1 = (4000 / 15) * link->lanes;
break;
case 12:
if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
if (pixel_mode == DPTX_MP_DUAL_PIXEL)
t1 = (1000 / 6) * link->lanes;
else
t1 = (1000 / 3) * link->lanes;
} else {
t1 = (2000 / 9) * link->lanes;
}
break;
case 16:
if (color_format != DRM_COLOR_FORMAT_YCBCR422 &&
pixel_mode == DPTX_MP_DUAL_PIXEL)
t1 = (1000 / 6) * link->lanes;
else
t1 = (1000 / 4) * link->lanes;
break;
default:
return -EINVAL;
}
if (color_format == DRM_COLOR_FORMAT_YCBCR420)
t2 = (link->rate / 4) * 1000 / (mode->clock / 2);
else
t2 = (link->rate / 4) * 1000 / mode->clock;
if (average_bytes_per_tu_frac)
t3 = average_bytes_per_tu + 1;
else
t3 = average_bytes_per_tu;
init_threshold = t1 * t2 * t3 / (1000 * 1000);
if (init_threshold <= 16 || average_bytes_per_tu < 10)
init_threshold = 40;
} }
average_bytes_per_tu_frac &= 0xf;
regmap_write(dp->regmap, DPTX_VIDEO_CONFIG5, regmap_write(dp->regmap, DPTX_VIDEO_CONFIG5,
FIELD_PREP(INIT_THRESHOLD_HI, init_threshold >> 6) | FIELD_PREP(INIT_THRESHOLD_HI, init_threshold >> 6) |
FIELD_PREP(AVERAGE_BYTES_PER_TU_FRAC, average_bytes_per_tu_frac) | FIELD_PREP(AVERAGE_BYTES_PER_TU_FRAC, average_bytes_per_tu_frac) |
@@ -2767,6 +2780,7 @@ static int dw_dp_video_enable(struct dw_dp *dp)
/* Configure DPTX_VIDEO_HBLANK_INTERVAL register */ /* Configure DPTX_VIDEO_HBLANK_INTERVAL register */
hblank_interval = hblank * (link->rate / 4) / mode->clock; hblank_interval = hblank * (link->rate / 4) / mode->clock;
regmap_write(dp->regmap, DPTX_VIDEO_HBLANK_INTERVAL, regmap_write(dp->regmap, DPTX_VIDEO_HBLANK_INTERVAL,
FIELD_PREP(HBLANK_INTERVAL_EN, 1) |
FIELD_PREP(HBLANK_INTERVAL, hblank_interval)); FIELD_PREP(HBLANK_INTERVAL, hblank_interval));
/* Video stream enable */ /* Video stream enable */
@@ -2808,6 +2822,63 @@ static irqreturn_t dw_dp_hpd_irq_handler(int irq, void *arg)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/*
Scenario HPD_STATE IRQ_HPD DP Host Action
Display insertion 01 0 Long HPD
Display removal 10 0 Long HPD
Link status change 1 1 Short HPD
EDID update 1 1 Short HPD
Resolution switch 1 1 Short HPD
*/
static int dw_dp_phy_extcon_notifier(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct dw_dp *dp = container_of(nb, struct dw_dp, phy_extcon_nb);
bool hpd_state = !!event;
bool current_hpd;
dev_dbg(dp->dev, "PHY extcon HPD notification: %s (event=%lu)\n",
hpd_state ? "connected" : "disconnected", event);
mutex_lock(&dp->irq_lock);
/* Get current HPD status */
current_hpd = dp->hotplug.status;
/*
* Distinguish between long HPD and short HPD:
* - If state changes long HPD (plug/unplug)
* - If state unchanged and state=true short HPD (IRQ pulse)
*/
if (current_hpd == hpd_state && hpd_state) {
/* State unchanged → short HPD */
dp->hotplug.long_hpd = false;
dev_dbg(dp->dev, "Short HPD detected (IRQ pulse)\n");
if (!current_hpd)
return NOTIFY_OK;
} else {
/* State changed → long HPD */
dp->hotplug.long_hpd = true;
dp->hotplug.status = hpd_state;
dev_dbg(dp->dev, "Long HPD detected: %s\n",
hpd_state ? "plug" : "unplug");
}
mutex_unlock(&dp->irq_lock);
/* Schedule HPD work queue */
schedule_work(&dp->hpd_work);
return NOTIFY_OK;
}
static void dw_dp_hpd_init(struct dw_dp *dp) static void dw_dp_hpd_init(struct dw_dp *dp)
{ {
dp->hotplug.status = dw_dp_detect(dp); dp->hotplug.status = dw_dp_detect(dp);
@@ -2842,13 +2913,6 @@ static void dw_dp_init(struct dw_dp *dp)
regmap_update_bits(dp->regmap, DPTX_CCTL, DEFAULT_FAST_LINK_TRAIN_EN, regmap_update_bits(dp->regmap, DPTX_CCTL, DEFAULT_FAST_LINK_TRAIN_EN,
FIELD_PREP(DEFAULT_FAST_LINK_TRAIN_EN, 0)); FIELD_PREP(DEFAULT_FAST_LINK_TRAIN_EN, 0));
#if 0
regmap_update_bits(dp->regmap, DPTX_GENERAL_INTERRUPT_ENABLE,
VIDEO_FIFO_OVERFLOW_STREAM0, FIELD_PREP(VIDEO_FIFO_OVERFLOW_STREAM0, 1));
regmap_update_bits(dp->regmap, DPTX_GENERAL_INTERRUPT_ENABLE,
VIDEO_FIFO_UNDERFLOW_STREAM0, FIELD_PREP(VIDEO_FIFO_UNDERFLOW_STREAM0, 1));
#endif
dw_dp_hpd_init(dp); dw_dp_hpd_init(dp);
dw_dp_aux_init(dp); dw_dp_aux_init(dp);
} }
@@ -2992,7 +3056,6 @@ static ssize_t dw_dp_aux_transfer(struct drm_dp_aux *aux,
case DP_AUX_I2C_READ: case DP_AUX_I2C_READ:
break; break;
default: { default: {
dev_err(dp->dev, "%s, %d, aux error\n", __func__, __LINE__);
return -EINVAL; return -EINVAL;
} }
} }
@@ -3115,13 +3178,9 @@ static void _dw_dp_loader_protect(struct dw_dp *dp, bool on)
link->rate = 162000; link->rate = 162000;
break; break;
} }
#if !NO_PHY
phy_power_on(dp->phy); phy_power_on(dp->phy);
#endif
} else { } else {
#if !NO_PHY
phy_power_off(dp->phy); phy_power_off(dp->phy);
#endif
} }
} }
@@ -3296,7 +3355,8 @@ static void dw_dp_bridge_detach(struct drm_bridge *bridge)
{ {
struct dw_dp *dp = bridge_to_dp(bridge); struct dw_dp *dp = bridge_to_dp(bridge);
drm_connector_cleanup(&dp->connector); if (dp->connector.dev)
drm_connector_cleanup(&dp->connector);
} }
static void dw_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge, static void dw_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
@@ -3350,9 +3410,7 @@ static void dw_dp_link_disable(struct dw_dp *dp)
dw_dp_phy_xmit_enable(dp, 0); dw_dp_phy_xmit_enable(dp, 0);
#if !NO_PHY
phy_power_off(dp->phy); phy_power_off(dp->phy);
#endif
link->train.clock_recovered = false; link->train.clock_recovered = false;
link->train.channel_equalized = false; link->train.channel_equalized = false;
@@ -3362,21 +3420,19 @@ static int dw_dp_link_enable(struct dw_dp *dp)
{ {
int ret; int ret;
#if !NO_PHY
ret = phy_power_on(dp->phy); ret = phy_power_on(dp->phy);
if (ret) if (ret)
return ret; return ret;
#endif
ret = dw_dp_link_power_up(dp); ret = dw_dp_link_power_up(dp);
if (ret < 0) { if (ret < 0) {
dev_err(dp->dev, "dw_dp_link_power_up failed: %d\n", ret); dev_info(dp->dev, "dw_dp_link_power_up failed: %d\n", ret);
return ret; return ret;
} }
ret = dw_dp_link_train(dp); ret = dw_dp_link_train(dp);
if (ret < 0) { if (ret < 0) {
dev_err(dp->dev, "link training failed: %d\n", ret); dev_info(dp->dev, "link training failed: %d\n", ret);
return ret; return ret;
} }
@@ -3409,7 +3465,7 @@ static void dw_dp_bridge_atomic_enable(struct drm_bridge *bridge,
ret = dw_dp_link_enable(dp); ret = dw_dp_link_enable(dp);
if (ret < 0) { if (ret < 0) {
dev_err(dp->dev, "failed to enable link: %d\n", ret); dev_info(dp->dev, "failed to enable link: %d\n", ret);
return; return;
} }
@@ -3473,11 +3529,9 @@ static bool dw_dp_detect_dpcd(struct dw_dp *dp)
u8 value; u8 value;
int ret; int ret;
#if !NO_PHY
ret = phy_power_on(dp->phy); ret = phy_power_on(dp->phy);
if (ret) if (ret)
goto fail_power_on; goto fail_power_on;
#endif
ret = drm_dp_dpcd_readb(&dp->aux, DP_DPCD_REV, &value); ret = drm_dp_dpcd_readb(&dp->aux, DP_DPCD_REV, &value);
if (ret < 0) { if (ret < 0) {
goto fail_probe; goto fail_probe;
@@ -3489,17 +3543,13 @@ static bool dw_dp_detect_dpcd(struct dw_dp *dp)
goto fail_probe; goto fail_probe;
} }
#if !NO_PHY
phy_power_off(dp->phy); phy_power_off(dp->phy);
#endif
return true; return true;
fail_probe: fail_probe:
#if !NO_PHY
phy_power_off(dp->phy); phy_power_off(dp->phy);
fail_power_on: fail_power_on:
#endif
return false; return false;
} }
@@ -3540,17 +3590,13 @@ static struct edid *dw_dp_bridge_get_edid(struct drm_bridge *bridge,
{ {
struct dw_dp *dp = bridge_to_dp(bridge); struct dw_dp *dp = bridge_to_dp(bridge);
struct edid *edid; struct edid *edid;
#if !NO_PHY
int ret; int ret;
ret = phy_power_on(dp->phy); ret = phy_power_on(dp->phy);
if (ret) if (ret)
return NULL; return NULL;
#endif
edid = drm_get_edid(connector, &dp->aux.ddc); edid = drm_get_edid(connector, &dp->aux.ddc);
#if !NO_PHY
phy_power_off(dp->phy); phy_power_off(dp->phy);
#endif
return edid; return edid;
} }
@@ -3972,18 +4018,6 @@ static irqreturn_t dw_dp_irq_handler(int irq, void *data)
if (!value) if (!value)
return IRQ_NONE; return IRQ_NONE;
#if 0
if (value & VIDEO_FIFO_OVERFLOW_STREAM0) {
regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT,
VIDEO_FIFO_OVERFLOW_STREAM0);
}
if (value & VIDEO_FIFO_UNDERFLOW_STREAM0) {
regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT,
VIDEO_FIFO_UNDERFLOW_STREAM0);
}
#endif
if (value & HPD_EVENT) if (value & HPD_EVENT)
dw_dp_handle_hpd_event(dp); dw_dp_handle_hpd_event(dp);
@@ -3996,8 +4030,6 @@ static irqreturn_t dw_dp_irq_handler(int irq, void *data)
if (value & HDCP_EVENT) if (value & HDCP_EVENT)
dw_dp_handle_hdcp_event(dp); dw_dp_handle_hdcp_event(dp);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@@ -4355,87 +4387,13 @@ static int dw_dp_parse_dt(struct dw_dp *dp)
return 0; return 0;
} }
static ssize_t dpinit_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
char kbuf[64];
char *p, *token;
unsigned long val;
int ret;
struct dw_dp *dp = dev_get_drvdata(dev);
struct dw_dp_link *link = &dp->link;
/* 简单的长度检查,避免溢出 */
if (count == 0)
return -EINVAL;
if (count >= sizeof(kbuf))
return -EINVAL;
/* buf 是 sysfs 传入的 kernel 空间缓存(已可读),复制并 null 终止以便分词 */
memcpy(kbuf, buf, count);
kbuf[count] = '\0';
p = kbuf;
/* 以空白字符或逗号分隔(支持 "100 4"、"100,4"、"0x64 0x4" 等格式) */
token = strsep(&p, " \t\n,");
if (!token || *token == '\0') {
dev_err(dev, "%s: missing threshold parameter\n", __func__);
return -EINVAL;
}
ret = kstrtoul(token, 0, &val); /* base=0 支持 0x 前缀 */
if (ret) {
dev_err(dev, "%s: invalid threshold '%s'\n", __func__, token);
return ret;
}
g_init_threshold = (unsigned int)val;
/* 第二个参数可选lanes */
token = strsep(&p, " \t\n,");
if (token && *token != '\0') {
ret = kstrtoul(token, 0, &val);
if (ret) {
dev_err(dev, "%s: invalid lanes '%s'\n", __func__, token);
return ret;
}
g_freqs = (unsigned int)val;
link->rate = g_freqs;
} else {
/* 如果未提供 lanes则保持原值或你可以改为返回错误以强制要求两个参数 */
dev_info(dev, "%s: freq not provided, keep %u\n", __func__, link->rate);
}
dev_err(dev, "%s, %d, g_init_threshold = %lu, g_freq = %u\n",
__func__, __LINE__, g_init_threshold, link->rate);
return count;
}
static DEVICE_ATTR_WO(dpinit);
int dw_dp_create_capabilities_sysfs(struct platform_device *pdev)
{
device_create_file(&pdev->dev, &dev_attr_dpinit);
return 0;
}
int dw_dp_remove_capabilities_sysfs(struct platform_device *pdev)
{
device_remove_file(&pdev->dev, &dev_attr_dpinit);
return 0;
}
static int dw_dp_probe(struct platform_device *pdev) static int dw_dp_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct dw_dp *dp; struct dw_dp *dp;
void __iomem *base; void __iomem *base;
int id, ret; int id, ret;
dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
if (!dp) if (!dp)
return -ENOMEM; return -ENOMEM;
@@ -4451,7 +4409,7 @@ static int dw_dp_probe(struct platform_device *pdev)
ret = dw_dp_parse_dt(dp); ret = dw_dp_parse_dt(dp);
if (ret) if (ret)
return dev_err_probe(dev, ret, "failed to parse DT\n"); return dev_err_probe(dev, ret, "failed to parse DT\n");
dp->force_hpd = 1;
mutex_init(&dp->irq_lock); mutex_init(&dp->irq_lock);
INIT_WORK(&dp->hpd_work, dw_dp_hpd_work); INIT_WORK(&dp->hpd_work, dw_dp_hpd_work);
init_completion(&dp->complete); init_completion(&dp->complete);
@@ -4465,12 +4423,10 @@ static int dw_dp_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(dp->regmap), return dev_err_probe(dev, PTR_ERR(dp->regmap),
"failed to create regmap\n"); "failed to create regmap\n");
#if !NO_PHY
dp->phy = devm_of_phy_get(dev, dev->of_node, NULL); dp->phy = devm_of_phy_get(dev, dev->of_node, NULL);
if (IS_ERR(dp->phy)) if (IS_ERR(dp->phy))
return dev_err_probe(dev, PTR_ERR(dp->phy), return dev_err_probe(dev, PTR_ERR(dp->phy),
"failed to get phy\n"); "failed to get phy\n");
#endif
dp->i2s_clk = devm_clk_get(dev, "i2s"); dp->i2s_clk = devm_clk_get(dev, "i2s");
if (IS_ERR(dp->i2s_clk)) if (IS_ERR(dp->i2s_clk))
return dev_err_probe(dev, PTR_ERR(dp->i2s_clk), return dev_err_probe(dev, PTR_ERR(dp->i2s_clk),
@@ -4485,7 +4441,7 @@ static int dw_dp_probe(struct platform_device *pdev)
if (IS_ERR(dp->aux_clk)) if (IS_ERR(dp->aux_clk))
return dev_err_probe(dev, PTR_ERR(dp->aux_clk), return dev_err_probe(dev, PTR_ERR(dp->aux_clk),
"failed to get aux clock\n"); "failed to get aux clock\n");
dp->gtc_clk = devm_clk_get(dev, "gtc"); dp->gtc_clk = devm_clk_get(dev, "gtc");
if (IS_ERR(dp->gtc_clk)) if (IS_ERR(dp->gtc_clk))
return dev_err_probe(dev, PTR_ERR(dp->gtc_clk), return dev_err_probe(dev, PTR_ERR(dp->gtc_clk),
@@ -4554,6 +4510,28 @@ static int dw_dp_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret, return dev_err_probe(dev, ret,
"failed to register extcon device\n"); "failed to register extcon device\n");
/* Try to get PHY's extcon for Type-C HPD notification */
dp->phy_extcon = extcon_get_edev_by_phandle(dev, 0);
if (IS_ERR(dp->phy_extcon)) {
if (PTR_ERR(dp->phy_extcon) == -EPROBE_DEFER) {
dev_err(dev, "PHY extcon not ready, deferring probe\n");
return -EPROBE_DEFER;
}
/* PHY extcon not available, will use GPIO or internal HPD */
dev_info(dev, "No PHY extcon found, using GPIO/internal HPD detection\n");
dp->phy_extcon = NULL;
} else {
/* Register notifier to listen for PHY HPD events */
dp->phy_extcon_nb.notifier_call = dw_dp_phy_extcon_notifier;
ret = devm_extcon_register_notifier(dev, dp->phy_extcon,
EXTCON_DISP_DP,
&dp->phy_extcon_nb);
if (ret) {
dev_err(dev, "Failed to register PHY extcon notifier: ret = %d \n", ret);
return ret;
}
}
//ret = dw_dp_register_audio_driver(dp); //ret = dw_dp_register_audio_driver(dp);
//if (ret) //if (ret)
// return ret; // return ret;
@@ -4592,7 +4570,6 @@ static int dw_dp_probe(struct platform_device *pdev)
secondary->split_mode = true; secondary->split_mode = true;
} }
dw_dp_create_capabilities_sysfs(pdev);
//dw_dp_hdcp_init(dp); //dw_dp_hdcp_init(dp);
return component_add(dev, &dw_dp_component_ops); return component_add(dev, &dw_dp_component_ops);
@@ -4604,7 +4581,6 @@ static int dw_dp_remove(struct platform_device *pdev)
component_del(dp->dev, &dw_dp_component_ops); component_del(dp->dev, &dw_dp_component_ops);
cancel_work_sync(&dp->hpd_work); cancel_work_sync(&dp->hpd_work);
dw_dp_remove_capabilities_sysfs(pdev);
return 0; return 0;
} }

View File

@@ -1030,13 +1030,17 @@ static int primary_bind(struct dw_mipi_dsi *dsi)
int ret; int ret;
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, &bridge); ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, &bridge);
if (ret) if (ret) {
dev_err(dev, "Could not locate any output bridge or panel\n");
return ret; return ret;
}
if (panel) { if (panel) {
bridge = drm_panel_bridge_add(panel); bridge = drm_panel_bridge_add(panel);
if (IS_ERR(bridge)) if (IS_ERR(bridge)) {
dev_err(dev, "drm panel bridge add failed\n");
return PTR_ERR(bridge); return PTR_ERR(bridge);
}
} }
primary->panel_bridge = bridge; primary->panel_bridge = bridge;
@@ -1138,30 +1142,42 @@ static int dsi_probe(struct platform_device *pdev)
funcs = of_device_get_match_data(dev); funcs = of_device_get_match_data(dev);
dsi = funcs->get_dsi(dev); dsi = funcs->get_dsi(dev);
if (!dsi) if (!dsi) {
dev_err(dev, "get dsi failed\n");
return -ENOMEM; return -ENOMEM;
}
dsi->regmap = syscon_regmap_lookup_by_phandle(np, "regmap"); dsi->regmap = syscon_regmap_lookup_by_phandle(np, "regmap");
if (IS_ERR(dsi->regmap)) if (IS_ERR(dsi->regmap)) {
return PTR_ERR(dsi->regmap); dev_err(dev, "Reg map failed\n");
return PTR_ERR(dsi->regmap);
}
dsi->pclk = devm_clk_get_optional(dev, "pclk"); dsi->pclk = devm_clk_get_optional(dev, "pclk");
if (IS_ERR(dsi->pclk)) if (IS_ERR(dsi->pclk)) {
dev_err(dev, "Get pclk failed\n");
return PTR_ERR(dsi->pclk); return PTR_ERR(dsi->pclk);
}
dsi->pixclk = devm_clk_get_optional(dev, "pixclk"); dsi->pixclk = devm_clk_get_optional(dev, "pixclk");
if (IS_ERR(dsi->pixclk)) if (IS_ERR(dsi->pixclk)) {
return PTR_ERR(dsi->pixclk); dev_err(dev, "Get pixclk failed\n");
return PTR_ERR(dsi->pixclk);
}
dsi->dphy = devm_phy_get(dev, "dphy"); dsi->dphy = devm_phy_get(dev, "dphy");
if (IS_ERR(dsi->dphy)) if (IS_ERR(dsi->dphy)) {
dev_err(dev, "Get dphy failed\n");
return PTR_ERR(dsi->dphy); return PTR_ERR(dsi->dphy);
}
dsi->host.ops = &dw_mipi_dsi_host_ops; dsi->host.ops = &dw_mipi_dsi_host_ops;
dsi->host.dev = dev; dsi->host.dev = dev;
ret = mipi_dsi_host_register(&dsi->host); ret = mipi_dsi_host_register(&dsi->host);
if (ret) if (ret) {
dev_err(dev, "Host register failed\n");
return ret; return ret;
}
dsi->funcs = funcs; dsi->funcs = funcs;
dev_set_drvdata(dev, dsi); dev_set_drvdata(dev, dsi);
@@ -1169,8 +1185,10 @@ static int dsi_probe(struct platform_device *pdev)
pm_runtime_enable(dev); pm_runtime_enable(dev);
ret = component_add(dev, &dsi_component_ops); ret = component_add(dev, &dsi_component_ops);
if (ret) if (ret) {
goto host_unregister; dev_err(dev, "Component add failed\n");
goto host_unregister;
}
return 0; return 0;

View File

@@ -7,12 +7,22 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#ifdef CONFIG_ZHIHE_AUXDISP
#include <linux/of.h>
#include <drm/drm_atomic.h>
#endif
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_modes.h>
#include <drm/vs_drm.h> #include <drm/vs_drm.h>
#include "vs_crtc.h" #include "vs_crtc.h"
#ifdef CONFIG_ZHIHE_AUXDISP
#include "vs_drv.h"
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
#include <linux/media-bus-format.h> #include <linux/media-bus-format.h>
#endif #endif
@@ -267,6 +277,17 @@ static bool vs_crtc_mode_fixup(struct drm_crtc *crtc,
return vs_crtc->funcs->mode_fixup(vs_crtc->dev, crtc, mode, adjusted_mode); return vs_crtc->funcs->mode_fixup(vs_crtc->dev, crtc, mode, adjusted_mode);
} }
static enum drm_mode_status vs_crtc_mode_valid(struct drm_crtc *crtc,
const struct drm_display_mode *mode)
{
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
if (vs_crtc->funcs->mode_valid)
return vs_crtc->funcs->mode_valid(vs_crtc->dev, crtc, mode);
return MODE_OK;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
static void vs_crtc_atomic_enable(struct drm_crtc *crtc, static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *old_state) struct drm_atomic_state *old_state)
@@ -289,7 +310,7 @@ static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
static void vs_crtc_atomic_disable(struct drm_crtc *crtc, static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_state *old_state) struct drm_atomic_state *state)
#else #else
static void vs_crtc_atomic_disable(struct drm_crtc *crtc, static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state) struct drm_crtc_state *old_state)
@@ -297,11 +318,50 @@ static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
{ {
struct vs_crtc *vs_crtc = to_vs_crtc(crtc); struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
#ifdef CONFIG_ZHIHE_AUXDISP
struct drm_device *drm_dev = crtc->dev;
struct vs_drm_private *priv = drm_dev->dev_private;
bool auxdisp_enabling = false;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
/* 检查是否有 AuxDisp CRTC 即将启用 */
struct drm_crtc *other_crtc;
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
int i;
for_each_oldnew_crtc_in_state(state, other_crtc, old_crtc_state, new_crtc_state, i) {
if (other_crtc == crtc)
continue;
/* 检查是否是 AuxDisp CRTC */
if (other_crtc->port && other_crtc->port->parent &&
of_device_is_compatible(other_crtc->port->parent, ZH_AUXDISP_COMPATIBLE)) {
/* 检查 AuxDisp 是否从 inactive → active */
if (!old_crtc_state->active && new_crtc_state->active) {
auxdisp_enabling = true;
break;
}
}
}
#endif
#endif
drm_crtc_vblank_off(crtc); drm_crtc_vblank_off(crtc);
vs_crtc->funcs->disable(vs_crtc->dev, crtc); vs_crtc->funcs->disable(vs_crtc->dev, crtc);
#ifdef CONFIG_ZHIHE_AUXDISP
/* 如果检测到 AuxDisp 即将启用,不释放 PM 引用 */
if (auxdisp_enabling) {
priv->dc_clk_held_for_auxdisp = true;
} else {
/* 正常情况:立即释放 PM 引用 */
pm_runtime_put(vs_crtc->dev);
}
#else
pm_runtime_put(vs_crtc->dev); pm_runtime_put(vs_crtc->dev);
#endif
spin_lock_irq(&crtc->dev->event_lock); spin_lock_irq(&crtc->dev->event_lock);
if (crtc->state->event && !crtc->state->active) { if (crtc->state->event && !crtc->state->active) {
@@ -361,6 +421,7 @@ static void vs_crtc_atomic_flush(struct drm_crtc *crtc,
} }
static const struct drm_crtc_helper_funcs vs_crtc_helper_funcs = { static const struct drm_crtc_helper_funcs vs_crtc_helper_funcs = {
.mode_valid = vs_crtc_mode_valid,
.mode_fixup = vs_crtc_mode_fixup, .mode_fixup = vs_crtc_mode_fixup,
.atomic_enable = vs_crtc_atomic_enable, .atomic_enable = vs_crtc_atomic_enable,
.atomic_disable = vs_crtc_atomic_disable, .atomic_disable = vs_crtc_atomic_disable,

View File

@@ -20,6 +20,9 @@ struct vs_crtc_funcs {
struct drm_crtc *crtc, struct drm_crtc *crtc,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode); struct drm_display_mode *adjusted_mode);
enum drm_mode_status (*mode_valid)(struct device *dev,
struct drm_crtc *crtc,
const struct drm_display_mode *mode);
void (*set_gamma)(struct device *dev, struct drm_crtc *crtc, void (*set_gamma)(struct device *dev, struct drm_crtc *crtc,
struct drm_color_lut *lut, unsigned int size); struct drm_color_lut *lut, unsigned int size);
void (*enable_gamma)(struct device *dev, struct drm_crtc *crtc, void (*enable_gamma)(struct device *dev, struct drm_crtc *crtc,

View File

@@ -14,6 +14,7 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <drm/drm_encoder.h>
#include <drm/drm_framebuffer.h> #include <drm/drm_framebuffer.h>
#include <drm/drm_atomic.h> #include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
@@ -319,7 +320,7 @@ static void vs_dc_dump_disable(struct device *dev)
static void vs_dc_set_display_path(struct device *dev, struct drm_atomic_state *state, struct vs_dc *dc, struct drm_crtc *crtc) static void vs_dc_set_display_path(struct device *dev, struct drm_atomic_state *state, struct vs_dc *dc, struct drm_crtc *crtc)
{ {
int i = 0; int i = 0;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_connector_state *conn_state; struct drm_connector_state *conn_state;
struct clk *clk = dc->pixclk[crtc->index]; struct clk *clk = dc->pixclk[crtc->index];
@@ -339,7 +340,7 @@ static void vs_dc_set_display_path(struct device *dev, struct drm_atomic_state *
clk_set_parent(dc->dptx_pixclk, clk); clk_set_parent(dc->dptx_pixclk, clk);
break; break;
default: default:
dev_err(dev, "invalid connector type:%d\n", connector->connector_type); dev_err(dev, "invalid connector type:%d\n", connector->connector_type);
} }
} }
} }
@@ -347,6 +348,12 @@ static void vs_dc_set_display_path(struct device *dev, struct drm_atomic_state *
static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc, struct drm_atomic_state *state) static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc, struct drm_atomic_state *state)
{ {
struct vs_dc *dc = dev_get_drvdata(dev); struct vs_dc *dc = dev_get_drvdata(dev);
#ifdef CONFIG_ZHIHE_AUXDISP
struct drm_device *drm_dev = crtc->dev;
struct vs_drm_private *priv = drm_dev->dev_private;
#endif
struct vs_crtc_state *crtc_state = to_vs_crtc_state(crtc->state); struct vs_crtc_state *crtc_state = to_vs_crtc_state(crtc->state);
struct drm_display_mode *mode = &crtc->state->adjusted_mode; struct drm_display_mode *mode = &crtc->state->adjusted_mode;
struct dc_hw_display display; struct dc_hw_display display;
@@ -380,12 +387,12 @@ static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc, struct drm_a
display.enable = true; display.enable = true;
if (dc->pix_clk_rate[display.id] != mode->clock) { if (dc->pix_clk_rate[display.id] != mode->clock) {
clk_set_rate(dc->pixclk[display.id], mode->clock * 1000); clk_set_rate(dc->pixclk[display.id], mode->clock * 1000);
dc->pix_clk_rate[display.id] = mode->clock; dc->pix_clk_rate[display.id] = mode->clock;
} }
if (crtc_state->encoder_type == DRM_MODE_ENCODER_DSI || if (crtc_state->encoder_type == DRM_MODE_ENCODER_DSI ||
crtc_state->encoder_type == DRM_MODE_ENCODER_DPI) crtc_state->encoder_type == DRM_MODE_ENCODER_DPI)
dc_hw_set_out(&dc->hw, OUT_DPI, display.id); dc_hw_set_out(&dc->hw, OUT_DPI, display.id);
else else
dc_hw_set_out(&dc->hw, OUT_DP, display.id); dc_hw_set_out(&dc->hw, OUT_DP, display.id);
@@ -402,6 +409,12 @@ static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc, struct drm_a
if (dc->is_zhihe_a210) if (dc->is_zhihe_a210)
vs_dc_set_display_path(dev, state, dc, crtc); vs_dc_set_display_path(dev, state, dc, crtc);
#ifdef CONFIG_ZHIHE_AUXDISP
if (priv->auxdisp_clk_held_for_dc && priv->auxdisp_dev) {
priv->auxdisp_clk_held_for_dc = false;
pm_runtime_put(priv->auxdisp_dev);
}
#endif
} }
static void vs_dc_disable(struct device *dev, struct drm_crtc *crtc) static void vs_dc_disable(struct device *dev, struct drm_crtc *crtc)
@@ -425,8 +438,8 @@ static bool vs_dc_mode_fixup(struct device *dev,
long clk_rate; long clk_rate;
if (unlikely(id >= DC_DISPLAY_NUM)) { if (unlikely(id >= DC_DISPLAY_NUM)) {
dev_err(dev, "invalid display id : %d\n", id); dev_err(dev, "invalid display id : %d\n", id);
return false; return false;
} }
if (dc->pixclk[id]) { if (dc->pixclk[id]) {
@@ -438,6 +451,61 @@ static bool vs_dc_mode_fixup(struct device *dev,
return true; return true;
} }
static bool crtc_is_dsi(struct drm_crtc *crtc)
{
struct drm_device *drm = crtc->dev;
struct drm_encoder *encoder;
drm_for_each_encoder(encoder, drm) {
if (!drm_encoder_crtc_ok(encoder, crtc))
continue;
if (encoder->encoder_type == DRM_MODE_ENCODER_DSI)
return true;
}
return false;
}
static enum drm_mode_status vs_dc_mode_valid(struct device *dev,
struct drm_crtc *crtc,
const struct drm_display_mode *mode)
{
#define PIXCLK_ERR_BP 25 //diff 0.25%
struct vs_dc *dc = dev_get_drvdata(dev);
int id = to_vs_display_id(dc, crtc);
unsigned long clk_rate, request_rate;
unsigned long diff, bp;
if (unlikely(id >= DC_DISPLAY_NUM))
return MODE_BAD;
if (!dc->pixclk[id])
return MODE_OK;
request_rate = mode->clock * 1000;
clk_rate = clk_round_rate(dc->pixclk[id], request_rate);
/*
*Range checking for DSI devices is delegated to the DSI subsystem.
*/
if (crtc_is_dsi(crtc)) {
return MODE_OK;
}
/*
* If the clock rate difference is more than 0.25%, the mode is
* considered unsupported by the CRTC hardware.
* refer to dw_hdmi_tx_phy_gen2_configure() function
*/
diff = clk_rate > request_rate ? clk_rate - request_rate : request_rate - clk_rate;
bp = diff * 10000ULL / request_rate;
if (bp > PIXCLK_ERR_BP)
return MODE_CLOCK_RANGE;
return MODE_OK;
}
static void vs_dc_set_gamma(struct device *dev, struct drm_crtc *crtc, static void vs_dc_set_gamma(struct device *dev, struct drm_crtc *crtc,
struct drm_color_lut *lut, unsigned int size) struct drm_color_lut *lut, unsigned int size)
{ {
@@ -465,9 +533,7 @@ static void vs_dc_enable_gamma(struct device *dev, struct drm_crtc *crtc,
bool enable) bool enable)
{ {
struct vs_dc *dc = dev_get_drvdata(dev); struct vs_dc *dc = dev_get_drvdata(dev);
u8 id; u8 id = to_vs_display_id(dc, crtc);
id = to_vs_display_id(dc, crtc);
dc_hw_enable_gamma(&dc->hw, id, enable); dc_hw_enable_gamma(&dc->hw, id, enable);
} }
@@ -889,9 +955,9 @@ static int vs_dc_check_plane(struct device *dev, struct vs_plane *plane,
/* 90/270 degree rotation requires non-linear fb */ /* 90/270 degree rotation requires non-linear fb */
if ((state->rotation == DRM_MODE_ROTATE_90 || if ((state->rotation == DRM_MODE_ROTATE_90 ||
state->rotation == DRM_MODE_ROTATE_270) && state->rotation == DRM_MODE_ROTATE_270) &&
(fb->modifier & DRM_FORMAT_MOD_LINEAR) == DRM_FORMAT_MOD_LINEAR) (fb->modifier & DRM_FORMAT_MOD_LINEAR) == DRM_FORMAT_MOD_LINEAR)
return -EINVAL; return -EINVAL;
return drm_atomic_helper_check_plane_state(state, crtc_state, return drm_atomic_helper_check_plane_state(state, crtc_state,
plane_info->min_scale, plane_info->min_scale,
@@ -908,13 +974,13 @@ static irqreturn_t dc_isr(int irq, void *data)
intr_vec = dc_hw_get_interrupt(&dc->hw); intr_vec = dc_hw_get_interrupt(&dc->hw);
for (i = 0; i < dc_info->panel_num; i++) { for (i = 0; i < dc_info->panel_num; i++) {
if (intr_vec & BIT(i)) if (intr_vec & BIT(i))
vs_crtc_handle_vblank(&dc->crtc[i]->base, vs_crtc_handle_vblank(&dc->crtc[i]->base,
dc_hw_check_underflow(&dc->hw)); dc_hw_check_underflow(&dc->hw));
} }
if (intr_vec & ~0x3) if (intr_vec & ~0x3)
pr_warn("%s: unhandled interrupt %#x\n", __func__, intr_vec); pr_warn("%s: unhandled interrupt %#x\n", __func__, intr_vec);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@@ -942,6 +1008,7 @@ static const struct vs_crtc_funcs dc_crtc_funcs = {
.enable = vs_dc_enable, .enable = vs_dc_enable,
.disable = vs_dc_disable, .disable = vs_dc_disable,
.mode_fixup = vs_dc_mode_fixup, .mode_fixup = vs_dc_mode_fixup,
.mode_valid = vs_dc_mode_valid,
.set_gamma = vs_dc_set_gamma, .set_gamma = vs_dc_set_gamma,
.enable_gamma = vs_dc_enable_gamma, .enable_gamma = vs_dc_enable_gamma,
.enable_vblank = vs_dc_enable_vblank, .enable_vblank = vs_dc_enable_vblank,
@@ -962,7 +1029,7 @@ static const struct vs_dc_funcs dc_funcs = {
static int dc_bind(struct device *dev, struct device *master, void *data) static int dc_bind(struct device *dev, struct device *master, void *data)
{ {
struct drm_device *drm_dev = data; struct drm_device *drm_dev = data;
#ifdef CONFIG_VERISILICON_MMU #if defined(CONFIG_VERISILICON_MMU) || defined(CONFIG_ZHIHE_AUXDISP)
struct vs_drm_private *priv = drm_dev->dev_private; struct vs_drm_private *priv = drm_dev->dev_private;
#endif #endif
struct vs_dc *dc = dev_get_drvdata(dev); struct vs_dc *dc = dev_get_drvdata(dev);
@@ -980,6 +1047,12 @@ static int dc_bind(struct device *dev, struct device *master, void *data)
return -ENODEV; return -ENODEV;
} }
#ifdef CONFIG_ZHIHE_AUXDISP
/* 注册 DC8200 设备到共享状态,用于 AuxDisp 切换协调 */
priv->dc_dev = dev;
dev_info(dev, "DC8200: Registered device for AuxDisp coordination\n");
#endif
ret = dc_init(dev); ret = dc_init(dev);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "Failed to initialize DC hardware.\n"); dev_err(dev, "Failed to initialize DC hardware.\n");
@@ -1118,35 +1191,33 @@ const struct component_ops dc_component_ops = {
}; };
static const struct of_device_id dc_driver_dt_match[] = { static const struct of_device_id dc_driver_dt_match[] = {
{ .compatible = "verisilicon,dc8200", }, { .compatible = VS_DC8200_COMPATIBLE },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, dc_driver_dt_match); MODULE_DEVICE_TABLE(of, dc_driver_dt_match);
static void dc_get_display_pll(struct device *dev, struct vs_dc *dc) static void dc_get_display_pll(struct device *dev, struct vs_dc *dc)
{ {
struct device_node *child; struct device_node *child;
u32 reg; u32 reg;
dc->dpu0pll_on = 0; dc->dpu0pll_on = 0;
dc->dpu1pll_on = 0; dc->dpu1pll_on = 0;
for_each_child_of_node(dev->of_node, child) { for_each_child_of_node(dev->of_node, child) {
if (!child->name || strcmp(child->name, "port") != 0) if (!child->name || strcmp(child->name, "port") != 0)
continue; continue;
if (of_property_read_u32(child, "reg", &reg)) { if (of_property_read_u32(child, "reg", &reg))
continue; continue;
}
if (reg == 0) { if (reg == 0)
dc->dpu0pll_on = of_device_is_available(child); dc->dpu0pll_on = of_device_is_available(child);
} else if (reg == 1) { else if (reg == 1)
dc->dpu1pll_on = of_device_is_available(child); dc->dpu1pll_on = of_device_is_available(child);
} }
}
dev_info(dev, "dpu0pll_on:%d dpu1pll_on:%d\n", dc->dpu0pll_on, dc->dpu1pll_on); dev_info(dev, "dpu0pll_on:%d dpu1pll_on:%d\n", dc->dpu0pll_on, dc->dpu1pll_on);
} }
static int dc_probe(struct platform_device *pdev) static int dc_probe(struct platform_device *pdev)
@@ -1281,73 +1352,73 @@ static int dc_remove(struct platform_device *pdev)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int dc_runtime_suspend(struct device *dev) static int dc_runtime_suspend(struct device *dev)
{ {
int i; int i;
struct vs_dc *dc = dev_get_drvdata(dev); struct vs_dc *dc = dev_get_drvdata(dev);
dev_dbg(dev, "%s\n", __func__); dev_dbg(dev, "%s\n", __func__);
clk_disable_unprepare(dc->axi_clk); clk_disable_unprepare(dc->axi_clk);
for (i = 0; i < DC_DISPLAY_NUM; i++){ for (i = 0; i < DC_DISPLAY_NUM; i++){
clk_disable_unprepare(dc->pix_clk[i]); clk_disable_unprepare(dc->pix_clk[i]);
clk_disable_unprepare(dc->pixclk[i]); clk_disable_unprepare(dc->pixclk[i]);
} }
clk_disable_unprepare(dc->core_clk); clk_disable_unprepare(dc->core_clk);
clk_disable_unprepare(dc->cfg_clk); clk_disable_unprepare(dc->cfg_clk);
if (dc->dpu0pll_on) if (dc->dpu0pll_on)
clk_disable_unprepare(dc->dpu0pll_clk); clk_disable_unprepare(dc->dpu0pll_clk);
if (dc->dpu1pll_on) if (dc->dpu1pll_on)
clk_disable_unprepare(dc->dpu1pll_clk); clk_disable_unprepare(dc->dpu1pll_clk);
return 0; return 0;
} }
static int dc_runtime_resume(struct device *dev) static int dc_runtime_resume(struct device *dev)
{ {
int i, ret; int i, ret;
struct vs_dc *dc = dev_get_drvdata(dev); struct vs_dc *dc = dev_get_drvdata(dev);
dev_dbg(dev, "%s\n", __func__); dev_dbg(dev, "%s\n", __func__);
if (dc->dpu0pll_on) if (dc->dpu0pll_on)
clk_prepare_enable(dc->dpu0pll_clk); clk_prepare_enable(dc->dpu0pll_clk);
if (dc->dpu1pll_on) if (dc->dpu1pll_on)
clk_prepare_enable(dc->dpu1pll_clk); clk_prepare_enable(dc->dpu1pll_clk);
ret = clk_prepare_enable(dc->cfg_clk); ret = clk_prepare_enable(dc->cfg_clk);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to prepare/enable cfg_clk\n"); dev_err(dev, "failed to prepare/enable cfg_clk\n");
return ret; return ret;
} }
ret = clk_prepare_enable(dc->core_clk); ret = clk_prepare_enable(dc->core_clk);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to prepare/enable core_clk\n"); dev_err(dev, "failed to prepare/enable core_clk\n");
return ret; return ret;
} }
for (i = 0; i < DC_DISPLAY_NUM; i++) { for (i = 0; i < DC_DISPLAY_NUM; i++) {
ret = clk_prepare_enable(dc->pix_clk[i]); ret = clk_prepare_enable(dc->pix_clk[i]);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to prepare/enable pix_clk %d\n", i); dev_err(dev, "failed to prepare/enable pix_clk %d\n", i);
return ret; return ret;
} }
ret = clk_prepare_enable(dc->pixclk[i]); ret = clk_prepare_enable(dc->pixclk[i]);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to prepare/enable pixclk %d\n", i); dev_err(dev, "failed to prepare/enable pixclk %d\n", i);
return ret; return ret;
} }
} }
ret = clk_prepare_enable(dc->axi_clk); ret = clk_prepare_enable(dc->axi_clk);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to prepare/enable axi_clk\n"); dev_err(dev, "failed to prepare/enable axi_clk\n");
return ret; return ret;
} }
return 0; return 0;
} }
#endif #endif
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
@@ -1355,7 +1426,7 @@ static int dc_runtime_resume(struct device *dev)
static int dc_suspend(struct device *dev) static int dc_suspend(struct device *dev)
{ {
int i; int i;
struct vs_dc *dc = dev_get_drvdata(dev); struct vs_dc *dc = dev_get_drvdata(dev);
for (i = 0; i < DC_DISPLAY_NUM; i++){ for (i = 0; i < DC_DISPLAY_NUM; i++){
dc->pix_clk_rate[i] = dc->def_pix_clk_rate[i]; dc->pix_clk_rate[i] = dc->def_pix_clk_rate[i];
@@ -1386,8 +1457,9 @@ static int dc_resume(struct device *dev)
#endif #endif
static const struct dev_pm_ops dc_pm_ops = { static const struct dev_pm_ops dc_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, SET_LATE_SYSTEM_SLEEP_PM_OPS(
pm_runtime_force_resume) pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(dc_runtime_suspend, dc_runtime_resume, NULL) SET_RUNTIME_PM_OPS(dc_runtime_suspend, dc_runtime_resume, NULL)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
SET_LATE_SYSTEM_SLEEP_PM_OPS(dc_suspend, dc_resume) SET_LATE_SYSTEM_SLEEP_PM_OPS(dc_suspend, dc_resume)

View File

@@ -172,7 +172,7 @@ static ssize_t log_show(struct kobject *kobj, struct kobj_attribute *attr, char
is_current_master ? 'y' : 'n', is_current_master ? 'y' : 'n',
priv->authenticated ? 'y' : 'n', priv->authenticated ? 'y' : 'n',
// from_kuid_munged(seq_user_ns(m), uid) // from_kuid_munged(seq_user_ns(m), uid)
uid, __kuid_val(uid),
priv->magic); priv->magic);
rcu_read_unlock(); rcu_read_unlock();
} }
@@ -212,7 +212,6 @@ static ssize_t log_show(struct kobject *kobj, struct kobj_attribute *attr, char
list_for_each_entry(drm_crtc, &drm_dev->mode_config.crtc_list, head) { list_for_each_entry(drm_crtc, &drm_dev->mode_config.crtc_list, head) {
// struct vs_crtc *crtc = to_vs_crtc(drm_crtc); // struct vs_crtc *crtc = to_vs_crtc(drm_crtc);
struct drm_crtc *crtc = drm_crtc->state->crtc; struct drm_crtc *crtc = drm_crtc->state->crtc;
struct vs_crtc_state *crtc_state = to_vs_crtc_state(drm_crtc->state);
len += scnprintf(buf + len, PAGE_SIZE - len, len += scnprintf(buf + len, PAGE_SIZE - len,
"crtc[%u]: %s\n" "crtc[%u]: %s\n"
"\tenable= %d\n" "\tenable= %d\n"
@@ -231,7 +230,6 @@ static ssize_t log_show(struct kobject *kobj, struct kobj_attribute *attr, char
list_for_each_entry(plane, &drm_dev->mode_config.plane_list, head) { list_for_each_entry(plane, &drm_dev->mode_config.plane_list, head) {
struct drm_plane_state *state = plane->state; struct drm_plane_state *state = plane->state;
struct vs_plane_state *plane_state = to_vs_plane_state(state);
struct drm_rect src = drm_plane_state_src(state); struct drm_rect src = drm_plane_state_src(state);
struct drm_rect dest = drm_plane_state_dest(state); struct drm_rect dest = drm_plane_state_dest(state);
@@ -466,20 +464,32 @@ static int vs_drm_bind(struct device *dev)
priv->dma_dev = drm_dev->dev; priv->dma_dev = drm_dev->dev;
priv->dma_dev->coherent_dma_mask = dma_mask; priv->dma_dev->coherent_dma_mask = dma_mask;
#ifdef CONFIG_ZHIHE_AUXDISP
/* 初始化 DC8200 ↔ AuxDisp 切换状态 */
priv->dc_dev = NULL;
priv->auxdisp_dev = NULL;
priv->dc_clk_held_for_auxdisp = false;
priv->auxdisp_clk_held_for_dc = false;
#endif
drm_dev->dev_private = priv; drm_dev->dev_private = priv;
drm_mode_config_init(drm_dev); drm_mode_config_init(drm_dev);
/* Now try and bind all our sub-components */ /* Now try and bind all our sub-components */
ret = component_bind_all(dev, drm_dev); ret = component_bind_all(dev, drm_dev);
if (ret) if (ret) {
DRM_ERROR("Failed to bind all components\n");
goto err_mode; goto err_mode;
}
vs_mode_config_init(drm_dev); vs_mode_config_init(drm_dev);
ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc); ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
if (ret) if (ret) {
dev_err(drm_dev->dev, "vblank init failed.\n");
goto err_bind; goto err_bind;
}
drm_mode_config_reset(drm_dev); drm_mode_config_reset(drm_dev);
@@ -490,8 +500,10 @@ static int vs_drm_bind(struct device *dev)
drm_kms_helper_poll_init(drm_dev); drm_kms_helper_poll_init(drm_dev);
ret = drm_dev_register(drm_dev, 0); ret = drm_dev_register(drm_dev, 0);
if (ret) if (ret) {
dev_err(drm_dev->dev, "Failed to register DRM device: %d\n", ret);
goto err_helper; goto err_helper;
}
ret = sysfs_create_group(&drm_dev->primary->kdev->kobj, &vs_dev_attr_group); ret = sysfs_create_group(&drm_dev->primary->kdev->kobj, &vs_dev_attr_group);
@@ -531,7 +543,7 @@ static void vs_drm_unbind(struct device *dev)
drm_kms_helper_poll_fini(drm_dev); drm_kms_helper_poll_fini(drm_dev);
drm_dev_unregister(drm_dev); drm_dev_unregister(drm_dev);
struct drm_connector *connector; struct drm_connector *connector;
struct drm_connector_list_iter iter; struct drm_connector_list_iter iter;
@@ -541,7 +553,7 @@ static void vs_drm_unbind(struct device *dev)
} }
drm_connector_list_iter_end(&iter); drm_connector_list_iter_end(&iter);
component_unbind_all(drm_dev->dev, drm_dev); component_unbind_all(drm_dev->dev, drm_dev);
drm_mode_config_cleanup(drm_dev); drm_mode_config_cleanup(drm_dev);
@@ -561,10 +573,17 @@ static const struct component_master_ops vs_drm_ops = {
}; };
extern struct platform_driver dw_dp_driver; extern struct platform_driver dw_dp_driver;
extern struct platform_driver auxdisp_crtc_driver;
static struct platform_driver *drm_sub_drivers[] = { static struct platform_driver *drm_sub_drivers[] = {
/* put display control driver at start */ /* put display control driver at start */
&dc_platform_driver, &dc_platform_driver,
/* auxiliary display CRTC */
#ifdef CONFIG_ZHIHE_AUXDISP
&auxdisp_crtc_driver,
#endif
/* connector */ /* connector */
/* bridge */ /* bridge */

View File

@@ -44,6 +44,13 @@ struct vs_drm_private {
#endif #endif
unsigned int pitch_alignment; unsigned int pitch_alignment;
#ifdef CONFIG_ZHIHE_AUXDISP
struct device *dc_dev; /* DC8200 设备指针 */
struct device *auxdisp_dev; /* AuxDisp 设备指针 */
bool dc_clk_held_for_auxdisp; /* DC8200 时钟是否被 AuxDisp 持有 */
bool auxdisp_clk_held_for_dc; /* AuxDisp 时钟是否被 DC8200 持有 */
#endif
}; };
int vs_drm_iommu_attach_device(struct drm_device *drm_dev, int vs_drm_iommu_attach_device(struct drm_device *drm_dev,
@@ -68,4 +75,9 @@ static inline bool is_iommu_enabled(struct drm_device *dev)
return priv->domain != NULL ? true : false; return priv->domain != NULL ? true : false;
} }
/* Device compatible strings */
#define VS_DC8200_COMPATIBLE "verisilicon,dc8200"
#define ZH_AUXDISP_COMPATIBLE "zhihe,auxdisp"
#endif /* __VS_DRV_H__ */ #endif /* __VS_DRV_H__ */

View File

@@ -17,10 +17,13 @@
#endif #endif
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_connector.h>
#include <drm/drm_damage_helper.h> #include <drm/drm_damage_helper.h>
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include "vs_fb.h" #include "vs_fb.h"
#include "vs_gem.h" #include "vs_gem.h"
@@ -166,10 +169,54 @@ vs_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
return NULL; return NULL;
} }
static int vs_drm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
#ifdef CONFIG_ZHIHE_AUXDISP
struct drm_connector *connector;
struct drm_connector_state *old_conn_state, *new_conn_state;
int i;
for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_conn_state, i) {
struct drm_crtc *old_crtc = old_conn_state->crtc;
struct drm_crtc *new_crtc = new_conn_state->crtc;
struct drm_crtc_state *old_crtc_state;
struct drm_connector *conn2;
struct drm_connector_state *conn2_state;
bool has_other_connectors;
int j;
if (!old_crtc || !new_crtc || old_crtc == new_crtc)
continue;
old_crtc_state = drm_atomic_get_crtc_state(state, old_crtc);
if (IS_ERR(old_crtc_state))
return PTR_ERR(old_crtc_state);
has_other_connectors = false;
for_each_new_connector_in_state(state, conn2, conn2_state, j) {
if (conn2 == connector)
continue;
if (conn2_state->crtc == old_crtc) {
has_other_connectors = true;
break;
}
}
if (!has_other_connectors) {
old_crtc_state->enable = false;
old_crtc_state->active = false;
}
}
#endif
return drm_atomic_helper_check(dev, state);
}
static const struct drm_mode_config_funcs vs_mode_config_funcs = { static const struct drm_mode_config_funcs vs_mode_config_funcs = {
.fb_create = vs_fb_create, .fb_create = vs_fb_create,
.get_format_info = vs_get_format_info, .get_format_info = vs_get_format_info,
.atomic_check = drm_atomic_helper_check, .atomic_check = vs_drm_atomic_check,
.atomic_commit = drm_atomic_helper_commit, .atomic_commit = drm_atomic_helper_commit,
}; };

View File

@@ -1 +1 @@
obj-$(CONFIG_RISCV_IOMMU) += iommu.o iommu-platform.o iommu-sysfs.o io_pgtable.o obj-$(CONFIG_RISCV_IOMMU) += iommu.o iommu-platform.o io_pgtable.o

View File

@@ -141,7 +141,7 @@ static int riscv_iommu_map_pages(struct io_pgtable_ops *ops,
pte_t pte_val; pte_t pte_val;
pgprot_t pte_prot; pgprot_t pte_prot;
dev_dbg(domain->iommu->dev, "%s enter iova=0x%lx, phys=0x%llx pgsize=0x%lx pgcount=0x%lx\n", __func__, iova, phys, pgsize, pgcount); dev_dbg(domain->iommus->dev, "%s enter iova=0x%lx, phys=0x%llx pgsize=0x%lx pgcount=0x%lx\n", __func__, iova, phys, pgsize, pgcount);
if (domain->domain.type == IOMMU_DOMAIN_BLOCKED) if (domain->domain.type == IOMMU_DOMAIN_BLOCKED)
return -ENODEV; return -ENODEV;

View File

@@ -11,99 +11,166 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/pm_runtime.h>
#include <linux/pm_domain.h>
#include <linux/clk.h>
#include <linux/of_clk.h>
#include <linux/clk-provider.h>
#include "iommu-bits.h" #include "iommu-bits.h"
#include "iommu.h" #include "iommu.h"
#define P100_IOMMU_CAP 0x28d0008210 #define A210_IOMMU_CAP 0x28d0008210
static int riscv_iommu_platform_probe(struct platform_device *pdev) static int riscv_iommu_platform_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct zh_iommu_device *iommus = NULL;
struct riscv_iommu_device *iommu = NULL; struct riscv_iommu_device *iommu = NULL;
struct resource *res = NULL; struct resource *res = NULL;
struct device_node *np = dev->of_node;
u32 fctl = 0; u32 fctl = 0;
int irq = 0; int irq = 0;
int ret = 0; int ret = 0;
int count;
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL); iommus = devm_kzalloc(dev, sizeof(*iommus), GFP_KERNEL);
if (!iommu) if (!iommus)
return -ENOMEM; return -ENOMEM;
iommus->dev = dev;
mutex_init(&iommus->lock);
INIT_LIST_HEAD(&iommus->iommus);
INIT_LIST_HEAD(&iommus->groups);
dev_set_drvdata(dev, iommus);
dev_set_name(dev, "%s", "zhihe,iommu");
iommu->dev = dev; count = of_count_phandle_with_args(np, "power-domains", "#power-domain-cells");
dev_set_drvdata(dev, iommu); if (count > 0) {
iommus->pd_devs = devm_kcalloc(dev, count, sizeof(*iommus->pd_devs), GFP_KERNEL);
if (!iommus->pd_devs)
return -ENOMEM;
iommus->num_pds = count;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); for (int i = 0; i < count; i++) {
if (!res) { iommus->pd_devs[i] = dev_pm_domain_attach_by_id(dev, i);
dev_err(dev, "could not find resource for register region\n"); if (IS_ERR(iommus->pd_devs[i]))
return -EINVAL; return PTR_ERR(iommus->pd_devs[i]);
device_link_add(dev, iommus->pd_devs[i], DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
}
} }
iommu->reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res); /*
if (IS_ERR(iommu->reg)) { * Get and prepare clocks early, before any hardware access.
ret = dev_err_probe(dev, PTR_ERR(iommu->reg), * Do NOT use pm_runtime_get_sync() before this, as it may trigger power
"could not map register region\n"); * domain operations that themselves need to prepare clocks, causing
goto fail; * circular locking: prepare_lock genpd_runtime_resume genpd->mlock
* a210_pd_power_on clk_prepare prepare_lock (deadlock).
*/
iommus->num_clks = devm_clk_bulk_get_all(dev, &iommus->clks);
if (iommus->num_clks < 0)
return dev_err_probe(dev, iommus->num_clks,
"Failed to get iommus's clocks\n");
ret = clk_bulk_prepare_enable(iommus->num_clks, iommus->clks);
if (ret)
return ret;
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
for (int i = 0; i < pdev->num_resources; i++) {
const char *name;
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
if (!iommu)
return -ENOMEM;
iommu->dev = dev;
INIT_LIST_HEAD(&iommu->list);
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res) {
dev_err(dev, "could not find resource for register region\n");
return -EINVAL;
}
iommu->reg = devm_platform_get_and_ioremap_resource(pdev, i, &res);
if (IS_ERR(iommu->reg)) {
ret = dev_err_probe(dev, PTR_ERR(iommu->reg),
"could not map register region\n");
goto fail;
}
of_property_read_string_index(np, "reg-names", i, &name);
iommu->name = kstrdup(name, GFP_KERNEL);
iommu->reg_phys = res->start;
ret = -ENODEV;
/* Sanity check: Did we get the whole register space ? */
if ((res->end - res->start + 1) < RISCV_IOMMU_REG_SIZE) {
dev_err(dev, "device region smaller than register file (0x%llx)\n",
res->end - res->start);
goto fail;
}
iommu->cap = riscv_iommu_readq(iommu, RISCV_IOMMU_REG_CAP);
if (iommu->cap != A210_IOMMU_CAP) {
dev_err_probe(dev, -ENODEV,
"IOMMU:%s Capacity Reg=0x%llx Error.Check clock power reset!\n", iommu->name, iommu->cap);
goto fail;
}
/* For now we only support WSIs until we have AIA support */
ret = FIELD_GET(RISCV_IOMMU_CAP_IGS, iommu->cap);
if (ret == RISCV_IOMMU_CAP_IGS_MSI) {
dev_err(dev, "IOMMU only supports MSIs\n");
goto fail;
}
/* Parse IRQ assignment */
irq = platform_get_irq(pdev, i);
if (irq > 0)
iommu->irq = irq;
else {
dev_err(dev, "no IRQ provided for iommu\n");
goto fail;
}
/* Make sure fctl.WSI is set */
fctl = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_FCTL);
fctl |= RISCV_IOMMU_FCTL_WSI;
riscv_iommu_writel(iommu, RISCV_IOMMU_REG_FCTL, fctl);
/* Parse Queue lengts */
ret = of_property_read_u32(pdev->dev.of_node, "cmdq_len", &iommu->cmdq_len);
if (!ret)
dev_info(dev, "command queue length set to %i\n", iommu->cmdq_len);
ret = of_property_read_u32(pdev->dev.of_node, "fltq_len", &iommu->fltq_len);
if (!ret)
dev_info(dev, "fault/event queue length set to %i\n", iommu->fltq_len);
ret = riscv_iommu_init(iommu);
if (ret) {
dev_err(dev, "riscv_iommu_init failed %d", ret);
goto fail;
}
list_add_tail(&iommu->list, &iommus->iommus);
} }
iommu->reg_phys = res->start;
ret = -ENODEV;
/* Sanity check: Did we get the whole register space ? */
if ((res->end - res->start + 1) < RISCV_IOMMU_REG_SIZE) {
dev_err(dev, "device region smaller than register file (0x%llx)\n",
res->end - res->start);
goto fail;
}
iommu->cap = riscv_iommu_readq(iommu, RISCV_IOMMU_REG_CAP);
if (iommu->cap != P100_IOMMU_CAP) {
dev_err_probe(dev, -ENODEV,
"IOMMU Capacity Reg=0x%llx Error.Check clock power reset!\n", iommu->cap);
goto fail;
}
/* For now we only support WSIs until we have AIA support */
ret = FIELD_GET(RISCV_IOMMU_CAP_IGS, iommu->cap);
if (ret == RISCV_IOMMU_CAP_IGS_MSI) {
dev_err(dev, "IOMMU only supports MSIs\n");
goto fail;
}
/* Parse IRQ assignment */
irq = platform_get_irq(pdev, 0);
if (irq > 0)
iommu->irq = irq;
else {
dev_err(dev, "no IRQ provided for iommu\n");
goto fail;
}
/* Make sure fctl.WSI is set */
fctl = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_FCTL);
fctl |= RISCV_IOMMU_FCTL_WSI;
riscv_iommu_writel(iommu, RISCV_IOMMU_REG_FCTL, fctl);
/* Parse Queue lengts */
ret = of_property_read_u32(pdev->dev.of_node, "cmdq_len", &iommu->cmdq_len);
if (!ret)
dev_info(dev, "command queue length set to %i\n", iommu->cmdq_len);
ret = of_property_read_u32(pdev->dev.of_node, "fltq_len", &iommu->fltq_len);
if (!ret)
dev_info(dev, "fault/event queue length set to %i\n", iommu->fltq_len);
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
ret = riscv_iommu_init(iommu); riscv_iommu_register(iommus);
//clear tlb list_for_each_entry(iommu, &iommus->iommus, list) {
if (!ret) { //clear tlb with a tmp domain
struct riscv_iommu_domain iommu_domain; struct riscv_iommu_domain iommu_domain;
iommu_domain.iommu = iommu; iommu_domain.iommus = iommus;
iommu_domain.pscid = 0; iommu_domain.pscid = 0;
iommu_domain.domain.ops = iommu->iommu.ops->default_domain_ops; iommu_domain.domain.ops = iommus->iommu.ops->default_domain_ops;
iommu_flush_iotlb_all(&iommu_domain.domain); iommu_flush_iotlb_all(&iommu_domain.domain);
} }
@@ -123,7 +190,7 @@ static void riscv_iommu_platform_shutdown(struct platform_device *pdev)
} }
static const struct of_device_id riscv_iommu_of_match[] = { static const struct of_device_id riscv_iommu_of_match[] = {
{.compatible = "riscv,iommu",}, {.compatible = "zhihe,iommu",},
{}, {},
}; };
@@ -131,7 +198,7 @@ MODULE_DEVICE_TABLE(of, riscv_iommu_of_match);
static struct platform_driver riscv_iommu_platform_driver = { static struct platform_driver riscv_iommu_platform_driver = {
.driver = { .driver = {
.name = "riscv,iommu", .name = "zhihe,iommu",
.of_match_table = riscv_iommu_of_match, .of_match_table = riscv_iommu_of_match,
.suppress_bind_attrs = true, .suppress_bind_attrs = true,
}, },

Some files were not shown because too many files have changed in this diff Show More