Merge commit '06f6ae89f8f371f4a923cc0bd9d1d05c3ed769dd'

* commit '06f6ae89f8f371f4a923cc0bd9d1d05c3ed769dd':
  clk: rockchip: rv1126b: fix clk_ref_pipephy parent clk
  pwm: rockchip: use the completion to check whether biphasic result is valid
  pwm: rockchip: use the completion to check whether frequency result is valid
  arm64: dts: rockchip: add rk3588-vehicle-evb-v23-linux
  drm/bridge: analogix_dp: use &link_train.max_lane_count to determine the &link_train.lane_count
  media: rockchip: fec: add module parameter cache_linesize
  pwm: rockchip: fix the check of disabling process for continuous biphasic counter mode
  arm64: dts: rockchip: rk3576: add dmcdbg node
  arm64: dts: rockchip: rk3588: add dmcdbg node
  arm64: dts: rockchip: rk356x: add dmcdbg node
  arm64: configs: rockchip_linux_defconfig enable ROCKCHIP_DMC_DEBUG
  ARM: configs: rockchip_linux_defconfig enable ROCKCHIP_DMC_DEBUG
  soc: rockchip: dmc_debug: move driver and support more rockchip SOCs
  arm64: dts: rockchip: rv1126b: add pvtpll node for isp
  clk: rockchip: clk-pvtpll: add isp pvtpll clk for rv1126b
  ARM: configs: rv1126b-ipc.config: update camera sensor
  net: can: rockchip: rk3576: support auto retx cnt setting
  media: rockchip: vicap fixes array out of bounds issue
  arm64: dts: rockchip: rv1126b-evb3-v10: fix mclk and dphy error

Change-Id: I0d84a2d30e52d4667820a2cf3d326f966492fa57
This commit is contained in:
Tao Huang
2025-04-16 20:14:40 +08:00
22 changed files with 431 additions and 237 deletions

View File

@@ -425,6 +425,7 @@ CONFIG_CPU_RK3188=y
CONFIG_CPU_RK3288=y
CONFIG_CPU_RK322X=y
CONFIG_ROCKCHIP_CPUINFO=y
CONFIG_ROCKCHIP_DMC_DEBUG=y
CONFIG_ROCKCHIP_GRF=y
CONFIG_ROCKCHIP_IODOMAIN=y
CONFIG_ROCKCHIP_IPA=y

View File

@@ -9,8 +9,8 @@ CONFIG_ROCKCHIP_RGA_PROC_FS=y
CONFIG_SPI=y
CONFIG_VFAT_FS=y
CONFIG_VIDEO_SC200AI=m
CONFIG_VIDEO_SC3336=m
CONFIG_VIDEO_SC530AI=m
CONFIG_VIDEO_SC450AI=m
CONFIG_VIDEO_SC850SL=m
# CONFIG_AD2S1200 is not set
# CONFIG_AD2S1210 is not set
# CONFIG_AD2S90 is not set

View File

@@ -351,6 +351,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-vehicle-evb-v20.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-vehicle-evb-v21.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-vehicle-evb-v22.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-vehicle-evb-v23.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-vehicle-evb-v23-linux.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-vehicle-s66-v10.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-evb1-lp4x-v10.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-evb1-lp4x-v10-linux.dtb

View File

@@ -283,6 +283,11 @@
};
};
dmcdbg: dmcdbg {
compatible = "rockchip,rk3568-dmcdbg";
status = "disabled";
};
firmware {
scmi: scmi {
compatible = "arm,scmi-smc";

View File

@@ -1268,6 +1268,11 @@
};
};
dmcdbg: dmcdbg {
compatible = "rockchip,rk3576-dmcdbg";
status = "disabled";
};
firmware {
scmi: scmi {
compatible = "arm,scmi-smc";

View File

@@ -0,0 +1,44 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2025 Rockchip Electronics Co., Ltd.
*
*/
/dts-v1/;
#include "rk3588-vehicle-evb-v23.dts"
#include "rk3588-linux.dtsi"
/ {
model = "Rockchip RK3588 VEHICLE EVB V23 Board";
compatible = "rockchip,rk3588-vehicle-evb-v23-linux", "rockchip,rk3588";
reserved-memory {
/delete-node/vendor_storage_rm;
};
/delete-node/vendor_storage;
};
&vop {
/delete-property/ support-multi-area;
};
/*dsi*/
&i2c2 {
himax@45 {
status = "disabled";
};
himax_split@46 {
status = "disabled";
};
};
/*dp0*/
&i2c4 {
himax@45 {
status = "disabled";
};
};

View File

@@ -2400,6 +2400,11 @@
};
};
dmcdbg: dmcdbg {
compatible = "rockchip,rk3588-dmcdbg";
status = "disabled";
};
firmware {
scmi: scmi {
compatible = "arm,scmi-smc";

View File

@@ -227,7 +227,7 @@
cpu-supply = <&vdd_cpu>;
};
&csi2_dphy0 {
&csi2_dphy3 {
status = "okay";
ports {
@@ -238,7 +238,7 @@
#address-cells = <1>;
#size-cells = <0>;
csi_dphy_input0: endpoint@1 {
csi_dphy3_input0: endpoint@1 {
reg = <1>;
remote-endpoint = <&ps5458_out>;
data-lanes = <1 2>;
@@ -249,9 +249,9 @@
#address-cells = <1>;
#size-cells = <0>;
csidphy0_out: endpoint@0 {
csidphy3_out: endpoint@0 {
reg = <0>;
remote-endpoint = <&mipi0_csi2_input>;
remote-endpoint = <&mipi2_csi2_input>;
};
};
};
@@ -292,7 +292,7 @@
ps5458: ps5458@4c {
compatible = "prime,ps5458";
reg = <0x4c>;
clocks = <&cru CLK_MIPI0_OUT2IO>;
clocks = <&cru CLK_MIPI2_OUT2IO>;
clock-names = "xvclk";
reset-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@@ -303,7 +303,7 @@
rockchip,camera-module-lens-name = "default";
port {
ps5458_out: endpoint {
remote-endpoint = <&csi_dphy_input0>;
remote-endpoint = <&csi_dphy3_input0>;
data-lanes = <1 2>;
};
};
@@ -326,7 +326,7 @@
};
};
&mipi0_csi2 {
&mipi2_csi2 {
status = "okay";
ports {
@@ -338,9 +338,9 @@
#address-cells = <1>;
#size-cells = <0>;
mipi0_csi2_input: endpoint@1 {
mipi2_csi2_input: endpoint@1 {
reg = <1>;
remote-endpoint = <&csidphy0_out>;
remote-endpoint = <&csidphy3_out>;
};
};
@@ -349,9 +349,9 @@
#address-cells = <1>;
#size-cells = <0>;
mipi0_csi2_output: endpoint@0 {
mipi2_csi2_output: endpoint@0 {
reg = <0>;
remote-endpoint = <&cif_mipi_in0>;
remote-endpoint = <&cif_mipi_in2>;
};
};
};
@@ -377,21 +377,21 @@
status = "okay";
};
&rkcif_mipi_lvds {
&rkcif_mipi_lvds2 {
status = "okay";
port {
cif_mipi_in0: endpoint {
remote-endpoint = <&mipi0_csi2_output>;
cif_mipi_in2: endpoint {
remote-endpoint = <&mipi2_csi2_output>;
};
};
};
&rkcif_mipi_lvds_sditf {
&rkcif_mipi_lvds2_sditf {
status = "okay";
port {
mipi_lvds_sditf: endpoint {
mipi_lvds2_sditf: endpoint {
remote-endpoint = <&isp_vir0>;
};
};
@@ -418,7 +418,7 @@
isp_vir0: endpoint@0 {
reg = <0>;
remote-endpoint = <&mipi_lvds_sditf>;
remote-endpoint = <&mipi_lvds2_sditf>;
};
};
};

View File

@@ -206,6 +206,15 @@
assigned-clock-rates = <1200000000>;
};
pvtpll_isp: pvtpll-isp@21c60000 {
compatible = "rockchip,rv1126b-isp-pvtpll";
reg = <0x21c60000 0x100>;
#clock-cells = <0>;
clock-output-names = "clk_isp_pvtpll";
assigned-clocks = <&pvtpll_isp>;
assigned-clock-rates = <490000000>;
};
pvtpll_enc: pvtpll-enc@21f00000 {
compatible = "rockchip,rv1126b-enc-pvtpll";
reg = <0x21f00000 0x100>;

View File

@@ -557,6 +557,7 @@ CONFIG_CPU_RK3588=y
CONFIG_ROCKCHIP_AMP=y
CONFIG_ROCKCHIP_CPUINFO=y
CONFIG_ROCKCHIP_CSU=y
CONFIG_ROCKCHIP_DMC_DEBUG=y
CONFIG_ROCKCHIP_GRF=y
CONFIG_ROCKCHIP_IODOMAIN=y
CONFIG_ROCKCHIP_IPA=y

View File

@@ -166,6 +166,11 @@ static struct pvtpll_table rv1126b_enc_pvtpll_table[] = {
ROCKCHIP_PVTPLL(550000000, 0, 72),
};
static struct pvtpll_table rv1126b_isp_pvtpll_table[] = {
/* rate_hz, ring_se, length */
ROCKCHIP_PVTPLL(490000000, 0, 100),
};
static struct pvtpll_table rv1126b_npu_pvtpll_table[] = {
/* rate_hz, ring_se, length, volt_sel_thr */
ROCKCHIP_PVTPLL_VOLT_SEL(1000000000, 0, 12, 7),
@@ -670,6 +675,15 @@ static const struct rockchip_clock_pvtpll_info rv1126b_enc_pvtpll_data = {
.pvtpll_calibrate = rv1103b_pvtpll_calibrate,
};
static const struct rockchip_clock_pvtpll_info rv1126b_isp_pvtpll_data = {
.config = rv1103b_pvtpll_configs,
.table_size = ARRAY_SIZE(rv1126b_isp_pvtpll_table),
.table = rv1126b_isp_pvtpll_table,
.calibrate_length_step = 8,
.calibrate_freq_per_step = 20,
.pvtpll_calibrate = rv1103b_pvtpll_calibrate,
};
static const struct rockchip_clock_pvtpll_info rv1126b_npu_pvtpll_data = {
.config = rv1126b_npu_pvtpll_configs,
.table_size = ARRAY_SIZE(rv1126b_npu_pvtpll_table),
@@ -717,6 +731,10 @@ static const struct of_device_id rockchip_clock_pvtpll_match[] = {
.compatible = "rockchip,rv1126b-enc-pvtpll",
.data = (void *)&rv1126b_enc_pvtpll_data,
},
{
.compatible = "rockchip,rv1126b-isp-pvtpll",
.data = (void *)&rv1126b_isp_pvtpll_data,
},
{
.compatible = "rockchip,rv1126b-npu-pvtpll",
.data = (void *)&rv1126b_npu_pvtpll_data,

View File

@@ -135,7 +135,7 @@ PNAME(sclk_uart0_p) = { "sclk_uart0_src", "xin24m", "clk_rcosc_src" };
PNAME(clk_osc_rcosc_ctrl_p) = { "clk_rcosc_src", "clk_testout_out" };
PNAME(lrck_src_asrc_p) = { "mclk_asrc0", "mclk_asrc1", "mclk_asrc2", "mclk_asrc3",
"fs_inter_from_sai0", "fs_inter_from_sai1", "fs_inter_from_sai2", "clkout_pdm"};
PNAME(clk_ref_pipephy_p) = { "clk_ref_pipephy_cpll_src", "xin_osc0_pipephy" };
PNAME(clk_ref_pipephy_p) = { "clk_ref_pipephy_cpll_src", "xin24m" };
PNAME(clk_timer0_parents_p) = { "clk_timer_root", "mclk_sai0_from_io", "sclk_sai0_from_io" };
PNAME(clk_timer1_parents_p) = { "clk_timer_root", "mclk_sai1_from_io", "sclk_sai1_from_io" };
PNAME(clk_timer2_parents_p) = { "clk_timer_root", "mclk_sai2_from_io", "sclk_sai2_from_io" };

View File

@@ -889,7 +889,7 @@ static int analogix_dp_full_link_train(struct analogix_dp_device *dp,
analogix_dp_reset_macro(dp);
/* Setup TX lane count */
dp->link_train.lane_count = min_t(u32, dp->link_train.lane_count, max_lanes);
dp->link_train.lane_count = min_t(u32, dp->link_train.max_lane_count, max_lanes);
/* Setup TX lane rate */
if (analogix_dp_select_rx_bandwidth(dp)) {

View File

@@ -11501,7 +11501,9 @@ static void rkcif_buf_done_prepare(struct rkcif_stream *stream,
}
if (cif_dev->channels[0].capture_info.mode == RKMODULE_ONE_CH_TO_MULTI_ISP)
vb_done->sequence /= cif_dev->channels[0].capture_info.one_to_multi.isp_num;
} else if (cif_dev->rdbk_buf[stream->id]) {
} else if (((cif_dev->hdr.hdr_mode == HDR_X2 && stream->id < 2) ||
(cif_dev->hdr.hdr_mode == HDR_X3 && stream->id < 3))
&& cif_dev->rdbk_buf[stream->id]) {
vb_done = &cif_dev->rdbk_buf[stream->id]->vb;
if (cif_dev->chip_id < CHIP_RK3588_CIF &&
cif_dev->active_sensor->mbus.type == V4L2_MBUS_BT656)
@@ -11512,7 +11514,9 @@ static void rkcif_buf_done_prepare(struct rkcif_stream *stream,
cif_dev->rdbk_buf[stream->id]->fe_timestamp = rkcif_time_get_ns(cif_dev);
}
if (cif_dev->hdr.hdr_mode == NO_HDR || cif_dev->hdr.hdr_mode == HDR_COMPR) {
if (cif_dev->hdr.hdr_mode == NO_HDR || cif_dev->hdr.hdr_mode == HDR_COMPR ||
(cif_dev->hdr.hdr_mode == HDR_X2 && stream->id > 1) ||
(cif_dev->hdr.hdr_mode == HDR_X3 && stream->id > 2)) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) {
if (stream->frame_phase == CIF_CSI_FRAME1_READY && active_buf) {

View File

@@ -13,10 +13,14 @@ int rkfec_debug;
module_param_named(debug, rkfec_debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-6)");
int rkfec_stdfps = 30;
static int rkfec_stdfps = 30;
module_param_named(standardfps, rkfec_stdfps, int, 0644);
MODULE_PARM_DESC(standardfps, "standard fps");
static int rkfec_cache_linesize = 2;
module_param_named(cache_linesize, rkfec_cache_linesize, int, 0644);
MODULE_PARM_DESC(cache_linesize, "Cache linesize (0-3)");
#if IS_LINUX_VERSION_AT_LEAST_6_1
#define GET_SG_TABLE(mem_ops, off_buf) mem_ops->cookie(&(off_buf)->vb, (off_buf)->mem)
#else
@@ -443,8 +447,10 @@ static int fec_running(struct file *file, struct rkfec_in_out *buf)
writel(0, base + RKFEC_CLK_DIS);
// cache
writel(0x1c, base + RKFEC_CACHE_MAX_READS);
writel(0x27, base + RKFEC_CACHE_CTRL);
val = SW_CACHE_LINESIZE(rkfec_cache_linesize) | 0x7;
writel(val, base + RKFEC_CACHE_CTRL);
//update
writel(SYS_FEC_FORCE_UPD, base + RKFEC_UPD);

View File

@@ -32,8 +32,8 @@ static void offline_fec_show_hw(struct seq_file *p, struct rkfec_hw_dev *hw)
};
static const char * const lut_density[] = {
"16x8",
"32x16",
"16x8",
"4x4"
};
@@ -86,7 +86,7 @@ static int offline_fec_show(struct seq_file *p, void *v)
seq_printf(p, "%-10s Version:v%02x.%02x.%02x\n", ofl->v4l2_dev.name,
RKFEC_DRIVER_VERSION >> 16,
(RKFEC_DRIVER_VERSION & 0xff00) >> 8,
RKFEC_DRIVER_VERSION & 0x00ff);
RKFEC_DRIVER_VERSION & 0xff);
for (i = 0; i < ofl->hw->clks_num; i++) {
seq_printf(p, "%-10s %ld\n", ofl->hw->match_data->clks[i],
clk_get_rate(ofl->hw->clks[i]));

View File

@@ -123,6 +123,13 @@
/* LUT SIZE */
#define SW_LUT_SIZE(x) ((x) & 0x3fffff)
/* FEC_CACHE_CTRL */
#define SW_CACHE_LINESIZE(x) ((x & 0x3) << 4)
#define SW_CACHE_FORCE_BSP(x) ((x & 0x1) << 12)
#define SW_REPLACE_STRATEGY(x) ((x & 0x1) << 9)
#define SW_CACHELINE_EN(x) ((x & 0x1) << 13)
#define SW_CACHE_BYPASS_EN(x) ((x & 0x1) << 6)
/* FEC_INT_EN */
#define PBUF_BD_CRS_P BIT(0)
#define FEC_STOP_IRQ BIT(1)

View File

@@ -170,7 +170,7 @@ enum {
#define RESET_MODE 0
#define WORK_MODE BIT(0)
#define RETX_TIME_LIMIT_CNT 0x12c /* 300 */
#define RETX_TIME_LIMIT_CNT_MAX 0xffff
#define RETX_TIME_LIMIT_SHIFT 3
#define RETX_LIMIT_EN BIT(1)
#define AUTO_RETX_EN BIT(0)
@@ -384,6 +384,7 @@ struct rk3576_canfd {
u32 rx_fifo_mask;
int rx_fifo_depth;
int rx_max_data;
unsigned int auto_retx_cnt;
bool use_dma;
u32 dma_size;
u32 dma_thr;
@@ -638,9 +639,12 @@ static int rk3576_canfd_start(struct net_device *ndev)
rk3576_canfd_write(rcan, CANFD_ERROR_MASK, 0);
}
rk3576_canfd_write(rcan, CANFD_AUTO_RETX_CFG,
AUTO_RETX_EN | RETX_LIMIT_EN |
(RETX_TIME_LIMIT_CNT << RETX_TIME_LIMIT_SHIFT));
if (rcan->auto_retx_cnt)
rk3576_canfd_write(rcan, CANFD_AUTO_RETX_CFG,
AUTO_RETX_EN | RETX_LIMIT_EN |
(rcan->auto_retx_cnt << RETX_TIME_LIMIT_SHIFT));
else
rk3576_canfd_write(rcan, CANFD_AUTO_RETX_CFG, AUTO_RETX_EN);
rk3576_canfd_write(rcan, CANFD_MODE, val);
if (rcan->use_dma)
@@ -1279,6 +1283,13 @@ static int rk3576_canfd_probe(struct platform_device *pdev)
rcan->rx_fifo_shift = INTM_LEFT_CNT_SHIFT;
rcan->rx_fifo_mask = INTM_LEFT_CNT_MASK;
if (device_property_read_u32(&pdev->dev, "rockchip,auto-retx-cnt", &val))
rcan->auto_retx_cnt = 0;
else
rcan->auto_retx_cnt = val;
if (rcan->auto_retx_cnt > RETX_TIME_LIMIT_CNT_MAX)
rcan->auto_retx_cnt = RETX_TIME_LIMIT_CNT_MAX;
/* rx-max-data only 4 Words or 18 words are supported */
if (device_property_read_u32_array(&pdev->dev, "rockchip,rx-max-data", &val, 1))
rcan->rx_max_data = 18;

View File

@@ -314,6 +314,8 @@ struct rockchip_pwm_chip {
struct resource *res;
struct dentry *debugfs;
struct completion ir_trans_completion;
struct completion freq_meter_completion;
struct completion biphasic_completion;
void __iomem *base;
unsigned long clk_rate;
unsigned long is_clk_enabled;
@@ -329,8 +331,6 @@ struct rockchip_pwm_chip {
bool wave_support;
bool biphasic_support;
bool ledc_support;
bool freq_res_valid;
bool biphasic_res_valid;
int channel_id;
int irq;
u32 scaler;
@@ -740,14 +740,15 @@ static irqreturn_t rockchip_pwm_irq_v4(int irq, void *data)
if (val & FREQ_INT) {
writel_relaxed(FREQ_INT, pc->base + INTSTS);
pc->freq_res_valid = true;
complete(&pc->freq_meter_completion);
ret = IRQ_HANDLED;
}
if (val & BIPHASIC_INT) {
writel_relaxed(BIPHASIC_INT, pc->base + INTSTS);
pc->biphasic_res_valid = true;
complete(&pc->biphasic_completion);
ret = IRQ_HANDLED;
}
@@ -1241,7 +1242,7 @@ static int rockchip_pwm_set_freq_meter_v4(struct pwm_chip *chip, struct pwm_devi
int ret;
if (enable) {
pc->freq_res_valid = false;
reinit_completion(&pc->freq_meter_completion);
arbiter = BIT(pc->channel_id) << FREQ_READ_LOCK_SHIFT |
BIT(pc->channel_id) << FREQ_GRANT_SHIFT;
@@ -1281,22 +1282,22 @@ static int rockchip_pwm_get_freq_meter_result_v4(struct pwm_chip *chip, struct p
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
u32 freq_res;
u32 freq_timer;
int ret = 0;
usleep_range(delay_ms * USEC_PER_MSEC, delay_ms * USEC_PER_MSEC);
if (pc->freq_res_valid) {
freq_res = readl_relaxed(pc->base + FREQ_RESULT_VALUE);
freq_timer = readl_relaxed(pc->base + FREQ_TIMER_VALUE);
*freq_hz = DIV_ROUND_CLOSEST_ULL((u64)pc->clk_rate * freq_res, freq_timer);
if (!*freq_hz)
return -EINVAL;
pc->freq_res_valid = false;
} else {
dev_err(chip->dev, "failed to wait for freq_meter interrupt\n");
ret = wait_for_completion_timeout(&pc->freq_meter_completion,
msecs_to_jiffies(delay_ms * 3 / 2));
if (!ret) {
dev_err(chip->dev, "Failed to wait for PWM%d frequency meter result to be valid\n",
pc->channel_id);
return -ETIMEDOUT;
}
freq_res = readl_relaxed(pc->base + FREQ_RESULT_VALUE);
freq_timer = readl_relaxed(pc->base + FREQ_TIMER_VALUE);
*freq_hz = DIV_ROUND_CLOSEST_ULL((u64)pc->clk_rate * freq_res, freq_timer);
if (!*freq_hz)
return -EINVAL;
return 0;
}
@@ -1737,7 +1738,9 @@ static int rockchip_pwm_set_biphasic_v4(struct pwm_chip *chip, struct pwm_device
ret = clk_enable(pc->clk);
if (ret)
return ret;
pc->biphasic_res_valid = false;
if (!config->is_continuous)
reinit_completion(&pc->biphasic_completion);
ctrl = BIPHASIC_EN(true) |
BIPHASIC_CONTINOUS_MODE_EN(config->is_continuous) |
@@ -1807,7 +1810,7 @@ int rockchip_pwm_set_biphasic(struct pwm_device *pwm, struct rockchip_pwm_biphas
dev_err(chip->dev, "Failed to setup biphasic counter mode for PWM%d\n",
pc->channel_id);
} else {
if (pc->biphasic_config->enable && !config->is_continuous) {
if (pc->biphasic_config && pc->biphasic_config->enable && !config->is_continuous) {
ret = pc->data->funcs.get_biphasic_result(chip, pwm, biphasic_res);
if (ret) {
dev_err(chip->dev,
@@ -1833,27 +1836,28 @@ static int rockchip_pwm_get_biphasic_result_v4(struct pwm_chip *chip, struct pwm
const struct rockchip_pwm_biphasic_config *config = pc->biphasic_config;
u32 val;
u32 biphasic_timer;
int ret = 0;
if (!config->is_continuous) {
usleep_range(config->delay_ms * USEC_PER_MSEC, config->delay_ms * USEC_PER_MSEC);
if (pc->biphasic_res_valid) {
*biphasic_res = readl_relaxed(pc->base + BIPHASIC_RESULT_VALUE);
if (!*biphasic_res)
return -EINVAL;
if (pc->biphasic_config->mode == PWM_BIPHASIC_COUNTER_MODE0_FREQ) {
val = *biphasic_res;
biphasic_timer = readl_relaxed(pc->base + BIPHASIC_TIMER_VALUE);
*biphasic_res = DIV_ROUND_CLOSEST_ULL((u64)pc->clk_rate * val,
biphasic_timer);
}
pc->biphasic_res_valid = false;
} else {
dev_err(chip->dev, "failed to wait for biphasic counter interrupt\n");
ret = wait_for_completion_timeout(&pc->biphasic_completion,
msecs_to_jiffies(config->delay_ms * 3 / 2));
if (!ret) {
dev_err(chip->dev,
"Failed to wait for PWM%d biphasic counter result to be valid\n",
pc->channel_id);
return -ETIMEDOUT;
}
*biphasic_res = readl_relaxed(pc->base + BIPHASIC_RESULT_VALUE);
if (!*biphasic_res)
return -EINVAL;
if (pc->biphasic_config->mode == PWM_BIPHASIC_COUNTER_MODE0_FREQ) {
val = *biphasic_res;
biphasic_timer = readl_relaxed(pc->base + BIPHASIC_TIMER_VALUE);
*biphasic_res = DIV_ROUND_CLOSEST_ULL((u64)pc->clk_rate * val,
biphasic_timer);
}
} else {
*biphasic_res = readl_relaxed(pc->base + BIPHASIC_RESULT_VALUE_SYNC);
}
@@ -2373,6 +2377,12 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
goto err_pclk;
}
if (pc->freq_meter_support)
init_completion(&pc->freq_meter_completion);
if (pc->biphasic_support)
init_completion(&pc->biphasic_completion);
if (pc->data->funcs.irq_handler) {
/*
* For pwm v1-v3, the older platform may not support interrupt, and

View File

@@ -58,6 +58,12 @@ config ROCKCHIP_CSU
help
This adds the clock subunit driver for Rockchip SoCs.
config ROCKCHIP_DMC_DEBUG
tristate "ROCKCHIP DMC DEBUG Driver"
depends on ARCH_ROCKCHIP && HAVE_ARM_SMCCC
help
This adds the dmc debug driver for the ROCKCHIP DMC.
config ROCKCHIP_GRF
tristate "Rockchip General Register Files support"
help

View File

@@ -6,6 +6,7 @@ obj-$(CONFIG_ROCKCHIP_AMP) += rockchip_amp.o
obj-$(CONFIG_ROCKCHIP_CPUINFO) += rockchip-cpuinfo.o
obj-$(CONFIG_ROCKCHIP_CSU) += rockchip_csu.o
obj-$(CONFIG_ROCKCHIP_DISABLE_UNUSED) += rockchip_disable_unused.o
obj-$(CONFIG_ROCKCHIP_DMC_DEBUG) += rockchip_dmc_debug.o
obj-$(CONFIG_ROCKCHIP_GRF) += grf.o
obj-$(CONFIG_ROCKCHIP_HW_DECOMPRESS) += rockchip_decompress.o
obj-$(CONFIG_ROCKCHIP_HW_DECOMPRESS_USER) += rockchip_decompress_user.o

View File

@@ -15,7 +15,7 @@
#include <soc/rockchip/rockchip_sip.h>
#include "rockchip_dmc_timing.h"
#include "../../devfreq/rockchip_dmc_timing.h"
/*
* DMCDBG share memory request 4KB for delivery parameter
@@ -74,10 +74,15 @@ struct dram_cap_info {
struct dram_info {
unsigned int version;
char dramtype[10];
char dramtype[12];
unsigned int dramfreq;
unsigned int channel_num;
struct dram_cap_info ch[2];
/* Version 2, support dramid */
unsigned int dramid[3];
/* Version 3, support 4 channel */
unsigned int ext_channel_num;
struct dram_cap_info ext_ch[2];
};
static const char * const power_save_msg[] = {
@@ -192,9 +197,9 @@ static int dmcinfo_proc_show(struct seq_file *m, void *v)
{
struct arm_smccc_res res;
struct dram_info *p_dram_info;
struct file *fp = NULL;
char cur_freq[20] = {0};
char governor[20] = {0};
struct file *fp = NULL;
char cur_freq[20] = { 0 };
char governor[20] = { 0 };
loff_t pos;
u32 i;
@@ -205,6 +210,11 @@ static int dmcinfo_proc_show(struct seq_file *m, void *v)
res.a0);
return -ENOMEM;
}
if (res.a1) {
seq_printf(m, "ddrdbg function get dram info error:%lx\n",
res.a1);
return -EPERM;
}
if (!dmcdbg_data.inited_flag) {
seq_puts(m, "dmcdbg_data no int\n");
@@ -213,25 +223,28 @@ static int dmcinfo_proc_show(struct seq_file *m, void *v)
p_dram_info = (struct dram_info *)dmcdbg_data.share_memory;
/* dram type information */
seq_printf(m,
"DramType: %s\n"
,
p_dram_info->dramtype
);
seq_printf(m, "DramType: %s\n", p_dram_info->dramtype);
if (p_dram_info->version >= 0x2) {
if ((strcmp(p_dram_info->dramtype, "LPDDR2") == 0) ||
(strcmp(p_dram_info->dramtype, "LPDDR3") == 0) ||
(strcmp(p_dram_info->dramtype, "LPDDR4") == 0) ||
(strcmp(p_dram_info->dramtype, "LPDDR4X") == 0) ||
(strcmp(p_dram_info->dramtype, "LPDDR5") == 0))
seq_printf(m,
"Dram ID: MR5=0x%x,MR6=0x%x,MR7=0x%x\n",
p_dram_info->dramid[0],
p_dram_info->dramid[1],
p_dram_info->dramid[2]);
else
seq_puts(m, "Dram ID: None\n");
}
/* dram capacity information */
seq_printf(m,
"\n"
"DramCapacity:\n"
);
seq_printf(m, "\n"
"DramCapacity:\n");
for (i = 0; i < p_dram_info->channel_num; i++) {
if (p_dram_info->channel_num == 2)
seq_printf(m,
"Channel [%d]:\n"
,
i
);
seq_printf(m, "Channel [%d]:\n", i);
seq_printf(m,
"CS Count: %d\n"
@@ -241,8 +254,7 @@ static int dmcinfo_proc_show(struct seq_file *m, void *v)
"CS0_Row: %d\n"
"CS1_Row: %d\n"
"DieBusWidth: %d bit\n"
"TotalSize: %d MB\n"
,
"TotalSize: %d MB\n",
p_dram_info->ch[i].rank,
p_dram_info->ch[i].buswidth,
p_dram_info->ch[i].col,
@@ -250,8 +262,30 @@ static int dmcinfo_proc_show(struct seq_file *m, void *v)
p_dram_info->ch[i].cs0_row,
p_dram_info->ch[i].cs1_row,
p_dram_info->ch[i].die_buswidth,
p_dram_info->ch[i].size
);
p_dram_info->ch[i].size);
}
if (p_dram_info->version >= 0x3) {
for (i = 0; i < p_dram_info->ext_channel_num; i++) {
seq_printf(m, "Channel [%d]:\n", i + 2);
seq_printf(m,
"CS Count: %d\n"
"Bus Width: %d bit\n"
"Column: %d\n"
"Bank: %d\n"
"CS0_Row: %d\n"
"CS1_Row: %d\n"
"DieBusWidth: %d bit\n"
"TotalSize: %d MB\n",
p_dram_info->ext_ch[i].rank,
p_dram_info->ext_ch[i].buswidth,
p_dram_info->ext_ch[i].col,
p_dram_info->ext_ch[i].bank,
p_dram_info->ext_ch[i].cs0_row,
p_dram_info->ext_ch[i].cs1_row,
p_dram_info->ext_ch[i].die_buswidth,
p_dram_info->ext_ch[i].size);
}
}
/* check devfreq/dmc device */
@@ -260,10 +294,8 @@ static int dmcinfo_proc_show(struct seq_file *m, void *v)
seq_printf(m,
"\n"
"devfreq/dmc: Disable\n"
"DramFreq: %d\n"
,
p_dram_info->dramfreq
);
"DramFreq: %d\n",
p_dram_info->dramfreq);
} else {
pos = 0;
kernel_read(fp, cur_freq, sizeof(cur_freq), &pos);
@@ -282,15 +314,11 @@ static int dmcinfo_proc_show(struct seq_file *m, void *v)
"\n"
"devfreq/dmc: Enable\n"
"governor: %s\n"
"cur_freq: %s\n"
,
governor,
cur_freq
);
"cur_freq: %s\n",
governor, cur_freq);
seq_printf(m,
"NOTE:\n"
"more information about dmc can get from /sys/class/devfreq/dmc.\n"
);
"more information about dmc can get from /sys/class/devfreq/dmc.\n");
}
return 0;
@@ -301,11 +329,11 @@ static int dmcinfo_proc_open(struct inode *inode, struct file *file)
return single_open(file, dmcinfo_proc_show, NULL);
}
static const struct file_operations dmcinfo_proc_fops = {
.open = dmcinfo_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
static const struct proc_ops dmcinfo_proc_fops = {
.proc_open = dmcinfo_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
static int proc_dmcinfo_init(void)
@@ -340,19 +368,15 @@ static int powersave_proc_show(struct seq_file *m, void *v)
}
p_power = (struct power_save_info *)dmcdbg_data.share_memory;
seq_printf(m,
"low power information:\n"
"\n"
"[number]name: value\n"
);
seq_printf(m, "low power information:\n"
"\n"
"[number]name: value\n");
p_uint = (unsigned int *)p_power;
for (i = 0; i < ARRAY_SIZE(power_save_msg); i++)
seq_printf(m,
"[%d]%s: %d\n"
,
i, power_save_msg[i], *(p_uint + i)
);
"[%d]%s: %d\n",
i, power_save_msg[i], *(p_uint + i));
seq_printf(m,
"\n"
@@ -364,8 +388,7 @@ static int powersave_proc_show(struct seq_file *m, void *v)
"Support for setting multiple parameters at the same time.\n"
"echo number=value,number=value,... > /proc/dmcdbg/powersave\n"
"eg:\n"
" echo 0=1,1=32 > /proc/dmcdbg/powersave\n"
);
" echo 0=1,1=32 > /proc/dmcdbg/powersave\n");
return 0;
}
@@ -463,12 +486,12 @@ err:
return ret;
}
static const struct file_operations powersave_proc_fops = {
.open = powersave_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = powersave_proc_write,
static const struct proc_ops powersave_proc_fops = {
.proc_open = powersave_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
.proc_write = powersave_proc_write,
};
static int proc_powersave_init(void)
@@ -502,48 +525,34 @@ static int drvodt_proc_show(struct seq_file *m, void *v)
}
p_drvodt = (struct drv_odt_info *)dmcdbg_data.share_memory;
seq_printf(m,
"drv and odt information:\n"
"\n"
"[number]name: value (ohm)\n"
);
seq_printf(m, "drv and odt information:\n"
"\n"
"[number]name: value (ohm)\n");
p_uint = (unsigned int *)p_drvodt;
for (i = 0; i < ARRAY_SIZE(drv_odt_msg); i++) {
if (*(p_uint + (i * 3)) == DRV_ODT_UNKNOWN)
seq_printf(m,
"[%2d]%s: NULL (unknown) %c\n"
,
"[%2d]%s: NULL (unknown) %c\n",
i, drv_odt_msg[i],
(*(p_uint + (i * 3) + 2) ==
DRV_ODT_SUSPEND_FIX) ? '\0' : '*'
);
(*(p_uint + (i * 3) + 2) == DRV_ODT_SUSPEND_FIX) ? '\0' : '*');
else if (*(p_uint + (i * 3) + 1) == DRV_ODT_UNKNOWN)
seq_printf(m,
"[%2d]%s: %d (unknown) %c\n"
,
"[%2d]%s: %d (unknown) %c\n",
i, drv_odt_msg[i], *(p_uint + (i * 3)),
(*(p_uint + (i * 3) + 2) ==
DRV_ODT_SUSPEND_FIX) ? '\0' : '*'
);
(*(p_uint + (i * 3) + 2) == DRV_ODT_SUSPEND_FIX) ? '\0' : '*');
else if (i < (ARRAY_SIZE(drv_odt_msg) - 2))
seq_printf(m,
"[%2d]%s: %d (%d ohm) %c\n"
,
"[%2d]%s: %d (%d ohm) %c\n",
i, drv_odt_msg[i], *(p_uint + (i * 3)),
*(p_uint + (i * 3) + 1),
(*(p_uint + (i * 3) + 2) ==
DRV_ODT_SUSPEND_FIX) ? '\0' : '*'
);
(*(p_uint + (i * 3) + 2) == DRV_ODT_SUSPEND_FIX) ? '\0' : '*');
else
seq_printf(m,
"[%2d]%s: %d (%d %%) %c\n"
,
"[%2d]%s: %d (%d %%) %c\n",
i, drv_odt_msg[i], *(p_uint + (i * 3)),
*(p_uint + (i * 3) + 1),
(*(p_uint + (i * 3) + 2) ==
DRV_ODT_SUSPEND_FIX) ? '\0' : '*'
);
(*(p_uint + (i * 3) + 2) == DRV_ODT_SUSPEND_FIX) ? '\0' : '*');
}
seq_printf(m,
@@ -558,8 +567,7 @@ static int drvodt_proc_show(struct seq_file *m, void *v)
"eg: set soc side ca drv up and down to 20\n"
" echo 6=20,7=20 > /proc/dmcdbg/drvodt\n"
"Note: Please update both up and down at the same time.\n"
" (*) mean unsupported setting value\n"
);
" (*) mean unsupported setting value\n");
return 0;
}
@@ -657,12 +665,12 @@ err:
return ret;
}
static const struct file_operations drvodt_proc_fops = {
.open = drvodt_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = drvodt_proc_write,
static const struct proc_ops drvodt_proc_fops = {
.proc_open = drvodt_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
.proc_write = drvodt_proc_write,
};
static int proc_drvodt_init(void)
@@ -694,28 +702,20 @@ static int skew_proc_show(struct seq_file *m, void *v)
return -EPERM;
}
seq_printf(m,
"de-skew information:\n"
"\n"
"[group_number]name: value\n"
);
seq_printf(m, "de-skew information:\n"
"\n"
"[group_number]name: value\n");
for (group = 0; group < dmcdbg_data.skew_group_num; group++) {
if (dmcdbg_data.skew_group[group].note != NULL)
seq_printf(m,
"%s\n"
,
dmcdbg_data.skew_group[group].note
);
seq_printf(m, "%s\n",
dmcdbg_data.skew_group[group].note);
p_uint = (unsigned int *)dmcdbg_data.skew_group[group].p_skew_info;
for (i = 0; i < dmcdbg_data.skew_group[group].skew_num; i++)
seq_printf(m,
"[%c%d_%d]%s: %d\n"
,
(i < 10) ? ' ' : '\0', group, i,
dmcdbg_data.skew_group[group].p_skew_timing[i],
*(p_uint + i)
);
seq_printf(m, "[%c%d_%d]%s: %d\n",
(i < 10) ? ' ' : '\0', group, i,
dmcdbg_data.skew_group[group].p_skew_timing[i],
*(p_uint + i));
}
seq_printf(m,
@@ -728,8 +728,7 @@ static int skew_proc_show(struct seq_file *m, void *v)
"Support for setting multiple parameters simultaneously.\n"
"echo group_number=value,group_number=value,... > /proc/dmcdbg/deskew\n"
"eg:\n"
" echo 0_1=8,1_2=8 > /proc/dmcdbg/deskew\n"
);
" echo 0_1=8,1_2=8 > /proc/dmcdbg/deskew\n");
return 0;
}
@@ -838,12 +837,12 @@ err:
return ret;
}
static const struct file_operations skew_proc_fops = {
.open = skew_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = skew_proc_write,
static const struct proc_ops skew_proc_fops = {
.proc_open = skew_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
.proc_write = skew_proc_write,
};
static int proc_skew_init(void)
@@ -876,18 +875,13 @@ static int regsinfo_proc_show(struct seq_file *m, void *v)
}
p_regsinfo = (struct registers_info *)dmcdbg_data.share_memory;
seq_printf(m,
"registers base address information:\n"
"\n"
);
seq_printf(m, "registers base address information:\n"
"\n");
for (i = 0; i < p_regsinfo->regs_num; i++) {
seq_printf(m,
"%s=0x%x\n"
,
seq_printf(m, "%s=0x%x\n",
p_regsinfo->regs[i].regs_name,
p_regsinfo->regs[i].regs_addr
);
p_regsinfo->regs[i].regs_addr);
}
return 0;
@@ -898,13 +892,63 @@ static int regsinfo_proc_open(struct inode *inode, struct file *file)
return single_open(file, regsinfo_proc_show, NULL);
}
static const struct file_operations regsinfo_proc_fops = {
.open = regsinfo_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
static const struct proc_ops regsinfo_proc_fops = {
.proc_open = regsinfo_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
static int rk_dmcdbg_sip_smc_match_ver(struct platform_device *pdev,
u32 match_ver)
{
struct arm_smccc_res res;
/* check ddr_debug_func version */
res = sip_smc_dram(0, DDRDBG_FUNC_GET_VERSION,
ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
dev_notice(&pdev->dev, "current ATF ddr_debug_func version 0x%lx.\n",
res.a1);
/*
* [15:8] major version, [7:0] minor version
* major version must match both kernel dmcdbg and ATF ddr_debug_func.
*/
if (res.a0 || res.a1 < match_ver || ((res.a1 & 0xff00) != (match_ver & 0xff00))) {
dev_err(&pdev->dev,
"version invalid, need update to 0x%x or newer, the major version unmatch!\n",
match_ver);
return -ENXIO;
}
return 0;
}
static int proc_dmcdbg_init(struct platform_device *pdev)
{
struct arm_smccc_res res;
/* request share memory for pass parameter */
res = sip_smc_request_share_mem(DMCDBG_PAGE_NUMS,
SHARE_PAGE_TYPE_DDRDBG);
if (res.a0 != 0) {
dev_err(&pdev->dev, "request share mem error!\n");
return -ENOMEM;
}
dmcdbg_data.share_memory = (void __iomem *)res.a1;
dmcdbg_data.inited_flag = 1;
/* create parent dir in /proc */
proc_dmcdbg_dir = proc_mkdir(PROC_DMCDBG_DIR_NAME, NULL);
if (!proc_dmcdbg_dir) {
dev_err(&pdev->dev, "create proc dir error!\n");
return -ENOENT;
}
return 0;
}
static int proc_regsinfo_init(void)
{
/* create dmcinfo file */
@@ -965,46 +1009,41 @@ static void rv1126_get_skew_parameter(void)
dmcdbg_data.skew_group[4].note = "(cs1_b_skew)";
}
static __maybe_unused int px30_dmcdbg_init(struct platform_device *pdev,
struct rockchip_dmcdbg *dmcdbg)
{
u32 version = 0x101;
int ret;
ret = rk_dmcdbg_sip_smc_match_ver(pdev, version);
if (ret)
return ret;
ret = proc_dmcdbg_init(pdev);
if (ret)
return ret;
proc_dmcinfo_init();
return 0;
}
static __maybe_unused int rv1126_dmcdbg_init(struct platform_device *pdev,
struct rockchip_dmcdbg *dmcdbg)
{
struct arm_smccc_res res;
u32 version = 0x102;
int ret;
/* check ddr_debug_func version */
res = sip_smc_dram(0, DDRDBG_FUNC_GET_VERSION,
ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
dev_notice(&pdev->dev, "current ATF ddr_debug_func version 0x%lx.\n",
res.a1);
/*
* [15:8] major version, [7:0] minor version
* major version must match both kernel dmcdbg and ATF ddr_debug_func.
*/
if (res.a0 || res.a1 < 0x101 || ((res.a1 & 0xff00) != 0x100)) {
dev_err(&pdev->dev,
"version invalid,need update,the major version unmatch!\n");
return -ENXIO;
}
ret = rk_dmcdbg_sip_smc_match_ver(pdev, version);
if (ret)
return ret;
/* request share memory for pass parameter */
res = sip_smc_request_share_mem(DMCDBG_PAGE_NUMS,
SHARE_PAGE_TYPE_DDRDBG);
if (res.a0 != 0) {
dev_err(&pdev->dev, "request share mem error\n");
return -ENOMEM;
}
dmcdbg_data.share_memory = (void __iomem *)res.a1;
dmcdbg_data.inited_flag = 1;
ret = proc_dmcdbg_init(pdev);
if (ret)
return ret;
rv1126_get_skew_parameter();
/* create parent dir in /proc */
proc_dmcdbg_dir = proc_mkdir(PROC_DMCDBG_DIR_NAME, NULL);
if (!proc_dmcdbg_dir) {
dev_err(&pdev->dev, "create proc dir error!");
return -ENOENT;
}
proc_dmcinfo_init();
proc_powersave_init();
proc_drvodt_init();
@@ -1014,7 +1053,21 @@ static __maybe_unused int rv1126_dmcdbg_init(struct platform_device *pdev,
}
static const struct of_device_id rockchip_dmcdbg_of_match[] = {
{ .compatible = "rockchip,rv1126-dmcdbg", .data = rv1126_dmcdbg_init},
#ifdef CONFIG_CPU_PX30
{ .compatible = "rockchip,px30-dmcdbg", .data = px30_dmcdbg_init },
#endif
#ifdef CONFIG_CPU_RV1126
{ .compatible = "rockchip,rv1126-dmcdbg", .data = rv1126_dmcdbg_init },
#endif
#ifdef CONFIG_CPU_RK3568
{ .compatible = "rockchip,rk3568-dmcdbg", .data = px30_dmcdbg_init },
#endif
#ifdef CONFIG_CPU_RK3576
{ .compatible = "rockchip,rk3576-dmcdbg", .data = px30_dmcdbg_init },
#endif
#ifdef CONFIG_CPU_RK3588
{ .compatible = "rockchip,rk3588-dmcdbg", .data = px30_dmcdbg_init },
#endif
{ },
};
MODULE_DEVICE_TABLE(of, rockchip_dmcdbg_of_match);
@@ -1023,7 +1076,6 @@ static int rockchip_dmcdbg_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rockchip_dmcdbg *data;
const struct of_device_id *match;
int (*init)(struct platform_device *pdev,
struct rockchip_dmcdbg *data);
int ret = 0;
@@ -1035,20 +1087,28 @@ static int rockchip_dmcdbg_probe(struct platform_device *pdev)
data->dev = dev;
/* match soc chip init */
match = of_match_node(rockchip_dmcdbg_of_match, pdev->dev.of_node);
if (match) {
init = match->data;
if (init) {
if (init(pdev, data))
return -EINVAL;
}
init = device_get_match_data(&pdev->dev);
if (init) {
if (init(pdev, data))
return -EINVAL;
}
return ret;
}
static int rockchip_dmcdbg_remove(struct platform_device *pdev)
{
remove_proc_subtree(PROC_DMCDBG_DIR_NAME, NULL);
dmcdbg_data.inited_flag = 0;
dmcdbg_data.share_memory = NULL;
return 0;
}
static struct platform_driver rockchip_dmcdbg_driver = {
.probe = rockchip_dmcdbg_probe,
.remove = rockchip_dmcdbg_remove,
.driver = {
.name = "rockchip,dmcdbg",
.of_match_table = rockchip_dmcdbg_of_match,