From 277f800e19634ace23cbaf44319668e406e278c9 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 20 May 2025 17:20:50 +0800 Subject: [PATCH 01/18] media: rockchip: vicap fixes error port parse of sditf Change-Id: Ie3fbd96be25ae0890b0d7736ae15777029a77f45 Signed-off-by: Zefa Chen --- drivers/media/platform/rockchip/cif/subdev-itf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index a980eb709cb0..35ff3d0bdec6 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -1501,8 +1501,8 @@ static int sditf_fwnode_parse(struct device *dev, struct v4l2_mbus_config *config = &s_asd->mbus; if (vep->base.port != 0) { - dev_err(dev, "sditf has only port 0\n"); - return -EINVAL; + dev_info(dev, "sditf has only parse port 0\n"); + return 0; } if (vep->bus_type == V4L2_MBUS_CSI2_DPHY || From de526eb4129955ab2b8dd7918e31ebf219b39d0e Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Thu, 15 May 2025 19:55:55 +0800 Subject: [PATCH 02/18] media: rockchip: vicap support crop with toisp mode Change-Id: I81457b978527690b7f14b6dbee8de0cedef9b884 Signed-off-by: Zefa Chen --- drivers/media/platform/rockchip/cif/subdev-itf.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 35ff3d0bdec6..5a376277694c 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -201,6 +201,11 @@ static int sditf_get_set_fmt(struct v4l2_subdev *sd, if (!ret) { fmt->format.width = input_sel.r.width; fmt->format.height = input_sel.r.height; + priv->cap_info.offset_x = input_sel.r.left; + priv->cap_info.offset_y = input_sel.r.top; + } else { + priv->cap_info.offset_x = 0; + priv->cap_info .offset_y = 0; } priv->cap_info.width = fmt->format.width; priv->cap_info.height = fmt->format.height; @@ -732,8 +737,8 @@ static int sditf_channel_enable_rv1103b(struct sditf_priv *priv, int user) unsigned int ctrl_ch1 = 0; unsigned int ctrl_ch2 = 0; unsigned int int_en = 0; - unsigned int offset_x = 0; - unsigned int offset_y = 0; + unsigned int offset_x = priv->cap_info.offset_x; + unsigned int offset_y = priv->cap_info.offset_y; unsigned int width = priv->cap_info.width; unsigned int height = priv->cap_info.height; int csi_idx = cif_dev->csi_host_idx; From e1ef5002b69a534e4096b076198f7280d47497e9 Mon Sep 17 00:00:00 2001 From: Lin Jianhua Date: Fri, 16 May 2025 14:42:19 +0800 Subject: [PATCH 03/18] arm64: dts: rockchip: rv1126b-evb4: enable sdmmc\gmac\can\sound\rtc\fspi Change-Id: I975ad645df4b2360ac2205aba67a54e51ab2a3df Signed-off-by: Lin Jianhua --- .../boot/dts/rockchip/rv1126b-evb4-v10.dts | 153 +++++++++++++++++- 1 file changed, 145 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts index fbd9355a5f48..89b954a5b801 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts @@ -26,14 +26,6 @@ reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; }; - vcc_mipi: vcc-mipi { - compatible = "regulator-fixed"; - regulator-name = "vcc_mipi"; - gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; - enable-active-high; - regulator-boot-on; - }; - vcc5v0_sys: vcc5v0-sys { compatible = "regulator-fixed"; regulator-name = "vcc5v0_sys"; @@ -71,6 +63,39 @@ pinctrl-0 = <&vcc5v0_host_en>; }; + vcc_mipi: vcc-mipi { + compatible = "regulator-fixed"; + regulator-name = "vcc_mipi"; + gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + }; + + vcc_sd: vcc-sd { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-low; + regulator-boot-on; // The legacy U-Boot GPIO driver needs this to set correct SDMMC0_PWREN value + vin-supply = <&vcc12v_dcin>; + }; + + vccio_sd: vccio-sd { + compatible = "regulator-gpio"; + regulator-boot-on; + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_volt>; + gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_sys>; + states = <1800000 0x0 + 3300000 0x1>; + }; + vdd_npu: vdd-npu { compatible = "pwm-regulator"; pwms = <&pwm0_8ch_0 0 25000 1>; @@ -105,10 +130,32 @@ }; }; +&acdcdig_dsm { + status = "okay"; + pa-ctl-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&dsm_aud_rn_pins &dsm_aud_rp_pins>; +}; + +&acodec_sound { + status = "okay"; +}; + +&audio_codec { + status = "okay"; +}; + &backlight { pwms = <&pwm0_8ch_3 0 25000 0>; }; +&can0 { + assigned-clocks = <&cru CLK_CAN0>; + assigned-clock-rates = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&can0m1_pins>; + status = "okay"; +}; + &cpu0 { cpu-supply = <&vdd_cpu>; }; @@ -140,6 +187,25 @@ status = "okay"; }; +&fspi0 { + status = "okay"; + + flash@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <75000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&gmac { + phy-mode = "rmii"; + clock_in_out = "input"; + phy-handle = <&rmii_phy>; + status = "okay"; +}; + &i2c0 { status = "okay"; @@ -267,6 +333,19 @@ }; }; +&mdio { + rmii_phy: ethernet-phy@2 { + compatible = "ethernet-phy-id0680.8101", "ethernet-phy-ieee802.3-c22"; + reg = <2>; + clocks = <&cru CLK_MACPHY>; + clock-frequency = <50000000>; + resets = <&cru SRST_RESETN_MACPHY>; + pinctrl-names = "default"; + pinctrl-0 = <&fephym1_pins>; + phy-is-integrated; + }; +}; + &mipi_dphy { status = "okay"; }; @@ -284,6 +363,13 @@ }; }; + sdmmc { + /omit-if-no-ref/ + sdmmc_volt: sdmmc-volt { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + usb { typec5v_pwren: typec5v-pwren { rockchip,pins = <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; @@ -319,10 +405,61 @@ rknpu-supply = <&vdd_npu>; }; +&rockchip_suspend { + status = "okay"; + + rockchip,sleep-mode-config = < + (0 + | RKPM_SLP_ARMOFF_LOGOFF + | RKPM_SLP_PMU_PMUALIVE_32K + | RKPM_SLP_PMU_DIS_OSC + | RKPM_SLP_32K_EXT + ) + >; + + rockchip,sleep-pin-config = < + (0 + | RKPM_SLEEP_PIN2_EN + ) + (0 + ) + >; +}; + &route_dsi { status = "okay"; }; +&rtc { + rockchip,rtc-suspend-bypass; + status = "okay"; +}; + +&sai2 { + rockchip,sai-rx-route = <1 0 2 3>; + status = "okay"; + /delete-property/ pinctrl-names; + /delete-property/ pinctrl-0; +}; + +&saradc0 { + vref-supply = <&vcc_1v8>; +}; + +&sdmmc0 { + max-frequency = <200000000>; + no-sdio; + no-mmc; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + &sdmmc1 { bus-width = <4>; cap-sd-highspeed; From f7a914c61a78e0022af63525e200c6f3670bb8e5 Mon Sep 17 00:00:00 2001 From: Lin Jianhua Date: Sat, 17 May 2025 16:46:41 +0800 Subject: [PATCH 04/18] arm64: dts: rockchip: rv1126b-evb4: add dsmc node Change-Id: If8534687510aaf1e567d32db6ac036286d4184e4 Signed-off-by: Lin Jianhua --- .../boot/dts/rockchip/rv1126b-evb4-v10.dts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts index 89b954a5b801..2a2830ee2914 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts @@ -176,6 +176,36 @@ power-supply = <&vcc_mipi>; }; +&dsmc { + clock-frequency = <100000000>; + status = "disabled"; + slave { + rockchip,dqs-dll = <0x20 0x20 + 0x20 0x20 + 0x20 0x20 + 0x20 0x20>; + rockchip,ranges = <0x0 0x10000000 0x0 0x2000000>; + }; +}; + +&dsmc_slave { + status = "disabled"; + lb-slave { + dsmc_lb_slave0: lb-slave0 { + rockchip,int-en = <0x0>; + status = "okay"; + dsmc_p0_region: region { + dsmc_p0_region0: region0 { + status = "okay"; + }; + dsmc_p0_region3: region3 { + status = "okay"; + }; + }; + }; + }; +}; + &emmc { bus-width = <8>; cap-mmc-highspeed; From 7f54c8f36a2923dd36024cb073392716e950f0d9 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Wed, 26 Feb 2025 20:08:43 +0800 Subject: [PATCH 05/18] media: rockchip: vicap fixes image error of last frame before suspend Signed-off-by: Zefa Chen Change-Id: Ia58c72697d5c895dd23083244ea50871842bea9c --- drivers/media/platform/rockchip/cif/capture.c | 8 +++++++- drivers/media/platform/rockchip/cif/dev.h | 1 + drivers/media/platform/rockchip/cif/subdev-itf.c | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index d84863a17cd0..f385352b66e2 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -9015,6 +9015,7 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id) stream->frame_idx = 0; memset(&stream->sensor_exp_info, 0, sizeof(stream->sensor_exp_info)); stream->frame_loss = 0; + stream->is_pause_stream = false; } int rkcif_sensor_set_power(struct rkcif_stream *stream, int on) @@ -13651,6 +13652,7 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, rkcif_stop_dma_capture(stream); } stream->is_wait_stop_complete = false; + stream->is_pause_stream = true; complete(&stream->stop_complete); } if (stream->cifdev->sensor_state_change && @@ -15023,6 +15025,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) if (stream->is_finish_stop_dma && stream->is_wait_stop_complete) { stream->is_wait_stop_complete = false; + stream->is_pause_stream = true; complete(&stream->stop_complete); } @@ -15168,8 +15171,11 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) } if (stream->to_stop_dma) { ret = rkcif_stop_dma_capture(stream); - if (!ret) + if (!ret) { stream->is_finish_stop_dma = true; + if (stream->is_wait_stop_complete) + stream->is_pause_stream = true; + } } spin_unlock_irqrestore(&stream->vbq_lock, flags); diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 89522611533e..4e453927e537 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -670,6 +670,7 @@ struct rkcif_stream { bool is_wait_single_cap; bool is_m_online_fb_res; bool is_fb_first_frame; + bool is_pause_stream; }; struct rkcif_lvds_subdev { diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 5a376277694c..7e0f5b5e4725 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -1321,7 +1321,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, if (!is_free && (!dbufs->is_switch) && stream->state == RKCIF_STATE_STREAMING) { list_add_tail(&rx_buf->list, &stream->rx_buf_head); rkcif_assign_check_buffer_update_toisp(stream); - if (cif_dev->resume_mode != RKISP_RTT_MODE_ONE_FRAME) { + if (cif_dev->resume_mode != RKISP_RTT_MODE_ONE_FRAME && + (!stream->is_pause_stream)) { if (!stream->dma_en) { stream->to_en_dma = RKCIF_DMAEN_BY_ISP; rkcif_enable_dma_capture(stream, true); From 15708c309d4c568536cdee07bb7ddb04f534ca51 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Wed, 26 Feb 2025 16:30:37 +0800 Subject: [PATCH 06/18] media: rockchip: vicap fixes error of sof intr loss Change-Id: Ifce44e0c14b56dc2d7e131cbb48ceefb4453f99c Signed-off-by: Zefa Chen --- drivers/media/platform/rockchip/cif/capture.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index f385352b66e2..085056f4eca1 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -13061,10 +13061,13 @@ void rkcif_enable_dma_capture(struct rkcif_stream *stream, bool is_only_enable) } else { val |= CSI_DMA_ENABLE_RK3576; uncompact = CSI_WRDDR_TYPE_RAW_UNCOMPACT << 3; - rkcif_write_register(cif_dev, CIF_REG_MIPI_LVDS_INTSTAT, - CSI_START_INTSTAT_RK3576(stream->id)); - rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_INTEN, - CSI_START_INTEN_RK3576(stream->id)); + if (!(rkcif_read_register(cif_dev, CIF_REG_MIPI_LVDS_INTEN) & + CSI_START_INTEN_RK3576(stream->id))) { + rkcif_write_register(cif_dev, CIF_REG_MIPI_LVDS_INTSTAT, + CSI_START_INTSTAT_RK3576(stream->id)); + rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_INTEN, + CSI_START_INTEN_RK3576(stream->id)); + } } if (!stream->is_compact) val |= uncompact; From 77e92452806464dbf781dd55ca71121f24855473 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 18 Mar 2025 20:23:54 +0800 Subject: [PATCH 07/18] media: rockchip: vicap free hdr buf after change to online Signed-off-by: Zefa Chen Change-Id: I334b6d893430ce5cf4371fabf387d3fa0846a5ef --- drivers/media/platform/rockchip/cif/capture.c | 30 ++------------ .../media/platform/rockchip/cif/subdev-itf.c | 40 +++++++++++++++++-- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 085056f4eca1..f5afd3474159 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -11737,27 +11737,6 @@ static void rkcif_store_last_buf_for_online(struct rkcif_stream *stream, buf->dummy.dma_addr); } -static void rkcif_release_unnecessary_buf_for_online(struct rkcif_stream *stream, - struct rkcif_rx_buffer *buf) -{ - struct rkcif_device *dev = stream->cifdev; - struct sditf_priv *priv = dev->sditf[0]; - struct rkcif_rx_buffer *rx_buf = NULL; - unsigned long flags; - int i = 0; - - spin_lock_irqsave(&priv->cif_dev->buffree_lock, flags); - for (i = 0; i < priv->buf_num; i++) { - rx_buf = &stream->rx_buf[i]; - if (rx_buf && (!rx_buf->dummy.is_free) && rx_buf != buf) { - list_add_tail(&rx_buf->list_free, &priv->buf_free_list); - stream->total_buf_num--; - } - } - spin_unlock_irqrestore(&priv->cif_dev->buffree_lock, flags); - schedule_work(&priv->buffree_work.work); -} - static void rkcif_line_wake_up_rdbk(struct rkcif_stream *stream, int mipi_id) { u32 mode; @@ -11820,7 +11799,6 @@ static void rkcif_line_wake_up_rdbk(struct rkcif_stream *stream, int mipi_id) stream->cur_stream_mode &= ~RKCIF_STREAM_MODE_TOISP_RDBK; stream->cur_stream_mode |= RKCIF_STREAM_MODE_TOISP; stream->cifdev->wait_line = 0; - stream->is_line_wake_up = false; v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev, "stream[%d] frame_idx %d, last_rx_buf_idx %d cur dma buf %x, change to online\n", stream->id, stream->frame_idx, stream->last_rx_buf_idx, @@ -15127,11 +15105,9 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) rkcif_modify_frame_skip_config(stream); if (stream->is_change_toisp) { stream->is_change_toisp = false; - if ((cif_dev->hdr.hdr_mode == HDR_X2 && stream->id != 1) || - (cif_dev->hdr.hdr_mode == HDR_X3 && stream->id != 2)) - rkcif_release_unnecessary_buf_for_online(stream, - stream->curr_buf_toisp); - else + if (cif_dev->hdr.hdr_mode == NO_HDR || + (cif_dev->hdr.hdr_mode == HDR_X2 && stream->id == 1) || + (cif_dev->hdr.hdr_mode == HDR_X3 && stream->id == 2)) sditf_change_to_online(cif_dev->sditf[0]); rkcif_modify_line_int(stream, false); stream->is_line_inten = false; diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 7e0f5b5e4725..2f3e8c902010 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -1021,10 +1021,36 @@ static void sditf_channel_disable_rv1103b(struct sditf_priv *priv, int user) rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CH2_CTRL, ~ctrl_val); } +static void rkcif_release_unnecessary_buf_for_online(struct rkcif_stream *stream, + struct rkcif_rx_buffer *buf) +{ + struct rkcif_device *dev = stream->cifdev; + struct sditf_priv *priv = dev->sditf[0]; + struct rkcif_rx_buffer *rx_buf = NULL; + unsigned long flags; + int i = 0; + + if (!buf) + buf = stream->last_buf_toisp; + spin_lock_irqsave(&priv->cif_dev->buffree_lock, flags); + for (i = 0; i < stream->rx_buf_num; i++) { + rx_buf = &stream->rx_buf[i]; + if (rx_buf && (!rx_buf->dummy.is_free) && rx_buf != buf) { + list_add_tail(&rx_buf->list_free, &priv->buf_free_list); + stream->total_buf_num--; + atomic_dec(&stream->buf_cnt); + } + } + spin_unlock_irqrestore(&priv->cif_dev->buffree_lock, flags); + schedule_work(&priv->buffree_work.work); +} + void sditf_change_to_online(struct sditf_priv *priv) { struct rkcif_device *cif_dev = priv->cif_dev; struct rkcif_stream *cur_stream = NULL; + int i = 0; + int stream_cnt = 0; priv->mode = priv->mode_src; if (priv->mode.rdbk_mode != RKISP_VICAP_ONLINE_UNITE && @@ -1032,18 +1058,21 @@ void sditf_change_to_online(struct sditf_priv *priv) sditf_enable_immediately(priv); if (cif_dev->is_thunderboot) { - if (priv->hdr_cfg.hdr_mode == NO_HDR) { - cur_stream = &cif_dev->stream[0]; - cif_dev->stream[0].is_line_wake_up = false; - } else if (priv->hdr_cfg.hdr_mode == HDR_X2) { + if (priv->hdr_cfg.hdr_mode == HDR_X2) { cur_stream = &cif_dev->stream[1]; cif_dev->stream[0].is_line_wake_up = false; cif_dev->stream[1].is_line_wake_up = false; + stream_cnt = 1; } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { cur_stream = &cif_dev->stream[2]; cif_dev->stream[0].is_line_wake_up = false; cif_dev->stream[1].is_line_wake_up = false; cif_dev->stream[2].is_line_wake_up = false; + stream_cnt = 2; + } else { + cur_stream = &cif_dev->stream[0]; + cif_dev->stream[0].is_line_wake_up = false; + stream_cnt = 0; } if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE) @@ -1057,6 +1086,9 @@ void sditf_change_to_online(struct sditf_priv *priv) if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE) rkcif_reinit_right_half_config(cur_stream); + for (i = 0; i < stream_cnt; i++) + rkcif_release_unnecessary_buf_for_online(&cif_dev->stream[i], + cif_dev->stream[i].curr_buf_toisp); } } From f3ae0fd773b143ff879974bb9737e63298279548 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Thu, 24 Apr 2025 19:46:46 +0800 Subject: [PATCH 08/18] media: rockchip: vicap add soft reset before start stream Change-Id: I29153568a978b2d5443568f52a7e3eb841575828 Signed-off-by: Zefa Chen --- drivers/media/platform/rockchip/cif/capture.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index f5afd3474159..7bf312c49ca1 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -4822,6 +4822,7 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, CSI_ALL_ERROR_INTEN_V1); + rkcif_do_soft_reset(dev); } #if IS_ENABLED(CONFIG_CPU_RV1106) if (channel->id == 1) @@ -5094,6 +5095,7 @@ static int rkcif_csi_channel_set_rv1126b(struct rkcif_stream *stream, rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, CSI_ALL_ERROR_INTEN_V1); + rkcif_do_soft_reset(dev); } if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE && From bcf0549c76a07e87eeca7f0da598b1afa7c9698c Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Wed, 21 May 2025 11:48:40 +0800 Subject: [PATCH 09/18] arm64: dts: rockchip: rk3588: Adjust the HDMITX1 DDC M0 IO driver strength The maximum drive strength level of vccio3 is 3, so the drive strength level configuration of DDC SCL is 3. Fixes: 3690970c8126 ("arm64: dts: rockchip: rk3588: Adjust the HDMI DDC IO driver strength") Change-Id: I72ed9dd669d2ef7e7fe406977d8c42e226323c99 Signed-off-by: Algea Cao --- arch/arm64/boot/dts/rockchip/rk3588-vccio3-pinctrl.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vccio3-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vccio3-pinctrl.dtsi index d1a1f2662134..137f65659038 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vccio3-pinctrl.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vccio3-pinctrl.dtsi @@ -160,14 +160,14 @@ hdmim0_tx1_scl: hdmim0-tx1-scl { rockchip,pins = /* hdmim0_tx1_scl */ - <2 RK_PB5 4 &pcfg_pull_none>; + <2 RK_PB5 4 &pcfg_pull_none_drv_level_3_smt>; }; /omit-if-no-ref/ hdmim0_tx1_sda: hdmim0-tx1-sda { rockchip,pins = /* hdmim0_tx1_sda */ - <2 RK_PB4 4 &pcfg_pull_none>; + <2 RK_PB4 4 &pcfg_pull_none_drv_level_1_smt>; }; }; From 244733786c8751726aa2e50f835b2d9e9c3993b3 Mon Sep 17 00:00:00 2001 From: Ye Zhang Date: Fri, 23 May 2025 09:34:47 +0800 Subject: [PATCH 10/18] arm64: dts: rockchip: rv1126b-pinctrl: update i2c config Signed-off-by: Ye Zhang Change-Id: I22e23961605faadc2727c7dbc3521de7f50d5c00 --- .../boot/dts/rockchip/rv1126b-pinctrl.dtsi | 84 +++++++++---------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi index 9f3559f96edd..a20a1987dac4 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi @@ -557,18 +557,18 @@ i2c0m0_pins: i2c0m0-pins { rockchip,pins = /* i2c0_scl_m0 */ - <0 RK_PC2 4 &pcfg_pull_none>, + <0 RK_PC2 4 &pcfg_pull_none_smt>, /* i2c0_sda_m0 */ - <0 RK_PC3 4 &pcfg_pull_none>; + <0 RK_PC3 4 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c0m1_pins: i2c0m1-pins { rockchip,pins = /* i2c0_scl_m1 */ - <2 RK_PA1 3 &pcfg_pull_none>, + <2 RK_PA1 3 &pcfg_pull_none_smt>, /* i2c0_sda_m1 */ - <2 RK_PA0 3 &pcfg_pull_none>; + <2 RK_PA0 3 &pcfg_pull_none_smt>; }; }; @@ -577,36 +577,36 @@ i2c1m0_pins: i2c1m0-pins { rockchip,pins = /* i2c1_scl_m0 */ - <0 RK_PB3 3 &pcfg_pull_none>, + <0 RK_PB3 3 &pcfg_pull_none_smt>, /* i2c1_sda_m0 */ - <0 RK_PB4 3 &pcfg_pull_none>; + <0 RK_PB4 3 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c1m1_pins: i2c1m1-pins { rockchip,pins = /* i2c1_scl_m1 */ - <3 RK_PA2 2 &pcfg_pull_none>, + <3 RK_PA2 2 &pcfg_pull_none_smt>, /* i2c1_sda_m1 */ - <3 RK_PA3 2 &pcfg_pull_none>; + <3 RK_PA3 2 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c1m2_pins: i2c1m2-pins { rockchip,pins = /* i2c1_scl_m2 */ - <4 RK_PA1 6 &pcfg_pull_none>, + <4 RK_PA1 6 &pcfg_pull_none_smt>, /* i2c1_sda_m2 */ - <4 RK_PA0 6 &pcfg_pull_none>; + <4 RK_PA0 6 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c1m3_pins: i2c1m3-pins { rockchip,pins = /* i2c1_scl_m3 */ - <7 RK_PB0 5 &pcfg_pull_none>, + <7 RK_PB0 5 &pcfg_pull_none_smt>, /* i2c1_sda_m3 */ - <7 RK_PB1 5 &pcfg_pull_none>; + <7 RK_PB1 5 &pcfg_pull_none_smt>; }; }; @@ -615,27 +615,27 @@ i2c2m0_pins: i2c2m0-pins { rockchip,pins = /* i2c2_scl_m0 */ - <0 RK_PD0 1 &pcfg_pull_none>, + <0 RK_PD0 1 &pcfg_pull_none_smt>, /* i2c2_sda_m0 */ - <0 RK_PD1 1 &pcfg_pull_none>; + <0 RK_PD1 1 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c2m1_pins: i2c2m1-pins { rockchip,pins = /* i2c2_scl_m1 */ - <5 RK_PD4 6 &pcfg_pull_none>, + <5 RK_PD4 6 &pcfg_pull_none_smt>, /* i2c2_sda_m1 */ - <5 RK_PD5 6 &pcfg_pull_none>; + <5 RK_PD5 6 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c2m2_pins: i2c2m2-pins { rockchip,pins = /* i2c2_scl_m2 */ - <6 RK_PC0 7 &pcfg_pull_none>, + <6 RK_PC0 7 &pcfg_pull_none_smt>, /* i2c2_sda_m2 */ - <6 RK_PC3 7 &pcfg_pull_none>; + <6 RK_PC3 7 &pcfg_pull_none_smt>; }; }; @@ -644,36 +644,36 @@ i2c3m0_pins: i2c3m0-pins { rockchip,pins = /* i2c3_scl_m0 */ - <0 RK_PC0 1 &pcfg_pull_none>, + <0 RK_PC0 1 &pcfg_pull_none_smt>, /* i2c3_sda_m0 */ - <0 RK_PC1 1 &pcfg_pull_none>; + <0 RK_PC1 1 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c3m1_pins: i2c3m1-pins { rockchip,pins = /* i2c3_scl_m1 */ - <4 RK_PA4 6 &pcfg_pull_none>, + <4 RK_PA4 6 &pcfg_pull_none_smt>, /* i2c3_sda_m1 */ - <4 RK_PA5 6 &pcfg_pull_none>; + <4 RK_PA5 6 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c3m2_pins: i2c3m2-pins { rockchip,pins = /* i2c3_scl_m2 */ - <5 RK_PD0 6 &pcfg_pull_none>, + <5 RK_PD0 6 &pcfg_pull_none_smt>, /* i2c3_sda_m2 */ - <5 RK_PD1 6 &pcfg_pull_none>; + <5 RK_PD1 6 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c3m3_pins: i2c3m3-pins { rockchip,pins = /* i2c3_scl_m3 */ - <6 RK_PA0 7 &pcfg_pull_none>, + <6 RK_PA0 7 &pcfg_pull_none_smt>, /* i2c3_sda_m3 */ - <6 RK_PA1 7 &pcfg_pull_none>; + <6 RK_PA1 7 &pcfg_pull_none_smt>; }; }; @@ -682,36 +682,36 @@ i2c4m0_pins: i2c4m0-pins { rockchip,pins = /* i2c4_scl_m0 */ - <3 RK_PB4 5 &pcfg_pull_none>, + <3 RK_PB4 5 &pcfg_pull_none_smt>, /* i2c4_sda_m0 */ - <3 RK_PB5 5 &pcfg_pull_none>; + <3 RK_PB5 5 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c4m1_pins: i2c4m1-pins { rockchip,pins = /* i2c4_scl_m1 */ - <6 RK_PA2 7 &pcfg_pull_none>, + <6 RK_PA2 7 &pcfg_pull_none_smt>, /* i2c4_sda_m1 */ - <6 RK_PA3 7 &pcfg_pull_none>; + <6 RK_PA3 7 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c4m2_pins: i2c4m2-pins { rockchip,pins = /* i2c4_scl_m2 */ - <4 RK_PA7 6 &pcfg_pull_none>, + <4 RK_PA7 6 &pcfg_pull_none_smt>, /* i2c4_sda_m2 */ - <4 RK_PA6 6 &pcfg_pull_none>; + <4 RK_PA6 6 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c4m3_pins: i2c4m3-pins { rockchip,pins = /* i2c4_scl_m3 */ - <7 RK_PA1 2 &pcfg_pull_none>, + <7 RK_PA1 2 &pcfg_pull_none_smt>, /* i2c4_sda_m3 */ - <7 RK_PA4 2 &pcfg_pull_none>; + <7 RK_PA4 2 &pcfg_pull_none_smt>; }; }; @@ -720,36 +720,36 @@ i2c5m0_pins: i2c5m0-pins { rockchip,pins = /* i2c5_scl_m0 */ - <0 RK_PC4 4 &pcfg_pull_none>, + <0 RK_PC4 4 &pcfg_pull_none_smt>, /* i2c5_sda_m0 */ - <0 RK_PC5 4 &pcfg_pull_none>; + <0 RK_PC5 4 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c5m1_pins: i2c5m1-pins { rockchip,pins = /* i2c5_scl_m1 */ - <3 RK_PB6 5 &pcfg_pull_none>, + <3 RK_PB6 5 &pcfg_pull_none_smt>, /* i2c5_sda_m1 */ - <3 RK_PB7 5 &pcfg_pull_none>; + <3 RK_PB7 5 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c5m2_pins: i2c5m2-pins { rockchip,pins = /* i2c5_scl_m2 */ - <5 RK_PA1 2 &pcfg_pull_none>, + <5 RK_PA1 2 &pcfg_pull_none_smt>, /* i2c5_sda_m2 */ - <5 RK_PA7 6 &pcfg_pull_none>; + <5 RK_PA7 6 &pcfg_pull_none_smt>; }; /omit-if-no-ref/ i2c5m3_pins: i2c5m3-pins { rockchip,pins = /* i2c5_scl_m3 */ - <6 RK_PA4 7 &pcfg_pull_none>, + <6 RK_PA4 7 &pcfg_pull_none_smt>, /* i2c5_sda_m3 */ - <6 RK_PA5 7 &pcfg_pull_none>; + <6 RK_PA5 7 &pcfg_pull_none_smt>; }; }; From 89b28a5b1e0ae3ac139bf226d160dbf942572b8e Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Thu, 22 May 2025 15:39:16 +0800 Subject: [PATCH 11/18] media: rockchip: isp: support wrap stream latter for isp35 Change-Id: I6758d25d980884b16fc7df5b7b75b7e32016119d Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/capture_v35.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/platform/rockchip/isp/capture_v35.c b/drivers/media/platform/rockchip/isp/capture_v35.c index b50372f90116..232cc1b797dd 100644 --- a/drivers/media/platform/rockchip/isp/capture_v35.c +++ b/drivers/media/platform/rockchip/isp/capture_v35.c @@ -530,6 +530,11 @@ static int mp_config_mi(struct rkisp_stream *stream) if (dev->cap_dev.wrap_line) { height = dev->cap_dev.wrap_line; rkisp_unite_clear_bits(dev, ISP32_MI_WR_WRAP_CTRL, BIT(0), false); + + val = ISP33_SW_ISP2ENC_PATH_EN; + if (IS_HDR_RDBK(dev->hdr.op_mode)) + val |= ISP33_PP_ENC_PIPE_EN; + rkisp_unite_set_bits(dev, CTRL_SWS_CFG, 0, val, false); } val = out_fmt->plane_fmt[0].bytesperline; if (fmt->fmt_type != FMT_TILE) From 2f9efcb0d95be0079a7347136bd2fd0e04e1713b Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 22 May 2025 10:12:52 +0800 Subject: [PATCH 12/18] cpufreq: rockchip: Add opp data for rk3576s Change-Id: I45021b6dc0226ec75ef8ec713406ee7c460a98cc Signed-off-by: Finley Xiao --- drivers/cpufreq/rockchip-cpufreq.c | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index 9e7566ea5b35..f5e26517c5a2 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -189,6 +189,58 @@ out: return ret; } +static int rk3576_cpu_get_soc_info(struct device *dev, struct device_node *np, + int *bin, int *process) +{ + int ret = 0; + u8 spec = 0, test_version = 0; + + if (!bin) + return 0; + + if (of_property_match_string(np, "nvmem-cell-names", + "specification_serial_number") >= 0) { + ret = rockchip_nvmem_cell_read_u8(np, + "specification_serial_number", + &spec); + if (ret) { + dev_err(dev, + "Failed to get specification_serial_number\n"); + return ret; + } + + } + if (of_property_match_string(np, "nvmem-cell-names", "test_version") >= 0) { + ret = rockchip_nvmem_cell_read_u8(np, "test_version", &test_version); + if (ret) { + dev_err(dev, "Failed to get test_version\n"); + return ret; + } + } + /* RK3576M */ + if (spec == 0xd) { + *bin = 1; + /* RK3576J */ + } else if (spec == 0xa) { + *bin = 2; + /* RK3576S */ + } else if (spec == 0x13) { + if (test_version == 0) { + *bin = 3; + } else { + *bin = 0; + dev_info(dev, "bin=%d (3)\n", *bin); + return 0; + } + } + + if (*bin < 0) + *bin = 0; + dev_info(dev, "bin=%d\n", *bin); + + return ret; +} + static int rk3576_cpu_set_read_margin(struct device *dev, struct rockchip_opp_info *opp_info, u32 rm) @@ -416,6 +468,7 @@ static const struct rockchip_opp_data rk3588_cpu_opp_data = { }; static const struct rockchip_opp_data rk3576_cpu_opp_data = { + .get_soc_info = rk3576_cpu_get_soc_info, .set_read_margin = rk3576_cpu_set_read_margin, .set_soc_info = rockchip_opp_set_low_length, .config_regulators = cpu_opp_config_regulators, @@ -450,6 +503,10 @@ static const struct of_device_id rockchip_cpufreq_of_match[] = { .compatible = "rockchip,rk3576", .data = (void *)&rk3576_cpu_opp_data, }, + { + .compatible = "rockchip,rk3576s", + .data = (void *)&rk3576_cpu_opp_data, + }, { .compatible = "rockchip,rk3588", .data = (void *)&rk3588_cpu_opp_data, From cf88c44b8dab3cb3f45a934c1e2eaffb35fc9c83 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 22 May 2025 10:15:38 +0800 Subject: [PATCH 13/18] MALI: bifrost: Add opp data for rk3576s Change-Id: I9eb6f08b7195384603018ddee14afb0bf80cce26 Signed-off-by: Finley Xiao --- .../platform/rk/mali_kbase_config_rk.c | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c index baec96532353..0b8a204b9828 100755 --- a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c +++ b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c @@ -508,6 +508,58 @@ static void kbase_platform_rk_remove_sysfs_files(struct device *dev) device_remove_file(dev, &dev_attr_utilisation); } +static int rk3576_gpu_get_soc_info(struct device *dev, struct device_node *np, + int *bin, int *process) +{ + int ret = 0; + u8 spec = 0, test_version = 0; + + if (!bin) + return 0; + + if (of_property_match_string(np, "nvmem-cell-names", + "specification_serial_number") >= 0) { + ret = rockchip_nvmem_cell_read_u8(np, + "specification_serial_number", + &spec); + if (ret) { + dev_err(dev, + "Failed to get specification_serial_number\n"); + return ret; + } + + } + if (of_property_match_string(np, "nvmem-cell-names", "test_version") >= 0) { + ret = rockchip_nvmem_cell_read_u8(np, "test_version", &test_version); + if (ret) { + dev_err(dev, "Failed to get test_version\n"); + return ret; + } + } + /* RK3576M */ + if (spec == 0xd) { + *bin = 1; + /* RK3576J */ + } else if (spec == 0xa) { + *bin = 2; + /* RK3576S */ + } else if (spec == 0x13) { + if (test_version == 0) { + *bin = 3; + } else { + *bin = 0; + dev_info(dev, "bin=%d (3)\n", *bin); + return 0; + } + } + + if (*bin < 0) + *bin = 0; + dev_info(dev, "bin=%d\n", *bin); + + return ret; +} + static int rk3576_gpu_set_read_margin(struct device *dev, struct rockchip_opp_info *opp_info, u32 rm) @@ -648,6 +700,7 @@ static int gpu_opp_config_clks(struct device *dev, struct opp_table *opp_table, } static const struct rockchip_opp_data rk3576_gpu_opp_data = { + .get_soc_info = rk3576_gpu_get_soc_info, .set_read_margin = rk3576_gpu_set_read_margin, .set_soc_info = rockchip_opp_set_low_length, .config_regulators = gpu_opp_config_regulators, @@ -671,6 +724,10 @@ static const struct of_device_id rockchip_mali_of_match[] = { .compatible = "rockchip,rk3576", .data = (void *)&rk3576_gpu_opp_data, }, + { + .compatible = "rockchip,rk3576s", + .data = (void *)&rk3576_gpu_opp_data, + }, { .compatible = "rockchip,rk3588", .data = (void *)&rk3588_gpu_opp_data, From e0e9133893dd338dcbfcbd76c70f415a75588623 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 22 May 2025 15:28:13 +0800 Subject: [PATCH 14/18] driver: rknpu: Add opp data for rk3576s Change-Id: Ifd41681600eb672f1addfd6641b7e3e3a0d72f8b Signed-off-by: Finley Xiao --- drivers/rknpu/rknpu_devfreq.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/rknpu/rknpu_devfreq.c b/drivers/rknpu/rknpu_devfreq.c index f4b440247a17..3ce543b606e6 100644 --- a/drivers/rknpu/rknpu_devfreq.c +++ b/drivers/rknpu/rknpu_devfreq.c @@ -273,6 +273,10 @@ static const struct of_device_id rockchip_npu_of_match[] = { .compatible = "rockchip,rk3576", .data = (void *)&rk3576_npu_opp_data, }, + { + .compatible = "rockchip,rk3576s", + .data = (void *)&rk3576_npu_opp_data, + }, { .compatible = "rockchip,rk3588", .data = (void *)&rk3588_npu_opp_data, From 4f3686ee3ab4742343a43aa30d4ddd1e573919c1 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 22 May 2025 09:41:58 +0800 Subject: [PATCH 15/18] arm64: dts: rockchip: rk3576: Add customer demand nvmem cell for opp table Change-Id: I1e846b30238e0841b18679d60029e51123f68687 Signed-off-by: Finley Xiao --- arch/arm64/boot/dts/rockchip/rk3576.dtsi | 28 +++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576.dtsi index cc384cea8076..9ed69e379cb6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi @@ -396,8 +396,10 @@ opp-shared; rockchip,opp-shared-cci; - nvmem-cells = <&cpul_leakage>, <&cpul_opp_info>, <&specification_serial_number>; - nvmem-cell-names = "leakage", "opp-info", "specification_serial_number"; + nvmem-cells = <&cpul_leakage>, <&cpul_opp_info>, + <&specification_serial_number>, <&test_version>; + nvmem-cell-names = "leakage", "opp-info", + "specification_serial_number", "test_version"; rockchip,supported-hw; rockchip,pvtm-hw = <0x06>; @@ -660,8 +662,10 @@ opp-shared; rockchip,cpu-freq-percent = <90>; - nvmem-cells = <&cpub_leakage>, <&cpub_opp_info>, <&specification_serial_number>; - nvmem-cell-names = "leakage", "opp-info", "specification_serial_number"; + nvmem-cells = <&cpub_leakage>, <&cpub_opp_info>, + <&specification_serial_number>, <&test_version>; + nvmem-cell-names = "leakage", "opp-info", + "specification_serial_number", "test_version"; rockchip,supported-hw; rockchip,pvtm-hw = <0x06>; @@ -2444,8 +2448,10 @@ npu_opp_table: npu-opp-table { compatible = "operating-points-v2"; - nvmem-cells = <&npu_leakage>, <&npu_opp_info>, <&specification_serial_number>; - nvmem-cell-names = "leakage", "opp-info", "specification_serial_number"; + nvmem-cells = <&npu_leakage>, <&npu_opp_info>, + <&specification_serial_number>, <&test_version>; + nvmem-cell-names = "leakage", "opp-info", + "specification_serial_number", "test_version"; rockchip,supported-hw; rockchip,pvtm-hw = <0x06>; @@ -2690,8 +2696,10 @@ gpu_opp_table: gpu-opp-table { compatible = "operating-points-v2"; - nvmem-cells = <&gpu_leakage>, <&gpu_opp_info>, <&specification_serial_number>; - nvmem-cell-names = "leakage", "opp-info", "specification_serial_number"; + nvmem-cells = <&gpu_leakage>, <&gpu_opp_info>, + <&specification_serial_number>, <&test_version>; + nvmem-cell-names = "leakage", "opp-info", + "specification_serial_number", "test_version"; rockchip,supported-hw; rockchip,pvtm-hw = <0x06>; @@ -4981,6 +4989,10 @@ reg = <0x05 0x1>; bits = <3 3>; }; + test_version: test-version@7 { + reg = <0x7 0x1>; + bits = <0 4>; + }; specification_serial_number: specification-serial-number@8 { reg = <0x08 0x1>; bits = <0 5>; From 859cced7108197ef1da84cc47d81a03d48c96d58 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Tue, 20 May 2025 16:57:45 +0800 Subject: [PATCH 16/18] drm/rockchip: vop2: update cluster fbc xoffset check rule cluster fbc xoffset check size is related to fbc block_w. Signed-off-by: Sandy Huang Change-Id: If091d9d740e22e5f6d192f4085a1b550e826d846 --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 6e31532f8856..89d8efce59be 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -5856,6 +5856,8 @@ static int vop2_cluster_two_win_mode_check(struct drm_plane_state *pstate) struct vop2_win *main_win = vop2_find_win_by_phys_id(vop2, win->phys_id); struct drm_plane_state *main_pstate; int actual_w = drm_rect_width(&pstate->src) >> 16; + struct drm_framebuffer *fb = pstate->fb; + u8 block_w = IS_ROCKCHIP_RFBC_MOD(fb->modifier) ? 64 : fb->modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 ? 32 : 16; int xoffset; if (pstate->fb->modifier == DRM_FORMAT_MOD_LINEAR) @@ -5890,9 +5892,9 @@ static int vop2_cluster_two_win_mode_check(struct drm_plane_state *pstate) xoffset = main_pstate->src.x1 >> 16; actual_w = drm_rect_width(&main_pstate->src) >> 16; - if ((actual_w + xoffset % 16) > 2048) { - DRM_ERROR("%s act_w(%d) + xoffset(%d) / 16 << 2048 in two win mode\n", - main_win->name, actual_w, xoffset); + if ((actual_w + xoffset % block_w) > 2048) { + DRM_ERROR("%s act_w(%d) + xoffset(%d) %% %d > 2048 in two win mode\n", + main_win->name, actual_w, xoffset, block_w); return -EINVAL; } From a8c1e9ec9b90eec8f47ff349e810ce731b8e0c89 Mon Sep 17 00:00:00 2001 From: Shengfei Xu Date: Wed, 16 Apr 2025 16:15:51 +0800 Subject: [PATCH 17/18] =?UTF-8?q?power:=20supply:=20rk817=5Fbattery:=20Sup?= =?UTF-8?q?porting=20battery=20charging=20with=20JEITA=20standards?= =?UTF-8?q?=E2=80=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implementing JEITA charging protocols is critical for enhancing battery safety and prolonging service life. Based on battery specifications and operating temperatures, it is necessary to adjust charging voltages and currents dynamically. Change-Id: Ieab12e792697373a7b50be9e6813061ce85c1232 Signed-off-by: Shengfei Xu --- drivers/power/supply/rk817_battery.c | 424 ++++++++++++++++++++++++++- 1 file changed, 418 insertions(+), 6 deletions(-) diff --git a/drivers/power/supply/rk817_battery.c b/drivers/power/supply/rk817_battery.c index f62f1aae4ba8..51119a1da8fa 100644 --- a/drivers/power/supply/rk817_battery.c +++ b/drivers/power/supply/rk817_battery.c @@ -73,6 +73,14 @@ module_param_named(dbg_level, dbg_enable, int, 0644); #define ADC_TO_CAPACITY_MAH(adc_value, samp_res) \ (adc_value / 1000 * 1720 / 3600 / samp_res) +/* Adjust full capacity to a reduced value */ +#define UPDATE_REDUCE_FCC(fcc) ((fcc) * 995 / 1000) +/* Raise the maximum capacity value */ +#define UPDATE_RAISE_FCC(fcc) ((fcc) * 1005 / 1000) +/* Effective full capacity */ +#define EFFECTIVE_FULL_MIN_CAP(fcc) ((fcc) * 800 / 1000) +#define EFFECTIVE_FULL_MAX_CAP(fcc) ((fcc) * 1200 / 1000) + #define ADC_CALIB_THRESHOLD 4 #define ADC_CALIB_LMT_MIN 3 #define ADC_CALIB_CNT 5 @@ -128,6 +136,40 @@ module_param_named(dbg_level, dbg_enable, int, 0644); /* OCV Table Percentage Accuracy: 5.000% */ #define OCV_TABLE_STEP 5000 +enum ts_fun { + TS_FUN_SOURCE_CURRENT, + TS_FUN_VOLTAGE_INPUT, +}; + +enum tscur_sel { + FLOW_OUT_10uA, + FLOW_OUT_20uA, + FLOW_OUT_30uA, + FLOW_OUT_40uA, +}; + +enum charge_current { + CHRG_CUR_1000MA, + CHRG_CUR_1500MA, + CHRG_CUR_2000MA, + CHRG_CUR_2500MA, + CHRG_CUR_2750MA, + CHRG_CUR_3000MA, + CHRG_CUR_3500MA, + CHRG_CUR_500MA, +}; + +enum charge_voltage { + CHRG_VOL_4100MV, + CHRG_VOL_4150MV, + CHRG_VOL_4200MV, + CHRG_VOL_4250MV, + CHRG_VOL_4300MV, + CHRG_VOL_4350MV, + CHRG_VOL_4400MV, + CHRG_VOL_4450MV, +}; + enum work_mode { MODE_ZERO = 0, MODE_FINISH, @@ -218,8 +260,8 @@ enum rk817_battery_fields { VOL_ADC_B3, VOL_ADC_B2, VOL_ADC_B1, VOL_ADC_B0, VOL_ADC_K3, VOL_ADC_K2, VOL_ADC_K1, VOL_ADC_K0, BAT_EXS, CHG_STS, BAT_OVP_STS, CHRG_IN_CLAMP, - CHIP_NAME_H, CHIP_NAME_L, - PLUG_IN_STS, + CHIP_NAME_H, CHIP_NAME_L, CHRG_CUR_SEL, CHRG_VOL_SEL, + PLUG_IN_STS, BAT_LTS_TS, USB_SYS_EN, F_MAX_FIELDS }; @@ -381,6 +423,10 @@ static const struct reg_field rk817_battery_reg_fields[] = { [VOL_ADC_K2] = REG_FIELD(0xAE, 0, 7), [VOL_ADC_K1] = REG_FIELD(0xAF, 0, 7), [VOL_ADC_K0] = REG_FIELD(0xB0, 0, 7), + [CHRG_CUR_SEL] = REG_FIELD(0xE4, 0, 2), + [CHRG_VOL_SEL] = REG_FIELD(0xE4, 4, 6), + [USB_SYS_EN] = REG_FIELD(0xE6, 6, 6), + [BAT_LTS_TS] = REG_FIELD(0xE9, 0, 7), [BAT_EXS] = REG_FIELD(0xEB, 7, 7), [CHG_STS] = REG_FIELD(0xEB, 4, 6), [BAT_OVP_STS] = REG_FIELD(0xEB, 3, 3), @@ -390,10 +436,24 @@ static const struct reg_field rk817_battery_reg_fields[] = { [PLUG_IN_STS] = REG_FIELD(0xF0, 6, 6), }; +struct temp_chrg_table { + int temp_down; + int temp_up; + int chrg_current; + int chrg_voltage; + int chrg_current_index; + int chrg_voltage_index; +}; + struct battery_platform_data { u32 *ocv_table; u32 ocv_size; - + struct temp_chrg_table *tc_table; + u32 tc_count; + u32 *ntc_table; + u32 ntc_size; + int ntc_degree_from; + u32 ntc_factor; u32 pwroff_vol; u32 monitor_sec; u32 bat_res; @@ -487,7 +547,7 @@ struct rk817_battery_device { bool is_force_calib; int ocv_pre_dsoc; int ocv_new_dsoc; - + int charge_index; int force_pre_dsoc; int force_new_dsoc; @@ -1100,7 +1160,7 @@ static void rk817_bat_update_qmax(struct rk817_battery_device *battery, rk817_bat_field_write(battery, Q_MAX_L1, buf); buf = (cap_adc >> 0) & 0xff; rk817_bat_field_write(battery, Q_MAX_L0, buf); - battery->qmax = capacity; + battery->qmax = capacity; } static int rk817_bat_get_qmax(struct rk817_battery_device *battery) @@ -1305,6 +1365,193 @@ static int rk817_bat_get_charge_status(struct rk817_battery_device *battery) return status; } +static void rk817_bat_update_fcc(struct rk817_battery_device *battery) +{ + static int update_status; + int temp_fcc = 0; + + if (update_status) + return; + + if ((battery->chrg_status == CHRG_OFF) && + (battery->voltage_avg <= battery->pdata->pwroff_vol) && + (battery->rsoc > 5 * 1000) && (battery->dsoc < 1000) && + (battery->temperature >= VIRTUAL_TEMPERATURE)) { + temp_fcc = UPDATE_REDUCE_FCC(battery->fcc); + if (temp_fcc > EFFECTIVE_FULL_MIN_CAP(battery->pdata->design_capacity)) { + DBG("update fcc: design: %d, old: %d, new: %d\n", + battery->pdata->design_capacity, battery->fcc, temp_fcc); + battery->qmax = temp_fcc; + battery->fcc = temp_fcc; + rk817_bat_update_qmax(battery, battery->qmax); + rk817_bat_save_fcc(battery, battery->fcc); + update_status = 1; + } + } + + if ((battery->chrg_status == CHRG_OFF) && + (battery->voltage_avg >= battery->pdata->ocv_table[1]) && + (battery->rsoc < 5 * 1000) && (battery->dsoc < 1000) && + (battery->temperature >= VIRTUAL_TEMPERATURE)) { + temp_fcc = UPDATE_RAISE_FCC(battery->fcc); + if (temp_fcc < EFFECTIVE_FULL_MAX_CAP(battery->pdata->design_capacity)) { + DBG("RAISE fcc: design: %d, old: %d, new: %d\n", + battery->pdata->design_capacity, battery->fcc, temp_fcc); + battery->qmax = temp_fcc; + battery->fcc = temp_fcc; + rk817_bat_update_qmax(battery, battery->qmax); + rk817_bat_save_fcc(battery, battery->fcc); + update_status = 1; + } + } +} + +static void rk817_bat_enable_usb2vsys(struct rk817_battery_device *battery) +{ + DBG("enable usb2vsys!!!\n"); + rk817_bat_field_write(battery, USB_SYS_EN, 1); +} + +static void rk817_bat_disable_usb2vsys(struct rk817_battery_device *battery) +{ + DBG("disable usb2vsys!!!\n"); + rk817_bat_field_write(battery, USB_SYS_EN, 0); +} + +static void rk817_bat_enable_charge(struct rk817_battery_device *battery) +{ + DBG("enable charge by BAT_LTS_TS: 0xFA\n"); + rk817_bat_field_write(battery, BAT_LTS_TS, 0xFA); +} + +static void rk817_bat_disable_charge(struct rk817_battery_device *battery) +{ + DBG("disable charge by BAT_LTS_TS: 0x05\n"); + rk817_bat_field_write(battery, BAT_LTS_TS, 0x05); +} + +static void rk817_bat_init_ts_detect(struct rk817_battery_device *battery) +{ + if (!battery->pdata->ntc_size) + return; + + /* the adc of ts1 controlled bit: enable */ + rk817_bat_field_write(battery, TS_ADC_EN, ENABLE); + /* source current to TS pin */ + rk817_bat_field_write(battery, TS_FUN, TS_FUN_SOURCE_CURRENT); + /* ts pin flow out current in active state */ + rk817_bat_field_write(battery, VOL_ADC_TSCUR_SEL, FLOW_OUT_20uA); + + battery->pdata->ntc_factor = (FLOW_OUT_20uA + 1) * 10; + rk817_bat_enable_charge(battery); +} + +static void rk817_bat_temperature_chrg(struct rk817_battery_device *battery, int temp) +{ + int i, up_temp, down_temp; + int now_temp = temp; + + for (i = 0; i < battery->pdata->tc_count; i++) { + up_temp = battery->pdata->tc_table[i].temp_up; + down_temp = battery->pdata->tc_table[i].temp_down; + + if (now_temp >= down_temp && now_temp <= up_temp) { + /* Temp range or charger are not update, return */ + if (battery->charge_index == i) + return; + + if ((battery->pdata->tc_table[i].chrg_current != 0) && + (battery->pdata->tc_table[i].chrg_current_index != 0xff)) { + rk817_bat_field_write(battery, + CHRG_CUR_SEL, + battery->pdata->tc_table[i].chrg_current_index); + DBG("T change: charger current: %d, index: %d\n", + battery->pdata->tc_table[i].chrg_current, + battery->pdata->tc_table[i].chrg_current_index); + } else + rk817_bat_disable_charge(battery); + + if ((battery->pdata->tc_table[i].chrg_voltage != 0) && + (battery->pdata->tc_table[i].chrg_voltage_index != 0xff)) { + rk817_bat_disable_usb2vsys(battery); + rk817_bat_field_write(battery, + CHRG_VOL_SEL, + battery->pdata->tc_table[i].chrg_voltage_index); + rk817_bat_enable_usb2vsys(battery); + DBG("T change: charger voltage: %d, index: %d\n", + battery->pdata->tc_table[i].chrg_voltage, + battery->pdata->tc_table[i].chrg_voltage_index); + } else + rk817_bat_enable_charge(battery); + + battery->charge_index = i; + } + } +} + +static int rk817_bat_get_bat_ts(struct rk817_battery_device *battery) +{ + int temp_value = 0; + + temp_value = rk817_bat_field_read(battery, BAT_TS_H) << 8; + temp_value |= rk817_bat_field_read(battery, BAT_TS_L); + + return temp_value; +} + +static int rk817_bat_get_nts_res(struct rk817_battery_device *battery) +{ + int temp_value, res; + int adc_to_vol; + + temp_value = rk817_bat_get_bat_ts(battery); + adc_to_vol = temp_value * 1200 / 65536; + + res = adc_to_vol * 1000 / battery->pdata->ntc_factor; + + DBG("NTC: ADC: value: 0x%x, adc2vol:%d, res: %d\n", + temp_value, adc_to_vol, res); + + return res; +} + +static void rk817_bat_update_temperature(struct rk817_battery_device *battery) +{ + u32 ntc_size, *ntc_table; + int i, res; + + ntc_table = battery->pdata->ntc_table; + ntc_size = battery->pdata->ntc_size; + + if (ntc_size) { + res = rk817_bat_get_nts_res(battery); + if (res == 0) + return; + + if (res < ntc_table[ntc_size - 1]) { + battery->temperature = (ntc_size + battery->pdata->ntc_degree_from) * 10; + DBG("bat ntc upper max degree: R=%d\n", res); + } else if (res > ntc_table[0]) { + battery->temperature = battery->pdata->ntc_degree_from * 10; + DBG("bat ntc lower min degree: R=%d\n", res); + } else { + for (i = 0; i < ntc_size; i++) { + if (res >= ntc_table[i]) + break; + } + + if (i <= 0) + battery->temperature = + (battery->pdata->ntc_degree_from) * 10; + else + battery->temperature = + (i + battery->pdata->ntc_degree_from) * 10; + } + DBG("Temperature: %d\n", battery->temperature); + rk817_bat_temperature_chrg(battery, battery->temperature / 10); + } +} + /* * cccv and finish switch all the time will cause dsoc freeze, * if so, do finish chrg, 100ma is less than min finish_ma. @@ -1657,6 +1904,7 @@ static void rk817_bat_init_fg(struct rk817_battery_device *battery) rk817_bat_init_caltimer(battery); rk817_bat_rsoc_init(battery); rk817_bat_init_coulomb_cap(battery, battery->nac); + rk817_bat_init_ts_detect(battery); DBG("rsoc%d, fcc = %d\n", battery->rsoc, battery->fcc); rk817_bat_init_dsoc_algorithm(battery); battery->qmax = rk817_bat_get_qmax(battery); @@ -1677,6 +1925,119 @@ static void rk817_bat_init_fg(struct rk817_battery_device *battery) DBG("OCV_THRE_VOL: 0x%x", rk817_bat_field_read(battery, OCV_THRE_VOL)); } +static u8 rk817_bat_decode_chrg_voltage(u32 chrg_voltage) +{ + if (chrg_voltage == 0) + return 0xff; + + if (chrg_voltage < 4150) + return CHRG_VOL_4100MV; + else if (chrg_voltage < 4200) + return CHRG_VOL_4100MV; + else if (chrg_voltage < 4250) + return CHRG_VOL_4200MV; + else if (chrg_voltage < 4300) + return CHRG_VOL_4250MV; + else if (chrg_voltage < 4350) + return CHRG_VOL_4300MV; + else if (chrg_voltage < 4400) + return CHRG_VOL_4350MV; + else if (chrg_voltage < 4450) + return CHRG_VOL_4400MV; + else + return CHRG_VOL_4450MV; +} + +static u8 rk817_bat_decode_chrg_current(struct rk817_battery_device *battery, + u32 chrg_current) +{ + int val; + + if (chrg_current == 0) + return 0xff; + + val = chrg_current * battery->pdata->sample_res / 10; + if (val < 1000) + return CHRG_CUR_500MA; + else if (val < 1500) + return CHRG_CUR_1000MA; + else if (val < 2000) + return CHRG_CUR_1500MA; + else if (val < 2500) + return CHRG_CUR_2000MA; + else if (val < 2750) + return CHRG_CUR_2500MA; + else if (val < 3000) + return CHRG_CUR_2750MA; + else if (val < 3500) + return CHRG_CUR_3000MA; + else + return CHRG_CUR_3500MA; +} + +static int parse_temperature_chrg_table(struct rk817_battery_device *battery, + struct device_node *np) +{ + int size, count; + int i, chrg_current, chrg_voltage; + const __be32 *list; + + if (!of_find_property(np, "temperature_chrg_table", &size)) + return 0; + + list = of_get_property(np, "temperature_chrg_table", &size); + size /= sizeof(u32); + if (!size || (size % 3)) { + dev_err(battery->dev, + "invalid temperature_chrg_table: size=%d\n", size); + return -EINVAL; + } + + count = size / 4; + battery->pdata->tc_count = count; + battery->pdata->tc_table = devm_kzalloc(battery->dev, + count * sizeof(*battery->pdata->tc_table), + GFP_KERNEL); + if (!battery->pdata->tc_table) + return -ENOMEM; + + for (i = 0; i < count; i++) { + /* temperature */ + battery->pdata->tc_table[i].temp_down = be32_to_cpu(*list++); + battery->pdata->tc_table[i].temp_up = be32_to_cpu(*list++); + chrg_current = be32_to_cpu(*list++); + chrg_voltage = be32_to_cpu(*list++); + + /* + * because charge current lowest level is 500mA: + * higher than or equal 1000ma, select charge current; + * lower than 500ma, must select input current. + */ + if (chrg_current >= 500) { + battery->pdata->tc_table[i].chrg_current = chrg_current; + battery->pdata->tc_table[i].chrg_current_index = rk817_bat_decode_chrg_current(battery, chrg_current); + } else { + battery->pdata->tc_table[i].chrg_current = 0; + } + + if (chrg_voltage >= 4100) { + battery->pdata->tc_table[i].chrg_voltage = chrg_voltage; + battery->pdata->tc_table[i].chrg_voltage_index = rk817_bat_decode_chrg_voltage(chrg_voltage); + } else { + battery->pdata->tc_table[i].chrg_voltage = 0; + } + DBG("temp%d: [%d, %d], chrg_current=%d, current_index: %d, chrg_voltage: %d, voltage_index: %d\n", + i, battery->pdata->tc_table[i].temp_down, + battery->pdata->tc_table[i].temp_up, + battery->pdata->tc_table[i].chrg_current, + battery->pdata->tc_table[i].chrg_current_index, + battery->pdata->tc_table[i].chrg_voltage, + battery->pdata->tc_table[i].chrg_voltage_index); + } + + return 0; +} + static int rk817_bat_parse_dt(struct rk817_battery_device *battery) { u32 out_value; @@ -1816,6 +2177,45 @@ static int rk817_bat_parse_dt(struct rk817_battery_device *battery) dev_err(dev, "not have to register chg psy!\n"); } + if (!of_find_property(np, "ntc_table", &length)) { + pdata->ntc_size = 0; + battery->temperature = VIRTUAL_TEMPERATURE; + } else { + /* get ntc degree base value */ + ret = of_property_read_u32_index(np, "ntc_degree_from", 1, + &pdata->ntc_degree_from); + if (ret) { + dev_err(dev, "invalid ntc_degree_from\n"); + return -EINVAL; + } + + ret = of_property_read_u32_index(np, "ntc_degree_from", 0, + &out_value); + if (ret) { + dev_err(dev, "invalid ntc_degree_from\n"); + return -EINVAL; + } + + if (out_value) + pdata->ntc_degree_from = -pdata->ntc_degree_from; + + pdata->ntc_size = length / sizeof(u32); + } + + if (pdata->ntc_size) { + parse_temperature_chrg_table(battery, np); + size = sizeof(*pdata->ntc_table) * pdata->ntc_size; + pdata->ntc_table = devm_kzalloc(battery->dev, size, GFP_KERNEL); + if (!pdata->ntc_table) + return -ENOMEM; + + ret = of_property_read_u32_array(np, "ntc_table", + pdata->ntc_table, + pdata->ntc_size); + if (ret < 0) + return ret; + } + DBG("the battery dts info dump:\n" "bat_res:%d\n" "res_sample:%d\n" @@ -2412,6 +2812,8 @@ static void rk817_bat_print_time(struct rk817_battery_device *battery) static void rk817_bat_output_info(struct rk817_battery_device *battery) { + int index; + DBG("info start:\n"); DBG("info: voltage_k %d\n", battery->voltage_k); DBG("info: voltage_b %d\n", battery->voltage_b); @@ -2422,13 +2824,21 @@ static void rk817_bat_output_info(struct rk817_battery_device *battery) DBG("info: awke: %d, count: %d\n", battery->pdata->charge_stay_awake, battery->active_awake); - DBG("DEBUG: dsoc/1000: %d, dsoc: %d, rsoc: %d, sm_soc: %d, delta_rsoc: %d, vol: %d, exp_vol %d, current: %d, sm_link: %d, remain_cap: %d, sm_cap: %d\n", battery->dsoc / 1000, battery->dsoc, battery->rsoc, battery->smooth_soc, battery->delta_rsoc, battery->voltage_avg, battery->expected_voltage, battery->current_avg, battery->sm_linek, battery->remain_cap, battery->sm_remain_cap); rk817_bat_print_time(battery); + if (battery->pdata->ntc_size) { + index = battery->charge_index; + DBG("Temperature: %d charger current: %dmA, index: %d, charger voltage: %dmV, index: %d\n", + battery->temperature, + battery->pdata->tc_table[index].chrg_current, + battery->pdata->tc_table[index].chrg_current_index, + battery->pdata->tc_table[index].chrg_voltage, + battery->pdata->tc_table[index].chrg_voltage_index); + } DBG("info END.\n"); } @@ -2442,9 +2852,11 @@ static void rk817_battery_work(struct work_struct *work) rk817_bat_update_fg_info(battery); rk817_bat_lowpwr_check(battery); rk817_bat_display_smooth(battery); + rk817_bat_update_fcc(battery); rk817_bat_power_supply_changed(battery); rk817_bat_save_data(battery); rk817_bat_stay_awake(battery); + rk817_bat_update_temperature(battery); rk817_bat_output_info(battery); if (rk817_bat_field_read(battery, CUR_CALIB_UPD)) { From 0374714804670f445ac6449d4c0d8b9fbe84590d Mon Sep 17 00:00:00 2001 From: Shengfei Xu Date: Wed, 16 Apr 2025 18:13:43 +0800 Subject: [PATCH 18/18] power: supply: rk817_battery: Supports battery aging calibration Change-Id: Ie7866d020fa16b39f3541d2874fc4d2d80977477 Signed-off-by: Shengfei Xu --- drivers/power/supply/rk817_battery.c | 222 +++++++++++++++------------ 1 file changed, 123 insertions(+), 99 deletions(-) diff --git a/drivers/power/supply/rk817_battery.c b/drivers/power/supply/rk817_battery.c index 51119a1da8fa..75cf99f8d068 100644 --- a/drivers/power/supply/rk817_battery.c +++ b/drivers/power/supply/rk817_battery.c @@ -80,6 +80,8 @@ module_param_named(dbg_level, dbg_enable, int, 0644); /* Effective full capacity */ #define EFFECTIVE_FULL_MIN_CAP(fcc) ((fcc) * 800 / 1000) #define EFFECTIVE_FULL_MAX_CAP(fcc) ((fcc) * 1200 / 1000) +/* Battery Percentage (or State of Charge (SOC) Percentage) */ +#define BATTERY_PERCENTAGE(n) (n * 1000) #define ADC_CALIB_THRESHOLD 4 #define ADC_CALIB_LMT_MIN 3 @@ -92,16 +94,6 @@ module_param_named(dbg_level, dbg_enable, int, 0644); #define DEFAULT_SLP_FILTER_CUR 100 #define DEFAULT_PWROFF_VOL_THRESD 3400 #define DEFAULT_MONITOR_SEC 5 -#define DEFAULT_ALGR_VOL_THRESD1 3850 -#define DEFAULT_ALGR_VOL_THRESD2 3950 -#define DEFAULT_CHRG_VOL_SEL CHRG_VOL4200MV -#define DEFAULT_CHRG_CUR_SEL CHRG_CUR1400MA -#define DEFAULT_CHRG_CUR_INPUT INPUT_CUR2000MA -#define DEFAULT_POFFSET 42 -#define DEFAULT_MAX_SOC_OFFSET 60 -#define DEFAULT_FB_TEMP TEMP_115C -#define DEFAULT_ENERGY_MODE 0 -#define DEFAULT_ZERO_RESERVE_DSOC 10 #define DEFAULT_SAMPLE_RES 20 /* sleep */ @@ -256,7 +248,7 @@ enum rk817_battery_fields { REMAIN_CAP_REG2, REMAIN_CAP_REG1, REMAIN_CAP_REG0, NEW_FCC_REG2, NEW_FCC_REG1, NEW_FCC_REG0, RESET_MODE, - FG_INIT, HALT_CNT_REG, CALC_REST_REGL, CALC_REST_REGH, + FG_INIT, HALT_CNT_REG, CALC_REST_REGL, UPDATE_LEVE_REG, VOL_ADC_B3, VOL_ADC_B2, VOL_ADC_B1, VOL_ADC_B0, VOL_ADC_K3, VOL_ADC_K2, VOL_ADC_K1, VOL_ADC_K0, BAT_EXS, CHG_STS, BAT_OVP_STS, CHRG_IN_CLAMP, @@ -412,7 +404,7 @@ static const struct reg_field rk817_battery_reg_fields[] = { [HALT_CNT_REG] = REG_FIELD(0xA6, 0, 7), [CALC_REST_REGL] = REG_FIELD(0xA7, 0, 7), - [CALC_REST_REGH] = REG_FIELD(0xA8, 0, 7), + [UPDATE_LEVE_REG] = REG_FIELD(0xA8, 0, 7), [VOL_ADC_B3] = REG_FIELD(0xA9, 0, 7), [VOL_ADC_B2] = REG_FIELD(0xAA, 0, 7), @@ -463,7 +455,6 @@ struct battery_platform_data { u32 sleep_exit_current; u32 sleep_filter_current; - u32 max_soc_offset; u32 bat_mode; u32 sample_res; u32 bat_res_up; @@ -583,6 +574,11 @@ static unsigned long base2sec(unsigned long x) return 0; } +static unsigned long base2min(unsigned long x) +{ + return base2sec(x) / 60; +} + static u32 interpolate(int value, u32 *table, int size) { u8 i; @@ -740,6 +736,16 @@ static void rk817_bat_init_voltage_kb(struct rk817_battery_device *battery) } } +static void rk817_bat_save_age_level(struct rk817_battery_device *battery, u8 level) +{ + rk817_bat_field_write(battery, UPDATE_LEVE_REG, level); +} + +static u8 rk817_bat_get_age_level(struct rk817_battery_device *battery) +{ + return rk817_bat_field_read(battery, UPDATE_LEVE_REG); +} + static void rk817_bat_restart_relax(struct rk817_battery_device *battery) { rk817_bat_field_write(battery, RELAX_VOL1_UPD, 0x00); @@ -826,14 +832,6 @@ static void rk817_bat_set_relax_sample(struct rk817_battery_device *battery) __func__, pdata->sleep_enter_current, pdata->sleep_exit_current); } -/* runtime OCV voltage, |RLX_VOL2 - RLX_VOL1| < OCV_THRE, - * the OCV reg update every 120s - */ -static void rk817_bat_ocv_thre(struct rk817_battery_device *battery, int value) -{ - rk817_bat_field_write(battery, OCV_THRE_VOL, value); -} - static int rk817_bat_get_ocv_voltage(struct rk817_battery_device *battery) { int vol, val = 0, vol_temp; @@ -1373,13 +1371,25 @@ static void rk817_bat_update_fcc(struct rk817_battery_device *battery) if (update_status) return; - if ((battery->chrg_status == CHRG_OFF) && - (battery->voltage_avg <= battery->pdata->pwroff_vol) && - (battery->rsoc > 5 * 1000) && (battery->dsoc < 1000) && - (battery->temperature >= VIRTUAL_TEMPERATURE)) { + /* The conditions to update FCC are: + * during discharging state, + * with temperature above 18°C and + * displayed battery level below 1% + */ + if ((battery->chrg_status != CHRG_OFF) || (battery->dsoc > 1000) || + (battery->temperature < VIRTUAL_TEMPERATURE)) + return; + + /* + * Update the FCC to 99.5% of its original value when the aforementioned + * basic conditions are met ‌and‌ the loaded voltage falls below + * the DTS-configured shutdown voltage. + */ + if ((battery->voltage_avg <= battery->pdata->pwroff_vol) && + (battery->rsoc > BATTERY_PERCENTAGE(1))) { temp_fcc = UPDATE_REDUCE_FCC(battery->fcc); if (temp_fcc > EFFECTIVE_FULL_MIN_CAP(battery->pdata->design_capacity)) { - DBG("update fcc: design: %d, old: %d, new: %d\n", + DBG("REDUCE: update fcc: design: %d, old: %d, new: %d\n", battery->pdata->design_capacity, battery->fcc, temp_fcc); battery->qmax = temp_fcc; battery->fcc = temp_fcc; @@ -1389,10 +1399,15 @@ static void rk817_bat_update_fcc(struct rk817_battery_device *battery) } } - if ((battery->chrg_status == CHRG_OFF) && - (battery->voltage_avg >= battery->pdata->ocv_table[1]) && - (battery->rsoc < 5 * 1000) && (battery->dsoc < 1000) && - (battery->temperature >= VIRTUAL_TEMPERATURE)) { + /* Update the FCC to 100.5% of its original value when the following conditions are met: + * + * The aforementioned basic conditions are satisfied + * (e.g., discharging state, temperature >18°C). + * The loaded voltage exceeds the voltage corresponding to 5% SOC in the OCV table. + * The RSOC (Relative State of Charge) is below 5%. + */ + if ((battery->voltage_avg >= battery->pdata->ocv_table[1]) && + (battery->rsoc < BATTERY_PERCENTAGE(5))) { temp_fcc = UPDATE_RAISE_FCC(battery->fcc); if (temp_fcc < EFFECTIVE_FULL_MAX_CAP(battery->pdata->design_capacity)) { DBG("RAISE fcc: design: %d, old: %d, new: %d\n", @@ -1770,7 +1785,7 @@ static void rk817_bat_first_pwron(struct rk817_battery_device *battery) static void rk817_bat_not_first_pwron(struct rk817_battery_device *battery) { - int now_cap, pre_soc, pre_cap, ocv_cap, ocv_soc, ocv_vol; + int now_cap, pre_soc, pre_cap; battery->fcc = rk817_bat_get_fcc(battery); pre_soc = rk817_bat_get_prev_dsoc(battery); @@ -1790,43 +1805,11 @@ static void rk817_bat_not_first_pwron(struct rk817_battery_device *battery) rk817_bat_init_coulomb_cap(battery, now_cap); pre_cap = now_cap; pre_soc = battery->rsoc; - goto finish; } else if (battery->is_initialized) { /* uboot initialized */ BAT_INFO("initialized yet..\n"); - goto finish; - } else if (battery->is_ocv_calib) { - /* not initialized and poweroff_cnt above 30 min */ - ocv_vol = rk817_bat_get_ocv_voltage(battery); - ocv_soc = rk817_bat_vol2soc(battery, ocv_vol); - ocv_cap = rk817_bat_vol2cap(battery, ocv_vol); - pre_cap = ocv_cap; - battery->ocv_pre_dsoc = pre_soc; - battery->ocv_new_dsoc = ocv_soc; - if (abs(ocv_soc - pre_soc) >= battery->pdata->max_soc_offset) { - battery->ocv_pre_dsoc = pre_soc; - battery->ocv_new_dsoc = ocv_soc; - battery->is_max_soc_offset = true; - BAT_INFO("trigger max soc offset, dsoc: %d -> %d\n", - pre_soc, ocv_soc); - pre_soc = ocv_soc; - } - BAT_INFO("OCV calib: cap=%d, rsoc=%d\n", ocv_cap, ocv_soc); - } else if (battery->pwroff_min > 0) { - ocv_vol = rk817_bat_get_ocv_voltage(battery); - ocv_soc = rk817_bat_vol2soc(battery, ocv_vol); - ocv_cap = rk817_bat_vol2cap(battery, ocv_vol); - battery->force_pre_dsoc = pre_soc; - battery->force_new_dsoc = ocv_soc; - if (abs(ocv_soc - pre_soc) >= 80) { - battery->is_force_calib = true; - BAT_INFO("dsoc force calib: %d -> %d\n", - pre_soc, ocv_soc); - pre_soc = ocv_soc; - pre_cap = ocv_cap; - } } -finish: + battery->dsoc = pre_soc; battery->nac = pre_cap; if (battery->nac < 0) @@ -1900,7 +1883,6 @@ static void rk817_bat_init_fg(struct rk817_battery_device *battery) rk817_bat_gg_con_init(battery); rk817_bat_init_voltage_kb(battery); rk817_bat_set_relax_sample(battery); - rk817_bat_ocv_thre(battery, 0xff); rk817_bat_init_caltimer(battery); rk817_bat_rsoc_init(battery); rk817_bat_init_coulomb_cap(battery, battery->nac); @@ -1922,7 +1904,6 @@ static void rk817_bat_init_fg(struct rk817_battery_device *battery) DBG("probe init: battery->dsoc = %d, rsoc = %d, remain_cap = %d\n, bat_vol = %d\n, sys_vol = %d, qmax = %d\n", battery->dsoc, battery->rsoc, battery->remain_cap, battery->voltage_avg, battery->voltage_sys, battery->qmax); - DBG("OCV_THRE_VOL: 0x%x", rk817_bat_field_read(battery, OCV_THRE_VOL)); } static u8 rk817_bat_decode_chrg_voltage(u32 chrg_voltage) @@ -2061,7 +2042,6 @@ static int rk817_bat_parse_dt(struct rk817_battery_device *battery) pdata->sleep_filter_current = DEFAULT_SLP_FILTER_CUR; pdata->bat_mode = MODE_BATTARY; - pdata->max_soc_offset = DEFAULT_MAX_SOC_OFFSET; pdata->fake_full_soc = 100; pdata->sample_res = DEFAULT_SAMPLE_RES; pdata->charge_stay_awake = 0; @@ -2107,11 +2087,6 @@ static int rk817_bat_parse_dt(struct rk817_battery_device *battery) if (ret < 0) dev_err(dev, "sample_res missing!\n"); - ret = of_property_read_u32(np, "max_soc_offset", - &pdata->max_soc_offset); - if (ret < 0) - dev_err(dev, "max_soc_offset missing!\n"); - ret = of_property_read_u32(np, "monitor_sec", &pdata->monitor_sec); if (ret < 0) dev_err(dev, "monitor_sec missing!\n"); @@ -2168,9 +2143,10 @@ static int rk817_bat_parse_dt(struct rk817_battery_device *battery) ret = of_property_read_u32(np, "design_max_voltage", &pdata->design_max_voltage); - if (ret < 0) + if (ret < 0) { dev_err(dev, "battery design_max_voltage missing!\n"); - + pdata->design_max_voltage = pdata->ocv_table[pdata->ocv_size - 1]; + } ret = of_property_read_u32(np, "register_chg_psy", &battery->is_register_chg_psy); if (ret < 0 || !battery->is_register_chg_psy) @@ -2225,7 +2201,6 @@ static int rk817_bat_parse_dt(struct rk817_battery_device *battery) "sleep_exit_current:%d\n" "sleep_filter_current:%d\n" "monitor_sec:%d\n" - "max_soc_offset:%d\n" "virtual_power:%d\n" "pwroff_vol:%d\n", pdata->bat_res, @@ -2236,7 +2211,6 @@ static int rk817_bat_parse_dt(struct rk817_battery_device *battery) pdata->sleep_exit_current, pdata->sleep_filter_current, pdata->monitor_sec, - pdata->max_soc_offset, pdata->bat_mode, pdata->pwroff_vol); @@ -2676,6 +2650,20 @@ static void rk817_bat_smooth_algorithm(struct rk817_battery_device *battery) delta_cap, battery->dsoc); } +static void rk817_bat_init_capacity(struct rk817_battery_device *battery, + u32 cap) +{ + int delta_cap; + + delta_cap = cap - battery->remain_cap; + if (!delta_cap) + return; + + battery->age_adjust_cap += delta_cap; + rk817_bat_init_coulomb_cap(battery, cap); + rk817_bat_smooth_algo_prepare(battery); +} + static void rk817_bat_finish_algorithm(struct rk817_battery_device *battery) { unsigned long finish_sec, soc_sec; @@ -2721,6 +2709,54 @@ static void rk817_bat_finish_algorithm(struct rk817_battery_device *battery) battery->dsoc = MAX_PERCENTAGE; } +static void rk817_bat_update_age_fcc(struct rk817_battery_device *battery) +{ + int fcc; + int remain_cap; + int age_keep_min; + + + fcc = battery->fcc * 1000; + remain_cap = fcc - battery->age_ocv_cap - battery->age_adjust_cap; + age_keep_min = base2min(battery->age_keep_sec); + + DBG("%s: lock_fcc=%d, age_ocv_cap=%d, age_adjust_cap=%d, remain_cap=%d, age_allow_update=%d, age_keep_min=%d\n", + __func__, fcc, battery->age_ocv_cap, battery->age_adjust_cap, remain_cap, + battery->age_allow_update, age_keep_min); + + if ((battery->chrg_status == CHARGE_FINISH) && (battery->age_allow_update) && + (age_keep_min < battery->fcc * 60 / 2000)) { + battery->age_allow_update = false; + fcc = remain_cap * 100 * 1000 / DIV(100 * 1000 - battery->age_ocv_soc); + BAT_INFO("calc_cap=%d, age: soc=%d, cap=%d, level=%d, fcc:%d->%d?\n", + remain_cap, battery->age_ocv_soc, + battery->age_ocv_cap, battery->age_level, battery->fcc, fcc); + + if ((fcc < EFFECTIVE_FULL_MAX_CAP(battery->pdata->design_capacity)) && + (fcc > EFFECTIVE_FULL_MIN_CAP(battery->pdata->design_capacity))) { + BAT_INFO("fcc:%d->%d!\n", battery->fcc, fcc); + battery->fcc = fcc / 1000; + rk817_bat_init_capacity(battery, battery->fcc); + rk817_bat_save_fcc(battery, battery->fcc); + } + } +} + +static void rk817_bat_wait_finish_sig(struct rk817_battery_device *battery) +{ + int chrg_finish_vol = battery->pdata->design_max_voltage; + + if (battery->chrg_status == CHARGE_FINISH) + return; + + if ((battery->chrg_status == CHARGE_FINISH) && + (battery->temperature >= VIRTUAL_TEMPERATURE) && + (battery->voltage_avg > chrg_finish_vol - 150) && battery->age_allow_update) { + rk817_bat_update_age_fcc(battery);/* save new fcc*/ + battery->age_allow_update = false; + } +} + static void rk817_bat_display_smooth(struct rk817_battery_device *battery) { if (battery->s2r && !battery->sleep_chrg_online) { @@ -2824,6 +2860,7 @@ static void rk817_bat_output_info(struct rk817_battery_device *battery) DBG("info: awke: %d, count: %d\n", battery->pdata->charge_stay_awake, battery->active_awake); + DBG("DEBUG: dsoc/1000: %d, dsoc: %d, rsoc: %d, sm_soc: %d, delta_rsoc: %d, vol: %d, exp_vol %d, current: %d, sm_link: %d, remain_cap: %d, sm_cap: %d\n", battery->dsoc / 1000, battery->dsoc, battery->rsoc, battery->smooth_soc, battery->delta_rsoc, @@ -2850,6 +2887,7 @@ static void rk817_battery_work(struct work_struct *work) bat_delay_work.work); rk817_bat_update_fg_info(battery); + rk817_bat_wait_finish_sig(battery); rk817_bat_lowpwr_check(battery); rk817_bat_display_smooth(battery); rk817_bat_update_fcc(battery); @@ -3124,7 +3162,7 @@ static int rk817_bat_rtc_sleep_sec(struct rk817_battery_device *battery) static void rk817_bat_relife_age_flag(struct rk817_battery_device *battery) { - u8 ocv_soc, ocv_cap, soc_level; + int age_level, ocv_soc, ocv_cap; if (battery->voltage_relax <= 0) return; @@ -3148,38 +3186,24 @@ static void rk817_bat_relife_age_flag(struct rk817_battery_device *battery) else battery->age_level = 80; - /*soc_level = rk818_bat_get_age_level(battery);*/ - soc_level = 0; - if (soc_level > battery->age_level) { + age_level = rk817_bat_get_age_level(battery); + if (age_level > battery->age_level) { battery->age_allow_update = false; + age_level -= 5; + if (age_level <= 80) + age_level = 80; + rk817_bat_save_age_level(battery, age_level); } else { battery->age_allow_update = true; battery->age_keep_sec = get_boot_sec(); } - BAT_INFO("resume: age_vol:%d, age_ocv_cap:%d, age_ocv_soc:%d\n" - "soc_level:%d, age_allow_update:%d\n" - "age_level:%d\n", + BAT_INFO("resume: age_vol:%d, age_ocv_cap:%d, age_ocv_soc:%d, age_allow_update:%d, age_level:%d\n", battery->age_voltage, battery->age_ocv_cap, - ocv_soc, soc_level, - battery->age_allow_update, battery->age_level); + ocv_soc, battery->age_allow_update, battery->age_level); } } -static void rk817_bat_init_capacity(struct rk817_battery_device *battery, - u32 cap) -{ - int delta_cap; - - delta_cap = cap - battery->remain_cap; - if (!delta_cap) - return; - - battery->age_adjust_cap += delta_cap; - rk817_bat_init_coulomb_cap(battery, cap); - rk817_bat_smooth_algo_prepare(battery); -} - static void rk817_bat_relax_vol_calib(struct rk817_battery_device *battery) { int soc, cap, vol;