Compare commits

...

42 Commits

Author SHA1 Message Date
cb381faa1e drm: verisilicon: fix fbcon
Always map the GEM object, because it may expect different page
attributes than the fixed map by kernel.

Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2026-04-17 16:47:11 +08:00
Han Gao
8b46a2314b drm: img: add zhihe a210 build
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2026-04-17 16:47:11 +08:00
Han Gao
ecf5e527ca a210: gpu: Add driver for PowerVR Rogue GPU
Add the driver for PowerVR Rogue graphics hardware.

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
2026-04-17 16:47:11 +08:00
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
643 changed files with 279680 additions and 7148 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 */
#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_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);
}
#define flush_cache_vmap_early(start, end) do { } while (0)
static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
{
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);
#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_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);
#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 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_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()
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();
}
#define flush_cache_vmap_early(start, end) do { } while (0)
extern void (*__flush_cache_vunmap)(void);
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_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)
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);
#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()
void flush_dcache_folio(struct folio *folio);

View File

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

View File

@@ -34,6 +34,7 @@ config SOC_STARFIVE
config ARCH_ZHIHE
bool "ZhiHe SoCs"
select CLOCKSOURCE_VALIDATE_LAST_CYCLE
help
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-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) += 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 {
label = "Sleep Wake Key";
wakeup-source;
//wakeup-source;
linux,code = <KEY_SLEEP>;
debounce-interval = <1>;
gpios = <&aogpio 2 GPIO_ACTIVE_LOW>;
@@ -1213,7 +1213,7 @@
broken-cd;
io_fixed_1v8;
non-removable;
post-power-on-delay-ms = <200>;
post-power-on-delay-ms = <1000>;
wprtn_ignore;
cap-sd-highspeed;
wakeup-source;

View File

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

View File

@@ -1,3 +1,5 @@
# 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/;
#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-peri.dtsi"
#include "a210-platform-dev.dtsi"
@@ -24,11 +26,15 @@
ethernet0 = &gmac0;
ethernet1 = &gmac1;
gpio0 = &gpio0;
gpio1 = &gpio1;
gpio2 = &gpio2;
gpio3 = &gpio3;
gpio4 = &gpio4;
gpio0 = &ao_gpio0;
gpio1 = &ao_gpio1;
gpio2 = &gpio0;
gpio3 = &gpio1;
gpio4 = &gpio2;
gpio5 = &gpio3;
gpio6 = &gpio4;
gpio7 = &aw9535_0;
gpio8 = &aw9535_1;
i2c0 = &i2c0;
i2c1 = &i2c1;
@@ -38,7 +44,7 @@
i2c5 = &i2c5;
i2c6 = &i2c6;
i2c7 = &i2c7;
aoi2c1 = &aoi2c1;
i2c8 = &aoi2c1;
can0 = &can0;
can1 = &can1;
@@ -62,6 +68,8 @@
spi3 = &spi1;
pcie3x4 = &dm3x4;
pcie3x1 = &rp3x1;
vi_sensor0 = &mipicsi0_4lane_port;
vi_sensor1 = &mipi1csi1_a_port;
};
/* 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 {
compatible = "simple-audio-card";
simple-audio-card,name = "Sound-Card-I2S0";
@@ -125,33 +138,296 @@
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87565_PA2 VO",
"AW87565_PA2 IN", "ES8156_DAC1 LOUT";
"Speaker", "AW87565_PA2 VO",
"AW87565_PA2 IN", "ES8156_DAC1 LOUT";
simple-audio-card,aux-devs = <&audio_aw87565_pa2>;
SOUND_CARD_LINK(0, i2s, i2s1, 0, es8156_dac1, 0);
SOUND_CARD_LINK(1, i2s, i2s1, 0, es7210_adc1, 0);
};
wcn_wifi: wireless-wlan {
compatible = "wlan-platdata";
WIFI,poweren-gpios = <&aw9535_1 11 GPIO_ACTIVE_HIGH>,
<&aw9535_1 12 GPIO_ACTIVE_HIGH>,
<&gpio0_porta 14 GPIO_ACTIVE_HIGH>;
power_on_after_init;
power_on_when_resume;
status = "okay";
};
lcd0_backlight: pwm-backlight@0 {
compatible = "pwm-backlight";
status = "okay";
pwms = <&pwm1 2 100000 0>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <7>;
enable-gpios = <&aw9535_1 15 GPIO_ACTIVE_HIGH>;
};
wcn_bt: wireless-bluetooth {
compatible = "bluetooth-platdata";
BT,power-gpios = <&ao_gpio1_porta 4 GPIO_ACTIVE_HIGH>,
<&aw9535_1 15 GPIO_ACTIVE_HIGH>;
status = "okay";
};
reg_vdd33_lcd0: regulator-vdd33-lcd0 {
compatible = "regulator-fixed";
regulator-name = "lcd0_vdd33";
regulator-min-microvolt = <3300000>;
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. */
chosen {
stdout-path = "serial4";
reg_vddtp33_lcd0: regulator-vddtp33-lcd0 {
compatible = "regulator-fixed";
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";
function = "aoi2c1";
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>;
input-enable;
input-schmitt-enable;
@@ -234,30 +541,9 @@
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 {
pins = "GPIO0_24", "GPIO0_25", "GPIO0_26", "GPIO0_27";
pins = "GPIO0_25";
function = "pcie_x1";
bias-disable;
drive-strength = <7>;
@@ -268,7 +554,7 @@
};
pcie_x4_pins: pcie_x4-1 {
pcie_x4-pins {
pins = "GPIO0_28", "GPIO0_29", "GPIO0_31";
pins = "GPIO0_29";
function = "pcie_x4";
bias-disable;
drive-strength = <7>;
@@ -339,14 +625,14 @@
slew-rate = <0>;
};
};
usb3_pins: usb3-1 {
usb3-pins {
pins = "GPIO0_27";
bt_gpios {
bt_wake_dev: bt-wake-dev {
pins = "GPIO0_17"; /* device-wake-gpios */
function = "gpio0";
bias-disable;
drive-strength = <13>;
bias-pull-up;
drive-strength = <7>;
input-disable;
input-schmitt-disable;
input-schmitt-enable;
slew-rate = <0>;
};
};
@@ -379,10 +665,10 @@
pins = "GPIO2_28", "GPIO2_29";
function = "i2c5";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
uart5_pins: uart5-1 {
@@ -411,10 +697,10 @@
pins = "GPIO2_8", "GPIO2_9";
function = "i2c6";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
i2s1_pins: i2s1-0 {
@@ -432,10 +718,10 @@
pins = "GPIO2_10", "GPIO2_11";
function = "i2c7";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
i2c4_pins: i2c4-2 {
@@ -443,10 +729,10 @@
pins = "GPIO2_26", "GPIO2_27";
function = "i2c4";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
pwm1_pins: pwm1-1 {
@@ -471,9 +757,20 @@
slew-rate = <0>;
};
};
sen_vclk_pins: sen_vclk-1 {
sen_vclk-pins {
pins = "GPIO3_0", "GPIO3_1";
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>;
@@ -534,16 +831,17 @@
};
&qspi0 {
cs-gpios = <&gpio0_porta 19 0>;
cs-gpios = <&gpio0 19 0>;
rx-sample-dly = <2>;
spi-swap-data = <1>;
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>;
status = "disabled";
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
@@ -563,6 +861,9 @@
pinctrl-0 = <&rtc_pins>;
compatible = "nxp,pcf8563";
reg = <0x51>;
interrupt-parent = <&ao_gpio0>;
interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
wakeup-source;
};
};
@@ -627,12 +928,76 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c6_pins>;
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 {
pinctrl-names = "default";
pinctrl-0 = <&i2c7_pins>;
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 {
@@ -641,33 +1006,99 @@
clock-frequency = <400000>;
status = "okay";
aw9535_0: gpio@20 {
compatible = "awinic,aw9535";
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <16>;
interrupt-parent = <&ao_gpio1>;
interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
gpio-line-names =
"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
"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
};
aw9535_0: gpio@20 {
compatible = "awinic,aw9535";
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <16>;
interrupt-parent = <&ao_gpio1>;
interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
gpio-line-names =
"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
"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
};
aw9535_1: gpio@21 {
compatible = "awinic,aw9535";
reg = <0x21>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <16>;
gpio-line-names =
"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
"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
};
aw9535_1: gpio@21 {
compatible = "awinic,aw9535";
reg = <0x21>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <16>;
gpio-line-names =
"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
"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
};
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 {
@@ -678,6 +1109,16 @@
&uart5 {
pinctrl-names = "default";
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 {
@@ -688,6 +1129,7 @@
&rp3x1 {
pinctrl-names = "default";
pinctrl-0 = <&pcie_x1_pins>;
status = "okay";
};
&dm3x4 {
@@ -717,11 +1159,6 @@
pinctrl-0 = <&pwm1_pins>;
};
&can0 {
pinctrl-names = "default";
pinctrl-0 = <&can0_pins>;
};
&hdmi_tx {
pinctrl-names = "default";
pinctrl-0 = <&hdmi_pins>;
@@ -734,16 +1171,15 @@
&emmc {
max-frequency = <196608000>;
non-removable;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
cap-mmc-highspeed;
mmc-hs200-1_8v;
io_fixed_1v8;
is_emmc;
no-sdio;
no-sd;
pull_up;
bus-width = <8>;
cap-mmc-highspeed;
};
&sdhci0 {
@@ -761,15 +1197,170 @@
post-power-on-delay-ms = <200>;
wprtn_ignore;
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 {
usb21-pwren-gpios = <&aw9535_1 8 GPIO_ACTIVE_HIGH>;
usb20-pwren-gpios = <&aw9535_1 9 GPIO_ACTIVE_HIGH>;
&usb20phy0 {
pwren-gpios = <&aw9535_1 8 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 {
pinctrl-names = "default";
pinctrl-0 = <&usb3_pins>;
typec-pwren-gpios = <&gpio0_porta 27 GPIO_ACTIVE_HIGH>;
dr_mode = "otg";
usb-role-switch;
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 {
compatible = "zhihe,p100-clk-emu";
compatible = "zhihe,a210-clk-emu";
};
&vidmem {
@@ -78,62 +78,6 @@
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.
* 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-die1.dtsi"
#include "a210-soc-peri.dtsi"
#include "a210-soc-peri-die1.dtsi"
#include "a210-platform-d2d.dtsi"
/ {
model = "A210 EVB D2D configuration";
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;
mmc1 = &sdhci0;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
serial3 = &uart3;
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 */
@@ -58,6 +94,11 @@
no-map;
};
npu1_mmu_memory@2130000000 {
reg = <0x21 0x30000000 0x00 0x04000000>;
no-map;
};
memblock-memory@17b800000 {
reg = <0x01 0x7b800000 0x00 0x04000000>;
no-map;
@@ -70,330 +111,306 @@
};
};
&uart0 {
status = "disabled";
/* DIE0 */
&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 {
status = "disabled";
&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>;
};
};
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 {
status = "disabled";
&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 {
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 {
current-speed = <115200>; /* OpenSBI */
};
&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";
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins>;
};
&hdmi_tx {
status = "disabled";
pinctrl-names = "default";
pinctrl-0 = <&hdmi_pins>;
};
&emmc {
max-frequency = <196608000>;
non-removable;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
cap-mmc-highspeed;
mmc-hs200-1_8v;
io_fixed_1v8;
is_emmc;
no-sdio;
no-sd;
pull_up;
bus-width = <8>;
cap-mmc-highspeed;
clk-delay-mmc-hs200 = <60>;
};
&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 {
status = "disabled";
/* DIE1 */
&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 {
status = "disabled";
&peri2_padctrl_die1 {
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 {
status = "disabled";
&qspi0_die1 {
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 {
status = "disabled";
&qspi1_die1 {
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 {
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";
};
&vidmem {
status = "disabled";
};
&usb2_0 {
status = "disabled";
};
&gpio0 {
status = "disabled";
};
&gpio1 {
status = "disabled";
};
&gpio2 {
status = "disabled";
};
&gpio3 {
status = "disabled";
};
&gpio4 {
status = "disabled";
&uart4_die1 {
current-speed = <115200>;
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins_die1>;
};

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;
pcie3x4 = &dm3x4;
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 */
@@ -140,76 +143,10 @@
status = "okay";
};
codec_dummy_pdm0: codec_dummy_pdm0 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC0";
#address-cells = <0>;
#size-cells = <0>;
codec_dmic: dmic-codec {
compatible = "dmic-codec";
num-channels = <8>;
#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 {
@@ -221,10 +158,10 @@
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87565_PA0 VO",
"Speaker", "AW87565_PA1 VO",
"AW87565_PA0 IN", "ES8156_DAC0 LOUT",
"AW87565_PA1 IN", "ES8156_DAC0 ROUT";
"Speaker", "AW87565_PA0 VO",
"Speaker", "AW87565_PA1 VO",
"AW87565_PA0 IN", "ES8156_DAC0 LOUT",
"AW87565_PA1 IN", "ES8156_DAC0 ROUT";
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(1, i2s, i2s1, 0, es7210_adc0, 0); /* I2S1 <-> es7210_adc0 */
@@ -239,10 +176,10 @@
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87565_PA2 VO",
"Speaker", "AW87565_PA3 VO",
"AW87565_PA2 IN", "ES8156_DAC1 LOUT",
"AW87565_PA3 IN", "ES8156_DAC1 ROUT";
"Speaker", "AW87565_PA2 VO",
"Speaker", "AW87565_PA3 VO",
"AW87565_PA2 IN", "ES8156_DAC1 LOUT",
"AW87565_PA3 IN", "ES8156_DAC1 ROUT";
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(1, i2s, i2s2, 0, es7210_adc1, 0); /* I2S2 <-> es7210_adc1 */
@@ -250,7 +187,7 @@
Sound_Card@2 {
compatible = "simple-audio-card";
simple-audio-card,name = "Sound-Card-I2S3";
simple-audio-card,name = "Sound-Card-HDMI";
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
@@ -259,6 +196,19 @@
};
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";
simple-audio-card,name = "Sound-Card-TDM";
#address-cells = <1>;
@@ -266,30 +216,64 @@
status = "okay";
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(2, dsp_b, tdm_slot2, 0, es7210_adc2, 0); /* TDM_SLOT2 <-> es7210_adc2 */
SOUND_CARD_LINK(3, dsp_b, tdm_slot3, 0, es7210_adc2, 0); /* TDM_SLOT3 <-> es7210_adc2 */
SOUND_CARD_LINK(4, dsp_b, tdm_slot4, 0, es7210_adc3, 0); /* TDM_SLOT4 <-> es7210_adc3 */
SOUND_CARD_LINK(5, dsp_b, tdm_slot5, 0, es7210_adc3, 0); /* TDM_SLOT5 <-> es7210_adc3 */
SOUND_CARD_LINK(6, dsp_b, tdm_slot6, 0, es7210_adc3, 0); /* TDM_SLOT6 <-> es7210_adc3 */
SOUND_CARD_LINK(7, dsp_b, tdm_slot7, 0, es7210_adc3, 0); /* TDM_SLOT7 <-> es7210_adc3 */
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, dummy_tdm, 0); /* TDM_SLOT2 <-> 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, dummy_tdm, 0); /* TDM_SLOT4 <-> 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, dummy_tdm, 0); /* TDM_SLOT6 <-> 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";
simple-audio-card,name = "Sound-Card-PDM";
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
SOUND_CARD_LINK(0, pdm, pdm0, 0, dummy_pdm0, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(1, pdm, pdm1, 1, dummy_pdm1, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(2, pdm, pdm2, 2, dummy_pdm2, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(3, pdm, pdm3, 3, dummy_pdm3, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(4, pdm, pdm4, 4, dummy_pdm4, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(5, pdm, pdm5, 5, dummy_pdm5, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(6, pdm, pdm6, 6, dummy_pdm6, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(7, pdm, pdm7, 7, dummy_pdm7, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(0, pdm, pdm0, 0, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(1, pdm, pdm1, 1, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(2, pdm, pdm2, 2, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(3, pdm, pdm3, 3, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(4, pdm, pdm4, 4, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(5, pdm, pdm5, 5, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(6, pdm, pdm6, 6, dmic, 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";
function = "i2s0";
bias-disable;
drive-strength = <13>;
input-schmitt-disable;
drive-strength = <20>;
input-schmitt-enable;
slew-rate = <0>;
};
};
sata_p1_pins: sata_p1-0 {
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";
bias-disable;
drive-strength = <7>;
@@ -412,7 +396,7 @@
};
sata_p0_pins: sata_p0-0 {
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";
bias-disable;
drive-strength = <7>;
@@ -426,10 +410,10 @@
pins = "GPIO0_22", "GPIO0_23";
function = "i2c2";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
tdm_pins: tdm-0 {
@@ -437,7 +421,7 @@
pins = "GPIO0_19", "GPIO0_20", "GPIO0_21";
function = "tdm";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
@@ -448,10 +432,10 @@
pins = "GPIO0_24", "GPIO0_25";
function = "i2c0";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
can0_pins: can0-0 {
@@ -480,10 +464,10 @@
pins = "GPIO0_26", "GPIO0_27";
function = "i2c1";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
can1_pins: can1-0 {
@@ -509,7 +493,7 @@
};
pcie_x1_pins: pcie_x1-1 {
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";
bias-disable;
drive-strength = <7>;
@@ -555,7 +539,7 @@
pins = "GPIO0_28", "GPIO0_29", "GPIO1_1";
function = "spi0";
bias-disable;
drive-strength = <7>;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
@@ -635,7 +619,7 @@
};
pdm_pins: pdm-0 {
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";
bias-disable;
drive-strength = <7>;
@@ -673,10 +657,10 @@
pins = "GPIO2_2", "GPIO2_3";
function = "i2c5";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
uart5_pins: uart5-0 {
@@ -705,10 +689,10 @@
pins = "GPIO2_4", "GPIO2_5";
function = "i2c6";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
uart6_pins: uart6-0 {
@@ -738,7 +722,7 @@
function = "i2s1";
bias-disable;
drive-strength = <13>;
input-schmitt-disable;
input-schmitt-enable;
slew-rate = <0>;
};
};
@@ -800,10 +784,10 @@
// pins = "GPIO2_6", "GPIO2_7";
// function = "i2c4";
// bias-disable;
// drive-strength = <7>;
// drive-strength = <25>;
// input-enable;
// input-schmitt-enable;
// slew-rate = <0>;
// slew-rate = <1>;
// };
// };
i2s2_pins: i2s2-0 {
@@ -812,7 +796,7 @@
function = "i2s2";
bias-disable;
drive-strength = <13>;
input-schmitt-disable;
input-schmitt-enable;
slew-rate = <0>;
};
};
@@ -842,10 +826,10 @@
pins = "GPIO2_10", "GPIO2_11";
function = "i2c7";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
spi1_pins: spi1-1 {
@@ -853,7 +837,7 @@
pins = "GPIO2_17", "GPIO2_21", "GPIO2_22";
function = "spi1";
bias-disable;
drive-strength = <7>;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
@@ -866,7 +850,7 @@
function = "i2s3";
bias-disable;
drive-strength = <13>;
input-schmitt-disable;
input-schmitt-enable;
slew-rate = <0>;
};
};
@@ -875,10 +859,10 @@
pins = "GPIO2_26", "GPIO2_27";
function = "i2c4";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
pwm1_pins: pwm1-1 {
@@ -897,10 +881,10 @@
pins = "GPIO2_24", "GPIO2_25";
function = "i2c3";
bias-disable;
drive-strength = <7>;
drive-strength = <25>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
slew-rate = <1>;
};
};
hdmi_pins: hdmi-0 {
@@ -914,9 +898,20 @@
slew-rate = <0>;
};
};
sen_vclk_pins: sen_vclk-1 {
sen_vclk-pins {
pins = "GPIO3_0", "GPIO3_1";
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>;
@@ -1047,13 +1042,13 @@
};
&spi0 {
cs-gpios = <&gpio0_porta 30 0>;
cs-gpios = <&gpio0 30 0>;
rx-sample-delay-ns = <4>;
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
#address-cells = <1>;
#size-cells = <1>;
reg = <0>;
@@ -1062,15 +1057,15 @@
};
&spi1 {
cs-gpios = <&gpio2_porta 18 0>;
cs-gpios = <&gpio2 18 0>;
rx-sample-delay-ns = <4>;
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
#address-cells = <1>;
#size-cells = <1>;
reg = <0>;
@@ -1079,16 +1074,16 @@
};
&qspi0 {
cs-gpios = <&gpio0_porta 19 0>;
cs-gpios = <&gpio0 19 0>;
rx-sample-dly = <2>;
spi-swap-data = <1>;
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
@@ -1099,16 +1094,16 @@
};
&qspi1 {
cs-gpios = <&gpio2_porta 29 0>;
cs-gpios = <&gpio2 29 0>;
rx-sample-dly = <2>;
spi-swap-data = <1>;
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
pinctrl-names = "default";
pinctrl-0 = <&qspi1_pins>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
@@ -1233,7 +1228,7 @@
work-mode = "ES7210_TDM_1LRCK_DSPB";
channels-max = <8>;
sound-name-prefix = "ES7210_ADC2";
status = "disabled";
status = "okay";
};
codec_es7210_adc3: es7210@43 {
@@ -1243,7 +1238,7 @@
work-mode = "ES7210_TDM_1LRCK_DSPB";
channels-max = <8>;
sound-name-prefix = "ES7210_ADC3";
status = "disabled";
status = "okay";
};
};
@@ -1251,11 +1246,16 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c4_pins>;
clock-frequency = <400000>;
status = "okay";
lt8911i2c: lt8911i2c@29{
compatible = "i2c,lt8911";
reg = <0x29>;
};
usbc: fusb302@0 {
compatible = "fcs,fusb302";
reg = <0x0>;
interrupt-parent = <&ao_gpio1_porta>;
interrupt-parent = <&ao_gpio1>;
interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
pinctrl-names = "default";
status = "disabled";
@@ -1290,7 +1290,7 @@
remote-endpoint = <&typec_con_usb>;
};
};
};
};
};
&i2c5 {
@@ -1305,11 +1305,6 @@
clock-frequency = <400000>;
};
&dm3x4 {
pinctrl-names = "default";
pinctrl-0 = <&pcie_x4_pins>;
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
@@ -1340,7 +1335,6 @@
pinctrl-0 = <&can2_pins>;
};
&audio_i2s2 {
pinctrl-names = "default";
pinctrl-0 = <&i2s2_pins>;
@@ -1365,6 +1359,7 @@
&sata {
pinctrl-names = "default";
pinctrl-0 = <&sata_p0_pins>;
status = "okay";
};
&hdmi_tx {
@@ -1375,16 +1370,15 @@
&emmc {
max-frequency = <196608000>;
non-removable;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
cap-mmc-highspeed;
mmc-hs200-1_8v;
io_fixed_1v8;
is_emmc;
no-sdio;
no-sd;
pull_up;
bus-width = <8>;
cap-mmc-highspeed;
};
&sdhci0 {
@@ -1406,62 +1400,6 @@
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 */
/*
@@ -1483,10 +1421,10 @@
GPMUX_SEL_04 -> 1
GPMUX_SEL_11 -> 1
*/
// &audio_i2s_8ch_sd0 {
// pinctrl-names = "default";
// pinctrl-0 = <&i2s3_pins>;
// };
&audio_i2s_8ch_sd0 {
pinctrl-names = "default";
pinctrl-0 = <&i2s3_pins>;
};
/*
expansion IO: audio_tdm
@@ -1519,10 +1457,22 @@
GPMUX_SEL_10 -> 0
通过J206跳线切换到pcie x1
*/
// &rp3x1 {
// pinctrl-names = "default";
// pinctrl-0 = <&pcie_x1_pins>;
// };
&rp3x1 {
pinctrl-names = "default";
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
@@ -1682,3 +1632,105 @@
&usb2_0 {
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";
};
codec_dummy_pdm0: codec_dummy_pdm0 {
compatible = "zhihe,dummy-pcm-pdm";
sound-name-prefix = "DMIC0";
#address-cells = <0>;
#size-cells = <0>;
codec_dmic: dmic-codec {
compatible = "dmic-codec";
num-channels = <8>;
#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 {
@@ -255,19 +189,19 @@
#size-cells = <0>;
status = "okay";
SOUND_CARD_LINK(0, pdm, pdm0, 0, dummy_pdm0, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(1, pdm, pdm1, 1, dummy_pdm1, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(2, pdm, pdm2, 2, dummy_pdm2, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(3, pdm, pdm3, 3, dummy_pdm3, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(4, pdm, pdm4, 4, dummy_pdm4, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(5, pdm, pdm5, 5, dummy_pdm5, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(6, pdm, pdm6, 6, dummy_pdm6, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(7, pdm, pdm7, 7, dummy_pdm7, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(0, pdm, pdm0, 0, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(1, pdm, pdm1, 1, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(2, pdm, pdm2, 2, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(3, pdm, pdm3, 3, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(4, pdm, pdm4, 4, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(5, pdm, pdm5, 5, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(6, pdm, pdm6, 6, dmic, 0); /* PDM <-> Dmic */
SOUND_CARD_LINK(7, pdm, pdm7, 7, dmic, 0); /* PDM <-> Dmic */
};
};
&clk {
compatible = "zhihe,p100-clk-haps";
compatible = "zhihe,a210-clk-haps";
/* pll */
audio0_pll_foutvco_frequency = <150000000>;
audio1_pll_foutvco_frequency = <80000000>;
@@ -319,7 +253,7 @@
};
&spi0 {
cs-gpios = <&gpio1_porta 7 0>;
cs-gpios = <&gpio1 7 0>;
rx-sample-delay-ns = <10>;
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
@@ -345,7 +279,7 @@
};
&spi1 {
// cs-gpios = <&gpio2_porta 15 0>;
// cs-gpios = <&gpio2 15 0>;
rx-sample-delay-ns = <10>;
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
@@ -362,7 +296,7 @@
};
&qspi0 {
cs-gpios = <&gpio0_porta 19 0>;
cs-gpios = <&gpio0 19 0>;
rx-sample-dly = <4>;
pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>;
@@ -396,7 +330,7 @@
};
&qspi1 {
cs-gpios = <&gpio2_porta 29 0>;
cs-gpios = <&gpio2 29 0>;
rx-sample-dly = <4>;
pinctrl-names = "default";
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 {
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";
};
&uart4 {
current-speed = <115200>; /* OpenSBI */
};
&uart6 {
status = "disabled";
};
@@ -58,6 +54,10 @@
status = "disabled";
};
&can0 {
status = "disabled";
};
&can1 {
status = "disabled";
};
@@ -106,6 +106,14 @@
status = "okay";
};
&auxdisp {
status = "disabled";
};
&dpu_enc0 {
status = "disabled";
};
&audio_i2s0 {
status = "disabled";
};
@@ -179,60 +187,36 @@
};
/* dfmu/iommu */
&vp_dfmu_iommu {
status = "disabled";
&iommu {
status = "okay";
};
&vp_dfmu_mt {
status = "disabled";
&dfmu_mt_vp {
status = "disabled";
};
&npu_dfmu_iommu {
status = "disabled";
&dfmu_mt_npu {
status = "disabled";
};
&npu_dfmu_mt {
status = "disabled";
&dfmu_mt_vi {
status = "disabled";
};
&vi_dfmu_iommu {
status = "disabled";
&dfmu_mt_vo {
status = "disabled";
};
&vi_dfmu_mt {
status = "disabled";
&dfmu_mt_peri1 {
status = "disabled";
};
&vo_dfmu_iommu {
status = "disabled";
&dfmu_mt_pcie {
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";
&dfmu_mt_usb {
status = "disabled";
};
&bmu9 {

View File

@@ -89,10 +89,6 @@
status = "disabled";
};
&uart4 {
current-speed = <115200>; /* OpenSBI */
};
&uart5 {
status = "disabled";
};
@@ -266,6 +262,14 @@
status = "disabled";
};
&auxdisp {
status = "disabled";
};
&dpu_enc0 {
status = "disabled";
};
&audio_i2s0 {
status = "disabled";
};
@@ -441,3 +445,31 @@
&power_npu_ip {
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 {
// status = "disabled";
// };
@@ -39,12 +34,12 @@
status = "disabled";
};
&uart3 {
&uart2 {
status = "disabled";
};
&uart4 {
current-speed = <115200>; /* OpenSBI */
&uart3 {
status = "disabled";
};
&uart5 {
@@ -71,10 +66,18 @@
status = "disabled";
};
&spi1 {
status = "disabled";
};
&qspi0 {
status = "disabled";
};
&qspi1 {
status = "okay";
};
&i2c1 {
status = "disabled";
};
@@ -87,6 +90,10 @@
status = "disabled";
};
&i2c4 {
status = "disabled";
};
&i2c5 {
status = "disabled";
};
@@ -99,30 +106,6 @@
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";
};
@@ -152,10 +135,6 @@
status = "disabled";
};
&uart2 {
status = "disabled";
};
&timer0 {
status = "disabled";
};
@@ -184,7 +163,23 @@
status = "disabled";
};
&i2c4 {
&rp3x1 {
status = "disabled";
};
&dm3x4 {
status = "disabled";
};
&sata {
status = "disabled";
};
&auxdisp {
status = "disabled";
};
&dpu_enc0 {
status = "disabled";
};
@@ -192,18 +187,47 @@
status = "disabled";
};
&dm3x4 {
&audio_i2s1 {
status = "okay";
};
&rp3x1 {
&audio_i2s2 {
status = "disabled";
};
// &usb31_zhihe {
// status = "disabled";
// };
&pwm0 {
status = "disabled";
};
// &sata {
// status = "disabled";
// };
&pwm2 {
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";
};
&uart4 {
current-speed = <115200>; /* OpenSBI */
};
&uart5 {
status = "disabled";
};
@@ -190,6 +186,14 @@
status = "disabled";
};
&auxdisp {
status = "disabled";
};
&dpu_enc0 {
status = "disabled";
};
&clk_gpu {
status = "disabled";
};
@@ -221,3 +225,31 @@
&clk_d2d {
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";
mmu-type = "riscv,sv39";
cpu-freq = "2Ghz";
cpu-icache = "32KB";
cpu-dcache = "32KB";
cpu-l2cache = "512KB";
i-cache-block-size = <64>;
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-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0";
capacity-dmips-mhz = <768>;
#cooling-cells = <2>;
@@ -46,11 +49,14 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39";
cpu-freq = "2Ghz";
cpu-icache = "32KB";
cpu-dcache = "32KB";
cpu-l2cache = "512KB";
i-cache-block-size = <64>;
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-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0";
capacity-dmips-mhz = <768>;
#cooling-cells = <2>;
@@ -70,11 +76,14 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39";
cpu-freq = "2Ghz";
cpu-icache = "32KB";
cpu-dcache = "32KB";
cpu-l2cache = "512KB";
i-cache-block-size = <64>;
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-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0";
capacity-dmips-mhz = <768>;
#cooling-cells = <2>;
@@ -94,11 +103,15 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39";
cpu-freq = "2Ghz";
cpu-icache = "32KB";
cpu-dcache = "32KB";
i-cache-block-size = <64>;
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-tlb = "1024 4-ways";
cpu-cacheline = "64Bytes";
cpu-vector = "1.0";
capacity-dmips-mhz = <768>;
#cooling-cells = <2>;
@@ -119,11 +132,15 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39";
cpu-freq = "2.6Ghz";
cpu-icache = "32KB";
cpu-dcache = "32KB";
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-cacheline = "64Bytes";
cpu-vector = "1.0";
capacity-dmips-mhz = <1024>;
#cooling-cells = <2>;
@@ -143,11 +160,14 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39";
cpu-freq = "2.6Ghz";
cpu-icache = "32KB";
cpu-dcache = "32KB";
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-cacheline = "64Bytes";
cpu-vector = "1.0";
capacity-dmips-mhz = <1024>;
#cooling-cells = <2>;
@@ -167,11 +187,14 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39";
cpu-freq = "2.6Ghz";
cpu-icache = "32KB";
cpu-dcache = "32KB";
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-cacheline = "64Bytes";
cpu-vector = "1.0";
capacity-dmips-mhz = <1024>;
#cooling-cells = <2>;
@@ -191,11 +214,14 @@
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "svpbmt", "sscofpmf";
mmu-type = "riscv,sv39";
cpu-freq = "2.6Ghz";
cpu-icache = "32KB";
cpu-dcache = "32KB";
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-cacheline = "64Bytes";
cpu-vector = "1.0";
capacity-dmips-mhz = <1024>;
#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 {
cluster2 {
core0 {
@@ -251,11 +294,7 @@
#size-cells = <2>;
ranges;
d2d: d2d {
compatible = "zhihe,d2d";
nr_dies = <2>;
};
/* OPENSBI */
/* OPENSBI */
reset: reset-sample {
compatible = "zhihe,reset-sample";
reg = <0x00 0x00 0x00 0x00>;
@@ -310,8 +349,595 @@
reg = <0x00 0x1a000000 0x0 0x02000000>;
reg-names = "control";
riscv,max-priority = <7>;
riscv,ndev = <400>;
cpu-id = <8>;
riscv,ndev = <351>;
};
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";
};
uart0_die1: serial@2002014000 {
compatible = "snps,dw-apb-uart", "ns16550";
reg = <0x20 0x02014000 0x0 0x400>;
interrupt-parent = <&intc_die1>;
interrupts = <321>;
clock-names = "baudclk";
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
peri1_padctrl_die1: peri1-padctrl@2002026000 {
compatible = "zhihe,a210-group1-pinctrl";
reg = <0x20 0x02026000 0x0 0x1000>;
clocks = <&clk_peri_die1 PERI1_PAD_CTRL_PCLK_EN>;
clock-names = "pclk";
status = "okay";
};
uart1_die1: serial@2002015000 {
compatible = "snps,dw-apb-uart";
reg = <0x20 0x02015000 0x0 0x1000>;
interrupt-parent = <&intc_die1>;
interrupts = <322>;
clocks = <&clk PERI1_UART1_SCLK_EN>;
clock-names = "baudclk";
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "disabled";
peri2_padctrl_die1: peri2-padctrl@2008411000 {
compatible = "zhihe,a210-group2-pinctrl";
reg = <0x20 0x08411000 0x0 0x1000>;
clocks = <&clk_peri_die1 PERI2_PAD_CTRL_PCLK_EN>;
clock-names = "pclk";
status = "okay";
};
uart2_die1: serial@2002016000 {
compatible = "snps,dw-apb-uart";
reg = <0x20 0x02016000 0x0 0x1000>;
interrupt-parent = <&intc_die1>;
interrupts = <323>;
clocks = <&clk PERI1_UART2_SCLK_EN>;
clock-names = "baudclk";
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "disabled";
gpio@2002012000 {
compatible = "snps,dw-apb-gpio";
reg = <0x20 0x02012000 0x0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clk_peri_die1 PERI1_GPIO0_PCLK_EN>,
<&clk_peri_die1 PERI1_GPIO0_DBCLK_EN>;
clock-names = "bus", "db";
status = "okay";
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 {
compatible = "snps,dw-apb-uart";
reg = <0x20 0x02017000 0x0 0x1000>;
interrupt-parent = <&intc_die1>;
interrupts = <37>;
clocks = <&clk PERI1_UART3_SCLK_EN>;
clock-names = "baudclk";
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "disabled";
gpio@2002013000 {
compatible = "snps,dw-apb-gpio";
reg = <0x20 0x02013000 0x0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clk_peri_die1 PERI1_GPIO1_PCLK_EN>,
<&clk_peri_die1 PERI1_GPIO1_DBCLK_EN>;
clock-names = "bus", "db";
status = "okay";
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";
reg = <0x20 0x0008401000 0x0 0x400>;
reg = <0x20 0x08401000 0x0 0x400>;
interrupt-parent = <&intc_die1>;
interrupts = <325>;
clocks = <&clk PERI2_UART4_SCLK_EN>;
clock-names = "baudclk";
clocks = <&clk_peri_die1 PERI2_UART4_PCLK_EN>, <&clk_peri_die1 PERI2_UART4_SCLK_EN>;
clock-names = "apb_pclk", "baudclk";
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay";
};
mbox_920_die1: mbox@2000320000 {
compatible = "zhihe,a210-mbox";
reg = <0x20 0x00321000 0x0 0x1000>, //mailbox1的中断通道
compatible = "zhihe,mailbox";
reg = <0x20 0x00321000 0x0 0x1000>,
<0x20 0x00320000 0x0 0x1000>,
<0x20 0x00322000 0x0 0x1000>,
<0x00 0x00312000 0x0 0x1000>,
<0x20 0x00312000 0x0 0x1000>;
<0x20 0x00311000 0x0 0x1000>;
reg-names = "interrupt_addr",
"local_addr0",
"local_addr1",
"remote_icu0",
"remote_icu1";
"remote_icu0";
interrupt-parent = <&intc_die1>;
interrupts = <336 IRQ_TYPE_LEVEL_HIGH>;
icu_cpu_id = <1>;
#mbox-cells = <2>;
version = <1>;
status = "okay";
};
aon_die1_to_die0: aon_subsys_die1_to_die0 {
compatible = "zhihe,a210-aon";
mbox-names = "aon2";
mboxes = <&mbox_920_die1 1 0>; //parent / channel / type
aon_die1: aon_subsys1@20308f8000 {
compatible = "zhihe,aon";
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>;
version = <1>;
status = "okay";
};
aon_die1_to_die1: aon_subsys_die1_to_die1 {
compatible = "zhihe,a210-aon";
mbox-names = "aon3";
mboxes = <&mbox_920_die1 1 0>;
#mbox-cells = <2>;
npu1: vipcore1@0x2007000000 {
compatible = "verisilicon,vipcore1";
reg = <0x20 0x07000000 0x00 0x10000>;
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";
};
};

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,routing =
"Speaker", "AW87565_PA2 VO",
"AW87565_PA2 IN", "ES8156_DAC1 LOUT";
"Speaker", "AW87565_PA2 VO",
"AW87565_PA2 IN", "ES8156_DAC1 LOUT";
simple-audio-card,aux-devs = <&audio_aw87565_pa2>;
SOUND_CARD_LINK(0, i2s, i2s1, 0, es8156_dac1, 0);
SOUND_CARD_LINK(1, i2s, i2s1, 0, es7210_adc1, 0);
@@ -505,16 +505,16 @@
};
&qspi0 {
cs-gpios = <&gpio0_porta 19 0>;
cs-gpios = <&gpio0 19 0>;
rx-sample-dly = <2>;
spi-swap-data = <1>;
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>;
spi-max-frequency = <42000000>;
#address-cells = <1>;
#size-cells = <1>;
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_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_PREEMPT=y
CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
@@ -17,6 +16,7 @@ CONFIG_NUMA_BALANCING=y
CONFIG_CGROUPS=y
CONFIG_MEMCG=y
CONFIG_CGROUP_SCHED=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
@@ -38,17 +38,29 @@ CONFIG_PERF_EVENTS=y
CONFIG_CRASH_DUMP=y
CONFIG_ARCH_ZHIHE=y
CONFIG_XUANTIE_SSTC=y
CONFIG_ERRATA_THEAD=y
# CONFIG_ERRATA_THEAD_PBMT is not set
CONFIG_ARCH_THEAD=y
CONFIG_ARCH_XUANTIE=y
CONFIG_SOC_VIRT=y
CONFIG_NONPORTABLE=y
CONFIG_SMP=y
CONFIG_NR_CPUS=16
CONFIG_NUMA=y
CONFIG_XUANTIE_ISA=y
CONFIG_RISCV_SBI_V01=y
# CONFIG_SUSPEND is not set
CONFIG_PM=y
CONFIG_PM_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_MODULES=y
CONFIG_MODULE_UNLOAD=y
@@ -60,8 +72,6 @@ CONFIG_CMA_SYSFS=y
CONFIG_CMA_AREAS=16
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_PNP=y
@@ -74,46 +84,68 @@ CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=y
CONFIG_BPFILTER=y
CONFIG_BRIDGE=y
CONFIG_VLAN_8021Q=m
CONFIG_DNS_RESOLVER=y
CONFIG_NETLINK_DIAG=y
CONFIG_CAN=m
CONFIG_CAN_J1939=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_MAC80211=y
CONFIG_MAC80211=m
CONFIG_RFKILL=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
# CONFIG_ETHTOOL_NETLINK is not set
CONFIG_PCI=y
CONFIG_PCIE_ZH=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_TH1520_AON_PD=y
CONFIG_TH1520_PROC_DEBUG=y
CONFIG_ZHIHE_PROC_DEBUG=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_OF_PARTS=m
CONFIG_MTD_BLOCK=y
CONFIG_MTD_SLRAM=m
CONFIG_MTD_PHRAM=m
CONFIG_MTD_SPI_NAND=y
CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_UBI=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=1
CONFIG_VIRTIO_BLK=y
CONFIG_PA_BLK_DEV=y
CONFIG_BLK_DEV_NVME=m
CONFIG_TH1520_DSMART_CARD=y
CONFIG_IO_EVENT_WRAPER=y
CONFIG_EEPROM_AT24=m
CONFIG_EEPROM_AT24=y
CONFIG_BLK_DEV_SD=m
CONFIG_ATA=m
CONFIG_AHCI_DWC=m
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
CONFIG_BLK_DEV_MD=y
CONFIG_MD_RAID0=m
CONFIG_MD_RAID1=m
CONFIG_MD_RAID456=m
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
CONFIG_MACVLAN=y
CONFIG_IPVLAN=y
CONFIG_VETH=y
CONFIG_VIRTIO_NET=y
CONFIG_NLMON=y
# CONFIG_NET_VENDOR_3COM 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_STMMAC_ETH=y
# CONFIG_DWMAC_GENERIC is not set
CONFIG_DWMAC_THEAD=y
CONFIG_DWMAC_ZHIHE=y
# CONFIG_NET_VENDOR_SUN 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_WIZNET is not set
# CONFIG_NET_VENDOR_XILINX is not set
CONFIG_MICROSEMI_PHY=y
CONFIG_MOTORCOMM_PHY=y
CONFIG_REALTEK_PHY=y
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_IWLMVM=m
CONFIG_HOSTAP=y
CONFIG_HOSTAP_FIRMWARE=y
CONFIG_HOSTAP_FIRMWARE_NVRAM=y
# CONFIG_RTL_CARDS is not set
CONFIG_RTW88=m
CONFIG_RTW88_8822CS=m
CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set
CONFIG_RTW88_8723DS=m
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_SERIAL_8250=y
# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
CONFIG_SERIAL_8250_CONSOLE=y
@@ -203,7 +249,12 @@ CONFIG_SERIAL_8250_NR_UARTS=10
CONFIG_SERIAL_8250_RUNTIME_UARTS=10
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_VIRTIO_CONSOLE=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_HELPER_AUTO is not set
CONFIG_I2C_SMBUS=m
@@ -215,13 +266,20 @@ CONFIG_SPI_DW_MMIO=y
CONFIG_SPI_SPIDEV=y
# CONFIG_PTP_1588_CLOCK is not set
CONFIG_PINCTRL=y
CONFIG_PINCTRL_TH1520=y
CONFIG_PINCTRL_A210=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_DWAPB=y
CONFIG_GPIO_PCA953X=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_THERMAL=y
CONFIG_THERMAL_STATISTICS=y
CONFIG_CPU_THERMAL=y
CONFIG_THERMAL_EMULATION=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_WATCHDOG_OPEN_TIMEOUT=32
@@ -231,20 +289,71 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=m
CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=m
CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP=y
CONFIG_DW_WATCHDOG=y
CONFIG_TH1520_PMIC_WATCHDOG=y
CONFIG_ZHIHE_WATCHDOG=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_WL2866D=y
# CONFIG_MEDIA_CEC_SUPPORT is not set
CONFIG_MEDIA_SUPPORT=y
# CONFIG_DVB_CORE is not set
CONFIG_MEDIA_USB_SUPPORT=y
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_LOAD_EDID_FIRMWARE=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_VERISILICON_DW_DP_P100=y
CONFIG_ZHIHE_AUXDISP=y
CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_PWM=y
# CONFIG_VGA_CONSOLE is not set
CONFIG_LOGO=y
CONFIG_SOUND=m
@@ -252,33 +361,52 @@ CONFIG_SND=m
CONFIG_SND_USB_AUDIO=m
CONFIG_SND_USB_AUDIO_MIDI_V2=y
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_TDM=m
CONFIG_SND_SOC_ZHIHE_PDM=m
CONFIG_SND_SOC_AW87519=m
CONFIG_SND_SOC_AW87565=m
CONFIG_SND_SOC_ES7210=m
CONFIG_SND_SOC_ES8156=m
CONFIG_SND_SOC_ES8323=m
CONFIG_SND_SIMPLE_CARD=m
CONFIG_USB=m
CONFIG_USB_XHCI_HCD=m
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_PRINTER=m
CONFIG_USB_WDM=m
CONFIG_USB_STORAGE=m
CONFIG_USB_STORAGE_SDDR09=m
CONFIG_USB_STORAGE_SDDR55=m
CONFIG_USB_DWC3=m
# CONFIG_USB_DWC3_HAPS is not set
# CONFIG_USB_DWC3_OF_SIMPLE is not set
CONFIG_USB_DWC2=m
CONFIG_USB_ONBOARD_HUB=m
CONFIG_USB_GADGET=m
CONFIG_USB_CONFIGFS=m
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_ETH_EEM=y
CONFIG_USB_GADGETFS=m
CONFIG_USB_FUNCTIONFS=m
CONFIG_USB_FUNCTIONFS_RNDIS=y
CONFIG_USB_FUNCTIONFS_GENERIC=y
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_TCPM=m
CONFIG_TYPEC_TCPCI=m
CONFIG_TYPEC_FUSB302=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
@@ -286,29 +414,49 @@ CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_OF_DWCMSHC=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PCF8563=m
CONFIG_RTC_DRV_XGENE=y
CONFIG_DMADEVICES=y
CONFIG_DW_AXI_DMAC=y
CONFIG_DMATEST=m
CONFIG_SW_SYNC=y
CONFIG_UDMABUF=y
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_CLK_TH1520_FM=y
CONFIG_CLK_A210=y
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_TH1520=y
CONFIG_MAILBOX=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_D2D=m
CONFIG_EXTCON=y
CONFIG_IIO=y
CONFIG_IIO_SW_DEVICE=y
CONFIG_PWM=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_TEE=m
CONFIG_OPTEE=m
CONFIG_IOPMP=y
CONFIG_ZH_IOPMP=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_F2FS_FS=m
CONFIG_EXPORTFS_BLOCK_OPS=y
CONFIG_QUOTA=y
CONFIG_AUTOFS_FS=y
@@ -323,7 +471,7 @@ CONFIG_NTFS3_FS=m
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_CONFIGFS_FS=y
CONFIG_JFFS2_FS=y
CONFIG_UBIFS_FS=y
CONFIG_EROFS_FS=y
CONFIG_NFS_FS=y
@@ -339,7 +487,19 @@ CONFIG_NFS_USE_LEGACY_DNS=y
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_UTF8=m
CONFIG_CRYPTO_USER=y
# 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_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
@@ -349,8 +509,11 @@ CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_SCHEDSTATS=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_LOCK_TORTURE_TEST=m
CONFIG_RCU_TORTURE_TEST=m
# CONFIG_RCU_TRACE is not set
CONFIG_FTRACE_SYSCALLS=y
CONFIG_BPF_KPROBE_OVERRIDE=y

View File

@@ -5,7 +5,7 @@ CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_PREEMPT=y
CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
@@ -71,6 +71,11 @@ CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=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_NETLINK_DIAG=y
CONFIG_BT=y
@@ -81,7 +86,7 @@ CONFIG_BT_HIDP=y
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_RTL3WIRE=y
CONFIG_CFG80211=y
CONFIG_CFG80211=m
CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=y
CONFIG_RFKILL=y
@@ -188,6 +193,7 @@ CONFIG_SUNXI_WATCHDOG=y
CONFIG_TH1520_PMIC_WATCHDOG=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_WL2866D=m
CONFIG_MEDIA_SUPPORT=y
# CONFIG_DVB_CORE is not set
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))
return false;
out:
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
return false;

View File

@@ -26,8 +26,8 @@
#include <asm/iomb.h>
/* p100-specific barrier to enforce ordering on devices, don't use in portable drivers*/
#define dma_mb() p100_iomb()
#define dma_wmb() p100_iowmb()
#define dma_mb() a210_iomb()
#define dma_wmb() a210_iowmb()
/* These barriers do not need to enforce ordering on devices, just memory. */
#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)
#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
#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
#define P100_IOMB_H
#ifndef A210_IOMB_H
#define A210_IOMB_H
inline void p100_iomb(void);
inline void p100_iowmb(void);
inline void a210_iomb(void);
inline void a210_iowmb(void);
#endif

View File

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

View File

@@ -12,6 +12,7 @@
#include <vdso/processor.h>
#include <asm/ptrace.h>
#include <asm/hw_breakpoint.h>
#ifdef CONFIG_64BIT
#define DEFAULT_MAP_WINDOW (UL(1) << (MMAP_VA_BITS - 1))
@@ -70,6 +71,7 @@
#ifndef __ASSEMBLY__
struct task_struct;
struct perf_event;
struct pt_regs;
/* CPU-specific state of a task */
@@ -83,6 +85,11 @@ struct thread_struct {
unsigned long vstate_ctrl;
struct __riscv_v_ext_state vstate;
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 */

View File

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

View File

@@ -32,6 +32,7 @@ enum sbi_ext_id {
SBI_EXT_SUSP = 0x53555350,
SBI_EXT_PMU = 0x504D55,
SBI_EXT_CONFIG_IOPMP = 0x5A5A5A5A,
SBI_EXT_DBTR = 0x44425452,
/* Experimentals extensions must lie within this range */
SBI_EXT_EXPERIMENTAL_START = 0x08000000,
@@ -47,6 +48,34 @@ enum sbi_ext_config_iopmp_fid {
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 {
SBI_EXT_BASE_GET_SPEC_VERSION = 0,
SBI_EXT_BASE_GET_IMP_ID,
@@ -288,9 +317,6 @@ void sbi_set_timer(uint64_t stime_value);
void sbi_shutdown(void);
void sbi_send_ipi(unsigned int cpu);
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,
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)
{
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 */

View File

@@ -11,6 +11,9 @@
#include <asm/smp.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
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)
void flush_tlb_all(void);
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_range(struct vm_area_struct *vma, unsigned long start,
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
#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
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();
}
#define flush_tlb_mm(mm) flush_tlb_all()
#endif /* !CONFIG_SMP || !CONFIG_MMU */
/* Flush a range of kernel pages */
static inline void flush_tlb_kernel_range(unsigned long start,
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 */

View File

@@ -15,6 +15,9 @@
#define PTRACE_GETFDPIC_EXEC 0
#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
*
@@ -134,6 +137,15 @@ struct __riscv_m_ext_state {
*/
#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 /* _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_HAVE_PERF_REGS) += perf_regs.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_RISCV_SBI) += sbi.o
ifeq ($(CONFIG_RISCV_SBI), y)
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/dma-mapping.h>
DEFINE_PER_CPU(struct page *, p100_iomb_page);
DEFINE_PER_CPU(void *, p100_iomb_flag0);
DEFINE_PER_CPU(void *, p100_iomb_flag1);
DEFINE_PER_CPU(void *, p100_iomb_flag2);
DEFINE_PER_CPU(void *, p100_iomb_flag3);
DEFINE_PER_CPU(u32, p100_iomb_data);
DEFINE_PER_CPU(struct page *, a210_iomb_page);
DEFINE_PER_CPU(void *, a210_iomb_flag0);
DEFINE_PER_CPU(void *, a210_iomb_flag1);
DEFINE_PER_CPU(void *, a210_iomb_flag2);
DEFINE_PER_CPU(void *, a210_iomb_flag3);
DEFINE_PER_CPU(u32, a210_iomb_data);
inline void p100_iomb(void)
inline void a210_iomb(void)
{
unsigned long flags;
unsigned int cpu;
local_irq_save(flags);
cpu = smp_processor_id();
mb();
*(unsigned int *)per_cpu(p100_iomb_flag0, cpu) = per_cpu(p100_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag1, cpu) = per_cpu(p100_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag2, cpu) = per_cpu(p100_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag3, 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(a210_iomb_flag1, cpu) = per_cpu(a210_iomb_data, cpu);
*(unsigned int *)per_cpu(a210_iomb_flag2, cpu) = per_cpu(a210_iomb_data, cpu);
*(unsigned int *)per_cpu(a210_iomb_flag3, cpu) = per_cpu(a210_iomb_data, cpu);
mb();
while (*(unsigned int *)per_cpu(p100_iomb_flag0, cpu) != per_cpu(p100_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag1, cpu) != per_cpu(p100_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag2, cpu) != per_cpu(p100_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag3, cpu) != per_cpu(p100_iomb_data, 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(a210_iomb_flag1, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(a210_iomb_flag2, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(a210_iomb_flag3, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
per_cpu(a210_iomb_data, cpu)++;
mb();
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 int cpu;
local_irq_save(flags);
cpu = smp_processor_id();
wmb();
*(unsigned int *)per_cpu(p100_iomb_flag0, cpu) = per_cpu(p100_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag1, cpu) = per_cpu(p100_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag2, cpu) = per_cpu(p100_iomb_data, cpu);
*(unsigned int *)per_cpu(p100_iomb_flag3, 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(a210_iomb_flag1, cpu) = per_cpu(a210_iomb_data, cpu);
*(unsigned int *)per_cpu(a210_iomb_flag2, cpu) = per_cpu(a210_iomb_data, cpu);
*(unsigned int *)per_cpu(a210_iomb_flag3, cpu) = per_cpu(a210_iomb_data, cpu);
wmb();
while (*(unsigned int *)per_cpu(p100_iomb_flag0, cpu) != per_cpu(p100_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag1, cpu) != per_cpu(p100_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag2, cpu) != per_cpu(p100_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(p100_iomb_flag3, cpu) != per_cpu(p100_iomb_data, 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(a210_iomb_flag1, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(a210_iomb_flag2, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
while (*(unsigned int *)per_cpu(a210_iomb_flag3, cpu) != per_cpu(a210_iomb_data, cpu)) {;}
per_cpu(a210_iomb_data, cpu)++;
wmb();
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;
for_each_possible_cpu(cpu) {
per_cpu(p100_iomb_page, cpu) = alloc_page(GFP_KERNEL);
if (!per_cpu(p100_iomb_page, cpu))
per_cpu(a210_iomb_page, cpu) = alloc_page(GFP_KERNEL);
if (!per_cpu(a210_iomb_page, cpu))
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));
per_cpu(p100_iomb_flag1, cpu) = per_cpu(p100_iomb_flag0, cpu) + 128;
per_cpu(p100_iomb_flag2, cpu) = per_cpu(p100_iomb_flag1, cpu) + 128;
per_cpu(p100_iomb_flag3, cpu) = per_cpu(p100_iomb_flag2, cpu) + 128;
per_cpu(a210_iomb_flag1, cpu) = per_cpu(a210_iomb_flag0, cpu) + 128;
per_cpu(a210_iomb_flag2, cpu) = per_cpu(a210_iomb_flag1, 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;
}
pure_initcall(p100_iomb_init);
pure_initcall(a210_iomb_init);
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");

View File

@@ -15,6 +15,7 @@
#include <linux/tick.h>
#include <linux/ptrace.h>
#include <linux/uaccess.h>
#include <linux/hw_breakpoint.h>
#include <asm/unistd.h>
#include <asm/processor.h>
@@ -154,6 +155,9 @@ void flush_thread(void)
kfree(current->thread.vstate.datap);
memset(&current->thread.vstate, 0, sizeof(struct __riscv_v_ext_state));
#endif
#ifdef CONFIG_HAVE_HW_BREAKPOINT
flush_ptrace_hw_breakpoint(current);
#endif
}
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;
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));
/* p->thread holds context to be restored by __switch_to() */

View File

@@ -19,6 +19,7 @@
#include <linux/regset.h>
#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include <linux/hw_breakpoint.h>
enum riscv_regset {
REGSET_X,
@@ -28,6 +29,10 @@ enum riscv_regset {
#ifdef CONFIG_RISCV_ISA_V
REGSET_V,
#endif
#ifdef CONFIG_HAVE_HW_BREAKPOINT
REGSET_HW_BREAK,
REGSET_HW_WATCH,
#endif
};
static int riscv_gpr_get(struct task_struct *target,
@@ -159,6 +164,218 @@ static int riscv_vr_set(struct task_struct *target,
}
#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[] = {
[REGSET_X] = {
.core_note_type = NT_PRSTATUS,
@@ -189,6 +406,24 @@ static const struct user_regset riscv_user_regset[] = {
.set = riscv_vr_set,
},
#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 = {

View File

@@ -11,6 +11,7 @@
#include <linux/reboot.h>
#include <asm/sbi.h>
#include <asm/smp.h>
#include <asm/tlbflush.h>
/* default SBI version is 0.1 */
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);
/**
* 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
* 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.
* @start: Start of the virtual address
* @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.
*/
@@ -410,8 +394,12 @@ int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask,
unsigned long size,
unsigned long asid)
{
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
cpu_mask, start, size, asid, 0);
if (asid == FLUSH_TLB_NO_ASID)
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);

View File

@@ -239,6 +239,7 @@ asmlinkage __visible void smp_callin(void)
mmgrab(mm);
current->active_mm = mm;
rcu_cpu_starting(curr_cpuid);
store_cpu_topology(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))
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;
if (user_mode(regs))

View File

@@ -20,7 +20,6 @@
DEFINE_STATIC_KEY_FALSE(use_asid_allocator);
static unsigned long asid_bits;
static unsigned long num_asids;
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
* 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
* 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)
{
#if 0
unsigned long old;
unsigned long asid_bits, old;
/* Figure-out number of ASID bits in HW */
old = csr_read(CSR_SATP);
@@ -283,7 +281,6 @@ static int __init asids_init(void)
} else {
pr_info("ASID allocator disabled (%lu bits)\n", asid_bits);
}
#endif
return 0;
}
early_initcall(asids_init);

View File

@@ -3,34 +3,56 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/sched.h>
#include <linux/hugetlb.h>
#include <asm/sbi.h>
#include <asm/mmu_context.h>
static inline void local_flush_tlb_all_asid(unsigned long asid)
{
__asm__ __volatile__ ("sfence.vma sp, x0\n ld x0, (sp)\n" ::: "memory");
__asm__ __volatile__ ("sfence.vma x0, %0"
:
: "r" (asid)
: "memory");
if (asid != FLUSH_TLB_NO_ASID)
__asm__ __volatile__ ("sfence.vma x0, %0"
:
: "r" (asid)
: "memory");
else
local_flush_tlb_all();
}
static inline void local_flush_tlb_page_asid(unsigned long addr,
unsigned long asid)
{
__asm__ __volatile__ ("sfence.vma %0, %1"
:
: "r" (addr), "r" (asid)
: "memory");
if (asid != FLUSH_TLB_NO_ASID)
__asm__ __volatile__ ("sfence.vma %0, %1"
:
: "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)
local_flush_tlb_page(start);
else
local_flush_tlb_all();
unsigned long nr_ptes_in_range = DIV_ROUND_UP(size, stride);
int i;
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,
@@ -38,8 +60,15 @@ static inline void local_flush_tlb_range_asid(unsigned long start,
{
if (size <= stride)
local_flush_tlb_page_asid(start, asid);
else
else if (size == FLUSH_TLB_MAX_SIZE)
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)
@@ -52,7 +81,7 @@ void flush_tlb_all(void)
if (riscv_use_ipi_for_rfence())
on_each_cpu(__ipi_flush_tlb_all, NULL, 1);
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 {
@@ -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);
}
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,
unsigned long size, unsigned long stride)
{
struct flush_tlb_range_data ftd;
struct cpumask *cmask = mm_cpumask(mm);
unsigned int cpuid;
const struct cpumask *cmask;
unsigned long asid = FLUSH_TLB_NO_ASID;
bool broadcast;
if (cpumask_empty(cmask))
return;
if (mm) {
unsigned int cpuid;
cpuid = get_cpu();
/* check if the tlbflush needs to be sent to other CPUs */
broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids;
if (static_branch_unlikely(&use_asid_allocator)) {
unsigned long asid = atomic_long_read(&mm->context.id) & asid_mask;
cmask = mm_cpumask(mm);
if (cpumask_empty(cmask))
return;
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);
}
cpuid = get_cpu();
/* check if the tlbflush needs to be sent to other CPUs */
broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids;
if (static_branch_unlikely(&use_asid_allocator))
asid = atomic_long_read(&mm->context.id) & asid_mask;
} else {
if (broadcast) {
if (riscv_use_ipi_for_rfence()) {
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);
}
cmask = cpu_online_mask;
broadcast = true;
}
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)
{
__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)
@@ -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,
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
void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)

View File

@@ -90,6 +90,7 @@ extern void copy_from_user_page(struct vm_area_struct *vma,
unsigned long len);
#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_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_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()
/* 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_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)
#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_dup_mm(mm) flush_cache_mm(mm)
#define flush_cache_vmap(start,end) flush_cache_all()
#define flush_cache_vunmap(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()
void flush_dcache_folio(struct folio *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_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 ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0

View File

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

View File

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

View File

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

View File

@@ -12,15 +12,66 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/types.h>
#include <dt-bindings/clock/a210-clock.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_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 top_cpu_ddr1_aclk_parents[] = {"cbus2ddr_aclk1", "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_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),
};
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),
};
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),
};
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),
};
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),
};
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),
};
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),
};
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),
};
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),
};
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(1500000000U, 1500000000U, 2, 125, 0, 1, 1),
PLL_RATE(1698000000U, 1698000000U, 4, 283, 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(1698000000U, 1698000000U, 4, 283, 0, 1, 1),
PLL_RATE(1896000000U, 1896000000U, 1, 79, 0, 1, 1),
PLL_RATE(2298000000U, 2298000000U, 4, 383, 0, 1, 1),
};
static struct p100_clk_info_pll plls_top[] = {
PLL_PARAM(TEE_PLL, P100_PLL_VCO, p100_teepll_tbl, ARRAY_SIZE(p100_teepll_tbl), 0x160, 0x170,
static struct zhihe_clk_info_pll plls_top[] = {
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"),
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"),
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"),
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"),
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"),
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"),
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"),
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"),
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"),
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, ""),
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, ""),
};
static struct p100_clk_reg regs_top[] = {
static struct zhihe_clk_reg regs_top[] = {
REG(PLL_WRAP),
REG(TOP_CRG),
REG(CPU_SS_CLK_SYSREG),
@@ -166,42 +217,43 @@ static struct p100_clk_reg regs_top[] = {
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_TOP_CLK_EN),
};
static struct p100_clk_reg regs_pcie[] = {
static struct zhihe_clk_reg regs_pcie[] = {
REG(PCIE_CLK_EN),
};
static struct p100_clk_reg regs_usb[] = {
static struct zhihe_clk_reg regs_usb[] = {
REG(USB_CLK_EN),
};
static struct p100_clk_reg regs_vi[] = {
static struct zhihe_clk_reg regs_vi[] = {
REG(VI_CLK),
REG(VI_MISC_CTRL),
};
static struct p100_clk_reg regs_vp[] = {
static struct zhihe_clk_reg regs_vp[] = {
REG(VP_CLK),
};
static struct p100_clk_reg regs_vo[] = {
static struct zhihe_clk_reg regs_vo[] = {
REG(VO_CLK),
REG(VO_PATH_CTRL),
};
static struct p100_clk_reg regs_npu[] = {
static struct zhihe_clk_reg regs_npu[] = {
REG(NPU_CLK),
REG(NPU_TOP_CLK),
};
static struct p100_clk_reg regs_d2d[] = {
static struct zhihe_clk_reg regs_d2d[] = {
REG(D2D_CRG_REG),
};
static struct p100_clk_reg regs_peri[] = {
static struct zhihe_clk_reg regs_peri[] = {
REG(PERI0_SYSREG),
REG(PERI1_SYSREG),
REG(PERI2_SYSREG),
@@ -209,7 +261,7 @@ static struct p100_clk_reg regs_peri[] = {
REG(TEE_CRG),
};
static struct p100_clk_info info_top[] = {
static struct zhihe_clk_info info_top[] = {
/* FIXED */
FIXED(AON_OSC_CLK_PHY, "aon_osc_clk_phy", "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),
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),
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),
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),
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),
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),
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),
@@ -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),
};
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_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),
@@ -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),
};
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),
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),
@@ -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),
};
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_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),
@@ -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),
};
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_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,
@@ -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_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_MIPI1CSI1_PCLK_EN, "mipi1_csi1_pclk", "vi_pclk", VI_CLK, 0, 12),
GATE(VI_VIPRE_PCLK_EN, "vipre_pclk", "vi_pclk", VI_CLK, 0, 7),
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, 12),
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_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),
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),
GATE(VI_MIPI1B_CFGCLK_EN, "mipi1_csi1_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_MIPI0B_CFGCLK_EN, "mipi0_csi1_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_MIPI1B_CFGCLK_EN, "mipi1_csi0_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 9),
GATE(VI_MIPI1A_CFGCLK_EN, "mipi1_csi1_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 8),
GATE(VI_MIPI0B_CFGCLK_EN, "mipi0_csi0_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 3),
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_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),
@@ -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_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_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_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),
@@ -611,7 +674,7 @@ static struct p100_clk_info info_vp[] = {
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_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),
@@ -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),
};
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_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),
@@ -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),
};
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_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 */
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),
@@ -828,112 +891,203 @@ static struct p100_clk_info info_peri[] = {
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),
info_top, ARRAY_SIZE(info_top), plls_top, ARRAY_SIZE(plls_top), false);
static struct p100_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);
static struct p100_clk_subsys gpu_clk = CLK_SUBSYS("gpu clk", regs_gpu, ARRAY_SIZE(regs_gpu),
info_gpu, ARRAY_SIZE(info_gpu), NULL, 0, false);
static struct p100_clk_subsys pcie_clk = CLK_SUBSYS("pcie clk", regs_pcie, ARRAY_SIZE(regs_pcie),
info_pcie, ARRAY_SIZE(info_pcie), NULL, 0, false);
static struct p100_clk_subsys usb_clk = CLK_SUBSYS("usb clk", regs_usb, ARRAY_SIZE(regs_usb),
info_usb, ARRAY_SIZE(info_usb), NULL, 0, false);
static struct p100_clk_subsys vi_clk = CLK_SUBSYS("vi clk", regs_vi, ARRAY_SIZE(regs_vi),
info_vi, ARRAY_SIZE(info_vi), NULL, 0, false);
static struct p100_clk_subsys vp_clk = CLK_SUBSYS("vp clk", regs_vp, ARRAY_SIZE(regs_vp),
info_vp, ARRAY_SIZE(info_vp), NULL, 0, false);
static struct p100_clk_subsys vo_clk = CLK_SUBSYS("vo clk", regs_vo, ARRAY_SIZE(regs_vo),
info_vo, ARRAY_SIZE(info_vo), NULL, 0, false);
static struct p100_clk_subsys npu_clk = CLK_SUBSYS("npu clk", regs_npu, ARRAY_SIZE(regs_npu),
info_npu, ARRAY_SIZE(info_npu), NULL, 0, false);
static struct p100_clk_subsys d2d_clk = CLK_SUBSYS("d2d clk", regs_d2d, ARRAY_SIZE(regs_d2d),
info_d2d, ARRAY_SIZE(info_d2d), NULL, 0, false);
static struct p100_clk_subsys peri_clk = CLK_SUBSYS("peri clk", regs_peri, ARRAY_SIZE(regs_peri),
info_peri, ARRAY_SIZE(info_peri), NULL, 0, false);
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, 0);
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, 0);
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, 0);
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, 0);
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, 0);
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, 0);
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, 0);
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, 0);
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, 0);
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, 0);
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, 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 p100_clocks_probe(struct platform_device *pdev)
static int a210_clocks_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct p100_clk_subsys *priv;
struct zhihe_clk_subsys *priv;
int ret;
if (clk_data.clks == NULL) {
clk_data.clks = devm_kcalloc(dev, CLK_END, sizeof(*clk_data.clks),
GFP_KERNEL);
if (!clk_data.clks)
return -ENOMEM;
clk_data.clk_num = CLK_END;
for (int i = 0; i < CLK_END; i++)
clk_data.clks[i] = ERR_PTR(-ENOENT);
struct clk_onecell_data *clk_data = devm_kzalloc(dev, sizeof(*clk_data), GFP_KERNEL);
if (!clk_data) {
ret = -ENOMEM;
goto fail;
}
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) {
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);
ret = p100_parse_regbase(pdev);
ret = zhihe_parse_regbase(pdev);
if (ret) {
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);
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;
}
ret = zhihe_clk_of_bulk_init(dev, priv->clk_data->clks);
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);
dev_info(dev, "succeed to register a210 %s driver on die%d\n", priv->name, priv->die_num);
return 0;
unregister_clks:
zhihe_unregister_clocks(priv->clk_data->clks, CLK_END);
fail:
return ret;
}
static const struct of_device_id p100_clk_of_match[] = {
{ .compatible = "zhihe,p100-clk", .data = (const void *)&top_clk},
{ .compatible = "zhihe,p100-clk-emu", .data = (const void *)&top_clk_fpga},
{ .compatible = "zhihe,p100-clk-haps", .data = (const void *)&top_clk_fpga},
{ .compatible = "zhihe,p100-gpu-clk", .data = (const void *)&gpu_clk},
{ .compatible = "zhihe,p100-pcie-clk", .data = (const void *)&pcie_clk},
{ .compatible = "zhihe,p100-usb-clk", .data = (const void *)&usb_clk},
{ .compatible = "zhihe,p100-vi-clk", .data = (const void *)&vi_clk},
{ .compatible = "zhihe,p100-vp-clk", .data = (const void *)&vp_clk},
{ .compatible = "zhihe,p100-vo-clk", .data = (const void *)&vo_clk},
{ .compatible = "zhihe,p100-npu-clk", .data = (const void *)&npu_clk},
{ .compatible = "zhihe,p100-d2d-clk", .data = (const void *)&d2d_clk},
{ .compatible = "zhihe,p100-peri-clk", .data = (const void *)&peri_clk},
static const struct of_device_id a210_clk_of_match[] = {
{ .compatible = "zhihe,a210-clk", .data = (const void *)&top_clk},
{ .compatible = "zhihe,a210-gpu-clk", .data = (const void *)&gpu_clk},
{ .compatible = "zhihe,a210-pcie-clk", .data = (const void *)&pcie_clk},
{ .compatible = "zhihe,a210-usb-clk", .data = (const void *)&usb_clk},
{ .compatible = "zhihe,a210-vi-clk", .data = (const void *)&vi_clk},
{ .compatible = "zhihe,a210-vp-clk", .data = (const void *)&vp_clk},
{ .compatible = "zhihe,a210-vo-clk", .data = (const void *)&vo_clk},
{ .compatible = "zhihe,a210-npu-clk", .data = (const void *)&npu_clk},
{ .compatible = "zhihe,a210-d2d-clk", .data = (const void *)&d2d_clk},
{ .compatible = "zhihe,a210-peri-clk", .data = (const void *)&peri_clk},
{ .compatible = "zhihe,a210-clk-emu", .data = (const void *)&top_clk_fpga},
{ .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 */ },
};
MODULE_DEVICE_TABLE(of, p100_clk_of_match);
MODULE_DEVICE_TABLE(of, a210_clk_of_match);
static struct platform_driver p100_clk_driver = {
.probe = p100_clocks_probe,
static struct platform_driver a210_clk_driver = {
.probe = a210_clocks_probe,
.driver = {
.name = "p100-clk",
.of_match_table = of_match_ptr(p100_clk_of_match),
.name = "a210-clk",
.of_match_table = of_match_ptr(a210_clk_of_match),
},
};
module_platform_driver(p100_clk_driver);
MODULE_AUTHOR("dong.yan <yand@zhcomputing.com>");
MODULE_DESCRIPTION("Zhihe P100 clock driver");
module_platform_driver(a210_clk_driver);
MODULE_AUTHOR("dong.yan <yand@zhihecomputing.com>");
MODULE_DESCRIPTION("Zhihe A210 clock driver");
MODULE_LICENSE("GPL v2");

View File

@@ -15,32 +15,10 @@
#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_SPINLOCK(zhihe_p100_clk_lock);
#define to_clk_p100pll(_hw) container_of(_hw, struct clk_p100pll, hw)
DEFINE_SPINLOCK(zhihe_clk_lock);
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]);
}
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)
{
unsigned long r;
@@ -358,112 +46,33 @@ int zhihe_clk_set_round_rate(struct device *dev, struct clk *clk, unsigned int f
return ret;
}
void zhihe_p100_clk_fake_pll_fixed_ops(void)
{
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)
static inline struct clk_zhihediv *to_clk_zhihediv(struct clk_hw *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)
{
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)
{
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)
{
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);
unsigned int divider, value;
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);
/* 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;
else
value = divider - 1;
/* handle the div valid range */
if (value > p100_div->max_div)
value = p100_div->max_div;
if (value < p100_div->min_div)
value = p100_div->min_div;
if (value > zhihe_div->max_div)
value = zhihe_div->max_div;
if (value < zhihe_div->min_div)
value = zhihe_div->min_div;
spin_lock_irqsave(div->lock, flags);
val = readl(div->reg);
if (p100_div->sync_en != NO_DIV_EN) {
val &= ~BIT(p100_div->sync_en);
if (zhihe_div->sync_en != NO_DIV_EN) {
val &= ~BIT(zhihe_div->sync_en);
writel(val, div->reg);
udelay(1);
}
@@ -502,9 +111,9 @@ static int clk_p100div_set_rate(struct clk_hw *hw, unsigned long rate,
val |= value << div->shift;
writel(val, div->reg);
if (p100_div->sync_en != NO_DIV_EN) {
if (zhihe_div->sync_en != NO_DIV_EN) {
udelay(1);
val |= BIT(p100_div->sync_en);
val |= BIT(zhihe_div->sync_en);
writel(val, div->reg);
}
@@ -513,168 +122,168 @@ static int clk_p100div_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
static const struct clk_ops clk_p100div_ops = {
.recalc_rate = clk_p100div_recalc_rate,
.round_rate = clk_p100div_round_rate,
.set_rate = clk_p100div_set_rate,
static const struct clk_ops clk_zhihediv_ops = {
.recalc_rate = clk_zhihediv_recalc_rate,
.round_rate = clk_zhihediv_round_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,
u8 sync, enum p100_div_type div_type,
u8 sync, enum zhihe_div_type div_type,
u16 min, u16 max, bool closest)
{
struct clk_p100div *p100_div;
struct clk_zhihediv *zhihe_div;
struct clk_hw *hw;
struct clk_init_data init;
int ret;
p100_div = kzalloc(sizeof(*p100_div), GFP_KERNEL);
if (!p100_div)
zhihe_div = kzalloc(sizeof(*zhihe_div), GFP_KERNEL);
if (!zhihe_div)
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &clk_p100div_ops;
init.ops = &clk_zhihediv_ops;
init.flags = CLK_SET_RATE_PARENT;
init.parent_names = parent ? &parent : NULL;
init.num_parents = parent ? 1 : 0;
p100_div->divider.reg = reg;
p100_div->divider.shift = shift;
p100_div->divider.width = width;
p100_div->divider.lock = &zhihe_p100_clk_lock;
p100_div->divider.hw.init = &init;
p100_div->ops = &clk_divider_ops;
p100_div->sync_en = sync;
p100_div->div_type = div_type;
if (p100_div->div_type == MUX_TYPE_DIV)
p100_div->divider.flags = CLK_DIVIDER_ONE_BASED;
zhihe_div->divider.reg = reg;
zhihe_div->divider.shift = shift;
zhihe_div->divider.width = width;
zhihe_div->divider.lock = &zhihe_clk_lock;
zhihe_div->divider.hw.init = &init;
zhihe_div->ops = &clk_divider_ops;
zhihe_div->sync_en = sync;
zhihe_div->div_type = div_type;
if (zhihe_div->div_type == MUX_TYPE_DIV)
zhihe_div->divider.flags = CLK_DIVIDER_ONE_BASED;
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;
p100_div->max_div = max > ((1 << width) - 1) ?
zhihe_div->max_div = max > ((1 << width) - 1) ?
((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) {
kfree(p100_div);
kfree(zhihe_div);
return ERR_PTR(ret);
}
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,
u8 sync, enum p100_div_type div_type,
u8 sync, enum zhihe_div_type div_type,
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);
}
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,
u8 sync, enum p100_div_type div_type,
u8 sync, enum zhihe_div_type div_type,
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);
}
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);
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 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 (WARN_ON(*p100_gate->share_count == 0))
if (zhihe_gate->share_count) {
if (WARN_ON(*zhihe_gate->share_count == 0))
return;
else if (--(*p100_gate->share_count) > 0) {
else if (--(*zhihe_gate->share_count) > 0) {
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)
return p100_gate->ops->disable(hw);
if (!zhihe_gate->share_count || *zhihe_gate->share_count == 0)
return zhihe_gate->ops->disable(hw);
}
static const struct clk_ops clk_p100gate_share_ops = {
.enable = clk_p100_gate_share_enable,
.disable = clk_p100_gate_share_disable,
.disable_unused = clk_p100_gate_share_disable_unused,
.is_enabled = clk_p100_gate_share_is_enabled,
static const struct clk_ops clk_zhihegate_share_ops = {
.enable = clk_zhihe_gate_share_enable,
.disable = clk_zhihe_gate_share_disable,
.disable_unused = clk_zhihe_gate_share_disable_unused,
.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,
u8 shift, spinlock_t *lock,
unsigned int *share_count)
{
struct clk_p100gate *p100_gate;
struct clk_zhihegate *zhihe_gate;
struct clk_hw *hw;
struct clk_init_data init;
int ret;
p100_gate = kzalloc(sizeof(*p100_gate), GFP_KERNEL);
if (!p100_gate)
zhihe_gate = kzalloc(sizeof(*zhihe_gate), GFP_KERNEL);
if (!zhihe_gate)
return ERR_PTR(-ENOMEM);
p100_gate->gate.reg = reg;
p100_gate->gate.bit_idx = shift;
p100_gate->gate.flags = 0;
p100_gate->gate.lock = lock;
p100_gate->gate.hw.init = &init;
p100_gate->ops = &clk_gate_ops;
p100_gate->share_count = share_count;
zhihe_gate->gate.reg = reg;
zhihe_gate->gate.bit_idx = shift;
zhihe_gate->gate.flags = 0;
zhihe_gate->gate.lock = lock;
zhihe_gate->gate.hw.init = &init;
zhihe_gate->ops = &clk_gate_ops;
zhihe_gate->share_count = share_count;
init.name = name;
init.ops = &clk_p100gate_share_ops;
init.ops = &clk_zhihegate_share_ops;
init.flags = flags;
init.parent_names = parent ? &parent : NULL;
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) {
kfree(p100_gate);
kfree(zhihe_gate);
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)
{
int i;
for (i = 0; i < CLK_END; i++) {
if (clks[i] == ERR_PTR(-ENOENT))
continue;
@@ -748,10 +356,10 @@ int zhihe_clk_of_bulk_init(struct device *dev, struct clk **clks)
return 0;
}
int p100_parse_regbase(struct platform_device *pdev)
int zhihe_parse_regbase(struct platform_device *pdev)
{
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;
for (int i = 0; i < priv->num_regs; i++) {
@@ -765,12 +373,51 @@ int p100_parse_regbase(struct platform_device *pdev)
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 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;
unsigned int freq;
char *name, *parent;
int ret;
/* 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++) {
enum p100_clk_types type = priv->info[i].type;
char *name = priv->info[i].name;
char *parent = priv->info[i].parent;
enum zhihe_clk_types type = priv->info[i].type;
if (priv->die_num != 0) {
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;
void __iomem *base = priv->regs[priv->info[i].reg].base +
priv->info[i].shift;
@@ -794,35 +446,36 @@ void p100_register_clock(struct platform_device *pdev)
switch (type) {
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;
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);
break;
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;
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.min, priv->info[i].divider.max);
break;
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.min, priv->info[i].divider.max);
break;
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;
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);
break;
case CLK_TYPE_MUX:
priv->clk_data->clks[id] = zhihe_p100_clk_mux_flags(name, base, bit_idx, width,
priv->info[i].mux.parents, priv->info[i].mux.num_parents,
const char * const *parents = zhihe_add_mux_suffix(pdev, i);
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);
break;
default:

View File

@@ -11,45 +11,9 @@
#include <linux/platform_device.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
/* 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 ZHIHE_CLK_NAME_SIZE 40
#define PLL_RATE(_vco, _rate, _r, _b, _f, _p, _k) \
{ \
@@ -144,7 +108,7 @@ extern spinlock_t zhihe_p100_clk_lock;
.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), \
.regs = (_regs), \
.num_regs = (_num_reg), \
@@ -153,38 +117,24 @@ extern spinlock_t zhihe_p100_clk_lock;
.plls = (_pll), \
.num_plls = (_num_pll), \
.is_fpga = (_is_fpga), \
.die_num = (_die_num), \
}
enum p100_pll_outtype {
P100_PLL_VCO,
P100_PLL_DIV,
enum zhihe_pll_outtype {
ZHIHE_PLL_VCO,
ZHIHE_PLL_DIV,
};
enum p100_div_type {
enum zhihe_div_type {
MUX_TYPE_DIV,
MUX_TYPE_CDE,
};
enum p100_div_sync_type {
enum zhihe_div_sync_type {
NO_DIV_EN = 255,
};
enum p100_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,
};
enum p100_clk_types {
enum zhihe_clk_types {
CLK_TYPE_FIXED,
CLK_TYPE_PLL,
CLK_TYPE_FIXED_FACTOR,
@@ -195,36 +145,37 @@ enum p100_clk_types {
CLK_TYPE_MUX,
};
enum p100_pll_mode {
enum zhihe_pll_mode {
PLL_MODE_FRAC,
PLL_MODE_INT,
};
struct p100_clk_reg {
struct zhihe_clk_reg {
void __iomem *base;
char name[P100_CLK_NAME_SIZE];
char name[ZHIHE_CLK_NAME_SIZE];
};
/* clk summary info at subsys level */
struct p100_clk_subsys {
char name[P100_CLK_NAME_SIZE];
struct p100_clk_reg *regs;
struct zhihe_clk_subsys {
char name[ZHIHE_CLK_NAME_SIZE];
struct zhihe_clk_reg *regs;
u32 num_regs;
struct p100_clk_info *info;
struct zhihe_clk_info *info;
u32 num_info;
struct p100_clk_info_pll *plls;
struct zhihe_clk_info_pll *plls;
u32 num_plls;
bool is_fpga;
struct clk_onecell_data *clk_data;
char die_num;
};
struct clk_p100pll {
struct clk_zhihepll {
struct clk_hw hw;
void __iomem *base;
enum p100_pll_clktype clk_type;
enum p100_pll_outtype out_type;
enum p100_pll_mode pll_mode;
const struct p100_pll_rate_table *rate_table;
unsigned int clk_type;
enum zhihe_pll_outtype out_type;
enum zhihe_pll_mode pll_mode;
const struct zhihe_pll_rate_table *rate_table;
int rate_count;
u32 cfg0_reg_off;
@@ -234,22 +185,22 @@ struct clk_p100pll {
int pll_bypass_bit;
};
struct clk_p100div {
struct clk_zhihediv {
struct clk_divider divider;
enum p100_div_type div_type;
enum zhihe_div_type div_type;
u16 min_div;
u16 max_div;
u8 sync_en;
const struct clk_ops *ops;
};
struct clk_p100gate {
struct clk_zhihegate {
struct clk_gate gate;
unsigned int *share_count;
const struct clk_ops *ops;
};
struct p100_pll_rate_table {
struct zhihe_pll_rate_table {
unsigned long vco_rate;
unsigned long rate;
unsigned int refdiv;
@@ -261,132 +212,133 @@ struct p100_pll_rate_table {
/* detailed clk info for each clk */
struct p100_clk_info_pll {
enum p100_pll_outtype out_type;
enum p100_pll_clktype clk_type;
struct p100_pll_rate_table *rate_table;
struct zhihe_clk_info_pll {
enum zhihe_pll_outtype out_type;
unsigned int clk_type;
struct zhihe_pll_rate_table *rate_table;
int rate_count;
int flags;
char name[P100_CLK_NAME_SIZE];
char name[ZHIHE_CLK_NAME_SIZE];
u32 cfg0_reg_off;
u32 pll_sts_off;
int pll_lock_bit;
int pll_rst_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;
};
struct p100_clk_info_fixed_factor {
struct zhihe_clk_info_fixed_factor {
unsigned int mult;
unsigned int div;
};
struct p100_clk_info_divider {
struct zhihe_clk_info_divider {
u8 sync;
enum p100_div_type div_type;
enum zhihe_div_type div_type;
u16 min;
u16 max;
};
struct p100_clk_info_gate_shared {
struct zhihe_clk_info_gate_shared {
unsigned int *share_count;
};
struct p100_clk_info_mux {
struct zhihe_clk_info_mux {
const char * const *parents;
int num_parents;
unsigned long flags;
};
struct p100_clk_info {
enum p100_clk_types type;
struct zhihe_clk_info {
enum zhihe_clk_types type;
u32 id;
char name[P100_CLK_NAME_SIZE];
char parent[P100_CLK_NAME_SIZE];
char name[ZHIHE_CLK_NAME_SIZE];
char parent[ZHIHE_CLK_NAME_SIZE];
u8 reg;
u32 shift;
u8 width;
u8 bit_idx;
union {
struct p100_clk_info_fixed fixed;
struct p100_clk_info_fixed_factor fixed_factor;
struct p100_clk_info_pll *pll;
struct p100_clk_info_divider divider;
struct p100_clk_info_gate_shared gate_shared;
struct p100_clk_info_mux mux;
struct zhihe_clk_info_fixed fixed;
struct zhihe_clk_info_fixed_factor fixed_factor;
struct zhihe_clk_info_pll *pll;
struct zhihe_clk_info_divider divider;
struct zhihe_clk_info_gate_shared gate_shared;
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)
{
return clk_register_fixed_factor(NULL, name, parent,
return clk_register_fixed_factor(dev, name, parent,
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,
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)
{
return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
shift, 0, &zhihe_p100_clk_lock);
return clk_register_gate(dev, name, parent, CLK_SET_RATE_PARENT, reg,
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,
u8 shift, spinlock_t *lock,
unsigned int *share_count);
struct clk *zhihe_clk_p100_divider(const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width,
u8 sync, enum p100_div_type div_type,
u16 min, u16 max);
struct clk *zhihe_clk_divider(struct device *dev, const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width,
u8 sync, enum zhihe_div_type div_type,
u16 min, u16 max);
/**
* By default, the clk framework calculates frequency by rounding downwards.
* This function is to achieve closest frequency.
*/
struct clk *zhihe_clk_p100_divider_closest(const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width,
u8 sync, enum p100_div_type div_type,
u16 min, u16 max);
struct clk *zhihe_clk_divider_closest(struct device *dev, const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width,
u8 sync, enum zhihe_div_type div_type,
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,
unsigned int *share_count)
{
return zhihe_clk_p100_register_gate_shared(name, parent, CLK_SET_RATE_PARENT, reg,
shift, &zhihe_p100_clk_lock, share_count);
return zhihe_clk_register_gate_shared(dev, name, parent, CLK_SET_RATE_PARENT, reg,
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,
const char * const *parents, int num_parents,
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,
&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_of_bulk_init(struct device *dev, struct clk **clks);
int p100_parse_regbase(struct platform_device *pdev);
void p100_register_clock(struct platform_device *pdev);
int add_die_suffix(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

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
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
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_US3_CPUFREQ) += sparc-us3-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
* @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.
*
* Return:
@@ -1728,7 +1728,7 @@ static const struct of_device_id dw_dma_of_id_table[] = {
.compatible = "xuantie,th1520-axi-dma",
.data = (void *)(AXI_DMA_FLAG_USE_CFG2),
}, {
.compatible = "zhihe,p100-axi-dma",
.compatible = "zhihe,a210-axi-dma",
.data = (void *)(AXI_DMA_FLAG_USE_CFG2),
},
{}

View File

@@ -210,7 +210,7 @@ out:
}
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 device_node *node;

View File

@@ -17,6 +17,14 @@
#include <linux/platform_device.h>
#include <linux/proc_fs.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_V2 0x1
@@ -211,7 +219,7 @@ out:
}
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 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;
}
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)
{
struct device *dev = &pdev->dev;
@@ -246,6 +326,17 @@ static int zhihe_aon_probe(struct platform_device *pdev)
struct device_node *np;
char dir_name[32] = { 0x0 };
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);
if (!aon_ipc)
return -ENOMEM;
@@ -323,7 +414,7 @@ static int __maybe_unused zhihe_aon_resume_noirq(struct device *dev)
aon_chan = &zhihe_aon_ipc_handle->chans;
complete(&aon_chan->tx_done);
#endif
#endif
return 0;
}
@@ -344,4 +435,3 @@ MODULE_AUTHOR("hongkun.xu <xuhongkun@zhcomputing.com>");
MODULE_AUTHOR("xionglue.huang <huangxionglue@zhcomputing.com>");
MODULE_DESCRIPTION("ZHIHE firmware protocol driver");
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 dwapb_gpio *gpio = to_dwapb_gpio(gc);
irq_hw_number_t hwirq = irqd_to_hwirq(d);
unsigned long flags;
u32 val;
raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
val = dwapb_read(gpio, GPIO_INTEN);
val |= BIT(irqd_to_hwirq(d));
val = dwapb_read(gpio, GPIO_INTEN) | BIT(hwirq);
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);
}
@@ -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 dwapb_gpio *gpio = to_dwapb_gpio(gc);
irq_hw_number_t hwirq = irqd_to_hwirq(d);
unsigned long flags;
u32 val;
raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
val = dwapb_read(gpio, GPIO_INTEN);
val &= ~BIT(irqd_to_hwirq(d));
val = dwapb_read(gpio, GPIO_INTMASK) | BIT(hwirq);
dwapb_write(gpio, GPIO_INTMASK, val);
val = dwapb_read(gpio, GPIO_INTEN) & ~BIT(hwirq);
dwapb_write(gpio, GPIO_INTEN, val);
raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
}

View File

@@ -389,6 +389,8 @@ source "drivers/gpu/drm/sprd/Kconfig"
source "drivers/gpu/drm/verisilicon/Kconfig"
source "drivers/gpu/drm/img-rogue/Kconfig"
config DRM_HYPERV
tristate "DRM Support for Hyper-V synthetic video device"
depends on DRM && PCI && MMU && HYPERV

View File

@@ -184,6 +184,7 @@ obj-y += hisilicon/
obj-y += mxsfb/
obj-y += tiny/
obj-$(CONFIG_DRM_PL111) += pl111/
obj-$(CONFIG_DRM_POWERVR_ROGUE) += img-rogue/
obj-$(CONFIG_DRM_TVE200) += tve200/
obj-$(CONFIG_DRM_XEN) += xen/
obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/

View File

@@ -22,6 +22,14 @@
#include <linux/pm_runtime.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 <uapi/linux/media-bus-format.h>
@@ -41,6 +49,10 @@
#include "dw-hdmi-cec.h"
#include "dw-hdmi.h"
#ifdef CONFIG_ZHIHE_AUXDISP
#define AUXDISP_DT_COMPATIBLE "zhihe,auxdisp"
#endif
#define DDC_CI_ADDR 0x37
#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_UYYVYY8_0_5X24:
color_format = 0x09;
#ifdef CONFIG_ZHIHE_AUXDISP
/* auxdisp 输出的NV12 AVI值为28 */
color_format = 0x1c;
#endif
break;
case MEDIA_BUS_FMT_YUV10_1X30:
case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
@@ -1115,7 +1131,7 @@ static int is_color_space_interpolation(struct dw_hdmi *hdmi)
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) ||
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,
const struct drm_connector *connector,
struct drm_connector *connector,
const struct drm_display_mode *mode)
{
int ret;
@@ -2697,6 +2713,162 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
/* -----------------------------------------------------------------------------
* 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 :
@@ -2742,6 +2914,11 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
if (!output_fmts)
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 (list_is_singular(&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)
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) {
/* If MEDIA_BUS_FMT_FIXED is tested, return default bus format */
case MEDIA_BUS_FMT_FIXED:

View File

@@ -0,0 +1,24 @@
config DRM_POWERVR_ROGUE
tristate "PowerVR Rogue"
depends on HAS_IOMEM
depends on DRM
select DRM_KMS_HELPER
select PM_DEVFREQ
select DEVFREQ_GOV_SIMPLE_ONDEMAND
select PM_OPP
select DEVFREQ_THERMAL
select SYNC_FILE
help
Driver for PowerVR Rogue graphics hardware.
Say Y here if your SoC contains a PowerVR Rogue GPU. For more
information, see <http://www.imgtec.com/powervr/>.
config DRM_POWERVR_ROGUE_DEBUG
bool "Enable PowerVR Rogue debug features"
depends on DRM_POWERVR_ROGUE
default n
help
Add additional debug features to the PowerVR Rogue driver.
To build a matching userspace, enable the following build options:
BUILD=debug SUPPORT_PAGE_FAULT_DEBUG=1 PVRSRV_ENABLE_GPU_MEMORY_INFO=1

View File

@@ -0,0 +1,14 @@
img_basedir := $(srctree)/$(src)
include $(img_basedir)/config_kernel.mk
obj-$(CONFIG_DRM_POWERVR_ROGUE) += pvrsrvkm.o
ccflags-y += \
-include config_kernel.h \
-I$(img_basedir)/include/drm \
-I$(img_basedir) \
-I$(img_basedir)/include \
-I$(img_basedir)/km \
-D__linux__
include $(img_basedir)/pvrsrvkm.mk

View File

@@ -0,0 +1,377 @@
/*************************************************************************/ /*!
@File
@Title Host memory management implementation for Linux
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ /**************************************************************************/
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/string.h>
#include "img_defs.h"
#include "allocmem.h"
#include "pvr_debug.h"
#include "process_stats.h"
#include "osfunc.h"
/*
* When memory statistics are disabled, memory records are used instead.
* In order for these to work, the PID of the process that requested the
* allocation needs to be stored at the end of the kmalloc'd memory, making
* sure 4 extra bytes are allocated to fit the PID.
*
* There is no need for this extra allocation when memory statistics are
* enabled, since all allocations are tracked in DebugFS mem_area files.
*/
#if defined(PVRSRV_ENABLE_PROCESS_STATS) && !defined(PVRSRV_ENABLE_MEMORY_STATS)
/* kmalloc guarantees a minimal alignment which is ARCH_KMALLOC_MINALIGN. This
* alignment is architecture specific and can be quite big, e.g. on Aarch64
* it can be 64 bytes. This is too much for keeping a single PID field and could
* lead to a lot of wasted memory. This is a reason why we're defaulting to 8
* bytes alignment which should be enough for any architecture.
*/
#define ALLOCMEM_PID_SIZE_PADDING PVR_ALIGN(sizeof(IMG_UINT32), 8)
#else
#define ALLOCMEM_PID_SIZE_PADDING 0UL
#endif
/* How many times kmalloc can fail before the allocation threshold is reduced */
static const IMG_UINT32 g_ui32kmallocFailLimit = 10;
/* How many kmalloc failures happened since the last allocation threshold change */
static IMG_UINT32 g_ui32kmallocFailCount = 0;
/* Current kmalloc threshold value in bytes */
static IMG_UINT32 g_ui32kmallocThreshold = PVR_LINUX_KMALLOC_ALLOCATION_THRESHOLD;
/* Spinlock used so that the global variables above may not be modified by more than 1 thread at a time */
static DEFINE_SPINLOCK(kmalloc_lock);
static inline void OSTryDecreaseKmallocThreshold(void)
{
unsigned long flags;
spin_lock_irqsave(&kmalloc_lock, flags);
g_ui32kmallocFailCount++;
if (g_ui32kmallocFailCount >= g_ui32kmallocFailLimit)
{
g_ui32kmallocFailCount = 0;
if (g_ui32kmallocThreshold > PAGE_SIZE)
{
g_ui32kmallocThreshold >>= 1;
printk(KERN_INFO "Threshold is now set to %d\n", g_ui32kmallocThreshold);
}
}
spin_unlock_irqrestore(&kmalloc_lock, flags);
}
static inline void OSResetKmallocFailCount(void)
{
unsigned long flags;
spin_lock_irqsave(&kmalloc_lock, flags);
g_ui32kmallocFailCount = 0;
spin_unlock_irqrestore(&kmalloc_lock, flags);
}
static inline void _pvr_vfree(const void* pvAddr)
{
#if defined(DEBUG)
/* Size harder to come by for vmalloc and since vmalloc allocates
* a whole number of pages, poison the minimum size known to have
* been allocated.
*/
OSCachedMemSet((void*)pvAddr, PVRSRV_POISON_ON_ALLOC_VALUE,
PAGE_SIZE);
#endif
vfree(pvAddr);
}
static inline void _pvr_kfree(const void* pvAddr)
{
#if defined(DEBUG)
/* Poison whole memory block */
OSCachedMemSet((void*)pvAddr, PVRSRV_POISON_ON_ALLOC_VALUE,
ksize(pvAddr));
#endif
kfree(pvAddr);
}
static inline void *_pvr_alloc_stats_add(void *pvAddr, IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS)
{
#if !defined(PVRSRV_ENABLE_PROCESS_STATS)
PVR_UNREFERENCED_PARAMETER(pvAddr);
#else
if (!is_vmalloc_addr(pvAddr))
{
#if defined(PVRSRV_ENABLE_MEMORY_STATS)
IMG_CPU_PHYADDR sCpuPAddr;
sCpuPAddr.uiAddr = 0;
PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_KMALLOC,
pvAddr,
sCpuPAddr,
ksize(pvAddr),
OSGetCurrentClientProcessIDKM()
DEBUG_MEMSTATS_ARGS);
#else
/* because clang has some features that allow detection out-of-bounds
* access we need to put the metadata in the beginning of the allocation */
*(IMG_UINT32 *) pvAddr = OSGetCurrentClientProcessIDKM();
PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_KMALLOC, ksize(pvAddr),
*(IMG_UINT32 *) pvAddr);
/* because metadata is kept in the beginning of the allocation we need
* to return address offset by the ALLOCMEM_PID_SIZE_PADDING */
pvAddr = (IMG_UINT8 *) pvAddr + ALLOCMEM_PID_SIZE_PADDING;
#endif /* defined(PVRSRV_ENABLE_MEMORY_STATS) */
}
else
{
#if defined(PVRSRV_ENABLE_MEMORY_STATS)
IMG_CPU_PHYADDR sCpuPAddr;
sCpuPAddr.uiAddr = 0;
PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_VMALLOC,
pvAddr,
sCpuPAddr,
PVR_ALIGN(ui32Size, PAGE_SIZE),
OSGetCurrentClientProcessIDKM()
DEBUG_MEMSTATS_ARGS);
#else
PVRSRVStatsIncrMemAllocStatAndTrack(PVRSRV_MEM_ALLOC_TYPE_VMALLOC,
PVR_ALIGN(ui32Size, PAGE_SIZE),
(IMG_UINT64)(uintptr_t) pvAddr,
OSGetCurrentClientProcessIDKM());
#endif /* defined(PVRSRV_ENABLE_MEMORY_STATS) */
}
#endif /* !defined(PVRSRV_ENABLE_PROCESS_STATS) */
return pvAddr;
}
static inline void *_pvr_alloc_stats_remove(void *pvAddr)
{
#if !defined(PVRSRV_ENABLE_PROCESS_STATS)
PVR_UNREFERENCED_PARAMETER(pvAddr);
#else
if (!is_vmalloc_addr(pvAddr))
{
#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
/* because metadata is kept in the beginning of the allocation we need
* shift address offset by the ALLOCMEM_PID_SIZE_PADDING to the original
* value */
pvAddr = (IMG_UINT8 *) pvAddr - ALLOCMEM_PID_SIZE_PADDING;
/* first 4 bytes of the allocation are the process' PID */
PVRSRVStatsDecrMemKAllocStat(ksize(pvAddr), *(IMG_UINT32 *) pvAddr);
#else
PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_KMALLOC,
(IMG_UINT64)(uintptr_t) pvAddr,
OSGetCurrentClientProcessIDKM());
#endif
}
else
{
#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
PVRSRVStatsDecrMemAllocStatAndUntrack(PVRSRV_MEM_ALLOC_TYPE_VMALLOC,
(IMG_UINT64)(uintptr_t) pvAddr);
#else
PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_VMALLOC,
(IMG_UINT64)(uintptr_t) pvAddr,
OSGetCurrentClientProcessIDKM());
#endif
}
#endif /* !defined(PVRSRV_ENABLE_PROCESS_STATS) */
return pvAddr;
}
void *(OSAllocMem)(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS)
{
void *pvRet = NULL;
if ((ui32Size + ALLOCMEM_PID_SIZE_PADDING) <= g_ui32kmallocThreshold)
{
pvRet = kmalloc(ui32Size + ALLOCMEM_PID_SIZE_PADDING, GFP_KERNEL);
if (pvRet == NULL)
{
OSTryDecreaseKmallocThreshold();
}
else
{
OSResetKmallocFailCount();
}
}
if (pvRet == NULL)
{
pvRet = vmalloc(ui32Size);
}
if (pvRet != NULL)
{
pvRet = _pvr_alloc_stats_add(pvRet, ui32Size DEBUG_MEMSTATS_ARGS);
}
return pvRet;
}
void *(OSAllocZMem)(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS)
{
void *pvRet = NULL;
if ((ui32Size + ALLOCMEM_PID_SIZE_PADDING) <= g_ui32kmallocThreshold)
{
pvRet = kzalloc(ui32Size + ALLOCMEM_PID_SIZE_PADDING, GFP_KERNEL);
if (pvRet == NULL)
{
OSTryDecreaseKmallocThreshold();
}
else
{
OSResetKmallocFailCount();
}
}
if (pvRet == NULL)
{
pvRet = vzalloc(ui32Size);
}
if (pvRet != NULL)
{
pvRet = _pvr_alloc_stats_add(pvRet, ui32Size DEBUG_MEMSTATS_ARGS);
}
return pvRet;
}
/*
* The parentheses around OSFreeMem prevent the macro in allocmem.h from
* applying, as it would break the function's definition.
*/
void (OSFreeMem)(void *pvMem)
{
if (pvMem != NULL)
{
pvMem = _pvr_alloc_stats_remove(pvMem);
if (!is_vmalloc_addr(pvMem))
{
_pvr_kfree(pvMem);
}
else
{
_pvr_vfree(pvMem);
}
}
}
void *OSAllocMemNoStats(IMG_UINT32 ui32Size)
{
void *pvRet = NULL;
if (ui32Size <= g_ui32kmallocThreshold)
{
pvRet = kmalloc(ui32Size, GFP_KERNEL);
if (pvRet == NULL)
{
OSTryDecreaseKmallocThreshold();
}
else
{
OSResetKmallocFailCount();
}
}
if (pvRet == NULL)
{
pvRet = vmalloc(ui32Size);
}
return pvRet;
}
void *OSAllocZMemNoStats(IMG_UINT32 ui32Size)
{
void *pvRet = NULL;
if (ui32Size <= g_ui32kmallocThreshold)
{
pvRet = kzalloc(ui32Size, GFP_KERNEL);
if (pvRet == NULL)
{
OSTryDecreaseKmallocThreshold();
}
else
{
OSResetKmallocFailCount();
}
}
if (pvRet == NULL)
{
pvRet = vzalloc(ui32Size);
}
return pvRet;
}
/*
* The parentheses around OSFreeMemNoStats prevent the macro in allocmem.h from
* applying, as it would break the function's definition.
*/
void (OSFreeMemNoStats)(void *pvMem)
{
if (pvMem != NULL)
{
if (!is_vmalloc_addr(pvMem))
{
_pvr_kfree(pvMem);
}
else
{
_pvr_vfree(pvMem);
}
}
}

View File

@@ -0,0 +1,224 @@
/*************************************************************************/ /*!
@File allocmem.h
@Title memory allocation header
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@Description Memory-Allocation API definitions
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ /**************************************************************************/
#ifndef ALLOCMEM_H
#define ALLOCMEM_H
#include "img_types.h"
#include "pvr_debug.h"
#if defined(__cplusplus)
extern "C" {
#endif
/*
* PVRSRV_ENABLE_PROCESS_STATS enables process statistics regarding events,
* resources and memory across all processes
* PVRSRV_ENABLE_MEMORY_STATS enables recording of Linux kernel memory
* allocations, provided that PVRSRV_ENABLE_PROCESS_STATS is enabled
* - Output can be found in:
* /(sys/kernel/debug|proc)/pvr/proc_stats/[live|retired]_pids_stats/mem_area
* PVRSRV_DEBUG_LINUX_MEMORY_STATS provides more details about memory
* statistics in conjunction with PVRSRV_ENABLE_MEMORY_STATS
* PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON is defined to encompass both memory
* allocation statistics functionalities described above in a single macro
*/
#if defined(PVRSRV_ENABLE_PROCESS_STATS) && defined(PVRSRV_ENABLE_MEMORY_STATS) && defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS) && defined(DEBUG)
#define PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON
#endif
/*
* When using detailed memory allocation statistics, the line number and
* file name where the allocation happened are also provided.
* When this feature is not used, these parameters are not needed.
*/
#if defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON)
#define DEBUG_MEMSTATS_PARAMS ,void *pvAllocFromFile, IMG_UINT32 ui32AllocFromLine
#define DEBUG_MEMSTATS_ARGS ,pvAllocFromFile, ui32AllocFromLine
#define DEBUG_MEMSTATS_UNREF (void)pvAllocFromFile; (void)ui32AllocFromLine;
#define DEBUG_MEMSTATS_VALUES ,__FILE__, __LINE__
#else
#define DEBUG_MEMSTATS_PARAMS /*!<
* Used for PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON
* build option. */
#define DEBUG_MEMSTATS_ARGS /*!<
* Used for PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON
* build option. */
#define DEBUG_MEMSTATS_UNREF /*!<
* Used for PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON
* build option. */
#define DEBUG_MEMSTATS_VALUES /*!<
* Used for PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON
* build option. */
#endif
/**************************************************************************/ /*!
@Function OSAllocMem
@Description Allocates CPU memory. Contents are uninitialized.
If passed a size of zero, function should not assert,
but just return a NULL pointer.
@Input ui32Size Size of required allocation (in bytes)
@Return Pointer to allocated memory on success.
Otherwise NULL.
*/ /**************************************************************************/
#if defined(DOXYGEN)
void *OSAllocMem(IMG_UINT32 ui32Size);
#else
void *OSAllocMem(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS);
#define OSAllocMem(_size) (OSAllocMem)((_size) DEBUG_MEMSTATS_VALUES)
#endif
/**************************************************************************/ /*!
@Function OSAllocZMem
@Description Allocates CPU memory and initializes the contents to zero.
If passed a size of zero, function should not assert,
but just return a NULL pointer.
@Input ui32Size Size of required allocation (in bytes)
@Return Pointer to allocated memory on success.
Otherwise NULL.
*/ /**************************************************************************/
#if defined(DOXYGEN)
void *OSAllocZMem(IMG_UINT32 ui32Size);
#else
void *OSAllocZMem(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS);
#define OSAllocZMem(_size) (OSAllocZMem)((_size) DEBUG_MEMSTATS_VALUES)
#endif
/**************************************************************************/ /*!
@Function OSAllocMemNoStats
@Description Allocates CPU memory. Contents are uninitialized.
If passed a size of zero, function should not assert,
but just return a NULL pointer.
The allocated memory is not accounted for by process stats.
Process stats are an optional feature (enabled only when
PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
of memory allocated to help in debugging. Where this is not
required, OSAllocMem() and OSAllocMemNoStats() equate to
the same operation.
@Input ui32Size Size of required allocation (in bytes)
@Return Pointer to allocated memory on success.
Otherwise NULL.
*/ /**************************************************************************/
void *OSAllocMemNoStats(IMG_UINT32 ui32Size);
/**************************************************************************/ /*!
@Function OSAllocZMemNoStats
@Description Allocates CPU memory and initializes the contents to zero.
If passed a size of zero, function should not assert,
but just return a NULL pointer.
The allocated memory is not accounted for by process stats.
Process stats are an optional feature (enabled only when
PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
of memory allocated to help in debugging. Where this is not
required, OSAllocZMem() and OSAllocZMemNoStats() equate to
the same operation.
@Input ui32Size Size of required allocation (in bytes)
@Return Pointer to allocated memory on success.
Otherwise NULL.
*/ /**************************************************************************/
void *OSAllocZMemNoStats(IMG_UINT32 ui32Size);
/**************************************************************************/ /*!
@Function OSFreeMem
@Description Frees previously allocated CPU memory.
@Input pvCpuVAddr Pointer to the memory to be freed.
@Return None.
*/ /**************************************************************************/
void OSFreeMem(void *pvCpuVAddr);
/**************************************************************************/ /*!
@Function OSFreeMemNoStats
@Description Frees previously allocated CPU memory.
The freed memory does not update the figures in process stats.
Process stats are an optional feature (enabled only when
PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
of memory allocated to help in debugging. Where this is not
required, OSFreeMem() and OSFreeMemNoStats() equate to the
same operation.
@Input pvCpuVAddr Pointer to the memory to be freed.
@Return None.
*/ /**************************************************************************/
void OSFreeMemNoStats(void *pvCpuVAddr);
/*
* These macros allow us to catch double-free bugs on DEBUG builds and
* prevent crashes on RELEASE builds.
*/
/*! @cond Doxygen_Suppress */
#if defined(DEBUG)
#define double_free_sentinel ((void *)&OSFreeMem)
#define ALLOCMEM_ASSERT(exp) PVR_ASSERT(exp)
#else
#define double_free_sentinel NULL
#define ALLOCMEM_ASSERT(exp) do {} while (0)
#endif
/*! @endcond */
/*! Frees memory allocated by OSAllocMem(). */
#define OSFreeMem(_ptr) do { \
ALLOCMEM_ASSERT((_ptr) != double_free_sentinel); \
(OSFreeMem)(_ptr); \
(_ptr) = double_free_sentinel; \
MSC_SUPPRESS_4127 \
} while (0)
/*! Frees memory allocated by OSAllocMemNoStats(). */
#define OSFreeMemNoStats(_ptr) do { \
ALLOCMEM_ASSERT((_ptr) != double_free_sentinel); \
(OSFreeMemNoStats)(_ptr); \
(_ptr) = double_free_sentinel; \
MSC_SUPPRESS_4127 \
} while (0)
#if defined(__cplusplus)
}
#endif
#endif /* ALLOCMEM_H */
/******************************************************************************
End of file (allocmem.h)
******************************************************************************/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,151 @@
/*************************************************************************/ /*!
@File cache_km.h
@Title CPU cache management header
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ /**************************************************************************/
#ifndef CACHE_KM_H
#define CACHE_KM_H
#if defined(__linux__)
#include <linux/version.h>
#else
#define KERNEL_VERSION
#endif
#include "pvrsrv_error.h"
#include "os_cpu_cache.h"
#include "img_types.h"
#include "cache_ops.h"
#include "device.h"
#include "pmr.h"
typedef IMG_UINT32 PVRSRV_CACHE_OP_ADDR_TYPE; /*!< Represents CPU address type required for CPU d-cache maintenance */
#define PVRSRV_CACHE_OP_ADDR_TYPE_VIRTUAL 0x1 /*!< Operation requires CPU virtual address only */
#define PVRSRV_CACHE_OP_ADDR_TYPE_PHYSICAL 0x2 /*!< Operation requires CPU physical address only */
#define PVRSRV_CACHE_OP_ADDR_TYPE_BOTH 0x3 /*!< Operation requires both CPU virtual & physical addresses */
#include "connection_server.h"
/*
* CacheOpInit() & CacheOpDeInit()
*
* This must be called to initialise the KM cache maintenance framework.
* This is called early during the driver/module (un)loading phase.
*/
PVRSRV_ERROR CacheOpInit(void);
void CacheOpDeInit(void);
/*
* CacheOpInit2() & CacheOpDeInit2()
*
* This must be called to initialise the UM cache maintenance framework.
* This is called when the driver is loaded/unloaded from the kernel.
*/
PVRSRV_ERROR CacheOpInit2(void);
void CacheOpDeInit2(void);
/*
* CacheOpExec()
*
* This is the primary CPU data-cache maintenance interface and it is
* always guaranteed to be synchronous; the arguments supplied must be
* pre-validated for performance reasons else the d-cache maintenance
* operation might cause the underlying OS kernel to fault.
*/
PVRSRV_ERROR CacheOpExec(PPVRSRV_DEVICE_NODE psDevNode,
void *pvVirtStart,
void *pvVirtEnd,
IMG_CPU_PHYADDR sCPUPhysStart,
IMG_CPU_PHYADDR sCPUPhysEnd,
PVRSRV_CACHE_OP uiCacheOp);
/*
* CacheOpValExec()
*
* Same as CacheOpExec(), except arguments are _Validated_ before being
* presented to the underlying OS kernel for CPU data-cache maintenance.
* The uiAddress is the start CPU virtual address for the to-be d-cache
* maintained PMR, it can be NULL in which case a remap will be performed
* internally, if required for cache maintenance. This is primarily used
* as the services client bridge call handler for synchronous user-mode
* cache maintenance requests.
*/
PVRSRV_ERROR CacheOpValExec(PMR *psPMR,
IMG_UINT64 uiAddress,
IMG_DEVMEM_OFFSET_T uiOffset,
IMG_DEVMEM_SIZE_T uiSize,
PVRSRV_CACHE_OP uiCacheOp);
/*
* CacheOpQueue()
*
* This is the secondary cache maintenance interface and it is not
* guaranteed to be synchronous in that requests could be deferred
* and executed asynchronously. This interface is primarily meant
* as services client bridge call handler. Both uiInfoPgGFSeqNum
* and ui32[Current,Next]FenceSeqNum implements an internal client
* server queueing protocol so making use of this interface outside
* of services client is not recommended and should not be done.
*/
PVRSRV_ERROR CacheOpQueue(CONNECTION_DATA *psConnection,
PPVRSRV_DEVICE_NODE psDevNode,
IMG_UINT32 ui32OpCount,
PMR **ppsPMR,
IMG_UINT64 *puiAddress,
IMG_DEVMEM_OFFSET_T *puiOffset,
IMG_DEVMEM_SIZE_T *puiSize,
PVRSRV_CACHE_OP *puiCacheOp,
IMG_UINT32 ui32OpTimeline);
/*
* CacheOpLog()
*
* This is used for logging client cache maintenance operations that
* was executed in user-space.
*/
PVRSRV_ERROR CacheOpLog(PMR *psPMR,
IMG_UINT64 uiAddress,
IMG_DEVMEM_OFFSET_T uiOffset,
IMG_DEVMEM_SIZE_T uiSize,
IMG_UINT64 ui64StartTime,
IMG_UINT64 ui64EndTime,
PVRSRV_CACHE_OP uiCacheOp);
#endif /* CACHE_KM_H */

View File

@@ -0,0 +1,61 @@
/*************************************************************************/ /*!
@File
@Title Services cache management header
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@Description Defines for cache management which are visible internally
and externally
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ /**************************************************************************/
#ifndef CACHE_OPS_H
#define CACHE_OPS_H
#include "img_types.h"
/*!
* @Defgroup CPUCacheAPIs
* @{
*/
#define CACHE_BATCH_MAX (8U)
#define MAX_DMA_OPS (34)
typedef IMG_UINT32 PVRSRV_CACHE_OP; /*!< Type represents cache maintenance operation */
#define PVRSRV_CACHE_OP_NONE 0x0U /*!< No operation */
#define PVRSRV_CACHE_OP_CLEAN 0x1U /*!< Flush w/o invalidate */
#define PVRSRV_CACHE_OP_INVALIDATE 0x2U /*!< Invalidate w/o flush */
#define PVRSRV_CACHE_OP_FLUSH 0x3U /*!< Flush w/ invalidate */
/*! @} End of Defgroup CPUCacheAPIs */
#endif /* CACHE_OPS_H */

View File

@@ -0,0 +1,80 @@
/*******************************************************************************
@File
@Title Client bridge header for cache
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@Description Exports the client bridge functions for cache
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/
#ifndef CLIENT_CACHE_BRIDGE_H
#define CLIENT_CACHE_BRIDGE_H
#include "img_defs.h"
#include "pvrsrv_error.h"
#if defined(PVR_INDIRECT_BRIDGE_CLIENTS)
#include "pvr_bridge_client.h"
#include "pvr_bridge.h"
#endif
#include "common_cache_bridge.h"
IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpQueue(IMG_HANDLE hBridge,
IMG_UINT32 ui32NumCacheOps,
IMG_HANDLE * phPMR,
IMG_UINT64 * pui64Address,
IMG_DEVMEM_OFFSET_T * puiOffset,
IMG_DEVMEM_SIZE_T * puiSize,
PVRSRV_CACHE_OP * piuCacheOp,
IMG_UINT32 ui32OpTimeline);
IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpExec(IMG_HANDLE hBridge,
IMG_HANDLE hPMR,
IMG_UINT64 ui64Address,
IMG_DEVMEM_OFFSET_T uiOffset,
IMG_DEVMEM_SIZE_T uiSize, PVRSRV_CACHE_OP iuCacheOp);
IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpLog(IMG_HANDLE hBridge,
IMG_HANDLE hPMR,
IMG_UINT64 ui64Address,
IMG_DEVMEM_OFFSET_T uiOffset,
IMG_DEVMEM_SIZE_T uiSize,
IMG_INT64 i64StartTime,
IMG_INT64 i64EndTime, PVRSRV_CACHE_OP iuCacheOp);
#endif /* CLIENT_CACHE_BRIDGE_H */

View File

@@ -0,0 +1,111 @@
/*******************************************************************************
@File
@Title Direct client bridge for cache
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@Description Implements the client side of the bridge for cache
which is used in calls from Server context.
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/
#include "client_cache_bridge.h"
#include "img_defs.h"
#include "pvr_debug.h"
/* Module specific includes */
#include "cache_ops.h"
#include "cache_km.h"
IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpQueue(IMG_HANDLE hBridge,
IMG_UINT32 ui32NumCacheOps,
IMG_HANDLE *phPMR,
IMG_UINT64 *pui64Address,
IMG_DEVMEM_OFFSET_T *puiOffset,
IMG_DEVMEM_SIZE_T *puiSize,
PVRSRV_CACHE_OP *piuCacheOp, IMG_UINT32 ui32OpTimeline)
{
PVRSRV_ERROR eError;
PMR **psPMRInt;
psPMRInt = (PMR **) phPMR;
eError =
CacheOpQueue(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
ui32NumCacheOps,
psPMRInt, pui64Address, puiOffset, puiSize, piuCacheOp, ui32OpTimeline);
return eError;
}
IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpExec(IMG_HANDLE hBridge,
IMG_HANDLE hPMR,
IMG_UINT64 ui64Address,
IMG_DEVMEM_OFFSET_T uiOffset,
IMG_DEVMEM_SIZE_T uiSize, PVRSRV_CACHE_OP iuCacheOp)
{
PVRSRV_ERROR eError;
PMR *psPMRInt;
PVR_UNREFERENCED_PARAMETER(hBridge);
psPMRInt = (PMR *) hPMR;
eError = CacheOpValExec(psPMRInt, ui64Address, uiOffset, uiSize, iuCacheOp);
return eError;
}
IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpLog(IMG_HANDLE hBridge,
IMG_HANDLE hPMR,
IMG_UINT64 ui64Address,
IMG_DEVMEM_OFFSET_T uiOffset,
IMG_DEVMEM_SIZE_T uiSize,
IMG_INT64 i64StartTime,
IMG_INT64 i64EndTime, PVRSRV_CACHE_OP iuCacheOp)
{
PVRSRV_ERROR eError;
PMR *psPMRInt;
PVR_UNREFERENCED_PARAMETER(hBridge);
psPMRInt = (PMR *) hPMR;
eError =
CacheOpLog(psPMRInt,
ui64Address, uiOffset, uiSize, i64StartTime, i64EndTime, iuCacheOp);
return eError;
}

View File

@@ -0,0 +1,111 @@
/*******************************************************************************
@File
@Title Client bridge header for devicememhistory
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@Description Exports the client bridge functions for devicememhistory
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/
#ifndef CLIENT_DEVICEMEMHISTORY_BRIDGE_H
#define CLIENT_DEVICEMEMHISTORY_BRIDGE_H
#include "img_defs.h"
#include "pvrsrv_error.h"
#if defined(PVR_INDIRECT_BRIDGE_CLIENTS)
#include "pvr_bridge_client.h"
#include "pvr_bridge.h"
#endif
#include "common_devicememhistory_bridge.h"
IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistoryMap(IMG_HANDLE hBridge,
IMG_HANDLE hPMR,
IMG_DEVMEM_SIZE_T uiOffset,
IMG_DEV_VIRTADDR sDevVAddr,
IMG_DEVMEM_SIZE_T uiSize,
const IMG_CHAR * puiText,
IMG_UINT32 ui32Log2PageSize,
IMG_UINT32 ui32AllocationIndex,
IMG_UINT32 * pui32AllocationIndexOut);
IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistoryUnmap(IMG_HANDLE hBridge,
IMG_HANDLE hPMR,
IMG_DEVMEM_SIZE_T uiOffset,
IMG_DEV_VIRTADDR sDevVAddr,
IMG_DEVMEM_SIZE_T uiSize,
const IMG_CHAR * puiText,
IMG_UINT32 ui32Log2PageSize,
IMG_UINT32 ui32AllocationIndex,
IMG_UINT32 * pui32AllocationIndexOut);
IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistoryMapVRange(IMG_HANDLE hBridge,
IMG_DEV_VIRTADDR sBaseDevVAddr,
IMG_UINT32 ui32ui32StartPage,
IMG_UINT32 ui32NumPages,
IMG_DEVMEM_SIZE_T uiAllocSize,
const IMG_CHAR * puiText,
IMG_UINT32 ui32Log2PageSize,
IMG_UINT32 ui32AllocationIndex,
IMG_UINT32 * pui32AllocationIndexOut);
IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistoryUnmapVRange(IMG_HANDLE hBridge,
IMG_DEV_VIRTADDR sBaseDevVAddr,
IMG_UINT32 ui32ui32StartPage,
IMG_UINT32 ui32NumPages,
IMG_DEVMEM_SIZE_T uiAllocSize,
const IMG_CHAR * puiText,
IMG_UINT32 ui32Log2PageSize,
IMG_UINT32 ui32AllocationIndex,
IMG_UINT32 * pui32AllocationIndexOut);
IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistorySparseChange(IMG_HANDLE hBridge,
IMG_HANDLE hPMR,
IMG_DEVMEM_SIZE_T uiOffset,
IMG_DEV_VIRTADDR sDevVAddr,
IMG_DEVMEM_SIZE_T uiSize,
const IMG_CHAR * puiText,
IMG_UINT32 ui32Log2PageSize,
IMG_UINT32 ui32AllocPageCount,
IMG_UINT32 * pui32AllocPageIndices,
IMG_UINT32 ui32FreePageCount,
IMG_UINT32 * pui32FreePageIndices,
IMG_UINT32 ui32AllocationIndex,
IMG_UINT32 * pui32AllocationIndexOut);
#endif /* CLIENT_DEVICEMEMHISTORY_BRIDGE_H */

View File

@@ -0,0 +1,195 @@
/*******************************************************************************
@File
@Title Direct client bridge for devicememhistory
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@Description Implements the client side of the bridge for devicememhistory
which is used in calls from Server context.
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/
#include "client_devicememhistory_bridge.h"
#include "img_defs.h"
#include "pvr_debug.h"
/* Module specific includes */
#include "img_types.h"
#include "img_defs.h"
#include "devicemem_typedefs.h"
#include "pmr.h"
#include "devicemem_history_server.h"
IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistoryMap(IMG_HANDLE hBridge,
IMG_HANDLE hPMR,
IMG_DEVMEM_SIZE_T uiOffset,
IMG_DEV_VIRTADDR sDevVAddr,
IMG_DEVMEM_SIZE_T uiSize,
const IMG_CHAR *puiText,
IMG_UINT32 ui32Log2PageSize,
IMG_UINT32 ui32AllocationIndex,
IMG_UINT32 *pui32AllocationIndexOut)
{
PVRSRV_ERROR eError;
PMR *psPMRInt;
PVR_UNREFERENCED_PARAMETER(hBridge);
psPMRInt = (PMR *) hPMR;
eError =
DevicememHistoryMapKM(psPMRInt,
uiOffset,
sDevVAddr,
uiSize,
puiText,
ui32Log2PageSize, ui32AllocationIndex, pui32AllocationIndexOut);
return eError;
}
IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistoryUnmap(IMG_HANDLE hBridge,
IMG_HANDLE hPMR,
IMG_DEVMEM_SIZE_T uiOffset,
IMG_DEV_VIRTADDR sDevVAddr,
IMG_DEVMEM_SIZE_T uiSize,
const IMG_CHAR *puiText,
IMG_UINT32 ui32Log2PageSize,
IMG_UINT32 ui32AllocationIndex,
IMG_UINT32 *pui32AllocationIndexOut)
{
PVRSRV_ERROR eError;
PMR *psPMRInt;
PVR_UNREFERENCED_PARAMETER(hBridge);
psPMRInt = (PMR *) hPMR;
eError =
DevicememHistoryUnmapKM(psPMRInt,
uiOffset,
sDevVAddr,
uiSize,
puiText,
ui32Log2PageSize, ui32AllocationIndex, pui32AllocationIndexOut);
return eError;
}
IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistoryMapVRange(IMG_HANDLE hBridge,
IMG_DEV_VIRTADDR sBaseDevVAddr,
IMG_UINT32 ui32ui32StartPage,
IMG_UINT32 ui32NumPages,
IMG_DEVMEM_SIZE_T uiAllocSize,
const IMG_CHAR *puiText,
IMG_UINT32 ui32Log2PageSize,
IMG_UINT32 ui32AllocationIndex,
IMG_UINT32 *pui32AllocationIndexOut)
{
PVRSRV_ERROR eError;
eError =
DevicememHistoryMapVRangeKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
sBaseDevVAddr,
ui32ui32StartPage,
ui32NumPages,
uiAllocSize,
puiText,
ui32Log2PageSize,
ui32AllocationIndex, pui32AllocationIndexOut);
return eError;
}
IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistoryUnmapVRange(IMG_HANDLE hBridge,
IMG_DEV_VIRTADDR sBaseDevVAddr,
IMG_UINT32 ui32ui32StartPage,
IMG_UINT32 ui32NumPages,
IMG_DEVMEM_SIZE_T uiAllocSize,
const IMG_CHAR *puiText,
IMG_UINT32 ui32Log2PageSize,
IMG_UINT32 ui32AllocationIndex,
IMG_UINT32 *pui32AllocationIndexOut)
{
PVRSRV_ERROR eError;
eError =
DevicememHistoryUnmapVRangeKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
sBaseDevVAddr,
ui32ui32StartPage,
ui32NumPages,
uiAllocSize,
puiText,
ui32Log2PageSize,
ui32AllocationIndex, pui32AllocationIndexOut);
return eError;
}
IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistorySparseChange(IMG_HANDLE hBridge,
IMG_HANDLE hPMR,
IMG_DEVMEM_SIZE_T uiOffset,
IMG_DEV_VIRTADDR sDevVAddr,
IMG_DEVMEM_SIZE_T uiSize,
const IMG_CHAR *puiText,
IMG_UINT32 ui32Log2PageSize,
IMG_UINT32 ui32AllocPageCount,
IMG_UINT32 *pui32AllocPageIndices,
IMG_UINT32 ui32FreePageCount,
IMG_UINT32 *pui32FreePageIndices,
IMG_UINT32 ui32AllocationIndex,
IMG_UINT32 *pui32AllocationIndexOut)
{
PVRSRV_ERROR eError;
PMR *psPMRInt;
PVR_UNREFERENCED_PARAMETER(hBridge);
psPMRInt = (PMR *) hPMR;
eError =
DevicememHistorySparseChangeKM(psPMRInt,
uiOffset,
sDevVAddr,
uiSize,
puiText,
ui32Log2PageSize,
ui32AllocPageCount,
pui32AllocPageIndices,
ui32FreePageCount,
pui32FreePageIndices,
ui32AllocationIndex, pui32AllocationIndexOut);
return eError;
}

View File

@@ -0,0 +1,64 @@
/*******************************************************************************
@File
@Title Client bridge header for htbuffer
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@Description Exports the client bridge functions for htbuffer
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/
#ifndef CLIENT_HTBUFFER_BRIDGE_H
#define CLIENT_HTBUFFER_BRIDGE_H
#include "img_defs.h"
#include "pvrsrv_error.h"
#if defined(PVR_INDIRECT_BRIDGE_CLIENTS)
#include "pvr_bridge_client.h"
#include "pvr_bridge.h"
#endif
#include "common_htbuffer_bridge.h"
IMG_INTERNAL PVRSRV_ERROR BridgeHTBControl(IMG_HANDLE hBridge,
IMG_UINT32 ui32NumGroups,
IMG_UINT32 * pui32GroupEnable,
IMG_UINT32 ui32LogLevel,
IMG_UINT32 ui32EnablePID,
IMG_UINT32 ui32LogMode, IMG_UINT32 ui32OpMode);
#endif /* CLIENT_HTBUFFER_BRIDGE_H */

View File

@@ -0,0 +1,70 @@
/*******************************************************************************
@File
@Title Direct client bridge for htbuffer
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@Description Implements the client side of the bridge for htbuffer
which is used in calls from Server context.
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/
#include "client_htbuffer_bridge.h"
#include "img_defs.h"
#include "pvr_debug.h"
/* Module specific includes */
#include "devicemem_typedefs.h"
#include "htbuffer_types.h"
#include "htbserver.h"
IMG_INTERNAL PVRSRV_ERROR BridgeHTBControl(IMG_HANDLE hBridge,
IMG_UINT32 ui32NumGroups,
IMG_UINT32 *pui32GroupEnable,
IMG_UINT32 ui32LogLevel,
IMG_UINT32 ui32EnablePID,
IMG_UINT32 ui32LogMode, IMG_UINT32 ui32OpMode)
{
PVRSRV_ERROR eError;
PVR_UNREFERENCED_PARAMETER(hBridge);
eError =
HTBControlKM(ui32NumGroups,
pui32GroupEnable, ui32LogLevel, ui32EnablePID, ui32LogMode, ui32OpMode);
return eError;
}

View File

@@ -0,0 +1,229 @@
/*******************************************************************************
@File
@Title Client bridge header for mm
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@Description Exports the client bridge functions for mm
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/
#ifndef CLIENT_MM_BRIDGE_H
#define CLIENT_MM_BRIDGE_H
#include "img_defs.h"
#include "pvrsrv_error.h"
#if defined(PVR_INDIRECT_BRIDGE_CLIENTS)
#include "pvr_bridge_client.h"
#include "pvr_bridge.h"
#endif
#include "common_mm_bridge.h"
IMG_INTERNAL PVRSRV_ERROR BridgePMRExportPMR(IMG_HANDLE hBridge,
IMG_HANDLE hPMR,
IMG_HANDLE * phPMRExport,
IMG_UINT64 * pui64Size,
IMG_UINT32 * pui32Log2Contig,
IMG_UINT64 * pui64Password);
IMG_INTERNAL PVRSRV_ERROR BridgePMRUnexportPMR(IMG_HANDLE hBridge, IMG_HANDLE hPMRExport);
IMG_INTERNAL PVRSRV_ERROR BridgePMRGetUID(IMG_HANDLE hBridge,
IMG_HANDLE hPMR, IMG_UINT64 * pui64UID);
IMG_INTERNAL PVRSRV_ERROR BridgePMRMakeLocalImportHandle(IMG_HANDLE hBridge,
IMG_HANDLE hBuffer, IMG_HANDLE * phExtMem);
IMG_INTERNAL PVRSRV_ERROR BridgePMRUnmakeLocalImportHandle(IMG_HANDLE hBridge, IMG_HANDLE hExtMem);
IMG_INTERNAL PVRSRV_ERROR BridgePMRImportPMR(IMG_HANDLE hBridge,
IMG_HANDLE hPMRExport,
IMG_UINT64 ui64uiPassword,
IMG_UINT64 ui64uiSize,
IMG_UINT32 ui32uiLog2Contig, IMG_HANDLE * phPMR);
IMG_INTERNAL PVRSRV_ERROR BridgePMRLocalImportPMR(IMG_HANDLE hBridge,
IMG_HANDLE hExtHandle,
IMG_HANDLE * phPMR,
IMG_DEVMEM_SIZE_T * puiSize,
IMG_DEVMEM_ALIGN_T * puiAlign);
IMG_INTERNAL PVRSRV_ERROR BridgePMRUnrefPMR(IMG_HANDLE hBridge, IMG_HANDLE hPMR);
IMG_INTERNAL PVRSRV_ERROR BridgePhysmemNewRamBackedPMR(IMG_HANDLE hBridge,
IMG_DEVMEM_SIZE_T uiSize,
IMG_UINT32 ui32NumPhysChunks,
IMG_UINT32 ui32NumVirtChunks,
IMG_UINT32 * pui32MappingTable,
IMG_UINT32 ui32Log2PageSize,
PVRSRV_MEMALLOCFLAGS_T uiFlags,
IMG_UINT32 ui32AnnotationLength,
const IMG_CHAR * puiAnnotation,
IMG_PID ui32PID,
IMG_HANDLE * phPMRPtr,
IMG_UINT32 ui32PDumpFlags,
PVRSRV_MEMALLOCFLAGS_T * puiOutFlags);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntCtxCreate(IMG_HANDLE hBridge,
IMG_BOOL bbKernelMemoryCtx,
IMG_HANDLE * phDevMemServerContext,
IMG_HANDLE * phPrivData,
IMG_UINT32 * pui32CPUCacheLineSize);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntCtxDestroy(IMG_HANDLE hBridge,
IMG_HANDLE hDevmemServerContext);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntHeapCreate(IMG_HANDLE hBridge,
IMG_HANDLE hDevmemCtx,
IMG_UINT32 ui32HeapConfigIndex,
IMG_UINT32 ui32HeapIndex,
IMG_HANDLE * phDevmemHeapPtr);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntHeapDestroy(IMG_HANDLE hBridge, IMG_HANDLE hDevmemHeap);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntMapPMR(IMG_HANDLE hBridge,
IMG_HANDLE hReservation, IMG_HANDLE hPMR);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntUnmapPMR(IMG_HANDLE hBridge, IMG_HANDLE hReservation);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntReserveRange(IMG_HANDLE hBridge,
IMG_HANDLE hDevmemServerHeap,
IMG_DEV_VIRTADDR sAddress,
IMG_DEVMEM_SIZE_T uiLength,
PVRSRV_MEMALLOCFLAGS_T uiFlags,
IMG_HANDLE * phReservation);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntReserveRangeAndMapPMR(IMG_HANDLE hBridge,
IMG_HANDLE hDevmemServerHeap,
IMG_DEV_VIRTADDR sAddress,
IMG_DEVMEM_SIZE_T uiLength,
IMG_HANDLE hPMR,
PVRSRV_MEMALLOCFLAGS_T uiFlags,
IMG_HANDLE * phReservation);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntUnreserveRange(IMG_HANDLE hBridge,
IMG_HANDLE hReservation);
IMG_INTERNAL PVRSRV_ERROR BridgeChangeSparseMem(IMG_HANDLE hBridge,
IMG_UINT32 ui32AllocPageCount,
IMG_UINT32 * pui32AllocPageIndices,
IMG_UINT32 ui32FreePageCount,
IMG_UINT32 * pui32FreePageIndices,
IMG_UINT32 ui32SparseFlags,
IMG_HANDLE hReservation);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIsVDevAddrValid(IMG_HANDLE hBridge,
IMG_HANDLE hDevmemCtx,
IMG_DEV_VIRTADDR sAddress);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemInvalidateFBSCTable(IMG_HANDLE hBridge,
IMG_HANDLE hDevmemCtx,
IMG_UINT64 ui64FBSCEntries);
IMG_INTERNAL PVRSRV_ERROR BridgeHeapCfgHeapConfigCount(IMG_HANDLE hBridge,
IMG_UINT32 * pui32NumHeapConfigs);
IMG_INTERNAL PVRSRV_ERROR BridgeHeapCfgHeapCount(IMG_HANDLE hBridge,
IMG_UINT32 ui32HeapConfigIndex,
IMG_UINT32 * pui32NumHeaps);
IMG_INTERNAL PVRSRV_ERROR BridgeHeapCfgHeapConfigName(IMG_HANDLE hBridge,
IMG_UINT32 ui32HeapConfigIndex,
IMG_UINT32 ui32HeapConfigNameBufSz,
IMG_CHAR * puiHeapConfigName);
IMG_INTERNAL PVRSRV_ERROR BridgeHeapCfgHeapDetails(IMG_HANDLE hBridge,
IMG_UINT32 ui32HeapConfigIndex,
IMG_UINT32 ui32HeapIndex,
IMG_UINT32 ui32HeapNameBufSz,
IMG_CHAR * puiHeapNameOut,
IMG_DEV_VIRTADDR * psDevVAddrBase,
IMG_DEVMEM_SIZE_T * puiHeapLength,
IMG_DEVMEM_SIZE_T * puiReservedRegionLength,
IMG_UINT32 * pui32Log2DataPageSizeOut,
IMG_UINT32 * pui32Log2ImportAlignmentOut);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntRegisterPFNotifyKM(IMG_HANDLE hBridge,
IMG_HANDLE hDevmemCtx,
IMG_BOOL bRegister);
IMG_INTERNAL PVRSRV_ERROR BridgePhysHeapGetMemInfo(IMG_HANDLE hBridge,
IMG_UINT32 ui32PhysHeapCount,
PVRSRV_PHYS_HEAP * peaPhysHeapID,
PHYS_HEAP_MEM_STATS * pasapPhysHeapMemStats);
IMG_INTERNAL PVRSRV_ERROR BridgeGetDefaultPhysicalHeap(IMG_HANDLE hBridge,
PVRSRV_PHYS_HEAP * peHeap);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemGetFaultAddress(IMG_HANDLE hBridge,
IMG_HANDLE hDevmemCtx,
IMG_DEV_VIRTADDR * psFaultAddress);
IMG_INTERNAL PVRSRV_ERROR BridgePVRSRVStatsUpdateOOMStat(IMG_HANDLE hBridge,
IMG_UINT32 ui32ui32StatType,
IMG_PID ui32pid);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemXIntReserveRange(IMG_HANDLE hBridge,
IMG_HANDLE hDevmemServerHeap,
IMG_DEV_VIRTADDR sAddress,
IMG_DEVMEM_SIZE_T uiLength,
IMG_HANDLE * phReservation);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemXIntUnreserveRange(IMG_HANDLE hBridge,
IMG_HANDLE hReservation);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemXIntMapPages(IMG_HANDLE hBridge,
IMG_HANDLE hReservation,
IMG_HANDLE hPMR,
IMG_UINT32 ui32PageCount,
IMG_UINT32 ui32PhysPageOffset,
PVRSRV_MEMALLOCFLAGS_T uiFlags,
IMG_UINT32 ui32VirtPageOffset);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemXIntUnmapPages(IMG_HANDLE hBridge,
IMG_HANDLE hReservation,
IMG_UINT32 ui32VirtPageOffset,
IMG_UINT32 ui32PageCount);
IMG_INTERNAL PVRSRV_ERROR BridgeDevmemXIntMapVRangeToBackingPage(IMG_HANDLE hBridge,
IMG_HANDLE hReservation,
IMG_UINT32 ui32PageCount,
PVRSRV_MEMALLOCFLAGS_T uiFlags,
IMG_UINT32 ui32VirtPageOffset);
#endif /* CLIENT_MM_BRIDGE_H */

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