From 1a5d2a8da4236bbde41b68749af0c28ac290a999 Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Thu, 8 Sep 2022 14:22:02 +0800 Subject: [PATCH 001/204] media: i2c: change sc3338 gain times from 1000 to 128 Signed-off-by: Su Yuefu Change-Id: I7bc0aa6bea913a4d5c64aec5a595d9c0960b83cf --- drivers/media/i2c/sc3338.c | 43 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/media/i2c/sc3338.c b/drivers/media/i2c/sc3338.c index 3cec60ed2490..b63e4bcbfaea 100644 --- a/drivers/media/i2c/sc3338.c +++ b/drivers/media/i2c/sc3338.c @@ -417,54 +417,55 @@ static int sc3338_set_gain_reg(struct sc3338 *sc3338, u32 gain) { struct i2c_client *client = sc3338->client; u32 coarse_again = 0, coarse_dgain = 0, fine_dgain = 0; - int ret = 0; + int ret = 0, gain_factor; if (gain < 128) gain = 128; else if (gain > SC3338_GAIN_MAX) gain = SC3338_GAIN_MAX; - if (gain < 1520) { + gain_factor = gain * 1000 / 128; + if (gain_factor < 1520) { coarse_again = 0x00; coarse_dgain = 0x00; - fine_dgain = gain * 128 / 1000; - } else if (gain < 3040) { + fine_dgain = gain_factor * 128 / 1000; + } else if (gain_factor < 3040) { coarse_again = 0x40; coarse_dgain = 0x00; - fine_dgain = gain * 128 / 1520; - } else if (gain < 6080) { + fine_dgain = gain_factor * 128 / 1520; + } else if (gain_factor < 6080) { coarse_again = 0x48; coarse_dgain = 0x00; - fine_dgain = gain * 128 / 3040; - } else if (gain < 12160) { + fine_dgain = gain_factor * 128 / 3040; + } else if (gain_factor < 12160) { coarse_again = 0x49; coarse_dgain = 0x00; - fine_dgain = gain * 128 / 6080; - } else if (gain < 24320) { + fine_dgain = gain_factor * 128 / 6080; + } else if (gain_factor < 24320) { coarse_again = 0x4b; coarse_dgain = 0x00; - fine_dgain = gain * 128 / 12160; - } else if (gain < 48640) { + fine_dgain = gain_factor * 128 / 12160; + } else if (gain_factor < 48640) { coarse_again = 0x4f; coarse_dgain = 0x00; - fine_dgain = gain * 128 / 24320; - } else if (gain < 48640 * 2) { + fine_dgain = gain_factor * 128 / 24320; + } else if (gain_factor < 48640 * 2) { //open dgain begin max digital gain 4X coarse_again = 0x5f; coarse_dgain = 0x00; - fine_dgain = gain * 128 / 48640; - } else if (gain < 48640 * 4) { + fine_dgain = gain_factor * 128 / 48640; + } else if (gain_factor < 48640 * 4) { coarse_again = 0x5f; coarse_dgain = 0x01; - fine_dgain = gain * 128 / 48640 / 2; - } else if (gain < 48640 * 8) { + fine_dgain = gain_factor * 128 / 48640 / 2; + } else if (gain_factor < 48640 * 8) { coarse_again = 0x5f; coarse_dgain = 0x03; - fine_dgain = gain * 128 / 48640 / 4; - } else if (gain < 48640 * 16) { + fine_dgain = gain_factor * 128 / 48640 / 4; + } else if (gain_factor < 48640 * 16) { coarse_again = 0x5f; coarse_dgain = 0x07; - fine_dgain = gain * 128 / 48640 / 8; + fine_dgain = gain_factor * 128 / 48640 / 8; } dev_dbg(&client->dev, "c_again: 0x%x, c_dgain: 0x%x, f_dgain: 0x%0x\n", coarse_again, coarse_dgain, fine_dgain); From adc69507ac3af9b140be45c86a10fbaf28dc28a4 Mon Sep 17 00:00:00 2001 From: Jianwei Zheng Date: Wed, 7 Sep 2022 10:06:00 +0800 Subject: [PATCH 002/204] phy: rockchip: inno-usb2: fix miss line irq for rk3588 RK3588 platform may miss line irq if the line state is not in SE0(D+ low, D- low) before usb controller call phy init function and enable line irq. To resolve this, when usb controller call phy init function, we can clear host_disconnect state if the line state is not in SE0 which means there is an usb device connected to the port. Signed-off-by: Jianwei Zheng Change-Id: Icb3f1abd790f16ddd66bbc098e0c06cc5d922d86 --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index c234b9ddedad..238668ea5394 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -746,6 +746,7 @@ static int rockchip_usb2phy_init(struct phy *phy) struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); int ret = 0; + unsigned int ul, ul_mask; mutex_lock(&rport->mutex); @@ -779,7 +780,12 @@ static int rockchip_usb2phy_init(struct phy *phy) } } else if (rport->port_id == USB2PHY_PORT_HOST) { if (rport->port_cfg->disfall_en.offset) { - rport->host_disconnect = true; + ret = regmap_read(rphy->grf, rport->port_cfg->utmi_ls.offset, &ul); + if (ret < 0) + goto out; + ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend, + rport->port_cfg->utmi_ls.bitstart); + rport->host_disconnect = (ul & ul_mask) == 0 ? true : false; ret = rockchip_usb2phy_enable_host_disc_irq(rphy, rport, true); if (ret) { dev_err(rphy->dev, "failed to enable disconnect irq\n"); From e4e2628ccc564e87b9e2cef2c9e0900e50f9b8cd Mon Sep 17 00:00:00 2001 From: Jianlong Wang Date: Wed, 16 Mar 2022 19:04:10 +0800 Subject: [PATCH 003/204] Revert "ARM64: dts: rockchip: rk3326-evb-lp3-v10-linux: update panel" This reverts commit 11a0bfb97cb9bf50d5afb8819381d6be8312bd00. Signed-off-by: Jianlong Wang Change-Id: I953108f01466c5bd52ebc86046d07011dbabc857 --- .../dts/rockchip/rk3326-evb-lp3-v10-linux.dts | 258 ++++-------------- 1 file changed, 46 insertions(+), 212 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-linux.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-linux.dts index 8a93245b4880..9b9cc30c0f30 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-linux.dts @@ -214,12 +214,12 @@ reg = <0>; backlight = <&backlight>; power-supply = <&vcc18_lcd_n>; - prepare-delay-ms = <0>; - reset-delay-ms = <0>; - init-delay-ms = <80>; - enable-delay-ms = <0>; - disable-delay-ms = <10>; - unprepare-delay-ms = <60>; + prepare-delay-ms = <2>; + reset-delay-ms = <1>; + init-delay-ms = <20>; + enable-delay-ms = <120>; + disable-delay-ms = <50>; + unprepare-delay-ms = <20>; width-mm = <68>; height-mm = <121>; @@ -230,212 +230,46 @@ dsi,lanes = <4>; panel-init-sequence = [ - 39 00 04 ff 98 81 03 - 15 00 02 01 00 - 15 00 02 02 00 - 15 00 02 03 53 - 15 00 02 04 53 - 15 00 02 05 13 - 15 00 02 06 04 - 15 00 02 07 02 - 15 00 02 08 02 - 15 00 02 09 00 - 15 00 02 0a 00 - 15 00 02 0b 00 - 15 00 02 0c 00 - 15 00 02 0d 00 - 15 00 02 0e 00 - 15 00 02 0f 00 - - 15 00 02 10 00 - 15 00 02 11 00 - 15 00 02 12 00 - 15 00 02 13 00 - 15 00 02 14 00 - 15 00 02 15 08 - 15 00 02 16 10 - 15 00 02 17 00 - 15 00 02 18 08 - 15 00 02 19 00 - 15 00 02 1a 00 - 15 00 02 1b 00 - 15 00 02 1c 00 - 15 00 02 1d 00 - 15 00 02 1e c0 - 15 00 02 1f 80 - - 15 00 02 20 02 - 15 00 02 21 09 - 15 00 02 22 00 - 15 00 02 23 00 - 15 00 02 24 00 - 15 00 02 25 00 - 15 00 02 26 00 - 15 00 02 27 00 - 15 00 02 28 55 - 15 00 02 29 03 - 15 00 02 2a 00 - 15 00 02 2b 00 - 15 00 02 2c 00 - 15 00 02 2d 00 - 15 00 02 2e 00 - 15 00 02 2f 00 - - 15 00 02 30 00 - 15 00 02 31 00 - 15 00 02 32 00 - 15 00 02 33 00 - 15 00 02 34 04 - 15 00 02 35 05 - 15 00 02 36 05 - 15 00 02 37 00 - 15 00 02 38 3c - 15 00 02 39 35 - 15 00 02 3a 00 - 15 00 02 3b 40 - 15 00 02 3c 00 - 15 00 02 3d 00 - 15 00 02 3e 00 - 15 00 02 3f 00 - - 15 00 02 40 00 - 15 00 02 41 88 - 15 00 02 42 00 - 15 00 02 43 00 - 15 00 02 44 1f - - 15 00 02 50 01 - 15 00 02 51 23 - 15 00 02 52 45 - 15 00 02 53 67 - 15 00 02 54 89 - 15 00 02 55 ab - 15 00 02 56 01 - 15 00 02 57 23 - 15 00 02 58 45 - 15 00 02 59 67 - 15 00 02 5a 89 - 15 00 02 5b ab - 15 00 02 5c cd - 15 00 02 5d ef - 15 00 02 5e 03 - 15 00 02 5f 14 - - 15 00 02 60 15 - 15 00 02 61 0c - 15 00 02 62 0d - 15 00 02 63 0e - 15 00 02 64 0f - 15 00 02 65 10 - 15 00 02 66 11 - 15 00 02 67 08 - 15 00 02 68 02 - 15 00 02 69 0a - 15 00 02 6a 02 - 15 00 02 6b 02 - 15 00 02 6c 02 - 15 00 02 6d 02 - 15 00 02 6e 02 - 15 00 02 6f 02 - - 15 00 02 70 02 - 15 00 02 71 02 - 15 00 02 72 06 - 15 00 02 73 02 - 15 00 02 74 02 - 15 00 02 75 14 - 15 00 02 76 15 - 15 00 02 77 0f - 15 00 02 78 0e - 15 00 02 79 0d - 15 00 02 7a 0c - 15 00 02 7b 11 - 15 00 02 7c 10 - 15 00 02 7d 06 - 15 00 02 7e 02 - 15 00 02 7f 0a - - 15 00 02 80 02 - 15 00 02 81 02 - 15 00 02 82 02 - 15 00 02 83 02 - 15 00 02 84 02 - 15 00 02 85 02 - 15 00 02 86 02 - 15 00 02 87 02 - 15 00 02 88 08 - 15 00 02 89 02 - 15 00 02 8a 02 - - 39 00 04 ff 98 81 04 - 15 00 02 00 80 - 15 00 02 70 00 - 15 00 02 71 00 - 15 00 02 66 fe - 15 00 02 82 15 - 15 00 02 84 15 - 15 00 02 85 15 - 15 00 02 3a 24 - 15 00 02 32 ac - 15 00 02 8c 80 - 15 00 02 3c f5 - 15 00 02 88 33 - - 39 00 04 ff 98 81 01 - 15 00 02 22 0a - 15 00 02 31 00 - 15 00 02 53 78 - 15 00 02 50 5b - 15 00 02 51 5b - 15 00 02 60 20 - 15 00 02 61 00 - 15 00 02 62 0d - 15 00 02 63 00 - - 15 00 02 a0 00 - 15 00 02 a1 10 - 15 00 02 a2 1c - 15 00 02 a3 13 - 15 00 02 a4 15 - 15 00 02 a5 26 - 15 00 02 a6 1a - 15 00 02 a7 1d - 15 00 02 a8 67 - 15 00 02 a9 1c - 15 00 02 aa 29 - 15 00 02 ab 5b - 15 00 02 ac 26 - 15 00 02 ad 28 - 15 00 02 ae 5c - 15 00 02 af 30 - 15 00 02 b0 31 - 15 00 02 b1 2e - 15 00 02 b2 32 - 15 00 02 b3 00 - - 15 00 02 c0 00 - 15 00 02 c1 10 - 15 00 02 c2 1c - 15 00 02 c3 13 - 15 00 02 c4 15 - 15 00 02 c5 26 - 15 00 02 c6 1a - 15 00 02 c7 1d - 15 00 02 c8 67 - 15 00 02 c9 1c - 15 00 02 ca 29 - 15 00 02 cb 5b - 15 00 02 cc 26 - 15 00 02 cd 28 - 15 00 02 ce 5c - 15 00 02 cf 30 - 15 00 02 d0 31 - 15 00 02 d1 2e - 15 00 02 d2 32 - 15 00 02 d3 00 - 39 00 04 ff 98 81 00 - 05 00 01 11 - 05 01 01 29 + 05 fa 01 11 + 39 00 04 b9 f1 12 83 + 39 00 1c ba 33 81 05 f9 0e 0e 00 00 00 + 00 00 00 00 00 44 25 00 91 0a + 00 00 02 4f 01 00 00 37 + 15 00 02 b8 25 + 39 00 04 bf 02 11 00 + 39 00 0b b3 0c 10 0a 50 03 ff 00 00 00 + 00 + 39 00 0a c0 73 73 50 50 00 00 08 70 00 + 15 00 02 bc 46 + 15 00 02 cc 0b + 15 00 02 b4 80 + 39 00 04 b2 c8 12 30 + 39 00 0f e3 07 07 0b 0b 03 0b 00 00 00 + 00 ff 00 c0 10 + 39 00 0d c1 53 00 1e 1e 77 e1 cc dd 67 + 77 33 33 + 39 00 07 c6 00 00 ff ff 01 ff + 39 00 03 b5 09 09 + 39 00 03 b6 87 95 + 39 00 40 e9 c2 10 05 05 10 05 a0 12 31 + 23 3f 81 0a a0 37 18 00 80 01 + 00 00 00 00 80 01 00 00 00 48 + f8 86 42 08 88 88 80 88 88 88 + 58 f8 87 53 18 88 88 81 88 88 + 88 00 00 00 01 00 00 00 00 00 + 00 00 00 00 + 39 00 3e ea 00 1a 00 00 00 00 02 00 00 + 00 00 00 1f 88 81 35 78 88 88 + 85 88 88 88 0f 88 80 24 68 88 + 88 84 88 88 88 23 10 00 00 1c + 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 30 05 a0 00 00 + 00 00 + 39 00 23 e0 00 06 08 2a 31 3f 38 36 07 + 0c 0d 11 13 12 13 11 18 00 06 + 08 2a 31 3f 38 36 07 0c 0d 11 + 13 12 13 11 18 + 05 32 01 29 ]; panel-exit-sequence = [ From b545e4bdc06fa24bfd16ec672c8473f79b1072da Mon Sep 17 00:00:00 2001 From: Jianlong Wang Date: Wed, 16 Mar 2022 19:10:22 +0800 Subject: [PATCH 004/204] arm64: dts: rockchip: rk3326: add rk3326-evb-lp3-v12-linux Signed-off-by: Jianlong Wang Change-Id: I0615508b407078b2b9be30b162a41ca226b9be06 --- arch/arm64/boot/dts/rockchip/Makefile | 1 + .../dts/rockchip/rk3326-evb-lp3-v12-linux.dts | 273 ++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v12-linux.dts diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index bc9f05fc62da..86cf9815f5e8 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -20,6 +20,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-evb-lp3-v10-avb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-evb-lp3-v10-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-evb-lp3-v11.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-evb-lp3-v11-avb.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-evb-lp3-v12-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-odroid-go2.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-863-lp3-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-863-lp3-v10-avb.dtb diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v12-linux.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v12-linux.dts new file mode 100644 index 000000000000..ed0781d2f2a8 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v12-linux.dts @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd + * + */ + +/dts-v1/; + +#include "rk3326-evb-lp3-v10-linux.dts" + +/ { + model = "Rockchip rk3326 evb lpddr3 v12 board for linux"; + compatible = "rockchip,rk3326-evb-lp3-v12-linux", "rockchip,rk3326"; +}; + +&dsi { + status = "okay"; + + panel@0 { + compatible = "sitronix,st7703", "simple-panel-dsi"; + reg = <0>; + backlight = <&backlight>; + power-supply = <&vcc18_lcd_n>; + prepare-delay-ms = <0>; + reset-delay-ms = <0>; + init-delay-ms = <80>; + enable-delay-ms = <0>; + disable-delay-ms = <10>; + unprepare-delay-ms = <60>; + + width-mm = <68>; + height-mm = <121>; + + dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>; + dsi,format = ; + dsi,lanes = <4>; + + panel-init-sequence = [ + 39 00 04 ff 98 81 03 + 15 00 02 01 00 + 15 00 02 02 00 + 15 00 02 03 53 + 15 00 02 04 53 + 15 00 02 05 13 + 15 00 02 06 04 + 15 00 02 07 02 + 15 00 02 08 02 + 15 00 02 09 00 + 15 00 02 0a 00 + 15 00 02 0b 00 + 15 00 02 0c 00 + 15 00 02 0d 00 + 15 00 02 0e 00 + 15 00 02 0f 00 + + 15 00 02 10 00 + 15 00 02 11 00 + 15 00 02 12 00 + 15 00 02 13 00 + 15 00 02 14 00 + 15 00 02 15 08 + 15 00 02 16 10 + 15 00 02 17 00 + 15 00 02 18 08 + 15 00 02 19 00 + 15 00 02 1a 00 + 15 00 02 1b 00 + 15 00 02 1c 00 + 15 00 02 1d 00 + 15 00 02 1e c0 + 15 00 02 1f 80 + + 15 00 02 20 02 + 15 00 02 21 09 + 15 00 02 22 00 + 15 00 02 23 00 + 15 00 02 24 00 + 15 00 02 25 00 + 15 00 02 26 00 + 15 00 02 27 00 + 15 00 02 28 55 + 15 00 02 29 03 + 15 00 02 2a 00 + 15 00 02 2b 00 + 15 00 02 2c 00 + 15 00 02 2d 00 + 15 00 02 2e 00 + 15 00 02 2f 00 + + 15 00 02 30 00 + 15 00 02 31 00 + 15 00 02 32 00 + 15 00 02 33 00 + 15 00 02 34 04 + 15 00 02 35 05 + 15 00 02 36 05 + 15 00 02 37 00 + 15 00 02 38 3c + 15 00 02 39 35 + 15 00 02 3a 00 + 15 00 02 3b 40 + 15 00 02 3c 00 + 15 00 02 3d 00 + 15 00 02 3e 00 + 15 00 02 3f 00 + + 15 00 02 40 00 + 15 00 02 41 88 + 15 00 02 42 00 + 15 00 02 43 00 + 15 00 02 44 1f + + 15 00 02 50 01 + 15 00 02 51 23 + 15 00 02 52 45 + 15 00 02 53 67 + 15 00 02 54 89 + 15 00 02 55 ab + 15 00 02 56 01 + 15 00 02 57 23 + 15 00 02 58 45 + 15 00 02 59 67 + 15 00 02 5a 89 + 15 00 02 5b ab + 15 00 02 5c cd + 15 00 02 5d ef + 15 00 02 5e 03 + 15 00 02 5f 14 + + 15 00 02 60 15 + 15 00 02 61 0c + 15 00 02 62 0d + 15 00 02 63 0e + 15 00 02 64 0f + 15 00 02 65 10 + 15 00 02 66 11 + 15 00 02 67 08 + 15 00 02 68 02 + 15 00 02 69 0a + 15 00 02 6a 02 + 15 00 02 6b 02 + 15 00 02 6c 02 + 15 00 02 6d 02 + 15 00 02 6e 02 + 15 00 02 6f 02 + + 15 00 02 70 02 + 15 00 02 71 02 + 15 00 02 72 06 + 15 00 02 73 02 + 15 00 02 74 02 + 15 00 02 75 14 + 15 00 02 76 15 + 15 00 02 77 0f + 15 00 02 78 0e + 15 00 02 79 0d + 15 00 02 7a 0c + 15 00 02 7b 11 + 15 00 02 7c 10 + 15 00 02 7d 06 + 15 00 02 7e 02 + 15 00 02 7f 0a + + 15 00 02 80 02 + 15 00 02 81 02 + 15 00 02 82 02 + 15 00 02 83 02 + 15 00 02 84 02 + 15 00 02 85 02 + 15 00 02 86 02 + 15 00 02 87 02 + 15 00 02 88 08 + 15 00 02 89 02 + 15 00 02 8a 02 + + 39 00 04 ff 98 81 04 + 15 00 02 00 80 + 15 00 02 70 00 + 15 00 02 71 00 + 15 00 02 66 fe + 15 00 02 82 15 + 15 00 02 84 15 + 15 00 02 85 15 + 15 00 02 3a 24 + 15 00 02 32 ac + 15 00 02 8c 80 + 15 00 02 3c f5 + 15 00 02 88 33 + + 39 00 04 ff 98 81 01 + 15 00 02 22 0a + 15 00 02 31 00 + 15 00 02 53 78 + 15 00 02 50 5b + 15 00 02 51 5b + 15 00 02 60 20 + 15 00 02 61 00 + 15 00 02 62 0d + 15 00 02 63 00 + + 15 00 02 a0 00 + 15 00 02 a1 10 + 15 00 02 a2 1c + 15 00 02 a3 13 + 15 00 02 a4 15 + 15 00 02 a5 26 + 15 00 02 a6 1a + 15 00 02 a7 1d + 15 00 02 a8 67 + 15 00 02 a9 1c + 15 00 02 aa 29 + 15 00 02 ab 5b + 15 00 02 ac 26 + 15 00 02 ad 28 + 15 00 02 ae 5c + 15 00 02 af 30 + 15 00 02 b0 31 + 15 00 02 b1 2e + 15 00 02 b2 32 + 15 00 02 b3 00 + + 15 00 02 c0 00 + 15 00 02 c1 10 + 15 00 02 c2 1c + 15 00 02 c3 13 + 15 00 02 c4 15 + 15 00 02 c5 26 + 15 00 02 c6 1a + 15 00 02 c7 1d + 15 00 02 c8 67 + 15 00 02 c9 1c + 15 00 02 ca 29 + 15 00 02 cb 5b + 15 00 02 cc 26 + 15 00 02 cd 28 + 15 00 02 ce 5c + 15 00 02 cf 30 + 15 00 02 d0 31 + 15 00 02 d1 2e + 15 00 02 d2 32 + 15 00 02 d3 00 + 39 00 04 ff 98 81 00 + 05 00 01 11 + 05 01 01 29 + ]; + + panel-exit-sequence = [ + 05 00 01 28 + 05 00 01 10 + ]; + + display-timings { + native-mode = <&timing0>; + + timing0: timing0 { + clock-frequency = <66000000>; + hactive = <720>; + vactive = <1280>; + hfront-porch = <40>; + hsync-len = <10>; + hback-porch = <40>; + vfront-porch = <22>; + vsync-len = <4>; + vback-porch = <11>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + }; + }; +}; From d3b3fc7cc51d530c368d6de5ecf68c46f31775ed Mon Sep 17 00:00:00 2001 From: Lin Jianhua Date: Thu, 8 Sep 2022 14:25:18 +0800 Subject: [PATCH 005/204] arm64: dts: rockchip: px30_linux_defconfig: enable multicodecs and remove CIF config Signed-off-by: Lin Jianhua Change-Id: I65cce7c3f4646fe2c508350e468f22f212d0b0dd --- arch/arm64/configs/px30_linux_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/px30_linux_defconfig b/arch/arm64/configs/px30_linux_defconfig index 518854521dc1..60bacd15e427 100644 --- a/arch/arm64/configs/px30_linux_defconfig +++ b/arch/arm64/configs/px30_linux_defconfig @@ -279,7 +279,6 @@ CONFIG_USB_VIDEO_CLASS=y # CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV is not set # CONFIG_USB_GSPCA is not set CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_VIDEO_ROCKCHIP_CIF=y CONFIG_VIDEO_ROCKCHIP_RKISP1=y CONFIG_V4L_MEM2MEM_DRIVERS=y # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set @@ -326,6 +325,8 @@ CONFIG_SND_DYNAMIC_MINORS=y CONFIG_SND_USB_AUDIO=y CONFIG_SND_SOC=y CONFIG_SND_SOC_ROCKCHIP=y +CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=y +CONFIG_SND_SOC_ROCKCHIP_MULTI_DAIS=y CONFIG_SND_SOC_ROCKCHIP_I2S=y CONFIG_SND_SOC_RK817=y CONFIG_SND_SIMPLE_CARD=y From 41407a36ac3f761bdd302fea8d7d645817c20e0d Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Tue, 6 Sep 2022 14:47:32 +0800 Subject: [PATCH 006/204] ARM: dts: rockchip: rv1106-thunder-boot: update memory layout Because of the meta and rkisp_thunderboot memory offset MUST match with RTOS, so move meta and rkisp_thunderboot to the top of memory layout. The memory layout for rv1106 thunder boot feature: SPL: 0 ~ 256KB RTOS: 256KB ~ 512KB SPL S & H: 512KB ~ (2MB - 8KB) ATAGS: (2MB - 8KB) ~ 2MB UBOOT: 2MB ~ KERNEL_R: (2MB + 0x8000) ~ (8MB - 128KB) DTB: (8MB - 128KB) ~ 8MB META: 8MB ~ (8MB + 384KB) ISP: (8MB + 384KB) ~ (8MB + 384KB + ceil(w*10/8/256)*256*h*(buf_num)) RAMDISK_R: 0x12ec000 ~ (0x12ec000 + 10MB) RAMDISK_C: (0x12ec000 + 10MB) ~ (0x12ec000 + 10MB + 5MB) KERNEL_C: (0x12ec000 + 10MB + 5MB) ~ (0x12ec000 + 10MB + 5MB + 5MB) Signed-off-by: Weiwen Chen Change-Id: I9d18041559ca10c96f5d94a1c0dcf1d535c90db4 --- arch/arm/boot/dts/rv1106-thunder-boot.dtsi | 25 +++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/rv1106-thunder-boot.dtsi b/arch/arm/boot/dts/rv1106-thunder-boot.dtsi index ecc9ac178d1b..df76f8fe8268 100644 --- a/arch/arm/boot/dts/rv1106-thunder-boot.dtsi +++ b/arch/arm/boot/dts/rv1106-thunder-boot.dtsi @@ -19,25 +19,30 @@ #size-cells = <1>; ranges; - rtos@40000 { + rtos: rtos@40000 { reg = <0x40000 0x40000>; }; - ramdisk_r: ramdisk@a00000 { - reg = <0x00a00000 (10 * 0x00100000)>; + meta: meta@800000 { + /* reg's offset MUST match with RTOS */ + reg = <0x00800000 0x60000>; }; - ramdisk_c: ramdisk@1900000 { - reg = <0x01900000 (5 * 0x00100000)>; + rkisp_thunderboot: rkisp@860000 { + /* reg's offset MUST match with RTOS */ + /* + * vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num) + * e.g. 1920x1080: 0xa8c000 + */ + reg = <0x00860000 0xa8c000>; }; - meta: meta@1e00000 { - reg = <0x01e00000 0x0>; + ramdisk_r: ramdisk_r { + reg = <0x12ec000 (10 * 0x00100000)>; }; - rkisp_thunderboot: rkisp@1e60000 { - /* NV12 (w*h*1.5*2) w and h 16 align, eg:1920x1088 */ - reg = <0x1e60000 0x0>; + ramdisk_c: ramdisk_c { + reg = <0x1cec000 (5 * 0x00100000)>; }; }; From 32154375ea2db04bc57c1b305f2a72ac750e5ec9 Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Tue, 6 Sep 2022 15:06:07 +0800 Subject: [PATCH 007/204] ARM: dts: rockchip: rv1103g-battery-ipc-v10: update meta and rkisp_thunderboot use default value Signed-off-by: Weiwen Chen Change-Id: Id7e231b7f3142761e1945d0a0f18cf4308ede672 --- arch/arm/boot/dts/rv1103g-battery-ipc-v10.dts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/arch/arm/boot/dts/rv1103g-battery-ipc-v10.dts b/arch/arm/boot/dts/rv1103g-battery-ipc-v10.dts index 9176465f1d43..e7acc2c26afe 100644 --- a/arch/arm/boot/dts/rv1103g-battery-ipc-v10.dts +++ b/arch/arm/boot/dts/rv1103g-battery-ipc-v10.dts @@ -190,11 +190,6 @@ reg = <0x00000000 0x04000000>; }; -&meta { - /* reserved meta partition 384KB */ - reg = <0x01e00000 (384 * 0x400)>; -}; - &mipi0_csi2 { status = "okay"; @@ -267,11 +262,6 @@ status = "okay"; }; -&rkisp_thunderboot { - /* vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num) */ - reg = <0x01e60000 0xa8c000>; -}; - &rkisp_vir0 { status = "okay"; From be3f404824a49f28b8792c31f01d55f62463f13c Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Tue, 6 Sep 2022 17:43:12 +0800 Subject: [PATCH 008/204] media: rockchip: isp: version v2.0.0 Change-Id: I538c3abb84a338e730c2bd266485ceb4bae6166d Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/version.h | 83 +++++++++++++++++++ include/uapi/linux/rkisp2-config.h | 2 +- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/rockchip/isp/version.h b/drivers/media/platform/rockchip/isp/version.h index c3eda612db71..01bd28330c38 100644 --- a/drivers/media/platform/rockchip/isp/version.h +++ b/drivers/media/platform/rockchip/isp/version.h @@ -274,6 +274,89 @@ * 53.procfs build with different isp version * 54.fix isp debug time for fe/fs irq together * 55.awb or gain debug info to ddr for isp32 + * + * v2.0.0: + * 1.fix bay3d ds size for isp32 + * 2.to support vicap merge raw + * 3.isp32 fix ae no working with af + * 4.api to free mesh buf for user + * 5.lock for buf alloc and free + * 6.for sdmmc lock + * 7.limit bay3d bwsaving config for isp32 + * 8.fix imx327 hdr mode for isp21 + * 9.ctrl the fps for isp32 + * 10.add the bp stream async for isp32 + * 11.fix info2ddr buf free for isp32 + * 12.fix csm range to full + * 13.add the pause, config, resume stream for isp32 + * 14.isp32 min clk to 200M + * 15.module auto gating for isp30/isp32 + * 16.add the max size dummybuf and shd stop for isp32 + * 17.add the config dvbm_init in wrap for isp32 + * 18.sync params state + * 19.delete the buf_done log for isp32 + * 20.params buf alloc remove to first buf queue + * 21.read the color_ctrl reg for isp32 + * 22.use lager clk in 4 vir-isp mode + * 23.rockit: support set wrap_line + * 24.tb helper add clk on/off + * 25.remove stream limit for dvbm for isp32 + * 26.fix hold at lsc ram data config + * 27.fix cac on/off for isp32 + * 28.thunderboot for isp32 + * 29.fix isp32 stream buf update double + * 30.add the double isp_dev in rockit for isp32 + * 31.isp32: fix wrap error for fast stream + * 32.check rockit pointer + * 33.support free rx buffer + * 34.initcall cif/isp early when ROCKCHIP_THUNDER_BOOT_ISP=y + * 35.fix rockit set fps fail + * 36.fix module exit + * 37.api get fast stream output info + * 38.api for video to free tb reserved memory + * 39.fix warp size error + * 40.fix isp30 cgc limit config + * 41.remove associated of cproc and ie for isp3x + * 42.Add missing sentinel to rkisp_hw_of_match + * 43.support mesh buf count from user for isp30 and isp32 + * 44.add tb api for rockit + * 45.fix isp30 cgc and cproc range + * 46.add slab.h fix compile + * 47.vb2 buf done in tasklet + * 48.rdbk to tasklet + * 49.set afen off before config af + * 50.remove isp1x compatible + * 51.frame end config params_v32 for fast output + * 52.match stream info for fast output + * 53.fix bug the second frame pts is 0 + * 54.fix error of lsc repeat switch + * 55.fix dhaz config for multi isp21 + * 56.cif/isp support compat_ioctl32 for video + * 57.unite mode to support multi dev for isp30 + * 58.enum multi isp size at power on + * 59.2 readback for support multishot large resolution + * 60.disable link vir isp when hw working + * 61.fill extend line data for fix dhaz bug + * 62.fix isp20 and isp21 default to online with vicap + * 63.add procfs write for debug + * 64.fix isp20 error + * 65.support rdbk without aiq + * 66.fast to vicap capture raw + * 67.first frame run double for isp32 fast mode + * 68.fix pm runtime return -EACCES for thunderboot + * 69.record isp read time for fast mode + * 70.first params from rtt for thunderboot + * 71.fix pm runtime return -EACCES for thunderboot + * 72.record isp read time for fast mode + * 73.first params from rtt for thunderboot + * 74.enum formats for different isp version + * 75.change the limit of height + * 76.enum the max frame size to isp input size + * 77.stop without waiting if isp idle for readback mode + * 78.fix limit of dcrop + * 79.fix isp32 stream force to update enable + * 80.fix mi no disable for multi sensor unite mode + * 81.fix size for multi isp composite mode */ #define RKISP_DRIVER_VERSION RKISP_API_VERSION diff --git a/include/uapi/linux/rkisp2-config.h b/include/uapi/linux/rkisp2-config.h index 20b9174cffc3..fa7e50911a71 100644 --- a/include/uapi/linux/rkisp2-config.h +++ b/include/uapi/linux/rkisp2-config.h @@ -10,7 +10,7 @@ #include #include -#define RKISP_API_VERSION KERNEL_VERSION(1, 9, 0) +#define RKISP_API_VERSION KERNEL_VERSION(2, 0, 0) /****************ISP SUBDEV IOCTL*****************************/ From 5f4e2f385996fc61b29dd68b5a67d0908b775bbb Mon Sep 17 00:00:00 2001 From: Binyuan Lan Date: Thu, 8 Jul 2021 21:24:39 +0800 Subject: [PATCH 009/204] ASoC: rockchip: rk817-codec: Solve pop problems DIGEN_CLKE can only be controlled when the amplifier is turned off Signed-off-by: Binyuan Lan Change-Id: I5758cab8f20bd2ede008d1ad138cdadcaa55e39d --- sound/soc/codecs/rk817_codec.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index 4ed82d328704..645a4538cef5 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -941,26 +941,27 @@ static int rk817_digital_mute(struct snd_soc_dai *dai, int mute, int stream) struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component); DBG("%s %d\n", __func__, mute); + if (mute) { + rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 0); + rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 0); + snd_soc_component_update_bits(component, RK817_CODEC_DDAC_MUTE_MIXCTL, DACMT_ENABLE, DACMT_ENABLE); + snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1, + PWD_DACBIAS_DOWN | PWD_DACD_DOWN | + PWD_DACL_DOWN | PWD_DACR_DOWN); /* Reset DAC DTOP_DIGEN_CLKE for playback stopped */ snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, DAC_DIG_CLK_EN, DAC_DIG_CLK_DIS); snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, DAC_DIG_CLK_EN, DAC_DIG_CLK_EN); - } else { snd_soc_component_update_bits(component, RK817_CODEC_DDAC_MUTE_MIXCTL, DACMT_ENABLE, DACMT_DISABLE); - } - if (mute) { - rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 0); - rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 0); - } else { switch (rk817->playback_path) { case SPK_PATH: case RING_SPK: From 8661e36ef0b82fa507fa562d76052796e7f5ea31 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Wed, 18 Aug 2021 15:25:05 +0800 Subject: [PATCH 010/204] ASoC: rk817: Move dbg message into CONFIG_SND_DEBUG $ ./scripts/bloat-o-meter rk817_codec.o.old rk817_codec.o add/remove: 5/9 grow/shrink: 1/13 up/down: 221/-1846 (-1625) Function old new delta __UNIQUE_ID_author400 - 56 +56 __UNIQUE_ID_file401 - 50 +50 __UNIQUE_ID_description399 - 50 +50 __UNIQUE_ID_license402 - 29 +29 rk817_playback_path_put 832 860 +28 __UNIQUE_ID___addressable_rk817_codec_driver_init398 - 8 +8 dbg_enable 4 - -4 __UNIQUE_ID___addressable_rk817_codec_driver_init399 8 - -8 __param_str_dbg_level 24 - -24 __UNIQUE_ID_license403 29 - -29 __UNIQUE_ID_dbg_leveltype397 37 - -37 rk817_remove 260 220 -40 rk817_probe 344 304 -40 __param_dbg_level 40 - -40 rk817_platform_shutdown 104 56 -48 __UNIQUE_ID_file402 50 - -50 __UNIQUE_ID_description400 50 - -50 rk817_set_dai_sysclk 88 32 -56 __UNIQUE_ID_author401 56 - -56 rk817_hw_params 516 456 -60 rk817_set_dai_fmt 184 116 -68 rk817_playback_path_get 108 36 -72 rk817_capture_path_get 108 36 -72 rk817_codec_power_down 516 424 -92 rk817_capture_path_put 632 492 -140 rk817_codec_power_up 756 580 -176 rk817_digital_mute 756 460 -296 rk817_platform_probe 1264 876 -388 Total: Before=9850, After=8225, chg -16.50% Change-Id: I98471c52ea342672e10deb02c4fb38d9fb82f906 Signed-off-by: Sugar Zhang --- sound/soc/codecs/rk817_codec.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index 645a4538cef5..abef7b38bce0 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -26,15 +26,11 @@ #include #include "rk817_codec.h" -static int dbg_enable; -module_param_named(dbg_level, dbg_enable, int, 0644); - -#define DBG(args...) \ - do { \ - if (dbg_enable) { \ - pr_info(args); \ - } \ - } while (0) +#ifdef CONFIG_SND_DEBUG +#define DBG(args...) pr_info(args) +#else +#define DBG(args...) +#endif /* For route */ #define RK817_CODEC_PLAYBACK 1 @@ -862,14 +858,12 @@ static int rk817_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; - struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component); unsigned int rate = params_rate(params); unsigned char apll_cfg3_val; unsigned char dtop_digen_sr_lmt0; unsigned char dtop_digen_clke; - DBG("%s : MCLK = %dHz, sample rate = %dHz\n", - __func__, rk817->stereo_sysclk, rate); + DBG("%s : sample rate = %dHz\n", __func__, rate); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dtop_digen_clke = DAC_DIG_CLK_EN; From 05446cfe5ac6cec2a4d384082fb91ad1d6743317 Mon Sep 17 00:00:00 2001 From: Binyuan Lan Date: Mon, 28 Mar 2022 14:01:13 +0000 Subject: [PATCH 011/204] ASoC: rockchip: rk817-codec: Add version recognition and set up different PLL configurations Signed-off-by: Binyuan Lan Change-Id: I0209db73994e428b25e9cba4417f0f3dd98fb3dc --- sound/soc/codecs/rk817_codec.c | 25 ++++++++++++++++++++++++- sound/soc/codecs/rk817_codec.h | 2 ++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index abef7b38bce0..5f32d8807ef0 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -88,6 +88,7 @@ struct rk817_codec_priv { struct gpio_desc *hp_ctl_gpio; int spk_mute_delay; int hp_mute_delay; + int chip_ver; }; static const struct reg_default rk817_reg_defaults[] = { @@ -153,6 +154,8 @@ static bool rk817_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { case RK817_CODEC_DTOP_LPT_SRST: + case RK817_PMIC_CHIP_NAME: + case RK817_PMIC_CHIP_VER: return true; default: return false; @@ -218,6 +221,8 @@ static bool rk817_codec_register(struct device *dev, unsigned int reg) case RK817_CODEC_DI2S_TXCR1: case RK817_CODEC_DI2S_TXCR2: case RK817_CODEC_DI2S_TXCR3_TXCMD: + case RK817_PMIC_CHIP_NAME: + case RK817_PMIC_CHIP_VER: return true; default: return false; @@ -858,6 +863,7 @@ static int rk817_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; + struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component); unsigned int rate = params_rate(params); unsigned char apll_cfg3_val; unsigned char dtop_digen_sr_lmt0; @@ -865,6 +871,16 @@ static int rk817_hw_params(struct snd_pcm_substream *substream, DBG("%s : sample rate = %dHz\n", __func__, rate); + if (rk817->chip_ver <= 0x4) { + DBG("%s: SMIC TudorAG and previous versions\n", __func__); + snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x0c); + snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0x95); + } else { + DBG("%s: SMIC TudorAG version later\n", __func__); + snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x04); + snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5); + } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dtop_digen_clke = DAC_DIG_CLK_EN; else @@ -1084,6 +1100,8 @@ static int rk817_resume(struct snd_soc_component *component) static int rk817_probe(struct snd_soc_component *component) { struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component); + int chip_name = 0; + int chip_ver = 0; DBG("%s\n", __func__); @@ -1097,6 +1115,11 @@ static int rk817_probe(struct snd_soc_component *component) rk817->playback_path = OFF; rk817->capture_path = MIC_OFF; + chip_name = snd_soc_component_read(component, RK817_PMIC_CHIP_NAME); + chip_ver = snd_soc_component_read(component, RK817_PMIC_CHIP_VER); + rk817->chip_ver = (chip_ver & 0x0f); + dev_info(component->dev, "%s: chip_name:0x%x, chip_ver:0x%x\n", __func__, chip_name, chip_ver); + rk817_reset(component); snd_soc_add_component_controls(component, rk817_snd_path_controls, ARRAY_SIZE(rk817_snd_path_controls)); @@ -1233,7 +1256,7 @@ static const struct regmap_config rk817_codec_regmap_config = { .reg_bits = 8, .val_bits = 8, .reg_stride = 1, - .max_register = 0x4f, + .max_register = 0xfe, .cache_type = REGCACHE_FLAT, .volatile_reg = rk817_volatile_register, .writeable_reg = rk817_codec_register, diff --git a/sound/soc/codecs/rk817_codec.h b/sound/soc/codecs/rk817_codec.h index a928c323928b..5c4a1bc89d84 100644 --- a/sound/soc/codecs/rk817_codec.h +++ b/sound/soc/codecs/rk817_codec.h @@ -74,6 +74,8 @@ #define RK817_CODEC_DI2S_TXCR1 (RK817_CODEC_BASE + 0x4d) #define RK817_CODEC_DI2S_TXCR2 (RK817_CODEC_BASE + 0x4e) #define RK817_CODEC_DI2S_TXCR3_TXCMD (RK817_CODEC_BASE + 0x4f) +#define RK817_PMIC_CHIP_NAME (RK817_CODEC_BASE + 0xed) +#define RK817_PMIC_CHIP_VER (RK817_CODEC_BASE + 0xee) /* RK817_CODEC_DTOP_DIGEN_CLKE */ #define ADC_DIG_CLK_MASK (0xf << 4) From 921b6ae03ebd49c79c7097adc4d67a83e770bb7e Mon Sep 17 00:00:00 2001 From: Binyuan Lan Date: Sat, 2 Jul 2022 12:19:51 +0000 Subject: [PATCH 012/204] ASoC: rockchip: rk817-codec: enable mclk when reset Solve the problem that LRCK level amplitude is not enough Signed-off-by: Binyuan Lan Change-Id: Id79df3de70cd525e1d5425d4177d774a514c45da --- sound/soc/codecs/rk817_codec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index 5f32d8807ef0..b6a25fa79885 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -1120,7 +1120,10 @@ static int rk817_probe(struct snd_soc_component *component) rk817->chip_ver = (chip_ver & 0x0f); dev_info(component->dev, "%s: chip_name:0x%x, chip_ver:0x%x\n", __func__, chip_name, chip_ver); + clk_prepare_enable(rk817->mclk); rk817_reset(component); + clk_disable_unprepare(rk817->mclk); + snd_soc_add_component_controls(component, rk817_snd_path_controls, ARRAY_SIZE(rk817_snd_path_controls)); return 0; From 1ea2169bc232028cd16e2d0fba29fc3ee09eab51 Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Fri, 9 Sep 2022 01:08:59 +0000 Subject: [PATCH 013/204] drm/bridge: synopsys: dw-hdmi-qp: disabel hpd irq when shutdown or suspend Signed-off-by: Chen Shunqing Change-Id: Ib35f11e376758560b7907684e58f31b04261c066 --- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 1360dc38f57b..cfa96940c0e2 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -3399,6 +3399,8 @@ static void dw_hdmi_rockchip_shutdown(struct platform_device *pdev) return; if (hdmi->is_hdmi_qp) { + if (hdmi->hpd_irq) + disable_irq(hdmi->hpd_irq); cancel_delayed_work(&hdmi->work); flush_workqueue(hdmi->workqueue); dw_hdmi_qp_suspend(hdmi->dev, hdmi->hdmi_qp); @@ -3420,10 +3422,13 @@ static int dw_hdmi_rockchip_suspend(struct device *dev) { struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); - if (hdmi->is_hdmi_qp) + if (hdmi->is_hdmi_qp) { + if (hdmi->hpd_irq) + disable_irq(hdmi->hpd_irq); dw_hdmi_qp_suspend(dev, hdmi->hdmi_qp); - else + } else { dw_hdmi_suspend(hdmi->hdmi); + } pm_runtime_put_sync(dev); return 0; @@ -3466,6 +3471,8 @@ static int dw_hdmi_rockchip_resume(struct device *dev) } dw_hdmi_qp_resume(dev, hdmi->hdmi_qp); + if (hdmi->hpd_irq) + enable_irq(hdmi->hpd_irq); drm_helper_hpd_irq_event(hdmi->drm_dev); } else { dw_hdmi_resume(hdmi->hdmi); From 06e1313973c49027bed9ad96a6d65995b823f74e Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Fri, 9 Sep 2022 10:50:51 +0800 Subject: [PATCH 014/204] crypto: rockchip: poll uses a uniform interface to read registers Use CRYPTO_READ or PKA_READ as uniform interface for poll function. Signed-off-by: Lin Jinhan Change-Id: I47e9e1efd0b4c66efe59eac3253fdaf2723e5c45 --- drivers/crypto/rockchip/rk_crypto_v2_ahash.c | 14 ++++++------ drivers/crypto/rockchip/rk_crypto_v2_pka.c | 6 ++--- .../crypto/rockchip/rk_crypto_v2_skcipher.c | 12 +++++----- drivers/crypto/rockchip/rk_crypto_v3_ahash.c | 22 ++++++++++--------- .../crypto/rockchip/rk_crypto_v3_skcipher.c | 12 +++++----- 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/drivers/crypto/rockchip/rk_crypto_v2_ahash.c b/drivers/crypto/rockchip/rk_crypto_v2_ahash.c index 16e7cbdb29db..dd9ea240bac0 100644 --- a/drivers/crypto/rockchip/rk_crypto_v2_ahash.c +++ b/drivers/crypto/rockchip/rk_crypto_v2_ahash.c @@ -51,8 +51,8 @@ static void rk_hash_reset(struct rk_crypto_dev *rk_dev) CRYPTO_WRITE(rk_dev, CRYPTO_RST_CTL, tmp | tmp_mask); /* This is usually done in 20 clock cycles */ - ret = readl_poll_timeout_atomic(rk_dev->reg + CRYPTO_RST_CTL, - tmp, !tmp, 0, pool_timeout_us); + ret = read_poll_timeout_atomic(CRYPTO_READ, tmp, !tmp, 0, pool_timeout_us, + false, rk_dev, CRYPTO_RST_CTL); if (ret) dev_err(rk_dev->dev, "cipher reset pool timeout %ums.", pool_timeout_us); @@ -285,11 +285,11 @@ static int rk_ahash_get_result(struct rk_crypto_dev *rk_dev, int ret = 0; u32 reg_ctrl = 0; - ret = readl_poll_timeout_atomic(rk_dev->reg + CRYPTO_HASH_VALID, - reg_ctrl, - reg_ctrl & CRYPTO_HASH_IS_VALID, - RK_POLL_PERIOD_US, - RK_POLL_TIMEOUT_US); + ret = read_poll_timeout_atomic(CRYPTO_READ, reg_ctrl, + reg_ctrl & CRYPTO_HASH_IS_VALID, + RK_POLL_PERIOD_US, + RK_POLL_TIMEOUT_US, false, + rk_dev, CRYPTO_HASH_VALID); if (ret) goto exit; diff --git a/drivers/crypto/rockchip/rk_crypto_v2_pka.c b/drivers/crypto/rockchip/rk_crypto_v2_pka.c index c2883626be04..d2c0a265b3ad 100644 --- a/drivers/crypto/rockchip/rk_crypto_v2_pka.c +++ b/drivers/crypto/rockchip/rk_crypto_v2_pka.c @@ -175,7 +175,7 @@ static int pka_wait_pipe_rdy(void) { u32 reg_val = 0; - return readl_poll_timeout(pka_base + CRYPTO_PKA_PIPE_RDY, reg_val, + return readx_poll_timeout(PKA_READ, CRYPTO_PKA_PIPE_RDY, reg_val, reg_val, PKA_POLL_PERIOD_US, PKA_POLL_TIMEOUT_US); } @@ -183,7 +183,7 @@ static int pka_wait_done(void) { u32 reg_val = 0; - return readl_poll_timeout(pka_base + CRYPTO_PKA_DONE, reg_val, + return readx_poll_timeout(PKA_READ, CRYPTO_PKA_DONE, reg_val, reg_val, PKA_POLL_PERIOD_US, PKA_POLL_TIMEOUT_US); } @@ -191,7 +191,7 @@ static int pka_max_wait_done(void) { u32 reg_val = 0; - return readl_poll_timeout(pka_base + CRYPTO_PKA_DONE, reg_val, + return readx_poll_timeout(PKA_READ, CRYPTO_PKA_DONE, reg_val, reg_val, PKA_MAX_POLL_PERIOD_US, PKA_MAX_POLL_TIMEOUT_US); } diff --git a/drivers/crypto/rockchip/rk_crypto_v2_skcipher.c b/drivers/crypto/rockchip/rk_crypto_v2_skcipher.c index cce8e86228bc..5edef31da8f6 100644 --- a/drivers/crypto/rockchip/rk_crypto_v2_skcipher.c +++ b/drivers/crypto/rockchip/rk_crypto_v2_skcipher.c @@ -136,11 +136,13 @@ static int get_tag_reg(struct rk_crypto_dev *rk_dev, u8 *tag, u32 tag_len) if (tag_len > RK_MAX_TAG_SIZE) return -EINVAL; - ret = readl_poll_timeout_atomic(rk_dev->reg + CRYPTO_TAG_VALID, + ret = read_poll_timeout_atomic(CRYPTO_READ, reg_ctrl, reg_ctrl & CRYPTO_CH0_TAG_VALID, - RK_POLL_PERIOD_US, - RK_POLL_TIMEOUT_US); + 0, + RK_POLL_TIMEOUT_US, + false, + rk_dev, CRYPTO_TAG_VALID); if (ret) goto exit; @@ -188,8 +190,8 @@ static void rk_cipher_reset(struct rk_crypto_dev *rk_dev) CRYPTO_WRITE(rk_dev, CRYPTO_RST_CTL, tmp | tmp_mask); /* This is usually done in 20 clock cycles */ - ret = readl_poll_timeout_atomic(rk_dev->reg + CRYPTO_RST_CTL, - tmp, !tmp, 0, pool_timeout_us); + ret = read_poll_timeout_atomic(CRYPTO_READ, tmp, !tmp, 0, + pool_timeout_us, false, rk_dev, CRYPTO_RST_CTL); if (ret) dev_err(rk_dev->dev, "cipher reset pool timeout %ums.", pool_timeout_us); diff --git a/drivers/crypto/rockchip/rk_crypto_v3_ahash.c b/drivers/crypto/rockchip/rk_crypto_v3_ahash.c index 213aaf1d084d..f39026dbc314 100644 --- a/drivers/crypto/rockchip/rk_crypto_v3_ahash.c +++ b/drivers/crypto/rockchip/rk_crypto_v3_ahash.c @@ -56,8 +56,8 @@ static void rk_hash_reset(struct rk_crypto_dev *rk_dev) CRYPTO_WRITE(rk_dev, CRYPTO_RST_CTL, tmp | tmp_mask); /* This is usually done in 20 clock cycles */ - ret = readl_poll_timeout_atomic(rk_dev->reg + CRYPTO_RST_CTL, - tmp, !tmp, 0, pool_timeout_us); + ret = read_poll_timeout_atomic(CRYPTO_READ, tmp, !tmp, 0, pool_timeout_us, + false, rk_dev, CRYPTO_RST_CTL); if (ret) dev_err(rk_dev->dev, "cipher reset pool timeout %ums.", pool_timeout_us); @@ -72,11 +72,13 @@ static int rk_hash_mid_data_store(struct rk_crypto_dev *rk_dev, struct rk_hash_m CRYPTO_TRACE(); - ret = readl_poll_timeout_atomic(rk_dev->reg + CRYPTO_MID_VALID, + ret = read_poll_timeout_atomic(CRYPTO_READ, reg_ctrl, reg_ctrl & CRYPTO_HASH_MID_IS_VALID, - RK_POLL_PERIOD_US, - RK_POLL_TIMEOUT_US); + 0, + RK_POLL_TIMEOUT_US, + false, rk_dev, CRYPTO_MID_VALID); + CRYPTO_WRITE(rk_dev, CRYPTO_MID_VALID_SWITCH, CRYPTO_MID_VALID_ENABLE << CRYPTO_WRITE_MASK_SHIFT); if (ret) { @@ -362,11 +364,11 @@ static int rk_ahash_get_result(struct rk_crypto_dev *rk_dev, memset(ctx->priv, 0x00, sizeof(struct rk_hash_mid_data)); - ret = readl_poll_timeout_atomic(rk_dev->reg + CRYPTO_HASH_VALID, - reg_ctrl, - reg_ctrl & CRYPTO_HASH_IS_VALID, - RK_POLL_PERIOD_US, - RK_POLL_TIMEOUT_US); + ret = read_poll_timeout_atomic(CRYPTO_READ, reg_ctrl, + reg_ctrl & CRYPTO_HASH_IS_VALID, + RK_POLL_PERIOD_US, + RK_POLL_TIMEOUT_US, false, + rk_dev, CRYPTO_HASH_VALID); if (ret) goto exit; diff --git a/drivers/crypto/rockchip/rk_crypto_v3_skcipher.c b/drivers/crypto/rockchip/rk_crypto_v3_skcipher.c index 06f7f74a8694..9eab01274fc8 100644 --- a/drivers/crypto/rockchip/rk_crypto_v3_skcipher.c +++ b/drivers/crypto/rockchip/rk_crypto_v3_skcipher.c @@ -135,11 +135,13 @@ static int get_tag_reg(struct rk_crypto_dev *rk_dev, u8 *tag, u32 tag_len) if (tag_len > RK_MAX_TAG_SIZE) return -EINVAL; - ret = readl_poll_timeout_atomic(rk_dev->reg + CRYPTO_TAG_VALID, + ret = read_poll_timeout_atomic(CRYPTO_READ, reg_ctrl, reg_ctrl & CRYPTO_CH0_TAG_VALID, - RK_POLL_PERIOD_US, - RK_POLL_TIMEOUT_US); + 0, + RK_POLL_TIMEOUT_US, + false, + rk_dev, CRYPTO_TAG_VALID); if (ret) goto exit; @@ -187,8 +189,8 @@ static void rk_cipher_reset(struct rk_crypto_dev *rk_dev) CRYPTO_WRITE(rk_dev, CRYPTO_RST_CTL, tmp | tmp_mask); /* This is usually done in 20 clock cycles */ - ret = readl_poll_timeout_atomic(rk_dev->reg + CRYPTO_RST_CTL, - tmp, !tmp, 0, pool_timeout_us); + ret = read_poll_timeout_atomic(CRYPTO_READ, tmp, !tmp, 0, + pool_timeout_us, false, rk_dev, CRYPTO_RST_CTL); if (ret) dev_err(rk_dev->dev, "cipher reset pool timeout %ums.", pool_timeout_us); From 9a4df920b527865af16201d2427e6ba4c6ef211d Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Fri, 9 Sep 2022 11:06:46 +0800 Subject: [PATCH 015/204] hwrng: rockchip: poll uses a uniform interface to read registers use rk_rng_readl as uniform interface for read registers. Signed-off-by: Lin Jinhan Change-Id: If3f4225d10153d469bb56967aa5abcea8f23d572 --- drivers/char/hw_random/rockchip-rng.c | 37 +++++++++++++++------------ 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/char/hw_random/rockchip-rng.c b/drivers/char/hw_random/rockchip-rng.c index 08ad08148d25..13503c54fe62 100644 --- a/drivers/char/hw_random/rockchip-rng.c +++ b/drivers/char/hw_random/rockchip-rng.c @@ -192,10 +192,12 @@ static int rk_crypto_v1_read(struct hwrng *rng, void *buf, size_t max, bool wait rk_rng_writel(rk_rng, reg_ctrl, CRYPTO_V1_CTRL); - ret = readl_poll_timeout(rk_rng->mem + CRYPTO_V1_CTRL, reg_ctrl, - !(reg_ctrl & CRYPTO_V1_RNG_START), - ROCKCHIP_POLL_PERIOD_US, - ROCKCHIP_POLL_TIMEOUT_US); + ret = read_poll_timeout(rk_rng_readl, reg_ctrl, + !(reg_ctrl & CRYPTO_V1_RNG_START), + ROCKCHIP_POLL_PERIOD_US, + ROCKCHIP_POLL_TIMEOUT_US, false, + rk_rng, CRYPTO_V1_CTRL); + if (ret < 0) goto out; @@ -228,10 +230,11 @@ static int rk_crypto_v2_read(struct hwrng *rng, void *buf, size_t max, bool wait rk_rng_writel(rk_rng, HIWORD_UPDATE(reg_ctrl, 0xffff, 0), CRYPTO_V2_RNG_CTL); - ret = readl_poll_timeout(rk_rng->mem + CRYPTO_V2_RNG_CTL, reg_ctrl, - !(reg_ctrl & CRYPTO_V2_RNG_START), - ROCKCHIP_POLL_PERIOD_US, - ROCKCHIP_POLL_TIMEOUT_US); + ret = read_poll_timeout(rk_rng_readl, reg_ctrl, + !(reg_ctrl & CRYPTO_V2_RNG_START), + ROCKCHIP_POLL_PERIOD_US, + ROCKCHIP_POLL_TIMEOUT_US, false, + rk_rng, CRYPTO_V2_RNG_CTL); if (ret < 0) goto out; @@ -281,10 +284,11 @@ static int rk_trng_v1_init(struct hwrng *rng) udelay(10); /* wait for GENERATING and RESEEDING flag to clear */ - readl_poll_timeout(rk_rng->mem + TRNG_V1_STAT, reg_ctrl, - (reg_ctrl & mask) == TRNG_V1_STAT_SEEDED, - ROCKCHIP_POLL_PERIOD_US, - ROCKCHIP_POLL_TIMEOUT_US); + read_poll_timeout(rk_rng_readl, reg_ctrl, + (reg_ctrl & mask) == TRNG_V1_STAT_SEEDED, + ROCKCHIP_POLL_PERIOD_US, + ROCKCHIP_POLL_TIMEOUT_US, false, + rk_rng, TRNG_V1_STAT); } /* clear ISTAT flag because trng may auto reseeding when power on */ @@ -324,10 +328,11 @@ static int rk_trng_v1_read(struct hwrng *rng, void *buf, size_t max, bool wait) reg_ctrl = rk_rng_readl(rk_rng, TRNG_V1_ISTAT); if (!(reg_ctrl & TRNG_V1_ISTAT_RAND_RDY)) { /* wait RAND_RDY triggered */ - ret = readl_poll_timeout(rk_rng->mem + TRNG_V1_ISTAT, reg_ctrl, - (reg_ctrl & TRNG_V1_ISTAT_RAND_RDY), - ROCKCHIP_POLL_PERIOD_US, - ROCKCHIP_POLL_TIMEOUT_US); + ret = read_poll_timeout(rk_rng_readl, reg_ctrl, + (reg_ctrl & TRNG_V1_ISTAT_RAND_RDY), + ROCKCHIP_POLL_PERIOD_US, + ROCKCHIP_POLL_TIMEOUT_US, false, + rk_rng, TRNG_V1_ISTAT); if (ret < 0) goto out; } From 965f3dc1002471e201be40240e2979bd1d97a137 Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Thu, 21 Jul 2022 15:03:28 +0800 Subject: [PATCH 016/204] crypto: rockchip: add procfs info cat /proc/rkcrypto will show crypto debug info. Change-Id: I1a295ccf5b8c71036892e866b46d5427d5e53e93 Signed-off-by: Lin Jinhan --- drivers/crypto/rockchip/Makefile | 3 +- drivers/crypto/rockchip/procfs.c | 160 +++++++++++++++++++++++ drivers/crypto/rockchip/procfs.h | 23 ++++ drivers/crypto/rockchip/rk_crypto_core.c | 36 ++++- drivers/crypto/rockchip/rk_crypto_core.h | 19 +++ 5 files changed, 237 insertions(+), 4 deletions(-) create mode 100644 drivers/crypto/rockchip/procfs.c create mode 100644 drivers/crypto/rockchip/procfs.h diff --git a/drivers/crypto/rockchip/Makefile b/drivers/crypto/rockchip/Makefile index 96f800fc4775..53e34aa47bc1 100644 --- a/drivers/crypto/rockchip/Makefile +++ b/drivers/crypto/rockchip/Makefile @@ -3,7 +3,8 @@ obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rk_crypto.o rk_crypto-objs := rk_crypto_core.o \ rk_crypto_utils.o \ rk_crypto_ahash_utils.o \ - rk_crypto_skcipher_utils.o + rk_crypto_skcipher_utils.o \ + procfs.o rk_crypto-$(CONFIG_CRYPTO_DEV_ROCKCHIP_V1) += \ rk_crypto_v1.o \ diff --git a/drivers/crypto/rockchip/procfs.c b/drivers/crypto/rockchip/procfs.c new file mode 100644 index 000000000000..e1f08fd5d968 --- /dev/null +++ b/drivers/crypto/rockchip/procfs.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) Rockchip Electronics Co., Ltd. */ +#include +#include +#include +#include + +#include "procfs.h" + +#ifdef CONFIG_PROC_FS + +static const char *alg_type2name[ALG_TYPE_MAX] = { + [ALG_TYPE_HASH] = "HASH", + [ALG_TYPE_HMAC] = "HMAC", + [ALG_TYPE_CIPHER] = "CIPHER", + [ALG_TYPE_ASYM] = "ASYM", + [ALG_TYPE_AEAD] = "AEAD", +}; + +static void crypto_show_clock(struct seq_file *p, struct clk_bulk_data *clk_bulks, int clks_num) +{ + int i; + + seq_puts(p, "clock info:\n"); + + for (i = 0; i < clks_num; i++) + seq_printf(p, "\t%-10s %ld\n", clk_bulks[i].id, clk_get_rate(clk_bulks[i].clk)); + + seq_puts(p, "\n"); +} + +static void crypto_show_stat(struct seq_file *p, struct rk_crypto_stat *stat) +{ + /* show statistic info */ + seq_puts(p, "Statistic info:\n"); + seq_printf(p, "\tbusy_cnt : %llu\n", stat->busy_cnt); + seq_printf(p, "\tequeue_cnt : %llu\n", stat->equeue_cnt); + seq_printf(p, "\tdequeue_cnt : %llu\n", stat->dequeue_cnt); + seq_printf(p, "\tdone_cnt : %llu\n", stat->done_cnt); + seq_printf(p, "\tcomplete_cnt : %llu\n", stat->complete_cnt); + seq_printf(p, "\tfake_cnt : %llu\n", stat->fake_cnt); + seq_printf(p, "\tirq_cnt : %llu\n", stat->irq_cnt); + seq_printf(p, "\ttimeout_cnt : %llu\n", stat->timeout_cnt); + seq_printf(p, "\terror_cnt : %llu\n", stat->error_cnt); + seq_printf(p, "\tlast_error : %d\n", stat->last_error); + seq_puts(p, "\n"); +} + +static void crypto_show_queue_info(struct seq_file *p, struct rk_crypto_dev *rk_dev) +{ + bool busy; + unsigned long flags; + u32 qlen, max_qlen; + + spin_lock_irqsave(&rk_dev->lock, flags); + + qlen = rk_dev->queue.qlen; + max_qlen = rk_dev->queue.max_qlen; + busy = rk_dev->busy; + + spin_unlock_irqrestore(&rk_dev->lock, flags); + + seq_printf(p, "Crypto queue usage [%u/%u], ever_max = %llu, status: %s\n", + qlen, max_qlen, rk_dev->stat.ever_queue_max, busy ? "busy" : "idle"); + + seq_puts(p, "\n"); +} + +static void crypto_show_valid_algo_single(struct seq_file *p, enum alg_type type, + struct rk_crypto_algt **algs, u32 algs_num) +{ + u32 i; + struct rk_crypto_algt *tmp_algs; + + seq_printf(p, "\t%s:\n", alg_type2name[type]); + + for (i = 0; i < algs_num; i++, algs++) { + tmp_algs = *algs; + + if (!(tmp_algs->valid_flag) || tmp_algs->type != type) + continue; + + seq_printf(p, "\t\t%s\n", tmp_algs->name); + } + + seq_puts(p, "\n"); +} + +static void crypto_show_valid_algos(struct seq_file *p, struct rk_crypto_soc_data *soc_data) +{ + u32 algs_num = 0; + struct rk_crypto_algt **algs; + + seq_puts(p, "Valid algorithms:\n"); + + algs = soc_data->hw_get_algts(&algs_num); + if (!algs || algs_num == 0) + return; + + crypto_show_valid_algo_single(p, ALG_TYPE_CIPHER, algs, algs_num); + crypto_show_valid_algo_single(p, ALG_TYPE_AEAD, algs, algs_num); + crypto_show_valid_algo_single(p, ALG_TYPE_HASH, algs, algs_num); + crypto_show_valid_algo_single(p, ALG_TYPE_HMAC, algs, algs_num); + crypto_show_valid_algo_single(p, ALG_TYPE_ASYM, algs, algs_num); +} + +static int crypto_show_all(struct seq_file *p, void *v) +{ + struct rk_crypto_dev *rk_dev = p->private; + struct rk_crypto_soc_data *soc_data = rk_dev->soc_data; + struct rk_crypto_stat *stat = &rk_dev->stat; + + seq_printf(p, "Rockchip Crypto Version: %s\n\n", + soc_data->crypto_ver); + + seq_printf(p, "use_soft_aes192 : %s\n\n", soc_data->use_soft_aes192 ? "true" : "false"); + + crypto_show_clock(p, rk_dev->clk_bulks, rk_dev->clks_num); + + crypto_show_valid_algos(p, soc_data); + + crypto_show_stat(p, stat); + + crypto_show_queue_info(p, rk_dev); + + return 0; +} + +static int crypto_open(struct inode *inode, struct file *file) +{ + struct rk_crypto_dev *data = PDE_DATA(inode); + + return single_open(file, crypto_show_all, data); +} + +static const struct proc_ops ops = { + .proc_open = crypto_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; + +int rkcrypto_proc_init(struct rk_crypto_dev *rk_dev) +{ + rk_dev->procfs = proc_create_data(rk_dev->name, 0, NULL, &ops, rk_dev); + if (!rk_dev->procfs) + return -EINVAL; + + return 0; +} + +void rkcrypto_proc_cleanup(struct rk_crypto_dev *rk_dev) +{ + if (rk_dev->procfs) + remove_proc_entry(rk_dev->name, NULL); + + rk_dev->procfs = NULL; +} + +#endif /* CONFIG_PROC_FS */ diff --git a/drivers/crypto/rockchip/procfs.h b/drivers/crypto/rockchip/procfs.h new file mode 100644 index 000000000000..e491c53b4e04 --- /dev/null +++ b/drivers/crypto/rockchip/procfs.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2022 Rockchip Electronics Co., Ltd. */ + +#ifndef _RKCRYPTO_PROCFS_H +#define _RKCRYPTO_PROCFS_H + +#include "rk_crypto_core.h" + +#ifdef CONFIG_PROC_FS +int rkcrypto_proc_init(struct rk_crypto_dev *dev); +void rkcrypto_proc_cleanup(struct rk_crypto_dev *dev); +#else +static inline int rkcrypto_proc_init(struct rk_crypto_dev *dev) +{ + return 0; +} +static inline void rkcrypto_proc_cleanup(struct rk_crypto_dev *dev) +{ + +} +#endif + +#endif diff --git a/drivers/crypto/rockchip/rk_crypto_core.c b/drivers/crypto/rockchip/rk_crypto_core.c index 4a89ccafa28c..f1dddc782ae4 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.c +++ b/drivers/crypto/rockchip/rk_crypto_core.c @@ -26,6 +26,9 @@ #include "rk_crypto_v2.h" #include "rk_crypto_v3.h" #include "cryptodev_linux/rk_cryptodev.h" +#include "procfs.h" + +#define CRYPTO_NAME "rkcrypto" static struct rk_alg_ctx *rk_alg_ctx_cast(struct crypto_async_request *async_req) { @@ -271,6 +274,7 @@ static void rk_crypto_irq_timer_handle(struct timer_list *t) struct rk_crypto_dev *rk_dev = from_timer(rk_dev, t, timer); rk_dev->err = -ETIMEDOUT; + rk_dev->stat.timeout_cnt++; tasklet_schedule(&rk_dev->done_task); } @@ -281,6 +285,8 @@ static irqreturn_t rk_crypto_irq_handle(int irq, void *dev_id) spin_lock(&rk_dev->lock); + rk_dev->stat.irq_cnt++; + if (alg_ctx->ops.irq_handle) alg_ctx->ops.irq_handle(irq, dev_id); @@ -310,6 +316,7 @@ static int rk_start_op(struct rk_crypto_dev *rk_dev) /* fake calculations are used to trigger the Done Task */ if (alg_ctx->total == 0) { CRYPTO_TRACE("fake done_task"); + rk_dev->stat.fake_cnt++; tasklet_schedule(&rk_dev->done_task); } @@ -333,14 +340,19 @@ static void rk_complete_op(struct rk_crypto_dev *rk_dev, int err) disable_irq(rk_dev->irq); del_timer(&rk_dev->timer); + rk_dev->stat.complete_cnt++; + + if (err) { + rk_dev->stat.error_cnt++; + rk_dev->stat.last_error = err; + dev_err(rk_dev->dev, "complete_op err = %d\n", err); + } + if (!alg_ctx || !alg_ctx->ops.complete) return; alg_ctx->ops.complete(rk_dev->async_req, err); - if (err) - dev_err(rk_dev->dev, "complete_op err = %d\n", err); - tasklet_schedule(&rk_dev->queue_task); } @@ -352,10 +364,17 @@ static int rk_crypto_enqueue(struct rk_crypto_dev *rk_dev, spin_lock_irqsave(&rk_dev->lock, flags); ret = crypto_enqueue_request(&rk_dev->queue, async_req); + + if (rk_dev->queue.qlen > rk_dev->stat.ever_queue_max) + rk_dev->stat.ever_queue_max = rk_dev->queue.qlen; + if (rk_dev->busy) { + rk_dev->stat.busy_cnt++; spin_unlock_irqrestore(&rk_dev->lock, flags); return ret; } + + rk_dev->stat.equeue_cnt++; rk_dev->busy = true; spin_unlock_irqrestore(&rk_dev->lock, flags); tasklet_schedule(&rk_dev->queue_task); @@ -379,6 +398,7 @@ static void rk_crypto_queue_task_cb(unsigned long data) spin_unlock_irqrestore(&rk_dev->lock, flags); return; } + rk_dev->stat.dequeue_cnt++; spin_unlock_irqrestore(&rk_dev->lock, flags); if (backlog) { @@ -397,6 +417,8 @@ static void rk_crypto_done_task_cb(unsigned long data) struct rk_crypto_dev *rk_dev = (struct rk_crypto_dev *)data; struct rk_alg_ctx *alg_ctx = rk_alg_ctx_cast(rk_dev->async_req); + rk_dev->stat.done_cnt++; + if (rk_dev->err) goto exit; @@ -500,6 +522,8 @@ static int rk_crypto_register(struct rk_crypto_dev *rk_dev) if (err) goto err_cipher_algs; + tmp_algs->valid_flag = true; + CRYPTO_TRACE("%s register OK!!!\n", *algs_name); } @@ -691,6 +715,8 @@ static int rk_crypto_probe(struct platform_device *pdev) goto err_crypto; } + rk_dev->name = CRYPTO_NAME; + match = of_match_node(crypto_of_id_table, np); soc_data = (struct rk_crypto_soc_data *)match->data; rk_dev->soc_data = soc_data; @@ -818,6 +844,8 @@ static int rk_crypto_probe(struct platform_device *pdev) rk_cryptodev_register_dev(rk_dev->dev, soc_data->crypto_ver); + rkcrypto_proc_init(rk_dev); + dev_info(dev, "%s Accelerator successfully registered\n", soc_data->crypto_ver); return 0; @@ -832,6 +860,8 @@ static int rk_crypto_remove(struct platform_device *pdev) { struct rk_crypto_dev *rk_dev = platform_get_drvdata(pdev); + rkcrypto_proc_cleanup(rk_dev); + rk_cryptodev_unregister_dev(rk_dev->dev); del_timer_sync(&rk_dev->timer); diff --git a/drivers/crypto/rockchip/rk_crypto_core.h b/drivers/crypto/rockchip/rk_crypto_core.h index 3914601caf9b..4efebaa4541a 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.h +++ b/drivers/crypto/rockchip/rk_crypto_core.h @@ -48,6 +48,20 @@ #define RK_FLAG_FINAL BIT(0) #define RK_FLAG_UPDATE BIT(1) +struct rk_crypto_stat { + unsigned long long busy_cnt; + unsigned long long equeue_cnt; + unsigned long long dequeue_cnt; + unsigned long long complete_cnt; + unsigned long long done_cnt; + unsigned long long fake_cnt; + unsigned long long irq_cnt; + unsigned long long timeout_cnt; + unsigned long long error_cnt; + unsigned long long ever_queue_max; + int last_error; +}; + struct rk_crypto_dev { struct device *dev; struct reset_control *rst; @@ -62,6 +76,9 @@ struct rk_crypto_dev { struct rk_crypto_soc_data *soc_data; int clks_num; struct clk_bulk_data *clk_bulks; + const char *name; + struct proc_dir_entry *procfs; + struct rk_crypto_stat stat; /* device lock */ spinlock_t lock; @@ -208,6 +225,7 @@ enum alg_type { ALG_TYPE_CIPHER, ALG_TYPE_ASYM, ALG_TYPE_AEAD, + ALG_TYPE_MAX, }; struct rk_crypto_algt { @@ -223,6 +241,7 @@ struct rk_crypto_algt { u32 mode; char *name; bool use_soft_aes192; + bool valid_flag; }; enum rk_hash_algo { From 4596f91c3d60869352a77d713886a784c3bf011f Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Thu, 21 Jul 2022 09:31:54 +0800 Subject: [PATCH 017/204] crypto: rockchip: add async_req NULL check Change-Id: Ie27402f25e0c0c8440f5e299694d91719514bc32 Signed-off-by: Lin Jinhan --- drivers/crypto/rockchip/rk_crypto_core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/crypto/rockchip/rk_crypto_core.c b/drivers/crypto/rockchip/rk_crypto_core.c index f1dddc782ae4..f69b9083c6d4 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.c +++ b/drivers/crypto/rockchip/rk_crypto_core.c @@ -353,6 +353,8 @@ static void rk_complete_op(struct rk_crypto_dev *rk_dev, int err) alg_ctx->ops.complete(rk_dev->async_req, err); + rk_dev->async_req = NULL; + tasklet_schedule(&rk_dev->queue_task); } @@ -388,6 +390,11 @@ static void rk_crypto_queue_task_cb(unsigned long data) struct crypto_async_request *async_req, *backlog; unsigned long flags; + if (rk_dev->async_req) { + dev_err(rk_dev->dev, "%s: Unexpected crypto paths.\n", __func__); + return; + } + rk_dev->err = 0; spin_lock_irqsave(&rk_dev->lock, flags); backlog = crypto_get_backlog(&rk_dev->queue); From 2df80b27a1e9a8f5034331619a93462b26433142 Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Fri, 9 Sep 2022 12:46:21 +0800 Subject: [PATCH 018/204] ARM: dts: rockchip: rv1106g-evb2-v10: update memory layout and sensor Signed-off-by: Weiwen Chen Change-Id: I717fb0217aa8001cd2f2824d0fc0848bef15b7c9 --- arch/arm/boot/dts/rv1106g-evb2-v10.dts | 47 ++++++++++++++++---------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/arch/arm/boot/dts/rv1106g-evb2-v10.dts b/arch/arm/boot/dts/rv1106g-evb2-v10.dts index deb02ea09767..afcdd663e852 100644 --- a/arch/arm/boot/dts/rv1106g-evb2-v10.dts +++ b/arch/arm/boot/dts/rv1106g-evb2-v10.dts @@ -14,7 +14,7 @@ compatible = "rockchip,rv1106g-evb2-v10", "rockchip,rv1106"; chosen { - bootargs = "loglevel=0 console=ttyFIQ0 root=/dev/rd0 snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0 driver_async_probe=dwmmc_rockchip rk_dma_heap_cma=24M mtdparts=sfc_nor:64K(env),256K@64K(idblock),256K(uboot),64K(vnvm),8M(boot),3M(userdata)"; + bootargs = "loglevel=0 console=ttyFIQ0 root=/dev/rd0 snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0 driver_async_probe=dwmmc_rockchip"; }; vcc_1v8: vcc-1v8 { @@ -54,7 +54,7 @@ csi_dphy_input0: endpoint@0 { reg = <0>; - remote-endpoint = <&sc3336_out>; + remote-endpoint = <&sc3338_out>; data-lanes = <1 2>; }; }; @@ -83,22 +83,23 @@ }; &i2c4 { - sc3336: sc3336@30 { - compatible = "smartsens,sc3336"; + rockchip,amp-shared; + + sc3338: sc3338@30 { + compatible = "smartsens,sc3338"; status = "okay"; reg = <0x30>; clocks = <&cru MCLK_REF_MIPI0>; clock-names = "xvclk"; - reset-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; - pwdn-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>; + 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 = "CMK-OT2119-PC1"; + rockchip,camera-module-name = "FKO1"; rockchip,camera-module-lens-name = "30IRC-F16"; port { - sc3336_out: endpoint { + sc3338_out: endpoint { remote-endpoint = <&csi_dphy_input0>; data-lanes = <1 2>; }; @@ -137,13 +138,8 @@ }; }; -&memory { - reg = <0x00000000 0x08000000>; -}; - -&meta { - /* reserved meta partition 384KB */ - reg = <0x01e00000 (384 * 0x400)>; +&mailbox { + status = "okay"; }; &rkcif { @@ -152,6 +148,7 @@ &rkcif_mipi_lvds { status = "okay"; + memory-region-thunderboot = <&rkisp_thunderboot>; pinctrl-names = "default"; pinctrl-0 = <&mipi_pins>; @@ -188,9 +185,25 @@ }; }; +&thunder_boot_service { + status = "okay"; +}; + &rkisp_thunderboot { - /* 9M for NV12 (w*h*1.5*2) w and h 16 align, 2304/1296 */ - reg = <0x01e60000 (9 * 0x00100000)>; + /* 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)>; }; &pwm10 { From 2ff8d70db79b0054ea497604edb7704ed55936e3 Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Thu, 8 Sep 2022 12:02:20 +0800 Subject: [PATCH 019/204] soc: rockchip: tb_service: clean up mcu's resource after mcu is done 1. make sure mcu is wfi 2. reset the mcu 3. free the reserved memory Signed-off-by: Ziyuan Xu Change-Id: Ia1f0db91789f142cfb567ac9f2b777a923c2435b --- .../rockchip/rockchip_thunderboot_service.c | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/soc/rockchip/rockchip_thunderboot_service.c b/drivers/soc/rockchip/rockchip_thunderboot_service.c index e552ed162389..fb40492c0685 100644 --- a/drivers/soc/rockchip/rockchip_thunderboot_service.c +++ b/drivers/soc/rockchip/rockchip_thunderboot_service.c @@ -2,11 +2,15 @@ /* * Copyright (C) 2022 Rockchip Electronics Co., Ltd. */ +#include #include #include +#include #include +#include #include #include +#include #include #include @@ -17,6 +21,9 @@ struct rk_tb_serv { struct device *dev; struct mbox_chan *mbox_rx_chan; struct mbox_client mbox_cl; + struct reset_control *rsts; + phys_addr_t mem_start; + size_t mem_size; }; static atomic_t mcu_done = ATOMIC_INIT(0); @@ -55,6 +62,16 @@ static void do_mcu_done(struct rk_tb_serv *serv) rockchip_mbox_read_msg(serv->mbox_rx_chan, &msg); if (msg.cmd == CMD_MCU_STATUS && msg.data == MCU_STATUS_DONE) { + void *start, *end; + + /* make sure mcu is wfi */ + udelay(15); + reset_control_assert(serv->rsts); + + start = phys_to_virt(serv->mem_start); + end = start + serv->mem_size; + free_reserved_area(start, end, -1, "rtos"); + spin_lock(&lock); if (atomic_read(&mcu_done)) { spin_unlock(&lock); @@ -85,11 +102,34 @@ static int rk_tb_serv_probe(struct platform_device *pdev) { struct rk_tb_serv *serv; struct mbox_client *mbox_cl; + struct device_node *mem; + struct resource reg; + int ret; serv = devm_kzalloc(&pdev->dev, sizeof(*serv), GFP_KERNEL); if (!serv) return -ENOMEM; + mem = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); + if (!mem) { + dev_err(&pdev->dev, "missing \"memory-region\" property\n"); + return -ENODEV; + } + + ret = of_address_to_resource(mem, 0, ®); + of_node_put(mem); + if (ret) { + dev_err(&pdev->dev, "missing \"reg\" property\n"); + return -ENODEV; + } + + serv->mem_start = reg.start; + serv->mem_size = resource_size(®); + + serv->rsts = devm_reset_control_array_get_optional_exclusive(&pdev->dev); + if (IS_ERR(serv->rsts) && PTR_ERR(serv->rsts) == -EPROBE_DEFER) + return -EPROBE_DEFER; + platform_set_drvdata(pdev, serv); mbox_cl = &serv->mbox_cl; From 58c3eecac4dccad924bd748cad06ee90cd1d7fbf Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Fri, 9 Sep 2022 10:36:01 +0800 Subject: [PATCH 020/204] ARM: dts: rockchip: rv1106-thunder-boot: export reset and reserved_mem node for tb_service Signed-off-by: Ziyuan Xu Change-Id: Ie1bc97c536fa2e48331ff9e3fe41b70b8c8f5886 --- arch/arm/boot/dts/rv1106-thunder-boot.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/rv1106-thunder-boot.dtsi b/arch/arm/boot/dts/rv1106-thunder-boot.dtsi index df76f8fe8268..f4951af8fa8f 100644 --- a/arch/arm/boot/dts/rv1106-thunder-boot.dtsi +++ b/arch/arm/boot/dts/rv1106-thunder-boot.dtsi @@ -78,6 +78,11 @@ compatible = "rockchip,thunder-boot-service"; mbox-names = "amp-rx"; mboxes = <&mailbox 1>; + resets = <&cru SRST_CORE_MCU>, <&cru SRST_CORE_MCU_PWRUP>, + <&cru SRST_CORE_MCU_CPU>, <&cru SRST_T_CORE_MCU_CPU>; + reset-names = "core_mcu", "core_mcu_pwrup", + "core_mcu_cpu", "t_core_mcu_cpu"; + memory-region = <&rtos>; status = "disabled"; }; }; From fea88dfd42c245a82c7ee01cc14ea39e8ee1aa33 Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Thu, 8 Sep 2022 19:11:57 +0800 Subject: [PATCH 021/204] ARM: configs: rv1106-battery-ipc.config: update use sc3338 default Signed-off-by: Su Yuefu Change-Id: I3ca8bd001c825ef55b72a22f735fba2faf52140c --- arch/arm/configs/rv1106-battery-ipc.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/rv1106-battery-ipc.config b/arch/arm/configs/rv1106-battery-ipc.config index 9e8e5eb72bbd..ac191f3ba281 100644 --- a/arch/arm/configs/rv1106-battery-ipc.config +++ b/arch/arm/configs/rv1106-battery-ipc.config @@ -13,7 +13,7 @@ CONFIG_SND_SOC_ROCKCHIP=m CONFIG_SND_SOC_ROCKCHIP_I2S_TDM=m CONFIG_SPI=y CONFIG_VIDEO_SC230AI=y -CONFIG_VIDEO_SC3336=y +CONFIG_VIDEO_SC3338=y # CONFIG_AD2S1200 is not set # CONFIG_AD2S1210 is not set # CONFIG_AD2S90 is not set From 0a754264ac40fda763a218e71ae7a28b0ecceee2 Mon Sep 17 00:00:00 2001 From: Wu Liangqing Date: Fri, 9 Sep 2022 02:21:52 +0000 Subject: [PATCH 022/204] arm64: dts: rockchip: px30/rk3326-evb move include px30-android.dtsi to dts Change-Id: I338587c1573486aeaee774e8c704f575d64ca059 Signed-off-by: Wu Liangqing --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-avb.dts | 2 ++ arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts | 2 ++ arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi | 3 --- arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11-avb.dts | 2 ++ arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11.dts | 2 ++ arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts | 2 ++ arch/arm64/boot/dts/rockchip/px30-evb-ext-rk618.dtsi | 1 + arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-avb.dts | 3 +++ arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts | 3 +++ arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi | 4 ---- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11-avb.dts | 3 +++ arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11.dts | 3 +++ 12 files changed, 23 insertions(+), 7 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-avb.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-avb.dts index e9a56be8c394..f213818200a8 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-avb.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-avb.dts @@ -4,6 +4,8 @@ */ /dts-v1/; +#include "px30.dtsi" +#include "px30-android.dtsi" #include "px30-evb-ddr3-v10.dtsi" / { diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 4fe2ab7bf8ca..8d8bea85b1cd 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -5,6 +5,8 @@ */ /dts-v1/; +#include "px30.dtsi" +#include "px30-android.dtsi" #include "px30-evb-ddr3-v10.dtsi" / { diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi index ee2a47830a35..271d78714944 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi @@ -3,14 +3,11 @@ * Copyright (c) 2017-2019 Fuzhou Rockchip Electronics Co., Ltd */ -/dts-v1/; #include #include #include #include #include -#include "px30.dtsi" -#include "px30-android.dtsi" / { adc-keys { diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11-avb.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11-avb.dts index f2659a7f524e..4e6170f8e691 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11-avb.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11-avb.dts @@ -4,6 +4,8 @@ */ /dts-v1/; +#include "px30.dtsi" +#include "px30-android.dtsi" #include "px30-evb-ddr3-v10.dtsi" / { diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11.dts index 2e59a09d3c5c..a4429672e190 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11.dts @@ -4,6 +4,8 @@ */ /dts-v1/; +#include "px30.dtsi" +#include "px30-android.dtsi" #include "px30-evb-ddr3-v10.dtsi" / { diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index ef9f356f9913..df920932b154 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -4,6 +4,8 @@ */ /dts-v1/; +#include "px30.dtsi" +#include "px30-android.dtsi" #include "px30-evb-ddr3-v10.dtsi" #include "px30-ddr4p416dd6-timing.dtsi" diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ext-rk618.dtsi b/arch/arm64/boot/dts/rockchip/px30-evb-ext-rk618.dtsi index 0eac63181407..f076787f5210 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ext-rk618.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ext-rk618.dtsi @@ -7,6 +7,7 @@ #include #include #include "px30-evb-ddr3-v10.dtsi" +#include "px30-android.dtsi" &dsi { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-avb.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-avb.dts index 4c12a79f814b..274dccd08acc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-avb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-avb.dts @@ -4,7 +4,10 @@ */ /dts-v1/; +#include "rk3326.dtsi" +#include "px30-android.dtsi" #include "rk3326-evb-lp3-v10.dtsi" +#include "rk3326-863-cif-sensor.dtsi" / { model = "Rockchip rk3326 evb board"; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts index 58bbfdafb489..cc2057e8f8c5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dts @@ -4,7 +4,10 @@ */ /dts-v1/; +#include "rk3326.dtsi" +#include "px30-android.dtsi" #include "rk3326-evb-lp3-v10.dtsi" +#include "rk3326-863-cif-sensor.dtsi" / { model = "Rockchip rk3326 evb board"; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi index 688b5be11be5..fbadb5259adc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi @@ -3,15 +3,11 @@ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd */ -/dts-v1/; #include #include #include #include #include -#include "rk3326.dtsi" -#include "rk3326-863-cif-sensor.dtsi" -#include "px30-android.dtsi" / { adc-keys { diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11-avb.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11-avb.dts index 2f0c3fc3a38d..0f2a35179f43 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11-avb.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11-avb.dts @@ -4,7 +4,10 @@ */ /dts-v1/; +#include "rk3326.dtsi" +#include "px30-android.dtsi" #include "rk3326-evb-lp3-v10.dtsi" +#include "rk3326-863-cif-sensor.dtsi" / { model = "Rockchip rk3326 evb board"; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11.dts index 139efd9d1332..f8a3eef33f4e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11.dts @@ -4,7 +4,10 @@ */ /dts-v1/; +#include "rk3326.dtsi" +#include "px30-android.dtsi" #include "rk3326-evb-lp3-v10.dtsi" +#include "rk3326-863-cif-sensor.dtsi" / { model = "Rockchip rk3326 evb board"; From cd13ec865c6a811079d4eed2c4c21540b07c4044 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Wed, 14 Sep 2022 10:54:32 +0800 Subject: [PATCH 023/204] MALI: bifrost: log: not to output "Protected memory allocator not found, Firmware protected mode entry will not be supported" as err log It's allowed to run without firmware protected mode entry. While the customer of RK3588 might be troubled by the log. Change-Id: I9f1b7c795f2095f1851692c93a7f4598acf702fc Signed-off-by: Zhen Chen --- drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.c index 553ee03dd9e1..beed4a3cd736 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.c @@ -589,7 +589,7 @@ static int parse_memory_setup_entry(struct kbase_device *kbdev, protected_mode = true; if (protected_mode && kbdev->csf.pma_dev == NULL) { - dev_err(kbdev->dev, + dev_dbg(kbdev->dev, "Protected memory allocator not found, Firmware protected mode entry will not be supported"); return 0; } From 5316507f751bf75012709571e881bdb62eadf870 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Fri, 9 Sep 2022 19:08:23 +0800 Subject: [PATCH 024/204] media: rockchip: isp: fix mipi error for isp2x with multi sensor Change-Id: Icdd6536bed9890c2b856ee28da805ee5f1cbfc17 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/regs.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/rockchip/isp/regs.h b/drivers/media/platform/rockchip/isp/regs.h index 48b6bc44c081..2d4588663354 100644 --- a/drivers/media/platform/rockchip/isp/regs.h +++ b/drivers/media/platform/rockchip/isp/regs.h @@ -1915,6 +1915,10 @@ static inline void force_cfg_update(struct rkisp_device *dev) u32 val = CIF_MI_CTRL_INIT_OFFSET_EN | CIF_MI_CTRL_INIT_BASE_EN; bool is_unite = dev->hw_dev->is_unite; + if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) { + val |= rkisp_read_reg_cache(dev, CIF_MI_CTRL); + rkisp_write(dev, CIF_MI_CTRL, val, true); + } dev->hw_dev->is_mi_update = true; rkisp_unite_set_bits(dev, CIF_MI_CTRL, 0, val, false, is_unite); val = CIF_MI_INIT_SOFT_UPD; From d4f6aaf7bc43d1a2b5ae0e3936d8de2076a840d9 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Wed, 7 Sep 2022 14:13:30 +0800 Subject: [PATCH 025/204] media: rockchip: isp: default reg config after reset Change-Id: Ib1e26819a1abfa74c072925af5dbb1ad7ec451f4 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/hw.c | 49 ++++++++++++++------- drivers/media/platform/rockchip/isp/rkisp.c | 2 - 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/hw.c b/drivers/media/platform/rockchip/isp/hw.c index db52cfe18017..65934f24a6e8 100644 --- a/drivers/media/platform/rockchip/isp/hw.c +++ b/drivers/media/platform/rockchip/isp/hw.c @@ -594,7 +594,15 @@ static inline bool is_iommu_enable(struct device *dev) void rkisp_soft_reset(struct rkisp_hw_dev *dev, bool is_secure) { void __iomem *base = dev->base_addr; - u32 val; + u32 val, iccl0, iccl1, clk_ctrl0, clk_ctrl1; + + /* record clk config and recover */ + iccl0 = readl(base + CIF_ICCL); + clk_ctrl0 = readl(base + CTRL_VI_ISP_CLK_CTRL); + if (dev->is_unite) { + iccl1 = readl(dev->base_next_addr + CIF_ICCL); + clk_ctrl1 = readl(dev->base_next_addr + CTRL_VI_ISP_CLK_CTRL); + } if (is_secure) { /* if isp working, cru reset isn't secure. @@ -633,6 +641,29 @@ void rkisp_soft_reset(struct rkisp_hw_dev *dev, bool is_secure) rockchip_iommu_disable(dev->dev); rockchip_iommu_enable(dev->dev); } + + writel(iccl0, base + CIF_ICCL); + writel(clk_ctrl0, base + CTRL_VI_ISP_CLK_CTRL); + if (dev->is_unite) { + writel(iccl1, dev->base_next_addr + CIF_ICCL); + writel(clk_ctrl1, dev->base_next_addr + CTRL_VI_ISP_CLK_CTRL); + } + + /* default config */ + if (dev->isp_ver == ISP_V12 || dev->isp_ver == ISP_V13) { + /* disable csi_rx interrupt */ + writel(0, dev->base_addr + CIF_ISP_CSI0_CTRL0); + writel(0, dev->base_addr + CIF_ISP_CSI0_MASK1); + writel(0, dev->base_addr + CIF_ISP_CSI0_MASK2); + writel(0, dev->base_addr + CIF_ISP_CSI0_MASK3); + } else if (dev->isp_ver == ISP_V32) { + /* disable down samplling default */ + writel(ISP32_DS_DS_DIS, dev->base_addr + ISP32_MI_MPDS_WR_CTRL); + writel(ISP32_DS_DS_DIS, dev->base_addr + ISP32_MI_BPDS_WR_CTRL); + + writel(0, dev->base_addr + ISP32_BLS_ISP_OB_PREDGAIN); + writel(0x37, dev->base_addr + ISP32_MI_WR_WRAP_CTRL); + } } static void isp_config_clk(struct rkisp_hw_dev *dev, int on) @@ -722,22 +753,6 @@ static int enable_sys_clk(struct rkisp_hw_dev *dev) rkisp_set_clk_rate(dev->clks[5], rate); rkisp_soft_reset(dev, false); isp_config_clk(dev, true); - - if (dev->isp_ver == ISP_V12 || dev->isp_ver == ISP_V13) { - /* disable csi_rx interrupt */ - writel(0, dev->base_addr + CIF_ISP_CSI0_CTRL0); - writel(0, dev->base_addr + CIF_ISP_CSI0_MASK1); - writel(0, dev->base_addr + CIF_ISP_CSI0_MASK2); - writel(0, dev->base_addr + CIF_ISP_CSI0_MASK3); - } else if (dev->isp_ver == ISP_V32) { - /* disable down samplling default */ - writel(ISP32_DS_DS_DIS, dev->base_addr + ISP32_MI_MPDS_WR_CTRL); - writel(ISP32_DS_DS_DIS, dev->base_addr + ISP32_MI_BPDS_WR_CTRL); - - writel(0, dev->base_addr + ISP32_BLS_ISP_OB_PREDGAIN); - writel(0x37, dev->base_addr + ISP32_MI_WR_WRAP_CTRL); - } - return 0; err: for (--i; i >= 0; --i) diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index d2b6a13a53ab..b89935cd4aac 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -1935,7 +1935,6 @@ static int rkisp_isp_stop(struct rkisp_device *dev) "MI_CTRL:%x, ISP_CTRL:%x\n", readl(base + CIF_MI_CTRL), readl(base + CIF_ISP_CTRL)); - val = rkisp_read(dev, CTRL_VI_ISP_CLK_CTRL, true); if (!in_interrupt()) { /* normal case */ /* check the isp_clk before isp reset operation */ @@ -1949,7 +1948,6 @@ static int rkisp_isp_stop(struct rkisp_device *dev) } rkisp_soft_reset(dev->hw_dev, false); } - rkisp_write(dev, CTRL_VI_ISP_CLK_CTRL, val, true); if (dev->isp_ver == ISP_V12 || dev->isp_ver == ISP_V13) { writel(0, base + CIF_ISP_CSI0_CSI2_RESETN); From 0b356f8ce8d0a718cef50a38e2f326961d28272c Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Tue, 19 Jul 2022 18:37:59 +0800 Subject: [PATCH 026/204] arm64/configs: add rk3568_linux.config defconfig CONFIG_MALI_CSF_SUPPORT is not used on RK356X Socs, that will cause the mali is abnormal with RK356x Socs. CONFIG_BCMDHD_PCIE and CONFIG_BCMDHD_SDIO can only be selected from two configurations, since that bcmdhd driver cannot be compatible with it at present. SDIO interfaces are widely used by default, at least on our EVB boards. Tested on RK3568 EVB1 boards: export CROSS_COMPILE=aarch64-linux-gnu- make ARCH=arm64 rockchip_linux_defconfig rk3568_linux.config make ARCH=arm64 rk3568-evb1-ddr4-v10-linux.img -j8 Signed-off-by: Caesar Wang Change-Id: Iea3c3d70fabe9920b95d6b096028b4d73c5b39f1 --- arch/arm64/configs/rk3568_linux.config | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 arch/arm64/configs/rk3568_linux.config diff --git a/arch/arm64/configs/rk3568_linux.config b/arch/arm64/configs/rk3568_linux.config new file mode 100644 index 000000000000..f2a23294e572 --- /dev/null +++ b/arch/arm64/configs/rk3568_linux.config @@ -0,0 +1,3 @@ +# CONFIG_MALI_CSF_SUPPORT is not set +CONFIG_BCMDHD_SDIO=y +# CONFIG_BCMDHD_PCIE is not set From e0c7d1b49fe3d12cd7870fa7d9a5c35539d55463 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 7 Jul 2022 16:02:13 +0800 Subject: [PATCH 027/204] arm64/configs: add rk3399_linux.config on rockchip platform CONFIG_BCMDHD_PCIE and CONFIG_BCMDHD_SDIO can only be selected from two configurations, since that bcmdhd driver cannot be compatible with it at present. SDIO interfaces are widely used by default, at least on our EVB boards. Tested on RK3399 EVB IND boards: export CROSS_COMPILE=aarch64-linux-gnu- make ARCH=arm64 rockchip_linux_defconfig rk3399_linux.config make ARCH=arm64 rk3399-evb-ind-lpddr4-linux.img -j8 Signed-off-by: Caesar Wang Change-Id: I7c1c416b58f618e1cee8f76608c24f750437bfa1 --- arch/arm64/configs/rk3399_linux.config | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 arch/arm64/configs/rk3399_linux.config diff --git a/arch/arm64/configs/rk3399_linux.config b/arch/arm64/configs/rk3399_linux.config new file mode 100644 index 000000000000..05f35714ca12 --- /dev/null +++ b/arch/arm64/configs/rk3399_linux.config @@ -0,0 +1,2 @@ +CONFIG_BCMDHD_SDIO=y +# CONFIG_BCMDHD_PCIE is not set From f111173dd3ee6df4abb8a17f411215cedc29ce80 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Fri, 2 Sep 2022 19:48:41 +0800 Subject: [PATCH 028/204] drm/rockchip: vop2: config vrr when crtc status change Signed-off-by: Zhang Yubing Change-Id: Ie6d0b0c263528fe570c14a4a6e0b23a24316412c --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 9dbd88daed2a..1c04095424fe 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -6996,7 +6996,8 @@ static int vop2_crtc_atomic_check(struct drm_crtc *crtc, } } - if (vcstate->request_refresh_rate != new_vcstate->request_refresh_rate) + if ((vcstate->request_refresh_rate != new_vcstate->request_refresh_rate) || + crtc_state->active_changed || crtc_state->mode_changed) vp->refresh_rate_change = true; else vp->refresh_rate_change = false; From 47e85085826daf6401265b803ac9ac7116ae6bb4 Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Tue, 13 Sep 2022 17:20:46 +0800 Subject: [PATCH 029/204] crypto: rockchip: rk3326/px30 add aes gcm support Signed-off-by: Lin Jinhan Change-Id: I75949554d4f573c63092841eef76765a69cc6b24 --- drivers/crypto/rockchip/rk_crypto_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/rockchip/rk_crypto_core.c b/drivers/crypto/rockchip/rk_crypto_core.c index f69b9083c6d4..f25d722ea776 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.c +++ b/drivers/crypto/rockchip/rk_crypto_core.c @@ -610,7 +610,7 @@ static void rk_crypto_action(void *data) } static char *crypto_no_sm_algs_name[] = { - "ecb(aes)", "cbc(aes)", "cfb(aes)", "ofb(aes)", "ctr(aes)", + "ecb(aes)", "cbc(aes)", "cfb(aes)", "ofb(aes)", "ctr(aes)", "gcm(aes)", "ecb(des)", "cbc(des)", "cfb(des)", "ofb(des)", "ecb(des3_ede)", "cbc(des3_ede)", "cfb(des3_ede)", "ofb(des3_ede)", "sha1", "sha224", "sha256", "sha384", "sha512", "md5", From d9d92d7f3612027ebb3d93687e725fc93846e1b0 Mon Sep 17 00:00:00 2001 From: Sach Lin Date: Mon, 5 Sep 2022 19:45:28 +0800 Subject: [PATCH 030/204] misc: rk803: fix current regs error. Signed-off-by: Sach Lin Change-Id: I4d01f9ca8df493763662719db9253bd8887746e8 --- drivers/misc/rk803.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/misc/rk803.c b/drivers/misc/rk803.c index a6a229aa7f05..b97b607af3af 100644 --- a/drivers/misc/rk803.c +++ b/drivers/misc/rk803.c @@ -25,8 +25,7 @@ #define RK803_TIMEOUT 1000 /* usec */ enum SL_LED_CURRENT { - LED_0MA = 0, - LED_100MA, + LED_100MA = 0, LED_200MA, LED_300MA, LED_400MA, @@ -40,12 +39,12 @@ enum SL_LED_CURRENT { LED_1200MA, LED_1300MA, LED_1400MA, - LED_1544MA = 15, + LED_1500MA, LED_1600MA, LED_1700MA, LED_1800MA, LED_1900MA, - LED_2000MA = 20, + LED_2000MA, LED_2100MA, LED_2200MA, LED_2300MA, @@ -55,7 +54,7 @@ enum SL_LED_CURRENT { LED_2700MA, LED_2800MA, LED_2900MA, - LED_3000MA = 30, + LED_3000MA, LED_3100MA, LED_3200MA }; From 80c7560709002667d328c6fcf0a5b91fd7960154 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Thu, 15 Sep 2022 14:44:02 +0800 Subject: [PATCH 031/204] media: rockchip: isp: fix isp20 mi no work isp20 mi config no save to cache and reg write to hw Change-Id: I3cefcf26cbd7df7e63ca8fea903999d70ca34b78 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/rockchip/isp/regs.h b/drivers/media/platform/rockchip/isp/regs.h index 2d4588663354..c902dc0044e5 100644 --- a/drivers/media/platform/rockchip/isp/regs.h +++ b/drivers/media/platform/rockchip/isp/regs.h @@ -1915,7 +1915,7 @@ static inline void force_cfg_update(struct rkisp_device *dev) u32 val = CIF_MI_CTRL_INIT_OFFSET_EN | CIF_MI_CTRL_INIT_BASE_EN; bool is_unite = dev->hw_dev->is_unite; - if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) { + if (dev->isp_ver == ISP_V21) { val |= rkisp_read_reg_cache(dev, CIF_MI_CTRL); rkisp_write(dev, CIF_MI_CTRL, val, true); } From 1c5d3aa79fe614a6eab234e58f137a1d7728bfb5 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Thu, 15 Sep 2022 14:17:31 +0800 Subject: [PATCH 032/204] drm/bridge: synopsys: dw-hdmi-qp: No need to force maxX/maxY to 9000 The max width and height have been set as default value(16384x16384). If HDMI sets it to a fixed value, it will cause no output in Debian's CMD mode. Signed-off-by: Algea Cao Change-Id: I2180109b285a9efd562864c6dd3c808b5667232e --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index cc0090f39e72..2cc24007498f 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -2265,14 +2265,8 @@ static void dw_hdmi_connector_force(struct drm_connector *connector) mutex_unlock(&hdmi->mutex); } -static int dw_hdmi_qp_fill_modes(struct drm_connector *connector, u32 max_x, - u32 max_y) -{ - return drm_helper_probe_single_connector_modes(connector, 9000, 9000); -} - static const struct drm_connector_funcs dw_hdmi_connector_funcs = { - .fill_modes = dw_hdmi_qp_fill_modes, + .fill_modes = drm_helper_probe_single_connector_modes, .detect = dw_hdmi_connector_detect, .destroy = drm_connector_cleanup, .force = dw_hdmi_connector_force, From 4e8841e155560026d620542d4307a8a95915a68b Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Tue, 13 Sep 2022 10:11:17 +0800 Subject: [PATCH 033/204] sched: cpufreq_schedutil: add attribute for change target_load Default target_load is 80% and change it by the follow command: echo 65 > /sys/devices/system/cpu/cpu0/cpufreq/schedutil/target_load Change-Id: Icb02c36eab345a3f2e2d065fba76fdc015f47fa4 Signed-off-by: Liang Chen --- kernel/sched/cpufreq_schedutil.c | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index b365895c2e2e..26cf3c3d7032 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -19,6 +19,9 @@ struct sugov_tunables { struct gov_attr_set attr_set; unsigned int rate_limit_us; +#ifdef CONFIG_ARCH_ROCKCHIP + unsigned int target_load; +#endif }; struct sugov_policy { @@ -170,7 +173,11 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy, if (next_freq) freq = next_freq; else +#ifdef CONFIG_ARCH_ROCKCHIP + freq = div64_ul((u64)(100 * freq / sg_policy->tunables->target_load) * util, max); +#else freq = map_util_freq(util, freq, max); +#endif if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) return sg_policy->next_freq; @@ -612,8 +619,39 @@ rate_limit_us_store(struct gov_attr_set *attr_set, const char *buf, size_t count static struct governor_attr rate_limit_us = __ATTR_RW(rate_limit_us); +#ifdef CONFIG_ARCH_ROCKCHIP +static ssize_t target_load_show(struct gov_attr_set *attr_set, char *buf) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + + return sprintf(buf, "%u\n", tunables->target_load); +} + +static ssize_t +target_load_store(struct gov_attr_set *attr_set, const char *buf, size_t count) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + unsigned int target_load; + + if (kstrtouint(buf, 10, &target_load)) + return -EINVAL; + + if (!target_load || (target_load > 100)) + return -EINVAL; + + tunables->target_load = target_load; + + return count; +} + +static struct governor_attr target_load = __ATTR_RW(target_load); +#endif + static struct attribute *sugov_attrs[] = { &rate_limit_us.attr, +#ifdef CONFIG_ARCH_ROCKCHIP + &target_load.attr, +#endif NULL }; ATTRIBUTE_GROUPS(sugov); @@ -777,6 +815,9 @@ static int sugov_init(struct cpufreq_policy *policy) } tunables->rate_limit_us = cpufreq_policy_transition_delay_us(policy); +#ifdef CONFIG_ARCH_ROCKCHIP + tunables->target_load = 80; +#endif policy->governor_data = sg_policy; sg_policy->tunables = tunables; From 68850661b51e40faf9f5f21e4b7a083476da3f99 Mon Sep 17 00:00:00 2001 From: William Wu Date: Wed, 14 Sep 2022 10:42:50 +0800 Subject: [PATCH 034/204] usb: host: ehci-platform: Add device_link between the ehci and companion Rockchip ehci controller has companion ohci controller, and the ohci depends on the ehci, if the ehci controller has been suspend or shutdown, it shouldn't access the ohci controller, otherwise, the system may hang in ohci_readl or ohci_writel on Rockchip platforms. In order to enforce suspend/resume and shutdown ordering, this commit creates link between the ehci and ohci. This link avoids to suspend or shutdown ehci before its companion ohci. Corresponding, DL_FLAG_AUTOREMOVE_CONSUMER can't be added, then device_link_removed should be added explicitly. Meanwhile, the ehci must not be resumed after its companion if the companion is the consumer device of ehci. Signed-off-by: William Wu Change-Id: If2935c651341917251c2178a6833357a73b71079 --- drivers/usb/host/ehci-platform.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 3e48737f893f..e6f0871375b9 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -276,6 +276,8 @@ static int ehci_platform_probe(struct platform_device *dev) struct ehci_platform_priv *priv; struct ehci_hcd *ehci; int err, irq, clk = 0; + struct device *companion_dev; + struct device_link *link; if (usb_disabled()) return -ENODEV; @@ -414,6 +416,21 @@ static int ehci_platform_probe(struct platform_device *dev) if (of_usb_get_phy_mode(dev->dev.of_node) == USBPHY_INTERFACE_MODE_HSIC) ehci_usic_init(hcd); + 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) { + link = device_link_add(companion_dev, hcd->self.controller, + DL_FLAG_STATELESS); + if (!link) { + dev_err(&dev->dev, "Unable to link %s\n", + dev_name(companion_dev)); + err = -EINVAL; + goto err_power; + } + } + } + device_wakeup_enable(hcd->self.controller); device_enable_async_suspend(hcd->self.controller); platform_set_drvdata(dev, hcd); @@ -447,11 +464,19 @@ static int ehci_platform_remove(struct platform_device *dev) struct usb_hcd *hcd = platform_get_drvdata(dev); struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); + struct device *companion_dev; int clk; if (priv->quirk_poll) quirk_poll_end(priv); + 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) + device_link_remove(companion_dev, hcd->self.controller); + } + usb_remove_hcd(hcd); if (pdata->power_off) @@ -510,7 +535,7 @@ static int __maybe_unused ehci_platform_resume(struct device *dev) } companion_dev = usb_of_get_companion_dev(hcd->self.controller); - if (companion_dev) { + if (companion_dev && !device_is_dependent(hcd->self.controller, companion_dev)) { device_pm_wait_for_dev(hcd->self.controller, companion_dev); put_device(companion_dev); } From 60a91711139a5cb3f10b812c3c374003a07c53c5 Mon Sep 17 00:00:00 2001 From: William Wu Date: Wed, 14 Sep 2022 11:28:39 +0800 Subject: [PATCH 035/204] arm64: dts: rockchip: rk3588: Add companion for ehci Add the companion ohci controller for usb_host0_ehci and usb_host1_ehci. Then we can use device_link to enforce suspend/resume and shutdown ordering for them. Signed-off-by: William Wu Change-Id: I8bc7c21b257beed40163178e4a1fced0763dddd9 --- arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi index 3a1c2bc73eb6..9fdddf666576 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -1908,11 +1908,12 @@ }; usb_host0_ehci: usb@fc800000 { - compatible = "generic-ehci"; + compatible = "rockchip,rk3588-ehci", "generic-ehci"; reg = <0x0 0xfc800000 0x0 0x40000>; interrupts = ; clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST_ARB0>, <&u2phy2>; clock-names = "usbhost", "arbiter", "utmi"; + companion = <&usb_host0_ohci>; phys = <&u2phy2_host>; phy-names = "usb2-phy"; power-domains = <&power RK3588_PD_USB>; @@ -1932,11 +1933,12 @@ }; usb_host1_ehci: usb@fc880000 { - compatible = "generic-ehci"; + compatible = "rockchip,rk3588-ehci", "generic-ehci"; reg = <0x0 0xfc880000 0x0 0x40000>; interrupts = ; clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST_ARB1>, <&u2phy3>; clock-names = "usbhost", "arbiter", "utmi"; + companion = <&usb_host1_ohci>; phys = <&u2phy3_host>; phy-names = "usb2-phy"; power-domains = <&power RK3588_PD_USB>; From 70a514ab1424d8e5eb58367aba10d257eaee8da7 Mon Sep 17 00:00:00 2001 From: Lin Jianhua Date: Fri, 9 Sep 2022 17:12:55 +0800 Subject: [PATCH 036/204] arm64: dts: rockchip: px30-evb: move some configs to common board dtsi files Signed-off-by: Lin Jianhua Change-Id: I30a74d33f5d865925ddd3d22bb28425295b7f68b --- arch/arm64/boot/dts/rockchip/Makefile | 4 +- .../dts/rockchip/px30-evb-ddr3-v10-avb.dts | 43 - .../dts/rockchip/px30-evb-ddr3-v10-linux.dts | 1071 +---------------- .../boot/dts/rockchip/px30-evb-ddr3-v10.dts | 13 - .../boot/dts/rockchip/px30-evb-ddr3-v10.dtsi | 28 +- .../boot/dts/rockchip/px30-evb-ddr4-v10.dts | 43 - ...avb.dts => px30-mini-evb-ddr3-v11-avb.dts} | 5 +- ...dr3-v11.dts => px30-mini-evb-ddr3-v11.dts} | 5 +- .../boot/dts/rockchip/px30-mini-evb-v11.dtsi | 31 + 9 files changed, 104 insertions(+), 1139 deletions(-) rename arch/arm64/boot/dts/rockchip/{px30-evb-ddr3-v11-avb.dts => px30-mini-evb-ddr3-v11-avb.dts} (96%) rename arch/arm64/boot/dts/rockchip/{px30-evb-ddr3-v11.dts => px30-mini-evb-ddr3-v11.dts} (97%) create mode 100644 arch/arm64/boot/dts/rockchip/px30-mini-evb-v11.dtsi diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index 86cf9815f5e8..82683049b811 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -3,8 +3,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb-ddr3-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb-ddr3-v10-avb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb-ddr3-v10-linux.dtb -dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb-ddr3-v11.dtb -dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb-ddr3-v11-avb.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-mini-evb-ddr3-v11.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-mini-evb-ddr3-v11-avb.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb-ddr3-v11-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb-ddr4-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-evb.dtb diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-avb.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-avb.dts index f213818200a8..7b122c5461f8 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-avb.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-avb.dts @@ -11,28 +11,6 @@ / { model = "Rockchip PX30 evb ddr3 board"; compatible = "rockchip,px30-evb-ddr3-v10-avb", "rockchip,px30"; - - rk_headset: rk-headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&hp_det>; - io-channels = <&saradc 1>; - }; - - wireless-bluetooth { - compatible = "bluetooth-platdata"; - clocks = <&rk809 1>; - clock-names = "ext_clock"; - uart_rts_gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_LOW>; - pinctrl-names = "default","rts_gpio"; - pinctrl-0 = <&uart1_rts>; - pinctrl-1 = <&uart1_rts_gpio>; - BT,reset_gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; - BT,wake_gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; - BT,wake_host_irq = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; }; &chosen { @@ -297,24 +275,3 @@ }; }; }; - -&gmac { - phy-supply = <&vcc_phy>; - clock_in_out = "input"; - assigned-clocks = <&cru SCLK_GMAC>; - assigned-clock-parents = <&gmac_clkin>; - pinctrl-names = "default"; - pinctrl-0 = <&rmii_pins &mac_refclk>; - snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - snps,reset-delays-us = <0 50000 50000>; - status = "okay"; -}; - -&pinctrl { - headphone { - hp_det: hp-det { - rockchip,pins = <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; - }; - }; -}; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-linux.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-linux.dts index 680e67c42a88..9edb04ae267c 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-linux.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10-linux.dts @@ -4,197 +4,31 @@ */ /dts-v1/; -#include -#include -#include -#include -#include #include "px30.dtsi" #include "rk3326-linux.dtsi" +#include "px30-evb-ddr3-v10.dtsi" / { model = "Rockchip linux PX30 evb ddr3 board"; compatible = "rockchip,px30-evb-ddr3-v10-linux", "rockchip,px30"; - adc-keys { - compatible = "adc-keys"; - io-channels = <&saradc 2>; - io-channel-names = "buttons"; - poll-interval = <100>; - keyup-threshold-microvolt = <1800000>; - - esc-key { - linux,code = ; - label = "esc"; - press-threshold-microvolt = <1310000>; - }; - - home-key { - linux,code = ; - label = "home"; - press-threshold-microvolt = <624000>; - }; - - menu-key { - linux,code = ; - label = "menu"; - press-threshold-microvolt = <987000>; - }; - - vol-down-key { - linux,code = ; - label = "volume down"; - press-threshold-microvolt = <300000>; - }; - - vol-up-key { - linux,code = ; - label = "volume up"; - press-threshold-microvolt = <17000>; - }; - }; - - backlight: backlight { - compatible = "pwm-backlight"; - pwms = <&pwm1 0 25000 0>; - brightness-levels = < - 0 1 2 3 4 5 6 7 - 8 9 10 11 12 13 14 15 - 16 17 18 19 20 21 22 23 - 24 25 26 27 28 29 30 31 - 32 33 34 35 36 37 38 39 - 40 41 42 43 44 45 46 47 - 48 49 50 51 52 53 54 55 - 56 57 58 59 60 61 62 63 - 64 65 66 67 68 69 70 71 - 72 73 74 75 76 77 78 79 - 80 81 82 83 84 85 86 87 - 88 89 90 91 92 93 94 95 - 96 97 98 99 100 101 102 103 - 104 105 106 107 108 109 110 111 - 112 113 114 115 116 117 118 119 - 120 121 122 123 124 125 126 127 - 128 129 130 131 132 133 134 135 - 136 137 138 139 140 141 142 143 - 144 145 146 147 148 149 150 151 - 152 153 154 155 156 157 158 159 - 160 161 162 163 164 165 166 167 - 168 169 170 171 172 173 174 175 - 176 177 178 179 180 181 182 183 - 184 185 186 187 188 189 190 191 - 192 193 194 195 196 197 198 199 - 200 201 202 203 204 205 206 207 - 208 209 210 211 212 213 214 215 - 216 217 218 219 220 221 222 223 - 224 225 226 227 228 229 230 231 - 232 233 234 235 236 237 238 239 - 240 241 242 243 244 245 246 247 - 248 249 250 251 252 253 254 255>; - default-brightness-level = <200>; - }; - - charge-animation { - compatible = "rockchip,uboot-charge"; - rockchip,uboot-charge-on = <0>; - rockchip,android-charge-on = <1>; - rockchip,uboot-low-power-voltage = <3500>; - rockchip,screen-on-voltage = <3600>; - status = "okay"; - }; - - rk809-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,name = "rockchip,rk809-codec"; - simple-audio-card,mclk-fs = <256>; - simple-audio-card,cpu { - sound-dai = <&i2s1_2ch>; - }; - simple-audio-card,codec { - sound-dai = <&rk809_codec>; - }; - }; - - rk_headset: rk-headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&hp_det>; - io-channels = <&saradc 1>; - }; - - sdio_pwrseq: sdio-pwrseq { - compatible = "mmc-pwrseq-simple"; - /*clocks = <&rk809 1>;*/ - /*clock-names = "ext_clock";*/ - pinctrl-names = "default"; - pinctrl-0 = <&wifi_enable_h>; - - /* - * On the module itself this is one of these (depending - * on the actual card populated): - * - SDIO_RESET_L_WL_REG_ON - * - PDN (power down when low) - */ - reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; /* GPIO3_A4 */ - }; - - vcc_phy: vcc-phy-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc_phy"; - regulator-always-on; - regulator-boot-on; - }; - - vcc5v0_sys: vccsys { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - }; - - wireless-wlan { - compatible = "wlan-platdata"; - wifi_chip_type = "AP6210"; - WIFI,host_wake_irq = <&gpio0 RK_PB2 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; - - wireless-bluetooth { - compatible = "bluetooth-platdata"; - clocks = <&rk809 1>; - clock-names = "ext_clock"; - uart_rts_gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_LOW>; - pinctrl-names = "default","rts_gpio"; - pinctrl-0 = <&uart1_rts>; - pinctrl-1 = <&uart1_rts_gpio>; - BT,reset_gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; - BT,wake_gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; - BT,wake_host_irq = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; -}; - -&display_subsystem { - status = "okay"; + /delete-node/ test-power; }; &dsi { status = "okay"; panel@0 { - compatible = "simple-panel-dsi"; + compatible = "sitronix,st7703", "simple-panel-dsi"; reg = <0>; power-supply = <&vcc3v3_lcd>; backlight = <&backlight>; - prepare-delay-ms = <0>; - reset-delay-ms = <0>; - init-delay-ms = <80>; - enable-delay-ms = <0>; - disable-delay-ms = <10>; - unprepare-delay-ms = <60>; + prepare-delay-ms = <2>; + reset-delay-ms = <1>; + init-delay-ms = <20>; + enable-delay-ms = <120>; + disable-delay-ms = <50>; + unprepare-delay-ms = <20>; width-mm = <68>; height-mm = <121>; @@ -205,212 +39,46 @@ dsi,lanes = <4>; panel-init-sequence = [ - 39 00 04 ff 98 81 03 - 15 00 02 01 00 - 15 00 02 02 00 - 15 00 02 03 53 - 15 00 02 04 53 - 15 00 02 05 13 - 15 00 02 06 04 - 15 00 02 07 02 - 15 00 02 08 02 - 15 00 02 09 00 - 15 00 02 0a 00 - 15 00 02 0b 00 - 15 00 02 0c 00 - 15 00 02 0d 00 - 15 00 02 0e 00 - 15 00 02 0f 00 - - 15 00 02 10 00 - 15 00 02 11 00 - 15 00 02 12 00 - 15 00 02 13 00 - 15 00 02 14 00 - 15 00 02 15 08 - 15 00 02 16 10 - 15 00 02 17 00 - 15 00 02 18 08 - 15 00 02 19 00 - 15 00 02 1a 00 - 15 00 02 1b 00 - 15 00 02 1c 00 - 15 00 02 1d 00 - 15 00 02 1e c0 - 15 00 02 1f 80 - - 15 00 02 20 02 - 15 00 02 21 09 - 15 00 02 22 00 - 15 00 02 23 00 - 15 00 02 24 00 - 15 00 02 25 00 - 15 00 02 26 00 - 15 00 02 27 00 - 15 00 02 28 55 - 15 00 02 29 03 - 15 00 02 2a 00 - 15 00 02 2b 00 - 15 00 02 2c 00 - 15 00 02 2d 00 - 15 00 02 2e 00 - 15 00 02 2f 00 - - 15 00 02 30 00 - 15 00 02 31 00 - 15 00 02 32 00 - 15 00 02 33 00 - 15 00 02 34 04 - 15 00 02 35 05 - 15 00 02 36 05 - 15 00 02 37 00 - 15 00 02 38 3c - 15 00 02 39 35 - 15 00 02 3a 00 - 15 00 02 3b 40 - 15 00 02 3c 00 - 15 00 02 3d 00 - 15 00 02 3e 00 - 15 00 02 3f 00 - - 15 00 02 40 00 - 15 00 02 41 88 - 15 00 02 42 00 - 15 00 02 43 00 - 15 00 02 44 1f - - 15 00 02 50 01 - 15 00 02 51 23 - 15 00 02 52 45 - 15 00 02 53 67 - 15 00 02 54 89 - 15 00 02 55 ab - 15 00 02 56 01 - 15 00 02 57 23 - 15 00 02 58 45 - 15 00 02 59 67 - 15 00 02 5a 89 - 15 00 02 5b ab - 15 00 02 5c cd - 15 00 02 5d ef - 15 00 02 5e 03 - 15 00 02 5f 14 - - 15 00 02 60 15 - 15 00 02 61 0c - 15 00 02 62 0d - 15 00 02 63 0e - 15 00 02 64 0f - 15 00 02 65 10 - 15 00 02 66 11 - 15 00 02 67 08 - 15 00 02 68 02 - 15 00 02 69 0a - 15 00 02 6a 02 - 15 00 02 6b 02 - 15 00 02 6c 02 - 15 00 02 6d 02 - 15 00 02 6e 02 - 15 00 02 6f 02 - - 15 00 02 70 02 - 15 00 02 71 02 - 15 00 02 72 06 - 15 00 02 73 02 - 15 00 02 74 02 - 15 00 02 75 14 - 15 00 02 76 15 - 15 00 02 77 0f - 15 00 02 78 0e - 15 00 02 79 0d - 15 00 02 7a 0c - 15 00 02 7b 11 - 15 00 02 7c 10 - 15 00 02 7d 06 - 15 00 02 7e 02 - 15 00 02 7f 0a - - 15 00 02 80 02 - 15 00 02 81 02 - 15 00 02 82 02 - 15 00 02 83 02 - 15 00 02 84 02 - 15 00 02 85 02 - 15 00 02 86 02 - 15 00 02 87 02 - 15 00 02 88 08 - 15 00 02 89 02 - 15 00 02 8a 02 - - 39 00 04 ff 98 81 04 - 15 00 02 00 80 - 15 00 02 70 00 - 15 00 02 71 00 - 15 00 02 66 fe - 15 00 02 82 15 - 15 00 02 84 15 - 15 00 02 85 15 - 15 00 02 3a 24 - 15 00 02 32 ac - 15 00 02 8c 80 - 15 00 02 3c f5 - 15 00 02 88 33 - - 39 00 04 ff 98 81 01 - 15 00 02 22 0a - 15 00 02 31 00 - 15 00 02 53 78 - 15 00 02 50 5b - 15 00 02 51 5b - 15 00 02 60 20 - 15 00 02 61 00 - 15 00 02 62 0d - 15 00 02 63 00 - - 15 00 02 a0 00 - 15 00 02 a1 10 - 15 00 02 a2 1c - 15 00 02 a3 13 - 15 00 02 a4 15 - 15 00 02 a5 26 - 15 00 02 a6 1a - 15 00 02 a7 1d - 15 00 02 a8 67 - 15 00 02 a9 1c - 15 00 02 aa 29 - 15 00 02 ab 5b - 15 00 02 ac 26 - 15 00 02 ad 28 - 15 00 02 ae 5c - 15 00 02 af 30 - 15 00 02 b0 31 - 15 00 02 b1 2e - 15 00 02 b2 32 - 15 00 02 b3 00 - - 15 00 02 c0 00 - 15 00 02 c1 10 - 15 00 02 c2 1c - 15 00 02 c3 13 - 15 00 02 c4 15 - 15 00 02 c5 26 - 15 00 02 c6 1a - 15 00 02 c7 1d - 15 00 02 c8 67 - 15 00 02 c9 1c - 15 00 02 ca 29 - 15 00 02 cb 5b - 15 00 02 cc 26 - 15 00 02 cd 28 - 15 00 02 ce 5c - 15 00 02 cf 30 - 15 00 02 d0 31 - 15 00 02 d1 2e - 15 00 02 d2 32 - 15 00 02 d3 00 - 39 00 04 ff 98 81 00 - 05 00 01 11 - 05 01 01 29 + 05 fa 01 11 + 39 00 04 b9 f1 12 83 + 39 00 1c ba 33 81 05 f9 0e 0e 00 00 00 + 00 00 00 00 00 44 25 00 91 0a + 00 00 02 4f 01 00 00 37 + 15 00 02 b8 25 + 39 00 04 bf 02 11 00 + 39 00 0b b3 0c 10 0a 50 03 ff 00 00 00 + 00 + 39 00 0a c0 73 73 50 50 00 00 08 70 00 + 15 00 02 bc 46 + 15 00 02 cc 0b + 15 00 02 b4 80 + 39 00 04 b2 c8 12 30 + 39 00 0f e3 07 07 0b 0b 03 0b 00 00 00 + 00 ff 00 c0 10 + 39 00 0d c1 53 00 1e 1e 77 e1 cc dd 67 + 77 33 33 + 39 00 07 c6 00 00 ff ff 01 ff + 39 00 03 b5 09 09 + 39 00 03 b6 87 95 + 39 00 40 e9 c2 10 05 05 10 05 a0 12 31 + 23 3f 81 0a a0 37 18 00 80 01 + 00 00 00 00 80 01 00 00 00 48 + f8 86 42 08 88 88 80 88 88 88 + 58 f8 87 53 18 88 88 81 88 88 + 88 00 00 00 01 00 00 00 00 00 + 00 00 00 00 + 39 00 3e ea 00 1a 00 00 00 00 02 00 00 + 00 00 00 1f 88 81 35 78 88 88 + 85 88 88 88 0f 88 80 24 68 88 + 88 84 88 88 88 23 10 00 00 1c + 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 30 05 a0 00 00 + 00 00 + 39 00 23 e0 00 06 08 2a 31 3f 38 36 07 + 0c 0d 11 13 12 13 11 18 00 06 + 08 2a 31 3f 38 36 07 0c 0d 11 + 13 12 13 11 18 + 05 32 01 29 ]; panel-exit-sequence = [ @@ -463,644 +131,3 @@ }; }; }; - -&dsi_in_vopb { - status = "okay"; -}; - -&dsi_in_vopl { - status = "disabled"; -}; - -&route_dsi { - connect = <&vopb_out_dsi>; - status = "okay"; -}; - -&bus_apll { - bus-supply = <&vdd_logic>; - status = "okay"; -}; - -&cpu0 { - cpu-supply = <&vdd_arm>; -}; - -&dfi { - status = "okay"; -}; - -&dmc { - center-supply = <&vdd_logic>; - status = "okay"; -}; - -&emmc { - bus-width = <8>; - cap-mmc-highspeed; - mmc-hs200-1_8v; - no-sdio; - no-sd; - disable-wp; - non-removable; - num-slots = <1>; - status = "okay"; -}; - -&gmac { - phy-supply = <&vcc_phy>; - clock_in_out = "input"; - assigned-clocks = <&cru SCLK_GMAC>; - assigned-clock-parents = <&gmac_clkin>; - pinctrl-names = "default"; - pinctrl-0 = <&rmii_pins &mac_refclk>; - snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - snps,reset-delays-us = <0 50000 50000>; - status = "okay"; -}; - -&gpu { - mali-supply = <&vdd_logic>; - status = "okay"; -}; - -&i2c0 { - status = "okay"; - - rk809: pmic@20 { - compatible = "rockchip,rk809"; - reg = <0x20>; - interrupt-parent = <&gpio0>; - interrupts = <7 IRQ_TYPE_LEVEL_LOW>; - pinctrl-names = "default", "pmic-sleep", - "pmic-power-off", "pmic-reset"; - pinctrl-0 = <&pmic_int>; - pinctrl-1 = <&soc_slppin_slp>, <&rk817_slppin_slp>; - pinctrl-2 = <&soc_slppin_gpio>, <&rk817_slppin_pwrdn>; - pinctrl-3 = <&soc_slppin_rst>, <&rk817_slppin_rst>; - rockchip,system-power-controller; - wakeup-source; - #clock-cells = <1>; - clock-output-names = "rk808-clkout1", "rk808-clkout2"; - //fb-inner-reg-idxs = <2>; - /* 1: rst regs (default in codes), 0: rst the pmic */ - pmic-reset-func = <1>; - - vcc1-supply = <&vcc5v0_sys>; - vcc2-supply = <&vcc5v0_sys>; - vcc3-supply = <&vcc5v0_sys>; - vcc4-supply = <&vcc5v0_sys>; - vcc5-supply = <&vcc3v3_sys>; - vcc6-supply = <&vcc3v3_sys>; - vcc7-supply = <&vcc3v3_sys>; - vcc8-supply = <&vcc3v3_sys>; - vcc9-supply = <&vcc5v0_sys>; - - pwrkey { - status = "okay"; - }; - - pinctrl_rk8xx: pinctrl_rk8xx { - gpio-controller; - #gpio-cells = <2>; - - rk817_slppin_null: rk817_slppin_null { - pins = "gpio_slp"; - function = "pin_fun0"; - }; - - rk817_slppin_slp: rk817_slppin_slp { - pins = "gpio_slp"; - function = "pin_fun1"; - }; - - rk817_slppin_pwrdn: rk817_slppin_pwrdn { - pins = "gpio_slp"; - function = "pin_fun2"; - }; - - rk817_slppin_rst: rk817_slppin_rst { - pins = "gpio_slp"; - function = "pin_fun3"; - }; - }; - - regulators { - vdd_logic: DCDC_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <6001>; - regulator-initial-mode = <0x2>; - regulator-name = "vdd_logic"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <950000>; - }; - }; - - vdd_arm: DCDC_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <6001>; - regulator-initial-mode = <0x2>; - regulator-name = "vdd_arm"; - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <950000>; - }; - }; - - vcc_ddr: DCDC_REG3 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vcc_ddr"; - regulator-initial-mode = <0x2>; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc_3v0: DCDC_REG4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - regulator-initial-mode = <0x2>; - regulator-name = "vcc_3v0"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3000000>; - }; - }; - - vcc_1v0: LDO_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-name = "vcc_1v0"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; - }; - }; - - vccio_sdio: vcc1v8_soc: LDO_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - - regulator-name = "vcc1v8_soc"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vdd1v0_soc: LDO_REG3 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - - regulator-name = "vcc1v0_soc"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; - }; - }; - - vcc3v0_pmu: LDO_REG4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - - regulator-name = "vcc3v0_pmu"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3000000>; - - }; - }; - - vccio_sd: LDO_REG5 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - - regulator-name = "vccio_sd"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vcc_sd: LDO_REG6 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - - regulator-name = "vcc_sd"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - - }; - }; - - vcc2v8_dvp: LDO_REG7 { - regulator-boot-on; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - - regulator-name = "vcc2v8_dvp"; - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <2800000>; - }; - }; - - vcc1v8_dvp: LDO_REG8 { - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - - regulator-name = "vcc1v8_dvp"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vdd1v5_dvp: LDO_REG9 { - regulator-boot-on; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <1500000>; - - regulator-name = "vdd1v5_dvp"; - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <1500000>; - }; - }; - - vcc3v3_sys: DCDC_REG5 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcc3v3_sys"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vcc5v0_host: SWITCH_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vcc5v0_host"; - }; - - vcc3v3_lcd: SWITCH_REG2 { - regulator-boot-on; - regulator-name = "vcc3v3_lcd"; - }; - }; - - rk809_codec: codec { - #sound-dai-cells = <0>; - compatible = "rockchip,rk809-codec", "rockchip,rk817-codec"; - clocks = <&cru SCLK_I2S1_OUT>; - clock-names = "mclk"; - pinctrl-names = "default"; - pinctrl-0 = <&i2s1_2ch_mclk>; - hp-volume = <20>; - spk-volume = <3>; - status = "okay"; - }; - }; -}; - -&i2c1 { - status = "okay"; - - sensor@f { - status = "okay"; - compatible = "ak8963"; - reg = <0x0f>; - type = ; - irq_enable = <0>; - poll_delay_ms = <30>; - layout = <1>; - reprobe_en = <1>; - }; - - gt1x: gt1x@14 { - compatible = "goodix,gt1x"; - reg = <0x14>; - power-supply = <&vcc3v3_lcd>; - goodix,rst-gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; - goodix,irq-gpio = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>; - }; - - sensor@4c { - status = "okay"; - compatible = "gs_mma7660"; - reg = <0x4c>; - type = ; - irq-gpio = <&gpio0 RK_PB7 IRQ_TYPE_LEVEL_LOW>; - irq_enable = <0>; - poll_delay_ms = <30>; - layout = <2>; - reprobe_en = <1>; - }; -}; - -&i2c2 { - status = "okay"; - - clock-frequency = <100000>; - - /* These are relatively safe rise/fall times; TODO: measure */ - i2c-scl-falling-time-ns = <50>; - i2c-scl-rising-time-ns = <300>; - - ov5695: ov5695@36 { - compatible = "ovti,ov5695"; - reg = <0x36>; - clocks = <&cru SCLK_CIF_OUT>; - clock-names = "xvclk"; - - avdd-supply = <&vcc2v8_dvp>; - dovdd-supply = <&vcc1v8_dvp>; - dvdd-supply = <&vdd1v5_dvp>; - - /*reset-gpios = <&gpio2 14 GPIO_ACTIVE_HIGH>;*/ - pwdn-gpios = <&gpio2 14 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&cif_clkout_m0>; - - rockchip,camera-module-index = <0>; - rockchip,camera-module-facing = "back"; - rockchip,camera-module-name = "TongJu"; - rockchip,camera-module-lens-name = "CHT842-MD"; - port { - ucam_out: endpoint { - remote-endpoint = <&mipi_in_ucam>; - data-lanes = <1 2>; - }; - }; - }; -}; - -&i2s1_2ch { - status = "okay"; - #sound-dai-cells = <0>; -}; - -&io_domains { - status = "okay"; - - vccio1-supply = <&vccio_sdio>; - vccio2-supply = <&vccio_sd>; - vccio3-supply = <&vcc_3v0>; - vccio4-supply = <&vcc3v0_pmu>; - vccio5-supply = <&vcc_3v0>; -}; - -&isp_mmu { - status = "okay"; -}; - -&mipi_dphy_rx0 { - status = "okay"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - - mipi_in_ucam: endpoint@1 { - reg = <1>; - remote-endpoint = <&ucam_out>; - data-lanes = <1 2>; - }; - }; - - port@1 { - reg = <1>; - #address-cells = <1>; - #size-cells = <0>; - - dphy_rx0_out: endpoint@0 { - reg = <0>; - remote-endpoint = <&isp0_mipi_in>; - }; - }; - }; -}; - -&nandc0 { - status = "okay"; -}; - -&pmu_io_domains { - status = "okay"; - - pmuio1-supply = <&vcc3v0_pmu>; - pmuio2-supply = <&vcc3v0_pmu>; -}; - -&pwm1 { - status = "okay"; -}; - -&rk_rga { - status = "okay"; -}; - -&rkisp1 { - status = "okay"; - - port { - #address-cells = <1>; - #size-cells = <0>; - - isp0_mipi_in: endpoint@0 { - reg = <0>; - remote-endpoint = <&dphy_rx0_out>; - }; - }; -}; - -&rockchip_suspend { - status = "okay"; - rockchip,sleep-debug-en = <1>; -}; - -&saradc { - status = "okay"; - vref-supply = <&vcc1v8_soc>; -}; - -&sdmmc { - bus-width = <4>; - cap-mmc-highspeed; - cap-sd-highspeed; - no-sdio; - no-mmc; - card-detect-delay = <800>; - ignore-pm-notify; - /*cd-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>; [> CD GPIO <]*/ - sd-uhs-sdr12; - sd-uhs-sdr25; - sd-uhs-sdr50; - sd-uhs-sdr104; - vqmmc-supply = <&vccio_sd>; - vmmc-supply = <&vcc_sd>; - status = "okay"; -}; - -&sdio { - bus-width = <4>; - cap-sd-highspeed; - no-sd; - no-mmc; - ignore-pm-notify; - keep-power-in-suspend; - non-removable; - mmc-pwrseq = <&sdio_pwrseq>; - sd-uhs-sdr104; - status = "okay"; -}; - -&tsadc { - pinctrl-names = "gpio", "otpout"; - pinctrl-0 = <&tsadc_otp_gpio>; - pinctrl-1 = <&tsadc_otp_out>; - status = "okay"; -}; - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&uart1_xfer &uart1_cts>; - status = "okay"; -}; - -&u2phy { - status = "okay"; - - u2phy_host: host-port { - status = "okay"; - }; - - u2phy_otg: otg-port { - status = "okay"; - }; -}; - -&usb20_otg { - status = "okay"; -}; - -&usb_host0_ehci { - status = "okay"; -}; - -&usb_host0_ohci { - status = "okay"; -}; - -&vopb { - status = "okay"; -}; - -&vopb_mmu { - status = "okay"; -}; - -&vopl { - status = "okay"; -}; - -&vopl_mmu { - status = "okay"; -}; - -&mpp_srv { - status = "okay"; -}; - -&vdpu { - status = "okay"; -}; - -&vepu { - status = "okay"; -}; - -&vpu_mmu { - status = "okay"; -}; - -&hevc { - status = "okay"; -}; - -&hevc_mmu { - status = "okay"; -}; - -&pinctrl { - headphone { - hp_det: hp-det { - rockchip,pins = <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; - }; - }; - - pmic { - pmic_int: pmic_int { - rockchip,pins = - <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; - }; - - soc_slppin_gpio: soc_slppin_gpio { - rockchip,pins = - <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; - }; - - soc_slppin_slp: soc_slppin_slp { - rockchip,pins = - <0 RK_PA4 1 &pcfg_pull_none>; - }; - - soc_slppin_rst: soc_slppin_rst { - rockchip,pins = - <0 RK_PA4 2 &pcfg_pull_none>; - }; - }; - - sdio-pwrseq { - wifi_enable_h: wifi-enable-h { - rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; -}; - -/* DON'T PUT ANYTHING BELOW HERE. PUT IT ABOVE PINCTRL */ -/* DON'T PUT ANYTHING BELOW HERE. PUT IT ABOVE PINCTRL */ -/* DON'T PUT ANYTHING BELOW HERE. PUT IT ABOVE PINCTRL */ - diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts index 8d8bea85b1cd..ac0836b9ac13 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dts @@ -127,16 +127,3 @@ }; }; }; - -&gmac { - phy-supply = <&vcc_phy>; - clock_in_out = "input"; - assigned-clocks = <&cru SCLK_GMAC>; - assigned-clock-parents = <&gmac_clkin>; - pinctrl-names = "default"; - pinctrl-0 = <&rmii_pins &mac_refclk>; - snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - snps,reset-delays-us = <0 50000 50000>; - status = "okay"; -}; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi index 271d78714944..2cd4d3a8fd76 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi @@ -111,7 +111,7 @@ rk_headset: rk-headset { compatible = "rockchip_headset"; - headset_gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_LOW>; + headset_gpio = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&hp_det>; io-channels = <&saradc 1>; @@ -160,7 +160,7 @@ status = "okay"; }; - wireless-bluetooth { + wireless_bluetooth: wireless-bluetooth { compatible = "bluetooth-platdata"; clocks = <&rk809 1>; clock-names = "ext_clock"; @@ -168,8 +168,8 @@ pinctrl-names = "default","rts_gpio"; pinctrl-0 = <&uart1_rts>; pinctrl-1 = <&uart1_rts_gpio>; - BT,reset_gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; - BT,wake_gpio = <&gpio2 RK_PB0 GPIO_ACTIVE_HIGH>; + BT,reset_gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; + BT,wake_gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; BT,wake_host_irq = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; status = "okay"; }; @@ -224,7 +224,11 @@ &gmac { phy-supply = <&vcc_phy>; - clock_in_out = "output"; + clock_in_out = "input"; + assigned-clocks = <&cru SCLK_GMAC>; + assigned-clock-parents = <&gmac_clkin>; + pinctrl-names = "default"; + pinctrl-0 = <&rmii_pins &mac_refclk>; snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; snps,reset-active-low; snps,reset-delays-us = <0 50000 50000>; @@ -339,13 +343,13 @@ vcc_3v0: DCDC_REG4 { regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; regulator-initial-mode = <0x2>; regulator-name = "vcc_3v0"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <3000000>; + regulator-suspend-microvolt = <3300000>; }; }; @@ -390,13 +394,13 @@ vcc3v0_pmu: LDO_REG4 { regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; regulator-name = "vcc3v0_pmu"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <3000000>; + regulator-suspend-microvolt = <3300000>; }; }; @@ -627,7 +631,7 @@ &pinctrl { headphone { hp_det: hp-det { - rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>; + rockchip,pins = <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts index df920932b154..24935f2a3c03 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr4-v10.dts @@ -12,28 +12,6 @@ / { model = "Rockchip PX30 evb ddr4 board"; compatible = "rockchip,px30-evb-ddr4-v10", "rockchip,px30"; - - rk_headset: rk-headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&hp_det>; - io-channels = <&saradc 1>; - }; - - wireless-bluetooth { - compatible = "bluetooth-platdata"; - clocks = <&rk809 1>; - clock-names = "ext_clock"; - uart_rts_gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_LOW>; - pinctrl-names = "default","rts_gpio"; - pinctrl-0 = <&uart1_rts>; - pinctrl-1 = <&uart1_rts_gpio>; - BT,reset_gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; - BT,wake_gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; - BT,wake_host_irq = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; }; &chosen { @@ -298,24 +276,3 @@ }; }; }; - -&gmac { - phy-supply = <&vcc_phy>; - clock_in_out = "input"; - assigned-clocks = <&cru SCLK_GMAC>; - assigned-clock-parents = <&gmac_clkin>; - pinctrl-names = "default"; - pinctrl-0 = <&rmii_pins &mac_refclk>; - snps,reset-gpio = <&gpio2 13 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - snps,reset-delays-us = <0 50000 50000>; - status = "okay"; -}; - -&pinctrl { - headphone { - hp_det: hp-det { - rockchip,pins = <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; - }; - }; -}; diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11-avb.dts b/arch/arm64/boot/dts/rockchip/px30-mini-evb-ddr3-v11-avb.dts similarity index 96% rename from arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11-avb.dts rename to arch/arm64/boot/dts/rockchip/px30-mini-evb-ddr3-v11-avb.dts index 4e6170f8e691..c47101d4e7f9 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11-avb.dts +++ b/arch/arm64/boot/dts/rockchip/px30-mini-evb-ddr3-v11-avb.dts @@ -7,10 +7,11 @@ #include "px30.dtsi" #include "px30-android.dtsi" #include "px30-evb-ddr3-v10.dtsi" +#include "px30-mini-evb-v11.dtsi" / { - model = "Rockchip PX30 evb ddr3 board"; - compatible = "rockchip,px30-evb-ddr3-v11-avb", "rockchip,px30"; + model = "Rockchip PX30 mini evb ddr3 board"; + compatible = "rockchip,px30-mini-evb-ddr3-v11-avb", "rockchip,px30"; }; &chosen { diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11.dts b/arch/arm64/boot/dts/rockchip/px30-mini-evb-ddr3-v11.dts similarity index 97% rename from arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11.dts rename to arch/arm64/boot/dts/rockchip/px30-mini-evb-ddr3-v11.dts index a4429672e190..34d3d9cab2e5 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v11.dts +++ b/arch/arm64/boot/dts/rockchip/px30-mini-evb-ddr3-v11.dts @@ -7,10 +7,11 @@ #include "px30.dtsi" #include "px30-android.dtsi" #include "px30-evb-ddr3-v10.dtsi" +#include "px30-mini-evb-v11.dtsi" / { - model = "Rockchip PX30 evb ddr3 board"; - compatible = "rockchip,px30-evb-ddr3-v11", "rockchip,px30"; + model = "Rockchip PX30 mini evb ddr3 board"; + compatible = "rockchip,px30-mini-evb-ddr3-v11", "rockchip,px30"; }; &dsi { diff --git a/arch/arm64/boot/dts/rockchip/px30-mini-evb-v11.dtsi b/arch/arm64/boot/dts/rockchip/px30-mini-evb-v11.dtsi new file mode 100644 index 000000000000..2304898a94ce --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/px30-mini-evb-v11.dtsi @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Fuzhou Rockchip Electronics Co., Ltd + */ + +&gmac { + clock_in_out = "output"; + /delete-property/ assigned-clocks; + /delete-property/ assigned-clock-parents; + pinctrl-names = "default"; + pinctrl-0 = <&rmii_pins &mac_refclk_12ma>; +}; + +&rk_headset { + headset_gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_LOW>; +}; + + +&pinctrl { + headphone { + hp_det: hp-det { + rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +}; + +&wireless_bluetooth { + BT,reset_gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; + BT,wake_gpio = <&gpio2 RK_PB0 GPIO_ACTIVE_HIGH>; +}; + From 86f98f048bd24afc7c88beae5bf0f4a6f4e1c25a Mon Sep 17 00:00:00 2001 From: Lin Jianhua Date: Sat, 10 Sep 2022 09:35:00 +0800 Subject: [PATCH 037/204] arm64: dts: rockchip: rk3326-evb-lp3-v10-linux: include rk3326-evb-lp3-v10.dtsi Signed-off-by: Lin Jianhua Change-Id: I23f9d17ec628660ef997023713c9a72468424d37 --- .../dts/rockchip/rk3326-evb-lp3-v10-linux.dts | 894 +----------------- 1 file changed, 14 insertions(+), 880 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-linux.dts b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-linux.dts index 9b9cc30c0f30..a6dfb18c2cbd 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-linux.dts @@ -4,13 +4,9 @@ */ /dts-v1/; -#include -#include -#include -#include -#include #include "rk3326.dtsi" #include "rk3326-linux.dtsi" +#include "rk3326-evb-lp3-v10.dtsi" / { model = "Rockchip rk3326 evb lpddr3 v10 board for linux"; @@ -20,170 +16,7 @@ bootargs = "earlycon=uart8250,mmio32,0xff160000 console=ttyFIQ0 rw root=PARTUUID=614e0000-0000 rootfstype=ext4 rootwait"; }; - adc-keys { - compatible = "adc-keys"; - io-channels = <&saradc 2>; - io-channel-names = "buttons"; - poll-interval = <100>; - keyup-threshold-microvolt = <1800000>; - - esc-key { - linux,code = ; - label = "esc"; - press-threshold-microvolt = <1310000>; - }; - - home-key { - linux,code = ; - label = "home"; - press-threshold-microvolt = <624000>; - }; - - menu-key { - linux,code = ; - label = "menu"; - press-threshold-microvolt = <987000>; - }; - - vol-down-key { - linux,code = ; - label = "volume down"; - press-threshold-microvolt = <300000>; - }; - - vol-up-key { - linux,code = ; - label = "volume up"; - press-threshold-microvolt = <17000>; - }; - }; - - backlight: backlight { - compatible = "pwm-backlight"; - pwms = <&pwm1 0 25000 0>; - brightness-levels = < - 0 1 2 3 4 5 6 7 - 8 9 10 11 12 13 14 15 - 16 17 18 19 20 21 22 23 - 24 25 26 27 28 29 30 31 - 32 33 34 35 36 37 38 39 - 40 41 42 43 44 45 46 47 - 48 49 50 51 52 53 54 55 - 56 57 58 59 60 61 62 63 - 64 65 66 67 68 69 70 71 - 72 73 74 75 76 77 78 79 - 80 81 82 83 84 85 86 87 - 88 89 90 91 92 93 94 95 - 96 97 98 99 100 101 102 103 - 104 105 106 107 108 109 110 111 - 112 113 114 115 116 117 118 119 - 120 121 122 123 124 125 126 127 - 128 129 130 131 132 133 134 135 - 136 137 138 139 140 141 142 143 - 144 145 146 147 148 149 150 151 - 152 153 154 155 156 157 158 159 - 160 161 162 163 164 165 166 167 - 168 169 170 171 172 173 174 175 - 176 177 178 179 180 181 182 183 - 184 185 186 187 188 189 190 191 - 192 193 194 195 196 197 198 199 - 200 201 202 203 204 205 206 207 - 208 209 210 211 212 213 214 215 - 216 217 218 219 220 221 222 223 - 224 225 226 227 228 229 230 231 - 232 233 234 235 236 237 238 239 - 240 241 242 243 244 245 246 247 - 248 249 250 251 252 253 254 255>; - default-brightness-level = <200>; - }; - - rk817-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,name = "rockchip,rk817-codec"; - simple-audio-card,mclk-fs = <256>; - simple-audio-card,widgets = - "Microphone", "Mic Jack", - "Headphone", "Headphone Jack"; - simple-audio-card,routing = - "MIC_IN", "Microphone Jack", - "IN1P", "Mic Jack", - "Headphone Jack", "HPOL", - "Headphone Jack", "HPOR"; - simple-audio-card,cpu { - sound-dai = <&i2s1_2ch>; - }; - simple-audio-card,codec { - sound-dai = <&rk817_codec>; - }; - }; - - rk_headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&hp_det>; - io-channels = <&saradc 1>; - }; - - sdio_pwrseq: sdio-pwrseq { - compatible = "mmc-pwrseq-simple"; - /*clocks = <&rk817 1>;*/ - /*clock-names = "ext_clock";*/ - pinctrl-names = "default"; - pinctrl-0 = <&wifi_enable_h>; - - /* - * On the module itself this is one of these (depending - * on the actual card populated): - * - SDIO_RESET_L_WL_REG_ON - * - PDN (power down when low) - */ - reset-gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; /* GPIO3_A4 */ - }; - - vccsys: vccsys { - compatible = "regulator-fixed"; - regulator-name = "vcc3v8_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3800000>; - regulator-max-microvolt = <3800000>; - }; - - wireless-wlan { - compatible = "wlan-platdata"; - wifi_chip_type = "AP6210"; - WIFI,host_wake_irq = <&gpio0 RK_PB2 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; - - wireless-bluetooth { - compatible = "bluetooth-platdata"; - clocks = <&rk817 1>; - clock-names = "ext_clock"; - uart_rts_gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_LOW>; - pinctrl-names = "default","rts_gpio"; - pinctrl-0 = <&uart1_rts>; - pinctrl-1 = <&uart1_rts_gpio>; - BT,reset_gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; - BT,wake_gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; - BT,wake_host_irq = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; - - vcc18_lcd_n: vcc18-lcd-n { - compatible = "regulator-fixed"; - regulator-name = "vcc18_lcd_n"; - regulator-boot-on; - gpio = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; - enable-active-high; - }; -}; - -&bus_apll { - bus-supply = <&vdd_logic>; - status = "okay"; + /delete-node/ test-power; }; &cif_new { @@ -198,519 +31,6 @@ }; }; -&cpu0 { - cpu-supply = <&vdd_arm>; -}; - -&display_subsystem { - status = "okay"; -}; - -&dsi { - status = "okay"; - - panel@0 { - compatible = "sitronix,st7703", "simple-panel-dsi"; - reg = <0>; - backlight = <&backlight>; - power-supply = <&vcc18_lcd_n>; - prepare-delay-ms = <2>; - reset-delay-ms = <1>; - init-delay-ms = <20>; - enable-delay-ms = <120>; - disable-delay-ms = <50>; - unprepare-delay-ms = <20>; - - width-mm = <68>; - height-mm = <121>; - - dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | - MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>; - dsi,format = ; - dsi,lanes = <4>; - - panel-init-sequence = [ - 05 fa 01 11 - 39 00 04 b9 f1 12 83 - 39 00 1c ba 33 81 05 f9 0e 0e 00 00 00 - 00 00 00 00 00 44 25 00 91 0a - 00 00 02 4f 01 00 00 37 - 15 00 02 b8 25 - 39 00 04 bf 02 11 00 - 39 00 0b b3 0c 10 0a 50 03 ff 00 00 00 - 00 - 39 00 0a c0 73 73 50 50 00 00 08 70 00 - 15 00 02 bc 46 - 15 00 02 cc 0b - 15 00 02 b4 80 - 39 00 04 b2 c8 12 30 - 39 00 0f e3 07 07 0b 0b 03 0b 00 00 00 - 00 ff 00 c0 10 - 39 00 0d c1 53 00 1e 1e 77 e1 cc dd 67 - 77 33 33 - 39 00 07 c6 00 00 ff ff 01 ff - 39 00 03 b5 09 09 - 39 00 03 b6 87 95 - 39 00 40 e9 c2 10 05 05 10 05 a0 12 31 - 23 3f 81 0a a0 37 18 00 80 01 - 00 00 00 00 80 01 00 00 00 48 - f8 86 42 08 88 88 80 88 88 88 - 58 f8 87 53 18 88 88 81 88 88 - 88 00 00 00 01 00 00 00 00 00 - 00 00 00 00 - 39 00 3e ea 00 1a 00 00 00 00 02 00 00 - 00 00 00 1f 88 81 35 78 88 88 - 85 88 88 88 0f 88 80 24 68 88 - 88 84 88 88 88 23 10 00 00 1c - 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 30 05 a0 00 00 - 00 00 - 39 00 23 e0 00 06 08 2a 31 3f 38 36 07 - 0c 0d 11 13 12 13 11 18 00 06 - 08 2a 31 3f 38 36 07 0c 0d 11 - 13 12 13 11 18 - 05 32 01 29 - ]; - - panel-exit-sequence = [ - 05 00 01 28 - 05 00 01 10 - ]; - - display-timings { - native-mode = <&timing0>; - - timing0: timing0 { - clock-frequency = <66000000>; - hactive = <720>; - vactive = <1280>; - hfront-porch = <40>; - hsync-len = <10>; - hback-porch = <40>; - vfront-porch = <22>; - vsync-len = <4>; - vback-porch = <11>; - hsync-active = <0>; - vsync-active = <0>; - de-active = <0>; - pixelclk-active = <0>; - }; - }; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - panel_in_dsi: endpoint { - remote-endpoint = <&dsi_out_panel>; - }; - }; - }; - }; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@1 { - reg = <1>; - dsi_out_panel: endpoint { - remote-endpoint = <&panel_in_dsi>; - }; - }; - }; -}; - -&dsi_in_vopb { - status = "okay"; -}; - -&dsi_in_vopl { - status = "disabled"; -}; - -&route_dsi { - connect = <&vopb_out_dsi>; - status = "okay"; -}; - -&dfi { - status = "okay"; -}; - -&dmc { - center-supply = <&vdd_logic>; - status = "okay"; -}; - -&emmc { - bus-width = <8>; - cap-mmc-highspeed; - mmc-hs200-1_8v; - no-sdio; - no-sd; - disable-wp; - non-removable; - num-slots = <1>; - status = "okay"; -}; - -&gpu { - mali-supply = <&vdd_logic>; - status = "okay"; -}; - -&i2c0 { - status = "okay"; - clock-frequency = <400000>; - i2c-scl-rising-time-ns = <280>; - i2c-scl-falling-time-ns = <16>; - - rk817: pmic@20 { - compatible = "rockchip,rk817"; - reg = <0x20>; - interrupt-parent = <&gpio0>; - interrupts = <7 IRQ_TYPE_LEVEL_LOW>; - pinctrl-names = "default", "pmic-sleep", - "pmic-power-off", "pmic-reset"; - pinctrl-0 = <&pmic_int>; - pinctrl-1 = <&soc_slppin_slp>, <&rk817_slppin_slp>; - pinctrl-2 = <&soc_slppin_gpio>, <&rk817_slppin_pwrdn>; - pinctrl-3 = <&soc_slppin_rst>, <&rk817_slppin_rst>; - rockchip,system-power-controller; - wakeup-source; - #clock-cells = <1>; - clock-output-names = "rk808-clkout1", "rk808-clkout2"; - //fb-inner-reg-idxs = <2>; - /* 1: rst regs (default in codes), 0: rst the pmic */ - pmic-reset-func = <1>; - - vcc1-supply = <&vccsys>; - vcc2-supply = <&vccsys>; - vcc3-supply = <&vccsys>; - vcc4-supply = <&vccsys>; - vcc5-supply = <&vccsys>; - vcc6-supply = <&vccsys>; - vcc7-supply = <&vcc_3v0>; - vcc8-supply = <&vccsys>; - vcc9-supply = <&dcdc_boost>; - - pwrkey { - status = "okay"; - }; - - pinctrl_rk8xx: pinctrl_rk8xx { - gpio-controller; - #gpio-cells = <2>; - - rk817_ts_gpio1: rk817_ts_gpio1 { - pins = "gpio_ts"; - function = "pin_fun1"; - /* output-low; */ - /* input-enable; */ - }; - - rk817_gt_gpio2: rk817_gt_gpio2 { - pins = "gpio_gt"; - function = "pin_fun1"; - }; - - rk817_pin_ts: rk817_pin_ts { - pins = "gpio_ts"; - function = "pin_fun0"; - }; - - rk817_pin_gt: rk817_pin_gt { - pins = "gpio_gt"; - function = "pin_fun0"; - }; - - rk817_slppin_null: rk817_slppin_null { - pins = "gpio_slp"; - function = "pin_fun0"; - }; - - rk817_slppin_slp: rk817_slppin_slp { - pins = "gpio_slp"; - function = "pin_fun1"; - }; - - rk817_slppin_pwrdn: rk817_slppin_pwrdn { - pins = "gpio_slp"; - function = "pin_fun2"; - }; - - rk817_slppin_rst: rk817_slppin_rst { - pins = "gpio_slp"; - function = "pin_fun3"; - }; - }; - - regulators { - vdd_logic: DCDC_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <6001>; - regulator-initial-mode = <0x2>; - regulator-name = "vdd_logic"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <950000>; - }; - }; - - vdd_arm: DCDC_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <6001>; - regulator-initial-mode = <0x2>; - regulator-name = "vdd_arm"; - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <950000>; - }; - }; - - vcc_ddr: DCDC_REG3 { - regulator-always-on; - regulator-boot-on; - regulator-initial-mode = <0x2>; - regulator-name = "vcc_ddr"; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc_3v0: DCDC_REG4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - regulator-initial-mode = <0x2>; - regulator-name = "vcc_3v0"; - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <3000000>; - }; - }; - - vcc_1v0: LDO_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-name = "vcc_1v0"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; - }; - }; - - vcc1v8_soc: LDO_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - - regulator-name = "vcc1v8_soc"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vdd1v0_soc: LDO_REG3 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - - regulator-name = "vcc1v0_soc"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; - }; - }; - - vcc3v0_pmu: LDO_REG4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - - regulator-name = "vcc3v0_pmu"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3000000>; - - }; - }; - - vccio_sd: LDO_REG5 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - - regulator-name = "vccio_sd"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vcc_sd: LDO_REG6 { - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - - regulator-name = "vcc_sd"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - - }; - }; - - vcc2v8_dvp: LDO_REG7 { - regulator-boot-on; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - - regulator-name = "vcc2v8_dvp"; - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <2800000>; - }; - }; - - vcc1v8_dvp: LDO_REG8 { - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - - regulator-name = "vcc1v8_dvp"; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vdd1v5_dvp: LDO_REG9 { - regulator-boot-on; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <1500000>; - - regulator-name = "vdd1v5_dvp"; - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <1500000>; - }; - }; - - dcdc_boost: BOOST { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <4700000>; - regulator-max-microvolt = <5400000>; - regulator-name = "boost"; - }; - - otg_switch: OTG_SWITCH { - regulator-name = "otg_switch"; - }; - }; - - battery { - compatible = "rk817,battery"; - ocv_table = <3500 3625 3685 3697 3718 3735 3748 - 3760 3774 3788 3802 3816 3834 3853 - 3877 3908 3946 3975 4018 4071 4106>; - design_capacity = <2500>; - design_qmax = <2750>; - bat_res = <100>; - sleep_enter_current = <300>; - sleep_exit_current = <300>; - sleep_filter_current = <100>; - power_off_thresd = <3500>; - zero_algorithm_vol = <3850>; - max_soc_offset = <60>; - monitor_sec = <5>; - sample_res = <10>; - virtual_power = <1>; - }; - - charger { - compatible = "rk817,charger"; - min_input_voltage = <4500>; - max_input_current = <1500>; - max_chrg_current = <2000>; - max_chrg_voltage = <4200>; - chrg_term_mode = <0>; - chrg_finish_cur = <300>; - virtual_power = <0>; - dc_det_adc = <0>; - extcon = <&u2phy>; - }; - - rk817_codec: codec { - #sound-dai-cells = <0>; - compatible = "rockchip,rk817-codec"; - clocks = <&cru SCLK_I2S1_OUT>; - clock-names = "mclk"; - pinctrl-names = "default"; - pinctrl-0 = <&i2s1_2ch_mclk>; - hp-volume = <20>; - spk-volume = <3>; - status = "okay"; - }; - }; -}; - -&i2c1 { - status = "okay"; - clock-frequency = <400000>; - i2c-scl-rising-time-ns = <275>; - i2c-scl-falling-time-ns = <16>; - - sensor@f { - status = "okay"; - compatible = "ak8963"; - reg = <0x0f>; - type = ; - irq_enable = <0>; - poll_delay_ms = <30>; - layout = <1>; - reprobe_en = <1>; - }; - - gt1x: gt1x@14 { - compatible = "goodix,gt1x"; - reg = <0x14>; - power-supply = <&vcc18_lcd_n>; - goodix,rst-gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; - goodix,irq-gpio = <&gpio0 RK_PA5 IRQ_TYPE_LEVEL_LOW>; - }; - - sensor@4c { - status = "okay"; - compatible = "gs_mma7660"; - reg = <0x4c>; - type = ; - irq-gpio = <&gpio0 RK_PB5 IRQ_TYPE_LEVEL_LOW>; - irq_enable = <0>; - poll_delay_ms = <30>; - layout = <1>; - reprobe_en = <1>; - }; -}; - &i2c2 { status = "okay"; clock-frequency = <400000>; @@ -773,25 +93,6 @@ }; }; -&i2s1_2ch { - status = "okay"; - #sound-dai-cells = <0>; -}; - -&io_domains { - status = "okay"; - - vccio1-supply = <&vcc1v8_soc>; - vccio2-supply = <&vccio_sd>; - vccio3-supply = <&vcc1v8_dvp>; - vccio4-supply = <&vcc_3v0>; - vccio5-supply = <&vcc_3v0>; -}; - -&isp_mmu { - status = "okay"; -}; - &mipi_dphy_rx0 { status = "okay"; @@ -824,153 +125,6 @@ }; }; -&nandc0 { - status = "okay"; -}; - -&rkisp1 { - status = "okay"; - - port { - #address-cells = <1>; - #size-cells = <0>; - - isp0_mipi_in: endpoint@0 { - reg = <0>; - remote-endpoint = <&dphy_rx0_out>; - }; - }; -}; - -&pmu_io_domains { - status = "okay"; - - pmuio1-supply = <&vcc3v0_pmu>; - pmuio2-supply = <&vcc3v0_pmu>; -}; - -&pwm1 { - status = "okay"; -}; - -&rk_rga { - status = "okay"; -}; - -&rockchip_suspend { - status = "okay"; - rockchip,sleep-debug-en = <1>; -}; - -&saradc { - status = "okay"; - vref-supply = <&vcc1v8_soc>; -}; - -&sdmmc { - bus-width = <4>; - cap-mmc-highspeed; - cap-sd-highspeed; - no-sdio; - no-mmc; - card-detect-delay = <800>; - ignore-pm-notify; - /*cd-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>; [> CD GPIO <]*/ - sd-uhs-sdr12; - sd-uhs-sdr25; - sd-uhs-sdr50; - sd-uhs-sdr104; - vqmmc-supply = <&vccio_sd>; - vmmc-supply = <&vcc_sd>; - status = "disabled"; -}; - -&sdio { - bus-width = <4>; - cap-sd-highspeed; - no-sd; - no-mmc; - ignore-pm-notify; - keep-power-in-suspend; - non-removable; - mmc-pwrseq = <&sdio_pwrseq>; - sd-uhs-sdr104; - status = "okay"; -}; - -&tsadc { - pinctrl-names = "gpio", "otpout"; - pinctrl-0 = <&tsadc_otp_gpio>; - pinctrl-1 = <&tsadc_otp_out>; - status = "okay"; -}; - -&u2phy { - status = "okay"; - - u2phy_host: host-port { - status = "okay"; - }; - - u2phy_otg: otg-port { - status = "okay"; - }; -}; - -&usb20_otg { - status = "okay"; -}; - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&uart1_xfer &uart1_cts>; - status = "okay"; -}; - -&vip_mmu { - status = "okay"; -}; - -&vopb { - status = "okay"; -}; - -&vopb_mmu { - status = "okay"; -}; - -&vopl { - status = "okay"; -}; - -&vopl_mmu { - status = "okay"; -}; - -&mpp_srv { - status = "okay"; -}; - -&vdpu { - status = "okay"; -}; - -&vepu { - status = "okay"; -}; - -&vpu_mmu { - status = "okay"; -}; - -&hevc { - status = "okay"; -}; - -&hevc_mmu { - status = "okay"; -}; - &pinctrl { cif-pin-m0 { cif_pin_m0: cif-pin-m0 { @@ -988,42 +142,22 @@ <2 RK_PB2 1 &pcfg_pull_none>;/* cif_clkin */ }; }; +}; - headphone { - hp_det: hp-det { - rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; - }; - }; +&rkisp1 { + status = "okay"; - pmic { - pmic_int: pmic_int { - rockchip,pins = - <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; - }; + port { + #address-cells = <1>; + #size-cells = <0>; - soc_slppin_gpio: soc_slppin_gpio { - rockchip,pins = - <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>; - }; - - soc_slppin_slp: soc_slppin_slp { - rockchip,pins = - <0 RK_PA4 1 &pcfg_pull_none>; - }; - - soc_slppin_rst: soc_slppin_rst { - rockchip,pins = - <0 RK_PA4 2 &pcfg_pull_none>; - }; - }; - - sdio-pwrseq { - wifi_enable_h: wifi-enable-h { - rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + isp0_mipi_in: endpoint@0 { + reg = <0>; + remote-endpoint = <&dphy_rx0_out>; }; }; }; -/* DON'T PUT ANYTHING BELOW HERE. PUT IT ABOVE PINCTRL */ -/* DON'T PUT ANYTHING BELOW HERE. PUT IT ABOVE PINCTRL */ -/* DON'T PUT ANYTHING BELOW HERE. PUT IT ABOVE PINCTRL */ +&vip_mmu { + status = "okay"; +}; From 3cf189f2225093442884a7ca0a6590d139d95af8 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Thu, 15 Sep 2022 10:58:01 +0000 Subject: [PATCH 038/204] drm/bridge: analogix_dp: Fix sync polarity configuration in msa packet Fixes: 2abd3af02c10 ("drm/bridge: analogix_dp: Use video format information from register") Signed-off-by: Wyon Bi Change-Id: Ia48058d9f4341adaa35fb4311911c557f0b162b8 --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 09d9ee7fac55..33e3787bcf2a 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1779,13 +1779,8 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge, /* Input video interlaces & hsync pol & vsync pol */ video->interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); - if (dp->plat_data->dev_type == RK3588_EDP) { - video->v_sync_polarity = true; - video->h_sync_polarity = true; - } else { - video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); - video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); - } + video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); + video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); /* Input video dynamic_range & colorimetry */ vic = drm_match_cea_mode(mode); From 918a2722e2752d85e520c3cab795045cf283a5ce Mon Sep 17 00:00:00 2001 From: Dingxian Wen Date: Wed, 7 Sep 2022 16:53:16 +0800 Subject: [PATCH 039/204] media: rockchip: hdmirx: modify the calculation method of pixelclock In order to be compatible with deep color mode. Signed-off-by: Dingxian Wen Change-Id: I37ccb5d1130d3c30145e6c0a45632bda4542c2ac --- drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index bddcdf1f3076..0cb6de232356 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -815,7 +815,7 @@ static int hdmirx_get_detected_timings(struct rk_hdmirx_dev *hdmirx_dev, tmp_data = tmds_clk * 24; do_div(tmp_data, color_depth); pix_clk = tmp_data; - bt->pixelclock = pix_clk; + bt->pixelclock = tmds_clk; hdmirx_get_timings(hdmirx_dev, bt, from_dma); if (bt->interlaced == V4L2_DV_INTERLACED) { @@ -823,7 +823,7 @@ static int hdmirx_get_detected_timings(struct rk_hdmirx_dev *hdmirx_dev, bt->il_vsync = bt->vsync + 1; } - v4l2_dbg(2, debug, v4l2_dev, "tmds_clk:%llu\n", tmds_clk); + v4l2_dbg(2, debug, v4l2_dev, "tmds_clk:%llu, pix_clk:%d\n", tmds_clk, pix_clk); v4l2_dbg(1, debug, v4l2_dev, "interlace:%d, fmt:%d, vic:%d, color:%d, mode:%s\n", bt->interlaced, hdmirx_dev->pix_fmt, hdmirx_dev->cur_vic, hdmirx_dev->color_depth, From 9e6cf9710fb86da2e188253c87769a8857c223d7 Mon Sep 17 00:00:00 2001 From: Dingxian Wen Date: Thu, 15 Sep 2022 10:57:17 +0800 Subject: [PATCH 040/204] media: rockchip: hdmirx: add private v4l2 event add private v4l2 event: RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST Signed-off-by: Dingxian Wen Change-Id: Iad6f519b36ebb7e18305e211f989795c9ebe3fdc --- drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c | 13 +++++++++++++ include/uapi/linux/rk_hdmirx_config.h | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index 0cb6de232356..2650b0cd3126 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -441,6 +441,8 @@ static int hdmirx_subscribe_event(struct v4l2_fh *fh, break; case V4L2_EVENT_CTRL: return v4l2_ctrl_subscribe_event(fh, sub); + case RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST: + return v4l2_event_subscribe(fh, sub, 0, NULL); default: return v4l2_ctrl_subscribe_event(fh, sub); @@ -2201,6 +2203,11 @@ static int hdmirx_register_stream_vdev(struct hdmirx_stream *stream) static void process_signal_change(struct rk_hdmirx_dev *hdmirx_dev) { + struct hdmirx_stream *stream = &hdmirx_dev->stream; + const struct v4l2_event evt_signal_lost = { + .type = RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST, + }; + hdmirx_update_bits(hdmirx_dev, DMA_CONFIG6, HDMIRX_DMA_EN, 0); hdmirx_update_bits(hdmirx_dev, DMA_CONFIG4, LINE_FLAG_INT_EN | @@ -2212,6 +2219,7 @@ static void process_signal_change(struct rk_hdmirx_dev *hdmirx_dev) HDMIRX_AXI_ERROR_INT_EN, 0); hdmirx_reset_dma(hdmirx_dev); hdmirx_dev->get_timing = false; + v4l2_event_queue(&stream->vdev, &evt_signal_lost); if (hdmirx_dev->hdcp && hdmirx_dev->hdcp->hdcp_stop) hdmirx_dev->hdcp->hdcp_stop(hdmirx_dev->hdcp); schedule_delayed_work_on(hdmirx_dev->bound_cpu, @@ -2665,10 +2673,15 @@ static void hdmirx_delayed_work_hotplug(struct work_struct *work) struct rk_hdmirx_dev *hdmirx_dev = container_of(dwork, struct rk_hdmirx_dev, delayed_work_hotplug); struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; + struct hdmirx_stream *stream = &hdmirx_dev->stream; + const struct v4l2_event evt_signal_lost = { + .type = RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST, + }; bool plugin; mutex_lock(&hdmirx_dev->work_lock); hdmirx_dev->get_timing = false; + v4l2_event_queue(&stream->vdev, &evt_signal_lost); plugin = tx_5v_power_present(hdmirx_dev); v4l2_ctrl_s_ctrl(hdmirx_dev->detect_tx_5v_ctrl, plugin); v4l2_dbg(1, debug, v4l2_dev, "%s: plugin:%d\n", __func__, plugin); diff --git a/include/uapi/linux/rk_hdmirx_config.h b/include/uapi/linux/rk_hdmirx_config.h index 3cf5b0c293b0..3e158f941af2 100644 --- a/include/uapi/linux/rk_hdmirx_config.h +++ b/include/uapi/linux/rk_hdmirx_config.h @@ -44,6 +44,7 @@ enum hdmirx_video_standard { HDMIRX_BT2020_RGB = 6, }; +/* Private v4l2 ioctl */ #define RK_HDMIRX_CMD_GET_FPS \ _IOR('V', BASE_VIDIOC_PRIVATE + 0, int) @@ -77,4 +78,8 @@ enum hdmirx_video_standard { #define RK_HDMIRX_CMD_GET_COLOR_SPACE \ _IOR('V', BASE_VIDIOC_PRIVATE + 10, int) +/* Private v4l2 event */ +#define RK_HDMIRX_V4L2_EVENT_SIGNAL_LOST \ + (V4L2_EVENT_PRIVATE_START + 1) + #endif /* _UAPI_RK_HDMIRX_CONFIG_H */ From 0d2ccf6058782cf3b01664db52746e50f02a25a6 Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Thu, 8 Sep 2022 12:39:52 +0000 Subject: [PATCH 041/204] drm/rockchip: dw_hdcp2: add reset func for ioctl Signed-off-by: Chen Shunqing Change-Id: I76c30690d5fa36489b930757a8fe749c0c085a66 --- drivers/gpu/drm/rockchip/dw_hdcp2.c | 53 ++++++++++++++++++++++++----- include/uapi/misc/dw_hdcp2.h | 3 ++ 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw_hdcp2.c b/drivers/gpu/drm/rockchip/dw_hdcp2.c index 44bc4293d0fc..f8362ddea171 100644 --- a/drivers/gpu/drm/rockchip/dw_hdcp2.c +++ b/drivers/gpu/drm/rockchip/dw_hdcp2.c @@ -80,6 +80,46 @@ enum { HDCP_PORT2, }; +static void dw_hdcp_free_hl_dev_slot(struct hl_device *hl_dev); + +static void dw_hdcp_free_hl(struct dw_hdcp *hdcp) +{ + dw_hdcp_free_hl_dev_slot(&hdcp->hl_dev); + hdcp->hl_dev.code_loaded = false; +} + +static void dw_hdcp_reset(struct dw_hdcp *hdcp) +{ + int ret; + + reset_control_assert(hdcp->rsts_bulk); + udelay(20); + reset_control_deassert(hdcp->rsts_bulk); + + ret = sip_hdcpkey_init(hdcp->id); + if (ret) + dev_err(hdcp->dev, "load hdcp key failed\n"); +} + +static int dw_hdcp_set_reset(struct dw_hdcp *hdcp, void __user *arg) +{ + u32 reset; + + if (!arg) + return -EFAULT; + + if (copy_from_user(&reset, arg, sizeof(reset))) + return -EFAULT; + + if (reset) { + dev_info(hdcp->dev, "hdcp reset\n"); + dw_hdcp_free_hl(hdcp); + dw_hdcp_reset(hdcp); + } + + return 0; +} + static int dw_hdcp_get_status(struct dw_hdcp *hdcp, void __user *arg) { struct hl_drv_ioc_status status; @@ -410,6 +450,8 @@ static long dw_hdcp_hld_ioctl(struct file *f, unsigned int cmd, unsigned long ar case RK_DRV_IOC_GET_STATUS: return dw_hdcp_get_status(hdcp, data); + case RK_DRV_IOC_RESET: + return dw_hdcp_set_reset(hdcp, data); default: return -EINVAL; } @@ -551,8 +593,7 @@ static int dw_hdcp_runtime_suspend(struct device *dev) hdcp->is_suspend = true; clk_bulk_disable_unprepare(hdcp->num_clks, hdcp->clks); - dw_hdcp_free_hl_dev_slot(&hdcp->hl_dev); - hdcp->hl_dev.code_loaded = false; + dw_hdcp_free_hl(hdcp); return 0; } @@ -566,13 +607,7 @@ static int dw_hdcp_runtime_resume(struct device *dev) if (ret) dev_err(dev, "prepare enable clk bulk failed\n"); - reset_control_assert(hdcp->rsts_bulk); - udelay(10); - reset_control_deassert(hdcp->rsts_bulk); - - ret = sip_hdcpkey_init(hdcp->id); - if (ret) - dev_err(dev, "load hdcp key failed\n"); + dw_hdcp_reset(hdcp); hdcp->is_suspend = false; return 0; diff --git a/include/uapi/misc/dw_hdcp2.h b/include/uapi/misc/dw_hdcp2.h index d4bbc995aba3..65b58ff67ca3 100644 --- a/include/uapi/misc/dw_hdcp2.h +++ b/include/uapi/misc/dw_hdcp2.h @@ -25,6 +25,7 @@ enum { HL_DRV_NR_WRITE_HPI, RK_DRV_NR_GET_STATUS, + RK_DRV_NR_RESET, HL_DRV_NR_MAX }; @@ -124,4 +125,6 @@ struct hl_drv_ioc_status { __u32 booted_status; }; +#define RK_DRV_IOC_RESET _IOR('H', RK_DRV_NR_RESET, __u32) + #endif // _DW_HDCP_HOST_LIB_DRIVER_LINUX_IF_H_ From 40cb5c370fc007167012c1de8860195414729127 Mon Sep 17 00:00:00 2001 From: Yifeng Zhao Date: Mon, 22 Aug 2022 19:30:08 +0800 Subject: [PATCH 042/204] mmc: sdhci-of-dwcmshc: optimize the clock processing for runtime PM 1. Disable the interface clock output at runtime suspend and enable it at runtime resume. 2. fix bug: [1476.144796][ T1281] mmc0: error -110 doing runtime resume [1476.204714][T24230] sdhci-dwcmshc fe2d0000.mmc: error -110 requesting status Signed-off-by: Yifeng Zhao Change-Id: I14ef9f8c723deda6fba81836d1a4c982e3580d54 --- drivers/mmc/host/sdhci-of-dwcmshc.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index f473d67334e0..157d1c4d3ccd 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -584,14 +584,11 @@ static int dwcmshc_resume(struct device *dev) static int dwcmshc_runtime_suspend(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); + u16 data; - priv->actual_clk = host->mmc->actual_clock; - sdhci_set_clock(host, 0); - priv->cclk_rate = clk_get_rate(pltfm_host->clk); - clk_set_rate(pltfm_host->clk, 24000000); - clk_bulk_disable_unprepare(ROCKCHIP_MAX_CLKS, priv->rockchip_clks); + data = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + data &= ~SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, data, SDHCI_CLOCK_CONTROL); return 0; } @@ -599,20 +596,13 @@ static int dwcmshc_runtime_suspend(struct device *dev) static int dwcmshc_runtime_resume(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); - int ret = 0; + u16 data; - clk_set_rate(pltfm_host->clk, priv->cclk_rate); - sdhci_set_clock(host, priv->actual_clk); - ret = clk_bulk_prepare_enable(ROCKCHIP_MAX_CLKS, priv->rockchip_clks); - /* - * DLL will not LOCK after frequency reduction, - * and it needs to be reconfigured. - */ - dwcmshc_rk_set_clock(host, priv->cclk_rate); + data = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + data |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, data, SDHCI_CLOCK_CONTROL); - return ret; + return 0; } #endif From ebf405e9ac023228f9debe88d228c6d5b72db0d7 Mon Sep 17 00:00:00 2001 From: Yiqing Zeng Date: Tue, 14 Jun 2022 21:19:21 +0800 Subject: [PATCH 043/204] arm64: dts: rockchip: rk3566-evb2: compatible with ov5695 and gc5025 Signed-off-by: Yiqing Zeng Change-Id: I0587126caa692a9c9faaa9c1566211a54a238d73 --- .../dts/rockchip/rk3566-evb2-lp4x-v10.dtsi | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi index fbbd5d038d54..318bf46e8842 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi @@ -78,6 +78,18 @@ remote-endpoint = <&gc8034_out>; data-lanes = <1 2 3 4>; }; + + mipi_in_ucam1: endpoint@2 { + reg = <2>; + remote-endpoint = <&ov5695_out>; + data-lanes = <1 2>; + }; + + mipi_in_ucam2: endpoint@3 { + reg = <3>; + remote-endpoint = <&gc5025_out>; + data-lanes = <1 2>; + }; }; port@1 { @@ -112,7 +124,7 @@ dphy1_in: endpoint@1 { reg = <1>; - remote-endpoint = <&ov5695_out>; + //remote-endpoint = <&ov5695_out>; data-lanes = <1 2>; }; }; @@ -149,7 +161,7 @@ dphy2_in: endpoint@1 { reg = <1>; - remote-endpoint = <&gc5025_out>; + //remote-endpoint = <&gc5025_out>; data-lanes = <1 2>; }; }; @@ -263,7 +275,7 @@ rockchip,camera-module-lens-name = "CHT842-MD"; port { ov5695_out: endpoint { - remote-endpoint = <&dphy1_in>; + remote-endpoint = <&mipi_in_ucam1>; data-lanes = <1 2>; }; }; @@ -288,7 +300,7 @@ rockchip,camera-module-lens-name = "CHT842-MD"; port { gc5025_out: endpoint { - remote-endpoint = <&dphy2_in>; + remote-endpoint = <&mipi_in_ucam2>; data-lanes = <1 2>; }; }; From 4e4348fed0204e37a22f4d9747e81fa0e353eaed Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Tue, 2 Aug 2022 11:37:42 +0000 Subject: [PATCH 044/204] drm/rockchip: direct_show: fix some parameters Signed-off-by: Jianwei Fan Change-Id: I5c018d13c52e6946add366ebc46242c9ca78f7ff --- .../drm/rockchip/rockchip_drm_direct_show.c | 18 +++++++++++++----- .../drm/rockchip/rockchip_drm_direct_show.h | 4 ++-- .../gpu/drm/rockchip/rockchip_drm_self_test.c | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_direct_show.c b/drivers/gpu/drm/rockchip/rockchip_drm_direct_show.c index 6679689f3316..9989820b5fc6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_direct_show.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_direct_show.c @@ -172,7 +172,7 @@ void rockchip_drm_direct_show_free_buffer(struct drm_device *drm, drm_gem_object_put(obj); } -struct drm_plane *rockchip_drm_direct_show_get_plane(struct drm_device *drm, char *name) +struct drm_plane *rockchip_drm_direct_show_get_plane(struct drm_device *drm, const char *name) { struct drm_plane *plane; @@ -190,15 +190,23 @@ struct drm_plane *rockchip_drm_direct_show_get_plane(struct drm_device *drm, cha return plane; } -struct drm_crtc *rockchip_drm_direct_show_get_crtc(struct drm_device *drm) +struct drm_crtc *rockchip_drm_direct_show_get_crtc(struct drm_device *drm, const char *name) { struct drm_crtc *crtc = NULL; bool crtc_active = false; drm_for_each_crtc(crtc, drm) { - if (crtc->state && crtc->state->active) { - crtc_active = true; - break; + if (name == NULL) { + if (crtc->state && crtc->state->active) { + crtc_active = true; + break; + } + } else { + if (crtc->state && crtc->state->active && + !strncmp(crtc->name, name, DRM_PROP_NAME_LEN)) { + crtc_active = true; + break; + } } } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_direct_show.h b/drivers/gpu/drm/rockchip/rockchip_drm_direct_show.h index 14a542fd63e2..939f0d451057 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_direct_show.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_direct_show.h @@ -56,8 +56,8 @@ int rockchip_drm_direct_show_alloc_buffer(struct drm_device *drm, struct rockchip_drm_direct_show_buffer *buffer); void rockchip_drm_direct_show_free_buffer(struct drm_device *drm, struct rockchip_drm_direct_show_buffer *buffer); -struct drm_crtc *rockchip_drm_direct_show_get_crtc(struct drm_device *drm); -struct drm_plane *rockchip_drm_direct_show_get_plane(struct drm_device *drm, char *name); +struct drm_crtc *rockchip_drm_direct_show_get_crtc(struct drm_device *drm, const char *name); +struct drm_plane *rockchip_drm_direct_show_get_plane(struct drm_device *drm, const char *name); int rockchip_drm_direct_show_commit(struct drm_device *drm, struct rockchip_drm_direct_show_commit_info *commit_info); int rockchip_drm_direct_show_disable_plane(struct drm_device *drm, struct drm_plane *plane); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_self_test.c b/drivers/gpu/drm/rockchip/rockchip_drm_self_test.c index b26bc2a7e466..7c764fca154d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_self_test.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_self_test.c @@ -145,7 +145,7 @@ static void rockchip_drm_self_test_commit(struct work_struct *work) rockchip_drm_draw_color_bar(self_test->drm_buffer[1]); /* get crtc and plane */ - self_test->crtc = rockchip_drm_direct_show_get_crtc(self_test->dev); + self_test->crtc = rockchip_drm_direct_show_get_crtc(self_test->dev, NULL); if (self_test->crtc == NULL) { pr_info("error: failed to get crtc\n"); goto free_buffer; From 720983a82cdd10ae27bdad2f9943ff2294e7aff9 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Fri, 16 Sep 2022 12:26:39 +0800 Subject: [PATCH 045/204] media: rockchip: vicap fixed error of get_selection when result of --get-compose is success, but width/height equal 0, may cause v4l2-ctl unable to save image Signed-off-by: Zefa Chen Change-Id: Ibe572b53da346aef233a15c70c6050ad2207a21d --- drivers/media/platform/rockchip/cif/capture.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 59592c0d8d15..61cd50d2c259 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -5770,9 +5770,7 @@ static int rkcif_g_selection(struct file *file, void *fh, s->r.width = stream->pixm.width; s->r.height = stream->pixm.height; } - } - - if (s->target == V4L2_SEL_TGT_CROP) { + } else if (s->target == V4L2_SEL_TGT_CROP) { if (stream->crop_mask & (CROP_SRC_USR_MASK | CROP_SRC_SENSOR_MASK)) { s->r = stream->crop[CROP_SRC_ACT]; } else { @@ -5781,6 +5779,8 @@ static int rkcif_g_selection(struct file *file, void *fh, s->r.width = stream->pixm.width; s->r.height = stream->pixm.height; } + } else { + goto err; } return ret; From 0267ad3b0c99bd90296260cc2d692a46adcc2797 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Sat, 17 Sep 2022 09:54:15 +0800 Subject: [PATCH 046/204] arm64: dts: rockchip: remove non-existent vopl on rk3326 Change-Id: I7e3e05d873ddcbe96d90cd4d8dbf39e30cb11761 Signed-off-by: Liang Chen --- arch/arm64/boot/dts/rockchip/px30-android.dtsi | 1 - arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dtsi | 12 ------------ arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi | 12 ------------ arch/arm64/boot/dts/rockchip/rk3326-linux.dtsi | 1 - arch/arm64/boot/dts/rockchip/rk3326.dtsi | 10 ++++++++++ 5 files changed, 10 insertions(+), 26 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-android.dtsi b/arch/arm64/boot/dts/rockchip/px30-android.dtsi index 98a94a448518..3f296c44e5dd 100644 --- a/arch/arm64/boot/dts/rockchip/px30-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-android.dtsi @@ -58,7 +58,6 @@ &display_subsystem { status = "disabled"; - ports = <&vopb_out>, <&vopl_out>; logo-memory-region = <&drm_logo>; route { diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dtsi index 9e7f1ea419a9..d3606248dc46 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dtsi @@ -245,10 +245,6 @@ status = "okay"; }; -&dsi_in_vopl { - status = "disabled"; -}; - &route_dsi { connect = <&vopb_out_dsi>; status = "okay"; @@ -800,14 +796,6 @@ status = "okay"; }; -&vopl { - status = "okay"; -}; - -&vopl_mmu { - status = "okay"; -}; - &mpp_srv { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi index fbadb5259adc..2413fe868b92 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi @@ -304,10 +304,6 @@ status = "okay"; }; -&dsi_in_vopl { - status = "disabled"; -}; - &route_dsi { connect = <&vopb_out_dsi>; status = "okay"; @@ -846,14 +842,6 @@ status = "okay"; }; -&vopl { - status = "okay"; -}; - -&vopl_mmu { - status = "okay"; -}; - &mpp_srv { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-linux.dtsi b/arch/arm64/boot/dts/rockchip/rk3326-linux.dtsi index 623431e2e355..6ba60b41291b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-linux.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3326-linux.dtsi @@ -48,7 +48,6 @@ &display_subsystem { status = "disabled"; - ports = <&vopb_out>, <&vopl_out>; logo-memory-region = <&drm_logo>; route { diff --git a/arch/arm64/boot/dts/rockchip/rk3326.dtsi b/arch/arm64/boot/dts/rockchip/rk3326.dtsi index fdb000c14038..004bda94a955 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3326.dtsi @@ -10,6 +10,10 @@ assigned-clock-rates = <1040000000>; }; +&display_subsystem { + ports = <&vopb_out>; +}; + &gpu_opp_table { opp-520000000 { opp-hz = /bits/ 64 <520000000>; @@ -76,3 +80,9 @@ }; }; }; + +/delete-node/ &dsi_in_vopl; +/delete-node/ &lvds_vopl_in; +/delete-node/ &rgb_in_vopl; +/delete-node/ &vopl; +/delete-node/ &vopl_mmu; From 1a0f4ae36ea9d862065ea9601ffe894d290413f5 Mon Sep 17 00:00:00 2001 From: Lin Jianhua Date: Fri, 16 Sep 2022 09:34:44 +0800 Subject: [PATCH 047/204] ARM: dts: rockchip: add rk3308hs-voice-module-board-v10-aarch32.dts Signed-off-by: Lin Jianhua Change-Id: I3e513c4b22848e969087893db7f397a9089cbe97 --- arch/arm/boot/dts/Makefile | 3 +- ...k3308hs-voice-module-board-v10-aarch32.dts | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/rk3308hs-voice-module-board-v10-aarch32.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 35473a5f6389..5212e7c0c8b0 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1037,7 +1037,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3288-vyasa.dtb \ rk3308bs-evb-amic-v11-aarch32.dtb \ rk3308bs-evb-dmic-pdm-v11-aarch32.dtb \ - rk3308bs-evb-mipi-display-v11-aarch32.dtb + rk3308bs-evb-mipi-display-v11-aarch32.dtb \ + rk3308hs-voice-module-board-v10-aarch32.dtb dtb-$(CONFIG_ARCH_S3C24XX) += \ s3c2416-smdk2416.dtb dtb-$(CONFIG_ARCH_S3C64XX) += \ diff --git a/arch/arm/boot/dts/rk3308hs-voice-module-board-v10-aarch32.dts b/arch/arm/boot/dts/rk3308hs-voice-module-board-v10-aarch32.dts new file mode 100644 index 000000000000..dd94a739ea07 --- /dev/null +++ b/arch/arm/boot/dts/rk3308hs-voice-module-board-v10-aarch32.dts @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd + */ + +/dts-v1/; + +#include "rk3308-voice-module-board-v11-aarch32.dts" + +/ { + model = "Rockchip RK3308HS Voice Module Board V10 (AArch32)"; + compatible = "rockchip,rk3308hs-voice-module-board-v10-aarch32", "rockchip,rk3308"; + + /delete-node/ vdd-1v0; + + vdd_0v9: vdd-0v9 { + compatible = "regulator-fixed"; + regulator-name = "vdd_0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + }; +}; + +&vcc_ddr { + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; +}; + +&vdd_log { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; +}; From 884bd428585b56e46742b838717888c97b47ff30 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 16 Sep 2022 16:28:07 +0800 Subject: [PATCH 048/204] arm64: dts: rockchip: rk3588-android: Move ramoops to reserved-memory Follow Documentation/devicetree/bindings/reserved-memory/ramoops.txt This is a child-node of "/reserved-memory". Signed-off-by: Tao Huang Change-Id: I02055d58b2e1f57f07030dbb1e1dbf74e1b37ff6 --- .../boot/dts/rockchip/rk3588-android.dtsi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-android.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-android.dtsi index 71ba6f7eb0fe..c8c1c6e45b9b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-android.dtsi @@ -53,15 +53,6 @@ }; }; - ramoops: ramoops@110000 { - compatible = "ramoops"; - reg = <0x0 0x110000 0x0 0xf0000>; - record-size = <0x20000>; - console-size = <0x80000>; - ftrace-size = <0x00000>; - pmsg-size = <0x50000>; - }; - reserved-memory { #address-cells = <2>; #size-cells = <2>; @@ -83,6 +74,15 @@ compatible = "rockchip,drm-cubic-lut"; reg = <0x0 0x0 0x0 0x0>; }; + + ramoops: ramoops@110000 { + compatible = "ramoops"; + reg = <0x0 0x110000 0x0 0xf0000>; + record-size = <0x20000>; + console-size = <0x80000>; + ftrace-size = <0x00000>; + pmsg-size = <0x50000>; + }; }; }; From 74c8bbbd67a137f357f00d3850a88faf1118bd3e Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Fri, 16 Sep 2022 16:33:20 +0800 Subject: [PATCH 049/204] arm64: dts: rockchip: rk3588-linux: Move ramoops to reserved-memory Follow Documentation/devicetree/bindings/reserved-memory/ramoops.txt This is a child-node of "/reserved-memory". Signed-off-by: Tao Huang Change-Id: I3f06deb6e3a49edebc03de4684c44d52d13c37e0 --- arch/arm64/boot/dts/rockchip/rk3588-linux.dtsi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-linux.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-linux.dtsi index ea2303acd475..12b815850b57 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-linux.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-linux.dtsi @@ -60,15 +60,6 @@ }; }; - ramoops: ramoops@110000 { - compatible = "ramoops"; - reg = <0x0 0x110000 0x0 0xf0000>; - record-size = <0x20000>; - console-size = <0x80000>; - ftrace-size = <0x00000>; - pmsg-size = <0x50000>; - }; - reserved-memory { #address-cells = <2>; #size-cells = <2>; @@ -90,6 +81,15 @@ compatible = "rockchip,drm-cubic-lut"; reg = <0x0 0x0 0x0 0x0>; }; + + ramoops: ramoops@110000 { + compatible = "ramoops"; + reg = <0x0 0x110000 0x0 0xf0000>; + record-size = <0x20000>; + console-size = <0x80000>; + ftrace-size = <0x00000>; + pmsg-size = <0x50000>; + }; }; }; From 4e01b0c2eabba4439f25f553af633a6d2c5ba523 Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Fri, 16 Sep 2022 12:49:40 +0000 Subject: [PATCH 050/204] media: rockchip: hdmirx: add debug node 1. sys/class/hdmirx/hdmirx/status show connected or disconnected 2. echo on/off to control hpd Signed-off-by: Chen Shunqing Change-Id: Ib7fecdb7d227158e5278270b166b69ec2beaf8c4 --- .../platform/rockchip/hdmirx/rk_hdmirx.c | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index 2650b0cd3126..aafbf0a3df1f 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -221,6 +221,8 @@ struct rk_hdmirx_dev { bool freq_qos_add; bool get_timing; bool cec_enable; + bool hpd_on; + bool force_off; u8 hdcp_enable; u32 num_clks; u32 edid_blocks_written; @@ -975,6 +977,9 @@ static void hdmirx_hpd_ctrl(struct rk_hdmirx_dev *hdmirx_dev, bool en) { struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; + if (hdmirx_dev->force_off && en) + return; + v4l2_dbg(1, debug, v4l2_dev, "%s: %sable, hpd_trigger_level:%d\n", __func__, en ? "en" : "dis", hdmirx_dev->hpd_trigger_level); @@ -984,6 +989,7 @@ static void hdmirx_hpd_ctrl(struct rk_hdmirx_dev *hdmirx_dev, bool en) HDCP1_P0_GPIO_IN_SEL | HDCP1_P0_GPIO_IN_SEL << 16); hdmirx_dev->hdcp->hdcp2_connect_ctrl(hdmirx_dev->hdcp, en); } + hdmirx_dev->hpd_on = en; } static int hdmirx_write_edid(struct rk_hdmirx_dev *hdmirx_dev, @@ -3399,14 +3405,54 @@ static ssize_t edid_store(struct device *dev, return count; } +static ssize_t status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct rk_hdmirx_dev *hdmirx_dev = dev_get_drvdata(dev); + + if (!hdmirx_dev) + return -EINVAL; + + return snprintf(buf, PAGE_SIZE, "%s\n", + hdmirx_dev->hpd_on ? "connected" : "disconnected"); +} + +static ssize_t status_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct rk_hdmirx_dev *hdmirx_dev = dev_get_drvdata(dev); + + if (!hdmirx_dev) + return -EINVAL; + + if (sysfs_streq(buf, "on")) { + hdmirx_dev->force_off = false; + if (!tx_5v_power_present(hdmirx_dev)) + return count; + hdmirx_hpd_ctrl(hdmirx_dev, true); + } else if (sysfs_streq(buf, "off")) { + hdmirx_dev->force_off = true; + if (!tx_5v_power_present(hdmirx_dev)) + return count; + hdmirx_hpd_ctrl(hdmirx_dev, false); + } else { + return -EINVAL; + } + + return count; +} + static DEVICE_ATTR_RO(audio_rate); static DEVICE_ATTR_RO(audio_present); static DEVICE_ATTR_RW(edid); +static DEVICE_ATTR_RW(status); static struct attribute *hdmirx_attrs[] = { &dev_attr_audio_rate.attr, &dev_attr_audio_present.attr, &dev_attr_edid.attr, + &dev_attr_status.attr, NULL }; ATTRIBUTE_GROUPS(hdmirx); @@ -3764,7 +3810,7 @@ static int hdmirx_status_show(struct seq_file *s, void *v) else seq_puts(s, "UNKNOWN\n"); - seq_printf(s, "Mode: %ux%u%s%u (%ux%u)", + seq_printf(s, "Timing: %ux%u%s%u (%ux%u)", bt->width, bt->height, bt->interlaced ? "i" : "p", fps, htot, vtot); @@ -3772,6 +3818,23 @@ static int hdmirx_status_show(struct seq_file *s, void *v) bt->hfrontporch, bt->hsync, bt->hbackporch, bt->vfrontporch, bt->vsync, bt->vbackporch); seq_printf(s, "Pixel Clk: %llu\n", bt->pixelclock); + seq_printf(s, "Mode: %s\n", hdmirx_dev->is_dvi_mode ? "DVI" : "HDMI"); + + hdmirx_get_color_range(hdmirx_dev); + seq_puts(s, "Color Range: "); + if (hdmirx_dev->cur_color_range == HDMIRX_DEFAULT_RANGE) + seq_puts(s, "DEFAULT\n"); + else if (hdmirx_dev->cur_color_range == HDMIRX_FULL_RANGE) + seq_puts(s, "FULL\n"); + else + seq_puts(s, "LIMITED\n"); + + hdmirx_get_color_space(hdmirx_dev); + seq_puts(s, "Color Space: "); + if (hdmirx_dev->cur_color_space < 8) + seq_printf(s, "%s\n", hdmirx_color_space[hdmirx_dev->cur_color_space]); + else + seq_puts(s, "Unknown\n"); return 0; } From 6148a5867ad33f4d8b37f1620d755799cb916b39 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 15 Sep 2022 15:16:11 +0800 Subject: [PATCH 051/204] dma-buf: heaps: Add the rk_system_heap Copy from system_heap.c. In order to make a smooth change, CONFIG_DMABUF_HEAPS_SYSTEM will build rk_system_heap. Signed-off-by: Jianqun Xu Change-Id: I7176b6bfecb483c87128857293be67f3e19a101a --- drivers/dma-buf/heaps/Makefile | 2 +- drivers/dma-buf/heaps/rk_system_heap.c | 842 +++++++++++++++++++++++++ 2 files changed, 843 insertions(+), 1 deletion(-) create mode 100644 drivers/dma-buf/heaps/rk_system_heap.c diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile index 4d4cd94a3a4a..c5650228bfab 100644 --- a/drivers/dma-buf/heaps/Makefile +++ b/drivers/dma-buf/heaps/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DMABUF_HEAPS_DEFERRED_FREE) += deferred-free-helper.o obj-$(CONFIG_DMABUF_HEAPS_PAGE_POOL) += page_pool.o -obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o +obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += rk_system_heap.o obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o diff --git a/drivers/dma-buf/heaps/rk_system_heap.c b/drivers/dma-buf/heaps/rk_system_heap.c new file mode 100644 index 000000000000..9a7fc51f562c --- /dev/null +++ b/drivers/dma-buf/heaps/rk_system_heap.c @@ -0,0 +1,842 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * DMABUF System heap exporter for Rockchip + * + * Copyright (C) 2011 Google, Inc. + * Copyright (C) 2019, 2020 Linaro Ltd. + * Copyright (c) 2021, 2022 Rockchip Electronics Co. Ltd. + * + * Portions based off of Andrew Davis' SRAM heap: + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "page_pool.h" +#include "deferred-free-helper.h" + +static struct dma_heap *sys_heap; +static struct dma_heap *sys_dma32_heap; +static struct dma_heap *sys_uncached_heap; +static struct dma_heap *sys_uncached_dma32_heap; + +/* Default setting */ +static u32 bank_bit_first = 12; +static u32 bank_bit_mask = 0x7; + +struct system_heap_buffer { + struct dma_heap *heap; + struct list_head attachments; + struct mutex lock; + unsigned long len; + struct sg_table sg_table; + int vmap_cnt; + void *vaddr; + struct deferred_freelist_item deferred_free; + + bool uncached; +}; + +struct dma_heap_attachment { + struct device *dev; + struct sg_table *table; + struct list_head list; + bool mapped; + + bool uncached; +}; + +#define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP) +#define MID_ORDER_GFP (LOW_ORDER_GFP | __GFP_NOWARN) +#define HIGH_ORDER_GFP (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \ + | __GFP_NORETRY) & ~__GFP_RECLAIM) \ + | __GFP_COMP) +static gfp_t order_flags[] = {HIGH_ORDER_GFP, MID_ORDER_GFP, LOW_ORDER_GFP}; +/* + * The selection of the orders used for allocation (1MB, 64K, 4K) is designed + * to match with the sizes often found in IOMMUs. Using order 4 pages instead + * of order 0 pages can significantly improve the performance of many IOMMUs + * by reducing TLB pressure and time spent updating page tables. + */ +static unsigned int orders[] = {8, 4, 0}; +#define NUM_ORDERS ARRAY_SIZE(orders) +struct dmabuf_page_pool *pools[NUM_ORDERS]; +struct dmabuf_page_pool *dma32_pools[NUM_ORDERS]; + +static struct sg_table *dup_sg_table(struct sg_table *table) +{ + struct sg_table *new_table; + int ret, i; + struct scatterlist *sg, *new_sg; + + new_table = kzalloc(sizeof(*new_table), GFP_KERNEL); + if (!new_table) + return ERR_PTR(-ENOMEM); + + ret = sg_alloc_table(new_table, table->orig_nents, GFP_KERNEL); + if (ret) { + kfree(new_table); + return ERR_PTR(-ENOMEM); + } + + new_sg = new_table->sgl; + for_each_sgtable_sg(table, sg, i) { + sg_set_page(new_sg, sg_page(sg), sg->length, sg->offset); + new_sg = sg_next(new_sg); + } + + return new_table; +} + +static int system_heap_attach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + struct sg_table *table; + + a = kzalloc(sizeof(*a), GFP_KERNEL); + if (!a) + return -ENOMEM; + + table = dup_sg_table(&buffer->sg_table); + if (IS_ERR(table)) { + kfree(a); + return -ENOMEM; + } + + a->table = table; + a->dev = attachment->dev; + INIT_LIST_HEAD(&a->list); + a->mapped = false; + a->uncached = buffer->uncached; + attachment->priv = a; + + mutex_lock(&buffer->lock); + list_add(&a->list, &buffer->attachments); + mutex_unlock(&buffer->lock); + + return 0; +} + +static void system_heap_detach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a = attachment->priv; + + mutex_lock(&buffer->lock); + list_del(&a->list); + mutex_unlock(&buffer->lock); + + sg_free_table(a->table); + kfree(a->table); + kfree(a); +} + +static struct sg_table *system_heap_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction direction) +{ + struct dma_heap_attachment *a = attachment->priv; + struct sg_table *table = a->table; + int attr = attachment->dma_map_attrs; + int ret; + + if (a->uncached) + attr |= DMA_ATTR_SKIP_CPU_SYNC; + + ret = dma_map_sgtable(attachment->dev, table, direction, attr); + if (ret) + return ERR_PTR(ret); + + a->mapped = true; + return table; +} + +static void system_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *table, + enum dma_data_direction direction) +{ + struct dma_heap_attachment *a = attachment->priv; + int attr = attachment->dma_map_attrs; + + if (a->uncached) + attr |= DMA_ATTR_SKIP_CPU_SYNC; + a->mapped = false; + dma_unmap_sgtable(attachment->dev, table, direction, attr); +} + +static int system_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction direction) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + + mutex_lock(&buffer->lock); + + if (buffer->vmap_cnt) + invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); + + if (!buffer->uncached) { + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + dma_sync_sgtable_for_cpu(a->dev, a->table, direction); + } + } + mutex_unlock(&buffer->lock); + + return 0; +} + +static int system_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction direction) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + + mutex_lock(&buffer->lock); + + if (buffer->vmap_cnt) + flush_kernel_vmap_range(buffer->vaddr, buffer->len); + + if (!buffer->uncached) { + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + dma_sync_sgtable_for_device(a->dev, a->table, direction); + } + } + mutex_unlock(&buffer->lock); + + return 0; +} + +static int system_heap_sgl_sync_range(struct device *dev, + struct sg_table *sgt, + unsigned int offset, + unsigned int length, + enum dma_data_direction dir, + bool for_cpu) +{ + struct scatterlist *sg; + unsigned int len = 0; + dma_addr_t sg_dma_addr; + int i; + + for_each_sgtable_sg(sgt, sg, i) { + unsigned int sg_offset, sg_left, size = 0; + + sg_dma_addr = sg_phys(sg); + + len += sg->length; + if (len <= offset) + continue; + + sg_left = len - offset; + sg_offset = sg->length - sg_left; + + size = (length < sg_left) ? length : sg_left; + if (for_cpu) + dma_sync_single_range_for_cpu(dev, sg_dma_addr, + sg_offset, size, dir); + else + dma_sync_single_range_for_device(dev, sg_dma_addr, + sg_offset, size, dir); + + offset += size; + length -= size; + + if (length == 0) + break; + } + + return 0; +} + +static int +system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, + enum dma_data_direction direction, + unsigned int offset, + unsigned int len) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct dma_heap *heap = buffer->heap; + struct sg_table *table = &buffer->sg_table; + int ret; + + if (direction == DMA_TO_DEVICE) + return 0; + + mutex_lock(&buffer->lock); + if (buffer->vmap_cnt) + invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); + + if (buffer->uncached) { + mutex_unlock(&buffer->lock); + return 0; + } + + ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table, + offset, len, direction, true); + mutex_unlock(&buffer->lock); + + return ret; +} + +static int +system_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, + enum dma_data_direction direction, + unsigned int offset, + unsigned int len) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct dma_heap *heap = buffer->heap; + struct sg_table *table = &buffer->sg_table; + int ret; + + mutex_lock(&buffer->lock); + if (buffer->vmap_cnt) + flush_kernel_vmap_range(buffer->vaddr, buffer->len); + + if (buffer->uncached) { + mutex_unlock(&buffer->lock); + return 0; + } + + ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table, + offset, len, direction, false); + mutex_unlock(&buffer->lock); + + return ret; +} + +static int system_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct sg_table *table = &buffer->sg_table; + unsigned long addr = vma->vm_start; + struct sg_page_iter piter; + int ret; + + if (buffer->uncached) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + for_each_sgtable_page(table, &piter, vma->vm_pgoff) { + struct page *page = sg_page_iter_page(&piter); + + ret = remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE, + vma->vm_page_prot); + if (ret) + return ret; + addr += PAGE_SIZE; + if (addr >= vma->vm_end) + return 0; + } + return 0; +} + +static void *system_heap_do_vmap(struct system_heap_buffer *buffer) +{ + struct sg_table *table = &buffer->sg_table; + int npages = PAGE_ALIGN(buffer->len) / PAGE_SIZE; + struct page **pages = vmalloc(sizeof(struct page *) * npages); + struct page **tmp = pages; + struct sg_page_iter piter; + pgprot_t pgprot = PAGE_KERNEL; + void *vaddr; + + if (!pages) + return ERR_PTR(-ENOMEM); + + if (buffer->uncached) + pgprot = pgprot_writecombine(PAGE_KERNEL); + + for_each_sgtable_page(table, &piter, 0) { + WARN_ON(tmp - pages >= npages); + *tmp++ = sg_page_iter_page(&piter); + } + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + vfree(pages); + + if (!vaddr) + return ERR_PTR(-ENOMEM); + + return vaddr; +} + +static void *system_heap_vmap(struct dma_buf *dmabuf) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + void *vaddr; + + mutex_lock(&buffer->lock); + if (buffer->vmap_cnt) { + buffer->vmap_cnt++; + vaddr = buffer->vaddr; + goto out; + } + + vaddr = system_heap_do_vmap(buffer); + if (IS_ERR(vaddr)) + goto out; + + buffer->vaddr = vaddr; + buffer->vmap_cnt++; +out: + mutex_unlock(&buffer->lock); + + return vaddr; +} + +static void system_heap_vunmap(struct dma_buf *dmabuf, void *vaddr) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + + mutex_lock(&buffer->lock); + if (!--buffer->vmap_cnt) { + vunmap(buffer->vaddr); + buffer->vaddr = NULL; + } + mutex_unlock(&buffer->lock); +} + +static int system_heap_zero_buffer(struct system_heap_buffer *buffer) +{ + struct sg_table *sgt = &buffer->sg_table; + struct sg_page_iter piter; + struct page *p; + void *vaddr; + int ret = 0; + + for_each_sgtable_page(sgt, &piter, 0) { + p = sg_page_iter_page(&piter); + vaddr = kmap_atomic(p); + memset(vaddr, 0, PAGE_SIZE); + kunmap_atomic(vaddr); + } + + return ret; +} + +static void system_heap_buf_free(struct deferred_freelist_item *item, + enum df_reason reason) +{ + struct system_heap_buffer *buffer; + struct sg_table *table; + struct scatterlist *sg; + int i, j; + + buffer = container_of(item, struct system_heap_buffer, deferred_free); + /* Zero the buffer pages before adding back to the pool */ + if (reason == DF_NORMAL) + if (system_heap_zero_buffer(buffer)) + reason = DF_UNDER_PRESSURE; // On failure, just free + + table = &buffer->sg_table; + for_each_sgtable_sg(table, sg, i) { + struct page *page = sg_page(sg); + + if (reason == DF_UNDER_PRESSURE) { + __free_pages(page, compound_order(page)); + } else { + for (j = 0; j < NUM_ORDERS; j++) { + if (compound_order(page) == orders[j]) + break; + } + dmabuf_page_pool_free(pools[j], page); + } + } + sg_free_table(table); + kfree(buffer); +} + +static void system_heap_dma_buf_release(struct dma_buf *dmabuf) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + int npages = PAGE_ALIGN(buffer->len) / PAGE_SIZE; + + deferred_free(&buffer->deferred_free, system_heap_buf_free, npages); +} + +static const struct dma_buf_ops system_heap_buf_ops = { + .attach = system_heap_attach, + .detach = system_heap_detach, + .map_dma_buf = system_heap_map_dma_buf, + .unmap_dma_buf = system_heap_unmap_dma_buf, + .begin_cpu_access = system_heap_dma_buf_begin_cpu_access, + .end_cpu_access = system_heap_dma_buf_end_cpu_access, + .begin_cpu_access_partial = system_heap_dma_buf_begin_cpu_access_partial, + .end_cpu_access_partial = system_heap_dma_buf_end_cpu_access_partial, + .mmap = system_heap_mmap, + .vmap = system_heap_vmap, + .vunmap = system_heap_vunmap, + .release = system_heap_dma_buf_release, +}; + +static struct page *system_heap_alloc_largest_available(struct dma_heap *heap, + unsigned long size, + unsigned int max_order) +{ + struct page *page; + int i; + const char *name = dma_heap_get_name(heap); + struct dmabuf_page_pool **pool; + + pool = strstr(name, "dma32") ? dma32_pools : pools; + for (i = 0; i < NUM_ORDERS; i++) { + if (size < (PAGE_SIZE << orders[i])) + continue; + if (max_order < orders[i]) + continue; + page = dmabuf_page_pool_alloc(pool[i]); + if (!page) + continue; + return page; + } + return NULL; +} + +static struct dma_buf *system_heap_do_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags, + bool uncached) +{ + struct system_heap_buffer *buffer; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + unsigned long size_remaining = len; + unsigned int max_order = orders[0]; + struct dma_buf *dmabuf; + struct sg_table *table; + struct scatterlist *sg; + struct list_head pages; + struct page *page, *tmp_page; + int i, ret = -ENOMEM; + struct list_head lists[8]; + unsigned int block_index[8] = {0}; + unsigned int block_1M = 0; + unsigned int block_64K = 0; + unsigned int maximum; + int j; + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&buffer->attachments); + mutex_init(&buffer->lock); + buffer->heap = heap; + buffer->len = len; + buffer->uncached = uncached; + + INIT_LIST_HEAD(&pages); + for (i = 0; i < 8; i++) + INIT_LIST_HEAD(&lists[i]); + i = 0; + while (size_remaining > 0) { + /* + * Avoid trying to allocate memory if the process + * has been killed by SIGKILL + */ + if (fatal_signal_pending(current)) + goto free_buffer; + + page = system_heap_alloc_largest_available(heap, size_remaining, max_order); + if (!page) + goto free_buffer; + + size_remaining -= page_size(page); + max_order = compound_order(page); + if (max_order) { + if (max_order == 8) + block_1M++; + if (max_order == 4) + block_64K++; + list_add_tail(&page->lru, &pages); + } else { + dma_addr_t phys = page_to_phys(page); + unsigned int bit_index = ((phys >> bank_bit_first) & bank_bit_mask) & 0x7; + + list_add_tail(&page->lru, &lists[bit_index]); + block_index[bit_index]++; + } + i++; + } + + table = &buffer->sg_table; + if (sg_alloc_table(table, i, GFP_KERNEL)) + goto free_buffer; + + maximum = block_index[0]; + for (i = 1; i < 8; i++) + maximum = max(maximum, block_index[i]); + sg = table->sgl; + list_for_each_entry_safe(page, tmp_page, &pages, lru) { + sg_set_page(sg, page, page_size(page), 0); + sg = sg_next(sg); + list_del(&page->lru); + } + for (i = 0; i < maximum; i++) { + for (j = 0; j < 8; j++) { + if (!list_empty(&lists[j])) { + page = list_first_entry(&lists[j], struct page, lru); + sg_set_page(sg, page, PAGE_SIZE, 0); + sg = sg_next(sg); + list_del(&page->lru); + } + } + } + + /* create the dmabuf */ + exp_info.exp_name = dma_heap_get_name(heap); + exp_info.ops = &system_heap_buf_ops; + exp_info.size = buffer->len; + exp_info.flags = fd_flags; + exp_info.priv = buffer; + dmabuf = dma_buf_export(&exp_info); + if (IS_ERR(dmabuf)) { + ret = PTR_ERR(dmabuf); + goto free_pages; + } + + /* + * For uncached buffers, we need to initially flush cpu cache, since + * the __GFP_ZERO on the allocation means the zeroing was done by the + * cpu and thus it is likely cached. Map (and implicitly flush) and + * unmap it now so we don't get corruption later on. + */ + if (buffer->uncached) { + dma_map_sgtable(dma_heap_get_dev(heap), table, DMA_BIDIRECTIONAL, 0); + dma_unmap_sgtable(dma_heap_get_dev(heap), table, DMA_BIDIRECTIONAL, 0); + } + + return dmabuf; + +free_pages: + for_each_sgtable_sg(table, sg, i) { + struct page *p = sg_page(sg); + + __free_pages(p, compound_order(p)); + } + sg_free_table(table); +free_buffer: + list_for_each_entry_safe(page, tmp_page, &pages, lru) + __free_pages(page, compound_order(page)); + for (i = 0; i < 8; i++) { + list_for_each_entry_safe(page, tmp_page, &lists[i], lru) + __free_pages(page, compound_order(page)); + } + kfree(buffer); + + return ERR_PTR(ret); +} + +static struct dma_buf *system_heap_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + return system_heap_do_allocate(heap, len, fd_flags, heap_flags, false); +} + +static long system_get_pool_size(struct dma_heap *heap) +{ + int i; + long num_pages = 0; + struct dmabuf_page_pool **pool; + const char *name = dma_heap_get_name(heap); + + pool = pools; + if (!strcmp(name, "system-dma32") || !strcmp(name, "system-uncached-dma32")) + pool = dma32_pools; + for (i = 0; i < NUM_ORDERS; i++, pool++) { + num_pages += ((*pool)->count[POOL_LOWPAGE] + + (*pool)->count[POOL_HIGHPAGE]) << (*pool)->order; + } + + return num_pages << PAGE_SHIFT; +} + +static const struct dma_heap_ops system_heap_ops = { + .allocate = system_heap_allocate, + .get_pool_size = system_get_pool_size, +}; + +static struct dma_buf *system_uncached_heap_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + return system_heap_do_allocate(heap, len, fd_flags, heap_flags, true); +} + +/* Dummy function to be used until we can call coerce_mask_and_coherent */ +static struct dma_buf *system_uncached_heap_not_initialized(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + return ERR_PTR(-EBUSY); +} + +static struct dma_heap_ops system_uncached_heap_ops = { + /* After system_heap_create is complete, we will swap this */ + .allocate = system_uncached_heap_not_initialized, +}; + +static int set_heap_dev_dma(struct device *heap_dev) +{ + int err = 0; + + if (!heap_dev) + return -EINVAL; + + dma_coerce_mask_and_coherent(heap_dev, DMA_BIT_MASK(64)); + + if (!heap_dev->dma_parms) { + heap_dev->dma_parms = devm_kzalloc(heap_dev, + sizeof(*heap_dev->dma_parms), + GFP_KERNEL); + if (!heap_dev->dma_parms) + return -ENOMEM; + + err = dma_set_max_seg_size(heap_dev, (unsigned int)DMA_BIT_MASK(64)); + if (err) { + devm_kfree(heap_dev, heap_dev->dma_parms); + dev_err(heap_dev, "Failed to set DMA segment size, err:%d\n", err); + return err; + } + } + + return 0; +} + +static int system_heap_create(void) +{ + struct dma_heap_export_info exp_info; + int i, err = 0; + struct dram_addrmap_info *ddr_map_info; + + /* + * Since swiotlb has memory size limitation, this will calculate + * the maximum size locally. + * + * Once swiotlb_max_segment() return not '0', means that the totalram size + * is larger than 4GiB and swiotlb is not force mode, in this case, system + * heap should limit largest allocation. + * + * FIX: fix the orders[] as a workaround. + */ + if (swiotlb_max_segment()) { + unsigned int max_size = (1 << IO_TLB_SHIFT) * IO_TLB_SEGSIZE; + int max_order = MAX_ORDER; + int i; + + max_size = max_t(unsigned int, max_size, PAGE_SIZE) >> PAGE_SHIFT; + max_order = min(max_order, ilog2(max_size)); + for (i = 0; i < NUM_ORDERS; i++) { + if (max_order < orders[i]) + orders[i] = max_order; + pr_info("system_heap: orders[%d] = %u\n", i, orders[i]); + } + } + + for (i = 0; i < NUM_ORDERS; i++) { + pools[i] = dmabuf_page_pool_create(order_flags[i], orders[i]); + + if (!pools[i]) { + int j; + + pr_err("%s: page pool creation failed!\n", __func__); + for (j = 0; j < i; j++) + dmabuf_page_pool_destroy(pools[j]); + return -ENOMEM; + } + } + + for (i = 0; i < NUM_ORDERS; i++) { + dma32_pools[i] = dmabuf_page_pool_create(order_flags[i] | GFP_DMA32, orders[i]); + + if (!dma32_pools[i]) { + int j; + + pr_err("%s: page dma32 pool creation failed!\n", __func__); + for (j = 0; j < i; j++) + dmabuf_page_pool_destroy(dma32_pools[j]); + goto err_dma32_pool; + } + } + + exp_info.name = "system"; + exp_info.ops = &system_heap_ops; + exp_info.priv = NULL; + + sys_heap = dma_heap_add(&exp_info); + if (IS_ERR(sys_heap)) + return PTR_ERR(sys_heap); + + exp_info.name = "system-dma32"; + exp_info.ops = &system_heap_ops; + exp_info.priv = NULL; + + sys_dma32_heap = dma_heap_add(&exp_info); + if (IS_ERR(sys_dma32_heap)) + return PTR_ERR(sys_dma32_heap); + + exp_info.name = "system-uncached"; + exp_info.ops = &system_uncached_heap_ops; + exp_info.priv = NULL; + + sys_uncached_heap = dma_heap_add(&exp_info); + if (IS_ERR(sys_uncached_heap)) + return PTR_ERR(sys_uncached_heap); + + err = set_heap_dev_dma(dma_heap_get_dev(sys_uncached_heap)); + if (err) + return err; + + exp_info.name = "system-uncached-dma32"; + exp_info.ops = &system_uncached_heap_ops; + exp_info.priv = NULL; + + sys_uncached_dma32_heap = dma_heap_add(&exp_info); + if (IS_ERR(sys_uncached_dma32_heap)) + return PTR_ERR(sys_uncached_dma32_heap); + + err = set_heap_dev_dma(dma_heap_get_dev(sys_uncached_dma32_heap)); + if (err) + return err; + dma_coerce_mask_and_coherent(dma_heap_get_dev(sys_uncached_dma32_heap), DMA_BIT_MASK(32)); + + mb(); /* make sure we only set allocate after dma_mask is set */ + system_uncached_heap_ops.allocate = system_uncached_heap_allocate; + + ddr_map_info = sip_smc_get_dram_map(); + if (ddr_map_info) { + bank_bit_first = ddr_map_info->bank_bit_first; + bank_bit_mask = ddr_map_info->bank_bit_mask; + } + + return 0; +err_dma32_pool: + for (i = 0; i < NUM_ORDERS; i++) + dmabuf_page_pool_destroy(pools[i]); + + return -ENOMEM; +} +module_init(system_heap_create); +MODULE_LICENSE("GPL v2"); From f78851187e7bea76863f1eafb3eb073f82785bae Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Wed, 14 Sep 2022 14:59:41 +0800 Subject: [PATCH 052/204] dma-buf: heaps: rk_system_heap free pages to correct pool All the pages are freed to the system heap page pools, it is a error for pages came from the dma32 heap pools. Signed-off-by: Jianqun Xu Change-Id: I96e50c6b741e6fdbee7e358b939658809059f421 --- drivers/dma-buf/heaps/rk_system_heap.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/dma-buf/heaps/rk_system_heap.c b/drivers/dma-buf/heaps/rk_system_heap.c index 9a7fc51f562c..2d29eec1a670 100644 --- a/drivers/dma-buf/heaps/rk_system_heap.c +++ b/drivers/dma-buf/heaps/rk_system_heap.c @@ -45,7 +45,7 @@ struct system_heap_buffer { int vmap_cnt; void *vaddr; struct deferred_freelist_item deferred_free; - + struct dmabuf_page_pool **pools; bool uncached; }; @@ -457,7 +457,7 @@ static void system_heap_buf_free(struct deferred_freelist_item *item, if (compound_order(page) == orders[j]) break; } - dmabuf_page_pool_free(pools[j], page); + dmabuf_page_pool_free(buffer->pools[j], page); } } sg_free_table(table); @@ -488,15 +488,13 @@ static const struct dma_buf_ops system_heap_buf_ops = { }; static struct page *system_heap_alloc_largest_available(struct dma_heap *heap, + struct dmabuf_page_pool **pool, unsigned long size, unsigned int max_order) { struct page *page; int i; - const char *name = dma_heap_get_name(heap); - struct dmabuf_page_pool **pool; - pool = strstr(name, "dma32") ? dma32_pools : pools; for (i = 0; i < NUM_ORDERS; i++) { if (size < (PAGE_SIZE << orders[i])) continue; @@ -542,6 +540,7 @@ static struct dma_buf *system_heap_do_allocate(struct dma_heap *heap, buffer->heap = heap; buffer->len = len; buffer->uncached = uncached; + buffer->pools = strstr(dma_heap_get_name(heap), "dma32") ? dma32_pools : pools; INIT_LIST_HEAD(&pages); for (i = 0; i < 8; i++) @@ -555,7 +554,9 @@ static struct dma_buf *system_heap_do_allocate(struct dma_heap *heap, if (fatal_signal_pending(current)) goto free_buffer; - page = system_heap_alloc_largest_available(heap, size_remaining, max_order); + page = system_heap_alloc_largest_available(heap, buffer->pools, + size_remaining, + max_order); if (!page) goto free_buffer; @@ -658,11 +659,8 @@ static long system_get_pool_size(struct dma_heap *heap) int i; long num_pages = 0; struct dmabuf_page_pool **pool; - const char *name = dma_heap_get_name(heap); - pool = pools; - if (!strcmp(name, "system-dma32") || !strcmp(name, "system-uncached-dma32")) - pool = dma32_pools; + pool = strstr(dma_heap_get_name(heap), "dma32") ? dma32_pools : pools; for (i = 0; i < NUM_ORDERS; i++, pool++) { num_pages += ((*pool)->count[POOL_LOWPAGE] + (*pool)->count[POOL_HIGHPAGE]) << (*pool)->order; From 11f0df3d9dd1d995b5961faeb01814453fa89c60 Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Sat, 17 Sep 2022 09:43:07 +0800 Subject: [PATCH 053/204] hwspinlock: rockchip: add compilation support make an option to compile Rockchip HW Spinlock driver. Signed-off-by: Frank Wang Change-Id: I6f51901f1787acd5ea15dcb1a0892a065b16aa98 --- drivers/hwspinlock/Kconfig | 10 ++++++++++ drivers/hwspinlock/Makefile | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig index 32cd26352f38..1760015ba302 100644 --- a/drivers/hwspinlock/Kconfig +++ b/drivers/hwspinlock/Kconfig @@ -28,6 +28,16 @@ config HWSPINLOCK_QCOM If unsure, say N. +config HWSPINLOCK_ROCKCHIP + tristate "Rockchip Hardware Spinlock device" + depends on ARCH_ROCKCHIP || COMPILE_TEST + help + Say y here to support the Rockchip Hardware Spinlock device, which + provides a synchronisation mechanism for the various processors + on the SoC. + + If unsure, say N. + config HWSPINLOCK_SIRF tristate "SIRF Hardware Spinlock device" depends on ARCH_SIRF || COMPILE_TEST diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile index ed053e3f02be..6b74ba1569a1 100644 --- a/drivers/hwspinlock/Makefile +++ b/drivers/hwspinlock/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_HWSPINLOCK) += hwspinlock_core.o obj-$(CONFIG_HWSPINLOCK_OMAP) += omap_hwspinlock.o obj-$(CONFIG_HWSPINLOCK_QCOM) += qcom_hwspinlock.o +obj-$(CONFIG_HWSPINLOCK_ROCKCHIP) += rockchip_hwspinlock.o obj-$(CONFIG_HWSPINLOCK_SIRF) += sirf_hwspinlock.o obj-$(CONFIG_HWSPINLOCK_SPRD) += sprd_hwspinlock.o obj-$(CONFIG_HWSPINLOCK_STM32) += stm32_hwspinlock.o From 776ecd8ba732d790d56902440d3a3ec58a823f69 Mon Sep 17 00:00:00 2001 From: Dingxian Wen Date: Fri, 16 Sep 2022 21:17:39 +0800 Subject: [PATCH 054/204] media: rockchip: hdmirx: modify edid configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.340M_edid:remove deep color support, config 4K50/60 YUV420 only. 2.600M_edid:remove deep color support. Signed-off-by: Dingxian Wen Change-Id: I3e11397670aa87abea6c13d606cd2fac466e989a --- .../platform/rockchip/hdmirx/rk_hdmirx.c | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index aafbf0a3df1f..5b11e43a30c2 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -273,22 +273,22 @@ static u8 edid_init_data_340M[] = { 0x00, 0x3B, 0x46, 0x1F, 0x8C, 0x3C, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xA7, - 0x02, 0x03, 0x2F, 0xF1, 0x51, 0x07, 0x16, 0x14, + 0x02, 0x03, 0x2E, 0xF1, 0x51, 0x07, 0x16, 0x14, 0x05, 0x01, 0x03, 0x12, 0x13, 0x84, 0x22, 0x1F, 0x90, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x23, 0x09, 0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0x67, 0x03, - 0x0C, 0x00, 0x30, 0x00, 0x18, 0x44, 0xE3, 0x05, - 0x03, 0x01, 0xE4, 0x0F, 0x00, 0x80, 0x01, 0x02, - 0x3A, 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40, 0x58, - 0x2C, 0x45, 0x00, 0x20, 0xC2, 0x31, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x30, 0x00, 0x00, 0x44, 0xE3, 0x05, + 0x03, 0x01, 0xE3, 0x0E, 0x60, 0x61, 0x02, 0x3A, + 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40, 0x58, 0x2C, + 0x45, 0x00, 0x20, 0xC2, 0x31, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2, }; static u8 edid_init_data_600M[] = { @@ -309,13 +309,13 @@ static u8 edid_init_data_600M[] = { 0x00, 0x3B, 0x46, 0x1F, 0x8C, 0x3C, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x39, - 0x02, 0x03, 0x21, 0xF2, 0x41, 0x61, 0x23, 0x09, - 0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0x66, 0x03, - 0x0C, 0x00, 0x30, 0x00, 0x18, 0x67, 0xD8, 0x5D, - 0xC4, 0x01, 0x78, 0xC0, 0x07, 0xE3, 0x05, 0x03, - 0x01, 0x08, 0xE8, 0x00, 0x30, 0xF2, 0x70, 0x5A, - 0x80, 0xB0, 0x58, 0x8A, 0x00, 0xC4, 0x8E, 0x21, - 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x03, 0x22, 0xF2, 0x41, 0x61, 0x23, 0x09, + 0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0x67, 0x03, + 0x0C, 0x00, 0x30, 0x00, 0x00, 0x78, 0x67, 0xD8, + 0x5D, 0xC4, 0x01, 0x78, 0xC0, 0x00, 0xE3, 0x05, + 0x03, 0x01, 0x08, 0xE8, 0x00, 0x30, 0xF2, 0x70, + 0x5A, 0x80, 0xB0, 0x58, 0x8A, 0x00, 0xC4, 0x8E, + 0x21, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -324,7 +324,7 @@ static u8 edid_init_data_600M[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, }; static char *hdmirx_color_space[8] = { From ff35acab81909a2d8c50964fcdaa6ed5e296250d Mon Sep 17 00:00:00 2001 From: Dingxian Wen Date: Fri, 16 Sep 2022 21:38:19 +0800 Subject: [PATCH 055/204] media: rockchip: hdmirx: modify some waiting time Signed-off-by: Dingxian Wen Change-Id: Id64c176ebb5d22b5ea5ab86afff3ecf735f8c254 --- .../platform/rockchip/hdmirx/rk_hdmirx.c | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index 5b11e43a30c2..1579bcdf8e38 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -68,6 +68,10 @@ MODULE_PARM_DESC(debug, "debug level (0-3)"); #define RK_IRQ_HDMIRX_HDMI 210 #define FILTER_FRAME_CNT 6 #define CPU_LIMIT_FREQ_KHZ 1200000 +#define WAIT_PHY_REG_TIME 50 +#define WAIT_TIMER_LOCK_TIME 50 +#define WAIT_SIGNAL_LOCK_TIME 600 /* if 5V present: 7ms each time */ +#define WAIT_AVI_PKT_TIME 300 #define is_validfs(x) (x == 32000 || \ x == 44100 || \ @@ -1216,13 +1220,13 @@ static int hdmirx_phy_register_read(struct rk_hdmirx_dev *hdmirx_dev, /* config read enable */ hdmirx_writel(hdmirx_dev, PHYCREG_CONTROL, PHYCREG_CR_PARA_READ_P); - for (i = 0; i < 50; i++) { + for (i = 0; i < WAIT_PHY_REG_TIME; i++) { usleep_range(200, 210); if (hdmirx_dev->cr_read_done) break; } - if (i == 50) { + if (i == WAIT_PHY_REG_TIME) { dev_err(dev, "%s wait cr read done failed!\n", __func__); return -1; } @@ -1252,13 +1256,13 @@ static int hdmirx_phy_register_write(struct rk_hdmirx_dev *hdmirx_dev, /* config write enable */ hdmirx_writel(hdmirx_dev, PHYCREG_CONTROL, PHYCREG_CR_PARA_WRITE_P); - for (i = 0; i < 50; i++) { + for (i = 0; i < WAIT_PHY_REG_TIME; i++) { usleep_range(200, 210); if (hdmirx_dev->cr_write_done) break; } - if (i == 50) { + if (i == WAIT_PHY_REG_TIME) { dev_err(dev, "%s wait cr write done failed!\n", __func__); return -1; } @@ -1346,13 +1350,13 @@ static void hdmirx_controller_init(struct rk_hdmirx_dev *hdmirx_dev) TIMER_BASE_LOCKED_IRQ, TIMER_BASE_LOCKED_IRQ); /* write irefclk freq */ hdmirx_writel(hdmirx_dev, GLOBAL_TIMER_REF_BASE, IREF_CLK_FREQ_HZ); - for (i = 0; i < 50; i++) { + for (i = 0; i < WAIT_TIMER_LOCK_TIME; i++) { usleep_range(200, 210); if (hdmirx_dev->timer_base_lock) break; } - if (i == 50) + if (i == WAIT_TIMER_LOCK_TIME) dev_err(dev, "%s wait timer base lock failed!\n", __func__); hdmirx_update_bits(hdmirx_dev, CMU_CONFIG0, @@ -1448,7 +1452,7 @@ static int hdmirx_wait_lock_and_get_timing(struct rk_hdmirx_dev *hdmirx_dev) u32 mu_status, scdc_status, dma_st10, cmu_st; struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; - for (i = 0; i < 300; i++) { + for (i = 0; i < WAIT_SIGNAL_LOCK_TIME; i++) { mu_status = hdmirx_readl(hdmirx_dev, MAINUNIT_STATUS); scdc_status = hdmirx_readl(hdmirx_dev, SCDC_REGBANK_STATUS3); dma_st10 = hdmirx_readl(hdmirx_dev, DMA_STATUS10); @@ -1467,7 +1471,7 @@ static int hdmirx_wait_lock_and_get_timing(struct rk_hdmirx_dev *hdmirx_dev) hdmirx_tmds_clk_ratio_config(hdmirx_dev); } - if (i == 300) { + if (i == WAIT_SIGNAL_LOCK_TIME) { v4l2_err(v4l2_dev, "%s signal not lock, tmds_clk_ratio:%d\n", __func__, hdmirx_dev->tmds_clk_ratio); v4l2_err(v4l2_dev, "%s mu_st:%#x, scdc_st:%#x, dma_st10:%#x\n", @@ -1484,7 +1488,7 @@ static int hdmirx_wait_lock_and_get_timing(struct rk_hdmirx_dev *hdmirx_dev) hdmirx_update_bits(hdmirx_dev, PKT_2_INT_MASK_N, PKTDEC_AVIIF_RCV_IRQ, PKTDEC_AVIIF_RCV_IRQ); - for (i = 0; i < 300; i++) { + for (i = 0; i < WAIT_AVI_PKT_TIME; i++) { usleep_range(1000, 1100); if (hdmirx_dev->avi_pkt_rcv) { v4l2_dbg(1, debug, v4l2_dev, @@ -1493,13 +1497,13 @@ static int hdmirx_wait_lock_and_get_timing(struct rk_hdmirx_dev *hdmirx_dev) } } - if (i == 300) { + if (i == WAIT_AVI_PKT_TIME) { v4l2_err(v4l2_dev, "%s wait avi_pkt_rcv failed!\n", __func__); hdmirx_update_bits(hdmirx_dev, PKT_2_INT_MASK_N, PKTDEC_AVIIF_RCV_IRQ, 0); } - usleep_range(50*1000, 50*1010); + usleep_range(200*1000, 200*1010); hdmirx_format_change(hdmirx_dev); return 0; @@ -1897,7 +1901,7 @@ static void hdmirx_stop_streaming(struct vb2_queue *queue) /* wait last irq to return the buffer */ ret = wait_event_timeout(stream->wq_stopped, stream->stopping != true, - msecs_to_jiffies(500)); + msecs_to_jiffies(50)); if (!ret) { v4l2_err(v4l2_dev, "%s wait last irq timeout, return bufs!\n", __func__); From 2a53c31cc93a8462844bcda75210c42f11126452 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Mon, 19 Sep 2022 18:31:12 +0800 Subject: [PATCH 056/204] arm64/configs: update some incompatible for rockchip_linux_defconfig CONFIG_BCMDHD_PCIE and CONFIG_BCMDHD_SDIO can only be selected from two configurations, since that bcmdhd driver cannot be compatible with it at present. That just enable the CONFIG_BCMDHD_PCIE by default on rk3588 SoCs. Also, CONFIG_MALI_CSF_SUPPORT need be enabled by default on rk3588 SoCs. Signed-off-by: Caesar Wang Change-Id: I053a704f6374cf7c43cd6dfa733d3d0d4214f256 --- arch/arm64/configs/rk3399_linux.config | 2 -- arch/arm64/configs/rk3568_linux.config | 3 --- arch/arm64/configs/rk3588_edge.config | 3 +++ arch/arm64/configs/rk3588_linux.config | 3 +++ arch/arm64/configs/rk3588_nvr.config | 1 + arch/arm64/configs/rockchip_linux_defconfig | 2 -- 6 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 arch/arm64/configs/rk3399_linux.config delete mode 100644 arch/arm64/configs/rk3568_linux.config create mode 100644 arch/arm64/configs/rk3588_linux.config diff --git a/arch/arm64/configs/rk3399_linux.config b/arch/arm64/configs/rk3399_linux.config deleted file mode 100644 index 05f35714ca12..000000000000 --- a/arch/arm64/configs/rk3399_linux.config +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_BCMDHD_SDIO=y -# CONFIG_BCMDHD_PCIE is not set diff --git a/arch/arm64/configs/rk3568_linux.config b/arch/arm64/configs/rk3568_linux.config deleted file mode 100644 index f2a23294e572..000000000000 --- a/arch/arm64/configs/rk3568_linux.config +++ /dev/null @@ -1,3 +0,0 @@ -# CONFIG_MALI_CSF_SUPPORT is not set -CONFIG_BCMDHD_SDIO=y -# CONFIG_BCMDHD_PCIE is not set diff --git a/arch/arm64/configs/rk3588_edge.config b/arch/arm64/configs/rk3588_edge.config index 1ccc4a1778d9..8b07747a6020 100644 --- a/arch/arm64/configs/rk3588_edge.config +++ b/arch/arm64/configs/rk3588_edge.config @@ -3,6 +3,9 @@ CONFIG_R8169=y CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP=y CONFIG_AP6XXX=y # CONFIG_WIFI_BUILD_MODULE is not set +# CONFIG_BCMDHD_SDIO is not set +CONFIG_BCMDHD_PCIE=y +CONFIG_MALI_CSF_SUPPORT=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_USB_CONFIGFS_RNDIS=y CONFIG_USB_CONFIGFS_F_UAC1=y diff --git a/arch/arm64/configs/rk3588_linux.config b/arch/arm64/configs/rk3588_linux.config new file mode 100644 index 000000000000..e2d30904b5f6 --- /dev/null +++ b/arch/arm64/configs/rk3588_linux.config @@ -0,0 +1,3 @@ +# CONFIG_BCMDHD_SDIO=y is not set +CONFIG_BCMDHD_PCIE=y +CONFIG_MALI_CSF_SUPPORT=y diff --git a/arch/arm64/configs/rk3588_nvr.config b/arch/arm64/configs/rk3588_nvr.config index 38b868946aee..e8356d628475 100644 --- a/arch/arm64/configs/rk3588_nvr.config +++ b/arch/arm64/configs/rk3588_nvr.config @@ -11,6 +11,7 @@ CONFIG_DRM_ITE_IT6161=y CONFIG_INPUT_MOUSEDEV=y # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_MALI400 is not set +CONFIG_MALI_CSF_SUPPORT=y # CONFIG_MALI_MIDGARD is not set # CONFIG_MEDIA_CEC_SUPPORT is not set # CONFIG_MEDIA_USB_SUPPORT is not set diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index b8b04e7792d4..051d00fbeaef 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -183,7 +183,6 @@ CONFIG_USB_RTL8152=y CONFIG_WL_ROCKCHIP=y CONFIG_WIFI_BUILD_MODULE=y CONFIG_AP6XXX=m -CONFIG_BCMDHD_PCIE=y CONFIG_INPUT_FF_MEMLESS=y CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_ADC=y @@ -328,7 +327,6 @@ CONFIG_MALI_DEBUG=y CONFIG_MALI_PWRSOFT_765=y CONFIG_MALI_BIFROST=y CONFIG_MALI_PLATFORM_NAME="rk" -CONFIG_MALI_CSF_SUPPORT=y CONFIG_MALI_BIFROST_EXPERT=y CONFIG_MALI_BIFROST_DEBUG=y CONFIG_BACKLIGHT_CLASS_DEVICE=y From f925e2b3ce24b0076cf50ddecbbce331e41da964 Mon Sep 17 00:00:00 2001 From: William Wu Date: Tue, 30 Mar 2021 11:15:03 +0800 Subject: [PATCH 057/204] usb: xhci: fix u2 bus suspend for Rockchip SNPS 3.0 xHC Rockchip SNPS xHC 3.0 set USB 2.0 PHY enter suspend mode from DWC3 core if the suspend conditions are valid (as per DWC3 controller databook 6.3.46 GUSB2PHYCFG register bit6). In this case, it needs to set the bus_suspended bit for USB 2.0, so that in xhci_bus_resume, it can set the xHC link state to XDEV_RESUME and send USB resume signal to USB 2.0 device. Test on RK3568 USB 3.0 Host interface with USB 2.0 Camera or USB 2.0 HUB which support USB auto suspend. Without this patch, the xHC fails to send USB resume signal on the USB bus to wakeup the USB 2.0 devices, and cause xHC died. Change-Id: Icb5a553d71a5f3144d77f8d5a5132892a5795285 Signed-off-by: William Wu Signed-off-by: Frank Wang --- drivers/usb/host/xhci-hub.c | 14 ++++++++++++++ drivers/usb/host/xhci-plat.c | 4 ++++ drivers/usb/host/xhci.h | 1 + 3 files changed, 19 insertions(+) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 44ed85a8da73..57c94c60cecc 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1676,7 +1676,21 @@ retry: t2 &= ~PORT_PLS_MASK; t2 |= PORT_LINK_STROBE | XDEV_U3; set_bit(port_index, &bus_state->bus_suspended); + } else if ((xhci->quirks & XHCI_U2_BROKEN_SUSPEND) && + (hcd->speed < HCD_USB3) && + (t1 & PORT_PLS_MASK) == XDEV_U3) { + /* + * Rockchip SNPS xHC 3.0 set USB 2.0 PHY enter + * suspend mode from DWC3 core if the suspend + * conditions are valid. In this case, it need + * to set the bus_suspended bit for USB 2.0, so + * that in xhci_bus_resume, it can set the xHC + * link state to XDEV_RESUME and send USB resume + * signal to USB 2.0 device. + */ + set_bit(port_index, &bus_state->bus_suspended); } + /* USB core sets remote wake mask for USB 3.0 hubs, * including the USB 3.0 roothub, but only if CONFIG_PM * is enabled, so also enable remote wake here. diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index bd62f03523f1..f76cdb306ea8 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -363,6 +363,10 @@ static int xhci_plat_probe(struct platform_device *pdev) if (device_property_read_bool(tmpdev, "quirk-skip-phy-init")) xhci->quirks |= XHCI_SKIP_PHY_INIT; + if (device_property_read_bool(tmpdev, + "xhci-u2-broken-suspend")) + xhci->quirks |= XHCI_U2_BROKEN_SUSPEND; + device_property_read_u32(tmpdev, "imod-interval-ns", &xhci->imod_interval); } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 111dc5ff3f0d..16cc027d2560 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1906,6 +1906,7 @@ struct xhci_hcd { #define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39) #define XHCI_NO_SOFT_RETRY BIT_ULL(40) #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) +#define XHCI_U2_BROKEN_SUSPEND BIT_ULL(43) unsigned int num_active_eps; unsigned int limit_active_eps; From 1f2d39df3fd763184bb9815bcd44df49d6ffcfcc Mon Sep 17 00:00:00 2001 From: William Wu Date: Tue, 30 Mar 2021 11:32:33 +0800 Subject: [PATCH 058/204] usb: dwc3: host: workaround xhci u2 broken suspend for RK356X The RK356X DWC3 supports to set the USB 2.0 PHY enter suspend mode if the DWC3 core suspend conditions are valid (as per DWC3 controller databook 6.3.46 GUSB2PHYCFG register bit6). This cause xHC driver failed to send USB resume signal to USB 2.0 device in xhci_bus_resume(). This patch adds a quirk "xhci-u2-broken-suspend" to force the xHC to set the link state to XDEV_RESUME and send USB resume signal to USB 2.0 device. Change-Id: I24c017867f80728890c0562a12e4554625913e67 Signed-off-by: William Wu Signed-off-by: Frank Wang --- drivers/usb/dwc3/host.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index e195176580de..a66f16e8816e 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -44,7 +44,7 @@ out: int dwc3_host_init(struct dwc3 *dwc) { - struct property_entry props[4]; + struct property_entry props[5]; struct platform_device *xhci; int ret, irq; struct resource *res; @@ -107,6 +107,9 @@ int dwc3_host_init(struct dwc3 *dwc) if (DWC3_VER_IS_WITHIN(DWC3, ANY, 300A)) props[prop_idx++] = PROPERTY_ENTRY_BOOL("quirk-broken-port-ped"); + if (!dwc->dis_u2_susphy_quirk) + props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-u2-broken-suspend"); + if (prop_idx) { ret = platform_device_add_properties(xhci, props); if (ret) { From 658b241460ff08273fbd04b278b2f20456e9af13 Mon Sep 17 00:00:00 2001 From: Lin Jianhua Date: Mon, 19 Sep 2022 18:01:38 +0800 Subject: [PATCH 059/204] arm64: dts: rockchip: rk3308k: fixup name of trip-point from trip-point-x to trip-point@x linux-4.4 the trip-point name is trip-point-x, but linux-5.10 the trip-point name is trip-point@x in rk3308.dtsi Signed-off-by: Lin Jianhua Change-Id: I1f484ad5081e76c18d2ab380ba2c0c13b66485e2 --- arch/arm64/boot/dts/rockchip/rk3308k.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3308k.dtsi b/arch/arm64/boot/dts/rockchip/rk3308k.dtsi index 6f9114846931..5f02591ad77b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3308k.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3308k.dtsi @@ -41,10 +41,10 @@ k_i = <0>; trips { - trip-point-0 { + trip-point@0 { temperature = <55000>; }; - trip-point-1 { + trip-point@1 { temperature = <90000>; }; }; From 0f5197b688b001f8d37bca1cbe27c622cb9c2fce Mon Sep 17 00:00:00 2001 From: Jiajian Wu Date: Thu, 1 Sep 2022 11:01:24 +0800 Subject: [PATCH 060/204] arm64: dts: rockchip: rk809 compatible to rockchip,multicodecs-card Signed-off-by: Jiajian Wu Change-Id: I72dd4bb6e7c24c364e65dfd0e70dc0b14b78bef2 --- .../boot/dts/rockchip/px30-evb-ddr3-v10.dtsi | 35 ++++++++++--------- .../boot/dts/rockchip/px30-mini-evb-v11.dtsi | 4 +-- .../dts/rockchip/rk3566-evb1-ddr4-v10.dtsi | 13 ------- .../dts/rockchip/rk3566-evb2-lp4x-v10.dtsi | 13 ------- arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi | 26 ++++++++------ .../dts/rockchip/rk3568-evb1-ddr4-v10.dtsi | 11 +++--- 6 files changed, 39 insertions(+), 63 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi index 2cd4d3a8fd76..480e76e8dc6a 100644 --- a/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-evb-ddr3-v10.dtsi @@ -96,25 +96,26 @@ status = "okay"; }; - rk809-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,name = "rockchip,rk809-codec"; - simple-audio-card,mclk-fs = <256>; - simple-audio-card,cpu { - sound-dai = <&i2s1_2ch>; - }; - simple-audio-card,codec { - sound-dai = <&rk809_codec>; - }; - }; - - rk_headset: rk-headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; + rk809_sound: rk809-sound { + status = "okay"; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip-rk809"; + hp-det-gpio = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>; + io-channels = <&saradc 1>; + io-channel-names = "adc-detect"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,cpu = <&i2s1_2ch>; + rockchip,codec = <&rk809_codec>; pinctrl-names = "default"; pinctrl-0 = <&hp_det>; - io-channels = <&saradc 1>; + play-pause-key { + label = "playpause"; + linux,code = ; + press-threshold-microvolt = <2000>; + }; }; sdio_pwrseq: sdio-pwrseq { diff --git a/arch/arm64/boot/dts/rockchip/px30-mini-evb-v11.dtsi b/arch/arm64/boot/dts/rockchip/px30-mini-evb-v11.dtsi index 2304898a94ce..ef6475ce4f73 100644 --- a/arch/arm64/boot/dts/rockchip/px30-mini-evb-v11.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-mini-evb-v11.dtsi @@ -11,8 +11,8 @@ pinctrl-0 = <&rmii_pins &mac_refclk_12ma>; }; -&rk_headset { - headset_gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_LOW>; +&rk809_sound { + hp-det-gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_LOW>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-evb1-ddr4-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-evb1-ddr4-v10.dtsi index b41db0eb5510..1ce24932257a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-evb1-ddr4-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-evb1-ddr4-v10.dtsi @@ -25,13 +25,6 @@ vin-supply = <&dc_12v>; }; - rk_headset: rk-headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio3 RK_PA1 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&hp_det>; - }; - vcc3v3_vga: vcc3v3-vga { compatible = "regulator-fixed"; regulator-name = "vcc3v3_vga"; @@ -457,12 +450,6 @@ }; }; - headphone { - hp_det: hp-det { - rockchip,pins = <3 RK_PA1 RK_FUNC_GPIO &pcfg_pull_down>; - }; - }; - lcd0 { lcd0_rst_gpio: lcd0-rst-gpio { rockchip,pins = <4 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi index 318bf46e8842..7dc4e284891b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi @@ -16,13 +16,6 @@ model = "Rockchip RK3566 EVB2 LP4X V10 Board"; compatible = "rockchip,rk3566-evb2-lp4x-v10", "rockchip,rk3566"; - rk_headset: rk-headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio3 RK_PA1 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&hp_det>; - }; - vcc_camera: vcc-camera-regulator { compatible = "regulator-fixed"; gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; @@ -442,12 +435,6 @@ }; }; - headphone { - hp_det: hp-det { - rockchip,pins = <3 RK_PA1 RK_FUNC_GPIO &pcfg_pull_down>; - }; - }; - sdio-pwrseq { wifi_enable_h: wifi-enable-h { rockchip,pins = <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi index c6e3f77abfd9..8a3dfb933b51 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi @@ -193,17 +193,15 @@ rk809_sound: rk809-sound { status = "okay"; - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,name = "rockchip,rk809-codec"; - simple-audio-card,mclk-fs = <256>; - - simple-audio-card,cpu { - sound-dai = <&i2s1_8ch>; - }; - simple-audio-card,codec { - sound-dai = <&rk809_codec 0>; - }; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip-rk809"; + hp-det-gpio = <&gpio3 RK_PA1 GPIO_ACTIVE_LOW>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,cpu = <&i2s1_8ch>; + rockchip,codec = <&rk809_codec>; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; }; spdif-sound { @@ -1452,6 +1450,12 @@ &pinctrl { + headphone { + hp_det: hp-det { + rockchip,pins = <3 RK_PA1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + mxc6655xa { mxc6655xa_irq_gpio: mxc6655xa_irq_gpio { rockchip,pins = <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi index 3860aca56a13..838c3680b0c0 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi @@ -15,13 +15,6 @@ model = "Rockchip RK3568 EVB1 DDR4 V10 Board"; compatible = "rockchip,rk3568-evb1-ddr4-v10", "rockchip,rk3568"; - rk_headset: rk-headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&hp_det>; - }; - vcc2v5_sys: vcc2v5-ddr { compatible = "regulator-fixed"; regulator-name = "vcc2v5-sys"; @@ -398,6 +391,10 @@ }; }; +&rk809_sound { + hp-det-gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>; +}; + &rkisp { status = "okay"; }; From b74f371bacf3dd49d0c49dc116770f1de09e82a6 Mon Sep 17 00:00:00 2001 From: Jiajian Wu Date: Thu, 1 Sep 2022 10:29:50 +0800 Subject: [PATCH 061/204] arm64: dts: rockchip: rk817 compatible to rockchip,multicodecs-card Signed-off-by: Jiajian Wu Change-Id: I9a257915416b17a668d2e73642bdd4ed04748c71 --- .../boot/dts/rockchip/rk3326-863-lp3-v10.dtsi | 30 ++++------------- .../boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi | 32 +++++++++--------- .../boot/dts/rockchip/rk3566-rk817-eink.dts | 20 +++++------ .../dts/rockchip/rk3566-rk817-tablet-v10.dts | 33 +++++++++---------- .../boot/dts/rockchip/rk3566-rk817-tablet.dts | 33 +++++++++---------- 5 files changed, 64 insertions(+), 84 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dtsi index d3606248dc46..c7b435a3a7c9 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3326-863-lp3-v10.dtsi @@ -83,29 +83,13 @@ }; rk817-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,name = "rockchip-rk817-codec"; - simple-audio-card,mclk-fs = <256>; - simple-audio-card,widgets = - "Microphone", "Mic Jack", - "Headphone", "Headphone Jack"; - simple-audio-card,routing = - "Mic Jack", "MICBIAS1", - "IN1P", "Mic Jack", - "Headphone Jack", "HPOL", - "Headphone Jack", "HPOR"; - simple-audio-card,cpu { - sound-dai = <&i2s1_2ch>; - }; - simple-audio-card,codec { - sound-dai = <&rk817_codec>; - }; - }; - - rk_headset: rk-headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_LOW>; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip-rk817"; + hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_LOW>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,cpu = <&i2s1_2ch>; + rockchip,codec = <&rk817_codec>; pinctrl-names = "default"; pinctrl-0 = <&hp_det>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi index 2413fe868b92..9eace0c152ef 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10.dtsi @@ -88,24 +88,24 @@ }; rk817-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,name = "rockchip,rk817-codec"; - simple-audio-card,mclk-fs = <256>; - simple-audio-card,cpu { - sound-dai = <&i2s1_2ch>; - }; - simple-audio-card,codec { - sound-dai = <&rk817_codec>; - }; - }; - - rk_headset: rk-headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_LOW>; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip-rk817"; + hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_LOW>; + io-channels = <&saradc 1>; + io-channel-names = "adc-detect"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,cpu = <&i2s1_2ch>; + rockchip,codec = <&rk817_codec>; pinctrl-names = "default"; pinctrl-0 = <&hp_det>; - io-channels = <&saradc 1>; + play-pause-key { + label = "playpause"; + linux,code = ; + press-threshold-microvolt = <2000>; + }; }; sdio_pwrseq: sdio-pwrseq { diff --git a/arch/arm64/boot/dts/rockchip/rk3566-rk817-eink.dts b/arch/arm64/boot/dts/rockchip/rk3566-rk817-eink.dts index 50412b44bb71..d491ba8ee87d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-rk817-eink.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-rk817-eink.dts @@ -75,17 +75,15 @@ }; rk817-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,name = "rockchip,rk817-codec"; - simple-audio-card,mclk-fs = <256>; - - simple-audio-card,cpu { - sound-dai = <&i2s1_8ch>; - }; - simple-audio-card,codec { - sound-dai = <&rk817_codec>; - }; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip-rk817"; + hp-det-gpio = <&gpio4 RK_PC4 GPIO_ACTIVE_LOW>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,cpu = <&i2s1_8ch>; + rockchip,codec = <&rk817_codec>; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; }; sdio_pwrseq: sdio-pwrseq { diff --git a/arch/arm64/boot/dts/rockchip/rk3566-rk817-tablet-v10.dts b/arch/arm64/boot/dts/rockchip/rk3566-rk817-tablet-v10.dts index 1d4a0484473a..4f3c935998a0 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-rk817-tablet-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-rk817-tablet-v10.dts @@ -137,25 +137,24 @@ }; rk817-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,name = "rockchip,rk817-codec"; - simple-audio-card,mclk-fs = <256>; - - simple-audio-card,cpu { - sound-dai = <&i2s1_8ch>; - }; - simple-audio-card,codec { - sound-dai = <&rk817_codec>; - }; - }; - - rk_headset: rk-headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio4 RK_PC4 GPIO_ACTIVE_LOW>; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip-rk817"; + hp-det-gpio = <&gpio4 RK_PC4 GPIO_ACTIVE_LOW>; + io-channels = <&saradc 2>; + io-channel-names = "adc-detect"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,cpu = <&i2s1_8ch>; + rockchip,codec = <&rk817_codec>; pinctrl-names = "default"; pinctrl-0 = <&hp_det>; - io-channels = <&saradc 2>; + play-pause-key { + label = "playpause"; + linux,code = ; + press-threshold-microvolt = <2000>; + }; }; sdio_pwrseq: sdio-pwrseq { diff --git a/arch/arm64/boot/dts/rockchip/rk3566-rk817-tablet.dts b/arch/arm64/boot/dts/rockchip/rk3566-rk817-tablet.dts index 40022eb6c646..9e2f59073671 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-rk817-tablet.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-rk817-tablet.dts @@ -137,25 +137,24 @@ }; rk817-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,name = "rockchip,rk817-codec"; - simple-audio-card,mclk-fs = <256>; - - simple-audio-card,cpu { - sound-dai = <&i2s1_8ch>; - }; - simple-audio-card,codec { - sound-dai = <&rk817_codec>; - }; - }; - - rk_headset: rk-headset { - compatible = "rockchip_headset"; - headset_gpio = <&gpio4 RK_PC4 GPIO_ACTIVE_LOW>; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip-rk817"; + hp-det-gpio = <&gpio4 RK_PC4 GPIO_ACTIVE_LOW>; + io-channels = <&saradc 2>; + io-channel-names = "adc-detect"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,cpu = <&i2s1_8ch>; + rockchip,codec = <&rk817_codec>; pinctrl-names = "default"; pinctrl-0 = <&hp_det>; - io-channels = <&saradc 2>; + play-pause-key { + label = "playpause"; + linux,code = ; + press-threshold-microvolt = <2000>; + }; }; sdio_pwrseq: sdio-pwrseq { From cc4a2d2f9b89852df8fa7fc2f00cb54deb1e1022 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Mon, 19 Sep 2022 09:32:47 +0800 Subject: [PATCH 062/204] drm/rockchip: vop2: set splice_mode flag in loader_protect Signed-off-by: Damon Ding Change-Id: I513a133e6471f0e758b161fa67f5be5fdfaa1528 --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 1c04095424fe..b02b2cce89e9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -5194,6 +5194,7 @@ static void vop2_crtc_disable_line_flag_event(struct drm_crtc *crtc) static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on) { struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); struct vop2 *vop2 = vp->vop2; struct rockchip_drm_private *private = crtc->dev->dev_private; const struct vop2_video_port_data *vp_data = &vop2->data->vp[vp->id]; @@ -5224,6 +5225,7 @@ static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on) crtc_state = drm_atomic_get_crtc_state(crtc->state->state, crtc); mode = &crtc_state->adjusted_mode; if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { + vcstate->splice_mode = true; splice_win = vop2_find_win_by_phys_id(vop2, win->splice_win_id); splice_win->splice_mode_right = true; From 30791c5555220a1789bfe2016ef627ca0a416567 Mon Sep 17 00:00:00 2001 From: Jianlong Wang Date: Fri, 17 Jun 2022 09:35:18 +0800 Subject: [PATCH 063/204] arm64: configs: delete rk3326_linux_defconfig add rk3326_linux.config&rk3358_linux.config update by: make ARCH=arm64 px30_linux_defconfig cp .config px30_linux.config make ARCH=arm64 px30_linux_defconfig rk3326_linux.config make ARCH=arm64 menuconfig scripts/diffconfig -m px30_linux.config .config > arch/arm64/configs/rk3326_linux.config make ARCH=arm64 px30_linux_defconfig rk3358_linux.config make ARCH=arm64 menuconfig scripts/diffconfig -m px30_linux.config .config > arch/arm64/configs/rk3358_linux.config Signed-off-by: Jianlong Wang Change-Id: I9404022b222f1e64c301111f5f944cf98d1abebb --- arch/arm64/configs/rk3326_linux.config | 8 + arch/arm64/configs/rk3326_linux_defconfig | 480 ---------------------- arch/arm64/configs/rk3358_linux.config | 2 + 3 files changed, 10 insertions(+), 480 deletions(-) create mode 100644 arch/arm64/configs/rk3326_linux.config delete mode 100644 arch/arm64/configs/rk3326_linux_defconfig create mode 100644 arch/arm64/configs/rk3358_linux.config diff --git a/arch/arm64/configs/rk3326_linux.config b/arch/arm64/configs/rk3326_linux.config new file mode 100644 index 000000000000..3d913bcc63c7 --- /dev/null +++ b/arch/arm64/configs/rk3326_linux.config @@ -0,0 +1,8 @@ +# CONFIG_ETHERNET is not set +CONFIG_MD=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_RAM=y +CONFIG_SND_SOC_ROCKCHIP_PDM=y +CONFIG_VIDEO_ROCKCHIP_CIF=y +CONFIG_VIDEO_GC2155=y diff --git a/arch/arm64/configs/rk3326_linux_defconfig b/arch/arm64/configs/rk3326_linux_defconfig deleted file mode 100644 index 3b5854cc9d15..000000000000 --- a/arch/arm64/configs/rk3326_linux_defconfig +++ /dev/null @@ -1,480 +0,0 @@ -CONFIG_DEFAULT_HOSTNAME="localhost" -CONFIG_SYSVIPC=y -CONFIG_FHANDLE=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_LOG_BUF_SHIFT=18 -CONFIG_CGROUPS=y -CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_DEVICE=y -CONFIG_CPUSETS=y -CONFIG_CGROUP_CPUACCT=y -CONFIG_CGROUP_SCHED=y -CONFIG_CFS_BANDWIDTH=y -CONFIG_NAMESPACES=y -CONFIG_USER_NS=y -CONFIG_DEFAULT_USE_ENERGY_AWARE=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_EMBEDDED=y -# CONFIG_COMPAT_BRK is not set -CONFIG_PROFILING=y -CONFIG_MODULES=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_PARTITION_ADVANCED=y -CONFIG_ARCH_ROCKCHIP=y -CONFIG_PCI=y -CONFIG_PCI_MSI=y -CONFIG_PCIEPORTBUS=y -CONFIG_PCIEASPM_POWERSAVE=y -# CONFIG_ARM64_ERRATUM_826319 is not set -# CONFIG_ARM64_ERRATUM_827319 is not set -# CONFIG_ARM64_ERRATUM_824069 is not set -# CONFIG_ARM64_ERRATUM_819472 is not set -# CONFIG_ARM64_ERRATUM_832075 is not set -# CONFIG_CAVIUM_ERRATUM_22375 is not set -# CONFIG_CAVIUM_ERRATUM_23154 is not set -CONFIG_SCHED_MC=y -CONFIG_NR_CPUS=8 -CONFIG_PREEMPT_VOLUNTARY=y -CONFIG_HZ_1000=y -# CONFIG_COMPACTION is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 -CONFIG_ZSMALLOC=y -CONFIG_SECCOMP=y -CONFIG_ARMV8_DEPRECATED=y -CONFIG_SWP_EMULATION=y -CONFIG_CP15_BARRIER_EMULATION=y -CONFIG_SETEND_EMULATION=y -# CONFIG_EFI is not set -CONFIG_COMPAT=y -CONFIG_PM_DEBUG=y -CONFIG_PM_ADVANCED_DEBUG=y -CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y -CONFIG_CPU_IDLE=y -CONFIG_ARM_CPUIDLE=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPUFREQ_DT=y -CONFIG_ARM_ROCKCHIP_CPUFREQ=y -CONFIG_ARM_SCMI_PROTOCOL=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MROUTE=y -CONFIG_SYN_COOKIES=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET6_XFRM_MODE_TUNNEL is not set -# CONFIG_INET6_XFRM_MODE_BEET is not set -# CONFIG_IPV6_SIT is not set -# CONFIG_ANDROID_PARANOID_NETWORK is not set -CONFIG_BT=y -CONFIG_BT_RFCOMM=y -CONFIG_BT_HIDP=y -CONFIG_BT_HCIBTUSB=y -CONFIG_BT_HCIUART=y -CONFIG_BT_HCIUART_ATH3K=y -CONFIG_BT_HCIUART_LL=y -CONFIG_BT_HCIBFUSB=y -CONFIG_BT_HCIVHCI=y -CONFIG_BT_MRVL=y -CONFIG_BT_MRVL_SDIO=y -CONFIG_NL80211_TESTMODE=y -CONFIG_CFG80211_DEBUGFS=y -CONFIG_CFG80211_WEXT=y -CONFIG_MAC80211_LEDS=y -CONFIG_MAC80211_DEBUGFS=y -CONFIG_MAC80211_DEBUG_MENU=y -CONFIG_MAC80211_VERBOSE_DEBUG=y -CONFIG_RFKILL=y -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_DTC_SYMBOLS=y -CONFIG_DEBUG_DEVRES=y -CONFIG_CONNECTOR=y -CONFIG_ZRAM=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=1 -CONFIG_BLK_DEV_NVME=y -CONFIG_ROCKCHIP_SCR=y -CONFIG_SRAM=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_DEV_SR=y -CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_SCSI_SPI_ATTRS=y -CONFIG_MD=y -CONFIG_NETDEVICES=y -# CONFIG_ETHERNET is not set -CONFIG_ROCKCHIP_PHY=y -CONFIG_USB_RTL8150=y -CONFIG_USB_RTL8152=y -CONFIG_USB_NET_CDC_MBIM=y -# CONFIG_USB_NET_NET1080 is not set -# CONFIG_USB_NET_CDC_SUBSET is not set -# CONFIG_USB_NET_ZAURUS is not set -CONFIG_LIBERTAS_THINFIRM=y -CONFIG_USB_NET_RNDIS_WLAN=y -CONFIG_WL_ROCKCHIP=y -CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP=y -CONFIG_AP6XXX=y -CONFIG_RTL8188EU=y -CONFIG_MWIFIEX=y -CONFIG_MWIFIEX_SDIO=y -CONFIG_INPUT_FF_MEMLESS=y -# CONFIG_INPUT_MOUSEDEV is not set -CONFIG_INPUT_EVDEV=y -CONFIG_KEYBOARD_ADC=y -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=y -CONFIG_KEYBOARD_GPIO_POLLED=y -CONFIG_KEYBOARD_ROCKCHIP=y -CONFIG_KEYBOARD_CROS_EC=y -# CONFIG_MOUSE_PS2 is not set -CONFIG_MOUSE_CYAPA=y -CONFIG_MOUSE_ELAN_I2C=y -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_ATMEL_MXT=y -CONFIG_TOUCHSCREEN_GSLX680_VR=y -CONFIG_TOUCHSCREEN_GSL3673=y -CONFIG_TOUCHSCREEN_GT9XX=y -CONFIG_TOUCHSCREEN_ELAN=y -CONFIG_TOUCHSCREEN_USB_COMPOSITE=y -CONFIG_TOUCHSCREEN_GT1X=y -CONFIG_ROCKCHIP_REMOTECTL=y -CONFIG_ROCKCHIP_REMOTECTL_PWM=y -CONFIG_INPUT_MISC=y -CONFIG_INPUT_RK8XX_PWRKEY=y -CONFIG_INPUT_UINPUT=y -CONFIG_INPUT_GPIO=y -# CONFIG_SERIO is not set -CONFIG_DEVPTS_MULTIPLE_INSTANCES=y -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_PCI is not set -CONFIG_SERIAL_8250_NR_UARTS=5 -CONFIG_SERIAL_8250_RUNTIME_UARTS=5 -CONFIG_SERIAL_8250_DW=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_HW_RANDOM=y -CONFIG_TCG_TPM=y -CONFIG_TCG_TIS_I2C_INFINEON=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_MUX=y -CONFIG_I2C_RK3X=y -CONFIG_I2C_CROS_EC_TUNNEL=y -CONFIG_SPI=y -CONFIG_SPI_BITBANG=y -CONFIG_SPI_ROCKCHIP=y -CONFIG_SPI_SPIDEV=y -CONFIG_PTP_1588_CLOCK=y -CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_RK8XX=y -CONFIG_BATTERY_SBS=y -CONFIG_CHARGER_GPIO=y -CONFIG_CHARGER_BQ24735=y -CONFIG_BATTERY_RK817=y -CONFIG_CHARGER_RK817=y -CONFIG_POWER_RESET_GPIO=y -CONFIG_POWER_RESET_GPIO_RESTART=y -CONFIG_SYSCON_REBOOT_MODE=y -CONFIG_POWER_AVS=y -CONFIG_ROCKCHIP_IODOMAIN=y -CONFIG_THERMAL=y -CONFIG_THERMAL_WRITABLE_TRIPS=y -CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR=y -CONFIG_THERMAL_GOV_FAIR_SHARE=y -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_CPU_THERMAL=y -CONFIG_DEVFREQ_THERMAL=y -CONFIG_ROCKCHIP_THERMAL=y -CONFIG_WATCHDOG=y -CONFIG_DW_WATCHDOG=y -CONFIG_MFD_CROS_EC=y -CONFIG_MFD_CROS_EC_SPI=y -CONFIG_MFD_RK808=y -CONFIG_MFD_TPS6586X=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_DEBUG=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_ACT8865=y -CONFIG_REGULATOR_FAN53555=y -CONFIG_REGULATOR_GPIO=y -CONFIG_REGULATOR_LP8752=y -CONFIG_REGULATOR_MP8865=y -CONFIG_REGULATOR_PWM=y -CONFIG_REGULATOR_RK808=y -CONFIG_REGULATOR_RK818=y -CONFIG_REGULATOR_TPS6586X=y -CONFIG_REGULATOR_XZ3216=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_MEDIA_RC_SUPPORT=y -CONFIG_MEDIA_CONTROLLER=y -CONFIG_VIDEO_V4L2_SUBDEV_API=y -# CONFIG_IR_RC5_DECODER is not set -# CONFIG_IR_RC6_DECODER is not set -# CONFIG_IR_JVC_DECODER is not set -# CONFIG_IR_SONY_DECODER is not set -# CONFIG_IR_SANYO_DECODER is not set -# CONFIG_IR_SHARP_DECODER is not set -# CONFIG_IR_MCE_KBD_DECODER is not set -# CONFIG_IR_XMP_DECODER is not set -CONFIG_MEDIA_USB_SUPPORT=y -CONFIG_USB_VIDEO_CLASS=y -# CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV is not set -# CONFIG_USB_GSPCA is not set -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_SOC_CAMERA=y -CONFIG_VIDEO_ROCKCHIP_CIF=y -CONFIG_VIDEO_ROCKCHIP_ISP1=y -CONFIG_V4L_MEM2MEM_DRIVERS=y -CONFIG_VIDEO_ROCKCHIP_RGA=y -# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -# CONFIG_VIDEO_IR_I2C is not set -CONFIG_VIDEO_OV5695=y -CONFIG_VIDEO_GC2155=y -# CONFIG_DVB_AU8522_V4L is not set -# CONFIG_DVB_TUNER_DIB0070 is not set -# CONFIG_DVB_TUNER_DIB0090 is not set -# CONFIG_VGA_ARB is not set -CONFIG_DRM=y -CONFIG_DRM_LOAD_EDID_FIRMWARE=y -CONFIG_DRM_DMA_SYNC=y -CONFIG_DRM_ROCKCHIP=y -CONFIG_ROCKCHIP_DW_MIPI_DSI=y -CONFIG_ROCKCHIP_ANALOGIX_DP=y -CONFIG_ROCKCHIP_LVDS=y -CONFIG_ROCKCHIP_DRM_TVE=y -CONFIG_DRM_PANEL_SIMPLE=y -CONFIG_MALI_PWRSOFT_765=y -CONFIG_MALI_BIFROST=y -CONFIG_MALI_BIFROST_DEVFREQ=y -CONFIG_MALI_PLATFORM_NAME="rk" -CONFIG_MALI_BIFROST_EXPERT=y -CONFIG_MALI_BIFROST_DEBUG=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y -# CONFIG_LCD_CLASS_DEVICE is not set -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_PWM=y -CONFIG_RK_VCODEC=y -CONFIG_ROCKCHIP_MPP_SERVICE=y -CONFIG_ROCKCHIP_MPP_DEVICE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_SEQUENCER=y -CONFIG_SND_SEQ_DUMMY=y -CONFIG_SND_HRTIMER=y -CONFIG_SND_DYNAMIC_MINORS=y -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_PROC_FS is not set -# CONFIG_SND_PCI is not set -# CONFIG_SND_SPI is not set -CONFIG_SND_USB_AUDIO=y -CONFIG_SND_SOC=y -CONFIG_SND_SOC_ROCKCHIP=y -CONFIG_SND_SOC_ROCKCHIP_SPDIF=y -CONFIG_SND_SOC_ROCKCHIP_MAX98090=y -CONFIG_SND_SOC_ROCKCHIP_RT5645=y -CONFIG_SND_SOC_ES8316=y -CONFIG_SND_SOC_RK817=y -CONFIG_SND_SOC_RT5616=y -CONFIG_SND_SOC_RT5640=y -CONFIG_SND_SOC_RT5651=y -CONFIG_SND_SOC_SPDIF=y -CONFIG_SND_SIMPLE_CARD=y -CONFIG_HID_BATTERY_STRENGTH=y -CONFIG_HIDRAW=y -CONFIG_UHID=y -CONFIG_HID_KENSINGTON=y -CONFIG_HID_MULTITOUCH=y -CONFIG_USB_HIDDEV=y -CONFIG_I2C_HID=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -# CONFIG_USB_DEFAULT_PERSIST is not set -CONFIG_USB_OTG=y -CONFIG_USB_MON=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_ROOT_HUB_TT=y -CONFIG_USB_EHCI_HCD_PLATFORM=y -CONFIG_USB_OHCI_HCD=y -# CONFIG_USB_OHCI_HCD_PCI is not set -CONFIG_USB_OHCI_HCD_PLATFORM=y -CONFIG_USB_ACM=y -CONFIG_USB_STORAGE=y -CONFIG_USB_UAS=y -CONFIG_USB_DWC2=y -CONFIG_USB_SERIAL=y -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_CP210X=y -CONFIG_USB_SERIAL_FTDI_SIO=y -CONFIG_USB_SERIAL_KEYSPAN=y -CONFIG_USB_SERIAL_PL2303=y -CONFIG_USB_SERIAL_OTI6858=y -CONFIG_USB_SERIAL_QUALCOMM=y -CONFIG_USB_SERIAL_SIERRAWIRELESS=y -CONFIG_USB_SERIAL_OPTION=y -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_DEBUG_FILES=y -CONFIG_USB_GADGET_VBUS_DRAW=500 -CONFIG_USB_CONFIGFS=y -CONFIG_USB_CONFIGFS_ACM=y -CONFIG_USB_CONFIGFS_MASS_STORAGE=y -CONFIG_USB_CONFIGFS_F_FS=y -CONFIG_USB_CONFIGFS_UEVENT=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK_MINORS=32 -CONFIG_MMC_TEST=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMC_SDHCI_OF_ARASAN=y -CONFIG_MMC_DW=y -CONFIG_MMC_DW_ROCKCHIP=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_IS31FL32XX=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_HYM8563=y -CONFIG_RTC_DRV_RK808=y -CONFIG_DMADEVICES=y -CONFIG_PL330_DMA=y -CONFIG_STAGING=y -CONFIG_SENSORS_ISL29018=y -CONFIG_TSL2583=y -# CONFIG_ANDROID_TIMED_OUTPUT is not set -CONFIG_FIQ_DEBUGGER=y -CONFIG_FIQ_DEBUGGER_NO_SLEEP=y -CONFIG_FIQ_DEBUGGER_CONSOLE=y -CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE=y -CONFIG_COMMON_CLK_RK808=y -CONFIG_COMMON_CLK_SCMI=y -CONFIG_MAILBOX=y -CONFIG_ROCKCHIP_IOMMU=y -CONFIG_CPU_PX30=y -CONFIG_ROCKCHIP_CPUINFO=y -CONFIG_ROCKCHIP_GRF=y -CONFIG_ROCKCHIP_IPA=y -CONFIG_ROCKCHIP_OPP=y -CONFIG_ROCKCHIP_PM_DOMAINS=y -CONFIG_ROCKCHIP_PVTM=y -CONFIG_ROCKCHIP_SUSPEND_MODE=y -CONFIG_ROCKCHIP_SYSTEM_MONITOR=y -CONFIG_PM_DEVFREQ=y -CONFIG_DEVFREQ_GOV_PERFORMANCE=y -CONFIG_DEVFREQ_GOV_POWERSAVE=y -CONFIG_DEVFREQ_GOV_USERSPACE=y -CONFIG_ARM_ROCKCHIP_BUS_DEVFREQ=y -CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=y -CONFIG_PM_DEVFREQ_EVENT=y -CONFIG_MEMORY=y -CONFIG_IIO=y -CONFIG_IIO_BUFFER=y -CONFIG_IIO_KFIFO_BUF=y -CONFIG_IIO_TRIGGER=y -CONFIG_ROCKCHIP_SARADC=y -CONFIG_SENSORS_TSL2563=y -CONFIG_IIO_SYSFS_TRIGGER=y -CONFIG_PWM=y -CONFIG_PWM_ROCKCHIP=y -CONFIG_PHY_ROCKCHIP_USB=y -CONFIG_PHY_ROCKCHIP_INNO_USB2=y -CONFIG_PHY_ROCKCHIP_EMMC=y -CONFIG_PHY_ROCKCHIP_DP=y -CONFIG_PHY_ROCKCHIP_INNO_VIDEO_COMBO_PHY=y -CONFIG_ANDROID=y -CONFIG_NVMEM=y -CONFIG_ROCKCHIP_OTP=y -CONFIG_ROCKCHIP_SIP=y -# CONFIG_ACPI is not set -CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_POSIX_ACL=y -CONFIG_EXT4_FS_SECURITY=y -CONFIG_XFS_FS=y -# CONFIG_DNOTIFY is not set -CONFIG_FUSE_FS=y -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=936 -CONFIG_FAT_DEFAULT_IOCHARSET="utf8" -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_SQUASHFS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -CONFIG_NFS_SWAP=y -CONFIG_NLS_DEFAULT="utf8" -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_CODEPAGE_936=y -CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NLS_UTF8=y -CONFIG_PRINTK_TIME=y -CONFIG_DYNAMIC_DEBUG=y -CONFIG_DEBUG_INFO=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0 -CONFIG_LOCKUP_DETECTOR=y -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y -CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y -CONFIG_SCHEDSTATS=y -CONFIG_TIMER_STATS=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_CREDENTIALS=y -CONFIG_RCU_CPU_STALL_TIMEOUT=60 -CONFIG_FUNCTION_TRACER=y -CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_LKDTM=y -CONFIG_STRICT_DEVMEM=y -CONFIG_DEBUG_SET_MODULE_RONX=y -# CONFIG_CRYPTO_ECHAINIV is not set -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_ANSI_CPRNG=y -CONFIG_CRYPTO_USER_API_HASH=y -CONFIG_CRYPTO_USER_API_SKCIPHER=y -CONFIG_ASYMMETRIC_KEY_TYPE=y -CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y -CONFIG_X509_CERTIFICATE_PARSER=y -CONFIG_PKCS7_MESSAGE_PARSER=y -CONFIG_SYSTEM_TRUSTED_KEYRING=y -CONFIG_ARM64_CRYPTO=y -CONFIG_CRYPTO_SHA1_ARM64_CE=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y -CONFIG_CRC_CCITT=y -CONFIG_CRC_T10DIF=y -CONFIG_CRC7=y -# CONFIG_XZ_DEC_X86 is not set -# CONFIG_XZ_DEC_POWERPC is not set -# CONFIG_XZ_DEC_IA64 is not set -# CONFIG_XZ_DEC_SPARC is not set diff --git a/arch/arm64/configs/rk3358_linux.config b/arch/arm64/configs/rk3358_linux.config new file mode 100644 index 000000000000..4be7a7cfe0ac --- /dev/null +++ b/arch/arm64/configs/rk3358_linux.config @@ -0,0 +1,2 @@ +CONFIG_LTE=y +CONFIG_LTE_RM310=y From 4e52a0886b883279891906cb4ee07ec1412d02ef Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Sat, 17 Sep 2022 17:14:13 +0800 Subject: [PATCH 064/204] arm64: dts: rockchip: enable route_edp node for rk3568 evb1 Signed-off-by: Caesar Wang Change-Id: Ie451bebc62e23d929bd2982281c277630685d083 --- arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi index 838c3680b0c0..7ef900001f51 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi @@ -422,6 +422,11 @@ connect = <&vp1_out_dsi0>; }; +&route_edp { + status = "okay"; + connect = <&vp0_out_edp>; +}; + &sata2 { status = "okay"; }; From 760e1d61b30d3050e50e93c72a464b51f97c9012 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 30 Aug 2022 14:42:53 +0800 Subject: [PATCH 065/204] media: rockchip: vicap move s_power out of start/stop stream when switching resolutions, the switching speed can be improved Signed-off-by: Zefa Chen Change-Id: I4b31894274dc3238675ece907ba1682d965e71bf --- drivers/media/platform/rockchip/cif/capture.c | 63 ++++++++----------- .../media/platform/rockchip/cif/subdev-itf.c | 8 ++- 2 files changed, 32 insertions(+), 39 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 61cd50d2c259..5e33907697c4 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -3988,18 +3988,6 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, ret = dev->pipe.close(&dev->pipe); if (ret < 0) v4l2_err(v4l2_dev, "pipeline close failed error:%d\n", ret); - pm_runtime_put_sync(dev->dev); - v4l2_pipeline_pm_put(&node->vdev.entity); - if (dev->sditf_cnt > 1) { - for (i = 0; i < dev->sditf_cnt; i++) - ret |= v4l2_subdev_call(dev->sditf[i]->sensor_sd, - core, - s_power, - 0); - if (ret < 0) - v4l2_err(v4l2_dev, "set power off fail, ret %d\n", - ret); - } if (dev->hdr.hdr_mode == HDR_X2) { if (dev->stream[RKCIF_STREAM_MIPI_ID0].state == RKCIF_STATE_READY && dev->stream[RKCIF_STREAM_MIPI_ID1].state == RKCIF_STATE_READY) { @@ -4949,7 +4937,6 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode) struct rkmodule_hdr_cfg hdr_cfg; int rkmodule_stream_seq = RKMODULE_START_STREAM_DEFAULT; int ret; - int i = 0; v4l2_info(&dev->v4l2_dev, "stream[%d] start streaming\n", stream->id); @@ -5018,29 +5005,6 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode) } if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) { - /* enable clocks/power-domains */ - ret = pm_runtime_resume_and_get(dev->dev); - if (ret < 0) { - v4l2_err(v4l2_dev, "Failed to get runtime pm, %d\n", - ret); - goto destroy_buf; - } - ret = v4l2_pipeline_pm_get(&node->vdev.entity); - if (ret < 0) { - v4l2_err(v4l2_dev, "cif pipeline_pm_get fail %d\n", - ret); - goto destroy_buf; - } - if (dev->sditf_cnt > 1) { - for (i = 0; i < dev->sditf_cnt; i++) - ret |= v4l2_subdev_call(dev->sditf[i]->sensor_sd, - core, - s_power, - 1); - if (ret < 0) - v4l2_err(v4l2_dev, "set power on fail, ret %d\n", - ret); - } ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true); if (ret < 0) { v4l2_err(v4l2_dev, "open cif pipeline failed %d\n", @@ -5438,6 +5402,7 @@ static int rkcif_fh_open(struct file *filp) struct rkcif_stream *stream = to_rkcif_stream(vnode); struct rkcif_device *cifdev = stream->cifdev; int ret; + int i = 0; ret = rkcif_attach_hw(cifdev); if (ret) @@ -5466,7 +5431,18 @@ static int rkcif_fh_open(struct file *filp) if (ret < 0) vb2_fop_release(filp); } - + if (cifdev->sditf_cnt > 1) { + for (i = 0; i < cifdev->sditf_cnt; i++) { + if (cifdev->sditf[i]->sensor_sd) + ret |= v4l2_subdev_call(cifdev->sditf[i]->sensor_sd, + core, + s_power, + 1); + } + if (ret < 0) + v4l2_err(vdev, "set sensor power on fail, ret %d\n", + ret); + } return ret; } @@ -5477,12 +5453,25 @@ static int rkcif_fh_release(struct file *filp) struct rkcif_stream *stream = to_rkcif_stream(vnode); struct rkcif_device *cifdev = stream->cifdev; int ret = 0; + int i = 0; ret = vb2_fop_release(filp); if (!ret) v4l2_pipeline_pm_put(&vnode->vdev.entity); pm_runtime_put_sync(cifdev->dev); + if (cifdev->sditf_cnt > 1) { + for (i = 0; i < cifdev->sditf_cnt; i++) { + if (cifdev->sditf[i]->sensor_sd) + ret |= v4l2_subdev_call(cifdev->sditf[i]->sensor_sd, + core, + s_power, + 0); + } + if (ret < 0) + v4l2_err(vdev, "set sensor power on fail, ret %d\n", + ret); + } return ret; } diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 7075a19b70d4..0d192ee18caa 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -622,6 +622,7 @@ static int sditf_s_power(struct v4l2_subdev *sd, int on) { struct sditf_priv *priv = to_sditf_priv(sd); struct rkcif_device *cif_dev = priv->cif_dev; + struct rkcif_vdev_node *node = &cif_dev->stream[0].vnode; int ret = 0; if (!on && atomic_dec_return(&priv->power_cnt)) @@ -634,10 +635,13 @@ static int sditf_s_power(struct v4l2_subdev *sd, int on) v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "%s, toisp mode %d, hdr %d, set power %d\n", __func__, priv->toisp_inf.link_mode, priv->hdr_cfg.hdr_mode, on); - if (on) + if (on) { ret = pm_runtime_resume_and_get(cif_dev->dev); - else + ret |= v4l2_pipeline_pm_get(&node->vdev.entity); + } else { + v4l2_pipeline_pm_put(&node->vdev.entity); pm_runtime_put_sync(cif_dev->dev); + } } return ret; } From 89364d5b3f57e19fadc182f8f22178b9fbf6f0ad Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 30 Aug 2022 15:34:13 +0800 Subject: [PATCH 066/204] media: rockchip: vicap stop stream immediately, when in vblank Signed-off-by: Zefa Chen Change-Id: I5ea4a0f48d970874447da7fbd02f5c0eaca8db83 --- drivers/media/platform/rockchip/cif/capture.c | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 5e33907697c4..9bddfb0f9d5a 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -3917,6 +3917,10 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, bool can_reset = true; int i; unsigned long flags; + u32 vblank = 0; + u32 vblank_ns = 0; + u64 cur_time = 0; + u64 fe_time = 0; mutex_lock(&dev->stream_lock); @@ -3925,13 +3929,25 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, if (mode == stream->cur_stream_mode) { stream->stopping = true; - - ret = wait_event_timeout(stream->wq_stopped, - stream->state != RKCIF_STATE_STREAMING, - msecs_to_jiffies(1000)); - if (!ret) { + if (!dev->sensor_linetime) + dev->sensor_linetime = rkcif_get_linetime(stream); + vblank = rkcif_get_sensor_vblank(dev); + vblank_ns = vblank * dev->sensor_linetime; + spin_lock_irqsave(&stream->fps_lock, flags); + fe_time = stream->readout.fe_timestamp; + spin_unlock_irqrestore(&stream->fps_lock, flags); + cur_time = ktime_get_ns(); + if (cur_time > fe_time && cur_time - fe_time < (vblank_ns - 200000)) { rkcif_stream_stop(stream); stream->stopping = false; + } else { + ret = wait_event_timeout(stream->wq_stopped, + stream->state != RKCIF_STATE_STREAMING, + msecs_to_jiffies(1000)); + if (!ret) { + rkcif_stream_stop(stream); + stream->stopping = false; + } } media_pipeline_stop(&node->vdev.entity); @@ -7477,6 +7493,12 @@ static void rkcif_deal_readout_time(struct rkcif_stream *stream) spin_lock_irqsave(&stream->fps_lock, flags); stream->readout.fe_timestamp = ktime_get_ns(); + + if (cif_dev->inf_id == RKCIF_DVP) { + spin_unlock_irqrestore(&stream->fps_lock, flags); + return; + } + if (stream->id == RKCIF_STREAM_MIPI_ID0) detect_stream->readout.readout_time = stream->readout.fe_timestamp - stream->readout.fs_timestamp; @@ -7527,8 +7549,7 @@ static void rkcif_update_stream(struct rkcif_device *cif_dev, spin_unlock_irqrestore(&stream->fps_lock, flags); } - if (cif_dev->inf_id == RKCIF_MIPI_LVDS) - rkcif_deal_readout_time(stream); + rkcif_deal_readout_time(stream); if (!stream->is_line_wake_up) { ret = rkcif_assign_new_buffer_pingpong(stream, From d2df348f0cd4bade0076ed7add727fd81d526e70 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Mon, 19 Sep 2022 11:56:47 +0800 Subject: [PATCH 067/204] video: rockchip: rga3: fbc output forced to sparse mode Signed-off-by: Yu Qiaowei Change-Id: I08da18596ec9a8d0b59f5d4f41faffb182ed315a --- drivers/video/rockchip/rga3/rga3_reg_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/rockchip/rga3/rga3_reg_info.c b/drivers/video/rockchip/rga3/rga3_reg_info.c index 85925a051a85..e065b820ca92 100644 --- a/drivers/video/rockchip/rga3/rga3_reg_info.c +++ b/drivers/video/rockchip/rga3/rga3_reg_info.c @@ -914,7 +914,7 @@ static void RGA3_set_reg_wr_info(u8 *base, struct rga3_req *msg) (s_RGA3_WR_CTRL_SW_WR_FORMAT(wr_interleaved))); reg = ((reg & (~m_RGA3_WR_CTRL_SW_WR_FBCE_SPARSE_EN)) | - (s_RGA3_WR_CTRL_SW_WR_FBCE_SPARSE_EN(0))); + (s_RGA3_WR_CTRL_SW_WR_FBCE_SPARSE_EN(1))); reg = ((reg & (~m_RGA3_WR_CTRL_SW_OUTSTANDING_MAX)) | From cae65d78f0f440c12703abd102056806f3a2b59c Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Fri, 8 Jul 2022 19:11:23 +0800 Subject: [PATCH 068/204] ASoC: rockchip: i2s-tdm: Add support for FIFO-XRUN detection This is useful for performance debug, throwing a WARNNING if FIFO-XRUN detected and then do snd_pcm_stop_xrun to stop stream and notify user XRUN state. TESTCASE: On the 192K-8CH-32BIT situation, FIFO full time is 83us (16 / 192000). Considering WATERLEVEL-16: 41.6us, WATERLEVEL-24: 62.5us. if any path (I2S<->DMA<->BUS<->DDR) blocked over this duration, FIFO xrun raised. This testcase injects a DMC-DVFS (> 80us) to reproduce FIFO-XRUN. Suggested to disable DMC-DVFS or switch to DMC-DVFS-SCENE policy to fix this on this situation. OTOH, optimizing DMC-DVFS (<40us) or place audio buffer into SRAM is also an alternative. x.sh: /#!/bin/sh echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor echo performance > /sys/devices/system/cpu/cpufreq/policy4/scaling_governor echo performance > /sys/devices/system/cpu/cpufreq/policy6/scaling_governor freqs=`cat /sys/devices/platform/dmc/devfreq/dmc/available_frequencies` echo "userspace" > /sys/devices/platform/dmc/devfreq/dmc/governor aplay -D hw:3,0 --period-size=1024 --buffer-size=4096 -r 192000 -c 8 \ -f s32_le /dev/zero & arecord -D hw:1,0 --period-size=1024 --buffer-size=4096 -r 192000 -c 8 \ -f s32_le /dev/zero & sleep 1 for f in $freqs do echo "dmc: set_freq $f" echo $f > /sys/devices/platform/dmc/devfreq/dmc/userspace/set_freq sleep 1 done killall aplay killall arecord Result: root@RK3588:/data# ./x.sh Playing raw data '/dev/zero' : Signed 32 bit Little Endian, Rate 192000 Hz, Channels 8 Recording WAVE '/dev/zero' : Signed 32 bit Little Endian, Rate 192000 Hz, Channels 8 dmc: set_freq 528000000 [ 69.222572] rockchip-i2s-tdm fddf0000.i2s: TX FIFO Underrun [ 69.222615] rockchip-i2s-tdm fe470000.i2s: RX FIFO Overrun dmc: set_freq 1068000000 [ 70.241013] rockchip-i2s-tdm fddf0000.i2s: TX FIFO Underrun [ 70.241109] rockchip-i2s-tdm fe470000.i2s: RX FIFO Overrun dmc: set_freq 1560000000 [ 71.259416] rockchip-i2s-tdm fddf0000.i2s: TX FIFO Underrun [ 71.259452] rockchip-i2s-tdm fe470000.i2s: RX FIFO Overrun dmc: set_freq 2112000000 [ 72.277841] rockchip-i2s-tdm fddf0000.i2s: TX FIFO Underrun [ 72.277875] rockchip-i2s-tdm fe470000.i2s: RX FIFO Overrun Signed-off-by: Sugar Zhang Change-Id: I4416c3424f3778560cadb94f585c0acb06eb3f40 --- sound/soc/rockchip/rockchip_i2s_tdm.c | 82 ++++++++++++++++++++++++++- sound/soc/rockchip/rockchip_i2s_tdm.h | 8 +-- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index e192befa027b..20c8a4e9c3bc 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -85,6 +85,7 @@ struct rk_i2s_tdm_dev { struct regmap *grf; struct snd_dmaengine_dai_dma_data capture_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data; + struct snd_pcm_substream *substreams[SNDRV_PCM_STREAM_LAST + 1]; struct reset_control *tx_reset; struct reset_control *rx_reset; const struct rk_i2s_soc_data *soc_data; @@ -438,9 +439,32 @@ static void rockchip_i2s_tdm_tx_fifo_padding(struct rk_i2s_tdm_dev *i2s_tdm, boo regmap_write(i2s_tdm->regmap, I2S_TXDR, 0x0); } +static void rockchip_i2s_tdm_fifo_xrun_detect(struct rk_i2s_tdm_dev *i2s_tdm, + int stream, bool en) +{ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* clear irq status which was asserted before TXUIE enabled */ + regmap_update_bits(i2s_tdm->regmap, I2S_INTCR, + I2S_INTCR_TXUIC, I2S_INTCR_TXUIC); + regmap_update_bits(i2s_tdm->regmap, I2S_INTCR, + I2S_INTCR_TXUIE_MASK, + I2S_INTCR_TXUIE(en)); + } else { + /* clear irq status which was asserted before RXOIE enabled */ + regmap_update_bits(i2s_tdm->regmap, I2S_INTCR, + I2S_INTCR_RXOIC, I2S_INTCR_RXOIC); + regmap_update_bits(i2s_tdm->regmap, I2S_INTCR, + I2S_INTCR_RXOIE_MASK, + I2S_INTCR_RXOIE(en)); + } +} + static void rockchip_i2s_tdm_dma_ctrl(struct rk_i2s_tdm_dev *i2s_tdm, int stream, bool en) { + if (!en) + rockchip_i2s_tdm_fifo_xrun_detect(i2s_tdm, stream, 0); + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { if (i2s_tdm->quirks & QUIRK_HDMI_PATH) rockchip_i2s_tdm_tx_fifo_padding(i2s_tdm, en); @@ -463,6 +487,9 @@ static void rockchip_i2s_tdm_dma_ctrl(struct rk_i2s_tdm_dev *i2s_tdm, I2S_DMACR_RDE_MASK, I2S_DMACR_RDE(en)); } + + if (en) + rockchip_i2s_tdm_fifo_xrun_detect(i2s_tdm, stream, 1); } static void rockchip_i2s_tdm_xfer_start(struct rk_i2s_tdm_dev *i2s_tdm, @@ -1466,6 +1493,11 @@ static int rockchip_i2s_tdm_startup(struct snd_pcm_substream *substream, { struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai); + if (i2s_tdm->substreams[substream->stream]) + return -EBUSY; + + i2s_tdm->substreams[substream->stream] = substream; + /* * Suggested to stop audio source before HDMI configure to make * sure audio data integrity on HDMI-PATH-ALWAYS-ON situation. @@ -1479,8 +1511,17 @@ static int rockchip_i2s_tdm_startup(struct snd_pcm_substream *substream, return 0; } +static void rockchip_i2s_tdm_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai); + + i2s_tdm->substreams[substream->stream] = NULL; +} + static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = { .startup = rockchip_i2s_tdm_startup, + .shutdown = rockchip_i2s_tdm_shutdown, .hw_params = rockchip_i2s_tdm_hw_params, .set_sysclk = rockchip_i2s_tdm_set_sysclk, .set_fmt = rockchip_i2s_tdm_set_fmt, @@ -1542,6 +1583,7 @@ static bool rockchip_i2s_tdm_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { case I2S_TXFIFOLR: + case I2S_INTCR: case I2S_INTSR: case I2S_CLR: case I2S_TXDR: @@ -1932,6 +1974,34 @@ static const struct snd_dlp_config dconfig = { .get_fifo_count = rockchip_i2s_tdm_get_fifo_count, }; +static irqreturn_t rockchip_i2s_tdm_isr(int irq, void *devid) +{ + struct rk_i2s_tdm_dev *i2s_tdm = (struct rk_i2s_tdm_dev *)devid; + struct snd_pcm_substream *substream; + u32 val; + + regmap_read(i2s_tdm->regmap, I2S_INTSR, &val); + if (val & I2S_INTSR_TXUI_ACT) { + dev_warn_ratelimited(i2s_tdm->dev, "TX FIFO Underrun\n"); + regmap_update_bits(i2s_tdm->regmap, I2S_INTCR, + I2S_INTCR_TXUIC, I2S_INTCR_TXUIC); + substream = i2s_tdm->substreams[SNDRV_PCM_STREAM_PLAYBACK]; + if (substream) + snd_pcm_stop_xrun(substream); + } + + if (val & I2S_INTSR_RXOI_ACT) { + dev_warn_ratelimited(i2s_tdm->dev, "RX FIFO Overrun\n"); + regmap_update_bits(i2s_tdm->regmap, I2S_INTCR, + I2S_INTCR_RXOIC, I2S_INTCR_RXOIC); + substream = i2s_tdm->substreams[SNDRV_PCM_STREAM_CAPTURE]; + if (substream) + snd_pcm_stop_xrun(substream); + } + + return IRQ_HANDLED; +} + static int rockchip_i2s_tdm_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -1943,7 +2013,7 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev) #ifdef HAVE_SYNC_RESET bool sync; #endif - int ret, val, i; + int ret, val, i, irq; ret = rockchip_i2s_tdm_dai_prepare(pdev, &soc_dai); if (ret) @@ -2076,6 +2146,16 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev) if (IS_ERR(i2s_tdm->regmap)) return PTR_ERR(i2s_tdm->regmap); + irq = platform_get_irq_optional(pdev, 0); + if (irq > 0) { + ret = devm_request_irq(&pdev->dev, irq, rockchip_i2s_tdm_isr, + IRQF_SHARED, node->name, i2s_tdm); + if (ret) { + dev_err(&pdev->dev, "failed to request irq %u\n", irq); + return ret; + } + } + i2s_tdm->playback_dma_data.addr = res->start + I2S_TXDR; i2s_tdm->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; i2s_tdm->playback_dma_data.maxburst = MAXBURST_PER_FIFO; diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.h b/sound/soc/rockchip/rockchip_i2s_tdm.h index e46b63031ca0..2a8c48930aa6 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.h +++ b/sound/soc/rockchip/rockchip_i2s_tdm.h @@ -166,8 +166,8 @@ #define I2S_INTCR_RFT(x) (((x) - 1) << I2S_INTCR_RFT_SHIFT) #define I2S_INTCR_RXOIC BIT(18) #define I2S_INTCR_RXOIE_SHIFT 17 -#define I2S_INTCR_RXOIE_DISABLE (0 << I2S_INTCR_RXOIE_SHIFT) -#define I2S_INTCR_RXOIE_ENABLE (1 << I2S_INTCR_RXOIE_SHIFT) +#define I2S_INTCR_RXOIE_MASK (1 << I2S_INTCR_RXOIE_SHIFT) +#define I2S_INTCR_RXOIE(x) ((x) << I2S_INTCR_RXOIE_SHIFT) #define I2S_INTCR_RXFIE_SHIFT 16 #define I2S_INTCR_RXFIE_DISABLE (0 << I2S_INTCR_RXFIE_SHIFT) #define I2S_INTCR_RXFIE_ENABLE (1 << I2S_INTCR_RXFIE_SHIFT) @@ -176,8 +176,8 @@ #define I2S_INTCR_TFT_MASK (0x1f << I2S_INTCR_TFT_SHIFT) #define I2S_INTCR_TXUIC BIT(2) #define I2S_INTCR_TXUIE_SHIFT 1 -#define I2S_INTCR_TXUIE_DISABLE (0 << I2S_INTCR_TXUIE_SHIFT) -#define I2S_INTCR_TXUIE_ENABLE (1 << I2S_INTCR_TXUIE_SHIFT) +#define I2S_INTCR_TXUIE_MASK (1 << I2S_INTCR_TXUIE_SHIFT) +#define I2S_INTCR_TXUIE(x) ((x) << I2S_INTCR_TXUIE_SHIFT) /* * INTSR From 3ecb6301c4986ac4d9609d0ccbd55a7d65095499 Mon Sep 17 00:00:00 2001 From: Lin Jianhua Date: Tue, 20 Sep 2022 09:43:06 +0800 Subject: [PATCH 069/204] arm64: dts: rockchip: px30_linux_defconfig: enable CMA Signed-off-by: Lin Jianhua Change-Id: Ib300cf500e90a4b24f2a8db55e7277bdf3b91a93 --- arch/arm64/configs/px30_linux_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/px30_linux_defconfig b/arch/arm64/configs/px30_linux_defconfig index 60bacd15e427..ab7b88f44532 100644 --- a/arch/arm64/configs/px30_linux_defconfig +++ b/arch/arm64/configs/px30_linux_defconfig @@ -38,6 +38,7 @@ CONFIG_PREEMPT_VOLUNTARY=y CONFIG_HZ_1000=y # CONFIG_COMPACTION is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +CONFIG_CMA=y CONFIG_ZSMALLOC=y CONFIG_SECCOMP=y CONFIG_ARMV8_DEPRECATED=y @@ -457,6 +458,7 @@ CONFIG_NLS_CODEPAGE_936=y CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=y +CONFIG_DMA_CMA=y CONFIG_PRINTK_TIME=y CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_INFO=y From ce25d3298e665b0aeacf1c7d24ca825af467d61f Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Fri, 9 Sep 2022 14:47:20 +0800 Subject: [PATCH 070/204] ARM: dts: rockchip: add gpio alias for gpio dt nodes Add gpio alias for gpio controller dt nodes, which is used by the new gpio driver to get the index of gpio controller for driver. Signed-off-by: Jianqun Xu Change-Id: I148297ea0e84d2749866858ffc60f2e0d1d38d03 --- arch/arm/boot/dts/rk3036.dtsi | 3 +++ arch/arm/boot/dts/rk3066a.dtsi | 9 +++++++++ arch/arm/boot/dts/rk3188.dtsi | 7 +++++++ arch/arm/boot/dts/rk322x.dtsi | 4 ++++ arch/arm/boot/dts/rk3288.dtsi | 9 +++++++++ 5 files changed, 32 insertions(+) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 814f4ba3ea02..8bd522e50eea 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -18,6 +18,9 @@ aliases { ethernet0 = &emac; + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi index ddcf5e1bfa2f..36bca1ab7323 100644 --- a/arch/arm/boot/dts/rk3066a.dtsi +++ b/arch/arm/boot/dts/rk3066a.dtsi @@ -13,6 +13,15 @@ / { compatible = "rockchip,rk3066a"; + aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; + gpio4 = &gpio4; + gpio6 = &gpio6; + }; + cpus { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index 1eb64aeecbe8..695dcae6f619 100644 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -13,6 +13,13 @@ / { compatible = "rockchip,rk3188"; + aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; + }; + cpus { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index b29c16d97a8d..e4554b299650 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -15,6 +15,10 @@ aliases { ethernet0 = &gmac; + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; serial0 = &uart0; serial1 = &uart1; serial2 = &uart2; diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index a7952ca9e915..5ca338b4e73e 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -19,6 +19,15 @@ aliases { ethernet0 = &gmac; + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; + gpio4 = &gpio4; + gpio5 = &gpio5; + gpio6 = &gpio6; + gpio7 = &gpio7; + gpio8 = &gpio8; i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; From 143b809917c8fe5e6797a4e02da2b4b9722d6811 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Fri, 9 Sep 2022 14:57:16 +0800 Subject: [PATCH 071/204] ARM: dts: rockchip: add 'clock-names' for gpio dt nodes Add 'clock-names' property for gpio dt nodes, which is used by the gpio driver to identified as the index for the gpio controller. Signed-off-by: Jianqun Xu Change-Id: I07334122babd5773cab891f066e5086a16fe34bf --- arch/arm/boot/dts/rk3036.dtsi | 3 +++ arch/arm/boot/dts/rk3066a.dtsi | 6 ++++++ arch/arm/boot/dts/rk3188.dtsi | 4 ++++ arch/arm/boot/dts/rk322x.dtsi | 4 ++++ 4 files changed, 17 insertions(+) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 8bd522e50eea..351e4b1631a7 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -704,6 +704,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x2007c000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO0>; gpio-controller; @@ -717,6 +718,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x20080000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO1>; gpio-controller; @@ -730,6 +732,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x20084000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO2>; gpio-controller; diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi index 36bca1ab7323..71e2495d78b2 100644 --- a/arch/arm/boot/dts/rk3066a.dtsi +++ b/arch/arm/boot/dts/rk3066a.dtsi @@ -419,6 +419,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x20034000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO0>; gpio-controller; @@ -432,6 +433,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x2003c000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO1>; gpio-controller; @@ -445,6 +447,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x2003e000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO2>; gpio-controller; @@ -458,6 +461,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x20080000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO3>; gpio-controller; @@ -471,6 +475,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x20084000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO4>; gpio-controller; @@ -484,6 +489,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x2000a000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO6>; gpio-controller; diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index 695dcae6f619..5e3c1038efa8 100644 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -258,6 +258,7 @@ compatible = "rockchip,rk3188-gpio-bank0"; reg = <0x2000a000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO0>; gpio-controller; @@ -271,6 +272,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x2003c000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO1>; gpio-controller; @@ -284,6 +286,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x2003e000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO2>; gpio-controller; @@ -297,6 +300,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x20080000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO3>; gpio-controller; diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index e4554b299650..1a72629369a7 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -837,6 +837,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x11110000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO0>; gpio-controller; @@ -850,6 +851,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x11120000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO1>; gpio-controller; @@ -863,6 +865,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x11130000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO2>; gpio-controller; @@ -876,6 +879,7 @@ compatible = "rockchip,gpio-bank"; reg = <0x11140000 0x100>; interrupts = ; + clock-names = "bus"; clocks = <&cru PCLK_GPIO3>; gpio-controller; From 064f8026d1e0c6602caa9fb465752e69c3553b96 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Fri, 9 Sep 2022 14:53:27 +0800 Subject: [PATCH 072/204] arm64: dts: rockchip: add gpio alias for gpio dt nodes Add gpio alias for gpio controller dt nodes, which is used by the new gpio driver to get the index of gpio controller for driver. Signed-off-by: Jianqun Xu Change-Id: I8fa25bed0193b6fcdbf617e3d457362d3734c4c8 --- arch/arm64/boot/dts/rockchip/rk3308.dtsi | 5 +++++ arch/arm64/boot/dts/rockchip/rk3328.dtsi | 4 ++++ arch/arm64/boot/dts/rockchip/rk3368.dtsi | 4 ++++ arch/arm64/boot/dts/rockchip/rk3399.dtsi | 5 +++++ 4 files changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi index afaad9a5a8e0..d4914057810a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi @@ -23,6 +23,11 @@ aliases { ethernet0 = &mac; + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; + gpio4 = &gpio4; i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index ddf1792bfa2f..503dba319e73 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -20,6 +20,10 @@ #size-cells = <2>; aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; serial0 = &uart0; serial1 = &uart1; serial2 = &uart2; diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi index e962c7962789..cf6b66e022c0 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi @@ -19,6 +19,10 @@ aliases { ethernet0 = &gmac; + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index b0188e115097..64b2d7f2fee5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi @@ -27,6 +27,11 @@ dsi0 = &dsi; dsi1 = &dsi1; ethernet0 = &gmac; + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; + gpio4 = &gpio4; i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; From 4ddfedbb27a6b0af9f5acd4d21637a2e1d4d31de Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Mon, 19 Sep 2022 09:36:08 +0800 Subject: [PATCH 073/204] drm/rockchip: logo: copy mode from mode_set if no used crtc 1. Add rockchip_drm_copy_mode_from_mode_set() to copy drm_display_mode from rockchip_drm_mode_set, which stores the display state information in uboot. 2. Call rockchip_drm_copy_mode_from_mode_set() if vp failed to initialize. Signed-off-by: Damon Ding Change-Id: I0dea7237353dfe7b0d56bee81a47970ebb538d50 --- drivers/gpu/drm/rockchip/rockchip_drm_logo.c | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c index aaccb9e59928..eae4605aa2c7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c @@ -869,6 +869,18 @@ static int update_state(struct drm_device *drm_dev, return ret; } +static void rockchip_drm_copy_mode_from_mode_set(struct drm_display_mode *mode, + struct rockchip_drm_mode_set *set) +{ + mode->clock = set->clock; + mode->hdisplay = set->hdisplay; + mode->vdisplay = set->vdisplay; + mode->crtc_hsync_end = set->crtc_hsync_end; + mode->crtc_vsync_end = set->crtc_vsync_end; + mode->flags = set->flags & DRM_MODE_FLAG_ALL; + mode->picture_aspect_ratio = set->picture_aspect_ratio; +} + void rockchip_drm_show_logo(struct drm_device *drm_dev) { struct drm_atomic_state *state, *old_state; @@ -942,11 +954,22 @@ void rockchip_drm_show_logo(struct drm_device *drm_dev) if (!find_used_crtc) { struct drm_crtc *crtc = unset->crtc; + struct drm_crtc_state *crtc_state; int pipe = drm_crtc_index(crtc); struct rockchip_drm_private *priv = drm_dev->dev_private; + /* + * The display timing information of mode_set is parsed from dts, which + * written in uboot. If the mode_set is added into mode_unset_list, it + * should be converted to crtc_state->adjusted_mode, in order to check + * splice_mode flag in loader_protect(). + */ if (unset->hdisplay && unset->vdisplay) { + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (crtc_state) + rockchip_drm_copy_mode_from_mode_set(&crtc_state->adjusted_mode, + unset); if (priv->crtc_funcs[pipe] && priv->crtc_funcs[pipe]->loader_protect) priv->crtc_funcs[pipe]->loader_protect(crtc, true); From 480163a87a56c277f3fb9153a2333499a7b918cf Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Tue, 20 Sep 2022 16:21:43 +0800 Subject: [PATCH 074/204] soc: rockchip: power-domain: correct name of pd_gpu for px30s Fixes: 41f9bdf3cf40 ("soc: rockchip: power-domain: keep pd_gpu always on for px30s") Change-Id: I9af58d9471204c4540cf491b206c6c6f5d318a7f Signed-off-by: Zhen Chen --- drivers/soc/rockchip/pm_domains.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index b5ed7a16e3d3..474f05629457 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -633,7 +633,7 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) return 0; if (!power_on && soc_is_px30s()) { - if (genpd->name && !strcmp(genpd->name, "pd_gpu")) + if (genpd->name && !strcmp(genpd->name, "gpu")) return 0; } From a6b577b1565c46f6c9cde01a6488a8f4395d03d1 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 20 Sep 2022 16:40:06 +0800 Subject: [PATCH 075/204] media: rockchip: vicap fixed error of buffer free state Signed-off-by: Zefa Chen Change-Id: Ifb0105a4a587295418f624e78489cdbbff05194d --- drivers/media/platform/rockchip/cif/subdev-itf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 0d192ee18caa..4d1b8319f2dc 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -658,6 +658,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, unsigned long flags, buffree_flags; u32 diff_time = 1000000; u32 early_time = 0; + bool is_free = false; if (!buf) { v4l2_err(&cif_dev->v4l2_dev, "buf is NULL\n"); @@ -703,9 +704,10 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, list_add_tail(&dbufs->list, &priv->buf_free_list); spin_unlock_irqrestore(&cif_dev->buffree_lock, buffree_flags); schedule_work(&priv->buffree_work.work); + is_free = true; } - if (!rx_buf->dummy.is_free) { + if (!is_free) { list_add_tail(&dbufs->list, &stream->rx_buf_head); rkcif_assign_check_buffer_update_toisp(stream); if (cif_dev->rdbk_debug) { From d61da3a0f29db893820f32bbed8d75cbd4887c45 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Thu, 24 Mar 2022 12:04:20 +0800 Subject: [PATCH 076/204] MALI: bifrost: quick_reset: reduce JM_DEFAULT_RESET_TIMEOUT_MS to 1 (ms) To implement quick reset. Not work for CSF based Valhall GPU. Change-Id: I4d84d3a11ec4a5632c1a5f09bd90ed241fb9fc9a Signed-off-by: Zhen Chen --- drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h b/drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h index 9972bc382441..013fd8880bf2 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h @@ -213,7 +213,7 @@ enum { /* Default number of milliseconds given for other jobs on the GPU to be * soft-stopped when the GPU needs to be reset. */ -#define JM_DEFAULT_RESET_TIMEOUT_MS (3000) /* 3s */ +#define JM_DEFAULT_RESET_TIMEOUT_MS (1) /* 1 ms */ #endif /* MALI_USE_CSF */ From a51d0f8e9bb60d81ec8cc02b4779f9a6c441037d Mon Sep 17 00:00:00 2001 From: Jason Zhang Date: Tue, 2 Aug 2022 19:26:35 +0800 Subject: [PATCH 077/204] iio: light: ucs12cm0: reapply settings at resume The UCS12CM0 does not currently preserve settings after powered down, it will default to the UCS12CM0 settings after powered up, not the settings set by the host. Reapply all the settings at resume. Signed-off-by: Jason Zhang Change-Id: I66967bf0f4e880650c0f715b6e353bae4e31a0cb --- drivers/iio/light/ucs12cm0.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/iio/light/ucs12cm0.c b/drivers/iio/light/ucs12cm0.c index b04df7a09689..16b31d635cbf 100644 --- a/drivers/iio/light/ucs12cm0.c +++ b/drivers/iio/light/ucs12cm0.c @@ -619,10 +619,29 @@ static const struct i2c_device_id ucs12cm0_id[] = { }; MODULE_DEVICE_TABLE(i2c, ucs12cm0_id); +static int ucs12cm0_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ucs12cm0_data *data = iio_priv(indio_dev); + int ret; + + ret = ucs12cm0_init(data); + if (ret < 0) + return ret; + + return 0; +} + +static const struct dev_pm_ops ucs12cm0_pm_ops = { + .resume = ucs12cm0_resume, +}; + static struct i2c_driver ucs12cm0_driver = { .driver = { .name = "ucs12cm0", .of_match_table = ucs12cm0_of_match, + .pm = &ucs12cm0_pm_ops, }, .probe = ucs12cm0_probe, .id_table = ucs12cm0_id, From d6407e9c2704c7ec1161413f7691aef09feaedc6 Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Fri, 22 Mar 2019 09:32:03 +0800 Subject: [PATCH 078/204] arm64: dts: rockchip: support ramoops device node for rk3326-linux Change-Id: Idc7f0696cd6ce12b4ad9ff1547b60acc32a4a006 Signed-off-by: Ziyuan Xu --- arch/arm64/boot/dts/rockchip/rk3326-linux.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3326-linux.dtsi b/arch/arm64/boot/dts/rockchip/rk3326-linux.dtsi index 6ba60b41291b..f3ed899ab054 100644 --- a/arch/arm64/boot/dts/rockchip/rk3326-linux.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3326-linux.dtsi @@ -39,6 +39,15 @@ compatible = "rockchip,drm-logo"; reg = <0x0 0x0 0x0 0x0>; }; + + ramoops: ramoops@110000 { + compatible = "ramoops"; + reg = <0x0 0x110000 0x0 0xf0000>; + record-size = <0x20000>; + console-size = <0x80000>; + ftrace-size = <0x00000>; + pmsg-size = <0x50000>; + }; }; }; From aa9cd6fd691a682e3a8b1c078b9079d1f28d908e Mon Sep 17 00:00:00 2001 From: ZhiZhan Chen Date: Tue, 13 Sep 2022 11:24:57 +0800 Subject: [PATCH 079/204] arm64: dts: rockchip: rk3399: enable route_hdmi for evb Signed-off-by: ZhiZhan Chen Change-Id: I5cb340f11ea3229ce1b44419ab413c208b4a1bd4 --- arch/arm64/boot/dts/rockchip/rk3399-evb-ind-lpddr4-linux.dts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb-ind-lpddr4-linux.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb-ind-lpddr4-linux.dts index 6589bb6853f2..b4b3a003dd33 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-evb-ind-lpddr4-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb-ind-lpddr4-linux.dts @@ -287,6 +287,11 @@ status = "okay"; }; +&route_hdmi { + status = "okay"; + connect = <&vopb_out_hdmi>; +}; + /* * if enable dp_sound, should disable spdif_sound and spdif_out */ From 727dcf4a26a1fc76c7eed887851bc81d61192506 Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Tue, 20 Sep 2022 16:24:39 +0800 Subject: [PATCH 080/204] ARM: dts: rockchip: fixes the map of mmc_ecsd for rv1106-thunder-boot-mmc The hpmcu run at [256K-512KB] address, change the mmc-escd's space to within 256KB. Signed-off-by: Ziyuan Xu Change-Id: I4d3acebd30b6fa780e7e8a7cb28adbd10d13050f --- arch/arm/boot/dts/rv1106-thunder-boot-emmc.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rv1106-thunder-boot-emmc.dtsi b/arch/arm/boot/dts/rv1106-thunder-boot-emmc.dtsi index dbb61987602c..208cb559d7b5 100644 --- a/arch/arm/boot/dts/rv1106-thunder-boot-emmc.dtsi +++ b/arch/arm/boot/dts/rv1106-thunder-boot-emmc.dtsi @@ -7,8 +7,8 @@ / { reserved-memory { - mmc_ecsd: mmc@3fe00 { - reg = <0x3fe00 0x00000800>; + mmc_ecsd: mmc@3f000 { + reg = <0x3f000 0x00001000>; }; mmc_idmac: mmc@100000 { From 361115cc9b4382b8719818ea76bb9881bec64f3b Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Mon, 19 Sep 2022 17:04:39 +0800 Subject: [PATCH 081/204] hwspinlock: rockchip: amend to use new helpers Use the new helpers that include struct_size(), devm_platform_ioremap_resource(), devm_hwspin_lock_register() and etc., which can simpify the code. Signed-off-by: Frank Wang Change-Id: I6507964759d6cc123a74c5d2c0112702927e017b --- drivers/hwspinlock/rockchip_hwspinlock.c | 54 ++++-------------------- 1 file changed, 8 insertions(+), 46 deletions(-) diff --git a/drivers/hwspinlock/rockchip_hwspinlock.c b/drivers/hwspinlock/rockchip_hwspinlock.c index 2d62aff57f72..26ba8ec31f01 100644 --- a/drivers/hwspinlock/rockchip_hwspinlock.c +++ b/drivers/hwspinlock/rockchip_hwspinlock.c @@ -5,13 +5,10 @@ #include #include #include -#include #include -#include #include #include #include -#include #include "hwspinlock_internal.h" @@ -59,19 +56,15 @@ static int rockchip_hwspinlock_probe(struct platform_device *pdev) { struct rockchip_hwspinlock *hwspin; struct hwspinlock *hwlock; - struct resource *res; - int idx, ret; + int idx; - if (!pdev->dev.of_node) - return -ENODEV; - - hwspin = devm_kzalloc(&pdev->dev, sizeof(*hwspin) + - sizeof(*hwlock) * HWSPINLOCK_NUMBER, GFP_KERNEL); + hwspin = devm_kzalloc(&pdev->dev, + struct_size(hwspin, bank.lock, HWSPINLOCK_NUMBER), + GFP_KERNEL); if (!hwspin) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hwspin->io_base = devm_ioremap_resource(&pdev->dev, res); + hwspin->io_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hwspin->io_base)) return PTR_ERR(hwspin->io_base); @@ -82,39 +75,9 @@ static int rockchip_hwspinlock_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hwspin); - pm_runtime_enable(&pdev->dev); - - ret = hwspin_lock_register(&hwspin->bank, &pdev->dev, - &rockchip_hwspinlock_ops, 0, - HWSPINLOCK_NUMBER); - if (ret) - goto reg_fail; - - return 0; - -reg_fail: - pm_runtime_disable(&pdev->dev); - iounmap(hwspin->io_base); - - return ret; -} - -static int rockchip_hwspinlock_remove(struct platform_device *pdev) -{ - struct rockchip_hwspinlock *hwspin = platform_get_drvdata(pdev); - int ret; - - ret = hwspin_lock_unregister(&hwspin->bank); - if (ret) { - dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret); - return ret; - } - - pm_runtime_disable(&pdev->dev); - - iounmap(hwspin->io_base); - - return 0; + return devm_hwspin_lock_register(&pdev->dev, &hwspin->bank, + &rockchip_hwspinlock_ops, 0, + HWSPINLOCK_NUMBER); } static const struct of_device_id rockchip_hwpinlock_ids[] = { @@ -125,7 +88,6 @@ MODULE_DEVICE_TABLE(of, rockchip_hwpinlock_ids); static struct platform_driver rockchip_hwspinlock_driver = { .probe = rockchip_hwspinlock_probe, - .remove = rockchip_hwspinlock_remove, .driver = { .name = "rockchip_hwspinlock", .of_match_table = of_match_ptr(rockchip_hwpinlock_ids), From a8af0afc5ec1c4949fdb0d55edd89391b5b51cb2 Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Sat, 17 Sep 2022 08:41:27 +0800 Subject: [PATCH 082/204] video: rockchip: mpp: fix av1 dec err when multi tiles Do not enable cache_all_e when source is multi tiles. Signed-off-by: Yandong Lin Change-Id: Ie40aac145dfc481f371865efc5e962dd0cfdb451 --- drivers/video/rockchip/mpp/mpp_av1dec.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_av1dec.c b/drivers/video/rockchip/mpp/mpp_av1dec.c index 26ef14a3fe79..0cb625ff3be2 100644 --- a/drivers/video/rockchip/mpp/mpp_av1dec.c +++ b/drivers/video/rockchip/mpp/mpp_av1dec.c @@ -534,11 +534,11 @@ static int av1dec_set_l2_cache(struct av1dec_dev *dec, struct av1dec_task *task) writel_relaxed(AV1_L2_CACHE_SHAPER_EN, dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_SHAPER_CTRL); - /* TODO: set exception list */ - - /* multi id enable bit */ - writel_relaxed(0x00000001, dec->reg_base[AV1DEC_CLASS_CACHE] + - AV1_L2_CACHE_RD_ONLY_CONFIG); + /* not enable cache en when multi tiles */ + if (!(regs[10] & BIT(1))) + /* cache all en */ + writel_relaxed(0x00000001, dec->reg_base[AV1DEC_CLASS_CACHE] + + AV1_L2_CACHE_RD_ONLY_CONFIG); /* reorder_e and cache_e */ writel_relaxed(0x00000081, dec->reg_base[AV1DEC_CLASS_CACHE] + AV1_L2_CACHE_RD_ONLY_CTRL); From d076332a585837ff72b0bdcf8b37bd86a92c8928 Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Wed, 7 Sep 2022 20:29:07 +0800 Subject: [PATCH 083/204] video: rockchip: mpp: do not register irq for av1 cache There is no need to care about cache irq Signed-off-by: Yandong Lin Change-Id: Iffd9461b928e1553dc23cf7f47b3979e404016ac --- drivers/video/rockchip/mpp/mpp_av1dec.c | 26 +------------------------ 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_av1dec.c b/drivers/video/rockchip/mpp/mpp_av1dec.c index 0cb625ff3be2..33e118ae6450 100644 --- a/drivers/video/rockchip/mpp/mpp_av1dec.c +++ b/drivers/video/rockchip/mpp/mpp_av1dec.c @@ -1199,25 +1199,8 @@ int av1dec_driver_register(struct platform_driver *drv) return driver_register(&drv->driver); } -static irqreturn_t av1dec_cache_irq(int irq, void *dev_id) -{ - struct av1dec_dev *dec = dev_id; - u32 shaper_st, rd_st; - - shaper_st = readl(dec->reg_base[AV1DEC_CLASS_CACHE] + 0x2c); - rd_st = readl(dec->reg_base[AV1DEC_CLASS_CACHE] + 0x204); - - mpp_debug(DEBUG_IRQ_STATUS, "cache irq st shaper 0x%x read 0x%x\n", shaper_st, rd_st); - - writel(shaper_st, dec->reg_base[AV1DEC_CLASS_CACHE] + 0x2c); - writel(rd_st, dec->reg_base[AV1DEC_CLASS_CACHE] + 0x204); - - return IRQ_HANDLED; -} - static int av1dec_cache_init(struct platform_device *pdev, struct av1dec_dev *dec) { - int ret; struct resource *res; struct device *dev = &pdev->dev; @@ -1230,14 +1213,7 @@ static int av1dec_cache_init(struct platform_device *pdev, struct av1dec_dev *de dev_err(dev, "ioremap failed for resource %pR\n", res); return -EINVAL; } - - dec->irq[AV1DEC_CLASS_CACHE] = platform_get_irq(pdev, 1); - - ret = devm_request_irq(dev, dec->irq[AV1DEC_CLASS_CACHE], - av1dec_cache_irq, IRQF_SHARED, "irq_cache", dec); - if (ret) - mpp_err("ret=%d\n", ret); - return ret; + return 0; } static int av1dec_afbc_init(struct platform_device *pdev, struct av1dec_dev *dec) From 216596cf79294be40a8dc322f7d4e6c0e1e29657 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Sat, 26 Mar 2022 17:33:30 +0800 Subject: [PATCH 084/204] MALI: bifrost: quick_reset: use short timeout (quick_reset) for the case to workaround Not work for CSF based Valhall GPU. Change-Id: I38d27d2006e25acbab826efd36b49efffa6b79f1 Signed-off-by: Zhen Chen --- .../backend/gpu/mali_kbase_js_backend.c | 5 +++ .../arm/bifrost/device/mali_kbase_device.c | 34 +++++++++++++++++++ drivers/gpu/arm/bifrost/mali_kbase.h | 7 ++++ .../gpu/arm/bifrost/mali_kbase_core_linux.c | 5 +++ drivers/gpu/arm/bifrost/mali_kbase_defs.h | 12 +++++++ drivers/gpu/arm/bifrost/mali_kbase_js.c | 5 +++ 6 files changed, 68 insertions(+) diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c index ea4c4d0cfe73..09798803f716 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c @@ -131,10 +131,15 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer) } else { soft_stop_ticks = js_devdata->soft_stop_ticks; + if (kbase_is_quick_reset_enabled(kbdev)) { + hard_stop_ticks = 2; + gpu_reset_ticks = 3; + } else { hard_stop_ticks = js_devdata->hard_stop_ticks_ss; gpu_reset_ticks = js_devdata->gpu_reset_ticks_ss; + } } /* If timeouts have been changed then ensure diff --git a/drivers/gpu/arm/bifrost/device/mali_kbase_device.c b/drivers/gpu/arm/bifrost/device/mali_kbase_device.c index 1949a211575d..d923b18f30ba 100644 --- a/drivers/gpu/arm/bifrost/device/mali_kbase_device.c +++ b/drivers/gpu/arm/bifrost/device/mali_kbase_device.c @@ -326,6 +326,13 @@ int kbase_device_misc_init(struct kbase_device * const kbdev) "Unable to register OOM notifier for Mali - but will continue\n"); kbdev->oom_notifier_block.notifier_call = NULL; } + +#if !MALI_USE_CSF + spin_lock_init(&kbdev->quick_reset_lock); + kbdev->quick_reset_enabled = true; + kbdev->num_of_atoms_hw_completed = 0; +#endif + return 0; term_ktrace: @@ -356,6 +363,33 @@ void kbase_device_misc_term(struct kbase_device *kbdev) unregister_oom_notifier(&kbdev->oom_notifier_block); } +#if !MALI_USE_CSF +void kbase_enable_quick_reset(struct kbase_device *kbdev) +{ + spin_lock(&kbdev->quick_reset_lock); + + kbdev->quick_reset_enabled = true; + kbdev->num_of_atoms_hw_completed = 0; + + spin_unlock(&kbdev->quick_reset_lock); +} + +void kbase_disable_quick_reset(struct kbase_device *kbdev) +{ + spin_lock(&kbdev->quick_reset_lock); + + kbdev->quick_reset_enabled = false; + kbdev->num_of_atoms_hw_completed = 0; + + spin_unlock(&kbdev->quick_reset_lock); +} + +bool kbase_is_quick_reset_enabled(struct kbase_device *kbdev) +{ + return kbdev->quick_reset_enabled; +} +#endif + void kbase_device_free(struct kbase_device *kbdev) { kfree(kbdev); diff --git a/drivers/gpu/arm/bifrost/mali_kbase.h b/drivers/gpu/arm/bifrost/mali_kbase.h index 10faaf355f7b..451d44713b10 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase.h +++ b/drivers/gpu/arm/bifrost/mali_kbase.h @@ -115,6 +115,13 @@ struct kbase_device *kbase_device_alloc(void); int kbase_device_misc_init(struct kbase_device *kbdev); void kbase_device_misc_term(struct kbase_device *kbdev); + +#if !MALI_USE_CSF +void kbase_enable_quick_reset(struct kbase_device *kbdev); +void kbase_disable_quick_reset(struct kbase_device *kbdev); +bool kbase_is_quick_reset_enabled(struct kbase_device *kbdev); +#endif + void kbase_device_free(struct kbase_device *kbdev); int kbase_device_has_feature(struct kbase_device *kbdev, u32 feature); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c index 0d3fd653af9f..6675add413fd 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c @@ -5564,6 +5564,11 @@ static int kbase_device_resume(struct device *dev) if (kbdev->devfreq) kbase_devfreq_enqueue_work(kbdev, DEVFREQ_WORK_RESUME); #endif + +#if !MALI_USE_CSF + kbase_enable_quick_reset(kbdev); +#endif + return 0; } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_defs.h index 26f1dab5401e..e4ad9743e79f 100755 --- a/drivers/gpu/arm/bifrost/mali_kbase_defs.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_defs.h @@ -1241,6 +1241,18 @@ struct kbase_device { struct notifier_block oom_notifier_block; +#if !MALI_USE_CSF + spinlock_t quick_reset_lock; + bool quick_reset_enabled; + /* + * 进入 quck_reset_mode 后 (quick_reset_enabled 为 true), + * 对已经进入 KBASE_JD_ATOM_STATE_HW_COMPLETED 状态的 atom 的计数. + * + * 若 num_of_atoms_hw_completed 达到一定值, 将退出 quck_reset_mode. + * 见 kbase_js_complete_atom() 对 num_of_atoms_hw_completed 的引用. + */ + u32 num_of_atoms_hw_completed; +#endif }; /** diff --git a/drivers/gpu/arm/bifrost/mali_kbase_js.c b/drivers/gpu/arm/bifrost/mali_kbase_js.c index 0de1cd75da89..4d3812711718 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_js.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_js.c @@ -3484,6 +3484,11 @@ struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom, katom->status = KBASE_JD_ATOM_STATE_HW_COMPLETED; dev_dbg(kbdev->dev, "Atom %pK status to HW completed\n", (void *)katom); + if (kbase_is_quick_reset_enabled(kbdev)) { + kbdev->num_of_atoms_hw_completed++; + if (kbdev->num_of_atoms_hw_completed >= 20) + kbase_disable_quick_reset(kbdev); + } if (katom->event_code != BASE_JD_EVENT_DONE) { kbase_js_evict_deps(kctx, katom, katom->slot_nr, From 2b324c90634dd8e4ba6d80a674d316622e61a555 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Tue, 29 Mar 2022 19:46:39 +0800 Subject: [PATCH 085/204] MALI: bifrost: quick_reset: disable err logs when quick_reset is enabled Not work for CSF based Valhall GPU. Change-Id: Ic2ad8073f8091b4d31f15527d30f10759d5b01ed Signed-off-by: Zhen Chen --- .../gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c | 13 +++++++++---- .../arm/bifrost/backend/gpu/mali_kbase_js_backend.c | 13 +++++++++---- drivers/gpu/arm/bifrost/mali_kbase_jd.c | 12 +++++++----- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c index 0d2683d73efd..ae781ec14a22 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c @@ -1071,6 +1071,9 @@ static void kbasep_reset_timeout_worker(struct work_struct *data) KBASE_RESET_GPU_SILENT) silent = true; + if (kbase_is_quick_reset_enabled(kbdev)) + silent = true; + KBASE_KTRACE_ADD_JM(kbdev, JM_BEGIN_RESET_WORKER, NULL, NULL, 0u, 0); /* Disable GPU hardware counters. @@ -1383,8 +1386,9 @@ void kbase_reset_gpu(struct kbase_device *kbdev) atomic_set(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_COMMITTED); - dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", - kbdev->reset_timeout_ms); + if (!kbase_is_quick_reset_enabled(kbdev)) + dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", + kbdev->reset_timeout_ms); hrtimer_start(&kbdev->hwaccess.backend.reset_timer, HR_TIMER_DELAY_MSEC(kbdev->reset_timeout_ms), @@ -1407,8 +1411,9 @@ void kbase_reset_gpu_locked(struct kbase_device *kbdev) atomic_set(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_COMMITTED); - dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", - kbdev->reset_timeout_ms); + if (!kbase_is_quick_reset_enabled(kbdev)) + dev_err(kbdev->dev, "Preparing to soft-reset GPU: Waiting (upto %d ms) for all jobs to complete soft-stop\n", + kbdev->reset_timeout_ms); hrtimer_start(&kbdev->hwaccess.backend.reset_timer, HR_TIMER_DELAY_MSEC(kbdev->reset_timeout_ms), HRTIMER_MODE_REL); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c index 09798803f716..a2f824da5e04 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_js_backend.c @@ -201,9 +201,10 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer) int ms = js_devdata->scheduling_period_ns / 1000000u; - dev_warn(kbdev->dev, "JS: Job Hard-Stopped (took more than %lu ticks at %lu ms/tick)", - (unsigned long)ticks, - (unsigned long)ms); + if (!kbase_is_quick_reset_enabled(kbdev)) + dev_warn(kbdev->dev, "JS: Job Hard-Stopped (took more than %lu ticks at %lu ms/tick)", + (unsigned long)ticks, + (unsigned long)ms); kbase_job_slot_hardstop(atom->kctx, s, atom); #endif @@ -260,7 +261,11 @@ static enum hrtimer_restart timer_callback(struct hrtimer *timer) } } if (reset_needed) { - dev_err(kbdev->dev, "JS: Job has been on the GPU for too long (JS_RESET_TICKS_SS/DUMPING timeout hit). Issuing GPU soft-reset to resolve."); + if (kbase_is_quick_reset_enabled(kbdev)) + dev_err(kbdev->dev, "quick reset"); + else { + dev_err(kbdev->dev, "JS: Job has been on the GPU for too long (JS_RESET_TICKS_SS/DUMPING timeout hit). Issuing GPU soft-reset to resolve."); + } if (kbase_prepare_to_reset_gpu_locked(kbdev, RESET_FLAGS_NONE)) kbase_reset_gpu_locked(kbdev); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jd.c b/drivers/gpu/arm/bifrost/mali_kbase_jd.c index d22e1bddb9bd..3f03a57241cf 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_jd.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_jd.c @@ -1464,11 +1464,13 @@ void kbase_jd_done_worker(struct work_struct *data) } if ((katom->event_code != BASE_JD_EVENT_DONE) && - (!kbase_ctx_flag(katom->kctx, KCTX_DYING))) - dev_err(kbdev->dev, - "t6xx: GPU fault 0x%02lx from job slot %d\n", - (unsigned long)katom->event_code, - katom->slot_nr); + (!kbase_ctx_flag(katom->kctx, KCTX_DYING))) { + if (!kbase_is_quick_reset_enabled(kbdev)) + dev_err(kbdev->dev, + "t6xx: GPU fault 0x%02lx from job slot %d\n", + (unsigned long)katom->event_code, + katom->slot_nr); + } /* Retain state before the katom disappears */ kbasep_js_atom_retained_state_copy(&katom_retained_state, katom); From f3a6824aaa1265b914253d4dcf60caac95d0a19e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 5 Nov 2021 14:42:26 +0200 Subject: [PATCH 086/204] UPSTREAM: pinctrl/rockchip: Drop wrong kernel doc annotation Kernel doc validator is not happy: .../pinctrl-rockchip.c:45: warning: This comment starts with '/**', but isn't a kernel-doc comment. Drop it as it's indeed not a kernel doc comment. Signed-off-by: Andy Shevchenko Reviewed-by: Heiko Stuebner (cherry picked from commit 5a83227b3d4f9dd1c66beba13f53f31e981efd48) Signed-off-by: Jianqun Xu Change-Id: Ib7d7e5efa9bb308d6173f0945928ad34b3c5ea5a --- drivers/pinctrl/pinctrl-rockchip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 0fde69842dec..4803cac0090d 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -40,7 +40,7 @@ #include "pinconf.h" #include "pinctrl-rockchip.h" -/** +/* * Generate a bitmask for setting a value (v) with a write mask bit in hiword * register 31:16 area. */ From 2a5b819bbbeb4f6ae21190734c090de7df17e7d8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 5 Nov 2021 14:42:27 +0200 Subject: [PATCH 087/204] UPSTREAM: pinctrl/rockchip: Use temporary variable for struct device Use temporary variable for struct device to make code neater. Signed-off-by: Andy Shevchenko Reviewed-by: Heiko Stuebner (cherry picked from commit e4dd7fd5ff0acb3f3ed290f52afe20fd840d22b0) Signed-off-by: Jianqun Xu Change-Id: I382e5c2276febe7774d954e70341ae548ce59855 --- drivers/pinctrl/pinctrl-rockchip.c | 116 +++++++++++++---------------- 1 file changed, 53 insertions(+), 63 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 4803cac0090d..2530c206dab3 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -334,6 +334,7 @@ static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev, { struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); const struct rockchip_pin_group *grp; + struct device *dev = info->dev; struct pinctrl_map *new_map; struct device_node *parent; int map_num = 1; @@ -345,8 +346,7 @@ static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev, */ grp = pinctrl_name_to_group(info, np->name); if (!grp) { - dev_err(info->dev, "unable to find group for node %pOFn\n", - np); + dev_err(dev, "unable to find group for node %pOFn\n", np); return -EINVAL; } @@ -380,7 +380,7 @@ static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev, new_map[i].data.configs.num_configs = grp->data[i].nconfigs; } - dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n", + dev_dbg(dev, "maps: function %s group %s num %d\n", (*map)->data.mux.function, (*map)->data.mux.group, map_num); return 0; @@ -1126,20 +1126,20 @@ static int rockchip_verify_mux(struct rockchip_pin_bank *bank, int pin, int mux) { struct rockchip_pinctrl *info = bank->drvdata; + struct device *dev = info->dev; int iomux_num = (pin / 8); if (iomux_num > 3) return -EINVAL; if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) { - dev_err(info->dev, "pin %d is unrouted\n", pin); + dev_err(dev, "pin %d is unrouted\n", pin); return -EINVAL; } if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) { if (mux != RK_FUNC_GPIO) { - dev_err(info->dev, - "pin %d only supports a gpio mux\n", pin); + dev_err(dev, "pin %d only supports a gpio mux\n", pin); return -ENOTSUPP; } } @@ -1164,6 +1164,7 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) { struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pin_ctrl *ctrl = info->ctrl; + struct device *dev = info->dev; int iomux_num = (pin / 8); struct regmap *regmap; int reg, ret, mask, mux_type; @@ -1177,8 +1178,7 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) return 0; - dev_dbg(info->dev, "setting mux of GPIO%d-%d to %d\n", - bank->bank_num, pin, mux); + dev_dbg(dev, "setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux); if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) regmap = info->regmap_pmu; @@ -2505,6 +2505,7 @@ static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank, { struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pin_ctrl *ctrl = info->ctrl; + struct device *dev = info->dev; struct regmap *regmap; int reg, ret; u32 data, temp, rmask_bits; @@ -2550,7 +2551,7 @@ static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank, bit -= 16; break; default: - dev_err(info->dev, "unsupported bit: %d for pinctrl drive type: %d\n", + dev_err(dev, "unsupported bit: %d for pinctrl drive type: %d\n", bit, drv_type); return -EINVAL; } @@ -2563,8 +2564,7 @@ static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank, rmask_bits = RK3288_DRV_BITS_PER_PIN; break; default: - dev_err(info->dev, "unsupported pinctrl drive type: %d\n", - drv_type); + dev_err(dev, "unsupported pinctrl drive type: %d\n", drv_type); return -EINVAL; } @@ -2597,13 +2597,14 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, { struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pin_ctrl *ctrl = info->ctrl; + struct device *dev = info->dev; struct regmap *regmap; int reg, ret, i, err; u32 data, rmask, rmask_bits, temp; u8 bit; int drv_type = bank->drv[pin_num / 8].drv_type; - dev_dbg(info->dev, "setting drive of GPIO%d-%d to %d\n", + dev_dbg(dev, "setting drive of GPIO%d-%d to %d\n", bank->bank_num, pin_num, strength); ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); @@ -2629,8 +2630,7 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, } if (ret < 0) { - dev_err(info->dev, "unsupported driver strength %d\n", - strength); + dev_err(dev, "unsupported driver strength %d\n", strength); return ret; } @@ -2669,7 +2669,7 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, bit -= 16; break; default: - dev_err(info->dev, "unsupported bit: %d for pinctrl drive type: %d\n", + dev_err(dev, "unsupported bit: %d for pinctrl drive type: %d\n", bit, drv_type); return -EINVAL; } @@ -2681,8 +2681,7 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, rmask_bits = RK3288_DRV_BITS_PER_PIN; break; default: - dev_err(info->dev, "unsupported pinctrl drive type: %d\n", - drv_type); + dev_err(dev, "unsupported pinctrl drive type: %d\n", drv_type); return -EINVAL; } @@ -2751,6 +2750,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) { struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pin_ctrl *ctrl = info->ctrl; + struct device *dev = info->dev; struct regmap *regmap; int reg, ret, pull_type; u8 bit; @@ -2790,7 +2790,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) return rockchip_pull_list[pull_type][data]; default: - dev_err(info->dev, "unsupported pinctrl type\n"); + dev_err(dev, "unsupported pinctrl type\n"); return -EINVAL; }; } @@ -2800,13 +2800,13 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, { struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pin_ctrl *ctrl = info->ctrl; + struct device *dev = info->dev; struct regmap *regmap; int reg, ret, i, pull_type; u8 bit; u32 data, rmask; - dev_dbg(info->dev, "setting pull of GPIO%d-%d to %d\n", - bank->bank_num, pin_num, pull); + dev_dbg(dev, "setting pull of GPIO%d-%d to %d\n", bank->bank_num, pin_num, pull); /* rk3066b does support any pulls */ if (ctrl->type == RK3066B) @@ -2853,8 +2853,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, } if (ret < 0) { - dev_err(info->dev, "unsupported pull setting %d\n", - pull); + dev_err(dev, "unsupported pull setting %d\n", pull); return ret; } @@ -2866,7 +2865,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, ret = regmap_update_bits(regmap, reg, rmask, data); break; default: - dev_err(info->dev, "unsupported pinctrl type\n"); + dev_err(dev, "unsupported pinctrl type\n"); return -EINVAL; } @@ -2957,12 +2956,13 @@ static int rockchip_set_schmitt(struct rockchip_pin_bank *bank, { struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pin_ctrl *ctrl = info->ctrl; + struct device *dev = info->dev; struct regmap *regmap; int reg, ret; u8 bit; u32 data, rmask; - dev_dbg(info->dev, "setting input schmitt of GPIO%d-%d to %d\n", + dev_dbg(dev, "setting input schmitt of GPIO%d-%d to %d\n", bank->bank_num, pin_num, enable); ret = ctrl->schmitt_calc_reg(bank, pin_num, ®map, ®, &bit); @@ -3105,10 +3105,11 @@ static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); const unsigned int *pins = info->groups[group].pins; const struct rockchip_pin_config *data = info->groups[group].data; + struct device *dev = info->dev; struct rockchip_pin_bank *bank; int cnt, ret = 0; - dev_dbg(info->dev, "enable function %s group %s\n", + dev_dbg(dev, "enable function %s group %s\n", info->functions[selector].name, info->groups[group].name); /* @@ -3408,6 +3409,7 @@ static int rockchip_pinctrl_parse_groups(struct device_node *np, struct rockchip_pinctrl *info, u32 index) { + struct device *dev = info->dev; struct rockchip_pin_bank *bank; int size; const __be32 *list; @@ -3415,7 +3417,7 @@ static int rockchip_pinctrl_parse_groups(struct device_node *np, int i, j; int ret; - dev_dbg(info->dev, "group(%d): %pOFn\n", index, np); + dev_dbg(dev, "group(%d): %pOFn\n", index, np); /* Initialise group */ grp->name = np->name; @@ -3428,18 +3430,14 @@ static int rockchip_pinctrl_parse_groups(struct device_node *np, /* we do not check return since it's safe node passed down */ size /= sizeof(*list); if (!size || size % 4) { - dev_err(info->dev, "wrong pins number or pins and configs should be by 4\n"); + dev_err(dev, "wrong pins number or pins and configs should be by 4\n"); return -EINVAL; } grp->npins = size / 4; - grp->pins = devm_kcalloc(info->dev, grp->npins, sizeof(unsigned int), - GFP_KERNEL); - grp->data = devm_kcalloc(info->dev, - grp->npins, - sizeof(struct rockchip_pin_config), - GFP_KERNEL); + grp->pins = devm_kcalloc(dev, grp->npins, sizeof(*grp->pins), GFP_KERNEL); + grp->data = devm_kcalloc(dev, grp->npins, sizeof(*grp->data), GFP_KERNEL); if (!grp->pins || !grp->data) return -ENOMEM; @@ -3473,6 +3471,7 @@ static int rockchip_pinctrl_parse_functions(struct device_node *np, struct rockchip_pinctrl *info, u32 index) { + struct device *dev = info->dev; struct device_node *child; struct rockchip_pmx_func *func; struct rockchip_pin_group *grp; @@ -3480,7 +3479,7 @@ static int rockchip_pinctrl_parse_functions(struct device_node *np, static u32 grp_index; u32 i = 0; - dev_dbg(info->dev, "parse function(%d): %pOFn\n", index, np); + dev_dbg(dev, "parse function(%d): %pOFn\n", index, np); func = &info->functions[index]; @@ -3490,8 +3489,7 @@ static int rockchip_pinctrl_parse_functions(struct device_node *np, if (func->ngroups <= 0) return 0; - func->groups = devm_kcalloc(info->dev, - func->ngroups, sizeof(char *), GFP_KERNEL); + func->groups = devm_kcalloc(dev, func->ngroups, sizeof(*func->groups), GFP_KERNEL); if (!func->groups) return -ENOMEM; @@ -3519,20 +3517,14 @@ static int rockchip_pinctrl_parse_dt(struct platform_device *pdev, rockchip_pinctrl_child_count(info, np); - dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions); - dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups); + dev_dbg(dev, "nfunctions = %d\n", info->nfunctions); + dev_dbg(dev, "ngroups = %d\n", info->ngroups); - info->functions = devm_kcalloc(dev, - info->nfunctions, - sizeof(struct rockchip_pmx_func), - GFP_KERNEL); + info->functions = devm_kcalloc(dev, info->nfunctions, sizeof(*info->functions), GFP_KERNEL); if (!info->functions) return -ENOMEM; - info->groups = devm_kcalloc(dev, - info->ngroups, - sizeof(struct rockchip_pin_group), - GFP_KERNEL); + info->groups = devm_kcalloc(dev, info->ngroups, sizeof(*info->groups), GFP_KERNEL); if (!info->groups) return -ENOMEM; @@ -3544,7 +3536,7 @@ static int rockchip_pinctrl_parse_dt(struct platform_device *pdev, ret = rockchip_pinctrl_parse_functions(child, info, i++); if (ret) { - dev_err(&pdev->dev, "failed to parse function\n"); + dev_err(dev, "failed to parse function\n"); of_node_put(child); return ret; } @@ -3559,6 +3551,7 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, struct pinctrl_desc *ctrldesc = &info->pctl; struct pinctrl_pin_desc *pindesc, *pdesc; struct rockchip_pin_bank *pin_bank; + struct device *dev = &pdev->dev; int pin, bank, ret; int k; @@ -3568,9 +3561,7 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, ctrldesc->pmxops = &rockchip_pmx_ops; ctrldesc->confops = &rockchip_pinconf_ops; - pindesc = devm_kcalloc(&pdev->dev, - info->ctrl->nr_pins, sizeof(*pindesc), - GFP_KERNEL); + pindesc = devm_kcalloc(dev, info->ctrl->nr_pins, sizeof(*pindesc), GFP_KERNEL); if (!pindesc) return -ENOMEM; @@ -3595,9 +3586,9 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, if (ret) return ret; - info->pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, info); + info->pctl_dev = devm_pinctrl_register(dev, ctrldesc, info); if (IS_ERR(info->pctl_dev)) { - dev_err(&pdev->dev, "could not register pinctrl driver\n"); + dev_err(dev, "could not register pinctrl driver\n"); return PTR_ERR(info->pctl_dev); } @@ -3613,8 +3604,9 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data( struct rockchip_pinctrl *d, struct platform_device *pdev) { + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; const struct of_device_id *match; - struct device_node *node = pdev->dev.of_node; struct rockchip_pin_ctrl *ctrl; struct rockchip_pin_bank *bank; int grf_offs, pmu_offs, drv_grf_offs, drv_pmu_offs, i, j; @@ -3671,7 +3663,7 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data( drv_pmu_offs : drv_grf_offs; } - dev_dbg(d->dev, "bank %d, iomux %d has iom_offset 0x%x drv_offset 0x%x\n", + dev_dbg(dev, "bank %d, iomux %d has iom_offset 0x%x drv_offset 0x%x\n", i, j, iom->offset, drv->offset); /* @@ -3820,8 +3812,8 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) { struct rockchip_pinctrl *info; struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node, *node; struct rockchip_pin_ctrl *ctrl; - struct device_node *np = pdev->dev.of_node, *node; struct resource *res; void __iomem *base; int ret; @@ -3858,8 +3850,8 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) rockchip_regmap_config.max_register = resource_size(res) - 4; rockchip_regmap_config.name = "rockchip,pinctrl"; - info->regmap_base = devm_regmap_init_mmio(&pdev->dev, base, - &rockchip_regmap_config); + info->regmap_base = + devm_regmap_init_mmio(dev, base, &rockchip_regmap_config); /* to check for the old dt-bindings */ info->reg_size = resource_size(res); @@ -3871,12 +3863,10 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - rockchip_regmap_config.max_register = - resource_size(res) - 4; + rockchip_regmap_config.max_register = resource_size(res) - 4; rockchip_regmap_config.name = "rockchip,pinctrl-pull"; - info->regmap_pull = devm_regmap_init_mmio(&pdev->dev, - base, - &rockchip_regmap_config); + info->regmap_pull = + devm_regmap_init_mmio(dev, base, &rockchip_regmap_config); } } @@ -3905,7 +3895,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) ret = of_platform_populate(np, rockchip_bank_match, NULL, NULL); if (ret) { - dev_err(&pdev->dev, "failed to register gpio device\n"); + dev_err(dev, "failed to register gpio device\n"); return ret; } dev_info(dev, "probed %s\n", dev_name(dev)); From 2ae7c84f1142dbc7f11905205c1afcc9f4f67537 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 5 Nov 2021 14:42:28 +0200 Subject: [PATCH 088/204] UPSTREAM: pinctrl/rockchip: Make use of the devm_platform_get_and_ioremap_resource() Use the devm_platform_get_and_ioremap_resource() helper instead of calling platform_get_resource() and devm_ioremap_resource() separately. Signed-off-by: Andy Shevchenko Reviewed-by: Heiko Stuebner (cherry picked from commit fb17dcd73fa9c772188724b63cbf5a3fdbb4e605) Signed-off-by: Jianqun Xu Change-Id: Idbdfaa90a0b614e59b393e436cebefb9aca6ffcc --- drivers/pinctrl/pinctrl-rockchip.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 2530c206dab3..a5f7408eea86 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -3843,8 +3843,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) if (IS_ERR(info->regmap_base)) return PTR_ERR(info->regmap_base); } else { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(base)) return PTR_ERR(base); @@ -3858,8 +3857,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) /* Honor the old binding, with pull registers as 2nd resource */ if (ctrl->type == RK3188 && info->reg_size < 0x200) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_get_and_ioremap_resource(pdev, 1, &res); if (IS_ERR(base)) return PTR_ERR(base); From 36318e1bfb085049ab0b09819b5db7867f171c95 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 5 Nov 2021 14:42:29 +0200 Subject: [PATCH 089/204] UPSTREAM: pinctrl/rockchip: Convert to use dev_err_probe() It's fine to call dev_err_probe() in ->probe() when error code is known. Convert the driver to use dev_err_probe(). Signed-off-by: Andy Shevchenko Reviewed-by: Heiko Stuebner (cherry picked from commit 0045028f318b58595596d7e53a88157923e83b0b) Signed-off-by: Jianqun Xu Change-Id: Id073cf03dc900550dae1c8a947e53693937b7de1 --- drivers/pinctrl/pinctrl-rockchip.c | 31 +++++++++++------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index a5f7408eea86..fdbdac1e6b3d 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -3429,10 +3429,8 @@ static int rockchip_pinctrl_parse_groups(struct device_node *np, list = of_get_property(np, "rockchip,pins", &size); /* we do not check return since it's safe node passed down */ size /= sizeof(*list); - if (!size || size % 4) { - dev_err(dev, "wrong pins number or pins and configs should be by 4\n"); - return -EINVAL; - } + if (!size || size % 4) + return dev_err_probe(dev, -EINVAL, "wrong pins number or pins and configs should be by 4\n"); grp->npins = size / 4; @@ -3587,10 +3585,8 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, return ret; info->pctl_dev = devm_pinctrl_register(dev, ctrldesc, info); - if (IS_ERR(info->pctl_dev)) { - dev_err(dev, "could not register pinctrl driver\n"); - return PTR_ERR(info->pctl_dev); - } + if (IS_ERR(info->pctl_dev)) + return dev_err_probe(dev, PTR_ERR(info->pctl_dev), "could not register pinctrl driver\n"); return 0; } @@ -3818,10 +3814,8 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) void __iomem *base; int ret; - if (!dev->of_node) { - dev_err(dev, "device tree node not found\n"); - return -ENODEV; - } + if (!dev->of_node) + return dev_err_probe(dev, -ENODEV, "device tree node not found\n"); info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); if (!info) @@ -3830,10 +3824,8 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) info->dev = dev; ctrl = rockchip_pinctrl_get_soc_data(info, pdev); - if (!ctrl) { - dev_err(dev, "driver data not available\n"); - return -EINVAL; - } + if (!ctrl) + return dev_err_probe(dev, -EINVAL, "driver data not available\n"); info->ctrl = ctrl; node = of_parse_phandle(np, "rockchip,grf", 0); @@ -3892,10 +3884,9 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) g_pctldev = info->pctl_dev; ret = of_platform_populate(np, rockchip_bank_match, NULL, NULL); - if (ret) { - dev_err(dev, "failed to register gpio device\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to register gpio device\n"); + dev_info(dev, "probed %s\n", dev_name(dev)); return 0; From 016473095c1e124ad5a857e80a8c1daf4eea0be8 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Wed, 21 Sep 2022 16:41:04 +0800 Subject: [PATCH 090/204] media: rockchip: vicap remove cru reset when stream off when doing cru reset, if there is an iommu operation, the device will be stuck Signed-off-by: Zefa Chen Change-Id: Id29878b0ee56e5f33ecd64c25b2c6f8b0bcdf491 --- drivers/media/platform/rockchip/cif/capture.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 9bddfb0f9d5a..87ad681c6393 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -4028,7 +4028,6 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, if (dev->can_be_reset && dev->chip_id >= CHIP_RK3588_CIF) rkcif_do_soft_reset(dev); if (dev->can_be_reset && can_reset) { - rkcif_do_cru_reset(dev); dev->can_be_reset = false; dev->reset_work_cancel = true; dev->early_line = 0; From f37a9465ce88df9322bb208b7b9b72a2809b2fe4 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Fri, 26 Nov 2021 15:13:52 +0000 Subject: [PATCH 091/204] UPSTREAM: pinctrl/rockchip: fix gpio device creation GPIO nodes are not themselves busses, so passing rockchip_bank_match here is wrong. Passing NULL instead uses the standard bus match table which is more appropriate. devm_of_platform_populate() shows that this is the normal way to call of_platform_populate() from a device driver, so in order to match that more closely also add the pinctrl device as the parent for the newly created GPIO controllers. Specifically, using the wrong match here can break dynamic GPIO hogs as marking the GPIO bank as a bus means that of_platform_notify() will set OF_POPULATED on new child nodes and if this happens before of_gpio_notify() is called then the new hog will be skipped as OF_POPULATED is already set. Fixes: 9ce9a02039de ("pinctrl/rockchip: drop the gpio related codes") Signed-off-by: John Keeping Link: https://lore.kernel.org/r/20211126151352.1509583-1-john@metanate.com Signed-off-by: Linus Walleij (cherry picked from commit bceb6732f3fd2a55d8f2e518cced1c7555e216b6) Signed-off-by: Jianqun Xu Change-Id: I21e0944d239cc85598b2638c952abadd85f55148 --- drivers/pinctrl/pinctrl-rockchip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index fdbdac1e6b3d..c521a2c3d5b4 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -3883,7 +3883,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, info); g_pctldev = info->pctl_dev; - ret = of_platform_populate(np, rockchip_bank_match, NULL, NULL); + ret = of_platform_populate(np, NULL, NULL, &pdev->dev); if (ret) return dev_err_probe(dev, ret, "failed to register gpio device\n"); From fd1e3e6b9340c5dd59cdb6cc591a0e1abf99d5b7 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 28 Mar 2022 01:50:02 +0100 Subject: [PATCH 092/204] UPSTREAM: pinctrl/rockchip: support deferring other gpio params Add support for deferring other params like PIN_CONFIG_INPUT_ENABLE. This will be used to add support for PIN_CONFIG_INPUT_ENABLE to the driver. Fixes: e7165b1dff06 ("pinctrl/rockchip: add a queue for deferred pin output settings on probe") Fixes: 59dd178e1d7c ("gpio/rockchip: fetch deferred output settings on probe") Signed-off-by: Caleb Connolly Link: https://lore.kernel.org/r/20220328005005.72492-2-kc@postmarketos.org Signed-off-by: Linus Walleij (cherry picked from commit 8ce5ef64546850294b021497046588a7abcebe96) Signed-off-by: Jianqun Xu Change-Id: I7935986c9fdff1d74f5ccd08e2457d1f50d3bf35 --- drivers/gpio/gpio-rockchip.c | 23 ++++++++----- drivers/pinctrl/pinctrl-rockchip.c | 54 ++++++++++++++++-------------- drivers/pinctrl/pinctrl-rockchip.h | 7 ++-- 3 files changed, 49 insertions(+), 35 deletions(-) diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index 36d81c7efec5..e4e16ba551be 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -777,20 +777,27 @@ static int rockchip_gpio_probe(struct platform_device *pdev) } } - while (!list_empty(&bank->deferred_output)) { - struct rockchip_pin_output_deferred *cfg; + while (!list_empty(&bank->deferred_pins)) { + struct rockchip_pin_deferred *cfg; - cfg = list_first_entry(&bank->deferred_output, - struct rockchip_pin_output_deferred, head); + cfg = list_first_entry(&bank->deferred_pins, + struct rockchip_pin_deferred, head); if (!cfg) break; list_del(&cfg->head); - ret = rockchip_gpio_direction_output(&bank->gpio_chip, cfg->pin, cfg->arg); - if (ret) - dev_warn(dev, "setting output pin %u to %u failed\n", cfg->pin, cfg->arg); - + switch (cfg->param) { + case PIN_CONFIG_OUTPUT: + ret = rockchip_gpio_direction_output(&bank->gpio_chip, cfg->pin, cfg->arg); + if (ret) + dev_warn(dev, "setting output pin %u to %u failed\n", cfg->pin, + cfg->arg); + break; + default: + dev_warn(dev, "unknown deferred config param %d\n", cfg->param); + break; + } kfree(cfg); } diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index c521a2c3d5b4..2733b2cbe0af 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -3174,19 +3174,20 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl, return false; } -static int rockchip_pinconf_defer_output(struct rockchip_pin_bank *bank, - unsigned int pin, u32 arg) +static int rockchip_pinconf_defer_pin(struct rockchip_pin_bank *bank, + unsigned int pin, u32 param, u32 arg) { - struct rockchip_pin_output_deferred *cfg; + struct rockchip_pin_deferred *cfg; cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); if (!cfg) return -ENOMEM; cfg->pin = pin; + cfg->param = param; cfg->arg = arg; - list_add_tail(&cfg->head, &bank->deferred_output); + list_add_tail(&cfg->head, &bank->deferred_pins); return 0; } @@ -3207,6 +3208,25 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, param = pinconf_to_config_param(configs[i]); arg = pinconf_to_config_argument(configs[i]); + if (param == (PIN_CONFIG_OUTPUT | PIN_CONFIG_INPUT_ENABLE)) { + /* + * Check for gpio driver not being probed yet. + * The lock makes sure that either gpio-probe has completed + * or the gpio driver hasn't probed yet. + */ + mutex_lock(&bank->deferred_lock); + if (!gpio || !gpio->direction_output) { + rc = rockchip_pinconf_defer_pin(bank, pin - bank->pin_base, param, + arg); + mutex_unlock(&bank->deferred_lock); + if (rc) + return rc; + + break; + } + mutex_unlock(&bank->deferred_lock); + } + switch (param) { case PIN_CONFIG_BIAS_DISABLE: rc = rockchip_set_pull(bank, pin - bank->pin_base, @@ -3235,22 +3255,6 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, if (rc != RK_FUNC_GPIO) return -EINVAL; - /* - * Check for gpio driver not being probed yet. - * The lock makes sure that either gpio-probe has completed - * or the gpio driver hasn't probed yet. - */ - mutex_lock(&bank->deferred_lock); - if (!gpio || !gpio->direction_output) { - rc = rockchip_pinconf_defer_output(bank, pin - bank->pin_base, arg); - mutex_unlock(&bank->deferred_lock); - if (rc) - return rc; - - break; - } - mutex_unlock(&bank->deferred_lock); - rc = gpio->direction_output(gpio, pin - bank->pin_base, arg); if (rc) @@ -3576,7 +3580,7 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, pdesc++; } - INIT_LIST_HEAD(&pin_bank->deferred_output); + INIT_LIST_HEAD(&pin_bank->deferred_pins); mutex_init(&pin_bank->deferred_lock); } @@ -3896,7 +3900,7 @@ static int rockchip_pinctrl_remove(struct platform_device *pdev) { struct rockchip_pinctrl *info = platform_get_drvdata(pdev); struct rockchip_pin_bank *bank; - struct rockchip_pin_output_deferred *cfg; + struct rockchip_pin_deferred *cfg; int i; g_pctldev = NULL; @@ -3906,9 +3910,9 @@ static int rockchip_pinctrl_remove(struct platform_device *pdev) bank = &info->ctrl->pin_banks[i]; mutex_lock(&bank->deferred_lock); - while (!list_empty(&bank->deferred_output)) { - cfg = list_first_entry(&bank->deferred_output, - struct rockchip_pin_output_deferred, head); + while (!list_empty(&bank->deferred_pins)) { + cfg = list_first_entry(&bank->deferred_pins, + struct rockchip_pin_deferred, head); list_del(&cfg->head); kfree(cfg); } diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h index de40db3244fc..b7361f04244f 100644 --- a/drivers/pinctrl/pinctrl-rockchip.h +++ b/drivers/pinctrl/pinctrl-rockchip.h @@ -343,7 +343,7 @@ struct rockchip_pin_bank { u32 toggle_edge_mode; u32 recalced_mask; u32 route_mask; - struct list_head deferred_output; + struct list_head deferred_pins; struct mutex deferred_lock; }; @@ -426,9 +426,12 @@ struct rockchip_pin_config { unsigned int nconfigs; }; -struct rockchip_pin_output_deferred { +enum pin_config_param; + +struct rockchip_pin_deferred { struct list_head head; unsigned int pin; + enum pin_config_param param; u32 arg; }; From 3f81f50a8542b665a43cec811dc1e80799779b93 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Mon, 28 Mar 2022 01:50:03 +0100 Subject: [PATCH 093/204] UPSTREAM: pinctrl/rockchip: support setting input-enable param Handle the PIN_CONFIG_INPUT_ENABLE param for configuring GPIOs as input. Signed-off-by: Caleb Connolly Link: https://lore.kernel.org/r/20220328005005.72492-3-kc@postmarketos.org Signed-off-by: Linus Walleij (cherry picked from commit 42d90a1e5caf73138ddde42da5a9fe2b543f9a2c) Signed-off-by: Jianqun Xu Change-Id: Iefcccf3b9b9ccb5f6729e304ad4ef38664018212 --- drivers/pinctrl/pinctrl-rockchip.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 2733b2cbe0af..bbf03b7280cf 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -3208,7 +3208,7 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, param = pinconf_to_config_param(configs[i]); arg = pinconf_to_config_argument(configs[i]); - if (param == (PIN_CONFIG_OUTPUT | PIN_CONFIG_INPUT_ENABLE)) { + if (param == PIN_CONFIG_OUTPUT || param == PIN_CONFIG_INPUT_ENABLE) { /* * Check for gpio driver not being probed yet. * The lock makes sure that either gpio-probe has completed @@ -3260,6 +3260,16 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, if (rc) return rc; break; + case PIN_CONFIG_INPUT_ENABLE: + rc = rockchip_set_mux(bank, pin - bank->pin_base, + RK_FUNC_GPIO); + if (rc != RK_FUNC_GPIO) + return -EINVAL; + + rc = gpio->direction_input(gpio, pin - bank->pin_base); + if (rc) + return rc; + break; case PIN_CONFIG_DRIVE_STRENGTH: /* rk3288 is the first with per-pin drive-strength */ if (!info->ctrl->drv_calc_reg) From ae7b9050a3f250a4ac02d6805127310178217167 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 20 Apr 2022 16:24:31 +0200 Subject: [PATCH 094/204] UPSTREAM: pinctrl: rockchip: fix RK3308 pinmux bits Some of the pinmuxing bits described in rk3308_mux_recalced_data are wrong, pointing to non-existing registers. Fix the entire table. Also add a comment in front of each entry with the same string that appears in the datasheet to make the table easier to compare with the docs. This fix has been tested on real hardware for the gpio3b3_sel entry. Fixes: 7825aeb7b208 ("pinctrl: rockchip: add rk3308 SoC support") Signed-off-by: Luca Ceresoli Reviewed-by: Heiko Stuebner Link: https://lore.kernel.org/r/20220420142432.248565-1-luca.ceresoli@bootlin.com Signed-off-by: Linus Walleij (cherry picked from commit 1f3e25a068832f8892a5ff71467622d012f5bc9f) Signed-off-by: Jianqun Xu Change-Id: Ide1ec0fdd675a29e3359049beb7777ec13b49738 --- drivers/pinctrl/pinctrl-rockchip.c | 45 ++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index bbf03b7280cf..3cd054d23e55 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -535,95 +535,110 @@ static struct rockchip_mux_recalced_data rk3128_mux_recalced_data[] = { static struct rockchip_mux_recalced_data rk3308_mux_recalced_data[] = { { + /* gpio1b6_sel */ .num = 1, .pin = 14, .reg = 0x28, .bit = 12, .mask = 0xf }, { + /* gpio1b7_sel */ .num = 1, .pin = 15, .reg = 0x2c, .bit = 0, .mask = 0x3 }, { + /* gpio1c2_sel */ .num = 1, .pin = 18, .reg = 0x30, .bit = 4, .mask = 0xf }, { + /* gpio1c3_sel */ .num = 1, .pin = 19, .reg = 0x30, .bit = 8, .mask = 0xf }, { + /* gpio1c4_sel */ .num = 1, .pin = 20, .reg = 0x30, .bit = 12, .mask = 0xf }, { + /* gpio1c5_sel */ .num = 1, .pin = 21, .reg = 0x34, .bit = 0, .mask = 0xf }, { + /* gpio1c6_sel */ .num = 1, .pin = 22, .reg = 0x34, .bit = 4, .mask = 0xf }, { + /* gpio1c7_sel */ .num = 1, .pin = 23, .reg = 0x34, .bit = 8, .mask = 0xf }, { + /* gpio3b4_sel */ .num = 3, .pin = 12, .reg = 0x68, .bit = 8, .mask = 0xf }, { + /* gpio3b5_sel */ .num = 3, .pin = 13, .reg = 0x68, .bit = 12, .mask = 0xf }, { + /* gpio2a2_sel */ .num = 2, .pin = 2, - .reg = 0x608, - .bit = 0, - .mask = 0x7 + .reg = 0x40, + .bit = 4, + .mask = 0x3 }, { + /* gpio2a3_sel */ .num = 2, .pin = 3, - .reg = 0x608, - .bit = 4, - .mask = 0x7 + .reg = 0x40, + .bit = 6, + .mask = 0x3 }, { + /* gpio2c0_sel */ .num = 2, .pin = 16, - .reg = 0x610, - .bit = 8, - .mask = 0x7 + .reg = 0x50, + .bit = 0, + .mask = 0x3 }, { + /* gpio3b2_sel */ .num = 3, .pin = 10, - .reg = 0x610, - .bit = 0, - .mask = 0x7 + .reg = 0x68, + .bit = 4, + .mask = 0x3 }, { + /* gpio3b3_sel */ .num = 3, .pin = 11, - .reg = 0x610, - .bit = 4, - .mask = 0x7 + .reg = 0x68, + .bit = 6, + .mask = 0x3 }, }; From f9dd52afac5f76af14408e3e38adf3cfb7a36868 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 20 Apr 2022 16:24:32 +0200 Subject: [PATCH 095/204] UPSTREAM: pinctrl: rockchip: sort the rk3308_mux_recalced_data entries All the entries are sorted according to num/pin except for two entries. Sort them too. Signed-off-by: Luca Ceresoli Reviewed-by: Heiko Stuebner Link: https://lore.kernel.org/r/20220420142432.248565-2-luca.ceresoli@bootlin.com Signed-off-by: Linus Walleij (cherry picked from commit 7c4cffc5d473e87ae2eaa50aed8cb27d17bcd1ec) Signed-off-by: Jianqun Xu Change-Id: I4f58ebf64d3acba726c3d4c90a0a9796d47d514a --- drivers/pinctrl/pinctrl-rockchip.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 3cd054d23e55..98c6d2b1e851 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -590,20 +590,6 @@ static struct rockchip_mux_recalced_data rk3308_mux_recalced_data[] = { .reg = 0x34, .bit = 8, .mask = 0xf - }, { - /* gpio3b4_sel */ - .num = 3, - .pin = 12, - .reg = 0x68, - .bit = 8, - .mask = 0xf - }, { - /* gpio3b5_sel */ - .num = 3, - .pin = 13, - .reg = 0x68, - .bit = 12, - .mask = 0xf }, { /* gpio2a2_sel */ .num = 2, @@ -639,6 +625,20 @@ static struct rockchip_mux_recalced_data rk3308_mux_recalced_data[] = { .reg = 0x68, .bit = 6, .mask = 0x3 + }, { + /* gpio3b4_sel */ + .num = 3, + .pin = 12, + .reg = 0x68, + .bit = 8, + .mask = 0xf + }, { + /* gpio3b5_sel */ + .num = 3, + .pin = 13, + .reg = 0x68, + .bit = 12, + .mask = 0xf }, }; From 48401c5ee2d17c13306adcb06d5eed2a30aa8560 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Fri, 22 Apr 2022 19:09:13 +0200 Subject: [PATCH 096/204] UPSTREAM: pinctrl/rockchip: add error handling for pull/drive register getters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add error handling for the pull and driver register getters in preparation for RK3588 support. Signed-off-by: Sebastian Reichel Reviewed-by: Heiko Stübner Link: https://lore.kernel.org/r/20220422170920.401914-13-sebastian.reichel@collabora.com Signed-off-by: Linus Walleij (cherry picked from commit 42573ab3b9f94fbeba8b84e142703ea551624f6d) Fix more error handling for codes havn't upstream yet. Signed-off-by: Jianqun Xu Change-Id: Ieb9f502c702ce4ac97fbfc1c426d072f4253f1d2 --- drivers/pinctrl/pinctrl-rockchip.c | 239 ++++++++++++++++++----------- drivers/pinctrl/pinctrl-rockchip.h | 12 +- 2 files changed, 157 insertions(+), 94 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 98c6d2b1e851..76b858b44591 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -1316,9 +1316,9 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) #define PX30_PULL_PINS_PER_REG 8 #define PX30_PULL_BANK_STRIDE 16 -static void px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1338,6 +1338,8 @@ static void px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / PX30_PULL_PINS_PER_REG) * 4); *bit = (pin_num % PX30_PULL_PINS_PER_REG); *bit *= PX30_PULL_BITS_PER_PIN; + + return 0; } #define PX30_DRV_PMU_OFFSET 0x20 @@ -1346,9 +1348,9 @@ static void px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define PX30_DRV_PINS_PER_REG 8 #define PX30_DRV_BANK_STRIDE 16 -static void px30_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int px30_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1368,6 +1370,8 @@ static void px30_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / PX30_DRV_PINS_PER_REG) * 4); *bit = (pin_num % PX30_DRV_PINS_PER_REG); *bit *= PX30_DRV_BITS_PER_PIN; + + return 0; } #define PX30_SCHMITT_PMU_OFFSET 0x38 @@ -1409,9 +1413,9 @@ static int px30_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, #define RV1106_DRV_GPIO3_OFFSET 0x20100 #define RV1106_DRV_GPIO4_OFFSET 0x30020 -static void rv1106_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rv1106_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1450,6 +1454,8 @@ static void rv1106_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RV1106_DRV_PINS_PER_REG) * 4); *bit = pin_num % RV1106_DRV_PINS_PER_REG; *bit *= RV1106_DRV_BITS_PER_PIN; + + return 0; } #define RV1106_PULL_BITS_PER_PIN 2 @@ -1460,9 +1466,9 @@ static void rv1106_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, #define RV1106_PULL_GPIO3_OFFSET 0x201E0 #define RV1106_PULL_GPIO4_OFFSET 0x30070 -static void rv1106_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rv1106_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1501,6 +1507,8 @@ static void rv1106_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RV1106_PULL_PINS_PER_REG) * 4); *bit = pin_num % RV1106_PULL_PINS_PER_REG; *bit *= RV1106_PULL_BITS_PER_PIN; + + return 0; } #define RV1106_SMT_BITS_PER_PIN 1 @@ -1563,9 +1571,9 @@ static int rv1106_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, #define RV1108_PULL_BITS_PER_PIN 2 #define RV1108_PULL_BANK_STRIDE 16 -static void rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1584,6 +1592,8 @@ static void rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RV1108_PULL_PINS_PER_REG) * 4); *bit = (pin_num % RV1108_PULL_PINS_PER_REG); *bit *= RV1108_PULL_BITS_PER_PIN; + + return 0; } #define RV1108_DRV_PMU_OFFSET 0x20 @@ -1592,9 +1602,9 @@ static void rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define RV1108_DRV_PINS_PER_REG 8 #define RV1108_DRV_BANK_STRIDE 16 -static void rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1614,6 +1624,8 @@ static void rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RV1108_DRV_PINS_PER_REG) * 4); *bit = pin_num % RV1108_DRV_PINS_PER_REG; *bit *= RV1108_DRV_BITS_PER_PIN; + + return 0; } #define RV1108_SCHMITT_PMU_OFFSET 0x30 @@ -1653,9 +1665,9 @@ static int rv1108_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, #define RV1126_PULL_BANK_STRIDE 16 #define RV1126_GPIO_C4_D7(p) (p >= 20 && p <= 31) /* GPIO0_C4 ~ GPIO0_D7 */ -static void rv1126_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rv1126_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1667,7 +1679,7 @@ static void rv1126_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg -= (((31 - pin_num) / RV1126_PULL_PINS_PER_REG + 1) * 4); *bit = pin_num % RV1126_PULL_PINS_PER_REG; *bit *= RV1126_PULL_BITS_PER_PIN; - return; + return 0; } *regmap = info->regmap_pmu; *reg = RV1126_PULL_PMU_OFFSET; @@ -1680,6 +1692,8 @@ static void rv1126_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RV1126_PULL_PINS_PER_REG) * 4); *bit = (pin_num % RV1126_PULL_PINS_PER_REG); *bit *= RV1126_PULL_BITS_PER_PIN; + + return 0; } #define RV1126_DRV_PMU_OFFSET 0x20 @@ -1688,9 +1702,9 @@ static void rv1126_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define RV1126_DRV_PINS_PER_REG 4 #define RV1126_DRV_BANK_STRIDE 32 -static void rv1126_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rv1126_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1703,7 +1717,7 @@ static void rv1126_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *reg -= 0x4; *bit = pin_num % RV1126_DRV_PINS_PER_REG; *bit *= RV1126_DRV_BITS_PER_PIN; - return; + return 0; } *regmap = info->regmap_pmu; *reg = RV1126_DRV_PMU_OFFSET; @@ -1716,6 +1730,8 @@ static void rv1126_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RV1126_DRV_PINS_PER_REG) * 4); *bit = pin_num % RV1126_DRV_PINS_PER_REG; *bit *= RV1126_DRV_BITS_PER_PIN; + + return 0; } #define RV1126_SCHMITT_PMU_OFFSET 0x60 @@ -1781,9 +1797,9 @@ static int rk3308_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, #define RK1808_PULL_BITS_PER_PIN 2 #define RK1808_PULL_BANK_STRIDE 16 -static void rk1808_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk1808_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1799,6 +1815,8 @@ static void rk1808_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RK1808_PULL_PINS_PER_REG) * 4); *bit = (pin_num % RK1808_PULL_PINS_PER_REG); *bit *= RK1808_PULL_BITS_PER_PIN; + + return 0; } #define RK1808_DRV_PMU_OFFSET 0x20 @@ -1807,10 +1825,10 @@ static void rk1808_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define RK1808_DRV_PINS_PER_REG 8 #define RK1808_DRV_BANK_STRIDE 16 -static void rk1808_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, - struct regmap **regmap, - int *reg, u8 *bit) +static int rk1808_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, + struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1826,6 +1844,8 @@ static void rk1808_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RK1808_DRV_PINS_PER_REG) * 4); *bit = pin_num % RK1808_DRV_PINS_PER_REG; *bit *= RK1808_DRV_BITS_PER_PIN; + + return 0; } #define RK1808_SR_PMU_OFFSET 0x0030 @@ -1884,9 +1904,9 @@ static int rk1808_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, #define RK2928_PULL_PINS_PER_REG 16 #define RK2928_PULL_BANK_STRIDE 8 -static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1896,13 +1916,15 @@ static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += (pin_num / RK2928_PULL_PINS_PER_REG) * 4; *bit = pin_num % RK2928_PULL_PINS_PER_REG; + + return 0; }; #define RK3128_PULL_OFFSET 0x118 -static void rk3128_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3128_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1912,6 +1934,8 @@ static void rk3128_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RK2928_PULL_PINS_PER_REG) * 4); *bit = pin_num % RK2928_PULL_PINS_PER_REG; + + return 0; } #define RK3188_PULL_OFFSET 0x164 @@ -1920,9 +1944,9 @@ static void rk3128_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define RK3188_PULL_BANK_STRIDE 16 #define RK3188_PULL_PMU_OFFSET 0x64 -static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1952,12 +1976,14 @@ static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = 7 - (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; } + + return 0; } #define RK3288_PULL_OFFSET 0x140 -static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1981,6 +2007,8 @@ static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; } + + return 0; } #define RK3288_DRV_PMU_OFFSET 0x70 @@ -1989,9 +2017,9 @@ static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define RK3288_DRV_PINS_PER_REG 8 #define RK3288_DRV_BANK_STRIDE 16 -static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -2015,13 +2043,15 @@ static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3288_DRV_PINS_PER_REG); *bit *= RK3288_DRV_BITS_PER_PIN; } + + return 0; } #define RK3228_PULL_OFFSET 0x100 -static void rk3228_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3228_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -2032,13 +2062,15 @@ static void rk3228_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; + + return 0; } #define RK3228_DRV_GRF_OFFSET 0x200 -static void rk3228_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3228_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -2049,13 +2081,15 @@ static void rk3228_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3288_DRV_PINS_PER_REG); *bit *= RK3288_DRV_BITS_PER_PIN; + + return 0; } #define RK3308_PULL_OFFSET 0xa0 -static void rk3308_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3308_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -2066,13 +2100,15 @@ static void rk3308_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; + + return 0; } #define RK3308_DRV_GRF_OFFSET 0x100 -static void rk3308_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3308_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -2083,6 +2119,8 @@ static void rk3308_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3288_DRV_PINS_PER_REG); *bit *= RK3288_DRV_BITS_PER_PIN; + + return 0; } #define RK3308_SLEW_RATE_GRF_OFFSET 0x150 @@ -2111,9 +2149,9 @@ static int rk3308_calc_slew_rate_reg_and_bit(struct rockchip_pin_bank *bank, #define RK3368_PULL_GRF_OFFSET 0x100 #define RK3368_PULL_PMU_OFFSET 0x10 -static void rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -2137,14 +2175,16 @@ static void rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; } + + return 0; } #define RK3368_DRV_PMU_OFFSET 0x20 #define RK3368_DRV_GRF_OFFSET 0x200 -static void rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -2168,15 +2208,17 @@ static void rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3288_DRV_PINS_PER_REG); *bit *= RK3288_DRV_BITS_PER_PIN; } + + return 0; } #define RK3399_PULL_GRF_OFFSET 0xe040 #define RK3399_PULL_PMU_OFFSET 0x40 #define RK3399_DRV_3BITS_PER_PIN 3 -static void rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -2202,11 +2244,13 @@ static void rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; } + + return 0; } -static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; int drv_num = (pin_num / 8); @@ -2223,6 +2267,8 @@ static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % 8) * 3; else *bit = (pin_num % 8) * 2; + + return 0; } #define RK3568_SR_PMU_OFFSET 0x60 @@ -2259,9 +2305,9 @@ static int rk3568_calc_slew_rate_reg_and_bit(struct rockchip_pin_bank *bank, #define RK3568_PULL_PINS_PER_REG 8 #define RK3568_PULL_BANK_STRIDE 0x10 -static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -2282,6 +2328,8 @@ static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3568_PULL_PINS_PER_REG); *bit *= RK3568_PULL_BITS_PER_PIN; } + + return 0; } #define RK3568_DRV_PMU_OFFSET 0x70 @@ -2290,9 +2338,9 @@ static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define RK3568_DRV_PINS_PER_REG 2 #define RK3568_DRV_BANK_STRIDE 0x40 -static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -2319,6 +2367,8 @@ static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, ((bank->bank_num == 2 || bank->bank_num == 3 || bank->bank_num == 4) && (pin_num == 7 || pin_num == 15 || pin_num == 23 || pin_num == 31))) *bit -= RK3568_DRV_BITS_PER_PIN; + + return 0; } #define RK3588_PMU1_IOC_REG 0x0000 @@ -2428,9 +2478,9 @@ static const u32 rk3588_smt_regs[][2] = { #define RK3588_PULL_BITS_PER_PIN 2 #define RK3588_PULL_PINS_PER_REG 8 -static void rk3588_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3588_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; u8 bank_num = bank->bank_num; @@ -2449,14 +2499,16 @@ static void rk3588_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin - rk3588_p_regs[i][0]) / RK3588_PULL_PINS_PER_REG) * 4; *bit = pin_num % RK3588_PULL_PINS_PER_REG; *bit *= RK3588_PULL_BITS_PER_PIN; + + return 0; } #define RK3588_DRV_BITS_PER_PIN 4 #define RK3588_DRV_PINS_PER_REG 4 -static void rk3588_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3588_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; u8 bank_num = bank->bank_num; @@ -2475,6 +2527,8 @@ static void rk3588_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin - rk3588_ds_regs[i][0]) / RK3588_DRV_PINS_PER_REG) * 4; *bit = pin_num % RK3588_DRV_PINS_PER_REG; *bit *= RK3588_DRV_BITS_PER_PIN; + + return 0; } #define RK3588_SMT_BITS_PER_PIN 1 @@ -2527,7 +2581,9 @@ static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank, u8 bit; int drv_type = bank->drv[pin_num / 8].drv_type; - ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); + ret = ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); + if (ret) + return ret; switch (drv_type) { case DRV_TYPE_IO_1V8_3V0_AUTO: @@ -2622,7 +2678,10 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, dev_dbg(dev, "setting drive of GPIO%d-%d to %d\n", bank->bank_num, pin_num, strength); - ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); + ret = ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); + if (ret) + return ret; + if (ctrl->type == RV1126 || ctrl->type == RK3588) { rmask_bits = RV1126_DRV_BITS_PER_PIN; ret = strength; @@ -2775,7 +2834,9 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) if (ctrl->type == RK3066B) return PIN_CONFIG_BIAS_DISABLE; - ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); + ret = ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); + if (ret) + return ret; ret = regmap_read(regmap, reg, &data); if (ret) @@ -2827,7 +2888,9 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, if (ctrl->type == RK3066B) return pull ? -EINVAL : 0; - ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); + ret = ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); + if (ret) + return ret; switch (ctrl->type) { case RK2928: diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h index b7361f04244f..1642432513fd 100644 --- a/drivers/pinctrl/pinctrl-rockchip.h +++ b/drivers/pinctrl/pinctrl-rockchip.h @@ -406,12 +406,12 @@ struct rockchip_pin_ctrl { int (*soc_data_init)(struct rockchip_pinctrl *info); - void (*pull_calc_reg)(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit); - void (*drv_calc_reg)(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit); + int (*pull_calc_reg)(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit); + int (*drv_calc_reg)(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit); int (*schmitt_calc_reg)(struct rockchip_pin_bank *bank, int pin_num, struct regmap **regmap, int *reg, u8 *bit); From a648efab5ea2866d34843093083998bf1469db76 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Wed, 7 Sep 2022 11:26:51 +0800 Subject: [PATCH 097/204] phy: rockchip-naneng-combo: Add ssc support for pcie Best parameter: 24M T0_1 650mV. Should co-work with change like below: &combphy0_ps { + rockchip,enable-ssc; + assigned-clock-rates = <24000000>; status = "okay"; }; Signed-off-by: Kever Yang Change-Id: I863b8d1758431c0037332e7da1b2c64cd7113573 --- .../rockchip/phy-rockchip-naneng-combphy.c | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c index 6f7aa8ebc292..f32b831b941b 100644 --- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c @@ -664,6 +664,12 @@ static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv) switch (priv->mode) { case PHY_TYPE_PCIE: + /* Set SSC downward spread spectrum */ + val = readl(priv->mmio + (0x1f << 2)); + val &= ~GENMASK(5, 4); + val |= 0x01 << 4; + writel(val, priv->mmio + 0x7c); + param_write(priv->phy_grf, &cfg->con0_for_pcie, true); param_write(priv->phy_grf, &cfg->con1_for_pcie, true); param_write(priv->phy_grf, &cfg->con2_for_pcie, true); @@ -841,6 +847,26 @@ static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv) } } + if (device_property_read_bool(priv->dev, "rockchip,enable-ssc")) { + val = readl(priv->mmio + (0x7 << 2)); + val |= BIT(4); + writel(val, priv->mmio + (0x7 << 2)); + + if (priv->mode == PHY_TYPE_PCIE && rate == 24000000) { + /* Xin24M T0_1 650mV */ + writel(0x00, priv->mmio + (0x10 << 2)); + writel(0x32, priv->mmio + (0x11 << 2)); + writel(0x00, priv->mmio + (0x1b << 2)); + writel(0x90, priv->mmio + (0x0a << 2)); + writel(0x02, priv->mmio + (0x0b << 2)); + writel(0x08, priv->mmio + (0x0c << 2)); + writel(0x57, priv->mmio + (0x0d << 2)); + writel(0x40, priv->mmio + (0x0e << 2)); + writel(0x5f, priv->mmio + (0x0f << 2)); + writel(0x10, priv->mmio + (0x20 << 2)); + } + } + return 0; } From fb41ff66cbe78eb11145bc311ff94ca096ebc05a Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Wed, 14 Sep 2022 10:00:45 +0000 Subject: [PATCH 098/204] fs: pstore: rename mcu log to boot log It is not only for mcu log now, includes tpl, spl, uboot, atf, optee and so on. Signed-off-by: Huibin Hong Change-Id: Ia3bb0db39edf9cfba2ef41982a6134f0f20c5d53 --- fs/pstore/Kconfig | 6 +-- fs/pstore/inode.c | 8 ++-- fs/pstore/platform.c | 4 +- fs/pstore/ram.c | 91 +++++++++++++++++++------------------- include/linux/pstore.h | 8 ++-- include/linux/pstore_ram.h | 10 ++--- 6 files changed, 63 insertions(+), 64 deletions(-) diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 45e20bfa427c..d51c74600f96 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -264,10 +264,10 @@ config PSTORE_BLK_FTRACE_SIZE NOTE that, both Kconfig and module parameters can configure pstore/blk, but module parameters have priority over Kconfig. -config PSTORE_MCU_LOG - bool "Print mcu log by linux" +config PSTORE_BOOT_LOG + bool "Print boot log by linux" depends on PSTORE help - When your soc has several mcu, you can get their log by cat command + Collect log from loader,uboot,ATF and so on, you can get their log by cat command through linux shell If unsure, say N. diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 32318e6d6519..29c91fda081d 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -24,7 +24,7 @@ #include #include -#ifdef CONFIG_PSTORE_MCU_LOG +#ifdef CONFIG_PSTORE_BOOT_LOG #include #include #endif @@ -135,12 +135,12 @@ static ssize_t pstore_file_read(struct file *file, char __user *userbuf, { struct seq_file *sf = file->private_data; struct pstore_private *ps = sf->private; -#ifdef CONFIG_PSTORE_MCU_LOG +#ifdef CONFIG_PSTORE_BOOT_LOG size_t size = 0; struct pstore_record *record = ps->record; - if (record->type == PSTORE_TYPE_MCU_LOG) { - size = ramoops_pstore_read_for_mcu_log(ps->record); + if (record->type == PSTORE_TYPE_BOOT_LOG) { + size = ramoops_pstore_read_for_boot_log(ps->record); size = simple_read_from_buffer(userbuf, count, ppos, record->buf, size); return size; } diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 1673f3cb23f3..417582b41757 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -58,8 +58,8 @@ static const char * const pstore_type_names[] = { "powerpc-common", "pmsg", "powerpc-opal", -#ifdef CONFIG_PSTORE_MCU_LOG - "mcu-log", +#ifdef CONFIG_PSTORE_BOOT_LOG + "boot-log", #endif }; diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 026782e95c74..143e94395987 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -81,8 +81,8 @@ struct ramoops_context { struct persistent_ram_zone *cprz; /* Console zone */ struct persistent_ram_zone **fprzs; /* Ftrace zones */ struct persistent_ram_zone *mprz; /* PMSG zone */ -#ifdef CONFIG_PSTORE_MCU_LOG - struct persistent_ram_zone **mcu_przs; /* MCU log zones */ +#ifdef CONFIG_PSTORE_BOOT_LOG + struct persistent_ram_zone **boot_przs; /* BOOT log zones */ #endif phys_addr_t phys_addr; unsigned long size; @@ -91,8 +91,8 @@ struct ramoops_context { size_t console_size; size_t ftrace_size; size_t pmsg_size; -#ifdef CONFIG_PSTORE_MCU_LOG - size_t mcu_log_size; +#ifdef CONFIG_PSTORE_BOOT_LOG + size_t boot_log_size; #endif u32 flags; struct persistent_ram_ecc_info ecc_info; @@ -104,9 +104,9 @@ struct ramoops_context { unsigned int max_ftrace_cnt; unsigned int ftrace_read_cnt; unsigned int pmsg_read_cnt; -#ifdef CONFIG_PSTORE_MCU_LOG - unsigned int mcu_log_read_cnt; - unsigned int max_mcu_log_cnt; +#ifdef CONFIG_PSTORE_BOOT_LOG + unsigned int boot_log_read_cnt; + unsigned int max_boot_log_cnt; #endif struct pstore_info pstore; }; @@ -184,8 +184,8 @@ static bool prz_ok(struct persistent_ram_zone *prz) persistent_ram_ecc_string(prz, NULL, 0)); } -#ifdef CONFIG_PSTORE_MCU_LOG -ssize_t ramoops_pstore_read_for_mcu_log(struct pstore_record *record) +#ifdef CONFIG_PSTORE_BOOT_LOG +ssize_t ramoops_pstore_read_for_boot_log(struct pstore_record *record) { struct ramoops_context *cxt = record->psi->data; struct persistent_ram_zone *prz; @@ -193,7 +193,7 @@ ssize_t ramoops_pstore_read_for_mcu_log(struct pstore_record *record) if (!cxt) return 0; - prz = cxt->mcu_przs[record->id]; + prz = cxt->boot_przs[record->id]; if (!prz) return 0; @@ -290,10 +290,10 @@ static ssize_t ramoops_pstore_read(struct pstore_record *record) } } -#ifdef CONFIG_PSTORE_MCU_LOG +#ifdef CONFIG_PSTORE_BOOT_LOG if (!prz_ok(prz)) { - while (cxt->mcu_log_read_cnt < cxt->max_mcu_log_cnt && !prz) { - prz = ramoops_get_next_prz(cxt->mcu_przs, cxt->mcu_log_read_cnt++, record); + while (cxt->boot_log_read_cnt < cxt->max_boot_log_cnt && !prz) { + prz = ramoops_get_next_prz(cxt->boot_przs, cxt->boot_log_read_cnt++, record); if (!prz_ok(prz)) continue; } @@ -305,8 +305,8 @@ static ssize_t ramoops_pstore_read(struct pstore_record *record) goto out; } -#ifdef CONFIG_PSTORE_MCU_LOG - if (record->type == PSTORE_TYPE_MCU_LOG) { +#ifdef CONFIG_PSTORE_BOOT_LOG + if (record->type == PSTORE_TYPE_BOOT_LOG) { persistent_ram_free_old(prz); persistent_ram_save_old(prz); } @@ -517,13 +517,13 @@ static void ramoops_free_przs(struct ramoops_context *cxt) kfree(cxt->fprzs); cxt->max_ftrace_cnt = 0; } -#ifdef CONFIG_PSTORE_MCU_LOG - /* Free mcu log PRZs */ - if (cxt->mcu_przs) { - for (i = 0; i < cxt->max_mcu_log_cnt; i++) - persistent_ram_free(cxt->mcu_przs[i]); - kfree(cxt->mcu_przs); - cxt->max_mcu_log_cnt = 0; +#ifdef CONFIG_PSTORE_BOOT_LOG + /* Free boot log PRZs */ + if (cxt->boot_przs) { + for (i = 0; i < cxt->max_boot_log_cnt; i++) + persistent_ram_free(cxt->boot_przs[i]); + kfree(cxt->boot_przs); + cxt->max_boot_log_cnt = 0; } #endif } @@ -745,9 +745,9 @@ static int ramoops_parse_dt(struct platform_device *pdev, parse_u32("ecc-size", pdata->ecc_info.ecc_size, 0); parse_u32("flags", pdata->flags, 0); parse_u32("max-reason", pdata->max_reason, pdata->max_reason); -#ifdef CONFIG_PSTORE_MCU_LOG - parse_u32("mcu-log-size", pdata->mcu_log_size, 0); - parse_u32("mcu-log-count", pdata->max_mcu_log_cnt, 0); +#ifdef CONFIG_PSTORE_BOOT_LOG + parse_u32("boot-log-size", pdata->boot_log_size, 0); + parse_u32("boot-log-count", pdata->max_boot_log_cnt, 0); #endif #undef parse_u32 @@ -810,9 +810,9 @@ static int ramoops_probe(struct platform_device *pdev) goto fail_out; } -#ifdef CONFIG_PSTORE_MCU_LOG +#ifdef CONFIG_PSTORE_BOOT_LOG if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size && - !pdata->ftrace_size && !pdata->pmsg_size && !pdata->mcu_log_size)) { + !pdata->ftrace_size && !pdata->pmsg_size && !pdata->boot_log_size)) { pr_err("The memory size and the record/console size must be " "non-zero\n"); goto fail_out; @@ -846,18 +846,28 @@ static int ramoops_probe(struct platform_device *pdev) cxt->pmsg_size = pdata->pmsg_size; cxt->flags = pdata->flags; cxt->ecc_info = pdata->ecc_info; -#ifdef CONFIG_PSTORE_MCU_LOG - cxt->mcu_log_size = pdata->mcu_log_size; - cxt->max_mcu_log_cnt = pdata->max_mcu_log_cnt; +#ifdef CONFIG_PSTORE_BOOT_LOG + cxt->boot_log_size = pdata->boot_log_size; + cxt->max_boot_log_cnt = pdata->max_boot_log_cnt; #endif paddr = cxt->phys_addr; dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size - cxt->pmsg_size; +#ifdef CONFIG_PSTORE_BOOT_LOG + dump_mem_sz -= cxt->boot_log_size; +#endif -#ifdef CONFIG_PSTORE_MCU_LOG - dump_mem_sz -= cxt->mcu_log_size; +#ifdef CONFIG_PSTORE_BOOT_LOG + err = ramoops_init_przs("boot-log", dev, cxt, &cxt->boot_przs, &paddr, + cxt->boot_log_size, -1, + &cxt->max_boot_log_cnt, 0, 0); + if (err) + goto fail_clear; + if (cxt->boot_log_size > 0) + for (i = 0; i < cxt->max_boot_log_cnt; i++) + pr_info("boot-log-%d\t0x%zx@%pa\n", i, cxt->boot_przs[i]->size, &cxt->boot_przs[i]->paddr); #endif err = ramoops_init_przs("dmesg", dev, cxt, &cxt->dprzs, &paddr, @@ -897,17 +907,6 @@ static int ramoops_probe(struct platform_device *pdev) if (cxt->pmsg_size > 0) pr_info("pmsg\t0x%zx@%pa\n", cxt->mprz->size, &cxt->mprz->paddr); -#ifdef CONFIG_PSTORE_MCU_LOG - err = ramoops_init_przs("mcu-log", dev, cxt, &cxt->mcu_przs, &paddr, - cxt->mcu_log_size, -1, - &cxt->max_mcu_log_cnt, 0, 0); - if (err) - goto fail_clear; - if (cxt->mcu_log_size > 0) - for (i = 0; i < cxt->max_mcu_log_cnt; i++) - pr_info("mcu-log-%d\t0x%zx@%pa\n", i, cxt->mcu_przs[i]->size, &cxt->mcu_przs[i]->paddr); -#endif - cxt->pstore.data = cxt; /* * Prepare frontend flags based on which areas are initialized. @@ -926,9 +925,9 @@ static int ramoops_probe(struct platform_device *pdev) cxt->pstore.flags |= PSTORE_FLAGS_FTRACE; if (cxt->pmsg_size) cxt->pstore.flags |= PSTORE_FLAGS_PMSG; -#ifdef CONFIG_PSTORE_MCU_LOG - if (cxt->mcu_log_size) - cxt->pstore.flags |= PSTORE_FLAGS_MCU_LOG; +#ifdef CONFIG_PSTORE_BOOT_LOG + if (cxt->boot_log_size) + cxt->pstore.flags |= PSTORE_FLAGS_BOOT_LOG; #endif /* diff --git a/include/linux/pstore.h b/include/linux/pstore.h index 2aac7a063196..3029c7f571b8 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -38,8 +38,8 @@ enum pstore_type_id { PSTORE_TYPE_PPC_COMMON = 6, PSTORE_TYPE_PMSG = 7, PSTORE_TYPE_PPC_OPAL = 8, -#ifdef CONFIG_PSTORE_MCU_LOG - PSTORE_TYPE_MCU_LOG = 9, +#ifdef CONFIG_PSTORE_BOOT_LOG + PSTORE_TYPE_BOOT_LOG = 9, #endif /* End of the list */ @@ -205,8 +205,8 @@ struct pstore_info { #define PSTORE_FLAGS_CONSOLE BIT(1) #define PSTORE_FLAGS_FTRACE BIT(2) #define PSTORE_FLAGS_PMSG BIT(3) -#ifdef CONFIG_PSTORE_MCU_LOG -#define PSTORE_FLAGS_MCU_LOG BIT(4) +#ifdef CONFIG_PSTORE_BOOT_LOG +#define PSTORE_FLAGS_BOOT_LOG BIT(4) #endif extern int pstore_register(struct pstore_info *); diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index ff42d9a3fc90..ad7e88a34d60 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -116,8 +116,8 @@ void *persistent_ram_old(struct persistent_ram_zone *prz); void persistent_ram_free_old(struct persistent_ram_zone *prz); ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, char *str, size_t len); -#ifdef CONFIG_PSTORE_MCU_LOG -ssize_t ramoops_pstore_read_for_mcu_log(struct pstore_record *record); +#ifdef CONFIG_PSTORE_BOOT_LOG +ssize_t ramoops_pstore_read_for_boot_log(struct pstore_record *record); #endif /* @@ -136,9 +136,9 @@ struct ramoops_platform_data { unsigned long console_size; unsigned long ftrace_size; unsigned long pmsg_size; -#ifdef CONFIG_PSTORE_MCU_LOG - unsigned long mcu_log_size; - unsigned long max_mcu_log_cnt; +#ifdef CONFIG_PSTORE_BOOT_LOG + unsigned long boot_log_size; + unsigned long max_boot_log_cnt; #endif int max_reason; u32 flags; From 7daafa597ac5c1c77c9b1f737f330b02bb091479 Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Wed, 14 Sep 2022 10:03:11 +0000 Subject: [PATCH 099/204] arm64: rockchip_defconfig: enable CONFIG_PSTORE_BOOT_LOG We can run "cat /sys/fs/pstore/boot-log-ramoops-0" to cat tpl,spl,uboot,atf,optee boot log. Signed-off-by: Huibin Hong Change-Id: Iffccd1bc6fa97c7e84f56c038b56caad8cd69c15 --- arch/arm64/configs/rockchip_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 4b27d47ec634..c266bef5c434 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -960,6 +960,7 @@ CONFIG_PSTORE=y CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_PMSG=y CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_BOOT_LOG=y CONFIG_CIFS=y CONFIG_CIFS_XATTR=y CONFIG_CIFS_POSIX=y From 4ed56e5bde807897eea7ac3116452883e33a5dc6 Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Wed, 14 Sep 2022 11:22:41 +0000 Subject: [PATCH 100/204] arm64: dts: rockchip: rk3588-android: add boot-log-size for ramoops Signed-off-by: Huibin Hong Change-Id: I60c3ff0f63b9982ce6616e73b4138bac5d2fd24c --- arch/arm64/boot/dts/rockchip/rk3588-android.dtsi | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-android.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-android.dtsi index c8c1c6e45b9b..d4cdfb8b9e9f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-android.dtsi @@ -77,11 +77,14 @@ ramoops: ramoops@110000 { compatible = "ramoops"; - reg = <0x0 0x110000 0x0 0xf0000>; - record-size = <0x20000>; + /* 0x110000 to 0x1f0000 is for ramoops */ + reg = <0x0 0x110000 0x0 0xe0000>; + boot-log-size = <0x8000>; /* do not change */ + boot-log-count = <0x1>; /* do not change */ console-size = <0x80000>; + pmsg-size = <0x30000>; ftrace-size = <0x00000>; - pmsg-size = <0x50000>; + record-size = <0x14000>; }; }; }; From ae492539259299880ea02831b8793eb0a811f688 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Wed, 21 Sep 2022 16:02:42 +0800 Subject: [PATCH 101/204] media: rockchip: vicap: rkcif_rx_buufer uses its own list_head Signed-off-by: Zefa Chen Change-Id: I15f0d631095d249daedeee859c4671de12dd750b --- drivers/media/platform/rockchip/cif/capture.c | 105 +++++++++--------- drivers/media/platform/rockchip/cif/dev.h | 6 + .../media/platform/rockchip/cif/subdev-itf.c | 19 ++-- 3 files changed, 68 insertions(+), 62 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 87ad681c6393..8dc75f078f96 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -1496,7 +1496,7 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, int channel_id) { struct rkcif_device *dev = stream->cifdev; - struct rkisp_rx_buf *dbufs; + struct rkcif_rx_buffer *rx_buf; struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; u32 frm0_addr_y; u32 frm1_addr_y; @@ -1516,12 +1516,12 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, if (!stream->curr_buf_toisp) { if (!list_empty(&stream->rx_buf_head)) { - dbufs = list_first_entry(&stream->rx_buf_head, - struct rkisp_rx_buf, + rx_buf = list_first_entry(&stream->rx_buf_head, + struct rkcif_rx_buffer, list); - if (dbufs) { - list_del(&dbufs->list); - stream->curr_buf_toisp = to_cif_rx_buf(dbufs); + if (rx_buf) { + list_del(&rx_buf->list); + stream->curr_buf_toisp = rx_buf; } } } @@ -1532,11 +1532,11 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, if (!stream->next_buf_toisp) { if (!list_empty(&stream->rx_buf_head)) { - dbufs = list_first_entry(&stream->rx_buf_head, - struct rkisp_rx_buf, list); - if (dbufs) { - list_del(&dbufs->list); - stream->next_buf_toisp = to_cif_rx_buf(dbufs); + rx_buf = list_first_entry(&stream->rx_buf_head, + struct rkcif_rx_buffer, list); + if (rx_buf) { + list_del(&rx_buf->list); + stream->next_buf_toisp = rx_buf; } else { stream->next_buf_toisp = stream->curr_buf_toisp; } @@ -1559,7 +1559,6 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, struct rkcif_device *dev = stream->cifdev; struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; struct rkcif_rx_buffer *buffer = NULL; - struct rkisp_rx_buf *dbufs = NULL; struct rkcif_rx_buffer *active_buf = NULL; struct sditf_priv *priv = dev->sditf[0]; u32 frm_addr_y; @@ -1584,12 +1583,11 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, else active_buf = stream->curr_buf_toisp; - dbufs = list_first_entry(&stream->rx_buf_head, - struct rkisp_rx_buf, list); - if (dbufs) { - list_del(&dbufs->list); - stream->curr_buf_toisp = to_cif_rx_buf(dbufs); - buffer = stream->curr_buf_toisp; + buffer = list_first_entry(&stream->rx_buf_head, + struct rkcif_rx_buffer, list); + if (buffer) { + list_del(&buffer->list); + stream->curr_buf_toisp = buffer; } if (priv && priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { if (!active_buf) @@ -1610,12 +1608,11 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, active_buf = NULL; else active_buf = stream->next_buf_toisp; - dbufs = list_first_entry(&stream->rx_buf_head, - struct rkisp_rx_buf, list); - if (dbufs) { - list_del(&dbufs->list); - stream->next_buf_toisp = to_cif_rx_buf(dbufs); - buffer = stream->next_buf_toisp; + buffer = list_first_entry(&stream->rx_buf_head, + struct rkcif_rx_buffer, list); + if (buffer) { + list_del(&buffer->list); + stream->next_buf_toisp = buffer; } if (priv && priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { if (!active_buf) @@ -1710,7 +1707,7 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) { struct rkcif_device *dev = stream->cifdev; struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; - struct rkisp_rx_buf *dbufs = NULL; + struct rkcif_rx_buffer *buffer = NULL; struct rkcif_rx_buffer *active_buf = NULL; u32 frm_addr_y; u32 vblank = 0; @@ -1768,11 +1765,11 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) if (!list_empty(&stream->rx_buf_head)) { if (frame_phase == CIF_CSI_FRAME0_READY) { active_buf = stream->curr_buf_toisp; - dbufs = list_first_entry(&stream->rx_buf_head, - struct rkisp_rx_buf, list); - if (dbufs) { - list_del(&dbufs->list); - stream->curr_buf_toisp = to_cif_rx_buf(dbufs); + buffer = list_first_entry(&stream->rx_buf_head, + struct rkcif_rx_buffer, list); + if (buffer) { + list_del(&buffer->list); + stream->curr_buf_toisp = buffer; rkcif_write_register(dev, frm_addr_y, stream->curr_buf_toisp->dummy.dma_addr); if (dev->rdbk_debug > 1 && @@ -1785,11 +1782,11 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) } } else if (frame_phase == CIF_CSI_FRAME1_READY) { active_buf = stream->next_buf_toisp; - dbufs = list_first_entry(&stream->rx_buf_head, - struct rkisp_rx_buf, list); - if (dbufs) { - list_del(&dbufs->list); - stream->next_buf_toisp = to_cif_rx_buf(dbufs); + buffer = list_first_entry(&stream->rx_buf_head, + struct rkcif_rx_buffer, list); + if (buffer) { + list_del(&buffer->list); + stream->next_buf_toisp = buffer; rkcif_write_register(dev, frm_addr_y, stream->next_buf_toisp->dummy.dma_addr); if (dev->rdbk_debug > 1 && @@ -2326,25 +2323,25 @@ static int rkcif_update_new_buffer_wake_up_mode(struct rkcif_stream *stream) static int rkcif_get_new_buffer_wake_up_mode_rdbk(struct rkcif_stream *stream) { - struct rkisp_rx_buf *dbufs = NULL; + struct rkcif_rx_buffer *buffer = NULL; int ret = 0; unsigned long flags; spin_lock_irqsave(&stream->vbq_lock, flags); if (!list_empty(&stream->rx_buf_head)) { if (stream->line_int_cnt % 2) { - dbufs = list_first_entry(&stream->rx_buf_head, - struct rkisp_rx_buf, list); - if (dbufs) { - list_del(&dbufs->list); - stream->curr_buf_toisp = to_cif_rx_buf(dbufs); + buffer = list_first_entry(&stream->rx_buf_head, + struct rkcif_rx_buffer, list); + if (buffer) { + list_del(&buffer->list); + stream->curr_buf_toisp = buffer; } } else { - dbufs = list_first_entry(&stream->rx_buf_head, - struct rkisp_rx_buf, list); - if (dbufs) { - list_del(&dbufs->list); - stream->next_buf_toisp = to_cif_rx_buf(dbufs); + buffer = list_first_entry(&stream->rx_buf_head, + struct rkcif_rx_buffer, list); + if (buffer) { + list_del(&buffer->list); + stream->next_buf_toisp = buffer; } } stream->is_buf_active = true; @@ -3608,7 +3605,7 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num) if (!dev->is_thunderboot) rkcif_free_buffer(dev, &buf->dummy); else - list_add_tail(&buf->dbufs.list, &priv->buf_free_list); + list_add_tail(&buf->list_free, &priv->buf_free_list); } if (dev->is_thunderboot) { @@ -3672,7 +3669,7 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) ret = rkcif_alloc_reserved_mem_buf(dev, buf); if (ret) { priv->buf_num = i; - v4l2_err(&dev->v4l2_dev, + v4l2_info(&dev->v4l2_dev, "reserved mem support alloc buf num %d, require buf num %d\n", i, buf_num); break; @@ -3681,7 +3678,7 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) ret = rkcif_alloc_buffer(dev, dummy); if (ret) { priv->buf_num = i; - v4l2_err(&dev->v4l2_dev, + v4l2_info(&dev->v4l2_dev, "alloc buf num %d, require buf num %d\n", i, buf_num); break; @@ -3690,7 +3687,7 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) } buf->dbufs.is_init = false; buf->dbufs.type = frm_type; - list_add_tail(&buf->dbufs.list, &stream->rx_buf_head); + list_add_tail(&buf->list, &stream->rx_buf_head); dummy->is_free = false; if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE && i == 0) { buf->dbufs.is_first = true; @@ -3698,8 +3695,14 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) stream->buf_num_toisp--; } i++; - if (!dev->is_thunderboot && i >= buf_num) + if (!dev->is_thunderboot && i >= buf_num) { break; + } else if (i >= RKISP_VICAP_BUF_CNT_MAX) { + priv->buf_num = i; + v4l2_info(&dev->v4l2_dev, + "reserved mem alloc buf num %d\n", i); + break; + } v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, "init rx_buf,dma_addr 0x%llx size: 0x%x\n", (u64)dummy->dma_addr, pixm->plane_fmt[0].sizeimage); diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index edcb6690f7b4..0c6cc783d5a1 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -442,8 +442,14 @@ enum rkcif_capture_mode { RKCIF_TO_ISP_DMA, }; +/* + * list: used for buf rotation + * list_free: only used to release buf asynchronously + */ struct rkcif_rx_buffer { int buf_idx; + struct list_head list; + struct list_head list_free; struct rkisp_rx_buf dbufs; struct rkcif_dummy_buffer dummy; struct rkisp_thunderboot_shmem shmem; diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 4d1b8319f2dc..432119127fad 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -38,20 +38,17 @@ static void sditf_buffree_work(struct work_struct *work) struct sditf_priv, buffree_work); struct rkcif_rx_buffer *rx_buf = NULL; - struct rkisp_rx_buf *dbufs = NULL; unsigned long flags; LIST_HEAD(local_list); spin_lock_irqsave(&priv->cif_dev->buffree_lock, flags); list_replace_init(&priv->buf_free_list, &local_list); while (!list_empty(&local_list)) { - dbufs = list_first_entry(&local_list, - struct rkisp_rx_buf, list); - if (dbufs) { - list_del(&dbufs->list); - rx_buf = container_of(dbufs, struct rkcif_rx_buffer, dbufs); - if (rx_buf) - rkcif_free_reserved_mem_buf(priv->cif_dev, rx_buf); + rx_buf = list_first_entry(&local_list, + struct rkcif_rx_buffer, list_free); + if (rx_buf) { + list_del(&rx_buf->list_free); + rkcif_free_reserved_mem_buf(priv->cif_dev, rx_buf); } } spin_unlock_irqrestore(&priv->cif_dev->buffree_lock, flags); @@ -701,14 +698,14 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, if (!list_empty(&stream->rx_buf_head) && cif_dev->is_thunderboot) { spin_lock_irqsave(&cif_dev->buffree_lock, buffree_flags); - list_add_tail(&dbufs->list, &priv->buf_free_list); + list_add_tail(&rx_buf->list_free, &priv->buf_free_list); spin_unlock_irqrestore(&cif_dev->buffree_lock, buffree_flags); schedule_work(&priv->buffree_work.work); is_free = true; } if (!is_free) { - list_add_tail(&dbufs->list, &stream->rx_buf_head); + list_add_tail(&rx_buf->list, &stream->rx_buf_head); rkcif_assign_check_buffer_update_toisp(stream); if (cif_dev->rdbk_debug) { u32 offset = 0; @@ -738,7 +735,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, spin_unlock_irqrestore(&stream->vbq_lock, flags); if (dbufs->runtime_us && cif_dev->early_line == 0) { - if (cif_dev->sensor_linetime) + if (!cif_dev->sensor_linetime) cif_dev->sensor_linetime = rkcif_get_linetime(stream); cif_dev->isp_runtime_max = dbufs->runtime_us; if (cif_dev->is_thunderboot) From c38b77a6e20c3f0dffe99845880dda4133ea3205 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Sun, 19 Jun 2022 09:45:39 +0800 Subject: [PATCH 102/204] MALI: rockchip: upgrade bifrost DDK to g13p0-01eac0, from g12p0-01eac0 Note, the corresponding mali_csffw.bin for DDK g13 MUST be used. Change-Id: I63c00b4eccd2e780aea2691faa2ecea6847c41e2 Signed-off-by: Zhen Chen --- Documentation/ABI/testing/sysfs-device-mali | 25 + .../base/arm/dma_buf_lock/src/dma_buf_lock.c | 51 +- .../dma-buf-test-exporter.c | 60 +- .../memory_group_manager.c | 36 +- drivers/gpu/arm/bifrost/Kbuild | 2 +- drivers/gpu/arm/bifrost/Kconfig | 14 + drivers/gpu/arm/bifrost/Makefile | 5 + drivers/gpu/arm/bifrost/Mconfig | 19 +- .../bifrost/arbiter/mali_kbase_arbiter_pm.c | 7 +- .../bifrost/backend/gpu/mali_kbase_devfreq.c | 6 - .../backend/gpu/mali_kbase_gpuprops_backend.c | 21 +- .../bifrost/backend/gpu/mali_kbase_jm_hw.c | 59 +- .../backend/gpu/mali_kbase_jm_internal.h | 9 +- .../bifrost/backend/gpu/mali_kbase_jm_rb.c | 94 +- .../backend/gpu/mali_kbase_model_dummy.c | 9 +- .../backend/gpu/mali_kbase_pm_backend.c | 3 +- .../bifrost/backend/gpu/mali_kbase_pm_defs.h | 4 +- .../backend/gpu/mali_kbase_pm_driver.c | 104 +- .../backend/gpu/mali_kbase_pm_metrics.c | 103 +- .../backend/gpu/mali_kbase_pm_policy.c | 48 +- .../arm/bifrost/backend/gpu/mali_kbase_time.c | 28 +- drivers/gpu/arm/bifrost/build.bp | 3 + .../arm/bifrost/context/mali_kbase_context.c | 4 +- drivers/gpu/arm/bifrost/csf/Kbuild | 1 + drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c | 255 ++-- drivers/gpu/arm/bifrost/csf/mali_kbase_csf.h | 7 +- .../bifrost/csf/mali_kbase_csf_csg_debugfs.c | 4 - .../gpu/arm/bifrost/csf/mali_kbase_csf_defs.h | 10 + .../arm/bifrost/csf/mali_kbase_csf_event.c | 9 +- .../arm/bifrost/csf/mali_kbase_csf_firmware.c | 83 +- .../arm/bifrost/csf/mali_kbase_csf_firmware.h | 3 + .../bifrost/csf/mali_kbase_csf_firmware_cfg.c | 8 + .../csf/mali_kbase_csf_firmware_no_mali.c | 27 +- .../gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c | 132 ++- .../gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.h | 10 +- .../bifrost/csf/mali_kbase_csf_kcpu_debugfs.c | 4 - .../bifrost/csf/mali_kbase_csf_registers.h | 57 +- .../bifrost/csf/mali_kbase_csf_scheduler.c | 426 ++++--- .../bifrost/csf/mali_kbase_csf_scheduler.h | 40 +- .../mali_kbase_debug_ktrace_codes_csf.h | 146 +-- .../backend/mali_kbase_debug_ktrace_csf.c | 8 +- .../mali_kbase_debug_ktrace_defs_csf.h | 4 +- .../backend/mali_kbase_debug_ktrace_jm.c | 5 +- .../mali_kbase_debug_linux_ktrace_csf.h | 144 +-- .../bifrost/debug/mali_kbase_debug_ktrace.c | 8 +- .../bifrost/debug/mali_kbase_debug_ktrace.h | 14 +- .../device/backend/mali_kbase_device_csf.c | 4 +- .../device/backend/mali_kbase_device_hw_jm.c | 6 +- .../arm/bifrost/device/mali_kbase_device.c | 26 +- .../arm/bifrost/device/mali_kbase_device.h | 18 +- .../arm/bifrost/device/mali_kbase_device_hw.c | 40 +- .../gpu/backend/mali_kbase_gpu_regmap_csf.h | 107 +- .../gpu/backend/mali_kbase_gpu_regmap_jm.h | 19 +- .../arm/bifrost/gpu/mali_kbase_gpu_regmap.h | 6 + .../gpu/arm/bifrost/jm/mali_kbase_jm_defs.h | 11 - drivers/gpu/arm/bifrost/jm/mali_kbase_jm_js.h | 76 +- .../gpu/arm/bifrost/jm/mali_kbase_js_defs.h | 2 +- .../arm/bifrost/mali_base_hwconfig_features.h | 7 +- .../arm/bifrost/mali_base_hwconfig_issues.h | 16 + drivers/gpu/arm/bifrost/mali_kbase.h | 11 +- .../arm/bifrost/mali_kbase_config_defaults.h | 8 +- .../gpu/arm/bifrost/mali_kbase_core_linux.c | 92 +- .../arm/bifrost/mali_kbase_debug_job_fault.c | 5 +- drivers/gpu/arm/bifrost/mali_kbase_defs.h | 7 +- .../gpu/arm/bifrost/mali_kbase_dma_fence.c | 6 +- .../gpu/arm/bifrost/mali_kbase_dma_fence.h | 2 +- .../gpu/arm/bifrost/mali_kbase_dvfs_debugfs.c | 6 +- drivers/gpu/arm/bifrost/mali_kbase_fence.h | 10 + .../gpu/arm/bifrost/mali_kbase_fence_ops.c | 4 +- drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c | 212 ++-- .../bifrost/mali_kbase_hwcnt_backend_csf.c | 71 +- .../bifrost/mali_kbase_hwcnt_backend_csf_if.h | 8 +- .../mali_kbase_hwcnt_backend_csf_if_fw.c | 60 +- .../arm/bifrost/mali_kbase_hwcnt_gpu_narrow.c | 4 +- drivers/gpu/arm/bifrost/mali_kbase_jd.c | 47 +- .../gpu/arm/bifrost/mali_kbase_jd_debugfs.c | 12 +- drivers/gpu/arm/bifrost/mali_kbase_js.c | 19 +- .../gpu/arm/bifrost/mali_kbase_kinstr_jm.c | 9 +- .../gpu/arm/bifrost/mali_kbase_kinstr_jm.h | 4 +- .../arm/bifrost/mali_kbase_kinstr_prfcnt.c | 11 +- drivers/gpu/arm/bifrost/mali_kbase_mem.c | 76 +- .../gpu/arm/bifrost/mali_kbase_mem_linux.c | 84 +- .../gpu/arm/bifrost/mali_kbase_mem_linux.h | 13 +- .../arm/bifrost/mali_kbase_mem_pool_debugfs.c | 8 +- .../bifrost/mali_kbase_mem_profile_debugfs.c | 4 - .../gpu/arm/bifrost/mali_kbase_native_mgm.c | 27 +- .../gpu/arm/bifrost/mali_kbase_pbha_debugfs.c | 8 +- drivers/gpu/arm/bifrost/mali_kbase_softjobs.c | 24 +- .../gpu/arm/bifrost/mali_kbase_sync_android.c | 19 +- .../gpu/arm/bifrost/mali_kbase_sync_file.c | 9 +- drivers/gpu/arm/bifrost/mali_kbase_vinstr.c | 13 +- .../bifrost/mmu/backend/mali_kbase_mmu_csf.c | 6 +- .../bifrost/mmu/backend/mali_kbase_mmu_jm.c | 4 +- drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.c | 1046 ++++++++++------- drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.h | 13 +- .../gpu/arm/bifrost/mmu/mali_kbase_mmu_hw.h | 99 +- .../bifrost/mmu/mali_kbase_mmu_hw_direct.c | 403 +++++-- .../bifrost/mmu/mali_kbase_mmu_mode_aarch64.c | 11 +- .../devicetree/mali_kbase_runtime_pm.c | 14 +- drivers/gpu/arm/bifrost/tests/Kbuild | 3 +- drivers/gpu/arm/bifrost/tests/Kconfig | 14 +- drivers/gpu/arm/bifrost/tests/Mconfig | 14 +- .../bifrost/tests/kutf/kutf_helpers_user.c | 4 +- .../gpu/arm/bifrost/tests/kutf/kutf_suite.c | 35 +- .../gpu/arm/bifrost/tests/kutf/kutf_utils.c | 4 +- .../kernel/mali_kutf_clk_rate_trace_test.c | 10 +- .../mali_kutf_irq_test_main.c | 2 +- .../mali_kutf_mgm_integration_test/Kbuild | 25 + .../mali_kutf_mgm_integration_test/build.bp | 41 + .../mali_kutf_mgm_integration_test_main.c | 210 ++++ .../arm/bifrost/tl/mali_kbase_timeline_io.c | 8 +- .../arm/bifrost/tl/mali_kbase_tracepoints.c | 4 +- .../arm/bifrost/tl/mali_kbase_tracepoints.h | 4 +- include/linux/memory_group_manager.h | 10 + include/linux/version_compat_defs.h | 31 + .../backend/gpu/mali_kbase_model_dummy.h | 5 +- .../arm/bifrost/csf/mali_base_csf_kernel.h | 236 +--- .../arm/bifrost/csf/mali_kbase_csf_ioctl.h | 10 +- .../gpu/arm/bifrost/jm/mali_base_jm_kernel.h | 263 +---- .../gpu/arm/bifrost/mali_base_common_kernel.h | 231 ++++ .../uapi/gpu/arm/bifrost/mali_base_kernel.h | 70 +- .../uapi/gpu/arm/bifrost/mali_base_mem_priv.h | 3 +- include/uapi/gpu/arm/bifrost/mali_uk.h | 70 -- 123 files changed, 3777 insertions(+), 2476 deletions(-) create mode 100644 drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/Kbuild create mode 100644 drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/build.bp create mode 100644 drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/mali_kutf_mgm_integration_test_main.c create mode 100644 include/linux/version_compat_defs.h create mode 100644 include/uapi/gpu/arm/bifrost/mali_base_common_kernel.h delete mode 100644 include/uapi/gpu/arm/bifrost/mali_uk.h diff --git a/Documentation/ABI/testing/sysfs-device-mali b/Documentation/ABI/testing/sysfs-device-mali index 99f8ae57b7c9..b7be50338f6e 100644 --- a/Documentation/ABI/testing/sysfs-device-mali +++ b/Documentation/ABI/testing/sysfs-device-mali @@ -211,6 +211,31 @@ Description: without forward progress to allow to elapse before terminating a GPU command queue group. +What: /sys/class/misc/mali%u/device/mcu_shader_pwroff_timeout +Description: + This attribute is available only with mali platform + device-driver that supports a CSF GPU. The duration value unit + is in micro-seconds and is used for configuring MCU shader Core power-off + timer. The configured MCU shader Core power-off timer will only have + effect when the host driver has delegated the shader cores + power management to MCU. The supplied value will be + recorded internally without any change. But the actual field + value will be subject to core power-off timer source frequency + scaling and maximum value limiting. The default source will be + SYSTEM_TIMESTAMP counter. But in case the platform is not able + to supply it, the GPU CYCLE_COUNTER source will be used as an + alternative. + + If we set the value to zero then MCU-controlled shader/tiler + power management will be disabled. + + +What: /sys/class/misc/mali%u/device/csg_scheduling_period +Description: + This attribute is available only with mali platform + device-driver that supports a CSF GPU. The duration value unit + is in milliseconds and is used for configuring csf scheduling + tick duration. What: /sys/class/misc/mali%u/device/reset_timeout Description: This attribute is used to set the number of milliseconds to diff --git a/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.c b/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.c index 04ec2d296c79..43333ca8e5e2 100644 --- a/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.c +++ b/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2012-2014, 2017-2018, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2012-2014, 2017-2018, 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -20,6 +20,7 @@ */ #include +#include #include #include #include @@ -99,9 +100,6 @@ static const struct file_operations dma_buf_lock_fops = { #if defined(HAVE_COMPAT_IOCTL) || ((KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE)) .compat_ioctl = dma_buf_lock_ioctl, #endif -#if !defined(HAVE_UNLOCKED_IOCTL) && !defined(HAVE_COMPAT_IOCTL) && ((KERNEL_VERSION(2, 6, 36) > LINUX_VERSION_CODE)) - .ioctl = dma_buf_lock_ioctl, -#endif }; struct dma_buf_lock_resource { @@ -480,15 +478,18 @@ static int dma_buf_lock_handle_release(struct inode *inode, struct file *file) return 0; } -static unsigned int dma_buf_lock_handle_poll( - struct file *file, - struct poll_table_struct *wait) +static __poll_t dma_buf_lock_handle_poll(struct file *file, poll_table *wait) { struct dma_buf_lock_resource *resource; unsigned int ret = 0; - if (!is_dma_buf_lock_file(file)) + if (!is_dma_buf_lock_file(file)) { +#if (KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE) return POLLERR; +#else + return EPOLLERR; +#endif + } resource = file->private_data; #if DMA_BUF_LOCK_DEBUG @@ -496,9 +497,15 @@ static unsigned int dma_buf_lock_handle_poll( #endif if (atomic_read(&resource->locked) == 1) { /* Resources have been locked */ +#if (KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE) ret = POLLIN | POLLRDNORM; if (resource->exclusive) - ret |= POLLOUT | POLLWRNORM; + ret |= POLLOUT | POLLWRNORM; +#else + ret = EPOLLIN | EPOLLRDNORM; + if (resource->exclusive) + ret |= EPOLLOUT | EPOLLWRNORM; +#endif } else { if (!poll_does_not_wait(wait)) poll_wait(file, &resource->wait, wait); @@ -533,10 +540,12 @@ static int dma_buf_lock_dolock(struct dma_buf_lock_k_request *request) { struct dma_buf_lock_resource *resource; struct ww_acquire_ctx ww_ctx; + struct file *file; int size; int fd; int i; int ret; + int error; if (request->list_of_dma_buf_fds == NULL) return -EINVAL; @@ -634,15 +643,21 @@ static int dma_buf_lock_dolock(struct dma_buf_lock_k_request *request) kref_get(&resource->refcount); - /* Create file descriptor associated with lock request */ - fd = anon_inode_getfd("dma_buf_lock", &dma_buf_lock_handle_fops, - (void *)resource, 0); - if (fd < 0) { + error = get_unused_fd_flags(0); + if (error < 0) + return error; + + fd = error; + + file = anon_inode_getfile("dma_buf_lock", &dma_buf_lock_handle_fops, (void *)resource, 0); + + if (IS_ERR(file)) { + put_unused_fd(fd); mutex_lock(&dma_buf_lock_mutex); kref_put(&resource->refcount, dma_buf_lock_dounlock); kref_put(&resource->refcount, dma_buf_lock_dounlock); mutex_unlock(&dma_buf_lock_mutex); - return fd; + return PTR_ERR(file); } resource->exclusive = request->exclusive; @@ -711,9 +726,7 @@ static int dma_buf_lock_dolock(struct dma_buf_lock_k_request *request) dma_resv_add_shared_fence(resv, &resource->fence); #endif } else { - ret = dma_buf_lock_add_fence_reservation_callback(resource, - resv, - true); + ret = dma_buf_lock_add_fence_reservation_callback(resource, resv, true); if (ret) { #if DMA_BUF_LOCK_DEBUG pr_debug("%s : Error %d adding reservation to callback.\n", __func__, ret); @@ -758,6 +771,10 @@ static int dma_buf_lock_dolock(struct dma_buf_lock_k_request *request) kref_put(&resource->refcount, dma_buf_lock_dounlock); mutex_unlock(&dma_buf_lock_mutex); + /* Installing the fd is deferred to the very last operation before return + * to avoid allowing userspace to close it during the setup. + */ + fd_install(fd, file); return fd; } diff --git a/drivers/base/arm/dma_buf_test_exporter/dma-buf-test-exporter.c b/drivers/base/arm/dma_buf_test_exporter/dma-buf-test-exporter.c index 22664c5690c0..6b9a4d70483a 100644 --- a/drivers/base/arm/dma_buf_test_exporter/dma-buf-test-exporter.c +++ b/drivers/base/arm/dma_buf_test_exporter/dma-buf-test-exporter.c @@ -30,9 +30,6 @@ #include #include #include -#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE) -#include -#endif #include /* Maximum size allowed in a single DMA_BUF_TE_ALLOC call */ @@ -211,20 +208,11 @@ static void dma_buf_te_release(struct dma_buf *buf) /* no need for locking */ if (alloc->contiguous) { -#if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE) dma_free_attrs(te_device.this_device, alloc->nr_pages * PAGE_SIZE, alloc->contig_cpu_addr, alloc->contig_dma_addr, DMA_ATTR_WRITE_COMBINE); -#else - DEFINE_DMA_ATTRS(attrs); - - dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); - dma_free_attrs(te_device.this_device, - alloc->nr_pages * PAGE_SIZE, - alloc->contig_cpu_addr, alloc->contig_dma_addr, &attrs); -#endif } else { for (i = 0; i < alloc->nr_pages; i++) __free_page(alloc->pages[i]); @@ -269,32 +257,17 @@ static int dma_buf_te_sync(struct dma_buf *dmabuf, return 0; } -#if (KERNEL_VERSION(4, 6, 0) <= LINUX_VERSION_CODE) static int dma_buf_te_begin_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction direction) -#else -static int dma_buf_te_begin_cpu_access(struct dma_buf *dmabuf, size_t start, - size_t len, - enum dma_data_direction direction) -#endif { return dma_buf_te_sync(dmabuf, direction, true); } -#if (KERNEL_VERSION(4, 6, 0) <= LINUX_VERSION_CODE) static int dma_buf_te_end_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction direction) { return dma_buf_te_sync(dmabuf, direction, false); } -#else -static void dma_buf_te_end_cpu_access(struct dma_buf *dmabuf, size_t start, - size_t len, - enum dma_data_direction direction) -{ - dma_buf_te_sync(dmabuf, direction, false); -} -#endif static void dma_buf_te_mmap_open(struct vm_area_struct *vma) { @@ -521,21 +494,11 @@ static int do_dma_buf_te_ioctl_alloc(struct dma_buf_te_ioctl_alloc __user *buf, if (contiguous) { dma_addr_t dma_aux; -#if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE) alloc->contig_cpu_addr = dma_alloc_attrs(te_device.this_device, alloc->nr_pages * PAGE_SIZE, &alloc->contig_dma_addr, GFP_KERNEL | __GFP_ZERO, DMA_ATTR_WRITE_COMBINE); -#else - DEFINE_DMA_ATTRS(attrs); - - dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); - alloc->contig_cpu_addr = dma_alloc_attrs(te_device.this_device, - alloc->nr_pages * PAGE_SIZE, - &alloc->contig_dma_addr, - GFP_KERNEL | __GFP_ZERO, &attrs); -#endif if (!alloc->contig_cpu_addr) { dev_err(te_device.this_device, "%s: couldn't alloc contiguous buffer %zu pages", __func__, alloc->nr_pages); @@ -591,20 +554,11 @@ no_export: /* i still valid */ no_page: if (contiguous) { -#if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE) dma_free_attrs(te_device.this_device, alloc->nr_pages * PAGE_SIZE, alloc->contig_cpu_addr, alloc->contig_dma_addr, DMA_ATTR_WRITE_COMBINE); -#else - DEFINE_DMA_ATTRS(attrs); - - dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); - dma_free_attrs(te_device.this_device, - alloc->nr_pages * PAGE_SIZE, - alloc->contig_cpu_addr, alloc->contig_dma_addr, &attrs); -#endif } else { while (i-- > 0) __free_page(alloc->pages[i]); @@ -703,7 +657,6 @@ static u32 dma_te_buf_fill(struct dma_buf *dma_buf, unsigned int value) struct sg_table *sgt; struct scatterlist *sg; unsigned int count; - unsigned int offset = 0; int ret = 0; size_t i; @@ -717,11 +670,7 @@ static u32 dma_te_buf_fill(struct dma_buf *dma_buf, unsigned int value) goto no_import; } - ret = dma_buf_begin_cpu_access(dma_buf, -#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE - 0, dma_buf->size, -#endif - DMA_BIDIRECTIONAL); + ret = dma_buf_begin_cpu_access(dma_buf, DMA_BIDIRECTIONAL); if (ret) goto no_cpu_access; @@ -744,15 +693,10 @@ static u32 dma_te_buf_fill(struct dma_buf *dma_buf, unsigned int value) dma_buf_kunmap(dma_buf, i >> PAGE_SHIFT, addr); #endif } - offset += sg_dma_len(sg); } no_kmap: - dma_buf_end_cpu_access(dma_buf, -#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE - 0, dma_buf->size, -#endif - DMA_BIDIRECTIONAL); + dma_buf_end_cpu_access(dma_buf, DMA_BIDIRECTIONAL); no_cpu_access: dma_buf_unmap_attachment(attachment, sgt, DMA_BIDIRECTIONAL); no_import: diff --git a/drivers/base/arm/memory_group_manager/memory_group_manager.c b/drivers/base/arm/memory_group_manager/memory_group_manager.c index b2bdc36f4a2d..7729492e0c80 100644 --- a/drivers/base/arm/memory_group_manager/memory_group_manager.c +++ b/drivers/base/arm/memory_group_manager/memory_group_manager.c @@ -42,18 +42,7 @@ static inline vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, pgprot_t pgprot) { - int err; - -#if ((KERNEL_VERSION(4, 4, 147) >= LINUX_VERSION_CODE) || \ - ((KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE) && \ - (KERNEL_VERSION(4, 5, 0) <= LINUX_VERSION_CODE))) - if (pgprot_val(pgprot) != pgprot_val(vma->vm_page_prot)) - return VM_FAULT_SIGBUS; - - err = vm_insert_pfn(vma, addr, pfn); -#else - err = vm_insert_pfn_prot(vma, addr, pfn, pgprot); -#endif + int err = vm_insert_pfn_prot(vma, addr, pfn, pgprot); if (unlikely(err == -ENOMEM)) return VM_FAULT_OOM; @@ -64,6 +53,10 @@ static inline vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma, } #endif +#define PTE_PBHA_SHIFT (59) +#define PTE_PBHA_MASK ((uint64_t)0xf << PTE_PBHA_SHIFT) +#define PTE_RES_BIT_MULTI_AS_SHIFT (63) + #define IMPORTED_MEMORY_ID (MEMORY_GROUP_MANAGER_NR_GROUPS - 1) /** @@ -335,8 +328,6 @@ static u64 example_mgm_update_gpu_pte( int const mmu_level, u64 pte) { struct mgm_groups *const data = mgm_dev->data; - const u32 pbha_bit_pos = 59; /* bits 62:59 */ - const u32 pbha_bit_mask = 0xf; /* 4-bit */ dev_dbg(data->dev, "%s(mgm_dev=%p, group_id=%d, mmu_level=%d, pte=0x%llx)\n", @@ -346,13 +337,27 @@ static u64 example_mgm_update_gpu_pte( WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS)) return pte; - pte |= ((u64)group_id & pbha_bit_mask) << pbha_bit_pos; + pte |= ((u64)group_id << PTE_PBHA_SHIFT) & PTE_PBHA_MASK; + + /* Address could be translated into a different bus address here */ + pte |= ((u64)1 << PTE_RES_BIT_MULTI_AS_SHIFT); data->groups[group_id].update_gpu_pte++; return pte; } +static u64 example_mgm_pte_to_original_pte(struct memory_group_manager_device *const mgm_dev, + int const group_id, int const mmu_level, u64 pte) +{ + /* Undo the group ID modification */ + pte &= ~PTE_PBHA_MASK; + /* Undo the bit set */ + pte &= ~((u64)1 << PTE_RES_BIT_MULTI_AS_SHIFT); + + return pte; +} + static vm_fault_t example_mgm_vmf_insert_pfn_prot( struct memory_group_manager_device *const mgm_dev, int const group_id, struct vm_area_struct *const vma, unsigned long const addr, @@ -428,6 +433,7 @@ static int memory_group_manager_probe(struct platform_device *pdev) example_mgm_get_import_memory_id; mgm_dev->ops.mgm_vmf_insert_pfn_prot = example_mgm_vmf_insert_pfn_prot; mgm_dev->ops.mgm_update_gpu_pte = example_mgm_update_gpu_pte; + mgm_dev->ops.mgm_pte_to_original_pte = example_mgm_pte_to_original_pte; mgm_data = kzalloc(sizeof(*mgm_data), GFP_KERNEL); if (!mgm_data) { diff --git a/drivers/gpu/arm/bifrost/Kbuild b/drivers/gpu/arm/bifrost/Kbuild index 7172468829c9..a7f0ba0da1e8 100644 --- a/drivers/gpu/arm/bifrost/Kbuild +++ b/drivers/gpu/arm/bifrost/Kbuild @@ -71,7 +71,7 @@ endif # # Driver version string which is returned to userspace via an ioctl -MALI_RELEASE_NAME ?= '"g12p0-01eac0"' +MALI_RELEASE_NAME ?= '"g13p0-01eac0"' # Set up defaults if not defined by build system ifeq ($(CONFIG_MALI_BIFROST_DEBUG), y) MALI_UNIT_TEST = 1 diff --git a/drivers/gpu/arm/bifrost/Kconfig b/drivers/gpu/arm/bifrost/Kconfig index 72f4c19fc07a..54f083dbad27 100644 --- a/drivers/gpu/arm/bifrost/Kconfig +++ b/drivers/gpu/arm/bifrost/Kconfig @@ -214,6 +214,20 @@ config MALI_GEM5_BUILD comment "Debug options" depends on MALI_BIFROST && MALI_BIFROST_EXPERT +config MALI_FW_CORE_DUMP + bool "Enable support for FW core dump" + depends on MALI_BIFROST && MALI_BIFROST_EXPERT && MALI_CSF_SUPPORT + default n + help + Adds ability to request firmware core dump + + Example: + * To explicitly request core dump: + echo 1 >/sys/kernel/debug/mali0/fw_core_dump + * To output current core dump (after explicitly requesting a core dump, + or kernel driver reported an internal firmware error): + cat /sys/kernel/debug/mali0/fw_core_dump + config MALI_BIFROST_DEBUG bool "Enable debug build" depends on MALI_BIFROST && MALI_BIFROST_EXPERT diff --git a/drivers/gpu/arm/bifrost/Makefile b/drivers/gpu/arm/bifrost/Makefile index 5233e4c1e26b..623177ed26fb 100644 --- a/drivers/gpu/arm/bifrost/Makefile +++ b/drivers/gpu/arm/bifrost/Makefile @@ -130,16 +130,19 @@ ifeq ($(CONFIG_MALI_BIFROST),m) ifeq ($(CONFIG_MALI_KUTF), y) CONFIG_MALI_KUTF_IRQ_TEST ?= y CONFIG_MALI_KUTF_CLK_RATE_TRACE ?= y + CONFIG_MALI_KUTF_MGM_INTEGRATION_TEST ?= y else # Prevent misuse when CONFIG_MALI_KUTF=n CONFIG_MALI_KUTF_IRQ_TEST = n CONFIG_MALI_KUTF_CLK_RATE_TRACE = n + CONFIG_MALI_KUTF_MGM_INTEGRATION_TEST = n endif else # Prevent misuse when CONFIG_MALI_BIFROST_DEBUG=n CONFIG_MALI_KUTF = n CONFIG_MALI_KUTF_IRQ_TEST = n CONFIG_MALI_KUTF_CLK_RATE_TRACE = n + CONFIG_MALI_KUTF_MGM_INTEGRATION_TEST = n endif else # Prevent misuse when CONFIG_MALI_BIFROST=n @@ -149,6 +152,7 @@ else CONFIG_MALI_KUTF = n CONFIG_MALI_KUTF_IRQ_TEST = n CONFIG_MALI_KUTF_CLK_RATE_TRACE = n + CONFIG_MALI_KUTF_MGM_INTEGRATION_TEST = n endif # All Mali CONFIG should be listed here @@ -189,6 +193,7 @@ CONFIGS := \ CONFIG_MALI_KUTF \ CONFIG_MALI_KUTF_IRQ_TEST \ CONFIG_MALI_KUTF_CLK_RATE_TRACE \ + CONFIG_MALI_KUTF_MGM_INTEGRATION_TEST \ CONFIG_MALI_XEN diff --git a/drivers/gpu/arm/bifrost/Mconfig b/drivers/gpu/arm/bifrost/Mconfig index f43da8ba28f2..fd81ac44af3d 100644 --- a/drivers/gpu/arm/bifrost/Mconfig +++ b/drivers/gpu/arm/bifrost/Mconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2012-2021 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2012-2022 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -65,8 +65,7 @@ config MALI_CSF_SUPPORT config MALI_BIFROST_DEVFREQ bool "Enable devfreq support for Mali" depends on MALI_BIFROST - default y if PLATFORM_JUNO - default y if PLATFORM_CUSTOM + default y help Support devfreq for Mali. @@ -192,6 +191,20 @@ config MALI_CORESTACK If unsure, say N. +config MALI_FW_CORE_DUMP + bool "Enable support for FW core dump" + depends on MALI_BIFROST && MALI_BIFROST_EXPERT && MALI_CSF_SUPPORT + default n + help + Adds ability to request firmware core dump + + Example: + * To explicitly request core dump: + echo 1 >/sys/kernel/debug/mali0/fw_core_dump + * To output current core dump (after explicitly requesting a core dump, + or kernel driver reported an internal firmware error): + cat /sys/kernel/debug/mali0/fw_core_dump + choice prompt "Error injection level" depends on MALI_BIFROST && MALI_BIFROST_EXPERT diff --git a/drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbiter_pm.c b/drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbiter_pm.c index 6079dd87e067..667552c561fb 100644 --- a/drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbiter_pm.c +++ b/drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbiter_pm.c @@ -955,7 +955,6 @@ static inline bool kbase_arbiter_pm_vm_gpu_assigned_lockheld( int kbase_arbiter_pm_ctx_active_handle_suspend(struct kbase_device *kbdev, enum kbase_pm_suspend_handler suspend_handler) { - struct kbasep_js_device_data *js_devdata = &kbdev->js_data; struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state; int res = 0; @@ -1008,11 +1007,9 @@ int kbase_arbiter_pm_ctx_active_handle_suspend(struct kbase_device *kbdev, /* Need to synchronously wait for GPU assignment */ atomic_inc(&kbdev->pm.gpu_users_waiting); mutex_unlock(&arb_vm_state->vm_state_lock); - mutex_unlock(&kbdev->pm.lock); - mutex_unlock(&js_devdata->runpool_mutex); + kbase_pm_unlock(kbdev); kbase_arbiter_pm_vm_wait_gpu_assignment(kbdev); - mutex_lock(&js_devdata->runpool_mutex); - mutex_lock(&kbdev->pm.lock); + kbase_pm_lock(kbdev); mutex_lock(&arb_vm_state->vm_state_lock); atomic_dec(&kbdev->pm.gpu_users_waiting); } diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c index 0590b13c1b24..9ca764488e9d 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c @@ -824,12 +824,6 @@ int kbase_devfreq_init(struct kbase_device *kbdev) goto ipa_init_failed; } } else { - err = kbase_ipa_init(kbdev); - if (err) { - dev_err(kbdev->dev, "IPA initialization failed\n"); - goto ipa_init_failed; - } - kbdev->devfreq_cooling = of_devfreq_cooling_register_power( kbdev->dev->of_node, kbdev->devfreq, diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpuprops_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpuprops_backend.c index 0ea14bc89da4..10e92ec94d3a 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpuprops_backend.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_gpuprops_backend.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2014-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -40,19 +40,7 @@ int kbase_backend_gpuprops_get(struct kbase_device *kbdev, registers.l2_features = kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_FEATURES)); - registers.core_features = 0; -#if !MALI_USE_CSF - /* TGOx */ - registers.core_features = kbase_reg_read(kbdev, - GPU_CONTROL_REG(CORE_FEATURES)); -#else /* !MALI_USE_CSF */ - if (!(((registers.gpu_id & GPU_ID2_PRODUCT_MODEL) == - GPU_ID2_PRODUCT_TDUX) || - ((registers.gpu_id & GPU_ID2_PRODUCT_MODEL) == - GPU_ID2_PRODUCT_TODX))) - registers.core_features = - kbase_reg_read(kbdev, GPU_CONTROL_REG(CORE_FEATURES)); -#endif /* MALI_USE_CSF */ + registers.tiler_features = kbase_reg_read(kbdev, GPU_CONTROL_REG(TILER_FEATURES)); registers.mem_features = kbase_reg_read(kbdev, @@ -170,6 +158,11 @@ int kbase_backend_gpuprops_get_features(struct kbase_device *kbdev, regdump->coherency_features = coherency_features; + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_CORE_FEATURES)) + regdump->core_features = kbase_reg_read(kbdev, GPU_CONTROL_REG(CORE_FEATURES)); + else + regdump->core_features = 0; + kbase_pm_register_access_disable(kbdev); return error; diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c index ae781ec14a22..08de02495a4a 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_hw.c @@ -191,9 +191,7 @@ static u64 select_job_chain(struct kbase_jd_atom *katom) return jc; } -void kbase_job_hw_submit(struct kbase_device *kbdev, - struct kbase_jd_atom *katom, - int js) +int kbase_job_hw_submit(struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js) { struct kbase_context *kctx; u32 cfg; @@ -202,13 +200,13 @@ void kbase_job_hw_submit(struct kbase_device *kbdev, struct slot_rb *ptr_slot_rb = &kbdev->hwaccess.backend.slot_rb[js]; lockdep_assert_held(&kbdev->hwaccess_lock); - KBASE_DEBUG_ASSERT(kbdev); - KBASE_DEBUG_ASSERT(katom); kctx = katom->kctx; /* Command register must be available */ - KBASE_DEBUG_ASSERT(kbasep_jm_is_js_free(kbdev, js, kctx)); + if (WARN(!kbasep_jm_is_js_free(kbdev, js, kctx), + "Attempting to assign to occupied slot %d in kctx %pK\n", js, (void *)kctx)) + return -EPERM; dev_dbg(kctx->kbdev->dev, "Write JS_HEAD_NEXT 0x%llx for atom %pK\n", jc_head, (void *)katom); @@ -329,6 +327,8 @@ void kbase_job_hw_submit(struct kbase_device *kbdev, kbase_reg_write(kbdev, JOB_SLOT_REG(js, JS_COMMAND_NEXT), JS_COMMAND_START); + + return 0; } /** @@ -393,8 +393,6 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done) lockdep_assert_held(&kbdev->hwaccess_lock); - KBASE_DEBUG_ASSERT(kbdev); - KBASE_KTRACE_ADD_JM(kbdev, JM_IRQ, NULL, NULL, 0, done); end_timestamp = ktime_get_raw(); @@ -409,7 +407,8 @@ void kbase_job_done(struct kbase_device *kbdev, u32 done) * numbered interrupts before the higher numbered ones. */ i = ffs(finished) - 1; - KBASE_DEBUG_ASSERT(i >= 0); + if (WARN(i < 0, "%s: called without receiving any interrupts\n", __func__)) + break; do { int nr_done; @@ -619,7 +618,7 @@ void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, u64 job_in_head_before; u32 status_reg_after; - KBASE_DEBUG_ASSERT(!(action & (~JS_COMMAND_MASK))); + WARN_ON(action & (~JS_COMMAND_MASK)); /* Check the head pointer */ job_in_head_before = ((u64) kbase_reg_read(kbdev, @@ -697,7 +696,8 @@ void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_HARDSTOP_1, head_kctx, head, head->jc, js); break; default: - BUG(); + WARN(1, "Unknown action %d on atom %pK in kctx %pK\n", action, + (void *)target_katom, (void *)target_katom->kctx); break; } } else { @@ -726,7 +726,8 @@ void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_HARDSTOP_1, NULL, NULL, 0, js); break; default: - BUG(); + WARN(1, "Unknown action %d on atom %pK in kctx %pK\n", action, + (void *)target_katom, (void *)target_katom->kctx); break; } } @@ -752,9 +753,7 @@ void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx, int i; bool stop_sent = false; - KBASE_DEBUG_ASSERT(kctx != NULL); kbdev = kctx->kbdev; - KBASE_DEBUG_ASSERT(kbdev != NULL); lockdep_assert_held(&kbdev->hwaccess_lock); @@ -934,7 +933,11 @@ void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, int js, dev_dbg(kbdev->dev, "Soft-stop atom %pK with flags 0x%x (s:%d)\n", target_katom, sw_flags, js); - KBASE_DEBUG_ASSERT(!(sw_flags & JS_COMMAND_MASK)); + if (sw_flags & JS_COMMAND_MASK) { + WARN(true, "Atom %pK in kctx %pK received non-NOP flags %d\n", (void *)target_katom, + target_katom ? (void *)target_katom->kctx : NULL, sw_flags); + sw_flags &= ~((u32)JS_COMMAND_MASK); + } kbase_backend_soft_hard_stop_slot(kbdev, NULL, js, target_katom, JS_COMMAND_SOFT_STOP | sw_flags); } @@ -1059,12 +1062,9 @@ static void kbasep_reset_timeout_worker(struct work_struct *data) bool silent = false; u32 max_loops = KBASE_CLEAN_CACHE_MAX_LOOPS; - KBASE_DEBUG_ASSERT(data); - kbdev = container_of(data, struct kbase_device, hwaccess.backend.reset_work); - KBASE_DEBUG_ASSERT(kbdev); js_devdata = &kbdev->js_data; if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) == @@ -1102,7 +1102,7 @@ static void kbasep_reset_timeout_worker(struct work_struct *data) return; } - KBASE_DEBUG_ASSERT(kbdev->irq_reset_flush == false); + WARN(kbdev->irq_reset_flush, "%s: GPU reset already in flight\n", __func__); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); spin_lock(&kbdev->mmu_mask_change); @@ -1143,7 +1143,8 @@ static void kbasep_reset_timeout_worker(struct work_struct *data) mutex_lock(&kbdev->pm.lock); /* We hold the pm lock, so there ought to be a current policy */ - KBASE_DEBUG_ASSERT(kbdev->pm.backend.pm_current_policy); + if (unlikely(!kbdev->pm.backend.pm_current_policy)) + dev_warn(kbdev->dev, "No power policy set!"); /* All slot have been soft-stopped and we've waited * SOFT_STOP_RESET_TIMEOUT for the slots to clear, at this point we @@ -1240,8 +1241,6 @@ static enum hrtimer_restart kbasep_reset_timer_callback(struct hrtimer *timer) struct kbase_device *kbdev = container_of(timer, struct kbase_device, hwaccess.backend.reset_timer); - KBASE_DEBUG_ASSERT(kbdev); - /* Reset still pending? */ if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_COMMITTED, KBASE_RESET_GPU_HAPPENING) == @@ -1262,8 +1261,6 @@ static void kbasep_try_reset_gpu_early_locked(struct kbase_device *kbdev) int i; int pending_jobs = 0; - KBASE_DEBUG_ASSERT(kbdev); - /* Count the number of jobs */ for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) pending_jobs += kbase_backend_nr_atoms_submitted(kbdev, i); @@ -1321,8 +1318,6 @@ bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev, { int i; - KBASE_DEBUG_ASSERT(kbdev); - #ifdef CONFIG_MALI_ARBITER_SUPPORT if (kbase_pm_is_gpu_lost(kbdev)) { /* GPU access has been removed, reset will be done by @@ -1376,13 +1371,11 @@ KBASE_EXPORT_TEST_API(kbase_prepare_to_reset_gpu); */ void kbase_reset_gpu(struct kbase_device *kbdev) { - KBASE_DEBUG_ASSERT(kbdev); - /* Note this is an assert/atomic_set because it is a software issue for * a race to be occurring here */ - KBASE_DEBUG_ASSERT(atomic_read(&kbdev->hwaccess.backend.reset_gpu) == - KBASE_RESET_GPU_PREPARED); + if (WARN_ON(atomic_read(&kbdev->hwaccess.backend.reset_gpu) != KBASE_RESET_GPU_PREPARED)) + return; atomic_set(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_COMMITTED); @@ -1401,13 +1394,11 @@ KBASE_EXPORT_TEST_API(kbase_reset_gpu); void kbase_reset_gpu_locked(struct kbase_device *kbdev) { - KBASE_DEBUG_ASSERT(kbdev); - /* Note this is an assert/atomic_set because it is a software issue for * a race to be occurring here */ - KBASE_DEBUG_ASSERT(atomic_read(&kbdev->hwaccess.backend.reset_gpu) == - KBASE_RESET_GPU_PREPARED); + if (WARN_ON(atomic_read(&kbdev->hwaccess.backend.reset_gpu) != KBASE_RESET_GPU_PREPARED)) + return; atomic_set(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_COMMITTED); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_internal.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_internal.h index 1039e851f959..1ebb8434046c 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_internal.h +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_internal.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2011-2016, 2018-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2011-2016, 2018-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -76,7 +76,6 @@ static inline int kbasep_jm_is_js_free(struct kbase_device *kbdev, int js, } #endif - /** * kbase_job_hw_submit() - Submit a job to the GPU * @kbdev: Device pointer @@ -88,10 +87,10 @@ static inline int kbasep_jm_is_js_free(struct kbase_device *kbdev, int js, * * The following locking conditions are made on the caller: * - it must hold the hwaccess_lock + * + * Return: 0 if the job was successfully submitted to hardware, an error otherwise. */ -void kbase_job_hw_submit(struct kbase_device *kbdev, - struct kbase_jd_atom *katom, - int js); +int kbase_job_hw_submit(struct kbase_device *kbdev, struct kbase_jd_atom *katom, int js); #if !MALI_USE_CSF /** diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.c index c49c2cb17085..9960beb2e9b4 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_jm_rb.c @@ -347,16 +347,35 @@ static void kbase_gpu_release_atom(struct kbase_device *kbdev, katom->protected_state.exit != KBASE_ATOM_EXIT_PROTECTED_CHECK) kbdev->protected_mode_transition = false; + + /* If the atom is at KBASE_ATOM_ENTER_PROTECTED_HWCNT state, it means + * one of two events prevented it from progressing to the next state and + * ultimately reach protected mode: + * - hwcnts were enabled, and the atom had to schedule a worker to + * disable them. + * - the hwcnts were already disabled, but some other error occurred. + * In the first case, if the worker has not yet completed + * (kbdev->protected_mode_hwcnt_disabled == false), we need to re-enable + * them and signal to the worker they have already been enabled + */ + if (kbase_jd_katom_is_protected(katom) && + (katom->protected_state.enter == KBASE_ATOM_ENTER_PROTECTED_HWCNT)) { + kbdev->protected_mode_hwcnt_desired = true; + if (kbdev->protected_mode_hwcnt_disabled) { + kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); + kbdev->protected_mode_hwcnt_disabled = false; + } + } + /* If the atom has suspended hwcnt but has not yet entered * protected mode, then resume hwcnt now. If the GPU is now in * protected mode then hwcnt will be resumed by GPU reset so * don't resume it here. */ if (kbase_jd_katom_is_protected(katom) && - ((katom->protected_state.enter == - KBASE_ATOM_ENTER_PROTECTED_IDLE_L2) || - (katom->protected_state.enter == - KBASE_ATOM_ENTER_PROTECTED_SET_COHERENCY))) { + ((katom->protected_state.enter == KBASE_ATOM_ENTER_PROTECTED_IDLE_L2) || + (katom->protected_state.enter == KBASE_ATOM_ENTER_PROTECTED_SET_COHERENCY) || + (katom->protected_state.enter == KBASE_ATOM_ENTER_PROTECTED_FINISHED))) { WARN_ON(!kbdev->protected_mode_hwcnt_disabled); kbdev->protected_mode_hwcnt_desired = true; if (kbdev->protected_mode_hwcnt_disabled) { @@ -507,17 +526,14 @@ static int kbase_jm_protected_entry(struct kbase_device *kbdev, KBASE_TLSTREAM_AUX_PROTECTED_ENTER_END(kbdev, kbdev); if (err) { /* - * Failed to switch into protected mode, resume - * GPU hwcnt and fail atom. + * Failed to switch into protected mode. + * + * At this point we expect: + * katom->gpu_rb_state = KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION && + * katom->protected_state.enter = KBASE_ATOM_ENTER_PROTECTED_FINISHED + * ==> + * kbdev->protected_mode_hwcnt_disabled = false */ - WARN_ON(!kbdev->protected_mode_hwcnt_disabled); - kbdev->protected_mode_hwcnt_desired = true; - if (kbdev->protected_mode_hwcnt_disabled) { - kbase_hwcnt_context_enable( - kbdev->hwcnt_gpu_ctx); - kbdev->protected_mode_hwcnt_disabled = false; - } - katom[idx]->event_code = BASE_JD_EVENT_JOB_INVALID; kbase_gpu_mark_atom_for_return(kbdev, katom[idx]); /* @@ -537,12 +553,9 @@ static int kbase_jm_protected_entry(struct kbase_device *kbdev, /* * Protected mode sanity checks. */ - KBASE_DEBUG_ASSERT_MSG( - kbase_jd_katom_is_protected(katom[idx]) == - kbase_gpu_in_protected_mode(kbdev), - "Protected mode of atom (%d) doesn't match protected mode of GPU (%d)", - kbase_jd_katom_is_protected(katom[idx]), - kbase_gpu_in_protected_mode(kbdev)); + WARN(kbase_jd_katom_is_protected(katom[idx]) != kbase_gpu_in_protected_mode(kbdev), + "Protected mode of atom (%d) doesn't match protected mode of GPU (%d)", + kbase_jd_katom_is_protected(katom[idx]), kbase_gpu_in_protected_mode(kbdev)); katom[idx]->gpu_rb_state = KBASE_ATOM_GPU_RB_READY; @@ -952,18 +965,6 @@ void kbase_backend_slot_update(struct kbase_device *kbdev) cores_ready = kbase_pm_cores_requested(kbdev, true); - if (katom[idx]->event_code == - BASE_JD_EVENT_PM_EVENT) { - KBASE_KTRACE_ADD_JM_SLOT_INFO( - kbdev, JM_MARK_FOR_RETURN_TO_JS, - katom[idx]->kctx, katom[idx], - katom[idx]->jc, js, - katom[idx]->event_code); - katom[idx]->gpu_rb_state = - KBASE_ATOM_GPU_RB_RETURN_TO_JS; - break; - } - if (!cores_ready) break; @@ -1012,9 +1013,10 @@ void kbase_backend_slot_update(struct kbase_device *kbdev) kbase_pm_request_gpu_cycle_counter_l2_is_on( kbdev); - kbase_job_hw_submit(kbdev, katom[idx], js); - katom[idx]->gpu_rb_state = - KBASE_ATOM_GPU_RB_SUBMITTED; + if (!kbase_job_hw_submit(kbdev, katom[idx], js)) + katom[idx]->gpu_rb_state = KBASE_ATOM_GPU_RB_SUBMITTED; + else + break; /* ***TRANSITION TO HIGHER STATE*** */ fallthrough; @@ -1407,14 +1409,14 @@ void kbase_backend_reset(struct kbase_device *kbdev, ktime_t *end_timestamp) if (katom->protected_state.exit == KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT) { /* protected mode sanity checks */ - KBASE_DEBUG_ASSERT_MSG( - kbase_jd_katom_is_protected(katom) == kbase_gpu_in_protected_mode(kbdev), - "Protected mode of atom (%d) doesn't match protected mode of GPU (%d)", - kbase_jd_katom_is_protected(katom), kbase_gpu_in_protected_mode(kbdev)); - KBASE_DEBUG_ASSERT_MSG( - (kbase_jd_katom_is_protected(katom) && js == 0) || - !kbase_jd_katom_is_protected(katom), - "Protected atom on JS%d not supported", js); + WARN(kbase_jd_katom_is_protected(katom) != + kbase_gpu_in_protected_mode(kbdev), + "Protected mode of atom (%d) doesn't match protected mode of GPU (%d)", + kbase_jd_katom_is_protected(katom), + kbase_gpu_in_protected_mode(kbdev)); + WARN(!(kbase_jd_katom_is_protected(katom) && js == 0) && + kbase_jd_katom_is_protected(katom), + "Protected atom on JS%d not supported", js); } if ((katom->gpu_rb_state < KBASE_ATOM_GPU_RB_SUBMITTED) && !kbase_ctx_flag(katom->kctx, KCTX_DYING)) @@ -1805,11 +1807,9 @@ void kbase_backend_complete_wq_post_sched(struct kbase_device *kbdev, base_jd_core_req core_req) { if (!kbdev->pm.active_count) { - mutex_lock(&kbdev->js_data.runpool_mutex); - mutex_lock(&kbdev->pm.lock); + kbase_pm_lock(kbdev); kbase_pm_update_active(kbdev); - mutex_unlock(&kbdev->pm.lock); - mutex_unlock(&kbdev->js_data.runpool_mutex); + kbase_pm_unlock(kbdev); } } diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_model_dummy.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_model_dummy.c index 12c6bb791e98..e4f4b2455925 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_model_dummy.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_model_dummy.c @@ -1066,7 +1066,7 @@ static void midgard_model_get_outputs(void *h) hw_error_status.gpu_error_irq || #if !MALI_USE_CSF dummy->prfcnt_sample_completed || -#endif /* !MALI_USE_CSF */ +#endif (dummy->clean_caches_completed && dummy->clean_caches_completed_irq_enabled)) gpu_device_raise_irq(dummy, GPU_DUMMY_GPU_IRQ); @@ -1247,7 +1247,7 @@ u8 midgard_model_write_reg(void *h, u32 addr, u32 value) if (value & (1 << 17)) dummy->clean_caches_completed = false; -#if !MALI_USE_CSF +#if !MALI_USE_CSF if (value & PRFCNT_SAMPLE_COMPLETED) dummy->prfcnt_sample_completed = 0; #endif /* !MALI_USE_CSF */ @@ -1274,7 +1274,7 @@ u8 midgard_model_write_reg(void *h, u32 addr, u32 value) pr_debug("clean caches requested"); dummy->clean_caches_completed = true; break; -#if !MALI_USE_CSF +#if !MALI_USE_CSF case GPU_COMMAND_PRFCNT_SAMPLE: midgard_model_dump_prfcnt(); dummy->prfcnt_sample_completed = 1; @@ -1545,7 +1545,8 @@ u8 midgard_model_read_reg(void *h, u32 addr, u32 * const value) #endif /* !MALI_USE_CSF */ else if (addr == GPU_CONTROL_REG(GPU_IRQ_MASK)) { *value = (dummy->reset_completed_mask << 8) | - (dummy->power_changed_mask << 9) | (1 << 7) | 1; + ((dummy->clean_caches_completed_irq_enabled ? 1u : 0u) << 17) | + (dummy->power_changed_mask << 9) | (1 << 7) | 1; pr_debug("GPU_IRQ_MASK read %x", *value); } else if (addr == GPU_CONTROL_REG(GPU_IRQ_RAWSTAT)) { *value = (dummy->power_changed << 9) | (dummy->power_changed << 10) | diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c index 90e580b906f3..df735d95de9f 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_backend.c @@ -422,8 +422,7 @@ static void kbase_pm_l2_clock_slow(struct kbase_device *kbdev) return; /* Stop the metrics gathering framework */ - if (kbase_pm_metrics_is_active(kbdev)) - kbase_pm_metrics_stop(kbdev); + kbase_pm_metrics_stop(kbdev); /* Keep the current freq to restore it upon resume */ kbdev->previous_frequency = clk_get_rate(clk); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h index faacbb929818..75d99a30efc0 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_defs.h @@ -144,7 +144,7 @@ struct kbasep_pm_metrics { * @initialized: tracks whether metrics_state has been initialized or not. * @timer: timer to regularly make DVFS decisions based on the power * management metrics. - * @timer_active: boolean indicating @timer is running + * @timer_state: atomic indicating current @timer state, on, off, or stopped. * @dvfs_last: values of the PM metrics from the last DVFS tick * @dvfs_diff: different between the current and previous PM metrics. */ @@ -168,7 +168,7 @@ struct kbasep_pm_metrics_state { #ifdef CONFIG_MALI_BIFROST_DVFS bool initialized; struct hrtimer timer; - bool timer_active; + atomic_t timer_state; struct kbasep_pm_metrics dvfs_last; struct kbasep_pm_metrics dvfs_diff; #endif diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c index 794a6066a6eb..94b87ce7166b 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_driver.c @@ -939,7 +939,7 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) case KBASE_MCU_ON_PEND_HALT: if (kbase_csf_firmware_mcu_halted(kbdev)) { - KBASE_KTRACE_ADD(kbdev, MCU_HALTED, NULL, + KBASE_KTRACE_ADD(kbdev, CSF_FIRMWARE_MCU_HALTED, NULL, kbase_csf_ktrace_gpu_cycle_cnt(kbdev)); if (kbdev->csf.firmware_hctl_core_pwr) backend->mcu_state = @@ -986,7 +986,7 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) case KBASE_MCU_ON_PEND_SLEEP: if (kbase_csf_firmware_is_mcu_in_sleep(kbdev)) { - KBASE_KTRACE_ADD(kbdev, MCU_IN_SLEEP, NULL, + KBASE_KTRACE_ADD(kbdev, CSF_FIRMWARE_MCU_SLEEP, NULL, kbase_csf_ktrace_gpu_cycle_cnt(kbdev)); backend->mcu_state = KBASE_MCU_IN_SLEEP; kbase_pm_enable_db_mirror_interrupt(kbdev); @@ -1108,13 +1108,24 @@ static bool can_power_down_l2(struct kbase_device *kbdev) #endif } +static bool need_tiler_control(struct kbase_device *kbdev) +{ +#if MALI_USE_CSF + if (kbase_pm_no_mcu_core_pwroff(kbdev)) + return true; + else + return false; +#else + return true; +#endif +} + static int kbase_pm_l2_update_state(struct kbase_device *kbdev) { struct kbase_pm_backend_data *backend = &kbdev->pm.backend; u64 l2_present = kbdev->gpu_props.curr_config.l2_present; -#if !MALI_USE_CSF u64 tiler_present = kbdev->gpu_props.props.raw_props.tiler_present; -#endif + bool l2_power_up_done; enum kbase_l2_core_state prev_state; lockdep_assert_held(&kbdev->hwaccess_lock); @@ -1125,24 +1136,18 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) KBASE_PM_CORE_L2); u64 l2_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2); - -#if !MALI_USE_CSF - u64 tiler_trans = kbase_pm_get_trans_cores(kbdev, - KBASE_PM_CORE_TILER); - u64 tiler_ready = kbase_pm_get_ready_cores(kbdev, - KBASE_PM_CORE_TILER); -#endif +#ifdef CONFIG_MALI_ARBITER_SUPPORT + u64 tiler_trans = kbase_pm_get_trans_cores( + kbdev, KBASE_PM_CORE_TILER); + u64 tiler_ready = kbase_pm_get_ready_cores( + kbdev, KBASE_PM_CORE_TILER); /* * kbase_pm_get_ready_cores and kbase_pm_get_trans_cores * are vulnerable to corruption if gpu is lost */ if (kbase_is_gpu_removed(kbdev) -#ifdef CONFIG_MALI_ARBITER_SUPPORT || kbase_pm_is_gpu_lost(kbdev)) { -#else - ) { -#endif backend->shaders_state = KBASE_SHADERS_OFF_CORESTACK_OFF; backend->hwcnt_desired = false; @@ -1165,14 +1170,13 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) } break; } +#endif /* CONFIG_MALI_ARBITER_SUPPORT */ /* mask off ready from trans in case transitions finished * between the register reads */ l2_trans &= ~l2_ready; -#if !MALI_USE_CSF - tiler_trans &= ~tiler_ready; -#endif + prev_state = backend->l2_state; switch (backend->l2_state) { @@ -1184,13 +1188,21 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) */ kbase_pm_l2_config_override(kbdev); kbase_pbha_write_settings(kbdev); -#if !MALI_USE_CSF - /* L2 is required, power on. Powering on the - * tiler will also power the first L2 cache. - */ - kbase_pm_invoke(kbdev, KBASE_PM_CORE_TILER, - tiler_present, ACTION_PWRON); + /* If Host is controlling the power for shader + * cores, then it also needs to control the + * power for Tiler. + * Powering on the tiler will also power the + * L2 cache. + */ + if (need_tiler_control(kbdev)) { + kbase_pm_invoke(kbdev, KBASE_PM_CORE_TILER, tiler_present, + ACTION_PWRON); + } else { + kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, l2_present, + ACTION_PWRON); + } +#if !MALI_USE_CSF /* If we have more than one L2 cache then we * must power them on explicitly. */ @@ -1200,30 +1212,36 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) ACTION_PWRON); /* Clear backend slot submission kctx */ kbase_pm_l2_clear_backend_slot_submit_kctx(kbdev); -#else - /* With CSF firmware, Host driver doesn't need to - * handle power management with both shader and tiler cores. - * The CSF firmware will power up the cores appropriately. - * So only power the l2 cache explicitly. - */ - kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, - l2_present, ACTION_PWRON); #endif backend->l2_state = KBASE_L2_PEND_ON; } break; case KBASE_L2_PEND_ON: -#if !MALI_USE_CSF - if (!l2_trans && l2_ready == l2_present && !tiler_trans - && tiler_ready == tiler_present) { - KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL, - tiler_ready); -#else + l2_power_up_done = false; if (!l2_trans && l2_ready == l2_present) { - KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_L2, NULL, - l2_ready); + if (need_tiler_control(kbdev)) { +#ifndef CONFIG_MALI_ARBITER_SUPPORT + u64 tiler_trans = kbase_pm_get_trans_cores( + kbdev, KBASE_PM_CORE_TILER); + u64 tiler_ready = kbase_pm_get_ready_cores( + kbdev, KBASE_PM_CORE_TILER); #endif + + tiler_trans &= ~tiler_ready; + if (!tiler_trans && tiler_ready == tiler_present) { + KBASE_KTRACE_ADD(kbdev, + PM_CORES_CHANGE_AVAILABLE_TILER, + NULL, tiler_ready); + l2_power_up_done = true; + } + } else { + KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_L2, NULL, + l2_ready); + l2_power_up_done = true; + } + } + if (l2_power_up_done) { /* * Ensure snoops are enabled after L2 is powered * up. Note that kbase keeps track of the snoop @@ -2248,12 +2266,14 @@ int kbase_pm_wait_for_l2_powered(struct kbase_device *kbdev) /* Wait for cores */ #if KERNEL_VERSION(4, 13, 1) <= LINUX_VERSION_CODE - remaining = wait_event_killable_timeout( + remaining = wait_event_killable_timeout(kbdev->pm.backend.gpu_in_desired_state_wait, + kbase_pm_is_in_desired_state_with_l2_powered(kbdev), + timeout); #else remaining = wait_event_timeout( -#endif kbdev->pm.backend.gpu_in_desired_state_wait, kbase_pm_is_in_desired_state_with_l2_powered(kbdev), timeout); +#endif if (!remaining) { kbase_pm_timed_out(kbdev); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c index 675cfd7d6baf..4cc2d50db586 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_metrics.c @@ -49,27 +49,51 @@ #define GPU_ACTIVE_SCALING_FACTOR ((u64)1E9) #endif +/* + * Possible state transitions + * ON -> ON | OFF | STOPPED + * STOPPED -> ON | OFF + * OFF -> ON + * + * + * ┌─e─┐┌────────────f─────────────┐ + * │ v│ v + * └───ON ──a──> STOPPED ──b──> OFF + * ^^ │ │ + * │└──────c─────┘ │ + * │ │ + * └─────────────d─────────────┘ + * + * Transition effects: + * a. None + * b. Timer expires without restart + * c. Timer is not stopped, timer period is unaffected + * d. Timer must be restarted + * e. Callback is executed and the timer is restarted + * f. Timer is cancelled, or the callback is waited on if currently executing. This is called during + * tear-down and should not be subject to a race from an OFF->ON transition + */ +enum dvfs_metric_timer_state { TIMER_OFF, TIMER_STOPPED, TIMER_ON }; + #ifdef CONFIG_MALI_BIFROST_DVFS static enum hrtimer_restart dvfs_callback(struct hrtimer *timer) { - unsigned long flags; struct kbasep_pm_metrics_state *metrics; - KBASE_DEBUG_ASSERT(timer != NULL); + if (WARN_ON(!timer)) + return HRTIMER_NORESTART; metrics = container_of(timer, struct kbasep_pm_metrics_state, timer); + + /* Transition (b) to fully off if timer was stopped, don't restart the timer in this case */ + if (atomic_cmpxchg(&metrics->timer_state, TIMER_STOPPED, TIMER_OFF) != TIMER_ON) + return HRTIMER_NORESTART; + kbase_pm_get_dvfs_action(metrics->kbdev); - spin_lock_irqsave(&metrics->lock, flags); - - if (metrics->timer_active) - hrtimer_start(timer, - HR_TIMER_DELAY_MSEC(metrics->kbdev->pm.dvfs_period), - HRTIMER_MODE_REL); - - spin_unlock_irqrestore(&metrics->lock, flags); - - return HRTIMER_NORESTART; + /* Set the new expiration time and restart (transition e) */ + hrtimer_forward_now(timer, HR_TIMER_DELAY_MSEC(metrics->kbdev->pm.dvfs_period)); + return HRTIMER_RESTART; } #endif /* CONFIG_MALI_BIFROST_DVFS */ @@ -135,6 +159,7 @@ int kbasep_pm_metrics_init(struct kbase_device *kbdev) HRTIMER_MODE_REL); kbdev->pm.backend.metrics.timer.function = dvfs_callback; kbdev->pm.backend.metrics.initialized = true; + atomic_set(&kbdev->pm.backend.metrics.timer_state, TIMER_OFF); kbase_pm_metrics_start(kbdev); #endif /* CONFIG_MALI_BIFROST_DVFS */ @@ -153,16 +178,12 @@ KBASE_EXPORT_TEST_API(kbasep_pm_metrics_init); void kbasep_pm_metrics_term(struct kbase_device *kbdev) { #ifdef CONFIG_MALI_BIFROST_DVFS - unsigned long flags; - KBASE_DEBUG_ASSERT(kbdev != NULL); - spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); - kbdev->pm.backend.metrics.timer_active = false; - spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); - - hrtimer_cancel(&kbdev->pm.backend.metrics.timer); + /* Cancel the timer, and block if the callback is currently executing (transition f) */ kbdev->pm.backend.metrics.initialized = false; + atomic_set(&kbdev->pm.backend.metrics.timer_state, TIMER_OFF); + hrtimer_cancel(&kbdev->pm.backend.metrics.timer); #endif /* CONFIG_MALI_BIFROST_DVFS */ #if MALI_USE_CSF @@ -399,57 +420,33 @@ void kbase_pm_get_dvfs_action(struct kbase_device *kbdev) bool kbase_pm_metrics_is_active(struct kbase_device *kbdev) { - bool isactive; - unsigned long flags; - KBASE_DEBUG_ASSERT(kbdev != NULL); - spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); - isactive = kbdev->pm.backend.metrics.timer_active; - spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); - - return isactive; + return atomic_read(&kbdev->pm.backend.metrics.timer_state) == TIMER_ON; } KBASE_EXPORT_TEST_API(kbase_pm_metrics_is_active); void kbase_pm_metrics_start(struct kbase_device *kbdev) { - unsigned long flags; - bool update = true; + struct kbasep_pm_metrics_state *metrics = &kbdev->pm.backend.metrics; - if (unlikely(!kbdev->pm.backend.metrics.initialized)) + if (unlikely(!metrics->initialized)) return; - spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); - if (!kbdev->pm.backend.metrics.timer_active) - kbdev->pm.backend.metrics.timer_active = true; - else - update = false; - spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); - - if (update) - hrtimer_start(&kbdev->pm.backend.metrics.timer, - HR_TIMER_DELAY_MSEC(kbdev->pm.dvfs_period), - HRTIMER_MODE_REL); + /* Transition to ON, from a stopped state (transition c) */ + if (atomic_xchg(&metrics->timer_state, TIMER_ON) == TIMER_OFF) + /* Start the timer only if it's been fully stopped (transition d)*/ + hrtimer_start(&metrics->timer, HR_TIMER_DELAY_MSEC(kbdev->pm.dvfs_period), + HRTIMER_MODE_REL); } void kbase_pm_metrics_stop(struct kbase_device *kbdev) { - unsigned long flags; - bool update = true; - if (unlikely(!kbdev->pm.backend.metrics.initialized)) return; - spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); - if (kbdev->pm.backend.metrics.timer_active) - kbdev->pm.backend.metrics.timer_active = false; - else - update = false; - spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); - - if (update) - hrtimer_cancel(&kbdev->pm.backend.metrics.timer); + /* Timer is Stopped if its currently on (transition a) */ + atomic_cmpxchg(&kbdev->pm.backend.metrics.timer_state, TIMER_ON, TIMER_STOPPED); } diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c index 306266cf075b..4788f04132c1 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_policy.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2010-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2010-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -292,6 +292,8 @@ void kbase_pm_set_policy(struct kbase_device *kbdev, unsigned int new_policy_csf_pm_sched_flags; bool sched_suspend; bool reset_gpu = false; + bool reset_op_prevented = true; + struct kbase_csf_scheduler *scheduler = NULL; #endif KBASE_DEBUG_ASSERT(kbdev != NULL); @@ -300,9 +302,23 @@ void kbase_pm_set_policy(struct kbase_device *kbdev, KBASE_KTRACE_ADD(kbdev, PM_SET_POLICY, NULL, new_policy->id); #if MALI_USE_CSF + scheduler = &kbdev->csf.scheduler; + KBASE_DEBUG_ASSERT(scheduler != NULL); + /* Serialize calls on kbase_pm_set_policy() */ mutex_lock(&kbdev->pm.backend.policy_change_lock); + if (kbase_reset_gpu_prevent_and_wait(kbdev)) { + dev_warn(kbdev->dev, "Set PM policy failing to prevent gpu reset"); + reset_op_prevented = false; + } + + /* In case of CSF, the scheduler may be invoked to suspend. In that + * case, there is a risk that the L2 may be turned on by the time we + * check it here. So we hold the scheduler lock to avoid other operations + * interfering with the policy change and vice versa. + */ + mutex_lock(&scheduler->lock); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); /* policy_change_clamp_state_to_off, when needed, is set/cleared in * this function, a very limited temporal scope for covering the @@ -315,24 +331,22 @@ void kbase_pm_set_policy(struct kbase_device *kbdev, * the always_on policy, reflected by the CSF_DYNAMIC_PM_CORE_KEEP_ON * flag bit. */ - sched_suspend = kbdev->csf.firmware_inited && + sched_suspend = reset_op_prevented && (CSF_DYNAMIC_PM_CORE_KEEP_ON & - (new_policy_csf_pm_sched_flags | - kbdev->pm.backend.csf_pm_sched_flags)); + (new_policy_csf_pm_sched_flags | kbdev->pm.backend.csf_pm_sched_flags)); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - if (sched_suspend) - kbase_csf_scheduler_pm_suspend(kbdev); + if (sched_suspend) { + /* Update the suspend flag to reflect actually suspend being done ! */ + sched_suspend = !kbase_csf_scheduler_pm_suspend_no_lock(kbdev); + /* Set the reset recovery flag if the required suspend failed */ + reset_gpu = !sched_suspend; + } spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - /* If the current active policy is always_on, one needs to clamp the - * MCU/L2 for reaching off-state - */ - if (sched_suspend) - kbdev->pm.backend.policy_change_clamp_state_to_off = - CSF_DYNAMIC_PM_CORE_KEEP_ON & kbdev->pm.backend.csf_pm_sched_flags; + kbdev->pm.backend.policy_change_clamp_state_to_off = sched_suspend; kbase_pm_update_state(kbdev); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); @@ -391,13 +405,19 @@ void kbase_pm_set_policy(struct kbase_device *kbdev, #if MALI_USE_CSF /* Reverse the suspension done */ + if (sched_suspend) + kbase_csf_scheduler_pm_resume_no_lock(kbdev); + mutex_unlock(&scheduler->lock); + + if (reset_op_prevented) + kbase_reset_gpu_allow(kbdev); + if (reset_gpu) { dev_warn(kbdev->dev, "Resorting to GPU reset for policy change\n"); if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE)) kbase_reset_gpu(kbdev); kbase_reset_gpu_wait(kbdev); - } else if (sched_suspend) - kbase_csf_scheduler_pm_resume(kbdev); + } mutex_unlock(&kbdev->pm.backend.policy_change_lock); #endif diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c index e5f92cb34159..6bee1fff324a 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_time.c @@ -116,8 +116,6 @@ unsigned int kbase_get_timeout_ms(struct kbase_device *kbdev, */ u64 timeout, nr_cycles = 0; - /* Default value to mean 'no cap' */ - u64 timeout_cap = U64_MAX; u64 freq_khz; /* Only for debug messages, safe default in case it's mis-maintained */ @@ -144,16 +142,15 @@ unsigned int kbase_get_timeout_ms(struct kbase_device *kbdev, fallthrough; case CSF_FIRMWARE_TIMEOUT: selector_str = "CSF_FIRMWARE_TIMEOUT"; - nr_cycles = CSF_FIRMWARE_TIMEOUT_CYCLES; - /* Setup a cap on CSF FW timeout to FIRMWARE_PING_INTERVAL_MS, - * if calculated timeout exceeds it. This should be adapted to - * a direct timeout comparison once the - * FIRMWARE_PING_INTERVAL_MS option is added to this timeout - * function. A compile-time check such as BUILD_BUG_ON can also - * be done once the firmware ping interval in cycles becomes - * available as a macro. + /* Any FW timeout cannot be longer than the FW ping interval, after which + * the firmware_aliveness_monitor will be triggered and may restart + * the GPU if the FW is unresponsive. */ - timeout_cap = FIRMWARE_PING_INTERVAL_MS; + nr_cycles = min(CSF_FIRMWARE_PING_TIMEOUT_CYCLES, CSF_FIRMWARE_TIMEOUT_CYCLES); + + if (nr_cycles == CSF_FIRMWARE_PING_TIMEOUT_CYCLES) + dev_warn(kbdev->dev, "Capping %s to CSF_FIRMWARE_PING_TIMEOUT\n", + selector_str); break; case CSF_PM_TIMEOUT: selector_str = "CSF_PM_TIMEOUT"; @@ -171,6 +168,10 @@ unsigned int kbase_get_timeout_ms(struct kbase_device *kbdev, selector_str = "CSF_FIRMWARE_BOOT_TIMEOUT"; nr_cycles = CSF_FIRMWARE_BOOT_TIMEOUT_CYCLES; break; + case CSF_FIRMWARE_PING_TIMEOUT: + selector_str = "CSF_FIRMWARE_PING_TIMEOUT"; + nr_cycles = CSF_FIRMWARE_PING_TIMEOUT_CYCLES; + break; case CSF_SCHED_PROTM_PROGRESS_TIMEOUT: selector_str = "CSF_SCHED_PROTM_PROGRESS_TIMEOUT"; nr_cycles = kbase_csf_timeout_get(kbdev); @@ -179,11 +180,6 @@ unsigned int kbase_get_timeout_ms(struct kbase_device *kbdev, } timeout = div_u64(nr_cycles, freq_khz); - if (timeout > timeout_cap) { - dev_dbg(kbdev->dev, "Capped %s %llu to %llu", selector_str, - (unsigned long long)timeout, (unsigned long long)timeout_cap); - timeout = timeout_cap; - } if (WARN(timeout > UINT_MAX, "Capping excessive timeout %llums for %s at freq %llukHz to UINT_MAX ms", (unsigned long long)timeout, selector_str, (unsigned long long)freq_khz)) diff --git a/drivers/gpu/arm/bifrost/build.bp b/drivers/gpu/arm/bifrost/build.bp index db02dd2e0052..977d13961786 100644 --- a/drivers/gpu/arm/bifrost/build.bp +++ b/drivers/gpu/arm/bifrost/build.bp @@ -139,6 +139,9 @@ bob_defaults { platform_is_fpga: { kbuild_options: ["CONFIG_MALI_IS_FPGA=y"], }, + mali_fw_core_dump: { + kbuild_options: ["CONFIG_MALI_FW_CORE_DUMP=y"], + }, kbuild_options: [ "CONFIG_MALI_PLATFORM_NAME={{.mali_platform_name}}", "MALI_CUSTOMER_RELEASE={{.release}}", diff --git a/drivers/gpu/arm/bifrost/context/mali_kbase_context.c b/drivers/gpu/arm/bifrost/context/mali_kbase_context.c index f5258bd9d8a0..f84e01edee93 100644 --- a/drivers/gpu/arm/bifrost/context/mali_kbase_context.c +++ b/drivers/gpu/arm/bifrost/context/mali_kbase_context.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2019-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -239,7 +239,9 @@ static void kbase_remove_kctx_from_process(struct kbase_context *kctx) /* Add checks, so that the terminating process Should not * hold any gpu_memory. */ + spin_lock(&kctx->kbdev->gpu_mem_usage_lock); WARN_ON(kprcs->total_gpu_pages); + spin_unlock(&kctx->kbdev->gpu_mem_usage_lock); WARN_ON(!RB_EMPTY_ROOT(&kprcs->dma_buf_root)); kfree(kprcs); } diff --git a/drivers/gpu/arm/bifrost/csf/Kbuild b/drivers/gpu/arm/bifrost/csf/Kbuild index 70ea295db617..c5d9154a2e35 100644 --- a/drivers/gpu/arm/bifrost/csf/Kbuild +++ b/drivers/gpu/arm/bifrost/csf/Kbuild @@ -40,6 +40,7 @@ bifrost_kbase-$(CONFIG_MALI_REAL_HW) += csf/mali_kbase_csf_firmware.o bifrost_kbase-$(CONFIG_MALI_BIFROST_NO_MALI) += csf/mali_kbase_csf_firmware_no_mali.o + ifeq ($(KBUILD_EXTMOD),) # in-tree -include $(src)/csf/ipa_control/Kbuild diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c index 497e05c9b691..45174b7caaa7 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2018-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2018-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -34,6 +34,7 @@ #include #include #include "mali_kbase_csf_event.h" +#include #define CS_REQ_EXCEPTION_MASK (CS_REQ_FAULT_MASK | CS_REQ_FATAL_MASK) #define CS_ACK_EXCEPTION_MASK (CS_ACK_FAULT_MASK | CS_ACK_FATAL_MASK) @@ -52,6 +53,23 @@ const u8 kbasep_csf_relative_to_queue_group_priority[KBASE_QUEUE_GROUP_PRIORITY_ BASE_QUEUE_GROUP_PRIORITY_LOW }; +/* + * struct irq_idle_and_protm_track - Object that tracks the idle and protected mode + * request information in an interrupt case across + * groups. + * + * @protm_grp: Possibly schedulable group that requested protected mode in the interrupt. + * If NULL, no such case observed in the tracked interrupt case. + * @idle_seq: The highest priority group that notified idle. If no such instance in the + * interrupt case, marked with the largest field value: U32_MAX. + * @idle_slot: The slot number if @p idle_seq is valid in the given tracking case. + */ +struct irq_idle_and_protm_track { + struct kbase_queue_group *protm_grp; + u32 idle_seq; + s8 idle_slot; +}; + static void put_user_pages_mmap_handle(struct kbase_context *kctx, struct kbase_queue *queue) { @@ -112,13 +130,13 @@ static int get_user_pages_mmap_handle(struct kbase_context *kctx, return 0; } -static void gpu_munmap_user_io_pages(struct kbase_context *kctx, - struct kbase_va_region *reg) +static void gpu_munmap_user_io_pages(struct kbase_context *kctx, struct kbase_va_region *reg, + struct tagged_addr *phys) { size_t num_pages = 2; - kbase_mmu_teardown_pages(kctx->kbdev, &kctx->kbdev->csf.mcu_mmu, - reg->start_pfn, num_pages, MCU_AS_NR); + kbase_mmu_teardown_pages(kctx->kbdev, &kctx->kbdev->csf.mcu_mmu, reg->start_pfn, phys, + num_pages, MCU_AS_NR); WARN_ON(reg->flags & KBASE_REG_FREE); @@ -159,12 +177,6 @@ static int gpu_mmap_user_io_pages(struct kbase_device *kbdev, */ const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_ASYNC; -#if ((KERNEL_VERSION(4, 4, 147) >= LINUX_VERSION_CODE) || \ - ((KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE) && \ - (KERNEL_VERSION(4, 5, 0) <= LINUX_VERSION_CODE))) - mem_flags |= - KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_NON_CACHEABLE); -#else if (kbdev->system_coherency == COHERENCY_NONE) { mem_flags |= KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_NON_CACHEABLE); @@ -172,7 +184,6 @@ static int gpu_mmap_user_io_pages(struct kbase_device *kbdev, mem_flags |= KBASE_REG_SHARE_BOTH | KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_SHARED); } -#endif mutex_lock(&kbdev->csf.reg_lock); ret = kbase_add_va_region_rbtree(kbdev, reg, 0, num_pages, 1); @@ -201,8 +212,7 @@ static int gpu_mmap_user_io_pages(struct kbase_device *kbdev, return 0; bad_insert_output_page: - kbase_mmu_teardown_pages(kbdev, &kbdev->csf.mcu_mmu, - reg->start_pfn, 1, MCU_AS_NR); + kbase_mmu_teardown_pages(kbdev, &kbdev->csf.mcu_mmu, reg->start_pfn, phys, 1, MCU_AS_NR); bad_insert: mutex_lock(&kbdev->csf.reg_lock); kbase_remove_va_region(kbdev, reg); @@ -231,6 +241,8 @@ static int kernel_map_user_io_pages(struct kbase_context *kctx, { struct page *page_list[2]; pgprot_t cpu_map_prot; + unsigned long flags; + char *user_io_addr; int ret = 0; size_t i; @@ -245,25 +257,19 @@ static int kernel_map_user_io_pages(struct kbase_context *kctx, /* The pages are mapped to Userspace also, so use the same mapping * attributes as used inside the CPU page fault handler. */ -#if ((KERNEL_VERSION(4, 4, 147) >= LINUX_VERSION_CODE) || \ - ((KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE) && \ - (KERNEL_VERSION(4, 5, 0) <= LINUX_VERSION_CODE))) - cpu_map_prot = pgprot_device(PAGE_KERNEL); -#else if (kctx->kbdev->system_coherency == COHERENCY_NONE) cpu_map_prot = pgprot_writecombine(PAGE_KERNEL); else cpu_map_prot = PAGE_KERNEL; -#endif for (i = 0; i < ARRAY_SIZE(page_list); i++) page_list[i] = as_page(queue->phys[i]); - queue->user_io_addr = vmap(page_list, ARRAY_SIZE(page_list), VM_MAP, cpu_map_prot); + user_io_addr = vmap(page_list, ARRAY_SIZE(page_list), VM_MAP, cpu_map_prot); - if (!queue->user_io_addr) { + if (!user_io_addr) { dev_err(kctx->kbdev->dev, - "%s(): queue->user_io_addr is NULL, queue: %p", + "%s(): user_io_addr is NULL, queue: %p", __func__, queue); ret = -ENOMEM; @@ -271,6 +277,10 @@ static int kernel_map_user_io_pages(struct kbase_context *kctx, atomic_add(ARRAY_SIZE(page_list), &kctx->permanent_mapped_pages); } + kbase_csf_scheduler_spin_lock(kctx->kbdev, &flags); + queue->user_io_addr = user_io_addr; + kbase_csf_scheduler_spin_unlock(kctx->kbdev, flags); + unlock: kbase_gpu_vm_unlock(kctx); return ret; @@ -307,7 +317,7 @@ static void kbase_csf_free_command_stream_user_pages(struct kbase_context *kctx, { const size_t num_pages = 2; - gpu_munmap_user_io_pages(kctx, queue->reg); + gpu_munmap_user_io_pages(kctx, queue->reg, &queue->phys[0]); kernel_unmap_user_io_pages(kctx, queue); kbase_mem_pool_free_pages( @@ -934,7 +944,7 @@ static void unbind_stopped_queue(struct kbase_context *kctx, kbase_csf_scheduler_spin_lock(kctx->kbdev, &flags); bitmap_clear(queue->group->protm_pending_bitmap, queue->csi_index, 1); - KBASE_KTRACE_ADD_CSF_GRP_Q(kctx->kbdev, PROTM_PENDING_CLEAR, + KBASE_KTRACE_ADD_CSF_GRP_Q(kctx->kbdev, CSI_PROTM_PEND_CLEAR, queue->group, queue, queue->group->protm_pending_bitmap[0]); queue->group->bound_queues[queue->csi_index] = NULL; queue->group = NULL; @@ -982,7 +992,7 @@ static void unbind_queue(struct kbase_context *kctx, struct kbase_queue *queue) } } -void kbase_csf_queue_unbind(struct kbase_queue *queue) +void kbase_csf_queue_unbind(struct kbase_queue *queue, bool process_exit) { struct kbase_context *kctx = queue->kctx; @@ -996,7 +1006,7 @@ void kbase_csf_queue_unbind(struct kbase_queue *queue) * whereas CSG TERM request would result in an immediate abort or * cancellation of the pending work. */ - if (current->flags & PF_EXITING) { + if (process_exit) { struct kbase_queue_group *group = get_bound_queue_group(queue); if (group) @@ -1344,10 +1354,12 @@ static int create_queue_group(struct kbase_context *const kctx, group->tiler_max = create->in.tiler_max; group->fragment_max = create->in.fragment_max; group->compute_max = create->in.compute_max; + group->csi_handlers = create->in.csi_handlers; group->priority = kbase_csf_priority_queue_group_priority_to_relative( kbase_csf_priority_check(kctx->kbdev, create->in.priority)); group->doorbell_nr = KBASEP_USER_DB_NR_INVALID; group->faulted = false; + group->reevaluate_idle_status = false; group->group_uid = generate_group_uid(); @@ -1391,6 +1403,14 @@ int kbase_csf_queue_group_create(struct kbase_context *const kctx, const u32 tiler_count = hweight64(create->in.tiler_mask); const u32 fragment_count = hweight64(create->in.fragment_mask); const u32 compute_count = hweight64(create->in.compute_mask); + size_t i; + + for (i = 0; i < sizeof(create->in.padding); i++) { + if (create->in.padding[i] != 0) { + dev_warn(kctx->kbdev->dev, "Invalid padding not 0 in queue group create\n"); + return -EINVAL; + } + } mutex_lock(&kctx->csf.lock); @@ -1409,6 +1429,10 @@ int kbase_csf_queue_group_create(struct kbase_context *const kctx, "No CSG has at least %d CSs", create->in.cs_min); err = -EINVAL; + } else if (create->in.csi_handlers & ~BASE_CSF_EXCEPTION_HANDLER_FLAGS_MASK) { + dev_warn(kctx->kbdev->dev, "Unknown exception handler flags set: %u", + create->in.csi_handlers & ~BASE_CSF_EXCEPTION_HANDLER_FLAGS_MASK); + err = -EINVAL; } else if (create->in.reserved) { dev_warn(kctx->kbdev->dev, "Reserved field was set to non-0"); err = -EINVAL; @@ -1447,9 +1471,8 @@ static void term_normal_suspend_buffer(struct kbase_context *const kctx, lockdep_assert_held(&kctx->csf.lock); - WARN_ON(kbase_mmu_teardown_pages( - kctx->kbdev, &kctx->kbdev->csf.mcu_mmu, - s_buf->reg->start_pfn, nr_pages, MCU_AS_NR)); + WARN_ON(kbase_mmu_teardown_pages(kctx->kbdev, &kctx->kbdev->csf.mcu_mmu, + s_buf->reg->start_pfn, s_buf->phy, nr_pages, MCU_AS_NR)); WARN_ON(s_buf->reg->flags & KBASE_REG_FREE); @@ -1479,10 +1502,16 @@ static void term_protected_suspend_buffer(struct kbase_device *const kbdev, { const size_t nr_pages = PFN_UP(kbdev->csf.global_iface.groups[0].suspend_size); + struct tagged_addr *phys = kmalloc(sizeof(*phys) * nr_pages, GFP_KERNEL); + size_t i = 0; - WARN_ON(kbase_mmu_teardown_pages( - kbdev, &kbdev->csf.mcu_mmu, - s_buf->reg->start_pfn, nr_pages, MCU_AS_NR)); + for (i = 0; phys && i < nr_pages; i++) + phys[i] = as_tagged(s_buf->pma[i]->pa); + + WARN_ON(kbase_mmu_teardown_pages(kbdev, &kbdev->csf.mcu_mmu, s_buf->reg->start_pfn, phys, + nr_pages, MCU_AS_NR)); + + kfree(phys); WARN_ON(s_buf->reg->flags & KBASE_REG_FREE); @@ -1929,7 +1958,7 @@ void kbase_csf_ctx_term(struct kbase_context *kctx) * handle_oom_event - Handle the OoM event generated by the firmware for the * CSI. * - * @kctx: Pointer to the kbase context in which the tiler heap was initialized. + * @group: Pointer to the CSG group the oom-event belongs to. * @stream: Pointer to the structure containing info provided by the firmware * about the CSI. * @@ -1944,9 +1973,10 @@ void kbase_csf_ctx_term(struct kbase_context *kctx) * Return: 0 if successfully handled the request, otherwise a negative error * code on failure. */ -static int handle_oom_event(struct kbase_context *const kctx, - struct kbase_csf_cmd_stream_info const *const stream) +static int handle_oom_event(struct kbase_queue_group *const group, + struct kbase_csf_cmd_stream_info const *const stream) { + struct kbase_context *const kctx = group->kctx; u64 gpu_heap_va = kbase_csf_firmware_cs_output(stream, CS_HEAP_ADDRESS_LO) | ((u64)kbase_csf_firmware_cs_output(stream, CS_HEAP_ADDRESS_HI) << 32); @@ -1973,12 +2003,18 @@ static int handle_oom_event(struct kbase_context *const kctx, err = kbase_csf_tiler_heap_alloc_new_chunk(kctx, gpu_heap_va, renderpasses_in_flight, pending_frag_count, &new_chunk_ptr); - /* It is okay to acknowledge with a NULL chunk (firmware will then wait - * for the fragment jobs to complete and release chunks) - */ - if (err == -EBUSY) + if ((group->csi_handlers & BASE_CSF_TILER_OOM_EXCEPTION_FLAG) && + (pending_frag_count == 0) && (err == -ENOMEM || err == -EBUSY)) { + /* The group allows incremental rendering, trigger it */ new_chunk_ptr = 0; - else if (err) + dev_dbg(kctx->kbdev->dev, "Group-%d (slot-%d) enter incremental render\n", + group->handle, group->csg_nr); + } else if (err == -EBUSY) { + /* Acknowledge with a NULL chunk (firmware will then wait for + * the fragment jobs to complete and release chunks) + */ + new_chunk_ptr = 0; + } else if (err) return err; kbase_csf_firmware_cs_input(stream, CS_TILER_HEAP_START_LO, @@ -2085,7 +2121,7 @@ static void kbase_queue_oom_event(struct kbase_queue *const queue) if (cs_oom_ack == cs_oom_req) goto unlock; - err = handle_oom_event(kctx, stream); + err = handle_oom_event(group, stream); kbase_csf_firmware_cs_input_mask(stream, CS_REQ, cs_oom_ack, CS_REQ_TILER_OOM_MASK); @@ -2221,7 +2257,7 @@ static void protm_event_worker(struct work_struct *data) struct kbase_queue_group *const group = container_of(data, struct kbase_queue_group, protm_event_work); - KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, PROTM_EVENT_WORKER_BEGIN, + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, PROTM_EVENT_WORKER_START, group, 0u); kbase_csf_scheduler_group_protm_enter(group); KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, PROTM_EVENT_WORKER_END, @@ -2441,6 +2477,9 @@ static void handle_queue_exception_event(struct kbase_queue *const queue, * @ginfo: The CSG interface provided by the firmware. * @irqreq: CSG's IRQ request bitmask (one bit per CS). * @irqack: CSG's IRQ acknowledge bitmask (one bit per CS). + * @track: Pointer that tracks the highest scanout priority idle CSG + * and any newly potentially viable protected mode requesting + * CSG in current IRQ context. * * If the interrupt request bitmask differs from the acknowledge bitmask * then the firmware is notifying the host of an event concerning those @@ -2449,8 +2488,9 @@ static void handle_queue_exception_event(struct kbase_queue *const queue, * the request and acknowledge registers for the individual CS(s). */ static void process_cs_interrupts(struct kbase_queue_group *const group, - struct kbase_csf_cmd_stream_group_info const *const ginfo, - u32 const irqreq, u32 const irqack) + struct kbase_csf_cmd_stream_group_info const *const ginfo, + u32 const irqreq, u32 const irqack, + struct irq_idle_and_protm_track *track) { struct kbase_device *const kbdev = group->kctx->kbdev; u32 remaining = irqreq ^ irqack; @@ -2482,7 +2522,8 @@ static void process_cs_interrupts(struct kbase_queue_group *const group, if ((cs_req & CS_REQ_EXCEPTION_MASK) ^ (cs_ack & CS_ACK_EXCEPTION_MASK)) { - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_FAULT_INTERRUPT, group, queue, cs_req ^ cs_ack); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_INTERRUPT_FAULT, + group, queue, cs_req ^ cs_ack); handle_queue_exception_event(queue, cs_req, cs_ack); } @@ -2494,16 +2535,18 @@ static void process_cs_interrupts(struct kbase_queue_group *const group, u32 const cs_req_remain = cs_req & ~CS_REQ_EXCEPTION_MASK; u32 const cs_ack_remain = cs_ack & ~CS_ACK_EXCEPTION_MASK; - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_IGNORED_INTERRUPTS_GROUP_SUSPEND, - group, queue, cs_req_remain ^ cs_ack_remain); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, + CSI_INTERRUPT_GROUP_SUSPENDS_IGNORED, + group, queue, + cs_req_remain ^ cs_ack_remain); continue; } if (((cs_req & CS_REQ_TILER_OOM_MASK) ^ (cs_ack & CS_ACK_TILER_OOM_MASK))) { get_queue(queue); - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_TILER_OOM_INTERRUPT, group, queue, - cs_req ^ cs_ack); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_INTERRUPT_TILER_OOM, + group, queue, cs_req ^ cs_ack); if (WARN_ON(!queue_work(wq, &queue->oom_event_work))) { /* The work item shall not have been * already queued, there can be only @@ -2516,8 +2559,8 @@ static void process_cs_interrupts(struct kbase_queue_group *const group, if ((cs_req & CS_REQ_PROTM_PEND_MASK) ^ (cs_ack & CS_ACK_PROTM_PEND_MASK)) { - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_PROTM_PEND_INTERRUPT, group, queue, - cs_req ^ cs_ack); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_INTERRUPT_PROTM_PEND, + group, queue, cs_req ^ cs_ack); dev_dbg(kbdev->dev, "Protected mode entry request for queue on csi %d bound to group-%d on slot %d", @@ -2525,7 +2568,7 @@ static void process_cs_interrupts(struct kbase_queue_group *const group, group->csg_nr); bitmap_set(group->protm_pending_bitmap, i, 1); - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, PROTM_PENDING_SET, group, queue, + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_PROTM_PEND_SET, group, queue, group->protm_pending_bitmap[0]); protm_pend = true; } @@ -2534,12 +2577,10 @@ static void process_cs_interrupts(struct kbase_queue_group *const group, if (protm_pend) { struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; - u32 current_protm_pending_seq = - scheduler->tick_protm_pending_seq; - if (current_protm_pending_seq > group->scan_seq_num) { + if (scheduler->tick_protm_pending_seq > group->scan_seq_num) { scheduler->tick_protm_pending_seq = group->scan_seq_num; - queue_work(group->kctx->csf.wq, &group->protm_event_work); + track->protm_grp = group; } if (test_bit(group->csg_nr, scheduler->csg_slots_idle_mask)) { @@ -2557,6 +2598,8 @@ static void process_cs_interrupts(struct kbase_queue_group *const group, * * @kbdev: Instance of a GPU platform device that implements a CSF interface. * @csg_nr: CSG number. + * @track: Pointer that tracks the highest idle CSG and the newly possible viable + * protected mode requesting group, in current IRQ context. * * Handles interrupts for a CSG and for CSs within it. * @@ -2567,8 +2610,8 @@ static void process_cs_interrupts(struct kbase_queue_group *const group, * * See process_cs_interrupts() for details of per-stream interrupt handling. */ -static void process_csg_interrupts(struct kbase_device *const kbdev, - int const csg_nr) +static void process_csg_interrupts(struct kbase_device *const kbdev, int const csg_nr, + struct irq_idle_and_protm_track *track) { struct kbase_csf_cmd_stream_group_info *ginfo; struct kbase_queue_group *group = NULL; @@ -2579,7 +2622,7 @@ static void process_csg_interrupts(struct kbase_device *const kbdev, if (WARN_ON(csg_nr >= kbdev->csf.global_iface.group_num)) return; - KBASE_KTRACE_ADD(kbdev, CSG_INTERRUPT_PROCESS, NULL, csg_nr); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_INTERRUPT_PROCESS_START, group, csg_nr); ginfo = &kbdev->csf.global_iface.groups[csg_nr]; req = kbase_csf_firmware_csg_input_read(ginfo, CSG_REQ); @@ -2619,7 +2662,7 @@ static void process_csg_interrupts(struct kbase_device *const kbdev, kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, ack, CSG_REQ_SYNC_UPDATE_MASK); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SYNC_UPDATE_INTERRUPT, group, req ^ ack); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_INTERRUPT_SYNC_UPDATE, group, req ^ ack); /* SYNC_UPDATE events shall invalidate GPU idle event */ atomic_set(&kbdev->csf.scheduler.gpu_no_longer_idle, true); @@ -2636,7 +2679,7 @@ static void process_csg_interrupts(struct kbase_device *const kbdev, set_bit(csg_nr, scheduler->csg_slots_idle_mask); KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_SET, group, scheduler->csg_slots_idle_mask[0]); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_IDLE_INTERRUPT, group, req ^ ack); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_INTERRUPT_IDLE, group, req ^ ack); dev_dbg(kbdev->dev, "Idle notification received for Group %u on slot %d\n", group->handle, csg_nr); @@ -2645,20 +2688,11 @@ static void process_csg_interrupts(struct kbase_device *const kbdev, * a tock for a replacement. */ mod_delayed_work(scheduler->wq, &scheduler->tock_work, 0); - } else { - u32 current_protm_pending_seq = - scheduler->tick_protm_pending_seq; + } - if ((current_protm_pending_seq != - KBASEP_TICK_PROTM_PEND_SCAN_SEQ_NR_INVALID) && - (group->scan_seq_num < current_protm_pending_seq)) { - /* If the protm enter was prevented due to groups - * priority, then fire a tock for the scheduler - * to re-examine the case. - */ - mod_delayed_work(scheduler->wq, - &scheduler->tock_work, 0); - } + if (group->scan_seq_num < track->idle_seq) { + track->idle_seq = group->scan_seq_num; + track->idle_slot = csg_nr; } } @@ -2666,7 +2700,7 @@ static void process_csg_interrupts(struct kbase_device *const kbdev, kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, ack, CSG_REQ_PROGRESS_TIMER_EVENT_MASK); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_PROGRESS_TIMER_INTERRUPT, + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_INTERRUPT_PROGRESS_TIMER_EVENT, group, req ^ ack); dev_info(kbdev->dev, "[%llu] Iterator PROGRESS_TIMER timeout notification received for group %u of ctx %d_%d on slot %d\n", @@ -2676,7 +2710,7 @@ static void process_csg_interrupts(struct kbase_device *const kbdev, handle_progress_timer_event(group); } - process_cs_interrupts(group, ginfo, irqreq, irqack); + process_cs_interrupts(group, ginfo, irqreq, irqack, track); out: /* group may still be NULL here */ @@ -2827,7 +2861,7 @@ static inline void process_protm_exit(struct kbase_device *kbdev, u32 glb_ack) GLB_REQ_PROTM_EXIT_MASK); if (likely(scheduler->active_protm_grp)) { - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_EXIT_PROTM, + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_PROTM_EXIT, scheduler->active_protm_grp, 0u); scheduler->active_protm_grp = NULL; } else { @@ -2841,24 +2875,83 @@ static inline void process_protm_exit(struct kbase_device *kbdev, u32 glb_ack) } } +static inline void process_tracked_info_for_protm(struct kbase_device *kbdev, + struct irq_idle_and_protm_track *track) +{ + struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; + struct kbase_queue_group *group = track->protm_grp; + u32 current_protm_pending_seq = scheduler->tick_protm_pending_seq; + + kbase_csf_scheduler_spin_lock_assert_held(kbdev); + + if (likely(current_protm_pending_seq == KBASEP_TICK_PROTM_PEND_SCAN_SEQ_NR_INVALID)) + return; + + /* Handle protm from the tracked information */ + if (track->idle_seq < current_protm_pending_seq) { + /* If the protm enter was prevented due to groups priority, then fire a tock + * for the scheduler to re-examine the case. + */ + dev_dbg(kbdev->dev, "Attempt pending protm from idle slot %d\n", track->idle_slot); + mod_delayed_work(scheduler->wq, &scheduler->tock_work, 0); + } else if (group) { + u32 i, num_groups = kbdev->csf.global_iface.group_num; + struct kbase_queue_group *grp; + bool tock_triggered = false; + + /* A new protm request, and track->idle_seq is not sufficient, check across + * previously notified idle CSGs in the current tick/tock cycle. + */ + for_each_set_bit(i, scheduler->csg_slots_idle_mask, num_groups) { + if (i == track->idle_slot) + continue; + grp = kbase_csf_scheduler_get_group_on_slot(kbdev, i); + /* If not NULL then the group pointer cannot disappear as the + * scheduler spinlock is held. + */ + if (grp == NULL) + continue; + + if (grp->scan_seq_num < current_protm_pending_seq) { + tock_triggered = true; + dev_dbg(kbdev->dev, + "Attempt new protm from tick/tock idle slot %d\n", i); + mod_delayed_work(scheduler->wq, &scheduler->tock_work, 0); + break; + } + } + + if (!tock_triggered) { + dev_dbg(kbdev->dev, "Group-%d on slot-%d start protm work\n", + group->handle, group->csg_nr); + queue_work(group->kctx->csf.wq, &group->protm_event_work); + } + } +} + void kbase_csf_interrupt(struct kbase_device *kbdev, u32 val) { unsigned long flags; u32 csg_interrupts = val & ~JOB_IRQ_GLOBAL_IF; + struct irq_idle_and_protm_track track = { .protm_grp = NULL, .idle_seq = U32_MAX }; lockdep_assert_held(&kbdev->hwaccess_lock); - KBASE_KTRACE_ADD(kbdev, CSF_INTERRUPT, NULL, val); + KBASE_KTRACE_ADD(kbdev, CSF_INTERRUPT_START, NULL, val); kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), val); if (csg_interrupts != 0) { kbase_csf_scheduler_spin_lock(kbdev, &flags); + /* Looping through and track the highest idle and protm groups */ while (csg_interrupts != 0) { int const csg_nr = ffs(csg_interrupts) - 1; - process_csg_interrupts(kbdev, csg_nr); + process_csg_interrupts(kbdev, csg_nr, &track); csg_interrupts &= ~(1 << csg_nr); } + + /* Handle protm from the tracked information */ + process_tracked_info_for_protm(kbdev, &track); kbase_csf_scheduler_spin_unlock(kbdev, flags); } @@ -2878,7 +2971,7 @@ void kbase_csf_interrupt(struct kbase_device *kbdev, u32 val) global_iface, GLB_REQ); glb_ack = kbase_csf_firmware_global_output( global_iface, GLB_ACK); - KBASE_KTRACE_ADD(kbdev, GLB_REQ_ACQ, NULL, glb_req ^ glb_ack); + KBASE_KTRACE_ADD(kbdev, CSF_INTERRUPT_GLB_REQ_ACK, NULL, glb_req ^ glb_ack); check_protm_enter_req_complete(kbdev, glb_req, glb_ack); diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.h index 46a052951e4a..b2677405761f 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2018-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2018-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -45,8 +45,6 @@ */ #define KBASEP_TICK_PROTM_PEND_SCAN_SEQ_NR_INVALID (U32_MAX) -#define FIRMWARE_PING_INTERVAL_MS (12000) /* 12 seconds */ - #define FIRMWARE_IDLE_HYSTERESIS_TIME_MS (10) /* Default 10 milliseconds */ /* Idle hysteresis time can be scaled down when GPU sleep feature is used */ @@ -161,8 +159,9 @@ int kbase_csf_queue_bind(struct kbase_context *kctx, * are any. * * @queue: Pointer to queue to be unbound. + * @process_exit: Flag to indicate if process exit is happening. */ -void kbase_csf_queue_unbind(struct kbase_queue *queue); +void kbase_csf_queue_unbind(struct kbase_queue *queue, bool process_exit); /** * kbase_csf_queue_unbind_stopped - Unbind a GPU command queue in the case diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_csg_debugfs.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_csg_debugfs.c index c511e5f3cd2d..92a511d79a05 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_csg_debugfs.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_csg_debugfs.c @@ -500,11 +500,7 @@ static const struct file_operations kbasep_csf_queue_group_debugfs_fops = { void kbase_csf_queue_group_debugfs_init(struct kbase_context *kctx) { struct dentry *file; -#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE) const mode_t mode = 0444; -#else - const mode_t mode = 0400; -#endif if (WARN_ON(!kctx || IS_ERR_OR_NULL(kctx->kctx_dentry))) return; diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_defs.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_defs.h index 798924fc4b21..89055e95a02f 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_defs.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_defs.h @@ -261,6 +261,8 @@ enum kbase_queue_group_priority { * @CSF_GPU_RESET_TIMEOUT: Waiting timeout for GPU reset to complete. * @CSF_CSG_SUSPEND_TIMEOUT: Timeout given for all active CSGs to be suspended. * @CSF_FIRMWARE_BOOT_TIMEOUT: Maximum time to wait for firmware to boot. + * @CSF_FIRMWARE_PING_TIMEOUT: Maximum time to wait for firmware to respond + * to a ping from KBase. * @CSF_SCHED_PROTM_PROGRESS_TIMEOUT: Timeout used to prevent protected mode execution hang. * @KBASE_TIMEOUT_SELECTOR_COUNT: Number of timeout selectors. Must be last in * the enum. @@ -271,6 +273,7 @@ enum kbase_timeout_selector { CSF_GPU_RESET_TIMEOUT, CSF_CSG_SUSPEND_TIMEOUT, CSF_FIRMWARE_BOOT_TIMEOUT, + CSF_FIRMWARE_PING_TIMEOUT, CSF_SCHED_PROTM_PROGRESS_TIMEOUT, /* Must be the last in the enum */ @@ -452,6 +455,7 @@ struct kbase_protected_suspend_buffer { * allowed to use. * @compute_max: Maximum number of compute endpoints the group is * allowed to use. + * @csi_handlers: Requested CSI exception handler flags for the group. * @tiler_mask: Mask of tiler endpoints the group is allowed to use. * @fragment_mask: Mask of fragment endpoints the group is allowed to use. * @compute_mask: Mask of compute endpoints the group is allowed to use. @@ -473,6 +477,10 @@ struct kbase_protected_suspend_buffer { * @faulted: Indicates that a GPU fault occurred for the queue group. * This flag persists until the fault has been queued to be * reported to userspace. + * @reevaluate_idle_status : Flag set when work is submitted for the normal group + * or it becomes unblocked during protected mode. The + * flag helps Scheduler confirm if the group actually + * became non idle or not. * @bound_queues: Array of registered queues bound to this queue group. * @doorbell_nr: Index of the hardware doorbell page assigned to the * group. @@ -500,6 +508,7 @@ struct kbase_queue_group { u8 tiler_max; u8 fragment_max; u8 compute_max; + u8 csi_handlers; u64 tiler_mask; u64 fragment_mask; @@ -513,6 +522,7 @@ struct kbase_queue_group { u32 prepared_seq_num; u32 scan_seq_num; bool faulted; + bool reevaluate_idle_status; struct kbase_queue *bound_queues[MAX_SUPPORTED_STREAMS_PER_GROUP]; diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_event.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_event.c index 5c86688c3ea6..170b7ec51af7 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_event.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_event.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2021-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -102,7 +102,7 @@ static void sync_update_notify_gpu(struct kbase_context *kctx) if (can_notify_gpu) { kbase_csf_ring_doorbell(kctx->kbdev, CSF_KERNEL_DOORBELL_NR); - KBASE_KTRACE_ADD(kctx->kbdev, SYNC_UPDATE_EVENT_NOTIFY_GPU, kctx, 0u); + KBASE_KTRACE_ADD(kctx->kbdev, CSF_SYNC_UPDATE_NOTIFY_GPU_EVENT, kctx, 0u); } spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, flags); @@ -226,12 +226,15 @@ void kbase_csf_event_add_error(struct kbase_context *const kctx, return; spin_lock_irqsave(&kctx->csf.event.lock, flags); - if (!WARN_ON(!list_empty(&error->link))) { + if (list_empty(&error->link)) { error->data = *data; list_add_tail(&error->link, &kctx->csf.event.error_list); dev_dbg(kctx->kbdev->dev, "Added error %pK of type %d in context %pK\n", (void *)error, data->type, (void *)kctx); + } else { + dev_dbg(kctx->kbdev->dev, "Error %pK of type %d already pending in context %pK", + (void *)error, error->data.type, (void *)kctx); } spin_unlock_irqrestore(&kctx->csf.event.lock, flags); } diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.c index beed4a3cd736..0fb56e0094c5 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.c @@ -44,6 +44,7 @@ #include #include #include +#include #if (KERNEL_VERSION(4, 13, 0) <= LINUX_VERSION_CODE) #include #endif @@ -94,6 +95,7 @@ MODULE_PARM_DESC(fw_debug, #define CSF_FIRMWARE_ENTRY_TYPE_FUTF_TEST (2) #define CSF_FIRMWARE_ENTRY_TYPE_TRACE_BUFFER (3) #define CSF_FIRMWARE_ENTRY_TYPE_TIMELINE_METADATA (4) +#define CSF_FIRMWARE_ENTRY_TYPE_BUILD_INFO_METADATA (6) #define CSF_FIRMWARE_CACHE_MODE_NONE (0ul << 3) #define CSF_FIRMWARE_CACHE_MODE_CACHED (1ul << 3) @@ -104,12 +106,18 @@ MODULE_PARM_DESC(fw_debug, #define TL_METADATA_ENTRY_NAME_OFFSET (0x8) +#define BUILD_INFO_METADATA_SIZE_OFFSET (0x4) +#define BUILD_INFO_GIT_SHA_LEN (40U) +#define BUILD_INFO_GIT_DIRTY_LEN (1U) +#define BUILD_INFO_GIT_SHA_PATTERN "git_sha: " + #define CSF_MAX_FW_STOP_LOOPS (100000) #define CSF_GLB_REQ_CFG_MASK \ (GLB_REQ_CFG_ALLOC_EN_MASK | GLB_REQ_CFG_PROGRESS_TIMER_MASK | \ GLB_REQ_CFG_PWROFF_TIMER_MASK | GLB_REQ_IDLE_ENABLE_MASK) + static inline u32 input_page_read(const u32 *const input, const u32 offset) { WARN_ON(offset % sizeof(u32)); @@ -719,8 +727,9 @@ static int parse_memory_setup_entry(struct kbase_device *kbdev, if (!reuse_pages) { ret = kbase_mmu_insert_pages_no_flush(kbdev, &kbdev->csf.mcu_mmu, - virtual_start >> PAGE_SHIFT, phys, num_pages_aligned, mem_flags, - KBASE_MEM_GROUP_CSF_FW); + virtual_start >> PAGE_SHIFT, phys, + num_pages_aligned, mem_flags, + KBASE_MEM_GROUP_CSF_FW, NULL); if (ret != 0) { dev_err(kbdev->dev, "Failed to insert firmware pages\n"); @@ -810,6 +819,57 @@ static int parse_timeline_metadata_entry(struct kbase_device *kbdev, return 0; } +/** + * parse_build_info_metadata_entry() - Process a "build info metadata" section + * @kbdev: Kbase device structure + * @fw: Firmware image containing the section + * @entry: Pointer to the section + * @size: Size (in bytes) of the section + * + * This prints the git SHA of the firmware on frimware load. + * + * Return: 0 if successful, negative error code on failure + */ +static int parse_build_info_metadata_entry(struct kbase_device *kbdev, + const struct kbase_csf_mcu_fw *const fw, + const u32 *entry, unsigned int size) +{ + const u32 meta_start_addr = entry[0]; + char *ptr = NULL; + size_t sha_pattern_len = strlen(BUILD_INFO_GIT_SHA_PATTERN); + + /* Only print git SHA to avoid releasing sensitive information */ + ptr = strstr(fw->data + meta_start_addr, BUILD_INFO_GIT_SHA_PATTERN); + /* Check that we won't overrun the found string */ + if (ptr && + strlen(ptr) >= BUILD_INFO_GIT_SHA_LEN + BUILD_INFO_GIT_DIRTY_LEN + sha_pattern_len) { + char git_sha[BUILD_INFO_GIT_SHA_LEN + BUILD_INFO_GIT_DIRTY_LEN + 1]; + int i = 0; + + /* Move ptr to start of SHA */ + ptr += sha_pattern_len; + for (i = 0; i < BUILD_INFO_GIT_SHA_LEN; i++) { + /* Ensure that the SHA is made up of hex digits */ + if (!isxdigit(ptr[i])) + break; + + git_sha[i] = ptr[i]; + } + + /* Check if the next char indicates git SHA is dirty */ + if (ptr[i] == ' ' || ptr[i] == '+') { + git_sha[i] = ptr[i]; + i++; + } + git_sha[i] = '\0'; + + dev_info(kbdev->dev, "Mali firmware git_sha: %s\n", git_sha); + } else + dev_info(kbdev->dev, "Mali firmware git_sha not found or invalid\n"); + + return 0; +} + /** * load_firmware_entry() - Process an entry from a firmware image * @@ -889,6 +949,13 @@ static int load_firmware_entry(struct kbase_device *kbdev, const struct kbase_cs return -EINVAL; } return parse_timeline_metadata_entry(kbdev, fw, entry, size); + case CSF_FIRMWARE_ENTRY_TYPE_BUILD_INFO_METADATA: + if (size < BUILD_INFO_METADATA_SIZE_OFFSET + sizeof(*entry)) { + dev_err(kbdev->dev, "Build info metadata entry too short (size=%u)\n", + size); + return -EINVAL; + } + return parse_build_info_metadata_entry(kbdev, fw, entry, size); } if (!optional) { @@ -1491,6 +1558,7 @@ static void enable_gpu_idle_timer(struct kbase_device *const kbdev) kbdev->csf.gpu_idle_dur_count); } + static void global_init(struct kbase_device *const kbdev, u64 core_mask) { u32 const ack_irq_mask = @@ -1665,7 +1733,7 @@ void kbase_csf_firmware_reload_completed(struct kbase_device *kbdev) if (version != kbdev->csf.global_iface.version) dev_err(kbdev->dev, "Version check failed in firmware reboot."); - KBASE_KTRACE_ADD(kbdev, FIRMWARE_REBOOT, NULL, 0u); + KBASE_KTRACE_ADD(kbdev, CSF_FIRMWARE_REBOOT, NULL, 0u); /* Tell MCU state machine to transit to next state */ kbdev->csf.firmware_reloaded = true; @@ -2121,7 +2189,7 @@ int kbase_csf_firmware_init(struct kbase_device *kbdev) goto err_out; /* Firmware loaded successfully, ret = 0 */ - KBASE_KTRACE_ADD(kbdev, FIRMWARE_BOOT, NULL, + KBASE_KTRACE_ADD(kbdev, CSF_FIRMWARE_BOOT, NULL, (((u64)version_hash) << 32) | (((u64)version_major) << 8) | version_minor); return 0; @@ -2611,9 +2679,9 @@ int kbase_csf_firmware_mcu_shared_mapping_init( gpu_map_properties &= (KBASE_REG_GPU_RD | KBASE_REG_GPU_WR); gpu_map_properties |= gpu_map_prot; - ret = kbase_mmu_insert_pages_no_flush(kbdev, &kbdev->csf.mcu_mmu, - va_reg->start_pfn, &phys[0], num_pages, - gpu_map_properties, KBASE_MEM_GROUP_CSF_FW); + ret = kbase_mmu_insert_pages_no_flush(kbdev, &kbdev->csf.mcu_mmu, va_reg->start_pfn, + &phys[0], num_pages, gpu_map_properties, + KBASE_MEM_GROUP_CSF_FW, NULL); if (ret) goto mmu_insert_pages_error; @@ -2674,3 +2742,4 @@ void kbase_csf_firmware_mcu_shared_mapping_term( vunmap(csf_mapping->cpu_addr); kfree(csf_mapping->phys); } + diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.h index f688fdcdb4d0..85caaa7b2ab4 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.h @@ -246,6 +246,7 @@ void kbase_csf_firmware_csg_input_mask( u32 kbase_csf_firmware_csg_output( const struct kbase_csf_cmd_stream_group_info *info, u32 offset); + /** * struct kbase_csf_global_iface - Global CSF interface * provided by the firmware. @@ -794,4 +795,6 @@ static inline u32 kbase_csf_interface_version(u32 major, u32 minor, u32 patch) * Return: 0 if success, or negative error code on failure. */ int kbase_csf_trigger_firmware_config_update(struct kbase_device *kbdev); + + #endif diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_cfg.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_cfg.c index 961335c024bd..ad4ae74c7569 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_cfg.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_cfg.c @@ -22,6 +22,7 @@ #include #include "mali_kbase_csf_firmware_cfg.h" #include +#include #if CONFIG_SYSFS #define CSF_FIRMWARE_CFG_SYSFS_DIR_NAME "firmware_config" @@ -209,11 +210,18 @@ static struct attribute *fw_cfg_attrs[] = { &fw_cfg_attr_cur, NULL, }; +#if (KERNEL_VERSION(5, 2, 0) <= LINUX_VERSION_CODE) +ATTRIBUTE_GROUPS(fw_cfg); +#endif static struct kobj_type fw_cfg_kobj_type = { .release = &fw_cfg_kobj_release, .sysfs_ops = &fw_cfg_ops, +#if (KERNEL_VERSION(5, 2, 0) <= LINUX_VERSION_CODE) + .default_groups = fw_cfg_groups, +#else .default_attrs = fw_cfg_attrs, +#endif }; int kbase_csf_firmware_cfg_init(struct kbase_device *kbdev) diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_no_mali.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_no_mali.c index 670e31ec0fce..54f1f6b9c199 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_no_mali.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_no_mali.c @@ -104,6 +104,7 @@ struct dummy_firmware_interface { (GLB_REQ_CFG_ALLOC_EN_MASK | GLB_REQ_CFG_PROGRESS_TIMER_MASK | \ GLB_REQ_CFG_PWROFF_TIMER_MASK | GLB_REQ_IDLE_ENABLE_MASK) + static inline u32 input_page_read(const u32 *const input, const u32 offset) { WARN_ON(offset % sizeof(u32)); @@ -703,17 +704,16 @@ static void enable_gpu_idle_timer(struct kbase_device *const kbdev) kbdev->csf.gpu_idle_dur_count); } + static void global_init(struct kbase_device *const kbdev, u64 core_mask) { - u32 const ack_irq_mask = GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_MASK | - GLB_ACK_IRQ_MASK_PING_MASK | - GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_MASK | - GLB_ACK_IRQ_MASK_PROTM_ENTER_MASK | - GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_MASK | - GLB_ACK_IRQ_MASK_PROTM_EXIT_MASK | - GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_MASK | - GLB_ACK_IRQ_MASK_IDLE_EVENT_MASK | - GLB_ACK_IRQ_MASK_IDLE_ENABLE_MASK; + u32 const ack_irq_mask = + GLB_ACK_IRQ_MASK_CFG_ALLOC_EN_MASK | GLB_ACK_IRQ_MASK_PING_MASK | + GLB_ACK_IRQ_MASK_CFG_PROGRESS_TIMER_MASK | GLB_ACK_IRQ_MASK_PROTM_ENTER_MASK | + GLB_ACK_IRQ_MASK_PROTM_EXIT_MASK | GLB_ACK_IRQ_MASK_FIRMWARE_CONFIG_UPDATE_MASK | + GLB_ACK_IRQ_MASK_CFG_PWROFF_TIMER_MASK | GLB_ACK_IRQ_MASK_IDLE_EVENT_MASK | + GLB_ACK_IRQ_MASK_IDLE_ENABLE_MASK | + 0; const struct kbase_csf_global_iface *const global_iface = &kbdev->csf.global_iface; @@ -1473,7 +1473,7 @@ int kbase_csf_firmware_mcu_shared_mapping_init( gpu_map_prot = KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_NON_CACHEABLE); cpu_map_prot = pgprot_writecombine(cpu_map_prot); - }; + } phys = kmalloc_array(num_pages, sizeof(*phys), GFP_KERNEL); if (!phys) @@ -1511,9 +1511,9 @@ int kbase_csf_firmware_mcu_shared_mapping_init( gpu_map_properties &= (KBASE_REG_GPU_RD | KBASE_REG_GPU_WR); gpu_map_properties |= gpu_map_prot; - ret = kbase_mmu_insert_pages_no_flush(kbdev, &kbdev->csf.mcu_mmu, - va_reg->start_pfn, &phys[0], num_pages, - gpu_map_properties, KBASE_MEM_GROUP_CSF_FW); + ret = kbase_mmu_insert_pages_no_flush(kbdev, &kbdev->csf.mcu_mmu, va_reg->start_pfn, + &phys[0], num_pages, gpu_map_properties, + KBASE_MEM_GROUP_CSF_FW, NULL); if (ret) goto mmu_insert_pages_error; @@ -1574,3 +1574,4 @@ void kbase_csf_firmware_mcu_shared_mapping_term( vunmap(csf_mapping->cpu_addr); kfree(csf_mapping->phys); } + diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c index c72142ca7685..542f04579898 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c @@ -33,6 +33,10 @@ static DEFINE_SPINLOCK(kbase_csf_fence_lock); #endif +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG +#define FENCE_WAIT_TIMEOUT_MS 3000 +#endif + static void kcpu_queue_process(struct kbase_kcpu_command_queue *kcpu_queue, bool drain_queue); @@ -748,7 +752,7 @@ static int kbase_kcpu_cqs_wait_process(struct kbase_device *kbdev, KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START(kbdev, queue); queue->command_started = true; - KBASE_KTRACE_ADD_CSF_KCPU(kbdev, CQS_WAIT_START, + KBASE_KTRACE_ADD_CSF_KCPU(kbdev, KCPU_CQS_WAIT_START, queue, cqs_wait->nr_objs, 0); } @@ -770,7 +774,7 @@ static int kbase_kcpu_cqs_wait_process(struct kbase_device *kbdev, error = true; } - KBASE_KTRACE_ADD_CSF_KCPU(kbdev, CQS_WAIT_END, + KBASE_KTRACE_ADD_CSF_KCPU(kbdev, KCPU_CQS_WAIT_END, queue, cqs_wait->objs[i].addr, error); @@ -877,7 +881,7 @@ static void kbase_kcpu_cqs_set_process(struct kbase_device *kbdev, evt[BASEP_EVENT_VAL_INDEX]++; kbase_phy_alloc_mapping_put(queue->kctx, mapping); - KBASE_KTRACE_ADD_CSF_KCPU(kbdev, CQS_SET, + KBASE_KTRACE_ADD_CSF_KCPU(kbdev, KCPU_CQS_SET, queue, cqs_set->objs[i].addr, evt[BASEP_EVENT_ERR_INDEX]); } @@ -1200,7 +1204,11 @@ static void kbase_csf_fence_wait_callback(struct dma_fence *fence, struct kbase_kcpu_command_queue *kcpu_queue = fence_info->kcpu_queue; struct kbase_context *const kctx = kcpu_queue->kctx; - KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, FENCE_WAIT_END, kcpu_queue, +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG + /* Fence gets signaled. Deactivate the timer for fence-wait timeout */ + del_timer(&kcpu_queue->fence_timeout); +#endif + KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, KCPU_FENCE_WAIT_END, kcpu_queue, fence->context, fence->seqno); /* Resume kcpu command queue processing. */ @@ -1222,8 +1230,15 @@ static void kbase_kcpu_fence_wait_cancel( bool removed = dma_fence_remove_callback(fence_info->fence, &fence_info->fence_cb); +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG + /* Fence-wait cancelled or fence signaled. In the latter case + * the timer would already have been deactivated inside + * kbase_csf_fence_wait_callback(). + */ + del_timer_sync(&kcpu_queue->fence_timeout); +#endif if (removed) - KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, FENCE_WAIT_END, + KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, KCPU_FENCE_WAIT_END, kcpu_queue, fence_info->fence->context, fence_info->fence->seqno); } @@ -1235,6 +1250,80 @@ static void kbase_kcpu_fence_wait_cancel( fence_info->fence = NULL; } +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG +/** + * fence_timeout_callback() - Timeout callback function for fence-wait + * + * @timer: Timer struct + * + * Context and seqno of the timed-out fence will be displayed in dmesg. + * If the fence has been signalled a work will be enqueued to process + * the fence-wait without displaying debugging information. + */ +static void fence_timeout_callback(struct timer_list *timer) +{ + struct kbase_kcpu_command_queue *kcpu_queue = + container_of(timer, struct kbase_kcpu_command_queue, fence_timeout); + struct kbase_context *const kctx = kcpu_queue->kctx; + struct kbase_kcpu_command *cmd = &kcpu_queue->commands[kcpu_queue->start_offset]; + struct kbase_kcpu_command_fence_info *fence_info; +#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) + struct fence *fence; +#else + struct dma_fence *fence; +#endif + struct kbase_sync_fence_info info; + + if (cmd->type != BASE_KCPU_COMMAND_TYPE_FENCE_WAIT) { + dev_err(kctx->kbdev->dev, + "%s: Unexpected command type %d in ctx:%d_%d kcpu queue:%u", __func__, + cmd->type, kctx->tgid, kctx->id, kcpu_queue->id); + return; + } + + fence_info = &cmd->info.fence; + + fence = kbase_fence_get(fence_info); + if (!fence) { + dev_err(kctx->kbdev->dev, "no fence found in ctx:%d_%d kcpu queue:%u", kctx->tgid, + kctx->id, kcpu_queue->id); + return; + } + + kbase_sync_fence_info_get(fence, &info); + + if (info.status == 1) { + queue_work(kctx->csf.kcpu_queues.wq, &kcpu_queue->work); + } else if (info.status == 0) { + dev_warn(kctx->kbdev->dev, "fence has not yet signalled in %ums", + FENCE_WAIT_TIMEOUT_MS); + dev_warn(kctx->kbdev->dev, + "ctx:%d_%d kcpu queue:%u still waiting for fence[%pK] context#seqno:%s", + kctx->tgid, kctx->id, kcpu_queue->id, fence, info.name); + } else { + dev_warn(kctx->kbdev->dev, "fence has got error"); + dev_warn(kctx->kbdev->dev, + "ctx:%d_%d kcpu queue:%u faulty fence[%pK] context#seqno:%s error(%d)", + kctx->tgid, kctx->id, kcpu_queue->id, fence, info.name, info.status); + } + + kbase_fence_put(fence); +} + +/** + * fence_timeout_start() - Start a timer to check fence-wait timeout + * + * @cmd: KCPU command queue + * + * Activate a timer to check whether a fence-wait command in the queue + * gets completed within FENCE_WAIT_TIMEOUT_MS + */ +static void fence_timeout_start(struct kbase_kcpu_command_queue *cmd) +{ + mod_timer(&cmd->fence_timeout, jiffies + msecs_to_jiffies(FENCE_WAIT_TIMEOUT_MS)); +} +#endif + /** * kbase_kcpu_fence_wait_process() - Process the kcpu fence wait command * @@ -1254,8 +1343,9 @@ static int kbase_kcpu_fence_wait_process( #else struct dma_fence *fence; #endif + struct kbase_context *const kctx = kcpu_queue->kctx; - lockdep_assert_held(&kcpu_queue->kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kctx->csf.kcpu_queues.lock); if (WARN_ON(!fence_info->fence)) return -EINVAL; @@ -1269,14 +1359,26 @@ static int kbase_kcpu_fence_wait_process( &fence_info->fence_cb, kbase_csf_fence_wait_callback); - KBASE_KTRACE_ADD_CSF_KCPU(kcpu_queue->kctx->kbdev, - FENCE_WAIT_START, kcpu_queue, + KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, + KCPU_FENCE_WAIT_START, kcpu_queue, fence->context, fence->seqno); fence_status = cb_err; - if (cb_err == 0) + if (cb_err == 0) { kcpu_queue->fence_wait_processed = true; - else if (cb_err == -ENOENT) +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG + fence_timeout_start(kcpu_queue); +#endif + } else if (cb_err == -ENOENT) { fence_status = dma_fence_get_status(fence); + if (!fence_status) { + struct kbase_sync_fence_info info; + + kbase_sync_fence_info_get(fence, &info); + dev_warn(kctx->kbdev->dev, + "Unexpected status for fence %s of ctx:%d_%d kcpu queue:%u", + info.name, kctx->tgid, kctx->id, kcpu_queue->id); + } + } } /* @@ -1321,7 +1423,6 @@ static int kbase_kcpu_fence_wait_prepare( current_command->type = BASE_KCPU_COMMAND_TYPE_FENCE_WAIT; current_command->info.fence.fence = fence_in; current_command->info.fence.kcpu_queue = kcpu_queue; - return 0; } @@ -1343,7 +1444,7 @@ static int kbase_kcpu_fence_signal_process( ret = 0; } - KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, FENCE_SIGNAL, kcpu_queue, + KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, KCPU_FENCE_SIGNAL, kcpu_queue, fence_info->fence->context, fence_info->fence->seqno); @@ -1465,7 +1566,7 @@ static int delete_queue(struct kbase_context *kctx, u32 id) struct kbase_kcpu_command_queue *queue = kctx->csf.kcpu_queues.array[id]; - KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, KCPU_QUEUE_DESTROY, + KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, KCPU_QUEUE_DELETE, queue, queue->num_pending_cmds, queue->cqs_wait_count); /* Drain the remaining work for this queue first and go past @@ -2221,8 +2322,11 @@ int kbase_csf_kcpu_queue_new(struct kbase_context *kctx, KBASE_TLSTREAM_TL_KBASE_NEW_KCPUQUEUE(kctx->kbdev, queue, queue->id, kctx->id, queue->num_pending_cmds); - KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, KCPU_QUEUE_NEW, queue, + KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, KCPU_QUEUE_CREATE, queue, queue->fence_context, 0); +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG + kbase_timer_setup(&queue->fence_timeout, fence_timeout_callback); +#endif out: mutex_unlock(&kctx->csf.kcpu_queues.lock); diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.h index ba702d0ae281..a4db86984721 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.h @@ -47,9 +47,9 @@ struct kbase_kcpu_command_import_info { * struct kbase_kcpu_command_fence_info - Structure which holds information * about the fence object enqueued in the kcpu command queue * - * @fence_cb: Fence callback - * @fence: Fence - * @kcpu_queue: kcpu command queue + * @fence_cb: Fence callback + * @fence: Fence + * @kcpu_queue: kcpu command queue */ struct kbase_kcpu_command_fence_info { #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) @@ -271,6 +271,7 @@ struct kbase_kcpu_command { * or without errors since last cleaned. * @jit_blocked: Used to keep track of command queues blocked * by a pending JIT allocation command. + * @fence_timeout: Timer used to detect the fence wait timeout. */ struct kbase_kcpu_command_queue { struct kbase_context *kctx; @@ -287,6 +288,9 @@ struct kbase_kcpu_command_queue { bool command_started; struct list_head jit_blocked; bool has_error; +#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG + struct timer_list fence_timeout; +#endif /* CONFIG_MALI_BIFROST_FENCE_DEBUG */ }; /** diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu_debugfs.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu_debugfs.c index b195afacb005..fa877778ca79 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu_debugfs.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu_debugfs.c @@ -167,11 +167,7 @@ static const struct file_operations kbasep_csf_kcpu_debugfs_fops = { void kbase_csf_kcpu_debugfs_init(struct kbase_context *kctx) { struct dentry *file; -#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE) const mode_t mode = 0444; -#else - const mode_t mode = 0400; -#endif if (WARN_ON(!kctx || IS_ERR_OR_NULL(kctx->kctx_dentry))) return; diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_registers.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_registers.h index 8257a3ea84ea..c797bcbc461a 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_registers.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_registers.h @@ -387,7 +387,7 @@ /* CS_BASE register */ #define CS_BASE_POINTER_SHIFT 0 -#define CS_BASE_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_BASE_POINTER_SHIFT) +#define CS_BASE_POINTER_MASK (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_BASE_POINTER_SHIFT) #define CS_BASE_POINTER_GET(reg_val) (((reg_val)&CS_BASE_POINTER_MASK) >> CS_BASE_POINTER_SHIFT) #define CS_BASE_POINTER_SET(reg_val, value) \ (((reg_val) & ~CS_BASE_POINTER_MASK) | (((value) << CS_BASE_POINTER_SHIFT) & CS_BASE_POINTER_MASK)) @@ -401,7 +401,8 @@ /* CS_TILER_HEAP_START register */ #define CS_TILER_HEAP_START_POINTER_SHIFT 0 -#define CS_TILER_HEAP_START_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_TILER_HEAP_START_POINTER_SHIFT) +#define CS_TILER_HEAP_START_POINTER_MASK \ + (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_TILER_HEAP_START_POINTER_SHIFT) #define CS_TILER_HEAP_START_POINTER_GET(reg_val) \ (((reg_val)&CS_TILER_HEAP_START_POINTER_MASK) >> CS_TILER_HEAP_START_POINTER_SHIFT) #define CS_TILER_HEAP_START_POINTER_SET(reg_val, value) \ @@ -412,7 +413,8 @@ /* CS_TILER_HEAP_END register */ #define CS_TILER_HEAP_END_POINTER_SHIFT 0 -#define CS_TILER_HEAP_END_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_TILER_HEAP_END_POINTER_SHIFT) +#define CS_TILER_HEAP_END_POINTER_MASK \ + (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_TILER_HEAP_END_POINTER_SHIFT) #define CS_TILER_HEAP_END_POINTER_GET(reg_val) \ (((reg_val)&CS_TILER_HEAP_END_POINTER_MASK) >> CS_TILER_HEAP_END_POINTER_SHIFT) #define CS_TILER_HEAP_END_POINTER_SET(reg_val, value) \ @@ -423,7 +425,7 @@ /* CS_USER_INPUT register */ #define CS_USER_INPUT_POINTER_SHIFT 0 -#define CS_USER_INPUT_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_USER_INPUT_POINTER_SHIFT) +#define CS_USER_INPUT_POINTER_MASK (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_USER_INPUT_POINTER_SHIFT) #define CS_USER_INPUT_POINTER_GET(reg_val) (((reg_val)&CS_USER_INPUT_POINTER_MASK) >> CS_USER_INPUT_POINTER_SHIFT) #define CS_USER_INPUT_POINTER_SET(reg_val, value) \ (((reg_val) & ~CS_USER_INPUT_POINTER_MASK) | \ @@ -431,7 +433,7 @@ /* CS_USER_OUTPUT register */ #define CS_USER_OUTPUT_POINTER_SHIFT 0 -#define CS_USER_OUTPUT_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_USER_OUTPUT_POINTER_SHIFT) +#define CS_USER_OUTPUT_POINTER_MASK (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_USER_OUTPUT_POINTER_SHIFT) #define CS_USER_OUTPUT_POINTER_GET(reg_val) (((reg_val)&CS_USER_OUTPUT_POINTER_MASK) >> CS_USER_OUTPUT_POINTER_SHIFT) #define CS_USER_OUTPUT_POINTER_SET(reg_val, value) \ (((reg_val) & ~CS_USER_OUTPUT_POINTER_MASK) | \ @@ -470,7 +472,8 @@ /* CS_INSTR_BUFFER_BASE register */ #define CS_INSTR_BUFFER_BASE_POINTER_SHIFT (0) -#define CS_INSTR_BUFFER_BASE_POINTER_MASK ((u64)0xFFFFFFFFFFFFFFFF << CS_INSTR_BUFFER_BASE_POINTER_SHIFT) +#define CS_INSTR_BUFFER_BASE_POINTER_MASK \ + (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_INSTR_BUFFER_BASE_POINTER_SHIFT) #define CS_INSTR_BUFFER_BASE_POINTER_GET(reg_val) \ (((reg_val)&CS_INSTR_BUFFER_BASE_POINTER_MASK) >> CS_INSTR_BUFFER_BASE_POINTER_SHIFT) #define CS_INSTR_BUFFER_BASE_POINTER_SET(reg_val, value) \ @@ -479,8 +482,8 @@ /* CS_INSTR_BUFFER_OFFSET_POINTER register */ #define CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_SHIFT (0) -#define CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_MASK \ - (((u64)0xFFFFFFFFFFFFFFFF) << CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_SHIFT) +#define CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_MASK \ + ((GPU_ULL(0xFFFFFFFFFFFFFFFF)) << CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_SHIFT) #define CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_GET(reg_val) \ (((reg_val)&CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_MASK) >> CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_SHIFT) #define CS_INSTR_BUFFER_OFFSET_POINTER_POINTER_SET(reg_val, value) \ @@ -529,7 +532,8 @@ /* CS_STATUS_CMD_PTR register */ #define CS_STATUS_CMD_PTR_POINTER_SHIFT 0 -#define CS_STATUS_CMD_PTR_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_STATUS_CMD_PTR_POINTER_SHIFT) +#define CS_STATUS_CMD_PTR_POINTER_MASK \ + (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_STATUS_CMD_PTR_POINTER_SHIFT) #define CS_STATUS_CMD_PTR_POINTER_GET(reg_val) \ (((reg_val)&CS_STATUS_CMD_PTR_POINTER_MASK) >> CS_STATUS_CMD_PTR_POINTER_SHIFT) #define CS_STATUS_CMD_PTR_POINTER_SET(reg_val, value) \ @@ -608,7 +612,8 @@ /* CS_STATUS_WAIT_SYNC_POINTER register */ #define CS_STATUS_WAIT_SYNC_POINTER_POINTER_SHIFT 0 -#define CS_STATUS_WAIT_SYNC_POINTER_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_STATUS_WAIT_SYNC_POINTER_POINTER_SHIFT) +#define CS_STATUS_WAIT_SYNC_POINTER_POINTER_MASK \ + (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_STATUS_WAIT_SYNC_POINTER_POINTER_SHIFT) #define CS_STATUS_WAIT_SYNC_POINTER_POINTER_GET(reg_val) \ (((reg_val)&CS_STATUS_WAIT_SYNC_POINTER_POINTER_MASK) >> CS_STATUS_WAIT_SYNC_POINTER_POINTER_SHIFT) #define CS_STATUS_WAIT_SYNC_POINTER_POINTER_SET(reg_val, value) \ @@ -709,7 +714,8 @@ /* CS_FAULT_INFO register */ #define CS_FAULT_INFO_EXCEPTION_DATA_SHIFT 0 -#define CS_FAULT_INFO_EXCEPTION_DATA_MASK (0xFFFFFFFFFFFFFFFF << CS_FAULT_INFO_EXCEPTION_DATA_SHIFT) +#define CS_FAULT_INFO_EXCEPTION_DATA_MASK \ + (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_FAULT_INFO_EXCEPTION_DATA_SHIFT) #define CS_FAULT_INFO_EXCEPTION_DATA_GET(reg_val) \ (((reg_val)&CS_FAULT_INFO_EXCEPTION_DATA_MASK) >> CS_FAULT_INFO_EXCEPTION_DATA_SHIFT) #define CS_FAULT_INFO_EXCEPTION_DATA_SET(reg_val, value) \ @@ -718,7 +724,8 @@ /* CS_FATAL_INFO register */ #define CS_FATAL_INFO_EXCEPTION_DATA_SHIFT 0 -#define CS_FATAL_INFO_EXCEPTION_DATA_MASK (0xFFFFFFFFFFFFFFFF << CS_FATAL_INFO_EXCEPTION_DATA_SHIFT) +#define CS_FATAL_INFO_EXCEPTION_DATA_MASK \ + (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_FATAL_INFO_EXCEPTION_DATA_SHIFT) #define CS_FATAL_INFO_EXCEPTION_DATA_GET(reg_val) \ (((reg_val)&CS_FATAL_INFO_EXCEPTION_DATA_MASK) >> CS_FATAL_INFO_EXCEPTION_DATA_SHIFT) #define CS_FATAL_INFO_EXCEPTION_DATA_SET(reg_val, value) \ @@ -750,7 +757,7 @@ /* CS_HEAP_ADDRESS register */ #define CS_HEAP_ADDRESS_POINTER_SHIFT 0 -#define CS_HEAP_ADDRESS_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CS_HEAP_ADDRESS_POINTER_SHIFT) +#define CS_HEAP_ADDRESS_POINTER_MASK (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_HEAP_ADDRESS_POINTER_SHIFT) #define CS_HEAP_ADDRESS_POINTER_GET(reg_val) (((reg_val)&CS_HEAP_ADDRESS_POINTER_MASK) >> CS_HEAP_ADDRESS_POINTER_SHIFT) #define CS_HEAP_ADDRESS_POINTER_SET(reg_val, value) \ (((reg_val) & ~CS_HEAP_ADDRESS_POINTER_MASK) | \ @@ -761,14 +768,14 @@ /* CS_INSERT register */ #define CS_INSERT_VALUE_SHIFT 0 -#define CS_INSERT_VALUE_MASK (0xFFFFFFFFFFFFFFFF << CS_INSERT_VALUE_SHIFT) +#define CS_INSERT_VALUE_MASK (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_INSERT_VALUE_SHIFT) #define CS_INSERT_VALUE_GET(reg_val) (((reg_val)&CS_INSERT_VALUE_MASK) >> CS_INSERT_VALUE_SHIFT) #define CS_INSERT_VALUE_SET(reg_val, value) \ (((reg_val) & ~CS_INSERT_VALUE_MASK) | (((value) << CS_INSERT_VALUE_SHIFT) & CS_INSERT_VALUE_MASK)) /* CS_EXTRACT_INIT register */ #define CS_EXTRACT_INIT_VALUE_SHIFT 0 -#define CS_EXTRACT_INIT_VALUE_MASK (0xFFFFFFFFFFFFFFFF << CS_EXTRACT_INIT_VALUE_SHIFT) +#define CS_EXTRACT_INIT_VALUE_MASK (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_EXTRACT_INIT_VALUE_SHIFT) #define CS_EXTRACT_INIT_VALUE_GET(reg_val) (((reg_val)&CS_EXTRACT_INIT_VALUE_MASK) >> CS_EXTRACT_INIT_VALUE_SHIFT) #define CS_EXTRACT_INIT_VALUE_SET(reg_val, value) \ (((reg_val) & ~CS_EXTRACT_INIT_VALUE_MASK) | \ @@ -779,7 +786,7 @@ /* CS_EXTRACT register */ #define CS_EXTRACT_VALUE_SHIFT 0 -#define CS_EXTRACT_VALUE_MASK (0xFFFFFFFFFFFFFFFF << CS_EXTRACT_VALUE_SHIFT) +#define CS_EXTRACT_VALUE_MASK (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CS_EXTRACT_VALUE_SHIFT) #define CS_EXTRACT_VALUE_GET(reg_val) (((reg_val)&CS_EXTRACT_VALUE_MASK) >> CS_EXTRACT_VALUE_SHIFT) #define CS_EXTRACT_VALUE_SET(reg_val, value) \ (((reg_val) & ~CS_EXTRACT_VALUE_MASK) | (((value) << CS_EXTRACT_VALUE_SHIFT) & CS_EXTRACT_VALUE_MASK)) @@ -932,7 +939,7 @@ /* CSG_SUSPEND_BUF register */ #define CSG_SUSPEND_BUF_POINTER_SHIFT 0 -#define CSG_SUSPEND_BUF_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CSG_SUSPEND_BUF_POINTER_SHIFT) +#define CSG_SUSPEND_BUF_POINTER_MASK (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CSG_SUSPEND_BUF_POINTER_SHIFT) #define CSG_SUSPEND_BUF_POINTER_GET(reg_val) (((reg_val)&CSG_SUSPEND_BUF_POINTER_MASK) >> CSG_SUSPEND_BUF_POINTER_SHIFT) #define CSG_SUSPEND_BUF_POINTER_SET(reg_val, value) \ (((reg_val) & ~CSG_SUSPEND_BUF_POINTER_MASK) | \ @@ -940,7 +947,8 @@ /* CSG_PROTM_SUSPEND_BUF register */ #define CSG_PROTM_SUSPEND_BUF_POINTER_SHIFT 0 -#define CSG_PROTM_SUSPEND_BUF_POINTER_MASK (0xFFFFFFFFFFFFFFFF << CSG_PROTM_SUSPEND_BUF_POINTER_SHIFT) +#define CSG_PROTM_SUSPEND_BUF_POINTER_MASK \ + (GPU_ULL(0xFFFFFFFFFFFFFFFF) << CSG_PROTM_SUSPEND_BUF_POINTER_SHIFT) #define CSG_PROTM_SUSPEND_BUF_POINTER_GET(reg_val) \ (((reg_val)&CSG_PROTM_SUSPEND_BUF_POINTER_MASK) >> CSG_PROTM_SUSPEND_BUF_POINTER_SHIFT) #define CSG_PROTM_SUSPEND_BUF_POINTER_SET(reg_val, value) \ @@ -1408,7 +1416,7 @@ /* GLB_ALLOC_EN register */ #define GLB_ALLOC_EN_MASK_SHIFT 0 -#define GLB_ALLOC_EN_MASK_MASK (0xFFFFFFFFFFFFFFFF << GLB_ALLOC_EN_MASK_SHIFT) +#define GLB_ALLOC_EN_MASK_MASK (GPU_ULL(0xFFFFFFFFFFFFFFFF) << GLB_ALLOC_EN_MASK_SHIFT) #define GLB_ALLOC_EN_MASK_GET(reg_val) (((reg_val)&GLB_ALLOC_EN_MASK_MASK) >> GLB_ALLOC_EN_MASK_SHIFT) #define GLB_ALLOC_EN_MASK_SET(reg_val, value) \ (((reg_val) & ~GLB_ALLOC_EN_MASK_MASK) | (((value) << GLB_ALLOC_EN_MASK_SHIFT) & GLB_ALLOC_EN_MASK_MASK)) @@ -1549,5 +1557,16 @@ (((reg_val) & ~GLB_PRFCNT_SIZE_HARDWARE_SIZE_MASK) | \ ((GLB_PRFCNT_SIZE_HARDWARE_SIZE_SET_MOD(value) << GLB_PRFCNT_SIZE_HARDWARE_SIZE_SHIFT) & \ GLB_PRFCNT_SIZE_HARDWARE_SIZE_MASK)) +#define GLB_PRFCNT_SIZE_FIRMWARE_SIZE_SET_MOD(value) ((value) >> 8) +#define GLB_PRFCNT_SIZE_FIRMWARE_SIZE_GET_MOD(value) ((value) << 8) +#define GLB_PRFCNT_SIZE_FIRMWARE_SIZE_SHIFT GPU_U(16) +#define GLB_PRFCNT_SIZE_FIRMWARE_SIZE_MASK (GPU_U(0xFFFF) << GLB_PRFCNT_SIZE_FIRMWARE_SIZE_SHIFT) +#define GLB_PRFCNT_SIZE_FIRMWARE_SIZE_GET(reg_val) \ + (GLB_PRFCNT_SIZE_FIRMWARE_SIZE_GET_MOD(((reg_val)&GLB_PRFCNT_SIZE_FIRMWARE_SIZE_MASK) >> \ + GLB_PRFCNT_SIZE_FIRMWARE_SIZE_SHIFT)) +#define GLB_PRFCNT_SIZE_FIRMWARE_SIZE_SET(reg_val, value) \ + (((reg_val) & ~GLB_PRFCNT_SIZE_FIRMWARE_SIZE_MASK) | \ + ((GLB_PRFCNT_SIZE_FIRMWARE_SIZE_SET_MOD(value) << GLB_PRFCNT_SIZE_FIRMWARE_SIZE_SHIFT) & \ + GLB_PRFCNT_SIZE_FIRMWARE_SIZE_MASK)) #endif /* _KBASE_CSF_REGISTERS_H_ */ diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.c index cd55bc64c9a2..c0f63fe75a0f 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.c @@ -236,7 +236,7 @@ static enum hrtimer_restart tick_timer_callback(struct hrtimer *timer) struct kbase_device *kbdev = container_of(timer, struct kbase_device, csf.scheduler.tick_timer); - kbase_csf_scheduler_advance_tick(kbdev); + kbase_csf_scheduler_tick_advance(kbdev); return HRTIMER_NORESTART; } @@ -476,7 +476,7 @@ void kbase_csf_scheduler_process_gpu_idle_event(struct kbase_device *kbdev) non_idle_offslot_grps = atomic_read(&scheduler->non_idle_offslot_grps); can_suspend_on_idle = kbase_pm_idle_groups_sched_suspendable(kbdev); - KBASE_KTRACE_ADD(kbdev, SCHEDULER_CAN_IDLE, NULL, + KBASE_KTRACE_ADD(kbdev, SCHEDULER_GPU_IDLE_EVENT_CAN_SUSPEND, NULL, ((u64)(u32)non_idle_offslot_grps) | (((u64)can_suspend_on_idle) << 32)); if (!non_idle_offslot_grps) { @@ -490,7 +490,7 @@ void kbase_csf_scheduler_process_gpu_idle_event(struct kbase_device *kbdev) } } else { /* Advance the scheduling tick to get the non-idle suspended groups loaded soon */ - kbase_csf_scheduler_advance_tick_nolock(kbdev); + kbase_csf_scheduler_tick_advance_nolock(kbdev); } } @@ -560,6 +560,12 @@ static bool on_slot_group_idle_locked(struct kbase_queue_group *group) return (group->run_state == KBASE_CSF_GROUP_IDLE); } +static bool can_schedule_idle_group(struct kbase_queue_group *group) +{ + return (on_slot_group_idle_locked(group) || + (group->priority == KBASE_QUEUE_GROUP_PRIORITY_REALTIME)); +} + static bool queue_group_scheduled(struct kbase_queue_group *group) { return (group->run_state != KBASE_CSF_GROUP_INACTIVE && @@ -575,7 +581,7 @@ static bool queue_group_scheduled_locked(struct kbase_queue_group *group) } /** - * scheduler_wait_protm_quit() - Wait for GPU to exit protected mode. + * scheduler_protm_wait_quit() - Wait for GPU to exit protected mode. * * @kbdev: Pointer to the GPU device * @@ -584,7 +590,7 @@ static bool queue_group_scheduled_locked(struct kbase_queue_group *group) * * Return: true on success, false otherwise. */ -static bool scheduler_wait_protm_quit(struct kbase_device *kbdev) +static bool scheduler_protm_wait_quit(struct kbase_device *kbdev) { struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; long wt = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms); @@ -593,8 +599,7 @@ static bool scheduler_wait_protm_quit(struct kbase_device *kbdev) lockdep_assert_held(&scheduler->lock); - KBASE_KTRACE_ADD(kbdev, SCHEDULER_WAIT_PROTM_QUIT, NULL, - jiffies_to_msecs(wt)); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_PROTM_WAIT_QUIT_START, NULL, jiffies_to_msecs(wt)); remaining = wait_event_timeout(kbdev->csf.event_wait, !kbase_csf_scheduler_protected_mode_in_use(kbdev), wt); @@ -606,8 +611,7 @@ static bool scheduler_wait_protm_quit(struct kbase_device *kbdev) success = false; } - KBASE_KTRACE_ADD(kbdev, SCHEDULER_WAIT_PROTM_QUIT_DONE, NULL, - jiffies_to_msecs(remaining)); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_PROTM_WAIT_QUIT_END, NULL, jiffies_to_msecs(remaining)); return success; } @@ -631,7 +635,7 @@ static void scheduler_force_protm_exit(struct kbase_device *kbdev) kbase_csf_firmware_ping(kbdev); - if (scheduler_wait_protm_quit(kbdev)) + if (scheduler_protm_wait_quit(kbdev)) return; dev_err(kbdev->dev, "Possible GPU hang in Protected mode"); @@ -958,8 +962,8 @@ static void update_idle_suspended_group_state(struct kbase_queue_group *group) return; new_val = atomic_inc_return(&scheduler->non_idle_offslot_grps); - KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC, - group, new_val); + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, SCHEDULER_NONIDLE_OFFSLOT_GRP_INC, group, + new_val); } int kbase_csf_scheduler_group_get_slot_locked(struct kbase_queue_group *group) @@ -1086,7 +1090,7 @@ static int halt_stream_sync(struct kbase_queue *queue) kbase_csf_firmware_cs_input_mask(stream, CS_REQ, CS_REQ_STATE_STOP, CS_REQ_STATE_MASK); - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_STOP_REQUESTED, group, queue, 0u); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_STOP_REQ, group, queue, 0u); kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, group->csg_nr, true); /* Timed wait */ @@ -1159,8 +1163,7 @@ static int sched_halt_stream(struct kbase_queue *queue) long remaining; int slot; int err = 0; - const u32 group_schedule_timeout = - 20 * kbdev->csf.scheduler.csg_scheduling_period_ms; + const u32 group_schedule_timeout = kbase_get_timeout_ms(kbdev, CSF_CSG_SUSPEND_TIMEOUT); if (WARN_ON(!group)) return -EINVAL; @@ -1531,8 +1534,8 @@ int kbase_csf_scheduler_queue_start(struct kbase_queue *queue) KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_START, group, queue, group->run_state); - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_STATUS_WAIT, queue->group, - queue, queue->status_wait); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE_WAIT_STATUS, queue->group, queue, + queue->status_wait); if (group->run_state == KBASE_CSF_GROUP_FAULT_EVICTED) { err = -EIO; @@ -1564,9 +1567,9 @@ int kbase_csf_scheduler_queue_start(struct kbase_queue *queue) } else program_cs(kbdev, queue, true); } - queue_delayed_work(system_long_wq, - &kbdev->csf.scheduler.ping_work, - msecs_to_jiffies(FIRMWARE_PING_INTERVAL_MS)); + queue_delayed_work(system_long_wq, &kbdev->csf.scheduler.ping_work, + msecs_to_jiffies(kbase_get_timeout_ms( + kbdev, CSF_FIRMWARE_PING_TIMEOUT))); } } @@ -1601,7 +1604,8 @@ static enum kbase_csf_csg_slot_state update_csg_slot_status( slot_state = CSG_SLOT_RUNNING; atomic_set(&csg_slot->state, slot_state); csg_slot->trigger_jiffies = jiffies; - KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_STARTED, csg_slot->resident_group, state); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_RUNNING, csg_slot->resident_group, + state); dev_dbg(kbdev->dev, "Group %u running on slot %d\n", csg_slot->resident_group->handle, slot); } @@ -1716,7 +1720,7 @@ static void halt_csg_slot(struct kbase_queue_group *group, bool suspend) flags); atomic_set(&csg_slot[slot].state, CSG_SLOT_DOWN2STOP); csg_slot[slot].trigger_jiffies = jiffies; - KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_STOP, group, halt_cmd); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_STOP_REQ, group, halt_cmd); KBASE_TLSTREAM_TL_KBASE_DEVICE_HALT_CSG( kbdev, kbdev->gpu_props.props.raw_props.gpu_id, slot); @@ -1760,10 +1764,10 @@ static bool evaluate_sync_update(struct kbase_queue *queue) sync_ptr = kbase_phy_alloc_mapping_get(queue->kctx, queue->sync_ptr, &mapping); - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE, queue->group, - queue, queue->sync_ptr); - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_BLOCKED_REASON, - queue->group, queue, queue->blocked_reason); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE_EVAL_START, queue->group, queue, + queue->sync_ptr); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE_BLOCKED_REASON, queue->group, queue, + queue->blocked_reason); if (!sync_ptr) { dev_dbg(queue->kctx->kbdev->dev, "sync memory VA 0x%016llX already freed", @@ -1778,11 +1782,11 @@ static bool evaluate_sync_update(struct kbase_queue *queue) (sync_wait_cond != CS_STATUS_WAIT_SYNC_WAIT_CONDITION_LE)); sync_current_val = READ_ONCE(*sync_ptr); - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_CURRENT_VAL, queue->group, - queue, sync_current_val); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE_CUR_VAL, queue->group, queue, + sync_current_val); - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_TEST_VAL, queue->group, - queue, queue->sync_value); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE_TEST_VAL, queue->group, queue, + queue->sync_value); if (((sync_wait_cond == CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GT) && (sync_current_val > queue->sync_value)) || @@ -1799,8 +1803,7 @@ static bool evaluate_sync_update(struct kbase_queue *queue) kbase_phy_alloc_mapping_put(queue->kctx, mapping); out: - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE_EVALUATED, - queue->group, queue, updated); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE_EVAL_END, queue->group, queue, updated); return updated; } @@ -1834,8 +1837,8 @@ bool save_slot_cs(struct kbase_csf_cmd_stream_group_info const *const ginfo, queue->saved_cmd_ptr = cmd_ptr; #endif - KBASE_KTRACE_ADD_CSF_GRP_Q(stream->kbdev, QUEUE_SYNC_STATUS_WAIT, - queue->group, queue, status); + KBASE_KTRACE_ADD_CSF_GRP_Q(stream->kbdev, QUEUE_SYNC_UPDATE_WAIT_STATUS, queue->group, + queue, status); if (CS_STATUS_WAIT_SYNC_WAIT_GET(status)) { queue->status_wait = status; @@ -1921,7 +1924,7 @@ void insert_group_to_runnable(struct kbase_csf_scheduler *const scheduler, list_add_tail(&group->link, &kctx->csf.sched.runnable_groups[group->priority]); kctx->csf.sched.num_runnable_grps++; - KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_INSERT_RUNNABLE, group, + KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_RUNNABLE_INSERT, group, kctx->csf.sched.num_runnable_grps); /* Add the kctx if not yet in runnable kctxs */ @@ -1929,7 +1932,7 @@ void insert_group_to_runnable(struct kbase_csf_scheduler *const scheduler, /* First runnable csg, adds to the runnable_kctxs */ INIT_LIST_HEAD(&kctx->csf.link); list_add_tail(&kctx->csf.link, &scheduler->runnable_kctxs); - KBASE_KTRACE_ADD(kbdev, SCHEDULER_INSERT_RUNNABLE, kctx, 0u); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_RUNNABLE_KCTX_INSERT, kctx, 0u); } scheduler->total_runnable_grps++; @@ -1986,7 +1989,7 @@ void remove_group_from_runnable(struct kbase_csf_scheduler *const scheduler, if (kbase_prepare_to_reset_gpu(kctx->kbdev, RESET_FLAGS_NONE)) kbase_reset_gpu(kctx->kbdev); - KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, SCHEDULER_EXIT_PROTM, + KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, SCHEDULER_PROTM_EXIT, scheduler->active_protm_grp, 0u); scheduler->active_protm_grp = NULL; } @@ -2016,13 +2019,12 @@ void remove_group_from_runnable(struct kbase_csf_scheduler *const scheduler, } kctx->csf.sched.num_runnable_grps--; - KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_REMOVE_RUNNABLE, group, + KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_RUNNABLE_REMOVE, group, kctx->csf.sched.num_runnable_grps); new_head_grp = (!list_empty(list)) ? list_first_entry(list, struct kbase_queue_group, link) : NULL; - KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_HEAD_RUNNABLE, new_head_grp, - 0u); + KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_RUNNABLE_HEAD, new_head_grp, 0u); if (kctx->csf.sched.num_runnable_grps == 0) { struct kbase_context *new_head_kctx; @@ -2031,13 +2033,11 @@ void remove_group_from_runnable(struct kbase_csf_scheduler *const scheduler, list_del_init(&kctx->csf.link); if (scheduler->top_ctx == kctx) scheduler->top_ctx = NULL; - KBASE_KTRACE_ADD(kctx->kbdev, SCHEDULER_REMOVE_RUNNABLE, kctx, - 0u); + KBASE_KTRACE_ADD(kctx->kbdev, SCHEDULER_RUNNABLE_KCTX_REMOVE, kctx, 0u); new_head_kctx = (!list_empty(kctx_list)) ? list_first_entry(kctx_list, struct kbase_context, csf.link) : NULL; - KBASE_KTRACE_ADD(kctx->kbdev, SCHEDULER_HEAD_RUNNABLE, - new_head_kctx, 0u); + KBASE_KTRACE_ADD(kctx->kbdev, SCHEDULER_RUNNABLE_KCTX_HEAD, new_head_kctx, 0u); } WARN_ON(scheduler->total_runnable_grps == 0); @@ -2064,7 +2064,7 @@ static void insert_group_to_idle_wait(struct kbase_queue_group *const group) list_add_tail(&group->link, &kctx->csf.sched.idle_wait_groups); kctx->csf.sched.num_idle_wait_grps++; - KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_INSERT_IDLE_WAIT, group, + KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_IDLE_WAIT_INSERT, group, kctx->csf.sched.num_idle_wait_grps); group->run_state = KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC; dev_dbg(kctx->kbdev->dev, @@ -2085,13 +2085,12 @@ static void remove_group_from_idle_wait(struct kbase_queue_group *const group) list_del_init(&group->link); WARN_ON(kctx->csf.sched.num_idle_wait_grps == 0); kctx->csf.sched.num_idle_wait_grps--; - KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_REMOVE_IDLE_WAIT, group, + KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_IDLE_WAIT_REMOVE, group, kctx->csf.sched.num_idle_wait_grps); new_head_grp = (!list_empty(list)) ? list_first_entry(list, struct kbase_queue_group, link) : NULL; - KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_HEAD_IDLE_WAIT, - new_head_grp, 0u); + KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_IDLE_WAIT_HEAD, new_head_grp, 0u); group->run_state = KBASE_CSF_GROUP_INACTIVE; } @@ -2117,8 +2116,7 @@ static void update_offslot_non_idle_cnt_for_faulty_grp(struct kbase_queue_group if (group->prepared_seq_num < scheduler->non_idle_scanout_grps) { int new_val = atomic_dec_return(&scheduler->non_idle_offslot_grps); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_DEC, - group, new_val); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_GRP_DEC, group, new_val); } } @@ -2134,8 +2132,7 @@ static void update_offslot_non_idle_cnt_for_onslot_grp(struct kbase_queue_group if (group->prepared_seq_num < scheduler->non_idle_scanout_grps) { int new_val = atomic_dec_return(&scheduler->non_idle_offslot_grps); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_DEC, - group, new_val); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_GRP_DEC, group, new_val); } } @@ -2155,15 +2152,15 @@ static void update_offslot_non_idle_cnt_on_grp_suspend( if (group->run_state == KBASE_CSF_GROUP_SUSPENDED) { int new_val = atomic_inc_return( &scheduler->non_idle_offslot_grps); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC, - group, new_val); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_GRP_INC, + group, new_val); } } else { if (group->run_state != KBASE_CSF_GROUP_SUSPENDED) { int new_val = atomic_dec_return( &scheduler->non_idle_offslot_grps); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_DEC, - group, new_val); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_GRP_DEC, + group, new_val); } } } else { @@ -2171,8 +2168,8 @@ static void update_offslot_non_idle_cnt_on_grp_suspend( if (group->run_state == KBASE_CSF_GROUP_SUSPENDED) { int new_val = atomic_inc_return( &scheduler->non_idle_offslot_grps); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC, - group, new_val); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_GRP_INC, group, + new_val); } } } @@ -2411,7 +2408,7 @@ static void update_csg_slot_priority(struct kbase_queue_group *group, u8 prio) group->handle, group->kctx->tgid, group->kctx->id, slot, prev_prio, prio); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_PRIO_UPDATE, group, prev_prio); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_PRIO_UPDATE, group, prev_prio); kbase_csf_ring_csg_doorbell(kbdev, slot); set_bit(slot, kbdev->csf.scheduler.csg_slots_prio_update); @@ -2560,10 +2557,9 @@ static void program_csg_slot(struct kbase_queue_group *group, s8 slot, dev_dbg(kbdev->dev, "Starting group %d of context %d_%d on slot %d with priority %u\n", group->handle, kctx->tgid, kctx->id, slot, prio); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_START, group, - (((u64)ep_cfg) << 32) | - ((((u32)kctx->as_nr) & 0xF) << 16) | - (state & (CSG_REQ_STATE_MASK >> CS_REQ_STATE_SHIFT))); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_START_REQ, group, + (((u64)ep_cfg) << 32) | ((((u32)kctx->as_nr) & 0xF) << 16) | + (state & (CSG_REQ_STATE_MASK >> CS_REQ_STATE_SHIFT))); kbase_csf_ring_csg_doorbell(kbdev, slot); @@ -2605,8 +2601,8 @@ static void sched_evict_group(struct kbase_queue_group *group, bool fault, group->run_state == KBASE_CSF_GROUP_RUNNABLE)) { int new_val = atomic_dec_return( &scheduler->non_idle_offslot_grps); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_DEC, - group, new_val); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_GRP_DEC, group, + new_val); } for (i = 0; i < MAX_SUPPORTED_STREAMS_PER_GROUP; i++) { @@ -2630,9 +2626,9 @@ static void sched_evict_group(struct kbase_queue_group *group, bool fault, if (fault) group->run_state = KBASE_CSF_GROUP_FAULT_EVICTED; - KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_EVICT_SCHED, group, - (((u64)scheduler->total_runnable_grps) << 32) | - ((u32)group->run_state)); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_EVICT, group, + (((u64)scheduler->total_runnable_grps) << 32) | + ((u32)group->run_state)); dev_dbg(kbdev->dev, "group %d exited scheduler, num_runnable_grps %d\n", group->handle, scheduler->total_runnable_grps); /* Notify a group has been evicted */ @@ -2783,6 +2779,8 @@ static int scheduler_group_schedule(struct kbase_queue_group *group) if (protm_grp && protm_grp != group) { clear_bit((unsigned int)group->csg_nr, scheduler->csg_slots_idle_mask); + /* Request the update to confirm the condition inferred. */ + group->reevaluate_idle_status = true; KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_CLEAR, group, scheduler->csg_slots_idle_mask[0]); } @@ -2809,8 +2807,7 @@ static int scheduler_group_schedule(struct kbase_queue_group *group) /* A new group into the scheduler */ new_val = atomic_inc_return( &kbdev->csf.scheduler.non_idle_offslot_grps); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC, - group, new_val); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_GRP_INC, group, new_val); } /* Since a group has become active now, check if GPU needs to be @@ -3448,6 +3445,17 @@ static void wait_csg_slots_finish_prio_update(struct kbase_device *kbdev) } } +static void report_csg_termination(struct kbase_queue_group *const group) +{ + struct base_gpu_queue_group_error + err = { .error_type = BASE_GPU_QUEUE_GROUP_ERROR_FATAL, + .payload = { .fatal_group = { + .status = GPU_EXCEPTION_TYPE_SW_FAULT_2, + } } }; + + kbase_csf_add_group_fatal_error(group, &err); +} + void kbase_csf_scheduler_evict_ctx_slots(struct kbase_device *kbdev, struct kbase_context *kctx, struct list_head *evicted_groups) { @@ -3465,16 +3473,21 @@ void kbase_csf_scheduler_evict_ctx_slots(struct kbase_device *kbdev, */ WARN_ON(!kbase_reset_gpu_is_active(kbdev)); - KBASE_KTRACE_ADD(kbdev, EVICT_CTX_SLOTS, kctx, 0u); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_EVICT_CTX_SLOTS_START, kctx, 0u); for (slot = 0; slot < num_groups; slot++) { group = kbdev->csf.scheduler.csg_slots[slot].resident_group; if (group && group->kctx == kctx) { bool as_fault; + dev_dbg(kbdev->dev, "Evicting group [%d] running on slot [%d] due to reset", + group->handle, group->csg_nr); + term_csg_slot(group); as_fault = cleanup_csg_slot(group); /* remove the group from the scheduler list */ sched_evict_group(group, as_fault, false); + /* signal Userspace that CSG is being terminated */ + report_csg_termination(group); /* return the evicted group to the caller */ list_add_tail(&group->link, evicted_groups); set_bit(slot, slot_mask); @@ -3484,6 +3497,15 @@ void kbase_csf_scheduler_evict_ctx_slots(struct kbase_device *kbdev, dev_info(kbdev->dev, "Evicting context %d_%d slots: 0x%*pb\n", kctx->tgid, kctx->id, num_groups, slot_mask); + /* Fatal errors may have been the cause of the GPU reset + * taking place, in which case we want to make sure that + * we wake up the fatal event queue to notify userspace + * only once. Otherwise, we may have duplicate event + * notifications between the time the first notification + * occurs and the time the GPU is reset. + */ + kbase_event_wakeup(kctx); + mutex_unlock(&scheduler->lock); } @@ -3528,8 +3550,8 @@ static bool scheduler_slot_protm_ack(struct kbase_device *const kbdev, struct kbase_queue *queue = group->bound_queues[i]; clear_bit(i, group->protm_pending_bitmap); - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, PROTM_PENDING_CLEAR, group, - queue, group->protm_pending_bitmap[0]); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_PROTM_PEND_CLEAR, group, queue, + group->protm_pending_bitmap[0]); if (!WARN_ON(!queue) && queue->enabled) { struct kbase_csf_cmd_stream_info *stream = @@ -3564,6 +3586,42 @@ static bool scheduler_slot_protm_ack(struct kbase_device *const kbdev, return protm_ack; } +/** + * protm_enter_set_next_pending_seq - Update the scheduler's field of + * tick_protm_pending_seq to that from the next available on-slot protm + * pending CSG. + * + * @kbdev: Pointer to the GPU device. + * + * If applicable, the function updates the scheduler's tick_protm_pending_seq + * field from the next available on-slot protm pending CSG. If not, the field + * is set to KBASEP_TICK_PROTM_PEND_SCAN_SEQ_NR_INVALID. + */ +static void protm_enter_set_next_pending_seq(struct kbase_device *const kbdev) +{ + struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; + u32 num_groups = kbdev->csf.global_iface.group_num; + u32 num_csis = kbdev->csf.global_iface.groups[0].stream_num; + DECLARE_BITMAP(active_csgs, MAX_SUPPORTED_CSGS) = { 0 }; + u32 i; + + kbase_csf_scheduler_spin_lock_assert_held(kbdev); + + bitmap_xor(active_csgs, scheduler->csg_slots_idle_mask, scheduler->csg_inuse_bitmap, + num_groups); + /* Reset the tick's pending protm seq number to invalid initially */ + scheduler->tick_protm_pending_seq = KBASEP_TICK_PROTM_PEND_SCAN_SEQ_NR_INVALID; + for_each_set_bit(i, active_csgs, num_groups) { + struct kbase_queue_group *group = scheduler->csg_slots[i].resident_group; + + /* Set to the next pending protm group's scan_seq_number */ + if ((group != scheduler->active_protm_grp) && + (!bitmap_empty(group->protm_pending_bitmap, num_csis)) && + (group->scan_seq_num < scheduler->tick_protm_pending_seq)) + scheduler->tick_protm_pending_seq = group->scan_seq_num; + } +} + /** * scheduler_group_check_protm_enter - Request the given group to be evaluated * for triggering the protected mode. @@ -3600,8 +3658,7 @@ static void scheduler_group_check_protm_enter(struct kbase_device *const kbdev, */ protm_in_use = kbase_csf_scheduler_protected_mode_in_use(kbdev) || kbdev->protected_mode; - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_CHECK_PROTM_ENTER, input_grp, - protm_in_use); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_PROTM_ENTER_CHECK, input_grp, protm_in_use); /* Firmware samples the PROTM_PEND ACK bit for CSs when * Host sends PROTM_ENTER global request. So if PROTM_PEND ACK bit @@ -3641,13 +3698,13 @@ static void scheduler_group_check_protm_enter(struct kbase_device *const kbdev, /* Switch to protected mode */ scheduler->active_protm_grp = input_grp; - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_ENTER_PROTM, - input_grp, 0u); - /* Reset the tick's pending protm seq number */ - scheduler->tick_protm_pending_seq = - KBASEP_TICK_PROTM_PEND_SCAN_SEQ_NR_INVALID; + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_PROTM_ENTER, input_grp, + 0u); kbase_csf_enter_protected_mode(kbdev); + /* Set the pending protm seq number to the next one */ + protm_enter_set_next_pending_seq(kbdev); + spin_unlock_irqrestore(&scheduler->interrupt_lock, flags); kbase_csf_wait_protected_mode_enter(kbdev); @@ -3812,7 +3869,7 @@ static void scheduler_ctx_scan_groups(struct kbase_device *kbdev, } if (queue_group_idle_locked(group)) { - if (on_slot_group_idle_locked(group)) + if (can_schedule_idle_group(group)) list_add_tail(&group->link_to_schedule, &scheduler->idle_groups_to_schedule); continue; @@ -3898,10 +3955,9 @@ static void scheduler_rotate_groups(struct kbase_device *kbdev) new_head_grp = (!list_empty(list)) ? list_first_entry(list, struct kbase_queue_group, link) : NULL; - KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_ROTATE_RUNNABLE, - top_grp, top_ctx->csf.sched.num_runnable_grps); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_HEAD_RUNNABLE, - new_head_grp, 0u); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_RUNNABLE_ROTATE, top_grp, + top_ctx->csf.sched.num_runnable_grps); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_RUNNABLE_HEAD, new_head_grp, 0u); dev_dbg(kbdev->dev, "groups rotated for a context, num_runnable_groups: %u\n", scheduler->top_ctx->csf.sched.num_runnable_grps); @@ -3932,13 +3988,12 @@ static void scheduler_rotate_ctxs(struct kbase_device *kbdev) struct kbase_context *new_head_kctx; list_move_tail(&pos->csf.link, list); - KBASE_KTRACE_ADD(kbdev, SCHEDULER_ROTATE_RUNNABLE, pos, - 0u); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_RUNNABLE_KCTX_ROTATE, pos, 0u); new_head_kctx = (!list_empty(list)) ? list_first_entry(list, struct kbase_context, csf.link) : NULL; - KBASE_KTRACE_ADD(kbdev, SCHEDULER_HEAD_RUNNABLE, - new_head_kctx, 0u); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_RUNNABLE_KCTX_HEAD, new_head_kctx, + 0u); dev_dbg(kbdev->dev, "contexts rotated\n"); } } @@ -3953,12 +4008,17 @@ static void scheduler_rotate_ctxs(struct kbase_device *kbdev) * @kbdev: Pointer to the GPU device. * @csg_bitmap: Bitmap of the CSG slots for which * the status update request completed successfully. - * @failed_csg_bitmap: Bitmap of the CSG slots for which + * @failed_csg_bitmap: Bitmap of the idle CSG slots for which * the status update request timedout. * * This function sends a CSG status update request for all the CSG slots - * present in the bitmap scheduler->csg_slots_idle_mask and wait for the - * request to complete. + * present in the bitmap scheduler->csg_slots_idle_mask. Additionally, if + * the group's 'reevaluate_idle_status' field is set, the nominally non-idle + * slots are also included in the status update for a confirmation of their + * status. The function wait for the status update request to complete and + * returns the update completed slots bitmap and any timed out idle-flagged + * slots bitmap. + * * The bits set in the scheduler->csg_slots_idle_mask bitmap are cleared by * this function. */ @@ -3970,35 +4030,71 @@ static void scheduler_update_idle_slots_status(struct kbase_device *kbdev, struct kbase_csf_global_iface *const global_iface = &kbdev->csf.global_iface; unsigned long flags, i; + u32 active_chk = 0; lockdep_assert_held(&scheduler->lock); spin_lock_irqsave(&scheduler->interrupt_lock, flags); - for_each_set_bit(i, scheduler->csg_slots_idle_mask, num_groups) { + + for_each_set_bit(i, scheduler->csg_inuse_bitmap, num_groups) { struct kbase_csf_csg_slot *csg_slot = &scheduler->csg_slots[i]; struct kbase_queue_group *group = csg_slot->resident_group; struct kbase_csf_cmd_stream_group_info *const ginfo = &global_iface->groups[i]; u32 csg_req; + bool idle_flag; - clear_bit(i, scheduler->csg_slots_idle_mask); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_CLEAR, group, - scheduler->csg_slots_idle_mask[0]); - if (WARN_ON(!group)) + if (WARN_ON(!group)) { + clear_bit(i, scheduler->csg_inuse_bitmap); + clear_bit(i, scheduler->csg_slots_idle_mask); continue; + } - KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_STATUS_UPDATE, group, - i); + idle_flag = test_bit(i, scheduler->csg_slots_idle_mask); + if (idle_flag || group->reevaluate_idle_status) { + if (idle_flag) { +#ifdef CONFIG_MALI_BIFROST_DEBUG + if (!bitmap_empty(group->protm_pending_bitmap, + ginfo->stream_num)) { + dev_warn(kbdev->dev, + "Idle bit set for group %d of ctx %d_%d on slot %d with pending protm execution", + group->handle, group->kctx->tgid, + group->kctx->id, (int)i); + } +#endif + clear_bit(i, scheduler->csg_slots_idle_mask); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_CLEAR, group, + scheduler->csg_slots_idle_mask[0]); + } else { + /* Updates include slots for which reevaluation is needed. + * Here one tracks the extra included slots in active_chk. + * For protm pending slots, their status of activeness are + * assured so no need to request an update. + */ + active_chk |= BIT(i); + group->reevaluate_idle_status = false; + } - csg_req = kbase_csf_firmware_csg_output(ginfo, CSG_ACK); - csg_req ^= CSG_REQ_STATUS_UPDATE_MASK; - kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, csg_req, - CSG_REQ_STATUS_UPDATE_MASK); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_UPDATE_IDLE_SLOT_REQ, group, i); + csg_req = kbase_csf_firmware_csg_output(ginfo, CSG_ACK); + csg_req ^= CSG_REQ_STATUS_UPDATE_MASK; + kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, csg_req, + CSG_REQ_STATUS_UPDATE_MASK); - set_bit(i, csg_bitmap); + /* Track the slot update requests in csg_bitmap. + * Note, if the scheduler requested extended update, the resulting + * csg_bitmap would be the idle_flags + active_chk. Otherwise it's + * identical to the idle_flags. + */ + set_bit(i, csg_bitmap); + } else { + group->run_state = KBASE_CSF_GROUP_RUNNABLE; + } } + spin_unlock_irqrestore(&scheduler->interrupt_lock, flags); + /* The groups are aggregated into a single kernel doorbell request */ if (!bitmap_empty(csg_bitmap, num_groups)) { long wt = @@ -4019,9 +4115,19 @@ static void scheduler_update_idle_slots_status(struct kbase_device *kbdev, /* Store the bitmap of timed out slots */ bitmap_copy(failed_csg_bitmap, csg_bitmap, num_groups); csg_bitmap[0] = ~csg_bitmap[0] & db_slots; + + /* Mask off any failed bit position contributed from active ones, as the + * intention is to retain the failed bit pattern contains only those from + * idle flags reporting back to the caller. This way, any failed to update + * original idle flag would be kept as 'idle' (an informed guess, as the + * update did not come to a conclusive result). So will be the failed + * active ones be treated as still 'non-idle'. This is for a graceful + * handling to the unexpected timeout condition. + */ + failed_csg_bitmap[0] &= ~active_chk; + } else { - KBASE_KTRACE_ADD(kbdev, SLOTS_STATUS_UPDATE_ACK, NULL, - db_slots); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_UPDATE_IDLE_SLOTS_ACK, NULL, db_slots); csg_bitmap[0] = db_slots; } } @@ -4100,8 +4206,7 @@ static void scheduler_scan_idle_groups(struct kbase_device *kbdev) list_for_each_entry_safe(group, n, &scheduler->idle_groups_to_schedule, link_to_schedule) { - - WARN_ON(!on_slot_group_idle_locked(group)); + WARN_ON(!can_schedule_idle_group(group)); if (!scheduler->ngrp_to_schedule) { /* keep the top csg's origin */ @@ -4235,7 +4340,7 @@ static bool all_on_slot_groups_remained_idle(struct kbase_device *kbdev) u64 const *output_addr; u64 cur_extract_ofs; - if (!queue) + if (!queue || !queue->user_io_addr) continue; output_addr = (u64 const *)(queue->user_io_addr + PAGE_SIZE); @@ -4336,7 +4441,7 @@ static bool scheduler_suspend_on_idle(struct kbase_device *kbdev) atomic_read( &kbdev->csf.scheduler.non_idle_offslot_grps)); /* Bring forward the next tick */ - kbase_csf_scheduler_advance_tick(kbdev); + kbase_csf_scheduler_tick_advance(kbdev); return false; } @@ -4354,14 +4459,14 @@ static void gpu_idle_worker(struct work_struct *work) bool scheduler_is_idle_suspendable = false; bool all_groups_suspended = false; - KBASE_KTRACE_ADD(kbdev, IDLE_WORKER_BEGIN, NULL, 0u); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_GPU_IDLE_WORKER_START, NULL, 0u); #define __ENCODE_KTRACE_INFO(reset, idle, all_suspend) \ (((u32)reset) | (((u32)idle) << 4) | (((u32)all_suspend) << 8)) if (kbase_reset_gpu_try_prevent(kbdev)) { dev_warn(kbdev->dev, "Quit idle for failing to prevent gpu reset.\n"); - KBASE_KTRACE_ADD(kbdev, IDLE_WORKER_END, NULL, + KBASE_KTRACE_ADD(kbdev, SCHEDULER_GPU_IDLE_WORKER_END, NULL, __ENCODE_KTRACE_INFO(true, false, false)); return; } @@ -4369,7 +4474,7 @@ static void gpu_idle_worker(struct work_struct *work) scheduler_is_idle_suspendable = scheduler_idle_suspendable(kbdev); if (scheduler_is_idle_suspendable) { - KBASE_KTRACE_ADD(kbdev, GPU_IDLE_HANDLING_START, NULL, + KBASE_KTRACE_ADD(kbdev, SCHEDULER_GPU_IDLE_WORKER_HANDLING_START, NULL, kbase_csf_ktrace_gpu_cycle_cnt(kbdev)); #ifdef KBASE_PM_RUNTIME if (kbase_pm_gpu_sleep_allowed(kbdev) && @@ -4382,9 +4487,8 @@ static void gpu_idle_worker(struct work_struct *work) mutex_unlock(&scheduler->lock); kbase_reset_gpu_allow(kbdev); - KBASE_KTRACE_ADD(kbdev, IDLE_WORKER_END, NULL, - __ENCODE_KTRACE_INFO(false, - scheduler_is_idle_suspendable, + KBASE_KTRACE_ADD(kbdev, SCHEDULER_GPU_IDLE_WORKER_END, NULL, + __ENCODE_KTRACE_INFO(false, scheduler_is_idle_suspendable, all_groups_suspended)); #undef __ENCODE_KTRACE_INFO } @@ -4440,7 +4544,7 @@ static int scheduler_prepare(struct kbase_device *kbdev) */ atomic_set(&scheduler->non_idle_offslot_grps, scheduler->non_idle_scanout_grps); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC, NULL, + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_GRP_INC, NULL, scheduler->non_idle_scanout_grps); /* Adds those idle but runnable groups to the scanout list */ @@ -4629,8 +4733,8 @@ redo_local_tock: dev_dbg(kbdev->dev, "Scheduler keep protm exec: group-%d", protm_grp->handle); new_val = atomic_dec_return(&scheduler->non_idle_offslot_grps); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_DEC, - protm_grp, new_val); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_GRP_DEC, protm_grp, + new_val); spin_unlock_irqrestore(&scheduler->interrupt_lock, flags); @@ -4767,7 +4871,7 @@ static void schedule_on_tock(struct work_struct *work) scheduler->state = SCHED_BUSY; /* Undertaking schedule action steps */ - KBASE_KTRACE_ADD(kbdev, SCHEDULER_TOCK, NULL, 0u); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_TOCK_START, NULL, 0u); schedule_actions(kbdev, false); /* Record time information on a non-skipped tock */ @@ -4812,8 +4916,7 @@ static void schedule_on_tick(struct work_struct *work) scheduler->state = SCHED_BUSY; /* Undertaking schedule action steps */ - KBASE_KTRACE_ADD(kbdev, SCHEDULER_TICK, NULL, - scheduler->total_runnable_grps); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_TICK_START, NULL, scheduler->total_runnable_grps); schedule_actions(kbdev, true); /* Record time information */ @@ -5074,8 +5177,7 @@ static bool scheduler_handle_reset_in_protected_mode(struct kbase_device *kbdev) * anyways. */ new_val = atomic_inc_return(&scheduler->non_idle_offslot_grps); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_INC, - group, new_val); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_NONIDLE_OFFSLOT_GRP_INC, group, new_val); } unlock: @@ -5109,8 +5211,8 @@ static void scheduler_inner_reset(struct kbase_device *kbdev) spin_lock_irqsave(&scheduler->interrupt_lock, flags); bitmap_fill(scheduler->csgs_events_enable_mask, MAX_SUPPORTED_CSGS); if (scheduler->active_protm_grp) - KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_EXIT_PROTM, - scheduler->active_protm_grp, 0u); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_PROTM_EXIT, scheduler->active_protm_grp, + 0u); scheduler->active_protm_grp = NULL; memset(kbdev->csf.scheduler.csg_slots, 0, num_groups * sizeof(struct kbase_csf_csg_slot)); @@ -5133,7 +5235,7 @@ void kbase_csf_scheduler_reset(struct kbase_device *kbdev) WARN_ON(!kbase_reset_gpu_is_active(kbdev)); - KBASE_KTRACE_ADD(kbdev, SCHEDULER_RESET, NULL, 0u); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_RESET_START, NULL, 0u); if (scheduler_handle_reset_in_protected_mode(kbdev) && !suspend_active_queue_groups_on_reset(kbdev)) { @@ -5235,9 +5337,9 @@ static void firmware_aliveness_monitor(struct work_struct *work) kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) kbase_reset_gpu(kbdev); } else if (kbase_csf_scheduler_get_nr_active_csgs(kbdev) == 1) { - queue_delayed_work(system_long_wq, - &kbdev->csf.scheduler.ping_work, - msecs_to_jiffies(FIRMWARE_PING_INTERVAL_MS)); + queue_delayed_work( + system_long_wq, &kbdev->csf.scheduler.ping_work, + msecs_to_jiffies(kbase_get_timeout_ms(kbdev, CSF_FIRMWARE_PING_TIMEOUT))); } kbase_pm_context_idle(kbdev); @@ -5537,7 +5639,7 @@ static bool check_sync_update_for_on_slot_group( stream, CS_STATUS_WAIT); unsigned long flags; - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_STATUS_WAIT, + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE_WAIT_STATUS, queue->group, queue, status); if (!CS_STATUS_WAIT_SYNC_WAIT_GET(status)) @@ -5579,6 +5681,10 @@ static bool check_sync_update_for_on_slot_group( scheduler->csg_slots_idle_mask[0]); spin_unlock_irqrestore( &scheduler->interrupt_lock, flags); + /* Request the scheduler to confirm the condition inferred + * here inside the protected mode. + */ + group->reevaluate_idle_status = true; group->run_state = KBASE_CSF_GROUP_RUNNABLE; } @@ -5689,7 +5795,7 @@ static void check_group_sync_update_worker(struct work_struct *work) mutex_lock(&scheduler->lock); - KBASE_KTRACE_ADD(kbdev, GROUP_SYNC_UPDATE_WORKER_BEGIN, kctx, 0u); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_GROUP_SYNC_UPDATE_WORKER_START, kctx, 0u); if (kctx->csf.sched.num_idle_wait_grps != 0) { struct kbase_queue_group *group, *temp; @@ -5719,7 +5825,7 @@ static void check_group_sync_update_worker(struct work_struct *work) if (!sync_updated && (scheduler->state == SCHED_SLEEPING)) check_sync_update_in_sleep_mode(kbdev); - KBASE_KTRACE_ADD(kbdev, GROUP_SYNC_UPDATE_WORKER_END, kctx, 0u); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_GROUP_SYNC_UPDATE_WORKER_END, kctx, 0u); mutex_unlock(&scheduler->lock); } @@ -5729,7 +5835,7 @@ enum kbase_csf_event_callback_action check_group_sync_update_cb(void *param) { struct kbase_context *const kctx = param; - KBASE_KTRACE_ADD(kctx->kbdev, SYNC_UPDATE_EVENT, kctx, 0u); + KBASE_KTRACE_ADD(kctx->kbdev, SCHEDULER_GROUP_SYNC_UPDATE_EVENT, kctx, 0u); queue_work(kctx->csf.sched.sync_update_wq, &kctx->csf.sched.sync_update_work); @@ -5999,24 +6105,12 @@ out: mutex_unlock(&scheduler->lock); } -int kbase_csf_scheduler_pm_suspend(struct kbase_device *kbdev) +int kbase_csf_scheduler_pm_suspend_no_lock(struct kbase_device *kbdev) { - int result = 0; struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; + int result = 0; - /* Cancel any potential queued delayed work(s) */ - cancel_work_sync(&scheduler->tick_work); - cancel_tock_work(scheduler); - - result = kbase_reset_gpu_prevent_and_wait(kbdev); - if (result) { - dev_warn(kbdev->dev, - "Stop PM suspending for failing to prevent gpu reset.\n"); - return result; - } - - mutex_lock(&scheduler->lock); - + lockdep_assert_held(&scheduler->lock); #ifdef KBASE_PM_RUNTIME /* If scheduler is in sleeping state, then MCU needs to be activated * to suspend CSGs. @@ -6043,6 +6137,27 @@ int kbase_csf_scheduler_pm_suspend(struct kbase_device *kbdev) } exit: + return result; +} + +int kbase_csf_scheduler_pm_suspend(struct kbase_device *kbdev) +{ + int result = 0; + struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; + + /* Cancel any potential queued delayed work(s) */ + cancel_work_sync(&scheduler->tick_work); + cancel_tock_work(scheduler); + + result = kbase_reset_gpu_prevent_and_wait(kbdev); + if (result) { + dev_warn(kbdev->dev, "Stop PM suspending for failing to prevent gpu reset.\n"); + return result; + } + + mutex_lock(&scheduler->lock); + + result = kbase_csf_scheduler_pm_suspend_no_lock(kbdev); mutex_unlock(&scheduler->lock); kbase_reset_gpu_allow(kbdev); @@ -6051,17 +6166,24 @@ exit: } KBASE_EXPORT_TEST_API(kbase_csf_scheduler_pm_suspend); -void kbase_csf_scheduler_pm_resume(struct kbase_device *kbdev) +void kbase_csf_scheduler_pm_resume_no_lock(struct kbase_device *kbdev) { struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; - mutex_lock(&scheduler->lock); + lockdep_assert_held(&scheduler->lock); if ((scheduler->total_runnable_grps > 0) && (scheduler->state == SCHED_SUSPENDED)) { dev_info(kbdev->dev, "Scheduler PM resume"); scheduler_wakeup(kbdev, true); } - mutex_unlock(&scheduler->lock); +} + +void kbase_csf_scheduler_pm_resume(struct kbase_device *kbdev) +{ + mutex_lock(&kbdev->csf.scheduler.lock); + + kbase_csf_scheduler_pm_resume_no_lock(kbdev); + mutex_unlock(&kbdev->csf.scheduler.lock); } KBASE_EXPORT_TEST_API(kbase_csf_scheduler_pm_resume); diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.h index a00a9ca168a3..12df5054e573 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2019-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -409,6 +409,17 @@ void kbase_csf_scheduler_pm_idle(struct kbase_device *kbdev); */ int kbase_csf_scheduler_wait_mcu_active(struct kbase_device *kbdev); +/** + * kbase_csf_scheduler_pm_resume_no_lock - Reactivate the scheduler on system resume + * + * @kbdev: Instance of a GPU platform device that implements a CSF interface. + * + * This function will make the scheduler resume the scheduling of queue groups + * and take the power managemenet reference, if there are any runnable groups. + * The caller must have acquired the global Scheduler lock. + */ +void kbase_csf_scheduler_pm_resume_no_lock(struct kbase_device *kbdev); + /** * kbase_csf_scheduler_pm_resume - Reactivate the scheduler on system resume * @@ -419,6 +430,19 @@ int kbase_csf_scheduler_wait_mcu_active(struct kbase_device *kbdev); */ void kbase_csf_scheduler_pm_resume(struct kbase_device *kbdev); +/** + * kbase_csf_scheduler_pm_suspend_no_lock - Idle the scheduler on system suspend + * + * @kbdev: Instance of a GPU platform device that implements a CSF interface. + * + * This function will make the scheduler suspend all the running queue groups + * and drop its power managemenet reference. + * The caller must have acquired the global Scheduler lock. + * + * Return: 0 on success. + */ +int kbase_csf_scheduler_pm_suspend_no_lock(struct kbase_device *kbdev); + /** * kbase_csf_scheduler_pm_suspend - Idle the scheduler on system suspend * @@ -448,7 +472,7 @@ static inline bool kbase_csf_scheduler_all_csgs_idle(struct kbase_device *kbdev) } /** - * kbase_csf_scheduler_advance_tick_nolock() - Advance the scheduling tick + * kbase_csf_scheduler_tick_advance_nolock() - Advance the scheduling tick * * @kbdev: Pointer to the device * @@ -458,23 +482,23 @@ static inline bool kbase_csf_scheduler_all_csgs_idle(struct kbase_device *kbdev) * The caller must hold the interrupt lock. */ static inline void -kbase_csf_scheduler_advance_tick_nolock(struct kbase_device *kbdev) +kbase_csf_scheduler_tick_advance_nolock(struct kbase_device *kbdev) { struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; lockdep_assert_held(&scheduler->interrupt_lock); if (scheduler->tick_timer_active) { - KBASE_KTRACE_ADD(kbdev, SCHEDULER_ADVANCE_TICK, NULL, 0u); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_TICK_ADVANCE, NULL, 0u); scheduler->tick_timer_active = false; queue_work(scheduler->wq, &scheduler->tick_work); } else { - KBASE_KTRACE_ADD(kbdev, SCHEDULER_NOADVANCE_TICK, NULL, 0u); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_TICK_NOADVANCE, NULL, 0u); } } /** - * kbase_csf_scheduler_advance_tick() - Advance the scheduling tick + * kbase_csf_scheduler_tick_advance() - Advance the scheduling tick * * @kbdev: Pointer to the device * @@ -482,13 +506,13 @@ kbase_csf_scheduler_advance_tick_nolock(struct kbase_device *kbdev) * immediate execution, but only if the tick hrtimer is active. If the timer * is inactive then the tick work item is already in flight. */ -static inline void kbase_csf_scheduler_advance_tick(struct kbase_device *kbdev) +static inline void kbase_csf_scheduler_tick_advance(struct kbase_device *kbdev) { struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; unsigned long flags; spin_lock_irqsave(&scheduler->interrupt_lock, flags); - kbase_csf_scheduler_advance_tick_nolock(kbdev); + kbase_csf_scheduler_tick_advance_nolock(kbdev); spin_unlock_irqrestore(&scheduler->interrupt_lock, flags); } diff --git a/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_codes_csf.h b/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_codes_csf.h index 2506ce184fcf..9e4da9f11787 100644 --- a/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_codes_csf.h +++ b/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_codes_csf.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -42,67 +42,67 @@ int dummy_array[] = { /* * Generic CSF events */ - KBASE_KTRACE_CODE_MAKE_CODE(EVICT_CTX_SLOTS), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_EVICT_CTX_SLOTS_START), /* info_val[0:7] == fw version_minor * info_val[15:8] == fw version_major * info_val[63:32] == fw version_hash */ - KBASE_KTRACE_CODE_MAKE_CODE(FIRMWARE_BOOT), - KBASE_KTRACE_CODE_MAKE_CODE(FIRMWARE_REBOOT), - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TOCK), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_FIRMWARE_BOOT), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_FIRMWARE_REBOOT), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TOCK_START), KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TOCK_END), /* info_val == total number of runnable groups across all kctxs */ - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TICK), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TICK_START), KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TICK_END), - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_RESET), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_RESET_START), /* info_val = timeout in ms */ - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_WAIT_PROTM_QUIT), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_PROTM_WAIT_QUIT_START), /* info_val = remaining ms timeout, or 0 if timedout */ - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_WAIT_PROTM_QUIT_DONE), - KBASE_KTRACE_CODE_MAKE_CODE(SYNC_UPDATE_EVENT), - KBASE_KTRACE_CODE_MAKE_CODE(SYNC_UPDATE_EVENT_NOTIFY_GPU), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_PROTM_WAIT_QUIT_END), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_GROUP_SYNC_UPDATE_EVENT), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_SYNC_UPDATE_NOTIFY_GPU_EVENT), /* info_val = JOB_IRQ_STATUS */ - KBASE_KTRACE_CODE_MAKE_CODE(CSF_INTERRUPT), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_INTERRUPT_START), /* info_val = JOB_IRQ_STATUS */ KBASE_KTRACE_CODE_MAKE_CODE(CSF_INTERRUPT_END), /* info_val = JOB_IRQ_STATUS */ - KBASE_KTRACE_CODE_MAKE_CODE(CSG_INTERRUPT_PROCESS), + KBASE_KTRACE_CODE_MAKE_CODE(CSG_INTERRUPT_PROCESS_START), /* info_val = GLB_REQ ^ GLB_ACQ */ - KBASE_KTRACE_CODE_MAKE_CODE(GLB_REQ_ACQ), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_INTERRUPT_GLB_REQ_ACK), /* info_val[31:0] = num non idle offslot groups * info_val[32] = scheduler can suspend on idle */ - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_CAN_IDLE), - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_ADVANCE_TICK), - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_NOADVANCE_TICK), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_GPU_IDLE_EVENT_CAN_SUSPEND), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TICK_ADVANCE), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TICK_NOADVANCE), /* kctx is added to the back of the list */ - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_INSERT_RUNNABLE), - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_REMOVE_RUNNABLE), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_RUNNABLE_KCTX_INSERT), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_RUNNABLE_KCTX_REMOVE), /* kctx is moved to the back of the list */ - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_ROTATE_RUNNABLE), - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_HEAD_RUNNABLE), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_RUNNABLE_KCTX_ROTATE), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_RUNNABLE_KCTX_HEAD), - KBASE_KTRACE_CODE_MAKE_CODE(IDLE_WORKER_BEGIN), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_GPU_IDLE_WORKER_START), /* 4-bit encoding of boolean values (ease of reading as hex values) * * info_val[3:0] = was reset active/failed to be prevented * info_val[7:4] = whether scheduler was both idle and suspendable * info_val[11:8] = whether all groups were suspended */ - KBASE_KTRACE_CODE_MAKE_CODE(IDLE_WORKER_END), - KBASE_KTRACE_CODE_MAKE_CODE(GROUP_SYNC_UPDATE_WORKER_BEGIN), - KBASE_KTRACE_CODE_MAKE_CODE(GROUP_SYNC_UPDATE_WORKER_END), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_GPU_IDLE_WORKER_END), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_GROUP_SYNC_UPDATE_WORKER_START), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_GROUP_SYNC_UPDATE_WORKER_END), /* info_val = bitmask of slots that gave an ACK for STATUS_UPDATE */ - KBASE_KTRACE_CODE_MAKE_CODE(SLOTS_STATUS_UPDATE_ACK), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_UPDATE_IDLE_SLOTS_ACK), /* info_val[63:0] = GPU cycle counter, used mainly for benchmarking * purpose. */ - KBASE_KTRACE_CODE_MAKE_CODE(GPU_IDLE_HANDLING_START), - KBASE_KTRACE_CODE_MAKE_CODE(MCU_HALTED), - KBASE_KTRACE_CODE_MAKE_CODE(MCU_IN_SLEEP), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_GPU_IDLE_WORKER_HANDLING_START), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_FIRMWARE_MCU_HALTED), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_FIRMWARE_MCU_SLEEP), /* * Group events @@ -111,17 +111,17 @@ int dummy_array[] = { * info_val[19:16] == as_nr * info_val[63:32] == endpoint config (max number of endpoints allowed) */ - KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_START), + KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_START_REQ), /* info_val == CSG_REQ state issued */ - KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_STOP), + KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_STOP_REQ), /* info_val == CSG_ACK state */ - KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_STARTED), + KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_RUNNING), /* info_val == CSG_ACK state */ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_STOPPED), /* info_val == slot cleaned */ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_CLEANED), /* info_val = slot requesting STATUS_UPDATE */ - KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_STATUS_UPDATE), + KBASE_KTRACE_CODE_MAKE_CODE(CSG_UPDATE_IDLE_SLOT_REQ), /* info_val = scheduler's new csg_slots_idle_mask[0] * group->csg_nr indicates which bit was set */ @@ -133,13 +133,13 @@ int dummy_array[] = { */ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_IDLE_CLEAR), /* info_val == previous priority */ - KBASE_KTRACE_CODE_MAKE_CODE(CSG_PRIO_UPDATE), + KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_PRIO_UPDATE), /* info_val == CSG_REQ ^ CSG_ACK */ - KBASE_KTRACE_CODE_MAKE_CODE(CSG_SYNC_UPDATE_INTERRUPT), + KBASE_KTRACE_CODE_MAKE_CODE(CSG_INTERRUPT_SYNC_UPDATE), /* info_val == CSG_REQ ^ CSG_ACK */ - KBASE_KTRACE_CODE_MAKE_CODE(CSG_IDLE_INTERRUPT), + KBASE_KTRACE_CODE_MAKE_CODE(CSG_INTERRUPT_IDLE), /* info_val == CSG_REQ ^ CSG_ACK */ - KBASE_KTRACE_CODE_MAKE_CODE(CSG_PROGRESS_TIMER_INTERRUPT), + KBASE_KTRACE_CODE_MAKE_CODE(CSG_INTERRUPT_PROGRESS_TIMER_EVENT), /* info_val[31:0] == CSG_REQ ^ CSG_ACQ * info_val[63:32] == CSG_IRQ_REQ ^ CSG_IRQ_ACK */ @@ -152,34 +152,34 @@ int dummy_array[] = { /* info_val[31:0] == new run state of the evicted group * info_val[63:32] == number of runnable groups */ - KBASE_KTRACE_CODE_MAKE_CODE(GROUP_EVICT_SCHED), + KBASE_KTRACE_CODE_MAKE_CODE(GROUP_EVICT), /* info_val == new num_runnable_grps * group is added to the back of the list for its priority level */ - KBASE_KTRACE_CODE_MAKE_CODE(GROUP_INSERT_RUNNABLE), + KBASE_KTRACE_CODE_MAKE_CODE(GROUP_RUNNABLE_INSERT), /* info_val == new num_runnable_grps */ - KBASE_KTRACE_CODE_MAKE_CODE(GROUP_REMOVE_RUNNABLE), + KBASE_KTRACE_CODE_MAKE_CODE(GROUP_RUNNABLE_REMOVE), /* info_val == num_runnable_grps * group is moved to the back of the list for its priority level */ - KBASE_KTRACE_CODE_MAKE_CODE(GROUP_ROTATE_RUNNABLE), - KBASE_KTRACE_CODE_MAKE_CODE(GROUP_HEAD_RUNNABLE), + KBASE_KTRACE_CODE_MAKE_CODE(GROUP_RUNNABLE_ROTATE), + KBASE_KTRACE_CODE_MAKE_CODE(GROUP_RUNNABLE_HEAD), /* info_val == new num_idle_wait_grps * group is added to the back of the list */ - KBASE_KTRACE_CODE_MAKE_CODE(GROUP_INSERT_IDLE_WAIT), + KBASE_KTRACE_CODE_MAKE_CODE(GROUP_IDLE_WAIT_INSERT), /* info_val == new num_idle_wait_grps * group is added to the back of the list */ - KBASE_KTRACE_CODE_MAKE_CODE(GROUP_REMOVE_IDLE_WAIT), - KBASE_KTRACE_CODE_MAKE_CODE(GROUP_HEAD_IDLE_WAIT), + KBASE_KTRACE_CODE_MAKE_CODE(GROUP_IDLE_WAIT_REMOVE), + KBASE_KTRACE_CODE_MAKE_CODE(GROUP_IDLE_WAIT_HEAD), /* info_val == is scheduler running with protected mode tasks */ - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_CHECK_PROTM_ENTER), - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_ENTER_PROTM), - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_EXIT_PROTM), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_PROTM_ENTER_CHECK), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_PROTM_ENTER), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_PROTM_EXIT), /* info_val[31:0] == number of GPU address space slots in use * info_val[63:32] == number of runnable groups */ @@ -187,11 +187,11 @@ int dummy_array[] = { /* info_val == new count of off-slot non-idle groups * no group indicates it was set rather than incremented */ - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_NONIDLE_OFFSLOT_INC), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_NONIDLE_OFFSLOT_GRP_INC), /* info_val == new count of off-slot non-idle groups */ - KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_NONIDLE_OFFSLOT_DEC), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_NONIDLE_OFFSLOT_GRP_DEC), - KBASE_KTRACE_CODE_MAKE_CODE(PROTM_EVENT_WORKER_BEGIN), + KBASE_KTRACE_CODE_MAKE_CODE(PROTM_EVENT_WORKER_START), KBASE_KTRACE_CODE_MAKE_CODE(PROTM_EVENT_WORKER_END), /* @@ -201,42 +201,42 @@ int dummy_array[] = { KBASE_KTRACE_CODE_MAKE_CODE(CSI_START), /* info_val == queue->enabled before stop */ KBASE_KTRACE_CODE_MAKE_CODE(CSI_STOP), - KBASE_KTRACE_CODE_MAKE_CODE(CSI_STOP_REQUESTED), + KBASE_KTRACE_CODE_MAKE_CODE(CSI_STOP_REQ), /* info_val == CS_REQ ^ CS_ACK that were not processed due to the group * being suspended */ - KBASE_KTRACE_CODE_MAKE_CODE(CSI_IGNORED_INTERRUPTS_GROUP_SUSPEND), + KBASE_KTRACE_CODE_MAKE_CODE(CSI_INTERRUPT_GROUP_SUSPENDS_IGNORED), /* info_val == CS_REQ ^ CS_ACK */ - KBASE_KTRACE_CODE_MAKE_CODE(CSI_FAULT_INTERRUPT), + KBASE_KTRACE_CODE_MAKE_CODE(CSI_INTERRUPT_FAULT), /* info_val == CS_REQ ^ CS_ACK */ - KBASE_KTRACE_CODE_MAKE_CODE(CSI_TILER_OOM_INTERRUPT), + KBASE_KTRACE_CODE_MAKE_CODE(CSI_INTERRUPT_TILER_OOM), /* info_val == CS_REQ ^ CS_ACK */ - KBASE_KTRACE_CODE_MAKE_CODE(CSI_PROTM_PEND_INTERRUPT), + KBASE_KTRACE_CODE_MAKE_CODE(CSI_INTERRUPT_PROTM_PEND), /* info_val == CS_ACK_PROTM_PEND ^ CS_REQ_PROTM_PEND */ KBASE_KTRACE_CODE_MAKE_CODE(CSI_PROTM_ACK), /* info_val == group->run_State (for group the queue is bound to) */ KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_START), KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_STOP), /* info_val == contents of CS_STATUS_WAIT_SYNC_POINTER */ - KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_UPDATE), + KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_UPDATE_EVAL_START), /* info_val == bool for result of the evaluation */ - KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_UPDATE_EVALUATED), + KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_UPDATE_EVAL_END), /* info_val == contents of CS_STATUS_WAIT */ - KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_STATUS_WAIT), + KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_UPDATE_WAIT_STATUS), /* info_val == current sync value pointed to by queue->sync_ptr */ - KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_CURRENT_VAL), + KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_UPDATE_CUR_VAL), /* info_val == current value of CS_STATUS_WAIT_SYNC_VALUE */ - KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_TEST_VAL), + KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_UPDATE_TEST_VAL), /* info_val == current value of CS_STATUS_BLOCKED_REASON */ - KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_BLOCKED_REASON), + KBASE_KTRACE_CODE_MAKE_CODE(QUEUE_SYNC_UPDATE_BLOCKED_REASON), /* info_val = group's new protm_pending_bitmap[0] * queue->csi_index indicates which bit was set */ - KBASE_KTRACE_CODE_MAKE_CODE(PROTM_PENDING_SET), + KBASE_KTRACE_CODE_MAKE_CODE(CSI_PROTM_PEND_SET), /* info_val = group's new protm_pending_bitmap[0] * queue->csi_index indicates which bit was cleared */ - KBASE_KTRACE_CODE_MAKE_CODE(PROTM_PENDING_CLEAR), + KBASE_KTRACE_CODE_MAKE_CODE(CSI_PROTM_PEND_CLEAR), /* * KCPU queue events @@ -244,42 +244,42 @@ int dummy_array[] = { /* KTrace info_val == KCPU queue fence context * KCPU extra_info_val == N/A. */ - KBASE_KTRACE_CODE_MAKE_CODE(KCPU_QUEUE_NEW), + KBASE_KTRACE_CODE_MAKE_CODE(KCPU_QUEUE_CREATE), /* KTrace info_val == Number of pending commands in KCPU queue when * it is destroyed. * KCPU extra_info_val == Number of CQS wait operations present in * the KCPU queue when it is destroyed. */ - KBASE_KTRACE_CODE_MAKE_CODE(KCPU_QUEUE_DESTROY), + KBASE_KTRACE_CODE_MAKE_CODE(KCPU_QUEUE_DELETE), /* KTrace info_val == CQS event memory address * KCPU extra_info_val == Upper 32 bits of event memory, i.e. contents * of error field. */ - KBASE_KTRACE_CODE_MAKE_CODE(CQS_SET), + KBASE_KTRACE_CODE_MAKE_CODE(KCPU_CQS_SET), /* KTrace info_val == Number of CQS objects to be waited upon * KCPU extra_info_val == N/A. */ - KBASE_KTRACE_CODE_MAKE_CODE(CQS_WAIT_START), + KBASE_KTRACE_CODE_MAKE_CODE(KCPU_CQS_WAIT_START), /* KTrace info_val == CQS event memory address * KCPU extra_info_val == 1 if CQS was signaled with an error and queue * inherited the error, otherwise 0. */ - KBASE_KTRACE_CODE_MAKE_CODE(CQS_WAIT_END), + KBASE_KTRACE_CODE_MAKE_CODE(KCPU_CQS_WAIT_END), /* KTrace info_val == Fence context * KCPU extra_info_val == Fence seqno. */ - KBASE_KTRACE_CODE_MAKE_CODE(FENCE_SIGNAL), + KBASE_KTRACE_CODE_MAKE_CODE(KCPU_FENCE_SIGNAL), /* KTrace info_val == Fence context * KCPU extra_info_val == Fence seqno. */ - KBASE_KTRACE_CODE_MAKE_CODE(FENCE_WAIT_START), + KBASE_KTRACE_CODE_MAKE_CODE(KCPU_FENCE_WAIT_START), /* KTrace info_val == Fence context * KCPU extra_info_val == Fence seqno. */ - KBASE_KTRACE_CODE_MAKE_CODE(FENCE_WAIT_END), + KBASE_KTRACE_CODE_MAKE_CODE(KCPU_FENCE_WAIT_END), #if 0 /* Dummy section to avoid breaking formatting */ }; #endif -/* ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ + /* ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ diff --git a/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_csf.c b/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_csf.c index 824ca4b87b36..cff6f8959c35 100644 --- a/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_csf.c +++ b/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_csf.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -98,6 +98,9 @@ void kbasep_ktrace_add_csf(struct kbase_device *kbdev, struct kbase_ktrace_msg *trace_msg; struct kbase_context *kctx = NULL; + if (unlikely(!kbasep_ktrace_initialized(&kbdev->ktrace))) + return; + spin_lock_irqsave(&kbdev->ktrace.lock, irqflags); /* Reserve and update indices */ @@ -165,6 +168,9 @@ void kbasep_ktrace_add_csf_kcpu(struct kbase_device *kbdev, struct kbase_ktrace_msg *trace_msg; struct kbase_context *kctx = queue->kctx; + if (unlikely(!kbasep_ktrace_initialized(&kbdev->ktrace))) + return; + spin_lock_irqsave(&kbdev->ktrace.lock, irqflags); /* Reserve and update indices */ diff --git a/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_defs_csf.h b/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_defs_csf.h index 7f32cd2f23c8..1896e10ed4ab 100644 --- a/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_defs_csf.h +++ b/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_defs_csf.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -47,7 +47,7 @@ * 1.3: * Add a lot of extra new traces. Tweak some existing scheduler related traces * to contain extra information information/happen at slightly different times. - * SCHEDULER_EXIT_PROTM now has group information + * SCHEDULER_PROTM_EXIT now has group information */ #define KBASE_KTRACE_VERSION_MAJOR 1 #define KBASE_KTRACE_VERSION_MINOR 3 diff --git a/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_jm.c b/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_jm.c index 05d1677a43d3..6597a15e5000 100644 --- a/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_jm.c +++ b/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_ktrace_jm.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -80,6 +80,9 @@ void kbasep_ktrace_add_jm(struct kbase_device *kbdev, unsigned long irqflags; struct kbase_ktrace_msg *trace_msg; + if (unlikely(!kbasep_ktrace_initialized(&kbdev->ktrace))) + return; + spin_lock_irqsave(&kbdev->ktrace.lock, irqflags); /* Reserve and update indices */ diff --git a/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_linux_ktrace_csf.h b/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_linux_ktrace_csf.h index 9ee7f8179336..86e81e510b47 100644 --- a/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_linux_ktrace_csf.h +++ b/drivers/gpu/arm/bifrost/debug/backend/mali_kbase_debug_linux_ktrace_csf.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -30,37 +30,36 @@ /* * Generic CSF events - using the common DEFINE_MALI_ADD_EVENT */ -DEFINE_MALI_ADD_EVENT(EVICT_CTX_SLOTS); -DEFINE_MALI_ADD_EVENT(FIRMWARE_BOOT); -DEFINE_MALI_ADD_EVENT(FIRMWARE_REBOOT); -DEFINE_MALI_ADD_EVENT(SCHEDULER_TOCK); +DEFINE_MALI_ADD_EVENT(SCHEDULER_EVICT_CTX_SLOTS_START); +DEFINE_MALI_ADD_EVENT(CSF_FIRMWARE_BOOT); +DEFINE_MALI_ADD_EVENT(CSF_FIRMWARE_REBOOT); +DEFINE_MALI_ADD_EVENT(SCHEDULER_TOCK_START); DEFINE_MALI_ADD_EVENT(SCHEDULER_TOCK_END); -DEFINE_MALI_ADD_EVENT(SCHEDULER_TICK); +DEFINE_MALI_ADD_EVENT(SCHEDULER_TICK_START); DEFINE_MALI_ADD_EVENT(SCHEDULER_TICK_END); -DEFINE_MALI_ADD_EVENT(SCHEDULER_RESET); -DEFINE_MALI_ADD_EVENT(SCHEDULER_WAIT_PROTM_QUIT); -DEFINE_MALI_ADD_EVENT(SCHEDULER_WAIT_PROTM_QUIT_DONE); -DEFINE_MALI_ADD_EVENT(SYNC_UPDATE_EVENT); -DEFINE_MALI_ADD_EVENT(SYNC_UPDATE_EVENT_NOTIFY_GPU); -DEFINE_MALI_ADD_EVENT(CSF_INTERRUPT); +DEFINE_MALI_ADD_EVENT(SCHEDULER_RESET_START); +DEFINE_MALI_ADD_EVENT(SCHEDULER_PROTM_WAIT_QUIT_START); +DEFINE_MALI_ADD_EVENT(SCHEDULER_PROTM_WAIT_QUIT_END); +DEFINE_MALI_ADD_EVENT(SCHEDULER_GROUP_SYNC_UPDATE_EVENT); +DEFINE_MALI_ADD_EVENT(CSF_SYNC_UPDATE_NOTIFY_GPU_EVENT); +DEFINE_MALI_ADD_EVENT(CSF_INTERRUPT_START); DEFINE_MALI_ADD_EVENT(CSF_INTERRUPT_END); -DEFINE_MALI_ADD_EVENT(CSG_INTERRUPT_PROCESS); -DEFINE_MALI_ADD_EVENT(GLB_REQ_ACQ); -DEFINE_MALI_ADD_EVENT(SCHEDULER_CAN_IDLE); -DEFINE_MALI_ADD_EVENT(SCHEDULER_ADVANCE_TICK); -DEFINE_MALI_ADD_EVENT(SCHEDULER_NOADVANCE_TICK); -DEFINE_MALI_ADD_EVENT(SCHEDULER_INSERT_RUNNABLE); -DEFINE_MALI_ADD_EVENT(SCHEDULER_REMOVE_RUNNABLE); -DEFINE_MALI_ADD_EVENT(SCHEDULER_ROTATE_RUNNABLE); -DEFINE_MALI_ADD_EVENT(SCHEDULER_HEAD_RUNNABLE); -DEFINE_MALI_ADD_EVENT(IDLE_WORKER_BEGIN); -DEFINE_MALI_ADD_EVENT(IDLE_WORKER_END); -DEFINE_MALI_ADD_EVENT(GROUP_SYNC_UPDATE_WORKER_BEGIN); -DEFINE_MALI_ADD_EVENT(GROUP_SYNC_UPDATE_WORKER_END); -DEFINE_MALI_ADD_EVENT(SLOTS_STATUS_UPDATE_ACK); -DEFINE_MALI_ADD_EVENT(GPU_IDLE_HANDLING_START); -DEFINE_MALI_ADD_EVENT(MCU_HALTED); -DEFINE_MALI_ADD_EVENT(MCU_IN_SLEEP); +DEFINE_MALI_ADD_EVENT(CSF_INTERRUPT_GLB_REQ_ACK); +DEFINE_MALI_ADD_EVENT(SCHEDULER_GPU_IDLE_EVENT_CAN_SUSPEND); +DEFINE_MALI_ADD_EVENT(SCHEDULER_TICK_ADVANCE); +DEFINE_MALI_ADD_EVENT(SCHEDULER_TICK_NOADVANCE); +DEFINE_MALI_ADD_EVENT(SCHEDULER_RUNNABLE_KCTX_INSERT); +DEFINE_MALI_ADD_EVENT(SCHEDULER_RUNNABLE_KCTX_REMOVE); +DEFINE_MALI_ADD_EVENT(SCHEDULER_RUNNABLE_KCTX_ROTATE); +DEFINE_MALI_ADD_EVENT(SCHEDULER_RUNNABLE_KCTX_HEAD); +DEFINE_MALI_ADD_EVENT(SCHEDULER_GPU_IDLE_WORKER_START); +DEFINE_MALI_ADD_EVENT(SCHEDULER_GPU_IDLE_WORKER_END); +DEFINE_MALI_ADD_EVENT(SCHEDULER_GROUP_SYNC_UPDATE_WORKER_START); +DEFINE_MALI_ADD_EVENT(SCHEDULER_GROUP_SYNC_UPDATE_WORKER_END); +DEFINE_MALI_ADD_EVENT(SCHEDULER_UPDATE_IDLE_SLOTS_ACK); +DEFINE_MALI_ADD_EVENT(SCHEDULER_GPU_IDLE_WORKER_HANDLING_START); +DEFINE_MALI_ADD_EVENT(CSF_FIRMWARE_MCU_HALTED); +DEFINE_MALI_ADD_EVENT(CSF_FIRMWARE_MCU_SLEEP); DECLARE_EVENT_CLASS(mali_csf_grp_q_template, TP_PROTO(struct kbase_device *kbdev, struct kbase_queue_group *group, @@ -130,37 +129,38 @@ DECLARE_EVENT_CLASS(mali_csf_grp_q_template, __entry->kctx_tgid, __entry->kctx_id, __entry->group_handle, \ __entry->csg_nr, __entry->slot_prio, __entry->info_val)) -DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_START); -DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_STOP); -DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_STARTED); +DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_START_REQ); +DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_STOP_REQ); +DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_RUNNING); DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_STOPPED); DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_CLEANED); -DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_STATUS_UPDATE); +DEFINE_MALI_CSF_GRP_EVENT(CSG_UPDATE_IDLE_SLOT_REQ); DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_IDLE_SET); DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_IDLE_CLEAR); -DEFINE_MALI_CSF_GRP_EVENT(CSG_PRIO_UPDATE); -DEFINE_MALI_CSF_GRP_EVENT(CSG_SYNC_UPDATE_INTERRUPT); -DEFINE_MALI_CSF_GRP_EVENT(CSG_IDLE_INTERRUPT); -DEFINE_MALI_CSF_GRP_EVENT(CSG_PROGRESS_TIMER_INTERRUPT); +DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_PRIO_UPDATE); +DEFINE_MALI_CSF_GRP_EVENT(CSG_INTERRUPT_SYNC_UPDATE); +DEFINE_MALI_CSF_GRP_EVENT(CSG_INTERRUPT_IDLE); +DEFINE_MALI_CSF_GRP_EVENT(CSG_INTERRUPT_PROGRESS_TIMER_EVENT); +DEFINE_MALI_CSF_GRP_EVENT(CSG_INTERRUPT_PROCESS_START); DEFINE_MALI_CSF_GRP_EVENT(CSG_INTERRUPT_PROCESS_END); DEFINE_MALI_CSF_GRP_EVENT(GROUP_SYNC_UPDATE_DONE); DEFINE_MALI_CSF_GRP_EVENT(GROUP_DESCHEDULE); DEFINE_MALI_CSF_GRP_EVENT(GROUP_SCHEDULE); -DEFINE_MALI_CSF_GRP_EVENT(GROUP_EVICT_SCHED); -DEFINE_MALI_CSF_GRP_EVENT(GROUP_INSERT_RUNNABLE); -DEFINE_MALI_CSF_GRP_EVENT(GROUP_REMOVE_RUNNABLE); -DEFINE_MALI_CSF_GRP_EVENT(GROUP_ROTATE_RUNNABLE); -DEFINE_MALI_CSF_GRP_EVENT(GROUP_HEAD_RUNNABLE); -DEFINE_MALI_CSF_GRP_EVENT(GROUP_INSERT_IDLE_WAIT); -DEFINE_MALI_CSF_GRP_EVENT(GROUP_REMOVE_IDLE_WAIT); -DEFINE_MALI_CSF_GRP_EVENT(GROUP_HEAD_IDLE_WAIT); -DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_CHECK_PROTM_ENTER); -DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_ENTER_PROTM); -DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_EXIT_PROTM); +DEFINE_MALI_CSF_GRP_EVENT(GROUP_EVICT); +DEFINE_MALI_CSF_GRP_EVENT(GROUP_RUNNABLE_INSERT); +DEFINE_MALI_CSF_GRP_EVENT(GROUP_RUNNABLE_REMOVE); +DEFINE_MALI_CSF_GRP_EVENT(GROUP_RUNNABLE_ROTATE); +DEFINE_MALI_CSF_GRP_EVENT(GROUP_RUNNABLE_HEAD); +DEFINE_MALI_CSF_GRP_EVENT(GROUP_IDLE_WAIT_INSERT); +DEFINE_MALI_CSF_GRP_EVENT(GROUP_IDLE_WAIT_REMOVE); +DEFINE_MALI_CSF_GRP_EVENT(GROUP_IDLE_WAIT_HEAD); +DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_PROTM_ENTER_CHECK); +DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_PROTM_ENTER); +DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_PROTM_EXIT); DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_TOP_GRP); -DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_NONIDLE_OFFSLOT_INC); -DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_NONIDLE_OFFSLOT_DEC); -DEFINE_MALI_CSF_GRP_EVENT(PROTM_EVENT_WORKER_BEGIN); +DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_NONIDLE_OFFSLOT_GRP_INC); +DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_NONIDLE_OFFSLOT_GRP_DEC); +DEFINE_MALI_CSF_GRP_EVENT(PROTM_EVENT_WORKER_START); DEFINE_MALI_CSF_GRP_EVENT(PROTM_EVENT_WORKER_END); #undef DEFINE_MALI_CSF_GRP_EVENT @@ -176,22 +176,22 @@ DEFINE_MALI_CSF_GRP_EVENT(PROTM_EVENT_WORKER_END); DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_START); DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_STOP); -DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_STOP_REQUESTED); -DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_IGNORED_INTERRUPTS_GROUP_SUSPEND); -DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_FAULT_INTERRUPT); -DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_TILER_OOM_INTERRUPT); -DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_PROTM_PEND_INTERRUPT); +DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_STOP_REQ); +DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_INTERRUPT_GROUP_SUSPENDS_IGNORED); +DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_INTERRUPT_FAULT); +DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_INTERRUPT_TILER_OOM); +DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_INTERRUPT_PROTM_PEND); DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_PROTM_ACK); DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_START); DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_STOP); -DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_UPDATE); -DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_UPDATE_EVALUATED); -DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_STATUS_WAIT); -DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_CURRENT_VAL); -DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_TEST_VAL); -DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_BLOCKED_REASON); -DEFINE_MALI_CSF_GRP_Q_EVENT(PROTM_PENDING_SET); -DEFINE_MALI_CSF_GRP_Q_EVENT(PROTM_PENDING_CLEAR); +DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_UPDATE_EVAL_START); +DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_UPDATE_EVAL_END); +DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_UPDATE_WAIT_STATUS); +DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_UPDATE_CUR_VAL); +DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_UPDATE_TEST_VAL); +DEFINE_MALI_CSF_GRP_Q_EVENT(QUEUE_SYNC_UPDATE_BLOCKED_REASON); +DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_PROTM_PEND_SET); +DEFINE_MALI_CSF_GRP_Q_EVENT(CSI_PROTM_PEND_CLEAR); #undef DEFINE_MALI_CSF_GRP_Q_EVENT @@ -230,14 +230,14 @@ DECLARE_EVENT_CLASS(mali_csf_kcpu_queue_template, u64 info_val1, u64 info_val2), \ TP_ARGS(queue, info_val1, info_val2)) -DEFINE_MALI_CSF_KCPU_EVENT(KCPU_QUEUE_NEW); -DEFINE_MALI_CSF_KCPU_EVENT(KCPU_QUEUE_DESTROY); -DEFINE_MALI_CSF_KCPU_EVENT(CQS_SET); -DEFINE_MALI_CSF_KCPU_EVENT(CQS_WAIT_START); -DEFINE_MALI_CSF_KCPU_EVENT(CQS_WAIT_END); -DEFINE_MALI_CSF_KCPU_EVENT(FENCE_SIGNAL); -DEFINE_MALI_CSF_KCPU_EVENT(FENCE_WAIT_START); -DEFINE_MALI_CSF_KCPU_EVENT(FENCE_WAIT_END); +DEFINE_MALI_CSF_KCPU_EVENT(KCPU_QUEUE_CREATE); +DEFINE_MALI_CSF_KCPU_EVENT(KCPU_QUEUE_DELETE); +DEFINE_MALI_CSF_KCPU_EVENT(KCPU_CQS_SET); +DEFINE_MALI_CSF_KCPU_EVENT(KCPU_CQS_WAIT_START); +DEFINE_MALI_CSF_KCPU_EVENT(KCPU_CQS_WAIT_END); +DEFINE_MALI_CSF_KCPU_EVENT(KCPU_FENCE_SIGNAL); +DEFINE_MALI_CSF_KCPU_EVENT(KCPU_FENCE_WAIT_START); +DEFINE_MALI_CSF_KCPU_EVENT(KCPU_FENCE_WAIT_END); #undef DEFINE_MALI_CSF_KCPU_EVENT diff --git a/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace.c b/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace.c index 9bf86108338f..f521b47120fb 100644 --- a/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace.c +++ b/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -27,13 +27,13 @@ int kbase_ktrace_init(struct kbase_device *kbdev) #if KBASE_KTRACE_TARGET_RBUF struct kbase_ktrace_msg *rbuf; + spin_lock_init(&kbdev->ktrace.lock); rbuf = kmalloc_array(KBASE_KTRACE_SIZE, sizeof(*rbuf), GFP_KERNEL); if (!rbuf) return -EINVAL; kbdev->ktrace.rbuf = rbuf; - spin_lock_init(&kbdev->ktrace.lock); #endif /* KBASE_KTRACE_TARGET_RBUF */ return 0; } @@ -42,6 +42,7 @@ void kbase_ktrace_term(struct kbase_device *kbdev) { #if KBASE_KTRACE_TARGET_RBUF kfree(kbdev->ktrace.rbuf); + kbdev->ktrace.rbuf = NULL; #endif /* KBASE_KTRACE_TARGET_RBUF */ } @@ -183,6 +184,9 @@ void kbasep_ktrace_add(struct kbase_device *kbdev, enum kbase_ktrace_code code, unsigned long irqflags; struct kbase_ktrace_msg *trace_msg; + if (unlikely(!kbasep_ktrace_initialized(&kbdev->ktrace))) + return; + WARN_ON((flags & ~KBASE_KTRACE_FLAG_COMMON_ALL)); spin_lock_irqsave(&kbdev->ktrace.lock, irqflags); diff --git a/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace.h b/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace.h index cc4bfc075792..11f0b5c42c89 100644 --- a/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace.h +++ b/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -81,6 +81,18 @@ void kbase_ktrace_debugfs_init(struct kbase_device *kbdev); * KTrace target for internal ringbuffer */ #if KBASE_KTRACE_TARGET_RBUF +/** + * kbasep_ktrace_initialized - Check whether kbase ktrace is initialized + * + * @ktrace: ktrace of kbase device. + * + * Return: true if ktrace has been initialized. + */ +static inline bool kbasep_ktrace_initialized(struct kbase_ktrace *ktrace) +{ + return ktrace->rbuf != NULL; +} + /** * kbasep_ktrace_add - internal function to add trace to the ringbuffer. * @kbdev: kbase device diff --git a/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_csf.c b/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_csf.c index 5602ff5409b0..1e84f6b2644d 100644 --- a/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_csf.c +++ b/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_csf.c @@ -315,10 +315,10 @@ static const struct kbase_device_init dev_init[] = { "GPU hwcnt backend creation failed" }, { kbase_device_hwcnt_context_init, kbase_device_hwcnt_context_term, "GPU hwcnt context initialization failed" }, - { kbase_backend_late_init, kbase_backend_late_term, - "Late backend initialization failed" }, { kbase_csf_early_init, kbase_csf_early_term, "Early CSF initialization failed" }, + { kbase_backend_late_init, kbase_backend_late_term, + "Late backend initialization failed" }, { NULL, kbase_device_firmware_hwcnt_term, NULL }, { kbase_device_debugfs_init, kbase_device_debugfs_term, "DebugFS initialization failed" }, diff --git a/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_hw_jm.c b/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_hw_jm.c index d1e978845431..52063fb0f533 100644 --- a/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_hw_jm.c +++ b/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_hw_jm.c @@ -109,8 +109,7 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val) #if !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) void kbase_reg_write(struct kbase_device *kbdev, u32 offset, u32 value) { - KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_powered); - KBASE_DEBUG_ASSERT(kbdev->dev != NULL); + WARN_ON(!kbdev->pm.backend.gpu_powered); writel(value, kbdev->reg + offset); @@ -127,8 +126,7 @@ u32 kbase_reg_read(struct kbase_device *kbdev, u32 offset) { u32 val; - KBASE_DEBUG_ASSERT(kbdev->pm.backend.gpu_powered); - KBASE_DEBUG_ASSERT(kbdev->dev != NULL); + WARN_ON(!kbdev->pm.backend.gpu_powered); val = readl(kbdev->reg + offset); diff --git a/drivers/gpu/arm/bifrost/device/mali_kbase_device.c b/drivers/gpu/arm/bifrost/device/mali_kbase_device.c index d923b18f30ba..7004e347fa1b 100644 --- a/drivers/gpu/arm/bifrost/device/mali_kbase_device.c +++ b/drivers/gpu/arm/bifrost/device/mali_kbase_device.c @@ -291,12 +291,9 @@ int kbase_device_misc_init(struct kbase_device * const kbdev) if (err) goto dma_set_mask_failed; - err = kbase_ktrace_init(kbdev); - if (err) - goto term_as; err = kbase_pbha_read_dtb(kbdev); if (err) - goto term_ktrace; + goto term_as; init_waitqueue_head(&kbdev->cache_clean_wait); @@ -335,8 +332,6 @@ int kbase_device_misc_init(struct kbase_device * const kbdev) return 0; -term_ktrace: - kbase_ktrace_term(kbdev); term_as: kbase_device_all_as_term(kbdev); dma_set_mask_failed: @@ -353,9 +348,6 @@ void kbase_device_misc_term(struct kbase_device *kbdev) #if KBASE_KTRACE_ENABLE kbase_debug_assert_register_hook(NULL, NULL); #endif - - kbase_ktrace_term(kbdev); - kbase_device_all_as_term(kbdev); @@ -522,10 +514,14 @@ int kbase_device_early_init(struct kbase_device *kbdev) { int err; + err = kbase_ktrace_init(kbdev); + if (err) + return err; + err = kbasep_platform_device_init(kbdev); if (err) - return err; + goto ktrace_term; err = kbase_pm_runtime_init(kbdev); if (err) @@ -539,7 +535,12 @@ int kbase_device_early_init(struct kbase_device *kbdev) /* Ensure we can access the GPU registers */ kbase_pm_register_access_enable(kbdev); - /* Find out GPU properties based on the GPU feature registers */ + /* + * Find out GPU properties based on the GPU feature registers. + * Note that this does not populate the few properties that depend on + * hw_features being initialized. Those are set by kbase_gpuprops_set_features + * soon after this in the init process. + */ kbase_gpuprops_set(kbdev); /* We're done accessing the GPU registers for now. */ @@ -562,6 +563,8 @@ fail_interrupts: kbase_pm_runtime_term(kbdev); fail_runtime_pm: kbasep_platform_device_term(kbdev); +ktrace_term: + kbase_ktrace_term(kbdev); return err; } @@ -578,6 +581,7 @@ void kbase_device_early_term(struct kbase_device *kbdev) #endif /* CONFIG_MALI_ARBITER_SUPPORT */ kbase_pm_runtime_term(kbdev); kbasep_platform_device_term(kbdev); + kbase_ktrace_term(kbdev); } int kbase_device_late_init(struct kbase_device *kbdev) diff --git a/drivers/gpu/arm/bifrost/device/mali_kbase_device.h b/drivers/gpu/arm/bifrost/device/mali_kbase_device.h index afd195cf3a3f..6706a61d5baa 100644 --- a/drivers/gpu/arm/bifrost/device/mali_kbase_device.h +++ b/drivers/gpu/arm/bifrost/device/mali_kbase_device.h @@ -115,6 +115,22 @@ u32 kbase_reg_read(struct kbase_device *kbdev, u32 offset); */ bool kbase_is_gpu_removed(struct kbase_device *kbdev); +/** + * kbase_gpu_cache_flush_pa_range_and_busy_wait() - Start a cache physical range flush + * and busy wait + * + * @kbdev: kbase device to issue the MMU operation on. + * @phys: Starting address of the physical range to start the operation on. + * @nr_bytes: Number of bytes to work on. + * @flush_op: Flush command register value to be sent to HW + * + * Issue a cache flush physical range command, then busy wait an irq status. + * This function will clear FLUSH_PA_RANGE_COMPLETED irq mask bit + * and busy-wait the rawstat register. + * + * Return: 0 if successful or a negative error code on failure. + */ +#define kbase_gpu_cache_flush_pa_range_and_busy_wait(kbdev, phys, nr_bytes, flush_op) (0) /** * kbase_gpu_cache_flush_and_busy_wait - Start a cache flush and busy wait * @kbdev: Kbase device @@ -188,7 +204,7 @@ int kbase_gpu_wait_cache_clean_timeout(struct kbase_device *kbdev, void kbase_gpu_cache_clean_wait_complete(struct kbase_device *kbdev); /** - * kbase_clean_caches_done - Issue preiously queued cache clean request or + * kbase_clean_caches_done - Issue previously queued cache clean request or * wake up the requester that issued cache clean. * @kbdev: Kbase device * diff --git a/drivers/gpu/arm/bifrost/device/mali_kbase_device_hw.c b/drivers/gpu/arm/bifrost/device/mali_kbase_device_hw.c index 6096bcc186e4..4bd545a82299 100644 --- a/drivers/gpu/arm/bifrost/device/mali_kbase_device_hw.c +++ b/drivers/gpu/arm/bifrost/device/mali_kbase_device_hw.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2014-2016, 2018-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2016, 2018-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -27,6 +27,9 @@ #include #include +#define U64_LO_MASK ((1ULL << 32) - 1) +#define U64_HI_MASK (~U64_LO_MASK) + #if !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) bool kbase_is_gpu_removed(struct kbase_device *kbdev) { @@ -38,8 +41,9 @@ bool kbase_is_gpu_removed(struct kbase_device *kbdev) } #endif /* !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) */ -static int busy_wait_cache_clean_irq(struct kbase_device *kbdev) +static int busy_wait_on_irq(struct kbase_device *kbdev, u32 irq_bit) { + char *irq_flag_name; /* Previously MMU-AS command was used for L2 cache flush on page-table update. * And we're using the same max-loops count for GPU command, because amount of * L2 cache flush overhead are same between them. @@ -48,28 +52,42 @@ static int busy_wait_cache_clean_irq(struct kbase_device *kbdev) /* Wait for the GPU cache clean operation to complete */ while (--max_loops && - !(kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT)) & - CLEAN_CACHES_COMPLETED)) { + !(kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_RAWSTAT)) & irq_bit)) { ; } /* reset gpu if time-out occurred */ if (max_loops == 0) { + switch (irq_bit) { + case CLEAN_CACHES_COMPLETED: + irq_flag_name = "CLEAN_CACHES_COMPLETED"; + break; + case FLUSH_PA_RANGE_COMPLETED: + irq_flag_name = "FLUSH_PA_RANGE_COMPLETED"; + break; + default: + irq_flag_name = "UNKNOWN"; + break; + } + dev_err(kbdev->dev, - "CLEAN_CACHES_COMPLETED bit stuck, might be caused by slow/unstable GPU clock or possible faulty FPGA connector\n"); + "Stuck waiting on %s bit, might be caused by slow/unstable GPU clock or possible faulty FPGA connector\n", + irq_flag_name); + if (kbase_prepare_to_reset_gpu_locked(kbdev, RESET_FLAGS_NONE)) kbase_reset_gpu_locked(kbdev); return -EBUSY; } - /* Clear the interrupt CLEAN_CACHES_COMPLETED bit. */ - KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, CLEAN_CACHES_COMPLETED); - kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), - CLEAN_CACHES_COMPLETED); + /* Clear the interrupt bit. */ + KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, irq_bit); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), irq_bit); return 0; } +#define kbase_gpu_cache_flush_pa_range_and_busy_wait(kbdev, phys, nr_bytes, flush_op) (0) + int kbase_gpu_cache_flush_and_busy_wait(struct kbase_device *kbdev, u32 flush_op) { @@ -97,7 +115,7 @@ int kbase_gpu_cache_flush_and_busy_wait(struct kbase_device *kbdev, irq_mask & ~CLEAN_CACHES_COMPLETED); /* busy wait irq status to be enabled */ - ret = busy_wait_cache_clean_irq(kbdev); + ret = busy_wait_on_irq(kbdev, (u32)CLEAN_CACHES_COMPLETED); if (ret) return ret; @@ -118,7 +136,7 @@ int kbase_gpu_cache_flush_and_busy_wait(struct kbase_device *kbdev, kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), flush_op); /* 3. Busy-wait irq status to be enabled. */ - ret = busy_wait_cache_clean_irq(kbdev); + ret = busy_wait_on_irq(kbdev, (u32)CLEAN_CACHES_COMPLETED); if (ret) return ret; diff --git a/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_csf.h b/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_csf.h index d1c6b39eca28..06c725c0e757 100644 --- a/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_csf.h +++ b/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_csf.h @@ -138,6 +138,7 @@ #define GPU_COMMAND_CODE_SET_PROTECTED_MODE 0x05 /* Places the GPU in protected mode */ #define GPU_COMMAND_CODE_FINISH_HALT 0x06 /* Halt CSF */ #define GPU_COMMAND_CODE_CLEAR_FAULT 0x07 /* Clear GPU_FAULTSTATUS and GPU_FAULTADDRESS, TODX */ +#define GPU_COMMAND_CODE_FLUSH_PA_RANGE 0x08 /* Flush the GPU caches for a physical range, TITX */ /* GPU_COMMAND_RESET payloads */ @@ -161,18 +162,29 @@ #define GPU_COMMAND_TIME_ENABLE 0x01 /* Enable cycle counter */ /* GPU_COMMAND_FLUSH_CACHES payloads bits for L2 caches */ -#define GPU_COMMAND_FLUSH_PAYLOAD_L2_NONE 0x000 /* No flush */ -#define GPU_COMMAND_FLUSH_PAYLOAD_L2_CLEAN 0x001 /* CLN only */ -#define GPU_COMMAND_FLUSH_PAYLOAD_L2_CLEAN_INVALIDATE 0x003 /* CLN + INV */ +#define GPU_COMMAND_FLUSH_CACHES_PAYLOAD_L2_NONE 0x000 /* No flush */ +#define GPU_COMMAND_FLUSH_CACHES_PAYLOAD_L2_CLEAN 0x001 /* CLN only */ +#define GPU_COMMAND_FLUSH_CACHES_PAYLOAD_L2_CLEAN_INVALIDATE 0x003 /* CLN + INV */ /* GPU_COMMAND_FLUSH_CACHES payloads bits for Load-store caches */ -#define GPU_COMMAND_FLUSH_PAYLOAD_LSC_NONE 0x000 /* No flush */ -#define GPU_COMMAND_FLUSH_PAYLOAD_LSC_CLEAN 0x010 /* CLN only */ -#define GPU_COMMAND_FLUSH_PAYLOAD_LSC_CLEAN_INVALIDATE 0x030 /* CLN + INV */ +#define GPU_COMMAND_FLUSH_CACHES_PAYLOAD_LSC_NONE 0x000 /* No flush */ +#define GPU_COMMAND_FLUSH_CACHES_PAYLOAD_LSC_CLEAN 0x010 /* CLN only */ +#define GPU_COMMAND_FLUSH_CACHES_PAYLOAD_LSC_CLEAN_INVALIDATE 0x030 /* CLN + INV */ /* GPU_COMMAND_FLUSH_CACHES payloads bits for Other caches */ -#define GPU_COMMAND_FLUSH_PAYLOAD_OTHER_NONE 0x000 /* No flush */ -#define GPU_COMMAND_FLUSH_PAYLOAD_OTHER_INVALIDATE 0x200 /* INV only */ +#define GPU_COMMAND_FLUSH_CACHES_PAYLOAD_OTHER_NONE 0x000 /* No flush */ +#define GPU_COMMAND_FLUSH_CACHES_PAYLOAD_OTHER_INVALIDATE 0x200 /* INV only */ + +/* GPU_COMMAND_FLUSH_PA_RANGE payload bits for flush modes */ +#define GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_MODE_NONE 0x00 /* No flush */ +#define GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_MODE_CLEAN 0x01 /* CLN only */ +#define GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_MODE_INVALIDATE 0x02 /* INV only */ +#define GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_MODE_CLEAN_INVALIDATE 0x03 /* CLN + INV */ + +/* GPU_COMMAND_FLUSH_PA_RANGE payload bits for which caches should be the target of the command */ +#define GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_OTHER_CACHE 0x10 /* Other caches */ +#define GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_LSC_CACHE 0x20 /* Load-store caches */ +#define GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_L2_CACHE 0x40 /* L2 caches */ /* GPU_COMMAND command + payload */ #define GPU_COMMAND_CODE_PAYLOAD(opcode, payload) \ @@ -200,28 +212,53 @@ GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_TIME, GPU_COMMAND_TIME_DISABLE) /* Clean and invalidate L2 cache (Equivalent to FLUSH_PT) */ -#define GPU_COMMAND_CACHE_CLN_INV_L2 \ - GPU_COMMAND_CODE_PAYLOAD( \ - GPU_COMMAND_CODE_FLUSH_CACHES, \ - (GPU_COMMAND_FLUSH_PAYLOAD_L2_CLEAN_INVALIDATE | \ - GPU_COMMAND_FLUSH_PAYLOAD_LSC_NONE | \ - GPU_COMMAND_FLUSH_PAYLOAD_OTHER_NONE)) +#define GPU_COMMAND_CACHE_CLN_INV_L2 \ + GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_FLUSH_CACHES, \ + (GPU_COMMAND_FLUSH_CACHES_PAYLOAD_L2_CLEAN_INVALIDATE | \ + GPU_COMMAND_FLUSH_CACHES_PAYLOAD_LSC_NONE | \ + GPU_COMMAND_FLUSH_CACHES_PAYLOAD_OTHER_NONE)) /* Clean and invalidate L2 and LSC caches (Equivalent to FLUSH_MEM) */ -#define GPU_COMMAND_CACHE_CLN_INV_L2_LSC \ - GPU_COMMAND_CODE_PAYLOAD( \ - GPU_COMMAND_CODE_FLUSH_CACHES, \ - (GPU_COMMAND_FLUSH_PAYLOAD_L2_CLEAN_INVALIDATE | \ - GPU_COMMAND_FLUSH_PAYLOAD_LSC_CLEAN_INVALIDATE | \ - GPU_COMMAND_FLUSH_PAYLOAD_OTHER_NONE)) +#define GPU_COMMAND_CACHE_CLN_INV_L2_LSC \ + GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_FLUSH_CACHES, \ + (GPU_COMMAND_FLUSH_CACHES_PAYLOAD_L2_CLEAN_INVALIDATE | \ + GPU_COMMAND_FLUSH_CACHES_PAYLOAD_LSC_CLEAN_INVALIDATE | \ + GPU_COMMAND_FLUSH_CACHES_PAYLOAD_OTHER_NONE)) /* Clean and invalidate L2, LSC, and Other caches */ -#define GPU_COMMAND_CACHE_CLN_INV_FULL \ - GPU_COMMAND_CODE_PAYLOAD( \ - GPU_COMMAND_CODE_FLUSH_CACHES, \ - (GPU_COMMAND_FLUSH_PAYLOAD_L2_CLEAN_INVALIDATE | \ - GPU_COMMAND_FLUSH_PAYLOAD_LSC_CLEAN_INVALIDATE | \ - GPU_COMMAND_FLUSH_PAYLOAD_OTHER_INVALIDATE)) +#define GPU_COMMAND_CACHE_CLN_INV_FULL \ + GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_FLUSH_CACHES, \ + (GPU_COMMAND_FLUSH_CACHES_PAYLOAD_L2_CLEAN_INVALIDATE | \ + GPU_COMMAND_FLUSH_CACHES_PAYLOAD_LSC_CLEAN_INVALIDATE | \ + GPU_COMMAND_FLUSH_CACHES_PAYLOAD_OTHER_INVALIDATE)) + +/* Clean and invalidate only LSC cache */ +#define GPU_COMMAND_CACHE_CLN_INV_LSC \ + GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_FLUSH_CACHES, \ + (GPU_COMMAND_FLUSH_CACHES_PAYLOAD_L2_NONE | \ + GPU_COMMAND_FLUSH_CACHES_PAYLOAD_LSC_CLEAN_INVALIDATE | \ + GPU_COMMAND_FLUSH_CACHES_PAYLOAD_OTHER_NONE)) + +/* Clean and invalidate physical range L2 cache (equivalent to FLUSH_PT) */ +#define GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_L2 \ + GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_FLUSH_PA_RANGE, \ + (GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_MODE_CLEAN_INVALIDATE | \ + GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_L2_CACHE)) + +/* Clean and invalidate physical range L2 and LSC cache (equivalent to FLUSH_MEM) */ +#define GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_L2_LSC \ + GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_FLUSH_PA_RANGE, \ + (GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_MODE_CLEAN_INVALIDATE | \ + GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_LSC_CACHE | \ + GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_L2_CACHE)) + +/* Clean and invalidate physical range L2, LSC and Other caches */ +#define GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_FULL \ + GPU_COMMAND_CODE_PAYLOAD(GPU_COMMAND_CODE_FLUSH_PA_RANGE, \ + (GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_MODE_CLEAN_INVALIDATE | \ + GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_OTHER_CACHE | \ + GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_LSC_CACHE | \ + GPU_COMMAND_FLUSH_PA_RANGE_PAYLOAD_L2_CACHE)) /* Merge cache flush commands */ #define GPU_COMMAND_FLUSH_CACHE_MERGE(cmd1, cmd2) ((cmd1) | (cmd2)) @@ -302,14 +339,16 @@ (((value) << GPU_FAULTSTATUS_ADDRESS_VALID_SHIFT) & GPU_FAULTSTATUS_ADDRESS_VALID_MASK)) /* IRQ flags */ -#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */ -#define GPU_PROTECTED_FAULT (1 << 1) /* A GPU fault has occurred in protected mode */ -#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. */ -#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */ -#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down. */ -#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */ -#define DOORBELL_MIRROR (1 << 18) /* Mirrors the doorbell interrupt line to the CPU */ -#define MCU_STATUS_GPU_IRQ (1 << 19) /* MCU requires attention */ +#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */ +#define GPU_PROTECTED_FAULT (1 << 1) /* A GPU fault has occurred in protected mode */ +#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. */ +#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */ +#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down. */ +#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */ +#define DOORBELL_MIRROR (1 << 18) /* Mirrors the doorbell interrupt line to the CPU */ +#define MCU_STATUS_GPU_IRQ (1 << 19) /* MCU requires attention */ +#define FLUSH_PA_RANGE_COMPLETED \ + (1 << 20) /* Set when a physical range cache clean operation has completed. */ /* * In Debug build, diff --git a/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_jm.h b/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_jm.h index d1cd8fc7d048..c349f4b058cd 100644 --- a/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_jm.h +++ b/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_jm.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2019-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -262,19 +262,22 @@ #define GPU_COMMAND_CACHE_CLN_INV_L2 GPU_COMMAND_CLEAN_INV_CACHES #define GPU_COMMAND_CACHE_CLN_INV_L2_LSC GPU_COMMAND_CLEAN_INV_CACHES #define GPU_COMMAND_CACHE_CLN_INV_FULL GPU_COMMAND_CLEAN_INV_CACHES +#define GPU_COMMAND_CACHE_CLN_INV_LSC GPU_COMMAND_CLEAN_INV_CACHES /* Merge cache flush commands */ #define GPU_COMMAND_FLUSH_CACHE_MERGE(cmd1, cmd2) \ ((cmd1) > (cmd2) ? (cmd1) : (cmd2)) /* IRQ flags */ -#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */ -#define MULTIPLE_GPU_FAULTS (1 << 7) /* More than one GPU Fault occurred. */ -#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. */ -#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */ -#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down. */ -#define PRFCNT_SAMPLE_COMPLETED (1 << 16) /* Set when a performance count sample has completed. */ -#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */ +#define GPU_FAULT (1 << 0) /* A GPU Fault has occurred */ +#define MULTIPLE_GPU_FAULTS (1 << 7) /* More than one GPU Fault occurred. */ +#define RESET_COMPLETED (1 << 8) /* Set when a reset has completed. */ +#define POWER_CHANGED_SINGLE (1 << 9) /* Set when a single core has finished powering up or down. */ +#define POWER_CHANGED_ALL (1 << 10) /* Set when all cores have finished powering up or down. */ +#define PRFCNT_SAMPLE_COMPLETED (1 << 16) /* Set when a performance count sample has completed. */ +#define CLEAN_CACHES_COMPLETED (1 << 17) /* Set when a cache clean operation has completed. */ +#define FLUSH_PA_RANGE_COMPLETED \ + (1 << 20) /* Set when a physical range cache clean operation has completed. */ /* * In Debug build, diff --git a/drivers/gpu/arm/bifrost/gpu/mali_kbase_gpu_regmap.h b/drivers/gpu/arm/bifrost/gpu/mali_kbase_gpu_regmap.h index b6033fea6440..396ebd5e21c9 100644 --- a/drivers/gpu/arm/bifrost/gpu/mali_kbase_gpu_regmap.h +++ b/drivers/gpu/arm/bifrost/gpu/mali_kbase_gpu_regmap.h @@ -100,6 +100,7 @@ #define TEXTURE_FEATURES_REG(n) GPU_CONTROL_REG(TEXTURE_FEATURES_0 + ((n) << 2)) + #define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */ #define SHADER_PRESENT_HI 0x104 /* (RO) Shader core present bitmap, high word */ @@ -368,6 +369,11 @@ (((reg_val) & ~AS_LOCKADDR_LOCKADDR_BASE_MASK) | \ (((value) << AS_LOCKADDR_LOCKADDR_BASE_SHIFT) & \ AS_LOCKADDR_LOCKADDR_BASE_MASK)) +#define AS_LOCKADDR_FLUSH_SKIP_LEVELS_SHIFT (6) +#define AS_LOCKADDR_FLUSH_SKIP_LEVELS_MASK ((0xF) << AS_LOCKADDR_FLUSH_SKIP_LEVELS_SHIFT) +#define AS_LOCKADDR_FLUSH_SKIP_LEVELS_SET(reg_val, value) \ + (((reg_val) & ~AS_LOCKADDR_FLUSH_SKIP_LEVELS_MASK) | \ + ((value << AS_LOCKADDR_FLUSH_SKIP_LEVELS_SHIFT) & AS_LOCKADDR_FLUSH_SKIP_LEVELS_MASK)) /* GPU_STATUS values */ #define GPU_STATUS_PRFCNT_ACTIVE (1 << 2) /* Set if the performance counters are active. */ diff --git a/drivers/gpu/arm/bifrost/jm/mali_kbase_jm_defs.h b/drivers/gpu/arm/bifrost/jm/mali_kbase_jm_defs.h index a7103ecea4b5..f9e0099a5cbf 100644 --- a/drivers/gpu/arm/bifrost/jm/mali_kbase_jm_defs.h +++ b/drivers/gpu/arm/bifrost/jm/mali_kbase_jm_defs.h @@ -186,8 +186,6 @@ struct kbase_jd_atom_dependency { static inline const struct kbase_jd_atom * kbase_jd_katom_dep_atom(const struct kbase_jd_atom_dependency *dep) { - KBASE_DEBUG_ASSERT(dep != NULL); - return (const struct kbase_jd_atom *)(dep->atom); } @@ -201,8 +199,6 @@ kbase_jd_katom_dep_atom(const struct kbase_jd_atom_dependency *dep) static inline u8 kbase_jd_katom_dep_type( const struct kbase_jd_atom_dependency *dep) { - KBASE_DEBUG_ASSERT(dep != NULL); - return dep->dep_type; } @@ -219,8 +215,6 @@ static inline void kbase_jd_katom_dep_set( { struct kbase_jd_atom_dependency *dep; - KBASE_DEBUG_ASSERT(const_dep != NULL); - dep = (struct kbase_jd_atom_dependency *)const_dep; dep->atom = a; @@ -237,8 +231,6 @@ static inline void kbase_jd_katom_dep_clear( { struct kbase_jd_atom_dependency *dep; - KBASE_DEBUG_ASSERT(const_dep != NULL); - dep = (struct kbase_jd_atom_dependency *)const_dep; dep->atom = NULL; @@ -508,7 +500,6 @@ struct kbase_ext_res { * BASE_JD_REQ_START_RENDERPASS set in its core requirements * with an atom that has BASE_JD_REQ_END_RENDERPASS set. * @jc_fragment: Set of GPU fragment job chains - * @retry_count: TODO: Not used,to be removed */ struct kbase_jd_atom { struct work_struct work; @@ -619,8 +610,6 @@ struct kbase_jd_atom { u32 atom_flags; - int retry_count; - enum kbase_atom_gpu_rb_state gpu_rb_state; bool need_cache_flush_cores_retained; diff --git a/drivers/gpu/arm/bifrost/jm/mali_kbase_jm_js.h b/drivers/gpu/arm/bifrost/jm/mali_kbase_jm_js.h index f5d4084fe4fb..d03bcc0f27d8 100644 --- a/drivers/gpu/arm/bifrost/jm/mali_kbase_jm_js.h +++ b/drivers/gpu/arm/bifrost/jm/mali_kbase_jm_js.h @@ -29,6 +29,8 @@ #include "mali_kbase_js_ctx_attr.h" +#define JS_MAX_RUNNING_JOBS 8 + /** * kbasep_js_devdata_init - Initialize the Job Scheduler * @kbdev: The kbase_device to operate on @@ -705,8 +707,10 @@ static inline bool kbasep_js_is_submit_allowed( bool is_allowed; /* Ensure context really is scheduled in */ - KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); - KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + if (WARN((kctx->as_nr == KBASEP_AS_NR_INVALID) || !kbase_ctx_flag(kctx, KCTX_SCHEDULED), + "%s: kctx %pK has assigned AS %d and context flag %d\n", __func__, (void *)kctx, + kctx->as_nr, atomic_read(&kctx->flags))) + return false; test_bit = (u16) (1u << kctx->as_nr); @@ -733,8 +737,10 @@ static inline void kbasep_js_set_submit_allowed( u16 set_bit; /* Ensure context really is scheduled in */ - KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); - KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + if (WARN((kctx->as_nr == KBASEP_AS_NR_INVALID) || !kbase_ctx_flag(kctx, KCTX_SCHEDULED), + "%s: kctx %pK has assigned AS %d and context flag %d\n", __func__, (void *)kctx, + kctx->as_nr, atomic_read(&kctx->flags))) + return; set_bit = (u16) (1u << kctx->as_nr); @@ -763,8 +769,10 @@ static inline void kbasep_js_clear_submit_allowed( u16 clear_mask; /* Ensure context really is scheduled in */ - KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); - KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); + if (WARN((kctx->as_nr == KBASEP_AS_NR_INVALID) || !kbase_ctx_flag(kctx, KCTX_SCHEDULED), + "%s: kctx %pK has assigned AS %d and context flag %d\n", __func__, (void *)kctx, + kctx->as_nr, atomic_read(&kctx->flags))) + return; clear_bit = (u16) (1u << kctx->as_nr); clear_mask = ~clear_bit; @@ -798,7 +806,7 @@ static inline void kbasep_js_atom_retained_state_init_invalid( * @retained_state: where to copy * @katom: where to copy from * - * Copy atom state that can be made available after jd_done_nolock() is called + * Copy atom state that can be made available after kbase_jd_done_nolock() is called * on that atom. */ static inline void kbasep_js_atom_retained_state_copy( @@ -872,9 +880,6 @@ static inline void kbase_js_runpool_inc_context_count( struct kbasep_js_device_data *js_devdata; struct kbasep_js_kctx_info *js_kctx_info; - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - js_devdata = &kbdev->js_data; js_kctx_info = &kctx->jctx.sched_info; @@ -882,13 +887,12 @@ static inline void kbase_js_runpool_inc_context_count( lockdep_assert_held(&js_devdata->runpool_mutex); /* Track total contexts */ - KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running < S8_MAX); + WARN_ON_ONCE(js_devdata->nr_all_contexts_running >= JS_MAX_RUNNING_JOBS); ++(js_devdata->nr_all_contexts_running); if (!kbase_ctx_flag(kctx, KCTX_SUBMIT_DISABLED)) { /* Track contexts that can submit jobs */ - KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running < - S8_MAX); + WARN_ON_ONCE(js_devdata->nr_user_contexts_running >= JS_MAX_RUNNING_JOBS); ++(js_devdata->nr_user_contexts_running); } } @@ -909,9 +913,6 @@ static inline void kbase_js_runpool_dec_context_count( struct kbasep_js_device_data *js_devdata; struct kbasep_js_kctx_info *js_kctx_info; - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - js_devdata = &kbdev->js_data; js_kctx_info = &kctx->jctx.sched_info; @@ -920,12 +921,12 @@ static inline void kbase_js_runpool_dec_context_count( /* Track total contexts */ --(js_devdata->nr_all_contexts_running); - KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running >= 0); + WARN_ON_ONCE(js_devdata->nr_all_contexts_running < 0); if (!kbase_ctx_flag(kctx, KCTX_SUBMIT_DISABLED)) { /* Track contexts that can submit jobs */ --(js_devdata->nr_user_contexts_running); - KBASE_DEBUG_ASSERT(js_devdata->nr_user_contexts_running >= 0); + WARN_ON_ONCE(js_devdata->nr_user_contexts_running < 0); } } @@ -950,8 +951,8 @@ extern const base_jd_prio kbasep_js_relative_priority_to_atom[KBASE_JS_ATOM_SCHED_PRIO_COUNT]; /** - * kbasep_js_atom_prio_to_sched_prio(): - Convert atom priority (base_jd_prio) - * to relative ordering + * kbasep_js_atom_prio_to_sched_prio - Convert atom priority (base_jd_prio) + * to relative ordering. * @atom_prio: Priority ID to translate. * * Atom priority values for @ref base_jd_prio cannot be compared directly to @@ -980,16 +981,33 @@ static inline int kbasep_js_atom_prio_to_sched_prio(base_jd_prio atom_prio) return kbasep_js_atom_priority_to_relative[atom_prio]; } -static inline base_jd_prio kbasep_js_sched_prio_to_atom_prio(int sched_prio) +/** + * kbasep_js_sched_prio_to_atom_prio - Convert relative scheduler priority + * to atom priority (base_jd_prio). + * + * @kbdev: Device pointer + * @sched_prio: Relative scheduler priority to translate. + * + * This function will convert relative scheduler priority back into base_jd_prio + * values. It takes values which priorities are monotonically increasing + * and converts them to the corresponding base_jd_prio values. If an invalid number is + * passed in (i.e. not within the expected range) an error code is returned instead. + * + * The mapping is 1:1 and the size of the valid input range is the same as the + * size of the valid output range, i.e. + * KBASE_JS_ATOM_SCHED_PRIO_COUNT == BASE_JD_NR_PRIO_LEVELS + * + * Return: On success: a value in the inclusive range + * 0..BASE_JD_NR_PRIO_LEVELS-1. On failure: BASE_JD_PRIO_INVALID. + */ +static inline base_jd_prio kbasep_js_sched_prio_to_atom_prio(struct kbase_device *kbdev, + int sched_prio) { - unsigned int prio_idx; - - KBASE_DEBUG_ASSERT(sched_prio >= 0 && - sched_prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT); - - prio_idx = (unsigned int)sched_prio; - - return kbasep_js_relative_priority_to_atom[prio_idx]; + if (likely(sched_prio >= 0 && sched_prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT)) + return kbasep_js_relative_priority_to_atom[sched_prio]; + /* Invalid priority value if reached here */ + dev_warn(kbdev->dev, "Unknown JS scheduling priority %d", sched_prio); + return BASE_JD_PRIO_INVALID; } /** diff --git a/drivers/gpu/arm/bifrost/jm/mali_kbase_js_defs.h b/drivers/gpu/arm/bifrost/jm/mali_kbase_js_defs.h index 998fde6f7e52..3d91efdf9d72 100644 --- a/drivers/gpu/arm/bifrost/jm/mali_kbase_js_defs.h +++ b/drivers/gpu/arm/bifrost/jm/mali_kbase_js_defs.h @@ -387,7 +387,7 @@ struct kbasep_js_kctx_info { * @sched_priority: priority * @device_nr: Core group atom was executed on * - * Subset of atom state that can be available after jd_done_nolock() is called + * Subset of atom state that can be available after kbase_jd_done_nolock() is called * on that atom. A copy must be taken via kbasep_js_atom_retained_state_copy(), * because the original atom could disappear. */ diff --git a/drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h b/drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h index a713681c8316..3669f7e23fa6 100644 --- a/drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h +++ b/drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2014-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -38,6 +38,7 @@ enum base_hw_feature { BASE_HW_FEATURE_ASN_HASH, BASE_HW_FEATURE_GPU_SLEEP, BASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER, + BASE_HW_FEATURE_CORE_FEATURES, BASE_HW_FEATURE_END }; @@ -87,6 +88,7 @@ __attribute__((unused)) static const enum base_hw_feature base_hw_features_tGOx[ BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, BASE_HW_FEATURE_TLS_HASHING, BASE_HW_FEATURE_IDVS_GROUP_SIZE, + BASE_HW_FEATURE_CORE_FEATURES, BASE_HW_FEATURE_END }; @@ -151,6 +153,7 @@ __attribute__((unused)) static const enum base_hw_feature base_hw_features_tGRx[ BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, BASE_HW_FEATURE_L2_CONFIG, BASE_HW_FEATURE_CLEAN_ONLY_SAFE, + BASE_HW_FEATURE_CORE_FEATURES, BASE_HW_FEATURE_END }; @@ -159,6 +162,7 @@ __attribute__((unused)) static const enum base_hw_feature base_hw_features_tVAx[ BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, BASE_HW_FEATURE_L2_CONFIG, BASE_HW_FEATURE_CLEAN_ONLY_SAFE, + BASE_HW_FEATURE_CORE_FEATURES, BASE_HW_FEATURE_END }; @@ -169,6 +173,7 @@ __attribute__((unused)) static const enum base_hw_feature base_hw_features_tTUx[ BASE_HW_FEATURE_CLEAN_ONLY_SAFE, BASE_HW_FEATURE_ASN_HASH, BASE_HW_FEATURE_GPU_SLEEP, + BASE_HW_FEATURE_CORE_FEATURES, BASE_HW_FEATURE_END }; diff --git a/drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h b/drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h index 95bdd1718e06..391730106f6d 100644 --- a/drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h +++ b/drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h @@ -62,6 +62,8 @@ enum base_hw_issue { BASE_HW_ISSUE_TURSEHW_1997, BASE_HW_ISSUE_GPU2019_3878, BASE_HW_ISSUE_TURSEHW_2716, + BASE_HW_ISSUE_GPU2019_3901, + BASE_HW_ISSUE_GPU2021PRO_290, BASE_HW_ISSUE_END }; @@ -599,6 +601,7 @@ __attribute__((unused)) static const enum base_hw_issue base_hw_issues_tODx_r0p0 BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3212, BASE_HW_ISSUE_GPU2019_3878, + BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_END }; @@ -609,6 +612,7 @@ __attribute__((unused)) static const enum base_hw_issue base_hw_issues_model_tOD BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3212, BASE_HW_ISSUE_GPU2019_3878, + BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_END }; @@ -617,6 +621,7 @@ __attribute__((unused)) static const enum base_hw_issue base_hw_issues_tGRx_r0p0 BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878, + BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_END }; @@ -626,6 +631,7 @@ __attribute__((unused)) static const enum base_hw_issue base_hw_issues_model_tGR BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878, + BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_END }; @@ -634,6 +640,7 @@ __attribute__((unused)) static const enum base_hw_issue base_hw_issues_tVAx_r0p0 BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878, + BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_END }; @@ -643,6 +650,7 @@ __attribute__((unused)) static const enum base_hw_issue base_hw_issues_model_tVA BASE_HW_ISSUE_TSIX_2033, BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878, + BASE_HW_ISSUE_GPU2019_3901, BASE_HW_ISSUE_END }; @@ -653,6 +661,8 @@ __attribute__((unused)) static const enum base_hw_issue base_hw_issues_tTUx_r0p0 BASE_HW_ISSUE_TURSEHW_1997, BASE_HW_ISSUE_GPU2019_3878, BASE_HW_ISSUE_TURSEHW_2716, + BASE_HW_ISSUE_GPU2019_3901, + BASE_HW_ISSUE_GPU2021PRO_290, BASE_HW_ISSUE_END }; @@ -663,6 +673,8 @@ __attribute__((unused)) static const enum base_hw_issue base_hw_issues_model_tTU BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878, BASE_HW_ISSUE_TURSEHW_2716, + BASE_HW_ISSUE_GPU2019_3901, + BASE_HW_ISSUE_GPU2021PRO_290, BASE_HW_ISSUE_END }; @@ -672,6 +684,8 @@ __attribute__((unused)) static const enum base_hw_issue base_hw_issues_tTUx_r1p0 BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878, BASE_HW_ISSUE_TURSEHW_2716, + BASE_HW_ISSUE_GPU2019_3901, + BASE_HW_ISSUE_GPU2021PRO_290, BASE_HW_ISSUE_END }; @@ -681,6 +695,8 @@ __attribute__((unused)) static const enum base_hw_issue base_hw_issues_tTUx_r1p1 BASE_HW_ISSUE_TTRX_1337, BASE_HW_ISSUE_GPU2019_3878, BASE_HW_ISSUE_TURSEHW_2716, + BASE_HW_ISSUE_GPU2019_3901, + BASE_HW_ISSUE_GPU2021PRO_290, BASE_HW_ISSUE_END }; diff --git a/drivers/gpu/arm/bifrost/mali_kbase.h b/drivers/gpu/arm/bifrost/mali_kbase.h index 451d44713b10..7d0d0dae0279 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase.h +++ b/drivers/gpu/arm/bifrost/mali_kbase.h @@ -82,14 +82,7 @@ #if MALI_USE_CSF #include "csf/mali_kbase_csf.h" -#endif -#ifndef u64_to_user_ptr -/* Introduced in Linux v4.6 */ -#define u64_to_user_ptr(x) ((void __user *)(uintptr_t)x) -#endif - -#if MALI_USE_CSF /* Physical memory group ID for CSF user I/O. */ #define KBASE_MEM_GROUP_CSF_IO BASE_MEM_GROUP_DEFAULT @@ -265,7 +258,7 @@ void kbase_jd_cancel(struct kbase_device *kbdev, struct kbase_jd_atom *katom); void kbase_jd_zap_context(struct kbase_context *kctx); /* - * jd_done_nolock - Perform the necessary handling of an atom that has completed + * kbase_jd_done_nolock - Perform the necessary handling of an atom that has completed * the execution. * * @katom: Pointer to the atom that completed the execution @@ -281,7 +274,7 @@ void kbase_jd_zap_context(struct kbase_context *kctx); * * The caller must hold the kbase_jd_context.lock. */ -bool jd_done_nolock(struct kbase_jd_atom *katom, bool post_immediately); +bool kbase_jd_done_nolock(struct kbase_jd_atom *katom, bool post_immediately); void kbase_jd_free_external_resources(struct kbase_jd_atom *katom); void kbase_jd_dep_clear_locked(struct kbase_jd_atom *katom); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h b/drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h index 013fd8880bf2..152ae2dfda8d 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_config_defaults.h @@ -176,7 +176,7 @@ enum { * Based on 75000ms timeout at nominal 100MHz, as is required for Android - based * on scaling from a 50MHz GPU system. */ -#define CSF_FIRMWARE_TIMEOUT_CYCLES (7500000000) +#define CSF_FIRMWARE_TIMEOUT_CYCLES (7500000000ull) /* Timeout in clock cycles for GPU Power Management to reach the desired * Shader, L2 and MCU state. @@ -203,6 +203,12 @@ enum { */ #define CSF_FIRMWARE_BOOT_TIMEOUT_CYCLES (25000000) +/* Waiting timeout for a ping request to be acknowledged, in clock cycles. + * + * Based on 6000ms timeout at 100MHz, scaled from a 50MHz GPU system. + */ +#define CSF_FIRMWARE_PING_TIMEOUT_CYCLES (600000000ull) + #else /* MALI_USE_CSF */ /* A default timeout in clock cycles to be used when an invalid timeout diff --git a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c index 6675add413fd..0c8f653a9bff 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c @@ -99,6 +99,7 @@ #include /* is_compat_task/in_compat_syscall */ #include #include +#include #include #if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) #include @@ -311,10 +312,9 @@ static int kbase_file_create_kctx(struct kbase_file *kfile, * * @kfile: A device file created by kbase_file_new() * - * This function returns an error code (encoded with ERR_PTR) if no context - * has been created for the given @kfile. This makes it safe to use in - * circumstances where the order of initialization cannot be enforced, but - * only if the caller checks the return value. + * This function returns NULL if no context has been created for the given @kfile. + * This makes it safe to use in circumstances where the order of initialization + * cannot be enforced, but only if the caller checks the return value. * * Return: Address of the kernel base context associated with the @kfile, or * NULL if no context exists. @@ -502,27 +502,6 @@ void kbase_release_device(struct kbase_device *kbdev) EXPORT_SYMBOL(kbase_release_device); #if IS_ENABLED(CONFIG_DEBUG_FS) -#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE && \ - !(KERNEL_VERSION(4, 4, 28) <= LINUX_VERSION_CODE && \ - KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE) -/* - * Older versions, before v4.6, of the kernel doesn't have - * kstrtobool_from_user(), except longterm 4.4.y which had it added in 4.4.28 - */ -static int kstrtobool_from_user(const char __user *s, size_t count, bool *res) -{ - char buf[4]; - - count = min(count, sizeof(buf) - 1); - - if (copy_from_user(buf, s, count)) - return -EFAULT; - buf[count] = '\0'; - - return strtobool(buf, res); -} -#endif - static ssize_t write_ctx_infinite_cache(struct file *f, const char __user *ubuf, size_t size, loff_t *off) { struct kbase_context *kctx = f->private_data; @@ -634,13 +613,8 @@ static int kbase_file_create_kctx(struct kbase_file *const kfile, kbdev = kfile->kbdev; -#if (KERNEL_VERSION(4, 6, 0) <= LINUX_VERSION_CODE) kctx = kbase_create_context(kbdev, in_compat_syscall(), flags, kfile->api_version, kfile->filp); -#else - kctx = kbase_create_context(kbdev, is_compat_task(), - flags, kfile->api_version, kfile->filp); -#endif /* (KERNEL_VERSION(4, 6, 0) <= LINUX_VERSION_CODE) */ /* if bad flags, will stay stuck in setup mode */ if (!kctx) @@ -661,16 +635,8 @@ static int kbase_file_create_kctx(struct kbase_file *const kfile, /* we don't treat this as a fail - just warn about it */ dev_warn(kbdev->dev, "couldn't create debugfs dir for kctx\n"); } else { -#if (KERNEL_VERSION(4, 7, 0) > LINUX_VERSION_CODE) - /* prevent unprivileged use of debug file system - * in old kernel version - */ - debugfs_create_file("infinite_cache", 0600, kctx->kctx_dentry, - kctx, &kbase_infinite_cache_fops); -#else debugfs_create_file("infinite_cache", 0644, kctx->kctx_dentry, kctx, &kbase_infinite_cache_fops); -#endif debugfs_create_file("force_same_va", 0600, kctx->kctx_dentry, kctx, &kbase_force_same_va_fops); @@ -2200,18 +2166,28 @@ static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, lof } #endif /* MALI_USE_CSF */ -static unsigned int kbase_poll(struct file *filp, poll_table *wait) +static __poll_t kbase_poll(struct file *filp, poll_table *wait) { struct kbase_file *const kfile = filp->private_data; struct kbase_context *const kctx = kbase_file_get_kctx_if_setup_complete(kfile); - if (unlikely(!kctx)) + if (unlikely(!kctx)) { +#if (KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE) return POLLERR; +#else + return EPOLLERR; +#endif + } poll_wait(filp, &kctx->event_queue, wait); - if (kbase_event_pending(kctx)) + if (kbase_event_pending(kctx)) { +#if (KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE) return POLLIN | POLLRDNORM; +#else + return EPOLLIN | EPOLLRDNORM; +#endif + } return 0; } @@ -4542,7 +4518,7 @@ int power_control_init(struct kbase_device *kbdev) } } if (err == -EPROBE_DEFER) { - while ((i > 0) && (i < BASE_MAX_NR_CLOCKS_REGULATORS)) + while (i > 0) regulator_put(kbdev->regulators[--i]); return err; } @@ -4579,8 +4555,8 @@ int power_control_init(struct kbase_device *kbdev) } } if (err == -EPROBE_DEFER) { - while ((i > 0) && (i < BASE_MAX_NR_CLOCKS_REGULATORS)) { - clk_unprepare(kbdev->clocks[--i]); + while (i > 0) { + clk_disable_unprepare(kbdev->clocks[--i]); clk_put(kbdev->clocks[i]); } goto clocks_probe_defer; @@ -4627,6 +4603,19 @@ int power_control_init(struct kbase_device *kbdev) #endif /* CONFIG_PM_OPP */ return 0; +#if defined(CONFIG_PM_OPP) && \ + ((KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE) && defined(CONFIG_REGULATOR)) + for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) { + if (kbdev->clocks[i]) { + if (__clk_is_enabled(kbdev->clocks[i])) + clk_disable_unprepare(kbdev->clocks[i]); + clk_put(kbdev->clocks[i]); + kbdev->clocks[i] = NULL; + } else + break; + } +#endif + clocks_probe_defer: #if defined(CONFIG_REGULATOR) for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) @@ -4819,12 +4808,7 @@ int kbase_device_debugfs_init(struct kbase_device *kbdev) /* prevent unprivileged use of debug file system * in old kernel version */ -#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE) - /* only for newer kernel version debug file system is safe */ const mode_t mode = 0644; -#else - const mode_t mode = 0600; -#endif kbdev->mali_debugfs_directory = debugfs_create_dir(kbdev->devname, NULL); @@ -4930,6 +4914,7 @@ int kbase_device_debugfs_init(struct kbase_device *kbdev) #endif kbase_dvfs_status_debugfs_init(kbdev); + return 0; out: @@ -5126,10 +5111,11 @@ static ssize_t fw_timeout_store(struct device *dev, ret = kstrtouint(buf, 0, &fw_timeout); if (ret || fw_timeout == 0) { - dev_err(kbdev->dev, "%s\n%s\n%u", - "Couldn't process fw_timeout write operation.", - "Use format 'fw_timeout_ms', and fw_timeout_ms > 0", - FIRMWARE_PING_INTERVAL_MS); + dev_err(kbdev->dev, + "Couldn't process fw_timeout write operation.\n" + "Use format 'fw_timeout_ms', and fw_timeout_ms > 0\n" + "Default fw_timeout: %u", + kbase_get_timeout_ms(kbdev, CSF_FIRMWARE_PING_TIMEOUT)); return -EINVAL; } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.c b/drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.c index 4f021b316b83..d6518b476115 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_debug_job_fault.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2012-2016, 2018-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2012-2016, 2018-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -87,8 +87,7 @@ static bool kbase_ctx_has_no_event_pending(struct kbase_context *kctx) static int wait_for_job_fault(struct kbase_device *kbdev) { -#if KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE && \ - KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE +#if KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE int ret = wait_event_interruptible_timeout(kbdev->job_fault_wq, kbase_is_job_fault_event_pending(kbdev), msecs_to_jiffies(2000)); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_defs.h index e4ad9743e79f..9fafe96d14a8 100755 --- a/drivers/gpu/arm/bifrost/mali_kbase_defs.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_defs.h @@ -579,7 +579,7 @@ struct kbase_mmu_mode { int (*pte_is_valid)(u64 pte, int level); void (*entry_set_ate)(u64 *entry, struct tagged_addr phy, unsigned long flags, int level); - void (*entry_set_pte)(u64 *pgd, u64 vpfn, phys_addr_t phy); + void (*entry_set_pte)(u64 *entry, phys_addr_t phy); void (*entry_invalidate)(u64 *entry); unsigned int (*get_num_valid_entries)(u64 *pgd); void (*set_num_valid_entries)(u64 *pgd, @@ -1154,11 +1154,8 @@ struct kbase_device { #endif bool poweroff_pending; -#if (KERNEL_VERSION(4, 4, 0) <= LINUX_VERSION_CODE) bool infinite_cache_active_default; -#else - u32 infinite_cache_active_default; -#endif + struct kbase_mem_pool_group_config mem_pool_defaults; u32 current_gpu_coherency_mode; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c index 51d1bd178b7f..d5f4fae091e8 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c @@ -161,7 +161,7 @@ kbase_dma_fence_cancel_atom(struct kbase_jd_atom *katom) if (katom->status == KBASE_JD_ATOM_STATE_QUEUED) { /* Wait was cancelled - zap the atom */ katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - if (jd_done_nolock(katom, true)) + if (kbase_jd_done_nolock(katom, true)) kbase_js_sched_all(katom->kctx->kbdev); } } @@ -193,10 +193,10 @@ kbase_dma_fence_work(struct work_struct *pwork) kbase_fence_free_callbacks(katom); /* * Queue atom on GPU, unless it has already completed due to a failing - * dependency. Run jd_done_nolock() on the katom if it is completed. + * dependency. Run kbase_jd_done_nolock() on the katom if it is completed. */ if (unlikely(katom->status == KBASE_JD_ATOM_STATE_COMPLETED)) - jd_done_nolock(katom, true); + kbase_jd_done_nolock(katom, true); else kbase_jd_dep_clear_locked(katom); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h index 36c34fe30107..f0c8d069b02c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h @@ -105,7 +105,7 @@ void kbase_dma_fence_cancel_all_atoms(struct kbase_context *kctx); * This function cancels all dma-buf fence callbacks on @katom, but does not * cancel the katom itself. * - * The caller is responsible for ensuring that jd_done_nolock is called on + * The caller is responsible for ensuring that kbase_jd_done_nolock is called on * @katom. * * Locking: jctx.lock must be held when calling this function. diff --git a/drivers/gpu/arm/bifrost/mali_kbase_dvfs_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_dvfs_debugfs.c index 1e584deb0e33..e4cb71632aee 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_dvfs_debugfs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_dvfs_debugfs.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -68,11 +68,7 @@ static const struct file_operations kbasep_dvfs_utilization_debugfs_fops = { void kbase_dvfs_status_debugfs_init(struct kbase_device *kbdev) { struct dentry *file; -#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE) const mode_t mode = 0444; -#else - const mode_t mode = 0400; -#endif if (WARN_ON(!kbdev || IS_ERR_OR_NULL(kbdev->mali_debugfs_directory))) return; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_fence.h b/drivers/gpu/arm/bifrost/mali_kbase_fence.h index 1ed3b9bd7f1d..4f952ad4d509 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_fence.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_fence.h @@ -271,6 +271,16 @@ bool kbase_fence_free_callbacks(struct kbase_jd_atom *katom); #endif /* !MALI_USE_CSF */ +/** + * kbase_fence_get() - Retrieve fence for a KCPUQ fence command. + * @fence_info: KCPUQ fence command + * + * A ref will be taken for the fence, so use @kbase_fence_put() to release it + * + * Return: The fence, or NULL if there is no fence for KCPUQ fence command + */ +#define kbase_fence_get(fence_info) dma_fence_get((fence_info)->fence) + /** * kbase_fence_put() - Releases a reference to a fence * @fence: Fence to release reference for. diff --git a/drivers/gpu/arm/bifrost/mali_kbase_fence_ops.c b/drivers/gpu/arm/bifrost/mali_kbase_fence_ops.c index 14ddf0308317..be141553c674 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_fence_ops.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_fence_ops.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -69,9 +69,11 @@ kbase_fence_fence_value_str(struct dma_fence *fence, char *str, int size) } #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) +extern const struct fence_ops kbase_fence_ops; /* silence checker warning */ const struct fence_ops kbase_fence_ops = { .wait = fence_default_wait, #else +extern const struct dma_fence_ops kbase_fence_ops; /* silence checker warning */ const struct dma_fence_ops kbase_fence_ops = { .wait = dma_fence_default_wait, #endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c index cd1ecba32b77..0bea655178d5 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2011-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2011-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -198,7 +198,6 @@ static int kbase_gpuprops_get_props(struct base_gpu_props * const gpu_props, gpu_props->raw_props.mem_features = regdump.mem_features; gpu_props->raw_props.mmu_features = regdump.mmu_features; gpu_props->raw_props.l2_features = regdump.l2_features; - gpu_props->raw_props.core_features = regdump.core_features; gpu_props->raw_props.as_present = regdump.as_present; gpu_props->raw_props.js_present = regdump.js_present; @@ -324,9 +323,6 @@ static void kbase_gpuprops_calculate_props( totalram_pages() << PAGE_SHIFT; #endif - gpu_props->core_props.num_exec_engines = - KBASE_UBFX32(gpu_props->raw_props.core_features, 0, 4); - for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++) gpu_props->core_props.texture_features[i] = gpu_props->raw_props.texture_features[i]; @@ -507,6 +503,21 @@ int kbase_gpuprops_set_features(struct kbase_device *kbdev) if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_THREAD_GROUP_SPLIT)) gpu_props->thread_props.max_thread_group_split = 0; + /* + * The CORE_FEATURES register has different meanings depending on GPU. + * On tGOx, bits[3:0] encode num_exec_engines. + * On CSF GPUs, bits[7:0] is an enumeration that needs to be parsed, + * instead. + * GPUs like tTIx have additional fields like LSC_SIZE that are + * otherwise reserved/RAZ on older GPUs. + */ + gpu_props->raw_props.core_features = regdump.core_features; + +#if !MALI_USE_CSF + gpu_props->core_props.num_exec_engines = + KBASE_UBFX32(gpu_props->raw_props.core_features, 0, 4); +#endif + return err; } @@ -694,94 +705,102 @@ static struct { #define PROP(name, member) \ {KBASE_GPUPROP_ ## name, offsetof(struct base_gpu_props, member), \ sizeof(((struct base_gpu_props *)0)->member)} - PROP(PRODUCT_ID, core_props.product_id), - PROP(VERSION_STATUS, core_props.version_status), - PROP(MINOR_REVISION, core_props.minor_revision), - PROP(MAJOR_REVISION, core_props.major_revision), - PROP(GPU_FREQ_KHZ_MAX, core_props.gpu_freq_khz_max), - PROP(LOG2_PROGRAM_COUNTER_SIZE, core_props.log2_program_counter_size), - PROP(TEXTURE_FEATURES_0, core_props.texture_features[0]), - PROP(TEXTURE_FEATURES_1, core_props.texture_features[1]), - PROP(TEXTURE_FEATURES_2, core_props.texture_features[2]), - PROP(TEXTURE_FEATURES_3, core_props.texture_features[3]), - PROP(GPU_AVAILABLE_MEMORY_SIZE, core_props.gpu_available_memory_size), - PROP(NUM_EXEC_ENGINES, core_props.num_exec_engines), +#define BACKWARDS_COMPAT_PROP(name, type) \ + { \ + KBASE_GPUPROP_##name, SIZE_MAX, sizeof(type) \ + } + PROP(PRODUCT_ID, core_props.product_id), + PROP(VERSION_STATUS, core_props.version_status), + PROP(MINOR_REVISION, core_props.minor_revision), + PROP(MAJOR_REVISION, core_props.major_revision), + PROP(GPU_FREQ_KHZ_MAX, core_props.gpu_freq_khz_max), + PROP(LOG2_PROGRAM_COUNTER_SIZE, core_props.log2_program_counter_size), + PROP(TEXTURE_FEATURES_0, core_props.texture_features[0]), + PROP(TEXTURE_FEATURES_1, core_props.texture_features[1]), + PROP(TEXTURE_FEATURES_2, core_props.texture_features[2]), + PROP(TEXTURE_FEATURES_3, core_props.texture_features[3]), + PROP(GPU_AVAILABLE_MEMORY_SIZE, core_props.gpu_available_memory_size), - PROP(L2_LOG2_LINE_SIZE, l2_props.log2_line_size), - PROP(L2_LOG2_CACHE_SIZE, l2_props.log2_cache_size), - PROP(L2_NUM_L2_SLICES, l2_props.num_l2_slices), +#if MALI_USE_CSF + BACKWARDS_COMPAT_PROP(NUM_EXEC_ENGINES, u8), +#else + PROP(NUM_EXEC_ENGINES, core_props.num_exec_engines), +#endif - PROP(TILER_BIN_SIZE_BYTES, tiler_props.bin_size_bytes), - PROP(TILER_MAX_ACTIVE_LEVELS, tiler_props.max_active_levels), + PROP(L2_LOG2_LINE_SIZE, l2_props.log2_line_size), + PROP(L2_LOG2_CACHE_SIZE, l2_props.log2_cache_size), + PROP(L2_NUM_L2_SLICES, l2_props.num_l2_slices), - PROP(MAX_THREADS, thread_props.max_threads), - PROP(MAX_WORKGROUP_SIZE, thread_props.max_workgroup_size), - PROP(MAX_BARRIER_SIZE, thread_props.max_barrier_size), - PROP(MAX_REGISTERS, thread_props.max_registers), - PROP(MAX_TASK_QUEUE, thread_props.max_task_queue), - PROP(MAX_THREAD_GROUP_SPLIT, thread_props.max_thread_group_split), - PROP(IMPL_TECH, thread_props.impl_tech), - PROP(TLS_ALLOC, thread_props.tls_alloc), + PROP(TILER_BIN_SIZE_BYTES, tiler_props.bin_size_bytes), + PROP(TILER_MAX_ACTIVE_LEVELS, tiler_props.max_active_levels), - PROP(RAW_SHADER_PRESENT, raw_props.shader_present), - PROP(RAW_TILER_PRESENT, raw_props.tiler_present), - PROP(RAW_L2_PRESENT, raw_props.l2_present), - PROP(RAW_STACK_PRESENT, raw_props.stack_present), - PROP(RAW_L2_FEATURES, raw_props.l2_features), - PROP(RAW_CORE_FEATURES, raw_props.core_features), - PROP(RAW_MEM_FEATURES, raw_props.mem_features), - PROP(RAW_MMU_FEATURES, raw_props.mmu_features), - PROP(RAW_AS_PRESENT, raw_props.as_present), - PROP(RAW_JS_PRESENT, raw_props.js_present), - PROP(RAW_JS_FEATURES_0, raw_props.js_features[0]), - PROP(RAW_JS_FEATURES_1, raw_props.js_features[1]), - PROP(RAW_JS_FEATURES_2, raw_props.js_features[2]), - PROP(RAW_JS_FEATURES_3, raw_props.js_features[3]), - PROP(RAW_JS_FEATURES_4, raw_props.js_features[4]), - PROP(RAW_JS_FEATURES_5, raw_props.js_features[5]), - PROP(RAW_JS_FEATURES_6, raw_props.js_features[6]), - PROP(RAW_JS_FEATURES_7, raw_props.js_features[7]), - PROP(RAW_JS_FEATURES_8, raw_props.js_features[8]), - PROP(RAW_JS_FEATURES_9, raw_props.js_features[9]), - PROP(RAW_JS_FEATURES_10, raw_props.js_features[10]), - PROP(RAW_JS_FEATURES_11, raw_props.js_features[11]), - PROP(RAW_JS_FEATURES_12, raw_props.js_features[12]), - PROP(RAW_JS_FEATURES_13, raw_props.js_features[13]), - PROP(RAW_JS_FEATURES_14, raw_props.js_features[14]), - PROP(RAW_JS_FEATURES_15, raw_props.js_features[15]), - PROP(RAW_TILER_FEATURES, raw_props.tiler_features), - PROP(RAW_TEXTURE_FEATURES_0, raw_props.texture_features[0]), - PROP(RAW_TEXTURE_FEATURES_1, raw_props.texture_features[1]), - PROP(RAW_TEXTURE_FEATURES_2, raw_props.texture_features[2]), - PROP(RAW_TEXTURE_FEATURES_3, raw_props.texture_features[3]), - PROP(RAW_GPU_ID, raw_props.gpu_id), - PROP(RAW_THREAD_MAX_THREADS, raw_props.thread_max_threads), - PROP(RAW_THREAD_MAX_WORKGROUP_SIZE, - raw_props.thread_max_workgroup_size), + PROP(MAX_THREADS, thread_props.max_threads), + PROP(MAX_WORKGROUP_SIZE, thread_props.max_workgroup_size), + PROP(MAX_BARRIER_SIZE, thread_props.max_barrier_size), + PROP(MAX_REGISTERS, thread_props.max_registers), + PROP(MAX_TASK_QUEUE, thread_props.max_task_queue), + PROP(MAX_THREAD_GROUP_SPLIT, thread_props.max_thread_group_split), + PROP(IMPL_TECH, thread_props.impl_tech), + PROP(TLS_ALLOC, thread_props.tls_alloc), + + PROP(RAW_SHADER_PRESENT, raw_props.shader_present), + PROP(RAW_TILER_PRESENT, raw_props.tiler_present), + PROP(RAW_L2_PRESENT, raw_props.l2_present), + PROP(RAW_STACK_PRESENT, raw_props.stack_present), + PROP(RAW_L2_FEATURES, raw_props.l2_features), + PROP(RAW_CORE_FEATURES, raw_props.core_features), + PROP(RAW_MEM_FEATURES, raw_props.mem_features), + PROP(RAW_MMU_FEATURES, raw_props.mmu_features), + PROP(RAW_AS_PRESENT, raw_props.as_present), + PROP(RAW_JS_PRESENT, raw_props.js_present), + PROP(RAW_JS_FEATURES_0, raw_props.js_features[0]), + PROP(RAW_JS_FEATURES_1, raw_props.js_features[1]), + PROP(RAW_JS_FEATURES_2, raw_props.js_features[2]), + PROP(RAW_JS_FEATURES_3, raw_props.js_features[3]), + PROP(RAW_JS_FEATURES_4, raw_props.js_features[4]), + PROP(RAW_JS_FEATURES_5, raw_props.js_features[5]), + PROP(RAW_JS_FEATURES_6, raw_props.js_features[6]), + PROP(RAW_JS_FEATURES_7, raw_props.js_features[7]), + PROP(RAW_JS_FEATURES_8, raw_props.js_features[8]), + PROP(RAW_JS_FEATURES_9, raw_props.js_features[9]), + PROP(RAW_JS_FEATURES_10, raw_props.js_features[10]), + PROP(RAW_JS_FEATURES_11, raw_props.js_features[11]), + PROP(RAW_JS_FEATURES_12, raw_props.js_features[12]), + PROP(RAW_JS_FEATURES_13, raw_props.js_features[13]), + PROP(RAW_JS_FEATURES_14, raw_props.js_features[14]), + PROP(RAW_JS_FEATURES_15, raw_props.js_features[15]), + PROP(RAW_TILER_FEATURES, raw_props.tiler_features), + PROP(RAW_TEXTURE_FEATURES_0, raw_props.texture_features[0]), + PROP(RAW_TEXTURE_FEATURES_1, raw_props.texture_features[1]), + PROP(RAW_TEXTURE_FEATURES_2, raw_props.texture_features[2]), + PROP(RAW_TEXTURE_FEATURES_3, raw_props.texture_features[3]), + PROP(RAW_GPU_ID, raw_props.gpu_id), + PROP(RAW_THREAD_MAX_THREADS, raw_props.thread_max_threads), + PROP(RAW_THREAD_MAX_WORKGROUP_SIZE, raw_props.thread_max_workgroup_size), PROP(RAW_THREAD_MAX_BARRIER_SIZE, raw_props.thread_max_barrier_size), - PROP(RAW_THREAD_FEATURES, raw_props.thread_features), - PROP(RAW_COHERENCY_MODE, raw_props.coherency_mode), - PROP(RAW_THREAD_TLS_ALLOC, raw_props.thread_tls_alloc), - PROP(RAW_GPU_FEATURES, raw_props.gpu_features), - PROP(COHERENCY_NUM_GROUPS, coherency_info.num_groups), - PROP(COHERENCY_NUM_CORE_GROUPS, coherency_info.num_core_groups), - PROP(COHERENCY_COHERENCY, coherency_info.coherency), - PROP(COHERENCY_GROUP_0, coherency_info.group[0].core_mask), - PROP(COHERENCY_GROUP_1, coherency_info.group[1].core_mask), - PROP(COHERENCY_GROUP_2, coherency_info.group[2].core_mask), - PROP(COHERENCY_GROUP_3, coherency_info.group[3].core_mask), - PROP(COHERENCY_GROUP_4, coherency_info.group[4].core_mask), - PROP(COHERENCY_GROUP_5, coherency_info.group[5].core_mask), - PROP(COHERENCY_GROUP_6, coherency_info.group[6].core_mask), - PROP(COHERENCY_GROUP_7, coherency_info.group[7].core_mask), - PROP(COHERENCY_GROUP_8, coherency_info.group[8].core_mask), - PROP(COHERENCY_GROUP_9, coherency_info.group[9].core_mask), - PROP(COHERENCY_GROUP_10, coherency_info.group[10].core_mask), - PROP(COHERENCY_GROUP_11, coherency_info.group[11].core_mask), - PROP(COHERENCY_GROUP_12, coherency_info.group[12].core_mask), - PROP(COHERENCY_GROUP_13, coherency_info.group[13].core_mask), - PROP(COHERENCY_GROUP_14, coherency_info.group[14].core_mask), - PROP(COHERENCY_GROUP_15, coherency_info.group[15].core_mask), + PROP(RAW_THREAD_FEATURES, raw_props.thread_features), + PROP(RAW_COHERENCY_MODE, raw_props.coherency_mode), + PROP(RAW_THREAD_TLS_ALLOC, raw_props.thread_tls_alloc), + PROP(RAW_GPU_FEATURES, raw_props.gpu_features), + PROP(COHERENCY_NUM_GROUPS, coherency_info.num_groups), + PROP(COHERENCY_NUM_CORE_GROUPS, coherency_info.num_core_groups), + PROP(COHERENCY_COHERENCY, coherency_info.coherency), + PROP(COHERENCY_GROUP_0, coherency_info.group[0].core_mask), + PROP(COHERENCY_GROUP_1, coherency_info.group[1].core_mask), + PROP(COHERENCY_GROUP_2, coherency_info.group[2].core_mask), + PROP(COHERENCY_GROUP_3, coherency_info.group[3].core_mask), + PROP(COHERENCY_GROUP_4, coherency_info.group[4].core_mask), + PROP(COHERENCY_GROUP_5, coherency_info.group[5].core_mask), + PROP(COHERENCY_GROUP_6, coherency_info.group[6].core_mask), + PROP(COHERENCY_GROUP_7, coherency_info.group[7].core_mask), + PROP(COHERENCY_GROUP_8, coherency_info.group[8].core_mask), + PROP(COHERENCY_GROUP_9, coherency_info.group[9].core_mask), + PROP(COHERENCY_GROUP_10, coherency_info.group[10].core_mask), + PROP(COHERENCY_GROUP_11, coherency_info.group[11].core_mask), + PROP(COHERENCY_GROUP_12, coherency_info.group[12].core_mask), + PROP(COHERENCY_GROUP_13, coherency_info.group[13].core_mask), + PROP(COHERENCY_GROUP_14, coherency_info.group[14].core_mask), + PROP(COHERENCY_GROUP_15, coherency_info.group[15].core_mask), #undef PROP }; @@ -818,7 +837,14 @@ int kbase_gpuprops_populate_user_buffer(struct kbase_device *kbdev) for (i = 0; i < count; i++) { u32 type = gpu_property_mapping[i].type; u8 type_size; - void *field = ((u8 *)props) + gpu_property_mapping[i].offset; + const size_t offset = gpu_property_mapping[i].offset; + const u64 dummy_backwards_compat_value = (u64)0; + const void *field; + + if (likely(offset < sizeof(struct base_gpu_props))) + field = ((const u8 *)props) + offset; + else + field = &dummy_backwards_compat_value; switch (gpu_property_mapping[i].size) { case 1: @@ -844,16 +870,16 @@ int kbase_gpuprops_populate_user_buffer(struct kbase_device *kbdev) switch (type_size) { case KBASE_GPUPROP_VALUE_SIZE_U8: - WRITE_U8(*((u8 *)field)); + WRITE_U8(*((const u8 *)field)); break; case KBASE_GPUPROP_VALUE_SIZE_U16: - WRITE_U16(*((u16 *)field)); + WRITE_U16(*((const u16 *)field)); break; case KBASE_GPUPROP_VALUE_SIZE_U32: - WRITE_U32(*((u32 *)field)); + WRITE_U32(*((const u32 *)field)); break; case KBASE_GPUPROP_VALUE_SIZE_U64: - WRITE_U64(*((u64 *)field)); + WRITE_U64(*((const u64 *)field)); break; default: /* Cannot be reached */ WARN_ON(1); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf.c b/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf.c index 016633164a9e..8afc990662da 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf.c @@ -173,23 +173,29 @@ struct kbase_hwcnt_backend_csf_info { /** * struct kbase_hwcnt_csf_physical_layout - HWC sample memory physical layout * information. + * @hw_block_cnt: Total number of hardware counters blocks. The hw counters blocks are + * sub-categorized into 4 classes: front-end, tiler, memory system, and shader. + * hw_block_cnt = fe_cnt + tiler_cnt + mmu_l2_cnt + shader_cnt. * @fe_cnt: Front end block count. * @tiler_cnt: Tiler block count. - * @mmu_l2_cnt: Memory system(MMU and L2 cache) block count. + * @mmu_l2_cnt: Memory system (MMU and L2 cache) block count. * @shader_cnt: Shader Core block count. - * @block_cnt: Total block count (sum of all other block counts). + * @fw_block_cnt: Total number of firmware counters blocks. + * @block_cnt: Total block count (sum of all counter blocks: hw_block_cnt + fw_block_cnt). * @shader_avail_mask: Bitmap of all shader cores in the system. * @enable_mask_offset: Offset in array elements of enable mask in each block * starting from the beginning of block. - * @headers_per_block: Header size per block. - * @counters_per_block: Counters size per block. - * @values_per_block: Total size per block. + * @headers_per_block: For any block, the number of counters designated as block's header. + * @counters_per_block: For any block, the number of counters designated as block's payload. + * @values_per_block: For any block, the number of counters in total (header + payload). */ struct kbase_hwcnt_csf_physical_layout { + u8 hw_block_cnt; u8 fe_cnt; u8 tiler_cnt; u8 mmu_l2_cnt; u8 shader_cnt; + u8 fw_block_cnt; u8 block_cnt; u64 shader_avail_mask; size_t enable_mask_offset; @@ -366,29 +372,38 @@ static void kbasep_hwcnt_backend_csf_init_layout( const struct kbase_hwcnt_backend_csf_if_prfcnt_info *prfcnt_info, struct kbase_hwcnt_csf_physical_layout *phys_layout) { - u8 shader_core_cnt; + size_t shader_core_cnt; size_t values_per_block; + size_t fw_blocks_count; + size_t hw_blocks_count; WARN_ON(!prfcnt_info); WARN_ON(!phys_layout); shader_core_cnt = fls64(prfcnt_info->core_mask); - values_per_block = - prfcnt_info->prfcnt_block_size / KBASE_HWCNT_VALUE_HW_BYTES; + values_per_block = prfcnt_info->prfcnt_block_size / KBASE_HWCNT_VALUE_HW_BYTES; + fw_blocks_count = div_u64(prfcnt_info->prfcnt_fw_size, prfcnt_info->prfcnt_block_size); + hw_blocks_count = div_u64(prfcnt_info->prfcnt_hw_size, prfcnt_info->prfcnt_block_size); + + /* The number of hardware counters reported by the GPU matches the legacy guess-work we + * have done in the past + */ + WARN_ON(hw_blocks_count != KBASE_HWCNT_V5_FE_BLOCK_COUNT + + KBASE_HWCNT_V5_TILER_BLOCK_COUNT + + prfcnt_info->l2_count + shader_core_cnt); *phys_layout = (struct kbase_hwcnt_csf_physical_layout){ .fe_cnt = KBASE_HWCNT_V5_FE_BLOCK_COUNT, .tiler_cnt = KBASE_HWCNT_V5_TILER_BLOCK_COUNT, .mmu_l2_cnt = prfcnt_info->l2_count, .shader_cnt = shader_core_cnt, - .block_cnt = KBASE_HWCNT_V5_FE_BLOCK_COUNT + - KBASE_HWCNT_V5_TILER_BLOCK_COUNT + - prfcnt_info->l2_count + shader_core_cnt, + .fw_block_cnt = fw_blocks_count, + .hw_block_cnt = hw_blocks_count, + .block_cnt = fw_blocks_count + hw_blocks_count, .shader_avail_mask = prfcnt_info->core_mask, .headers_per_block = KBASE_HWCNT_V5_HEADERS_PER_BLOCK, .values_per_block = values_per_block, - .counters_per_block = - values_per_block - KBASE_HWCNT_V5_HEADERS_PER_BLOCK, + .counters_per_block = values_per_block - KBASE_HWCNT_V5_HEADERS_PER_BLOCK, .enable_mask_offset = KBASE_HWCNT_V5_PRFCNT_EN_HEADER, }; } @@ -463,7 +478,15 @@ static void kbasep_hwcnt_backend_csf_accumulate_sample( u64 *acc_block = accum_buf; const size_t values_per_block = phys_layout->values_per_block; - for (block_idx = 0; block_idx < phys_layout->block_cnt; block_idx++) { + /* Performance counter blocks for firmware are stored before blocks for hardware. + * We skip over the firmware's performance counter blocks (counters dumping is not + * supported for firmware blocks, only hardware ones). + */ + old_block += values_per_block * phys_layout->fw_block_cnt; + new_block += values_per_block * phys_layout->fw_block_cnt; + + for (block_idx = phys_layout->fw_block_cnt; block_idx < phys_layout->block_cnt; + block_idx++) { const u32 old_enable_mask = old_block[phys_layout->enable_mask_offset]; const u32 new_enable_mask = @@ -551,8 +574,8 @@ static void kbasep_hwcnt_backend_csf_accumulate_sample( old_sample_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); WARN_ON(new_block != new_sample_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); - WARN_ON(acc_block != - accum_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); + WARN_ON(acc_block != accum_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES) - + (values_per_block * phys_layout->fw_block_cnt)); (void)dump_bytes; } @@ -1942,7 +1965,6 @@ void kbase_hwcnt_backend_csf_on_prfcnt_disable( int kbase_hwcnt_backend_csf_metadata_init( struct kbase_hwcnt_backend_interface *iface) { - int errcode; struct kbase_hwcnt_backend_csf_info *csf_info; struct kbase_hwcnt_gpu_info gpu_info; @@ -1968,19 +1990,8 @@ int kbase_hwcnt_backend_csf_metadata_init( gpu_info.prfcnt_values_per_block = csf_info->prfcnt_info.prfcnt_block_size / KBASE_HWCNT_VALUE_HW_BYTES; - errcode = kbase_hwcnt_csf_metadata_create( - &gpu_info, csf_info->counter_set, &csf_info->metadata); - if (errcode) - return errcode; - - /* - * Dump abstraction size should be exactly twice the size and layout as - * the physical dump size since 64-bit per value used in metadata. - */ - WARN_ON(csf_info->prfcnt_info.dump_bytes * 2 != - csf_info->metadata->dump_buf_bytes); - - return 0; + return kbase_hwcnt_csf_metadata_create(&gpu_info, csf_info->counter_set, + &csf_info->metadata); } void kbase_hwcnt_backend_csf_metadata_term( diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if.h b/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if.h index a4355ffd4796..24b26c2bd6f4 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if.h @@ -55,8 +55,12 @@ struct kbase_hwcnt_backend_csf_if_enable { /** * struct kbase_hwcnt_backend_csf_if_prfcnt_info - Performance counter * information. + * @prfcnt_hw_size: Total length in bytes of all the hardware counters data. The hardware + * counters are sub-divided into 4 classes: front-end, shader, tiler, and + * memory system (l2 cache + MMU). + * @prfcnt_fw_size: Total length in bytes of all the firmware counters data. * @dump_bytes: Bytes of GPU memory required to perform a performance - * counter dump. + * counter dump. dump_bytes = prfcnt_hw_size + prfcnt_fw_size. * @prfcnt_block_size: Bytes of each performance counter block. * @l2_count: The MMU L2 cache count. * @core_mask: Shader core mask. @@ -65,6 +69,8 @@ struct kbase_hwcnt_backend_csf_if_enable { * is taken. */ struct kbase_hwcnt_backend_csf_if_prfcnt_info { + size_t prfcnt_hw_size; + size_t prfcnt_fw_size; size_t dump_bytes; size_t prfcnt_block_size; size_t l2_count; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if_fw.c b/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if_fw.c index 46be35ae5974..ab33a0b26486 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if_fw.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if_fw.c @@ -221,30 +221,29 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( struct kbase_hwcnt_backend_csf_if_prfcnt_info *prfcnt_info) { #if IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) - size_t dummy_model_blk_count; struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx = (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx; - prfcnt_info->l2_count = KBASE_DUMMY_MODEL_MAX_MEMSYS_BLOCKS; - prfcnt_info->core_mask = - (1ull << KBASE_DUMMY_MODEL_MAX_SHADER_CORES) - 1; - /* 1 FE block + 1 Tiler block + l2_count blocks + shader_core blocks */ - dummy_model_blk_count = - 2 + prfcnt_info->l2_count + fls64(prfcnt_info->core_mask); - prfcnt_info->dump_bytes = - dummy_model_blk_count * KBASE_DUMMY_MODEL_BLOCK_SIZE; - prfcnt_info->prfcnt_block_size = - KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK * - KBASE_HWCNT_VALUE_HW_BYTES; - prfcnt_info->clk_cnt = 1; - prfcnt_info->clearing_samples = true; + *prfcnt_info = (struct kbase_hwcnt_backend_csf_if_prfcnt_info){ + .l2_count = KBASE_DUMMY_MODEL_MAX_MEMSYS_BLOCKS, + .core_mask = (1ull << KBASE_DUMMY_MODEL_MAX_SHADER_CORES) - 1, + .prfcnt_hw_size = + KBASE_DUMMY_MODEL_MAX_NUM_HARDWARE_BLOCKS * KBASE_DUMMY_MODEL_BLOCK_SIZE, + .prfcnt_fw_size = + KBASE_DUMMY_MODEL_MAX_FIRMWARE_BLOCKS * KBASE_DUMMY_MODEL_BLOCK_SIZE, + .dump_bytes = KBASE_DUMMY_MODEL_MAX_SAMPLE_SIZE, + .prfcnt_block_size = KBASE_DUMMY_MODEL_BLOCK_SIZE, + .clk_cnt = 1, + .clearing_samples = true, + }; + fw_ctx->buf_bytes = prfcnt_info->dump_bytes; #else struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx; struct kbase_device *kbdev; u32 prfcnt_size; - u32 prfcnt_hw_size = 0; - u32 prfcnt_fw_size = 0; + u32 prfcnt_hw_size; + u32 prfcnt_fw_size; u32 prfcnt_block_size = KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK * KBASE_HWCNT_VALUE_HW_BYTES; @@ -254,8 +253,8 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( fw_ctx = (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx; kbdev = fw_ctx->kbdev; prfcnt_size = kbdev->csf.global_iface.prfcnt_size; - prfcnt_hw_size = (prfcnt_size & 0xFF) << 8; - prfcnt_fw_size = (prfcnt_size >> 16) << 8; + prfcnt_hw_size = GLB_PRFCNT_SIZE_HARDWARE_SIZE_GET(prfcnt_size); + prfcnt_fw_size = GLB_PRFCNT_SIZE_FIRMWARE_SIZE_GET(prfcnt_size); fw_ctx->buf_bytes = prfcnt_hw_size + prfcnt_fw_size; /* Read the block size if the GPU has the register PRFCNT_FEATURES @@ -269,14 +268,16 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( << 8; } - prfcnt_info->dump_bytes = fw_ctx->buf_bytes; - prfcnt_info->prfcnt_block_size = prfcnt_block_size; - prfcnt_info->l2_count = kbdev->gpu_props.props.l2_props.num_l2_slices; - prfcnt_info->core_mask = - kbdev->gpu_props.props.coherency_info.group[0].core_mask; - - prfcnt_info->clk_cnt = fw_ctx->clk_cnt; - prfcnt_info->clearing_samples = true; + *prfcnt_info = (struct kbase_hwcnt_backend_csf_if_prfcnt_info){ + .prfcnt_hw_size = prfcnt_hw_size, + .prfcnt_fw_size = prfcnt_fw_size, + .dump_bytes = fw_ctx->buf_bytes, + .prfcnt_block_size = prfcnt_block_size, + .l2_count = kbdev->gpu_props.props.l2_props.num_l2_slices, + .core_mask = kbdev->gpu_props.props.coherency_info.group[0].core_mask, + .clk_cnt = fw_ctx->clk_cnt, + .clearing_samples = true, + }; /* Block size must be multiple of counter size. */ WARN_ON((prfcnt_info->prfcnt_block_size % KBASE_HWCNT_VALUE_HW_BYTES) != @@ -506,10 +507,9 @@ static void kbasep_hwcnt_backend_csf_if_fw_ring_buf_free( if (fw_ring_buf->phys) { u64 gpu_va_base = KBASE_HWC_CSF_RING_BUFFER_VA_START; - WARN_ON(kbase_mmu_teardown_pages( - fw_ctx->kbdev, &fw_ctx->kbdev->csf.mcu_mmu, - gpu_va_base >> PAGE_SHIFT, fw_ring_buf->num_pages, - MCU_AS_NR)); + WARN_ON(kbase_mmu_teardown_pages(fw_ctx->kbdev, &fw_ctx->kbdev->csf.mcu_mmu, + gpu_va_base >> PAGE_SHIFT, fw_ring_buf->phys, + fw_ring_buf->num_pages, MCU_AS_NR)); vunmap(fw_ring_buf->cpu_dump_base); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu_narrow.c b/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu_narrow.c index e2caa1c063d7..2a1cde79709b 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu_narrow.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu_narrow.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2021-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -161,7 +161,7 @@ void kbase_hwcnt_dump_buffer_narrow_free( return; kfree(dump_buf_narrow->dump_buf); - *dump_buf_narrow = (struct kbase_hwcnt_dump_buffer_narrow){ 0 }; + *dump_buf_narrow = (struct kbase_hwcnt_dump_buffer_narrow){ NULL }; } int kbase_hwcnt_dump_buffer_narrow_array_alloc( diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jd.c b/drivers/gpu/arm/bifrost/mali_kbase_jd.c index 3f03a57241cf..5a96f924bfbd 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_jd.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_jd.c @@ -82,7 +82,7 @@ static void jd_mark_atom_complete(struct kbase_jd_atom *katom) * Returns whether the JS needs a reschedule. * * Note that the caller must also check the atom status and - * if it is KBASE_JD_ATOM_STATE_COMPLETED must call jd_done_nolock + * if it is KBASE_JD_ATOM_STATE_COMPLETED must call kbase_jd_done_nolock */ static bool jd_run_atom(struct kbase_jd_atom *katom) { @@ -148,7 +148,7 @@ void kbase_jd_dep_clear_locked(struct kbase_jd_atom *katom) if (katom->status == KBASE_JD_ATOM_STATE_COMPLETED) { /* The atom has already finished */ - resched |= jd_done_nolock(katom, true); + resched |= kbase_jd_done_nolock(katom, true); } if (resched) @@ -703,7 +703,7 @@ static void jd_update_jit_usage(struct kbase_jd_atom *katom) } #endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ -bool jd_done_nolock(struct kbase_jd_atom *katom, bool post_immediately) +bool kbase_jd_done_nolock(struct kbase_jd_atom *katom, bool post_immediately) { struct kbase_context *kctx = katom->kctx; struct list_head completed_jobs; @@ -711,6 +711,8 @@ bool jd_done_nolock(struct kbase_jd_atom *katom, bool post_immediately) bool need_to_try_schedule_context = false; int i; + lockdep_assert_held(&kctx->jctx.lock); + KBASE_TLSTREAM_TL_JD_DONE_NO_LOCK_START(kctx->kbdev, katom); INIT_LIST_HEAD(&completed_jobs); @@ -820,7 +822,7 @@ bool jd_done_nolock(struct kbase_jd_atom *katom, bool post_immediately) return need_to_try_schedule_context; } -KBASE_EXPORT_TEST_API(jd_done_nolock); +KBASE_EXPORT_TEST_API(kbase_jd_done_nolock); #if IS_ENABLED(CONFIG_GPU_TRACEPOINTS) enum { @@ -928,7 +930,6 @@ static bool jd_submit_atom(struct kbase_context *const kctx, katom->jobslot = user_atom->jobslot; katom->seq_nr = user_atom->seq_nr; katom->atom_flags = 0; - katom->retry_count = 0; katom->need_cache_flush_cores_retained = 0; katom->pre_dep = NULL; katom->post_dep = NULL; @@ -989,7 +990,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx, * dependencies. */ jd_trace_atom_submit(kctx, katom, NULL); - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } } } @@ -1053,7 +1054,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx, if (err >= 0) kbase_finish_soft_job(katom); } - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } katom->will_fail_event_code = katom->event_code; @@ -1087,7 +1088,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx, "Rejecting atom with unsupported core_req 0x%x\n", katom->core_req); katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } #endif /* !MALI_INCREMENTAL_RENDERING_JM */ @@ -1101,7 +1102,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx, */ dev_err(kctx->kbdev->dev, "Rejecting atom with jc = NULL\n"); katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } /* Reject atoms with an invalid device_nr */ @@ -1111,7 +1112,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx, "Rejecting atom with invalid device_nr %d\n", katom->device_nr); katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } /* Reject atoms with invalid core requirements */ @@ -1121,7 +1122,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx, "Rejecting atom with invalid core requirements\n"); katom->event_code = BASE_JD_EVENT_JOB_INVALID; katom->core_req &= ~BASE_JD_REQ_EVENT_COALESCE; - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } /* Reject soft-job atom of certain types from accessing external resources */ @@ -1132,7 +1133,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx, dev_err(kctx->kbdev->dev, "Rejecting soft-job atom accessing external resources\n"); katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { @@ -1140,7 +1141,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx, if (kbase_jd_pre_external_resources(katom, user_atom) != 0) { /* setup failed (no access, bad resource, unknown resource types, etc.) */ katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } } @@ -1151,7 +1152,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx, * JIT IDs - atom is invalid. */ katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } #endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ @@ -1165,13 +1166,13 @@ static bool jd_submit_atom(struct kbase_context *const kctx, if ((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0) { if (!kbase_js_is_atom_valid(kctx->kbdev, katom)) { katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } } else { /* Soft-job */ if (kbase_prepare_soft_job(katom) != 0) { katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } } @@ -1193,7 +1194,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx, if (katom->core_req & BASE_JD_REQ_SOFT_JOB) { if (kbase_process_soft_job(katom) == 0) { kbase_finish_soft_job(katom); - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } return false; } @@ -1223,7 +1224,7 @@ static bool jd_submit_atom(struct kbase_context *const kctx, } /* This is a pure dependency. Resolve it immediately */ - return jd_done_nolock(katom, true); + return kbase_jd_done_nolock(katom, true); } int kbase_jd_submit(struct kbase_context *kctx, @@ -1482,8 +1483,8 @@ void kbase_jd_done_worker(struct work_struct *data) kbasep_js_remove_job(kbdev, kctx, katom); mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); mutex_unlock(&js_devdata->queue_mutex); - /* jd_done_nolock() requires the jsctx_mutex lock to be dropped */ - jd_done_nolock(katom, false); + /* kbase_jd_done_nolock() requires the jsctx_mutex lock to be dropped */ + kbase_jd_done_nolock(katom, false); /* katom may have been freed now, do not use! */ @@ -1549,7 +1550,7 @@ void kbase_jd_done_worker(struct work_struct *data) kbase_js_sched_all(kbdev); if (!atomic_dec_return(&kctx->work_count)) { - /* If worker now idle then post all events that jd_done_nolock() + /* If worker now idle then post all events that kbase_jd_done_nolock() * has queued */ mutex_lock(&jctx->lock); @@ -1623,7 +1624,7 @@ static void jd_cancel_worker(struct work_struct *data) mutex_lock(&jctx->lock); - need_to_try_schedule_context = jd_done_nolock(katom, true); + need_to_try_schedule_context = kbase_jd_done_nolock(katom, true); /* Because we're zapping, we're not adding any more jobs to this ctx, so no need to * schedule the context. There's also no need for the jsctx_mutex to have been taken * around this too. @@ -1667,6 +1668,8 @@ void kbase_jd_done(struct kbase_jd_atom *katom, int slot_nr, kbdev = kctx->kbdev; KBASE_DEBUG_ASSERT(kbdev); + lockdep_assert_held(&kbdev->hwaccess_lock); + if (done_code & KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT) katom->event_code = BASE_JD_EVENT_REMOVED_FROM_NEXT; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c index 3b9d6ebf8652..87c92330dfe2 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c @@ -72,9 +72,7 @@ static void kbase_jd_debugfs_fence_info(struct kbase_jd_atom *atom, #endif seq_printf(sfile, -#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE) - "Sd(%u#%u: %s) ", -#elif (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE) +#if (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE) "Sd(%llu#%u: %s) ", #else "Sd(%llu#%llu: %s) ", @@ -93,9 +91,7 @@ static void kbase_jd_debugfs_fence_info(struct kbase_jd_atom *atom, #endif seq_printf(sfile, -#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE) - "Wd(%u#%u: %s) ", -#elif (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE) +#if (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE) "Wd(%llu#%u: %s) ", #else "Wd(%llu#%llu: %s) ", @@ -230,11 +226,7 @@ static const struct file_operations kbasep_jd_debugfs_atoms_fops = { void kbasep_jd_debugfs_ctx_init(struct kbase_context *kctx) { -#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE) const mode_t mode = 0444; -#else - const mode_t mode = 0400; -#endif /* Caller already ensures this, but we keep the pattern for * maintenance safety. diff --git a/drivers/gpu/arm/bifrost/mali_kbase_js.c b/drivers/gpu/arm/bifrost/mali_kbase_js.c index 4d3812711718..1991bfa9532d 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_js.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_js.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2011-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2011-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -4021,13 +4021,16 @@ base_jd_prio kbase_js_priority_check(struct kbase_device *kbdev, base_jd_prio pr { struct priority_control_manager_device *pcm_device = kbdev->pcm_dev; int req_priority, out_priority; - base_jd_prio out_jd_priority = priority; - if (pcm_device) { - req_priority = kbasep_js_atom_prio_to_sched_prio(priority); - out_priority = pcm_device->ops.pcm_scheduler_priority_check(pcm_device, current, req_priority); - out_jd_priority = kbasep_js_sched_prio_to_atom_prio(out_priority); - } - return out_jd_priority; + req_priority = kbasep_js_atom_prio_to_sched_prio(priority); + out_priority = req_priority; + /* Does not use pcm defined priority check if PCM not defined or if + * kbasep_js_atom_prio_to_sched_prio returns an error + * (KBASE_JS_ATOM_SCHED_PRIO_INVALID). + */ + if (pcm_device && (req_priority != KBASE_JS_ATOM_SCHED_PRIO_INVALID)) + out_priority = pcm_device->ops.pcm_scheduler_priority_check(pcm_device, current, + req_priority); + return kbasep_js_sched_prio_to_atom_prio(kbdev, out_priority); } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.c b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.c index 6ebd35b73a8b..78fa6f37ef6c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.c @@ -45,6 +45,7 @@ #include #include #include +#include #include /* Define static_assert(). @@ -60,10 +61,6 @@ #define __static_assert(e, msg, ...) _Static_assert(e, msg) #endif -#if KERNEL_VERSION(4, 16, 0) >= LINUX_VERSION_CODE -typedef unsigned int __poll_t; -#endif - #ifndef ENOTSUP #define ENOTSUP EOPNOTSUPP #endif @@ -637,11 +634,11 @@ static __poll_t reader_poll(struct file *const file, struct reader_changes *changes; if (unlikely(!file || !wait)) - return -EINVAL; + return (__poll_t)-EINVAL; reader = file->private_data; if (unlikely(!reader)) - return -EBADF; + return (__poll_t)-EBADF; changes = &reader->changes; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.h b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.h index 6e9a8d23ec10..9451d4cd943d 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2019-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -71,8 +71,6 @@ #else /* empty wrapper macros for userspace */ #define static_branch_unlikely(key) (1) -#define KERNEL_VERSION(a, b, c) (0) -#define LINUX_VERSION_CODE (1) #endif /* __KERNEL__ */ /* Forward declarations */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.c b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.c index 17e12e5eb208..81758c32259c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.c @@ -36,6 +36,7 @@ #include #include #include +#include #include /* The minimum allowed interval between dumps, in nanoseconds @@ -226,25 +227,19 @@ static struct prfcnt_enum_item kinstr_prfcnt_supported_requests[] = { * Return: POLLIN if data can be read without blocking, 0 if data can not be * read without blocking, else error code. */ -#if KERNEL_VERSION(4, 16, 0) >= LINUX_VERSION_CODE -static unsigned int -kbasep_kinstr_prfcnt_hwcnt_reader_poll(struct file *filp, - struct poll_table_struct *wait) -#else static __poll_t kbasep_kinstr_prfcnt_hwcnt_reader_poll(struct file *filp, struct poll_table_struct *wait) -#endif { struct kbase_kinstr_prfcnt_client *cli; if (!filp || !wait) - return -EINVAL; + return (__poll_t)-EINVAL; cli = filp->private_data; if (!cli) - return -EINVAL; + return (__poll_t)-EINVAL; poll_wait(filp, &cli->waitq, wait); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem.c b/drivers/gpu/arm/bifrost/mali_kbase_mem.c index 878cad62d580..e0785793e26a 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem.c @@ -1802,9 +1802,8 @@ int kbase_gpu_mmap(struct kbase_context *kctx, struct kbase_va_region *reg, return err; bad_insert: - kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu, - reg->start_pfn, reg->nr_pages, - kctx->as_nr); + kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu, reg->start_pfn, alloc->pages, + reg->nr_pages, kctx->as_nr); kbase_remove_va_region(kctx->kbdev, reg); @@ -1819,6 +1818,7 @@ static void kbase_jd_user_buf_unmap(struct kbase_context *kctx, int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg) { int err = 0; + struct kbase_mem_phy_alloc *alloc; if (reg->start_pfn == 0) return 0; @@ -1826,11 +1826,12 @@ int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg) if (!reg->gpu_alloc) return -EINVAL; + alloc = reg->gpu_alloc; + /* Tear down GPU page tables, depending on memory type. */ - switch (reg->gpu_alloc->type) { + switch (alloc->type) { case KBASE_MEM_TYPE_ALIAS: { size_t i = 0; - struct kbase_mem_phy_alloc *alloc = reg->gpu_alloc; /* Due to the way the number of valid PTEs and ATEs are tracked * currently, only the GPU virtual range that is backed & mapped @@ -1842,9 +1843,8 @@ int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg) if (alloc->imported.alias.aliased[i].alloc) { int err_loop = kbase_mmu_teardown_pages( kctx->kbdev, &kctx->mmu, - reg->start_pfn + - (i * - alloc->imported.alias.stride), + reg->start_pfn + (i * alloc->imported.alias.stride), + alloc->pages + (i * alloc->imported.alias.stride), alloc->imported.alias.aliased[i].length, kctx->as_nr); if (WARN_ON_ONCE(err_loop)) @@ -1854,39 +1854,37 @@ int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg) } break; case KBASE_MEM_TYPE_IMPORTED_UMM: - err = kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu, - reg->start_pfn, reg->nr_pages, kctx->as_nr); + err = kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu, reg->start_pfn, + alloc->pages, reg->nr_pages, kctx->as_nr); break; default: - err = kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu, - reg->start_pfn, kbase_reg_current_backed_size(reg), - kctx->as_nr); + err = kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu, reg->start_pfn, + alloc->pages, kbase_reg_current_backed_size(reg), + kctx->as_nr); break; } /* Update tracking, and other cleanup, depending on memory type. */ - switch (reg->gpu_alloc->type) { + switch (alloc->type) { case KBASE_MEM_TYPE_ALIAS: /* We mark the source allocs as unmapped from the GPU when * putting reg's allocs */ break; case KBASE_MEM_TYPE_IMPORTED_USER_BUF: { - struct kbase_alloc_import_user_buf *user_buf = - ®->gpu_alloc->imported.user_buf; + struct kbase_alloc_import_user_buf *user_buf = &alloc->imported.user_buf; - if (user_buf->current_mapping_usage_count & PINNED_ON_IMPORT) { - user_buf->current_mapping_usage_count &= - ~PINNED_ON_IMPORT; + if (user_buf->current_mapping_usage_count & PINNED_ON_IMPORT) { + user_buf->current_mapping_usage_count &= ~PINNED_ON_IMPORT; - /* The allocation could still have active mappings. */ - if (user_buf->current_mapping_usage_count == 0) { - kbase_jd_user_buf_unmap(kctx, reg->gpu_alloc, - (reg->flags & (KBASE_REG_CPU_WR | - KBASE_REG_GPU_WR))); - } + /* The allocation could still have active mappings. */ + if (user_buf->current_mapping_usage_count == 0) { + kbase_jd_user_buf_unmap(kctx, alloc, + (reg->flags & + (KBASE_REG_CPU_WR | KBASE_REG_GPU_WR))); } } + } fallthrough; default: kbase_mem_phy_alloc_gpu_unmapped(reg->gpu_alloc); @@ -3687,12 +3685,7 @@ void kbase_jit_debugfs_init(struct kbase_context *kctx) /* prevent unprivileged use of debug file system * in old kernel version */ -#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE) - /* only for newer kernel version debug file system is safe */ const mode_t mode = 0444; -#else - const mode_t mode = 0400; -#endif /* Caller already ensures this, but we keep the pattern for * maintenance safety. @@ -4809,18 +4802,7 @@ int kbase_jd_user_buf_pin_pages(struct kbase_context *kctx, write = reg->flags & (KBASE_REG_CPU_WR | KBASE_REG_GPU_WR); -#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE - pinned_pages = get_user_pages(NULL, mm, address, alloc->imported.user_buf.nr_pages, -#if KERNEL_VERSION(4, 4, 168) <= LINUX_VERSION_CODE && \ -KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE - write ? FOLL_WRITE : 0, pages, NULL); -#else - write, 0, pages, NULL); -#endif -#elif KERNEL_VERSION(4, 9, 0) > LINUX_VERSION_CODE - pinned_pages = get_user_pages_remote(NULL, mm, address, alloc->imported.user_buf.nr_pages, - write, 0, pages, NULL); -#elif KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE +#if KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE pinned_pages = get_user_pages_remote(NULL, mm, address, alloc->imported.user_buf.nr_pages, write ? FOLL_WRITE : 0, pages, NULL); #elif KERNEL_VERSION(5, 9, 0) > LINUX_VERSION_CODE @@ -5056,12 +5038,10 @@ void kbase_unmap_external_resource(struct kbase_context *kctx, if (!kbase_is_region_invalid_or_free(reg) && reg->gpu_alloc == alloc) - kbase_mmu_teardown_pages( - kctx->kbdev, - &kctx->mmu, - reg->start_pfn, - kbase_reg_current_backed_size(reg), - kctx->as_nr); + kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu, reg->start_pfn, + alloc->pages, + kbase_reg_current_backed_size(reg), + kctx->as_nr); if (reg && ((reg->flags & (KBASE_REG_CPU_WR | KBASE_REG_GPU_WR)) == 0)) writeable = false; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c index 6e3898ecedda..c373cf82ea37 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c @@ -31,9 +31,6 @@ #include #include #include -#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE) -#include -#endif /* LINUX_VERSION_CODE < 4.8.0 */ #include #include #include @@ -104,6 +101,23 @@ static int kbase_mem_shrink_gpu_mapping(struct kbase_context *kctx, struct kbase_va_region *reg, u64 new_pages, u64 old_pages); +static bool is_process_exiting(struct vm_area_struct *vma) +{ + /* PF_EXITING flag can't be reliably used here for the detection + * of process exit, as 'mm_users' counter could still be non-zero + * when all threads of the process have exited. Later when the + * thread (which took a reference on the 'mm' of process that + * exited) drops it reference, the vm_ops->close method would be + * called for all the vmas (owned by 'mm' of process that exited) + * but the PF_EXITING flag may not be neccessarily set for the + * thread at that time. + */ + if (atomic_read(&vma->vm_mm->mm_users)) + return false; + + return true; +} + /* Retrieve the associated region pointer if the GPU address corresponds to * one of the event memory pages. The enclosing region, if found, shouldn't * have been marked as free. @@ -1103,19 +1117,7 @@ int kbase_mem_do_sync_imported(struct kbase_context *kctx, ret = 0; } #else - /* Though the below version check could be superfluous depending upon the version condition - * used for enabling KBASE_MEM_ION_SYNC_WORKAROUND, we still keep this check here to allow - * ease of modification for non-ION systems or systems where ION has been patched. - */ -#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE && !defined(CONFIG_CHROMEOS) - dma_buf_end_cpu_access(dma_buf, - 0, dma_buf->size, - dir); - ret = 0; -#else - ret = dma_buf_end_cpu_access(dma_buf, - dir); -#endif + ret = dma_buf_end_cpu_access(dma_buf, dir); #endif /* KBASE_MEM_ION_SYNC_WORKAROUND */ break; case KBASE_SYNC_TO_CPU: @@ -1132,11 +1134,7 @@ int kbase_mem_do_sync_imported(struct kbase_context *kctx, ret = 0; } #else - ret = dma_buf_begin_cpu_access(dma_buf, -#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE && !defined(CONFIG_CHROMEOS) - 0, dma_buf->size, -#endif - dir); + ret = dma_buf_begin_cpu_access(dma_buf, dir); #endif /* KBASE_MEM_ION_SYNC_WORKAROUND */ break; } @@ -1315,11 +1313,8 @@ int kbase_mem_umm_map(struct kbase_context *kctx, return 0; bad_pad_insert: - kbase_mmu_teardown_pages(kctx->kbdev, - &kctx->mmu, - reg->start_pfn, - alloc->nents, - kctx->as_nr); + kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu, reg->start_pfn, alloc->pages, + alloc->nents, kctx->as_nr); bad_insert: kbase_mem_umm_unmap_attachment(kctx, alloc); bad_map_attachment: @@ -1347,11 +1342,8 @@ void kbase_mem_umm_unmap(struct kbase_context *kctx, if (!kbase_is_region_invalid_or_free(reg) && reg->gpu_alloc == alloc) { int err; - err = kbase_mmu_teardown_pages(kctx->kbdev, - &kctx->mmu, - reg->start_pfn, - reg->nr_pages, - kctx->as_nr); + err = kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu, reg->start_pfn, + alloc->pages, reg->nr_pages, kctx->as_nr); WARN_ON(err); } @@ -1669,18 +1661,7 @@ static struct kbase_va_region *kbase_mem_from_user_buffer( write = reg->flags & (KBASE_REG_CPU_WR | KBASE_REG_GPU_WR); -#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE - faulted_pages = get_user_pages(current, current->mm, address, *va_pages, -#if KERNEL_VERSION(4, 4, 168) <= LINUX_VERSION_CODE && \ -KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE - write ? FOLL_WRITE : 0, pages, NULL); -#else - write, 0, pages, NULL); -#endif -#elif KERNEL_VERSION(4, 9, 0) > LINUX_VERSION_CODE - faulted_pages = get_user_pages(address, *va_pages, - write, 0, pages, NULL); -#elif KERNEL_VERSION(5, 9, 0) > LINUX_VERSION_CODE +#if KERNEL_VERSION(5, 9, 0) > LINUX_VERSION_CODE faulted_pages = get_user_pages(address, *va_pages, write ? FOLL_WRITE : 0, pages, NULL); #else @@ -2193,10 +2174,11 @@ static int kbase_mem_shrink_gpu_mapping(struct kbase_context *const kctx, u64 const new_pages, u64 const old_pages) { u64 delta = old_pages - new_pages; + struct kbase_mem_phy_alloc *alloc = reg->gpu_alloc; int ret = 0; - ret = kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu, - reg->start_pfn + new_pages, delta, kctx->as_nr); + ret = kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu, reg->start_pfn + new_pages, + alloc->pages + new_pages, delta, kctx->as_nr); return ret; } @@ -2414,7 +2396,7 @@ static void kbase_cpu_vm_close(struct vm_area_struct *vma) /* Avoid freeing memory on the process death which results in * GPU Page Fault. Memory will be freed in kbase_destroy_context */ - if (!(current->flags & PF_EXITING)) + if (!is_process_exiting(vma)) kbase_mem_free_region(map->kctx, map->region); } @@ -3314,7 +3296,7 @@ static void kbase_csf_user_io_pages_vm_close(struct vm_area_struct *vma) reset_prevented = true; mutex_lock(&kctx->csf.lock); - kbase_csf_queue_unbind(queue); + kbase_csf_queue_unbind(queue, is_process_exiting(vma)); mutex_unlock(&kctx->csf.lock); if (reset_prevented) @@ -3355,13 +3337,6 @@ static vm_fault_t kbase_csf_user_io_pages_vm_fault(struct vm_fault *vmf) /* Always map the doorbell page as uncached */ doorbell_pgprot = pgprot_device(vma->vm_page_prot); -#if ((KERNEL_VERSION(4, 4, 147) >= LINUX_VERSION_CODE) || \ - ((KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE) && \ - (KERNEL_VERSION(4, 5, 0) <= LINUX_VERSION_CODE))) - vma->vm_page_prot = doorbell_pgprot; - input_page_pgprot = doorbell_pgprot; - output_page_pgprot = doorbell_pgprot; -#else if (kbdev->system_coherency == COHERENCY_NONE) { input_page_pgprot = pgprot_writecombine(vma->vm_page_prot); output_page_pgprot = pgprot_writecombine(vma->vm_page_prot); @@ -3369,7 +3344,6 @@ static vm_fault_t kbase_csf_user_io_pages_vm_fault(struct vm_fault *vmf) input_page_pgprot = vma->vm_page_prot; output_page_pgprot = vma->vm_page_prot; } -#endif doorbell_cpu_addr = vma->vm_start; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h index 1f6877aff758..5e5d991105a6 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h @@ -439,18 +439,7 @@ u32 kbase_get_cache_line_alignment(struct kbase_device *kbdev); static inline vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, pgprot_t pgprot) { - int err; - -#if ((KERNEL_VERSION(4, 4, 147) >= LINUX_VERSION_CODE) || \ - ((KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE) && \ - (KERNEL_VERSION(4, 5, 0) <= LINUX_VERSION_CODE))) - if (pgprot_val(pgprot) != pgprot_val(vma->vm_page_prot)) - return VM_FAULT_SIGBUS; - - err = vm_insert_pfn(vma, addr, pfn); -#else - err = vm_insert_pfn_prot(vma, addr, pfn, pgprot); -#endif + int err = vm_insert_pfn_prot(vma, addr, pfn, pgprot); if (unlikely(err == -ENOMEM)) return VM_FAULT_OOM; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.c index cfb43b029c6c..3b1b2bae15c8 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_debugfs.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2014-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -168,13 +168,7 @@ static const struct file_operations kbase_mem_pool_debugfs_max_size_fops = { void kbase_mem_pool_debugfs_init(struct dentry *parent, struct kbase_context *kctx) { - /* prevent unprivileged use of debug file in old kernel version */ -#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE) - /* only for newer kernel version debug file system is safe */ const mode_t mode = 0644; -#else - const mode_t mode = 0600; -#endif debugfs_create_file("mem_pool_size", mode, parent, &kctx->mem_pools.small, &kbase_mem_pool_debugfs_fops); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.c index 92ab1b8ffd2a..9317023b71bb 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs.c @@ -69,11 +69,7 @@ static const struct file_operations kbasep_mem_profile_debugfs_fops = { int kbasep_mem_profile_debugfs_insert(struct kbase_context *kctx, char *data, size_t size) { -#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE) const mode_t mode = 0444; -#else - const mode_t mode = 0400; -#endif int err = 0; mutex_lock(&kctx->mem_profile_lock); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_native_mgm.c b/drivers/gpu/arm/bifrost/mali_kbase_native_mgm.c index 4554bee783e7..10a7f506b1a4 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_native_mgm.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_native_mgm.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2019-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -140,6 +140,30 @@ kbase_native_mgm_update_gpu_pte(struct memory_group_manager_device *mgm_dev, return pte; } +/** + * kbase_native_mgm_pte_to_original_pte - Native method to undo changes done in + * kbase_native_mgm_update_gpu_pte() + * + * @mgm_dev: The memory group manager the request is being made through. + * @group_id: A physical memory group ID, which must be valid but is not used. + * Its valid range is 0 .. MEMORY_GROUP_MANAGER_NR_GROUPS-1. + * @mmu_level: The level of the MMU page table where the page is getting mapped. + * @pte: The prepared page table entry. + * + * This function simply returns the @pte without modification. + * + * Return: A GPU page table entry to be stored in a page table. + */ +static u64 kbase_native_mgm_pte_to_original_pte(struct memory_group_manager_device *mgm_dev, + int group_id, int mmu_level, u64 pte) +{ + CSTD_UNUSED(mgm_dev); + CSTD_UNUSED(group_id); + CSTD_UNUSED(mmu_level); + + return pte; +} + struct memory_group_manager_device kbase_native_mgm_dev = { .ops = { .mgm_alloc_page = kbase_native_mgm_alloc, @@ -147,6 +171,7 @@ struct memory_group_manager_device kbase_native_mgm_dev = { .mgm_get_import_memory_id = NULL, .mgm_vmf_insert_pfn_prot = kbase_native_mgm_vmf_insert_pfn_prot, .mgm_update_gpu_pte = kbase_native_mgm_update_gpu_pte, + .mgm_pte_to_original_pte = kbase_native_mgm_pte_to_original_pte, }, .data = NULL }; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_pbha_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_pbha_debugfs.c index 47eab63456f4..4130dd609157 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_pbha_debugfs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_pbha_debugfs.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2021-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -120,14 +120,10 @@ static const struct file_operations pbha_int_id_overrides_fops = { void kbase_pbha_debugfs_init(struct kbase_device *kbdev) { if (kbasep_pbha_supported(kbdev)) { -#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE) - /* only for newer kernel version debug file system is safe */ const mode_t mode = 0644; -#else - const mode_t mode = 0600; -#endif struct dentry *debugfs_pbha_dir = debugfs_create_dir( "pbha", kbdev->mali_debugfs_directory); + if (IS_ERR_OR_NULL(debugfs_pbha_dir)) { dev_err(kbdev->dev, "Couldn't create mali debugfs page-based hardware attributes directory\n"); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c b/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c index 78ab1c6a6bab..5808a2e893cc 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2011-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2011-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -213,7 +213,7 @@ void kbase_soft_event_wait_callback(struct kbase_jd_atom *katom) mutex_lock(&kctx->jctx.lock); kbasep_remove_waiting_soft_job(katom); kbase_finish_soft_job(katom); - if (jd_done_nolock(katom, true)) + if (kbase_jd_done_nolock(katom, true)) kbase_js_sched_all(kctx->kbdev); mutex_unlock(&kctx->jctx.lock); } @@ -227,7 +227,7 @@ static void kbasep_soft_event_complete_job(struct work_struct *work) int resched; mutex_lock(&kctx->jctx.lock); - resched = jd_done_nolock(katom, true); + resched = kbase_jd_done_nolock(katom, true); mutex_unlock(&kctx->jctx.lock); if (resched) @@ -498,7 +498,7 @@ out: static void kbasep_soft_event_cancel_job(struct kbase_jd_atom *katom) { katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - if (jd_done_nolock(katom, true)) + if (kbase_jd_done_nolock(katom, true)) kbase_js_sched_all(katom->kctx->kbdev); } @@ -810,11 +810,7 @@ int kbase_mem_copy_from_extres(struct kbase_context *kctx, dma_to_copy = min(dma_buf->size, (size_t)(buf_data->nr_extres_pages * PAGE_SIZE)); - ret = dma_buf_begin_cpu_access(dma_buf, -#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE && !defined(CONFIG_CHROMEOS) - 0, dma_to_copy, -#endif - DMA_FROM_DEVICE); + ret = dma_buf_begin_cpu_access(dma_buf, DMA_FROM_DEVICE); if (ret) goto out_unlock; @@ -841,11 +837,7 @@ int kbase_mem_copy_from_extres(struct kbase_context *kctx, break; } } - dma_buf_end_cpu_access(dma_buf, -#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE && !defined(CONFIG_CHROMEOS) - 0, dma_to_copy, -#endif - DMA_FROM_DEVICE); + dma_buf_end_cpu_access(dma_buf, DMA_FROM_DEVICE); break; } default: @@ -1355,7 +1347,7 @@ static void kbasep_jit_finish_worker(struct work_struct *work) mutex_lock(&kctx->jctx.lock); kbase_finish_soft_job(katom); - resched = jd_done_nolock(katom, true); + resched = kbase_jd_done_nolock(katom, true); mutex_unlock(&kctx->jctx.lock); if (resched) @@ -1786,7 +1778,7 @@ void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev) if (kbase_process_soft_job(katom_iter) == 0) { kbase_finish_soft_job(katom_iter); - resched |= jd_done_nolock(katom_iter, true); + resched |= kbase_jd_done_nolock(katom_iter, true); #ifdef CONFIG_MALI_ARBITER_SUPPORT atomic_dec(&kbdev->pm.gpu_users_waiting); #endif /* CONFIG_MALI_ARBITER_SUPPORT */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c b/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c index 8a8ea126aa70..8c5cb6c3838e 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2012-2017, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2012-2017, 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -248,22 +248,17 @@ int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int tl_fd) /* create a fd representing the fence */ fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC); if (fd < 0) { + sync_pt_free(pt); sync_fence_put(fence); + katom->fence = NULL; goto out; } + /* Place the successfully created fence in katom */ + katom->fence = fence; + /* bind fence to the new fd */ sync_fence_install(fence, fd); - - katom->fence = sync_fence_fdget(fd); - if (katom->fence == NULL) { - /* The only way the fence can be NULL is if userspace closed it - * for us, so we don't need to clear it up - */ - fd = -EINVAL; - goto out; - } - out: fput(tl_file); @@ -445,7 +440,7 @@ void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom) kbasep_remove_waiting_soft_job(katom); kbase_finish_soft_job(katom); - if (jd_done_nolock(katom, true)) + if (kbase_jd_done_nolock(katom, true)) kbase_js_sched_all(katom->kctx->kbdev); } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c b/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c index fca80e452c60..e08a87210fbc 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2012-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2012-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -262,7 +262,7 @@ void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom) kbasep_remove_waiting_soft_job(katom); kbase_finish_soft_job(katom); - if (jd_done_nolock(katom, true)) + if (kbase_jd_done_nolock(katom, true)) kbase_js_sched_all(katom->kctx->kbdev); } @@ -309,10 +309,7 @@ void kbase_sync_fence_info_get(struct dma_fence *fence, info->status = 0; /* still active (unsignaled) */ } -#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE) - scnprintf(info->name, sizeof(info->name), "%u#%u", - fence->context, fence->seqno); -#elif (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE) +#if (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE) scnprintf(info->name, sizeof(info->name), "%llu#%u", fence->context, fence->seqno); #else diff --git a/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c b/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c index 34d0359eb2d9..abcf53041069 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c @@ -38,6 +38,7 @@ #include #include #include +#include #include /* Hwcnt reader API version */ @@ -113,9 +114,7 @@ struct kbase_vinstr_client { wait_queue_head_t waitq; }; -static unsigned int kbasep_vinstr_hwcnt_reader_poll( - struct file *filp, - poll_table *wait); +static __poll_t kbasep_vinstr_hwcnt_reader_poll(struct file *filp, poll_table *wait); static long kbasep_vinstr_hwcnt_reader_ioctl( struct file *filp, @@ -1038,18 +1037,16 @@ static long kbasep_vinstr_hwcnt_reader_ioctl( * Return: POLLIN if data can be read without blocking, 0 if data can not be * read without blocking, else error code. */ -static unsigned int kbasep_vinstr_hwcnt_reader_poll( - struct file *filp, - poll_table *wait) +static __poll_t kbasep_vinstr_hwcnt_reader_poll(struct file *filp, poll_table *wait) { struct kbase_vinstr_client *cli; if (!filp || !wait) - return -EINVAL; + return (__poll_t)-EINVAL; cli = filp->private_data; if (!cli) - return -EINVAL; + return (__poll_t)-EINVAL; poll_wait(filp, &cli->waitq, wait); if (kbasep_vinstr_hwcnt_reader_buffer_ready(cli)) diff --git a/drivers/gpu/arm/bifrost/mmu/backend/mali_kbase_mmu_csf.c b/drivers/gpu/arm/bifrost/mmu/backend/mali_kbase_mmu_csf.c index c9ba3fcb91f5..04f5cdf42b84 100644 --- a/drivers/gpu/arm/bifrost/mmu/backend/mali_kbase_mmu_csf.c +++ b/drivers/gpu/arm/bifrost/mmu/backend/mali_kbase_mmu_csf.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2019-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -152,8 +152,8 @@ void kbase_gpu_report_bus_fault_and_kill(struct kbase_context *kctx, /* terminal fault, print info about the fault */ dev_err(kbdev->dev, - "GPU bus fault in AS%d at VA 0x%016llX\n" - "VA_VALID: %s\n" + "GPU bus fault in AS%d at PA 0x%016llX\n" + "PA_VALID: %s\n" "raw fault status: 0x%X\n" "exception type 0x%X: %s\n" "access type 0x%X: %s\n" diff --git a/drivers/gpu/arm/bifrost/mmu/backend/mali_kbase_mmu_jm.c b/drivers/gpu/arm/bifrost/mmu/backend/mali_kbase_mmu_jm.c index fad55540feb1..3130b332dec2 100644 --- a/drivers/gpu/arm/bifrost/mmu/backend/mali_kbase_mmu_jm.c +++ b/drivers/gpu/arm/bifrost/mmu/backend/mali_kbase_mmu_jm.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2019-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -66,7 +66,7 @@ void kbase_gpu_report_bus_fault_and_kill(struct kbase_context *kctx, /* terminal fault, print info about the fault */ dev_err(kbdev->dev, - "GPU bus fault in AS%d at VA 0x%016llX\n" + "GPU bus fault in AS%d at PA 0x%016llX\n" "raw fault status: 0x%X\n" "exception type 0x%X: %s\n" "exception data 0x%X\n" diff --git a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.c b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.c index 9bc15097540e..fc7c8923ab07 100644 --- a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.c +++ b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.c @@ -49,6 +49,25 @@ #include #include +/* Threshold used to decide whether to flush full caches or just a physical range */ +#define KBASE_PA_RANGE_THRESHOLD_NR_PAGES 20 +#define MGM_DEFAULT_PTE_GROUP (0) + +/* Macro to convert updated PDGs to flags indicating levels skip in flush */ +#define pgd_level_to_skip_flush(dirty_pgds) (~(dirty_pgds) & 0xF) + +/* Small wrapper function to factor out GPU-dependent context releasing */ +static void release_ctx(struct kbase_device *kbdev, + struct kbase_context *kctx) +{ +#if MALI_USE_CSF + CSTD_UNUSED(kbdev); + kbase_ctx_sched_release_ctx_lock(kctx); +#else /* MALI_USE_CSF */ + kbasep_js_runpool_release_ctx(kbdev, kctx); +#endif /* MALI_USE_CSF */ +} + static void mmu_hw_operation_begin(struct kbase_device *kbdev) { #if !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) @@ -109,112 +128,227 @@ static bool mmu_flush_cache_on_gpu_ctrl(struct kbase_device *kbdev) } /** - * mmu_flush_invalidate_on_gpu_ctrl() - Flush and invalidate the GPU caches - * through GPU_CONTROL interface. - * @kbdev: kbase device to issue the MMU operation on. - * @as: address space to issue the MMU operation on. - * @op_param: parameters for the operation. + * mmu_flush_pa_range() - Flush physical address range * - * This wrapper function alternates AS_COMMAND_FLUSH_PT and AS_COMMAND_FLUSH_MEM - * to equivalent GPU_CONTROL command FLUSH_CACHES. - * The function first issue LOCK to MMU-AS with kbase_mmu_hw_do_operation(). - * And issues cache-flush with kbase_gpu_cache_flush_and_busy_wait() function - * then issue UNLOCK to MMU-AS with kbase_mmu_hw_do_operation(). + * @kbdev: kbase device to issue the MMU operation on. + * @phys: Starting address of the physical range to start the operation on. + * @nr_bytes: Number of bytes to work on. + * @op: Type of cache flush operation to perform. * - * Return: Zero if the operation was successful, non-zero otherwise. + * Issue a cache flush physical range command. */ -static int -mmu_flush_invalidate_on_gpu_ctrl(struct kbase_device *kbdev, - struct kbase_as *as, - struct kbase_mmu_hw_op_param *op_param) + +/** + * mmu_invalidate() - Perform an invalidate operation on MMU caches. + * @kbdev: The Kbase device. + * @kctx: The Kbase context. + * @as_nr: GPU address space number for which invalidate is required. + * @op_param: Non-NULL pointer to struct containing information about the MMU + * operation to perform. + * + * Perform an MMU invalidate operation on a particual address space + * by issuing a UNLOCK command. + */ +static void mmu_invalidate(struct kbase_device *kbdev, struct kbase_context *kctx, int as_nr, + const struct kbase_mmu_hw_op_param *op_param) { - u32 flush_op; - int ret, ret2; + int err = 0; + unsigned long flags; - if (WARN_ON(kbdev == NULL) || - WARN_ON(as == NULL) || - WARN_ON(op_param == NULL)) - return -EINVAL; + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - lockdep_assert_held(&kbdev->hwaccess_lock); - lockdep_assert_held(&kbdev->mmu_hw_mutex); - - /* Translate operation to command */ - if (op_param->op == KBASE_MMU_OP_FLUSH_PT) { - flush_op = GPU_COMMAND_CACHE_CLN_INV_L2; - } else if (op_param->op == KBASE_MMU_OP_FLUSH_MEM) { - flush_op = GPU_COMMAND_CACHE_CLN_INV_L2_LSC; - } else { - dev_warn(kbdev->dev, "Invalid flush request (op = %d)\n", - op_param->op); - return -EINVAL; + if (kbdev->pm.backend.gpu_powered && (!kctx || kctx->as_nr >= 0)) { + as_nr = kctx ? kctx->as_nr : as_nr; + err = kbase_mmu_hw_do_unlock(kbdev, &kbdev->as[as_nr], op_param); } - /* 1. Issue MMU_AS_CONTROL.COMMAND.LOCK operation. */ - op_param->op = KBASE_MMU_OP_LOCK; - ret = kbase_mmu_hw_do_operation(kbdev, as, op_param); - if (ret) - return ret; + if (err) { + dev_err(kbdev->dev, + "Invalidate after GPU page table update did not complete. Issuing GPU soft-reset to recover"); + if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) + kbase_reset_gpu(kbdev); + } - /* 2. Issue GPU_CONTROL.COMMAND.FLUSH_CACHES operation */ - ret = kbase_gpu_cache_flush_and_busy_wait(kbdev, flush_op); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} - /* 3. Issue MMU_AS_CONTROL.COMMAND.UNLOCK operation. */ - op_param->op = KBASE_MMU_OP_UNLOCK; - ret2 = kbase_mmu_hw_do_operation(kbdev, as, op_param); +/* Perform a flush/invalidate on a particular address space + */ +static void mmu_flush_invalidate_as(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param) +{ + int err; + bool gpu_powered; + unsigned long flags; - return ret ?: ret2; + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + gpu_powered = kbdev->pm.backend.gpu_powered; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + /* GPU is off so there's no need to perform flush/invalidate. + * But even if GPU is not actually powered down, after gpu_powered flag + * was set to false, it is still safe to skip the flush/invalidate. + * The TLB invalidation will anyways be performed due to AS_COMMAND_UPDATE + * which is sent when address spaces are restored after gpu_powered flag + * is set to true. Flushing of L2 cache is certainly not required as L2 + * cache is definitely off if gpu_powered is false. + */ + if (!gpu_powered) + return; + + if (kbase_pm_context_active_handle_suspend(kbdev, + KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { + /* GPU has just been powered off due to system suspend. + * So again, no need to perform flush/invalidate. + */ + return; + } + + /* AS transaction begin */ + mutex_lock(&kbdev->mmu_hw_mutex); + + mmu_hw_operation_begin(kbdev); + err = kbase_mmu_hw_do_flush(kbdev, as, op_param); + mmu_hw_operation_end(kbdev); + + if (err) { + /* Flush failed to complete, assume the GPU has hung and + * perform a reset to recover. + */ + dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issuing GPU soft-reset to recover"); + + if (kbase_prepare_to_reset_gpu( + kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) + kbase_reset_gpu(kbdev); + } + + mutex_unlock(&kbdev->mmu_hw_mutex); + /* AS transaction end */ + + kbase_pm_context_idle(kbdev); } /** - * kbase_mmu_flush_invalidate() - Flush and invalidate the GPU caches. - * @kctx: The KBase context. - * @vpfn: The virtual page frame number to start the flush on. - * @nr: The number of pages to flush. - * @sync: Set if the operation should be synchronous or not. + * mmu_flush_invalidate() - Perform a flush operation on GPU caches. + * @kbdev: The Kbase device. + * @kctx: The Kbase context. + * @as_nr: GPU address space number for which flush + invalidate is required. + * @op_param: Non-NULL pointer to struct containing information about the MMU + * operation to perform. * - * Issue a cache flush + invalidate to the GPU caches and invalidate the TLBs. + * This function performs the cache flush operation described by @op_param. + * The function retains a reference to the given @kctx and releases it + * after performing the flush operation. * - * If sync is not set then transactions still in flight when the flush is issued - * may use the old page tables and the data they write will not be written out - * to memory, this function returns after the flush has been issued but - * before all accesses which might effect the flushed region have completed. + * If operation is set to KBASE_MMU_OP_FLUSH_PT then this function will issue + * a cache flush + invalidate to the L2 caches and invalidate the TLBs. * - * If sync is set then accesses in the flushed region will be drained - * before data is flush and invalidated through L1, L2 and into memory, - * after which point this function will return. - * @mmu_sync_info: Indicates whether this call is synchronous wrt MMU ops. + * If operation is set to KBASE_MMU_OP_FLUSH_MEM then this function will issue + * a cache flush + invalidate to the L2 and GPU Load/Store caches as well as + * invalidating the TLBs. + * + * If operation is set to KBASE_MMU_OP_UNLOCK then this function will only + * invalidate the MMU caches and TLBs. */ -static void -kbase_mmu_flush_invalidate(struct kbase_context *kctx, u64 vpfn, size_t nr, - bool sync, - enum kbase_caller_mmu_sync_info mmu_sync_info); +static void mmu_flush_invalidate(struct kbase_device *kbdev, struct kbase_context *kctx, int as_nr, + const struct kbase_mmu_hw_op_param *op_param) +{ + bool ctx_is_in_runpool; + + /* Early out if there is nothing to do */ + if (op_param->nr == 0) + return; + + /* If no context is provided then MMU operation is performed on address + * space which does not belong to user space context. Otherwise, retain + * refcount to context provided and release after flush operation. + */ + if (!kctx) { + mmu_flush_invalidate_as(kbdev, &kbdev->as[as_nr], op_param); + } else { +#if !MALI_USE_CSF + mutex_lock(&kbdev->js_data.queue_mutex); + ctx_is_in_runpool = kbase_ctx_sched_inc_refcount(kctx); + mutex_unlock(&kbdev->js_data.queue_mutex); +#else + ctx_is_in_runpool = kbase_ctx_sched_inc_refcount_if_as_valid(kctx); +#endif /* !MALI_USE_CSF */ + + if (ctx_is_in_runpool) { + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + mmu_flush_invalidate_as(kbdev, &kbdev->as[kctx->as_nr], op_param); + + release_ctx(kbdev, kctx); + } + } +} /** - * kbase_mmu_flush_invalidate_no_ctx() - Flush and invalidate the GPU caches. - * @kbdev: Device pointer. - * @vpfn: The virtual page frame number to start the flush on. - * @nr: The number of pages to flush. - * @sync: Set if the operation should be synchronous or not. - * @as_nr: GPU address space number for which flush + invalidate is required. - * @mmu_sync_info: Indicates whether this call is synchronous wrt MMU ops. + * mmu_flush_invalidate_on_gpu_ctrl() - Perform a flush operation on GPU caches via + * the GPU_CONTROL interface + * @kbdev: The Kbase device. + * @kctx: The Kbase context. + * @as_nr: GPU address space number for which flush + invalidate is required. + * @op_param: Non-NULL pointer to struct containing information about the MMU + * operation to perform. * - * This is used for MMU tables which do not belong to a user space context. + * Perform a flush/invalidate on a particular address space via the GPU_CONTROL + * interface. */ -static void kbase_mmu_flush_invalidate_no_ctx( - struct kbase_device *kbdev, u64 vpfn, size_t nr, bool sync, int as_nr, - enum kbase_caller_mmu_sync_info mmu_sync_info); +static void mmu_flush_invalidate_on_gpu_ctrl(struct kbase_device *kbdev, struct kbase_context *kctx, + int as_nr, const struct kbase_mmu_hw_op_param *op_param) +{ + int err = 0; + unsigned long flags; + + /* AS transaction begin */ + mutex_lock(&kbdev->mmu_hw_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + if (kbdev->pm.backend.gpu_powered && (!kctx || kctx->as_nr >= 0)) { + as_nr = kctx ? kctx->as_nr : as_nr; + err = kbase_mmu_hw_do_flush_on_gpu_ctrl(kbdev, &kbdev->as[as_nr], + op_param); + } + + if (err) { + /* Flush failed to complete, assume the GPU has hung and + * perform a reset to recover. + */ + dev_err(kbdev->dev, + "Flush for GPU page table update did not complete. Issuing GPU soft-reset to recover\n"); + + if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) + kbase_reset_gpu(kbdev); + } + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); +} /** * kbase_mmu_sync_pgd() - sync page directory to memory when needed. - * @kbdev: Device pointer. - * @handle: Address of DMA region. - * @size: Size of the region to sync. + * @kbdev: Device pointer. + * @kctx: Context pointer. + * @phys: Starting physical address of the destination region. + * @handle: Address of DMA region. + * @size: Size of the region to sync. + * @flush_op: MMU cache flush operation to perform on the physical address + * range, if GPU control is available. + * + * This function is called whenever the association between a virtual address + * range and a physical address range changes, because a mapping is created or + * destroyed. + * One of the effects of this operation is performing an MMU cache flush + * operation only on the physical address range affected by this function, if + * GPU control is available. * * This should be called after each page directory update. */ -static void kbase_mmu_sync_pgd(struct kbase_device *kbdev, - dma_addr_t handle, size_t size) +static void kbase_mmu_sync_pgd(struct kbase_device *kbdev, struct kbase_context *kctx, + phys_addr_t phys, dma_addr_t handle, size_t size, + enum kbase_mmu_op_type flush_op) { /* In non-coherent system, ensure the GPU can read * the pages from memory @@ -222,6 +356,7 @@ static void kbase_mmu_sync_pgd(struct kbase_device *kbdev, if (kbdev->system_coherency == COHERENCY_NONE) dma_sync_single_for_device(kbdev->dev, handle, size, DMA_TO_DEVICE); + } /* @@ -234,23 +369,25 @@ static void kbase_mmu_sync_pgd(struct kbase_device *kbdev, */ static int kbase_mmu_update_pages_no_flush(struct kbase_context *kctx, u64 vpfn, - struct tagged_addr *phys, size_t nr, - unsigned long flags, int group_id); + struct tagged_addr *phys, size_t nr, unsigned long flags, + int group_id, u64 *dirty_pgds); /** * kbase_mmu_update_and_free_parent_pgds() - Update number of valid entries and * free memory of the page directories * - * @kbdev: Device pointer. - * @mmut: GPU MMU page table. - * @pgds: Physical addresses of page directories to be freed. - * @vpfn: The virtual page frame number. - * @level: The level of MMU page table. + * @kbdev: Device pointer. + * @mmut: GPU MMU page table. + * @pgds: Physical addresses of page directories to be freed. + * @vpfn: The virtual page frame number. + * @level: The level of MMU page table. + * @flush_op: The type of MMU flush operation to perform. + * @dirty_pgds: Flags to track every level where a PGD has been updated. */ static void kbase_mmu_update_and_free_parent_pgds(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, - phys_addr_t *pgds, u64 vpfn, - int level); + struct kbase_mmu_table *mmut, phys_addr_t *pgds, + u64 vpfn, int level, + enum kbase_mmu_op_type flush_op, u64 *dirty_pgds); /** * kbase_mmu_free_pgd() - Free memory of the page directory * @@ -345,8 +482,10 @@ static size_t reg_grow_calc_extra_pages(struct kbase_device *kbdev, static void kbase_gpu_mmu_handle_write_faulting_as(struct kbase_device *kbdev, struct kbase_as *faulting_as, u64 start_pfn, size_t nr, - u32 kctx_id) + u32 kctx_id, u64 dirty_pgds) { + int err; + /* Calls to this function are inherently synchronous, with respect to * MMU operations. */ @@ -359,22 +498,23 @@ static void kbase_gpu_mmu_handle_write_faulting_as(struct kbase_device *kbdev, KBASE_MMU_FAULT_TYPE_PAGE); /* flush L2 and unlock the VA (resumes the MMU) */ - op_param = (struct kbase_mmu_hw_op_param){ - .vpfn = start_pfn, - .nr = nr, - .op = KBASE_MMU_OP_FLUSH_PT, - .kctx_id = kctx_id, - .mmu_sync_info = mmu_sync_info, - }; + op_param.vpfn = start_pfn; + op_param.nr = nr; + op_param.op = KBASE_MMU_OP_FLUSH_PT; + op_param.kctx_id = kctx_id; + op_param.mmu_sync_info = mmu_sync_info; if (mmu_flush_cache_on_gpu_ctrl(kbdev)) { unsigned long irq_flags; spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); - mmu_flush_invalidate_on_gpu_ctrl(kbdev, faulting_as, &op_param); + op_param.flush_skip_levels = + pgd_level_to_skip_flush(dirty_pgds); + err = kbase_mmu_hw_do_flush_on_gpu_ctrl(kbdev, faulting_as, + &op_param); spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); } else { mmu_hw_operation_begin(kbdev); - kbase_mmu_hw_do_operation(kbdev, faulting_as, &op_param); + err = kbase_mmu_hw_do_flush(kbdev, faulting_as, &op_param); mmu_hw_operation_end(kbdev); } @@ -414,6 +554,7 @@ static void kbase_gpu_mmu_handle_write_fault(struct kbase_context *kctx, u64 fault_pfn, pfn_offset; int ret; int as_no; + u64 dirty_pgds = 0; as_no = faulting_as->number; kbdev = container_of(faulting_as, struct kbase_device, as[as_no]); @@ -472,12 +613,11 @@ static void kbase_gpu_mmu_handle_write_fault(struct kbase_context *kctx, } /* Now make this faulting page writable to GPU. */ - ret = kbase_mmu_update_pages_no_flush(kctx, fault_pfn, - fault_phys_addr, - 1, region->flags, region->gpu_alloc->group_id); + ret = kbase_mmu_update_pages_no_flush(kctx, fault_pfn, fault_phys_addr, 1, region->flags, + region->gpu_alloc->group_id, &dirty_pgds); kbase_gpu_mmu_handle_write_faulting_as(kbdev, faulting_as, fault_pfn, 1, - kctx->id); + kctx->id, dirty_pgds); kbase_gpu_vm_unlock(kctx); } @@ -712,18 +852,6 @@ static bool page_fault_try_alloc(struct kbase_context *kctx, return true; } -/* Small wrapper function to factor out GPU-dependent context releasing */ -static void release_ctx(struct kbase_device *kbdev, - struct kbase_context *kctx) -{ -#if MALI_USE_CSF - CSTD_UNUSED(kbdev); - kbase_ctx_sched_release_ctx_lock(kctx); -#else /* MALI_USE_CSF */ - kbasep_js_runpool_release_ctx(kbdev, kctx); -#endif /* MALI_USE_CSF */ -} - void kbase_mmu_page_fault_worker(struct work_struct *data) { u64 fault_pfn; @@ -938,16 +1066,29 @@ page_fault_retry: * transaction (which should cause the other page fault to be * raised again). */ - op_param = (struct kbase_mmu_hw_op_param){ - .vpfn = 0, - .nr = 0, - .op = KBASE_MMU_OP_UNLOCK, - .kctx_id = kctx->id, - .mmu_sync_info = mmu_sync_info, - }; - mmu_hw_operation_begin(kbdev); - kbase_mmu_hw_do_operation(kbdev, faulting_as, &op_param); - mmu_hw_operation_end(kbdev); + op_param.mmu_sync_info = mmu_sync_info; + op_param.kctx_id = kctx->id; + if (!mmu_flush_cache_on_gpu_ctrl(kbdev)) { + mmu_hw_operation_begin(kbdev); + err = kbase_mmu_hw_do_unlock_no_addr(kbdev, faulting_as, + &op_param); + mmu_hw_operation_end(kbdev); + } else { + /* Can safely skip the invalidate for all levels in case + * of duplicate page faults. + */ + op_param.flush_skip_levels = 0xF; + op_param.vpfn = fault_pfn; + op_param.nr = 1; + err = kbase_mmu_hw_do_unlock(kbdev, faulting_as, + &op_param); + } + + if (err) { + dev_err(kbdev->dev, + "Invalidation for MMU did not complete on handling page fault @ 0x%llx", + fault->addr); + } mutex_unlock(&kbdev->mmu_hw_mutex); @@ -975,16 +1116,29 @@ page_fault_retry: KBASE_MMU_FAULT_TYPE_PAGE); /* See comment [1] about UNLOCK usage */ - op_param = (struct kbase_mmu_hw_op_param){ - .vpfn = 0, - .nr = 0, - .op = KBASE_MMU_OP_UNLOCK, - .kctx_id = kctx->id, - .mmu_sync_info = mmu_sync_info, - }; - mmu_hw_operation_begin(kbdev); - kbase_mmu_hw_do_operation(kbdev, faulting_as, &op_param); - mmu_hw_operation_end(kbdev); + op_param.mmu_sync_info = mmu_sync_info; + op_param.kctx_id = kctx->id; + if (!mmu_flush_cache_on_gpu_ctrl(kbdev)) { + mmu_hw_operation_begin(kbdev); + err = kbase_mmu_hw_do_unlock_no_addr(kbdev, faulting_as, + &op_param); + mmu_hw_operation_end(kbdev); + } else { + /* Can safely skip the invalidate for all levels in case + * of duplicate page faults. + */ + op_param.flush_skip_levels = 0xF; + op_param.vpfn = fault_pfn; + op_param.nr = 1; + err = kbase_mmu_hw_do_unlock(kbdev, faulting_as, + &op_param); + } + + if (err) { + dev_err(kbdev->dev, + "Invalidation for MMU did not complete on handling page fault @ 0x%llx", + fault->addr); + } mutex_unlock(&kbdev->mmu_hw_mutex); @@ -1009,6 +1163,7 @@ page_fault_retry: spin_unlock(&kctx->mem_partials_lock); if (grown) { + u64 dirty_pgds = 0; u64 pfn_offset; struct kbase_mmu_hw_op_param op_param; @@ -1027,9 +1182,10 @@ page_fault_retry: * us to unlock the MMU as we see fit. */ err = kbase_mmu_insert_pages_no_flush(kbdev, &kctx->mmu, - region->start_pfn + pfn_offset, - &kbase_get_gpu_phy_pages(region)[pfn_offset], - new_pages, region->flags, region->gpu_alloc->group_id); + region->start_pfn + pfn_offset, + &kbase_get_gpu_phy_pages(region)[pfn_offset], + new_pages, region->flags, + region->gpu_alloc->group_id, &dirty_pgds); if (err) { kbase_free_phy_pages_helper(region->gpu_alloc, new_pages); @@ -1084,25 +1240,22 @@ page_fault_retry: kbase_mmu_hw_clear_fault(kbdev, faulting_as, KBASE_MMU_FAULT_TYPE_PAGE); - /* flush L2 and unlock the VA (resumes the MMU) */ - op_param = (struct kbase_mmu_hw_op_param){ - .vpfn = fault->addr >> PAGE_SHIFT, - .nr = new_pages, - .op = KBASE_MMU_OP_FLUSH_PT, - .kctx_id = kctx->id, - .mmu_sync_info = mmu_sync_info, - }; + op_param.vpfn = region->start_pfn + pfn_offset; + op_param.nr = new_pages; + op_param.op = KBASE_MMU_OP_FLUSH_PT; + op_param.kctx_id = kctx->id; + op_param.mmu_sync_info = mmu_sync_info; if (mmu_flush_cache_on_gpu_ctrl(kbdev)) { - unsigned long irq_flags; - - spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); - err = mmu_flush_invalidate_on_gpu_ctrl(kbdev, faulting_as, - &op_param); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); + /* Unlock to invalidate the TLB (and resume the MMU) */ + op_param.flush_skip_levels = + pgd_level_to_skip_flush(dirty_pgds); + err = kbase_mmu_hw_do_unlock(kbdev, faulting_as, + &op_param); } else { + /* flush L2 and unlock the VA (resumes the MMU) */ mmu_hw_operation_begin(kbdev); - err = kbase_mmu_hw_do_operation(kbdev, faulting_as, - &op_param); + err = kbase_mmu_hw_do_flush(kbdev, faulting_as, + &op_param); mmu_hw_operation_end(kbdev); } @@ -1221,6 +1374,7 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev, u64 *page; int i; struct page *p; + phys_addr_t pgd; p = kbase_mem_pool_alloc(&kbdev->mem_pools.small[mmut->group_id]); if (!p) @@ -1230,6 +1384,8 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev, if (page == NULL) goto alloc_free; + pgd = page_to_phys(p); + /* If the MMU tables belong to a context then account the memory usage * to that context, otherwise the MMU tables are device wide and are * only accounted to the device. @@ -1253,10 +1409,13 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev, for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) kbdev->mmu_mode->entry_invalidate(&page[i]); - kbase_mmu_sync_pgd(kbdev, kbase_dma_addr(p), PAGE_SIZE); + /* MMU cache flush strategy is NONE because this page is newly created, therefore + * there is no content to clean or invalidate in the GPU caches. + */ + kbase_mmu_sync_pgd(kbdev, mmut->kctx, pgd, kbase_dma_addr(p), PAGE_SIZE, KBASE_MMU_OP_NONE); kunmap(p); - return page_to_phys(p); + return pgd; alloc_free: kbase_mem_pool_free(&kbdev->mem_pools.small[mmut->group_id], p, false); @@ -1267,9 +1426,9 @@ alloc_free: /* Given PGD PFN for level N, return PGD PFN for level N+1, allocating the * new table from the pool if needed and possible */ -static int mmu_get_next_pgd(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, - phys_addr_t *pgd, u64 vpfn, int level) +static int mmu_get_next_pgd(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, + phys_addr_t *pgd, u64 vpfn, int level, bool *newly_created_pgd, + u64 *dirty_pgds) { u64 *page; phys_addr_t target_pgd; @@ -1293,9 +1452,14 @@ static int mmu_get_next_pgd(struct kbase_device *kbdev, return -EINVAL; } - target_pgd = kbdev->mmu_mode->pte_to_phy_addr(page[vpfn]); + target_pgd = kbdev->mmu_mode->pte_to_phy_addr( + kbdev->mgm_dev->ops.mgm_pte_to_original_pte( + kbdev->mgm_dev, MGM_DEFAULT_PTE_GROUP, level, page[vpfn])); if (!target_pgd) { + enum kbase_mmu_op_type flush_op = KBASE_MMU_OP_NONE; + unsigned int current_valid_entries; + u64 managed_pte; target_pgd = kbase_mmu_alloc_pgd(kbdev, mmut); if (!target_pgd) { dev_dbg(kbdev->dev, "%s: kbase_mmu_alloc_pgd failure\n", @@ -1304,10 +1468,31 @@ static int mmu_get_next_pgd(struct kbase_device *kbdev, return -ENOMEM; } - kbdev->mmu_mode->entry_set_pte(page, vpfn, target_pgd); + current_valid_entries = kbdev->mmu_mode->get_num_valid_entries(page); + kbdev->mmu_mode->entry_set_pte(&managed_pte, target_pgd); + page[vpfn] = kbdev->mgm_dev->ops.mgm_update_gpu_pte( + kbdev->mgm_dev, MGM_DEFAULT_PTE_GROUP, level, managed_pte); + kbdev->mmu_mode->set_num_valid_entries(page, current_valid_entries + 1); - kbase_mmu_sync_pgd(kbdev, kbase_dma_addr(p), PAGE_SIZE); /* Rely on the caller to update the address space flags. */ + if (newly_created_pgd && !*newly_created_pgd) { + *newly_created_pgd = true; + /* If code reaches here we know parent PGD of target PGD was + * not newly created and should be flushed. + */ + flush_op = KBASE_MMU_OP_FLUSH_PT; + + if (dirty_pgds) + *dirty_pgds |= 1ULL << level; + } + + /* MMU cache flush strategy is FLUSH_PT because a new entry is added + * to an existing PGD which may be stored in GPU caches and needs a + * "clean" operation. An "invalidation" operation is not required here + * as this entry points to a new page and cannot be present in GPU + * caches. + */ + kbase_mmu_sync_pgd(kbdev, mmut->kctx, *pgd, kbase_dma_addr(p), PAGE_SIZE, flush_op); } kunmap(p); @@ -1319,11 +1504,9 @@ static int mmu_get_next_pgd(struct kbase_device *kbdev, /* * Returns the PGD for the specified level of translation */ -static int mmu_get_pgd_at_level(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, - u64 vpfn, - int level, - phys_addr_t *out_pgd) +static int mmu_get_pgd_at_level(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, u64 vpfn, + int level, phys_addr_t *out_pgd, bool *newly_created_pgd, + u64 *dirty_pgds) { phys_addr_t pgd; int l; @@ -1332,7 +1515,8 @@ static int mmu_get_pgd_at_level(struct kbase_device *kbdev, pgd = mmut->pgd; for (l = MIDGARD_MMU_TOPLEVEL; l < level; l++) { - int err = mmu_get_next_pgd(kbdev, mmut, &pgd, vpfn, l); + int err = + mmu_get_next_pgd(kbdev, mmut, &pgd, vpfn, l, newly_created_pgd, dirty_pgds); /* Handle failure condition */ if (err) { dev_dbg(kbdev->dev, @@ -1347,18 +1531,16 @@ static int mmu_get_pgd_at_level(struct kbase_device *kbdev, return 0; } -static int mmu_get_bottom_pgd(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, - u64 vpfn, - phys_addr_t *out_pgd) +static int mmu_get_bottom_pgd(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, u64 vpfn, + phys_addr_t *out_pgd, bool *newly_created_pgd, u64 *dirty_pgds) { - return mmu_get_pgd_at_level(kbdev, mmut, vpfn, MIDGARD_MMU_BOTTOMLEVEL, - out_pgd); + return mmu_get_pgd_at_level(kbdev, mmut, vpfn, MIDGARD_MMU_BOTTOMLEVEL, out_pgd, + newly_created_pgd, dirty_pgds); } static void mmu_insert_pages_failure_recovery(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, - u64 from_vpfn, u64 to_vpfn) + struct kbase_mmu_table *mmut, u64 from_vpfn, + u64 to_vpfn, u64 *dirty_pgds) { phys_addr_t pgd; u64 vpfn = from_vpfn; @@ -1398,7 +1580,8 @@ static void mmu_insert_pages_failure_recovery(struct kbase_device *kbdev, if (mmu_mode->ate_is_valid(page[idx], level)) break; /* keep the mapping */ kunmap(phys_to_page(pgd)); - pgd = mmu_mode->pte_to_phy_addr(page[idx]); + pgd = mmu_mode->pte_to_phy_addr(kbdev->mgm_dev->ops.mgm_pte_to_original_pte( + kbdev->mgm_dev, MGM_DEFAULT_PTE_GROUP, level, page[idx])); } switch (level) { @@ -1416,6 +1599,9 @@ static void mmu_insert_pages_failure_recovery(struct kbase_device *kbdev, goto next; } + if (dirty_pgds && pcount > 0) + *dirty_pgds |= 1ULL << level; + num_of_valid_entries = mmu_mode->get_num_valid_entries(page); if (WARN_ON_ONCE(num_of_valid_entries < pcount)) num_of_valid_entries = 0; @@ -1427,8 +1613,8 @@ static void mmu_insert_pages_failure_recovery(struct kbase_device *kbdev, kbase_mmu_free_pgd(kbdev, mmut, pgd, true); - kbase_mmu_update_and_free_parent_pgds(kbdev, mmut, pgds, - vpfn, level); + kbase_mmu_update_and_free_parent_pgds(kbdev, mmut, pgds, vpfn, level, + KBASE_MMU_OP_NONE, dirty_pgds); vpfn += count; continue; } @@ -1439,9 +1625,12 @@ static void mmu_insert_pages_failure_recovery(struct kbase_device *kbdev, mmu_mode->set_num_valid_entries(page, num_of_valid_entries); - kbase_mmu_sync_pgd(kbdev, - kbase_dma_addr(phys_to_page(pgd)) + 8 * idx, - 8 * pcount); + /* MMU cache flush strategy is NONE because GPU cache maintenance is + * going to be done by the caller + */ + kbase_mmu_sync_pgd(kbdev, mmut->kctx, pgd + (idx * sizeof(u64)), + kbase_dma_addr(phys_to_page(pgd)) + 8 * idx, 8 * pcount, + KBASE_MMU_OP_NONE); kunmap(phys_to_page(pgd)); next: vpfn += count; @@ -1467,6 +1656,9 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, size_t remain = nr; int err; struct kbase_device *kbdev; + enum kbase_mmu_op_type flush_op; + struct kbase_mmu_hw_op_param op_param; + u64 dirty_pgds = 0; if (WARN_ON(kctx == NULL)) return -EINVAL; @@ -1480,6 +1672,15 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, if (nr == 0) return 0; + /* Set up MMU flush operation parameters. */ + op_param = (struct kbase_mmu_hw_op_param){ + .vpfn = vpfn, + .nr = nr, + .op = KBASE_MMU_OP_FLUSH_PT, + .kctx_id = kctx->id, + .mmu_sync_info = mmu_sync_info, + }; + mutex_lock(&kctx->mmu.mmu_lock); while (remain) { @@ -1488,6 +1689,7 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; struct page *p; register unsigned int num_of_valid_entries; + bool newly_created_pgd = false; if (count > remain) count = remain; @@ -1500,8 +1702,8 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, * 256 pages at once (on average). Do we really care? */ do { - err = mmu_get_bottom_pgd(kbdev, &kctx->mmu, - vpfn, &pgd); + err = mmu_get_bottom_pgd(kbdev, &kctx->mmu, vpfn, &pgd, &newly_created_pgd, + &dirty_pgds); if (err != -ENOMEM) break; /* Fill the memory pool with enough pages for @@ -1521,10 +1723,9 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, /* Invalidate the pages we have partially * completed */ - mmu_insert_pages_failure_recovery(kbdev, - &kctx->mmu, - start_vpfn, - start_vpfn + recover_count); + mmu_insert_pages_failure_recovery(kbdev, &kctx->mmu, start_vpfn, + start_vpfn + recover_count, + &dirty_pgds); } goto fail_unlock; } @@ -1537,10 +1738,9 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, /* Invalidate the pages we have partially * completed */ - mmu_insert_pages_failure_recovery(kbdev, - &kctx->mmu, - start_vpfn, - start_vpfn + recover_count); + mmu_insert_pages_failure_recovery(kbdev, &kctx->mmu, start_vpfn, + start_vpfn + recover_count, + &dirty_pgds); } err = -ENOMEM; goto fail_unlock; @@ -1565,9 +1765,21 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, vpfn += count; remain -= count; - kbase_mmu_sync_pgd(kbdev, - kbase_dma_addr(p) + (index * sizeof(u64)), - count * sizeof(u64)); + if (count > 0 && !newly_created_pgd) + dirty_pgds |= 1ULL << MIDGARD_MMU_BOTTOMLEVEL; + + /* MMU cache flush operation here will depend on whether bottom level + * PGD is newly created or not. + * + * If bottom level PGD is newly created then no cache maintenance is + * required as the PGD will not exist in GPU cache. Otherwise GPU cache + * maintenance is required for existing PGD. + */ + flush_op = newly_created_pgd ? KBASE_MMU_OP_NONE : KBASE_MMU_OP_FLUSH_PT; + + kbase_mmu_sync_pgd(kbdev, kctx, pgd + (index * sizeof(u64)), + kbase_dma_addr(p) + (index * sizeof(u64)), count * sizeof(u64), + flush_op); kunmap(p); /* We have started modifying the page table. @@ -1578,12 +1790,25 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, recover_count += count; } mutex_unlock(&kctx->mmu.mmu_lock); - kbase_mmu_flush_invalidate(kctx, start_vpfn, nr, false, mmu_sync_info); + + op_param.flush_skip_levels = pgd_level_to_skip_flush(dirty_pgds); + /* If FLUSH_PA_RANGE is supported then existing PGDs will have been flushed + * and all that remains is TLB (or MMU cache) invalidation which is done via + * MMU UNLOCK command. + */ + if (mmu_flush_cache_on_gpu_ctrl(kbdev)) + mmu_invalidate(kbdev, kctx, kctx->as_nr, &op_param); + else + mmu_flush_invalidate(kbdev, kctx, kctx->as_nr, &op_param); return 0; fail_unlock: mutex_unlock(&kctx->mmu.mmu_lock); - kbase_mmu_flush_invalidate(kctx, start_vpfn, nr, false, mmu_sync_info); + op_param.flush_skip_levels = pgd_level_to_skip_flush(dirty_pgds); + if (mmu_flush_cache_on_gpu_ctrl(kbdev)) + mmu_flush_invalidate_on_gpu_ctrl(kbdev, kctx, kctx->as_nr, &op_param); + else + mmu_flush_invalidate(kbdev, kctx, kctx->as_nr, &op_param); return err; } @@ -1624,12 +1849,9 @@ u64 kbase_mmu_create_ate(struct kbase_device *const kbdev, group_id, level, entry); } -int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, - const u64 start_vpfn, - struct tagged_addr *phys, size_t nr, - unsigned long flags, - int const group_id) +int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, + const u64 start_vpfn, struct tagged_addr *phys, size_t nr, + unsigned long flags, int const group_id, u64 *dirty_pgds) { phys_addr_t pgd; u64 *pgd_page; @@ -1657,6 +1879,8 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, struct page *p; int cur_level; register unsigned int num_of_valid_entries; + enum kbase_mmu_op_type flush_op; + bool newly_created_pgd = false; if (count > remain) count = remain; @@ -1674,8 +1898,8 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, * 256 pages at once (on average). Do we really care? */ do { - err = mmu_get_pgd_at_level(kbdev, mmut, insert_vpfn, - cur_level, &pgd); + err = mmu_get_pgd_at_level(kbdev, mmut, insert_vpfn, cur_level, &pgd, + &newly_created_pgd, dirty_pgds); if (err != -ENOMEM) break; /* Fill the memory pool with enough pages for @@ -1689,14 +1913,13 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, } while (!err); if (err) { - dev_warn(kbdev->dev, - "%s: mmu_get_bottom_pgd failure\n", __func__); + dev_warn(kbdev->dev, "%s: mmu_get_pgd_at_level failure\n", __func__); if (insert_vpfn != start_vpfn) { /* Invalidate the pages we have partially * completed */ - mmu_insert_pages_failure_recovery(kbdev, - mmut, start_vpfn, insert_vpfn); + mmu_insert_pages_failure_recovery(kbdev, mmut, start_vpfn, + insert_vpfn, dirty_pgds); } goto fail_unlock; } @@ -1710,8 +1933,8 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, /* Invalidate the pages we have partially * completed */ - mmu_insert_pages_failure_recovery(kbdev, - mmut, start_vpfn, insert_vpfn); + mmu_insert_pages_failure_recovery(kbdev, mmut, start_vpfn, + insert_vpfn, dirty_pgds); } err = -ENOMEM; goto fail_unlock; @@ -1728,7 +1951,9 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, kbase_mmu_free_pgd( kbdev, mmut, kbdev->mmu_mode->pte_to_phy_addr( - *target), + kbdev->mgm_dev->ops.mgm_pte_to_original_pte( + kbdev->mgm_dev, MGM_DEFAULT_PTE_GROUP, + cur_level, *target)), false); num_of_valid_entries--; } @@ -1758,13 +1983,28 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, mmu_mode->set_num_valid_entries(pgd_page, num_of_valid_entries); + if (dirty_pgds && count > 0 && !newly_created_pgd) + *dirty_pgds |= 1ULL << cur_level; + phys += count; insert_vpfn += count; remain -= count; - kbase_mmu_sync_pgd(kbdev, - kbase_dma_addr(p) + (vindex * sizeof(u64)), - count * sizeof(u64)); + /* For the most part, the creation of a new virtual memory mapping does + * not require cache flush operations, because the operation results + * into the creation of new memory pages which are not present in GPU + * caches. Therefore the defaul operation is NONE. + * + * However, it is quite common for the mapping to start and/or finish + * at an already existing PGD. Moreover, the PTEs modified are not + * necessarily aligned with GPU cache lines. Therefore, GPU cache + * maintenance is required for existing PGDs. + */ + flush_op = newly_created_pgd ? KBASE_MMU_OP_NONE : KBASE_MMU_OP_FLUSH_PT; + + kbase_mmu_sync_pgd(kbdev, mmut->kctx, pgd + (vindex * sizeof(u64)), + kbase_dma_addr(p) + (vindex * sizeof(u64)), count * sizeof(u64), + flush_op); kunmap(p); } @@ -1787,16 +2027,35 @@ int kbase_mmu_insert_pages(struct kbase_device *kbdev, enum kbase_caller_mmu_sync_info mmu_sync_info) { int err; + struct kbase_mmu_hw_op_param op_param = { 0 }; + u64 dirty_pgds = 0; - err = kbase_mmu_insert_pages_no_flush(kbdev, mmut, vpfn, - phys, nr, flags, group_id); + /* Early out if there is nothing to do */ + if (nr == 0) + return 0; - if (mmut->kctx) - kbase_mmu_flush_invalidate(mmut->kctx, vpfn, nr, false, - mmu_sync_info); + err = kbase_mmu_insert_pages_no_flush(kbdev, mmut, vpfn, phys, nr, flags, group_id, + &dirty_pgds); + + op_param.vpfn = vpfn; + op_param.nr = nr; + op_param.op = KBASE_MMU_OP_FLUSH_PT; + op_param.mmu_sync_info = mmu_sync_info; + op_param.kctx_id = mmut->kctx ? mmut->kctx->id : 0xFFFFFFFF; + op_param.flush_skip_levels = pgd_level_to_skip_flush(dirty_pgds); + + /* MMU cache flush strategy depends on whether GPU control commands for + * flushing physical address ranges are supported. The new physical pages + * are not present in GPU caches there for they don't need any cache + * maintenance, but PGDs in the page table may or may not be created anew. + * + * Operations that affect the whole GPU cache shall only be done if it's + * impossible to update physical ranges. + */ + if (mmu_flush_cache_on_gpu_ctrl(kbdev)) + mmu_invalidate(kbdev, mmut->kctx, as_nr, &op_param); else - kbase_mmu_flush_invalidate_no_ctx(kbdev, vpfn, nr, false, as_nr, - mmu_sync_info); + mmu_flush_invalidate(kbdev, mmut->kctx, as_nr, &op_param); return err; } @@ -1804,7 +2063,7 @@ int kbase_mmu_insert_pages(struct kbase_device *kbdev, KBASE_EXPORT_TEST_API(kbase_mmu_insert_pages); /** - * kbase_mmu_flush_invalidate_noretain() - Flush and invalidate the GPU caches + * kbase_mmu_flush_noretain() - Flush and invalidate the GPU caches * without retaining the kbase context. * @kctx: The KBase context. * @vpfn: The virtual page frame number to start the flush on. @@ -1813,17 +2072,15 @@ KBASE_EXPORT_TEST_API(kbase_mmu_insert_pages); * As per kbase_mmu_flush_invalidate but doesn't retain the kctx or do any * other locking. */ -static void kbase_mmu_flush_invalidate_noretain(struct kbase_context *kctx, - u64 vpfn, size_t nr) +static void kbase_mmu_flush_noretain(struct kbase_context *kctx, u64 vpfn, size_t nr) { struct kbase_device *kbdev = kctx->kbdev; - struct kbase_mmu_hw_op_param op_param; int err; - /* Calls to this function are inherently asynchronous, with respect to * MMU operations. */ const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_ASYNC; + struct kbase_mmu_hw_op_param op_param; lockdep_assert_held(&kctx->kbdev->hwaccess_lock); lockdep_assert_held(&kctx->kbdev->mmu_hw_mutex); @@ -1833,155 +2090,32 @@ static void kbase_mmu_flush_invalidate_noretain(struct kbase_context *kctx, return; /* flush L2 and unlock the VA (resumes the MMU) */ - op_param = (struct kbase_mmu_hw_op_param){ - .vpfn = vpfn, - .nr = nr, - .op = KBASE_MMU_OP_FLUSH_MEM, - .kctx_id = kctx->id, - .mmu_sync_info = mmu_sync_info, - }; - + op_param.vpfn = vpfn; + op_param.nr = nr; + op_param.op = KBASE_MMU_OP_FLUSH_MEM; + op_param.kctx_id = kctx->id; + op_param.mmu_sync_info = mmu_sync_info; if (mmu_flush_cache_on_gpu_ctrl(kbdev)) { - err = mmu_flush_invalidate_on_gpu_ctrl( - kbdev, &kbdev->as[kctx->as_nr], &op_param); + /* Value used to prevent skipping of any levels when flushing */ + op_param.flush_skip_levels = pgd_level_to_skip_flush(0xF); + err = kbase_mmu_hw_do_flush_on_gpu_ctrl(kbdev, &kbdev->as[kctx->as_nr], + &op_param); } else { - err = kbase_mmu_hw_do_operation(kbdev, &kbdev->as[kctx->as_nr], - &op_param); + err = kbase_mmu_hw_do_flush_locked(kbdev, &kbdev->as[kctx->as_nr], + &op_param); } if (err) { /* Flush failed to complete, assume the * GPU has hung and perform a reset to recover */ - dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issuing GPU soft-reset to recover\n"); + dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issuing GPU soft-reset to recover"); if (kbase_prepare_to_reset_gpu_locked(kbdev, RESET_FLAGS_NONE)) kbase_reset_gpu_locked(kbdev); } } -/* Perform a flush/invalidate on a particular address space - */ -static void -kbase_mmu_flush_invalidate_as(struct kbase_device *kbdev, struct kbase_as *as, - u64 vpfn, size_t nr, bool sync, u32 kctx_id, - enum kbase_caller_mmu_sync_info mmu_sync_info) -{ - int err; - bool gpu_powered; - unsigned long flags; - struct kbase_mmu_hw_op_param op_param; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - gpu_powered = kbdev->pm.backend.gpu_powered; - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - /* GPU is off so there's no need to perform flush/invalidate. - * But even if GPU is not actually powered down, after gpu_powered flag - * was set to false, it is still safe to skip the flush/invalidate. - * The TLB invalidation will anyways be performed due to AS_COMMAND_UPDATE - * which is sent when address spaces are restored after gpu_powered flag - * is set to true. Flushing of L2 cache is certainly not required as L2 - * cache is definitely off if gpu_powered is false. - */ - if (!gpu_powered) - return; - - if (kbase_pm_context_active_handle_suspend(kbdev, - KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { - /* GPU has just been powered off due to system suspend. - * So again, no need to perform flush/invalidate. - */ - return; - } - - /* AS transaction begin */ - mutex_lock(&kbdev->mmu_hw_mutex); - - op_param = (struct kbase_mmu_hw_op_param){ - .vpfn = vpfn, - .nr = nr, - .kctx_id = kctx_id, - .mmu_sync_info = mmu_sync_info, - }; - - if (sync) - op_param.op = KBASE_MMU_OP_FLUSH_MEM; - else - op_param.op = KBASE_MMU_OP_FLUSH_PT; - - if (mmu_flush_cache_on_gpu_ctrl(kbdev)) { - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - err = mmu_flush_invalidate_on_gpu_ctrl(kbdev, as, &op_param); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - } else { - mmu_hw_operation_begin(kbdev); - err = kbase_mmu_hw_do_operation(kbdev, as, &op_param); - mmu_hw_operation_end(kbdev); - } - - if (err) { - /* Flush failed to complete, assume the GPU has hung and - * perform a reset to recover - */ - dev_err(kbdev->dev, "Flush for GPU page table update did not complete. Issuing GPU soft-reset to recover\n"); - - if (kbase_prepare_to_reset_gpu( - kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) - kbase_reset_gpu(kbdev); - } - - mutex_unlock(&kbdev->mmu_hw_mutex); - /* AS transaction end */ - - kbase_pm_context_idle(kbdev); -} - -static void -kbase_mmu_flush_invalidate_no_ctx(struct kbase_device *kbdev, u64 vpfn, - size_t nr, bool sync, int as_nr, - enum kbase_caller_mmu_sync_info mmu_sync_info) -{ - /* Skip if there is nothing to do */ - if (nr) { - kbase_mmu_flush_invalidate_as(kbdev, &kbdev->as[as_nr], vpfn, - nr, sync, 0xFFFFFFFF, - mmu_sync_info); - } -} - -static void -kbase_mmu_flush_invalidate(struct kbase_context *kctx, u64 vpfn, size_t nr, - bool sync, - enum kbase_caller_mmu_sync_info mmu_sync_info) -{ - struct kbase_device *kbdev; - bool ctx_is_in_runpool; - - /* Early out if there is nothing to do */ - if (nr == 0) - return; - - kbdev = kctx->kbdev; -#if !MALI_USE_CSF - mutex_lock(&kbdev->js_data.queue_mutex); - ctx_is_in_runpool = kbase_ctx_sched_inc_refcount(kctx); - mutex_unlock(&kbdev->js_data.queue_mutex); -#else - ctx_is_in_runpool = kbase_ctx_sched_inc_refcount_if_as_valid(kctx); -#endif /* !MALI_USE_CSF */ - - if (ctx_is_in_runpool) { - KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); - - kbase_mmu_flush_invalidate_as(kbdev, &kbdev->as[kctx->as_nr], - vpfn, nr, sync, kctx->id, - mmu_sync_info); - - release_ctx(kbdev, kctx); - } -} - void kbase_mmu_update(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, int as_nr) @@ -2021,7 +2155,7 @@ void kbase_mmu_disable(struct kbase_context *kctx) * The job scheduler code will already be holding the locks and context * so just do the flush. */ - kbase_mmu_flush_invalidate_noretain(kctx, 0, ~0); + kbase_mmu_flush_noretain(kctx, 0, ~0); kctx->kbdev->mmu_mode->disable_as(kctx->kbdev, kctx->as_nr); #if !MALI_USE_CSF @@ -2037,9 +2171,9 @@ void kbase_mmu_disable(struct kbase_context *kctx) KBASE_EXPORT_TEST_API(kbase_mmu_disable); static void kbase_mmu_update_and_free_parent_pgds(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, - phys_addr_t *pgds, u64 vpfn, - int level) + struct kbase_mmu_table *mmut, phys_addr_t *pgds, + u64 vpfn, int level, + enum kbase_mmu_op_type flush_op, u64 *dirty_pgds) { int current_level; @@ -2051,6 +2185,10 @@ static void kbase_mmu_update_and_free_parent_pgds(struct kbase_device *kbdev, unsigned int current_valid_entries = kbdev->mmu_mode->get_num_valid_entries(current_page); + /* We need to track every level that needs updating */ + if (dirty_pgds) + *dirty_pgds |= 1ULL << current_level; + if (current_valid_entries == 1 && current_level != MIDGARD_MMU_LEVEL(0)) { kunmap(phys_to_page(pgds[current_level])); @@ -2067,11 +2205,10 @@ static void kbase_mmu_update_and_free_parent_pgds(struct kbase_device *kbdev, kbdev->mmu_mode->set_num_valid_entries( current_page, current_valid_entries); - kbase_mmu_sync_pgd(kbdev, - kbase_dma_addr(phys_to_page( - pgds[current_level])) + - 8 * index, - 8 * 1); + kbase_mmu_sync_pgd( + kbdev, mmut->kctx, pgds[current_level] + (index * sizeof(u64)), + kbase_dma_addr(phys_to_page(pgds[current_level])) + 8 * index, + 8 * 1, flush_op); kunmap(phys_to_page(pgds[current_level])); break; @@ -2079,7 +2216,53 @@ static void kbase_mmu_update_and_free_parent_pgds(struct kbase_device *kbdev, } } -/* +/** + * mmu_flush_invalidate_teardown_pages() - Perform flush operation after unmapping pages. + * + * @kbdev: Pointer to kbase device. + * @kctx: Pointer to kbase context. + * @as_nr: Address space number, for GPU cache maintenance operations + * that happen outside a specific kbase context. + * @phys: Array of physical pages to flush. + * @op_param: Non-NULL pointer to struct containing information about the flush + * operation to perform. + * + * This function will do one of three things: + * 1. Invalidate the MMU caches, followed by a partial GPU cache flush of the + * individual pages that were unmapped if feature is supported on GPU. + * 2. Perform a full GPU cache flush through the GPU_CONTROL interface if feature is + * supported on GPU or, + * 3. Perform a full GPU cache flush through the MMU_CONTROL interface. + */ +static void mmu_flush_invalidate_teardown_pages(struct kbase_device *kbdev, + struct kbase_context *kctx, int as_nr, + struct tagged_addr *phys, + struct kbase_mmu_hw_op_param *op_param) +{ + + if (!mmu_flush_cache_on_gpu_ctrl(kbdev)) { + mmu_flush_invalidate(kbdev, kctx, as_nr, op_param); + return; + } else if (op_param->op == KBASE_MMU_OP_FLUSH_MEM) { + mmu_flush_invalidate_on_gpu_ctrl(kbdev, kctx, as_nr, op_param); + return; + } + +} + +/** + * kbase_mmu_teardown_pages - Remove GPU virtual addresses from the MMU page table + * + * @kbdev: Pointer to kbase device. + * @mmut: Pointer to GPU MMU page table. + * @vpfn: Start page frame number of the GPU virtual pages to unmap. + * @phys: Array of physical pages currently mapped to the virtual + * pages to unmap, or NULL. This is only used for GPU cache + * maintenance. + * @nr: Number of pages to unmap. + * @as_nr: Address space number, for GPU cache maintenance operations + * that happen outside a specific kbase context. + * * We actually discard the ATE and free the page table pages if no valid entries * exist in PGD. * @@ -2088,15 +2271,26 @@ static void kbase_mmu_update_and_free_parent_pgds(struct kbase_device *kbdev, * These locks must be taken in the correct order with respect to others * already held by the caller. Refer to kbasep_js_runpool_release_ctx() for more * information. + * + * The @p phys pointer to physical pages is not necessary for unmapping virtual memory, + * but it is used for fine-grained GPU cache maintenance. If @p phys is NULL, + * GPU cache maintenance will be done as usual, that is invalidating the whole GPU caches + * instead of specific physical address ranges. + * + * Return: 0 on success, otherwise an error code. */ -int kbase_mmu_teardown_pages(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, u64 vpfn, size_t nr, int as_nr) +int kbase_mmu_teardown_pages(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, u64 vpfn, + struct tagged_addr *phys, size_t nr, int as_nr) { phys_addr_t pgd; u64 start_vpfn = vpfn; size_t requested_nr = nr; + enum kbase_mmu_op_type flush_op = KBASE_MMU_OP_NONE; struct kbase_mmu_mode const *mmu_mode; + struct kbase_mmu_hw_op_param op_param; + unsigned int i; int err = -EFAULT; + u64 dirty_pgds = 0; /* Calls to this function are inherently asynchronous, with respect to * MMU operations. @@ -2108,12 +2302,25 @@ int kbase_mmu_teardown_pages(struct kbase_device *kbdev, return 0; } + /* MMU cache flush strategy depends on the number of pages to unmap. In both cases + * the operation is invalidate but the granularity of cache maintenance may change + * according to the situation. + * + * If GPU control command operations are present and the number of pages is "small", + * then the optimal strategy is flushing on the physical address range of the pages + * which are affected by the operation. That implies both the PGDs which are modified + * or removed from the page table and the physical pages which are freed from memory. + * + * Otherwise, there's no alternative to invalidating the whole GPU cache. + */ + if (mmu_flush_cache_on_gpu_ctrl(kbdev) && phys && nr <= KBASE_PA_RANGE_THRESHOLD_NR_PAGES) + flush_op = KBASE_MMU_OP_FLUSH_PT; + mutex_lock(&mmut->mmu_lock); mmu_mode = kbdev->mmu_mode; while (nr) { - unsigned int i; unsigned int index = vpfn & 0x1FF; unsigned int count = KBASE_MMU_PAGE_ENTRIES - index; unsigned int pcount; @@ -2156,7 +2363,9 @@ int kbase_mmu_teardown_pages(struct kbase_device *kbdev, count = nr; goto next; } - next_pgd = mmu_mode->pte_to_phy_addr(page[index]); + next_pgd = mmu_mode->pte_to_phy_addr( + kbdev->mgm_dev->ops.mgm_pte_to_original_pte( + kbdev->mgm_dev, MGM_DEFAULT_PTE_GROUP, level, page[index])); pgds[level] = pgd; kunmap(phys_to_page(pgd)); pgd = next_pgd; @@ -2194,6 +2403,9 @@ int kbase_mmu_teardown_pages(struct kbase_device *kbdev, continue; } + if (pcount > 0) + dirty_pgds |= 1ULL << level; + num_of_valid_entries = mmu_mode->get_num_valid_entries(page); if (WARN_ON_ONCE(num_of_valid_entries < pcount)) num_of_valid_entries = 0; @@ -2205,8 +2417,8 @@ int kbase_mmu_teardown_pages(struct kbase_device *kbdev, kbase_mmu_free_pgd(kbdev, mmut, pgd, true); - kbase_mmu_update_and_free_parent_pgds(kbdev, mmut, pgds, - vpfn, level); + kbase_mmu_update_and_free_parent_pgds(kbdev, mmut, pgds, vpfn, level, + flush_op, &dirty_pgds); vpfn += count; nr -= count; @@ -2219,9 +2431,9 @@ int kbase_mmu_teardown_pages(struct kbase_device *kbdev, mmu_mode->set_num_valid_entries(page, num_of_valid_entries); - kbase_mmu_sync_pgd( - kbdev, kbase_dma_addr(phys_to_page(pgd)) + 8 * index, - 8 * pcount); + kbase_mmu_sync_pgd(kbdev, mmut->kctx, pgd + (index * sizeof(u64)), + kbase_dma_addr(phys_to_page(pgd)) + 8 * index, 8 * pcount, + flush_op); next: kunmap(phys_to_page(pgd)); vpfn += count; @@ -2230,14 +2442,17 @@ next: err = 0; out: mutex_unlock(&mmut->mmu_lock); - - if (mmut->kctx) - kbase_mmu_flush_invalidate(mmut->kctx, start_vpfn, requested_nr, - true, mmu_sync_info); - else - kbase_mmu_flush_invalidate_no_ctx(kbdev, start_vpfn, - requested_nr, true, as_nr, - mmu_sync_info); + /* Set up MMU operation parameters. See above about MMU cache flush strategy. */ + op_param = (struct kbase_mmu_hw_op_param){ + .vpfn = start_vpfn, + .nr = requested_nr, + .mmu_sync_info = mmu_sync_info, + .kctx_id = mmut->kctx ? mmut->kctx->id : 0xFFFFFFFF, + .op = (flush_op == KBASE_MMU_OP_FLUSH_PT) ? KBASE_MMU_OP_FLUSH_PT : + KBASE_MMU_OP_FLUSH_MEM, + .flush_skip_levels = pgd_level_to_skip_flush(dirty_pgds), + }; + mmu_flush_invalidate_teardown_pages(kbdev, mmut->kctx, as_nr, phys, &op_param); return err; } @@ -2257,6 +2472,7 @@ KBASE_EXPORT_TEST_API(kbase_mmu_teardown_pages); * @flags: Flags * @group_id: The physical memory group in which the page was allocated. * Valid range is 0..(MEMORY_GROUP_MANAGER_NR_GROUPS-1). + * @dirty_pgds: Flags to track every level where a PGD has been updated. * * This will update page table entries that already exist on the GPU based on * the new flags that are passed (the physical pages pointed to by the page @@ -2269,8 +2485,8 @@ KBASE_EXPORT_TEST_API(kbase_mmu_teardown_pages); * successfully, otherwise an error code. */ static int kbase_mmu_update_pages_no_flush(struct kbase_context *kctx, u64 vpfn, - struct tagged_addr *phys, size_t nr, - unsigned long flags, int const group_id) + struct tagged_addr *phys, size_t nr, unsigned long flags, + int const group_id, u64 *dirty_pgds) { phys_addr_t pgd; u64 *pgd_page; @@ -2304,7 +2520,8 @@ static int kbase_mmu_update_pages_no_flush(struct kbase_context *kctx, u64 vpfn, if (is_huge(*phys) && (index == index_in_large_page(*phys))) cur_level = MIDGARD_MMU_LEVEL(2); - err = mmu_get_pgd_at_level(kbdev, &kctx->mmu, vpfn, cur_level, &pgd); + err = mmu_get_pgd_at_level(kbdev, &kctx->mmu, vpfn, cur_level, &pgd, NULL, + dirty_pgds); if (WARN_ON(err)) goto fail_unlock; @@ -2331,9 +2548,9 @@ static int kbase_mmu_update_pages_no_flush(struct kbase_context *kctx, u64 vpfn, pgd_page[level_index] = kbase_mmu_create_ate(kbdev, *target_phys, flags, MIDGARD_MMU_LEVEL(2), group_id); - kbase_mmu_sync_pgd(kbdev, - kbase_dma_addr(p) + (level_index * sizeof(u64)), - sizeof(u64)); + kbase_mmu_sync_pgd(kbdev, kctx, pgd + (level_index * sizeof(u64)), + kbase_dma_addr(p) + (level_index * sizeof(u64)), + sizeof(u64), KBASE_MMU_OP_NONE); } else { for (i = 0; i < count; i++) { #ifdef CONFIG_MALI_BIFROST_DEBUG @@ -2345,14 +2562,21 @@ static int kbase_mmu_update_pages_no_flush(struct kbase_context *kctx, u64 vpfn, phys[i], flags, MIDGARD_MMU_BOTTOMLEVEL, group_id); } - kbase_mmu_sync_pgd(kbdev, - kbase_dma_addr(p) + (index * sizeof(u64)), - count * sizeof(u64)); + + /* MMU cache flush strategy is NONE because GPU cache maintenance + * will be done by the caller. + */ + kbase_mmu_sync_pgd(kbdev, kctx, pgd + (index * sizeof(u64)), + kbase_dma_addr(p) + (index * sizeof(u64)), + count * sizeof(u64), KBASE_MMU_OP_NONE); } kbdev->mmu_mode->set_num_valid_entries(pgd_page, num_of_valid_entries); + if (dirty_pgds && count > 0) + *dirty_pgds |= 1ULL << cur_level; + phys += count; vpfn += count; nr -= count; @@ -2373,15 +2597,29 @@ int kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn, unsigned long flags, int const group_id) { int err; + struct kbase_mmu_hw_op_param op_param; + u64 dirty_pgds = 0; /* Calls to this function are inherently asynchronous, with respect to * MMU operations. */ const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_ASYNC; - err = kbase_mmu_update_pages_no_flush(kctx, vpfn, phys, nr, flags, - group_id); - kbase_mmu_flush_invalidate(kctx, vpfn, nr, true, mmu_sync_info); + err = kbase_mmu_update_pages_no_flush(kctx, vpfn, phys, nr, flags, group_id, &dirty_pgds); + + op_param = (const struct kbase_mmu_hw_op_param){ + .vpfn = vpfn, + .nr = nr, + .op = KBASE_MMU_OP_FLUSH_MEM, + .kctx_id = kctx->id, + .mmu_sync_info = mmu_sync_info, + .flush_skip_levels = pgd_level_to_skip_flush(dirty_pgds), + }; + + if (mmu_flush_cache_on_gpu_ctrl(kctx->kbdev)) + mmu_flush_invalidate_on_gpu_ctrl(kctx->kbdev, kctx, kctx->as_nr, &op_param); + else + mmu_flush_invalidate(kctx->kbdev, kctx, kctx->as_nr, &op_param); return err; } @@ -2418,7 +2656,9 @@ static void mmu_teardown_level(struct kbase_device *kbdev, mmu_mode = kbdev->mmu_mode; for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) { - target_pgd = mmu_mode->pte_to_phy_addr(pgd_page[i]); + target_pgd = mmu_mode->pte_to_phy_addr(kbdev->mgm_dev->ops.mgm_pte_to_original_pte( + kbdev->mgm_dev, MGM_DEFAULT_PTE_GROUP, + level, pgd_page[i])); if (target_pgd) { if (mmu_mode->pte_is_valid(pgd_page[i], level)) { @@ -2555,7 +2795,9 @@ static size_t kbasep_mmu_dump_level(struct kbase_context *kctx, phys_addr_t pgd, for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) { if (mmu_mode->pte_is_valid(pgd_page[i], level)) { target_pgd = mmu_mode->pte_to_phy_addr( - pgd_page[i]); + kbdev->mgm_dev->ops.mgm_pte_to_original_pte( + kbdev->mgm_dev, MGM_DEFAULT_PTE_GROUP, + level, pgd_page[i])); dump_size = kbasep_mmu_dump_level(kctx, target_pgd, level + 1, diff --git a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.h b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.h index 017c96e67001..53d1d194eca7 100644 --- a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.h +++ b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.h @@ -129,11 +129,9 @@ void kbase_mmu_term(struct kbase_device *kbdev, struct kbase_mmu_table *mmut); u64 kbase_mmu_create_ate(struct kbase_device *kbdev, struct tagged_addr phy, unsigned long flags, int level, int group_id); -int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, - const u64 start_vpfn, - struct tagged_addr *phys, size_t nr, - unsigned long flags, int group_id); +int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, + const u64 start_vpfn, struct tagged_addr *phys, size_t nr, + unsigned long flags, int group_id, u64 *dirty_pgds); int kbase_mmu_insert_pages(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, u64 vpfn, struct tagged_addr *phys, size_t nr, @@ -144,9 +142,8 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, unsigned long flags, int group_id, enum kbase_caller_mmu_sync_info mmu_sync_info); -int kbase_mmu_teardown_pages(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, u64 vpfn, - size_t nr, int as_nr); +int kbase_mmu_teardown_pages(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, u64 vpfn, + struct tagged_addr *phys, size_t nr, int as_nr); int kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn, struct tagged_addr *phys, size_t nr, unsigned long flags, int const group_id); diff --git a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_hw.h b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_hw.h index 31658e0038b7..09b3fa809bea 100644 --- a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_hw.h +++ b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_hw.h @@ -75,12 +75,14 @@ enum kbase_mmu_op_type { }; /** - * struct kbase_mmu_hw_op_param - parameters for kbase_mmu_hw_do_operation() - * @vpfn: MMU Virtual Page Frame Number to start the operation on. - * @nr: Number of pages to work on. - * @op: Operation type (written to ASn_COMMAND). - * @kctx_id: Kernel context ID for MMU command tracepoint - * @mmu_sync_info: Indicates whether this call is synchronous wrt MMU ops. + * struct kbase_mmu_hw_op_param - parameters for kbase_mmu_hw_do_* functions + * @vpfn: MMU Virtual Page Frame Number to start the operation on. + * @nr: Number of pages to work on. + * @op: Operation type (written to ASn_COMMAND). + * @kctx_id: Kernel context ID for MMU command tracepoint. + * @mmu_sync_info: Indicates whether this call is synchronous wrt MMU ops. + * @flush_skip_levels: Page table levels to skip flushing. (Only + * applicable if GPU supports feature) */ struct kbase_mmu_hw_op_param { u64 vpfn; @@ -88,6 +90,7 @@ struct kbase_mmu_hw_op_param { enum kbase_mmu_op_type op; u32 kctx_id; enum kbase_caller_mmu_sync_info mmu_sync_info; + u64 flush_skip_levels; }; /** @@ -102,18 +105,86 @@ void kbase_mmu_hw_configure(struct kbase_device *kbdev, struct kbase_as *as); /** - * kbase_mmu_hw_do_operation - Issue an operation to the MMU. - * @kbdev: kbase device to issue the MMU operation on. - * @as: address space to issue the MMU operation on. - * @op_param: parameters for the operation. + * kbase_mmu_hw_do_unlock_no_addr - Issue UNLOCK command to the MMU without + * programming the LOCKADDR register and wait + * for it to complete before returning. * - * Issue an operation (MMU invalidate, MMU flush, etc) on the address space that - * is associated with the provided kbase_context over the specified range + * @kbdev: Kbase device to issue the MMU operation on. + * @as: Address space to issue the MMU operation on. + * @op_param: Pointer to struct containing information about the MMU + * operation to perform. + * + * Return: 0 if issuing the command was successful, otherwise an error code. + */ +int kbase_mmu_hw_do_unlock_no_addr(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param); + +/** + * kbase_mmu_hw_do_unlock - Issue UNLOCK command to the MMU and wait for it + * to complete before returning. + * + * @kbdev: Kbase device to issue the MMU operation on. + * @as: Address space to issue the MMU operation on. + * @op_param: Pointer to struct containing information about the MMU + * operation to perform. + * + * Return: 0 if issuing the command was successful, otherwise an error code. + */ +int kbase_mmu_hw_do_unlock(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param); +/** + * kbase_mmu_hw_do_flush - Issue a flush operation to the MMU. + * + * @kbdev: Kbase device to issue the MMU operation on. + * @as: Address space to issue the MMU operation on. + * @op_param: Pointer to struct containing information about the MMU + * operation to perform. + * + * Issue a flush operation on the address space as per the information + * specified inside @op_param. This function should not be called for + * GPUs where MMU command to flush the cache(s) is deprecated. + * mmu_hw_mutex needs to be held when calling this function. * * Return: Zero if the operation was successful, non-zero otherwise. */ -int kbase_mmu_hw_do_operation(struct kbase_device *kbdev, struct kbase_as *as, - struct kbase_mmu_hw_op_param *op_param); +int kbase_mmu_hw_do_flush(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param); + +/** + * kbase_mmu_hw_do_flush_locked - Issue a flush operation to the MMU. + * + * @kbdev: Kbase device to issue the MMU operation on. + * @as: Address space to issue the MMU operation on. + * @op_param: Pointer to struct containing information about the MMU + * operation to perform. + * + * Issue a flush operation on the address space as per the information + * specified inside @op_param. This function should not be called for + * GPUs where MMU command to flush the cache(s) is deprecated. + * Both mmu_hw_mutex and hwaccess_lock need to be held when calling this + * function. + * + * Return: Zero if the operation was successful, non-zero otherwise. + */ +int kbase_mmu_hw_do_flush_locked(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param); + +/** + * kbase_mmu_hw_do_flush_on_gpu_ctrl - Issue a flush operation to the MMU. + * + * @kbdev: Kbase device to issue the MMU operation on. + * @as: Address space to issue the MMU operation on. + * @op_param: Pointer to struct containing information about the MMU + * operation to perform. + * + * Issue a flush operation on the address space as per the information + * specified inside @op_param. GPU command is used to flush the cache(s) + * instead of the MMU command. + * + * Return: Zero if the operation was successful, non-zero otherwise. + */ +int kbase_mmu_hw_do_flush_on_gpu_ctrl(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param); /** * kbase_mmu_hw_clear_fault - Clear a fault that has been previously reported by diff --git a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_hw_direct.c b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_hw_direct.c index 21c8798242e4..c9e5ef288ff8 100644 --- a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_hw_direct.c +++ b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_hw_direct.c @@ -26,13 +26,17 @@ #include #include #include +#include + /** * lock_region() - Generate lockaddr to lock memory region in MMU - * @gpu_props: GPU properties for finding the MMU lock region size - * @pfn: Starting page frame number of the region to lock - * @num_pages: Number of pages to lock. It must be greater than 0. - * @lockaddr: Address and size of memory region to lock + * + * @gpu_props: GPU properties for finding the MMU lock region size. + * @lockaddr: Address and size of memory region to lock. + * @op_param: Pointer to a struct containing the starting page frame number of + * the region to lock, the number of pages to lock and page table + * levels to skip when flushing (if supported). * * The lockaddr value is a combination of the starting address and * the size of the region that encompasses all the memory pages to lock. @@ -63,14 +67,14 @@ * * Return: 0 if success, or an error code on failure. */ -static int lock_region(struct kbase_gpu_props const *gpu_props, u64 pfn, u32 num_pages, - u64 *lockaddr) +static int lock_region(struct kbase_gpu_props const *gpu_props, u64 *lockaddr, + const struct kbase_mmu_hw_op_param *op_param) { - const u64 lockaddr_base = pfn << PAGE_SHIFT; - const u64 lockaddr_end = ((pfn + num_pages) << PAGE_SHIFT) - 1; + const u64 lockaddr_base = op_param->vpfn << PAGE_SHIFT; + const u64 lockaddr_end = ((op_param->vpfn + op_param->nr) << PAGE_SHIFT) - 1; u64 lockaddr_size_log2; - if (num_pages == 0) + if (op_param->nr == 0) return -EINVAL; /* The MMU lock region is a self-aligned region whose size @@ -122,7 +126,6 @@ static int lock_region(struct kbase_gpu_props const *gpu_props, u64 pfn, u32 num */ *lockaddr = lockaddr_base & ~((1ull << lockaddr_size_log2) - 1); *lockaddr |= lockaddr_size_log2 - 1; - return 0; } @@ -165,6 +168,100 @@ static int write_cmd(struct kbase_device *kbdev, int as_nr, u32 cmd) return status; } +#if MALI_USE_CSF && !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) +static int wait_cores_power_trans_complete(struct kbase_device *kbdev) +{ +#define WAIT_TIMEOUT 1000 /* 1ms timeout */ +#define DELAY_TIME_IN_US 1 + const int max_iterations = WAIT_TIMEOUT; + int loop; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + for (loop = 0; loop < max_iterations; loop++) { + u32 lo = + kbase_reg_read(kbdev, GPU_CONTROL_REG(SHADER_PWRTRANS_LO)); + u32 hi = + kbase_reg_read(kbdev, GPU_CONTROL_REG(SHADER_PWRTRANS_HI)); + + if (!lo && !hi) + break; + + udelay(DELAY_TIME_IN_US); + } + + if (loop == max_iterations) { + dev_warn(kbdev->dev, "SHADER_PWRTRANS set for too long"); + return -ETIMEDOUT; + } + + return 0; +} + +/** + * apply_hw_issue_GPU2019_3901_wa - Apply WA for the HW issue GPU2019_3901 + * + * @kbdev: Kbase device to issue the MMU operation on. + * @mmu_cmd: Pointer to the variable contain the value of MMU command + * that needs to be sent to flush the L2 cache and do an + * implicit unlock. + * @as_nr: Address space number for which MMU command needs to be + * sent. + * @hwaccess_locked: Flag to indicate if hwaccess_lock is held by the caller. + * + * This functions ensures that the flush of LSC is not missed for the pages that + * were unmapped from the GPU, due to the power down transition of shader cores. + * + * Return: 0 if the WA was successfully applied, non-zero otherwise. + */ +static int apply_hw_issue_GPU2019_3901_wa(struct kbase_device *kbdev, + u32 *mmu_cmd, unsigned int as_nr, bool hwaccess_locked) +{ + unsigned long flags = 0; + int ret = 0; + + if (!hwaccess_locked) + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + /* Check if L2 is OFF. The cores also must be OFF if L2 is not up, so + * the workaround can be safely skipped. + */ + if (kbdev->pm.backend.l2_state != KBASE_L2_OFF) { + if (*mmu_cmd != AS_COMMAND_FLUSH_MEM) { + dev_warn(kbdev->dev, + "Unexpected mmu command received"); + ret = -EINVAL; + goto unlock; + } + + /* Wait for the LOCK MMU command to complete, issued by the caller */ + ret = wait_ready(kbdev, as_nr); + if (ret) + goto unlock; + + ret = kbase_gpu_cache_flush_and_busy_wait(kbdev, + GPU_COMMAND_CACHE_CLN_INV_LSC); + if (ret) + goto unlock; + + ret = wait_cores_power_trans_complete(kbdev); + if (ret) + goto unlock; + + /* As LSC is guaranteed to have been flushed we can use FLUSH_PT + * MMU command to only flush the L2. + */ + *mmu_cmd = AS_COMMAND_FLUSH_PT; + } + +unlock: + if (!hwaccess_locked) + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return ret; +} +#endif + void kbase_mmu_hw_configure(struct kbase_device *kbdev, struct kbase_as *as) { struct kbase_mmu_setup *current_setup = &as->current_setup; @@ -222,95 +319,245 @@ void kbase_mmu_hw_configure(struct kbase_device *kbdev, struct kbase_as *as) #endif } -int kbase_mmu_hw_do_operation(struct kbase_device *kbdev, struct kbase_as *as, - struct kbase_mmu_hw_op_param *op_param) +/** + * mmu_command_instr - Record an MMU command for instrumentation purposes. + * + * @kbdev: Kbase device used to issue MMU operation on. + * @kctx_id: Kernel context ID for MMU command tracepoint. + * @cmd: Command issued to the MMU. + * @lock_addr: Address of memory region locked for the operation. + * @mmu_sync_info: Indicates whether this call is synchronous wrt MMU ops. + */ +static void mmu_command_instr(struct kbase_device *kbdev, u32 kctx_id, u32 cmd, u64 lock_addr, + enum kbase_caller_mmu_sync_info mmu_sync_info) +{ + u64 lock_addr_base = AS_LOCKADDR_LOCKADDR_BASE_GET(lock_addr); + u32 lock_addr_size = AS_LOCKADDR_LOCKADDR_SIZE_GET(lock_addr); + + bool is_mmu_synchronous = (mmu_sync_info == CALLER_MMU_SYNC); + + KBASE_TLSTREAM_AUX_MMU_COMMAND(kbdev, kctx_id, cmd, is_mmu_synchronous, lock_addr_base, + lock_addr_size); +} + +/* Helper function to program the LOCKADDR register before LOCK/UNLOCK command + * is issued. + */ +static int mmu_hw_set_lock_addr(struct kbase_device *kbdev, int as_nr, u64 *lock_addr, + const struct kbase_mmu_hw_op_param *op_param) +{ + int ret; + + ret = lock_region(&kbdev->gpu_props, lock_addr, op_param); + + if (!ret) { + /* Set the region that needs to be updated */ + kbase_reg_write(kbdev, MMU_AS_REG(as_nr, AS_LOCKADDR_LO), + *lock_addr & 0xFFFFFFFFUL); + kbase_reg_write(kbdev, MMU_AS_REG(as_nr, AS_LOCKADDR_HI), + (*lock_addr >> 32) & 0xFFFFFFFFUL); + } + return ret; +} + +/** + * mmu_hw_do_lock_no_wait - Issue LOCK command to the MMU and return without + * waiting for it's completion. + * + * @kbdev: Kbase device to issue the MMU operation on. + * @as: Address space to issue the MMU operation on. + * @lock_addr: Address of memory region locked for this operation. + * @op_param: Pointer to a struct containing information about the MMU operation. + * + * Return: 0 if issuing the command was successful, otherwise an error code. + */ +static int mmu_hw_do_lock_no_wait(struct kbase_device *kbdev, struct kbase_as *as, u64 *lock_addr, + const struct kbase_mmu_hw_op_param *op_param) +{ + int ret; + + ret = mmu_hw_set_lock_addr(kbdev, as->number, lock_addr, op_param); + + if (!ret) + write_cmd(kbdev, as->number, AS_COMMAND_LOCK); + + return ret; +} + +static int mmu_hw_do_lock(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param) { int ret; u64 lock_addr = 0x0; - if (WARN_ON(kbdev == NULL) || - WARN_ON(as == NULL) || - WARN_ON(op_param == NULL)) + if (WARN_ON(kbdev == NULL) || WARN_ON(as == NULL)) return -EINVAL; - lockdep_assert_held(&kbdev->mmu_hw_mutex); + ret = mmu_hw_do_lock_no_wait(kbdev, as, &lock_addr, op_param); - if (op_param->op == KBASE_MMU_OP_UNLOCK) { - /* Unlock doesn't require a lock first */ - ret = write_cmd(kbdev, as->number, AS_COMMAND_UNLOCK); - - /* Wait for UNLOCK command to complete */ + if (!ret) ret = wait_ready(kbdev, as->number); - if (!ret) { - /* read MMU_AS_CONTROL.LOCKADDR register */ - lock_addr |= (u64)kbase_reg_read(kbdev, - MMU_AS_REG(as->number, AS_LOCKADDR_HI)) << 32; - lock_addr |= (u64)kbase_reg_read(kbdev, - MMU_AS_REG(as->number, AS_LOCKADDR_LO)); - } - } else if (op_param->op >= KBASE_MMU_OP_FIRST && - op_param->op < KBASE_MMU_OP_COUNT) { - ret = lock_region(&kbdev->gpu_props, op_param->vpfn, op_param->nr, &lock_addr); + if (!ret) + mmu_command_instr(kbdev, op_param->kctx_id, AS_COMMAND_LOCK, lock_addr, + op_param->mmu_sync_info); - if (!ret) { - /* Lock the region that needs to be updated */ - kbase_reg_write(kbdev, - MMU_AS_REG(as->number, AS_LOCKADDR_LO), - lock_addr & 0xFFFFFFFFUL); - kbase_reg_write(kbdev, - MMU_AS_REG(as->number, AS_LOCKADDR_HI), - (lock_addr >> 32) & 0xFFFFFFFFUL); - write_cmd(kbdev, as->number, AS_COMMAND_LOCK); + return ret; +} - /* Translate and send operation to HW */ - switch (op_param->op) { - case KBASE_MMU_OP_FLUSH_PT: - write_cmd(kbdev, as->number, - AS_COMMAND_FLUSH_PT); - break; - case KBASE_MMU_OP_FLUSH_MEM: - write_cmd(kbdev, as->number, - AS_COMMAND_FLUSH_MEM); - break; - case KBASE_MMU_OP_LOCK: - /* No further operation. */ - break; - default: - dev_warn(kbdev->dev, - "Unsupported MMU operation (op=%d).\n", - op_param->op); - return -EINVAL; - }; +int kbase_mmu_hw_do_unlock_no_addr(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param) +{ + int ret = 0; - /* Wait for the command to complete */ - ret = wait_ready(kbdev, as->number); - } - } else { - /* Code should not reach here. */ - dev_warn(kbdev->dev, "Invalid mmu operation (op=%d).\n", - op_param->op); + if (WARN_ON(kbdev == NULL) || WARN_ON(as == NULL)) return -EINVAL; - } - /* MMU command instrumentation */ + ret = write_cmd(kbdev, as->number, AS_COMMAND_UNLOCK); + + /* Wait for UNLOCK command to complete */ + if (!ret) + ret = wait_ready(kbdev, as->number); + if (!ret) { - u64 lock_addr_base = AS_LOCKADDR_LOCKADDR_BASE_GET(lock_addr); - u32 lock_addr_size = AS_LOCKADDR_LOCKADDR_SIZE_GET(lock_addr); + u64 lock_addr = 0x0; + /* read MMU_AS_CONTROL.LOCKADDR register */ + lock_addr |= (u64)kbase_reg_read(kbdev, MMU_AS_REG(as->number, AS_LOCKADDR_HI)) + << 32; + lock_addr |= (u64)kbase_reg_read(kbdev, MMU_AS_REG(as->number, AS_LOCKADDR_LO)); - bool is_mmu_synchronous = false; - - if (op_param->mmu_sync_info == CALLER_MMU_SYNC) - is_mmu_synchronous = true; - - KBASE_TLSTREAM_AUX_MMU_COMMAND(kbdev, op_param->kctx_id, - op_param->op, is_mmu_synchronous, - lock_addr_base, lock_addr_size); + mmu_command_instr(kbdev, op_param->kctx_id, AS_COMMAND_UNLOCK, + lock_addr, op_param->mmu_sync_info); } return ret; } +int kbase_mmu_hw_do_unlock(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param) +{ + int ret = 0; + u64 lock_addr = 0x0; + + if (WARN_ON(kbdev == NULL) || WARN_ON(as == NULL)) + return -EINVAL; + + ret = mmu_hw_set_lock_addr(kbdev, as->number, &lock_addr, op_param); + + if (!ret) + ret = kbase_mmu_hw_do_unlock_no_addr(kbdev, as, + op_param); + + return ret; +} + +static int mmu_hw_do_flush(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param, bool hwaccess_locked) +{ + int ret; + u64 lock_addr = 0x0; + u32 mmu_cmd = AS_COMMAND_FLUSH_MEM; + + if (WARN_ON(kbdev == NULL) || WARN_ON(as == NULL)) + return -EINVAL; + + /* MMU operations can be either FLUSH_PT or FLUSH_MEM, anything else at + * this point would be unexpected. + */ + if (op_param->op != KBASE_MMU_OP_FLUSH_PT && + op_param->op != KBASE_MMU_OP_FLUSH_MEM) { + dev_err(kbdev->dev, "Unexpected flush operation received"); + return -EINVAL; + } + + lockdep_assert_held(&kbdev->mmu_hw_mutex); + + if (op_param->op == KBASE_MMU_OP_FLUSH_PT) + mmu_cmd = AS_COMMAND_FLUSH_PT; + + /* Lock the region that needs to be updated */ + ret = mmu_hw_do_lock_no_wait(kbdev, as, &lock_addr, op_param); + if (ret) + return ret; + +#if MALI_USE_CSF && !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) + /* WA for the BASE_HW_ISSUE_GPU2019_3901. No runtime check is used here + * as the WA is applicable to all CSF GPUs where FLUSH_MEM/PT command is + * supported, and this function doesn't gets called for the GPUs where + * FLUSH_MEM/PT command is deprecated. + */ + if (mmu_cmd == AS_COMMAND_FLUSH_MEM) { + ret = apply_hw_issue_GPU2019_3901_wa(kbdev, &mmu_cmd, + as->number, hwaccess_locked); + if (ret) + return ret; + } +#endif + + write_cmd(kbdev, as->number, mmu_cmd); + + /* Wait for the command to complete */ + ret = wait_ready(kbdev, as->number); + + if (!ret) + mmu_command_instr(kbdev, op_param->kctx_id, mmu_cmd, lock_addr, + op_param->mmu_sync_info); + + return ret; +} + +int kbase_mmu_hw_do_flush_locked(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + return mmu_hw_do_flush(kbdev, as, op_param, true); +} + +int kbase_mmu_hw_do_flush(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param) +{ + return mmu_hw_do_flush(kbdev, as, op_param, false); +} + +int kbase_mmu_hw_do_flush_on_gpu_ctrl(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param) +{ + int ret, ret2; + u32 gpu_cmd = GPU_COMMAND_CACHE_CLN_INV_L2_LSC; + + if (WARN_ON(kbdev == NULL) || WARN_ON(as == NULL)) + return -EINVAL; + + /* MMU operations can be either FLUSH_PT or FLUSH_MEM, anything else at + * this point would be unexpected. + */ + if (op_param->op != KBASE_MMU_OP_FLUSH_PT && + op_param->op != KBASE_MMU_OP_FLUSH_MEM) { + dev_err(kbdev->dev, "Unexpected flush operation received"); + return -EINVAL; + } + + lockdep_assert_held(&kbdev->hwaccess_lock); + lockdep_assert_held(&kbdev->mmu_hw_mutex); + + if (op_param->op == KBASE_MMU_OP_FLUSH_PT) + gpu_cmd = GPU_COMMAND_CACHE_CLN_INV_L2; + + /* 1. Issue MMU_AS_CONTROL.COMMAND.LOCK operation. */ + ret = mmu_hw_do_lock(kbdev, as, op_param); + if (ret) + return ret; + + /* 2. Issue GPU_CONTROL.COMMAND.FLUSH_CACHES operation */ + ret = kbase_gpu_cache_flush_and_busy_wait(kbdev, gpu_cmd); + + /* 3. Issue MMU_AS_CONTROL.COMMAND.UNLOCK operation. */ + ret2 = kbase_mmu_hw_do_unlock_no_addr(kbdev, as, op_param); + + return ret ?: ret2; +} + void kbase_mmu_hw_clear_fault(struct kbase_device *kbdev, struct kbase_as *as, enum kbase_mmu_fault_type type) { diff --git a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_mode_aarch64.c b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_mode_aarch64.c index c06109940dd0..dfbdee17782b 100644 --- a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_mode_aarch64.c +++ b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu_mode_aarch64.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2010-2014, 2016-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2010-2014, 2016-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -189,14 +189,9 @@ static void set_num_valid_entries(u64 *pgd, unsigned int num_of_valid_entries) << UNUSED_BIT_POSITION_IN_PAGE_DESCRIPTOR); } -static void entry_set_pte(u64 *pgd, u64 vpfn, phys_addr_t phy) +static void entry_set_pte(u64 *entry, phys_addr_t phy) { - unsigned int nr_entries = get_num_valid_entries(pgd); - - page_table_entry_set(&pgd[vpfn], (phy & PAGE_MASK) | ENTRY_ACCESS_BIT | - ENTRY_IS_PTE); - - set_num_valid_entries(pgd, nr_entries + 1); + page_table_entry_set(entry, (phy & PAGE_MASK) | ENTRY_ACCESS_BIT | ENTRY_IS_PTE); } static void entry_invalidate(u64 *entry) diff --git a/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c b/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c index 5e4bf3f68d06..07b09f868735 100644 --- a/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c +++ b/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_runtime_pm.c @@ -29,6 +29,7 @@ #include "mali_kbase_config_platform.h" + static void enable_gpu_power_control(struct kbase_device *kbdev) { unsigned int i; @@ -50,7 +51,6 @@ static void enable_gpu_power_control(struct kbase_device *kbdev) } } - static void disable_gpu_power_control(struct kbase_device *kbdev) { unsigned int i; @@ -99,9 +99,8 @@ static int pm_callback_power_on(struct kbase_device *kbdev) #else spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +#ifdef KBASE_PM_RUNTIME error = pm_runtime_get_sync(kbdev->dev); - enable_gpu_power_control(kbdev); - if (error == 1) { /* * Let core know that the chip has not been @@ -109,8 +108,11 @@ static int pm_callback_power_on(struct kbase_device *kbdev) */ ret = 0; } - dev_dbg(kbdev->dev, "pm_runtime_get_sync returned %d\n", error); +#else + enable_gpu_power_control(kbdev); +#endif /* KBASE_PM_RUNTIME */ + #endif /* MALI_USE_CSF */ return ret; @@ -243,7 +245,9 @@ static int pm_callback_runtime_on(struct kbase_device *kbdev) { dev_dbg(kbdev->dev, "%s\n", __func__); +#if !MALI_USE_CSF enable_gpu_power_control(kbdev); +#endif return 0; } @@ -251,7 +255,9 @@ static void pm_callback_runtime_off(struct kbase_device *kbdev) { dev_dbg(kbdev->dev, "%s\n", __func__); +#if !MALI_USE_CSF disable_gpu_power_control(kbdev); +#endif } static void pm_callback_resume(struct kbase_device *kbdev) diff --git a/drivers/gpu/arm/bifrost/tests/Kbuild b/drivers/gpu/arm/bifrost/tests/Kbuild index ee3de7b00652..38e4dd4d712a 100644 --- a/drivers/gpu/arm/bifrost/tests/Kbuild +++ b/drivers/gpu/arm/bifrost/tests/Kbuild @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2017, 2020-2021 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2017, 2020-2022 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -27,4 +27,5 @@ subdir-ccflags-y += -I$(src)/include \ obj-$(CONFIG_MALI_KUTF) += kutf/ obj-$(CONFIG_MALI_KUTF_IRQ_TEST) += mali_kutf_irq_test/ obj-$(CONFIG_MALI_KUTF_CLK_RATE_TRACE) += mali_kutf_clk_rate_trace/kernel/ +obj-$(CONFIG_MALI_KUTF_MGM_INTEGRATION) += mali_kutf_mgm_integration_test/ diff --git a/drivers/gpu/arm/bifrost/tests/Kconfig b/drivers/gpu/arm/bifrost/tests/Kconfig index 820f11e65d87..e9fe22771416 100644 --- a/drivers/gpu/arm/bifrost/tests/Kconfig +++ b/drivers/gpu/arm/bifrost/tests/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2017, 2020-2021 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2017, 2020-2022 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -52,6 +52,18 @@ config MALI_KUTF_CLK_RATE_TRACE Modules: - mali_kutf_clk_rate_trace_test_portal.ko +config MALI_KUTF_MGM_INTEGRATION_TEST + bool "Build Mali KUTF MGM integration test module" + depends on MALI_KUTF + default y + help + This option will build the MGM integration test module. + It can test the implementation of PTE translation for specific + group ids. + + Modules: + - mali_kutf_mgm_integration_test.ko + comment "Enable MALI_BIFROST_DEBUG for KUTF modules support" depends on MALI_BIFROST && !MALI_BIFROST_DEBUG && MALI_KUTF diff --git a/drivers/gpu/arm/bifrost/tests/Mconfig b/drivers/gpu/arm/bifrost/tests/Mconfig index f5fdeffe9b3c..738dbd42aac7 100644 --- a/drivers/gpu/arm/bifrost/tests/Mconfig +++ b/drivers/gpu/arm/bifrost/tests/Mconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2018-2021 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2018-2022 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -52,6 +52,18 @@ config MALI_KUTF_CLK_RATE_TRACE Modules: - mali_kutf_clk_rate_trace_test_portal.ko +config MALI_KUTF_MGM_INTEGRATION_TEST + bool "Build Mali KUTF MGM integration test module" + depends on MALI_KUTF + default y + help + This option will build the MGM integration test module. + It can test the implementation of PTE translation for specific + group ids. + + Modules: + - mali_kutf_mgm_integration_test.ko + # Enable MALI_BIFROST_DEBUG for KUTF modules support diff --git a/drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers_user.c b/drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers_user.c index f88e138c9030..c4e294325262 100644 --- a/drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers_user.c +++ b/drivers/gpu/arm/bifrost/tests/kutf/kutf_helpers_user.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2017, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2017, 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -28,7 +28,7 @@ #include #include -const char *valtype_names[] = { +static const char *const valtype_names[] = { "INVALID", "U64", "STR", diff --git a/drivers/gpu/arm/bifrost/tests/kutf/kutf_suite.c b/drivers/gpu/arm/bifrost/tests/kutf/kutf_suite.c index 91065b5820dd..4468066f1b27 100644 --- a/drivers/gpu/arm/bifrost/tests/kutf/kutf_suite.c +++ b/drivers/gpu/arm/bifrost/tests/kutf/kutf_suite.c @@ -106,22 +106,16 @@ struct kutf_convert_table { enum kutf_result_status result; }; -struct kutf_convert_table kutf_convert[] = { -#define ADD_UTF_RESULT(_name) \ -{ \ - #_name, \ - _name, \ -}, -ADD_UTF_RESULT(KUTF_RESULT_BENCHMARK) -ADD_UTF_RESULT(KUTF_RESULT_SKIP) -ADD_UTF_RESULT(KUTF_RESULT_UNKNOWN) -ADD_UTF_RESULT(KUTF_RESULT_PASS) -ADD_UTF_RESULT(KUTF_RESULT_DEBUG) -ADD_UTF_RESULT(KUTF_RESULT_INFO) -ADD_UTF_RESULT(KUTF_RESULT_WARN) -ADD_UTF_RESULT(KUTF_RESULT_FAIL) -ADD_UTF_RESULT(KUTF_RESULT_FATAL) -ADD_UTF_RESULT(KUTF_RESULT_ABORT) +static const struct kutf_convert_table kutf_convert[] = { +#define ADD_UTF_RESULT(_name) \ + { \ +#_name, _name, \ + } + ADD_UTF_RESULT(KUTF_RESULT_BENCHMARK), ADD_UTF_RESULT(KUTF_RESULT_SKIP), + ADD_UTF_RESULT(KUTF_RESULT_UNKNOWN), ADD_UTF_RESULT(KUTF_RESULT_PASS), + ADD_UTF_RESULT(KUTF_RESULT_DEBUG), ADD_UTF_RESULT(KUTF_RESULT_INFO), + ADD_UTF_RESULT(KUTF_RESULT_WARN), ADD_UTF_RESULT(KUTF_RESULT_FAIL), + ADD_UTF_RESULT(KUTF_RESULT_FATAL), ADD_UTF_RESULT(KUTF_RESULT_ABORT), }; #define UTF_CONVERT_SIZE (ARRAY_SIZE(kutf_convert)) @@ -191,8 +185,7 @@ static void kutf_set_expected_result(struct kutf_context *context, * * Return: 1 if test result was successfully converted to string, 0 otherwise */ -static int kutf_result_to_string(char **result_str, - enum kutf_result_status result) +static int kutf_result_to_string(const char **result_str, enum kutf_result_status result) { int i; int ret = 0; @@ -382,7 +375,7 @@ static ssize_t kutf_debugfs_run_read(struct file *file, char __user *buf, struct kutf_result *res; unsigned long bytes_not_copied; ssize_t bytes_copied = 0; - char *kutf_str_ptr = NULL; + const char *kutf_str_ptr = NULL; size_t kutf_str_len = 0; size_t message_len = 0; char separator = ':'; @@ -599,11 +592,7 @@ static int create_fixture_variant(struct kutf_test_function *test_func, goto fail_file; } -#if KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE tmp = debugfs_create_file_unsafe( -#else - tmp = debugfs_create_file( -#endif "run", 0600, test_fix->dir, test_fix, &kutf_debugfs_run_ops); diff --git a/drivers/gpu/arm/bifrost/tests/kutf/kutf_utils.c b/drivers/gpu/arm/bifrost/tests/kutf/kutf_utils.c index 2ae15109f109..21f5fadcc5f6 100644 --- a/drivers/gpu/arm/bifrost/tests/kutf/kutf_utils.c +++ b/drivers/gpu/arm/bifrost/tests/kutf/kutf_utils.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2014, 2017, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014, 2017, 2020-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -31,7 +31,7 @@ static char tmp_buffer[KUTF_MAX_DSPRINTF_LEN]; -DEFINE_MUTEX(buffer_lock); +static DEFINE_MUTEX(buffer_lock); const char *kutf_dsprintf(struct kutf_mempool *pool, const char *fmt, ...) diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c b/drivers/gpu/arm/bifrost/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c index e64c44a0b1f9..2d7289daca20 100644 --- a/drivers/gpu/arm/bifrost/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c @@ -46,7 +46,7 @@ #define MINOR_FOR_FIRST_KBASE_DEV (-1) /* KUTF test application pointer for this test */ -struct kutf_application *kutf_app; +static struct kutf_application *kutf_app; enum portal_server_state { PORTAL_STATE_NO_CLK, @@ -113,7 +113,7 @@ struct kbasep_cmd_name_pair { const char *name; }; -struct kbasep_cmd_name_pair kbasep_portal_cmd_name_map[] = { +static const struct kbasep_cmd_name_pair kbasep_portal_cmd_name_map[] = { { PORTAL_CMD_GET_PLATFORM, GET_PLATFORM }, { PORTAL_CMD_GET_CLK_RATE_MGR, GET_CLK_RATE_MGR }, { PORTAL_CMD_GET_CLK_RATE_TRACE, GET_CLK_RATE_TRACE }, @@ -128,7 +128,7 @@ struct kbasep_cmd_name_pair kbasep_portal_cmd_name_map[] = { * this pointer is engaged, new requests for create fixture will fail * hence limiting the use of the portal at any time to a singleton. */ -struct kutf_clk_rate_trace_fixture_data *g_ptr_portal_data; +static struct kutf_clk_rate_trace_fixture_data *g_ptr_portal_data; #define PORTAL_MSG_LEN (KUTF_MAX_LINE_LENGTH - MAX_REPLY_NAME_LEN) static char portal_msg_buf[PORTAL_MSG_LEN]; @@ -825,7 +825,7 @@ static void *mali_kutf_clk_rate_trace_create_fixture( if (!data) return NULL; - *data = (const struct kutf_clk_rate_trace_fixture_data) { 0 }; + *data = (const struct kutf_clk_rate_trace_fixture_data){ NULL }; pr_debug("Hooking up the test portal to kbdev clk rate trace\n"); spin_lock(&kbdev->pm.clk_rtm.lock); @@ -909,7 +909,7 @@ static int __init mali_kutf_clk_rate_trace_test_module_init(void) { struct kutf_suite *suite; unsigned int filters; - union kutf_callback_data suite_data = { 0 }; + union kutf_callback_data suite_data = { NULL }; pr_debug("Creating app\n"); diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c index 5824a4c2c530..2d6e68946c00 100644 --- a/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c @@ -40,7 +40,7 @@ */ /* KUTF test application pointer for this test */ -struct kutf_application *irq_app; +static struct kutf_application *irq_app; /** * struct kutf_irq_fixture_data - test fixture used by the test functions. diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/Kbuild b/drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/Kbuild new file mode 100644 index 000000000000..e9bff98b88b6 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/Kbuild @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note +# +# (C) COPYRIGHT 2022 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU license. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# + +ifeq ($(CONFIG_MALI_KUTF_MGM_INTEGRATION_TEST),y) +obj-m += mali_kutf_mgm_integration_test.o + +mali_kutf_mgm_integration_test-y := mali_kutf_mgm_integration_test_main.o +endif diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/build.bp b/drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/build.bp new file mode 100644 index 000000000000..2e4a083863e4 --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/build.bp @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * + * (C) COPYRIGHT 2022 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-2.0.html. + * + */ +bob_kernel_module { + name: "mali_kutf_mgm_integration_test", + defaults: [ + "mali_kbase_shared_config_defaults", + "kernel_test_configs", + "kernel_test_includes", + ], + srcs: [ + "Kbuild", + "mali_kutf_mgm_integration_test_main.c", + ], + extra_symbols: [ + "mali_kbase", + "kutf", + ], + enabled: false, + mali_kutf_mgm_integration_test: { + kbuild_options: ["CONFIG_MALI_KUTF_MGM_INTEGRATION_TEST=y"], + enabled: true, + }, +} \ No newline at end of file diff --git a/drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/mali_kutf_mgm_integration_test_main.c b/drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/mali_kutf_mgm_integration_test_main.c new file mode 100644 index 000000000000..5a42bd675c2a --- /dev/null +++ b/drivers/gpu/arm/bifrost/tests/mali_kutf_mgm_integration_test/mali_kutf_mgm_integration_test_main.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note +/* + * + * (C) COPYRIGHT 2022 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-2.0.html. + * + */ +#include +#include "mali_kbase.h" +#include +#include +#include +#include + +#define MINOR_FOR_FIRST_KBASE_DEV (-1) + +#define BASE_MEM_GROUP_COUNT (16) +#define PA_MAX ((1ULL << 48) - 1) +#define PA_START_BIT 12 +#define ENTRY_ACCESS_BIT (1ULL << 10) + +#define ENTRY_IS_ATE_L3 3ULL +#define ENTRY_IS_ATE_L02 1ULL + +#define MGM_INTEGRATION_SUITE_NAME "mgm_integration" +#define MGM_INTEGRATION_PTE_TRANSLATION "pte_translation" + +static char msg_buf[KUTF_MAX_LINE_LENGTH]; + +/* KUTF test application pointer for this test */ +struct kutf_application *mgm_app; + +/** + * struct kutf_mgm_fixture_data - test fixture used by test functions + * @kbdev: kbase device for the GPU. + * @group_id: Memory group ID to test based on fixture index. + */ +struct kutf_mgm_fixture_data { + struct kbase_device *kbdev; + int group_id; +}; + +/** + * mali_kutf_mgm_pte_translation_test() - Tests forward and reverse translation + * of PTE by the MGM module + * @context: KUTF context within which to perform the test. + * + * This test creates PTEs with physical addresses in the range + * 0x0000-0xFFFFFFFFF000 and tests that mgm_update_gpu_pte() returns a different + * PTE and mgm_pte_to_original_pte() returns the original PTE. This is tested + * at MMU level 2 and 3 as mgm_update_gpu_pte() is called for ATEs only. + * + * This test is run for a specific group_id depending on the fixture_id. + */ +static void mali_kutf_mgm_pte_translation_test(struct kutf_context *context) +{ + struct kutf_mgm_fixture_data *data = context->fixture; + struct kbase_device *kbdev = data->kbdev; + struct memory_group_manager_device *mgm_dev = kbdev->mgm_dev; + u64 addr; + + for (addr = 1 << (PA_START_BIT - 1); addr <= PA_MAX; addr <<= 1) { + /* Mask 1 << 11 by ~0xFFF to get 0x0000 at first iteration */ + phys_addr_t pa = addr; + u8 mmu_level; + + /* Test MMU level 3 and 2 (2MB pages) only */ + for (mmu_level = MIDGARD_MMU_LEVEL(2); mmu_level <= MIDGARD_MMU_LEVEL(3); + mmu_level++) { + u64 translated_pte; + u64 returned_pte; + u64 original_pte; + + if (mmu_level == MIDGARD_MMU_LEVEL(3)) + original_pte = + (pa & PAGE_MASK) | ENTRY_ACCESS_BIT | ENTRY_IS_ATE_L3; + else + original_pte = + (pa & PAGE_MASK) | ENTRY_ACCESS_BIT | ENTRY_IS_ATE_L02; + + dev_dbg(kbdev->dev, "Testing group_id=%u, mmu_level=%u, pte=0x%llx\n", + data->group_id, mmu_level, original_pte); + + translated_pte = mgm_dev->ops.mgm_update_gpu_pte(mgm_dev, data->group_id, + mmu_level, original_pte); + if (translated_pte == original_pte) { + snprintf( + msg_buf, sizeof(msg_buf), + "PTE unchanged. translated_pte (0x%llx) == original_pte (0x%llx) for mmu_level=%u, group_id=%d", + translated_pte, original_pte, mmu_level, data->group_id); + kutf_test_fail(context, msg_buf); + return; + } + + returned_pte = mgm_dev->ops.mgm_pte_to_original_pte( + mgm_dev, data->group_id, mmu_level, translated_pte); + dev_dbg(kbdev->dev, "\treturned_pte=%llx\n", returned_pte); + + if (returned_pte != original_pte) { + snprintf( + msg_buf, sizeof(msg_buf), + "Original PTE not returned. returned_pte (0x%llx) != origin al_pte (0x%llx) for mmu_level=%u, group_id=%d", + returned_pte, original_pte, mmu_level, data->group_id); + kutf_test_fail(context, msg_buf); + return; + } + } + } + snprintf(msg_buf, sizeof(msg_buf), "Translation passed for group_id=%d", data->group_id); + kutf_test_pass(context, msg_buf); +} + +/** + * mali_kutf_mgm_integration_create_fixture() - Creates the fixture data + * required for all tests in the mgm integration suite. + * @context: KUTF context. + * + * Return: Fixture data created on success or NULL on failure + */ +static void *mali_kutf_mgm_integration_create_fixture(struct kutf_context *context) +{ + struct kutf_mgm_fixture_data *data; + struct kbase_device *kbdev; + + pr_debug("Finding kbase device\n"); + kbdev = kbase_find_device(MINOR_FOR_FIRST_KBASE_DEV); + if (kbdev == NULL) { + kutf_test_fail(context, "Failed to find kbase device"); + return NULL; + } + pr_debug("Creating fixture\n"); + + data = kutf_mempool_alloc(&context->fixture_pool, sizeof(struct kutf_mgm_fixture_data)); + if (!data) + return NULL; + data->kbdev = kbdev; + data->group_id = context->fixture_index; + + pr_debug("Fixture created\n"); + return data; +} + +/** + * mali_kutf_mgm_integration_remove_fixture() - Destroy fixture data previously + * created by mali_kutf_mgm_integration_create_fixture. + * @context: KUTF context. + */ +static void mali_kutf_mgm_integration_remove_fixture(struct kutf_context *context) +{ + struct kutf_mgm_fixture_data *data = context->fixture; + struct kbase_device *kbdev = data->kbdev; + + kbase_release_device(kbdev); +} + +/** + * mali_kutf_mgm_integration_test_main_init() - Module entry point for this test. + * + * Return: 0 on success, error code on failure. + */ +static int __init mali_kutf_mgm_integration_test_main_init(void) +{ + struct kutf_suite *suite; + + mgm_app = kutf_create_application("mgm"); + + if (mgm_app == NULL) { + pr_warn("Creation of mgm KUTF app failed!\n"); + return -ENOMEM; + } + suite = kutf_create_suite(mgm_app, MGM_INTEGRATION_SUITE_NAME, BASE_MEM_GROUP_COUNT, + mali_kutf_mgm_integration_create_fixture, + mali_kutf_mgm_integration_remove_fixture); + if (suite == NULL) { + pr_warn("Creation of %s suite failed!\n", MGM_INTEGRATION_SUITE_NAME); + kutf_destroy_application(mgm_app); + return -ENOMEM; + } + kutf_add_test(suite, 0x0, MGM_INTEGRATION_PTE_TRANSLATION, + mali_kutf_mgm_pte_translation_test); + return 0; +} + +/** + * mali_kutf_mgm_integration_test_main_exit() - Module exit point for this test. + */ +static void __exit mali_kutf_mgm_integration_test_main_exit(void) +{ + kutf_destroy_application(mgm_app); +} + +module_init(mali_kutf_mgm_integration_test_main_init); +module_exit(mali_kutf_mgm_integration_test_main_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION("1.0"); diff --git a/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline_io.c b/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline_io.c index d2443bee461b..af8b3d8c8c35 100644 --- a/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline_io.c +++ b/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline_io.c @@ -26,12 +26,12 @@ #include #include +#include /* The timeline stream file operations functions. */ static ssize_t kbasep_timeline_io_read(struct file *filp, char __user *buffer, size_t size, loff_t *f_pos); -static unsigned int kbasep_timeline_io_poll(struct file *filp, - poll_table *wait); +static __poll_t kbasep_timeline_io_poll(struct file *filp, poll_table *wait); static int kbasep_timeline_io_release(struct inode *inode, struct file *filp); static int kbasep_timeline_io_fsync(struct file *filp, loff_t start, loff_t end, int datasync); @@ -292,7 +292,7 @@ static ssize_t kbasep_timeline_io_read(struct file *filp, char __user *buffer, * * Return: POLLIN if data can be read without blocking, otherwise zero */ -static unsigned int kbasep_timeline_io_poll(struct file *filp, poll_table *wait) +static __poll_t kbasep_timeline_io_poll(struct file *filp, poll_table *wait) { struct kbase_tlstream *stream; unsigned int rb_idx; @@ -302,7 +302,7 @@ static unsigned int kbasep_timeline_io_poll(struct file *filp, poll_table *wait) KBASE_DEBUG_ASSERT(wait); if (WARN_ON(!filp->private_data)) - return -EFAULT; + return (__poll_t)-EFAULT; timeline = (struct kbase_timeline *)filp->private_data; diff --git a/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.c b/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.c index 6aae4e0ac8b4..3ac78503ce1f 100644 --- a/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.c +++ b/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.c @@ -305,11 +305,11 @@ enum tl_msg_id_obj { "@p", \ "atom") \ TRACEPOINT_DESC(KBASE_TL_JD_DONE_NO_LOCK_START, \ - "Within function jd_done_nolock", \ + "Within function kbase_jd_done_nolock", \ "@p", \ "atom") \ TRACEPOINT_DESC(KBASE_TL_JD_DONE_NO_LOCK_END, \ - "Within function jd_done_nolock - end", \ + "Within function kbase_jd_done_nolock - end", \ "@p", \ "atom") \ TRACEPOINT_DESC(KBASE_TL_JD_DONE_START, \ diff --git a/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.h b/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.h index 0bcd50abd597..cb1e63ef56f5 100644 --- a/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.h +++ b/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.h @@ -1686,7 +1686,7 @@ struct kbase_tlstream; } while (0) /** - * KBASE_TLSTREAM_TL_JD_DONE_NO_LOCK_START - Within function jd_done_nolock + * KBASE_TLSTREAM_TL_JD_DONE_NO_LOCK_START - Within function kbase_jd_done_nolock * * @kbdev: Kbase device * @atom: Atom identifier @@ -1705,7 +1705,7 @@ struct kbase_tlstream; } while (0) /** - * KBASE_TLSTREAM_TL_JD_DONE_NO_LOCK_END - Within function jd_done_nolock - end + * KBASE_TLSTREAM_TL_JD_DONE_NO_LOCK_END - Within function kbase_jd_done_nolock - end * * @kbdev: Kbase device * @atom: Atom identifier diff --git a/include/linux/memory_group_manager.h b/include/linux/memory_group_manager.h index efa35f5714f7..c4667803b361 100644 --- a/include/linux/memory_group_manager.h +++ b/include/linux/memory_group_manager.h @@ -127,6 +127,16 @@ struct memory_group_manager_ops { u64 (*mgm_update_gpu_pte)(struct memory_group_manager_device *mgm_dev, int group_id, int mmu_level, u64 pte); + /* + * Undo any modifications done during mgm_update_gpu_pte(). + * This function allows getting back the original PTE entry as given + * to mgm_update_gpu_pte(). + * + * Return: PTE entry as originally specified to mgm_update_gpu_pte() + */ + u64 (*mgm_pte_to_original_pte)(struct memory_group_manager_device *mgm_dev, int group_id, + int mmu_level, u64 pte); + /* * mgm_vmf_insert_pfn_prot - Map a physical page in a group for the CPU * diff --git a/include/linux/version_compat_defs.h b/include/linux/version_compat_defs.h new file mode 100644 index 000000000000..a8e08742069d --- /dev/null +++ b/include/linux/version_compat_defs.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * + * (C) COPYRIGHT 2022 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-2.0.html. + * + */ + +#ifndef _VERSION_COMPAT_DEFS_H_ +#define _VERSION_COMPAT_DEFS_H_ + +#include + +#if KERNEL_VERSION(4, 16, 0) >= LINUX_VERSION_CODE +typedef unsigned int __poll_t; +#endif + +#endif /* _VERSION_COMPAT_DEFS_H_ */ diff --git a/include/uapi/gpu/arm/bifrost/backend/gpu/mali_kbase_model_dummy.h b/include/uapi/gpu/arm/bifrost/backend/gpu/mali_kbase_model_dummy.h index 8a3cc6bea6ac..613eb1fdd081 100644 --- a/include/uapi/gpu/arm/bifrost/backend/gpu/mali_kbase_model_dummy.h +++ b/include/uapi/gpu/arm/bifrost/backend/gpu/mali_kbase_model_dummy.h @@ -43,8 +43,11 @@ (KBASE_DUMMY_MODEL_VALUES_PER_BLOCK * sizeof(__u32)) #define KBASE_DUMMY_MODEL_MAX_MEMSYS_BLOCKS 8 #define KBASE_DUMMY_MODEL_MAX_SHADER_CORES 32 -#define KBASE_DUMMY_MODEL_MAX_NUM_PERF_BLOCKS \ +#define KBASE_DUMMY_MODEL_MAX_FIRMWARE_BLOCKS 0 +#define KBASE_DUMMY_MODEL_MAX_NUM_HARDWARE_BLOCKS \ (1 + 1 + KBASE_DUMMY_MODEL_MAX_MEMSYS_BLOCKS + KBASE_DUMMY_MODEL_MAX_SHADER_CORES) +#define KBASE_DUMMY_MODEL_MAX_NUM_PERF_BLOCKS \ + (KBASE_DUMMY_MODEL_MAX_NUM_HARDWARE_BLOCKS + KBASE_DUMMY_MODEL_MAX_FIRMWARE_BLOCKS) #define KBASE_DUMMY_MODEL_COUNTER_TOTAL \ (KBASE_DUMMY_MODEL_MAX_NUM_PERF_BLOCKS * \ KBASE_DUMMY_MODEL_COUNTER_PER_CORE) diff --git a/include/uapi/gpu/arm/bifrost/csf/mali_base_csf_kernel.h b/include/uapi/gpu/arm/bifrost/csf/mali_base_csf_kernel.h index 0543da02f20f..3b02350c08bf 100644 --- a/include/uapi/gpu/arm/bifrost/csf/mali_base_csf_kernel.h +++ b/include/uapi/gpu/arm/bifrost/csf/mali_base_csf_kernel.h @@ -23,99 +23,16 @@ #define _UAPI_BASE_CSF_KERNEL_H_ #include +#include "../mali_base_common_kernel.h" -/* Memory allocation, access/hint flags. +/* Memory allocation, access/hint flags & mask specific to CSF GPU. * * See base_mem_alloc_flags. */ -/* IN */ -/* Read access CPU side - */ -#define BASE_MEM_PROT_CPU_RD ((base_mem_alloc_flags)1 << 0) - -/* Write access CPU side - */ -#define BASE_MEM_PROT_CPU_WR ((base_mem_alloc_flags)1 << 1) - -/* Read access GPU side - */ -#define BASE_MEM_PROT_GPU_RD ((base_mem_alloc_flags)1 << 2) - -/* Write access GPU side - */ -#define BASE_MEM_PROT_GPU_WR ((base_mem_alloc_flags)1 << 3) - -/* Execute allowed on the GPU side - */ -#define BASE_MEM_PROT_GPU_EX ((base_mem_alloc_flags)1 << 4) - -/* Will be permanently mapped in kernel space. - * Flag is only allowed on allocations originating from kbase. - */ -#define BASEP_MEM_PERMANENT_KERNEL_MAPPING ((base_mem_alloc_flags)1 << 5) - -/* The allocation will completely reside within the same 4GB chunk in the GPU - * virtual space. - * Since this flag is primarily required only for the TLS memory which will - * not be used to contain executable code and also not used for Tiler heap, - * it can't be used along with BASE_MEM_PROT_GPU_EX and TILER_ALIGN_TOP flags. - */ -#define BASE_MEM_GPU_VA_SAME_4GB_PAGE ((base_mem_alloc_flags)1 << 6) - -/* Userspace is not allowed to free this memory. - * Flag is only allowed on allocations originating from kbase. - */ -#define BASEP_MEM_NO_USER_FREE ((base_mem_alloc_flags)1 << 7) - /* Must be FIXED memory. */ #define BASE_MEM_FIXED ((base_mem_alloc_flags)1 << 8) -/* Grow backing store on GPU Page Fault - */ -#define BASE_MEM_GROW_ON_GPF ((base_mem_alloc_flags)1 << 9) - -/* Page coherence Outer shareable, if available - */ -#define BASE_MEM_COHERENT_SYSTEM ((base_mem_alloc_flags)1 << 10) - -/* Page coherence Inner shareable - */ -#define BASE_MEM_COHERENT_LOCAL ((base_mem_alloc_flags)1 << 11) - -/* IN/OUT */ -/* Should be cached on the CPU, returned if actually cached - */ -#define BASE_MEM_CACHED_CPU ((base_mem_alloc_flags)1 << 12) - -/* IN/OUT */ -/* Must have same VA on both the GPU and the CPU - */ -#define BASE_MEM_SAME_VA ((base_mem_alloc_flags)1 << 13) - -/* OUT */ -/* Must call mmap to acquire a GPU address for the alloc - */ -#define BASE_MEM_NEED_MMAP ((base_mem_alloc_flags)1 << 14) - -/* IN */ -/* Page coherence Outer shareable, required. - */ -#define BASE_MEM_COHERENT_SYSTEM_REQUIRED ((base_mem_alloc_flags)1 << 15) - -/* Protected memory - */ -#define BASE_MEM_PROTECTED ((base_mem_alloc_flags)1 << 16) - -/* Not needed physical memory - */ -#define BASE_MEM_DONT_NEED ((base_mem_alloc_flags)1 << 17) - -/* Must use shared CPU/GPU zone (SAME_VA zone) but doesn't require the - * addresses to be the same - */ -#define BASE_MEM_IMPORT_SHARED ((base_mem_alloc_flags)1 << 18) - /* CSF event memory * * If Outer shareable coherence is not specified or not available, then on @@ -131,46 +48,15 @@ #define BASE_MEM_RESERVED_BIT_20 ((base_mem_alloc_flags)1 << 20) -/* Should be uncached on the GPU, will work only for GPUs using AARCH64 mmu - * mode. Some components within the GPU might only be able to access memory - * that is GPU cacheable. Refer to the specific GPU implementation for more - * details. The 3 shareability flags will be ignored for GPU uncached memory. - * If used while importing USER_BUFFER type memory, then the import will fail - * if the memory is not aligned to GPU and CPU cache line width. - */ -#define BASE_MEM_UNCACHED_GPU ((base_mem_alloc_flags)1 << 21) - -/* - * Bits [22:25] for group_id (0~15). - * - * base_mem_group_id_set() should be used to pack a memory group ID into a - * base_mem_alloc_flags value instead of accessing the bits directly. - * base_mem_group_id_get() should be used to extract the memory group ID from - * a base_mem_alloc_flags value. - */ -#define BASEP_MEM_GROUP_ID_SHIFT 22 -#define BASE_MEM_GROUP_ID_MASK \ - ((base_mem_alloc_flags)0xF << BASEP_MEM_GROUP_ID_SHIFT) - -/* Must do CPU cache maintenance when imported memory is mapped/unmapped - * on GPU. Currently applicable to dma-buf type only. - */ -#define BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP ((base_mem_alloc_flags)1 << 26) - -/* OUT */ -/* Kernel side cache sync ops required */ -#define BASE_MEM_KERNEL_SYNC ((base_mem_alloc_flags)1 << 28) /* Must be FIXABLE memory: its GPU VA will be determined at a later point, * at which time it will be at a fixed GPU VA. */ #define BASE_MEM_FIXABLE ((base_mem_alloc_flags)1 << 29) -/* Number of bits used as flags for base memory management - * - * Must be kept in sync with the base_mem_alloc_flags flags +/* Note that the number of bits used for base_mem_alloc_flags + * must be less than BASE_MEM_FLAGS_NR_BITS !!! */ -#define BASE_MEM_FLAGS_NR_BITS 30 /* A mask of all the flags which are only valid for allocations within kbase, * and may not be passed from user space. @@ -178,30 +64,14 @@ #define BASEP_MEM_FLAGS_KERNEL_ONLY \ (BASEP_MEM_PERMANENT_KERNEL_MAPPING | BASEP_MEM_NO_USER_FREE) -/* A mask for all output bits, excluding IN/OUT bits. - */ -#define BASE_MEM_FLAGS_OUTPUT_MASK BASE_MEM_NEED_MMAP - -/* A mask for all input bits, including IN/OUT bits. - */ -#define BASE_MEM_FLAGS_INPUT_MASK \ - (((1 << BASE_MEM_FLAGS_NR_BITS) - 1) & ~BASE_MEM_FLAGS_OUTPUT_MASK) - /* A mask of all currently reserved flags */ #define BASE_MEM_FLAGS_RESERVED BASE_MEM_RESERVED_BIT_20 -#define BASEP_MEM_INVALID_HANDLE (0ul) -#define BASE_MEM_MMU_DUMP_HANDLE (1ul << LOCAL_PAGE_SHIFT) -#define BASE_MEM_TRACE_BUFFER_HANDLE (2ul << LOCAL_PAGE_SHIFT) -#define BASE_MEM_MAP_TRACKING_HANDLE (3ul << LOCAL_PAGE_SHIFT) -#define BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE (4ul << LOCAL_PAGE_SHIFT) -/* reserved handles ..-47< for future special handles */ +/* Special base mem handles specific to CSF. + */ #define BASEP_MEM_CSF_USER_REG_PAGE_HANDLE (47ul << LOCAL_PAGE_SHIFT) #define BASEP_MEM_CSF_USER_IO_PAGES_HANDLE (48ul << LOCAL_PAGE_SHIFT) -#define BASE_MEM_COOKIE_BASE (64ul << LOCAL_PAGE_SHIFT) -#define BASE_MEM_FIRST_FREE_ADDRESS \ - ((BITS_PER_LONG << LOCAL_PAGE_SHIFT) + BASE_MEM_COOKIE_BASE) #define KBASE_CSF_NUM_USER_IO_PAGES_HANDLE \ ((BASE_MEM_COOKIE_BASE - BASEP_MEM_CSF_USER_IO_PAGES_HANDLE) >> \ @@ -210,28 +80,7 @@ /* Valid set of just-in-time memory allocation flags */ #define BASE_JIT_ALLOC_VALID_FLAGS ((__u8)0) -/* Flags to pass to ::base_context_init. - * Flags can be ORed together to enable multiple things. - * - * These share the same space as BASEP_CONTEXT_FLAG_*, and so must - * not collide with them. - */ -typedef __u32 base_context_create_flags; - -/* No flags set */ -#define BASE_CONTEXT_CREATE_FLAG_NONE ((base_context_create_flags)0) - -/* Base context is embedded in a cctx object (flag used for CINSTR - * software counter macros) - */ -#define BASE_CONTEXT_CCTX_EMBEDDED ((base_context_create_flags)1 << 0) - -/* Base context is a 'System Monitor' context for Hardware counters. - * - * One important side effect of this is that job submission is disabled. - */ -#define BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED \ - ((base_context_create_flags)1 << 1) +/* flags for base context specific to CSF */ /* Base context creates a CSF event notification thread. * @@ -240,22 +89,6 @@ typedef __u32 base_context_create_flags; */ #define BASE_CONTEXT_CSF_EVENT_THREAD ((base_context_create_flags)1 << 2) -/* Bit-shift used to encode a memory group ID in base_context_create_flags - */ -#define BASEP_CONTEXT_MMU_GROUP_ID_SHIFT (3) - -/* Bitmask used to encode a memory group ID in base_context_create_flags - */ -#define BASEP_CONTEXT_MMU_GROUP_ID_MASK \ - ((base_context_create_flags)0xF << BASEP_CONTEXT_MMU_GROUP_ID_SHIFT) - -/* Bitpattern describing the base_context_create_flags that can be - * passed to the kernel - */ -#define BASEP_CONTEXT_CREATE_KERNEL_FLAGS \ - (BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED | \ - BASEP_CONTEXT_MMU_GROUP_ID_MASK) - /* Bitpattern describing the ::base_context_create_flags that can be * passed to base_context_init() */ @@ -264,15 +97,7 @@ typedef __u32 base_context_create_flags; BASE_CONTEXT_CSF_EVENT_THREAD | \ BASEP_CONTEXT_CREATE_KERNEL_FLAGS) -/* Enable additional tracepoints for latency measurements (TL_ATOM_READY, - * TL_ATOM_DONE, TL_ATOM_PRIO_CHANGE, TL_ATOM_EVENT_POST) - */ -#define BASE_TLSTREAM_ENABLE_LATENCY_TRACEPOINTS (1 << 0) - -/* Indicate that job dumping is enabled. This could affect certain timers - * to account for the performance impact. - */ -#define BASE_TLSTREAM_JOB_DUMPING_ENABLED (1 << 1) +/* Flags for base tracepoint specific to CSF */ /* Enable KBase tracepoints for CSF builds */ #define BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS (1 << 2) @@ -304,6 +129,10 @@ typedef __u32 base_context_create_flags; */ #define BASEP_KCPU_CQS_MAX_NUM_OBJS ((size_t)32) +/* CSF CSI EXCEPTION_HANDLER_FLAGS */ +#define BASE_CSF_TILER_OOM_EXCEPTION_FLAG (1u << 0) +#define BASE_CSF_EXCEPTION_HANDLER_FLAGS_MASK (BASE_CSF_TILER_OOM_EXCEPTION_FLAG) + /** * enum base_kcpu_command_type - Kernel CPU queue command type. * @BASE_KCPU_COMMAND_TYPE_FENCE_SIGNAL: fence_signal, @@ -723,4 +552,45 @@ struct base_csf_notification { } payload; }; +/** + * struct mali_base_gpu_core_props - GPU core props info + * + * @product_id: Pro specific value. + * @version_status: Status of the GPU release. No defined values, but starts at + * 0 and increases by one for each release status (alpha, beta, EAC, etc.). + * 4 bit values (0-15). + * @minor_revision: Minor release number of the GPU. "P" part of an "RnPn" + * release number. + * 8 bit values (0-255). + * @major_revision: Major release number of the GPU. "R" part of an "RnPn" + * release number. + * 4 bit values (0-15). + * @padding: padding to align to 8-byte + * @gpu_freq_khz_max: The maximum GPU frequency. Reported to applications by + * clGetDeviceInfo() + * @log2_program_counter_size: Size of the shader program counter, in bits. + * @texture_features: TEXTURE_FEATURES_x registers, as exposed by the GPU. This + * is a bitpattern where a set bit indicates that the format is supported. + * Before using a texture format, it is recommended that the corresponding + * bit be checked. + * @gpu_available_memory_size: Theoretical maximum memory available to the GPU. + * It is unlikely that a client will be able to allocate all of this memory + * for their own purposes, but this at least provides an upper bound on the + * memory available to the GPU. + * This is required for OpenCL's clGetDeviceInfo() call when + * CL_DEVICE_GLOBAL_MEM_SIZE is requested, for OpenCL GPU devices. The + * client will not be expecting to allocate anywhere near this value. + */ +struct mali_base_gpu_core_props { + __u32 product_id; + __u16 version_status; + __u16 minor_revision; + __u16 major_revision; + __u16 padding; + __u32 gpu_freq_khz_max; + __u32 log2_program_counter_size; + __u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + __u64 gpu_available_memory_size; +}; + #endif /* _UAPI_BASE_CSF_KERNEL_H_ */ diff --git a/include/uapi/gpu/arm/bifrost/csf/mali_kbase_csf_ioctl.h b/include/uapi/gpu/arm/bifrost/csf/mali_kbase_csf_ioctl.h index 00d2585f4aef..db7252605f06 100644 --- a/include/uapi/gpu/arm/bifrost/csf/mali_kbase_csf_ioctl.h +++ b/include/uapi/gpu/arm/bifrost/csf/mali_kbase_csf_ioctl.h @@ -58,10 +58,12 @@ * - First release of new HW performance counters interface. * 1.11: * - Dummy model (no mali) backend will now clear HWC values after each sample + * 1.12: + * - Added support for incremental rendering flag in CSG create call */ #define BASE_UK_VERSION_MAJOR 1 -#define BASE_UK_VERSION_MINOR 11 +#define BASE_UK_VERSION_MINOR 12 /** * struct kbase_ioctl_version_check - Check version compatibility between @@ -247,6 +249,9 @@ union kbase_ioctl_cs_queue_group_create_1_6 { * allowed to use. * @in.compute_max: Maximum number of compute endpoints the group is allowed * to use. + * @in.csi_handlers: Flags to signal that the application intends to use CSI + * exception handlers in some linear buffers to deal with + * the given exception types. * @in.padding: Currently unused, must be zero * @out: Output parameters * @out.group_handle: Handle of a newly created queue group. @@ -263,7 +268,8 @@ union kbase_ioctl_cs_queue_group_create { __u8 tiler_max; __u8 fragment_max; __u8 compute_max; - __u8 padding[3]; + __u8 csi_handlers; + __u8 padding[2]; /** * @in.reserved: Reserved */ diff --git a/include/uapi/gpu/arm/bifrost/jm/mali_base_jm_kernel.h b/include/uapi/gpu/arm/bifrost/jm/mali_base_jm_kernel.h index 94f4dc701be2..ae43908b9360 100644 --- a/include/uapi/gpu/arm/bifrost/jm/mali_base_jm_kernel.h +++ b/include/uapi/gpu/arm/bifrost/jm/mali_base_jm_kernel.h @@ -23,100 +23,16 @@ #define _UAPI_BASE_JM_KERNEL_H_ #include +#include "../mali_base_common_kernel.h" -/* Memory allocation, access/hint flags. +/* Memory allocation, access/hint flags & mask specific to JM GPU. * * See base_mem_alloc_flags. */ -/* IN */ -/* Read access CPU side - */ -#define BASE_MEM_PROT_CPU_RD ((base_mem_alloc_flags)1 << 0) - -/* Write access CPU side - */ -#define BASE_MEM_PROT_CPU_WR ((base_mem_alloc_flags)1 << 1) - -/* Read access GPU side - */ -#define BASE_MEM_PROT_GPU_RD ((base_mem_alloc_flags)1 << 2) - -/* Write access GPU side - */ -#define BASE_MEM_PROT_GPU_WR ((base_mem_alloc_flags)1 << 3) - -/* Execute allowed on the GPU side - */ -#define BASE_MEM_PROT_GPU_EX ((base_mem_alloc_flags)1 << 4) - -/* Will be permanently mapped in kernel space. - * Flag is only allowed on allocations originating from kbase. - */ -#define BASEP_MEM_PERMANENT_KERNEL_MAPPING ((base_mem_alloc_flags)1 << 5) - -/* The allocation will completely reside within the same 4GB chunk in the GPU - * virtual space. - * Since this flag is primarily required only for the TLS memory which will - * not be used to contain executable code and also not used for Tiler heap, - * it can't be used along with BASE_MEM_PROT_GPU_EX and TILER_ALIGN_TOP flags. - */ -#define BASE_MEM_GPU_VA_SAME_4GB_PAGE ((base_mem_alloc_flags)1 << 6) - -/* Userspace is not allowed to free this memory. - * Flag is only allowed on allocations originating from kbase. - */ -#define BASEP_MEM_NO_USER_FREE ((base_mem_alloc_flags)1 << 7) - -/* Used as BASE_MEM_FIXED in other backends - */ +/* Used as BASE_MEM_FIXED in other backends */ #define BASE_MEM_RESERVED_BIT_8 ((base_mem_alloc_flags)1 << 8) -/* Grow backing store on GPU Page Fault - */ -#define BASE_MEM_GROW_ON_GPF ((base_mem_alloc_flags)1 << 9) - -/* Page coherence Outer shareable, if available - */ -#define BASE_MEM_COHERENT_SYSTEM ((base_mem_alloc_flags)1 << 10) - -/* Page coherence Inner shareable - */ -#define BASE_MEM_COHERENT_LOCAL ((base_mem_alloc_flags)1 << 11) - -/* IN/OUT */ -/* Should be cached on the CPU, returned if actually cached - */ -#define BASE_MEM_CACHED_CPU ((base_mem_alloc_flags)1 << 12) - -/* IN/OUT */ -/* Must have same VA on both the GPU and the CPU - */ -#define BASE_MEM_SAME_VA ((base_mem_alloc_flags)1 << 13) - -/* OUT */ -/* Must call mmap to acquire a GPU address for the allocation - */ -#define BASE_MEM_NEED_MMAP ((base_mem_alloc_flags)1 << 14) - -/* IN */ -/* Page coherence Outer shareable, required. - */ -#define BASE_MEM_COHERENT_SYSTEM_REQUIRED ((base_mem_alloc_flags)1 << 15) - -/* Protected memory - */ -#define BASE_MEM_PROTECTED ((base_mem_alloc_flags)1 << 16) - -/* Not needed physical memory - */ -#define BASE_MEM_DONT_NEED ((base_mem_alloc_flags)1 << 17) - -/* Must use shared CPU/GPU zone (SAME_VA zone) but doesn't require the - * addresses to be the same - */ -#define BASE_MEM_IMPORT_SHARED ((base_mem_alloc_flags)1 << 18) - /** * BASE_MEM_RESERVED_BIT_19 - Bit 19 is reserved. * @@ -131,47 +47,15 @@ */ #define BASE_MEM_TILER_ALIGN_TOP ((base_mem_alloc_flags)1 << 20) -/* Should be uncached on the GPU, will work only for GPUs using AARCH64 mmu - * mode. Some components within the GPU might only be able to access memory - * that is GPU cacheable. Refer to the specific GPU implementation for more - * details. The 3 shareability flags will be ignored for GPU uncached memory. - * If used while importing USER_BUFFER type memory, then the import will fail - * if the memory is not aligned to GPU and CPU cache line width. - */ -#define BASE_MEM_UNCACHED_GPU ((base_mem_alloc_flags)1 << 21) - -/* - * Bits [22:25] for group_id (0~15). - * - * base_mem_group_id_set() should be used to pack a memory group ID into a - * base_mem_alloc_flags value instead of accessing the bits directly. - * base_mem_group_id_get() should be used to extract the memory group ID from - * a base_mem_alloc_flags value. - */ -#define BASEP_MEM_GROUP_ID_SHIFT 22 -#define BASE_MEM_GROUP_ID_MASK \ - ((base_mem_alloc_flags)0xF << BASEP_MEM_GROUP_ID_SHIFT) - -/* Must do CPU cache maintenance when imported memory is mapped/unmapped - * on GPU. Currently applicable to dma-buf type only. - */ -#define BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP ((base_mem_alloc_flags)1 << 26) - /* Use the GPU VA chosen by the kernel client */ #define BASE_MEM_FLAG_MAP_FIXED ((base_mem_alloc_flags)1 << 27) -/* OUT */ -/* Kernel side cache sync ops required */ -#define BASE_MEM_KERNEL_SYNC ((base_mem_alloc_flags)1 << 28) - /* Force trimming of JIT allocations when creating a new allocation */ #define BASEP_MEM_PERFORM_JIT_TRIM ((base_mem_alloc_flags)1 << 29) -/* Number of bits used as flags for base memory management - * - * Must be kept in sync with the base_mem_alloc_flags flags +/* Note that the number of bits used for base_mem_alloc_flags + * must be less than BASE_MEM_FLAGS_NR_BITS !!! */ -#define BASE_MEM_FLAGS_NR_BITS 30 /* A mask of all the flags which are only valid for allocations within kbase, * and may not be passed from user space. @@ -180,29 +64,11 @@ (BASEP_MEM_PERMANENT_KERNEL_MAPPING | BASEP_MEM_NO_USER_FREE | \ BASE_MEM_FLAG_MAP_FIXED | BASEP_MEM_PERFORM_JIT_TRIM) -/* A mask for all output bits, excluding IN/OUT bits. - */ -#define BASE_MEM_FLAGS_OUTPUT_MASK BASE_MEM_NEED_MMAP - -/* A mask for all input bits, including IN/OUT bits. - */ -#define BASE_MEM_FLAGS_INPUT_MASK \ - (((1 << BASE_MEM_FLAGS_NR_BITS) - 1) & ~BASE_MEM_FLAGS_OUTPUT_MASK) - /* A mask of all currently reserved flags */ #define BASE_MEM_FLAGS_RESERVED \ (BASE_MEM_RESERVED_BIT_8 | BASE_MEM_RESERVED_BIT_19) -#define BASEP_MEM_INVALID_HANDLE (0ul) -#define BASE_MEM_MMU_DUMP_HANDLE (1ul << LOCAL_PAGE_SHIFT) -#define BASE_MEM_TRACE_BUFFER_HANDLE (2ul << LOCAL_PAGE_SHIFT) -#define BASE_MEM_MAP_TRACKING_HANDLE (3ul << LOCAL_PAGE_SHIFT) -#define BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE (4ul << LOCAL_PAGE_SHIFT) -/* reserved handles ..-47< for future special handles */ -#define BASE_MEM_COOKIE_BASE (64ul << LOCAL_PAGE_SHIFT) -#define BASE_MEM_FIRST_FREE_ADDRESS \ - ((BITS_PER_LONG << LOCAL_PAGE_SHIFT) + BASE_MEM_COOKIE_BASE) /* Similar to BASE_MEM_TILER_ALIGN_TOP, memory starting from the end of the * initial commit is aligned to 'extension' pages, where 'extension' must be a power @@ -227,47 +93,6 @@ #define BASE_JIT_ALLOC_VALID_FLAGS \ (BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP | BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE) -/** - * typedef base_context_create_flags - Flags to pass to ::base_context_init. - * - * Flags can be ORed together to enable multiple things. - * - * These share the same space as BASEP_CONTEXT_FLAG_*, and so must - * not collide with them. - */ -typedef __u32 base_context_create_flags; - -/* No flags set */ -#define BASE_CONTEXT_CREATE_FLAG_NONE ((base_context_create_flags)0) - -/* Base context is embedded in a cctx object (flag used for CINSTR - * software counter macros) - */ -#define BASE_CONTEXT_CCTX_EMBEDDED ((base_context_create_flags)1 << 0) - -/* Base context is a 'System Monitor' context for Hardware counters. - * - * One important side effect of this is that job submission is disabled. - */ -#define BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED \ - ((base_context_create_flags)1 << 1) - -/* Bit-shift used to encode a memory group ID in base_context_create_flags - */ -#define BASEP_CONTEXT_MMU_GROUP_ID_SHIFT (3) - -/* Bitmask used to encode a memory group ID in base_context_create_flags - */ -#define BASEP_CONTEXT_MMU_GROUP_ID_MASK \ - ((base_context_create_flags)0xF << BASEP_CONTEXT_MMU_GROUP_ID_SHIFT) - -/* Bitpattern describing the base_context_create_flags that can be - * passed to the kernel - */ -#define BASEP_CONTEXT_CREATE_KERNEL_FLAGS \ - (BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED | \ - BASEP_CONTEXT_MMU_GROUP_ID_MASK) - /* Bitpattern describing the ::base_context_create_flags that can be * passed to base_context_init() */ @@ -287,16 +112,7 @@ typedef __u32 base_context_create_flags; #define BASEP_CONTEXT_FLAG_JOB_DUMP_DISABLED \ ((base_context_create_flags)(1 << 31)) -/* Enable additional tracepoints for latency measurements (TL_ATOM_READY, - * TL_ATOM_DONE, TL_ATOM_PRIO_CHANGE, TL_ATOM_EVENT_POST) - */ -#define BASE_TLSTREAM_ENABLE_LATENCY_TRACEPOINTS (1 << 0) - -/* Indicate that job dumping is enabled. This could affect certain timers - * to account for the performance impact. - */ -#define BASE_TLSTREAM_JOB_DUMPING_ENABLED (1 << 1) - +/* Flags for base tracepoint specific to JM */ #define BASE_TLSTREAM_FLAGS_MASK (BASE_TLSTREAM_ENABLE_LATENCY_TRACEPOINTS | \ BASE_TLSTREAM_JOB_DUMPING_ENABLED) /* @@ -509,9 +325,6 @@ typedef __u32 base_jd_core_req; * takes priority * * This is only guaranteed to work for BASE_JD_REQ_ONLY_COMPUTE atoms. - * - * If the core availability policy is keeping the required core group turned - * off, then the job will fail with a BASE_JD_EVENT_PM_EVENT error code. */ #define BASE_JD_REQ_SPECIFIC_COHERENT_GROUP ((base_jd_core_req)1 << 11) @@ -770,6 +583,9 @@ typedef __u8 base_jd_prio; */ #define BASE_JD_PRIO_REALTIME ((base_jd_prio)3) +/* Invalid atom priority (max uint8_t value) */ +#define BASE_JD_PRIO_INVALID ((base_jd_prio)255) + /* Count of the number of priority levels. This itself is not a valid * base_jd_prio setting */ @@ -1016,11 +832,6 @@ enum { * BASE_JD_EVENT_JOB_CONFIG_FAULT, or if the * platform doesn't support the feature specified in * the atom. - * @BASE_JD_EVENT_PM_EVENT: TODO: remove as it's not used - * @BASE_JD_EVENT_TIMED_OUT: TODO: remove as it's not used - * @BASE_JD_EVENT_BAG_INVALID: TODO: remove as it's not used - * @BASE_JD_EVENT_PROGRESS_REPORT: TODO: remove as it's not used - * @BASE_JD_EVENT_BAG_DONE: TODO: remove as it's not used * @BASE_JD_EVENT_DRV_TERMINATED: this is a special event generated to indicate * to userspace that the KBase context has been * destroyed and Base should stop listening for @@ -1115,17 +926,10 @@ enum base_jd_event_code { /* SW defined exceptions */ BASE_JD_EVENT_MEM_GROWTH_FAILED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x000, - BASE_JD_EVENT_TIMED_OUT = - BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x001, BASE_JD_EVENT_JOB_CANCELLED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x002, BASE_JD_EVENT_JOB_INVALID = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x003, - BASE_JD_EVENT_PM_EVENT = - BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x004, - - BASE_JD_EVENT_BAG_INVALID = - BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_BAG | 0x003, BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_RESERVED | 0x3FF, @@ -1133,10 +937,6 @@ enum base_jd_event_code { BASE_JD_EVENT_RANGE_SW_SUCCESS_START = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | 0x000, - BASE_JD_EVENT_PROGRESS_REPORT = BASE_JD_SW_EVENT | - BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_JOB | 0x000, - BASE_JD_EVENT_BAG_DONE = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | - BASE_JD_SW_EVENT_BAG | 0x000, BASE_JD_EVENT_DRV_TERMINATED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | BASE_JD_SW_EVENT_INFO | 0x000, @@ -1203,4 +1003,49 @@ struct base_dump_cpu_gpu_counters { __u8 padding[36]; }; +/** + * struct mali_base_gpu_core_props - GPU core props info + * + * @product_id: Pro specific value. + * @version_status: Status of the GPU release. No defined values, but starts at + * 0 and increases by one for each release status (alpha, beta, EAC, etc.). + * 4 bit values (0-15). + * @minor_revision: Minor release number of the GPU. "P" part of an "RnPn" + * release number. + * 8 bit values (0-255). + * @major_revision: Major release number of the GPU. "R" part of an "RnPn" + * release number. + * 4 bit values (0-15). + * @padding: padding to align to 8-byte + * @gpu_freq_khz_max: The maximum GPU frequency. Reported to applications by + * clGetDeviceInfo() + * @log2_program_counter_size: Size of the shader program counter, in bits. + * @texture_features: TEXTURE_FEATURES_x registers, as exposed by the GPU. This + * is a bitpattern where a set bit indicates that the format is supported. + * Before using a texture format, it is recommended that the corresponding + * bit be checked. + * @gpu_available_memory_size: Theoretical maximum memory available to the GPU. + * It is unlikely that a client will be able to allocate all of this memory + * for their own purposes, but this at least provides an upper bound on the + * memory available to the GPU. + * This is required for OpenCL's clGetDeviceInfo() call when + * CL_DEVICE_GLOBAL_MEM_SIZE is requested, for OpenCL GPU devices. The + * client will not be expecting to allocate anywhere near this value. + * @num_exec_engines: The number of execution engines. Only valid for tGOX + * (Bifrost) GPUs, where GPU_HAS_REG_CORE_FEATURES is defined. Otherwise, + * this is always 0. + */ +struct mali_base_gpu_core_props { + __u32 product_id; + __u16 version_status; + __u16 minor_revision; + __u16 major_revision; + __u16 padding; + __u32 gpu_freq_khz_max; + __u32 log2_program_counter_size; + __u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + __u64 gpu_available_memory_size; + __u8 num_exec_engines; +}; + #endif /* _UAPI_BASE_JM_KERNEL_H_ */ diff --git a/include/uapi/gpu/arm/bifrost/mali_base_common_kernel.h b/include/uapi/gpu/arm/bifrost/mali_base_common_kernel.h new file mode 100644 index 000000000000..f8378146aceb --- /dev/null +++ b/include/uapi/gpu/arm/bifrost/mali_base_common_kernel.h @@ -0,0 +1,231 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * + * (C) COPYRIGHT 2022 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you can access it online at + * http://www.gnu.org/licenses/gpl-2.0.html. + * + */ + +#ifndef _UAPI_BASE_COMMON_KERNEL_H_ +#define _UAPI_BASE_COMMON_KERNEL_H_ + +#include + +struct base_mem_handle { + struct { + __u64 handle; + } basep; +}; + +#define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 4 + +/* Memory allocation, access/hint flags & mask. + * + * See base_mem_alloc_flags. + */ + +/* IN */ +/* Read access CPU side + */ +#define BASE_MEM_PROT_CPU_RD ((base_mem_alloc_flags)1 << 0) + +/* Write access CPU side + */ +#define BASE_MEM_PROT_CPU_WR ((base_mem_alloc_flags)1 << 1) + +/* Read access GPU side + */ +#define BASE_MEM_PROT_GPU_RD ((base_mem_alloc_flags)1 << 2) + +/* Write access GPU side + */ +#define BASE_MEM_PROT_GPU_WR ((base_mem_alloc_flags)1 << 3) + +/* Execute allowed on the GPU side + */ +#define BASE_MEM_PROT_GPU_EX ((base_mem_alloc_flags)1 << 4) + +/* Will be permanently mapped in kernel space. + * Flag is only allowed on allocations originating from kbase. + */ +#define BASEP_MEM_PERMANENT_KERNEL_MAPPING ((base_mem_alloc_flags)1 << 5) + +/* The allocation will completely reside within the same 4GB chunk in the GPU + * virtual space. + * Since this flag is primarily required only for the TLS memory which will + * not be used to contain executable code and also not used for Tiler heap, + * it can't be used along with BASE_MEM_PROT_GPU_EX and TILER_ALIGN_TOP flags. + */ +#define BASE_MEM_GPU_VA_SAME_4GB_PAGE ((base_mem_alloc_flags)1 << 6) + +/* Userspace is not allowed to free this memory. + * Flag is only allowed on allocations originating from kbase. + */ +#define BASEP_MEM_NO_USER_FREE ((base_mem_alloc_flags)1 << 7) + +/* Grow backing store on GPU Page Fault + */ +#define BASE_MEM_GROW_ON_GPF ((base_mem_alloc_flags)1 << 9) + +/* Page coherence Outer shareable, if available + */ +#define BASE_MEM_COHERENT_SYSTEM ((base_mem_alloc_flags)1 << 10) + +/* Page coherence Inner shareable + */ +#define BASE_MEM_COHERENT_LOCAL ((base_mem_alloc_flags)1 << 11) + +/* IN/OUT */ +/* Should be cached on the CPU, returned if actually cached + */ +#define BASE_MEM_CACHED_CPU ((base_mem_alloc_flags)1 << 12) + +/* IN/OUT */ +/* Must have same VA on both the GPU and the CPU + */ +#define BASE_MEM_SAME_VA ((base_mem_alloc_flags)1 << 13) + +/* OUT */ +/* Must call mmap to acquire a GPU address for the allocation + */ +#define BASE_MEM_NEED_MMAP ((base_mem_alloc_flags)1 << 14) + +/* IN */ +/* Page coherence Outer shareable, required. + */ +#define BASE_MEM_COHERENT_SYSTEM_REQUIRED ((base_mem_alloc_flags)1 << 15) + +/* Protected memory + */ +#define BASE_MEM_PROTECTED ((base_mem_alloc_flags)1 << 16) + +/* Not needed physical memory + */ +#define BASE_MEM_DONT_NEED ((base_mem_alloc_flags)1 << 17) + +/* Must use shared CPU/GPU zone (SAME_VA zone) but doesn't require the + * addresses to be the same + */ +#define BASE_MEM_IMPORT_SHARED ((base_mem_alloc_flags)1 << 18) + +/* Should be uncached on the GPU, will work only for GPUs using AARCH64 mmu + * mode. Some components within the GPU might only be able to access memory + * that is GPU cacheable. Refer to the specific GPU implementation for more + * details. The 3 shareability flags will be ignored for GPU uncached memory. + * If used while importing USER_BUFFER type memory, then the import will fail + * if the memory is not aligned to GPU and CPU cache line width. + */ +#define BASE_MEM_UNCACHED_GPU ((base_mem_alloc_flags)1 << 21) + +/* + * Bits [22:25] for group_id (0~15). + * + * base_mem_group_id_set() should be used to pack a memory group ID into a + * base_mem_alloc_flags value instead of accessing the bits directly. + * base_mem_group_id_get() should be used to extract the memory group ID from + * a base_mem_alloc_flags value. + */ +#define BASEP_MEM_GROUP_ID_SHIFT 22 +#define BASE_MEM_GROUP_ID_MASK ((base_mem_alloc_flags)0xF << BASEP_MEM_GROUP_ID_SHIFT) + +/* Must do CPU cache maintenance when imported memory is mapped/unmapped + * on GPU. Currently applicable to dma-buf type only. + */ +#define BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP ((base_mem_alloc_flags)1 << 26) + +/* OUT */ +/* Kernel side cache sync ops required */ +#define BASE_MEM_KERNEL_SYNC ((base_mem_alloc_flags)1 << 28) + +/* Number of bits used as flags for base memory management + * + * Must be kept in sync with the base_mem_alloc_flags flags + */ +#define BASE_MEM_FLAGS_NR_BITS 30 + +/* A mask for all output bits, excluding IN/OUT bits. + */ +#define BASE_MEM_FLAGS_OUTPUT_MASK BASE_MEM_NEED_MMAP + +/* A mask for all input bits, including IN/OUT bits. + */ +#define BASE_MEM_FLAGS_INPUT_MASK \ + (((1 << BASE_MEM_FLAGS_NR_BITS) - 1) & ~BASE_MEM_FLAGS_OUTPUT_MASK) + +/* Special base mem handles. + */ +#define BASEP_MEM_INVALID_HANDLE (0ul) +#define BASE_MEM_MMU_DUMP_HANDLE (1ul << LOCAL_PAGE_SHIFT) +#define BASE_MEM_TRACE_BUFFER_HANDLE (2ul << LOCAL_PAGE_SHIFT) +#define BASE_MEM_MAP_TRACKING_HANDLE (3ul << LOCAL_PAGE_SHIFT) +#define BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE (4ul << LOCAL_PAGE_SHIFT) +/* reserved handles ..-47< for future special handles */ +#define BASE_MEM_COOKIE_BASE (64ul << LOCAL_PAGE_SHIFT) +#define BASE_MEM_FIRST_FREE_ADDRESS ((BITS_PER_LONG << LOCAL_PAGE_SHIFT) + BASE_MEM_COOKIE_BASE) + +/* Flags to pass to ::base_context_init. + * Flags can be ORed together to enable multiple things. + * + * These share the same space as BASEP_CONTEXT_FLAG_*, and so must + * not collide with them. + */ +typedef __u32 base_context_create_flags; + +/* Flags for base context */ + +/* No flags set */ +#define BASE_CONTEXT_CREATE_FLAG_NONE ((base_context_create_flags)0) + +/* Base context is embedded in a cctx object (flag used for CINSTR + * software counter macros) + */ +#define BASE_CONTEXT_CCTX_EMBEDDED ((base_context_create_flags)1 << 0) + +/* Base context is a 'System Monitor' context for Hardware counters. + * + * One important side effect of this is that job submission is disabled. + */ +#define BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED ((base_context_create_flags)1 << 1) + +/* Bit-shift used to encode a memory group ID in base_context_create_flags + */ +#define BASEP_CONTEXT_MMU_GROUP_ID_SHIFT (3) + +/* Bitmask used to encode a memory group ID in base_context_create_flags + */ +#define BASEP_CONTEXT_MMU_GROUP_ID_MASK \ + ((base_context_create_flags)0xF << BASEP_CONTEXT_MMU_GROUP_ID_SHIFT) + +/* Bitpattern describing the base_context_create_flags that can be + * passed to the kernel + */ +#define BASEP_CONTEXT_CREATE_KERNEL_FLAGS \ + (BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED | BASEP_CONTEXT_MMU_GROUP_ID_MASK) + +/* Flags for base tracepoint + */ + +/* Enable additional tracepoints for latency measurements (TL_ATOM_READY, + * TL_ATOM_DONE, TL_ATOM_PRIO_CHANGE, TL_ATOM_EVENT_POST) + */ +#define BASE_TLSTREAM_ENABLE_LATENCY_TRACEPOINTS (1 << 0) + +/* Indicate that job dumping is enabled. This could affect certain timers + * to account for the performance impact. + */ +#define BASE_TLSTREAM_JOB_DUMPING_ENABLED (1 << 1) + +#endif /* _UAPI_BASE_COMMON_KERNEL_H_ */ diff --git a/include/uapi/gpu/arm/bifrost/mali_base_kernel.h b/include/uapi/gpu/arm/bifrost/mali_base_kernel.h index f3ffb361ea2c..6adbd81bcc70 100644 --- a/include/uapi/gpu/arm/bifrost/mali_base_kernel.h +++ b/include/uapi/gpu/arm/bifrost/mali_base_kernel.h @@ -27,19 +27,10 @@ #define _UAPI_BASE_KERNEL_H_ #include - -struct base_mem_handle { - struct { - __u64 handle; - } basep; -}; - #include "mali_base_mem_priv.h" #include "gpu/mali_kbase_gpu_id.h" #include "gpu/mali_kbase_gpu_coherency.h" -#define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 4 - #define BASE_MAX_COHERENT_GROUPS 16 #if defined(PAGE_MASK) && defined(PAGE_SHIFT) @@ -458,49 +449,6 @@ struct base_jd_debug_copy_buffer { * 16 coherent groups, since core groups are typically 4 cores. */ -/** - * struct mali_base_gpu_core_props - GPU core props info - * - * @product_id: Pro specific value. - * @version_status: Status of the GPU release. No defined values, but starts at - * 0 and increases by one for each release status (alpha, beta, EAC, etc.). - * 4 bit values (0-15). - * @minor_revision: Minor release number of the GPU. "P" part of an "RnPn" - * release number. - * 8 bit values (0-255). - * @major_revision: Major release number of the GPU. "R" part of an "RnPn" - * release number. - * 4 bit values (0-15). - * @padding: padding to allign to 8-byte - * @gpu_freq_khz_max: The maximum GPU frequency. Reported to applications by - * clGetDeviceInfo() - * @log2_program_counter_size: Size of the shader program counter, in bits. - * @texture_features: TEXTURE_FEATURES_x registers, as exposed by the GPU. This - * is a bitpattern where a set bit indicates that the format is supported. - * Before using a texture format, it is recommended that the corresponding - * bit be checked. - * @gpu_available_memory_size: Theoretical maximum memory available to the GPU. - * It is unlikely that a client will be able to allocate all of this memory - * for their own purposes, but this at least provides an upper bound on the - * memory available to the GPU. - * This is required for OpenCL's clGetDeviceInfo() call when - * CL_DEVICE_GLOBAL_MEM_SIZE is requested, for OpenCL GPU devices. The - * client will not be expecting to allocate anywhere near this value. - * @num_exec_engines: The number of execution engines. - */ -struct mali_base_gpu_core_props { - __u32 product_id; - __u16 version_status; - __u16 minor_revision; - __u16 major_revision; - __u16 padding; - __u32 gpu_freq_khz_max; - __u32 log2_program_counter_size; - __u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; - __u64 gpu_available_memory_size; - __u8 num_exec_engines; -}; - /* * More information is possible - but associativity and bus width are not * required by upper-level apis. @@ -531,7 +479,7 @@ struct mali_base_gpu_tiler_props { * field. * @impl_tech: 0 = Not specified, 1 = Silicon, 2 = FPGA, * 3 = SW Model/Emulation - * @padding: padding to allign to 8-byte + * @padding: padding to align to 8-byte * @tls_alloc: Number of threads per core that TLS must be * allocated for */ @@ -551,7 +499,7 @@ struct mali_base_gpu_thread_props { * struct mali_base_gpu_coherent_group - descriptor for a coherent group * @core_mask: Core restriction mask required for the group * @num_cores: Number of cores in the group - * @padding: padding to allign to 8-byte + * @padding: padding to align to 8-byte * * \c core_mask exposes all cores in that coherent group, and \c num_cores * provides a cached population-count for that mask. @@ -581,7 +529,7 @@ struct mali_base_gpu_coherent_group { * are in the group[] member. Use num_groups instead. * @coherency: Coherency features of the memory, accessed by gpu_mem_features * methods - * @padding: padding to allign to 8-byte + * @padding: padding to align to 8-byte * @group: Descriptors of coherent groups * * Note that the sizes of the members could be reduced. However, the \c group @@ -599,6 +547,12 @@ struct mali_base_gpu_coherent_group_info { struct mali_base_gpu_coherent_group group[BASE_MAX_COHERENT_GROUPS]; }; +#if MALI_USE_CSF +#include "csf/mali_base_csf_kernel.h" +#else +#include "jm/mali_base_jm_kernel.h" +#endif + /** * struct gpu_raw_gpu_props - A complete description of the GPU's Hardware * Configuration Discovery registers. @@ -696,12 +650,6 @@ struct base_gpu_props { struct mali_base_gpu_coherent_group_info coherency_info; }; -#if MALI_USE_CSF -#include "csf/mali_base_csf_kernel.h" -#else -#include "jm/mali_base_jm_kernel.h" -#endif - #define BASE_MEM_GROUP_ID_GET(flags) \ ((flags & BASE_MEM_GROUP_ID_MASK) >> BASEP_MEM_GROUP_ID_SHIFT) diff --git a/include/uapi/gpu/arm/bifrost/mali_base_mem_priv.h b/include/uapi/gpu/arm/bifrost/mali_base_mem_priv.h index 290662045134..70f5b0977520 100644 --- a/include/uapi/gpu/arm/bifrost/mali_base_mem_priv.h +++ b/include/uapi/gpu/arm/bifrost/mali_base_mem_priv.h @@ -23,8 +23,7 @@ #define _UAPI_BASE_MEM_PRIV_H_ #include - -#include "mali_base_kernel.h" +#include "mali_base_common_kernel.h" #define BASE_SYNCSET_OP_MSYNC (1U << 0) #define BASE_SYNCSET_OP_CSYNC (1U << 1) diff --git a/include/uapi/gpu/arm/bifrost/mali_uk.h b/include/uapi/gpu/arm/bifrost/mali_uk.h deleted file mode 100644 index 78946f675efa..000000000000 --- a/include/uapi/gpu/arm/bifrost/mali_uk.h +++ /dev/null @@ -1,70 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2010, 2012-2015, 2018, 2020-2022 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/** - * DOC: Types and definitions that are common across OSs for both the user - * and kernel side of the User-Kernel interface. - */ - -#ifndef _UAPI_UK_H_ -#define _UAPI_UK_H_ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/** - * DOC: uk_api User-Kernel Interface API - * - * The User-Kernel Interface abstracts the communication mechanism between the user and kernel-side code of device - * drivers developed as part of the Midgard DDK. Currently that includes the Base driver. - * - * It exposes an OS independent API to user-side code (UKU) which routes functions calls to an OS-independent - * kernel-side API (UKK) via an OS-specific communication mechanism. - * - * This API is internal to the Midgard DDK and is not exposed to any applications. - * - */ - -/** - * enum uk_client_id - These are identifiers for kernel-side drivers - * implementing a UK interface, aka UKK clients. - * @UK_CLIENT_MALI_T600_BASE: Value used to identify the Base driver UK client. - * @UK_CLIENT_COUNT: The number of uk clients supported. This must be - * the last member of the enum - * - * The UK module maps this to an OS specific device name, e.g. "gpu_base" -> "GPU0:". Specify this - * identifier to select a UKK client to the uku_open() function. - * - * When a new UKK client driver is created a new identifier needs to be added to the uk_client_id - * enumeration and the uku_open() implemenation for the various OS ports need to be updated to - * provide a mapping of the identifier to the OS specific device name. - * - */ -enum uk_client_id { - UK_CLIENT_MALI_T600_BASE, - UK_CLIENT_COUNT -}; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* _UAPI_UK_H_ */ From d559263e694e1968cf14b79c5b827d23fac4922b Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Wed, 27 Apr 2022 15:31:47 +0800 Subject: [PATCH 103/204] MALI: bifrost: from ARM: handle_oom_event(): ignore "Invalid Heap statistics" error Continue heap chunk alloc. Change-Id: I49aade60f7d2402c7ae268eafb4d717f9147a88e Signed-off-by: Zhen Chen --- drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c index 45174b7caaa7..cc1369ce8766 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c @@ -1990,15 +1990,20 @@ static int handle_oom_event(struct kbase_queue_group *const group, u32 pending_frag_count; u64 new_chunk_ptr; int err; + bool frag_end_err = false; if ((frag_end > vt_end) || (vt_end >= vt_start)) { - dev_warn(kctx->kbdev->dev, "Invalid Heap statistics provided by firmware: vt_start %d, vt_end %d, frag_end %d\n", + frag_end_err = true; + dev_dbg(kctx->kbdev->dev, "Invalid Heap statistics provided by firmware: vt_start %d, vt_end %d, frag_end %d\n", vt_start, vt_end, frag_end); - return -EINVAL; } - - renderpasses_in_flight = vt_start - frag_end; - pending_frag_count = vt_end - frag_end; + if (frag_end_err) { + renderpasses_in_flight = 1; + pending_frag_count = 1; + } else { + renderpasses_in_flight = vt_start - frag_end; + pending_frag_count = vt_end - frag_end; + } err = kbase_csf_tiler_heap_alloc_new_chunk(kctx, gpu_heap_va, renderpasses_in_flight, pending_frag_count, &new_chunk_ptr); From aef810d2c1568b760cab2efa5b4e83a2fce1ebb9 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Mon, 11 Jul 2022 09:45:58 +0800 Subject: [PATCH 104/204] MALI: bifrost: from ARM: do a faster & cleaner reset for unrecoverable CS_FATAL This is part of the workaround for HW_issue_of_fragment_endpoint_TERMINATED_responses, though it is not expected to be triggered often. Change-Id: I6b0cf15b8050ebacd3099f52af1a03d786c6ff44 Signed-off-by: Zhen Chen --- drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c | 6 ++++++ drivers/gpu/arm/bifrost/csf/mali_kbase_csf_defs.h | 3 +++ drivers/gpu/arm/bifrost/csf/mali_kbase_csf_registers.h | 1 + drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.c | 3 ++- .../gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_fault_csf.c | 5 ++++- 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c index cc1369ce8766..80e37a36ca76 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c @@ -1359,6 +1359,7 @@ static int create_queue_group(struct kbase_context *const kctx, kbase_csf_priority_check(kctx->kbdev, create->in.priority)); group->doorbell_nr = KBASEP_USER_DB_NR_INVALID; group->faulted = false; + group->cs_unrecoverable = false; group->reevaluate_idle_status = false; @@ -2429,6 +2430,11 @@ handle_fatal_event(struct kbase_queue *const queue, CS_FATAL_EXCEPTION_TYPE_FIRMWARE_INTERNAL_ERROR) { queue_work(system_wq, &kbdev->csf.fw_error_work); } else { + if (cs_fatal_exception_type == CS_FATAL_EXCEPTION_TYPE_CS_UNRECOVERABLE) { + queue->group->cs_unrecoverable = true; + if (kbase_prepare_to_reset_gpu(queue->kctx->kbdev, RESET_FLAGS_NONE)) + kbase_reset_gpu(queue->kctx->kbdev); + } get_queue(queue); queue->cs_fatal = cs_fatal; queue->cs_fatal_info = cs_fatal_info; diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_defs.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_defs.h index 89055e95a02f..27aa53de110d 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_defs.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_defs.h @@ -477,6 +477,8 @@ struct kbase_protected_suspend_buffer { * @faulted: Indicates that a GPU fault occurred for the queue group. * This flag persists until the fault has been queued to be * reported to userspace. + * @cs_unrecoverable: Flag to unblock the thread waiting for CSG termination in + * case of CS_FATAL_EXCEPTION_TYPE_CS_UNRECOVERABLE * @reevaluate_idle_status : Flag set when work is submitted for the normal group * or it becomes unblocked during protected mode. The * flag helps Scheduler confirm if the group actually @@ -522,6 +524,7 @@ struct kbase_queue_group { u32 prepared_seq_num; u32 scan_seq_num; bool faulted; + bool cs_unrecoverable; bool reevaluate_idle_status; struct kbase_queue *bound_queues[MAX_SUPPORTED_STREAMS_PER_GROUP]; diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_registers.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_registers.h index c797bcbc461a..177569bfb427 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_registers.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_registers.h @@ -699,6 +699,7 @@ (((value) << CS_FATAL_EXCEPTION_TYPE_SHIFT) & CS_FATAL_EXCEPTION_TYPE_MASK)) /* CS_FATAL_EXCEPTION_TYPE values */ #define CS_FATAL_EXCEPTION_TYPE_CS_CONFIG_FAULT 0x40 +#define CS_FATAL_EXCEPTION_TYPE_CS_UNRECOVERABLE 0x41 #define CS_FATAL_EXCEPTION_TYPE_CS_ENDPOINT_FAULT 0x44 #define CS_FATAL_EXCEPTION_TYPE_CS_BUS_FAULT 0x48 #define CS_FATAL_EXCEPTION_TYPE_CS_INVALID_INSTRUCTION 0x49 diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.c index c0f63fe75a0f..af3b6912845d 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.c @@ -2645,7 +2645,8 @@ static int term_group_sync(struct kbase_queue_group *group) term_csg_slot(group); remaining = wait_event_timeout(kbdev->csf.event_wait, - csg_slot_stopped_locked(kbdev, group->csg_nr), remaining); + group->cs_unrecoverable || csg_slot_stopped_locked(kbdev, group->csg_nr), + remaining); if (!remaining) { dev_warn(kbdev->dev, "[%llu] term request timeout (%d ms) for group %d of context %d_%d on slot %d", diff --git a/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_fault_csf.c b/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_fault_csf.c index 893a3352a908..15bfd0375f0b 100644 --- a/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_fault_csf.c +++ b/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_fault_csf.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2019-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -86,6 +86,9 @@ const char *kbase_gpu_exception_name(u32 const exception_code) case CS_FATAL_EXCEPTION_TYPE_FIRMWARE_INTERNAL_ERROR: e = "FIRMWARE_INTERNAL_ERROR"; break; + case CS_FATAL_EXCEPTION_TYPE_CS_UNRECOVERABLE: + e = "CS_UNRECOVERABLE"; + break; case CS_FAULT_EXCEPTION_TYPE_RESOURCE_EVICTION_TIMEOUT: e = "RESOURCE_EVICTION_TIMEOUT"; break; From 1e81983bed9d03b68ea97c6b59b1dd95d707f185 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Thu, 22 Sep 2022 19:27:39 +0800 Subject: [PATCH 105/204] video: rockchip: rga3: Fixed the crash caused by RGA2 using dma_buf_fd When rga2 uses sgt to generate the page table, length should be used instead of dma_length, which will cause the length of the sgt after the default_mapping_core to be the length of the entire dma_buf. Update driver version to 1.2.20 Signed-off-by: Yu Qiaowei Change-Id: I07ad619b41554ededc0c5ade552a3bc176fef3f7 --- drivers/video/rockchip/rga3/include/rga_drv.h | 2 +- drivers/video/rockchip/rga3/rga_mm.c | 27 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/video/rockchip/rga3/include/rga_drv.h b/drivers/video/rockchip/rga3/include/rga_drv.h index 6b8bac5fec2f..7f94456bc497 100644 --- a/drivers/video/rockchip/rga3/include/rga_drv.h +++ b/drivers/video/rockchip/rga3/include/rga_drv.h @@ -87,7 +87,7 @@ #define DRIVER_MAJOR_VERISON 1 #define DRIVER_MINOR_VERSION 2 -#define DRIVER_REVISION_VERSION 19 +#define DRIVER_REVISION_VERSION 20 #define DRIVER_PATCH_VERSION #define DRIVER_VERSION (STR(DRIVER_MAJOR_VERISON) "." STR(DRIVER_MINOR_VERSION) \ diff --git a/drivers/video/rockchip/rga3/rga_mm.c b/drivers/video/rockchip/rga3/rga_mm.c index 4c5a667311bb..7d59472d0888 100644 --- a/drivers/video/rockchip/rga3/rga_mm.c +++ b/drivers/video/rockchip/rga3/rga_mm.c @@ -1042,15 +1042,24 @@ static int rga_mm_sgt_to_page_table(struct sg_table *sg, uint32_t break_flag = 0; do { - len = sg_dma_len(sgl) >> PAGE_SHIFT; - if (len == 0) - len = sgl->length >> PAGE_SHIFT; + /* + * The length of each sgl is expected to be obtained here, not + * the length of the entire dma_buf, so sg_dma_len() is not used. + */ + len = sgl->length >> PAGE_SHIFT; if (use_dma_address) /* - * The fd passed by user space gets sg through - * dma_buf_map_attachment, - * so dma_address can be use here. + * The fd passed by user space gets sg through + * dma_buf_map_attachment, so dma_address can + * be use here. + * When the mapped device does not have iommu, it will + * return the first address of the real physical page + * when it meets the requirements of the current device, + * and will trigger swiotlb when it does not meet the + * requirements to obtain a software-mapped physical + * address that is mapped to meet the device address + * requirements. */ Address = sg_dma_address(sgl); else @@ -1061,15 +1070,13 @@ static int rga_mm_sgt_to_page_table(struct sg_table *sg, break_flag = 1; break; } - page_table[mapped_size + i] = - (uint32_t) (Address + (i << PAGE_SHIFT)); + page_table[mapped_size + i] = (uint32_t)(Address + (i << PAGE_SHIFT)); } if (break_flag) break; mapped_size += len; sg_num += 1; - } while ((sgl = sg_next(sgl)) && (mapped_size < pageCount) - && (sg_num < sg->nents)); + } while ((sgl = sg_next(sgl)) && (mapped_size < pageCount) && (sg_num < sg->orig_nents)); return 0; } From 0d8246f6d34b644d80d486c05cf3f786f8ee0030 Mon Sep 17 00:00:00 2001 From: Yiqing Zeng Date: Fri, 10 Jun 2022 17:02:05 +0800 Subject: [PATCH 106/204] ARM: dts: rockchip: disabled ircut for rv1106-ipc end rv1106-evb-cam Signed-off-by: Yiqing Zeng Change-Id: I83007c6be54c275f95ad13bc9930ace4c5375d0c --- arch/arm/boot/dts/rv1106-evb-cam.dtsi | 13 ------------- arch/arm/boot/dts/rv1106-ipc.dtsi | 10 ---------- 2 files changed, 23 deletions(-) diff --git a/arch/arm/boot/dts/rv1106-evb-cam.dtsi b/arch/arm/boot/dts/rv1106-evb-cam.dtsi index dfb5e8d9c708..541c38e43065 100644 --- a/arch/arm/boot/dts/rv1106-evb-cam.dtsi +++ b/arch/arm/boot/dts/rv1106-evb-cam.dtsi @@ -3,16 +3,6 @@ * Copyright (c) 2022 Rockchip Electronics Co., Ltd. * */ -/ { - cam_ircut0: cam_ircut { - status = "okay"; - compatible = "rockchip,ircut"; - ircut-open-gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>; - ircut-close-gpios = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; - rockchip,camera-module-index = <0>; - rockchip,camera-module-facing = "back"; - }; -}; &csi2_dphy_hw { status = "okay"; @@ -90,7 +80,6 @@ rockchip,camera-module-facing = "back"; rockchip,camera-module-name = "CMK-OT2115-PC1"; rockchip,camera-module-lens-name = "30IRC-F16"; - lens-focus = <&cam_ircut0>; port { sc530ai_out: endpoint { remote-endpoint = <&csi_dphy_input0>; @@ -113,7 +102,6 @@ rockchip,camera-module-facing = "back"; rockchip,camera-module-name = "CMK-OT2119-PC1"; rockchip,camera-module-lens-name = "30IRC-F16"; - lens-focus = <&cam_ircut0>; port { sc3336_out: endpoint { remote-endpoint = <&csi_dphy_input1>; @@ -136,7 +124,6 @@ rockchip,camera-module-facing = "back"; rockchip,camera-module-name = "OT01"; rockchip,camera-module-lens-name = "40IRC_F16"; - lens-focus = <&cam_ircut0>; port { sc4336_out: endpoint { remote-endpoint = <&csi_dphy_input2>; diff --git a/arch/arm/boot/dts/rv1106-ipc.dtsi b/arch/arm/boot/dts/rv1106-ipc.dtsi index 80ce6af2eda9..d4ac29301f1f 100644 --- a/arch/arm/boot/dts/rv1106-ipc.dtsi +++ b/arch/arm/boot/dts/rv1106-ipc.dtsi @@ -22,15 +22,6 @@ }; }; - cam_ircut0: cam_ircut { - status = "okay"; - compatible = "rockchip,ircut"; - ircut-open-gpios = <&gpio1 RK_PC7 GPIO_ACTIVE_HIGH>; - ircut-close-gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>; - rockchip,camera-module-index = <0>; - rockchip,camera-module-facing = "back"; - }; - vcc_1v8: vcc-1v8 { compatible = "regulator-fixed"; regulator-name = "vcc_1v8"; @@ -156,7 +147,6 @@ pwdn-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&mipi_refclk_out0>; - lens-focus = <&cam_ircut0>; rockchip,camera-module-index = <0>; rockchip,camera-module-facing = "back"; rockchip,camera-module-name = "OT01"; From 7bc10a9db54b143bc8138c81f31f6231e0c7d891 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 24 Sep 2022 09:11:26 +0800 Subject: [PATCH 107/204] Revert "dma-buf: heaps: system_heap: partial sync with sgtable from heap buffer" This reverts commit 3212cfb965baa09f6e8bbbef2ca2ed7034031343. Use rk_system_heap.c instead of system_heap.c now, reverts all changes. Signed-off-by: Tao Huang Change-Id: I023ebda5731f5c509c703799bfb96115701bdf9e --- drivers/dma-buf/heaps/system_heap.c | 58 ++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index a21fddd4abc6..2e5d44acd4c6 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -272,9 +272,8 @@ system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, unsigned int len) { struct system_heap_buffer *buffer = dmabuf->priv; - struct dma_heap *heap = buffer->heap; - struct sg_table *table = &buffer->sg_table; - int ret; + struct dma_heap_attachment *a; + int ret = 0; if (direction == DMA_TO_DEVICE) return 0; @@ -283,13 +282,25 @@ system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, if (buffer->vmap_cnt) invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); - if (buffer->uncached) { - mutex_unlock(&buffer->lock); - return 0; - } + if (buffer->uncached) + goto unlock; - ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table, - offset, len, direction, true); + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + + ret = system_heap_sgl_sync_range(a->dev, a->table, offset, len, + direction, true); + } + if (list_empty(&buffer->attachments)) { + struct dma_heap *heap = buffer->heap; + struct sg_table *table = &buffer->sg_table; + + ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table, + offset, len, + direction, true); + } +unlock: mutex_unlock(&buffer->lock); return ret; @@ -302,21 +313,32 @@ system_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, unsigned int len) { struct system_heap_buffer *buffer = dmabuf->priv; - struct dma_heap *heap = buffer->heap; - struct sg_table *table = &buffer->sg_table; - int ret; + struct dma_heap_attachment *a; + int ret = 0; mutex_lock(&buffer->lock); if (buffer->vmap_cnt) flush_kernel_vmap_range(buffer->vaddr, buffer->len); - if (buffer->uncached) { - mutex_unlock(&buffer->lock); - return 0; - } + if (buffer->uncached) + goto unlock; - ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table, - offset, len, direction, false); + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + + ret = system_heap_sgl_sync_range(a->dev, a->table, offset, len, + direction, false); + } + if (list_empty(&buffer->attachments)) { + struct dma_heap *heap = buffer->heap; + struct sg_table *table = &buffer->sg_table; + + ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table, + offset, len, + direction, false); + } +unlock: mutex_unlock(&buffer->lock); return ret; From e87b0f89a5f6c8864e40105910872649acaad639 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 24 Sep 2022 09:15:36 +0800 Subject: [PATCH 108/204] Revert "dma-buf: heaps: system_heap: fix to for_each_sgtable_sg" This reverts commit 4925881228101b824d57ba68990c1e1b4c859b9d. Use rk_system_heap.c instead of system_heap.c now, reverts all changes. Signed-off-by: Tao Huang Change-Id: Ib7e1dd75ff948b7a190b4169037df83d4596b70e --- drivers/dma-buf/heaps/system_heap.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index 2e5d44acd4c6..f9a7629cc10e 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -224,7 +224,8 @@ static int system_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, } static int system_heap_sgl_sync_range(struct device *dev, - struct sg_table *sgt, + struct scatterlist *sgl, + unsigned int nents, unsigned int offset, unsigned int length, enum dma_data_direction dir, @@ -235,7 +236,7 @@ static int system_heap_sgl_sync_range(struct device *dev, dma_addr_t sg_dma_addr; int i; - for_each_sgtable_sg(sgt, sg, i) { + for_each_sg(sgl, sg, nents, i) { unsigned int sg_offset, sg_left, size = 0; sg_dma_addr = sg_phys(sg); @@ -289,14 +290,18 @@ system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, if (!a->mapped) continue; - ret = system_heap_sgl_sync_range(a->dev, a->table, offset, len, + ret = system_heap_sgl_sync_range(a->dev, a->table->sgl, + a->table->nents, + offset, len, direction, true); } if (list_empty(&buffer->attachments)) { struct dma_heap *heap = buffer->heap; struct sg_table *table = &buffer->sg_table; - ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table, + ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), + table->sgl, + table->nents, offset, len, direction, true); } @@ -327,14 +332,18 @@ system_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, if (!a->mapped) continue; - ret = system_heap_sgl_sync_range(a->dev, a->table, offset, len, + ret = system_heap_sgl_sync_range(a->dev, a->table->sgl, + a->table->nents, + offset, len, direction, false); } if (list_empty(&buffer->attachments)) { struct dma_heap *heap = buffer->heap; struct sg_table *table = &buffer->sg_table; - ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table, + ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), + table->sgl, + table->nents, offset, len, direction, false); } From ea59f61ab477197a33afccd29fe05740e878cd19 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 24 Sep 2022 09:16:11 +0800 Subject: [PATCH 109/204] Revert "dma-buf: heaps: system_heap: fix partial sync contition error" This reverts commit e1650283910f9b35f1dfbea12cabc61a9b9141d6. Use rk_system_heap.c instead of system_heap.c now, reverts all changes. Signed-off-by: Tao Huang Change-Id: Iaa80d3480d2e039cdd530e3278035c84553d07e7 --- drivers/dma-buf/heaps/system_heap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index f9a7629cc10e..aabda43a534c 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -283,7 +283,7 @@ system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, if (buffer->vmap_cnt) invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); - if (buffer->uncached) + if (!buffer->uncached) goto unlock; list_for_each_entry(a, &buffer->attachments, list) { @@ -325,7 +325,7 @@ system_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, if (buffer->vmap_cnt) flush_kernel_vmap_range(buffer->vaddr, buffer->len); - if (buffer->uncached) + if (!buffer->uncached) goto unlock; list_for_each_entry(a, &buffer->attachments, list) { From 940557cb336a0bd110b2c11c9dc6ef3daad1654c Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 24 Sep 2022 09:16:42 +0800 Subject: [PATCH 110/204] Revert "dma-buf: system_heap: do force sync only if attachment list empty" This reverts commit 33b98bf612bd33ed58516a0ed2ac01ff9ef2fc9c. Use rk_system_heap.c instead of system_heap.c now, reverts all changes. Signed-off-by: Tao Huang Change-Id: Id265fd16b1531708478f07187f50fe23e74e427e --- drivers/dma-buf/heaps/system_heap.c | 47 +++++++++++++++++------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index aabda43a534c..2e46028f498f 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -26,6 +26,8 @@ #include "page_pool.h" #include "deferred-free-helper.h" +#define CONFIG_SYSTEM_HEAP_FORCE_DMA_SYNC + static struct dma_heap *sys_heap; static struct dma_heap *sys_dma32_heap; static struct dma_heap *sys_uncached_heap; @@ -239,7 +241,7 @@ static int system_heap_sgl_sync_range(struct device *dev, for_each_sg(sgl, sg, nents, i) { unsigned int sg_offset, sg_left, size = 0; - sg_dma_addr = sg_phys(sg); + sg_dma_addr = sg_dma_address(sg); len += sg->length; if (len <= offset) @@ -280,6 +282,18 @@ system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, return 0; mutex_lock(&buffer->lock); + if (IS_ENABLED(CONFIG_SYSTEM_HEAP_FORCE_DMA_SYNC)) { + struct dma_heap *heap = buffer->heap; + struct sg_table *table = &buffer->sg_table; + + ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), + table->sgl, + table->nents, + offset, len, + direction, true); + goto unlock; + } + if (buffer->vmap_cnt) invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); @@ -295,16 +309,7 @@ system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, offset, len, direction, true); } - if (list_empty(&buffer->attachments)) { - struct dma_heap *heap = buffer->heap; - struct sg_table *table = &buffer->sg_table; - ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), - table->sgl, - table->nents, - offset, len, - direction, true); - } unlock: mutex_unlock(&buffer->lock); @@ -322,6 +327,18 @@ system_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, int ret = 0; mutex_lock(&buffer->lock); + if (IS_ENABLED(CONFIG_SYSTEM_HEAP_FORCE_DMA_SYNC)) { + struct dma_heap *heap = buffer->heap; + struct sg_table *table = &buffer->sg_table; + + ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), + table->sgl, + table->nents, + offset, len, + direction, false); + goto unlock; + } + if (buffer->vmap_cnt) flush_kernel_vmap_range(buffer->vaddr, buffer->len); @@ -337,16 +354,6 @@ system_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, offset, len, direction, false); } - if (list_empty(&buffer->attachments)) { - struct dma_heap *heap = buffer->heap; - struct sg_table *table = &buffer->sg_table; - - ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), - table->sgl, - table->nents, - offset, len, - direction, false); - } unlock: mutex_unlock(&buffer->lock); From 1f9114b0baf439151ea506d3c6e376c6a0df6386 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 24 Sep 2022 09:17:02 +0800 Subject: [PATCH 111/204] Revert "ANDROID: dma-buf: system_heap: dynamic get ddr map info for reorder page" This reverts commit a22edac69e894a5015cb2ebccf24ac5beb4ed515. Use rk_system_heap.c instead of system_heap.c now, reverts all changes. Signed-off-by: Tao Huang Change-Id: Iae81cc96b1e1ac3073d1e0fe4cf6cdb55abf6103 --- drivers/dma-buf/heaps/system_heap.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index 2e46028f498f..8a95d6058088 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "page_pool.h" #include "deferred-free-helper.h" @@ -33,10 +32,6 @@ static struct dma_heap *sys_dma32_heap; static struct dma_heap *sys_uncached_heap; static struct dma_heap *sys_uncached_dma32_heap; -/* Default setting */ -static u32 bank_bit_first = 12; -static u32 bank_bit_mask = 0x7; - struct system_heap_buffer { struct dma_heap *heap; struct list_head attachments; @@ -606,10 +601,10 @@ static struct dma_buf *system_heap_do_allocate(struct dma_heap *heap, list_add_tail(&page->lru, &pages); } else { dma_addr_t phys = page_to_phys(page); - unsigned int bit_index = ((phys >> bank_bit_first) & bank_bit_mask) & 0x7; + unsigned int bit12_14 = (phys >> 12) & 0x7; - list_add_tail(&page->lru, &lists[bit_index]); - block_index[bit_index]++; + list_add_tail(&page->lru, &lists[bit12_14]); + block_index[bit12_14]++; } i++; } @@ -766,7 +761,6 @@ static int system_heap_create(void) { struct dma_heap_export_info exp_info; int i, err = 0; - struct dram_addrmap_info *ddr_map_info; /* * Since swiotlb has memory size limitation, this will calculate @@ -862,12 +856,6 @@ static int system_heap_create(void) mb(); /* make sure we only set allocate after dma_mask is set */ system_uncached_heap_ops.allocate = system_uncached_heap_allocate; - ddr_map_info = sip_smc_get_dram_map(); - if (ddr_map_info) { - bank_bit_first = ddr_map_info->bank_bit_first; - bank_bit_mask = ddr_map_info->bank_bit_mask; - } - return 0; err_dma32_pool: for (i = 0; i < NUM_ORDERS; i++) From d2c32e14b694d227b06bda06aabc7b86262a240a Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 24 Sep 2022 09:17:26 +0800 Subject: [PATCH 112/204] Revert "dma-buf: system_heap: fix compile warning" This reverts commit 9d91ed824a4afe48109c3f795fe034849df9405d. Use rk_system_heap.c instead of system_heap.c now, reverts all changes. Signed-off-by: Tao Huang Change-Id: Ibb891bd5d9c8a1a56208b8b39402b9b7b04bdd4f --- drivers/dma-buf/heaps/system_heap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index 8a95d6058088..2a3872d06978 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -270,6 +270,7 @@ system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, unsigned int len) { struct system_heap_buffer *buffer = dmabuf->priv; + struct sg_table *table = &buffer->sg_table; struct dma_heap_attachment *a; int ret = 0; @@ -279,7 +280,6 @@ system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, mutex_lock(&buffer->lock); if (IS_ENABLED(CONFIG_SYSTEM_HEAP_FORCE_DMA_SYNC)) { struct dma_heap *heap = buffer->heap; - struct sg_table *table = &buffer->sg_table; ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table->sgl, @@ -318,13 +318,13 @@ system_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, unsigned int len) { struct system_heap_buffer *buffer = dmabuf->priv; + struct sg_table *table = &buffer->sg_table; struct dma_heap_attachment *a; int ret = 0; mutex_lock(&buffer->lock); if (IS_ENABLED(CONFIG_SYSTEM_HEAP_FORCE_DMA_SYNC)) { struct dma_heap *heap = buffer->heap; - struct sg_table *table = &buffer->sg_table; ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), table->sgl, From 83065feb357fa293f5ac4a082ee112a471930465 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 24 Sep 2022 09:17:49 +0800 Subject: [PATCH 113/204] Revert "ANDROID: dma-buf: system_heap: allocate from dma32_pool for dma32* heap" This reverts commit 383018f42d4d3ee0ecb8d3d424db04e7fa6de4a2. Use rk_system_heap.c instead of system_heap.c now, reverts all changes. Signed-off-by: Tao Huang Change-Id: I27099b713ac3249acb628868c7255c51b2881371 --- drivers/dma-buf/heaps/system_heap.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index 2a3872d06978..3c348c755004 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -519,22 +519,18 @@ static const struct dma_buf_ops system_heap_buf_ops = { .release = system_heap_dma_buf_release, }; -static struct page *system_heap_alloc_largest_available(struct dma_heap *heap, - unsigned long size, - unsigned int max_order) +static struct page *alloc_largest_available(unsigned long size, + unsigned int max_order) { struct page *page; int i; - const char *name = dma_heap_get_name(heap); - struct dmabuf_page_pool **pool; - pool = strstr(name, "dma32") ? dma32_pools : pools; for (i = 0; i < NUM_ORDERS; i++) { if (size < (PAGE_SIZE << orders[i])) continue; if (max_order < orders[i]) continue; - page = dmabuf_page_pool_alloc(pool[i]); + page = dmabuf_page_pool_alloc(pools[i]); if (!page) continue; return page; @@ -587,7 +583,7 @@ static struct dma_buf *system_heap_do_allocate(struct dma_heap *heap, if (fatal_signal_pending(current)) goto free_buffer; - page = system_heap_alloc_largest_available(heap, size_remaining, max_order); + page = alloc_largest_available(size_remaining, max_order); if (!page) goto free_buffer; From e83883cf8703045c61ebdd7a49dd98eb67710662 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 24 Sep 2022 09:23:09 +0800 Subject: [PATCH 114/204] Revert "ANDROID: dma-buf: system_heap: support to allocate pages with GFP_DMA32" This reverts commit 8880c05e5a2cd733550d77ff13e852b0d22a405c. Use rk_system_heap.c instead of system_heap.c now, reverts all changes. Signed-off-by: Tao Huang Change-Id: I1b00ac9fabb0825dcedf8719a840ac8138bdc81e --- drivers/dma-buf/heaps/system_heap.c | 45 ----------------------------- 1 file changed, 45 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index 3c348c755004..d34b1ea0d472 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -28,9 +28,7 @@ #define CONFIG_SYSTEM_HEAP_FORCE_DMA_SYNC static struct dma_heap *sys_heap; -static struct dma_heap *sys_dma32_heap; static struct dma_heap *sys_uncached_heap; -static struct dma_heap *sys_uncached_dma32_heap; struct system_heap_buffer { struct dma_heap *heap; @@ -69,7 +67,6 @@ static gfp_t order_flags[] = {HIGH_ORDER_GFP, MID_ORDER_GFP, LOW_ORDER_GFP}; static unsigned int orders[] = {8, 4, 0}; #define NUM_ORDERS ARRAY_SIZE(orders) struct dmabuf_page_pool *pools[NUM_ORDERS]; -struct dmabuf_page_pool *dma32_pools[NUM_ORDERS]; static struct sg_table *dup_sg_table(struct sg_table *table) { @@ -686,11 +683,8 @@ static long system_get_pool_size(struct dma_heap *heap) int i; long num_pages = 0; struct dmabuf_page_pool **pool; - const char *name = dma_heap_get_name(heap); pool = pools; - if (!strcmp(name, "system-dma32") || !strcmp(name, "system-uncached-dma32")) - pool = dma32_pools; for (i = 0; i < NUM_ORDERS; i++, pool++) { num_pages += ((*pool)->count[POOL_LOWPAGE] + (*pool)->count[POOL_HIGHPAGE]) << (*pool)->order; @@ -795,19 +789,6 @@ static int system_heap_create(void) } } - for (i = 0; i < NUM_ORDERS; i++) { - dma32_pools[i] = dmabuf_page_pool_create(order_flags[i] | GFP_DMA32, orders[i]); - - if (!dma32_pools[i]) { - int j; - - pr_err("%s: page dma32 pool creation failed!\n", __func__); - for (j = 0; j < i; j++) - dmabuf_page_pool_destroy(dma32_pools[j]); - goto err_dma32_pool; - } - } - exp_info.name = "system"; exp_info.ops = &system_heap_ops; exp_info.priv = NULL; @@ -816,14 +797,6 @@ static int system_heap_create(void) if (IS_ERR(sys_heap)) return PTR_ERR(sys_heap); - exp_info.name = "system-dma32"; - exp_info.ops = &system_heap_ops; - exp_info.priv = NULL; - - sys_dma32_heap = dma_heap_add(&exp_info); - if (IS_ERR(sys_dma32_heap)) - return PTR_ERR(sys_dma32_heap); - exp_info.name = "system-uncached"; exp_info.ops = &system_uncached_heap_ops; exp_info.priv = NULL; @@ -836,28 +809,10 @@ static int system_heap_create(void) if (err) return err; - exp_info.name = "system-uncached-dma32"; - exp_info.ops = &system_uncached_heap_ops; - exp_info.priv = NULL; - - sys_uncached_dma32_heap = dma_heap_add(&exp_info); - if (IS_ERR(sys_uncached_dma32_heap)) - return PTR_ERR(sys_uncached_dma32_heap); - - err = set_heap_dev_dma(dma_heap_get_dev(sys_uncached_dma32_heap)); - if (err) - return err; - dma_coerce_mask_and_coherent(dma_heap_get_dev(sys_uncached_dma32_heap), DMA_BIT_MASK(32)); - mb(); /* make sure we only set allocate after dma_mask is set */ system_uncached_heap_ops.allocate = system_uncached_heap_allocate; return 0; -err_dma32_pool: - for (i = 0; i < NUM_ORDERS; i++) - dmabuf_page_pool_destroy(pools[i]); - - return -ENOMEM; } module_init(system_heap_create); MODULE_LICENSE("GPL v2"); From 7f281c203b614c64b873d00c0619454ec49382a2 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 24 Sep 2022 09:23:32 +0800 Subject: [PATCH 115/204] Revert "ANDROID: dma-buf: system_heap: reorder pages for scatterlist" This reverts commit 10e18d6585ffa52ab8d50aadbb00599dc3e22eb1. Use rk_system_heap.c instead of system_heap.c now, reverts all changes. Signed-off-by: Tao Huang Change-Id: I32e5e13c2d9765c9cf1bbda4622731ec7a8c1848 --- drivers/dma-buf/heaps/system_heap.c | 39 +---------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index d34b1ea0d472..cb14a3b7e475 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -551,12 +551,6 @@ static struct dma_buf *system_heap_do_allocate(struct dma_heap *heap, struct list_head pages; struct page *page, *tmp_page; int i, ret = -ENOMEM; - struct list_head lists[8]; - unsigned int block_index[8] = {0}; - unsigned int block_1M = 0; - unsigned int block_64K = 0; - unsigned int maximum; - int j; buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); if (!buffer) @@ -569,8 +563,6 @@ static struct dma_buf *system_heap_do_allocate(struct dma_heap *heap, buffer->uncached = uncached; INIT_LIST_HEAD(&pages); - for (i = 0; i < 8; i++) - INIT_LIST_HEAD(&lists[i]); i = 0; while (size_remaining > 0) { /* @@ -584,21 +576,9 @@ static struct dma_buf *system_heap_do_allocate(struct dma_heap *heap, if (!page) goto free_buffer; + list_add_tail(&page->lru, &pages); size_remaining -= page_size(page); max_order = compound_order(page); - if (max_order) { - if (max_order == 8) - block_1M++; - if (max_order == 4) - block_64K++; - list_add_tail(&page->lru, &pages); - } else { - dma_addr_t phys = page_to_phys(page); - unsigned int bit12_14 = (phys >> 12) & 0x7; - - list_add_tail(&page->lru, &lists[bit12_14]); - block_index[bit12_14]++; - } i++; } @@ -606,25 +586,12 @@ static struct dma_buf *system_heap_do_allocate(struct dma_heap *heap, if (sg_alloc_table(table, i, GFP_KERNEL)) goto free_buffer; - maximum = block_index[0]; - for (i = 1; i < 8; i++) - maximum = max(maximum, block_index[i]); sg = table->sgl; list_for_each_entry_safe(page, tmp_page, &pages, lru) { sg_set_page(sg, page, page_size(page), 0); sg = sg_next(sg); list_del(&page->lru); } - for (i = 0; i < maximum; i++) { - for (j = 0; j < 8; j++) { - if (!list_empty(&lists[j])) { - page = list_first_entry(&lists[j], struct page, lru); - sg_set_page(sg, page, PAGE_SIZE, 0); - sg = sg_next(sg); - list_del(&page->lru); - } - } - } /* create the dmabuf */ exp_info.exp_name = dma_heap_get_name(heap); @@ -661,10 +628,6 @@ free_pages: free_buffer: list_for_each_entry_safe(page, tmp_page, &pages, lru) __free_pages(page, compound_order(page)); - for (i = 0; i < 8; i++) { - list_for_each_entry_safe(page, tmp_page, &lists[i], lru) - __free_pages(page, compound_order(page)); - } kfree(buffer); return ERR_PTR(ret); From 86ab879b664f02c7a0b66f07a173ba5134e07952 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 24 Sep 2022 09:23:47 +0800 Subject: [PATCH 116/204] Revert "dma-buf: system_heap: support cpu access partial dma-buf" This reverts commit 21f2fd663ea7b18421554b334d2527d5724fce2b. Use rk_system_heap.c instead of system_heap.c now, reverts all changes. Signed-off-by: Tao Huang Change-Id: Ica9d2358c14956a8233523b7b91e1a9d09d50632 --- drivers/dma-buf/heaps/system_heap.c | 139 ---------------------------- 1 file changed, 139 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index cb14a3b7e475..ca2e8e29645b 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -25,8 +25,6 @@ #include "page_pool.h" #include "deferred-free-helper.h" -#define CONFIG_SYSTEM_HEAP_FORCE_DMA_SYNC - static struct dma_heap *sys_heap; static struct dma_heap *sys_uncached_heap; @@ -217,141 +215,6 @@ static int system_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, return 0; } -static int system_heap_sgl_sync_range(struct device *dev, - struct scatterlist *sgl, - unsigned int nents, - unsigned int offset, - unsigned int length, - enum dma_data_direction dir, - bool for_cpu) -{ - struct scatterlist *sg; - unsigned int len = 0; - dma_addr_t sg_dma_addr; - int i; - - for_each_sg(sgl, sg, nents, i) { - unsigned int sg_offset, sg_left, size = 0; - - sg_dma_addr = sg_dma_address(sg); - - len += sg->length; - if (len <= offset) - continue; - - sg_left = len - offset; - sg_offset = sg->length - sg_left; - - size = (length < sg_left) ? length : sg_left; - if (for_cpu) - dma_sync_single_range_for_cpu(dev, sg_dma_addr, - sg_offset, size, dir); - else - dma_sync_single_range_for_device(dev, sg_dma_addr, - sg_offset, size, dir); - - offset += size; - length -= size; - - if (length == 0) - break; - } - - return 0; -} - -static int -system_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, - enum dma_data_direction direction, - unsigned int offset, - unsigned int len) -{ - struct system_heap_buffer *buffer = dmabuf->priv; - struct sg_table *table = &buffer->sg_table; - struct dma_heap_attachment *a; - int ret = 0; - - if (direction == DMA_TO_DEVICE) - return 0; - - mutex_lock(&buffer->lock); - if (IS_ENABLED(CONFIG_SYSTEM_HEAP_FORCE_DMA_SYNC)) { - struct dma_heap *heap = buffer->heap; - - ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), - table->sgl, - table->nents, - offset, len, - direction, true); - goto unlock; - } - - if (buffer->vmap_cnt) - invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); - - if (!buffer->uncached) - goto unlock; - - list_for_each_entry(a, &buffer->attachments, list) { - if (!a->mapped) - continue; - - ret = system_heap_sgl_sync_range(a->dev, a->table->sgl, - a->table->nents, - offset, len, - direction, true); - } - -unlock: - mutex_unlock(&buffer->lock); - - return ret; -} - -static int -system_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, - enum dma_data_direction direction, - unsigned int offset, - unsigned int len) -{ - struct system_heap_buffer *buffer = dmabuf->priv; - struct sg_table *table = &buffer->sg_table; - struct dma_heap_attachment *a; - int ret = 0; - - mutex_lock(&buffer->lock); - if (IS_ENABLED(CONFIG_SYSTEM_HEAP_FORCE_DMA_SYNC)) { - struct dma_heap *heap = buffer->heap; - - ret = system_heap_sgl_sync_range(dma_heap_get_dev(heap), - table->sgl, - table->nents, - offset, len, - direction, false); - goto unlock; - } - - if (buffer->vmap_cnt) - flush_kernel_vmap_range(buffer->vaddr, buffer->len); - - if (!buffer->uncached) - goto unlock; - - list_for_each_entry(a, &buffer->attachments, list) { - if (!a->mapped) - continue; - - ret = system_heap_sgl_sync_range(a->dev, a->table->sgl, - a->table->nents, - offset, len, - direction, false); - } -unlock: - mutex_unlock(&buffer->lock); - - return ret; -} - static int system_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) { struct system_heap_buffer *buffer = dmabuf->priv; @@ -508,8 +371,6 @@ static const struct dma_buf_ops system_heap_buf_ops = { .unmap_dma_buf = system_heap_unmap_dma_buf, .begin_cpu_access = system_heap_dma_buf_begin_cpu_access, .end_cpu_access = system_heap_dma_buf_end_cpu_access, - .begin_cpu_access_partial = system_heap_dma_buf_begin_cpu_access_partial, - .end_cpu_access_partial = system_heap_dma_buf_end_cpu_access_partial, .mmap = system_heap_mmap, .vmap = system_heap_vmap, .vunmap = system_heap_vunmap, From a0c6cc5fdbe9486d7ad52372baf8adf965754306 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Sat, 24 Sep 2022 09:24:04 +0800 Subject: [PATCH 117/204] Revert "dma-buf: system_heap: adjust orders if swiotlb limit" This reverts commit 79c6a1e08b1f4a9761113690c1c91f3909cb6d44. Use rk_system_heap.c instead of system_heap.c now, reverts all changes. Signed-off-by: Tao Huang Change-Id: I0351b2a839fa984729ca167c66ca10231475ec5e --- drivers/dma-buf/heaps/system_heap.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index ca2e8e29645b..b46cdaa69702 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "page_pool.h" @@ -62,7 +61,7 @@ static gfp_t order_flags[] = {HIGH_ORDER_GFP, MID_ORDER_GFP, LOW_ORDER_GFP}; * of order 0 pages can significantly improve the performance of many IOMMUs * by reducing TLB pressure and time spent updating page tables. */ -static unsigned int orders[] = {8, 4, 0}; +static const unsigned int orders[] = {8, 4, 0}; #define NUM_ORDERS ARRAY_SIZE(orders) struct dmabuf_page_pool *pools[NUM_ORDERS]; @@ -576,30 +575,6 @@ static int system_heap_create(void) struct dma_heap_export_info exp_info; int i, err = 0; - /* - * Since swiotlb has memory size limitation, this will calculate - * the maximum size locally. - * - * Once swiotlb_max_segment() return not '0', means that the totalram size - * is larger than 4GiB and swiotlb is not force mode, in this case, system - * heap should limit largest allocation. - * - * FIX: fix the orders[] as a workaround. - */ - if (swiotlb_max_segment()) { - unsigned int max_size = (1 << IO_TLB_SHIFT) * IO_TLB_SEGSIZE; - int max_order = MAX_ORDER; - int i; - - max_size = max_t(unsigned int, max_size, PAGE_SIZE) >> PAGE_SHIFT; - max_order = min(max_order, ilog2(max_size)); - for (i = 0; i < NUM_ORDERS; i++) { - if (max_order < orders[i]) - orders[i] = max_order; - pr_info("system_heap: orders[%d] = %u\n", i, orders[i]); - } - } - for (i = 0; i < NUM_ORDERS; i++) { pools[i] = dmabuf_page_pool_create(order_flags[i], orders[i]); From 5999dafd2b4f3206c192e077c29712b99308c552 Mon Sep 17 00:00:00 2001 From: Nickey Yang Date: Fri, 23 Sep 2022 20:27:48 +0800 Subject: [PATCH 118/204] arm64: rockchip_linux_config: enable CONFIG_ROCKCHIP_DW_HDCP2 Signed-off-by: Nickey Yang Change-Id: Icedd151f0c6e6751faa39eb9c3053860c36c91fe --- arch/arm64/configs/rockchip_linux_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index 051d00fbeaef..3783dc7717b5 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -308,6 +308,7 @@ CONFIG_ROCKCHIP_DW_DP=y CONFIG_ROCKCHIP_INNO_HDMI=y CONFIG_ROCKCHIP_LVDS=y CONFIG_ROCKCHIP_RGB=y +CONFIG_ROCKCHIP_DW_HDCP2=y CONFIG_DRM_PANEL_SIMPLE=y CONFIG_DRM_DISPLAY_CONNECTOR=y CONFIG_DRM_SII902X=y From 5ebe93e6bf3d849aa9ba911c675221b58f3900e2 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 20 Sep 2022 21:30:20 +0800 Subject: [PATCH 119/204] ASoC: codecs: rv1106_codec: fix and optimize ADC enabling VREF Signed-off-by: Xing Zheng Change-Id: Ieb34e125972faef68f0bef23c4819aeaf6127ee7 --- sound/soc/codecs/rv1106_codec.c | 17 ++++++----------- sound/soc/codecs/rv1106_codec.h | 6 +++--- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/sound/soc/codecs/rv1106_codec.c b/sound/soc/codecs/rv1106_codec.c index e8f98ccfc1a6..9aae936dd384 100644 --- a/sound/soc/codecs/rv1106_codec.c +++ b/sound/soc/codecs/rv1106_codec.c @@ -1370,13 +1370,6 @@ static int rv1106_codec_adc_enable(struct rv1106_codec_priv *rv1106) R(lr, ACODEC_ADC_R_SINGLE_END)); } - regmap_update_bits(rv1106->regmap, - ACODEC_ADC_ANA_CTL3, - L(lr, ACODEC_MIC_L_MSK) | - R(lr, ACODEC_MIC_R_MSK), - L(lr, ACODEC_MIC_L_EN) | - R(lr, ACODEC_MIC_R_EN)); - /* vendor step 2 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL1, L(lr, ACODEC_ADC_L_MIC_MSK) | @@ -1386,8 +1379,8 @@ static int rv1106_codec_adc_enable(struct rv1106_codec_priv *rv1106) /* vendor step 3 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL0, - ACODEC_ADC_CUR_SRC_MSK, - ACODEC_ADC_CUR_SRC_EN); + ACODEC_ADC_IBIAS_MSK, + ACODEC_ADC_IBIAS_EN); /* vendor step 4*/ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL1, @@ -1395,6 +1388,8 @@ static int rv1106_codec_adc_enable(struct rv1106_codec_priv *rv1106) R(lr, ACODEC_ADC_R_REF_VOL_BUF_MSK), L(lr, ACODEC_ADC_L_REF_VOL_BUF_EN) | R(lr, ACODEC_ADC_R_REF_VOL_BUF_EN)); + /* waiting VREF be stable */ + msleep(100); /* vendor step 5 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL3, @@ -1511,8 +1506,8 @@ static int rv1106_codec_adc_disable(struct rv1106_codec_priv *rv1106) /* vendor step 7 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL0, - ACODEC_ADC_CUR_SRC_MSK, - ACODEC_ADC_CUR_SRC_DIS); + ACODEC_ADC_IBIAS_MSK, + ACODEC_ADC_IBIAS_DIS); /* vendor step 8 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6, diff --git a/sound/soc/codecs/rv1106_codec.h b/sound/soc/codecs/rv1106_codec.h index 6311957c16ef..a62fd549f348 100644 --- a/sound/soc/codecs/rv1106_codec.h +++ b/sound/soc/codecs/rv1106_codec.h @@ -265,9 +265,9 @@ #define ACODEC_ADC_REF_VOL_MSK (0x1 << 5) #define ACODEC_ADC_REF_VOL_EN (0x1 << 5) #define ACODEC_ADC_REF_VOL_DIS (0x0 << 5) -#define ACODEC_ADC_CUR_SRC_MSK (0x1 << 4) -#define ACODEC_ADC_CUR_SRC_EN (0x1 << 4) -#define ACODEC_ADC_CUR_SRC_DIS (0x0 << 4) +#define ACODEC_ADC_IBIAS_MSK (0x1 << 4) +#define ACODEC_ADC_IBIAS_EN (0x1 << 4) +#define ACODEC_ADC_IBIAS_DIS (0x0 << 4) #define ACODEC_MICBIAS_SFT 3 #define ACODEC_MICBIAS_MSK (0x1 << 3) #define ACODEC_MICBIAS_WORK (0x1 << 3) From 1bf8b6d4b41d058fc0d5fa90b108cd61992816e6 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Fri, 9 Sep 2022 19:20:37 +0800 Subject: [PATCH 120/204] drm/bridge: synopsys: dw-hdmi-qp: Support ALLM Add two drm properties for ALLM: allm_capacity: values: 0 1 0: sink not support ALLM 1: sink support ALLM allm_enable: 0: disable ALLM 1: enable ALLM Signed-off-by: Algea Cao Change-Id: I0f5a6fa324c6727c37414f017b4839b3ec910206 --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 112 +++++++++++++++---- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 62 +++++++++- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 10 +- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 2 +- include/drm/bridge/dw_hdmi.h | 6 +- 6 files changed, 164 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 2cc24007498f..6e7335f2104f 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -252,6 +252,7 @@ struct dw_hdmi_qp { bool dclk_en; bool frl_switch; bool cec_enable; + bool allm_enable; struct mutex mutex; /* for state below and previous_mode */ struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */ @@ -1299,6 +1300,12 @@ static void hdmi_config_AVI(struct dw_hdmi_qp *hdmi, hdmi_modb(hdmi, PKTSCHED_AVI_TX_EN, PKTSCHED_AVI_TX_EN, PKTSCHED_PKT_EN); } +#define VSI_PKT_TYPE 0x81 +#define VSI_PKT_VERSION 1 +#define HDMI_FORUM_OUI 0xc45dd8 +#define ALLM_MODE BIT(1) +#define HDMI_FORUM_LEN 9 + static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi_qp *hdmi, const struct drm_connector *connector, const struct drm_display_mode *mode) @@ -1308,24 +1315,47 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi_qp *hdmi, u32 val; ssize_t err; int i, reg; + struct dw_hdmi_link_config *link_cfg = NULL; + void *data = hdmi->plat_data->phy_data; + + if (hdmi->plat_data->get_link_cfg) + link_cfg = hdmi->plat_data->get_link_cfg(data); hdmi_modb(hdmi, 0, PKTSCHED_VSI_TX_EN, PKTSCHED_PKT_EN); - err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, connector, - mode); - if (err < 0) - /* - * Going into that statement does not means vendor infoframe - * fails. It just informed us that vendor infoframe is not - * needed for the selected mode. Only 4k or stereoscopic 3D - * mode requires vendor infoframe. So just simply return. - */ - return; + for (i = 0; i <= 7; i++) + hdmi_writel(hdmi, 0, PKT_VSI_CONTENTS0 + i * 4); - err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer)); - if (err < 0) { - dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n", - err); - return; + if (hdmi->allm_enable && (link_cfg->add_func & SUPPORT_HDMI_ALLM)) { + buffer[0] = VSI_PKT_TYPE; + buffer[1] = VSI_PKT_VERSION; + buffer[2] = 5; + buffer[4] = HDMI_FORUM_OUI & 0xff; + buffer[5] = (HDMI_FORUM_OUI >> 8) & 0xff; + buffer[6] = (HDMI_FORUM_OUI >> 16) & 0xff; + buffer[7] = VSI_PKT_VERSION; + buffer[8] = ALLM_MODE; + + hdmi_infoframe_set_checksum(buffer, HDMI_FORUM_LEN); + + err = 9; + } else { + err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, connector, + mode); + if (err < 0) + /* + * Going into that statement does not means vendor infoframe + * fails. It just informed us that vendor infoframe is not + * needed for the selected mode. Only 4k or stereoscopic 3D + * mode requires vendor infoframe. So just simply return. + */ + return; + + err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer)); + if (err < 0) { + dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n", + err); + return; + } } /* vsi header */ @@ -2044,6 +2074,37 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) return ret; } +void dw_hdmi_qp_set_allm_enable(struct dw_hdmi_qp *hdmi, bool enable) +{ + struct dw_hdmi_link_config *link_cfg = NULL; + void *data; + + if (!hdmi || !hdmi->curr_conn) + return; + + data = hdmi->plat_data->phy_data; + + if (hdmi->plat_data->get_link_cfg) + link_cfg = hdmi->plat_data->get_link_cfg(data); + + if (!link_cfg) + return; + + if (enable == hdmi->allm_enable) + return; + + hdmi->allm_enable = enable; + + if (enable && !(link_cfg->add_func & SUPPORT_HDMI_ALLM)) { + hdmi->allm_enable = false; + dev_err(hdmi->dev, "sink don't support allm, allm won't be enabled\n"); + return; + } + + hdmi_config_vendor_specific_infoframe(hdmi, hdmi->curr_conn, &hdmi->previous_mode); +} +EXPORT_SYMBOL_GPL(dw_hdmi_qp_set_allm_enable); + static int dw_hdmi_atomic_connector_set_property(struct drm_connector *connector, struct drm_connector_state *state, @@ -2088,6 +2149,7 @@ dw_hdmi_connector_set_property(struct drm_connector *connector, static void dw_hdmi_attach_properties(struct dw_hdmi_qp *hdmi) { + u32 val; u64 color = MEDIA_BUS_FMT_YUV8_1X24; const struct dw_hdmi_property_ops *ops = hdmi->plat_data->property_ops; @@ -2095,14 +2157,21 @@ static void dw_hdmi_attach_properties(struct dw_hdmi_qp *hdmi) enum drm_connector_status connect_status = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); - if (hdmi->plat_data->get_grf_color_fmt && - (connect_status == connector_status_connected) && - hdmi->initialized) - color = hdmi->plat_data->get_grf_color_fmt(data); + if ((connect_status == connector_status_connected) && + hdmi->initialized) { + if (hdmi->plat_data->get_grf_color_fmt) + color = hdmi->plat_data->get_grf_color_fmt(data); + + val = (hdmi_readl(hdmi, PKT_VSI_CONTENTS1) >> 8) & 0xffffff; + if (val == HDMI_FORUM_OUI) + hdmi->allm_enable = true; + else + hdmi->allm_enable = false; + } if (ops && ops->attach_properties) return ops->attach_properties(&hdmi->connector, color, 0, - hdmi->plat_data->phy_data); + hdmi->plat_data->phy_data, hdmi->allm_enable); } static void dw_hdmi_destroy_properties(struct dw_hdmi_qp *hdmi) @@ -2188,6 +2257,7 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, * drm_display_mode and set phy status to enabled. */ if (!vmode->mpixelclock) { + hdmi->curr_conn = connector; if (hdmi->plat_data->get_enc_in_encoding) hdmi->hdmi_data.enc_in_encoding = hdmi->plat_data->get_enc_in_encoding(data); @@ -2805,7 +2875,7 @@ static int dw_hdmi_status_show(struct seq_file *s, void *v) seq_printf(s, "TMDS Mode Pixel Clk: %luHz\t\tTMDS Clk: %uHz\n", hdmi->hdmi_data.video_mode.mpixelclock, val); } - + seq_printf(s, "ALLM: %d\n", hdmi->allm_enable); seq_puts(s, "Color Format: "); if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) seq_puts(s, "RGB"); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 28a3bc53f192..088b638a9dfd 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -3240,7 +3240,7 @@ static void dw_hdmi_attach_properties(struct dw_hdmi *hdmi) if (ops && ops->attach_properties) return ops->attach_properties(&hdmi->connector, color, hdmi->version, - hdmi->plat_data->phy_data); + hdmi->plat_data->phy_data, 0); } static void dw_hdmi_destroy_properties(struct dw_hdmi *hdmi) diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index cfa96940c0e2..31eebd779955 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -196,6 +196,8 @@ struct rockchip_hdmi { struct drm_property *output_hdmi_dvi; struct drm_property *output_type_capacity; struct drm_property *user_split_mode_prop; + struct drm_property *allm_capacity; + struct drm_property *allm_enable; struct drm_property_blob *hdr_panel_blob_ptr; struct drm_property_blob *next_hdr_data_ptr; @@ -204,11 +206,13 @@ struct rockchip_hdmi { unsigned int colorimetry; unsigned int hdmi_quant_range; unsigned int phy_bus_width; + unsigned int enable_allm; enum rk_if_color_format hdmi_output; struct rockchip_drm_sub_dev sub_dev; u8 max_frl_rate_per_lane; u8 max_lanes; + u8 add_func; struct rockchip_drm_dsc_cap dsc_cap; struct next_hdr_sink_data next_hdr_data; struct dw_hdmi_link_config link_cfg; @@ -800,6 +804,7 @@ static void hdmi_select_link_config(struct rockchip_hdmi *hdmi, hdmi->link_cfg.dsc_mode = false; hdmi->link_cfg.frl_lanes = max_lanes; hdmi->link_cfg.rate_per_lane = max_rate_per_lane; + hdmi->link_cfg.add_func = hdmi->add_func; if (!max_frl_rate || (tmdsclk < HDMI20_MAX_RATE && mode.clock < HDMI20_MAX_RATE)) { dev_info(hdmi->dev, "use tmds mode\n"); @@ -2167,9 +2172,14 @@ dw_hdmi_rockchip_get_edid_dsc_info(void *data, struct edid *edid) if (!edid) return -EINVAL; + memset(&hdmi->dsc_cap, 0, sizeof(hdmi->dsc_cap)); + hdmi->max_frl_rate_per_lane = 0; + hdmi->max_lanes = 0; + hdmi->add_func = 0; + return rockchip_drm_parse_cea_ext(&hdmi->dsc_cap, &hdmi->max_frl_rate_per_lane, - &hdmi->max_lanes, edid); + &hdmi->max_lanes, &hdmi->add_func, edid); } static int @@ -2296,10 +2306,15 @@ static const struct drm_prop_enum_list output_type_cap_list[] = { { 1, "HDMI" }, }; +static const struct drm_prop_enum_list allm_enable_list[] = { + { 0, "disable" }, + { 1, "enable" }, +}; + static void dw_hdmi_rockchip_attach_properties(struct drm_connector *connector, unsigned int color, int version, - void *data) + void *data, bool allm_en) { struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; struct drm_property *prop; @@ -2414,6 +2429,23 @@ dw_hdmi_rockchip_attach_properties(struct drm_connector *connector, hdmi->user_split_mode ? 1 : 0); } + prop = drm_property_create_bool(connector->dev, 0, "allm_capacity"); + if (prop) { + hdmi->allm_capacity = prop; + drm_object_attach_property(&connector->base, prop, + !!(hdmi->add_func & SUPPORT_HDMI_ALLM)); + } + + prop = drm_property_create_enum(connector->dev, 0, + "allm_enable", + allm_enable_list, + ARRAY_SIZE(allm_enable_list)); + if (prop) { + hdmi->allm_enable = prop; + drm_object_attach_property(&connector->base, prop, 0); + } + hdmi->enable_allm = allm_en; + if (!hdmi->is_hdmi_qp) { prop = drm_property_create_enum(connector->dev, 0, "output_hdmi_dvi", @@ -2518,6 +2550,17 @@ dw_hdmi_rockchip_destroy_properties(struct drm_connector *connector, hdmi->user_split_mode_prop); hdmi->user_split_mode_prop = NULL; } + + if (hdmi->allm_capacity) { + drm_property_destroy(connector->dev, + hdmi->allm_capacity); + hdmi->allm_capacity = NULL; + } + + if (hdmi->allm_enable) { + drm_property_destroy(connector->dev, hdmi->allm_enable); + hdmi->allm_enable = NULL; + } } static int @@ -2566,6 +2609,15 @@ dw_hdmi_rockchip_set_property(struct drm_connector *connector, return 0; } else if (property == hdmi->output_type_capacity) { return 0; + } else if (property == hdmi->allm_capacity) { + return 0; + } else if (property == hdmi->allm_enable) { + u64 allm_enable = hdmi->enable_allm; + + hdmi->enable_allm = val; + if (allm_enable != hdmi->enable_allm) + dw_hdmi_qp_set_allm_enable(hdmi->hdmi_qp, hdmi->enable_allm); + return 0; } DRM_ERROR("Unknown property [PROP:%d:%s]\n", @@ -2635,6 +2687,12 @@ dw_hdmi_rockchip_get_property(struct drm_connector *connector, } else if (property == hdmi->user_split_mode_prop) { *val = hdmi->user_split_mode; return 0; + } else if (property == hdmi->allm_capacity) { + *val = !!(hdmi->add_func & SUPPORT_HDMI_ALLM); + return 0; + } else if (property == hdmi->allm_enable) { + *val = hdmi->enable_allm; + return 0; } DRM_ERROR("Unknown property [PROP:%d:%s]\n", diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 286a9db986c7..185f0387da81 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -620,7 +620,7 @@ void get_max_frl_rate(int max_frl_rate, u8 *max_lanes, u8 *max_rate_per_lane) static void parse_edid_forum_vsdb(struct rockchip_drm_dsc_cap *dsc_cap, - u8 *max_frl_rate_per_lane, u8 *max_lanes, + u8 *max_frl_rate_per_lane, u8 *max_lanes, u8 *add_func, const u8 *hf_vsdb) { u8 max_frl_rate; @@ -635,6 +635,8 @@ void parse_edid_forum_vsdb(struct rockchip_drm_dsc_cap *dsc_cap, get_max_frl_rate(max_frl_rate, max_lanes, max_frl_rate_per_lane); + *add_func = hf_vsdb[8]; + if (cea_db_payload_len(hf_vsdb) < 13) return; @@ -844,13 +846,13 @@ void parse_next_hdr_block(struct next_hdr_sink_data *sink_data, } int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap, - u8 *max_frl_rate_per_lane, u8 *max_lanes, + u8 *max_frl_rate_per_lane, u8 *max_lanes, u8 *add_func, const struct edid *edid) { const u8 *edid_ext; int i, start, end; - if (!dsc_cap || !max_frl_rate_per_lane || !max_lanes || !edid) + if (!dsc_cap || !max_frl_rate_per_lane || !max_lanes || !edid || !add_func) return -EINVAL; edid_ext = find_cea_extension(edid); @@ -865,7 +867,7 @@ int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap, if (cea_db_is_hdmi_forum_vsdb(db)) parse_edid_forum_vsdb(dsc_cap, max_frl_rate_per_lane, - max_lanes, db); + max_lanes, add_func, db); } return 0; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index b19fcf3363fc..424273d61ae4 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -486,7 +486,7 @@ uint32_t rockchip_drm_get_bpp(const struct drm_format_info *info); int rockchip_drm_get_yuv422_format(struct drm_connector *connector, struct edid *edid); int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap, - u8 *max_frl_rate_per_lane, u8 *max_lanes, + u8 *max_frl_rate_per_lane, u8 *max_lanes, u8 *add_func, const struct edid *edid); int rockchip_drm_parse_next_hdr(struct next_hdr_sink_data *sink_data, const struct edid *edid); diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 600c87339ecf..35b4889b01dc 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -78,6 +78,8 @@ struct platform_device; * +----------------------+----------------------------------+------------------------------+ */ +#define SUPPORT_HDMI_ALLM BIT(1) + enum { DW_HDMI_RES_8, DW_HDMI_RES_10, @@ -135,6 +137,7 @@ struct dw_hdmi_link_config { int frl_lanes; int rate_per_lane; int hcactive; + u8 add_func; u8 pps_payload[128]; }; @@ -165,7 +168,7 @@ struct dw_hdmi_qp_phy_ops { struct dw_hdmi_property_ops { void (*attach_properties)(struct drm_connector *connector, unsigned int color, int version, - void *data); + void *data, bool allm_en); void (*destroy_properties)(struct drm_connector *connector, void *data); int (*set_property)(struct drm_connector *connector, @@ -296,6 +299,7 @@ void dw_hdmi_set_output_type(struct dw_hdmi *hdmi, u64 val); bool dw_hdmi_get_output_whether_hdmi(struct dw_hdmi *hdmi); int dw_hdmi_get_output_type_cap(struct dw_hdmi *hdmi); void dw_hdmi_set_cec_adap(struct dw_hdmi *hdmi, struct cec_adapter *adap); +void dw_hdmi_qp_set_allm_enable(struct dw_hdmi_qp *hdmi_qp, bool enable); void dw_hdmi_qp_unbind(struct dw_hdmi_qp *hdmi); struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, From 432173aa04e0445e6b8a655088e76d97f40748cc Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Sat, 24 Sep 2022 15:36:30 +0800 Subject: [PATCH 121/204] drm/rockchip: drv: fix iommu pagefault when pitch isn't aligned as 4 byte The unit of VOP stride is word, so we return error to avoid userspace to commit legal alignment. Signed-off-by: Sandy Huang Change-Id: I147f4985f4c6304db68efb0876c3f918da76ff52 --- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index e4b4c349a94f..308e453bc955 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -198,12 +198,20 @@ rockchip_fb_create(struct drm_device *dev, struct drm_file *file, { struct drm_afbc_framebuffer *afbc_fb; const struct drm_format_info *info; - int ret; + int ret, i; info = drm_get_format_info(dev, mode_cmd); if (!info) return ERR_PTR(-ENOMEM); + for (i = 0; i < info->num_planes; ++i) { + if (mode_cmd->pitches[i] % 4) { + DRM_DEV_ERROR_RATELIMITED(dev->dev, + "fb pitch[%d] must be 4 byte aligned: %d\n", i, mode_cmd->pitches[i]); + return ERR_PTR(-EINVAL); + } + } + afbc_fb = kzalloc(sizeof(*afbc_fb), GFP_KERNEL); if (!afbc_fb) return ERR_PTR(-ENOMEM); @@ -216,8 +224,6 @@ rockchip_fb_create(struct drm_device *dev, struct drm_file *file, } if (drm_is_afbc(mode_cmd->modifier[0])) { - int i; - ret = drm_gem_fb_afbc_init(dev, mode_cmd, afbc_fb); if (ret) { struct drm_gem_object **obj = afbc_fb->base.obj; From 282ccecc15c8996669e56250eba90b4636e795f1 Mon Sep 17 00:00:00 2001 From: Huang Jianan Date: Thu, 5 Aug 2021 08:35:59 +0800 Subject: [PATCH 122/204] BACKPORT: erofs: iomap support for non-tailpacking DIO Add iomap support for non-tailpacking uncompressed data in order to support DIO and DAX. Direct I/O is useful in certain scenarios for uncompressed files. For example, double pagecache can be avoid by direct I/O when loop device is used for uncompressed files containing upper layer compressed filesystem. This adds iomap DIO support for non-tailpacking cases first and tail-packing inline files are handled in the follow-up patch. Link: https://lore.kernel.org/r/20210805003601.183063-2-hsiangkao@linux.alibaba.com Cc: linux-fsdevel@vger.kernel.org Reviewed-by: Chao Yu Signed-off-by: Huang Jianan Signed-off-by: Gao Xiang [ Add include linux/uio.h and replace filemap_read with generic_file_buffered_read ] Signed-off-by: Tao Huang Change-Id: I421298df25eb8b5cf22ad43339d168ac50777012 (cherry picked from commit a08e67a0280215f74eccf14fda81dd7fed6596ba) --- fs/erofs/Kconfig | 1 + fs/erofs/data.c | 95 +++++++++++++++++++++++++++++++++++++++++++++ fs/erofs/inode.c | 5 ++- fs/erofs/internal.h | 1 + 4 files changed, 101 insertions(+), 1 deletion(-) diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 858b3339f381..d5ac4721f055 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -3,6 +3,7 @@ config EROFS_FS tristate "EROFS filesystem support" depends on BLOCK + select FS_IOMAP select LIBCRC32C help EROFS (Enhanced Read-Only File System) is a lightweight diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 76c47c34b09f..75eb05d28240 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -6,6 +6,8 @@ */ #include "internal.h" #include +#include +#include #include @@ -317,10 +319,103 @@ static sector_t erofs_bmap(struct address_space *mapping, sector_t block) return 0; } +static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, + unsigned int flags, struct iomap *iomap, struct iomap *srcmap) +{ + int ret; + struct erofs_map_blocks map; + + map.m_la = offset; + map.m_llen = length; + + ret = erofs_map_blocks_flatmode(inode, &map, EROFS_GET_BLOCKS_RAW); + if (ret < 0) + return ret; + + iomap->bdev = inode->i_sb->s_bdev; + iomap->offset = map.m_la; + iomap->length = map.m_llen; + iomap->flags = 0; + + if (!(map.m_flags & EROFS_MAP_MAPPED)) { + iomap->type = IOMAP_HOLE; + iomap->addr = IOMAP_NULL_ADDR; + if (!iomap->length) + iomap->length = length; + return 0; + } + + /* that shouldn't happen for now */ + if (map.m_flags & EROFS_MAP_META) { + DBG_BUGON(1); + return -ENOTBLK; + } + iomap->type = IOMAP_MAPPED; + iomap->addr = map.m_pa; + return 0; +} + +static const struct iomap_ops erofs_iomap_ops = { + .iomap_begin = erofs_iomap_begin, +}; + +static int erofs_prepare_dio(struct kiocb *iocb, struct iov_iter *to) +{ + struct inode *inode = file_inode(iocb->ki_filp); + loff_t align = iocb->ki_pos | iov_iter_count(to) | + iov_iter_alignment(to); + struct block_device *bdev = inode->i_sb->s_bdev; + unsigned int blksize_mask; + + if (bdev) + blksize_mask = (1 << ilog2(bdev_logical_block_size(bdev))) - 1; + else + blksize_mask = (1 << inode->i_blkbits) - 1; + + if (align & blksize_mask) + return -EINVAL; + + /* + * Temporarily fall back tail-packing inline to buffered I/O instead + * since tail-packing inline support relies on an iomap core update. + */ + if (EROFS_I(inode)->datalayout == EROFS_INODE_FLAT_INLINE && + iocb->ki_pos + iov_iter_count(to) > + rounddown(inode->i_size, EROFS_BLKSIZ)) + return 1; + return 0; +} + +static ssize_t erofs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) +{ + /* no need taking (shared) inode lock since it's a ro filesystem */ + if (!iov_iter_count(to)) + return 0; + + if (iocb->ki_flags & IOCB_DIRECT) { + int err = erofs_prepare_dio(iocb, to); + + if (!err) + return iomap_dio_rw(iocb, to, &erofs_iomap_ops, + NULL, 0); + if (err < 0) + return err; + } + return generic_file_buffered_read(iocb, to, 0); +} + /* for uncompressed (aligned) files and raw access for other files */ const struct address_space_operations erofs_raw_access_aops = { .readpage = erofs_raw_access_readpage, .readahead = erofs_raw_access_readahead, .bmap = erofs_bmap, + .direct_IO = noop_direct_IO, +}; + +const struct file_operations erofs_file_fops = { + .llseek = generic_file_llseek, + .read_iter = erofs_file_read_iter, + .mmap = generic_file_readonly_mmap, + .splice_read = generic_file_splice_read, }; diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index 0a94a52a119f..464404177b5f 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -248,7 +248,10 @@ static int erofs_fill_inode(struct inode *inode, int isdir) switch (inode->i_mode & S_IFMT) { case S_IFREG: inode->i_op = &erofs_generic_iops; - inode->i_fop = &generic_ro_fops; + if (erofs_inode_is_data_compressed(vi->datalayout)) + inode->i_fop = &generic_ro_fops; + else + inode->i_fop = &erofs_file_fops; break; case S_IFDIR: inode->i_op = &erofs_dir_iops; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index e2120c740be9..9b1a96b3244e 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -372,6 +372,7 @@ static inline int z_erofs_map_blocks_iter(struct inode *inode, #endif /* !CONFIG_EROFS_FS_ZIP */ /* data.c */ +extern const struct file_operations erofs_file_fops; struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr); /* inode.c */ From f0b75ac1fc8c440abeca0b5ff0510f400573f644 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Thu, 5 Aug 2021 08:36:00 +0800 Subject: [PATCH 123/204] UPSTREAM: erofs: dax support for non-tailpacking regular file DAX is quite useful for some VM use cases in order to save guest memory extremely with minimal lightweight EROFS. In order to prepare for such use cases, add preliminary dax support for non-tailpacking regular files for now. Tested with the DRAM-emulated PMEM and the EROFS image generated by "mkfs.erofs -Enoinline_data enwik9.fsdax.img enwik9" Link: https://lore.kernel.org/r/20210805003601.183063-3-hsiangkao@linux.alibaba.com Cc: nvdimm@lists.linux.dev Cc: linux-fsdevel@vger.kernel.org Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Change-Id: I640c90ce0b20e636848aac828ed0f568676e74e1 Signed-off-by: Tao Huang (cherry picked from commit 06252e9ce05b94b587e522667b85848a30197b15) --- Documentation/filesystems/erofs.rst | 3 ++ fs/erofs/data.c | 42 +++++++++++++++++++- fs/erofs/inode.c | 4 ++ fs/erofs/internal.h | 3 ++ fs/erofs/super.c | 59 ++++++++++++++++++++++++++++- 5 files changed, 107 insertions(+), 4 deletions(-) diff --git a/Documentation/filesystems/erofs.rst b/Documentation/filesystems/erofs.rst index bf145171c2bf..42109e46b80f 100644 --- a/Documentation/filesystems/erofs.rst +++ b/Documentation/filesystems/erofs.rst @@ -84,6 +84,9 @@ cache_strategy=%s Select a strategy for cached decompression from now on: It still does in-place I/O decompression for the rest compressed physical clusters. ========== ============================================= +dax={always,never} Use direct access (no page cache). See + Documentation/filesystems/dax.rst. +dax A legacy option which is an alias for ``dax=always``. =================== ========================================================= On-disk details diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 75eb05d28240..ffc298d39ae2 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -8,7 +8,7 @@ #include #include #include - +#include #include static void erofs_readendio(struct bio *bio) @@ -333,6 +333,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, return ret; iomap->bdev = inode->i_sb->s_bdev; + iomap->dax_dev = EROFS_I_SB(inode)->dax_dev; iomap->offset = map.m_la; iomap->length = map.m_llen; iomap->flags = 0; @@ -392,6 +393,10 @@ static ssize_t erofs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) if (!iov_iter_count(to)) return 0; +#ifdef CONFIG_FS_DAX + if (IS_DAX(iocb->ki_filp->f_mapping->host)) + return dax_iomap_rw(iocb, to, &erofs_iomap_ops); +#endif if (iocb->ki_flags & IOCB_DIRECT) { int err = erofs_prepare_dio(iocb, to); @@ -412,10 +417,43 @@ const struct address_space_operations erofs_raw_access_aops = { .direct_IO = noop_direct_IO, }; +#ifdef CONFIG_FS_DAX +static vm_fault_t erofs_dax_huge_fault(struct vm_fault *vmf, + enum page_entry_size pe_size) +{ + return dax_iomap_fault(vmf, pe_size, NULL, NULL, &erofs_iomap_ops); +} + +static vm_fault_t erofs_dax_fault(struct vm_fault *vmf) +{ + return erofs_dax_huge_fault(vmf, PE_SIZE_PTE); +} + +static const struct vm_operations_struct erofs_dax_vm_ops = { + .fault = erofs_dax_fault, + .huge_fault = erofs_dax_huge_fault, +}; + +static int erofs_file_mmap(struct file *file, struct vm_area_struct *vma) +{ + if (!IS_DAX(file_inode(file))) + return generic_file_readonly_mmap(file, vma); + + if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) + return -EINVAL; + + vma->vm_ops = &erofs_dax_vm_ops; + vma->vm_flags |= VM_HUGEPAGE; + return 0; +} +#else +#define erofs_file_mmap generic_file_readonly_mmap +#endif + const struct file_operations erofs_file_fops = { .llseek = generic_file_llseek, .read_iter = erofs_file_read_iter, - .mmap = generic_file_readonly_mmap, + .mmap = erofs_file_mmap, .splice_read = generic_file_splice_read, }; diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index 464404177b5f..fae089938afe 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -175,6 +175,10 @@ static struct page *erofs_read_inode(struct inode *inode, inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec; inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec; + inode->i_flags &= ~S_DAX; + if (test_opt(&sbi->ctx, DAX_ALWAYS) && S_ISREG(inode->i_mode) && + vi->datalayout == EROFS_INODE_FLAT_PLAIN) + inode->i_flags |= S_DAX; if (!nblks) /* measure inode.i_blocks as generic filesystems */ inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 9b1a96b3244e..64e1e65e1492 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -84,6 +84,7 @@ struct erofs_sb_info { struct erofs_sb_lz4_info lz4; #endif /* CONFIG_EROFS_FS_ZIP */ + struct dax_device *dax_dev; u32 blocks; u32 meta_blkaddr; #ifdef CONFIG_EROFS_FS_XATTR @@ -116,6 +117,8 @@ struct erofs_sb_info { /* Mount flags set via mount options or defaults */ #define EROFS_MOUNT_XATTR_USER 0x00000010 #define EROFS_MOUNT_POSIX_ACL 0x00000020 +#define EROFS_MOUNT_DAX_ALWAYS 0x00000040 +#define EROFS_MOUNT_DAX_NEVER 0x00000080 #define clear_opt(ctx, option) ((ctx)->mount_opt &= ~EROFS_MOUNT_##option) #define set_opt(ctx, option) ((ctx)->mount_opt |= EROFS_MOUNT_##option) diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 92d9a4a9fc81..e09ad3e33c50 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "xattr.h" #define CREATE_TRACE_POINTS @@ -356,6 +357,8 @@ enum { Opt_user_xattr, Opt_acl, Opt_cache_strategy, + Opt_dax, + Opt_dax_enum, Opt_err }; @@ -366,14 +369,47 @@ static const struct constant_table erofs_param_cache_strategy[] = { {} }; +static const struct constant_table erofs_dax_param_enums[] = { + {"always", EROFS_MOUNT_DAX_ALWAYS}, + {"never", EROFS_MOUNT_DAX_NEVER}, + {} +}; + static const struct fs_parameter_spec erofs_fs_parameters[] = { fsparam_flag_no("user_xattr", Opt_user_xattr), fsparam_flag_no("acl", Opt_acl), fsparam_enum("cache_strategy", Opt_cache_strategy, erofs_param_cache_strategy), + fsparam_flag("dax", Opt_dax), + fsparam_enum("dax", Opt_dax_enum, erofs_dax_param_enums), {} }; +static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode) +{ +#ifdef CONFIG_FS_DAX + struct erofs_fs_context *ctx = fc->fs_private; + + switch (mode) { + case EROFS_MOUNT_DAX_ALWAYS: + warnfc(fc, "DAX enabled. Warning: EXPERIMENTAL, use at your own risk"); + set_opt(ctx, DAX_ALWAYS); + clear_opt(ctx, DAX_NEVER); + return true; + case EROFS_MOUNT_DAX_NEVER: + set_opt(ctx, DAX_NEVER); + clear_opt(ctx, DAX_ALWAYS); + return true; + default: + DBG_BUGON(1); + return false; + } +#else + errorfc(fc, "dax options not supported"); + return false; +#endif +} + static int erofs_fc_parse_param(struct fs_context *fc, struct fs_parameter *param) { @@ -413,6 +449,14 @@ static int erofs_fc_parse_param(struct fs_context *fc, errorfc(fc, "compression not supported, cache_strategy ignored"); #endif break; + case Opt_dax: + if (!erofs_fc_set_dax_mode(fc, EROFS_MOUNT_DAX_ALWAYS)) + return -EINVAL; + break; + case Opt_dax_enum: + if (!erofs_fc_set_dax_mode(fc, result.uint_32)) + return -EINVAL; + break; default: return -ENOPARAM; } @@ -497,10 +541,16 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) return -ENOMEM; sb->s_fs_info = sbi; + sbi->dax_dev = fs_dax_get_by_bdev(sb->s_bdev); err = erofs_read_superblock(sb); if (err) return err; + if (test_opt(ctx, DAX_ALWAYS) && + !bdev_dax_supported(sb->s_bdev, EROFS_BLKSIZ)) { + errorfc(fc, "DAX unsupported by block device. Turning off DAX."); + clear_opt(ctx, DAX_ALWAYS); + } sb->s_flags |= SB_RDONLY | SB_NOATIME; sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_time_gran = 1; @@ -610,6 +660,7 @@ static void erofs_kill_sb(struct super_block *sb) sbi = EROFS_SB(sb); if (!sbi) return; + fs_put_dax(sbi->dax_dev); kfree(sbi); sb->s_fs_info = NULL; } @@ -712,8 +763,8 @@ static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf) static int erofs_show_options(struct seq_file *seq, struct dentry *root) { - struct erofs_sb_info *sbi __maybe_unused = EROFS_SB(root->d_sb); - struct erofs_fs_context *ctx __maybe_unused = &sbi->ctx; + struct erofs_sb_info *sbi = EROFS_SB(root->d_sb); + struct erofs_fs_context *ctx = &sbi->ctx; #ifdef CONFIG_EROFS_FS_XATTR if (test_opt(ctx, XATTR_USER)) @@ -735,6 +786,10 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root) else if (ctx->cache_strategy == EROFS_ZIP_CACHE_READAROUND) seq_puts(seq, ",cache_strategy=readaround"); #endif + if (test_opt(ctx, DAX_ALWAYS)) + seq_puts(seq, ",dax=always"); + if (test_opt(ctx, DAX_NEVER)) + seq_puts(seq, ",dax=never"); return 0; } From bd0c2d37e0a6d3a24eee12b1d1fe3ae3e99de3ab Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 21 Sep 2022 11:44:34 +0800 Subject: [PATCH 124/204] soc: rockchip: ramdisk: Add DAX support Signed-off-by: Tao Huang Change-Id: I27085e3a323975bffc001ac8bd5188be731b9501 --- drivers/soc/rockchip/rockchip_ramdisk.c | 83 ++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/drivers/soc/rockchip/rockchip_ramdisk.c b/drivers/soc/rockchip/rockchip_ramdisk.c index 245dff4b89e4..e2118ac52d2a 100644 --- a/drivers/soc/rockchip/rockchip_ramdisk.c +++ b/drivers/soc/rockchip/rockchip_ramdisk.c @@ -7,9 +7,12 @@ */ #include +#include #include #include +#include #include +#include #define PAGE_SECTORS_SHIFT (PAGE_SHIFT - SECTOR_SHIFT) #define PAGE_SECTORS (1 << PAGE_SECTORS_SHIFT) @@ -21,6 +24,9 @@ struct rd_device { struct device *dev; phys_addr_t mem_addr; size_t mem_size; + size_t mem_pages; + void *mem_kaddr; + struct dax_device *dax_dev; }; static int rd_major; @@ -182,8 +188,65 @@ static const struct block_device_operations rd_fops = { .rw_page = rd_rw_page, }; +static long rd_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, + long nr_pages, void **kaddr, pfn_t *pfn) +{ + struct rd_device *rd = dax_get_private(dax_dev); + + phys_addr_t offset = PFN_PHYS(pgoff); + size_t max_nr_pages = rd->mem_pages - pgoff; + + if (kaddr) + *kaddr = rd->mem_kaddr + offset; + if (pfn) + *pfn = phys_to_pfn_t(rd->mem_addr + offset, PFN_DEV | PFN_MAP); + + return nr_pages > max_nr_pages ? max_nr_pages : nr_pages; +} + +static bool rd_dax_supported(struct dax_device *dax_dev, + struct block_device *bdev, int blocksize, + sector_t start, sector_t sectors) +{ + return true; +} + +static size_t rd_dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *i) +{ + return copy_from_iter(addr, bytes, i); +} + +static size_t rd_dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *i) +{ + return copy_to_iter(addr, bytes, i); +} + +static int rd_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, size_t nr_pages) +{ + long rc; + void *kaddr; + + rc = dax_direct_access(dax_dev, pgoff, nr_pages, &kaddr, NULL); + if (rc < 0) + return rc; + memset(kaddr, 0, nr_pages << PAGE_SHIFT); + + return 0; +} + +static const struct dax_operations rd_dax_ops = { + .direct_access = rd_dax_direct_access, + .dax_supported = rd_dax_supported, + .copy_from_iter = rd_dax_copy_from_iter, + .copy_to_iter = rd_dax_copy_to_iter, + .zero_page_range = rd_dax_zero_page_range, +}; + static int rd_init(struct rd_device *rd, int major, int minor) { + int ret; struct gendisk *disk; rd->rd_queue = blk_alloc_queue(NUMA_NO_NODE); @@ -198,8 +261,10 @@ static int rd_init(struct rd_device *rd, int major, int minor) */ blk_queue_physical_block_size(rd->rd_queue, PAGE_SIZE); disk = alloc_disk(1); - if (!disk) + if (!disk) { + ret = -ENOMEM; goto out_free_queue; + } disk->major = major; disk->first_minor = 0; disk->fops = &rd_fops; @@ -209,9 +274,21 @@ static int rd_init(struct rd_device *rd, int major, int minor) set_capacity(disk, rd->mem_size >> SECTOR_SHIFT); rd->rd_disk = disk; + rd->mem_kaddr = phys_to_virt(rd->mem_addr); + rd->mem_pages = PHYS_PFN(rd->mem_size); + rd->dax_dev = alloc_dax(rd, disk->disk_name, &rd_dax_ops, DAXDEV_F_SYNC); + if (IS_ERR(rd->dax_dev)) { + ret = PTR_ERR(rd->dax_dev); + dev_err(rd->dev, "alloc_dax failed %d\n", ret); + rd->dax_dev = NULL; + goto out_free_queue; + } + /* Tell the block layer that this is not a rotational device */ blk_queue_flag_set(QUEUE_FLAG_NONROT, rd->rd_queue); blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, rd->rd_queue); + if (rd->dax_dev) + blk_queue_flag_set(QUEUE_FLAG_DAX, rd->rd_queue); rd->rd_disk->queue = rd->rd_queue; add_disk(rd->rd_disk); @@ -220,7 +297,7 @@ static int rd_init(struct rd_device *rd, int major, int minor) out_free_queue: blk_cleanup_queue(rd->rd_queue); - return -ENOMEM; + return ret; } static int rd_probe(struct platform_device *pdev) @@ -253,6 +330,8 @@ static int rd_probe(struct platform_device *pdev) rd->mem_size = resource_size(®); ret = rd_init(rd, rd_major, 0); + dev_info(dev, "0x%zx@%pa -> 0x%px dax:%d ret:%d\n", + rd->mem_size, &rd->mem_addr, rd->mem_kaddr, (bool)rd->dax_dev, ret); return ret; } From f14ace6fc654ba1b4ece36a7e9732552963650b7 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 21 Sep 2022 17:34:50 +0800 Subject: [PATCH 125/204] dax: support ARM ARM missing define copy_user_page. Signed-off-by: Tao Huang Change-Id: Ib2ae611a9605e153e72f4c94936ab6ebcae3510e --- fs/dax.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/dax.c b/fs/dax.c index d5d7b9393bca..61e73b6a2314 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -728,6 +728,11 @@ static int copy_cow_page_dax(struct block_device *bdev, struct dax_device *dax_d return rc; } vto = kmap_atomic(to); +#ifdef CONFIG_ARM +#ifndef copy_user_page +#define copy_user_page(to, from, vaddr, pg) copy_page(to, from) +#endif +#endif copy_user_page(vto, (void __force *)kaddr, vaddr, to); kunmap_atomic(vto); dax_read_unlock(id); From 2a3041442454875e5e83ac813479cdc1e1e28dd7 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 21 Sep 2022 17:35:34 +0800 Subject: [PATCH 126/204] erofs: fix panic when CONFIG_ROCKCHIP_RAMDISK=y on ARM Internal error: Oops - BUG: 0 [#1] THUMB2 Modules linked in: CPU: 0 PID: 271 Comm: busybox Not tainted 5.10.110 #117 Hardware name: Generic DT based system PC is at __vm_insert_mixed+0x1e/0xda LR is at vmf_insert_mixed+0xf/0x12 pc : [] lr : [] psr: 20000133 sp : b668fdb0 ip : 00000000 fp : 00000000 r10: 00000000 r9 : b0bb25a8 r8 : 00005001 r7 : 00010000 r6 : 000043a8 r5 : b6656528 r4 : 0000018f r3 : 00007ffb r2 : 00005001 r1 : 00010000 r0 : b6656528 Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA Thumb Segment user Control: 50c53c7d Table: 00d6c059 DAC: 00000055 Process busybox (pid: 271, stack limit = 0xaf1f1034) [] (__vm_insert_mixed) from [] (vmf_insert_mixed+0xf/0x12) [] (vmf_insert_mixed) from [] (dax_iomap_pte_fault+0x429/0x470) [] (dax_iomap_pte_fault) from [] (erofs_dax_huge_fault+0xf/0x18) [] (erofs_dax_huge_fault) from [] (__do_fault+0x23/0x3a) [] (__do_fault) from [] (handle_mm_fault+0x259/0x45e) [] (handle_mm_fault) from [] (do_page_fault+0x10f/0x184) [] (do_page_fault) from [] (do_DataAbort+0x27/0x80) [] (do_DataAbort) from [] (__dabt_usr+0x4f/0x60) Signed-off-by: Tao Huang Change-Id: Id241bf92d60a473dc6baa88d65bb17a775875713 --- fs/erofs/data.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/erofs/data.c b/fs/erofs/data.c index ffc298d39ae2..479c6b00bf35 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -444,6 +444,9 @@ static int erofs_file_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_ops = &erofs_dax_vm_ops; vma->vm_flags |= VM_HUGEPAGE; +#if defined(CONFIG_ROCKCHIP_RAMDISK) && defined(CONFIG_ARM) + vma->vm_flags |= VM_MIXEDMAP; +#endif return 0; } #else From 2c601817eb573c13cf77cb14a64a70816e271b8b Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 21 Sep 2022 17:57:48 +0800 Subject: [PATCH 127/204] dax: allow FS_DAX when CONFIG_ROCKCHIP_RAMDISK=y on ARM Signed-off-by: Tao Huang Change-Id: Ic73f4ad0989e33ea14d1842e2b99dd02628f242e --- fs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/Kconfig b/fs/Kconfig index a6a721108d1c..f6ba03a5a9b4 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -45,7 +45,7 @@ source "fs/zonefs/Kconfig" config FS_DAX bool "Direct Access (DAX) support" depends on MMU - depends on !(ARM || MIPS || SPARC) + depends on !(ARM || MIPS || SPARC) || (ROCKCHIP_RAMDISK && ARM) select DEV_PAGEMAP_OPS if (ZONE_DEVICE && !FS_DAX_LIMITED) select FS_IOMAP select DAX From f1f705150db34757991644c1138d25a3c847ac06 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 21 Sep 2022 18:11:12 +0800 Subject: [PATCH 128/204] ARM: rv1106-tb.config: Replace ROMFS with EROFS with DAX size vmlinux: before: text data bss dec hex filename 2595092 1136900 85540 3817532 3a403c vmlinux after: text data bss dec hex filename 2639206 1147196 121300 3907702 3ba076 vmlinux Signed-off-by: Tao Huang Change-Id: I2c88bec947fe1cf5f28cc0a8e2251fa4012f6165 --- arch/arm/configs/rv1106-tb.config | 110 ++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 5 deletions(-) diff --git a/arch/arm/configs/rv1106-tb.config b/arch/arm/configs/rv1106-tb.config index e5d89bd5a24b..3b992dde3d5b 100644 --- a/arch/arm/configs/rv1106-tb.config +++ b/arch/arm/configs/rv1106-tb.config @@ -1,7 +1,11 @@ CONFIG_BLK_DEV_INITRD=y +CONFIG_CRYPTO=y +CONFIG_DAX=y +CONFIG_EROFS_FS=y # CONFIG_ETHERNET is not set CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_XZ is not set +CONFIG_LIBCRC32C=y # CONFIG_MDIO_DEVICE is not set CONFIG_MMC=y CONFIG_MTD_BLOCK=y @@ -14,11 +18,111 @@ CONFIG_ROCKCHIP_MULTI_RGA=y CONFIG_ROCKCHIP_RAMDISK=y CONFIG_ROCKCHIP_RGA_PROC_FS=y CONFIG_ROCKCHIP_THUNDER_BOOT=y -CONFIG_ROMFS_FS=y # CONFIG_SLUB_SYSFS is not set CONFIG_SND_SOC_RV1106=m CONFIG_VIDEO_ROCKCHIP_CIF=y CONFIG_VIDEO_ROCKCHIP_ISP=y +# CONFIG_ARM_CRYPTO is not set +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_ADIANTUM is not set +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_AES_TI is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_BLAKE2B is not set +# CONFIG_CRYPTO_BLAKE2S is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CFB is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_CRC32 is not set +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_CURVE25519 is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_ECRDSA is not set +# CONFIG_CRYPTO_ESSIV is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_CRYPTO_JITTERENTROPY is not set +# CONFIG_CRYPTO_KEYWRAP is not set +# CONFIG_CRYPTO_LIB_BLAKE2S is not set +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +# CONFIG_CRYPTO_LIB_POLY1305 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=9 +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_MANAGER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_OFB is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_POLY1305 is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_RSA is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA3 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SM2 is not set +# CONFIG_CRYPTO_SM3 is not set +# CONFIG_CRYPTO_SM4 is not set +# CONFIG_CRYPTO_STREEBOG is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_VMAC is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_XXHASH is not set +# CONFIG_CRYPTO_ZSTD is not set +# CONFIG_EROFS_FS_DEBUG is not set +# CONFIG_EROFS_FS_XATTR is not set +# CONFIG_EROFS_FS_ZIP is not set +CONFIG_FS_DAX=y +CONFIG_FS_IOMAP=y # CONFIG_INITCALL_ASYNC is not set # CONFIG_INITRAMFS_FORCE is not set CONFIG_INITRAMFS_SOURCE="" @@ -54,9 +158,5 @@ CONFIG_MTD_BLKDEVS=y CONFIG_ROCKCHIP_RGA_DEBUGGER=y CONFIG_ROCKCHIP_THUNDER_BOOT_MMC=y CONFIG_ROCKCHIP_THUNDER_BOOT_SFC=y -CONFIG_ROMFS_BACKED_BY_BLOCK=y -# CONFIG_ROMFS_BACKED_BY_BOTH is not set -# CONFIG_ROMFS_BACKED_BY_MTD is not set -CONFIG_ROMFS_ON_BLOCK=y # CONFIG_SDIO_UART is not set CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP=y From c5bdad8318215cfdeedb15a207ce0788941548fd Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Thu, 22 Sep 2022 11:24:11 +0800 Subject: [PATCH 129/204] ARM: dts: rockchip: rv1106g-evb2-v10: use erofs default Change-Id: I283eb3e7fe46eac90003d3e430ef91216c94ef2d Signed-off-by: Weiwen Chen --- arch/arm/boot/dts/rv1106g-evb2-v10.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rv1106g-evb2-v10.dts b/arch/arm/boot/dts/rv1106g-evb2-v10.dts index afcdd663e852..68aed729ec96 100644 --- a/arch/arm/boot/dts/rv1106g-evb2-v10.dts +++ b/arch/arm/boot/dts/rv1106g-evb2-v10.dts @@ -14,7 +14,7 @@ compatible = "rockchip,rv1106g-evb2-v10", "rockchip,rv1106"; chosen { - bootargs = "loglevel=0 console=ttyFIQ0 root=/dev/rd0 snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0 driver_async_probe=dwmmc_rockchip"; + 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"; }; vcc_1v8: vcc-1v8 { From 06eeb706c4e56b7fe0c36b84d028a393c7be63d4 Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Mon, 26 Sep 2022 11:16:04 +0800 Subject: [PATCH 130/204] ARM: dts: rockchip: rv1103g-battery-ipc-v10: use erofs default Signed-off-by: Weiwen Chen Change-Id: I0447efd99dd55c9bf995a651ca36976accb03c43 --- arch/arm/boot/dts/rv1103g-battery-ipc-v10.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rv1103g-battery-ipc-v10.dts b/arch/arm/boot/dts/rv1103g-battery-ipc-v10.dts index e7acc2c26afe..c96f6f4f43cb 100644 --- a/arch/arm/boot/dts/rv1103g-battery-ipc-v10.dts +++ b/arch/arm/boot/dts/rv1103g-battery-ipc-v10.dts @@ -44,7 +44,7 @@ }; chosen { - bootargs = "loglevel=0 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"; + 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 { From 8c27fc9fb43db6115eeaaac7991fadcc903dd2de Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Mon, 26 Sep 2022 09:54:30 +0800 Subject: [PATCH 131/204] media: i2c: sc3336 increase vblank to 8ms Signed-off-by: Su Yuefu Change-Id: I66705f4669e3af9a7ef53791a49e26f0fd83e775 --- drivers/media/i2c/sc3336.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/media/i2c/sc3336.c b/drivers/media/i2c/sc3336.c index 44fc244a8e1b..690d56cb3ae6 100644 --- a/drivers/media/i2c/sc3336.c +++ b/drivers/media/i2c/sc3336.c @@ -186,19 +186,17 @@ static const struct regval sc3336_linear_10_2304x1296_25fps_regs[] = { {0x0103, 0x01}, {0x36e9, 0x80}, {0x37f9, 0x80}, - {0x301f, 0x62}, + {0x301f, 0x01}, {0x30b8, 0x33}, - {0x320c, 0x05}, - {0x320d, 0xdc}, + {0x320e, 0x06}, + {0x320f, 0x54}, {0x3253, 0x10}, {0x325f, 0x20}, {0x3301, 0x04}, - {0x3302, 0xa0}, {0x3306, 0x50}, {0x3309, 0xa8}, {0x330a, 0x00}, {0x330b, 0xd8}, - {0x330d, 0xa0}, {0x3314, 0x13}, {0x331f, 0x99}, {0x3333, 0x10}, @@ -220,7 +218,7 @@ static const struct regval sc3336_linear_10_2304x1296_25fps_regs[] = { {0x3399, 0x04}, {0x339a, 0x0a}, {0x339b, 0x3a}, - {0x339c, 0xa0}, + {0x339c, 0xb4}, {0x33a2, 0x04}, {0x33ac, 0x08}, {0x33ad, 0x1c}, @@ -471,7 +469,7 @@ static const struct sc3336_mode supported_modes[] = { }, .exp_def = 0x0080, .hts_def = 0x05dc, - .vts_def = 0x0546, + .vts_def = 0x0654, .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, .reg_list = sc3336_linear_10_2304x1296_25fps_regs, .hdr_mode = NO_HDR, From 88807cdb04c97de7b2006e2ff0e97c9869a43cfe Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Mon, 26 Sep 2022 13:59:56 +0800 Subject: [PATCH 132/204] media: rockchip: isp: fix stream off just close isp Fixes: 39c3a52c259d ("media: rockchip: isp: stop without waiting if isp idle for readback mode") Change-Id: I80446449bf705819b0266e6a0cbdc9e2ee67b57e Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/capture_v21.c | 6 ++++-- drivers/media/platform/rockchip/isp/capture_v30.c | 6 ++++-- drivers/media/platform/rockchip/isp/capture_v32.c | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/capture_v21.c b/drivers/media/platform/rockchip/isp/capture_v21.c index 650b8cb85659..2dc077a48d25 100644 --- a/drivers/media/platform/rockchip/isp/capture_v21.c +++ b/drivers/media/platform/rockchip/isp/capture_v21.c @@ -1331,6 +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; if (!dev->dmarx_dev.trigger && (is_rdbk_stream(stream) || is_hdr_stream(stream))) { @@ -1348,12 +1349,13 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) if (IS_HDR_RDBK(dev->rd_mode)) { spin_lock_irqsave(&dev->hw_dev->rdbk_lock, lock_flags); if (dev->hw_dev->cur_dev_id != dev->dev_id || dev->hw_dev->is_idle) + is_wait = false; + if (atomic_read(&dev->cap_dev.refcnt) == 1 && !is_wait) dev->isp_state = ISP_STOP; spin_unlock_irqrestore(&dev->hw_dev->rdbk_lock, lock_flags); } } - if (dev->isp_state & ISP_START && - !stream->ops->is_stream_stopped(stream)) { + if (is_wait && !stream->ops->is_stream_stopped(stream)) { ret = wait_event_timeout(stream->done, !stream->streaming, msecs_to_jiffies(500)); diff --git a/drivers/media/platform/rockchip/isp/capture_v30.c b/drivers/media/platform/rockchip/isp/capture_v30.c index 683df04e317a..d0ff8e295e0a 100644 --- a/drivers/media/platform/rockchip/isp/capture_v30.c +++ b/drivers/media/platform/rockchip/isp/capture_v30.c @@ -966,6 +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; stream->stopping = true; if (dev->hw_dev->is_single) @@ -973,11 +974,12 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) if (IS_HDR_RDBK(dev->rd_mode)) { spin_lock_irqsave(&dev->hw_dev->rdbk_lock, lock_flags); if (dev->hw_dev->cur_dev_id != dev->dev_id || dev->hw_dev->is_idle) + is_wait = false; + if (atomic_read(&dev->cap_dev.refcnt) == 1 && !is_wait) dev->isp_state = ISP_STOP; spin_unlock_irqrestore(&dev->hw_dev->rdbk_lock, lock_flags); } - if (dev->isp_state & ISP_START && - !stream->ops->is_stream_stopped(stream)) { + if (is_wait && !stream->ops->is_stream_stopped(stream)) { ret = wait_event_timeout(stream->done, !stream->streaming, msecs_to_jiffies(500)); diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index 219f49ad4f10..637b5e882f6d 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -1299,6 +1299,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; stream->stopping = true; stream->is_pause = false; @@ -1307,11 +1308,12 @@ static void rkisp_stream_stop(struct rkisp_stream *stream) if (IS_HDR_RDBK(dev->rd_mode)) { spin_lock_irqsave(&dev->hw_dev->rdbk_lock, lock_flags); if (dev->hw_dev->cur_dev_id != dev->dev_id || dev->hw_dev->is_idle) + is_wait = false; + if (atomic_read(&dev->cap_dev.refcnt) == 1 && !is_wait) dev->isp_state = ISP_STOP; spin_unlock_irqrestore(&dev->hw_dev->rdbk_lock, lock_flags); } - if (dev->isp_state & ISP_START && - !stream->ops->is_stream_stopped(stream)) { + if (is_wait && !stream->ops->is_stream_stopped(stream)) { ret = wait_event_timeout(stream->done, !stream->streaming, msecs_to_jiffies(500)); From 61a8f0b804a94a98709618a97628c2c9c17c87fe Mon Sep 17 00:00:00 2001 From: Wang Xiaobin Date: Mon, 26 Sep 2022 14:44:54 +0800 Subject: [PATCH 133/204] ARM: dts: rockchip: rv1106g-smart-door: remove the meta node The layout about meta has been changed and defined in rv1106-thunder-boot.dtsi. Signed-off-by: Wang Xiaobin Change-Id: I9d658cdcd01905e74e7a9faaaaead6396171dd84 --- arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v10.dts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v10.dts b/arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v10.dts index 081d1603f72a..d64f9b7acca1 100644 --- a/arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v10.dts +++ b/arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v10.dts @@ -98,11 +98,6 @@ status = "disabled"; }; -&meta { - /* reserved meta partition 384KB */ - reg = <0x01e00000 (384 * 0x400)>; -}; - &pinctrl { mcu { /omit-if-no-ref/ From 662e202de897f0c7e8045fc6beebf74ae3254290 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Fri, 23 Sep 2022 17:35:32 +0800 Subject: [PATCH 134/204] dma-buf: heaps: Add the rk_cma_heap Renamed from cma_heap.c and add copyright from Rockchip. Signed-off-by: Jianqun Xu Change-Id: If67e0a76d95389b34027c1990f0816c0b95f2a28 --- drivers/dma-buf/heaps/Makefile | 2 +- drivers/dma-buf/heaps/rk_cma_heap.c | 606 ++++++++++++++++++++++++++++ 2 files changed, 607 insertions(+), 1 deletion(-) create mode 100644 drivers/dma-buf/heaps/rk_cma_heap.c diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile index c5650228bfab..4e134a221a06 100644 --- a/drivers/dma-buf/heaps/Makefile +++ b/drivers/dma-buf/heaps/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_DMABUF_HEAPS_DEFERRED_FREE) += deferred-free-helper.o obj-$(CONFIG_DMABUF_HEAPS_PAGE_POOL) += page_pool.o obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += rk_system_heap.o -obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o +obj-$(CONFIG_DMABUF_HEAPS_CMA) += rk_cma_heap.o diff --git a/drivers/dma-buf/heaps/rk_cma_heap.c b/drivers/dma-buf/heaps/rk_cma_heap.c new file mode 100644 index 000000000000..a405a3e15855 --- /dev/null +++ b/drivers/dma-buf/heaps/rk_cma_heap.c @@ -0,0 +1,606 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * DMABUF CMA heap exporter + * + * Copyright (C) 2012, 2019, 2020 Linaro Ltd. + * Author: for ST-Ericsson. + * + * Also utilizing parts of Andrew Davis' SRAM heap: + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * Copyright (C) 2021, 2022 Rockchip Electronics Co. Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct cma_heap { + struct dma_heap *heap; + struct cma *cma; +}; + +struct cma_heap_buffer { + struct cma_heap *heap; + struct list_head attachments; + struct mutex lock; + unsigned long len; + struct page *cma_pages; + struct page **pages; + pgoff_t pagecount; + int vmap_cnt; + void *vaddr; + + bool uncached; +}; + +struct dma_heap_attachment { + struct device *dev; + struct sg_table table; + struct list_head list; + bool mapped; + + bool uncached; +}; + +static int cma_heap_attach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + int ret; + + a = kzalloc(sizeof(*a), GFP_KERNEL); + if (!a) + return -ENOMEM; + + ret = sg_alloc_table_from_pages(&a->table, buffer->pages, + buffer->pagecount, 0, + buffer->pagecount << PAGE_SHIFT, + GFP_KERNEL); + if (ret) { + kfree(a); + return ret; + } + + a->dev = attachment->dev; + INIT_LIST_HEAD(&a->list); + a->mapped = false; + + a->uncached = buffer->uncached; + attachment->priv = a; + + mutex_lock(&buffer->lock); + list_add(&a->list, &buffer->attachments); + mutex_unlock(&buffer->lock); + + return 0; +} + +static void cma_heap_detach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a = attachment->priv; + + mutex_lock(&buffer->lock); + list_del(&a->list); + mutex_unlock(&buffer->lock); + + sg_free_table(&a->table); + kfree(a); +} + +static struct sg_table *cma_heap_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction direction) +{ + struct dma_heap_attachment *a = attachment->priv; + struct sg_table *table = &a->table; + int attrs = attachment->dma_map_attrs; + int ret; + + if (a->uncached) + attrs |= DMA_ATTR_SKIP_CPU_SYNC; + + ret = dma_map_sgtable(attachment->dev, table, direction, attrs); + if (ret) + return ERR_PTR(-ENOMEM); + a->mapped = true; + return table; +} + +static void cma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *table, + enum dma_data_direction direction) +{ + struct dma_heap_attachment *a = attachment->priv; + int attrs = attachment->dma_map_attrs; + + a->mapped = false; + + if (a->uncached) + attrs |= DMA_ATTR_SKIP_CPU_SYNC; + + dma_unmap_sgtable(attachment->dev, table, direction, attrs); +} + +static int +cma_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, + enum dma_data_direction direction, + unsigned int offset, + unsigned int len) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + + if (buffer->vmap_cnt) + invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); + + if (buffer->uncached) + return 0; + + mutex_lock(&buffer->lock); + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + dma_sync_sgtable_for_cpu(a->dev, &a->table, direction); + } + if (list_empty(&buffer->attachments)) { + phys_addr_t phys = page_to_phys(buffer->cma_pages); + + dma_sync_single_for_cpu(dma_heap_get_dev(buffer->heap->heap), + phys + offset, + len, + direction); + } + mutex_unlock(&buffer->lock); + + return 0; +} + +static int +cma_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, + enum dma_data_direction direction, + unsigned int offset, + unsigned int len) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + + if (buffer->vmap_cnt) + flush_kernel_vmap_range(buffer->vaddr, buffer->len); + + if (buffer->uncached) + return 0; + + mutex_lock(&buffer->lock); + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + dma_sync_sgtable_for_device(a->dev, &a->table, direction); + } + if (list_empty(&buffer->attachments)) { + phys_addr_t phys = page_to_phys(buffer->cma_pages); + + dma_sync_single_for_device(dma_heap_get_dev(buffer->heap->heap), + phys + offset, + len, + direction); + } + mutex_unlock(&buffer->lock); + + return 0; +} + +static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction dir) +{ + return cma_heap_dma_buf_begin_cpu_access_partial(dmabuf, dir, 0, + dmabuf->size); +} + +static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction dir) +{ + return cma_heap_dma_buf_end_cpu_access_partial(dmabuf, dir, 0, + dmabuf->size); +} + +static vm_fault_t cma_heap_vm_fault(struct vm_fault *vmf) +{ + struct vm_area_struct *vma = vmf->vma; + struct cma_heap_buffer *buffer = vma->vm_private_data; + + if (vmf->pgoff > buffer->pagecount) + return VM_FAULT_SIGBUS; + + vmf->page = buffer->pages[vmf->pgoff]; + get_page(vmf->page); + + return 0; +} + +static const struct vm_operations_struct dma_heap_vm_ops = { + .fault = cma_heap_vm_fault, +}; + +static int cma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + + if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0) + return -EINVAL; + + if (buffer->uncached) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + vma->vm_ops = &dma_heap_vm_ops; + vma->vm_private_data = buffer; + + return 0; +} + +static void *cma_heap_do_vmap(struct cma_heap_buffer *buffer) +{ + void *vaddr; + pgprot_t pgprot = PAGE_KERNEL; + + if (buffer->uncached) + pgprot = pgprot_writecombine(PAGE_KERNEL); + + vaddr = vmap(buffer->pages, buffer->pagecount, VM_MAP, pgprot); + if (!vaddr) + return ERR_PTR(-ENOMEM); + + return vaddr; +} + +static void *cma_heap_vmap(struct dma_buf *dmabuf) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + void *vaddr; + + mutex_lock(&buffer->lock); + if (buffer->vmap_cnt) { + buffer->vmap_cnt++; + vaddr = buffer->vaddr; + goto out; + } + + vaddr = cma_heap_do_vmap(buffer); + if (IS_ERR(vaddr)) + goto out; + + buffer->vaddr = vaddr; + buffer->vmap_cnt++; +out: + mutex_unlock(&buffer->lock); + + return vaddr; +} + +static void cma_heap_vunmap(struct dma_buf *dmabuf, void *vaddr) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + + mutex_lock(&buffer->lock); + if (!--buffer->vmap_cnt) { + vunmap(buffer->vaddr); + buffer->vaddr = NULL; + } + mutex_unlock(&buffer->lock); +} + +static void cma_heap_dma_buf_release(struct dma_buf *dmabuf) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + struct cma_heap *cma_heap = buffer->heap; + + if (buffer->vmap_cnt > 0) { + WARN(1, "%s: buffer still mapped in the kernel\n", __func__); + vunmap(buffer->vaddr); + } + + /* free page list */ + kfree(buffer->pages); + /* release memory */ + cma_release(cma_heap->cma, buffer->cma_pages, buffer->pagecount); + kfree(buffer); +} + +static const struct dma_buf_ops cma_heap_buf_ops = { + .attach = cma_heap_attach, + .detach = cma_heap_detach, + .map_dma_buf = cma_heap_map_dma_buf, + .unmap_dma_buf = cma_heap_unmap_dma_buf, + .begin_cpu_access = cma_heap_dma_buf_begin_cpu_access, + .end_cpu_access = cma_heap_dma_buf_end_cpu_access, + .begin_cpu_access_partial = cma_heap_dma_buf_begin_cpu_access_partial, + .end_cpu_access_partial = cma_heap_dma_buf_end_cpu_access_partial, + .mmap = cma_heap_mmap, + .vmap = cma_heap_vmap, + .vunmap = cma_heap_vunmap, + .release = cma_heap_dma_buf_release, +}; + +static struct dma_buf *cma_heap_do_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags, bool uncached) +{ + struct cma_heap *cma_heap = dma_heap_get_drvdata(heap); + struct cma_heap_buffer *buffer; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + size_t size = PAGE_ALIGN(len); + pgoff_t pagecount = size >> PAGE_SHIFT; + unsigned long align = get_order(size); + struct page *cma_pages; + struct dma_buf *dmabuf; + int ret = -ENOMEM; + pgoff_t pg; + dma_addr_t dma; + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) + return ERR_PTR(-ENOMEM); + + buffer->uncached = uncached; + + INIT_LIST_HEAD(&buffer->attachments); + mutex_init(&buffer->lock); + buffer->len = size; + + if (align > CONFIG_CMA_ALIGNMENT) + align = CONFIG_CMA_ALIGNMENT; + + cma_pages = cma_alloc(cma_heap->cma, pagecount, align, GFP_KERNEL); + if (!cma_pages) + goto free_buffer; + + /* Clear the cma pages */ + if (PageHighMem(cma_pages)) { + unsigned long nr_clear_pages = pagecount; + struct page *page = cma_pages; + + while (nr_clear_pages > 0) { + void *vaddr = kmap_atomic(page); + + memset(vaddr, 0, PAGE_SIZE); + kunmap_atomic(vaddr); + /* + * Avoid wasting time zeroing memory if the process + * has been killed by by SIGKILL + */ + if (fatal_signal_pending(current)) + goto free_cma; + page++; + nr_clear_pages--; + } + } else { + memset(page_address(cma_pages), 0, size); + } + + buffer->pages = kmalloc_array(pagecount, sizeof(*buffer->pages), GFP_KERNEL); + if (!buffer->pages) { + ret = -ENOMEM; + goto free_cma; + } + + for (pg = 0; pg < pagecount; pg++) + buffer->pages[pg] = &cma_pages[pg]; + + buffer->cma_pages = cma_pages; + buffer->heap = cma_heap; + buffer->pagecount = pagecount; + + /* create the dmabuf */ + exp_info.exp_name = dma_heap_get_name(heap); + exp_info.ops = &cma_heap_buf_ops; + exp_info.size = buffer->len; + exp_info.flags = fd_flags; + exp_info.priv = buffer; + dmabuf = dma_buf_export(&exp_info); + if (IS_ERR(dmabuf)) { + ret = PTR_ERR(dmabuf); + goto free_pages; + } + + if (buffer->uncached) { + dma = dma_map_page(dma_heap_get_dev(heap), buffer->cma_pages, 0, + buffer->pagecount * PAGE_SIZE, DMA_FROM_DEVICE); + dma_unmap_page(dma_heap_get_dev(heap), dma, + buffer->pagecount * PAGE_SIZE, DMA_FROM_DEVICE); + } + + return dmabuf; + +free_pages: + kfree(buffer->pages); +free_cma: + cma_release(cma_heap->cma, cma_pages, pagecount); +free_buffer: + kfree(buffer); + + return ERR_PTR(ret); +} + +static struct dma_buf *cma_heap_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + return cma_heap_do_allocate(heap, len, fd_flags, heap_flags, false); +} + +#if IS_ENABLED(CONFIG_NO_GKI) +static int cma_heap_get_phys(struct dma_heap *heap, + struct dma_heap_phys_data *phys) +{ + struct cma_heap *cma_heap = dma_heap_get_drvdata(heap); + struct cma_heap_buffer *buffer; + struct dma_buf *dmabuf; + + phys->paddr = (__u64)-1; + + if (IS_ERR_OR_NULL(phys)) + return -EINVAL; + + dmabuf = dma_buf_get(phys->fd); + if (IS_ERR_OR_NULL(dmabuf)) + return -EBADFD; + + buffer = dmabuf->priv; + if (IS_ERR_OR_NULL(buffer)) + goto err; + + if (buffer->heap != cma_heap) + goto err; + + phys->paddr = page_to_phys(buffer->cma_pages); + +err: + dma_buf_put(dmabuf); + + return (phys->paddr == (__u64)-1) ? -EINVAL : 0; +} +#endif + +static const struct dma_heap_ops cma_heap_ops = { + .allocate = cma_heap_allocate, +#if IS_ENABLED(CONFIG_NO_GKI) + .get_phys = cma_heap_get_phys, +#endif +}; + +static struct dma_buf *cma_uncached_heap_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + return cma_heap_do_allocate(heap, len, fd_flags, heap_flags, true); +} + +static struct dma_buf *cma_uncached_heap_not_initialized(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + pr_info("heap %s not initialized\n", dma_heap_get_name(heap)); + return ERR_PTR(-EBUSY); +} + +static struct dma_heap_ops cma_uncached_heap_ops = { + .allocate = cma_uncached_heap_not_initialized, +}; + +static int set_heap_dev_dma(struct device *heap_dev) +{ + int err = 0; + + if (!heap_dev) + return -EINVAL; + + dma_coerce_mask_and_coherent(heap_dev, DMA_BIT_MASK(64)); + + if (!heap_dev->dma_parms) { + heap_dev->dma_parms = devm_kzalloc(heap_dev, + sizeof(*heap_dev->dma_parms), + GFP_KERNEL); + if (!heap_dev->dma_parms) + return -ENOMEM; + + err = dma_set_max_seg_size(heap_dev, (unsigned int)DMA_BIT_MASK(64)); + if (err) { + devm_kfree(heap_dev, heap_dev->dma_parms); + dev_err(heap_dev, "Failed to set DMA segment size, err:%d\n", err); + return err; + } + } + + return 0; +} + +static int __add_cma_heap(struct cma *cma, void *data) +{ + struct cma_heap *cma_heap, *cma_uncached_heap; + struct dma_heap_export_info exp_info; + int ret; + + cma_heap = kzalloc(sizeof(*cma_heap), GFP_KERNEL); + if (!cma_heap) + return -ENOMEM; + cma_heap->cma = cma; + + exp_info.name = cma_get_name(cma); + exp_info.ops = &cma_heap_ops; + exp_info.priv = cma_heap; + + cma_heap->heap = dma_heap_add(&exp_info); + if (IS_ERR(cma_heap->heap)) { + ret = PTR_ERR(cma_heap->heap); + goto free_cma_heap; + } + + cma_uncached_heap = kzalloc(sizeof(*cma_heap), GFP_KERNEL); + if (!cma_uncached_heap) { + ret = -ENOMEM; + goto put_cma_heap; + } + + cma_uncached_heap->cma = cma; + + exp_info.name = "cma-uncached"; + exp_info.ops = &cma_uncached_heap_ops; + exp_info.priv = cma_uncached_heap; + + cma_uncached_heap->heap = dma_heap_add(&exp_info); + if (IS_ERR(cma_uncached_heap->heap)) { + ret = PTR_ERR(cma_uncached_heap->heap); + goto free_uncached_cma_heap; + } + + ret = set_heap_dev_dma(dma_heap_get_dev(cma_uncached_heap->heap)); + if (ret) + goto put_uncached_cma_heap; + + mb(); /* make sure we only set allocate after dma_mask is set */ + cma_uncached_heap_ops.allocate = cma_uncached_heap_allocate; + + return 0; + +put_uncached_cma_heap: + dma_heap_put(cma_uncached_heap->heap); +free_uncached_cma_heap: + kfree(cma_uncached_heap); +put_cma_heap: + dma_heap_put(cma_heap->heap); +free_cma_heap: + kfree(cma_heap); + + return ret; +} + +static int add_default_cma_heap(void) +{ + struct cma *default_cma = dev_get_cma_area(NULL); + int ret = 0; + + if (default_cma) + ret = __add_cma_heap(default_cma, NULL); + + return ret; +} +module_init(add_default_cma_heap); +MODULE_DESCRIPTION("DMA-BUF CMA Heap"); +MODULE_LICENSE("GPL v2"); From b7cf9d28723b3064b83af1e1da442d41fcceeadf Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Mon, 26 Sep 2022 19:14:55 +0800 Subject: [PATCH 135/204] drm/bridge: synopsys: dw-hdmi-qp: Reset avp data path before flt Fix probabilistic no signal output in samsung 8K TV. Signed-off-by: Algea Cao Change-Id: I366311b61595534ce8fefeb235bc9b20cb3991e0 --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 6e7335f2104f..59965f85109c 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -1598,6 +1598,9 @@ static int hdmi_start_flt(struct dw_hdmi_qp *hdmi, u8 rate) hdmi_modb(hdmi, AVP_DATAPATH_VIDEO_SWDISABLE, AVP_DATAPATH_VIDEO_SWDISABLE, GLOBAL_SWDISABLE); + /* reset avp data path */ + hdmi_writel(hdmi, BIT(6), GLOBAL_SWRESET_REQUEST); + /* FLT_READY & FFE_LEVELS read */ for (i = 0; i < 20; i++) { drm_scdc_readb(hdmi->ddc, SCDC_STATUS_FLAGS_0, &val); From cc85d657a18e8eb87c7c1e4c8ae6236176e5b89b Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Tue, 27 Sep 2022 08:54:39 +0800 Subject: [PATCH 136/204] dma-buf: heaps: rk_cma_heap fix module license to "GPL" WARNING: Prefer "GPL" over "GPL v2" - see commit bf7fbeeae6db ("module: Cure the MODULE_LICENSE "GPL" vs. "GPL v2" bogosity") Signed-off-by: Jianqun Xu Change-Id: I52c2110ac9b150e615bbeb497b7e997d49ec2106 --- drivers/dma-buf/heaps/rk_cma_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma-buf/heaps/rk_cma_heap.c b/drivers/dma-buf/heaps/rk_cma_heap.c index a405a3e15855..49dec4bdf2eb 100644 --- a/drivers/dma-buf/heaps/rk_cma_heap.c +++ b/drivers/dma-buf/heaps/rk_cma_heap.c @@ -603,4 +603,4 @@ static int add_default_cma_heap(void) } module_init(add_default_cma_heap); MODULE_DESCRIPTION("DMA-BUF CMA Heap"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); From 59b87bad33be1ee960aa17ea221aacdffd95e3f0 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Tue, 27 Sep 2022 08:58:05 +0800 Subject: [PATCH 137/204] dma-buf: heaps: rk_cma_heap fix the implement of partial sync Make the partial sync separated from normal sync. Fixes: dcbfe3bd8c9f ("dma-buf: cma_heap: support dmabuf partial sync") Signed-off-by: Jianqun Xu Change-Id: I07342cf850f212e9682a589818069977ef4b78a8 --- drivers/dma-buf/heaps/rk_cma_heap.c | 76 ++++++++++++++++------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/drivers/dma-buf/heaps/rk_cma_heap.c b/drivers/dma-buf/heaps/rk_cma_heap.c index 49dec4bdf2eb..3d5245ed298e 100644 --- a/drivers/dma-buf/heaps/rk_cma_heap.c +++ b/drivers/dma-buf/heaps/rk_cma_heap.c @@ -142,7 +142,7 @@ cma_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, unsigned int len) { struct cma_heap_buffer *buffer = dmabuf->priv; - struct dma_heap_attachment *a; + phys_addr_t phys = page_to_phys(buffer->cma_pages); if (buffer->vmap_cnt) invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); @@ -151,19 +151,10 @@ cma_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, return 0; mutex_lock(&buffer->lock); - list_for_each_entry(a, &buffer->attachments, list) { - if (!a->mapped) - continue; - dma_sync_sgtable_for_cpu(a->dev, &a->table, direction); - } - if (list_empty(&buffer->attachments)) { - phys_addr_t phys = page_to_phys(buffer->cma_pages); - - dma_sync_single_for_cpu(dma_heap_get_dev(buffer->heap->heap), - phys + offset, - len, - direction); - } + dma_sync_single_for_cpu(dma_heap_get_dev(buffer->heap->heap), + phys + offset, + len, + direction); mutex_unlock(&buffer->lock); return 0; @@ -176,7 +167,7 @@ cma_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, unsigned int len) { struct cma_heap_buffer *buffer = dmabuf->priv; - struct dma_heap_attachment *a; + phys_addr_t phys = page_to_phys(buffer->cma_pages); if (buffer->vmap_cnt) flush_kernel_vmap_range(buffer->vaddr, buffer->len); @@ -185,36 +176,53 @@ cma_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, return 0; mutex_lock(&buffer->lock); - list_for_each_entry(a, &buffer->attachments, list) { - if (!a->mapped) - continue; - dma_sync_sgtable_for_device(a->dev, &a->table, direction); - } - if (list_empty(&buffer->attachments)) { - phys_addr_t phys = page_to_phys(buffer->cma_pages); - - dma_sync_single_for_device(dma_heap_get_dev(buffer->heap->heap), - phys + offset, - len, - direction); - } + dma_sync_single_for_device(dma_heap_get_dev(buffer->heap->heap), + phys + offset, + len, + direction); mutex_unlock(&buffer->lock); return 0; } static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, - enum dma_data_direction dir) + enum dma_data_direction direction) { - return cma_heap_dma_buf_begin_cpu_access_partial(dmabuf, dir, 0, - dmabuf->size); + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + + if (buffer->vmap_cnt) + invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); + + mutex_lock(&buffer->lock); + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + dma_sync_sgtable_for_cpu(a->dev, &a->table, direction); + } + mutex_unlock(&buffer->lock); + + return 0; } static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, - enum dma_data_direction dir) + enum dma_data_direction direction) { - return cma_heap_dma_buf_end_cpu_access_partial(dmabuf, dir, 0, - dmabuf->size); + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + + if (buffer->vmap_cnt) + flush_kernel_vmap_range(buffer->vaddr, buffer->len); + + mutex_lock(&buffer->lock); + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + dma_sync_sgtable_for_device(a->dev, &a->table, direction); + } + mutex_unlock(&buffer->lock); + + return 0; } static vm_fault_t cma_heap_vm_fault(struct vm_fault *vmf) From e8bbe703942485eb9a223a79063d66dfad3e058e Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Tue, 27 Sep 2022 09:00:12 +0800 Subject: [PATCH 138/204] dma-buf: heaps: rk_cma_heap named cma-heap default to be "cma-heap" The userland (gralloc or libdmaheap) fixed to use a heap name "cma-heap" to be the device name, without this patch, the dt file should named the cma default node name as "cma". otherwise it is defaultly to be "reserved" that make the userland fail to open the device. This patch fixes the cma-heap default name to "cma-heap". Signed-off-by: Jianqun Xu Change-Id: I09befb35bb8d4cd042b8c1c66c5d99c7d58fbbb6 --- drivers/dma-buf/heaps/rk_cma_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma-buf/heaps/rk_cma_heap.c b/drivers/dma-buf/heaps/rk_cma_heap.c index 3d5245ed298e..7631997e8e21 100644 --- a/drivers/dma-buf/heaps/rk_cma_heap.c +++ b/drivers/dma-buf/heaps/rk_cma_heap.c @@ -550,7 +550,7 @@ static int __add_cma_heap(struct cma *cma, void *data) return -ENOMEM; cma_heap->cma = cma; - exp_info.name = cma_get_name(cma); + exp_info.name = "cma"; exp_info.ops = &cma_heap_ops; exp_info.priv = cma_heap; From 449b29d7ab04ec2149a29d293562887cbcc51692 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Mon, 26 Sep 2022 14:46:05 +0800 Subject: [PATCH 139/204] Revert "dma-buf: cma_heap: Fix compile warning when !CONFIG_NO_GKI" This reverts commit 78a3c0db57b0f742898309e6aa270c81595f2ac2. Convert to use rk_cma_heap.c Signed-off-by: Jianqun Xu Change-Id: I799107c485187d99f1c71e58ede360865337cf3e --- drivers/dma-buf/heaps/cma_heap.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index 803f523cd3e5..ab6f937eb60d 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -441,7 +441,6 @@ static struct dma_buf *cma_heap_allocate(struct dma_heap *heap, return cma_heap_do_allocate(heap, len, fd_flags, heap_flags, false); } -#if IS_ENABLED(CONFIG_NO_GKI) static int cma_heap_get_phys(struct dma_heap *heap, struct dma_heap_phys_data *phys) { @@ -472,7 +471,6 @@ err: return (phys->paddr == (__u64)-1) ? -EINVAL : 0; } -#endif static const struct dma_heap_ops cma_heap_ops = { .allocate = cma_heap_allocate, From 23cdadf8a5c2e6b12764fea4d6c38f4be21ea2b6 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Mon, 26 Sep 2022 14:46:08 +0800 Subject: [PATCH 140/204] Revert "dma-buf: dma-heap: heap ops supports get_phys" This partially reverts commit 61a32e157ecef6732df9bf400c2da29e8f3df390. Convert to use rk_cma_heap.c and keep fixes to dma-heap.c Signed-off-by: Jianqun Xu Change-Id: I740d0de75d8b526f7de987b0b1c18dc3f6298705 --- drivers/dma-buf/heaps/cma_heap.c | 35 -------------------------------- 1 file changed, 35 deletions(-) diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index ab6f937eb60d..2c0ba561957c 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -21,7 +21,6 @@ #include #include #include -#include struct cma_heap { @@ -441,42 +440,8 @@ static struct dma_buf *cma_heap_allocate(struct dma_heap *heap, return cma_heap_do_allocate(heap, len, fd_flags, heap_flags, false); } -static int cma_heap_get_phys(struct dma_heap *heap, - struct dma_heap_phys_data *phys) -{ - struct cma_heap *cma_heap = dma_heap_get_drvdata(heap); - struct cma_heap_buffer *buffer; - struct dma_buf *dmabuf; - - phys->paddr = (__u64)-1; - - if (IS_ERR_OR_NULL(phys)) - return -EINVAL; - - dmabuf = dma_buf_get(phys->fd); - if (IS_ERR_OR_NULL(dmabuf)) - return -EBADFD; - - buffer = dmabuf->priv; - if (IS_ERR_OR_NULL(buffer)) - goto err; - - if (buffer->heap != cma_heap) - goto err; - - phys->paddr = page_to_phys(buffer->cma_pages); - -err: - dma_buf_put(dmabuf); - - return (phys->paddr == (__u64)-1) ? -EINVAL : 0; -} - static const struct dma_heap_ops cma_heap_ops = { .allocate = cma_heap_allocate, -#if IS_ENABLED(CONFIG_NO_GKI) - .get_phys = cma_heap_get_phys, -#endif }; static struct dma_buf *cma_uncached_heap_allocate(struct dma_heap *heap, From 257c52e940268ee52775b9661fe7901e6c6791d7 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Mon, 26 Sep 2022 14:46:09 +0800 Subject: [PATCH 141/204] Revert "dma-buf: cma_heap: support dmabuf partial sync" This reverts commit dcbfe3bd8c9f09bd58a248ff2e60941937caa7f9. Convert to use rk_cma_heap.c Signed-off-by: Jianqun Xu Change-Id: Iee39ced1023abce09116d73143bb81a6b15ca54f --- drivers/dma-buf/heaps/cma_heap.c | 46 +++----------------------------- 1 file changed, 4 insertions(+), 42 deletions(-) diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index 2c0ba561957c..90602a77086b 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -132,11 +132,8 @@ static void cma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, dma_unmap_sgtable(attachment->dev, table, direction, attrs); } -static int -cma_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, - enum dma_data_direction direction, - unsigned int offset, - unsigned int len) +static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction direction) { struct cma_heap_buffer *buffer = dmabuf->priv; struct dma_heap_attachment *a; @@ -153,24 +150,13 @@ cma_heap_dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf, continue; dma_sync_sgtable_for_cpu(a->dev, &a->table, direction); } - if (list_empty(&buffer->attachments)) { - phys_addr_t phys = page_to_phys(buffer->cma_pages); - - dma_sync_single_for_cpu(dma_heap_get_dev(buffer->heap->heap), - phys + offset, - len, - direction); - } mutex_unlock(&buffer->lock); return 0; } -static int -cma_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, - enum dma_data_direction direction, - unsigned int offset, - unsigned int len) +static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction direction) { struct cma_heap_buffer *buffer = dmabuf->priv; struct dma_heap_attachment *a; @@ -187,33 +173,11 @@ cma_heap_dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf, continue; dma_sync_sgtable_for_device(a->dev, &a->table, direction); } - if (list_empty(&buffer->attachments)) { - phys_addr_t phys = page_to_phys(buffer->cma_pages); - - dma_sync_single_for_device(dma_heap_get_dev(buffer->heap->heap), - phys + offset, - len, - direction); - } mutex_unlock(&buffer->lock); return 0; } -static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, - enum dma_data_direction dir) -{ - return cma_heap_dma_buf_begin_cpu_access_partial(dmabuf, dir, 0, - dmabuf->size); -} - -static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, - enum dma_data_direction dir) -{ - return cma_heap_dma_buf_end_cpu_access_partial(dmabuf, dir, 0, - dmabuf->size); -} - static vm_fault_t cma_heap_vm_fault(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; @@ -323,8 +287,6 @@ static const struct dma_buf_ops cma_heap_buf_ops = { .unmap_dma_buf = cma_heap_unmap_dma_buf, .begin_cpu_access = cma_heap_dma_buf_begin_cpu_access, .end_cpu_access = cma_heap_dma_buf_end_cpu_access, - .begin_cpu_access_partial = cma_heap_dma_buf_begin_cpu_access_partial, - .end_cpu_access_partial = cma_heap_dma_buf_end_cpu_access_partial, .mmap = cma_heap_mmap, .vmap = cma_heap_vmap, .vunmap = cma_heap_vunmap, From 5b4996597cf78f49e03856e7448823bab5269b98 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Mon, 26 Sep 2022 14:46:11 +0800 Subject: [PATCH 142/204] Revert "dma-buf: heaps: cma: add uncached" This reverts commit d3bf1f97b44cdd8f356bb0dc3bc3183826b7f564. Convert to use rk_cma_heap.c Signed-off-by: Jianqun Xu Change-Id: I463c67387fc8fba06b4cf5b09e8d4d1c7f0e4856 --- drivers/dma-buf/heaps/cma_heap.c | 142 ++----------------------------- 1 file changed, 8 insertions(+), 134 deletions(-) diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index 90602a77086b..fd564aa70ee9 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -38,8 +38,6 @@ struct cma_heap_buffer { pgoff_t pagecount; int vmap_cnt; void *vaddr; - - bool uncached; }; struct dma_heap_attachment { @@ -47,8 +45,6 @@ struct dma_heap_attachment { struct sg_table table; struct list_head list; bool mapped; - - bool uncached; }; static int cma_heap_attach(struct dma_buf *dmabuf, @@ -75,7 +71,6 @@ static int cma_heap_attach(struct dma_buf *dmabuf, INIT_LIST_HEAD(&a->list); a->mapped = false; - a->uncached = buffer->uncached; attachment->priv = a; mutex_lock(&buffer->lock); @@ -107,9 +102,6 @@ static struct sg_table *cma_heap_map_dma_buf(struct dma_buf_attachment *attachme int attrs = attachment->dma_map_attrs; int ret; - if (a->uncached) - attrs |= DMA_ATTR_SKIP_CPU_SYNC; - ret = dma_map_sgtable(attachment->dev, table, direction, attrs); if (ret) return ERR_PTR(-ENOMEM); @@ -125,10 +117,6 @@ static void cma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, int attrs = attachment->dma_map_attrs; a->mapped = false; - - if (a->uncached) - attrs |= DMA_ATTR_SKIP_CPU_SYNC; - dma_unmap_sgtable(attachment->dev, table, direction, attrs); } @@ -141,9 +129,6 @@ static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, if (buffer->vmap_cnt) invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); - if (buffer->uncached) - return 0; - mutex_lock(&buffer->lock); list_for_each_entry(a, &buffer->attachments, list) { if (!a->mapped) @@ -164,9 +149,6 @@ static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, if (buffer->vmap_cnt) flush_kernel_vmap_range(buffer->vaddr, buffer->len); - if (buffer->uncached) - return 0; - mutex_lock(&buffer->lock); list_for_each_entry(a, &buffer->attachments, list) { if (!a->mapped) @@ -203,9 +185,6 @@ static int cma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0) return -EINVAL; - if (buffer->uncached) - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - vma->vm_ops = &dma_heap_vm_ops; vma->vm_private_data = buffer; @@ -215,12 +194,8 @@ static int cma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) static void *cma_heap_do_vmap(struct cma_heap_buffer *buffer) { void *vaddr; - pgprot_t pgprot = PAGE_KERNEL; - if (buffer->uncached) - pgprot = pgprot_writecombine(PAGE_KERNEL); - - vaddr = vmap(buffer->pages, buffer->pagecount, VM_MAP, pgprot); + vaddr = vmap(buffer->pages, buffer->pagecount, VM_MAP, PAGE_KERNEL); if (!vaddr) return ERR_PTR(-ENOMEM); @@ -293,10 +268,10 @@ static const struct dma_buf_ops cma_heap_buf_ops = { .release = cma_heap_dma_buf_release, }; -static struct dma_buf *cma_heap_do_allocate(struct dma_heap *heap, +static struct dma_buf *cma_heap_allocate(struct dma_heap *heap, unsigned long len, unsigned long fd_flags, - unsigned long heap_flags, bool uncached) + unsigned long heap_flags) { struct cma_heap *cma_heap = dma_heap_get_drvdata(heap); struct cma_heap_buffer *buffer; @@ -308,14 +283,11 @@ static struct dma_buf *cma_heap_do_allocate(struct dma_heap *heap, struct dma_buf *dmabuf; int ret = -ENOMEM; pgoff_t pg; - dma_addr_t dma; buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); if (!buffer) return ERR_PTR(-ENOMEM); - buffer->uncached = uncached; - INIT_LIST_HEAD(&buffer->attachments); mutex_init(&buffer->lock); buffer->len = size; @@ -375,13 +347,6 @@ static struct dma_buf *cma_heap_do_allocate(struct dma_heap *heap, goto free_pages; } - if (buffer->uncached) { - dma = dma_map_page(dma_heap_get_dev(heap), buffer->cma_pages, 0, - buffer->pagecount * PAGE_SIZE, DMA_FROM_DEVICE); - dma_unmap_page(dma_heap_get_dev(heap), dma, - buffer->pagecount * PAGE_SIZE, DMA_FROM_DEVICE); - } - return dmabuf; free_pages: @@ -394,71 +359,14 @@ free_buffer: return ERR_PTR(ret); } -static struct dma_buf *cma_heap_allocate(struct dma_heap *heap, - unsigned long len, - unsigned long fd_flags, - unsigned long heap_flags) -{ - return cma_heap_do_allocate(heap, len, fd_flags, heap_flags, false); -} - static const struct dma_heap_ops cma_heap_ops = { .allocate = cma_heap_allocate, }; -static struct dma_buf *cma_uncached_heap_allocate(struct dma_heap *heap, - unsigned long len, - unsigned long fd_flags, - unsigned long heap_flags) -{ - return cma_heap_do_allocate(heap, len, fd_flags, heap_flags, true); -} - -static struct dma_buf *cma_uncached_heap_not_initialized(struct dma_heap *heap, - unsigned long len, - unsigned long fd_flags, - unsigned long heap_flags) -{ - pr_info("heap %s not initialized\n", dma_heap_get_name(heap)); - return ERR_PTR(-EBUSY); -} - -static struct dma_heap_ops cma_uncached_heap_ops = { - .allocate = cma_uncached_heap_not_initialized, -}; - -static int set_heap_dev_dma(struct device *heap_dev) -{ - int err = 0; - - if (!heap_dev) - return -EINVAL; - - dma_coerce_mask_and_coherent(heap_dev, DMA_BIT_MASK(64)); - - if (!heap_dev->dma_parms) { - heap_dev->dma_parms = devm_kzalloc(heap_dev, - sizeof(*heap_dev->dma_parms), - GFP_KERNEL); - if (!heap_dev->dma_parms) - return -ENOMEM; - - err = dma_set_max_seg_size(heap_dev, (unsigned int)DMA_BIT_MASK(64)); - if (err) { - devm_kfree(heap_dev, heap_dev->dma_parms); - dev_err(heap_dev, "Failed to set DMA segment size, err:%d\n", err); - return err; - } - } - - return 0; -} - static int __add_cma_heap(struct cma *cma, void *data) { - struct cma_heap *cma_heap, *cma_uncached_heap; + struct cma_heap *cma_heap; struct dma_heap_export_info exp_info; - int ret; cma_heap = kzalloc(sizeof(*cma_heap), GFP_KERNEL); if (!cma_heap) @@ -471,47 +379,13 @@ static int __add_cma_heap(struct cma *cma, void *data) cma_heap->heap = dma_heap_add(&exp_info); if (IS_ERR(cma_heap->heap)) { - ret = PTR_ERR(cma_heap->heap); - goto free_cma_heap; + int ret = PTR_ERR(cma_heap->heap); + + kfree(cma_heap); + return ret; } - cma_uncached_heap = kzalloc(sizeof(*cma_heap), GFP_KERNEL); - if (!cma_uncached_heap) { - ret = -ENOMEM; - goto put_cma_heap; - } - - cma_uncached_heap->cma = cma; - - exp_info.name = "cma-uncached"; - exp_info.ops = &cma_uncached_heap_ops; - exp_info.priv = cma_uncached_heap; - - cma_uncached_heap->heap = dma_heap_add(&exp_info); - if (IS_ERR(cma_uncached_heap->heap)) { - ret = PTR_ERR(cma_uncached_heap->heap); - goto free_uncached_cma_heap; - } - - ret = set_heap_dev_dma(dma_heap_get_dev(cma_uncached_heap->heap)); - if (ret) - goto put_uncached_cma_heap; - - mb(); /* make sure we only set allocate after dma_mask is set */ - cma_uncached_heap_ops.allocate = cma_uncached_heap_allocate; - return 0; - -put_uncached_cma_heap: - dma_heap_put(cma_uncached_heap->heap); -free_uncached_cma_heap: - kfree(cma_uncached_heap); -put_cma_heap: - dma_heap_put(cma_heap->heap); -free_cma_heap: - kfree(cma_heap); - - return ret; } static int add_default_cma_heap(void) From cbf9da816c4a2d062c55272de83936e597df31d2 Mon Sep 17 00:00:00 2001 From: Wang Xiaobin Date: Tue, 27 Sep 2022 09:20:02 +0800 Subject: [PATCH 143/204] ARM: dts: rockchip: rv1106g-smart-door: use erofs with dax Signed-off-by: Wang Xiaobin Change-Id: I23a83c0118c3a0d497d2c7a408fd223be422fe09 --- arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v10.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v10.dts b/arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v10.dts index d64f9b7acca1..16b9fb261d17 100644 --- a/arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v10.dts +++ b/arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v10.dts @@ -15,7 +15,7 @@ compatible = "rockchip,rv1106g-smart-door-lock-rmsl-v10", "rockchip,rv1106"; chosen { - bootargs = "loglevel=0 console=ttyFIQ0 root=/dev/rd0 snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0 driver_async_probe=dwmmc_rockchip"; + 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"; }; acodec_sound: acodec-sound { From 4935d15e9b39cb8bbf052cd7da3e238ca5703338 Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Thu, 11 Aug 2022 11:36:57 +0800 Subject: [PATCH 144/204] video: rockchip: mpp: fix dec err issue for rk356x 1. Add need_hack check for rk356x 2. Use cancel_delayed_work replace cancel_delayed_work_sync 3. Remove the operation of resetting rkvdec2 before suspend Signed-off-by: Yandong Lin Change-Id: If826ce65fa1db164a99067bdc9ab5092474a88a3 --- drivers/video/rockchip/mpp/mpp_rkvdec2.c | 9 --------- drivers/video/rockchip/mpp/mpp_rkvdec2_link.c | 19 +++++++++++++++++-- drivers/video/rockchip/mpp/mpp_rkvdec2_link.h | 1 + 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2.c b/drivers/video/rockchip/mpp/mpp_rkvdec2.c index 5c5ca8f38c90..ada9df5961ad 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2.c @@ -1595,17 +1595,8 @@ static int __maybe_unused rkvdec2_runtime_suspend(struct device *dev) mpp_clk_safe_disable(ccu->aclk_info.clk); } else { - u32 val; struct mpp_dev *mpp = dev_get_drvdata(dev); - /* soft reset */ - mpp_write(mpp, RKVDEC_REG_IMPORTANT_BASE, RKVDEC_SOFTREST_EN); - udelay(5); - val = mpp_read(mpp, RKVDEC_REG_INT_EN); - if (!(val & RKVDEC_SOFT_RESET_READY)) - mpp_err("soft reset fail, int %08x\n", val); - mpp_write(mpp, RKVDEC_REG_INT_EN, 0); - if (mpp->is_irq_startup) { /* disable core irq */ disable_irq(mpp->irq); diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c index 0dd7c21d85af..f7418621c683 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c @@ -71,6 +71,7 @@ struct rkvdec_link_info rkvdec_link_v2_hw_info = { .reg_num = 28, }, .tb_reg_int = 180, + .hack_setup = 0, }; /* vdpu34x link hw info for rk356x */ @@ -123,6 +124,7 @@ struct rkvdec_link_info rkvdec_link_rk356x_hw_info = { .reg_num = 28, }, .tb_reg_int = 164, + .hack_setup = 1, }; static void rkvdec_link_status_update(struct rkvdec_link_dev *dev) @@ -601,7 +603,7 @@ static int rkvdec_link_isr_recv_task(struct mpp_dev *mpp, task->irq_status = irq_status ? irq_status : mpp->irq_status; - cancel_delayed_work_sync(&mpp_task->timeout_work); + cancel_delayed_work(&mpp_task->timeout_work); set_bit(TASK_STATE_HANDLE, &mpp_task->state); if (link_dec->statistic_count && @@ -768,7 +770,7 @@ static int rkvdec2_link_isr(struct mpp_dev *mpp) rkvdec_link_reg_dump("timeout", link_dec); val = mpp_read(mpp, 224 * 4); - if (!(val & BIT(2))) { + if (link_dec->info->hack_setup && !(val & BIT(2))) { dev_info(mpp->dev, "frame not complete\n"); link_dec->decoded++; } @@ -955,6 +957,9 @@ int rkvdec2_link_init(struct platform_device *pdev, struct rkvdec2_dev *dec) if (ret) goto done; + if (dec->fix) + rkvdec2_link_hack_data_setup(dec->fix); + link_dec->mpp = mpp; link_dec->dev = dev; atomic_set(&link_dec->task_timeout, 0); @@ -1282,6 +1287,7 @@ int rkvdec2_link_process_task(struct mpp_session *session, { struct mpp_task *task = NULL; struct mpp_dev *mpp = session->mpp; + struct rkvdec_link_info *link_info = mpp->var->hw_info->link_info; task = rkvdec2_alloc_task(session, msgs); if (!task) { @@ -1289,6 +1295,15 @@ int rkvdec2_link_process_task(struct mpp_session *session, return -ENOMEM; } + if (link_info->hack_setup) { + u32 fmt; + struct rkvdec2_task *dec_task = NULL; + + dec_task = to_rkvdec2_task(task); + fmt = RKVDEC_GET_FORMAT(dec_task->reg[RKVDEC_REG_FORMAT_INDEX]); + dec_task->need_hack = (fmt == RKVDEC_FMT_H264D); + } + kref_init(&task->ref); atomic_set(&task->abort_request, 0); task->task_index = atomic_fetch_inc(&mpp->task_index); diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.h b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.h index 208789c7c36b..635516ae3262 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.h +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.h @@ -112,6 +112,7 @@ struct rkvdec_link_info { /* interrupt read back in table buffer */ u32 tb_reg_int; + bool hack_setup; }; struct rkvdec_link_dev { From 13f3f5405629e9c1d5b9cc816ad5a558a6cc7775 Mon Sep 17 00:00:00 2001 From: Sach Lin Date: Thu, 15 Sep 2022 16:02:13 +0800 Subject: [PATCH 145/204] ARM: configs: rv1106-smart-door: enable CONFIG_EEPROM_AT24 Signed-off-by: Sach Lin Change-Id: I5f1300451d10b821775427ad519eb3739f896a1e --- arch/arm/configs/rv1106-smart-door.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/rv1106-smart-door.config b/arch/arm/configs/rv1106-smart-door.config index 6b367836a6d4..5cdd669122f2 100644 --- a/arch/arm/configs/rv1106-smart-door.config +++ b/arch/arm/configs/rv1106-smart-door.config @@ -1,8 +1,10 @@ CONFIG_CONFIGFS_FS=m CONFIG_CRYPTO=y +CONFIG_EEPROM_AT24=y CONFIG_EXTCON=m CONFIG_JFFS2_FS=y CONFIG_KEYS=y +CONFIG_NVMEM_SYSFS=y CONFIG_RFKILL=y CONFIG_RK803=y CONFIG_ROCKCHIP_HW_DECOMPRESS_USER=y From 46af2a4fc8e101fd83b5acda031b9e6c42f95ad9 Mon Sep 17 00:00:00 2001 From: Sach Lin Date: Thu, 15 Sep 2022 16:03:36 +0800 Subject: [PATCH 146/204] ARM: dts: rockchip: rv1106-smd-cam: add gt24c512 Signed-off-by: Sach Lin Change-Id: I1d298fa02c42e9a2b0cfa120a4a569ed21ee4d02 --- arch/arm/boot/dts/rv1106-smd-cam.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/rv1106-smd-cam.dtsi b/arch/arm/boot/dts/rv1106-smd-cam.dtsi index 03bff39c00f4..7238b22f6a05 100644 --- a/arch/arm/boot/dts/rv1106-smd-cam.dtsi +++ b/arch/arm/boot/dts/rv1106-smd-cam.dtsi @@ -132,6 +132,11 @@ }; }; + gt24c512: gt24c512@50 { + compatible = "atmel,24c512"; + reg = <0x50>; + }; + vcsel_rk803: vcsel_rk803@63 { compatible = "rockchip,rk803"; status = "okay"; From 45b3d59d138e0fbf9be1946122f6b653d42d210a Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Wed, 24 Jun 2020 14:12:46 +0800 Subject: [PATCH 147/204] mm: cma: add CmaAllocated/CmaReleased info for meminfo node Show the CMA pages used by cma_alloc in meminfo node. Tested on RV1126 EVB DDR3: CmaTotal: 270336 kB CmaAllocated: 44408 kB CmaReleased: 225928 kB CmaFree: 0 kB The CmaTotal = CmaAllocated + CmaReleased, and the CmaFree is pages under cma area unused by system. The CmaAllocated can be calculated by CMA_DEBUGFS. Tested on RV1126 EVB DDR3: cat /sys/kernel/debug/cma/*/used 10756 346 The results from cma used is in page count, 1 page = 4kByte CmaAllocated = 44408kB = 10756 + 346 pages Change-Id: Ib79001367562c968e6432816b158cba551978173 Signed-off-by: Jianqun Xu --- fs/proc/meminfo.c | 4 ++++ include/linux/cma.h | 4 +++- mm/cma.c | 20 ++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index 208c9c4a83d7..d6303964a274 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -142,6 +142,10 @@ static int meminfo_proc_show(struct seq_file *m, void *v) #ifdef CONFIG_CMA show_val_kb(m, "CmaTotal: ", totalcma_pages); +#ifdef CONFIG_NO_GKI + show_val_kb(m, "CmaAllocated: ", cma_used_pages()); + show_val_kb(m, "CmaReleased: ", totalcma_pages - cma_used_pages()); +#endif show_val_kb(m, "CmaFree: ", global_zone_page_state(NR_FREE_CMA_PAGES)); #endif diff --git a/include/linux/cma.h b/include/linux/cma.h index 4f29ac17067d..a60e6745bcaa 100644 --- a/include/linux/cma.h +++ b/include/linux/cma.h @@ -56,6 +56,8 @@ extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size, extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align, gfp_t gfp_mask); extern bool cma_release(struct cma *cma, const struct page *pages, unsigned int count); - +#ifdef CONFIG_NO_GKI +extern unsigned long cma_used_pages(void); +#endif extern int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data); #endif diff --git a/mm/cma.c b/mm/cma.c index ce3531d355a5..2e82b2758a64 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -642,6 +642,26 @@ bool cma_release(struct cma *cma, const struct page *pages, unsigned int count) } EXPORT_SYMBOL_GPL(cma_release); +#ifdef CONFIG_NO_GKI +unsigned long cma_used_pages(void) +{ + struct cma *cma; + unsigned long used; + unsigned long val = 0; + int i; + + for (i = 0; i < cma_area_count; i++) { + cma = &cma_areas[i]; + mutex_lock(&cma->lock); + used = bitmap_weight(cma->bitmap, (int)cma_bitmap_maxno(cma)); + mutex_unlock(&cma->lock); + val += used << cma->order_per_bit; + } + return val; +} +EXPORT_SYMBOL_GPL(cma_used_pages); +#endif + int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data) { int i; From 247fa56c8dbc421ef2a1d0d241cfa420cac7b733 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Tue, 13 Sep 2022 11:00:10 +0800 Subject: [PATCH 148/204] drm/rockchip: vop2: Fix the pixel/yrgb_mst/uv_mst alignments of NV15/NV12 at splice mode The mst of yrgb/uv must start at a byte aligned address with a full group of pixel. For a pixel with NV15 format, the y channel has 10 bits and uv channel has 5 bits. So limit the alignment to 8 pixel(10 bytes for Y, and 5 bytes for UV) to meet this requirement. For a pixel with NV12 format, we should limit the alignment to 2 pixel. Change-Id: I23eccca6d706d3da25d2deac29e5a862e4bf355d Signed-off-by: Andy Yan --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index b02b2cce89e9..6fdd71acfdfe 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -4344,6 +4344,8 @@ static void vop2_calc_drm_rect_for_splice(struct vop2_plane_state *vpstate, int dst_w = drm_rect_width(dst); int src_w = drm_rect_width(src) >> 16; int left_src_w, left_dst_w, right_dst_w; + struct drm_plane_state *pstate = &vpstate->base; + struct drm_framebuffer *fb = pstate->fb; left_dst_w = min_t(u16, half_hdisplay, dst->x2) - dst->x1; if (left_dst_w < 0) @@ -4354,6 +4356,17 @@ static void vop2_calc_drm_rect_for_splice(struct vop2_plane_state *vpstate, left_src_w = src_w; else left_src_w = (left_dst_w * hscale) >> 16; + + /* + * Make sure the yrgb/uv mst of right win are byte aligned + * with full pixel. + */ + if (right_dst_w) { + if (fb->format->format == DRM_FORMAT_NV15) + left_src_w &= ~0x7; + else if (fb->format->format == DRM_FORMAT_NV12) + left_src_w &= ~0x1; + } left_src->x1 = src->x1; left_src->x2 = src->x1 + (left_src_w << 16); left_dst->x1 = dst->x1; @@ -4361,6 +4374,9 @@ static void vop2_calc_drm_rect_for_splice(struct vop2_plane_state *vpstate, right_src->x1 = left_src->x2; right_src->x2 = src->x2; right_dst->x1 = dst->x1 + left_dst_w - half_hdisplay; + if (right_dst->x1 < 0) + right_dst->x1 = 0; + right_dst->x2 = right_dst->x1 + right_dst_w; left_src->y1 = src->y1; From 797ce37d8cc1727d627b0bf5fd7882133a85e96a Mon Sep 17 00:00:00 2001 From: Dingxian Wen Date: Sat, 24 Sep 2022 18:06:22 +0800 Subject: [PATCH 149/204] media: rockchip: hdmirx: enhance the stability of reading resolution sometimes the signal is locked, but the resolution is not stable. Signed-off-by: Dingxian Wen Change-Id: I4088690c58159dbdc6a36a1f3fe1db4dada4bfbb --- .../media/platform/rockchip/hdmirx/rk_hdmirx.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index 1579bcdf8e38..5148727c52a2 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -881,11 +881,21 @@ static int hdmirx_try_to_get_timings(struct rk_hdmirx_dev *hdmirx_dev, int i, cnt = 0, fail_cnt = 0, ret = 0; bool from_dma = false; struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; + u32 last_w, last_h; + struct v4l2_bt_timings *bt = &timings->bt; + last_w = 0; + last_h = 0; hdmirx_set_negative_pol(hdmirx_dev, false); for (i = 0; i < try_cnt; i++) { ret = hdmirx_get_detected_timings(hdmirx_dev, timings, from_dma); - if (ret) { + + if ((last_w == 0) && (last_h == 0)) { + last_w = bt->width; + last_h = bt->height; + } + + if (ret || (last_w != bt->width) || (last_h != bt->height)) { cnt = 0; fail_cnt++; if (fail_cnt > 3) { @@ -896,9 +906,11 @@ static int hdmirx_try_to_get_timings(struct rk_hdmirx_dev *hdmirx_dev, cnt++; } - if (cnt >= 5) + if (cnt >= 8) break; + last_w = bt->width; + last_h = bt->height; usleep_range(10*1000, 10*1100); } From f537dfe3835b334509039a7cb1d89ba2739fdec2 Mon Sep 17 00:00:00 2001 From: William Wu Date: Tue, 27 Sep 2022 21:13:35 +0800 Subject: [PATCH 150/204] USB: quirks: add quirk auto suspend for Sonix webcam The Sonix webcam (idVendor=0x0c45,idProduct=0x636a) can't support auto-suspend well on rockchip platforms. With auto-suspend, the usb mic of the webcam fail to start capture. So we need to disable auto-suspend for this Sonix webcam. Signed-off-by: William Wu Change-Id: Icc59c4fe1fda78be73441dc4320d6d738d031efd --- drivers/usb/core/quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 5acf9fa3d446..ad57ebf49154 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -416,6 +416,7 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0bda, 0x8153), .driver_info = USB_QUIRK_NO_LPM }, /* Sonix FaceBlack device */ + { USB_DEVICE(0x0c45, 0x636a), .driver_info = USB_QUIRK_AUTO_SUSPEND }, { USB_DEVICE(0x0c45, 0x64ab), .driver_info = USB_QUIRK_AUTO_SUSPEND }, { USB_DEVICE(0x0c45, 0x64ac), .driver_info = USB_QUIRK_AUTO_SUSPEND }, From bc8ef86861382473416451e42a5095ea64cfd44b Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Wed, 27 Nov 2019 09:06:46 +0800 Subject: [PATCH 151/204] mm/page_isolation.c: dump page owner if fail to isolate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CMA alloc may failure due to page busy caused by isolated failure, it's helpful to dump page owner stack for debug. To use this debug, there should enable PAGE_OWNER debug first by - CONFIG_PAGE_OWNER=y - add “page_owner=on” to boot cmdline then it will shows as following: page allocated via order 0, migratetype Movable, gfp_mask 0x6212ca(GFP_HIGHUSER_MOVABLE|__GFP_NOWARN|__GFP_NORETRY) get_page_from_freelist+0x1404/0x1920 __alloc_pages_nodemask+0xf4/0xe90 __do_page_cache_readahead+0x104/0x1f0 filemap_fault+0x3d4/0x618 ext4_filemap_fault+0x30/0x50 __do_fault+0x50/0x118 __handle_mm_fault+0x7e4/0xb40 handle_mm_fault+0xcc/0x1a0 do_page_fault+0x1f0/0x4a8 do_translation_fault+0x5c/0x64 do_mem_abort+0x54/0xf8 el0_da+0x1c/0x20 Change-Id: I94b02a7c4ce9174f8151e0979e18adba4011c1d2 Signed-off-by: Jianqun Xu --- mm/page_isolation.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mm/page_isolation.c b/mm/page_isolation.c index b391091bfd5c..48ff14250004 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c @@ -279,6 +279,10 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn, else break; } +#ifdef CONFIG_NO_GKI + if (pfn < end_pfn) + dump_page_owner(page); +#endif return pfn; } From f3fe5ad04b2ac54658fa9933b8e31bca5591b5ef Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Tue, 20 Sep 2022 15:37:04 +0800 Subject: [PATCH 152/204] ASoC: rockchip: i2s-tdm: Workaround for Skyworth 8K TVs' Playback Bring back CLK ASAP after cfg changed to make SINK devices active on HDMI-PATH-ALWAYS-ON situation, this workaround for some TVs no sound issue. at the moment, it's 8K@60Hz display situation. On HDMI-PATH-ALWAYS-ON situation, we almost keep XFER always on, so, for new data start, suggested to STOP-CLEAR-START to make sure data aligned. Signed-off-by: Sugar Zhang Change-Id: I56f97d7246cf790ea33a7410eff418baeeecc6d0 --- sound/soc/rockchip/rockchip_i2s_tdm.c | 32 ++++++++++++++++++--------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index 20c8a4e9c3bc..19691b6d5a39 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -591,6 +591,17 @@ static void rockchip_i2s_tdm_trcm_resume(struct snd_pcm_substream *substream, static void rockchip_i2s_tdm_start(struct rk_i2s_tdm_dev *i2s_tdm, int stream) { + /* + * On HDMI-PATH-ALWAYS-ON situation, we almost keep XFER always on, + * so, for new data start, suggested to STOP-CLEAR-START to make sure + * data aligned. + */ + if ((i2s_tdm->quirks & QUIRK_HDMI_PATH) && + (i2s_tdm->quirks & QUIRK_ALWAYS_ON) && + (stream == SNDRV_PCM_STREAM_PLAYBACK)) { + rockchip_i2s_tdm_xfer_stop(i2s_tdm, stream, true); + } + rockchip_i2s_tdm_dma_ctrl(i2s_tdm, stream, 1); if (i2s_tdm->clk_trcm) @@ -1127,6 +1138,17 @@ static int rockchip_i2s_tdm_params(struct snd_pcm_substream *substream, fmt); } + /* + * Bring back CLK ASAP after cfg changed to make SINK devices active + * on HDMI-PATH-ALWAYS-ON situation, this workaround for some TVs no + * sound issue. at the moment, it's 8K@60Hz display situation. + */ + if ((i2s_tdm->quirks & QUIRK_HDMI_PATH) && + (i2s_tdm->quirks & QUIRK_ALWAYS_ON) && + (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) { + rockchip_i2s_tdm_xfer_start(i2s_tdm, SNDRV_PCM_STREAM_PLAYBACK); + } + return 0; } @@ -1498,16 +1520,6 @@ static int rockchip_i2s_tdm_startup(struct snd_pcm_substream *substream, i2s_tdm->substreams[substream->stream] = substream; - /* - * Suggested to stop audio source before HDMI configure to make - * sure audio data integrity on HDMI-PATH-ALWAYS-ON situation. - */ - if ((i2s_tdm->quirks & QUIRK_HDMI_PATH) && - (i2s_tdm->quirks & QUIRK_ALWAYS_ON) && - (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) { - rockchip_i2s_tdm_xfer_stop(i2s_tdm, substream->stream, true); - } - return 0; } From 112acab47d561ee7d135ee0516623802bd0a74ca Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Tue, 9 Aug 2022 10:27:33 +0800 Subject: [PATCH 153/204] ASoC: dmaengine: Fix NULL pointer reference Unable to handle kernel NULL pointer dereference at virtual address 0000000000000080 Internal error: Oops: 96000005 [#1] PREEMPT SMP Modules linked in: bcmdhd dhd_static_buf r8168 CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.10.110 #470 Hardware name: Rockchip RK3588 EVB1 LP4 V10 Board (DT) pstate: 20400009 (nzCv daif +PAN -UAO -TCO BTYPE=--) pc : dmaengine_pcm_dma_complete+0x44/0xdc lr : pl330_tasklet+0xd4/0x2d0 sp : ffffffc01249bdf0 x29: ffffffc01249bdf0 x28: 0000000000000000 x27: ffffff8102c8c608 x26: 0000000000000002 x25: ffffff8102c8c608 x24: ffffff8102d4c600 x23: ffffff81018868c0 x22: ffffff8102c8c618 x21: 0000000000000000 x20: ffffffc010f238ec x19: ffffff8102c8c560 x18: ffffffc012491048 x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 x14: 000000000007fcc4 x13: 0000000000000004 x12: 0000000a7e22d2ff x11: 0000000000004007 x10: 0000000000000000 x9 : 0000000000003000 x8 : ffffff8030b7d480 x7 : 000000b2b5593519 x6 : 00000000003033ff x5 : 0000000000000000 x4 : 0000000000bb82b6 x3 : ffffff8102c90b28 x2 : 0000000000000001 x1 : 0000000000000000 x0 : ffffff8102d4c600 Call trace: dmaengine_pcm_dma_complete+0x44/0xdc pl330_tasklet+0xd4/0x2d0 tasklet_action_common+0x11c/0x414 tasklet_action+0x28/0x38 _stext+0x108/0x408 __irq_exit_rcu+0xc0/0xc4 irq_exit+0x14/0x28 __handle_domain_irq+0x84/0xd0 gic_handle_irq+0x78/0x154 el1_irq+0xe4/0x1c0 cpuidle_enter_state+0x200/0x3b8 cpuidle_enter+0x3c/0x58 cpuidle_idle_call+0x158/0x238 do_idle+0xac/0xfc cpu_startup_entry+0x28/0x2c rest_init+0xd8/0xec arch_call_rest_init+0x14/0x24 start_kernel+0x3d8/0x500 Signed-off-by: Sugar Zhang Change-Id: Ib3d3ac842d3cd249c8cc6f516178031400dbc307 --- sound/core/pcm_dmaengine.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index c9314c9e87f1..c54dce1e6aef 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -18,6 +18,7 @@ #include #include +#include "pcm_local.h" struct dmaengine_pcm_runtime_data { struct dma_chan *dma_chan; @@ -133,11 +134,20 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); static void dmaengine_pcm_dma_complete(void *arg) { struct snd_pcm_substream *substream = arg; - struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + struct dmaengine_pcm_runtime_data *prtd; + + snd_pcm_stream_lock_irq(substream); + if (PCM_RUNTIME_CHECK(substream)) { + snd_pcm_stream_unlock_irq(substream); + return; + } + + prtd = substream_to_prtd(substream); prtd->pos += snd_pcm_lib_period_bytes(substream); if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) prtd->pos = 0; + snd_pcm_stream_unlock_irq(substream); snd_pcm_period_elapsed(substream); } From 217d03411df5197d7bf9f7ff0c60b2cedba53d33 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Thu, 22 Sep 2022 20:59:20 +0800 Subject: [PATCH 154/204] power: reset: reboot-mode: Don't miss panic reboot mode pre_restart will rewrite reboot mode with normal mode when panic. Fixes: c0b196cd5b85 ("power: reset: reboot-mode: Register callback for kernel pre restart") Signed-off-by: Tao Huang Change-Id: I8ad03b8f699b9c1a544a46bbdb60d118381d8356 --- drivers/power/reset/reboot-mode.c | 21 +++++++++++++++++++-- include/linux/reboot-mode.h | 1 + 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index feaaa80caa9f..b0bb534f241e 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c @@ -51,6 +51,8 @@ static int get_reboot_mode_magic(struct reboot_mode_driver *reboot, return magic; } +static int last_magic; + static void reboot_mode_write(struct reboot_mode_driver *reboot, const void *cmd) { @@ -59,8 +61,10 @@ static void reboot_mode_write(struct reboot_mode_driver *reboot, magic = get_reboot_mode_magic(reboot, cmd); if (!magic) magic = get_reboot_mode_magic(reboot, NULL); - if (magic) + if (magic) { reboot->write(reboot, magic); + last_magic = magic; + } } static int reboot_mode_notify(struct notifier_block *this, @@ -74,6 +78,18 @@ static int reboot_mode_notify(struct notifier_block *this, return NOTIFY_DONE; } +static int reboot_mode_pre_restart_notify(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + struct reboot_mode_driver *reboot; + + reboot = container_of(this, struct reboot_mode_driver, pre_restart_notifier); + if (cmd || !last_magic) + reboot_mode_write(reboot, cmd); + + return NOTIFY_DONE; +} + static int reboot_mode_panic_notify(struct notifier_block *this, unsigned long ev, void *ptr) { @@ -151,9 +167,10 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) boot_mode_parse(reboot); reboot->reboot_notifier.notifier_call = reboot_mode_notify; + reboot->pre_restart_notifier.notifier_call = reboot_mode_pre_restart_notify; reboot->panic_notifier.notifier_call = reboot_mode_panic_notify; register_reboot_notifier(&reboot->reboot_notifier); - register_pre_restart_handler(&reboot->reboot_notifier); + register_pre_restart_handler(&reboot->pre_restart_notifier); atomic_notifier_chain_register(&panic_notifier_list, &reboot->panic_notifier); ret = sysfs_create_file(kernel_kobj, &kobj_boot_mode.attr); diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index a7aa69d004c4..250147abb6f3 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -8,6 +8,7 @@ struct reboot_mode_driver { int (*write)(struct reboot_mode_driver *reboot, unsigned int magic); int (*read)(struct reboot_mode_driver *reboot); struct notifier_block reboot_notifier; + struct notifier_block pre_restart_notifier; struct notifier_block panic_notifier; }; From cf0e68c8b47c91b030bb588ff77874046ee12c7c Mon Sep 17 00:00:00 2001 From: Shaohan Yao Date: Mon, 19 Sep 2022 10:27:18 +0800 Subject: [PATCH 155/204] soc: rockchip: rockchip_system_monitor: Add temperature notifier Signed-off-by: Shaohan Yao Signed-off-by: Finley Xiao Change-Id: I8152d13f09f9e4f38a1d402ca32ae1e7f4a8585c --- .../soc/rockchip/rockchip_system_monitor.c | 37 +++++++++++++++++-- .../soc/rockchip/rockchip_system_monitor.h | 24 ++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/drivers/soc/rockchip/rockchip_system_monitor.c b/drivers/soc/rockchip/rockchip_system_monitor.c index c2dd057a5f3e..4f3f46364355 100644 --- a/drivers/soc/rockchip/rockchip_system_monitor.c +++ b/drivers/soc/rockchip/rockchip_system_monitor.c @@ -71,6 +71,7 @@ struct system_monitor { struct thermal_zone_device *tz; struct delayed_work thermal_work; + int last_temp; int offline_cpus_temp; int temp_hysteresis; unsigned int delay; @@ -91,6 +92,7 @@ static LIST_HEAD(monitor_dev_list); static struct system_monitor *system_monitor; static atomic_t monitor_in_suspend; +static BLOCKING_NOTIFIER_HEAD(system_monitor_notifier_list); static BLOCKING_NOTIFIER_HEAD(system_status_notifier_list); int rockchip_register_system_status_notifier(struct notifier_block *nb) @@ -1448,6 +1450,31 @@ void rockchip_system_monitor_unregister(struct monitor_dev_info *info) } EXPORT_SYMBOL(rockchip_system_monitor_unregister); +int rockchip_system_monitor_register_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&system_monitor_notifier_list, nb); +} +EXPORT_SYMBOL(rockchip_system_monitor_register_notifier); + +void rockchip_system_monitor_unregister_notifier(struct notifier_block *nb) +{ + blocking_notifier_chain_unregister(&system_monitor_notifier_list, nb); +} +EXPORT_SYMBOL(rockchip_system_monitor_unregister_notifier); + +static int rockchip_system_monitor_temp_notify(int temp) +{ + struct system_monitor_event_data event_data; + int ret; + + event_data.temp = temp; + ret = blocking_notifier_call_chain(&system_monitor_notifier_list, + SYSTEM_MONITOR_CHANGE_TEMP, + (void *)&event_data); + + return notifier_to_errno(ret); +} + static int notify_dummy(struct thermal_zone_device *tz, int trip) { return 0; @@ -1564,7 +1591,6 @@ static void rockchip_system_monitor_thermal_update(void) { int temp, ret; struct monitor_dev_info *info; - static int last_temp = INT_MAX; ret = thermal_zone_get_temp(system_monitor->tz, &temp); if (ret || temp == THERMAL_TEMP_INVALID) @@ -1572,9 +1598,12 @@ static void rockchip_system_monitor_thermal_update(void) dev_dbg(system_monitor->dev, "temperature=%d\n", temp); - if (temp < last_temp && last_temp - temp <= 2000) + if (temp < system_monitor->last_temp && + system_monitor->last_temp - temp <= 2000) goto out; - last_temp = temp; + system_monitor->last_temp = temp; + + rockchip_system_monitor_temp_notify(temp); down_read(&mdev_list_sem); list_for_each_entry(info, &monitor_dev_list, node) @@ -1700,6 +1729,7 @@ static int monitor_pm_notify(struct notifier_block *nb, rockchip_system_monitor_thermal_update(); atomic_set(&monitor_in_suspend, 0); rockchip_system_monitor_set_cpu_uevent_suppress(false); + system_monitor->last_temp = INT_MAX; break; default: break; @@ -1819,6 +1849,7 @@ static int rockchip_system_monitor_probe(struct platform_device *pdev) rockchip_system_monitor_parse_dt(system_monitor); if (system_monitor->tz) { + system_monitor->last_temp = INT_MAX; INIT_DELAYED_WORK(&system_monitor->thermal_work, rockchip_system_monitor_thermal_check); mod_delayed_work(system_freezable_wq, diff --git a/include/soc/rockchip/rockchip_system_monitor.h b/include/soc/rockchip/rockchip_system_monitor.h index a8f500651165..e6698c054c0d 100644 --- a/include/soc/rockchip/rockchip_system_monitor.h +++ b/include/soc/rockchip/rockchip_system_monitor.h @@ -6,11 +6,23 @@ #ifndef __SOC_ROCKCHIP_SYSTEM_MONITOR_H #define __SOC_ROCKCHIP_SYSTEM_MONITOR_H +#include +#include +#include + enum monitor_dev_type { MONITOR_TPYE_CPU = 0, /* CPU */ MONITOR_TPYE_DEV, /* GPU, NPU, DMC, and so on */ }; +enum system_monitor_event_type { + SYSTEM_MONITOR_CHANGE_TEMP = 0, +}; + +struct system_monitor_event_data { + int temp; +}; + struct volt_adjust_table { unsigned int min; /* Minimum frequency in MHz */ unsigned int max; /* Maximum frequency in MHz */ @@ -148,6 +160,8 @@ int rockchip_monitor_dev_low_temp_adjust(struct monitor_dev_info *info, int rockchip_monitor_dev_high_temp_adjust(struct monitor_dev_info *info, bool is_high); int rockchip_monitor_suspend_low_temp_adjust(int cpu); +int rockchip_system_monitor_register_notifier(struct notifier_block *nb); +void rockchip_system_monitor_unregister_notifier(struct notifier_block *nb); #else static inline struct monitor_dev_info * rockchip_system_monitor_register(struct device *dev, @@ -208,6 +222,16 @@ static inline int rockchip_monitor_suspend_low_temp_adjust(int cpu) return 0; }; +static inline int +rockchip_system_monitor_register_notifier(struct notifier_block *nb) +{ + return 0; +}; + +static inline void +rockchip_system_monitor_unregister_notifier(struct notifier_block *nb) +{ +}; #endif /* CONFIG_ROCKCHIP_SYSTEM_MONITOR */ #endif From 4f1d178da1985c2ca4541ae94096297020ef5ec6 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Thu, 29 Sep 2022 10:02:27 +0800 Subject: [PATCH 156/204] soc: rockchip: rockchip_system_monitor: use IS_REACHABLE instead of IS_ENABLED Signed-off-by: Tao Huang Change-Id: I1726278ab44f17bb204d0c57758952f5f3896d76 --- include/soc/rockchip/rockchip-system-status.h | 2 +- include/soc/rockchip/rockchip_system_monitor.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/soc/rockchip/rockchip-system-status.h b/include/soc/rockchip/rockchip-system-status.h index 200b1ee89602..e04921240450 100644 --- a/include/soc/rockchip/rockchip-system-status.h +++ b/include/soc/rockchip/rockchip-system-status.h @@ -6,7 +6,7 @@ #ifndef __SOC_ROCKCHIP_SYSTEM_STATUS_H #define __SOC_ROCKCHIP_SYSTEM_STATUS_H -#if IS_ENABLED(CONFIG_ROCKCHIP_SYSTEM_MONITOR) +#if IS_REACHABLE(CONFIG_ROCKCHIP_SYSTEM_MONITOR) int rockchip_register_system_status_notifier(struct notifier_block *nb); int rockchip_unregister_system_status_notifier(struct notifier_block *nb); void rockchip_set_system_status(unsigned long status); diff --git a/include/soc/rockchip/rockchip_system_monitor.h b/include/soc/rockchip/rockchip_system_monitor.h index e6698c054c0d..8613838416ea 100644 --- a/include/soc/rockchip/rockchip_system_monitor.h +++ b/include/soc/rockchip/rockchip_system_monitor.h @@ -143,7 +143,7 @@ struct monitor_dev_profile { struct rockchip_opp_info *opp_info; }; -#if IS_ENABLED(CONFIG_ROCKCHIP_SYSTEM_MONITOR) +#if IS_REACHABLE(CONFIG_ROCKCHIP_SYSTEM_MONITOR) struct monitor_dev_info * rockchip_system_monitor_register(struct device *dev, struct monitor_dev_profile *devp); From ab64dbf5f0965a425f9ae1ae3929f261f21990da Mon Sep 17 00:00:00 2001 From: Shaohan Yao Date: Mon, 19 Sep 2022 10:28:12 +0800 Subject: [PATCH 157/204] hwmon: (pwm-fan) Add system monitor notifier Add support to change fan speed according to temperature, and force to update pwm state when suspend and resume as the configuration of pwm is lost. Signed-off-by: Shaohan Yao Signed-off-by: Finley Xiao Change-Id: I05b286d1373dd4ace2fb519f4598008b851e4eff --- .../devicetree/bindings/hwmon/pwm-fan.txt | 5 + drivers/hwmon/pwm-fan.c | 110 +++++++++++++++++- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/hwmon/pwm-fan.txt b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt index 41b76762953a..457ce1663d6a 100644 --- a/Documentation/devicetree/bindings/hwmon/pwm-fan.txt +++ b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt @@ -17,6 +17,11 @@ Optional properties: - pulses-per-revolution : define the tachometer pulses per fan revolution as an integer (default is 2 interrupts per revolution). The value must be greater than zero. +- rockchip,temp-trips : The property is an array of 2-tuples items, and + each item consists of temperature in millicelsius and + pwm cooling state. This depends on CONFIG_ROCKCHIP_SYSTEM_MONITOR. + If add the property the fan cooling state will be changed + by system monitor. Otherwise, use the default thermal governor. Example: fan0: pwm-fan { diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c index ec171f2b684a..6298da53ef14 100644 --- a/drivers/hwmon/pwm-fan.c +++ b/drivers/hwmon/pwm-fan.c @@ -19,9 +19,15 @@ #include #include #include +#include #define MAX_PWM 255 +struct thermal_trips { + int temp; + int state; +}; + struct pwm_fan_ctx { struct mutex lock; struct pwm_device *pwm; @@ -39,6 +45,9 @@ struct pwm_fan_ctx { unsigned int pwm_fan_max_state; unsigned int *pwm_fan_cooling_levels; struct thermal_cooling_device *cdev; + struct notifier_block thermal_nb; + struct thermal_trips *thermal_trips; + bool thermal_notifier_is_ok; }; /* This handler assumes self resetting edge triggered interrupt. */ @@ -278,6 +287,94 @@ static void pwm_fan_pwm_disable(void *__ctx) del_timer_sync(&ctx->rpm_timer); } +static int pwm_fan_get_thermal_trips(struct device *dev, char *porp_name, + struct thermal_trips **trips) +{ + struct device_node *np = dev->of_node; + struct thermal_trips *thermal_trips; + const struct property *prop; + int count, i; + + prop = of_find_property(np, porp_name, NULL); + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + count = of_property_count_u32_elems(np, porp_name); + if (count < 0) + return -EINVAL; + if (count % 2) + return -EINVAL; + thermal_trips = devm_kzalloc(dev, + sizeof(*thermal_trips) * (count / 2 + 1), + GFP_KERNEL); + if (!thermal_trips) + return -ENOMEM; + + for (i = 0; i < count / 2; i++) { + of_property_read_u32_index(np, porp_name, 2 * i, + &thermal_trips[i].temp); + of_property_read_u32_index(np, porp_name, 2 * i + 1, + &thermal_trips[i].state); + } + thermal_trips[i].temp = 0; + thermal_trips[i].state = INT_MAX; + + *trips = thermal_trips; + + return 0; +} + +static int pwm_fan_temp_to_state(struct pwm_fan_ctx *ctx, int temp) +{ + struct thermal_trips *trips = ctx->thermal_trips; + int i, state = 0; + + for (i = 0; trips[i].state != INT_MAX; i++) { + if (temp >= trips[i].temp) + state = trips[i].state; + } + + return state; +} + +static int pwm_fan_thermal_notifier_call(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct pwm_fan_ctx *ctx = container_of(nb, struct pwm_fan_ctx, thermal_nb); + struct system_monitor_event_data *event_data = data; + int state, ret; + + if (event != SYSTEM_MONITOR_CHANGE_TEMP) + return NOTIFY_OK; + + state = pwm_fan_temp_to_state(ctx, event_data->temp); + if (state > ctx->pwm_fan_max_state) + return NOTIFY_BAD; + if (state == ctx->pwm_fan_state) + return NOTIFY_OK; + + ret = __set_pwm(ctx, ctx->pwm_fan_cooling_levels[state]); + if (ret) + return NOTIFY_BAD; + + ctx->pwm_fan_state = state; + + return NOTIFY_OK; +} + +static int pwm_fan_register_thermal_notifier(struct device *dev, + struct pwm_fan_ctx *ctx) +{ + if (pwm_fan_get_thermal_trips(dev, "rockchip,temp-trips", + &ctx->thermal_trips)) + return -EINVAL; + + ctx->thermal_nb.notifier_call = pwm_fan_thermal_notifier_call; + + return rockchip_system_monitor_register_notifier(&ctx->thermal_nb); +} + static int pwm_fan_probe(struct platform_device *pdev) { struct thermal_cooling_device *cdev; @@ -379,6 +476,15 @@ static int pwm_fan_probe(struct platform_device *pdev) return ret; ctx->pwm_fan_state = ctx->pwm_fan_max_state; + if (IS_REACHABLE(CONFIG_ROCKCHIP_SYSTEM_MONITOR) && + of_find_property(dev->of_node, "rockchip,temp-trips", NULL)) { + ret = pwm_fan_register_thermal_notifier(dev, ctx); + if (ret) + dev_err(dev, "Failed to register thermal notifier: %d\n", ret); + else + ctx->thermal_notifier_is_ok = true; + return 0; + } if (IS_ENABLED(CONFIG_THERMAL)) { cdev = devm_thermal_of_cooling_device_register(dev, dev->of_node, "pwm-fan", ctx, &pwm_fan_cooling_ops); @@ -404,7 +510,7 @@ static int pwm_fan_disable(struct device *dev) pwm_get_args(ctx->pwm, &args); - if (ctx->pwm_value) { + if (ctx->pwm_value || ctx->thermal_notifier_is_ok) { ret = pwm_config(ctx->pwm, 0, args.period); if (ret < 0) return ret; @@ -449,7 +555,7 @@ static int pwm_fan_resume(struct device *dev) } } - if (ctx->pwm_value == 0) + if (ctx->pwm_value == 0 && !ctx->thermal_notifier_is_ok) return 0; pwm_get_args(ctx->pwm, &pargs); From b5386fc7679b323057ebe247960cda269c96f792 Mon Sep 17 00:00:00 2001 From: Shaohan Yao Date: Mon, 19 Sep 2022 10:26:26 +0800 Subject: [PATCH 158/204] arm64: dts: rockchip: rk3588-evb: Enable pwm fan Signed-off-by: Shaohan Yao Signed-off-by: Finley Xiao Change-Id: I5413438ed4d94e358c4ad0826371520cf78e037e Signed-off-by: Wu Liangqing --- .../boot/dts/rockchip/rk3588-evb1-lp4.dtsi | 19 +++++++++++++++++++ .../boot/dts/rockchip/rk3588-evb2-lp4.dtsi | 8 ++++++++ .../boot/dts/rockchip/rk3588-evb3-lp5.dtsi | 8 ++++++++ .../boot/dts/rockchip/rk3588-evb4-lp4.dtsi | 8 ++++++++ .../boot/dts/rockchip/rk3588-evb5-lp4.dtsi | 8 ++++++++ .../boot/dts/rockchip/rk3588-evb7-lp4.dtsi | 8 ++++++++ .../boot/dts/rockchip/rk3588-vehicle-evb.dtsi | 8 ++++++++ .../boot/dts/rockchip/rk3588s-evb1-lp4x.dtsi | 8 ++++++++ .../boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi | 8 ++++++++ .../boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi | 8 ++++++++ .../boot/dts/rockchip/rk3588s-evb8-lp4x.dtsi | 8 ++++++++ 11 files changed, 99 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi index f5269776b64e..e41782fa3618 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi @@ -62,6 +62,20 @@ }; }; + fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + pwms = <&pwm9 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; + }; + hdmiin_dc: hdmiin-dc { compatible = "rockchip,dummy-codec"; #sound-dai-cells = <0>; @@ -666,6 +680,11 @@ status = "okay"; }; +&pwm9 { + pinctrl-0 = <&pwm9m1_pins>; + status = "okay"; +}; + &route_dsi0 { status = "okay"; connect = <&vp3_out_dsi0>; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi index 1f2822c781d9..a9962e37122c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi @@ -67,6 +67,14 @@ compatible = "pwm-fan"; #cooling-cells = <2>; pwms = <&pwm9 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; }; pcie20_avdd0v85: pcie20-avdd0v85 { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5.dtsi index 90354594a657..3b08bb998fe9 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5.dtsi @@ -68,6 +68,14 @@ compatible = "pwm-fan"; #cooling-cells = <2>; pwms = <&pwm6 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; }; hall_sensor: hall-mh248 { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi index 4f6e0c422062..05507d4a5dc4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi @@ -14,6 +14,14 @@ compatible = "pwm-fan"; #cooling-cells = <2>; pwms = <&pwm14 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; }; pcie30_avdd1v8: pcie30-avdd1v8 { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb5-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb5-lp4.dtsi index e05e2948d8ab..8e783a98735c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb5-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb5-lp4.dtsi @@ -28,6 +28,14 @@ compatible = "pwm-fan"; #cooling-cells = <2>; pwms = <&pwm9 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; }; hdmiin_dc: hdmiin-dc { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi index 639f23a67369..d08549fa78aa 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi @@ -66,6 +66,14 @@ compatible = "pwm-fan"; #cooling-cells = <2>; pwms = <&pwm3 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; }; hdmiin_dc: hdmiin-dc { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb.dtsi index 9c870a80d8db..7c5bc3ea7e05 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-evb.dtsi @@ -51,6 +51,14 @@ compatible = "pwm-fan"; #cooling-cells = <2>; pwms = <&pwm3 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb1-lp4x.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-evb1-lp4x.dtsi index b7839d4960a6..2396a91d06a1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-evb1-lp4x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb1-lp4x.dtsi @@ -115,6 +115,14 @@ compatible = "pwm-fan"; #cooling-cells = <2>; pwms = <&pwm11 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; }; hall_sensor: hall-mh248 { diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi index ea951d375e11..cf031ef2ec10 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi @@ -34,6 +34,14 @@ compatible = "pwm-fan"; #cooling-cells = <2>; pwms = <&pwm7 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; }; vcc3v3_lcd_n: vcc3v3-lcd0-n { diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi index a79a6220fe87..5862e2fefe82 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi @@ -88,6 +88,14 @@ compatible = "pwm-fan"; #cooling-cells = <2>; pwms = <&pwm11 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; }; vbus5v0_typec: vbus5v0-typec { diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb8-lp4x.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-evb8-lp4x.dtsi index c2cd7f4b7c64..a9e68fe49ee8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-evb8-lp4x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb8-lp4x.dtsi @@ -88,6 +88,14 @@ compatible = "pwm-fan"; #cooling-cells = <2>; pwms = <&pwm11 0 50000 0>; + cooling-levels = <0 50 100 150 200 255>; + rockchip,temp-trips = < + 50000 1 + 55000 2 + 60000 3 + 65000 4 + 70000 5 + >; }; panel-edp { From a927626fae534d28e4524bafc58bd72102c9a73c Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Wed, 28 Sep 2022 19:52:05 +0800 Subject: [PATCH 159/204] drm/rockchip: vop2: Restore lut after VP exit standby vop2_crtc_load_lut need to sync with vysnc, so we should make sure the VP exit standby and setting the right dclk, or we will meet a cfg done timeout: [drm:vop2_wait_for_fs_by_done_bit_status] *ERROR* wait vp1 done bit status timeout, vcnt: 0 Fixes: 5aa1d0e08f49 ("drm/rockchip: vop2: fix double config done at one frame time") Change-Id: I66d1e7ba260dc376c7f7ce132dad2212649b31e8 Signed-off-by: Andy Yan --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 6fdd71acfdfe..863cb206d0a7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -6609,11 +6609,6 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state vcstate->mode_update = vop2_crtc_mode_update(crtc); if (vcstate->mode_update) vop2_disable_all_planes_for_crtc(crtc); - /* - * restore the lut table. - */ - if (vp->gamma_lut_active) - vop2_crtc_load_lut(crtc); dclk_inv = (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; val = (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); @@ -6976,8 +6971,12 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state vop2_clk_reset(vp->dclk_rst); if (vcstate->dsc_enable) rk3588_vop2_dsc_cfg_done(crtc); - drm_crtc_vblank_on(crtc); + /* + * restore the lut table. + */ + if (vp->gamma_lut_active) + vop2_crtc_load_lut(crtc); out: vop2_unlock(vop2); } From b4dff81bd732de02a583af364742977a07ec985b Mon Sep 17 00:00:00 2001 From: Jason Zhu Date: Mon, 26 Sep 2022 20:24:20 +0800 Subject: [PATCH 160/204] ASoC: rockchip: vad: update cpudai process The process is "startup->prepare->trigger". Others, fix the pdm + vad do not work well since use the patch: 'commit 343716232771 ("ASoC: rockchip: pdm: Fix pop noise in the beginning")' Signed-off-by: Jason Zhu Change-Id: Ifdc40af04695f4082d536b83309c76ed0426fece --- sound/soc/rockchip/rockchip_vad.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_vad.c b/sound/soc/rockchip/rockchip_vad.c index d69278aa5317..e37312f80702 100644 --- a/sound/soc/rockchip/rockchip_vad.c +++ b/sound/soc/rockchip/rockchip_vad.c @@ -872,11 +872,20 @@ static int rockchip_vad_enable_cpudai(struct rockchip_vad *vad) return 0; pm_runtime_get_sync(cpu_dai->dev); + if (cpu_dai->driver->ops) { + if (cpu_dai->driver->ops->startup) + ret = cpu_dai->driver->ops->startup(substream, + cpu_dai); - if (cpu_dai->driver->ops && cpu_dai->driver->ops->trigger) - ret = cpu_dai->driver->ops->trigger(substream, - SNDRV_PCM_TRIGGER_START, - cpu_dai); + if (cpu_dai->driver->ops->prepare) + ret |= cpu_dai->driver->ops->prepare(substream, + cpu_dai); + + if (cpu_dai->driver->ops->trigger) + ret |= cpu_dai->driver->ops->trigger(substream, + SNDRV_PCM_TRIGGER_START, + cpu_dai); + } return ret; } From 78b085b196d1fd5b1590c032203d81dbca3dfadc Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Thu, 29 Sep 2022 14:40:21 +0800 Subject: [PATCH 161/204] video: rockchip: rga3: rga_image_size_cal supports YUV422 10bit Signed-off-by: Yu Qiaowei Change-Id: I042a85cc427df7ccd9473c3b49f9d2294160fe67 --- drivers/video/rockchip/rga3/rga_common.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/rockchip/rga3/rga_common.c b/drivers/video/rockchip/rga3/rga_common.c index a96e9fba0f7c..0e21326c4cda 100644 --- a/drivers/video/rockchip/rga3/rga_common.c +++ b/drivers/video/rockchip/rga3/rga_common.c @@ -619,6 +619,9 @@ int rga_image_size_cal(int w, int h, int format, /* YUV FORMAT */ case RGA_FORMAT_YCbCr_422_SP: case RGA_FORMAT_YCrCb_422_SP: + /* 10bit format stride is externally configured. */ + case RGA_FORMAT_YCbCr_422_SP_10B: + case RGA_FORMAT_YCrCb_422_SP_10B: yrgb = w * h; uv = w * h; break; From 6feda272d380ec5ff660351ee02736a0b1a0b283 Mon Sep 17 00:00:00 2001 From: Wangqiang Guo Date: Sat, 17 Sep 2022 03:21:50 +0000 Subject: [PATCH 162/204] media: rockchip: hdmirx: fix some source ced err. The boundary of different frequency points is set as the default value to avoid CED interruption being triggered by mistake. Signed-off-by: Wangqiang Guo Change-Id: I0b1257586d43e335496e87803628da72bc2a7c0c --- .../media/platform/rockchip/hdmirx/rk_hdmirx.c | 16 ++++++++++++++++ .../media/platform/rockchip/hdmirx/rk_hdmirx.h | 10 ++++++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index 5148727c52a2..18b06d4dcb03 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -1338,6 +1338,22 @@ static void hdmirx_phy_config(struct rk_hdmirx_dev *hdmirx_dev) hdmirx_phy_register_write(hdmirx_dev, SUP_DIG_ANA_CREGS_SUP_ANA_NC, 0); hdmirx_phy_register_write(hdmirx_dev, SUP_DIG_ANA_CREGS_SUP_ANA_NC, 0); + hdmirx_phy_register_write(hdmirx_dev, + HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_RATE_CALC_HDMI14_CDR_SETTING_3_REG, + CDR_SETTING_BOUNDARY_3_DEFAULT); + hdmirx_phy_register_write(hdmirx_dev, + HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_RATE_CALC_HDMI14_CDR_SETTING_4_REG, + CDR_SETTING_BOUNDARY_4_DEFAULT); + hdmirx_phy_register_write(hdmirx_dev, + HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_RATE_CALC_HDMI14_CDR_SETTING_5_REG, + CDR_SETTING_BOUNDARY_5_DEFAULT); + hdmirx_phy_register_write(hdmirx_dev, + HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_RATE_CALC_HDMI14_CDR_SETTING_6_REG, + CDR_SETTING_BOUNDARY_6_DEFAULT); + hdmirx_phy_register_write(hdmirx_dev, + HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_RATE_CALC_HDMI14_CDR_SETTING_7_REG, + CDR_SETTING_BOUNDARY_7_DEFAULT); + hdmirx_update_bits(hdmirx_dev, PHY_CONFIG, PHY_PDDQ, 0); if (wait_reg_bit_status(hdmirx_dev, PHY_STATUS, PDDQ_ACK, 0, false, 10)) dev_err(dev, "%s wait pddq ack failed!\n", __func__); diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.h b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.h index ea7d40176b18..7f57c464df24 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.h +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.h @@ -51,6 +51,16 @@ #define HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_FSM_CONFIG 0x20c4 #define HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_ADAPT_REF_FOM 0x20c7 +#define HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_RATE_CALC_HDMI14_CDR_SETTING_3_REG 0x20e9 +#define CDR_SETTING_BOUNDARY_3_DEFAULT 0x52da +#define HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_RATE_CALC_HDMI14_CDR_SETTING_4_REG 0x20ea +#define CDR_SETTING_BOUNDARY_4_DEFAULT 0x43cd +#define HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_RATE_CALC_HDMI14_CDR_SETTING_5_REG 0x20eb +#define CDR_SETTING_BOUNDARY_5_DEFAULT 0x35b3 +#define HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_RATE_CALC_HDMI14_CDR_SETTING_6_REG 0x20fb +#define CDR_SETTING_BOUNDARY_6_DEFAULT 0x2799 +#define HDMIPCS_DIG_CTRL_PATH_MAIN_FSM_RATE_CALC_HDMI14_CDR_SETTING_7_REG 0x20fc +#define CDR_SETTING_BOUNDARY_7_DEFAULT 0x1b65 #define RAWLANE0_DIG_PCS_XF_RX_OVRD_OUT 0x300e #define RAWLANE1_DIG_PCS_XF_RX_OVRD_OUT 0x310e From c39732fb25c2ada87193210d4589e867bdf39ac4 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Thu, 29 Sep 2022 15:21:22 +0800 Subject: [PATCH 163/204] mtd: spinand: macronix: Support new devices MX35UF1GE4AC, MX35UF1GE4AD, MX35UF2GE4AD, MX35UF4GE4AD Change-Id: Ief8230ac8d37ad28d3253a9bec8786506698c8c3 Signed-off-by: Jon Lin --- drivers/mtd/nand/spi/macronix.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c index 5c4e36c8e861..f38fe26908c6 100644 --- a/drivers/mtd/nand/spi/macronix.c +++ b/drivers/mtd/nand/spi/macronix.c @@ -297,7 +297,36 @@ static const struct spinand_info macronix_spinand_table[] = { SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, mx35lf1ge4ab_ecc_get_status)), - + SPINAND_INFO("MX35UF1GE4AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x96), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF2GE4AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xA6), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX35UF4GE4AD", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB7), + NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), }; static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = { From b6601c35fd89a89a70af1368dd3be713fb7e9528 Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Thu, 15 Sep 2022 08:08:47 +0800 Subject: [PATCH 164/204] media: i2c: sc200ai support fastboot Signed-off-by: Su Yuefu Change-Id: I521c53b826c485231aa4c59b310a0352d6cdf428 Signed-off-by: Zefa Chen --- drivers/media/i2c/sc200ai.c | 210 +++++++++++++++++++++++++++++++----- 1 file changed, 184 insertions(+), 26 deletions(-) diff --git a/drivers/media/i2c/sc200ai.c b/drivers/media/i2c/sc200ai.c index 2b1c1a49fb9e..26fbea10893b 100644 --- a/drivers/media/i2c/sc200ai.c +++ b/drivers/media/i2c/sc200ai.c @@ -33,6 +33,7 @@ #include #include #include +#include "../platform/rockchip/isp/rkisp_tb_helper.h" #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x07) @@ -46,6 +47,7 @@ #define PIXEL_RATE_WITH_371M_10BIT (SC200AI_LINK_FREQ_371 * 2 * \ SC200AI_LANES / SC200AI_BITS_PER_SAMPLE) + #define SC200AI_XVCLK_FREQ 27000000 #define CHIP_ID 0xcb1c @@ -174,6 +176,8 @@ struct sc200ai { const char *len_name; u32 cur_vts; bool has_init_exp; + bool is_thunderboot; + bool is_first_streamoff; struct preisp_hdrae_exp_s init_hdrae_exp; }; @@ -188,10 +192,10 @@ static const struct regval sc200ai_global_regs[] = { /* * Xclk 24Mhz - * max_framerate 90fps + * max_framerate 60fps * mipi_datarate per lane 1008Mbps, 4lane */ -static const struct regval sc200ai_linear_10_1920x1080_regs[] = { +static const struct regval sc200ai_linear_10_1920x1080_60fps_regs[] = { {0x0103, 0x01}, {0x0100, 0x00}, {0x36e9, 0x80}, @@ -328,6 +332,113 @@ static const struct regval sc200ai_linear_10_1920x1080_regs[] = { {REG_NULL, 0x00}, }; +/* + * Xclk 27Mhz + * max_framerate 30fps + * mipi_datarate per lane 371.25Mbps, 2lane + */ +static const struct regval sc200ai_linear_10_1920x1080_30fps_regs[] = { + {0x0103, 0x01}, + {0x0100, 0x00}, + {0x36e9, 0x80}, + {0x36f9, 0x80}, + {0x301f, 0x03}, + //HTS=1100*2=2200 + {0x320c, 0x04}, + {0x320d, 0x4c}, + //VTS=1125 + {0x320e, 0x04}, + {0x320f, 0x65}, + {0x3243, 0x01}, + {0x3248, 0x02}, + {0x3249, 0x09}, + {0x3253, 0x08}, + {0x3271, 0x0a}, + {0x3301, 0x20}, + {0x3304, 0x40}, + {0x3306, 0x32}, + {0x330b, 0x88}, + {0x330f, 0x02}, + {0x331e, 0x39}, + {0x3333, 0x10}, + {0x3621, 0xe8}, + {0x3622, 0x16}, + {0x3637, 0x1b}, + {0x363a, 0x1f}, + {0x363b, 0xc6}, + {0x363c, 0x0e}, + {0x3670, 0x0a}, + {0x3674, 0x82}, + {0x3675, 0x76}, + {0x3676, 0x78}, + {0x367c, 0x48}, + {0x367d, 0x58}, + {0x3690, 0x34}, + {0x3691, 0x33}, + {0x3692, 0x44}, + {0x369c, 0x40}, + {0x369d, 0x48}, + {0x3901, 0x02}, + {0x3904, 0x04}, + {0x3908, 0x41}, + {0x391d, 0x14}, + {0x391f, 0x18}, + {0x3e01, 0x8c}, + {0x3e02, 0x20}, + {0x3e16, 0x00}, + {0x3e17, 0x80}, + {0x3f09, 0x48}, + {0x5787, 0x10}, + {0x5788, 0x06}, + {0x578a, 0x10}, + {0x578b, 0x06}, + {0x5790, 0x10}, + {0x5791, 0x10}, + {0x5792, 0x00}, + {0x5793, 0x10}, + {0x5794, 0x10}, + {0x5795, 0x00}, + {0x5799, 0x00}, + {0x57c7, 0x10}, + {0x57c8, 0x06}, + {0x57ca, 0x10}, + {0x57cb, 0x06}, + {0x57d1, 0x10}, + {0x57d4, 0x10}, + {0x57d9, 0x00}, + {0x59e0, 0x60}, + {0x59e1, 0x08}, + {0x59e2, 0x3f}, + {0x59e3, 0x18}, + {0x59e4, 0x18}, + {0x59e5, 0x3f}, + {0x59e6, 0x06}, + {0x59e7, 0x02}, + {0x59e8, 0x38}, + {0x59e9, 0x10}, + {0x59ea, 0x0c}, + {0x59eb, 0x10}, + {0x59ec, 0x04}, + {0x59ed, 0x02}, + {0x59ee, 0xa0}, + {0x59ef, 0x08}, + {0x59f4, 0x18}, + {0x59f5, 0x10}, + {0x59f6, 0x0c}, + {0x59f7, 0x10}, + {0x59f8, 0x06}, + {0x59f9, 0x02}, + {0x59fa, 0x18}, + {0x59fb, 0x10}, + {0x59fc, 0x0c}, + {0x59fd, 0x10}, + {0x59fe, 0x04}, + {0x59ff, 0x02}, + {0x36e9, 0x20}, + {0x36f9, 0x27}, + {REG_NULL, 0x00}, +}; + /* * Xclk 27Mhz * max_framerate 30fps @@ -490,6 +601,20 @@ static const struct regval sc200ai_hdr_10_1920x1080_regs[] = { static const struct sc200ai_mode supported_modes[] = { { + .width = 1920, + .height = 1080, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x0080, + .hts_def = 0x44C * 2, + .vts_def = 0x0465, + .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, + .reg_list = sc200ai_linear_10_1920x1080_30fps_regs, + .hdr_mode = NO_HDR, + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, + }, { .width = 1920, .height = 1080, .max_fps = { @@ -500,7 +625,7 @@ static const struct sc200ai_mode supported_modes[] = { .hts_def = 0x44C * 2, .vts_def = 0x0465, .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, - .reg_list = sc200ai_linear_10_1920x1080_regs, + .reg_list = sc200ai_linear_10_1920x1080_60fps_regs, .hdr_mode = NO_HDR, .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, }, { @@ -1230,21 +1355,23 @@ static int __sc200ai_start_stream(struct sc200ai *sc200ai) { int ret; - ret = sc200ai_write_array(sc200ai->client, sc200ai->cur_mode->reg_list); - if (ret) - return ret; - - /* In case these controls are set before streaming */ - ret = __v4l2_ctrl_handler_setup(&sc200ai->ctrl_handler); - if (ret) - return ret; - if (sc200ai->has_init_exp && sc200ai->cur_mode->hdr_mode != NO_HDR) { - ret = sc200ai_ioctl(&sc200ai->subdev, PREISP_CMD_SET_HDRAE_EXP, - &sc200ai->init_hdrae_exp); - if (ret) { - dev_err(&sc200ai->client->dev, - "init exp fail in hdr mode\n"); + if (!sc200ai->is_thunderboot) { + ret = sc200ai_write_array(sc200ai->client, sc200ai->cur_mode->reg_list); + if (ret) return ret; + + /* In case these controls are set before streaming */ + ret = __v4l2_ctrl_handler_setup(&sc200ai->ctrl_handler); + if (ret) + return ret; + if (sc200ai->has_init_exp && sc200ai->cur_mode->hdr_mode != NO_HDR) { + ret = sc200ai_ioctl(&sc200ai->subdev, PREISP_CMD_SET_HDRAE_EXP, + &sc200ai->init_hdrae_exp); + if (ret) { + dev_err(&sc200ai->client->dev, + "init exp fail in hdr mode\n"); + return ret; + } } } @@ -1255,10 +1382,13 @@ static int __sc200ai_start_stream(struct sc200ai *sc200ai) static int __sc200ai_stop_stream(struct sc200ai *sc200ai) { sc200ai->has_init_exp = false; + if (sc200ai->is_thunderboot) + sc200ai->is_first_streamoff = true; return sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE, SC200AI_REG_VALUE_08BIT, SC200AI_MODE_SW_STANDBY); } +static int __sc200ai_power_on(struct sc200ai *sc200ai); static int sc200ai_s_stream(struct v4l2_subdev *sd, int on) { struct sc200ai *sc200ai = to_sc200ai(sd); @@ -1271,6 +1401,10 @@ static int sc200ai_s_stream(struct v4l2_subdev *sd, int on) goto unlock_and_return; if (on) { + if (sc200ai->is_thunderboot && rkisp_tb_get_state() == RKISP_TB_NG) { + sc200ai->is_thunderboot = false; + __sc200ai_power_on(sc200ai); + } ret = pm_runtime_get_sync(&client->dev); if (ret < 0) { pm_runtime_put_noidle(&client->dev); @@ -1315,11 +1449,13 @@ static int sc200ai_s_power(struct v4l2_subdev *sd, int on) goto unlock_and_return; } - ret = sc200ai_write_array(sc200ai->client, sc200ai_global_regs); - if (ret) { - v4l2_err(sd, "could not set init registers\n"); - pm_runtime_put_noidle(&client->dev); - goto unlock_and_return; + if (!sc200ai->is_thunderboot) { + ret = sc200ai_write_array(sc200ai->client, sc200ai_global_regs); + if (ret) { + v4l2_err(sd, "could not set init registers\n"); + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } } sc200ai->power_on = true; @@ -1362,6 +1498,9 @@ static int __sc200ai_power_on(struct sc200ai *sc200ai) dev_err(dev, "Failed to enable xvclk\n"); return ret; } + if (sc200ai->is_thunderboot) + return 0; + if (!IS_ERR(sc200ai->reset_gpio)) gpiod_set_value_cansleep(sc200ai->reset_gpio, 0); @@ -1400,6 +1539,15 @@ static void __sc200ai_power_off(struct sc200ai *sc200ai) int ret; struct device *dev = &sc200ai->client->dev; + clk_disable_unprepare(sc200ai->xvclk); + if (sc200ai->is_thunderboot) { + if (sc200ai->is_first_streamoff) { + sc200ai->is_thunderboot = false; + sc200ai->is_first_streamoff = false; + } else { + return; + } + } if (!IS_ERR(sc200ai->pwdn_gpio)) gpiod_set_value_cansleep(sc200ai->pwdn_gpio, 0); clk_disable_unprepare(sc200ai->xvclk); @@ -1651,7 +1799,7 @@ static int sc200ai_initialize_controls(struct sc200ai *sc200ai) V4L2_CID_VBLANK, vblank_def, SC200AI_VTS_MAX - mode->height, 1, vblank_def); - exposure_max = mode->vts_def - 4; + exposure_max = 2 * mode->vts_def - 8; sc200ai->exposure = v4l2_ctrl_new_std(handler, &sc200ai_ctrl_ops, V4L2_CID_EXPOSURE, SC200AI_EXPOSURE_MIN, exposure_max, SC200AI_EXPOSURE_STEP, @@ -1698,6 +1846,11 @@ static int sc200ai_check_sensor_id(struct sc200ai *sc200ai, u32 id = 0; int ret; + if (sc200ai->is_thunderboot) { + dev_info(dev, "Enable thunderboot mode, skip sensor id check\n"); + return 0; + } + ret = sc200ai_read_reg(client, SC200AI_REG_CHIP_ID, SC200AI_REG_VALUE_16BIT, &id); if (id != CHIP_ID) { @@ -1756,6 +1909,7 @@ static int sc200ai_probe(struct i2c_client *client, return -EINVAL; } + sc200ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); sc200ai->client = client; for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { if (hdr_mode == supported_modes[i].hdr_mode) { @@ -1772,11 +1926,11 @@ static int sc200ai_probe(struct i2c_client *client, return -EINVAL; } - sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + sc200ai->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS); if (IS_ERR(sc200ai->reset_gpio)) dev_warn(dev, "Failed to get reset-gpios\n"); - sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); + sc200ai->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_ASIS); if (IS_ERR(sc200ai->pwdn_gpio)) dev_warn(dev, "Failed to get pwdn-gpios\n"); @@ -1921,8 +2075,12 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc200ai_i2c_driver); } +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +subsys_initcall(sensor_mod_init); +#else device_initcall_sync(sensor_mod_init); +#endif module_exit(sensor_mod_exit); MODULE_DESCRIPTION("smartsens sc200ai sensor driver"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); From a868b3f46bd5f83846a05e554d83c6d0061e154d Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Sat, 17 Sep 2022 15:59:14 +0800 Subject: [PATCH 165/204] media: i2c: updata sc200ai hdr config Signed-off-by: Su Yuefu Change-Id: I028b796c20c17ad8ca1bdb2b1d2ed189106cd06c Signed-off-by: Zefa Chen --- drivers/media/i2c/sc200ai.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/sc200ai.c b/drivers/media/i2c/sc200ai.c index 26fbea10893b..9e5841b946f4 100644 --- a/drivers/media/i2c/sc200ai.c +++ b/drivers/media/i2c/sc200ai.c @@ -450,8 +450,12 @@ static const struct regval sc200ai_hdr_10_1920x1080_regs[] = { {0x36e9, 0x80}, {0x36f9, 0x80}, {0x301f, 0x02}, + //HTS=1100*2=2200 + {0x320c, 0x04}, + {0x320d, 0x4c}, + //VTS =2252 {0x320e, 0x08}, - {0x320f, 0xca}, + {0x320f, 0xcc}, {0x3220, 0x53}, {0x3243, 0x01}, {0x3248, 0x02}, @@ -476,9 +480,11 @@ static const struct regval sc200ai_hdr_10_1920x1080_regs[] = { {0x331f, 0x61}, {0x3320, 0x07}, {0x3333, 0x10}, + {0x3347, 0x77}, {0x334c, 0x08}, {0x3356, 0x09}, {0x3364, 0x17}, + {0x336c, 0xcc}, {0x3390, 0x08}, {0x3391, 0x18}, {0x3392, 0x38}, @@ -536,7 +542,7 @@ static const struct regval sc200ai_hdr_10_1920x1080_regs[] = { {0x3e16, 0x00}, {0x3e17, 0x80}, {0x3e23, 0x00}, - {0x3e24, 0x40}, + {0x3e24, 0x88}, {0x3f09, 0x48}, {0x4816, 0xb1}, {0x4819, 0x09}, @@ -637,7 +643,7 @@ static const struct sc200ai_mode supported_modes[] = { }, .exp_def = 0x0080, .hts_def = 0x44C * 2, - .vts_def = 0x08CA, + .vts_def = 0x08CC, .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, .reg_list = sc200ai_hdr_10_1920x1080_regs, .hdr_mode = HDR_X2, @@ -956,7 +962,6 @@ static int sc200ai_set_hdrae(struct sc200ai *sc200ai, SC200AI_REG_VALUE_08BIT, SC200AI_FETCH_EXP_L(s_exp_time)); - ret |= sc200ai_set_gain_reg(sc200ai, l_a_gain, SC200AI_LGAIN); ret |= sc200ai_set_gain_reg(sc200ai, s_a_gain, SC200AI_SGAIN); return ret; From 9b0a2023cc4c0f8533e6dfedd1c44c5b27576332 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Fri, 23 Sep 2022 17:53:32 +0800 Subject: [PATCH 166/204] media: rockchip: vicap: thunderboot support HDR mode Signed-off-by: Zefa Chen Change-Id: I85c29687c6bdcfd3adfab9d2de14097a2721433b --- drivers/media/platform/rockchip/cif/capture.c | 412 +++++++++++++----- drivers/media/platform/rockchip/cif/common.c | 23 +- drivers/media/platform/rockchip/cif/dev.h | 1 + .../media/platform/rockchip/cif/subdev-itf.c | 52 ++- 4 files changed, 365 insertions(+), 123 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 8dc75f078f96..7dc2767df0b2 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -1305,7 +1305,7 @@ int rkcif_get_linetime(struct rkcif_stream *stream) /***************************** stream operations ******************************/ static int rkcif_assign_new_buffer_oneframe(struct rkcif_stream *stream, - enum rkcif_yuvaddr_state stat) + enum rkcif_yuvaddr_state stat) { struct rkcif_device *dev = stream->cifdev; struct rkcif_dummy_buffer *dummy_buf = &dev->dummy_buf; @@ -1463,8 +1463,8 @@ static void rkcif_s_rx_buffer(struct rkcif_device *dev, struct rkisp_rx_buf *dbu dbufs->sequence < 15) { rx_buf = to_cif_rx_buf(dbufs); v4l2_info(&dev->v4l2_dev, - "s_buf seq %d dma addr %x, %lld\n", - dbufs->sequence, (u32)rx_buf->dummy.dma_addr, + "s_buf seq %d type %d, dma addr %x, %lld\n", + dbufs->sequence, dbufs->type, (u32)rx_buf->dummy.dma_addr, ktime_get_ns()); } v4l2_subdev_call(sd, video, s_rx_buffer, dbufs, NULL); @@ -1492,8 +1492,121 @@ static void rkcif_disable_skip_frame(struct rkcif_stream *stream) stream->skip_info.skip_en = false; } +static void rkcif_rdbk_frame_end_toisp(struct rkcif_stream *stream, + struct rkcif_rx_buffer *buffer) +{ + struct rkcif_device *dev = stream->cifdev; + struct rkcif_sensor_info *sensor = &stream->cifdev->terminal_sensor; + u32 denominator, numerator; + u64 l_ts, m_ts, s_ts, time = 30000000LL; + int ret, fps = -1; + unsigned long flags; + + spin_lock_irqsave(&dev->hdr_lock, flags); + if (dev->rdbk_rx_buf[stream->id]) { + list_add_tail(&dev->rdbk_rx_buf[stream->id]->list, &stream->rx_buf_head); + dev->rdbk_rx_buf[stream->id] = buffer; + } else { + dev->rdbk_rx_buf[stream->id] = buffer; + } + + numerator = sensor->fi.interval.numerator; + denominator = sensor->fi.interval.denominator; + if (denominator && numerator) + time = numerator * 1000 / denominator * 1000 * 1000; + + if (dev->hdr.hdr_mode == HDR_X3 && + dev->rdbk_rx_buf[RDBK_L] && + dev->rdbk_rx_buf[RDBK_M] && + dev->rdbk_rx_buf[RDBK_S]) { + l_ts = dev->rdbk_rx_buf[RDBK_L]->dbufs.timestamp; + m_ts = dev->rdbk_rx_buf[RDBK_M]->dbufs.timestamp; + s_ts = dev->rdbk_rx_buf[RDBK_S]->dbufs.timestamp; + + if (m_ts < l_ts || s_ts < m_ts) { + v4l2_err(&dev->v4l2_dev, + "s/m/l frame err, timestamp s:%lld m:%lld l:%lld\n", + s_ts, m_ts, l_ts); + goto RDBK_TOISP_UNMATCH; + } + + if ((m_ts - l_ts) > time || (s_ts - m_ts) > time) { + ret = v4l2_subdev_call(sensor->sd, + video, + g_frame_interval, + &sensor->fi); + if (!ret) { + denominator = sensor->fi.interval.denominator; + numerator = sensor->fi.interval.numerator; + if (denominator && numerator) { + time = numerator * 1000 / denominator * 1000 * 1000; + fps = denominator / numerator; + } + } + + if ((m_ts - l_ts) > time || (s_ts - m_ts) > time) { + v4l2_err(&dev->v4l2_dev, + "timestamp no match, s:%lld m:%lld l:%lld, fps:%d\n", + s_ts, m_ts, l_ts, fps); + goto RDBK_TOISP_UNMATCH; + } + } + dev->rdbk_rx_buf[RDBK_M]->dbufs.sequence = dev->rdbk_rx_buf[RDBK_L]->dbufs.sequence; + dev->rdbk_rx_buf[RDBK_S]->dbufs.sequence = dev->rdbk_rx_buf[RDBK_L]->dbufs.sequence; + rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_L]->dbufs); + rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_M]->dbufs); + rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_S]->dbufs); + dev->rdbk_rx_buf[RDBK_L] = NULL; + dev->rdbk_rx_buf[RDBK_M] = NULL; + dev->rdbk_rx_buf[RDBK_S] = NULL; + } else if (dev->hdr.hdr_mode == HDR_X2 && + dev->rdbk_rx_buf[RDBK_L] && dev->rdbk_rx_buf[RDBK_M]) { + l_ts = dev->rdbk_rx_buf[RDBK_L]->dbufs.timestamp; + s_ts = dev->rdbk_rx_buf[RDBK_M]->dbufs.timestamp; + + if (s_ts < l_ts) { + v4l2_err(&dev->v4l2_dev, + "s/l frame err, timestamp s:%lld l:%lld\n", + s_ts, l_ts); + goto RDBK_TOISP_UNMATCH; + } + + if ((s_ts - l_ts) > time) { + ret = v4l2_subdev_call(sensor->sd, + video, + g_frame_interval, + &sensor->fi); + if (!ret) { + denominator = sensor->fi.interval.denominator; + numerator = sensor->fi.interval.numerator; + if (denominator && numerator) { + time = numerator * 1000 / denominator * 1000 * 1000; + fps = denominator / numerator; + } + } + if ((s_ts - l_ts) > time) { + v4l2_err(&dev->v4l2_dev, + "timestamp no match, s:%lld l:%lld, fps:%d\n", + s_ts, l_ts, fps); + goto RDBK_TOISP_UNMATCH; + } + } + dev->rdbk_rx_buf[RDBK_M]->dbufs.sequence = dev->rdbk_rx_buf[RDBK_L]->dbufs.sequence; + rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_L]->dbufs); + rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_M]->dbufs); + dev->rdbk_rx_buf[RDBK_L] = NULL; + dev->rdbk_rx_buf[RDBK_M] = NULL; + } + + spin_unlock_irqrestore(&dev->hdr_lock, flags); + return; + +RDBK_TOISP_UNMATCH: + spin_unlock_irqrestore(&dev->hdr_lock, flags); +} + static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, - int channel_id) + int channel_id) { struct rkcif_device *dev = stream->cifdev; struct rkcif_rx_buffer *rx_buf; @@ -1554,7 +1667,7 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, } static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, - int channel_id) + int channel_id) { struct rkcif_device *dev = stream->cifdev; struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; @@ -1597,7 +1710,10 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, active_buf->dbufs.sequence = stream->frame_idx - 1; active_buf->dbufs.timestamp = stream->readout.fs_timestamp; stream->last_frame_idx = stream->frame_idx; - rkcif_s_rx_buffer(dev, &active_buf->dbufs); + if (dev->hdr.hdr_mode == NO_HDR) + rkcif_s_rx_buffer(dev, &active_buf->dbufs); + else + rkcif_rdbk_frame_end_toisp(stream, active_buf); stream->buf_num_toisp--; } else { rkcif_s_rx_buffer(dev, &stream->next_buf_toisp->dbufs); @@ -1622,7 +1738,10 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, active_buf->dbufs.sequence = stream->frame_idx - 1; active_buf->dbufs.timestamp = stream->readout.fs_timestamp; stream->last_frame_idx = stream->frame_idx; - rkcif_s_rx_buffer(dev, &active_buf->dbufs); + if (dev->hdr.hdr_mode == NO_HDR) + rkcif_s_rx_buffer(dev, &active_buf->dbufs); + else + rkcif_rdbk_frame_end_toisp(stream, active_buf); stream->buf_num_toisp--; } else { rkcif_s_rx_buffer(dev, &stream->curr_buf_toisp->dbufs); @@ -1655,7 +1774,8 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, } if (stream->cifdev->rdbk_debug) v4l2_info(&stream->cifdev->v4l2_dev, - "hold buf %x\n", + "stream[%d] hold buf %x\n", + stream->id, (u32)stream->next_buf_toisp->dummy.dma_addr); } if (priv && priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO && active_buf) { @@ -1664,11 +1784,15 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, active_buf->dbufs.sequence = stream->frame_idx - 1; active_buf->dbufs.timestamp = stream->readout.fs_timestamp; stream->last_frame_idx = stream->frame_idx; - rkcif_s_rx_buffer(dev, &active_buf->dbufs); + if (dev->hdr.hdr_mode == NO_HDR) + rkcif_s_rx_buffer(dev, &active_buf->dbufs); + else + rkcif_rdbk_frame_end_toisp(stream, active_buf); } else { if (stream->cifdev->rdbk_debug && dev->dummy_buf.vaddr) v4l2_info(&stream->cifdev->v4l2_dev, - "loss frame %d\n", + "stream[%d] loss frame %d\n", + stream->id, stream->frame_idx - 1); } } @@ -1680,7 +1804,8 @@ out_get_buf: if (dev->rdbk_debug > 1 && stream->frame_idx < 15) v4l2_info(&dev->v4l2_dev, - "update, seq %d, reg %x, buf %x\n", + "stream[%d] update, seq %d, reg %x, buf %x\n", + stream->id, stream->frame_idx - 1, frm_addr_y, (u32)buffer->dummy.dma_addr); } else if (dev->dummy_buf.vaddr) { @@ -1692,7 +1817,7 @@ out_get_buf: } static int rkcif_assign_new_buffer_pingpong_toisp(struct rkcif_stream *stream, - int init, int channel_id) + int init, int channel_id) { int ret = 0; @@ -1721,7 +1846,8 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) if (dev->rdbk_debug > 2 && stream->frame_idx < 15) v4l2_info(&dev->v4l2_dev, - "addr check not equal 0x%x 0x%x\n", + "stream[%d] addr check not equal 0x%x 0x%x\n", + stream->id, (u32)stream->curr_buf_toisp->dummy.dma_addr, (u32)stream->next_buf_toisp->dummy.dma_addr); return; @@ -1748,7 +1874,8 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) if (dev->rdbk_debug > 2 && stream->frame_idx < 15) v4l2_info(&dev->v4l2_dev, - "check update, cur %lld, fe %lld, vb %u lack_buf %d\n", + "stream[%d] check update, cur %lld, fe %lld, vb %u lack_buf %d\n", + stream->id, cur_time, stream->readout.fe_timestamp, vblank_ns, stream->lack_buf_cnt); if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || @@ -1775,7 +1902,8 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) if (dev->rdbk_debug > 1 && stream->frame_idx < 15) v4l2_info(&dev->v4l2_dev, - "check update, seq %d, addr 0x%x, buf 0x%x\n", + "stream[%d] check update, seq %d, addr 0x%x, buf 0x%x\n", + stream->id, stream->frame_idx - 1, frm_addr_y, (u32)stream->curr_buf_toisp->dummy.dma_addr); stream->buf_num_toisp--; @@ -1792,7 +1920,8 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) if (dev->rdbk_debug > 1 && stream->frame_idx < 15) v4l2_info(&dev->v4l2_dev, - "check update, seq %d, addr 0x%x, buf 0x%x\n", + "stream[%d] check update, seq %d, addr 0x%x, buf 0x%x\n", + stream->id, stream->frame_idx - 1, frm_addr_y, (u32)stream->next_buf_toisp->dummy.dma_addr); stream->buf_num_toisp--; @@ -1805,7 +1934,8 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) if (dev->rdbk_debug > 1 && stream->frame_idx < 15) v4l2_info(&dev->v4l2_dev, - "early update, seq %d\n", + "stream[%d] early update, seq %d\n", + stream->id, stream->frame_idx - 1); if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) @@ -1969,7 +2099,7 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream, } static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream, - int channel_id) + int channel_id) { struct rkcif_device *dev = stream->cifdev; struct rkcif_dummy_buffer *dummy_buf = &dev->dummy_buf; @@ -2324,8 +2454,12 @@ static int rkcif_update_new_buffer_wake_up_mode(struct rkcif_stream *stream) static int rkcif_get_new_buffer_wake_up_mode_rdbk(struct rkcif_stream *stream) { struct rkcif_rx_buffer *buffer = NULL; + struct rkcif_device *dev = stream->cifdev; + struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; int ret = 0; unsigned long flags; + u32 frm_addr_y; + int frame_phase = 0; spin_lock_irqsave(&stream->vbq_lock, flags); if (!list_empty(&stream->rx_buf_head)) { @@ -2336,6 +2470,7 @@ static int rkcif_get_new_buffer_wake_up_mode_rdbk(struct rkcif_stream *stream) list_del(&buffer->list); stream->curr_buf_toisp = buffer; } + frame_phase = CIF_CSI_FRAME0_READY; } else { buffer = list_first_entry(&stream->rx_buf_head, struct rkcif_rx_buffer, list); @@ -2343,8 +2478,8 @@ static int rkcif_get_new_buffer_wake_up_mode_rdbk(struct rkcif_stream *stream) list_del(&buffer->list); stream->next_buf_toisp = buffer; } + frame_phase = CIF_CSI_FRAME1_READY; } - stream->is_buf_active = true; if (stream->lack_buf_cnt) stream->lack_buf_cnt--; } else { @@ -2356,61 +2491,41 @@ static int rkcif_get_new_buffer_wake_up_mode_rdbk(struct rkcif_stream *stream) stream->curr_buf_toisp = stream->next_buf_toisp; else stream->next_buf_toisp = stream->curr_buf_toisp; - stream->is_buf_active = true; + buffer = stream->curr_buf_toisp; ret = 0; if (stream->cifdev->rdbk_debug) v4l2_info(&stream->cifdev->v4l2_dev, - "hold buf %x\n", + "stream[%d] hold buf %x\n", + stream->id, (u32)stream->next_buf_toisp->dummy.dma_addr); } else { - stream->is_buf_active = false; ret = -EINVAL; } } - spin_unlock_irqrestore(&stream->vbq_lock, flags); - - return ret; -} - -static int rkcif_update_new_buffer_wake_up_mode_rdbk(struct rkcif_stream *stream) -{ - struct rkcif_device *dev = stream->cifdev; - struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; - struct rkcif_rx_buffer *buffer = NULL; - u32 frm_addr_y; - int channel_id = stream->id; - int ret = 0; - unsigned long flags; - - if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || - mbus_cfg->type == V4L2_MBUS_CSI2_CPHY || - mbus_cfg->type == V4L2_MBUS_CCP2) { - frm_addr_y = stream->frame_phase & CIF_CSI_FRAME0_READY ? - get_reg_index_of_frm0_y_addr(channel_id) : - get_reg_index_of_frm1_y_addr(channel_id); - } else { - frm_addr_y = stream->frame_phase & CIF_CSI_FRAME0_READY ? - get_dvp_reg_index_of_frm0_y_addr(channel_id) : - get_dvp_reg_index_of_frm1_y_addr(channel_id); - } - spin_lock_irqsave(&stream->vbq_lock, flags); - if (stream->is_buf_active) { - if (stream->frame_phase == CIF_CSI_FRAME0_READY) - buffer = stream->curr_buf_toisp; - else if (stream->frame_phase == CIF_CSI_FRAME1_READY) - buffer = stream->next_buf_toisp; - } - spin_unlock_irqrestore(&stream->vbq_lock, flags); if (buffer) { + if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || + mbus_cfg->type == V4L2_MBUS_CSI2_CPHY || + mbus_cfg->type == V4L2_MBUS_CCP2) { + frm_addr_y = frame_phase & CIF_CSI_FRAME0_READY ? + get_reg_index_of_frm0_y_addr(stream->id) : + get_reg_index_of_frm1_y_addr(stream->id); + } else { + frm_addr_y = frame_phase & CIF_CSI_FRAME0_READY ? + get_dvp_reg_index_of_frm0_y_addr(stream->id) : + get_dvp_reg_index_of_frm1_y_addr(stream->id); + } rkcif_write_register(dev, frm_addr_y, buffer->dummy.dma_addr); if (dev->rdbk_debug > 1 && stream->frame_idx < 15) v4l2_info(&dev->v4l2_dev, - "rdbk update, seq %d, reg %x, buf %x\n", + "stream[%d] rdbk update, seq %d, reg %x, buf %x\n", + stream->id, stream->frame_idx - 1, frm_addr_y, (u32)buffer->dummy.dma_addr); } + spin_unlock_irqrestore(&stream->vbq_lock, flags); + return ret; } @@ -2554,7 +2669,7 @@ static void rkcif_csi_set_lvds_sav_eav(struct rkcif_stream *stream, } static unsigned char get_csi_fmt_val(const struct cif_input_fmt *cif_fmt_in, - struct csi_channel_info *csi_info) + struct csi_channel_info *csi_info) { unsigned char csi_fmt_val = 0; @@ -2694,8 +2809,8 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, } static int rkcif_csi_channel_set(struct rkcif_stream *stream, - struct csi_channel_info *channel, - enum v4l2_mbus_type mbus_type) + struct csi_channel_info *channel, + enum v4l2_mbus_type mbus_type) { unsigned int val = 0x0; struct rkcif_device *dev = stream->cifdev; @@ -3006,8 +3121,8 @@ static void rkcif_modify_frame_skip_config(struct rkcif_stream *stream) /*config reg for rk3588*/ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, - struct csi_channel_info *channel, - enum v4l2_mbus_type mbus_type, unsigned int mode) + struct csi_channel_info *channel, + enum v4l2_mbus_type mbus_type, unsigned int mode) { unsigned int val = 0x0; struct rkcif_device *dev = stream->cifdev; @@ -3296,8 +3411,8 @@ static void rkcif_stream_stop(struct rkcif_stream *stream) } static bool rkcif_is_extending_line_for_height(struct rkcif_device *dev, - struct rkcif_stream *stream, - const struct cif_input_fmt *fmt) + struct rkcif_stream *stream, + const struct cif_input_fmt *fmt) { bool is_extended = false; struct rkmodule_hdr_cfg hdr_cfg; @@ -3378,7 +3493,7 @@ static int rkcif_queue_setup(struct vb2_queue *queue, } static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream, - int channel_id) + int channel_id) { struct rkcif_device *dev = stream->cifdev; struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; @@ -3611,7 +3726,6 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num) if (dev->is_thunderboot) { spin_unlock_irqrestore(&dev->buffree_lock, flags); schedule_work(&priv->buffree_work.work); - dev->is_thunderboot = false; } stream->dma_en &= ~RKCIF_DMAEN_BY_ISP; v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev, @@ -3674,6 +3788,10 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) i, buf_num); break; } + if (dev->rdbk_debug) + v4l2_info(&dev->v4l2_dev, + "stream[%d] buf addr 0x%llx\n", + stream->id, (u64)dummy->dma_addr); } else { ret = rkcif_alloc_buffer(dev, dummy); if (ret) { @@ -3909,7 +4027,7 @@ static void rkcif_detach_sync_mode(struct rkcif_device *cif_dev) } void rkcif_do_stop_stream(struct rkcif_stream *stream, - unsigned int mode) + unsigned int mode) { struct rkcif_vdev_node *node = &stream->vnode; struct rkcif_device *dev = stream->cifdev; @@ -5171,8 +5289,8 @@ static int rkcif_init_vb2_queue(struct vb2_queue *q, } int rkcif_set_fmt(struct rkcif_stream *stream, - struct v4l2_pix_format_mplane *pixm, - bool try) + struct v4l2_pix_format_mplane *pixm, + bool try) { struct rkcif_device *dev = stream->cifdev; const struct cif_output_fmt *fmt; @@ -5682,7 +5800,7 @@ static int rkcif_querycap(struct file *file, void *priv, } static __maybe_unused int rkcif_cropcap(struct file *file, void *fh, - struct v4l2_cropcap *cap) + struct v4l2_cropcap *cap) { struct rkcif_stream *stream = video_drvdata(file); struct rkcif_device *dev = stream->cifdev; @@ -5709,7 +5827,7 @@ static __maybe_unused int rkcif_cropcap(struct file *file, void *fh, } static int rkcif_s_selection(struct file *file, void *fh, - struct v4l2_selection *s) + struct v4l2_selection *s) { struct rkcif_stream *stream = video_drvdata(file); struct rkcif_device *dev = stream->cifdev; @@ -5744,7 +5862,7 @@ err: } static int rkcif_g_selection(struct file *file, void *fh, - struct v4l2_selection *s) + struct v4l2_selection *s) { struct rkcif_stream *stream = video_drvdata(file); struct rkcif_device *dev = stream->cifdev; @@ -5904,10 +6022,10 @@ void rkcif_set_fps(struct rkcif_stream *stream, struct rkcif_fps *fps) } static int rkcif_do_reset_work(struct rkcif_device *cif_dev, - enum rkmodule_reset_src reset_src); + enum rkmodule_reset_src reset_src); static long rkcif_ioctl_default(struct file *file, void *fh, - bool valid_prio, unsigned int cmd, void *arg) + bool valid_prio, unsigned int cmd, void *arg) { struct rkcif_stream *stream = video_drvdata(file); struct rkcif_device *dev = stream->cifdev; @@ -6209,8 +6327,8 @@ static int rkcif_lvds_sd_get_fmt(struct v4l2_subdev *sd, } static struct v4l2_rect *rkcif_lvds_sd_get_crop(struct rkcif_lvds_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - enum v4l2_subdev_format_whence which) + struct v4l2_subdev_pad_config *cfg, + enum v4l2_subdev_format_whence which) { if (which == V4L2_SUBDEV_FORMAT_TRY) return v4l2_subdev_get_try_crop(&subdev->sd, cfg, RKCIF_LVDS_PAD_SINK); @@ -6219,8 +6337,8 @@ static struct v4l2_rect *rkcif_lvds_sd_get_crop(struct rkcif_lvds_subdev *subdev } static int rkcif_lvds_sd_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) { struct rkcif_lvds_subdev *subdev = container_of(sd, struct rkcif_lvds_subdev, sd); struct v4l2_subdev *sensor = get_lvds_remote_sensor(sd); @@ -6235,8 +6353,8 @@ static int rkcif_lvds_sd_set_selection(struct v4l2_subdev *sd, } static int rkcif_lvds_sd_get_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) { struct rkcif_lvds_subdev *subdev = container_of(sd, struct rkcif_lvds_subdev, sd); struct v4l2_subdev *sensor = get_lvds_remote_sensor(sd); @@ -6321,7 +6439,7 @@ static int rkcif_lvds_sd_s_power(struct v4l2_subdev *sd, int on) } static int rkcif_sof_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) + struct v4l2_event_subscription *sub) { if (sub->type == V4L2_EVENT_FRAME_SYNC || sub->type == V4L2_EVENT_RESET_DEV) @@ -6541,7 +6659,7 @@ void rkcif_unregister_dvp_sof_subdev(struct rkcif_device *dev) } void rkcif_vb_done_oneframe(struct rkcif_stream *stream, - struct vb2_v4l2_buffer *vb_done) + struct vb2_v4l2_buffer *vb_done) { const struct cif_output_fmt *fmt = stream->cif_fmt_out; u32 i; @@ -6649,7 +6767,7 @@ void rkcif_irq_oneframe(struct rkcif_device *cif_dev) } static int rkcif_csi_g_mipi_id(struct v4l2_device *v4l2_dev, - unsigned int intstat) + unsigned int intstat) { if (intstat & CSI_FRAME_END_ID0) { if ((intstat & CSI_FRAME_END_ID0) == @@ -6723,7 +6841,7 @@ static int rkcif_dvp_g_ch_id(struct v4l2_device *v4l2_dev, } static int rkcif_dvp_g_ch_id_by_fe(struct v4l2_device *v4l2_dev, - u32 intstat) + u32 intstat) { if (intstat & DVP_ALL_END_ID0) { if ((intstat & DVP_ALL_END_ID0) == @@ -7276,9 +7394,9 @@ RDBK_FRM_UNMATCH: } static void rkcif_buf_done_prepare(struct rkcif_stream *stream, - struct rkcif_buffer *active_buf, - int mipi_id, - u32 mode) + struct rkcif_buffer *active_buf, + int mipi_id, + u32 mode) { unsigned long flags; struct vb2_v4l2_buffer *vb_done = NULL; @@ -7428,6 +7546,50 @@ static void rkcif_line_wake_up(struct rkcif_stream *stream, int mipi_id) rkcif_buf_done_prepare(stream, active_buf, mipi_id, mode); } +static void rkcif_store_last_buf_for_online(struct rkcif_stream *stream, + struct rkcif_rx_buffer *buf) +{ + struct rkcif_device *dev = stream->cifdev; + struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; + u32 frm0_addr_y, frm1_addr_y; + + INIT_LIST_HEAD(&stream->rx_buf_head); + stream->curr_buf_toisp = buf; + stream->next_buf_toisp = buf; + if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || + mbus_cfg->type == V4L2_MBUS_CSI2_CPHY || + mbus_cfg->type == V4L2_MBUS_CCP2) { + frm0_addr_y = get_reg_index_of_frm0_y_addr(stream->id); + frm1_addr_y = get_reg_index_of_frm1_y_addr(stream->id); + } else { + frm0_addr_y = get_dvp_reg_index_of_frm0_y_addr(stream->id); + frm1_addr_y = get_dvp_reg_index_of_frm1_y_addr(stream->id); + } + rkcif_write_register(dev, frm0_addr_y, + buf->dummy.dma_addr); + rkcif_write_register(dev, frm1_addr_y, + 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); + } + spin_unlock_irqrestore(&priv->cif_dev->buffree_lock, flags); + schedule_work(&priv->buffree_work.work); +} + static int rkcif_stop_dma_capture(struct rkcif_stream *stream); static void rkcif_line_wake_up_rdbk(struct rkcif_stream *stream, int mipi_id) { @@ -7464,24 +7626,35 @@ static void rkcif_line_wake_up_rdbk(struct rkcif_stream *stream, int mipi_id) (u32)active_buf->dummy.dma_addr); if (!ret) { priv = stream->cifdev->sditf[0]; - if (priv && priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { + if (stream->cur_stream_mode & RKCIF_STREAM_MODE_TOISP_RDBK) { spin_lock_irqsave(&stream->vbq_lock, flags); - if ((stream->frame_idx - 1) == stream->last_rx_buf_idx && - stream->cifdev->is_thunderboot) { + if (stream->cifdev->is_thunderboot && + (stream->frame_idx - 1) == stream->last_rx_buf_idx) { stream->cur_stream_mode &= ~RKCIF_STREAM_MODE_TOISP_RDBK; stream->cur_stream_mode |= RKCIF_STREAM_MODE_TOISP; - if (stream->cifdev->hdr.hdr_mode == NO_HDR) - stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; - rkcif_stop_dma_capture(stream); - active_buf->dbufs.is_switch = true; stream->cifdev->wait_line = 0; stream->is_line_wake_up = false; + if (stream->cifdev->hdr.hdr_mode == NO_HDR || + (priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 1) || + (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id == 2)) { + stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; + rkcif_stop_dma_capture(stream); + } + active_buf->dbufs.is_switch = true; + if ((priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id != 1) || + (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id != 2)) { + rkcif_store_last_buf_for_online(stream, active_buf); + stream->is_change_toisp = true; + } } spin_unlock_irqrestore(&stream->vbq_lock, flags); active_buf->dbufs.sequence = stream->frame_idx - 1; active_buf->dbufs.timestamp = stream->readout.fs_timestamp; stream->last_frame_idx = stream->frame_idx; - rkcif_s_rx_buffer(stream->cifdev, &active_buf->dbufs); + if (stream->cifdev->hdr.hdr_mode == NO_HDR) + rkcif_s_rx_buffer(stream->cifdev, &active_buf->dbufs); + else + rkcif_rdbk_frame_end_toisp(stream, active_buf); stream->buf_num_toisp--; } } @@ -7574,8 +7747,8 @@ static void rkcif_update_stream(struct rkcif_device *cif_dev, } static void rkcif_update_stream_toisp(struct rkcif_device *cif_dev, - struct rkcif_stream *stream, - int mipi_id) + struct rkcif_stream *stream, + int mipi_id) { if (stream->frame_phase == (CIF_CSI_FRAME0_READY | CIF_CSI_FRAME1_READY)) { @@ -7598,8 +7771,6 @@ static void rkcif_update_stream_toisp(struct rkcif_device *cif_dev, rkcif_assign_new_buffer_pingpong_toisp(stream, RKCIF_YUV_ADDR_STATE_UPDATE, mipi_id); - else - rkcif_update_new_buffer_wake_up_mode_rdbk(stream); } static u32 rkcif_get_sof(struct rkcif_device *cif_dev) @@ -7639,7 +7810,7 @@ static void rkcif_set_sof(struct rkcif_device *cif_dev, u32 seq) } static int rkcif_do_reset_work(struct rkcif_device *cif_dev, - enum rkmodule_reset_src reset_src) + enum rkmodule_reset_src reset_src) { struct rkcif_pipeline *p = &cif_dev->pipe; struct rkcif_stream *stream = NULL; @@ -8237,6 +8408,18 @@ static void rkcif_detect_wake_up_mode_change(struct rkcif_stream *stream) } if (stream->is_line_wake_up) { rkcif_modify_line_int(stream, true); + if (cif_dev->hdr.hdr_mode == HDR_X2) { + cif_dev->stream[0].is_line_wake_up = true; + cif_dev->stream[0].is_line_inten = true; + cif_dev->stream[0].line_int_cnt = stream->line_int_cnt; + } else if (cif_dev->hdr.hdr_mode == HDR_X3) { + cif_dev->stream[0].is_line_wake_up = true; + cif_dev->stream[1].is_line_wake_up = true; + cif_dev->stream[0].is_line_inten = true; + cif_dev->stream[1].is_line_inten = true; + cif_dev->stream[0].line_int_cnt = stream->line_int_cnt; + cif_dev->stream[1].line_int_cnt = stream->line_int_cnt; + } stream->is_line_inten = true; } } @@ -8514,7 +8697,8 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, if (stream->cifdev->rdbk_debug && stream->frame_idx < 15) v4l2_info(&priv->cif_dev->v4l2_dev, - "toisp fe %d\n", + "stream[%d] toisp fe %d\n", + stream->id, stream->frame_idx - 1); if (stream->to_en_dma) @@ -8551,7 +8735,8 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, if (stream->cifdev->rdbk_debug && stream->frame_idx < 15) v4l2_info(&priv->cif_dev->v4l2_dev, - "toisp sof seq %d\n", + "stream[%d] toisp sof seq %d\n", + stream->id, stream->frame_idx - 1); switch (ch) { case RKCIF_TOISP_CH0: @@ -8719,9 +8904,11 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) if (!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode) detect_stream->frame_idx++; if (detect_stream->cifdev->rdbk_debug && - detect_stream->frame_idx < 15) + detect_stream->frame_idx < 15 && + (!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode)) v4l2_info(&cif_dev->v4l2_dev, - "sof %d %lld\n", + "stream[%d] sof %d %lld\n", + detect_stream->id, detect_stream->frame_idx - 1, ktime_get_ns()); } @@ -8886,9 +9073,11 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) break; } if (stream->cifdev->rdbk_debug && - stream->frame_idx < 15) + stream->frame_idx < 15 && + (!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode)) v4l2_info(&cif_dev->v4l2_dev, - "fe %d, phase %d, %lld\n", + "stream[%d] fe %d, phase %d, %lld\n", + stream->id, stream->frame_idx - 1, stream->frame_phase, ktime_get_ns()); @@ -8907,8 +9096,15 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) rkcif_modify_frame_skip_config(stream); } else if (stream->dma_en & RKCIF_DMAEN_BY_ISP) { rkcif_update_stream_toisp(cif_dev, stream, mipi_id); - } else if (stream->is_change_toisp) { - sditf_change_to_online(cif_dev->sditf[0]); + } + 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 + sditf_change_to_online(cif_dev->sditf[0]); } spin_lock_irqsave(&stream->vbq_lock, flags); diff --git a/drivers/media/platform/rockchip/cif/common.c b/drivers/media/platform/rockchip/cif/common.c index d9493b2adf6c..76a4d1ade82b 100644 --- a/drivers/media/platform/rockchip/cif/common.c +++ b/drivers/media/platform/rockchip/cif/common.c @@ -345,6 +345,8 @@ int rkcif_alloc_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffe void rkcif_free_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffer *buf) { struct rkcif_dummy_buffer *dummy = &buf->dummy; + struct media_pad *pad = NULL; + struct v4l2_subdev *sd; if (buf->dummy.is_free) return; @@ -353,7 +355,26 @@ void rkcif_free_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffe v4l2_info(&dev->v4l2_dev, "free reserved mem addr 0x%x\n", (u32)dummy->dma_addr); - + if (dev->sditf[0]) { + if (dev->sditf[0]->is_combine_mode) + pad = media_entity_remote_pad(&dev->sditf[0]->pads[1]); + else + pad = media_entity_remote_pad(&dev->sditf[0]->pads[0]); + } else { + v4l2_info(&dev->v4l2_dev, + "not find sditf\n"); + return; + } + if (pad) { + sd = media_entity_to_v4l2_subdev(pad->entity); + } else { + v4l2_info(&dev->v4l2_dev, + "not find remote pad\n"); + return; + } + if (buf->dbufs.is_init) + v4l2_subdev_call(sd, core, ioctl, + RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs); if (dummy->is_need_vaddr) dummy->dbuf->ops->vunmap(dummy->dbuf, dummy->vaddr); #ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 0c6cc783d5a1..58fbc4682795 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -795,6 +795,7 @@ struct rkcif_device { bool can_be_reset; struct rkmodule_hdr_cfg hdr; struct rkcif_buffer *rdbk_buf[RDBK_MAX]; + struct rkcif_rx_buffer *rdbk_rx_buf[RDBK_MAX]; struct rkcif_luma_vdev luma_vdev; struct rkcif_lvds_subdev lvds_subdev; struct rkcif_dvp_sof_subdev dvp_sof_subdev; diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 432119127fad..847da7af7875 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -215,14 +215,31 @@ static int sditf_init_buf(struct sditf_priv *priv) int ret = 0; if (priv->hdr_cfg.hdr_mode == HDR_X2) { - ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num); - if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) - ret = rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num); + if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { + if (cif_dev->is_thunderboot) + cif_dev->resmem_size /= 2; + ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num); + if (cif_dev->is_thunderboot) + cif_dev->resmem_pa += cif_dev->resmem_size; + ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num); + } else { + ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num); + } } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { - ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num); - ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num); - if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) - ret = rkcif_init_rx_buf(&cif_dev->stream[2], priv->buf_num); + if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { + if (cif_dev->is_thunderboot) + cif_dev->resmem_size /= 3; + ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num); + if (cif_dev->is_thunderboot) + cif_dev->resmem_pa += cif_dev->resmem_size; + ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num); + if (cif_dev->is_thunderboot) + cif_dev->resmem_pa += cif_dev->resmem_size; + ret |= rkcif_init_rx_buf(&cif_dev->stream[2], priv->buf_num); + } else { + ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num); + ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num); + } } else { if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num); @@ -246,6 +263,7 @@ static void sditf_free_buf(struct sditf_priv *priv) } else { rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num); } + cif_dev->is_thunderboot = false; } static int sditf_get_selection(struct v4l2_subdev *sd, @@ -515,6 +533,10 @@ void sditf_change_to_online(struct sditf_priv *priv) } if (priv->hdr_cfg.hdr_mode == NO_HDR) rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num); + else if (priv->hdr_cfg.hdr_mode == HDR_X2) + rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num); + else if (priv->hdr_cfg.hdr_mode == HDR_X3) + rkcif_free_rx_buf(&cif_dev->stream[2], priv->buf_num); } static int sditf_start_stream(struct sditf_priv *priv) @@ -696,7 +718,9 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, stream->last_rx_buf_idx = dbufs->sequence + 1; if (!list_empty(&stream->rx_buf_head) && - cif_dev->is_thunderboot) { + cif_dev->is_thunderboot && + (dbufs->type == BUF_SHORT || + (dbufs->type != BUF_SHORT && (!dbufs->is_switch)))) { spin_lock_irqsave(&cif_dev->buffree_lock, buffree_flags); list_add_tail(&rx_buf->list_free, &priv->buf_free_list); spin_unlock_irqrestore(&cif_dev->buffree_lock, buffree_flags); @@ -704,7 +728,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, is_free = true; } - if (!is_free) { + if (!is_free && (!dbufs->is_switch)) { list_add_tail(&rx_buf->list, &stream->rx_buf_head); rkcif_assign_check_buffer_update_toisp(stream); if (cif_dev->rdbk_debug) { @@ -724,7 +748,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, } } - if (dbufs->is_switch) { + if (dbufs->is_switch && dbufs->type == BUF_SHORT) { if (stream->is_in_vblank) sditf_change_to_online(priv); else @@ -751,10 +775,10 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, if (cif_dev->rdbk_debug && dbufs->sequence < 15) v4l2_info(&cif_dev->v4l2_dev, - "%s, isp runtime %d, line time %d, early_line %d, line_intr_cnt %d, seq %d, dma_addr %x\n", + "%s, isp runtime %d, line time %d, early_line %d, line_intr_cnt %d, seq %d, type %d, dma_addr %x\n", __func__, dbufs->runtime_us, cif_dev->sensor_linetime, cif_dev->early_line, cif_dev->wait_line_cache, - dbufs->sequence, (u32)rx_buf->dummy.dma_addr); + dbufs->sequence, dbufs->type, (u32)rx_buf->dummy.dma_addr); } else { if (dbufs->runtime_us < cif_dev->isp_runtime_max) { cif_dev->isp_runtime_max = dbufs->runtime_us; @@ -772,8 +796,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, if (cif_dev->rdbk_debug && dbufs->sequence < 15) v4l2_info(&cif_dev->v4l2_dev, - "isp runtime %d, seq %d, early_line %d, dma addr %x\n", - dbufs->runtime_us, dbufs->sequence, + "isp runtime %d, seq %d, type %d, early_line %d, dma addr %x\n", + dbufs->runtime_us, dbufs->sequence, dbufs->type, cif_dev->early_line, (u32)rx_buf->dummy.dma_addr); } return 0; From fb8b382053e1af2bee02f620c74425750361d818 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Thu, 29 Sep 2022 14:20:23 +0800 Subject: [PATCH 167/204] media: rockchip: vicap fixed bug for hdr online mode to capture raw 1. fixed bug caysed by commit 75dc121c3a61 2. enable dma capture in fs intr, otherwise, if enable during vblank will cause VICAP to use the buffer address of last runtime, but the buffer is released. Fixes: 75dc121c3a61 ("media: rockchip: vicap support wake up buffer with mode of rdbk by isp driver") Signed-off-by: Zefa Chen Change-Id: I51d6e0aaf513dc1e5039980e7643faa7505c271b --- drivers/media/platform/rockchip/cif/capture.c | 61 +++++++++++++------ 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 7dc2767df0b2..7620570967d2 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -1434,7 +1434,9 @@ static void rkcif_rx_buffer_free(struct rkcif_stream *stream) while (!list_empty(&stream->rx_buf_head_vicap)) { dbufs = list_first_entry(&stream->rx_buf_head_vicap, struct rkisp_rx_buf, list); - v4l2_subdev_call(sd, core, ioctl, RKISP_VICAP_CMD_RX_BUFFER_FREE, dbufs); + if (dbufs->is_init) + v4l2_subdev_call(sd, core, ioctl, + RKISP_VICAP_CMD_RX_BUFFER_FREE, dbufs); dma_buf_put(dbufs->dbuf); list_del(&dbufs->list); kfree(dbufs); @@ -1751,6 +1753,8 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, if (stream->lack_buf_cnt) stream->lack_buf_cnt--; } else { + if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) + goto out_get_buf; if (stream->lack_buf_cnt < 2) stream->lack_buf_cnt++; if (dev->dummy_buf.vaddr) { @@ -1778,7 +1782,7 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, stream->id, (u32)stream->next_buf_toisp->dummy.dma_addr); } - if (priv && priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO && active_buf) { + if (active_buf) { if (stream->frame_idx == 1) active_buf->dbufs.is_first = true; active_buf->dbufs.sequence = stream->frame_idx - 1; @@ -1798,6 +1802,7 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, } out_get_buf: + stream->frame_phase_cache = stream->frame_phase; if (buffer) { rkcif_write_register(dev, frm_addr_y, buffer->dummy.dma_addr); @@ -1808,7 +1813,8 @@ out_get_buf: stream->id, stream->frame_idx - 1, frm_addr_y, (u32)buffer->dummy.dma_addr); - } else if (dev->dummy_buf.vaddr) { + } else if (dev->dummy_buf.vaddr && priv && + priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { rkcif_write_register(dev, frm_addr_y, dev->dummy_buf.dma_addr); } @@ -2156,6 +2162,9 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream, if (stream->curr_buf) { list_del(&stream->curr_buf->queue); buffer = stream->curr_buf; + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, + "stream[%d] update curr_buf 0x%x\n", + stream->id, buffer->buff_addr[0]); } } else if (stream->frame_phase == CIF_CSI_FRAME1_READY) { if (!stream->next_buf) @@ -2174,6 +2183,9 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream, if (stream->next_buf) { list_del(&stream->next_buf->queue); buffer = stream->next_buf; + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, + "stream[%d] update next_buf 0x%x\n", + stream->id, buffer->buff_addr[0]); } } } @@ -2234,13 +2246,13 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream, dbuf = stream->curr_buf->dbuf; if (dbuf) { - list_for_each_entry(dbufs, &stream->rx_buf_head_vicap, list) + list_for_each_entry(dbufs, &stream->rx_buf_head_vicap, list) { if (dbufs->dbuf == dbuf) break; - } else { - dbufs = &stream->curr_buf_toisp->dbufs; + } } - rkcif_s_rx_buffer(dev, dbufs); + if (dbufs) + rkcif_s_rx_buffer(dev, dbufs); stream->buf_num_toisp--; } } else { @@ -2314,12 +2326,16 @@ stop_dma: } else { dbufs = &stream->curr_buf_toisp->dbufs; } - rkcif_s_rx_buffer(dev, dbufs); + if (dbufs) + rkcif_s_rx_buffer(dev, dbufs); stream->buf_num_toisp--; - if (stream->frame_phase == CIF_CSI_FRAME0_READY) { + + if (stream->frame_phase == CIF_CSI_FRAME0_READY && + stream->curr_buf) { list_add_tail(&stream->curr_buf->queue, &stream->buf_head); stream->curr_buf = NULL; - } else { + } else if (stream->frame_phase == CIF_CSI_FRAME1_READY && + stream->next_buf) { list_add_tail(&stream->next_buf->queue, &stream->buf_head); stream->next_buf = NULL; } @@ -3335,7 +3351,6 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode (!stream->dma_en)) stream->to_en_dma = RKCIF_DMAEN_BY_ISP; } - rkcif_enable_dma_capture(stream, false); } } if (stream->state != RKCIF_STATE_STREAMING) { @@ -3690,8 +3705,8 @@ void rkcif_buf_queue(struct vb2_buffer *vb) stream->lack_buf_cnt) rkcif_check_buffer_update_pingpong(stream, stream->id); v4l2_dbg(2, rkcif_debug, &stream->cifdev->v4l2_dev, - "stream[%d] buf queue, index: %d\n", - stream->id, vb->index); + "stream[%d] buf queue, index: %d, dma_addr 0x%x\n", + stream->id, vb->index, cifbuf->buff_addr[0]); } void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num) @@ -4114,8 +4129,12 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, rkcif_release_rdbk_buf(stream); rkcif_rx_buffer_free(stream); - list_for_each_entry(buf, &stream->buf_head, queue) + list_for_each_entry(buf, &stream->buf_head, queue) { + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, + "stream[%d] buf return addr 0x%x\n", + stream->id, buf->buff_addr[0]); vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } INIT_LIST_HEAD(&stream->buf_head); stream->lack_buf_cnt = 0; stream->dma_en &= ~RKCIF_DMAEN_BY_VICAP; @@ -8701,12 +8720,6 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, stream->id, stream->frame_idx - 1); - if (stream->to_en_dma) - rkcif_enable_dma_capture(stream, false); - if (stream->to_en_scale) { - stream->to_en_scale = false; - rkcif_scale_start(stream->scale_vdev); - } switch (ch) { case RKCIF_TOISP_CH0: val = TOISP_END_CH0(index); @@ -8738,6 +8751,12 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, "stream[%d] toisp sof seq %d\n", stream->id, stream->frame_idx - 1); + if (stream->to_en_dma) + rkcif_enable_dma_capture(stream, false); + if (stream->to_en_scale) { + stream->to_en_scale = false; + rkcif_scale_start(stream->scale_vdev); + } switch (ch) { case RKCIF_TOISP_CH0: val = TOISP_FS_CH0(index); @@ -9158,6 +9177,8 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) if (!ret) stream->is_finish_stop_dma = true; } + if (stream->to_en_dma) + rkcif_enable_dma_capture(stream, false); } if (intstat & CSI_LINE_INTSTAT_V1(i)) { stream = &cif_dev->stream[i]; From 48db713cf46330d24b80c7138d6edf82a0f46083 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Thu, 29 Sep 2022 10:59:56 +0800 Subject: [PATCH 168/204] drm/rockchip: vop2: fix win disable failed Before this commit the following scenario maybe disable win failed: -> disable win and config done -> vop fs coming, this time win state is disabled. -> enable win and config done -> disable win[the fs haven't come yes, so win state is disabled, this will skip to disable win and lead to disable win failed] ->fs coming, this time win state is still enabled. so we add judge win backup register state to avoid disable win failed. Signed-off-by: Sandy Huang Change-Id: Ie08aa141616291fc900313d99fbc07622b5d1a83 --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 863cb206d0a7..c521ff929774 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -118,6 +118,9 @@ #define VOP_WIN_GET(vop2, win, name) \ vop2_read_reg(vop2, win->offset, &VOP_WIN_NAME(win, name)) +#define VOP_WIN_GET_REG_BAK(vop2, win, name) \ + vop2_read_reg_bak(vop2, win->offset, &VOP_WIN_NAME(win, name)) + #define VOP_WIN_NAME(win, name) \ (vop2_get_win_regs(win, &win->regs->name)->name) @@ -893,6 +896,12 @@ static inline uint32_t vop2_read_reg(struct vop2 *vop2, uint32_t base, return (vop2_readl(vop2, base + reg->offset) >> reg->shift) & reg->mask; } +static inline uint32_t vop2_read_reg_bak(struct vop2 *vop2, uint32_t base, + const struct vop_reg *reg) +{ + return (vop2->regsbak[(base + reg->offset) >> 2] >> reg->shift) & reg->mask; +} + static inline uint32_t vop2_read_grf_reg(struct regmap *regmap, const struct vop_reg *reg) { return (vop2_grf_readl(regmap, reg) >> reg->shift) & reg->mask; @@ -1665,7 +1674,7 @@ static void vop2_win_disable(struct vop2_win *win, bool skip_splice_win) win->splice_win = NULL; } - if (VOP_WIN_GET(vop2, win, enable)) { + if (VOP_WIN_GET(vop2, win, enable) || VOP_WIN_GET_REG_BAK(vop2, win, enable)) { VOP_WIN_SET(vop2, win, enable, 0); if (win->feature & WIN_FEATURE_CLUSTER_MAIN) { struct vop2_win *sub_win; From fefa0e0325498f1ba5be0d8ed170015a851c1373 Mon Sep 17 00:00:00 2001 From: ZiHan Huang Date: Wed, 28 Sep 2022 20:56:23 +0800 Subject: [PATCH 169/204] arm64: dts: rockchip: rk3588-evb1-lp4-v10-ipc-6x-linux.dts: open hdmi0 node Signed-off-by: ZiHan Huang Change-Id: I00e2bbd7404b4474a061907cb41bd757223ce0f8 --- .../rk3588-evb1-lp4-v10-ipc-6x-linux.dts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-ipc-6x-linux.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-ipc-6x-linux.dts index 4ee88903c50f..2dcef191fc6b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-ipc-6x-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-ipc-6x-linux.dts @@ -67,18 +67,6 @@ status = "disabled"; }; -&hdmi0 { - status = "disabled"; -}; - -&hdmi0_in_vp0 { - status = "disabled"; -}; - -&hdmi0_sound { - status = "disabled"; -}; - &hdmi1 { status = "disabled"; }; @@ -91,10 +79,6 @@ status = "disabled"; }; -&hdptxphy_hdmi0 { - status = "disabled"; -}; - &hdptxphy_hdmi1 { status = "disabled"; }; From d8b6c8e1f737a036238b8db86d9ef2202c849a65 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Wed, 25 May 2022 19:24:37 +0800 Subject: [PATCH 170/204] drm/rockchip: delay destroy logo fb Some NVR product want skip-ref-fb, destroy logo fb after some delay to make sure the plane is disabled. Signed-off-by: Andy Yan Change-Id: Ia257a510ea2382b5ee6aa4f65b2fef856687b0bc --- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 25 ++++++++++++++++++++-- drivers/gpu/drm/rockchip/rockchip_drm_fb.h | 4 ++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 308e453bc955..e442befd850c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -26,7 +26,7 @@ static bool is_rockchip_logo_fb(struct drm_framebuffer *fb) return fb->flags & ROCKCHIP_DRM_MODE_LOGO_FB ? true : false; } -static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb) +static void __rockchip_drm_fb_destroy(struct drm_framebuffer *fb) { int i = 0; @@ -49,6 +49,27 @@ static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb) } } +static void rockchip_drm_fb_destroy_work(struct work_struct *work) +{ + struct rockchip_drm_logo_fb *fb; + + fb = container_of(to_delayed_work(work), struct rockchip_drm_logo_fb, destroy_work); + + __rockchip_drm_fb_destroy(&fb->fb); +} + +static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb) +{ + + if (is_rockchip_logo_fb(fb)) { + struct rockchip_drm_logo_fb *rockchip_logo_fb = to_rockchip_logo_fb(fb); + + schedule_delayed_work(&rockchip_logo_fb->destroy_work, HZ); + } else { + __rockchip_drm_fb_destroy(fb); + } +} + static int rockchip_drm_gem_fb_create_handle(struct drm_framebuffer *fb, struct drm_file *file, unsigned int *handle) @@ -123,7 +144,7 @@ rockchip_drm_logo_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 rockchip_logo_fb->rk_obj.dma_addr = logo->dma_addr; rockchip_logo_fb->rk_obj.kvaddr = logo->kvaddr; logo->count++; - + INIT_DELAYED_WORK(&rockchip_logo_fb->destroy_work, rockchip_drm_fb_destroy_work); return &rockchip_logo_fb->fb; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.h b/drivers/gpu/drm/rockchip/rockchip_drm_fb.h index e5577c2bb7c0..4442719270ab 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.h @@ -31,6 +31,10 @@ struct rockchip_drm_logo_fb { struct drm_framebuffer fb; struct rockchip_logo *logo; struct rockchip_gem_object rk_obj; + /* + * Used for delayed logo fb release + */ + struct delayed_work destroy_work; }; #endif /* _ROCKCHIP_DRM_FB_H */ From 0d01ed0d12b7f29908f3b072e6c559b4ae294077 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Fri, 30 Sep 2022 10:22:07 +0800 Subject: [PATCH 171/204] arm64: dts: rockchip: rk3588: set pcfg_pull_up for touch int pin This patch can save 0.6mA for PMUIO2(3V3). Tested on RK3588_EVB1_LP4_V10 platform. Change-Id: If9298b7de5859e8bfd28baf3e1022b71efd78218 Signed-off-by: Liang Chen --- arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3588-toybrick-edp-x0.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3588s-evb2-lp5.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3588s-tablet-rk806-single.dtsi | 2 +- arch/arm64/boot/dts/rockchip/rk3588s-tablet.dtsi | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi index e41782fa3618..d7708b7f9005 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi @@ -627,7 +627,7 @@ touch_gpio: touch-gpio { rockchip,pins = <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>, - <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi index a9962e37122c..37d7bdfe5706 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi @@ -419,7 +419,7 @@ touch_gpio: touch-gpio { rockchip,pins = <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>, - <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi index 05507d4a5dc4..ef5dd89975c4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi @@ -381,7 +381,7 @@ touch_gpio: touch-gpio { rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>, - <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4.dtsi index 53c30e532694..96b7406c9b3a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4.dtsi @@ -416,7 +416,7 @@ touch_gpio: touch-gpio { rockchip,pins = <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>, - <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-edp-x0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-edp-x0.dtsi index 440d5866e4f4..9f8768cec79e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-edp-x0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-edp-x0.dtsi @@ -647,7 +647,7 @@ touch_gpio: touch-gpio { rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>, - <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dtsi index b68b407e0147..ea8cab776e77 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dtsi @@ -613,7 +613,7 @@ touch_gpio: touch-gpio { rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>, - <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb2-lp5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-evb2-lp5.dtsi index fd97039080b7..263bdfe3bd70 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-evb2-lp5.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb2-lp5.dtsi @@ -890,7 +890,7 @@ touch_gpio: touch-gpio { rockchip,pins = <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, - <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; + <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi index cf031ef2ec10..cfdbcae8cbe8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi @@ -251,7 +251,7 @@ touch_gpio: touch-gpio { rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, - <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi index 5862e2fefe82..d61d365c80dc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi @@ -686,7 +686,7 @@ touch_gpio: touch-gpio { rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, - <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-tablet-rk806-single.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-tablet-rk806-single.dtsi index ceae180041eb..4357661eac4c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-tablet-rk806-single.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-tablet-rk806-single.dtsi @@ -1457,7 +1457,7 @@ touch_gpio: touch-gpio { rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, - <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-tablet.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-tablet.dtsi index 59fad2df04b2..21c5e721d4cc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-tablet.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-tablet.dtsi @@ -920,7 +920,7 @@ touch_gpio: touch-gpio { rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, - <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; }; }; From 73635093a15ac91cfb486f7e3db26a0b69e7ea53 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Tue, 23 Aug 2022 15:04:47 +0800 Subject: [PATCH 172/204] pcie-dma-trx: update to version 0x4 1.Optimize DMA hook to support multiple independent DMA channels 2.Add interrupt callback to support multiple independent DMA channels Change-Id: I42a638a4cb9fa61ebc1cd51d4e9f6d6942715fd1 Signed-off-by: Jon Lin --- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 102 +++++++----------- drivers/pci/controller/pcie-rockchip-host.c | 4 +- drivers/pci/controller/rockchip-pcie-dma.c | 31 +++++- drivers/pci/controller/rockchip-pcie-dma.h | 3 +- 4 files changed, 70 insertions(+), 70 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index ec9489fa4e07..5a87275499fa 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -87,6 +87,8 @@ enum rk_pcie_device_mode { #define PCIE_DMA_RD_INT_MASK 0xa8 #define PCIE_DMA_RD_INT_CLEAR 0xac +#define PCIE_DMA_CHANEL_MAX_NUM 2 + /* Parameters for the waiting for iATU enabled routine */ #define LINK_WAIT_IATU_MIN 9000 #define LINK_WAIT_IATU_MAX 10000 @@ -1330,10 +1332,9 @@ static int rk_pcie_reset_grant_ctrl(struct rk_pcie *rk_pcie, return ret; } -static void rk_pcie_start_dma_rd(struct dma_trx_obj *obj, int ctr_off) +static void rk_pcie_start_dma_rd(struct dma_trx_obj *obj, struct dma_table *cur, int ctr_off) { struct rk_pcie *rk_pcie = dev_get_drvdata(obj->dev); - struct dma_table *cur = obj->cur; dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB, cur->enb.asdword); @@ -1355,10 +1356,9 @@ static void rk_pcie_start_dma_rd(struct dma_trx_obj *obj, int ctr_off) cur->start.asdword); } -static void rk_pcie_start_dma_wr(struct dma_trx_obj *obj, int ctr_off) +static void rk_pcie_start_dma_wr(struct dma_trx_obj *obj, struct dma_table *cur, int ctr_off) { struct rk_pcie *rk_pcie = dev_get_drvdata(obj->dev); - struct dma_table *cur = obj->cur; dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB, cur->enb.asdword); @@ -1382,17 +1382,17 @@ static void rk_pcie_start_dma_wr(struct dma_trx_obj *obj, int ctr_off) cur->start.asdword); } -static void rk_pcie_start_dma_dwc(struct dma_trx_obj *obj) +static void rk_pcie_start_dma_dwc(struct dma_trx_obj *obj, struct dma_table *table) { - int dir = obj->cur->dir; - int chn = obj->cur->chn; + int dir = table->dir; + int chn = table->chn; int ctr_off = PCIE_DMA_OFFSET + chn * 0x200; if (dir == DMA_FROM_BUS) - rk_pcie_start_dma_rd(obj, ctr_off); + rk_pcie_start_dma_rd(obj, table, ctr_off); else if (dir == DMA_TO_BUS) - rk_pcie_start_dma_wr(obj, ctr_off); + rk_pcie_start_dma_wr(obj, table, ctr_off); } static void rk_pcie_config_dma_dwc(struct dma_table *table) @@ -1419,76 +1419,50 @@ static void rk_pcie_config_dma_dwc(struct dma_table *table) table->start.chnl = table->chn; } -static inline void -rk_pcie_handle_dma_interrupt(struct rk_pcie *rk_pcie) -{ - struct dma_trx_obj *obj = rk_pcie->dma_obj; - struct dma_table *cur; - - if (!obj) - return; - - cur = obj->cur; - if (!cur) { - pr_err("no pcie dma table\n"); - return; - } - - obj->dma_free = true; - obj->irq_num++; - - if (cur->dir == DMA_TO_BUS) { - if (list_empty(&obj->tbl_list)) { - if (obj->dma_free && - obj->loop_count >= obj->loop_count_threshold) - complete(&obj->done); - } - } -} - static irqreturn_t rk_pcie_sys_irq_handler(int irq, void *arg) { struct rk_pcie *rk_pcie = arg; - u32 chn = 0; + u32 chn; union int_status status; union int_clear clears; u32 reg, val; status.asdword = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS); + for (chn = 0; chn < PCIE_DMA_CHANEL_MAX_NUM; chn++) { + if (status.donesta & BIT(chn)) { + clears.doneclr = 0x1 << chn; + dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + + PCIE_DMA_WR_INT_CLEAR, clears.asdword); + if (rk_pcie->dma_obj && rk_pcie->dma_obj->cb) + rk_pcie->dma_obj->cb(rk_pcie->dma_obj, chn, DMA_TO_BUS); + } - if (rk_pcie->dma_obj && rk_pcie->dma_obj->cur) - chn = rk_pcie->dma_obj->cur->chn; - - if (status.donesta & BIT(chn)) { - clears.doneclr = 0x1 << chn; - dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + - PCIE_DMA_WR_INT_CLEAR, clears.asdword); - rk_pcie_handle_dma_interrupt(rk_pcie); - } - - if (status.abortsta & BIT(chn)) { - dev_err(rk_pcie->pci->dev, "%s, abort\n", __func__); - clears.abortclr = 0x1 << chn; - dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + - PCIE_DMA_WR_INT_CLEAR, clears.asdword); + if (status.abortsta & BIT(chn)) { + dev_err(rk_pcie->pci->dev, "%s, abort\n", __func__); + clears.abortclr = 0x1 << chn; + dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + + PCIE_DMA_WR_INT_CLEAR, clears.asdword); + } } status.asdword = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS); + for (chn = 0; chn < PCIE_DMA_CHANEL_MAX_NUM; chn++) { + if (status.donesta & BIT(chn)) { + clears.doneclr = 0x1 << chn; + dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + + PCIE_DMA_RD_INT_CLEAR, clears.asdword); + if (rk_pcie->dma_obj && rk_pcie->dma_obj->cb) + rk_pcie->dma_obj->cb(rk_pcie->dma_obj, chn, DMA_FROM_BUS); + } - if (status.donesta & BIT(chn)) { - clears.doneclr = 0x1 << chn; - dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + - PCIE_DMA_RD_INT_CLEAR, clears.asdword); - rk_pcie_handle_dma_interrupt(rk_pcie); - } - - if (status.abortsta & BIT(chn)) { - dev_err(rk_pcie->pci->dev, "%s, abort\n", __func__); - clears.abortclr = 0x1 << chn; - dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + - PCIE_DMA_RD_INT_CLEAR, clears.asdword); + if (status.abortsta & BIT(chn)) { + dev_err(rk_pcie->pci->dev, "%s, abort\n", __func__); + clears.abortclr = 0x1 << chn; + dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + + PCIE_DMA_RD_INT_CLEAR, clears.asdword); + } } reg = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC); diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c index 8d273c1c7c13..c6fcbcbc7291 100644 --- a/drivers/pci/controller/pcie-rockchip-host.c +++ b/drivers/pci/controller/pcie-rockchip-host.c @@ -40,10 +40,10 @@ #include "pcie-rockchip.h" #include "rockchip-pcie-dma.h" -static void rk_pcie_start_dma_rk3399(struct dma_trx_obj *obj) +static void rk_pcie_start_dma_rk3399(struct dma_trx_obj *obj, struct dma_table *cur) { struct rockchip_pcie *rockchip = dev_get_drvdata(obj->dev); - struct dma_table *tbl = obj->cur; + struct dma_table *tbl = cur; int chn = tbl->chn; rockchip_pcie_write(rockchip, (u32)(tbl->phys_descs & 0xffffffff), diff --git a/drivers/pci/controller/rockchip-pcie-dma.c b/drivers/pci/controller/rockchip-pcie-dma.c index 458f012c2ddd..6ffd33514095 100644 --- a/drivers/pci/controller/rockchip-pcie-dma.c +++ b/drivers/pci/controller/rockchip-pcie-dma.c @@ -154,6 +154,30 @@ static unsigned int rk_pcie_check_sum(unsigned int *src, int size) return result; } +static int rk_pcie_handle_dma_interrupt(struct dma_trx_obj *obj, u32 chn, enum dma_dir dir) +{ + struct dma_table *cur; + + cur = obj->cur; + if (!cur) { + pr_err("no pcie dma table\n"); + return 0; + } + + obj->dma_free = true; + obj->irq_num++; + + if (cur->dir == DMA_TO_BUS) { + if (list_empty(&obj->tbl_list)) { + if (obj->dma_free && + obj->loop_count >= obj->loop_count_threshold) + complete(&obj->done); + } + } + + return 0; +} + static void rk_pcie_prepare_dma(struct dma_trx_obj *obj, unsigned int idx, unsigned int bus_idx, unsigned int local_idx, size_t buf_size, @@ -295,7 +319,7 @@ static void rk_pcie_dma_trx_work(struct work_struct *work) return; } reinit_completion(&obj->done); - obj->start_dma_func(obj); + obj->start_dma_func(obj, table); } } } @@ -483,7 +507,7 @@ static void rk_pcie_send_addr_to_remote(struct dma_trx_obj *obj) table->chn = PCIE_DMA_DEFAULT_CHN; obj->config_dma_func(table); obj->cur = table; - obj->start_dma_func(obj); + obj->start_dma_func(obj, table); } static long rk_pcie_misc_ioctl(struct file *filp, unsigned int cmd, @@ -940,8 +964,9 @@ struct dma_trx_obj *rk_pcie_dma_obj_probe(struct device *dev) obj->irq_num = 0; obj->loop_count_threshold = 0; obj->ref_count = 0; - obj->version = 0x3; + obj->version = 0x4; init_completion(&obj->done); + obj->cb = rk_pcie_handle_dma_interrupt; mutex_init(&obj->count_mutex); rk_pcie_add_misc(obj); diff --git a/drivers/pci/controller/rockchip-pcie-dma.h b/drivers/pci/controller/rockchip-pcie-dma.h index 01f41947dac4..8ac55f021025 100644 --- a/drivers/pci/controller/rockchip-pcie-dma.h +++ b/drivers/pci/controller/rockchip-pcie-dma.h @@ -188,8 +188,9 @@ struct dma_trx_obj { unsigned long irq_num; struct dentry *pcie_root; struct pcie_misc_dev *pcie_dev; - void (*start_dma_func)(struct dma_trx_obj *obj); + void (*start_dma_func)(struct dma_trx_obj *obj, struct dma_table *table); void (*config_dma_func)(struct dma_table *table); + int (*cb)(struct dma_trx_obj *obj, u32 chn, enum dma_dir dir); ktime_t begin; ktime_t end; u64 cache_time_total; From 533492f3b55bcbd29db7ef8b8384f4b34c9c6548 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Mon, 22 Aug 2022 19:55:23 +0800 Subject: [PATCH 173/204] PCI: rockchip: dw: Add dmatest Test code of embedded DMA design based on dwc controller. Show the controller registered with dmatest, and you can assigned the correspond test_dev for test: echo show > ./sys/module/pcie_dw_dmatest/parameters/dmatest Check the value of the current parameter: grep -H . /sys/module/pcie_dw_dmatest/parameters/* Fix parameter and run the dmatest: echo 0 > ./sys/module/pcie_dw_dmatest/parameters/test_dev echo 1 > ./sys/module/pcie_dw_dmatest/parameters/chn_en echo 1 > ./sys/module/pcie_dw_dmatest/parameters/rw_test echo 0x100 > ./sys/module/pcie_dw_dmatest/parameters/size echo 0x1 > ./sys/module/pcie_dw_dmatest/parameters/cycles_count echo 0x3c000000 > ./sys/module/pcie_dw_dmatest/parameters/local_addr echo 0x3c000000 > ./sys/module/pcie_dw_dmatest/parameters/bus_addr echo run > ./sys/module/pcie_dw_dmatest/parameters/dmatest Change-Id: I1b48f849e5e37baec27bc62d2a8cf4945fb40cbc Signed-off-by: Jon Lin --- drivers/pci/controller/dwc/Kconfig | 7 + drivers/pci/controller/dwc/Makefile | 1 + drivers/pci/controller/dwc/pcie-dw-dmatest.c | 406 +++++++++++++++++++ drivers/pci/controller/dwc/pcie-dw-dmatest.h | 17 + 4 files changed, 431 insertions(+) create mode 100644 drivers/pci/controller/dwc/pcie-dw-dmatest.c create mode 100644 drivers/pci/controller/dwc/pcie-dw-dmatest.h diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index 29d8450912bc..90b02c763507 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -98,6 +98,13 @@ config PCIE_RK_THREADED_INIT help Enables threaded initialize Rockchip DW based PCIe controller. +config PCIE_DW_DMATEST + bool "DesignWare PCIe DMA test" + depends on PCIE_DW_ROCKCHIP + depends on !ROCKCHIP_PCIE_DMA_OBJ + help + Enables support for the DW PCIe controller DMA test. + config PCI_EXYNOS bool "Samsung Exynos PCIe controller" depends on SOC_EXYNOS5440 || COMPILE_TEST diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile index fa790f08faad..7e91eb5c4507 100644 --- a/drivers/pci/controller/dwc/Makefile +++ b/drivers/pci/controller/dwc/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_PCIE_TEGRA194) += pcie-tegra194.o obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o obj-$(CONFIG_PCIE_UNIPHIER_EP) += pcie-uniphier-ep.o obj-$(CONFIG_PCIE_DW_ROCKCHIP) += pcie-dw-rockchip.o +obj-$(CONFIG_PCIE_DW_DMATEST) += pcie-dw-dmatest.o # The following drivers are for devices that use the generic ACPI # pci_root.c driver but don't support standard ECAM config access. diff --git a/drivers/pci/controller/dwc/pcie-dw-dmatest.c b/drivers/pci/controller/dwc/pcie-dw-dmatest.c new file mode 100644 index 000000000000..f6d2cbe159b1 --- /dev/null +++ b/drivers/pci/controller/dwc/pcie-dw-dmatest.c @@ -0,0 +1,406 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcie-designware.h" +#include "pcie-dw-dmatest.h" +#include "../rockchip-pcie-dma.h" + +static int test_size = 0x20; +module_param_named(size, test_size, int, 0644); +MODULE_PARM_DESC(size, "each packet size in bytes"); + +static unsigned int cycles_count = 1; +module_param(cycles_count, uint, 0644); +MODULE_PARM_DESC(cycles_count, "how many erase cycles to do (default 1)"); + +static unsigned int chn_en = 1; +module_param(chn_en, uint, 0644); +MODULE_PARM_DESC(chn_en, "Each bits for one dma channel, up to 2 channels, (default enable channel 0)"); + +static unsigned int rw_test = 3; +module_param(rw_test, uint, 0644); +MODULE_PARM_DESC(rw_test, "Read/Write test, 1-read 2-write 3-both(default 3)"); + +static unsigned int bus_addr = 0x3c000000; +module_param(bus_addr, uint, 0644); +MODULE_PARM_DESC(bus_addr, "Dmatest chn0 bus_addr(remote), chn1 add offset 0x100000, (default 0x3c000000)"); + +static unsigned int local_addr = 0x3c000000; +module_param(local_addr, uint, 0644); +MODULE_PARM_DESC(local_addr, "Dmatest chn0 local_addr(local), chn1 add offset 0x100000, (default 0x3c000000)"); + +static unsigned int test_dev; +module_param(test_dev, uint, 0644); +MODULE_PARM_DESC(test_dev, "Choose dma_obj device,(default 0)"); + +#define PCIE_DW_MISC_DMATEST_DEV_MAX 5 + +#define PCIE_DMA_OFFSET 0x380000 + +#define PCIE_DMA_CTRL_OFF 0x8 +#define PCIE_DMA_WR_ENB 0xc +#define PCIE_DMA_WR_CTRL_LO 0x200 +#define PCIE_DMA_WR_CTRL_HI 0x204 +#define PCIE_DMA_WR_XFERSIZE 0x208 +#define PCIE_DMA_WR_SAR_PTR_LO 0x20c +#define PCIE_DMA_WR_SAR_PTR_HI 0x210 +#define PCIE_DMA_WR_DAR_PTR_LO 0x214 +#define PCIE_DMA_WR_DAR_PTR_HI 0x218 +#define PCIE_DMA_WR_WEILO 0x18 +#define PCIE_DMA_WR_WEIHI 0x1c +#define PCIE_DMA_WR_DOORBELL 0x10 +#define PCIE_DMA_WR_INT_STATUS 0x4c +#define PCIE_DMA_WR_INT_MASK 0x54 +#define PCIE_DMA_WR_INT_CLEAR 0x58 + +#define PCIE_DMA_RD_ENB 0x2c +#define PCIE_DMA_RD_CTRL_LO 0x300 +#define PCIE_DMA_RD_CTRL_HI 0x304 +#define PCIE_DMA_RD_XFERSIZE 0x308 +#define PCIE_DMA_RD_SAR_PTR_LO 0x30c +#define PCIE_DMA_RD_SAR_PTR_HI 0x310 +#define PCIE_DMA_RD_DAR_PTR_LO 0x314 +#define PCIE_DMA_RD_DAR_PTR_HI 0x318 +#define PCIE_DMA_RD_WEILO 0x38 +#define PCIE_DMA_RD_WEIHI 0x3c +#define PCIE_DMA_RD_DOORBELL 0x30 +#define PCIE_DMA_RD_INT_STATUS 0xa0 +#define PCIE_DMA_RD_INT_MASK 0xa8 +#define PCIE_DMA_RD_INT_CLEAR 0xac + +#define PCIE_DMA_CHANEL_MAX_NUM 2 + +struct pcie_dw_dmatest_dev { + struct dma_trx_obj *obj; + struct dw_pcie *pci; + + bool irq_en; + struct completion rd_done[PCIE_DMA_CHANEL_MAX_NUM]; + struct completion wr_done[PCIE_DMA_CHANEL_MAX_NUM]; + + struct mutex rd_lock[PCIE_DMA_CHANEL_MAX_NUM]; /* Corresponding to each read DMA channel */ + struct mutex wr_lock[PCIE_DMA_CHANEL_MAX_NUM]; /* Corresponding to each write DMA channel */ +}; + +static struct pcie_dw_dmatest_dev s_dmatest_dev[PCIE_DW_MISC_DMATEST_DEV_MAX]; +static int cur_dmatest_dev; + +static void pcie_dw_dmatest_show(void) +{ + int i; + + for (i = 0; i < PCIE_DW_MISC_DMATEST_DEV_MAX; i++) { + if (s_dmatest_dev[i].obj) + dev_info(s_dmatest_dev[i].obj->dev, " test_dev index %d\n", i); + else + break; + } + + dev_info(s_dmatest_dev[test_dev].obj->dev, " is current test_dev\n"); +} + +static int rk_pcie_get_dma_status(struct dw_pcie *pci, u8 chn, enum dma_dir dir) +{ + union int_status status; + union int_clear clears; + int ret = 0; + + dev_dbg(pci->dev, "%s %x %x\n", __func__, dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS), + dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS)); + + if (dir == DMA_TO_BUS) { + status.asdword = dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS); + if (status.donesta & BIT(chn)) { + clears.doneclr = 0x1 << chn; + dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_CLEAR, clears.asdword); + ret = 1; + } + + if (status.abortsta & BIT(chn)) { + dev_err(pci->dev, "%s, write abort\n", __func__); + clears.abortclr = 0x1 << chn; + dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_CLEAR, clears.asdword); + ret = -1; + } + } else { + status.asdword = dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS); + + if (status.donesta & BIT(chn)) { + clears.doneclr = 0x1 << chn; + dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_CLEAR, clears.asdword); + ret = 1; + } + + if (status.abortsta & BIT(chn)) { + dev_err(pci->dev, "%s, read abort %x\n", __func__, status.asdword); + clears.abortclr = 0x1 << chn; + dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_CLEAR, clears.asdword); + ret = -1; + } + } + + return ret; +} + +static int rk_pcie_dma_wait_for_finised(struct dma_trx_obj *obj, struct dw_pcie *pci, struct dma_table *table) +{ + int ret; + + do { + ret = rk_pcie_get_dma_status(pci, table->chn, table->dir); + } while (!ret); + + return ret; +} + +static int rk_pcie_dma_frombus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, + u32 local_paddr, u32 bus_paddr, u32 size) +{ + struct dma_table *table; + struct dma_trx_obj *obj = dmatest_dev->obj; + struct dw_pcie *pci = dmatest_dev->pci; + int ret; + + if (chn >= PCIE_DMA_CHANEL_MAX_NUM) + return -1; + + table = kzalloc(sizeof(struct dma_table), GFP_KERNEL); + if (!table) + return -ENOMEM; + + mutex_lock(&dmatest_dev->rd_lock[chn]); + if (dmatest_dev->irq_en) + reinit_completion(&dmatest_dev->rd_done[chn]); + + table->buf_size = size; + table->bus = bus_paddr; + table->local = local_paddr; + table->chn = chn; + table->dir = DMA_FROM_BUS; + + obj->config_dma_func(table); + obj->start_dma_func(obj, table); + + if (dmatest_dev->irq_en) { + ret = wait_for_completion_interruptible_timeout(&dmatest_dev->rd_done[chn], HZ); + if (ret < 0) + dev_err(obj->dev, "%s interrupted\n", __func__); + else if (ret == 0) + dev_err(obj->dev, "%s timed out\n", __func__); + } else { + ret = rk_pcie_dma_wait_for_finised(obj, pci, table); + } + mutex_unlock(&dmatest_dev->rd_lock[chn]); + + kfree(table); + + return ret; +} + +static int rk_pcie_dma_tobus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, + u32 bus_paddr, u32 local_paddr, u32 size) +{ + struct dma_table *table; + struct dma_trx_obj *obj = dmatest_dev->obj; + struct dw_pcie *pci = dmatest_dev->pci; + int ret; + + if (chn >= PCIE_DMA_CHANEL_MAX_NUM) + return -1; + + table = kzalloc(sizeof(struct dma_table), GFP_KERNEL); + if (!table) + return -ENOMEM; + + mutex_lock(&dmatest_dev->wr_lock[chn]); + if (dmatest_dev->irq_en) + reinit_completion(&dmatest_dev->wr_done[chn]); + + table->buf_size = size; + table->bus = bus_paddr; + table->local = local_paddr; + table->chn = chn; + table->dir = DMA_TO_BUS; + + obj->config_dma_func(table); + obj->start_dma_func(obj, table); + + if (dmatest_dev->irq_en) { + ret = wait_for_completion_interruptible_timeout(&dmatest_dev->wr_done[chn], HZ); + if (ret < 0) + dev_err(obj->dev, "%s interrupted\n", __func__); + else if (ret == 0) + dev_err(obj->dev, "%s timed out\n", __func__); + } else { + ret = rk_pcie_dma_wait_for_finised(obj, pci, table); + } + mutex_unlock(&dmatest_dev->wr_lock[chn]); + + kfree(table); + + return ret; +} + +static int rk_pcie_dma_interrupt_handler_call_back(struct dma_trx_obj *obj, u32 chn, enum dma_dir dir) +{ + struct pcie_dw_dmatest_dev *dmatest_dev = (struct pcie_dw_dmatest_dev *)obj->priv; + + if (chn >= PCIE_DMA_CHANEL_MAX_NUM) + return -1; + + if (dir == DMA_FROM_BUS) + complete(&dmatest_dev->rd_done[chn]); + else + complete(&dmatest_dev->wr_done[chn]); + + return 0; +} + +struct dma_trx_obj *pcie_dw_dmatest_register(struct dw_pcie *pci, bool irq_en) +{ + struct dma_trx_obj *obj; + struct pcie_dw_dmatest_dev *dmatest_dev = &s_dmatest_dev[cur_dmatest_dev]; + int i; + + obj = devm_kzalloc(pci->dev, sizeof(struct dma_trx_obj), GFP_KERNEL); + if (!obj) + return ERR_PTR(-ENOMEM); + + obj->dev = pci->dev; + obj->priv = dmatest_dev; + obj->cb = rk_pcie_dma_interrupt_handler_call_back; + + /* Save for dmatest */ + dmatest_dev->obj = obj; + dmatest_dev->pci = pci; + for (i = 0; i < PCIE_DMA_CHANEL_MAX_NUM; i++) { + init_completion(&dmatest_dev->rd_done[i]); + init_completion(&dmatest_dev->wr_done[i]); + mutex_init(&dmatest_dev->rd_lock[i]); + mutex_init(&dmatest_dev->wr_lock[i]); + } + + /* Enable IRQ transfer as default */ + dmatest_dev->irq_en = irq_en; + cur_dmatest_dev++; + + return obj; +} + +static int dma_test(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, + u32 bus_paddr, u32 local_paddr, u32 size, u32 loop, u8 rd_en, u8 wr_en) +{ + ktime_t start_time; + ktime_t end_time; + ktime_t cost_time; + u32 i; + long long total_byte; + long long us = 0; + struct dma_trx_obj *obj = dmatest_dev->obj; + + start_time = ktime_get(); + for (i = 0; i < loop; i++) { + if (rd_en) { + rk_pcie_dma_frombus(dmatest_dev, chn, local_paddr, bus_paddr, size); + dma_sync_single_for_cpu(obj->dev, local_paddr, size, DMA_FROM_DEVICE); + } + + if (wr_en) { + dma_sync_single_for_device(obj->dev, local_paddr, size, DMA_TO_DEVICE); + rk_pcie_dma_tobus(dmatest_dev, chn, bus_paddr, local_paddr, size); + } + } + end_time = ktime_get(); + cost_time = ktime_sub(end_time, start_time); + us = ktime_to_us(cost_time); + + total_byte = (wr_en + rd_en) * size * loop; /* 1 rd,1 wr */ + total_byte = total_byte * (1000000 / 1024) / us; + pr_err("pcie dma %s/%s test (%d+%d)*%d*%d cost %lldus speed:%lldKB/S\n", + wr_en ? "wr" : "", rd_en ? "rd" : "", wr_en, rd_en, size, loop, us, total_byte); + + return 0; +} + +static int dma_test_ch0(void *p) +{ + dma_test(&s_dmatest_dev[test_dev], 0, bus_addr, local_addr, test_size, + cycles_count, rw_test & 0x1, (rw_test & 0x2) >> 1); + + return 0; +} + +static int dma_test_ch1(void *p) +{ + /* Test in different area with ch0 */ + if (chn_en == 3) + dma_test(&s_dmatest_dev[test_dev], 1, bus_addr + test_size, local_addr + test_size, test_size, + cycles_count, rw_test & 0x1, (rw_test & 0x2) >> 1); + else + dma_test(&s_dmatest_dev[test_dev], 1, bus_addr, local_addr, test_size, + cycles_count, rw_test & 0x1, (rw_test & 0x2) >> 1); + + return 0; +} + +static int dma_run(void) +{ + if (chn_en == 3) { + kthread_run(dma_test_ch0, NULL, "dma_test_ch0"); + kthread_run(dma_test_ch1, NULL, "dma_test_ch1"); + } else if (chn_en == 2) { + dma_test_ch1(NULL); + } else { + dma_test_ch0(NULL); + } + + return 0; +} + +static int pcie_dw_dmatest(const char *val, const struct kernel_param *kp) +{ + char tmp[8]; + + if (!s_dmatest_dev[0].obj) { + pr_err("dmatest dev not exits\n"); + kfree(tmp); + + return -1; + } + + strncpy(tmp, val, 8); + if (!strncmp(tmp, "run", 3)) { + dma_run(); + } else if (!strncmp(tmp, "show", 4)) { + pcie_dw_dmatest_show(); + } else { + pr_info("input error\n"); + } + + return 0; +} + +static const struct kernel_param_ops pcie_dw_dmatest_ops = { + .set = pcie_dw_dmatest, + .get = param_get_uint, +}; + +module_param_cb(dmatest, &pcie_dw_dmatest_ops, &pcie_dw_dmatest, 0644); +MODULE_PARM_DESC(dmatest, "test rockchip pcie dma module"); + +MODULE_AUTHOR("Jon Lin"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pci/controller/dwc/pcie-dw-dmatest.h b/drivers/pci/controller/dwc/pcie-dw-dmatest.h new file mode 100644 index 000000000000..524f5b53f361 --- /dev/null +++ b/drivers/pci/controller/dwc/pcie-dw-dmatest.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2022 Rockchip Electronics Co., Ltd. + */ +#ifndef __PCIE_DW_DMATEST_H +#define __PCIE_DW_DMATEST_H + +#if IS_ENABLED(CONFIG_PCIE_DW_DMATEST) +struct dma_trx_obj *pcie_dw_dmatest_register(struct dw_pcie *pci, bool irq_en); +#else +static inline struct dma_trx_obj *pcie_dw_dmatest_register(struct dw_pcie *pci, bool irq_en) +{ + return NULL; +} +#endif + +#endif From fa919e9611b40ff8cdd3c9fba028034de6b75422 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Wed, 24 Aug 2022 11:53:20 +0800 Subject: [PATCH 174/204] pcie: rockchip: dw: Support dmatest Change-Id: I14bd31839bfb3fe70d8b12b7e3e6efca535028a1 Signed-off-by: Jon Lin --- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index 5a87275499fa..ff517ce76623 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -46,6 +46,7 @@ #include "pcie-designware.h" #include "../../pci.h" #include "../rockchip-pcie-dma.h" +#include "pcie-dw-dmatest.h" enum rk_pcie_device_mode { RK_PCIE_EP_TYPE, @@ -837,7 +838,7 @@ static bool rk_pcie_udma_enabled(struct rk_pcie *rk_pcie) PCIE_DMA_CTRL_OFF); } -static int rk_pcie_host_init_dma_trx(struct rk_pcie *rk_pcie) +static int rk_pcie_init_dma_trx(struct rk_pcie *rk_pcie) { if (!rk_pcie_udma_enabled(rk_pcie)) return 0; @@ -848,6 +849,12 @@ static int rk_pcie_host_init_dma_trx(struct rk_pcie *rk_pcie) return -EINVAL; } + rk_pcie->dma_obj = pcie_dw_dmatest_register(rk_pcie->pci, true); + if (IS_ERR(rk_pcie->dma_obj)) { + dev_err(rk_pcie->pci->dev, "failed to prepare dmatest\n"); + return -EINVAL; + } + /* Enable client write and read interrupt */ rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0xc000000); @@ -1132,11 +1139,6 @@ static int rk_add_pcie_port(struct rk_pcie *rk_pcie, struct platform_device *pde return ret; } - ret = rk_pcie_host_init_dma_trx(rk_pcie); - if (ret) { - dev_err(dev, "failed to init host dma trx\n"); - return ret; - } return 0; } @@ -2080,6 +2082,12 @@ retry_regulator: if (ret) goto remove_irq_domain; + ret = rk_pcie_init_dma_trx(rk_pcie); + if (ret) { + dev_err(dev, "failed to add dma extension\n"); + return ret; + } + if (rk_pcie->dma_obj) { rk_pcie->dma_obj->start_dma_func = rk_pcie_start_dma_dwc; rk_pcie->dma_obj->config_dma_func = rk_pcie_config_dma_dwc; From ce59362f58cf0bac63abb07acf9054270ec4f104 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 13 Sep 2022 19:39:32 +0800 Subject: [PATCH 175/204] media: rockchip: vicap fixed sof error for rv1126/rk356x in HDR mode Signed-off-by: Zefa Chen Change-Id: I78dd84b17ebbbcde166b3557a80bcfb132065c23 --- drivers/media/platform/rockchip/cif/capture.c | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 7620570967d2..1b41157eebc4 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -2847,10 +2847,9 @@ static int rkcif_csi_channel_set(struct rkcif_stream *stream, CSI_DMA_END_INTSTAT(channel->id) | CSI_LINE_INTSTAT(channel->id))); - /* enable id0 frame start int for sof(long frame, for hdr) */ - if (channel->id == RKCIF_STREAM_MIPI_ID0) - rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, - CSI_START_INTEN(channel->id)); + rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, + CSI_START_INTEN(channel->id)); + if (detect_stream->is_line_wake_up) { rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, CSI_LINE_INTEN(channel->id)); @@ -9351,9 +9350,6 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev) __func__); } - if (intstat & CSI_FRAME0_START_ID0 || intstat & CSI_FRAME1_START_ID0) - rkcif_deal_sof(cif_dev); - for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) { if (intstat & CSI_LINE_INTSTAT(i)) { stream = &cif_dev->stream[i]; @@ -9368,11 +9364,6 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev) } } - /* if do not reach frame dma end, return irq */ - mipi_id = rkcif_csi_g_mipi_id(&cif_dev->v4l2_dev, intstat); - if (mipi_id < 0) - return; - for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) { mipi_id = rkcif_csi_g_mipi_id(&cif_dev->v4l2_dev, intstat); @@ -9429,8 +9420,33 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev) detect_stream->fs_cnt_in_single_frame--; } } + cif_dev->irq_stats.all_frm_end_cnt++; + } + for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) { + if (intstat & CSI_START_INTSTAT(i)) { + stream = &cif_dev->stream[i]; + if (i == 0) { + rkcif_deal_sof(cif_dev); + } else { + spin_lock_irqsave(&stream->fps_lock, flags); + stream->readout.fs_timestamp = ktime_get_ns(); + stream->frame_idx++; + spin_unlock_irqrestore(&stream->fps_lock, flags); + } + stream->is_in_vblank = false; + } + if (intstat & CSI_LINE_INTSTAT(i)) { + stream = &cif_dev->stream[i]; + if (stream->is_line_inten) { + stream->line_int_cnt++; + rkcif_line_wake_up(stream, stream->id); + rkcif_modify_line_int(stream, false); + stream->is_line_inten = false; + } + v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, + "%s: id0 cur line:%d\n", __func__, lastline & 0x3fff); + } } - cif_dev->irq_stats.all_frm_end_cnt++; } else { u32 lastline, lastpix, ctl; u32 cif_frmst, frmid, int_en; From aed0776380bd745052f2710933486ca2de887e63 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Fri, 23 Sep 2022 10:06:01 +0800 Subject: [PATCH 176/204] net: can: rockchip: canfd: Support extended frames transmit for rk3568 Signed-off-by: Elaine Zhang Change-Id: I097fd66d34b56d9e6104f21da40e5b41bf2b4109 --- .../bindings/net/can/rockchip_canfd.txt | 3 +- drivers/net/can/rockchip/rockchip_canfd.c | 106 ++++++++++++++++-- 2 files changed, 100 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/net/can/rockchip_canfd.txt b/Documentation/devicetree/bindings/net/can/rockchip_canfd.txt index e73a8a6a0fc9..ad96a1501b5d 100644 --- a/Documentation/devicetree/bindings/net/can/rockchip_canfd.txt +++ b/Documentation/devicetree/bindings/net/can/rockchip_canfd.txt @@ -4,7 +4,8 @@ Rockchip CANFD controller Device Tree Bindings Required properties: - compatible : Should be: - "rockchip,canfd-1.0" for CANFD controllers 1.0 - - "rockchip,can-2.0" for CAN controllers 2.0 + - "rockchip,can-2.0" for RK3588 CAN controllers 2.0 + - "rockchip,rk3568-can-2.0" for RK3568 CAN controllers 2.0 - reg : Physical base address and size of the controller registers map. - interrupts : Property with a value describing the interrupt diff --git a/drivers/net/can/rockchip/rockchip_canfd.c b/drivers/net/can/rockchip/rockchip_canfd.c index d6bb345a876c..434a7d45c733 100644 --- a/drivers/net/can/rockchip/rockchip_canfd.c +++ b/drivers/net/can/rockchip/rockchip_canfd.c @@ -41,6 +41,7 @@ enum rockchip_canfd_reg { CAN_TX_ERR_CNT = 0x38, CAN_IDCODE = 0x3c, CAN_IDMASK = 0x40, + CAN_TX_CHECK_FIC = 0x50, CAN_NBTP = 0x100, CAN_DBTP = 0x104, CAN_TDCR = 0x108, @@ -103,6 +104,7 @@ enum rockchip_canfd_reg { enum { ROCKCHIP_CANFD_MODE = 0, ROCKCHIP_CAN_MODE, + ROCKCHIP_RK3568_CAN_MODE, }; #define DATE_LENGTH_12_BYTE (0x9) @@ -188,6 +190,10 @@ enum { #define TX_FD_BRS_ENABLE BIT(4) #define FIFO_ENABLE BIT(0) +#define RX_FIFO_CNT0_SHIFT 4 +#define RX_FIFO_CNT0_MASK (0x7 << RX_FIFO_CNT0_SHIFT) +#define RX_FIFO_CNT1_SHIFT 5 +#define RX_FIFO_CNT1_MASK (0x7 << RX_FIFO_CNT1_SHIFT) #define FORMAT_SHIFT 7 #define FORMAT_MASK (0x1 << FORMAT_SHIFT) @@ -220,6 +226,10 @@ struct rockchip_canfd { void __iomem *base; u32 irqstatus; unsigned long mode; + int rx_fifo_shift; + u32 rx_fifo_mask; + bool txtorx; + u32 tx_invalid[4]; }; static inline u32 rockchip_canfd_read(const struct rockchip_canfd *priv, @@ -281,6 +291,8 @@ static int set_normal_mode(struct net_device *ndev) val = rockchip_canfd_read(rcan, CAN_MODE); val |= WORK_MODE; + if (rcan->mode >= ROCKCHIP_CAN_MODE && rcan->txtorx) + val |= MODE_RXSTX; rockchip_canfd_write(rcan, CAN_MODE, val); netdev_dbg(ndev, "%s MODE=0x%08x\n", __func__, @@ -409,9 +421,6 @@ static int rockchip_canfd_start(struct net_device *ndev) /* Mode */ val |= MODE_FDOE; - rockchip_canfd_write(rcan, CAN_TXFIC, - rockchip_canfd_read(rcan, CAN_TXFIC) | - TX_FD_ENABLE); /* Loopback Mode */ if (rcan->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) @@ -487,6 +496,7 @@ static int rockchip_canfd_start_xmit(struct sk_buff *skb, u32 id, dlc; u32 cmd = CAN_TX0_REQ; int i; + unsigned long flags; if (can_dropped_invalid_skb(ndev, skb)) return NETDEV_TX_OK; @@ -522,6 +532,30 @@ static int rockchip_canfd_start_xmit(struct sk_buff *skb, dlc |= TX_FD_BRS_ENABLE; } + if (!rcan->txtorx && rcan->mode >= ROCKCHIP_CAN_MODE && cf->can_id & CAN_EFF_FLAG) { + /* Two frames are sent consecutively. + * Before the first frame is tx finished, + * the register of the second frame is configured. + * Don't be interrupted in the middle. + */ + local_irq_save(flags); + rockchip_canfd_write(rcan, CAN_TXID, rcan->tx_invalid[1]); + rockchip_canfd_write(rcan, CAN_TXFIC, rcan->tx_invalid[0]); + rockchip_canfd_write(rcan, CAN_TXDAT0, rcan->tx_invalid[2]); + rockchip_canfd_write(rcan, CAN_TXDAT1, rcan->tx_invalid[3]); + rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ); + rockchip_canfd_write(rcan, CAN_TXID, id); + rockchip_canfd_write(rcan, CAN_TXFIC, dlc); + for (i = 0; i < cf->len; i += 4) + rockchip_canfd_write(rcan, CAN_TXDAT0 + i, + *(u32 *)(cf->data + i)); + rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ); + local_irq_restore(flags); + can_put_echo_skb(skb, ndev, 0); + + return NETDEV_TX_OK; + } + rockchip_canfd_write(rcan, CAN_TXID, id); rockchip_canfd_write(rcan, CAN_TXFIC, dlc); @@ -529,9 +563,9 @@ static int rockchip_canfd_start_xmit(struct sk_buff *skb, rockchip_canfd_write(rcan, CAN_TXDAT0 + i, *(u32 *)(cf->data + i)); - can_put_echo_skb(skb, ndev, 0); + rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ); - rockchip_canfd_write(rcan, CAN_CMD, cmd); + can_put_echo_skb(skb, ndev, 0); return NETDEV_TX_OK; } @@ -553,6 +587,23 @@ static int rockchip_canfd_rx(struct net_device *ndev) for (i = 0; i < 16; i++) data[i] = rockchip_canfd_read(rcan, CAN_RXFRD); + if (rcan->mode >= ROCKCHIP_CAN_MODE) { + /* may be an empty frame */ + if (!dlc && !id_rockchip_canfd) + return 1; + + if (rcan->txtorx) { + if (rockchip_canfd_read(rcan, CAN_TX_CHECK_FIC) & FORMAT_MASK) { + ret = rockchip_canfd_read(rcan, CAN_TXID) & CAN_SFF_MASK; + if (id_rockchip_canfd == ret) { + rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, + ts | CAN_TX0_REQ); + return 1; + } + } + } + } + /* create zero'ed CAN frame buffer */ if (dlc & FDF_MASK) skb = alloc_canfd_skb(ndev, &cf); @@ -560,7 +611,7 @@ static int rockchip_canfd_rx(struct net_device *ndev) skb = alloc_can_skb(ndev, (struct can_frame **)&cf); if (!skb) { stats->rx_dropped++; - return 0; + return 1; } /* Change CAN data length format to socketCAN data format */ @@ -669,6 +720,7 @@ static irqreturn_t rockchip_canfd_interrupt(int irq, void *dev_id) TX_LOSTARB_INT | BUS_ERR_INT | BUS_OFF_INT; u32 isr; u32 dlc = 0; + u32 quota, work_done = 0; isr = rockchip_canfd_read(rcan, CAN_INT); if (isr & TX_FINISH_INT) { @@ -679,14 +731,33 @@ static irqreturn_t rockchip_canfd_interrupt(int irq, void *dev_id) else stats->tx_bytes += (dlc & DLC_MASK); stats->tx_packets++; + if (rcan->txtorx && rcan->mode >= ROCKCHIP_CAN_MODE && dlc & FORMAT_MASK) { + rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, FORMAT_MASK); + quota = (rockchip_canfd_read(rcan, CAN_RXFC) & + rcan->rx_fifo_mask) >> + rcan->rx_fifo_shift; + if (quota) { + while (work_done < quota) + work_done += rockchip_canfd_rx(ndev); + } + if (rockchip_canfd_read(rcan, CAN_TX_CHECK_FIC) & CAN_TX0_REQ) + rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ); + rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, 0); + } rockchip_canfd_write(rcan, CAN_CMD, 0); can_get_echo_skb(ndev, 0); netif_wake_queue(ndev); can_led_event(ndev, CAN_LED_EVENT_TX); } - if (isr & RX_FINISH_INT) - rockchip_canfd_rx(ndev); + if (isr & RX_FINISH_INT) { + quota = (rockchip_canfd_read(rcan, CAN_RXFC) & rcan->rx_fifo_mask) >> + rcan->rx_fifo_shift; + if (quota) { + while (work_done < quota) + work_done += rockchip_canfd_rx(ndev); + } + } if (isr & err_int) { /* error interrupt */ @@ -861,6 +932,10 @@ static const struct of_device_id rockchip_canfd_of_match[] = { .compatible = "rockchip,can-2.0", .data = (void *)ROCKCHIP_CAN_MODE }, + { + .compatible = "rockchip,rk3568-can-2.0", + .data = (void *)ROCKCHIP_RK3568_CAN_MODE + }, {}, }; MODULE_DEVICE_TABLE(of, rockchip_canfd_of_match); @@ -927,8 +1002,11 @@ static int rockchip_canfd_probe(struct platform_device *pdev) /* IFI CANFD can do both Bosch FD and ISO FD */ rcan->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_FD; + rcan->rx_fifo_shift = RX_FIFO_CNT0_SHIFT; + rcan->rx_fifo_mask = RX_FIFO_CNT0_MASK; break; case ROCKCHIP_CAN_MODE: + case ROCKCHIP_RK3568_CAN_MODE: rcan->can.bittiming_const = &rockchip_canfd_bittiming_const; rcan->can.do_set_mode = rockchip_canfd_set_mode; rcan->can.do_get_berr_counter = rockchip_canfd_get_berr_counter; @@ -936,11 +1014,23 @@ static int rockchip_canfd_probe(struct platform_device *pdev) CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_3_SAMPLES; + rcan->rx_fifo_shift = RX_FIFO_CNT0_SHIFT; + rcan->rx_fifo_mask = RX_FIFO_CNT0_MASK; break; default: return -EINVAL; } + if (rcan->mode == ROCKCHIP_CAN_MODE) { + rcan->rx_fifo_shift = RX_FIFO_CNT1_SHIFT; + rcan->rx_fifo_mask = RX_FIFO_CNT1_MASK; + } + + if (device_property_read_u32_array(&pdev->dev, + "rockchip,tx-invalid-info", + rcan->tx_invalid, 4)) + rcan->txtorx = 1; + ndev->netdev_ops = &rockchip_canfd_netdev_ops; ndev->irq = irq; ndev->flags |= IFF_ECHO; From c282cc82a1f0340aedea41f2a4daeea1503b1321 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Fri, 23 Sep 2022 10:29:11 +0800 Subject: [PATCH 177/204] arm64: dts: rockchip: rk3568: Fixed compatible for the CAN node Signed-off-by: Elaine Zhang Change-Id: I19b64e7c7fd1a663d3a41479a66cf95eb6ff3f05 --- arch/arm64/boot/dts/rockchip/rk3568.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi index e9790f5cd2fd..c5a7af71d403 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi @@ -2892,7 +2892,7 @@ }; can0: can@fe570000 { - compatible = "rockchip,canfd-1.0"; + compatible = "rockchip,rk3568-can-2.0"; reg = <0x0 0xfe570000 0x0 0x1000>; interrupts = ; clocks = <&cru CLK_CAN0>, <&cru PCLK_CAN0>; @@ -2905,7 +2905,7 @@ }; can1: can@fe580000 { - compatible = "rockchip,canfd-1.0"; + compatible = "rockchip,rk3568-can-2.0"; reg = <0x0 0xfe580000 0x0 0x1000>; interrupts = ; clocks = <&cru CLK_CAN1>, <&cru PCLK_CAN1>; @@ -2918,7 +2918,7 @@ }; can2: can@fe590000 { - compatible = "rockchip,canfd-1.0"; + compatible = "rockchip,rk3568-can-2.0"; reg = <0x0 0xfe590000 0x0 0x1000>; interrupts = ; clocks = <&cru CLK_CAN2>, <&cru PCLK_CAN2>; From d711b7f541a85be26c171e82df740822d5407f1b Mon Sep 17 00:00:00 2001 From: Xu Hongfei Date: Thu, 29 Sep 2022 15:12:10 +0800 Subject: [PATCH 178/204] media: rockchip: isp: remove the judgment that gain turn off if ldch is enabled Signed-off-by: Xu Hongfei Change-Id: I3dd7679f7052a6c0c76a41b9466a8235053afd5b --- drivers/media/platform/rockchip/isp/isp_params_v32.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/isp_params_v32.c b/drivers/media/platform/rockchip/isp/isp_params_v32.c index dd6ae74508d4..12b276c1e9e6 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v32.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v32.c @@ -3419,11 +3419,7 @@ isp_gain_enable(struct rkisp_isp_params_vdev *params_vdev, bool en) { struct rkisp_isp_params_val_v32 *priv_val = (struct rkisp_isp_params_val_v32 *)params_vdev->priv_val; - u32 val = isp3_param_read_cache(params_vdev, ISP3X_LDCH_STS); - - /* gain will affect ldch, no support for ldch and gain enable */ - if (val & ISP32_MODULE_EN && en) - return; + u32 val = 0; val = isp3_param_read_cache(params_vdev, ISP3X_GAIN_CTRL); if (en) { From f6886f6606525ba78201c99d988793a22ba782b2 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Thu, 29 Sep 2022 10:33:34 +0800 Subject: [PATCH 179/204] media: i2c: sc200ai change short exposure max to 404 half-line (3ms) Change-Id: I3149273398b5fe4e66e90f74a883234d8531f4e7 Signed-off-by: Zefa Chen --- drivers/media/i2c/sc200ai.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/sc200ai.c b/drivers/media/i2c/sc200ai.c index 9e5841b946f4..43f6c3a44e28 100644 --- a/drivers/media/i2c/sc200ai.c +++ b/drivers/media/i2c/sc200ai.c @@ -541,8 +541,8 @@ static const struct regval sc200ai_hdr_10_1920x1080_regs[] = { {0x3e13, 0x40}, {0x3e16, 0x00}, {0x3e17, 0x80}, - {0x3e23, 0x00}, - {0x3e24, 0x88}, + {0x3e23, 0x01}, + {0x3e24, 0x9e}, {0x3f09, 0x48}, {0x4816, 0xb1}, {0x4819, 0x09}, @@ -938,8 +938,8 @@ static int sc200ai_set_hdrae(struct sc200ai *sc200ai, s_exp_time = s_exp_time * 2; if (l_exp_time > 4362) //(2250 - 64 - 5) * 2 l_exp_time = 4362; - if (s_exp_time > 118) //(64 - 5) * 2 - s_exp_time = 118; + if (s_exp_time > 404) //(64 - 5) * 2 + s_exp_time = 404; ret = sc200ai_write_reg(sc200ai->client, SC200AI_REG_EXPOSURE_H, From 98ec1888333108468cd5407ff05a4ce873d08edd Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Thu, 29 Sep 2022 14:44:24 +0800 Subject: [PATCH 180/204] ASoC: codecs: rv1106_codec: To clarify the steps of enabling ADC Signed-off-by: Xing Zheng Change-Id: I66921b120dc2a7d197c984369ecb261b50d037a0 --- sound/soc/codecs/rv1106_codec.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/sound/soc/codecs/rv1106_codec.c b/sound/soc/codecs/rv1106_codec.c index 9aae936dd384..d84dbff79fff 100644 --- a/sound/soc/codecs/rv1106_codec.c +++ b/sound/soc/codecs/rv1106_codec.c @@ -1348,7 +1348,7 @@ static int rv1106_codec_adc_enable(struct rv1106_codec_priv *rv1106) return ret; } - /* vendor step 1 */ + /* vendor step 00 */ if (rv1106->soc_id == SOC_RV1103 && rv1106->adc_mode == DIFF_ADCL) { /* The ADCL is differential mode on rv1103 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL3, @@ -1370,19 +1370,19 @@ static int rv1106_codec_adc_enable(struct rv1106_codec_priv *rv1106) R(lr, ACODEC_ADC_R_SINGLE_END)); } - /* vendor step 2 */ + /* vendor step 01 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL1, L(lr, ACODEC_ADC_L_MIC_MSK) | R(lr, ACODEC_ADC_R_MIC_MSK), L(lr, ACODEC_ADC_L_MIC_WORK) | R(lr, ACODEC_ADC_R_MIC_WORK)); - /* vendor step 3 */ + /* vendor step 02 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL0, ACODEC_ADC_IBIAS_MSK, ACODEC_ADC_IBIAS_EN); - /* vendor step 4*/ + /* vendor step 03 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL1, L(lr, ACODEC_ADC_L_REF_VOL_BUF_MSK) | R(lr, ACODEC_ADC_R_REF_VOL_BUF_MSK), @@ -1391,60 +1391,60 @@ static int rv1106_codec_adc_enable(struct rv1106_codec_priv *rv1106) /* waiting VREF be stable */ msleep(100); - /* vendor step 5 */ + /* vendor step 04 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL3, L(lr, ACODEC_MIC_L_MSK) | R(lr, ACODEC_MIC_R_MSK), L(lr, ACODEC_MIC_L_EN) | R(lr, ACODEC_MIC_R_EN)); - /* vendor step 6 */ + /* vendor step 05 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL3, L(lr, ACODEC_ADC_L_MSK) | R(lr, ACODEC_ADC_R_MSK), L(lr, ACODEC_ADC_L_EN) | R(lr, ACODEC_ADC_R_EN)); - /* vendor step 7 */ + /* vendor step 06 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6, L(lr, ACODEC_ADC_L_CLK_MSK) | R(lr, ACODEC_ADC_R_CLK_MSK), L(lr, ACODEC_ADC_L_CLK_WORK) | R(lr, ACODEC_ADC_R_CLK_WORK)); - /* vendor step 8 */ + /* vendor step 07 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6, L(lr, ACODEC_ADC_L_WORK) | R(lr, ACODEC_ADC_R_WORK), L(lr, ACODEC_ADC_L_WORK) | R(lr, ACODEC_ADC_R_WORK)); - /* vendor step 9 */ + /* vendor step 08 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6, L(lr, ACODEC_ADC_L_SIGNAL_EN) | R(lr, ACODEC_ADC_R_SIGNAL_EN), L(lr, ACODEC_ADC_L_SIGNAL_EN) | R(lr, ACODEC_ADC_R_SIGNAL_EN)); - /* vendor step 10 */ + /* vendor step 09 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6, L(lr, ACODEC_ADC_L_ALC_MSK) | R(lr, ACODEC_ADC_R_ALC_MSK), L(lr, ACODEC_ADC_L_ALC_WORK) | R(lr, ACODEC_ADC_R_ALC_WORK)); - /* vendor step 11 */ + /* vendor step 10 */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL1, L(lr, ACODEC_ADC_L_MIC_SIGNAL_MSK) | R(lr, ACODEC_ADC_R_MIC_SIGNAL_MSK), L(lr, ACODEC_ADC_L_MIC_SIGNAL_WORK) | R(lr, ACODEC_ADC_R_MIC_SIGNAL_WORK)); - /* vendor step 12 */ + /* vendor step 11, configure GAIN_MICL/R by user */ + + /* vendor step 12, configure GAIN_ALCL/R by user */ /* vendor step 13 */ - - /* vendor step 14 */ regmap_read(rv1106->regmap, ACODEC_ADC_ANA_CTL1, &agc_func_en); if (agc_func_en & ACODEC_AGC_FUNC_SEL_EN) { regmap_update_bits(rv1106->regmap, From af14a79ae3e531ed80293e1adc2fea7541b58fc8 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Fri, 30 Sep 2022 15:18:16 +0800 Subject: [PATCH 181/204] clk: rockchip: rk3588: support aclk_vop_sub_src set parent to aclk_vop_div2_src Signed-off-by: Elaine Zhang Change-Id: If493c3918bd8022accf089d69cce4cb93326d9e5 --- drivers/clk/rockchip/clk-rk3588.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c index 99bb5111d695..ee2826a70742 100644 --- a/drivers/clk/rockchip/clk-rk3588.c +++ b/drivers/clk/rockchip/clk-rk3588.c @@ -1890,6 +1890,7 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = { COMPOSITE(ACLK_VOP_ROOT, "aclk_vop_root", gpll_cpll_dmyaupll_npll_spll_p, 0, RK3588_CLKSEL_CON(110), 5, 3, MFLAGS, 0, 5, DFLAGS, RK3588_CLKGATE_CON(52), 0, GFLAGS), + FACTOR(0, "aclk_vop_div2_src", "aclk_vop_root", 0, 1, 2), COMPOSITE_NODIV(ACLK_VOP_LOW_ROOT, "aclk_vop_low_root", mux_400m_200m_100m_24m_p, 0, RK3588_CLKSEL_CON(110), 8, 2, MFLAGS, RK3588_CLKGATE_CON(52), 1, GFLAGS), @@ -1905,7 +1906,7 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = { COMPOSITE_NODIV(HCLK_VO1USB_TOP_ROOT, "hclk_vo1usb_top_root", mux_200m_100m_50m_24m_p, CLK_IS_CRITICAL, RK3588_CLKSEL_CON(170), 6, 2, MFLAGS, RK3588_CLKGATE_CON(74), 2, GFLAGS), - MUX(ACLK_VOP_SUB_SRC, "aclk_vop_sub_src", aclk_vop_sub_src_p, CLK_SET_RATE_PARENT, + MUX(ACLK_VOP_SUB_SRC, "aclk_vop_sub_src", aclk_vop_sub_src_p, 0, RK3588_CLKSEL_CON(115), 9, 1, MFLAGS), GATE(PCLK_EDP0, "pclk_edp0", "pclk_vo1_root", 0, RK3588_CLKGATE_CON(62), 0, GFLAGS), From e08caf351acfa23c39d795742fe9c3934eb861f2 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Tue, 13 Sep 2022 12:11:43 +0000 Subject: [PATCH 182/204] media: i2c: lt7911uxc: add 5K60 support for CPHY Signed-off-by: Jianwei Fan Change-Id: I223f4e8e87266c4b75d201f4b23e853cfca05964 --- drivers/media/i2c/lt7911uxc.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/lt7911uxc.c b/drivers/media/i2c/lt7911uxc.c index 1618d01d1ec4..8fea3659d1cd 100644 --- a/drivers/media/i2c/lt7911uxc.c +++ b/drivers/media/i2c/lt7911uxc.c @@ -10,6 +10,7 @@ * V0.0X01.0X01 support DPHY 4K60. * V0.0X01.0X02 add CPHY support. * V0.0X01.0X03 add rk3588 dcphy param. + * V0.0X01.0X04 add 5K60 support for CPHY. * */ @@ -37,7 +38,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x04) static int debug; module_param(debug, int, 0644); @@ -48,7 +49,8 @@ MODULE_PARM_DESC(debug, "debug level (0-3)"); #define LT7911UXC_LINK_FREQ_HIGH 1250000000 #define LT7911UXC_LINK_FREQ_LOW 400000000 -#define LT7911UXC_PIXEL_RATE 600000000 +#define LT7911UXC_LINK_FREQ_700M 700000000 +#define LT7911UXC_PIXEL_RATE 800000000 #define LT7911UXC_CHIPID 0x0119 #define CHIPID_REGH 0xe101 @@ -96,6 +98,7 @@ MODULE_PARM_DESC(debug, "debug level (0-3)"); static const s64 link_freq_menu_items[] = { LT7911UXC_LINK_FREQ_HIGH, LT7911UXC_LINK_FREQ_LOW, + LT7911UXC_LINK_FREQ_700M, }; struct lt7911uxc { @@ -139,7 +142,7 @@ struct lt7911uxc { static const struct v4l2_dv_timings_cap lt7911uxc_timings_cap = { .type = V4L2_DV_BT_656_1120, .reserved = { 0 }, - V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 600000000, + V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 800000000, V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED | @@ -224,6 +227,16 @@ static const struct lt7911uxc_mode supported_modes_dphy[] = { static const struct lt7911uxc_mode supported_modes_cphy[] = { { + .width = 5120, + .height = 2160, + .max_fps = { + .numerator = 10000, + .denominator = 600000, + }, + .hts_def = 5500, + .vts_def = 2250, + .mipi_freq_idx = 2, + }, { .width = 3840, .height = 2160, .max_fps = { From 8d29486a151549af2dedd2fefacc3af7b6608581 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Fri, 30 Sep 2022 18:01:25 +0800 Subject: [PATCH 183/204] pinctrl/rockchip: fix rk3308 pinmux error The GPIO2A2 GPIO2A3 GPIO2C0 GPIO3B2 GPIO3B3 have 3 bits for pinmux, and have a extra bit to select 2bits or 3bits. The Rockchip downstream has a soc_data_init to choice 3bits mode, but the upstream uses 2bits mode. This patch removes the soc_data_init/re_init and set the soc data init directly during probe. Fixes: ae7b9050a3f2 ("UPSTREAM: pinctrl: rockchip: fix RK3308 pinmux bits") Signed-off-by: Jianqun Xu Change-Id: I57b88c776f86a37e34a38cd7b81e422e0cce2e03 --- drivers/pinctrl/pinctrl-rockchip.c | 40 ++++++++++++++---------------- drivers/pinctrl/pinctrl-rockchip.h | 5 ---- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 76b858b44591..2f5eb0756c3e 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -591,35 +591,35 @@ static struct rockchip_mux_recalced_data rk3308_mux_recalced_data[] = { .bit = 8, .mask = 0xf }, { - /* gpio2a2_sel */ + /* gpio2a2_sel_plus */ .num = 2, .pin = 2, - .reg = 0x40, - .bit = 4, - .mask = 0x3 + .reg = 0x608, + .bit = 0, + .mask = 0x7 }, { - /* gpio2a3_sel */ + /* gpio2a3_sel_plus */ .num = 2, .pin = 3, - .reg = 0x40, - .bit = 6, - .mask = 0x3 + .reg = 0x608, + .bit = 4, + .mask = 0x7 }, { - /* gpio2c0_sel */ + /* gpio2c0_sel_plus */ .num = 2, .pin = 16, - .reg = 0x50, - .bit = 0, - .mask = 0x3 + .reg = 0x610, + .bit = 8, + .mask = 0x7 }, { - /* gpio3b2_sel */ + /* gpio3b2_sel_plus */ .num = 3, .pin = 10, - .reg = 0x68, - .bit = 4, - .mask = 0x3 + .reg = 0x610, + .bit = 0, + .mask = 0x7 }, { - /* gpio3b3_sel */ + /* gpio3b3_sel_plus */ .num = 3, .pin = 11, .reg = 0x68, @@ -3961,9 +3961,8 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) return PTR_ERR(info->regmap_pmu); } - /* Special handle for some Socs */ - if (ctrl->soc_data_init) { - ret = ctrl->soc_data_init(info); + if (IS_ENABLED(CONFIG_CPU_RK3308) && ctrl->type == RK3308) { + ret = rk3308_soc_data_init(info); if (ret) return ret; } @@ -4408,7 +4407,6 @@ static struct rockchip_pin_ctrl rk3308_pin_ctrl __maybe_unused = { .niomux_recalced = ARRAY_SIZE(rk3308_mux_recalced_data), .iomux_routes = rk3308_mux_route_data, .niomux_routes = ARRAY_SIZE(rk3308_mux_route_data), - .soc_data_init = rk3308_soc_data_init, .pull_calc_reg = rk3308_calc_pull_reg_and_bit, .drv_calc_reg = rk3308_calc_drv_reg_and_bit, .schmitt_calc_reg = rk3308_calc_schmitt_reg_and_bit, diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h index 1642432513fd..2faedfb9ac24 100644 --- a/drivers/pinctrl/pinctrl-rockchip.h +++ b/drivers/pinctrl/pinctrl-rockchip.h @@ -401,11 +401,6 @@ struct rockchip_pin_ctrl { u32 niomux_recalced; struct rockchip_mux_route_data *iomux_routes; u32 niomux_routes; - - int (*ctrl_data_re_init)(struct rockchip_pin_ctrl *ctrl); - - int (*soc_data_init)(struct rockchip_pinctrl *info); - int (*pull_calc_reg)(struct rockchip_pin_bank *bank, int pin_num, struct regmap **regmap, int *reg, u8 *bit); From 482424b9aacbc7ad4687748025b3b86931f0be55 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Sat, 8 Oct 2022 09:47:23 +0800 Subject: [PATCH 184/204] video: rockchip: rga3: support rga2_iommu Signed-off-by: Yu Qiaowei Change-Id: Ic4d4ad1e4cd6490aa487b272003130eb0504219f --- .../rockchip/rga3/include/rga_hw_config.h | 1 + drivers/video/rockchip/rga3/rga2_reg_info.c | 10 +++++++ drivers/video/rockchip/rga3/rga_drv.c | 3 +++ drivers/video/rockchip/rga3/rga_hw_config.c | 26 +++++++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/drivers/video/rockchip/rga3/include/rga_hw_config.h b/drivers/video/rockchip/rga3/include/rga_hw_config.h index ae5c53d23f4c..73f05f7f517d 100644 --- a/drivers/video/rockchip/rga3/include/rga_hw_config.h +++ b/drivers/video/rockchip/rga3/include/rga_hw_config.h @@ -67,6 +67,7 @@ struct rga_hw_data { extern const struct rga_hw_data rga3_data; extern const struct rga_hw_data rga2e_data; extern const struct rga_hw_data rga2e_1106_data; +extern const struct rga_hw_data rga2e_iommu_data; /* Returns false if in range, true otherwise */ static inline bool rga_hw_out_of_range(const struct rga_rect_range *range, int width, int height) diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index 4216ffb3b8f4..923c1f30625d 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -2064,6 +2064,10 @@ void rga2_soft_reset(struct rga_scheduler_t *scheduler) { u32 i; u32 reg; + u32 iommu_dte_addr; + + if (scheduler->data->mmu == RGA_IOMMU) + iommu_dte_addr = rga_read(0xf00, scheduler); rga_write((1 << 3) | (1 << 4) | (1 << 6), RGA2_SYS_CTRL, scheduler); @@ -2077,6 +2081,12 @@ void rga2_soft_reset(struct rga_scheduler_t *scheduler) udelay(1); } + if (scheduler->data->mmu == RGA_IOMMU) { + rga_write(iommu_dte_addr, 0xf00, scheduler); + /* enable iommu */ + rga_write(0, 0xf08, scheduler); + } + if (i == RGA_RESET_TIMEOUT) pr_err("soft reset timeout.\n"); } diff --git a/drivers/video/rockchip/rga3/rga_drv.c b/drivers/video/rockchip/rga3/rga_drv.c index 5b809d143ab5..576b460f91f3 100644 --- a/drivers/video/rockchip/rga3/rga_drv.c +++ b/drivers/video/rockchip/rga3/rga_drv.c @@ -1502,6 +1502,9 @@ static int rga_drv_probe(struct platform_device *pdev) } else if (scheduler->core == RGA2_SCHEDULER_CORE0) { if (!strcmp(scheduler->version.str, "3.3.87975")) scheduler->data = &rga2e_1106_data; + else if (!strcmp(scheduler->version.str, "3.6.92812") || + !strcmp(scheduler->version.str, "3.7.93215")) + scheduler->data = &rga2e_iommu_data; else scheduler->data = &rga2e_data; } diff --git a/drivers/video/rockchip/rga3/rga_hw_config.c b/drivers/video/rockchip/rga3/rga_hw_config.c index 797ab676b053..42d7bdb52a54 100644 --- a/drivers/video/rockchip/rga3/rga_hw_config.c +++ b/drivers/video/rockchip/rga3/rga_hw_config.c @@ -325,3 +325,29 @@ const struct rga_hw_data rga2e_1106_data = { RGA_MODE_CSC_BT709, .mmu = RGA_NONE_MMU, }; + +const struct rga_hw_data rga2e_iommu_data = { + .version = 0, + .input_range = {{2, 2}, {8192, 8192}}, + .output_range = {{2, 2}, {4096, 4096}}, + + .win = rga2e_win_data, + .win_size = ARRAY_SIZE(rga2e_win_data), + /* 1 << factor mean real factor */ + .max_upscale_factor = 4, + .max_downscale_factor = 4, + + .byte_stride_align = 4, + .max_byte_stride = WORD_TO_BYTE(8192), + + .feature = RGA_COLOR_FILL | RGA_COLOR_PALETTE | + RGA_COLOR_KEY | RGA_ROP_CALCULATE | + RGA_NN_QUANTIZE | RGA_DITHER | RGA_MOSAIC | + RGA_YIN_YOUT | RGA_YUV_HDS | RGA_YUV_VDS | + RGA_OSD | RGA_PRE_INTR, + .csc_r2y_mode = RGA_MODE_CSC_BT601L | RGA_MODE_CSC_BT601F | + RGA_MODE_CSC_BT709, + .csc_y2r_mode = RGA_MODE_CSC_BT601L | RGA_MODE_CSC_BT601F | + RGA_MODE_CSC_BT709, + .mmu = RGA_IOMMU, +}; From 9a94f8e0804692175f4b77b013182523793d57eb Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Fri, 30 Sep 2022 00:52:30 +0000 Subject: [PATCH 185/204] media: i2c: ov13855: fix power on sequence to avoid i2c communication failed Signed-off-by: Jianwei Fan Change-Id: I8534e9512cc94bd1af30fa213653d0024900e7e2 --- drivers/media/i2c/ov13855.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/ov13855.c b/drivers/media/i2c/ov13855.c index 9beeddedfe2c..c05c5cea46f1 100644 --- a/drivers/media/i2c/ov13855.c +++ b/drivers/media/i2c/ov13855.c @@ -10,6 +10,7 @@ * V0.0X01.0X03 * 1. 4224x3136@15fps & 2114x1568@60fps only enable for debug. * 2. fix some regs setting. + * V0.0X01.0X04 fix power on sequence */ //#define DEBUG #include @@ -31,7 +32,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x04) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -1127,6 +1128,8 @@ static int ov13855_set_fmt(struct v4l2_subdev *sd, __v4l2_ctrl_s_ctrl(ov13855->link_freq, mode->link_freq_idx); } + dev_info(&ov13855->client->dev, "%s: mode->link_freq_idx(%d)", + __func__, mode->link_freq_idx); mutex_unlock(&ov13855->mutex); @@ -1470,13 +1473,13 @@ static int __ov13855_power_on(struct ov13855 *ov13855) if (!IS_ERR(ov13855->reset_gpio)) gpiod_set_value_cansleep(ov13855->reset_gpio, 1); - usleep_range(500, 1000); + usleep_range(5000, 6000); if (!IS_ERR(ov13855->pwdn_gpio)) gpiod_set_value_cansleep(ov13855->pwdn_gpio, 1); /* 8192 cycles prior to first SCCB transaction */ delay_us = ov13855_cal_delay(8192); - usleep_range(delay_us, delay_us * 2); + usleep_range(delay_us * 2, delay_us * 3); return 0; From aa33064d9b248937603b0ecde9400e9de5e8ffe5 Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Sat, 1 Oct 2022 03:00:10 +0000 Subject: [PATCH 186/204] drm/bridge: dw-hdmi-qp-cec: fix receive message error Signed-off-by: Chen Shunqing Change-Id: I741c45dceca7efba896c8892e1ac790b4dffc4e5 --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp-cec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp-cec.c index 05bcfcaec665..2d2320ed0769 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp-cec.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp-cec.c @@ -149,7 +149,7 @@ static irqreturn_t dw_hdmi_qp_cec_hardirq(int irq, void *data) len = sizeof(cec->rx_msg.msg); for (i = 0; i < 4; i++) { - val = dw_hdmi_qp_read(cec, CEC_RX_DATA3_0 + i); + val = dw_hdmi_qp_read(cec, CEC_RX_DATA3_0 + i * 4); cec->rx_msg.msg[i * 4] = val & 0xff; cec->rx_msg.msg[i * 4 + 1] = (val >> 8) & 0xff; cec->rx_msg.msg[i * 4 + 2] = (val >> 16) & 0xff; From 4037c8a7696f62c54c0c2696c19a51eecdd07b00 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Fri, 30 Sep 2022 17:05:54 +0800 Subject: [PATCH 187/204] media: rockchip: isp: drop first output for fast case Change-Id: I7e303b6307032187a70b5558f2a78ccd6b8f3ca5 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/capture_v32.c | 10 +++++++++- drivers/media/platform/rockchip/isp/rkisp.c | 12 +++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index 637b5e882f6d..67cb27c320eb 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -1253,6 +1253,7 @@ static int mi_frame_start(struct rkisp_stream *stream, u32 mis) */ static int mi_frame_end(struct rkisp_stream *stream) { + struct rkisp_device *dev = stream->ispdev; struct capture_fmt *isp_fmt = &stream->out_isp_fmt; unsigned long lock_flags = 0; u32 i; @@ -1262,6 +1263,13 @@ static int mi_frame_end(struct rkisp_stream *stream) if (stream->curr_buf) { struct vb2_buffer *vb2_buf = &stream->curr_buf->vb.vb2_buf; + if (dev->skip_frame) { + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + list_add_tail(&stream->curr_buf->queue, &stream->buf_queue); + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + goto next; + } + for (i = 0; i < isp_fmt->mplanes; i++) { u32 payload_size = stream->out_fmt.plane_fmt[i].sizeimage; @@ -1273,7 +1281,7 @@ static int mi_frame_end(struct rkisp_stream *stream) else rkisp_rockit_buf_done(stream, ROCKIT_DVBM_END); } - +next: spin_lock_irqsave(&stream->vbq_lock, lock_flags); stream->curr_buf = stream->next_buf; stream->next_buf = NULL; diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index b89935cd4aac..7597539eb919 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -789,8 +789,10 @@ static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd) isp->sw_rd_cnt = 1; times = 0; } - if (dev->is_pre_on && t.frame_id == 0) + if (dev->is_pre_on && t.frame_id == 0) { dev->is_first_double = true; + dev->skip_frame = 1; + } } end: spin_unlock_irqrestore(&hw->rdbk_lock, lock_flags); @@ -847,8 +849,6 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq) { u32 val = 0; - if (dev->is_first_double) - return; if (dev->hw_dev->is_multi_overflow && dev->sw_rd_cnt && irq & ISP_FRAME_END) @@ -867,6 +867,12 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq) if (dev->irq_ends != dev->irq_ends_mask || !IS_HDR_RDBK(dev->rd_mode)) return; + if (dev->is_first_double) { + dev->skip_frame = 0; + dev->irq_ends = 0; + return; + } + /* check output stream is off */ val = ISP_FRAME_MP | ISP_FRAME_SP | ISP_FRAME_MPFBC | ISP_FRAME_BP; if (!(dev->irq_ends_mask & val)) { From 266443eda94651585cf65e23920ef1ac67bb5f31 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Sat, 24 Sep 2022 16:03:13 +0800 Subject: [PATCH 188/204] media: i2c: sc200ai support get config from cmdline for thunderboot Signed-off-by: Zefa Chen Change-Id: I34f1339ebf033122663f0f24cf5b4725948b258e --- drivers/media/i2c/sc200ai.c | 153 ++++++++++++++++++++++++++++++++---- 1 file changed, 139 insertions(+), 14 deletions(-) diff --git a/drivers/media/i2c/sc200ai.c b/drivers/media/i2c/sc200ai.c index 43f6c3a44e28..d26f576714b2 100644 --- a/drivers/media/i2c/sc200ai.c +++ b/drivers/media/i2c/sc200ai.c @@ -1360,6 +1360,13 @@ static int __sc200ai_start_stream(struct sc200ai *sc200ai) { int ret; + dev_info(&sc200ai->client->dev, + "%dx%d@%d, mode %d, vts 0x%x\n", + sc200ai->cur_mode->width, + sc200ai->cur_mode->height, + sc200ai->cur_fps.denominator / sc200ai->cur_fps.numerator, + sc200ai->cur_mode->hdr_mode, + sc200ai->cur_vts); if (!sc200ai->is_thunderboot) { ret = sc200ai_write_array(sc200ai->client, sc200ai->cur_mode->reg_list); if (ret) @@ -1667,8 +1674,8 @@ static void sc200ai_modify_fps_info(struct sc200ai *sc200ai) { const struct sc200ai_mode *mode = sc200ai->cur_mode; - sc200ai->cur_fps.denominator = mode->max_fps.denominator * sc200ai->cur_vts / - mode->vts_def; + sc200ai->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def/ + sc200ai->cur_vts; } static int sc200ai_set_ctrl(struct v4l2_ctrl *ctrl) @@ -1799,7 +1806,9 @@ static int sc200ai_initialize_controls(struct sc200ai *sc200ai) h_blank, h_blank, 1, h_blank); if (sc200ai->hblank) sc200ai->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + sc200ai->cur_fps = mode->max_fps; vblank_def = mode->vts_def - mode->height; + sc200ai->cur_vts = mode->vts_def; sc200ai->vblank = v4l2_ctrl_new_std(handler, &sc200ai_ctrl_ops, V4L2_CID_VBLANK, vblank_def, SC200AI_VTS_MAX - mode->height, @@ -1833,8 +1842,6 @@ static int sc200ai_initialize_controls(struct sc200ai *sc200ai) sc200ai->subdev.ctrl_handler = handler; sc200ai->has_init_exp = false; - sc200ai->cur_fps = mode->max_fps; - sc200ai->cur_vts = mode->vts_def; return 0; @@ -1880,6 +1887,132 @@ static int sc200ai_configure_regulators(struct sc200ai *sc200ai) sc200ai->supplies); } +#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP +static u32 rk_cam_hdr; +static u32 rk_cam_w; +static u32 rk_cam_h; +static u32 rk_cam_fps; + +static int __init __maybe_unused rk_cam_hdr_setup(char *str) +{ + int ret = 0; + unsigned long val = 0; + + ret = kstrtoul(str, 0, &val); + if (!ret) + rk_cam_hdr = (u32)val; + else + pr_err("get rk_cam_hdr fail\n"); + return 1; +} + +static int __init __maybe_unused rk_cam_w_setup(char *str) +{ + int ret = 0; + unsigned long val = 0; + + ret = kstrtoul(str, 0, &val); + if (!ret) + rk_cam_w = (u32)val; + else + pr_err("get rk_cam_w fail\n"); + return 1; +} + +static int __init __maybe_unused rk_cam_h_setup(char *str) +{ + int ret = 0; + unsigned long val = 0; + + ret = kstrtoul(str, 0, &val); + if (!ret) + rk_cam_h = (u32)val; + else + pr_err("get rk_cam_h fail\n"); + return 1; +} + +static int __init __maybe_unused rk_cam_fps_setup(char *str) +{ + int ret = 0; + unsigned long val = 0; + + ret = kstrtoul(str, 0, &val); + if (!ret) + rk_cam_fps = (u32)val; + else + pr_err("get rk_cam_fps fail\n"); + return 1; +} + +__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); + +static void find_terminal_resolution(struct sc200ai *sc200ai) +{ + int i = 0; + const struct sc200ai_mode *mode = NULL; + const struct sc200ai_mode *fit_mode = NULL; + u32 cur_fps = 0; + u32 dst_fps = 0; + u32 tmp_fps = 0; + + if (rk_cam_w == 0 || rk_cam_h == 0 || + rk_cam_fps == 0) + goto err_find_res; + + dst_fps = rk_cam_fps; + for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { + mode = &supported_modes[i]; + cur_fps = mode->max_fps.denominator / mode->max_fps.numerator; + if (mode->width == rk_cam_w && mode->height == rk_cam_h && + mode->hdr_mode == rk_cam_hdr) { + if (cur_fps == dst_fps) { + sc200ai->cur_mode = mode; + return; + } + if (cur_fps >= dst_fps) { + if (fit_mode) { + tmp_fps = fit_mode->max_fps.denominator / fit_mode->max_fps.numerator; + if (tmp_fps - dst_fps > cur_fps - dst_fps) + fit_mode = mode; + } else { + fit_mode = mode; + } + } + } + } + if (fit_mode) { + sc200ai->cur_mode = fit_mode; + return; + } +err_find_res: + dev_err(&sc200ai->client->dev, "not match %dx%d@%dfps mode %d\n!", + rk_cam_w, rk_cam_h, dst_fps, rk_cam_hdr); + sc200ai->cur_mode = &supported_modes[0]; +} +#else +static void find_terminal_resolution(struct sc200ai *sc200ai) +{ + u32 hdr_mode = 0; + struct device_node *node = sc200ai->client->dev.of_node; + int i = 0; + + of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode); + for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { + if (hdr_mode == supported_modes[i].hdr_mode) { + sc200ai->cur_mode = &supported_modes[i]; + break; + } + } + if (i == ARRAY_SIZE(supported_modes)) + sc200ai->cur_mode = &supported_modes[0]; + +} +#endif + static int sc200ai_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1889,7 +2022,6 @@ static int sc200ai_probe(struct i2c_client *client, struct v4l2_subdev *sd; char facing[2]; int ret; - u32 i, hdr_mode = 0; dev_info(dev, "driver version: %02x.%02x.%02x", DRIVER_VERSION >> 16, @@ -1900,7 +2032,6 @@ static int sc200ai_probe(struct i2c_client *client, if (!sc200ai) return -ENOMEM; - of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode); ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, &sc200ai->module_index); ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, @@ -1916,14 +2047,8 @@ static int sc200ai_probe(struct i2c_client *client, sc200ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); sc200ai->client = client; - for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { - if (hdr_mode == supported_modes[i].hdr_mode) { - sc200ai->cur_mode = &supported_modes[i]; - break; - } - } - if (i == ARRAY_SIZE(supported_modes)) - sc200ai->cur_mode = &supported_modes[0]; + + find_terminal_resolution(sc200ai); sc200ai->xvclk = devm_clk_get(dev, "xvclk"); if (IS_ERR(sc200ai->xvclk)) { From 77a650e3d057632960563aeea72865dace446246 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Thu, 29 Sep 2022 21:58:31 +0800 Subject: [PATCH 189/204] mtd: spinand: foresee: Support new device F35SQA512M, F35UQA512M Change-Id: Ica5e7e1bafd481d7b5c883fd9ab75b8f9599e003 Signed-off-by: Jon Lin --- drivers/mtd/nand/spi/foresee.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/mtd/nand/spi/foresee.c b/drivers/mtd/nand/spi/foresee.c index 4061aa8fbf4e..e8eff658391c 100644 --- a/drivers/mtd/nand/spi/foresee.c +++ b/drivers/mtd/nand/spi/foresee.c @@ -97,6 +97,24 @@ static const struct spinand_info foresee_spinand_table[] = { &update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&fsxxndxxg_ooblayout, NULL)), + SPINAND_INFO("F35SQA512M", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x70), + NAND_MEMORG(1, 2048, 64, 64, 512, 20, 1, 1, 1), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&fsxxndxxg_ooblayout, NULL)), + SPINAND_INFO("F35UQA512M", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x60), + NAND_MEMORG(1, 2048, 64, 64, 512, 20, 1, 1, 1), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&fsxxndxxg_ooblayout, NULL)), }; static const struct spinand_manufacturer_ops foresee_spinand_manuf_ops = { From e3354602f7d7be97a12c1aee029c99a57dfc58c3 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Fri, 16 Sep 2022 14:07:05 +0800 Subject: [PATCH 190/204] spi: rockchip: Support rkspi-devN misc devices Reach controller register in user space by mmap operation, And only do spi transmission in user space. Change-Id: I37e22ad04813c2cd10d97324339afc5a11da59bd Signed-off-by: Jon Lin --- drivers/spi/Kconfig | 10 +++++ drivers/spi/spi-rockchip.c | 79 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 4469a177751a..0bdd5fe31d66 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -640,6 +640,16 @@ config SPI_ROCKCHIP The main usecase of this controller is to use spi flash as boot device. +config SPI_ROCKCHIP_MISCDEV + bool "Rockchip SPI controller misc devices" + depends on SPI_ROCKCHIP + help + This selects a misc driver for Rockchip SPI controller. + + If you say yes to this option, It will register rkspi-devN misc device + for each spi controller and support to get the controller register + resource by calling mmap. + config SPI_ROCKCHIP_SFC tristate "Rockchip Serial Flash Controller (SFC)" imply ROCKCHIP_MTD_VENDOR_STORAGE diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index be61a77901e4..c8302e38f4c2 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -169,6 +170,8 @@ #define ROCKCHIP_SPI_VER2_TYPE1 0x05EC0002 #define ROCKCHIP_SPI_VER2_TYPE2 0x00110002 +#define ROCKCHIP_SPI_REGISTER_SIZE 0x1000 + struct rockchip_spi_quirks { u32 max_baud_div_in_cpha; }; @@ -209,6 +212,8 @@ struct rockchip_spi { bool cs_high_supported; /* native CS supports active-high polarity */ struct spi_transfer *xfer; /* Store xfer temporarily */ + phys_addr_t base_addr_phy; + struct miscdevice miscdev; /* quirks */ u32 max_baud_div_in_cpha; @@ -785,6 +790,60 @@ static int rockchip_spi_setup(struct spi_device *spi) return 0; } +static int rockchip_spi_misc_open(struct inode *inode, struct file *filp) +{ + struct miscdevice *misc = filp->private_data; + struct spi_controller *ctlr = dev_get_drvdata(misc->parent); + struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); + + pm_runtime_get_sync(rs->dev); + + return 0; +} + +static int rockchip_spi_misc_release(struct inode *inode, struct file *filp) +{ + struct miscdevice *misc = filp->private_data; + struct spi_controller *ctlr = dev_get_drvdata(misc->parent); + struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); + + pm_runtime_put(rs->dev); + + return 0; +} + +static int rockchip_spi_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct miscdevice *misc = filp->private_data; + struct spi_controller *ctlr = dev_get_drvdata(misc->parent); + struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); + size_t size = vma->vm_end - vma->vm_start; + int err; + + if (size > ROCKCHIP_SPI_REGISTER_SIZE) { + dev_warn(misc->parent, "mmap size is out of limitation\n"); + return -EINVAL; + } + + vma->vm_flags |= VM_IO; + vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP); + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + err = remap_pfn_range(vma, vma->vm_start, + __phys_to_pfn(rs->base_addr_phy), + size, vma->vm_page_prot); + if (err) + return -EAGAIN; + + return 0; +} + +static const struct file_operations rockchip_spi_misc_fops = { + .open = rockchip_spi_misc_open, + .release = rockchip_spi_misc_release, + .mmap = rockchip_spi_mmap, +}; + static int rockchip_spi_probe(struct platform_device *pdev) { int ret; @@ -821,6 +880,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) ret = PTR_ERR(rs->regs); goto err_put_ctlr; } + rs->base_addr_phy = mem->start; if (!has_acpi_companion(&pdev->dev)) rs->apb_pclk = devm_clk_get(&pdev->dev, "apb_pclk"); @@ -999,6 +1059,22 @@ static int rockchip_spi_probe(struct platform_device *pdev) goto err_free_dma_rx; } + if (IS_ENABLED(CONFIG_SPI_ROCKCHIP_MISCDEV)) { + char misc_name[20]; + + snprintf(misc_name, sizeof(misc_name), "rkspi-dev%d", ctlr->bus_num); + rs->miscdev.minor = MISC_DYNAMIC_MINOR; + rs->miscdev.name = misc_name; + rs->miscdev.fops = &rockchip_spi_misc_fops; + rs->miscdev.parent = &pdev->dev; + + ret = misc_register(&rs->miscdev); + if (ret) + dev_err(&pdev->dev, "failed to register misc device %s\n", misc_name); + else + dev_info(&pdev->dev, "register misc device %s\n", misc_name); + } + return 0; err_free_dma_rx: @@ -1026,6 +1102,9 @@ static int rockchip_spi_remove(struct platform_device *pdev) struct spi_controller *ctlr = spi_controller_get(platform_get_drvdata(pdev)); struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); + if (IS_ENABLED(CONFIG_SPI_ROCKCHIP_MISCDEV)) + misc_deregister(&rs->miscdev); + pm_runtime_get_sync(&pdev->dev); clk_disable_unprepare(rs->sclk_in); From fda1cfae99dc341168aaaebf701264b2c3b98a84 Mon Sep 17 00:00:00 2001 From: David Wu Date: Mon, 11 Apr 2022 16:11:48 +0800 Subject: [PATCH 191/204] ARM: dts: rockchip: rk3288-evb: Change rgmii clock mode from input to output for gmac Signed-off-by: David Wu Change-Id: Ia73346adb607744bd037c7b255ba1647678ad77c --- arch/arm/boot/dts/rk3288-evb-rk1608.dts | 7 ++++--- arch/arm/boot/dts/rk3288-evb.dtsi | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-evb-rk1608.dts b/arch/arm/boot/dts/rk3288-evb-rk1608.dts index ff1f97f08d7c..f65da82f79d5 100644 --- a/arch/arm/boot/dts/rk3288-evb-rk1608.dts +++ b/arch/arm/boot/dts/rk3288-evb-rk1608.dts @@ -423,12 +423,13 @@ &gmac { phy-supply = <&vccio_pmu>; phy-mode = "rgmii"; - clock_in_out = "input"; + clock_in_out = "output"; + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&cru PLL_NPLL>; + assigned-clock-rates = <125000000>; snps,reset-gpio = <&gpio4 7 0>; snps,reset-active-low; snps,reset-delays-us = <0 10000 50000>; - assigned-clocks = <&cru SCLK_MAC>; - assigned-clock-parents = <&ext_gmac>; pinctrl-names = "default"; pinctrl-0 = <&rgmii_pins>; tx_delay = <0x30>; diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index c4ca73b40d4a..1ca204a8454b 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -237,12 +237,13 @@ &gmac { phy-supply = <&vcc_phy>; phy-mode = "rgmii"; - clock_in_out = "input"; + clock_in_out = "output"; + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&cru PLL_NPLL>; + assigned-clock-rates = <125000000>; snps,reset-gpio = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; snps,reset-active-low; snps,reset-delays-us = <0 10000 1000000>; - assigned-clocks = <&cru SCLK_MAC>; - assigned-clock-parents = <&ext_gmac>; pinctrl-names = "default"; pinctrl-0 = <&rgmii_pins>; tx_delay = <0x30>; From bc2d913a399e735d25fc530b84cc7d4d0f2e2f3e Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Sat, 8 Oct 2022 20:13:59 +0800 Subject: [PATCH 192/204] soc: rockchip: opp_select: dump current opp state when panic for cpu/ddr panic log: cpu cpu6: cur_freq: 1008000000 Hz, volt_vdd: 675000 uV, volt_mem: 675000 uV cpu cpu4: cur_freq: 408000000 Hz, volt_vdd: 675000 uV, volt_mem: 675000 uV cpu cpu0: cur_freq: 816000000 Hz, volt_vdd: 675000 uV, volt_mem: 675000 uV rockchip-dmc dmc: cur_freq: 528000000 Hz, volt_vdd: 675000 uV, volt_mem: 700000 uV Change-Id: I29ea94cc9deaba0e1d285390312256567708d6ef Signed-off-by: Liang Chen --- drivers/cpufreq/rockchip-cpufreq.c | 21 +++++++++++ drivers/devfreq/rockchip_dmc.c | 18 ++++++++++ drivers/soc/rockchip/rockchip_opp_select.c | 42 ++++++++++++++++++++++ include/soc/rockchip/rockchip_opp_select.h | 6 ++++ 4 files changed, 87 insertions(+) diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index 0067a0cfd708..699f53e15ece 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -899,6 +899,22 @@ static struct notifier_block rockchip_cpufreq_transition_notifier_block = { .notifier_call = rockchip_cpufreq_transition_notifier, }; +static int rockchip_cpufreq_panic_notifier(struct notifier_block *nb, + unsigned long v, void *p) +{ + struct cluster_info *ci; + + list_for_each_entry(ci, &cluster_info_list, list_head) { + rockchip_opp_dump_cur_state(ci->opp_info.dev); + } + + return 0; +} + +static struct notifier_block rockchip_cpufreq_panic_notifier_block = { + .notifier_call = rockchip_cpufreq_panic_notifier, +}; + static int __init rockchip_cpufreq_driver_init(void) { struct cluster_info *cluster, *pos; @@ -948,6 +964,11 @@ static int __init rockchip_cpufreq_driver_init(void) #endif } + ret = atomic_notifier_chain_register(&panic_notifier_list, + &rockchip_cpufreq_panic_notifier_block); + if (ret) + pr_err("failed to register cpufreq panic notifier\n"); + return PTR_ERR_OR_ZERO(platform_device_register_data(NULL, "cpufreq-dt", -1, (void *)&pdata, sizeof(struct cpufreq_dt_platform_data))); diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 1cdb66af9084..4348297316e0 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -118,6 +118,7 @@ struct rockchip_dmcfreq { struct regulator *vdd_center; struct regulator *mem_reg; struct notifier_block status_nb; + struct notifier_block panic_nb; struct list_head video_info_list; struct freq_map_table *cpu_bw_tbl; struct work_struct boost_work; @@ -2576,6 +2577,17 @@ next: return NOTIFY_OK; } +static int rockchip_dmcfreq_panic_notifier(struct notifier_block *nb, + unsigned long v, void *p) +{ + struct rockchip_dmcfreq *dmcfreq = + container_of(nb, struct rockchip_dmcfreq, panic_nb); + + rockchip_opp_dump_cur_state(dmcfreq->dev); + + return 0; +} + static ssize_t rockchip_dmcfreq_status_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -3129,6 +3141,12 @@ static void rockchip_dmcfreq_register_notifier(struct rockchip_dmcfreq *dmcfreq) if (ret) dev_err(dmcfreq->dev, "failed to register system_status nb\n"); + dmcfreq->panic_nb.notifier_call = rockchip_dmcfreq_panic_notifier; + ret = atomic_notifier_chain_register(&panic_notifier_list, + &dmcfreq->panic_nb); + if (ret) + dev_err(dmcfreq->dev, "failed to register panic nb\n"); + dmc_mdevp.data = dmcfreq->info.devfreq; dmcfreq->mdev_info = rockchip_system_monitor_register(dmcfreq->dev, &dmc_mdevp); diff --git a/drivers/soc/rockchip/rockchip_opp_select.c b/drivers/soc/rockchip/rockchip_opp_select.c index 2c50c0e57215..4a50b4a6a347 100644 --- a/drivers/soc/rockchip/rockchip_opp_select.c +++ b/drivers/soc/rockchip/rockchip_opp_select.c @@ -1728,6 +1728,48 @@ out: } EXPORT_SYMBOL(rockchip_init_opp_table); +int rockchip_opp_dump_cur_state(struct device *dev) +{ + struct clk *clk; + struct opp_table *opp_table; + int volt_vdd, volt_mem; + + if (!dev) + return -ENODEV; + + opp_table = dev_pm_opp_get_opp_table(dev); + if (IS_ERR(opp_table)) { + dev_err(dev, "%s: device opp doesn't exist\n", __func__); + return PTR_ERR(opp_table); + } + + clk = opp_table->clk; + if (IS_ERR(clk)) { + dev_err(dev, "%s: No clock available for the device\n", + __func__); + dev_pm_opp_put_opp_table(opp_table); + return PTR_ERR(clk); + } + + if (opp_table->regulator_count == 1) { + volt_vdd = regulator_get_voltage(opp_table->regulators[0]); + dev_info(dev, "cur_freq: %lu Hz, volt: %d uV\n", + clk_get_rate(clk), volt_vdd); + } + + if (opp_table->regulator_count == 2) { + volt_vdd = regulator_get_voltage(opp_table->regulators[0]); + volt_mem = regulator_get_voltage(opp_table->regulators[1]); + dev_info(dev, "cur_freq: %lu Hz, volt_vdd: %d uV, volt_mem: %d uV\n", + clk_get_rate(clk), volt_vdd, volt_mem); + } + + dev_pm_opp_put_opp_table(opp_table); + + return 0; +} +EXPORT_SYMBOL(rockchip_opp_dump_cur_state); + MODULE_DESCRIPTION("ROCKCHIP OPP Select"); MODULE_AUTHOR("Finley Xiao , Liang Chen "); MODULE_LICENSE("GPL"); diff --git a/include/soc/rockchip/rockchip_opp_select.h b/include/soc/rockchip/rockchip_opp_select.h index da9cab568295..35353d8ade6d 100644 --- a/include/soc/rockchip/rockchip_opp_select.h +++ b/include/soc/rockchip/rockchip_opp_select.h @@ -107,6 +107,7 @@ int rockchip_set_intermediate_rate(struct device *dev, int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info, char *lkg_name, char *reg_name); +int rockchip_opp_dump_cur_state(struct device *dev); #else static inline int rockchip_of_get_leakage(struct device *dev, char *lkg_name, int *leakage) @@ -226,6 +227,11 @@ static inline int rockchip_init_opp_table(struct device *dev, return -EOPNOTSUPP; } +static inline int rockchip_opp_dump_cur_state(struct device *dev) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_ROCKCHIP_OPP */ #endif From 379474682f9fdd191e6ef59bb9f8fdedccb0470b Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 30 Sep 2022 01:46:16 +0000 Subject: [PATCH 193/204] drm/rockchip: Add return value to .loader_protect() Callback loader_protect() maybe failed. Signed-off-by: Wyon Bi Change-Id: Icb9a25701929c79b94c9a63568a408913e49f87c --- .../drm/bridge/analogix/analogix_dp_core.c | 14 ++++++++++-- .../gpu/drm/rockchip/analogix_dp-rockchip.c | 22 ++++++++++++++----- drivers/gpu/drm/rockchip/dw-dp.c | 4 +++- .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 4 +++- .../gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c | 4 +++- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 6 +++-- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_logo.c | 12 ++++++++-- drivers/gpu/drm/rockchip/rockchip_lvds.c | 6 +++-- drivers/gpu/drm/rockchip/rockchip_rgb.c | 8 ++++--- include/drm/bridge/analogix_dp.h | 1 + 11 files changed, 62 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 33e3787bcf2a..592efc5318dd 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1714,6 +1714,12 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) dp->dpms_mode = DRM_MODE_DPMS_OFF; } +void analogix_dp_disable(struct analogix_dp_device *dp) +{ + analogix_dp_bridge_disable(&dp->bridge); +} +EXPORT_SYMBOL_GPL(analogix_dp_disable); + static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) @@ -2105,15 +2111,19 @@ int analogix_dp_loader_protect(struct analogix_dp_device *dp) ret = analogix_dp_fast_link_train_detection(dp); if (ret) - return ret; + goto err_disable; if (analogix_dp_detect_sink_psr(dp)) { ret = analogix_dp_enable_sink_psr(dp); if (ret) - return ret; + goto err_disable; } return 0; + +err_disable: + analogix_dp_disable(dp); + return ret; } EXPORT_SYMBOL_GPL(analogix_dp_loader_protect); diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 325ddd1fb21a..3d489d9609f2 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -232,25 +232,35 @@ static int rockchip_dp_get_modes(struct analogix_dp_plat_data *plat_data, return 0; } -static void rockchip_dp_loader_protect(struct drm_encoder *encoder, bool on) +static int rockchip_dp_loader_protect(struct drm_encoder *encoder, bool on) { struct rockchip_dp_device *dp = to_dp(encoder); struct analogix_dp_plat_data *plat_data = &dp->plat_data; + struct rockchip_dp_device *secondary = NULL; + int ret; if (plat_data->right) { - struct rockchip_dp_device *secondary = - rockchip_dp_find_by_id(dp->dev->driver, !dp->id); + secondary = rockchip_dp_find_by_id(dp->dev->driver, !dp->id); - rockchip_dp_loader_protect(&secondary->encoder, on); + ret = rockchip_dp_loader_protect(&secondary->encoder, on); + if (ret) + return ret; } if (!on) - return; + return 0; if (plat_data->panel) panel_simple_loader_protect(plat_data->panel); - analogix_dp_loader_protect(dp->adp); + ret = analogix_dp_loader_protect(dp->adp); + if (ret) { + if (secondary) + analogix_dp_disable(secondary->adp); + return ret; + } + + return 0; } static bool rockchip_dp_skip_connector(struct drm_bridge *bridge) diff --git a/drivers/gpu/drm/rockchip/dw-dp.c b/drivers/gpu/drm/rockchip/dw-dp.c index 37fb38b908cb..b0f2c05f4c83 100644 --- a/drivers/gpu/drm/rockchip/dw-dp.c +++ b/drivers/gpu/drm/rockchip/dw-dp.c @@ -2106,13 +2106,15 @@ static void _dw_dp_loader_protect(struct dw_dp *dp, bool on) } } -static void dw_dp_loader_protect(struct drm_encoder *encoder, bool on) +static int dw_dp_loader_protect(struct drm_encoder *encoder, bool on) { struct dw_dp *dp = encoder_to_dp(encoder); _dw_dp_loader_protect(dp, on); if (dp->right) _dw_dp_loader_protect(dp->right, on); + + return 0; } static int dw_dp_connector_init(struct dw_dp *dp) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index a052e6228f84..6922f56d1fad 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -830,7 +830,7 @@ static void dw_mipi_dsi_rockchip_loader_protect(struct dw_mipi_dsi_rockchip *dsi dw_mipi_dsi_rockchip_loader_protect(dsi->slave, on); } -static void dw_mipi_dsi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, +static int dw_mipi_dsi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, bool on) { struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder); @@ -839,6 +839,8 @@ static void dw_mipi_dsi_rockchip_encoder_loader_protect(struct drm_encoder *enco panel_simple_loader_protect(dsi->panel); dw_mipi_dsi_rockchip_loader_protect(dsi, on); + + return 0; } static const struct drm_encoder_helper_funcs diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c index ff36a8aeb907..f55a3a5c5c7c 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c @@ -962,7 +962,7 @@ static void dw_mipi_dsi2_loader_protect(struct dw_mipi_dsi2 *dsi2, bool on) dw_mipi_dsi2_loader_protect(dsi2->slave, on); } -static void dw_mipi_dsi2_encoder_loader_protect(struct drm_encoder *encoder, +static int dw_mipi_dsi2_encoder_loader_protect(struct drm_encoder *encoder, bool on) { struct dw_mipi_dsi2 *dsi2 = encoder_to_dsi2(encoder); @@ -971,6 +971,8 @@ static void dw_mipi_dsi2_encoder_loader_protect(struct drm_encoder *encoder, panel_simple_loader_protect(dsi2->panel); dw_mipi_dsi2_loader_protect(dsi2, on); + + return 0; } static const struct drm_encoder_helper_funcs diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 31eebd779955..d1af980127b1 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -1573,7 +1573,7 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) ret ? "LIT" : "BIG"); } -static void dw_hdmi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, +static int dw_hdmi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, bool on) { struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); @@ -1584,7 +1584,7 @@ static void dw_hdmi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, ret = clk_prepare_enable(hdmi->link_clk); if (ret < 0) { DRM_DEV_ERROR(hdmi->dev, "failed to enable link_clk %d\n", ret); - return; + return ret; } } @@ -1593,6 +1593,8 @@ static void dw_hdmi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, clk_disable_unprepare(hdmi->link_clk); hdmi->phy->power_count--; } + + return 0; } static void rk3588_set_link_mode(struct rockchip_hdmi *hdmi) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 424273d61ae4..434d3c93271b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -90,7 +90,7 @@ struct rockchip_drm_sub_dev { struct list_head list; struct drm_connector *connector; struct device_node *of_node; - void (*loader_protect)(struct drm_encoder *encoder, bool on); + int (*loader_protect)(struct drm_encoder *encoder, bool on); void (*oob_hotplug_event)(struct drm_connector *connector); void (*update_vfp_for_vrr)(struct drm_connector *connector, struct drm_display_mode *mode, int vfp); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c index eae4605aa2c7..d0fcbb5c47a4 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c @@ -657,8 +657,16 @@ static int setup_initial_state(struct drm_device *drm_dev, else conn_state->best_encoder = rockchip_drm_connector_get_single_encoder(connector); - if (set->sub_dev->loader_protect) - set->sub_dev->loader_protect(conn_state->best_encoder, true); + if (set->sub_dev->loader_protect) { + ret = set->sub_dev->loader_protect(conn_state->best_encoder, true); + if (ret) { + dev_err(drm_dev->dev, + "connector[%s] loader protect failed\n", + connector->name); + return ret; + } + } + num_modes = rockchip_drm_fill_connector_modes(connector, 7680, 7680, set->force_output); if (!num_modes) { dev_err(drm_dev->dev, "connector[%s] can't found any modes\n", diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index ca2838db89eb..ce4b3a251146 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -318,13 +318,15 @@ static void rockchip_lvds_encoder_disable(struct drm_encoder *encoder) drm_panel_unprepare(lvds->panel); } -static void rockchip_lvds_encoder_loader_protect(struct drm_encoder *encoder, - bool on) +static int rockchip_lvds_encoder_loader_protect(struct drm_encoder *encoder, + bool on) { struct rockchip_lvds *lvds = encoder_to_lvds(encoder); if (lvds->panel) panel_simple_loader_protect(lvds->panel); + + return 0; } static const diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c index 972cbc8a6708..c6ca9596ca1f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c @@ -308,8 +308,8 @@ rockchip_rgb_encoder_atomic_check(struct drm_encoder *encoder, return 0; } -static void rockchip_rgb_encoder_loader_protect(struct drm_encoder *encoder, - bool on) +static int rockchip_rgb_encoder_loader_protect(struct drm_encoder *encoder, + bool on) { struct rockchip_rgb *rgb = encoder_to_rgb(encoder); @@ -319,11 +319,13 @@ static void rockchip_rgb_encoder_loader_protect(struct drm_encoder *encoder, mcu_panel->prepared = true; mcu_panel->enabled = true; - return; + return 0; } if (rgb->panel) panel_simple_loader_protect(rgb->panel); + + return 0; } static enum drm_mode_status diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h index bc5e8edf8d7d..e912503a9149 100644 --- a/include/drm/bridge/analogix_dp.h +++ b/include/drm/bridge/analogix_dp.h @@ -80,5 +80,6 @@ int analogix_dp_audio_startup(struct analogix_dp_device *dp); int analogix_dp_audio_get_eld(struct analogix_dp_device *dp, u8 *buf, size_t len); int analogix_dp_loader_protect(struct analogix_dp_device *dp); +void analogix_dp_disable(struct analogix_dp_device *dp); #endif /* _ANALOGIX_DP_H_ */ From beaac7714a793bbc111647d16d57aa98309dd698 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 30 Sep 2022 01:18:21 +0000 Subject: [PATCH 194/204] drm/bridge: analogix_dp: Check link status in loader_protect() Signed-off-by: Wyon Bi Change-Id: I8816a0527eb7a1c1d3a2d7b7480057b888e375e0 --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 592efc5318dd..456d33c36d69 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -2099,6 +2099,7 @@ static void analogix_dp_link_train_restore(struct analogix_dp_device *dp) int analogix_dp_loader_protect(struct analogix_dp_device *dp) { + u8 link_status[DP_LINK_STATUS_SIZE]; int ret; ret = analogix_dp_phy_power_on(dp); @@ -2119,6 +2120,18 @@ int analogix_dp_loader_protect(struct analogix_dp_device *dp) goto err_disable; } + ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status); + if (ret < 0) { + dev_err(dp->dev, "Failed to read link status\n"); + goto err_disable; + } + + if (!drm_dp_channel_eq_ok(link_status, dp->link_train.lane_count)) { + dev_err(dp->dev, "Channel EQ or CR not ok\n"); + ret = -EINVAL; + goto err_disable; + } + return 0; err_disable: From a34aa766dc9b2ecb5b79b03ced0af85628f093cc Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Sat, 8 Oct 2022 21:00:19 +0800 Subject: [PATCH 195/204] media: rockchip: isp: fix scl for unite mode Change-Id: Ic224cfa5956ed1dea523e608ceed46be0c2dd49c Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/regs.c | 35 ++++++++++++++-------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/regs.c b/drivers/media/platform/rockchip/isp/regs.c index fd77e13c4d4b..eef92d66eee3 100644 --- a/drivers/media/platform/rockchip/isp/regs.c +++ b/drivers/media/platform/rockchip/isp/regs.c @@ -233,24 +233,35 @@ static void set_scale(struct rkisp_stream *stream, struct v4l2_rect *in_y, ISP3X_MAIN_RESIZE_IN_CROP_OFFSET : ISP3X_SELF_RESIZE_IN_CROP_OFFSET; u32 isp_in_w = in_y->width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; u32 scl_w = out_y->width / 2; - u32 left_y = DIV_ROUND_UP(scl_w * 65536, scale_hy); - u32 left_c = DIV_ROUND_UP(scl_w * 65536 / 2, scale_hc); + u32 left_y = scale_hy == 1 ? scl_w : DIV_ROUND_UP(scl_w * 65536, scale_hy); + u32 left_c = scale_hc == 1 ? scl_w / 2 : DIV_ROUND_UP(scl_w * 65536 / 2, scale_hc); u32 phase_src_y = left_y * scale_hy; u32 phase_dst_y = scl_w * 65536; - u32 phase_left_y = scale_hy - (phase_src_y - phase_dst_y); + u32 phase_left_y = scale_hy == 1 ? 0 : scale_hy - (phase_src_y - phase_dst_y); u32 phase_src_c = left_c * scale_hc; u32 phase_dst_c = scl_w * 65536 / 2; - u32 phase_left_c = scale_hc - (phase_src_c - phase_dst_c); - u32 right_y = phase_left_y ? - in_y->width - (left_y - 1) : - in_y->width - left_y; - u32 right_c = phase_left_c ? - in_y->width - (left_c - 1) * 2 : - in_y->width - left_c * 2; + u32 phase_left_c = scale_hc == 1 ? 0 : scale_hc - (phase_src_c - phase_dst_c); + u32 right_y = phase_left_y ? in_y->width - (left_y - 1) : in_y->width - left_y; + u32 right_c = phase_left_c ? in_y->width - (left_c - 1) * 2 : in_y->width - left_c * 2; u32 right_crop_y = isp_in_w - right_y; u32 right_crop_c = isp_in_w - right_c; - u32 right_scl_in_y = right_crop_y - RKMOUDLE_UNITE_EXTEND_PIXEL; - u32 right_scl_in_c = right_crop_c - RKMOUDLE_UNITE_EXTEND_PIXEL; + u32 extend = RKMOUDLE_UNITE_EXTEND_PIXEL; + u32 right_scl_in_y; + u32 right_scl_in_c; + + if (right_crop_y < RKMOUDLE_UNITE_EXTEND_PIXEL) { + u32 reg; + + extend = right_crop_y & ~0x1; + reg = stream->config->dual_crop.h_offset; + rkisp_next_write(dev, reg, extend, false); + reg = stream->config->dual_crop.h_size; + rkisp_next_write(dev, reg, isp_in_w - extend, false); + reg = stream->config->dual_crop.ctrl; + rkisp_next_write(dev, reg, rkisp_next_read_reg_cache(dev, reg), false); + } + right_scl_in_y = right_crop_y - extend; + right_scl_in_c = right_crop_c - extend; /* left isp */ rkisp_write(dev, hy_size_reg, scl_w, false); From a366f684c2ab0815d801d6fd2ff5a73d292c6102 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Sun, 9 Oct 2022 10:37:13 +0800 Subject: [PATCH 196/204] arm64: dts: rockchip: rk3588s: Fix spi driver strength Except spi2m2 which is used for pmic. all spi change from 33ohm to 40ohm to avoid overcharge. Change-Id: Ib1f613b19c1ca9f978c11a7d26422ff66b4b910c Signed-off-by: Jon Lin --- .../boot/dts/rockchip/rk3588s-pinctrl.dtsi | 138 +++++++++--------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi index 3673af66be55..0aceee389623 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi @@ -2527,97 +2527,97 @@ spi0m0_pins: spi0m0-pins { rockchip,pins = /* spi0_clk_m0 */ - <0 RK_PC6 8 &pcfg_pull_up_drv_level_1>, + <0 RK_PC6 8 &pcfg_pull_up_drv_level_6>, /* spi0_miso_m0 */ - <0 RK_PC7 8 &pcfg_pull_up_drv_level_1>, + <0 RK_PC7 8 &pcfg_pull_up_drv_level_6>, /* spi0_mosi_m0 */ - <0 RK_PC0 8 &pcfg_pull_up_drv_level_1>; + <0 RK_PC0 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi0m0_cs0: spi0m0-cs0 { rockchip,pins = /* spi0_cs0_m0 */ - <0 RK_PD1 8 &pcfg_pull_up_drv_level_1>; + <0 RK_PD1 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi0m0_cs1: spi0m0-cs1 { rockchip,pins = /* spi0_cs1_m0 */ - <0 RK_PB7 8 &pcfg_pull_up_drv_level_1>; + <0 RK_PB7 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi0m1_pins: spi0m1-pins { rockchip,pins = /* spi0_clk_m1 */ - <4 RK_PA2 8 &pcfg_pull_up_drv_level_1>, + <4 RK_PA2 8 &pcfg_pull_up_drv_level_6>, /* spi0_miso_m1 */ - <4 RK_PA0 8 &pcfg_pull_up_drv_level_1>, + <4 RK_PA0 8 &pcfg_pull_up_drv_level_6>, /* spi0_mosi_m1 */ - <4 RK_PA1 8 &pcfg_pull_up_drv_level_1>; + <4 RK_PA1 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi0m1_cs0: spi0m1-cs0 { rockchip,pins = /* spi0_cs0_m1 */ - <4 RK_PB2 8 &pcfg_pull_up_drv_level_1>; + <4 RK_PB2 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi0m1_cs1: spi0m1-cs1 { rockchip,pins = /* spi0_cs1_m1 */ - <4 RK_PB1 8 &pcfg_pull_up_drv_level_1>; + <4 RK_PB1 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi0m2_pins: spi0m2-pins { rockchip,pins = /* spi0_clk_m2 */ - <1 RK_PB3 8 &pcfg_pull_up_drv_level_1>, + <1 RK_PB3 8 &pcfg_pull_up_drv_level_6>, /* spi0_miso_m2 */ - <1 RK_PB1 8 &pcfg_pull_up_drv_level_1>, + <1 RK_PB1 8 &pcfg_pull_up_drv_level_6>, /* spi0_mosi_m2 */ - <1 RK_PB2 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PB2 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi0m2_cs0: spi0m2-cs0 { rockchip,pins = /* spi0_cs0_m2 */ - <1 RK_PB4 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PB4 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi0m2_cs1: spi0m2-cs1 { rockchip,pins = /* spi0_cs1_m2 */ - <1 RK_PB5 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PB5 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi0m3_pins: spi0m3-pins { rockchip,pins = /* spi0_clk_m3 */ - <3 RK_PD3 8 &pcfg_pull_up_drv_level_1>, + <3 RK_PD3 8 &pcfg_pull_up_drv_level_6>, /* spi0_miso_m3 */ - <3 RK_PD1 8 &pcfg_pull_up_drv_level_1>, + <3 RK_PD1 8 &pcfg_pull_up_drv_level_6>, /* spi0_mosi_m3 */ - <3 RK_PD2 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PD2 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi0m3_cs0: spi0m3-cs0 { rockchip,pins = /* spi0_cs0_m3 */ - <3 RK_PD4 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PD4 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi0m3_cs1: spi0m3-cs1 { rockchip,pins = /* spi0_cs1_m3 */ - <3 RK_PD5 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PD5 8 &pcfg_pull_up_drv_level_6>; }; }; @@ -2626,50 +2626,50 @@ spi1m1_pins: spi1m1-pins { rockchip,pins = /* spi1_clk_m1 */ - <3 RK_PC1 8 &pcfg_pull_up_drv_level_1>, + <3 RK_PC1 8 &pcfg_pull_up_drv_level_6>, /* spi1_miso_m1 */ - <3 RK_PC0 8 &pcfg_pull_up_drv_level_1>, + <3 RK_PC0 8 &pcfg_pull_up_drv_level_6>, /* spi1_mosi_m1 */ - <3 RK_PB7 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PB7 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi1m1_cs0: spi1m1-cs0 { rockchip,pins = /* spi1_cs0_m1 */ - <3 RK_PC2 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PC2 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi1m1_cs1: spi1m1-cs1 { rockchip,pins = /* spi1_cs1_m1 */ - <3 RK_PC3 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PC3 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi1m2_pins: spi1m2-pins { rockchip,pins = /* spi1_clk_m2 */ - <1 RK_PD2 8 &pcfg_pull_up_drv_level_1>, + <1 RK_PD2 8 &pcfg_pull_up_drv_level_6>, /* spi1_miso_m2 */ - <1 RK_PD0 8 &pcfg_pull_up_drv_level_1>, + <1 RK_PD0 8 &pcfg_pull_up_drv_level_6>, /* spi1_mosi_m2 */ - <1 RK_PD1 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PD1 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi1m2_cs0: spi1m2-cs0 { rockchip,pins = /* spi1_cs0_m2 */ - <1 RK_PD3 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PD3 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi1m2_cs1: spi1m2-cs1 { rockchip,pins = /* spi1_cs1_m2 */ - <1 RK_PD5 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PD5 8 &pcfg_pull_up_drv_level_6>; }; }; @@ -2678,50 +2678,50 @@ spi2m0_pins: spi2m0-pins { rockchip,pins = /* spi2_clk_m0 */ - <1 RK_PA6 8 &pcfg_pull_up_drv_level_1>, + <1 RK_PA6 8 &pcfg_pull_up_drv_level_6>, /* spi2_miso_m0 */ - <1 RK_PA4 8 &pcfg_pull_up_drv_level_1>, + <1 RK_PA4 8 &pcfg_pull_up_drv_level_6>, /* spi2_mosi_m0 */ - <1 RK_PA5 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PA5 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi2m0_cs0: spi2m0-cs0 { rockchip,pins = /* spi2_cs0_m0 */ - <1 RK_PA7 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PA7 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi2m0_cs1: spi2m0-cs1 { rockchip,pins = /* spi2_cs1_m0 */ - <1 RK_PB0 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PB0 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi2m1_pins: spi2m1-pins { rockchip,pins = /* spi2_clk_m1 */ - <4 RK_PA6 8 &pcfg_pull_up_drv_level_1>, + <4 RK_PA6 8 &pcfg_pull_up_drv_level_6>, /* spi2_miso_m1 */ - <4 RK_PA4 8 &pcfg_pull_up_drv_level_1>, + <4 RK_PA4 8 &pcfg_pull_up_drv_level_6>, /* spi2_mosi_m1 */ - <4 RK_PA5 8 &pcfg_pull_up_drv_level_1>; + <4 RK_PA5 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi2m1_cs0: spi2m1-cs0 { rockchip,pins = /* spi2_cs0_m1 */ - <4 RK_PA7 8 &pcfg_pull_up_drv_level_1>; + <4 RK_PA7 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi2m1_cs1: spi2m1-cs1 { rockchip,pins = /* spi2_cs1_m1 */ - <4 RK_PB0 8 &pcfg_pull_up_drv_level_1>; + <4 RK_PB0 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ @@ -2755,75 +2755,75 @@ spi3m1_pins: spi3m1-pins { rockchip,pins = /* spi3_clk_m1 */ - <4 RK_PB7 8 &pcfg_pull_up_drv_level_1>, + <4 RK_PB7 8 &pcfg_pull_up_drv_level_6>, /* spi3_miso_m1 */ - <4 RK_PB5 8 &pcfg_pull_up_drv_level_1>, + <4 RK_PB5 8 &pcfg_pull_up_drv_level_6>, /* spi3_mosi_m1 */ - <4 RK_PB6 8 &pcfg_pull_up_drv_level_1>; + <4 RK_PB6 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi3m1_cs0: spi3m1-cs0 { rockchip,pins = /* spi3_cs0_m1 */ - <4 RK_PC0 8 &pcfg_pull_up_drv_level_1>; + <4 RK_PC0 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi3m1_cs1: spi3m1-cs1 { rockchip,pins = /* spi3_cs1_m1 */ - <4 RK_PC1 8 &pcfg_pull_up_drv_level_1>; + <4 RK_PC1 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi3m2_pins: spi3m2-pins { rockchip,pins = /* spi3_clk_m2 */ - <0 RK_PD3 8 &pcfg_pull_up_drv_level_1>, + <0 RK_PD3 8 &pcfg_pull_up_drv_level_6>, /* spi3_miso_m2 */ - <0 RK_PD0 8 &pcfg_pull_up_drv_level_1>, + <0 RK_PD0 8 &pcfg_pull_up_drv_level_6>, /* spi3_mosi_m2 */ - <0 RK_PD2 8 &pcfg_pull_up_drv_level_1>; + <0 RK_PD2 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi3m2_cs0: spi3m2-cs0 { rockchip,pins = /* spi3_cs0_m2 */ - <0 RK_PD4 8 &pcfg_pull_up_drv_level_1>; + <0 RK_PD4 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi3m2_cs1: spi3m2-cs1 { rockchip,pins = /* spi3_cs1_m2 */ - <0 RK_PD5 8 &pcfg_pull_up_drv_level_1>; + <0 RK_PD5 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi3m3_pins: spi3m3-pins { rockchip,pins = /* spi3_clk_m3 */ - <3 RK_PD0 8 &pcfg_pull_up_drv_level_1>, + <3 RK_PD0 8 &pcfg_pull_up_drv_level_6>, /* spi3_miso_m3 */ - <3 RK_PC6 8 &pcfg_pull_up_drv_level_1>, + <3 RK_PC6 8 &pcfg_pull_up_drv_level_6>, /* spi3_mosi_m3 */ - <3 RK_PC7 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PC7 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi3m3_cs0: spi3m3-cs0 { rockchip,pins = /* spi3_cs0_m3 */ - <3 RK_PC4 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PC4 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi3m3_cs1: spi3m3-cs1 { rockchip,pins = /* spi3_cs1_m3 */ - <3 RK_PC5 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PC5 8 &pcfg_pull_up_drv_level_6>; }; }; @@ -2832,68 +2832,68 @@ spi4m0_pins: spi4m0-pins { rockchip,pins = /* spi4_clk_m0 */ - <1 RK_PC2 8 &pcfg_pull_up_drv_level_1>, + <1 RK_PC2 8 &pcfg_pull_up_drv_level_6>, /* spi4_miso_m0 */ - <1 RK_PC0 8 &pcfg_pull_up_drv_level_1>, + <1 RK_PC0 8 &pcfg_pull_up_drv_level_6>, /* spi4_mosi_m0 */ - <1 RK_PC1 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PC1 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi4m0_cs0: spi4m0-cs0 { rockchip,pins = /* spi4_cs0_m0 */ - <1 RK_PC3 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PC3 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi4m0_cs1: spi4m0-cs1 { rockchip,pins = /* spi4_cs1_m0 */ - <1 RK_PC4 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PC4 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi4m1_pins: spi4m1-pins { rockchip,pins = /* spi4_clk_m1 */ - <3 RK_PA2 8 &pcfg_pull_up_drv_level_1>, + <3 RK_PA2 8 &pcfg_pull_up_drv_level_6>, /* spi4_miso_m1 */ - <3 RK_PA0 8 &pcfg_pull_up_drv_level_1>, + <3 RK_PA0 8 &pcfg_pull_up_drv_level_6>, /* spi4_mosi_m1 */ - <3 RK_PA1 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PA1 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi4m1_cs0: spi4m1-cs0 { rockchip,pins = /* spi4_cs0_m1 */ - <3 RK_PA3 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PA3 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi4m1_cs1: spi4m1-cs1 { rockchip,pins = /* spi4_cs1_m1 */ - <3 RK_PA4 8 &pcfg_pull_up_drv_level_1>; + <3 RK_PA4 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi4m2_pins: spi4m2-pins { rockchip,pins = /* spi4_clk_m2 */ - <1 RK_PA2 8 &pcfg_pull_up_drv_level_1>, + <1 RK_PA2 8 &pcfg_pull_up_drv_level_6>, /* spi4_miso_m2 */ - <1 RK_PA0 8 &pcfg_pull_up_drv_level_1>, + <1 RK_PA0 8 &pcfg_pull_up_drv_level_6>, /* spi4_mosi_m2 */ - <1 RK_PA1 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PA1 8 &pcfg_pull_up_drv_level_6>; }; /omit-if-no-ref/ spi4m2_cs0: spi4m2-cs0 { rockchip,pins = /* spi4_cs0_m2 */ - <1 RK_PA3 8 &pcfg_pull_up_drv_level_1>; + <1 RK_PA3 8 &pcfg_pull_up_drv_level_6>; }; }; From 6ab995ba9733ecbae7d6fa598999ddc762ad0da9 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Sun, 2 Oct 2022 14:32:44 +0800 Subject: [PATCH 197/204] media: i2c: SmartSens sensor driver fixed modify fps error Signed-off-by: Zefa Chen Change-Id: Idd09bfac19006e47340660f3f7c0c774240caf42 --- drivers/media/i2c/sc031gs.c | 4 ++-- drivers/media/i2c/sc035gs.c | 4 ++-- drivers/media/i2c/sc132gs.c | 4 ++-- drivers/media/i2c/sc210iot.c | 4 ++-- drivers/media/i2c/sc2232.c | 4 ++-- drivers/media/i2c/sc2239.c | 4 ++-- drivers/media/i2c/sc230ai.c | 4 ++-- drivers/media/i2c/sc2310.c | 4 ++-- drivers/media/i2c/sc301iot.c | 4 ++-- drivers/media/i2c/sc3336.c | 4 ++-- drivers/media/i2c/sc3338.c | 4 ++-- drivers/media/i2c/sc401ai.c | 4 ++-- drivers/media/i2c/sc4210.c | 4 ++-- drivers/media/i2c/sc4238.c | 4 ++-- drivers/media/i2c/sc430cs.c | 4 ++-- drivers/media/i2c/sc4336.c | 4 ++-- drivers/media/i2c/sc500ai.c | 4 ++-- drivers/media/i2c/sc530ai.c | 11 ++++++----- 18 files changed, 40 insertions(+), 39 deletions(-) diff --git a/drivers/media/i2c/sc031gs.c b/drivers/media/i2c/sc031gs.c index bd6f9eeb7bc7..854c2a0f9ee7 100644 --- a/drivers/media/i2c/sc031gs.c +++ b/drivers/media/i2c/sc031gs.c @@ -999,8 +999,8 @@ static void sc031gs_modify_fps_info(struct sc031gs *sc031gs) { const struct sc031gs_mode *mode = sc031gs->cur_mode; - sc031gs->cur_fps.denominator = mode->max_fps.denominator * sc031gs->cur_vts / - mode->vts_def; + sc031gs->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc031gs->cur_vts; } static int sc031gs_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc035gs.c b/drivers/media/i2c/sc035gs.c index 5814e3f69bda..0001f37d65f8 100644 --- a/drivers/media/i2c/sc035gs.c +++ b/drivers/media/i2c/sc035gs.c @@ -983,8 +983,8 @@ static void sc035gs_modify_fps_info(struct sc035gs *sc035gs) { const struct sc035gs_mode *mode = sc035gs->cur_mode; - sc035gs->cur_fps.denominator = mode->max_fps.denominator * sc035gs->cur_vts / - mode->vts_def; + sc035gs->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc035gs->cur_vts; } static int sc035gs_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc132gs.c b/drivers/media/i2c/sc132gs.c index ae2f3177be7f..dd6b63e28db2 100644 --- a/drivers/media/i2c/sc132gs.c +++ b/drivers/media/i2c/sc132gs.c @@ -1098,8 +1098,8 @@ static void sc132gs_modify_fps_info(struct sc132gs *sc132gs) { const struct sc132gs_mode *mode = sc132gs->cur_mode; - sc132gs->cur_fps.denominator = mode->max_fps.denominator * sc132gs->cur_vts / - mode->vts_def; + sc132gs->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc132gs->cur_vts; } static int sc132gs_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc210iot.c b/drivers/media/i2c/sc210iot.c index ba1d93534558..d5a2f6777395 100644 --- a/drivers/media/i2c/sc210iot.c +++ b/drivers/media/i2c/sc210iot.c @@ -369,8 +369,8 @@ static void sc210iot_modify_fps_info(struct sc210iot *sc210iot) { const struct sc210iot_mode *mode = sc210iot->cur_mode; - sc210iot->cur_fps.denominator = mode->max_fps.denominator * sc210iot->cur_vts / - mode->vts_def; + sc210iot->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc210iot->cur_vts; } static int sc210iot_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc2232.c b/drivers/media/i2c/sc2232.c index 30294828f872..0278d2f31b55 100644 --- a/drivers/media/i2c/sc2232.c +++ b/drivers/media/i2c/sc2232.c @@ -1161,8 +1161,8 @@ static void sc2232_modify_fps_info(struct sc2232 *sc2232) { const struct sc2232_mode *mode = sc2232->cur_mode; - sc2232->cur_fps.denominator = mode->max_fps.denominator * sc2232->cur_vts / - mode->vts_def; + sc2232->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc2232->cur_vts; } static int sc2232_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc2239.c b/drivers/media/i2c/sc2239.c index c23cee7dd18a..ddc3a90a073e 100644 --- a/drivers/media/i2c/sc2239.c +++ b/drivers/media/i2c/sc2239.c @@ -927,8 +927,8 @@ static void sc2239_modify_fps_info(struct sc2239 *sc2239) { const struct sc2239_mode *mode = sc2239->cur_mode; - sc2239->cur_fps.denominator = mode->max_fps.denominator * sc2239->cur_vts / - mode->vts_def; + sc2239->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc2239->cur_vts; } static int sc2239_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc230ai.c b/drivers/media/i2c/sc230ai.c index 9e76ce5b4db7..e7975c80fa85 100644 --- a/drivers/media/i2c/sc230ai.c +++ b/drivers/media/i2c/sc230ai.c @@ -1385,8 +1385,8 @@ static void sc230ai_modify_fps_info(struct sc230ai *sc230ai) { const struct sc230ai_mode *mode = sc230ai->cur_mode; - sc230ai->cur_fps.denominator = mode->max_fps.denominator * sc230ai->cur_vts / - mode->vts_def; + sc230ai->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc230ai->cur_vts; } static int sc230ai_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc2310.c b/drivers/media/i2c/sc2310.c index 54fad6c12fe7..ac76a27afc83 100644 --- a/drivers/media/i2c/sc2310.c +++ b/drivers/media/i2c/sc2310.c @@ -1574,8 +1574,8 @@ static void sc2310_modify_fps_info(struct sc2310 *sc2310) { const struct sc2310_mode *mode = sc2310->cur_mode; - sc2310->cur_fps.denominator = mode->max_fps.denominator * sc2310->cur_vts / - mode->vts_def; + sc2310->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc2310->cur_vts; } static int sc2310_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc301iot.c b/drivers/media/i2c/sc301iot.c index 4d81b30aa3ba..ff0fa6520284 100644 --- a/drivers/media/i2c/sc301iot.c +++ b/drivers/media/i2c/sc301iot.c @@ -1869,8 +1869,8 @@ static void SC301IOT_modify_fps_info(struct SC301IOT *SC301IOT) { const struct SC301IOT_mode *mode = SC301IOT->cur_mode; - SC301IOT->cur_fps.denominator = mode->max_fps.denominator * SC301IOT->cur_vts / - mode->vts_def; + SC301IOT->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + SC301IOT->cur_vts; } static int SC301IOT_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc3336.c b/drivers/media/i2c/sc3336.c index 690d56cb3ae6..431a0384bebf 100644 --- a/drivers/media/i2c/sc3336.c +++ b/drivers/media/i2c/sc3336.c @@ -1314,8 +1314,8 @@ static void sc3336_modify_fps_info(struct sc3336 *sc3336) { const struct sc3336_mode *mode = sc3336->cur_mode; - sc3336->cur_fps.denominator = mode->max_fps.denominator * sc3336->cur_vts / - mode->vts_def; + sc3336->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc3336->cur_vts; } static int sc3336_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc3338.c b/drivers/media/i2c/sc3338.c index b63e4bcbfaea..ff451cd696a2 100644 --- a/drivers/media/i2c/sc3338.c +++ b/drivers/media/i2c/sc3338.c @@ -1133,8 +1133,8 @@ static void sc3338_modify_fps_info(struct sc3338 *sc3338) { const struct sc3338_mode *mode = sc3338->cur_mode; - sc3338->cur_fps.denominator = mode->max_fps.denominator * sc3338->cur_vts / - mode->vts_def; + sc3338->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc3338->cur_vts; } static int sc3338_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc401ai.c b/drivers/media/i2c/sc401ai.c index 42e43eb39f5a..450fbd8baaf0 100644 --- a/drivers/media/i2c/sc401ai.c +++ b/drivers/media/i2c/sc401ai.c @@ -1267,8 +1267,8 @@ static void sc401ai_modify_fps_info(struct sc401ai *sc401ai) { const struct sc401ai_mode *mode = sc401ai->cur_mode; - sc401ai->cur_fps.denominator = mode->max_fps.denominator * sc401ai->cur_vts / - mode->vts_def; + sc401ai->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc401ai->cur_vts; } static int sc401ai_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc4210.c b/drivers/media/i2c/sc4210.c index 787c1383517f..5f8958f1ad87 100644 --- a/drivers/media/i2c/sc4210.c +++ b/drivers/media/i2c/sc4210.c @@ -2325,8 +2325,8 @@ static void sc4210_modify_fps_info(struct sc4210 *sc4210) { const struct sc4210_mode *mode = sc4210->cur_mode; - sc4210->cur_fps.denominator = mode->max_fps.denominator * sc4210->cur_vts / - mode->vts_def; + sc4210->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc4210->cur_vts; } static int sc4210_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc4238.c b/drivers/media/i2c/sc4238.c index 3ca0a61d461f..8750d5a43427 100644 --- a/drivers/media/i2c/sc4238.c +++ b/drivers/media/i2c/sc4238.c @@ -2410,8 +2410,8 @@ static void sc4238_modify_fps_info(struct sc4238 *sc4238) { const struct sc4238_mode *mode = sc4238->cur_mode; - sc4238->cur_fps.denominator = mode->max_fps.denominator * sc4238->cur_vts / - mode->vts_def; + sc4238->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc4238->cur_vts; } static int sc4238_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc430cs.c b/drivers/media/i2c/sc430cs.c index 1783fd37926f..5900da6887fa 100644 --- a/drivers/media/i2c/sc430cs.c +++ b/drivers/media/i2c/sc430cs.c @@ -1138,8 +1138,8 @@ static void sc430cs_modify_fps_info(struct sc430cs *sc430cs) { const struct sc430cs_mode *mode = sc430cs->cur_mode; - sc430cs->cur_fps.denominator = mode->max_fps.denominator * sc430cs->cur_vts / - mode->vts_def; + sc430cs->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc430cs->cur_vts; } static int sc430cs_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc4336.c b/drivers/media/i2c/sc4336.c index abbfeb37e385..2fdf63b86f0c 100644 --- a/drivers/media/i2c/sc4336.c +++ b/drivers/media/i2c/sc4336.c @@ -1104,8 +1104,8 @@ static void sc4336_modify_fps_info(struct sc4336 *sc4336) { const struct sc4336_mode *mode = sc4336->cur_mode; - sc4336->cur_fps.denominator = mode->max_fps.denominator * sc4336->cur_vts / - mode->vts_def; + sc4336->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc4336->cur_vts; } static int sc4336_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc500ai.c b/drivers/media/i2c/sc500ai.c index 7797885804a0..00456f9b3b41 100644 --- a/drivers/media/i2c/sc500ai.c +++ b/drivers/media/i2c/sc500ai.c @@ -1396,8 +1396,8 @@ static void sc500ai_modify_fps_info(struct sc500ai *sc500ai) { const struct sc500ai_mode *mode = sc500ai->cur_mode; - sc500ai->cur_fps.denominator = mode->max_fps.denominator * sc500ai->cur_vts / - mode->vts_def; + sc500ai->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc500ai->cur_vts; } static int sc500ai_set_ctrl(struct v4l2_ctrl *ctrl) diff --git a/drivers/media/i2c/sc530ai.c b/drivers/media/i2c/sc530ai.c index b8d818cbe30d..b582ed65dd37 100644 --- a/drivers/media/i2c/sc530ai.c +++ b/drivers/media/i2c/sc530ai.c @@ -950,9 +950,10 @@ static int sc530ai_g_frame_interval(struct v4l2_subdev *sd, struct sc530ai *sc530ai = to_sc530ai(sd); const struct sc530ai_mode *mode = sc530ai->cur_mode; - mutex_lock(&sc530ai->mutex); - fi->interval = mode->max_fps; - mutex_unlock(&sc530ai->mutex); + if (sc530ai->streaming) + fi->interval = sc530ai->cur_fps; + else + fi->interval = mode->max_fps; return 0; } @@ -1635,8 +1636,8 @@ static void sc530ai_modify_fps_info(struct sc530ai *sc5330ai) { const struct sc530ai_mode *mode = sc5330ai->cur_mode; - sc5330ai->cur_fps.denominator = mode->max_fps.denominator * sc5330ai->cur_vts / - mode->vts_def; + sc5330ai->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + sc5330ai->cur_vts; } static int sc530ai_set_ctrl(struct v4l2_ctrl *ctrl) From 50bc70c3f61f1cb9f10c16cef059352e12f5cbcd Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Sun, 9 Oct 2022 09:51:03 +0000 Subject: [PATCH 198/204] drm/bridge: analogix_dp: Fix stream valid control Add DT property 'analogix,force-stream-valid' to DTS node if want to support vrr. Fixes: 2abd3af02c10 ("drm/bridge: analogix_dp: Use video format information from register") Signed-off-by: Wyon Bi Change-Id: Ic4624e4ca3a03322f1d9520a7e3cee0d054c36ee --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 ++ drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 1 + drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 8 +++++--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 456d33c36d69..ead215ff6183 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1998,6 +1998,8 @@ static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp) video_info->video_bist_enable = of_property_read_bool(dp_node, "analogix,video-bist-enable"); + video_info->force_stream_valid = + of_property_read_bool(dp_node, "analogix,force-stream-valid"); prop = of_find_property(dp_node, "data-lanes", &len); if (!prop) { diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 090bc255042b..a843a739b76c 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -142,6 +142,7 @@ struct video_info { u32 lane_map[4]; bool video_bist_enable; + bool force_stream_valid; }; struct link_train { diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 663c56144af8..e756d7cd3d41 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -790,9 +790,11 @@ void analogix_dp_init_video(struct analogix_dp_device *dp) reg = CHA_CRI(4) | CHA_CTRL; analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_2, reg); - reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3); - reg |= VALID_CTRL | F_VALID; - analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, reg); + if (dp->video_info.force_stream_valid) { + reg = analogix_dp_read(dp, ANALOGIX_DP_SYS_CTL_3); + reg |= VALID_CTRL | F_VALID; + analogix_dp_write(dp, ANALOGIX_DP_SYS_CTL_3, reg); + } reg = VID_HRES_TH(2) | VID_VRES_TH(0); analogix_dp_write(dp, ANALOGIX_DP_VIDEO_CTL_8, reg); From e2bf2eaab8d824b97a115917c99a68d08305ae52 Mon Sep 17 00:00:00 2001 From: Wang Xiaobin Date: Mon, 10 Oct 2022 10:50:05 +0800 Subject: [PATCH 199/204] ARM: dts: rockchip: rv1103g-rmsl311: remove meta node and use erofs The layout about meta has been changed and defined in rv1106-thunder-boot.dtsi. Signed-off-by: Wang Xiaobin Change-Id: Ia05c9020dd52b5c6a0e9c94b1e7d799fd65d9d76 --- arch/arm/boot/dts/rv1103g-rmsl311-dloc-sl-v10.dts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/rv1103g-rmsl311-dloc-sl-v10.dts b/arch/arm/boot/dts/rv1103g-rmsl311-dloc-sl-v10.dts index 970f598e0596..1ef3a983b1c3 100644 --- a/arch/arm/boot/dts/rv1103g-rmsl311-dloc-sl-v10.dts +++ b/arch/arm/boot/dts/rv1103g-rmsl311-dloc-sl-v10.dts @@ -13,7 +13,7 @@ compatible = "rockchip,rv1103g-rmsl311-dloc-v10", "rockchip,rv1103"; chosen { - bootargs = "loglevel=0 console=ttyFIQ0 root=/dev/rd0 snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0 driver_async_probe=dwmmc_rockchip"; + 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"; }; vcc_1v8: vcc-1v8 { @@ -132,11 +132,6 @@ reg = <0x00000000 0x04000000>; }; -&meta { - /* reserved meta partition 384KB */ - reg = <0x01e00000 (384 * 0x400)>; -}; - &mipi0_csi2 { status = "okay"; From 4512ef481e41155596b1ae64b219b98e9f41d809 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Mon, 10 Oct 2022 09:53:53 +0800 Subject: [PATCH 200/204] drm/rockchip: dw_hdmi_qp: Support rk3588 switch HDMI/DVI mode Add property output_hdmi_dvi: enums: auto=0 force_hdmi=1 force_dvi=2 Signed-off-by: Algea Cao Change-Id: I395644ebf1b8eea6a41f80e1282fbc3373144503 --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 55 ++++++++++++++++++- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 56 ++++++++++++-------- include/drm/bridge/dw_hdmi.h | 3 ++ 3 files changed, 89 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 59965f85109c..927be632b9a4 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -253,6 +253,8 @@ struct dw_hdmi_qp { bool frl_switch; bool cec_enable; bool allm_enable; + bool support_hdmi; + int force_output; struct mutex mutex; /* for state below and previous_mode */ struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */ @@ -1980,6 +1982,25 @@ dw_hdmi_update_hdr_property(struct drm_connector *connector) return ret; } +static bool dw_hdmi_qp_check_output_type_changed(struct dw_hdmi_qp *hdmi) +{ + bool sink_hdmi; + + sink_hdmi = hdmi->sink_is_hdmi; + + if (hdmi->force_output == 1) + hdmi->sink_is_hdmi = true; + else if (hdmi->force_output == 2) + hdmi->sink_is_hdmi = false; + else + hdmi->sink_is_hdmi = hdmi->support_hdmi; + + if (sink_hdmi != hdmi->sink_is_hdmi) + return true; + + return false; +} + static int dw_hdmi_connector_get_modes(struct drm_connector *connector) { struct dw_hdmi_qp *hdmi = @@ -2001,7 +2022,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", edid->width_cm, edid->height_cm); - hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); + hdmi->support_hdmi = drm_detect_hdmi_monitor(edid); hdmi->sink_has_audio = drm_detect_monitor_audio(edid); drm_connector_update_edid_property(connector, edid); if (hdmi->cec_notifier) @@ -2036,7 +2057,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) } kfree(edid); } else { - hdmi->sink_is_hdmi = true; + hdmi->support_hdmi = true; hdmi->sink_has_audio = true; if (hdmi->plat_data->split_mode) { @@ -2073,6 +2094,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) dev_info(hdmi->dev, "failed to get edid\n"); } + dw_hdmi_qp_check_output_type_changed(hdmi); return ret; } @@ -2318,6 +2340,35 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, return 0; } +void dw_hdmi_qp_set_output_type(struct dw_hdmi_qp *hdmi, u64 val) +{ + hdmi->force_output = val; + + if (!dw_hdmi_qp_check_output_type_changed(hdmi)) + return; + + if (hdmi->disabled) + return; + + if (!hdmi->sink_is_hdmi) + hdmi_modb(hdmi, OPMODE_DVI, OPMODE_DVI, LINK_CONFIG0); + else + hdmi_modb(hdmi, 0, OPMODE_DVI, LINK_CONFIG0); +} +EXPORT_SYMBOL_GPL(dw_hdmi_qp_set_output_type); + +bool dw_hdmi_qp_get_output_whether_hdmi(struct dw_hdmi_qp *hdmi) +{ + return hdmi->sink_is_hdmi; +} +EXPORT_SYMBOL_GPL(dw_hdmi_qp_get_output_whether_hdmi); + +int dw_hdmi_qp_get_output_type_cap(struct dw_hdmi_qp *hdmi) +{ + return hdmi->support_hdmi; +} +EXPORT_SYMBOL_GPL(dw_hdmi_qp_get_output_type_cap); + static void dw_hdmi_connector_force(struct drm_connector *connector) { struct dw_hdmi_qp *hdmi = diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index d1af980127b1..69801ca30474 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -1766,6 +1766,8 @@ dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state, if (!hdmi->is_hdmi_qp) sink_is_hdmi = dw_hdmi_get_output_whether_hdmi(hdmi->hdmi); + else + sink_is_hdmi = dw_hdmi_qp_get_output_whether_hdmi(hdmi->hdmi_qp); *color_format = RK_IF_FORMAT_RGB; @@ -2448,25 +2450,25 @@ dw_hdmi_rockchip_attach_properties(struct drm_connector *connector, } hdmi->enable_allm = allm_en; + prop = drm_property_create_enum(connector->dev, 0, + "output_hdmi_dvi", + output_hdmi_dvi_enum_list, + ARRAY_SIZE(output_hdmi_dvi_enum_list)); + if (prop) { + hdmi->output_hdmi_dvi = prop; + drm_object_attach_property(&connector->base, prop, 0); + } + + prop = drm_property_create_enum(connector->dev, 0, + "output_type_capacity", + output_type_cap_list, + ARRAY_SIZE(output_type_cap_list)); + if (prop) { + hdmi->output_type_capacity = prop; + drm_object_attach_property(&connector->base, prop, 0); + } + if (!hdmi->is_hdmi_qp) { - prop = drm_property_create_enum(connector->dev, 0, - "output_hdmi_dvi", - output_hdmi_dvi_enum_list, - ARRAY_SIZE(output_hdmi_dvi_enum_list)); - if (prop) { - hdmi->output_hdmi_dvi = prop; - drm_object_attach_property(&connector->base, prop, 0); - } - - prop = drm_property_create_enum(connector->dev, 0, - "output_type_capacity", - output_type_cap_list, - ARRAY_SIZE(output_type_cap_list)); - if (prop) { - hdmi->output_type_capacity = prop; - drm_object_attach_property(&connector->base, prop, 0); - } - prop = drm_property_create_enum(connector->dev, 0, "hdmi_quant_range", quant_range_enum_list, @@ -2600,10 +2602,15 @@ dw_hdmi_rockchip_set_property(struct drm_connector *connector, } else if (property == config->hdr_output_metadata_property) { return 0; } else if (property == hdmi->output_hdmi_dvi) { - if (hdmi->force_output != val) - hdmi->color_changed++; - hdmi->force_output = val; - dw_hdmi_set_output_type(hdmi->hdmi, val); + if (!hdmi->is_hdmi_qp) { + if (hdmi->force_output != val) + hdmi->color_changed++; + hdmi->force_output = val; + dw_hdmi_set_output_type(hdmi->hdmi, val); + } else { + hdmi->force_output = val; + dw_hdmi_qp_set_output_type(hdmi->hdmi_qp, val); + } return 0; } else if (property == hdmi->colordepth_capacity) { return 0; @@ -2684,7 +2691,10 @@ dw_hdmi_rockchip_get_property(struct drm_connector *connector, *val = hdmi->force_output; return 0; } else if (property == hdmi->output_type_capacity) { - *val = dw_hdmi_get_output_type_cap(hdmi->hdmi); + if (!hdmi->is_hdmi_qp) + *val = dw_hdmi_get_output_type_cap(hdmi->hdmi); + else + *val = dw_hdmi_qp_get_output_type_cap(hdmi->hdmi_qp); return 0; } else if (property == hdmi->user_split_mode_prop) { *val = hdmi->user_split_mode; diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 35b4889b01dc..3e2c6ecb6575 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -321,5 +321,8 @@ void dw_hdmi_qp_audio_enable(struct dw_hdmi_qp *hdmi); void dw_hdmi_qp_audio_disable(struct dw_hdmi_qp *hdmi); int dw_hdmi_qp_set_plugged_cb(struct dw_hdmi_qp *hdmi, hdmi_codec_plugged_cb fn, struct device *codec_dev); +void dw_hdmi_qp_set_output_type(struct dw_hdmi_qp *hdmi, u64 val); +bool dw_hdmi_qp_get_output_whether_hdmi(struct dw_hdmi_qp *hdmi); +int dw_hdmi_qp_get_output_type_cap(struct dw_hdmi_qp *hdmi); #endif /* __IMX_HDMI_H__ */ From 8e32089501b8a885c5ce2120950040f2dc9e67e1 Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Mon, 10 Oct 2022 11:42:23 +0800 Subject: [PATCH 201/204] iommu/rockchip: fix rockchip private interface dependence Fixes: fae620b2b6a3 ("iommu/rockchip: add irq mask cb") Change-Id: I9783a64d866d7919ade89a48e004b9c51b38dde6 Signed-off-by: Simon Xue --- drivers/video/rockchip/mpp/mpp_rkvenc.c | 1 + include/linux/iommu.h | 10 ---------- include/soc/rockchip/rockchip_iommu.h | 8 ++++++++ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_rkvenc.c b/drivers/video/rockchip/mpp/mpp_rkvenc.c index 3d142a05e8c9..ce6b42186452 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvenc.c +++ b/drivers/video/rockchip/mpp/mpp_rkvenc.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 2476f1a97fb6..f7f6ada34836 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -588,8 +588,6 @@ static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain, extern struct iommu_group *pci_device_group(struct device *dev); /* Generic device grouping function */ extern struct iommu_group *generic_device_group(struct device *dev); -extern void rk_iommu_mask_irq(struct device *dev); -extern void rk_iommu_unmask_irq(struct device *dev); /* FSL-MC device grouping function */ struct iommu_group *fsl_mc_device_group(struct device *dev); @@ -1098,14 +1096,6 @@ static inline struct iommu_fwspec *dev_iommu_fwspec_get(struct device *dev) { return NULL; } - -static inline void rk_iommu_mask_irq(struct device *dev) -{ -} - -static inline void rk_iommu_unmask_irq(struct device *dev) -{ -} #endif /* CONFIG_IOMMU_API */ /** diff --git a/include/soc/rockchip/rockchip_iommu.h b/include/soc/rockchip/rockchip_iommu.h index 804f0fdc44a4..e4e9d41ab99c 100644 --- a/include/soc/rockchip/rockchip_iommu.h +++ b/include/soc/rockchip/rockchip_iommu.h @@ -13,6 +13,8 @@ int rockchip_iommu_disable(struct device *dev); int rockchip_pagefault_done(struct device *master_dev); void __iomem *rockchip_get_iommu_base(struct device *master_dev, int idx); bool rockchip_iommu_is_enabled(struct device *dev); +void rk_iommu_mask_irq(struct device *dev); +void rk_iommu_unmask_irq(struct device *dev); #else static inline int rockchip_iommu_enable(struct device *dev) { @@ -34,6 +36,12 @@ static inline bool rockchip_iommu_is_enabled(struct device *dev) { return false; } +static inline void rk_iommu_mask_irq(struct device *dev) +{ +} +static inline void rk_iommu_unmask_irq(struct device *dev) +{ +} #endif #endif From 91e883deed2c0859e24570216ecef4c1122c3662 Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Mon, 10 Oct 2022 15:58:35 +0800 Subject: [PATCH 202/204] iommu/rockchip: rename rk_iommu_[un]mask_irq() to rockchip_iommu_[un]mask_irq() Signed-off-by: Simon Xue Signed-off-by: Tao Huang Change-Id: I66d8248357039ff049002b8204dc99eab90d3666 --- drivers/iommu/rockchip-iommu.c | 8 ++++---- drivers/video/rockchip/mpp/mpp_rkvdec2_link.c | 2 +- drivers/video/rockchip/mpp/mpp_rkvenc.c | 4 ++-- include/soc/rockchip/rockchip_iommu.h | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 0e0baa944c2c..5d22c575b295 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -1720,7 +1720,7 @@ static int rk_iommu_of_xlate(struct device *dev, return 0; } -void rk_iommu_mask_irq(struct device *dev) +void rockchip_iommu_mask_irq(struct device *dev) { struct rk_iommu *iommu = rk_iommu_from_dev(dev); int i; @@ -1731,9 +1731,9 @@ void rk_iommu_mask_irq(struct device *dev) for (i = 0; i < iommu->num_mmu; i++) rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, 0); } -EXPORT_SYMBOL(rk_iommu_mask_irq); +EXPORT_SYMBOL(rockchip_iommu_mask_irq); -void rk_iommu_unmask_irq(struct device *dev) +void rockchip_iommu_unmask_irq(struct device *dev) { struct rk_iommu *iommu = rk_iommu_from_dev(dev); int i; @@ -1749,7 +1749,7 @@ void rk_iommu_unmask_irq(struct device *dev) rk_iommu_base_command(iommu->bases[i], RK_MMU_CMD_PAGE_FAULT_DONE); } } -EXPORT_SYMBOL(rk_iommu_unmask_irq); +EXPORT_SYMBOL(rockchip_iommu_unmask_irq); static struct iommu_ops rk_iommu_ops = { .domain_alloc = rk_iommu_domain_alloc, diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c index f7418621c683..b62bc01589f5 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c @@ -1797,7 +1797,7 @@ int rkvdec2_ccu_iommu_fault_handle(struct iommu_domain *iommu, atomic_inc(&mpp->queue->reset_request); for (i = 0; i < mpp->queue->core_count; i++) - rk_iommu_mask_irq(mpp->queue->cores[i]->dev); + rockchip_iommu_mask_irq(mpp->queue->cores[i]->dev); kthread_queue_work(&mpp->queue->worker, &mpp->work); diff --git a/drivers/video/rockchip/mpp/mpp_rkvenc.c b/drivers/video/rockchip/mpp/mpp_rkvenc.c index ce6b42186452..36a888193246 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvenc.c +++ b/drivers/video/rockchip/mpp/mpp_rkvenc.c @@ -1144,7 +1144,7 @@ static void rkvenc_iommu_handle_work(struct work_struct *work_s) else enc->aux_iova = page_iova; - rk_iommu_unmask_irq(mpp->dev); + rockchip_iommu_unmask_irq(mpp->dev); mpp_iommu_up_write(mpp->iommu_info); mpp_debug_leave(); @@ -1161,7 +1161,7 @@ static int rkvenc_iommu_fault_handle(struct iommu_domain *iommu, mpp_debug(DEBUG_IOMMU, "IOMMU_GET_BUS_ID(status)=%d\n", IOMMU_GET_BUS_ID(status)); if (IOMMU_GET_BUS_ID(status)) { enc->fault_iova = iova; - rk_iommu_mask_irq(mpp->dev); + rockchip_iommu_mask_irq(mpp->dev); queue_work(enc->iommu_wq, &enc->iommu_work); } mpp_debug_leave(); diff --git a/include/soc/rockchip/rockchip_iommu.h b/include/soc/rockchip/rockchip_iommu.h index e4e9d41ab99c..10a5d62ae35d 100644 --- a/include/soc/rockchip/rockchip_iommu.h +++ b/include/soc/rockchip/rockchip_iommu.h @@ -13,8 +13,8 @@ int rockchip_iommu_disable(struct device *dev); int rockchip_pagefault_done(struct device *master_dev); void __iomem *rockchip_get_iommu_base(struct device *master_dev, int idx); bool rockchip_iommu_is_enabled(struct device *dev); -void rk_iommu_mask_irq(struct device *dev); -void rk_iommu_unmask_irq(struct device *dev); +void rockchip_iommu_mask_irq(struct device *dev); +void rockchip_iommu_unmask_irq(struct device *dev); #else static inline int rockchip_iommu_enable(struct device *dev) { @@ -36,10 +36,10 @@ static inline bool rockchip_iommu_is_enabled(struct device *dev) { return false; } -static inline void rk_iommu_mask_irq(struct device *dev) +static inline void rockchip_iommu_mask_irq(struct device *dev) { } -static inline void rk_iommu_unmask_irq(struct device *dev) +static inline void rockchip_iommu_unmask_irq(struct device *dev) { } #endif From 9802fa376f14e29fa4499721713f132cad903d68 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Wed, 21 Sep 2022 16:03:20 +0800 Subject: [PATCH 203/204] drm/rockchip: vop2: update dsc_hsync and dly num config according IC suggest Signed-off-by: Sandy Huang Change-Id: I47fcc5d143b10bc1d636691a138312b1b109006d --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 27 +++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index c521ff929774..fcfce8bf55f9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -6384,19 +6384,38 @@ static void vop2_crtc_enable_dsc(struct drm_crtc *crtc, struct drm_crtc_state *o * dly_num = delay_line_num * T(one-line) / T (dsc_cds) * T (one-line) = 1/v_pixclk_mhz * htotal = htotal/v_pixclk_mhz * T (dsc_cds) = 1 / dsc_cds_rate_mhz + * + * HDMI: * delay_line_num: according the pps initial_xmit_delay to adjust vop dsc delay * delay_line_num = 4 - BPP / 8 * = (64 - target_bpp / 8) / 16 - * * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; + * + * MIPI DSI[4320 and 9216 is buffer size for DSC]: + * DSC0:delay_line_num = 4320 * 8 / slince_num / chunk_size; + * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; + * DSC1:delay_line_num = 9216 * 2 / slince_num / chunk_size; + * delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; + * dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num */ do_div(dsc_cds_rate, 1000000); /* hz to Mhz */ dsc_cds_rate_mhz = dsc_cds_rate; - dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; + dsc_hsync = hsync_len / 2; + if (dsc_interface_mode == VOP_DSC_IF_HDMI) { + dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * (64 - target_bpp / 8) / 16; + } else { + int dsc_buf_size = dsc->id == 0 ? 4320 * 8 : 9216 * 2; + int delay_line_num = dsc_buf_size / vcstate->dsc_slice_num / be16_to_cpu(vcstate->pps.chunk_size); + + delay_line_num = delay_line_num > 5 ? 5 : delay_line_num; + dly_num = htotal * dsc_cds_rate_mhz / v_pixclk_mhz * delay_line_num; + + /* The dsc mipi video mode dsc_hsync minimum size is 8 pixels */ + if (dsc_hsync < 8) + dsc_hsync = 8; + } VOP_MODULE_SET(vop2, dsc, dsc_init_dly_mode, 0); VOP_MODULE_SET(vop2, dsc, dsc_init_dly_num, dly_num); - - dsc_hsync = hsync_len / 2; /* * htotal / dclk_core = dsc_htotal /cds_clk * From 67e4e92e23fb05a6c58403232914019f1b59ccf2 Mon Sep 17 00:00:00 2001 From: Alex Zhao Date: Mon, 10 Oct 2022 15:20:29 +0800 Subject: [PATCH 204/204] net: wireless: rockchip_wlan: bcmdhd: enable WL_SCHED_SCAN Signed-off-by: Alex Zhao Change-Id: I687794f636bd2f5c0f3629f293620e893e5a6f6e --- drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile index e9e2403c968a..2a618ef1ef74 100755 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile @@ -31,6 +31,7 @@ CONFIG_MACH_PLATFORM := y DHDCFLAGS = -Wall -Wstrict-prototypes -Wno-date-time \ -Wno-implicit-fallthrough -Wno-declaration-after-statement \ + -Wno-vla -Wno-vla-extension \ -Dlinux -DLINUX -DBCMDRIVER \ -DBCMDONGLEHOST -DBCMDMA32 -DBCMFILEIMAGE \ -DDHDTHREAD -DDHD_DEBUG -DSHOW_EVENTS -DGET_OTP_MAC_ENABLE \ @@ -41,7 +42,7 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Wno-date-time \ -DPOWERUP_MAX_RETRY=0 -DIFACE_HANG_FORCE_DEV_CLOSE -DWAIT_DEQUEUE \ -DUSE_NEW_RSPEC_DEFS -DBCM_USE_PLATFORM_STRLCPY \ -DWL_EXT_IAPSTA -DWL_ESCAN -DCCODE_LIST -DSUSPEND_EVENT \ - -DEAPOL_RESEND -DEAPOL_DYNAMATIC_RESEND \ + -DEAPOL_RESEND -DEAPOL_DYNAMATIC_RESEND -DWL_SCHED_SCAN \ -DENABLE_INSMOD_NO_FW_LOAD -Wframe-larger-than=2048 DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o \