From f97dd008a314ae79ea5a395abe30a8a59dec1622 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Tue, 11 Oct 2022 10:19:20 +0800 Subject: [PATCH 01/12] media: rockchip: isp: no wait if shutdown Change-Id: I76d161cb6b1a4b22d41d3a4a2be4d604049ed3af Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/bridge_v20.c | 12 +++++++----- drivers/media/platform/rockchip/isp/capture_v1x.c | 3 ++- drivers/media/platform/rockchip/isp/capture_v20.c | 3 ++- drivers/media/platform/rockchip/isp/capture_v21.c | 2 +- drivers/media/platform/rockchip/isp/capture_v30.c | 2 +- drivers/media/platform/rockchip/isp/capture_v32.c | 9 +++++---- drivers/media/platform/rockchip/isp/dmarx.c | 3 ++- drivers/media/platform/rockchip/isp/rkisp.c | 2 +- 8 files changed, 21 insertions(+), 15 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/bridge_v20.c b/drivers/media/platform/rockchip/isp/bridge_v20.c index f441b8d8e9b4..c637b0069128 100644 --- a/drivers/media/platform/rockchip/isp/bridge_v20.c +++ b/drivers/media/platform/rockchip/isp/bridge_v20.c @@ -609,11 +609,13 @@ static int bridge_stop(struct rkisp_bridge_device *dev) dev->ops->disable(dev); rkisp_stop_spstream(sp_stream); hdr_stop_dmatx(dev->ispdev); - ret = wait_event_timeout(dev->done, !dev->en, - msecs_to_jiffies(1000)); - if (!ret) - v4l2_warn(&dev->sd, - "%s timeout ret:%d\n", __func__, ret); + if (!dev->ispdev->hw_dev->is_shutdown) { + ret = wait_event_timeout(dev->done, !dev->en, + msecs_to_jiffies(1000)); + if (!ret) + v4l2_warn(&dev->sd, + "%s timeout ret:%d\n", __func__, ret); + } crop_off(dev); dev->stopping = false; dev->en = false; diff --git a/drivers/media/platform/rockchip/isp/capture_v1x.c b/drivers/media/platform/rockchip/isp/capture_v1x.c index 181978acf1b7..3c1df5e5273d 100644 --- a/drivers/media/platform/rockchip/isp/capture_v1x.c +++ b/drivers/media/platform/rockchip/isp/capture_v1x.c @@ -790,7 +790,8 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) stream->stopping = true; stream->ops->stop_mi(stream); if ((dev->isp_state & ISP_START) && - dev->isp_inp != INP_DMARX_ISP) { + dev->isp_inp != INP_DMARX_ISP && + !dev->hw_dev->is_shutdown) { ret = wait_event_timeout(stream->done, !stream->streaming, msecs_to_jiffies(1000)); diff --git a/drivers/media/platform/rockchip/isp/capture_v20.c b/drivers/media/platform/rockchip/isp/capture_v20.c index 8307ae6cb74e..75df13bfd66b 100644 --- a/drivers/media/platform/rockchip/isp/capture_v20.c +++ b/drivers/media/platform/rockchip/isp/capture_v20.c @@ -1518,7 +1518,8 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) stream->stopping = true; stream->ops->stop_mi(stream); if ((dev->isp_state & ISP_START) && - dev->isp_inp != INP_DMARX_ISP) { + dev->isp_inp != INP_DMARX_ISP && + !dev->hw_dev->is_shutdown) { ret = wait_event_timeout(stream->done, !stream->streaming, msecs_to_jiffies(1000)); diff --git a/drivers/media/platform/rockchip/isp/capture_v21.c b/drivers/media/platform/rockchip/isp/capture_v21.c index 2dc077a48d25..d685952f9f25 100644 --- a/drivers/media/platform/rockchip/isp/capture_v21.c +++ b/drivers/media/platform/rockchip/isp/capture_v21.c @@ -1331,7 +1331,7 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) struct v4l2_device *v4l2_dev = &dev->v4l2_dev; unsigned long lock_flags = 0; int ret = 0; - bool is_wait = true; + bool is_wait = dev->hw_dev->is_shutdown ? false : true; if (!dev->dmarx_dev.trigger && (is_rdbk_stream(stream) || is_hdr_stream(stream))) { diff --git a/drivers/media/platform/rockchip/isp/capture_v30.c b/drivers/media/platform/rockchip/isp/capture_v30.c index d0ff8e295e0a..f6b06fe2217c 100644 --- a/drivers/media/platform/rockchip/isp/capture_v30.c +++ b/drivers/media/platform/rockchip/isp/capture_v30.c @@ -966,7 +966,7 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) struct v4l2_device *v4l2_dev = &dev->v4l2_dev; unsigned long lock_flags = 0; int ret = 0; - bool is_wait = true; + bool is_wait = dev->hw_dev->is_shutdown ? false : true; stream->stopping = true; if (dev->hw_dev->is_single) diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index 67cb27c320eb..2b33bbb951e9 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -1307,7 +1307,7 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) struct v4l2_device *v4l2_dev = &dev->v4l2_dev; unsigned long lock_flags = 0; int ret = 0; - bool is_wait = true; + bool is_wait = dev->hw_dev->is_shutdown ? false : true; stream->stopping = true; stream->is_pause = false; @@ -1562,9 +1562,10 @@ static void rkisp_stop_streaming(struct vb2_queue *queue) if (stream->id == RKISP_STREAM_LUMA) { stream->stopping = true; - wait_event_timeout(stream->done, - stream->frame_end, - msecs_to_jiffies(500)); + if (!dev->hw_dev->is_shutdown) + wait_event_timeout(stream->done, + stream->frame_end, + msecs_to_jiffies(500)); stream->streaming = false; stream->stopping = false; destroy_buf_queue(stream, VB2_BUF_STATE_ERROR); diff --git a/drivers/media/platform/rockchip/isp/dmarx.c b/drivers/media/platform/rockchip/isp/dmarx.c index 2d8a7eb9b855..fade9c243d7e 100644 --- a/drivers/media/platform/rockchip/isp/dmarx.c +++ b/drivers/media/platform/rockchip/isp/dmarx.c @@ -505,7 +505,8 @@ static void dmarx_stop(struct rkisp_stream *stream) int ret = 0; stream->stopping = true; - if ((dev->isp_state & ISP_START) && !stream->frame_end) { + if ((dev->isp_state & ISP_START) && !stream->frame_end && + !dev->hw_dev->is_shutdown) { ret = wait_event_timeout(stream->done, !stream->streaming, msecs_to_jiffies(100)); diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index 7597539eb919..fbc772eff2a4 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -1838,7 +1838,7 @@ static void rkisp_stop_3a_run(struct rkisp_device *dev) int ret = 1000; if (!rkisp_is_need_3a(dev) || dev->isp_ver == ISP_V20 || - !params_vdev->is_subs_evt) + !params_vdev->is_subs_evt || dev->hw_dev->is_shutdown) return; v4l2_event_queue(vdev, &ev); From 50d0d25b96297ffcbe7a9483d0c680c2b446b511 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Sun, 9 Oct 2022 18:10:55 +0800 Subject: [PATCH 02/12] media: rockchip: isp: fix stream no output for multi sensor Change-Id: I1eac20635753120bcd45bf3b04d45b64a6f35f0a Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/common.c | 8 ++++++++ drivers/media/platform/rockchip/isp/rkisp.c | 9 +++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/common.c b/drivers/media/platform/rockchip/isp/common.c index 534b83c34020..875d6da59ed0 100644 --- a/drivers/media/platform/rockchip/isp/common.c +++ b/drivers/media/platform/rockchip/isp/common.c @@ -167,9 +167,17 @@ void rkisp_update_regs(struct rkisp_device *dev, u32 start, u32 end) } if (*flag == SW_REG_CACHE) { + if ((i == ISP3X_MAIN_RESIZE_CTRL || + i == ISP32_BP_RESIZE_CTRL || + i == ISP3X_SELF_RESIZE_CTRL) && *val == 0) + *val = CIF_RSZ_CTRL_CFG_UPD; writel(*val, base + i); if (hw->is_unite) { val = dev->sw_base_addr + i + RKISP_ISP_SW_MAX_SIZE; + if ((i == ISP3X_MAIN_RESIZE_CTRL || + i == ISP32_BP_RESIZE_CTRL || + i == ISP3X_SELF_RESIZE_CTRL) && *val == 0) + *val = CIF_RSZ_CTRL_CFG_UPD; writel(*val, hw->base_next_addr + i); } } diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index fbc772eff2a4..1b63317584eb 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -616,11 +616,12 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo rkisp_update_regs(dev, CTRL_VI_ISP_PATH, SUPER_IMP_COLOR_CR); rkisp_update_regs(dev, DUAL_CROP_M_H_OFFS, DUAL_CROP_S_V_SIZE); rkisp_update_regs(dev, ISP_ACQ_PROP, DUAL_CROP_CTRL); - rkisp_update_regs(dev, MAIN_RESIZE_SCALE_HY, MI_WR_CTRL); - rkisp_update_regs(dev, SELF_RESIZE_SCALE_HY, MAIN_RESIZE_CTRL); - rkisp_update_regs(dev, ISP_GAMMA_OUT_CTRL, SELF_RESIZE_CTRL); + rkisp_update_regs(dev, SELF_RESIZE_SCALE_HY, MI_WR_CTRL); + rkisp_update_regs(dev, ISP32_BP_RESIZE_SCALE_HY, SELF_RESIZE_CTRL); + rkisp_update_regs(dev, MAIN_RESIZE_SCALE_HY, ISP32_BP_RESIZE_CTRL); + rkisp_update_regs(dev, ISP_GAMMA_OUT_CTRL, MAIN_RESIZE_CTRL); rkisp_update_regs(dev, MI_RD_CTRL2, ISP_LSC_CTRL); - rkisp_update_regs(dev, MI_MP_WR_Y_BASE, MI_MP_WR_Y_LLENGTH); + rkisp_update_regs(dev, MI_MP_WR_Y_BASE, MI_WR_CTRL2 - 4); rkisp_update_regs(dev, ISP_LSC_XGRAD_01, ISP_RAWAWB_RAM_DATA); if (dev->isp_ver == ISP_V20 && (rkisp_read(dev, ISP_DHAZ_CTRL, false) & ISP_DHAZ_ENMUX || From f727d3ad8e73bf0af93f81b8ab137a67193cec71 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Tue, 30 Nov 2021 20:56:10 +0800 Subject: [PATCH 03/12] drm/fourcc: Add definitions for Rockchip vendor and VPU tiled format This introduces specific definitions for vendor Rockchip and its associated tiled format modifier. This modifier is used for the output format of the Video/JPEG Decoder, that can be imported directly with the VOP2. Signed-off-by: Andy Yan Signed-off-by: Sandy Huang Change-Id: I03c1a51af5fd8bc0702209ae216c4706b4101c49 --- include/uapi/drm/drm_fourcc.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 5b5db0381729..bedc59d650ae 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -334,6 +334,7 @@ extern "C" { #define DRM_FORMAT_MOD_VENDOR_ARM 0x08 #define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09 #define DRM_FORMAT_MOD_VENDOR_AMLOGIC 0x0a +#define DRM_FORMAT_MOD_VENDOR_ROCKCHIP 0x0b /* add more to the end as needed */ @@ -1058,6 +1059,15 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) */ #define AMLOGIC_FBC_OPTION_MEM_SAVING (1ULL << 0) +#define ROCKCHIP_TILED_BLOCK_SIZE_MASK 0xf +#define ROCKCHIP_TILED_BLOCK_SIZE_8x8 (1ULL) +#define ROCKCHIP_TILED_BLOCK_SIZE_4x4_MODE0 (2ULL) +#define ROCKCHIP_TILED_BLOCK_SIZE_4x4_MODE1 (3ULL) + +#define DRM_FORMAT_MOD_ROCKCHIP_TILED(_mode) fourcc_mod_code(ROCKCHIP, _mode) + +#define IS_ROCKCHIP_TILED_MOD(val) (((val) >> 56) == DRM_FORMAT_MOD_VENDOR_ROCKCHIP) + #if defined(__cplusplus) } #endif From 7a616cbc2fb5e247ba53188cde9481eed5464c5f Mon Sep 17 00:00:00 2001 From: William Wu Date: Mon, 10 Oct 2022 11:23:40 +0800 Subject: [PATCH 04/12] usb: host: ehci-platform: fix companion-device leak for rockchip Make sure do drop the reference taken to the companion device during probe/remove/resume. Fixes: 68850661b51e ("usb: host: ehci-platform: Add device_link between the ehci and companion") Signed-off-by: William Wu Change-Id: I0bbfe77987a1c11bfaa5006d98a56480ff16224f --- drivers/usb/host/ehci-platform.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index e6f0871375b9..51da2e36f883 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -422,6 +422,7 @@ static int ehci_platform_probe(struct platform_device *dev) if (companion_dev) { link = device_link_add(companion_dev, hcd->self.controller, DL_FLAG_STATELESS); + put_device(companion_dev); if (!link) { dev_err(&dev->dev, "Unable to link %s\n", dev_name(companion_dev)); @@ -473,8 +474,10 @@ static int ehci_platform_remove(struct platform_device *dev) if (of_device_is_compatible(dev->dev.of_node, "rockchip,rk3588-ehci")) { companion_dev = usb_of_get_companion_dev(hcd->self.controller); - if (companion_dev) + if (companion_dev) { device_link_remove(companion_dev, hcd->self.controller); + put_device(companion_dev); + } } usb_remove_hcd(hcd); @@ -535,8 +538,9 @@ static int __maybe_unused ehci_platform_resume(struct device *dev) } companion_dev = usb_of_get_companion_dev(hcd->self.controller); - if (companion_dev && !device_is_dependent(hcd->self.controller, companion_dev)) { - device_pm_wait_for_dev(hcd->self.controller, companion_dev); + if (companion_dev) { + if (!device_is_dependent(hcd->self.controller, companion_dev)) + device_pm_wait_for_dev(hcd->self.controller, companion_dev); put_device(companion_dev); } From 9af1805a1b5dc458cbf8495b3dd62ea5e540c0fc Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Tue, 11 Oct 2022 10:35:40 +0800 Subject: [PATCH 05/12] ARM: dts: rockchip: add rv1103g-battery-ipc-v11.dts diff rv1103g_bat_ipc_demo_v11 with rv1103g_bat_ipc_demo_v10 1. camera sensor use SC3338 2. remove WiFi's PA 3. control lux_en(GPIO3_A2) inversely Signed-off-by: Weiwen Chen Change-Id: I57b9dd35a7cddc5869d385412d47112c3b9a6222 --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/rv1103g-battery-ipc-v11.dts | 329 ++++++++++++++++++ 2 files changed, 330 insertions(+) create mode 100644 arch/arm/boot/dts/rv1103g-battery-ipc-v11.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 5212e7c0c8b0..92ea252c13a1 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -973,6 +973,7 @@ dtb-$(CONFIG_ARCH_RENESAS) += \ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rv1103g-38x38-ipc-v10.dtb \ rv1103g-battery-ipc-v10.dtb \ + rv1103g-battery-ipc-v11.dtb \ rv1103g-evb-v10.dtb \ rv1103g-rmsl311-dloc-sl-v10.dtb \ rv1103g-scaner-v10.dtb \ diff --git a/arch/arm/boot/dts/rv1103g-battery-ipc-v11.dts b/arch/arm/boot/dts/rv1103g-battery-ipc-v11.dts new file mode 100644 index 000000000000..f582694226c3 --- /dev/null +++ b/arch/arm/boot/dts/rv1103g-battery-ipc-v11.dts @@ -0,0 +1,329 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; + +#include "rv1103.dtsi" +#include "rv1106-evb.dtsi" +#include "rv1106-thunder-boot-spi-nor.dtsi" + +/ { + model = "Rockchip RV1103G Battery IPC V11 Board"; + compatible = "rockchip,rv1103g-battery-ipc-v11", "rockchip,rv1103"; + + aliases { + /delete-property/ csi2dphy1; + /delete-property/ csi2dphy2; + /delete-property/ ethernet0; + /delete-property/ i2c0; + /delete-property/ i2c1; + /delete-property/ i2c2; + /delete-property/ i2c3; + /delete-property/ mmc0; + /delete-property/ mmc1; + /delete-property/ pwm0; + /delete-property/ pwm1; + /delete-property/ pwm2; + /delete-property/ pwm3; + /delete-property/ pwm4; + /delete-property/ pwm5; + /delete-property/ pwm6; + /delete-property/ pwm7; + /delete-property/ pwm8; + /delete-property/ pwm9; + /delete-property/ rkcif_mipi_lvds1; + /delete-property/ serial0; + /delete-property/ serial1; + /delete-property/ serial3; + /delete-property/ serial4; + /delete-property/ serial5; + /delete-property/ spi0; + /delete-property/ spi1; + }; + + chosen { + bootargs = "loglevel=0 rootfstype=erofs rootflags=dax console=ttyFIQ0 root=/dev/rd0 snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0 driver_async_probe=dwmmc_rockchip storagemedia=mtd androidboot.storagemedia=mtd androidboot.mode=normal"; + }; + + acodec_sound: acodec-sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "rv1103-acodec"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,cpu { + sound-dai = <&i2s0_8ch>; + }; + simple-audio-card,codec { + sound-dai = <&acodec>; + }; + }; + + vcc_1v8: vcc-1v8 { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; +}; + +/delete-node/ &dsm; +/delete-node/ &i2c0; +/delete-node/ &i2c1; +/delete-node/ &i2c2; +/delete-node/ &i2c3; +/delete-node/ &emmc; +/delete-node/ &gmac; +/delete-node/ &pwm0; +/delete-node/ &pwm1; +/delete-node/ &pwm2; +/delete-node/ &pwm3; +/delete-node/ &pwm4; +/delete-node/ &pwm5; +/delete-node/ &pwm6; +/delete-node/ &pwm7; +/delete-node/ &pwm8; +/delete-node/ &pwm9; +/delete-node/ &rkcif_dvp; +/delete-node/ &rkcif_dvp_sditf; +/delete-node/ &rkcif_mipi_lvds1; +/delete-node/ &rkcif_mipi_lvds1_sditf; +/delete-node/ &sdmmc; +/delete-node/ &spi0; +/delete-node/ &spi1; +/delete-node/ &uart0; +/delete-node/ &uart1; +/delete-node/ &uart3; +/delete-node/ &uart4; +/delete-node/ &uart5; + +&acodec { + #sound-dai-cells = <0>; + pa-ctl-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&csi2_dphy_hw { + status = "okay"; +}; + +&csi2_dphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + csi_dphy_input0: endpoint@0 { + reg = <0>; + remote-endpoint = <&sc3338_out>; + data-lanes = <1 2>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csi_dphy_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_csi2_input>; + }; + }; + }; +}; + +&fiq_debugger { + rockchip,baudrate = <1500000>; + pinctrl-names = "default"; + pinctrl-0 = <&uart2m1_xfer>; +}; + +&i2c4 { + rockchip,amp-shared; + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c4m2_xfer>; + status = "okay"; + + sc3338: sc3338@30 { + compatible = "smartsens,sc3338"; + status = "okay"; + reg = <0x30>; + clocks = <&cru MCLK_REF_MIPI0>; + clock-names = "xvclk"; + pwdn-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipi_refclk_out0>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "FKO1"; + rockchip,camera-module-lens-name = "30IRC-F16"; + port { + sc3338_out: endpoint { + remote-endpoint = <&csi_dphy_input0>; + data-lanes = <1 2>; + }; + }; + }; +}; + +&i2s0_8ch { + #sound-dai-cells = <0>; + status = "okay"; +}; + +&mailbox { + status = "okay"; +}; + +&memory { + reg = <0x00000000 0x04000000>; +}; + +&mipi0_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csi_dphy_output>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in>; + }; + }; + }; +}; + +&pwm10 { + status = "okay"; +}; + +&pwm11 { + status = "okay"; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_mipi_lvds { + status = "okay"; + + memory-region-thunderboot = <&rkisp_thunderboot>; + pinctrl-names = "default"; + pinctrl-0 = <&mipi_pins>; + port { + /* MIPI CSI-2 endpoint */ + cif_mipi_in: endpoint { + remote-endpoint = <&mipi_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds_sditf { + status = "okay"; + + port { + /* MIPI CSI-2 endpoint */ + mipi_lvds_sditf: endpoint { + remote-endpoint = <&isp_in>; + }; + }; +}; + +&rkisp { + status = "okay"; +}; + +&rkisp_vir0 { + status = "okay"; + + port@0 { + isp_in: endpoint { + remote-endpoint = <&mipi_lvds_sditf>; + }; + }; +}; + +&saradc { + status = "okay"; + vref-supply = <&vcc_1v8>; +}; + +&sdio { + max-frequency = <30000000>; + no-sd; + no-mmc; + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + keep-power-in-suspend; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1m1_cmd &sdmmc1m1_clk &sdmmc1m1_bus4>; + no-prescan-powerup; + post-power-on-delay-ms = <0>; + status = "okay"; +}; + +&sfc { + assigned-clocks = <&cru SCLK_SFC>; + assigned-clock-rates = <125000000>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <125000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&thunder_boot_service { + status = "okay"; +}; + +&rkisp_thunderboot { + /* reg's offset MUST match with RTOS */ + /* + * vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num) + * e.g. 2304x1296: 0xf30000 + */ + reg = <0x00860000 0xf30000>; +}; + +&ramdisk_r { + reg = <0x1790000 (10 * 0x00100000)>; +}; + +&ramdisk_c { + reg = <0x2190000 (5 * 0x00100000)>; +}; From d8db0c1fa4ae5dec6b4e54716fad3b8fc3af2830 Mon Sep 17 00:00:00 2001 From: William Wu Date: Mon, 10 Oct 2022 11:27:24 +0800 Subject: [PATCH 06/12] phy: rockchip: inno-usb2: fix phy reset during power on for rk3588 The RK3588 USB2 PHY provides CLK12MOHCI and CLK48MOHCI to OHCI controllers, and the two clocks are turned off upon PHY reset, therefore it shouldn't access OHCI Controller if USB2 PHY in reset. However, during the system PM resume, the current USB2 PHY power on sequence with PHY reset operation has potential risk that reset PHY accidentally when OHCI platform resume access OHCI Controller, and cause system hung. The reason is EHCI/OHCI controllers resume ordering on RK3588. In outline form, the hcd_bus_resume() of EHCI and the ohci_resume() of OHCI operating concurrently on different CPUs perform the following actions: CPU 0 CPU 1 ---------------------------- --------------------------------- async_resume() usb_resume() hcd_bus_resume() -- EHCI usb_phy_roothub_resume() phy_power_on() rockchip_usb2phy_power_on() ohci_platform_resume() rockchip_usb2phy_reset() ohci_resume() assert phy reset ... udelay(10); ohci_readl or ohci_writel This patch fixes USB2 PHY reset during power on for RK3588, only do USB2 PHY reset for RK3588 USB OTG0 and OTG1, because their 'common_on_n' bit can be set to 1'b1 (aka REFCLK_LOGIC, Bias, and PLL blocks are powered down) in PM runtime process. And keep the 'common_on_n' to 1'b0 for RK3588 USB2 HOST0 and HOST1, thus we don't need to do PHY reset during power on for them. This patch doesn't increase the USB2 PHY power consumption, because the USB2 HOST0 and HOST1 don't support PM runtime management, so actually the PHY PLL blocks of USB2 HOST0 and HOST1 are always powered on. Signed-off-by: William Wu Change-Id: Ia0121a7c49bef4f0f3a1fb11a810e4ef95b29982 --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 238668ea5394..2b3dec923248 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -853,9 +853,12 @@ static int rockchip_usb2phy_power_on(struct phy *phy) * please keep the common_on_n 1'b0 to set these blocks * remain powered. */ - ret = rockchip_usb2phy_reset(rphy); - if (ret) - goto unlock; + if (rport->port_id == USB2PHY_PORT_OTG && + of_device_is_compatible(rphy->dev->of_node, "rockchip,rk3588-usb2phy")) { + ret = rockchip_usb2phy_reset(rphy); + if (ret) + goto unlock; + } /* waiting for the utmi_clk to become stable */ usleep_range(1500, 2000); @@ -3665,7 +3668,7 @@ static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = { .reg = 0x8000, .num_ports = 1, .phy_tuning = rk3588_usb2phy_tuning, - .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, + .clkout_ctl = { 0x0000, 0, 0, 0, 0 }, .ls_filter_con = { 0x0040, 19, 0, 0x30100, 0x00020 }, .port_cfgs = { [USB2PHY_PORT_HOST] = { @@ -3687,7 +3690,7 @@ static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = { .reg = 0xc000, .num_ports = 1, .phy_tuning = rk3588_usb2phy_tuning, - .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, + .clkout_ctl = { 0x0000, 0, 0, 0, 0 }, .ls_filter_con = { 0x0040, 19, 0, 0x30100, 0x00020 }, .port_cfgs = { [USB2PHY_PORT_HOST] = { From 6cfa171d7f1b597d86b607db055a65d3847eb7c3 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Wed, 12 Oct 2022 15:06:16 +0800 Subject: [PATCH 07/12] media: rockchip: isp: fix hdr config for unite multi sensor Change-Id: Ia164e14291b6be0e48ab5cd02c40fbaf9bb75ff8 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/isp_params_v3x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/rockchip/isp/isp_params_v3x.c b/drivers/media/platform/rockchip/isp/isp_params_v3x.c index 6080f5a36aea..9f897d218417 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v3x.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v3x.c @@ -4104,6 +4104,10 @@ void __isp_config_hdrshd(struct rkisp_isp_params_vdev *params_vdev) struct rkisp_isp_params_val_v3x *priv_val = (struct rkisp_isp_params_val_v3x *)params_vdev->priv_val; + if (params_vdev->dev->hw_dev->is_unite) { + ops->hdrmge_config(params_vdev, &priv_val->last_hdrmge, RKISP_PARAMS_SHD, 1); + ops->hdrdrc_config(params_vdev, &priv_val->last_hdrdrc, RKISP_PARAMS_SHD, 1); + } ops->hdrmge_config(params_vdev, &priv_val->last_hdrmge, RKISP_PARAMS_SHD, 0); ops->hdrdrc_config(params_vdev, &priv_val->last_hdrdrc, RKISP_PARAMS_SHD, 0); } From d6835708d6fe443ba85aae72fa1a973a9abf4e97 Mon Sep 17 00:00:00 2001 From: Yongzhen Date: Wed, 12 Oct 2022 16:29:01 +0800 Subject: [PATCH 08/12] media: i2c: sc200ai fix rk_cam_fps mistake Fixes: 266443eda946 ("media: i2c: sc200ai support get config from cmdline for thunderboot") Signed-off-by: Yongzhen Change-Id: I9624bd9f36795e1fd6802990b17173c68be63bb7 --- drivers/media/i2c/sc200ai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/sc200ai.c b/drivers/media/i2c/sc200ai.c index d26f576714b2..0eca27f3b01c 100644 --- a/drivers/media/i2c/sc200ai.c +++ b/drivers/media/i2c/sc200ai.c @@ -1948,7 +1948,7 @@ static int __init __maybe_unused rk_cam_fps_setup(char *str) __setup("rk_cam_hdr=", rk_cam_hdr_setup); __setup("rk_cam_w=", rk_cam_w_setup); __setup("rk_cam_h=", rk_cam_h_setup); -__setup("rk_cam_fps", rk_cam_fps_setup); +__setup("rk_cam_fps=", rk_cam_fps_setup); static void find_terminal_resolution(struct sc200ai *sc200ai) { From 7d566067060549844ed3c827ce24204d5e84000d Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Tue, 11 Oct 2022 09:57:06 +0800 Subject: [PATCH 09/12] media: rockchip: isp: make sure to free buf after isp stop Change-Id: Ie9dd6fa1c482103d5961ff5acda07461773cf735 Signed-off-by: Cai YiWei --- .../media/platform/rockchip/isp/isp_params.c | 11 ++- .../platform/rockchip/isp/isp_params_v32.c | 91 ++++++++++++++----- 2 files changed, 73 insertions(+), 29 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/isp_params.c b/drivers/media/platform/rockchip/isp/isp_params.c index 1103d3c67dd6..db82e4626bed 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.c +++ b/drivers/media/platform/rockchip/isp/isp_params.c @@ -272,12 +272,8 @@ static int rkisp_params_fh_open(struct file *filp) static int rkisp_params_fop_release(struct file *file) { struct rkisp_isp_params_vdev *params = video_drvdata(file); - struct video_device *vdev = video_devdata(file); int ret; - if (file->private_data == vdev->queue->owner && params->ops->fop_release) - params->ops->fop_release(params); - ret = vb2_fop_release(file); if (!ret) v4l2_pipeline_pm_put(¶ms->vnode.vdev.entity); @@ -408,14 +404,19 @@ void rkisp_params_set_meshbuf_size(struct rkisp_isp_params_vdev *params_vdev, void rkisp_params_meshbuf_free(struct rkisp_isp_params_vdev *params_vdev, u64 id) { - if (params_vdev->ops->free_meshbuf) + /* isp working no to free buf */ + if (params_vdev->ops->free_meshbuf && + !(params_vdev->dev->isp_state & ISP_START)) params_vdev->ops->free_meshbuf(params_vdev, id); } void rkisp_params_stream_stop(struct rkisp_isp_params_vdev *params_vdev) { + /* isp stop to free buf */ if (params_vdev->ops->stream_stop) params_vdev->ops->stream_stop(params_vdev); + if (params_vdev->ops->fop_release) + params_vdev->ops->fop_release(params_vdev); } bool rkisp_params_check_bigmode(struct rkisp_isp_params_vdev *params_vdev) diff --git a/drivers/media/platform/rockchip/isp/isp_params_v32.c b/drivers/media/platform/rockchip/isp/isp_params_v32.c index 12b276c1e9e6..cebb4eefca65 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v32.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v32.c @@ -4064,6 +4064,8 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev, priv_val->buf_3dlut_idx = 0; for (i = 0; i < ISP32_3DLUT_BUF_NUM; i++) { + if (priv_val->buf_3dlut[i].mem_priv) + continue; priv_val->buf_3dlut[i].is_need_vaddr = true; priv_val->buf_3dlut[i].size = ISP32_3DLUT_BUF_SIZE; ret = rkisp_alloc_buffer(dev, &priv_val->buf_3dlut[i]); @@ -4084,6 +4086,7 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev, u32 h = ALIGN(isp_sdev->in_crop.height, 16); u32 val, wrap_line, wsize, div; dma_addr_t dma_addr; + bool is_alloc; priv_val->is_lo8x8 = (!new_params->others.bay3d_cfg.lo4x8_en && !new_params->others.bay3d_cfg.lo4x4_en); @@ -4102,11 +4105,20 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev, wsize *= 2; div = is_bwopt_dis ? 1 : 2; val = ALIGN(wsize * h / div, 16); - priv_val->buf_3dnr_iir.size = val; - ret = rkisp_alloc_buffer(dev, &priv_val->buf_3dnr_iir); - if (ret) { - dev_err(dev->dev, "alloc bay3d iir buf fail:%d\n", ret); - goto err_3dnr; + is_alloc = true; + if (priv_val->buf_3dnr_iir.mem_priv) { + if (val > priv_val->buf_3dnr_iir.size) + rkisp_free_buffer(dev, &priv_val->buf_3dnr_iir); + else + is_alloc = false; + } + if (is_alloc) { + priv_val->buf_3dnr_iir.size = val; + ret = rkisp_alloc_buffer(dev, &priv_val->buf_3dnr_iir); + if (ret) { + dev_err(dev->dev, "alloc bay3d iir buf fail:%d\n", ret); + goto err_3dnr; + } } isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_IIR_WR_SIZE); val = priv_val->buf_3dnr_iir.dma_addr; @@ -4117,12 +4129,21 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev, val = w * h / div; /* pixel to Byte and align */ val = ALIGN(val * 2, 16); - priv_val->buf_3dnr_ds.size = val; - ret = rkisp_alloc_buffer(dev, &priv_val->buf_3dnr_ds); - if (ret) { - rkisp_free_buffer(dev, &priv_val->buf_3dnr_iir); - dev_err(dev->dev, "alloc bay3d ds buf fail:%d\n", ret); - goto err_3dnr; + is_alloc = true; + if (priv_val->buf_3dnr_ds.mem_priv) { + if (val > priv_val->buf_3dnr_ds.size) + rkisp_free_buffer(dev, &priv_val->buf_3dnr_ds); + else + is_alloc = false; + } + if (is_alloc) { + priv_val->buf_3dnr_ds.size = val; + ret = rkisp_alloc_buffer(dev, &priv_val->buf_3dnr_ds); + if (ret) { + rkisp_free_buffer(dev, &priv_val->buf_3dnr_iir); + dev_err(dev->dev, "alloc bay3d ds buf fail:%d\n", ret); + goto err_3dnr; + } } isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_DS_WR_SIZE); val = priv_val->buf_3dnr_ds.dma_addr; @@ -4139,8 +4160,16 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev, wsize = ALIGN(wsize * 2, 16); div = is_bwopt_dis ? 1 : 2; val = ALIGN(wsize * wrap_line / div, 16); - priv_val->buf_3dnr_cur.size = val; - if (val > dev->hw_dev->sram.size) { + is_alloc = true; + if (priv_val->buf_3dnr_cur.mem_priv) { + if (val > priv_val->buf_3dnr_cur.size || + val < dev->hw_dev->sram.size) + rkisp_free_buffer(dev, &priv_val->buf_3dnr_cur); + else + is_alloc = false; + } + if (val > dev->hw_dev->sram.size && is_alloc) { + priv_val->buf_3dnr_cur.size = val; ret = rkisp_alloc_buffer(dev, &priv_val->buf_3dnr_cur); if (ret) { rkisp_free_buffer(dev, &priv_val->buf_3dnr_iir); @@ -4150,9 +4179,11 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev, } dma_addr = priv_val->buf_3dnr_cur.dma_addr; priv_val->is_sram = false; - } else { + } else if (val <= dev->hw_dev->sram.size) { dma_addr = dev->hw_dev->sram.dma_addr; priv_val->is_sram = true; + } else { + dma_addr = priv_val->buf_3dnr_cur.dma_addr; } isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_CUR_WR_SIZE); isp3_param_write(params_vdev, val, ISP32_MI_BAY3D_CUR_RD_SIZE); @@ -4443,6 +4474,7 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, u32 mesh_h = meshsize->meas_height; u32 mesh_size, buf_size; int i, ret, buf_cnt = meshsize->buf_cnt; + bool is_alloc; priv_val = params_vdev->priv_val; if (!priv_val) { @@ -4475,16 +4507,28 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, buf->is_need_vaddr = true; buf->is_need_dbuf = true; buf->is_need_dmafd = true; - buf->size = buf_size; - ret = rkisp_alloc_buffer(params_vdev->dev, buf); - if (ret) { - dev_err(dev, "%s failed\n", __func__); - goto err; + is_alloc = true; + if (buf->mem_priv) { + if (buf_size > buf->size) { + rkisp_free_buffer(params_vdev->dev, buf); + } else { + is_alloc = false; + buf->dma_fd = dma_buf_fd(buf->dbuf, O_CLOEXEC); + if (buf->dma_fd < 0) + goto err; + } + } + if (is_alloc) { + buf->size = buf_size; + ret = rkisp_alloc_buffer(params_vdev->dev, buf); + if (ret) { + dev_err(dev, "%s failed\n", __func__); + goto err; + } + mesh_head = (struct isp2x_mesh_head *)buf->vaddr; + mesh_head->stat = MESH_BUF_INIT; + mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); } - - mesh_head = (struct isp2x_mesh_head *)buf->vaddr; - mesh_head->stat = MESH_BUF_INIT; - mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); buf++; } @@ -4541,7 +4585,6 @@ rkisp_params_set_meshbuf_size_v32(struct rkisp_isp_params_vdev *params_vdev, { struct rkisp_meshbuf_size *meshsize = size; - rkisp_deinit_mesh_buf(params_vdev, meshsize->module_id); rkisp_init_mesh_buf(params_vdev, meshsize); } From 494310d19973390e97c81d732c95ec8d227192c0 Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Tue, 27 Sep 2022 11:47:47 +0800 Subject: [PATCH 10/12] video: rockchip: mpp: fix the decoding buf is released issue Signed-off-by: Yandong Lin Change-Id: I66906651dc3e80470d0873cae7fce8ee1e662b0a --- drivers/video/rockchip/mpp/mpp_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/rockchip/mpp/mpp_iommu.c b/drivers/video/rockchip/mpp/mpp_iommu.c index 067c91a78034..eb91b5d82b9b 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.c +++ b/drivers/video/rockchip/mpp/mpp_iommu.c @@ -97,7 +97,7 @@ mpp_dma_remove_extra_buffer(struct mpp_dma_session *dma) oldest = buffer; } } - if (oldest) + if (oldest && kref_read(&oldest->ref) <= 1) kref_put(&oldest->ref, mpp_dma_release_buffer); mutex_unlock(&dma->list_mutex); } From 0e1556a3397351dd0d187408b178bd512345a87a Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Thu, 13 Oct 2022 17:44:39 +0800 Subject: [PATCH 11/12] ARM: rv1106-evb.config: enable CONFIG_NVMEM_SYSFS Signed-off-by: Weiwen Chen Change-Id: I83ecba98d3d31424e479db46f428cd4bba799ad8 --- arch/arm/configs/rv1106-evb.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/configs/rv1106-evb.config b/arch/arm/configs/rv1106-evb.config index 178d7b60a82d..7261bcf6be6a 100644 --- a/arch/arm/configs/rv1106-evb.config +++ b/arch/arm/configs/rv1106-evb.config @@ -23,6 +23,7 @@ CONFIG_MTD_UBI=y CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y +CONFIG_NVMEM_SYSFS=y CONFIG_RK_CMA_PROCFS=y CONFIG_RK_DMABUF_PROCFS=y CONFIG_RK_MEMBLOCK_PROCFS=y @@ -302,6 +303,7 @@ CONFIG_DRM_KMS_HELPER=y # CONFIG_DRM_MAXIM_MAX96745 is not set # CONFIG_DRM_MAXIM_MAX96752F is not set # CONFIG_DRM_MAXIM_MAX96755F is not set +# CONFIG_DRM_MAXIM_MAX96776 is not set # CONFIG_DRM_MCDE is not set # CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set # CONFIG_DRM_MXSFB is not set @@ -315,6 +317,7 @@ CONFIG_DRM_PANEL_BRIDGE=y # CONFIG_DRM_PANEL_LG_LB035Q02 is not set # CONFIG_DRM_PANEL_LG_LG4573 is not set # CONFIG_DRM_PANEL_LVDS is not set +# CONFIG_DRM_PANEL_MAXIM_DESERIALIZER is not set # CONFIG_DRM_PANEL_NEC_NL8048HL11 is not set # CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set # CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set @@ -702,6 +705,7 @@ CONFIG_SPI_MEM=y # CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PL022 is not set CONFIG_SPI_ROCKCHIP=y +# CONFIG_SPI_ROCKCHIP_MISCDEV is not set CONFIG_SPI_ROCKCHIP_SFC=y # CONFIG_SPI_SC18IS602 is not set # CONFIG_SPI_SIFIVE is not set From 70680c754ee59eb1768f398325e60385790872e5 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Wed, 12 Oct 2022 22:49:32 +0800 Subject: [PATCH 12/12] drivers: rkflash: Using kmap_atomic to build page address mapping The virtual address of allocated __GFP_HIGHMEM pages is not mapped, Using kmap_atomic to build it, or it will failed like: Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = 50ec00c8 [00000000] *pgd=00000000 Internal error: Oops: 817 [#1] PREEMPT SMP ARM Modules linked in: CPU: 3 PID: 67 Comm: rkflash Not tainted 4.19.111 #67 Hardware name: Generic DT based system PC is at memcpy+0x50/0x330 LR is at 0x61640a68 Change-Id: I0cde9012d29e49d9ba751cb019ccfa784c01b7c7 Signed-off-by: Jon Lin --- drivers/rkflash/rkflash_blk.c | 67 ++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/drivers/rkflash/rkflash_blk.c b/drivers/rkflash/rkflash_blk.c index 5d09dbc63a62..14a6c0a512d8 100644 --- a/drivers/rkflash/rkflash_blk.c +++ b/drivers/rkflash/rkflash_blk.c @@ -223,20 +223,26 @@ static int rkflash_blk_xfer(struct flash_blk_dev *dev, static int rkflash_blk_check_buffer_align(struct request *req, char **pbuf) { int nr_vec = 0; - struct bio_vec bvec; + struct bio_vec bv; struct req_iterator iter; char *buffer; void *firstbuf = 0; char *nextbuffer = 0; - rq_for_each_segment(bvec, req, iter) { - buffer = page_address(bvec.bv_page) + bvec.bv_offset; + rq_for_each_segment(bv, req, iter) { + /* high mem return 0 and using kernel buffer */ + if (PageHighMem(bv.bv_page)) + return 0; + + buffer = page_address(bv.bv_page) + bv.bv_offset; + if (!buffer) + return 0; if (!firstbuf) firstbuf = buffer; nr_vec++; if (nextbuffer && nextbuffer != buffer) return 0; - nextbuffer = buffer + bvec.bv_len; + nextbuffer = buffer + bv.bv_len; } *pbuf = firstbuf; return 1; @@ -247,12 +253,11 @@ static blk_status_t do_blktrans_all_request(struct flash_blk_ops *tr, struct request *req) { unsigned long block, nsect; - char *buf = NULL; + char *buf = NULL, *page_buf; struct req_iterator rq_iter; struct bio_vec bvec; int ret; unsigned long totle_nsect; - unsigned long rq_len = 0; block = blk_rq_pos(req); nsect = blk_rq_cur_bytes(req) >> 9; @@ -281,11 +286,13 @@ static blk_status_t do_blktrans_all_request(struct flash_blk_ops *tr, char *p = buf; rq_for_each_segment(bvec, req, rq_iter) { - memcpy(page_address(bvec.bv_page) + - bvec.bv_offset, - p, - bvec.bv_len); + page_buf = kmap_atomic(bvec.bv_page); + memcpy(page_buf + + bvec.bv_offset, + p, + bvec.bv_len); p += bvec.bv_len; + kunmap_atomic(page_buf); } } @@ -296,30 +303,26 @@ static blk_status_t do_blktrans_all_request(struct flash_blk_ops *tr, case REQ_OP_WRITE: rkflash_print_bio("%s write block=%lx nsec=%lx\n", __func__, block, totle_nsect); - rq_for_each_segment(bvec, req, rq_iter) { - if ((page_address(bvec.bv_page) + bvec.bv_offset) == (buf + rq_len)) { - rq_len += bvec.bv_len; - } else { - if (rq_len) { - ret = rkflash_blk_xfer(dev, - block, - rq_len >> 9, - buf, - REQ_OP_WRITE); - } - block += rq_len >> 9; - buf = (page_address(bvec.bv_page) + bvec.bv_offset); - rq_len = bvec.bv_len; + buf = mtd_read_temp_buffer; + rkflash_blk_check_buffer_align(req, &buf); + if (buf == mtd_read_temp_buffer) { + char *p = buf; + + rq_for_each_segment(bvec, req, rq_iter) { + page_buf = kmap_atomic(bvec.bv_page); + memcpy(p, + page_buf + + bvec.bv_offset, + bvec.bv_len); + p += bvec.bv_len; + kunmap_atomic(page_buf); } } - - if (rq_len) { - ret = rkflash_blk_xfer(dev, - block, - rq_len >> 9, - buf, - REQ_OP_WRITE); - } + ret = rkflash_blk_xfer(dev, + block, + totle_nsect, + buf, + REQ_OP_WRITE); if (ret) return BLK_STS_IOERR;