Compare commits
22 Commits
f071dc9a24
...
218862ffdd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
218862ffdd | ||
|
|
95d169caeb | ||
|
|
d1a0fed7aa | ||
|
|
006816cce1 | ||
|
|
b56f19ed96 | ||
|
|
7a3477fcec | ||
|
|
2ac7095ee6 | ||
|
|
1225339fca | ||
|
|
434ae3d5fc | ||
|
|
1479e89f14 | ||
|
|
0a484b1703 | ||
|
|
4b10ff3937 | ||
|
|
8cf766e6cf | ||
|
|
52d25821d3 | ||
|
|
8add2b4251 | ||
|
|
ca4f09cd41 | ||
|
|
e31acb1b2d | ||
|
|
876ebfd3c5 | ||
|
|
4b8bcc0c64 | ||
|
|
0cf5473f0f | ||
|
|
841a1afde6 | ||
|
|
ef98ee35f2 |
@@ -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) */
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -5,4 +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
|
||||
dtb-$(CONFIG_ARCH_XUANTIE) += a200-evb.dtb a200-dev.dtb
|
||||
|
||||
2189
arch/riscv/boot/dts/thead/a200-dev.dts
Normal file
2189
arch/riscv/boot/dts/thead/a200-dev.dts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -435,14 +435,14 @@
|
||||
/* ONKEY/SYS_RST_N */
|
||||
key1 {
|
||||
label = "Key1";
|
||||
wakeup-source;
|
||||
//wakeup-source;
|
||||
linux,code = <KEY_MACRO1>;
|
||||
debounce-interval = <1>;
|
||||
gpios = <&aogpio 4 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
key2 {
|
||||
label = "Key2";
|
||||
wakeup-source;
|
||||
//wakeup-source;
|
||||
linux,code = <KEY_MACRO2>;
|
||||
debounce-interval = <1>;
|
||||
gpios = <&aogpio 5 GPIO_ACTIVE_LOW>;
|
||||
@@ -1948,23 +1948,6 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdio1 { // WiFi&BT
|
||||
max-frequency = <100000000>;
|
||||
bus-width = <4>;
|
||||
pull_up;
|
||||
no-sd;
|
||||
no-mmc;
|
||||
broken-cd;
|
||||
io_fixed_1v8;
|
||||
non-removable;
|
||||
post-power-on-delay-ms = <200>;
|
||||
wprtn_ignore;
|
||||
cap-sd-highspeed;
|
||||
wakeup-source;
|
||||
keep-power-in-suspend;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&ap_i2s {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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"
|
||||
@@ -67,7 +69,7 @@
|
||||
pcie3x4 = &dm3x4;
|
||||
pcie3x1 = &rp3x1;
|
||||
vi_sensor0 = &mipicsi0_4lane_port;
|
||||
vi_sensor1 = &mipicsi1_a_port;
|
||||
vi_sensor1 = &mipi1csi1_a_port;
|
||||
};
|
||||
|
||||
/* The actual capacity will be adjusted through SPL */
|
||||
@@ -111,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";
|
||||
@@ -131,34 +138,13 @@
|
||||
|
||||
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,vcc1-gpios = <&aw9535_1 11 GPIO_ACTIVE_HIGH>;
|
||||
WIFI,vcc2-gpios = <&aw9535_1 12 GPIO_ACTIVE_HIGH>;
|
||||
WIFI,poweren-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
|
||||
power_on_after_init;
|
||||
power_on_when_resume;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
wcn_bt: wireless-bluetooth {
|
||||
compatible = "bluetooth-platdata";
|
||||
BT,power-gpios = <&ao_gpio1 4 GPIO_ACTIVE_HIGH>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* The bootargs in U-Boot will override the configuration set here. */
|
||||
chosen {
|
||||
stdout-path = "serial4";
|
||||
};
|
||||
|
||||
lcd0_backlight: pwm-backlight@0 {
|
||||
compatible = "pwm-backlight";
|
||||
status = "okay";
|
||||
@@ -203,7 +189,7 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
mipicsi1_a_port: mipicsi1_a_port@0 {
|
||||
mipi1csi1_a_port: mipi1csi1_a_port@0 {
|
||||
compatible = "zhihe,vi_sensor";
|
||||
clocks = <&clk SW_TOP_PAD_SENSOR_VCLK1_EN>;
|
||||
clock-names = "core_clk";
|
||||
@@ -219,17 +205,63 @@
|
||||
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 {
|
||||
pwoer-5v-en-hog {
|
||||
power-5v-en-hog {
|
||||
gpio-hog;
|
||||
gpios = <29 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "power_5v_en";
|
||||
};
|
||||
|
||||
pwoer-3v3-en-hog {
|
||||
power-3v3-en-hog {
|
||||
gpio-hog;
|
||||
gpios = <26 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
@@ -332,6 +364,7 @@
|
||||
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;
|
||||
@@ -341,6 +374,7 @@
|
||||
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;
|
||||
@@ -350,24 +384,25 @@
|
||||
regulator-name = "dvdd_vp";
|
||||
regulator-type = "voltage";
|
||||
regulator-ramp-delay = <100>;
|
||||
regulator-enable-ramp-delay = <2000>;
|
||||
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-enable-ramp-delay = <2000>;
|
||||
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-enable-ramp-delay = <2000>;
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <1000000>;
|
||||
regulator-always-on;
|
||||
@@ -377,9 +412,9 @@
|
||||
regulator-name = "dvdd_gpu";
|
||||
regulator-type = "voltage";
|
||||
regulator-ramp-delay = <100>;
|
||||
regulator-enable-ramp-delay = <2000>;
|
||||
regulator-min-microvolt = <750000>;
|
||||
regulator-max-microvolt = <800000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
};
|
||||
@@ -413,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;
|
||||
@@ -475,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_18", "GPIO0_19", "GPIO0_20", "GPIO0_21";
|
||||
pins = "GPIO0_25";
|
||||
function = "pcie_x1";
|
||||
bias-disable;
|
||||
drive-strength = <7>;
|
||||
@@ -509,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>;
|
||||
@@ -580,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>;
|
||||
};
|
||||
};
|
||||
@@ -620,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 {
|
||||
@@ -652,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 {
|
||||
@@ -673,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 {
|
||||
@@ -684,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 {
|
||||
@@ -789,14 +834,14 @@
|
||||
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>;
|
||||
@@ -961,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 = <®_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 {
|
||||
@@ -998,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 {
|
||||
@@ -1008,11 +1129,6 @@
|
||||
&rp3x1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pcie_x1_pins>;
|
||||
minipcie-1v5-pwren-gpios = <&aw9535_0 6 GPIO_ACTIVE_HIGH>;
|
||||
minipcie-3v3-pwren-gpios = <&aw9535_0 7 GPIO_ACTIVE_HIGH>;
|
||||
minipcie-perst-gpios = <&aw9535_0 15 GPIO_ACTIVE_HIGH>;
|
||||
pcie-clk-en-gpios = <&aw9535_0 12 GPIO_ACTIVE_HIGH>;
|
||||
pcie-clk-pwren-gpios = <&aw9535_1 13 GPIO_ACTIVE_HIGH>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -1043,11 +1159,6 @@
|
||||
pinctrl-0 = <&pwm1_pins>;
|
||||
};
|
||||
|
||||
&can0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&can0_pins>;
|
||||
};
|
||||
|
||||
&hdmi_tx {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&hdmi_pins>;
|
||||
@@ -1069,7 +1180,6 @@
|
||||
pull_up;
|
||||
bus-width = <8>;
|
||||
cap-mmc-highspeed;
|
||||
clk-delay-mmc-hs200 = <60>;
|
||||
};
|
||||
|
||||
&sdhci0 {
|
||||
@@ -1087,25 +1197,39 @@
|
||||
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>;
|
||||
};
|
||||
|
||||
&usb3 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&usb3_pins>;
|
||||
typec-pwren-gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>;
|
||||
&usb20phy1 {
|
||||
pwren-gpios = <&aw9535_1 9 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
&sata {
|
||||
m2-sata-3v3-pwren-gpios = <&aw9535_0 14 GPIO_ACTIVE_HIGH>;
|
||||
m2-sata-en-gpios = <&aw9535_0 9 GPIO_ACTIVE_HIGH>;
|
||||
sata-clk-en-gpios = <&aw9535_0 12 GPIO_ACTIVE_HIGH>;
|
||||
sata-clk-pwren-gpios = <&aw9535_1 13 GPIO_ACTIVE_HIGH>;
|
||||
status = "disabled";
|
||||
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 {
|
||||
@@ -1122,29 +1246,19 @@
|
||||
};
|
||||
|
||||
//config dsi display: dpu_disp0->dup_enc0->dsi0->lcd_plane
|
||||
|
||||
&dpu_enc0 {
|
||||
status = "disabled";
|
||||
ports {
|
||||
/* output */
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
enc0_out: endpoint {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
&dsi_enc_out {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
|
||||
&dhost_0 {
|
||||
status = "disabled";
|
||||
&dsi_host0 {
|
||||
status = "okay";
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dsi0_in: endpoint {
|
||||
remote-endpoint = <&enc0_out>;
|
||||
remote-endpoint = <&dsi_enc_out>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
@@ -1179,3 +1293,74 @@
|
||||
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 {
|
||||
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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -245,13 +245,13 @@
|
||||
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>;
|
||||
@@ -265,13 +265,13 @@
|
||||
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>;
|
||||
@@ -373,13 +373,13 @@
|
||||
cs-gpios = <&gpio0_die1 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_die1>;
|
||||
|
||||
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>;
|
||||
@@ -393,13 +393,13 @@
|
||||
cs-gpios = <&gpio2_die1 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_die1>;
|
||||
|
||||
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>;
|
||||
|
||||
@@ -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 */
|
||||
@@ -122,34 +125,7 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
codec_dummy_i2s_8ch0: codec_dummy_i2s_8ch0 {
|
||||
compatible = "zhihe,dummy-pcm-i2s-8ch";
|
||||
sound-name-prefix = "DUMMY";
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
#sound-dai-cells = <1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
codec_dummy_i2s_8ch1: codec_dummy_i2s_8ch1 {
|
||||
compatible = "zhihe,dummy-pcm-i2s-8ch";
|
||||
sound-name-prefix = "DUMMY";
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
#sound-dai-cells = <1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
codec_dummy_i2s_8ch2: codec_dummy_i2s_8ch2 {
|
||||
compatible = "zhihe,dummy-pcm-i2s-8ch";
|
||||
sound-name-prefix = "DUMMY";
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
#sound-dai-cells = <1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
codec_dummy_i2s_8ch3: codec_dummy_i2s_8ch3 {
|
||||
codec_dummy_i2s_8ch: codec_dummy_i2s_8ch {
|
||||
compatible = "zhihe,dummy-pcm-i2s-8ch";
|
||||
sound-name-prefix = "DUMMY";
|
||||
#address-cells = <0>;
|
||||
@@ -167,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 {
|
||||
@@ -248,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 */
|
||||
@@ -266,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 */
|
||||
@@ -292,10 +202,10 @@
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
|
||||
SOUND_CARD_LINK(0, left_j, i2s_8ch_sd0, 0, dummy_i2s_8ch0, 0); /* I2S3-SD0 <-> HW-Codec */
|
||||
SOUND_CARD_LINK(1, left_j, i2s_8ch_sd1, 0, dummy_i2s_8ch1, 0); /* I2S3-SD1 <-> HW-Codec */
|
||||
SOUND_CARD_LINK(2, left_j, i2s_8ch_sd2, 0, dummy_i2s_8ch2, 0); /* I2S3-SD2 <-> HW-Codec */
|
||||
SOUND_CARD_LINK(3, left_j, i2s_8ch_sd3, 0, dummy_i2s_8ch3, 0); /* I2S3-SD3 <-> HW-Codec */
|
||||
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 {
|
||||
@@ -306,13 +216,13 @@
|
||||
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@5 {
|
||||
@@ -322,14 +232,48 @@
|
||||
#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";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -402,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>;
|
||||
@@ -452,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>;
|
||||
@@ -466,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 {
|
||||
@@ -477,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>;
|
||||
@@ -488,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 {
|
||||
@@ -520,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 {
|
||||
@@ -549,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>;
|
||||
@@ -595,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>;
|
||||
@@ -675,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>;
|
||||
@@ -713,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 {
|
||||
@@ -745,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 {
|
||||
@@ -778,7 +722,7 @@
|
||||
function = "i2s1";
|
||||
bias-disable;
|
||||
drive-strength = <13>;
|
||||
input-schmitt-disable;
|
||||
input-schmitt-enable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
@@ -840,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 {
|
||||
@@ -852,7 +796,7 @@
|
||||
function = "i2s2";
|
||||
bias-disable;
|
||||
drive-strength = <13>;
|
||||
input-schmitt-disable;
|
||||
input-schmitt-enable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
@@ -882,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 {
|
||||
@@ -893,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>;
|
||||
@@ -906,7 +850,7 @@
|
||||
function = "i2s3";
|
||||
bias-disable;
|
||||
drive-strength = <13>;
|
||||
input-schmitt-disable;
|
||||
input-schmitt-enable;
|
||||
slew-rate = <0>;
|
||||
};
|
||||
};
|
||||
@@ -915,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 {
|
||||
@@ -937,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 {
|
||||
@@ -954,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>;
|
||||
@@ -1089,11 +1044,11 @@
|
||||
&spi0 {
|
||||
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>;
|
||||
@@ -1104,13 +1059,13 @@
|
||||
&spi1 {
|
||||
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>;
|
||||
@@ -1122,13 +1077,13 @@
|
||||
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>;
|
||||
@@ -1142,13 +1097,13 @@
|
||||
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>;
|
||||
@@ -1273,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 {
|
||||
@@ -1283,7 +1238,7 @@
|
||||
work-mode = "ES7210_TDM_1LRCK_DSPB";
|
||||
channels-max = <8>;
|
||||
sound-name-prefix = "ES7210_ADC3";
|
||||
status = "disabled";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1291,6 +1246,11 @@
|
||||
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";
|
||||
@@ -1345,11 +1305,6 @@
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
&dm3x4 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pcie_x4_pins>;
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart2_pins>;
|
||||
@@ -1380,7 +1335,6 @@
|
||||
pinctrl-0 = <&can2_pins>;
|
||||
};
|
||||
|
||||
|
||||
&audio_i2s2 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s2_pins>;
|
||||
@@ -1405,6 +1359,7 @@
|
||||
&sata {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sata_p0_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&hdmi_tx {
|
||||
@@ -1424,7 +1379,6 @@
|
||||
pull_up;
|
||||
bus-width = <8>;
|
||||
cap-mmc-highspeed;
|
||||
clk-delay-mmc-hs200 = <60>;
|
||||
};
|
||||
|
||||
&sdhci0 {
|
||||
@@ -1446,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 */
|
||||
|
||||
/*
|
||||
@@ -1559,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
|
||||
@@ -1736,29 +1646,20 @@
|
||||
phy_name = "CSI_4LANE"; //combination 4lane
|
||||
};
|
||||
|
||||
//config dsi display: dpu_disp0->dup_enc0->dsi0->lcd_plane
|
||||
&dpu_enc0 {
|
||||
status = "disabled";
|
||||
ports {
|
||||
/* output */
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
enc0_out: endpoint {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
//config dsi display: auxdisp->enc0->dsi0->lcd_lt8819_plane
|
||||
&dsi_enc_out {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
|
||||
&dhost_0 {
|
||||
status = "disabled";
|
||||
&dsi_host0 {
|
||||
status = "okay";
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
dsi0_in: endpoint {
|
||||
remote-endpoint = <&enc0_out>;
|
||||
remote-endpoint = <&dsi_enc_out>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
@@ -1768,10 +1669,14 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
panel0@0 { //virtual panel0, not yet enabled
|
||||
compatible = "jadard,jd9365da-h3";
|
||||
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>;
|
||||
@@ -1779,3 +1684,53 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&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>;
|
||||
};
|
||||
|
||||
@@ -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>;
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
@@ -1,3 +1,74 @@
|
||||
/ {
|
||||
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";
|
||||
@@ -191,7 +262,7 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&usb31_zhihe {
|
||||
&usb31 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -199,7 +270,7 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&dhost_0 {
|
||||
&dsi_host0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -211,60 +282,32 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&vp_dfmu_iommu {
|
||||
status = "disabled";
|
||||
&dfmu_mt_vp {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&vp_dfmu_mt {
|
||||
status = "disabled";
|
||||
&dfmu_mt_npu {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&npu_dfmu_iommu {
|
||||
status = "disabled";
|
||||
&dfmu_mt_vi {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&npu_dfmu_mt {
|
||||
status = "disabled";
|
||||
&dfmu_mt_vo {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&vi_dfmu_iommu {
|
||||
status = "disabled";
|
||||
&dfmu_mt_peri1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&vi_dfmu_mt {
|
||||
status = "disabled";
|
||||
&dfmu_mt_pcie {
|
||||
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";
|
||||
&dfmu_mt_usb {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&vidmem {
|
||||
@@ -275,3 +318,11 @@
|
||||
&uart4_die1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&auxdisp {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&dpu_enc0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -54,6 +54,10 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&can0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&can1 {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -102,6 +106,14 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&auxdisp {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&dpu_enc0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&audio_i2s0 {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -175,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 {
|
||||
|
||||
@@ -262,6 +262,14 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&auxdisp {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&dpu_enc0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&audio_i2s0 {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -437,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";
|
||||
};
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
|
||||
&c908_0 {
|
||||
// status = "disabled";
|
||||
};
|
||||
|
||||
// &c908_1 {
|
||||
// status = "disabled";
|
||||
// };
|
||||
@@ -39,6 +34,10 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&uart3 {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -75,6 +74,10 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&qspi1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -87,6 +90,10 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c4 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c5 {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -99,18 +106,6 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&pwm0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&pwm2 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&audio_i2s2 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&peri3_padctrl {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -140,10 +135,6 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&timer0 {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -172,7 +163,23 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c4 {
|
||||
&rp3x1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&dm3x4 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&sata {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&auxdisp {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&dpu_enc0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -180,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";
|
||||
};
|
||||
|
||||
@@ -186,6 +186,14 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&auxdisp {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&dpu_enc0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&clk_gpu {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -217,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";
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//sec-tee.dtsi
|
||||
|
||||
/ {
|
||||
//compatible = "zhihe,p100,tee";//update dst compatible value for tee
|
||||
//compatible = "zhihe,a210,tee";//update dst compatible value for tee
|
||||
chosen {
|
||||
opensbi-domains {
|
||||
compatible = "opensbi,domain,config";
|
||||
@@ -175,149 +175,149 @@
|
||||
|
||||
/* PCIE iopmp*/
|
||||
&device_pcie_mt_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_pcie_0_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_pcie_1_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_sata_0_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_dmac_ap_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_sd_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_emmc_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_pcie_iommu_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
|
||||
/* VP iopmp*/
|
||||
&device_vp_mt_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_venc_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_vdec_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_g2d_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_vp_iommu_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
|
||||
/* VI iopmp*/
|
||||
&device_vi_mt_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_isp_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_vipre_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_dw200_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_vi_comp_decomp_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_vi_iommu_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
|
||||
/* NPU iopmp*/
|
||||
&device_npu_mt_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_npu_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_npu_iommu_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
|
||||
/* VO iopmp */
|
||||
&device_vo_mt_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_display_0_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_display_1_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_auxdisp_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_vo_iommu_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
|
||||
/* PERI1 iopmp */
|
||||
&device_peri1_mt_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_gmac_0_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_gmac_1_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_gmac_2_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_chip_dbg_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
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>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
|
||||
/* USB iopmp*/
|
||||
&device_usb_mt_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_usb3_0_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_usb2_1_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_usb2_2_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_usb_iommu_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
|
||||
/* GPU iopmp*/
|
||||
&device_gpu_mt_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
&device_gpu_iopmp {
|
||||
iopmp-regions = <&security_device_region>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
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>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
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>, <&tee_os_region>, <&trust_firmware_region>, <&bypass_region>;
|
||||
iopmp-regions = <&security_device_region>, <&trust_firmware_region>, <&tee_os_region>, <&bypass_region>;
|
||||
};
|
||||
|
||||
@@ -294,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>;
|
||||
@@ -353,8 +349,7 @@
|
||||
reg = <0x00 0x1a000000 0x0 0x02000000>;
|
||||
reg-names = "control";
|
||||
riscv,max-priority = <7>;
|
||||
riscv,ndev = <400>;
|
||||
cpu-id = <8>;
|
||||
riscv,ndev = <351>;
|
||||
};
|
||||
|
||||
clocks1 {
|
||||
@@ -537,9 +532,9 @@
|
||||
<&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_TEE_CLK_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_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 */
|
||||
@@ -734,7 +729,7 @@
|
||||
<&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_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 */
|
||||
@@ -930,7 +925,7 @@
|
||||
<&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_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 */
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <dt-bindings/clock/a210-clock.h>
|
||||
#include <dt-bindings/reset/a210-reset.h>
|
||||
#include <dt-bindings/iopmp/zh-iopmp.h>
|
||||
#include <dt-bindings/power/a210-power.h>
|
||||
|
||||
/ {
|
||||
compatible = "zhihe,a210";
|
||||
@@ -398,8 +399,8 @@
|
||||
cluster1_opp: opp-table-cluster1 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
opp1-1500000000 {
|
||||
opp-hz = /bits/ 64 <1500000000>;
|
||||
opp1-500000000 {
|
||||
opp-hz = /bits/ 64 <500000000>;
|
||||
opp-microvolt = <800000>;
|
||||
};
|
||||
opp1-1698000000 {
|
||||
@@ -495,28 +496,6 @@
|
||||
entry-cnt = <4 4>; /* The number of CPUs in each cluster */
|
||||
control-reg = <0x00 0x10144004 0x00 0x10144008>;/* SWRST C908 C920*/
|
||||
control-val = <0x1f 0x1f>; /* bit0:clust, bit1~4:core0~core3 */
|
||||
csr-init = < /* 0x00 0x00, Magic New Cluster start */
|
||||
0x00 0x00 /* Cluster0 init CSR Register */
|
||||
0x00 0x7c5 0x00 0x212A10C /* mhint*/
|
||||
0x01 0x7cc 0x02 0x00000000 /* mhint2 bit33: When the CPU hangs, it is possible to obtain the CPU's internal context register through jtag */
|
||||
0x01 0x7cd 0x00 0x06 /* mhint3 bit1~2: Fix the stuttering issue on multi-core processors*/
|
||||
0x01 0x7ce 0x00 0x00002000 /* mhint4 bit13:enabled L2 cache free write to reduce L2 miss latency, bit7,28: enable cpu wirte-evict function o enable cpu to write clean data to LLC(L3) 0x10002080*/
|
||||
0x00 0x7c3 0x00 0xA2490008 /* mccr2 */
|
||||
0x00 0x7f3 0x00 0x01 /* msmpr(smpen) */
|
||||
0x00 0x7c1 0x00 0x10011FF /* mhcr */
|
||||
0x00 0x7c0 0x00 0x438000 /* mxstatus CONFIG_STD_SVPBMT */
|
||||
0x00 0x30a 0x40000000 0x00000000 /* menvcfg PBMTE=1 */
|
||||
0x00 0x00 /* Cluster1 init CSR Register */
|
||||
0x00 0x7c5 0x00 0x316A32C /* mhint*/
|
||||
0x00 0x7cc 0x1000 0x00000180 /* mhint2*/
|
||||
0x01 0x7cd 0x00 0x06 /* mhint3 bit1~2: Fix the stuttering issue on multi-core processors*/
|
||||
0x01 0x7ce 0x00 0x00002000 /* mhint4 bit13:enabled L2 cache free write to reduce L2 miss latency, bit7,28: enable cpu wirte-evict function o enable cpu to write clean data to LLC(L3) 0x10002080*/
|
||||
0x00 0x7c3 0x00 0xE2490009 /* mccr2 */
|
||||
0x00 0x7f3 0x00 0x01 /* msmpr */
|
||||
0x00 0x7c1 0x00 0x11FF /* mhcr */
|
||||
0x00 0x7c0 0x00 0x438000 /* mxstatus CONFIG_STD_SVPBMT */
|
||||
0x00 0x30a 0x40000000 0x00000000 /* menvcfg PBMTE=1 */
|
||||
>;
|
||||
};
|
||||
|
||||
clint0: clint@001c000000 {
|
||||
@@ -574,6 +553,7 @@
|
||||
#clock-cells = <1>;
|
||||
assigned-clocks = <&clk TOP_GPU_CORE_CLK_DIV>;
|
||||
assigned-clock-rates = <792000000>;
|
||||
power-domains = <&power_gpu>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -607,9 +587,10 @@
|
||||
|
||||
clk_vi: clock-controller@4 {
|
||||
compatible = "zhihe,a210-vi-clk";
|
||||
reg = <0x00 0x063a0200 0x0 0x200>;
|
||||
reg-names = "VI_CLK";
|
||||
reg = <0x00 0x063a0200 0x0 0x200>, <0x00 0x063a0050 0x0 0x4>;
|
||||
reg-names = "VI_CLK", "VI_MISC_CTRL";
|
||||
#clock-cells = <1>;
|
||||
power-domains = <&power_vi_wrapper>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -622,6 +603,7 @@
|
||||
<&clk TOP_VP_VENC_CCLK_DIV>, <&clk TOP_VP_G2D_CCLK_DIV>;
|
||||
assigned-clock-rates = <880000000>, <786432000>,
|
||||
<600000000>, <786432000>;
|
||||
power-domains = <&power_vp_wrapper>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -633,11 +615,14 @@
|
||||
assigned-clocks = <&clk_vo VO_DPUC_CLK_EN>, <&clk_vo VO_CH0_PIXCLK_EN>,
|
||||
<&clk_vo VO_CH1_PIXCLK_EN>, <&clk_vo VO_CH2_PIXCLK_EN>,
|
||||
<&clk_vo VO_DPU_ACLK_EN>, <&clk_vo VO_HDMI_PCLK_EN>,
|
||||
<&clk_vo VO_DECOMP0_CLK_EN>, <&clk_vo VO_DECOMP1_CLK_EN>;
|
||||
<&clk_vo VO_DECOMP0_CLK_EN>, <&clk_vo VO_DECOMP1_CLK_EN>,
|
||||
<&clk_vo VO_AUXDISP_ACLK_EN>, <&clk_vo VO_AUXDISP_PCLK_EN>;
|
||||
assigned-clock-rates = <880000000>, <594000000>,
|
||||
<594000000>, <594000000>,
|
||||
<880000000>, <165000000>,
|
||||
<220000000>, <220000000>;
|
||||
<220000000>, <220000000>,
|
||||
<880000000>, <165000000>;
|
||||
power-domains = <&power_vo>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -648,6 +633,7 @@
|
||||
#clock-cells = <1>;
|
||||
assigned-clocks = <&clk TOP_NPU_CCLK_DIV>, <&clk TOP_NPU_ACLK_DIV>;
|
||||
assigned-clock-rates = <880000000>, <880000000>;
|
||||
power-domains = <&power_npu_wrapper>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -676,9 +662,9 @@
|
||||
<&clk TOP_PERI_QSPI_SSI_CLK_MUX1>, <&clk TOP_PERI_PDM_MCLK_DIV>,
|
||||
<&clk TOP_PERI_TDM_SRC_CLK_MUX>, <&clk TOP_PAD_SENSOR_VCLK0_DIV>,
|
||||
<&clk TOP_PAD_SENSOR_VCLK1_DIV>, <&clk TOP_PERI_HIRES_CLK0_DIV>,
|
||||
<&clk TOP_PERI_HIRES_CLK1_DIV>, <&clk TOP_TEE_CLK_DIV>,
|
||||
<&clk TOP_PERI_EMMC_REF_CLK_DIV>, <&clk TOP_PERI_MST_ACLK0_DIV>,
|
||||
<&clk TOP_PERI_MST_CLK1_DIV>;
|
||||
<&clk TOP_PERI_HIRES_CLK1_DIV>, <&clk TOP_PERI_EMMC_REF_CLK_DIV>,
|
||||
<&clk TOP_PERI_MST_ACLK0_DIV>, <&clk TOP_PERI_MST_CLK1_DIV>,
|
||||
<&clk 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 */
|
||||
@@ -692,86 +678,85 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
power: p100-power-domain {
|
||||
compatible = "zhihe,p100-power-domain";
|
||||
reg = <0x00 0x30892000 0x0 0x1000>,<0x00 0x06BFB000 0x0 0x1000>,
|
||||
<0x00 0x06BF9000 0x0 0x1000>,<0x00 0x06BF8000 0x0 0x1000>,
|
||||
<0x00 0x06BF0000 0x0 0x1000>,<0x00 0x06BF3000 0x0 0x1000>,
|
||||
<0x00 0x06BF2000 0x0 0x1000>,<0x00 0x06BF6000 0x0 0x1000>,
|
||||
<0x00 0x06BF5000 0x0 0x1000>,<0x00 0x06E00600 0x0 0x200>,
|
||||
<0x00 0x06E00400 0x0 0x200>,<0x00 0x06E00000 0x0 0x200>,
|
||||
<0x00 0x07300600 0x0 0x200>,<0x00 0x07300200 0x0 0x200>,
|
||||
<0x00 0x07300000 0x0 0x200>,<0x00 0x07117200 0x0 0x200>,
|
||||
<0x00 0x07117000 0x0 0x200>,<0x00 0x0A006200 0x0 0x200>,
|
||||
<0x00 0x0A006000 0x0 0x200>,<0x00 0x0A006600 0x0 0x200>,
|
||||
<0x00 0x0A006400 0x0 0x200>,<0x00 0x0A006A00 0x0 0x200>,
|
||||
<0x00 0x0A006800 0x0 0x200>,<0x00 0x08004200 0x0 0x200>,
|
||||
<0x00 0x08004000 0x0 0x200>,<0x00 0x063F0000 0x0 0x200>,
|
||||
<0x00 0x063F9000 0x0 0x200>,<0x00 0x063F8000 0x0 0x200>,
|
||||
<0x00 0x063F6000 0x0 0x200>,<0x00 0x063F5000 0x0 0x200>,
|
||||
<0x00 0x067F1000 0x0 0x200>,<0x00 0x067F0000 0x0 0x200>;
|
||||
reg-names = "AON_PMIC_CTRL","VP_PCA","VP_WRAP_BPC","VP_WRAP_PCU",
|
||||
"VP_R2P","VP_VENC_BPC","VP_VENC_PCU","VP_VDEC_BPC",
|
||||
"VP_VDEC_PCU","GPU_PCA","GPU_BPC","GPU_PCU",
|
||||
"NPU_PCA","NPU_WRAP_BPC","NPU_WRAP_PCU","NPU_IP_BPC",
|
||||
"NPU_IP_PCU","PCIE0_BPC","PCIE0_PCU","PCIE1_BPC",
|
||||
"PCIE1_PCU","SATA_BPC","SATA_PCU","USB_BPC",
|
||||
"USB_PCU","VI_R2P","VI_WRAP_BPC","VI_WRAP_PCU",
|
||||
"VI_ISP_BPC","VI_ISP_PCU","VO_BPC","VO_PCU";
|
||||
power: a210-power-domain {
|
||||
compatible = "zhihe,a210-power-domain";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
power_top:power_top {
|
||||
#power-domain-cells = <0>;
|
||||
id = <A210_PD_TOP>;
|
||||
iopmps = <&device_pcie_mt_iopmp>,<&device_pcie_iommu_iopmp>, <&device_eip120i_iopmp>,
|
||||
<&device_eip120ii_iopmp>, <&device_eip120iii_iopmp>, <&device_tee_dmac_iopmp>;
|
||||
<&device_eip120ii_iopmp>, <&device_eip120iii_iopmp>, <&device_tee_dmac_iopmp>,
|
||||
<&device_aon_iopmp>, <&device_chip_dbg_iopmp> ,<&device_peri1_iommu_iopmp>,
|
||||
<&device_gmac_0_iopmp>, <&device_gmac_1_iopmp>, <&device_gmac_2_iopmp>,
|
||||
<&device_peri1_mt_iopmp>, <&device_dmac_ap_iopmp>, <&device_emmc_iopmp>,
|
||||
<&device_sd_iopmp>;
|
||||
};
|
||||
power_gpu:power_gpu {
|
||||
reg = <0x00 0x06E00600 0x0 0x200>, <0x00 0x06E00400 0x0 0x200>, <0x00 0x06E00000 0x0 0x200>;
|
||||
reg-names = "pca","bpc","pcu";
|
||||
#power-domain-cells = <0>;
|
||||
id = <A210_PD_GPU>;
|
||||
resets = <&rst GPU_PWR_WRAP_RGX_HOOD_RST>,
|
||||
<&rst GPU_PWR_WRAP_DFMU_RST>;
|
||||
iopmps = <&device_gpu_iopmp>, <&device_gpu_mt_iopmp>;
|
||||
};
|
||||
power_npu_wrapper:power_npu_wrapper {
|
||||
reg = <0x00 0x07300600 0x0 0x200>,<0x00 0x07300200 0x0 0x200>, <0x00 0x07300000 0x0 0x200>;
|
||||
reg-names = "pca","bpc","pcu";
|
||||
#power-domain-cells = <0>;
|
||||
id = <A210_PD_NPU_WRAPPER>;
|
||||
};
|
||||
power_npu_ip:power_npu_ip {
|
||||
reg = <0x00 0x07117200 0x0 0x200>, <0x00 0x07117000 0x0 0x200>;
|
||||
reg-names = "bpc","pcu";
|
||||
power-domains = <&power_npu_wrapper>;
|
||||
#power-domain-cells = <0>;
|
||||
clocks = <&clk_npu SW_NPU_IP_ACLK_EN>, <&clk_npu SW_NPU_IP_CCLK_EN>,
|
||||
<&clk_npu SW_NPU_IP_HCLK_EN>;
|
||||
id = <A210_PD_NPU_IP>;
|
||||
resets = <&rst NPU_ARST>, <&rst NPU_CRST>, <&rst NPU_HRST>;
|
||||
iopmps = <&device_npu_iopmp>, <&device_npu_iommu_iopmp>, <&device_npu_mt_iopmp>;
|
||||
};
|
||||
power_pcie0:power_pcie0 {
|
||||
reg = <0x00 0x0A006200 0x0 0x200>, <0x00 0x0A006000 0x0 0x200>;
|
||||
reg-names = "bpc","pcu";
|
||||
power-domains = <&power_top>;
|
||||
#power-domain-cells = <0>;
|
||||
clocks = <&clk_pcie E16PHY_PCLK_EN>, <&clk_pcie PCIE_DM_GEN3X4_AUX_CLK_EN>,
|
||||
id = <A210_PD_PCIE0>;
|
||||
clocks = <&clk_pcie PCIE_DM_GEN3X4_AUX_CLK_EN>,
|
||||
<&clk_pcie PCIE_DM_GEN3X4_SLV_ACLK_EN>, <&clk_pcie PCIE_DM_GEN3X4_MST_ACLK_EN>,
|
||||
<&clk_pcie PCIE_DM_GEN3X4_PCLK_EN>;
|
||||
resets = <&rst PCIE_E16PHY_PHY_RST>, <&rst PCIE_E16PHY_APBS_PRST>,
|
||||
<&rst PCIE_DM_GEN3X4_APBS_PRST>, <&rst PCIE_DM_GEN3X4_POWER_UP_RST>;
|
||||
resets = <&rst PCIE_DM_GEN3X4_APBS_PRST>, <&rst PCIE_DM_GEN3X4_POWER_UP_RST>;
|
||||
iopmps = <&device_pcie_0_iopmp>;
|
||||
};
|
||||
power_pcie1:power_pcie1 {
|
||||
reg = <0x00 0x0A006600 0x0 0x200>, <0x00 0x0A006400 0x0 0x200>;
|
||||
reg-names = "bpc","pcu";
|
||||
power-domains = <&power_top>;
|
||||
#power-domain-cells = <0>;
|
||||
clocks = <&clk_pcie E16PHY_PCLK_EN>, <&clk_pcie PCIE_RP_GEN3X1_AUX_CLK_EN>,
|
||||
id = <A210_PD_PCIE1>;
|
||||
clocks = <&clk_pcie PCIE_RP_GEN3X1_AUX_CLK_EN>,
|
||||
<&clk_pcie PCIE_RP_GEN3X1_SLV_ACLK_EN>, <&clk_pcie PCIE_RP_GEN3X1_MST_ACLK_EN>,
|
||||
<&clk_pcie PCIE_RP_GEN3X1_PCLK_EN>;
|
||||
resets = <&rst PCIE_E16PHY_PHY_RST>, <&rst PCIE_E16PHY_APBS_PRST>,
|
||||
<&rst PCIE_RP_GEN3X1_APBS_PRST>, <&rst PCIE_RP_GEN3X1_POWER_UP_RST>;
|
||||
resets = <&rst PCIE_RP_GEN3X1_APBS_PRST>, <&rst PCIE_RP_GEN3X1_POWER_UP_RST>;
|
||||
iopmps = <&device_pcie_1_iopmp>;
|
||||
};
|
||||
power_sata:power_sata {
|
||||
reg = <0x00 0x0A006A00 0x0 0x200>, <0x00 0x0A006800 0x0 0x200>;
|
||||
reg-names = "bpc","pcu";
|
||||
power-domains = <&power_top>;
|
||||
#power-domain-cells = <0>;
|
||||
clocks = <&clk_pcie E16PHY_PCLK_EN>, <&clk_pcie SATA_GEN3X2_ACLK_EN>, <&clk_pcie SATA_PMALIVE_CLK_EN>,
|
||||
id = <A210_PD_SATA>;
|
||||
clocks = <&clk_pcie SATA_GEN3X2_ACLK_EN>, <&clk_pcie SATA_PMALIVE_CLK_EN>,
|
||||
<&clk_pcie SATA_RXOOB0_CLK_EN>, <&clk_pcie SATA_RXOOB1_CLK_EN>;
|
||||
resets = <&rst PCIE_E16PHY_PHY_RST>, <&rst PCIE_E16PHY_APBS_PRST>, <&rst PCIE_SATA_ARESET>,
|
||||
resets = <&rst PCIE_SATA_ARESET>,
|
||||
<&rst PCIE_SATA_RST_PMALIVE>, <&rst PCIE_SATA_RST_ASIC0>, <&rst PCIE_SATA_RST_ASIC1>,
|
||||
<&rst PCIE_SATA_RST_RXOOB0>, <&rst PCIE_SATA_RST_RXOOB1>;
|
||||
iopmps = <&device_sata_0_iopmp>;
|
||||
};
|
||||
power_usb:power_usb {
|
||||
#power-domain-cells = <0>;
|
||||
id = <A210_PD_USB>;
|
||||
clocks = <&clk_usb DPTX_PCLK_EN>, <&clk_usb DPTX_GTC_CLK_EN>, <&clk_usb DPTX_AUX_CLK_EN>,
|
||||
<&clk_usb DPTX_IPI_CLK_EN>, <&clk_usb DPTX_I2S_CLK_EN>;
|
||||
resets = <&rst USB_DPTX_APBS_PRST>, <&rst USB_DPTX_VCC_RST>,
|
||||
@@ -781,21 +766,10 @@
|
||||
<&device_usb_mt_iopmp>;
|
||||
};
|
||||
power_vi_wrapper:power_vi_wrapper {
|
||||
reg = <0x00 0x063F9000 0x0 0x200>,<0x00 0x063F8000 0x0 0x200>;
|
||||
reg-names = "bpc","pcu";
|
||||
#power-domain-cells = <0>;
|
||||
clocks = <&clk_vi VI_MIPI0CSI0_PCLK_EN>, <&clk_vi VI_MIPI0CSI1_PCLK_EN>, <&clk_vi VI_MIPI0A_CFGCLK_EN>,
|
||||
<&clk_vi VI_MIPI0B_CFGCLK_EN>, <&clk_vi VI_MIPI0_CSI0_PIXCLK_EN>, <&clk_vi VI_MIPI0_CSI1_PIXCLK_EN>,
|
||||
<&clk_vi VI_MIPI1CSI0_PCLK_EN>, <&clk_vi VI_MIPI1CSI1_PCLK_EN>, <&clk_vi VI_MIPI1A_CFGCLK_EN>,
|
||||
<&clk_vi VI_MIPI1B_CFGCLK_EN>, <&clk_vi VI_MIPI1_CSI0_PIXCLK_EN>, <&clk_vi VI_MIPI1_CSI1_PIXCLK_EN>,
|
||||
<&clk_vi VI_VIPRE_PCLK_EN>, <&clk_vi VI_VIPRE_I0_PIXCLK_EN>, <&clk_vi VI_VIPRE_I1_PIXCLK_EN>,
|
||||
<&clk_vi VI_VIPRE_SCLK_EN>, <&clk_vi VI_VIPRE_ACLK_EN>,
|
||||
<&clk_vi VI_COMP_PCLK_EN>, <&clk_vi VI_COMP_ACLK_EN>,
|
||||
<&clk_vi VI_DECOUT_CLK_EN>, <&clk_vi VI_VSEOUT_CLK_EN>, <&clk_vi VI_COMP0_CLK_EN>,
|
||||
<&clk_vi VI_COMP1_CLK_EN>, <&clk_vi VI_DECOMP_CLK_EN>, <&clk_vi VI_DW200_HCLK_EN>,
|
||||
<&clk_vi VI_DW200_ACLK_EN>, <&clk_vi VI_DWE_CLK_EN>, <&clk_vi VI_VSE_CLK_EN>,
|
||||
<&clk_vi VI_DW_SCLK_EN>, <&clk_vi VI_PTW_ACLK_EN>, <&clk_vi VI_X2H0_CLK_EN>,
|
||||
<&clk_vi VI_X2H1_CLK_EN>, <&clk_vi VI_X2H2_CLK_EN>, <&clk_vi VI_MIPI0CSI0_FPCLK_EN>,
|
||||
<&clk_vi VI_MIPI0CSI1_FPCLK_EN>, <&clk_vi VI_MIPI1CSI0_FPCLK_EN>, <&clk_vi VI_MIPI1CSI1_FPCLK_EN>,
|
||||
<&clk_vi VI_REC_PCLK_EN>, <&clk_vi VI_REC_ACLK_EN>;
|
||||
id = <A210_PD_VI_WRAP>;
|
||||
resets = <&rst VI_MIPI0_CSI0_PRST>, <&rst VI_MIPI0_CSI1_PRST>, <&rst VI_MIPI0_FIFO_RST>,
|
||||
<&rst VI_MIPI1_CSI0_PRST>, <&rst VI_MIPI1_CSI1_PRST>, <&rst VI_MIPI1_FIFO_RST>,
|
||||
<&rst VI_VIPRE_PRST>, <&rst VI_VIPRE_I0_PIX_RST>, <&rst VI_VIPRE_I1_PIX_RST>,
|
||||
@@ -809,14 +783,19 @@
|
||||
<&device_vi_mt_iopmp>;
|
||||
};
|
||||
power_vi_isp:power_vi_isp {
|
||||
reg = <0x00 0x063F6000 0x0 0x200>,<0x00 0x063F5000 0x0 0x200>;
|
||||
reg-names = "bpc","pcu";
|
||||
power-domains = <&power_vi_wrapper>;
|
||||
#power-domain-cells = <0>;
|
||||
clocks = <&clk_vi VI_ISP_CLK_EN>, <&clk_vi VI_ISPOUT_CLK_EN>;
|
||||
id = <A210_PD_VI_ISP>;
|
||||
resets = <&rst VI_ISP_RST>;
|
||||
iopmps = <&device_isp_iopmp>;
|
||||
};
|
||||
power_vo:power_vo {
|
||||
reg = <0x00 0x067F1000 0x0 0x200>,<0x00 0x067F0000 0x0 0x200>;
|
||||
reg-names = "bpc","pcu";
|
||||
#power-domain-cells = <0>;
|
||||
id = <A210_PD_VO>;
|
||||
resets = <&rst VO_X2H0_RST>, <&rst VO_X2H1_RST>, <&rst VO_DPU_HRST>,
|
||||
<&rst VO_DPU_CRST>, <&rst VO_DPU_ARST>, <&rst VO_AUXDISP_PRST>,
|
||||
<&rst VO_AUXDISP_PIX_RST>, <&rst VO_AUXDISP_ARST>, <&rst VO_HDMI_PRST>,
|
||||
@@ -827,11 +806,10 @@
|
||||
<&device_vo_mt_iopmp>;
|
||||
};
|
||||
power_vp_wrapper:power_vp_wrapper {
|
||||
reg = <0x00 0x06BFB000 0x0 0x1000>, <0x00 0x06BF9000 0x0 0x1000>, <0x00 0x06BF8000 0x0 0x1000>;
|
||||
reg-names = "pca","bpc","pcu";
|
||||
#power-domain-cells = <0>;
|
||||
clocks = <&clk_vp VP_G2D_PCLK_EN>, <&clk_vp VP_G2D_CCLK_EN>, <&clk_vp VP_G2D_ACLK_EN>,
|
||||
<&clk_vp VP_COMP_PCLK_EN>, <&clk_vp VP_COMP_CCLK_EN>, <&clk_vp VP_COMP_ACLK_EN>,
|
||||
<&clk_vp VP_DECOMP_PCLK_EN>, <&clk_vp VP_DECOMP_CCLK_EN>, <&clk_vp VP_DECOMP_ACLK_EN>,
|
||||
<&clk_vp VP_COMP_EXTPCLK_EN>, <&clk_vp VP_DECOMP_EXTPCLK_EN>;
|
||||
id = <A210_PD_VP_WRAP>;
|
||||
resets = <&rst VP_G2D_PRST>, <&rst VP_G2D_CRST>,
|
||||
<&rst VP_G2D_ARST>, <&rst VP_COMP_PRST>,
|
||||
<&rst VP_COMP_CRST>, <&rst VP_COMP_ARST>,
|
||||
@@ -841,70 +819,27 @@
|
||||
iopmps = <&device_vp_iommu_iopmp>, <&device_g2d_iopmp>, <&device_vp_mt_iopmp>;
|
||||
};
|
||||
power_venc:power_venc {
|
||||
reg = <0x00 0x06BF3000 0x0 0x1000>, <0x00 0x06BF2000 0x0 0x1000>;
|
||||
reg-names = "bpc","pcu";
|
||||
power-domains = <&power_vp_wrapper>;
|
||||
#power-domain-cells = <0>;
|
||||
clocks = <&clk_vp VP_VENC_PCLK_EN>, <&clk_vp VP_VENC_CCLK_EN>, <&clk_vp VP_VENC_ACLK_EN>;
|
||||
id = <A210_PD_VENC>;
|
||||
resets = <&rst VP_VENC_PRST>, <&rst VP_VENC_CRST>, <&rst VP_VENC_ARST>;
|
||||
iopmps = <&device_venc_iopmp>;
|
||||
};
|
||||
power_vdec:power_vdec {
|
||||
reg = <0x00 0x06BF6000 0x0 0x1000>, <0x00 0x06BF5000 0x0 0x1000>;
|
||||
reg-names = "bpc","pcu";
|
||||
power-domains = <&power_vp_wrapper>;
|
||||
#power-domain-cells = <0>;
|
||||
clocks = <&clk_vp VP_VDEC_PCLK_EN>, <&clk_vp VP_VDEC_CCLK_EN>, <&clk_vp VP_VDEC_ACLK_EN>;
|
||||
id = <A210_PD_VDEC>;
|
||||
resets = <&rst VP_VDEC_PRST>, <&rst VP_VDEC_CRST>, <&rst VP_VDEC_ARST>;
|
||||
iopmps = <&device_vdec_iopmp>;
|
||||
};
|
||||
power_peri0:power_peri0 {
|
||||
power-domains = <&power_top>;
|
||||
#power-domain-cells = <0>;
|
||||
clocks = <&clk_peri PERI0_TIMER1_PCLK_EN>, <&clk_peri PERI0_TIMER1_CCLK_EN>;
|
||||
resets = <&rst PERI0_TIMER0_CRST>, <&rst PERI0_TIMER0_PRST>, <&rst PERI0_TIMER1_CRST>,
|
||||
<&rst PERI0_TIMER1_PRST>, <&rst PERI0_WDT0_PRST>, <&rst PERI0_MBOX0_PRST>,
|
||||
<&rst PERI0_MBOX1_PRST>;
|
||||
};
|
||||
power_peri1:power_peri1 {
|
||||
power-domains = <&power_top>;
|
||||
#power-domain-cells = <0>;
|
||||
clocks = <&clk_peri PERI1_GMAC0_ACLK_EN>, <&clk_peri PERI1_GMAC0_HCLK_EN>, <&clk_peri PERI1_GMAC1_ACLK_EN>,
|
||||
<&clk_peri PERI1_GMAC1_HCLK_EN>, <&clk_peri PERI1_I2C0_IC_CLK_EN>, <&clk_peri PERI1_I2C0_PCLK_EN>,
|
||||
<&clk_peri PERI1_I2C1_IC_CLK_EN>, <&clk_peri PERI1_I2C1_PCLK_EN>, <&clk_peri PERI1_I2C2_IC_CLK_EN>,
|
||||
<&clk_peri PERI1_I2C2_PCLK_EN>, <&clk_peri PERI1_I2S0_PCLK_EN>, <&clk_peri PERI1_I2S0_SRC_CLK_EN>,
|
||||
<&clk_peri PERI1_PWM0_CCLK_EN>, <&clk_peri PERI1_PWM0_PCLK_EN>, <&clk_peri PERI1_SPI0_PCLK_EN>,
|
||||
<&clk_peri PERI1_SPI0_SSI_CLK_EN>, <&clk_peri PERI1_UART1_PCLK_EN>, <&clk_peri PERI1_UART1_SCLK_EN>,
|
||||
<&clk_peri PERI1_UART2_PCLK_EN>, <&clk_peri PERI1_UART2_SCLK_EN>, <&clk_peri PERI1_UART3_PCLK_EN>,
|
||||
<&clk_peri PERI1_UART3_SCLK_EN>, <&clk_peri PERI1_X2H_GMAC0_ACLK_EN>, <&clk_peri PERI1_X2H_GMAC0_HCLK_EN>,
|
||||
<&clk_peri PERI1_X2H_GMAC1_ACLK_EN>, <&clk_peri PERI1_X2H_GMAC1_HCLK_EN>, <&clk_peri PERI1_CAN0_HIRES_CLK_EN>,
|
||||
<&clk_peri PERI1_CAN0_OSC_CLK_EN>, <&clk_peri PERI1_CAN0_PCLK_EN>, <&clk_peri PERI1_CAN1_HIRES_CLK_EN>,
|
||||
<&clk_peri PERI1_CAN1_OSC_CLK_EN>, <&clk_peri PERI1_CAN1_PCLK_EN>, <&clk_peri PERI1_PDM0_MCLK_EN>,
|
||||
<&clk_peri PERI1_PDM0_PCLK_EN>, <&clk_peri PERI1_TDM0_PCLK_EN>, <&clk_peri PERI1_TDM0_SCLK_EN>,
|
||||
<&clk_peri PERI1_X2H_GMAC2_ACLK_EN>, <&clk_peri PERI1_X2H_GMAC2_HCLK_EN>, <&clk_peri PERI1_GMAC2_ACLK_EN>,
|
||||
<&clk_peri PERI1_GMAC2_HCLK_EN>, <&clk_peri PERI1_ZGMAC_X2X_ACLK_EN>;
|
||||
resets = <&rst PERI1_GMAC0_ARST>, <&rst PERI1_GMAC0_HRST>, <&rst PERI1_GMAC1_ARST>,
|
||||
<&rst PERI1_GMAC1_HRST>, <&rst PERI1_GPIO0_DBRST>, <&rst PERI1_GPIO0_PRST>,
|
||||
<&rst PERI1_GPIO1_DBRST>, <&rst PERI1_GPIO1_PRST>, <&rst PERI1_I2C0_IC_RST>,
|
||||
<&rst PERI1_I2C0_PRST>, <&rst PERI1_I2C1_IC_RST>, <&rst PERI1_I2C1_PRST>,
|
||||
<&rst PERI1_I2C2_IC_RST>, <&rst PERI1_I2C2_PRST>, <&rst PERI1_I2S0_PRST>,
|
||||
<&rst PERI1_PWM0_CRST>,
|
||||
<&rst PERI1_PWM0_PRST>, <&rst PERI1_QSPI0_PRST>, <&rst PERI1_QSPI0_SSI_RST>,
|
||||
<&rst PERI1_SPI0_PRST>, <&rst PERI1_SPI0_SSI_RST>, <&rst PERI1_UART0_PRST>,
|
||||
<&rst PERI1_UART0_S_RST>, <&rst PERI1_UART1_PRST>, <&rst PERI1_UART1_S_RST>,
|
||||
<&rst PERI1_UART2_PRST>, <&rst PERI1_UART2_S_RST>, <&rst PERI1_UART3_PRST>,
|
||||
<&rst PERI1_UART3_S_RST>, <&rst PERI1_X2H_GMAC0_ARST>, <&rst PERI1_X2H_GMAC0_HRST>,
|
||||
<&rst PERI1_X2H_GMAC1_ARST>, <&rst PERI1_X2H_GMAC1_HRST>, <&rst PERI1_PDM0_MRST>,
|
||||
<&rst PERI1_PDM0_PRST>, <&rst PERI1_TDM0_RST>, <&rst PERI1_CAN0_IPG_PE_RST>,
|
||||
<&rst PERI1_CAN0_IPG_RST>, <&rst PERI1_CAN0_IPG_SOFT_RST>, <&rst PERI1_CAN0_IPG_TS_RST>,
|
||||
<&rst PERI1_CAN0_PRST>, <&rst PERI1_CAN1_IPG_PE_RST>, <&rst PERI1_CAN1_IPG_RST>,
|
||||
<&rst PERI1_CAN1_IPG_SOFT_RST>, <&rst PERI1_CAN1_IPG_TS_RST>, <&rst PERI1_CAN1_PRST>,
|
||||
<&rst PERI1_CHIP_DBG_ARST>, <&rst PERI1_CHIP_DBG_CRST>, <&rst PERI1_CHIP_DBG_PRST>,
|
||||
<&rst PERI1_GMAC_CRST>, <&rst PERI1_X2H_GMAC2_ARST>, <&rst PERI1_X2H_GMAC2_HRST>,
|
||||
<&rst PERI1_ZGMAC_X2X_ARST>;
|
||||
iopmps = <&device_aon_iopmp>, <&device_chip_dbg_iopmp> ,<&device_peri1_iommu_iopmp>,
|
||||
<&device_gmac_0_iopmp>, <&device_gmac_1_iopmp>, <&device_gmac_2_iopmp>,
|
||||
<&device_peri1_mt_iopmp>;
|
||||
};
|
||||
power_peri2:power_peri2 {
|
||||
power-domains = <&power_top>;
|
||||
#power-domain-cells = <0>;
|
||||
id = <A210_PD_PERI2>;
|
||||
clocks = <&clk_peri PERI2_CAN2_HIRES_CLK_EN>, <&clk_peri PERI2_CAN2_OSC_CLK_EN>, <&clk_peri PERI2_SPI1_SSI_CLK_EN>,
|
||||
<&clk_peri PERI2_UART5_SCLK_EN>, <&clk_peri PERI2_UART6_SCLK_EN>, <&clk_peri PERI2_CAN2_PCLK_EN>,
|
||||
<&clk_peri PERI2_SPI1_PCLK_EN>, <&clk_peri PERI2_UART5_PCLK_EN>, <&clk_peri PERI2_UART6_PCLK_EN>,
|
||||
@@ -935,23 +870,16 @@
|
||||
power_peri3:power_peri3 {
|
||||
power-domains = <&power_top>;
|
||||
#power-domain-cells = <0>;
|
||||
id = <A210_PD_PERI3>;
|
||||
clocks = <&clk_peri PERI3_DMAC_ACLK_EN>, <&clk_peri PERI3_DMAC_HCLK_EN>, <&clk_peri PERI3_SDIO_ACLK_EN>,
|
||||
<&clk_peri PERI3_SDIO_HCLK_EN>, <&clk_peri PERI3_SDIO_OSC_CLK_EN>, <&clk_peri PERI3_SDIO_X2X_ACLK_M_EN>,
|
||||
<&clk_peri PERI3_SDIO_X2X_ACLK_S_EN>, <&clk_peri PERI3_ADC_PCLK_EN>;
|
||||
resets = <&rst PERI3_DMAC_ARESET>, <&rst PERI3_DMAC_HRESET>, <&rst PERI3_ADC_PRST>;
|
||||
iopmps = <&device_dmac_ap_iopmp>, <&device_emmc_iopmp>, <&device_sd_iopmp>;
|
||||
};
|
||||
power_tee:power_tee {
|
||||
power-domains = <&power_top>;
|
||||
#power-domain-cells = <0>;
|
||||
resets = <&rst TEE_DMAC_ARST>, <&rst TEE_DMAC_HRST>, <&rst TEE_EIP120SI_ARST>,
|
||||
<&rst TEE_EIP120SI_HRST>, <&rst TEE_EIP120SII_ARST>, <&rst TEE_EIP120SII_HRST>,
|
||||
<&rst TEE_EIP120SIII_ARST>, <&rst TEE_EIP120SIII_HRST>, <&rst TEE_EIP150B_HRST>;
|
||||
};
|
||||
};
|
||||
|
||||
rst: reset-controller {
|
||||
compatible = "zhihe,p100-reset-controller";
|
||||
compatible = "zhihe,a210-reset-controller";
|
||||
reg = <0x00 0x06B20400 0x0 0x200>,
|
||||
<0x00 0x063A0400 0x0 0x200>,
|
||||
<0x00 0x07112200 0x0 0x10>,
|
||||
@@ -988,7 +916,7 @@
|
||||
reg = <0x00 0x18000000 0x0 0x04000000>;
|
||||
reg-names = "control";
|
||||
riscv,max-priority = <7>;
|
||||
riscv,ndev = <400>;
|
||||
riscv,ndev = <351>;
|
||||
};
|
||||
|
||||
clocks {
|
||||
|
||||
@@ -177,37 +177,34 @@
|
||||
};
|
||||
|
||||
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
|
||||
#mbox-cells = <2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
aon_die1_to_die1: aon_subsys_die1_to_die1 {
|
||||
compatible = "zhihe,a210-aon";
|
||||
mbox-names = "aon3";
|
||||
mboxes = <&mbox_920_die1 1 0>;
|
||||
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";
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
@@ -508,13 +508,13 @@
|
||||
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>;
|
||||
|
||||
@@ -578,7 +578,6 @@
|
||||
pull_up;
|
||||
bus-width = <8>;
|
||||
cap-mmc-highspeed;
|
||||
clk-delay-mmc-hs200 = <60>;
|
||||
};
|
||||
|
||||
&sdhci0 {
|
||||
@@ -622,7 +621,7 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&dhost_0 {
|
||||
&dsi_host0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@ 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_CPUFREQ_DT=y
|
||||
CONFIG_RISCV_XUANTIE_TH1520_CPUFREQ=y
|
||||
CONFIG_RISCV_ZHIHE_CPUFREQ=y
|
||||
CONFIG_KPROBES=y
|
||||
@@ -85,6 +84,7 @@ 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
|
||||
@@ -222,6 +222,7 @@ 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
|
||||
@@ -341,15 +342,18 @@ CONFIG_V4L_MEM2MEM_DRIVERS=y
|
||||
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=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=m
|
||||
CONFIG_BACKLIGHT_PWM=m
|
||||
CONFIG_BACKLIGHT_CLASS_DEVICE=y
|
||||
CONFIG_BACKLIGHT_PWM=y
|
||||
# CONFIG_VGA_CONSOLE is not set
|
||||
CONFIG_LOGO=y
|
||||
CONFIG_SOUND=m
|
||||
@@ -381,6 +385,7 @@ 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
|
||||
@@ -420,6 +425,7 @@ CONFIG_SW_SYNC=y
|
||||
CONFIG_UDMABUF=y
|
||||
CONFIG_DMABUF_SELFTESTS=m
|
||||
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
|
||||
@@ -432,13 +438,16 @@ 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_THEAD_TH1520_ADC=m
|
||||
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
|
||||
@@ -447,6 +456,7 @@ 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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -317,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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -89,8 +89,6 @@ static int arch_smp_setup_sbi_shmem(unsigned int cpu)
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("CPU %d: HW Breakpoint shared memory registered.\n", cpu);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#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>
|
||||
|
||||
@@ -37,6 +36,7 @@
|
||||
#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 */
|
||||
@@ -232,6 +232,7 @@ static struct zhihe_clk_reg regs_usb[] = {
|
||||
|
||||
static struct zhihe_clk_reg regs_vi[] = {
|
||||
REG(VI_CLK),
|
||||
REG(VI_MISC_CTRL),
|
||||
};
|
||||
|
||||
static struct zhihe_clk_reg regs_vp[] = {
|
||||
@@ -396,13 +397,13 @@ static struct zhihe_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),
|
||||
@@ -583,8 +584,8 @@ static struct zhihe_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),
|
||||
@@ -615,10 +616,10 @@ static struct zhihe_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),
|
||||
@@ -629,6 +630,17 @@ static struct zhihe_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 zhihe_clk_info info_vp[] = {
|
||||
@@ -970,13 +982,17 @@ static int a210_clocks_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
|
||||
struct clk_onecell_data *clk_data = devm_kzalloc(dev, sizeof(*clk_data), GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
if (!clk_data) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
clk_data->clks = devm_kcalloc(dev, CLK_END, sizeof(*clk_data->clks),
|
||||
GFP_KERNEL);
|
||||
if (!clk_data->clks)
|
||||
return -ENOMEM;
|
||||
if (!clk_data->clks) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
clk_data->clk_num = CLK_END;
|
||||
|
||||
for (int i = 0; i < CLK_END; i++)
|
||||
@@ -995,7 +1011,8 @@ static int a210_clocks_probe(struct platform_device *pdev)
|
||||
ret = zhihe_parse_regbase(pdev);
|
||||
if (ret) {
|
||||
dev_err(dev, "fail to parse reg base");
|
||||
return ret;
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
zhihe_register_clock(pdev);
|
||||
@@ -1007,11 +1024,11 @@ static int a210_clocks_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ static const struct clk_ops clk_zhihediv_ops = {
|
||||
.set_rate = clk_zhihediv_set_rate,
|
||||
};
|
||||
|
||||
static struct clk *zhihe_clk_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 zhihe_div_type div_type,
|
||||
u16 min, u16 max, bool closest)
|
||||
@@ -169,7 +169,7 @@ static struct clk *zhihe_clk_divider_internal(const char *name, const char *pare
|
||||
|
||||
hw = &zhihe_div->divider.hw;
|
||||
|
||||
ret = clk_hw_register(NULL, hw);
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
kfree(zhihe_div);
|
||||
return ERR_PTR(ret);
|
||||
@@ -178,21 +178,21 @@ static struct clk *zhihe_clk_divider_internal(const char *name, const char *pare
|
||||
return hw->clk;
|
||||
}
|
||||
|
||||
struct clk *zhihe_clk_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 zhihe_div_type div_type,
|
||||
u16 min, u16 max)
|
||||
{
|
||||
return zhihe_clk_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_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 zhihe_div_type div_type,
|
||||
u16 min, u16 max)
|
||||
{
|
||||
return zhihe_clk_divider_internal(name, parent, reg, shift, width,
|
||||
return zhihe_clk_divider_internal(dev, name, parent, reg, shift, width,
|
||||
sync, div_type, min, max, true);
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ static const struct clk_ops clk_zhihegate_share_ops = {
|
||||
.is_enabled = clk_zhihe_gate_share_is_enabled,
|
||||
};
|
||||
|
||||
struct clk *zhihe_clk_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)
|
||||
@@ -281,7 +281,7 @@ struct clk *zhihe_clk_register_gate_shared(const char *name, const char *parent,
|
||||
|
||||
hw = &zhihe_gate->gate.hw;
|
||||
|
||||
ret = clk_hw_register(NULL, hw);
|
||||
ret = clk_hw_register(dev, hw);
|
||||
if (ret) {
|
||||
kfree(zhihe_gate);
|
||||
return ERR_PTR(ret);
|
||||
@@ -446,35 +446,35 @@ void zhihe_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_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_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_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_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_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_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:
|
||||
const char * const *parents = zhihe_add_mux_suffix(pdev, i);
|
||||
priv->clk_data->clks[id] = zhihe_clk_mux_flags(name, base, bit_idx, width,
|
||||
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;
|
||||
|
||||
@@ -272,63 +272,63 @@ struct zhihe_clk_info {
|
||||
};
|
||||
};
|
||||
|
||||
static inline struct clk *zhihe_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_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 zhihe_clk_info_pll *pll_clk);
|
||||
|
||||
static inline struct clk *zhihe_clk_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,
|
||||
return clk_register_gate(dev, name, parent, CLK_SET_RATE_PARENT, reg,
|
||||
shift, 0, &zhihe_clk_lock);
|
||||
}
|
||||
|
||||
struct clk *zhihe_clk_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_divider(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);
|
||||
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_divider_closest(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);
|
||||
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);
|
||||
|
||||
|
||||
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_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_register_gate_shared(name, parent, CLK_SET_RATE_PARENT, reg,
|
||||
return zhihe_clk_register_gate_shared(dev, name, parent, CLK_SET_RATE_PARENT, reg,
|
||||
shift, &zhihe_clk_lock, share_count);
|
||||
}
|
||||
|
||||
static inline struct clk *zhihe_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_clk_lock);
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ void zhihe_clk_fake_pll_fixed_ops(void)
|
||||
return;
|
||||
}
|
||||
|
||||
struct clk *zhihe_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 zhihe_clk_info_pll *pll_clk)
|
||||
{
|
||||
@@ -397,7 +397,7 @@ struct clk *zhihe_pll(const char *name, const char *parent_name,
|
||||
}
|
||||
writel_relaxed(val, pll->base + pll->cfg0_reg_off + ZHIHE_PLL_CFG1);
|
||||
|
||||
clk = clk_register(NULL, &pll->hw);
|
||||
clk = clk_register(dev, &pll->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("failed to register pll %s %ld\n",
|
||||
name, PTR_ERR(clk));
|
||||
|
||||
@@ -373,24 +373,19 @@ static int zh_cpufreq_prepare_cluster(struct device *dev, int cpu)
|
||||
* the name of the regulator first.
|
||||
*/
|
||||
num_regulators = find_supply_name(dev, of_get_cpu_node(cpu, NULL), ®_names);
|
||||
if (num_regulators <= 0) {
|
||||
of_node_put(of_get_cpu_node(cpu, NULL));
|
||||
ret = dev_err_probe(dev, num_regulators,
|
||||
"failed to find regulators for cpu%d\n", cpu);
|
||||
goto free_cpumask;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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 .
|
||||
@@ -457,7 +452,7 @@ 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;
|
||||
|
||||
@@ -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),
|
||||
},
|
||||
{}
|
||||
|
||||
@@ -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
|
||||
@@ -237,6 +245,78 @@ static int get_aon_log_mem(struct device *dev, phys_addr_t *mem, size_t *mem_siz
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -3,35 +3,35 @@
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define ILI9881_PAGE(_page) DSI_DCS_WRITE(dsi, 0xff, 0x98, 0x81, _page)
|
||||
#define IILI9881_COMMAND(_cmd, _data...) DSI_DCS_WRITE(dsi, _cmd, _data)
|
||||
#define DCS_CMD_READ_ID1 0xDA
|
||||
#define ILI9881_PAGE(_page) DSI_DCS_WRITE(dsi, 0xff, 0x98, 0x81, _page)
|
||||
#define IILI9881_COMMAND(_cmd, _data...) DSI_DCS_WRITE(dsi, _cmd, _data)
|
||||
#define DCS_CMD_READ_ID1 0xDA
|
||||
|
||||
#define LT_8911_I2C_ADAPTER 3
|
||||
#define LT_8911_I2C_ADDR 0x45
|
||||
#define LT_8911_I2C_ADAPTER 3
|
||||
#define LT_8911_I2C_ADDR 0x45
|
||||
|
||||
static struct i2c_mipi_dsi g_lt8911_mipi_dsi;
|
||||
static bool g_is_std_suspend __nosavedata;
|
||||
|
||||
static const struct drm_display_mode lt8911_default_mode = {
|
||||
.clock = 152840,
|
||||
.hdisplay = 1920,
|
||||
.hsync_start = 1920 + 140,
|
||||
.hsync_end = 1920 + 140 + 160,
|
||||
.htotal = 1920 + 140 + 160 + 30,
|
||||
.clock = 152840,
|
||||
.hdisplay = 1920,
|
||||
.hsync_start = 1920 + 140,
|
||||
.hsync_end = 1920 + 140 + 160,
|
||||
.htotal = 1920 + 140 + 160 + 30,
|
||||
|
||||
.vdisplay = 1080,
|
||||
.vsync_start = 1080 + 18,
|
||||
.vsync_end = 1080 + 18 + 28,
|
||||
.vtotal = 1080 + 18 + 28 + 6,
|
||||
.vdisplay = 1080,
|
||||
.vsync_start = 1080 + 18,
|
||||
.vsync_end = 1080 + 18 + 28,
|
||||
.vtotal = 1080 + 18 + 28 + 6,
|
||||
|
||||
.width_mm = 110,
|
||||
.height_mm = 62,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
.width_mm = 110,
|
||||
.height_mm = 62,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
};
|
||||
|
||||
static struct panel_data lt8911_panel_data = {
|
||||
.display_mode = <8911_default_mode,
|
||||
.display_mode = (struct drm_display_mode *)<8911_default_mode,
|
||||
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO_BURST,
|
||||
.format = MIPI_DSI_FMT_RGB888,
|
||||
.lanes = 4,
|
||||
@@ -65,8 +65,7 @@ static int mipi_timing[] = {
|
||||
15284 /* pixel_clk / 10000 */
|
||||
};
|
||||
|
||||
static int lt8911_i2c_write(struct i2c_client *client,
|
||||
uint8_t reg, uint8_t val)
|
||||
static int lt8911_i2c_write(struct i2c_client *client, uint8_t reg, uint8_t val)
|
||||
{
|
||||
int ret = -1;
|
||||
int retries = 0;
|
||||
@@ -121,6 +120,9 @@ static int lt8911_i2c_read(struct i2c_client *client, uint8_t reg)
|
||||
|
||||
static void lt8911_reset(struct i2c_mipi_dsi *md)
|
||||
{
|
||||
if (!gpio_is_valid(md->reset_pin))
|
||||
return;
|
||||
|
||||
gpio_set_value(md->reset_pin, 0);
|
||||
msleep(md->rst_delay_ms);
|
||||
gpio_set_value(md->reset_pin, 1);
|
||||
@@ -503,24 +505,29 @@ static int panel_prepare(struct drm_panel *panel)
|
||||
|
||||
DBG_FUNC("lt8911exb enter\n");
|
||||
|
||||
if(g_is_std_suspend){
|
||||
if (md->prepared)
|
||||
return 0;
|
||||
|
||||
if (g_is_std_suspend) {
|
||||
DBG_FUNC("lt8911exb prepare under std mode, do not prepare\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(md->client == NULL){
|
||||
if (md->client == NULL) {
|
||||
DBG_FUNC("lt8911exb i2c client still not ready\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = regulator_enable(md->vspn3v3);
|
||||
if(ret){
|
||||
goto fail;
|
||||
if (md->vspn3v3) {
|
||||
ret = regulator_enable(md->vspn3v3);
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = regulator_enable(md->hsvcc);
|
||||
if(ret){
|
||||
goto fail;
|
||||
if (md->hsvcc) {
|
||||
ret = regulator_enable(md->hsvcc);
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
//msleep(200);
|
||||
@@ -536,12 +543,18 @@ static int panel_prepare(struct drm_panel *panel)
|
||||
lt8911_i2c_read(client, 0x01),
|
||||
lt8911_i2c_read(client, 0x02));
|
||||
|
||||
md->prepared = true;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
gpio_set_value(md->reset_pin, 0);
|
||||
regulator_disable(md->hsvcc);
|
||||
regulator_disable(md->vspn3v3);
|
||||
dev_err(&md->client->dev, "lt8911exb prepare failed: %d\n", ret);
|
||||
if (gpio_is_valid(md->reset_pin))
|
||||
gpio_set_value(md->reset_pin, 0);
|
||||
if (md->hsvcc)
|
||||
regulator_disable(md->hsvcc);
|
||||
if (md->vspn3v3)
|
||||
regulator_disable(md->vspn3v3);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -550,12 +563,19 @@ static int panel_unprepare(struct drm_panel *panel)
|
||||
int ret = 0;
|
||||
struct i2c_mipi_dsi *md = panel_to_md(panel);
|
||||
|
||||
if (!md->prepared)
|
||||
return 0;
|
||||
|
||||
DBG_FUNC("panel_unprepare enter\n");
|
||||
gpio_set_value(md->reset_pin, 0);
|
||||
if (gpio_is_valid(md->reset_pin))
|
||||
gpio_set_value(md->reset_pin, 0);
|
||||
|
||||
regulator_disable(md->hsvcc);
|
||||
regulator_disable(md->vspn3v3);
|
||||
if (md->hsvcc)
|
||||
regulator_disable(md->hsvcc);
|
||||
if (md->vspn3v3)
|
||||
regulator_disable(md->vspn3v3);
|
||||
|
||||
md->prepared = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -571,7 +591,8 @@ static int panel_enable(struct drm_panel *panel)
|
||||
return 0;
|
||||
}
|
||||
|
||||
gpio_set_value(md->backlight_pin, 1);
|
||||
if (gpio_is_valid(md->backlight_pin))
|
||||
gpio_set_value(md->backlight_pin, 1);
|
||||
|
||||
lt8911exb_cfg_set_mipi_timing(md);
|
||||
lt8911exb_cfg_set_edp_timing(md);
|
||||
@@ -590,7 +611,8 @@ static int panel_disable(struct drm_panel *panel)
|
||||
|
||||
DBG_FUNC("panel_disable enter\n");
|
||||
|
||||
gpio_set_value(md->backlight_pin, 0);
|
||||
if (gpio_is_valid(md->backlight_pin))
|
||||
gpio_set_value(md->backlight_pin, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -637,6 +659,11 @@ static int backlight_update(struct backlight_device *bd)
|
||||
struct i2c_mipi_dsi *md = bl_get_data(bd);
|
||||
int brightness = bd->props.brightness;
|
||||
|
||||
if (!md->prepared) {
|
||||
dev_dbg(&bd->dev, "lcd not ready yet for setting its backlight!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (bd->props.power != FB_BLANK_UNBLANK ||
|
||||
bd->props.fb_blank != FB_BLANK_UNBLANK ||
|
||||
(bd->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))) {
|
||||
@@ -656,9 +683,6 @@ static const struct backlight_ops backlight_ops = {
|
||||
static int lt8911_pm_notify(struct notifier_block *notify_block,
|
||||
unsigned long mode, void *unused)
|
||||
{
|
||||
struct i2c_mipi_dsi *ctx = container_of(
|
||||
notify_block, struct i2c_mipi_dsi, pm_notify);
|
||||
|
||||
DBG_FUNC("pm_notify: mode (%ld)\n", mode);
|
||||
|
||||
switch (mode) {
|
||||
@@ -706,7 +730,6 @@ static int backlight_init(struct i2c_mipi_dsi *md)
|
||||
|
||||
static int i2c_md_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct i2c_mipi_dsi *md = &g_lt8911_mipi_dsi;
|
||||
|
||||
DBG_FUNC("start");
|
||||
@@ -746,52 +769,64 @@ static int lt8911_parse_dt(struct i2c_mipi_dsi *md)
|
||||
struct mipi_dsi_device *dsi = md->dsi;
|
||||
struct device_node *np = dsi->dev.of_node;
|
||||
|
||||
md->hsvcc = devm_regulator_get(&dsi->dev, "hsvcc");
|
||||
if (IS_ERR(md->hsvcc))
|
||||
return dev_err_probe(&dsi->dev, PTR_ERR(md->hsvcc),
|
||||
"Failed to request hsvcc regulator\n");
|
||||
md->hsvcc = devm_regulator_get_optional(&dsi->dev, "hsvcc");
|
||||
if (IS_ERR(md->hsvcc)) {
|
||||
if (PTR_ERR(md->hsvcc) == -ENODEV) {
|
||||
DBG_FUNC("%s: hsvcc regulator not defined, continue without it\n", __func__);
|
||||
md->hsvcc = NULL;
|
||||
} else {
|
||||
return dev_err_probe(&dsi->dev, PTR_ERR(md->hsvcc),
|
||||
"Failed to request hsvcc regulator\n");
|
||||
}
|
||||
}
|
||||
|
||||
md->vspn3v3 = devm_regulator_get(&dsi->dev, "vspn3v3");
|
||||
if (IS_ERR(md->vspn3v3))
|
||||
return dev_err_probe(&dsi->dev, PTR_ERR(md->vspn3v3),
|
||||
"Failed to request vspn3v3 regulator\n");
|
||||
md->vspn3v3 = devm_regulator_get_optional(&dsi->dev, "vspn3v3");
|
||||
if (IS_ERR(md->vspn3v3)) {
|
||||
if (PTR_ERR(md->vspn3v3) == -ENODEV) {
|
||||
DBG_FUNC("%s: vspn3v3 regulator not defined, continue without it\n", __func__);
|
||||
md->vspn3v3 = NULL;
|
||||
} else {
|
||||
return dev_err_probe(&dsi->dev, PTR_ERR(md->vspn3v3),
|
||||
"Failed to request vspn3v3 regulator\n");
|
||||
}
|
||||
}
|
||||
|
||||
md->backlight_pin = of_get_named_gpio(np,
|
||||
"lt8911,backlight-gpio",
|
||||
0);
|
||||
if (!gpio_is_valid(md->backlight_pin)) {
|
||||
DBG_FUNC("%s: backlight-gpio is invalid\n", __func__);
|
||||
return -EINVAL;
|
||||
DBG_FUNC("%s: backlight-gpio is invalid, continue without it\n", __func__);
|
||||
md->backlight_pin = -EINVAL;
|
||||
} else {
|
||||
ret = devm_gpio_request_one(&dsi->dev,
|
||||
md->backlight_pin,
|
||||
GPIOF_DIR_OUT, NULL);
|
||||
if (ret) {
|
||||
DBG_FUNC("%s: failed to request backlight gpio\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
gpio_set_value(md->backlight_pin, 0);
|
||||
DBG_FUNC("%s: succeed to init backlight gpio\n", __func__);
|
||||
}
|
||||
|
||||
ret = devm_gpio_request_one(&dsi->dev,
|
||||
md->backlight_pin,
|
||||
GPIOF_DIR_OUT, NULL);
|
||||
if (ret) {
|
||||
DBG_FUNC("%s: failed to request backlight gpio\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
gpio_set_value(md->backlight_pin, 0);
|
||||
DBG_FUNC("%s: succeed to init backlight gpio\n", __func__);
|
||||
|
||||
md->irq_pin = of_get_named_gpio(np,
|
||||
"lt8911,irq-gpio", 0);
|
||||
if (!gpio_is_valid(md->irq_pin)) {
|
||||
DBG_FUNC("%s: irq-gpio is invalid\n", __func__);
|
||||
return -EINVAL;
|
||||
DBG_FUNC("%s: irq-gpio is invalid, continue without it\n", __func__);
|
||||
md->irq_pin = -EINVAL;
|
||||
} else {
|
||||
ret = devm_gpio_request_one(&dsi->dev,
|
||||
md->irq_pin,
|
||||
GPIOF_DIR_IN, NULL);
|
||||
if (ret) {
|
||||
DBG_FUNC("%s: failed to request irq gpio\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
DBG_FUNC("%s: succeed to init irq gpio\n", __func__);
|
||||
}
|
||||
|
||||
ret = devm_gpio_request_one(&dsi->dev,
|
||||
md->irq_pin,
|
||||
GPIOF_DIR_IN, NULL);
|
||||
if (ret) {
|
||||
DBG_FUNC("%s: failed to request irq gpio\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
DBG_FUNC("%s: succeed to init irq gpio\n", __func__);
|
||||
|
||||
ret = of_property_read_u32(np, "lt8911,rst-delay-ms",
|
||||
&md->rst_delay_ms);
|
||||
if (ret < 0) {
|
||||
@@ -803,21 +838,21 @@ static int lt8911_parse_dt(struct i2c_mipi_dsi *md)
|
||||
md->reset_pin = of_get_named_gpio(np,
|
||||
"lt8911,reset-gpio", 0);
|
||||
if (!gpio_is_valid(md->reset_pin)) {
|
||||
DBG_FUNC("%s: reset-gpio is invalid\n", __func__);
|
||||
return -EINVAL;
|
||||
DBG_FUNC("%s: reset-gpio is invalid, continue without it\n", __func__);
|
||||
md->reset_pin = -EINVAL;
|
||||
} else {
|
||||
ret = devm_gpio_request_one(&dsi->dev,
|
||||
md->reset_pin,
|
||||
GPIOF_DIR_OUT, NULL);
|
||||
if (ret) {
|
||||
DBG_FUNC("%s: failed to request reset gpio\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
gpio_set_value(md->reset_pin, 0);
|
||||
DBG_FUNC("%s: succeed to init reset gpio\n", __func__);
|
||||
}
|
||||
|
||||
ret = devm_gpio_request_one(&dsi->dev,
|
||||
md->reset_pin,
|
||||
GPIOF_DIR_OUT, NULL);
|
||||
if (ret) {
|
||||
DBG_FUNC("%s: failed to request reset gpio\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
gpio_set_value(md->reset_pin, 0);
|
||||
DBG_FUNC("%s: succeed to init reset gpio\n", __func__);
|
||||
|
||||
if (of_property_read_u32(np, "lt8911,edp-lane-cnt",
|
||||
&md->edp_lane_cnt)) {
|
||||
DBG_FUNC("%s: miss edp-lane-cnt property in dts\n",
|
||||
@@ -837,20 +872,17 @@ static int lt8911_parse_dt(struct i2c_mipi_dsi *md)
|
||||
* 6 bit: 262K colors
|
||||
* 8 bit: 16.7M colors
|
||||
*/
|
||||
if (of_property_read_u32(np, "lt8911,edp-depth",
|
||||
&md->edp_depth)) {
|
||||
if (of_property_read_u32(np, "lt8911,edp-depth", &md->edp_depth)) {
|
||||
DBG_FUNC("%s: miss edp-depth property in dts\n",
|
||||
__func__);
|
||||
md->edp_depth = 8;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id i2c_md_of_ids[] = {
|
||||
{
|
||||
.compatible = "i2c,lt8911",
|
||||
},
|
||||
{ .compatible = "i2c,lt8911", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, i2c_md_of_ids);
|
||||
@@ -868,8 +900,7 @@ static int edpi2c_resume(struct device *dev)
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops edpi2c_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(edpi2c_suspend,
|
||||
edpi2c_resume)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(edpi2c_suspend, edpi2c_resume)
|
||||
};
|
||||
|
||||
#define EDPI2C_PM_OPS &edpi2c_pm_ops
|
||||
@@ -891,8 +922,6 @@ static struct i2c_driver i2c_md_driver = {
|
||||
.shutdown = i2c_md_shutdown,
|
||||
};
|
||||
|
||||
module_i2c_driver(i2c_md_driver);
|
||||
|
||||
static int lt8911_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
int ret;
|
||||
@@ -900,21 +929,19 @@ static int lt8911_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
|
||||
ctx = &g_lt8911_mipi_dsi;
|
||||
|
||||
if(ctx == NULL){
|
||||
if (ctx == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if(ctx->client == NULL){
|
||||
if (ctx->client == NULL)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
g_is_std_suspend = false;
|
||||
|
||||
|
||||
ctx->dsi = dsi;
|
||||
ctx->desc = <8911_panel_data;
|
||||
ret = lt8911_parse_dt(ctx);
|
||||
ret = lt8911_parse_dt(ctx);
|
||||
if (ret) {
|
||||
DBG_FUNC("%s: failed to parse device tree\n", __func__);
|
||||
dev_err(&dsi->dev, "%s: failed to parse device tree\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -927,9 +954,7 @@ static int lt8911_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
//ctx->panel_data->set_dsi(ctx->dsi);
|
||||
drm_panel_init(&ctx->panel, &dsi->dev, &panel_funcs, DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ret = drm_panel_of_backlight(&ctx->panel);
|
||||
if (ret)
|
||||
return ret;
|
||||
drm_panel_of_backlight(&ctx->panel);
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
@@ -940,11 +965,10 @@ static int lt8911_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
|
||||
ret = register_pm_notifier(&ctx->pm_notify);
|
||||
if (ret)
|
||||
DBG_FUNC("register_pm_notifier failed: %d\n", ret);
|
||||
dev_err(&dsi->dev, "register_pm_notifier failed: %d\n", ret);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
drm_panel_remove(&ctx->panel);
|
||||
}
|
||||
|
||||
@@ -959,8 +983,6 @@ static void lt8911_dsi_remove(struct mipi_dsi_device *dsi)
|
||||
|
||||
mipi_dsi_detach(dsi);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void lt8911_dsi_shutdown(struct mipi_dsi_device *dsi)
|
||||
@@ -975,15 +997,47 @@ static const struct of_device_id lt8911_of_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, lt8911_of_match);
|
||||
|
||||
static struct mipi_dsi_driver lt8911_dsi_driver = {
|
||||
.probe = lt8911_dsi_probe,
|
||||
.remove = lt8911_dsi_remove,
|
||||
.shutdown = lt8911_dsi_shutdown,
|
||||
.driver = {
|
||||
.name = "panel-lt8911",
|
||||
.probe = lt8911_dsi_probe,
|
||||
.remove = lt8911_dsi_remove,
|
||||
.shutdown = lt8911_dsi_shutdown,
|
||||
.driver = {
|
||||
.name = "panel-lt8911",
|
||||
.of_match_table = lt8911_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(lt8911_dsi_driver);
|
||||
|
||||
static int __init lt8911_drivers_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
|
||||
ret = mipi_dsi_driver_register(<8911_dsi_driver);
|
||||
if (ret) {
|
||||
pr_err("lt8911: failed to add dsi driver: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = i2c_add_driver(&i2c_md_driver);
|
||||
if (ret) {
|
||||
pr_err("lt8911: failed to add i2c driver: %d\n", ret);
|
||||
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
|
||||
mipi_dsi_driver_unregister(<8911_dsi_driver);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit lt8911_drivers_exit(void)
|
||||
{
|
||||
i2c_del_driver(&i2c_md_driver);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
|
||||
mipi_dsi_driver_unregister(<8911_dsi_driver);
|
||||
}
|
||||
|
||||
module_init(lt8911_drivers_init);
|
||||
module_exit(lt8911_drivers_exit);
|
||||
|
||||
MODULE_DESCRIPTION("LT8911 Controller Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -82,6 +82,7 @@ struct i2c_mipi_dsi {
|
||||
|
||||
// backlight
|
||||
int brightness;
|
||||
bool prepared;
|
||||
};
|
||||
|
||||
#define panel_to_md(_p) container_of(_p, struct i2c_mipi_dsi, panel)
|
||||
|
||||
@@ -69,3 +69,13 @@ config VERISILICON_DEC
|
||||
This is a decompression function which reads compressed pixels from
|
||||
external memory (DDR or SRAM) under DPU's control, then it decompress
|
||||
comprssed pixels before returing these pixels to DPU.
|
||||
|
||||
config ZHIHE_AUXDISP
|
||||
bool "Auxiliary Display CRTC support"
|
||||
depends on DRM_VERISILICON
|
||||
help
|
||||
Enable support for auxiliary display CRTC device.
|
||||
This CRTC can connect to HDMI and DisplayPort outputs,
|
||||
providing additional display pipeline for external monitors.
|
||||
It supports up to 10-bit color depth and multiple color formats
|
||||
including RGB444, YCbCr444, and YCbCr422.
|
||||
|
||||
@@ -15,5 +15,6 @@ vs_drm-$(CONFIG_VERISILICON_DW_HDMI_TH1520) += dw_hdmi-th1520.o
|
||||
vs_drm-$(CONFIG_VERISILICON_DW_DP_P100) += dw_dp.o
|
||||
vs_drm-$(CONFIG_VERISILICON_MMU) += vs_dc_mmu.o
|
||||
vs_drm-$(CONFIG_VERISILICON_DEC) += vs_dc_dec.o
|
||||
vs_drm-$(CONFIG_ZHIHE_AUXDISP) += auxdisp_crtc.o
|
||||
|
||||
obj-$(CONFIG_DRM_VERISILICON) += vs_drm.o
|
||||
|
||||
1285
drivers/gpu/drm/verisilicon/auxdisp_crtc.c
Normal file
1285
drivers/gpu/drm/verisilicon/auxdisp_crtc.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/extcon-provider.h>
|
||||
#include <linux/extcon.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/of_device.h>
|
||||
@@ -47,9 +48,6 @@
|
||||
#include <sound/hdmi-codec.h>
|
||||
|
||||
#include <uapi/linux/videodev2.h>
|
||||
#define NO_PHY 1
|
||||
#define MAX_FREQ 540000
|
||||
#define LANES_NUM 4
|
||||
|
||||
#define RK_IF_PROP_COLOR_DEPTH "color_depth"
|
||||
#define RK_IF_PROP_COLOR_FORMAT "color_format"
|
||||
@@ -530,7 +528,7 @@ struct dw_dp_compliance {
|
||||
bool test_active;
|
||||
};
|
||||
|
||||
struct p100_drm_sub_dev {
|
||||
struct a210_drm_sub_dev {
|
||||
struct list_head list;
|
||||
struct drm_connector *connector;
|
||||
struct device_node *of_node;
|
||||
@@ -561,7 +559,9 @@ struct dw_dp {
|
||||
bool force_hpd;
|
||||
struct dw_dp_hotplug hotplug;
|
||||
struct mutex irq_lock;
|
||||
struct extcon_dev *extcon;
|
||||
struct extcon_dev *extcon; /* Extcon provider for audio/userspace */
|
||||
struct extcon_dev *phy_extcon; /* Extcon consumer from PHY */
|
||||
struct notifier_block phy_extcon_nb; /* Notifier for PHY extcon events */
|
||||
|
||||
struct drm_bridge bridge;
|
||||
struct drm_connector connector;
|
||||
@@ -589,7 +589,7 @@ struct dw_dp {
|
||||
struct drm_property *hdr_panel_metadata_property;
|
||||
struct drm_property_blob *hdr_panel_blob_ptr;
|
||||
|
||||
struct p100_drm_sub_dev sub_dev;
|
||||
struct a210_drm_sub_dev sub_dev;
|
||||
struct dw_dp_hdcp hdcp;
|
||||
int eotf_type;
|
||||
|
||||
@@ -696,15 +696,6 @@ static const struct dw_dp_output_format possible_output_fmts[] = {
|
||||
DPTX_VM_RGB_6BIT, 6, 18 },
|
||||
};
|
||||
|
||||
static unsigned long g_init_threshold = 0;
|
||||
static unsigned long g_freqs = 0;
|
||||
//void rockchip_drm_register_sub_dev(struct rockchip_drm_sub_dev *sub_dev)
|
||||
//{
|
||||
// mutex_lock(&rockchip_drm_sub_dev_lock);
|
||||
// list_add_tail(&sub_dev->list, &rockchip_drm_sub_dev_list);
|
||||
// mutex_unlock(&rockchip_drm_sub_dev_lock);
|
||||
//}
|
||||
|
||||
uint32_t rockchip_drm_of_find_possible_crtcs(struct drm_device *dev,
|
||||
struct device_node *port)
|
||||
{
|
||||
@@ -884,7 +875,7 @@ static int dw_dp_hdcp2_auth_check(struct dw_dp *dp)
|
||||
|
||||
dp->hdcp.hdcp2_encrypted = true;
|
||||
|
||||
dev_err(dp->dev, "HDCP2 authentication succeed\n");
|
||||
dev_dbg(dp->dev, "HDCP2 authentication succeed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -961,7 +952,7 @@ static int __maybe_unused dw_dp_hdcp_auth_check(struct dw_dp *dp)
|
||||
} else {
|
||||
regmap_write(dp->regmap, DPTX_HDCPAPIINTCLR, HDCP_ENGAGED);
|
||||
dp->hdcp.hdcp_encrypted = true;
|
||||
dev_err(dp->dev, "HDCP authentication succeed\n");
|
||||
dev_dbg(dp->dev, "HDCP authentication succeed\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1611,7 +1602,7 @@ static int dw_dp_connector_atomic_check(struct drm_connector *conn,
|
||||
dp_old_state = connector_to_dp_state(old_state);
|
||||
dp_new_state = connector_to_dp_state(new_state);
|
||||
|
||||
//dw_dp_hdcp_atomic_check(conn, state);
|
||||
dw_dp_hdcp_atomic_check(conn, state);
|
||||
|
||||
if (!new_state->crtc)
|
||||
return 0;
|
||||
@@ -1636,7 +1627,7 @@ static int dw_dp_connector_atomic_check(struct drm_connector *conn,
|
||||
if ((dp_old_state->bpc != dp_new_state->bpc) ||
|
||||
(dp_old_state->color_format != dp_new_state->color_format)) {
|
||||
if ((dp_old_state->bpc == 0) && (dp_new_state->bpc == 0))
|
||||
dev_err(dp->dev, "still auto set color mode\n");
|
||||
dev_dbg(dp->dev, "still auto set color mode\n");
|
||||
else
|
||||
crtc_state->mode_changed = true;
|
||||
}
|
||||
@@ -1758,18 +1749,12 @@ static int dw_dp_link_probe(struct dw_dp *dp)
|
||||
!!(dpcd & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
|
||||
|
||||
link->revision = link->dpcd[DP_DPCD_REV];
|
||||
#if NO_PHY
|
||||
//link->rate = MAX_FREQ;
|
||||
//link->lanes = LANES_NUM;
|
||||
link->rate = drm_dp_max_link_rate(link->dpcd);
|
||||
link->lanes = min_t(u8, LANES_NUM, drm_dp_max_lane_count(link->dpcd));
|
||||
#else
|
||||
link->rate = min_t(u32, min(dp->max_link_rate, dp->phy->attrs.max_link_rate * 100),
|
||||
drm_dp_max_link_rate(link->dpcd));
|
||||
|
||||
link->lanes = min_t(u8, phy_get_bus_width(dp->phy),
|
||||
drm_dp_max_lane_count(link->dpcd));
|
||||
#endif
|
||||
|
||||
link->caps.enhanced_framing = drm_dp_enhanced_frame_cap(link->dpcd);
|
||||
link->caps.tps3_supported = drm_dp_tps3_supported(link->dpcd);
|
||||
link->caps.tps4_supported = drm_dp_tps4_supported(link->dpcd);
|
||||
@@ -1786,9 +1771,7 @@ static int dw_dphy_set_voltage_pre_level(struct dw_dp *dp, int lane_id, int leve
|
||||
static int dw_dp_phy_update_vs_emph(struct dw_dp *dp, unsigned int rate, unsigned int lanes,
|
||||
struct drm_dp_link_train_set *train_set)
|
||||
{
|
||||
#if !NO_PHY
|
||||
union phy_configure_opts phy_cfg;
|
||||
#endif
|
||||
unsigned int *vs, *pe;
|
||||
u8 buf[4];
|
||||
int i, ret;
|
||||
@@ -1796,19 +1779,11 @@ static int dw_dp_phy_update_vs_emph(struct dw_dp *dp, unsigned int rate, unsigne
|
||||
vs = train_set->voltage_swing;
|
||||
pe = train_set->pre_emphasis;
|
||||
|
||||
// unsigned int phy_ctl_val;
|
||||
// regmap_read(dp->regmap, DPTX_PHYIF_CTRL, &phy_ctl_val);
|
||||
// regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_POWERDOWN,
|
||||
// FIELD_PREP(PHY_POWERDOWN, 0x3));
|
||||
//
|
||||
for (i = 0; i < lanes; i++) {
|
||||
dw_dphy_set_voltage_sw_level(dp, i, vs[i]);
|
||||
dw_dphy_set_voltage_pre_level(dp, i, pe[i]);
|
||||
}
|
||||
|
||||
// regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_POWERDOWN,
|
||||
// FIELD_PREP(PHY_POWERDOWN, 0x0));
|
||||
#if !NO_PHY
|
||||
for (i = 0; i < lanes; i++) {
|
||||
phy_cfg.dp.voltage[i] = vs[i];
|
||||
phy_cfg.dp.pre[i] = pe[i];
|
||||
@@ -1821,9 +1796,9 @@ static int dw_dp_phy_update_vs_emph(struct dw_dp *dp, unsigned int rate, unsigne
|
||||
phy_cfg.dp.set_voltages = true;
|
||||
|
||||
ret = phy_configure(dp->phy, &phy_cfg);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 0; i < lanes; i++) {
|
||||
buf[i] = (vs[i] << DP_TRAIN_VOLTAGE_SWING_SHIFT) |
|
||||
@@ -1866,7 +1841,7 @@ static int dw_dphy_set_rate(struct dw_dp *dp, unsigned int rate)
|
||||
val = 3;
|
||||
break;
|
||||
default:
|
||||
dev_err(dp->dev, "%s, %d, Error, dp unsopport rate %u\n", __func__, __LINE__, rate);
|
||||
dev_err(dp->dev, "Error, dp unsopport rate %u\n", rate);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1877,7 +1852,6 @@ static int dw_dphy_set_rate(struct dw_dp *dp, unsigned int rate)
|
||||
static int dw_dphy_set_voltage_sw_level(struct dw_dp *dp, int lane_id, int level)
|
||||
{
|
||||
if (level < 0 || level > 3) {
|
||||
dev_err(dp->dev, "%s, %d, Error, dp sw unsopport level %d\n", __func__, __LINE__, level);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1897,7 +1871,7 @@ static int dw_dphy_set_voltage_sw_level(struct dw_dp *dp, int lane_id, int level
|
||||
static int dw_dphy_set_voltage_pre_level(struct dw_dp *dp, int lane_id, int level)
|
||||
{
|
||||
if (level < 0 || level > 3) {
|
||||
dev_err(dp->dev, "%s, %d, Error, dp pre unsopport level%d\n", __func__, __LINE__, level);
|
||||
dev_err(dp->dev, "Error, dp pre unsopport level%d\n", level);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1918,26 +1892,11 @@ static int dw_dp_phy_configure(struct dw_dp *dp, unsigned int rate,
|
||||
unsigned int lanes, bool ssc)
|
||||
{
|
||||
/* Move PHY to P3 */
|
||||
unsigned int phy_ctl_val = 0, count = 10;
|
||||
regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_POWERDOWN,
|
||||
FIELD_PREP(PHY_POWERDOWN, 0x3));
|
||||
|
||||
|
||||
regmap_read(dp->regmap, DPTX_PHYIF_CTRL, &phy_ctl_val);
|
||||
while((PHY_BUSY & phy_ctl_val) && count) {
|
||||
regmap_read(dp->regmap, DPTX_PHYIF_CTRL, &phy_ctl_val);
|
||||
count--;
|
||||
dev_dbg(dp->dev, "dp wait phy busy 0x%lx\n", (PHY_BUSY & phy_ctl_val));
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (PHY_BUSY & phy_ctl_val) {
|
||||
dev_err(dp->dev, "%s, %d, Error, phy is busy\n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
dw_dphy_set_rate(dp, rate);
|
||||
|
||||
#if !NO_PHY
|
||||
union phy_configure_opts phy_cfg;
|
||||
int ret;
|
||||
phy_cfg.dp.lanes = lanes;
|
||||
@@ -1949,7 +1908,6 @@ static int dw_dp_phy_configure(struct dw_dp *dp, unsigned int rate,
|
||||
ret = phy_configure(dp->phy, &phy_cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_LANES,
|
||||
FIELD_PREP(PHY_LANES, lanes / 2));
|
||||
@@ -2066,7 +2024,6 @@ static int dw_dp_link_train_set_pattern(struct dw_dp *dp, u32 pattern)
|
||||
ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
|
||||
buf | pattern);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "%s, %d, dpct write error %d\n", __func__, __LINE__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2238,6 +2195,7 @@ static int dw_dp_link_downgrade(struct dw_dp *dp)
|
||||
{
|
||||
struct dw_dp_link *link = &dp->link;
|
||||
struct dw_dp_video *video = &dp->video;
|
||||
u32 rate = link->rate;
|
||||
|
||||
switch (link->rate) {
|
||||
case 162000:
|
||||
@@ -2253,9 +2211,11 @@ static int dw_dp_link_downgrade(struct dw_dp *dp)
|
||||
break;
|
||||
}
|
||||
|
||||
/*If the downgrade fails, retry using the previous rate. */
|
||||
if (!dw_dp_bandwidth_ok(dp, &video->mode, video->bpp, link->lanes,
|
||||
link->rate))
|
||||
return -E2BIG;
|
||||
link->rate)) {
|
||||
link->rate = rate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2267,6 +2227,10 @@ static int dw_dp_link_train_full(struct dw_dp *dp)
|
||||
|
||||
retry:
|
||||
dw_dp_link_train_init(&link->train);
|
||||
|
||||
dev_dbg(dp->dev, "full-training link: %u lane%s at %u MHz\n",
|
||||
link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
|
||||
|
||||
ret = dw_dp_link_configure(dp);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
|
||||
@@ -2280,11 +2244,10 @@ retry:
|
||||
}
|
||||
|
||||
if (!link->train.clock_recovered) {
|
||||
dev_err(dp->dev, "clock recovery failed, downgrading link\n");
|
||||
dev_info(dp->dev, "clock recovery failed, downgrading link, retry\n");
|
||||
|
||||
ret = dw_dp_link_downgrade(dp);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "downgrade failed, goto out\n");
|
||||
goto out;
|
||||
} else
|
||||
goto retry;
|
||||
@@ -2319,6 +2282,9 @@ static int dw_dp_link_train_fast(struct dw_dp *dp)
|
||||
|
||||
dw_dp_link_train_init(&link->train);
|
||||
|
||||
dev_dbg(dp->dev, "fast-training link: %u lane%s at %u MHz\n",
|
||||
link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100);
|
||||
|
||||
ret = dw_dp_link_configure(dp);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "failed to configure DP link: %d\n", ret);
|
||||
@@ -2665,12 +2631,11 @@ static int dw_dp_video_enable(struct dw_dp *dp)
|
||||
u8 color_format = video->color_format;
|
||||
u8 bpc = video->bpc;
|
||||
u8 pixel_mode = video->pixel_mode;
|
||||
u8 bpp = video->bpp, vic;
|
||||
u32 init_threshold;
|
||||
u8 bpp = video->bpp, init_threshold, vic;
|
||||
u32 hactive, hblank, h_sync_width, h_front_porch;
|
||||
u32 vactive, vblank, v_sync_width, v_front_porch;
|
||||
u32 vstart = mode->vsync_end- mode->vdisplay;
|
||||
u32 hstart = mode->hsync_end- mode->hdisplay;
|
||||
u32 vstart = mode->vtotal - mode->vsync_start;
|
||||
u32 hstart = mode->htotal - mode->hsync_start;
|
||||
u32 peak_stream_bandwidth, link_bandwidth;
|
||||
u32 average_bytes_per_tu, average_bytes_per_tu_frac;
|
||||
u32 ts, hblank_interval;
|
||||
@@ -2697,7 +2662,6 @@ static int dw_dp_video_enable(struct dw_dp *dp)
|
||||
regmap_write(dp->regmap, DPTX_VINPUT_POLARITY_CTRL, value);
|
||||
|
||||
/* Configure DPTX_VIDEO_CONFIG1 register */
|
||||
|
||||
hactive = mode->hdisplay;
|
||||
hblank = mode->htotal - mode->hdisplay;
|
||||
value = FIELD_PREP(HACTIVE, hactive) | FIELD_PREP(HBLANK, hblank);
|
||||
@@ -2717,7 +2681,6 @@ static int dw_dp_video_enable(struct dw_dp *dp)
|
||||
/* Configure DPTX_VIDEO_CONFIG2 register */
|
||||
vblank = mode->vtotal - mode->vdisplay;
|
||||
vactive = mode->vdisplay;
|
||||
|
||||
regmap_write(dp->regmap, DPTX_VIDEO_CONFIG2,
|
||||
FIELD_PREP(VBLANK, vblank) | FIELD_PREP(VACTIVE, vactive));
|
||||
|
||||
@@ -2734,16 +2697,15 @@ static int dw_dp_video_enable(struct dw_dp *dp)
|
||||
regmap_write(dp->regmap, DPTX_VIDEO_CONFIG4,
|
||||
FIELD_PREP(V_SYNC_WIDTH, v_sync_width) |
|
||||
FIELD_PREP(V_FRONT_PORCH, v_front_porch));
|
||||
|
||||
/* Configure DPTX_VIDEO_CONFIG5 register */
|
||||
peak_stream_bandwidth = mode->clock * bpp / 8;
|
||||
link_bandwidth = (link->rate / 1000) * link->lanes;
|
||||
ts = peak_stream_bandwidth * 64 / link_bandwidth;
|
||||
average_bytes_per_tu = ts / 1000;
|
||||
average_bytes_per_tu_frac = ts - average_bytes_per_tu * 1000;
|
||||
average_bytes_per_tu_frac = average_bytes_per_tu_frac / 100;
|
||||
|
||||
average_bytes_per_tu_frac = ts / 100 - average_bytes_per_tu * 10;
|
||||
if (pixel_mode == DPTX_MP_SINGLE_PIXEL) {
|
||||
if (average_bytes_per_tu < 16)
|
||||
if (average_bytes_per_tu < 6)
|
||||
init_threshold = 32;
|
||||
else if (hblank <= 80 && color_format != DRM_COLOR_FORMAT_YCBCR420)
|
||||
init_threshold = 12;
|
||||
@@ -2751,13 +2713,64 @@ static int dw_dp_video_enable(struct dw_dp *dp)
|
||||
init_threshold = 3;
|
||||
else
|
||||
init_threshold = 16;
|
||||
}
|
||||
} else {
|
||||
u32 t1 = 0, t2 = 0, t3 = 0;
|
||||
|
||||
if (g_init_threshold) {
|
||||
init_threshold = g_init_threshold;
|
||||
switch (bpc) {
|
||||
case 6:
|
||||
t1 = (4 * 1000 / 9) * link->lanes;
|
||||
break;
|
||||
case 8:
|
||||
if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
|
||||
t1 = (1000 / 2) * link->lanes;
|
||||
} else {
|
||||
if (pixel_mode == DPTX_MP_DUAL_PIXEL)
|
||||
t1 = (1000 / 3) * link->lanes;
|
||||
else
|
||||
t1 = (3000 / 16) * link->lanes;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (color_format == DRM_COLOR_FORMAT_YCBCR422)
|
||||
t1 = (2000 / 5) * link->lanes;
|
||||
else
|
||||
t1 = (4000 / 15) * link->lanes;
|
||||
break;
|
||||
case 12:
|
||||
if (color_format == DRM_COLOR_FORMAT_YCBCR422) {
|
||||
if (pixel_mode == DPTX_MP_DUAL_PIXEL)
|
||||
t1 = (1000 / 6) * link->lanes;
|
||||
else
|
||||
t1 = (1000 / 3) * link->lanes;
|
||||
} else {
|
||||
t1 = (2000 / 9) * link->lanes;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
if (color_format != DRM_COLOR_FORMAT_YCBCR422 &&
|
||||
pixel_mode == DPTX_MP_DUAL_PIXEL)
|
||||
t1 = (1000 / 6) * link->lanes;
|
||||
else
|
||||
t1 = (1000 / 4) * link->lanes;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (color_format == DRM_COLOR_FORMAT_YCBCR420)
|
||||
t2 = (link->rate / 4) * 1000 / (mode->clock / 2);
|
||||
else
|
||||
t2 = (link->rate / 4) * 1000 / mode->clock;
|
||||
|
||||
if (average_bytes_per_tu_frac)
|
||||
t3 = average_bytes_per_tu + 1;
|
||||
else
|
||||
t3 = average_bytes_per_tu;
|
||||
init_threshold = t1 * t2 * t3 / (1000 * 1000);
|
||||
if (init_threshold <= 16 || average_bytes_per_tu < 10)
|
||||
init_threshold = 40;
|
||||
}
|
||||
|
||||
average_bytes_per_tu_frac &= 0xf;
|
||||
regmap_write(dp->regmap, DPTX_VIDEO_CONFIG5,
|
||||
FIELD_PREP(INIT_THRESHOLD_HI, init_threshold >> 6) |
|
||||
FIELD_PREP(AVERAGE_BYTES_PER_TU_FRAC, average_bytes_per_tu_frac) |
|
||||
@@ -2767,6 +2780,7 @@ static int dw_dp_video_enable(struct dw_dp *dp)
|
||||
/* Configure DPTX_VIDEO_HBLANK_INTERVAL register */
|
||||
hblank_interval = hblank * (link->rate / 4) / mode->clock;
|
||||
regmap_write(dp->regmap, DPTX_VIDEO_HBLANK_INTERVAL,
|
||||
FIELD_PREP(HBLANK_INTERVAL_EN, 1) |
|
||||
FIELD_PREP(HBLANK_INTERVAL, hblank_interval));
|
||||
|
||||
/* Video stream enable */
|
||||
@@ -2808,6 +2822,63 @@ static irqreturn_t dw_dp_hpd_irq_handler(int irq, void *arg)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
┌────────────────────┬───────────┬─────────┬────────────────┐
|
||||
│ Scenario │ HPD_STATE │ IRQ_HPD │ DP Host Action │
|
||||
├────────────────────┼───────────┼─────────┼────────────────┤
|
||||
│ Display insertion │ 0→1 │ 0 │ Long HPD │
|
||||
├────────────────────┼───────────┼─────────┼────────────────┤
|
||||
│ Display removal │ 1→0 │ 0 │ Long HPD │
|
||||
├────────────────────┼───────────┼─────────┼────────────────┤
|
||||
│ Link status change │ 1 │ 1 │ Short HPD │
|
||||
├────────────────────┼───────────┼─────────┼────────────────┤
|
||||
│ EDID update │ 1 │ 1 │ Short HPD │
|
||||
├────────────────────┼───────────┼─────────┼────────────────┤
|
||||
│ Resolution switch │ 1 │ 1 │ Short HPD │
|
||||
└────────────────────┴───────────┴─────────┴────────────────┘
|
||||
*/
|
||||
static int dw_dp_phy_extcon_notifier(struct notifier_block *nb,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct dw_dp *dp = container_of(nb, struct dw_dp, phy_extcon_nb);
|
||||
bool hpd_state = !!event;
|
||||
bool current_hpd;
|
||||
|
||||
dev_dbg(dp->dev, "PHY extcon HPD notification: %s (event=%lu)\n",
|
||||
hpd_state ? "connected" : "disconnected", event);
|
||||
|
||||
mutex_lock(&dp->irq_lock);
|
||||
|
||||
/* Get current HPD status */
|
||||
current_hpd = dp->hotplug.status;
|
||||
|
||||
/*
|
||||
* Distinguish between long HPD and short HPD:
|
||||
* - If state changes → long HPD (plug/unplug)
|
||||
* - If state unchanged and state=true → short HPD (IRQ pulse)
|
||||
*/
|
||||
if (current_hpd == hpd_state && hpd_state) {
|
||||
/* State unchanged → short HPD */
|
||||
dp->hotplug.long_hpd = false;
|
||||
dev_dbg(dp->dev, "Short HPD detected (IRQ pulse)\n");
|
||||
if (!current_hpd)
|
||||
return NOTIFY_OK;
|
||||
} else {
|
||||
/* State changed → long HPD */
|
||||
dp->hotplug.long_hpd = true;
|
||||
dp->hotplug.status = hpd_state;
|
||||
dev_dbg(dp->dev, "Long HPD detected: %s\n",
|
||||
hpd_state ? "plug" : "unplug");
|
||||
}
|
||||
|
||||
mutex_unlock(&dp->irq_lock);
|
||||
|
||||
/* Schedule HPD work queue */
|
||||
schedule_work(&dp->hpd_work);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static void dw_dp_hpd_init(struct dw_dp *dp)
|
||||
{
|
||||
dp->hotplug.status = dw_dp_detect(dp);
|
||||
@@ -2842,13 +2913,6 @@ static void dw_dp_init(struct dw_dp *dp)
|
||||
regmap_update_bits(dp->regmap, DPTX_CCTL, DEFAULT_FAST_LINK_TRAIN_EN,
|
||||
FIELD_PREP(DEFAULT_FAST_LINK_TRAIN_EN, 0));
|
||||
|
||||
#if 0
|
||||
regmap_update_bits(dp->regmap, DPTX_GENERAL_INTERRUPT_ENABLE,
|
||||
VIDEO_FIFO_OVERFLOW_STREAM0, FIELD_PREP(VIDEO_FIFO_OVERFLOW_STREAM0, 1));
|
||||
|
||||
regmap_update_bits(dp->regmap, DPTX_GENERAL_INTERRUPT_ENABLE,
|
||||
VIDEO_FIFO_UNDERFLOW_STREAM0, FIELD_PREP(VIDEO_FIFO_UNDERFLOW_STREAM0, 1));
|
||||
#endif
|
||||
dw_dp_hpd_init(dp);
|
||||
dw_dp_aux_init(dp);
|
||||
}
|
||||
@@ -2992,7 +3056,6 @@ static ssize_t dw_dp_aux_transfer(struct drm_dp_aux *aux,
|
||||
case DP_AUX_I2C_READ:
|
||||
break;
|
||||
default: {
|
||||
dev_err(dp->dev, "%s, %d, aux error\n", __func__, __LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -3115,13 +3178,9 @@ static void _dw_dp_loader_protect(struct dw_dp *dp, bool on)
|
||||
link->rate = 162000;
|
||||
break;
|
||||
}
|
||||
#if !NO_PHY
|
||||
phy_power_on(dp->phy);
|
||||
#endif
|
||||
} else {
|
||||
#if !NO_PHY
|
||||
phy_power_off(dp->phy);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3351,9 +3410,7 @@ static void dw_dp_link_disable(struct dw_dp *dp)
|
||||
|
||||
dw_dp_phy_xmit_enable(dp, 0);
|
||||
|
||||
#if !NO_PHY
|
||||
phy_power_off(dp->phy);
|
||||
#endif
|
||||
|
||||
link->train.clock_recovered = false;
|
||||
link->train.channel_equalized = false;
|
||||
@@ -3363,21 +3420,19 @@ static int dw_dp_link_enable(struct dw_dp *dp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if !NO_PHY
|
||||
ret = phy_power_on(dp->phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
ret = dw_dp_link_power_up(dp);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "dw_dp_link_power_up failed: %d\n", ret);
|
||||
dev_info(dp->dev, "dw_dp_link_power_up failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dw_dp_link_train(dp);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "link training failed: %d\n", ret);
|
||||
dev_info(dp->dev, "link training failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3410,7 +3465,7 @@ static void dw_dp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
|
||||
ret = dw_dp_link_enable(dp);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "failed to enable link: %d\n", ret);
|
||||
dev_info(dp->dev, "failed to enable link: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3474,11 +3529,9 @@ static bool dw_dp_detect_dpcd(struct dw_dp *dp)
|
||||
u8 value;
|
||||
int ret;
|
||||
|
||||
#if !NO_PHY
|
||||
ret = phy_power_on(dp->phy);
|
||||
if (ret)
|
||||
goto fail_power_on;
|
||||
#endif
|
||||
ret = drm_dp_dpcd_readb(&dp->aux, DP_DPCD_REV, &value);
|
||||
if (ret < 0) {
|
||||
goto fail_probe;
|
||||
@@ -3490,17 +3543,13 @@ static bool dw_dp_detect_dpcd(struct dw_dp *dp)
|
||||
goto fail_probe;
|
||||
}
|
||||
|
||||
#if !NO_PHY
|
||||
phy_power_off(dp->phy);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
||||
fail_probe:
|
||||
#if !NO_PHY
|
||||
phy_power_off(dp->phy);
|
||||
fail_power_on:
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3541,17 +3590,13 @@ static struct edid *dw_dp_bridge_get_edid(struct drm_bridge *bridge,
|
||||
{
|
||||
struct dw_dp *dp = bridge_to_dp(bridge);
|
||||
struct edid *edid;
|
||||
#if !NO_PHY
|
||||
int ret;
|
||||
|
||||
ret = phy_power_on(dp->phy);
|
||||
if (ret)
|
||||
return NULL;
|
||||
#endif
|
||||
edid = drm_get_edid(connector, &dp->aux.ddc);
|
||||
#if !NO_PHY
|
||||
phy_power_off(dp->phy);
|
||||
#endif
|
||||
|
||||
return edid;
|
||||
}
|
||||
@@ -3973,18 +4018,6 @@ static irqreturn_t dw_dp_irq_handler(int irq, void *data)
|
||||
if (!value)
|
||||
return IRQ_NONE;
|
||||
|
||||
#if 0
|
||||
if (value & VIDEO_FIFO_OVERFLOW_STREAM0) {
|
||||
regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT,
|
||||
VIDEO_FIFO_OVERFLOW_STREAM0);
|
||||
}
|
||||
|
||||
if (value & VIDEO_FIFO_UNDERFLOW_STREAM0) {
|
||||
regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT,
|
||||
VIDEO_FIFO_UNDERFLOW_STREAM0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (value & HPD_EVENT)
|
||||
dw_dp_handle_hpd_event(dp);
|
||||
|
||||
@@ -3997,8 +4030,6 @@ static irqreturn_t dw_dp_irq_handler(int irq, void *data)
|
||||
if (value & HDCP_EVENT)
|
||||
dw_dp_handle_hdcp_event(dp);
|
||||
|
||||
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -4356,87 +4387,13 @@ static int dw_dp_parse_dt(struct dw_dp *dp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t dpinit_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
char kbuf[64];
|
||||
char *p, *token;
|
||||
unsigned long val;
|
||||
int ret;
|
||||
struct dw_dp *dp = dev_get_drvdata(dev);
|
||||
struct dw_dp_link *link = &dp->link;
|
||||
|
||||
|
||||
/* 简单的长度检查,避免溢出 */
|
||||
if (count == 0)
|
||||
return -EINVAL;
|
||||
if (count >= sizeof(kbuf))
|
||||
return -EINVAL;
|
||||
|
||||
/* buf 是 sysfs 传入的 kernel 空间缓存(已可读),复制并 null 终止以便分词 */
|
||||
memcpy(kbuf, buf, count);
|
||||
kbuf[count] = '\0';
|
||||
|
||||
p = kbuf;
|
||||
|
||||
/* 以空白字符或逗号分隔(支持 "100 4"、"100,4"、"0x64 0x4" 等格式) */
|
||||
token = strsep(&p, " \t\n,");
|
||||
if (!token || *token == '\0') {
|
||||
dev_err(dev, "%s: missing threshold parameter\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = kstrtoul(token, 0, &val); /* base=0 支持 0x 前缀 */
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: invalid threshold '%s'\n", __func__, token);
|
||||
return ret;
|
||||
}
|
||||
g_init_threshold = (unsigned int)val;
|
||||
|
||||
/* 第二个参数可选:lanes */
|
||||
token = strsep(&p, " \t\n,");
|
||||
if (token && *token != '\0') {
|
||||
ret = kstrtoul(token, 0, &val);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: invalid lanes '%s'\n", __func__, token);
|
||||
return ret;
|
||||
}
|
||||
g_freqs = (unsigned int)val;
|
||||
link->rate = g_freqs;
|
||||
} else {
|
||||
/* 如果未提供 lanes,则保持原值(或你可以改为返回错误以强制要求两个参数) */
|
||||
dev_info(dev, "%s: freq not provided, keep %u\n", __func__, link->rate);
|
||||
}
|
||||
|
||||
|
||||
dev_err(dev, "%s, %d, g_init_threshold = %lu, g_freq = %u\n",
|
||||
__func__, __LINE__, g_init_threshold, link->rate);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_WO(dpinit);
|
||||
|
||||
int dw_dp_create_capabilities_sysfs(struct platform_device *pdev)
|
||||
{
|
||||
device_create_file(&pdev->dev, &dev_attr_dpinit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dw_dp_remove_capabilities_sysfs(struct platform_device *pdev)
|
||||
{
|
||||
device_remove_file(&pdev->dev, &dev_attr_dpinit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_dp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dw_dp *dp;
|
||||
void __iomem *base;
|
||||
int id, ret;
|
||||
|
||||
dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
|
||||
if (!dp)
|
||||
return -ENOMEM;
|
||||
@@ -4452,7 +4409,7 @@ static int dw_dp_probe(struct platform_device *pdev)
|
||||
ret = dw_dp_parse_dt(dp);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to parse DT\n");
|
||||
dp->force_hpd = 1;
|
||||
|
||||
mutex_init(&dp->irq_lock);
|
||||
INIT_WORK(&dp->hpd_work, dw_dp_hpd_work);
|
||||
init_completion(&dp->complete);
|
||||
@@ -4466,12 +4423,10 @@ static int dw_dp_probe(struct platform_device *pdev)
|
||||
return dev_err_probe(dev, PTR_ERR(dp->regmap),
|
||||
"failed to create regmap\n");
|
||||
|
||||
#if !NO_PHY
|
||||
dp->phy = devm_of_phy_get(dev, dev->of_node, NULL);
|
||||
if (IS_ERR(dp->phy))
|
||||
return dev_err_probe(dev, PTR_ERR(dp->phy),
|
||||
"failed to get phy\n");
|
||||
#endif
|
||||
dp->i2s_clk = devm_clk_get(dev, "i2s");
|
||||
if (IS_ERR(dp->i2s_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(dp->i2s_clk),
|
||||
@@ -4486,7 +4441,7 @@ static int dw_dp_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(dp->aux_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(dp->aux_clk),
|
||||
"failed to get aux clock\n");
|
||||
|
||||
|
||||
dp->gtc_clk = devm_clk_get(dev, "gtc");
|
||||
if (IS_ERR(dp->gtc_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(dp->gtc_clk),
|
||||
@@ -4555,6 +4510,28 @@ static int dw_dp_probe(struct platform_device *pdev)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to register extcon device\n");
|
||||
|
||||
/* Try to get PHY's extcon for Type-C HPD notification */
|
||||
dp->phy_extcon = extcon_get_edev_by_phandle(dev, 0);
|
||||
if (IS_ERR(dp->phy_extcon)) {
|
||||
if (PTR_ERR(dp->phy_extcon) == -EPROBE_DEFER) {
|
||||
dev_err(dev, "PHY extcon not ready, deferring probe\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
/* PHY extcon not available, will use GPIO or internal HPD */
|
||||
dev_info(dev, "No PHY extcon found, using GPIO/internal HPD detection\n");
|
||||
dp->phy_extcon = NULL;
|
||||
} else {
|
||||
/* Register notifier to listen for PHY HPD events */
|
||||
dp->phy_extcon_nb.notifier_call = dw_dp_phy_extcon_notifier;
|
||||
ret = devm_extcon_register_notifier(dev, dp->phy_extcon,
|
||||
EXTCON_DISP_DP,
|
||||
&dp->phy_extcon_nb);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register PHY extcon notifier: ret = %d \n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
//ret = dw_dp_register_audio_driver(dp);
|
||||
//if (ret)
|
||||
// return ret;
|
||||
@@ -4593,7 +4570,6 @@ static int dw_dp_probe(struct platform_device *pdev)
|
||||
secondary->split_mode = true;
|
||||
}
|
||||
|
||||
dw_dp_create_capabilities_sysfs(pdev);
|
||||
//dw_dp_hdcp_init(dp);
|
||||
|
||||
return component_add(dev, &dw_dp_component_ops);
|
||||
@@ -4605,7 +4581,6 @@ static int dw_dp_remove(struct platform_device *pdev)
|
||||
|
||||
component_del(dp->dev, &dw_dp_component_ops);
|
||||
cancel_work_sync(&dp->hpd_work);
|
||||
dw_dp_remove_capabilities_sysfs(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#ifdef CONFIG_ZHIHE_AUXDISP
|
||||
#include <linux/of.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#endif
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_modes.h>
|
||||
@@ -14,6 +19,10 @@
|
||||
|
||||
#include "vs_crtc.h"
|
||||
|
||||
#ifdef CONFIG_ZHIHE_AUXDISP
|
||||
#include "vs_drv.h"
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
|
||||
#include <linux/media-bus-format.h>
|
||||
#endif
|
||||
@@ -301,7 +310,7 @@ static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
|
||||
static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
#else
|
||||
static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_state)
|
||||
@@ -309,11 +318,50 @@ static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
{
|
||||
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
|
||||
|
||||
#ifdef CONFIG_ZHIHE_AUXDISP
|
||||
struct drm_device *drm_dev = crtc->dev;
|
||||
struct vs_drm_private *priv = drm_dev->dev_private;
|
||||
bool auxdisp_enabling = false;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
|
||||
/* 检查是否有 AuxDisp CRTC 即将启用 */
|
||||
struct drm_crtc *other_crtc;
|
||||
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||
int i;
|
||||
|
||||
for_each_oldnew_crtc_in_state(state, other_crtc, old_crtc_state, new_crtc_state, i) {
|
||||
if (other_crtc == crtc)
|
||||
continue;
|
||||
|
||||
/* 检查是否是 AuxDisp CRTC */
|
||||
if (other_crtc->port && other_crtc->port->parent &&
|
||||
of_device_is_compatible(other_crtc->port->parent, ZH_AUXDISP_COMPATIBLE)) {
|
||||
|
||||
/* 检查 AuxDisp 是否从 inactive → active */
|
||||
if (!old_crtc_state->active && new_crtc_state->active) {
|
||||
auxdisp_enabling = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
|
||||
vs_crtc->funcs->disable(vs_crtc->dev, crtc);
|
||||
|
||||
#ifdef CONFIG_ZHIHE_AUXDISP
|
||||
/* 如果检测到 AuxDisp 即将启用,不释放 PM 引用 */
|
||||
if (auxdisp_enabling) {
|
||||
priv->dc_clk_held_for_auxdisp = true;
|
||||
} else {
|
||||
/* 正常情况:立即释放 PM 引用 */
|
||||
pm_runtime_put(vs_crtc->dev);
|
||||
}
|
||||
#else
|
||||
pm_runtime_put(vs_crtc->dev);
|
||||
#endif
|
||||
|
||||
spin_lock_irq(&crtc->dev->event_lock);
|
||||
if (crtc->state->event && !crtc->state->active) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
@@ -319,7 +320,7 @@ static void vs_dc_dump_disable(struct device *dev)
|
||||
|
||||
static void vs_dc_set_display_path(struct device *dev, struct drm_atomic_state *state, struct vs_dc *dc, struct drm_crtc *crtc)
|
||||
{
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *conn_state;
|
||||
struct clk *clk = dc->pixclk[crtc->index];
|
||||
@@ -339,7 +340,7 @@ static void vs_dc_set_display_path(struct device *dev, struct drm_atomic_state *
|
||||
clk_set_parent(dc->dptx_pixclk, clk);
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "invalid connector type:%d\n", connector->connector_type);
|
||||
dev_err(dev, "invalid connector type:%d\n", connector->connector_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,6 +348,12 @@ static void vs_dc_set_display_path(struct device *dev, struct drm_atomic_state *
|
||||
static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc, struct drm_atomic_state *state)
|
||||
{
|
||||
struct vs_dc *dc = dev_get_drvdata(dev);
|
||||
|
||||
#ifdef CONFIG_ZHIHE_AUXDISP
|
||||
struct drm_device *drm_dev = crtc->dev;
|
||||
struct vs_drm_private *priv = drm_dev->dev_private;
|
||||
#endif
|
||||
|
||||
struct vs_crtc_state *crtc_state = to_vs_crtc_state(crtc->state);
|
||||
struct drm_display_mode *mode = &crtc->state->adjusted_mode;
|
||||
struct dc_hw_display display;
|
||||
@@ -380,12 +387,12 @@ static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc, struct drm_a
|
||||
display.enable = true;
|
||||
|
||||
if (dc->pix_clk_rate[display.id] != mode->clock) {
|
||||
clk_set_rate(dc->pixclk[display.id], mode->clock * 1000);
|
||||
clk_set_rate(dc->pixclk[display.id], mode->clock * 1000);
|
||||
dc->pix_clk_rate[display.id] = mode->clock;
|
||||
}
|
||||
|
||||
if (crtc_state->encoder_type == DRM_MODE_ENCODER_DSI ||
|
||||
crtc_state->encoder_type == DRM_MODE_ENCODER_DPI)
|
||||
crtc_state->encoder_type == DRM_MODE_ENCODER_DPI)
|
||||
dc_hw_set_out(&dc->hw, OUT_DPI, display.id);
|
||||
else
|
||||
dc_hw_set_out(&dc->hw, OUT_DP, display.id);
|
||||
@@ -402,6 +409,12 @@ static void vs_dc_enable(struct device *dev, struct drm_crtc *crtc, struct drm_a
|
||||
if (dc->is_zhihe_a210)
|
||||
vs_dc_set_display_path(dev, state, dc, crtc);
|
||||
|
||||
#ifdef CONFIG_ZHIHE_AUXDISP
|
||||
if (priv->auxdisp_clk_held_for_dc && priv->auxdisp_dev) {
|
||||
priv->auxdisp_clk_held_for_dc = false;
|
||||
pm_runtime_put(priv->auxdisp_dev);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void vs_dc_disable(struct device *dev, struct drm_crtc *crtc)
|
||||
@@ -425,8 +438,8 @@ static bool vs_dc_mode_fixup(struct device *dev,
|
||||
long clk_rate;
|
||||
|
||||
if (unlikely(id >= DC_DISPLAY_NUM)) {
|
||||
dev_err(dev, "invalid display id : %d\n", id);
|
||||
return false;
|
||||
dev_err(dev, "invalid display id : %d\n", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dc->pixclk[id]) {
|
||||
@@ -438,13 +451,31 @@ static bool vs_dc_mode_fixup(struct device *dev,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool crtc_is_dsi(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
drm_for_each_encoder(encoder, drm) {
|
||||
if (!drm_encoder_crtc_ok(encoder, crtc))
|
||||
continue;
|
||||
|
||||
if (encoder->encoder_type == DRM_MODE_ENCODER_DSI)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum drm_mode_status vs_dc_mode_valid(struct device *dev,
|
||||
struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
#define PIXCLK_ERR_BP 25 //diff 0.25%
|
||||
struct vs_dc *dc = dev_get_drvdata(dev);
|
||||
int id = to_vs_display_id(dc, crtc);
|
||||
long clk_rate, request_rate;
|
||||
unsigned long clk_rate, request_rate;
|
||||
unsigned long diff, bp;
|
||||
|
||||
if (unlikely(id >= DC_DISPLAY_NUM))
|
||||
return MODE_BAD;
|
||||
@@ -456,11 +487,20 @@ static enum drm_mode_status vs_dc_mode_valid(struct device *dev,
|
||||
clk_rate = clk_round_rate(dc->pixclk[id], request_rate);
|
||||
|
||||
/*
|
||||
* If the clock rate difference is more than 100, the mode is
|
||||
*Range checking for DSI devices is delegated to the DSI subsystem.
|
||||
*/
|
||||
if (crtc_is_dsi(crtc)) {
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the clock rate difference is more than 0.25%, the mode is
|
||||
* considered unsupported by the CRTC hardware.
|
||||
* refer to dw_hdmi_tx_phy_gen2_configure() function
|
||||
*/
|
||||
if (abs(clk_rate - request_rate) > 100)
|
||||
diff = clk_rate > request_rate ? clk_rate - request_rate : request_rate - clk_rate;
|
||||
bp = diff * 10000ULL / request_rate;
|
||||
if (bp > PIXCLK_ERR_BP)
|
||||
return MODE_CLOCK_RANGE;
|
||||
|
||||
return MODE_OK;
|
||||
@@ -493,9 +533,7 @@ static void vs_dc_enable_gamma(struct device *dev, struct drm_crtc *crtc,
|
||||
bool enable)
|
||||
{
|
||||
struct vs_dc *dc = dev_get_drvdata(dev);
|
||||
u8 id;
|
||||
|
||||
id = to_vs_display_id(dc, crtc);
|
||||
u8 id = to_vs_display_id(dc, crtc);
|
||||
dc_hw_enable_gamma(&dc->hw, id, enable);
|
||||
}
|
||||
|
||||
@@ -917,9 +955,9 @@ static int vs_dc_check_plane(struct device *dev, struct vs_plane *plane,
|
||||
|
||||
/* 90/270 degree rotation requires non-linear fb */
|
||||
if ((state->rotation == DRM_MODE_ROTATE_90 ||
|
||||
state->rotation == DRM_MODE_ROTATE_270) &&
|
||||
(fb->modifier & DRM_FORMAT_MOD_LINEAR) == DRM_FORMAT_MOD_LINEAR)
|
||||
return -EINVAL;
|
||||
state->rotation == DRM_MODE_ROTATE_270) &&
|
||||
(fb->modifier & DRM_FORMAT_MOD_LINEAR) == DRM_FORMAT_MOD_LINEAR)
|
||||
return -EINVAL;
|
||||
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
plane_info->min_scale,
|
||||
@@ -936,13 +974,13 @@ static irqreturn_t dc_isr(int irq, void *data)
|
||||
intr_vec = dc_hw_get_interrupt(&dc->hw);
|
||||
|
||||
for (i = 0; i < dc_info->panel_num; i++) {
|
||||
if (intr_vec & BIT(i))
|
||||
vs_crtc_handle_vblank(&dc->crtc[i]->base,
|
||||
dc_hw_check_underflow(&dc->hw));
|
||||
if (intr_vec & BIT(i))
|
||||
vs_crtc_handle_vblank(&dc->crtc[i]->base,
|
||||
dc_hw_check_underflow(&dc->hw));
|
||||
}
|
||||
|
||||
if (intr_vec & ~0x3)
|
||||
pr_warn("%s: unhandled interrupt %#x\n", __func__, intr_vec);
|
||||
pr_warn("%s: unhandled interrupt %#x\n", __func__, intr_vec);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@@ -991,7 +1029,7 @@ static const struct vs_dc_funcs dc_funcs = {
|
||||
static int dc_bind(struct device *dev, struct device *master, void *data)
|
||||
{
|
||||
struct drm_device *drm_dev = data;
|
||||
#ifdef CONFIG_VERISILICON_MMU
|
||||
#if defined(CONFIG_VERISILICON_MMU) || defined(CONFIG_ZHIHE_AUXDISP)
|
||||
struct vs_drm_private *priv = drm_dev->dev_private;
|
||||
#endif
|
||||
struct vs_dc *dc = dev_get_drvdata(dev);
|
||||
@@ -1009,6 +1047,12 @@ static int dc_bind(struct device *dev, struct device *master, void *data)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ZHIHE_AUXDISP
|
||||
/* 注册 DC8200 设备到共享状态,用于 AuxDisp 切换协调 */
|
||||
priv->dc_dev = dev;
|
||||
dev_info(dev, "DC8200: Registered device for AuxDisp coordination\n");
|
||||
#endif
|
||||
|
||||
ret = dc_init(dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize DC hardware.\n");
|
||||
@@ -1147,35 +1191,33 @@ const struct component_ops dc_component_ops = {
|
||||
};
|
||||
|
||||
static const struct of_device_id dc_driver_dt_match[] = {
|
||||
{ .compatible = "verisilicon,dc8200", },
|
||||
{ .compatible = VS_DC8200_COMPATIBLE },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, dc_driver_dt_match);
|
||||
|
||||
static void dc_get_display_pll(struct device *dev, struct vs_dc *dc)
|
||||
{
|
||||
struct device_node *child;
|
||||
u32 reg;
|
||||
struct device_node *child;
|
||||
u32 reg;
|
||||
|
||||
dc->dpu0pll_on = 0;
|
||||
dc->dpu1pll_on = 0;
|
||||
dc->dpu0pll_on = 0;
|
||||
dc->dpu1pll_on = 0;
|
||||
|
||||
for_each_child_of_node(dev->of_node, child) {
|
||||
if (!child->name || strcmp(child->name, "port") != 0)
|
||||
continue;
|
||||
for_each_child_of_node(dev->of_node, child) {
|
||||
if (!child->name || strcmp(child->name, "port") != 0)
|
||||
continue;
|
||||
|
||||
if (of_property_read_u32(child, "reg", ®)) {
|
||||
continue;
|
||||
}
|
||||
if (of_property_read_u32(child, "reg", ®))
|
||||
continue;
|
||||
|
||||
if (reg == 0) {
|
||||
dc->dpu0pll_on = of_device_is_available(child);
|
||||
} else if (reg == 1) {
|
||||
dc->dpu1pll_on = of_device_is_available(child);
|
||||
}
|
||||
}
|
||||
if (reg == 0)
|
||||
dc->dpu0pll_on = of_device_is_available(child);
|
||||
else if (reg == 1)
|
||||
dc->dpu1pll_on = of_device_is_available(child);
|
||||
}
|
||||
|
||||
dev_info(dev, "dpu0pll_on:%d dpu1pll_on:%d\n", dc->dpu0pll_on, dc->dpu1pll_on);
|
||||
dev_info(dev, "dpu0pll_on:%d dpu1pll_on:%d\n", dc->dpu0pll_on, dc->dpu1pll_on);
|
||||
}
|
||||
|
||||
static int dc_probe(struct platform_device *pdev)
|
||||
@@ -1310,73 +1352,73 @@ static int dc_remove(struct platform_device *pdev)
|
||||
#ifdef CONFIG_PM
|
||||
static int dc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
struct vs_dc *dc = dev_get_drvdata(dev);
|
||||
int i;
|
||||
struct vs_dc *dc = dev_get_drvdata(dev);
|
||||
|
||||
dev_dbg(dev, "%s\n", __func__);
|
||||
clk_disable_unprepare(dc->axi_clk);
|
||||
dev_dbg(dev, "%s\n", __func__);
|
||||
clk_disable_unprepare(dc->axi_clk);
|
||||
|
||||
for (i = 0; i < DC_DISPLAY_NUM; i++){
|
||||
clk_disable_unprepare(dc->pix_clk[i]);
|
||||
for (i = 0; i < DC_DISPLAY_NUM; i++){
|
||||
clk_disable_unprepare(dc->pix_clk[i]);
|
||||
clk_disable_unprepare(dc->pixclk[i]);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(dc->core_clk);
|
||||
clk_disable_unprepare(dc->core_clk);
|
||||
|
||||
clk_disable_unprepare(dc->cfg_clk);
|
||||
clk_disable_unprepare(dc->cfg_clk);
|
||||
|
||||
if (dc->dpu0pll_on)
|
||||
clk_disable_unprepare(dc->dpu0pll_clk);
|
||||
if (dc->dpu1pll_on)
|
||||
clk_disable_unprepare(dc->dpu1pll_clk);
|
||||
if (dc->dpu0pll_on)
|
||||
clk_disable_unprepare(dc->dpu0pll_clk);
|
||||
if (dc->dpu1pll_on)
|
||||
clk_disable_unprepare(dc->dpu1pll_clk);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dc_runtime_resume(struct device *dev)
|
||||
{
|
||||
int i, ret;
|
||||
struct vs_dc *dc = dev_get_drvdata(dev);
|
||||
int i, ret;
|
||||
struct vs_dc *dc = dev_get_drvdata(dev);
|
||||
|
||||
dev_dbg(dev, "%s\n", __func__);
|
||||
if (dc->dpu0pll_on)
|
||||
clk_prepare_enable(dc->dpu0pll_clk);
|
||||
if (dc->dpu1pll_on)
|
||||
clk_prepare_enable(dc->dpu1pll_clk);
|
||||
dev_dbg(dev, "%s\n", __func__);
|
||||
if (dc->dpu0pll_on)
|
||||
clk_prepare_enable(dc->dpu0pll_clk);
|
||||
if (dc->dpu1pll_on)
|
||||
clk_prepare_enable(dc->dpu1pll_clk);
|
||||
|
||||
ret = clk_prepare_enable(dc->cfg_clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to prepare/enable cfg_clk\n");
|
||||
return ret;
|
||||
}
|
||||
ret = clk_prepare_enable(dc->cfg_clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to prepare/enable cfg_clk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dc->core_clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to prepare/enable core_clk\n");
|
||||
return ret;
|
||||
}
|
||||
ret = clk_prepare_enable(dc->core_clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to prepare/enable core_clk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < DC_DISPLAY_NUM; i++) {
|
||||
ret = clk_prepare_enable(dc->pix_clk[i]);
|
||||
for (i = 0; i < DC_DISPLAY_NUM; i++) {
|
||||
ret = clk_prepare_enable(dc->pix_clk[i]);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to prepare/enable pix_clk %d\n", i);
|
||||
return ret;
|
||||
}
|
||||
dev_err(dev, "failed to prepare/enable pix_clk %d\n", i);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dc->pixclk[i]);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to prepare/enable pixclk %d\n", i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to prepare/enable pixclk %d\n", i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dc->axi_clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to prepare/enable axi_clk\n");
|
||||
return ret;
|
||||
}
|
||||
ret = clk_prepare_enable(dc->axi_clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to prepare/enable axi_clk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
@@ -1384,7 +1426,7 @@ static int dc_runtime_resume(struct device *dev)
|
||||
static int dc_suspend(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
struct vs_dc *dc = dev_get_drvdata(dev);
|
||||
struct vs_dc *dc = dev_get_drvdata(dev);
|
||||
|
||||
for (i = 0; i < DC_DISPLAY_NUM; i++){
|
||||
dc->pix_clk_rate[i] = dc->def_pix_clk_rate[i];
|
||||
@@ -1415,8 +1457,9 @@ static int dc_resume(struct device *dev)
|
||||
|
||||
#endif
|
||||
static const struct dev_pm_ops dc_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(
|
||||
pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_RUNTIME_PM_OPS(dc_runtime_suspend, dc_runtime_resume, NULL)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(dc_suspend, dc_resume)
|
||||
|
||||
@@ -172,7 +172,7 @@ static ssize_t log_show(struct kobject *kobj, struct kobj_attribute *attr, char
|
||||
is_current_master ? 'y' : 'n',
|
||||
priv->authenticated ? 'y' : 'n',
|
||||
// from_kuid_munged(seq_user_ns(m), uid)
|
||||
uid,
|
||||
__kuid_val(uid),
|
||||
priv->magic);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@@ -212,7 +212,6 @@ static ssize_t log_show(struct kobject *kobj, struct kobj_attribute *attr, char
|
||||
list_for_each_entry(drm_crtc, &drm_dev->mode_config.crtc_list, head) {
|
||||
// struct vs_crtc *crtc = to_vs_crtc(drm_crtc);
|
||||
struct drm_crtc *crtc = drm_crtc->state->crtc;
|
||||
struct vs_crtc_state *crtc_state = to_vs_crtc_state(drm_crtc->state);
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"crtc[%u]: %s\n"
|
||||
"\tenable= %d\n"
|
||||
@@ -231,7 +230,6 @@ static ssize_t log_show(struct kobject *kobj, struct kobj_attribute *attr, char
|
||||
|
||||
list_for_each_entry(plane, &drm_dev->mode_config.plane_list, head) {
|
||||
struct drm_plane_state *state = plane->state;
|
||||
struct vs_plane_state *plane_state = to_vs_plane_state(state);
|
||||
struct drm_rect src = drm_plane_state_src(state);
|
||||
struct drm_rect dest = drm_plane_state_dest(state);
|
||||
|
||||
@@ -466,6 +464,14 @@ static int vs_drm_bind(struct device *dev)
|
||||
priv->dma_dev = drm_dev->dev;
|
||||
priv->dma_dev->coherent_dma_mask = dma_mask;
|
||||
|
||||
#ifdef CONFIG_ZHIHE_AUXDISP
|
||||
/* 初始化 DC8200 ↔ AuxDisp 切换状态 */
|
||||
priv->dc_dev = NULL;
|
||||
priv->auxdisp_dev = NULL;
|
||||
priv->dc_clk_held_for_auxdisp = false;
|
||||
priv->auxdisp_clk_held_for_dc = false;
|
||||
#endif
|
||||
|
||||
drm_dev->dev_private = priv;
|
||||
|
||||
drm_mode_config_init(drm_dev);
|
||||
@@ -537,7 +543,7 @@ static void vs_drm_unbind(struct device *dev)
|
||||
drm_kms_helper_poll_fini(drm_dev);
|
||||
|
||||
drm_dev_unregister(drm_dev);
|
||||
|
||||
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
|
||||
@@ -547,7 +553,7 @@ static void vs_drm_unbind(struct device *dev)
|
||||
}
|
||||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
component_unbind_all(drm_dev->dev, drm_dev);
|
||||
component_unbind_all(drm_dev->dev, drm_dev);
|
||||
|
||||
drm_mode_config_cleanup(drm_dev);
|
||||
|
||||
@@ -567,10 +573,17 @@ static const struct component_master_ops vs_drm_ops = {
|
||||
};
|
||||
|
||||
extern struct platform_driver dw_dp_driver;
|
||||
extern struct platform_driver auxdisp_crtc_driver;
|
||||
|
||||
static struct platform_driver *drm_sub_drivers[] = {
|
||||
/* put display control driver at start */
|
||||
&dc_platform_driver,
|
||||
|
||||
/* auxiliary display CRTC */
|
||||
#ifdef CONFIG_ZHIHE_AUXDISP
|
||||
&auxdisp_crtc_driver,
|
||||
#endif
|
||||
|
||||
/* connector */
|
||||
|
||||
/* bridge */
|
||||
|
||||
@@ -44,6 +44,13 @@ struct vs_drm_private {
|
||||
#endif
|
||||
|
||||
unsigned int pitch_alignment;
|
||||
|
||||
#ifdef CONFIG_ZHIHE_AUXDISP
|
||||
struct device *dc_dev; /* DC8200 设备指针 */
|
||||
struct device *auxdisp_dev; /* AuxDisp 设备指针 */
|
||||
bool dc_clk_held_for_auxdisp; /* DC8200 时钟是否被 AuxDisp 持有 */
|
||||
bool auxdisp_clk_held_for_dc; /* AuxDisp 时钟是否被 DC8200 持有 */
|
||||
#endif
|
||||
};
|
||||
|
||||
int vs_drm_iommu_attach_device(struct drm_device *drm_dev,
|
||||
@@ -68,4 +75,9 @@ static inline bool is_iommu_enabled(struct drm_device *dev)
|
||||
|
||||
return priv->domain != NULL ? true : false;
|
||||
}
|
||||
|
||||
/* Device compatible strings */
|
||||
#define VS_DC8200_COMPATIBLE "verisilicon,dc8200"
|
||||
#define ZH_AUXDISP_COMPATIBLE "zhihe,auxdisp"
|
||||
|
||||
#endif /* __VS_DRV_H__ */
|
||||
|
||||
@@ -17,10 +17,13 @@
|
||||
#endif
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
|
||||
#include "vs_fb.h"
|
||||
#include "vs_gem.h"
|
||||
@@ -166,10 +169,54 @@ vs_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int vs_drm_atomic_check(struct drm_device *dev,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
#ifdef CONFIG_ZHIHE_AUXDISP
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *old_conn_state, *new_conn_state;
|
||||
int i;
|
||||
|
||||
for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_conn_state, i) {
|
||||
struct drm_crtc *old_crtc = old_conn_state->crtc;
|
||||
struct drm_crtc *new_crtc = new_conn_state->crtc;
|
||||
struct drm_crtc_state *old_crtc_state;
|
||||
struct drm_connector *conn2;
|
||||
struct drm_connector_state *conn2_state;
|
||||
bool has_other_connectors;
|
||||
int j;
|
||||
|
||||
if (!old_crtc || !new_crtc || old_crtc == new_crtc)
|
||||
continue;
|
||||
|
||||
old_crtc_state = drm_atomic_get_crtc_state(state, old_crtc);
|
||||
if (IS_ERR(old_crtc_state))
|
||||
return PTR_ERR(old_crtc_state);
|
||||
|
||||
has_other_connectors = false;
|
||||
for_each_new_connector_in_state(state, conn2, conn2_state, j) {
|
||||
if (conn2 == connector)
|
||||
continue;
|
||||
|
||||
if (conn2_state->crtc == old_crtc) {
|
||||
has_other_connectors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_other_connectors) {
|
||||
old_crtc_state->enable = false;
|
||||
old_crtc_state->active = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return drm_atomic_helper_check(dev, state);
|
||||
}
|
||||
|
||||
static const struct drm_mode_config_funcs vs_mode_config_funcs = {
|
||||
.fb_create = vs_fb_create,
|
||||
.get_format_info = vs_get_format_info,
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
.atomic_check = vs_drm_atomic_check,
|
||||
.atomic_commit = drm_atomic_helper_commit,
|
||||
};
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
obj-$(CONFIG_RISCV_IOMMU) += iommu.o iommu-platform.o iommu-sysfs.o io_pgtable.o
|
||||
obj-$(CONFIG_RISCV_IOMMU) += iommu.o iommu-platform.o io_pgtable.o
|
||||
|
||||
@@ -141,7 +141,7 @@ static int riscv_iommu_map_pages(struct io_pgtable_ops *ops,
|
||||
pte_t pte_val;
|
||||
pgprot_t pte_prot;
|
||||
|
||||
dev_dbg(domain->iommu->dev, "%s enter iova=0x%lx, phys=0x%llx pgsize=0x%lx pgcount=0x%lx\n", __func__, iova, phys, pgsize, pgcount);
|
||||
dev_dbg(domain->iommus->dev, "%s enter iova=0x%lx, phys=0x%llx pgsize=0x%lx pgcount=0x%lx\n", __func__, iova, phys, pgsize, pgcount);
|
||||
if (domain->domain.type == IOMMU_DOMAIN_BLOCKED)
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
@@ -11,99 +11,166 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of_clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include "iommu-bits.h"
|
||||
#include "iommu.h"
|
||||
|
||||
#define P100_IOMMU_CAP 0x28d0008210
|
||||
#define A210_IOMMU_CAP 0x28d0008210
|
||||
|
||||
static int riscv_iommu_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct zh_iommu_device *iommus = NULL;
|
||||
struct riscv_iommu_device *iommu = NULL;
|
||||
struct resource *res = NULL;
|
||||
struct device_node *np = dev->of_node;
|
||||
u32 fctl = 0;
|
||||
int irq = 0;
|
||||
int ret = 0;
|
||||
int count;
|
||||
|
||||
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
|
||||
if (!iommu)
|
||||
iommus = devm_kzalloc(dev, sizeof(*iommus), GFP_KERNEL);
|
||||
if (!iommus)
|
||||
return -ENOMEM;
|
||||
iommus->dev = dev;
|
||||
mutex_init(&iommus->lock);
|
||||
INIT_LIST_HEAD(&iommus->iommus);
|
||||
INIT_LIST_HEAD(&iommus->groups);
|
||||
dev_set_drvdata(dev, iommus);
|
||||
dev_set_name(dev, "%s", "zhihe,iommu");
|
||||
|
||||
iommu->dev = dev;
|
||||
dev_set_drvdata(dev, iommu);
|
||||
count = of_count_phandle_with_args(np, "power-domains", "#power-domain-cells");
|
||||
if (count > 0) {
|
||||
iommus->pd_devs = devm_kcalloc(dev, count, sizeof(*iommus->pd_devs), GFP_KERNEL);
|
||||
if (!iommus->pd_devs)
|
||||
return -ENOMEM;
|
||||
iommus->num_pds = count;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(dev, "could not find resource for register region\n");
|
||||
return -EINVAL;
|
||||
for (int i = 0; i < count; i++) {
|
||||
iommus->pd_devs[i] = dev_pm_domain_attach_by_id(dev, i);
|
||||
if (IS_ERR(iommus->pd_devs[i]))
|
||||
return PTR_ERR(iommus->pd_devs[i]);
|
||||
device_link_add(dev, iommus->pd_devs[i], DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
|
||||
}
|
||||
}
|
||||
|
||||
iommu->reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||
if (IS_ERR(iommu->reg)) {
|
||||
ret = dev_err_probe(dev, PTR_ERR(iommu->reg),
|
||||
"could not map register region\n");
|
||||
goto fail;
|
||||
/*
|
||||
* Get and prepare clocks early, before any hardware access.
|
||||
* Do NOT use pm_runtime_get_sync() before this, as it may trigger power
|
||||
* domain operations that themselves need to prepare clocks, causing
|
||||
* circular locking: prepare_lock → genpd_runtime_resume → genpd->mlock
|
||||
* → a210_pd_power_on → clk_prepare → prepare_lock (deadlock).
|
||||
*/
|
||||
iommus->num_clks = devm_clk_bulk_get_all(dev, &iommus->clks);
|
||||
if (iommus->num_clks < 0)
|
||||
return dev_err_probe(dev, iommus->num_clks,
|
||||
"Failed to get iommus's clocks\n");
|
||||
|
||||
ret = clk_bulk_prepare_enable(iommus->num_clks, iommus->clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
for (int i = 0; i < pdev->num_resources; i++) {
|
||||
const char *name;
|
||||
|
||||
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
|
||||
if (!iommu)
|
||||
return -ENOMEM;
|
||||
|
||||
iommu->dev = dev;
|
||||
INIT_LIST_HEAD(&iommu->list);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
|
||||
if (!res) {
|
||||
dev_err(dev, "could not find resource for register region\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
iommu->reg = devm_platform_get_and_ioremap_resource(pdev, i, &res);
|
||||
if (IS_ERR(iommu->reg)) {
|
||||
ret = dev_err_probe(dev, PTR_ERR(iommu->reg),
|
||||
"could not map register region\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
of_property_read_string_index(np, "reg-names", i, &name);
|
||||
iommu->name = kstrdup(name, GFP_KERNEL);
|
||||
|
||||
iommu->reg_phys = res->start;
|
||||
|
||||
ret = -ENODEV;
|
||||
|
||||
/* Sanity check: Did we get the whole register space ? */
|
||||
if ((res->end - res->start + 1) < RISCV_IOMMU_REG_SIZE) {
|
||||
dev_err(dev, "device region smaller than register file (0x%llx)\n",
|
||||
res->end - res->start);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
iommu->cap = riscv_iommu_readq(iommu, RISCV_IOMMU_REG_CAP);
|
||||
if (iommu->cap != A210_IOMMU_CAP) {
|
||||
dev_err_probe(dev, -ENODEV,
|
||||
"IOMMU:%s Capacity Reg=0x%llx Error.Check clock power reset!\n", iommu->name, iommu->cap);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* For now we only support WSIs until we have AIA support */
|
||||
ret = FIELD_GET(RISCV_IOMMU_CAP_IGS, iommu->cap);
|
||||
if (ret == RISCV_IOMMU_CAP_IGS_MSI) {
|
||||
dev_err(dev, "IOMMU only supports MSIs\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Parse IRQ assignment */
|
||||
irq = platform_get_irq(pdev, i);
|
||||
if (irq > 0)
|
||||
iommu->irq = irq;
|
||||
else {
|
||||
dev_err(dev, "no IRQ provided for iommu\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Make sure fctl.WSI is set */
|
||||
fctl = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_FCTL);
|
||||
fctl |= RISCV_IOMMU_FCTL_WSI;
|
||||
riscv_iommu_writel(iommu, RISCV_IOMMU_REG_FCTL, fctl);
|
||||
|
||||
/* Parse Queue lengts */
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "cmdq_len", &iommu->cmdq_len);
|
||||
if (!ret)
|
||||
dev_info(dev, "command queue length set to %i\n", iommu->cmdq_len);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "fltq_len", &iommu->fltq_len);
|
||||
if (!ret)
|
||||
dev_info(dev, "fault/event queue length set to %i\n", iommu->fltq_len);
|
||||
|
||||
ret = riscv_iommu_init(iommu);
|
||||
if (ret) {
|
||||
dev_err(dev, "riscv_iommu_init failed %d", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
list_add_tail(&iommu->list, &iommus->iommus);
|
||||
}
|
||||
|
||||
iommu->reg_phys = res->start;
|
||||
|
||||
ret = -ENODEV;
|
||||
|
||||
/* Sanity check: Did we get the whole register space ? */
|
||||
if ((res->end - res->start + 1) < RISCV_IOMMU_REG_SIZE) {
|
||||
dev_err(dev, "device region smaller than register file (0x%llx)\n",
|
||||
res->end - res->start);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
iommu->cap = riscv_iommu_readq(iommu, RISCV_IOMMU_REG_CAP);
|
||||
if (iommu->cap != P100_IOMMU_CAP) {
|
||||
dev_err_probe(dev, -ENODEV,
|
||||
"IOMMU Capacity Reg=0x%llx Error.Check clock power reset!\n", iommu->cap);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* For now we only support WSIs until we have AIA support */
|
||||
ret = FIELD_GET(RISCV_IOMMU_CAP_IGS, iommu->cap);
|
||||
if (ret == RISCV_IOMMU_CAP_IGS_MSI) {
|
||||
dev_err(dev, "IOMMU only supports MSIs\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Parse IRQ assignment */
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq > 0)
|
||||
iommu->irq = irq;
|
||||
else {
|
||||
dev_err(dev, "no IRQ provided for iommu\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Make sure fctl.WSI is set */
|
||||
fctl = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_FCTL);
|
||||
fctl |= RISCV_IOMMU_FCTL_WSI;
|
||||
riscv_iommu_writel(iommu, RISCV_IOMMU_REG_FCTL, fctl);
|
||||
|
||||
/* Parse Queue lengts */
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "cmdq_len", &iommu->cmdq_len);
|
||||
if (!ret)
|
||||
dev_info(dev, "command queue length set to %i\n", iommu->cmdq_len);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "fltq_len", &iommu->fltq_len);
|
||||
if (!ret)
|
||||
dev_info(dev, "fault/event queue length set to %i\n", iommu->fltq_len);
|
||||
|
||||
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
|
||||
|
||||
ret = riscv_iommu_init(iommu);
|
||||
riscv_iommu_register(iommus);
|
||||
|
||||
//clear tlb
|
||||
if (!ret) {
|
||||
list_for_each_entry(iommu, &iommus->iommus, list) {
|
||||
//clear tlb with a tmp domain
|
||||
struct riscv_iommu_domain iommu_domain;
|
||||
iommu_domain.iommu = iommu;
|
||||
iommu_domain.iommus = iommus;
|
||||
iommu_domain.pscid = 0;
|
||||
iommu_domain.domain.ops = iommu->iommu.ops->default_domain_ops;
|
||||
iommu_domain.domain.ops = iommus->iommu.ops->default_domain_ops;
|
||||
iommu_flush_iotlb_all(&iommu_domain.domain);
|
||||
}
|
||||
|
||||
@@ -123,7 +190,7 @@ static void riscv_iommu_platform_shutdown(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct of_device_id riscv_iommu_of_match[] = {
|
||||
{.compatible = "riscv,iommu",},
|
||||
{.compatible = "zhihe,iommu",},
|
||||
{},
|
||||
};
|
||||
|
||||
@@ -131,7 +198,7 @@ MODULE_DEVICE_TABLE(of, riscv_iommu_of_match);
|
||||
|
||||
static struct platform_driver riscv_iommu_platform_driver = {
|
||||
.driver = {
|
||||
.name = "riscv,iommu",
|
||||
.name = "zhihe,iommu",
|
||||
.of_match_table = riscv_iommu_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
|
||||
@@ -61,10 +61,6 @@ static DEVICE_ATTR_RO(address);
|
||||
return len; \
|
||||
}
|
||||
|
||||
extern void riscv_iommu_flush_iotlb_range(struct iommu_domain *iommu_domain,
|
||||
unsigned long *start, unsigned long *end,
|
||||
size_t *pgsize);
|
||||
|
||||
#define ATTR_WR_REG64(name, offset) \
|
||||
ssize_t reg_ ## name ## _store(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
@@ -73,21 +69,13 @@ extern void riscv_iommu_flush_iotlb_range(struct iommu_domain *iommu_domain,
|
||||
struct riscv_iommu_device *iommu = sysfs_dev_to_iommu(dev); \
|
||||
unsigned long long val; \
|
||||
int ret; \
|
||||
unsigned long end = 0xffffffff; \
|
||||
size_t pgsize = 0x1000; \
|
||||
ret = kstrtoull(buf, 0, &val); \
|
||||
if (ret) \
|
||||
return ret; \
|
||||
if (offset == 0xdeadbeef) { \
|
||||
unsigned long tmp = (unsigned long)val; \
|
||||
riscv_iommu_flush_iotlb_range(&iommu->domain->domain, &tmp, &end, &pgsize); \
|
||||
} else { \
|
||||
riscv_iommu_writeq(iommu, offset, val); \
|
||||
} \
|
||||
riscv_iommu_writeq(iommu, offset, val); \
|
||||
return len; \
|
||||
}
|
||||
|
||||
|
||||
#define ATTR_RO_REG32(name, offset) \
|
||||
static ATTR_RD_REG32(name, offset); \
|
||||
static DEVICE_ATTR_RO(reg_ ## name)
|
||||
@@ -139,7 +127,6 @@ ATTR_RW_REG64(iohpmctr_4, RISCV_IOMMU_REG_IOHPMCTR(3));
|
||||
ATTR_RW_REG64(iohpmctr_5, RISCV_IOMMU_REG_IOHPMCTR(4));
|
||||
ATTR_RW_REG64(iohpmctr_6, RISCV_IOMMU_REG_IOHPMCTR(5));
|
||||
ATTR_RW_REG64(iohpmctr_7, RISCV_IOMMU_REG_IOHPMCTR(6));
|
||||
ATTR_RW_REG64(invalid_range, 0xdeadbeef);
|
||||
|
||||
static struct attribute *riscv_iommu_attrs[] = {
|
||||
&dev_attr_address.attr,
|
||||
@@ -176,7 +163,6 @@ static struct attribute *riscv_iommu_attrs[] = {
|
||||
&dev_attr_reg_iohpmevt_6.attr,
|
||||
&dev_attr_reg_iohpmctr_7.attr,
|
||||
&dev_attr_reg_iohpmevt_7.attr,
|
||||
&dev_attr_reg_invalid_range.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
#include "../dma-iommu.h"
|
||||
@@ -31,6 +32,8 @@
|
||||
#include <asm/csr.h>
|
||||
#include <asm/delay.h>
|
||||
|
||||
#include <dt-bindings/iommu/zh-iommu.h>
|
||||
|
||||
MODULE_DESCRIPTION("IOMMU driver for RISC-V architected Ziommu implementations");
|
||||
MODULE_AUTHOR("Tomasz Jeznach <tjeznach@rivosinc.com>");
|
||||
MODULE_AUTHOR("Nick Kossifidis <mick@ics.forth.gr>");
|
||||
@@ -326,86 +329,89 @@ static inline void riscv_iommu_cmd_iodir_set_did(struct riscv_iommu_command *cmd
|
||||
}
|
||||
|
||||
/* TODO: Convert into lock-less MPSC implementation. */
|
||||
static bool riscv_iommu_post_sync(struct riscv_iommu_device *iommu,
|
||||
static void riscv_iommu_post_sync(struct zh_iommu_device *iommus,
|
||||
struct riscv_iommu_command *cmd, bool sync)
|
||||
{
|
||||
u32 head, tail, next, last;
|
||||
unsigned long flags;
|
||||
struct riscv_iommu_device *iommu;
|
||||
|
||||
spin_lock_irqsave(&iommu->cq_lock, flags);
|
||||
head = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_CQH) & (iommu->cmdq.cnt - 1);
|
||||
tail = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_CQT) & (iommu->cmdq.cnt - 1);
|
||||
last = iommu->cmdq.lui;
|
||||
if (tail != last) {
|
||||
spin_unlock_irqrestore(&iommu->cq_lock, flags);
|
||||
/*
|
||||
* FIXME: This is a workaround for dropped MMIO writes/reads on QEMU platform.
|
||||
* While debugging of the problem is still ongoing, this provides
|
||||
* a simple impolementation of try-again policy.
|
||||
* Will be changed to lock-less algorithm in the feature.
|
||||
*/
|
||||
dev_dbg(iommu->dev, "IOMMU CQT: %x != %x (1st)\n", last, tail);
|
||||
list_for_each_entry(iommu, &iommus->iommus, list) {
|
||||
spin_lock_irqsave(&iommu->cq_lock, flags);
|
||||
tail =
|
||||
riscv_iommu_readl(iommu, RISCV_IOMMU_REG_CQT) & (iommu->cmdq.cnt - 1);
|
||||
head = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_CQH) & (iommu->cmdq.cnt - 1);
|
||||
tail = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_CQT) & (iommu->cmdq.cnt - 1);
|
||||
last = iommu->cmdq.lui;
|
||||
if (tail != last) {
|
||||
spin_unlock_irqrestore(&iommu->cq_lock, flags);
|
||||
dev_dbg(iommu->dev, "IOMMU CQT: %x != %x (2nd)\n", last, tail);
|
||||
/*
|
||||
* FIXME: This is a workaround for dropped MMIO writes/reads on QEMU platform.
|
||||
* While debugging of the problem is still ongoing, this provides
|
||||
* a simple impolementation of try-again policy.
|
||||
* Will be changed to lock-less algorithm in the feature.
|
||||
*/
|
||||
dev_dbg(iommu->dev, "IOMMU CQT: %x != %x (1st)\n", last, tail);
|
||||
spin_lock_irqsave(&iommu->cq_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
next = (last + 1) & (iommu->cmdq.cnt - 1);
|
||||
if (next != head) {
|
||||
struct riscv_iommu_command *ptr = iommu->cmdq.base;
|
||||
ptr[last] = *cmd;
|
||||
dma_wmb();
|
||||
riscv_iommu_writel(iommu, RISCV_IOMMU_REG_CQT, next);
|
||||
iommu->cmdq.lui = next;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&iommu->cq_lock, flags);
|
||||
|
||||
if (sync && head != next) {
|
||||
cycles_t start_time = get_cycles();
|
||||
while (1) {
|
||||
last = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_CQH) &
|
||||
(iommu->cmdq.cnt - 1);
|
||||
if (head < next && last >= next)
|
||||
break;
|
||||
if (head > next && last < head && last >= next)
|
||||
break;
|
||||
if (RISCV_IOMMU_TIMEOUT < (get_cycles() - start_time)) {
|
||||
dev_err(iommu->dev, "IOFENCE TIMEOUT\n");
|
||||
return false;
|
||||
tail =
|
||||
riscv_iommu_readl(iommu, RISCV_IOMMU_REG_CQT) & (iommu->cmdq.cnt - 1);
|
||||
last = iommu->cmdq.lui;
|
||||
if (tail != last) {
|
||||
spin_unlock_irqrestore(&iommu->cq_lock, flags);
|
||||
dev_dbg(iommu->dev, "IOMMU CQT: %x != %x (2nd)\n", last, tail);
|
||||
spin_lock_irqsave(&iommu->cq_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
next = (last + 1) & (iommu->cmdq.cnt - 1);
|
||||
if (next != head) {
|
||||
struct riscv_iommu_command *ptr = iommu->cmdq.base;
|
||||
ptr[last] = *cmd;
|
||||
dma_wmb();
|
||||
riscv_iommu_writel(iommu, RISCV_IOMMU_REG_CQT, next);
|
||||
iommu->cmdq.lui = next;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&iommu->cq_lock, flags);
|
||||
|
||||
if (sync && head != next) {
|
||||
cycles_t start_time = get_cycles();
|
||||
while (1) {
|
||||
last = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_CQH) &
|
||||
(iommu->cmdq.cnt - 1);
|
||||
if (head < next && last >= next)
|
||||
break;
|
||||
if (head > next && last < head && last >= next)
|
||||
break;
|
||||
if (RISCV_IOMMU_TIMEOUT < (get_cycles() - start_time)) {
|
||||
dev_err(iommu->dev, "IOFENCE TIMEOUT\n");
|
||||
return;
|
||||
}
|
||||
cpu_relax();
|
||||
}
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
|
||||
return next != head;
|
||||
return;
|
||||
}
|
||||
|
||||
static bool riscv_iommu_post(struct riscv_iommu_device *iommu,
|
||||
static void riscv_iommu_post(struct zh_iommu_device *iommus,
|
||||
struct riscv_iommu_command *cmd)
|
||||
{
|
||||
return riscv_iommu_post_sync(iommu, cmd, false);
|
||||
return riscv_iommu_post_sync(iommus, cmd, false);
|
||||
}
|
||||
|
||||
static bool riscv_iommu_iodir_inv_devid(struct riscv_iommu_device *iommu, unsigned devid)
|
||||
static void riscv_iommu_iodir_inv_devid(struct zh_iommu_device *iommus, unsigned devid)
|
||||
{
|
||||
struct riscv_iommu_command cmd;
|
||||
riscv_iommu_cmd_iodir_inval_ddt(&cmd);
|
||||
riscv_iommu_cmd_iodir_set_did(&cmd, devid);
|
||||
return riscv_iommu_post(iommu, &cmd);
|
||||
return riscv_iommu_post(iommus, &cmd);
|
||||
}
|
||||
|
||||
static bool riscv_iommu_iofence_sync(struct riscv_iommu_device *iommu)
|
||||
static void riscv_iommu_iofence_sync(struct zh_iommu_device *iommus)
|
||||
{
|
||||
struct riscv_iommu_command cmd;
|
||||
riscv_iommu_cmd_iofence(&cmd);
|
||||
return riscv_iommu_post_sync(iommu, &cmd, true);
|
||||
return riscv_iommu_post_sync(iommus, &cmd, true);
|
||||
}
|
||||
|
||||
/* Command queue primary interrupt handler */
|
||||
@@ -423,7 +429,8 @@ static irqreturn_t riscv_iommu_cmdq_irq_check(int irq, void *data)
|
||||
static void riscv_iommu_dump_regs(struct riscv_iommu_device *iommu)
|
||||
{
|
||||
dev_warn_ratelimited(iommu->dev,
|
||||
"riscv_iommu_dump_regs: CAP=0x%llx\n FCTL=0x%x\n DDTP=0x%llx\n CQB=0x%llx\n CQH=0x%x\n CQT=0x%x\n CQCSR=0x%x\n",
|
||||
"%s iommu dump regs: CAP=0x%llx\n FCTL=0x%x\n DDTP=0x%llx\n CQB=0x%llx\n CQH=0x%x\n CQT=0x%x\n CQCSR=0x%x\n",
|
||||
iommu->name,
|
||||
riscv_iommu_readq(iommu, RISCV_IOMMU_REG_CAP),
|
||||
riscv_iommu_readl(iommu, RISCV_IOMMU_REG_FCTL),
|
||||
riscv_iommu_readq(iommu, RISCV_IOMMU_REG_DDTP),
|
||||
@@ -447,7 +454,7 @@ static irqreturn_t riscv_iommu_cmdq_process(int irq, void *data)
|
||||
if (ctrl & (RISCV_IOMMU_CQCSR_CQMF |
|
||||
RISCV_IOMMU_CQCSR_CMD_TO | RISCV_IOMMU_CQCSR_CMD_ILL)) {
|
||||
riscv_iommu_queue_ctrl(iommu, &iommu->cmdq, ctrl);
|
||||
dev_warn_ratelimited(iommu->dev,
|
||||
dev_err(iommu->dev,
|
||||
"Command queue error: fault: %d tout: %d err: %d\n",
|
||||
!!(ctrl & RISCV_IOMMU_CQCSR_CQMF),
|
||||
!!(ctrl & RISCV_IOMMU_CQCSR_CMD_TO),
|
||||
@@ -635,7 +642,7 @@ static void riscv_iommu_get_dc(struct riscv_iommu_device *iommu,
|
||||
*/
|
||||
ddtp += (ep->devids[i] >> split) & 0x1FF;
|
||||
|
||||
printk("%s ddi_bits[%d]=%d, split=%d, (devid >> split) & 0x1FF=%d 1st ddtp=0x%px indexed ddtp=0x%px\n", __func__,
|
||||
printk("%s ddi_bits[%d]=%d, split=%d, (devid >> split) & 0x1FF=%d 1st ddtp=0x%px indexed ddtp=0x%px\n", __func__,
|
||||
depth, ddi_bits[depth], split, (ep->devids[i] >> split) & 0x1FF, (u64 *)iommu->ddtp, (u64 *)ddtp);
|
||||
retry:
|
||||
/*
|
||||
@@ -682,31 +689,58 @@ retry:
|
||||
return;
|
||||
}
|
||||
|
||||
/* find out exactly which iommu hardware ip is used for specific devid */
|
||||
static struct riscv_iommu_device *riscv_iommu_find_hardware(struct zh_iommu_device *iommus, u32 devid)
|
||||
{
|
||||
char name[10];
|
||||
struct riscv_iommu_device *iommu;
|
||||
|
||||
if (devid >= DEVID_DIE0_PERI1_DFMU && devid <= DEVID_DIE0_EMMC)
|
||||
strcpy(name, "peri1");
|
||||
else if (devid >= DEVID_DIE0_USB_DFMU && devid <= DEVID_DIE0_USB2_1)
|
||||
strcpy(name, "usb");
|
||||
else if (devid >= DEVID_DIE0_PCIE_DFMU && devid <= DEVID_DIE0_TEE_DMAC)
|
||||
strcpy(name, "pcie");
|
||||
else if (devid >= DEVID_DIE0_VI_DFMU && devid <= DEVID_DIE0_DW200)
|
||||
strcpy(name, "vi");
|
||||
else if (devid >= DEVID_DIE0_VP_DFMU && devid <= DEVID_DIE0_G2D)
|
||||
strcpy(name, "vp");
|
||||
else if (devid >= DEVID_DIE0_VO_DFMU && devid <= DEVID_DIE0_PIP_REC)
|
||||
strcpy(name, "vo");
|
||||
else if (devid >= DEVID_DIE0_NPU_DFMU && devid <= DEVID_DIE0_NPU)
|
||||
strcpy(name, "npu");
|
||||
else if (devid == DEVID_VIDEO_MEMORY_DUMMY)
|
||||
strcpy(name, "vp");
|
||||
else
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
list_for_each_entry(iommu, &iommus->iommus, list) {
|
||||
if (strcmp(name, iommu->name) == 0)
|
||||
return iommu;
|
||||
}
|
||||
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static struct iommu_device *riscv_iommu_probe_device(struct device *dev)
|
||||
{
|
||||
struct riscv_iommu_device *iommu;
|
||||
struct zh_iommu_device *iommus;
|
||||
struct riscv_iommu_endpoint *ep;
|
||||
struct iommu_fwspec *fwspec;
|
||||
int i;
|
||||
struct device_node *np = dev->of_node;
|
||||
int i, ret;
|
||||
|
||||
fwspec = dev_iommu_fwspec_get(dev);
|
||||
if (!fwspec || fwspec->ops != &riscv_iommu_ops ||
|
||||
!fwspec->iommu_fwnode || !fwspec->iommu_fwnode->dev || !fwspec->ids)
|
||||
!fwspec->iommu_fwnode || !fwspec->iommu_fwnode->dev)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
iommu = dev_get_drvdata(fwspec->iommu_fwnode->dev);
|
||||
if (!iommu)
|
||||
iommus = dev_get_drvdata(fwspec->iommu_fwnode->dev);
|
||||
if (!iommus)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
//enable iommu ddt to LV2 mode
|
||||
int ret = riscv_iommu_enable(iommu, ddt_mode);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable iommu LV2, error:%d\n", ret);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
if (dev_iommu_priv_get(dev))
|
||||
return &iommu->iommu;
|
||||
if (dev_iommu_priv_get(dev)) // in case ep is ready
|
||||
return &iommus->iommu;
|
||||
|
||||
ep = kzalloc(sizeof(*ep), GFP_KERNEL);
|
||||
if (!ep)
|
||||
@@ -720,22 +754,37 @@ static struct iommu_device *riscv_iommu_probe_device(struct device *dev)
|
||||
ep->num_ids = fwspec->num_ids;
|
||||
ep->domid = 0;
|
||||
|
||||
ep->iommu = iommu;
|
||||
ep->iommu = riscv_iommu_find_hardware(iommus, ep->devids[0]);
|
||||
if (IS_ERR(ep->iommu)) {
|
||||
dev_err(dev, "riscv_iommu_find_hardware failed with devid:0x%x", ep->devids[0]);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
ep->iommus = iommus;
|
||||
ep->dev = dev;
|
||||
|
||||
/* Initial DC pointer can be NULL if IOMMU is configured in OFF or BARE mode */
|
||||
riscv_iommu_get_dc(iommu, ep);
|
||||
if (of_property_read_u32(np, "iommu-group", &ep->group_id))
|
||||
ep->group_id = IOMMU_GROUP_PER_DEV;
|
||||
|
||||
printk(KERN_CONT "adding device to iommu with devid ");
|
||||
//enable iommu ddt to LV2 mode
|
||||
ret = riscv_iommu_enable(ep->iommu, ddt_mode);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable iommu LV2, error:%d\n", ret);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/* Initial DC pointer can be NULL if IOMMU is configured in OFF or BARE mode */
|
||||
riscv_iommu_get_dc(ep->iommu, ep);
|
||||
|
||||
printk(KERN_CONT "adding device with devid ");
|
||||
for (i = 0; i < ep->num_ids; i++) {
|
||||
printk(KERN_CONT "%i ", ep->devids[i]);
|
||||
}
|
||||
printk(KERN_CONT "in domain %i\n", ep->domid);
|
||||
printk(KERN_CONT "to %s iommu\n", ep->iommu->name);
|
||||
|
||||
dev_iommu_priv_set(dev, ep);
|
||||
riscv_iommu_add_device(iommu, dev);
|
||||
riscv_iommu_add_device(ep->iommu, dev);
|
||||
|
||||
return &iommu->iommu;
|
||||
return &iommus->iommu;
|
||||
}
|
||||
|
||||
static void riscv_iommu_probe_finalize(struct device *dev)
|
||||
@@ -763,7 +812,7 @@ static void riscv_iommu_release_device(struct device *dev)
|
||||
dma_wmb();
|
||||
ep->dc[i]->fsc = 0ULL;
|
||||
dma_wmb();
|
||||
riscv_iommu_iodir_inv_devid(iommu, ep->devids[i]);
|
||||
riscv_iommu_iodir_inv_devid(ep->iommus, ep->devids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -778,9 +827,59 @@ static void riscv_iommu_release_device(struct device *dev)
|
||||
kfree(ep);
|
||||
}
|
||||
|
||||
static void riscv_iommu_group_release(void *iommu_data)
|
||||
{
|
||||
struct riscv_iommu_group *group = iommu_data;
|
||||
struct zh_iommu_device *iommus = group->iommus;
|
||||
|
||||
mutex_lock(&iommus->lock);
|
||||
list_del(&group->list);
|
||||
mutex_unlock(&iommus->lock);
|
||||
}
|
||||
|
||||
static char * riscv_iommu_group_names[] = {"IOMMU_GROUP_PER_DEV", "IOMMU_GROUP_VIDEO", "IOMMU_GROUP_NPU"};
|
||||
|
||||
static struct iommu_group *riscv_iommu_device_group(struct device *dev)
|
||||
{
|
||||
return generic_device_group(dev);
|
||||
struct riscv_iommu_endpoint *ep = dev_iommu_priv_get(dev);
|
||||
struct zh_iommu_device *iommus = ep->iommus;
|
||||
struct riscv_iommu_group *group;
|
||||
struct iommu_group *grp;
|
||||
|
||||
mutex_lock(&iommus->lock);
|
||||
|
||||
/* Find if desired group existed in the list of riscv_iommu_device */
|
||||
list_for_each_entry(group, &iommus->groups, list) {
|
||||
if (group->group_id == ep->group_id && ep->group_id != IOMMU_GROUP_PER_DEV) {
|
||||
grp = iommu_group_ref_get(group->group);
|
||||
mutex_unlock(&iommus->lock);
|
||||
return grp;
|
||||
}
|
||||
}
|
||||
|
||||
group = devm_kzalloc(iommus->dev, sizeof(*group), GFP_KERNEL);
|
||||
if (!group) {
|
||||
mutex_unlock(&iommus->lock);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&group->list);
|
||||
group->iommus = iommus;
|
||||
group->group_id = ep->group_id;
|
||||
group->group = generic_device_group(dev);
|
||||
|
||||
if (IS_ERR(group->group)) {
|
||||
devm_kfree(iommus->dev, group);
|
||||
mutex_unlock(&iommus->lock);
|
||||
return group->group;
|
||||
}
|
||||
|
||||
iommu_group_set_iommudata(group->group, group, riscv_iommu_group_release);
|
||||
iommu_group_set_name(group->group, riscv_iommu_group_names[group->group_id]);
|
||||
list_add_tail(&group->list, &iommus->groups);
|
||||
mutex_unlock(&iommus->lock);
|
||||
|
||||
return group->group;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -811,7 +910,7 @@ static struct iommu_domain *riscv_iommu_domain_alloc(unsigned type)
|
||||
domain->pscid = ida_alloc_range(&riscv_iommu_pscids, 1,
|
||||
RISCV_IOMMU_MAX_PSCID, GFP_KERNEL);
|
||||
|
||||
printk("domain alloc %u\n", domain->pscid);
|
||||
printk("domain->pscid alloc %u\n", domain->pscid);
|
||||
|
||||
return &domain->domain;
|
||||
}
|
||||
@@ -839,15 +938,15 @@ static void riscv_iommu_domain_free(struct iommu_domain *iommu_domain)
|
||||
}
|
||||
|
||||
static int riscv_iommu_domain_finalize(struct riscv_iommu_domain *domain,
|
||||
struct riscv_iommu_device *iommu)
|
||||
struct zh_iommu_device *iommus)
|
||||
{
|
||||
struct iommu_domain_geometry *geometry;
|
||||
|
||||
/* Domain assigned to another iommu */
|
||||
if (domain->iommu && domain->iommu != iommu)
|
||||
if (domain->iommus && domain->iommus != iommus)
|
||||
return -EINVAL;
|
||||
/* Domain already initialized */
|
||||
else if (domain->iommu)
|
||||
else if (domain->iommus)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@@ -871,8 +970,7 @@ static int riscv_iommu_domain_finalize(struct riscv_iommu_domain *domain,
|
||||
geometry->aperture_end = DMA_BIT_MASK(VA_BITS - 1);
|
||||
geometry->force_aperture = true;
|
||||
|
||||
domain->iommu = iommu;
|
||||
iommu->domain = domain;
|
||||
domain->iommus = iommus;
|
||||
|
||||
if (domain->domain.type == IOMMU_DOMAIN_IDENTITY)
|
||||
return 0;
|
||||
@@ -919,7 +1017,7 @@ static int riscv_iommu_attach_dev(struct iommu_domain *iommu_domain, struct devi
|
||||
}
|
||||
|
||||
/* allocate root pages, initialize io-pgtable ops, etc. */
|
||||
ret = riscv_iommu_domain_finalize(domain, ep->iommu);
|
||||
ret = riscv_iommu_domain_finalize(domain, ep->iommus);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "can not finalize domain: %d\n", ret);
|
||||
mutex_unlock(&ep->lock);
|
||||
@@ -935,23 +1033,23 @@ static int riscv_iommu_attach_dev(struct iommu_domain *iommu_domain, struct devi
|
||||
}
|
||||
|
||||
for (i = 0; i < ep->num_ids; i++) {
|
||||
if (!ep->dc[i])
|
||||
return -ENODEV;
|
||||
if (!ep->dc[i])
|
||||
return -ENODEV;
|
||||
|
||||
/* S-Stage translation table only. G-Stage not supported. */
|
||||
val = FIELD_PREP(RISCV_IOMMU_DC_TA_PSCID, domain->pscid);
|
||||
ep->dc[i]->ta = cpu_to_le64(val);
|
||||
ep->dc[i]->fsc = cpu_to_le64(riscv_iommu_domain_atp(domain));
|
||||
/* S-Stage translation table only. G-Stage not supported. */
|
||||
val = FIELD_PREP(RISCV_IOMMU_DC_TA_PSCID, domain->pscid);
|
||||
ep->dc[i]->ta = cpu_to_le64(val);
|
||||
ep->dc[i]->fsc = cpu_to_le64(riscv_iommu_domain_atp(domain));
|
||||
|
||||
dma_wmb();
|
||||
dma_wmb();
|
||||
|
||||
/* Mark device context as valid, synchronise device context cache. */
|
||||
val = RISCV_IOMMU_DC_TC_V;
|
||||
ep->dc[i]->tc = cpu_to_le64(val);
|
||||
dma_wmb();
|
||||
arch_sync_dma_for_device(__pa(ep->dc[i]), SZ_4K, DMA_TO_DEVICE); // flush LV2 DDT
|
||||
printk("%s flush cache for LV2 DDT pa=0x%lx\n", __func__, __pa(ep->dc[i]));
|
||||
riscv_iommu_iodir_inv_devid(ep->iommu, ep->devids[i]);
|
||||
/* Mark device context as valid, synchronise device context cache. */
|
||||
val = RISCV_IOMMU_DC_TC_V;
|
||||
ep->dc[i]->tc = cpu_to_le64(val);
|
||||
dma_wmb();
|
||||
arch_sync_dma_for_device(__pa(ep->dc[i]), SZ_4K, DMA_TO_DEVICE); // flush LV2 DDT
|
||||
printk("%s flush cache for LV2 DDT pa=0x%lx\n", __func__, __pa(ep->dc[i]));
|
||||
riscv_iommu_iodir_inv_devid(ep->iommus, ep->devids[i]);
|
||||
}
|
||||
|
||||
list_add_tail(&ep->domain, &domain->endpoints);
|
||||
@@ -978,7 +1076,7 @@ void riscv_iommu_flush_iotlb_range(struct iommu_domain *iommu_domain,
|
||||
return;
|
||||
|
||||
/* Domain not attached to an IOMMU! */
|
||||
BUG_ON(!domain->iommu);
|
||||
BUG_ON(!domain->iommus);
|
||||
|
||||
riscv_iommu_cmd_inval_vma(&cmd);
|
||||
riscv_iommu_cmd_inval_set_pscid(&cmd, domain->pscid);
|
||||
@@ -988,12 +1086,12 @@ void riscv_iommu_flush_iotlb_range(struct iommu_domain *iommu_domain,
|
||||
for (iova = *start; iova <= *end; iova += *pgsize) {
|
||||
//printk("riscv_iommu_cmd_inval_set_addr iova = 0x%lx\n", iova);
|
||||
riscv_iommu_cmd_inval_set_addr(&cmd, iova);
|
||||
riscv_iommu_post(domain->iommu, &cmd);
|
||||
riscv_iommu_post(domain->iommus, &cmd);
|
||||
}
|
||||
} else {
|
||||
riscv_iommu_post(domain->iommu, &cmd);
|
||||
riscv_iommu_post(domain->iommus, &cmd);
|
||||
}
|
||||
riscv_iommu_iofence_sync(domain->iommu);
|
||||
riscv_iommu_iofence_sync(domain->iommus);
|
||||
}
|
||||
|
||||
static void riscv_iommu_flush_iotlb_all(struct iommu_domain *iommu_domain)
|
||||
@@ -1035,7 +1133,7 @@ static int riscv_iommu_map_pages(struct iommu_domain *iommu_domain,
|
||||
ret = domain->pgtbl.ops.map_pages(&domain->pgtbl.ops, iova, phys,
|
||||
pgsize, pgcount, prot, gfp, mapped);
|
||||
|
||||
dev_dbg(domain->iommu->dev, "LV3 target pa = 0x%llx\n", domain->pgtbl.ops.iova_to_phys(&domain->pgtbl.ops, iova));
|
||||
dev_dbg(domain->iommus->dev, "LV3 target pa = 0x%llx\n", domain->pgtbl.ops.iova_to_phys(&domain->pgtbl.ops, iova));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1136,12 +1234,12 @@ static int riscv_iommu_enable(struct riscv_iommu_device *iommu, unsigned request
|
||||
}
|
||||
|
||||
mode_readback = FIELD_GET(RISCV_IOMMU_DDTP_MODE, ddtp);
|
||||
dev_info(dev, "mode_readback: %i, mode: %i\n", mode_readback, mode);
|
||||
dev_info(dev, "%s iommu mode_readback: %i, mode: %i\n", iommu->name, mode_readback, mode);
|
||||
if (mode_readback != mode)
|
||||
goto fail;
|
||||
|
||||
iommu->ddt_mode = mode;
|
||||
dev_info(dev, "ddt_mode: %i\n", iommu->ddt_mode);
|
||||
dev_info(dev, "%s iommu ddt_mode: %i\n", iommu->name, iommu->ddt_mode);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -1179,18 +1277,21 @@ static const struct iommu_ops riscv_iommu_ops = {
|
||||
.default_domain_ops = &riscv_iommu_domain_ops,
|
||||
};
|
||||
|
||||
void riscv_iommu_remove(struct riscv_iommu_device *iommu)
|
||||
void riscv_iommu_remove(struct zh_iommu_device *iommus)
|
||||
{
|
||||
iommu_device_unregister(&iommu->iommu);
|
||||
iommu_device_sysfs_remove(&iommu->iommu);
|
||||
riscv_iommu_enable(iommu, RISCV_IOMMU_DDTP_MODE_OFF);
|
||||
riscv_iommu_queue_free(iommu, &iommu->fltq);
|
||||
riscv_iommu_queue_free(iommu, &iommu->cmdq);
|
||||
struct riscv_iommu_device *iommu;
|
||||
|
||||
iommu_device_unregister(&iommus->iommu);
|
||||
iommu_device_sysfs_remove(&iommus->iommu);
|
||||
list_for_each_entry(iommu, &iommus->iommus, list) {
|
||||
riscv_iommu_enable(iommu, RISCV_IOMMU_DDTP_MODE_OFF);
|
||||
riscv_iommu_queue_free(iommu, &iommu->fltq);
|
||||
riscv_iommu_queue_free(iommu, &iommu->cmdq);
|
||||
}
|
||||
}
|
||||
|
||||
int riscv_iommu_init(struct riscv_iommu_device *iommu)
|
||||
{
|
||||
struct device *dev = iommu->dev;
|
||||
int ret;
|
||||
|
||||
iommu->eps = RB_ROOT;
|
||||
@@ -1217,19 +1318,6 @@ int riscv_iommu_init(struct riscv_iommu_device *iommu)
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
ret = riscv_iommu_sysfs_add(iommu);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot register sysfs interface (%d)\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = iommu_device_register(&iommu->iommu, &riscv_iommu_ops, dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot register iommu interface (%d)\n", ret);
|
||||
iommu_device_sysfs_remove(&iommu->iommu);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
riscv_iommu_enable(iommu, RISCV_IOMMU_DDTP_MODE_OFF);
|
||||
@@ -1237,3 +1325,24 @@ int riscv_iommu_init(struct riscv_iommu_device *iommu)
|
||||
riscv_iommu_queue_free(iommu, &iommu->cmdq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int riscv_iommu_register(struct zh_iommu_device *iommus)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iommu_device_sysfs_add(&iommus->iommu, NULL,
|
||||
NULL, "zhihe-iommu");
|
||||
if (ret) {
|
||||
dev_err(iommus->dev, "cannot register sysfs interface (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iommu_device_register(&iommus->iommu, &riscv_iommu_ops, iommus->dev);
|
||||
if (ret) {
|
||||
dev_err(iommus->dev, "cannot register iommu interface (%d)\n", ret);
|
||||
iommu_device_sysfs_remove(&iommus->iommu);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -46,9 +46,23 @@ enum riscv_queue_ids {
|
||||
RISCV_IOMMU_PAGE_REQUEST_QUEUE = 2
|
||||
};
|
||||
|
||||
struct riscv_iommu_device {
|
||||
/* virtual iommu device representing all the real iommu hardware IPs and register to kernel iommu framework */
|
||||
struct zh_iommu_device {
|
||||
struct iommu_device iommu; /* iommu core interface */
|
||||
struct device *dev; /* iommu hardware */
|
||||
struct list_head groups; /* struct riscv_iommu_group{} existed */
|
||||
struct list_head iommus; /* struct riscv_iommu_device{} for individual iommu IPs existed*/
|
||||
struct mutex lock; /* protect modification of member: groups,iommus */
|
||||
struct device **pd_devs;
|
||||
int num_pds;
|
||||
struct clk_bulk_data *clks;
|
||||
u32 num_clks;
|
||||
};
|
||||
|
||||
/* real iommu hardware IP */
|
||||
struct riscv_iommu_device {
|
||||
struct device *dev; /* iommu hardware */
|
||||
char *name;
|
||||
|
||||
/* hardware control register space */
|
||||
void __iomem *reg;
|
||||
@@ -79,7 +93,7 @@ struct riscv_iommu_device {
|
||||
struct rb_root eps;
|
||||
struct mutex eps_mutex;
|
||||
|
||||
struct riscv_iommu_domain *domain;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct riscv_iommu_domain {
|
||||
@@ -90,7 +104,7 @@ struct riscv_iommu_domain {
|
||||
struct list_head notifiers;
|
||||
struct mutex lock;
|
||||
struct mmu_notifier mn;
|
||||
struct riscv_iommu_device *iommu;
|
||||
struct zh_iommu_device *iommus;
|
||||
|
||||
unsigned mode; /* RIO_ATP_MODE_* enum */
|
||||
unsigned pscid; /* RISC-V IOMMU PSCID / GSCID */
|
||||
@@ -104,11 +118,21 @@ struct riscv_iommu_endpoint {
|
||||
unsigned num_ids;
|
||||
unsigned domid; /* PCI domain number, segment */
|
||||
struct rb_node node; /* device tracking node (lookup by devid) */
|
||||
struct riscv_iommu_device *iommu; /* parent iommu device */
|
||||
struct zh_iommu_device *iommus; /* virtual iommu device */
|
||||
struct riscv_iommu_device *iommu; /* real parent iommu device */
|
||||
struct mutex lock;
|
||||
struct list_head domain; /* endpoint attached managed domain */
|
||||
struct riscv_iommu_dc **dc; /* device context pointer entries */
|
||||
u32 *devids; /* PCI bus:device:function number */
|
||||
unsigned int group_id; /* desire to join which iommu_group */
|
||||
};
|
||||
|
||||
/* include one instance of struct iommu_group and it's managing tools */
|
||||
struct riscv_iommu_group {
|
||||
struct list_head list;
|
||||
struct zh_iommu_device *iommus;
|
||||
struct iommu_group *group;
|
||||
unsigned int group_id;
|
||||
};
|
||||
|
||||
/* Helper functions and macros */
|
||||
@@ -138,8 +162,9 @@ static inline void riscv_iommu_writeq(struct riscv_iommu_device *iommu,
|
||||
}
|
||||
|
||||
int riscv_iommu_init(struct riscv_iommu_device *iommu);
|
||||
void riscv_iommu_remove(struct riscv_iommu_device *iommu);
|
||||
void riscv_iommu_remove(struct zh_iommu_device *iommus);
|
||||
|
||||
int riscv_iommu_sysfs_add(struct riscv_iommu_device *iommu);
|
||||
int riscv_iommu_sysfs_add(struct zh_iommu_device *iommus);
|
||||
int riscv_iommu_register(struct zh_iommu_device *iommus);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#define ZHIHE_MBOX_V1 0x0
|
||||
#define ZHIHE_MBOX_V2 0x1
|
||||
@@ -100,6 +101,7 @@ struct zhihe_mbox_priv {
|
||||
|
||||
struct zhihe_mbox_con_priv con_priv[ZHIHE_MBOX_CHANS];
|
||||
struct clk *clk;
|
||||
struct reset_control *reset;
|
||||
int irq;
|
||||
int version;
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
@@ -569,6 +571,15 @@ static int zhihe_mbox_probe(struct platform_device *pdev)
|
||||
dev_err(dev, "Failed to enable clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->reset = of_reset_control_array_get_optional_exclusive(np);
|
||||
if (IS_ERR(priv->reset)) {
|
||||
dev_err(dev, "failed to get reset return %ld\n", PTR_ERR(priv->reset));
|
||||
return PTR_ERR(priv->reset);
|
||||
}
|
||||
reset_control_assert(priv->reset);
|
||||
reset_control_deassert(priv->reset);
|
||||
|
||||
/* init the chans */
|
||||
if (priv->version == ZHIHE_MBOX_V1) {
|
||||
for (i = 0; i < ZHIHE_MBOX_CHANS; i++) {
|
||||
|
||||
@@ -490,24 +490,63 @@ static void th1520_set_uhs_signaling(struct sdhci_host *host,
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
|
||||
struct th1520_priv *th_priv = priv->th_priv;
|
||||
u32 val;
|
||||
|
||||
dwcmshc_set_uhs_signaling(host, timing);
|
||||
|
||||
pr_debug("%s: %s timing %d\n",host->hw_name,__func__,timing);
|
||||
if (timing == MMC_TIMING_MMC_HS400) {
|
||||
//disable auto tuning
|
||||
u32 reg = sdhci_readl(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
reg &= ~AT_CTRL_AT_EN;
|
||||
sdhci_writel(host, reg, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
/* Disable auto tuning */
|
||||
val = sdhci_readl(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
val &= ~AT_CTRL_AT_EN;
|
||||
sdhci_writel(host, val, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
|
||||
priv->delay_line = th_priv->delay_line[MMC_TIMING_MMC_HS400];
|
||||
th1520_sdhci_set_phy(host); /* update tx delay*/
|
||||
} else if(timing == MMC_TIMING_MMC_HS200) {
|
||||
priv->delay_line = th_priv->delay_line[MMC_TIMING_MMC_HS200];
|
||||
} else if(timing == MMC_TIMING_UHS_SDR104) {
|
||||
priv->delay_line = th_priv->delay_line[MMC_TIMING_UHS_SDR104];
|
||||
th1520_sdhci_set_phy(host); /* update tx delay*/
|
||||
sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R);
|
||||
/* Update tx delay */
|
||||
priv->delay_line = th_priv->delay_line[timing];
|
||||
th1520_sdhci_set_phy(host);
|
||||
} else if((timing == MMC_TIMING_MMC_HS200) | (timing == MMC_TIMING_UHS_SDR104)) {
|
||||
/*
|
||||
* Default count=MAX_TUNING_LOOP(40),
|
||||
* th1520 device Must be configured to 128.
|
||||
*/
|
||||
host->tuning_loop_count = 128;
|
||||
|
||||
/* Drives drift_cclk_rx DelayLine's config input. */
|
||||
sdhci_writeb(host, FIELD_PREP(PHY_ATDL_CNFG_INPSEL_MASK, PHY_ATDL_CNFG_INPSEL), PHY_ATDL_CNFG_R);
|
||||
|
||||
/*
|
||||
* Clear tuning settings:
|
||||
* - center phase select code driven in block gap interval
|
||||
* - disable reporting of framing errors
|
||||
* - disable software managed tuning
|
||||
* - disable sampling window threshold
|
||||
* Choose largest sampling window tuning schema, do not care AT_CTRL_SWIN_TH_VAL
|
||||
* - disable user selection of sampling window edges,
|
||||
* instead tuning calculated edges are used
|
||||
*/
|
||||
val = sdhci_readl(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
val &= ~(AT_CTRL_CI_SEL | AT_CTRL_RPT_TUNE_ERR | AT_CTRL_SW_TUNE_EN | AT_CTRL_SWIN_TH_EN |
|
||||
AT_CTRL_WIN_EDGE_SEL_MASK | AT_CTRL_SWIN_TH_VAL_MASK);
|
||||
|
||||
/*
|
||||
* Configure tuning settings:
|
||||
* - enable auto-tuning
|
||||
* - stop clocks during phase code change
|
||||
* - set max latency in cycles between tx and rx clocks
|
||||
* - set max latency in cycles to switch output phase
|
||||
* - set max sampling window threshold value
|
||||
*/
|
||||
val |= AT_CTRL_AT_EN | AT_CTRL_TUNE_CLK_STOP_EN;
|
||||
val |= FIELD_PREP(AT_CTRL_PRE_CHANGE_DLY_MASK, AT_CTRL_PRE_CHANGE_DLY);
|
||||
val |= FIELD_PREP(AT_CTRL_POST_CHANGE_DLY_MASK, AT_CTRL_POST_CHANGE_DLY);
|
||||
sdhci_writel(host, val, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
|
||||
/* Update tx delay */
|
||||
priv->delay_line = th_priv->delay_line[timing];
|
||||
th1520_sdhci_set_phy(host);
|
||||
if (timing == MMC_TIMING_UHS_SDR104) {
|
||||
sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R);
|
||||
}
|
||||
} else {
|
||||
sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R);
|
||||
if(th_priv->rxclk_sw_tune_en && (timing == MMC_TIMING_SD_HS)) {
|
||||
@@ -662,66 +701,6 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
|
||||
sdhci_reset(host, mask);
|
||||
}
|
||||
|
||||
static int th1520_execute_tuning(struct sdhci_host *host, u32 opcode)
|
||||
{
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
|
||||
u32 val = 0;
|
||||
|
||||
if (host->flags & SDHCI_HS400_TUNING)
|
||||
return 0;
|
||||
|
||||
sdhci_writeb(host, FIELD_PREP(PHY_ATDL_CNFG_INPSEL_MASK, PHY_ATDL_CNFG_INPSEL),
|
||||
PHY_ATDL_CNFG_R);
|
||||
val = sdhci_readl(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
|
||||
/*
|
||||
* configure tuning settings:
|
||||
* - center phase select code driven in block gap interval
|
||||
* - disable reporting of framing errors
|
||||
* - disable software managed tuning
|
||||
* - disable user selection of sampling window edges,
|
||||
* instead tuning calculated edges are used
|
||||
*/
|
||||
val &= ~(AT_CTRL_CI_SEL | AT_CTRL_RPT_TUNE_ERR | AT_CTRL_SW_TUNE_EN |
|
||||
FIELD_PREP(AT_CTRL_WIN_EDGE_SEL_MASK, AT_CTRL_WIN_EDGE_SEL));
|
||||
|
||||
/*
|
||||
* configure tuning settings:
|
||||
* - enable auto-tuning
|
||||
* - enable sampling window threshold
|
||||
* - stop clocks during phase code change
|
||||
* - set max latency in cycles between tx and rx clocks
|
||||
* - set max latency in cycles to switch output phase
|
||||
* - set max sampling window threshold value
|
||||
*/
|
||||
val |= AT_CTRL_AT_EN | AT_CTRL_SWIN_TH_EN | AT_CTRL_TUNE_CLK_STOP_EN;
|
||||
val |= FIELD_PREP(AT_CTRL_PRE_CHANGE_DLY_MASK, AT_CTRL_PRE_CHANGE_DLY);
|
||||
val |= FIELD_PREP(AT_CTRL_POST_CHANGE_DLY_MASK, AT_CTRL_POST_CHANGE_DLY);
|
||||
val |= FIELD_PREP(AT_CTRL_SWIN_TH_VAL_MASK, AT_CTRL_SWIN_TH_VAL);
|
||||
|
||||
sdhci_writel(host, val, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
val = sdhci_readl(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
|
||||
host->tuning_loop_count = 128; /*max loop count allow to 128*/
|
||||
|
||||
val &= ~AT_CTRL_AT_EN;
|
||||
sdhci_writel(host, val, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
|
||||
/* perform tuning */
|
||||
sdhci_start_tuning(host);
|
||||
host->tuning_err = __sdhci_execute_tuning(host, opcode);
|
||||
if (host->tuning_err) {
|
||||
/* disable auto-tuning upon tuning error */
|
||||
val &= ~AT_CTRL_AT_EN;
|
||||
sdhci_writel(host, val, priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
dev_err(mmc_dev(host->mmc), "tuning failed: %d\n", host->tuning_err);
|
||||
return -EIO;
|
||||
}
|
||||
sdhci_end_tuning(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void th1520_sdhci_reset(struct sdhci_host *host, u8 mask)
|
||||
{
|
||||
@@ -914,7 +893,6 @@ static const struct sdhci_ops sdhci_dwcmshc_th1520_ops = {
|
||||
.get_ro = th1520_sdhci_get_ro,
|
||||
.adma_write_desc = dwcmshc_adma_write_desc,
|
||||
.voltage_switch = dwcmshc_phy_1_8v_init,
|
||||
.platform_execute_tuning = &th1520_execute_tuning,
|
||||
};
|
||||
|
||||
static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
|
||||
@@ -950,7 +928,7 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_th1520_pdata = {
|
||||
static const struct sdhci_pltfm_data sdhci_dwcmshc_a210_pdata = {
|
||||
.ops = &sdhci_dwcmshc_th1520_ops,
|
||||
.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
|
||||
SDHCI_QUIRK_SINGLE_POWER_WRITE | SDHCI_QUIRK_BROKEN_ADMA,
|
||||
SDHCI_QUIRK_SINGLE_POWER_WRITE,
|
||||
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
|
||||
};
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ int zhihe_dwmac_clk_enable(struct platform_device *pdev, void *bsp_priv)
|
||||
|
||||
int zhihe_dwmac_clk_init(struct platform_device *pdev, void *bsp_priv)
|
||||
{
|
||||
struct zhihe_dwmac_priv_data *zhihe_plat_dat = bsp_priv;
|
||||
struct zhihe_dwmac_priv_data *zhihe_plat_dat = bsp_priv;
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret = 0;
|
||||
unsigned int reg = 0;
|
||||
@@ -475,7 +475,7 @@ static struct zhihe_dwmac_ops zhihe_dwmac_data = {
|
||||
};
|
||||
|
||||
static const struct of_device_id zhihe_dwmac_match[] = {
|
||||
{ .compatible = "zhihe,p100-dwmac", .data = &zhihe_dwmac_data },
|
||||
{ .compatible = "zhihe,a210-dwmac", .data = &zhihe_dwmac_data },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, zhihe_dwmac_match);
|
||||
|
||||
@@ -370,7 +370,7 @@ static bool nvme_dbbuf_update_and_check_event(u16 value, __le32 *dbbuf_db,
|
||||
* ordering to ensure the envent index is updated before reading
|
||||
* the doorbell.
|
||||
*/
|
||||
mb();
|
||||
dma_mb();
|
||||
|
||||
event_idx = le32_to_cpu(*dbbuf_ei);
|
||||
if (!nvme_dbbuf_need_event(event_idx, value, old_value))
|
||||
@@ -858,7 +858,7 @@ static blk_status_t nvme_prep_rq(struct nvme_dev *dev, struct request *req)
|
||||
if (ret)
|
||||
goto out_unmap_data;
|
||||
}
|
||||
|
||||
dma_mb();
|
||||
nvme_start_request(req);
|
||||
return BLK_STS_OK;
|
||||
out_unmap_data:
|
||||
|
||||
@@ -1139,7 +1139,7 @@ static const struct attribute_group dev_attr_efuse_sysfs_group = {
|
||||
};
|
||||
|
||||
static const struct of_device_id zh_efuse_of_match[] = {
|
||||
{.compatible = "zhihe,p100-fm-efuse"},
|
||||
{.compatible = "zhihe,a210-fm-efuse"},
|
||||
{ /* sentinel */},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, zh_efuse_of_match);
|
||||
@@ -1165,7 +1165,7 @@ static int __maybe_unused zh_efuse_runtime_suspend(struct device *dev)
|
||||
|
||||
dev_dbg(dev, "[%s,%d] ret = %d, pd status: 0x%lx\n", __func__, __LINE__, ret,
|
||||
readl(priv->base + CON) & EFUSE_CON_POWER_MSK);
|
||||
|
||||
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
return ret;
|
||||
@@ -1183,7 +1183,7 @@ static int __maybe_unused zh_efuse_runtime_resume(struct device *dev)
|
||||
dev_err(dev, "failed to get efuse clk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
return efuse_poweron(priv->base);
|
||||
}
|
||||
|
||||
@@ -1208,7 +1208,7 @@ static int __maybe_unused zh_efuse_suspend(struct device *dev)
|
||||
|
||||
dev_dbg(dev, "[%s,%d] ret = %d, pd status: 0x%lx\n", __func__, __LINE__, ret,
|
||||
readl(priv->base + CON) & EFUSE_CON_POWER_MSK);
|
||||
|
||||
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
return ret;
|
||||
@@ -1226,7 +1226,7 @@ static int __maybe_unused zh_efuse_resume(struct device *dev)
|
||||
dev_err(dev, "failed to get efuse clk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
return efuse_poweron(priv->base);
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ int dw_pcie_get_resources(struct dw_pcie *pci)
|
||||
pci->dbi_base = devm_pci_remap_cfg_resource(pci->dev, res);
|
||||
if (IS_ERR(pci->dbi_base))
|
||||
return PTR_ERR(pci->dbi_base);
|
||||
pci->dbi_phys_addr = res->start;
|
||||
}
|
||||
|
||||
/* DBI2 is mainly useful for the endpoint controller */
|
||||
@@ -155,6 +156,16 @@ int dw_pcie_get_resources(struct dw_pcie *pci)
|
||||
}
|
||||
}
|
||||
|
||||
/* ELBI is an optional resource */
|
||||
if (!pci->elbi_base) {
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
|
||||
if (res) {
|
||||
pci->elbi_base = devm_ioremap_resource(pci->dev, res);
|
||||
if (IS_ERR(pci->elbi_base))
|
||||
return PTR_ERR(pci->elbi_base);
|
||||
}
|
||||
}
|
||||
|
||||
/* LLDD is supposed to manually switch the clocks and resets state */
|
||||
if (dw_pcie_cap_is(pci, REQ_RES)) {
|
||||
ret = dw_pcie_get_clocks(pci);
|
||||
@@ -365,6 +376,7 @@ void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val)
|
||||
if (ret)
|
||||
dev_err(pci->dev, "write DBI address failed\n");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_pcie_write_dbi2);
|
||||
|
||||
static inline void __iomem *dw_pcie_select_atu(struct dw_pcie *pci, u32 dir,
|
||||
u32 index)
|
||||
@@ -880,7 +892,7 @@ static int dw_pcie_edma_irq_verify(struct dw_pcie *pci)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(pci->dev);
|
||||
u16 ch_cnt = pci->edma.ll_wr_cnt + pci->edma.ll_rd_cnt;
|
||||
char name[6];
|
||||
char name[15];
|
||||
int ret;
|
||||
|
||||
if (pci->edma.nr_irqs == 1)
|
||||
|
||||
@@ -70,6 +70,9 @@
|
||||
#define LINK_WAIT_IATU 9
|
||||
|
||||
/* Synopsys-specific PCIe configuration registers */
|
||||
#define PCIE_PORT_FORCE 0x708
|
||||
#define PORT_FORCE_DO_DESKEW_FOR_SRIS BIT(23)
|
||||
|
||||
#define PCIE_PORT_AFR 0x70C
|
||||
#define PORT_AFR_N_FTS_MASK GENMASK(15, 8)
|
||||
#define PORT_AFR_N_FTS(n) FIELD_PREP(PORT_AFR_N_FTS_MASK, n)
|
||||
@@ -90,9 +93,13 @@
|
||||
#define PORT_LINK_MODE_2_LANES PORT_LINK_MODE(0x3)
|
||||
#define PORT_LINK_MODE_4_LANES PORT_LINK_MODE(0x7)
|
||||
#define PORT_LINK_MODE_8_LANES PORT_LINK_MODE(0xf)
|
||||
#define PORT_LINK_MODE_16_LANES PORT_LINK_MODE(0x1f)
|
||||
|
||||
#define PCIE_PORT_LANE_SKEW 0x714
|
||||
#define PORT_LANE_SKEW_INSERT_MASK GENMASK(23, 0)
|
||||
|
||||
#define PCIE_PORT_DEBUG0 0x728
|
||||
#define PORT_LOGIC_LTSSM_STATE_MASK 0x1f
|
||||
#define PORT_LOGIC_LTSSM_STATE_MASK 0x3f
|
||||
#define PORT_LOGIC_LTSSM_STATE_L0 0x11
|
||||
#define PCIE_PORT_DEBUG1 0x72C
|
||||
#define PCIE_PORT_DEBUG1_LINK_UP BIT(4)
|
||||
@@ -116,11 +123,31 @@
|
||||
|
||||
#define GEN3_RELATED_OFF 0x890
|
||||
#define GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL BIT(0)
|
||||
#define GEN3_RELATED_OFF_EQ_PHASE_2_3 BIT(9)
|
||||
#define GEN3_RELATED_OFF_RXEQ_RGRDLESS_RXTS BIT(13)
|
||||
#define GEN3_RELATED_OFF_GEN3_EQ_DISABLE BIT(16)
|
||||
#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT 24
|
||||
#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK GENMASK(25, 24)
|
||||
|
||||
#define GEN3_EQ_CONTROL_OFF 0x8A8
|
||||
#define GEN3_EQ_CONTROL_OFF_FB_MODE GENMASK(3, 0)
|
||||
#define GEN3_EQ_CONTROL_OFF_PHASE23_EXIT_MODE BIT(4)
|
||||
#define GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC GENMASK(23, 8)
|
||||
#define GEN3_EQ_CONTROL_OFF_FOM_INC_INITIAL_EVAL BIT(24)
|
||||
|
||||
#define GEN3_EQ_FB_MODE_DIR_CHANGE_OFF 0x8AC
|
||||
#define GEN3_EQ_FMDC_T_MIN_PHASE23 GENMASK(4, 0)
|
||||
#define GEN3_EQ_FMDC_N_EVALS GENMASK(9, 5)
|
||||
#define GEN3_EQ_FMDC_MAX_PRE_CURSOR_DELTA GENMASK(13, 10)
|
||||
#define GEN3_EQ_FMDC_MAX_POST_CURSOR_DELTA GENMASK(17, 14)
|
||||
|
||||
#define COHERENCY_CONTROL_1_OFF 0x8E0
|
||||
#define CFG_MEMTYPE_BOUNDARY_LOW_ADDR_MASK GENMASK(31, 2)
|
||||
#define CFG_MEMTYPE_VALUE BIT(0)
|
||||
|
||||
#define COHERENCY_CONTROL_2_OFF 0x8E4
|
||||
#define COHERENCY_CONTROL_3_OFF 0x8E8
|
||||
|
||||
#define PCIE_PORT_MULTI_LANE_CTRL 0x8C0
|
||||
#define PORT_MLTI_UPCFG_SUPPORT BIT(7)
|
||||
|
||||
@@ -147,11 +174,14 @@
|
||||
#define PCIE_ATU_TYPE_IO 0x2
|
||||
#define PCIE_ATU_TYPE_CFG0 0x4
|
||||
#define PCIE_ATU_TYPE_CFG1 0x5
|
||||
#define PCIE_ATU_TYPE_MSG 0x10
|
||||
#define PCIE_ATU_TD BIT(8)
|
||||
#define PCIE_ATU_FUNC_NUM(pf) ((pf) << 20)
|
||||
#define PCIE_ATU_REGION_CTRL2 0x004
|
||||
#define PCIE_ATU_ENABLE BIT(31)
|
||||
#define PCIE_ATU_BAR_MODE_ENABLE BIT(30)
|
||||
#define PCIE_ATU_CFG_SHIFT_MODE_ENABLE BIT(28)
|
||||
#define PCIE_ATU_INHIBIT_PAYLOAD BIT(22)
|
||||
#define PCIE_ATU_FUNC_NUM_MATCH_EN BIT(19)
|
||||
#define PCIE_ATU_LOWER_BASE 0x008
|
||||
#define PCIE_ATU_UPPER_BASE 0x00C
|
||||
@@ -190,6 +220,24 @@
|
||||
|
||||
#define PCIE_PL_CHK_REG_ERR_ADDR 0xB28
|
||||
|
||||
/*
|
||||
* 16.0 GT/s (Gen 4) lane margining register definitions
|
||||
*/
|
||||
#define GEN4_LANE_MARGINING_1_OFF 0xB80
|
||||
#define MARGINING_MAX_VOLTAGE_OFFSET GENMASK(29, 24)
|
||||
#define MARGINING_NUM_VOLTAGE_STEPS GENMASK(22, 16)
|
||||
#define MARGINING_MAX_TIMING_OFFSET GENMASK(13, 8)
|
||||
#define MARGINING_NUM_TIMING_STEPS GENMASK(5, 0)
|
||||
|
||||
#define GEN4_LANE_MARGINING_2_OFF 0xB84
|
||||
#define MARGINING_IND_ERROR_SAMPLER BIT(28)
|
||||
#define MARGINING_SAMPLE_REPORTING_METHOD BIT(27)
|
||||
#define MARGINING_IND_LEFT_RIGHT_TIMING BIT(26)
|
||||
#define MARGINING_IND_UP_DOWN_VOLTAGE BIT(25)
|
||||
#define MARGINING_VOLTAGE_SUPPORTED BIT(24)
|
||||
#define MARGINING_MAXLANES GENMASK(20, 16)
|
||||
#define MARGINING_SAMPLE_RATE_TIMING GENMASK(13, 8)
|
||||
#define MARGINING_SAMPLE_RATE_VOLTAGE GENMASK(5, 0)
|
||||
/*
|
||||
* iATU Unroll-specific register definitions
|
||||
* From 4.80 core version the address translation will be made by unroll
|
||||
@@ -222,6 +270,21 @@
|
||||
|
||||
#define PCIE_RAS_DES_EVENT_COUNTER_DATA 0xc
|
||||
|
||||
/* PTM register definitions */
|
||||
#define PTM_RES_REQ_CTRL 0x8
|
||||
#define PTM_RES_CCONTEXT_VALID BIT(0)
|
||||
#define PTM_REQ_AUTO_UPDATE_ENABLED BIT(0)
|
||||
#define PTM_REQ_START_UPDATE BIT(1)
|
||||
|
||||
#define PTM_LOCAL_LSB 0x10
|
||||
#define PTM_LOCAL_MSB 0x14
|
||||
#define PTM_T1_T2_LSB 0x18
|
||||
#define PTM_T1_T2_MSB 0x1c
|
||||
#define PTM_T3_T4_LSB 0x28
|
||||
#define PTM_T3_T4_MSB 0x2c
|
||||
#define PTM_MASTER_LSB 0x38
|
||||
#define PTM_MASTER_MSB 0x3c
|
||||
|
||||
/*
|
||||
* The default address offset between dbi_base and atu_base. Root controller
|
||||
* drivers are not required to initialize atu_base if the offset matches this
|
||||
@@ -292,8 +355,40 @@ enum dw_pcie_ltssm {
|
||||
/* Need to align with PCIE_PORT_DEBUG0 bits 0:5 */
|
||||
DW_PCIE_LTSSM_DETECT_QUIET = 0x0,
|
||||
DW_PCIE_LTSSM_DETECT_ACT = 0x1,
|
||||
DW_PCIE_LTSSM_POLL_ACTIVE = 0x2,
|
||||
DW_PCIE_LTSSM_POLL_COMPLIANCE = 0x3,
|
||||
DW_PCIE_LTSSM_POLL_CONFIG = 0x4,
|
||||
DW_PCIE_LTSSM_PRE_DETECT_QUIET = 0x5,
|
||||
DW_PCIE_LTSSM_DETECT_WAIT = 0x6,
|
||||
DW_PCIE_LTSSM_CFG_LINKWD_START = 0x7,
|
||||
DW_PCIE_LTSSM_CFG_LINKWD_ACEPT = 0x8,
|
||||
DW_PCIE_LTSSM_CFG_LANENUM_WAI = 0x9,
|
||||
DW_PCIE_LTSSM_CFG_LANENUM_ACEPT = 0xa,
|
||||
DW_PCIE_LTSSM_CFG_COMPLETE = 0xb,
|
||||
DW_PCIE_LTSSM_CFG_IDLE = 0xc,
|
||||
DW_PCIE_LTSSM_RCVRY_LOCK = 0xd,
|
||||
DW_PCIE_LTSSM_RCVRY_SPEED = 0xe,
|
||||
DW_PCIE_LTSSM_RCVRY_RCVRCFG = 0xf,
|
||||
DW_PCIE_LTSSM_RCVRY_IDLE = 0x10,
|
||||
DW_PCIE_LTSSM_L0 = 0x11,
|
||||
DW_PCIE_LTSSM_L0S = 0x12,
|
||||
DW_PCIE_LTSSM_L123_SEND_EIDLE = 0x13,
|
||||
DW_PCIE_LTSSM_L1_IDLE = 0x14,
|
||||
DW_PCIE_LTSSM_L2_IDLE = 0x15,
|
||||
DW_PCIE_LTSSM_L2_WAKE = 0x16,
|
||||
DW_PCIE_LTSSM_DISABLED_ENTRY = 0x17,
|
||||
DW_PCIE_LTSSM_DISABLED_IDLE = 0x18,
|
||||
DW_PCIE_LTSSM_DISABLED = 0x19,
|
||||
DW_PCIE_LTSSM_LPBK_ENTRY = 0x1a,
|
||||
DW_PCIE_LTSSM_LPBK_ACTIVE = 0x1b,
|
||||
DW_PCIE_LTSSM_LPBK_EXIT = 0x1c,
|
||||
DW_PCIE_LTSSM_LPBK_EXIT_TIMEOUT = 0x1d,
|
||||
DW_PCIE_LTSSM_HOT_RESET_ENTRY = 0x1e,
|
||||
DW_PCIE_LTSSM_HOT_RESET = 0x1f,
|
||||
DW_PCIE_LTSSM_RCVRY_EQ0 = 0x20,
|
||||
DW_PCIE_LTSSM_RCVRY_EQ1 = 0x21,
|
||||
DW_PCIE_LTSSM_RCVRY_EQ2 = 0x22,
|
||||
DW_PCIE_LTSSM_RCVRY_EQ3 = 0x23,
|
||||
|
||||
DW_PCIE_LTSSM_UNKNOWN = 0xFFFFFFFF,
|
||||
};
|
||||
@@ -383,8 +478,10 @@ struct dw_pcie_ops {
|
||||
struct dw_pcie {
|
||||
struct device *dev;
|
||||
void __iomem *dbi_base;
|
||||
resource_size_t dbi_phys_addr;
|
||||
void __iomem *dbi_base2;
|
||||
void __iomem *atu_base;
|
||||
void __iomem *elbi_base;
|
||||
size_t atu_size;
|
||||
u32 num_ib_windows;
|
||||
u32 num_ob_windows;
|
||||
|
||||
@@ -1,206 +1,278 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* PCIe RC driver for zh P100
|
||||
* PCIe RC driver for A210
|
||||
*
|
||||
* Copyright (C) 2025 zh computing, Inc.
|
||||
* Copyright (C) 2025 zhihe computing, Inc.
|
||||
*
|
||||
* Author: Ya.Huang
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/resource.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
#include "pcie-designware.h"
|
||||
|
||||
#define PCIE_X4_TYPE 0x00000000
|
||||
#define PCIE_X1_TYPE 0x00000001
|
||||
#define APP_PCIE_GEN3X4_CTRL_REG 0x000
|
||||
#define DEVICE_TYPE_EP 0
|
||||
#define DEVICE_TYPE_RP BIT(2)
|
||||
#define DEVICE_TYPE_SYSREG BIT(4)
|
||||
#define APP_LTSSM_ENABLE BIT(8)
|
||||
#define APP_DEVICE_TYPE_MASK GENMASK(3, 0)
|
||||
|
||||
#define PCIE_GEN3X4_DBI_BADDR 0x0b000000
|
||||
#define PCIE_GEN3X4_CTRL_REG 0x00000000
|
||||
#define PCIE_GEN3X4_DBG_INFO_REG0 0x00000430
|
||||
#define APP_PCIE_GEN3X4_LINK_STS_REG 0x034
|
||||
#define RDLH_LINK_UP BIT(0)
|
||||
#define SMLH_LINK_UP BIT(4)
|
||||
#define SMLH_LTSM_STATE_MASK GENMASK(25, 20)
|
||||
#define SMLH_LTSM_S_L0 BIT(20) | BIT(24)
|
||||
|
||||
#define E16PHY_GLB_CTRL_REG 0x00000000
|
||||
#define E16PHY_SRC_SEL_REG 0x00000004
|
||||
#define E16PHY_PROTLCOL_REG 0x00000008
|
||||
#define E16PHY_RES_RTURN_REG 0x00000048
|
||||
#define APP_PCIE_GEN3X4_DBG_INFO_REG0 0x430
|
||||
|
||||
#define PORT_LINK_CTRL_OFF 0x00000710
|
||||
#define LANE_SKEW_OFF 0x00000714
|
||||
#define GEN2_CTRL_OFF 0x0000080c
|
||||
#define GEN3_EQ_CONTROL_OFF 0x000008a8
|
||||
#define GEN3_EQ_FB_MODE_DIR_CHANGE_OFF 0x000008ac
|
||||
#define PCIE_EXTENDED_REG0 0x00000154
|
||||
#define PCIE_EXTENDED_REG1 0x00000158
|
||||
#define PCIE_EXTENDED_REG2 0x0000015c
|
||||
#define PCIE_EXTENDED_REG3 0x00000160
|
||||
|
||||
#define PCIE_EXTENDED_REG0 0x00000154
|
||||
#define PCIE_EXTENDED_REG1 0x00000158
|
||||
#define PCIE_EXTENDED_REG2 0x0000015c
|
||||
#define PCIE_EXTENDED_REG3 0x00000160
|
||||
#define TYPE1_STATUS_COMMAND_REG 0x00000004
|
||||
#define SEC_STAT_IO_LIMIT_IO_BASE_REG 0x0000001c
|
||||
#define MEM_LIMIT_MEM_BASE_REG 0x00000020
|
||||
#define PREF_MEM_LIMIT_PREF_MEM_BASE_REG 0x00000024
|
||||
#define PREF_BASE_UPPER_REG 0x00000028
|
||||
#define PREF_LIMIT_UPPER_REG 0x0000002c
|
||||
#define IO_LIMIT_UPPER_IO_BASE_UPPER_REG 0x00000030
|
||||
#define TRGT_MAP_CTRL_OFF 0x0000081c
|
||||
|
||||
#define TYPE1_STATUS_COMMAND_REG 0x00000004
|
||||
#define DBI2_BAR0_REG 0x00100010
|
||||
#define DBI2_BAR1_REG 0x00100014
|
||||
#define SEC_STAT_IO_LIMIT_IO_BASE_REG 0x0000001c
|
||||
#define MEM_LIMIT_MEM_BASE_REG 0x00000020
|
||||
#define PREF_MEM_LIMIT_PREF_MEM_BASE_REG 0x00000024
|
||||
#define PREF_BASE_UPPER_REG 0x00000028
|
||||
#define PREF_LIMIT_UPPER_REG 0x0000002c
|
||||
#define IO_LIMIT_UPPER_IO_BASE_UPPER_REG 0x00000030
|
||||
#define TRGT_MAP_CTRL_OFF 0x0000081c
|
||||
#define DEVICE_CONTROL_DEVICE_STATUS 0x00000078
|
||||
#define LINK_CONTROL2_LINK_STATUS2_REG 0x000000a0
|
||||
|
||||
#define DEVICE_CONTROL_DEVICE_STATUS 0x00000078
|
||||
#define LINK_CONTROL2_LINK_STATUS2_REG 0x000000a0
|
||||
|
||||
#define LINK_UP_IS_OK 0x11
|
||||
|
||||
struct p100_plat_pcie {
|
||||
struct dw_pcie *pci;
|
||||
enum dw_pcie_device_mode mode;
|
||||
unsigned int ip_type;
|
||||
void __iomem *apb_base;
|
||||
void __iomem *wrap_base;
|
||||
void __iomem *phy_base;
|
||||
void __iomem *cpr_base;
|
||||
struct reset_control *pcie_rst;
|
||||
struct reset_control *pcie_prst;
|
||||
struct gpio_desc *pcie_bat_en;
|
||||
struct gpio_desc *pcie_3v3_en;
|
||||
struct gpio_desc *pcie_12v_en;
|
||||
struct gpio_desc *pcie_clk_en;
|
||||
struct gpio_desc *minipcie_1v5_pwren;
|
||||
struct gpio_desc *minipcie_3v3_pwren;
|
||||
struct gpio_desc *minipcie_perst;
|
||||
struct gpio_desc *pcie_clk_pwren;
|
||||
struct zhihe_pcie {
|
||||
struct dw_pcie pci;
|
||||
enum dw_pcie_device_mode mode;
|
||||
void __iomem *app_base;
|
||||
struct phy *phy;
|
||||
u32 cap_base;
|
||||
};
|
||||
|
||||
struct p100_plat_pcie_of_data {
|
||||
#define to_zhihe_pcie(x) (struct zhihe_pcie*)dev_get_drvdata((x)->dev)
|
||||
|
||||
struct zhihe_pcie_of_data {
|
||||
enum dw_pcie_device_mode mode;
|
||||
};
|
||||
|
||||
static const struct dw_pcie_host_ops p100_plat_pcie_host_ops = {
|
||||
static void pcie_update_bits(void __iomem *base, u32 ofs, u32 mask, u32 val)
|
||||
{
|
||||
u32 old;
|
||||
|
||||
old = readl(base + ofs);
|
||||
val = (old & ~mask) | (val & mask);
|
||||
|
||||
if (val != old)
|
||||
writel(val, base + ofs);
|
||||
}
|
||||
|
||||
static inline int pcie_app_rd(struct zhihe_pcie *pcie, u32 reg)
|
||||
{
|
||||
return readl(pcie->app_base + reg);
|
||||
}
|
||||
|
||||
static inline void pcie_app_wr(struct zhihe_pcie *pcie, u32 reg, u32 val)
|
||||
{
|
||||
writel(val, pcie->app_base + reg);
|
||||
}
|
||||
|
||||
static void pcie_app_wr_mask(struct zhihe_pcie *pcie, u32 ofs,
|
||||
u32 mask, u32 val)
|
||||
{
|
||||
pcie_update_bits(pcie->app_base, ofs, mask, val);
|
||||
}
|
||||
|
||||
static void __maybe_unused pcie_dump_mmio(struct device *dev, void __iomem *start,
|
||||
unsigned int bytes)
|
||||
{
|
||||
unsigned int b, w, o, offset = 0;
|
||||
unsigned char linebuf[38];
|
||||
|
||||
for (b = 0; b < bytes;) {
|
||||
for (w = 0, o = 0; b < bytes && w < 4; w++) {
|
||||
o += scnprintf(linebuf + o, sizeof(linebuf) - o,
|
||||
"%08x ", readl(start + b));
|
||||
b += sizeof(u32);
|
||||
}
|
||||
dev_info(dev, "%03x: %s\n", offset, linebuf);
|
||||
offset += w * sizeof(u32);
|
||||
}
|
||||
}
|
||||
|
||||
static void zhihe_pcie_set_device_type(struct zhihe_pcie *pcie, u32 type)
|
||||
{
|
||||
pcie_app_wr_mask(pcie, APP_PCIE_GEN3X4_CTRL_REG,
|
||||
DEVICE_TYPE_SYSREG | APP_DEVICE_TYPE_MASK,
|
||||
DEVICE_TYPE_SYSREG | type);
|
||||
}
|
||||
|
||||
static void zhihe_pcie_ltssm_enable(struct zhihe_pcie *pcie)
|
||||
{
|
||||
pcie_app_wr_mask(pcie, APP_PCIE_GEN3X4_CTRL_REG, APP_LTSSM_ENABLE, APP_LTSSM_ENABLE);
|
||||
}
|
||||
|
||||
static void zhihe_pcie_ltssm_disable(struct zhihe_pcie *pcie)
|
||||
{
|
||||
pcie_app_wr_mask(pcie, APP_PCIE_GEN3X4_CTRL_REG, APP_LTSSM_ENABLE, 0);
|
||||
}
|
||||
|
||||
static int zhihe_pcie_wait_linkup(struct zhihe_pcie *pcie)
|
||||
{
|
||||
u32 ltssm_stat;
|
||||
int count = 20;
|
||||
|
||||
do {
|
||||
ltssm_stat = pcie_app_rd(pcie, APP_PCIE_GEN3X4_LINK_STS_REG);
|
||||
if (ltssm_stat && (SMLH_LTSM_S_L0 | SMLH_LINK_UP | RDLH_LINK_UP)) {
|
||||
dev_info(pcie->pci.dev, "ltssm:link up ok!\n");
|
||||
break;
|
||||
}
|
||||
mdelay(50);
|
||||
} while (count--);
|
||||
|
||||
if (count < 0) {
|
||||
dev_err(pcie->pci.dev, "ltssm_stat = 0x%x,link up fail!\n",ltssm_stat);
|
||||
pcie_dump_mmio(pcie->pci.dev, pcie->app_base, 0x490);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int zhihe_pcie_get_resources(struct platform_device *pdev,
|
||||
struct zhihe_pcie *pcie)
|
||||
{
|
||||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Failed to get PCIe DBI resource\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcie_sysreg");
|
||||
pcie->app_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pcie->app_base))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(pcie->app_base),
|
||||
"Failed to get pcie_sysreg resource");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused zhihe_pcie_phy_init(struct zhihe_pcie *pcie)
|
||||
{
|
||||
struct device *dev = pcie->pci.dev;
|
||||
int ret;
|
||||
|
||||
pcie->phy = devm_phy_get(dev, "pcie-phy");
|
||||
if (IS_ERR(pcie->phy))
|
||||
return dev_err_probe(dev, PTR_ERR(pcie->phy),
|
||||
"missing PHY\n");
|
||||
|
||||
ret = phy_init(pcie->phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = phy_set_mode_ext(pcie->phy, PHY_MODE_PCIE, pcie->mode);
|
||||
if (ret) {
|
||||
phy_exit(pcie->phy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = phy_power_on(pcie->phy);
|
||||
if (ret)
|
||||
phy_exit(pcie->phy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __maybe_unused zhihe_pcie_phy_deinit(struct zhihe_pcie *pcie)
|
||||
{
|
||||
phy_exit(pcie->phy);
|
||||
phy_power_off(pcie->phy);
|
||||
}
|
||||
|
||||
static int zhihe_pcie_start_link(struct dw_pcie *pci)
|
||||
{
|
||||
struct zhihe_pcie *pcie = to_zhihe_pcie(pci);
|
||||
zhihe_pcie_ltssm_enable(pcie);
|
||||
return zhihe_pcie_wait_linkup(pcie);
|
||||
}
|
||||
|
||||
static void zhihe_pcie_stop_link(struct dw_pcie *pci)
|
||||
{
|
||||
struct zhihe_pcie *pcie = to_zhihe_pcie(pci);
|
||||
zhihe_pcie_ltssm_disable(pcie);
|
||||
}
|
||||
|
||||
static const struct dw_pcie_ops dw_pcie_ops = {
|
||||
.start_link = zhihe_pcie_start_link,
|
||||
.stop_link = zhihe_pcie_stop_link,
|
||||
};
|
||||
|
||||
static inline int p100_pcie_readl_apb(struct p100_plat_pcie *p100_plat_pcie,
|
||||
u32 reg)
|
||||
static int zhihe_pcie_host_init(struct dw_pcie_rp *pp)
|
||||
{
|
||||
return readl(p100_plat_pcie->apb_base + reg);
|
||||
}
|
||||
u32 val;
|
||||
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||||
struct zhihe_pcie *pcie = to_zhihe_pcie(pci);
|
||||
|
||||
static inline void p100_pcie_writel_apb(struct p100_plat_pcie *p100_plat_pcie,
|
||||
u32 reg, u32 val)
|
||||
{
|
||||
writel(val, p100_plat_pcie->apb_base + reg);
|
||||
}
|
||||
|
||||
static inline int p100_pcie_readl_wrap(struct p100_plat_pcie *p100_plat_pcie,
|
||||
u32 reg)
|
||||
{
|
||||
return readl(p100_plat_pcie->wrap_base + reg);
|
||||
}
|
||||
|
||||
static inline void p100_pcie_writel_wrap(struct p100_plat_pcie *p100_plat_pcie,
|
||||
u32 reg, u32 val)
|
||||
{
|
||||
writel(val, p100_plat_pcie->wrap_base + reg);
|
||||
}
|
||||
|
||||
static inline int p100_pcie_readl_phy(struct p100_plat_pcie *p100_plat_pcie,
|
||||
u32 reg)
|
||||
{
|
||||
return readl(p100_plat_pcie->phy_base + reg);
|
||||
}
|
||||
|
||||
static inline void p100_pcie_writel_phy(struct p100_plat_pcie *p100_plat_pcie,
|
||||
u32 reg, u32 val)
|
||||
{
|
||||
writel(val, p100_plat_pcie->phy_base + reg);
|
||||
}
|
||||
|
||||
static inline int p100_pcie_readl_cpr(struct p100_plat_pcie *p100_plat_pcie,
|
||||
u32 reg)
|
||||
{
|
||||
return readl(p100_plat_pcie->cpr_base + reg);
|
||||
}
|
||||
|
||||
static inline void p100_pcie_writel_cpr(struct p100_plat_pcie *p100_plat_pcie,
|
||||
u32 reg, u32 val)
|
||||
{
|
||||
writel(val, p100_plat_pcie->cpr_base + reg);
|
||||
}
|
||||
|
||||
static void p100_pcie_ipctrl_init(struct p100_plat_pcie *p100_plat_pcie)
|
||||
{
|
||||
int rdata = 0;
|
||||
int ret = zhihe_pcie_phy_init(pcie);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*disable ltssm*/
|
||||
p100_pcie_writel_wrap(p100_plat_pcie, PCIE_GEN3X4_CTRL_REG, 0x1014);
|
||||
/*enable rp && sata*/
|
||||
if (p100_plat_pcie->ip_type == PCIE_X1_TYPE) {
|
||||
p100_pcie_writel_phy(p100_plat_pcie, E16PHY_GLB_CTRL_REG, 0x110101);
|
||||
p100_pcie_writel_phy(p100_plat_pcie, E16PHY_SRC_SEL_REG, 0x1100);
|
||||
p100_pcie_writel_phy(p100_plat_pcie, E16PHY_PROTLCOL_REG, 0x2200);
|
||||
}
|
||||
/*phy deassert*/
|
||||
if (p100_plat_pcie->ip_type == PCIE_X4_TYPE) {
|
||||
reset_control_deassert(p100_plat_pcie->pcie_rst);
|
||||
reset_control_deassert(p100_plat_pcie->pcie_prst);
|
||||
}
|
||||
/*resistor tune request && res_ack_in*/
|
||||
p100_pcie_writel_phy(p100_plat_pcie, E16PHY_RES_RTURN_REG, 0x10001);
|
||||
if (p100_plat_pcie->ip_type == PCIE_X4_TYPE) {
|
||||
/*cfg x4 lane*/
|
||||
p100_pcie_writel_apb(p100_plat_pcie, PORT_LINK_CTRL_OFF, 0x70120);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, LANE_SKEW_OFF, 0x1c000000);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, GEN3_EQ_CONTROL_OFF, 0xc020071);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, GEN2_CTRL_OFF, 0x304be);
|
||||
} else {
|
||||
/*cfg x1 lane*/
|
||||
p100_pcie_writel_apb(p100_plat_pcie, PORT_LINK_CTRL_OFF, 0x10120);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, LANE_SKEW_OFF, 0x4000000);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, GEN3_EQ_CONTROL_OFF, 0xc020071);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, GEN2_CTRL_OFF, 0x101be);
|
||||
}
|
||||
/*ip ctrl cfg*/
|
||||
p100_pcie_writel_apb(p100_plat_pcie, GEN3_RELATED_OFF, 0x2000);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, GEN3_RELATED_OFF, 0x2a00);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, PCIE_EXTENDED_REG0, 0x21614536);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, PCIE_EXTENDED_REG1, 0x6337451);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, PCIE_EXTENDED_REG2, 0x8553824);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, PCIE_EXTENDED_REG3, 0x47373650);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, GEN3_EQ_FB_MODE_DIR_CHANGE_OFF, 0x0);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, DEVICE_CONTROL_DEVICE_STATUS, 0x2130);
|
||||
/*cfg Gen3*/
|
||||
rdata = p100_pcie_readl_apb(p100_plat_pcie, LINK_CONTROL2_LINK_STATUS2_REG);
|
||||
rdata &= 0xfffffff0;
|
||||
rdata |= 0x3;
|
||||
p100_pcie_writel_apb(p100_plat_pcie, LINK_CONTROL2_LINK_STATUS2_REG, rdata);
|
||||
/*config space setup*/
|
||||
p100_pcie_writel_apb(p100_plat_pcie, DBI2_BAR0_REG, 0x0);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, DBI2_BAR1_REG, 0x0);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, TRGT_MAP_CTRL_OFF, 0x40);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, SEC_STAT_IO_LIMIT_IO_BASE_REG, 0x4f40);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, IO_LIMIT_UPPER_IO_BASE_UPPER_REG, 0x0);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, MEM_LIMIT_MEM_BASE_REG, 0xc91fc800);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, PREF_MEM_LIMIT_PREF_MEM_BASE_REG, 0xfff0);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, PREF_BASE_UPPER_REG, 0x0);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, PREF_LIMIT_UPPER_REG, 0x0);
|
||||
p100_pcie_writel_apb(p100_plat_pcie, TYPE1_STATUS_COMMAND_REG, 0x100007);
|
||||
/*enable ltssm*/
|
||||
p100_pcie_writel_wrap(p100_plat_pcie, PCIE_GEN3X4_CTRL_REG, 0x1114);
|
||||
zhihe_pcie_ltssm_disable(pcie);
|
||||
/* Set RP mode */
|
||||
zhihe_pcie_set_device_type(pcie, DEVICE_TYPE_RP);
|
||||
|
||||
if (!pcie->cap_base)
|
||||
pcie->cap_base = dw_pcie_find_capability(&pcie->pci, PCI_CAP_ID_EXP);
|
||||
|
||||
/* Disable BARs for inbound access */
|
||||
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0);
|
||||
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0);
|
||||
|
||||
/* Configure Max lane width from DT */
|
||||
dw_pcie_dbi_ro_wr_en(pci);
|
||||
val = dw_pcie_readl_dbi(pci, pcie->cap_base + PCI_EXP_LNKCAP);
|
||||
val &= ~PCI_EXP_LNKCAP_MLW;
|
||||
val |= (pci->num_lanes << PCI_EXP_LNKSTA_NLW_SHIFT);
|
||||
dw_pcie_writel_dbi(pci, pcie->cap_base + PCI_EXP_LNKCAP, val);
|
||||
dw_pcie_dbi_ro_wr_dis(pci);
|
||||
|
||||
val = dw_pcie_readl_dbi(pci, PCIE_PORT_LANE_SKEW);
|
||||
val &= ~PORT_LANE_SKEW_INSERT_MASK;
|
||||
if (pci->num_lanes < 4)
|
||||
val |= BIT(6);
|
||||
dw_pcie_writel_dbi(pci, PCIE_PORT_LANE_SKEW, val);
|
||||
|
||||
val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF);
|
||||
val |= GEN3_RELATED_OFF_EQ_PHASE_2_3;
|
||||
dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val);
|
||||
dw_pcie_writel_dbi(pci, GEN3_EQ_CONTROL_OFF, 0xc020071);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p100_plat_add_pcie_port(struct p100_plat_pcie *p100_plat_pcie,
|
||||
struct platform_device *pdev)
|
||||
static const struct dw_pcie_host_ops zhihe_pcie_host_ops = {
|
||||
.host_init = zhihe_pcie_host_init,
|
||||
};
|
||||
|
||||
static int zhihe_add_pcie_port(struct zhihe_pcie *pcie, struct platform_device *pdev)
|
||||
{
|
||||
struct dw_pcie *pci = p100_plat_pcie->pci;
|
||||
struct dw_pcie *pci = &pcie->pci;
|
||||
struct dw_pcie_rp *pp = &pci->pp;
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
@@ -210,7 +282,7 @@ static int p100_plat_add_pcie_port(struct p100_plat_pcie *p100_plat_pcie,
|
||||
return pp->irq;
|
||||
|
||||
pp->num_vectors = MAX_MSI_IRQS;
|
||||
pp->ops = &p100_plat_pcie_host_ops;
|
||||
pp->ops = &zhihe_pcie_host_ops;
|
||||
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
@@ -221,270 +293,85 @@ static int p100_plat_add_pcie_port(struct p100_plat_pcie *p100_plat_pcie,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void p100_pcie_wait_linkup(struct platform_device *pdev,struct p100_plat_pcie *p100_plat_pcie)
|
||||
{
|
||||
u32 ltssm_stat = 0;
|
||||
unsigned long cnt = 0;
|
||||
unsigned int TIME_OUT_CNT = 20;
|
||||
unsigned int DELAY_MS = 50;
|
||||
|
||||
do {
|
||||
mdelay(DELAY_MS);
|
||||
ltssm_stat = p100_pcie_readl_wrap(p100_plat_pcie, \
|
||||
PCIE_GEN3X4_DBG_INFO_REG0);
|
||||
ltssm_stat &= 0x3f;
|
||||
if (ltssm_stat == LINK_UP_IS_OK) {
|
||||
dev_info(&pdev->dev, "ltssm:link up ok!\n");
|
||||
break;
|
||||
}
|
||||
if (cnt > TIME_OUT_CNT) {
|
||||
dev_err(&pdev->dev, "ltssm_stat = 0x%x,link up fail!\n",ltssm_stat);
|
||||
break;
|
||||
}
|
||||
cnt++;
|
||||
} while (ltssm_stat != LINK_UP_IS_OK);
|
||||
}
|
||||
|
||||
static int p100_pcie_get_resource(struct platform_device *pdev,
|
||||
struct p100_plat_pcie *p100_plat_pcie)
|
||||
{
|
||||
struct resource *res;
|
||||
static void __iomem *ep16phy_base;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Failed to get PCIe DBI resource\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if(res->start == PCIE_GEN3X4_DBI_BADDR)
|
||||
p100_plat_pcie->ip_type = PCIE_X4_TYPE;
|
||||
else
|
||||
p100_plat_pcie->ip_type = PCIE_X1_TYPE;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apb");
|
||||
p100_plat_pcie->apb_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(p100_plat_pcie->apb_base))
|
||||
return PTR_ERR(p100_plat_pcie->apb_base);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wrap_sysreg");
|
||||
p100_plat_pcie->wrap_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(p100_plat_pcie->wrap_base))
|
||||
return PTR_ERR(p100_plat_pcie->wrap_base);
|
||||
|
||||
if (p100_plat_pcie->ip_type == PCIE_X4_TYPE) {
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_sysreg");
|
||||
p100_plat_pcie->phy_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(p100_plat_pcie->phy_base))
|
||||
return PTR_ERR(p100_plat_pcie->phy_base);
|
||||
ep16phy_base = p100_plat_pcie->phy_base;
|
||||
}
|
||||
|
||||
if (p100_plat_pcie->ip_type == PCIE_X1_TYPE)
|
||||
p100_plat_pcie->phy_base = ep16phy_base;
|
||||
|
||||
if (p100_plat_pcie->ip_type == PCIE_X4_TYPE) {
|
||||
p100_plat_pcie->pcie_rst = devm_reset_control_get_shared(&pdev->dev, "pcie-rst");
|
||||
if(IS_ERR(p100_plat_pcie->pcie_rst))
|
||||
return PTR_ERR(p100_plat_pcie->pcie_rst);
|
||||
p100_plat_pcie->pcie_prst = devm_reset_control_get_shared(&pdev->dev, "pcie-prst");
|
||||
if(IS_ERR(p100_plat_pcie->pcie_prst))
|
||||
return PTR_ERR(p100_plat_pcie->pcie_prst);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void p100_pcie_ltssm_disable(struct p100_plat_pcie *p100_plat_pcie)
|
||||
{
|
||||
p100_pcie_writel_wrap(p100_plat_pcie, PCIE_GEN3X4_CTRL_REG, 0x1014);
|
||||
}
|
||||
|
||||
static void p100_pcie_stop_link(struct dw_pcie *pci)
|
||||
{
|
||||
struct p100_plat_pcie *p100_plat_pcie = dev_get_drvdata(pci->dev);
|
||||
|
||||
p100_pcie_ltssm_disable(p100_plat_pcie);
|
||||
}
|
||||
|
||||
static const struct dw_pcie_ops dw_pcie_ops = {
|
||||
.stop_link = p100_pcie_stop_link,
|
||||
};
|
||||
|
||||
static int p100_plat_pcie_probe(struct platform_device *pdev)
|
||||
static int zhihe_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct p100_plat_pcie *p100_plat_pcie;
|
||||
struct zhihe_pcie *pcie;
|
||||
struct dw_pcie *pci;
|
||||
int ret;
|
||||
const struct p100_plat_pcie_of_data *data;
|
||||
|
||||
const struct zhihe_pcie_of_data *data;
|
||||
enum dw_pcie_device_mode mode;
|
||||
|
||||
dev_info(dev, "Enter into zh_pci platform!\n");
|
||||
|
||||
data = of_device_get_match_data(dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
mode = (enum dw_pcie_device_mode)data->mode;
|
||||
goto deinit_phy;
|
||||
|
||||
p100_plat_pcie = devm_kzalloc(dev, sizeof(*p100_plat_pcie), GFP_KERNEL);
|
||||
if (!p100_plat_pcie)
|
||||
return -ENOMEM;
|
||||
|
||||
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
|
||||
if (!pci)
|
||||
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
|
||||
if (!pcie)
|
||||
return -ENOMEM;
|
||||
|
||||
pci = &pcie->pci;
|
||||
pci->dev = dev;
|
||||
p100_plat_pcie->pci = pci;
|
||||
p100_plat_pcie->mode = mode;
|
||||
mode = pcie->mode =(enum dw_pcie_device_mode)data->mode;;
|
||||
pci->ops = &dw_pcie_ops;
|
||||
|
||||
p100_plat_pcie->pci->ops = &dw_pcie_ops;
|
||||
ret = p100_pcie_get_resource(pdev, p100_plat_pcie);
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
ret = zhihe_pcie_get_resources(pdev, pcie);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
p100_pcie_ipctrl_init(p100_plat_pcie);
|
||||
p100_pcie_wait_linkup(pdev, p100_plat_pcie);
|
||||
|
||||
platform_set_drvdata(pdev, p100_plat_pcie);
|
||||
switch (p100_plat_pcie->mode) {
|
||||
switch (pcie->mode) {
|
||||
case DW_PCIE_RC_TYPE:
|
||||
/* Get GPIO descriptors for PCIe power control */
|
||||
p100_plat_pcie->pcie_bat_en = devm_gpiod_get_optional(&pdev->dev,
|
||||
"pcie-bat-en",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(p100_plat_pcie->pcie_bat_en)) {
|
||||
dev_err(&pdev->dev, "Failed to get pcie-bat-en GPIO\n");
|
||||
return PTR_ERR(p100_plat_pcie->pcie_bat_en);
|
||||
}
|
||||
|
||||
p100_plat_pcie->pcie_3v3_en = devm_gpiod_get_optional(&pdev->dev,
|
||||
"pcie-3v3-en",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(p100_plat_pcie->pcie_3v3_en)) {
|
||||
dev_err(&pdev->dev, "Failed to get pcie-3v3-en GPIO\n");
|
||||
return PTR_ERR(p100_plat_pcie->pcie_3v3_en);
|
||||
}
|
||||
|
||||
p100_plat_pcie->pcie_12v_en = devm_gpiod_get_optional(&pdev->dev,
|
||||
"pcie-12v-en",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(p100_plat_pcie->pcie_12v_en)) {
|
||||
dev_err(&pdev->dev, "Failed to get pcie-12v-en GPIO\n");
|
||||
return PTR_ERR(p100_plat_pcie->pcie_12v_en);
|
||||
}
|
||||
|
||||
p100_plat_pcie->pcie_clk_en = devm_gpiod_get_optional(&pdev->dev,
|
||||
"pcie-clk-en",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(p100_plat_pcie->pcie_clk_en)) {
|
||||
dev_err(&pdev->dev, "Failed to get pcie-clk-en GPIO\n");
|
||||
return PTR_ERR(p100_plat_pcie->pcie_clk_en);
|
||||
}
|
||||
|
||||
if (p100_plat_pcie->pcie_bat_en)
|
||||
gpiod_set_value(p100_plat_pcie->pcie_bat_en, 1);
|
||||
|
||||
if (p100_plat_pcie->pcie_3v3_en)
|
||||
gpiod_set_value(p100_plat_pcie->pcie_3v3_en, 1);
|
||||
|
||||
if (p100_plat_pcie->pcie_12v_en)
|
||||
gpiod_set_value(p100_plat_pcie->pcie_12v_en, 1);
|
||||
|
||||
if (p100_plat_pcie->pcie_clk_en)
|
||||
gpiod_set_value(p100_plat_pcie->pcie_clk_en, 1);
|
||||
|
||||
p100_plat_pcie->minipcie_1v5_pwren = devm_gpiod_get_optional(&pdev->dev,
|
||||
"minipcie-1v5-pwren",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(p100_plat_pcie->minipcie_1v5_pwren)) {
|
||||
dev_err(&pdev->dev, "Failed to get minipcie-1v5-pwren GPIO\n");
|
||||
return PTR_ERR(p100_plat_pcie->minipcie_1v5_pwren);
|
||||
}
|
||||
|
||||
if (p100_plat_pcie->minipcie_1v5_pwren)
|
||||
gpiod_set_value(p100_plat_pcie->minipcie_1v5_pwren, 1);
|
||||
|
||||
p100_plat_pcie->minipcie_3v3_pwren = devm_gpiod_get_optional(&pdev->dev,
|
||||
"minipcie-3v3-pwren",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(p100_plat_pcie->minipcie_3v3_pwren)) {
|
||||
dev_err(&pdev->dev, "Failed to get minipcie-3v3-pwren GPIO\n");
|
||||
return PTR_ERR(p100_plat_pcie->minipcie_3v3_pwren);
|
||||
}
|
||||
|
||||
if (p100_plat_pcie->minipcie_3v3_pwren)
|
||||
gpiod_set_value(p100_plat_pcie->minipcie_3v3_pwren, 1);
|
||||
|
||||
p100_plat_pcie->minipcie_perst = devm_gpiod_get_optional(&pdev->dev,
|
||||
"minipcie-perst",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(p100_plat_pcie->minipcie_perst)) {
|
||||
dev_err(&pdev->dev, "Failed to get minipcie-perst GPIO\n");
|
||||
return PTR_ERR(p100_plat_pcie->minipcie_perst);
|
||||
}
|
||||
|
||||
if (p100_plat_pcie->minipcie_perst)
|
||||
gpiod_set_value(p100_plat_pcie->minipcie_perst, 1);
|
||||
|
||||
p100_plat_pcie->pcie_clk_pwren = devm_gpiod_get_optional(&pdev->dev,
|
||||
"pcie-clk-pwren",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(p100_plat_pcie->pcie_clk_pwren)) {
|
||||
dev_err(&pdev->dev, "Failed to get pcie-clk-pwren GPIO\n");
|
||||
return PTR_ERR(p100_plat_pcie->pcie_clk_pwren);
|
||||
}
|
||||
|
||||
if (p100_plat_pcie->pcie_clk_pwren)
|
||||
gpiod_set_value(p100_plat_pcie->pcie_clk_pwren, 1);
|
||||
p100_plat_pcie->pci->dbi_base = p100_plat_pcie->apb_base;
|
||||
|
||||
ret = p100_plat_add_pcie_port(p100_plat_pcie, pdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = zhihe_add_pcie_port(pcie, pdev);
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "INVALID device type %d\n", p100_plat_pcie->mode);
|
||||
ret = -EINVAL;
|
||||
dev_err(dev, "Invalid device type %d\n", pcie->mode);
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
deinit_phy:
|
||||
zhihe_pcie_phy_deinit(pcie);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int p100_plat_pcie_remove(struct platform_device *pdev)
|
||||
static int zhihe_pcie_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct p100_plat_pcie *p100_plat_pcie = platform_get_drvdata(pdev);
|
||||
struct zhihe_pcie *pcie = platform_get_drvdata(pdev);
|
||||
|
||||
dw_pcie_host_deinit(&p100_plat_pcie->pci->pp);
|
||||
|
||||
reset_control_assert(p100_plat_pcie->pcie_rst);
|
||||
reset_control_assert(p100_plat_pcie->pcie_prst);
|
||||
dw_pcie_host_deinit(&pcie->pci.pp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct p100_plat_pcie_of_data p100_plat_pcie_rc_of_data = {
|
||||
static const struct zhihe_pcie_of_data zhihe_pcie_rc_of_data = {
|
||||
.mode = DW_PCIE_RC_TYPE,
|
||||
};
|
||||
|
||||
static const struct of_device_id p100_plat_pcie_of_match[] = {
|
||||
static const struct of_device_id zhihe_pcie_of_match[] = {
|
||||
{
|
||||
.compatible = "zh,p100-pcie",
|
||||
.data = &p100_plat_pcie_rc_of_data,
|
||||
.compatible = "zhihe,a210-pcie",
|
||||
.data = &zhihe_pcie_rc_of_data,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver p100_plat_pcie_driver = {
|
||||
static struct platform_driver zhihe_pcie_driver = {
|
||||
.driver = {
|
||||
.name = "zh-pcie",
|
||||
.of_match_table = p100_plat_pcie_of_match,
|
||||
.of_match_table = zhihe_pcie_of_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = p100_plat_pcie_probe,
|
||||
.remove = p100_plat_pcie_remove,
|
||||
.probe = zhihe_pcie_probe,
|
||||
.remove = zhihe_pcie_remove,
|
||||
};
|
||||
module_platform_driver(p100_plat_pcie_driver);
|
||||
module_platform_driver(zhihe_pcie_driver);
|
||||
|
||||
MODULE_DEVICE_TABLE(of, zhihe_pcie_of_match);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -99,6 +99,6 @@ source "drivers/phy/tegra/Kconfig"
|
||||
source "drivers/phy/ti/Kconfig"
|
||||
source "drivers/phy/intel/Kconfig"
|
||||
source "drivers/phy/xilinx/Kconfig"
|
||||
source "drivers/phy/synopsys/Kconfig"
|
||||
source "drivers/phy/zhihe/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -37,4 +37,4 @@ obj-y += allwinner/ \
|
||||
tegra/ \
|
||||
ti/ \
|
||||
xilinx/ \
|
||||
synopsys/
|
||||
zhihe/
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
config PHY_DW_DPHY
|
||||
tristate "Synopsys DesignWare MIPI D-PHY Support"
|
||||
depends on HAS_IOMEM && OF
|
||||
select GENERIC_PHY
|
||||
select GENERIC_PHY_MIPI_DPHY
|
||||
help
|
||||
Choose this option if you have DesignWare D-PHY in your system.
|
||||
If M is selected, the module will be called dw-dphy.
|
||||
@@ -1,3 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_PHY_DW_DPHY) += phy-dw-mipi-dphy.o
|
||||
41
drivers/phy/zhihe/Kconfig
Normal file
41
drivers/phy/zhihe/Kconfig
Normal file
@@ -0,0 +1,41 @@
|
||||
#SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
config PHY_DW_DPHY
|
||||
tristate "Synopsys DesignWare MIPI D-PHY Support"
|
||||
depends on HAS_IOMEM && OF
|
||||
select GENERIC_PHY
|
||||
select GENERIC_PHY_MIPI_DPHY
|
||||
help
|
||||
Choose this option if you have DesignWare D-PHY in your system.
|
||||
If M is selected, the module will be called dw-dphy.
|
||||
|
||||
config PHY_ZHIHE_SNPS_PCIE3
|
||||
tristate "Zhihe Snps PCIe3 PHY Driver"
|
||||
depends on (ARCH_ZHIHE && OF) || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
select GENERIC_PHY
|
||||
select MFD_SYSCON
|
||||
help
|
||||
Enable this to support the ZHIHE snps PCIe3 PHY.
|
||||
|
||||
config PHY_ZHIHE_SNPS_USB2
|
||||
tristate "Zhihe Snps USB2.0 PHY Driver"
|
||||
depends on (ARCH_ZHIHE && OF) || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
select GENERIC_PHY
|
||||
help
|
||||
Enable this to support the ZHIHE Snps USB 2.0 PHY.
|
||||
This driver provides PHY support for the USB 2.0 controllers
|
||||
on ZHIHE platforms.
|
||||
|
||||
config PHY_ZHIHE_SNPS_C10PHY
|
||||
tristate "ZHIHE C10PHY USB3.1 PHY Driver"
|
||||
depends on ARCH_ZHIHE || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
select GENERIC_PHY
|
||||
help
|
||||
Enable this to support the ZHIHE C10PHY USB3.1 PHY.
|
||||
This PHY is used in ZHIHE A210 SoCs for USB 3.1 functionality.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called phy-c10phy.
|
||||
6
drivers/phy/zhihe/Makefile
Normal file
6
drivers/phy/zhihe/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_PHY_DW_DPHY) += phy-zhihe-snps-mipidsi.o
|
||||
obj-$(CONFIG_PHY_ZHIHE_SNPS_PCIE3) += phy-zhihe-snps-e16phy.o
|
||||
obj-$(CONFIG_PHY_ZHIHE_SNPS_USB2) += phy-zhihe-snps-usb2.o
|
||||
obj-$(CONFIG_PHY_ZHIHE_SNPS_C10PHY) += phy-zhihe-snps-c10phy.o
|
||||
1012
drivers/phy/zhihe/phy-zhihe-snps-c10phy.c
Normal file
1012
drivers/phy/zhihe/phy-zhihe-snps-c10phy.c
Normal file
File diff suppressed because it is too large
Load Diff
275
drivers/phy/zhihe/phy-zhihe-snps-e16phy.c
Normal file
275
drivers/phy/zhihe/phy-zhihe-snps-e16phy.c
Normal file
@@ -0,0 +1,275 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Synopsys DesignWare E16 PCIe 3.0 PHY driver for ZHIHE SoC
|
||||
*
|
||||
* Copyright (C) ZHIHE
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/phy/pcie.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
/* Registers definition for ZHIHE A210 */
|
||||
#define E16PHY_RES_RTUNE_REG 0x00000048
|
||||
#define PHY_RTUNE_REQ BIT(0)
|
||||
#define PHY_RTUNE_ACK BIT(4)
|
||||
#define PHY_RES_REQ_IN BIT(8)
|
||||
#define PHY_RES_REQ_OUT BIT(12)
|
||||
#define PHY_RES_ACK_IN BIT(16)
|
||||
#define PHY_RES_ACK_OUT BIT(20)
|
||||
|
||||
struct e16phy_seq {
|
||||
u32 addr;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
struct zhihe_e16phy_priv {
|
||||
void __iomem *mmio;
|
||||
int mode;
|
||||
struct reset_control *apb_rst;
|
||||
struct reset_control *phy_rst;
|
||||
struct phy *phy;
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
struct e16phy_seq *init_seq;
|
||||
int num_init_seq;
|
||||
struct gpio_descs *base_en;
|
||||
struct gpio_descs *sata_en;
|
||||
struct gpio_descs *pcie_en;
|
||||
};
|
||||
|
||||
static void e16phy_dump_mmio(struct device *dev, void __iomem *start,
|
||||
unsigned int bytes)
|
||||
{
|
||||
unsigned int b, w, o, offset = 0;
|
||||
unsigned char linebuf[38];
|
||||
|
||||
for (b = 0; b < bytes;) {
|
||||
for (w = 0, o = 0; b < bytes && w < 4; w++) {
|
||||
o += scnprintf(linebuf + o, sizeof(linebuf) - o,
|
||||
"%08x ", readl(start + b));
|
||||
b += sizeof(u32);
|
||||
}
|
||||
dev_info(dev, "%03x: %s\n", offset, linebuf);
|
||||
offset += w * sizeof(u32);
|
||||
}
|
||||
}
|
||||
|
||||
static int zhihe_e16phy_init(struct phy *phy)
|
||||
{
|
||||
struct zhihe_e16phy_priv *priv = phy_get_drvdata(phy);
|
||||
unsigned int timeout;
|
||||
int ret, i;
|
||||
u32 val;
|
||||
|
||||
ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
|
||||
if (ret) {
|
||||
dev_err(&phy->dev, "failed to enable PCIe bulk clks %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
reset_control_deassert(priv->apb_rst);
|
||||
reset_control_assert(priv->phy_rst);
|
||||
udelay(100);
|
||||
|
||||
for (i = 0; i < priv->num_init_seq; i++) {
|
||||
struct e16phy_seq *seq = &priv->init_seq[i];
|
||||
writel(seq->val, priv->mmio + seq->addr);
|
||||
dev_info(&phy->dev, "[0x%03x] = 0x%08x\n",
|
||||
seq->addr, seq->val);
|
||||
}
|
||||
|
||||
reset_control_deassert(priv->phy_rst);
|
||||
|
||||
/* Wait for PHY RTUNE acknowledgment */
|
||||
timeout = 100;
|
||||
while (timeout--) {
|
||||
val = readl(priv->mmio + E16PHY_RES_RTUNE_REG);
|
||||
if (val & PHY_RTUNE_ACK)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
dev_err(&phy->dev, "PHY RTUNE timeout\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto err_disable_clks;
|
||||
}
|
||||
|
||||
e16phy_dump_mmio(&phy->dev, priv->mmio, 0x100);
|
||||
mdelay(200);
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable_clks:
|
||||
clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int zhihe_e16phy_exit(struct phy *phy)
|
||||
{
|
||||
struct zhihe_e16phy_priv *priv = phy_get_drvdata(phy);
|
||||
|
||||
clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
|
||||
reset_control_assert(priv->phy_rst);
|
||||
reset_control_assert(priv->apb_rst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void zhihe_e16phy_gpio_set_value(struct gpio_descs *gpios, int val)
|
||||
{
|
||||
if (!gpios)
|
||||
return;
|
||||
for (int i = 0; i < gpios->ndescs; i++)
|
||||
gpiod_set_value(gpios->desc[i], val);
|
||||
}
|
||||
|
||||
static int zhihe_e16phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
{
|
||||
struct zhihe_e16phy_priv *priv = phy_get_drvdata(phy);
|
||||
|
||||
/* Actually We don't care EP/RC mode, but just record it */
|
||||
switch (mode) {
|
||||
case PHY_MODE_SATA:
|
||||
priv->mode = PHY_MODE_SATA;
|
||||
zhihe_e16phy_gpio_set_value(priv->base_en, 1);
|
||||
zhihe_e16phy_gpio_set_value(priv->sata_en, 1);
|
||||
break;
|
||||
case PHY_MODE_PCIE:
|
||||
priv->mode = PHY_MODE_PCIE;
|
||||
zhihe_e16phy_gpio_set_value(priv->base_en, 1);
|
||||
zhihe_e16phy_gpio_set_value(priv->pcie_en, 1);
|
||||
break;
|
||||
default:
|
||||
dev_err(&phy->dev, "%s, invalid mode\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ops zhihe_e16phy_ops = {
|
||||
.init = zhihe_e16phy_init,
|
||||
.exit = zhihe_e16phy_exit,
|
||||
.set_mode = zhihe_e16phy_set_mode,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int zhihe_e16phy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct zhihe_e16phy_priv *priv;
|
||||
struct phy_provider *phy_provider;
|
||||
const char *mode_name;
|
||||
char prop_name[64];
|
||||
int ret, size;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
|
||||
if (IS_ERR(priv->mmio))
|
||||
return PTR_ERR(priv->mmio);
|
||||
|
||||
priv->phy = devm_phy_create(dev, NULL, &zhihe_e16phy_ops);
|
||||
if (IS_ERR(priv->phy)) {
|
||||
dev_err(dev, "failed to create combphy\n");
|
||||
return PTR_ERR(priv->phy);
|
||||
}
|
||||
|
||||
priv->apb_rst = devm_reset_control_get_shared(dev, "apb");
|
||||
if (IS_ERR(priv->apb_rst))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->apb_rst),
|
||||
"failed to get apb reset control\n");
|
||||
|
||||
priv->phy_rst = devm_reset_control_get_shared(dev, "phy");
|
||||
if (IS_ERR(priv->phy_rst))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->phy_rst),
|
||||
"failed to get phy reset control\n");
|
||||
|
||||
priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
|
||||
if (priv->num_clks < 1)
|
||||
return dev_err_probe(dev, priv->num_clks, "failed to get clocks\n");
|
||||
|
||||
/* Get init-seq-select property to determine which init-seq to use */
|
||||
ret = of_property_read_string(dev->of_node, "init-seq-select",
|
||||
&mode_name);
|
||||
if (ret) {
|
||||
return dev_err_probe(dev, ret, "failed to get init-seq-select property\n");
|
||||
}
|
||||
|
||||
snprintf(prop_name, sizeof(prop_name), "init-seq-%s", mode_name);
|
||||
size = of_property_count_u32_elems(dev->of_node, prop_name);
|
||||
if (size < 0) {
|
||||
return dev_err_probe(dev, size, "failed to find property '%s'\n", prop_name);
|
||||
}
|
||||
|
||||
priv->num_init_seq = size / 2;
|
||||
priv->init_seq = devm_kmalloc_array(dev, priv->num_init_seq,
|
||||
sizeof(*priv->init_seq), GFP_KERNEL);
|
||||
if (!priv->init_seq)
|
||||
return dev_err_probe(dev, -ENOMEM, "failed to allocate init_seq\n");
|
||||
|
||||
ret = of_property_read_u32_array(dev->of_node, prop_name,
|
||||
(u32 *)priv->init_seq, size);
|
||||
if (ret) {
|
||||
return dev_err_probe(dev, ret, "failed to read property '%s'\n", prop_name);
|
||||
}
|
||||
|
||||
/* Get base-en-gpios property */
|
||||
priv->base_en = devm_gpiod_get_array_optional(&pdev->dev,
|
||||
"base-en", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(priv->base_en))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(priv->base_en),
|
||||
"Failed to get base-en GPIO");
|
||||
|
||||
priv->pcie_en = devm_gpiod_get_array_optional(&pdev->dev,
|
||||
"pcie-en", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(priv->pcie_en))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(priv->pcie_en),
|
||||
"Failed to get pcie-en GPIO");
|
||||
|
||||
priv->sata_en = devm_gpiod_get_array_optional(&pdev->dev,
|
||||
"sata-en", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(priv->sata_en))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(priv->sata_en),
|
||||
"Failed to get sata-en GPIO");
|
||||
|
||||
dev_set_drvdata(dev, priv);
|
||||
phy_set_drvdata(priv->phy, priv);
|
||||
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
|
||||
return PTR_ERR_OR_ZERO(phy_provider);
|
||||
}
|
||||
|
||||
static const struct of_device_id zhihe_e16phy_of_match[] = {
|
||||
{ .compatible = "zhihe,a210-e16phy" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, zhihe_e16phy_of_match);
|
||||
|
||||
static struct platform_driver zhihe_e16phy_driver = {
|
||||
.probe = zhihe_e16phy_probe,
|
||||
.driver = {
|
||||
.name = "zhihe-snps-pcie3-phy",
|
||||
.of_match_table = zhihe_e16phy_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(zhihe_e16phy_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Zhihe Synopsys PCIe 3.0 PHY driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -115,7 +115,7 @@
|
||||
/* ---------------------------------- PLL ------------------------------- */
|
||||
|
||||
#define FCLKIN_FREQ_MIN 2000UL /* in KHz */
|
||||
#define FCLKIN_FREQ_MAX 297000UL
|
||||
#define FCLKIN_FREQ_MAX 594000UL
|
||||
#define FOUT_FREQ_MIN 40000UL
|
||||
#define FOUT_FREQ_MAX 2500000UL
|
||||
#define CFGCLK_FREQ_MIN 17000UL
|
||||
@@ -726,6 +726,8 @@ static int dw_dphy_runtime_suspend(struct device *dev)
|
||||
clk_disable_unprepare(dphy->refclk);
|
||||
clk_disable_unprepare(dphy->cfgclk);
|
||||
clk_disable_unprepare(dphy->pclk);
|
||||
clk_disable_unprepare(dphy->prefclk);
|
||||
clk_disable_unprepare(dphy->pcfgclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -753,10 +755,20 @@ static int dw_dphy_runtime_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dphy->prefclk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to prepare/enable prefclk\n");
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dphy->pcfgclk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to prepare/enable pcfgclk\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_dphy_resume(struct device *dev)
|
||||
static int __maybe_unused dw_dphy_resume(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct dw_dphy *dphy = dev_get_drvdata(dev);
|
||||
@@ -764,6 +776,8 @@ static int dw_dphy_resume(struct device *dev)
|
||||
clk_disable_unprepare(dphy->refclk);
|
||||
clk_disable_unprepare(dphy->cfgclk);
|
||||
clk_disable_unprepare(dphy->pclk);
|
||||
clk_disable_unprepare(dphy->prefclk);
|
||||
clk_disable_unprepare(dphy->pcfgclk);
|
||||
|
||||
ret = clk_prepare_enable(dphy->pclk);
|
||||
if (ret) {
|
||||
@@ -783,19 +797,33 @@ static int dw_dphy_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dphy->pcfgclk);
|
||||
if (ret) {
|
||||
dev_err(dev, "dphy resume failed to prepare/enable pcfgclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dphy->prefclk);
|
||||
if (ret) {
|
||||
dev_err(dev, "dphy resume failed to prepare/enable prefclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dw_dphy_config_testclr(dphy, 1);
|
||||
dw_dphy_config_testclr(dphy, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_dphy_suspend(struct device *dev)
|
||||
static int __maybe_unused dw_dphy_suspend(struct device *dev)
|
||||
{
|
||||
struct dw_dphy *dphy = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(dphy->refclk);
|
||||
clk_disable_unprepare(dphy->cfgclk);
|
||||
clk_disable_unprepare(dphy->pclk);
|
||||
clk_disable_unprepare(dphy->prefclk);
|
||||
clk_disable_unprepare(dphy->pcfgclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
229
drivers/phy/zhihe/phy-zhihe-snps-usb2.c
Normal file
229
drivers/phy/zhihe/phy-zhihe-snps-usb2.c
Normal file
@@ -0,0 +1,229 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* phy-zhihe-snps-femto-v2.c - ZHIHE USB 2.0 PHY driver
|
||||
*
|
||||
* Based on PHY operations from dwc2-zhihe.c
|
||||
*
|
||||
* Copyright (C) 2025, Anonymous <Anonymous@zhcomputing.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
/* USB20 BLK SYSREG registers */
|
||||
#define PHY_CFG 0x4
|
||||
#define PHY_DM_PULLDOWN BIT(1)
|
||||
#define PHY_DP_PULLDOWN BIT(0)
|
||||
#define PHY_DMDP_PULLDOWN (PHY_DM_PULLDOWN | PHY_DP_PULLDOWN)
|
||||
|
||||
struct usb2_phy_seq {
|
||||
u32 addr;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
struct zhihe_usb2_phy_priv {
|
||||
struct device *dev;
|
||||
struct phy *phy;
|
||||
struct regmap *regs;
|
||||
enum phy_mode mode;
|
||||
int num_clks;
|
||||
struct clk_bulk_data *clks;
|
||||
struct reset_control *phy_rst;
|
||||
struct gpio_desc *pwren;
|
||||
struct usb2_phy_seq *init_seq;
|
||||
int num_init_seq;
|
||||
void (*usb_phy_config)(struct zhihe_usb2_phy_priv *priv);
|
||||
};
|
||||
|
||||
static const struct regmap_config zhihe_usb2_phy_regmap_cfg = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.disable_locking = true,
|
||||
.max_register = 0x40,
|
||||
};
|
||||
|
||||
static void usb_phy0_config(struct zhihe_usb2_phy_priv *priv)
|
||||
{
|
||||
regmap_set_bits(priv->regs, PHY_CFG, PHY_DMDP_PULLDOWN);
|
||||
}
|
||||
|
||||
static void usb_phy1_config(struct zhihe_usb2_phy_priv *priv)
|
||||
{
|
||||
regmap_set_bits(priv->regs, PHY_CFG, PHY_DMDP_PULLDOWN << 2);
|
||||
}
|
||||
|
||||
static int zhihe_usb2_phy_init(struct phy *phy)
|
||||
{
|
||||
struct zhihe_usb2_phy_priv *priv = phy_get_drvdata(phy);
|
||||
int ret;
|
||||
|
||||
/* Set PHY power enable */
|
||||
if (priv->pwren)
|
||||
gpiod_set_value(priv->pwren, 1);
|
||||
|
||||
ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Pull-up the PHY reset */
|
||||
if (priv->usb_phy_config)
|
||||
priv->usb_phy_config(priv);
|
||||
|
||||
ret = reset_control_assert(priv->phy_rst);
|
||||
if (ret)
|
||||
goto disable_clocks;
|
||||
|
||||
usleep_range(100, 150);
|
||||
|
||||
for (int i = 0; i < priv->num_init_seq; i++) {
|
||||
struct usb2_phy_seq *seq = &priv->init_seq[i];
|
||||
regmap_write(priv->regs, seq->addr, seq->val);
|
||||
dev_info(priv->dev, " [0x%03x] = 0x%08x\n", seq->addr, seq->val);
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(priv->phy_rst);
|
||||
if (ret)
|
||||
goto disable_clocks;
|
||||
|
||||
usleep_range(80, 100);
|
||||
|
||||
return 0;
|
||||
disable_clocks:
|
||||
clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int zhihe_usb2_phy_exit(struct phy *phy)
|
||||
{
|
||||
struct zhihe_usb2_phy_priv *priv = phy_get_drvdata(phy);
|
||||
|
||||
/* Assert reset to power down PHY */
|
||||
reset_control_assert(priv->phy_rst);
|
||||
/* Set PHY power disable */
|
||||
if (priv->pwren)
|
||||
gpiod_set_value(priv->pwren, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zhihe_usb2_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
{
|
||||
struct zhihe_usb2_phy_priv *priv = phy_get_drvdata(phy);
|
||||
|
||||
priv->mode = mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct phy_ops zhihe_usb2_phy_ops = {
|
||||
.init = zhihe_usb2_phy_init,
|
||||
.exit = zhihe_usb2_phy_exit,
|
||||
.set_mode = zhihe_usb2_set_mode,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int zhihe_usb2_phy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct zhihe_usb2_phy_priv *priv;
|
||||
struct phy_provider *phy_provider;
|
||||
int ret, size;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->dev = dev;
|
||||
priv->usb_phy_config = device_get_match_data(&pdev->dev);
|
||||
|
||||
/* Check if this PHY shares registers with USB31 controller */
|
||||
if (of_device_is_compatible(dev->of_node, "zhihe,a210-usb2-phy2")) {
|
||||
priv->regs = syscon_regmap_lookup_by_phandle(np, "syscon");
|
||||
if (IS_ERR(priv->regs))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->regs), "Failed to get regmap\n");
|
||||
} else {
|
||||
/* PHY0/PHY1 have dedicated register space */
|
||||
void __iomem *base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
priv->regs = devm_regmap_init_mmio(dev, base, &zhihe_usb2_phy_regmap_cfg);
|
||||
if (IS_ERR(priv->regs)) {
|
||||
dev_err(dev, "Couldn't create regmap\n");
|
||||
return PTR_ERR(priv->regs);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get PHY reset control */
|
||||
priv->phy_rst = devm_reset_control_get_shared(dev, "phy-rst");
|
||||
if (IS_ERR(priv->phy_rst))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->phy_rst),
|
||||
"Couldn't get phy-rst\n");
|
||||
priv->pwren = devm_gpiod_get_optional(&pdev->dev, "pwren", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(priv->pwren))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->pwren),
|
||||
"Failed to get pwren GPIO\n");
|
||||
|
||||
size = of_property_count_u32_elems(dev->of_node, "zhihe,init-seq");
|
||||
if (size < 0)
|
||||
size = 0;
|
||||
priv->num_init_seq = size / 2;
|
||||
priv->init_seq = devm_kmalloc_array(dev, priv->num_init_seq,
|
||||
sizeof(*priv->init_seq), GFP_KERNEL);
|
||||
if (!priv->init_seq)
|
||||
return dev_err_probe(dev, -ENOMEM, "Couldn't allocate init_seq\n");
|
||||
|
||||
ret = of_property_read_u32_array(dev->of_node, "zhihe,init-seq",
|
||||
(u32 *)priv->init_seq, size);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Couldn't read init_seq\n");
|
||||
|
||||
/* Create PHY */
|
||||
priv->phy = devm_phy_create(dev, NULL, &zhihe_usb2_phy_ops);
|
||||
if (IS_ERR(priv->phy))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->phy), "Couldn't create phy\n");
|
||||
|
||||
dev_set_drvdata(dev, priv);
|
||||
phy_set_drvdata(priv->phy, priv);
|
||||
|
||||
/* Register PHY provider */
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
if (IS_ERR(phy_provider))
|
||||
return dev_err_probe(dev, PTR_ERR(phy_provider),
|
||||
"failed to register phy provider\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id zhihe_usb2_phy_of_match[] = {
|
||||
{ .compatible = "zhihe,a210-usb2-phy0", .data = usb_phy0_config},
|
||||
{ .compatible = "zhihe,a210-usb2-phy1", .data = usb_phy1_config},
|
||||
{ .compatible = "zhihe,a210-usb2-phy2", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, zhihe_usb2_phy_of_match);
|
||||
|
||||
static struct platform_driver zhihe_usb2_phy_driver = {
|
||||
.probe = zhihe_usb2_phy_probe,
|
||||
.driver = {
|
||||
.name = "phy-a210-usb2",
|
||||
.of_match_table = zhihe_usb2_phy_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(zhihe_usb2_phy_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ZHIHE USB 2.0 PHY driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Zhu Guangzhao <zhuzg.zhu@zhcomputing.com>");
|
||||
@@ -22,40 +22,18 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <dt-bindings/iopmp/zh-iopmp.h>
|
||||
#include <asm/zh-iopmp.h>
|
||||
|
||||
#include "a210-pd.h"
|
||||
|
||||
static const struct p100_pd_range p100_pd_ranges[] = {
|
||||
{"power_gpu", P100_PD_GPU},
|
||||
{"power_npu_wrapper", P100_PD_NPU_WRAPPER},
|
||||
{"power_npu_ip", P100_PD_NPU_IP},
|
||||
{"power_d2d", P100_PD_D2D},
|
||||
{"power_pcie0", P100_PD_PCIE0},
|
||||
{"power_pcie1", P100_PD_PCIE1},
|
||||
{"power_sata", P100_PD_SATA},
|
||||
{"power_usb", P100_PD_USB},
|
||||
{"power_vi_wrapper", P100_PD_VI_WRAP},
|
||||
{"power_vi_isp", P100_PD_VI_ISP},
|
||||
{"power_vo", P100_PD_VO},
|
||||
{"power_vp_wrapper", P100_PD_VP_WRAP},
|
||||
{"power_venc", P100_PD_VENC},
|
||||
{"power_vdec", P100_PD_VDEC},
|
||||
{"power_top", P100_PD_TOP},
|
||||
{"power_peri0", P100_PD_PERI0},
|
||||
{"power_peri1", P100_PD_PERI1},
|
||||
{"power_peri2", P100_PD_PERI2},
|
||||
{"power_peri3", P100_PD_PERI3},
|
||||
{"power_tee", P100_PD_TEE},
|
||||
};
|
||||
|
||||
static struct dentry *pd_debugfs_root;
|
||||
static struct dentry *pd_pde;
|
||||
|
||||
static inline struct p100_pm_domain *to_p100_pd(struct generic_pm_domain *domain)
|
||||
static inline struct a210_pm_domain *to_a210_pd(struct generic_pm_domain *domain)
|
||||
{
|
||||
return container_of(domain, struct p100_pm_domain, pd);
|
||||
return container_of(domain, struct a210_pm_domain, pd);
|
||||
}
|
||||
|
||||
static void bpc_config(struct device *dev, const char *str, void __iomem *base_addr, u32 bpc_ctrl)
|
||||
@@ -95,10 +73,9 @@ static void pcu_intr(struct device *dev, const char *str, void __iomem *base_add
|
||||
static void pcu_config(struct device *dev, const char *str,
|
||||
void __iomem * base_addr, u32 pcu_ctrl, u32 state)
|
||||
{
|
||||
dev_dbg(dev, "Enter %s pcu_config intr enable...\n", str);
|
||||
writel(0x3f, base_addr + 0x24); // interrupt enable
|
||||
if ((pcu_ctrl & (1 << 0)) != 0) {
|
||||
dev_dbg(dev, "Enter %s pcu_config: pcu reg trigger...\n", str);
|
||||
dev_dbg(dev, "Enter %s pcu_config: pcu reg trigger...state=0x%x\n", str, state);
|
||||
writel((state & 0x1f), base_addr + 0x0c); // lpstate = power on
|
||||
writel(0x1, base_addr + 0x08); // lqreq
|
||||
pcu_intr(dev, str, base_addr); // wait for accept
|
||||
@@ -107,202 +84,92 @@ static void pcu_config(struct device *dev, const char *str,
|
||||
}
|
||||
}
|
||||
|
||||
static void vpss_r2p_intr(struct p100_pd_soc *soc, u32 r2p_ctrl)
|
||||
static int a210_pd_power_switch(struct generic_pm_domain *domain, power_mode mode)
|
||||
{
|
||||
struct a210_pm_domain *a210_pd = to_a210_pd(domain);
|
||||
struct a210_pd_soc *soc = a210_pd->soc;
|
||||
|
||||
struct device *dev = soc->dev;
|
||||
u32 data;
|
||||
void* __iomem base = soc->base[VP_R2P];
|
||||
struct regulator *regulator = soc->regulators[a210_pd->index];
|
||||
const char *name = domain->name;
|
||||
int ret;
|
||||
|
||||
if ((r2p_ctrl & (1 << 0)) == 0) {
|
||||
udelay(1);
|
||||
data = readl(base + 0x1c); // rd r2p intr
|
||||
while (data == 0) {
|
||||
udelay(1);
|
||||
data = readl(base + 0x1c); // rd r2p intr
|
||||
if (mode == ON && regulator != NULL) {
|
||||
ret = regulator_enable(regulator);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to regulator_enable for %s", name);
|
||||
return ret;
|
||||
}
|
||||
if ((data & (1 << 0)) != 0) {
|
||||
dev_dbg(dev, "vpss_r2p_intr accept\n");
|
||||
}
|
||||
if ((data & (1 << 1)) != 0) {
|
||||
dev_err(dev, "vpss_r2p_intr deny\n");
|
||||
}
|
||||
if ((data & (1 << 2)) != 0) {
|
||||
dev_err(dev, "vpss_r2p_intr timeout\n");
|
||||
}
|
||||
writel(data, base + 0x14); // clr pwr pcu intr
|
||||
} else {
|
||||
dev_dbg(dev, "vpss_r2p intr bypass: pcu reg trigger...\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void vpss_r2p_low_power_config(struct p100_pd_soc *soc, u32 r2p_ctrl, u32 pctrl_en)
|
||||
{
|
||||
struct device *dev = soc->dev;
|
||||
int order;
|
||||
//srand((unsigned int)time(NULL));
|
||||
//order = rand() % 2;
|
||||
order = 0;
|
||||
dev_dbg(dev, "Enter vpss_r2p_config: intr enable...\n");
|
||||
writel(0x7, soc->base[VP_R2P] + 0x10); // r2p intr en
|
||||
if ((r2p_ctrl & (1 << 0)) == 0) {
|
||||
writel((0x00001f << 4) | ((pctrl_en & 0x7) << 1) | (order & 0x1), soc->base[VP_R2P] + 0x08); // r2p
|
||||
writel(0x01, soc->base[VP_R2P] + 0x04);
|
||||
if ((pctrl_en & 0x7) == 0x0 || (pctrl_en & 0x7) == 0x2 || (pctrl_en & 0x7) == 0x4 || (pctrl_en & 0x7) == 0x6) {
|
||||
dev_dbg(dev, "Enter vpss_r2p_config: r2p need set: trigger pwr pcu ctrl_en | pctrl_en='h%x, order='h%x\n", pctrl_en, order);
|
||||
} else if ((pctrl_en & 0x7) == 0x1) {
|
||||
dev_dbg(dev, "Enter vpss_r2p_config: pwr pcu ctrl_en, venc&vdec ctrl_dis | pctrl_en='h%x, order='h%x\n", pctrl_en, order);
|
||||
pcu_intr(dev, "vp_wrap_pctrl", soc->base[VP_WRAP_PCU]);
|
||||
} else if ((pctrl_en & 0x7) == 0x3) {
|
||||
dev_dbg(dev, "Enter vpss_r2p_config: pwr&venc pcu ctrl_en,vdec ctrl_dis | pctrl_en='h%x, order='h%x\n", pctrl_en, order);
|
||||
pcu_intr(dev, "vp_venc_pctrl", soc->base[VP_VENC_PCU]);
|
||||
pcu_intr(dev, "vp_wrap_pctrl", soc->base[VP_WRAP_PCU]);
|
||||
} else if ((pctrl_en & 0x7) == 0x5) {
|
||||
dev_dbg(dev, "Enter vpss_r2p_config: pwr&vdec pcu ctrl_en,venc ctrl_dis | pctrl_en='h%x, order='h%x\n", pctrl_en, order);
|
||||
pcu_intr(dev, "vp_vdec_pctrl", soc->base[VP_VDEC_PCU]);
|
||||
pcu_intr(dev, "vp_wrap_pctrl", soc->base[VP_WRAP_PCU]);
|
||||
} else if ((pctrl_en & 0x7) == 0x7) {
|
||||
dev_dbg(dev, "Enter vpss_r2p_config: pwr&venc&vdec pcu ctrl_en ||pctrl_en='h%x, order='h%x\n", pctrl_en, order);
|
||||
pcu_intr(dev, "vp_vdec_pctrl", soc->base[VP_VDEC_PCU]);
|
||||
pcu_intr(dev, "vp_venc_pctrl", soc->base[VP_VENC_PCU]);
|
||||
pcu_intr(dev, "vp_wrap_pctrl", soc->base[VP_WRAP_PCU]);
|
||||
}
|
||||
dev_dbg(dev, "Enter vpss_r2p_config: r2p trigger pcu...\n");
|
||||
} else {
|
||||
dev_dbg(dev, "vpss_r2p_config bypass: pcu reg trigger...\n");
|
||||
}
|
||||
vpss_r2p_intr(soc->base[VP_R2P], r2p_ctrl);
|
||||
}
|
||||
|
||||
static int p100_ip_pd_switch(struct device *dev, const char *name, void __iomem *pca_base,
|
||||
void __iomem *bpc_base, void __iomem *pcu_base, power_mode mode)
|
||||
{
|
||||
/* usb ss can't power off because uart4(peri2) is inside it's power domain. */
|
||||
if (strcmp(name, "power_usb") == 0 && mode == OFF)
|
||||
return 0;
|
||||
|
||||
/* config pca if needed */
|
||||
if (mode == ON && pca_base != NULL)
|
||||
writel(0x0, pca_base + 0x20);
|
||||
if (mode == ON && !IS_ERR(a210_pd->pca_base))
|
||||
writel(0x0, a210_pd->pca_base + 0x20);
|
||||
|
||||
bpc_config(dev, name, bpc_base, BPC_HW_MODEL);
|
||||
pcu_config(dev, name, pcu_base, PCU_REG_TRIGGER, mode);
|
||||
if (!IS_ERR(a210_pd->bpc_base))
|
||||
bpc_config(dev, name, a210_pd->bpc_base, BPC_HW_MODEL);
|
||||
if (!IS_ERR(a210_pd->pcu_base))
|
||||
pcu_config(dev, name, a210_pd->pcu_base, PCU_REG_TRIGGER, mode);
|
||||
|
||||
if (mode == OFF && regulator != NULL) {
|
||||
ret = regulator_disable(regulator);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to regulator_disable for %s", name);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p100_pd_power_switch(struct generic_pm_domain *domain, power_mode mode)
|
||||
static int a210_pd_power_off(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct p100_pm_domain *p100_pd = to_p100_pd(domain);
|
||||
struct p100_pd_soc *soc = p100_pd->soc;
|
||||
struct device *dev = soc->dev;
|
||||
int ret;
|
||||
|
||||
switch(p100_pd->index) {
|
||||
case P100_PD_VP_WRAP:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, soc->base[VP_PCA], soc->base[VP_WRAP_BPC],
|
||||
soc->base[VP_WRAP_PCU], mode);
|
||||
vpss_r2p_low_power_config(soc, PCU_REG_TRIGGER, 0x7);
|
||||
break;
|
||||
case P100_PD_VENC:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, NULL, soc->base[VP_VENC_BPC],
|
||||
soc->base[VP_VENC_PCU], mode);
|
||||
break;
|
||||
case P100_PD_VDEC:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, NULL, soc->base[VP_VDEC_BPC],
|
||||
soc->base[VP_VDEC_PCU], mode);
|
||||
break;
|
||||
case P100_PD_GPU:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, soc->base[GPU_PCA], soc->base[GPU_BPC],
|
||||
soc->base[GPU_PCU], mode);
|
||||
break;
|
||||
case P100_PD_NPU_WRAPPER:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, soc->base[NPU_PCA], soc->base[NPU_WRAP_BPC],
|
||||
soc->base[NPU_WRAP_PCU], mode);
|
||||
break;
|
||||
case P100_PD_NPU_IP:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, NULL, soc->base[NPU_IP_BPC],
|
||||
soc->base[NPU_IP_PCU], mode);
|
||||
break;
|
||||
case P100_PD_PCIE0:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, NULL, soc->base[PCIE0_BPC],
|
||||
soc->base[PCIE0_PCU], mode);
|
||||
break;
|
||||
case P100_PD_PCIE1:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, NULL, soc->base[PCIE1_BPC],
|
||||
soc->base[PCIE1_PCU], mode);
|
||||
break;
|
||||
case P100_PD_SATA:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, NULL, soc->base[SATA_BPC],
|
||||
soc->base[SATA_PCU], mode);
|
||||
break;
|
||||
case P100_PD_VI_WRAP:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, NULL, soc->base[VI_WRAP_BPC],
|
||||
soc->base[VI_WRAP_PCU], mode);
|
||||
writel(0x7, soc->base[VI_R2P] + 0x10);
|
||||
break;
|
||||
case P100_PD_VI_ISP:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, NULL, soc->base[VI_ISP_BPC],
|
||||
soc->base[VI_ISP_PCU], mode);
|
||||
break;
|
||||
case P100_PD_VO:
|
||||
ret = p100_ip_pd_switch(dev, domain->name, NULL, soc->base[VO_BPC],
|
||||
soc->base[VO_PCU], mode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int p100_pd_power_off(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct p100_pm_domain *p100_pd = to_p100_pd(domain);
|
||||
struct a210_pm_domain *a210_pd = to_a210_pd(domain);
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_ZH_IOPMP
|
||||
if(p100_pd->device_count > 0)
|
||||
iopmp_disable(p100_pd->device_ids, p100_pd->device_count);
|
||||
if(a210_pd->device_ids_count > 0)
|
||||
iopmp_disable(a210_pd->device_ids, a210_pd->device_ids_count);
|
||||
#endif
|
||||
|
||||
if (p100_pd->num_clks)
|
||||
clk_bulk_disable(p100_pd->num_clks, p100_pd->clks);
|
||||
if (a210_pd->num_clks)
|
||||
clk_bulk_disable_unprepare(a210_pd->num_clks, a210_pd->clks);
|
||||
|
||||
ret = reset_control_assert(p100_pd->reset);
|
||||
ret = reset_control_assert(a210_pd->reset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return p100_pd_power_switch(domain, OFF);
|
||||
return a210_pd_power_switch(domain, OFF);
|
||||
}
|
||||
|
||||
static int p100_pd_power_on(struct generic_pm_domain *domain)
|
||||
static int a210_pd_power_on(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct p100_pm_domain *p100_pd = to_p100_pd(domain);
|
||||
struct a210_pm_domain *a210_pd = to_a210_pd(domain);
|
||||
int ret;
|
||||
|
||||
ret = p100_pd_power_switch(domain, ON);
|
||||
ret = a210_pd_power_switch(domain, ON);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (p100_pd->num_clks) {
|
||||
ret = clk_bulk_enable(p100_pd->num_clks, p100_pd->clks);
|
||||
if (a210_pd->num_clks) {
|
||||
ret = clk_bulk_prepare_enable(a210_pd->num_clks, a210_pd->clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(p100_pd->reset);
|
||||
ret = reset_control_deassert(a210_pd->reset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_ZH_IOPMP
|
||||
if(p100_pd->device_count > 0)
|
||||
iopmp_enable(p100_pd->device_ids, p100_pd->device_count);
|
||||
if(a210_pd->device_ids_count > 0)
|
||||
iopmp_enable(a210_pd->device_ids, a210_pd->device_ids_count);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *p100_pd_get_user_string(const char __user *userbuf, size_t userlen)
|
||||
static char *a210_pd_get_user_string(const char __user *userbuf, size_t userlen)
|
||||
{
|
||||
char *buffer;
|
||||
|
||||
@@ -327,20 +194,20 @@ static char *p100_pd_get_user_string(const char __user *userbuf, size_t userlen)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static ssize_t p100_power_domain_write(struct file *file,
|
||||
static ssize_t a210_power_domain_write(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t userlen, loff_t *ppos)
|
||||
{
|
||||
char *buffer, *start, *end;
|
||||
struct seq_file *m = (struct seq_file *)file->private_data;
|
||||
struct p100_pd_soc *soc = m->private;
|
||||
struct a210_pd_soc *soc = m->private;
|
||||
struct device *dev = soc->dev;
|
||||
struct generic_pm_domain *domain;
|
||||
char pd_name[P100_PD_NAME_SIZE];
|
||||
char pd_state[P100_PD_STATE_NAME_SIZE];
|
||||
char pd_name[A210_PD_NAME_SIZE];
|
||||
char pd_state[A210_PD_STATE_NAME_SIZE];
|
||||
int idx, ret;
|
||||
|
||||
buffer = p100_pd_get_user_string(userbuf, userlen);
|
||||
buffer = a210_pd_get_user_string(userbuf, userlen);
|
||||
if (IS_ERR(buffer))
|
||||
return PTR_ERR(buffer);
|
||||
|
||||
@@ -350,21 +217,16 @@ static ssize_t p100_power_domain_write(struct file *file,
|
||||
end++;
|
||||
|
||||
*end = '\0';
|
||||
strcpy(pd_name, start);
|
||||
dev_dbg(dev, "power domain name: %s\n", pd_name);
|
||||
strlcpy(pd_name, start, sizeof(pd_name));
|
||||
|
||||
/* find the target power domain */
|
||||
for (idx = 0; idx < soc->num_domains; idx++) {
|
||||
domain = &soc->domains[idx]->pd;
|
||||
dev_dbg(dev, "generic pm domain name: %s, user input name: %s, ret = %d\n",
|
||||
domain->name, pd_name, strcmp(pd_name, domain->name));
|
||||
if (strcmp(pd_name, domain->name))
|
||||
continue;
|
||||
dev_dbg(dev, "target pm power domain-%s found, index: %d\n",
|
||||
domain->name, idx);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (idx == soc->num_domains) {
|
||||
dev_err(dev, "no taget power domain-%s found, idx = %d, total pd numbers = %d\n",
|
||||
pd_name, idx, soc->num_domains);
|
||||
@@ -379,8 +241,7 @@ static ssize_t p100_power_domain_write(struct file *file,
|
||||
end++;
|
||||
|
||||
*end = '\0';
|
||||
strcpy(pd_state, start);
|
||||
dev_dbg(dev, "power domain target state: %s\n", pd_state);
|
||||
strlcpy(pd_state, start, sizeof(pd_state));
|
||||
|
||||
if (!strcmp(pd_state, "on")) {
|
||||
ret = domain->power_on(domain);
|
||||
@@ -406,9 +267,9 @@ out:
|
||||
return userlen;
|
||||
}
|
||||
|
||||
static int p100_power_domain_show(struct seq_file *m, void *v)
|
||||
static int a210_power_domain_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct p100_pd_soc *soc = m->private;
|
||||
struct a210_pd_soc *soc = m->private;
|
||||
u32 count = soc->num_domains;
|
||||
int idx;
|
||||
|
||||
@@ -422,101 +283,133 @@ static int p100_power_domain_show(struct seq_file *m, void *v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p100_power_domain_open(struct inode *inode, struct file *file)
|
||||
static int a210_power_domain_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct p100_pd_soc *soc = inode->i_private;
|
||||
struct a210_pd_soc *soc = inode->i_private;
|
||||
|
||||
return single_open(file, p100_power_domain_show, soc);
|
||||
return single_open(file, a210_power_domain_show, soc);
|
||||
}
|
||||
|
||||
static const struct file_operations p100_power_domain_fops = {
|
||||
static const struct file_operations a210_power_domain_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = p100_power_domain_write,
|
||||
.write = a210_power_domain_write,
|
||||
.read = seq_read,
|
||||
.open = p100_power_domain_open,
|
||||
.open = a210_power_domain_open,
|
||||
.llseek = generic_file_llseek,
|
||||
};
|
||||
|
||||
static void pd_debugfs_init(struct p100_pd_soc *soc)
|
||||
static void pd_debugfs_init(struct a210_pd_soc *soc)
|
||||
{
|
||||
pd_debugfs_root = debugfs_create_dir("power_domain", NULL);
|
||||
if (IS_ERR_OR_NULL(pd_debugfs_root))
|
||||
return;
|
||||
|
||||
pd_pde = debugfs_create_file("domain", 0600, pd_debugfs_root,
|
||||
soc, &p100_power_domain_fops);
|
||||
soc, &a210_power_domain_fops);
|
||||
}
|
||||
|
||||
static int p100_domain_lookup(struct device *dev, const char *name)
|
||||
static int a210_domain_lookup(struct device_node *np)
|
||||
{
|
||||
struct p100_pd_soc *pd_soc = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pd_soc->num_ranges; i++) {
|
||||
if (strcmp(pd_soc->pd_ranges[i].name, name) == 0)
|
||||
return pd_soc->pd_ranges[i].index;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p100_add_one_domain(struct device *dev, struct device_node *np)
|
||||
{
|
||||
struct p100_pd_soc *pd_soc = dev_get_drvdata(dev);
|
||||
struct p100_pm_domain *p100_pd;
|
||||
int id;
|
||||
unsigned int id;
|
||||
int ret;
|
||||
|
||||
p100_pd = devm_kzalloc(dev, sizeof(*p100_pd), GFP_KERNEL);
|
||||
if (!p100_pd)
|
||||
return -ENOMEM;
|
||||
ret = of_property_read_u32(np, "id", &id);
|
||||
if (ret)
|
||||
return -ENODEV;
|
||||
|
||||
id = p100_domain_lookup(dev, np->name);
|
||||
if (!id) {
|
||||
goto free_mem;
|
||||
return id;
|
||||
}
|
||||
|
||||
void __iomem *a210_ioremap_resource_by_node(struct device *dev, struct device_node *np, const char *name)
|
||||
{
|
||||
struct resource *res;
|
||||
int idx;
|
||||
int ret;
|
||||
void __iomem *addr;
|
||||
|
||||
idx = of_property_match_string(np, "reg-names", name);
|
||||
if (idx < 0) {
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
p100_pd->index = id;
|
||||
p100_pd->pd.name = np->name;
|
||||
p100_pd->pd.power_off = p100_pd_power_off;
|
||||
p100_pd->pd.power_on = p100_pd_power_on;
|
||||
p100_pd->soc = pd_soc;
|
||||
res = kzalloc(sizeof(*res), GFP_KERNEL);
|
||||
if (!res)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = pm_genpd_init(&p100_pd->pd, NULL, true);
|
||||
ret = of_address_to_resource(np, idx, res);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to init power domain %s index %d",
|
||||
p100_pd->pd.name, p100_pd->index);
|
||||
devm_kfree(dev, p100_pd);
|
||||
kfree(res);
|
||||
dev_err(dev, "Failed to get resource from node %pOF at index %d\n", np, idx);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
addr = devm_ioremap_resource(dev, res);
|
||||
kfree(res);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static int a210_add_one_domain(struct platform_device *pdev, struct device_node *np)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct a210_pd_soc *pd_soc = dev_get_drvdata(dev);
|
||||
struct a210_pm_domain *a210_pd;
|
||||
int ret;
|
||||
|
||||
a210_pd = devm_kzalloc(dev, sizeof(*a210_pd), GFP_KERNEL);
|
||||
if (!a210_pd)
|
||||
return -ENOMEM;
|
||||
|
||||
int id = a210_domain_lookup(np);
|
||||
if (id < 0) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = of_genpd_add_provider_simple(np, &p100_pd->pd);
|
||||
a210_pd->index = id;
|
||||
a210_pd->pd.name = np->name;
|
||||
a210_pd->pd.power_off = a210_pd_power_off;
|
||||
a210_pd->pd.power_on = a210_pd_power_on;
|
||||
a210_pd->soc = pd_soc;
|
||||
|
||||
a210_pd->pca_base = a210_ioremap_resource_by_node(dev, np, "pca");
|
||||
a210_pd->bpc_base = a210_ioremap_resource_by_node(dev, np, "bpc");
|
||||
a210_pd->pcu_base = a210_ioremap_resource_by_node(dev, np, "pcu");
|
||||
|
||||
ret = pm_genpd_init(&a210_pd->pd, NULL, true);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to init power domain %s index %d",
|
||||
a210_pd->pd.name, a210_pd->index);
|
||||
devm_kfree(dev, a210_pd);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = of_genpd_add_provider_simple(np, &a210_pd->pd);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to add PM domain provider for %pOFn: %d\n",
|
||||
np, ret);
|
||||
goto remove_genpd;
|
||||
}
|
||||
|
||||
p100_pd->reset = of_reset_control_array_get_optional_shared(np);
|
||||
if (IS_ERR(p100_pd->reset)) {
|
||||
ret = PTR_ERR(p100_pd->reset);
|
||||
a210_pd->reset = of_reset_control_array_get_optional_shared(np);
|
||||
if (IS_ERR(a210_pd->reset)) {
|
||||
ret = PTR_ERR(a210_pd->reset);
|
||||
dev_err(dev, "failed to get device resets for domain:%s\n", np->name);
|
||||
goto reset_fail;
|
||||
}
|
||||
|
||||
p100_pd->num_clks = of_clk_get_parent_count(np);
|
||||
if (p100_pd->num_clks) {
|
||||
p100_pd->clks = devm_kcalloc(dev, p100_pd->num_clks,
|
||||
sizeof(*p100_pd->clks), GFP_KERNEL);
|
||||
if (!p100_pd->clks) {
|
||||
a210_pd->num_clks = of_clk_get_parent_count(np);
|
||||
if (a210_pd->num_clks) {
|
||||
a210_pd->clks = devm_kcalloc(dev, a210_pd->num_clks,
|
||||
sizeof(*a210_pd->clks), GFP_KERNEL);
|
||||
if (!a210_pd->clks) {
|
||||
ret = -ENOMEM;
|
||||
goto reset_fail;
|
||||
}
|
||||
|
||||
for (int i = 0; i < p100_pd->num_clks; i++) {
|
||||
p100_pd->clks[i].clk = of_clk_get(np, i);
|
||||
if (IS_ERR(p100_pd->clks[i].clk)) {
|
||||
ret = PTR_ERR(p100_pd->clks[i].clk);
|
||||
for (int i = 0; i < a210_pd->num_clks; i++) {
|
||||
a210_pd->clks[i].clk = of_clk_get(np, i);
|
||||
if (IS_ERR(a210_pd->clks[i].clk)) {
|
||||
ret = PTR_ERR(a210_pd->clks[i].clk);
|
||||
dev_err(dev,
|
||||
"failed to get clk at index %d: err:%d for domain:%s\n",
|
||||
i, ret, np->name);
|
||||
@@ -524,17 +417,11 @@ static int p100_add_one_domain(struct device *dev, struct device_node *np)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = clk_bulk_prepare(p100_pd->num_clks, p100_pd->clks);
|
||||
if (ret) {
|
||||
clk_bulk_put(p100_pd->num_clks, p100_pd->clks);
|
||||
goto clk_fail;
|
||||
}
|
||||
}
|
||||
|
||||
pd_soc->domains[pd_soc->num_domains++] = p100_pd;
|
||||
pd_soc->domains[pd_soc->num_domains++] = a210_pd;
|
||||
|
||||
dev_dbg(dev, "added PM domain %s\n", p100_pd->pd.name);
|
||||
dev_dbg(dev, "added PM domain %s\n", a210_pd->pd.name);
|
||||
|
||||
#ifdef CONFIG_ZH_IOPMP
|
||||
/* get iopmps config node */
|
||||
@@ -550,30 +437,30 @@ static int p100_add_one_domain(struct device *dev, struct device_node *np)
|
||||
else {
|
||||
u32 device_id;
|
||||
if (of_property_read_u32(iopmp_node, "device-id", &device_id) == 0) {
|
||||
p100_pd->device_ids[device_id_count] = device_id;
|
||||
a210_pd->device_ids[device_id_count] = device_id;
|
||||
device_id_count++;
|
||||
dev_dbg(dev, "domain %pOFn iopmp node %pOFn: device id: %d\n", np, iopmp_node, device_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
p100_pd->device_count = device_id_count;
|
||||
a210_pd->device_ids_count = device_id_count;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
clk_fail:
|
||||
devm_kfree(dev, p100_pd->clks);
|
||||
devm_kfree(dev, a210_pd->clks);
|
||||
reset_fail:
|
||||
reset_control_put(p100_pd->reset);
|
||||
reset_control_put(a210_pd->reset);
|
||||
remove_genpd:
|
||||
pm_genpd_remove(&p100_pd->pd);
|
||||
free_mem:
|
||||
devm_kfree(dev, p100_pd);
|
||||
pm_genpd_remove(&a210_pd->pd);
|
||||
devm_kfree(dev, a210_pd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int p100_init_pm_domains(struct device *dev)
|
||||
static int a210_init_pm_domains(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *child;
|
||||
struct of_phandle_args child_args, parent_args;
|
||||
@@ -582,8 +469,8 @@ static int p100_init_pm_domains(struct device *dev)
|
||||
for_each_child_of_node(np, child) {
|
||||
if (!of_device_is_available(child))
|
||||
continue;
|
||||
|
||||
ret = p100_add_one_domain(dev, child);
|
||||
|
||||
ret = a210_add_one_domain(pdev, child);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to handle node %pOFn: %d\n",
|
||||
child, ret);
|
||||
@@ -614,245 +501,68 @@ static int p100_init_pm_domains(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int p100_pd_parse_regbase(struct platform_device *pdev)
|
||||
static int a210_pd_parse_regulators(struct device *dev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct p100_pd_soc *priv = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
struct a210_pd_soc *pd_soc = dev_get_drvdata(dev);
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *child, *child_regulator;
|
||||
|
||||
priv->base[PMIC_CTRL] = devm_platform_ioremap_resource_byname(pdev, "AON_PMIC_CTRL");
|
||||
if (WARN_ON(IS_ERR(priv->base[PMIC_CTRL]))) {
|
||||
ret = PTR_ERR(priv->base[PMIC_CTRL]);
|
||||
return ret;
|
||||
for_each_child_of_node(np, child) {
|
||||
if (!of_device_is_available(child))
|
||||
continue;
|
||||
|
||||
int id = a210_domain_lookup(child);
|
||||
if (id < 0) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_property_present(child, "pmic-supply")) {
|
||||
child_regulator = of_parse_phandle(child, "pmic-supply", 0);
|
||||
pd_soc->regulators[id] = regulator_get_optional(dev, child_regulator->name);
|
||||
if (IS_ERR(pd_soc->regulators[id])) {
|
||||
dev_dbg(dev, "Regulator for %s deferred %ld\n", child->name, PTR_ERR(pd_soc->regulators[id]));
|
||||
return -EPROBE_DEFER;
|
||||
} else {
|
||||
u32 max_uV = 0;
|
||||
if (of_property_read_u32(child_regulator, "regulator-max-microvolt", &max_uV) == 0) {
|
||||
regulator_set_voltage(pd_soc->regulators[id], max_uV, max_uV);
|
||||
dev_info(dev, "Set %s voltage target %duV\n",
|
||||
child->name, max_uV);
|
||||
regulator_put(pd_soc->regulators[id]);
|
||||
pd_soc->regulators[id] = devm_regulator_get_optional(dev, child_regulator->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
of_node_put(np);
|
||||
|
||||
priv->base[VP_PCA] = devm_platform_ioremap_resource_byname(pdev, "VP_PCA");
|
||||
if (WARN_ON(IS_ERR(priv->base[VP_PCA]))) {
|
||||
ret = PTR_ERR(priv->base[VP_PCA]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VP_WRAP_BPC] = devm_platform_ioremap_resource_byname(pdev, "VP_WRAP_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[VP_WRAP_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[VP_WRAP_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VP_WRAP_PCU] = devm_platform_ioremap_resource_byname(pdev, "VP_WRAP_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[VP_WRAP_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[VP_WRAP_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VP_R2P] = devm_platform_ioremap_resource_byname(pdev, "VP_R2P");
|
||||
if (WARN_ON(IS_ERR(priv->base[VP_R2P]))) {
|
||||
ret = PTR_ERR(priv->base[VP_R2P]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VP_VENC_BPC] = devm_platform_ioremap_resource_byname(pdev, "VP_VENC_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[VP_VENC_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[VP_VENC_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VP_VENC_PCU] = devm_platform_ioremap_resource_byname(pdev, "VP_VENC_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[VP_VENC_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[VP_VENC_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VP_VDEC_BPC] = devm_platform_ioremap_resource_byname(pdev, "VP_VDEC_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[VP_VDEC_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[VP_VDEC_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VP_VDEC_PCU] = devm_platform_ioremap_resource_byname(pdev, "VP_VDEC_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[VP_VDEC_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[VP_VDEC_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[GPU_PCA] = devm_platform_ioremap_resource_byname(pdev, "GPU_PCA");
|
||||
if (WARN_ON(IS_ERR(priv->base[GPU_PCA]))) {
|
||||
ret = PTR_ERR(priv->base[GPU_PCA]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[GPU_BPC] = devm_platform_ioremap_resource_byname(pdev, "GPU_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[GPU_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[GPU_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[GPU_PCU] = devm_platform_ioremap_resource_byname(pdev, "GPU_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[GPU_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[GPU_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[NPU_PCA] = devm_platform_ioremap_resource_byname(pdev, "NPU_PCA");
|
||||
if (WARN_ON(IS_ERR(priv->base[NPU_PCA]))) {
|
||||
ret = PTR_ERR(priv->base[NPU_PCA]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[NPU_WRAP_BPC] = devm_platform_ioremap_resource_byname(pdev, "NPU_WRAP_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[NPU_WRAP_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[NPU_WRAP_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[NPU_WRAP_PCU] = devm_platform_ioremap_resource_byname(pdev, "NPU_WRAP_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[NPU_WRAP_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[NPU_WRAP_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[NPU_IP_BPC] = devm_platform_ioremap_resource_byname(pdev, "NPU_IP_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[NPU_IP_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[NPU_IP_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[NPU_IP_PCU] = devm_platform_ioremap_resource_byname(pdev, "NPU_IP_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[NPU_IP_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[NPU_IP_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[PCIE0_BPC] = devm_platform_ioremap_resource_byname(pdev, "PCIE0_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[PCIE0_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[PCIE0_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[PCIE0_PCU] = devm_platform_ioremap_resource_byname(pdev, "PCIE0_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[PCIE0_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[PCIE0_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[PCIE1_BPC] = devm_platform_ioremap_resource_byname(pdev, "PCIE1_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[PCIE1_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[PCIE1_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[PCIE1_PCU] = devm_platform_ioremap_resource_byname(pdev, "PCIE1_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[PCIE1_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[PCIE1_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[SATA_BPC] = devm_platform_ioremap_resource_byname(pdev, "SATA_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[SATA_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[SATA_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[SATA_PCU] = devm_platform_ioremap_resource_byname(pdev, "SATA_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[SATA_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[SATA_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[USB_BPC] = devm_platform_ioremap_resource_byname(pdev, "USB_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[USB_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[USB_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[USB_PCU] = devm_platform_ioremap_resource_byname(pdev, "USB_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[USB_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[USB_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VI_R2P] = devm_platform_ioremap_resource_byname(pdev, "VI_R2P");
|
||||
if (WARN_ON(IS_ERR(priv->base[VI_R2P]))) {
|
||||
ret = PTR_ERR(priv->base[VI_R2P]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VI_WRAP_BPC] = devm_platform_ioremap_resource_byname(pdev, "VI_WRAP_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[VI_WRAP_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[VI_WRAP_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VI_WRAP_PCU] = devm_platform_ioremap_resource_byname(pdev, "VI_WRAP_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[VI_WRAP_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[VI_WRAP_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VI_ISP_BPC] = devm_platform_ioremap_resource_byname(pdev, "VI_ISP_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[VI_ISP_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[VI_ISP_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VI_ISP_PCU] = devm_platform_ioremap_resource_byname(pdev, "VI_ISP_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[VI_ISP_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[VI_ISP_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VO_BPC] = devm_platform_ioremap_resource_byname(pdev, "VO_BPC");
|
||||
if (WARN_ON(IS_ERR(priv->base[VO_BPC]))) {
|
||||
ret = PTR_ERR(priv->base[VO_BPC]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base[VO_PCU] = devm_platform_ioremap_resource_byname(pdev, "VO_PCU");
|
||||
if (WARN_ON(IS_ERR(priv->base[VO_PCU]))) {
|
||||
ret = PTR_ERR(priv->base[VO_PCU]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void p100_init_pmic_ctrl(struct device *dev)
|
||||
{
|
||||
struct p100_pd_soc *pd_soc = dev_get_drvdata(dev);
|
||||
|
||||
writel(readl(pd_soc->base[PMIC_CTRL] + 0x50) | 24, pd_soc->base[PMIC_CTRL] + 0x50);
|
||||
writel(AON_AON_I2C0_BADDR + 0x04, pd_soc->base[PMIC_CTRL] + 0x5c);
|
||||
writel(AON_AON_I2C0_BADDR + 0x10, pd_soc->base[PMIC_CTRL] + 0x58);
|
||||
}
|
||||
|
||||
static int p100_pd_probe(struct platform_device *pdev)
|
||||
static int a210_pd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct p100_pd_soc *pd_soc;
|
||||
struct a210_pd_soc *pd_soc;
|
||||
int ret;
|
||||
|
||||
pd_soc = devm_kzalloc(dev, sizeof(*pd_soc), GFP_KERNEL);
|
||||
if (!pd_soc)
|
||||
return -ENOMEM;
|
||||
dev_set_drvdata(dev, pd_soc);
|
||||
|
||||
pd_soc->pd_ranges = p100_pd_ranges;
|
||||
pd_soc->num_ranges = ARRAY_SIZE(p100_pd_ranges);
|
||||
pd_soc->dev = dev;
|
||||
|
||||
ret = p100_pd_parse_regbase(pdev);
|
||||
dev_set_drvdata(dev, pd_soc);
|
||||
|
||||
ret = a210_pd_parse_regulators(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = p100_init_pm_domains(dev);
|
||||
ret = a210_init_pm_domains(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
p100_init_pmic_ctrl(dev);
|
||||
|
||||
pd_debugfs_init(pd_soc);
|
||||
|
||||
pr_cont("Registered p100 power domain:");
|
||||
pr_cont("Registered a210 power domain:");
|
||||
for (int i = 0; i < pd_soc->num_domains; i++) {
|
||||
if (pd_soc->domains[i]) {
|
||||
pr_cont(" %s", pd_soc->domains[i]->pd.name);
|
||||
@@ -863,22 +573,22 @@ static int p100_pd_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id p100_pd_of_match[] = {
|
||||
{ .compatible = "zhihe,p100-power-domain"},
|
||||
static const struct of_device_id a210_pd_of_match[] = {
|
||||
{ .compatible = "zhihe,a210-power-domain"},
|
||||
{ /* Sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, p100_pd_of_match);
|
||||
MODULE_DEVICE_TABLE(of, a210_pd_of_match);
|
||||
|
||||
static struct platform_driver p100_pd_driver = {
|
||||
.probe = p100_pd_probe,
|
||||
static struct platform_driver a210_pd_driver = {
|
||||
.probe = a210_pd_probe,
|
||||
.driver = {
|
||||
.name = "p100-power-domain",
|
||||
.of_match_table = of_match_ptr(p100_pd_of_match),
|
||||
.name = "a210-power-domain",
|
||||
.of_match_table = of_match_ptr(a210_pd_of_match),
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(p100_pd_driver);
|
||||
builtin_platform_driver(a210_pd_driver);
|
||||
|
||||
MODULE_AUTHOR("dong.yan <yand@zhcomputing.com>");
|
||||
MODULE_DESCRIPTION("Zhihe P100 power domain driver");
|
||||
MODULE_DESCRIPTION("Zhihe A210 power domain driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -6,42 +6,18 @@
|
||||
#ifndef __A210_PD_H
|
||||
#define __A210_PD_H
|
||||
|
||||
#define P100_PD_NAME_SIZE 20
|
||||
#define P100_PD_STATE_NAME_SIZE 10
|
||||
#include <dt-bindings/power/a210-power.h>
|
||||
|
||||
#define A210_PD_NAME_SIZE 20
|
||||
#define A210_PD_STATE_NAME_SIZE 10
|
||||
|
||||
#define BPC_SW_MODEL 1
|
||||
#define BPC_HW_MODEL 0
|
||||
#define PCU_REG_TRIGGER 1
|
||||
#define PCU_R2P_TRIGGER 0
|
||||
|
||||
#define AON_AON_I2C0_BADDR 0x3084A000
|
||||
|
||||
#define IOPMP_DEVICES_MAX_COUNT 16
|
||||
|
||||
enum {
|
||||
P100_PD_GPU = 1,
|
||||
P100_PD_NPU_WRAPPER,
|
||||
P100_PD_NPU_IP,
|
||||
P100_PD_D2D,
|
||||
P100_PD_PCIE0,
|
||||
P100_PD_PCIE1,
|
||||
P100_PD_SATA,
|
||||
P100_PD_USB,
|
||||
P100_PD_VI_WRAP,
|
||||
P100_PD_VI_ISP,
|
||||
P100_PD_VO,
|
||||
P100_PD_VP_WRAP,
|
||||
P100_PD_VENC,
|
||||
P100_PD_VDEC,
|
||||
P100_PD_TOP,
|
||||
P100_PD_PERI0,
|
||||
P100_PD_PERI1,
|
||||
P100_PD_PERI2,
|
||||
P100_PD_PERI3,
|
||||
P100_PD_TEE,
|
||||
P100_POWER_DOMAINS_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
PMIC_CTRL,
|
||||
VP_PCA,
|
||||
@@ -75,34 +51,30 @@ enum {
|
||||
VI_ISP_PCU,
|
||||
VO_BPC,
|
||||
VO_PCU,
|
||||
P100_POWER_DOMAIN_REGS_MAX,
|
||||
};
|
||||
|
||||
struct p100_pd_range {
|
||||
char *name;
|
||||
u32 index;
|
||||
A210_POWER_DOMAIN_REGS_MAX,
|
||||
};
|
||||
|
||||
/* represent power domains info at soc level */
|
||||
struct p100_pd_soc {
|
||||
const struct p100_pd_range *pd_ranges;
|
||||
u8 num_ranges;
|
||||
struct p100_pm_domain *domains[P100_POWER_DOMAINS_MAX];
|
||||
u8 num_domains;
|
||||
struct a210_pd_soc {
|
||||
struct device *dev;
|
||||
void __iomem *base[P100_POWER_DOMAIN_REGS_MAX];
|
||||
struct a210_pm_domain *domains[A210_POWER_DOMAINS_MAX];
|
||||
u32 num_domains;
|
||||
struct regulator *regulators[A210_POWER_DOMAINS_MAX];
|
||||
};
|
||||
|
||||
/* represent a single power domain */
|
||||
struct p100_pm_domain {
|
||||
struct a210_pm_domain {
|
||||
struct generic_pm_domain pd;
|
||||
u16 index;
|
||||
struct p100_pd_soc *soc;
|
||||
struct a210_pd_soc *soc;
|
||||
struct reset_control *reset;
|
||||
struct clk_bulk_data *clks;
|
||||
u32 num_clks;
|
||||
u32 device_count;
|
||||
u32 device_ids[IOPMP_DEVICES_MAX_COUNT];
|
||||
u32 device_ids_count;
|
||||
void __iomem *pca_base;
|
||||
void __iomem *bpc_base;
|
||||
void __iomem *pcu_base;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#define THEAD_PWM_MAX_NUM 6
|
||||
#define THEAD_PWM_MAX_PERIOD GENMASK(31, 0)
|
||||
@@ -220,25 +221,29 @@ static int thead_pwm_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(priv->mmio_base))
|
||||
return PTR_ERR(priv->mmio_base);
|
||||
|
||||
priv->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
||||
if (IS_ERR(priv->clk))
|
||||
return PTR_ERR(priv->clk);
|
||||
|
||||
priv->chip.ops = &thead_pwm_ops;
|
||||
priv->chip.dev = &pdev->dev;
|
||||
priv->chip.npwm = THEAD_PWM_MAX_NUM;
|
||||
|
||||
/* check whether PWM is ever started or not */
|
||||
for (i = 0; i < priv->chip.npwm; i++) {
|
||||
val = readl(priv->mmio_base + THEAD_PWM_FP(i));
|
||||
if (val)
|
||||
priv->channel_ever_started |= 1 << i;
|
||||
}
|
||||
|
||||
ret = devm_pwmchip_add(&pdev->dev, &priv->chip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(priv->clk))
|
||||
return PTR_ERR(priv->clk);
|
||||
|
||||
/* Compatible with the default clock being enabled state. */
|
||||
if (__clk_get_enable_count(priv->clk) > 0) {
|
||||
/* check whether PWM is ever started or not */
|
||||
for (i = 0; i < priv->chip.npwm; i++) {
|
||||
val = readl(priv->mmio_base + THEAD_PWM_FP(i));
|
||||
if (val)
|
||||
priv->channel_ever_started |= 1 << i;
|
||||
}
|
||||
clk_disable_unprepare(priv->clk);
|
||||
}
|
||||
|
||||
devm_pm_runtime_enable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <dt-bindings/reset/a210-reset.h>
|
||||
|
||||
|
||||
#define P100_RST_NAME_SIZE 20
|
||||
#define A210_RST_NAME_SIZE 20
|
||||
|
||||
/* reset subsys enumeration */
|
||||
enum {
|
||||
@@ -26,31 +26,31 @@ enum {
|
||||
USB_RST,
|
||||
TEE_RST,
|
||||
GPU_RST,
|
||||
P100_RESET_SUBSYS_MAX,
|
||||
A210_RESET_SUBSYS_MAX,
|
||||
};
|
||||
|
||||
/* one single reset signal*/
|
||||
struct p100_rst_signal {
|
||||
struct a210_rst_signal {
|
||||
unsigned int offset, bit;
|
||||
};
|
||||
|
||||
/* reset info within a subsys */
|
||||
struct p100_rst_subsys {
|
||||
struct a210_rst_subsys {
|
||||
void __iomem *base;
|
||||
const struct p100_rst_signal *signals;
|
||||
const struct a210_rst_signal *signals;
|
||||
u32 num_signals;
|
||||
char name[P100_RST_NAME_SIZE];
|
||||
char name[A210_RST_NAME_SIZE];
|
||||
};
|
||||
|
||||
struct p100_reset {
|
||||
struct a210_reset {
|
||||
struct device *dev;
|
||||
struct reset_controller_dev reset;
|
||||
struct p100_rst_subsys *subsys;
|
||||
struct a210_rst_subsys *subsys;
|
||||
u32 num_subsys;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal vp_rst_signals[] = {
|
||||
static const struct a210_rst_signal vp_rst_signals[] = {
|
||||
[VP_VDEC_PRST & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[VP_VDEC_CRST & RST_SIGNAL_MASK] = {0, BIT(1)},
|
||||
[VP_VDEC_ARST & RST_SIGNAL_MASK] = {0, BIT(2)},
|
||||
@@ -76,7 +76,7 @@ static const struct p100_rst_signal vp_rst_signals[] = {
|
||||
[VP_DECOMP_EXTPRST & RST_SIGNAL_MASK] = {0, BIT(23)},
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal vi_rst_signals[] = {
|
||||
static const struct a210_rst_signal vi_rst_signals[] = {
|
||||
[VI_MIPI0_CSI0_PRST & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[VI_MIPI0_CSI1_PRST & RST_SIGNAL_MASK] = {0, BIT(1)},
|
||||
[VI_MIPI0_FIFO_RST & RST_SIGNAL_MASK] = {0, BIT(2)},
|
||||
@@ -109,7 +109,7 @@ static const struct p100_rst_signal vi_rst_signals[] = {
|
||||
[VI_REC_ARST & RST_SIGNAL_MASK] = {0, BIT(30)},
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal npu_rst_signals[] = {
|
||||
static const struct a210_rst_signal npu_rst_signals[] = {
|
||||
[NPU_AAB_MST_RST & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[NPU_AFENCE_RST & RST_SIGNAL_MASK] = {0, BIT(1)},
|
||||
[NPU_AXI_CCU_PRST & RST_SIGNAL_MASK] = {0, BIT(2)},
|
||||
@@ -140,7 +140,7 @@ static const struct p100_rst_signal npu_rst_signals[] = {
|
||||
[NPU_SRAM_RST & RST_SIGNAL_MASK] = {0, BIT(27)},
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal vo_rst_signals[] = {
|
||||
static const struct a210_rst_signal vo_rst_signals[] = {
|
||||
[VO_X2H0_RST & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[VO_X2H1_RST & RST_SIGNAL_MASK] = {0, BIT(1)},
|
||||
[VO_DPU_HRST & RST_SIGNAL_MASK] = {0, BIT(2)},
|
||||
@@ -162,7 +162,7 @@ static const struct p100_rst_signal vo_rst_signals[] = {
|
||||
[VO_DFMU_ARST & RST_SIGNAL_MASK] = {0, BIT(18)},
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal peri0_rst_signals[] = {
|
||||
static const struct a210_rst_signal peri0_rst_signals[] = {
|
||||
[PERI0_TIMER0_CRST & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[PERI0_TIMER0_PRST & RST_SIGNAL_MASK] = {0, BIT(1)},
|
||||
[PERI0_TIMER1_CRST & RST_SIGNAL_MASK] = {0, BIT(2)},
|
||||
@@ -170,9 +170,11 @@ static const struct p100_rst_signal peri0_rst_signals[] = {
|
||||
[PERI0_WDT0_PRST & RST_SIGNAL_MASK] = {0, BIT(4)},
|
||||
[PERI0_MBOX0_PRST & RST_SIGNAL_MASK] = {0, BIT(5)},
|
||||
[PERI0_MBOX1_PRST & RST_SIGNAL_MASK] = {0, BIT(6)},
|
||||
[PERI0_TIMER0_RST & RST_SIGNAL_MASK] = {0, BIT(0) | BIT(1)},
|
||||
[PERI0_TIMER1_RST & RST_SIGNAL_MASK] = {0, BIT(2) | BIT(3)},
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal peri1_rst_signals[] = {
|
||||
static const struct a210_rst_signal peri1_rst_signals[] = {
|
||||
[PERI1_GMAC0_ARST & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[PERI1_GMAC0_HRST & RST_SIGNAL_MASK] = {0, BIT(1)},
|
||||
[PERI1_GMAC1_ARST & RST_SIGNAL_MASK] = {0, BIT(2)},
|
||||
@@ -233,7 +235,7 @@ static const struct p100_rst_signal peri1_rst_signals[] = {
|
||||
[PERI1_ZGMAC_X2X_ARST & RST_SIGNAL_MASK] = {0x4, BIT(25)},
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal peri2_rst_signals[] = {
|
||||
static const struct a210_rst_signal peri2_rst_signals[] = {
|
||||
[PERI2_CAN2_IPG_PE_RST & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[PERI2_CAN2_IPG_RST & RST_SIGNAL_MASK] = {0, BIT(1)},
|
||||
[PERI2_CAN2_IPG_SOFT_RST & RST_SIGNAL_MASK] = {0, BIT(2)},
|
||||
@@ -279,7 +281,7 @@ static const struct p100_rst_signal peri2_rst_signals[] = {
|
||||
[PERI2_PWM2_PRST & RST_SIGNAL_MASK] = {0x4, BIT(10)},
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal peri3_rst_signals[] = {
|
||||
static const struct a210_rst_signal peri3_rst_signals[] = {
|
||||
[PERI3_DMAC_ARESET & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[PERI3_DMAC_HRESET & RST_SIGNAL_MASK] = {0, BIT(1)},
|
||||
[PERI3_EMMC_SDIO_CLKGEN_RST & RST_SIGNAL_MASK] = {0, BIT(2)},
|
||||
@@ -300,7 +302,7 @@ static const struct p100_rst_signal peri3_rst_signals[] = {
|
||||
[PERI3_PAD_CTRL_PRST & RST_SIGNAL_MASK] = {0, BIT(17)},
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal pcie_rst_signals[] = {
|
||||
static const struct a210_rst_signal pcie_rst_signals[] = {
|
||||
[PCIE_X2X_PERI_SLV_ARST & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[PCIE_X2X_PERI_MST_ARST & RST_SIGNAL_MASK] = {0, BIT(4)},
|
||||
[PCIE_AXI4_PCIE_MST_ARST & RST_SIGNAL_MASK] = {0, BIT(8)},
|
||||
@@ -329,7 +331,7 @@ static const struct p100_rst_signal pcie_rst_signals[] = {
|
||||
[PCIE_RP_MST_AFENCE_ARST & RST_SIGNAL_MASK] = {0x24, BIT(20)},
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal usb_rst_signals[] = {
|
||||
static const struct a210_rst_signal usb_rst_signals[] = {
|
||||
[USB_DFMU_PRST & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[USB_DFMU_ARST & RST_SIGNAL_MASK] = {0, BIT(4)},
|
||||
[USB_AXI4_MST_ARST & RST_SIGNAL_MASK] = {0, BIT(8)},
|
||||
@@ -363,7 +365,7 @@ static const struct p100_rst_signal usb_rst_signals[] = {
|
||||
[USB_PERI2_SLV_AFENCE_ARST & RST_SIGNAL_MASK] = {0x20, BIT(4)},
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal tee_rst_signals[] = {
|
||||
static const struct a210_rst_signal tee_rst_signals[] = {
|
||||
[TEE_KEYRAM_PRST & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[TEE_DS_PRST & RST_SIGNAL_MASK] = {0, BIT(1)},
|
||||
[TEE_EFUSE_PRST & RST_SIGNAL_MASK] = {0, BIT(2)},
|
||||
@@ -388,12 +390,12 @@ static const struct p100_rst_signal tee_rst_signals[] = {
|
||||
[TEE_AHB2_TEESYS_HRST & RST_SIGNAL_MASK] = {0, BIT(29)},
|
||||
};
|
||||
|
||||
static const struct p100_rst_signal gpu_rst_signals[] = {
|
||||
static const struct a210_rst_signal gpu_rst_signals[] = {
|
||||
[GPU_PWR_WRAP_RGX_HOOD_RST & RST_SIGNAL_MASK] = {0, BIT(0)},
|
||||
[GPU_PWR_WRAP_DFMU_RST & RST_SIGNAL_MASK] = {0, BIT(1)},
|
||||
};
|
||||
|
||||
static struct p100_rst_subsys subsys[] = {
|
||||
static struct a210_rst_subsys subsys[] = {
|
||||
[VP_RST] = {
|
||||
.signals = vp_rst_signals,
|
||||
.num_signals = ARRAY_SIZE(vp_rst_signals),
|
||||
@@ -456,13 +458,13 @@ static struct p100_rst_subsys subsys[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int p100_reset_parse_regbase(struct platform_device *pdev)
|
||||
static int a210_reset_parse_regbase(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct p100_reset *priv = dev_get_drvdata(dev);
|
||||
struct a210_reset *priv = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
for (int i = 0; i < P100_RESET_SUBSYS_MAX; i++) {
|
||||
for (int i = 0; i < A210_RESET_SUBSYS_MAX; i++) {
|
||||
priv->subsys[i].base = devm_platform_ioremap_resource_byname(pdev, priv->subsys[i].name);
|
||||
if (WARN_ON(IS_ERR(priv->subsys[i].base))) {
|
||||
return PTR_ERR(priv->subsys[i].base);
|
||||
@@ -472,13 +474,13 @@ static int p100_reset_parse_regbase(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline struct p100_reset *to_p100_reset(struct reset_controller_dev *rcdev)
|
||||
static inline struct a210_reset *to_a210_reset(struct reset_controller_dev *rcdev)
|
||||
{
|
||||
return container_of(rcdev, struct p100_reset, reset);
|
||||
return container_of(rcdev, struct a210_reset, reset);
|
||||
}
|
||||
|
||||
static int p100_reset_subsys_signal_lookup(struct p100_reset *priv, unsigned long id,
|
||||
struct p100_rst_subsys **subsys, const struct p100_rst_signal **signal)
|
||||
static int a210_reset_subsys_signal_lookup(struct a210_reset *priv, unsigned long id,
|
||||
struct a210_rst_subsys **subsys, const struct a210_rst_signal **signal)
|
||||
{
|
||||
u32 subsys_id = id >> 8;
|
||||
u32 signal_id = id & RST_SIGNAL_MASK;
|
||||
@@ -496,17 +498,17 @@ static int p100_reset_subsys_signal_lookup(struct p100_reset *priv, unsigned lon
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p100_reset_update(struct reset_controller_dev *rcdev,
|
||||
static int a210_reset_update(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
u32 reg;
|
||||
struct p100_reset *priv = to_p100_reset(rcdev);
|
||||
struct p100_rst_subsys *subsys;
|
||||
const struct p100_rst_signal *signal;
|
||||
struct a210_reset *priv = to_a210_reset(rcdev);
|
||||
struct a210_rst_subsys *subsys;
|
||||
const struct a210_rst_signal *signal;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
ret = p100_reset_subsys_signal_lookup(priv, id, &subsys, &signal);
|
||||
ret = a210_reset_subsys_signal_lookup(priv, id, &subsys, &signal);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
@@ -525,59 +527,59 @@ static int p100_reset_update(struct reset_controller_dev *rcdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p100_reset_assert(struct reset_controller_dev *rcdev,
|
||||
static int a210_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
return p100_reset_update(rcdev, id, true);
|
||||
return a210_reset_update(rcdev, id, true);
|
||||
}
|
||||
|
||||
static int p100_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
static int a210_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
return p100_reset_update(rcdev, id, false);
|
||||
return a210_reset_update(rcdev, id, false);
|
||||
}
|
||||
|
||||
static int p100_reset_status(struct reset_controller_dev *rcdev,
|
||||
static int a210_reset_status(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct p100_reset *priv = to_p100_reset(rcdev);
|
||||
struct p100_rst_subsys *subsys;
|
||||
const struct p100_rst_signal *signal;
|
||||
struct a210_reset *priv = to_a210_reset(rcdev);
|
||||
struct a210_rst_subsys *subsys;
|
||||
const struct a210_rst_signal *signal;
|
||||
int ret;
|
||||
|
||||
ret = p100_reset_subsys_signal_lookup(priv, id, &subsys, &signal);
|
||||
ret = a210_reset_subsys_signal_lookup(priv, id, &subsys, &signal);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return !!(readl(subsys->base + signal->offset) & signal->bit);
|
||||
}
|
||||
|
||||
static const struct reset_control_ops p100_reset_ops = {
|
||||
.assert = p100_reset_assert,
|
||||
.deassert = p100_reset_deassert,
|
||||
.status = p100_reset_status,
|
||||
static const struct reset_control_ops a210_reset_ops = {
|
||||
.assert = a210_reset_assert,
|
||||
.deassert = a210_reset_deassert,
|
||||
.status = a210_reset_status,
|
||||
};
|
||||
|
||||
static void p100_register_reset(struct platform_device *pdev)
|
||||
static void a210_register_reset(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct p100_reset *priv = dev_get_drvdata(dev);
|
||||
struct a210_reset *priv = dev_get_drvdata(dev);
|
||||
|
||||
priv->reset.ops = &p100_reset_ops;
|
||||
priv->reset.ops = &a210_reset_ops;
|
||||
priv->reset.owner = THIS_MODULE;
|
||||
priv->reset.of_node = dev->of_node;
|
||||
priv->reset.of_reset_n_cells = 1;
|
||||
priv->reset.nr_resets = P100_RESETS_MAX;
|
||||
priv->reset.nr_resets = A210_RESETS_MAX;
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
reset_controller_register(&priv->reset);
|
||||
}
|
||||
|
||||
static int p100_reset_probe(struct platform_device *pdev)
|
||||
static int a210_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct p100_reset *priv;
|
||||
struct a210_reset *priv;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
@@ -589,13 +591,13 @@ static int p100_reset_probe(struct platform_device *pdev)
|
||||
priv->num_subsys = ARRAY_SIZE(subsys);
|
||||
priv->dev = dev;
|
||||
|
||||
ret = p100_reset_parse_regbase(pdev);
|
||||
ret = a210_reset_parse_regbase(pdev);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
p100_register_reset(pdev);
|
||||
a210_register_reset(pdev);
|
||||
|
||||
dev_warn(dev, "succeed to register p100 reset driver\n");
|
||||
dev_info(dev, "succeed to register a210 reset driver\n");
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -604,25 +606,25 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id p100_reset_of_match[] = {
|
||||
{.compatible = "zhihe,p100-reset-controller"},
|
||||
static const struct of_device_id a210_reset_of_match[] = {
|
||||
{.compatible = "zhihe,a210-reset-controller"},
|
||||
{ /* Sentinel */ },
|
||||
};
|
||||
|
||||
struct platform_driver p100_reset_driver = {
|
||||
.probe = p100_reset_probe,
|
||||
struct platform_driver a210_reset_driver = {
|
||||
.probe = a210_reset_probe,
|
||||
.driver = {
|
||||
.name = "p100-reset",
|
||||
.of_match_table = of_match_ptr(p100_reset_of_match),
|
||||
.name = "a210-reset",
|
||||
.of_match_table = of_match_ptr(a210_reset_of_match),
|
||||
},
|
||||
};
|
||||
|
||||
static int p100_reset_init(void)
|
||||
static int a210_reset_init(void)
|
||||
{
|
||||
return platform_driver_register(&p100_reset_driver);
|
||||
return platform_driver_register(&a210_reset_driver);
|
||||
}
|
||||
|
||||
arch_initcall(p100_reset_init);
|
||||
arch_initcall(a210_reset_init);
|
||||
|
||||
MODULE_AUTHOR("dong.yan <yand@zhcomputing.com>");
|
||||
MODULE_DESCRIPTION("Zhihe P100 reset driver");
|
||||
|
||||
@@ -22,4 +22,10 @@ config A210_BMU
|
||||
help
|
||||
This driver provides support for A210 bmu.
|
||||
|
||||
config A210_D2D
|
||||
tristate "A210 d2d driver"
|
||||
default n
|
||||
help
|
||||
This is the d2d driver for A210 Soc.
|
||||
|
||||
endmenu
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user