diff --git a/arch/arm/configs/rockchip_linux_defconfig b/arch/arm/configs/rockchip_linux_defconfig index 57e9ca5142ee..3a8b9886c56e 100644 --- a/arch/arm/configs/rockchip_linux_defconfig +++ b/arch/arm/configs/rockchip_linux_defconfig @@ -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 diff --git a/arch/arm/configs/rv1126b-ipc.config b/arch/arm/configs/rv1126b-ipc.config index ccd4e93023f7..c2e72a2f6547 100644 --- a/arch/arm/configs/rv1126b-ipc.config +++ b/arch/arm/configs/rv1126b-ipc.config @@ -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 diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index d966c8675cda..e7ce8f8dfd6c 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -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 diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi index ab9bb9450401..d1fa06bbb912 100644 --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi @@ -283,6 +283,11 @@ }; }; + dmcdbg: dmcdbg { + compatible = "rockchip,rk3568-dmcdbg"; + status = "disabled"; + }; + firmware { scmi: scmi { compatible = "arm,scmi-smc"; diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576.dtsi index b78d1ae11d83..cc384cea8076 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi @@ -1268,6 +1268,11 @@ }; }; + dmcdbg: dmcdbg { + compatible = "rockchip,rk3576-dmcdbg"; + status = "disabled"; + }; + firmware { scmi: scmi { compatible = "arm,scmi-smc"; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23-linux.dts b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23-linux.dts new file mode 100644 index 000000000000..706cf080c9a8 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb-v23-linux.dts @@ -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"; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi index 3561cd1ef646..8e389f8eb6c0 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -2400,6 +2400,11 @@ }; }; + dmcdbg: dmcdbg { + compatible = "rockchip,rk3588-dmcdbg"; + status = "disabled"; + }; + firmware { scmi: scmi { compatible = "arm,scmi-smc"; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts index 0f9d19709076..d7c69c18fb26 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts @@ -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>; }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index 3798515b5019..f6a66bcab364 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -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>; diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index e94724dd2778..6f223ad42580 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -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 diff --git a/drivers/clk/rockchip/clk-pvtpll.c b/drivers/clk/rockchip/clk-pvtpll.c index 8fb1136757e6..22289bf57bac 100644 --- a/drivers/clk/rockchip/clk-pvtpll.c +++ b/drivers/clk/rockchip/clk-pvtpll.c @@ -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, diff --git a/drivers/clk/rockchip/clk-rv1126b.c b/drivers/clk/rockchip/clk-rv1126b.c index dd136c619c43..52554b1cea17 100644 --- a/drivers/clk/rockchip/clk-rv1126b.c +++ b/drivers/clk/rockchip/clk-rv1126b.c @@ -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" }; diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index c37201c4fb78..85f6f5df4f1a 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -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)) { diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index fe1b42e83516..f80644b61b34 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -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) { diff --git a/drivers/media/platform/rockchip/fec/fec_offline.c b/drivers/media/platform/rockchip/fec/fec_offline.c index b0c1f2e96a11..95ef4ef2904b 100644 --- a/drivers/media/platform/rockchip/fec/fec_offline.c +++ b/drivers/media/platform/rockchip/fec/fec_offline.c @@ -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); diff --git a/drivers/media/platform/rockchip/fec/procfs.c b/drivers/media/platform/rockchip/fec/procfs.c index 4038c9f63af0..aabfe8bd9c40 100644 --- a/drivers/media/platform/rockchip/fec/procfs.c +++ b/drivers/media/platform/rockchip/fec/procfs.c @@ -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])); diff --git a/drivers/media/platform/rockchip/fec/regs.h b/drivers/media/platform/rockchip/fec/regs.h index 2ad693db912e..a50f0e4f0b8d 100644 --- a/drivers/media/platform/rockchip/fec/regs.h +++ b/drivers/media/platform/rockchip/fec/regs.h @@ -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) diff --git a/drivers/net/can/rockchip/rk3576_canfd.c b/drivers/net/can/rockchip/rk3576_canfd.c index e1fbbff61a9d..2c0d7f056721 100644 --- a/drivers/net/can/rockchip/rk3576_canfd.c +++ b/drivers/net/can/rockchip/rk3576_canfd.c @@ -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; diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index b8c2f2d15e79..bb40b2d20da5 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -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 diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig index aa94a31a8d5e..97af2f1d9528 100644 --- a/drivers/soc/rockchip/Kconfig +++ b/drivers/soc/rockchip/Kconfig @@ -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 diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile index 4ba238e1563f..efa1809dd949 100644 --- a/drivers/soc/rockchip/Makefile +++ b/drivers/soc/rockchip/Makefile @@ -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 diff --git a/drivers/devfreq/rockchip_dmc_dbg.c b/drivers/soc/rockchip/rockchip_dmc_debug.c similarity index 79% rename from drivers/devfreq/rockchip_dmc_dbg.c rename to drivers/soc/rockchip/rockchip_dmc_debug.c index 80b25e9046d1..64403dc8566b 100644 --- a/drivers/devfreq/rockchip_dmc_dbg.c +++ b/drivers/soc/rockchip/rockchip_dmc_debug.c @@ -15,7 +15,7 @@ #include -#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,