Release v2.7.0

This commit is contained in:
hongyi
2025-09-03 19:48:10 +08:00
parent 3b13ec5435
commit 9efc54dae0
63 changed files with 2028 additions and 1506 deletions

View File

@@ -69,7 +69,7 @@
riscv,isa = "rv64imafdc_xtheadvector";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicntr", "zicsr",
"zifencei", "zihpm", "xtheadvector";
"zifencei", "zihpm", "xtheadvector", "xtheadsscofpmf";
reg = <0>;
i-cache-block-size = <64>;
i-cache-size = <65536>;
@@ -105,7 +105,7 @@
riscv,isa = "rv64imafdc_xtheadvector";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicntr", "zicsr",
"zifencei", "zihpm", "xtheadvector";
"zifencei", "zihpm", "xtheadvector", "xtheadsscofpmf";
reg = <1>;
i-cache-block-size = <64>;
i-cache-size = <65536>;
@@ -139,7 +139,7 @@
riscv,isa = "rv64imafdc_xtheadvector";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicntr", "zicsr",
"zifencei", "zihpm", "xtheadvector";
"zifencei", "zihpm", "xtheadvector", "xtheadsscofpmf";
reg = <2>;
i-cache-block-size = <64>;
i-cache-size = <65536>;
@@ -173,7 +173,7 @@
riscv,isa = "rv64imafdc_xtheadvector";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicntr", "zicsr",
"zifencei", "zihpm", "xtheadvector";
"zifencei", "zihpm", "xtheadvector", "xtheadsscofpmf";
reg = <3>;
i-cache-block-size = <64>;
i-cache-size = <65536>;

View File

@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_ARCH_ZHIHE) += p100-emu.dtb p100-emu-d2d.dtb p100-evb.dtb
dtb-$(CONFIG_ARCH_ZHIHE) += a210-emu.dtb a210-emu-d2d.dtb a210-evb.dtb

View File

@@ -1,13 +1,13 @@
/dts-v1/;
#include "p100-soc-core.dtsi"
#include "p100-soc-peri.dtsi"
#include "p100-soc-core-die1.dtsi"
#include "p100-soc-peri-die1.dtsi"
#include "p100-platform-emu.dtsi"
#include "a210-soc-core.dtsi"
#include "a210-soc-peri.dtsi"
#include "a210-soc-core-die1.dtsi"
#include "a210-soc-peri-die1.dtsi"
#include "a210-platform-emu.dtsi"
/ {
model = "P100 EMU configuration";
model = "A210 EMU configuration";
aliases {
serial0 = &uart0;
@@ -70,7 +70,7 @@
stdout-path = "serial4";
};
aon_subsys_die0_to_die1:aon_subsys_die0_to_die1 {
compatible = "zhihe,p100-aon";
compatible = "zhihe,a210-aon";
mbox-names = "aon1";
mboxes = <&mbox_920 2 0>;
#mbox-cells = <2>;
@@ -111,7 +111,7 @@
};
&mbox_920 {
compatible = "zhihe,p100-mbox";
compatible = "zhihe,a210-mbox";
reg = <0x00 0x00321000 0x0 0x1000>,
<0x00 0x00320000 0x0 0x1000>,
<0x00 0x00322000 0x0 0x1000>,

View File

@@ -1,11 +1,11 @@
/dts-v1/;
#include "p100-soc-core.dtsi"
#include "p100-soc-peri.dtsi"
#include "p100-platform-emu.dtsi"
#include "a210-soc-core.dtsi"
#include "a210-soc-peri.dtsi"
#include "a210-platform-emu.dtsi"
/ {
model = "P100 EMU configuration";
model = "A210 EMU configuration";
aliases {
serial0 = &uart0;

View File

@@ -1,8 +1,8 @@
/dts-v1/;
#include "p100-soc-core.dtsi"
#include "p100-soc-peri.dtsi"
#include "p100-platform-evb.dtsi"
#include "a210-soc-core.dtsi"
#include "a210-soc-peri.dtsi"
#include "a210-platform-evb.dtsi"
#define SOUND_CARD_LINK(REG, FMT, CPU, M, CODEC, N) \
simple-audio-card,dai-link@##REG { \
@@ -17,7 +17,7 @@
}
/ {
model = "P100 EVB configuration";
model = "A210 EVB configuration";
aliases {
ethernet0 = &gmac0;

View File

@@ -1,8 +1,8 @@
/dts-v1/;
#include "p100-soc-core.dtsi"
#include "p100-soc-peri.dtsi"
#include "p100-platform-evb.dtsi"
#include "a210-soc-core.dtsi"
#include "a210-soc-peri.dtsi"
#include "a210-platform-evb.dtsi"
#define SOUND_CARD_LINK(REG, FMT, CPU, M, CODEC, N) \
simple-audio-card,dai-link@##REG { \
@@ -17,7 +17,7 @@
}
/ {
model = "P100 EVB configuration";
model = "A210 EVB configuration";
aliases {
ethernet0 = &gmac0;

View File

@@ -1,8 +1,8 @@
/dts-v1/;
#include "p100-soc-core.dtsi"
#include "p100-soc-peri.dtsi"
#include "p100-platform-evb.dtsi"
#include "a210-soc-core.dtsi"
#include "a210-soc-peri.dtsi"
#include "a210-platform-evb.dtsi"
#define SOUND_CARD_LINK(REG, FMT, CPU, M, CODEC, N) \
simple-audio-card,dai-link@##REG { \
@@ -17,7 +17,7 @@
}
/ {
model = "P100 EVB configuration";
model = "A210 EVB configuration";
aliases {
ethernet0 = &gmac0;
@@ -295,16 +295,25 @@
&peri1_padctrl {
gmac0_pins: gmac0-0 {
txclk-pins {
pins = "GPIO0_0"; /* GMAC0_TX_CLK */
function = "gmac0";
bias-disable;
drive-strength = <13>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
tx-pins {
pins = "GPIO0_0", /* GMAC0_TX_CLK */
"GPIO0_2", /* GMAC0_TXEN */
pins = "GPIO0_2", /* GMAC0_TXEN */
"GPIO0_3", /* GMAC0_TXD0 */
"GPIO0_4", /* GMAC0_TXD1 */
"GPIO0_5", /* GMAC0_TXD2 */
"GPIO0_6"; /* GMAC0_TXD3 */
function = "gmac0";
bias-disable;
drive-strength = <25>;
drive-strength = <20>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
@@ -319,7 +328,7 @@
"GPIO0_11"; /* GMAC0_RXD3 */
function = "gmac0";
bias-disable;
drive-strength = <1>;
drive-strength = <13>;
input-enable;
input-schmitt-disable;
slew-rate = <0>;
@@ -414,7 +423,7 @@
pins = "GPIO0_18", "GPIO0_20", "GPIO0_21", "GPIO0_22", "GPIO0_23";
function = "qspi0";
bias-disable;
drive-strength = <7>;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
@@ -469,7 +478,7 @@
pins = "GPIO0_25";
function = "can0";
bias-disable;
drive-strength = <25>;
drive-strength = <5>;
input-disable;
input-schmitt-disable;
slew-rate = <1>;
@@ -501,7 +510,7 @@
pins = "GPIO0_27";
function = "can1";
bias-disable;
drive-strength = <25>;
drive-strength = <5>;
input-disable;
input-schmitt-disable;
slew-rate = <1>;
@@ -572,21 +581,28 @@
};
};
gmac1_pins: gmac1-0 {
txclk-pins {
pins = "GPIO1_2"; /* GMAC1_TX_CLK */
function = "gmac1";
bias-disable;
drive-strength = <13>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
tx-pins {
pins = "GPIO1_2", /* GMAC1_TX_CLK */
"GPIO1_4", /* GMAC1_TXEN */
pins = "GPIO1_4", /* GMAC1_TXEN */
"GPIO1_5", /* GMAC1_TXD0 */
"GPIO1_6", /* GMAC1_TXD1 */
"GPIO1_7", /* GMAC1_TXD2 */
"GPIO1_8"; /* GMAC1_TXD3 */
function = "gmac1";
bias-disable;
drive-strength = <25>;
drive-strength = <20>;
input-disable;
input-schmitt-disable;
slew-rate = <0>;
};
rx-pins {
pins = "GPIO1_3", /* GMAC1_RX_CLK */
"GPIO1_9", /* GMAC1_RXDV */
@@ -596,7 +612,7 @@
"GPIO1_13"; /* GMAC1_RXD3 */
function = "gmac1";
bias-disable;
drive-strength = <1>;
drive-strength = <13>;
input-enable;
input-schmitt-disable;
slew-rate = <0>;
@@ -941,7 +957,7 @@
pins = "GPIO3_1";
function = "can2";
bias-disable;
drive-strength = <25>;
drive-strength = <5>;
input-disable;
input-schmitt-disable;
slew-rate = <1>;
@@ -962,7 +978,7 @@
pins = "GPIO3_2", "GPIO3_5", "GPIO3_6", "GPIO3_7", "GPIO3_8";
function = "qspi1";
bias-disable;
drive-strength = <7>;
drive-strength = <13>;
input-enable;
input-schmitt-enable;
slew-rate = <0>;
@@ -1066,16 +1082,14 @@
&spi0 {
cs-gpios = <&gpio0_porta 30 0>;
rx-sample-delay-ns = <4>;
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
spi-max-frequency = <55000000>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>;
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <36000000>;
w25q,fast-read;
status = "okay";
};
};
@@ -1083,33 +1097,35 @@
&spi1 {
cs-gpios = <&gpio2_porta 18 0>;
rx-sample-delay-ns = <4>;
spi-max-frequency = <55000000>;
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>;
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <36000000>;
w25q,fast-read;
status = "okay";
};
};
&qspi0 {
cs-gpios = <&gpio0_porta 19 0>;
rx-sample-dly = <4>;
rx-sample-dly = <2>;
spi-swap-data = <1>;
spi-max-frequency = <55000000>;
pinctrl-names = "default";
pinctrl-0 = <&qspi0_pins>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>;
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
spi-max-frequency = <36000000>;
reg = <0>;
status = "okay";
};
@@ -1117,17 +1133,19 @@
&qspi1 {
cs-gpios = <&gpio2_porta 29 0>;
rx-sample-dly = <4>;
rx-sample-dly = <2>;
spi-swap-data = <1>;
spi-max-frequency = <55000000>;
pinctrl-names = "default";
pinctrl-0 = <&qspi1_pins>;
spi_norflash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <55000000>;
#address-cells = <1>;
#size-cells = <1>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
spi-max-frequency = <36000000>;
reg = <0>;
status = "okay";
@@ -1149,22 +1167,6 @@
};
};
};
spi-nandflash@1 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "spi-nand";
spi-max-frequency = <100000000>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reg = <1>;
status = "disabled";
partition@0 {
label = "nand1";
reg = <0x00000000 0x08000000>;
};
};
};
&i2c0 {
@@ -1663,10 +1665,10 @@
GPMUX_SEL_07 -> 1
GPMUX_SEL_08 -> 1
*/
// &spi0 {
// pinctrl-names = "default";
// pinctrl-0 = <&spi0_pins>;
// };
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
};
/*
expansion IO: pwm2_ch5
@@ -1696,71 +1698,6 @@
pinctrl-0 = <&can1_pins>;
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* FIXME: clk stages overlay to be selected for real SOC. */
/* bringup stage 3: full subsys + high freq */
/* refer to maximum clk freq in p100-soc-core.dtsi */
/* bringup stage 2: full subsys + medium freq*/
// &clk_peri {
// peri1_spi_ssi_clk_frequency = <220000000>;
// peri2_spi_ssi_clk_frequency = <220000000>;
// peri1_qspi_ssi_clk_frequency = <220000000>;
// peri2_qspi_ssi_clk_frequency = <220000000>;
// uart_sclk_frequency = <24000000>;
// emmc_ref_clk_frequency = <203076924>;
// tee_clk_frequency = <200000000>;
// };
// &clk_pcie {
// pcie_ss_axi_m_aclk_frequency = <240000000>;
// };
// &clk_npu {
// npu_cclk_frequency = <600000000>;
// npu_aclk_frequency = <600000000>;
// };
// &emmc {
// max-frequency = <49152000>;
// };
// &sdhci0 {
// max-frequency = <49152000>;
// };
/* bringup stage 1: minisys + low freq */
// &clk {
// top_cfg_aclk_frequency = <165000000>;
// top_pclk_frequency = <82500000>;
// top_amux_clk_frequency = <240000000>;
// iommu_ptw_aclk_frequency = <165000000>;
// noc_cclk_frequency = <240000000>;
// top_cpusys_bus_clk_frequency = <220000000>;
// top_cpusys_pic_clk_frequency = <250000000>;
// };
// &clk_peri {
// peri1_spi_ssi_clk_frequency = <220000000>;
// peri2_spi_ssi_clk_frequency = <220000000>;
// peri1_qspi_ssi_clk_frequency = <220000000>;
// peri2_qspi_ssi_clk_frequency = <220000000>;
// uart_sclk_frequency = <24000000>;
// emmc_ref_clk_frequency = <203076924>;
// peri1_mst_aclk_frequency = <165000000>;
// peri3_mst_aclk_frequency = <220000000>;
// tee_clk_frequency = <200000000>;
// };
// &emmc {
// max-frequency = <49152000>;
// };
// &sdhci0 {
// max-frequency = <49152000>;
// };
&vidmem {
status = "okay";

View File

@@ -1,8 +1,8 @@
/dts-v1/;
#include "p100-soc-core.dtsi"
#include "p100-soc-peri.dtsi"
#include "p100-platform-haps.dtsi"
#include "a210-soc-core.dtsi"
#include "a210-soc-peri.dtsi"
#include "a210-platform-haps.dtsi"
#define SOUND_CARD_LINK(REG, FMT, CPU, M, CODEC, N) \
simple-audio-card,dai-link@##REG { \
@@ -17,7 +17,7 @@
}
/ {
model = "P100 HAPS configuration";
model = "A210 HAPS configuration";
aliases {
ethernet0 = &gmac0;

View File

@@ -222,6 +222,14 @@
status = "disabled";
};
&dm3x4 {
status = "okay";
};
&rp3x1 {
status = "disabled";
};
// &usb31_zhihe {
// status = "disabled";
// };

View File

@@ -3,8 +3,8 @@
* Copyright (C) 2021 Alibaba Group Holding Limited.
*/
#include <dt-bindings/clock/p100-clock.h>
#include <dt-bindings/reset/p100-reset.h>
#include <dt-bindings/clock/a210-clock.h>
#include <dt-bindings/reset/a210-reset.h>
#include <dt-bindings/iopmp/zh-iopmp.h>
/ {
@@ -444,7 +444,7 @@
#clock-cells = <1>;
clocks = <&clk TOP_GPU_CORE_CLK_DIV>;
clock-names = "top_gpu_core_clk";
top_gpu_core_clk_frequency = <786432000>;
top_gpu_core_clk_frequency = <792000000>;
status = "okay";
};
@@ -560,15 +560,15 @@
<&clk TOP_PERI_I2S_8CH0_SRC_CLK_MUX>, <&clk TOP_PERI_SPI_SSI_CLK0_DIV>,
<&clk TOP_PERI_SPI_SSI_CLK1_DIV>, <&clk TOP_PERI_QSPI_SSI_CLK_MUX0>,
<&clk TOP_PERI_QSPI_SSI_CLK_MUX1>, <&clk TOP_PERI_PDM_MCLK_DIV>,
<&clk TOP_UART_SCLK_MUX>, <&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_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>;
clock-names = "peri0_timer_clk", "peri1_i2s0_src_clk", "peri2_i2s1_src_clk",
"peri2_i2s2_src_clk", "peri2_i2s3_src_clk", "peri1_spi_ssi_clk",
"peri2_spi_ssi_clk", "peri1_qspi_ssi_clk", "peri2_qspi_ssi_clk",
"peri1_pdm_mclk", "uart_sclk", "peri1_tdm_src_clk",
"peri1_pdm_mclk", "peri1_tdm_src_clk",
"top_pad_sensor_vclk0_div", "top_pad_sensor_vclk1_div", "peri1_hires_clk",
"peri2_hires_clk", "tee_clk", "emmc_ref_clk",
"peri1_mst_aclk", "peri3_mst_aclk";
@@ -582,7 +582,6 @@
peri1_qspi_ssi_clk_frequency = <421478400>;
peri2_qspi_ssi_clk_frequency = <421478400>;
peri1_pdm_mclk_frequency = <31610880>;
uart_sclk_frequency = <24000000>;
peri1_tdm_src_clk_frequency = <316108800>;
top_pad_sensor_vclk0_div_frequency = <74250000>;
top_pad_sensor_vclk1_div_frequency = <148500000>;

View File

@@ -1,5 +1,5 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/p100-clock.h>
#include <dt-bindings/clock/a210-clock.h>
/ {
soc {
@@ -85,7 +85,7 @@
status = "okay";
};
mbox_920_die1: mbox@2000320000 {
compatible = "zhihe,p100-mbox";
compatible = "zhihe,a210-mbox";
reg = <0x20 0x00321000 0x0 0x1000>, //mailbox1的中断通道
<0x20 0x00320000 0x0 0x1000>,
<0x20 0x00322000 0x0 0x1000>,
@@ -103,14 +103,14 @@
status = "okay";
};
aon_die1_to_die0: aon_subsys_die1_to_die0 {
compatible = "zhihe,p100-aon";
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,p100-aon";
compatible = "zhihe,a210-aon";
mbox-names = "aon3";
mboxes = <&mbox_920_die1 1 0>;
#mbox-cells = <2>;

View File

@@ -1,6 +1,6 @@
#include <dt-bindings/i2c/i2c.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/p100-clock.h>
#include <dt-bindings/clock/a210-clock.h>
#include <dt-bindings/iommu/zh-iommu.h>
#include <dt-bindings/ata/ahci.h>
@@ -180,12 +180,12 @@
};
can0: flexcan@2000000 {
compatible = "fsl,a210-flexcan";
compatible = "fsl,zha210-flexcan";
reg = <0x00 0x2000000 0x0 0x4000>;
interrupt-parent = <&intc>;
interrupts = <261>;
clocks = <&clk_peri PERI1_CAN0_HIRES_CLK_EN>,
<&clk_peri PERI1_CAN0_OSC_CLK_EN>;
<&clk_peri PERI1_CAN0_PCLK_EN>;
clock-names = "ipg", "per";
power-domains = <&power_peri1>;
/* fsl,stop-mode = <&gpr 0x34 29 0x10 18>; */
@@ -193,12 +193,12 @@
};
can1: flexcan@2004000 {
compatible = "fsl,a210-flexcan";
compatible = "fsl,zha210-flexcan";
reg = <0x00 0x2004000 0x0 0x4000>;
interrupt-parent = <&intc>;
interrupts = <262>;
clocks = <&clk_peri PERI1_CAN1_HIRES_CLK_EN>,
<&clk_peri PERI1_CAN1_OSC_CLK_EN>;
<&clk_peri PERI1_CAN1_PCLK_EN>;
clock-names = "ipg", "per";
power-domains = <&power_peri1>;
/* fsl,stop-mode = <&gpr 0x34 29 0x10 18>; */
@@ -206,12 +206,12 @@
};
can2: flexcan@8420000 {
compatible = "fsl,a210-flexcan";
compatible = "fsl,zha210-flexcan";
reg = <0x00 0x8420000 0x0 0x4000>;
interrupt-parent = <&intc>;
interrupts = <263>;
clocks = <&clk_peri PERI2_CAN2_HIRES_CLK_EN>,
<&clk_peri PERI2_CAN2_OSC_CLK_EN>;
<&clk_peri PERI2_CAN2_PCLK_EN>;
clock-names = "ipg", "per";
power-domains = <&power_peri2>;
/* fsl,stop-mode = <&gpr 0x34 29 0x10 18>; */
@@ -278,7 +278,6 @@
power-domains = <&power_peri1>;
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay";
};
@@ -292,7 +291,6 @@
power-domains = <&power_peri1>;
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay";
};
@@ -306,7 +304,6 @@
power-domains = <&power_peri1>;
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay";
};
@@ -320,7 +317,6 @@
power-domains = <&power_peri1>;
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay";
};
@@ -334,7 +330,6 @@
power-domains = <&power_peri2>;
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay";
};
@@ -348,7 +343,6 @@
power-domains = <&power_peri2>;
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay";
};
@@ -362,7 +356,6 @@
power-domains = <&power_peri2>;
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay";
};
@@ -376,7 +369,6 @@
power-domains = <&power_peri2>;
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay";
};
@@ -390,7 +382,6 @@
power-domains = <&power_peri2>;
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay";
};
@@ -404,7 +395,6 @@
power-domains = <&power_peri2>;
reg-shift = <2>;
reg-io-width = <4>;
hw-flow-control = "unsupport";
status = "okay";
};
@@ -424,9 +414,8 @@
reg = <0x00 0x02023000 0x0 0x1000>;
interrupt-parent = <&intc>;
interrupts = <310>;
clocks = <&clk_peri PERI1_SPI0_SSI_CLK_EN>,
<&clk_peri PERI1_SPI0_PCLK_EN>;
clock-names = "sclk", "pclk";
clocks = <&clk_peri PERI1_SPI0_SSI_CLK_EN>;
clock-names = "sclk";
power-domains = <&power_peri1>;
dmas = <&dmac0 9>, <&dmac0 8>;
dma-names = "tx", "rx";
@@ -444,9 +433,8 @@
reg = <0x00 0x08413000 0x0 0x1000>;
interrupt-parent = <&intc>;
interrupts = <311>;
clocks = <&clk_peri PERI2_SPI1_SSI_CLK_EN>,
<&clk_peri PERI2_SPI1_PCLK_EN>;
clock-names = "sclk", "pclk";
clocks = <&clk_peri PERI2_SPI1_SSI_CLK_EN>;
clock-names = "sclk";
power-domains = <&power_peri2>;
dmas = <&dmac0 62>, <&dmac0 61>;
dma-names = "tx", "rx";
@@ -464,9 +452,8 @@
reg = <0x00 0x01000000 0x0 0x4000>;
interrupt-parent = <&intc>;
interrupts = <308>;
clocks = <&clk_peri PERI1_QSPI0_SSI_CLK_EN>,
<&clk_peri PERI1_QSPI0_PCLK_EN>;
clock-names = "sclk", "pclk";
clocks = <&clk_peri PERI1_QSPI0_SSI_CLK_EN>;
clock-names = "sclk";
power-domains = <&power_peri1>;
num-cs = <2>;
#address-cells = <1>;
@@ -479,9 +466,8 @@
reg = <0x00 0x08428000 0x0 0x4000>;
interrupt-parent = <&intc>;
interrupts = <309>;
clocks = <&clk_peri PERI2_QSPI1_SSI_CLK_EN>,
<&clk_peri PERI2_QSPI1_PCLK_EN>;
clock-names = "sclk", "pclk";
clocks = <&clk_peri PERI2_QSPI1_SSI_CLK_EN>;
clock-names = "sclk";
power-domains = <&power_peri2>;
num-cs = <2>;
#address-cells = <1>;
@@ -1552,7 +1538,7 @@
};
mbox_920: mbox@0000310000 {
compatible = "zhihe,p100-mbox";
compatible = "zhihe,a210-mbox";
reg = <0x00 0x00321000 0x0 0x1000>,
<0x00 0x00320000 0x0 0x1000>,
<0x00 0x00311000 0x0 0x1000>;
@@ -1566,7 +1552,7 @@
status = "okay";
};
aon: aon_subsys {
compatible = "zhihe,p100-aon";
compatible = "zhihe,a210-aon";
mbox-names = "aon0";
mboxes = <&mbox_920 1 0>; //parent / channel / type
#mbox-cells = <2>;

View File

@@ -199,4 +199,4 @@ CONFIG_DEBUG_ATOMIC_SLEEP=y
# CONFIG_RCU_TRACE is not set
# CONFIG_FTRACE is not set
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_P100_BMU=y
CONFIG_A210_BMU=y

View File

@@ -150,7 +150,7 @@ CONFIG_UDMABUF=y
CONFIG_DMABUF_SELFTESTS=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
CONFIG_CLK_P100=y
CONFIG_CLK_A210=y
CONFIG_HWSPINLOCK=y
CONFIG_RISCV_IOMMU=y
CONFIG_RESET_CONTROLLER=y
@@ -194,4 +194,4 @@ CONFIG_DEBUG_ATOMIC_SLEEP=y
# CONFIG_RCU_TRACE is not set
# CONFIG_FTRACE is not set
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_P100_BMU=y
CONFIG_A210_BMU=y

View File

@@ -160,7 +160,7 @@ CONFIG_SPI_DW_MMIO=y
CONFIG_SPI_SPIDEV=y
# CONFIG_PTP_1588_CLOCK is not set
CONFIG_PINCTRL=y
CONFIG_PINCTRL_P100=y
CONFIG_PINCTRL_A210=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_DWAPB=y
CONFIG_SENSORS_MR75203=y
@@ -174,6 +174,7 @@ CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=m
CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=m
CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP=y
CONFIG_DW_WATCHDOG=y
CONFIG_A210_WATCHDOG=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
# CONFIG_MEDIA_CEC_SUPPORT is not set
@@ -226,10 +227,11 @@ CONFIG_UDMABUF=y
CONFIG_DMABUF_SELFTESTS=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
CONFIG_CLK_P100=y
CONFIG_CLK_A210=y
CONFIG_HWSPINLOCK=y
CONFIG_MAILBOX=y
CONFIG_RISCV_IOMMU=y
CONFIG_P100_BMU=y
CONFIG_A210_BMU=y
CONFIG_IIO=y
CONFIG_PWM=y
CONFIG_PWM_THEAD=y

View File

@@ -155,7 +155,7 @@ CONFIG_SPI_DW_MMIO=m
CONFIG_SPI_SPIDEV=m
# CONFIG_PTP_1588_CLOCK is not set
CONFIG_PINCTRL=y
CONFIG_PINCTRL_P100=y
CONFIG_PINCTRL_A210=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_DWAPB=y
@@ -203,7 +203,7 @@ CONFIG_UDMABUF=y
CONFIG_DMABUF_SELFTESTS=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
CONFIG_CLK_P100=y
CONFIG_CLK_A210=y
CONFIG_HWSPINLOCK=y
CONFIG_RISCV_IOMMU=y
CONFIG_PWM=y
@@ -252,4 +252,4 @@ CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
# CONFIG_RCU_TRACE is not set
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_P100_BMU=y
CONFIG_A210_BMU=y

View File

@@ -52,6 +52,8 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
CONFIG_CPUFREQ_DT=y
CONFIG_RISCV_XUANTIE_TH1520_CPUFREQ=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=y
CONFIG_ACPI=y
CONFIG_KPROBES=y
# CONFIG_STRICT_KERNEL_RWX is not set

View File

@@ -4,9 +4,9 @@ config ZHIHE_CLK
bool
def_bool ARCH_ZHIHE
config CLK_P100
bool "Zhihe P100 Clock Driver"
config CLK_A210
bool "Zhihe A210 Clock Driver"
depends on ARCH_ZHIHE
default n
help
Build the driver for zhihe p100 Clock Driver
Build the driver for zhihe A210 Clock Driver

View File

@@ -3,4 +3,4 @@
obj-$(CONFIG_ZHIHE_CLK) += \
clk-helper.o
obj-$(CONFIG_CLK_P100) += clk-p100.o
obj-$(CONFIG_CLK_A210) += clk-a210.o

View File

@@ -14,7 +14,7 @@
#include <linux/of_address.h>
#include <linux/types.h>
#include <dt-bindings/clock/p100-clock.h>
#include <dt-bindings/clock/a210-clock.h>
#include "clk-helper.h"
@@ -52,7 +52,6 @@ static const char * const peri2_i2s2_src_clk_parents[] = {"audio1_pll_fout2", "a
static const char * const peri1_qspi_ssi_clk_parents[] = {"peri1_qspi_ssi_clk_div1", "peri1_qspi_ssi_clk_div0"};
static const char * const peri2_qspi_ssi_clk_parents[] = {"peri2_qspi_ssi_clk_div1", "peri2_qspi_ssi_clk_div0"};
static const char * const peri1_tdm_src_clk_parents[] = {"audio1_pll_fout2", "audio0_pll_fout2"};
static const char * const uart_sclk_parents[] = {"uart_sclk_100M", "aon_osc_clk_logic"};
static const char * const pdm_clk_mux_parents[] = {"audio1_pll_fout2", "audio0_pll_fout2"};
static const char * const emmc_ref_clk_mux_parents[] = {"audio0_pll_foutvco", "video_pll_foutvco"};
static const char * const pad_sensor_vclk0_mux_parents[] = {"dpu0_pll_foutvco", "dpu1_pll_foutvco",
@@ -223,8 +222,8 @@ static struct p100_clk_info info_top[] = {
PLL(AUDIO1_PLL_FOUTVCO, "audio1_pll_foutvco", "osc_24m", PLL_WRAP, 0, &plls_top[AUDIO1_PLL]),
FIXED_FACTOR(AUDIO1_PLL_FOUTPOSTDIV, "audio1_pll_foutpostdiv", "audio1_pll_foutvco", 1, 2),
FIXED_FACTOR(AUDIO1_PLL_FOUT2, "audio1_pll_fout2", "audio1_pll_foutvco", 1, 8),
PLL(C908_PLL_FOUTVCO, "c908_pll_foutvco", "osc_24m", PLL_WRAP, 0, &plls_top[C908_PLL]),
PLL(C920_PLL_FOUTVCO, "c920_pll_foutvco", "osc_24m", PLL_WRAP, 0, &plls_top[C920_PLL]),
PLL(C908_PLL_FOUTVCO, "c908_pll_foutvco", "osc_24m", CPU_SS_CPU_PLL, 0, &plls_top[C908_PLL]),
PLL(C920_PLL_FOUTVCO, "c920_pll_foutvco", "osc_24m", CPU_SS_CPU_PLL, 0, &plls_top[C920_PLL]),
PLL(VIDEO_PLL_FOUTVCO, "video_pll_foutvco", "top_pll_ref_clk", PLL_WRAP, 0, &plls_top[VIDEO_PLL]),
FIXED_FACTOR(VIDEO_PLL_FOUTPOSTDIV, "video_pll_foutpostdiv", "video_pll_foutvco", 1, 2),
FIXED_FACTOR(VIDEO_PLL_FOUT1PH0, "video_pll_fout1ph0", "video_pll_foutvco", 1, 4),
@@ -361,9 +360,7 @@ static struct p100_clk_info info_top[] = {
NO_DIV_EN, MUX_TYPE_DIV, 33, 63),
MUX(TOP_PERI_TDM_SRC_CLK_MUX, "peri1_tdm_src_clk", TOP_CRG, 0x28, 25, 1,
peri1_tdm_src_clk_parents, ARRAY_SIZE(peri1_tdm_src_clk_parents), CLK_SET_RATE_PARENT),
FIXED_FACTOR(UART_SCLK_100M, "uart_sclk_100M", "gmac_pll_foutpostdiv", 1, 10),
MUX(TOP_UART_SCLK_MUX, "uart_sclk", TOP_CRG, 0x28, 24, 1,
uart_sclk_parents, ARRAY_SIZE(uart_sclk_parents), CLK_SET_RATE_PARENT),
FIXED_FACTOR(UART_SCLK_100M, "uart_sclk", "gmac_pll_foutpostdiv", 1, 10),
FIXED_FACTOR(PERI1_UART_SCLK, "peri1_uart_sclk", "uart_sclk", 1, 1),
FIXED_FACTOR(PERI2_UART_SCLK, "peri2_uart_sclk", "uart_sclk", 1, 1),
DIV(TOP_PERI_PDM_MCLK_DIV, "peri1_pdm_mclk", "pdm_clk_mux", TOP_CRG, 0x2c, 24, 8,

View File

@@ -9,7 +9,7 @@
#include <linux/spinlock.h>
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/p100-clock.h>
#include <dt-bindings/clock/a210-clock.h>
extern spinlock_t zhihe_p100_clk_lock;

View File

@@ -1,10 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
config P100_AON
bool "P100 Aon Protocol driver"
depends on P100_MBOX
config A210_AON
bool "A210 Aon Protocol driver"
depends on A210_MBOX
default y
help
ZHIHE P100 Aon is a low-level system function which runs a dedicated
ZHIHE A210 Aon is a low-level system function which runs a dedicated
ZHIHE riscv E902 core to provide power, clock and resource management.
This driver manages the IPC interface between host cpu liks thead

View File

@@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_P100_AON) += p100_aon.o
obj-$(CONFIG_A210_AON) += a210_aon.o

View File

@@ -16,7 +16,7 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
//#include <linux/p100_proc_debug.h>
//#include <linux/a210_proc_debug.h>
@@ -25,8 +25,8 @@
#define MAX_RX_TIMEOUT (msecs_to_jiffies(3000))
#define MAX_TX_TIMEOUT (msecs_to_jiffies(500))
struct p100_aon_chan {
struct p100_aon_ipc *aon_ipc;
struct a210_aon_chan {
struct a210_aon_ipc *aon_ipc;
struct mbox_client cl;
struct mbox_chan *ch;
struct completion tx_done;
@@ -38,8 +38,8 @@ struct p100_aon_chan {
struct proc_dir_entry *proc_dir;
};
struct p100_aon_ipc {
struct p100_aon_chan chans;
struct a210_aon_ipc {
struct a210_aon_chan chans;
struct device *dev;
struct mutex lock;
struct completion done;
@@ -50,83 +50,83 @@ struct p100_aon_ipc {
/*
* This type is used to indicate error response for most functions.
*/
enum p100_aon_error_codes {
P100_AON_ERR_NONE = 0, /* Success */
P100_AON_ERR_VERSION = 1, /* Incompatible API version */
P100_AON_ERR_CONFIG = 2, /* Configuration error */
P100_AON_ERR_PARM = 3, /* Bad parameter */
P100_AON_ERR_NOACCESS = 4, /* Permission error (no access) */
P100_AON_ERR_LOCKED = 5, /* Permission error (locked) */
P100_AON_ERR_UNAVAILABLE = 6, /* Unavailable (out of resources) */
P100_AON_ERR_NOTFOUND = 7, /* Not found */
P100_AON_ERR_NOPOWER = 8, /* No power */
P100_AON_ERR_IPC = 9, /* Generic IPC error */
P100_AON_ERR_BUSY = 10, /* Resource is currently busy/active */
P100_AON_ERR_FAIL = 11, /* General I/O failure */
P100_AON_ERR_LAST
enum a210_aon_error_codes {
A210_AON_ERR_NONE = 0, /* Success */
A210_AON_ERR_VERSION = 1, /* Incompatible API version */
A210_AON_ERR_CONFIG = 2, /* Configuration error */
A210_AON_ERR_PARM = 3, /* Bad parameter */
A210_AON_ERR_NOACCESS = 4, /* Permission error (no access) */
A210_AON_ERR_LOCKED = 5, /* Permission error (locked) */
A210_AON_ERR_UNAVAILABLE = 6, /* Unavailable (out of resources) */
A210_AON_ERR_NOTFOUND = 7, /* Not found */
A210_AON_ERR_NOPOWER = 8, /* No power */
A210_AON_ERR_IPC = 9, /* Generic IPC error */
A210_AON_ERR_BUSY = 10, /* Resource is currently busy/active */
A210_AON_ERR_FAIL = 11, /* General I/O failure */
A210_AON_ERR_LAST
};
static int p100_aon_linux_errmap[P100_AON_ERR_LAST] = {
0, /* P100_AON_ERR_NONE */
-EINVAL, /* P100_AON_ERR_VERSION */
-EINVAL, /* P100_AON_ERR_CONFIG */
-EINVAL, /* P100_AON_ERR_PARM */
-EACCES, /* P100_AON_ERR_NOACCESS */
-EACCES, /* P100_AON_ERR_LOCKED */
-ERANGE, /* P100_AON_ERR_UNAVAILABLE */
-EEXIST, /* P100_AON_ERR_NOTFOUND */
-EPERM, /* P100_AON_ERR_NOPOWER */
-EPIPE, /* P100_AON_ERR_IPC */
-EBUSY, /* P100_AON_ERR_BUSY */
-EIO, /* P100_AON_ERR_FAIL */
static int a210_aon_linux_errmap[A210_AON_ERR_LAST] = {
0, /* A210_AON_ERR_NONE */
-EINVAL, /* A210_AON_ERR_VERSION */
-EINVAL, /* A210_AON_ERR_CONFIG */
-EINVAL, /* A210_AON_ERR_PARM */
-EACCES, /* A210_AON_ERR_NOACCESS */
-EACCES, /* A210_AON_ERR_LOCKED */
-ERANGE, /* A210_AON_ERR_UNAVAILABLE */
-EEXIST, /* A210_AON_ERR_NOTFOUND */
-EPERM, /* A210_AON_ERR_NOPOWER */
-EPIPE, /* A210_AON_ERR_IPC */
-EBUSY, /* A210_AON_ERR_BUSY */
-EIO, /* A210_AON_ERR_FAIL */
};
#define P100_AON_CHN_MAX (4)
static struct p100_aon_ipc *p100_aon_ipc_handle[P100_AON_CHN_MAX];
#define A210_AON_CHN_MAX (4)
static struct a210_aon_ipc *a210_aon_ipc_handle[A210_AON_CHN_MAX];
static uint32_t g_aon_ipc_handle_num;
static inline int p100_aon_to_linux_errno(int errno)
static inline int a210_aon_to_linux_errno(int errno)
{
if (errno >= P100_AON_ERR_NONE && errno < P100_AON_ERR_LAST)
return p100_aon_linux_errmap[errno];
if (errno >= A210_AON_ERR_NONE && errno < A210_AON_ERR_LAST)
return a210_aon_linux_errmap[errno];
return -EIO;
}
/*
* Get the default handle used by SCU
*/
int p100_aon_get_handle(struct p100_aon_ipc **ipc, char* name)
int a210_aon_get_handle(struct a210_aon_ipc **ipc, char* name)
{
uint32_t i = 0;
if(!name)
return -1;
for(i = 0;i<g_aon_ipc_handle_num;i++) {
if(!p100_aon_ipc_handle[i])
return -1;
if(!strcmp(name, p100_aon_ipc_handle[i]->mbox_name))) {
*ipc = p100_aon_ipc_handle[i];
if(!a210_aon_ipc_handle[i])
return -EPROBE_DEFER;
if(!strcmp(name, a210_aon_ipc_handle[i]->mbox_name)) {
*ipc = a210_aon_ipc_handle[i];
return 0;
}
}
return -1;
return -EPROBE_DEFER;
}
EXPORT_SYMBOL(p100_aon_get_handle);
EXPORT_SYMBOL(a210_aon_get_handle);
static void p100_aon_tx_done(struct mbox_client *cl, void *mssg, int r)
static void a210_aon_tx_done(struct mbox_client *cl, void *mssg, int r)
{
struct p100_aon_chan *aon_chan =
container_of(cl, struct p100_aon_chan, cl);
struct a210_aon_chan *aon_chan =
container_of(cl, struct a210_aon_chan, cl);
complete(&aon_chan->tx_done);
}
static void p100_aon_rx_callback(struct mbox_client *c, void *msg)
static void a210_aon_rx_callback(struct mbox_client *c, void *msg)
{
struct p100_aon_chan *aon_chan =
container_of(c, struct p100_aon_chan, cl);
struct p100_aon_ipc *aon_ipc = aon_chan->aon_ipc;
struct p100_aon_rpc_msg_hdr *hdr =
(struct p100_aon_rpc_msg_hdr *)msg;
uint8_t recv_size = sizeof(struct p100_aon_rpc_msg_hdr) + hdr->size;
struct a210_aon_chan *aon_chan =
container_of(c, struct a210_aon_chan, cl);
struct a210_aon_ipc *aon_ipc = aon_chan->aon_ipc;
struct a210_aon_rpc_msg_hdr *hdr =
(struct a210_aon_rpc_msg_hdr *)msg;
uint8_t recv_size = sizeof(struct a210_aon_rpc_msg_hdr) + hdr->size;
memcpy(aon_ipc->msg, msg, recv_size);
dev_dbg(aon_ipc->dev, "msg head: 0x%x, size:%d\n", *((u32 *)msg),
@@ -134,14 +134,14 @@ static void p100_aon_rx_callback(struct mbox_client *c, void *msg)
complete(&aon_ipc->done);
}
static int p100_aon_ipc_write(struct p100_aon_ipc *aon_ipc, void *msg)
static int a210_aon_ipc_write(struct a210_aon_ipc *aon_ipc, void *msg)
{
struct p100_aon_rpc_msg_hdr *hdr = msg;
struct p100_aon_chan *aon_chan;
struct a210_aon_rpc_msg_hdr *hdr = msg;
struct a210_aon_chan *aon_chan;
u32 *data = msg;
int ret;
/* check size, currently it requires 7 MSG in one transfer */
if (hdr->size != P100_AON_RPC_MSG_NUM)
if (hdr->size != A210_AON_RPC_MSG_NUM)
return -EINVAL;
dev_dbg(aon_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr->svc,
@@ -164,10 +164,10 @@ static int p100_aon_ipc_write(struct p100_aon_ipc *aon_ipc, void *msg)
/*
* RPC command/response
*/
int p100_aon_call_rpc(struct p100_aon_ipc *aon_ipc, void *msg,
int a210_aon_call_rpc(struct a210_aon_ipc *aon_ipc, void *msg,
void *ack_msg, bool have_resp)
{
struct p100_aon_rpc_msg_hdr *hdr = msg;
struct a210_aon_rpc_msg_hdr *hdr = msg;
int ret = 0;
if (WARN_ON(!aon_ipc || !msg))
return -EINVAL;
@@ -175,7 +175,7 @@ int p100_aon_call_rpc(struct p100_aon_ipc *aon_ipc, void *msg,
return -EINVAL;
mutex_lock(&aon_ipc->lock);
reinit_completion(&aon_ipc->done);
RPC_SET_VER(hdr, P100_AON_RPC_VERSION);
RPC_SET_VER(hdr, A210_AON_RPC_VERSION);
/*svc id use 6bit for version 2*/
RPC_SET_SVC_ID(hdr, hdr->svc);
RPC_SET_SVC_FLAG_MSG_TYPE(hdr, RPC_SVC_MSG_TYPE_DATA);
@@ -185,7 +185,7 @@ int p100_aon_call_rpc(struct p100_aon_ipc *aon_ipc, void *msg,
} else {
RPC_SET_SVC_FLAG_ACK_TYPE(hdr, RPC_SVC_MSG_NO_NEED_ACK);
}
ret = p100_aon_ipc_write(aon_ipc, msg);
ret = a210_aon_ipc_write(aon_ipc, msg);
if (ret < 0) {
dev_err(aon_ipc->dev, "RPC send msg failed: %d\n", ret);
goto out;
@@ -199,7 +199,7 @@ int p100_aon_call_rpc(struct p100_aon_ipc *aon_ipc, void *msg,
}
/* response status is stored in msg data[0] field */
struct p100_aon_rpc_ack_common *ack = ack_msg;
struct a210_aon_rpc_ack_common *ack = ack_msg;
ret = ack->err_code;
}
out:
@@ -207,15 +207,15 @@ out:
dev_dbg(aon_ipc->dev, "RPC SVC done\n");
return p100_aon_to_linux_errno(ret);
return a210_aon_to_linux_errno(ret);
}
EXPORT_SYMBOL(p100_aon_call_rpc);
EXPORT_SYMBOL(a210_aon_call_rpc);
static int p100_aon_probe(struct platform_device *pdev)
static int a210_aon_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct p100_aon_ipc *aon_ipc;
struct p100_aon_chan *aon_chan;
struct a210_aon_ipc *aon_ipc;
struct a210_aon_chan *aon_chan;
struct mbox_client *cl;
struct device_node *np;
int ret;
@@ -227,10 +227,10 @@ static int p100_aon_probe(struct platform_device *pdev)
cl->dev = dev;
cl->tx_block = false;
cl->knows_txdone = true;
cl->rx_callback = p100_aon_rx_callback;
cl->rx_callback = a210_aon_rx_callback;
/* Initial tx_done completion as "done" */
cl->tx_done = p100_aon_tx_done;
cl->tx_done = a210_aon_tx_done;
init_completion(&aon_chan->tx_done);
complete(&aon_chan->tx_done);
@@ -251,45 +251,45 @@ static int p100_aon_probe(struct platform_device *pdev)
mutex_init(&aon_ipc->lock);
init_completion(&aon_ipc->done);
aon_chan->log_ctrl = NULL;
if(g_aon_ipc_handle_num>=P100_AON_CHN_MAX) {
if(g_aon_ipc_handle_num>=A210_AON_CHN_MAX) {
dev_err(dev, "aon_ipc:%s handle num overflow\n",aon_ipc->mbox_name);
return -1;
}
p100_aon_ipc_handle[g_aon_ipc_handle_num] = aon_ipc;
a210_aon_ipc_handle[g_aon_ipc_handle_num] = aon_ipc;
g_aon_ipc_handle_num++;
return devm_of_platform_populate(dev);
}
static const struct of_device_id p100_aon_match[] = {
static const struct of_device_id a210_aon_match[] = {
{
.compatible = "zhihe,p100-aon",
.compatible = "zhihe,a210-aon",
},
{ /* Sentinel */ }
};
static int __maybe_unused p100_aon_resume_noirq(struct device *dev)
static int __maybe_unused a210_aon_resume_noirq(struct device *dev)
{
#if 0
struct p100_aon_chan *aon_chan;
aon_chan = &p100_aon_ipc_handle->chans;
struct a210_aon_chan *aon_chan;
aon_chan = &a210_aon_ipc_handle->chans;
complete(&aon_chan->tx_done);
#endif
return 0;
}
static const struct dev_pm_ops p100_aon_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, p100_aon_resume_noirq)
static const struct dev_pm_ops a210_aon_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, a210_aon_resume_noirq)
};
static struct platform_driver p100_aon_driver = {
static struct platform_driver a210_aon_driver = {
.driver = {
.name = "p100-aon",
.of_match_table = p100_aon_match,
.pm = &p100_aon_pm_ops,
.name = "a210-aon",
.of_match_table = a210_aon_match,
.pm = &a210_aon_pm_ops,
},
.probe = p100_aon_probe,
.probe = a210_aon_probe,
};
builtin_platform_driver(p100_aon_driver);
builtin_platform_driver(a210_aon_driver);
MODULE_AUTHOR("xionglue.huang <huangxionglue@zhcomputing.com>");
MODULE_DESCRIPTION("ZHIHE firmware protocol driver");

View File

@@ -11,7 +11,7 @@ config ZH_IOPMP
depends on ARCH_ZHIHE || COMPILE_TEST
help
Say Y here to include support for zhihe iopmp found on found on
P100 fullmask devices
A210 fullmask devices
To compile this driver as a module, choose M here: the module
will be called zh-iopmp.

View File

@@ -303,12 +303,12 @@ config TH1520_MBOX
Mailbox implementation for Xuantie TH1520 SoCs.
Say Y here if you want to have this support. If unsure say N.
config P100_MBOX
tristate "p100 Mailbox driver"
config A210_MBOX
tristate "A210 Mailbox driver"
depends on ARCH_ZHIHE || COMPILE_TEST
default y
help
Mailbox implementation for ZHIHE p100 SoCs.
Mailbox implementation for ZHIHE A210 SoCs.
Say Y here if you want to have this support. If unsure say N.
endif

View File

@@ -65,4 +65,4 @@ obj-$(CONFIG_APPLE_MAILBOX) += apple-mailbox.o
obj-$(CONFIG_TH1520_MBOX) += th1520-mailbox.o
obj-$(CONFIG_P100_MBOX) += p100-mailbox.o
obj-$(CONFIG_A210_MBOX) += a210-mailbox.o

View File

@@ -0,0 +1,576 @@
// SPDX-License-Identifier: GPL-2.0
/*
* a210 MailBox support
*
* Copyright (C) 2024 ZHIHE Group Holding Limited.
*
* Author: xionglue.huang <huangxionglue@zhcomputing.com>
*
*/
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mailbox_controller.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
/* Status Register */
#define A210_MBOX_STA 0x0
#define A210_MBOX_CLR 0x4
#define A210_MBOX_MASK 0xc
/* Transmit/receive data register:
* INFO0 ~ INFO6
*/
#define A210_MBOX_INFO_NUM 8
#define A210_MBOX_DATA_INFO_NUM 7
#define A210_MBOX_INFO0 0x14
/* Transmit ack register: INFO7 */
#define A210_MBOX_INFO7 0x30
/* Generate remote icu IRQ Register */
#define A210_MBOX_GEN 0x10
#define A210_MBOX_GEN_RX_DATA BIT(6)
#define A210_MBOX_GEN_TX_ACK BIT(7)
#define A210_MBOX_CHAN_RES_SIZE 0x1000
#define A210_MBOX_CHANS 4
#define A210_MBOX_CHAN_NAME_SIZE 20
#define A210_MBOX_ACK_MAGIC 0xdeadbeaf
#ifdef CONFIG_PM_SLEEP
/* store MBOX context across system-wide suspend/resume transitions */
struct a210_mbox_context {
u32 intr_mask[A210_MBOX_CHANS - 1];
};
#endif
enum a210_mbox_chan_type {
A210_MBOX_TYPE_TXRX, /* Tx & Rx chan */
A210_MBOX_TYPE_DB, /* Tx & Rx doorbell */
};
enum a210_mbox_icu_cpu_id {
A210_MBOX_ICU_CPU0 = 0, /*die0-908*/
A210_MBOX_ICU_CPU1 = 1,
A210_MBOX_ICU_CPU2 = 2,
A210_MBOX_ICU_CPU3 = 3,
};
enum a210_mbox_local_id {
A210_MBOX_INTERRUPT = 0,
A210_MBOX_DATA_CH0 = 1, /* die0-908--die0-902*/
A210_MBOX_DATA_CH1 = 2,
A210_MBOX_DATA_CH2 = 3,
};
enum a210_mbox_remote_id {
A210_MBOX_REMOTE_CH0 = 0, /* die0-908--die0-902*/
A210_MBOX_REMOTE_CH1 = 1,
A210_MBOX_REMOTE_CH2 = 2,
};
struct a210_mbox_con_priv {
enum a210_mbox_local_id idx;
enum a210_mbox_chan_type type;
void __iomem *comm_local_base;
void __iomem *comm_remote_base;
char irq_desc[A210_MBOX_CHAN_NAME_SIZE];
struct mbox_chan *chan;
struct tasklet_struct txdb_tasklet;
};
struct a210_mbox_priv {
struct device *dev;
void __iomem *local_icu[A210_MBOX_CHANS];
void __iomem *remote_icu[A210_MBOX_CHANS - 1];
void __iomem *cur_cpu_ch_base;
enum a210_mbox_icu_cpu_id cur_icu_cpu_id;
spinlock_t mbox_lock; /* control register lock */
struct mbox_controller mbox;
struct mbox_chan mbox_chans[A210_MBOX_CHANS];
struct a210_mbox_con_priv con_priv[A210_MBOX_CHANS];
struct clk *clk;
int irq;
#ifdef CONFIG_PM_SLEEP
struct a210_mbox_context *ctx;
#endif
};
static struct a210_mbox_priv *to_a210_mbox_priv(struct mbox_controller *mbox)
{
return container_of(mbox, struct a210_mbox_priv, mbox);
}
static void a210_mbox_write(struct a210_mbox_priv *priv, u32 val, u32 offs)
{
iowrite32(val, priv->cur_cpu_ch_base + offs);
}
static u32 a210_mbox_read(struct a210_mbox_priv *priv, u32 offs)
{
return ioread32(priv->cur_cpu_ch_base + offs);
}
static u32 a210_mbox_rmw(struct a210_mbox_priv *priv,
u32 off, u32 set, u32 clr)
{
u32 val;
unsigned long flags;
spin_lock_irqsave(&priv->mbox_lock, flags);
val = a210_mbox_read(priv, off);
val &= ~clr;
val |= set;
a210_mbox_write(priv, val, off);
spin_unlock_irqrestore(&priv->mbox_lock, flags);
return val;
}
static void a210_mbox_chan_write(struct a210_mbox_con_priv *cp,
u32 val, u32 offs, bool is_remote)
{
if (is_remote)
iowrite32(val, cp->comm_remote_base + offs);
else
iowrite32(val, cp->comm_local_base + offs);
}
static u32 a210_mbox_chan_read(struct a210_mbox_con_priv *cp,
u32 offs, bool is_remote)
{
uint32_t t = 0;
if (is_remote)
t = ioread32(cp->comm_remote_base + offs);
else
t = ioread32(cp->comm_local_base + offs);
return t;
}
static void a210_mbox_chan_rmw(struct a210_mbox_con_priv *cp,
u32 off, u32 set, u32 clr, bool is_remote)
{
u32 val;
unsigned long flags;
struct a210_mbox_priv *priv = to_a210_mbox_priv(cp->chan->mbox);
spin_lock_irqsave(&priv->mbox_lock, flags);
val = a210_mbox_chan_read(cp, off, is_remote);
val &= ~clr;
val |= set;
a210_mbox_chan_write(cp, val, off, is_remote);
spin_unlock_irqrestore(&priv->mbox_lock, flags);
}
static void a210_mbox_chan_rd_data(struct a210_mbox_con_priv *cp,
void *data, bool is_remote)
{
u32 i;
u32 *arg = data;
u32 off = A210_MBOX_INFO0;
/* read info0 ~ info6, totally 28 bytes
* requires data memory size is 28 bytes
*/
for (i = 0; i < A210_MBOX_DATA_INFO_NUM; i++) {
*arg = a210_mbox_chan_read(cp, off, is_remote);
off += 4;
arg++;
}
}
static void a210_mbox_chan_wr_data(struct a210_mbox_con_priv *cp,
void *data, bool is_remote)
{
u32 i;
u32 *arg = data;
u32 off = A210_MBOX_INFO0;
/* write info0 ~ info6, totally 28 bytes
* requires data memory is 28 bytes valid data
*/
for (i = 0; i < A210_MBOX_DATA_INFO_NUM; i++) {
a210_mbox_chan_write(cp, *arg, off, is_remote);
off += 4;
arg++;
}
}
static void a210_mbox_chan_wr_ack(struct a210_mbox_con_priv *cp,
void *data, bool is_remote)
{
u32 *arg = data;
u32 off = A210_MBOX_INFO7;
a210_mbox_chan_write(cp, *arg, off, is_remote);
}
static int a210_mbox_chan_id_to_mapbit(struct a210_mbox_con_priv *cp)
{
int i;
int mapbit = 0;
for (i = 0; i < A210_MBOX_CHANS; i++) {
if (i == cp->idx)
return mapbit;
if (i != A210_MBOX_INTERRUPT)
mapbit++;
}
if (i == A210_MBOX_CHANS)
dev_err(cp->chan->mbox->dev, "convert to mapbit failed\n");
return 0;
}
static void a210_mbox_txdb_tasklet(unsigned long data)
{
struct a210_mbox_con_priv *cp = (struct a210_mbox_con_priv *)data;
mbox_chan_txdone(cp->chan, 0);
}
static irqreturn_t a210_mbox_isr(int irq, void *p)
{
u32 info0_data, info7_data;
u32 sta, dat[A210_MBOX_DATA_INFO_NUM];
u32 ack_magic = A210_MBOX_ACK_MAGIC;
struct mbox_chan *chan = p;
struct a210_mbox_con_priv *cp = chan->con_priv;
int mapbit = a210_mbox_chan_id_to_mapbit(cp);
struct a210_mbox_priv *priv = to_a210_mbox_priv(chan->mbox);
sta = a210_mbox_read(priv, A210_MBOX_STA);
if (!(sta & BIT(mapbit)))
return IRQ_NONE;
/* clear chan irq bit in STA register */
a210_mbox_rmw(priv, A210_MBOX_CLR, BIT(mapbit), 0);
/* rx doorbell */
if (cp->type == A210_MBOX_TYPE_DB) {
mbox_chan_received_data(cp->chan, NULL);
return IRQ_HANDLED;
}
/* info0 is the protocol word, should not be zero! */
info0_data = a210_mbox_chan_read(cp, A210_MBOX_INFO0, false);
if (info0_data) {
/* read info0~info6 data */
a210_mbox_chan_rd_data(cp, dat, false);
/* clear local info0 */
a210_mbox_chan_write(cp, 0x0, A210_MBOX_INFO0, false);
/* notify remote cpu */
a210_mbox_chan_wr_ack(cp, &ack_magic, true);
/* transfer the data to client */
mbox_chan_received_data(chan, (void *)dat);
}
/* info7 magic value mean the real ack signal, not generate bit7 */
info7_data = a210_mbox_chan_read(cp, A210_MBOX_INFO7, false);
if (info7_data == A210_MBOX_ACK_MAGIC) {
/* clear local info7 */
a210_mbox_chan_write(cp, 0x0, A210_MBOX_INFO7, false);
/* notify framework the last TX has completed */
mbox_chan_txdone(chan, 0);
}
if (!info0_data && !info7_data)
return IRQ_NONE;
return IRQ_HANDLED;
}
static int a210_mbox_send_data(struct mbox_chan *chan, void *data)
{
struct a210_mbox_con_priv *cp = chan->con_priv;
if (cp->type == A210_MBOX_TYPE_DB)
tasklet_schedule(&cp->txdb_tasklet);
else
a210_mbox_chan_wr_data(cp, data, true);
a210_mbox_chan_rmw(cp, A210_MBOX_GEN, A210_MBOX_GEN_RX_DATA, 0,
true);
return 0;
}
static int a210_mbox_startup(struct mbox_chan *chan)
{
int ret;
int mask_bit;
u32 data[8] = {0};
struct a210_mbox_con_priv *cp = chan->con_priv;
struct a210_mbox_priv *priv = to_a210_mbox_priv(chan->mbox);
/* clear local and remote generate and info0~info7 */
a210_mbox_chan_rmw(cp, A210_MBOX_GEN, 0x0, 0xff, true);
a210_mbox_chan_rmw(cp, A210_MBOX_GEN, 0x0, 0xff, false);
a210_mbox_chan_wr_ack(cp, &data[7], true);
a210_mbox_chan_wr_ack(cp, &data[7], false);
a210_mbox_chan_wr_data(cp, &data[0], true);
a210_mbox_chan_wr_data(cp, &data[0], false);
/* enable the chan mask */
mask_bit = a210_mbox_chan_id_to_mapbit(cp);
a210_mbox_rmw(priv, A210_MBOX_MASK, BIT(mask_bit), 0);
if (cp->type == A210_MBOX_TYPE_DB)
/* tx doorbell doesn't have ACK, rx doorbell requires isr */
tasklet_init(&cp->txdb_tasklet, a210_mbox_txdb_tasklet,
(unsigned long)cp);
ret = request_irq(priv->irq, a210_mbox_isr, IRQF_SHARED |
IRQF_NO_SUSPEND, cp->irq_desc, chan);
if (ret) {
dev_err(priv->dev,
"Unable to acquire IRQ %d\n", priv->irq);
return ret;
}
return 0;
}
static void a210_mbox_shutdown(struct mbox_chan *chan)
{
int mask_bit;
struct a210_mbox_con_priv *cp = chan->con_priv;
struct a210_mbox_priv *priv = to_a210_mbox_priv(chan->mbox);
/* clear the chan mask */
mask_bit = a210_mbox_chan_id_to_mapbit(cp);
a210_mbox_rmw(priv, A210_MBOX_MASK, 0, BIT(mask_bit));
free_irq(priv->irq, chan);
}
static const struct mbox_chan_ops a210_mbox_ops = {
.send_data = a210_mbox_send_data,
.startup = a210_mbox_startup,
.shutdown = a210_mbox_shutdown,
};
static int a210_mbox_init_generic(struct a210_mbox_priv *priv)
{
#ifdef CONFIG_PM_SLEEP
priv->ctx = devm_kzalloc(priv->dev, sizeof(*priv->ctx), GFP_KERNEL);
if (!priv->ctx)
return -ENOMEM;
#endif
/* Set default configuration */
a210_mbox_write(priv, 0xff, A210_MBOX_CLR);
a210_mbox_write(priv, 0x0, A210_MBOX_MASK);
return 0;
}
static struct mbox_chan *a210_mbox_xlate(struct mbox_controller *mbox,
const struct of_phandle_args *sp)
{
u32 chan, type;
struct a210_mbox_con_priv *cp;
if (sp->args_count != 2) {
dev_err(mbox->dev,
"Invalid argument count %d\n", sp->args_count);
return ERR_PTR(-EINVAL);
}
chan = sp->args[0]; /* comm remote channel */
type = sp->args[1]; /* comm channel type */
if (chan >= mbox->num_chans) {
dev_err(mbox->dev, "Not supported channel number: %d\n", chan);
return ERR_PTR(-EINVAL);
}
if (type > A210_MBOX_TYPE_DB) {
dev_err(mbox->dev,
"Not supported the type for channel[%d]\n", chan);
return ERR_PTR(-EINVAL);
}
cp = mbox->chans[chan].con_priv;
cp->type = type;
return &mbox->chans[chan];
}
static int a210_mbox_probe(struct platform_device *pdev)
{
int ret;
unsigned int i;
struct resource *res;
struct a210_mbox_priv *priv;
unsigned int remote_idx = 0;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
if (of_property_read_u32(np, "icu_cpu_id", &priv->cur_icu_cpu_id)) {
dev_err(dev, "icu_cpu_id is missing\n");
return -EINVAL;
}
priv->dev = dev;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "interrupt_addr");
priv->local_icu[A210_MBOX_INTERRUPT] = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->local_icu[A210_MBOX_INTERRUPT]))
return PTR_ERR(priv->local_icu[A210_MBOX_INTERRUPT]);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "local_addr0");
priv->local_icu[A210_MBOX_DATA_CH0] = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->local_icu[A210_MBOX_DATA_CH0]))
return PTR_ERR(priv->local_icu[A210_MBOX_DATA_CH0]);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "remote_icu0");
priv->remote_icu[A210_MBOX_REMOTE_CH0] = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->remote_icu[A210_MBOX_REMOTE_CH0]))
return PTR_ERR(priv->remote_icu[A210_MBOX_REMOTE_CH0]);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "local_addr1");
if(res!=NULL) {
priv->local_icu[A210_MBOX_DATA_CH1] = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->local_icu[A210_MBOX_DATA_CH1]))
return PTR_ERR(priv->local_icu[A210_MBOX_DATA_CH1]);
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "remote_icu1");
if(res!=NULL) {
priv->remote_icu[A210_MBOX_REMOTE_CH1] = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->remote_icu[A210_MBOX_REMOTE_CH1]))
return PTR_ERR(priv->remote_icu[A210_MBOX_REMOTE_CH1]);
}
priv->cur_cpu_ch_base = priv->local_icu[A210_MBOX_INTERRUPT];
priv->irq = platform_get_irq(pdev, 0);
if (priv->irq < 0)
return priv->irq;
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
if (PTR_ERR(priv->clk) != -ENOENT)
return PTR_ERR(priv->clk);
priv->clk = NULL;
}
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(dev, "Failed to enable clock\n");
return ret;
}
/* init the chans */
for (i = 0; i < A210_MBOX_CHANS; i++) {
struct a210_mbox_con_priv *cp = &priv->con_priv[i];
cp->idx = i;
cp->chan = &priv->mbox_chans[i];
priv->mbox_chans[i].con_priv = cp;
snprintf(cp->irq_desc, sizeof(cp->irq_desc),
"a210_mbox_chan[%i]", cp->idx);
cp->comm_local_base = priv->local_icu[i];
if (i != A210_MBOX_INTERRUPT) {
cp->comm_remote_base = priv->remote_icu[remote_idx];
remote_idx++;
}
}
spin_lock_init(&priv->mbox_lock);
priv->mbox.dev = dev;
priv->mbox.ops = &a210_mbox_ops;
priv->mbox.chans = priv->mbox_chans;
priv->mbox.num_chans = A210_MBOX_CHANS;
priv->mbox.of_xlate = a210_mbox_xlate;
priv->mbox.txdone_irq = true;
platform_set_drvdata(pdev, priv);
ret = a210_mbox_init_generic(priv);
if (ret) {
dev_err(dev, "Failed to init mailbox context\n");
return ret;
}
return devm_mbox_controller_register(dev, &priv->mbox);
}
static int a210_mbox_remove(struct platform_device *pdev)
{
struct a210_mbox_priv *priv = platform_get_drvdata(pdev);
clk_disable_unprepare(priv->clk);
return 0;
}
static const struct of_device_id a210_mbox_dt_ids[] = {
{ .compatible = "zhihe,a210-mbox" },
{ },
};
MODULE_DEVICE_TABLE(of, a210_mbox_dt_ids);
#ifdef CONFIG_PM_SLEEP
static int __maybe_unused a210_mbox_suspend_noirq(struct device *dev)
{
u32 i;
struct a210_mbox_priv *priv = dev_get_drvdata(dev);
struct a210_mbox_context *ctx = priv->ctx;
/*
* ONLY interrupt mask bit should be stored and restores.
* INFO data all assumed to be lost.
*/
for (i = 0 ; i < A210_MBOX_CHANS; i++)
ctx->intr_mask[i] = ioread32(priv->local_icu[i] +
A210_MBOX_MASK);
return 0;
}
static int __maybe_unused a210_mbox_resume_noirq(struct device *dev)
{
u32 i;
struct a210_mbox_priv *priv = dev_get_drvdata(dev);
struct a210_mbox_context *ctx = priv->ctx;
for (i = 0 ; i < A210_MBOX_CHANS; i++)
iowrite32(ctx->intr_mask[i],
priv->local_icu[i] + A210_MBOX_MASK);
return 0;
}
#endif
static int __maybe_unused a210_mbox_runtime_suspend(struct device *dev)
{
struct a210_mbox_priv *priv = dev_get_drvdata(dev);
clk_disable_unprepare(priv->clk);
return 0;
}
static int __maybe_unused a210_mbox_runtime_resume(struct device *dev)
{
struct a210_mbox_priv *priv = dev_get_drvdata(dev);
int ret = clk_prepare_enable(priv->clk);
if (ret)
dev_err(dev, "failed to enable clock\n");
return ret;
}
static const struct dev_pm_ops a210_mbox_pm_ops = {
#ifdef CONFIG_PM_SLEEP
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(a210_mbox_suspend_noirq,
a210_mbox_resume_noirq)
#endif
SET_RUNTIME_PM_OPS(a210_mbox_runtime_suspend,
a210_mbox_runtime_resume, NULL)
};
static struct platform_driver a210_mbox_driver = {
.probe = a210_mbox_probe,
.remove = a210_mbox_remove,
.driver = {
.name = "a210_mbox",
.of_match_table = a210_mbox_dt_ids,
.pm = &a210_mbox_pm_ops,
},
};
module_platform_driver(a210_mbox_driver);
MODULE_AUTHOR("xionglue.huang <huangxionglue@zhcomputing.com>");
MODULE_DESCRIPTION("a210 Mailbox IPC driver");
MODULE_LICENSE("GPL v2");

View File

@@ -1,576 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* p100 MailBox support
*
* Copyright (C) 2024 ZHIHE Group Holding Limited.
*
* Author: xionglue.huang <huangxionglue@zhcomputing.com>
*
*/
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mailbox_controller.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
/* Status Register */
#define P100_MBOX_STA 0x0
#define P100_MBOX_CLR 0x4
#define P100_MBOX_MASK 0xc
/* Transmit/receive data register:
* INFO0 ~ INFO6
*/
#define P100_MBOX_INFO_NUM 8
#define P100_MBOX_DATA_INFO_NUM 7
#define P100_MBOX_INFO0 0x14
/* Transmit ack register: INFO7 */
#define P100_MBOX_INFO7 0x30
/* Generate remote icu IRQ Register */
#define P100_MBOX_GEN 0x10
#define P100_MBOX_GEN_RX_DATA BIT(6)
#define P100_MBOX_GEN_TX_ACK BIT(7)
#define P100_MBOX_CHAN_RES_SIZE 0x1000
#define P100_MBOX_CHANS 4
#define P100_MBOX_CHAN_NAME_SIZE 20
#define P100_MBOX_ACK_MAGIC 0xdeadbeaf
#ifdef CONFIG_PM_SLEEP
/* store MBOX context across system-wide suspend/resume transitions */
struct p100_mbox_context {
u32 intr_mask[P100_MBOX_CHANS - 1];
};
#endif
enum p100_mbox_chan_type {
P100_MBOX_TYPE_TXRX, /* Tx & Rx chan */
P100_MBOX_TYPE_DB, /* Tx & Rx doorbell */
};
enum p100_mbox_icu_cpu_id {
P100_MBOX_ICU_CPU0 = 0, /*die0-908*/
P100_MBOX_ICU_CPU1 = 1,
P100_MBOX_ICU_CPU2 = 2,
P100_MBOX_ICU_CPU3 = 3,
};
enum p100_mbox_local_id {
P100_MBOX_INTERRUPT = 0,
P100_MBOX_DATA_CH0 = 1, /* die0-908--die0-902*/
P100_MBOX_DATA_CH1 = 2,
P100_MBOX_DATA_CH2 = 3,
};
enum p100_mbox_remote_id {
P100_MBOX_REMOTE_CH0 = 0, /* die0-908--die0-902*/
P100_MBOX_REMOTE_CH1 = 1,
P100_MBOX_REMOTE_CH2 = 2,
};
struct p100_mbox_con_priv {
enum p100_mbox_local_id idx;
enum p100_mbox_chan_type type;
void __iomem *comm_local_base;
void __iomem *comm_remote_base;
char irq_desc[P100_MBOX_CHAN_NAME_SIZE];
struct mbox_chan *chan;
struct tasklet_struct txdb_tasklet;
};
struct p100_mbox_priv {
struct device *dev;
void __iomem *local_icu[P100_MBOX_CHANS];
void __iomem *remote_icu[P100_MBOX_CHANS - 1];
void __iomem *cur_cpu_ch_base;
enum p100_mbox_icu_cpu_id cur_icu_cpu_id;
spinlock_t mbox_lock; /* control register lock */
struct mbox_controller mbox;
struct mbox_chan mbox_chans[P100_MBOX_CHANS];
struct p100_mbox_con_priv con_priv[P100_MBOX_CHANS];
struct clk *clk;
int irq;
#ifdef CONFIG_PM_SLEEP
struct p100_mbox_context *ctx;
#endif
};
static struct p100_mbox_priv *to_p100_mbox_priv(struct mbox_controller *mbox)
{
return container_of(mbox, struct p100_mbox_priv, mbox);
}
static void p100_mbox_write(struct p100_mbox_priv *priv, u32 val, u32 offs)
{
iowrite32(val, priv->cur_cpu_ch_base + offs);
}
static u32 p100_mbox_read(struct p100_mbox_priv *priv, u32 offs)
{
return ioread32(priv->cur_cpu_ch_base + offs);
}
static u32 p100_mbox_rmw(struct p100_mbox_priv *priv,
u32 off, u32 set, u32 clr)
{
u32 val;
unsigned long flags;
spin_lock_irqsave(&priv->mbox_lock, flags);
val = p100_mbox_read(priv, off);
val &= ~clr;
val |= set;
p100_mbox_write(priv, val, off);
spin_unlock_irqrestore(&priv->mbox_lock, flags);
return val;
}
static void p100_mbox_chan_write(struct p100_mbox_con_priv *cp,
u32 val, u32 offs, bool is_remote)
{
if (is_remote)
iowrite32(val, cp->comm_remote_base + offs);
else
iowrite32(val, cp->comm_local_base + offs);
}
static u32 p100_mbox_chan_read(struct p100_mbox_con_priv *cp,
u32 offs, bool is_remote)
{
uint32_t t = 0;
if (is_remote)
t = ioread32(cp->comm_remote_base + offs);
else
t = ioread32(cp->comm_local_base + offs);
return t;
}
static void p100_mbox_chan_rmw(struct p100_mbox_con_priv *cp,
u32 off, u32 set, u32 clr, bool is_remote)
{
u32 val;
unsigned long flags;
struct p100_mbox_priv *priv = to_p100_mbox_priv(cp->chan->mbox);
spin_lock_irqsave(&priv->mbox_lock, flags);
val = p100_mbox_chan_read(cp, off, is_remote);
val &= ~clr;
val |= set;
p100_mbox_chan_write(cp, val, off, is_remote);
spin_unlock_irqrestore(&priv->mbox_lock, flags);
}
static void p100_mbox_chan_rd_data(struct p100_mbox_con_priv *cp,
void *data, bool is_remote)
{
u32 i;
u32 *arg = data;
u32 off = P100_MBOX_INFO0;
/* read info0 ~ info6, totally 28 bytes
* requires data memory size is 28 bytes
*/
for (i = 0; i < P100_MBOX_DATA_INFO_NUM; i++) {
*arg = p100_mbox_chan_read(cp, off, is_remote);
off += 4;
arg++;
}
}
static void p100_mbox_chan_wr_data(struct p100_mbox_con_priv *cp,
void *data, bool is_remote)
{
u32 i;
u32 *arg = data;
u32 off = P100_MBOX_INFO0;
/* write info0 ~ info6, totally 28 bytes
* requires data memory is 28 bytes valid data
*/
for (i = 0; i < P100_MBOX_DATA_INFO_NUM; i++) {
p100_mbox_chan_write(cp, *arg, off, is_remote);
off += 4;
arg++;
}
}
static void p100_mbox_chan_wr_ack(struct p100_mbox_con_priv *cp,
void *data, bool is_remote)
{
u32 *arg = data;
u32 off = P100_MBOX_INFO7;
p100_mbox_chan_write(cp, *arg, off, is_remote);
}
static int p100_mbox_chan_id_to_mapbit(struct p100_mbox_con_priv *cp)
{
int i;
int mapbit = 0;
for (i = 0; i < P100_MBOX_CHANS; i++) {
if (i == cp->idx)
return mapbit;
if (i != P100_MBOX_INTERRUPT)
mapbit++;
}
if (i == P100_MBOX_CHANS)
dev_err(cp->chan->mbox->dev, "convert to mapbit failed\n");
return 0;
}
static void p100_mbox_txdb_tasklet(unsigned long data)
{
struct p100_mbox_con_priv *cp = (struct p100_mbox_con_priv *)data;
mbox_chan_txdone(cp->chan, 0);
}
static irqreturn_t p100_mbox_isr(int irq, void *p)
{
u32 info0_data, info7_data;
u32 sta, dat[P100_MBOX_DATA_INFO_NUM];
u32 ack_magic = P100_MBOX_ACK_MAGIC;
struct mbox_chan *chan = p;
struct p100_mbox_con_priv *cp = chan->con_priv;
int mapbit = p100_mbox_chan_id_to_mapbit(cp);
struct p100_mbox_priv *priv = to_p100_mbox_priv(chan->mbox);
sta = p100_mbox_read(priv, P100_MBOX_STA);
if (!(sta & BIT(mapbit)))
return IRQ_NONE;
/* clear chan irq bit in STA register */
p100_mbox_rmw(priv, P100_MBOX_CLR, BIT(mapbit), 0);
/* rx doorbell */
if (cp->type == P100_MBOX_TYPE_DB) {
mbox_chan_received_data(cp->chan, NULL);
return IRQ_HANDLED;
}
/* info0 is the protocol word, should not be zero! */
info0_data = p100_mbox_chan_read(cp, P100_MBOX_INFO0, false);
if (info0_data) {
/* read info0~info6 data */
p100_mbox_chan_rd_data(cp, dat, false);
/* clear local info0 */
p100_mbox_chan_write(cp, 0x0, P100_MBOX_INFO0, false);
/* notify remote cpu */
p100_mbox_chan_wr_ack(cp, &ack_magic, true);
/* transfer the data to client */
mbox_chan_received_data(chan, (void *)dat);
}
/* info7 magic value mean the real ack signal, not generate bit7 */
info7_data = p100_mbox_chan_read(cp, P100_MBOX_INFO7, false);
if (info7_data == P100_MBOX_ACK_MAGIC) {
/* clear local info7 */
p100_mbox_chan_write(cp, 0x0, P100_MBOX_INFO7, false);
/* notify framework the last TX has completed */
mbox_chan_txdone(chan, 0);
}
if (!info0_data && !info7_data)
return IRQ_NONE;
return IRQ_HANDLED;
}
static int p100_mbox_send_data(struct mbox_chan *chan, void *data)
{
struct p100_mbox_con_priv *cp = chan->con_priv;
if (cp->type == P100_MBOX_TYPE_DB)
tasklet_schedule(&cp->txdb_tasklet);
else
p100_mbox_chan_wr_data(cp, data, true);
p100_mbox_chan_rmw(cp, P100_MBOX_GEN, P100_MBOX_GEN_RX_DATA, 0,
true);
return 0;
}
static int p100_mbox_startup(struct mbox_chan *chan)
{
int ret;
int mask_bit;
u32 data[8] = {0};
struct p100_mbox_con_priv *cp = chan->con_priv;
struct p100_mbox_priv *priv = to_p100_mbox_priv(chan->mbox);
/* clear local and remote generate and info0~info7 */
p100_mbox_chan_rmw(cp, P100_MBOX_GEN, 0x0, 0xff, true);
p100_mbox_chan_rmw(cp, P100_MBOX_GEN, 0x0, 0xff, false);
p100_mbox_chan_wr_ack(cp, &data[7], true);
p100_mbox_chan_wr_ack(cp, &data[7], false);
p100_mbox_chan_wr_data(cp, &data[0], true);
p100_mbox_chan_wr_data(cp, &data[0], false);
/* enable the chan mask */
mask_bit = p100_mbox_chan_id_to_mapbit(cp);
p100_mbox_rmw(priv, P100_MBOX_MASK, BIT(mask_bit), 0);
if (cp->type == P100_MBOX_TYPE_DB)
/* tx doorbell doesn't have ACK, rx doorbell requires isr */
tasklet_init(&cp->txdb_tasklet, p100_mbox_txdb_tasklet,
(unsigned long)cp);
ret = request_irq(priv->irq, p100_mbox_isr, IRQF_SHARED |
IRQF_NO_SUSPEND, cp->irq_desc, chan);
if (ret) {
dev_err(priv->dev,
"Unable to acquire IRQ %d\n", priv->irq);
return ret;
}
return 0;
}
static void p100_mbox_shutdown(struct mbox_chan *chan)
{
int mask_bit;
struct p100_mbox_con_priv *cp = chan->con_priv;
struct p100_mbox_priv *priv = to_p100_mbox_priv(chan->mbox);
/* clear the chan mask */
mask_bit = p100_mbox_chan_id_to_mapbit(cp);
p100_mbox_rmw(priv, P100_MBOX_MASK, 0, BIT(mask_bit));
free_irq(priv->irq, chan);
}
static const struct mbox_chan_ops p100_mbox_ops = {
.send_data = p100_mbox_send_data,
.startup = p100_mbox_startup,
.shutdown = p100_mbox_shutdown,
};
static int p100_mbox_init_generic(struct p100_mbox_priv *priv)
{
#ifdef CONFIG_PM_SLEEP
priv->ctx = devm_kzalloc(priv->dev, sizeof(*priv->ctx), GFP_KERNEL);
if (!priv->ctx)
return -ENOMEM;
#endif
/* Set default configuration */
p100_mbox_write(priv, 0xff, P100_MBOX_CLR);
p100_mbox_write(priv, 0x0, P100_MBOX_MASK);
return 0;
}
static struct mbox_chan *p100_mbox_xlate(struct mbox_controller *mbox,
const struct of_phandle_args *sp)
{
u32 chan, type;
struct p100_mbox_con_priv *cp;
if (sp->args_count != 2) {
dev_err(mbox->dev,
"Invalid argument count %d\n", sp->args_count);
return ERR_PTR(-EINVAL);
}
chan = sp->args[0]; /* comm remote channel */
type = sp->args[1]; /* comm channel type */
if (chan >= mbox->num_chans) {
dev_err(mbox->dev, "Not supported channel number: %d\n", chan);
return ERR_PTR(-EINVAL);
}
if (type > P100_MBOX_TYPE_DB) {
dev_err(mbox->dev,
"Not supported the type for channel[%d]\n", chan);
return ERR_PTR(-EINVAL);
}
cp = mbox->chans[chan].con_priv;
cp->type = type;
return &mbox->chans[chan];
}
static int p100_mbox_probe(struct platform_device *pdev)
{
int ret;
unsigned int i;
struct resource *res;
struct p100_mbox_priv *priv;
unsigned int remote_idx = 0;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
if (of_property_read_u32(np, "icu_cpu_id", &priv->cur_icu_cpu_id)) {
dev_err(dev, "icu_cpu_id is missing\n");
return -EINVAL;
}
priv->dev = dev;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "interrupt_addr");
priv->local_icu[P100_MBOX_INTERRUPT] = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->local_icu[P100_MBOX_INTERRUPT]))
return PTR_ERR(priv->local_icu[P100_MBOX_INTERRUPT]);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "local_addr0");
priv->local_icu[P100_MBOX_DATA_CH0] = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->local_icu[P100_MBOX_DATA_CH0]))
return PTR_ERR(priv->local_icu[P100_MBOX_DATA_CH0]);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "remote_icu0");
priv->remote_icu[P100_MBOX_REMOTE_CH0] = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->remote_icu[P100_MBOX_REMOTE_CH0]))
return PTR_ERR(priv->remote_icu[P100_MBOX_REMOTE_CH0]);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "local_addr1");
if(res!=NULL) {
priv->local_icu[P100_MBOX_DATA_CH1] = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->local_icu[P100_MBOX_DATA_CH1]))
return PTR_ERR(priv->local_icu[P100_MBOX_DATA_CH1]);
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "remote_icu1");
if(res!=NULL) {
priv->remote_icu[P100_MBOX_REMOTE_CH1] = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->remote_icu[P100_MBOX_REMOTE_CH1]))
return PTR_ERR(priv->remote_icu[P100_MBOX_REMOTE_CH1]);
}
priv->cur_cpu_ch_base = priv->local_icu[P100_MBOX_INTERRUPT];
priv->irq = platform_get_irq(pdev, 0);
if (priv->irq < 0)
return priv->irq;
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
if (PTR_ERR(priv->clk) != -ENOENT)
return PTR_ERR(priv->clk);
priv->clk = NULL;
}
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(dev, "Failed to enable clock\n");
return ret;
}
/* init the chans */
for (i = 0; i < P100_MBOX_CHANS; i++) {
struct p100_mbox_con_priv *cp = &priv->con_priv[i];
cp->idx = i;
cp->chan = &priv->mbox_chans[i];
priv->mbox_chans[i].con_priv = cp;
snprintf(cp->irq_desc, sizeof(cp->irq_desc),
"p100_mbox_chan[%i]", cp->idx);
cp->comm_local_base = priv->local_icu[i];
if (i != P100_MBOX_INTERRUPT) {
cp->comm_remote_base = priv->remote_icu[remote_idx];
remote_idx++;
}
}
spin_lock_init(&priv->mbox_lock);
priv->mbox.dev = dev;
priv->mbox.ops = &p100_mbox_ops;
priv->mbox.chans = priv->mbox_chans;
priv->mbox.num_chans = P100_MBOX_CHANS;
priv->mbox.of_xlate = p100_mbox_xlate;
priv->mbox.txdone_irq = true;
platform_set_drvdata(pdev, priv);
ret = p100_mbox_init_generic(priv);
if (ret) {
dev_err(dev, "Failed to init mailbox context\n");
return ret;
}
return devm_mbox_controller_register(dev, &priv->mbox);
}
static int p100_mbox_remove(struct platform_device *pdev)
{
struct p100_mbox_priv *priv = platform_get_drvdata(pdev);
clk_disable_unprepare(priv->clk);
return 0;
}
static const struct of_device_id p100_mbox_dt_ids[] = {
{ .compatible = "zhihe,p100-mbox" },
{ },
};
MODULE_DEVICE_TABLE(of, p100_mbox_dt_ids);
#ifdef CONFIG_PM_SLEEP
static int __maybe_unused p100_mbox_suspend_noirq(struct device *dev)
{
u32 i;
struct p100_mbox_priv *priv = dev_get_drvdata(dev);
struct p100_mbox_context *ctx = priv->ctx;
/*
* ONLY interrupt mask bit should be stored and restores.
* INFO data all assumed to be lost.
*/
for (i = 0 ; i < P100_MBOX_CHANS; i++)
ctx->intr_mask[i] = ioread32(priv->local_icu[i] +
P100_MBOX_MASK);
return 0;
}
static int __maybe_unused p100_mbox_resume_noirq(struct device *dev)
{
u32 i;
struct p100_mbox_priv *priv = dev_get_drvdata(dev);
struct p100_mbox_context *ctx = priv->ctx;
for (i = 0 ; i < P100_MBOX_CHANS; i++)
iowrite32(ctx->intr_mask[i],
priv->local_icu[i] + P100_MBOX_MASK);
return 0;
}
#endif
static int __maybe_unused p100_mbox_runtime_suspend(struct device *dev)
{
struct p100_mbox_priv *priv = dev_get_drvdata(dev);
clk_disable_unprepare(priv->clk);
return 0;
}
static int __maybe_unused p100_mbox_runtime_resume(struct device *dev)
{
struct p100_mbox_priv *priv = dev_get_drvdata(dev);
int ret = clk_prepare_enable(priv->clk);
if (ret)
dev_err(dev, "failed to enable clock\n");
return ret;
}
static const struct dev_pm_ops p100_mbox_pm_ops = {
#ifdef CONFIG_PM_SLEEP
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(p100_mbox_suspend_noirq,
p100_mbox_resume_noirq)
#endif
SET_RUNTIME_PM_OPS(p100_mbox_runtime_suspend,
p100_mbox_runtime_resume, NULL)
};
static struct platform_driver p100_mbox_driver = {
.probe = p100_mbox_probe,
.remove = p100_mbox_remove,
.driver = {
.name = "p100_mbox",
.of_match_table = p100_mbox_dt_ids,
.pm = &p100_mbox_pm_ops,
},
};
module_platform_driver(p100_mbox_driver);
MODULE_AUTHOR("xionglue.huang <huangxionglue@zhcomputing.com>");
MODULE_DESCRIPTION("p100 Mailbox IPC driver");
MODULE_LICENSE("GPL v2");

View File

@@ -3114,6 +3114,10 @@ static bool sdhci_request_done(struct sdhci_host *host)
sdhci_reset_for(host, REQUEST_ERROR);
host->pending_reset = false;
/* Clear any pending interrupts after reset */
sdhci_writel(host, SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK,
SDHCI_INT_STATUS);
}
/*

View File

@@ -378,7 +378,7 @@ static const struct flexcan_devtype_data fsl_lx2160a_r1_devtype_data = {
FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR,
};
static const struct flexcan_devtype_data fsl_a210_devtype_data = {
static const struct flexcan_devtype_data fsl_zhihe_a210_devtype_data = {
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_USE_RX_MAILBOX | FLEXCAN_QUIRK_SUPPORT_FD |
@@ -2027,7 +2027,7 @@ static const struct of_device_id flexcan_of_match[] = {
{ .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, },
{ .compatible = "fsl,ls1021ar2-flexcan", .data = &fsl_ls1021a_r2_devtype_data, },
{ .compatible = "fsl,lx2160ar1-flexcan", .data = &fsl_lx2160a_r1_devtype_data, },
{ .compatible = "fsl,a210-flexcan", .data = &fsl_a210_devtype_data, },
{ .compatible = "fsl,zha210-flexcan", .data = &fsl_zhihe_a210_devtype_data, },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, flexcan_of_match);

View File

@@ -433,7 +433,7 @@ config NVMEM_ZH_EFUSE
depends on HAS_IOMEM
help
Say Y here to include support for Thead efuse found on found on
P100 fullmask devices
A210 fullmask devices
To compile this driver as a module, choose M here: the module
will be called nvmem-zh-efuse.

View File

@@ -478,14 +478,14 @@ config PINCTRL_TH1520
help
This selects the pinctrl driver for XuanTie TH1520 RISC-V SoC.
config PINCTRL_P100
tristate "Pinctrl driver for the ZhiHe P100 SoC"
config PINCTRL_A210
tristate "Pinctrl driver for the ZhiHe A210 SoC"
depends on ARCH_ZHIHE || COMPILE_TEST
select GENERIC_PINMUX_FUNCTIONS
select GENERIC_PINCONF
select PINMUX
help
This selects the pinctrl driver for ZhiHe P100 RISC-V SoC.
This selects the pinctrl driver for ZhiHe A210 RISC-V SoC.
config PINCTRL_ZYNQ
bool "Pinctrl driver for Xilinx Zynq"

View File

@@ -49,7 +49,7 @@ obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o
obj-$(CONFIG_PINCTRL_TH1520) += pinctrl-th1520.o
obj-$(CONFIG_PINCTRL_P100) += pinctrl-p100.o
obj-$(CONFIG_PINCTRL_A210) += pinctrl-a210.o
obj-$(CONFIG_PINCTRL_ZYNQMP) += pinctrl-zynqmp.o
obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o

View File

@@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_P100_POWER_DOMAIN) += p100-pd.o
obj-$(CONFIG_A210_POWER_DOMAIN) += a210-pd.o

View File

@@ -25,7 +25,7 @@
#include <dt-bindings/iopmp/zh-iopmp.h>
#include <asm/zh-iopmp.h>
#include "p100-pd.h"
#include "a210-pd.h"
static const struct p100_pd_range p100_pd_ranges[] = {
{"power_gpu", P100_PD_GPU},

View File

@@ -3,8 +3,8 @@
* Copyright (C) 2025 Zhihe Computing Limited.
*/
#ifndef __P100_PD_H
#define __P100_PD_H
#ifndef __A210_PD_H
#define __A210_PD_H
#define P100_PD_NAME_SIZE 20
#define P100_PD_STATE_NAME_SIZE 10

View File

@@ -328,12 +328,12 @@ config RESET_ZYNQ
help
This enables the reset controller driver for Xilinx Zynq SoCs.
config RESET_P100
bool "P100 Reset Driver"
config RESET_A210
bool "A210 Reset Driver"
depends on ARCH_ZHIHE
default y
help
Build the driver for zhihe p100 Reset Driver
Build the driver for ZhiHe A210 Reset Driver
source "drivers/reset/starfive/Kconfig"
source "drivers/reset/sti/Kconfig"

View File

@@ -42,4 +42,4 @@ obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
obj-$(CONFIG_RESET_P100) += reset-p100.o
obj-$(CONFIG_RESET_A210) += reset-a210.o

View File

@@ -7,7 +7,7 @@
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/io.h>
#include <dt-bindings/reset/p100-reset.h>
#include <dt-bindings/reset/a210-reset.h>
#define P100_RST_NAME_SIZE 20

View File

@@ -2,24 +2,24 @@
menu "ZHIHE SoC drivers"
config P100_MEMTESTER
tristate "ZHIHE P100 memtester support"
config A210_MEMTESTER
tristate "ZHIHE A210 memtester support"
default y
help
This driver supports P100 memtester feature.
This driver supports A210 memtester feature.
config P100_POWER_DOMAIN
bool "P100 Power Domain driver"
config A210_POWER_DOMAIN
bool "A210 Power Domain driver"
depends on PM
select PM_GENERIC_DOMAINS
default y
help
This is the power domain driver that controls PCU/PPU for P100 Soc.
This is the power domain driver that controls PCU/PPU for A210 Soc.
config P100_BMU
tristate "p100-bmu driver"
config A210_BMU
tristate "A210 bmu driver"
default n
help
This driver provides support for p100 bmu.
This driver provides support for A210 bmu.
endmenu

View File

@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_P100_MEMTESTER) += p100-memtester.o
obj-$(CONFIG_P100_BMU) += p100-bmu.o
obj-$(CONFIG_A210_MEMTESTER) += a210-memtester.o
obj-$(CONFIG_A210_BMU) += a210-bmu.o

View File

@@ -1,5 +1,5 @@
#ifndef _P100_BMU_TYPE_H
#define _P100_BMU_TYPE_H
#ifndef _A210_BMU_TYPE_H
#define _A210_BMU_TYPE_H
#include <linux/kernel.h>
//#include <linux/spinlock.h>

View File

@@ -5,7 +5,7 @@
#define TRACE_SYSTEM bmu
#include <linux/tracepoint.h>
#include "p100_bmu_type.h"
#include "a210_bmu_type.h"
TRACE_EVENT (bmu_cnt_bytes_cycle_trans,
TP_PROTO (char *name, u8 ch, pft_event_array_t * pft_event),

View File

@@ -87,7 +87,8 @@ static int dw_qspi_mmio_probe(struct platform_device *pdev)
struct dw_qspi_mmio *dwsmmio;
struct dw_spi *dws;
int ret;
int num_cs,rx_sample_dly;
u32 num_cs, rx_sample_dly = 4;
u32 swap_data = 0;
dwsmmio = devm_kzalloc(&pdev->dev, sizeof(struct dw_qspi_mmio),
GFP_KERNEL);
@@ -150,10 +151,14 @@ static int dw_qspi_mmio_probe(struct platform_device *pdev)
num_cs = 1;
device_property_read_u32(&pdev->dev, "num-cs", &num_cs);
dws->num_cs = num_cs;
rx_sample_dly = 4;
device_property_read_u32(&pdev->dev, "rx-sample-dly", &rx_sample_dly);
printk("get gpio succes %d\n",rx_sample_dly);
dev_dbg(&pdev->dev, "get rx_sample_dly success %d\n", rx_sample_dly);
dws->rx_sample_delay = rx_sample_dly;
device_property_read_u32(&pdev->dev, "spi-swap-data", &swap_data);
dws->swap_data = swap_data;
init_func = device_get_match_data(&pdev->dev);
if (init_func) {
ret = init_func(pdev, dwsmmio);

View File

@@ -272,10 +272,17 @@ static void dw_writer(struct dw_spi *dws)
if (dws->tx_end - dws->len) {
if (dws->n_bytes == 1)
txw = *(u8 *)(dws->tx);
else if(dws->n_bytes == 2)
txw = *(u16 *)(dws->tx);
else
txw = *(u32 *)(dws->tx);
else if(dws->n_bytes == 2) {
if (dws->swap_data)
txw = swab16(*(u16 *)(dws->tx));
else
txw = *(u16 *)(dws->tx);
} else {
if (dws->swap_data)
txw = swab32(*(u32 *)(dws->tx));
else
txw = *(u32 *)(dws->tx);
}
}
dw_write_io_reg(dws, DW_SPI_DR, txw);
dws->tx += dws->n_bytes;
@@ -296,10 +303,17 @@ static void dw_reader(struct dw_spi *dws)
if (dws->rx_end - dws->len) {
if (dws->n_bytes == 1)
*(u8 *)(dws->rx) = rxw;
else if(dws->n_bytes ==2)
*(u16 *)(dws->rx) = rxw;
else
*(u32 *)(dws->rx) = rxw;
else if(dws->n_bytes == 2) {
if (dws->swap_data)
*(u16 *)(dws->rx) = swab16(rxw);
else
*(u16 *)(dws->rx) = rxw;
} else {
if (dws->swap_data)
*(u32 *)(dws->rx) = swab32(rxw);
else
*(u32 *)(dws->rx) = rxw;
}
}
dws->rx += dws->n_bytes;
}

View File

@@ -199,9 +199,10 @@ struct dw_spi {
int cs_override;
u32 reg_io_width; /* DR I/O width in bytes */
u16 bus_num;
u16 num_cs; /* supported slave numbers */
u16 rx_sample_delay;/* timing value for rx sample delay */
u32 bus_num;
u32 num_cs; /* supported slave numbers */
u32 rx_sample_delay;/* timing value for rx sample delay */
u32 swap_data;
struct gpio_desc *slave_cs; /* gpio cs handle */
void (*set_cs)(struct spi_device *spi, bool enable);
/* used by spi_controller_mem_ops interface */

View File

@@ -2057,7 +2057,21 @@ config TH1520_PMIC_WATCHDOG
module will be called acquirewdt.
Most people will say N.
config A210_WATCHDOG
tristate "A210 watchdog"
depends on A210_MBOX
select WATCHDOG_CORE
help
This is the driver for the hardware watchdog on A210 Board. This watchdog
simply watches your kernel to make sure it doesn't freeze, and if
it does, it reboots your computer after a certain amount of time.
To compile this driver as a module, choose M here: the
module will be called acquirewdt.
Most people will say N.
# S390 Architecture
config DIAG288_WATCHDOG

View File

@@ -197,6 +197,7 @@ obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
# RISC-V Architecture
obj-$(CONFIG_STARFIVE_WATCHDOG) += starfive-wdt.o
obj-$(CONFIG_TH1520_PMIC_WATCHDOG) += th1520_wdt.o
obj-$(CONFIG_A210_WATCHDOG) += a210_wdt.o
# S390 Architecture
obj-$(CONFIG_DIAG288_WATCHDOG) += diag288_wdt.o

437
drivers/watchdog/a210_wdt.c Executable file
View File

@@ -0,0 +1,437 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021-2024 Alibaba Group Holding Limited.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/device.h>
#include <linux/watchdog.h>
#include <linux/firmware/zhihe/ipc.h>
#include <linux/delay.h>
#define DRV_NAME "a210-wdt"
/*
* Watchdog selector to timeout in seconds.
* 0: WDT disabled;
* others: timeout = 2048 ms * 2^(TWDSCALE-1).
*/
static const unsigned int wdt_timeout[] = {8, 16, 32,128};
#define A210_TWDSCALE_DISABLE 0
#define A210_TWDSCALE_MIN 1
#define A210_TWDSCALE_MAX (ARRAY_SIZE(wdt_timeout) - 1)
#define A210_WDT_MIN_TIMEOUT wdt_timeout[A210_TWDSCALE_MIN]
#define A210_WDT_MAX_TIMEOUT wdt_timeout[A210_TWDSCALE_MAX]
#define A210_WDT_TIMEOUT wdt_timeout[3]
#define A210_RESET_PROTECTION_MS 256
struct a210_aon_msg_wdg_ctrl {
struct a210_aon_rpc_msg_hdr hdr;
u32 timeout;
u32 running_state;
u32 reserved[1];
} __packed __aligned(1);
struct a210_aon_msg_wdg_ctrl_ack {
struct a210_aon_rpc_ack_common ack_hdr;
u32 timeout;
u32 running_state;
u32 reserved[1];
} __packed __aligned(1);
struct a210_wdt_device {
struct device *dev;
struct a210_aon_ipc *ipc_handle;
struct a210_aon_msg_wdg_ctrl msg;
unsigned int is_aon_wdt_ena;
};
struct a210_wdt_device *a210_power_off_wdt;
static unsigned int a210_wdt_timeout_to_sel(unsigned secs)
{
unsigned int i;
for (i = A210_TWDSCALE_MIN; i <= A210_TWDSCALE_MAX; i++) {
if (wdt_timeout[i] >= secs)
return i;
}
return A210_TWDSCALE_MAX;
}
static void a210_wdt_msg_hdr_fill(struct a210_aon_rpc_msg_hdr *hdr, enum a210_aon_wdg_func func)
{
hdr->svc = (uint8_t)A210_AON_RPC_SVC_WDG;
hdr->func = (uint8_t)func;
hdr->size = A210_AON_RPC_MSG_NUM;
}
static int a210_wdt_is_running(struct a210_wdt_device *wdt_dev)
{
struct a210_aon_ipc *ipc = wdt_dev->ipc_handle;
struct a210_aon_msg_wdg_ctrl_ack ack_msg= {0};
int ret;
a210_wdt_msg_hdr_fill(&wdt_dev->msg.hdr, A210_AON_WDG_FUNC_GET_STATE);
wdt_dev->msg.running_state = -1;
ret = a210_aon_call_rpc(ipc, &wdt_dev->msg, &ack_msg, true);
printk("a210_wdt_is_running ret %d",ret);
if (ret)
return ret;
//RPC_GET_BE32(&ack_msg.timeout, 0, &wdt_dev->msg.timeout);
RPC_GET_BE32(&ack_msg.timeout, 4, &wdt_dev->msg.running_state);
pr_debug("ret = %d, timeout = %d, running_state = %d\n", ret, wdt_dev->msg.timeout,
wdt_dev->msg.running_state);
printk("ret = %d, timeout = %d, running_state = %d\n", ret, wdt_dev->msg.timeout,
wdt_dev->msg.running_state);
return wdt_dev->msg.running_state;
}
static int a210_wdt_update_timeout(struct a210_wdt_device *wdt_dev, unsigned int timeout)
{
/*
* The watchdog triggers a reboot if a timeout value is already
* programmed because the timeout value combines two functions
* in one: indicating the counter limit and starting the watchdog.
* The watchdog must be disabled to be able to change the timeout
* value if the watchdog is already running. Then we can set the
* new timeout value which enables the watchdog again.
*/
struct a210_aon_ipc *ipc = wdt_dev->ipc_handle;
struct a210_aon_msg_wdg_ctrl_ack ack_msg= {0};
int ret;
a210_wdt_msg_hdr_fill(&wdt_dev->msg.hdr, A210_AON_WDG_FUNC_TIMEOUTSET);
RPC_SET_BE32(&wdt_dev->msg.timeout, 0 , timeout);
ret = a210_aon_call_rpc(ipc, &wdt_dev->msg, &ack_msg, true);
if (ret)
return ret;
return 0;
}
static int a210_wdt_set_timeout(struct watchdog_device *wdd, unsigned int timeout)
{
struct a210_wdt_device *wdt_dev = watchdog_get_drvdata(wdd);
int ret = 0;
/*
* There are two cases when a set_timeout() will be called:
* 1. The watchdog is off and someone wants to set the timeout for the
* further use.
* 2. The watchdog is already running and a new timeout value should be
* set.
*
* The watchdog can't store a timeout value not equal zero without
* enabling the watchdog, so the timeout must be buffered by the driver.
*/
if (watchdog_active(wdd))
ret = a210_wdt_update_timeout(wdt_dev, timeout);
else
wdd->timeout = wdt_timeout[a210_wdt_timeout_to_sel(timeout)];
return ret;
}
static int a210_wdt_start(struct watchdog_device *wdd)
{
struct a210_wdt_device *wdt_dev = watchdog_get_drvdata(wdd);
struct a210_aon_ipc *ipc = wdt_dev->ipc_handle;
struct a210_aon_rpc_ack_common ack_msg = {0};
int ret;
a210_wdt_msg_hdr_fill(&wdt_dev->msg.hdr, A210_AON_WDG_FUNC_START);
ret = a210_aon_call_rpc(ipc, &wdt_dev->msg, &ack_msg, true);
if (ret)
return ret;
return 0;
}
static int a210_wdt_stop(struct watchdog_device *wdd)
{
struct a210_wdt_device *wdt_dev = watchdog_get_drvdata(wdd);
struct a210_aon_ipc *ipc = wdt_dev->ipc_handle;
struct a210_aon_rpc_ack_common ack_msg = {0};
int ret;
a210_wdt_msg_hdr_fill(&wdt_dev->msg.hdr, A210_AON_WDG_FUNC_STOP);
ret = a210_aon_call_rpc(ipc, &wdt_dev->msg, &ack_msg, true);
if (ret)
return ret;
return 0;
}
static int a210_wdt_ping(struct watchdog_device *wdd)
{
struct a210_wdt_device *wdt_dev = watchdog_get_drvdata(wdd);
struct a210_aon_ipc *ipc = wdt_dev->ipc_handle;
struct a210_aon_rpc_ack_common ack_msg = {0};
int ret;
a210_wdt_msg_hdr_fill(&wdt_dev->msg.hdr, A210_AON_WDG_FUNC_PING);
ret = a210_aon_call_rpc(ipc, &wdt_dev->msg, &ack_msg, true);
if (ret)
return ret;
return 0;
}
static int a210_wdt_restart(struct watchdog_device *wdd, unsigned long action, void *data)
{
struct a210_wdt_device *wdt_dev = watchdog_get_drvdata(wdd);
struct a210_aon_ipc *ipc = wdt_dev->ipc_handle;
int ret;
a210_wdt_msg_hdr_fill(&wdt_dev->msg.hdr, A210_AON_WDG_FUNC_RESTART);
pr_debug("[%s,%d]: Inform aon to restart the whole system....\n", __func__, __LINE__);
printk("a210_wdt_restart msg 0x%x\n",wdt_dev->msg.hdr);
ret = a210_aon_call_rpc(ipc, &wdt_dev->msg, NULL, false);
if (ret)
return ret;
pr_debug("[%s,%d]: Finish to inform aon to restart the whole system....\n", __func__, __LINE__);
printk("Finish to inform aon to restart the whole system....\n");
return 0;
}
static const struct watchdog_info a210_watchdog_info = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
.identity = "p100 Watchdog",
};
static const struct watchdog_ops a210_watchdog_ops = {
.owner = THIS_MODULE,
.start = a210_wdt_start,
.stop = a210_wdt_stop,
.ping = a210_wdt_ping,
.set_timeout = a210_wdt_set_timeout,
.restart = a210_wdt_restart,
};
static ssize_t aon_sys_wdt_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
struct a210_wdt_device *wdt_dev = platform_get_drvdata(pdev);
return sprintf(buf,"%u\n",wdt_dev->is_aon_wdt_ena);
}
static ssize_t aon_sys_wdt_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
struct platform_device *pdev = to_platform_device(dev);
struct a210_wdt_device *wdt_dev = platform_get_drvdata(pdev);
struct a210_aon_rpc_ack_common ack_msg = {0};
struct a210_aon_ipc *ipc;
int ret;
char *start = (char *)buf;
unsigned long val;
ipc = wdt_dev->ipc_handle;
val = simple_strtoul(start, &start, 0);
wdt_dev->is_aon_wdt_ena = val;
if (val)
a210_wdt_msg_hdr_fill(&wdt_dev->msg.hdr, A210_AON_WDG_FUNC_AON_WDT_ON);
else
a210_wdt_msg_hdr_fill(&wdt_dev->msg.hdr, A210_AON_WDG_FUNC_AON_WDT_OFF);
ret = a210_aon_call_rpc(ipc, &wdt_dev->msg, &ack_msg, true);
if (ret){
pr_err("%s: err:%d \n",__func__,ret);
return -EINVAL;
}
return size;
}
void a210_pm_power_off(void)
{
struct a210_wdt_device *wdt_dev = a210_power_off_wdt;
struct a210_aon_ipc *ipc = wdt_dev->ipc_handle;
struct a210_aon_rpc_ack_common ack_msg = {0};
int ret;
pr_info("[%s,%d]poweroff system...\n", __func__, __LINE__);
a210_wdt_msg_hdr_fill(&wdt_dev->msg.hdr, A210_AON_WDG_FUNC_POWER_OFF);
ret = a210_aon_call_rpc(ipc, &wdt_dev->msg, &ack_msg, true);
if (ret)
pr_err("failed to power off the system\n");
}
static DEVICE_ATTR(aon_sys_wdt, 0644, aon_sys_wdt_show, aon_sys_wdt_store);
static struct attribute *aon_sys_wdt_sysfs_entries[] = {
&dev_attr_aon_sys_wdt.attr,
NULL
};
static const struct attribute_group dev_attr_aon_sys_wdt_group = {
.attrs = aon_sys_wdt_sysfs_entries,
};
static int a210_wdt_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct a210_wdt_device *wdt_dev;
int ret;
struct watchdog_device *wdd;
printk("a210_wdt_probe\n");
msleep(1000);
wdt_dev = devm_kzalloc(dev, sizeof(*wdt_dev), GFP_KERNEL);
if (!wdt_dev)
return -ENOMEM;
wdt_dev->is_aon_wdt_ena = 0;
ret = a210_aon_get_handle(&(wdt_dev->ipc_handle),"aon0");
printk("a210_wdt_probe wdt_dev->ipc_handle 0x%x",wdt_dev->ipc_handle);
printk("a210_wdt_probe ret %d",ret);
if (ret == -EPROBE_DEFER)
return ret;
printk("a210_wdt_probe get_handleOK %d",ret);
wdd = devm_kzalloc(dev, sizeof(*wdd), GFP_KERNEL);
if (!wdd)
return -ENOMEM;
wdd->info = &a210_watchdog_info;
wdd->ops = &a210_watchdog_ops;
wdd->min_timeout = A210_WDT_MIN_TIMEOUT;
wdd->max_timeout = A210_WDT_MAX_TIMEOUT;
wdd->min_hw_heartbeat_ms = A210_RESET_PROTECTION_MS;
wdd->status = WATCHDOG_NOWAYOUT_INIT_STATUS;
watchdog_set_restart_priority(wdd, 128);
watchdog_set_drvdata(wdd, wdt_dev);
/* Set default timeout, maybe default value if the watchdog is running */
wdd->timeout = A210_WDT_TIMEOUT;
watchdog_init_timeout(wdd, 0, dev);
a210_wdt_set_timeout(wdd, wdd->timeout);
platform_set_drvdata(pdev, wdt_dev);
ret = a210_wdt_is_running(wdt_dev);
if (ret < 0) {
printk("a210_wdt_probe failed to get pmic wdt running state\n");
pr_err("failed to get pmic wdt running state\n");
return ret;
}
if (ret) {
a210_wdt_update_timeout(wdt_dev, wdd->timeout);
set_bit(WDOG_HW_RUNNING, &wdd->status);
}
ret = devm_watchdog_register_device(dev, wdd);
if (ret)
return ret;
printk("[%s,%d] register power off callback\n", __func__, __LINE__);
pr_info("[%s,%d] register power off callback\n", __func__, __LINE__);
pm_power_off = a210_pm_power_off;
a210_power_off_wdt = wdt_dev;
ret = sysfs_create_group(&pdev->dev.kobj, &dev_attr_aon_sys_wdt_group);
if (ret) {
dev_err(&pdev->dev, "Failed to create aon_sys_wdt sysfs.\n");
return ret;
}
pr_info("succeed to register p100 pmic watchdog\n");
printk("a210_wdt_probe succeed to register p100 pmic watchdog\n");
return 0;
}
static int a210_wdt_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct a210_wdt_device *wdt_dev = platform_get_drvdata(pdev);
struct a210_aon_ipc *ipc = wdt_dev->ipc_handle;
struct a210_aon_rpc_ack_common ack_msg = {0};
int ret;
a210_wdt_msg_hdr_fill(&wdt_dev->msg.hdr, A210_AON_WDG_FUNC_STOP);
ret = a210_aon_call_rpc(ipc, &wdt_dev->msg, &ack_msg, true);
if (ret)
dev_err(dev, "a210_wdt_suspend call aon wdt stop fail, ret:%d\n", ret);
return 0;
}
static int a210_wdt_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct a210_wdt_device *wdt_dev = platform_get_drvdata(pdev);
struct a210_aon_ipc *ipc = wdt_dev->ipc_handle;
struct a210_aon_rpc_ack_common ack_msg = {0};
int ret;
a210_wdt_msg_hdr_fill(&wdt_dev->msg.hdr, A210_AON_WDG_FUNC_START);
ret = a210_aon_call_rpc(ipc, &wdt_dev->msg, &ack_msg, true);
if (ret)
dev_err(dev, "a210_wdt_resume call aon wdt start fail, ret:%d\n", ret);
return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(a210_wdt_pm_ops, a210_wdt_suspend, a210_wdt_resume);
static struct platform_driver a210_wdt_driver = {
.driver = {
.name = DRV_NAME,
.pm = pm_sleep_ptr(&a210_wdt_pm_ops),
},
.probe = a210_wdt_probe,
};
static int __init a210_wdt_init(void)
{
static struct platform_device *pdev;
int ret;
pdev = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
ret = platform_driver_register(&a210_wdt_driver);
if (ret) {
platform_device_unregister(pdev);
return PTR_ERR(pdev);
}
pr_info("Watchdog module: %s loaded\n", DRV_NAME);
printk("Watchdog module: %s loaded\n", DRV_NAME);
return 0;
}
device_initcall(a210_wdt_init);
MODULE_AUTHOR("Wei.Liu <lw312886@linux.alibaba.com>");
MODULE_DESCRIPTION("PMIC Watchdog Driver for p100");
MODULE_LICENSE("GPL");

View File

@@ -10,76 +10,76 @@
#include <linux/types.h>
#define AON_RPC_MSG_MAGIC (0xef)
#define P100_AON_RPC_VERSION (2)
#define P100_AON_RPC_MSG_NUM (7)
#define A210_AON_RPC_VERSION (2)
#define A210_AON_RPC_MSG_NUM (7)
struct p100_aon_ipc;
struct a210_aon_ipc;
enum p100_aon_rpc_svc {
P100_AON_RPC_SVC_UNKNOWN = 0,
P100_AON_RPC_SVC_PM = 1,
P100_AON_RPC_SVC_MISC = 2,
P100_AON_RPC_SVC_AVFS = 3,
P100_AON_RPC_SVC_SYS = 4,
P100_AON_RPC_SVC_WDG = 5,
P100_AON_RPC_SVC_LPM = 6,
P100_AON_RPC_SVC_MAX = 0x3F,
enum a210_aon_rpc_svc {
A210_AON_RPC_SVC_UNKNOWN = 0,
A210_AON_RPC_SVC_PM = 1,
A210_AON_RPC_SVC_MISC = 2,
A210_AON_RPC_SVC_AVFS = 3,
A210_AON_RPC_SVC_SYS = 4,
A210_AON_RPC_SVC_WDG = 5,
A210_AON_RPC_SVC_LPM = 6,
A210_AON_RPC_SVC_MAX = 0x3F,
};
enum p100_aon_misc_func {
P100_AON_MISC_FUNC_UNKNOWN = 0,
P100_AON_MISC_FUNC_SET_CONTROL = 1,
P100_AON_MISC_FUNC_GET_CONTROL = 2,
P100_AON_MISC_FUNC_REGDUMP_CFG = 3,
enum a210_aon_misc_func {
A210_AON_MISC_FUNC_UNKNOWN = 0,
A210_AON_MISC_FUNC_SET_CONTROL = 1,
A210_AON_MISC_FUNC_GET_CONTROL = 2,
A210_AON_MISC_FUNC_REGDUMP_CFG = 3,
};
enum p100_aon_wdg_func {
P100_AON_WDG_FUNC_UNKNOWN = 0,
P100_AON_WDG_FUNC_START = 1,
P100_AON_WDG_FUNC_STOP = 2,
P100_AON_WDG_FUNC_PING = 3,
P100_AON_WDG_FUNC_TIMEOUTSET = 4,
P100_AON_WDG_FUNC_RESTART = 5,
P100_AON_WDG_FUNC_GET_STATE = 6,
P100_AON_WDG_FUNC_POWER_OFF = 7,
P100_AON_WDG_FUNC_AON_WDT_ON = 8,
P100_AON_WDG_FUNC_AON_WDT_OFF = 9,
enum a210_aon_wdg_func {
A210_AON_WDG_FUNC_UNKNOWN = 0,
A210_AON_WDG_FUNC_START = 1,
A210_AON_WDG_FUNC_STOP = 2,
A210_AON_WDG_FUNC_PING = 3,
A210_AON_WDG_FUNC_TIMEOUTSET = 4,
A210_AON_WDG_FUNC_RESTART = 5,
A210_AON_WDG_FUNC_GET_STATE = 6,
A210_AON_WDG_FUNC_POWER_OFF = 7,
A210_AON_WDG_FUNC_AON_WDT_ON = 8,
A210_AON_WDG_FUNC_AON_WDT_OFF = 9,
};
enum p100_aon_sys_func {
P100_AON_SYS_FUNC_UNKNOWN = 0,
P100_AON_SYS_FUNC_AON_RESERVE_MEM = 1,
enum a210_aon_sys_func {
A210_AON_SYS_FUNC_UNKNOWN = 0,
A210_AON_SYS_FUNC_AON_RESERVE_MEM = 1,
};
enum p100_aon_lpm_func {
P100_AON_LPM_FUNC_UNKNOWN = 0,
P100_AON_LPM_FUNC_REQUIRE_STR = 1,
P100_AON_LPM_FUNC_RESUME_STR = 2,
P100_AON_LPM_FUNC_REQUIRE_STD = 3,
P100_AON_LPM_FUNC_CPUHP = 4,
P100_AON_LPM_FUNC_REGDUMP_CFG = 5,
enum a210_aon_lpm_func {
A210_AON_LPM_FUNC_UNKNOWN = 0,
A210_AON_LPM_FUNC_REQUIRE_STR = 1,
A210_AON_LPM_FUNC_RESUME_STR = 2,
A210_AON_LPM_FUNC_REQUIRE_STD = 3,
A210_AON_LPM_FUNC_CPUHP = 4,
A210_AON_LPM_FUNC_REGDUMP_CFG = 5,
};
enum p100_aon_pm_func {
P100_AON_PM_FUNC_UNKNOWN = 0,
P100_AON_PM_FUNC_SET_RESOURCE_REGULATOR = 1,
P100_AON_PM_FUNC_GET_RESOURCE_REGULATOR = 2,
P100_AON_PM_FUNC_SET_RESOURCE_POWER_MODE = 3,
P100_AON_PM_FUNC_PWR_SET = 4,
P100_AON_PM_FUNC_PWR_GET = 5,
P100_AON_PM_FUNC_CHECK_FAULT = 6,
P100_AON_PM_FUNC_GET_TEMPERATURE = 7,
enum a210_aon_pm_func {
A210_AON_PM_FUNC_UNKNOWN = 0,
A210_AON_PM_FUNC_SET_RESOURCE_REGULATOR = 1,
A210_AON_PM_FUNC_GET_RESOURCE_REGULATOR = 2,
A210_AON_PM_FUNC_SET_RESOURCE_POWER_MODE = 3,
A210_AON_PM_FUNC_PWR_SET = 4,
A210_AON_PM_FUNC_PWR_GET = 5,
A210_AON_PM_FUNC_CHECK_FAULT = 6,
A210_AON_PM_FUNC_GET_TEMPERATURE = 7,
};
struct p100_aon_rpc_msg_hdr {
struct a210_aon_rpc_msg_hdr {
uint8_t ver; ///< version of msg hdr
uint8_t size; ///< msg size ,uinit in bytes,the size includes rpc msg header self.
uint8_t svc; ///< rpc main service id
uint8_t func; ///< rpc sub func id of specific service, sent by caller
} __packed __aligned(1);
struct p100_aon_rpc_ack_common {
struct p100_aon_rpc_msg_hdr hdr;
struct a210_aon_rpc_ack_common {
struct a210_aon_rpc_msg_hdr hdr;
uint8_t err_code;
} __packed __aligned(1);
@@ -158,13 +158,13 @@ struct p100_aon_rpc_ack_common {
/*
* Defines for SC PM Power Mode
*/
#define P100_AON_PM_PW_MODE_OFF 0 /* Power off */
#define P100_AON_PM_PW_MODE_STBY 1 /* Power in standby */
#define P100_AON_PM_PW_MODE_LP 2 /* Power in low-power */
#define P100_AON_PM_PW_MODE_ON 3 /* Power on */
#define A210_AON_PM_PW_MODE_OFF 0 /* Power off */
#define A210_AON_PM_PW_MODE_STBY 1 /* Power in standby */
#define A210_AON_PM_PW_MODE_LP 2 /* Power in low-power */
#define A210_AON_PM_PW_MODE_ON 3 /* Power on */
int p100_aon_call_rpc(struct p100_aon_ipc *ipc, void *msg, void *ack_msg, bool have_resp);
int p100_aon_get_handle(struct p100_aon_ipc **ipc, char* name);
int p100_aon_misc_set_control(struct p100_aon_ipc *ipc, u16 resource, u32 ctrl, u32 val);
int p100_aon_misc_get_control(struct p100_aon_ipc *ipc, u16 resource, u32 ctrl, u32 *val);
int a210_aon_call_rpc(struct a210_aon_ipc *ipc, void *msg, void *ack_msg, bool have_resp);
int a210_aon_get_handle(struct a210_aon_ipc **ipc, char* name);
int a210_aon_misc_set_control(struct a210_aon_ipc *ipc, u16 resource, u32 ctrl, u32 val);
int a210_aon_misc_get_control(struct a210_aon_ipc *ipc, u16 resource, u32 ctrl, u32 *val);
#endif /* _SC_IPC_H */

View File

@@ -19,7 +19,7 @@ _DEFAULT_OUTPUT = 'compile_commands.json'
_DEFAULT_LOG_LEVEL = 'WARNING'
_FILENAME_PATTERN = r'^\..*\.cmd$'
_LINE_PATTERN = r'^savedcmd_[^ ]*\.o := (.* )([^ ]*\.[cS]) *(;|$)'
_LINE_PATTERN = r'^(saved)?cmd_[^ ]*\.o := (?P<command_prefix>.* )(?P<file_path>[^ ]*\.[cS]) *(;|$)'
_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
# The tools/ directory adopts a different build system, and produces .cmd
# files in a different format. Do not support it.
@@ -64,7 +64,7 @@ def parse_arguments():
args = parser.parse_args()
return (args.log_level,
os.path.abspath(args.directory),
os.path.realpath(args.directory),
args.output,
args.ar,
args.paths if len(args.paths) > 0 else [args.directory])
@@ -167,13 +167,13 @@ def process_line(root_directory, command_prefix, file_path):
root_directory or file_directory.
"""
# The .cmd files are intended to be included directly by Make, so they
# escape the pound sign '#', either as '\#' or '$(pound)' (depending on the
# kernel version). The compile_commands.json file is not interepreted
# by Make, so this code replaces the escaped version with '#'.
prefix = command_prefix.replace('\#', '#').replace('$(pound)', '#')
# escape the pound sign '#' as '$(pound)'. The compile_commands.json file
# is not interepreted by Make, so this code replaces the escaped version
# with '#'.
prefix = command_prefix.replace('$(pound)', '#')
# Use os.path.abspath() to normalize the path resolving '.' and '..' .
abs_path = os.path.abspath(os.path.join(root_directory, file_path))
# Return the canonical path, eliminating any symbolic links encountered in the path.
abs_path = os.path.realpath(os.path.join(root_directory, file_path))
if not os.path.exists(abs_path):
raise ValueError('File %s not found' % abs_path)
return {
@@ -213,15 +213,15 @@ def main():
result = line_matcher.match(f.readline())
if result:
try:
entry = process_line(directory, result.group(1),
result.group(2))
entry = process_line(directory, result.group('command_prefix'),
result.group('file_path'))
compile_commands.append(entry)
except ValueError as err:
logging.info('Could not add line from %s: %s',
cmdfile, err)
with open(output, 'wt') as f:
json.dump(compile_commands, f, indent=2, sort_keys=True)
json.dump(sorted(compile_commands, key=lambda x: x["file"]), f, indent=2, sort_keys=True)
if __name__ == '__main__':

File diff suppressed because it is too large Load Diff

View File

@@ -136,7 +136,7 @@ static void es8156_enable_spk(struct es8156_priv *es8156, bool enable)
static const char *es8156_DAC_SRC[] = { "Left to Left, Right to Right",
"Right to both Left and Right","Left to both Left & Right", "Left to Right, Right to Left" };
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9600, 50, 1);
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9550, 50, 1);
static const DECLARE_TLV_DB_SCALE(alc_gain_tlv,-2800,400,1);
static SOC_ENUM_SINGLE_DECL(es8165_dac_enum, ES8156_MISC_CONTROL3_REG18, 4, es8156_DAC_SRC);
@@ -152,8 +152,8 @@ static const struct snd_kcontrol_new es8156_snd_controls[] = {
SOC_DOUBLE("ALC Maximum Minimum Volume",ES8156_ALC_CONFIG3_REG17,
4,0,15,0),
/* DAC Digital controls */
SOC_SINGLE_TLV("DAC Playback Volume", ES8156_VOLUME_CONTROL_REG14,
0, ES8156_VOL_MAX, 0, dac_vol_tlv),
SOC_SINGLE_TLV("Master Playback Volume", ES8156_VOLUME_CONTROL_REG14, 0,
ES8156_VOL_MAX, 0, dac_vol_tlv),
SOC_SINGLE("HP Switch",ES8156_ANALOG_SYS3_REG22,3,1,0),