From ff311139ed5a97b07ccb837fb86d031002a2cddc Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Thu, 10 Nov 2022 18:47:40 +0800 Subject: [PATCH 001/235] ARM: dts: rockchip: rk3288: remove PLL_CPLL assignment from cru node PLL_CPLL is for VOP only, which does not need to be initialized in CRU. Signed-off-by: Damon Ding Change-Id: Ic51b4e2ef377ee6f796e807131f1fe02d0db39cc --- arch/arm/boot/dts/rk3288.dtsi | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 078c151ee854..1a9bb2c59dfb 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -893,16 +893,14 @@ rockchip,grf = <&grf>; #clock-cells = <1>; #reset-cells = <1>; - assigned-clocks = <&cru PLL_GPLL>, <&cru PLL_CPLL>, - <&cru PLL_NPLL>, <&cru ACLK_CPU>, - <&cru HCLK_CPU>, <&cru PCLK_CPU>, - <&cru ACLK_PERI>, <&cru HCLK_PERI>, - <&cru PCLK_PERI>; - assigned-clock-rates = <594000000>, <400000000>, - <500000000>, <300000000>, - <150000000>, <75000000>, + assigned-clocks = <&cru PLL_GPLL>, <&cru PLL_NPLL>, + <&cru ACLK_CPU>, <&cru HCLK_CPU>, + <&cru PCLK_CPU>, <&cru ACLK_PERI>, + <&cru HCLK_PERI>, <&cru PCLK_PERI>; + assigned-clock-rates = <594000000>, <500000000>, <300000000>, <150000000>, - <75000000>; + <75000000>, <300000000>, + <150000000>, <75000000>; }; grf: syscon@ff770000 { From 36f27e69051b513c026a34af88890dd914b92201 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Mon, 14 Nov 2022 16:05:06 +0800 Subject: [PATCH 002/235] ARM: dts: rockchip: rk3288: assign clock rate for ACLK_VIO0 and ACLK_VIO1 Signed-off-by: Wyon Bi Signed-off-by: Damon Ding Change-Id: I87fbbe3e043b040f8b9b9c79f21a8327b8e32bd0 --- arch/arm/boot/dts/rk3288.dtsi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 1a9bb2c59dfb..6b3c97392678 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -896,11 +896,13 @@ assigned-clocks = <&cru PLL_GPLL>, <&cru PLL_NPLL>, <&cru ACLK_CPU>, <&cru HCLK_CPU>, <&cru PCLK_CPU>, <&cru ACLK_PERI>, - <&cru HCLK_PERI>, <&cru PCLK_PERI>; + <&cru HCLK_PERI>, <&cru PCLK_PERI>, + <&cru ACLK_VIO0>, <&cru ACLK_VIO1>; assigned-clock-rates = <594000000>, <500000000>, <300000000>, <150000000>, <75000000>, <300000000>, - <150000000>, <75000000>; + <150000000>, <75000000>, + <594000000>, <297000000>; }; grf: syscon@ff770000 { From 1e6ad41b1de0add665d46f7b2e59514a5420d904 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 11 Dec 2020 00:59:00 +0000 Subject: [PATCH 003/235] ARM: dts: rockchip: rk3288: Fix edp node Change-Id: I01855dd3ef2ea3be1db063e35f9aebd815fd66ba Signed-off-by: Wyon Bi --- arch/arm/boot/dts/rk3288.dtsi | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 6b3c97392678..235810f0bb2e 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -922,6 +922,13 @@ status = "disabled"; }; + mipi_phy_rx0: mipi-phy-rx0 { + compatible = "rockchip,rk3288-mipi-dphy"; + clocks = <&cru SCLK_MIPIDSI_24M>, <&cru PCLK_MIPI_CSI>; + clock-names = "dphy-ref", "pclk"; + status = "disabled"; + }; + usbphy: usbphy { compatible = "rockchip,rk3288-usb-phy"; #address-cells = <1>; @@ -1206,14 +1213,28 @@ }; }; + video_phy: video-phy@ff96c000 { + compatible = "rockchip,rk3288-video-phy"; + reg = <0x0 0xff96c000 0x0 0x4000>; + clocks = <&cru PCLK_LVDS_PHY>; + clock-names = "pclk"; + resets = <&cru SRST_LVDS_PHY>; + reset-names = "rst"; + power-domains = <&power RK3288_PD_VIO>; + #phy-cells = <0>; + status = "disabled"; + }; + edp: dp@ff970000 { compatible = "rockchip,rk3288-dp"; reg = <0x0 0xff970000 0x0 0x4000>; interrupts = ; - clocks = <&cru SCLK_EDP>, <&cru PCLK_EDP_CTRL>; - clock-names = "dp", "pclk"; - phys = <&edp_phy>; - phy-names = "dp"; + clocks = <&cru SCLK_EDP_24M>, <&cru PCLK_EDP_CTRL>, + <&cru SCLK_EDP>; + clock-names = "dp", "pclk", "spdif"; + assigned-clocks = <&cru SCLK_EDP_24M>; + assigned-clock-parents = <&xin24m>; + power-domains = <&power RK3288_PD_VIO>; resets = <&cru SRST_EDP>; reset-names = "dp"; rockchip,grf = <&grf>; From 69870f9db0b6036941c6a748eec1542d4e53a2b1 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Thu, 10 Nov 2022 19:09:31 +0800 Subject: [PATCH 004/235] ARM: dts: rockchip: rk3288: fix display related nodes Signed-off-by: Damon Ding Change-Id: I0f1dda389fe89f06495661baeb3c21edbc18dfbe --- arch/arm/boot/dts/rk3288.dtsi | 168 +++++++++++++++++++++++++++------- 1 file changed, 136 insertions(+), 32 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 235810f0bb2e..9b202692084b 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -929,6 +929,65 @@ status = "disabled"; }; + lvds: lvds { + compatible = "rockchip,rk3288-lvds"; + phys = <&video_phy>; + phy-names = "phy"; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + lvds_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_lvds>; + }; + + lvds_in_vopl: endpoint@1 { + reg = <1>; + remote-endpoint = <&vopl_out_lvds>; + }; + }; + }; + }; + + rgb: rgb { + compatible = "rockchip,rk3288-rgb"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&lcdc_rgb_pins>; + pinctrl-1 = <&lcdc_sleep_pins>; + phys = <&video_phy>; + phy-names = "phy"; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + rgb_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_rgb>; + }; + + rgb_in_vopl: endpoint@1 { + reg = <1>; + remote-endpoint = <&vopl_out_rgb>; + }; + }; + }; + }; + usbphy: usbphy { compatible = "rockchip,rk3288-usb-phy"; #address-cells = <1>; @@ -1055,8 +1114,9 @@ }; vopb: vop@ff930000 { - compatible = "rockchip,rk3288-vop"; + compatible = "rockchip,rk3288-vop-big"; reg = <0x0 0xff930000 0x0 0x19c>, <0x0 0xff931000 0x0 0x1000>; + reg-names = "regs", "gamma_lut"; interrupts = ; clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>; clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; @@ -1080,15 +1140,25 @@ remote-endpoint = <&edp_in_vopb>; }; - vopb_out_mipi: endpoint@2 { + vopb_out_dsi0: endpoint@2 { reg = <2>; - remote-endpoint = <&mipi_in_vopb>; + remote-endpoint = <&dsi0_in_vopb>; }; - vopb_out_lvds: endpoint@3 { + vopb_out_dsi1: endpoint@3 { reg = <3>; + remote-endpoint = <&dsi1_in_vopb>; + }; + + vopb_out_lvds: endpoint@4 { + reg = <4>; remote-endpoint = <&lvds_in_vopb>; }; + + vopb_out_rgb: endpoint@5 { + reg = <5>; + remote-endpoint = <&rgb_in_vopb>; + }; }; }; @@ -1101,12 +1171,14 @@ clock-names = "aclk", "iface"; power-domains = <&power RK3288_PD_VIO>; #iommu-cells = <0>; + rockchip,disable-device-link-resume; status = "disabled"; }; vopl: vop@ff940000 { - compatible = "rockchip,rk3288-vop"; + compatible = "rockchip,rk3288-vop-lit"; reg = <0x0 0xff940000 0x0 0x19c>, <0x0 0xff941000 0x0 0x1000>; + reg-names = "regs", "gamma_lut"; interrupts = ; clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>; clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; @@ -1130,15 +1202,25 @@ remote-endpoint = <&edp_in_vopl>; }; - vopl_out_mipi: endpoint@2 { + vopl_out_dsi0: endpoint@2 { reg = <2>; - remote-endpoint = <&mipi_in_vopl>; + remote-endpoint = <&dsi0_in_vopl>; }; - vopl_out_lvds: endpoint@3 { + vopl_out_dsi1: endpoint@3 { reg = <3>; + remote-endpoint = <&dsi1_in_vopl>; + }; + + vopl_out_lvds: endpoint@4 { + reg = <4>; remote-endpoint = <&lvds_in_vopl>; }; + + vopl_out_rgb: endpoint@5 { + reg = <5>; + remote-endpoint = <&rgb_in_vopl>; + }; }; }; @@ -1151,63 +1233,69 @@ clock-names = "aclk", "iface"; power-domains = <&power RK3288_PD_VIO>; #iommu-cells = <0>; + rockchip,disable-device-link-resume; status = "disabled"; }; - mipi_dsi: mipi@ff960000 { + dsi0: dsi@ff960000 { compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi"; reg = <0x0 0xff960000 0x0 0x4000>; interrupts = ; clocks = <&cru SCLK_MIPIDSI_24M>, <&cru PCLK_MIPI_DSI0>; clock-names = "ref", "pclk"; + resets = <&cru SRST_MIPIDSI0>; + reset-names = "apb"; power-domains = <&power RK3288_PD_VIO>; rockchip,grf = <&grf>; + #address-cells = <1>; + #size-cells = <0>; status = "disabled"; ports { mipi_in: port { #address-cells = <1>; #size-cells = <0>; - mipi_in_vopb: endpoint@0 { + dsi0_in_vopb: endpoint@0 { reg = <0>; - remote-endpoint = <&vopb_out_mipi>; + remote-endpoint = <&vopb_out_dsi0>; }; - mipi_in_vopl: endpoint@1 { + dsi0_in_vopl: endpoint@1 { reg = <1>; - remote-endpoint = <&vopl_out_mipi>; + remote-endpoint = <&vopl_out_dsi0>; }; }; }; }; - lvds: lvds@ff96c000 { - compatible = "rockchip,rk3288-lvds"; - reg = <0x0 0xff96c000 0x0 0x4000>; - clocks = <&cru PCLK_LVDS_PHY>; - clock-names = "pclk_lvds"; - pinctrl-names = "lcdc"; - pinctrl-0 = <&lcdc_ctl>; + dsi1: dsi@ff964000 { + compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi"; + reg = <0x0 0xff964000 0x0 0x4000>; + interrupts = ; + clocks = <&cru SCLK_MIPIDSI_24M>, <&cru PCLK_MIPI_DSI1>; + clock-names = "ref", "pclk"; + resets = <&cru SRST_MIPIDSI1>; + reset-names = "apb"; power-domains = <&power RK3288_PD_VIO>; rockchip,grf = <&grf>; + #address-cells = <1>; + #size-cells = <0>; status = "disabled"; ports { #address-cells = <1>; #size-cells = <0>; - lvds_in: port@0 { - reg = <0>; - + dsi1_in: port { #address-cells = <1>; #size-cells = <0>; - lvds_in_vopb: endpoint@0 { + dsi1_in_vopb: endpoint@0 { reg = <0>; - remote-endpoint = <&vopb_out_lvds>; + remote-endpoint = <&vopb_out_dsi1>; }; - lvds_in_vopl: endpoint@1 { + dsi1_in_vopl: endpoint@1 { reg = <1>; - remote-endpoint = <&vopl_out_lvds>; + remote-endpoint = <&vopl_out_dsi1>; }; }; }; @@ -1268,7 +1356,11 @@ interrupts = ; clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>, <&cru SCLK_HDMI_CEC>; clock-names = "iahb", "isfr", "cec"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&hdmi_ddc>; + pinctrl-1 = <&hdmi_gpio>; power-domains = <&power RK3288_PD_VIO>; + unsupported-yuv-input; status = "disabled"; ports { @@ -1666,6 +1758,11 @@ }; hdmi { + hdmi_gpio: hdmi-gpio { + rockchip,pins = <7 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>, + <7 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + hdmi_cec_c0: hdmi-cec-c0 { rockchip,pins = <7 RK_PC0 2 &pcfg_pull_none>; }; @@ -1784,11 +1881,18 @@ }; lcdc { - lcdc_ctl: lcdc-ctl { - rockchip,pins = <1 RK_PD0 1 &pcfg_pull_none>, - <1 RK_PD1 1 &pcfg_pull_none>, - <1 RK_PD2 1 &pcfg_pull_none>, - <1 RK_PD3 1 &pcfg_pull_none>; + lcdc_rgb_pins: lcdc-rgb-pins { + rockchip,pins = <1 RK_PD3 1 &pcfg_pull_none>, /* LCDC_DCLK */ + <1 RK_PD2 1 &pcfg_pull_none>, /* LCDC_DEN */ + <1 RK_PD1 1 &pcfg_pull_none>, /* LCDC_VSYNC */ + <1 RK_PD0 1 &pcfg_pull_none>; /* LCDC_HSYNC */ + }; + + lcdc_sleep_pins: lcdc-sleep-pins { + rockchip,pins = <1 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>, /* LCDC_DCLK */ + <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>, /* LCDC_DEN */ + <1 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>, /* LCDC_VSYNC */ + <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; /* LCDC_HSYNC */ }; }; From 6a7a7f513d54a30a8078a69586719029d5c7558e Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 10 Nov 2022 17:37:43 +0800 Subject: [PATCH 005/235] ARM: dts: rockchip: rk3288 fix gpu node to match midgard driver Signed-off-by: Jianqun Xu Change-Id: I74cfa3309c76ca01df9b42ff39ce51c719189258 --- arch/arm/boot/dts/rk3288.dtsi | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 9b202692084b..21ef673117b8 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1491,17 +1491,31 @@ }; gpu: gpu@ffa30000 { - compatible = "rockchip,rk3288-mali", "arm,mali-t760"; + compatible = "rockchip,rk3288-mali", "arm,mali-t760", + "arm,malit764", "arm,malit76x", "arm,malit7xx", + "arm,mali-midgard"; reg = <0x0 0xffa30000 0x0 0x10000>; interrupts = , , ; interrupt-names = "job", "mmu", "gpu"; clocks = <&cru ACLK_GPU>; + clock-names = "clk_mali"; operating-points-v2 = <&gpu_opp_table>; #cooling-cells = <2>; /* min followed by max */ power-domains = <&power RK3288_PD_GPU>; status = "disabled"; + + upthreshold = <75>; + downdifferential = <10>; + + gpu_power_model: power_model { + compatible = "arm,mali-simple-power-model"; + static-coefficient = <411000>; + dynamic-coefficient = <733>; + ts = <32000 4700 (-80) 2>; + thermal-zone = "gpu-thermal"; + }; }; gpu_opp_table: gpu-opp-table { From 9b45bb6e86f9f497cd26c23cece6640e51105587 Mon Sep 17 00:00:00 2001 From: Jianlong Wang Date: Fri, 11 Nov 2022 14:48:41 +0800 Subject: [PATCH 006/235] ARM: configs: add fragment defconfig for rk312x generate by: make ARCH=arm rockchip_linux_defconfig cp .config rockchip_linux.config make ARCH=arm rockchip_linux_defconfig rk3126_linux.config scripts/diffconfig -m rockchip_linux.config .config > \ arch/arm/configs/rk3126_linux.config make ARCH=arm rockchip_linux_defconfig rk3126_linux_slc_nand.config scripts/diffconfig -m rockchip_linux.config .config > \ arch/arm/configs/rk3126_linux_slc_nand.config make ARCH=arm rockchip_linux_defconfig rk3128_linux.config scripts/diffconfig -m rockchip_linux.config .config > \ arch/arm/configs/rk3128_linux.config Change-Id: I25fef40998b06ede079704fe7fc2f3b49d5b55c4 Signed-off-by: Jianlong Wang --- arch/arm/configs/rk3126_linux.config | 281 ++++++++++++++ arch/arm/configs/rk3126_linux_slc_nand.config | 348 ++++++++++++++++++ arch/arm/configs/rk3128_linux.config | 166 +++++++++ 3 files changed, 795 insertions(+) create mode 100644 arch/arm/configs/rk3126_linux.config create mode 100644 arch/arm/configs/rk3126_linux_slc_nand.config create mode 100644 arch/arm/configs/rk3128_linux.config diff --git a/arch/arm/configs/rk3126_linux.config b/arch/arm/configs/rk3126_linux.config new file mode 100644 index 000000000000..6408ae272e57 --- /dev/null +++ b/arch/arm/configs/rk3126_linux.config @@ -0,0 +1,281 @@ +# CONFIG_ALLOW_DEV_COREDUMP is not set +# CONFIG_ASHMEM is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BLK_CGROUP is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BT is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CPUSETS is not set +# CONFIG_CPU_FREQ_STAT is not set +# CONFIG_CPU_FREQ_TIMES is not set +# CONFIG_CPU_RK3036 is not set +# CONFIG_CPU_RK30XX is not set +# CONFIG_CPU_RK3188 is not set +# CONFIG_CPU_RK322X is not set +# CONFIG_CPU_RK3288 is not set +# CONFIG_CRC7 is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRYPTO_CFB is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_OFB is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SM3 is not set +# CONFIG_CRYPTO_SM4 is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_DEBUG_GPIO=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DNS_RESOLVER is not set +# CONFIG_DRM_IGNORE_IOTCL_PERMIT is not set +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_ETHERNET is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FIQ_DEBUGGER_TRUST_ZONE is not set +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_RMI is not set +# CONFIG_HOSTAP is not set +# CONFIG_HWMON is not set +# CONFIG_I2C_HID is not set +# CONFIG_I2C_STUB is not set +# CONFIG_IKCONFIG is not set +# CONFIG_INITRD_ASYNC is not set +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_IOSCHED_BFQ is not set +# CONFIG_IPV6 is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_KERNEL_GZIP is not set +CONFIG_KERNEL_LZ4=y +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MALI_MIDGARD is not set +# CONFIG_MDIO_DEVICE is not set +# CONFIG_MEDIA_CEC_SUPPORT is not set +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MMC_TEST is not set +# CONFIG_MODULE_FORCE_LOAD is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MWIFIEX is not set +CONFIG_NAMESPACES=y +# CONFIG_NETFILTER is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +# CONFIG_NET_KEY is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_UTF8 is not set +# CONFIG_PHYLIB is not set +# CONFIG_PHY_ROCKCHIP_DP is not set +# CONFIG_PHY_ROCKCHIP_INNO_HDMI is not set +# CONFIG_PHY_ROCKCHIP_USB is not set +# CONFIG_PINCTRL_RK805 is not set +# CONFIG_PM_DEBUG is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_PPS is not set +# CONFIG_PSI is not set +# CONFIG_PTP_1588_CLOCK is not set +# CONFIG_RD_XZ is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_RELAY is not set +# CONFIG_RFKILL_RK is not set +CONFIG_RK_CONSOLE_THREAD=y +CONFIG_RK_HEADSET=y +# CONFIG_RMI4_CORE is not set +# CONFIG_ROCKCHIP_ANALOGIX_DP is not set +# CONFIG_ROCKCHIP_DDRCLK_SIP_V2 is not set +# CONFIG_ROCKCHIP_DW_HDMI is not set +# CONFIG_ROCKCHIP_INNO_HDMI is not set +# CONFIG_ROCKCHIP_MPP_RKVDEC is not set +# CONFIG_ROCKCHIP_MPP_RKVENC is not set +# CONFIG_ROCKCHIP_MPP_VDPU2 is not set +# CONFIG_ROCKCHIP_MPP_VEPU2 is not set +# CONFIG_ROCKCHIP_PLL_RK3066 is not set +# CONFIG_ROCKCHIP_VENDOR_STORAGE_UPDATE_LOADER is not set +# CONFIG_RT2X00 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +CONFIG_RUNTIME_TESTING_MENU=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_TSL2563 is not set +CONFIG_SENSOR_DEVICE=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +# CONFIG_SERIAL_OF_PLATFORM is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_SND_SOC_ES8323 is not set +# CONFIG_SND_SOC_ES8396 is not set +# CONFIG_SND_SOC_ROCKCHIP_MAX98090 is not set +# CONFIG_SND_SOC_ROCKCHIP_RT5645 is not set +# CONFIG_SND_SOC_RT5616 is not set +# CONFIG_SND_SOC_RT5640 is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SPI_SPIDEV is not set +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +# CONFIG_SQUASHFS_DECOMP_SINGLE is not set +CONFIG_STAGING_MEDIA=y +# CONFIG_TCG_TPM is not set +# CONFIG_TEE is not set +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_GSL3673 is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TSL2583 is not set +# CONFIG_UDF_FS is not set +# CONFIG_UNWINDER_FRAME_POINTER is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +# CONFIG_USB_CONFIGFS_ACM is not set +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_WDM is not set +# CONFIG_V4L_TEST_DRIVERS is not set +CONFIG_VIDEO_GC2145=y +# CONFIG_VIDEO_IMX219 is not set +# CONFIG_VIDEO_OV13850 is not set +# CONFIG_VIDEO_OV5647 is not set +# CONFIG_VIDEO_OV8858 is not set +# CONFIG_VIDEO_SGM3784 is not set +CONFIG_WIFI_GENERATE_RANDOM_MAC_ADDR=y +# CONFIG_XZ_DEC is not set +# CONFIG_ANGLE_DEVICE is not set +CONFIG_ARM_UNWIND=y +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_BMA2XX_ACC is not set +# CONFIG_COMPASS_DEVICE is not set +CONFIG_ENABLE_DEFAULT_TRACERS=y +# CONFIG_FIND_BIT_BENCHMARK is not set +CONFIG_GSENSOR_DEVICE=y +# CONFIG_GS_BMA023 is not set +# CONFIG_GS_DA215S is not set +# CONFIG_GS_DA223 is not set +# CONFIG_GS_DA228E is not set +# CONFIG_GS_DMT10 is not set +# CONFIG_GS_KXTIK is not set +# CONFIG_GS_KXTJ9 is not set +# CONFIG_GS_LIS3DH is not set +# CONFIG_GS_LSM303D is not set +# CONFIG_GS_MC3230 is not set +CONFIG_GS_MMA7660=y +# CONFIG_GS_MMA8452 is not set +# CONFIG_GS_MXC6225 is not set +# CONFIG_GS_MXC6655XA is not set +# CONFIG_GS_SC7660 is not set +# CONFIG_GS_SC7A20 is not set +# CONFIG_GS_SC7A30 is not set +# CONFIG_GYROSCOPE_DEVICE is not set +# CONFIG_HALL_DEVICE is not set +# CONFIG_ICM2060X_ACC is not set +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INTERVAL_TREE_TEST is not set +CONFIG_IPC_NS=y +# CONFIG_LIGHT_DEVICE is not set +# CONFIG_LKDTM is not set +# CONFIG_LSM330_ACC is not set +# CONFIG_MPU6500_ACC is not set +# CONFIG_MPU6880_ACC is not set +CONFIG_NET_NS=y +# CONFIG_PERCPU_TEST is not set +CONFIG_PID_NS=y +# CONFIG_PRESSURE_DEVICE is not set +# CONFIG_PROXIMITY_DEVICE is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_REED_SOLOMON_TEST is not set +# CONFIG_STK8BAXX_ACC is not set +# CONFIG_TEMPERATURE_DEVICE is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_BITOPS is not set +# CONFIG_TEST_BLACKHOLE_DEV is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_FREE_PAGES is not set +# CONFIG_TEST_HASH is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_IDA is not set +# CONFIG_TEST_KMOD is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_MEMCAT_P is not set +# CONFIG_TEST_MEMINIT is not set +# CONFIG_TEST_MIN_HEAP is not set +# CONFIG_TEST_OVERFLOW is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_SORT is not set +# CONFIG_TEST_STACKINIT is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_STRSCPY is not set +# CONFIG_TEST_SYSCTL is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_UUID is not set +# CONFIG_TEST_VMALLOC is not set +# CONFIG_TEST_XARRAY is not set +CONFIG_UNWINDER_ARM=y +CONFIG_USER_NS=y +CONFIG_UTS_NS=y +CONFIG_VIDEOBUF2_DMA_CONTIG=y +# CONFIG_VIDEO_HANTRO is not set +CONFIG_VIDEO_ROCKCHIP_ISP1=y +# CONFIG_VIDEO_ROCKCHIP_VDEC is not set diff --git a/arch/arm/configs/rk3126_linux_slc_nand.config b/arch/arm/configs/rk3126_linux_slc_nand.config new file mode 100644 index 000000000000..acc66a32ccea --- /dev/null +++ b/arch/arm/configs/rk3126_linux_slc_nand.config @@ -0,0 +1,348 @@ +# CONFIG_ALLOW_DEV_COREDUMP is not set +# CONFIG_ASHMEM is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BLK_CGROUP is not set +CONFIG_BLK_CMDLINE_PARSER=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BT is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_GPIO is not set +CONFIG_CMDLINE_PARTITION=y +# CONFIG_CPUSETS is not set +# CONFIG_CPU_FREQ_STAT is not set +# CONFIG_CPU_FREQ_TIMES is not set +# CONFIG_CPU_RK3036 is not set +# CONFIG_CPU_RK30XX is not set +# CONFIG_CPU_RK3188 is not set +# CONFIG_CPU_RK322X is not set +# CONFIG_CPU_RK3288 is not set +# CONFIG_CRC7 is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRYPTO_CFB is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_OFB is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SM3 is not set +# CONFIG_CRYPTO_SM4 is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_XTS is not set +CONFIG_CRYPTO_ZSTD=y +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_DEBUG_GPIO=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DNS_RESOLVER is not set +# CONFIG_DRM_IGNORE_IOTCL_PERMIT is not set +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_ETHERNET is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FIQ_DEBUGGER_TRUST_ZONE is not set +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_RMI is not set +# CONFIG_HOSTAP is not set +# CONFIG_HWMON is not set +# CONFIG_I2C_HID is not set +# CONFIG_I2C_STUB is not set +# CONFIG_IKCONFIG is not set +# CONFIG_INITRD_ASYNC is not set +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_IOSCHED_BFQ is not set +# CONFIG_IPV6 is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_KERNEL_GZIP is not set +CONFIG_KERNEL_LZ4=y +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MALI_MIDGARD is not set +# CONFIG_MDIO_DEVICE is not set +# CONFIG_MEDIA_CEC_SUPPORT is not set +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MMC_TEST is not set +# CONFIG_MODULE_FORCE_LOAD is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +CONFIG_MTD=y +# CONFIG_MWIFIEX is not set +CONFIG_NAMESPACES=y +# CONFIG_NETFILTER is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +# CONFIG_NET_KEY is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_UTF8 is not set +# CONFIG_PHYLIB is not set +# CONFIG_PHY_ROCKCHIP_DP is not set +# CONFIG_PHY_ROCKCHIP_INNO_HDMI is not set +# CONFIG_PHY_ROCKCHIP_USB is not set +# CONFIG_PINCTRL_RK805 is not set +# CONFIG_PM_DEBUG is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_PPS is not set +# CONFIG_PSI is not set +# CONFIG_PTP_1588_CLOCK is not set +# CONFIG_RD_XZ is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_RELAY is not set +# CONFIG_RFKILL_RK is not set +CONFIG_RK_CONSOLE_THREAD=y +CONFIG_RK_HEADSET=y +# CONFIG_RK_NAND is not set +# CONFIG_RMI4_CORE is not set +# CONFIG_ROCKCHIP_ANALOGIX_DP is not set +# CONFIG_ROCKCHIP_DDRCLK_SIP_V2 is not set +# CONFIG_ROCKCHIP_DW_HDMI is not set +# CONFIG_ROCKCHIP_EFUSE is not set +# CONFIG_ROCKCHIP_INNO_HDMI is not set +# CONFIG_ROCKCHIP_MPP_RKVDEC is not set +# CONFIG_ROCKCHIP_MPP_RKVENC is not set +# CONFIG_ROCKCHIP_MPP_VDPU2 is not set +# CONFIG_ROCKCHIP_MPP_VEPU2 is not set +# CONFIG_ROCKCHIP_PLL_RK3066 is not set +# CONFIG_ROCKCHIP_VENDOR_STORAGE_UPDATE_LOADER is not set +# CONFIG_RT2X00 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +CONFIG_RUNTIME_TESTING_MENU=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_TSL2563 is not set +CONFIG_SENSOR_DEVICE=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +# CONFIG_SERIAL_OF_PLATFORM is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_SND_SOC_ES8323 is not set +# CONFIG_SND_SOC_ES8396 is not set +# CONFIG_SND_SOC_ROCKCHIP_MAX98090 is not set +# CONFIG_SND_SOC_ROCKCHIP_RT5645 is not set +# CONFIG_SND_SOC_RT5616 is not set +# CONFIG_SND_SOC_RT5640 is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SPI_SPIDEV is not set +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +# CONFIG_SQUASHFS_DECOMP_SINGLE is not set +CONFIG_STAGING_MEDIA=y +# CONFIG_TCG_TPM is not set +# CONFIG_TEE is not set +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_GSL3673 is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TSL2583 is not set +# CONFIG_UDF_FS is not set +# CONFIG_UNWINDER_FRAME_POINTER is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +# CONFIG_USB_CONFIGFS_ACM is not set +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_WDM is not set +# CONFIG_V4L_TEST_DRIVERS is not set +CONFIG_VIDEO_GC2145=y +# CONFIG_VIDEO_IMX219 is not set +# CONFIG_VIDEO_OV13850 is not set +# CONFIG_VIDEO_OV5647 is not set +# CONFIG_VIDEO_OV8858 is not set +# CONFIG_VIDEO_SGM3784 is not set +CONFIG_WIFI_GENERATE_RANDOM_MAC_ADDR=y +# CONFIG_XZ_DEC is not set +# CONFIG_ANGLE_DEVICE is not set +CONFIG_ARM_UNWIND=y +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_BMA2XX_ACC is not set +# CONFIG_COMPASS_DEVICE is not set +CONFIG_ENABLE_DEFAULT_TRACERS=y +# CONFIG_FIND_BIT_BENCHMARK is not set +# CONFIG_FTL is not set +CONFIG_GSENSOR_DEVICE=y +# CONFIG_GS_BMA023 is not set +# CONFIG_GS_DA215S is not set +# CONFIG_GS_DA223 is not set +# CONFIG_GS_DA228E is not set +# CONFIG_GS_DMT10 is not set +# CONFIG_GS_KXTIK is not set +# CONFIG_GS_KXTJ9 is not set +# CONFIG_GS_LIS3DH is not set +# CONFIG_GS_LSM303D is not set +# CONFIG_GS_MC3230 is not set +CONFIG_GS_MMA7660=y +# CONFIG_GS_MMA8452 is not set +# CONFIG_GS_MXC6225 is not set +# CONFIG_GS_MXC6655XA is not set +# CONFIG_GS_SC7660 is not set +# CONFIG_GS_SC7A20 is not set +# CONFIG_GS_SC7A30 is not set +# CONFIG_GYROSCOPE_DEVICE is not set +# CONFIG_HALL_DEVICE is not set +# CONFIG_ICM2060X_ACC is not set +# CONFIG_INFTL is not set +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INTERVAL_TREE_TEST is not set +CONFIG_IPC_NS=y +# CONFIG_JFFS2_FS is not set +# CONFIG_LIGHT_DEVICE is not set +# CONFIG_LKDTM is not set +# CONFIG_LSM330_ACC is not set +# CONFIG_MPU6500_ACC is not set +# CONFIG_MPU6880_ACC is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_MTD_BLOCK2MTD is not set +# CONFIG_MTD_CFI is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_HYPERBUS is not set +# CONFIG_MTD_JEDECPROBE is not set +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_LPDDR2_NVM is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_OF_PARTS is not set +# CONFIG_MTD_ONENAND is not set +# CONFIG_MTD_OOPS is not set +CONFIG_MTD_PARTITIONED_MASTER=y +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_RAW_NAND is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_SPI_NAND is not set +# CONFIG_MTD_SPI_NOR is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_TESTS is not set +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_NET_NS=y +# CONFIG_NFTL is not set +# CONFIG_PERCPU_TEST is not set +CONFIG_PID_NS=y +# CONFIG_PRESSURE_DEVICE is not set +# CONFIG_PROXIMITY_DEVICE is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_REED_SOLOMON_TEST is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SM_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_STK8BAXX_ACC is not set +# CONFIG_TEMPERATURE_DEVICE is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_BITOPS is not set +# CONFIG_TEST_BLACKHOLE_DEV is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_FREE_PAGES is not set +# CONFIG_TEST_HASH is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_IDA is not set +# CONFIG_TEST_KMOD is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_MEMCAT_P is not set +# CONFIG_TEST_MEMINIT is not set +# CONFIG_TEST_MIN_HEAP is not set +# CONFIG_TEST_OVERFLOW is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_SORT is not set +# CONFIG_TEST_STACKINIT is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_STRSCPY is not set +# CONFIG_TEST_SYSCTL is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_UUID is not set +# CONFIG_TEST_VMALLOC is not set +# CONFIG_TEST_XARRAY is not set +# CONFIG_UBIFS_ATIME_SUPPORT is not set +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +# CONFIG_UBIFS_FS_AUTHENTICATION is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_SECURITY=y +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UBIFS_FS_ZSTD=y +CONFIG_UNWINDER_ARM=y +CONFIG_USER_NS=y +CONFIG_UTS_NS=y +CONFIG_VIDEOBUF2_DMA_CONTIG=y +# CONFIG_VIDEO_HANTRO is not set +CONFIG_VIDEO_ROCKCHIP_ISP1=y +# CONFIG_VIDEO_ROCKCHIP_VDEC is not set +CONFIG_ZSTD_COMPRESS=y diff --git a/arch/arm/configs/rk3128_linux.config b/arch/arm/configs/rk3128_linux.config new file mode 100644 index 000000000000..ec0f007d2a41 --- /dev/null +++ b/arch/arm/configs/rk3128_linux.config @@ -0,0 +1,166 @@ +# CONFIG_BLK_CGROUP is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CPUSETS is not set +# CONFIG_CPU_FREQ_STAT is not set +# CONFIG_CPU_FREQ_TIMES is not set +# CONFIG_CPU_RK3036 is not set +# CONFIG_CPU_RK30XX is not set +# CONFIG_CPU_RK3188 is not set +# CONFIG_CPU_RK322X is not set +# CONFIG_CPU_RK3288 is not set +# CONFIG_CRYPTO_CFB is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_DEV_ROCKCHIP is not set +# CONFIG_CRYPTO_OFB is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SM3 is not set +# CONFIG_CRYPTO_SM4 is not set +# CONFIG_CRYPTO_XTS is not set +CONFIG_DEBUG_GPIO=y +# CONFIG_DEBUG_LIST is not set +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_DNS_RESOLVER is not set +# CONFIG_DRM_IGNORE_IOTCL_PERMIT is not set +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +CONFIG_DRM_UDL=y +# CONFIG_ECRYPT_FS is not set +# CONFIG_IEP is not set +# CONFIG_IKCONFIG is not set +# CONFIG_INITRD_ASYNC is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_IOSCHED_BFQ is not set +# CONFIG_MALI_MIDGARD is not set +# CONFIG_MODULE_FORCE_LOAD is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_NAMESPACES=y +# CONFIG_NETWORK_FILESYSTEMS is not set +# CONFIG_PINCTRL_RK805 is not set +# CONFIG_PM_DEBUG is not set +# CONFIG_PSI is not set +# CONFIG_RFKILL_RK is not set +CONFIG_RK_HEADSET=y +# CONFIG_ROCKCHIP_ANALOGIX_DP is not set +# CONFIG_ROCKCHIP_DDRCLK_SIP_V2 is not set +# CONFIG_ROCKCHIP_DW_HDMI is not set +# CONFIG_ROCKCHIP_MPP_SERVICE is not set +# CONFIG_ROCKCHIP_MULTI_RGA is not set +# CONFIG_ROCKCHIP_PLL_RK3066 is not set +CONFIG_ROCKCHIP_REMOTECTL=y +CONFIG_ROCKCHIP_RGA=y +# CONFIG_ROCKCHIP_VENDOR_STORAGE_UPDATE_LOADER is not set +CONFIG_RUNTIME_TESTING_MENU=y +# CONFIG_SCHED_STACK_END_CHECK is not set +CONFIG_SENSOR_DEVICE=y +# CONFIG_SERIAL_OF_PLATFORM is not set +CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=y +CONFIG_SOFTLOCKUP_DETECTOR=y +# CONFIG_SPI_SPIDEV is not set +CONFIG_STAGING_MEDIA=y +# CONFIG_TEE is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_GSL3673 is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_SERIAL is not set +# CONFIG_V4L_TEST_DRIVERS is not set +CONFIG_VIDEO_GC2145=y +# CONFIG_VIDEO_IMX219 is not set +# CONFIG_VIDEO_OV13850 is not set +# CONFIG_VIDEO_OV5647 is not set +# CONFIG_VIDEO_OV8858 is not set +# CONFIG_VIDEO_SGM3784 is not set +CONFIG_WIFI_GENERATE_RANDOM_MAC_ADDR=y +# CONFIG_ANGLE_DEVICE is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_BMA2XX_ACC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1 +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1 +# CONFIG_COMPASS_DEVICE is not set +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +CONFIG_DRM_GEM_SHMEM_HELPER=y +# CONFIG_FIND_BIT_BENCHMARK is not set +CONFIG_GSENSOR_DEVICE=y +# CONFIG_GS_BMA023 is not set +# CONFIG_GS_DA215S is not set +# CONFIG_GS_DA223 is not set +# CONFIG_GS_DA228E is not set +# CONFIG_GS_DMT10 is not set +# CONFIG_GS_KXTIK is not set +# CONFIG_GS_KXTJ9 is not set +# CONFIG_GS_LIS3DH is not set +# CONFIG_GS_LSM303D is not set +# CONFIG_GS_MC3230 is not set +CONFIG_GS_MMA7660=y +# CONFIG_GS_MMA8452 is not set +# CONFIG_GS_MXC6225 is not set +# CONFIG_GS_MXC6655XA is not set +# CONFIG_GS_SC7660 is not set +# CONFIG_GS_SC7A20 is not set +# CONFIG_GS_SC7A30 is not set +# CONFIG_GYROSCOPE_DEVICE is not set +# CONFIG_HALL_DEVICE is not set +# CONFIG_ICM2060X_ACC is not set +# CONFIG_INTERVAL_TREE_TEST is not set +CONFIG_IPC_NS=y +# CONFIG_LIGHT_DEVICE is not set +CONFIG_LKDTM=y +CONFIG_LOCKUP_DETECTOR=y +# CONFIG_LSM330_ACC is not set +# CONFIG_MPU6500_ACC is not set +# CONFIG_MPU6880_ACC is not set +CONFIG_NET_NS=y +# CONFIG_PERCPU_TEST is not set +CONFIG_PID_NS=y +# CONFIG_PRESSURE_DEVICE is not set +# CONFIG_PROXIMITY_DEVICE is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_REED_SOLOMON_TEST is not set +CONFIG_ROCKCHIP_REMOTECTL_PWM=y +# CONFIG_ROCKCHIP_RGA2 is not set +# CONFIG_STK8BAXX_ACC is not set +# CONFIG_TEMPERATURE_DEVICE is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_BITOPS is not set +# CONFIG_TEST_BLACKHOLE_DEV is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_FREE_PAGES is not set +# CONFIG_TEST_HASH is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_IDA is not set +# CONFIG_TEST_KMOD is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_MEMCAT_P is not set +# CONFIG_TEST_MEMINIT is not set +# CONFIG_TEST_MIN_HEAP is not set +# CONFIG_TEST_OVERFLOW is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_SORT is not set +# CONFIG_TEST_STACKINIT is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_STRSCPY is not set +# CONFIG_TEST_SYSCTL is not set +CONFIG_TEST_UDELAY=y +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_UUID is not set +# CONFIG_TEST_VMALLOC is not set +# CONFIG_TEST_XARRAY is not set +CONFIG_USER_NS=y +CONFIG_UTS_NS=y +CONFIG_VIDEOBUF2_DMA_CONTIG=y +# CONFIG_VIDEO_HANTRO is not set +CONFIG_VIDEO_ROCKCHIP_ISP1=y +# CONFIG_VIDEO_ROCKCHIP_VDEC is not set From 6b444336b5fe3bfc8d81bbc952bb866f3972af3c Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Wed, 9 Nov 2022 11:19:59 +0800 Subject: [PATCH 007/235] ARM: dts: rockchip: rk3288-linux use fiq as console Signed-off-by: Jianqun Xu Change-Id: I2c67d7e541425667cdb41d6133538acaba665e0d --- arch/arm/boot/dts/rk3288-linux.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-linux.dtsi b/arch/arm/boot/dts/rk3288-linux.dtsi index 80844a7c6a50..584a5cc38d9f 100644 --- a/arch/arm/boot/dts/rk3288-linux.dtsi +++ b/arch/arm/boot/dts/rk3288-linux.dtsi @@ -8,7 +8,7 @@ / { chosen { - bootargs = "earlycon=uart8250,mmio32,0xff690000 vmalloc=496M rw root=PARTUUID=614e0000-0000 rootfstype=ext4 rootwait"; + bootargs = "earlycon=uart8250,mmio32,0xff690000 console=ttyFIQ0 vmalloc=496M rw root=PARTUUID=614e0000-0000 rootfstype=ext4 rootwait"; }; /delete-node/ dmc@ff610000; @@ -89,7 +89,7 @@ interrupts = ; rockchip,serial-id = <2>; rockchip,wake-irq = <0>; - rockchip,irq-mode-enable = <0>; /* If enable uart uses irq instead of fiq */ + rockchip,irq-mode-enable = <1>; /* If enable uart uses irq instead of fiq */ rockchip,baudrate = <115200>; /* Only 115200 and 1500000 */ pinctrl-names = "default"; pinctrl-0 = <&uart2_xfer>; From abb9ecec3dd9d5c189d4a7e86da02816a13fd7fc Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 15 Nov 2022 14:31:16 +0800 Subject: [PATCH 008/235] arm64: dts: rockchip: rk3399: Change low temperature to 10 degrees C Signed-off-by: Finley Xiao Change-Id: I9f17e4f89a1552115b0d4a34f2290e785990c8bb --- arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi index f9f2cc8abec7..645c2d479969 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi @@ -11,7 +11,7 @@ opp-shared; rockchip,temp-hysteresis = <5000>; - rockchip,low-temp = <0>; + rockchip,low-temp = <10000>; rockchip,low-temp-min-volt = <900000>; nvmem-cells = <&cpul_leakage>, <&specification_serial_number>, @@ -104,7 +104,7 @@ opp-shared; rockchip,temp-hysteresis = <5000>; - rockchip,low-temp = <0>; + rockchip,low-temp = <10000>; rockchip,low-temp-min-volt = <900000>; nvmem-cells = <&cpub_leakage>, <&specification_serial_number>, @@ -224,7 +224,7 @@ rockchip,thermal-zone = "soc-thermal"; rockchip,temp-hysteresis = <5000>; - rockchip,low-temp = <0>; + rockchip,low-temp = <10000>; rockchip,low-temp-min-volt = <900000>; nvmem-cells = <&gpu_leakage>; From 886953b713e7bae26a57e615b2fe9b6aad170168 Mon Sep 17 00:00:00 2001 From: William Wu Date: Mon, 14 Nov 2022 18:18:35 +0800 Subject: [PATCH 009/235] arm64: dts: rockchip: rk3568: add quirk-skip-phy-init for usb otg0 The rk3568 usb dwc3 controller has phy management at its own driver to cover both device and host mode. And for usb otg0, it enable device wakeup that make the usb hcd core to keep the phy initialized so the device can wake up the system. However, most of rk3568 platforms power off the logic and cause phy grf lost power, thus we need to add quirk-skip-phy-init to reinit phy grf upon system resume. Signed-off-by: William Wu Change-Id: I14061e3b8bad05818e8496d4710695ef31deed9f --- arch/arm64/boot/dts/rockchip/rk3568.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi index c5a7af71d403..82d3326351da 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi @@ -583,6 +583,7 @@ snps,dis-tx-ipgap-linecheck-quirk; snps,dis_rxdet_inp3_quirk; snps,xhci-trb-ent-quirk; + quirk-skip-phy-init; status = "disabled"; }; }; From 3b67ff56d69899ff3a09a0a58e03260fbac2872c Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Thu, 10 Nov 2022 10:48:45 +0800 Subject: [PATCH 010/235] video: rockchip: mpp: add iommu flush tlb before hw run for px30 Signed-off-by: Yandong Lin Change-Id: I20ae76b0890a8f6bee158a5a5c4dddd4d660e74a --- drivers/video/rockchip/mpp/mpp_rkvdec.c | 19 ++++++++++++++++++- drivers/video/rockchip/mpp/mpp_vdpu2.c | 19 ++++++++++++++++++- drivers/video/rockchip/mpp/mpp_vepu2.c | 23 ++++++++++++++++++++++- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec.c b/drivers/video/rockchip/mpp/mpp_rkvdec.c index 7b8c8176f8e3..57694df86365 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec.c @@ -976,6 +976,13 @@ static int rkvdec_1126_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) return rkvdec_run(mpp, mpp_task); } +static int rkvdec_px30_run(struct mpp_dev *mpp, + struct mpp_task *mpp_task) +{ + mpp_iommu_flush_tlb(mpp->iommu_info); + return rkvdec_run(mpp, mpp_task); +} + static int rkvdec_irq(struct mpp_dev *mpp) { mpp->irq_status = mpp_read(mpp, RKVDEC_REG_INT_EN); @@ -1728,6 +1735,16 @@ static struct mpp_dev_ops rkvdec_v1_dev_ops = { .free_task = rkvdec_free_task, }; +static struct mpp_dev_ops rkvdec_px30_dev_ops = { + .alloc_task = rkvdec_alloc_task, + .run = rkvdec_px30_run, + .irq = rkvdec_irq, + .isr = rkvdec_isr, + .finish = rkvdec_finish, + .result = rkvdec_result, + .free_task = rkvdec_free_task, +}; + static struct mpp_hw_ops rkvdec_3328_hw_ops = { .init = rkvdec_3328_init, .exit = rkvdec_3328_exit, @@ -1790,7 +1807,7 @@ static const struct mpp_dev_var rk_hevcdec_px30_data = { .hw_info = &rk_hevcdec_hw_info, .trans_info = rk_hevcdec_trans, .hw_ops = &rkvdec_px30_hw_ops, - .dev_ops = &rkvdec_v1_dev_ops, + .dev_ops = &rkvdec_px30_dev_ops, }; static const struct mpp_dev_var rkvdec_v1_data = { diff --git a/drivers/video/rockchip/mpp/mpp_vdpu2.c b/drivers/video/rockchip/mpp/mpp_vdpu2.c index b63fc48c4568..af9817570e53 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpu2.c +++ b/drivers/video/rockchip/mpp/mpp_vdpu2.c @@ -375,6 +375,13 @@ static int vdpu_run(struct mpp_dev *mpp, return 0; } +static int vdpu_px30_run(struct mpp_dev *mpp, + struct mpp_task *mpp_task) +{ + mpp_iommu_flush_tlb(mpp->iommu_info); + return vdpu_run(mpp, mpp_task); +} + static int vdpu_finish(struct mpp_dev *mpp, struct mpp_task *mpp_task) { @@ -658,6 +665,16 @@ static struct mpp_dev_ops vdpu_v2_dev_ops = { .free_task = vdpu_free_task, }; +static struct mpp_dev_ops vdpu_px30_dev_ops = { + .alloc_task = vdpu_alloc_task, + .run = vdpu_px30_run, + .irq = vdpu_irq, + .isr = vdpu_isr, + .finish = vdpu_finish, + .result = vdpu_result, + .free_task = vdpu_free_task, +}; + static const struct mpp_dev_var vdpu_v2_data = { .device_type = MPP_DEVICE_VDPU2, .hw_info = &vdpu_v2_hw_info, @@ -671,7 +688,7 @@ static const struct mpp_dev_var vdpu_px30_data = { .hw_info = &vdpu_v2_hw_info, .trans_info = vdpu_v2_trans, .hw_ops = &vdpu_px30_hw_ops, - .dev_ops = &vdpu_v2_dev_ops, + .dev_ops = &vdpu_px30_dev_ops, }; static const struct of_device_id mpp_vdpu2_dt_match[] = { diff --git a/drivers/video/rockchip/mpp/mpp_vepu2.c b/drivers/video/rockchip/mpp/mpp_vepu2.c index cb61fc044b6a..f767c533515d 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu2.c +++ b/drivers/video/rockchip/mpp/mpp_vepu2.c @@ -388,6 +388,13 @@ static int vepu_run(struct mpp_dev *mpp, return 0; } +static int vepu_px30_run(struct mpp_dev *mpp, + struct mpp_task *mpp_task) +{ + mpp_iommu_flush_tlb(mpp->iommu_info); + return vepu_run(mpp, mpp_task); +} + static int vepu_irq(struct mpp_dev *mpp) { mpp->irq_status = mpp_read(mpp, VEPU2_REG_INT); @@ -902,6 +909,20 @@ static struct mpp_dev_ops vepu_v2_dev_ops = { .dump_session = vepu_dump_session, }; +static struct mpp_dev_ops vepu_px30_dev_ops = { + .alloc_task = vepu_alloc_task, + .run = vepu_px30_run, + .irq = vepu_irq, + .isr = vepu_isr, + .finish = vepu_finish, + .result = vepu_result, + .free_task = vepu_free_task, + .ioctl = vepu_control, + .init_session = vepu_init_session, + .free_session = vepu_free_session, + .dump_session = vepu_dump_session, +}; + static struct mpp_dev_ops vepu_ccu_dev_ops = { .alloc_task = vepu_alloc_task, .prepare = vepu_prepare, @@ -931,7 +952,7 @@ static const struct mpp_dev_var vepu_px30_data = { .hw_info = &vepu_v2_hw_info, .trans_info = trans_rk_vepu2, .hw_ops = &vepu_px30_hw_ops, - .dev_ops = &vepu_v2_dev_ops, + .dev_ops = &vepu_px30_dev_ops, }; static const struct mpp_dev_var vepu_ccu_data = { From 411f2d11eec307cc03d3711898a4913cc03362ca Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Thu, 10 Nov 2022 10:51:36 +0800 Subject: [PATCH 011/235] arm64: dts: rockchip: px30: fix enc and dec run at the same issue Due to the particularity of the px30 iommu, it is necessary to configure the grf to switch iommu. So need to configure rockchip,shootdown-entire to prevent a case from happening: when one device is running, the task of another device operates iommu when doing map. This commit relies on the following commit: commit 3b67ff56d698 ("video: rockchip: mpp: add iommu flush tlb before hw run for px30") Signed-off-by: Yandong Lin Change-Id: Ifd94ab4b5d7f53f711320b608ff105539fd9b38d --- arch/arm64/boot/dts/rockchip/px30.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index ea9ab107fe3d..6b9adc6ba0c7 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -1580,6 +1580,7 @@ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; clock-names = "aclk", "iface"; power-domains = <&power PX30_PD_VPU>; + rockchip,shootdown-entire; #iommu-cells = <0>; status = "disabled"; }; @@ -1630,6 +1631,7 @@ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; clock-names = "aclk", "iface"; power-domains = <&power PX30_PD_VPU>; + rockchip,shootdown-entire; #iommu-cells = <0>; status = "disabled"; }; From af9e6b8f0404406409c8470e9c2cae87d9e61b20 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Mon, 14 Nov 2022 14:45:45 +0800 Subject: [PATCH 012/235] iommu/iova: fix cpu from 'unsigned long' to 'unsigned int' for for_each_online_cpu Fixes: 4fe55239b3ba ("iommu/iova: add iova procfs for each dma iommu") Signed-off-by: Jianqun Xu Change-Id: I2206cec92eaca795faaf18df6117b36108ea75b4 --- drivers/iommu/iova.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index 3558ccf88fb0..c710cb413a28 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -33,8 +33,9 @@ static int iova_used_show(struct seq_file *s, void *v) { struct iova_domain *iovad = s->private; struct iova *iova, *t; - unsigned long flags, cpu; + unsigned long flags; unsigned long used_pfn = 0; + unsigned int cpu; int i = 0; for_each_online_cpu(cpu) From b983e5d5b534a3708b7628f3a8ecb9806c3a4a6a Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Tue, 15 Nov 2022 16:31:00 +0800 Subject: [PATCH 013/235] ARM: dts: rockchip: rk3288-evb: fix edp panel node Rockchip kernel uses the simple-panel driver. Fixes: 8039c828a6cb ("ARM: dts: rockchip: Kill off "simple-panel" compatibles") Signed-off-by: Damon Ding Signed-off-by: Jianqun Xu Change-Id: Ic3398aba021cafaca2f092668d27c0c7ca2854a0 --- arch/arm/boot/dts/rk3288-evb-rk808-linux.dts | 48 -------------------- arch/arm/boot/dts/rk3288-evb.dtsi | 20 +++++++- 2 files changed, 19 insertions(+), 49 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts b/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts index c8c2dfafe4f4..7d06817d3d8b 100644 --- a/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts +++ b/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts @@ -46,39 +46,6 @@ / { compatible = "rockchip,rk3288-evb-rk808-linux", "rockchip,rk3288"; - panel { - compatible = "simple-panel"; - backlight = <&backlight>; - enable-gpios = <&gpio7 RK_PA4 GPIO_ACTIVE_HIGH>; - prepare-delay-ms = <120>; - - display-timings { - native-mode = <&timing0>; - - timing0: timing0 { - clock-frequency = <200000000>; - hactive = <1536>; - vactive = <2048>; - hfront-porch = <12>; - hsync-len = <16>; - hback-porch = <48>; - vfront-porch = <8>; - vsync-len = <4>; - vback-porch = <8>; - hsync-active = <0>; - vsync-active = <0>; - de-active = <0>; - pixelclk-active = <0>; - }; - }; - - port { - panel_in_edp: endpoint { - remote-endpoint = <&edp_out_panel>; - }; - }; - }; - adc-keys { compatible = "adc-keys"; io-channels = <&saradc 1>; @@ -191,21 +158,6 @@ status = "okay"; }; -&edp { - force-hpd; - status = "okay"; - - ports { - port@1 { - reg = <1>; - - edp_out_panel: endpoint { - remote-endpoint = <&panel_in_edp>; - }; - }; - }; -}; - &edp_in_vopb { status = "disabled"; }; diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index 33c98c30a604..7a60a952d430 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -97,10 +97,28 @@ }; panel: panel { - compatible = "lg,lp079qx1-sp0v"; + compatible = "simple-panel"; backlight = <&backlight>; enable-gpios = <&gpio7 RK_PA4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; pinctrl-0 = <&lcd_cs>; + prepare-delay-ms = <120>; + + panel-timing { + clock-frequency = <200000000>; + hactive = <1536>; + hfront-porch = <12>; + hback-porch = <48>; + hsync-len = <16>; + vactive = <2048>; + vfront-porch = <8>; + vback-porch = <8>; + vsync-len = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; ports { panel_in: port { From 7e31422aa467ee857e4e88ead1e8667f6e117a54 Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Fri, 8 Jul 2022 17:57:14 +0800 Subject: [PATCH 014/235] UPSTREAM: extcon: Add EXTCON_DISP_CVBS and EXTCON_DISP_EDP Add EXTCON_DISP_CVBS for Composite Video Broadcast Signal. Add EXTCON_DISP_EDP for Embedded Display Port [1] https://en.wikipedia.org/wiki/Composite_video [2] https://en.wikipedia.org/wiki/DisplayPort#eDP Signed-off-by: Michael Wu Signed-off-by: Chanwoo Choi (cherry picked from commit 3a06ed80265fa62eecaf519d92f1633e4f9510c7) Change-Id: I95d278eb158341ea3d08d16e7c300a775107c302 Signed-off-by: Wyon Bi --- drivers/extcon/extcon.c | 10 ++++++++++ include/linux/extcon.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 7b9ff1392deb..dfdb151364de 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -172,6 +172,16 @@ static const struct __extcon_info { .id = EXTCON_DISP_HMD, .name = "HMD", }, + [EXTCON_DISP_CVBS] = { + .type = EXTCON_TYPE_DISP, + .id = EXTCON_DISP_CVBS, + .name = "CVBS", + }, + [EXTCON_DISP_EDP] = { + .type = EXTCON_TYPE_DISP, + .id = EXTCON_DISP_EDP, + .name = "EDP", + }, /* Miscellaneous external connector */ [EXTCON_DOCK] = { diff --git a/include/linux/extcon.h b/include/linux/extcon.h index 9c4ff7f7df29..6f851be8cb25 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -77,6 +77,8 @@ #define EXTCON_DISP_VGA 43 /* Video Graphics Array */ #define EXTCON_DISP_DP 44 /* Display Port */ #define EXTCON_DISP_HMD 45 /* Head-Mounted Display */ +#define EXTCON_DISP_CVBS 46 /* Composite Video Broadcast Signal */ +#define EXTCON_DISP_EDP 47 /* Embedded Display Port */ /* Miscellaneous external connector */ #define EXTCON_DOCK 60 From b37ab4ccd03095614b2395573f4dcbd07958be9d Mon Sep 17 00:00:00 2001 From: William Wu Date: Tue, 8 Nov 2022 17:26:00 +0800 Subject: [PATCH 015/235] usb: gadget: uvc: wait for req complete before free req when uvc calls uvcg_video_enable() to disable the video stream, it dequeues all requests from the usb endpoint, and it expects the usb controller to giveback the requests immediately, and then it can free the requests safely. But for usb dwc3 controller, it doesn't giveback the started requests in dequeue ops. Instead, it issues the end transfer command and wait for the command completion IRQ, then giveback the requests to uvc. If the uvc driver free req before the command completion IRQ, it will led to null pointer dereference problem. So need to wait for the req complete before free it. Example call stack on RK3588 platform: Thread#1: uvcg_video_enable() -> usb_ep_dequeue() -> dwc3_gadget_ep_dequeue() -> dwc3_stop_active_transfer() issue end transfer command -> dwc3_gadget_move_cancelled_request() ... -> uvc_video_free_requests() -> Thread#2 executes Thread#2: dwc3 end transfer command completion IRQ occurs dwc3_gadget_endpoint_command_complete() -> dwc3_gadget_ep_cleanup_cancelled_requests() -> dwc3_gadget_giveback() -> usb_gadget_giveback_request() -> uvc_video_complete() Signed-off-by: William Wu Change-Id: I0bcb8d18e851448fc973f901d74afa19ab1e2406 --- drivers/usb/gadget/function/uvc.h | 3 ++ drivers/usb/gadget/function/uvc_video.c | 38 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 7e9af56d060a..9a5507d49545 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -77,6 +77,9 @@ struct uvc_request { struct usb_request *req; u8 *req_buffer; struct uvc_video *video; +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + struct completion req_done; +#endif }; struct uvc_video { diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 4962b5562ba7..bec9e6155d61 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -32,11 +32,42 @@ static bool uvc_using_zero_copy(struct uvc_video *video) else return false; } + +static void uvc_wait_req_complete(struct uvc_video *video, struct uvc_request *ureq) +{ + unsigned long flags; + struct usb_request *req; + int ret; + + spin_lock_irqsave(&video->req_lock, flags); + + list_for_each_entry(req, &video->req_free, list) { + if (req == ureq->req) + break; + } + + if (req != ureq->req) { + reinit_completion(&ureq->req_done); + + spin_unlock_irqrestore(&video->req_lock, flags); + ret = wait_for_completion_timeout(&ureq->req_done, + msecs_to_jiffies(500)); + if (ret == 0) + uvcg_warn(&video->uvc->func, + "timed out waiting for req done\n"); + return; + } + + spin_unlock_irqrestore(&video->req_lock, flags); +} #else static inline bool uvc_using_zero_copy(struct uvc_video *video) { return false; } + +static inline void uvc_wait_req_complete(struct uvc_video *video, struct uvc_request *ureq) +{ } #endif /* -------------------------------------------------------------------------- @@ -212,6 +243,9 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) spin_lock_irqsave(&video->req_lock, flags); list_add_tail(&req->list, &video->req_free); +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + complete(&ureq->req_done); +#endif spin_unlock_irqrestore(&video->req_lock, flags); if (uvc->state == UVC_STATE_STREAMING) @@ -226,6 +260,7 @@ uvc_video_free_requests(struct uvc_video *video) if (video->ureq) { for (i = 0; i < video->uvc_num_requests; ++i) { if (video->ureq[i].req) { + uvc_wait_req_complete(video, &video->ureq[i]); usb_ep_free_request(video->ep, video->ureq[i].req); video->ureq[i].req = NULL; } @@ -282,6 +317,9 @@ uvc_video_alloc_requests(struct uvc_video *video) video->ureq[i].req->context = &video->ureq[i]; video->ureq[i].video = video; +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + init_completion(&video->ureq[i].req_done); +#endif list_add_tail(&video->ureq[i].req->list, &video->req_free); } From 672b2060ed99c2b2b667f09ad65fe679c64a500f Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 15 Nov 2022 01:59:32 +0000 Subject: [PATCH 016/235] drm/bridge: analogix_dp: Compatible for EXTCON_DISP_EDP cable Signed-off-by: Wyon Bi Change-Id: I042d3f855fdb09f971d9d533951c267686a57245 --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 92f22cffc68f..bf41d8244fb4 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -37,6 +37,11 @@ static const bool verify_fast_training; +#ifdef CONFIG_NO_GKI +#undef EXTCON_DISP_DP +#define EXTCON_DISP_DP EXTCON_DISP_EDP +#endif + static const unsigned int analogix_dp_cable[] = { EXTCON_DISP_DP, EXTCON_NONE, From b199fc40bf53fe9dcb835f5fcb085fb41f2245cc Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Tue, 15 Nov 2022 16:58:29 +0800 Subject: [PATCH 017/235] ARM: dts: rockchip: rk3288-evb hdmi use i2c-hdmi instead of i2c5 Fix the error from pinctrl [ 5.112827] rockchip-pinctrl pinctrl: could not request pin 235 (gpio7-19) from group i2c5-xfer on device rockchip-pinctrl [ 5.123951] rk3x-i2c ff170000.i2c: Error applying setting, reverse things back [ 5.131207] rk3x-i2c: probe of ff170000.i2c failed with error -22 Signed-off-by: Jianqun Xu Change-Id: I7bdf76832fb2805ced05f0a5bb52612f528d8ebf --- arch/arm/boot/dts/rk3288-evb.dtsi | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index 7a60a952d430..4fc7d681a044 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -279,7 +279,6 @@ }; &hdmi { - ddc-i2c-bus = <&i2c5>; status = "okay"; }; @@ -287,10 +286,6 @@ status = "okay"; }; -&i2c5 { - status = "okay"; -}; - &wdt { status = "okay"; }; From 4e8fc0099df5dc8280cb9e9a33359749866bb32a Mon Sep 17 00:00:00 2001 From: Jacob Chen Date: Tue, 15 Nov 2022 09:28:22 +0800 Subject: [PATCH 018/235] MALI: utgard: fix mali_mmap failed Validate vmf_insert_pfn return value with VM_FAULT_NOPAGE Signed-off-by: Jacob Chen Change-Id: I53b1eabd20ab76f08f5edf571ead1ffaccd19ec1 --- drivers/gpu/arm/mali400/mali/linux/mali_memory_cow.c | 6 +++--- drivers/gpu/arm/mali400/mali/linux/mali_memory_manager.c | 1 - drivers/gpu/arm/mali400/mali/linux/mali_memory_os_alloc.c | 6 +++--- drivers/gpu/arm/mali400/mali/linux/mali_memory_secure.c | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_cow.c b/drivers/gpu/arm/mali400/mali/linux/mali_memory_cow.c index 0bdf90b167d6..b9de93ede394 100644 --- a/drivers/gpu/arm/mali400/mali/linux/mali_memory_cow.c +++ b/drivers/gpu/arm/mali400/mali/linux/mali_memory_cow.c @@ -534,8 +534,8 @@ int mali_mem_cow_cpu_map(mali_mem_backend *mem_bkend, struct vm_area_struct *vma */ ret = vmf_insert_pfn(vma, addr, _mali_page_node_get_pfn(m_page)); - if (unlikely(0 != ret)) { - return ret; + if (unlikely(VM_FAULT_NOPAGE != ret)) { + return -EFAULT; } addr += _MALI_OSK_MALI_PAGE_SIZE; } @@ -571,7 +571,7 @@ _mali_osk_errcode_t mali_mem_cow_cpu_map_pages_locked(mali_mem_backend *mem_bken if ((count >= offset) && (count < offset + num)) { ret = vmf_insert_pfn(vma, vaddr, _mali_page_node_get_pfn(m_page)); - if (unlikely(0 != ret)) { + if (unlikely(VM_FAULT_NOPAGE != ret)) { if (count == offset) { return _MALI_OSK_ERR_FAULT; } else { diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_manager.c b/drivers/gpu/arm/mali400/mali/linux/mali_memory_manager.c index 27dee0f19c81..6c0a2e9a8a14 100644 --- a/drivers/gpu/arm/mali400/mali/linux/mali_memory_manager.c +++ b/drivers/gpu/arm/mali400/mali/linux/mali_memory_manager.c @@ -592,7 +592,6 @@ failed_alloc_pages: failed_prepare_map: mali_mem_backend_struct_destory(&mem_backend, mali_allocation->backend_handle); failed_alloc_backend: - mali_vma_offset_remove(&session->allocation_mgr, &mali_allocation->mali_vma_node); mali_mem_allocation_struct_destory(mali_allocation); diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_os_alloc.c b/drivers/gpu/arm/mali400/mali/linux/mali_memory_os_alloc.c index 1e1f5eb4a0f7..9c8214ba3b8e 100755 --- a/drivers/gpu/arm/mali400/mali/linux/mali_memory_os_alloc.c +++ b/drivers/gpu/arm/mali400/mali/linux/mali_memory_os_alloc.c @@ -367,7 +367,7 @@ int mali_mem_os_cpu_map(mali_mem_backend *mem_bkend, struct vm_area_struct *vma) page = m_page->page; ret = vmf_insert_pfn(vma, addr, page_to_pfn(page)); - if (unlikely(0 != ret)) { + if (unlikely(VM_FAULT_NOPAGE != ret)) { return -EFAULT; } addr += _MALI_OSK_MALI_PAGE_SIZE; @@ -405,7 +405,7 @@ _mali_osk_errcode_t mali_mem_os_resize_cpu_map_locked(mali_mem_backend *mem_bken if (mapping_page_num > 0) { ret = vmf_insert_pfn(vma, vm_end, page_to_pfn(m_page->page)); - if (unlikely(0 != ret)) { + if (unlikely(VM_FAULT_NOPAGE != ret)) { /*will return -EBUSY If the page has already been mapped into table, but it's OK*/ if (-EBUSY == ret) { break; @@ -428,7 +428,7 @@ _mali_osk_errcode_t mali_mem_os_resize_cpu_map_locked(mali_mem_backend *mem_bken ret = vmf_insert_pfn(vma, vstart, page_to_pfn(m_page->page)); - if (unlikely(0 != ret)) { + if (unlikely(VM_FAULT_NOPAGE != ret)) { /*will return -EBUSY If the page has already been mapped into table, but it's OK*/ if (-EBUSY == ret) { break; diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_memory_secure.c b/drivers/gpu/arm/mali400/mali/linux/mali_memory_secure.c index 0b4f828680d0..63506bfbe9fe 100644 --- a/drivers/gpu/arm/mali400/mali/linux/mali_memory_secure.c +++ b/drivers/gpu/arm/mali400/mali/linux/mali_memory_secure.c @@ -131,7 +131,7 @@ int mali_mem_secure_cpu_map(mali_mem_backend *mem_bkend, struct vm_area_struct * for (j = 0; j < size / _MALI_OSK_MALI_PAGE_SIZE; j++) { ret = vmf_insert_pfn(vma, addr, PFN_DOWN(phys)); - if (unlikely(0 != ret)) { + if (unlikely(VM_FAULT_NOPAGE != ret)) { return -EFAULT; } addr += _MALI_OSK_MALI_PAGE_SIZE; From 62d3af47b81dcaa03eb3d5348c87b74e4b490f42 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Wed, 9 Nov 2022 09:17:38 +0800 Subject: [PATCH 019/235] PCI: rockchip: dw: Fix error in calling dw_pcie_prog_inbound_atu function drivers/pci/controller/dwc/pcie-dw-ep-rockchip.c:533:70: error: too few arguments to function call, expected 6, have 5 ret = dw_pcie_prog_inbound_atu(pci, free_win, bar, cpu_addr, as_type); Change-Id: Iaa3083f6cfe4edbba422fff5a245515f40c70db4 Signed-off-by: Jon Lin --- drivers/pci/controller/dwc/pcie-dw-ep-rockchip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/controller/dwc/pcie-dw-ep-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-ep-rockchip.c index f6156a624898..b0215077026f 100644 --- a/drivers/pci/controller/dwc/pcie-dw-ep-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-ep-rockchip.c @@ -530,7 +530,7 @@ static int rockchip_pcie_ep_set_bar(struct rockchip_pcie *rockchip) bar = BAR_0; cpu_addr = rockchip->ib_target_address; - ret = dw_pcie_prog_inbound_atu(pci, free_win, bar, cpu_addr, as_type); + ret = dw_pcie_prog_inbound_atu(pci, 0, free_win, bar, cpu_addr, as_type); if (ret < 0) { dev_err(pci->dev, "Failed to program IB window\n"); return ret; From 933af6b20cb4e050ccf2ccbafa1608634b6e7564 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Wed, 16 Nov 2022 07:33:30 +0000 Subject: [PATCH 020/235] media: i2c: sensors: fix pm_runtime_put issue in HDR mode Change-Id: I11189e30eeb5ac2b7073888329e819a9a7f6b074 Signed-off-by: Jianwei Fan --- drivers/media/i2c/imx335.c | 5 +++-- drivers/media/i2c/imx415.c | 5 +++-- drivers/media/i2c/imx577.c | 5 +++-- drivers/media/i2c/os05a20.c | 7 ++++--- drivers/media/i2c/ov12d2q.c | 5 +++-- drivers/media/i2c/ov2775.c | 5 +++-- drivers/media/i2c/sc2232.c | 5 +++-- drivers/media/i2c/sc4210.c | 5 +++-- drivers/media/i2c/sc500ai.c | 5 +++-- drivers/media/i2c/sc530ai.c | 5 +++-- 10 files changed, 31 insertions(+), 21 deletions(-) diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index d33d16c0c799..e741c52b9bfd 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -1734,7 +1734,7 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_EXPOSURE: if (imx335->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; shr0 = imx335->cur_vts - ctrl->val; ret = imx335_write_reg(imx335->client, IMX335_LF_EXPO_REG_L, IMX335_REG_VALUE_08BIT, @@ -1750,7 +1750,7 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_ANALOGUE_GAIN: if (imx335->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; ret = imx335_write_reg(imx335->client, IMX335_LF_GAIN_REG_H, IMX335_REG_VALUE_08BIT, IMX335_FETCH_GAIN_H(ctrl->val)); @@ -1830,6 +1830,7 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) break; } +ctrl_end: pm_runtime_put(&client->dev); return ret; diff --git a/drivers/media/i2c/imx415.c b/drivers/media/i2c/imx415.c index ccc93119ddaa..f0276b812713 100644 --- a/drivers/media/i2c/imx415.c +++ b/drivers/media/i2c/imx415.c @@ -2303,7 +2303,7 @@ static int imx415_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_EXPOSURE: if (imx415->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; shr0 = imx415->cur_vts - ctrl->val; ret = imx415_write_reg(imx415->client, IMX415_LF_EXPO_REG_L, IMX415_REG_VALUE_08BIT, @@ -2319,7 +2319,7 @@ static int imx415_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_ANALOGUE_GAIN: if (imx415->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; ret = imx415_write_reg(imx415->client, IMX415_LF_GAIN_REG_H, IMX415_REG_VALUE_08BIT, IMX415_FETCH_GAIN_H(ctrl->val)); @@ -2388,6 +2388,7 @@ static int imx415_set_ctrl(struct v4l2_ctrl *ctrl) break; } +ctrl_end: pm_runtime_put(&client->dev); return ret; diff --git a/drivers/media/i2c/imx577.c b/drivers/media/i2c/imx577.c index 53da4ddc6f68..24c2f1e84aac 100644 --- a/drivers/media/i2c/imx577.c +++ b/drivers/media/i2c/imx577.c @@ -2048,7 +2048,7 @@ static int imx577_set_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_EXPOSURE: /* 4 least significant bits of expsoure are fractional part */ if (imx577->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; ret = imx577_write_reg(imx577->client, IMX577_REG_EXPOSURE_H, IMX577_REG_VALUE_08BIT, @@ -2067,7 +2067,7 @@ static int imx577_set_ctrl(struct v4l2_ctrl *ctrl) * gain_reg = 1024 - 1024 * 16 / (gain_ana * 16) */ if (imx577->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; if (ctrl->val > 0x1600) ctrl->val = 0x1600; if (ctrl->val < 0x10) @@ -2138,6 +2138,7 @@ static int imx577_set_ctrl(struct v4l2_ctrl *ctrl) break; } +ctrl_end: pm_runtime_put(&client->dev); return ret; diff --git a/drivers/media/i2c/os05a20.c b/drivers/media/i2c/os05a20.c index 3ca1b2df6086..b47a0fb8a4fc 100644 --- a/drivers/media/i2c/os05a20.c +++ b/drivers/media/i2c/os05a20.c @@ -674,7 +674,7 @@ static const struct os05a20_mode supported_modes[] = { .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1, .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0 .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1, - .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2 //Á½Õë¹Ì¶¨¶ÌÖ¡ + .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2 }, }; @@ -1565,7 +1565,7 @@ static int os05a20_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_EXPOSURE: if (os05a20->cur_mode->hdr_mode != NO_HDR) - return 0; + goto ctrl_end; ret = os05a20_write_reg(os05a20->client, OS05A20_REG_EXP_LONG_H, OS05A20_REG_VALUE_16BIT, @@ -1575,7 +1575,7 @@ static int os05a20_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_ANALOGUE_GAIN: if (os05a20->cur_mode->hdr_mode != NO_HDR) - return 0; + goto ctrl_end; if (ctrl->val > 1984) {// >15.5x dgain = ctrl->val * 10 / 155; again = 1984; @@ -1634,6 +1634,7 @@ static int os05a20_set_ctrl(struct v4l2_ctrl *ctrl) break; } +ctrl_end: pm_runtime_put(&client->dev); return ret; diff --git a/drivers/media/i2c/ov12d2q.c b/drivers/media/i2c/ov12d2q.c index 66d5830e901c..0d92a446b0cc 100644 --- a/drivers/media/i2c/ov12d2q.c +++ b/drivers/media/i2c/ov12d2q.c @@ -2761,7 +2761,7 @@ static int ov12d2q_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_EXPOSURE: if (ov12d2q->cur_mode->hdr_mode != NO_HDR) - return 0; + goto ctrl_end; ret = ov12d2q_write_reg(ov12d2q->client, OV12D2Q_REG_EXP_L_H, OV12D2Q_REG_VALUE_16BIT, @@ -2771,7 +2771,7 @@ static int ov12d2q_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_ANALOGUE_GAIN: if (ov12d2q->cur_mode->hdr_mode != NO_HDR) - return 0; + goto ctrl_end; if (ctrl->val > 1984) {// >15.5x dgain = ctrl->val * 10 / 155; again = 1984; @@ -2888,6 +2888,7 @@ static int ov12d2q_set_ctrl(struct v4l2_ctrl *ctrl) break; } +ctrl_end: pm_runtime_put(&client->dev); return ret; diff --git a/drivers/media/i2c/ov2775.c b/drivers/media/i2c/ov2775.c index 589b7bf6dc42..da438d47e2f2 100644 --- a/drivers/media/i2c/ov2775.c +++ b/drivers/media/i2c/ov2775.c @@ -4865,7 +4865,7 @@ static int ov2775_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_EXPOSURE: if (ov2775->cur_mode->hdr_mode != NO_HDR) - return 0; + goto ctrl_end; ret = ov2775_write_reg(ov2775->client, OV2775_REG_EXPOSURE_H, OV2775_REG_VALUE_08BIT, @@ -4880,7 +4880,7 @@ static int ov2775_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_ANALOGUE_GAIN: if (ov2775->cur_mode->hdr_mode != NO_HDR) - return 0; + goto ctrl_end; ov2775_get_linear_reg(ctrl->val, &gain_a, &gain_d); ret = ov2775_write_reg(ov2775->client, OV2775_REG_GAIN, @@ -4937,6 +4937,7 @@ static int ov2775_set_ctrl(struct v4l2_ctrl *ctrl) break; } +ctrl_end: pm_runtime_put(&client->dev); return ret; diff --git a/drivers/media/i2c/sc2232.c b/drivers/media/i2c/sc2232.c index 0278d2f31b55..59156adda6c0 100644 --- a/drivers/media/i2c/sc2232.c +++ b/drivers/media/i2c/sc2232.c @@ -1192,7 +1192,7 @@ static int sc2232_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_EXPOSURE: if (sc2232->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; val = ctrl->val << 1; ret = sc2232_write_reg(sc2232->client, SC2232_REG_EXP_LONG_L, @@ -1210,7 +1210,7 @@ static int sc2232_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_ANALOGUE_GAIN: if (sc2232->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; ret = sc2232_set_gain(sc2232, ctrl->val); break; case V4L2_CID_VBLANK: @@ -1256,6 +1256,7 @@ static int sc2232_set_ctrl(struct v4l2_ctrl *ctrl) break; } +ctrl_end: pm_runtime_put(&client->dev); return ret; } diff --git a/drivers/media/i2c/sc4210.c b/drivers/media/i2c/sc4210.c index 5f8958f1ad87..b3277973e3cf 100644 --- a/drivers/media/i2c/sc4210.c +++ b/drivers/media/i2c/sc4210.c @@ -2357,7 +2357,7 @@ static int sc4210_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_EXPOSURE: if (sc4210->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; val = ctrl->val << 1; ret = sc4210_write_reg(sc4210->client, SC4210_REG_EXPOSURE_H, @@ -2376,7 +2376,7 @@ static int sc4210_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_ANALOGUE_GAIN: if (sc4210->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; sc4210_get_gain_reg(ctrl->val, &again, &again_fine, &dgain, &dgain_fine); ret = sc4210_write_reg(sc4210->client, @@ -2448,6 +2448,7 @@ static int sc4210_set_ctrl(struct v4l2_ctrl *ctrl) break; } +ctrl_end: pm_runtime_put(&client->dev); return ret; diff --git a/drivers/media/i2c/sc500ai.c b/drivers/media/i2c/sc500ai.c index 00456f9b3b41..060c5d216ca1 100644 --- a/drivers/media/i2c/sc500ai.c +++ b/drivers/media/i2c/sc500ai.c @@ -1433,7 +1433,7 @@ static int sc500ai_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_EXPOSURE: if (sc500ai->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; val = ctrl->val << 1; ret = sc500ai_write_reg(sc500ai->client, SC500AI_REG_EXPOSURE_H, @@ -1452,7 +1452,7 @@ static int sc500ai_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_ANALOGUE_GAIN: if (sc500ai->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; sc500ai_get_gain_reg(ctrl->val, &again, &again_fine, &dgain, &dgain_fine); ret = sc500ai_write_reg(sc500ai->client, @@ -1557,6 +1557,7 @@ static int sc500ai_set_ctrl(struct v4l2_ctrl *ctrl) break; } +ctrl_end: pm_runtime_put(&client->dev); return ret; diff --git a/drivers/media/i2c/sc530ai.c b/drivers/media/i2c/sc530ai.c index b582ed65dd37..7c92587c518d 100644 --- a/drivers/media/i2c/sc530ai.c +++ b/drivers/media/i2c/sc530ai.c @@ -1668,7 +1668,7 @@ static int sc530ai_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_EXPOSURE: if (sc530ai->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; val = ctrl->val << 1; ret = sc530ai_write_reg(sc530ai->client, SC530AI_REG_EXPOSURE_H, @@ -1687,7 +1687,7 @@ static int sc530ai_set_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_ANALOGUE_GAIN: if (sc530ai->cur_mode->hdr_mode != NO_HDR) - return ret; + goto ctrl_end; sc530ai_get_gain_reg(ctrl->val, &again, &dgain, &dgain_fine); ret = sc530ai_write_reg(sc530ai->client, @@ -1756,6 +1756,7 @@ static int sc530ai_set_ctrl(struct v4l2_ctrl *ctrl) break; } +ctrl_end: pm_runtime_put(&client->dev); return ret; From 9086c42501da99d5226585afe036d9d9e0e32593 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Wed, 16 Nov 2022 06:59:23 +0000 Subject: [PATCH 021/235] media: i2c: imx577: fix configuration of HDR2 30fps Change-Id: Iea82c79fd52a30f06fcbd6d0782958ebead9ee96 Signed-off-by: Jianwei Fan --- drivers/media/i2c/imx577.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/imx577.c b/drivers/media/i2c/imx577.c index 24c2f1e84aac..3fc6e38443a9 100644 --- a/drivers/media/i2c/imx577.c +++ b/drivers/media/i2c/imx577.c @@ -9,8 +9,9 @@ * V0.0X01.0X02 fix gain and exposure setting. * V0.0X01.0X03 * 1.support 10bit HDR DOL2. - * 2.4032*3040 @ 25fps + * 2.4056*3040 @ 25fps * V0.0X01.0X04 add dgain ctrl + * V0.0X01.0X05 fix 4056*3040 HDRx2 30fps * */ @@ -38,7 +39,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x04) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x05) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -707,8 +708,8 @@ static __maybe_unused const struct regval imx577_hdr2_10bit_4056x3040_30fps_regs {0x0114, 0x03}, {0x0342, 0x11}, {0x0343, 0xA0}, - {0x0340, 0x0E}, - {0x0341, 0x8A}, + {0x0340, 0x0C}, + {0x0341, 0x1E}, {0x3210, 0x00}, {0x0344, 0x00}, {0x0345, 0x00}, @@ -968,11 +969,11 @@ static const struct imx577_mode supported_modes[] = { .height = 3040, .max_fps = { .numerator = 10000, - .denominator = 250000, + .denominator = 300000, }, .exp_def = 0x0c10, .hts_def = 0x11a0, - .vts_def = 0x0e8a, + .vts_def = 0x0c1e, .bpp = 10, .bus_fmt = MEDIA_BUS_FMT_SRGGB10_1X10, .reg_list = imx577_hdr2_10bit_4056x3040_30fps_regs, From a9a4f474d752ddcd66ca404649512bd48828945f Mon Sep 17 00:00:00 2001 From: William Wu Date: Wed, 16 Nov 2022 09:44:58 +0800 Subject: [PATCH 022/235] usb: dwc3: gadget: fix deadlock in kick transfer If kick transfer command fail and the return value isn't EAGAIN, the current code will issue end transfer command to stop the active transfer, and only set dep->flags with DWC3_EP_END_TRANSFER_PENDING if the end transfer command is done successfully. If the DWC3_EP_END_TRANSFER_PENDING isn't set, it cleanup the cancelled requests and give the request back to the gadget layer immediately. For uvc gadget, the uvc gadget driver hold spinlock and then call usb_ep_queue() to submit uvc usb request to dwc3 controller. The dwc3 controller may kick transfer for the request sequentially, if the kick transfer command and the end transfer command all failed, the dwc3 will give the request back to the uvc gadget driver via the request complete function uvc_video_complete(), in this function, it try to get the spinlock again that lead to deadlock. This case always happens with the following warning log: WARNING: CPU: 0 PID: 14450 at drivers/usb/dwc3/gadget.c:1839 __dwc3_gadget_kick_transfer+0x3a0/0x3b0 ... Workqueue: events uvcg_video_pump ... Call trace: __dwc3_gadget_kick_transfer+0x3a0/0x3b0 __dwc3_gadget_ep_queue+0x128/0x1f0 dwc3_gadget_ep_queue+0x40/0x6c usb_ep_queue+0x44/0x100 uvcg_video_pump+0xd0/0x1d4 process_one_work+0x1f4/0x490 worker_thread+0x278/0x4dc kthread+0x13c/0x344 ret_from_fork+0x10/0x30 Fixes: 0ec00e864a87 ("UPSTREAM: usb: dwc3: gadget: move cmd_endtransfer to extra function") Change-Id: I43d455a45d542efcaa9234de60e37277611b3c47 Signed-off-by: William Wu --- drivers/usb/dwc3/gadget.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2b7900241ae8..637bb2ea78f7 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1851,7 +1851,7 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int if (!interrupt) dep->flags &= ~DWC3_EP_TRANSFER_STARTED; - else if (!ret) + else dep->flags |= DWC3_EP_END_TRANSFER_PENDING; return ret; @@ -2032,8 +2032,11 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep) * status, issue END_TRANSFER command and retry on the next XferNotReady * event. */ - if (ret == -EAGAIN) + if (ret == -EAGAIN) { ret = __dwc3_stop_active_transfer(dep, false, true); + if (ret) + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; + } return ret; } From fb22b123d6239a2a74b7a3673726e259babe884f Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Mon, 14 Nov 2022 15:22:05 +0800 Subject: [PATCH 023/235] arm64: dts: rockchip: use new type-c framework on rk3399pro evb boards Amends to support the new type-c framework. Change-Id: I060da4667e6a5da9477841f80995c459021ef345 Signed-off-by: Caesar Wang --- .../rockchip/rk3399pro-evb-lp4-v11-linux.dts | 50 ++++++-- .../dts/rockchip/rk3399pro-evb-v10-linux.dts | 98 +++++++++++++--- .../boot/dts/rockchip/rk3399pro-evb-v10.dts | 98 +++++++++++++--- .../dts/rockchip/rk3399pro-evb-v11-linux.dts | 110 +++++++++++++++--- .../boot/dts/rockchip/rk3399pro-evb-v11.dts | 100 +++++++++++++--- 5 files changed, 376 insertions(+), 80 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-evb-lp4-v11-linux.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-evb-lp4-v11-linux.dts index f975f47b76d6..e0a75ed92439 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399pro-evb-lp4-v11-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399pro-evb-lp4-v11-linux.dts @@ -8,6 +8,7 @@ #include #include #include +#include "dt-bindings/usb/pd.h" #include "rk3399pro.dtsi" #include "rk3399-linux.dtsi" #include "rk3399-opp.dtsi" @@ -208,6 +209,16 @@ regulator-boot-on; }; + vbus_typec: vbus-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec0_en>; + regulator-name = "vbus_typec"; + vin-supply = <&vcc5v0_sys>; + }; + vcc5v0_sys: vccsys { compatible = "regulator-fixed"; regulator-name = "vcc5v0_sys"; @@ -243,7 +254,6 @@ &cdn_dp { status = "okay"; - extcon = <&fusb0>; phys = <&tcphy0_dp>; }; @@ -746,7 +756,6 @@ bq25700: bq25700@6b { compatible = "ti,bq25703"; reg = <0x6b>; - extcon = <&fusb0>; interrupt-parent = <&gpio1>; interrupts = ; pinctrl-names = "default"; @@ -1072,8 +1081,16 @@ }; &tcphy0 { - extcon = <&fusb0>; status = "okay"; + orientation-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + tcphy0_orientation_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_orien_sw>; + }; + }; }; &tcphy1 { @@ -1144,7 +1161,15 @@ &usbdrd_dwc3_0 { status = "okay"; - extcon = <&fusb0>; + usb-role-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + dwc3_0_role_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_role_sw>; + }; + }; }; &usbdrd_dwc3_1 { @@ -1178,13 +1203,6 @@ }; }; - fusb30x { - fusb0_int: fusb0-int { - rockchip,pins = - <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - headphone { hp_det: hp-det { rockchip,pins = @@ -1275,6 +1293,16 @@ }; }; + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vcc5v0_typec0_en: vcc5v0-typec0-en { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + wireless-bluetooth { bt_irq_gpio: bt-irq-gpio { rockchip,pins = diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v10-linux.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v10-linux.dts index 08ac2a477852..004ccbc3d8d6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v10-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v10-linux.dts @@ -8,6 +8,7 @@ #include #include #include +#include "dt-bindings/usb/pd.h" #include "rk3399pro.dtsi" #include "rk3399-linux.dtsi" #include "rk3399-opp.dtsi" @@ -196,6 +197,16 @@ reset-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_LOW>; }; + vbus_typec: vbus-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec0_en>; + regulator-name = "vbus_typec"; + vin-supply = <&vcc5v0_sys>; + }; + vcc_phy: vcc-phy-regulator { compatible = "regulator-fixed"; regulator-name = "vcc_phy"; @@ -238,7 +249,6 @@ &cdn_dp { status = "okay"; - extcon = <&fusb0>; phys = <&tcphy0_dp>; }; @@ -647,7 +657,6 @@ bq25700: bq25700@6b { compatible = "ti,bq25703"; reg = <0x6b>; - extcon = <&fusb0>; interrupt-parent = <&gpio1>; interrupts = ; pinctrl-names = "default"; @@ -774,13 +783,52 @@ i2c-scl-falling-time-ns = <11>; clock-frequency = <100000>; - fusb0: fusb30x@22 { - compatible = "fairchild,fusb302"; + usbc0: fusb302@22 { + compatible = "fcs,fusb302"; reg = <0x22>; + interrupt-parent = <&gpio1>; + interrupts = ; pinctrl-names = "default"; - pinctrl-0 = <&fusb0_int>; - int-n-gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&usbc0_int>; + vbus-supply = <&vbus_typec>; status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_role_sw: endpoint@0 { + remote-endpoint = <&dwc3_0_role_switch>; + }; + }; + }; + + usb_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + data-role = "dual"; + power-role = "dual"; + try-power-role = "sink"; + op-sink-microwatt = <1000000>; + sink-pdos = + ; + source-pdos = + ; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_orien_sw: endpoint { + remote-endpoint = <&tcphy0_orientation_switch>; + }; + }; + }; + }; }; }; @@ -982,8 +1030,16 @@ }; &tcphy0 { - extcon = <&fusb0>; status = "okay"; + orientation-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + tcphy0_orientation_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_orien_sw>; + }; + }; }; &tcphy1 { @@ -998,7 +1054,6 @@ &u2phy0 { status = "okay"; - extcon = <&fusb0>; u2phy0_otg: otg-port { status = "okay"; @@ -1054,7 +1109,15 @@ &usbdrd_dwc3_0 { status = "okay"; - extcon = <&fusb0>; + usb-role-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + dwc3_0_role_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_role_sw>; + }; + }; }; &usbdrd_dwc3_1 { @@ -1088,13 +1151,6 @@ }; }; - fusb30x { - fusb0_int: fusb0-int { - rockchip,pins = - <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - headphone { hp_det: hp-det { rockchip,pins = @@ -1146,6 +1202,16 @@ }; }; + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vcc5v0_typec0_en: vcc5v0-typec0-en { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + sdio-pwrseq { wifi_enable_h: wifi-enable-h { rockchip,pins = diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v10.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v10.dts index 398f962114cf..8eb9ac1ae383 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v10.dts @@ -197,6 +197,16 @@ reset-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_LOW>; }; + vbus_typec: vbus-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec0_en>; + regulator-name = "vbus_typec"; + vin-supply = <&vcc5v0_sys>; + }; + vcc_phy: vcc-phy-regulator { compatible = "regulator-fixed"; regulator-name = "vcc_phy"; @@ -239,7 +249,6 @@ &cdn_dp { status = "okay"; - extcon = <&fusb0>; phys = <&tcphy0_dp>; }; @@ -676,7 +685,6 @@ bq25700: bq25700@6b { compatible = "ti,bq25703"; reg = <0x6b>; - extcon = <&fusb0>; interrupt-parent = <&gpio1>; interrupts = ; pinctrl-names = "default"; @@ -750,15 +758,53 @@ i2c-scl-falling-time-ns = <11>; clock-frequency = <100000>; - fusb0: fusb30x@22 { - compatible = "fairchild,fusb302"; + usbc0: fusb302@22 { + compatible = "fcs,fusb302"; reg = <0x22>; + interrupt-parent = <&gpio1>; + interrupts = ; pinctrl-names = "default"; - pinctrl-0 = <&fusb0_int>; - int-n-gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&usbc0_int>; + vbus-supply = <&vbus_typec>; status = "okay"; - }; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_role_sw: endpoint@0 { + remote-endpoint = <&dwc3_0_role_switch>; + }; + }; + }; + + usb_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + data-role = "dual"; + power-role = "dual"; + try-power-role = "sink"; + op-sink-microwatt = <1000000>; + sink-pdos = + ; + source-pdos = + ; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_orien_sw: endpoint { + remote-endpoint = <&tcphy0_orientation_switch>; + }; + }; + }; + }; + }; }; &i2s1 { @@ -856,8 +902,16 @@ }; &tcphy0 { - extcon = <&fusb0>; status = "okay"; + orientation-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + tcphy0_orientation_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_orien_sw>; + }; + }; }; &tcphy1 { @@ -872,7 +926,6 @@ &u2phy0 { status = "okay"; - extcon = <&fusb0>; u2phy0_otg: otg-port { status = "okay"; @@ -928,7 +981,15 @@ &usbdrd_dwc3_0 { status = "okay"; - extcon = <&fusb0>; + usb-role-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + dwc3_0_role_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_role_sw>; + }; + }; }; &usbdrd_dwc3_1 { @@ -956,13 +1017,6 @@ }; }; - fusb30x { - fusb0_int: fusb0-int { - rockchip,pins = - <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - headphone { hp_det: hp-det { rockchip,pins = @@ -1048,6 +1102,16 @@ }; }; + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vcc5v0_typec0_en: vcc5v0-typec0-en { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + wireless-bluetooth { uart0_gpios: uart0-gpios { rockchip,pins = diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v11-linux.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v11-linux.dts index c3faaa1ba4d3..84fc2c743c57 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v11-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v11-linux.dts @@ -8,6 +8,7 @@ #include #include #include +#include "dt-bindings/usb/pd.h" #include "rk3399pro.dtsi" #include "rk3399-linux.dtsi" #include "rk3399-opp.dtsi" @@ -201,6 +202,26 @@ status = "disabled"; }; + vbus_typec: vbus-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec0_en>; + regulator-name = "vbus_typec"; + vin-supply = <&vcc5v0_sys>; + }; + + vbus_typec: vbus-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec0_en>; + regulator-name = "vbus_typec"; + vin-supply = <&vcc5v0_sys>; + }; + vcc_phy: vcc-phy-regulator { compatible = "regulator-fixed"; regulator-name = "vcc_phy"; @@ -243,7 +264,6 @@ &cdn_dp { status = "okay"; - extcon = <&fusb0>; phys = <&tcphy0_dp>; }; @@ -657,7 +677,6 @@ bq25700: bq25700@6b { compatible = "ti,bq25703"; reg = <0x6b>; - extcon = <&fusb0>; interrupt-parent = <&gpio1>; interrupts = ; pinctrl-names = "default"; @@ -786,16 +805,53 @@ i2c-scl-falling-time-ns = <11>; clock-frequency = <100000>; - fusb0: fusb30x@22 { - compatible = "fairchild,fusb302"; + usbc0: fusb302@22 { + compatible = "fcs,fusb302"; reg = <0x22>; + interrupt-parent = <&gpio1>; + interrupts = ; pinctrl-names = "default"; - pinctrl-0 = <&fusb0_int>; - int-n-gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>; - vbus-5v-gpios = <&gpio0 RK_PA1 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&usbc0_int>; + vbus-supply = <&vbus_typec>; status = "okay"; - }; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_role_sw: endpoint@0 { + remote-endpoint = <&dwc3_0_role_switch>; + }; + }; + }; + + usb_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + data-role = "dual"; + power-role = "dual"; + try-power-role = "sink"; + op-sink-microwatt = <1000000>; + sink-pdos = + ; + source-pdos = + ; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_orien_sw: endpoint { + remote-endpoint = <&tcphy0_orientation_switch>; + }; + }; + }; + }; + }; }; &i2s1 { @@ -995,8 +1051,16 @@ }; &tcphy0 { - extcon = <&fusb0>; status = "okay"; + orientation-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + tcphy0_orientation_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_orien_sw>; + }; + }; }; &tcphy1 { @@ -1011,7 +1075,6 @@ &u2phy0 { status = "okay"; - extcon = <&fusb0>; u2phy0_otg: otg-port { status = "okay"; @@ -1067,7 +1130,15 @@ &usbdrd_dwc3_0 { status = "okay"; - extcon = <&fusb0>; + usb-role-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + dwc3_0_role_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_role_sw>; + }; + }; }; &usbdrd_dwc3_1 { @@ -1108,13 +1179,6 @@ }; }; - fusb30x { - fusb0_int: fusb0-int { - rockchip,pins = - <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - headphone { hp_det: hp-det { rockchip,pins = @@ -1205,6 +1269,16 @@ }; }; + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vcc5v0_typec0_en: vcc5v0-typec0-en { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + wireless-bluetooth { bt_irq_gpio: bt-irq-gpio { rockchip,pins = diff --git a/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v11.dts b/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v11.dts index 7d118a783353..6fea49960e39 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v11.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399pro-evb-v11.dts @@ -8,6 +8,7 @@ #include #include #include +#include "dt-bindings/usb/pd.h" #include "rk3399pro.dtsi" #include "rk3399-android.dtsi" #include "rk3399-opp.dtsi" @@ -198,6 +199,16 @@ reset-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_LOW>; }; + vbus_typec: vbus-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec0_en>; + regulator-name = "vbus_typec"; + vin-supply = <&vcc5v0_sys>; + }; + vcc_phy: vcc-phy-regulator { compatible = "regulator-fixed"; regulator-name = "vcc_phy"; @@ -240,7 +251,6 @@ &cdn_dp { status = "okay"; - extcon = <&fusb0>; phys = <&tcphy0_dp>; }; @@ -661,7 +671,6 @@ bq25700: bq25700@6b { compatible = "ti,bq25703"; reg = <0x6b>; - extcon = <&fusb0>; interrupt-parent = <&gpio1>; interrupts = ; pinctrl-names = "default"; @@ -735,16 +744,53 @@ i2c-scl-falling-time-ns = <11>; clock-frequency = <100000>; - fusb0: fusb30x@22 { - compatible = "fairchild,fusb302"; + usbc0: fusb302@22 { + compatible = "fcs,fusb302"; reg = <0x22>; + interrupt-parent = <&gpio1>; + interrupts = ; pinctrl-names = "default"; - pinctrl-0 = <&fusb0_int>; - int-n-gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>; - vbus-5v-gpios = <&gpio0 RK_PA1 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&usbc0_int>; + vbus-supply = <&vbus_typec>; status = "okay"; - }; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_role_sw: endpoint@0 { + remote-endpoint = <&dwc3_0_role_switch>; + }; + }; + }; + + usb_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + data-role = "dual"; + power-role = "dual"; + try-power-role = "sink"; + op-sink-microwatt = <1000000>; + sink-pdos = + ; + source-pdos = + ; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_orien_sw: endpoint { + remote-endpoint = <&tcphy0_orientation_switch>; + }; + }; + }; + }; + }; }; &i2s1 { @@ -838,8 +884,16 @@ }; &tcphy0 { - extcon = <&fusb0>; status = "okay"; + orientation-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + tcphy0_orientation_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_orien_sw>; + }; + }; }; &tcphy1 { @@ -854,7 +908,6 @@ &u2phy0 { status = "okay"; - extcon = <&fusb0>; u2phy0_otg: otg-port { status = "okay"; @@ -911,7 +964,15 @@ &usbdrd_dwc3_0 { status = "okay"; - extcon = <&fusb0>; + usb-role-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + dwc3_0_role_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_role_sw>; + }; + }; }; &usbdrd_dwc3_1 { @@ -939,13 +1000,6 @@ }; }; - fusb30x { - fusb0_int: fusb0-int { - rockchip,pins = - <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - headphone { hp_det: hp-det { rockchip,pins = @@ -1031,6 +1085,16 @@ }; }; + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vcc5v0_typec0_en: vcc5v0-typec0-en { + rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + wireless-bluetooth { uart0_gpios: uart0-gpios { rockchip,pins = From 72fafe97a1fc11be5f09d2cdcbb93eda3960c0d3 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Fri, 30 Sep 2022 18:51:46 +0800 Subject: [PATCH 024/235] drm/rockchip: Add dynamic debug Signed-off-by: Andy Yan Change-Id: I441245ec77122dae766c9e175d182ee6d15e217f --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 30 +++++++++++++++++ drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 11 +++++++ drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 34 +++++++++++++------- 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 7531cdc6f313..582fa1390d5c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -53,6 +53,36 @@ static bool iommu_reserve_map; static struct drm_driver rockchip_drm_driver; +static unsigned int drm_debug; +module_param_named(debug, drm_debug, int, 0600); + +static inline bool rockchip_drm_debug_enabled(enum rockchip_drm_debug_category category) +{ + return unlikely(drm_debug & category); +} + +__printf(3, 4) +void rockchip_drm_dbg(const struct device *dev, enum rockchip_drm_debug_category category, + const char *format, ...) +{ + struct va_format vaf; + va_list args; + + if (!rockchip_drm_debug_enabled(category)) + return; + + va_start(args, format); + vaf.fmt = format; + vaf.va = &args; + + if (dev) + dev_printk(KERN_DEBUG, dev, "%pV", &vaf); + else + printk(KERN_DEBUG "%pV", &vaf); + + va_end(args); +} + /** * rockchip_drm_wait_vact_end * @crtc: CRTC to enable line flag diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 434d3c93271b..f470d798e916 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -64,6 +64,14 @@ struct iommu_domain; #define RK_IF_PROP_COLOR_DEPTH_CAPS "color_depth_caps" #define RK_IF_PROP_COLOR_FORMAT_CAPS "color_format_caps" +enum rockchip_drm_debug_category { + VOP_DEBUG_PLANE = BIT(0), + VOP_DEBUG_OVERLAY = BIT(1), + VOP_DEBUG_WB = BIT(2), + VOP_DEBUG_CFG_DONE = BIT(3), + VOP_DEBUG_VSYNC = BIT(7), +}; + enum rk_if_color_depth { RK_IF_DEPTH_8, RK_IF_DEPTH_10, @@ -490,6 +498,9 @@ int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap, const struct edid *edid); int rockchip_drm_parse_next_hdr(struct next_hdr_sink_data *sink_data, const struct edid *edid); +__printf(3, 4) +void rockchip_drm_dbg(const struct device *dev, enum rockchip_drm_debug_category category, + const char *format, ...); extern struct platform_driver cdn_dp_driver; extern struct platform_driver dw_hdmi_rockchip_pltfm_driver; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 7ea5a356e16e..c61598e28dbe 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1488,6 +1488,9 @@ static inline void rk3568_vop2_cfg_done(struct drm_crtc *crtc) * This is rather low probability for miss some done bit. */ val |= vop2_readl(vop2, RK3568_REG_CFG_DONE) & 0x7; + + rockchip_drm_dbg(vop2->dev, VOP_DEBUG_CFG_DONE, "cfg_done: 0x%x\n", val); + vop2_writel(vop2, 0, val); /** @@ -1513,6 +1516,8 @@ static inline void rk3588_vop2_cfg_done(struct drm_crtc *crtc) if (vcstate->splice_mode) val |= BIT(vp_data->splice_vp_id) | (BIT(vp_data->splice_vp_id) << 16); + rockchip_drm_dbg(vop2->dev, VOP_DEBUG_CFG_DONE, "cfg_done: 0x%x\n", val); + vop2_writel(vop2, 0, val); } @@ -3156,8 +3161,10 @@ static void vop2_wb_commit(struct drm_crtc *crtc) if (conn_state->writeback_job && conn_state->writeback_job->fb) { struct drm_framebuffer *fb = conn_state->writeback_job->fb; - DRM_DEV_DEBUG(vop2->dev, "Enable wb %ux%u fmt: %u pitches: %d addr: %pad\n", - fb->width, fb->height, wb_state->format, fb->pitches[0], &wb_state->yrgb_addr); + rockchip_drm_dbg(vop2->dev, VOP_DEBUG_WB, + "Enable wb %ux%u fmt: %u pitches: %d addr: %pad\n", + fb->width, fb->height, wb_state->format, + fb->pitches[0], &wb_state->yrgb_addr); drm_writeback_queue_job(wb_conn, conn_state); conn_state->writeback_job = NULL; @@ -4611,7 +4618,8 @@ static void vop2_plane_atomic_disable(struct drm_plane *plane, struct drm_plane_ struct vop2_plane_state *vpstate = to_vop2_plane_state(plane->state); #endif - DRM_DEV_DEBUG(vop2->dev, "%s disable\n", win->name); + rockchip_drm_dbg(vop2->dev, VOP_DEBUG_PLANE, "%s disable %s\n", + win->name, current->comm); if (!old_state->crtc) return; @@ -4896,11 +4904,12 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s vop2_win_enable(win); spin_lock(&vop2->reg_lock); - DRM_DEV_DEBUG(vop2->dev, "vp%d update %s[%dx%d->%dx%d@(%d, %d)] fmt[%.4s%s] addr[%pad]\n", - vp->id, win->name, actual_w, actual_h, dsp_w, dsp_h, - dsp_stx, dsp_sty, - drm_get_format_name(fb->format->format, &format_name), - modifier_to_string(fb->modifier), &vpstate->yrgb_mst); + rockchip_drm_dbg(vop2->dev, VOP_DEBUG_PLANE, + "vp%d update %s[%dx%d->%dx%d@(%d, %d)] fmt[%.4s%s] addr[%pad] by %s\n", + vp->id, win->name, actual_w, actual_h, dsp_w, dsp_h, + dsp_stx, dsp_sty, + drm_get_format_name(fb->format->format, &format_name), + modifier_to_string(fb->modifier), &vpstate->yrgb_mst, current->comm); if (vop2->version != VOP_VERSION_RK3568) rk3588_vop2_win_cfg_axi(win); @@ -8478,8 +8487,8 @@ static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state vop2_zpos[nr_layers].zpos = vpstate->zpos; vop2_zpos[nr_layers].plane = plane; - DRM_DEV_DEBUG(vop2->dev, "%s active zpos:%d for vp%d from vp%d\n", - win->name, vpstate->zpos, vp->id, old_vp->id); + rockchip_drm_dbg(vop2->dev, VOP_DEBUG_OVERLAY, "%s active zpos:%d for vp%d from vp%d\n", + win->name, vpstate->zpos, vp->id, old_vp->id); /* left and right win may have different number */ if (vcstate->splice_mode) { splice_win = vop2_find_win_by_phys_id(vop2, win->splice_win_id); @@ -8512,8 +8521,8 @@ static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state } vp->hdr10_at_splice_mode = hdr10_at_splice_mode; - DRM_DEV_DEBUG(vop2->dev, "vp%d: %d windows, active layers %d\n", - vp->id, hweight32(vp->win_mask), nr_layers); + rockchip_drm_dbg(vop2->dev, VOP_DEBUG_OVERLAY, "vp%d: %d windows, active layers %d\n", + vp->id, hweight32(vp->win_mask), nr_layers); if (nr_layers) { vp->nr_layers = nr_layers; @@ -9345,6 +9354,7 @@ static irqreturn_t vop2_isr(int irq, void *data) } if (active_irqs & FS_FIELD_INTR) { + rockchip_drm_dbg(vop2->dev, VOP_DEBUG_VSYNC, "vsync_vp%d\n", vp->id); vop2_wb_handler(vp); if (likely(!vp->skip_vsync) || (vp->layer_sel_update == false)) { drm_crtc_handle_vblank(crtc); From 28567ec23ea9f7b797bed3afb32a4ed2a588a195 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Mon, 11 Jan 2021 17:43:05 +0800 Subject: [PATCH 025/235] ASoC: rockchip: pdm: Add support for clk compensation This patch introduces a method to handle clk drift and compensation. e.g: /# amixer contents numid=1,iface=PCM,name='PCM Clk Compensation In PPM' ; type=INTEGER,access=rw------,values=1,min=-1000,max=1000,step=1 : values=0 /# arecord -D hw:0,0 --period-size=1024 --buffer-size=4096 -r 16000 -c 2 -f s16_le /dev/zero & /# amixer -- cset numid=1 -10 numid=1,iface=PCM,name='PCM Clk Compensation In PPM' ; type=INTEGER,access=rw------,values=1,min=-1000,max=1000,step=1 : values=-10 /# amixer -- cset numid=1 10 numid=1,iface=PCM,name='PCM Clk Compensation In PPM' ; type=INTEGER,access=rw------,values=1,min=-1000,max=1000,step=1 : values=10 Change-Id: Ibc70ce8ccec6dddb082161fa544d066c706c37bc Signed-off-by: Sugar Zhang Signed-off-by: XiaoTan Luo --- sound/soc/rockchip/rockchip_pdm.c | 128 +++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 3 deletions(-) diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index 703219e9c42c..85e545aac523 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -29,6 +30,8 @@ #define PDM_FILTER_DELAY_MS_MIN (20) #define PDM_FILTER_DELAY_MS_MAX (1000) #define PDM_CLK_SHIFT_PPM_MAX (1000000) /* 1 ppm */ +#define CLK_PPM_MIN (-1000) +#define CLK_PPM_MAX (1000) enum rk_pdm_version { RK_PDM_RK3229, @@ -40,6 +43,7 @@ enum rk_pdm_version { struct rk_pdm_dev { struct device *dev; struct clk *clk; + struct clk *clk_root; struct clk *hclk; struct regmap *regmap; struct snd_dmaengine_dai_dma_data capture_dma_data; @@ -47,6 +51,10 @@ struct rk_pdm_dev { unsigned int start_delay_ms; unsigned int filter_delay_ms; enum rk_pdm_version version; + unsigned int clk_root_rate; + unsigned int clk_root_initial_rate; + int clk_ppm; + bool clk_calibrate; }; struct rk_pdm_clkref { @@ -103,6 +111,11 @@ static unsigned int get_pdm_clk(struct rk_pdm_dev *pdm, unsigned int sr, div = sr / clkref[i].sr; if ((div & (div - 1)) == 0) { *clk_out = clkref[i].clk_out; + if (pdm->clk_calibrate) { + clk = clkref[i].clk; + *clk_src = clk; + break; + } rate = clk_round_rate(pdm->clk, clkref[i].clk); delta = clkref[i].clk / PDM_CLK_SHIFT_PPM_MAX; if (rate < clkref[i].clk - delta || @@ -219,8 +232,8 @@ static void rockchip_pdm_rxctrl(struct rk_pdm_dev *pdm, int on) static int rockchip_pdm_set_samplerate(struct rk_pdm_dev *pdm, unsigned int samplerate) { - unsigned int val = 0; - unsigned int clk_rate, clk_div; + unsigned int val = 0, div = 0; + unsigned int clk_rate, clk_div, rate; unsigned int clk_src = 0, clk_out = 0, signoff = PDM_SIGNOFF_CLK_100M; unsigned long m, n; bool change; @@ -232,9 +245,30 @@ static int rockchip_pdm_set_samplerate(struct rk_pdm_dev *pdm, unsigned int samp if (!clk_rate) return -EINVAL; + if (pdm->clk_calibrate) { + ret = clk_set_parent(pdm->clk, pdm->clk_root); + if (ret) + return ret; + + rate = pdm->clk_root_rate; + if (rate % clk_src) { + div = DIV_ROUND_CLOSEST(pdm->clk_root_initial_rate, clk_src); + if (!div) + return -EINVAL; + + rate = clk_src * round_up(div, 2); + pdm->clk_ppm = 0; + ret = clk_set_rate(pdm->clk_root, rate); + if (ret) + return ret; + + pdm->clk_root_rate = clk_get_rate(pdm->clk_root); + } + } + ret = clk_set_rate(pdm->clk, clk_src); if (ret) - return -EINVAL; + return ret; if (pdm->version == RK_PDM_RK3308 || pdm->version == RK_PDM_RK3588 || @@ -496,6 +530,81 @@ static const struct snd_kcontrol_new rockchip_pdm_controls[] = { }, }; +static int rockchip_pdm_clk_set_rate(struct rk_pdm_dev *pdm, + struct clk *clk, unsigned long rate) +{ + unsigned long rate_target; + int delta, ret; + + ret = rockchip_pll_clk_compensation(clk, pdm->clk_ppm); + if (!ret) + return ret; + + delta = (pdm->clk_ppm < 0) ? -1 : 1; + delta *= (int)div64_u64((uint64_t)rate * (uint64_t)abs(pdm->clk_ppm) + 500000, 1000000); + + rate_target = rate + delta; + + if (!rate_target) + return -EINVAL; + + ret = clk_set_rate(clk, rate_target); + + return ret; +} + +static int rockchip_pdm_clk_compensation_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = CLK_PPM_MIN; + uinfo->value.integer.max = CLK_PPM_MAX; + uinfo->value.integer.step = 1; + + return 0; +} + + +static int rockchip_pdm_clk_compensation_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + +{ + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai); + + ucontrol->value.integer.value[0] = pdm->clk_ppm; + + return 0; +} + + +static int rockchip_pdm_clk_compensation_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + +{ + struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); + struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai); + + + if ((ucontrol->value.integer.value[0] < CLK_PPM_MIN) || + (ucontrol->value.integer.value[0] > CLK_PPM_MAX)) + return -EINVAL; + + pdm->clk_ppm = ucontrol->value.integer.value[0]; + + return rockchip_pdm_clk_set_rate(pdm, pdm->clk_root, pdm->clk_root_rate); +} + +static struct snd_kcontrol_new rockchip_pdm_compensation_control = { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "PDM PCM Clk Compensation In PPM", + .info = rockchip_pdm_clk_compensation_info, + .get = rockchip_pdm_clk_compensation_get, + .put = rockchip_pdm_clk_compensation_put, + +}; + static int rockchip_pdm_dai_probe(struct snd_soc_dai *dai) { struct rk_pdm_dev *pdm = to_info(dai); @@ -503,6 +612,8 @@ static int rockchip_pdm_dai_probe(struct snd_soc_dai *dai) dai->capture_dma_data = &pdm->capture_dma_data; snd_soc_add_dai_controls(dai, rockchip_pdm_controls, ARRAY_SIZE(rockchip_pdm_controls)); + if (pdm->clk_calibrate) + snd_soc_add_dai_controls(dai, &rockchip_pdm_compensation_control, 1); return 0; } @@ -798,6 +909,17 @@ static int rockchip_pdm_probe(struct platform_device *pdev) pdm->start_delay_ms = PDM_START_DELAY_MS_DEFAULT; pdm->filter_delay_ms = PDM_FILTER_DELAY_MS_MIN; + pdm->clk_calibrate = + of_property_read_bool(node, "rockchip,mclk-calibrate"); + if (pdm->clk_calibrate) { + pdm->clk_root = devm_clk_get(&pdev->dev, "pdm_clk_root"); + if (IS_ERR(pdm->clk_root)) + return PTR_ERR(pdm->clk_root); + + pdm->clk_root_initial_rate = clk_get_rate(pdm->clk_root); + pdm->clk_root_rate = pdm->clk_root_initial_rate; + } + pdm->clk = devm_clk_get(&pdev->dev, "pdm_clk"); if (IS_ERR(pdm->clk)) return PTR_ERR(pdm->clk); From 89764514b717c2103b8871be58f14073aa1f6d76 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Thu, 14 Jan 2021 18:11:00 +0800 Subject: [PATCH 026/235] ASoC: rockchip: pdm: Shift rate back to 0 ppm when restart Change-Id: Ibb867e8b1a9a553a3077a7c91d415eea82cc76ba Signed-off-by: Sugar Zhang Signed-off-by: XiaoTan Luo --- sound/soc/rockchip/rockchip_pdm.c | 76 ++++++++++++++++++------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index 85e545aac523..5ec3fe8c1f33 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -229,13 +229,46 @@ static void rockchip_pdm_rxctrl(struct rk_pdm_dev *pdm, int on) } } +static int rockchip_pdm_clk_set_rate(struct rk_pdm_dev *pdm, + struct clk *clk, unsigned long rate, + int ppm) +{ + unsigned long rate_target; + int delta, ret; + + if (ppm == pdm->clk_ppm) + return 0; + + ret = rockchip_pll_clk_compensation(clk, ppm); + if (ret != -ENOSYS) + goto out; + + delta = (ppm < 0) ? -1 : 1; + delta *= (int)div64_u64((uint64_t)rate * (uint64_t)abs(ppm) + 500000, 1000000); + + rate_target = rate + delta; + + if (!rate_target) + return -EINVAL; + + ret = clk_set_rate(clk, rate_target); + if (ret) + return ret; +out: + if (!ret) + pdm->clk_ppm = ppm; + + return ret; +} + static int rockchip_pdm_set_samplerate(struct rk_pdm_dev *pdm, unsigned int samplerate) { unsigned int val = 0, div = 0; - unsigned int clk_rate, clk_div, rate; + unsigned int clk_rate, clk_div, rate, delta; unsigned int clk_src = 0, clk_out = 0, signoff = PDM_SIGNOFF_CLK_100M; unsigned long m, n; + uint64_t ppm; bool change; int ret; @@ -250,14 +283,21 @@ static int rockchip_pdm_set_samplerate(struct rk_pdm_dev *pdm, unsigned int samp if (ret) return ret; + ret = rockchip_pdm_clk_set_rate(pdm, pdm->clk_root, + pdm->clk_root_rate, 0); + if (ret) + return ret; + rate = pdm->clk_root_rate; - if (rate % clk_src) { + delta = abs(rate % clk_src - clk_src); + ppm = div64_u64((uint64_t)delta * 1000000, (uint64_t)rate); + + if (ppm) { div = DIV_ROUND_CLOSEST(pdm->clk_root_initial_rate, clk_src); if (!div) return -EINVAL; rate = clk_src * round_up(div, 2); - pdm->clk_ppm = 0; ret = clk_set_rate(pdm->clk_root, rate); if (ret) return ret; @@ -530,29 +570,6 @@ static const struct snd_kcontrol_new rockchip_pdm_controls[] = { }, }; -static int rockchip_pdm_clk_set_rate(struct rk_pdm_dev *pdm, - struct clk *clk, unsigned long rate) -{ - unsigned long rate_target; - int delta, ret; - - ret = rockchip_pll_clk_compensation(clk, pdm->clk_ppm); - if (!ret) - return ret; - - delta = (pdm->clk_ppm < 0) ? -1 : 1; - delta *= (int)div64_u64((uint64_t)rate * (uint64_t)abs(pdm->clk_ppm) + 500000, 1000000); - - rate_target = rate + delta; - - if (!rate_target) - return -EINVAL; - - ret = clk_set_rate(clk, rate_target); - - return ret; -} - static int rockchip_pdm_clk_compensation_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -578,22 +595,19 @@ static int rockchip_pdm_clk_compensation_get(struct snd_kcontrol *kcontrol, return 0; } - static int rockchip_pdm_clk_compensation_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) - { struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol); struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai); + int ppm = ucontrol->value.integer.value[0]; if ((ucontrol->value.integer.value[0] < CLK_PPM_MIN) || (ucontrol->value.integer.value[0] > CLK_PPM_MAX)) return -EINVAL; - pdm->clk_ppm = ucontrol->value.integer.value[0]; - - return rockchip_pdm_clk_set_rate(pdm, pdm->clk_root, pdm->clk_root_rate); + return rockchip_pdm_clk_set_rate(pdm, pdm->clk_root, pdm->clk_root_rate, ppm); } static struct snd_kcontrol_new rockchip_pdm_compensation_control = { From 416f4a15a49cd76486fc61100c747f20dba5d861 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Wed, 9 Nov 2022 15:58:15 +0800 Subject: [PATCH 027/235] PCI: rockchip: dw: Add cache clean for dma read test Add cache clean for coherent when DMA is running. Change-Id: Ic5df0588009367de6716db9c6cc418b05e8a43f6 Signed-off-by: Jon Lin --- drivers/pci/controller/dwc/pcie-dw-dmatest.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-dw-dmatest.c b/drivers/pci/controller/dwc/pcie-dw-dmatest.c index f6d2cbe159b1..79af779a2e6a 100644 --- a/drivers/pci/controller/dwc/pcie-dw-dmatest.c +++ b/drivers/pci/controller/dwc/pcie-dw-dmatest.c @@ -312,6 +312,14 @@ static int dma_test(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, long long us = 0; struct dma_trx_obj *obj = dmatest_dev->obj; + /* + * Clean the cache to ensure memory consistency. The CPU writes to the normal memory + * cache before the transmission is initiated, which may cause IO consistency problems, + * such as IO commands. + */ + if (rd_en) + dma_sync_single_for_device(obj->dev, local_paddr, size, DMA_TO_DEVICE); + start_time = ktime_get(); for (i = 0; i < loop; i++) { if (rd_en) { From 5083234249c388d81b9c1d50bb69373fa3c5f8a8 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Tue, 15 Nov 2022 15:55:31 +0800 Subject: [PATCH 028/235] mmc: dw_mmc: Remove useless SDMMC_INT_TXDR and SDMMC_INT_RXDR These two interrupts are managed by data routine and not need to enable it via runtime_resume each time. Signed-off-by: Shawn Lin Change-Id: I9ef2ae0acabefeba4a69ff6b4c7edc3c0318fdeb --- drivers/mmc/host/dw_mmc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index a77e439f35ca..df385fe6dd13 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -3618,9 +3618,7 @@ int dw_mci_runtime_resume(struct device *dev) mci_writel(host, TMOUT, 0xFFFFFFFF); mci_writel(host, RINTSTS, 0xFFFFFFFF); - mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | - SDMMC_INT_TXDR | SDMMC_INT_RXDR | - DW_MCI_ERROR_FLAGS); + mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | DW_MCI_ERROR_FLAGS); mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); if (host->is_rv1106_sd) { From b7cf98650b2f8cb1e59b89d43c15f96d318bf5bf Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Mon, 24 Oct 2022 20:30:54 +0800 Subject: [PATCH 029/235] mtd: spi-nor: core: Support misc devices Calling ioctl PCIE_DMA_GET_FLASH_INFO to get spi nor id. Change-Id: I1ecfdd527f18c0c323fba9673546c167032d1726 Signed-off-by: Jon Lin --- drivers/mtd/spi-nor/Kconfig | 7 +++ drivers/mtd/spi-nor/core.c | 86 +++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 1 + include/uapi/linux/spi_nor_misc.h | 20 +++++++ 4 files changed, 114 insertions(+) create mode 100644 include/uapi/linux/spi_nor_misc.h diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index ffc4b380f2b1..ed4a5640866a 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig @@ -24,6 +24,13 @@ config MTD_SPI_NOR_USE_4K_SECTORS Please note that some tools/drivers/filesystems may not work with 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum). +config MTD_SPI_NOR_MISC + bool "Support SPI NOR misc device" + default n + help + Support obtaining flash information through the ioctl interface + of the misc device. + source "drivers/mtd/spi-nor/controllers/Kconfig" endif # MTD_SPI_NOR diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 2f38ca1e5568..fdec7c815937 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -21,9 +21,17 @@ #include #include #include +#include + +#include #include "core.h" +struct spi_nor_misc_dev { + struct miscdevice dev; + struct spi_nor *nor; +}; + /* Define max times to check status register before we give up. */ /* @@ -3462,6 +3470,78 @@ static int spi_nor_create_write_dirmap(struct spi_nor *nor) return PTR_ERR_OR_ZERO(nor->dirmap.wdesc); } +static int spi_nor_misc_open(struct inode *inode, struct file *file) +{ + struct miscdevice *miscdev = file->private_data; + struct spi_nor_misc_dev *nor_dev; + + nor_dev = container_of(miscdev, struct spi_nor_misc_dev, dev); + file->private_data = nor_dev->nor; + + return 0; +} + +static long spi_nor_misc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct spi_nor *nor = (struct spi_nor *)file->private_data; + struct nor_flash_user_info info; + void __user *uarg = (void __user *)arg; + int i, ret; + + switch (cmd) { + case NOR_GET_FLASH_INFO: + for (i = 0; i < SPI_NOR_MAX_ID_LEN; i++) + info.id[i] = nor->info->id[i]; + + ret = copy_to_user(uarg, &info, sizeof(info)); + if (ret) { + dev_err(nor->dev, "failed to get elbi data\n"); + return -EFAULT; + } + break; + default: + break; + } + return 0; +} + +static const struct file_operations spi_nor_misc_ops = { + .owner = THIS_MODULE, + .open = spi_nor_misc_open, + .unlocked_ioctl = spi_nor_misc_ioctl, +}; + +static int spi_nor_add_misc(struct spi_nor *nor) +{ + int ret; + struct spi_nor_misc_dev *nor_dev; + char name[24]; + + nor_dev = devm_kzalloc(nor->dev, sizeof(struct spi_nor_misc_dev), + GFP_KERNEL); + if (!nor_dev) + return -ENOMEM; + + nor_dev->dev.minor = MISC_DYNAMIC_MINOR; + snprintf(name, sizeof(name), "%s%s", "nor_misc_", dev_name(nor->dev)); + nor_dev->dev.name = devm_kstrdup(nor->dev, name, GFP_KERNEL); + nor_dev->dev.fops = &spi_nor_misc_ops; + nor_dev->dev.parent = nor->dev; + + ret = misc_register(&nor_dev->dev); + if (ret) { + dev_err(nor->dev, "failed to register misc device.\n"); + return ret; + } + + nor_dev->nor = nor; + nor->misc_dev = &nor_dev->dev; + + dev_info(nor->dev, "register misc device\n"); + + return 0; +} + static int spi_nor_probe(struct spi_mem *spimem) { struct spi_device *spi = spimem->spi; @@ -3531,6 +3611,9 @@ static int spi_nor_probe(struct spi_mem *spimem) if (ret) return ret; + if (IS_ENABLED(CONFIG_MTD_SPI_NOR_MISC)) + spi_nor_add_misc(nor); + return mtd_device_register(&nor->mtd, data ? data->parts : NULL, data ? data->nr_parts : 0); } @@ -3541,6 +3624,9 @@ static int spi_nor_remove(struct spi_mem *spimem) spi_nor_restore(nor); + if (IS_ENABLED(CONFIG_MTD_SPI_NOR_MISC) && nor->misc_dev) + misc_deregister(nor->misc_dev); + /* Clean up MTD stuff. */ return mtd_device_unregister(&nor->mtd); } diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index bfe4d492c6bf..36d354a36077 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -388,6 +388,7 @@ struct spi_nor { struct spi_mem_dirmap_desc *wdesc; } dirmap; + struct miscdevice *misc_dev; void *priv; }; diff --git a/include/uapi/linux/spi_nor_misc.h b/include/uapi/linux/spi_nor_misc.h new file mode 100644 index 000000000000..4b6e604cc0fc --- /dev/null +++ b/include/uapi/linux/spi_nor_misc.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +#ifndef _UAPI__SPI_NOR_MISC_H__ +#define _UAPI__SPI_NOR_MISC_H__ + +#include + +#define SPI_NOR_MAX_ID_LEN 6 + +struct nor_flash_user_info { + __u8 id[SPI_NOR_MAX_ID_LEN]; +}; + +#define NOR_BASE 'P' +#define NOR_GET_FLASH_INFO _IOR(NOR_BASE, 0, struct nor_flash_user_info) + +#endif From 797a0b4b119c609af03948c9637c20110c94da62 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Wed, 16 Nov 2022 11:32:30 +0800 Subject: [PATCH 030/235] media: rockchip: isp: fix stats buf update for multi sensor Change-Id: Ic1a8b62ab73b0076a83033c350759be71df53793 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/rkisp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index 5859c1d85439..f3b0948237b1 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -2722,10 +2722,10 @@ static void rkisp_global_update_mi(struct rkisp_device *dev) struct rkisp_stream *stream; int i; + rkisp_stats_first_ddr_config(&dev->stats_vdev); if (dev->hw_dev->is_mi_update) return; - rkisp_stats_first_ddr_config(&dev->stats_vdev); rkisp_config_dmatx_valid_buf(dev); force_cfg_update(dev); From 660f1d040d94de67e9c96df2a9ab67b1fb694643 Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Thu, 17 Nov 2022 11:20:47 +0800 Subject: [PATCH 031/235] media: i2c: sc230ai: pm_runtime_put device until stream_off for thunderboot Signed-off-by: Su Yuefu Change-Id: If328b3af33d14fdc5309c35d6e3a222abbcb47ec --- drivers/media/i2c/sc230ai.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/sc230ai.c b/drivers/media/i2c/sc230ai.c index e7975c80fa85..bfd76fcfca2e 100644 --- a/drivers/media/i2c/sc230ai.c +++ b/drivers/media/i2c/sc230ai.c @@ -1107,8 +1107,10 @@ static int __sc230ai_start_stream(struct sc230ai *sc230ai) static int __sc230ai_stop_stream(struct sc230ai *sc230ai) { sc230ai->has_init_exp = false; - if (sc230ai->is_thunderboot) + if (sc230ai->is_thunderboot) { sc230ai->is_first_streamoff = true; + pm_runtime_put(&sc230ai->client->dev); + } return sc230ai_write_reg(sc230ai->client, SC230AI_REG_CTRL_MODE, SC230AI_REG_VALUE_08BIT, SC230AI_MODE_SW_STANDBY); } @@ -1744,7 +1746,10 @@ static int sc230ai_probe(struct i2c_client *client, pm_runtime_set_active(dev); pm_runtime_enable(dev); - pm_runtime_idle(dev); + if (sc230ai->is_thunderboot) + pm_runtime_get_sync(dev); + else + pm_runtime_idle(dev); return 0; From 927e0f59f77baff13233458076ba08ba43211d91 Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Thu, 17 Nov 2022 11:23:04 +0800 Subject: [PATCH 032/235] media: i2c: sc200ai: pm_runtime_put device until stream_off for thunderboot Signed-off-by: Su Yuefu Change-Id: I5754491e2d5344efcfe41897a241435b21804593 --- drivers/media/i2c/sc200ai.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/sc200ai.c b/drivers/media/i2c/sc200ai.c index 0eca27f3b01c..e47fa1abb81b 100644 --- a/drivers/media/i2c/sc200ai.c +++ b/drivers/media/i2c/sc200ai.c @@ -1394,8 +1394,10 @@ 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) + if (sc200ai->is_thunderboot) { sc200ai->is_first_streamoff = true; + pm_runtime_put(&sc200ai->client->dev); + } return sc200ai_write_reg(sc200ai->client, SC200AI_REG_CTRL_MODE, SC200AI_REG_VALUE_08BIT, SC200AI_MODE_SW_STANDBY); } @@ -2133,7 +2135,10 @@ static int sc200ai_probe(struct i2c_client *client, pm_runtime_set_active(dev); pm_runtime_enable(dev); - pm_runtime_idle(dev); + if (sc200ai->is_thunderboot) + pm_runtime_get_sync(dev); + else + pm_runtime_idle(dev); return 0; From d55a25476c976d4366bcf6ea02e2bd2bda1903f5 Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Thu, 17 Nov 2022 11:25:17 +0800 Subject: [PATCH 033/235] media: i2c: gc3003: pm_runtime_put device until stream_off for thunderboot Signed-off-by: Su Yuefu Change-Id: I041b9cdb4a3416951e5d3855e2d4400db84e3c94 --- drivers/media/i2c/gc3003.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/gc3003.c b/drivers/media/i2c/gc3003.c index cf5c652141cc..6bfe04d5acc1 100644 --- a/drivers/media/i2c/gc3003.c +++ b/drivers/media/i2c/gc3003.c @@ -1332,10 +1332,10 @@ static int __gc3003_stop_stream(struct gc3003 *gc3003) int ret; gc3003->has_init_exp = false; - - if (gc3003->is_thunderboot) + if (gc3003->is_thunderboot) { gc3003->is_first_streamoff = true; - + pm_runtime_put(&gc3003->client->dev); + } ret = gc3003_write_array(gc3003->client, gc3003->cur_mode->stand_by_reg_list); return ret; @@ -1994,7 +1994,10 @@ static int gc3003_probe(struct i2c_client *client, pm_runtime_set_active(dev); pm_runtime_enable(dev); - pm_runtime_idle(dev); + if (gc3003->is_thunderboot) + pm_runtime_get_sync(dev); + else + pm_runtime_idle(dev); return 0; From a9175d765e7be98f48bb1a3c0152d48076c2ad1b Mon Sep 17 00:00:00 2001 From: Ding Wei Date: Tue, 26 Nov 2019 15:34:52 +0800 Subject: [PATCH 034/235] video: rockchip: mpp: deal with the case for iommu share In platform arm32, iommu is shared in different device, it must attach to ensure hardware working in current device. Change-Id: I854a362adf6145dcfd796885922683f8a6b7e131 Signed-off-by: Ding Wei --- drivers/video/rockchip/mpp/mpp_common.c | 9 +++++++++ drivers/video/rockchip/mpp/mpp_iommu.c | 3 +++ 2 files changed, 12 insertions(+) diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index 2ac23651b26f..e7c7e50a994c 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -806,6 +806,15 @@ static int mpp_task_run(struct mpp_dev *mpp, } else { mpp_set_grf(mpp->grf_info); } + /* + * for iommu share hardware, should attach to ensure + * working in current device + */ + ret = mpp_iommu_attach(mpp->iommu_info); + if (ret) { + dev_err(mpp->dev, "mpp_iommu_attach failed\n"); + return -ENODATA; + } mpp_power_on(mpp); mpp_debug_func(DEBUG_TASK_INFO, "pid %d run %s\n", diff --git a/drivers/video/rockchip/mpp/mpp_iommu.c b/drivers/video/rockchip/mpp/mpp_iommu.c index db98386da6cd..5ba44f54f5fe 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.c +++ b/drivers/video/rockchip/mpp/mpp_iommu.c @@ -388,6 +388,9 @@ int mpp_iommu_attach(struct mpp_iommu_info *info) if (!info) return 0; + if (info->domain == iommu_get_domain_for_dev(info->dev)) + return 0; + return iommu_attach_group(info->domain, info->group); } From 2e18f6fc3220ba8674e4c11c6c5a61f9487a448a Mon Sep 17 00:00:00 2001 From: Chen Jinsen Date: Wed, 8 Apr 2020 17:33:07 +0800 Subject: [PATCH 035/235] ARM: dts: rockchip: vdpu support automatic frequency for rk3288 Signed-off-by: Chen Jinsen Change-Id: I0378d57524d1b7146dbebec3d4fa9c125430b0d0 --- arch/arm/boot/dts/rk3288.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 21ef673117b8..1e270ab8e8cc 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1419,7 +1419,7 @@ }; vdpu: vdpu@ff9a0400 { - compatible = "rockchip,vpu-decoder-v1"; + compatible = "rockchip,vpu-decoder-rk3288", "rockchip,vpu-decoder-v1"; reg = <0x0 0xff9a0400 0x0 0x400>; interrupts = ; interrupt-names = "irq_dec"; From fee9944154bd993826da136b006ed9d182cc7c06 Mon Sep 17 00:00:00 2001 From: Ding Wei Date: Wed, 27 May 2020 18:31:22 +0800 Subject: [PATCH 036/235] ARM: dts: rockchip: rk3288 add clk-rates setting for vdpu and rkvdec Change-Id: Ibd695ef470c40829a348c660dd94de3f6a2b320c Signed-off-by: Ding Wei --- arch/arm/boot/dts/rk3288.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 1e270ab8e8cc..77525dc41131 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1425,6 +1425,8 @@ interrupt-names = "irq_dec"; clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; clock-names = "aclk_vcodec", "hclk_vcodec"; + rockchip,normal-rates = <300000000>, <0>; + rockchip,advanced-rates = <600000000>, <0>; resets = <&cru SRST_VCODEC_AXI>, <&cru SRST_VCODEC_AHB>; reset-names = "shared_video_a", "shared_video_h"; assigned-clocks = <&cru ACLK_VCODEC>; @@ -1458,6 +1460,10 @@ <&cru SCLK_HEVC_CABAC>; clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core", "clk_cabac"; + rockchip,normal-rates = <300000000>, <0>, <200000000>, + <200000000>; + rockchip,advanced-rates = <500000000>, <0>, <400000000>, + <400000000>; resets = <&cru SRST_HEVC>; reset-names = "video_core"; From d5519c96056780c391e78c2bf689517cd11f7f08 Mon Sep 17 00:00:00 2001 From: Ding Wei Date: Thu, 25 Feb 2021 11:39:53 +0800 Subject: [PATCH 037/235] ARM: dts: rockchip: rk3288: hevc_service: add default val setting Change-Id: I3f71fe50e8b51e21728afae850f0aca21b8b160c Signed-off-by: Ding Wei --- arch/arm/boot/dts/rk3288.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 77525dc41131..3aa3d3b8611d 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1464,6 +1464,7 @@ <200000000>; rockchip,advanced-rates = <500000000>, <0>, <400000000>, <400000000>; + rockchip,default-max-load = <2088960>; resets = <&cru SRST_HEVC>; reset-names = "video_core"; From 9ec339342efc088b00f922911f66fa216f920956 Mon Sep 17 00:00:00 2001 From: Peter Geis Date: Thu, 20 May 2021 12:32:30 -0400 Subject: [PATCH 038/235] UPSTREAM: net: phy: add driver for Motorcomm yt8511 phy Add a driver for the Motorcomm yt8511 phy that will be used in the production Pine64 rk3566-quartz64 development board. It supports gigabit transfer speeds, rgmii, and 125mhz clk output. Signed-off-by: Peter Geis Signed-off-by: David S. Miller Signed-off-by: David Wu (cherry-pick from commit 48e8c6f1612b3d2dccaea2285231def830cc5b8e) Change-Id: If0af67cda0ad607e4a31f126804547e9d8b3df50 --- MAINTAINERS | 6 ++ drivers/net/phy/Kconfig | 6 ++ drivers/net/phy/Makefile | 1 + drivers/net/phy/motorcomm.c | 136 ++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 drivers/net/phy/motorcomm.c diff --git a/MAINTAINERS b/MAINTAINERS index e492b0e3a4c5..18d7e173ce34 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11836,6 +11836,12 @@ F: Documentation/userspace-api/media/drivers/meye* F: drivers/media/pci/meye/ F: include/uapi/linux/meye.h +MOTORCOMM PHY DRIVER +M: Peter Geis +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/phy/motorcomm.c + MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD M: Jiri Slaby S: Maintained diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 77c8fd3b6799..7b884fac7adc 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -223,6 +223,12 @@ config MICROSEMI_PHY help Currently supports VSC8514, VSC8530, VSC8531, VSC8540 and VSC8541 PHYs +config MOTORCOMM_PHY + tristate "Motorcomm PHYs" + help + Enables support for Motorcomm network PHYs. + Currently supports the YT8511 gigabit PHY. + config NATIONAL_PHY tristate "National Semiconductor PHYs" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index bcc1c1267d0c..8423e4a6fb3d 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_MICREL_PHY) += micrel.o obj-$(CONFIG_MICROCHIP_PHY) += microchip.o obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o obj-$(CONFIG_MICROSEMI_PHY) += mscc/ +obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o obj-$(CONFIG_NATIONAL_PHY) += national.o obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c new file mode 100644 index 000000000000..796b68f4b499 --- /dev/null +++ b/drivers/net/phy/motorcomm.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Driver for Motorcomm PHYs + * + * Author: Peter Geis + */ + +#include +#include +#include + +#define PHY_ID_YT8511 0x0000010a + +#define YT8511_PAGE_SELECT 0x1e +#define YT8511_PAGE 0x1f +#define YT8511_EXT_CLK_GATE 0x0c +#define YT8511_EXT_DELAY_DRIVE 0x0d +#define YT8511_EXT_SLEEP_CTRL 0x27 + +/* 2b00 25m from pll + * 2b01 25m from xtl *default* + * 2b10 62.m from pll + * 2b11 125m from pll + */ +#define YT8511_CLK_125M (BIT(2) | BIT(1)) +#define YT8511_PLLON_SLP BIT(14) + +/* RX Delay enabled = 1.8ns 1000T, 8ns 10/100T */ +#define YT8511_DELAY_RX BIT(0) + +/* TX Gig-E Delay is bits 7:4, default 0x5 + * TX Fast-E Delay is bits 15:12, default 0xf + * Delay = 150ps * N - 250ps + * On = 2000ps, off = 50ps + */ +#define YT8511_DELAY_GE_TX_EN (0xf << 4) +#define YT8511_DELAY_GE_TX_DIS (0x2 << 4) +#define YT8511_DELAY_FE_TX_EN (0xf << 12) +#define YT8511_DELAY_FE_TX_DIS (0x2 << 12) + +static int yt8511_read_page(struct phy_device *phydev) +{ + return __phy_read(phydev, YT8511_PAGE_SELECT); +}; + +static int yt8511_write_page(struct phy_device *phydev, int page) +{ + return __phy_write(phydev, YT8511_PAGE_SELECT, page); +}; + +static int yt8511_config_init(struct phy_device *phydev) +{ + unsigned int ge, fe; + int ret, oldpage; + + /* set clock mode to 125mhz */ + oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE); + if (oldpage < 0) + goto err_restore_page; + + ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M); + if (ret < 0) + goto err_restore_page; + + /* set rgmii delay mode */ + switch (phydev->interface) { + case PHY_INTERFACE_MODE_RGMII: + ge = YT8511_DELAY_GE_TX_DIS; + fe = YT8511_DELAY_FE_TX_DIS; + break; + case PHY_INTERFACE_MODE_RGMII_RXID: + ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_DIS; + fe = YT8511_DELAY_FE_TX_DIS; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + ge = YT8511_DELAY_GE_TX_EN; + fe = YT8511_DELAY_FE_TX_EN; + break; + case PHY_INTERFACE_MODE_RGMII_ID: + ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN; + fe = YT8511_DELAY_FE_TX_EN; + break; + default: /* leave everything alone in other modes */ + break; + } + + ret = __phy_modify(phydev, YT8511_PAGE, (YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN), ge); + if (ret < 0) + goto err_restore_page; + + /* fast ethernet delay is in a separate page */ + ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_DELAY_DRIVE); + if (ret < 0) + goto err_restore_page; + + ret = __phy_modify(phydev, YT8511_PAGE, YT8511_DELAY_FE_TX_EN, fe); + if (ret < 0) + goto err_restore_page; + + /* leave pll enabled in sleep */ + ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_SLEEP_CTRL); + if (ret < 0) + goto err_restore_page; + + ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_PLLON_SLP); + if (ret < 0) + goto err_restore_page; + +err_restore_page: + return phy_restore_page(phydev, oldpage, ret); +} + +static struct phy_driver motorcomm_phy_drvs[] = { + { + PHY_ID_MATCH_EXACT(PHY_ID_YT8511), + .name = "YT8511 Gigabit Ethernet", + .config_init = yt8511_config_init, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = yt8511_read_page, + .write_page = yt8511_write_page, + }, +}; + +module_phy_driver(motorcomm_phy_drvs); + +MODULE_DESCRIPTION("Motorcomm PHY driver"); +MODULE_AUTHOR("Peter Geis"); +MODULE_LICENSE("GPL"); + +static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { + { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, + { /* sentinal */ } +}; + +MODULE_DEVICE_TABLE(mdio, motorcomm_tbl); From 14adf98ff1bedc55c8fbe66db596729c07743c2d Mon Sep 17 00:00:00 2001 From: Peter Geis Date: Sat, 29 May 2021 07:05:55 -0400 Subject: [PATCH 039/235] UPSTREAM: net: phy: fix yt8511 clang uninitialized variable warning clang doesn't preinitialize variables. If phy_select_page failed and returned an error, phy_restore_page would be called with `ret` being uninitialized. Even though phy_restore_page won't use `ret` in this scenario, initialize `ret` to silence the warning. Fixes: 48e8c6f1612b ("net: phy: add driver for Motorcomm yt8511 phy") Reported-by: kernel test robot Reviewed-by: Andrew Lunn Signed-off-by: Peter Geis Signed-off-by: Jakub Kicinski Signed-off-by: David Wu (cherry-pick from commit 546d6bad18c04926c4d0eba4222654a9a60ea830) Change-Id: I0467ca4b5846e71ddca8a6818e5c021010a72d98 --- drivers/net/phy/motorcomm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c index 796b68f4b499..68cd19540c67 100644 --- a/drivers/net/phy/motorcomm.c +++ b/drivers/net/phy/motorcomm.c @@ -50,8 +50,8 @@ static int yt8511_write_page(struct phy_device *phydev, int page) static int yt8511_config_init(struct phy_device *phydev) { + int oldpage, ret = 0; unsigned int ge, fe; - int ret, oldpage; /* set clock mode to 125mhz */ oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE); From 4de4ec6c665b721832bda498ecd12596601e5113 Mon Sep 17 00:00:00 2001 From: Peter Geis Date: Sat, 29 May 2021 07:05:56 -0400 Subject: [PATCH 040/235] UPSTREAM: net: phy: abort loading yt8511 driver in unsupported modes While investigating the clang `ge` uninitialized variable report, it was discovered the default switch would have unintended consequences. Due to the switch to __phy_modify, the driver would modify the ID values in the default scenario. Fix this by promoting the interface mode switch and aborting when the mode is not a supported RGMII mode. This prevents the `ge` and `fe` variables from ever being used uninitialized. Fixes: 48e8c6f1612b ("net: phy: add driver for Motorcomm yt8511 phy") Reported-by: kernel test robot Reviewed-by: Andrew Lunn Signed-off-by: Peter Geis Signed-off-by: Jakub Kicinski Signed-off-by: David Wu (cherry-pick from commit 0cc8bddb5b0665283baba6d89684630663c0ccbd) Change-Id: I610c03a4f032a8a8dde8ef58d105b721c0541bf5 --- drivers/net/phy/motorcomm.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c index 68cd19540c67..7e6ac2c5e27e 100644 --- a/drivers/net/phy/motorcomm.c +++ b/drivers/net/phy/motorcomm.c @@ -53,15 +53,10 @@ static int yt8511_config_init(struct phy_device *phydev) int oldpage, ret = 0; unsigned int ge, fe; - /* set clock mode to 125mhz */ oldpage = phy_select_page(phydev, YT8511_EXT_CLK_GATE); if (oldpage < 0) goto err_restore_page; - ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M); - if (ret < 0) - goto err_restore_page; - /* set rgmii delay mode */ switch (phydev->interface) { case PHY_INTERFACE_MODE_RGMII: @@ -80,14 +75,20 @@ static int yt8511_config_init(struct phy_device *phydev) ge = YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN; fe = YT8511_DELAY_FE_TX_EN; break; - default: /* leave everything alone in other modes */ - break; + default: /* do not support other modes */ + ret = -EOPNOTSUPP; + goto err_restore_page; } ret = __phy_modify(phydev, YT8511_PAGE, (YT8511_DELAY_RX | YT8511_DELAY_GE_TX_EN), ge); if (ret < 0) goto err_restore_page; + /* set clock mode to 125mhz */ + ret = __phy_modify(phydev, YT8511_PAGE, 0, YT8511_CLK_125M); + if (ret < 0) + goto err_restore_page; + /* fast ethernet delay is in a separate page */ ret = __phy_write(phydev, YT8511_PAGE_SELECT, YT8511_EXT_DELAY_DRIVE); if (ret < 0) From 5b7a85aa3e5bf79c60c3889e02fdf58175a94001 Mon Sep 17 00:00:00 2001 From: David Wu Date: Mon, 7 Nov 2022 20:12:18 +0800 Subject: [PATCH 041/235] net: phy: Add motorcomm driver for RK631 PHY Signed-off-by: David Wu Change-Id: Iad8fd02e5f3dd2397dbdb7eb150325fc76e9c422 --- drivers/net/phy/Kconfig | 2 +- drivers/net/phy/motorcomm.c | 509 ++++++++++++++++++++++++++++++++++++ 2 files changed, 510 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 7b884fac7adc..1f94d0e85b9d 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -227,7 +227,7 @@ config MOTORCOMM_PHY tristate "Motorcomm PHYs" help Enables support for Motorcomm network PHYs. - Currently supports the YT8511 gigabit PHY. + Currently supports the YT8511, YT8521, YT8531, RK631 gigabit PHY. config NATIONAL_PHY tristate "National Semiconductor PHYs" diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c index 7e6ac2c5e27e..3cb8ea0a9c9d 100644 --- a/drivers/net/phy/motorcomm.c +++ b/drivers/net/phy/motorcomm.c @@ -7,9 +7,12 @@ #include #include +#include #include #define PHY_ID_YT8511 0x0000010a +#define PHY_ID_YT8531S 0x4f51e91a +#define PHY_ID_YT8531 0x4f51e91b #define YT8511_PAGE_SELECT 0x1e #define YT8511_PAGE 0x1f @@ -38,6 +41,45 @@ #define YT8511_DELAY_FE_TX_EN (0xf << 12) #define YT8511_DELAY_FE_TX_DIS (0x2 << 12) +/* if system depends on ethernet packet to restore from sleep, + * please define this macro to 1 otherwise, define it to 0. + */ +#define SYS_WAKEUP_BASED_ON_ETH_PKT 1 + +/* to enable system WOL feature of phy, please define this macro to 1 + * otherwise, define it to 0. + */ +#define YTPHY_WOL_FEATURE_ENABLE 0 + +#if (YTPHY_WOL_FEATURE_ENABLE) +#undef SYS_WAKEUP_BASED_ON_ETH_PKT +#define SYS_WAKEUP_BASED_ON_ETH_PKT 1 +#endif + +/* for YT8531 package A xtal init config */ +#define YTPHY8531A_XTAL_INIT 0 + +#define REG_PHY_SPEC_STATUS 0x11 +#define REG_DEBUG_ADDR_OFFSET 0x1e +#define REG_DEBUG_DATA 0x1f + +#define YT8521_EXTREG_SLEEP_CONTROL1 0x27 +#define YT8521_EN_SLEEP_SW_BIT 15 + +#define YT8521_SPEED_MODE 0xc000 +#define YT8521_DUPLEX 0x2000 +#define YT8521_SPEED_MODE_BIT 14 +#define YT8521_DUPLEX_BIT 13 +#define YT8521_LINK_STATUS_BIT 10 + +/* YT8521 polling mode */ +#define YT8521_PHY_MODE_FIBER 1 /* fiber mode only */ +#define YT8521_PHY_MODE_UTP 2 /* utp mode only */ +#define YT8521_PHY_MODE_POLL 3 /* fiber and utp, poll mode */ + +static int yt8521_hw_strap_polling(struct phy_device *phydev); +#define YT8521_PHY_MODE_CURR yt8521_hw_strap_polling(phydev) + static int yt8511_read_page(struct phy_device *phydev) { return __phy_read(phydev, YT8511_PAGE_SELECT); @@ -111,6 +153,444 @@ err_restore_page: return phy_restore_page(phydev, oldpage, ret); } +static u32 ytphy_read_ext(struct phy_device *phydev, u32 regnum) +{ + int ret; + + phy_lock_mdio_bus(phydev); + ret = __phy_write(phydev, REG_DEBUG_ADDR_OFFSET, regnum); + if (ret < 0) + goto err_handle; + + ret = __phy_read(phydev, REG_DEBUG_DATA); + if (ret < 0) + goto err_handle; + +err_handle: + phy_unlock_mdio_bus(phydev); + return ret; +} + +static int ytphy_write_ext(struct phy_device *phydev, u32 regnum, u16 val) +{ + int ret; + + phy_lock_mdio_bus(phydev); + ret = __phy_write(phydev, REG_DEBUG_ADDR_OFFSET, regnum); + if (ret < 0) + goto err_handle; + + ret = __phy_write(phydev, REG_DEBUG_DATA, val); + if (ret < 0) + goto err_handle; + +err_handle: + phy_unlock_mdio_bus(phydev); + return ret; +} + +static int ytphy_soft_reset(struct phy_device *phydev) +{ + int ret = 0, val = 0; + + val = phy_read(phydev, MII_BMCR); + if (val < 0) + return val; + + ret = phy_write(phydev, MII_BMCR, val | BMCR_RESET); + if (ret < 0) + return ret; + + return ret; +} + +static int yt8521_soft_reset(struct phy_device *phydev) +{ + int ret = 0, val; + + if (YT8521_PHY_MODE_CURR == YT8521_PHY_MODE_UTP) { + ytphy_write_ext(phydev, 0xa000, 0); + ret = ytphy_soft_reset(phydev); + if (ret < 0) + return ret; + } + + if (YT8521_PHY_MODE_CURR == YT8521_PHY_MODE_FIBER) { + ytphy_write_ext(phydev, 0xa000, 2); + ret = ytphy_soft_reset(phydev); + if (ret < 0) + return ret; + + ytphy_write_ext(phydev, 0xa000, 0); + } + + if (YT8521_PHY_MODE_CURR == YT8521_PHY_MODE_POLL) { + val = ytphy_read_ext(phydev, 0xa001); + ytphy_write_ext(phydev, 0xa001, (val & ~0x8000)); + + ytphy_write_ext(phydev, 0xa000, 0); + ret = ytphy_soft_reset(phydev); + if (ret < 0) + return ret; + } + + return 0; +} + +static int yt8521_hw_strap_polling(struct phy_device *phydev) +{ + int val = 0; + + val = ytphy_read_ext(phydev, 0xa001) & 0x7; + switch (val) { + case 1: + case 4: + case 5: + return YT8521_PHY_MODE_FIBER; + case 2: + case 6: + case 7: + return YT8521_PHY_MODE_POLL; + case 3: + case 0: + default: + return YT8521_PHY_MODE_UTP; + } +} + +static int yt8521_config_init(struct phy_device *phydev) +{ + int ret, hw_strap_mode; + int val; + +#if (YTPHY_WOL_FEATURE_ENABLE) + struct ethtool_wolinfo wol; + + /* set phy wol enable */ + memset(&wol, 0x0, sizeof(struct ethtool_wolinfo)); + wol.wolopts |= WAKE_MAGIC; + ytphy_wol_feature_set(phydev, &wol); +#endif + + phydev->irq = PHY_POLL; + /* NOTE: this function should not be called more than one for each chip. */ + hw_strap_mode = ytphy_read_ext(phydev, 0xa001) & 0x7; + + ytphy_write_ext(phydev, 0xa000, 0); + + /* disable auto sleep */ + val = ytphy_read_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1); + if (val < 0) + return val; + + val &= (~BIT(YT8521_EN_SLEEP_SW_BIT)); + ret = ytphy_write_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1, val); + if (ret < 0) + return ret; + + /* enable RXC clock when no wire plug */ + val = ytphy_read_ext(phydev, 0xc); + if (val < 0) + return val; + val &= ~(1 << 12); + ret = ytphy_write_ext(phydev, 0xc, val); + if (ret < 0) + return ret; + + netdev_info(phydev->attached_dev, "%s done, phy addr: %d, strap mode = %d, polling mode = %d\n", + __func__, phydev->mdio.addr, hw_strap_mode, yt8521_hw_strap_polling(phydev)); + + return ret; +} + +/* for fiber mode, there is no 10M speed mode and + * this function is for this purpose. + */ +static int yt8521_adjust_status(struct phy_device *phydev, int val, int is_utp) +{ + int speed = SPEED_UNKNOWN; + int speed_mode, duplex; + + if (is_utp) + duplex = (val & YT8521_DUPLEX) >> YT8521_DUPLEX_BIT; + else + duplex = 1; + speed_mode = (val & YT8521_SPEED_MODE) >> YT8521_SPEED_MODE_BIT; + switch (speed_mode) { + case 0: + if (is_utp) + speed = SPEED_10; + break; + case 1: + speed = SPEED_100; + break; + case 2: + speed = SPEED_1000; + break; + case 3: + break; + default: + speed = SPEED_UNKNOWN; + break; + } + + phydev->speed = speed; + phydev->duplex = duplex; + + return 0; +} + +/* for fiber mode, when speed is 100M, there is no definition for + * autonegotiation, and this function handles this case and return + * 1 per linux kernel's polling. + */ +static int yt8521_aneg_done(struct phy_device *phydev) +{ + int link_fiber = 0, link_utp = 0; + + /* reading Fiber */ + ytphy_write_ext(phydev, 0xa000, 2); + link_fiber = !!(phy_read(phydev, REG_PHY_SPEC_STATUS) & (BIT(YT8521_LINK_STATUS_BIT))); + + /* reading UTP */ + ytphy_write_ext(phydev, 0xa000, 0); + if (!link_fiber) + link_utp = !!(phy_read(phydev, REG_PHY_SPEC_STATUS) & (BIT(YT8521_LINK_STATUS_BIT))); + + netdev_info(phydev->attached_dev, "%s, phy addr: %d, link_fiber: %d, link_utp: %d\n", + __func__, phydev->mdio.addr, link_fiber, link_utp); + return !!(link_fiber | link_utp); +} + +static int yt8521_read_status(struct phy_device *phydev) +{ + int link_utp = 0, link_fiber = 0; + int yt8521_fiber_latch_val; + int yt8521_fiber_curr_val; + int link, ret; + int val; + + if (YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_FIBER) { + /* reading UTP */ + ret = ytphy_write_ext(phydev, 0xa000, 0); + if (ret < 0) + return ret; + + val = phy_read(phydev, REG_PHY_SPEC_STATUS); + if (val < 0) + return val; + + link = val & (BIT(YT8521_LINK_STATUS_BIT)); + if (link) { + link_utp = 1; + yt8521_adjust_status(phydev, val, 1); + } else { + link_utp = 0; + } + } + + if (YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_UTP) { + /* reading Fiber */ + ret = ytphy_write_ext(phydev, 0xa000, 2); + if (ret < 0) + return ret; + + val = phy_read(phydev, REG_PHY_SPEC_STATUS); + if (val < 0) + return val; + + /* note: below debug information is used to check multiple PHy ports. */ + + /* for fiber, from 1000m to 100m, there is not link down from 0x11, + * and check reg 1 to identify such case this is important for Linux + * kernel for that, missing linkdown event will cause problem. + */ + yt8521_fiber_latch_val = phy_read(phydev, MII_BMSR); + yt8521_fiber_curr_val = phy_read(phydev, MII_BMSR); + link = val & (BIT(YT8521_LINK_STATUS_BIT)); + if (link && yt8521_fiber_latch_val != yt8521_fiber_curr_val) { + link = 0; + netdev_info(phydev->attached_dev, "%s, phy addr: %d, fiber link down detect, latch = %04x, curr = %04x\n", + __func__, phydev->mdio.addr, yt8521_fiber_latch_val, + yt8521_fiber_curr_val); + } + + if (link) { + link_fiber = 1; + yt8521_adjust_status(phydev, val, 0); + } else { + link_fiber = 0; + } + } + + if (link_utp || link_fiber) { + if (phydev->link == 0) + netdev_info(phydev->attached_dev, "%s, phy addr: %d, link up, media: %s, mii reg 0x11 = 0x%x\n", + __func__, phydev->mdio.addr, + (link_utp && link_fiber) ? "UNKNOWN MEDIA" : (link_utp ? "UTP" : "Fiber"), + (unsigned int)val); + phydev->link = 1; + } else { + if (phydev->link == 1) + netdev_info(phydev->attached_dev, "%s, phy addr: %d, link down\n", + __func__, phydev->mdio.addr); + phydev->link = 0; + } + + /* utp or combo */ + if (YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_FIBER) { + if (link_fiber) + ytphy_write_ext(phydev, 0xa000, 2); + if (link_utp) + ytphy_write_ext(phydev, 0xa000, 0); + } + + return 0; +} + +static int yt8521_suspend(struct phy_device *phydev) +{ +#if !(SYS_WAKEUP_BASED_ON_ETH_PKT) + int value; + + ytphy_write_ext(phydev, 0xa000, 0); + value = phy_read(phydev, MII_BMCR); + phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); + + ytphy_write_ext(phydev, 0xa000, 2); + value = phy_read(phydev, MII_BMCR); + phy_write(phydev, MII_BMCR, value | BMCR_PDOWN); + + ytphy_write_ext(phydev, 0xa000, 0); +#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ + + return 0; +} + +static int yt8521_resume(struct phy_device *phydev) +{ + int value, ret; + + /* disable auto sleep */ + value = ytphy_read_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1); + if (value < 0) + return value; + + value &= (~BIT(YT8521_EN_SLEEP_SW_BIT)); + + ret = ytphy_write_ext(phydev, YT8521_EXTREG_SLEEP_CONTROL1, value); + if (ret < 0) + return ret; + +#if !(SYS_WAKEUP_BASED_ON_ETH_PKT) + if (YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_FIBER) { + ytphy_write_ext(phydev, 0xa000, 0); + value = phy_read(phydev, MII_BMCR); + phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN); + } + + if (YT8521_PHY_MODE_CURR != YT8521_PHY_MODE_UTP) { + ytphy_write_ext(phydev, 0xa000, 2); + value = phy_read(phydev, MII_BMCR); + phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN); + + ytphy_write_ext(phydev, 0xa000, 0); + } +#endif /*!(SYS_WAKEUP_BASED_ON_ETH_PKT)*/ + + return 0; +} + +static int yt8531_rxclk_duty_init(struct phy_device *phydev) +{ + unsigned int value = 0x9696; + int ret = 0; + + ret = ytphy_write_ext(phydev, 0xa040, 0xffff); + if (ret < 0) + return ret; + + ret = ytphy_write_ext(phydev, 0xa041, 0xff); + if (ret < 0) + return ret; + + ret = ytphy_write_ext(phydev, 0xa039, 0xbf00); + if (ret < 0) + return ret; + + /* nodelay duty = 0x9696 (default) + * fixed delay duty = 0x4040 + * step delay 0xf duty = 0x4041 + */ + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) + value = 0x4040; + + ret = ytphy_write_ext(phydev, 0xa03a, value); + if (ret < 0) + return ret; + ret = ytphy_write_ext(phydev, 0xa03b, value); + if (ret < 0) + return ret; + ret = ytphy_write_ext(phydev, 0xa03c, value); + if (ret < 0) + return ret; + ret = ytphy_write_ext(phydev, 0xa03d, value); + if (ret < 0) + return ret; + ret = ytphy_write_ext(phydev, 0xa03e, value); + if (ret < 0) + return ret; + ret = ytphy_write_ext(phydev, 0xa03f, value); + if (ret < 0) + return ret; + + return ret; +} + +static int yt8531S_config_init(struct phy_device *phydev) +{ +#if (YTPHY8531A_XTAL_INIT) + int ret = 0; + + ret = yt8531a_xtal_init(phydev); + if (ret < 0) + return ret; +#endif + + return yt8521_config_init(phydev); +} + +static int yt8531_config_init(struct phy_device *phydev) +{ + int ret = 0; + +#if (YTPHY8531A_XTAL_INIT) + ret = yt8531a_xtal_init(phydev); + if (ret < 0) + return ret; +#endif + + /* PHY_CLK_OUT 125M enabled (default) */ + ret = ytphy_write_ext(phydev, 0xa012, 0xd0); + if (ret < 0) + return ret; + + ret = yt8531_rxclk_duty_init(phydev); + if (ret < 0) + return ret; + + /* RXC, PHY_CLK_OUT and RXData Drive strength: + * Drive strength of RXC = 4, PHY_CLK_OUT = 3, RXD0 = 4 (default) + * If the io voltage is 3.3v, PHY_CLK_OUT = 2, set 0xa010 = 0x9acf + */ + ret = ytphy_write_ext(phydev, 0xa010, 0x9bcf); + if (ret < 0) + return ret; + + return ret; +} + static struct phy_driver motorcomm_phy_drvs[] = { { PHY_ID_MATCH_EXACT(PHY_ID_YT8511), @@ -120,6 +600,33 @@ static struct phy_driver motorcomm_phy_drvs[] = { .resume = genphy_resume, .read_page = yt8511_read_page, .write_page = yt8511_write_page, + }, { + /* same as 8521 */ + PHY_ID_MATCH_EXACT(PHY_ID_YT8531S), + .name = "YT8531S Gigabit Ethernet", + .features = PHY_GBIT_FEATURES, + .soft_reset = yt8521_soft_reset, + .aneg_done = yt8521_aneg_done, + .config_init = yt8531S_config_init, + .read_status = yt8521_read_status, + .suspend = yt8521_suspend, + .resume = yt8521_resume, +#if (YTPHY_WOL_FEATURE_ENABLE) + .get_wol = &ytphy_wol_feature_get, + .set_wol = &ytphy_wol_feature_set, +#endif + }, { + /* same as 8511 */ + PHY_ID_MATCH_EXACT(PHY_ID_YT8531), + .name = "YT8531 Gigabit Ethernet", + .features = PHY_GBIT_FEATURES, + .config_init = yt8531_config_init, + .suspend = genphy_suspend, + .resume = genphy_resume, +#if (YTPHY_WOL_FEATURE_ENABLE) + .get_wol = &ytphy_wol_feature_get, + .set_wol = &ytphy_wol_feature_set, +#endif }, }; @@ -131,6 +638,8 @@ MODULE_LICENSE("GPL"); static const struct mdio_device_id __maybe_unused motorcomm_tbl[] = { { PHY_ID_MATCH_EXACT(PHY_ID_YT8511) }, + { PHY_ID_MATCH_EXACT(PHY_ID_YT8531S) }, + { PHY_ID_MATCH_EXACT(PHY_ID_YT8531) }, { /* sentinal */ } }; From 54f657fcdb766453493f2da974a48511335291c1 Mon Sep 17 00:00:00 2001 From: David Wu Date: Wed, 9 Nov 2022 14:17:49 +0800 Subject: [PATCH 042/235] configs: rockchip: Enable CONFIG_MOTORCOMM_PHY for RK631 Signed-off-by: David Wu Change-Id: Id19b664d3688908f3f758bb26eab8e0b7c7d4201 --- arch/arm/configs/rockchip_defconfig | 1 + arch/arm/configs/rockchip_linux_defconfig | 1 + arch/arm64/configs/rockchip_defconfig | 1 + arch/arm64/configs/rockchip_linux_defconfig | 1 + 4 files changed, 4 insertions(+) diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index 2c6e91b4c70c..fb7398f745a9 100644 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -298,6 +298,7 @@ CONFIG_STMMAC_ETH=y # CONFIG_NET_VENDOR_SYNOPSYS is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_MOTORCOMM_PHY=y CONFIG_ROCKCHIP_PHY=y CONFIG_PPP=y CONFIG_PPP_BSDCOMP=y diff --git a/arch/arm/configs/rockchip_linux_defconfig b/arch/arm/configs/rockchip_linux_defconfig index b76d47e8528e..d6c90d75711b 100644 --- a/arch/arm/configs/rockchip_linux_defconfig +++ b/arch/arm/configs/rockchip_linux_defconfig @@ -174,6 +174,7 @@ CONFIG_TUN=y CONFIG_VETH=y CONFIG_EMAC_ROCKCHIP=y CONFIG_STMMAC_ETH=y +CONFIG_MOTORCOMM_PHY=y CONFIG_ROCKCHIP_PHY=y CONFIG_PPP=y CONFIG_PPP_ASYNC=y diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 0adcefe9e83d..41acc0b8ec81 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -361,6 +361,7 @@ CONFIG_STMMAC_ETH=y # CONFIG_NET_VENDOR_TI is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_MOTORCOMM_PHY=y CONFIG_ROCKCHIP_PHY=y CONFIG_PPP=y CONFIG_PPP_BSDCOMP=y diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index aacc4dc45e12..2c8e31b4a2ba 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -177,6 +177,7 @@ CONFIG_STMMAC_ETH=y # CONFIG_NET_VENDOR_TI is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_MOTORCOMM_PHY=y CONFIG_ROCKCHIP_PHY=y CONFIG_USB_RTL8150=y CONFIG_USB_RTL8152=y From 334791b0d3a2a25665393086b233189c0a1892b6 Mon Sep 17 00:00:00 2001 From: Lin Jianhua Date: Mon, 16 May 2022 09:36:02 +0800 Subject: [PATCH 043/235] input: touchscreen: gt1x: ignore pin of reset and support power invert Signed-off-by: Lin Jianhua Change-Id: I3f0da33eef197d78bfb72c620bfe2c25dd87d02a --- drivers/input/touchscreen/gt1x/gt1x.c | 53 ++++++++++++++----- drivers/input/touchscreen/gt1x/gt1x_generic.c | 6 ++- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/drivers/input/touchscreen/gt1x/gt1x.c b/drivers/input/touchscreen/gt1x/gt1x.c index f59b5c875803..6fe0deaab785 100644 --- a/drivers/input/touchscreen/gt1x/gt1x.c +++ b/drivers/input/touchscreen/gt1x/gt1x.c @@ -33,6 +33,7 @@ static const struct dev_pm_ops gt1x_ts_pm_ops; bool gt1x_gt5688; int gt1x_rst_gpio; int gt1x_int_gpio; +static bool power_invert; #endif static int gt1x_register_powermanger(void); @@ -277,6 +278,11 @@ static void gt1x_ts_work_func(struct work_struct *work) #else ret = gt1x_touch_event_handler(point_data, input_dev, NULL); #endif + if (ret < 0) { +#if !GTP_ESD_PROTECT + gt1x_power_reset(); +#endif + } exit_work_func: if (!gt1x_rawdiff_mode && (ret >= 0 || ret == ERROR_VALUE)) { @@ -323,9 +329,14 @@ static int gt1x_parse_dt(struct device *dev) gt1x_int_gpio = of_get_named_gpio(np, "goodix,irq-gpio", 0); gt1x_rst_gpio = of_get_named_gpio(np, "goodix,rst-gpio", 0); - if (!gpio_is_valid(gt1x_int_gpio) || !gpio_is_valid(gt1x_rst_gpio)) { - GTP_ERROR("Invalid GPIO, irq-gpio:%d, rst-gpio:%d", - gt1x_int_gpio, gt1x_rst_gpio); + if (!gpio_is_valid(gt1x_rst_gpio)) { + GTP_INFO("Invalid GPIO, rst-gpio:%d", + gt1x_rst_gpio); + } + + if (!gpio_is_valid(gt1x_int_gpio)) { + GTP_ERROR("Invalid GPIO, irq-gpio:%d", + gt1x_int_gpio); return -EINVAL; } @@ -336,6 +347,9 @@ static int gt1x_parse_dt(struct device *dev) if (PTR_ERR(vdd_ana) == -ENODEV) { GTP_ERROR("power not specified, ignore power ctrl"); vdd_ana = NULL; + } else { + power_invert = of_property_read_bool(np, "power-invert"); + GTP_INFO("Power Invert,%s ", power_invert ? "yes" : "no"); } } if (IS_ERR(vdd_ana)) { @@ -364,7 +378,7 @@ static int gt1x_parse_dt(struct device *dev) */ int gt1x_power_switch(int on) { - int ret; + int ret = 0; struct i2c_client *client = gt1x_i2c_client; if (!client || !vdd_ana) @@ -372,10 +386,22 @@ int gt1x_power_switch(int on) if (on) { GTP_DEBUG("GTP power on."); - ret = regulator_enable(vdd_ana); + if (power_invert) { + if (regulator_is_enabled(vdd_ana) > 0) + ret = regulator_disable(vdd_ana); + } else { + if (!regulator_is_enabled(vdd_ana)) + ret = regulator_enable(vdd_ana); + } } else { GTP_DEBUG("GTP power off."); - ret = regulator_disable(vdd_ana); + if (power_invert) { + if (!regulator_is_enabled(vdd_ana)) + ret = regulator_enable(vdd_ana); + } else { + if (regulator_is_enabled(vdd_ana) > 0) + ret = regulator_disable(vdd_ana); + } } return ret; } @@ -411,14 +437,17 @@ static s32 gt1x_request_io_port(void) GTP_GPIO_AS_INT(GTP_INT_PORT); gt1x_i2c_client->irq = GTP_INT_IRQ; - ret = gpio_request(GTP_RST_PORT, "GTP_RST_PORT"); - if (ret < 0) { - GTP_ERROR("Failed to request GPIO:%d, ERRNO:%d", (s32) GTP_RST_PORT, ret); - gpio_free(GTP_INT_PORT); - return ret; + if (gpio_is_valid(gt1x_rst_gpio)) { + ret = gpio_request(GTP_RST_PORT, "GTP_RST_PORT"); + if (ret < 0) { + GTP_ERROR("Failed to request GPIO:%d, ERRNO:%d", (s32) GTP_RST_PORT, ret); + gpio_free(GTP_INT_PORT); + return ret; + } + + GTP_GPIO_AS_INPUT(GTP_RST_PORT); } - GTP_GPIO_AS_INPUT(GTP_RST_PORT); return 0; } diff --git a/drivers/input/touchscreen/gt1x/gt1x_generic.c b/drivers/input/touchscreen/gt1x/gt1x_generic.c index 2531bf6e4d0a..4cb0d2e869a6 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_generic.c +++ b/drivers/input/touchscreen/gt1x/gt1x_generic.c @@ -661,10 +661,12 @@ s32 gt1x_init_panel(void) void gt1x_select_addr(void) { - GTP_GPIO_OUTPUT(GTP_RST_PORT, 0); + if (gpio_is_valid(gt1x_rst_gpio)) + GTP_GPIO_OUTPUT(GTP_RST_PORT, 0); GTP_GPIO_OUTPUT(GTP_INT_PORT, gt1x_i2c_client->addr == 0x14); usleep_range(2000, 3000); - GTP_GPIO_OUTPUT(GTP_RST_PORT, 1); + if (gpio_is_valid(gt1x_rst_gpio)) + GTP_GPIO_OUTPUT(GTP_RST_PORT, 1); usleep_range(2000, 3000); } From f91fc90bbea9d71eb1c36248a8ada27b465af051 Mon Sep 17 00:00:00 2001 From: Ziyuan Xu Date: Wed, 16 Nov 2022 18:10:20 +0800 Subject: [PATCH 044/235] media: i2c: sc3338: pm_runtime_put device until stream_off for thunderboot The camera device should keep *power on* until stream off, that make sure the mclk is enable. Signed-off-by: Ziyuan Xu Change-Id: I2db0070793d755d8d1fe2cda3f87aaa498e052d3 --- drivers/media/i2c/sc3338.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/sc3338.c b/drivers/media/i2c/sc3338.c index d3435802fd03..9af90ce0cd24 100644 --- a/drivers/media/i2c/sc3338.c +++ b/drivers/media/i2c/sc3338.c @@ -855,8 +855,10 @@ static int __sc3338_start_stream(struct sc3338 *sc3338) static int __sc3338_stop_stream(struct sc3338 *sc3338) { sc3338->has_init_exp = false; - if (sc3338->is_thunderboot) + if (sc3338->is_thunderboot) { sc3338->is_first_streamoff = true; + pm_runtime_put(&sc3338->client->dev); + } return sc3338_write_reg(sc3338->client, SC3338_REG_CTRL_MODE, SC3338_REG_VALUE_08BIT, SC3338_MODE_SW_STANDBY); } @@ -1470,7 +1472,10 @@ static int sc3338_probe(struct i2c_client *client, pm_runtime_set_active(dev); pm_runtime_enable(dev); - pm_runtime_idle(dev); + if (sc3338->is_thunderboot) + pm_runtime_get_sync(dev); + else + pm_runtime_idle(dev); return 0; From 3f98f91c6fb7d500b99e6857250152763361a2c6 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Thu, 17 Nov 2022 06:37:05 +0000 Subject: [PATCH 045/235] arm64: dts: rockchip: rk3326-evb-lp3: remove pinctrl dvp_d0d1_m0 In rk3326-evb-lp3-avb, gpio2_b6 is used for CAM_PDN0 instead of cif_data1. Change-Id: I926474f2b06cc39052997750eb1894a8b0fe04d7 Signed-off-by: Jianwei Fan --- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v10-avb.dts | 2 +- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11-avb.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 274dccd08acc..9f7901939bee 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 @@ -80,7 +80,7 @@ &rkisp1 { status = "okay"; pinctrl-names = "default"; - pinctrl-0 = <&cif_clkout_m0 &dvp_d0d1_m0 &dvp_d2d9_m0>; + pinctrl-0 = <&cif_clkout_m0 &dvp_d2d9_m0>; port { #address-cells = <1>; #size-cells = <0>; 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 0f2a35179f43..88dc225f4f01 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 @@ -340,7 +340,7 @@ &rkisp1 { status = "okay"; pinctrl-names = "default"; - pinctrl-0 = <&cif_clkout_m0 &dvp_d0d1_m0 &dvp_d2d9_m0>; + pinctrl-0 = <&cif_clkout_m0 &dvp_d2d9_m0>; port { #address-cells = <1>; #size-cells = <0>; From 4ba9bb22289589924d185f124d293a71c46eb311 Mon Sep 17 00:00:00 2001 From: Yifeng Zhao Date: Wed, 9 Nov 2022 10:57:52 +0800 Subject: [PATCH 046/235] drivers: rk_nand: fix compile warning warning: drivers/rk_nand/rk_ftlv5_arm32.o uses 4-byte wchar_t yet the output is to use 2-byte wchar_t; Signed-off-by: Yifeng Zhao Change-Id: I9ea1cdb05be5e4edb297517a9ae8c5e5377538be --- drivers/rk_nand/rk_ftl_arm_v7.S | 1 - drivers/rk_nand/rk_ftl_arm_v7_thumb.S | 1 - drivers/rk_nand/rk_ftlv5_arm32.S | 1 - drivers/rk_nand/rk_zftl_arm32.S | 1 - 4 files changed, 4 deletions(-) diff --git a/drivers/rk_nand/rk_ftl_arm_v7.S b/drivers/rk_nand/rk_ftl_arm_v7.S index db549c3b269e..da6f8a9667e3 100644 --- a/drivers/rk_nand/rk_ftl_arm_v7.S +++ b/drivers/rk_nand/rk_ftl_arm_v7.S @@ -16,7 +16,6 @@ .eabi_attribute 26, 2 .eabi_attribute 30, 4 .eabi_attribute 34, 1 - .eabi_attribute 18, 4 .file "rk_ftl_arm_v7.c" .syntax unified .text diff --git a/drivers/rk_nand/rk_ftl_arm_v7_thumb.S b/drivers/rk_nand/rk_ftl_arm_v7_thumb.S index a67898acb677..4cf752e4b834 100644 --- a/drivers/rk_nand/rk_ftl_arm_v7_thumb.S +++ b/drivers/rk_nand/rk_ftl_arm_v7_thumb.S @@ -17,7 +17,6 @@ .eabi_attribute 26, 2 .eabi_attribute 30, 4 .eabi_attribute 34, 1 - .eabi_attribute 18, 4 .file "rk_ftl_arm_v7.c" .thumb .text diff --git a/drivers/rk_nand/rk_ftlv5_arm32.S b/drivers/rk_nand/rk_ftlv5_arm32.S index 26e2a694fb6d..28d165342153 100644 --- a/drivers/rk_nand/rk_ftlv5_arm32.S +++ b/drivers/rk_nand/rk_ftlv5_arm32.S @@ -17,7 +17,6 @@ .eabi_attribute 26, 2 .eabi_attribute 30, 4 .eabi_attribute 34, 1 - .eabi_attribute 18, 4 .file "rk_ftlv5_arm_v8.c" .text .align 2 diff --git a/drivers/rk_nand/rk_zftl_arm32.S b/drivers/rk_nand/rk_zftl_arm32.S index ec6959a4c9c9..4af2ab302d33 100644 --- a/drivers/rk_nand/rk_zftl_arm32.S +++ b/drivers/rk_nand/rk_zftl_arm32.S @@ -18,7 +18,6 @@ .eabi_attribute 26, 2 .eabi_attribute 30, 4 .eabi_attribute 34, 1 - .eabi_attribute 18, 4 .file "rk_zftl_arm_v7.c" .syntax unified .text From 1f38917aebeea4cfab6954a8d77fd98d254a5558 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 17 Nov 2022 15:12:17 +0800 Subject: [PATCH 047/235] ARM: dts: rockchip: rk3288: fix base address for i2s to 0xff8b0000 This patch fixes the error base address for the i2s controller from 0xff88b0000 to 0xff8b0000. Also order the i2s node by mapping address. Signed-off-by: Jianqun Xu Change-Id: I613eaf64ee010c41208f1c8169e55efbf39fd34c --- arch/arm/boot/dts/rk3288.dtsi | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 3aa3d3b8611d..966b4d968749 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1034,21 +1034,6 @@ status = "disabled"; }; - spdif: sound@ff88b0000 { - compatible = "rockchip,rk3288-spdif", "rockchip,rk3066-spdif"; - reg = <0x0 0xff8b0000 0x0 0x10000>; - #sound-dai-cells = <0>; - clocks = <&cru SCLK_SPDIF8CH>, <&cru HCLK_SPDIF8CH>; - clock-names = "mclk", "hclk"; - dmas = <&dmac_bus_s 3>; - dma-names = "tx"; - interrupts = ; - pinctrl-names = "default"; - pinctrl-0 = <&spdif_tx>; - rockchip,grf = <&grf>; - status = "disabled"; - }; - i2s: i2s@ff890000 { compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s"; reg = <0x0 0xff890000 0x0 0x10000>; @@ -1079,6 +1064,21 @@ status = "okay"; }; + spdif: sound@ff8b0000 { + compatible = "rockchip,rk3288-spdif", "rockchip,rk3066-spdif"; + reg = <0x0 0xff8b0000 0x0 0x10000>; + #sound-dai-cells = <0>; + clocks = <&cru SCLK_SPDIF8CH>, <&cru HCLK_SPDIF8CH>; + clock-names = "mclk", "hclk"; + dmas = <&dmac_bus_s 3>; + dma-names = "tx"; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&spdif_tx>; + rockchip,grf = <&grf>; + status = "disabled"; + }; + iep_mmu: iommu@ff900800 { compatible = "rockchip,iommu"; reg = <0x0 0xff900800 0x0 0x40>; From f1d80296b4c9b9a19213a09845e1f46d8c2255c4 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 17 Nov 2022 11:00:09 +0800 Subject: [PATCH 048/235] ARM: dts: rockchip: rk3288-evb-rk808-linux fix to hdmi_cec_c0 DTC arch/arm/boot/dts/rk3288-evb-rk808-linux.dtb arch/arm/boot/dts/rk3288.dtsi:1433.22-1463.4: ERROR (phandle_references): /hdmi@ff980000: Reference to non-existent node or label "hdmi_cec" Signed-off-by: Jianqun Xu Change-Id: I976f1ea4d9ee796ce1c179f5dfead625c257f8af --- arch/arm/boot/dts/rk3288-evb-rk808-linux.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts b/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts index 7d06817d3d8b..f630496fcfdc 100644 --- a/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts +++ b/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts @@ -172,7 +172,7 @@ }; &hdmi { - pinctrl-0 = <&hdmi_ddc>, <&hdmi_cec>; + pinctrl-0 = <&hdmi_ddc>, <&hdmi_cec_c0>; }; &i2c0 { From 9903fc2377f80534fbf80296902f4def2a1e2fa6 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 17 Nov 2022 11:01:34 +0800 Subject: [PATCH 049/235] ARM: dts: rockchip: rk3288-evb-rk808-linux add wifi_enable_h pinctrl DTC arch/arm/boot/dts/rk3288-evb-rk808-linux.dtb arch/arm/boot/dts/rk3288-evb-rk808-linux.dts:87.27-101.4: ERROR (phandle_references): /sdio-pwrseq: Reference to non-existent node or label "wifi_enable_h" Signed-off-by: Jianqun Xu Change-Id: I14eb634ed8823e4caef581b8974a5dded63f5d8e --- arch/arm/boot/dts/rk3288-evb.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index 4fc7d681a044..ae934d669784 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -354,6 +354,12 @@ }; }; + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + sdmmc { /* * Default drive strength isn't enough to achieve even From a4a177f7367d9d5eb734c2c28119dfda0ef63728 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Mon, 14 Nov 2022 15:48:51 +0800 Subject: [PATCH 050/235] ARM: dts: rockchip: rk3288-evb enable sound with rt5640 Change-Id: Ibe3f218f9b3283c82329500486fd73298fc3b0d6 Signed-off-by: Jacob Chen Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288-evb-rk808-linux.dts | 4 -- arch/arm/boot/dts/rk3288-evb.dtsi | 58 ++++++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts b/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts index f630496fcfdc..9d19736b1170 100644 --- a/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts +++ b/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts @@ -498,10 +498,6 @@ status = "okay"; }; -&sound { - status = "okay"; -}; - &uart2 { status = "disabled"; }; diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index ae934d669784..03d9c5f0533c 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -47,6 +47,45 @@ }; }; + sound: sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "rockchip,rt5640-codec"; + simple-audio-card,mclk-fs = <512>; + status = "okay"; + + simple-audio-card,dai-link@0 { + format = "i2s"; + cpu { + sound-dai = <&i2s>; + }; + + codec { + sound-dai = <&rt5640>; + }; + }; + + simple-audio-card,dai-link@1 { + format = "i2s"; + cpu { + sound-dai = <&i2s>; + }; + + codec { + sound-dai = <&hdmi>; + }; + }; + }; + + hdmi_analog_sound: hdmi-analog-sound { + compatible = "rockchip,rk3288-hdmi-analog", + "rockchip,rk3368-hdmi-analog"; + rockchip,model = "rockchip,rt5640-codec"; + rockchip,cpu = <&i2s>; + rockchip,codec = <&rt5640>, <&hdmi>; + status = "disabled"; + }; + backlight: backlight { compatible = "pwm-backlight"; brightness-levels = < @@ -286,6 +325,25 @@ status = "okay"; }; +&i2c2 { + status = "okay"; + + rt5640: rt5640@1c { + #sound-dai-cells = <0>; + compatible = "realtek,rt5640"; + reg = <0x1c>; + clocks = <&cru SCLK_I2S0_OUT>; + clock-names = "mclk"; + interrupt-parent = <&gpio7>; + interrupts = <7 IRQ_TYPE_EDGE_FALLING>; + }; +}; + +&i2s { + #sound-dai-cells = <0>; + status = "okay"; +}; + &wdt { status = "okay"; }; From d906b2183262275b11b69161365ccefa5f7ec4ea Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 17 Nov 2022 11:27:45 +0800 Subject: [PATCH 051/235] ARM: dts: rockchip: rk3288: Add SCLK_HDMI_CEC to PD_VIO Change-Id: I6de8283516f01093213ea16f0792bcd10fb1af2b Signed-off-by: Nickey Yang Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 966b4d968749..4f8bc1096e41 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -820,6 +820,7 @@ <&cru PCLK_MIPI_DSI1>, <&cru SCLK_EDP_24M>, <&cru SCLK_EDP>, + <&cru SCLK_HDMI_CEC>, <&cru SCLK_ISP_JPE>, <&cru SCLK_ISP>, <&cru SCLK_RGA>; From e7be6c1a2950c7f8bc254404ec1e5abe55c710f0 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 17 Nov 2022 11:29:45 +0800 Subject: [PATCH 052/235] ARM: dts: rockchip: rk3288: add rockchip-suspend node Change-Id: Id5700548a6034248ed5ad3226dd652d0833eec13 Signed-off-by: shengfei Xu Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 4f8bc1096e41..c87df57c7dd3 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include / { #address-cells = <2>; @@ -1654,6 +1655,30 @@ compatible = "rockchip,system-monitor"; }; + rockchip_suspend: rockchip-suspend { + compatible = "rockchip,pm-rk3288"; + status = "disabled"; + rockchip,sleep-mode-config = < + (0 + |RKPM_CTR_PWR_DMNS + |RKPM_CTR_GTCLKS + |RKPM_CTR_PLLS + |RKPM_CTR_ARMOFF_LPMD + |RKPM_CTR_SYSCLK_OSC_DIS + ) + >; + rockchip,wakeup-config = < + (0 + | RKPM_GPIO_WKUP_EN + ) + >; + rockchip,pwm-regulator-config = < + (0 + | PWM2_REGULATOR_EN + ) + >; + }; + pinctrl: pinctrl { compatible = "rockchip,rk3288-pinctrl"; rockchip,grf = <&grf>; From e5611037e83d086cbcf4ef6e8333a187effed3ff Mon Sep 17 00:00:00 2001 From: Elon Zhang Date: Mon, 6 Jul 2020 15:36:35 +0800 Subject: [PATCH 053/235] ARM: dts: rockchip: rk3288: Add firmware and optee node Add optee node to supply OP-TEE required properties. /optee node is supposed to be below /firmware node. Signed-off-by: Elon Zhang Signed-off-by: Jianqun Xu Change-Id: I067f12319a2ec3252655669b199ced6ab451cbd9 --- arch/arm/boot/dts/rk3288.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index c87df57c7dd3..cd099e8f07da 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -208,6 +208,13 @@ }; }; + firmware { + optee: optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + }; + reserved-memory { #address-cells = <2>; #size-cells = <2>; From 0fce242c0177650a84f61f3c7b68a33a4cce2384 Mon Sep 17 00:00:00 2001 From: William Wu Date: Tue, 1 Aug 2017 14:25:12 +0800 Subject: [PATCH 054/235] ARM: dts: rockchip: rk3288: Fix reg size for ehci According to rk3288 TRM, the size of usb ehci is 128K, so let's fix it in dts. Change-Id: I1adf02080033906a88b34cae877bb84ad0f63059 Signed-off-by: William Wu --- arch/arm/boot/dts/rk3288.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index cd099e8f07da..73f38b2f97a6 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -637,7 +637,7 @@ usb_host0_ehci: usb@ff500000 { compatible = "generic-ehci"; - reg = <0x0 0xff500000 0x0 0x100>; + reg = <0x0 0xff500000 0x0 0x20000>; interrupts = ; clocks = <&cru HCLK_USBHOST0>; phys = <&usbphy1>; From 0b16181d0a68f1acd8192e6dc02f99fd0a6b8970 Mon Sep 17 00:00:00 2001 From: xcq Date: Mon, 17 Apr 2017 16:32:43 +0800 Subject: [PATCH 055/235] ARM: dts: rockchip: rk3288: Add isp config Change-Id: I00883343c8addff1adc71bef5001d3064b829d97 Signed-off-by: xcq Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 118 ++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 73f38b2f97a6..d683ad0dd733 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1099,6 +1099,46 @@ status = "disabled"; }; + isp: isp@ff910000 { + compatible = "rockchip,rk3288-isp", "rockchip,isp"; + reg = <0x0 0xff910000 0x0 0x4000>; + interrupts = ; + power-domains = <&power RK3288_PD_VIO>; + clocks = + <&cru ACLK_ISP>, <&cru HCLK_ISP>, <&cru SCLK_ISP>, + <&cru SCLK_ISP_JPE>, <&cru PCLK_ISP_IN>, + <&cru SCLK_VIP_OUT>, <&cru SCLK_MIPIDSI_24M>, + <&cru SCLK_VIP_OUT>, <&cru PCLK_MIPI_CSI>; + clock-names = + "aclk_isp", "hclk_isp", "clk_isp", + "clk_isp_jpe", "pclkin_isp", "clk_cif_out", + "clk_mipi_24m", "clk_cif_pll", "hclk_mipiphy1"; + pinctrl-names = + "default", "isp_dvp8bit2", "isp_dvp10bit", + "isp_dvp12bit", "isp_dvp8bit0", "isp_mipi_fl", + "isp_mipi_fl_prefl", "isp_flash_as_gpio", + "isp_flash_as_trigger_out"; + pinctrl-0 = <&isp_mipi>; + pinctrl-1 = <&isp_mipi &isp_dvp_d2d9>; + pinctrl-2 = <&isp_mipi &isp_dvp_d2d9 &isp_dvp_d0d1>; + pinctrl-3 = <&isp_mipi &isp_dvp_d2d9 &isp_dvp_d0d1 + &isp_dvp_d10d11>; + pinctrl-4 = <&isp_mipi &isp_dvp_d0d7>; + pinctrl-5 = <&isp_mipi>; + pinctrl-6 = <&isp_mipi &isp_prelight>; + pinctrl-7 = <&isp_flash_trigger_as_gpio>; + pinctrl-8 = <&isp_flash_trigger>; + rockchip,isp,mipiphy = <2>; + rockchip,isp,cifphy = <1>; + rockchip,isp,mipiphy1,reg = <0xff968000 0x4000>; + rockchip,grf = <&grf>; + rockchip,cru = <&cru>; + rockchip,gpios = <&gpio7 13 GPIO_ACTIVE_HIGH>; + rockchip,isp,iommu_enable = <1>; + iommus = <&isp_mmu>; + status = "disabled"; + }; + isp_mmu: iommu@ff914000 { compatible = "rockchip,iommu"; reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>; @@ -2300,5 +2340,83 @@ rockchip,pins = <6 RK_PB3 1 &pcfg_pull_none>; }; }; + + isp_pin { + isp_mipi: isp-mipi { + rockchip,pins = + /* cif_clkout */ + <2 RK_PB3 1 &pcfg_pull_none>; + }; + + isp_dvp_d2d9: isp-d2d9 { + rockchip,pins = + /* cif_data2 ... cif_data9 */ + <2 RK_PA0 1 &pcfg_pull_none>, + <2 RK_PA1 1 &pcfg_pull_none>, + <2 RK_PA2 1 &pcfg_pull_none>, + <2 RK_PA3 1 &pcfg_pull_none>, + <2 RK_PA4 1 &pcfg_pull_none>, + <2 RK_PA5 1 &pcfg_pull_none>, + <2 RK_PA6 1 &pcfg_pull_none>, + <2 RK_PA7 1 &pcfg_pull_none>, + /* cif_sync, cif_href */ + <2 RK_PB0 1 &pcfg_pull_none>, + <2 RK_PB1 1 &pcfg_pull_none>, + /* cif_clkin */ + <2 RK_PB2 1 &pcfg_pull_none>; + }; + + isp_dvp_d0d1: isp-d0d1 { + rockchip,pins = + /* cif_data0, cif_data1 */ + <2 RK_PB4 1 &pcfg_pull_none>, + <2 RK_PB5 1 &pcfg_pull_none>; + }; + + isp_dvp_d10d11: isp-d10d11 { + rockchip,pins = + /* cif_data10, cif_data11 */ + <2 RK_PB6 1 &pcfg_pull_none>, + <2 RK_PB7 1 &pcfg_pull_none>; + }; + + isp_dvp_d0d7: isp-d0d7 { + rockchip,pins = + /* cif_data0 ... cif_data7 */ + <2 RK_PB4 1 &pcfg_pull_none>, + <2 RK_PB5 1 &pcfg_pull_none>, + <2 RK_PA0 1 &pcfg_pull_none>, + <2 RK_PA1 1 &pcfg_pull_none>, + <2 RK_PA2 1 &pcfg_pull_none>, + <2 RK_PA3 1 &pcfg_pull_none>, + <2 RK_PA4 1 &pcfg_pull_none>, + <2 RK_PA5 1 &pcfg_pull_none>; + }; + + isp_shutter: isp-shutter { + rockchip,pins = + /* SHUTTEREN, SHUTTERTRIG */ + <7 RK_PB4 2 &pcfg_pull_none>, + <7 RK_PB7 2 &pcfg_pull_none>; + }; + + isp_flash_trigger: isp-flash-trigger { + rockchip,pins = + /* ISP_FLASHTRIGOU */ + <7 RK_PB5 2 &pcfg_pull_none>; + }; + + isp_prelight: isp-prelight { + rockchip,pins = + /* ISP_PRELIGHTTRIG */ + <7 RK_PB6 2 &pcfg_pull_none>; + }; + + isp_flash_trigger_as_gpio: isp-flash-trigger-as-gpio { + rockchip,pins = + /* ISP_FLASHTRIGOU */ + <7 RK_PB5 2 &pcfg_pull_none>; + }; + }; }; }; From 853742ebfe01a31ac179fb47a724e014b5ecbb14 Mon Sep 17 00:00:00 2001 From: Allon Huang Date: Thu, 17 Nov 2022 11:48:07 +0800 Subject: [PATCH 056/235] ARM: dts: rockchip: rk3288: Add csi_host and cif_pin Change-Id: I43f289d3de897ef16098639a57b140c9554de3cd Signed-off-by: Allon Huang --- arch/arm/boot/dts/rk3288.dtsi | 63 +++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index d683ad0dd733..0b0f51891fb1 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1139,6 +1139,24 @@ status = "disabled"; }; + rkisp1: rkisp1@ff910000 { + compatible = "rockchip,rk3288-rkisp1"; + reg = <0x0 0xff910000 0x0 0x4000>; + interrupts = ; + interrupt-names = "isp_irq"; + clocks = <&cru SCLK_ISP>, <&cru ACLK_ISP>, + <&cru HCLK_ISP>, <&cru PCLK_ISP_IN>, + <&cru SCLK_ISP_JPE>; + clock-names = "clk_isp", "aclk_isp", + "hclk_isp", "pclk_isp_in", + "sclk_isp_jpe"; + assigned-clocks = <&cru SCLK_ISP>, <&cru SCLK_ISP_JPE>; + assigned-clock-rates = <400000000>, <400000000>; + power-domains = <&power RK3288_PD_VIO>; + iommus = <&isp_mmu>; + status = "disabled"; + }; + isp_mmu: iommu@ff914000 { compatible = "rockchip,iommu"; reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>; @@ -1286,6 +1304,24 @@ status = "disabled"; }; + cif: cif@ff950000 { + compatible = "rockchip,cif", "rockchip,rk3288-cif"; + reg = <0x0 0xff950000 0x0 0x400>; + interrupts = ; + clocks = <&cru ACLK_VIP>, <&cru HCLK_VIP>, + <&cru PCLK_VIP_IN>, <&cru SCLK_VIP_OUT>; + clock-names = "aclk_cif0", "hclk_cif0", + "cif0_in", "cif0_out"; + resets = <&cru SRST_VIP>; + reset-names = "rst_cif"; + pinctrl-names = "cif_pin_all"; + pinctrl-0 = <&isp_mipi &isp_dvp_d2d9 &isp_dvp_d10d11>; + rockchip,grf = <&grf>; + rockchip,cru = <&cru>; + power-domains = <&power RK3288_PD_VIO>; + status = "disabled"; + }; + dsi0: dsi@ff960000 { compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi"; reg = <0x0 0xff960000 0x0 0x4000>; @@ -2418,5 +2454,32 @@ <7 RK_PB5 2 &pcfg_pull_none>; }; }; + + cif_pin { + cif_dvp_d0d1: cif-dvp-d0d1 { + rockchip,pins = <2 RK_PB4 1 &pcfg_pull_none>, /* cif_data0 */ + <2 RK_PB5 1 &pcfg_pull_none>; /* cif_data1 */ + }; + + cif_dvp_d2d9: cif-dvp-d2d9 { + rockchip,pins = <2 RK_PA0 1 &pcfg_pull_none>, /* cif_data2 */ + <2 RK_PA1 1 &pcfg_pull_none>, /* cif_data3 */ + <2 RK_PA2 1 &pcfg_pull_none>, /* cif_data4 */ + <2 RK_PA3 1 &pcfg_pull_none>, /* cif_data5 */ + <2 RK_PA4 1 &pcfg_pull_none>, /* cif_data6 */ + <2 RK_PA5 1 &pcfg_pull_none>, /* cif_data7 */ + <2 RK_PA6 1 &pcfg_pull_none>, /* cif_data8 */ + <2 RK_PA7 1 &pcfg_pull_none>, /* cif_data9 */ + <2 RK_PB0 1 &pcfg_pull_none>, /* cif_sync */ + <2 RK_PB1 1 &pcfg_pull_none>, /* cif_href */ + <2 RK_PB2 1 &pcfg_pull_none>, /* cif_clkin */ + <2 RK_PB3 1 &pcfg_pull_none>; /* cif_clkout */ + }; + + cif_dvp_d10d11: cif-dvp-d10d11 { + rockchip,pins = <2 RK_PB6 1 &pcfg_pull_none>, /* cif_data10 */ + <2 RK_PB7 1 &pcfg_pull_none>; /* cif_data11 */ + }; + }; }; }; From dff006bcf026cb8fa905a0870dcd506faca49dfa Mon Sep 17 00:00:00 2001 From: Jason Song Date: Wed, 14 Mar 2018 09:04:22 +0800 Subject: [PATCH 057/235] ARM: dts: rockchip: rk3288: fix uart pinctrl to pullup Change-Id: Ia1d5af0a3fadf9f8649df664aef2e6f3d862d778 Signed-off-by: Jason Song Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 0b0f51891fb1..06699f23050b 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -2222,7 +2222,7 @@ uart0 { uart0_xfer: uart0-xfer { rockchip,pins = <4 RK_PC0 1 &pcfg_pull_up>, - <4 RK_PC1 1 &pcfg_pull_none>; + <4 RK_PC1 1 &pcfg_pull_up>; }; uart0_cts: uart0-cts { @@ -2237,7 +2237,7 @@ uart1 { uart1_xfer: uart1-xfer { rockchip,pins = <5 RK_PB0 1 &pcfg_pull_up>, - <5 RK_PB1 1 &pcfg_pull_none>; + <5 RK_PB1 1 &pcfg_pull_up>; }; uart1_cts: uart1-cts { @@ -2252,7 +2252,7 @@ uart2 { uart2_xfer: uart2-xfer { rockchip,pins = <7 RK_PC6 1 &pcfg_pull_up>, - <7 RK_PC7 1 &pcfg_pull_none>; + <7 RK_PC7 1 &pcfg_pull_up>; }; /* no rts / cts for uart2 */ }; @@ -2260,7 +2260,7 @@ uart3 { uart3_xfer: uart3-xfer { rockchip,pins = <7 RK_PA7 1 &pcfg_pull_up>, - <7 RK_PB0 1 &pcfg_pull_none>; + <7 RK_PB0 1 &pcfg_pull_up>; }; uart3_cts: uart3-cts { @@ -2275,7 +2275,7 @@ uart4 { uart4_xfer: uart4-xfer { rockchip,pins = <5 RK_PB7 3 &pcfg_pull_up>, - <5 RK_PB6 3 &pcfg_pull_none>; + <5 RK_PB6 3 &pcfg_pull_up>; }; uart4_cts: uart4-cts { From 9ee437dc1defa095858e675f559169a60cd0e6cd Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 28 Aug 2018 10:40:25 +0800 Subject: [PATCH 058/235] ARM: dts: rockchip: rk3288: Change 400MHz to 420Mhz for gpu It doesn't support 400MHz, but support 420MHz. Change-Id: Ife31469307912f83919b02b532acde91cc0f19ce Signed-off-by: Finley Xiao Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 06699f23050b..cf89919cc49a 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1625,8 +1625,8 @@ opp-hz = /bits/ 64 <300000000>; opp-microvolt = <1000000>; }; - opp-400000000 { - opp-hz = /bits/ 64 <400000000>; + opp-420000000 { + opp-hz = /bits/ 64 <420000000>; opp-microvolt = <1100000>; }; opp-600000000 { From a6202ba721d9a57d4ecc68a3f2683dbce7838046 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Wed, 28 Jun 2017 10:09:20 +0800 Subject: [PATCH 059/235] ARM: dts: rockchip: rk3288: fix to timer0 for broadcast timer Change-Id: I0dd9a367c2587391b17ab9bb3a4610abdee14816 Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index cf89919cc49a..2228ab394161 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -253,14 +253,6 @@ arm,no-tick-in-suspend; }; - timer: timer@ff810000 { - compatible = "rockchip,rk3288-timer"; - reg = <0x0 0xff810000 0x0 0x20>; - interrupts = ; - clocks = <&cru PCLK_TIMER>, <&xin24m>; - clock-names = "pclk", "timer"; - }; - display-subsystem { compatible = "rockchip,display-subsystem"; ports = <&vopl_out>, <&vopb_out>; @@ -751,6 +743,14 @@ status = "disabled"; }; + timer: timer@ff6b0000 { + compatible = "rockchip,rk3288-timer"; + reg = <0x0 0xff6b0000 0x0 0x20>; + interrupts = ; + clocks = <&cru PCLK_TIMER>, <&xin24m>; + clock-names = "pclk", "timer"; + }; + bus_intmem: sram@ff700000 { compatible = "mmio-sram"; reg = <0x0 0xff700000 0x0 0x18000>; From 5c12a1263cc925d07b92f4164e0059c5b1744ef7 Mon Sep 17 00:00:00 2001 From: XiaoTan Luo Date: Thu, 28 May 2020 10:01:08 +0800 Subject: [PATCH 060/235] ARM: dts: rockchip: rk3288: add spdif_2ch node Signed-off-by: XiaoTan Luo Change-Id: Id0abf6748053cbf0666f20c28fd68bbf9c3f2086 Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 2228ab394161..e89b772b195b 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1043,6 +1043,21 @@ status = "disabled"; }; + spdif_2ch: sound@ff880000 { + compatible = "rockchip,rk3288-spdif", "rockchip,rk3066-spdif"; + reg = <0x0 0xff880000 0x0 0x10000>; + #sound-dai-cells = <0>; + clocks = <&cru SCLK_SPDIF>, <&cru HCLK_SPDIF>; + clock-names = "mclk", "hclk"; + dmas = <&dmac_bus_s 2>; + dma-names = "tx"; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&spdif_tx>; + rockchip,grf = <&grf>; + status = "disabled"; + }; + i2s: i2s@ff890000 { compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s"; reg = <0x0 0xff890000 0x0 0x10000>; From 212d2666256b31c116281753e0f82df626412477 Mon Sep 17 00:00:00 2001 From: Rocky Hao Date: Thu, 30 Mar 2017 11:46:15 +0800 Subject: [PATCH 061/235] ARM: dts: rockchip: rk3288: Assign tsadc clock to 5 KHz Add tsadc's working clock rate for rk3288. if not set, tsadc will work at the default rate of 1k hz. Change-Id: I1b26351c3fb97f5ceb4657c2356c2f5649ad140c Signed-off-by: Rocky Hao Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index e89b772b195b..3102401995e6 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -596,6 +596,8 @@ interrupts = ; clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; clock-names = "tsadc", "apb_pclk"; + assigned-clocks = <&cru SCLK_TSADC>; + assigned-clock-rates = <5000>; resets = <&cru SRST_TSADC>; reset-names = "tsadc-apb"; pinctrl-names = "gpio", "otpout"; From 3ad628c268718a76e785601704071e29ed08de57 Mon Sep 17 00:00:00 2001 From: "buluess.li" Date: Tue, 27 Jun 2017 11:38:48 +0800 Subject: [PATCH 062/235] ARM: dts: rockchip: rk3288: add iep node Change-Id: Ie7fe0bbc91a5fedb0617d9b6c6056bdb4aed610d Signed-off-by: buluess.li Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 3102401995e6..3d60c7c4f5b0 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1105,6 +1105,20 @@ status = "disabled"; }; + iep: iep@ff90000 { + compatible = "rockchip,iep"; + iommu_enabled = <1>; + iommus = <&iep_mmu>; + reg = <0x0 0xff900000 0x0 0x800>; + interrupts = ; + clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>; + clock-names = "aclk_iep", "hclk_iep"; + power-domains = <&power RK3288_PD_VIO>; + allocator = <1>; + version = <1>; + status = "disabled"; + }; + iep_mmu: iommu@ff900800 { compatible = "rockchip,iommu"; reg = <0x0 0xff900800 0x0 0x40>; From 043ddfca3f2e74011531db3fa45c8784c0b434bd Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 17 Nov 2022 11:03:36 +0800 Subject: [PATCH 063/235] ARM: dts: rockchip: rk3288: add operating-points-v2 for cpu nodes Merge the pvtm patch to this patch. Change-Id: I3cb938fbfaf0ae5957d4832f4ad5671ab9631409 Signed-off-by: Finley Xiao Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 155 ++++++++++++++++++++++++++++++---- 1 file changed, 140 insertions(+), 15 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 3d60c7c4f5b0..6f41ed32328d 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -114,53 +114,136 @@ compatible = "operating-points-v2"; opp-shared; + clocks = <&cru PLL_APLL>; + rockchip,avs-scale = <17>; + rockchip,max-volt = <1350000>; + nvmem-cells = <&cpu_leakage>, <&special_function>, + <&performance>, <&process_version>, + <&performance_w>, <&package_info>; + nvmem-cell-names = "leakage", "special", + "performance", "process", + "performance-w", "package"; + rockchip,bin-scaling-sel = < + 0 17 + 1 25 + 2 27 + 3 31 + >; + rockchip,pvtm-voltage-sel = < + 0 15300 0 + 15301 16000 1 + 16001 17000 2 + 17001 99999 3 + >; + rockchip,pvtm-freq = <408000>; + rockchip,pvtm-volt = <1000000>; + rockchip,pvtm-ch = <0 0>; + rockchip,pvtm-sample-time = <1000>; + rockchip,pvtm-number = <10>; + rockchip,pvtm-error = <1000>; + rockchip,pvtm-ref-temp = <35>; + rockchip,pvtm-temp-prop = <(-18) (-18)>; + rockchip,thermal-zone = "soc-thermal"; + opp-126000000 { opp-hz = /bits/ 64 <126000000>; - opp-microvolt = <900000>; + opp-microvolt = <950000 950000 1350000>; + opp-microvolt-L0 = <950000 950000 1350000>; + opp-microvolt-L1 = <950000 950000 1350000>; + opp-microvolt-L2 = <950000 950000 1350000>; + opp-microvolt-L3 = <950000 950000 1350000>; + clock-latency-ns = <40000>; }; opp-216000000 { opp-hz = /bits/ 64 <216000000>; - opp-microvolt = <900000>; - }; - opp-312000000 { - opp-hz = /bits/ 64 <312000000>; - opp-microvolt = <900000>; + opp-microvolt = <950000 950000 1350000>; + opp-microvolt-L0 = <950000 950000 1350000>; + opp-microvolt-L1 = <950000 950000 1350000>; + opp-microvolt-L2 = <950000 950000 1350000>; + opp-microvolt-L3 = <950000 950000 1350000>; + clock-latency-ns = <40000>; }; opp-408000000 { opp-hz = /bits/ 64 <408000000>; - opp-microvolt = <900000>; + opp-microvolt = <975000 975000 1350000>; + opp-microvolt-L0 = <975000 975000 1350000>; + opp-microvolt-L1 = <950000 950000 1350000>; + opp-microvolt-L2 = <950000 950000 1350000>; + opp-microvolt-L3 = <950000 950000 1350000>; + clock-latency-ns = <40000>; }; opp-600000000 { opp-hz = /bits/ 64 <600000000>; - opp-microvolt = <900000>; + opp-microvolt = <975000 975000 1350000>; + opp-microvolt-L0 = <975000 975000 1350000>; + opp-microvolt-L1 = <950000 950000 1350000>; + opp-microvolt-L2 = <950000 950000 1350000>; + opp-microvolt-L3 = <950000 950000 1350000>; + clock-latency-ns = <40000>; }; opp-696000000 { opp-hz = /bits/ 64 <696000000>; - opp-microvolt = <950000>; + opp-microvolt = <975000 975000 1350000>; + opp-microvolt-L0 = <975000 975000 1350000>; + opp-microvolt-L1 = <950000 950000 1350000>; + opp-microvolt-L2 = <950000 950000 1350000>; + opp-microvolt-L3 = <950000 950000 1350000>; + clock-latency-ns = <40000>; }; opp-816000000 { opp-hz = /bits/ 64 <816000000>; - opp-microvolt = <1000000>; + opp-microvolt = <1075000 1075000 1350000>; + opp-microvolt-L0 = <1075000 1075000 1350000>; + opp-microvolt-L1 = <1050000 1050000 1350000>; + opp-microvolt-L2 = <1000000 1000000 1350000>; + opp-microvolt-L3 = <950000 950000 1350000>; + clock-latency-ns = <40000>; + opp-suspend; }; opp-1008000000 { opp-hz = /bits/ 64 <1008000000>; - opp-microvolt = <1050000>; + opp-microvolt = <1150000 1150000 1350000>; + opp-microvolt-L0 = <1150000 1150000 1350000>; + opp-microvolt-L1 = <1100000 1100000 1350000>; + opp-microvolt-L2 = <1050000 1050000 1350000>; + opp-microvolt-L3 = <1000000 1000000 1350000>; + clock-latency-ns = <40000>; }; opp-1200000000 { opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <1100000>; + opp-microvolt = <1200000 1200000 1350000>; + opp-microvolt-L0 = <1200000 1200000 1350000>; + opp-microvolt-L1 = <1150000 1150000 1350000>; + opp-microvolt-L2 = <1100000 1100000 1350000>; + opp-microvolt-L3 = <1050000 1050000 1350000>; + clock-latency-ns = <40000>; }; opp-1416000000 { opp-hz = /bits/ 64 <1416000000>; - opp-microvolt = <1200000>; + opp-microvolt = <1300000 1300000 1350000>; + opp-microvolt-L0 = <1300000 1300000 1350000>; + opp-microvolt-L1 = <1250000 1250000 1350000>; + opp-microvolt-L2 = <1200000 1200000 1350000>; + opp-microvolt-L3 = <1150000 1150000 1350000>; + clock-latency-ns = <40000>; }; opp-1512000000 { opp-hz = /bits/ 64 <1512000000>; - opp-microvolt = <1300000>; + opp-microvolt = <1350000 1350000 1350000>; + opp-microvolt-L0 = <1350000 1350000 1350000>; + opp-microvolt-L1 = <1300000 1300000 1350000>; + opp-microvolt-L2 = <1250000 1250000 1350000>; + opp-microvolt-L3 = <1200000 1200000 1350000>; + clock-latency-ns = <40000>; }; opp-1608000000 { opp-hz = /bits/ 64 <1608000000>; - opp-microvolt = <1350000>; + opp-microvolt = <1350000 1350000 1350000>; + opp-microvolt-L0 = <1350000 1350000 1350000>; + opp-microvolt-L1 = <1350000 1350000 1350000>; + opp-microvolt-L2 = <1300000 1300000 1350000>; + opp-microvolt-L3 = <1250000 1250000 1350000>; + clock-latency-ns = <40000>; }; }; @@ -1035,6 +1118,28 @@ reset-names = "phy-reset"; }; }; + + pvtm: pvtm { + compatible = "rockchip,rk3288-pvtm"; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + pvtm@0 { + reg = <0>; + clocks = <&cru SCLK_PVTM_CORE>; + clock-names = "clk"; + resets = <&cru SRST_CORE_PVTM>; + reset-names = "rst"; + }; + pvtm@1 { + reg = <1>; + clocks = <&cru SCLK_PVTM_GPU>; + clock-names = "clk"; + resets = <&cru SRST_GPU_PVTM>; + reset-names = "rst"; + }; + }; }; wdt: watchdog@ff800000 { @@ -1744,12 +1849,32 @@ clocks = <&cru PCLK_EFUSE256>; clock-names = "pclk_efuse"; + special_function: special-function@5 { + reg = <0x5 0x1>; + bits = <4 4>; + }; + package_info: package-info@5 { + reg = <0x5 0x1>; + bits = <2 2>; + }; + process_version: process-version@6 { + reg = <0x6 0x1>; + bits = <0 4>; + }; cpu_id: cpu-id@7 { reg = <0x07 0x10>; }; cpu_leakage: cpu_leakage@17 { reg = <0x17 0x1>; }; + performance_w: performance@1c { + reg = <0x1c 0x1>; + bits = <4 3>; + }; + performance: performance@1d { + reg = <0x1d 0x1>; + bits = <4 3>; + }; }; gic: interrupt-controller@ffc01000 { From bcb9689220bbebd8a60d690fd51f7d700b46036a Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Tue, 26 Dec 2017 09:02:22 +0800 Subject: [PATCH 064/235] ARM: dts: rockchip: rk3288: Add utmi clock for ehci and ohci This change adds USB-PHY output clock reference for EHCI and OHCI. Change-Id: I39e91fed99756a86c83fe9332587c6630a5e5853 Signed-off-by: Frank Wang Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 6f41ed32328d..92c7f05ed303 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -716,7 +716,8 @@ compatible = "generic-ehci"; reg = <0x0 0xff500000 0x0 0x20000>; interrupts = ; - clocks = <&cru HCLK_USBHOST0>; + clocks = <&cru HCLK_USBHOST0>, <&usbphy1>; + clock-names = "usbhost", "utmi"; phys = <&usbphy1>; phy-names = "usb"; status = "disabled"; @@ -727,7 +728,8 @@ compatible = "generic-ohci"; reg = <0x0 0xff520000 0x0 0x100>; interrupts = ; - clocks = <&cru HCLK_USBHOST0>; + clocks = <&cru HCLK_USBHOST0>, <&usbphy1>; + clock-names = "usbhost", "utmi"; phys = <&usbphy1>; phy-names = "usb"; status = "disabled"; From 3673d0a600c020a563a6d8b92d9449273248a6b2 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 5 Dec 2017 16:55:55 +0800 Subject: [PATCH 065/235] ARM: dts: rockchip: rk3288: Assigned i2s_src parent to GPLL The default parent of i2s_src is 200MHz CPLL, it doesn't meet the constraint of fractional divider that denominator must be 20 times larger than numerator. Change-Id: I986525ca7a92cb5883facd1b6e89079398302856 Signed-off-by: Finley Xiao Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 92c7f05ed303..cca4a12ab369 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1174,6 +1174,8 @@ interrupts = ; clocks = <&cru SCLK_I2S0>, <&cru HCLK_I2S0>; clock-names = "i2s_clk", "i2s_hclk"; + assigned-clocks = <&cru SCLK_I2S_SRC>; + assigned-clock-parents = <&cru PLL_GPLL>; dmas = <&dmac_bus_s 0>, <&dmac_bus_s 1>; dma-names = "tx", "rx"; pinctrl-names = "default"; From 674536165c5880ee43e2e3bb8f23f97551cc2e18 Mon Sep 17 00:00:00 2001 From: Jianing Ren Date: Thu, 12 Mar 2020 18:08:40 +0800 Subject: [PATCH 066/235] ARM: dts: rockchip: rk3288: Add otg-bvalid interrupt Change-Id: Id652b5ba4c16f8a53cc5bee9cd50fecfacff45c1 Signed-off-by: Jianing Ren --- arch/arm/boot/dts/rk3288.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index cca4a12ab369..6efb3f6a6a95 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1098,6 +1098,8 @@ #clock-cells = <0>; resets = <&cru SRST_USBOTG_PHY>; reset-names = "phy-reset"; + interrupts = ; + interrupt-names = "otg-bvalid"; }; usbphy1: usb-phy@334 { From bc82ddeea8437d2b8f4cb34a364633bfea5a3d79 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 17 Nov 2022 16:37:06 +0800 Subject: [PATCH 067/235] ARM: dts: rockchip: rk3288: add alias for dsi0 and dsi1 Fixes: 69870f9db0b6 ("ARM: dts: rockchip: rk3288: fix display related nodes") Signed-off-by: Jianqun Xu Change-Id: Ie929fa6ef965bf69ad1e0b4eb383535352068f84 --- arch/arm/boot/dts/rk3288.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 6efb3f6a6a95..cad689a726a4 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -19,6 +19,8 @@ interrupt-parent = <&gic>; aliases { + dsi0 = &dsi0; + dsi1 = &dsi1; ethernet0 = &gmac; gpio0 = &gpio0; gpio1 = &gpio1; From dcb9d29dbffcc965faf51981aae936155cfd1673 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 17 Nov 2022 17:04:54 +0800 Subject: [PATCH 068/235] ARM: dts: rockchip: rk3288-evb add rockchip-relinquish-port quirk for ehci This adds force abnormal ohci relinquish port owner and back to ehci on rk3288 SoC. Change-Id: I33be55c08762be7e8a239f741a8c8dbb28522306 Signed-off-by: Frank Wang Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288-evb.dtsi | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index 03d9c5f0533c..e3dad0f2502a 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -197,6 +197,15 @@ regulator-boot-on; }; + vcc_otg_vbus: otg-vbus-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&otg_vbus_drv>; + regulator-name = "vcc_otg_vbus"; + }; + vcc_phy: vcc-phy-regulator { compatible = "regulator-fixed"; enable-active-high; @@ -447,6 +456,10 @@ host_vbus_drv: host-vbus-drv { rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; }; + + otg_vbus_drv: otg-bus-drv { + rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; + }; }; eth_phy { @@ -461,6 +474,11 @@ }; &usb_host0_ehci { + rockchip-relinquish-port; + status = "okay"; +}; + +&usb_host0_ohci { status = "okay"; }; @@ -468,6 +486,11 @@ status = "okay"; }; +&usb_otg { + vbus-supply = <&vcc_otg_vbus>; + status = "okay"; +}; + &vopb { status = "okay"; }; From 13155994fcf3435806a5a945404025214fe92874 Mon Sep 17 00:00:00 2001 From: Nickey Yang Date: Thu, 4 Aug 2016 17:08:02 +0800 Subject: [PATCH 069/235] ARM: dts: rockchip: rk3288-evb support AP6335 wifi and bt This patch add and enable AP6335 wifi node for rk3288-evb Change-Id: I49e7f6a67130a105579627d30db55010967da57a Signed-off-by: Nickey Yang Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288-evb-act8846.dts | 20 +++++++++-- arch/arm/boot/dts/rk3288-evb-rk808.dts | 16 +++++++++ arch/arm/boot/dts/rk3288-evb.dtsi | 45 ++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-evb-act8846.dts b/arch/arm/boot/dts/rk3288-evb-act8846.dts index be695b8c1f67..3e9393f1c12a 100644 --- a/arch/arm/boot/dts/rk3288-evb-act8846.dts +++ b/arch/arm/boot/dts/rk3288-evb-act8846.dts @@ -7,6 +7,22 @@ model = "Rockchip RK3288 EVB ACT8846"; compatible = "rockchip,rk3288-evb-act8846", "rockchip,rk3288"; + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&hym8563>; + 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 = <&gpio4 28 GPIO_ACTIVE_LOW>; + }; + vcc_lcd: vcc-lcd { compatible = "regulator-fixed"; enable-active-high; @@ -54,12 +70,12 @@ vin-supply = <&vcc_sys>; }; - hym8563@51 { + hym8563: hym8563@51 { compatible = "haoyu,hym8563"; reg = <0x51>; interrupt-parent = <&gpio0>; - interrupts = ; + interrupts = <4 IRQ_TYPE_EDGE_FALLING>; pinctrl-names = "default"; pinctrl-0 = <&pmic_int>; diff --git a/arch/arm/boot/dts/rk3288-evb-rk808.dts b/arch/arm/boot/dts/rk3288-evb-rk808.dts index 42384ea4ca21..e9f3cdf8fa4e 100644 --- a/arch/arm/boot/dts/rk3288-evb-rk808.dts +++ b/arch/arm/boot/dts/rk3288-evb-rk808.dts @@ -6,6 +6,22 @@ / { model = "Rockchip RK3288 EVB RK808"; compatible = "rockchip,rk3288-evb-rk808", "rockchip,rk3288"; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk808 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 = <&gpio4 28 GPIO_ACTIVE_LOW>; + }; }; &i2c0 { diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index e3dad0f2502a..65f5a5379285 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -244,6 +244,27 @@ startup-delay-us = <100000>; vin-supply = <&vcc_io>; }; + + wireless-bluetooth { + compatible = "bluetooth-platdata"; + uart_rts_gpios = <&gpio4 19 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart0_rts>; + pinctrl-1 = <&uart0_gpios>; + BT,reset_gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>; + BT,wake_gpio = <&gpio4 26 GPIO_ACTIVE_HIGH>; + BT,wake_host_irq = <&gpio4 31 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + wireless-wlan { + compatible = "wlan-platdata"; + rockchip,grf = <&grf>; + wifi_chip_type = "ap6335"; + sdio_vref = <1800>; + WIFI,host_wake_irq = <&gpio4 30 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; }; &cpu0 { @@ -361,7 +382,25 @@ status = "okay"; }; +&sdio0 { + status = "okay"; + max-frequency = <150000000>; + bus-width = <4>; + cap-sd-highspeed; + no-mmc; + no-sd; + cap-sdio-irq; + mmc-pwrseq = <&sdio_pwrseq>; + keep-power-in-suspend; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk &sdio0_int>; + sd-uhs-sdr104; +}; + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer &uart0_cts>; status = "okay"; }; @@ -467,6 +506,12 @@ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; }; }; + + wireless-bluetooth { + uart0_gpios: uart0-gpios { + rockchip,pins = <4 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; }; &usbphy { From 6e89c6ee15f2b13c57893bbe296f728ef5e189d7 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Fri, 24 Mar 2017 10:37:46 +0800 Subject: [PATCH 070/235] ARM: dts: rockchip: rk3288-evb disable uart 1/3/4 Uart3 has been iomux to gpio, for vcc_3g regulator, which is designed on rk3288 evb main board. Disable unused uarts to fix gpio request blame during system booting. Change-Id: I2eb79ae63a6f226255c12fc3da9ba95ec4219d32 Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288-evb.dtsi | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index 65f5a5379285..49530074a727 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -404,22 +404,10 @@ status = "okay"; }; -&uart1 { - status = "okay"; -}; - &uart2 { status = "okay"; }; -&uart3 { - status = "okay"; -}; - -&uart4 { - status = "okay"; -}; - &tsadc { rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */ rockchip,hw-tshut-polarity = <0>; /* tshut polarity 0:LOW 1:HIGH */ From 641b252347610dbd1b68f1d8065ced0cdc4dde32 Mon Sep 17 00:00:00 2001 From: Jacob Chen Date: Fri, 15 Jul 2016 15:50:53 +0800 Subject: [PATCH 071/235] ARM: dts: rockchip: rk3288-evb enable high speed on sdcard Change-Id: Idd855fb565dde2e47891f6676175c6573c245fcd Signed-off-by: Jacob Chen Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288-evb.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index 49530074a727..ad9058f4fd5e 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -313,6 +313,10 @@ &sdmmc { bus-width = <4>; cap-mmc-highspeed; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; cap-sd-highspeed; no-mmc; no-sdio; From 723f0eabf68135e3159cba9fc3b66dad2b6b7922 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Mon, 27 Mar 2017 16:51:50 +0800 Subject: [PATCH 072/235] ARM: dts: rockchip: rk3288-evb add support for GSL3673 GSL3673 is a touchscreen device, let support it. Change-Id: I4bf302c395491ca49a1874c8984caa0b49cfb326 Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288-evb.dtsi | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index ad9058f4fd5e..c229ed5fcf96 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -373,6 +373,21 @@ }; }; +&i2c4 { + status = "okay"; + clock-frequency = <400000>; + + gsl3673@40 { + compatible = "GSL,GSL3673"; + reg = <0x40>; + screen_max_x = <1536>; + screen_max_y = <2048>; + irq_gpio_number = <&gpio7 6 IRQ_TYPE_LEVEL_LOW>; + rst_gpio_number = <&gpio7 5 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + &i2s { #sound-dai-cells = <0>; status = "okay"; From 89c19af784a60525a08a3615018988d76d3beb46 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 28 Mar 2019 16:51:24 +0800 Subject: [PATCH 073/235] ARM: dts: rockchip: rk3288: Add performance configuration for gpu Change-Id: Iac51c59395c3111d267b50aea69a2704442def1b Signed-off-by: Finley Xiao Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index cad689a726a4..d6ede5928df6 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1757,6 +1757,16 @@ gpu_opp_table: gpu-opp-table { compatible = "operating-points-v2"; + clocks = <&cru PLL_GPLL>; + nvmem-cells = <&performance>, <&performance_w>; + nvmem-cell-names = "performance", "performance-w"; + rockchip,bin-scaling-sel = < + 0 55 + 1 59 + 2 61 + 3 61 + >; + opp-100000000 { opp-hz = /bits/ 64 <100000000>; opp-microvolt = <950000>; From 25e9b5b53a5cca05e224824d16d29e69939d3e3d Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Fri, 12 Apr 2019 09:56:34 +0800 Subject: [PATCH 074/235] ARM: dts: rockchip: delete gpu 100MHz for rk3288 100MHz will hurt performance when app startup. Change-Id: Ia55a5f53b101559b9d6b94ca98609f7072df6d86 Signed-off-by: Liang Chen --- arch/arm/boot/dts/rk3288.dtsi | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index d6ede5928df6..6c4c1c86f44e 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1767,10 +1767,6 @@ 3 61 >; - opp-100000000 { - opp-hz = /bits/ 64 <100000000>; - opp-microvolt = <950000>; - }; opp-200000000 { opp-hz = /bits/ 64 <200000000>; opp-microvolt = <950000>; From 0a4c984ad08ba9707c9a89d10927af349c355b4f Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Fri, 18 Nov 2022 16:00:49 +0800 Subject: [PATCH 075/235] ARM: dts: rockchip: rk3288: fix 'gpu_thermal' to 'gpu-thermal' The midgard reports a error about the thermal zone as following: [ 6.242958] midgard ffa30000.gpu: GPU identified as 0x0750 r1p0 status 0 [ 6.249761] midgard ffa30000.gpu: Protected mode not available [ 6.255837] midgard ffa30000.gpu: l=-2147483648 h=2147483647 hyst=0 l_limit=0 h_limit=0 h_table=0 [ 6.264833] Error -19 getting thermal zone 'gpu-thermal', not yet ready? [ 6.271551] midgard ffa30000.gpu: recalculation of power model mali-simple-power-model returned error -517 [ 6.281210] midgard ffa30000.gpu: IPA initialization failed [ 6.281333] devfreq ffa30000.gpu: Couldn't update frequency transition information. [ 6.294566] midgard ffa30000.gpu: Continuing without devfreq [ 6.300568] midgard ffa30000.gpu: Probed as mali0 Signed-off-by: Jianqun Xu Change-Id: I6ff5a0bd5679e7b7c3b657c475b0a788eb03f24a --- arch/arm/boot/dts/rk3288.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 6c4c1c86f44e..3d83ab11d8a0 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -646,7 +646,7 @@ }; }; - gpu_thermal: gpu_thermal { + gpu_thermal: gpu-thermal { polling-delay-passive = <100>; /* milliseconds */ polling-delay = <5000>; /* milliseconds */ From d3593fabde89402c8e03eeac7667ef22bd0c5885 Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Sat, 12 Oct 2019 09:10:28 +0800 Subject: [PATCH 076/235] ARM: dts: rockchip: rk3288: add rng node rng node is compflict with crypto node, so default disable rng node and crypto node. Change-Id: I9a28108a5667f88c15d5cc9916d927115cdb8918 Signed-off-by: Lin Jinhan Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 3d83ab11d8a0..799687142a44 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1191,6 +1191,16 @@ status = "disabled"; }; + rng: rng@ff8a0000 { + compatible = "rockchip,cryptov1-rng"; + reg = <0x0 0xff8a0000 0x0 0x4000>; + clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO>; + clock-names = "clk_crypto", "hclk_crypto"; + assigned-clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO>; + assigned-clock-rates = <150000000>, <100000000>; + status = "disabled"; + }; + crypto: crypto@ff8a0000 { compatible = "rockchip,rk3288-crypto"; reg = <0x0 0xff8a0000 0x0 0x4000>; @@ -1200,7 +1210,7 @@ clock-names = "aclk", "hclk", "sclk", "apb_pclk"; resets = <&cru SRST_CRYPTO>; reset-names = "crypto-rst"; - status = "okay"; + status = "disabled"; }; spdif: sound@ff8b0000 { From 8c99ad8b0f626f8302cedcb9160caf17c3697bdf Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Sat, 19 Nov 2022 11:44:49 +0800 Subject: [PATCH 077/235] ARM: dts: rockchip: rk3288-linux: Enable rng node Signed-off-by: Lin Jinhan Signed-off-by: Jianqun Xu Change-Id: I581f17e04b20493c979b275b1b8624a0af7809c9 --- arch/arm/boot/dts/rk3288-linux.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-linux.dtsi b/arch/arm/boot/dts/rk3288-linux.dtsi index 584a5cc38d9f..2ce2b059c1cb 100644 --- a/arch/arm/boot/dts/rk3288-linux.dtsi +++ b/arch/arm/boot/dts/rk3288-linux.dtsi @@ -194,6 +194,10 @@ status = "okay"; }; +&rng { + status = "okay"; +}; + &uart2 { status = "disabled"; }; From cdea157c04ea06ac68c4e0e3e70795993eebb47c Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Wed, 20 Sep 2017 10:11:10 +0800 Subject: [PATCH 078/235] ARM: dts: rockchip: rk3288: split i2s mclk pinctrl from i2s bus because currently mclk is handled by codec side, so the associated pinctrl should be handled by codec too. Change-Id: I0611b7a291351a20f72b5124c501dc79d92787d6 Signed-off-by: Sugar Zhang Signed-off-by: Jianqun Xu --- arch/arm/boot/dts/rk3288.dtsi | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 799687142a44..b37075bc74f7 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -2185,8 +2185,11 @@ <6 RK_PA1 1 &pcfg_pull_none>, <6 RK_PA2 1 &pcfg_pull_none>, <6 RK_PA3 1 &pcfg_pull_none>, - <6 RK_PA4 1 &pcfg_pull_none>, - <6 RK_PB0 1 &pcfg_pull_none>; + <6 RK_PA4 1 &pcfg_pull_none>; + }; + + i2s0_mclk: i2s0-mclk { + rockchip,pins = <6 RK_PB0 1 &pcfg_pull_none>; }; }; From 70e4176f1c4d95a3e17ff91110c1723df5c6d676 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Sat, 19 Nov 2022 11:50:52 +0800 Subject: [PATCH 079/235] ARM: dts: rockchip: rk3288-evb: split i2s mclk pinctrl from i2s bus because currently mclk is handled by codec side, so the associated pinctrl should be handled by codec too. Signed-off-by: Sugar Zhang Signed-off-by: Jianqun Xu Change-Id: If9c2d2fdedbc2673b2fe0e6738ed8fb54c98a0ba --- arch/arm/boot/dts/rk3288-evb.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index c229ed5fcf96..0b1cda728171 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -370,6 +370,8 @@ clock-names = "mclk"; interrupt-parent = <&gpio7>; interrupts = <7 IRQ_TYPE_EDGE_FALLING>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_mclk>; }; }; From a6a8f8d0a3fcc83a81388cc3c332ae6ffb8c07ce Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Fri, 18 Nov 2022 10:57:26 +0800 Subject: [PATCH 080/235] clk: rockchip: rk3288 set aclk_peri_niu as critical Fixes: 938e2f2261c0 ("clk: rockchip: drop use of rockchip_clk_protect_critical()") Signed-off-by: Jianqun Xu Change-Id: I65b4dd2f380d30d7638212234ff23dc17e2d4349 --- drivers/clk/rockchip/clk-rk3288.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 01838b61659d..265061bb4227 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -724,7 +724,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { /* aclk_peri gates */ GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(6), 2, GFLAGS), GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 3, GFLAGS), - GATE(0, "aclk_peri_niu", "aclk_peri", 0, RK3288_CLKGATE_CON(7), 11, GFLAGS), + GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IS_CRITICAL, RK3288_CLKGATE_CON(7), 11, GFLAGS), GATE(ACLK_MMU, "aclk_mmu", "aclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(8), 12, GFLAGS), GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 0, GFLAGS), GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 2, GFLAGS), From e733a7a8b34b91dad35eec0d16aedc78f1a83150 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Fri, 18 Nov 2022 17:39:49 +0800 Subject: [PATCH 081/235] clk: rockchip: fix to SIP_V2 for rk3288 Fixes: d2b92a90eabd ("clk: rockchip: support setting ddr clock via SCPI and SIP Version 2 APIs") Signed-off-by: Jianqun Xu Change-Id: I7521443f50dbe3049fd8a08c769a74f5e364334a --- drivers/clk/rockchip/clk-rk3288.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 265061bb4227..f9c4678fcd73 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -339,7 +339,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { RK3288_CLKGATE_CON(0), 9, GFLAGS), COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, 0, RK3288_CLKSEL_CON(26), 2, 1, 0, 0, - ROCKCHIP_DDRCLK_SIP), + ROCKCHIP_DDRCLK_SIP_V2), COMPOSITE_NOGATE(0, "ddrphy", mux_ddrphy_p, CLK_IGNORE_UNUSED, RK3288_CLKSEL_CON(26), 2, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO), From 7cfaa4a10f78f8ab69f7c2922ae0b0793d08dfa0 Mon Sep 17 00:00:00 2001 From: Yiqing Zeng Date: Mon, 14 Nov 2022 20:05:11 +0800 Subject: [PATCH 082/235] ARM: configs: rockchip_linux_defconfig: enable rkisp1 config CONFIG_VIDEO_ROCKCHIP_RKISP1=y Change-Id: I11f913c8f04efd2eb53fb63d5ebe24c0e072d915 Signed-off-by: Yiqing Zeng --- arch/arm/configs/rockchip_linux_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/rockchip_linux_defconfig b/arch/arm/configs/rockchip_linux_defconfig index d6c90d75711b..1714966b09ee 100644 --- a/arch/arm/configs/rockchip_linux_defconfig +++ b/arch/arm/configs/rockchip_linux_defconfig @@ -273,6 +273,7 @@ CONFIG_USB_VIDEO_CLASS=y # 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_V4L_TEST_DRIVERS=y CONFIG_VIDEO_IMX219=y From 14a26d6f6b03060f73132399d272e926060f01e6 Mon Sep 17 00:00:00 2001 From: Yiqing Zeng Date: Mon, 14 Nov 2022 20:39:19 +0800 Subject: [PATCH 083/235] ARM: configs: rockchip_linux_defconfig: add gc8034 config CONFIG_VIDEO_GC8034=y Change-Id: I44c5cf192936f668a9b3c9322136781070435e48 Signed-off-by: Yiqing Zeng --- arch/arm/configs/rockchip_linux_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/rockchip_linux_defconfig b/arch/arm/configs/rockchip_linux_defconfig index 1714966b09ee..dcd5e71914a0 100644 --- a/arch/arm/configs/rockchip_linux_defconfig +++ b/arch/arm/configs/rockchip_linux_defconfig @@ -276,6 +276,7 @@ CONFIG_VIDEO_ROCKCHIP_CIF=y CONFIG_VIDEO_ROCKCHIP_RKISP1=y CONFIG_V4L_MEM2MEM_DRIVERS=y CONFIG_V4L_TEST_DRIVERS=y +CONFIG_VIDEO_GC8034=y CONFIG_VIDEO_IMX219=y CONFIG_VIDEO_OV5647=y CONFIG_VIDEO_OV8858=y From 70de50acbbc926c3c7a6d09691b9075c284c1f4d Mon Sep 17 00:00:00 2001 From: Yiqing Zeng Date: Mon, 14 Nov 2022 20:37:08 +0800 Subject: [PATCH 084/235] ARM: dts: rockchip: support ov13850/gc8034 for rk3288-evb-rk808-linux Change-Id: I84c7e782a99270a29de0976b97784ccc73b35bad Signed-off-by: Yiqing Zeng --- arch/arm/boot/dts/rk3288-evb-rk808-linux.dts | 79 +++++++++++++++----- 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts b/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts index 9d19736b1170..ef5899441582 100644 --- a/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts +++ b/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts @@ -41,7 +41,6 @@ /dts-v1/; #include "rk3288-evb.dtsi" #include "rk3288-linux.dtsi" -#include "rk3288-rkisp1.dtsi" / { compatible = "rockchip,rk3288-evb-rk808-linux", "rockchip,rk3288"; @@ -429,29 +428,48 @@ ov13850: ov13850@10 { compatible = "ovti,ov13850"; - status = "okay"; reg = <0x10>; clocks = <&cru SCLK_VIP_OUT>; clock-names = "xvclk"; - - reset-gpios = <&gpio7 21 GPIO_ACTIVE_HIGH>; - pwdn-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>; - + /* avdd-supply = <>; */ + /* dvdd-supply = <>; */ + /* dovdd-supply = <>; */ + /* reset-gpios = <>; */ + pinctrl-names = "rockchip,camera_default"; + pinctrl-0 = <&isp_mipi>; + power-gpio = <&gpio7 RK_PC5 GPIO_ACTIVE_HIGH>; + pwdn-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "CMK-CT0116"; + rockchip,camera-module-lens-name = "Largan-50013A1"; port { - cam_out: endpoint { - remote-endpoint = <&mipi_in_cam>; + ov13850_out: endpoint { + remote-endpoint = <&mipi_in_ucam0>; data-lanes = <1 2>; }; }; }; -}; -&isp { - status = "okay"; - - port { - isp_mipi_in: endpoint { - remote-endpoint = <&dphy_rx0_out>; + gc8034: gc8034@37 { + compatible = "galaxycore,gc8034"; + status = "okay"; + reg = <0x37>; + clocks = <&cru SCLK_VIP_OUT>; + clock-names = "xvclk"; + pinctrl-names = "rockchip,camera_default"; + pinctrl-0 = <&isp_mipi>; + reset-gpios = <&gpio7 RK_PC5 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "LH-RK-8034-v1.0"; + rockchip,camera-module-lens-name = "CK8401"; + port { + gc8034_out: endpoint { + remote-endpoint = <&mipi_in_gc8034>; + data-lanes = <1 2 3 4>; + }; }; }; }; @@ -469,23 +487,48 @@ port@0 { reg = <0>; + #address-cells = <1>; + #size-cells = <0>; - mipi_in_cam: endpoint { - remote-endpoint = <&cam_out>; + mipi_in_ucam0: endpoint@1 { + reg = <1>; + remote-endpoint = <&ov13850_out>; data-lanes = <1 2>; }; + mipi_in_gc8034: endpoint@0 { + reg = <0>; + remote-endpoint = <&gc8034_out>; + data-lanes = <1 2 3 4>; + }; }; port@1 { reg = <1>; + #address-cells = <1>; + #size-cells = <0>; - dphy_rx0_out: endpoint { + dphy_rx_out: endpoint@0 { + reg = <0>; remote-endpoint = <&isp_mipi_in>; }; }; }; }; +&rkisp1 { + status = "okay"; + port { + #address-cells = <1>; + #size-cells = <0>; + + isp_mipi_in: endpoint@0 { + reg = <0>; + remote-endpoint = <&dphy_rx_out>; + }; + + }; +}; + &rga { status = "okay"; }; From 1cde5fb12c3538572574cab4ae6293f412c9dd89 Mon Sep 17 00:00:00 2001 From: Shuangjie Lin Date: Wed, 9 Nov 2022 17:29:34 +0800 Subject: [PATCH 085/235] driver: rknpu: Fix system interrupt signal cost rknpu wait error Using wait_event_timeout() replace wait_event_interruptible_timeout(). Change-Id: I53481d25cb96a86a6262672bb65e9a2ed942164a Signed-off-by: Shuangjie Lin --- drivers/rknpu/rknpu_job.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/rknpu/rknpu_job.c b/drivers/rknpu/rknpu_job.c index 6f601ab5fe6d..9e50467b22ec 100644 --- a/drivers/rknpu/rknpu_job.c +++ b/drivers/rknpu/rknpu_job.c @@ -166,10 +166,10 @@ static inline int rknpu_job_wait(struct rknpu_job *job) subcore_data = &rknpu_dev->subcore_datas[core_index]; do { - ret = wait_event_interruptible_timeout( - subcore_data->job_done_wq, - job->flags & RKNPU_JOB_DONE || rknpu_dev->soft_reseting, - msecs_to_jiffies(args->timeout)); + ret = wait_event_timeout(subcore_data->job_done_wq, + job->flags & RKNPU_JOB_DONE || + rknpu_dev->soft_reseting, + msecs_to_jiffies(args->timeout)); if (++wait_count >= 3) break; } while (ret == 0 && job->in_queue[core_index]); From 8fedbbb946759fdf99f852cc00ea0bb155981447 Mon Sep 17 00:00:00 2001 From: XiaoDong Huang Date: Wed, 16 Nov 2022 11:41:41 +0800 Subject: [PATCH 086/235] PM / devfreq: rockchip_bus: support parse soc-bus-table Signed-off-by: XiaoDong Huang Change-Id: I76ff30103cfa93289b9ecde0d95f42f960284e9b --- drivers/devfreq/rockchip_bus.c | 48 ++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/devfreq/rockchip_bus.c b/drivers/devfreq/rockchip_bus.c index 7032b4815c5a..88792d60a0b2 100644 --- a/drivers/devfreq/rockchip_bus.c +++ b/drivers/devfreq/rockchip_bus.c @@ -73,7 +73,9 @@ static int rockchip_bus_smc_config(struct rockchip_bus *bus) struct device_node *np = dev->of_node; struct device_node *child; unsigned int enable_msk, bus_id, cfg; - int ret; + char *prp_name = "rockchip,soc-bus-table"; + u32 *table = NULL; + int ret = 0, config_cnt, i; for_each_available_child_of_node(np, child) { ret = of_property_read_u32_index(child, "bus-id", 0, @@ -108,7 +110,49 @@ static int rockchip_bus_smc_config(struct rockchip_bus *bus) } } - return 0; + config_cnt = of_property_count_u32_elems(np, prp_name); + if (config_cnt <= 0) { + return 0; + } else if (config_cnt % 3) { + dev_err(dev, "Invalid count of %s\n", prp_name); + return -EINVAL; + } + + table = kmalloc_array(config_cnt, sizeof(u32), GFP_KERNEL); + if (!table) + return -ENOMEM; + + ret = of_property_read_u32_array(np, prp_name, table, config_cnt); + if (ret) { + dev_err(dev, "get %s error\n", prp_name); + goto free_table; + } + + /* table[3n]: bus_id + * table[3n + 1]: config + * table[3n + 2]: enable_mask + */ + for (i = 0; i < config_cnt; i += 3) { + bus_id = table[i]; + cfg = table[i + 1]; + enable_msk = table[i + 2]; + + if (!cfg) { + dev_info(dev, "cfg-val invalid in %s-%d\n", prp_name, bus_id); + continue; + } + + ret = rockchip_sip_bus_smc_config(bus_id, cfg, enable_msk); + if (ret) { + dev_err(dev, "bus smc config error: %x!\n", ret); + goto free_table; + } + } + +free_table: + kfree(table); + + return ret; } static int rockchip_bus_set_freq_table(struct rockchip_bus *bus) From 9cc95efeb52a35a18ac29057fdbfd0ee6bbcc996 Mon Sep 17 00:00:00 2001 From: XiaoDong Huang Date: Wed, 16 Nov 2022 11:48:25 +0800 Subject: [PATCH 087/235] PM / devfreq: rockchip_bus: add support for rk3588 Signed-off-by: XiaoDong Huang Change-Id: If03fa9331168187dabf6f97cc38354f0b560fc1c --- drivers/devfreq/rockchip_bus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/devfreq/rockchip_bus.c b/drivers/devfreq/rockchip_bus.c index 88792d60a0b2..6dd20a6e2b0e 100644 --- a/drivers/devfreq/rockchip_bus.c +++ b/drivers/devfreq/rockchip_bus.c @@ -492,6 +492,7 @@ static const struct of_device_id rockchip_busfreq_of_match[] = { { .compatible = "rockchip,rk3368-bus", }, { .compatible = "rockchip,rk3399-bus", }, { .compatible = "rockchip,rk3568-bus", }, + { .compatible = "rockchip,rk3588-bus", }, { .compatible = "rockchip,rv1126-bus", }, { }, }; From 54162171af2c6de95b77507150868432f949553d Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 17 Nov 2022 22:02:38 +0800 Subject: [PATCH 088/235] net: phy: rk630phy: Add agc offset for initial flow Signed-off-by: David Wu Change-Id: Ibea8e37f7cf6e462ef281981c2529b6126287b9f --- drivers/net/phy/rk630phy.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/phy/rk630phy.c b/drivers/net/phy/rk630phy.c index 23ab0b1f9d11..42662f3d39f2 100644 --- a/drivers/net/phy/rk630phy.c +++ b/drivers/net/phy/rk630phy.c @@ -207,6 +207,8 @@ static void rk630_phy_t22_config_init(struct phy_device *phydev) /* Switch to page 1 */ phy_write(phydev, REG_PAGE_SEL, 0x0100); + /* Enable offset clock */ + phy_write(phydev, 0x10, 0xfbfe); /* Disable APS */ phy_write(phydev, REG_PAGE1_APS_CTRL, 0x4824); /* Switch to page 2 */ @@ -241,6 +243,8 @@ static void rk630_phy_t22_config_init(struct phy_device *phydev) phy_write(phydev, REG_PAGE_SEL, 0x0800); /* Disable auto-cal */ phy_write(phydev, REG_PAGE8_AUTO_CAL, 0x0844); + /* Reatart offset calibration */ + phy_write(phydev, 0x13, 0xc096); /* Switch to page 0 */ phy_write(phydev, REG_PAGE_SEL, 0x0000); From f340fd1bf02388ecef2df84805112b7e53378397 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 15 Nov 2022 20:07:40 +0800 Subject: [PATCH 089/235] Revert "ARM: dts: rockchip: Fix UART pull-ups on rk312x" This reverts commit 026248a29fce3e23c29a76e0239edabe2115e11a. Signed-off-by: Steven Liu Change-Id: I71c65cee85fbe72b7bb6aefbf610cb2e6264ec3a --- arch/arm/boot/dts/rk312x.dtsi | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/rk312x.dtsi b/arch/arm/boot/dts/rk312x.dtsi index 484bec18b00b..895b737b6896 100644 --- a/arch/arm/boot/dts/rk312x.dtsi +++ b/arch/arm/boot/dts/rk312x.dtsi @@ -1294,10 +1294,6 @@ bias-pull-pin-default; }; - pcfg_pull_up: pcfg-pull-up { - bias-pull-up; - }; - pcfg_output_high: pcfg-output-high { output-high; }; @@ -1422,8 +1418,8 @@ uart0 { uart0_xfer: uart0-xfer { - rockchip,pins = <2 RK_PD2 2 &pcfg_pull_up>, - <2 RK_PD3 2 &pcfg_pull_up>; + rockchip,pins = <2 RK_PD2 2 &pcfg_pull_default>, + <2 RK_PD3 2 &pcfg_pull_none>; }; uart0_cts: uart0-cts { @@ -1437,8 +1433,8 @@ uart1 { uart1_xfer: uart1-xfer { - rockchip,pins = <1 RK_PB1 2 &pcfg_pull_up>, - <1 RK_PB2 2 &pcfg_pull_up>; + rockchip,pins = <1 RK_PB1 2 &pcfg_pull_default>, + <1 RK_PB2 2 &pcfg_pull_default>; }; uart1_cts: uart1-cts { @@ -1452,8 +1448,8 @@ uart2 { uart2_xfer: uart2-xfer { - rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>, - <1 RK_PC3 2 &pcfg_pull_up>; + rockchip,pins = <1 RK_PC2 2 &pcfg_pull_default>, + <1 RK_PC3 2 &pcfg_pull_none>; }; uart2_cts: uart2-cts { From 7a35e84b14fa75ace4d55602fa50f99bb97d0e93 Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 15 Nov 2022 20:10:57 +0800 Subject: [PATCH 090/235] Revert "ARM: dts: rockchip: Fix UART pull-ups on rk3066a" This reverts commit dd2f0befb2b01fceb16f015c93d0276faa5d0c3b. Signed-off-by: Steven Liu Change-Id: I6efc99eea9740888fa0b7b311435c394381c7d9f --- arch/arm/boot/dts/rk3066a.dtsi | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi index 71e2495d78b2..3993abc9468f 100644 --- a/arch/arm/boot/dts/rk3066a.dtsi +++ b/arch/arm/boot/dts/rk3066a.dtsi @@ -503,10 +503,6 @@ bias-pull-pin-default; }; - pcfg_pull_up: pcfg-pull-up { - bias-pull-up; - }; - pcfg_pull_none: pcfg_pull_none { bias-disable; }; @@ -658,8 +654,8 @@ uart0 { uart0_xfer: uart0-xfer { - rockchip,pins = <1 RK_PA0 1 &pcfg_pull_up>, - <1 RK_PA1 1 &pcfg_pull_up>; + rockchip,pins = <1 RK_PA0 1 &pcfg_pull_default>, + <1 RK_PA1 1 &pcfg_pull_default>; }; uart0_cts: uart0-cts { @@ -673,8 +669,8 @@ uart1 { uart1_xfer: uart1-xfer { - rockchip,pins = <1 RK_PA4 1 &pcfg_pull_up>, - <1 RK_PA5 1 &pcfg_pull_up>; + rockchip,pins = <1 RK_PA4 1 &pcfg_pull_default>, + <1 RK_PA5 1 &pcfg_pull_default>; }; uart1_cts: uart1-cts { @@ -688,16 +684,16 @@ uart2 { uart2_xfer: uart2-xfer { - rockchip,pins = <1 RK_PB0 1 &pcfg_pull_up>, - <1 RK_PB1 1 &pcfg_pull_up>; + rockchip,pins = <1 RK_PB0 1 &pcfg_pull_default>, + <1 RK_PB1 1 &pcfg_pull_default>; }; /* no rts / cts for uart2 */ }; uart3 { uart3_xfer: uart3-xfer { - rockchip,pins = <3 RK_PD3 1 &pcfg_pull_up>, - <3 RK_PD4 1 &pcfg_pull_up>; + rockchip,pins = <3 RK_PD3 1 &pcfg_pull_default>, + <3 RK_PD4 1 &pcfg_pull_default>; }; uart3_cts: uart3-cts { From 99f754dcaa2d8df70556c1c4166142447fa587fa Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Tue, 15 Nov 2022 20:13:40 +0800 Subject: [PATCH 091/235] Revert "ARM: dts: rockchip: Fix UART pull-ups on rk3036" This reverts commit eb04688f6fd61747a9ad7d31fc3ab44ff71c553f. Signed-off-by: Steven Liu Change-Id: Ifbc43c2b6ba476fcc3c50c71b21b05aee4dd91c4 --- arch/arm/boot/dts/rk3036.dtsi | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 351e4b1631a7..9ac64dd5f11d 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -746,10 +746,6 @@ bias-pull-pin-default; }; - pcfg_pull_up: pcfg-pull-up { - bias-pull-up; - }; - pcfg_pull_none: pcfg-pull-none { bias-disable; }; @@ -910,8 +906,8 @@ uart0 { uart0_xfer: uart0-xfer { - rockchip,pins = <0 RK_PC0 1 &pcfg_pull_up>, - <0 RK_PC1 1 &pcfg_pull_up>; + rockchip,pins = <0 RK_PC0 1 &pcfg_pull_default>, + <0 RK_PC1 1 &pcfg_pull_default>; }; uart0_cts: uart0-cts { @@ -925,16 +921,16 @@ uart1 { uart1_xfer: uart1-xfer { - rockchip,pins = <2 RK_PC6 1 &pcfg_pull_up>, - <2 RK_PC7 1 &pcfg_pull_up>; + rockchip,pins = <2 RK_PC6 1 &pcfg_pull_default>, + <2 RK_PC7 1 &pcfg_pull_default>; }; /* no rts / cts for uart1 */ }; uart2 { uart2_xfer: uart2-xfer { - rockchip,pins = <1 RK_PC2 2 &pcfg_pull_up>, - <1 RK_PC3 2 &pcfg_pull_up>; + rockchip,pins = <1 RK_PC2 2 &pcfg_pull_default>, + <1 RK_PC3 2 &pcfg_pull_default>; }; /* no rts / cts for uart2 */ }; From 8b37dde38e8306388b5165066d6fd528eed332c7 Mon Sep 17 00:00:00 2001 From: David Wu Date: Tue, 15 Nov 2022 15:32:44 +0800 Subject: [PATCH 092/235] ARM: dts: rockchip: rk3036: Keep the pwm pins default pull state In order to ensure the accuracy of PWM voltage regulation, keep the pull state of PWM consistent with the default; The pull state has little effect on other case such as output mode. Signed-off-by: David Wu Change-Id: I4d4813a9426e45a1c3f3690603b63c57addcdb73 --- arch/arm/boot/dts/rk3036.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 9ac64dd5f11d..ba17c1274f5a 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -752,25 +752,25 @@ pwm0 { pwm0_pin: pwm0-pin { - rockchip,pins = <0 RK_PA0 2 &pcfg_pull_none>; + rockchip,pins = <0 RK_PA0 2 &pcfg_pull_default>; }; }; pwm1 { pwm1_pin: pwm1-pin { - rockchip,pins = <0 RK_PA1 2 &pcfg_pull_none>; + rockchip,pins = <0 RK_PA1 2 &pcfg_pull_default>; }; }; pwm2 { pwm2_pin: pwm2-pin { - rockchip,pins = <0 RK_PA1 2 &pcfg_pull_none>; + rockchip,pins = <0 RK_PA1 2 &pcfg_pull_default>; }; }; pwm3 { pwm3_pin: pwm3-pin { - rockchip,pins = <0 RK_PD3 1 &pcfg_pull_none>; + rockchip,pins = <0 RK_PD3 1 &pcfg_pull_default>; }; }; From 57b8f4d774bbd305a858d51a39cd2ba125942722 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 13 Nov 2017 15:32:25 +0800 Subject: [PATCH 093/235] clk: rockchip: rk3036: leave apll for core, mac and lcdc only In order not to affect other clocks, remove the apll from the parent list of other clocks and only core, mac and lcdc can select apll as parent. Change-Id: I58b995f8ccf69c6564f74b5823f618a186030d70 Signed-off-by: Finley Xiao Signed-off-by: Elaine Zhang --- drivers/clk/rockchip/clk-rk3036.c | 36 ++++++++++++++++--------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 9872eb15864e..ed05eb6c51f3 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -119,15 +119,17 @@ static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = { PNAME(mux_pll_p) = { "xin24m", "xin24m" }; -PNAME(mux_busclk_p) = { "apll", "dpll_cpu", "gpll_cpu" }; +PNAME(mux_busclk_p) = { "dummy_apll", "dpll_cpu", "gpll_cpu" }; PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" }; -PNAME(mux_pll_src_3plls_p) = { "apll", "dpll", "gpll" }; +PNAME(mux_pll_src_apll_dpll_gpll_p) = { "apll", "dpll", "gpll" }; +PNAME(mux_pll_src_dmyapll_dpll_gpll_p) = { "dummy_apll", "dpll", "gpll" }; + PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" }; -PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll", "usb480m" }; +PNAME(mux_pll_src_dmyapll_dpll_gpll_usb480m_p) = { "dummy_apll", "dpll", "gpll", "usb480m" }; PNAME(mux_pll_src_dmyapll_dpll_gpll_xin24_p) = { "dummy_apll", "dpll", "gpll", "xin24m" }; -PNAME(mux_mmc_src_p) = { "apll", "dpll", "gpll", "xin24m" }; +PNAME(mux_mmc_src_p) = { "dummy_apll", "dpll", "gpll", "xin24m" }; PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" }; PNAME(mux_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" }; @@ -212,7 +214,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_READ_ONLY, RK2928_CLKGATE_CON(0), 4, GFLAGS), - COMPOSITE(0, "aclk_peri_src", mux_pll_src_3plls_p, CLK_IS_CRITICAL, + COMPOSITE(0, "aclk_peri_src", mux_pll_src_dmyapll_dpll_gpll_p, 0, RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(2), 0, GFLAGS), @@ -240,7 +242,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKSEL_CON(2), 7, 1, MFLAGS, RK2928_CLKGATE_CON(2), 5, GFLAGS), - MUX(0, "uart_pll_clk", mux_pll_src_apll_dpll_gpll_usb480m_p, 0, + MUX(0, "uart_pll_clk", mux_pll_src_dmyapll_dpll_gpll_usb480m_p, 0, RK2928_CLKSEL_CON(13), 10, 2, MFLAGS), COMPOSITE_NOMUX(0, "uart0_src", "uart_pll_clk", 0, RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, @@ -264,23 +266,23 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKGATE_CON(1), 13, GFLAGS, &rk3036_uart2_fracmux), - COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0, + COMPOSITE(ACLK_VCODEC, "aclk_vcodec", mux_pll_src_dmyapll_dpll_gpll_p, 0, RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(3), 11, GFLAGS), FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4, RK2928_CLKGATE_CON(3), 12, GFLAGS), - COMPOSITE(ACLK_HEVC, "aclk_hevc", mux_pll_src_3plls_p, 0, + COMPOSITE(ACLK_HEVC, "aclk_hevc", mux_pll_src_dmyapll_dpll_gpll_p, 0, RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS, RK2928_CLKGATE_CON(10), 6, GFLAGS), - COMPOSITE(0, "aclk_disp1_pre", mux_pll_src_3plls_p, 0, + COMPOSITE(0, "aclk_disp1_pre", mux_pll_src_dmyapll_dpll_gpll_p, 0, RK2928_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(1), 4, GFLAGS), - COMPOSITE(0, "hclk_disp_pre", mux_pll_src_3plls_p, 0, + COMPOSITE(0, "hclk_disp_pre", mux_pll_src_dmyapll_dpll_gpll_p, 0, RK2928_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(0), 11, GFLAGS), - COMPOSITE(SCLK_LCDC, "dclk_lcdc", mux_pll_src_3plls_p, 0, + COMPOSITE(SCLK_LCDC, "dclk_lcdc", mux_pll_src_apll_dpll_gpll_p, 0, RK2928_CLKSEL_CON(28), 0, 2, MFLAGS, 8, 8, DFLAGS, RK2928_CLKGATE_CON(3), 2, GFLAGS), @@ -309,7 +311,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3036_EMMC_CON0, 1), MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3036_EMMC_CON1, 0), - COMPOSITE(0, "i2s_src", mux_pll_src_3plls_p, 0, + COMPOSITE(0, "i2s_src", mux_pll_src_dmyapll_dpll_gpll_p, 0, RK2928_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 9, GFLAGS), COMPOSITE_FRACMUX(SCLK_I2S_FRAC, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT, @@ -322,7 +324,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { GATE(SCLK_I2S, "sclk_i2s", "i2s_pre", CLK_SET_RATE_PARENT, RK2928_CLKGATE_CON(0), 14, GFLAGS), - COMPOSITE(0, "spdif_src", mux_pll_src_3plls_p, 0, + COMPOSITE(0, "spdif_src", mux_pll_src_dmyapll_dpll_gpll_p, 0, RK2928_CLKSEL_CON(5), 10, 2, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(2), 10, GFLAGS), COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", 0, @@ -333,15 +335,15 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin12m", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(1), 5, GFLAGS), - COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_3plls_p, 0, + COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_dmyapll_dpll_gpll_p, 0, RK2928_CLKSEL_CON(34), 8, 2, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(3), 13, GFLAGS), - COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_3plls_p, 0, + COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_dmyapll_dpll_gpll_p, 0, RK2928_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(2), 9, GFLAGS), - COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_3plls_p, 0, + COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_dmyapll_dpll_gpll_p, 0, RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS, RK2928_CLKGATE_CON(10), 4, GFLAGS), @@ -349,7 +351,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS, RK2928_CLKGATE_CON(10), 5, GFLAGS), - COMPOSITE_NOGATE(SCLK_MACPLL, "mac_pll_src", mux_pll_src_3plls_p, CLK_SET_RATE_NO_REPARENT, + COMPOSITE_NOGATE(SCLK_MACPLL, "mac_pll_src", mux_pll_src_apll_dpll_gpll_p, CLK_SET_RATE_NO_REPARENT, RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 9, 5, DFLAGS), MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(21), 3, 1, MFLAGS), From 276bad482bcbede7b03b83029c5390ace2cff30e Mon Sep 17 00:00:00 2001 From: wlq Date: Wed, 16 Nov 2022 08:02:52 +0000 Subject: [PATCH 094/235] arm64: dts: rockchip: px30: disabled uart dma Change-Id: I1a1343459c0a67393d22be3101cd8d269a2f26f0 Signed-off-by: Wuliangqing --- arch/arm64/boot/dts/rockchip/px30.dtsi | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 6b9adc6ba0c7..b958c5d08728 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -674,7 +674,8 @@ clocks = <&pmucru SCLK_UART0_PMU>, <&pmucru PCLK_UART0_PMU>; clock-names = "baudclk", "apb_pclk"; dmas = <&dmac 0>, <&dmac 1>; - dma-names = "tx", "rx"; + /*You can add it to enable dma*/ + /*dma-names = "tx", "rx";*/ reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; @@ -877,7 +878,8 @@ clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; clock-names = "baudclk", "apb_pclk"; dmas = <&dmac 2>, <&dmac 3>; - dma-names = "tx", "rx"; + /*You can add it to enable dma*/ + /*dma-names = "tx", "rx";*/ reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; @@ -892,7 +894,8 @@ clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; clock-names = "baudclk", "apb_pclk"; dmas = <&dmac 4>, <&dmac 5>; - dma-names = "tx", "rx"; + /*You can add it to enable dma*/ + /*dma-names = "tx", "rx";*/ reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; @@ -907,7 +910,8 @@ clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; clock-names = "baudclk", "apb_pclk"; dmas = <&dmac 6>, <&dmac 7>; - dma-names = "tx", "rx"; + /*You can add it to enable dma*/ + /*dma-names = "tx", "rx";*/ reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; @@ -922,7 +926,8 @@ clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>; clock-names = "baudclk", "apb_pclk"; dmas = <&dmac 8>, <&dmac 9>; - dma-names = "tx", "rx"; + /*You can add it to enable dma*/ + /*dma-names = "tx", "rx";*/ reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; @@ -937,7 +942,8 @@ clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>; clock-names = "baudclk", "apb_pclk"; dmas = <&dmac 10>, <&dmac 11>; - dma-names = "tx", "rx"; + /*You can add it to enable dma*/ + /*dma-names = "tx", "rx";*/ reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; From 59f45fdccdff18d97df9a9cc18e08c2fc1617ba2 Mon Sep 17 00:00:00 2001 From: Jason Zhu Date: Fri, 18 Nov 2022 10:26:45 +0800 Subject: [PATCH 095/235] ASoC: codecs: rv1106_codec: use interface set_sysclk to set clk Instead of setting clk by node mclk_cpu. Signed-off-by: Jason Zhu Change-Id: Ib54d219d4f0ad488722524aac7effb4b019d1b7e --- sound/soc/codecs/rv1106_codec.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/sound/soc/codecs/rv1106_codec.c b/sound/soc/codecs/rv1106_codec.c index d84dbff79fff..a16f64b5cf43 100644 --- a/sound/soc/codecs/rv1106_codec.c +++ b/sound/soc/codecs/rv1106_codec.c @@ -73,7 +73,6 @@ struct rv1106_codec_priv { struct regmap *grf; struct clk *pclk_acodec; struct clk *mclk_acodec; - struct clk *mclk_cpu; struct gpio_desc *pa_ctl_gpio; struct snd_soc_component *component; @@ -1607,11 +1606,29 @@ static void rv1106_pcm_shutdown(struct snd_pcm_substream *substream, regcache_sync(rv1106->regmap); } +static int rv1106_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct snd_soc_component *component = dai->component; + struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component); + int ret; + + if (!freq) + return 0; + + ret = clk_set_rate(rv1106->mclk_acodec, freq); + if (ret) + dev_err(&rv1106->dev, "Failed to set mclk %d\n", ret); + + return ret; +} + static const struct snd_soc_dai_ops rv1106_dai_ops = { .hw_params = rv1106_hw_params, .set_fmt = rv1106_set_dai_fmt, .mute_stream = rv1106_mute_stream, .shutdown = rv1106_pcm_shutdown, + .set_sysclk = rv1106_set_sysclk, }; static struct snd_soc_dai_driver rv1106_dai[] = { @@ -2075,11 +2092,6 @@ static int rv1106_platform_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(rv1106->mclk_acodec), "Can't get acodec mclk_acodec\n"); - rv1106->mclk_cpu = devm_clk_get(&pdev->dev, "mclk_cpu"); - if (IS_ERR(rv1106->mclk_cpu)) - return dev_err_probe(&pdev->dev, PTR_ERR(rv1106->mclk_cpu), - "Can't get acodec mclk_cpu\n"); - ret = rv1106_codec_sysfs_init(pdev, rv1106); if (ret < 0) return dev_err_probe(&pdev->dev, ret, "Sysfs init failed\n"); @@ -2106,15 +2118,6 @@ static int rv1106_platform_probe(struct platform_device *pdev) goto failed_1; } - /** - * In PERICRU_PERICLKSEL_CON08, the mclk_acodec_t/rx_div are div 4 - * by default, we need to calibrate once, make the div is 1 and keep - * the rate of mclk_acodec is the same with mclk_i2s. - * - * FIXME: need to handle div dynamically if the DSMAUDIO is enabled. - */ - clk_set_rate(rv1106->mclk_acodec, clk_get_rate(rv1106->mclk_cpu)); - rv1106_codec_check_micbias(rv1106, np); ret = rv1106_codec_adc_i2s_route(rv1106); From 7fdefc3445633e70ec43d5554ca790cdfd21f75e Mon Sep 17 00:00:00 2001 From: Jason Zhu Date: Fri, 18 Nov 2022 10:29:26 +0800 Subject: [PATCH 096/235] ARM: dts: rockchip: rv1106: delete unused clk info of acodec Signed-off-by: Jason Zhu Change-Id: Iadd90b902ca73b576ba6c1d8c6013dc6d9375709 --- arch/arm/boot/dts/rv1106.dtsi | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/rv1106.dtsi b/arch/arm/boot/dts/rv1106.dtsi index 54361446933e..95aa613423d7 100644 --- a/arch/arm/boot/dts/rv1106.dtsi +++ b/arch/arm/boot/dts/rv1106.dtsi @@ -810,10 +810,8 @@ compatible = "rockchip,rv1106-codec"; reg = <0xff480000 0x1000>; rockchip,grf = <&grf>; - clocks = <&cru PCLK_ACODEC>, - <&cru MCLK_ACODEC_TX>, - <&cru MCLK_I2S0_8CH_TX>; - clock-names = "pclk_acodec", "mclk_acodec", "mclk_cpu"; + clocks = <&cru PCLK_ACODEC>, <&cru MCLK_ACODEC_TX>; + clock-names = "pclk_acodec", "mclk_acodec"; resets = <&cru SRST_P_ACODEC>; reset-names = "acodec-reset"; acodec,micbias; From fe04d8bac2eed207a80a22fa10bb9fa826189b4d Mon Sep 17 00:00:00 2001 From: David Wu Date: Tue, 15 Nov 2022 14:55:37 +0800 Subject: [PATCH 097/235] ARM: dts: rockchip: rk3036: Change the property for emmc/sdio/sdmmc nodes Signed-off-by: David Wu Change-Id: I332b505d937eb97a26400ff9882b3d58401a00bf --- arch/arm/boot/dts/rk3036.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index ba17c1274f5a..08a284dc6673 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -386,6 +386,8 @@ interrupts = ; resets = <&cru SRST_MMC0>; reset-names = "reset"; + no-mmc; + no-sdio; status = "disabled"; }; @@ -400,6 +402,8 @@ interrupts = ; resets = <&cru SRST_SDIO>; reset-names = "reset"; + no-mmc; + no-sd; status = "disabled"; }; @@ -420,6 +424,8 @@ dma-names = "rx-tx"; fifo-depth = <0x100>; non-removable; + no-sdio; + no-sd; pinctrl-names = "default"; pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; resets = <&cru SRST_EMMC>; From ae4ab91e5ee644c83d625bb3f488601b164b62c6 Mon Sep 17 00:00:00 2001 From: Wang Panzhenzhuan Date: Sat, 19 Nov 2022 02:47:47 +0000 Subject: [PATCH 098/235] media: i2c: s5kjn1: fix low probability mipi error issue 1. add delays in setting to fix probability wrong reg writed. 2. add register setting readback check support. Signed-off-by: Wang Panzhenzhuan Change-Id: If74df1f175d09e63c33b47a63c321c024f70c6f2 --- drivers/media/i2c/s5kjn1.c | 64 +++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/s5kjn1.c b/drivers/media/i2c/s5kjn1.c index 8172cdfb2416..0fcc9d27017d 100644 --- a/drivers/media/i2c/s5kjn1.c +++ b/drivers/media/i2c/s5kjn1.c @@ -9,6 +9,9 @@ * V0.0X01.0X02 * 1. set binning output 32 pixel aligned. * 2. fix channel info omitted copy from user issue. + * V0.0X01.0X03 + * 1. add delays in setting to fix probability wrong reg write. + * 2. add register setting readback check support. */ //#define DEBUG #include @@ -34,7 +37,10 @@ #include #include "otp_eeprom.h" -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) + +/* verify default register values */ +//#define CHECK_REG_VALUE #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -184,9 +190,9 @@ static const struct regval s5kjn1_10bit_4080x3072_dphy_30fps_regs[] = { {0x6028, 0x4000}, // Init setting {0x6010, 0x0001}, - //p5 + {DELAY_MS, 5}, //Delay 5ms {0x6226, 0x0001}, - //p10 + {DELAY_MS, 10}, //Delay 10ms {0x6028, 0x2400}, //Global, Analog setting {0x602A, 0x1354}, @@ -510,9 +516,9 @@ static const struct regval s5kjn1_10bit_8128x6144_dphy_10fps_regs[] = { {0x6028, 0x4000}, // Init setting {0x6010, 0x0001}, - //p5 + {DELAY_MS, 5}, //Delay 5ms {0x6226, 0x0001}, - //p10 + {DELAY_MS, 10}, //Delay 10ms {0x6028, 0x2400}, //Global, Analog setting {0x11d2, 0x00FF}, //Global, Analog setting @@ -987,6 +993,46 @@ static int s5kjn1_read_reg(struct i2c_client *client, return 0; } +/* Check Register value */ +#ifdef CHECK_REG_VALUE +static int s5kjn1_reg_verify(struct i2c_client *client, + const struct regval *regs) +{ + u32 i; + int ret = 0; + u32 value; + + for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) { + if (regs[i].addr == 0x6028 && regs[i].val == 0x4000) { + ret = s5kjn1_write_reg(client, regs[i].addr, + S5KJN1_REG_VALUE_16BIT, regs[i].val); + if (ret) + dev_err(&client->dev, "%s failed !\n", __func__); + continue; + } else if (regs[i].addr == 0x6028 && regs[i].val == 0x2400) { + ret = s5kjn1_write_reg(client, 0x602C, + S5KJN1_REG_VALUE_16BIT, regs[i].val); + if (ret) + dev_err(&client->dev, "%s failed !\n", __func__); + continue; + } else if (regs[i].addr == 0x602A) { + ret = s5kjn1_write_reg(client, 0x602E, + S5KJN1_REG_VALUE_16BIT, regs[i].val); + if (ret) + dev_err(&client->dev, "%s failed !\n", __func__); + continue; + } + ret = s5kjn1_read_reg(client, regs[i].addr, + S5KJN1_REG_VALUE_16BIT, &value); + if (value != regs[i].val) { + dev_info(&client->dev, "%s: 0x%04x is 0x%x instead of 0x%x\n", + __func__, regs[i].addr, value, regs[i].val); + } + } + return ret; +} +#endif + static int s5kjn1_get_reso_dist(const struct s5kjn1_mode *mode, struct v4l2_mbus_framefmt *framefmt) { @@ -1481,6 +1527,14 @@ static int __s5kjn1_start_stream(struct s5kjn1 *s5kjn1) return ret; } +#ifdef CHECK_REG_VALUE + /* verify default values to make sure everything has */ + /* been written correctly as expected */ + dev_info(&s5kjn1->client->dev, "%s:Check register value!\n", __func__); + ret = s5kjn1_reg_verify(s5kjn1->client, s5kjn1->cur_mode->reg_list); + if (ret) + return ret; +#endif /* In case these controls are set before streaming */ ret = __v4l2_ctrl_handler_setup(&s5kjn1->ctrl_handler); if (ret) From 38a4540cd6e4fe30c4530571056d374272d78bc4 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 19 Jun 2021 15:53:18 -0500 Subject: [PATCH 099/235] BACKPORT: cifs: fix SMB1 error path in cifs_get_file_info_unix We were trying to fill in uninitialized file attributes in the error case. Addresses-Coverity: 139689 ("Uninitialized variables") Signed-off-by: Steve French (cherry picked from commit e39df24169a2ceb0d359eb3a05ff982711f2eb32) Change-Id: Id02f0a50c2ba3505bb8f5538f489e451c9423c0b Signed-off-by: Jianqun Xu --- fs/cifs/inode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index b11a919b9cab..b31a977522d2 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -360,9 +360,12 @@ cifs_get_file_info_unix(struct file *filp) } else if (rc == -EREMOTE) { cifs_create_dfs_fattr(&fattr, inode->i_sb); rc = 0; - } + } else + goto cifs_gfiunix_out; cifs_fattr_to_inode(inode, &fattr); + +cifs_gfiunix_out: free_xid(xid); return rc; } From ad1c79a5b779a8eabd70ce3f02bd280fe7eacd56 Mon Sep 17 00:00:00 2001 From: Jianlong Wang Date: Thu, 17 Nov 2022 10:35:01 +0800 Subject: [PATCH 100/235] ARM: dts: rockchip: rk312x-linux: enable mpp_srv node Change-Id: Ic226f8ccdb8cdb803fad3c6e450aeb9d0115ea82 Signed-off-by: Jianlong Wang --- .../boot/dts/rk3126c-evb-ddr3-v10-linux.dts | 78 +++++++++-------- .../boot/dts/rk3128-evb-ddr3-v10-linux.dts | 86 ++++++++++--------- 2 files changed, 86 insertions(+), 78 deletions(-) diff --git a/arch/arm/boot/dts/rk3126c-evb-ddr3-v10-linux.dts b/arch/arm/boot/dts/rk3126c-evb-ddr3-v10-linux.dts index 599b02d37bca..8f406ed7db2e 100644 --- a/arch/arm/boot/dts/rk3126c-evb-ddr3-v10-linux.dts +++ b/arch/arm/boot/dts/rk3126c-evb-ddr3-v10-linux.dts @@ -139,25 +139,6 @@ }; }; -&codec { - #sound-dai-cells = <0>; - spk-ctl-gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; - spk-mute-delay = <200>; - hp-mute-delay = <100>; - rk312x_for_mid = <0>; - is_rk3128 = <0>; - spk_volume = <25>; - hp_volume = <25>; - capture_volume = <26>; - gpio_debug = <1>; - codec_hp_det = <0>; - status = "okay"; -}; - -&cpu0 { - cpu-supply = <&vdd_arm>; -}; - &cif_new { status = "okay"; @@ -178,6 +159,25 @@ }; }; +&codec { + #sound-dai-cells = <0>; + spk-ctl-gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; + spk-mute-delay = <200>; + hp-mute-delay = <100>; + rk312x_for_mid = <0>; + is_rk3128 = <0>; + spk_volume = <25>; + hp_volume = <25>; + capture_volume = <26>; + gpio_debug = <1>; + codec_hp_det = <0>; + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vdd_arm>; +}; + &display_subsystem { status = "okay"; }; @@ -751,6 +751,10 @@ status = "okay"; }; +&mpp_srv { + status = "okay"; +}; + &nandc { status = "okay"; }; @@ -792,16 +796,6 @@ vref-supply = <&vccadc_ref>; }; -&sdmmc { - cap-mmc-highspeed; - supports-sd; - card-detect-delay = <800>; - ignore-pm-notify; - keep-power-in-suspend; - cd-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; /* CD GPIO */ - status = "disabled"; -}; - &sdio { bus-width = <4>; max-frequency = <50000000>; @@ -814,6 +808,16 @@ status = "okay"; }; +&sdmmc { + cap-mmc-highspeed; + supports-sd; + card-detect-delay = <800>; + ignore-pm-notify; + keep-power-in-suspend; + cd-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; /* CD GPIO */ + status = "disabled"; +}; + &tsadc { status = "okay"; }; @@ -849,6 +853,14 @@ status = "okay"; }; +&vdpu { + status = "okay"; +}; + +&vepu { + status = "okay"; +}; + &video_phy { status = "okay"; }; @@ -861,14 +873,6 @@ status = "okay"; }; -&vdpu { - status = "okay"; -}; - -&vepu { - status = "okay"; -}; - &vpu_mmu { status = "okay"; }; diff --git a/arch/arm/boot/dts/rk3128-evb-ddr3-v10-linux.dts b/arch/arm/boot/dts/rk3128-evb-ddr3-v10-linux.dts index 5766da0b5514..9a0a2f154fa8 100644 --- a/arch/arm/boot/dts/rk3128-evb-ddr3-v10-linux.dts +++ b/arch/arm/boot/dts/rk3128-evb-ddr3-v10-linux.dts @@ -242,6 +242,20 @@ }; }; +&cif_new { + status = "okay"; + + ports { + port@0 { + cif_in_bcam: endpoint@0 { + remote-endpoint = <&gc2145_out>; + vsync-active = <0>; + hsync-active = <1>; + }; + }; + }; +}; + &codec{ spk-ctl-gpios = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>; hp-ctl-gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_LOW>; @@ -264,20 +278,6 @@ cpu-supply = <&vdd_arm>; }; -&cif_new { - status = "okay"; - - ports { - port@0 { - cif_in_bcam: endpoint@0 { - remote-endpoint = <&gc2145_out>; - vsync-active = <0>; - hsync-active = <1>; - }; - }; - }; -}; - &display_subsystem { status = "okay"; }; @@ -785,6 +785,10 @@ #sound-dai-cells = <0>; }; +&mpp_srv { + status = "okay"; +}; + &pinctrl { codec{ spk_ctl_h: spk-ctl-h{ @@ -895,19 +899,6 @@ vref-supply = <&vcc_io>; }; -&sdmmc { - cap-mmc-highspeed; - cap-sd-highspeed; - supports-sd; - vmmc-supply = <&vcc_sdmmc>; - broken-cd; - card-detect-delay = <800>; - ignore-pm-notify; - keep-power-in-suspend; - cd-gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>; /* CD GPIO */ - status = "disabled"; -}; - &sdio { max-frequency = <50000000>; supports-sdio; @@ -923,6 +914,19 @@ status = "okay"; }; +&sdmmc { + cap-mmc-highspeed; + cap-sd-highspeed; + supports-sd; + vmmc-supply = <&vcc_sdmmc>; + broken-cd; + card-detect-delay = <800>; + ignore-pm-notify; + keep-power-in-suspend; + cd-gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>; /* CD GPIO */ + status = "disabled"; +}; + &spdif{ compatible = "rockchip,rk3188-spdif"; status = "okay"; @@ -931,12 +935,6 @@ #sound-dai-cells = <0>; }; -&uart0{ - pinctrl-names = "default"; - pinctrl-0 = <&uart0_xfer &uart0_cts>; - status = "okay"; -}; - &u2phy { status = "okay"; @@ -950,6 +948,12 @@ }; }; +&uart0{ + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer &uart0_cts>; + status = "okay"; +}; + &usb_host_ehci { status = "okay"; }; @@ -962,14 +966,6 @@ status = "okay"; }; -&vop { - status = "okay"; -}; - -&vop_mmu { - status = "okay"; -}; - &vdpu { status = "okay"; }; @@ -978,6 +974,14 @@ status = "okay"; }; +&vop { + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + &vpu_mmu { status = "okay"; }; From e361a115eb9098168be4c46528554a2206961374 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 14 Oct 2022 19:18:32 -0500 Subject: [PATCH 101/235] UPSTREAM: cifs: lease key is uninitialized in smb1 paths It is cleaner to set lease key to zero in the places where leases are not supported (smb1 can not return lease keys so the field was uninitialized). Addresses-Coverity: 1513994 ("Uninitialized scalar variable") Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French (cherry picked from commit 625b60d4f9517903ad499633776825e67fdb0c16) Signed-off-by: Jianqun Xu Change-Id: I0cef58f5169c3e2b2fbe427f2340c277174a2be0 --- fs/cifs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 0d7238cb45b5..7a67d47034e2 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -467,7 +467,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, struct tcon_link *tlink; struct cifs_tcon *tcon; struct TCP_Server_Info *server; - struct cifs_fid fid; + struct cifs_fid fid = {}; struct cifs_pending_open open; __u32 oplock; struct cifsFileInfo *file_info; From 13c8f4001f492ede943183bfc46654928f3b74c1 Mon Sep 17 00:00:00 2001 From: David Wu Date: Sat, 19 Nov 2022 18:59:49 +0800 Subject: [PATCH 102/235] ethernet: stmmac: dwmac: Enable xpcs_eee clock for sgmii mode If xpcs_eee clock was not enabled, the sgmii mode cannot work after suspend/resume. Signed-off-by: David Wu Change-Id: If187b8e3344553f2e7062c677b1a851a761b5a18 --- drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 46811926f5c4..05748b22deef 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -67,6 +67,7 @@ struct rk_priv_data { struct clk *pclk_mac; struct clk *clk_phy; struct clk *pclk_xpcs; + struct clk *clk_xpcs_eee; struct reset_control *phy_reset; @@ -1908,8 +1909,10 @@ static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat) bsp_priv->phy_iface == PHY_INTERFACE_MODE_QSGMII) { bsp_priv->pclk_xpcs = devm_clk_get(dev, "pclk_xpcs"); if (IS_ERR(bsp_priv->pclk_xpcs)) - dev_err(dev, "cannot get clock %s\n", - "pclk_xpcs"); + dev_err(dev, "cannot get clock %s\n", "pclk_xpcs"); + bsp_priv->clk_xpcs_eee = devm_clk_get(dev, "clk_xpcs_eee"); + if (IS_ERR(bsp_priv->clk_xpcs_eee)) + dev_err(dev, "cannot get clock %s\n", "clk_xpcs_eee"); } bsp_priv->clk_mac_speed = devm_clk_get(dev, "clk_mac_speed"); @@ -1977,6 +1980,9 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) if (!IS_ERR(bsp_priv->pclk_xpcs)) clk_prepare_enable(bsp_priv->pclk_xpcs); + if (!IS_ERR(bsp_priv->clk_xpcs_eee)) + clk_prepare_enable(bsp_priv->clk_xpcs_eee); + if (bsp_priv->ops && bsp_priv->ops->set_clock_selection) bsp_priv->ops->set_clock_selection(bsp_priv, bsp_priv->clock_input, true); @@ -2014,6 +2020,8 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) clk_disable_unprepare(bsp_priv->pclk_xpcs); + clk_disable_unprepare(bsp_priv->clk_xpcs_eee); + /** * if (!IS_ERR(bsp_priv->clk_mac)) * clk_disable_unprepare(bsp_priv->clk_mac); From 720d1c7da4527e40e8b23ee4e8380bd109fec14a Mon Sep 17 00:00:00 2001 From: David Wu Date: Sat, 19 Nov 2022 19:02:48 +0800 Subject: [PATCH 103/235] arm64: dts: rockchip: rk3568: Add xpcs_eee clk for gmac xpcs Signed-off-by: David Wu Change-Id: Iba2c79b343273751ea87f30be8f257a2539447c2 --- arch/arm64/boot/dts/rockchip/rk3568.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi index 82d3326351da..7f4b108684cc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi @@ -1774,12 +1774,12 @@ <&cru SCLK_GMAC1_RX_TX>, <&cru CLK_MAC1_REFOUT>, <&cru ACLK_GMAC1>, <&cru PCLK_GMAC1>, <&cru SCLK_GMAC1_RX_TX>, <&cru CLK_GMAC1_PTP_REF>, - <&cru PCLK_XPCS>; + <&cru PCLK_XPCS>, <&cru CLK_XPCS_EEE>; clock-names = "stmmaceth", "mac_clk_rx", "mac_clk_tx", "clk_mac_refout", "aclk_mac", "pclk_mac", "clk_mac_speed", "ptp_ref", - "pclk_xpcs"; + "pclk_xpcs", "clk_xpcs_eee"; resets = <&cru SRST_A_GMAC1>; reset-names = "stmmaceth"; @@ -2519,12 +2519,12 @@ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>, <&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>, - <&cru PCLK_XPCS>; + <&cru PCLK_XPCS>, <&cru CLK_XPCS_EEE>; clock-names = "stmmaceth", "mac_clk_rx", "mac_clk_tx", "clk_mac_refout", "aclk_mac", "pclk_mac", "clk_mac_speed", "ptp_ref", - "pclk_xpcs"; + "pclk_xpcs", "clk_xpcs_eee"; resets = <&cru SRST_A_GMAC0>; reset-names = "stmmaceth"; From 68f953fab3c73afb6949d54170cf725634b128c8 Mon Sep 17 00:00:00 2001 From: Jian Zheng Date: Tue, 8 Nov 2022 15:17:00 +0800 Subject: [PATCH 104/235] ARM: dts: rockchip: rv1106g-evb-v11-cvr: do not include rv1106-evb-ext-rgb-v10.dtsi Due to the reuse of pins on the evb board, wifi enable requires that rgb be temporarily turned off Signed-off-by: Jian Zheng Change-Id: I7f19d8d6ea80faee66dc1c44bb06b9e0d1507edf --- arch/arm/boot/dts/rv1106g-evb1-v11-cvr.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/rv1106g-evb1-v11-cvr.dts b/arch/arm/boot/dts/rv1106g-evb1-v11-cvr.dts index 035d2abd19ca..576559bcfb39 100644 --- a/arch/arm/boot/dts/rv1106g-evb1-v11-cvr.dts +++ b/arch/arm/boot/dts/rv1106g-evb1-v11-cvr.dts @@ -6,7 +6,6 @@ /dts-v1/; #include "rv1106g-evb1-v11.dts" -#include "rv1106-evb-ext-rgb-v10.dtsi" / { model = "Rockchip RV1106G EVB1 V11 Board For CVR"; From 84d08ffd326627d6de883af19610f8442eed2e8f Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Tue, 11 Oct 2022 17:50:41 +0800 Subject: [PATCH 105/235] media: i2c: add gc1084 support Signed-off-by: Lin Jinhan Change-Id: Idecacd6d217659a908de09517d10db02dd438478 --- drivers/media/i2c/Kconfig | 11 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/gc1084.c | 1275 ++++++++++++++++++++++++++++++++++++ 3 files changed, 1287 insertions(+) create mode 100644 drivers/media/i2c/gc1084.c diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index a94efb9a6bc0..5ed7c572bb86 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -920,6 +920,17 @@ config VIDEO_GC08A3 To compile this driver as a module, choose M here: the module will be called gc08a3. +config VIDEO_GC1084 + tristate "GalaxyCore GC1084 sensor support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT + select V4L2_FWNODE + help + Support for the GalaxyCore GC1084 sensor. + + To compile this driver as a module, choose M here: the + module will be called gc1084. + config VIDEO_GC2053 tristate "GalaxyCore GC2053 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index a366d81e5197..557ab737a7c3 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -173,6 +173,7 @@ obj-$(CONFIG_VIDEO_RK628) += rk628/ obj-$(CONFIG_VIDEO_AR0230) += ar0230.o obj-$(CONFIG_VIDEO_GC02M2) += gc02m2.o obj-$(CONFIG_VIDEO_GC08A3) += gc08a3.o +obj-$(CONFIG_VIDEO_GC1084) += gc1084.o obj-$(CONFIG_VIDEO_GC2053) += gc2053.o obj-$(CONFIG_VIDEO_GC2093) += gc2093.o obj-$(CONFIG_VIDEO_GC2145) += gc2145.o diff --git a/drivers/media/i2c/gc1084.c b/drivers/media/i2c/gc1084.c new file mode 100644 index 000000000000..d91da4fb401d --- /dev/null +++ b/drivers/media/i2c/gc1084.c @@ -0,0 +1,1275 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * gc1084 sensor driver + * + * Copyright (C) 2022 Rockchip Electronics Co., Ltd. + * + * V0.0X01.0X00 first version. + * V0.0X01.0X01 Add HDR support. + * V0.0X01.0X02 update sensor driver + * 1. fix linear mode ae flicker issue. + * 2. add hdr mode exposure limit issue. + * 3. fix hdr mode highlighting pink issue. + * 4. add some debug info. + */ +//#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define GC1084_NAME "gc1084" +#define GC1084_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG10_1X10 + +#define MIPI_FREQ_400M 400000000 + +#define GC1084_XVCLK_FREQ 27000000 + +#define GC1084_REG_CHIP_ID_H 0x03F0 +#define GC1084_REG_CHIP_ID_L 0x03F1 + +#define GC1084_REG_EXP_H 0x0d03 +#define GC1084_REG_EXP_L 0x0d04 + +#define GC1084_REG_VTS_H 0x0000 +#define GC1084_REG_VTS_L 0x0001 + +#define GC1084_REG_CTRL_MODE 0x003E +#define GC1084_MODE_SW_STANDBY 0x11 +#define GC1084_MODE_STREAMING 0x91 + +#define GC1084_CHIP_ID 0x1084 + +#define GC1084_VTS_MAX 0x3FFF +#define GC1084_HTS_MAX 0xFFF + +#define GC1084_EXPOSURE_MAX 0x3FFF +#define GC1084_EXPOSURE_MIN 1 +#define GC1084_EXPOSURE_STEP 1 + +#define GC1084_GAIN_MIN 0x40 +#define GC1084_GAIN_MAX 0x2000 +#define GC1084_GAIN_STEP 1 +#define GC1084_GAIN_DEFAULT 64 +#define REG_NULL 0xFFFF + +#define GC1084_LANES 1 + +static const char * const gc1084_supply_names[] = { + "dovdd", /* Digital I/O power */ + "avdd", /* Analog power */ + "dvdd", /* Digital power */ +}; + +#define GC1084_NUM_SUPPLIES ARRAY_SIZE(gc1084_supply_names) + +#define to_gc1084(sd) container_of(sd, struct gc1084, subdev) + +enum { + LINK_FREQ_400M_INDEX, +}; + +struct gain_reg_config { + u32 value; + u16 analog_gain; + u16 col_gain; + u16 reserved; +}; + +struct gc1084_mode { + u32 width; + u32 height; + struct v4l2_fract max_fps; + u32 hts_def; + u32 vts_def; + u32 exp_def; + u32 link_freq_index; + const struct reg_sequence *reg_list; + u32 reg_num; + u32 hdr_mode; + u32 vc[PAD_MAX]; +}; + +struct gc1084 { + struct device *dev; + struct clk *xvclk; + struct regmap *regmap; + struct gpio_desc *reset_gpio; + struct gpio_desc *pwdn_gpio; + struct regulator_bulk_data supplies[GC1084_NUM_SUPPLIES]; + + struct v4l2_subdev subdev; + struct media_pad pad; + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *anal_gain; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *h_flip; + struct v4l2_ctrl *v_flip; + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate; + + struct mutex lock; + bool streaming; + bool power_on; + unsigned int cfg_num; + const struct gc1084_mode *cur_mode; + + u32 module_index; + const char *module_facing; + const char *module_name; + const char *len_name; + u32 cur_vts; + + bool has_init_exp; + struct preisp_hdrae_exp_s init_hdrae_exp; +}; + +static const struct regmap_config gc1084_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .max_register = 0x1000, +}; + +static const s64 link_freq_menu_items[] = { + MIPI_FREQ_400M, +}; + +/* + * window size=1280*720 mipi@1lane + * mclk=27M mipi_clk=400Mbps + * pixel_line_total=2200 line_frame_total=1125 + * row_time=44.4444us frame_rate=30fps + */ +static const struct reg_sequence gc1084_1280x720_liner_settings[] = { + {0x03fe, 0xf0}, + {0x03fe, 0xf0}, + {0x03fe, 0xf0}, + {0x03fe, 0x00}, + {0x03f2, 0x00}, + {0x03f3, 0x00}, + {0x03f4, 0x36}, + {0x03f5, 0xc0}, + {0x03f6, 0x13}, + {0x03f7, 0x01}, + {0x03f8, 0x32}, + {0x03f9, 0x21}, + {0x03fc, 0xae}, + {0x0d05, 0x08}, + {0x0d06, 0xae}, + {0x0d08, 0x10}, + {0x0d0a, 0x02}, + {0x000c, 0x03}, + {0x0d0d, 0x02}, + {0x0d0e, 0xd4}, + {0x000f, 0x05}, + {0x0010, 0x08}, + {0x0017, 0x08}, + {0x0d73, 0x92}, + {0x0076, 0x00}, + {0x0d76, 0x00}, + {0x0d41, 0x02}, + {0x0d42, 0xee}, + {0x0d7a, 0x0a}, + {0x006b, 0x18}, + {0x0db0, 0x9d}, + {0x0db1, 0x00}, + {0x0db2, 0xac}, + {0x0db3, 0xd5}, + {0x0db4, 0x00}, + {0x0db5, 0x97}, + {0x0db6, 0x09}, + {0x00d2, 0xfc}, + {0x0d19, 0x31}, + {0x0d20, 0x40}, + {0x0d25, 0xcb}, + {0x0d27, 0x03}, + {0x0d29, 0x40}, + {0x0d43, 0x20}, + {0x0058, 0x60}, + {0x00d6, 0x66}, + {0x00d7, 0x19}, + {0x0093, 0x02}, + {0x00d9, 0x14}, + {0x00da, 0xc1}, + {0x0d2a, 0x00}, + {0x0d28, 0x04}, + {0x0dc2, 0x84}, + {0x0050, 0x30}, + {0x0080, 0x07}, + {0x008c, 0x05}, + {0x008d, 0xa8}, + {0x0077, 0x01}, + {0x0078, 0xee}, + {0x0079, 0x02}, + {0x0067, 0xc0}, + {0x0054, 0xff}, + {0x0055, 0x02}, + {0x0056, 0x00}, + {0x0057, 0x04}, + {0x005a, 0xff}, + {0x005b, 0x07}, + {0x00d5, 0x03}, + {0x0102, 0xa9}, + {0x0d03, 0x02}, + {0x0d04, 0xd0}, + {0x007a, 0x60}, + {0x04e0, 0xff}, + {0x0414, 0x75}, + {0x0415, 0x75}, + {0x0416, 0x75}, + {0x0417, 0x75}, + {0x0122, 0x00}, + {0x0121, 0x80}, + {0x0428, 0x10}, + {0x0429, 0x10}, + {0x042a, 0x10}, + {0x042b, 0x10}, + {0x042c, 0x14}, + {0x042d, 0x14}, + {0x042e, 0x18}, + {0x042f, 0x18}, + {0x0430, 0x05}, + {0x0431, 0x05}, + {0x0432, 0x05}, + {0x0433, 0x05}, + {0x0434, 0x05}, + {0x0435, 0x05}, + {0x0436, 0x05}, + {0x0437, 0x05}, + {0x0153, 0x00}, + {0x0190, 0x01}, + {0x0192, 0x02}, + {0x0194, 0x04}, + {0x0195, 0x02}, + {0x0196, 0xd0}, + {0x0197, 0x05}, + {0x0198, 0x00}, + {0x0201, 0x23}, + {0x0202, 0x53}, + {0x0203, 0xce}, + {0x0208, 0x39}, + {0x0212, 0x06}, + {0x0213, 0x40}, + {0x0215, 0x12}, + {0x0229, 0x05}, + {0x023e, 0x98}, + {0x031e, 0x3e}, +}; + +static const struct gc1084_mode supported_modes[] = { + { + .width = 1280, + .height = 720, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x460, + .hts_def = 0x898, + .vts_def = 0x465, + .link_freq_index = LINK_FREQ_400M_INDEX, + .reg_list = gc1084_1280x720_liner_settings, + .reg_num = ARRAY_SIZE(gc1084_1280x720_liner_settings), + .hdr_mode = NO_HDR, + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, + }, +}; + +/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ +/* * 2, to match suitable isp freq */ +static u64 to_pixel_rate(u32 index) +{ + u64 pixel_rate = link_freq_menu_items[index] * 2 * GC1084_LANES * 2; + + do_div(pixel_rate, 10); + + return pixel_rate; +} + +static inline int gc1084_read_reg(struct gc1084 *gc1084, u16 addr, u8 *value) +{ + unsigned int val; + int ret; + + ret = regmap_read(gc1084->regmap, addr, &val); + if (ret) { + dev_err(gc1084->dev, "i2c read failed at addr: %x\n", addr); + return ret; + } + + *value = val & 0xff; + + return 0; +} + +static inline int gc1084_write_reg(struct gc1084 *gc1084, u16 addr, u8 value) +{ + int ret; + + ret = regmap_write(gc1084->regmap, addr, value); + if (ret) { + dev_err(gc1084->dev, "i2c write failed at addr: %x\n", addr); + return ret; + } + + return ret; +} + +static const struct gain_reg_config gain_reg_configs[] = { + { 64, 0x0000, 0x0100, 0x0080}, + { 76, 0x0a00, 0x010b, 0x0080}, + { 90, 0x0001, 0x0119, 0x0080}, + { 106, 0x0a01, 0x012a, 0x0080}, + { 128, 0x0002, 0x0200, 0x0080}, + { 152, 0x0a02, 0x0217, 0x0080}, + { 179, 0x0003, 0x0233, 0x0080}, + { 212, 0x0a03, 0x0314, 0x0080}, + { 256, 0x0004, 0x0400, 0x0090}, + { 303, 0x0a04, 0x042f, 0x0090}, + { 358, 0x0005, 0x0526, 0x0090}, + { 425, 0x0a05, 0x0628, 0x0090}, + { 512, 0x0006, 0x0800, 0x00a0}, + { 607, 0x0a06, 0x091e, 0x00a0}, + { 716, 0x1246, 0x0b0c, 0x00a0}, + { 848, 0x1966, 0x0d10, 0x00a0}, + {1024, 0x4004, 0x1000, 0x00a0}, + {1214, 0x4a04, 0x123d, 0x00a0}, + {1434, 0x4005, 0x1619, 0x00b0}, + {1699, 0x4a05, 0x1a23, 0x00c0}, + {2048, 0x4006, 0x2000, 0x00c0}, + {2427, 0x4a06, 0x253b, 0x00c0}, + {2865, 0x5246, 0x2c30, 0x00c0}, + {3393, 0x5946, 0x3501, 0x00d0}, + {4096, 0x6006, 0x3f3f, 0x00e0}, +}; + +static int gc1084_set_gain(struct gc1084 *gc1084, u32 gain) +{ + int ret, i = 0; + u16 pre_gain = 0; + + for (i = 0; i < ARRAY_SIZE(gain_reg_configs) - 1; i++) + if ((gain_reg_configs[i].value <= gain) && (gain < gain_reg_configs[i+1].value)) + break; + + ret = gc1084_write_reg(gc1084, 0x00d1, (gain_reg_configs[i].analog_gain >> 8) & 0x3f); + ret |= gc1084_write_reg(gc1084, 0x00d0, gain_reg_configs[i].analog_gain & 0xff); + + ret |= gc1084_write_reg(gc1084, 0x031d, 0x2e); + + ret |= gc1084_write_reg(gc1084, 0x0dc1, (gain_reg_configs[i].analog_gain >> 14) & 1); + + ret |= gc1084_write_reg(gc1084, 0x031d, 0x28); + + ret |= gc1084_write_reg(gc1084, 0x0155, gain_reg_configs[i].reserved & 0xff); + + ret |= gc1084_write_reg(gc1084, 0x00b8, gain_reg_configs[i].col_gain >> 8); + ret |= gc1084_write_reg(gc1084, 0x00b9, gain_reg_configs[i].col_gain & 0xff); + + pre_gain = 64 * gain / gain_reg_configs[i].value; + + ret |= gc1084_write_reg(gc1084, 0x00b1, (pre_gain >> 6)); + ret |= gc1084_write_reg(gc1084, 0x00b2, ((pre_gain & 0x3f) << 2)); + + return ret; +} + +static int gc1084_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct gc1084 *gc1084 = container_of(ctrl->handler, + struct gc1084, ctrl_handler); + s64 max; + int ret = 0; + u32 vts = 0; + + /* Propagate change of current control to all related controls */ + switch (ctrl->id) { + case V4L2_CID_VBLANK: + /* Update max exposure while meeting expected vblanking */ + max = gc1084->cur_mode->height + ctrl->val - 4; + __v4l2_ctrl_modify_range(gc1084->exposure, + gc1084->exposure->minimum, max, + gc1084->exposure->step, + gc1084->exposure->default_value); + break; + } + if (!pm_runtime_get_if_in_use(gc1084->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + if (gc1084->cur_mode->hdr_mode != NO_HDR) + goto ctrl_end; + dev_dbg(gc1084->dev, "set exposure value 0x%x\n", ctrl->val); + ret = gc1084_write_reg(gc1084, GC1084_REG_EXP_H, + (ctrl->val >> 8) & 0x3f); + ret |= gc1084_write_reg(gc1084, GC1084_REG_EXP_L, + ctrl->val & 0xff); + break; + case V4L2_CID_ANALOGUE_GAIN: + if (gc1084->cur_mode->hdr_mode != NO_HDR) + goto ctrl_end; + dev_dbg(gc1084->dev, "set gain value 0x%x\n", ctrl->val); + gc1084_set_gain(gc1084, ctrl->val); + break; + case V4L2_CID_VBLANK: + vts = gc1084->cur_mode->height + ctrl->val; + gc1084->cur_vts = vts; + ret = gc1084_write_reg(gc1084, GC1084_REG_VTS_H, + (vts >> 8) & 0x3f); + ret |= gc1084_write_reg(gc1084, GC1084_REG_VTS_L, + vts & 0xff); + dev_dbg(gc1084->dev, " set blank value 0x%x\n", ctrl->val); + break; + default: + dev_warn(gc1084->dev, "%s Unhandled id:0x%x, val:0x%x\n", + __func__, ctrl->id, ctrl->val); + break; + } + +ctrl_end: + pm_runtime_put(gc1084->dev); + return ret; +} + +static const struct v4l2_ctrl_ops gc1084_ctrl_ops = { + .s_ctrl = gc1084_set_ctrl, +}; + +static int gc1084_get_regulators(struct gc1084 *gc1084) +{ + unsigned int i; + + for (i = 0; i < GC1084_NUM_SUPPLIES; i++) + gc1084->supplies[i].supply = gc1084_supply_names[i]; + + return devm_regulator_bulk_get(gc1084->dev, + GC1084_NUM_SUPPLIES, + gc1084->supplies); +} + +static int gc1084_initialize_controls(struct gc1084 *gc1084) +{ + const struct gc1084_mode *mode; + struct v4l2_ctrl_handler *handler; + s64 exposure_max, vblank_def; + u32 h_blank; + int ret; + + handler = &gc1084->ctrl_handler; + mode = gc1084->cur_mode; + ret = v4l2_ctrl_handler_init(handler, 8); + if (ret) + return ret; + handler->lock = &gc1084->lock; + + gc1084->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, + ARRAY_SIZE(link_freq_menu_items) - 1, 0, + link_freq_menu_items); + + gc1084->pixel_rate = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, + 0, to_pixel_rate(LINK_FREQ_400M_INDEX), + 1, to_pixel_rate(LINK_FREQ_400M_INDEX)); + + h_blank = mode->hts_def - mode->width; + gc1084->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK, + h_blank, h_blank, 1, h_blank); + if (gc1084->hblank) + gc1084->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + vblank_def = mode->vts_def - mode->height; + gc1084->cur_vts = mode->vts_def; + gc1084->vblank = v4l2_ctrl_new_std(handler, &gc1084_ctrl_ops, + V4L2_CID_VBLANK, vblank_def, + GC1084_VTS_MAX - mode->height, + 1, vblank_def); + + exposure_max = mode->vts_def - 4; + gc1084->exposure = v4l2_ctrl_new_std(handler, &gc1084_ctrl_ops, + V4L2_CID_EXPOSURE, GC1084_EXPOSURE_MIN, + exposure_max, GC1084_EXPOSURE_STEP, + mode->exp_def); + + gc1084->anal_gain = v4l2_ctrl_new_std(handler, &gc1084_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, GC1084_GAIN_MIN, + GC1084_GAIN_MAX, GC1084_GAIN_STEP, + GC1084_GAIN_DEFAULT); + + gc1084->h_flip = v4l2_ctrl_new_std(handler, &gc1084_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + + gc1084->v_flip = v4l2_ctrl_new_std(handler, &gc1084_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + + if (handler->error) { + ret = handler->error; + dev_err(gc1084->dev, "Failed to init controls(%d)\n", ret); + goto err_free_handler; + } + + gc1084->subdev.ctrl_handler = handler; + gc1084->has_init_exp = false; + + return 0; + +err_free_handler: + v4l2_ctrl_handler_free(handler); + return ret; +} + +static int __gc1084_power_on(struct gc1084 *gc1084) +{ + int ret; + struct device *dev = gc1084->dev; + + ret = clk_set_rate(gc1084->xvclk, GC1084_XVCLK_FREQ); + if (ret < 0) + dev_warn(dev, "Failed to set xvclk rate\n"); + + if (clk_get_rate(gc1084->xvclk) != GC1084_XVCLK_FREQ) + dev_warn(dev, "xvclk mismatched, modes are based on 27MHz\n"); + + ret = clk_prepare_enable(gc1084->xvclk); + if (ret < 0) { + dev_err(dev, "Failed to enable xvclk\n"); + return ret; + } + + ret = regulator_bulk_enable(GC1084_NUM_SUPPLIES, gc1084->supplies); + if (ret < 0) { + dev_err(dev, "Failed to enable regulators\n"); + goto disable_clk; + } + + if (!IS_ERR(gc1084->reset_gpio)) + gpiod_set_value_cansleep(gc1084->reset_gpio, 1); + + usleep_range(1000, 2000); + + if (!IS_ERR(gc1084->pwdn_gpio)) + gpiod_set_value_cansleep(gc1084->pwdn_gpio, 1); + if (!IS_ERR(gc1084->reset_gpio)) + gpiod_set_value_cansleep(gc1084->reset_gpio, 0); + + usleep_range(10000, 20000); + + return 0; + +disable_clk: + clk_disable_unprepare(gc1084->xvclk); + return ret; +} + +static void __gc1084_power_off(struct gc1084 *gc1084) +{ + if (!IS_ERR(gc1084->reset_gpio)) + gpiod_set_value_cansleep(gc1084->reset_gpio, 1); + if (!IS_ERR(gc1084->pwdn_gpio)) + gpiod_set_value_cansleep(gc1084->pwdn_gpio, 0); + + regulator_bulk_disable(GC1084_NUM_SUPPLIES, gc1084->supplies); + clk_disable_unprepare(gc1084->xvclk); +} + +static int gc1084_check_sensor_id(struct gc1084 *gc1084) +{ + u8 id_h = 0, id_l = 0; + u16 id = 0; + int ret = 0; + + ret = gc1084_read_reg(gc1084, GC1084_REG_CHIP_ID_H, &id_h); + ret |= gc1084_read_reg(gc1084, GC1084_REG_CHIP_ID_L, &id_l); + if (ret) { + dev_err(gc1084->dev, "Failed to read sensor id, (%d)\n", ret); + return ret; + } + + id = id_h << 8 | id_l; + if (id != GC1084_CHIP_ID) { + dev_err(gc1084->dev, "sensor id: %04X mismatched\n", id); + return -ENODEV; + } + + dev_info(gc1084->dev, "Detected GC1084 sensor\n"); + return 0; +} + +static void gc1084_get_module_inf(struct gc1084 *gc1084, + struct rkmodule_inf *inf) +{ + memset(inf, 0, sizeof(*inf)); + strlcpy(inf->base.lens, gc1084->len_name, sizeof(inf->base.lens)); + strlcpy(inf->base.sensor, GC1084_NAME, sizeof(inf->base.sensor)); + strlcpy(inf->base.module, gc1084->module_name, sizeof(inf->base.module)); +} + +static long gc1084_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct gc1084 *gc1084 = to_gc1084(sd); + struct rkmodule_hdr_cfg *hdr_cfg; + long ret = 0; + u32 stream = 0; + u64 delay_us = 0; + u32 fps = 0; + + switch (cmd) { + case RKMODULE_GET_HDR_CFG: + hdr_cfg = (struct rkmodule_hdr_cfg *)arg; + hdr_cfg->esp.mode = HDR_NORMAL_VC; + hdr_cfg->hdr_mode = gc1084->cur_mode->hdr_mode; + break; + case RKMODULE_GET_MODULE_INFO: + gc1084_get_module_inf(gc1084, (struct rkmodule_inf *)arg); + break; + case RKMODULE_SET_QUICK_STREAM: + + stream = *((u32 *)arg); + + if (stream) { + ret = gc1084_write_reg(gc1084, GC1084_REG_CTRL_MODE, + GC1084_MODE_STREAMING); + } else { + ret = gc1084_write_reg(gc1084, GC1084_REG_CTRL_MODE, + GC1084_MODE_SW_STANDBY); + fps = gc1084->cur_mode->max_fps.denominator / + gc1084->cur_mode->max_fps.numerator; + delay_us = 1000000 / (gc1084->cur_mode->vts_def * fps / gc1084->cur_vts); + usleep_range(delay_us, delay_us + 2000); + } + break; + default: + ret = -ENOIOCTLCMD; + break; + } + return ret; +} + +static int __gc1084_start_stream(struct gc1084 *gc1084) +{ + int ret; + + ret = regmap_multi_reg_write(gc1084->regmap, + gc1084->cur_mode->reg_list, + gc1084->cur_mode->reg_num); + if (ret) + return ret; + + /* Apply customized control from user */ + mutex_unlock(&gc1084->lock); + v4l2_ctrl_handler_setup(&gc1084->ctrl_handler); + mutex_lock(&gc1084->lock); + + if (gc1084->has_init_exp && gc1084->cur_mode->hdr_mode != NO_HDR) { + ret = gc1084_ioctl(&gc1084->subdev, PREISP_CMD_SET_HDRAE_EXP, + &gc1084->init_hdrae_exp); + if (ret) { + dev_err(gc1084->dev, "init exp fail in hdr mode\n"); + return ret; + } + } + + return gc1084_write_reg(gc1084, GC1084_REG_CTRL_MODE, + GC1084_MODE_STREAMING); +} + +static int __gc1084_stop_stream(struct gc1084 *gc1084) +{ + gc1084->has_init_exp = false; + return gc1084_write_reg(gc1084, GC1084_REG_CTRL_MODE, + GC1084_MODE_SW_STANDBY); +} + +#ifdef CONFIG_COMPAT +static long gc1084_compat_ioctl32(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + void __user *up = compat_ptr(arg); + struct rkmodule_inf *inf; + struct rkmodule_hdr_cfg *hdr; + struct preisp_hdrae_exp_s *hdrae; + long ret = 0; + u32 stream = 0; + + switch (cmd) { + case RKMODULE_GET_MODULE_INFO: + inf = kzalloc(sizeof(*inf), GFP_KERNEL); + if (!inf) { + ret = -ENOMEM; + return ret; + } + + ret = gc1084_ioctl(sd, cmd, inf); + if (!ret) { + ret = copy_to_user(up, inf, sizeof(*inf)); + if (ret) + ret = -EFAULT; + } + kfree(inf); + break; + case RKMODULE_GET_HDR_CFG: + hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); + if (!hdr) { + ret = -ENOMEM; + return ret; + } + + ret = gc1084_ioctl(sd, cmd, hdr); + if (!ret) { + ret = copy_to_user(up, hdr, sizeof(*hdr)); + if (ret) + ret = -EFAULT; + } + kfree(hdr); + break; + case RKMODULE_SET_HDR_CFG: + hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); + if (!hdr) { + ret = -ENOMEM; + return ret; + } + + ret = copy_from_user(hdr, up, sizeof(*hdr)); + if (!ret) + ret = gc1084_ioctl(sd, cmd, hdr); + else + ret = -EFAULT; + kfree(hdr); + break; + case PREISP_CMD_SET_HDRAE_EXP: + hdrae = kzalloc(sizeof(*hdrae), GFP_KERNEL); + if (!hdrae) { + ret = -ENOMEM; + return ret; + } + + ret = copy_from_user(hdrae, up, sizeof(*hdrae)); + if (!ret) + ret = gc1084_ioctl(sd, cmd, hdrae); + else + ret = -EFAULT; + kfree(hdrae); + break; + case RKMODULE_SET_QUICK_STREAM: + ret = copy_from_user(&stream, up, sizeof(u32)); + if (!ret) + ret = gc1084_ioctl(sd, cmd, &stream); + else + ret = -EFAULT; + break; + default: + ret = -ENOIOCTLCMD; + break; + } + return ret; +} +#endif + +static int gc1084_s_stream(struct v4l2_subdev *sd, int on) +{ + struct gc1084 *gc1084 = to_gc1084(sd); + int ret = 0; + unsigned int fps; + unsigned int delay_us; + + fps = DIV_ROUND_CLOSEST(gc1084->cur_mode->max_fps.denominator, + gc1084->cur_mode->max_fps.numerator); + + dev_info(gc1084->dev, "%s: on: %d, %dx%d@%d\n", __func__, on, + gc1084->cur_mode->width, + gc1084->cur_mode->height, + fps); + + mutex_lock(&gc1084->lock); + on = !!on; + if (on == gc1084->streaming) + goto unlock_and_return; + + if (on) { + ret = pm_runtime_get_sync(gc1084->dev); + if (ret < 0) { + pm_runtime_put_noidle(gc1084->dev); + goto unlock_and_return; + } + + ret = __gc1084_start_stream(gc1084); + if (ret) { + dev_err(gc1084->dev, "Failed to start gc1084 stream\n"); + pm_runtime_put(gc1084->dev); + goto unlock_and_return; + } + } else { + __gc1084_stop_stream(gc1084); + /* delay to enable oneframe complete */ + delay_us = 1000 * 1000 / fps; + usleep_range(delay_us, delay_us+10); + dev_info(gc1084->dev, "%s: on: %d, sleep(%dus)\n", + __func__, on, delay_us); + + pm_runtime_put(gc1084->dev); + } + + gc1084->streaming = on; + +unlock_and_return: + mutex_unlock(&gc1084->lock); + return 0; +} + +static int gc1084_g_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct gc1084 *gc1084 = to_gc1084(sd); + const struct gc1084_mode *mode = gc1084->cur_mode; + + mutex_lock(&gc1084->lock); + fi->interval = mode->max_fps; + mutex_unlock(&gc1084->lock); + + return 0; +} + +static int gc1084_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, + struct v4l2_mbus_config *config) +{ + struct gc1084 *gc1084 = to_gc1084(sd); + u32 val = 1 << (GC1084_LANES - 1) | V4L2_MBUS_CSI2_CHANNEL_0 | + V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; + + config->type = V4L2_MBUS_CSI2_DPHY; + config->flags = (gc1084->cur_mode->hdr_mode == NO_HDR) ? + val : (val | V4L2_MBUS_CSI2_CHANNEL_1); + + return 0; +} + +static int gc1084_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index != 0) + return -EINVAL; + code->code = GC1084_MEDIA_BUS_FMT; + return 0; +} + +static int gc1084_enum_frame_sizes(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct gc1084 *gc1084 = to_gc1084(sd); + + if (fse->index >= gc1084->cfg_num) + return -EINVAL; + + if (fse->code != GC1084_MEDIA_BUS_FMT) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = supported_modes[fse->index].width; + fse->max_height = supported_modes[fse->index].height; + fse->min_height = supported_modes[fse->index].height; + return 0; +} + +static int gc1084_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct gc1084 *gc1084 = to_gc1084(sd); + + if (fie->index >= gc1084->cfg_num) + return -EINVAL; + + fie->code = GC1084_MEDIA_BUS_FMT; + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + fie->reserved[0] = supported_modes[fie->index].hdr_mode; + return 0; +} + +static int gc1084_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct gc1084 *gc1084 = to_gc1084(sd); + const struct gc1084_mode *mode; + s64 h_blank, vblank_def; + + mutex_lock(&gc1084->lock); + + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), + width, height, + fmt->format.width, fmt->format.height); + + fmt->format.code = GC1084_MEDIA_BUS_FMT; + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.field = V4L2_FIELD_NONE; + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; +#else + mutex_unlock(&gc1084->lock); + return -ENOTTY; +#endif + } else { + gc1084->cur_mode = mode; + __v4l2_ctrl_s_ctrl(gc1084->link_freq, mode->link_freq_index); + __v4l2_ctrl_s_ctrl_int64(gc1084->pixel_rate, + to_pixel_rate(mode->link_freq_index)); + h_blank = mode->hts_def - mode->width; + __v4l2_ctrl_modify_range(gc1084->hblank, h_blank, + h_blank, 1, h_blank); + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(gc1084->vblank, vblank_def, + GC1084_VTS_MAX - mode->height, + 1, vblank_def); + } + + mutex_unlock(&gc1084->lock); + return 0; +} + +static int gc1084_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct gc1084 *gc1084 = to_gc1084(sd); + const struct gc1084_mode *mode = gc1084->cur_mode; + + mutex_lock(&gc1084->lock); + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad); +#else + mutex_unlock(&gc1084->lock); + return -ENOTTY; +#endif + } else { + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.code = GC1084_MEDIA_BUS_FMT; + fmt->format.field = V4L2_FIELD_NONE; + + /* format info: width/height/data type/virctual channel */ + if (fmt->pad < PAD_MAX && mode->hdr_mode != NO_HDR) + fmt->reserved[0] = mode->vc[fmt->pad]; + else + fmt->reserved[0] = mode->vc[PAD0]; + + } + mutex_unlock(&gc1084->lock); + return 0; +} + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static int gc1084_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct gc1084 *gc1084 = to_gc1084(sd); + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->pad, 0); + const struct gc1084_mode *def_mode = &supported_modes[0]; + + mutex_lock(&gc1084->lock); + /* Initialize try_fmt */ + try_fmt->width = def_mode->width; + try_fmt->height = def_mode->height; + try_fmt->code = GC1084_MEDIA_BUS_FMT; + try_fmt->field = V4L2_FIELD_NONE; + mutex_unlock(&gc1084->lock); + + return 0; +} +#endif + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static const struct v4l2_subdev_internal_ops gc1084_internal_ops = { + .open = gc1084_open, +}; +#endif + +static int gc1084_s_power(struct v4l2_subdev *sd, int on) +{ + struct gc1084 *gc1084 = to_gc1084(sd); + int ret = 0; + + mutex_lock(&gc1084->lock); + + if (gc1084->power_on == !!on) + goto unlock_and_return; + + if (on) { + ret = pm_runtime_get_sync(gc1084->dev); + if (ret < 0) { + pm_runtime_put_noidle(gc1084->dev); + goto unlock_and_return; + } + gc1084->power_on = true; + } else { + pm_runtime_put(gc1084->dev); + gc1084->power_on = false; + } + +unlock_and_return: + mutex_unlock(&gc1084->lock); + + return ret; +} + +static const struct v4l2_subdev_core_ops gc1084_core_ops = { + .s_power = gc1084_s_power, + .ioctl = gc1084_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = gc1084_compat_ioctl32, +#endif +}; + +static const struct v4l2_subdev_video_ops gc1084_video_ops = { + .s_stream = gc1084_s_stream, + .g_frame_interval = gc1084_g_frame_interval, +}; + +static const struct v4l2_subdev_pad_ops gc1084_pad_ops = { + .enum_mbus_code = gc1084_enum_mbus_code, + .enum_frame_size = gc1084_enum_frame_sizes, + .enum_frame_interval = gc1084_enum_frame_interval, + .get_fmt = gc1084_get_fmt, + .set_fmt = gc1084_set_fmt, + .get_mbus_config = gc1084_g_mbus_config, +}; + +static const struct v4l2_subdev_ops gc1084_subdev_ops = { + .core = &gc1084_core_ops, + .video = &gc1084_video_ops, + .pad = &gc1084_pad_ops, +}; + +static int gc1084_runtime_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct gc1084 *gc1084 = to_gc1084(sd); + + __gc1084_power_on(gc1084); + return 0; +} + +static int gc1084_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct gc1084 *gc1084 = to_gc1084(sd); + + __gc1084_power_off(gc1084); + return 0; +} + +static const struct dev_pm_ops gc1084_pm_ops = { + SET_RUNTIME_PM_OPS(gc1084_runtime_suspend, + gc1084_runtime_resume, NULL) +}; + +static int gc1084_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct device_node *node = dev->of_node; + struct gc1084 *gc1084; + struct v4l2_subdev *sd; + char facing[2]; + int ret; + + dev_info(dev, "driver version: %02x.%02x.%02x", + DRIVER_VERSION >> 16, + (DRIVER_VERSION & 0xff00) >> 8, + DRIVER_VERSION & 0x00ff); + + gc1084 = devm_kzalloc(dev, sizeof(*gc1084), GFP_KERNEL); + if (!gc1084) + return -ENOMEM; + + gc1084->dev = dev; + gc1084->regmap = devm_regmap_init_i2c(client, &gc1084_regmap_config); + if (IS_ERR(gc1084->regmap)) { + dev_err(dev, "Failed to initialize I2C\n"); + return -ENODEV; + } + + ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, + &gc1084->module_index); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, + &gc1084->module_facing); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME, + &gc1084->module_name); + ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME, + &gc1084->len_name); + if (ret) { + dev_err(dev, "Failed to get module information\n"); + return -EINVAL; + } + + gc1084->xvclk = devm_clk_get(gc1084->dev, "xvclk"); + if (IS_ERR(gc1084->xvclk)) { + dev_err(gc1084->dev, "Failed to get xvclk\n"); + return -EINVAL; + } + + gc1084->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(gc1084->reset_gpio)) + dev_warn(dev, "Failed to get reset-gpios\n"); + + gc1084->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_HIGH); + if (IS_ERR(gc1084->pwdn_gpio)) + dev_warn(dev, "Failed to get pwdn-gpios\n"); + + ret = gc1084_get_regulators(gc1084); + if (ret) { + dev_err(dev, "Failed to get regulators\n"); + return ret; + } + + mutex_init(&gc1084->lock); + + /* set default mode */ + gc1084->cur_mode = &supported_modes[0]; + gc1084->cfg_num = ARRAY_SIZE(supported_modes); + gc1084->cur_vts = gc1084->cur_mode->vts_def; + + sd = &gc1084->subdev; + v4l2_i2c_subdev_init(sd, client, &gc1084_subdev_ops); + ret = gc1084_initialize_controls(gc1084); + if (ret) + goto err_destroy_mutex; + + ret = __gc1084_power_on(gc1084); + if (ret) + goto err_free_handler; + + ret = gc1084_check_sensor_id(gc1084); + if (ret) + goto err_power_off; + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + sd->internal_ops = &gc1084_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; +#endif + +#ifdef CONFIG_MEDIA_CONTROLLER + gc1084->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&sd->entity, 1, &gc1084->pad); + if (ret < 0) + goto err_power_off; +#endif + + memset(facing, 0, sizeof(facing)); + if (strcmp(gc1084->module_facing, "back") == 0) + facing[0] = 'b'; + else + facing[0] = 'f'; + + snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", + gc1084->module_index, facing, + GC1084_NAME, dev_name(sd->dev)); + + ret = v4l2_async_register_subdev_sensor_common(sd); + if (ret) { + dev_err(dev, "Failed to register v4l2 async subdev\n"); + goto err_clean_entity; + } + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_idle(dev); + + return 0; + +err_clean_entity: +#ifdef CONFIG_MEDIA_CONTROLLER + media_entity_cleanup(&sd->entity); +#endif +err_power_off: + __gc1084_power_off(gc1084); +err_free_handler: + v4l2_ctrl_handler_free(&gc1084->ctrl_handler); +err_destroy_mutex: + mutex_destroy(&gc1084->lock); + + return ret; +} + +static int gc1084_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct gc1084 *gc1084 = to_gc1084(sd); + + v4l2_async_unregister_subdev(sd); +#ifdef CONFIG_MEDIA_CONTROLLER + media_entity_cleanup(&sd->entity); +#endif + v4l2_ctrl_handler_free(&gc1084->ctrl_handler); + mutex_destroy(&gc1084->lock); + + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + __gc1084_power_off(gc1084); + pm_runtime_set_suspended(&client->dev); + return 0; +} + +static const struct i2c_device_id gc1084_match_id[] = { + { "gc1084", 0 }, + { }, +}; + +static const struct of_device_id gc1084_of_match[] = { + { .compatible = "galaxycore,gc1084" }, + {}, +}; +MODULE_DEVICE_TABLE(of, gc1084_of_match); + +static struct i2c_driver gc1084_i2c_driver = { + .driver = { + .name = GC1084_NAME, + .pm = &gc1084_pm_ops, + .of_match_table = of_match_ptr(gc1084_of_match), + }, + .probe = &gc1084_probe, + .remove = &gc1084_remove, + .id_table = gc1084_match_id, +}; + +static int __init sensor_mod_init(void) +{ + return i2c_add_driver(&gc1084_i2c_driver); +} +static void __exit sensor_mod_exit(void) +{ + i2c_del_driver(&gc1084_i2c_driver); +} + +device_initcall_sync(sensor_mod_init); +module_exit(sensor_mod_exit); + +MODULE_DESCRIPTION("Galaxycore GC1084 Image Sensor driver"); +MODULE_LICENSE("GPL v2"); From f13dae5b9cf4db5c5328d8451a4af741cc048e7b Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Wed, 16 Nov 2022 20:37:32 +0800 Subject: [PATCH 106/235] video: rockchip: rga3: iommu device uses slave mode Signed-off-by: Yu Qiaowei Change-Id: I1ab682d3ee687ae13ba4d7c252d1d9ec25875efd --- .../rockchip/rga3/include/rga2_reg_info.h | 2 - drivers/video/rockchip/rga3/rga2_reg_info.c | 20 +++++++--- drivers/video/rockchip/rga3/rga3_reg_info.c | 40 ++++++++++++------- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/drivers/video/rockchip/rga3/include/rga2_reg_info.h b/drivers/video/rockchip/rga3/include/rga2_reg_info.h index 4c134793d744..37afb7640f8a 100644 --- a/drivers/video/rockchip/rga3/include/rga2_reg_info.h +++ b/drivers/video/rockchip/rga3/include/rga2_reg_info.h @@ -4,8 +4,6 @@ #include "rga_drv.h" -#define RGA2_USE_MASTER_MODE 1 - #define RGA2_SYS_REG_BASE 0x000 #define RGA2_CSC_REG_BASE 0x060 #define RGA2_CMD_REG_BASE 0x100 diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index 0d433138bbd0..2310f70cad8d 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -167,10 +167,6 @@ static void RGA2_set_mode_ctrl(u8 *base, struct rga2_req *msg) if (msg->render_mode == 4) render_mode = 3; - /* In slave mode, the current frame completion interrupt must be enabled. */ - if (!RGA2_USE_MASTER_MODE) - msg->CMD_fin_int_enable = 1; - reg = ((reg & (~m_RGA2_MODE_CTRL_SW_RENDER_MODE)) | (s_RGA2_MODE_CTRL_SW_RENDER_MODE(render_mode))); @@ -2268,6 +2264,10 @@ static int rga2_init_reg(struct rga_job *job) } } + /* In slave mode, the current frame completion interrupt must be enabled. */ + if (scheduler->data->mmu == RGA_IOMMU) + req.CMD_fin_int_enable = 1; + if (rga2_gen_reg_info((uint8_t *)job->cmd_reg, &req) == -1) { pr_err("gen reg info error\n"); return -EINVAL; @@ -2411,9 +2411,19 @@ static void rga2_set_reg_full_csc(struct rga_job *job, struct rga_scheduler_t *s static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) { int i; + bool master_mode_en; uint32_t sys_ctrl; ktime_t now = ktime_get(); + /* + * Currently there is no iova allocated for storing cmd for the IOMMU device, + * so the iommu device needs to use the slave mode. + */ + if (scheduler->data->mmu != RGA_IOMMU) + master_mode_en = true; + else + master_mode_en = false; + if (job->pre_intr_info.enable) rga2_set_pre_intr_reg(job, scheduler); @@ -2444,7 +2454,7 @@ static int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) m_RGA2_SYS_CTRL_RST_PROTECT_P | m_RGA2_SYS_CTRL_DST_WR_OPT_DIS | m_RGA2_SYS_CTRL_SRC0YUV420SP_RD_OPT_DIS; - if (RGA2_USE_MASTER_MODE) { + if (master_mode_en) { /* master mode */ sys_ctrl |= s_RGA2_SYS_CTRL_CMD_MODE(1); diff --git a/drivers/video/rockchip/rga3/rga3_reg_info.c b/drivers/video/rockchip/rga3/rga3_reg_info.c index efb579b6b532..3fac6dbf3cfc 100644 --- a/drivers/video/rockchip/rga3/rga3_reg_info.c +++ b/drivers/video/rockchip/rga3/rga3_reg_info.c @@ -8,6 +8,7 @@ #define pr_fmt(fmt) "rga3_reg: " fmt #include "rga3_reg_info.h" +#include "rga_dma_buf.h" #include "rga_common.h" #include "rga_debugger.h" #include "rga_hw_config.h" @@ -1899,9 +1900,19 @@ static void rga3_dump_read_back_reg(struct rga_scheduler_t *scheduler) static int rga3_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) { int i; + bool master_mode_en; uint32_t sys_ctrl; ktime_t now = ktime_get(); + /* + * Currently there is no iova allocated for storing cmd for the IOMMU device, + * so the iommu device needs to use the slave mode. + */ + if (scheduler->data->mmu != RGA_IOMMU) + master_mode_en = true; + else + master_mode_en = false; + if (DEBUGGER_EN(REG)) { uint32_t *p; @@ -1917,24 +1928,25 @@ static int rga3_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler) rga_write(m_RGA3_INT_FRM_DONE | m_RGA3_INT_CMD_LINE_FINISH | m_RGA3_INT_ERROR_MASK, RGA3_INT_EN, scheduler); -#if 0 - /* master mode */ - sys_ctrl = s_RGA3_SYS_CTRL_CMD_MODE(1); + if (master_mode_en) { + /* master mode */ + sys_ctrl = s_RGA3_SYS_CTRL_CMD_MODE(1); - rga_dma_flush_range(&job->cmd_reg[0], &job->cmd_reg[50], scheduler); + /* cmd buffer flush cache to ddr */ + rga_dma_sync_flush_range(&job->cmd_reg[0], &job->cmd_reg[50], scheduler); - rga_write(virt_to_phys(job->cmd_reg), RGA3_CMD_ADDR, scheduler); - rga_write(sys_ctrl, RGA3_SYS_CTRL, scheduler); - rga_write(m_RGA3_CMD_CTRL_CMD_LINE_ST_P, RGA3_CMD_CTRL, scheduler); -#else - /* slave mode */ - sys_ctrl = s_RGA3_SYS_CTRL_CMD_MODE(0) | m_RGA3_SYS_CTRL_RGA_SART; + rga_write(virt_to_phys(job->cmd_reg), RGA3_CMD_ADDR, scheduler); + rga_write(sys_ctrl, RGA3_SYS_CTRL, scheduler); + rga_write(m_RGA3_CMD_CTRL_CMD_LINE_ST_P, RGA3_CMD_CTRL, scheduler); + } else { + /* slave mode */ + sys_ctrl = s_RGA3_SYS_CTRL_CMD_MODE(0) | m_RGA3_SYS_CTRL_RGA_SART; - for (i = 0; i <= 50; i++) - rga_write(job->cmd_reg[i], 0x100 + i * 4, scheduler); + for (i = 0; i <= 50; i++) + rga_write(job->cmd_reg[i], 0x100 + i * 4, scheduler); - rga_write(sys_ctrl, RGA3_SYS_CTRL, scheduler); -#endif + rga_write(sys_ctrl, RGA3_SYS_CTRL, scheduler); + } if (DEBUGGER_EN(REG)) { pr_info("sys_ctrl = 0x%x, int_en = 0x%x, int_raw = 0x%x\n", From 96e93dba44de78a6e09dd0323bd87b97e18a3667 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Mon, 21 Nov 2022 10:10:06 +0800 Subject: [PATCH 107/235] video: rockchip: rga3: fix misconfiguration of updating lut table mode Signed-off-by: Yu Qiaowei Change-Id: I120b57fcb2c190a3e9cba7cb49ecbb0035e498ea --- drivers/video/rockchip/rga3/rga2_reg_info.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index 2310f70cad8d..7bc277a0b85a 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -164,8 +164,8 @@ static void RGA2_set_mode_ctrl(u8 *base, struct rga2_req *msg) bRGA_MODE_CTL = (u32 *) (base + RGA2_MODE_CTRL_OFFSET); - if (msg->render_mode == 4) - render_mode = 3; + if (msg->render_mode == UPDATE_PALETTE_TABLE_MODE) + render_mode = 0x3; reg = ((reg & (~m_RGA2_MODE_CTRL_SW_RENDER_MODE)) | From 034aad5dd8fa7429dfa069cd3505f22b2f4d7208 Mon Sep 17 00:00:00 2001 From: Zhen Chen Date: Thu, 13 Oct 2022 08:42:04 +0800 Subject: [PATCH 108/235] MALI: rockchip: upgrade bifrost DDK to g15p0-01eac0, from g13p0-01eac0 Note, the corresponding mali_csffw.bin for DDK g15 MUST be used. Change-Id: Ic30634fa6247d62bf96f506c64d13b89e16b02e6 Signed-off-by: Zhen Chen --- Documentation/ABI/testing/sysfs-device-mali | 1 + .../devicetree/bindings/arm/mali-bifrost.txt | 4 +- drivers/base/arm/Kbuild | 3 +- drivers/base/arm/Kconfig | 12 +- drivers/base/arm/Makefile | 37 +- drivers/base/arm/Mconfig | 18 +- .../base/arm/dma_buf_lock/src/dma_buf_lock.c | 908 ------------- .../base/arm/dma_buf_test_exporter/build.bp | 4 +- .../dma-buf-test-exporter.c | 5 +- .../base/arm/memory_group_manager/build.bp | 4 +- .../memory_group_manager.c | 22 +- .../arm/protected_memory_allocator/build.bp | 4 +- drivers/gpu/arm/bifrost/Kbuild | 36 +- drivers/gpu/arm/bifrost/Kconfig | 19 +- drivers/gpu/arm/bifrost/Makefile | 42 +- drivers/gpu/arm/bifrost/Mconfig | 31 +- .../arm/bifrost/arbiter/mali_kbase_arbif.c | 13 +- drivers/gpu/arm/bifrost/arbitration/Kconfig | 49 - .../gpu/arm/bifrost/arbitration/ptm/Kconfig | 28 - drivers/gpu/arm/bifrost/backend/gpu/Kbuild | 2 +- .../gpu/mali_kbase_cache_policy_backend.c | 51 +- .../gpu/mali_kbase_cache_policy_backend.h | 21 +- .../backend/gpu/mali_kbase_instr_defs.h | 4 +- .../backend/gpu/mali_kbase_irq_linux.c | 3 +- .../bifrost/backend/gpu/mali_kbase_jm_hw.c | 7 +- .../bifrost/backend/gpu/mali_kbase_jm_rb.c | 2 +- .../backend/gpu/mali_kbase_model_dummy.c | 804 +++++++----- .../gpu/mali_kbase_model_error_generator.c | 15 +- .../backend/gpu/mali_kbase_pm_backend.c | 2 +- .../bifrost/backend/gpu/mali_kbase_pm_ca.c | 29 +- .../backend/gpu/mali_kbase_pm_driver.c | 196 ++- .../backend/gpu/mali_kbase_pm_internal.h | 31 + .../backend/gpu/mali_kbase_pm_metrics.c | 2 + drivers/gpu/arm/bifrost/build.bp | 22 +- .../context/backend/mali_kbase_context_csf.c | 3 +- .../context/backend/mali_kbase_context_jm.c | 5 +- .../arm/bifrost/context/mali_kbase_context.c | 8 +- drivers/gpu/arm/bifrost/csf/Kbuild | 8 +- .../ipa_control/mali_kbase_csf_ipa_control.c | 41 +- .../ipa_control/mali_kbase_csf_ipa_control.h | 29 +- drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c | 586 ++++++--- .../bifrost/csf/mali_kbase_csf_csg_debugfs.c | 227 +++- .../gpu/arm/bifrost/csf/mali_kbase_csf_defs.h | 198 ++- .../arm/bifrost/csf/mali_kbase_csf_event.c | 11 +- .../arm/bifrost/csf/mali_kbase_csf_firmware.c | 315 +++-- .../arm/bifrost/csf/mali_kbase_csf_firmware.h | 78 +- .../bifrost/csf/mali_kbase_csf_firmware_cfg.c | 26 +- .../bifrost/csf/mali_kbase_csf_firmware_log.c | 451 +++++++ .../bifrost/csf/mali_kbase_csf_firmware_log.h | 74 ++ .../csf/mali_kbase_csf_firmware_no_mali.c | 62 +- .../csf/mali_kbase_csf_heap_context_alloc.c | 10 +- .../gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c | 196 +-- .../gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.h | 4 + .../bifrost/csf/mali_kbase_csf_registers.h | 30 +- .../bifrost/csf/mali_kbase_csf_reset_gpu.c | 77 +- .../bifrost/csf/mali_kbase_csf_scheduler.c | 804 +++++++++--- .../bifrost/csf/mali_kbase_csf_scheduler.h | 22 +- .../bifrost/csf/mali_kbase_csf_tiler_heap.c | 1143 +++++++++++++---- .../bifrost/csf/mali_kbase_csf_tiler_heap.h | 37 +- .../csf/mali_kbase_csf_tiler_heap_def.h | 44 +- .../csf/mali_kbase_csf_tiler_heap_reclaim.c | 367 ++++++ .../csf/mali_kbase_csf_tiler_heap_reclaim.h | 80 ++ .../bifrost/csf/mali_kbase_csf_tl_reader.c | 15 +- .../bifrost/csf/mali_kbase_csf_trace_buffer.c | 145 +-- .../bifrost/csf/mali_kbase_csf_trace_buffer.h | 23 +- .../bifrost/csf/mali_kbase_debug_csf_fault.c | 271 ++++ .../bifrost/csf/mali_kbase_debug_csf_fault.h | 137 ++ .../mali_kbase_debug_ktrace_codes_csf.h | 37 + .../mali_kbase_debug_linux_ktrace_csf.h | 23 + .../debug/mali_kbase_debug_ktrace_codes.h | 7 +- .../debug/mali_kbase_debug_linux_ktrace.h | 5 +- .../device/backend/mali_kbase_device_csf.c | 76 +- .../device/backend/mali_kbase_device_hw_csf.c | 17 +- .../device/backend/mali_kbase_device_jm.c | 6 +- .../arm/bifrost/device/mali_kbase_device.c | 12 +- .../arm/bifrost/device/mali_kbase_device.h | 6 +- .../arm/bifrost/device/mali_kbase_device_hw.c | 36 +- .../gpu/backend/mali_kbase_gpu_fault_jm.c | 4 +- .../gpu/backend/mali_kbase_gpu_regmap_csf.h | 13 +- .../gpu/backend/mali_kbase_gpu_regmap_jm.h | 21 +- .../arm/bifrost/gpu/mali_kbase_gpu_regmap.h | 120 +- .../src => gpu/arm/bifrost/hwcnt}/Kbuild | 20 +- .../backend}/mali_kbase_hwcnt_backend.h | 48 +- .../backend}/mali_kbase_hwcnt_backend_csf.c | 668 ++++------ .../backend}/mali_kbase_hwcnt_backend_csf.h | 51 +- .../mali_kbase_hwcnt_backend_csf_if.h | 69 +- .../mali_kbase_hwcnt_backend_csf_if_fw.c | 296 ++--- .../mali_kbase_hwcnt_backend_csf_if_fw.h | 11 +- .../backend}/mali_kbase_hwcnt_backend_jm.c | 303 ++--- .../backend}/mali_kbase_hwcnt_backend_jm.h | 12 +- .../mali_kbase_hwcnt_backend_jm_watchdog.c | 58 +- .../mali_kbase_hwcnt_backend_jm_watchdog.h | 6 +- .../bifrost/{ => hwcnt}/mali_kbase_hwcnt.c | 125 +- .../mali_kbase_hwcnt_accumulator.h | 24 +- .../{ => hwcnt}/mali_kbase_hwcnt_context.h | 13 +- .../{ => hwcnt}/mali_kbase_hwcnt_gpu.c | 219 ++-- .../{ => hwcnt}/mali_kbase_hwcnt_gpu.h | 51 +- .../{ => hwcnt}/mali_kbase_hwcnt_gpu_narrow.c | 129 +- .../{ => hwcnt}/mali_kbase_hwcnt_gpu_narrow.h | 97 +- .../{ => hwcnt}/mali_kbase_hwcnt_types.c | 302 ++--- .../{ => hwcnt}/mali_kbase_hwcnt_types.h | 297 ++--- .../mali_kbase_hwcnt_virtualizer.c | 240 ++-- .../mali_kbase_hwcnt_virtualizer.h | 43 +- .../mali_kbase_hwcnt_watchdog_if.h | 17 +- .../mali_kbase_hwcnt_watchdog_if_timer.c | 43 +- .../mali_kbase_hwcnt_watchdog_if_timer.h | 8 +- .../mali_kbase_ipa_counter_common_jm.h | 4 +- .../ipa/backend/mali_kbase_ipa_counter_csf.c | 5 +- .../ipa/backend/mali_kbase_ipa_counter_jm.c | 10 - drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h | 4 +- .../arm/bifrost/ipa/mali_kbase_ipa_simple.c | 4 + .../gpu/arm/bifrost/jm/mali_kbase_jm_defs.h | 80 +- .../arm/bifrost/mali_base_hwconfig_features.h | 13 + .../arm/bifrost/mali_base_hwconfig_issues.h | 30 + drivers/gpu/arm/bifrost/mali_kbase.h | 6 +- .../gpu/arm/bifrost/mali_kbase_core_linux.c | 457 ++++--- .../gpu/arm/bifrost/mali_kbase_ctx_sched.c | 4 +- .../arm/bifrost/mali_kbase_debug_mem_allocs.c | 138 ++ .../bifrost/mali_kbase_debug_mem_allocs.h} | 37 +- .../arm/bifrost/mali_kbase_debug_mem_view.h | 4 +- drivers/gpu/arm/bifrost/mali_kbase_defs.h | 151 ++- .../gpu/arm/bifrost/mali_kbase_dma_fence.c | 491 ------- .../gpu/arm/bifrost/mali_kbase_dma_fence.h | 150 --- drivers/gpu/arm/bifrost/mali_kbase_fence.c | 94 +- drivers/gpu/arm/bifrost/mali_kbase_fence.h | 128 +- drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c | 12 +- drivers/gpu/arm/bifrost/mali_kbase_hw.c | 18 + drivers/gpu/arm/bifrost/mali_kbase_jd.c | 268 +--- .../gpu/arm/bifrost/mali_kbase_jd_debugfs.c | 51 +- drivers/gpu/arm/bifrost/mali_kbase_js.c | 10 +- .../gpu/arm/bifrost/mali_kbase_kinstr_jm.c | 26 +- .../arm/bifrost/mali_kbase_kinstr_prfcnt.c | 19 +- .../arm/bifrost/mali_kbase_kinstr_prfcnt.h | 4 +- drivers/gpu/arm/bifrost/mali_kbase_mem.c | 315 +++-- drivers/gpu/arm/bifrost/mali_kbase_mem.h | 286 ++++- .../gpu/arm/bifrost/mali_kbase_mem_linux.c | 449 +++++-- .../gpu/arm/bifrost/mali_kbase_mem_linux.h | 68 +- .../gpu/arm/bifrost/mali_kbase_mem_migrate.c | 350 +++++ .../gpu/arm/bifrost/mali_kbase_mem_migrate.h | 94 ++ drivers/gpu/arm/bifrost/mali_kbase_mem_pool.c | 195 ++- .../arm/bifrost/mali_kbase_mem_pool_group.c | 29 +- .../arm/bifrost/mali_kbase_mem_pool_group.h | 7 +- drivers/gpu/arm/bifrost/mali_kbase_pbha.c | 66 +- .../gpu/arm/bifrost/mali_kbase_pbha_debugfs.c | 95 +- .../arm/bifrost/mali_kbase_platform_fake.c | 11 +- drivers/gpu/arm/bifrost/mali_kbase_pm.c | 4 +- .../gpu/arm/bifrost/mali_kbase_reset_gpu.h | 12 + drivers/gpu/arm/bifrost/mali_kbase_softjobs.c | 66 +- drivers/gpu/arm/bifrost/mali_kbase_sync.h | 5 +- .../gpu/arm/bifrost/mali_kbase_sync_android.c | 514 -------- .../gpu/arm/bifrost/mali_kbase_sync_file.c | 150 ++- drivers/gpu/arm/bifrost/mali_kbase_vinstr.c | 21 +- drivers/gpu/arm/bifrost/mali_malisw.h | 12 +- .../bifrost/mmu/backend/mali_kbase_mmu_csf.c | 5 + .../bifrost/mmu/backend/mali_kbase_mmu_jm.c | 1 + drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.c | 862 +++++++------ drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.h | 1 + .../bifrost/mmu/mali_kbase_mmu_hw_direct.c | 65 +- .../bifrost/mmu/mali_kbase_mmu_mode_aarch64.c | 35 +- .../arm/bifrost/platform/devicetree/Kbuild | 1 - .../devicetree/mali_kbase_config_platform.c | 43 - .../devicetree/mali_kbase_config_platform.h | 3 +- .../devicetree/mali_kbase_runtime_pm.c | 6 +- .../platform/meson/mali_kbase_runtime_pm.c | 2 +- drivers/gpu/arm/bifrost/tests/Mconfig | 16 +- drivers/gpu/arm/bifrost/tests/build.bp | 4 +- .../kernel/mali_kutf_clk_rate_trace_test.c | 2 +- .../mali_kutf_irq_test_main.c | 7 +- .../mali_kutf_mgm_integration_test/build.bp | 2 +- drivers/gpu/arm/bifrost/tl/Kbuild | 2 +- .../gpu/arm/bifrost/tl/mali_kbase_timeline.c | 168 +-- .../gpu/arm/bifrost/tl/mali_kbase_timeline.h | 8 + .../arm/bifrost/tl/mali_kbase_timeline_io.c | 136 +- .../arm/bifrost/tl/mali_kbase_timeline_priv.h | 27 +- .../arm/bifrost/tl/mali_kbase_tracepoints.c | 134 +- .../arm/bifrost/tl/mali_kbase_tracepoints.h | 156 +-- .../linux/mali_arbiter_interface.h | 2 +- include/linux/memory_group_manager.h | 16 +- include/linux/version_compat_defs.h | 16 + .../arm/bifrost/csf/mali_base_csf_kernel.h | 2 + .../csf/mali_kbase_csf_errors_dumpfault.h | 81 ++ .../arm/bifrost/csf/mali_kbase_csf_ioctl.h | 80 +- .../gpu/backend/mali_kbase_gpu_regmap_csf.h | 27 +- .../gpu/backend/mali_kbase_gpu_regmap_jm.h | 24 +- .../gpu/arm/bifrost/gpu/mali_kbase_gpu_id.h | 2 + .../arm/bifrost/gpu/mali_kbase_gpu_regmap.h | 61 +- .../gpu/arm/bifrost/jm/mali_base_jm_kernel.h | 4 + .../gpu/arm/bifrost/jm/mali_kbase_jm_ioctl.h | 8 +- .../uapi/gpu/arm/bifrost/mali_base_kernel.h | 59 - .../gpu/arm/bifrost/mali_kbase_hwcnt_reader.h | 6 + .../uapi/gpu/arm/bifrost/mali_kbase_ioctl.h | 46 - .../mali_kbase_mem_profile_debugfs_buf_size.h | 7 +- 192 files changed, 10415 insertions(+), 8170 deletions(-) delete mode 100644 drivers/base/arm/dma_buf_lock/src/dma_buf_lock.c delete mode 100644 drivers/gpu/arm/bifrost/arbitration/Kconfig delete mode 100644 drivers/gpu/arm/bifrost/arbitration/ptm/Kconfig create mode 100644 drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_log.c create mode 100644 drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_log.h create mode 100644 drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_reclaim.c create mode 100644 drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_reclaim.h create mode 100644 drivers/gpu/arm/bifrost/csf/mali_kbase_debug_csf_fault.c create mode 100644 drivers/gpu/arm/bifrost/csf/mali_kbase_debug_csf_fault.h rename drivers/{base/arm/dma_buf_lock/src => gpu/arm/bifrost/hwcnt}/Kbuild (53%) rename drivers/gpu/arm/bifrost/{ => hwcnt/backend}/mali_kbase_hwcnt_backend.h (85%) rename drivers/gpu/arm/bifrost/{ => hwcnt/backend}/mali_kbase_hwcnt_backend_csf.c (76%) rename drivers/gpu/arm/bifrost/{ => hwcnt/backend}/mali_kbase_hwcnt_backend_csf.h (77%) rename drivers/gpu/arm/bifrost/{ => hwcnt/backend}/mali_kbase_hwcnt_backend_csf_if.h (85%) rename drivers/gpu/arm/bifrost/{ => hwcnt/backend}/mali_kbase_hwcnt_backend_csf_if_fw.c (73%) rename drivers/gpu/arm/bifrost/{ => hwcnt/backend}/mali_kbase_hwcnt_backend_csf_if_fw.h (82%) rename drivers/gpu/arm/bifrost/{ => hwcnt/backend}/mali_kbase_hwcnt_backend_jm.c (73%) rename drivers/gpu/arm/bifrost/{ => hwcnt/backend}/mali_kbase_hwcnt_backend_jm.h (84%) rename drivers/gpu/arm/bifrost/{ => hwcnt/backend}/mali_kbase_hwcnt_backend_jm_watchdog.c (97%) rename drivers/gpu/arm/bifrost/{ => hwcnt/backend}/mali_kbase_hwcnt_backend_jm_watchdog.h (94%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt.c (87%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_accumulator.h (90%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_context.h (95%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_gpu.c (78%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_gpu.h (92%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_gpu_narrow.c (68%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_gpu_narrow.h (84%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_types.c (56%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_types.h (84%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_virtualizer.c (75%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_virtualizer.h (83%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_watchdog_if.h (84%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_watchdog_if_timer.c (76%) rename drivers/gpu/arm/bifrost/{ => hwcnt}/mali_kbase_hwcnt_watchdog_if_timer.h (85%) create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_debug_mem_allocs.c rename drivers/{base/arm/dma_buf_lock/src/dma_buf_lock.h => gpu/arm/bifrost/mali_kbase_debug_mem_allocs.h} (56%) delete mode 100644 drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c delete mode 100644 drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem_migrate.c create mode 100644 drivers/gpu/arm/bifrost/mali_kbase_mem_migrate.h delete mode 100644 drivers/gpu/arm/bifrost/mali_kbase_sync_android.c delete mode 100644 drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.c rename drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbiter_interface.h => include/linux/mali_arbiter_interface.h (99%) create mode 100644 include/uapi/gpu/arm/bifrost/csf/mali_kbase_csf_errors_dumpfault.h rename drivers/base/arm/dma_buf_lock/src/build.bp => include/uapi/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_csf.h (67%) rename {drivers => include/uapi}/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h (88%) diff --git a/Documentation/ABI/testing/sysfs-device-mali b/Documentation/ABI/testing/sysfs-device-mali index b7be50338f6e..cd011dae9b50 100644 --- a/Documentation/ABI/testing/sysfs-device-mali +++ b/Documentation/ABI/testing/sysfs-device-mali @@ -236,6 +236,7 @@ Description: 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/Documentation/devicetree/bindings/arm/mali-bifrost.txt b/Documentation/devicetree/bindings/arm/mali-bifrost.txt index 04e1bd1a5a39..2b3b1d028ccd 100644 --- a/Documentation/devicetree/bindings/arm/mali-bifrost.txt +++ b/Documentation/devicetree/bindings/arm/mali-bifrost.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2013-2021 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2013-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 @@ -129,7 +129,7 @@ for details. set and the setting coresponding to the SYSC_ALLOC register. -Example for a Mali GPU with 1 clock and no regulators: +Example for a Mali GPU with 1 clock and 1 regulator: gpu@0xfc010000 { compatible = "arm,malit602", "arm,malit60x", "arm,malit6xx", "arm,mali-midgard"; diff --git a/drivers/base/arm/Kbuild b/drivers/base/arm/Kbuild index 01de13bef37c..e5ded4cf7395 100644 --- a/drivers/base/arm/Kbuild +++ b/drivers/base/arm/Kbuild @@ -1,6 +1,6 @@ # 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 @@ -28,7 +28,6 @@ subdir-ccflags-y += $(ccflags-y) # # Kernel modules # -obj-$(CONFIG_DMA_BUF_LOCK) += dma_buf_lock/src/ obj-$(CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER) += dma_buf_test_exporter/ obj-$(CONFIG_MALI_MEMORY_GROUP_MANAGER) += memory_group_manager/ obj-$(CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR) += protected_memory_allocator/ diff --git a/drivers/base/arm/Kconfig b/drivers/base/arm/Kconfig index e5fca3a39ccb..7f9f1d4c418a 100644 --- a/drivers/base/arm/Kconfig +++ b/drivers/base/arm/Kconfig @@ -1,6 +1,6 @@ # 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 @@ -26,16 +26,6 @@ menuconfig MALI_BASE_MODULES Those modules provide extra features or debug interfaces and, are optional for the use of the Mali GPU modules. -config DMA_BUF_LOCK - bool "Build dma-buf lock module" - depends on MALI_BASE_MODULES && MALI_DMA_FENCE - default y - help - This option will build the dma_buf_lock module. - - Modules: - - dma_buf_lock.ko - config DMA_SHARED_BUFFER_TEST_EXPORTER bool "Build dma-buf framework test exporter module" depends on MALI_BASE_MODULES && DMA_SHARED_BUFFER diff --git a/drivers/base/arm/Makefile b/drivers/base/arm/Makefile index ed5c118a5ef4..c1a61a1106d0 100644 --- a/drivers/base/arm/Makefile +++ b/drivers/base/arm/Makefile @@ -38,11 +38,9 @@ ifeq ($(CONFIG_MALI_BASE_MODULES),y) CONFIG_MALI_CSF_SUPPORT ?= n ifneq ($(CONFIG_DMA_SHARED_BUFFER),n) - CONFIG_DMA_BUF_LOCK ?= y CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER ?= y else # Prevent misuse when CONFIG_DMA_SHARED_BUFFER=n - CONFIG_DMA_BUF_LOCK = n CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER = n endif @@ -54,7 +52,6 @@ ifeq ($(CONFIG_MALI_BASE_MODULES),y) else # Prevent misuse when CONFIG_MALI_BASE_MODULES=n - CONFIG_DMA_BUF_LOCK = n CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER = n CONFIG_MALI_MEMORY_GROUP_MANAGER = n CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR = n @@ -64,10 +61,9 @@ endif CONFIGS := \ CONFIG_MALI_BASE_MODULES \ CONFIG_MALI_CSF_SUPPORT \ - CONFIG_DMA_BUF_LOCK \ CONFIG_DMA_SHARED_BUFFER_TEST_EXPORTER \ CONFIG_MALI_MEMORY_GROUP_MANAGER \ - CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR + CONFIG_MALI_PROTECTED_MEMORY_ALLOCATOR \ # @@ -92,26 +88,47 @@ EXTRA_CFLAGS := $(foreach config,$(CONFIGS), \ $(if $(filter y m,$(value $(value config))), \ -D$(value config)=1)) -# The following were added to align with W=1 in scripts/Makefile.extrawarn -# from the Linux source tree KBUILD_CFLAGS += -Wall -Werror + +# The following were added to align with W=1 in scripts/Makefile.extrawarn +# from the Linux source tree (v5.18.14) KBUILD_CFLAGS += -Wextra -Wunused -Wno-unused-parameter KBUILD_CFLAGS += -Wmissing-declarations KBUILD_CFLAGS += -Wmissing-format-attribute KBUILD_CFLAGS += -Wmissing-prototypes KBUILD_CFLAGS += -Wold-style-definition -KBUILD_CFLAGS += -Wmissing-include-dirs +# The -Wmissing-include-dirs cannot be enabled as the path to some of the +# included directories change depending on whether it is an in-tree or +# out-of-tree build. KBUILD_CFLAGS += $(call cc-option, -Wunused-but-set-variable) KBUILD_CFLAGS += $(call cc-option, -Wunused-const-variable) KBUILD_CFLAGS += $(call cc-option, -Wpacked-not-aligned) KBUILD_CFLAGS += $(call cc-option, -Wstringop-truncation) # The following turn off the warnings enabled by -Wextra -KBUILD_CFLAGS += -Wno-missing-field-initializers KBUILD_CFLAGS += -Wno-sign-compare -KBUILD_CFLAGS += -Wno-type-limits +KBUILD_CFLAGS += -Wno-shift-negative-value +# This flag is needed to avoid build errors on older kernels +KBUILD_CFLAGS += $(call cc-option, -Wno-cast-function-type) KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN1 +# The following were added to align with W=2 in scripts/Makefile.extrawarn +# from the Linux source tree (v5.18.14) +KBUILD_CFLAGS += -Wdisabled-optimization +# The -Wshadow flag cannot be enabled unless upstream kernels are +# patched to fix redefinitions of certain built-in functions and +# global variables. +KBUILD_CFLAGS += $(call cc-option, -Wlogical-op) +KBUILD_CFLAGS += -Wmissing-field-initializers +KBUILD_CFLAGS += -Wtype-limits +KBUILD_CFLAGS += $(call cc-option, -Wmaybe-uninitialized) +KBUILD_CFLAGS += $(call cc-option, -Wunused-macros) + +KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN2 + +# This warning is disabled to avoid build failures in some kernel versions +KBUILD_CFLAGS += -Wno-ignored-qualifiers + all: $(MAKE) -C $(KDIR) M=$(CURDIR) $(MAKE_ARGS) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" modules diff --git a/drivers/base/arm/Mconfig b/drivers/base/arm/Mconfig index a48df6d8b090..f7787f0ccd34 100644 --- a/drivers/base/arm/Mconfig +++ b/drivers/base/arm/Mconfig @@ -1,6 +1,6 @@ # 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 @@ -26,16 +26,6 @@ menuconfig MALI_BASE_MODULES Those modules provide extra features or debug interfaces and, are optional for the use of the Mali GPU modules. -config DMA_BUF_LOCK - bool "Build dma-buf lock module" - depends on MALI_BASE_MODULES && MALI_DMA_FENCE - default y - help - This option will build the dma_buf_lock module. - - Modules: - - dma_buf_lock.ko - config DMA_SHARED_BUFFER_TEST_EXPORTER bool "Build dma-buf framework test exporter module" depends on MALI_BASE_MODULES @@ -45,7 +35,7 @@ config DMA_SHARED_BUFFER_TEST_EXPORTER Usable to help test importers. Modules: - - dma-buf-test-exporter.ko + - dma-buf-test-exporter.ko config MALI_MEMORY_GROUP_MANAGER bool "Build Mali Memory Group Manager module" @@ -57,7 +47,7 @@ config MALI_MEMORY_GROUP_MANAGER for memory pools managed by Mali GPU device drivers. Modules: - - memory_group_manager.ko + - memory_group_manager.ko config MALI_PROTECTED_MEMORY_ALLOCATOR bool "Build Mali Protected Memory Allocator module" @@ -70,5 +60,5 @@ config MALI_PROTECTED_MEMORY_ALLOCATOR of Mali GPU device drivers. Modules: - - protected_memory_allocator.ko + - protected_memory_allocator.ko 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 deleted file mode 100644 index 43333ca8e5e2..000000000000 --- a/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.c +++ /dev/null @@ -1,908 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (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 - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) -#include -#else -#include -#endif -#include -#include -#include -#include -#include -#include - -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) - -#include - -#define dma_fence_context_alloc(a) fence_context_alloc(a) -#define dma_fence_init(a, b, c, d, e) fence_init(a, b, c, d, e) -#define dma_fence_get(a) fence_get(a) -#define dma_fence_put(a) fence_put(a) -#define dma_fence_signal(a) fence_signal(a) -#define dma_fence_is_signaled(a) fence_is_signaled(a) -#define dma_fence_add_callback(a, b, c) fence_add_callback(a, b, c) -#define dma_fence_remove_callback(a, b) fence_remove_callback(a, b) - -#if (KERNEL_VERSION(4, 9, 68) > LINUX_VERSION_CODE) -#define dma_fence_get_status(a) (fence_is_signaled(a) ? (a)->status ?: 1 : 0) -#else -#define dma_fence_get_status(a) (fence_is_signaled(a) ? (a)->error ?: 1 : 0) -#endif - -#else - -#include - -#if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE) -#define dma_fence_get_status(a) (dma_fence_is_signaled(a) ? \ - (a)->status ?: 1 \ - : 0) -#endif - -#endif /* < 4.10.0 */ - -#include "dma_buf_lock.h" - -/* Maximum number of buffers that a single handle can address */ -#define DMA_BUF_LOCK_BUF_MAX 32 - -#define DMA_BUF_LOCK_DEBUG 1 - -#define DMA_BUF_LOCK_INIT_BIAS 0xFF - -static dev_t dma_buf_lock_dev; -static struct cdev dma_buf_lock_cdev; -static struct class *dma_buf_lock_class; -static const char dma_buf_lock_dev_name[] = "dma_buf_lock"; - -#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL) || ((KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE)) -static long dma_buf_lock_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -#else -static int dma_buf_lock_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); -#endif - -static const struct file_operations dma_buf_lock_fops = { - .owner = THIS_MODULE, -#if defined(HAVE_UNLOCKED_IOCTL) || ((KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE)) - .unlocked_ioctl = dma_buf_lock_ioctl, -#endif -#if defined(HAVE_COMPAT_IOCTL) || ((KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE)) - .compat_ioctl = dma_buf_lock_ioctl, -#endif -}; - -struct dma_buf_lock_resource { -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) - struct fence fence; -#else - struct dma_fence fence; -#endif - int *list_of_dma_buf_fds; /* List of buffers copied from userspace */ - atomic_t locked; /* Status of lock */ - struct dma_buf **dma_bufs; - unsigned long exclusive; /* Exclusive access bitmap */ - atomic_t fence_dep_count; /* Number of dma-fence dependencies */ - struct list_head dma_fence_callbacks; /* list of all callbacks set up to wait on other fences */ - wait_queue_head_t wait; - struct kref refcount; - struct list_head link; - struct work_struct work; - int count; -}; - -/** - * struct dma_buf_lock_fence_cb - Callback data struct for dma-fence - * @fence_cb: Callback function - * @fence: Pointer to the fence object on which this callback is waiting - * @res: Pointer to dma_buf_lock_resource that is waiting on this callback - * @node: List head for linking this callback to the lock resource - */ -struct dma_buf_lock_fence_cb { -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) - struct fence_cb fence_cb; - struct fence *fence; -#else - struct dma_fence_cb fence_cb; - struct dma_fence *fence; -#endif - struct dma_buf_lock_resource *res; - struct list_head node; -}; - -static LIST_HEAD(dma_buf_lock_resource_list); -static DEFINE_MUTEX(dma_buf_lock_mutex); - -static inline int is_dma_buf_lock_file(struct file *); -static void dma_buf_lock_dounlock(struct kref *ref); - - -/*** dma_buf_lock fence part ***/ - -/* Spin lock protecting all Mali fences as fence->lock. */ -static DEFINE_SPINLOCK(dma_buf_lock_fence_lock); - -static const char * -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) -dma_buf_lock_fence_get_driver_name(struct fence *fence) -#else -dma_buf_lock_fence_get_driver_name(struct dma_fence *fence) -#endif -{ - return "dma_buf_lock"; -} - -static const char * -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) -dma_buf_lock_fence_get_timeline_name(struct fence *fence) -#else -dma_buf_lock_fence_get_timeline_name(struct dma_fence *fence) -#endif -{ - return "dma_buf_lock.timeline"; -} - -static bool -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) -dma_buf_lock_fence_enable_signaling(struct fence *fence) -#else -dma_buf_lock_fence_enable_signaling(struct dma_fence *fence) -#endif -{ - return true; -} - -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) -const struct fence_ops dma_buf_lock_fence_ops = { - .wait = fence_default_wait, -#else -const struct dma_fence_ops dma_buf_lock_fence_ops = { - .wait = dma_fence_default_wait, -#endif - .get_driver_name = dma_buf_lock_fence_get_driver_name, - .get_timeline_name = dma_buf_lock_fence_get_timeline_name, - .enable_signaling = dma_buf_lock_fence_enable_signaling, -}; - -static void -dma_buf_lock_fence_init(struct dma_buf_lock_resource *resource) -{ - dma_fence_init(&resource->fence, - &dma_buf_lock_fence_ops, - &dma_buf_lock_fence_lock, - 0, - 0); -} - -static void -dma_buf_lock_fence_free_callbacks(struct dma_buf_lock_resource *resource) -{ - struct dma_buf_lock_fence_cb *cb, *tmp; - - /* Clean up and free callbacks. */ - list_for_each_entry_safe(cb, tmp, &resource->dma_fence_callbacks, node) { - /* Cancel callbacks that hasn't been called yet and release the - * reference taken in dma_buf_lock_fence_add_callback(). - */ - dma_fence_remove_callback(cb->fence, &cb->fence_cb); - dma_fence_put(cb->fence); - list_del(&cb->node); - kfree(cb); - } -} - -static void -dma_buf_lock_fence_work(struct work_struct *pwork) -{ - struct dma_buf_lock_resource *resource = - container_of(pwork, struct dma_buf_lock_resource, work); - - WARN_ON(atomic_read(&resource->fence_dep_count)); - WARN_ON(!atomic_read(&resource->locked)); - WARN_ON(!resource->exclusive); - - mutex_lock(&dma_buf_lock_mutex); - kref_put(&resource->refcount, dma_buf_lock_dounlock); - mutex_unlock(&dma_buf_lock_mutex); -} - -static void -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) -dma_buf_lock_fence_callback(struct fence *fence, struct fence_cb *cb) -#else -dma_buf_lock_fence_callback(struct dma_fence *fence, struct dma_fence_cb *cb) -#endif -{ - struct dma_buf_lock_fence_cb *dma_buf_lock_cb = container_of(cb, - struct dma_buf_lock_fence_cb, - fence_cb); - struct dma_buf_lock_resource *resource = dma_buf_lock_cb->res; - -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s\n", __func__); -#endif - - /* Callback function will be invoked in atomic context. */ - - if (atomic_dec_and_test(&resource->fence_dep_count)) { - atomic_set(&resource->locked, 1); - wake_up(&resource->wait); - - if (resource->exclusive) - /* Warn if the work was already queued */ - WARN_ON(!schedule_work(&resource->work)); - } -} - -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) -static int -dma_buf_lock_fence_add_callback(struct dma_buf_lock_resource *resource, - struct fence *fence, - fence_func_t callback) -#else -static int -dma_buf_lock_fence_add_callback(struct dma_buf_lock_resource *resource, - struct dma_fence *fence, - dma_fence_func_t callback) -#endif -{ - int err = 0; - struct dma_buf_lock_fence_cb *fence_cb; - - if (!fence) - return -EINVAL; - - fence_cb = kmalloc(sizeof(*fence_cb), GFP_KERNEL); - if (!fence_cb) - return -ENOMEM; - - fence_cb->fence = fence; - fence_cb->res = resource; - INIT_LIST_HEAD(&fence_cb->node); - - err = dma_fence_add_callback(fence, &fence_cb->fence_cb, - callback); - - if (err == -ENOENT) { - /* Fence signaled, get the completion result */ - err = dma_fence_get_status(fence); - - /* remap success completion to err code */ - if (err == 1) - err = 0; - - kfree(fence_cb); - } else if (err) { - kfree(fence_cb); - } else { - /* - * Get reference to fence that will be kept until callback gets - * cleaned up in dma_buf_lock_fence_free_callbacks(). - */ - dma_fence_get(fence); - atomic_inc(&resource->fence_dep_count); - /* Add callback to resource's list of callbacks */ - list_add(&fence_cb->node, &resource->dma_fence_callbacks); - } - - return err; -} - -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) -static int -dma_buf_lock_add_fence_reservation_callback(struct dma_buf_lock_resource *resource, - struct reservation_object *resv, - bool exclusive) -#else -static int -dma_buf_lock_add_fence_reservation_callback(struct dma_buf_lock_resource *resource, - struct dma_resv *resv, - bool exclusive) -#endif -{ -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) - struct fence *excl_fence = NULL; - struct fence **shared_fences = NULL; -#else - struct dma_fence *excl_fence = NULL; - struct dma_fence **shared_fences = NULL; -#endif - unsigned int shared_count = 0; - int err, i; - -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - err = reservation_object_get_fences_rcu( -#elif (KERNEL_VERSION(5, 14, 0) > LINUX_VERSION_CODE) - err = dma_resv_get_fences_rcu( -#else - err = dma_resv_get_fences( -#endif - resv, - &excl_fence, - &shared_count, - &shared_fences); - if (err) - return err; - - if (excl_fence) { - err = dma_buf_lock_fence_add_callback(resource, - excl_fence, - dma_buf_lock_fence_callback); - - /* Release our reference, taken by reservation_object_get_fences_rcu(), - * to the fence. We have set up our callback (if that was possible), - * and it's the fence's owner is responsible for singling the fence - * before allowing it to disappear. - */ - dma_fence_put(excl_fence); - - if (err) - goto out; - } - - if (exclusive) { - for (i = 0; i < shared_count; i++) { - err = dma_buf_lock_fence_add_callback(resource, - shared_fences[i], - dma_buf_lock_fence_callback); - if (err) - goto out; - } - } - - /* Release all our references to the shared fences, taken by - * reservation_object_get_fences_rcu(). We have set up our callback (if - * that was possible), and it's the fence's owner is responsible for - * signaling the fence before allowing it to disappear. - */ -out: - for (i = 0; i < shared_count; i++) - dma_fence_put(shared_fences[i]); - kfree(shared_fences); - - return err; -} - -static void -dma_buf_lock_release_fence_reservation(struct dma_buf_lock_resource *resource, - struct ww_acquire_ctx *ctx) -{ - unsigned int r; - - for (r = 0; r < resource->count; r++) - ww_mutex_unlock(&resource->dma_bufs[r]->resv->lock); - ww_acquire_fini(ctx); -} - -static int -dma_buf_lock_acquire_fence_reservation(struct dma_buf_lock_resource *resource, - struct ww_acquire_ctx *ctx) -{ -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - struct reservation_object *content_resv = NULL; -#else - struct dma_resv *content_resv = NULL; -#endif - unsigned int content_resv_idx = 0; - unsigned int r; - int err = 0; - - ww_acquire_init(ctx, &reservation_ww_class); - -retry: - for (r = 0; r < resource->count; r++) { - if (resource->dma_bufs[r]->resv == content_resv) { - content_resv = NULL; - continue; - } - - err = ww_mutex_lock(&resource->dma_bufs[r]->resv->lock, ctx); - if (err) - goto error; - } - - ww_acquire_done(ctx); - return err; - -error: - content_resv_idx = r; - - /* Unlock the locked one ones */ - while (r--) - ww_mutex_unlock(&resource->dma_bufs[r]->resv->lock); - - if (content_resv) - ww_mutex_unlock(&content_resv->lock); - - /* If we deadlock try with lock_slow and retry */ - if (err == -EDEADLK) { -#if DMA_BUF_LOCK_DEBUG - pr_debug("deadlock at dma_buf fd %i\n", - resource->list_of_dma_buf_fds[content_resv_idx]); -#endif - content_resv = resource->dma_bufs[content_resv_idx]->resv; - ww_mutex_lock_slow(&content_resv->lock, ctx); - goto retry; - } - - /* If we are here the function failed */ - ww_acquire_fini(ctx); - return err; -} - -static int dma_buf_lock_handle_release(struct inode *inode, struct file *file) -{ - struct dma_buf_lock_resource *resource; - - if (!is_dma_buf_lock_file(file)) - return -EINVAL; - - resource = file->private_data; -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s\n", __func__); -#endif - mutex_lock(&dma_buf_lock_mutex); - kref_put(&resource->refcount, dma_buf_lock_dounlock); - mutex_unlock(&dma_buf_lock_mutex); - - return 0; -} - -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 (KERNEL_VERSION(4, 19, 0) > LINUX_VERSION_CODE) - return POLLERR; -#else - return EPOLLERR; -#endif - } - - resource = file->private_data; -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s\n", __func__); -#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; -#else - ret = EPOLLIN | EPOLLRDNORM; - if (resource->exclusive) - ret |= EPOLLOUT | EPOLLWRNORM; -#endif - } else { - if (!poll_does_not_wait(wait)) - poll_wait(file, &resource->wait, wait); - } -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s : return %i\n", __func__, ret); -#endif - return ret; -} - -static const struct file_operations dma_buf_lock_handle_fops = { - .owner = THIS_MODULE, - .release = dma_buf_lock_handle_release, - .poll = dma_buf_lock_handle_poll, -}; - -/* - * is_dma_buf_lock_file - Check if struct file* is associated with dma_buf_lock - */ -static inline int is_dma_buf_lock_file(struct file *file) -{ - return file->f_op == &dma_buf_lock_handle_fops; -} - -/* - * Start requested lock. - * - * Allocates required memory, copies dma_buf_fd list from userspace, - * acquires related reservation objects, and starts the lock. - */ -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; - if (request->count <= 0) - return -EINVAL; - if (request->count > DMA_BUF_LOCK_BUF_MAX) - return -EINVAL; - if (request->exclusive != DMA_BUF_LOCK_NONEXCLUSIVE && - request->exclusive != DMA_BUF_LOCK_EXCLUSIVE) - return -EINVAL; - - resource = kzalloc(sizeof(*resource), GFP_KERNEL); - if (resource == NULL) - return -ENOMEM; - - atomic_set(&resource->locked, 0); - kref_init(&resource->refcount); - INIT_LIST_HEAD(&resource->link); - INIT_WORK(&resource->work, dma_buf_lock_fence_work); - resource->count = request->count; - - /* Allocate space to store dma_buf_fds received from user space */ - size = request->count * sizeof(int); - resource->list_of_dma_buf_fds = kmalloc(size, GFP_KERNEL); - - if (resource->list_of_dma_buf_fds == NULL) { - kfree(resource); - return -ENOMEM; - } - - /* Allocate space to store dma_buf pointers associated with dma_buf_fds */ - size = sizeof(struct dma_buf *) * request->count; - resource->dma_bufs = kmalloc(size, GFP_KERNEL); - - if (resource->dma_bufs == NULL) { - kfree(resource->list_of_dma_buf_fds); - kfree(resource); - return -ENOMEM; - } - - /* Copy requested list of dma_buf_fds from user space */ - size = request->count * sizeof(int); - if (copy_from_user(resource->list_of_dma_buf_fds, - (void __user *)request->list_of_dma_buf_fds, - size) != 0) { - kfree(resource->list_of_dma_buf_fds); - kfree(resource->dma_bufs); - kfree(resource); - return -ENOMEM; - } -#if DMA_BUF_LOCK_DEBUG - for (i = 0; i < request->count; i++) - pr_debug("dma_buf %i = %X\n", i, resource->list_of_dma_buf_fds[i]); -#endif - - /* Initialize the fence associated with dma_buf_lock resource */ - dma_buf_lock_fence_init(resource); - - INIT_LIST_HEAD(&resource->dma_fence_callbacks); - - atomic_set(&resource->fence_dep_count, DMA_BUF_LOCK_INIT_BIAS); - - /* Add resource to global list */ - mutex_lock(&dma_buf_lock_mutex); - - list_add(&resource->link, &dma_buf_lock_resource_list); - - mutex_unlock(&dma_buf_lock_mutex); - - for (i = 0; i < request->count; i++) { - /* Convert fd into dma_buf structure */ - resource->dma_bufs[i] = dma_buf_get(resource->list_of_dma_buf_fds[i]); - - if (IS_ERR_VALUE(PTR_ERR(resource->dma_bufs[i]))) { - mutex_lock(&dma_buf_lock_mutex); - kref_put(&resource->refcount, dma_buf_lock_dounlock); - mutex_unlock(&dma_buf_lock_mutex); - return -EINVAL; - } - - /*Check the reservation object associated with dma_buf */ - if (resource->dma_bufs[i]->resv == NULL) { - mutex_lock(&dma_buf_lock_mutex); - kref_put(&resource->refcount, dma_buf_lock_dounlock); - mutex_unlock(&dma_buf_lock_mutex); - return -EINVAL; - } -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s : dma_buf_fd %i dma_buf %p dma_fence reservation %p\n", - __func__, resource->list_of_dma_buf_fds[i], resource->dma_bufs[i], resource->dma_bufs[i]->resv); -#endif - } - - init_waitqueue_head(&resource->wait); - - kref_get(&resource->refcount); - - 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 PTR_ERR(file); - } - - resource->exclusive = request->exclusive; - - /* Start locking process */ - ret = dma_buf_lock_acquire_fence_reservation(resource, &ww_ctx); - if (ret) { -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s : Error %d locking reservations.\n", __func__, ret); -#endif - 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 ret; - } - - /* Take an extra reference for exclusive access, which will be dropped - * once the pre-existing fences attached to dma-buf resources, for which - * we have commited for exclusive access, are signaled. - * At a given time there can be only one exclusive fence attached to a - * reservation object, so the new exclusive fence replaces the original - * fence and the future sync is done against the new fence which is - * supposed to be signaled only after the original fence was signaled. - * If the new exclusive fence is signaled prematurely then the resources - * would become available for new access while they are already being - * written to by the original owner. - */ - if (resource->exclusive) - kref_get(&resource->refcount); - - for (i = 0; i < request->count; i++) { -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - struct reservation_object *resv = resource->dma_bufs[i]->resv; -#else - struct dma_resv *resv = resource->dma_bufs[i]->resv; -#endif - if (!test_bit(i, &resource->exclusive)) { - -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - ret = reservation_object_reserve_shared(resv); -#else - ret = dma_resv_reserve_shared(resv, 0); -#endif - if (ret) { -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s : Error %d reserving space for shared fence.\n", __func__, ret); -#endif - break; - } - - ret = dma_buf_lock_add_fence_reservation_callback(resource, - resv, - false); - if (ret) { -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s : Error %d adding reservation to callback.\n", __func__, ret); -#endif - break; - } - -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - reservation_object_add_shared_fence(resv, &resource->fence); -#else - dma_resv_add_shared_fence(resv, &resource->fence); -#endif - } else { - 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); -#endif - break; - } - -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - reservation_object_add_excl_fence(resv, &resource->fence); -#else - dma_resv_add_excl_fence(resv, &resource->fence); -#endif - } - } - - dma_buf_lock_release_fence_reservation(resource, &ww_ctx); - - /* Test if the callbacks were already triggered */ - if (!atomic_sub_return(DMA_BUF_LOCK_INIT_BIAS, &resource->fence_dep_count)) { - atomic_set(&resource->locked, 1); - - /* Drop the extra reference taken for exclusive access */ - if (resource->exclusive) - dma_buf_lock_fence_work(&resource->work); - } - - if (IS_ERR_VALUE((unsigned long)ret)) { - 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 ret; - } - -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s : complete\n", __func__); -#endif - mutex_lock(&dma_buf_lock_mutex); - 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; -} - -static void dma_buf_lock_dounlock(struct kref *ref) -{ - int i; - struct dma_buf_lock_resource *resource = container_of(ref, struct dma_buf_lock_resource, refcount); - - atomic_set(&resource->locked, 0); - - /* Signal the resource's fence. */ - dma_fence_signal(&resource->fence); - - dma_buf_lock_fence_free_callbacks(resource); - - list_del(&resource->link); - - for (i = 0; i < resource->count; i++) { - if (resource->dma_bufs[i]) - dma_buf_put(resource->dma_bufs[i]); - } - - kfree(resource->dma_bufs); - kfree(resource->list_of_dma_buf_fds); - dma_fence_put(&resource->fence); -} - -static int __init dma_buf_lock_init(void) -{ - int err; -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s\n", __func__); -#endif - err = alloc_chrdev_region(&dma_buf_lock_dev, 0, 1, dma_buf_lock_dev_name); - - if (err == 0) { - cdev_init(&dma_buf_lock_cdev, &dma_buf_lock_fops); - - err = cdev_add(&dma_buf_lock_cdev, dma_buf_lock_dev, 1); - - if (err == 0) { - dma_buf_lock_class = class_create(THIS_MODULE, dma_buf_lock_dev_name); - if (IS_ERR(dma_buf_lock_class)) - err = PTR_ERR(dma_buf_lock_class); - else { - struct device *mdev = device_create( - dma_buf_lock_class, NULL, dma_buf_lock_dev, - NULL, "%s", dma_buf_lock_dev_name); - if (!IS_ERR(mdev)) - return 0; - - err = PTR_ERR(mdev); - class_destroy(dma_buf_lock_class); - } - cdev_del(&dma_buf_lock_cdev); - } - - unregister_chrdev_region(dma_buf_lock_dev, 1); - } -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s failed\n", __func__); -#endif - return err; -} - -static void __exit dma_buf_lock_exit(void) -{ -#if DMA_BUF_LOCK_DEBUG - pr_debug("%s\n", __func__); -#endif - - /* Unlock all outstanding references */ - while (1) { - struct dma_buf_lock_resource *resource; - - mutex_lock(&dma_buf_lock_mutex); - if (list_empty(&dma_buf_lock_resource_list)) { - mutex_unlock(&dma_buf_lock_mutex); - break; - } - - resource = list_entry(dma_buf_lock_resource_list.next, - struct dma_buf_lock_resource, link); - - kref_put(&resource->refcount, dma_buf_lock_dounlock); - mutex_unlock(&dma_buf_lock_mutex); - } - - device_destroy(dma_buf_lock_class, dma_buf_lock_dev); - - class_destroy(dma_buf_lock_class); - - cdev_del(&dma_buf_lock_cdev); - - unregister_chrdev_region(dma_buf_lock_dev, 1); -} - -#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL) || ((KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE)) -static long dma_buf_lock_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -#else -static int dma_buf_lock_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -#endif -{ - struct dma_buf_lock_k_request request; - int size = _IOC_SIZE(cmd); - - if (_IOC_TYPE(cmd) != DMA_BUF_LOCK_IOC_MAGIC) - return -ENOTTY; - if ((_IOC_NR(cmd) < DMA_BUF_LOCK_IOC_MINNR) || (_IOC_NR(cmd) > DMA_BUF_LOCK_IOC_MAXNR)) - return -ENOTTY; - - switch (cmd) { - case DMA_BUF_LOCK_FUNC_LOCK_ASYNC: - if (size != sizeof(request)) - return -ENOTTY; - if (copy_from_user(&request, (void __user *)arg, size)) - return -EFAULT; -#if DMA_BUF_LOCK_DEBUG - pr_debug("DMA_BUF_LOCK_FUNC_LOCK_ASYNC - %i\n", request.count); -#endif - return dma_buf_lock_dolock(&request); - } - - return -ENOTTY; -} - -module_init(dma_buf_lock_init); -module_exit(dma_buf_lock_exit); - -MODULE_LICENSE("GPL"); -MODULE_INFO(import_ns, "DMA_BUF"); diff --git a/drivers/base/arm/dma_buf_test_exporter/build.bp b/drivers/base/arm/dma_buf_test_exporter/build.bp index a49fb81d6665..aabd32aa5103 100644 --- a/drivers/base/arm/dma_buf_test_exporter/build.bp +++ b/drivers/base/arm/dma_buf_test_exporter/build.bp @@ -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 @@ -22,7 +22,7 @@ bob_kernel_module { name: "dma-buf-test-exporter", defaults: [ - "kernel_defaults" + "kernel_defaults", ], srcs: [ "Kbuild", 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 6b9a4d70483a..5f033a60026c 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 @@ -19,7 +19,7 @@ * */ -#include +#include #include #include #include @@ -32,6 +32,9 @@ #include #include +#define DMA_BUF_TE_VER_MAJOR 1 +#define DMA_BUF_TE_VER_MINOR 0 + /* Maximum size allowed in a single DMA_BUF_TE_ALLOC call */ #define DMA_BUF_TE_ALLOC_MAX_SIZE ((8ull << 30) >> PAGE_SHIFT) /* 8 GB */ diff --git a/drivers/base/arm/memory_group_manager/build.bp b/drivers/base/arm/memory_group_manager/build.bp index 23db183e4f1b..f4b809e774d2 100644 --- a/drivers/base/arm/memory_group_manager/build.bp +++ b/drivers/base/arm/memory_group_manager/build.bp @@ -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 @@ -22,7 +22,7 @@ bob_kernel_module { name: "memory_group_manager", defaults: [ - "kernel_defaults" + "kernel_defaults", ], srcs: [ "Kbuild", 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 7729492e0c80..825893e3cf8e 100644 --- a/drivers/base/arm/memory_group_manager/memory_group_manager.c +++ b/drivers/base/arm/memory_group_manager/memory_group_manager.c @@ -265,8 +265,8 @@ static struct page *example_mgm_alloc_page( struct mgm_groups *const data = mgm_dev->data; struct page *p; - dev_dbg(data->dev, "%s(mgm_dev=%p, group_id=%d gfp_mask=0x%x order=%u\n", - __func__, (void *)mgm_dev, group_id, gfp_mask, order); + dev_dbg(data->dev, "%s(mgm_dev=%pK, group_id=%d gfp_mask=0x%x order=%u\n", __func__, + (void *)mgm_dev, group_id, gfp_mask, order); if (WARN_ON(group_id < 0) || WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS)) @@ -291,8 +291,8 @@ static void example_mgm_free_page( { struct mgm_groups *const data = mgm_dev->data; - dev_dbg(data->dev, "%s(mgm_dev=%p, group_id=%d page=%p order=%u\n", - __func__, (void *)mgm_dev, group_id, (void *)page, order); + dev_dbg(data->dev, "%s(mgm_dev=%pK, group_id=%d page=%pK order=%u\n", __func__, + (void *)mgm_dev, group_id, (void *)page, order); if (WARN_ON(group_id < 0) || WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS)) @@ -309,9 +309,8 @@ static int example_mgm_get_import_memory_id( { struct mgm_groups *const data = mgm_dev->data; - dev_dbg(data->dev, "%s(mgm_dev=%p, import_data=%p (type=%d)\n", - __func__, (void *)mgm_dev, (void *)import_data, - (int)import_data->type); + dev_dbg(data->dev, "%s(mgm_dev=%pK, import_data=%pK (type=%d)\n", __func__, (void *)mgm_dev, + (void *)import_data, (int)import_data->type); if (!WARN_ON(!import_data)) { WARN_ON(!import_data->u.dma_buf); @@ -329,9 +328,8 @@ static u64 example_mgm_update_gpu_pte( { struct mgm_groups *const data = mgm_dev->data; - dev_dbg(data->dev, - "%s(mgm_dev=%p, group_id=%d, mmu_level=%d, pte=0x%llx)\n", - __func__, (void *)mgm_dev, group_id, mmu_level, pte); + dev_dbg(data->dev, "%s(mgm_dev=%pK, group_id=%d, mmu_level=%d, pte=0x%llx)\n", __func__, + (void *)mgm_dev, group_id, mmu_level, pte); if (WARN_ON(group_id < 0) || WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS)) @@ -367,9 +365,9 @@ static vm_fault_t example_mgm_vmf_insert_pfn_prot( vm_fault_t fault; dev_dbg(data->dev, - "%s(mgm_dev=%p, group_id=%d, vma=%p, addr=0x%lx, pfn=0x%lx, prot=0x%llx)\n", + "%s(mgm_dev=%pK, group_id=%d, vma=%pK, addr=0x%lx, pfn=0x%lx, prot=0x%llx)\n", __func__, (void *)mgm_dev, group_id, (void *)vma, addr, pfn, - (unsigned long long) pgprot_val(prot)); + (unsigned long long)pgprot_val(prot)); if (WARN_ON(group_id < 0) || WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS)) diff --git a/drivers/base/arm/protected_memory_allocator/build.bp b/drivers/base/arm/protected_memory_allocator/build.bp index 4c56154061e8..aef5344da31c 100644 --- a/drivers/base/arm/protected_memory_allocator/build.bp +++ b/drivers/base/arm/protected_memory_allocator/build.bp @@ -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 @@ -22,7 +22,7 @@ bob_kernel_module { name: "protected_memory_allocator", defaults: [ - "kernel_defaults" + "kernel_defaults", ], srcs: [ "Kbuild", diff --git a/drivers/gpu/arm/bifrost/Kbuild b/drivers/gpu/arm/bifrost/Kbuild index a7f0ba0da1e8..70f3997b2bd3 100644 --- a/drivers/gpu/arm/bifrost/Kbuild +++ b/drivers/gpu/arm/bifrost/Kbuild @@ -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 @@ -59,10 +59,8 @@ ifeq ($(CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS), y) endif ifeq ($(CONFIG_MALI_BIFROST_FENCE_DEBUG), y) - ifneq ($(CONFIG_SYNC), y) - ifneq ($(CONFIG_SYNC_FILE), y) - $(error CONFIG_MALI_BIFROST_FENCE_DEBUG depends on CONFIG_SYNC || CONFIG_SYNC_FILE to be set in Kernel configuration) - endif + ifneq ($(CONFIG_SYNC_FILE), y) + $(error CONFIG_MALI_BIFROST_FENCE_DEBUG depends on CONFIG_SYNC_FILE to be set in Kernel configuration) endif endif @@ -71,7 +69,7 @@ endif # # Driver version string which is returned to userspace via an ioctl -MALI_RELEASE_NAME ?= '"g13p0-01eac0"' +MALI_RELEASE_NAME ?= '"g15p0-01eac0"' # Set up defaults if not defined by build system ifeq ($(CONFIG_MALI_BIFROST_DEBUG), y) MALI_UNIT_TEST = 1 @@ -151,6 +149,7 @@ bifrost_kbase-y := \ mali_kbase_cache_policy.o \ mali_kbase_ccswe.o \ mali_kbase_mem.o \ + mali_kbase_mem_migrate.o \ mali_kbase_mem_pool_group.o \ mali_kbase_native_mgm.o \ mali_kbase_ctx_sched.o \ @@ -159,12 +158,6 @@ bifrost_kbase-y := \ mali_kbase_config.o \ mali_kbase_kinstr_prfcnt.o \ mali_kbase_vinstr.o \ - mali_kbase_hwcnt.o \ - mali_kbase_hwcnt_gpu.o \ - mali_kbase_hwcnt_gpu_narrow.o \ - mali_kbase_hwcnt_types.o \ - mali_kbase_hwcnt_virtualizer.o \ - mali_kbase_hwcnt_watchdog_if_timer.o \ mali_kbase_softjobs.o \ mali_kbase_hw.o \ mali_kbase_debug.o \ @@ -175,6 +168,7 @@ bifrost_kbase-y := \ mali_kbase_disjoint_events.o \ mali_kbase_debug_mem_view.o \ mali_kbase_debug_mem_zones.o \ + mali_kbase_debug_mem_allocs.o \ mali_kbase_smc.o \ mali_kbase_mem_pool.o \ mali_kbase_mem_pool_debugfs.o \ @@ -191,24 +185,14 @@ bifrost_kbase-$(CONFIG_DEBUG_FS) += mali_kbase_pbha_debugfs.o bifrost_kbase-$(CONFIG_MALI_CINSTR_GWT) += mali_kbase_gwt.o -bifrost_kbase-$(CONFIG_SYNC) += \ - mali_kbase_sync_android.o \ - mali_kbase_sync_common.o - bifrost_kbase-$(CONFIG_SYNC_FILE) += \ mali_kbase_fence_ops.o \ mali_kbase_sync_file.o \ mali_kbase_sync_common.o -ifeq ($(CONFIG_MALI_CSF_SUPPORT),y) - bifrost_kbase-y += \ - mali_kbase_hwcnt_backend_csf.o \ - mali_kbase_hwcnt_backend_csf_if_fw.o -else +ifneq ($(CONFIG_MALI_CSF_SUPPORT),y) bifrost_kbase-y += \ mali_kbase_jm.o \ - mali_kbase_hwcnt_backend_jm.o \ - mali_kbase_hwcnt_backend_jm_watchdog.o \ mali_kbase_dummy_job_wa.o \ mali_kbase_debug_job_fault.o \ mali_kbase_event.o \ @@ -218,11 +202,6 @@ else mali_kbase_js_ctx_attr.o \ mali_kbase_kinstr_jm.o - bifrost_kbase-$(CONFIG_MALI_BIFROST_DMA_FENCE) += \ - mali_kbase_fence_ops.o \ - mali_kbase_dma_fence.o \ - mali_kbase_fence.o - bifrost_kbase-$(CONFIG_SYNC_FILE) += \ mali_kbase_fence_ops.o \ mali_kbase_fence.o @@ -236,6 +215,7 @@ INCLUDE_SUBDIR = \ $(src)/backend/gpu/Kbuild \ $(src)/mmu/Kbuild \ $(src)/tl/Kbuild \ + $(src)/hwcnt/Kbuild \ $(src)/gpu/Kbuild \ $(src)/thirdparty/Kbuild \ $(src)/platform/$(MALI_PLATFORM_DIR)/Kbuild diff --git a/drivers/gpu/arm/bifrost/Kconfig b/drivers/gpu/arm/bifrost/Kconfig index 54f083dbad27..1bfb59ca14e2 100644 --- a/drivers/gpu/arm/bifrost/Kconfig +++ b/drivers/gpu/arm/bifrost/Kconfig @@ -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 @@ -91,16 +91,6 @@ config MALI_BIFROST_ENABLE_TRACE Enables tracing in kbase. Trace log available through the "mali_trace" debugfs file, when the CONFIG_DEBUG_FS is enabled -config MALI_BIFROST_DMA_FENCE - bool "Enable DMA_BUF fence support for Mali" - depends on MALI_BIFROST - default n - help - Support DMA_BUF fences for Mali. - - This option should only be enabled if the Linux Kernel has built in - support for DMA_BUF fences. - config MALI_ARBITER_SUPPORT bool "Enable arbiter support for Mali" depends on MALI_BIFROST && !MALI_CSF_SUPPORT @@ -117,7 +107,7 @@ config MALI_DMA_BUF_MAP_ON_DEMAND depends on MALI_BIFROST default n help - This option caused kbase to set up the GPU mapping of imported + This option will cause kbase to set up the GPU mapping of imported dma-buf when needed to run atoms. This is the legacy behavior. This is intended for testing and the option will get removed in the @@ -237,7 +227,7 @@ config MALI_BIFROST_DEBUG config MALI_BIFROST_FENCE_DEBUG bool "Enable debug sync fence usage" - depends on MALI_BIFROST && MALI_BIFROST_EXPERT && (SYNC || SYNC_FILE) + depends on MALI_BIFROST && MALI_BIFROST_EXPERT && SYNC_FILE default y if MALI_BIFROST_DEBUG help Select this option to enable additional checking and reporting on the @@ -385,9 +375,6 @@ config MALI_ARBITRATION virtualization setup for Mali If unsure, say N. -if MALI_ARBITRATION -source "drivers/gpu/arm/bifrost/arbitration/Kconfig" -endif # source "drivers/gpu/arm/bifrost/tests/Kconfig" diff --git a/drivers/gpu/arm/bifrost/Makefile b/drivers/gpu/arm/bifrost/Makefile index 623177ed26fb..3fb736d7950e 100644 --- a/drivers/gpu/arm/bifrost/Makefile +++ b/drivers/gpu/arm/bifrost/Makefile @@ -65,7 +65,7 @@ ifeq ($(CONFIG_MALI_BIFROST),m) endif ifeq ($(CONFIG_XEN),y) - ifneq ($(CONFIG_MALI_ARBITRATION), n) + ifneq ($(CONFIG_MALI_ARBITER_SUPPORT), n) CONFIG_MALI_XEN ?= m endif endif @@ -91,14 +91,10 @@ ifeq ($(CONFIG_MALI_BIFROST),m) CONFIG_MALI_BIFROST_ENABLE_TRACE ?= y CONFIG_MALI_BIFROST_SYSTEM_TRACE ?= y - ifeq ($(CONFIG_SYNC), y) + ifeq ($(CONFIG_SYNC_FILE), y) CONFIG_MALI_BIFROST_FENCE_DEBUG ?= y else - ifeq ($(CONFIG_SYNC_FILE), y) - CONFIG_MALI_BIFROST_FENCE_DEBUG ?= y - else - CONFIG_MALI_BIFROST_FENCE_DEBUG = n - endif + CONFIG_MALI_BIFROST_FENCE_DEBUG = n endif else # Prevent misuse when CONFIG_MALI_BIFROST_DEBUG=n @@ -160,7 +156,6 @@ CONFIGS := \ CONFIG_MALI_BIFROST \ CONFIG_MALI_CSF_SUPPORT \ CONFIG_MALI_BIFROST_GATOR_SUPPORT \ - CONFIG_MALI_BIFROST_DMA_FENCE \ CONFIG_MALI_ARBITER_SUPPORT \ CONFIG_MALI_ARBITRATION \ CONFIG_MALI_ARBITER_MODULES \ @@ -227,26 +222,47 @@ EXTRA_CFLAGS += -DCONFIG_MALI_PLATFORM_NAME=$(CONFIG_MALI_PLATFORM_NAME) # KBUILD_EXTRA_SYMBOLS to prevent warnings about unknown functions # -# The following were added to align with W=1 in scripts/Makefile.extrawarn -# from the Linux source tree KBUILD_CFLAGS += -Wall -Werror + +# The following were added to align with W=1 in scripts/Makefile.extrawarn +# from the Linux source tree (v5.18.14) KBUILD_CFLAGS += -Wextra -Wunused -Wno-unused-parameter KBUILD_CFLAGS += -Wmissing-declarations KBUILD_CFLAGS += -Wmissing-format-attribute KBUILD_CFLAGS += -Wmissing-prototypes KBUILD_CFLAGS += -Wold-style-definition -KBUILD_CFLAGS += -Wmissing-include-dirs +# The -Wmissing-include-dirs cannot be enabled as the path to some of the +# included directories change depending on whether it is an in-tree or +# out-of-tree build. KBUILD_CFLAGS += $(call cc-option, -Wunused-but-set-variable) KBUILD_CFLAGS += $(call cc-option, -Wunused-const-variable) KBUILD_CFLAGS += $(call cc-option, -Wpacked-not-aligned) KBUILD_CFLAGS += $(call cc-option, -Wstringop-truncation) # The following turn off the warnings enabled by -Wextra -KBUILD_CFLAGS += -Wno-missing-field-initializers KBUILD_CFLAGS += -Wno-sign-compare -KBUILD_CFLAGS += -Wno-type-limits +KBUILD_CFLAGS += -Wno-shift-negative-value +# This flag is needed to avoid build errors on older kernels +KBUILD_CFLAGS += $(call cc-option, -Wno-cast-function-type) KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN1 +# The following were added to align with W=2 in scripts/Makefile.extrawarn +# from the Linux source tree (v5.18.14) +KBUILD_CFLAGS += -Wdisabled-optimization +# The -Wshadow flag cannot be enabled unless upstream kernels are +# patched to fix redefinitions of certain built-in functions and +# global variables. +KBUILD_CFLAGS += $(call cc-option, -Wlogical-op) +KBUILD_CFLAGS += -Wmissing-field-initializers +KBUILD_CFLAGS += -Wtype-limits +KBUILD_CFLAGS += $(call cc-option, -Wmaybe-uninitialized) +KBUILD_CFLAGS += $(call cc-option, -Wunused-macros) + +KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN2 + +# This warning is disabled to avoid build failures in some kernel versions +KBUILD_CFLAGS += -Wno-ignored-qualifiers + all: $(MAKE) -C $(KDIR) M=$(CURDIR) $(MAKE_ARGS) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" modules diff --git a/drivers/gpu/arm/bifrost/Mconfig b/drivers/gpu/arm/bifrost/Mconfig index fd81ac44af3d..f812bcad639c 100644 --- a/drivers/gpu/arm/bifrost/Mconfig +++ b/drivers/gpu/arm/bifrost/Mconfig @@ -97,16 +97,6 @@ config MALI_BIFROST_ENABLE_TRACE Enables tracing in kbase. Trace log available through the "mali_trace" debugfs file, when the CONFIG_DEBUG_FS is enabled -config MALI_BIFROST_DMA_FENCE - bool "Enable DMA_BUF fence support for Mali" - depends on MALI_BIFROST - default n - help - Support DMA_BUF fences for Mali. - - This option should only be enabled if the Linux Kernel has built in - support for DMA_BUF fences. - config MALI_ARBITER_SUPPORT bool "Enable arbiter support for Mali" depends on MALI_BIFROST && !MALI_CSF_SUPPORT @@ -129,7 +119,7 @@ config MALI_DMA_BUF_MAP_ON_DEMAND default n default y if !DMA_BUF_SYNC_IOCTL_SUPPORTED help - This option caused kbase to set up the GPU mapping of imported + This option will cause kbase to set up the GPU mapping of imported dma-buf when needed to run atoms. This is the legacy behavior. This is intended for testing and the option will get removed in the @@ -157,17 +147,6 @@ menuconfig MALI_BIFROST_EXPERT Enabling this option and modifying the default settings may produce a driver with performance or other limitations. -config MALI_2MB_ALLOC - bool "Attempt to allocate 2MB pages" - depends on MALI_BIFROST && MALI_BIFROST_EXPERT - default n - help - Rather than allocating all GPU memory page-by-page, attempt to - allocate 2MB pages from the kernel. This reduces TLB pressure and - helps to prevent memory fragmentation. - - If in doubt, say N - config MALI_MEMORY_FULLY_BACKED bool "Enable memory fully physically-backed" depends on MALI_BIFROST && MALI_BIFROST_EXPERT @@ -200,10 +179,10 @@ config MALI_FW_CORE_DUMP Example: * To explicitly request core dump: - echo 1 >/sys/kernel/debug/mali0/fw_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 + or kernel driver reported an internal firmware error): + cat /sys/kernel/debug/mali0/fw_core_dump choice prompt "Error injection level" @@ -343,5 +322,5 @@ config MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE slowest clock will be selected. -source "kernel/drivers/gpu/arm/midgard/arbitration/Mconfig" +source "kernel/drivers/gpu/arm/arbitration/Mconfig" source "kernel/drivers/gpu/arm/midgard/tests/Mconfig" diff --git a/drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbif.c b/drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbif.c index 64e11ce53625..b5d3cd685ba5 100644 --- a/drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbif.c +++ b/drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbif.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 @@ -28,12 +28,12 @@ #include #include #include -#include "mali_kbase_arbiter_interface.h" +#include "linux/mali_arbiter_interface.h" /* Arbiter interface version against which was implemented this module */ #define MALI_REQUIRED_KBASE_ARBITER_INTERFACE_VERSION 5 #if MALI_REQUIRED_KBASE_ARBITER_INTERFACE_VERSION != \ - MALI_KBASE_ARBITER_INTERFACE_VERSION + MALI_ARBITER_INTERFACE_VERSION #error "Unsupported Mali Arbiter interface version." #endif @@ -205,6 +205,7 @@ int kbase_arbif_init(struct kbase_device *kbdev) if (!pdev->dev.driver || !try_module_get(pdev->dev.driver->owner)) { dev_err(kbdev->dev, "arbiter_if driver not available\n"); + put_device(&pdev->dev); return -EPROBE_DEFER; } kbdev->arb.arb_dev = &pdev->dev; @@ -212,6 +213,7 @@ int kbase_arbif_init(struct kbase_device *kbdev) if (!arb_if) { dev_err(kbdev->dev, "arbiter_if driver not ready\n"); module_put(pdev->dev.driver->owner); + put_device(&pdev->dev); return -EPROBE_DEFER; } @@ -233,6 +235,7 @@ int kbase_arbif_init(struct kbase_device *kbdev) if (err) { dev_err(&pdev->dev, "Failed to register with arbiter\n"); module_put(pdev->dev.driver->owner); + put_device(&pdev->dev); if (err != -EPROBE_DEFER) err = -EFAULT; return err; @@ -262,8 +265,10 @@ void kbase_arbif_destroy(struct kbase_device *kbdev) arb_if->vm_ops.vm_arb_unregister_dev(kbdev->arb.arb_if); } kbdev->arb.arb_if = NULL; - if (kbdev->arb.arb_dev) + if (kbdev->arb.arb_dev) { module_put(kbdev->arb.arb_dev->driver->owner); + put_device(kbdev->arb.arb_dev); + } kbdev->arb.arb_dev = NULL; } diff --git a/drivers/gpu/arm/bifrost/arbitration/Kconfig b/drivers/gpu/arm/bifrost/arbitration/Kconfig deleted file mode 100644 index e991653e8d81..000000000000 --- a/drivers/gpu/arm/bifrost/arbitration/Kconfig +++ /dev/null @@ -1,49 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note OR MIT -# -# (C) COPYRIGHT 2012-2021 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. -# -# - -config MALI_XEN - tristate "Enable Xen Interface reference code" - depends on MALI_ARBITRATION && XEN - default n - help - Enables the build of xen interface modules used in the reference - virtualization setup for Mali - If unsure, say N. - -config MALI_ARBITER_MODULES - tristate "Enable mali arbiter modules" - depends on MALI_ARBITRATION - default y - help - Enables the build of the arbiter modules used in the reference - virtualization setup for Mali - If unsure, say N - -config MALI_GPU_POWER_MODULES - tristate "Enable gpu power modules" - depends on MALI_ARBITRATION - default y - help - Enables the build of the gpu power modules used in the reference - virtualization setup for Mali - If unsure, say N - - -source "drivers/gpu/arm/bifrost/arbitration/ptm/Kconfig" diff --git a/drivers/gpu/arm/bifrost/arbitration/ptm/Kconfig b/drivers/gpu/arm/bifrost/arbitration/ptm/Kconfig deleted file mode 100644 index 074ebd50daa5..000000000000 --- a/drivers/gpu/arm/bifrost/arbitration/ptm/Kconfig +++ /dev/null @@ -1,28 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note OR MIT -# -# (C) COPYRIGHT 2021 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. -# -# - -config MALI_PARTITION_MANAGER - tristate "Enable compilation of partition manager modules" - depends on MALI_ARBITRATION - default n - help - This option enables the compilation of the partition manager - modules used to configure the Mali-G78AE GPU. - diff --git a/drivers/gpu/arm/bifrost/backend/gpu/Kbuild b/drivers/gpu/arm/bifrost/backend/gpu/Kbuild index 65f07e23412d..7eec91ff6631 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/Kbuild +++ b/drivers/gpu/arm/bifrost/backend/gpu/Kbuild @@ -1,6 +1,6 @@ # 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 diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.c index 9587c704ff8a..7c0abbaf860f 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2014-2016, 2018, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2016, 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 @@ -22,12 +22,32 @@ #include "backend/gpu/mali_kbase_cache_policy_backend.h" #include +/** + * kbasep_amba_register_present() - Check AMBA_<> register is present + * in the GPU. + * @kbdev: Device pointer + * + * Note: Only for arch version 12.x.1 onwards. + * + * Return: true if AMBA_FEATURES/ENABLE registers are present. + */ +static bool kbasep_amba_register_present(struct kbase_device *kbdev) +{ + return (ARCH_MAJOR_REV_REG(kbdev->gpu_props.props.raw_props.gpu_id) >= + GPU_ID2_ARCH_MAJOR_REV_MAKE(12, 1)); +} void kbase_cache_set_coherency_mode(struct kbase_device *kbdev, u32 mode) { kbdev->current_gpu_coherency_mode = mode; + if (kbasep_amba_register_present(kbdev)) { + u32 val = kbase_reg_read(kbdev, AMBA_ENABLE); + + val = AMBA_ENABLE_COHERENCY_PROTOCOL_SET(val, mode); + kbase_reg_write(kbdev, AMBA_ENABLE, val); + } else kbase_reg_write(kbdev, COHERENCY_ENABLE, mode); } @@ -35,9 +55,38 @@ u32 kbase_cache_get_coherency_features(struct kbase_device *kbdev) { u32 coherency_features; + if (kbasep_amba_register_present(kbdev)) + coherency_features = + kbase_reg_read(kbdev, GPU_CONTROL_REG(AMBA_FEATURES)); + else coherency_features = kbase_reg_read( kbdev, GPU_CONTROL_REG(COHERENCY_FEATURES)); return coherency_features; } +void kbase_amba_set_memory_cache_support(struct kbase_device *kbdev, + bool enable) +{ + if (kbasep_amba_register_present(kbdev)) { + u32 val = kbase_reg_read(kbdev, AMBA_ENABLE); + + val = AMBA_ENABLE_MEMORY_CACHE_SUPPORT_SET(val, enable); + kbase_reg_write(kbdev, AMBA_ENABLE, val); + + } else { + WARN(1, "memory_cache_support not supported"); + } +} + +void kbase_amba_set_invalidate_hint(struct kbase_device *kbdev, bool enable) +{ + if (kbasep_amba_register_present(kbdev)) { + u32 val = kbase_reg_read(kbdev, AMBA_ENABLE); + + val = AMBA_ENABLE_INVALIDATE_HINT_SET(val, enable); + kbase_reg_write(kbdev, AMBA_ENABLE, val); + } else { + WARN(1, "invalidate_hint not supported"); + } +} diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.h index 795dbea40318..758e3be08c16 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.h +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_cache_policy_backend.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2014-2016, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2016, 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 @@ -43,4 +43,23 @@ void kbase_cache_set_coherency_mode(struct kbase_device *kbdev, */ u32 kbase_cache_get_coherency_features(struct kbase_device *kbdev); +/** + * kbase_amba_set_memory_cache_support() - Sets AMBA memory cache support + * in the GPU. + * @kbdev: Device pointer + * @enable: true for enable. + * + * Note: Only for arch version 12.x.1 onwards. + */ +void kbase_amba_set_memory_cache_support(struct kbase_device *kbdev, + bool enable); +/** + * kbase_amba_set_invalidate_hint() - Sets AMBA invalidate hint + * in the GPU. + * @kbdev: Device pointer + * @enable: true for enable. + * + * Note: Only for arch version 12.x.1 onwards. + */ +void kbase_amba_set_invalidate_hint(struct kbase_device *kbdev, bool enable); #endif /* _KBASE_CACHE_POLICY_BACKEND_H_ */ diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_defs.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_defs.h index 7190f42c2104..bd2eb8a12047 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_defs.h +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_instr_defs.h @@ -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 @@ -26,7 +26,7 @@ #ifndef _KBASE_INSTR_DEFS_H_ #define _KBASE_INSTR_DEFS_H_ -#include +#include /* * Instrumentation State Machine States diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.c index 72def5e7aabb..15999cbc9126 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_irq_linux.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 @@ -163,7 +163,6 @@ static irq_handler_t kbase_handler_table[] = { #ifdef CONFIG_MALI_BIFROST_DEBUG #define JOB_IRQ_HANDLER JOB_IRQ_TAG -#define MMU_IRQ_HANDLER MMU_IRQ_TAG #define GPU_IRQ_HANDLER GPU_IRQ_TAG /** 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 08de02495a4a..e17014e45f6b 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 @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -1440,6 +1440,11 @@ bool kbase_reset_gpu_is_active(struct kbase_device *kbdev) return true; } +bool kbase_reset_gpu_is_not_pending(struct kbase_device *kbdev) +{ + return atomic_read(&kbdev->hwaccess.backend.reset_gpu) == KBASE_RESET_GPU_NOT_PENDING; +} + int kbase_reset_gpu_wait(struct kbase_device *kbdev) { wait_event(kbdev->hwaccess.backend.reset_wait, 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 9960beb2e9b4..e5af4ca8fc43 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 @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include 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 e4f4b2455925..1a0209f702ac 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 @@ -80,31 +80,360 @@ static bool ipa_control_timer_enabled; #endif #define LO_MASK(M) ((M) & 0xFFFFFFFF) +#if !MALI_USE_CSF #define HI_MASK(M) ((M) & 0xFFFFFFFF00000000) +#endif -static u32 get_implementation_register(u32 reg) -{ - switch (reg) { - case GPU_CONTROL_REG(SHADER_PRESENT_LO): - return LO_MASK(DUMMY_IMPLEMENTATION_SHADER_PRESENT); - case GPU_CONTROL_REG(TILER_PRESENT_LO): - return LO_MASK(DUMMY_IMPLEMENTATION_TILER_PRESENT); - case GPU_CONTROL_REG(L2_PRESENT_LO): - return LO_MASK(DUMMY_IMPLEMENTATION_L2_PRESENT); - case GPU_CONTROL_REG(STACK_PRESENT_LO): - return LO_MASK(DUMMY_IMPLEMENTATION_STACK_PRESENT); +/* Construct a value for the THREAD_FEATURES register, *except* the two most + * significant bits, which are set to IMPLEMENTATION_MODEL in + * midgard_model_read_reg(). + */ +#if MALI_USE_CSF +#define THREAD_FEATURES_PARTIAL(MAX_REGISTERS, MAX_TASK_QUEUE, MAX_TG_SPLIT) \ + ((MAX_REGISTERS) | ((MAX_TASK_QUEUE) << 24)) +#else +#define THREAD_FEATURES_PARTIAL(MAX_REGISTERS, MAX_TASK_QUEUE, MAX_TG_SPLIT) \ + ((MAX_REGISTERS) | ((MAX_TASK_QUEUE) << 16) | ((MAX_TG_SPLIT) << 24)) +#endif - case GPU_CONTROL_REG(SHADER_PRESENT_HI): - case GPU_CONTROL_REG(TILER_PRESENT_HI): - case GPU_CONTROL_REG(L2_PRESENT_HI): - case GPU_CONTROL_REG(STACK_PRESENT_HI): - /* *** FALLTHROUGH *** */ - default: - return 0; - } -} +struct error_status_t hw_error_status; -struct { +/** + * struct control_reg_values_t - control register values specific to the GPU being 'emulated' + * @name: GPU name + * @gpu_id: GPU ID to report + * @as_present: Bitmap of address spaces present + * @thread_max_threads: Maximum number of threads per core + * @thread_max_workgroup_size: Maximum number of threads per workgroup + * @thread_max_barrier_size: Maximum number of threads per barrier + * @thread_features: Thread features, NOT INCLUDING the 2 + * most-significant bits, which are always set to + * IMPLEMENTATION_MODEL. + * @core_features: Core features + * @tiler_features: Tiler features + * @mmu_features: MMU features + * @gpu_features_lo: GPU features (low) + * @gpu_features_hi: GPU features (high) + * @shader_present: Available shader bitmap + * @stack_present: Core stack present bitmap + * + */ +struct control_reg_values_t { + const char *name; + u32 gpu_id; + u32 as_present; + u32 thread_max_threads; + u32 thread_max_workgroup_size; + u32 thread_max_barrier_size; + u32 thread_features; + u32 core_features; + u32 tiler_features; + u32 mmu_features; + u32 gpu_features_lo; + u32 gpu_features_hi; + u32 shader_present; + u32 stack_present; +}; + +struct job_slot { + int job_active; + int job_queued; + int job_complete_irq_asserted; + int job_irq_mask; + int job_disabled; +}; + +struct dummy_model_t { + int reset_completed; + int reset_completed_mask; +#if !MALI_USE_CSF + int prfcnt_sample_completed; +#endif /* !MALI_USE_CSF */ + int power_changed_mask; /* 2bits: _ALL,_SINGLE */ + int power_changed; /* 1bit */ + bool clean_caches_completed; + bool clean_caches_completed_irq_enabled; +#if MALI_USE_CSF + bool flush_pa_range_completed; + bool flush_pa_range_completed_irq_enabled; +#endif + int power_on; /* 6bits: SHADER[4],TILER,L2 */ + u32 stack_power_on_lo; + u32 coherency_enable; + unsigned int job_irq_js_state; + struct job_slot slots[NUM_SLOTS]; + const struct control_reg_values_t *control_reg_values; + u32 l2_config; + void *data; +}; + +/* Array associating GPU names with control register values. The first + * one is used in the case of no match. + */ +static const struct control_reg_values_t all_control_reg_values[] = { + { + .name = "tMIx", + .gpu_id = GPU_ID2_MAKE(6, 0, 10, 0, 0, 1, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tHEx", + .gpu_id = GPU_ID2_MAKE(6, 2, 0, 1, 0, 3, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tSIx", + .gpu_id = GPU_ID2_MAKE(7, 0, 0, 0, 1, 1, 0), + .as_present = 0xFF, + .thread_max_threads = 0x300, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), + .tiler_features = 0x209, + .mmu_features = 0x2821, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tDVx", + .gpu_id = GPU_ID2_MAKE(7, 0, 0, 3, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x300, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), + .tiler_features = 0x209, + .mmu_features = 0x2821, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tNOx", + .gpu_id = GPU_ID2_MAKE(7, 2, 1, 1, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tGOx_r0p0", + .gpu_id = GPU_ID2_MAKE(7, 2, 2, 2, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tGOx_r1p0", + .gpu_id = GPU_ID2_MAKE(7, 4, 0, 2, 1, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), + .core_features = 0x2, + .tiler_features = 0x209, + .mmu_features = 0x2823, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tTRx", + .gpu_id = GPU_ID2_MAKE(9, 0, 8, 0, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tNAx", + .gpu_id = GPU_ID2_MAKE(9, 0, 8, 1, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tBEx", + .gpu_id = GPU_ID2_MAKE(9, 2, 0, 2, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tBAx", + .gpu_id = GPU_ID2_MAKE(9, 14, 4, 5, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tDUx", + .gpu_id = GPU_ID2_MAKE(10, 2, 0, 1, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tODx", + .gpu_id = GPU_ID2_MAKE(10, 8, 0, 2, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tGRx", + .gpu_id = GPU_ID2_MAKE(10, 10, 0, 3, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), + .core_features = 0x0, /* core_1e16fma2tex */ + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tVAx", + .gpu_id = GPU_ID2_MAKE(10, 12, 0, 4, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x180, + .thread_max_workgroup_size = 0x180, + .thread_max_barrier_size = 0x180, + .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), + .core_features = 0x0, /* core_1e16fma2tex */ + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0, + .gpu_features_hi = 0, + .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, + .stack_present = DUMMY_IMPLEMENTATION_STACK_PRESENT, + }, + { + .name = "tTUx", + .gpu_id = GPU_ID2_MAKE(11, 8, 5, 2, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x800, + .thread_max_workgroup_size = 0x400, + .thread_max_barrier_size = 0x400, + .thread_features = THREAD_FEATURES_PARTIAL(0x10000, 4, 0), + .core_features = 0x0, /* core_1e32fma2tex */ + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0xf, + .gpu_features_hi = 0, + .shader_present = 0xFF, + .stack_present = 0xF, + }, + { + .name = "tTIx", + .gpu_id = GPU_ID2_MAKE(12, 8, 1, 0, 0, 0, 0), + .as_present = 0xFF, + .thread_max_threads = 0x800, + .thread_max_workgroup_size = 0x400, + .thread_max_barrier_size = 0x400, + .thread_features = THREAD_FEATURES_PARTIAL(0x10000, 16, 0), + .core_features = 0x1, /* core_1e64fma4tex */ + .tiler_features = 0x809, + .mmu_features = 0x2830, + .gpu_features_lo = 0xf, + .gpu_features_hi = 0, + .shader_present = 0xFF, + .stack_present = 0xF, + }, +}; + +static struct { spinlock_t access_lock; #if !MALI_USE_CSF unsigned long prfcnt_base; @@ -125,74 +454,33 @@ struct { #endif /* !MALI_USE_CSF */ u64 tiler_counters[KBASE_DUMMY_MODEL_COUNTER_PER_CORE]; u64 l2_counters[KBASE_DUMMY_MODEL_MAX_MEMSYS_BLOCKS * - KBASE_DUMMY_MODEL_COUNTER_PER_CORE]; + KBASE_DUMMY_MODEL_COUNTER_PER_CORE]; u64 shader_counters[KBASE_DUMMY_MODEL_MAX_SHADER_CORES * - KBASE_DUMMY_MODEL_COUNTER_PER_CORE]; + KBASE_DUMMY_MODEL_COUNTER_PER_CORE]; +} performance_counters; -} performance_counters = { - .l2_present = DUMMY_IMPLEMENTATION_L2_PRESENT, - .shader_present = DUMMY_IMPLEMENTATION_SHADER_PRESENT, -}; +static u32 get_implementation_register(u32 reg, + const struct control_reg_values_t *const control_reg_values) +{ + switch (reg) { + case GPU_CONTROL_REG(SHADER_PRESENT_LO): + return LO_MASK(control_reg_values->shader_present); + case GPU_CONTROL_REG(TILER_PRESENT_LO): + return LO_MASK(DUMMY_IMPLEMENTATION_TILER_PRESENT); + case GPU_CONTROL_REG(L2_PRESENT_LO): + return LO_MASK(DUMMY_IMPLEMENTATION_L2_PRESENT); + case GPU_CONTROL_REG(STACK_PRESENT_LO): + return LO_MASK(control_reg_values->stack_present); -struct job_slot { - int job_active; - int job_queued; - int job_complete_irq_asserted; - int job_irq_mask; - int job_disabled; -}; - -/** - * struct control_reg_values_t - control register values specific to the GPU being 'emulated' - * @name: GPU name - * @gpu_id: GPU ID to report - * @as_present: Bitmap of address spaces present - * @thread_max_threads: Maximum number of threads per core - * @thread_max_workgroup_size: Maximum number of threads per workgroup - * @thread_max_barrier_size: Maximum number of threads per barrier - * @thread_features: Thread features, NOT INCLUDING the 2 - * most-significant bits, which are always set to - * IMPLEMENTATION_MODEL. - * @core_features: Core features - * @tiler_features: Tiler features - * @mmu_features: MMU features - * @gpu_features_lo: GPU features (low) - * @gpu_features_hi: GPU features (high) - */ -struct control_reg_values_t { - const char *name; - u32 gpu_id; - u32 as_present; - u32 thread_max_threads; - u32 thread_max_workgroup_size; - u32 thread_max_barrier_size; - u32 thread_features; - u32 core_features; - u32 tiler_features; - u32 mmu_features; - u32 gpu_features_lo; - u32 gpu_features_hi; -}; - -struct dummy_model_t { - int reset_completed; - int reset_completed_mask; -#if !MALI_USE_CSF - int prfcnt_sample_completed; -#endif /* !MALI_USE_CSF */ - int power_changed_mask; /* 2bits: _ALL,_SINGLE */ - int power_changed; /* 1bit */ - bool clean_caches_completed; - bool clean_caches_completed_irq_enabled; - int power_on; /* 6bits: SHADER[4],TILER,L2 */ - u32 stack_power_on_lo; - u32 coherency_enable; - unsigned int job_irq_js_state; - struct job_slot slots[NUM_SLOTS]; - const struct control_reg_values_t *control_reg_values; - u32 l2_config; - void *data; -}; + case GPU_CONTROL_REG(SHADER_PRESENT_HI): + case GPU_CONTROL_REG(TILER_PRESENT_HI): + case GPU_CONTROL_REG(L2_PRESENT_HI): + case GPU_CONTROL_REG(STACK_PRESENT_HI): + /* *** FALLTHROUGH *** */ + default: + return 0; + } +} void gpu_device_set_data(void *model, void *data) { @@ -221,238 +509,6 @@ static char *no_mali_gpu = CONFIG_MALI_NO_MALI_DEFAULT_GPU; module_param(no_mali_gpu, charp, 0000); MODULE_PARM_DESC(no_mali_gpu, "GPU to identify as"); -/* Construct a value for the THREAD_FEATURES register, *except* the two most - * significant bits, which are set to IMPLEMENTATION_MODEL in - * midgard_model_read_reg(). - */ -#if MALI_USE_CSF -#define THREAD_FEATURES_PARTIAL(MAX_REGISTERS, MAX_TASK_QUEUE, MAX_TG_SPLIT) \ - ((MAX_REGISTERS) | ((MAX_TASK_QUEUE) << 24)) -#else -#define THREAD_FEATURES_PARTIAL(MAX_REGISTERS, MAX_TASK_QUEUE, MAX_TG_SPLIT) \ - ((MAX_REGISTERS) | ((MAX_TASK_QUEUE) << 16) | ((MAX_TG_SPLIT) << 24)) -#endif - -/* Array associating GPU names with control register values. The first - * one is used in the case of no match. - */ -static const struct control_reg_values_t all_control_reg_values[] = { - { - .name = "tMIx", - .gpu_id = GPU_ID2_MAKE(6, 0, 10, 0, 0, 1, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tHEx", - .gpu_id = GPU_ID2_MAKE(6, 2, 0, 1, 0, 3, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tSIx", - .gpu_id = GPU_ID2_MAKE(7, 0, 0, 0, 1, 1, 0), - .as_present = 0xFF, - .thread_max_threads = 0x300, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), - .tiler_features = 0x209, - .mmu_features = 0x2821, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tDVx", - .gpu_id = GPU_ID2_MAKE(7, 0, 0, 3, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x300, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), - .tiler_features = 0x209, - .mmu_features = 0x2821, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tNOx", - .gpu_id = GPU_ID2_MAKE(7, 2, 1, 1, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tGOx_r0p0", - .gpu_id = GPU_ID2_MAKE(7, 2, 2, 2, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tGOx_r1p0", - .gpu_id = GPU_ID2_MAKE(7, 4, 0, 2, 1, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 10), - .core_features = 0x2, - .tiler_features = 0x209, - .mmu_features = 0x2823, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tTRx", - .gpu_id = GPU_ID2_MAKE(9, 0, 8, 0, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tNAx", - .gpu_id = GPU_ID2_MAKE(9, 0, 8, 1, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tBEx", - .gpu_id = GPU_ID2_MAKE(9, 2, 0, 2, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tBAx", - .gpu_id = GPU_ID2_MAKE(9, 14, 4, 5, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tDUx", - .gpu_id = GPU_ID2_MAKE(10, 2, 0, 1, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tODx", - .gpu_id = GPU_ID2_MAKE(10, 8, 0, 2, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tGRx", - .gpu_id = GPU_ID2_MAKE(10, 10, 0, 3, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), - .core_features = 0x0, /* core_1e16fma2tex */ - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tVAx", - .gpu_id = GPU_ID2_MAKE(10, 12, 0, 4, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x180, - .thread_max_workgroup_size = 0x180, - .thread_max_barrier_size = 0x180, - .thread_features = THREAD_FEATURES_PARTIAL(0x6000, 4, 0), - .core_features = 0x0, /* core_1e16fma2tex */ - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0, - .gpu_features_hi = 0, - }, - { - .name = "tTUx", - .gpu_id = GPU_ID2_MAKE(11, 8, 5, 2, 0, 0, 0), - .as_present = 0xFF, - .thread_max_threads = 0x800, - .thread_max_workgroup_size = 0x400, - .thread_max_barrier_size = 0x400, - .thread_features = THREAD_FEATURES_PARTIAL(0x10000, 4, 0), - .core_features = 0x0, /* core_1e32fma2tex */ - .tiler_features = 0x809, - .mmu_features = 0x2830, - .gpu_features_lo = 0xf, - .gpu_features_hi = 0, - }, -}; - -struct error_status_t hw_error_status; - #if MALI_USE_CSF static u32 gpu_model_get_prfcnt_value(enum kbase_ipa_core_type core_type, u32 cnt_idx, bool is_low_word) @@ -1011,6 +1067,21 @@ static const struct control_reg_values_t *find_control_reg_values(const char *gp size_t i; const struct control_reg_values_t *ret = NULL; + /* Edge case for tGOx, as it has 2 entries in the table for its R0 and R1 + * revisions respectively. As none of them are named "tGOx" the name comparison + * needs to be fixed in these cases. CONFIG_GPU_HWVER should be one of "r0p0" + * or "r1p0" and is derived from the DDK's build configuration. In cases + * where it is unavailable, it defaults to tGOx r1p0. + */ + if (!strcmp(gpu, "tGOx")) { +#ifdef CONFIG_GPU_HWVER + if (!strcmp(CONFIG_GPU_HWVER, "r0p0")) + gpu = "tGOx_r0p0"; + else if (!strcmp(CONFIG_GPU_HWVER, "r1p0")) +#endif /* CONFIG_GPU_HWVER defined */ + gpu = "tGOx_r1p0"; + } + for (i = 0; i < ARRAY_SIZE(all_control_reg_values); ++i) { const struct control_reg_values_t * const fcrv = &all_control_reg_values[i]; @@ -1043,6 +1114,10 @@ void *midgard_model_create(const void *config) dummy->job_irq_js_state = 0; init_register_statuses(dummy); dummy->control_reg_values = find_control_reg_values(no_mali_gpu); + performance_counters.l2_present = get_implementation_register( + GPU_CONTROL_REG(L2_PRESENT_LO), dummy->control_reg_values); + performance_counters.shader_present = get_implementation_register( + GPU_CONTROL_REG(SHADER_PRESENT_LO), dummy->control_reg_values); } return dummy; } @@ -1066,6 +1141,8 @@ static void midgard_model_get_outputs(void *h) hw_error_status.gpu_error_irq || #if !MALI_USE_CSF dummy->prfcnt_sample_completed || +#else + (dummy->flush_pa_range_completed && dummy->flush_pa_range_completed_irq_enabled) || #endif (dummy->clean_caches_completed && dummy->clean_caches_completed_irq_enabled)) gpu_device_raise_irq(dummy, GPU_DUMMY_GPU_IRQ); @@ -1235,6 +1312,9 @@ u8 midgard_model_write_reg(void *h, u32 addr, u32 value) dummy->reset_completed_mask = (value >> 8) & 0x01; dummy->power_changed_mask = (value >> 9) & 0x03; dummy->clean_caches_completed_irq_enabled = (value & (1u << 17)) != 0u; +#if MALI_USE_CSF + dummy->flush_pa_range_completed_irq_enabled = (value & (1u << 20)) != 0u; +#endif } else if (addr == GPU_CONTROL_REG(COHERENCY_ENABLE)) { dummy->coherency_enable = value; } else if (addr == GPU_CONTROL_REG(GPU_IRQ_CLEAR)) { @@ -1247,10 +1327,17 @@ 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 (value & PRFCNT_SAMPLE_COMPLETED) + +#if MALI_USE_CSF + if (value & (1u << 20)) + dummy->flush_pa_range_completed = false; +#endif /* MALI_USE_CSF */ + +#if !MALI_USE_CSF + if (value & PRFCNT_SAMPLE_COMPLETED) /* (1 << 16) */ dummy->prfcnt_sample_completed = 0; #endif /* !MALI_USE_CSF */ + /*update error status */ hw_error_status.gpu_error_irq &= ~(value); } else if (addr == GPU_CONTROL_REG(GPU_COMMAND)) { @@ -1274,7 +1361,15 @@ 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_FLUSH_PA_RANGE_CLN_INV_L2: + case GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_L2_LSC: + case GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_FULL: + pr_debug("pa range flush requested"); + dummy->flush_pa_range_completed = true; + break; +#endif /* MALI_USE_CSF */ +#if !MALI_USE_CSF case GPU_COMMAND_PRFCNT_SAMPLE: midgard_model_dump_prfcnt(); dummy->prfcnt_sample_completed = 1; @@ -1282,6 +1377,11 @@ u8 midgard_model_write_reg(void *h, u32 addr, u32 value) default: break; } +#if MALI_USE_CSF + } else if (addr >= GPU_CONTROL_REG(GPU_COMMAND_ARG0_LO) && + addr <= GPU_CONTROL_REG(GPU_COMMAND_ARG1_HI)) { + /* Writes ignored */ +#endif } else if (addr == GPU_CONTROL_REG(L2_CONFIG)) { dummy->l2_config = value; } @@ -1291,6 +1391,12 @@ u8 midgard_model_write_reg(void *h, u32 addr, u32 value) (CSF_NUM_DOORBELL * CSF_HW_DOORBELL_PAGE_SIZE))) { if (addr == GPU_CONTROL_REG(CSF_HW_DOORBELL_PAGE_OFFSET)) hw_error_status.job_irq_status = JOB_IRQ_GLOBAL_IF; + } else if ((addr >= GPU_CONTROL_REG(SYSC_ALLOC0)) && + (addr < GPU_CONTROL_REG(SYSC_ALLOC(SYSC_ALLOC_COUNT)))) { + /* Do nothing */ + } else if ((addr >= GPU_CONTROL_REG(ASN_HASH_0)) && + (addr < GPU_CONTROL_REG(ASN_HASH(ASN_HASH_COUNT)))) { + /* Do nothing */ } else if (addr == IPA_CONTROL_REG(COMMAND)) { pr_debug("Received IPA_CONTROL command"); } else if (addr == IPA_CONTROL_REG(TIMER)) { @@ -1315,8 +1421,7 @@ u8 midgard_model_write_reg(void *h, u32 addr, u32 value) hw_error_status.mmu_irq_mask = value; } else if (addr == MMU_REG(MMU_IRQ_CLEAR)) { hw_error_status.mmu_irq_rawstat &= (~value); - } else if ((addr >= MMU_AS_REG(0, AS_TRANSTAB_LO)) && - (addr <= MMU_AS_REG(15, AS_STATUS))) { + } else if ((addr >= MMU_AS_REG(0, AS_TRANSTAB_LO)) && (addr <= MMU_AS_REG(15, AS_STATUS))) { int mem_addr_space = (addr - MMU_AS_REG(0, AS_TRANSTAB_LO)) >> 6; @@ -1443,7 +1548,8 @@ u8 midgard_model_write_reg(void *h, u32 addr, u32 value) dummy->power_changed = 1; break; case SHADER_PWRON_LO: - dummy->power_on |= (value & 0xF) << 2; + dummy->power_on |= + (value & dummy->control_reg_values->shader_present) << 2; dummy->power_changed = 1; break; case L2_PWRON_LO: @@ -1459,7 +1565,8 @@ u8 midgard_model_write_reg(void *h, u32 addr, u32 value) dummy->power_changed = 1; break; case SHADER_PWROFF_LO: - dummy->power_on &= ~((value & 0xF) << 2); + dummy->power_on &= + ~((value & dummy->control_reg_values->shader_present) << 2); dummy->power_changed = 1; break; case L2_PWROFF_LO: @@ -1546,6 +1653,9 @@ u8 midgard_model_read_reg(void *h, u32 addr, u32 * const value) else if (addr == GPU_CONTROL_REG(GPU_IRQ_MASK)) { *value = (dummy->reset_completed_mask << 8) | ((dummy->clean_caches_completed_irq_enabled ? 1u : 0u) << 17) | +#if MALI_USE_CSF + ((dummy->flush_pa_range_completed_irq_enabled ? 1u : 0u) << 20) | +#endif (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)) { @@ -1555,6 +1665,9 @@ u8 midgard_model_read_reg(void *h, u32 addr, u32 * const value) (dummy->prfcnt_sample_completed ? PRFCNT_SAMPLE_COMPLETED : 0) | #endif /* !MALI_USE_CSF */ ((dummy->clean_caches_completed ? 1u : 0u) << 17) | +#if MALI_USE_CSF + ((dummy->flush_pa_range_completed ? 1u : 0u) << 20) | +#endif hw_error_status.gpu_error_irq; pr_debug("GPU_IRQ_RAWSTAT read %x", *value); } else if (addr == GPU_CONTROL_REG(GPU_IRQ_STATUS)) { @@ -1569,6 +1682,13 @@ u8 midgard_model_read_reg(void *h, u32 addr, u32 * const value) 1u : 0u) << 17) | +#if MALI_USE_CSF + (((dummy->flush_pa_range_completed && + dummy->flush_pa_range_completed_irq_enabled) ? + 1u : + 0u) + << 20) | +#endif hw_error_status.gpu_error_irq; pr_debug("GPU_IRQ_STAT read %x", *value); } else if (addr == GPU_CONTROL_REG(GPU_STATUS)) { @@ -1581,8 +1701,18 @@ u8 midgard_model_read_reg(void *h, u32 addr, u32 * const value) *value = hw_error_status.gpu_fault_status; } else if (addr == GPU_CONTROL_REG(L2_CONFIG)) { *value = dummy->l2_config; - } else if ((addr >= GPU_CONTROL_REG(SHADER_PRESENT_LO)) && - (addr <= GPU_CONTROL_REG(L2_MMU_CONFIG))) { + } +#if MALI_USE_CSF + else if ((addr >= GPU_CONTROL_REG(SYSC_ALLOC0)) && + (addr < GPU_CONTROL_REG(SYSC_ALLOC(SYSC_ALLOC_COUNT)))) { + *value = 0; + } else if ((addr >= GPU_CONTROL_REG(ASN_HASH_0)) && + (addr < GPU_CONTROL_REG(ASN_HASH(ASN_HASH_COUNT)))) { + *value = 0; + } +#endif + else if ((addr >= GPU_CONTROL_REG(SHADER_PRESENT_LO)) && + (addr <= GPU_CONTROL_REG(L2_MMU_CONFIG))) { switch (addr) { case GPU_CONTROL_REG(SHADER_PRESENT_LO): case GPU_CONTROL_REG(SHADER_PRESENT_HI): @@ -1592,27 +1722,27 @@ u8 midgard_model_read_reg(void *h, u32 addr, u32 * const value) case GPU_CONTROL_REG(L2_PRESENT_HI): case GPU_CONTROL_REG(STACK_PRESENT_LO): case GPU_CONTROL_REG(STACK_PRESENT_HI): - *value = get_implementation_register(addr); + *value = get_implementation_register(addr, dummy->control_reg_values); break; case GPU_CONTROL_REG(SHADER_READY_LO): *value = (dummy->power_on >> 0x02) & - get_implementation_register( - GPU_CONTROL_REG(SHADER_PRESENT_LO)); + get_implementation_register(GPU_CONTROL_REG(SHADER_PRESENT_LO), + dummy->control_reg_values); break; case GPU_CONTROL_REG(TILER_READY_LO): *value = (dummy->power_on >> 0x01) & - get_implementation_register( - GPU_CONTROL_REG(TILER_PRESENT_LO)); + get_implementation_register(GPU_CONTROL_REG(TILER_PRESENT_LO), + dummy->control_reg_values); break; case GPU_CONTROL_REG(L2_READY_LO): *value = dummy->power_on & - get_implementation_register( - GPU_CONTROL_REG(L2_PRESENT_LO)); + get_implementation_register(GPU_CONTROL_REG(L2_PRESENT_LO), + dummy->control_reg_values); break; case GPU_CONTROL_REG(STACK_READY_LO): *value = dummy->stack_power_on_lo & - get_implementation_register( - GPU_CONTROL_REG(STACK_PRESENT_LO)); + get_implementation_register(GPU_CONTROL_REG(STACK_PRESENT_LO), + dummy->control_reg_values); break; case GPU_CONTROL_REG(SHADER_READY_HI): @@ -1904,6 +2034,8 @@ u8 midgard_model_read_reg(void *h, u32 addr, u32 * const value) *value = gpu_model_get_prfcnt_value(KBASE_IPA_CORE_TYPE_SHADER, counter_index, is_low_word); + } else if (addr == USER_REG(LATEST_FLUSH)) { + *value = 0; } #endif else if (addr == GPU_CONTROL_REG(GPU_FEATURES_LO)) { diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_model_error_generator.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_model_error_generator.c index 344046089d6e..972d1c87fb1a 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_model_error_generator.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_model_error_generator.c @@ -23,13 +23,6 @@ #include #include "backend/gpu/mali_kbase_model_dummy.h" -/* all the error conditions supported by the model */ -#define TOTAL_FAULTS 27 -/* maximum number of levels in the MMU translation table tree */ -#define MAX_MMU_TABLE_LEVEL 4 -/* worst case scenario is <1 MMU fault + 1 job fault + 2 GPU faults> */ -#define MAX_CONCURRENT_FAULTS 3 - static struct kbase_error_atom *error_track_list; unsigned int rand_seed; @@ -40,6 +33,14 @@ unsigned int error_probability = 50; /* to be set between 0 and 100 */ unsigned int multiple_error_probability = 50; #ifdef CONFIG_MALI_ERROR_INJECT_RANDOM + +/* all the error conditions supported by the model */ +#define TOTAL_FAULTS 27 +/* maximum number of levels in the MMU translation table tree */ +#define MAX_MMU_TABLE_LEVEL 4 +/* worst case scenario is <1 MMU fault + 1 job fault + 2 GPU faults> */ +#define MAX_CONCURRENT_FAULTS 3 + /** * gpu_generate_error - Generate GPU error */ 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 df735d95de9f..5c71fdf154b9 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 @@ -36,7 +36,7 @@ #include #include #endif /* !MALI_USE_CSF */ -#include +#include #include #include #include diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c index d9e3dfcc6994..9e38b904b459 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_ca.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2013-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2013-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 @@ -92,29 +92,10 @@ void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask) * for those cores to get powered down */ if ((core_mask & old_core_mask) != old_core_mask) { - bool can_wait; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - can_wait = kbdev->pm.backend.gpu_ready && kbase_pm_is_mcu_desired(kbdev); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - /* This check is ideally not required, the wait function can - * deal with the GPU power down. But it has been added to - * address the scenario where down-scaling request comes from - * the platform specific code soon after the GPU power down - * and at the time same time application thread tries to - * power up the GPU (on the flush of GPU queue). - * The platform specific @ref callback_power_on that gets - * invoked on power up does not return until down-scaling - * request is complete. The check mitigates the race caused by - * the problem in platform specific code. - */ - if (likely(can_wait)) { - if (kbase_pm_wait_for_desired_state(kbdev)) { - dev_warn(kbdev->dev, - "Wait for update of core_mask from %llx to %llx failed", - old_core_mask, core_mask); - } + if (kbase_pm_wait_for_cores_down_scale(kbdev)) { + dev_warn(kbdev->dev, + "Wait for update of core_mask from %llx to %llx failed", + old_core_mask, core_mask); } } #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 94b87ce7166b..8173cf6ba7d7 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 @@ -39,7 +39,7 @@ #include #include -#include +#include #include #include #include @@ -538,6 +538,14 @@ static void kbase_pm_l2_config_override(struct kbase_device *kbdev) if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_L2_CONFIG)) return; +#if MALI_USE_CSF + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PBHA_HWU)) { + val = kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_CONFIG)); + kbase_reg_write(kbdev, GPU_CONTROL_REG(L2_CONFIG), + L2_CONFIG_PBHA_HWU_SET(val, kbdev->pbha_propagate_bits)); + } +#endif /* MALI_USE_CSF */ + /* * Skip if size and hash are not given explicitly, * which means default values are used. @@ -599,6 +607,21 @@ static const char *kbase_mcu_state_to_string(enum kbase_mcu_state state) return strings[state]; } +static +void kbase_ktrace_log_mcu_state(struct kbase_device *kbdev, enum kbase_mcu_state state) +{ +#if KBASE_KTRACE_ENABLE + switch (state) { +#define KBASEP_MCU_STATE(n) \ + case KBASE_MCU_ ## n: \ + KBASE_KTRACE_ADD(kbdev, PM_MCU_ ## n, NULL, state); \ + break; +#include "mali_kbase_pm_mcu_states.h" +#undef KBASEP_MCU_STATE + } +#endif +} + static inline bool kbase_pm_handle_mcu_core_attr_update(struct kbase_device *kbdev) { struct kbase_pm_backend_data *backend = &kbdev->pm.backend; @@ -689,7 +712,6 @@ static void wait_mcu_as_inactive(struct kbase_device *kbdev) } #endif - /** * kbasep_pm_toggle_power_interrupt - Toggles the IRQ mask for power interrupts * from the firmware @@ -697,10 +719,10 @@ static void wait_mcu_as_inactive(struct kbase_device *kbdev) * @kbdev: Pointer to the device * @enable: boolean indicating to enable interrupts or not * - * The POWER_CHANGED_ALL and POWER_CHANGED_SINGLE interrupts can be disabled - * after L2 has been turned on when FW is controlling the power for the shader - * cores. Correspondingly, the interrupts can be re-enabled after the MCU has - * been disabled before the power down of L2. + * The POWER_CHANGED_ALL interrupt can be disabled after L2 has been turned on + * when FW is controlling the power for the shader cores. Correspondingly, the + * interrupts can be re-enabled after the MCU has been disabled before the + * power down of L2. */ static void kbasep_pm_toggle_power_interrupt(struct kbase_device *kbdev, bool enable) { @@ -710,10 +732,12 @@ static void kbasep_pm_toggle_power_interrupt(struct kbase_device *kbdev, bool en irq_mask = kbase_reg_read(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK)); - if (enable) - irq_mask |= POWER_CHANGED_ALL | POWER_CHANGED_SINGLE; - else - irq_mask &= ~(POWER_CHANGED_ALL | POWER_CHANGED_SINGLE); + if (enable) { + irq_mask |= POWER_CHANGED_ALL; + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), POWER_CHANGED_ALL); + } else { + irq_mask &= ~POWER_CHANGED_ALL; + } kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_MASK), irq_mask); } @@ -1028,10 +1052,12 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) backend->mcu_state); } - if (backend->mcu_state != prev_state) + if (backend->mcu_state != prev_state) { dev_dbg(kbdev->dev, "MCU state transition: %s to %s\n", kbase_mcu_state_to_string(prev_state), kbase_mcu_state_to_string(backend->mcu_state)); + kbase_ktrace_log_mcu_state(kbdev, backend->mcu_state); + } } while (backend->mcu_state != prev_state); @@ -1079,6 +1105,21 @@ static const char *kbase_l2_core_state_to_string(enum kbase_l2_core_state state) return strings[state]; } +static +void kbase_ktrace_log_l2_core_state(struct kbase_device *kbdev, enum kbase_l2_core_state state) +{ +#if KBASE_KTRACE_ENABLE + switch (state) { +#define KBASEP_L2_STATE(n) \ + case KBASE_L2_ ## n: \ + KBASE_KTRACE_ADD(kbdev, PM_L2_ ## n, NULL, state); \ + break; +#include "mali_kbase_pm_l2_states.h" +#undef KBASEP_L2_STATE + } +#endif +} + #if !MALI_USE_CSF /* On powering on the L2, the tracked kctx becomes stale and can be cleared. * This enables the backend to spare the START_FLUSH.INV_SHADER_OTHER @@ -1136,18 +1177,13 @@ 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); -#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); +#ifdef CONFIG_MALI_ARBITER_SUPPORT /* * 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) - || kbase_pm_is_gpu_lost(kbdev)) { + if (kbase_is_gpu_removed(kbdev) || kbase_pm_is_gpu_lost(kbdev)) { backend->shaders_state = KBASE_SHADERS_OFF_CORESTACK_OFF; backend->hwcnt_desired = false; @@ -1161,16 +1197,19 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) */ backend->l2_state = KBASE_L2_ON_HWCNT_DISABLE; + KBASE_KTRACE_ADD(kbdev, PM_L2_ON_HWCNT_DISABLE, NULL, + backend->l2_state); kbase_pm_trigger_hwcnt_disable(kbdev); } if (backend->hwcnt_disabled) { backend->l2_state = KBASE_L2_OFF; + KBASE_KTRACE_ADD(kbdev, PM_L2_OFF, NULL, backend->l2_state); dev_dbg(kbdev->dev, "GPU lost has occurred - L2 off\n"); } break; } -#endif /* CONFIG_MALI_ARBITER_SUPPORT */ +#endif /* mask off ready from trans in case transitions finished * between the register reads @@ -1182,6 +1221,12 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) switch (backend->l2_state) { case KBASE_L2_OFF: if (kbase_pm_is_l2_desired(kbdev)) { +#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) + /* Enable HW timer of IPA control before + * L2 cache is powered-up. + */ + kbase_ipa_control_handle_gpu_sleep_exit(kbdev); +#endif /* * Set the desired config for L2 before * powering it on @@ -1221,14 +1266,12 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) l2_power_up_done = false; if (!l2_trans && l2_ready == l2_present) { 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, @@ -1437,12 +1480,26 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) /* We only need to check the L2 here - if the L2 * is off then the tiler is definitely also off. */ - if (!l2_trans && !l2_ready) + if (!l2_trans && !l2_ready) { +#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) + /* Allow clock gating within the GPU and prevent it + * from being seen as active during sleep. + */ + kbase_ipa_control_handle_gpu_sleep_enter(kbdev); +#endif /* L2 is now powered off */ backend->l2_state = KBASE_L2_OFF; + } } else { - if (!kbdev->cache_clean_in_progress) + if (!kbdev->cache_clean_in_progress) { +#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) + /* Allow clock gating within the GPU and prevent it + * from being seen as active during sleep. + */ + kbase_ipa_control_handle_gpu_sleep_enter(kbdev); +#endif backend->l2_state = KBASE_L2_OFF; + } } break; @@ -1457,11 +1514,13 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) backend->l2_state); } - if (backend->l2_state != prev_state) + if (backend->l2_state != prev_state) { dev_dbg(kbdev->dev, "L2 state transition: %s to %s\n", kbase_l2_core_state_to_string(prev_state), kbase_l2_core_state_to_string( backend->l2_state)); + kbase_ktrace_log_l2_core_state(kbdev, backend->l2_state); + } } while (backend->l2_state != prev_state); @@ -1925,7 +1984,7 @@ static bool kbase_pm_is_in_desired_state_nolock(struct kbase_device *kbdev) kbdev->pm.backend.shaders_state != KBASE_SHADERS_OFF_CORESTACK_OFF) in_desired_state = false; #else - in_desired_state = kbase_pm_mcu_is_in_desired_state(kbdev); + in_desired_state &= kbase_pm_mcu_is_in_desired_state(kbdev); #endif return in_desired_state; @@ -2122,6 +2181,7 @@ void kbase_pm_reset_start_locked(struct kbase_device *kbdev) backend->in_reset = true; backend->l2_state = KBASE_L2_RESET_WAIT; + KBASE_KTRACE_ADD(kbdev, PM_L2_RESET_WAIT, NULL, backend->l2_state); #if !MALI_USE_CSF backend->shaders_state = KBASE_SHADERS_RESET_WAIT; #else @@ -2130,6 +2190,7 @@ void kbase_pm_reset_start_locked(struct kbase_device *kbdev) */ if (likely(kbdev->csf.firmware_inited)) { backend->mcu_state = KBASE_MCU_RESET_WAIT; + KBASE_KTRACE_ADD(kbdev, PM_MCU_RESET_WAIT, NULL, backend->mcu_state); #ifdef KBASE_PM_RUNTIME backend->exit_gpu_sleep_mode = true; #endif @@ -2328,6 +2389,66 @@ int kbase_pm_wait_for_desired_state(struct kbase_device *kbdev) } KBASE_EXPORT_TEST_API(kbase_pm_wait_for_desired_state); +#if MALI_USE_CSF +/** + * core_mask_update_done - Check if downscaling of shader cores is done + * + * @kbdev: The kbase device structure for the device. + * + * This function checks if the downscaling of cores is effectively complete. + * + * Return: true if the downscale is done. + */ +static bool core_mask_update_done(struct kbase_device *kbdev) +{ + bool update_done = false; + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + /* If MCU is in stable ON state then it implies that the downscale + * request had completed. + * If MCU is not active then it implies all cores are off, so can + * consider the downscale request as complete. + */ + if ((kbdev->pm.backend.mcu_state == KBASE_MCU_ON) || + kbase_pm_is_mcu_inactive(kbdev, kbdev->pm.backend.mcu_state)) + update_done = true; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return update_done; +} + +int kbase_pm_wait_for_cores_down_scale(struct kbase_device *kbdev) +{ + long timeout = kbase_csf_timeout_in_jiffies(kbase_get_timeout_ms(kbdev, CSF_PM_TIMEOUT)); + long remaining; + int err = 0; + + /* Wait for core mask update to complete */ +#if KERNEL_VERSION(4, 13, 1) <= LINUX_VERSION_CODE + remaining = wait_event_killable_timeout( + kbdev->pm.backend.gpu_in_desired_state_wait, + core_mask_update_done(kbdev), timeout); +#else + remaining = wait_event_timeout( + kbdev->pm.backend.gpu_in_desired_state_wait, + core_mask_update_done(kbdev), timeout); +#endif + + if (!remaining) { + kbase_pm_timed_out(kbdev); + err = -ETIMEDOUT; + } else if (remaining < 0) { + dev_info( + kbdev->dev, + "Wait for cores down scaling got interrupted"); + err = (int)remaining; + } + + return err; +} +#endif + void kbase_pm_enable_interrupts(struct kbase_device *kbdev) { unsigned long flags; @@ -2391,19 +2512,25 @@ static void update_user_reg_page_mapping(struct kbase_device *kbdev) lockdep_assert_held(&kbdev->pm.lock); mutex_lock(&kbdev->csf.reg_lock); - if (kbdev->csf.mali_file_inode) { - /* This would zap the pte corresponding to the mapping of User - * register page for all the Kbase contexts. - */ - unmap_mapping_range(kbdev->csf.mali_file_inode->i_mapping, - BASEP_MEM_CSF_USER_REG_PAGE_HANDLE, - PAGE_SIZE, 1); + + /* Only if the mappings for USER page exist, update all PTEs associated to it */ + if (kbdev->csf.nr_user_page_mapped > 0) { + if (likely(kbdev->csf.mali_file_inode)) { + /* This would zap the pte corresponding to the mapping of User + * register page for all the Kbase contexts. + */ + unmap_mapping_range(kbdev->csf.mali_file_inode->i_mapping, + BASEP_MEM_CSF_USER_REG_PAGE_HANDLE, PAGE_SIZE, 1); + } else { + dev_err(kbdev->dev, + "Device file inode not exist even if USER page previously mapped"); + } } + mutex_unlock(&kbdev->csf.reg_lock); } #endif - /* * pmu layout: * 0x0000: PMU TAG (RO) (0xCAFECAFE) @@ -2541,7 +2668,6 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume) backend->gpu_idled = false; } #endif - } KBASE_EXPORT_TEST_API(kbase_pm_clock_on); diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h index dddc10550306..115cd3c34d90 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_pm_internal.h @@ -269,6 +269,37 @@ int kbase_pm_wait_for_desired_state(struct kbase_device *kbdev); */ int kbase_pm_wait_for_l2_powered(struct kbase_device *kbdev); +#if MALI_USE_CSF +/** + * kbase_pm_wait_for_cores_down_scale - Wait for the downscaling of shader cores + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * This function can be called to ensure that the downscaling of cores is + * effectively complete and it would be safe to lower the voltage. + * The function assumes that caller had exercised the MCU state machine for the + * downscale request through the kbase_pm_update_state() function. + * + * This function needs to be used by the caller to safely wait for the completion + * of downscale request, instead of kbase_pm_wait_for_desired_state(). + * The downscale request would trigger a state change in MCU state machine + * and so when MCU reaches the stable ON state, it can be inferred that + * downscaling is complete. But it has been observed that the wake up of the + * waiting thread can get delayed by few milli seconds and by the time the + * thread wakes up the power down transition could have started (after the + * completion of downscale request). + * On the completion of power down transition another wake up signal would be + * sent, but again by the time thread wakes up the power up transition can begin. + * And the power up transition could then get blocked inside the platform specific + * callback_power_on() function due to the thread that called into Kbase (from the + * platform specific code) to perform the downscaling and then ended up waiting + * for the completion of downscale request. + * + * Return: 0 on success, error code on error or remaining jiffies on timeout. + */ +int kbase_pm_wait_for_cores_down_scale(struct kbase_device *kbdev); +#endif + /** * kbase_pm_update_dynamic_cores_onoff - Update the L2 and shader power state * machines after changing shader core 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 4cc2d50db586..29e945d00fbe 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 @@ -38,11 +38,13 @@ #include #include +#if defined(CONFIG_MALI_BIFROST_DEVFREQ) || defined(CONFIG_MALI_BIFROST_DVFS) || !MALI_USE_CSF /* Shift used for kbasep_pm_metrics_data.time_busy/idle - units of (1 << 8) ns * This gives a maximum period between samples of 2^(32+8)/100 ns = slightly * under 11s. Exceeding this will cause overflow */ #define KBASE_PM_TIME_SHIFT 8 +#endif #if MALI_USE_CSF /* To get the GPU_ACTIVE value in nano seconds unit */ diff --git a/drivers/gpu/arm/bifrost/build.bp b/drivers/gpu/arm/bifrost/build.bp index 977d13961786..a17ff432398c 100644 --- a/drivers/gpu/arm/bifrost/build.bp +++ b/drivers/gpu/arm/bifrost/build.bp @@ -32,6 +32,7 @@ bob_defaults { kbuild_options: [ "CONFIG_MALI_BIFROST_NO_MALI=y", "CONFIG_MALI_NO_MALI_DEFAULT_GPU={{.gpu}}", + "CONFIG_GPU_HWVER={{.hwver}}", ], }, mali_platform_dt_pin_rst: { @@ -52,9 +53,6 @@ bob_defaults { mali_midgard_enable_trace: { kbuild_options: ["CONFIG_MALI_BIFROST_ENABLE_TRACE=y"], }, - mali_dma_fence: { - kbuild_options: ["CONFIG_MALI_BIFROST_DMA_FENCE=y"], - }, mali_arbiter_support: { kbuild_options: ["CONFIG_MALI_ARBITER_SUPPORT=y"], }, @@ -64,7 +62,7 @@ bob_defaults { mali_dma_buf_legacy_compat: { kbuild_options: ["CONFIG_MALI_DMA_BUF_LEGACY_COMPAT=y"], }, - mali_2mb_alloc: { + large_page_alloc: { kbuild_options: ["CONFIG_MALI_2MB_ALLOC=y"], }, mali_memory_fully_backed: { @@ -89,7 +87,7 @@ bob_defaults { kbuild_options: ["CONFIG_MALI_BIFROST_ERROR_INJECT=y"], }, mali_gem5_build: { - kbuild_options: ["CONFIG_MALI_GEM5_BUILD=y"], + kbuild_options: ["CONFIG_MALI_GEM5_BUILD=y"], }, mali_debug: { kbuild_options: [ @@ -163,9 +161,7 @@ bob_defaults { // (catch-all for experimental CS code without separating it into // different features). "MALI_INCREMENTAL_RENDERING_JM={{.incremental_rendering_jm}}", - "MALI_GPU_TIMESTAMP_CORRECTION={{.gpu_timestamp_correction}}", "MALI_BASE_CSF_PERFORMANCE_TESTS={{.base_csf_performance_tests}}", - "MALI_GPU_TIMESTAMP_INTERPOLATION={{.gpu_timestamp_interpolation}}", ], } @@ -184,6 +180,10 @@ bob_kernel_module { "context/*.c", "context/*.h", "context/Kbuild", + "hwcnt/*.c", + "hwcnt/*.h", + "hwcnt/backend/*.h", + "hwcnt/Kbuild", "ipa/*.c", "ipa/*.h", "ipa/Kbuild", @@ -217,6 +217,10 @@ bob_kernel_module { "device/backend/*_jm.c", "gpu/backend/*_jm.c", "gpu/backend/*_jm.h", + "hwcnt/backend/*_jm.c", + "hwcnt/backend/*_jm.h", + "hwcnt/backend/*_jm_*.c", + "hwcnt/backend/*_jm_*.h", "jm/*.h", "tl/backend/*_jm.c", "mmu/backend/*_jm.c", @@ -238,6 +242,10 @@ bob_kernel_module { "device/backend/*_csf.c", "gpu/backend/*_csf.c", "gpu/backend/*_csf.h", + "hwcnt/backend/*_csf.c", + "hwcnt/backend/*_csf.h", + "hwcnt/backend/*_csf_*.c", + "hwcnt/backend/*_csf_*.h", "tl/backend/*_csf.c", "mmu/backend/*_csf.c", "ipa/backend/*_csf.c", diff --git a/drivers/gpu/arm/bifrost/context/backend/mali_kbase_context_csf.c b/drivers/gpu/arm/bifrost/context/backend/mali_kbase_context_csf.c index 32bf82526aa3..3abc7a2a66f4 100644 --- a/drivers/gpu/arm/bifrost/context/backend/mali_kbase_context_csf.c +++ b/drivers/gpu/arm/bifrost/context/backend/mali_kbase_context_csf.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -39,12 +38,14 @@ #include #include #include +#include #include void kbase_context_debugfs_init(struct kbase_context *const kctx) { kbase_debug_mem_view_init(kctx); kbase_debug_mem_zones_init(kctx); + kbase_debug_mem_allocs_init(kctx); kbase_mem_pool_debugfs_init(kctx->kctx_dentry, kctx); kbase_jit_debugfs_init(kctx); kbase_csf_queue_group_debugfs_init(kctx); diff --git a/drivers/gpu/arm/bifrost/context/backend/mali_kbase_context_jm.c b/drivers/gpu/arm/bifrost/context/backend/mali_kbase_context_jm.c index 97cd46e0e5b5..995a08e36f43 100644 --- a/drivers/gpu/arm/bifrost/context/backend/mali_kbase_context_jm.c +++ b/drivers/gpu/arm/bifrost/context/backend/mali_kbase_context_jm.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -37,12 +36,14 @@ #if IS_ENABLED(CONFIG_DEBUG_FS) #include #include +#include #include void kbase_context_debugfs_init(struct kbase_context *const kctx) { kbase_debug_mem_view_init(kctx); kbase_debug_mem_zones_init(kctx); + kbase_debug_mem_allocs_init(kctx); kbase_mem_pool_debugfs_init(kctx->kctx_dentry, kctx); kbase_jit_debugfs_init(kctx); kbasep_jd_debugfs_ctx_init(kctx); @@ -128,8 +129,6 @@ static const struct kbase_context_init context_init[] = { { NULL, kbase_context_free, NULL }, { kbase_context_common_init, kbase_context_common_term, "Common context initialization failed" }, - { kbase_dma_fence_init, kbase_dma_fence_term, - "DMA fence initialization failed" }, { kbase_context_mem_pool_group_init, kbase_context_mem_pool_group_term, "Memory pool group initialization failed" }, { kbase_mem_evictable_init, kbase_mem_evictable_deinit, diff --git a/drivers/gpu/arm/bifrost/context/mali_kbase_context.c b/drivers/gpu/arm/bifrost/context/mali_kbase_context.c index f84e01edee93..b6abfc44d212 100644 --- a/drivers/gpu/arm/bifrost/context/mali_kbase_context.c +++ b/drivers/gpu/arm/bifrost/context/mali_kbase_context.c @@ -165,7 +165,9 @@ int kbase_context_common_init(struct kbase_context *kctx) atomic64_set(&kctx->num_fixed_allocs, 0); #endif + kbase_gpu_vm_lock(kctx); bitmap_copy(kctx->cookies, &cookies_mask, BITS_PER_LONG); + kbase_gpu_vm_unlock(kctx); kctx->id = atomic_add_return(1, &(kctx->kbdev->ctx_num)) - 1; @@ -274,10 +276,8 @@ void kbase_context_common_term(struct kbase_context *kctx) int kbase_context_mem_pool_group_init(struct kbase_context *kctx) { - return kbase_mem_pool_group_init(&kctx->mem_pools, - kctx->kbdev, - &kctx->kbdev->mem_pool_defaults, - &kctx->kbdev->mem_pools); + return kbase_mem_pool_group_init(&kctx->mem_pools, kctx->kbdev, + &kctx->kbdev->mem_pool_defaults, &kctx->kbdev->mem_pools); } void kbase_context_mem_pool_group_term(struct kbase_context *kctx) diff --git a/drivers/gpu/arm/bifrost/csf/Kbuild b/drivers/gpu/arm/bifrost/csf/Kbuild index c5d9154a2e35..1474bdaacb0d 100644 --- a/drivers/gpu/arm/bifrost/csf/Kbuild +++ b/drivers/gpu/arm/bifrost/csf/Kbuild @@ -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 @@ -34,12 +34,16 @@ bifrost_kbase-y += \ csf/mali_kbase_csf_protected_memory.o \ csf/mali_kbase_csf_tiler_heap_debugfs.o \ csf/mali_kbase_csf_cpu_queue_debugfs.o \ - csf/mali_kbase_csf_event.o + csf/mali_kbase_csf_event.o \ + csf/mali_kbase_csf_firmware_log.o \ + csf/mali_kbase_csf_tiler_heap_reclaim.o 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 +bifrost_kbase-$(CONFIG_DEBUG_FS) += csf/mali_kbase_debug_csf_fault.o + ifeq ($(KBUILD_EXTMOD),) # in-tree diff --git a/drivers/gpu/arm/bifrost/csf/ipa_control/mali_kbase_csf_ipa_control.c b/drivers/gpu/arm/bifrost/csf/ipa_control/mali_kbase_csf_ipa_control.c index e503b08d13b9..c81d0a5a7236 100644 --- a/drivers/gpu/arm/bifrost/csf/ipa_control/mali_kbase_csf_ipa_control.c +++ b/drivers/gpu/arm/bifrost/csf/ipa_control/mali_kbase_csf_ipa_control.c @@ -28,8 +28,6 @@ * Status flags from the STATUS register of the IPA Control interface. */ #define STATUS_COMMAND_ACTIVE ((u32)1 << 0) -#define STATUS_TIMER_ACTIVE ((u32)1 << 1) -#define STATUS_AUTO_ACTIVE ((u32)1 << 2) #define STATUS_PROTECTED_MODE ((u32)1 << 8) #define STATUS_RESET ((u32)1 << 9) #define STATUS_TIMER_ENABLED ((u32)1 << 31) @@ -37,9 +35,7 @@ /* * Commands for the COMMAND register of the IPA Control interface. */ -#define COMMAND_NOP ((u32)0) #define COMMAND_APPLY ((u32)1) -#define COMMAND_CLEAR ((u32)2) #define COMMAND_SAMPLE ((u32)3) #define COMMAND_PROTECTED_ACK ((u32)4) #define COMMAND_RESET_ACK ((u32)5) @@ -965,6 +961,43 @@ void kbase_ipa_control_handle_gpu_reset_post(struct kbase_device *kbdev) } KBASE_EXPORT_TEST_API(kbase_ipa_control_handle_gpu_reset_post); +#ifdef KBASE_PM_RUNTIME +void kbase_ipa_control_handle_gpu_sleep_enter(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (kbdev->pm.backend.mcu_state == KBASE_MCU_IN_SLEEP) { + /* GPU Sleep is treated as a power down */ + kbase_ipa_control_handle_gpu_power_off(kbdev); + + /* SELECT_CSHW register needs to be cleared to prevent any + * IPA control message to be sent to the top level GPU HWCNT. + */ + kbase_reg_write(kbdev, IPA_CONTROL_REG(SELECT_CSHW_LO), 0); + kbase_reg_write(kbdev, IPA_CONTROL_REG(SELECT_CSHW_HI), 0); + + /* No need to issue the APPLY command here */ + } +} +KBASE_EXPORT_TEST_API(kbase_ipa_control_handle_gpu_sleep_enter); + +void kbase_ipa_control_handle_gpu_sleep_exit(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + if (kbdev->pm.backend.mcu_state == KBASE_MCU_IN_SLEEP) { + /* To keep things simple, currently exit from + * GPU Sleep is treated as a power on event where + * all 4 SELECT registers are reconfigured. + * On exit from sleep, reconfiguration is needed + * only for the SELECT_CSHW register. + */ + kbase_ipa_control_handle_gpu_power_on(kbdev); + } +} +KBASE_EXPORT_TEST_API(kbase_ipa_control_handle_gpu_sleep_exit); +#endif + #if MALI_UNIT_TEST void kbase_ipa_control_rate_change_notify_test(struct kbase_device *kbdev, u32 clk_index, u32 clk_rate_hz) diff --git a/drivers/gpu/arm/bifrost/csf/ipa_control/mali_kbase_csf_ipa_control.h b/drivers/gpu/arm/bifrost/csf/ipa_control/mali_kbase_csf_ipa_control.h index 0469c482dfff..69ff8973bac4 100644 --- a/drivers/gpu/arm/bifrost/csf/ipa_control/mali_kbase_csf_ipa_control.h +++ b/drivers/gpu/arm/bifrost/csf/ipa_control/mali_kbase_csf_ipa_control.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 @@ -198,6 +198,33 @@ void kbase_ipa_control_handle_gpu_reset_pre(struct kbase_device *kbdev); */ void kbase_ipa_control_handle_gpu_reset_post(struct kbase_device *kbdev); +#ifdef KBASE_PM_RUNTIME +/** + * kbase_ipa_control_handle_gpu_sleep_enter - Handle the pre GPU Sleep event + * + * @kbdev: Pointer to kbase device. + * + * This function is called after MCU has been put to sleep state & L2 cache has + * been powered down. The top level part of GPU is still powered up when this + * function is called. + */ +void kbase_ipa_control_handle_gpu_sleep_enter(struct kbase_device *kbdev); + +/** + * kbase_ipa_control_handle_gpu_sleep_exit - Handle the post GPU Sleep event + * + * @kbdev: Pointer to kbase device. + * + * This function is called when L2 needs to be powered up and MCU can exit the + * sleep state. The top level part of GPU is powered up when this function is + * called. + * + * This function must be called only if kbase_ipa_control_handle_gpu_sleep_enter() + * was called previously. + */ +void kbase_ipa_control_handle_gpu_sleep_exit(struct kbase_device *kbdev); +#endif + #if MALI_UNIT_TEST /** * kbase_ipa_control_rate_change_notify_test - Notify GPU rate change diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c index 80e37a36ca76..b77007300c5c 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf.c @@ -348,9 +348,8 @@ int kbase_csf_alloc_command_stream_user_pages(struct kbase_context *kctx, if (!reg) return -ENOMEM; - ret = kbase_mem_pool_alloc_pages( - &kctx->mem_pools.small[KBASE_MEM_GROUP_CSF_IO], - num_pages, queue->phys, false); + ret = kbase_mem_pool_alloc_pages(&kctx->mem_pools.small[KBASE_MEM_GROUP_CSF_IO], num_pages, + queue->phys, false); if (ret != num_pages) goto phys_alloc_failed; @@ -374,8 +373,11 @@ int kbase_csf_alloc_command_stream_user_pages(struct kbase_context *kctx, queue->db_file_offset = kbdev->csf.db_file_offsets; kbdev->csf.db_file_offsets += BASEP_QUEUE_NR_MMAP_USER_PAGES; - +#if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE) WARN(atomic_read(&queue->refcount) != 1, "Incorrect refcounting for queue object\n"); +#else + WARN(refcount_read(&queue->refcount) != 1, "Incorrect refcounting for queue object\n"); +#endif /* This is the second reference taken on the queue object and * would be dropped only when the IO mapping is removed either * explicitly by userspace or implicitly by kernel on process exit. @@ -444,25 +446,34 @@ static struct kbase_queue *find_queue(struct kbase_context *kctx, u64 base_addr) static void get_queue(struct kbase_queue *queue) { +#if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE) WARN_ON(!atomic_inc_not_zero(&queue->refcount)); +#else + WARN_ON(!refcount_inc_not_zero(&queue->refcount)); +#endif } static void release_queue(struct kbase_queue *queue) { lockdep_assert_held(&queue->kctx->csf.lock); - - WARN_ON(atomic_read(&queue->refcount) <= 0); - +#if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE) if (atomic_dec_and_test(&queue->refcount)) { +#else + if (refcount_dec_and_test(&queue->refcount)) { +#endif /* The queue can't still be on the per context list. */ WARN_ON(!list_empty(&queue->link)); WARN_ON(queue->group); + dev_dbg(queue->kctx->kbdev->dev, + "Remove any pending command queue fatal from ctx %d_%d", + queue->kctx->tgid, queue->kctx->id); + kbase_csf_event_remove_error(queue->kctx, &queue->error); kfree(queue); } } static void oom_event_worker(struct work_struct *data); -static void fatal_event_worker(struct work_struct *data); +static void cs_error_worker(struct work_struct *data); /* Between reg and reg_ex, one and only one must be null */ static int csf_queue_register_internal(struct kbase_context *kctx, @@ -565,7 +576,11 @@ static int csf_queue_register_internal(struct kbase_context *kctx, queue->enabled = false; queue->priority = reg->priority; +#if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE) atomic_set(&queue->refcount, 1); +#else + refcount_set(&queue->refcount, 1); +#endif queue->group = NULL; queue->bind_state = KBASE_CSF_QUEUE_UNBOUND; @@ -588,7 +603,7 @@ static int csf_queue_register_internal(struct kbase_context *kctx, INIT_LIST_HEAD(&queue->link); INIT_LIST_HEAD(&queue->error.link); INIT_WORK(&queue->oom_event_work, oom_event_worker); - INIT_WORK(&queue->fatal_event_work, fatal_event_worker); + INIT_WORK(&queue->cs_error_work, cs_error_worker); list_add(&queue->link, &kctx->csf.queue_list); queue->extract_ofs = 0; @@ -699,11 +714,6 @@ void kbase_csf_queue_terminate(struct kbase_context *kctx, } kbase_gpu_vm_unlock(kctx); - dev_dbg(kctx->kbdev->dev, - "Remove any pending command queue fatal from context %pK\n", - (void *)kctx); - kbase_csf_event_remove_error(kctx, &queue->error); - release_queue(queue); } @@ -784,6 +794,11 @@ static struct kbase_queue_group *get_bound_queue_group( return group; } +static void enqueue_gpu_submission_work(struct kbase_context *const kctx) +{ + queue_work(system_highpri_wq, &kctx->csf.pending_submission_work); +} + /** * pending_submission_worker() - Work item to process pending kicked GPU command queues. * @@ -813,11 +828,21 @@ static void pending_submission_worker(struct work_struct *work) list_for_each_entry(queue, &kctx->csf.queue_list, link) { if (atomic_cmpxchg(&queue->pending, 1, 0) == 1) { struct kbase_queue_group *group = get_bound_queue_group(queue); + int ret; - if (!group || queue->bind_state != KBASE_CSF_QUEUE_BOUND) + if (!group || queue->bind_state != KBASE_CSF_QUEUE_BOUND) { dev_dbg(kbdev->dev, "queue is not bound to a group"); - else - WARN_ON(kbase_csf_scheduler_queue_start(queue)); + continue; + } + + ret = kbase_csf_scheduler_queue_start(queue); + if (unlikely(ret)) { + dev_dbg(kbdev->dev, "Failed to start queue"); + if (ret == -EBUSY) { + atomic_cmpxchg(&queue->pending, 0, 1); + enqueue_gpu_submission_work(kctx); + } + } } } @@ -831,6 +856,8 @@ void kbase_csf_ring_csg_doorbell(struct kbase_device *kbdev, int slot) if (WARN_ON(slot < 0)) return; + kbase_csf_scheduler_spin_lock_assert_held(kbdev); + kbase_csf_ring_csg_slots_doorbell(kbdev, (u32) (1 << slot)); } @@ -843,6 +870,8 @@ void kbase_csf_ring_csg_slots_doorbell(struct kbase_device *kbdev, (u32) ((1U << kbdev->csf.global_iface.group_num) - 1); u32 value; + kbase_csf_scheduler_spin_lock_assert_held(kbdev); + if (WARN_ON(slot_bitmap > allowed_bitmap)) return; @@ -872,6 +901,8 @@ void kbase_csf_ring_cs_kernel_doorbell(struct kbase_device *kbdev, struct kbase_csf_cmd_stream_group_info *ginfo; u32 value; + kbase_csf_scheduler_spin_lock_assert_held(kbdev); + if (WARN_ON(csg_nr < 0) || WARN_ON(csg_nr >= kbdev->csf.global_iface.group_num)) return; @@ -891,11 +922,6 @@ void kbase_csf_ring_cs_kernel_doorbell(struct kbase_device *kbdev, kbase_csf_ring_csg_doorbell(kbdev, csg_nr); } -static void enqueue_gpu_submission_work(struct kbase_context *const kctx) -{ - queue_work(system_highpri_wq, &kctx->csf.pending_submission_work); -} - int kbase_csf_queue_kick(struct kbase_context *kctx, struct kbase_ioctl_cs_queue_kick *kick) { @@ -1129,9 +1155,8 @@ static int create_normal_suspend_buffer(struct kbase_context *const kctx, } /* Get physical page for a normal suspend buffer */ - err = kbase_mem_pool_alloc_pages( - &kctx->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], - nr_pages, &s_buf->phy[0], false); + err = kbase_mem_pool_alloc_pages(&kctx->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], nr_pages, + &s_buf->phy[0], false); if (err < 0) goto phy_pages_alloc_failed; @@ -1362,6 +1387,11 @@ static int create_queue_group(struct kbase_context *const kctx, group->cs_unrecoverable = false; group->reevaluate_idle_status = false; + group->dvs_buf = create->in.dvs_buf; + +#if IS_ENABLED(CONFIG_DEBUG_FS) + group->deschedule_deferred_cnt = 0; +#endif group->group_uid = generate_group_uid(); create->out.group_uid = group->group_uid; @@ -1377,6 +1407,9 @@ static int create_queue_group(struct kbase_context *const kctx, MAX_SUPPORTED_STREAMS_PER_GROUP); group->run_state = KBASE_CSF_GROUP_INACTIVE; + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, CSF_GROUP_INACTIVE, group, + group->run_state); + err = create_suspend_buffers(kctx, group); if (err < 0) { @@ -1396,6 +1429,17 @@ static int create_queue_group(struct kbase_context *const kctx, return group_handle; } +static bool dvs_supported(u32 csf_version) +{ + if (GLB_VERSION_MAJOR_GET(csf_version) < 3) + return false; + + if (GLB_VERSION_MAJOR_GET(csf_version) == 3) + if (GLB_VERSION_MINOR_GET(csf_version) < 2) + return false; + + return true; +} int kbase_csf_queue_group_create(struct kbase_context *const kctx, union kbase_ioctl_cs_queue_group_create *const create) @@ -1434,8 +1478,17 @@ int kbase_csf_queue_group_create(struct kbase_context *const kctx, 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"); + } else if (!dvs_supported(kctx->kbdev->csf.global_iface.version) && + create->in.dvs_buf) { + dev_warn( + kctx->kbdev->dev, + "GPU does not support DVS but userspace is trying to use it"); + err = -EINVAL; + } else if (dvs_supported(kctx->kbdev->csf.global_iface.version) && + !CSG_DVS_BUF_BUFFER_POINTER_GET(create->in.dvs_buf) && + CSG_DVS_BUF_BUFFER_SIZE_GET(create->in.dvs_buf)) { + dev_warn(kctx->kbdev->dev, + "DVS buffer pointer is null but size is not 0"); err = -EINVAL; } else { /* For the CSG which satisfies the condition for having @@ -1555,6 +1608,7 @@ void kbase_csf_term_descheduled_queue_group(struct kbase_queue_group *group) &group->protected_suspend_buf); group->run_state = KBASE_CSF_GROUP_TERMINATED; + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, CSF_GROUP_TERMINATED, group, group->run_state); } /** @@ -1585,6 +1639,34 @@ static void term_queue_group(struct kbase_queue_group *group) kbase_csf_term_descheduled_queue_group(group); } +/** + * wait_group_deferred_deschedule_completion - Wait for refcount of the group to + * become 0 that was taken when the group deschedule had to be deferred. + * + * @group: Pointer to GPU command queue group that is being deleted. + * + * This function is called when Userspace deletes the group and after the group + * has been descheduled. The function synchronizes with the other threads that were + * also trying to deschedule the group whilst the dumping was going on for a fault. + * Please refer the documentation of wait_for_dump_complete_on_group_deschedule() + * for more details. + */ +static void wait_group_deferred_deschedule_completion(struct kbase_queue_group *group) +{ +#if IS_ENABLED(CONFIG_DEBUG_FS) + struct kbase_context *kctx = group->kctx; + + lockdep_assert_held(&kctx->csf.lock); + + if (likely(!group->deschedule_deferred_cnt)) + return; + + mutex_unlock(&kctx->csf.lock); + wait_event(kctx->kbdev->csf.event_wait, !group->deschedule_deferred_cnt); + mutex_lock(&kctx->csf.lock); +#endif +} + static void cancel_queue_group_events(struct kbase_queue_group *group) { cancel_work_sync(&group->timer_event_work); @@ -1626,24 +1708,39 @@ void kbase_csf_queue_group_terminate(struct kbase_context *kctx, group = find_queue_group(kctx, group_handle); if (group) { - remove_pending_group_fatal_error(group); - term_queue_group(group); kctx->csf.queue_groups[group_handle] = NULL; + /* Stop the running of the given group */ + term_queue_group(group); + mutex_unlock(&kctx->csf.lock); + + if (reset_prevented) { + /* Allow GPU reset before cancelling the group specific + * work item to avoid potential deadlock. + * Reset prevention isn't needed after group termination. + */ + kbase_reset_gpu_allow(kbdev); + reset_prevented = false; + } + + /* Cancel any pending event callbacks. If one is in progress + * then this thread waits synchronously for it to complete (which + * is why we must unlock the context first). We already ensured + * that no more callbacks can be enqueued by terminating the group. + */ + cancel_queue_group_events(group); + + mutex_lock(&kctx->csf.lock); + + /* Clean up after the termination */ + remove_pending_group_fatal_error(group); + + wait_group_deferred_deschedule_completion(group); } mutex_unlock(&kctx->csf.lock); if (reset_prevented) kbase_reset_gpu_allow(kbdev); - if (!group) - return; - - /* Cancel any pending event callbacks. If one is in progress - * then this thread waits synchronously for it to complete (which - * is why we must unlock the context first). We already ensured - * that no more callbacks can be enqueued by terminating the group. - */ - cancel_queue_group_events(group); kfree(group); } @@ -1738,7 +1835,6 @@ void kbase_csf_active_queue_groups_reset(struct kbase_device *kbdev, int kbase_csf_ctx_init(struct kbase_context *kctx) { - struct kbase_device *kbdev = kctx->kbdev; int err = -ENOMEM; INIT_LIST_HEAD(&kctx->csf.queue_list); @@ -1747,19 +1843,6 @@ int kbase_csf_ctx_init(struct kbase_context *kctx) kbase_csf_event_init(kctx); kctx->csf.user_reg_vma = NULL; - mutex_lock(&kbdev->pm.lock); - /* The inode information for /dev/malixx file is not available at the - * time of device probe as the inode is created when the device node - * is created by udevd (through mknod). - */ - if (kctx->filp) { - if (!kbdev->csf.mali_file_inode) - kbdev->csf.mali_file_inode = kctx->filp->f_inode; - - /* inode is unique for a file */ - WARN_ON(kbdev->csf.mali_file_inode != kctx->filp->f_inode); - } - mutex_unlock(&kbdev->pm.lock); /* Mark all the cookies as 'free' */ bitmap_fill(kctx->csf.cookies, KBASE_CSF_NUM_USER_IO_PAGES_HANDLE); @@ -1874,8 +1957,6 @@ void kbase_csf_ctx_term(struct kbase_context *kctx) else reset_prevented = true; - cancel_work_sync(&kctx->csf.pending_submission_work); - mutex_lock(&kctx->csf.lock); /* Iterate through the queue groups that were not terminated by @@ -1894,6 +1975,8 @@ void kbase_csf_ctx_term(struct kbase_context *kctx) if (reset_prevented) kbase_reset_gpu_allow(kbdev); + cancel_work_sync(&kctx->csf.pending_submission_work); + /* Now that all queue groups have been terminated, there can be no * more OoM or timer event interrupts but there can be inflight work * items. Destroying the wq will implicitly flush those work items. @@ -1938,7 +2021,11 @@ void kbase_csf_ctx_term(struct kbase_context *kctx) * only one reference left that was taken when queue was * registered. */ +#if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE) if (atomic_read(&queue->refcount) != 1) +#else + if (refcount_read(&queue->refcount) != 1) +#endif dev_warn(kctx->kbdev->dev, "Releasing queue with incorrect refcounting!\n"); list_del_init(&queue->link); @@ -2059,6 +2146,36 @@ static void report_tiler_oom_error(struct kbase_queue_group *group) kbase_event_wakeup(group->kctx); } +static void flush_gpu_cache_on_fatal_error(struct kbase_device *kbdev) +{ + int err; + const unsigned int cache_flush_wait_timeout_ms = 2000; + + kbase_pm_lock(kbdev); + /* With the advent of partial cache flush, dirty cache lines could + * be left in the GPU L2 caches by terminating the queue group here + * without waiting for proper cache maintenance. A full cache flush + * here will prevent these dirty cache lines from being arbitrarily + * evicted later and possible causing memory corruption. + */ + if (kbdev->pm.backend.gpu_powered) { + kbase_gpu_start_cache_clean(kbdev, GPU_COMMAND_CACHE_CLN_INV_L2_LSC); + err = kbase_gpu_wait_cache_clean_timeout(kbdev, cache_flush_wait_timeout_ms); + + if (err) { + dev_warn( + kbdev->dev, + "[%llu] Timeout waiting for cache clean to complete after fatal error", + kbase_backend_get_cycle_cnt(kbdev)); + + if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) + kbase_reset_gpu(kbdev); + } + } + + kbase_pm_unlock(kbdev); +} + /** * kbase_queue_oom_event - Handle tiler out-of-memory for a GPU command queue. * @@ -2071,8 +2188,8 @@ static void report_tiler_oom_error(struct kbase_queue_group *group) * notification to allow the firmware to report out-of-memory again in future. * If the out-of-memory condition was successfully handled then this function * rings the relevant doorbell to notify the firmware; otherwise, it terminates - * the GPU command queue group to which the queue is bound. See - * term_queue_group() for details. + * the GPU command queue group to which the queue is bound and notify a waiting + * user space client of the failure. */ static void kbase_queue_oom_event(struct kbase_queue *const queue) { @@ -2084,6 +2201,7 @@ static void kbase_queue_oom_event(struct kbase_queue *const queue) struct kbase_csf_cmd_stream_info const *stream; int csi_index = queue->csi_index; u32 cs_oom_ack, cs_oom_req; + unsigned long flags; lockdep_assert_held(&kctx->csf.lock); @@ -2129,20 +2247,23 @@ static void kbase_queue_oom_event(struct kbase_queue *const queue) err = handle_oom_event(group, stream); + kbase_csf_scheduler_spin_lock(kbdev, &flags); kbase_csf_firmware_cs_input_mask(stream, CS_REQ, cs_oom_ack, CS_REQ_TILER_OOM_MASK); + kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, slot_num, true); + kbase_csf_scheduler_spin_unlock(kbdev, flags); - if (err) { + if (unlikely(err)) { dev_warn( kbdev->dev, "Queue group to be terminated, couldn't handle the OoM event\n"); + kbase_debug_csf_fault_notify(kbdev, kctx, DF_TILER_OOM); kbase_csf_scheduler_unlock(kbdev); term_queue_group(group); + flush_gpu_cache_on_fatal_error(kbdev); report_tiler_oom_error(group); return; } - - kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, slot_num, true); unlock: kbase_csf_scheduler_unlock(kbdev); } @@ -2164,6 +2285,7 @@ static void oom_event_worker(struct work_struct *data) struct kbase_device *const kbdev = kctx->kbdev; int err = kbase_reset_gpu_try_prevent(kbdev); + /* Regardless of whether reset failed or is currently happening, exit * early */ @@ -2216,12 +2338,13 @@ static void timer_event_worker(struct work_struct *data) struct kbase_queue_group *const group = container_of(data, struct kbase_queue_group, timer_event_work); struct kbase_context *const kctx = group->kctx; + struct kbase_device *const kbdev = kctx->kbdev; bool reset_prevented = false; - int err = kbase_reset_gpu_prevent_and_wait(kctx->kbdev); + int err = kbase_reset_gpu_prevent_and_wait(kbdev); if (err) dev_warn( - kctx->kbdev->dev, + kbdev->dev, "Unsuccessful GPU reset detected when terminating group %d on progress timeout, attempting to terminate regardless", group->handle); else @@ -2230,11 +2353,12 @@ static void timer_event_worker(struct work_struct *data) mutex_lock(&kctx->csf.lock); term_queue_group(group); + flush_gpu_cache_on_fatal_error(kbdev); report_group_timeout_error(group); mutex_unlock(&kctx->csf.lock); if (reset_prevented) - kbase_reset_gpu_allow(kctx->kbdev); + kbase_reset_gpu_allow(kbdev); } /** @@ -2242,11 +2366,15 @@ static void timer_event_worker(struct work_struct *data) * * @group: Pointer to GPU queue group for which the timeout event is received. * + * Notify a waiting user space client of the timeout. * Enqueue a work item to terminate the group and notify the event notification * thread of progress timeout fault for the GPU command queue group. */ static void handle_progress_timer_event(struct kbase_queue_group *const group) { + kbase_debug_csf_fault_notify(group->kctx->kbdev, group->kctx, + DF_PROGRESS_TIMER_TIMEOUT); + queue_work(group->kctx->csf.wq, &group->timer_event_work); } @@ -2274,16 +2402,20 @@ static void protm_event_worker(struct work_struct *data) * handle_fault_event - Handler for CS fault. * * @queue: Pointer to queue for which fault event was received. - * @stream: Pointer to the structure containing info provided by the - * firmware about the CSI. - * - * Prints meaningful CS fault information. + * @cs_ack: Value of the CS_ACK register in the CS kernel input page used for + * the queue. * + * Print required information about the CS fault and notify the user space client + * about the fault. */ static void -handle_fault_event(struct kbase_queue *const queue, - struct kbase_csf_cmd_stream_info const *const stream) +handle_fault_event(struct kbase_queue *const queue, const u32 cs_ack) { + struct kbase_device *const kbdev = queue->kctx->kbdev; + struct kbase_csf_cmd_stream_group_info const *ginfo = + &kbdev->csf.global_iface.groups[queue->group->csg_nr]; + struct kbase_csf_cmd_stream_info const *stream = + &ginfo->streams[queue->csi_index]; const u32 cs_fault = kbase_csf_firmware_cs_output(stream, CS_FAULT); const u64 cs_fault_info = kbase_csf_firmware_cs_output(stream, CS_FAULT_INFO_LO) | @@ -2295,7 +2427,6 @@ handle_fault_event(struct kbase_queue *const queue, CS_FAULT_EXCEPTION_DATA_GET(cs_fault); const u64 cs_fault_info_exception_data = CS_FAULT_INFO_EXCEPTION_DATA_GET(cs_fault_info); - struct kbase_device *const kbdev = queue->kctx->kbdev; kbase_csf_scheduler_spin_lock_assert_held(kbdev); @@ -2310,6 +2441,36 @@ handle_fault_event(struct kbase_queue *const queue, kbase_gpu_exception_name(cs_fault_exception_type), cs_fault_exception_data, cs_fault_info_exception_data); + +#if IS_ENABLED(CONFIG_DEBUG_FS) + /* CS_RESOURCE_TERMINATED type fault event can be ignored from the + * standpoint of dump on error. It is used to report fault for the CSIs + * that are associated with the same CSG as the CSI for which the actual + * fault was reported by the Iterator. + * Dumping would be triggered when the actual fault is reported. + * + * CS_INHERIT_FAULT can also be ignored. It could happen due to the error + * in other types of queues (cpu/kcpu). If a fault had occurred in some + * other GPU queue then the dump would have been performed anyways when + * that fault was reported. + */ + if ((cs_fault_exception_type != CS_FAULT_EXCEPTION_TYPE_CS_INHERIT_FAULT) && + (cs_fault_exception_type != CS_FAULT_EXCEPTION_TYPE_CS_RESOURCE_TERMINATED)) { + if (unlikely(kbase_debug_csf_fault_notify(kbdev, queue->kctx, DF_CS_FAULT))) { + get_queue(queue); + queue->cs_error = cs_fault; + queue->cs_error_info = cs_fault_info; + queue->cs_error_fatal = false; + if (!queue_work(queue->kctx->csf.wq, &queue->cs_error_work)) + release_queue(queue); + return; + } + } +#endif + + kbase_csf_firmware_cs_input_mask(stream, CS_REQ, cs_ack, + CS_REQ_FAULT_MASK); + kbase_csf_ring_cs_kernel_doorbell(kbdev, queue->csi_index, queue->group->csg_nr, true); } static void report_queue_fatal_error(struct kbase_queue *const queue, @@ -2341,16 +2502,16 @@ static void report_queue_fatal_error(struct kbase_queue *const queue, } /** - * fatal_event_worker - Handle the fatal error for the GPU queue + * fatal_event_worker - Handle the CS_FATAL/CS_FAULT error for the GPU queue * * @data: Pointer to a work_struct embedded in GPU command queue. * * Terminate the CSG and report the error to userspace. */ -static void fatal_event_worker(struct work_struct *const data) +static void cs_error_worker(struct work_struct *const data) { struct kbase_queue *const queue = - container_of(data, struct kbase_queue, fatal_event_work); + container_of(data, struct kbase_queue, cs_error_work); struct kbase_context *const kctx = queue->kctx; struct kbase_device *const kbdev = kctx->kbdev; struct kbase_queue_group *group; @@ -2365,6 +2526,7 @@ static void fatal_event_worker(struct work_struct *const data) else reset_prevented = true; + kbase_debug_csf_fault_wait_completion(kbdev); mutex_lock(&kctx->csf.lock); group = get_bound_queue_group(queue); @@ -2373,9 +2535,35 @@ static void fatal_event_worker(struct work_struct *const data) goto unlock; } +#if IS_ENABLED(CONFIG_DEBUG_FS) + if (!queue->cs_error_fatal) { + unsigned long flags; + int slot_num; + + kbase_csf_scheduler_spin_lock(kbdev, &flags); + slot_num = kbase_csf_scheduler_group_get_slot_locked(group); + if (slot_num >= 0) { + struct kbase_csf_cmd_stream_group_info const *ginfo = + &kbdev->csf.global_iface.groups[slot_num]; + struct kbase_csf_cmd_stream_info const *stream = + &ginfo->streams[queue->csi_index]; + u32 const cs_ack = + kbase_csf_firmware_cs_output(stream, CS_ACK); + + kbase_csf_firmware_cs_input_mask(stream, CS_REQ, cs_ack, + CS_REQ_FAULT_MASK); + kbase_csf_ring_cs_kernel_doorbell(kbdev, queue->csi_index, + slot_num, true); + } + kbase_csf_scheduler_spin_unlock(kbdev, flags); + goto unlock; + } +#endif + group_handle = group->handle; term_queue_group(group); - report_queue_fatal_error(queue, queue->cs_fatal, queue->cs_fatal_info, + flush_gpu_cache_on_fatal_error(kbdev); + report_queue_fatal_error(queue, queue->cs_error, queue->cs_error_info, group_handle); unlock: @@ -2391,14 +2579,18 @@ unlock: * @queue: Pointer to queue for which fatal event was received. * @stream: Pointer to the structure containing info provided by the * firmware about the CSI. + * @cs_ack: Value of the CS_ACK register in the CS kernel input page used for + * the queue. * - * Prints meaningful CS fatal information. + * Notify a waiting user space client of the CS fatal and prints meaningful + * information. * Enqueue a work item to terminate the group and report the fatal error * to user space. */ static void handle_fatal_event(struct kbase_queue *const queue, - struct kbase_csf_cmd_stream_info const *const stream) + struct kbase_csf_cmd_stream_info const *const stream, + u32 cs_ack) { const u32 cs_fatal = kbase_csf_firmware_cs_output(stream, CS_FATAL); const u64 cs_fatal_info = @@ -2428,57 +2620,26 @@ handle_fatal_event(struct kbase_queue *const queue, if (cs_fatal_exception_type == CS_FATAL_EXCEPTION_TYPE_FIRMWARE_INTERNAL_ERROR) { + kbase_debug_csf_fault_notify(kbdev, queue->kctx, DF_FW_INTERNAL_ERROR); queue_work(system_wq, &kbdev->csf.fw_error_work); } else { + kbase_debug_csf_fault_notify(kbdev, queue->kctx, DF_CS_FATAL); 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; - if (!queue_work(queue->kctx->csf.wq, &queue->fatal_event_work)) + queue->cs_error = cs_fatal; + queue->cs_error_info = cs_fatal_info; + queue->cs_error_fatal = true; + if (!queue_work(queue->kctx->csf.wq, &queue->cs_error_work)) release_queue(queue); } -} + kbase_csf_firmware_cs_input_mask(stream, CS_REQ, cs_ack, + CS_REQ_FATAL_MASK); -/** - * handle_queue_exception_event - Handler for CS fatal/fault exception events. - * - * @queue: Pointer to queue for which fatal/fault event was received. - * @cs_req: Value of the CS_REQ register from the CS's input page. - * @cs_ack: Value of the CS_ACK register from the CS's output page. - */ -static void handle_queue_exception_event(struct kbase_queue *const queue, - const u32 cs_req, const u32 cs_ack) -{ - struct kbase_csf_cmd_stream_group_info const *ginfo; - struct kbase_csf_cmd_stream_info const *stream; - struct kbase_context *const kctx = queue->kctx; - struct kbase_device *const kbdev = kctx->kbdev; - struct kbase_queue_group *group = queue->group; - int csi_index = queue->csi_index; - int slot_num = group->csg_nr; - - kbase_csf_scheduler_spin_lock_assert_held(kbdev); - - ginfo = &kbdev->csf.global_iface.groups[slot_num]; - stream = &ginfo->streams[csi_index]; - - if ((cs_ack & CS_ACK_FATAL_MASK) != (cs_req & CS_REQ_FATAL_MASK)) { - handle_fatal_event(queue, stream); - kbase_csf_firmware_cs_input_mask(stream, CS_REQ, cs_ack, - CS_REQ_FATAL_MASK); - } - - if ((cs_ack & CS_ACK_FAULT_MASK) != (cs_req & CS_REQ_FAULT_MASK)) { - handle_fault_event(queue, stream); - kbase_csf_firmware_cs_input_mask(stream, CS_REQ, cs_ack, - CS_REQ_FAULT_MASK); - kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, slot_num, true); - } } /** @@ -2531,11 +2692,16 @@ static void process_cs_interrupts(struct kbase_queue_group *const group, kbase_csf_firmware_cs_output(stream, CS_ACK); struct workqueue_struct *wq = group->kctx->csf.wq; - if ((cs_req & CS_REQ_EXCEPTION_MASK) ^ - (cs_ack & CS_ACK_EXCEPTION_MASK)) { + if ((cs_ack & CS_ACK_FATAL_MASK) != (cs_req & CS_REQ_FATAL_MASK)) { 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); + handle_fatal_event(queue, stream, cs_ack); + } + + if ((cs_ack & CS_ACK_FAULT_MASK) != (cs_req & CS_REQ_FAULT_MASK)) { + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_INTERRUPT_FAULT, + group, queue, cs_req ^ cs_ack); + handle_fault_event(queue, cs_ack); } /* PROTM_PEND and TILER_OOM can be safely ignored @@ -2597,6 +2763,8 @@ static void process_cs_interrupts(struct kbase_queue_group *const group, if (test_bit(group->csg_nr, scheduler->csg_slots_idle_mask)) { clear_bit(group->csg_nr, scheduler->csg_slots_idle_mask); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_CLEAR, group, + scheduler->csg_slots_idle_mask[0]); dev_dbg(kbdev->dev, "Group-%d on slot %d de-idled by protm request", group->handle, group->csg_nr); @@ -2698,7 +2866,12 @@ static void process_csg_interrupts(struct kbase_device *const kbdev, int const c /* If there are non-idle CSGs waiting for a slot, fire * a tock for a replacement. */ - mod_delayed_work(scheduler->wq, &scheduler->tock_work, 0); + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_INTERRUPT_NON_IDLE_GROUPS, + group, req ^ ack); + kbase_csf_scheduler_invoke_tock(kbdev); + } else { + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_INTERRUPT_NO_NON_IDLE_GROUPS, + group, req ^ ack); } if (group->scan_seq_num < track->idle_seq) { @@ -2709,14 +2882,15 @@ static void process_csg_interrupts(struct kbase_device *const kbdev, int const c if ((req ^ ack) & CSG_REQ_PROGRESS_TIMER_EVENT_MASK) { kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, ack, - CSG_REQ_PROGRESS_TIMER_EVENT_MASK); + CSG_REQ_PROGRESS_TIMER_EVENT_MASK); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_INTERRUPT_PROGRESS_TIMER_EVENT, - group, req ^ ack); - dev_info(kbdev->dev, + 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", - kbase_backend_get_cycle_cnt(kbdev), - group->handle, group->kctx->tgid, group->kctx->id, csg_nr); + kbase_backend_get_cycle_cnt(kbdev), group->handle, group->kctx->tgid, + group->kctx->id, csg_nr); handle_progress_timer_event(group); } @@ -2904,7 +3078,7 @@ static inline void process_tracked_info_for_protm(struct kbase_device *kbdev, * 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); + kbase_csf_scheduler_invoke_tock(kbdev); } else if (group) { u32 i, num_groups = kbdev->csf.global_iface.group_num; struct kbase_queue_group *grp; @@ -2927,7 +3101,7 @@ static inline void process_tracked_info_for_protm(struct kbase_device *kbdev, 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); + kbase_csf_scheduler_invoke_tock(kbdev); break; } } @@ -2940,77 +3114,133 @@ static inline void process_tracked_info_for_protm(struct kbase_device *kbdev, } } +static void order_job_irq_clear_with_iface_mem_read(void) +{ + /* Ensure that write to the JOB_IRQ_CLEAR is ordered with regards to the + * read from interface memory. The ordering is needed considering the way + * FW & Kbase writes to the JOB_IRQ_RAWSTAT and JOB_IRQ_CLEAR registers + * without any synchronization. Without the barrier there is no guarantee + * about the ordering, the write to IRQ_CLEAR can take effect after the read + * from interface memory and that could cause a problem for the scenario where + * FW sends back to back notifications for the same CSG for events like + * SYNC_UPDATE and IDLE, but Kbase gets a single IRQ and observes only the + * first event. Similar thing can happen with glb events like CFG_ALLOC_EN + * acknowledgment and GPU idle notification. + * + * MCU CPU + * --------------- ---------------- + * Update interface memory Write to IRQ_CLEAR to clear current IRQ + * + * Write to IRQ_RAWSTAT to raise new IRQ Read interface memory + */ + + /* CPU and GPU would be in the same Outer shareable domain */ + dmb(osh); +} + 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 }; + bool deferred_handling_glb_idle_irq = false; lockdep_assert_held(&kbdev->hwaccess_lock); 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; + do { + 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 }; + bool glb_idle_irq_received = false; - process_csg_interrupts(kbdev, csg_nr, &track); - csg_interrupts &= ~(1 << csg_nr); + kbase_reg_write(kbdev, JOB_CONTROL_REG(JOB_IRQ_CLEAR), val); + order_job_irq_clear_with_iface_mem_read(); + + 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, &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); } - /* Handle protm from the tracked information */ - process_tracked_info_for_protm(kbdev, &track); - kbase_csf_scheduler_spin_unlock(kbdev, flags); - } + if (val & JOB_IRQ_GLOBAL_IF) { + const struct kbase_csf_global_iface *const global_iface = + &kbdev->csf.global_iface; - if (val & JOB_IRQ_GLOBAL_IF) { - const struct kbase_csf_global_iface *const global_iface = - &kbdev->csf.global_iface; + kbdev->csf.interrupt_received = true; - kbdev->csf.interrupt_received = true; + if (!kbdev->csf.firmware_reloaded) + kbase_csf_firmware_reload_completed(kbdev); + else if (global_iface->output) { + u32 glb_req, glb_ack; - if (!kbdev->csf.firmware_reloaded) - kbase_csf_firmware_reload_completed(kbdev); - else if (global_iface->output) { - u32 glb_req, glb_ack; + kbase_csf_scheduler_spin_lock(kbdev, &flags); + glb_req = + kbase_csf_firmware_global_input_read(global_iface, GLB_REQ); + glb_ack = kbase_csf_firmware_global_output(global_iface, GLB_ACK); + KBASE_KTRACE_ADD(kbdev, CSF_INTERRUPT_GLB_REQ_ACK, NULL, + glb_req ^ glb_ack); - kbase_csf_scheduler_spin_lock(kbdev, &flags); - glb_req = kbase_csf_firmware_global_input_read( - global_iface, GLB_REQ); - glb_ack = kbase_csf_firmware_global_output( - global_iface, 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); - check_protm_enter_req_complete(kbdev, glb_req, glb_ack); + if ((glb_req ^ glb_ack) & GLB_REQ_PROTM_EXIT_MASK) + process_protm_exit(kbdev, glb_ack); - if ((glb_req ^ glb_ack) & GLB_REQ_PROTM_EXIT_MASK) - process_protm_exit(kbdev, glb_ack); - - /* Handle IDLE Hysteresis notification event */ - if ((glb_req ^ glb_ack) & GLB_REQ_IDLE_EVENT_MASK) { - dev_dbg(kbdev->dev, "Idle-hysteresis event flagged"); - kbase_csf_firmware_global_input_mask( + /* Handle IDLE Hysteresis notification event */ + if ((glb_req ^ glb_ack) & GLB_REQ_IDLE_EVENT_MASK) { + dev_dbg(kbdev->dev, "Idle-hysteresis event flagged"); + kbase_csf_firmware_global_input_mask( global_iface, GLB_REQ, glb_ack, GLB_REQ_IDLE_EVENT_MASK); - kbase_csf_scheduler_process_gpu_idle_event(kbdev); + glb_idle_irq_received = true; + /* Defer handling this IRQ to account for a race condition + * where the idle worker could be executed before we have + * finished handling all pending IRQs (including CSG IDLE + * IRQs). + */ + deferred_handling_glb_idle_irq = true; + } + + process_prfcnt_interrupts(kbdev, glb_req, glb_ack); + + kbase_csf_scheduler_spin_unlock(kbdev, flags); + + /* Invoke the MCU state machine as a state transition + * might have completed. + */ + kbase_pm_update_state(kbdev); } - - process_prfcnt_interrupts(kbdev, glb_req, glb_ack); - - kbase_csf_scheduler_spin_unlock(kbdev, flags); - - /* Invoke the MCU state machine as a state transition - * might have completed. - */ - kbase_pm_update_state(kbdev); } + + if (!glb_idle_irq_received) + break; + /* Attempt to serve potential IRQs that might have occurred + * whilst handling the previous IRQ. In case we have observed + * the GLB IDLE IRQ without all CSGs having been marked as + * idle, the GPU would be treated as no longer idle and left + * powered on. + */ + val = kbase_reg_read(kbdev, JOB_CONTROL_REG(JOB_IRQ_STATUS)); + } while (val); + + if (deferred_handling_glb_idle_irq) { + unsigned long flags; + + kbase_csf_scheduler_spin_lock(kbdev, &flags); + kbase_csf_scheduler_process_gpu_idle_event(kbdev); + kbase_csf_scheduler_spin_unlock(kbdev, flags); } wake_up_all(&kbdev->csf.event_wait); + KBASE_KTRACE_ADD(kbdev, CSF_INTERRUPT_END, NULL, val); } @@ -3037,9 +3267,8 @@ int kbase_csf_doorbell_mapping_init(struct kbase_device *kbdev) if (IS_ERR(filp)) return PTR_ERR(filp); - ret = kbase_mem_pool_alloc_pages( - &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], - 1, &phys, false); + ret = kbase_mem_pool_alloc_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], 1, &phys, + false); if (ret <= 0) { fput(filp); @@ -3073,9 +3302,8 @@ int kbase_csf_setup_dummy_user_reg_page(struct kbase_device *kbdev) kbdev->csf.dummy_user_reg_page = as_tagged(0); - ret = kbase_mem_pool_alloc_pages( - &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], 1, &phys, - false); + ret = kbase_mem_pool_alloc_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], 1, &phys, + false); if (ret <= 0) return ret; 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 92a511d79a05..3afbe6d4005e 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 @@ -23,12 +23,135 @@ #include #include #include -#include #include #if IS_ENABLED(CONFIG_DEBUG_FS) #include "mali_kbase_csf_tl_reader.h" +/* Wait time to be used cumulatively for all the CSG slots. + * Since scheduler lock is held when STATUS_UPDATE request is sent, there won't be + * any other Host request pending on the FW side and usually FW would be responsive + * to the Doorbell IRQs as it won't do any polling for a long time and also it won't + * have to wait for any HW state transition to complete for publishing the status. + * So it is reasonable to expect that handling of STATUS_UPDATE request would be + * relatively very quick. + */ +#define STATUS_UPDATE_WAIT_TIMEOUT 500 + +/* The bitmask of CSG slots for which the STATUS_UPDATE request completed. + * The access to it is serialized with scheduler lock, so at a time it would + * get used either for "active_groups" or per context "groups" debugfs file. + */ +static DECLARE_BITMAP(csg_slots_status_updated, MAX_SUPPORTED_CSGS); + +static +bool csg_slot_status_update_finish(struct kbase_device *kbdev, u32 csg_nr) +{ + struct kbase_csf_cmd_stream_group_info const *const ginfo = + &kbdev->csf.global_iface.groups[csg_nr]; + + return !((kbase_csf_firmware_csg_input_read(ginfo, CSG_REQ) ^ + kbase_csf_firmware_csg_output(ginfo, CSG_ACK)) & + CSG_REQ_STATUS_UPDATE_MASK); +} + +static +bool csg_slots_status_update_finish(struct kbase_device *kbdev, + const unsigned long *slots_mask) +{ + const u32 max_csg_slots = kbdev->csf.global_iface.group_num; + bool changed = false; + u32 csg_nr; + + lockdep_assert_held(&kbdev->csf.scheduler.lock); + + for_each_set_bit(csg_nr, slots_mask, max_csg_slots) { + if (csg_slot_status_update_finish(kbdev, csg_nr)) { + set_bit(csg_nr, csg_slots_status_updated); + changed = true; + } + } + + return changed; +} + +static void wait_csg_slots_status_update_finish(struct kbase_device *kbdev, + unsigned long *slots_mask) +{ + const u32 max_csg_slots = kbdev->csf.global_iface.group_num; + long remaining = kbase_csf_timeout_in_jiffies(STATUS_UPDATE_WAIT_TIMEOUT); + + lockdep_assert_held(&kbdev->csf.scheduler.lock); + + bitmap_zero(csg_slots_status_updated, max_csg_slots); + + while (!bitmap_empty(slots_mask, max_csg_slots) && remaining) { + remaining = wait_event_timeout(kbdev->csf.event_wait, + csg_slots_status_update_finish(kbdev, slots_mask), + remaining); + if (likely(remaining)) { + bitmap_andnot(slots_mask, slots_mask, + csg_slots_status_updated, max_csg_slots); + } else { + dev_warn(kbdev->dev, + "STATUS_UPDATE request timed out for slots 0x%lx", + slots_mask[0]); + } + } +} + +static void update_active_groups_status(struct kbase_device *kbdev, struct seq_file *file) +{ + u32 max_csg_slots = kbdev->csf.global_iface.group_num; + DECLARE_BITMAP(used_csgs, MAX_SUPPORTED_CSGS) = { 0 }; + u32 csg_nr; + unsigned long flags; + + lockdep_assert_held(&kbdev->csf.scheduler.lock); + + /* Global doorbell ring for CSG STATUS_UPDATE request or User doorbell + * ring for Extract offset update, shall not be made when MCU has been + * put to sleep otherwise it will undesirably make MCU exit the sleep + * state. Also it isn't really needed as FW will implicitly update the + * status of all on-slot groups when MCU sleep request is sent to it. + */ + if (kbdev->csf.scheduler.state == SCHED_SLEEPING) { + bitmap_copy(csg_slots_status_updated, + kbdev->csf.scheduler.csg_inuse_bitmap, max_csg_slots); + return; + } + + for (csg_nr = 0; csg_nr < max_csg_slots; csg_nr++) { + struct kbase_queue_group *const group = + kbdev->csf.scheduler.csg_slots[csg_nr].resident_group; + if (!group) + continue; + /* Ring the User doorbell for FW to update the Extract offset */ + kbase_csf_ring_doorbell(kbdev, group->doorbell_nr); + set_bit(csg_nr, used_csgs); + } + + /* Return early if there are no on-slot groups */ + if (bitmap_empty(used_csgs, max_csg_slots)) + return; + + kbase_csf_scheduler_spin_lock(kbdev, &flags); + for_each_set_bit(csg_nr, used_csgs, max_csg_slots) { + struct kbase_csf_cmd_stream_group_info const *const ginfo = + &kbdev->csf.global_iface.groups[csg_nr]; + kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, + ~kbase_csf_firmware_csg_output(ginfo, CSG_ACK), + CSG_REQ_STATUS_UPDATE_MASK); + } + + BUILD_BUG_ON(MAX_SUPPORTED_CSGS > (sizeof(used_csgs[0]) * BITS_PER_BYTE)); + kbase_csf_ring_csg_slots_doorbell(kbdev, used_csgs[0]); + kbase_csf_scheduler_spin_unlock(kbdev, flags); + wait_csg_slots_status_update_finish(kbdev, used_csgs); + /* Wait for the User doobell ring to take effect */ + msleep(100); +} + #define MAX_SCHED_STATE_STRING_LEN (16) static const char *scheduler_state_to_string(struct kbase_device *kbdev, enum kbase_csf_scheduler_state sched_state) @@ -77,16 +200,32 @@ static const char *blocked_reason_to_string(u32 reason_id) return cs_blocked_reason[reason_id]; } +static bool sb_source_supported(u32 glb_version) +{ + bool supported = false; + + if (((GLB_VERSION_MAJOR_GET(glb_version) == 3) && + (GLB_VERSION_MINOR_GET(glb_version) >= 5)) || + ((GLB_VERSION_MAJOR_GET(glb_version) == 2) && + (GLB_VERSION_MINOR_GET(glb_version) >= 6)) || + ((GLB_VERSION_MAJOR_GET(glb_version) == 1) && + (GLB_VERSION_MINOR_GET(glb_version) >= 3))) + supported = true; + + return supported; +} + static void kbasep_csf_scheduler_dump_active_queue_cs_status_wait( - struct seq_file *file, u32 wait_status, u32 wait_sync_value, - u64 wait_sync_live_value, u64 wait_sync_pointer, u32 sb_status, - u32 blocked_reason) + struct seq_file *file, u32 glb_version, u32 wait_status, u32 wait_sync_value, + u64 wait_sync_live_value, u64 wait_sync_pointer, u32 sb_status, u32 blocked_reason) { #define WAITING "Waiting" #define NOT_WAITING "Not waiting" seq_printf(file, "SB_MASK: %d\n", CS_STATUS_WAIT_SB_MASK_GET(wait_status)); + if (sb_source_supported(glb_version)) + seq_printf(file, "SB_SOURCE: %d\n", CS_STATUS_WAIT_SB_SOURCE_GET(wait_status)); seq_printf(file, "PROGRESS_WAIT: %s\n", CS_STATUS_WAIT_PROGRESS_WAIT_GET(wait_status) ? WAITING : NOT_WAITING); @@ -156,10 +295,13 @@ static void kbasep_csf_scheduler_dump_active_queue(struct seq_file *file, struct kbase_vmap_struct *mapping; u64 *evt; u64 wait_sync_live_value; + u32 glb_version; if (!queue) return; + glb_version = queue->kctx->kbdev->csf.global_iface.version; + if (WARN_ON(queue->csi_index == KBASEP_IF_NR_INVALID || !queue->group)) return; @@ -200,9 +342,8 @@ static void kbasep_csf_scheduler_dump_active_queue(struct seq_file *file, } kbasep_csf_scheduler_dump_active_queue_cs_status_wait( - file, wait_status, wait_sync_value, - wait_sync_live_value, wait_sync_pointer, - sb_status, blocked_reason); + file, glb_version, wait_status, wait_sync_value, + wait_sync_live_value, wait_sync_pointer, sb_status, blocked_reason); } } else { struct kbase_device const *const kbdev = @@ -257,9 +398,8 @@ static void kbasep_csf_scheduler_dump_active_queue(struct seq_file *file, } kbasep_csf_scheduler_dump_active_queue_cs_status_wait( - file, wait_status, wait_sync_value, - wait_sync_live_value, wait_sync_pointer, sb_status, - blocked_reason); + file, glb_version, wait_status, wait_sync_value, wait_sync_live_value, + wait_sync_pointer, sb_status, blocked_reason); /* Dealing with cs_trace */ if (kbase_csf_scheduler_queue_has_trace(queue)) kbasep_csf_scheduler_dump_active_cs_trace(file, stream); @@ -270,54 +410,6 @@ static void kbasep_csf_scheduler_dump_active_queue(struct seq_file *file, seq_puts(file, "\n"); } -static void update_active_group_status(struct seq_file *file, - struct kbase_queue_group *const group) -{ - struct kbase_device *const kbdev = group->kctx->kbdev; - struct kbase_csf_cmd_stream_group_info const *const ginfo = - &kbdev->csf.global_iface.groups[group->csg_nr]; - long remaining = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms); - unsigned long flags; - - /* Global doorbell ring for CSG STATUS_UPDATE request or User doorbell - * ring for Extract offset update, shall not be made when MCU has been - * put to sleep otherwise it will undesirably make MCU exit the sleep - * state. Also it isn't really needed as FW will implicitly update the - * status of all on-slot groups when MCU sleep request is sent to it. - */ - if (kbdev->csf.scheduler.state == SCHED_SLEEPING) - return; - - /* Ring the User doobell shared between the queues bound to this - * group, to have FW update the CS_EXTRACT for all the queues - * bound to the group. Ring early so that FW gets adequate time - * for the handling. - */ - kbase_csf_ring_doorbell(kbdev, group->doorbell_nr); - - kbase_csf_scheduler_spin_lock(kbdev, &flags); - kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, - ~kbase_csf_firmware_csg_output(ginfo, CSG_ACK), - CSG_REQ_STATUS_UPDATE_MASK); - kbase_csf_scheduler_spin_unlock(kbdev, flags); - kbase_csf_ring_csg_doorbell(kbdev, group->csg_nr); - - remaining = wait_event_timeout(kbdev->csf.event_wait, - !((kbase_csf_firmware_csg_input_read(ginfo, CSG_REQ) ^ - kbase_csf_firmware_csg_output(ginfo, CSG_ACK)) & - CSG_REQ_STATUS_UPDATE_MASK), remaining); - - if (!remaining) { - dev_err(kbdev->dev, - "Timed out for STATUS_UPDATE on group %d on slot %d", - group->handle, group->csg_nr); - - seq_printf(file, "*** Warn: Timed out for STATUS_UPDATE on slot %d\n", - group->csg_nr); - seq_puts(file, "*** The following group-record is likely stale\n"); - } -} - static void kbasep_csf_scheduler_dump_active_group(struct seq_file *file, struct kbase_queue_group *const group) { @@ -331,8 +423,6 @@ static void kbasep_csf_scheduler_dump_active_group(struct seq_file *file, u8 slot_priority = kbdev->csf.scheduler.csg_slots[group->csg_nr].priority; - update_active_group_status(file, group); - ep_c = kbase_csf_firmware_csg_output(ginfo, CSG_STATUS_EP_CURRENT); ep_r = kbase_csf_firmware_csg_output(ginfo, CSG_STATUS_EP_REQ); @@ -348,6 +438,12 @@ static void kbasep_csf_scheduler_dump_active_group(struct seq_file *file, CSG_STATUS_STATE_IDLE_MASK) idle = 'Y'; + if (!test_bit(group->csg_nr, csg_slots_status_updated)) { + seq_printf(file, "*** Warn: Timed out for STATUS_UPDATE on slot %d\n", + group->csg_nr); + seq_puts(file, "*** The following group-record is likely stale\n"); + } + seq_puts(file, "GroupID, CSG NR, CSG Prio, Run State, Priority, C_EP(Alloc/Req), F_EP(Alloc/Req), T_EP(Alloc/Req), Exclusive, Idle\n"); seq_printf(file, "%7d, %6d, %8d, %9d, %8d, %11d/%3d, %11d/%3d, %11d/%3d, %9c, %4c\n", group->handle, @@ -363,10 +459,6 @@ static void kbasep_csf_scheduler_dump_active_group(struct seq_file *file, CSG_STATUS_EP_REQ_TILER_EP_GET(ep_r), exclusive, idle); - - /* Wait for the User doobell ring to take effect */ - if (kbdev->csf.scheduler.state != SCHED_SLEEPING) - msleep(100); } else { seq_puts(file, "GroupID, CSG NR, Run State, Priority\n"); seq_printf(file, "%7d, %6d, %9d, %8d\n", @@ -416,10 +508,11 @@ static int kbasep_csf_queue_group_debugfs_show(struct seq_file *file, kbase_csf_scheduler_lock(kbdev); if (kbdev->csf.scheduler.state == SCHED_SLEEPING) { /* Wait for the MCU sleep request to complete. Please refer the - * update_active_group_status() function for the explanation. + * update_active_groups_status() function for the explanation. */ kbase_pm_wait_for_desired_state(kbdev); } + update_active_groups_status(kbdev, file); for (gr = 0; gr < MAX_QUEUE_GROUP_NUM; gr++) { struct kbase_queue_group *const group = kctx->csf.queue_groups[gr]; @@ -455,10 +548,11 @@ static int kbasep_csf_scheduler_dump_active_groups(struct seq_file *file, kbase_csf_scheduler_lock(kbdev); if (kbdev->csf.scheduler.state == SCHED_SLEEPING) { /* Wait for the MCU sleep request to complete. Please refer the - * update_active_group_status() function for the explanation. + * update_active_groups_status() function for the explanation. */ kbase_pm_wait_for_desired_state(kbdev); } + update_active_groups_status(kbdev, file); for (csg_nr = 0; csg_nr < num_groups; csg_nr++) { struct kbase_queue_group *const group = kbdev->csf.scheduler.csg_slots[csg_nr].resident_group; @@ -664,7 +758,6 @@ void kbase_csf_debugfs_init(struct kbase_device *kbdev) &kbasep_csf_debugfs_scheduler_state_fops); kbase_csf_tl_reader_debugfs_init(kbdev); - kbase_csf_firmware_trace_buffer_debugfs_init(kbdev); } #else 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 27aa53de110d..32a1c557e387 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_defs.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_defs.h @@ -31,6 +31,7 @@ #include "mali_kbase_csf_firmware.h" #include "mali_kbase_csf_event.h" +#include /* Maximum number of KCPU command queues to be created per GPU address space. */ @@ -355,14 +356,19 @@ struct kbase_csf_notification { * @trace_buffer_size: CS trace buffer size for the queue. * @trace_cfg: CS trace configuration parameters. * @error: GPU command queue fatal information to pass to user space. - * @fatal_event_work: Work item to handle the CS fatal event reported for this - * queue. - * @cs_fatal_info: Records additional information about the CS fatal event. - * @cs_fatal: Records information about the CS fatal event. + * @cs_error_work: Work item to handle the CS fatal event reported for this + * queue or the CS fault event if dump on fault is enabled + * and acknowledgment for CS fault event needs to be done + * after dumping is complete. + * @cs_error_info: Records additional information about the CS fatal event or + * about CS fault event if dump on fault is enabled. + * @cs_error: Records information about the CS fatal event or + * about CS fault event if dump on fault is enabled. + * @cs_error_fatal: Flag to track if the CS fault or CS fatal event occurred. * @pending: Indicating whether the queue has new submitted work. - * @extract_ofs: The current EXTRACT offset, this is updated during certain - * events such as GPU idle IRQ in order to help detect a - * queue's true idle status. + * @extract_ofs: The current EXTRACT offset, this is only updated when handling + * the GLB IDLE IRQ if the idle timeout value is non-0 in order + * to help detect a queue's true idle status. * @saved_cmd_ptr: The command pointer value for the GPU queue, saved when the * group to which queue is bound is suspended. * This can be useful in certain cases to know that till which @@ -377,7 +383,11 @@ struct kbase_queue { int doorbell_nr; unsigned long db_file_offset; struct list_head link; +#if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE) atomic_t refcount; +#else + refcount_t refcount; +#endif struct kbase_queue_group *group; struct kbase_va_region *queue_reg; struct work_struct oom_event_work; @@ -397,14 +407,15 @@ struct kbase_queue { u32 trace_buffer_size; u32 trace_cfg; struct kbase_csf_notification error; - struct work_struct fatal_event_work; - u64 cs_fatal_info; - u32 cs_fatal; + struct work_struct cs_error_work; + u64 cs_error_info; + u32 cs_error; + bool cs_error_fatal; atomic_t pending; u64 extract_ofs; #if IS_ENABLED(CONFIG_DEBUG_FS) u64 saved_cmd_ptr; -#endif +#endif /* CONFIG_DEBUG_FS */ }; /** @@ -498,6 +509,9 @@ struct kbase_protected_suspend_buffer { * to be returned to userspace if such an error has occurred. * @timer_event_work: Work item to handle the progress timeout fatal event * for the group. + * @deschedule_deferred_cnt: Counter keeping a track of the number of threads + * that tried to deschedule the group and had to defer + * the descheduling due to the dump on fault. */ struct kbase_queue_group { struct kbase_context *kctx; @@ -539,6 +553,15 @@ struct kbase_queue_group { struct work_struct timer_event_work; + /** + * @dvs_buf: Address and size of scratch memory. + * + * Used to store intermediate DVS data by the GPU. + */ + u64 dvs_buf; +#if IS_ENABLED(CONFIG_DEBUG_FS) + u32 deschedule_deferred_cnt; +#endif }; /** @@ -548,10 +571,10 @@ struct kbase_queue_group { * @lock: Lock preventing concurrent access to @array and the @in_use bitmap. * @array: Array of pointers to kernel CPU command queues. * @in_use: Bitmap which indicates which kernel CPU command queues are in use. - * @wq: Dedicated workqueue for processing kernel CPU command queues. - * @num_cmds: The number of commands that have been enqueued across - * all the KCPU command queues. This could be used as a - * timestamp to determine the command's enqueueing time. + * @cmd_seq_num: The sequence number assigned to an enqueued command, + * in incrementing order (older commands shall have a + * smaller number). + * @jit_lock: Lock to serialise JIT operations. * @jit_cmds_head: A list of the just-in-time memory commands, both * allocate & free, in submission order, protected * by kbase_csf_kcpu_queue_context.lock. @@ -564,9 +587,9 @@ struct kbase_csf_kcpu_queue_context { struct mutex lock; struct kbase_kcpu_command_queue *array[KBASEP_MAX_KCPU_QUEUES]; DECLARE_BITMAP(in_use, KBASEP_MAX_KCPU_QUEUES); - struct workqueue_struct *wq; - u64 num_cmds; + atomic64_t cmd_seq_num; + struct mutex jit_lock; struct list_head jit_cmds_head; struct list_head jit_blocked_queues; }; @@ -636,6 +659,28 @@ struct kbase_csf_tiler_heap_context { u64 nr_of_heaps; }; +/** + * struct kbase_csf_ctx_heap_reclaim_info - Object representing the data section of + * a kctx for tiler heap reclaim manger + * @mgr_link: Link for hooking up to the heap reclaim manger's kctx lists + * @nr_freed_pages: Number of freed pages from the the kctx, after its attachment + * to the reclaim manager. This is used for tracking reclaim's + * free operation progress. + * @nr_est_unused_pages: Estimated number of pages that could be freed for the kctx + * when all its CSGs are off-slot, on attaching to the reclaim + * manager. + * @on_slot_grps: Number of on-slot groups from this kctx. In principle, if a + * kctx has groups on-slot, the scheduler will detach it from + * the tiler heap reclaim manager, i.e. no tiler heap memory + * reclaiming operations on the kctx. + */ +struct kbase_csf_ctx_heap_reclaim_info { + struct list_head mgr_link; + u32 nr_freed_pages; + u32 nr_est_unused_pages; + u8 on_slot_grps; +}; + /** * struct kbase_csf_scheduler_context - Object representing the scheduler's * context for a GPU address space. @@ -657,6 +702,10 @@ struct kbase_csf_tiler_heap_context { * streams bound to groups of @idle_wait_groups list. * @ngrp_to_schedule: Number of groups added for the context to the * 'groups_to_schedule' list of scheduler instance. + * @heap_info: Heap reclaim information data of the kctx. As the + * reclaim action needs to be coordinated with the scheduler + * operations, any manipulations on the data needs holding + * the scheduler's mutex lock. */ struct kbase_csf_scheduler_context { struct list_head runnable_groups[KBASE_QUEUE_GROUP_PRIORITY_COUNT]; @@ -666,6 +715,7 @@ struct kbase_csf_scheduler_context { struct workqueue_struct *sync_update_wq; struct work_struct sync_update_work; u32 ngrp_to_schedule; + struct kbase_csf_ctx_heap_reclaim_info heap_info; }; /** @@ -808,6 +858,22 @@ struct kbase_csf_csg_slot { u8 priority; }; +/** + * struct kbase_csf_sched_heap_reclaim_mgr - Object for managing tiler heap reclaim + * kctx lists inside the CSF device's scheduler. + * + * @heap_reclaim: Tiler heap reclaim shrinker object. + * @ctx_lists: Array of kctx lists, size matching CSG defined priorities. The + * lists track the kctxs attached to the reclaim manager. + * @unused_pages: Estimated number of unused pages from the @ctxlist array. The + * number is indicative for use with reclaim shrinker's count method. + */ +struct kbase_csf_sched_heap_reclaim_mgr { + struct shrinker heap_reclaim; + struct list_head ctx_lists[KBASE_QUEUE_GROUP_PRIORITY_COUNT]; + atomic_t unused_pages; +}; + /** * struct kbase_csf_scheduler - Object representing the scheduler used for * CSF for an instance of GPU platform device. @@ -880,6 +946,8 @@ struct kbase_csf_csg_slot { * operation to implement timeslice-based scheduling. * @tock_work: Work item that would perform the schedule on tock * operation to implement the asynchronous scheduling. + * @pending_tock_work: Indicates that the tock work item should re-execute + * once it's finished instead of going back to sleep. * @ping_work: Work item that would ping the firmware at regular * intervals, only if there is a single active CSG * slot, to check if firmware is alive and would @@ -889,8 +957,6 @@ struct kbase_csf_csg_slot { * @top_grp. * @top_grp: Pointer to queue group inside @groups_to_schedule * list that was assigned the highest slot priority. - * @tock_pending_request: A "tock" request is pending: a group that is not - * currently on the GPU demands to be scheduled. * @active_protm_grp: Indicates if firmware has been permitted to let GPU * enter protected mode with the given group. On exit * from protected mode the pointer is reset to NULL. @@ -903,6 +969,13 @@ struct kbase_csf_csg_slot { * handler. * @gpu_idle_work: Work item for facilitating the scheduler to bring * the GPU to a low-power mode on becoming idle. + * @fast_gpu_idle_handling: Indicates whether to relax many of the checks + * normally done in the GPU idle worker. This is + * set to true when handling the GLB IDLE IRQ if the + * idle hysteresis timeout is 0, since it makes it + * possible to receive this IRQ before the extract + * offset is published (which would cause more + * extensive GPU idle checks to fail). * @gpu_no_longer_idle: Effective only when the GPU idle worker has been * queued for execution, this indicates whether the * GPU has become non-idle since the last time the @@ -934,6 +1007,7 @@ struct kbase_csf_csg_slot { * groups. It is updated on every tick/tock. * @interrupt_lock is used to serialize the access. * @protm_enter_time: GPU protected mode enter time. + * @reclaim_mgr: CSGs tiler heap manager object. */ struct kbase_csf_scheduler { struct mutex lock; @@ -960,13 +1034,14 @@ struct kbase_csf_scheduler { struct hrtimer tick_timer; struct work_struct tick_work; struct delayed_work tock_work; + atomic_t pending_tock_work; struct delayed_work ping_work; struct kbase_context *top_ctx; struct kbase_queue_group *top_grp; - bool tock_pending_request; struct kbase_queue_group *active_protm_grp; struct workqueue_struct *idle_wq; struct work_struct gpu_idle_work; + bool fast_gpu_idle_handling; atomic_t gpu_no_longer_idle; atomic_t non_idle_offslot_grps; u32 non_idle_scanout_grps; @@ -975,6 +1050,7 @@ struct kbase_csf_scheduler { bool tick_timer_active; u32 tick_protm_pending_seq; ktime_t protm_enter_time; + struct kbase_csf_sched_heap_reclaim_mgr reclaim_mgr; }; /* @@ -1161,6 +1237,7 @@ struct kbase_ipa_control { * @flags: bitmask of CSF_FIRMWARE_ENTRY_* conveying the interface attributes * @data_start: Offset into firmware image at which the interface data starts * @data_end: Offset into firmware image at which the interface data ends + * @virtual_exe_start: Starting GPU execution virtual address of this interface * @kernel_map: A kernel mapping of the memory or NULL if not required to be * mapped in the kernel * @pma: Array of pointers to protected memory allocations. @@ -1177,6 +1254,7 @@ struct kbase_csf_firmware_interface { u32 flags; u32 data_start; u32 data_end; + u32 virtual_exe_start; void *kernel_map; struct protected_memory_allocation **pma; }; @@ -1208,6 +1286,74 @@ struct kbase_csf_mcu_fw { u8 *data; }; +/* + * Firmware log polling period. + */ +#define KBASE_CSF_FIRMWARE_LOG_POLL_PERIOD_MS 25 + +/** + * enum kbase_csf_firmware_log_mode - Firmware log operating mode + * + * @KBASE_CSF_FIRMWARE_LOG_MODE_MANUAL: Manual mode, firmware log can be read + * manually by the userspace (and it will also be dumped automatically into + * dmesg on GPU reset). + * + * @KBASE_CSF_FIRMWARE_LOG_MODE_AUTO_PRINT: Automatic printing mode, firmware log + * will be periodically emptied into dmesg, manual reading through debugfs is + * disabled. + */ +enum kbase_csf_firmware_log_mode { + KBASE_CSF_FIRMWARE_LOG_MODE_MANUAL, + KBASE_CSF_FIRMWARE_LOG_MODE_AUTO_PRINT +}; + +/** + * struct kbase_csf_firmware_log - Object containing members for handling firmware log. + * + * @mode: Firmware log operating mode. + * @busy: Indicating whether a firmware log operation is in progress. + * @poll_work: Work item that would poll firmware log buffer + * at regular intervals to perform any periodic + * activities required by current log mode. + * @dump_buf: Buffer used for dumping the log. + * @func_call_list_va_start: Virtual address of the start of the call list of FW log functions. + * @func_call_list_va_end: Virtual address of the end of the call list of FW log functions. + */ +struct kbase_csf_firmware_log { + enum kbase_csf_firmware_log_mode mode; + atomic_t busy; + struct delayed_work poll_work; + u8 *dump_buf; + u32 func_call_list_va_start; + u32 func_call_list_va_end; +}; + +#if IS_ENABLED(CONFIG_DEBUG_FS) +/** + * struct kbase_csf_dump_on_fault - Faulty information to deliver to the daemon + * + * @error_code: Error code. + * @kctx_tgid: tgid value of the Kbase context for which the fault happened. + * @kctx_id: id of the Kbase context for which the fault happened. + * @enabled: Flag to indicate that 'csf_fault' debugfs has been opened + * so dump on fault is enabled. + * @fault_wait_wq: Waitqueue on which user space client is blocked till kbase + * reports a fault. + * @dump_wait_wq: Waitqueue on which kbase threads are blocked till user space client + * completes the dump on fault. + * @lock: Lock to protect this struct members from concurrent access. + */ +struct kbase_csf_dump_on_fault { + enum dumpfault_error_type error_code; + u32 kctx_tgid; + u32 kctx_id; + atomic_t enabled; + wait_queue_head_t fault_wait_wq; + wait_queue_head_t dump_wait_wq; + spinlock_t lock; +}; +#endif /* CONFIG_DEBUG_FS*/ + /** * struct kbase_csf_device - Object representing CSF for an instance of GPU * platform device. @@ -1251,11 +1397,14 @@ struct kbase_csf_mcu_fw { * in the address space of every process, that created * a Base context, to enable the access to LATEST_FLUSH * register from userspace. + * @nr_user_page_mapped: The number of clients using the mapping of USER page. + * This is used to maintain backward compatibility. + * It's protected by @reg_lock. * @mali_file_inode: Pointer to the inode corresponding to mali device * file. This is needed in order to switch to the * @dummy_user_reg_page on GPU power down. * All instances of the mali device file will point to - * the same inode. + * the same inode. It's protected by @reg_lock. * @reg_lock: Lock to serialize the MCU firmware related actions * that affect all contexts such as allocation of * regions from shared interface area, assignment of @@ -1320,6 +1469,8 @@ struct kbase_csf_mcu_fw { * @hwcnt: Contain members required for handling the dump of * HW counters. * @fw: Copy of the loaded MCU firmware image. + * @fw_log: Contain members required for handling firmware log. + * @dof: Structure for dump on fault. */ struct kbase_csf_device { struct kbase_mmu_table mcu_mmu; @@ -1334,6 +1485,7 @@ struct kbase_csf_device { u32 db_file_offsets; struct tagged_addr dummy_db_page; struct tagged_addr dummy_user_reg_page; + u32 nr_user_page_mapped; struct inode *mali_file_inode; struct mutex reg_lock; wait_queue_head_t event_wait; @@ -1360,6 +1512,10 @@ struct kbase_csf_device { unsigned int fw_timeout_ms; struct kbase_csf_hwcnt hwcnt; struct kbase_csf_mcu_fw fw; + struct kbase_csf_firmware_log fw_log; +#if IS_ENABLED(CONFIG_DEBUG_FS) + struct kbase_csf_dump_on_fault dof; +#endif /* CONFIG_DEBUG_FS */ }; /** 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 170b7ec51af7..49e52938499f 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_event.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_event.c @@ -169,7 +169,8 @@ void kbase_csf_event_term(struct kbase_context *kctx) kfree(event_cb); } - WARN_ON(!list_empty(&kctx->csf.event.error_list)); + WARN(!list_empty(&kctx->csf.event.error_list), + "Error list not empty for ctx %d_%d\n", kctx->tgid, kctx->id); spin_unlock_irqrestore(&kctx->csf.event.lock, flags); } @@ -244,6 +245,14 @@ bool kbase_csf_event_error_pending(struct kbase_context *kctx) bool error_pending = false; unsigned long flags; + /* Withhold the error event if the dump on fault is ongoing. + * This would prevent the Userspace from taking error recovery actions + * (which can potentially affect the state that is being dumped). + * Event handling thread would eventually notice the error event. + */ + if (unlikely(!kbase_debug_csf_fault_dump_complete(kctx->kbdev))) + return false; + spin_lock_irqsave(&kctx->csf.event.lock, flags); error_pending = !list_empty(&kctx->csf.event.error_list); 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 0fb56e0094c5..1f4a4d9b6876 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.c @@ -21,6 +21,7 @@ #include "mali_kbase.h" #include "mali_kbase_csf_firmware_cfg.h" +#include "mali_kbase_csf_firmware_log.h" #include "mali_kbase_csf_trace_buffer.h" #include "mali_kbase_csf_timeout.h" #include "mali_kbase_mem.h" @@ -77,9 +78,11 @@ MODULE_PARM_DESC(fw_debug, "Enables effective use of a debugger for debugging firmware code."); #endif -#define FIRMWARE_HEADER_MAGIC (0xC3F13A6Eul) -#define FIRMWARE_HEADER_VERSION (0ul) -#define FIRMWARE_HEADER_LENGTH (0x14ul) + +#define FIRMWARE_HEADER_MAGIC (0xC3F13A6Eul) +#define FIRMWARE_HEADER_VERSION_MAJOR (0ul) +#define FIRMWARE_HEADER_VERSION_MINOR (2ul) +#define FIRMWARE_HEADER_LENGTH (0x14ul) #define CSF_FIRMWARE_ENTRY_SUPPORTED_FLAGS \ (CSF_FIRMWARE_ENTRY_READ | \ @@ -92,10 +95,10 @@ MODULE_PARM_DESC(fw_debug, #define CSF_FIRMWARE_ENTRY_TYPE_INTERFACE (0) #define CSF_FIRMWARE_ENTRY_TYPE_CONFIGURATION (1) -#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_ENTRY_TYPE_FUNC_CALL_LIST (7) #define CSF_FIRMWARE_CACHE_MODE_NONE (0ul << 3) #define CSF_FIRMWARE_CACHE_MODE_CACHED (1ul << 3) @@ -431,8 +434,8 @@ static void load_fw_image_section(struct kbase_device *kbdev, const u8 *data, memset(p + copy_len, 0, zi_len); } - kbase_sync_single_for_device(kbdev, kbase_dma_addr(page), - PAGE_SIZE, DMA_TO_DEVICE); + kbase_sync_single_for_device(kbdev, kbase_dma_addr_from_tagged(phys[page_num]), + PAGE_SIZE, DMA_TO_DEVICE); kunmap_atomic(p); } } @@ -525,6 +528,58 @@ static inline bool entry_find_large_page_to_reuse( *pma = NULL; + /* If the section starts at 2MB aligned boundary, + * then use 2MB page(s) for it. + */ + if (!(virtual_start & (SZ_2M - 1))) { + *num_pages_aligned = + round_up(*num_pages_aligned, NUM_4K_PAGES_IN_2MB_PAGE); + *is_small_page = false; + goto out; + } + + /* If the section doesn't lie within the same 2MB aligned boundary, + * then use 4KB pages as it would be complicated to use a 2MB page + * for such section. + */ + if ((virtual_start & ~(SZ_2M - 1)) != (virtual_end & ~(SZ_2M - 1))) + goto out; + + /* Find the nearest 2MB aligned section which comes before the current + * section. + */ + list_for_each_entry(interface, &kbdev->csf.firmware_interfaces, node) { + const u32 virtual_diff = virtual_start - interface->virtual; + + if (interface->virtual > virtual_end) + continue; + + if (interface->virtual & (SZ_2M - 1)) + continue; + + if (virtual_diff < virtual_diff_min) { + target_interface = interface; + virtual_diff_min = virtual_diff; + } + } + + if (target_interface) { + const u32 page_index = virtual_diff_min >> PAGE_SHIFT; + + if (page_index >= target_interface->num_pages_aligned) + goto out; + + if (target_interface->phys) + *phys = &target_interface->phys[page_index]; + + if (target_interface->pma) + *pma = &target_interface->pma[page_index / NUM_4K_PAGES_IN_2MB_PAGE]; + + *is_small_page = false; + reuse_large_page = true; + } + +out: return reuse_large_page; } @@ -555,6 +610,8 @@ static int parse_memory_setup_entry(struct kbase_device *kbdev, u32 num_pages; u32 num_pages_aligned; char *name; + void *name_entry; + unsigned int name_len; struct tagged_addr *phys = NULL; struct kbase_csf_firmware_interface *interface = NULL; bool allocated_pages = false, protected_mode = false; @@ -625,8 +682,8 @@ static int parse_memory_setup_entry(struct kbase_device *kbdev, } else { if (!reuse_pages) { ret = kbase_mem_pool_alloc_pages( - kbase_mem_pool_group_select( - kbdev, KBASE_MEM_GROUP_CSF_FW, is_small_page), + kbase_mem_pool_group_select(kbdev, KBASE_MEM_GROUP_CSF_FW, + is_small_page), num_pages_aligned, phys, false); } } @@ -643,21 +700,24 @@ static int parse_memory_setup_entry(struct kbase_device *kbdev, data_start, data_end); /* Allocate enough memory for the struct kbase_csf_firmware_interface and - * the name of the interface. An extra byte is allocated to place a - * NUL-terminator in. This should already be included according to the - * specification but here we add it anyway to be robust against a - * corrupt firmware image. + * the name of the interface. */ - interface = kmalloc(sizeof(*interface) + - size - INTERFACE_ENTRY_NAME_OFFSET + 1, GFP_KERNEL); + name_entry = (void *)entry + INTERFACE_ENTRY_NAME_OFFSET; + name_len = strnlen(name_entry, size - INTERFACE_ENTRY_NAME_OFFSET); + if (size < (INTERFACE_ENTRY_NAME_OFFSET + name_len + 1 + sizeof(u32))) { + dev_err(kbdev->dev, "Memory setup entry too short to contain virtual_exe_start"); + ret = -EINVAL; + goto out; + } + + interface = kmalloc(sizeof(*interface) + name_len + 1, GFP_KERNEL); if (!interface) { ret = -ENOMEM; goto out; } name = (void *)(interface + 1); - memcpy(name, entry + (INTERFACE_ENTRY_NAME_OFFSET / sizeof(*entry)), - size - INTERFACE_ENTRY_NAME_OFFSET); - name[size - INTERFACE_ENTRY_NAME_OFFSET] = 0; + memcpy(name, name_entry, name_len); + name[name_len] = 0; interface->name = name; interface->phys = phys; @@ -672,6 +732,11 @@ static int parse_memory_setup_entry(struct kbase_device *kbdev, interface->data_end = data_end; interface->pma = pma; + /* Discover the virtual execution address field after the end of the name + * field taking into account the NULL-termination character. + */ + interface->virtual_exe_start = *((u32 *)(name_entry + name_len + 1)); + mem_flags = convert_mem_flags(kbdev, flags, &cache_mode); if (flags & CSF_FIRMWARE_ENTRY_SHARED) { @@ -956,6 +1021,15 @@ static int load_firmware_entry(struct kbase_device *kbdev, const struct kbase_cs return -EINVAL; } return parse_build_info_metadata_entry(kbdev, fw, entry, size); + case CSF_FIRMWARE_ENTRY_TYPE_FUNC_CALL_LIST: + /* Function call list section */ + if (size < 2 * sizeof(*entry)) { + dev_err(kbdev->dev, "Function call list entry too short (size=%u)\n", + size); + return -EINVAL; + } + kbase_csf_firmware_log_parse_logging_call_list_entry(kbdev, entry); + break; } if (!optional) { @@ -1179,40 +1253,80 @@ static int parse_capabilities(struct kbase_device *kbdev) return 0; } +static inline void access_firmware_memory_common(struct kbase_device *kbdev, + struct kbase_csf_firmware_interface *interface, u32 offset_bytes, + u32 *value, const bool read) +{ + u32 page_num = offset_bytes >> PAGE_SHIFT; + u32 offset_in_page = offset_bytes & ~PAGE_MASK; + struct page *target_page = as_page(interface->phys[page_num]); + uintptr_t cpu_addr = (uintptr_t)kmap_atomic(target_page); + u32 *addr = (u32 *)(cpu_addr + offset_in_page); + + if (read) { + kbase_sync_single_for_device(kbdev, + kbase_dma_addr_from_tagged(interface->phys[page_num]) + offset_in_page, + sizeof(u32), DMA_BIDIRECTIONAL); + *value = *addr; + } else { + *addr = *value; + kbase_sync_single_for_device(kbdev, + kbase_dma_addr_from_tagged(interface->phys[page_num]) + offset_in_page, + sizeof(u32), DMA_BIDIRECTIONAL); + } + + kunmap_atomic((u32 *)cpu_addr); +} + static inline void access_firmware_memory(struct kbase_device *kbdev, u32 gpu_addr, u32 *value, const bool read) { - struct kbase_csf_firmware_interface *interface; + struct kbase_csf_firmware_interface *interface, *access_interface = NULL; + u32 offset_bytes = 0; list_for_each_entry(interface, &kbdev->csf.firmware_interfaces, node) { if ((gpu_addr >= interface->virtual) && (gpu_addr < interface->virtual + (interface->num_pages << PAGE_SHIFT))) { - u32 offset_bytes = gpu_addr - interface->virtual; - u32 page_num = offset_bytes >> PAGE_SHIFT; - u32 offset_in_page = offset_bytes & ~PAGE_MASK; - struct page *target_page = as_page( - interface->phys[page_num]); - u32 *cpu_addr = kmap_atomic(target_page); - - if (read) { - kbase_sync_single_for_device(kbdev, - kbase_dma_addr(target_page) + offset_in_page, - sizeof(u32), DMA_BIDIRECTIONAL); - - *value = cpu_addr[offset_in_page >> 2]; - } else { - cpu_addr[offset_in_page >> 2] = *value; - - kbase_sync_single_for_device(kbdev, - kbase_dma_addr(target_page) + offset_in_page, - sizeof(u32), DMA_BIDIRECTIONAL); - } - - kunmap_atomic(cpu_addr); - return; + offset_bytes = gpu_addr - interface->virtual; + access_interface = interface; + break; } } - dev_warn(kbdev->dev, "Invalid GPU VA %x passed\n", gpu_addr); + + if (access_interface) + access_firmware_memory_common(kbdev, access_interface, offset_bytes, value, read); + else + dev_warn(kbdev->dev, "Invalid GPU VA %x passed", gpu_addr); +} + +static inline void access_firmware_memory_exe(struct kbase_device *kbdev, + u32 gpu_addr, u32 *value, const bool read) +{ + struct kbase_csf_firmware_interface *interface, *access_interface = NULL; + u32 offset_bytes = 0; + + list_for_each_entry(interface, &kbdev->csf.firmware_interfaces, node) { + if ((gpu_addr >= interface->virtual_exe_start) && + (gpu_addr < interface->virtual_exe_start + + (interface->num_pages << PAGE_SHIFT))) { + offset_bytes = gpu_addr - interface->virtual_exe_start; + access_interface = interface; + + /* If there's an overlap in execution address range between a moved and a + * non-moved areas, always prefer the moved one. The idea is that FW may + * move sections around during init time, but after the layout is settled, + * any moved sections are going to override non-moved areas at the same + * location. + */ + if (interface->virtual_exe_start != interface->virtual) + break; + } + } + + if (access_interface) + access_firmware_memory_common(kbdev, access_interface, offset_bytes, value, read); + else + dev_warn(kbdev->dev, "Invalid GPU VA %x passed", gpu_addr); } void kbase_csf_read_firmware_memory(struct kbase_device *kbdev, @@ -1227,6 +1341,18 @@ void kbase_csf_update_firmware_memory(struct kbase_device *kbdev, access_firmware_memory(kbdev, gpu_addr, &value, false); } +void kbase_csf_read_firmware_memory_exe(struct kbase_device *kbdev, + u32 gpu_addr, u32 *value) +{ + access_firmware_memory_exe(kbdev, gpu_addr, value, true); +} + +void kbase_csf_update_firmware_memory_exe(struct kbase_device *kbdev, + u32 gpu_addr, u32 value) +{ + access_firmware_memory_exe(kbdev, gpu_addr, &value, false); +} + void kbase_csf_firmware_cs_input( const struct kbase_csf_cmd_stream_info *const info, const u32 offset, const u32 value) @@ -1462,11 +1588,10 @@ static bool global_request_complete(struct kbase_device *const kbdev, return complete; } -static int wait_for_global_request(struct kbase_device *const kbdev, - u32 const req_mask) +static int wait_for_global_request_with_timeout(struct kbase_device *const kbdev, + u32 const req_mask, unsigned int timeout_ms) { - const long wait_timeout = - kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms); + const long wait_timeout = kbase_csf_timeout_in_jiffies(timeout_ms); long remaining; int err = 0; @@ -1475,10 +1600,9 @@ static int wait_for_global_request(struct kbase_device *const kbdev, wait_timeout); if (!remaining) { - dev_warn(kbdev->dev, "[%llu] Timeout (%d ms) waiting for global request %x to complete", - kbase_backend_get_cycle_cnt(kbdev), - kbdev->csf.fw_timeout_ms, - req_mask); + dev_warn(kbdev->dev, + "[%llu] Timeout (%d ms) waiting for global request %x to complete", + kbase_backend_get_cycle_cnt(kbdev), timeout_ms, req_mask); err = -ETIMEDOUT; } @@ -1486,6 +1610,11 @@ static int wait_for_global_request(struct kbase_device *const kbdev, return err; } +static int wait_for_global_request(struct kbase_device *const kbdev, u32 const req_mask) +{ + return wait_for_global_request_with_timeout(kbdev, req_mask, kbdev->csf.fw_timeout_ms); +} + static void set_global_request( const struct kbase_csf_global_iface *const global_iface, u32 const req_mask) @@ -1559,6 +1688,25 @@ static void enable_gpu_idle_timer(struct kbase_device *const kbdev) } +/** + * kbasep_enable_rtu - Enable Ray Tracing Unit on powering up shader core + * + * @kbdev: The kbase device structure of the device + * + * This function needs to be called to enable the Ray Tracing Unit + * by writing SHADER_PWRFEATURES only when host controls shader cores power. + */ +static void kbasep_enable_rtu(struct kbase_device *kbdev) +{ + const u32 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id; + + if (gpu_id < GPU_ID2_PRODUCT_MAKE(12, 8, 3, 0)) + return; + + if (kbdev->csf.firmware_hctl_core_pwr) + kbase_reg_write(kbdev, GPU_CONTROL_REG(SHADER_PWRFEATURES), 1); +} + static void global_init(struct kbase_device *const kbdev, u64 core_mask) { u32 const ack_irq_mask = @@ -1574,6 +1722,8 @@ static void global_init(struct kbase_device *const kbdev, u64 core_mask) kbase_csf_scheduler_spin_lock(kbdev, &flags); + kbasep_enable_rtu(kbdev); + /* Update shader core allocation enable mask */ enable_endpoints_global(global_iface, core_mask); enable_shader_poweroff_timer(kbdev, global_iface); @@ -1854,7 +2004,6 @@ end: static u32 convert_dur_to_core_pwroff_count(struct kbase_device *kbdev, const u32 dur_us) { -#define PWROFF_VAL_UNIT_SHIFT (10) /* Get the cntfreq_el0 value, which drives the SYSTEM_TIMESTAMP */ u64 freq = arch_timer_get_cntfrq(); u64 dur_val = dur_us; @@ -1991,16 +2140,6 @@ int kbase_csf_firmware_early_init(struct kbase_device *kbdev) kbdev->csf.fw_timeout_ms = kbase_get_timeout_ms(kbdev, CSF_FIRMWARE_TIMEOUT); - kbdev->csf.gpu_idle_hysteresis_ms = FIRMWARE_IDLE_HYSTERESIS_TIME_MS; -#ifdef KBASE_PM_RUNTIME - if (kbase_pm_gpu_sleep_allowed(kbdev)) - kbdev->csf.gpu_idle_hysteresis_ms /= - FIRMWARE_IDLE_HYSTERESIS_GPU_SLEEP_SCALER; -#endif - WARN_ON(!kbdev->csf.gpu_idle_hysteresis_ms); - kbdev->csf.gpu_idle_dur_count = convert_dur_to_idle_count( - kbdev, kbdev->csf.gpu_idle_hysteresis_ms); - kbdev->csf.mcu_core_pwroff_dur_us = DEFAULT_GLB_PWROFF_TIMEOUT_US; kbdev->csf.mcu_core_pwroff_dur_count = convert_dur_to_core_pwroff_count( kbdev, DEFAULT_GLB_PWROFF_TIMEOUT_US); @@ -2020,7 +2159,26 @@ int kbase_csf_firmware_early_init(struct kbase_device *kbdev) return 0; } -int kbase_csf_firmware_init(struct kbase_device *kbdev) +void kbase_csf_firmware_early_term(struct kbase_device *kbdev) +{ + mutex_destroy(&kbdev->csf.reg_lock); +} + +int kbase_csf_firmware_late_init(struct kbase_device *kbdev) +{ + kbdev->csf.gpu_idle_hysteresis_ms = FIRMWARE_IDLE_HYSTERESIS_TIME_MS; +#ifdef KBASE_PM_RUNTIME + if (kbase_pm_gpu_sleep_allowed(kbdev)) + kbdev->csf.gpu_idle_hysteresis_ms /= FIRMWARE_IDLE_HYSTERESIS_GPU_SLEEP_SCALER; +#endif + WARN_ON(!kbdev->csf.gpu_idle_hysteresis_ms); + kbdev->csf.gpu_idle_dur_count = + convert_dur_to_idle_count(kbdev, kbdev->csf.gpu_idle_hysteresis_ms); + + return 0; +} + +int kbase_csf_firmware_load_init(struct kbase_device *kbdev) { const struct firmware *firmware = NULL; struct kbase_csf_mcu_fw *const mcu_fw = &kbdev->csf.fw; @@ -2093,7 +2251,8 @@ int kbase_csf_firmware_init(struct kbase_device *kbdev) version_minor = mcu_fw->data[4]; version_major = mcu_fw->data[5]; - if (version_major != FIRMWARE_HEADER_VERSION) { + if (version_major != FIRMWARE_HEADER_VERSION_MAJOR || + version_minor != FIRMWARE_HEADER_VERSION_MINOR) { dev_err(kbdev->dev, "Firmware header version %d.%d not understood\n", version_major, version_minor); @@ -2188,6 +2347,12 @@ int kbase_csf_firmware_init(struct kbase_device *kbdev) if (ret != 0) goto err_out; + ret = kbase_csf_firmware_log_init(kbdev); + if (ret != 0) { + dev_err(kbdev->dev, "Failed to initialize FW trace (err %d)", ret); + goto err_out; + } + /* Firmware loaded successfully, ret = 0 */ KBASE_KTRACE_ADD(kbdev, CSF_FIRMWARE_BOOT, NULL, (((u64)version_hash) << 32) | @@ -2195,11 +2360,11 @@ int kbase_csf_firmware_init(struct kbase_device *kbdev) return 0; err_out: - kbase_csf_firmware_term(kbdev); + kbase_csf_firmware_unload_term(kbdev); return ret; } -void kbase_csf_firmware_term(struct kbase_device *kbdev) +void kbase_csf_firmware_unload_term(struct kbase_device *kbdev) { unsigned long flags; int ret = 0; @@ -2210,6 +2375,8 @@ void kbase_csf_firmware_term(struct kbase_device *kbdev) WARN(ret, "failed to wait for GPU reset"); + kbase_csf_firmware_log_term(kbdev); + kbase_csf_firmware_cfg_term(kbdev); kbase_csf_timeout_term(kbdev); @@ -2297,8 +2464,6 @@ void kbase_csf_firmware_term(struct kbase_device *kbdev) */ kbase_mcu_shared_interface_region_tracker_term(kbdev); - mutex_destroy(&kbdev->csf.reg_lock); - kbase_mmu_term(kbdev, &kbdev->csf.mcu_mmu); /* Release the address space */ @@ -2350,10 +2515,11 @@ void kbase_csf_firmware_ping(struct kbase_device *const kbdev) kbase_csf_scheduler_spin_unlock(kbdev, flags); } -int kbase_csf_firmware_ping_wait(struct kbase_device *const kbdev) +int kbase_csf_firmware_ping_wait(struct kbase_device *const kbdev, unsigned int wait_timeout_ms) { kbase_csf_firmware_ping(kbdev); - return wait_for_global_request(kbdev, GLB_REQ_PING_MASK); + + return wait_for_global_request_with_timeout(kbdev, GLB_REQ_PING_MASK, wait_timeout_ms); } int kbase_csf_firmware_set_timeout(struct kbase_device *const kbdev, @@ -2392,7 +2558,7 @@ void kbase_csf_enter_protected_mode(struct kbase_device *kbdev) kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR); } -void kbase_csf_wait_protected_mode_enter(struct kbase_device *kbdev) +int kbase_csf_wait_protected_mode_enter(struct kbase_device *kbdev) { int err; @@ -2432,12 +2598,14 @@ void kbase_csf_wait_protected_mode_enter(struct kbase_device *kbdev) } } - if (err) { + if (unlikely(err)) { if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) kbase_reset_gpu(kbdev); } KBASE_TLSTREAM_AUX_PROTECTED_ENTER_END(kbdev, kbdev); + + return err; } void kbase_csf_firmware_trigger_mcu_halt(struct kbase_device *kbdev) @@ -2651,9 +2819,8 @@ int kbase_csf_firmware_mcu_shared_mapping_init( if (!page_list) goto page_list_alloc_error; - ret = kbase_mem_pool_alloc_pages( - &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], - num_pages, phys, false); + ret = kbase_mem_pool_alloc_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, + phys, false); if (ret <= 0) goto phys_mem_pool_alloc_error; 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 85caaa7b2ab4..7560a298ac9c 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware.h @@ -364,7 +364,45 @@ void kbase_csf_update_firmware_memory(struct kbase_device *kbdev, u32 gpu_addr, u32 value); /** - * kbase_csf_firmware_early_init() - Early initializatin for the firmware. + * kbase_csf_read_firmware_memory_exe - Read a value in a GPU address in the + * region of its final execution location. + * + * @kbdev: Device pointer + * @gpu_addr: GPU address to read + * @value: Output pointer to which the read value will be written + * + * This function read a value in a GPU address that belongs to a private loaded + * firmware memory region based on its final execution location. The function + * assumes that the location is not permanently mapped on the CPU address space, + * therefore it maps it and then unmaps it to access it independently. This function + * needs to be used when accessing firmware memory regions which will be moved to + * their final execution location during firmware boot using an address based on the + * final execution location. + */ +void kbase_csf_read_firmware_memory_exe(struct kbase_device *kbdev, + u32 gpu_addr, u32 *value); + +/** + * kbase_csf_update_firmware_memory_exe - Write a value in a GPU address in the + * region of its final execution location. + * + * @kbdev: Device pointer + * @gpu_addr: GPU address to write + * @value: Value to write + * + * This function writes a value in a GPU address that belongs to a private loaded + * firmware memory region based on its final execution location. The function + * assumes that the location is not permanently mapped on the CPU address space, + * therefore it maps it and then unmaps it to access it independently. This function + * needs to be used when accessing firmware memory regions which will be moved to + * their final execution location during firmware boot using an address based on the + * final execution location. + */ +void kbase_csf_update_firmware_memory_exe(struct kbase_device *kbdev, + u32 gpu_addr, u32 value); + +/** + * kbase_csf_firmware_early_init() - Early initialization for the firmware. * @kbdev: Kbase device * * Initialize resources related to the firmware. Must be called at kbase probe. @@ -374,22 +412,43 @@ void kbase_csf_update_firmware_memory(struct kbase_device *kbdev, int kbase_csf_firmware_early_init(struct kbase_device *kbdev); /** - * kbase_csf_firmware_init() - Load the firmware for the CSF MCU + * kbase_csf_firmware_early_term() - Terminate resources related to the firmware + * after the firmware unload has been done. + * + * @kbdev: Device pointer + * + * This should be called only when kbase probe fails or gets rmmoded. + */ +void kbase_csf_firmware_early_term(struct kbase_device *kbdev); + +/** + * kbase_csf_firmware_late_init() - Late initialization for the firmware. + * @kbdev: Kbase device + * + * Initialize resources related to the firmware. But must be called after + * backend late init is done. Must be used at probe time only. + * + * Return: 0 if successful, negative error code on failure + */ +int kbase_csf_firmware_late_init(struct kbase_device *kbdev); + +/** + * kbase_csf_firmware_load_init() - Load the firmware for the CSF MCU * @kbdev: Kbase device * * Request the firmware from user space and load it into memory. * * Return: 0 if successful, negative error code on failure */ -int kbase_csf_firmware_init(struct kbase_device *kbdev); +int kbase_csf_firmware_load_init(struct kbase_device *kbdev); /** - * kbase_csf_firmware_term() - Unload the firmware + * kbase_csf_firmware_unload_term() - Unload the firmware * @kbdev: Kbase device * - * Frees the memory allocated by kbase_csf_firmware_init() + * Frees the memory allocated by kbase_csf_firmware_load_init() */ -void kbase_csf_firmware_term(struct kbase_device *kbdev); +void kbase_csf_firmware_unload_term(struct kbase_device *kbdev); /** * kbase_csf_firmware_ping - Send the ping request to firmware. @@ -404,13 +463,14 @@ void kbase_csf_firmware_ping(struct kbase_device *kbdev); * kbase_csf_firmware_ping_wait - Send the ping request to firmware and waits. * * @kbdev: Instance of a GPU platform device that implements a CSF interface. + * @wait_timeout_ms: Timeout to get the acknowledgment for PING request from FW. * * The function sends the ping request to firmware and waits to confirm it is * alive. * * Return: 0 on success, or negative on failure. */ -int kbase_csf_firmware_ping_wait(struct kbase_device *kbdev); +int kbase_csf_firmware_ping_wait(struct kbase_device *kbdev, unsigned int wait_timeout_ms); /** * kbase_csf_firmware_set_timeout - Set a hardware endpoint progress timeout. @@ -447,8 +507,10 @@ void kbase_csf_enter_protected_mode(struct kbase_device *kbdev); * This function needs to be called after kbase_csf_enter_protected_mode() to * wait for the GPU to actually enter protected mode. GPU reset is triggered if * the wait is unsuccessful. + * + * Return: 0 on success, or negative on failure. */ -void kbase_csf_wait_protected_mode_enter(struct kbase_device *kbdev); +int kbase_csf_wait_protected_mode_enter(struct kbase_device *kbdev); static inline bool kbase_csf_firmware_mcu_halted(struct kbase_device *kbdev) { 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 ad4ae74c7569..c895b080143a 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 @@ -20,13 +20,17 @@ */ #include -#include "mali_kbase_csf_firmware_cfg.h" #include #include +#include "mali_kbase_csf_firmware_cfg.h" +#include "mali_kbase_csf_firmware_log.h" + #if CONFIG_SYSFS #define CSF_FIRMWARE_CFG_SYSFS_DIR_NAME "firmware_config" +#define CSF_FIRMWARE_CFG_LOG_VERBOSITY_ENTRY_NAME "Log verbosity" + /** * struct firmware_config - Configuration item within the MCU firmware * @@ -125,7 +129,7 @@ static ssize_t store_fw_cfg(struct kobject *kobj, if (attr == &fw_cfg_attr_cur) { unsigned long flags; - u32 val; + u32 val, cur_val; int ret = kstrtouint(buf, 0, &val); if (ret) { @@ -140,7 +144,9 @@ static ssize_t store_fw_cfg(struct kobject *kobj, return -EINVAL; spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - if (config->cur_val == val) { + + cur_val = config->cur_val; + if (cur_val == val) { spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); return count; } @@ -177,6 +183,20 @@ static ssize_t store_fw_cfg(struct kobject *kobj, spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + /* Enable FW logging only if Log verbosity is non-zero */ + if (!strcmp(config->name, CSF_FIRMWARE_CFG_LOG_VERBOSITY_ENTRY_NAME) && + (!cur_val || !val)) { + ret = kbase_csf_firmware_log_toggle_logging_calls(kbdev, val); + if (ret) { + /* Undo FW configuration changes */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + config->cur_val = cur_val; + kbase_csf_update_firmware_memory(kbdev, config->address, cur_val); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + return ret; + } + } + /* If we can update the config without firmware reset then * we need to just trigger FIRMWARE_CONFIG_UPDATE. */ diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_log.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_log.c new file mode 100644 index 000000000000..20d8c0d4fdb1 --- /dev/null +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_log.c @@ -0,0 +1,451 @@ +// 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 "backend/gpu/mali_kbase_pm_internal.h" +#include +#include +#include +#include +#include + +/* + * ARMv7 instruction: Branch with Link calls a subroutine at a PC-relative address. + */ +#define ARMV7_T1_BL_IMM_INSTR 0xd800f000 + +/* + * ARMv7 instruction: Branch with Link calls a subroutine at a PC-relative address, maximum + * negative jump offset. + */ +#define ARMV7_T1_BL_IMM_RANGE_MIN -16777216 + +/* + * ARMv7 instruction: Branch with Link calls a subroutine at a PC-relative address, maximum + * positive jump offset. + */ +#define ARMV7_T1_BL_IMM_RANGE_MAX 16777214 + +/* + * ARMv7 instruction: Double NOP instructions. + */ +#define ARMV7_DOUBLE_NOP_INSTR 0xbf00bf00 + +#if defined(CONFIG_DEBUG_FS) + +static int kbase_csf_firmware_log_enable_mask_read(void *data, u64 *val) +{ + struct kbase_device *kbdev = (struct kbase_device *)data; + struct firmware_trace_buffer *tb = + kbase_csf_firmware_get_trace_buffer(kbdev, FIRMWARE_LOG_BUF_NAME); + + if (tb == NULL) { + dev_err(kbdev->dev, "Couldn't get the firmware trace buffer"); + return -EIO; + } + /* The enabled traces limited to u64 here, regarded practical */ + *val = kbase_csf_firmware_trace_buffer_get_active_mask64(tb); + return 0; +} + +static int kbase_csf_firmware_log_enable_mask_write(void *data, u64 val) +{ + struct kbase_device *kbdev = (struct kbase_device *)data; + struct firmware_trace_buffer *tb = + kbase_csf_firmware_get_trace_buffer(kbdev, FIRMWARE_LOG_BUF_NAME); + u64 new_mask; + unsigned int enable_bits_count; + + if (tb == NULL) { + dev_err(kbdev->dev, "Couldn't get the firmware trace buffer"); + return -EIO; + } + + /* Ignore unsupported types */ + enable_bits_count = kbase_csf_firmware_trace_buffer_get_trace_enable_bits_count(tb); + if (enable_bits_count > 64) { + dev_dbg(kbdev->dev, "Limit enabled bits count from %u to 64", enable_bits_count); + enable_bits_count = 64; + } + new_mask = val & ((1 << enable_bits_count) - 1); + + if (new_mask != kbase_csf_firmware_trace_buffer_get_active_mask64(tb)) + return kbase_csf_firmware_trace_buffer_set_active_mask64(tb, new_mask); + else + return 0; +} + +static int kbasep_csf_firmware_log_debugfs_open(struct inode *in, struct file *file) +{ + struct kbase_device *kbdev = in->i_private; + + file->private_data = kbdev; + dev_dbg(kbdev->dev, "Opened firmware trace buffer dump debugfs file"); + + return 0; +} + +static ssize_t kbasep_csf_firmware_log_debugfs_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + struct kbase_device *kbdev = file->private_data; + struct kbase_csf_firmware_log *fw_log = &kbdev->csf.fw_log; + unsigned int n_read; + unsigned long not_copied; + /* Limit reads to the kernel dump buffer size */ + size_t mem = MIN(size, FIRMWARE_LOG_DUMP_BUF_SIZE); + int ret; + + struct firmware_trace_buffer *tb = + kbase_csf_firmware_get_trace_buffer(kbdev, FIRMWARE_LOG_BUF_NAME); + + if (tb == NULL) { + dev_err(kbdev->dev, "Couldn't get the firmware trace buffer"); + return -EIO; + } + + if (atomic_cmpxchg(&fw_log->busy, 0, 1) != 0) + return -EBUSY; + + /* Reading from userspace is only allowed in manual mode */ + if (fw_log->mode != KBASE_CSF_FIRMWARE_LOG_MODE_MANUAL) { + ret = -EINVAL; + goto out; + } + + n_read = kbase_csf_firmware_trace_buffer_read_data(tb, fw_log->dump_buf, mem); + + /* Do the copy, if we have obtained some trace data */ + not_copied = (n_read) ? copy_to_user(buf, fw_log->dump_buf, n_read) : 0; + + if (not_copied) { + dev_err(kbdev->dev, "Couldn't copy trace buffer data to user space buffer"); + ret = -EFAULT; + goto out; + } + + *ppos += n_read; + ret = n_read; + +out: + atomic_set(&fw_log->busy, 0); + return ret; +} + +static int kbase_csf_firmware_log_mode_read(void *data, u64 *val) +{ + struct kbase_device *kbdev = (struct kbase_device *)data; + struct kbase_csf_firmware_log *fw_log = &kbdev->csf.fw_log; + + *val = fw_log->mode; + return 0; +} + +static int kbase_csf_firmware_log_mode_write(void *data, u64 val) +{ + struct kbase_device *kbdev = (struct kbase_device *)data; + struct kbase_csf_firmware_log *fw_log = &kbdev->csf.fw_log; + int ret = 0; + + if (atomic_cmpxchg(&fw_log->busy, 0, 1) != 0) + return -EBUSY; + + if (val == fw_log->mode) + goto out; + + switch (val) { + case KBASE_CSF_FIRMWARE_LOG_MODE_MANUAL: + cancel_delayed_work_sync(&fw_log->poll_work); + break; + case KBASE_CSF_FIRMWARE_LOG_MODE_AUTO_PRINT: + schedule_delayed_work(&fw_log->poll_work, + msecs_to_jiffies(KBASE_CSF_FIRMWARE_LOG_POLL_PERIOD_MS)); + break; + default: + ret = -EINVAL; + goto out; + } + + fw_log->mode = val; + +out: + atomic_set(&fw_log->busy, 0); + return ret; +} + +DEFINE_DEBUGFS_ATTRIBUTE(kbase_csf_firmware_log_enable_mask_fops, + kbase_csf_firmware_log_enable_mask_read, + kbase_csf_firmware_log_enable_mask_write, "%llx\n"); + +static const struct file_operations kbasep_csf_firmware_log_debugfs_fops = { + .owner = THIS_MODULE, + .open = kbasep_csf_firmware_log_debugfs_open, + .read = kbasep_csf_firmware_log_debugfs_read, + .llseek = no_llseek, +}; + +DEFINE_DEBUGFS_ATTRIBUTE(kbase_csf_firmware_log_mode_fops, kbase_csf_firmware_log_mode_read, + kbase_csf_firmware_log_mode_write, "%llu\n"); + +#endif /* CONFIG_DEBUG_FS */ + +static void kbase_csf_firmware_log_poll(struct work_struct *work) +{ + struct kbase_device *kbdev = + container_of(work, struct kbase_device, csf.fw_log.poll_work.work); + struct kbase_csf_firmware_log *fw_log = &kbdev->csf.fw_log; + + schedule_delayed_work(&fw_log->poll_work, + msecs_to_jiffies(KBASE_CSF_FIRMWARE_LOG_POLL_PERIOD_MS)); + + kbase_csf_firmware_log_dump_buffer(kbdev); +} + +int kbase_csf_firmware_log_init(struct kbase_device *kbdev) +{ + struct kbase_csf_firmware_log *fw_log = &kbdev->csf.fw_log; + + /* Add one byte for null-termination */ + fw_log->dump_buf = kmalloc(FIRMWARE_LOG_DUMP_BUF_SIZE + 1, GFP_KERNEL); + if (fw_log->dump_buf == NULL) + return -ENOMEM; + + /* Ensure null-termination for all strings */ + fw_log->dump_buf[FIRMWARE_LOG_DUMP_BUF_SIZE] = 0; + + fw_log->mode = KBASE_CSF_FIRMWARE_LOG_MODE_MANUAL; + + atomic_set(&fw_log->busy, 0); + INIT_DEFERRABLE_WORK(&fw_log->poll_work, kbase_csf_firmware_log_poll); + +#if defined(CONFIG_DEBUG_FS) + debugfs_create_file("fw_trace_enable_mask", 0644, kbdev->mali_debugfs_directory, kbdev, + &kbase_csf_firmware_log_enable_mask_fops); + debugfs_create_file("fw_traces", 0444, kbdev->mali_debugfs_directory, kbdev, + &kbasep_csf_firmware_log_debugfs_fops); + debugfs_create_file("fw_trace_mode", 0644, kbdev->mali_debugfs_directory, kbdev, + &kbase_csf_firmware_log_mode_fops); +#endif /* CONFIG_DEBUG_FS */ + + return 0; +} + +void kbase_csf_firmware_log_term(struct kbase_device *kbdev) +{ + struct kbase_csf_firmware_log *fw_log = &kbdev->csf.fw_log; + + if (fw_log->dump_buf) { + cancel_delayed_work_sync(&fw_log->poll_work); + kfree(fw_log->dump_buf); + fw_log->dump_buf = NULL; + } +} + +void kbase_csf_firmware_log_dump_buffer(struct kbase_device *kbdev) +{ + struct kbase_csf_firmware_log *fw_log = &kbdev->csf.fw_log; + u8 *buf = fw_log->dump_buf, *p, *pnewline, *pend, *pendbuf; + unsigned int read_size, remaining_size; + struct firmware_trace_buffer *tb = + kbase_csf_firmware_get_trace_buffer(kbdev, FIRMWARE_LOG_BUF_NAME); + + if (tb == NULL) { + dev_dbg(kbdev->dev, "Can't get the trace buffer, firmware trace dump skipped"); + return; + } + + if (atomic_cmpxchg(&fw_log->busy, 0, 1) != 0) + return; + + /* FW should only print complete messages, so there's no need to handle + * partial messages over multiple invocations of this function + */ + + p = buf; + pendbuf = &buf[FIRMWARE_LOG_DUMP_BUF_SIZE]; + + while ((read_size = kbase_csf_firmware_trace_buffer_read_data(tb, p, pendbuf - p))) { + pend = p + read_size; + p = buf; + + while (p < pend && (pnewline = memchr(p, '\n', pend - p))) { + /* Null-terminate the string */ + *pnewline = 0; + + dev_err(kbdev->dev, "FW> %s", p); + + p = pnewline + 1; + } + + remaining_size = pend - p; + + if (!remaining_size) { + p = buf; + } else if (remaining_size < FIRMWARE_LOG_DUMP_BUF_SIZE) { + /* Copy unfinished string to the start of the buffer */ + memmove(buf, p, remaining_size); + p = &buf[remaining_size]; + } else { + /* Print abnormally long string without newlines */ + dev_err(kbdev->dev, "FW> %s", buf); + p = buf; + } + } + + if (p != buf) { + /* Null-terminate and print last unfinished string */ + *p = 0; + dev_err(kbdev->dev, "FW> %s", buf); + } + + atomic_set(&fw_log->busy, 0); +} + +void kbase_csf_firmware_log_parse_logging_call_list_entry(struct kbase_device *kbdev, + const uint32_t *entry) +{ + kbdev->csf.fw_log.func_call_list_va_start = entry[0]; + kbdev->csf.fw_log.func_call_list_va_end = entry[1]; +} + +/** + * toggle_logging_calls_in_loaded_image - Toggles FW log func calls in loaded FW image. + * + * @kbdev: Instance of a GPU platform device that implements a CSF interface. + * @enable: Whether to enable or disable the function calls. + */ +static void toggle_logging_calls_in_loaded_image(struct kbase_device *kbdev, bool enable) +{ + uint32_t bl_instruction, diff; + uint32_t imm11, imm10, i1, i2, j1, j2, sign; + uint32_t calling_address = 0, callee_address = 0; + uint32_t list_entry = kbdev->csf.fw_log.func_call_list_va_start; + const uint32_t list_va_end = kbdev->csf.fw_log.func_call_list_va_end; + + if (list_entry == 0 || list_va_end == 0) + return; + + if (enable) { + for (; list_entry < list_va_end; list_entry += 2 * sizeof(uint32_t)) { + /* Read calling address */ + kbase_csf_read_firmware_memory(kbdev, list_entry, &calling_address); + /* Read callee address */ + kbase_csf_read_firmware_memory(kbdev, list_entry + sizeof(uint32_t), + &callee_address); + + diff = callee_address - calling_address - 4; + sign = !!(diff & 0x80000000); + if (ARMV7_T1_BL_IMM_RANGE_MIN > (int32_t)diff && + ARMV7_T1_BL_IMM_RANGE_MAX < (int32_t)diff) { + dev_warn(kbdev->dev, "FW log patch 0x%x out of range, skipping", + calling_address); + continue; + } + + i1 = (diff & 0x00800000) >> 23; + j1 = !i1 ^ sign; + i2 = (diff & 0x00400000) >> 22; + j2 = !i2 ^ sign; + imm11 = (diff & 0xffe) >> 1; + imm10 = (diff & 0x3ff000) >> 12; + + /* Compose BL instruction */ + bl_instruction = ARMV7_T1_BL_IMM_INSTR; + bl_instruction |= j1 << 29; + bl_instruction |= j2 << 27; + bl_instruction |= imm11 << 16; + bl_instruction |= sign << 10; + bl_instruction |= imm10; + + /* Patch logging func calls in their load location */ + dev_dbg(kbdev->dev, "FW log patch 0x%x: 0x%x\n", calling_address, + bl_instruction); + kbase_csf_update_firmware_memory_exe(kbdev, calling_address, + bl_instruction); + } + } else { + for (; list_entry < list_va_end; list_entry += 2 * sizeof(uint32_t)) { + /* Read calling address */ + kbase_csf_read_firmware_memory(kbdev, list_entry, &calling_address); + + /* Overwrite logging func calls with 2 NOP instructions */ + kbase_csf_update_firmware_memory_exe(kbdev, calling_address, + ARMV7_DOUBLE_NOP_INSTR); + } + } +} + +int kbase_csf_firmware_log_toggle_logging_calls(struct kbase_device *kbdev, u32 val) +{ + unsigned long flags; + struct kbase_csf_firmware_log *fw_log = &kbdev->csf.fw_log; + bool mcu_inactive; + bool resume_needed = false; + int ret = 0; + struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; + + if (atomic_cmpxchg(&fw_log->busy, 0, 1) != 0) + return -EBUSY; + + /* Suspend all the active CS groups */ + dev_dbg(kbdev->dev, "Suspend all the active CS groups"); + + kbase_csf_scheduler_lock(kbdev); + while (scheduler->state != SCHED_SUSPENDED) { + kbase_csf_scheduler_unlock(kbdev); + kbase_csf_scheduler_pm_suspend(kbdev); + kbase_csf_scheduler_lock(kbdev); + resume_needed = true; + } + + /* Wait for the MCU to get disabled */ + dev_info(kbdev->dev, "Wait for the MCU to get disabled"); + ret = kbase_pm_wait_for_desired_state(kbdev); + if (ret) { + dev_err(kbdev->dev, + "wait for PM state failed when toggling FW logging calls"); + ret = -EAGAIN; + goto out; + } + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + mcu_inactive = + kbase_pm_is_mcu_inactive(kbdev, kbdev->pm.backend.mcu_state); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + if (!mcu_inactive) { + dev_err(kbdev->dev, + "MCU not inactive after PM state wait when toggling FW logging calls"); + ret = -EAGAIN; + goto out; + } + + /* Toggle FW logging call in the loaded FW image */ + toggle_logging_calls_in_loaded_image(kbdev, val); + dev_dbg(kbdev->dev, "FW logging: %s", val ? "enabled" : "disabled"); + +out: + kbase_csf_scheduler_unlock(kbdev); + if (resume_needed) + /* Resume queue groups and start mcu */ + kbase_csf_scheduler_pm_resume(kbdev); + atomic_set(&fw_log->busy, 0); + return ret; +} diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_log.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_log.h new file mode 100644 index 000000000000..8d7a2210a457 --- /dev/null +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_firmware_log.h @@ -0,0 +1,74 @@ +/* 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 _KBASE_CSF_FIRMWARE_LOG_H_ +#define _KBASE_CSF_FIRMWARE_LOG_H_ + +#include + +/* + * Firmware log dumping buffer size. + */ +#define FIRMWARE_LOG_DUMP_BUF_SIZE PAGE_SIZE + +/** + * kbase_csf_firmware_log_init - Initialize firmware log handling. + * + * @kbdev: Pointer to the Kbase device + * + * Return: The initialization error code. + */ +int kbase_csf_firmware_log_init(struct kbase_device *kbdev); + +/** + * kbase_csf_firmware_log_term - Terminate firmware log handling. + * + * @kbdev: Pointer to the Kbase device + */ +void kbase_csf_firmware_log_term(struct kbase_device *kbdev); + +/** + * kbase_csf_firmware_log_dump_buffer - Read remaining data in the firmware log + * buffer and print it to dmesg. + * + * @kbdev: Pointer to the Kbase device + */ +void kbase_csf_firmware_log_dump_buffer(struct kbase_device *kbdev); + +/** + * kbase_csf_firmware_log_parse_logging_call_list_entry - Parse FW logging function call list entry. + * + * @kbdev: Instance of a GPU platform device that implements a CSF interface. + * @entry: Pointer to section. + */ +void kbase_csf_firmware_log_parse_logging_call_list_entry(struct kbase_device *kbdev, + const uint32_t *entry); +/** + * kbase_csf_firmware_log_toggle_logging_calls - Enables/Disables FW logging function calls. + * + * @kbdev: Instance of a GPU platform device that implements a CSF interface. + * @val: Configuration option value. + * + * Return: 0 if successful, negative error code on failure + */ +int kbase_csf_firmware_log_toggle_logging_calls(struct kbase_device *kbdev, u32 val); + +#endif /* _KBASE_CSF_FIRMWARE_LOG_H_ */ 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 54f1f6b9c199..f414d8894306 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 @@ -273,6 +273,18 @@ void kbase_csf_update_firmware_memory(struct kbase_device *kbdev, /* NO_MALI: Nothing to do here */ } +void kbase_csf_read_firmware_memory_exe(struct kbase_device *kbdev, + u32 gpu_addr, u32 *value) +{ + /* NO_MALI: Nothing to do here */ +} + +void kbase_csf_update_firmware_memory_exe(struct kbase_device *kbdev, + u32 gpu_addr, u32 value) +{ + /* NO_MALI: Nothing to do here */ +} + void kbase_csf_firmware_cs_input( const struct kbase_csf_cmd_stream_info *const info, const u32 offset, const u32 value) @@ -971,7 +983,6 @@ end: static u32 convert_dur_to_core_pwroff_count(struct kbase_device *kbdev, const u32 dur_us) { -#define PWROFF_VAL_UNIT_SHIFT (10) /* Get the cntfreq_el0 value, which drives the SYSTEM_TIMESTAMP */ u64 freq = arch_timer_get_cntfrq(); u64 dur_val = dur_us; @@ -1046,16 +1057,6 @@ int kbase_csf_firmware_early_init(struct kbase_device *kbdev) kbdev->csf.fw_timeout_ms = kbase_get_timeout_ms(kbdev, CSF_FIRMWARE_TIMEOUT); - kbdev->csf.gpu_idle_hysteresis_ms = FIRMWARE_IDLE_HYSTERESIS_TIME_MS; -#ifdef KBASE_PM_RUNTIME - if (kbase_pm_gpu_sleep_allowed(kbdev)) - kbdev->csf.gpu_idle_hysteresis_ms /= - FIRMWARE_IDLE_HYSTERESIS_GPU_SLEEP_SCALER; -#endif - WARN_ON(!kbdev->csf.gpu_idle_hysteresis_ms); - kbdev->csf.gpu_idle_dur_count = convert_dur_to_idle_count( - kbdev, kbdev->csf.gpu_idle_hysteresis_ms); - INIT_LIST_HEAD(&kbdev->csf.firmware_interfaces); INIT_LIST_HEAD(&kbdev->csf.firmware_config); INIT_LIST_HEAD(&kbdev->csf.firmware_trace_buffers.list); @@ -1068,7 +1069,26 @@ int kbase_csf_firmware_early_init(struct kbase_device *kbdev) return 0; } -int kbase_csf_firmware_init(struct kbase_device *kbdev) +void kbase_csf_firmware_early_term(struct kbase_device *kbdev) +{ + mutex_destroy(&kbdev->csf.reg_lock); +} + +int kbase_csf_firmware_late_init(struct kbase_device *kbdev) +{ + kbdev->csf.gpu_idle_hysteresis_ms = FIRMWARE_IDLE_HYSTERESIS_TIME_MS; +#ifdef KBASE_PM_RUNTIME + if (kbase_pm_gpu_sleep_allowed(kbdev)) + kbdev->csf.gpu_idle_hysteresis_ms /= FIRMWARE_IDLE_HYSTERESIS_GPU_SLEEP_SCALER; +#endif + WARN_ON(!kbdev->csf.gpu_idle_hysteresis_ms); + kbdev->csf.gpu_idle_dur_count = + convert_dur_to_idle_count(kbdev, kbdev->csf.gpu_idle_hysteresis_ms); + + return 0; +} + +int kbase_csf_firmware_load_init(struct kbase_device *kbdev) { int ret; @@ -1134,11 +1154,11 @@ int kbase_csf_firmware_init(struct kbase_device *kbdev) return 0; error: - kbase_csf_firmware_term(kbdev); + kbase_csf_firmware_unload_term(kbdev); return ret; } -void kbase_csf_firmware_term(struct kbase_device *kbdev) +void kbase_csf_firmware_unload_term(struct kbase_device *kbdev) { cancel_work_sync(&kbdev->csf.fw_error_work); @@ -1173,8 +1193,6 @@ void kbase_csf_firmware_term(struct kbase_device *kbdev) /* NO_MALI: No trace buffers to terminate */ - mutex_destroy(&kbdev->csf.reg_lock); - /* This will also free up the region allocated for the shared interface * entry parsed from the firmware image. */ @@ -1227,8 +1245,9 @@ void kbase_csf_firmware_ping(struct kbase_device *const kbdev) kbase_csf_scheduler_spin_unlock(kbdev, flags); } -int kbase_csf_firmware_ping_wait(struct kbase_device *const kbdev) +int kbase_csf_firmware_ping_wait(struct kbase_device *const kbdev, unsigned int wait_timeout_ms) { + CSTD_UNUSED(wait_timeout_ms); kbase_csf_firmware_ping(kbdev); return wait_for_global_request(kbdev, GLB_REQ_PING_MASK); } @@ -1267,7 +1286,7 @@ void kbase_csf_enter_protected_mode(struct kbase_device *kbdev) kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR); } -void kbase_csf_wait_protected_mode_enter(struct kbase_device *kbdev) +int kbase_csf_wait_protected_mode_enter(struct kbase_device *kbdev) { int err = wait_for_global_request(kbdev, GLB_REQ_PROTM_ENTER_MASK); @@ -1275,6 +1294,8 @@ void kbase_csf_wait_protected_mode_enter(struct kbase_device *kbdev) if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE)) kbase_reset_gpu(kbdev); } + + return err; } void kbase_csf_firmware_trigger_mcu_halt(struct kbase_device *kbdev) @@ -1483,9 +1504,8 @@ int kbase_csf_firmware_mcu_shared_mapping_init( if (!page_list) goto page_list_alloc_error; - ret = kbase_mem_pool_alloc_pages( - &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], - num_pages, phys, false); + ret = kbase_mem_pool_alloc_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, + phys, false); if (ret <= 0) goto phys_mem_pool_alloc_error; diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_heap_context_alloc.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_heap_context_alloc.c index 4b3931f6ccf7..1876d505dd5b 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_heap_context_alloc.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_heap_context_alloc.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 @@ -154,8 +154,8 @@ u64 kbase_csf_heap_context_allocator_alloc( struct kbase_csf_heap_context_allocator *const ctx_alloc) { struct kbase_context *const kctx = ctx_alloc->kctx; - u64 flags = BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR | - BASE_MEM_PROT_CPU_WR | BASEP_MEM_NO_USER_FREE; + u64 flags = BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR | BASE_MEM_PROT_CPU_WR | + BASEP_MEM_NO_USER_FREE | BASE_MEM_PROT_CPU_RD; u64 nr_pages = PFN_UP(HEAP_CTX_REGION_SIZE); u64 heap_gpu_va = 0; @@ -164,10 +164,6 @@ u64 kbase_csf_heap_context_allocator_alloc( */ const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_ASYNC; -#ifdef CONFIG_MALI_VECTOR_DUMP - flags |= BASE_MEM_PROT_CPU_RD; -#endif - mutex_lock(&ctx_alloc->lock); /* If the pool of heap contexts wasn't already allocated then 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 542f04579898..0b3f1334a9e6 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.c @@ -55,7 +55,7 @@ static int kbase_kcpu_map_import_prepare( long i; int ret = 0; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kcpu_queue->lock); /* Take the processes mmap lock */ down_read(kbase_mem_get_process_mmap_lock()); @@ -114,7 +114,7 @@ static int kbase_kcpu_unmap_import_prepare_internal( struct kbase_va_region *reg; int ret = 0; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kcpu_queue->lock); kbase_gpu_vm_lock(kctx); @@ -182,7 +182,8 @@ static void kbase_jit_add_to_pending_alloc_list( &kctx->csf.kcpu_queues.jit_blocked_queues; struct kbase_kcpu_command_queue *blocked_queue; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&queue->lock); + lockdep_assert_held(&kctx->csf.kcpu_queues.jit_lock); list_for_each_entry(blocked_queue, &kctx->csf.kcpu_queues.jit_blocked_queues, @@ -227,25 +228,28 @@ static int kbase_kcpu_jit_allocate_process( u32 i; int ret; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); - - if (alloc_info->blocked) { - list_del(&queue->jit_blocked); - alloc_info->blocked = false; - } + lockdep_assert_held(&queue->lock); if (WARN_ON(!info)) return -EINVAL; + mutex_lock(&kctx->csf.kcpu_queues.jit_lock); + /* Check if all JIT IDs are not in use */ for (i = 0; i < count; i++, info++) { /* The JIT ID is still in use so fail the allocation */ if (kctx->jit_alloc[info->id]) { dev_dbg(kctx->kbdev->dev, "JIT ID still in use"); - return -EINVAL; + ret = -EINVAL; + goto fail; } } + if (alloc_info->blocked) { + list_del(&queue->jit_blocked); + alloc_info->blocked = false; + } + /* Now start the allocation loop */ for (i = 0, info = alloc_info->info; i < count; i++, info++) { /* Create a JIT allocation */ @@ -280,7 +284,7 @@ static int kbase_kcpu_jit_allocate_process( */ dev_warn_ratelimited(kctx->kbdev->dev, "JIT alloc command failed: %pK\n", cmd); ret = -ENOMEM; - goto fail; + goto fail_rollback; } /* There are pending frees for an active allocation @@ -298,7 +302,8 @@ static int kbase_kcpu_jit_allocate_process( kctx->jit_alloc[info->id] = NULL; } - return -EAGAIN; + ret = -EAGAIN; + goto fail; } /* Bind it to the user provided ID. */ @@ -314,7 +319,7 @@ static int kbase_kcpu_jit_allocate_process( KBASE_REG_CPU_WR, &mapping); if (!ptr) { ret = -ENOMEM; - goto fail; + goto fail_rollback; } reg = kctx->jit_alloc[info->id]; @@ -323,9 +328,11 @@ static int kbase_kcpu_jit_allocate_process( kbase_vunmap(kctx, &mapping); } + mutex_unlock(&kctx->csf.kcpu_queues.jit_lock); + return 0; -fail: +fail_rollback: /* Roll back completely */ for (i = 0, info = alloc_info->info; i < count; i++, info++) { /* Free the allocations that were successful. @@ -338,6 +345,8 @@ fail: kctx->jit_alloc[info->id] = KBASE_RESERVED_REG_JIT_ALLOC; } +fail: + mutex_unlock(&kctx->csf.kcpu_queues.jit_lock); return ret; } @@ -354,7 +363,7 @@ static int kbase_kcpu_jit_allocate_prepare( int ret = 0; u32 i; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kcpu_queue->lock); if (!data || count > kcpu_queue->kctx->jit_max_allocations || count > ARRAY_SIZE(kctx->jit_alloc)) { @@ -392,11 +401,13 @@ static int kbase_kcpu_jit_allocate_prepare( } current_command->type = BASE_KCPU_COMMAND_TYPE_JIT_ALLOC; - list_add_tail(¤t_command->info.jit_alloc.node, - &kctx->csf.kcpu_queues.jit_cmds_head); current_command->info.jit_alloc.info = info; current_command->info.jit_alloc.count = count; current_command->info.jit_alloc.blocked = false; + mutex_lock(&kctx->csf.kcpu_queues.jit_lock); + list_add_tail(¤t_command->info.jit_alloc.node, + &kctx->csf.kcpu_queues.jit_cmds_head); + mutex_unlock(&kctx->csf.kcpu_queues.jit_lock); return 0; out_free: @@ -415,7 +426,9 @@ static void kbase_kcpu_jit_allocate_finish( struct kbase_kcpu_command_queue *queue, struct kbase_kcpu_command *cmd) { - lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&queue->lock); + + mutex_lock(&queue->kctx->csf.kcpu_queues.jit_lock); /* Remove this command from the jit_cmds_head list */ list_del(&cmd->info.jit_alloc.node); @@ -429,6 +442,8 @@ static void kbase_kcpu_jit_allocate_finish( cmd->info.jit_alloc.blocked = false; } + mutex_unlock(&queue->kctx->csf.kcpu_queues.jit_lock); + kfree(cmd->info.jit_alloc.info); } @@ -441,18 +456,17 @@ static void kbase_kcpu_jit_retry_pending_allocs(struct kbase_context *kctx) { struct kbase_kcpu_command_queue *blocked_queue; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kctx->csf.kcpu_queues.jit_lock); /* * Reschedule all queues blocked by JIT_ALLOC commands. * NOTE: This code traverses the list of blocked queues directly. It * only works as long as the queued works are not executed at the same * time. This precondition is true since we're holding the - * kbase_csf_kcpu_queue_context.lock . + * kbase_csf_kcpu_queue_context.jit_lock . */ - list_for_each_entry(blocked_queue, - &kctx->csf.kcpu_queues.jit_blocked_queues, jit_blocked) - queue_work(kctx->csf.kcpu_queues.wq, &blocked_queue->work); + list_for_each_entry(blocked_queue, &kctx->csf.kcpu_queues.jit_blocked_queues, jit_blocked) + queue_work(blocked_queue->wq, &blocked_queue->work); } static int kbase_kcpu_jit_free_process(struct kbase_kcpu_command_queue *queue, @@ -469,7 +483,8 @@ static int kbase_kcpu_jit_free_process(struct kbase_kcpu_command_queue *queue, if (WARN_ON(!ids)) return -EINVAL; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&queue->lock); + mutex_lock(&kctx->csf.kcpu_queues.jit_lock); KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_FREE_END(queue->kctx->kbdev, queue); @@ -501,9 +516,6 @@ static int kbase_kcpu_jit_free_process(struct kbase_kcpu_command_queue *queue, queue->kctx->kbdev, queue, item_err, pages_used); } - /* Free the list of ids */ - kfree(ids); - /* * Remove this command from the jit_cmds_head list and retry pending * allocations. @@ -511,6 +523,11 @@ static int kbase_kcpu_jit_free_process(struct kbase_kcpu_command_queue *queue, list_del(&cmd->info.jit_free.node); kbase_kcpu_jit_retry_pending_allocs(kctx); + mutex_unlock(&kctx->csf.kcpu_queues.jit_lock); + + /* Free the list of ids */ + kfree(ids); + return rc; } @@ -526,7 +543,7 @@ static int kbase_kcpu_jit_free_prepare( int ret; u32 i; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kcpu_queue->lock); /* Sanity checks */ if (!count || count > ARRAY_SIZE(kctx->jit_alloc)) { @@ -572,10 +589,12 @@ static int kbase_kcpu_jit_free_prepare( } current_command->type = BASE_KCPU_COMMAND_TYPE_JIT_FREE; - list_add_tail(¤t_command->info.jit_free.node, - &kctx->csf.kcpu_queues.jit_cmds_head); current_command->info.jit_free.ids = ids; current_command->info.jit_free.count = count; + mutex_lock(&kctx->csf.kcpu_queues.jit_lock); + list_add_tail(¤t_command->info.jit_free.node, + &kctx->csf.kcpu_queues.jit_cmds_head); + mutex_unlock(&kctx->csf.kcpu_queues.jit_lock); return 0; out_free: @@ -601,7 +620,7 @@ static int kbase_csf_queue_group_suspend_prepare( int pinned_pages = 0, ret = 0; struct kbase_va_region *reg; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kcpu_queue->lock); if (suspend_buf->size < csg_suspend_buf_size) return -EINVAL; @@ -652,9 +671,12 @@ static int kbase_csf_queue_group_suspend_prepare( u64 start, end, i; if (((reg->flags & KBASE_REG_ZONE_MASK) != KBASE_REG_ZONE_SAME_VA) || - reg->nr_pages < nr_pages || - kbase_reg_current_backed_size(reg) != - reg->nr_pages) { + (kbase_reg_current_backed_size(reg) < nr_pages) || + !(reg->flags & KBASE_REG_CPU_WR) || + (reg->gpu_alloc->type != KBASE_MEM_TYPE_NATIVE) || + (reg->flags & KBASE_REG_DONT_NEED) || + (reg->flags & KBASE_REG_ACTIVE_JIT_ALLOC) || + (reg->flags & KBASE_REG_NO_USER_FREE)) { ret = -EINVAL; goto out_clean_pages; } @@ -703,9 +725,8 @@ static enum kbase_csf_event_callback_action event_cqs_callback(void *param) { struct kbase_kcpu_command_queue *kcpu_queue = (struct kbase_kcpu_command_queue *)param; - struct kbase_context *const kctx = kcpu_queue->kctx; - queue_work(kctx->csf.kcpu_queues.wq, &kcpu_queue->work); + queue_work(kcpu_queue->wq, &kcpu_queue->work); return KBASE_CSF_EVENT_CALLBACK_KEEP; } @@ -735,7 +756,7 @@ static int kbase_kcpu_cqs_wait_process(struct kbase_device *kbdev, { u32 i; - lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&queue->lock); if (WARN_ON(!cqs_wait->objs)) return -EINVAL; @@ -803,7 +824,7 @@ static int kbase_kcpu_cqs_wait_prepare(struct kbase_kcpu_command_queue *queue, struct base_cqs_wait_info *objs; unsigned int nr_objs = cqs_wait_info->nr_objs; - lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&queue->lock); if (nr_objs > BASEP_KCPU_CQS_MAX_NUM_OBJS) return -EINVAL; @@ -857,7 +878,7 @@ static void kbase_kcpu_cqs_set_process(struct kbase_device *kbdev, { unsigned int i; - lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&queue->lock); if (WARN_ON(!cqs_set->objs)) return; @@ -898,11 +919,10 @@ static int kbase_kcpu_cqs_set_prepare( struct base_kcpu_command_cqs_set_info *cqs_set_info, struct kbase_kcpu_command *current_command) { - struct kbase_context *const kctx = kcpu_queue->kctx; struct base_cqs_set *objs; unsigned int nr_objs = cqs_set_info->nr_objs; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kcpu_queue->lock); if (nr_objs > BASEP_KCPU_CQS_MAX_NUM_OBJS) return -EINVAL; @@ -952,7 +972,7 @@ static int kbase_kcpu_cqs_wait_operation_process(struct kbase_device *kbdev, { u32 i; - lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&queue->lock); if (WARN_ON(!cqs_wait_operation->objs)) return -EINVAL; @@ -1039,7 +1059,7 @@ static int kbase_kcpu_cqs_wait_operation_prepare(struct kbase_kcpu_command_queue struct base_cqs_wait_operation_info *objs; unsigned int nr_objs = cqs_wait_operation_info->nr_objs; - lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&queue->lock); if (nr_objs > BASEP_KCPU_CQS_MAX_NUM_OBJS) return -EINVAL; @@ -1094,7 +1114,7 @@ static void kbase_kcpu_cqs_set_operation_process( { unsigned int i; - lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&queue->lock); if (WARN_ON(!cqs_set_operation->objs)) return; @@ -1161,11 +1181,10 @@ static int kbase_kcpu_cqs_set_operation_prepare( struct base_kcpu_command_cqs_set_operation_info *cqs_set_operation_info, struct kbase_kcpu_command *current_command) { - struct kbase_context *const kctx = kcpu_queue->kctx; struct base_cqs_set_operation_info *objs; unsigned int nr_objs = cqs_set_operation_info->nr_objs; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kcpu_queue->lock); if (nr_objs > BASEP_KCPU_CQS_MAX_NUM_OBJS) return -EINVAL; @@ -1212,7 +1231,7 @@ static void kbase_csf_fence_wait_callback(struct dma_fence *fence, fence->context, fence->seqno); /* Resume kcpu command queue processing. */ - queue_work(kctx->csf.kcpu_queues.wq, &kcpu_queue->work); + queue_work(kcpu_queue->wq, &kcpu_queue->work); } static void kbase_kcpu_fence_wait_cancel( @@ -1221,7 +1240,7 @@ static void kbase_kcpu_fence_wait_cancel( { struct kbase_context *const kctx = kcpu_queue->kctx; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kcpu_queue->lock); if (WARN_ON(!fence_info->fence)) return; @@ -1293,7 +1312,7 @@ static void fence_timeout_callback(struct timer_list *timer) kbase_sync_fence_info_get(fence, &info); if (info.status == 1) { - queue_work(kctx->csf.kcpu_queues.wq, &kcpu_queue->work); + queue_work(kcpu_queue->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); @@ -1345,7 +1364,7 @@ static int kbase_kcpu_fence_wait_process( #endif struct kbase_context *const kctx = kcpu_queue->kctx; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kcpu_queue->lock); if (WARN_ON(!fence_info->fence)) return -EINVAL; @@ -1401,7 +1420,6 @@ static int kbase_kcpu_fence_wait_prepare( struct base_kcpu_command_fence_info *fence_info, struct kbase_kcpu_command *current_command) { - struct kbase_context *const kctx = kcpu_queue->kctx; #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) struct fence *fence_in; #else @@ -1409,7 +1427,7 @@ static int kbase_kcpu_fence_wait_prepare( #endif struct base_fence fence; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kcpu_queue->lock); if (copy_from_user(&fence, u64_to_user_ptr(fence_info->fence), sizeof(fence))) @@ -1460,7 +1478,6 @@ static int kbase_kcpu_fence_signal_prepare( struct base_kcpu_command_fence_info *fence_info, struct kbase_kcpu_command *current_command) { - struct kbase_context *const kctx = kcpu_queue->kctx; #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) struct fence *fence_out; #else @@ -1471,7 +1488,7 @@ static int kbase_kcpu_fence_signal_prepare( int ret = 0; int fd; - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&kcpu_queue->lock); if (copy_from_user(&fence, u64_to_user_ptr(fence_info->fence), sizeof(fence))) @@ -1549,11 +1566,9 @@ static void kcpu_queue_process_worker(struct work_struct *data) struct kbase_kcpu_command_queue *queue = container_of(data, struct kbase_kcpu_command_queue, work); - mutex_lock(&queue->kctx->csf.kcpu_queues.lock); - + mutex_lock(&queue->lock); kcpu_queue_process(queue, false); - - mutex_unlock(&queue->kctx->csf.kcpu_queues.lock); + mutex_unlock(&queue->lock); } static int delete_queue(struct kbase_context *kctx, u32 id) @@ -1569,6 +1584,17 @@ static int delete_queue(struct kbase_context *kctx, u32 id) KBASE_KTRACE_ADD_CSF_KCPU(kctx->kbdev, KCPU_QUEUE_DELETE, queue, queue->num_pending_cmds, queue->cqs_wait_count); + /* Disassociate the queue from the system to prevent further + * submissions. Draining pending commands would be acceptable + * even if a new queue is created using the same ID. + */ + kctx->csf.kcpu_queues.array[id] = NULL; + bitmap_clear(kctx->csf.kcpu_queues.in_use, id, 1); + + mutex_unlock(&kctx->csf.kcpu_queues.lock); + + mutex_lock(&queue->lock); + /* Drain the remaining work for this queue first and go past * all the waits. */ @@ -1580,17 +1606,17 @@ static int delete_queue(struct kbase_context *kctx, u32 id) /* All CQS wait commands should have been cleaned up */ WARN_ON(queue->cqs_wait_count); - kctx->csf.kcpu_queues.array[id] = NULL; - bitmap_clear(kctx->csf.kcpu_queues.in_use, id, 1); - /* Fire the tracepoint with the mutex held to enforce correct * ordering with the summary stream. */ KBASE_TLSTREAM_TL_KBASE_DEL_KCPUQUEUE(kctx->kbdev, queue); - mutex_unlock(&kctx->csf.kcpu_queues.lock); + mutex_unlock(&queue->lock); cancel_work_sync(&queue->work); + destroy_workqueue(queue->wq); + + mutex_destroy(&queue->lock); kfree(queue); } else { @@ -1657,7 +1683,7 @@ static void kcpu_queue_process(struct kbase_kcpu_command_queue *queue, bool process_next = true; size_t i; - lockdep_assert_held(&queue->kctx->csf.kcpu_queues.lock); + lockdep_assert_held(&queue->lock); for (i = 0; i != queue->num_pending_cmds; ++i) { struct kbase_kcpu_command *cmd = @@ -2058,9 +2084,11 @@ int kbase_csf_kcpu_queue_enqueue(struct kbase_context *kctx, /* The offset to the first command that is being processed or yet to * be processed is of u8 type, so the number of commands inside the - * queue cannot be more than 256. + * queue cannot be more than 256. The current implementation expects + * exactly 256, any other size will require the addition of wrapping + * logic. */ - BUILD_BUG_ON(KBASEP_KCPU_QUEUE_SIZE > 256); + BUILD_BUG_ON(KBASEP_KCPU_QUEUE_SIZE != 256); /* Whilst the backend interface allows enqueueing multiple commands in * a single operation, the Base interface does not expose any mechanism @@ -2076,13 +2104,13 @@ int kbase_csf_kcpu_queue_enqueue(struct kbase_context *kctx, } mutex_lock(&kctx->csf.kcpu_queues.lock); - - if (!kctx->csf.kcpu_queues.array[enq->id]) { - ret = -EINVAL; - goto out; - } - queue = kctx->csf.kcpu_queues.array[enq->id]; + mutex_unlock(&kctx->csf.kcpu_queues.lock); + + if (queue == NULL) + return -EINVAL; + + mutex_lock(&queue->lock); if (kcpu_queue_get_space(queue) < enq->nr_commands) { ret = -EBUSY; @@ -2097,7 +2125,7 @@ int kbase_csf_kcpu_queue_enqueue(struct kbase_context *kctx, * for the possibility to roll back. */ - for (i = 0; (i != enq->nr_commands) && !ret; ++i, ++kctx->csf.kcpu_queues.num_cmds) { + for (i = 0; (i != enq->nr_commands) && !ret; ++i) { struct kbase_kcpu_command *kcpu_cmd = &queue->commands[(u8)(queue->start_offset + queue->num_pending_cmds + i)]; struct base_kcpu_command command; @@ -2120,7 +2148,7 @@ int kbase_csf_kcpu_queue_enqueue(struct kbase_context *kctx, } } - kcpu_cmd->enqueue_ts = kctx->csf.kcpu_queues.num_cmds; + kcpu_cmd->enqueue_ts = atomic64_inc_return(&kctx->csf.kcpu_queues.cmd_seq_num); switch (command.type) { case BASE_KCPU_COMMAND_TYPE_FENCE_WAIT: #if IS_ENABLED(CONFIG_SYNC_FILE) @@ -2208,13 +2236,10 @@ int kbase_csf_kcpu_queue_enqueue(struct kbase_context *kctx, queue->num_pending_cmds += enq->nr_commands; kcpu_queue_process(queue, false); - } else { - /* Roll back the number of enqueued commands */ - kctx->csf.kcpu_queues.num_cmds -= i; } out: - mutex_unlock(&kctx->csf.kcpu_queues.lock); + mutex_unlock(&queue->lock); return ret; } @@ -2228,14 +2253,9 @@ int kbase_csf_kcpu_queue_context_init(struct kbase_context *kctx) for (idx = 0; idx < KBASEP_MAX_KCPU_QUEUES; ++idx) kctx->csf.kcpu_queues.array[idx] = NULL; - kctx->csf.kcpu_queues.wq = alloc_workqueue("mali_kbase_csf_kcpu", - WQ_UNBOUND | WQ_HIGHPRI, 0); - if (!kctx->csf.kcpu_queues.wq) - return -ENOMEM; - mutex_init(&kctx->csf.kcpu_queues.lock); - kctx->csf.kcpu_queues.num_cmds = 0; + atomic64_set(&kctx->csf.kcpu_queues.cmd_seq_num, 0); return 0; } @@ -2253,7 +2273,6 @@ void kbase_csf_kcpu_queue_context_term(struct kbase_context *kctx) (void)delete_queue(kctx, id); } - destroy_workqueue(kctx->csf.kcpu_queues.wq); mutex_destroy(&kctx->csf.kcpu_queues.lock); } @@ -2297,8 +2316,17 @@ int kbase_csf_kcpu_queue_new(struct kbase_context *kctx, goto out; } + queue->wq = alloc_workqueue("mali_kbase_csf_kcpu_wq_%i", WQ_UNBOUND | WQ_HIGHPRI, 0, idx); + if (queue->wq == NULL) { + kfree(queue); + ret = -ENOMEM; + + goto out; + } + bitmap_set(kctx->csf.kcpu_queues.in_use, idx, 1); kctx->csf.kcpu_queues.array[idx] = queue; + mutex_init(&queue->lock); queue->kctx = kctx; queue->start_offset = 0; queue->num_pending_cmds = 0; 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 a4db86984721..5f9b8e0684bc 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_kcpu.h @@ -236,9 +236,11 @@ struct kbase_kcpu_command { /** * struct kbase_kcpu_command_queue - a command queue executed by the kernel * + * @lock: Lock to protect accesses to this queue. * @kctx: The context to which this command queue belongs. * @commands: Array of commands which have been successfully * enqueued to this command queue. + * @wq: Dedicated workqueue for processing commands. * @work: struct work_struct which contains a pointer to * the function which handles processing of kcpu * commands enqueued into a kcpu command queue; @@ -274,8 +276,10 @@ struct kbase_kcpu_command { * @fence_timeout: Timer used to detect the fence wait timeout. */ struct kbase_kcpu_command_queue { + struct mutex lock; struct kbase_context *kctx; struct kbase_kcpu_command commands[KBASEP_KCPU_QUEUE_SIZE]; + struct workqueue_struct *wq; struct work_struct work; u8 start_offset; u8 id; 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 177569bfb427..6dde56cb161a 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_registers.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_registers.h @@ -163,6 +163,8 @@ #define CSG_PROTM_SUSPEND_BUF_HI 0x004C /* () Protected mode suspend buffer, high word */ #define CSG_CONFIG 0x0050 /* () CSG configuration options */ #define CSG_ITER_TRACE_CONFIG 0x0054 /* () CSG trace configuration */ +#define CSG_DVS_BUF_LO 0x0060 /* () Normal mode deferred vertex shading work buffer, low word */ +#define CSG_DVS_BUF_HI 0x0064 /* () Normal mode deferred vertex shading work buffer, high word */ /* CSG_OUTPUT_BLOCK register offsets */ #define CSG_ACK 0x0000 /* () CSG acknowledge flags */ @@ -547,6 +549,13 @@ #define CS_STATUS_WAIT_SB_MASK_SET(reg_val, value) \ (((reg_val) & ~CS_STATUS_WAIT_SB_MASK_MASK) | \ (((value) << CS_STATUS_WAIT_SB_MASK_SHIFT) & CS_STATUS_WAIT_SB_MASK_MASK)) +#define CS_STATUS_WAIT_SB_SOURCE_SHIFT 16 +#define CS_STATUS_WAIT_SB_SOURCE_MASK (0xF << CS_STATUS_WAIT_SB_SOURCE_SHIFT) +#define CS_STATUS_WAIT_SB_SOURCE_GET(reg_val) \ + (((reg_val)&CS_STATUS_WAIT_SB_SOURCE_MASK) >> CS_STATUS_WAIT_SB_SOURCE_SHIFT) +#define CS_STATUS_WAIT_SB_SOURCE_SET(reg_val, value) \ + (((reg_val) & ~CS_STATUS_WAIT_SB_SOURCE_MASK) | \ + (((value) << CS_STATUS_WAIT_SB_SOURCE_SHIFT) & CS_STATUS_WAIT_SB_SOURCE_MASK)) #define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_SHIFT 24 #define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_MASK (0xF << CS_STATUS_WAIT_SYNC_WAIT_CONDITION_SHIFT) #define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GET(reg_val) \ @@ -557,6 +566,7 @@ /* CS_STATUS_WAIT_SYNC_WAIT_CONDITION values */ #define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_LE 0x0 #define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GT 0x1 +#define CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GE 0x5 /* End of CS_STATUS_WAIT_SYNC_WAIT_CONDITION values */ #define CS_STATUS_WAIT_PROGRESS_WAIT_SHIFT 28 #define CS_STATUS_WAIT_PROGRESS_WAIT_MASK (0x1 << CS_STATUS_WAIT_PROGRESS_WAIT_SHIFT) @@ -835,11 +845,6 @@ #define CSG_REQ_IDLE_GET(reg_val) (((reg_val)&CSG_REQ_IDLE_MASK) >> CSG_REQ_IDLE_SHIFT) #define CSG_REQ_IDLE_SET(reg_val, value) \ (((reg_val) & ~CSG_REQ_IDLE_MASK) | (((value) << CSG_REQ_IDLE_SHIFT) & CSG_REQ_IDLE_MASK)) -#define CSG_REQ_DOORBELL_SHIFT 30 -#define CSG_REQ_DOORBELL_MASK (0x1 << CSG_REQ_DOORBELL_SHIFT) -#define CSG_REQ_DOORBELL_GET(reg_val) (((reg_val)&CSG_REQ_DOORBELL_MASK) >> CSG_REQ_DOORBELL_SHIFT) -#define CSG_REQ_DOORBELL_SET(reg_val, value) \ - (((reg_val) & ~CSG_REQ_DOORBELL_MASK) | (((value) << CSG_REQ_DOORBELL_SHIFT) & CSG_REQ_DOORBELL_MASK)) #define CSG_REQ_PROGRESS_TIMER_EVENT_SHIFT 31 #define CSG_REQ_PROGRESS_TIMER_EVENT_MASK (0x1 << CSG_REQ_PROGRESS_TIMER_EVENT_SHIFT) #define CSG_REQ_PROGRESS_TIMER_EVENT_GET(reg_val) \ @@ -956,6 +961,21 @@ (((reg_val) & ~CSG_PROTM_SUSPEND_BUF_POINTER_MASK) | \ (((value) << CSG_PROTM_SUSPEND_BUF_POINTER_SHIFT) & CSG_PROTM_SUSPEND_BUF_POINTER_MASK)) +/* CSG_DVS_BUF_BUFFER register */ +#define CSG_DVS_BUF_BUFFER_SIZE_SHIFT GPU_U(0) +#define CSG_DVS_BUF_BUFFER_SIZE_MASK (GPU_U(0xFFF) << CSG_DVS_BUF_BUFFER_SIZE_SHIFT) +#define CSG_DVS_BUF_BUFFER_SIZE_GET(reg_val) (((reg_val)&CSG_DVS_BUF_BUFFER_SIZE_MASK) >> CSG_DVS_BUF_BUFFER_SIZE_SHIFT) +#define CSG_DVS_BUF_BUFFER_SIZE_SET(reg_val, value) \ + (((reg_val) & ~CSG_DVS_BUF_BUFFER_SIZE_MASK) | \ + (((value) << CSG_DVS_BUF_BUFFER_SIZE_SHIFT) & CSG_DVS_BUF_BUFFER_SIZE_MASK)) +#define CSG_DVS_BUF_BUFFER_POINTER_SHIFT GPU_U(12) +#define CSG_DVS_BUF_BUFFER_POINTER_MASK \ + (GPU_ULL(0xFFFFFFFFFFFFF) << CSG_DVS_BUF_BUFFER_POINTER_SHIFT) +#define CSG_DVS_BUF_BUFFER_POINTER_GET(reg_val) \ + (((reg_val)&CSG_DVS_BUF_BUFFER_POINTER_MASK) >> CSG_DVS_BUF_BUFFER_POINTER_SHIFT) +#define CSG_DVS_BUF_BUFFER_POINTER_SET(reg_val, value) \ + (((reg_val) & ~CSG_DVS_BUF_BUFFER_POINTER_MASK) | \ + (((value) << CSG_DVS_BUF_BUFFER_POINTER_SHIFT) & CSG_DVS_BUF_BUFFER_POINTER_MASK)) /* End of CSG_INPUT_BLOCK register set definitions */ diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_reset_gpu.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_reset_gpu.c index 10de93faee27..fe3b91a4845d 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_reset_gpu.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_reset_gpu.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 @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include @@ -29,7 +29,7 @@ #include #include #include -#include +#include enum kbasep_soft_reset_status { RESET_SUCCESS = 0, @@ -257,68 +257,6 @@ static void kbase_csf_debug_dump_registers(struct kbase_device *kbdev) kbase_reg_read(kbdev, GPU_CONTROL_REG(TILER_CONFIG))); } -static void kbase_csf_dump_firmware_trace_buffer(struct kbase_device *kbdev) -{ - u8 *buf, *p, *pnewline, *pend, *pendbuf; - unsigned int read_size, remaining_size; - struct firmware_trace_buffer *tb = - kbase_csf_firmware_get_trace_buffer(kbdev, FW_TRACE_BUF_NAME); - - if (tb == NULL) { - dev_dbg(kbdev->dev, "Can't get the trace buffer, firmware trace dump skipped"); - return; - } - - buf = kmalloc(PAGE_SIZE + 1, GFP_KERNEL); - if (buf == NULL) { - dev_err(kbdev->dev, "Short of memory, firmware trace dump skipped"); - return; - } - - buf[PAGE_SIZE] = 0; - - p = buf; - pendbuf = &buf[PAGE_SIZE]; - - dev_err(kbdev->dev, "Firmware trace buffer dump:"); - while ((read_size = kbase_csf_firmware_trace_buffer_read_data(tb, p, - pendbuf - p))) { - pend = p + read_size; - p = buf; - - while (p < pend && (pnewline = memchr(p, '\n', pend - p))) { - /* Null-terminate the string */ - *pnewline = 0; - - dev_err(kbdev->dev, "FW> %s", p); - - p = pnewline + 1; - } - - remaining_size = pend - p; - - if (!remaining_size) { - p = buf; - } else if (remaining_size < PAGE_SIZE) { - /* Copy unfinished string to the start of the buffer */ - memmove(buf, p, remaining_size); - p = &buf[remaining_size]; - } else { - /* Print abnormal page-long string without newlines */ - dev_err(kbdev->dev, "FW> %s", buf); - p = buf; - } - } - - if (p != buf) { - /* Null-terminate and print last unfinished string */ - *p = 0; - dev_err(kbdev->dev, "FW> %s", buf); - } - - kfree(buf); -} - /** * kbase_csf_hwcnt_on_reset_error() - Sets HWCNT to appropriate state in the * event of an error during GPU reset. @@ -378,7 +316,6 @@ static enum kbasep_soft_reset_status kbase_csf_reset_gpu_once(struct kbase_devic "The flush has completed so reset the active indicator\n"); kbdev->irq_reset_flush = false; - mutex_lock(&kbdev->pm.lock); if (!silent) dev_err(kbdev->dev, "Resetting GPU (allowing up to %d ms)", RESET_TIMEOUT); @@ -389,7 +326,7 @@ static enum kbasep_soft_reset_status kbase_csf_reset_gpu_once(struct kbase_devic if (!silent) { kbase_csf_debug_dump_registers(kbdev); if (likely(firmware_inited)) - kbase_csf_dump_firmware_trace_buffer(kbdev); + kbase_csf_firmware_log_dump_buffer(kbdev); } spin_lock_irqsave(&kbdev->hwaccess_lock, flags); @@ -403,6 +340,7 @@ static enum kbasep_soft_reset_status kbase_csf_reset_gpu_once(struct kbase_devic */ kbase_hwcnt_backend_csf_on_before_reset(&kbdev->hwcnt_gpu_iface); + mutex_lock(&kbdev->pm.lock); /* Reset the GPU */ err = kbase_pm_init_hw(kbdev, 0); @@ -633,6 +571,11 @@ bool kbase_reset_gpu_is_active(struct kbase_device *kbdev) return kbase_csf_reset_state_is_active(reset_state); } +bool kbase_reset_gpu_is_not_pending(struct kbase_device *kbdev) +{ + return atomic_read(&kbdev->csf.reset.state) == KBASE_CSF_RESET_GPU_NOT_PENDING; +} + int kbase_reset_gpu_wait(struct kbase_device *kbdev) { const long wait_timeout = 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 af3b6912845d..b3cdef7dae52 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.c @@ -31,6 +31,7 @@ #include #include #include +#include "mali_kbase_csf_tiler_heap_reclaim.h" /* Value to indicate that a queue group is not groups_to_schedule list */ #define KBASEP_GROUP_PREPARED_SEQ_NUM_INVALID (U32_MAX) @@ -50,36 +51,12 @@ /* CSF scheduler time slice value */ #define CSF_SCHEDULER_TIME_TICK_MS (100) /* 100 milliseconds */ -/* - * CSF scheduler time threshold for converting "tock" requests into "tick" if - * they come too close to the end of a tick interval. This avoids scheduling - * twice in a row. - */ -#define CSF_SCHEDULER_TIME_TICK_THRESHOLD_MS \ - CSF_SCHEDULER_TIME_TICK_MS - -#define CSF_SCHEDULER_TIME_TICK_THRESHOLD_JIFFIES \ - msecs_to_jiffies(CSF_SCHEDULER_TIME_TICK_THRESHOLD_MS) - -/* Nanoseconds per millisecond */ -#define NS_PER_MS ((u64)1000 * 1000) - -/* - * CSF minimum time to reschedule for a new "tock" request. Bursts of "tock" - * requests are not serviced immediately, but shall wait for a minimum time in - * order to reduce load on the CSF scheduler thread. - */ -#define CSF_SCHEDULER_TIME_TOCK_JIFFIES 1 /* 1 jiffies-time */ - -/* CS suspended and is idle (empty ring buffer) */ -#define CS_IDLE_FLAG (1 << 0) - -/* CS suspended and is wait for a CQS condition */ -#define CS_WAIT_SYNC_FLAG (1 << 1) - /* A GPU address space slot is reserved for MCU. */ #define NUM_RESERVED_AS_SLOTS (1) +/* Time to wait for completion of PING req before considering MCU as hung */ +#define FW_PING_AFTER_ERROR_TIMEOUT_MS (10) + static int scheduler_group_schedule(struct kbase_queue_group *group); static void remove_group_from_idle_wait(struct kbase_queue_group *const group); static @@ -97,9 +74,105 @@ static int suspend_active_queue_groups(struct kbase_device *kbdev, static int suspend_active_groups_on_powerdown(struct kbase_device *kbdev, bool system_suspend); static void schedule_in_cycle(struct kbase_queue_group *group, bool force); +static bool queue_group_scheduled_locked(struct kbase_queue_group *group); #define kctx_as_enabled(kctx) (!kbase_ctx_flag(kctx, KCTX_AS_DISABLED_ON_FAULT)) +/** + * wait_for_dump_complete_on_group_deschedule() - Wait for dump on fault and + * scheduling tick/tock to complete before the group deschedule. + * + * @group: Pointer to the group that is being descheduled. + * + * This function blocks the descheduling of the group until the dump on fault is + * completed and scheduling tick/tock has completed. + * To deschedule an on slot group CSG termination request would be sent and that + * might time out if the fault had occurred and also potentially affect the state + * being dumped. Moreover the scheduler lock would be held, so the access to debugfs + * files would get blocked. + * Scheduler lock and 'kctx->csf.lock' are released before this function starts + * to wait. When a request sent by the Scheduler to the FW times out, Scheduler + * would also wait for the dumping to complete and release the Scheduler lock + * before the wait. Meanwhile Userspace can try to delete the group, this function + * would ensure that the group doesn't exit the Scheduler until scheduling + * tick/tock has completed. Though very unlikely, group deschedule can be triggered + * from multiple threads around the same time and after the wait Userspace thread + * can win the race and get the group descheduled and free the memory for group + * pointer before the other threads wake up and notice that group has already been + * descheduled. To avoid the freeing in such a case, a sort of refcount is used + * for the group which is incremented & decremented across the wait. + */ +static +void wait_for_dump_complete_on_group_deschedule(struct kbase_queue_group *group) +{ +#if IS_ENABLED(CONFIG_DEBUG_FS) + struct kbase_device *kbdev = group->kctx->kbdev; + struct kbase_context *kctx = group->kctx; + struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; + + lockdep_assert_held(&kctx->csf.lock); + lockdep_assert_held(&scheduler->lock); + + if (likely(!kbase_debug_csf_fault_dump_enabled(kbdev))) + return; + + while ((!kbase_debug_csf_fault_dump_complete(kbdev) || + (scheduler->state == SCHED_BUSY)) && + queue_group_scheduled_locked(group)) { + group->deschedule_deferred_cnt++; + mutex_unlock(&scheduler->lock); + mutex_unlock(&kctx->csf.lock); + kbase_debug_csf_fault_wait_completion(kbdev); + mutex_lock(&kctx->csf.lock); + mutex_lock(&scheduler->lock); + group->deschedule_deferred_cnt--; + } +#endif +} + +/** + * schedule_actions_trigger_df() - Notify the client about the fault and + * wait for the dumping to complete. + * + * @kbdev: Pointer to the device + * @kctx: Pointer to the context associated with the CSG slot for which + * the timeout was seen. + * @error: Error code indicating the type of timeout that occurred. + * + * This function notifies the Userspace client waiting for the faults and wait + * for the Client to complete the dumping. + * The function is called only from Scheduling tick/tock when a request sent by + * the Scheduler to FW times out or from the protm event work item of the group + * when the protected mode entry request times out. + * In the latter case there is no wait done as scheduler lock would be released + * immediately. In the former case the function waits and releases the scheduler + * lock before the wait. It has been ensured that the Scheduler view of the groups + * won't change meanwhile, so no group can enter/exit the Scheduler, become + * runnable or go off slot. + */ +static void schedule_actions_trigger_df(struct kbase_device *kbdev, + struct kbase_context *kctx, enum dumpfault_error_type error) +{ +#if IS_ENABLED(CONFIG_DEBUG_FS) + struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; + + lockdep_assert_held(&scheduler->lock); + + if (!kbase_debug_csf_fault_notify(kbdev, kctx, error)) + return; + + if (unlikely(scheduler->state != SCHED_BUSY)) { + WARN_ON(error != DF_PROTECTED_MODE_ENTRY_FAILURE); + return; + } + + mutex_unlock(&scheduler->lock); + kbase_debug_csf_fault_wait_completion(kbdev); + mutex_lock(&scheduler->lock); + WARN_ON(scheduler->state != SCHED_BUSY); +#endif +} + #ifdef KBASE_PM_RUNTIME /** * wait_for_scheduler_to_exit_sleep() - Wait for Scheduler to exit the @@ -207,6 +280,7 @@ static int force_scheduler_to_exit_sleep(struct kbase_device *kbdev) } scheduler->state = SCHED_SUSPENDED; + KBASE_KTRACE_ADD(kbdev, SCHED_SUSPENDED, NULL, scheduler->state); return 0; @@ -472,6 +546,7 @@ void kbase_csf_scheduler_process_gpu_idle_event(struct kbase_device *kbdev) int non_idle_offslot_grps; bool can_suspend_on_idle; + lockdep_assert_held(&kbdev->hwaccess_lock); lockdep_assert_held(&scheduler->interrupt_lock); non_idle_offslot_grps = atomic_read(&scheduler->non_idle_offslot_grps); @@ -481,12 +556,23 @@ void kbase_csf_scheduler_process_gpu_idle_event(struct kbase_device *kbdev) if (!non_idle_offslot_grps) { if (can_suspend_on_idle) { + /* fast_gpu_idle_handling is protected by the + * interrupt_lock, which would prevent this from being + * updated whilst gpu_idle_worker() is executing. + */ + scheduler->fast_gpu_idle_handling = + (kbdev->csf.gpu_idle_hysteresis_ms == 0) || + !kbase_csf_scheduler_all_csgs_idle(kbdev); + /* The GPU idle worker relies on update_on_slot_queues_offsets() to have * finished. It's queued before to reduce the time it takes till execution * but it'll eventually be blocked by the scheduler->interrupt_lock. */ enqueue_gpu_idle_work(scheduler); - update_on_slot_queues_offsets(kbdev); + + /* The extract offsets are unused in fast GPU idle handling */ + if (!scheduler->fast_gpu_idle_handling) + update_on_slot_queues_offsets(kbdev); } } else { /* Advance the scheduling tick to get the non-idle suspended groups loaded soon */ @@ -604,10 +690,14 @@ static bool scheduler_protm_wait_quit(struct kbase_device *kbdev) remaining = wait_event_timeout(kbdev->csf.event_wait, !kbase_csf_scheduler_protected_mode_in_use(kbdev), wt); - if (!remaining) { + if (unlikely(!remaining)) { + struct kbase_queue_group *group = kbdev->csf.scheduler.active_protm_grp; + struct kbase_context *kctx = group ? group->kctx : NULL; + dev_warn(kbdev->dev, "[%llu] Timeout (%d ms), protm_quit wait skipped", kbase_backend_get_cycle_cnt(kbdev), kbdev->csf.fw_timeout_ms); + schedule_actions_trigger_df(kbdev, kctx, DF_PROTECTED_MODE_EXIT_TIMEOUT); success = false; } @@ -728,7 +818,8 @@ static int scheduler_pm_active_handle_suspend(struct kbase_device *kbdev, * Scheduler * * @kbdev: Pointer to the device - * @flags: flags containing previous interrupt state + * @flags: Pointer to the flags variable containing the interrupt state + * when hwaccess lock was acquired. * * This function is called when Scheduler needs to be activated from the * sleeping state. @@ -736,14 +827,14 @@ static int scheduler_pm_active_handle_suspend(struct kbase_device *kbdev, * MCU is initiated. It resets the flag that indicates to the MCU state * machine that MCU needs to be put in sleep state. * - * Note: This function shall be called with hwaccess lock held and it will - * release that lock. + * Note: This function shall be called with hwaccess lock held and it may + * release that lock and reacquire it. * * Return: zero when the PM reference was taken and non-zero when the * system is being suspending/suspended. */ static int scheduler_pm_active_after_sleep(struct kbase_device *kbdev, - unsigned long flags) + unsigned long *flags) { u32 prev_count; int ret = 0; @@ -754,20 +845,20 @@ static int scheduler_pm_active_after_sleep(struct kbase_device *kbdev, prev_count = kbdev->csf.scheduler.pm_active_count; if (!WARN_ON(prev_count == U32_MAX)) kbdev->csf.scheduler.pm_active_count++; - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); /* On 0 => 1, make a pm_ctx_active request */ if (!prev_count) { + spin_unlock_irqrestore(&kbdev->hwaccess_lock, *flags); + ret = kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + spin_lock_irqsave(&kbdev->hwaccess_lock, *flags); if (ret) kbdev->csf.scheduler.pm_active_count--; else kbdev->pm.backend.gpu_sleep_mode_active = false; kbase_pm_update_state(kbdev); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); } return ret; @@ -871,8 +962,8 @@ static void scheduler_wakeup(struct kbase_device *kbdev, bool kick) "Re-activating the Scheduler out of sleep"); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - ret = scheduler_pm_active_after_sleep(kbdev, flags); - /* hwaccess_lock is released in the previous function call. */ + ret = scheduler_pm_active_after_sleep(kbdev, &flags); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); #endif } @@ -886,6 +977,7 @@ static void scheduler_wakeup(struct kbase_device *kbdev, bool kick) } scheduler->state = SCHED_INACTIVE; + KBASE_KTRACE_ADD(kbdev, SCHED_INACTIVE, NULL, scheduler->state); if (kick) scheduler_enable_tick_timer_nolock(kbdev); @@ -901,6 +993,7 @@ static void scheduler_suspend(struct kbase_device *kbdev) dev_dbg(kbdev->dev, "Suspending the Scheduler"); scheduler_pm_idle(kbdev); scheduler->state = SCHED_SUSPENDED; + KBASE_KTRACE_ADD(kbdev, SCHED_SUSPENDED, NULL, scheduler->state); } } @@ -931,6 +1024,8 @@ static void update_idle_suspended_group_state(struct kbase_queue_group *group) KBASE_CSF_GROUP_SUSPENDED); } else if (group->run_state == KBASE_CSF_GROUP_SUSPENDED_ON_IDLE) { group->run_state = KBASE_CSF_GROUP_SUSPENDED; + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, CSF_GROUP_SUSPENDED, group, + group->run_state); /* If scheduler is not suspended and the given group's * static priority (reflected by the scan_seq_num) is inside @@ -1055,6 +1150,7 @@ static int halt_stream_sync(struct kbase_queue *queue) struct kbase_csf_cmd_stream_info *stream; int csi_index = queue->csi_index; long remaining = kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms); + unsigned long flags; if (WARN_ON(!group) || WARN_ON(!kbasep_csf_scheduler_group_is_on_slot_locked(group))) @@ -1086,12 +1182,15 @@ static int halt_stream_sync(struct kbase_queue *queue) kbase_csf_timeout_in_jiffies(kbdev->csf.fw_timeout_ms); } + spin_lock_irqsave(&kbdev->csf.scheduler.interrupt_lock, flags); /* Set state to STOP */ 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_REQ, group, queue, 0u); kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, group->csg_nr, true); + spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock, flags); + + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_STOP_REQ, group, queue, 0u); /* Timed wait */ remaining = wait_event_timeout(kbdev->csf.event_wait, @@ -1362,6 +1461,7 @@ int kbase_csf_scheduler_queue_stop(struct kbase_queue *queue) } mutex_unlock(&kbdev->csf.scheduler.lock); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_STOP, group, queue, group->run_state); return err; } @@ -1439,6 +1539,7 @@ static void program_cs(struct kbase_device *kbdev, struct kbase_csf_cmd_stream_group_info *ginfo; struct kbase_csf_cmd_stream_info *stream; int csi_index = queue->csi_index; + unsigned long flags; u64 user_input; u64 user_output; @@ -1495,6 +1596,20 @@ static void program_cs(struct kbase_device *kbdev, /* Enable all interrupts for now */ kbase_csf_firmware_cs_input(stream, CS_ACK_IRQ_MASK, ~((u32)0)); + spin_lock_irqsave(&kbdev->csf.scheduler.interrupt_lock, flags); + + /* The fault bit could be misaligned between CS_REQ and CS_ACK if the + * acknowledgment was deferred due to dump on fault and the group was + * removed from the CSG slot before the fault could be acknowledged. + */ + if (queue->enabled) { + u32 const cs_ack = + kbase_csf_firmware_cs_output(stream, CS_ACK); + + kbase_csf_firmware_cs_input_mask(stream, CS_REQ, cs_ack, + CS_REQ_FAULT_MASK); + } + /* * Enable the CSG idle notification once the CS's ringbuffer * becomes empty or the CS becomes sync_idle, waiting sync update @@ -1508,11 +1623,12 @@ static void program_cs(struct kbase_device *kbdev, kbase_csf_firmware_cs_input_mask(stream, CS_REQ, queue->enabled ? CS_REQ_STATE_START : CS_REQ_STATE_STOP, CS_REQ_STATE_MASK); + kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, group->csg_nr, + ring_csg_doorbell); + spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock, flags); KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_START, group, queue, queue->enabled); - kbase_csf_ring_cs_kernel_doorbell(kbdev, csi_index, group->csg_nr, - ring_csg_doorbell); update_hw_active(queue, true); } @@ -1532,6 +1648,13 @@ int kbase_csf_scheduler_queue_start(struct kbase_queue *queue) mutex_lock(&kbdev->csf.scheduler.lock); +#if IS_ENABLED(CONFIG_DEBUG_FS) + if (unlikely(kbdev->csf.scheduler.state == SCHED_BUSY)) { + mutex_unlock(&kbdev->csf.scheduler.lock); + return -EBUSY; + } +#endif + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_START, group, queue, group->run_state); KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE_WAIT_STATUS, queue->group, queue, @@ -1716,6 +1839,7 @@ static void halt_csg_slot(struct kbase_queue_group *group, bool suspend) /* Set state to SUSPEND/TERMINATE */ kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, halt_cmd, CSG_REQ_STATE_MASK); + kbase_csf_ring_csg_doorbell(kbdev, slot); spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock, flags); atomic_set(&csg_slot[slot].state, CSG_SLOT_DOWN2STOP); @@ -1724,7 +1848,6 @@ static void halt_csg_slot(struct kbase_queue_group *group, bool suspend) KBASE_TLSTREAM_TL_KBASE_DEVICE_HALT_CSG( kbdev, kbdev->gpu_props.props.raw_props.gpu_id, slot); - kbase_csf_ring_csg_doorbell(kbdev, slot); } } @@ -1738,6 +1861,31 @@ static void suspend_csg_slot(struct kbase_queue_group *group) halt_csg_slot(group, true); } +static bool csf_wait_ge_condition_supported(struct kbase_device *kbdev) +{ + const uint32_t glb_major = GLB_VERSION_MAJOR_GET(kbdev->csf.global_iface.version); + const uint32_t glb_minor = GLB_VERSION_MINOR_GET(kbdev->csf.global_iface.version); + + switch (glb_major) { + case 0: + break; + case 1: + if (glb_minor >= 4) + return true; + break; + case 2: + if (glb_minor >= 6) + return true; + break; + case 3: + if (glb_minor >= 6) + return true; + break; + default: + return true; + } + return false; +} /** * evaluate_sync_update() - Evaluate the sync wait condition the GPU command * queue has been blocked on. @@ -1754,11 +1902,13 @@ static bool evaluate_sync_update(struct kbase_queue *queue) u32 sync_wait_cond; u32 sync_current_val; struct kbase_device *kbdev; + bool sync_wait_cond_valid = false; if (WARN_ON(!queue)) return false; kbdev = queue->kctx->kbdev; + lockdep_assert_held(&kbdev->csf.scheduler.lock); sync_ptr = kbase_phy_alloc_mapping_get(queue->kctx, queue->sync_ptr, @@ -1777,9 +1927,12 @@ static bool evaluate_sync_update(struct kbase_queue *queue) sync_wait_cond = CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GET(queue->status_wait); + sync_wait_cond_valid = (sync_wait_cond == CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GT) || + (sync_wait_cond == CS_STATUS_WAIT_SYNC_WAIT_CONDITION_LE) || + ((sync_wait_cond == CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GE) && + csf_wait_ge_condition_supported(kbdev)); - WARN_ON((sync_wait_cond != CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GT) && - (sync_wait_cond != CS_STATUS_WAIT_SYNC_WAIT_CONDITION_LE)); + WARN_ON(!sync_wait_cond_valid); sync_current_val = READ_ONCE(*sync_ptr); KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, QUEUE_SYNC_UPDATE_CUR_VAL, queue->group, queue, @@ -1790,6 +1943,8 @@ static bool evaluate_sync_update(struct kbase_queue *queue) if (((sync_wait_cond == CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GT) && (sync_current_val > queue->sync_value)) || + ((sync_wait_cond == CS_STATUS_WAIT_SYNC_WAIT_CONDITION_GE) && + (sync_current_val >= queue->sync_value) && csf_wait_ge_condition_supported(kbdev)) || ((sync_wait_cond == CS_STATUS_WAIT_SYNC_WAIT_CONDITION_LE) && (sync_current_val <= queue->sync_value))) { /* The sync wait condition is satisfied so the group to which @@ -1892,12 +2047,48 @@ static void schedule_in_cycle(struct kbase_queue_group *group, bool force) * of work needs to be enforced in situation such as entering into * protected mode). */ - if ((likely(scheduler_timer_is_enabled_nolock(kbdev)) || force) && - !scheduler->tock_pending_request) { - scheduler->tock_pending_request = true; + if (likely(scheduler_timer_is_enabled_nolock(kbdev)) || force) { dev_dbg(kbdev->dev, "Kicking async for group %d\n", group->handle); - mod_delayed_work(scheduler->wq, &scheduler->tock_work, 0); + kbase_csf_scheduler_invoke_tock(kbdev); + } +} + +static void ktrace_log_group_state(struct kbase_queue_group *const group) +{ + switch (group->run_state) { + case KBASE_CSF_GROUP_INACTIVE: + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, CSF_GROUP_INACTIVE, group, + group->run_state); + break; + case KBASE_CSF_GROUP_RUNNABLE: + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, CSF_GROUP_RUNNABLE, group, + group->run_state); + break; + case KBASE_CSF_GROUP_IDLE: + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, CSF_GROUP_IDLE, group, + group->run_state); + break; + case KBASE_CSF_GROUP_SUSPENDED: + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, CSF_GROUP_SUSPENDED, group, + group->run_state); + break; + case KBASE_CSF_GROUP_SUSPENDED_ON_IDLE: + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, CSF_GROUP_SUSPENDED_ON_IDLE, group, + group->run_state); + break; + case KBASE_CSF_GROUP_SUSPENDED_ON_WAIT_SYNC: + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, CSF_GROUP_SUSPENDED_ON_WAIT_SYNC, + group, group->run_state); + break; + case KBASE_CSF_GROUP_FAULT_EVICTED: + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, CSF_GROUP_FAULT_EVICTED, group, + group->run_state); + break; + case KBASE_CSF_GROUP_TERMINATED: + KBASE_KTRACE_ADD_CSF_GRP(group->kctx->kbdev, CSF_GROUP_TERMINATED, group, + group->run_state); + break; } } @@ -1918,6 +2109,8 @@ void insert_group_to_runnable(struct kbase_csf_scheduler *const scheduler, group->run_state = run_state; + ktrace_log_group_state(group); + if (run_state == KBASE_CSF_GROUP_RUNNABLE) group->prepared_seq_num = KBASEP_GROUP_PREPARED_SEQ_NUM_INVALID; @@ -1969,6 +2162,9 @@ void remove_group_from_runnable(struct kbase_csf_scheduler *const scheduler, WARN_ON(!queue_group_scheduled_locked(group)); group->run_state = run_state; + + ktrace_log_group_state(group); + list_del_init(&group->link); spin_lock_irqsave(&scheduler->interrupt_lock, flags); @@ -2067,6 +2263,8 @@ static void insert_group_to_idle_wait(struct kbase_queue_group *const 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; + KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, CSF_GROUP_SUSPENDED_ON_WAIT_SYNC, group, + group->run_state); dev_dbg(kctx->kbdev->dev, "Group-%d suspended on sync_wait, total wait_groups: %u\n", group->handle, kctx->csf.sched.num_idle_wait_grps); @@ -2092,6 +2290,7 @@ static void remove_group_from_idle_wait(struct kbase_queue_group *const group) NULL; KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, GROUP_IDLE_WAIT_HEAD, new_head_grp, 0u); group->run_state = KBASE_CSF_GROUP_INACTIVE; + KBASE_KTRACE_ADD_CSF_GRP(kctx->kbdev, CSF_GROUP_INACTIVE, group, group->run_state); } static void deschedule_idle_wait_group(struct kbase_csf_scheduler *scheduler, @@ -2270,14 +2469,19 @@ static void save_csg_slot(struct kbase_queue_group *group) else { group->run_state = KBASE_CSF_GROUP_SUSPENDED_ON_IDLE; + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSF_GROUP_SUSPENDED_ON_IDLE, group, + group->run_state); dev_dbg(kbdev->dev, "Group-%d suspended: idle", group->handle); } } else { group->run_state = KBASE_CSF_GROUP_SUSPENDED; + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSF_GROUP_SUSPENDED, group, + group->run_state); } update_offslot_non_idle_cnt_on_grp_suspend(group); + kbase_csf_tiler_heap_reclaim_sched_notify_grp_suspend(group); } } @@ -2400,6 +2604,7 @@ static void update_csg_slot_priority(struct kbase_queue_group *group, u8 prio) csg_req ^= CSG_REQ_EP_CFG_MASK; kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, csg_req, CSG_REQ_EP_CFG_MASK); + kbase_csf_ring_csg_doorbell(kbdev, slot); spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock, flags); csg_slot->priority = prio; @@ -2410,7 +2615,6 @@ static void update_csg_slot_priority(struct kbase_queue_group *group, u8 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); } @@ -2522,6 +2726,12 @@ static void program_csg_slot(struct kbase_queue_group *group, s8 slot, protm_suspend_buf >> 32); } + if (group->dvs_buf) { + kbase_csf_firmware_csg_input(ginfo, CSG_DVS_BUF_LO, + group->dvs_buf & U32_MAX); + kbase_csf_firmware_csg_input(ginfo, CSG_DVS_BUF_HI, + group->dvs_buf >> 32); + } /* Enable all interrupts for now */ kbase_csf_firmware_csg_input(ginfo, CSG_ACK_IRQ_MASK, ~((u32)0)); @@ -2542,6 +2752,7 @@ static void program_csg_slot(struct kbase_queue_group *group, s8 slot, kbase_csf_firmware_csg_input_mask(ginfo, CSG_REQ, state, CSG_REQ_STATE_MASK); + kbase_csf_ring_csg_doorbell(kbdev, slot); spin_unlock_irqrestore(&kbdev->csf.scheduler.interrupt_lock, flags); /* Update status before rings the door-bell, marking ready => run */ @@ -2561,7 +2772,8 @@ static void program_csg_slot(struct kbase_queue_group *group, s8 slot, (((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); + /* Update the heap reclaim manager */ + kbase_csf_tiler_heap_reclaim_sched_notify_grp_active(group); /* Programming a slot consumes a group from scanout */ update_offslot_non_idle_cnt_for_onslot_grp(group); @@ -2623,8 +2835,11 @@ static void sched_evict_group(struct kbase_queue_group *group, bool fault, WARN_ON(group->run_state != KBASE_CSF_GROUP_INACTIVE); - if (fault) + if (fault) { group->run_state = KBASE_CSF_GROUP_FAULT_EVICTED; + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSF_GROUP_FAULT_EVICTED, group, + scheduler->total_runnable_grps); + } KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_EVICT, group, (((u64)scheduler->total_runnable_grps) << 32) | @@ -2634,6 +2849,8 @@ static void sched_evict_group(struct kbase_queue_group *group, bool fault, /* Notify a group has been evicted */ wake_up_all(&kbdev->csf.event_wait); } + + kbase_csf_tiler_heap_reclaim_sched_notify_grp_evict(group); } static int term_group_sync(struct kbase_queue_group *group) @@ -2648,11 +2865,16 @@ static int term_group_sync(struct kbase_queue_group *group) group->cs_unrecoverable || csg_slot_stopped_locked(kbdev, group->csg_nr), remaining); - if (!remaining) { + if (unlikely(!remaining)) { + enum dumpfault_error_type error_type = DF_CSG_TERMINATE_TIMEOUT; + dev_warn(kbdev->dev, "[%llu] term request timeout (%d ms) for group %d of context %d_%d on slot %d", kbase_backend_get_cycle_cnt(kbdev), kbdev->csf.fw_timeout_ms, group->handle, group->kctx->tgid, group->kctx->id, group->csg_nr); + if (kbase_csf_firmware_ping_wait(kbdev, FW_PING_AFTER_ERROR_TIMEOUT_MS)) + error_type = DF_PING_REQUEST_TIMEOUT; + kbase_debug_csf_fault_notify(kbdev, group->kctx, error_type); if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE)) kbase_reset_gpu(kbdev); @@ -2667,6 +2889,7 @@ void kbase_csf_scheduler_group_deschedule(struct kbase_queue_group *group) { struct kbase_device *kbdev = group->kctx->kbdev; struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; + bool wait_for_termination = true; bool on_slot; kbase_reset_gpu_assert_failed_or_prevented(kbdev); @@ -2674,6 +2897,7 @@ void kbase_csf_scheduler_group_deschedule(struct kbase_queue_group *group) mutex_lock(&scheduler->lock); KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_DESCHEDULE, group, group->run_state); + wait_for_dump_complete_on_group_deschedule(group); if (!queue_group_scheduled_locked(group)) goto unlock; @@ -2681,39 +2905,28 @@ void kbase_csf_scheduler_group_deschedule(struct kbase_queue_group *group) #ifdef KBASE_PM_RUNTIME /* If the queue group is on slot and Scheduler is in SLEEPING state, - * then we need to wait here for Scheduler to exit the sleep state - * (i.e. wait for the runtime suspend or power down of GPU). This would - * be better than aborting the power down. The group will be suspended - * anyways on power down, so won't have to send the CSG termination - * request to FW. + * then we need to wake up the Scheduler to exit the sleep state rather + * than waiting for the runtime suspend or power down of GPU. + * The group termination is usually triggered in the context of Application + * thread and it has been seen that certain Apps can destroy groups at + * random points and not necessarily when the App is exiting. */ if (on_slot && (scheduler->state == SCHED_SLEEPING)) { - if (wait_for_scheduler_to_exit_sleep(kbdev)) { + scheduler_wakeup(kbdev, true); + + /* Wait for MCU firmware to start running */ + if (kbase_csf_scheduler_wait_mcu_active(kbdev)) { dev_warn( kbdev->dev, - "Wait for scheduler to exit sleep state timedout when terminating group %d of context %d_%d on slot %d", + "[%llu] Wait for MCU active failed when terminating group %d of context %d_%d on slot %d", + kbase_backend_get_cycle_cnt(kbdev), group->handle, group->kctx->tgid, group->kctx->id, group->csg_nr); - - scheduler_wakeup(kbdev, true); - - /* Wait for MCU firmware to start running */ - if (kbase_csf_scheduler_wait_mcu_active(kbdev)) - dev_warn( - kbdev->dev, - "[%llu] Wait for MCU active failed when terminating group %d of context %d_%d on slot %d", - kbase_backend_get_cycle_cnt(kbdev), - group->handle, group->kctx->tgid, - group->kctx->id, group->csg_nr); + /* No point in waiting for CSG termination if MCU didn't + * become active. + */ + wait_for_termination = false; } - - /* Check the group state again as scheduler lock would have been - * released when waiting for the exit from SLEEPING state. - */ - if (!queue_group_scheduled_locked(group)) - goto unlock; - - on_slot = kbasep_csf_scheduler_group_is_on_slot_locked(group); } #endif if (!on_slot) { @@ -2721,7 +2934,11 @@ void kbase_csf_scheduler_group_deschedule(struct kbase_queue_group *group) } else { bool as_faulty; - term_group_sync(group); + if (likely(wait_for_termination)) + term_group_sync(group); + else + term_csg_slot(group); + /* Treat the csg been terminated */ as_faulty = cleanup_csg_slot(group); /* remove from the scheduler list */ @@ -2770,6 +2987,8 @@ static int scheduler_group_schedule(struct kbase_queue_group *group) group)); group->run_state = KBASE_CSF_GROUP_RUNNABLE; + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSF_GROUP_RUNNABLE, group, + group->run_state); /* A normal mode CSG could be idle onslot during * protected mode. In this case clear the @@ -3124,7 +3343,7 @@ static void program_suspending_csg_slots(struct kbase_device *kbdev) csg_slot_stopped_raw), remaining); - if (remaining) { + if (likely(remaining)) { u32 i; for_each_set_bit(i, changed, num_groups) { @@ -3164,6 +3383,7 @@ static void program_suspending_csg_slots(struct kbase_device *kbdev) for_each_set_bit(i, slot_mask, num_groups) { struct kbase_queue_group *const group = scheduler->csg_slots[i].resident_group; + enum dumpfault_error_type error_type = DF_CSG_SUSPEND_TIMEOUT; struct base_gpu_queue_group_error const err_payload = { .error_type = @@ -3177,10 +3397,6 @@ static void program_suspending_csg_slots(struct kbase_device *kbdev) if (unlikely(group == NULL)) continue; - kbase_csf_add_group_fatal_error(group, - &err_payload); - kbase_event_wakeup(group->kctx); - /* TODO GPUCORE-25328: The CSG can't be * terminated, the GPU will be reset as a * work-around. @@ -3192,6 +3408,13 @@ static void program_suspending_csg_slots(struct kbase_device *kbdev) group->handle, group->kctx->tgid, group->kctx->id, i, kbdev->csf.fw_timeout_ms); + if (kbase_csf_firmware_ping_wait(kbdev, + FW_PING_AFTER_ERROR_TIMEOUT_MS)) + error_type = DF_PING_REQUEST_TIMEOUT; + schedule_actions_trigger_df(kbdev, group->kctx, error_type); + + kbase_csf_add_group_fatal_error(group, &err_payload); + kbase_event_wakeup(group->kctx); /* The group has failed suspension, stop * further examination. @@ -3279,7 +3502,7 @@ static void wait_csg_slots_start(struct kbase_device *kbdev) slots_state_changed(kbdev, changed, csg_slot_running), remaining); - if (remaining) { + if (likely(remaining)) { for_each_set_bit(i, changed, num_groups) { struct kbase_queue_group *group = scheduler->csg_slots[i].resident_group; @@ -3287,12 +3510,22 @@ static void wait_csg_slots_start(struct kbase_device *kbdev) /* The on slot csg is now running */ clear_bit(i, slot_mask); group->run_state = KBASE_CSF_GROUP_RUNNABLE; + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSF_GROUP_RUNNABLE, group, + group->run_state); } } else { - dev_warn(kbdev->dev, "[%llu] Timeout (%d ms) waiting for CSG slots to start, slots: 0x%*pb\n", - kbase_backend_get_cycle_cnt(kbdev), - kbdev->csf.fw_timeout_ms, - num_groups, slot_mask); + const int csg_nr = ffs(slot_mask[0]) - 1; + struct kbase_queue_group *group = + scheduler->csg_slots[csg_nr].resident_group; + enum dumpfault_error_type error_type = DF_CSG_START_TIMEOUT; + + dev_err(kbdev->dev, + "[%llu] Timeout (%d ms) waiting for CSG slots to start, slots: 0x%*pb\n", + kbase_backend_get_cycle_cnt(kbdev), kbdev->csf.fw_timeout_ms, + num_groups, slot_mask); + if (kbase_csf_firmware_ping_wait(kbdev, FW_PING_AFTER_ERROR_TIMEOUT_MS)) + error_type = DF_PING_REQUEST_TIMEOUT; + schedule_actions_trigger_df(kbdev, group->kctx, error_type); if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE)) kbase_reset_gpu(kbdev); @@ -3409,11 +3642,10 @@ static int wait_csg_slots_handshake_ack(struct kbase_device *kbdev, slot_mask, dones), remaining); - if (remaining) + if (likely(remaining)) bitmap_andnot(slot_mask, slot_mask, dones, num_groups); else { - /* Timed-out on the wait */ return -ETIMEDOUT; } @@ -3432,17 +3664,25 @@ static void wait_csg_slots_finish_prio_update(struct kbase_device *kbdev) lockdep_assert_held(&kbdev->csf.scheduler.lock); - if (ret != 0) { - /* The update timeout is not regarded as a serious - * issue, no major consequences are expected as a - * result, so just warn the case. - */ + if (unlikely(ret != 0)) { + const int csg_nr = ffs(slot_mask[0]) - 1; + struct kbase_queue_group *group = + kbdev->csf.scheduler.csg_slots[csg_nr].resident_group; + enum dumpfault_error_type error_type = DF_CSG_EP_CFG_TIMEOUT; + dev_warn( kbdev->dev, "[%llu] Timeout (%d ms) on CSG_REQ:EP_CFG, skipping the update wait: slot mask=0x%lx", kbase_backend_get_cycle_cnt(kbdev), kbdev->csf.fw_timeout_ms, slot_mask[0]); + if (kbase_csf_firmware_ping_wait(kbdev, FW_PING_AFTER_ERROR_TIMEOUT_MS)) + error_type = DF_PING_REQUEST_TIMEOUT; + schedule_actions_trigger_df(kbdev, group->kctx, error_type); + + /* Timeout could indicate firmware is unresponsive so trigger a GPU reset. */ + if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) + kbase_reset_gpu(kbdev); } } @@ -3508,6 +3748,7 @@ void kbase_csf_scheduler_evict_ctx_slots(struct kbase_device *kbdev, kbase_event_wakeup(kctx); mutex_unlock(&scheduler->lock); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_EVICT_CTX_SLOTS_END, kctx, num_groups); } /** @@ -3690,6 +3931,8 @@ static void scheduler_group_check_protm_enter(struct kbase_device *const kbdev, CSG_SLOT_RUNNING) { if (kctx_as_enabled(input_grp->kctx) && scheduler_slot_protm_ack(kbdev, input_grp, slot)) { + int err; + /* Option of acknowledging to multiple * CSGs from the same kctx is dropped, * after consulting with the @@ -3708,9 +3951,13 @@ static void scheduler_group_check_protm_enter(struct kbase_device *const kbdev, spin_unlock_irqrestore(&scheduler->interrupt_lock, flags); - kbase_csf_wait_protected_mode_enter(kbdev); + err = kbase_csf_wait_protected_mode_enter(kbdev); mutex_unlock(&kbdev->mmu_hw_mutex); + if (err) + schedule_actions_trigger_df(kbdev, input_grp->kctx, + DF_PROTECTED_MODE_ENTRY_FAILURE); + scheduler->protm_enter_time = ktime_get_raw(); return; @@ -4093,8 +4340,6 @@ static void scheduler_update_idle_slots_status(struct kbase_device *kbdev, } } - spin_unlock_irqrestore(&scheduler->interrupt_lock, flags); - /* The groups are aggregated into a single kernel doorbell request */ if (!bitmap_empty(csg_bitmap, num_groups)) { @@ -4103,15 +4348,22 @@ static void scheduler_update_idle_slots_status(struct kbase_device *kbdev, u32 db_slots = (u32)csg_bitmap[0]; kbase_csf_ring_csg_slots_doorbell(kbdev, db_slots); + spin_unlock_irqrestore(&scheduler->interrupt_lock, flags); if (wait_csg_slots_handshake_ack(kbdev, CSG_REQ_STATUS_UPDATE_MASK, csg_bitmap, wt)) { + const int csg_nr = ffs(csg_bitmap[0]) - 1; + struct kbase_queue_group *group = + scheduler->csg_slots[csg_nr].resident_group; + dev_warn( kbdev->dev, "[%llu] Timeout (%d ms) on CSG_REQ:STATUS_UPDATE, treat groups as not idle: slot mask=0x%lx", kbase_backend_get_cycle_cnt(kbdev), kbdev->csf.fw_timeout_ms, csg_bitmap[0]); + schedule_actions_trigger_df(kbdev, group->kctx, + DF_CSG_STATUS_UPDATE_TIMEOUT); /* Store the bitmap of timed out slots */ bitmap_copy(failed_csg_bitmap, csg_bitmap, num_groups); @@ -4131,6 +4383,8 @@ static void scheduler_update_idle_slots_status(struct kbase_device *kbdev, KBASE_KTRACE_ADD(kbdev, SCHEDULER_UPDATE_IDLE_SLOTS_ACK, NULL, db_slots); csg_bitmap[0] = db_slots; } + } else { + spin_unlock_irqrestore(&scheduler->interrupt_lock, flags); } } @@ -4185,17 +4439,21 @@ static void scheduler_handle_idle_slots(struct kbase_device *kbdev) if (group_on_slot_is_idle(kbdev, i)) { group->run_state = KBASE_CSF_GROUP_IDLE; + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSF_GROUP_IDLE, group, group->run_state); set_bit(i, scheduler->csg_slots_idle_mask); KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_SET, group, scheduler->csg_slots_idle_mask[0]); - } else + } else { group->run_state = KBASE_CSF_GROUP_RUNNABLE; + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSF_GROUP_RUNNABLE, group, + group->run_state); + } } bitmap_or(scheduler->csg_slots_idle_mask, scheduler->csg_slots_idle_mask, failed_csg_bitmap, num_groups); - KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSG_SLOT_IDLE_SET, NULL, + KBASE_KTRACE_ADD_CSF_GRP(kbdev, SCHEDULER_HANDLE_IDLE_SLOTS, NULL, scheduler->csg_slots_idle_mask[0]); spin_unlock_irqrestore(&scheduler->interrupt_lock, flags); } @@ -4281,7 +4539,12 @@ static int suspend_active_groups_on_powerdown(struct kbase_device *kbdev, int ret = suspend_active_queue_groups(kbdev, slot_mask); - if (ret) { + if (unlikely(ret)) { + const int csg_nr = ffs(slot_mask[0]) - 1; + struct kbase_queue_group *group = + scheduler->csg_slots[csg_nr].resident_group; + enum dumpfault_error_type error_type = DF_CSG_SUSPEND_TIMEOUT; + /* The suspend of CSGs failed, * trigger the GPU reset to be in a deterministic state. */ @@ -4289,6 +4552,9 @@ static int suspend_active_groups_on_powerdown(struct kbase_device *kbdev, kbase_backend_get_cycle_cnt(kbdev), kbdev->csf.fw_timeout_ms, kbdev->csf.global_iface.group_num, slot_mask); + if (kbase_csf_firmware_ping_wait(kbdev, FW_PING_AFTER_ERROR_TIMEOUT_MS)) + error_type = DF_PING_REQUEST_TIMEOUT; + schedule_actions_trigger_df(kbdev, group->kctx, error_type); if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE)) kbase_reset_gpu(kbdev); @@ -4372,6 +4638,21 @@ static bool scheduler_idle_suspendable(struct kbase_device *kbdev) spin_lock_irqsave(&kbdev->hwaccess_lock, flags); spin_lock(&scheduler->interrupt_lock); + + if (scheduler->fast_gpu_idle_handling) { + scheduler->fast_gpu_idle_handling = false; + + if (scheduler->total_runnable_grps) { + suspend = !atomic_read(&scheduler->non_idle_offslot_grps) && + kbase_pm_idle_groups_sched_suspendable(kbdev); + } else + suspend = kbase_pm_no_runnables_sched_suspendable(kbdev); + spin_unlock(&scheduler->interrupt_lock); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return suspend; + } + if (scheduler->total_runnable_grps) { /* Check both on-slots and off-slots groups idle status */ @@ -4418,6 +4699,7 @@ static void scheduler_sleep_on_idle(struct kbase_device *kbdev) cancel_tick_timer(kbdev); scheduler_pm_idle_before_sleep(kbdev); scheduler->state = SCHED_SLEEPING; + KBASE_KTRACE_ADD(kbdev, SCHED_SLEEPING, NULL, scheduler->state); } #endif @@ -4471,8 +4753,17 @@ static void gpu_idle_worker(struct work_struct *work) __ENCODE_KTRACE_INFO(true, false, false)); return; } + kbase_debug_csf_fault_wait_completion(kbdev); mutex_lock(&scheduler->lock); +#if IS_ENABLED(CONFIG_DEBUG_FS) + if (unlikely(scheduler->state == SCHED_BUSY)) { + mutex_unlock(&scheduler->lock); + kbase_reset_gpu_allow(kbdev); + return; + } +#endif + scheduler_is_idle_suspendable = scheduler_idle_suspendable(kbdev); if (scheduler_is_idle_suspendable) { KBASE_KTRACE_ADD(kbdev, SCHEDULER_GPU_IDLE_WORKER_HANDLING_START, NULL, @@ -4484,6 +4775,8 @@ static void gpu_idle_worker(struct work_struct *work) else #endif all_groups_suspended = scheduler_suspend_on_idle(kbdev); + + KBASE_KTRACE_ADD(kbdev, SCHEDULER_GPU_IDLE_WORKER_HANDLING_END, NULL, 0u); } mutex_unlock(&scheduler->lock); @@ -4641,14 +4934,162 @@ static int prepare_fast_local_tock(struct kbase_device *kbdev) struct kbase_csf_csg_slot *csg_slot = &scheduler->csg_slots[i]; struct kbase_queue_group *group = csg_slot->resident_group; - if (!queue_group_idle_locked(group)) + if (!queue_group_idle_locked(group)) { group->run_state = KBASE_CSF_GROUP_IDLE; + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSF_GROUP_IDLE, group, group->run_state); + } } /* Return the number of idle slots for potential replacement */ return bitmap_weight(csg_bitmap, num_groups); } +static int wait_csg_slots_suspend(struct kbase_device *kbdev, unsigned long *slot_mask, + unsigned int timeout_ms) +{ + struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; + long remaining = kbase_csf_timeout_in_jiffies(timeout_ms); + u32 num_groups = kbdev->csf.global_iface.group_num; + int err = 0; + DECLARE_BITMAP(slot_mask_local, MAX_SUPPORTED_CSGS); + + lockdep_assert_held(&scheduler->lock); + + bitmap_copy(slot_mask_local, slot_mask, MAX_SUPPORTED_CSGS); + + while (!bitmap_empty(slot_mask_local, MAX_SUPPORTED_CSGS) && remaining) { + DECLARE_BITMAP(changed, MAX_SUPPORTED_CSGS); + + bitmap_copy(changed, slot_mask_local, MAX_SUPPORTED_CSGS); + + remaining = wait_event_timeout( + kbdev->csf.event_wait, + slots_state_changed(kbdev, changed, csg_slot_stopped_locked), remaining); + + if (likely(remaining)) { + u32 i; + + for_each_set_bit(i, changed, num_groups) { + struct kbase_queue_group *group; + + if (WARN_ON(!csg_slot_stopped_locked(kbdev, (s8)i))) + continue; + + /* The on slot csg is now stopped */ + clear_bit(i, slot_mask_local); + + group = scheduler->csg_slots[i].resident_group; + if (likely(group)) { + /* Only do save/cleanup if the + * group is not terminated during + * the sleep. + */ + save_csg_slot(group); + if (cleanup_csg_slot(group)) + sched_evict_group(group, true, true); + } + } + } else { + dev_warn( + kbdev->dev, + "[%llu] Suspend request sent on CSG slots 0x%lx timed out for slots 0x%lx", + kbase_backend_get_cycle_cnt(kbdev), slot_mask[0], + slot_mask_local[0]); + /* Return the bitmask of the timed out slots to the caller */ + bitmap_copy(slot_mask, slot_mask_local, MAX_SUPPORTED_CSGS); + + err = -ETIMEDOUT; + } + } + + return err; +} + +/** + * evict_lru_or_blocked_csg() - Evict the least-recently-used idle or blocked CSG + * + * @kbdev: Pointer to the device + * + * Used to allow for speedier starting/resumption of another CSG. The worst-case + * scenario of the evicted CSG being scheduled next is expected to be rare. + * Also, the eviction will not be applied if the GPU is running in protected mode. + * Otherwise the the eviction attempt would force the MCU to quit the execution of + * the protected mode, and likely re-request to enter it again. + */ +static void evict_lru_or_blocked_csg(struct kbase_device *kbdev) +{ + struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; + size_t i; + struct kbase_queue_group *lru_idle_group = NULL; + const u32 total_csg_slots = kbdev->csf.global_iface.group_num; + const bool all_addr_spaces_used = (scheduler->num_active_address_spaces >= + (kbdev->nr_hw_address_spaces - NUM_RESERVED_AS_SLOTS)); + u8 as_usage[BASE_MAX_NR_AS] = { 0 }; + + lockdep_assert_held(&scheduler->lock); + if (kbase_csf_scheduler_protected_mode_in_use(kbdev)) + return; + + BUILD_BUG_ON(MAX_SUPPORTED_CSGS > (sizeof(int) * BITS_PER_BYTE)); + if (fls(scheduler->csg_inuse_bitmap[0]) != total_csg_slots) + return; /* Some CSG slots remain unused */ + + if (all_addr_spaces_used) { + for (i = 0; i != total_csg_slots; ++i) { + if (scheduler->csg_slots[i].resident_group != NULL) + as_usage[scheduler->csg_slots[i].resident_group->kctx->as_nr]++; + } + } + + for (i = 0; i != total_csg_slots; ++i) { + struct kbase_queue_group *const group = scheduler->csg_slots[i].resident_group; + + /* We expect that by this point all groups would normally be + * assigned a physical CSG slot, but if circumstances have + * changed then bail out of this optimisation. + */ + if (group == NULL) + return; + + /* Real-time priority CSGs must be kept on-slot even when + * idle. + */ + if ((group->run_state == KBASE_CSF_GROUP_IDLE) && + (group->priority != BASE_QUEUE_GROUP_PRIORITY_REALTIME) && + ((lru_idle_group == NULL) || + (lru_idle_group->prepared_seq_num < group->prepared_seq_num))) { + /* If all address spaces are used, we need to ensure the group does not + * share the AS with other active CSGs. Or CSG would be freed without AS + * and this optimization would not work. + */ + if ((!all_addr_spaces_used) || (as_usage[group->kctx->as_nr] == 1)) + lru_idle_group = group; + } + } + + if (lru_idle_group != NULL) { + unsigned long slot_mask = 1 << lru_idle_group->csg_nr; + + dev_dbg(kbdev->dev, "Suspending LRU idle group %d of context %d_%d on slot %d", + lru_idle_group->handle, lru_idle_group->kctx->tgid, + lru_idle_group->kctx->id, lru_idle_group->csg_nr); + suspend_queue_group(lru_idle_group); + if (wait_csg_slots_suspend(kbdev, &slot_mask, kbdev->csf.fw_timeout_ms)) { + enum dumpfault_error_type error_type = DF_CSG_SUSPEND_TIMEOUT; + + dev_warn( + kbdev->dev, + "[%llu] LRU idle group %d of context %d_%d failed to suspend on slot %d (timeout %d ms)", + kbase_backend_get_cycle_cnt(kbdev), lru_idle_group->handle, + lru_idle_group->kctx->tgid, lru_idle_group->kctx->id, + lru_idle_group->csg_nr, kbdev->csf.fw_timeout_ms); + if (kbase_csf_firmware_ping_wait(kbdev, FW_PING_AFTER_ERROR_TIMEOUT_MS)) + error_type = DF_PING_REQUEST_TIMEOUT; + schedule_actions_trigger_df(kbdev, lru_idle_group->kctx, error_type); + } + } +} + static void schedule_actions(struct kbase_device *kbdev, bool is_tick) { struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; @@ -4796,6 +5237,8 @@ redo_local_tock: } else { spin_unlock_irqrestore(&scheduler->interrupt_lock, flags); } + + evict_lru_or_blocked_csg(kbdev); } /** @@ -4817,6 +5260,9 @@ static bool can_skip_scheduling(struct kbase_device *kbdev) lockdep_assert_held(&scheduler->lock); + if (unlikely(!kbase_reset_gpu_is_not_pending(kbdev))) + return true; + if (scheduler->state == SCHED_SUSPENDED) return true; @@ -4826,12 +5272,12 @@ static bool can_skip_scheduling(struct kbase_device *kbdev) spin_lock_irqsave(&kbdev->hwaccess_lock, flags); if (kbdev->pm.backend.exit_gpu_sleep_mode) { - int ret = scheduler_pm_active_after_sleep(kbdev, flags); - /* hwaccess_lock is released in the previous function - * call. - */ + int ret = scheduler_pm_active_after_sleep(kbdev, &flags); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); if (!ret) { scheduler->state = SCHED_INACTIVE; + KBASE_KTRACE_ADD(kbdev, SCHED_INACTIVE, NULL, scheduler->state); return false; } @@ -4849,14 +5295,11 @@ static bool can_skip_scheduling(struct kbase_device *kbdev) static void schedule_on_tock(struct work_struct *work) { - struct kbase_device *kbdev = container_of(work, struct kbase_device, - csf.scheduler.tock_work.work); + struct kbase_device *kbdev = + container_of(work, struct kbase_device, csf.scheduler.tock_work.work); struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; int err; - /* Tock work item is serviced */ - scheduler->tock_pending_request = false; - err = kbase_reset_gpu_try_prevent(kbdev); /* Regardless of whether reset failed or is currently happening, exit * early @@ -4864,21 +5307,28 @@ static void schedule_on_tock(struct work_struct *work) if (err) return; + kbase_debug_csf_fault_wait_completion(kbdev); mutex_lock(&scheduler->lock); if (can_skip_scheduling(kbdev)) + { + atomic_set(&scheduler->pending_tock_work, false); goto exit_no_schedule_unlock; + } WARN_ON(!(scheduler->state == SCHED_INACTIVE)); scheduler->state = SCHED_BUSY; + KBASE_KTRACE_ADD(kbdev, SCHED_BUSY, NULL, scheduler->state); /* Undertaking schedule action steps */ KBASE_KTRACE_ADD(kbdev, SCHEDULER_TOCK_START, NULL, 0u); - schedule_actions(kbdev, false); + while (atomic_cmpxchg(&scheduler->pending_tock_work, true, false) == true) + schedule_actions(kbdev, false); /* Record time information on a non-skipped tock */ scheduler->last_schedule = jiffies; scheduler->state = SCHED_INACTIVE; + KBASE_KTRACE_ADD(kbdev, SCHED_INACTIVE, NULL, scheduler->state); if (!scheduler->total_runnable_grps) enqueue_gpu_idle_work(scheduler); mutex_unlock(&scheduler->lock); @@ -4897,8 +5347,8 @@ exit_no_schedule_unlock: static void schedule_on_tick(struct work_struct *work) { - struct kbase_device *kbdev = container_of(work, struct kbase_device, - csf.scheduler.tick_work); + struct kbase_device *kbdev = + container_of(work, struct kbase_device, csf.scheduler.tick_work); struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; int err = kbase_reset_gpu_try_prevent(kbdev); @@ -4908,6 +5358,7 @@ static void schedule_on_tick(struct work_struct *work) if (err) return; + kbase_debug_csf_fault_wait_completion(kbdev); mutex_lock(&scheduler->lock); WARN_ON(scheduler->tick_timer_active); @@ -4915,6 +5366,7 @@ static void schedule_on_tick(struct work_struct *work) goto exit_no_schedule_unlock; scheduler->state = SCHED_BUSY; + KBASE_KTRACE_ADD(kbdev, SCHED_BUSY, NULL, scheduler->state); /* Undertaking schedule action steps */ KBASE_KTRACE_ADD(kbdev, SCHEDULER_TICK_START, NULL, scheduler->total_runnable_grps); @@ -4936,6 +5388,7 @@ static void schedule_on_tick(struct work_struct *work) scheduler->state = SCHED_INACTIVE; mutex_unlock(&scheduler->lock); + KBASE_KTRACE_ADD(kbdev, SCHED_INACTIVE, NULL, scheduler->state); kbase_reset_gpu_allow(kbdev); dev_dbg(kbdev->dev, "Waking up for event after schedule-on-tick completes."); @@ -4949,67 +5402,6 @@ exit_no_schedule_unlock: kbase_reset_gpu_allow(kbdev); } -static int wait_csg_slots_suspend(struct kbase_device *kbdev, - const unsigned long *slot_mask, - unsigned int timeout_ms) -{ - struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; - long remaining = kbase_csf_timeout_in_jiffies(timeout_ms); - u32 num_groups = kbdev->csf.global_iface.group_num; - int err = 0; - DECLARE_BITMAP(slot_mask_local, MAX_SUPPORTED_CSGS); - - lockdep_assert_held(&scheduler->lock); - - bitmap_copy(slot_mask_local, slot_mask, MAX_SUPPORTED_CSGS); - - while (!bitmap_empty(slot_mask_local, MAX_SUPPORTED_CSGS) - && remaining) { - DECLARE_BITMAP(changed, MAX_SUPPORTED_CSGS); - - bitmap_copy(changed, slot_mask_local, MAX_SUPPORTED_CSGS); - - remaining = wait_event_timeout(kbdev->csf.event_wait, - slots_state_changed(kbdev, changed, - csg_slot_stopped_locked), - remaining); - - if (remaining) { - u32 i; - - for_each_set_bit(i, changed, num_groups) { - struct kbase_queue_group *group; - - if (WARN_ON(!csg_slot_stopped_locked(kbdev, (s8)i))) - continue; - - /* The on slot csg is now stopped */ - clear_bit(i, slot_mask_local); - - group = scheduler->csg_slots[i].resident_group; - if (likely(group)) { - /* Only do save/cleanup if the - * group is not terminated during - * the sleep. - */ - save_csg_slot(group); - if (cleanup_csg_slot(group)) - sched_evict_group(group, true, true); - } - } - } else { - dev_warn(kbdev->dev, "[%llu] Timeout waiting for CSG slots to suspend, slot_mask: 0x%*pb\n", - kbase_backend_get_cycle_cnt(kbdev), - num_groups, slot_mask_local); - - - err = -ETIMEDOUT; - } - } - - return err; -} - static int suspend_active_queue_groups(struct kbase_device *kbdev, unsigned long *slot_mask) { @@ -5172,6 +5564,7 @@ static bool scheduler_handle_reset_in_protected_mode(struct kbase_device *kbdev) cleanup_csg_slot(group); group->run_state = KBASE_CSF_GROUP_SUSPENDED; + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSF_GROUP_SUSPENDED, group, group->run_state); /* Simply treat the normal mode groups as non-idle. The tick * scheduled after the reset will re-initialize the counter @@ -5186,10 +5579,15 @@ unlock: return suspend_on_slot_groups; } +static void cancel_tick_work(struct kbase_csf_scheduler *const scheduler) +{ + cancel_work_sync(&scheduler->tick_work); +} + static void cancel_tock_work(struct kbase_csf_scheduler *const scheduler) { + atomic_set(&scheduler->pending_tock_work, false); cancel_delayed_work_sync(&scheduler->tock_work); - scheduler->tock_pending_request = false; } static void scheduler_inner_reset(struct kbase_device *kbdev) @@ -5203,7 +5601,7 @@ static void scheduler_inner_reset(struct kbase_device *kbdev) /* Cancel any potential queued delayed work(s) */ cancel_work_sync(&kbdev->csf.scheduler.gpu_idle_work); cancel_tick_timer(kbdev); - cancel_work_sync(&scheduler->tick_work); + cancel_tick_work(scheduler); cancel_tock_work(scheduler); cancel_delayed_work_sync(&scheduler->ping_work); @@ -5238,6 +5636,8 @@ void kbase_csf_scheduler_reset(struct kbase_device *kbdev) KBASE_KTRACE_ADD(kbdev, SCHEDULER_RESET_START, NULL, 0u); + kbase_debug_csf_fault_wait_completion(kbdev); + if (scheduler_handle_reset_in_protected_mode(kbdev) && !suspend_active_queue_groups_on_reset(kbdev)) { /* As all groups have been successfully evicted from the CSG @@ -5274,6 +5674,8 @@ void kbase_csf_scheduler_reset(struct kbase_device *kbdev) mutex_unlock(&kbdev->kctx_list_lock); + KBASE_KTRACE_ADD(kbdev, SCHEDULER_RESET_END, NULL, 0u); + /* After queue groups reset, the scheduler data fields clear out */ scheduler_inner_reset(kbdev); } @@ -5328,7 +5730,7 @@ static void firmware_aliveness_monitor(struct work_struct *work) kbase_csf_scheduler_wait_mcu_active(kbdev); - err = kbase_csf_firmware_ping_wait(kbdev); + err = kbase_csf_firmware_ping_wait(kbdev, kbdev->csf.fw_timeout_ms); if (err) { /* It is acceptable to enqueue a reset whilst we've prevented @@ -5687,6 +6089,8 @@ static bool check_sync_update_for_on_slot_group( */ group->reevaluate_idle_status = true; group->run_state = KBASE_CSF_GROUP_RUNNABLE; + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSF_GROUP_RUNNABLE, group, + group->run_state); } KBASE_KTRACE_ADD_CSF_GRP(kbdev, GROUP_SYNC_UPDATE_DONE, group, 0u); @@ -5796,6 +6200,15 @@ static void check_group_sync_update_worker(struct work_struct *work) mutex_lock(&scheduler->lock); +#if IS_ENABLED(CONFIG_DEBUG_FS) + if (unlikely(scheduler->state == SCHED_BUSY)) { + queue_work(kctx->csf.sched.sync_update_wq, + &kctx->csf.sched.sync_update_work); + mutex_unlock(&scheduler->lock); + return; + } +#endif + 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; @@ -5871,6 +6284,8 @@ int kbase_csf_scheduler_context_init(struct kbase_context *kctx) INIT_WORK(&kctx->csf.sched.sync_update_work, check_group_sync_update_worker); + kbase_csf_tiler_heap_reclaim_ctx_init(kctx); + err = kbase_csf_event_wait_add(kctx, check_group_sync_update_cb, kctx); if (err) { @@ -5930,6 +6345,7 @@ int kbase_csf_scheduler_early_init(struct kbase_device *kbdev) INIT_WORK(&scheduler->tick_work, schedule_on_tick); INIT_DEFERRABLE_WORK(&scheduler->tock_work, schedule_on_tock); + atomic_set(&scheduler->pending_tock_work, false); INIT_DEFERRABLE_WORK(&scheduler->ping_work, firmware_aliveness_monitor); @@ -5945,18 +6361,19 @@ int kbase_csf_scheduler_early_init(struct kbase_device *kbdev) (sizeof(scheduler->csgs_events_enable_mask) * BITS_PER_BYTE)); bitmap_fill(scheduler->csgs_events_enable_mask, MAX_SUPPORTED_CSGS); scheduler->state = SCHED_SUSPENDED; + KBASE_KTRACE_ADD(kbdev, SCHED_SUSPENDED, NULL, scheduler->state); scheduler->pm_active_count = 0; scheduler->ngrp_to_schedule = 0; scheduler->total_runnable_grps = 0; scheduler->top_ctx = NULL; scheduler->top_grp = NULL; scheduler->last_schedule = 0; - scheduler->tock_pending_request = false; scheduler->active_protm_grp = NULL; scheduler->csg_scheduling_period_ms = CSF_SCHEDULER_TIME_TICK_MS; scheduler_doorbell_init(kbdev); INIT_WORK(&scheduler->gpu_idle_work, gpu_idle_worker); + scheduler->fast_gpu_idle_handling = false; atomic_set(&scheduler->gpu_no_longer_idle, false); atomic_set(&scheduler->non_idle_offslot_grps, 0); @@ -5964,6 +6381,8 @@ int kbase_csf_scheduler_early_init(struct kbase_device *kbdev) scheduler->tick_timer.function = tick_timer_callback; scheduler->tick_timer_active = false; + kbase_csf_tiler_heap_reclaim_mgr_init(kbdev); + return 0; } @@ -5981,22 +6400,26 @@ void kbase_csf_scheduler_term(struct kbase_device *kbdev) mutex_lock(&kbdev->csf.scheduler.lock); if (kbdev->csf.scheduler.state != SCHED_SUSPENDED) { + unsigned long flags; /* The power policy could prevent the Scheduler from * getting suspended when GPU becomes idle. */ + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); WARN_ON(kbase_pm_idle_groups_sched_suspendable(kbdev)); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); scheduler_suspend(kbdev); } mutex_unlock(&kbdev->csf.scheduler.lock); cancel_delayed_work_sync(&kbdev->csf.scheduler.ping_work); cancel_tick_timer(kbdev); - cancel_work_sync(&kbdev->csf.scheduler.tick_work); + cancel_tick_work(&kbdev->csf.scheduler); cancel_tock_work(&kbdev->csf.scheduler); - mutex_destroy(&kbdev->csf.scheduler.lock); kfree(kbdev->csf.scheduler.csg_slots); kbdev->csf.scheduler.csg_slots = NULL; } + KBASE_KTRACE_ADD_CSF_GRP(kbdev, CSF_GROUP_TERMINATED, NULL, + kbase_csf_scheduler_get_nr_active_csgs(kbdev)); } void kbase_csf_scheduler_early_term(struct kbase_device *kbdev) @@ -6005,6 +6428,9 @@ void kbase_csf_scheduler_early_term(struct kbase_device *kbdev) destroy_workqueue(kbdev->csf.scheduler.idle_wq); if (kbdev->csf.scheduler.wq) destroy_workqueue(kbdev->csf.scheduler.wq); + + kbase_csf_tiler_heap_reclaim_mgr_term(kbdev); + mutex_destroy(&kbdev->csf.scheduler.lock); } /** @@ -6069,13 +6495,12 @@ void kbase_csf_scheduler_timer_set_enabled(struct kbase_device *kbdev, if (currently_enabled && !enable) { scheduler->timer_enabled = false; cancel_tick_timer(kbdev); - cancel_delayed_work(&scheduler->tock_work); - scheduler->tock_pending_request = false; mutex_unlock(&scheduler->lock); /* The non-sync version to cancel the normal work item is not * available, so need to drop the lock before cancellation. */ - cancel_work_sync(&scheduler->tick_work); + cancel_tick_work(scheduler); + cancel_tock_work(scheduler); return; } @@ -6112,6 +6537,12 @@ int kbase_csf_scheduler_pm_suspend_no_lock(struct kbase_device *kbdev) int result = 0; lockdep_assert_held(&scheduler->lock); + +#if IS_ENABLED(CONFIG_DEBUG_FS) + if (unlikely(scheduler->state == SCHED_BUSY)) + return -EBUSY; +#endif + #ifdef KBASE_PM_RUNTIME /* If scheduler is in sleeping state, then MCU needs to be activated * to suspend CSGs. @@ -6147,7 +6578,7 @@ int kbase_csf_scheduler_pm_suspend(struct kbase_device *kbdev) struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; /* Cancel any potential queued delayed work(s) */ - cancel_work_sync(&scheduler->tick_work); + cancel_tick_work(scheduler); cancel_tock_work(scheduler); result = kbase_reset_gpu_prevent_and_wait(kbdev); @@ -6271,6 +6702,7 @@ int kbase_csf_scheduler_handle_runtime_suspend(struct kbase_device *kbdev) } scheduler->state = SCHED_SUSPENDED; + KBASE_KTRACE_ADD(kbdev, SCHED_SUSPENDED, NULL, scheduler->state); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); kbdev->pm.backend.gpu_sleep_mode_active = false; spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); 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 12df5054e573..d22d7c8b9dce 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_scheduler.h @@ -36,7 +36,9 @@ * If the CSG is already scheduled and resident, the CSI will be started * right away, otherwise once the group is made resident. * - * Return: 0 on success, or negative on failure. + * Return: 0 on success, or negative on failure. -EBUSY is returned to + * indicate to the caller that queue could not be enabled due to Scheduler + * state and the caller can try to enable the queue after sometime. */ int kbase_csf_scheduler_queue_start(struct kbase_queue *queue); @@ -530,12 +532,30 @@ static inline void kbase_csf_scheduler_invoke_tick(struct kbase_device *kbdev) struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; unsigned long flags; + KBASE_KTRACE_ADD(kbdev, SCHEDULER_TICK_INVOKE, NULL, 0u); spin_lock_irqsave(&scheduler->interrupt_lock, flags); if (!scheduler->tick_timer_active) queue_work(scheduler->wq, &scheduler->tick_work); spin_unlock_irqrestore(&scheduler->interrupt_lock, flags); } +/** + * kbase_csf_scheduler_invoke_tock() - Invoke the scheduling tock + * + * @kbdev: Pointer to the device + * + * This function will queue the scheduling tock work item for immediate + * execution. + */ +static inline void kbase_csf_scheduler_invoke_tock(struct kbase_device *kbdev) +{ + struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; + + KBASE_KTRACE_ADD(kbdev, SCHEDULER_TOCK_INVOKE, NULL, 0u); + if (atomic_cmpxchg(&scheduler->pending_tock_work, false, true) == false) + mod_delayed_work(scheduler->wq, &scheduler->tock_work, 0); +} + /** * kbase_csf_scheduler_queue_has_trace() - report whether the queue has been * configured to operate with the diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap.c index 769369150687..909362da0047 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap.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 @@ -25,6 +25,26 @@ #include "mali_kbase_csf_tiler_heap_def.h" #include "mali_kbase_csf_heap_context_alloc.h" +/* Tiler heap shrink stop limit for maintaining a minimum number of chunks */ +#define HEAP_SHRINK_STOP_LIMIT (1) + +/** + * struct kbase_csf_gpu_buffer_heap - A gpu buffer object specific to tiler heap + * + * @cdsbp_0: Descriptor_type and buffer_type + * @size: The size of the current heap chunk + * @pointer: Pointer to the current heap chunk + * @low_pointer: Pointer to low end of current heap chunk + * @high_pointer: Pointer to high end of current heap chunk + */ +struct kbase_csf_gpu_buffer_heap { + u32 cdsbp_0; + u32 size; + u64 pointer; + u64 low_pointer; + u64 high_pointer; +} __packed; + /** * encode_chunk_ptr - Encode the address and size of a chunk as an integer. * @@ -73,6 +93,35 @@ static struct kbase_csf_tiler_heap_chunk *get_last_chunk( struct kbase_csf_tiler_heap_chunk, link); } +/** + * remove_external_chunk_mappings - Remove external mappings from a chunk that + * is being transitioned to the tiler heap + * memory system. + * + * @kctx: kbase context the chunk belongs to. + * @chunk: The chunk whose external mappings are going to be removed. + * + * This function marks the region as DONT NEED. Along with KBASE_REG_NO_USER_FREE, this indicates + * that the VA region is owned by the tiler heap and could potentially be shrunk at any time. Other + * parts of kbase outside of tiler heap management should not take references on its physical + * pages, and should not modify them. + */ +static void remove_external_chunk_mappings(struct kbase_context *const kctx, + struct kbase_csf_tiler_heap_chunk *chunk) +{ + lockdep_assert_held(&kctx->reg_lock); + + if (chunk->region->cpu_alloc != NULL) { + kbase_mem_shrink_cpu_mapping(kctx, chunk->region, 0, + chunk->region->cpu_alloc->nents); + } +#if !defined(CONFIG_MALI_VECTOR_DUMP) + chunk->region->flags |= KBASE_REG_DONT_NEED; +#endif + + dev_dbg(kctx->kbdev->dev, "Removed external mappings from chunk 0x%llX", chunk->gpu_va); +} + /** * link_chunk - Link a chunk into a tiler heap * @@ -93,19 +142,12 @@ static int link_chunk(struct kbase_csf_tiler_heap *const heap, if (prev) { struct kbase_context *const kctx = heap->kctx; - struct kbase_vmap_struct map; - u64 *const prev_hdr = kbase_vmap_prot(kctx, prev->gpu_va, - sizeof(*prev_hdr), KBASE_REG_CPU_WR, &map); + u64 *prev_hdr = prev->map.addr; - if (unlikely(!prev_hdr)) { - dev_err(kctx->kbdev->dev, - "Failed to map tiler heap chunk 0x%llX\n", - prev->gpu_va); - return -ENOMEM; - } + WARN((prev->region->flags & KBASE_REG_CPU_CACHED), + "Cannot support CPU cached chunks without sync operations"); *prev_hdr = encode_chunk_ptr(heap->chunk_size, chunk->gpu_va); - kbase_vunmap(kctx, &map); dev_dbg(kctx->kbdev->dev, "Linked tiler heap chunks, 0x%llX -> 0x%llX\n", @@ -132,152 +174,264 @@ static int link_chunk(struct kbase_csf_tiler_heap *const heap, static int init_chunk(struct kbase_csf_tiler_heap *const heap, struct kbase_csf_tiler_heap_chunk *const chunk, bool link_with_prev) { - struct kbase_vmap_struct map; - struct u64 *chunk_hdr = NULL; + int err = 0; + u64 *chunk_hdr; struct kbase_context *const kctx = heap->kctx; + lockdep_assert_held(&kctx->csf.tiler_heaps.lock); + if (unlikely(chunk->gpu_va & ~CHUNK_ADDR_MASK)) { dev_err(kctx->kbdev->dev, "Tiler heap chunk address is unusable\n"); return -EINVAL; } - chunk_hdr = kbase_vmap_prot(kctx, - chunk->gpu_va, CHUNK_HDR_SIZE, KBASE_REG_CPU_WR, &map); - - if (unlikely(!chunk_hdr)) { - dev_err(kctx->kbdev->dev, - "Failed to map a tiler heap chunk header\n"); - return -ENOMEM; + WARN((chunk->region->flags & KBASE_REG_CPU_CACHED), + "Cannot support CPU cached chunks without sync operations"); + chunk_hdr = chunk->map.addr; + if (WARN(chunk->map.size < CHUNK_HDR_SIZE, + "Tiler chunk kernel mapping was not large enough for zero-init")) { + return -EINVAL; } memset(chunk_hdr, 0, CHUNK_HDR_SIZE); - kbase_vunmap(kctx, &map); + INIT_LIST_HEAD(&chunk->link); if (link_with_prev) - return link_chunk(heap, chunk); - else - return 0; + err = link_chunk(heap, chunk); + + if (unlikely(err)) { + dev_err(kctx->kbdev->dev, "Failed to link a chunk to a tiler heap\n"); + return -EINVAL; + } + + list_add_tail(&chunk->link, &heap->chunks_list); + heap->chunk_count++; + + return err; +} + +/** + * remove_unlinked_chunk - Remove a chunk that is not currently linked into a + * heap. + * + * @kctx: Kbase context that was used to allocate the memory. + * @chunk: Chunk that has been allocated, but not linked into a heap. + */ +static void remove_unlinked_chunk(struct kbase_context *kctx, + struct kbase_csf_tiler_heap_chunk *chunk) +{ + if (WARN_ON(!list_empty(&chunk->link))) + return; + + kbase_gpu_vm_lock(kctx); + kbase_vunmap(kctx, &chunk->map); + /* KBASE_REG_DONT_NEED regions will be confused with ephemeral regions (inc freed JIT + * regions), and so we must clear that flag too before freeing + */ +#if !defined(CONFIG_MALI_VECTOR_DUMP) + chunk->region->flags &= ~(KBASE_REG_NO_USER_FREE | KBASE_REG_DONT_NEED); +#else + chunk->region->flags &= ~KBASE_REG_NO_USER_FREE; +#endif + kbase_mem_free_region(kctx, chunk->region); + kbase_gpu_vm_unlock(kctx); + + kfree(chunk); +} + +/** + * alloc_new_chunk - Allocate new chunk metadata for the tiler heap, reserve a fully backed VA + * region for the chunk, and provide a kernel mapping. + * @kctx: kbase context with which the chunk will be linked + * @chunk_size: the size of the chunk from the corresponding heap + * + * Allocate the chunk tracking metadata and a corresponding fully backed VA region for the + * chunk. The kernel may need to invoke the reclaim path while trying to fulfill the allocation, so + * we cannot hold any lock that would be held in the shrinker paths (JIT evict lock or tiler heap + * lock). + * + * Since the chunk may have its physical backing removed, to prevent use-after-free scenarios we + * ensure that it is protected from being mapped by other parts of kbase. + * + * The chunk's GPU memory can be accessed via its 'map' member, but should only be done so by the + * shrinker path, as it may be otherwise shrunk at any time. + * + * Return: pointer to kbase_csf_tiler_heap_chunk on success or a NULL pointer + * on failure + */ +static struct kbase_csf_tiler_heap_chunk *alloc_new_chunk(struct kbase_context *kctx, + u64 chunk_size) +{ + u64 nr_pages = PFN_UP(chunk_size); + u64 flags = BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR | BASE_MEM_PROT_CPU_WR | + BASEP_MEM_NO_USER_FREE | BASE_MEM_COHERENT_LOCAL | BASE_MEM_PROT_CPU_RD; + struct kbase_csf_tiler_heap_chunk *chunk = NULL; + /* The chunk kernel mapping needs to be large enough to: + * - initially zero the CHUNK_HDR_SIZE area + * - on shrinking, access the NEXT_CHUNK_ADDR_SIZE area + */ + const size_t chunk_kernel_map_size = max(CHUNK_HDR_SIZE, NEXT_CHUNK_ADDR_SIZE); + + /* Calls to this function are inherently synchronous, with respect to + * MMU operations. + */ + const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_SYNC; + flags |= kbase_mem_group_id_set(kctx->jit_group_id); + + chunk = kzalloc(sizeof(*chunk), GFP_KERNEL); + if (unlikely(!chunk)) { + dev_err(kctx->kbdev->dev, + "No kernel memory for a new tiler heap chunk\n"); + return NULL; + } + + /* Allocate GPU memory for the new chunk. */ + chunk->region = + kbase_mem_alloc(kctx, nr_pages, nr_pages, 0, &flags, &chunk->gpu_va, mmu_sync_info); + + if (unlikely(!chunk->region)) { + dev_err(kctx->kbdev->dev, "Failed to allocate a tiler heap chunk!\n"); + goto unroll_chunk; + } + + kbase_gpu_vm_lock(kctx); + + /* Some checks done here as KBASE_REG_NO_USER_FREE still allows such things to be made + * whilst we had dropped the region lock + */ + if (unlikely(atomic_read(&chunk->region->gpu_alloc->kernel_mappings) > 0)) { + dev_err(kctx->kbdev->dev, "Chunk region has active kernel mappings!\n"); + goto unroll_region; + } + + /* Whilst we can be sure of a number of other restrictions due to BASEP_MEM_NO_USER_FREE + * being requested, it's useful to document in code what those restrictions are, and ensure + * they remain in place in future. + */ + if (WARN(!chunk->region->gpu_alloc, + "KBASE_REG_NO_USER_FREE chunks should not have had their alloc freed")) { + goto unroll_region; + } + + if (WARN(chunk->region->gpu_alloc->type != KBASE_MEM_TYPE_NATIVE, + "KBASE_REG_NO_USER_FREE chunks should not have been freed and then reallocated as imported/non-native regions")) { + goto unroll_region; + } + + if (WARN((chunk->region->flags & KBASE_REG_ACTIVE_JIT_ALLOC), + "KBASE_REG_NO_USER_FREE chunks should not have been freed and then reallocated as JIT regions")) { + goto unroll_region; + } + + if (WARN((chunk->region->flags & KBASE_REG_DONT_NEED), + "KBASE_REG_NO_USER_FREE chunks should not have been made ephemeral")) { + goto unroll_region; + } + + if (WARN(atomic_read(&chunk->region->cpu_alloc->gpu_mappings) > 1, + "KBASE_REG_NO_USER_FREE chunks should not have been aliased")) { + goto unroll_region; + } + + if (unlikely(!kbase_vmap_reg(kctx, chunk->region, chunk->gpu_va, chunk_kernel_map_size, + (KBASE_REG_CPU_RD | KBASE_REG_CPU_WR), &chunk->map, + KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING))) { + dev_err(kctx->kbdev->dev, "Failed to map chunk header for shrinking!\n"); + goto unroll_region; + } + + remove_external_chunk_mappings(kctx, chunk); + kbase_gpu_vm_unlock(kctx); + + return chunk; + +unroll_region: + /* KBASE_REG_DONT_NEED regions will be confused with ephemeral regions (inc freed JIT + * regions), and so we must clear that flag too before freeing. + */ +#if !defined(CONFIG_MALI_VECTOR_DUMP) + chunk->region->flags &= ~(KBASE_REG_NO_USER_FREE | KBASE_REG_DONT_NEED); +#else + chunk->region->flags &= ~KBASE_REG_NO_USER_FREE; +#endif + kbase_mem_free_region(kctx, chunk->region); + kbase_gpu_vm_unlock(kctx); +unroll_chunk: + kfree(chunk); + return NULL; } /** * create_chunk - Create a tiler heap chunk * * @heap: Pointer to the tiler heap for which to allocate memory. - * @link_with_prev: Flag to indicate if the chunk to be allocated needs to be - * linked with the previously allocated chunk. * - * This function allocates a chunk of memory for a tiler heap and adds it to - * the end of the list of chunks associated with that heap. The size of the - * chunk is not a parameter because it is configured per-heap not per-chunk. + * This function allocates a chunk of memory for a tiler heap, adds it to the + * the list of chunks associated with that heap both on the host side and in GPU + * memory. * * Return: 0 if successful or a negative error code on failure. */ -static int create_chunk(struct kbase_csf_tiler_heap *const heap, - bool link_with_prev) +static int create_chunk(struct kbase_csf_tiler_heap *const heap) { int err = 0; - struct kbase_context *const kctx = heap->kctx; - u64 nr_pages = PFN_UP(heap->chunk_size); - u64 flags = BASE_MEM_PROT_GPU_RD | BASE_MEM_PROT_GPU_WR | - BASE_MEM_PROT_CPU_WR | BASEP_MEM_NO_USER_FREE | - BASE_MEM_COHERENT_LOCAL; struct kbase_csf_tiler_heap_chunk *chunk = NULL; - /* Calls to this function are inherently synchronous, with respect to - * MMU operations. - */ - const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_SYNC; - - flags |= kbase_mem_group_id_set(kctx->jit_group_id); - -#if defined(CONFIG_MALI_BIFROST_DEBUG) || defined(CONFIG_MALI_VECTOR_DUMP) - flags |= BASE_MEM_PROT_CPU_RD; -#endif - - chunk = kzalloc(sizeof(*chunk), GFP_KERNEL); + chunk = alloc_new_chunk(heap->kctx, heap->chunk_size); if (unlikely(!chunk)) { - dev_err(kctx->kbdev->dev, - "No kernel memory for a new tiler heap chunk\n"); - return -ENOMEM; - } - - /* Allocate GPU memory for the new chunk. */ - INIT_LIST_HEAD(&chunk->link); - chunk->region = - kbase_mem_alloc(kctx, nr_pages, nr_pages, 0, &flags, &chunk->gpu_va, mmu_sync_info); - - if (unlikely(!chunk->region)) { - dev_err(kctx->kbdev->dev, - "Failed to allocate a tiler heap chunk\n"); err = -ENOMEM; - } else { - err = init_chunk(heap, chunk, link_with_prev); - if (unlikely(err)) { - kbase_gpu_vm_lock(kctx); - chunk->region->flags &= ~KBASE_REG_NO_USER_FREE; - kbase_mem_free_region(kctx, chunk->region); - kbase_gpu_vm_unlock(kctx); - } + goto allocation_failure; } - if (unlikely(err)) { - kfree(chunk); - } else { - list_add_tail(&chunk->link, &heap->chunks_list); - heap->chunk_count++; + mutex_lock(&heap->kctx->csf.tiler_heaps.lock); + err = init_chunk(heap, chunk, true); + mutex_unlock(&heap->kctx->csf.tiler_heaps.lock); - dev_dbg(kctx->kbdev->dev, "Created tiler heap chunk 0x%llX\n", - chunk->gpu_va); - } + if (unlikely(err)) + goto initialization_failure; + dev_dbg(heap->kctx->kbdev->dev, "Created tiler heap chunk 0x%llX\n", chunk->gpu_va); + + return 0; +initialization_failure: + remove_unlinked_chunk(heap->kctx, chunk); +allocation_failure: return err; } /** - * delete_chunk - Delete a tiler heap chunk - * - * @heap: Pointer to the tiler heap for which @chunk was allocated. - * @chunk: Pointer to a chunk to be deleted. - * - * This function frees a tiler heap chunk previously allocated by @create_chunk - * and removes it from the list of chunks associated with the heap. - * - * WARNING: The deleted chunk is not unlinked from the list of chunks used by - * the GPU, therefore it is only safe to use this function when - * deleting a heap. - */ -static void delete_chunk(struct kbase_csf_tiler_heap *const heap, - struct kbase_csf_tiler_heap_chunk *const chunk) -{ - struct kbase_context *const kctx = heap->kctx; - - kbase_gpu_vm_lock(kctx); - chunk->region->flags &= ~KBASE_REG_NO_USER_FREE; - kbase_mem_free_region(kctx, chunk->region); - kbase_gpu_vm_unlock(kctx); - list_del(&chunk->link); - heap->chunk_count--; - kfree(chunk); -} - -/** - * delete_all_chunks - Delete all chunks belonging to a tiler heap + * delete_all_chunks - Delete all chunks belonging to an unlinked tiler heap * * @heap: Pointer to a tiler heap. * - * This function empties the list of chunks associated with a tiler heap by - * freeing all chunks previously allocated by @create_chunk. + * This function empties the list of chunks associated with a tiler heap by freeing all chunks + * previously allocated by @create_chunk. + * + * The heap must not be reachable from a &struct kbase_context.csf.tiler_heaps.list, as the + * tiler_heaps lock cannot be held whilst deleting its chunks due to also needing the &struct + * kbase_context.region_lock. + * + * WARNING: Whilst the deleted chunks are unlinked from host memory, they are not unlinked from the + * list of chunks used by the GPU, therefore it is only safe to use this function when + * deleting a heap. */ static void delete_all_chunks(struct kbase_csf_tiler_heap *heap) { + struct kbase_context *const kctx = heap->kctx; struct list_head *entry = NULL, *tmp = NULL; + WARN(!list_empty(&heap->link), + "Deleting a heap's chunks when that heap is still linked requires the tiler_heaps lock, which cannot be held by the caller"); + list_for_each_safe(entry, tmp, &heap->chunks_list) { struct kbase_csf_tiler_heap_chunk *chunk = list_entry( entry, struct kbase_csf_tiler_heap_chunk, link); - delete_chunk(heap, chunk); + list_del_init(&chunk->link); + heap->chunk_count--; + + remove_unlinked_chunk(kctx, chunk); } } @@ -299,7 +453,7 @@ static int create_initial_chunks(struct kbase_csf_tiler_heap *const heap, u32 i; for (i = 0; (i < nchunks) && likely(!err); i++) - err = create_chunk(heap, true); + err = create_chunk(heap); if (unlikely(err)) delete_all_chunks(heap); @@ -308,14 +462,17 @@ static int create_initial_chunks(struct kbase_csf_tiler_heap *const heap, } /** - * delete_heap - Delete a tiler heap + * delete_heap - Delete an unlinked tiler heap * * @heap: Pointer to a tiler heap to be deleted. * * This function frees any chunks allocated for a tiler heap previously - * initialized by @kbase_csf_tiler_heap_init and removes it from the list of - * heaps associated with the kbase context. The heap context structure used by + * initialized by @kbase_csf_tiler_heap_init. The heap context structure used by * the firmware is also freed. + * + * The heap must not be reachable from a &struct kbase_context.csf.tiler_heaps.list, as the + * tiler_heaps lock cannot be held whilst deleting it due to also needing the &struct + * kbase_context.region_lock. */ static void delete_heap(struct kbase_csf_tiler_heap *heap) { @@ -323,23 +480,41 @@ static void delete_heap(struct kbase_csf_tiler_heap *heap) dev_dbg(kctx->kbdev->dev, "Deleting tiler heap 0x%llX\n", heap->gpu_va); - lockdep_assert_held(&kctx->csf.tiler_heaps.lock); + WARN(!list_empty(&heap->link), + "Deleting a heap that is still linked requires the tiler_heaps lock, which cannot be held by the caller"); + /* Make sure that all of the VA regions corresponding to the chunks are + * freed at this time and that the work queue is not trying to access freed + * memory. + * + * Note: since the heap is unlinked, and that no references are made to chunks other + * than from their heap, there is no need to separately move the chunks out of the + * heap->chunks_list to delete them. + */ delete_all_chunks(heap); + kbase_vunmap(kctx, &heap->gpu_va_map); /* We could optimize context destruction by not freeing leaked heap - * contexts but it doesn't seem worth the extra complexity. + * contexts but it doesn't seem worth the extra complexity. After this + * point, the suballocation is returned to the heap context allocator and + * may be overwritten with new data, meaning heap->gpu_va should not + * be used past this point. */ kbase_csf_heap_context_allocator_free(&kctx->csf.tiler_heaps.ctx_alloc, heap->gpu_va); - list_del(&heap->link); - WARN_ON(heap->chunk_count); KBASE_TLSTREAM_AUX_TILER_HEAP_STATS(kctx->kbdev, kctx->id, heap->heap_id, 0, 0, heap->max_chunks, heap->chunk_size, 0, heap->target_in_flight, 0); + if (heap->buf_desc_reg) { + kbase_vunmap(kctx, &heap->buf_desc_map); + kbase_gpu_vm_lock(kctx); + heap->buf_desc_reg->flags &= ~KBASE_REG_NO_USER_FREE; + kbase_gpu_vm_unlock(kctx); + } + kfree(heap); } @@ -375,6 +550,23 @@ static struct kbase_csf_tiler_heap *find_tiler_heap( return NULL; } +static struct kbase_csf_tiler_heap_chunk *find_chunk(struct kbase_csf_tiler_heap *heap, + u64 const chunk_gpu_va) +{ + struct kbase_csf_tiler_heap_chunk *chunk = NULL; + + lockdep_assert_held(&heap->kctx->csf.tiler_heaps.lock); + + list_for_each_entry(chunk, &heap->chunks_list, link) { + if (chunk->gpu_va == chunk_gpu_va) + return chunk; + } + + dev_dbg(heap->kctx->kbdev->dev, "Tiler heap chunk 0x%llX was not found\n", chunk_gpu_va); + + return NULL; +} + int kbase_csf_tiler_heap_context_init(struct kbase_context *const kctx) { int err = kbase_csf_heap_context_allocator_init( @@ -393,37 +585,88 @@ int kbase_csf_tiler_heap_context_init(struct kbase_context *const kctx) void kbase_csf_tiler_heap_context_term(struct kbase_context *const kctx) { + LIST_HEAD(local_heaps_list); struct list_head *entry = NULL, *tmp = NULL; dev_dbg(kctx->kbdev->dev, "Terminating a context for tiler heaps\n"); mutex_lock(&kctx->csf.tiler_heaps.lock); + list_splice_init(&kctx->csf.tiler_heaps.list, &local_heaps_list); + mutex_unlock(&kctx->csf.tiler_heaps.lock); - list_for_each_safe(entry, tmp, &kctx->csf.tiler_heaps.list) { + list_for_each_safe(entry, tmp, &local_heaps_list) { struct kbase_csf_tiler_heap *heap = list_entry( entry, struct kbase_csf_tiler_heap, link); + + list_del_init(&heap->link); delete_heap(heap); } - mutex_unlock(&kctx->csf.tiler_heaps.lock); mutex_destroy(&kctx->csf.tiler_heaps.lock); kbase_csf_heap_context_allocator_term(&kctx->csf.tiler_heaps.ctx_alloc); } -int kbase_csf_tiler_heap_init(struct kbase_context *const kctx, - u32 const chunk_size, u32 const initial_chunks, u32 const max_chunks, - u16 const target_in_flight, u64 *const heap_gpu_va, - u64 *const first_chunk_va) +/** + * kbasep_is_buffer_descriptor_region_suitable - Check if a VA region chosen to house + * the tiler heap buffer descriptor + * is suitable for the purpose. + * @kctx: kbase context of the tiler heap + * @reg: VA region being checked for suitability + * + * The tiler heap buffer descriptor memory does not admit page faults according + * to its design, so it must have the entirety of the backing upon allocation, + * and it has to remain alive as long as the tiler heap is alive, meaning it + * cannot be allocated from JIT/Ephemeral, or user freeable memory. + * + * Return: true on suitability, false otherwise. + */ +static bool kbasep_is_buffer_descriptor_region_suitable(struct kbase_context *const kctx, + struct kbase_va_region *const reg) +{ + if (kbase_is_region_invalid_or_free(reg)) { + dev_err(kctx->kbdev->dev, "Region is either invalid or free!\n"); + return false; + } + + if (!(reg->flags & KBASE_REG_CPU_RD) || (reg->flags & KBASE_REG_DONT_NEED) || + (reg->flags & KBASE_REG_PF_GROW) || (reg->flags & KBASE_REG_ACTIVE_JIT_ALLOC)) { + dev_err(kctx->kbdev->dev, "Region has invalid flags: 0x%lX!\n", reg->flags); + return false; + } + + if (reg->gpu_alloc->type != KBASE_MEM_TYPE_NATIVE) { + dev_err(kctx->kbdev->dev, "Region has invalid type!\n"); + return false; + } + + if ((reg->nr_pages != kbase_reg_current_backed_size(reg)) || + (reg->nr_pages < PFN_UP(sizeof(struct kbase_csf_gpu_buffer_heap)))) { + dev_err(kctx->kbdev->dev, "Region has invalid backing!\n"); + return false; + } + + return true; +} + +#define TILER_BUF_DESC_SIZE (sizeof(struct kbase_csf_gpu_buffer_heap)) + +int kbase_csf_tiler_heap_init(struct kbase_context *const kctx, u32 const chunk_size, + u32 const initial_chunks, u32 const max_chunks, + u16 const target_in_flight, u64 const buf_desc_va, + u64 *const heap_gpu_va, u64 *const first_chunk_va) { int err = 0; struct kbase_csf_tiler_heap *heap = NULL; struct kbase_csf_heap_context_allocator *const ctx_alloc = &kctx->csf.tiler_heaps.ctx_alloc; + struct kbase_csf_tiler_heap_chunk *chunk = NULL; + struct kbase_va_region *gpu_va_reg = NULL; + void *vmap_ptr = NULL; dev_dbg(kctx->kbdev->dev, - "Creating a tiler heap with %u chunks (limit: %u) of size %u\n", - initial_chunks, max_chunks, chunk_size); + "Creating a tiler heap with %u chunks (limit: %u) of size %u, buf_desc_va: 0x%llx\n", + initial_chunks, max_chunks, chunk_size, buf_desc_va); if (!kbase_mem_allow_alloc(kctx)) return -EINVAL; @@ -445,8 +688,7 @@ int kbase_csf_tiler_heap_init(struct kbase_context *const kctx, heap = kzalloc(sizeof(*heap), GFP_KERNEL); if (unlikely(!heap)) { - dev_err(kctx->kbdev->dev, - "No kernel memory for a new tiler heap\n"); + dev_err(kctx->kbdev->dev, "No kernel memory for a new tiler heap"); return -ENOMEM; } @@ -454,57 +696,126 @@ int kbase_csf_tiler_heap_init(struct kbase_context *const kctx, heap->chunk_size = chunk_size; heap->max_chunks = max_chunks; heap->target_in_flight = target_in_flight; + heap->buf_desc_checked = false; INIT_LIST_HEAD(&heap->chunks_list); + INIT_LIST_HEAD(&heap->link); + + /* Check on the buffer descriptor virtual Address */ + if (buf_desc_va) { + struct kbase_va_region *buf_desc_reg; + + kbase_gpu_vm_lock(kctx); + buf_desc_reg = + kbase_region_tracker_find_region_enclosing_address(kctx, buf_desc_va); + + if (!kbasep_is_buffer_descriptor_region_suitable(kctx, buf_desc_reg)) { + kbase_gpu_vm_unlock(kctx); + dev_err(kctx->kbdev->dev, + "Could not find a suitable VA region for the tiler heap buf desc!\n"); + err = -EINVAL; + goto buf_desc_not_suitable; + } + + /* If we don't prevent userspace from unmapping this, we may run into + * use-after-free, as we don't check for the existence of the region throughout. + */ + buf_desc_reg->flags |= KBASE_REG_NO_USER_FREE; + + heap->buf_desc_va = buf_desc_va; + heap->buf_desc_reg = buf_desc_reg; + + vmap_ptr = kbase_vmap_reg(kctx, buf_desc_reg, buf_desc_va, TILER_BUF_DESC_SIZE, + KBASE_REG_CPU_RD, &heap->buf_desc_map, + KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING); + kbase_gpu_vm_unlock(kctx); + + if (unlikely(!vmap_ptr)) { + dev_err(kctx->kbdev->dev, + "Could not vmap buffer descriptor into kernel memory (err %d)\n", + err); + err = -ENOMEM; + goto buf_desc_vmap_failed; + } + } heap->gpu_va = kbase_csf_heap_context_allocator_alloc(ctx_alloc); - if (unlikely(!heap->gpu_va)) { - dev_dbg(kctx->kbdev->dev, - "Failed to allocate a tiler heap context"); + dev_dbg(kctx->kbdev->dev, "Failed to allocate a tiler heap context\n"); err = -ENOMEM; - } else { - err = create_initial_chunks(heap, initial_chunks); - if (unlikely(err)) - kbase_csf_heap_context_allocator_free(ctx_alloc, heap->gpu_va); + goto heap_context_alloc_failed; } + gpu_va_reg = ctx_alloc->region; + + kbase_gpu_vm_lock(kctx); + /* gpu_va_reg was created with BASEP_MEM_NO_USER_FREE, the code to unset this only happens + * on kctx termination (after all syscalls on kctx have finished), and so it is safe to + * assume that gpu_va_reg is still present. + */ + vmap_ptr = kbase_vmap_reg(kctx, gpu_va_reg, heap->gpu_va, NEXT_CHUNK_ADDR_SIZE, + (KBASE_REG_CPU_RD | KBASE_REG_CPU_WR), &heap->gpu_va_map, + KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING); + kbase_gpu_vm_unlock(kctx); + if (unlikely(!vmap_ptr)) { + dev_dbg(kctx->kbdev->dev, "Failed to vmap the correct heap GPU VA address\n"); + err = -ENOMEM; + goto heap_context_vmap_failed; + } + + err = create_initial_chunks(heap, initial_chunks); if (unlikely(err)) { - kfree(heap); - } else { - struct kbase_csf_tiler_heap_chunk const *chunk = list_first_entry( - &heap->chunks_list, struct kbase_csf_tiler_heap_chunk, link); + dev_dbg(kctx->kbdev->dev, "Failed to create the initial tiler heap chunks\n"); + goto create_chunks_failed; + } + chunk = list_first_entry(&heap->chunks_list, struct kbase_csf_tiler_heap_chunk, link); - *heap_gpu_va = heap->gpu_va; - *first_chunk_va = chunk->gpu_va; + *heap_gpu_va = heap->gpu_va; + *first_chunk_va = chunk->gpu_va; - mutex_lock(&kctx->csf.tiler_heaps.lock); - kctx->csf.tiler_heaps.nr_of_heaps++; - heap->heap_id = kctx->csf.tiler_heaps.nr_of_heaps; - list_add(&heap->link, &kctx->csf.tiler_heaps.list); + mutex_lock(&kctx->csf.tiler_heaps.lock); + kctx->csf.tiler_heaps.nr_of_heaps++; + heap->heap_id = kctx->csf.tiler_heaps.nr_of_heaps; + list_add(&heap->link, &kctx->csf.tiler_heaps.list); - KBASE_TLSTREAM_AUX_TILER_HEAP_STATS( - kctx->kbdev, kctx->id, heap->heap_id, - PFN_UP(heap->chunk_size * heap->max_chunks), - PFN_UP(heap->chunk_size * heap->chunk_count), heap->max_chunks, - heap->chunk_size, heap->chunk_count, heap->target_in_flight, 0); + KBASE_TLSTREAM_AUX_TILER_HEAP_STATS(kctx->kbdev, kctx->id, heap->heap_id, + PFN_UP(heap->chunk_size * heap->max_chunks), + PFN_UP(heap->chunk_size * heap->chunk_count), + heap->max_chunks, heap->chunk_size, heap->chunk_count, + heap->target_in_flight, 0); #if defined(CONFIG_MALI_VECTOR_DUMP) - list_for_each_entry(chunk, &heap->chunks_list, link) { - KBASE_TLSTREAM_JD_TILER_HEAP_CHUNK_ALLOC( - kctx->kbdev, kctx->id, heap->heap_id, chunk->gpu_va); - } -#endif - - dev_dbg(kctx->kbdev->dev, "Created tiler heap 0x%llX\n", heap->gpu_va); - mutex_unlock(&kctx->csf.tiler_heaps.lock); - kctx->running_total_tiler_heap_nr_chunks += heap->chunk_count; - kctx->running_total_tiler_heap_memory += - heap->chunk_size * heap->chunk_count; - if (kctx->running_total_tiler_heap_memory > - kctx->peak_total_tiler_heap_memory) - kctx->peak_total_tiler_heap_memory = - kctx->running_total_tiler_heap_memory; + list_for_each_entry(chunk, &heap->chunks_list, link) { + KBASE_TLSTREAM_JD_TILER_HEAP_CHUNK_ALLOC(kctx->kbdev, kctx->id, heap->heap_id, + chunk->gpu_va); } +#endif + kctx->running_total_tiler_heap_nr_chunks += heap->chunk_count; + kctx->running_total_tiler_heap_memory += (u64)heap->chunk_size * heap->chunk_count; + if (kctx->running_total_tiler_heap_memory > kctx->peak_total_tiler_heap_memory) + kctx->peak_total_tiler_heap_memory = kctx->running_total_tiler_heap_memory; + + dev_dbg(kctx->kbdev->dev, + "Created tiler heap 0x%llX, buffer descriptor 0x%llX, ctx_%d_%d\n", heap->gpu_va, + buf_desc_va, kctx->tgid, kctx->id); + mutex_unlock(&kctx->csf.tiler_heaps.lock); + + return 0; + +create_chunks_failed: + kbase_vunmap(kctx, &heap->gpu_va_map); +heap_context_vmap_failed: + kbase_csf_heap_context_allocator_free(ctx_alloc, heap->gpu_va); +heap_context_alloc_failed: + if (heap->buf_desc_reg) + kbase_vunmap(kctx, &heap->buf_desc_map); +buf_desc_vmap_failed: + if (heap->buf_desc_reg) { + kbase_gpu_vm_lock(kctx); + heap->buf_desc_reg->flags &= ~KBASE_REG_NO_USER_FREE; + kbase_gpu_vm_unlock(kctx); + } +buf_desc_not_suitable: + kfree(heap); return err; } @@ -517,16 +828,19 @@ int kbase_csf_tiler_heap_term(struct kbase_context *const kctx, u64 heap_size = 0; mutex_lock(&kctx->csf.tiler_heaps.lock); - heap = find_tiler_heap(kctx, heap_gpu_va); if (likely(heap)) { chunk_count = heap->chunk_count; heap_size = heap->chunk_size * chunk_count; - delete_heap(heap); - } else - err = -EINVAL; - mutex_unlock(&kctx->csf.tiler_heaps.lock); + list_del_init(&heap->link); + } else { + err = -EINVAL; + } + + /* Update stats whilst still holding the lock so they are in sync with the tiler_heaps.list + * at all times + */ if (likely(kctx->running_total_tiler_heap_memory >= heap_size)) kctx->running_total_tiler_heap_memory -= heap_size; else @@ -537,36 +851,27 @@ int kbase_csf_tiler_heap_term(struct kbase_context *const kctx, else dev_warn(kctx->kbdev->dev, "Running total tiler chunk count lower than expected!"); + if (!err) + dev_dbg(kctx->kbdev->dev, + "Terminated tiler heap 0x%llX, buffer descriptor 0x%llX, ctx_%d_%d\n", + heap->gpu_va, heap->buf_desc_va, kctx->tgid, kctx->id); + mutex_unlock(&kctx->csf.tiler_heaps.lock); + + /* Deletion requires the kctx->reg_lock, so must only operate on it whilst unlinked from + * the kctx's csf.tiler_heaps.list, and without holding the csf.tiler_heaps.lock + */ + if (likely(heap)) + delete_heap(heap); + return err; } -/** - * alloc_new_chunk - Allocate a new chunk for the tiler heap. - * - * @heap: Pointer to the tiler heap. - * @nr_in_flight: Number of render passes that are in-flight, must not be zero. - * @pending_frag_count: Number of render passes in-flight with completed vertex/tiler stage. - * The minimum value is zero but it must be less or equal to - * the total number of render passes in flight - * @new_chunk_ptr: Where to store the GPU virtual address & size of the new - * chunk allocated for the heap. - * - * This function will allocate a new chunk for the chunked tiler heap depending - * on the settings provided by userspace when the heap was created and the - * heap's statistics (like number of render passes in-flight). - * - * Return: 0 if a new chunk was allocated otherwise an appropriate negative - * error code. - */ -static int alloc_new_chunk(struct kbase_csf_tiler_heap *heap, - u32 nr_in_flight, u32 pending_frag_count, u64 *new_chunk_ptr) +static int validate_allocation_request(struct kbase_csf_tiler_heap *heap, u32 nr_in_flight, + u32 pending_frag_count) { - int err = -ENOMEM; - lockdep_assert_held(&heap->kctx->csf.tiler_heaps.lock); - if (WARN_ON(!nr_in_flight) || - WARN_ON(pending_frag_count > nr_in_flight)) + if (WARN_ON(!nr_in_flight) || WARN_ON(pending_frag_count > nr_in_flight)) return -EINVAL; if (nr_in_flight <= heap->target_in_flight) { @@ -574,66 +879,446 @@ static int alloc_new_chunk(struct kbase_csf_tiler_heap *heap, /* Not exceeded the target number of render passes yet so be * generous with memory. */ - err = create_chunk(heap, false); - - if (likely(!err)) { - struct kbase_csf_tiler_heap_chunk *new_chunk = - get_last_chunk(heap); - if (!WARN_ON(!new_chunk)) { - *new_chunk_ptr = - encode_chunk_ptr(heap->chunk_size, - new_chunk->gpu_va); - return 0; - } - } + return 0; } else if (pending_frag_count > 0) { - err = -EBUSY; + return -EBUSY; } else { - err = -ENOMEM; + return -ENOMEM; } } else { /* Reached target number of render passes in flight. * Wait for some of them to finish */ - err = -EBUSY; + return -EBUSY; } - - return err; + return -ENOMEM; } int kbase_csf_tiler_heap_alloc_new_chunk(struct kbase_context *kctx, u64 gpu_heap_va, u32 nr_in_flight, u32 pending_frag_count, u64 *new_chunk_ptr) { struct kbase_csf_tiler_heap *heap; + struct kbase_csf_tiler_heap_chunk *chunk; int err = -EINVAL; + u64 chunk_size = 0; + u64 heap_id = 0; + + /* To avoid potential locking issues during allocation, this is handled + * in three phases: + * 1. Take the lock, find the corresponding heap, and find its chunk size + * (this is always 2 MB, but may change down the line). + * 2. Allocate memory for the chunk and its region. + * 3. If the heap still exists, link it to the end of the list. If it + * doesn't, roll back the allocation. + */ mutex_lock(&kctx->csf.tiler_heaps.lock); + heap = find_tiler_heap(kctx, gpu_heap_va); + if (likely(heap)) { + chunk_size = heap->chunk_size; + heap_id = heap->heap_id; + } else { + dev_err(kctx->kbdev->dev, "Heap 0x%llX does not exist", gpu_heap_va); + mutex_unlock(&kctx->csf.tiler_heaps.lock); + goto prelink_failure; + } + err = validate_allocation_request(heap, nr_in_flight, pending_frag_count); + if (unlikely(err)) { + dev_err(kctx->kbdev->dev, + "Not allocating new chunk for heap 0x%llX due to current heap state (err %d)", + gpu_heap_va, err); + mutex_unlock(&kctx->csf.tiler_heaps.lock); + goto prelink_failure; + } + mutex_unlock(&kctx->csf.tiler_heaps.lock); + /* this heap must not be used whilst we have dropped the lock */ + heap = NULL; + + chunk = alloc_new_chunk(kctx, chunk_size); + if (unlikely(!chunk)) { + dev_err(kctx->kbdev->dev, "Could not allocate chunk of size %lld for ctx %d_%d", + chunk_size, kctx->tgid, kctx->id); + goto prelink_failure; + } + + /* After this point, the heap that we were targeting could already have had the needed + * chunks allocated, if we were handling multiple OoM events on multiple threads, so + * we need to revalidate the need for the allocation. + */ + mutex_lock(&kctx->csf.tiler_heaps.lock); heap = find_tiler_heap(kctx, gpu_heap_va); - if (likely(heap)) { - err = alloc_new_chunk(heap, nr_in_flight, pending_frag_count, - new_chunk_ptr); - if (likely(!err)) { - /* update total and peak tiler heap memory record */ - kctx->running_total_tiler_heap_nr_chunks++; - kctx->running_total_tiler_heap_memory += heap->chunk_size; - - if (kctx->running_total_tiler_heap_memory > - kctx->peak_total_tiler_heap_memory) - kctx->peak_total_tiler_heap_memory = - kctx->running_total_tiler_heap_memory; - } - - KBASE_TLSTREAM_AUX_TILER_HEAP_STATS( - kctx->kbdev, kctx->id, heap->heap_id, - PFN_UP(heap->chunk_size * heap->max_chunks), - PFN_UP(heap->chunk_size * heap->chunk_count), - heap->max_chunks, heap->chunk_size, heap->chunk_count, - heap->target_in_flight, nr_in_flight); + if (unlikely(!heap)) { + dev_err(kctx->kbdev->dev, "Tiler heap 0x%llX no longer exists!\n", gpu_heap_va); + mutex_unlock(&kctx->csf.tiler_heaps.lock); + goto unroll_chunk; } + if (heap_id != heap->heap_id) { + dev_err(kctx->kbdev->dev, + "Tiler heap 0x%llX was removed from ctx %d_%d while allocating chunk of size %lld!", + gpu_heap_va, kctx->tgid, kctx->id, chunk_size); + mutex_unlock(&kctx->csf.tiler_heaps.lock); + goto unroll_chunk; + } + + if (WARN_ON(chunk_size != heap->chunk_size)) { + mutex_unlock(&kctx->csf.tiler_heaps.lock); + goto unroll_chunk; + } + + err = validate_allocation_request(heap, nr_in_flight, pending_frag_count); + if (unlikely(err)) { + dev_warn( + kctx->kbdev->dev, + "Aborting linking chunk to heap 0x%llX: heap state changed during allocation (err %d)", + gpu_heap_va, err); + mutex_unlock(&kctx->csf.tiler_heaps.lock); + goto unroll_chunk; + } + + err = init_chunk(heap, chunk, false); + + /* On error, the chunk would not be linked, so we can still treat it as an unlinked + * chunk for error handling. + */ + if (unlikely(err)) { + dev_err(kctx->kbdev->dev, + "Could not link chunk(0x%llX) with tiler heap 0%llX in ctx %d_%d due to error %d", + chunk->gpu_va, gpu_heap_va, kctx->tgid, kctx->id, err); + mutex_unlock(&kctx->csf.tiler_heaps.lock); + goto unroll_chunk; + } + + *new_chunk_ptr = encode_chunk_ptr(heap->chunk_size, chunk->gpu_va); + + /* update total and peak tiler heap memory record */ + kctx->running_total_tiler_heap_nr_chunks++; + kctx->running_total_tiler_heap_memory += heap->chunk_size; + + if (kctx->running_total_tiler_heap_memory > kctx->peak_total_tiler_heap_memory) + kctx->peak_total_tiler_heap_memory = kctx->running_total_tiler_heap_memory; + + KBASE_TLSTREAM_AUX_TILER_HEAP_STATS(kctx->kbdev, kctx->id, heap->heap_id, + PFN_UP(heap->chunk_size * heap->max_chunks), + PFN_UP(heap->chunk_size * heap->chunk_count), + heap->max_chunks, heap->chunk_size, heap->chunk_count, + heap->target_in_flight, nr_in_flight); + mutex_unlock(&kctx->csf.tiler_heaps.lock); + return err; +unroll_chunk: + remove_unlinked_chunk(kctx, chunk); +prelink_failure: return err; } + +static bool delete_chunk_physical_pages(struct kbase_csf_tiler_heap *heap, u64 chunk_gpu_va, + u64 *hdr_val) +{ + int err; + u64 *chunk_hdr; + struct kbase_context *kctx = heap->kctx; + struct kbase_csf_tiler_heap_chunk *chunk = NULL; + + lockdep_assert_held(&heap->kctx->csf.tiler_heaps.lock); + + chunk = find_chunk(heap, chunk_gpu_va); + if (unlikely(!chunk)) { + dev_warn(kctx->kbdev->dev, + "Failed to find tiler heap(0x%llX) chunk(0x%llX) for reclaim-delete\n", + heap->gpu_va, chunk_gpu_va); + return false; + } + + WARN((chunk->region->flags & KBASE_REG_CPU_CACHED), + "Cannot support CPU cached chunks without sync operations"); + chunk_hdr = chunk->map.addr; + *hdr_val = *chunk_hdr; + + dev_dbg(kctx->kbdev->dev, + "Reclaim: delete chunk(0x%llx) in heap(0x%llx), header value(0x%llX)\n", + chunk_gpu_va, heap->gpu_va, *hdr_val); + + err = kbase_mem_shrink_gpu_mapping(kctx, chunk->region, 0, chunk->region->gpu_alloc->nents); + if (unlikely(err)) { + dev_warn( + kctx->kbdev->dev, + "Reclaim: shrinking GPU mapping failed on chunk(0x%llx) in heap(0x%llx) (err %d)\n", + chunk_gpu_va, heap->gpu_va, err); + + /* Cannot free the pages whilst references on the GPU remain, so keep the chunk on + * the heap's chunk list and try a different heap. + */ + + return false; + } + /* Destroy the mapping before the physical pages which are mapped are destroyed. */ + kbase_vunmap(kctx, &chunk->map); + + err = kbase_free_phy_pages_helper(chunk->region->gpu_alloc, + chunk->region->gpu_alloc->nents); + if (unlikely(err)) { + dev_warn( + kctx->kbdev->dev, + "Reclaim: remove physical backing failed on chunk(0x%llx) in heap(0x%llx) (err %d), continuing with deferred removal\n", + chunk_gpu_va, heap->gpu_va, err); + + /* kbase_free_phy_pages_helper() should only fail on invalid input, and WARNs + * anyway, so continue instead of returning early. + * + * Indeed, we don't want to leave the chunk on the heap's chunk list whilst it has + * its mapping removed, as that could lead to problems. It's safest to instead + * continue with deferred destruction of the chunk. + */ + } + + dev_dbg(kctx->kbdev->dev, + "Reclaim: delete chunk(0x%llx) in heap(0x%llx), header value(0x%llX)\n", + chunk_gpu_va, heap->gpu_va, *hdr_val); + + mutex_lock(&heap->kctx->jit_evict_lock); + list_move(&chunk->region->jit_node, &kctx->jit_destroy_head); + mutex_unlock(&heap->kctx->jit_evict_lock); + + list_del(&chunk->link); + heap->chunk_count--; + kfree(chunk); + + return true; +} + +static void sanity_check_gpu_buffer_heap(struct kbase_csf_tiler_heap *heap, + struct kbase_csf_gpu_buffer_heap *desc) +{ + u64 first_hoarded_chunk_gpu_va = desc->pointer & CHUNK_ADDR_MASK; + + lockdep_assert_held(&heap->kctx->csf.tiler_heaps.lock); + + if (first_hoarded_chunk_gpu_va) { + struct kbase_csf_tiler_heap_chunk *chunk = + find_chunk(heap, first_hoarded_chunk_gpu_va); + + if (likely(chunk)) { + dev_dbg(heap->kctx->kbdev->dev, + "Buffer descriptor 0x%llX sanity check ok, HW reclaim allowed\n", + heap->buf_desc_va); + + heap->buf_desc_checked = true; + return; + } + } + /* If there is no match, defer the check to next time */ + dev_dbg(heap->kctx->kbdev->dev, "Buffer descriptor 0x%llX runtime sanity check deferred\n", + heap->buf_desc_va); +} + +static bool can_read_hw_gpu_buffer_heap(struct kbase_csf_tiler_heap *heap, u64 *chunk_gpu_va_ptr) +{ + struct kbase_context *kctx = heap->kctx; + + lockdep_assert_held(&kctx->csf.tiler_heaps.lock); + + /* Initialize the descriptor pointer value to 0 */ + *chunk_gpu_va_ptr = 0; + + /* The BufferDescriptor on heap is a hint on creation, do a sanity check at runtime */ + if (heap->buf_desc_reg && !heap->buf_desc_checked) { + struct kbase_csf_gpu_buffer_heap *desc = heap->buf_desc_map.addr; + + /* BufferDescriptor is supplied by userspace, so could be CPU-cached */ + if (heap->buf_desc_map.flags & KBASE_VMAP_FLAG_SYNC_NEEDED) + kbase_sync_mem_regions(kctx, &heap->buf_desc_map, KBASE_SYNC_TO_CPU); + + sanity_check_gpu_buffer_heap(heap, desc); + if (heap->buf_desc_checked) + *chunk_gpu_va_ptr = desc->pointer & CHUNK_ADDR_MASK; + } + + return heap->buf_desc_checked; +} + +static u32 delete_hoarded_chunks(struct kbase_csf_tiler_heap *heap) +{ + u32 freed = 0; + u64 chunk_gpu_va = 0; + struct kbase_context *kctx = heap->kctx; + struct kbase_csf_tiler_heap_chunk *chunk = NULL; + + lockdep_assert_held(&kctx->csf.tiler_heaps.lock); + + if (can_read_hw_gpu_buffer_heap(heap, &chunk_gpu_va)) { + u64 chunk_hdr_val; + u64 *hw_hdr; + + if (!chunk_gpu_va) { + struct kbase_csf_gpu_buffer_heap *desc = heap->buf_desc_map.addr; + + /* BufferDescriptor is supplied by userspace, so could be CPU-cached */ + if (heap->buf_desc_map.flags & KBASE_VMAP_FLAG_SYNC_NEEDED) + kbase_sync_mem_regions(kctx, &heap->buf_desc_map, + KBASE_SYNC_TO_CPU); + chunk_gpu_va = desc->pointer & CHUNK_ADDR_MASK; + + if (!chunk_gpu_va) { + dev_dbg(kctx->kbdev->dev, + "Buffer descriptor 0x%llX has no chunks (NULL) for reclaim scan\n", + heap->buf_desc_va); + goto out; + } + } + + chunk = find_chunk(heap, chunk_gpu_va); + if (unlikely(!chunk)) + goto out; + + WARN((chunk->region->flags & KBASE_REG_CPU_CACHED), + "Cannot support CPU cached chunks without sync operations"); + hw_hdr = chunk->map.addr; + + /* Move onto the next chunk relevant information */ + chunk_hdr_val = *hw_hdr; + chunk_gpu_va = chunk_hdr_val & CHUNK_ADDR_MASK; + + while (chunk_gpu_va && heap->chunk_count > HEAP_SHRINK_STOP_LIMIT) { + bool success = + delete_chunk_physical_pages(heap, chunk_gpu_va, &chunk_hdr_val); + + if (!success) + break; + + freed++; + /* On success, chunk_hdr_val is updated, extract the next chunk address */ + chunk_gpu_va = chunk_hdr_val & CHUNK_ADDR_MASK; + } + + /* Update the existing hardware chunk header, after reclaim deletion of chunks */ + *hw_hdr = chunk_hdr_val; + + dev_dbg(heap->kctx->kbdev->dev, + "HW reclaim scan freed chunks: %u, set hw_hdr[0]: 0x%llX\n", freed, + chunk_hdr_val); + } else { + dev_dbg(kctx->kbdev->dev, + "Skip HW reclaim scan, (disabled: buffer descriptor 0x%llX)\n", + heap->buf_desc_va); + } +out: + return freed; +} + +static u64 delete_unused_chunk_pages(struct kbase_csf_tiler_heap *heap) +{ + u32 freed_chunks = 0; + u64 freed_pages = 0; + u64 chunk_gpu_va; + u64 chunk_hdr_val; + struct kbase_context *kctx = heap->kctx; + u64 *ctx_ptr; + + lockdep_assert_held(&kctx->csf.tiler_heaps.lock); + + WARN(heap->gpu_va_map.flags & KBASE_VMAP_FLAG_SYNC_NEEDED, + "Cannot support CPU cached heap context without sync operations"); + + ctx_ptr = heap->gpu_va_map.addr; + + /* Extract the first chunk address from the context's free_list_head */ + chunk_hdr_val = *ctx_ptr; + chunk_gpu_va = chunk_hdr_val & CHUNK_ADDR_MASK; + + while (chunk_gpu_va) { + u64 hdr_val; + bool success = delete_chunk_physical_pages(heap, chunk_gpu_va, &hdr_val); + + if (!success) + break; + + freed_chunks++; + chunk_hdr_val = hdr_val; + /* extract the next chunk address */ + chunk_gpu_va = chunk_hdr_val & CHUNK_ADDR_MASK; + } + + /* Update the post-scan deletion to context header */ + *ctx_ptr = chunk_hdr_val; + + /* Try to scan the HW hoarded list of unused chunks */ + freed_chunks += delete_hoarded_chunks(heap); + freed_pages = freed_chunks * PFN_UP(heap->chunk_size); + dev_dbg(heap->kctx->kbdev->dev, + "Scan reclaim freed chunks/pages %u/%llu, set heap-ctx_u64[0]: 0x%llX\n", + freed_chunks, freed_pages, chunk_hdr_val); + + /* Update context tiler heaps memory usage */ + kctx->running_total_tiler_heap_memory -= freed_pages << PAGE_SHIFT; + kctx->running_total_tiler_heap_nr_chunks -= freed_chunks; + return freed_pages; +} + +u32 kbase_csf_tiler_heap_scan_kctx_unused_pages(struct kbase_context *kctx, u32 to_free) +{ + u64 freed = 0; + struct kbase_csf_tiler_heap *heap; + + mutex_lock(&kctx->csf.tiler_heaps.lock); + + list_for_each_entry(heap, &kctx->csf.tiler_heaps.list, link) { + freed += delete_unused_chunk_pages(heap); + + /* If freed enough, then stop here */ + if (freed >= to_free) + break; + } + + mutex_unlock(&kctx->csf.tiler_heaps.lock); + /* The scan is surely not more than 4-G pages, but for logic flow limit it */ + if (WARN_ON(unlikely(freed > U32_MAX))) + return U32_MAX; + else + return (u32)freed; +} + +static u64 count_unused_heap_pages(struct kbase_csf_tiler_heap *heap) +{ + u32 chunk_cnt = 0; + u64 page_cnt = 0; + + lockdep_assert_held(&heap->kctx->csf.tiler_heaps.lock); + + /* Here the count is basically an informed estimate, avoiding the costly mapping/unmaping + * in the chunk list walk. The downside is that the number is a less reliable guide for + * later on scan (free) calls on this heap for what actually is freeable. + */ + if (heap->chunk_count > HEAP_SHRINK_STOP_LIMIT) { + chunk_cnt = heap->chunk_count - HEAP_SHRINK_STOP_LIMIT; + page_cnt = chunk_cnt * PFN_UP(heap->chunk_size); + } + + dev_dbg(heap->kctx->kbdev->dev, + "Reclaim count chunks/pages %u/%llu (estimated), heap_va: 0x%llX\n", chunk_cnt, + page_cnt, heap->gpu_va); + + return page_cnt; +} + +u32 kbase_csf_tiler_heap_count_kctx_unused_pages(struct kbase_context *kctx) +{ + u64 page_cnt = 0; + struct kbase_csf_tiler_heap *heap; + + mutex_lock(&kctx->csf.tiler_heaps.lock); + + list_for_each_entry(heap, &kctx->csf.tiler_heaps.list, link) + page_cnt += count_unused_heap_pages(heap); + + mutex_unlock(&kctx->csf.tiler_heaps.lock); + + /* The count is surely not more than 4-G pages, but for logic flow limit it */ + if (WARN_ON(unlikely(page_cnt > U32_MAX))) + return U32_MAX; + else + return (u32)page_cnt; +} diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap.h index f4b80da68fe5..1b5cb560894f 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap.h @@ -23,7 +23,6 @@ #define _KBASE_CSF_TILER_HEAP_H_ #include - /** * kbase_csf_tiler_heap_context_init - Initialize the tiler heaps context for a * GPU address space @@ -58,6 +57,12 @@ void kbase_csf_tiler_heap_context_term(struct kbase_context *kctx); * @target_in_flight: Number of render-passes that the driver should attempt to * keep in flight for which allocation of new chunks is * allowed. Must not be zero. + * @buf_desc_va: Buffer descriptor GPU virtual address. This is a hint for + * indicating that the caller is intending to perform tiler heap + * chunks reclaim for those that are hoarded with hardware while + * the associated shader activites are suspended and the CSGs are + * off slots. If the referred reclaiming is not desired, can + * set it to 0. * @gpu_heap_va: Where to store the GPU virtual address of the context that was * set up for the tiler heap. * @first_chunk_va: Where to store the GPU virtual address of the first chunk @@ -66,10 +71,9 @@ void kbase_csf_tiler_heap_context_term(struct kbase_context *kctx); * * Return: 0 if successful or a negative error code on failure. */ -int kbase_csf_tiler_heap_init(struct kbase_context *kctx, - u32 chunk_size, u32 initial_chunks, u32 max_chunks, - u16 target_in_flight, u64 *gpu_heap_va, - u64 *first_chunk_va); +int kbase_csf_tiler_heap_init(struct kbase_context *kctx, u32 chunk_size, u32 initial_chunks, + u32 max_chunks, u16 target_in_flight, u64 const buf_desc_va, + u64 *gpu_heap_va, u64 *first_chunk_va); /** * kbase_csf_tiler_heap_term - Terminate a chunked tiler memory heap. @@ -112,4 +116,27 @@ int kbase_csf_tiler_heap_term(struct kbase_context *kctx, u64 gpu_heap_va); */ int kbase_csf_tiler_heap_alloc_new_chunk(struct kbase_context *kctx, u64 gpu_heap_va, u32 nr_in_flight, u32 pending_frag_count, u64 *new_chunk_ptr); + +/** + * kbase_csf_tiler_heap_scan_kctx_unused_pages - Performs the tiler heap shrinker calim's scan + * functionality. + * + * @kctx: Pointer to the kbase context for which the tiler heap recalim is to be + * operated with. + * @to_free: Number of pages suggested for the reclaim scan (free) method to reach. + * + * Return: the actual number of pages the scan method has freed from the call. + */ +u32 kbase_csf_tiler_heap_scan_kctx_unused_pages(struct kbase_context *kctx, u32 to_free); + +/** + * kbase_csf_tiler_heap_count_kctx_unused_pages - Performs the tiler heap shrinker calim's count + * functionality. + * + * @kctx: Pointer to the kbase context for which the tiler heap recalim is to be + * operated with. + * + * Return: a number of pages that could likely be freed on the subsequent scan method call. + */ +u32 kbase_csf_tiler_heap_count_kctx_unused_pages(struct kbase_context *kctx); #endif diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_def.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_def.h index 2c006d9dc9e4..96f2b03d2d31 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_def.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_def.h @@ -56,12 +56,20 @@ ((CHUNK_HDR_NEXT_ADDR_MASK >> CHUNK_HDR_NEXT_ADDR_POS) << \ CHUNK_HDR_NEXT_ADDR_ENCODE_SHIFT) +/* The size of the area needed to be vmapped prior to handing the tiler heap + * over to the tiler, so that the shrinker could be invoked. + */ +#define NEXT_CHUNK_ADDR_SIZE (sizeof(u64)) + /** * struct kbase_csf_tiler_heap_chunk - A tiler heap chunk managed by the kernel * * @link: Link to this chunk in a list of chunks belonging to a * @kbase_csf_tiler_heap. * @region: Pointer to the GPU memory region allocated for the chunk. + * @map: Kernel VA mapping so that we would not need to use vmap in the + * shrinker callback, which can allocate. This maps only the header + * of the chunk, so it could be traversed. * @gpu_va: GPU virtual address of the start of the memory region. * This points to the header of the chunk and not to the low address * of free memory within it. @@ -75,9 +83,12 @@ struct kbase_csf_tiler_heap_chunk { struct list_head link; struct kbase_va_region *region; + struct kbase_vmap_struct map; u64 gpu_va; }; +#define HEAP_BUF_DESCRIPTOR_CHECKED (1 << 0) + /** * struct kbase_csf_tiler_heap - A tiler heap managed by the kernel * @@ -85,6 +96,20 @@ struct kbase_csf_tiler_heap_chunk { * associated. * @link: Link to this heap in a list of tiler heaps belonging to * the @kbase_csf_tiler_heap_context. + * @chunks_list: Linked list of allocated chunks. + * @gpu_va: The GPU virtual address of the heap context structure that + * was allocated for the firmware. This is also used to + * uniquely identify the heap. + * @heap_id: Unique id representing the heap, assigned during heap + * initialization. + * @buf_desc_va: Buffer descriptor GPU VA. Can be 0 for backward compatible + * to earlier version base interfaces. + * @buf_desc_reg: Pointer to the VA region that covers the provided buffer + * descriptor memory object pointed to by buf_desc_va. + * @gpu_va_map: Kernel VA mapping of the GPU VA region. + * @buf_desc_map: Kernel VA mapping of the buffer descriptor, read from + * during the tiler heap shrinker. Sync operations may need + * to be done before each read. * @chunk_size: Size of each chunk, in bytes. Must be page-aligned. * @chunk_count: The number of chunks currently allocated. Must not be * zero or greater than @max_chunks. @@ -93,22 +118,23 @@ struct kbase_csf_tiler_heap_chunk { * @target_in_flight: Number of render-passes that the driver should attempt * to keep in flight for which allocation of new chunks is * allowed. Must not be zero. - * @gpu_va: The GPU virtual address of the heap context structure that - * was allocated for the firmware. This is also used to - * uniquely identify the heap. - * @heap_id: Unique id representing the heap, assigned during heap - * initialization. - * @chunks_list: Linked list of allocated chunks. + * @buf_desc_checked: Indicates if runtime check on buffer descriptor has been done. */ struct kbase_csf_tiler_heap { struct kbase_context *kctx; struct list_head link; + struct list_head chunks_list; + u64 gpu_va; + u64 heap_id; + u64 buf_desc_va; + struct kbase_va_region *buf_desc_reg; + struct kbase_vmap_struct buf_desc_map; + struct kbase_vmap_struct gpu_va_map; u32 chunk_size; u32 chunk_count; u32 max_chunks; u16 target_in_flight; - u64 gpu_va; - u64 heap_id; - struct list_head chunks_list; + bool buf_desc_checked; }; + #endif /* !_KBASE_CSF_TILER_HEAP_DEF_H_ */ diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_reclaim.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_reclaim.c new file mode 100644 index 000000000000..bcab31d27945 --- /dev/null +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_reclaim.c @@ -0,0 +1,367 @@ +// 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_csf.h" +#include "mali_kbase_csf_tiler_heap.h" +#include "mali_kbase_csf_tiler_heap_reclaim.h" + +/* Tiler heap shrinker seek value, needs to be higher than jit and memory pools */ +#define HEAP_SHRINKER_SEEKS (DEFAULT_SEEKS + 2) + +/* Tiler heap shrinker batch value */ +#define HEAP_SHRINKER_BATCH (512) + +/* Tiler heap reclaim scan (free) method size for limiting a scan run length */ +#define HEAP_RECLAIM_SCAN_BATCH_SIZE (HEAP_SHRINKER_BATCH << 7) + +static u8 get_kctx_highest_csg_priority(struct kbase_context *kctx) +{ + u8 prio; + + for (prio = KBASE_QUEUE_GROUP_PRIORITY_REALTIME; prio < KBASE_QUEUE_GROUP_PRIORITY_LOW; + prio++) + if (!list_empty(&kctx->csf.sched.runnable_groups[prio])) + break; + + if (prio != KBASE_QUEUE_GROUP_PRIORITY_REALTIME && kctx->csf.sched.num_idle_wait_grps) { + struct kbase_queue_group *group; + + list_for_each_entry(group, &kctx->csf.sched.idle_wait_groups, link) { + if (group->priority < prio) + prio = group->priority; + } + } + + return prio; +} + +static void detach_ctx_from_heap_reclaim_mgr(struct kbase_context *kctx) +{ + struct kbase_csf_scheduler *const scheduler = &kctx->kbdev->csf.scheduler; + struct kbase_csf_ctx_heap_reclaim_info *info = &kctx->csf.sched.heap_info; + + lockdep_assert_held(&scheduler->lock); + + if (!list_empty(&info->mgr_link)) { + u32 remaining = (info->nr_est_unused_pages > info->nr_freed_pages) ? + info->nr_est_unused_pages - info->nr_freed_pages : + 0; + + list_del_init(&info->mgr_link); + if (remaining) + WARN_ON(atomic_sub_return(remaining, &scheduler->reclaim_mgr.unused_pages) < + 0); + + dev_dbg(kctx->kbdev->dev, + "Reclaim_mgr_detach: ctx_%d_%d, est_pages=0%u, freed_pages=%u", kctx->tgid, + kctx->id, info->nr_est_unused_pages, info->nr_freed_pages); + } +} + +static void attach_ctx_to_heap_reclaim_mgr(struct kbase_context *kctx) +{ + struct kbase_csf_ctx_heap_reclaim_info *const info = &kctx->csf.sched.heap_info; + struct kbase_csf_scheduler *const scheduler = &kctx->kbdev->csf.scheduler; + u8 const prio = get_kctx_highest_csg_priority(kctx); + + lockdep_assert_held(&scheduler->lock); + + if (WARN_ON(!list_empty(&info->mgr_link))) + list_del_init(&info->mgr_link); + + /* Count the pages that could be freed */ + info->nr_est_unused_pages = kbase_csf_tiler_heap_count_kctx_unused_pages(kctx); + /* Initialize the scan operation tracking pages */ + info->nr_freed_pages = 0; + + list_add_tail(&info->mgr_link, &scheduler->reclaim_mgr.ctx_lists[prio]); + /* Accumulate the estimated pages to the manager total field */ + atomic_add(info->nr_est_unused_pages, &scheduler->reclaim_mgr.unused_pages); + + dev_dbg(kctx->kbdev->dev, "Reclaim_mgr_attach: ctx_%d_%d, est_count_pages=%u", kctx->tgid, + kctx->id, info->nr_est_unused_pages); +} + +void kbase_csf_tiler_heap_reclaim_sched_notify_grp_active(struct kbase_queue_group *group) +{ + struct kbase_context *kctx = group->kctx; + struct kbase_csf_ctx_heap_reclaim_info *info = &kctx->csf.sched.heap_info; + + lockdep_assert_held(&kctx->kbdev->csf.scheduler.lock); + + info->on_slot_grps++; + /* If the kctx has an on-slot change from 0 => 1, detach it from reclaim_mgr */ + if (info->on_slot_grps == 1) { + dev_dbg(kctx->kbdev->dev, "CSG_%d_%d_%d on-slot, remove kctx from reclaim manager", + group->kctx->tgid, group->kctx->id, group->handle); + + detach_ctx_from_heap_reclaim_mgr(kctx); + } +} + +void kbase_csf_tiler_heap_reclaim_sched_notify_grp_evict(struct kbase_queue_group *group) +{ + struct kbase_context *kctx = group->kctx; + struct kbase_csf_ctx_heap_reclaim_info *const info = &kctx->csf.sched.heap_info; + struct kbase_csf_scheduler *const scheduler = &kctx->kbdev->csf.scheduler; + const u32 num_groups = kctx->kbdev->csf.global_iface.group_num; + u32 on_slot_grps = 0; + u32 i; + + lockdep_assert_held(&scheduler->lock); + + /* Group eviction from the scheduler is a bit more complex, but fairly less + * frequent in operations. Taking the opportunity to actually count the + * on-slot CSGs from the given kctx, for robustness and clearer code logic. + */ + 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 *grp = csg_slot->resident_group; + + if (unlikely(!grp)) + continue; + + if (grp->kctx == kctx) + on_slot_grps++; + } + + info->on_slot_grps = on_slot_grps; + + /* If the kctx has no other CSGs on-slot, handle the heap reclaim related actions */ + if (!info->on_slot_grps) { + if (kctx->csf.sched.num_runnable_grps || kctx->csf.sched.num_idle_wait_grps) { + /* The kctx has other operational CSGs, attach it if not yet done */ + if (list_empty(&info->mgr_link)) { + dev_dbg(kctx->kbdev->dev, + "CSG_%d_%d_%d evict, add kctx to reclaim manager", + group->kctx->tgid, group->kctx->id, group->handle); + + attach_ctx_to_heap_reclaim_mgr(kctx); + } + } else { + /* The kctx is a zombie after the group eviction, drop it out */ + dev_dbg(kctx->kbdev->dev, + "CSG_%d_%d_%d evict leading to zombie kctx, dettach from reclaim manager", + group->kctx->tgid, group->kctx->id, group->handle); + + detach_ctx_from_heap_reclaim_mgr(kctx); + } + } +} + +void kbase_csf_tiler_heap_reclaim_sched_notify_grp_suspend(struct kbase_queue_group *group) +{ + struct kbase_context *kctx = group->kctx; + struct kbase_csf_ctx_heap_reclaim_info *info = &kctx->csf.sched.heap_info; + + lockdep_assert_held(&kctx->kbdev->csf.scheduler.lock); + + if (!WARN_ON(info->on_slot_grps == 0)) + info->on_slot_grps--; + /* If the kctx has no CSGs on-slot, attach it to scheduler's reclaim manager */ + if (info->on_slot_grps == 0) { + dev_dbg(kctx->kbdev->dev, "CSG_%d_%d_%d off-slot, add kctx to reclaim manager", + group->kctx->tgid, group->kctx->id, group->handle); + + attach_ctx_to_heap_reclaim_mgr(kctx); + } +} + +static unsigned long reclaim_unused_heap_pages(struct kbase_device *kbdev) +{ + struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; + struct kbase_csf_sched_heap_reclaim_mgr *const mgr = &scheduler->reclaim_mgr; + unsigned long total_freed_pages = 0; + int prio; + + lockdep_assert_held(&kbdev->csf.scheduler.lock); + + for (prio = KBASE_QUEUE_GROUP_PRIORITY_LOW; + total_freed_pages < HEAP_RECLAIM_SCAN_BATCH_SIZE && + prio >= KBASE_QUEUE_GROUP_PRIORITY_REALTIME; + prio--) { + struct kbase_csf_ctx_heap_reclaim_info *info, *tmp; + u32 cnt_ctxs = 0; + + list_for_each_entry_safe(info, tmp, &scheduler->reclaim_mgr.ctx_lists[prio], + mgr_link) { + struct kbase_context *kctx = + container_of(info, struct kbase_context, csf.sched.heap_info); + u32 freed_pages = kbase_csf_tiler_heap_scan_kctx_unused_pages( + kctx, info->nr_est_unused_pages); + + if (freed_pages) { + /* Remove the freed pages from the manager retained estimate. The + * accumulated removals from the kctx should not exceed the kctx + * initially notified contribution amount: + * info->nr_est_unused_pages. + */ + u32 rm_cnt = MIN(info->nr_est_unused_pages - info->nr_freed_pages, + freed_pages); + + WARN_ON(atomic_sub_return(rm_cnt, &mgr->unused_pages) < 0); + + /* tracking the freed pages, before a potential detach call */ + info->nr_freed_pages += freed_pages; + total_freed_pages += freed_pages; + + schedule_work(&kctx->jit_work); + } + + /* If the kctx can't offer anymore, drop it from the reclaim manger, + * otherwise leave it remaining in. If the kctx changes its state (i.e. + * some CSGs becoming on-slot), the scheduler will pull it out. + */ + if (info->nr_freed_pages >= info->nr_est_unused_pages || freed_pages == 0) + detach_ctx_from_heap_reclaim_mgr(kctx); + + cnt_ctxs++; + + /* Enough has been freed, break to avoid holding the lock too long */ + if (total_freed_pages >= HEAP_RECLAIM_SCAN_BATCH_SIZE) + break; + } + + dev_dbg(kbdev->dev, "Reclaim free heap pages: %lu (cnt_ctxs: %u, prio: %d)", + total_freed_pages, cnt_ctxs, prio); + } + + dev_dbg(kbdev->dev, "Reclaim free total heap pages: %lu (across all CSG priority)", + total_freed_pages); + + return total_freed_pages; +} + +static unsigned long kbase_csf_tiler_heap_reclaim_count_free_pages(struct kbase_device *kbdev, + struct shrink_control *sc) +{ + struct kbase_csf_sched_heap_reclaim_mgr *mgr = &kbdev->csf.scheduler.reclaim_mgr; + unsigned long page_cnt = atomic_read(&mgr->unused_pages); + + dev_dbg(kbdev->dev, "Reclaim count unused pages (estimate): %lu", page_cnt); + + return page_cnt; +} + +static unsigned long kbase_csf_tiler_heap_reclaim_scan_free_pages(struct kbase_device *kbdev, + struct shrink_control *sc) +{ + struct kbase_csf_sched_heap_reclaim_mgr *mgr = &kbdev->csf.scheduler.reclaim_mgr; + unsigned long freed = 0; + unsigned long avail = 0; + + /* If Scheduler is busy in action, return 0 */ + if (!mutex_trylock(&kbdev->csf.scheduler.lock)) { + struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; + + /* Wait for roughly 2-ms */ + wait_event_timeout(kbdev->csf.event_wait, (scheduler->state != SCHED_BUSY), + msecs_to_jiffies(2)); + if (!mutex_trylock(&kbdev->csf.scheduler.lock)) { + dev_dbg(kbdev->dev, "Tiler heap reclaim scan see device busy (freed: 0)"); + return 0; + } + } + + avail = atomic_read(&mgr->unused_pages); + if (avail) + freed = reclaim_unused_heap_pages(kbdev); + + mutex_unlock(&kbdev->csf.scheduler.lock); + +#if (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE) + if (freed > sc->nr_to_scan) + sc->nr_scanned = freed; +#endif /* (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE) */ + + dev_info(kbdev->dev, "Tiler heap reclaim scan freed pages: %lu (unused: %lu)", freed, + avail); + + /* On estimate suggesting available, yet actual free failed, return STOP */ + if (avail && !freed) + return SHRINK_STOP; + else + return freed; +} + +static unsigned long kbase_csf_tiler_heap_reclaim_count_objects(struct shrinker *s, + struct shrink_control *sc) +{ + struct kbase_device *kbdev = + container_of(s, struct kbase_device, csf.scheduler.reclaim_mgr.heap_reclaim); + + return kbase_csf_tiler_heap_reclaim_count_free_pages(kbdev, sc); +} + +static unsigned long kbase_csf_tiler_heap_reclaim_scan_objects(struct shrinker *s, + struct shrink_control *sc) +{ + struct kbase_device *kbdev = + container_of(s, struct kbase_device, csf.scheduler.reclaim_mgr.heap_reclaim); + + return kbase_csf_tiler_heap_reclaim_scan_free_pages(kbdev, sc); +} + +void kbase_csf_tiler_heap_reclaim_ctx_init(struct kbase_context *kctx) +{ + /* Per-kctx heap_info object initialization */ + memset(&kctx->csf.sched.heap_info, 0, sizeof(struct kbase_csf_ctx_heap_reclaim_info)); + INIT_LIST_HEAD(&kctx->csf.sched.heap_info.mgr_link); +} + +void kbase_csf_tiler_heap_reclaim_mgr_init(struct kbase_device *kbdev) +{ + struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; + struct shrinker *reclaim = &scheduler->reclaim_mgr.heap_reclaim; + u8 prio; + + for (prio = KBASE_QUEUE_GROUP_PRIORITY_REALTIME; prio < KBASE_QUEUE_GROUP_PRIORITY_COUNT; + prio++) + INIT_LIST_HEAD(&scheduler->reclaim_mgr.ctx_lists[prio]); + + atomic_set(&scheduler->reclaim_mgr.unused_pages, 0); + + reclaim->count_objects = kbase_csf_tiler_heap_reclaim_count_objects; + reclaim->scan_objects = kbase_csf_tiler_heap_reclaim_scan_objects; + reclaim->seeks = HEAP_SHRINKER_SEEKS; + reclaim->batch = HEAP_SHRINKER_BATCH; + +#if !defined(CONFIG_MALI_VECTOR_DUMP) + register_shrinker(reclaim); +#endif +} + +void kbase_csf_tiler_heap_reclaim_mgr_term(struct kbase_device *kbdev) +{ + struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; + u8 prio; + +#if !defined(CONFIG_MALI_VECTOR_DUMP) + unregister_shrinker(&scheduler->reclaim_mgr.heap_reclaim); +#endif + + for (prio = KBASE_QUEUE_GROUP_PRIORITY_REALTIME; prio < KBASE_QUEUE_GROUP_PRIORITY_COUNT; + prio++) + WARN_ON(!list_empty(&scheduler->reclaim_mgr.ctx_lists[prio])); + + WARN_ON(atomic_read(&scheduler->reclaim_mgr.unused_pages)); +} diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_reclaim.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_reclaim.h new file mode 100644 index 000000000000..b6e580e48df6 --- /dev/null +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tiler_heap_reclaim.h @@ -0,0 +1,80 @@ +/* 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 _KBASE_CSF_TILER_HEAP_RECLAIM_H_ +#define _KBASE_CSF_TILER_HEAP_RECLAIM_H_ + +#include + +/** + * kbase_csf_tiler_heap_reclaim_sched_notify_grp_active - Notifier function for the scheduler + * to use when a group is put on-slot. + * + * @group: Pointer to the group object that has been placed on-slot for running. + * + */ +void kbase_csf_tiler_heap_reclaim_sched_notify_grp_active(struct kbase_queue_group *group); + +/** + * kbase_csf_tiler_heap_reclaim_sched_notify_grp_evict - Notifier function for the scheduler + * to use when a group is evicted out of the schedulder's scope, i.e no run of + * the group is possible afterwards. + * + * @group: Pointer to the group object that has been evicted. + * + */ +void kbase_csf_tiler_heap_reclaim_sched_notify_grp_evict(struct kbase_queue_group *group); + +/** + * kbase_csf_tiler_heap_reclaim_sched_notify_grp_suspend - Notifier function for the scheduler + * to use when a group is suspended from running, but could resume in future. + * + * @group: Pointer to the group object that is in suspended state. + * + */ +void kbase_csf_tiler_heap_reclaim_sched_notify_grp_suspend(struct kbase_queue_group *group); + +/** + * kbase_csf_tiler_heap_reclaim_ctx_init - Initializer on per context data fields for use + * with the tiler heap reclaim manager. + * + * @kctx: Pointer to the kbase_context. + * + */ +void kbase_csf_tiler_heap_reclaim_ctx_init(struct kbase_context *kctx); + +/** + * kbase_csf_tiler_heap_reclaim_mgr_init - Initializer for the tiler heap reclaim manger. + * + * @kbdev: Pointer to the device. + * + */ +void kbase_csf_tiler_heap_reclaim_mgr_init(struct kbase_device *kbdev); + +/** + * kbase_csf_tiler_heap_reclaim_mgr_term - Termination call for the tiler heap reclaim manger. + * + * @kbdev: Pointer to the device. + * + */ +void kbase_csf_tiler_heap_reclaim_mgr_term(struct kbase_device *kbdev); + +#endif diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tl_reader.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tl_reader.c index 6ae1029ab123..71ec91e3de03 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tl_reader.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_tl_reader.c @@ -88,13 +88,11 @@ DEFINE_DEBUGFS_ATTRIBUTE(kbase_csf_tl_poll_interval_fops, kbase_csf_tl_debugfs_poll_interval_read, kbase_csf_tl_debugfs_poll_interval_write, "%llu\n"); - void kbase_csf_tl_reader_debugfs_init(struct kbase_device *kbdev) { debugfs_create_file("csf_tl_poll_interval_in_ms", 0644, kbdev->debugfs_instr_directory, kbdev, &kbase_csf_tl_poll_interval_fops); - } #endif @@ -166,11 +164,10 @@ static int kbase_ts_converter_init( * * Return: The CPU timestamp. */ -static void __maybe_unused -kbase_ts_converter_convert(const struct kbase_ts_converter *self, u64 *gpu_ts) +static u64 __maybe_unused +kbase_ts_converter_convert(const struct kbase_ts_converter *self, u64 gpu_ts) { - u64 old_gpu_ts = *gpu_ts; - *gpu_ts = div64_u64(old_gpu_ts * self->multiplier, self->divisor) + + return div64_u64(gpu_ts * self->multiplier, self->divisor) + self->offset; } @@ -250,7 +247,6 @@ static void tl_reader_reset(struct kbase_csf_tl_reader *self) self->tl_header.btc = 0; } - int kbase_csf_tl_reader_flush_buffer(struct kbase_csf_tl_reader *self) { int ret = 0; @@ -275,7 +271,6 @@ int kbase_csf_tl_reader_flush_buffer(struct kbase_csf_tl_reader *self) return -EBUSY; } - /* Copying the whole buffer in a single shot. We assume * that the buffer will not contain partially written messages. */ @@ -326,8 +321,8 @@ int kbase_csf_tl_reader_flush_buffer(struct kbase_csf_tl_reader *self) { struct kbase_csffw_tl_message *msg = (struct kbase_csffw_tl_message *) csffw_data_it; - kbase_ts_converter_convert(&self->ts_converter, - &msg->timestamp); + msg->timestamp = kbase_ts_converter_convert(&self->ts_converter, + msg->timestamp); } /* Copy the message out to the tl_stream. */ diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_trace_buffer.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_trace_buffer.c index 23202c87a404..46872f937dbf 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_trace_buffer.c +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_trace_buffer.c @@ -119,7 +119,7 @@ static const struct firmware_trace_buffer_data trace_buffer_data[] = { #if MALI_UNIT_TEST { "fwutf", { 0 }, 1 }, #endif - { FW_TRACE_BUF_NAME, { 0 }, 4 }, + { FIRMWARE_LOG_BUF_NAME, { 0 }, 4 }, { "benchmark", { 0 }, 2 }, { "timeline", { 0 }, KBASE_CSF_TL_BUFFER_NR_PAGES }, }; @@ -506,10 +506,16 @@ unsigned int kbase_csf_firmware_trace_buffer_read_data( } EXPORT_SYMBOL(kbase_csf_firmware_trace_buffer_read_data); -#if IS_ENABLED(CONFIG_DEBUG_FS) +static void update_trace_buffer_active_mask64(struct firmware_trace_buffer *tb, u64 mask) +{ + unsigned int i; + + for (i = 0; i < tb->trace_enable_entry_count; i++) + kbasep_csf_firmware_trace_buffer_update_trace_enable_bit(tb, i, (mask >> i) & 1); +} #define U32_BITS 32 -static u64 get_trace_buffer_active_mask64(struct firmware_trace_buffer *tb) +u64 kbase_csf_firmware_trace_buffer_get_active_mask64(struct firmware_trace_buffer *tb) { u64 active_mask = tb->trace_enable_init_mask[0]; @@ -519,18 +525,7 @@ static u64 get_trace_buffer_active_mask64(struct firmware_trace_buffer *tb) return active_mask; } -static void update_trace_buffer_active_mask64(struct firmware_trace_buffer *tb, - u64 mask) -{ - unsigned int i; - - for (i = 0; i < tb->trace_enable_entry_count; i++) - kbasep_csf_firmware_trace_buffer_update_trace_enable_bit( - tb, i, (mask >> i) & 1); -} - -static int set_trace_buffer_active_mask64(struct firmware_trace_buffer *tb, - u64 mask) +int kbase_csf_firmware_trace_buffer_set_active_mask64(struct firmware_trace_buffer *tb, u64 mask) { struct kbase_device *kbdev = tb->kbdev; unsigned long flags; @@ -558,123 +553,3 @@ static int set_trace_buffer_active_mask64(struct firmware_trace_buffer *tb, return err; } - -static int kbase_csf_firmware_trace_enable_mask_read(void *data, u64 *val) -{ - struct kbase_device *kbdev = (struct kbase_device *)data; - struct firmware_trace_buffer *tb = - kbase_csf_firmware_get_trace_buffer(kbdev, FW_TRACE_BUF_NAME); - - if (tb == NULL) { - dev_err(kbdev->dev, "Couldn't get the firmware trace buffer"); - return -EIO; - } - /* The enabled traces limited to u64 here, regarded practical */ - *val = get_trace_buffer_active_mask64(tb); - return 0; -} - -static int kbase_csf_firmware_trace_enable_mask_write(void *data, u64 val) -{ - struct kbase_device *kbdev = (struct kbase_device *)data; - struct firmware_trace_buffer *tb = - kbase_csf_firmware_get_trace_buffer(kbdev, FW_TRACE_BUF_NAME); - u64 new_mask; - unsigned int enable_bits_count; - - if (tb == NULL) { - dev_err(kbdev->dev, "Couldn't get the firmware trace buffer"); - return -EIO; - } - - /* Ignore unsupported types */ - enable_bits_count = - kbase_csf_firmware_trace_buffer_get_trace_enable_bits_count(tb); - if (enable_bits_count > 64) { - dev_dbg(kbdev->dev, "Limit enabled bits count from %u to 64", - enable_bits_count); - enable_bits_count = 64; - } - new_mask = val & ((1 << enable_bits_count) - 1); - - if (new_mask != get_trace_buffer_active_mask64(tb)) - return set_trace_buffer_active_mask64(tb, new_mask); - else - return 0; -} - -static int kbasep_csf_firmware_trace_debugfs_open(struct inode *in, - struct file *file) -{ - struct kbase_device *kbdev = in->i_private; - - file->private_data = kbdev; - dev_dbg(kbdev->dev, "Opened firmware trace buffer dump debugfs file"); - - return 0; -} - -static ssize_t kbasep_csf_firmware_trace_debugfs_read(struct file *file, - char __user *buf, size_t size, loff_t *ppos) -{ - struct kbase_device *kbdev = file->private_data; - u8 *pbyte; - unsigned int n_read; - unsigned long not_copied; - /* Limit the kernel buffer to no more than two pages */ - size_t mem = MIN(size, 2 * PAGE_SIZE); - unsigned long flags; - - struct firmware_trace_buffer *tb = - kbase_csf_firmware_get_trace_buffer(kbdev, FW_TRACE_BUF_NAME); - - if (tb == NULL) { - dev_err(kbdev->dev, "Couldn't get the firmware trace buffer"); - return -EIO; - } - - pbyte = kmalloc(mem, GFP_KERNEL); - if (pbyte == NULL) { - dev_err(kbdev->dev, "Couldn't allocate memory for trace buffer dump"); - return -ENOMEM; - } - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - n_read = kbase_csf_firmware_trace_buffer_read_data(tb, pbyte, mem); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - /* Do the copy, if we have obtained some trace data */ - not_copied = (n_read) ? copy_to_user(buf, pbyte, n_read) : 0; - kfree(pbyte); - - if (!not_copied) { - *ppos += n_read; - return n_read; - } - - dev_err(kbdev->dev, "Couldn't copy trace buffer data to user space buffer"); - return -EFAULT; -} - -DEFINE_DEBUGFS_ATTRIBUTE(kbase_csf_firmware_trace_enable_mask_fops, - kbase_csf_firmware_trace_enable_mask_read, - kbase_csf_firmware_trace_enable_mask_write, "%llx\n"); - -static const struct file_operations kbasep_csf_firmware_trace_debugfs_fops = { - .owner = THIS_MODULE, - .open = kbasep_csf_firmware_trace_debugfs_open, - .read = kbasep_csf_firmware_trace_debugfs_read, - .llseek = no_llseek, -}; - -void kbase_csf_firmware_trace_buffer_debugfs_init(struct kbase_device *kbdev) -{ - debugfs_create_file("fw_trace_enable_mask", 0644, - kbdev->mali_debugfs_directory, kbdev, - &kbase_csf_firmware_trace_enable_mask_fops); - - debugfs_create_file("fw_traces", 0444, - kbdev->mali_debugfs_directory, kbdev, - &kbasep_csf_firmware_trace_debugfs_fops); -} -#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_trace_buffer.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_trace_buffer.h index a28d0f057700..0389d093a904 100644 --- a/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_trace_buffer.h +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_csf_trace_buffer.h @@ -25,7 +25,7 @@ #include #define CSF_FIRMWARE_TRACE_ENABLE_INIT_MASK_MAX (4) -#define FW_TRACE_BUF_NAME "fwlog" +#define FIRMWARE_LOG_BUF_NAME "fwlog" /* Forward declarations */ struct firmware_trace_buffer; @@ -165,14 +165,23 @@ bool kbase_csf_firmware_trace_buffer_is_empty( unsigned int kbase_csf_firmware_trace_buffer_read_data( struct firmware_trace_buffer *trace_buffer, u8 *data, unsigned int num_bytes); -#if IS_ENABLED(CONFIG_DEBUG_FS) /** - * kbase_csf_firmware_trace_buffer_debugfs_init() - Add debugfs entries for - * setting enable mask and dumping the binary firmware trace buffer + * kbase_csf_firmware_trace_buffer_get_active_mask64 - Get trace buffer active mask * - * @kbdev: Pointer to the device + * @tb: Trace buffer handle + * + * Return: Trace buffer active mask. */ -void kbase_csf_firmware_trace_buffer_debugfs_init(struct kbase_device *kbdev); -#endif /* CONFIG_DEBUG_FS */ +u64 kbase_csf_firmware_trace_buffer_get_active_mask64(struct firmware_trace_buffer *tb); + +/** + * kbase_csf_firmware_trace_buffer_set_active_mask64 - Set trace buffer active mask + * + * @tb: Trace buffer handle + * @mask: New active mask + * + * Return: 0 if successful, negative error code on failure. + */ +int kbase_csf_firmware_trace_buffer_set_active_mask64(struct firmware_trace_buffer *tb, u64 mask); #endif /* _KBASE_CSF_TRACE_BUFFER_H_ */ diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_debug_csf_fault.c b/drivers/gpu/arm/bifrost/csf/mali_kbase_debug_csf_fault.c new file mode 100644 index 000000000000..185779c16815 --- /dev/null +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_debug_csf_fault.c @@ -0,0 +1,271 @@ +// 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 + +#if IS_ENABLED(CONFIG_DEBUG_FS) + +/** + * kbasep_fault_occurred - Check if fault occurred. + * + * @kbdev: Device pointer + * + * Return: true if a fault occurred. + */ +static bool kbasep_fault_occurred(struct kbase_device *kbdev) +{ + unsigned long flags; + bool ret; + + spin_lock_irqsave(&kbdev->csf.dof.lock, flags); + ret = (kbdev->csf.dof.error_code != DF_NO_ERROR); + spin_unlock_irqrestore(&kbdev->csf.dof.lock, flags); + + return ret; +} + +void kbase_debug_csf_fault_wait_completion(struct kbase_device *kbdev) +{ + if (likely(!kbase_debug_csf_fault_dump_enabled(kbdev))) { + dev_dbg(kbdev->dev, "No userspace client for dumping exists"); + return; + } + + wait_event(kbdev->csf.dof.dump_wait_wq, kbase_debug_csf_fault_dump_complete(kbdev)); +} +KBASE_EXPORT_TEST_API(kbase_debug_csf_fault_wait_completion); + +/** + * kbase_debug_csf_fault_wakeup - Wake up a waiting user space client. + * + * @kbdev: Kbase device + */ +static void kbase_debug_csf_fault_wakeup(struct kbase_device *kbdev) +{ + wake_up_interruptible(&kbdev->csf.dof.fault_wait_wq); +} + +bool kbase_debug_csf_fault_notify(struct kbase_device *kbdev, + struct kbase_context *kctx, enum dumpfault_error_type error) +{ + unsigned long flags; + + if (likely(!kbase_debug_csf_fault_dump_enabled(kbdev))) + return false; + + if (WARN_ON(error == DF_NO_ERROR)) + return false; + + if (kctx && kbase_ctx_flag(kctx, KCTX_DYING)) { + dev_info(kbdev->dev, "kctx %d_%d is dying when error %d is reported", + kctx->tgid, kctx->id, error); + kctx = NULL; + } + + spin_lock_irqsave(&kbdev->csf.dof.lock, flags); + + /* Only one fault at a time can be processed */ + if (kbdev->csf.dof.error_code) { + dev_info(kbdev->dev, "skip this fault as there's a pending fault"); + goto unlock; + } + + kbdev->csf.dof.kctx_tgid = kctx ? kctx->tgid : 0; + kbdev->csf.dof.kctx_id = kctx ? kctx->id : 0; + kbdev->csf.dof.error_code = error; + kbase_debug_csf_fault_wakeup(kbdev); + +unlock: + spin_unlock_irqrestore(&kbdev->csf.dof.lock, flags); + return true; +} + +static ssize_t debug_csf_fault_read(struct file *file, char __user *buffer, size_t size, + loff_t *f_pos) +{ +#define BUF_SIZE 64 + struct kbase_device *kbdev; + unsigned long flags; + int count; + char buf[BUF_SIZE]; + u32 tgid, ctx_id; + enum dumpfault_error_type error_code; + + if (unlikely(!file)) { + pr_warn("%s: file is NULL", __func__); + return -EINVAL; + } + + kbdev = file->private_data; + if (unlikely(!buffer)) { + dev_warn(kbdev->dev, "%s: buffer is NULL", __func__); + return -EINVAL; + } + + if (unlikely(*f_pos < 0)) { + dev_warn(kbdev->dev, "%s: f_pos is negative", __func__); + return -EINVAL; + } + + if (size < sizeof(buf)) { + dev_warn(kbdev->dev, "%s: buffer is too small", __func__); + return -EINVAL; + } + + if (wait_event_interruptible(kbdev->csf.dof.fault_wait_wq, kbasep_fault_occurred(kbdev))) + return -ERESTARTSYS; + + spin_lock_irqsave(&kbdev->csf.dof.lock, flags); + tgid = kbdev->csf.dof.kctx_tgid; + ctx_id = kbdev->csf.dof.kctx_id; + error_code = kbdev->csf.dof.error_code; + BUILD_BUG_ON(sizeof(buf) < (sizeof(tgid) + sizeof(ctx_id) + sizeof(error_code))); + count = scnprintf(buf, sizeof(buf), "%u_%u_%u\n", tgid, ctx_id, error_code); + spin_unlock_irqrestore(&kbdev->csf.dof.lock, flags); + + dev_info(kbdev->dev, "debug csf fault info read"); + return simple_read_from_buffer(buffer, size, f_pos, buf, count); +} + +static int debug_csf_fault_open(struct inode *in, struct file *file) +{ + struct kbase_device *kbdev; + + if (unlikely(!in)) { + pr_warn("%s: inode is NULL", __func__); + return -EINVAL; + } + + kbdev = in->i_private; + if (unlikely(!file)) { + dev_warn(kbdev->dev, "%s: file is NULL", __func__); + return -EINVAL; + } + + if (atomic_cmpxchg(&kbdev->csf.dof.enabled, 0, 1) == 1) { + dev_warn(kbdev->dev, "Only one client is allowed for dump on fault"); + return -EBUSY; + } + + dev_info(kbdev->dev, "debug csf fault file open"); + + return simple_open(in, file); +} + +static ssize_t debug_csf_fault_write(struct file *file, const char __user *ubuf, size_t count, + loff_t *ppos) +{ + struct kbase_device *kbdev; + unsigned long flags; + + if (unlikely(!file)) { + pr_warn("%s: file is NULL", __func__); + return -EINVAL; + } + + kbdev = file->private_data; + spin_lock_irqsave(&kbdev->csf.dof.lock, flags); + kbdev->csf.dof.error_code = DF_NO_ERROR; + kbdev->csf.dof.kctx_tgid = 0; + kbdev->csf.dof.kctx_id = 0; + dev_info(kbdev->dev, "debug csf fault dump complete"); + spin_unlock_irqrestore(&kbdev->csf.dof.lock, flags); + + /* User space finished the dump. + * Wake up blocked kernel threads to proceed. + */ + wake_up(&kbdev->csf.dof.dump_wait_wq); + + return count; +} + +static int debug_csf_fault_release(struct inode *in, struct file *file) +{ + struct kbase_device *kbdev; + unsigned long flags; + + if (unlikely(!in)) { + pr_warn("%s: inode is NULL", __func__); + return -EINVAL; + } + + kbdev = in->i_private; + spin_lock_irqsave(&kbdev->csf.dof.lock, flags); + kbdev->csf.dof.kctx_tgid = 0; + kbdev->csf.dof.kctx_id = 0; + kbdev->csf.dof.error_code = DF_NO_ERROR; + spin_unlock_irqrestore(&kbdev->csf.dof.lock, flags); + + atomic_set(&kbdev->csf.dof.enabled, 0); + dev_info(kbdev->dev, "debug csf fault file close"); + + /* User space closed the debugfs file. + * Wake up blocked kernel threads to resume. + */ + wake_up(&kbdev->csf.dof.dump_wait_wq); + + return 0; +} + +static const struct file_operations kbasep_debug_csf_fault_fops = { + .owner = THIS_MODULE, + .open = debug_csf_fault_open, + .read = debug_csf_fault_read, + .write = debug_csf_fault_write, + .llseek = default_llseek, + .release = debug_csf_fault_release, +}; + +void kbase_debug_csf_fault_debugfs_init(struct kbase_device *kbdev) +{ + const char *fname = "csf_fault"; + + if (unlikely(!kbdev)) { + pr_warn("%s: kbdev is NULL", __func__); + return; + } + + debugfs_create_file(fname, 0600, kbdev->mali_debugfs_directory, kbdev, + &kbasep_debug_csf_fault_fops); +} + +int kbase_debug_csf_fault_init(struct kbase_device *kbdev) +{ + if (unlikely(!kbdev)) { + pr_warn("%s: kbdev is NULL", __func__); + return -EINVAL; + } + + init_waitqueue_head(&(kbdev->csf.dof.fault_wait_wq)); + init_waitqueue_head(&(kbdev->csf.dof.dump_wait_wq)); + spin_lock_init(&kbdev->csf.dof.lock); + kbdev->csf.dof.kctx_tgid = 0; + kbdev->csf.dof.kctx_id = 0; + kbdev->csf.dof.error_code = DF_NO_ERROR; + atomic_set(&kbdev->csf.dof.enabled, 0); + + return 0; +} + +void kbase_debug_csf_fault_term(struct kbase_device *kbdev) +{ +} +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/gpu/arm/bifrost/csf/mali_kbase_debug_csf_fault.h b/drivers/gpu/arm/bifrost/csf/mali_kbase_debug_csf_fault.h new file mode 100644 index 000000000000..6e9b1a9d51de --- /dev/null +++ b/drivers/gpu/arm/bifrost/csf/mali_kbase_debug_csf_fault.h @@ -0,0 +1,137 @@ +/* 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 _KBASE_DEBUG_CSF_FAULT_H +#define _KBASE_DEBUG_CSF_FAULT_H + +#if IS_ENABLED(CONFIG_DEBUG_FS) +/** + * kbase_debug_csf_fault_debugfs_init - Initialize CSF fault debugfs + * @kbdev: Device pointer + */ +void kbase_debug_csf_fault_debugfs_init(struct kbase_device *kbdev); + +/** + * kbase_debug_csf_fault_init - Create the fault event wait queue per device + * and initialize the required resources. + * @kbdev: Device pointer + * + * Return: Zero on success or a negative error code. + */ +int kbase_debug_csf_fault_init(struct kbase_device *kbdev); + +/** + * kbase_debug_csf_fault_term - Clean up resources created by + * @kbase_debug_csf_fault_init. + * @kbdev: Device pointer + */ +void kbase_debug_csf_fault_term(struct kbase_device *kbdev); + +/** + * kbase_debug_csf_fault_wait_completion - Wait for the client to complete. + * + * @kbdev: Device Pointer + * + * Wait for the user space client to finish reading the fault information. + * This function must be called in thread context. + */ +void kbase_debug_csf_fault_wait_completion(struct kbase_device *kbdev); + +/** + * kbase_debug_csf_fault_notify - Notify client of a fault. + * + * @kbdev: Device pointer + * @kctx: Faulty context (can be NULL) + * @error: Error code. + * + * Store fault information and wake up the user space client. + * + * Return: true if a dump on fault was initiated or was is in progress and + * so caller can opt to wait for the dumping to complete. + */ +bool kbase_debug_csf_fault_notify(struct kbase_device *kbdev, + struct kbase_context *kctx, enum dumpfault_error_type error); + +/** + * kbase_debug_csf_fault_dump_enabled - Check if dump on fault is enabled. + * + * @kbdev: Device pointer + * + * Return: true if debugfs file is opened so dump on fault is enabled. + */ +static inline bool kbase_debug_csf_fault_dump_enabled(struct kbase_device *kbdev) +{ + return atomic_read(&kbdev->csf.dof.enabled); +} + +/** + * kbase_debug_csf_fault_dump_complete - Check if dump on fault is completed. + * + * @kbdev: Device pointer + * + * Return: true if dump on fault completes or file is closed. + */ +static inline bool kbase_debug_csf_fault_dump_complete(struct kbase_device *kbdev) +{ + unsigned long flags; + bool ret; + + if (likely(!kbase_debug_csf_fault_dump_enabled(kbdev))) + return true; + + spin_lock_irqsave(&kbdev->csf.dof.lock, flags); + ret = (kbdev->csf.dof.error_code == DF_NO_ERROR); + spin_unlock_irqrestore(&kbdev->csf.dof.lock, flags); + + return ret; +} +#else /* CONFIG_DEBUG_FS */ +static inline int kbase_debug_csf_fault_init(struct kbase_device *kbdev) +{ + return 0; +} + +static inline void kbase_debug_csf_fault_term(struct kbase_device *kbdev) +{ +} + +static inline void kbase_debug_csf_fault_wait_completion(struct kbase_device *kbdev) +{ +} + +static inline bool kbase_debug_csf_fault_notify(struct kbase_device *kbdev, + struct kbase_context *kctx, enum dumpfault_error_type error) +{ + return false; +} + +static inline bool kbase_debug_csf_fault_dump_enabled(struct kbase_device *kbdev) +{ + return false; +} + +static inline bool kbase_debug_csf_fault_dump_complete(struct kbase_device *kbdev) +{ + return true; +} +#endif /* CONFIG_DEBUG_FS */ + +#endif /*_KBASE_DEBUG_CSF_FAULT_H*/ 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 9e4da9f11787..41b2b00f18c8 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 @@ -42,19 +42,25 @@ int dummy_array[] = { /* * Generic CSF events */ + /* info_val = 0 */ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_EVICT_CTX_SLOTS_START), + /* info_val == number of CSGs supported */ + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_EVICT_CTX_SLOTS_END), /* 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(CSF_FIRMWARE_BOOT), KBASE_KTRACE_CODE_MAKE_CODE(CSF_FIRMWARE_REBOOT), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TOCK_INVOKE), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TICK_INVOKE), 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_START), KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_TICK_END), KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_RESET_START), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_RESET_END), /* info_val = timeout in ms */ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_PROTM_WAIT_QUIT_START), /* info_val = remaining ms timeout, or 0 if timedout */ @@ -101,6 +107,8 @@ int dummy_array[] = { * purpose. */ KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_GPU_IDLE_WORKER_HANDLING_START), + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_GPU_IDLE_WORKER_HANDLING_END), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_FIRMWARE_MCU_HALTED), KBASE_KTRACE_CODE_MAKE_CODE(CSF_FIRMWARE_MCU_SLEEP), @@ -126,6 +134,8 @@ int dummy_array[] = { * group->csg_nr indicates which bit was set */ KBASE_KTRACE_CODE_MAKE_CODE(CSG_SLOT_IDLE_SET), + KBASE_KTRACE_CODE_MAKE_CODE(CSG_INTERRUPT_NO_NON_IDLE_GROUPS), + KBASE_KTRACE_CODE_MAKE_CODE(CSG_INTERRUPT_NON_IDLE_GROUPS), /* info_val = scheduler's new csg_slots_idle_mask[0] * group->csg_nr indicates which bit was cleared * @@ -190,10 +200,37 @@ int dummy_array[] = { 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_GRP_DEC), + /* info_val = scheduler's new csg_slots_idle_mask[0] + * group->csg_nr indicates which bit was set + */ + KBASE_KTRACE_CODE_MAKE_CODE(SCHEDULER_HANDLE_IDLE_SLOTS), KBASE_KTRACE_CODE_MAKE_CODE(PROTM_EVENT_WORKER_START), KBASE_KTRACE_CODE_MAKE_CODE(PROTM_EVENT_WORKER_END), + /* info_val = scheduler state */ + KBASE_KTRACE_CODE_MAKE_CODE(SCHED_BUSY), + KBASE_KTRACE_CODE_MAKE_CODE(SCHED_INACTIVE), + KBASE_KTRACE_CODE_MAKE_CODE(SCHED_SUSPENDED), + KBASE_KTRACE_CODE_MAKE_CODE(SCHED_SLEEPING), + + /* info_val = mcu state */ +#define KBASEP_MCU_STATE(n) KBASE_KTRACE_CODE_MAKE_CODE(PM_MCU_ ## n), +#include "backend/gpu/mali_kbase_pm_mcu_states.h" +#undef KBASEP_MCU_STATE + + /* info_val = number of runnable groups */ + KBASE_KTRACE_CODE_MAKE_CODE(CSF_GROUP_INACTIVE), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_GROUP_RUNNABLE), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_GROUP_IDLE), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_GROUP_SUSPENDED), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_GROUP_SUSPENDED_ON_IDLE), + KBASE_KTRACE_CODE_MAKE_CODE(CSF_GROUP_SUSPENDED_ON_WAIT_SYNC), + /* info_val = new run state of the evicted group */ + KBASE_KTRACE_CODE_MAKE_CODE(CSF_GROUP_FAULT_EVICTED), + /* info_val = get the number of active CSGs */ + KBASE_KTRACE_CODE_MAKE_CODE(CSF_GROUP_TERMINATED), + /* * Group + Queue events */ 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 86e81e510b47..ddcac906c492 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 @@ -31,13 +31,17 @@ * Generic CSF events - using the common DEFINE_MALI_ADD_EVENT */ DEFINE_MALI_ADD_EVENT(SCHEDULER_EVICT_CTX_SLOTS_START); +DEFINE_MALI_ADD_EVENT(SCHEDULER_EVICT_CTX_SLOTS_END); DEFINE_MALI_ADD_EVENT(CSF_FIRMWARE_BOOT); DEFINE_MALI_ADD_EVENT(CSF_FIRMWARE_REBOOT); +DEFINE_MALI_ADD_EVENT(SCHEDULER_TOCK_INVOKE); +DEFINE_MALI_ADD_EVENT(SCHEDULER_TICK_INVOKE); DEFINE_MALI_ADD_EVENT(SCHEDULER_TOCK_START); DEFINE_MALI_ADD_EVENT(SCHEDULER_TOCK_END); DEFINE_MALI_ADD_EVENT(SCHEDULER_TICK_START); DEFINE_MALI_ADD_EVENT(SCHEDULER_TICK_END); DEFINE_MALI_ADD_EVENT(SCHEDULER_RESET_START); +DEFINE_MALI_ADD_EVENT(SCHEDULER_RESET_END); 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); @@ -58,8 +62,16 @@ 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(SCHEDULER_GPU_IDLE_WORKER_HANDLING_END); DEFINE_MALI_ADD_EVENT(CSF_FIRMWARE_MCU_HALTED); DEFINE_MALI_ADD_EVENT(CSF_FIRMWARE_MCU_SLEEP); +DEFINE_MALI_ADD_EVENT(SCHED_BUSY); +DEFINE_MALI_ADD_EVENT(SCHED_INACTIVE); +DEFINE_MALI_ADD_EVENT(SCHED_SUSPENDED); +DEFINE_MALI_ADD_EVENT(SCHED_SLEEPING); +#define KBASEP_MCU_STATE(n) DEFINE_MALI_ADD_EVENT(PM_MCU_ ## n); +#include "backend/gpu/mali_kbase_pm_mcu_states.h" +#undef KBASEP_MCU_STATE DECLARE_EVENT_CLASS(mali_csf_grp_q_template, TP_PROTO(struct kbase_device *kbdev, struct kbase_queue_group *group, @@ -136,6 +148,8 @@ DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_STOPPED); DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_CLEANED); 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_INTERRUPT_NO_NON_IDLE_GROUPS); +DEFINE_MALI_CSF_GRP_EVENT(CSG_INTERRUPT_NON_IDLE_GROUPS); DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_IDLE_CLEAR); DEFINE_MALI_CSF_GRP_EVENT(CSG_SLOT_PRIO_UPDATE); DEFINE_MALI_CSF_GRP_EVENT(CSG_INTERRUPT_SYNC_UPDATE); @@ -160,8 +174,17 @@ DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_PROTM_EXIT); DEFINE_MALI_CSF_GRP_EVENT(SCHEDULER_TOP_GRP); 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(SCHEDULER_HANDLE_IDLE_SLOTS); DEFINE_MALI_CSF_GRP_EVENT(PROTM_EVENT_WORKER_START); DEFINE_MALI_CSF_GRP_EVENT(PROTM_EVENT_WORKER_END); +DEFINE_MALI_CSF_GRP_EVENT(CSF_GROUP_INACTIVE); +DEFINE_MALI_CSF_GRP_EVENT(CSF_GROUP_RUNNABLE); +DEFINE_MALI_CSF_GRP_EVENT(CSF_GROUP_IDLE); +DEFINE_MALI_CSF_GRP_EVENT(CSF_GROUP_SUSPENDED); +DEFINE_MALI_CSF_GRP_EVENT(CSF_GROUP_SUSPENDED_ON_IDLE); +DEFINE_MALI_CSF_GRP_EVENT(CSF_GROUP_SUSPENDED_ON_WAIT_SYNC); +DEFINE_MALI_CSF_GRP_EVENT(CSF_GROUP_FAULT_EVICTED); +DEFINE_MALI_CSF_GRP_EVENT(CSF_GROUP_TERMINATED); #undef DEFINE_MALI_CSF_GRP_EVENT diff --git a/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace_codes.h b/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace_codes.h index 1c6b4cd26fe0..6103c3ee04a8 100644 --- a/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace_codes.h +++ b/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_ktrace_codes.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2011-2015, 2018-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2011-2015, 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 @@ -142,6 +142,11 @@ int dummy_array[] = { KBASE_KTRACE_CODE_MAKE_CODE(PM_RUNTIME_SUSPEND_CALLBACK), KBASE_KTRACE_CODE_MAKE_CODE(PM_RUNTIME_RESUME_CALLBACK), + /* info_val = l2 state */ +#define KBASEP_L2_STATE(n) KBASE_KTRACE_CODE_MAKE_CODE(PM_L2_ ## n), +#include "backend/gpu/mali_kbase_pm_l2_states.h" +#undef KBASEP_L2_STATE + /* * Context Scheduler events */ diff --git a/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_linux_ktrace.h b/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_linux_ktrace.h index 5fac763d1916..6d96647161b4 100644 --- a/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_linux_ktrace.h +++ b/drivers/gpu/arm/bifrost/debug/mali_kbase_debug_linux_ktrace.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2014, 2018, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014, 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 @@ -98,6 +98,9 @@ DEFINE_MALI_ADD_EVENT(PM_WAKE_WAITERS); DEFINE_MALI_ADD_EVENT(PM_POWEROFF_WAIT_WQ); DEFINE_MALI_ADD_EVENT(PM_RUNTIME_SUSPEND_CALLBACK); DEFINE_MALI_ADD_EVENT(PM_RUNTIME_RESUME_CALLBACK); +#define KBASEP_L2_STATE(n) DEFINE_MALI_ADD_EVENT(PM_L2_ ## n); +#include "backend/gpu/mali_kbase_pm_l2_states.h" +#undef KBASEP_L2_STATE DEFINE_MALI_ADD_EVENT(SCHED_RETAIN_CTX_NOLOCK); DEFINE_MALI_ADD_EVENT(SCHED_RELEASE_CTX); #ifdef CONFIG_MALI_ARBITER_SUPPORT 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 1e84f6b2644d..277569381292 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 @@ -23,8 +23,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -40,9 +40,10 @@ #include #include #include -#include +#include #include #include +#include /** * kbase_device_firmware_hwcnt_term - Terminate CSF firmware and HWC @@ -60,7 +61,7 @@ static void kbase_device_firmware_hwcnt_term(struct kbase_device *kbdev) kbase_vinstr_term(kbdev->vinstr_ctx); kbase_hwcnt_virtualizer_term(kbdev->hwcnt_gpu_virt); kbase_hwcnt_backend_csf_metadata_term(&kbdev->hwcnt_gpu_iface); - kbase_csf_firmware_term(kbdev); + kbase_csf_firmware_unload_term(kbdev); } } @@ -197,6 +198,20 @@ static int kbase_csf_early_init(struct kbase_device *kbdev) static void kbase_csf_early_term(struct kbase_device *kbdev) { kbase_csf_scheduler_early_term(kbdev); + kbase_csf_firmware_early_term(kbdev); +} + +/** + * kbase_csf_late_init - late initialization for firmware. + * @kbdev: Device pointer + * + * Return: 0 on success, error code otherwise. + */ +static int kbase_csf_late_init(struct kbase_device *kbdev) +{ + int err = kbase_csf_firmware_late_init(kbdev); + + return err; } /** @@ -269,59 +284,48 @@ static void kbase_device_hwcnt_backend_csf_term(struct kbase_device *kbdev) static const struct kbase_device_init dev_init[] = { #if IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) - { kbase_gpu_device_create, kbase_gpu_device_destroy, - "Dummy model initialization failed" }, + { kbase_gpu_device_create, kbase_gpu_device_destroy, "Dummy model initialization failed" }, #else { assign_irqs, NULL, "IRQ search failed" }, { registers_map, registers_unmap, "Register map failed" }, #endif - { power_control_init, power_control_term, - "Power control initialization failed" }, + { power_control_init, power_control_term, "Power control initialization failed" }, { kbase_device_io_history_init, kbase_device_io_history_term, "Register access history initialization failed" }, - { kbase_device_early_init, kbase_device_early_term, - "Early device initialization failed" }, - { kbase_device_populate_max_freq, NULL, - "Populating max frequency failed" }, - { kbase_pm_lowest_gpu_freq_init, NULL, - "Lowest freq initialization failed" }, + { kbase_device_early_init, kbase_device_early_term, "Early device initialization failed" }, + { kbase_device_populate_max_freq, NULL, "Populating max frequency failed" }, + { kbase_pm_lowest_gpu_freq_init, NULL, "Lowest freq initialization failed" }, { kbase_device_misc_init, kbase_device_misc_term, "Miscellaneous device initialization failed" }, { kbase_device_pcm_dev_init, kbase_device_pcm_dev_term, "Priority control manager initialization failed" }, - { kbase_ctx_sched_init, kbase_ctx_sched_term, - "Context scheduler initialization failed" }, - { kbase_mem_init, kbase_mem_term, - "Memory subsystem initialization failed" }, + { kbase_ctx_sched_init, kbase_ctx_sched_term, "Context scheduler initialization failed" }, + { kbase_mem_init, kbase_mem_term, "Memory subsystem initialization failed" }, { kbase_csf_protected_memory_init, kbase_csf_protected_memory_term, "Protected memory allocator initialization failed" }, { kbase_device_coherency_init, NULL, "Device coherency init failed" }, { kbase_protected_mode_init, kbase_protected_mode_term, "Protected mode subsystem initialization failed" }, - { kbase_device_list_init, kbase_device_list_term, - "Device list setup failed" }, + { kbase_device_list_init, kbase_device_list_term, "Device list setup failed" }, { kbase_device_timeline_init, kbase_device_timeline_term, "Timeline stream initialization failed" }, { kbase_clk_rate_trace_manager_init, kbase_clk_rate_trace_manager_term, "Clock rate trace manager initialization failed" }, - { kbase_device_hwcnt_watchdog_if_init, - kbase_device_hwcnt_watchdog_if_term, + { kbase_device_hwcnt_watchdog_if_init, kbase_device_hwcnt_watchdog_if_term, "GPU hwcnt backend watchdog interface creation failed" }, - { kbase_device_hwcnt_backend_csf_if_init, - kbase_device_hwcnt_backend_csf_if_term, + { kbase_device_hwcnt_backend_csf_if_init, kbase_device_hwcnt_backend_csf_if_term, "GPU hwcnt backend CSF interface creation failed" }, - { kbase_device_hwcnt_backend_csf_init, - kbase_device_hwcnt_backend_csf_term, + { kbase_device_hwcnt_backend_csf_init, kbase_device_hwcnt_backend_csf_term, "GPU hwcnt backend creation failed" }, { kbase_device_hwcnt_context_init, kbase_device_hwcnt_context_term, "GPU hwcnt context 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" }, + { kbase_csf_early_init, kbase_csf_early_term, "Early CSF initialization failed" }, + { kbase_backend_late_init, kbase_backend_late_term, "Late backend initialization failed" }, + { kbase_csf_late_init, NULL, "Late CSF initialization failed" }, { NULL, kbase_device_firmware_hwcnt_term, NULL }, - { kbase_device_debugfs_init, kbase_device_debugfs_term, - "DebugFS initialization failed" }, + { kbase_debug_csf_fault_init, kbase_debug_csf_fault_term, + "CSF fault debug initialization failed" }, + { kbase_device_debugfs_init, kbase_device_debugfs_term, "DebugFS initialization failed" }, /* Sysfs init needs to happen before registering the device with * misc_register(), otherwise it causes a race condition between * registering the device and a uevent event being generated for @@ -339,8 +343,7 @@ static const struct kbase_device_init dev_init[] = { "Misc device registration failed" }, { kbase_gpuprops_populate_user_buffer, kbase_gpuprops_free_user_buffer, "GPU property population failed" }, - { kbase_device_late_init, kbase_device_late_term, - "Late device initialization failed" }, + { kbase_device_late_init, kbase_device_late_term, "Late device initialization failed" }, }; static void kbase_device_term_partial(struct kbase_device *kbdev, @@ -468,7 +471,7 @@ static int kbase_csf_firmware_deferred_init(struct kbase_device *kbdev) lockdep_assert_held(&kbdev->fw_load_lock); - err = kbase_csf_firmware_init(kbdev); + err = kbase_csf_firmware_load_init(kbdev); if (!err) { unsigned long flags; @@ -498,11 +501,12 @@ int kbase_device_firmware_init_once(struct kbase_device *kbdev) ret = kbase_device_hwcnt_csf_deferred_init(kbdev); if (ret) { - kbase_csf_firmware_term(kbdev); + kbase_csf_firmware_unload_term(kbdev); goto out; } kbase_csf_debugfs_init(kbdev); + kbase_timeline_io_debugfs_init(kbdev); out: kbase_pm_context_idle(kbdev); } diff --git a/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_hw_csf.c b/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_hw_csf.c index 7939bfd8e74c..3b792968a7d7 100644 --- a/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_hw_csf.c +++ b/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_hw_csf.c @@ -115,6 +115,9 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val) GPU_EXCEPTION_TYPE_SW_FAULT_0, } } }; + kbase_debug_csf_fault_notify(kbdev, scheduler->active_protm_grp->kctx, + DF_GPU_PROTECTED_FAULT); + scheduler->active_protm_grp->faulted = true; kbase_csf_add_group_fatal_error( scheduler->active_protm_grp, &err_payload); @@ -201,8 +204,11 @@ static bool kbase_is_register_accessible(u32 offset) 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); + if (WARN_ON(!kbdev->pm.backend.gpu_powered)) + return; + + if (WARN_ON(kbdev->dev == NULL)) + return; if (!kbase_is_register_accessible(offset)) return; @@ -222,8 +228,11 @@ 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); + if (WARN_ON(!kbdev->pm.backend.gpu_powered)) + return 0; + + if (WARN_ON(kbdev->dev == NULL)) + return 0; if (!kbase_is_register_accessible(offset)) return 0; diff --git a/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_jm.c b/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_jm.c index ed7512ef2e39..129b4e430c52 100644 --- a/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_jm.c +++ b/drivers/gpu/arm/bifrost/device/backend/mali_kbase_device_jm.c @@ -27,9 +27,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #if IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) #include diff --git a/drivers/gpu/arm/bifrost/device/mali_kbase_device.c b/drivers/gpu/arm/bifrost/device/mali_kbase_device.c index 7004e347fa1b..fa3669a409e2 100644 --- a/drivers/gpu/arm/bifrost/device/mali_kbase_device.c +++ b/drivers/gpu/arm/bifrost/device/mali_kbase_device.c @@ -42,8 +42,8 @@ #include #include "mali_kbase_kinstr_prfcnt.h" #include "mali_kbase_vinstr.h" -#include "mali_kbase_hwcnt_context.h" -#include "mali_kbase_hwcnt_virtualizer.h" +#include "hwcnt/mali_kbase_hwcnt_context.h" +#include "hwcnt/mali_kbase_hwcnt_virtualizer.h" #include "mali_kbase_device.h" #include "mali_kbase_device_internal.h" @@ -56,17 +56,15 @@ #include "arbiter/mali_kbase_arbiter_pm.h" #endif /* CONFIG_MALI_ARBITER_SUPPORT */ -/* NOTE: Magic - 0x45435254 (TRCE in ASCII). - * Supports tracing feature provided in the base module. - * Please keep it in sync with the value of base module. - */ -#define TRACE_BUFFER_HEADER_SPECIAL 0x45435254 +#if defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) /* Number of register accesses for the buffer that we allocate during * initialization time. The buffer size can be changed later via debugfs. */ #define KBASEP_DEFAULT_REGISTER_HISTORY_SIZE ((u16)512) +#endif /* defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) */ + static DEFINE_MUTEX(kbase_dev_list_lock); static LIST_HEAD(kbase_dev_list); static int kbase_dev_nr; diff --git a/drivers/gpu/arm/bifrost/device/mali_kbase_device.h b/drivers/gpu/arm/bifrost/device/mali_kbase_device.h index 6706a61d5baa..f025011009d5 100644 --- a/drivers/gpu/arm/bifrost/device/mali_kbase_device.h +++ b/drivers/gpu/arm/bifrost/device/mali_kbase_device.h @@ -130,7 +130,11 @@ bool kbase_is_gpu_removed(struct kbase_device *kbdev); * * 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) +#if MALI_USE_CSF +int kbase_gpu_cache_flush_pa_range_and_busy_wait(struct kbase_device *kbdev, phys_addr_t phys, + size_t nr_bytes, u32 flush_op); +#endif /* MALI_USE_CSF */ + /** * kbase_gpu_cache_flush_and_busy_wait - Start a cache flush and busy wait * @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 4bd545a82299..d55495045892 100644 --- a/drivers/gpu/arm/bifrost/device/mali_kbase_device_hw.c +++ b/drivers/gpu/arm/bifrost/device/mali_kbase_device_hw.c @@ -27,9 +27,6 @@ #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) { @@ -86,7 +83,38 @@ static int busy_wait_on_irq(struct kbase_device *kbdev, u32 irq_bit) return 0; } -#define kbase_gpu_cache_flush_pa_range_and_busy_wait(kbdev, phys, nr_bytes, flush_op) (0) +#if MALI_USE_CSF +#define U64_LO_MASK ((1ULL << 32) - 1) +#define U64_HI_MASK (~U64_LO_MASK) + +int kbase_gpu_cache_flush_pa_range_and_busy_wait(struct kbase_device *kbdev, phys_addr_t phys, + size_t nr_bytes, u32 flush_op) +{ + u64 start_pa, end_pa; + int ret = 0; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + /* 1. Clear the interrupt FLUSH_PA_RANGE_COMPLETED bit. */ + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_IRQ_CLEAR), FLUSH_PA_RANGE_COMPLETED); + + /* 2. Issue GPU_CONTROL.COMMAND.FLUSH_PA_RANGE operation. */ + start_pa = phys; + end_pa = start_pa + nr_bytes - 1; + + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND_ARG0_LO), start_pa & U64_LO_MASK); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND_ARG0_HI), + (start_pa & U64_HI_MASK) >> 32); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND_ARG1_LO), end_pa & U64_LO_MASK); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND_ARG1_HI), (end_pa & U64_HI_MASK) >> 32); + kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), flush_op); + + /* 3. Busy-wait irq status to be enabled. */ + ret = busy_wait_on_irq(kbdev, (u32)FLUSH_PA_RANGE_COMPLETED); + + return ret; +} +#endif /* MALI_USE_CSF */ int kbase_gpu_cache_flush_and_busy_wait(struct kbase_device *kbdev, u32 flush_op) diff --git a/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_fault_jm.c b/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_fault_jm.c index 37015ccacd7c..7f3743ca6432 100644 --- a/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_fault_jm.c +++ b/drivers/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_fault_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 @@ -170,7 +170,7 @@ const char *kbase_gpu_exception_name(u32 const exception_code) default: e = "UNKNOWN"; break; - }; + } return e; } 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 06c725c0e757..e7457ddb5534 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 @@ -35,10 +35,7 @@ #define MCU_SUBSYSTEM_BASE 0x20000 /* IPA control registers */ -#define IPA_CONTROL_BASE 0x40000 -#define IPA_CONTROL_REG(r) (IPA_CONTROL_BASE+(r)) #define COMMAND 0x000 /* (WO) Command register */ -#define STATUS 0x004 /* (RO) Status register */ #define TIMER 0x008 /* (RW) Timer control register */ #define SELECT_CSHW_LO 0x010 /* (RW) Counter select for CS hardware, low word */ @@ -127,8 +124,16 @@ #define MCU_STATUS_HALTED (1 << 1) +#define L2_CONFIG_PBHA_HWU_SHIFT GPU_U(12) +#define L2_CONFIG_PBHA_HWU_MASK (GPU_U(0xF) << L2_CONFIG_PBHA_HWU_SHIFT) +#define L2_CONFIG_PBHA_HWU_GET(reg_val) \ + (((reg_val)&L2_CONFIG_PBHA_HWU_MASK) >> L2_CONFIG_PBHA_HWU_SHIFT) +#define L2_CONFIG_PBHA_HWU_SET(reg_val, value) \ + (((reg_val) & ~L2_CONFIG_PBHA_HWU_MASK) | \ + (((value) << L2_CONFIG_PBHA_HWU_SHIFT) & L2_CONFIG_PBHA_HWU_MASK)) + /* JOB IRQ flags */ -#define JOB_IRQ_GLOBAL_IF (1 << 31) /* Global interface interrupt received */ +#define JOB_IRQ_GLOBAL_IF (1u << 31) /* Global interface interrupt received */ /* GPU_COMMAND codes */ #define GPU_COMMAND_CODE_NOP 0x00 /* No operation, nothing happens */ 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 c349f4b058cd..380ec30d607f 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 @@ -127,29 +127,12 @@ #define JOB_SLOT_REG(n, r) (JOB_CONTROL_REG(JOB_SLOT0 + ((n) << 7)) + (r)) -#define JS_HEAD_LO 0x00 /* (RO) Job queue head pointer for job slot n, low word */ -#define JS_HEAD_HI 0x04 /* (RO) Job queue head pointer for job slot n, high word */ -#define JS_TAIL_LO 0x08 /* (RO) Job queue tail pointer for job slot n, low word */ -#define JS_TAIL_HI 0x0C /* (RO) Job queue tail pointer for job slot n, high word */ -#define JS_AFFINITY_LO 0x10 /* (RO) Core affinity mask for job slot n, low word */ -#define JS_AFFINITY_HI 0x14 /* (RO) Core affinity mask for job slot n, high word */ -#define JS_CONFIG 0x18 /* (RO) Configuration settings for job slot n */ -/* (RO) Extended affinity mask for job slot n*/ -#define JS_XAFFINITY 0x1C +#define JS_XAFFINITY 0x1C /* (RO) Extended affinity mask for job slot n*/ #define JS_COMMAND 0x20 /* (WO) Command register for job slot n */ #define JS_STATUS 0x24 /* (RO) Status register for job slot n */ -#define JS_HEAD_NEXT_LO 0x40 /* (RW) Next job queue head pointer for job slot n, low word */ -#define JS_HEAD_NEXT_HI 0x44 /* (RW) Next job queue head pointer for job slot n, high word */ - -#define JS_AFFINITY_NEXT_LO 0x50 /* (RW) Next core affinity mask for job slot n, low word */ -#define JS_AFFINITY_NEXT_HI 0x54 /* (RW) Next core affinity mask for job slot n, high word */ -#define JS_CONFIG_NEXT 0x58 /* (RW) Next configuration settings for job slot n */ -/* (RW) Next extended affinity mask for job slot n */ -#define JS_XAFFINITY_NEXT 0x5C - -#define JS_COMMAND_NEXT 0x60 /* (RW) Next command register for job slot n */ +#define JS_XAFFINITY_NEXT 0x5C /* (RW) Next extended affinity mask for job slot n */ #define JS_FLUSH_ID_NEXT 0x70 /* (RW) Next job slot n cache flush ID */ 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 396ebd5e21c9..282f566c0746 100644 --- a/drivers/gpu/arm/bifrost/gpu/mali_kbase_gpu_regmap.h +++ b/drivers/gpu/arm/bifrost/gpu/mali_kbase_gpu_regmap.h @@ -45,9 +45,6 @@ /* Begin Register Offsets */ /* GPU control registers */ -#define GPU_CONTROL_BASE 0x0000 -#define GPU_CONTROL_REG(r) (GPU_CONTROL_BASE + (r)) -#define GPU_ID 0x000 /* (RO) GPU and revision identifier */ #define L2_FEATURES 0x004 /* (RO) Level 2 cache features */ #define TILER_FEATURES 0x00C /* (RO) Tiler Features */ #define MEM_FEATURES 0x010 /* (RO) Memory system features */ @@ -100,6 +97,10 @@ #define TEXTURE_FEATURES_REG(n) GPU_CONTROL_REG(TEXTURE_FEATURES_0 + ((n) << 2)) +#define GPU_COMMAND_ARG0_LO 0x0D0 /* (RW) Additional parameter 0 for GPU commands, low word */ +#define GPU_COMMAND_ARG0_HI 0x0D4 /* (RW) Additional parameter 0 for GPU commands, high word */ +#define GPU_COMMAND_ARG1_LO 0x0D8 /* (RW) Additional parameter 1 for GPU commands, low word */ +#define GPU_COMMAND_ARG1_HI 0x0DC /* (RW) Additional parameter 1 for GPU commands, high word */ #define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */ #define SHADER_PRESENT_HI 0x104 /* (RO) Shader core present bitmap, high word */ @@ -113,26 +114,10 @@ #define STACK_PRESENT_LO 0xE00 /* (RO) Core stack present bitmap, low word */ #define STACK_PRESENT_HI 0xE04 /* (RO) Core stack present bitmap, high word */ -#define SHADER_READY_LO 0x140 /* (RO) Shader core ready bitmap, low word */ -#define SHADER_READY_HI 0x144 /* (RO) Shader core ready bitmap, high word */ - -#define TILER_READY_LO 0x150 /* (RO) Tiler core ready bitmap, low word */ -#define TILER_READY_HI 0x154 /* (RO) Tiler core ready bitmap, high word */ - -#define L2_READY_LO 0x160 /* (RO) Level 2 cache ready bitmap, low word */ -#define L2_READY_HI 0x164 /* (RO) Level 2 cache ready bitmap, high word */ - #define STACK_READY_LO 0xE10 /* (RO) Core stack ready bitmap, low word */ #define STACK_READY_HI 0xE14 /* (RO) Core stack ready bitmap, high word */ -#define SHADER_PWRON_LO 0x180 /* (WO) Shader core power on bitmap, low word */ -#define SHADER_PWRON_HI 0x184 /* (WO) Shader core power on bitmap, high word */ - -#define TILER_PWRON_LO 0x190 /* (WO) Tiler core power on bitmap, low word */ -#define TILER_PWRON_HI 0x194 /* (WO) Tiler core power on bitmap, high word */ - -#define L2_PWRON_LO 0x1A0 /* (WO) Level 2 cache power on bitmap, low word */ -#define L2_PWRON_HI 0x1A4 /* (WO) Level 2 cache power on bitmap, high word */ +#define SHADER_PWRFEATURES 0x188 /* (RW) Shader core power features */ #define STACK_PWRON_LO 0xE20 /* (RO) Core stack power on bitmap, low word */ #define STACK_PWRON_HI 0xE24 /* (RO) Core stack power on bitmap, high word */ @@ -181,6 +166,8 @@ #define COHERENCY_FEATURES 0x300 /* (RO) Coherency features present */ #define COHERENCY_ENABLE 0x304 /* (RW) Coherency enable */ +#define AMBA_FEATURES 0x300 /* (RO) AMBA bus supported features */ +#define AMBA_ENABLE 0x304 /* (RW) AMBA features enable */ #define SHADER_CONFIG 0xF04 /* (RW) Shader core configuration (implementation-specific) */ #define TILER_CONFIG 0xF08 /* (RW) Tiler core configuration (implementation-specific) */ @@ -188,13 +175,7 @@ /* Job control registers */ -#define JOB_CONTROL_BASE 0x1000 - -#define JOB_CONTROL_REG(r) (JOB_CONTROL_BASE + (r)) - #define JOB_IRQ_RAWSTAT 0x000 /* Raw interrupt status register */ -#define JOB_IRQ_CLEAR 0x004 /* Interrupt clear register */ -#define JOB_IRQ_MASK 0x008 /* Interrupt mask register */ #define JOB_IRQ_STATUS 0x00C /* Interrupt status register */ /* MMU control registers */ @@ -203,7 +184,6 @@ #define MMU_IRQ_MASK 0x008 /* (RW) Interrupt mask register */ #define MMU_IRQ_STATUS 0x00C /* (RO) Interrupt status register */ -#define MMU_AS0 0x400 /* Configuration registers for address space 0 */ #define MMU_AS1 0x440 /* Configuration registers for address space 1 */ #define MMU_AS2 0x480 /* Configuration registers for address space 2 */ #define MMU_AS3 0x4C0 /* Configuration registers for address space 3 */ @@ -221,25 +201,13 @@ #define MMU_AS15 0x7C0 /* Configuration registers for address space 15 */ /* MMU address space control registers */ - -#define MMU_AS_REG(n, r) (MMU_REG(MMU_AS0 + ((n) << 6)) + (r)) - -#define AS_TRANSTAB_LO 0x00 /* (RW) Translation Table Base Address for address space n, low word */ -#define AS_TRANSTAB_HI 0x04 /* (RW) Translation Table Base Address for address space n, high word */ -#define AS_MEMATTR_LO 0x08 /* (RW) Memory attributes for address space n, low word. */ -#define AS_MEMATTR_HI 0x0C /* (RW) Memory attributes for address space n, high word. */ #define AS_LOCKADDR_LO 0x10 /* (RW) Lock region address for address space n, low word */ #define AS_LOCKADDR_HI 0x14 /* (RW) Lock region address for address space n, high word */ -#define AS_COMMAND 0x18 /* (WO) MMU command register for address space n */ #define AS_FAULTSTATUS 0x1C /* (RO) MMU fault status register for address space n */ #define AS_FAULTADDRESS_LO 0x20 /* (RO) Fault Address for address space n, low word */ #define AS_FAULTADDRESS_HI 0x24 /* (RO) Fault Address for address space n, high word */ #define AS_STATUS 0x28 /* (RO) Status flags for address space n */ -/* (RW) Translation table configuration for address space n, low word */ -#define AS_TRANSCFG_LO 0x30 -/* (RW) Translation table configuration for address space n, high word */ -#define AS_TRANSCFG_HI 0x34 /* (RO) Secondary fault address for address space n, low word */ #define AS_FAULTEXTRA_LO 0x38 /* (RO) Secondary fault address for address space n, high word */ @@ -464,6 +432,80 @@ #define L2_CONFIG_ASN_HASH_ENABLE_MASK (1ul << L2_CONFIG_ASN_HASH_ENABLE_SHIFT) /* End L2_CONFIG register */ +/* AMBA_FEATURES register */ +#define AMBA_FEATURES_ACE_LITE_SHIFT GPU_U(0) +#define AMBA_FEATURES_ACE_LITE_MASK (GPU_U(0x1) << AMBA_FEATURES_ACE_LITE_SHIFT) +#define AMBA_FEATURES_ACE_LITE_GET(reg_val) \ + (((reg_val)&AMBA_FEATURES_ACE_LITE_MASK) >> \ + AMBA_FEATURES_ACE_LITE_SHIFT) +#define AMBA_FEATURES_ACE_LITE_SET(reg_val, value) \ + (((reg_val) & ~AMBA_FEATURES_ACE_LITE_MASK) | \ + (((value) << AMBA_FEATURES_ACE_LITE_SHIFT) & \ + AMBA_FEATURES_ACE_LITE_MASK)) +#define AMBA_FEATURES_ACE_SHIFT GPU_U(1) +#define AMBA_FEATURES_ACE_MASK (GPU_U(0x1) << AMBA_FEATURES_ACE_SHIFT) +#define AMBA_FEATURES_ACE_GET(reg_val) \ + (((reg_val)&AMBA_FEATURES_ACE_MASK) >> AMBA_FEATURES_ACE_SHIFT) +#define AMBA_FEATURES_ACE_SET(reg_val, value) \ + (((reg_val) & ~AMBA_FEATURES_ACE_MASK) | \ + (((value) << AMBA_FEATURES_ACE_SHIFT) & AMBA_FEATURES_ACE_MASK)) +#define AMBA_FEATURES_MEMORY_CACHE_SUPPORT_SHIFT GPU_U(5) +#define AMBA_FEATURES_MEMORY_CACHE_SUPPORT_MASK \ + (GPU_U(0x1) << AMBA_FEATURES_MEMORY_CACHE_SUPPORT_SHIFT) +#define AMBA_FEATURES_MEMORY_CACHE_SUPPORT_GET(reg_val) \ + (((reg_val)&AMBA_FEATURES_MEMORY_CACHE_SUPPORT_MASK) >> \ + AMBA_FEATURES_MEMORY_CACHE_SUPPORT_SHIFT) +#define AMBA_FEATURES_MEMORY_CACHE_SUPPORT_SET(reg_val, value) \ + (((reg_val) & ~AMBA_FEATURES_MEMORY_CACHE_SUPPORT_MASK) | \ + (((value) << AMBA_FEATURES_MEMORY_CACHE_SUPPORT_SHIFT) & \ + AMBA_FEATURES_MEMORY_CACHE_SUPPORT_MASK)) +#define AMBA_FEATURES_INVALIDATE_HINT_SHIFT GPU_U(6) +#define AMBA_FEATURES_INVALIDATE_HINT_MASK \ + (GPU_U(0x1) << AMBA_FEATURES_INVALIDATE_HINT_SHIFT) +#define AMBA_FEATURES_INVALIDATE_HINT_GET(reg_val) \ + (((reg_val)&AMBA_FEATURES_INVALIDATE_HINT_MASK) >> \ + AMBA_FEATURES_INVALIDATE_HINT_SHIFT) +#define AMBA_FEATURES_INVALIDATE_HINT_SET(reg_val, value) \ + (((reg_val) & ~AMBA_FEATURES_INVALIDATE_HINT_MASK) | \ + (((value) << AMBA_FEATURES_INVALIDATE_HINT_SHIFT) & \ + AMBA_FEATURES_INVALIDATE_HINT_MASK)) + +/* AMBA_ENABLE register */ +#define AMBA_ENABLE_COHERENCY_PROTOCOL_SHIFT GPU_U(0) +#define AMBA_ENABLE_COHERENCY_PROTOCOL_MASK \ + (GPU_U(0x1F) << AMBA_ENABLE_COHERENCY_PROTOCOL_SHIFT) +#define AMBA_ENABLE_COHERENCY_PROTOCOL_GET(reg_val) \ + (((reg_val)&AMBA_ENABLE_COHERENCY_PROTOCOL_MASK) >> \ + AMBA_ENABLE_COHERENCY_PROTOCOL_SHIFT) +#define AMBA_ENABLE_COHERENCY_PROTOCOL_SET(reg_val, value) \ + (((reg_val) & ~AMBA_ENABLE_COHERENCY_PROTOCOL_MASK) | \ + (((value) << AMBA_ENABLE_COHERENCY_PROTOCOL_SHIFT) & \ + AMBA_ENABLE_COHERENCY_PROTOCOL_MASK)) +/* AMBA_ENABLE_coherency_protocol values */ +#define AMBA_ENABLE_COHERENCY_PROTOCOL_ACE_LITE 0x0 +#define AMBA_ENABLE_COHERENCY_PROTOCOL_ACE 0x1 +#define AMBA_ENABLE_COHERENCY_PROTOCOL_NO_COHERENCY 0x1F +/* End of AMBA_ENABLE_coherency_protocol values */ +#define AMBA_ENABLE_MEMORY_CACHE_SUPPORT_SHIFT GPU_U(5) +#define AMBA_ENABLE_MEMORY_CACHE_SUPPORT_MASK \ + (GPU_U(0x1) << AMBA_ENABLE_MEMORY_CACHE_SUPPORT_SHIFT) +#define AMBA_ENABLE_MEMORY_CACHE_SUPPORT_GET(reg_val) \ + (((reg_val)&AMBA_ENABLE_MEMORY_CACHE_SUPPORT_MASK) >> \ + AMBA_ENABLE_MEMORY_CACHE_SUPPORT_SHIFT) +#define AMBA_ENABLE_MEMORY_CACHE_SUPPORT_SET(reg_val, value) \ + (((reg_val) & ~AMBA_ENABLE_MEMORY_CACHE_SUPPORT_MASK) | \ + (((value) << AMBA_ENABLE_MEMORY_CACHE_SUPPORT_SHIFT) & \ + AMBA_ENABLE_MEMORY_CACHE_SUPPORT_MASK)) +#define AMBA_ENABLE_INVALIDATE_HINT_SHIFT GPU_U(6) +#define AMBA_ENABLE_INVALIDATE_HINT_MASK \ + (GPU_U(0x1) << AMBA_ENABLE_INVALIDATE_HINT_SHIFT) +#define AMBA_ENABLE_INVALIDATE_HINT_GET(reg_val) \ + (((reg_val)&AMBA_ENABLE_INVALIDATE_HINT_MASK) >> \ + AMBA_ENABLE_INVALIDATE_HINT_SHIFT) +#define AMBA_ENABLE_INVALIDATE_HINT_SET(reg_val, value) \ + (((reg_val) & ~AMBA_ENABLE_INVALIDATE_HINT_MASK) | \ + (((value) << AMBA_ENABLE_INVALIDATE_HINT_SHIFT) & \ + AMBA_ENABLE_INVALIDATE_HINT_MASK)) /* IDVS_GROUP register */ #define IDVS_GROUP_SIZE_SHIFT (16) diff --git a/drivers/base/arm/dma_buf_lock/src/Kbuild b/drivers/gpu/arm/bifrost/hwcnt/Kbuild similarity index 53% rename from drivers/base/arm/dma_buf_lock/src/Kbuild rename to drivers/gpu/arm/bifrost/hwcnt/Kbuild index b6b741b39119..c1a381b24593 100644 --- a/drivers/base/arm/dma_buf_lock/src/Kbuild +++ b/drivers/gpu/arm/bifrost/hwcnt/Kbuild @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2012, 2020-2021 ARM Limited. All rights reserved. +# (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 @@ -18,6 +18,20 @@ # # -ifeq ($(CONFIG_DMA_BUF_LOCK), y) -obj-m := dma_buf_lock.o +bifrost_kbase-y += \ + hwcnt/mali_kbase_hwcnt.o \ + hwcnt/mali_kbase_hwcnt_gpu.o \ + hwcnt/mali_kbase_hwcnt_gpu_narrow.o \ + hwcnt/mali_kbase_hwcnt_types.o \ + hwcnt/mali_kbase_hwcnt_virtualizer.o \ + hwcnt/mali_kbase_hwcnt_watchdog_if_timer.o + +ifeq ($(CONFIG_MALI_CSF_SUPPORT),y) + bifrost_kbase-y += \ + hwcnt/backend/mali_kbase_hwcnt_backend_csf.o \ + hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.o +else + bifrost_kbase-y += \ + hwcnt/backend/mali_kbase_hwcnt_backend_jm.o \ + hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.o endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend.h b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend.h similarity index 85% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend.h rename to drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend.h index b069fc12be69..6cfa6f5ee6f4 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend.h +++ b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2018, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 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 @@ -56,8 +56,8 @@ struct kbase_hwcnt_backend; * * Return: Non-NULL pointer to immutable hardware counter metadata. */ -typedef const struct kbase_hwcnt_metadata *kbase_hwcnt_backend_metadata_fn( - const struct kbase_hwcnt_backend_info *info); +typedef const struct kbase_hwcnt_metadata * +kbase_hwcnt_backend_metadata_fn(const struct kbase_hwcnt_backend_info *info); /** * typedef kbase_hwcnt_backend_init_fn - Initialise a counter backend. @@ -69,9 +69,8 @@ typedef const struct kbase_hwcnt_metadata *kbase_hwcnt_backend_metadata_fn( * * Return: 0 on success, else error code. */ -typedef int kbase_hwcnt_backend_init_fn( - const struct kbase_hwcnt_backend_info *info, - struct kbase_hwcnt_backend **out_backend); +typedef int kbase_hwcnt_backend_init_fn(const struct kbase_hwcnt_backend_info *info, + struct kbase_hwcnt_backend **out_backend); /** * typedef kbase_hwcnt_backend_term_fn - Terminate a counter backend. @@ -86,8 +85,7 @@ typedef void kbase_hwcnt_backend_term_fn(struct kbase_hwcnt_backend *backend); * * Return: Backend timestamp in nanoseconds. */ -typedef u64 kbase_hwcnt_backend_timestamp_ns_fn( - struct kbase_hwcnt_backend *backend); +typedef u64 kbase_hwcnt_backend_timestamp_ns_fn(struct kbase_hwcnt_backend *backend); /** * typedef kbase_hwcnt_backend_dump_enable_fn - Start counter dumping with the @@ -102,9 +100,8 @@ typedef u64 kbase_hwcnt_backend_timestamp_ns_fn( * * Return: 0 on success, else error code. */ -typedef int kbase_hwcnt_backend_dump_enable_fn( - struct kbase_hwcnt_backend *backend, - const struct kbase_hwcnt_enable_map *enable_map); +typedef int kbase_hwcnt_backend_dump_enable_fn(struct kbase_hwcnt_backend *backend, + const struct kbase_hwcnt_enable_map *enable_map); /** * typedef kbase_hwcnt_backend_dump_enable_nolock_fn - Start counter dumping @@ -118,9 +115,9 @@ typedef int kbase_hwcnt_backend_dump_enable_fn( * * Return: 0 on success, else error code. */ -typedef int kbase_hwcnt_backend_dump_enable_nolock_fn( - struct kbase_hwcnt_backend *backend, - const struct kbase_hwcnt_enable_map *enable_map); +typedef int +kbase_hwcnt_backend_dump_enable_nolock_fn(struct kbase_hwcnt_backend *backend, + const struct kbase_hwcnt_enable_map *enable_map); /** * typedef kbase_hwcnt_backend_dump_disable_fn - Disable counter dumping with @@ -130,8 +127,7 @@ typedef int kbase_hwcnt_backend_dump_enable_nolock_fn( * If the backend is already disabled, does nothing. * Any undumped counter values since the last dump get will be lost. */ -typedef void kbase_hwcnt_backend_dump_disable_fn( - struct kbase_hwcnt_backend *backend); +typedef void kbase_hwcnt_backend_dump_disable_fn(struct kbase_hwcnt_backend *backend); /** * typedef kbase_hwcnt_backend_dump_clear_fn - Reset all the current undumped @@ -142,8 +138,7 @@ typedef void kbase_hwcnt_backend_dump_disable_fn( * * Return: 0 on success, else error code. */ -typedef int kbase_hwcnt_backend_dump_clear_fn( - struct kbase_hwcnt_backend *backend); +typedef int kbase_hwcnt_backend_dump_clear_fn(struct kbase_hwcnt_backend *backend); /** * typedef kbase_hwcnt_backend_dump_request_fn - Request an asynchronous counter @@ -157,9 +152,8 @@ typedef int kbase_hwcnt_backend_dump_clear_fn( * * Return: 0 on success, else error code. */ -typedef int kbase_hwcnt_backend_dump_request_fn( - struct kbase_hwcnt_backend *backend, - u64 *dump_time_ns); +typedef int kbase_hwcnt_backend_dump_request_fn(struct kbase_hwcnt_backend *backend, + u64 *dump_time_ns); /** * typedef kbase_hwcnt_backend_dump_wait_fn - Wait until the last requested @@ -170,8 +164,7 @@ typedef int kbase_hwcnt_backend_dump_request_fn( * * Return: 0 on success, else error code. */ -typedef int kbase_hwcnt_backend_dump_wait_fn( - struct kbase_hwcnt_backend *backend); +typedef int kbase_hwcnt_backend_dump_wait_fn(struct kbase_hwcnt_backend *backend); /** * typedef kbase_hwcnt_backend_dump_get_fn - Copy or accumulate enable the @@ -189,11 +182,10 @@ typedef int kbase_hwcnt_backend_dump_wait_fn( * * Return: 0 on success, else error code. */ -typedef int kbase_hwcnt_backend_dump_get_fn( - struct kbase_hwcnt_backend *backend, - struct kbase_hwcnt_dump_buffer *dump_buffer, - const struct kbase_hwcnt_enable_map *enable_map, - bool accumulate); +typedef int kbase_hwcnt_backend_dump_get_fn(struct kbase_hwcnt_backend *backend, + struct kbase_hwcnt_dump_buffer *dump_buffer, + const struct kbase_hwcnt_enable_map *enable_map, + bool accumulate); /** * struct kbase_hwcnt_backend_interface - Hardware counter backend virtual diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf.c b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf.c similarity index 76% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf.c rename to drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf.c index 8afc990662da..10d40bedc0f8 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf.c +++ b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf.c @@ -19,9 +19,9 @@ * */ -#include "mali_kbase_hwcnt_backend_csf.h" -#include "mali_kbase_hwcnt_gpu.h" -#include "mali_kbase_hwcnt_types.h" +#include "hwcnt/backend/mali_kbase_hwcnt_backend_csf.h" +#include "hwcnt/mali_kbase_hwcnt_gpu.h" +#include "hwcnt/mali_kbase_hwcnt_types.h" #include #include @@ -267,8 +267,7 @@ struct kbase_hwcnt_backend_csf { struct work_struct hwc_threshold_work; }; -static bool kbasep_hwcnt_backend_csf_backend_exists( - struct kbase_hwcnt_backend_csf_info *csf_info) +static bool kbasep_hwcnt_backend_csf_backend_exists(struct kbase_hwcnt_backend_csf_info *csf_info) { WARN_ON(!csf_info); csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx); @@ -282,19 +281,20 @@ static bool kbasep_hwcnt_backend_csf_backend_exists( * @backend_csf: Non-NULL pointer to backend. * @enable_map: Non-NULL pointer to enable map specifying enabled counters. */ -static void kbasep_hwcnt_backend_csf_cc_initial_sample( - struct kbase_hwcnt_backend_csf *backend_csf, - const struct kbase_hwcnt_enable_map *enable_map) +static void +kbasep_hwcnt_backend_csf_cc_initial_sample(struct kbase_hwcnt_backend_csf *backend_csf, + const struct kbase_hwcnt_enable_map *enable_map) { u64 clk_enable_map = enable_map->clk_enable_map; u64 cycle_counts[BASE_MAX_NR_CLOCKS_REGULATORS]; size_t clk; /* Read cycle count from CSF interface for both clock domains. */ - backend_csf->info->csf_if->get_gpu_cycle_count( - backend_csf->info->csf_if->ctx, cycle_counts, clk_enable_map); + backend_csf->info->csf_if->get_gpu_cycle_count(backend_csf->info->csf_if->ctx, cycle_counts, + clk_enable_map); - kbase_hwcnt_metadata_for_each_clock(enable_map->metadata, clk) { + kbase_hwcnt_metadata_for_each_clock(enable_map->metadata, clk) + { if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, clk)) backend_csf->prev_cycle_count[clk] = cycle_counts[clk]; } @@ -303,42 +303,35 @@ static void kbasep_hwcnt_backend_csf_cc_initial_sample( backend_csf->clk_enable_map = clk_enable_map; } -static void -kbasep_hwcnt_backend_csf_cc_update(struct kbase_hwcnt_backend_csf *backend_csf) +static void kbasep_hwcnt_backend_csf_cc_update(struct kbase_hwcnt_backend_csf *backend_csf) { u64 cycle_counts[BASE_MAX_NR_CLOCKS_REGULATORS]; size_t clk; - backend_csf->info->csf_if->assert_lock_held( - backend_csf->info->csf_if->ctx); + backend_csf->info->csf_if->assert_lock_held(backend_csf->info->csf_if->ctx); - backend_csf->info->csf_if->get_gpu_cycle_count( - backend_csf->info->csf_if->ctx, cycle_counts, - backend_csf->clk_enable_map); + backend_csf->info->csf_if->get_gpu_cycle_count(backend_csf->info->csf_if->ctx, cycle_counts, + backend_csf->clk_enable_map); - kbase_hwcnt_metadata_for_each_clock(backend_csf->info->metadata, clk) { - if (kbase_hwcnt_clk_enable_map_enabled( - backend_csf->clk_enable_map, clk)) { + kbase_hwcnt_metadata_for_each_clock(backend_csf->info->metadata, clk) + { + if (kbase_hwcnt_clk_enable_map_enabled(backend_csf->clk_enable_map, clk)) { backend_csf->cycle_count_elapsed[clk] = - cycle_counts[clk] - - backend_csf->prev_cycle_count[clk]; + cycle_counts[clk] - backend_csf->prev_cycle_count[clk]; backend_csf->prev_cycle_count[clk] = cycle_counts[clk]; } } } /* CSF backend implementation of kbase_hwcnt_backend_timestamp_ns_fn */ -static u64 -kbasep_hwcnt_backend_csf_timestamp_ns(struct kbase_hwcnt_backend *backend) +static u64 kbasep_hwcnt_backend_csf_timestamp_ns(struct kbase_hwcnt_backend *backend) { - struct kbase_hwcnt_backend_csf *backend_csf = - (struct kbase_hwcnt_backend_csf *)backend; + struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend; if (!backend_csf || !backend_csf->info || !backend_csf->info->csf_if) return 0; - return backend_csf->info->csf_if->timestamp_ns( - backend_csf->info->csf_if->ctx); + return backend_csf->info->csf_if->timestamp_ns(backend_csf->info->csf_if->ctx); } /** kbasep_hwcnt_backend_csf_process_enable_map() - Process the enable_map to @@ -347,8 +340,8 @@ kbasep_hwcnt_backend_csf_timestamp_ns(struct kbase_hwcnt_backend *backend) * required. *@phys_enable_map: HWC physical enable map to be processed. */ -static void kbasep_hwcnt_backend_csf_process_enable_map( - struct kbase_hwcnt_physical_enable_map *phys_enable_map) +static void +kbasep_hwcnt_backend_csf_process_enable_map(struct kbase_hwcnt_physical_enable_map *phys_enable_map) { WARN_ON(!phys_enable_map); @@ -408,19 +401,19 @@ static void kbasep_hwcnt_backend_csf_init_layout( }; } -static void kbasep_hwcnt_backend_csf_reset_internal_buffers( - struct kbase_hwcnt_backend_csf *backend_csf) +static void +kbasep_hwcnt_backend_csf_reset_internal_buffers(struct kbase_hwcnt_backend_csf *backend_csf) { size_t user_buf_bytes = backend_csf->info->metadata->dump_buf_bytes; memset(backend_csf->to_user_buf, 0, user_buf_bytes); memset(backend_csf->accum_buf, 0, user_buf_bytes); - memset(backend_csf->old_sample_buf, 0, - backend_csf->info->prfcnt_info.dump_bytes); + memset(backend_csf->old_sample_buf, 0, backend_csf->info->prfcnt_info.dump_bytes); } -static void kbasep_hwcnt_backend_csf_zero_sample_prfcnt_en_header( - struct kbase_hwcnt_backend_csf *backend_csf, u32 *sample) +static void +kbasep_hwcnt_backend_csf_zero_sample_prfcnt_en_header(struct kbase_hwcnt_backend_csf *backend_csf, + u32 *sample) { u32 block_idx; const struct kbase_hwcnt_csf_physical_layout *phys_layout; @@ -434,8 +427,8 @@ static void kbasep_hwcnt_backend_csf_zero_sample_prfcnt_en_header( } } -static void kbasep_hwcnt_backend_csf_zero_all_prfcnt_en_header( - struct kbase_hwcnt_backend_csf *backend_csf) +static void +kbasep_hwcnt_backend_csf_zero_all_prfcnt_en_header(struct kbase_hwcnt_backend_csf *backend_csf) { u32 idx; u32 *sample; @@ -446,19 +439,16 @@ static void kbasep_hwcnt_backend_csf_zero_all_prfcnt_en_header( for (idx = 0; idx < backend_csf->info->ring_buf_cnt; idx++) { sample = (u32 *)&cpu_dump_base[idx * dump_bytes]; - kbasep_hwcnt_backend_csf_zero_sample_prfcnt_en_header( - backend_csf, sample); + kbasep_hwcnt_backend_csf_zero_sample_prfcnt_en_header(backend_csf, sample); } } -static void kbasep_hwcnt_backend_csf_update_user_sample( - struct kbase_hwcnt_backend_csf *backend_csf) +static void kbasep_hwcnt_backend_csf_update_user_sample(struct kbase_hwcnt_backend_csf *backend_csf) { size_t user_buf_bytes = backend_csf->info->metadata->dump_buf_bytes; /* Copy the data into the sample and wait for the user to get it. */ - memcpy(backend_csf->to_user_buf, backend_csf->accum_buf, - user_buf_bytes); + memcpy(backend_csf->to_user_buf, backend_csf->accum_buf, user_buf_bytes); /* After copied data into user sample, clear the accumulator values to * prepare for the next accumulator, such as the next request or @@ -468,9 +458,8 @@ static void kbasep_hwcnt_backend_csf_update_user_sample( } static void kbasep_hwcnt_backend_csf_accumulate_sample( - const struct kbase_hwcnt_csf_physical_layout *phys_layout, - size_t dump_bytes, u64 *accum_buf, const u32 *old_sample_buf, - const u32 *new_sample_buf, bool clearing_samples) + const struct kbase_hwcnt_csf_physical_layout *phys_layout, size_t dump_bytes, + u64 *accum_buf, const u32 *old_sample_buf, const u32 *new_sample_buf, bool clearing_samples) { size_t block_idx; const u32 *old_block = old_sample_buf; @@ -487,10 +476,8 @@ static void kbasep_hwcnt_backend_csf_accumulate_sample( 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 = - new_block[phys_layout->enable_mask_offset]; + const u32 old_enable_mask = old_block[phys_layout->enable_mask_offset]; + const u32 new_enable_mask = new_block[phys_layout->enable_mask_offset]; if (new_enable_mask == 0) { /* Hardware block was unavailable or we didn't turn on @@ -503,9 +490,7 @@ static void kbasep_hwcnt_backend_csf_accumulate_sample( size_t ctr_idx; /* Unconditionally copy the headers. */ - for (ctr_idx = 0; - ctr_idx < phys_layout->headers_per_block; - ctr_idx++) { + for (ctr_idx = 0; ctr_idx < phys_layout->headers_per_block; ctr_idx++) { acc_block[ctr_idx] = new_block[ctr_idx]; } @@ -534,34 +519,25 @@ static void kbasep_hwcnt_backend_csf_accumulate_sample( * counters only, as we know previous * values are zeroes. */ - for (ctr_idx = - phys_layout - ->headers_per_block; - ctr_idx < values_per_block; - ctr_idx++) { - acc_block[ctr_idx] += - new_block[ctr_idx]; + for (ctr_idx = phys_layout->headers_per_block; + ctr_idx < values_per_block; ctr_idx++) { + acc_block[ctr_idx] += new_block[ctr_idx]; } } else { /* Hardware block was previously * available. Accumulate the delta * between old and new counter values. */ - for (ctr_idx = - phys_layout - ->headers_per_block; - ctr_idx < values_per_block; - ctr_idx++) { + for (ctr_idx = phys_layout->headers_per_block; + ctr_idx < values_per_block; ctr_idx++) { acc_block[ctr_idx] += - new_block[ctr_idx] - - old_block[ctr_idx]; + new_block[ctr_idx] - old_block[ctr_idx]; } } } else { for (ctr_idx = phys_layout->headers_per_block; ctr_idx < values_per_block; ctr_idx++) { - acc_block[ctr_idx] += - new_block[ctr_idx]; + acc_block[ctr_idx] += new_block[ctr_idx]; } } } @@ -570,18 +546,16 @@ static void kbasep_hwcnt_backend_csf_accumulate_sample( acc_block += values_per_block; } - WARN_ON(old_block != - 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(old_block != 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) - (values_per_block * phys_layout->fw_block_cnt)); (void)dump_bytes; } -static void kbasep_hwcnt_backend_csf_accumulate_samples( - struct kbase_hwcnt_backend_csf *backend_csf, u32 extract_index_to_start, - u32 insert_index_to_stop) +static void kbasep_hwcnt_backend_csf_accumulate_samples(struct kbase_hwcnt_backend_csf *backend_csf, + u32 extract_index_to_start, + u32 insert_index_to_stop) { u32 raw_idx; unsigned long flags; @@ -598,25 +572,22 @@ static void kbasep_hwcnt_backend_csf_accumulate_samples( /* Sync all the buffers to CPU side before read the data. */ backend_csf->info->csf_if->ring_buf_sync(backend_csf->info->csf_if->ctx, - backend_csf->ring_buf, - extract_index_to_start, + backend_csf->ring_buf, extract_index_to_start, insert_index_to_stop, true); /* Consider u32 wrap case, '!=' is used here instead of '<' operator */ - for (raw_idx = extract_index_to_start; raw_idx != insert_index_to_stop; - raw_idx++) { + for (raw_idx = extract_index_to_start; raw_idx != insert_index_to_stop; raw_idx++) { /* The logical "&" acts as a modulo operation since buf_count * must be a power of two. */ const u32 buf_idx = raw_idx & (ring_buf_cnt - 1); - new_sample_buf = - (u32 *)&cpu_dump_base[buf_idx * buf_dump_bytes]; + new_sample_buf = (u32 *)&cpu_dump_base[buf_idx * buf_dump_bytes]; - kbasep_hwcnt_backend_csf_accumulate_sample( - &backend_csf->phys_layout, buf_dump_bytes, - backend_csf->accum_buf, old_sample_buf, new_sample_buf, - clearing_samples); + kbasep_hwcnt_backend_csf_accumulate_sample(&backend_csf->phys_layout, + buf_dump_bytes, backend_csf->accum_buf, + old_sample_buf, new_sample_buf, + clearing_samples); old_sample_buf = new_sample_buf; } @@ -625,19 +596,16 @@ static void kbasep_hwcnt_backend_csf_accumulate_samples( memcpy(backend_csf->old_sample_buf, new_sample_buf, buf_dump_bytes); /* Reset the prfcnt_en header on each sample before releasing them. */ - for (raw_idx = extract_index_to_start; raw_idx != insert_index_to_stop; - raw_idx++) { + for (raw_idx = extract_index_to_start; raw_idx != insert_index_to_stop; raw_idx++) { const u32 buf_idx = raw_idx & (ring_buf_cnt - 1); u32 *sample = (u32 *)&cpu_dump_base[buf_idx * buf_dump_bytes]; - kbasep_hwcnt_backend_csf_zero_sample_prfcnt_en_header( - backend_csf, sample); + kbasep_hwcnt_backend_csf_zero_sample_prfcnt_en_header(backend_csf, sample); } /* Sync zeroed buffers to avoid coherency issues on future use. */ backend_csf->info->csf_if->ring_buf_sync(backend_csf->info->csf_if->ctx, - backend_csf->ring_buf, - extract_index_to_start, + backend_csf->ring_buf, extract_index_to_start, insert_index_to_stop, false); /* After consuming all samples between extract_idx and insert_idx, @@ -645,22 +613,20 @@ static void kbasep_hwcnt_backend_csf_accumulate_samples( * can be released back to the ring buffer pool. */ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags); - backend_csf->info->csf_if->set_extract_index( - backend_csf->info->csf_if->ctx, insert_index_to_stop); + backend_csf->info->csf_if->set_extract_index(backend_csf->info->csf_if->ctx, + insert_index_to_stop); /* Update the watchdog last seen index to check any new FW auto samples * in next watchdog callback. */ backend_csf->watchdog_last_seen_insert_idx = insert_index_to_stop; - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, - flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); } static void kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( struct kbase_hwcnt_backend_csf *backend_csf, enum kbase_hwcnt_backend_csf_enable_state new_state) { - backend_csf->info->csf_if->assert_lock_held( - backend_csf->info->csf_if->ctx); + backend_csf->info->csf_if->assert_lock_held(backend_csf->info->csf_if->ctx); if (backend_csf->enable_state != new_state) { backend_csf->enable_state = new_state; @@ -691,26 +657,22 @@ static void kbasep_hwcnt_backend_watchdog_timer_cb(void *info) (!csf_info->fw_in_protected_mode) && /* 3. dump state indicates no other dumping is in progress. */ ((backend_csf->dump_state == KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE) || - (backend_csf->dump_state == - KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED))) { + (backend_csf->dump_state == KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED))) { u32 extract_index; u32 insert_index; /* Read the raw extract and insert indexes from the CSF interface. */ - csf_info->csf_if->get_indexes(csf_info->csf_if->ctx, - &extract_index, &insert_index); + csf_info->csf_if->get_indexes(csf_info->csf_if->ctx, &extract_index, &insert_index); /* Do watchdog request if no new FW auto samples. */ - if (insert_index == - backend_csf->watchdog_last_seen_insert_idx) { + if (insert_index == backend_csf->watchdog_last_seen_insert_idx) { /* Trigger the watchdog request. */ csf_info->csf_if->dump_request(csf_info->csf_if->ctx); /* A watchdog dump is required, change the state to * start the request process. */ - backend_csf->dump_state = - KBASE_HWCNT_BACKEND_CSF_DUMP_WATCHDOG_REQUESTED; + backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_WATCHDOG_REQUESTED; } } @@ -719,12 +681,10 @@ static void kbasep_hwcnt_backend_watchdog_timer_cb(void *info) * counter enabled interrupt. */ if ((backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) || - (backend_csf->enable_state == - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED)) { + (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED)) { /* Reschedule the timer for next watchdog callback. */ - csf_info->watchdog_if->modify( - csf_info->watchdog_if->timer, - HWCNT_BACKEND_WATCHDOG_TIMER_INTERVAL_MS); + csf_info->watchdog_if->modify(csf_info->watchdog_if->timer, + HWCNT_BACKEND_WATCHDOG_TIMER_INTERVAL_MS); } csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); @@ -747,8 +707,7 @@ static void kbasep_hwcnt_backend_csf_dump_worker(struct work_struct *work) u32 insert_index; WARN_ON(!work); - backend_csf = container_of(work, struct kbase_hwcnt_backend_csf, - hwc_dump_work); + backend_csf = container_of(work, struct kbase_hwcnt_backend_csf, hwc_dump_work); backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags); /* Assert the backend is not destroyed. */ WARN_ON(backend_csf != backend_csf->info->backend); @@ -757,26 +716,22 @@ static void kbasep_hwcnt_backend_csf_dump_worker(struct work_struct *work) * launched. */ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_ENABLED) { - WARN_ON(backend_csf->dump_state != - KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE); + WARN_ON(backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE); WARN_ON(!completion_done(&backend_csf->dump_completed)); - backend_csf->info->csf_if->unlock( - backend_csf->info->csf_if->ctx, flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); return; } - WARN_ON(backend_csf->dump_state != - KBASE_HWCNT_BACKEND_CSF_DUMP_WORKER_LAUNCHED); + WARN_ON(backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_WORKER_LAUNCHED); backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_ACCUMULATING; insert_index_to_acc = backend_csf->insert_index_to_accumulate; /* Read the raw extract and insert indexes from the CSF interface. */ - backend_csf->info->csf_if->get_indexes(backend_csf->info->csf_if->ctx, - &extract_index, &insert_index); + backend_csf->info->csf_if->get_indexes(backend_csf->info->csf_if->ctx, &extract_index, + &insert_index); - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, - flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); /* Accumulate up to the insert we grabbed at the prfcnt request * interrupt. @@ -797,22 +752,18 @@ static void kbasep_hwcnt_backend_csf_dump_worker(struct work_struct *work) /* The backend was disabled or had an error while we were accumulating. */ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_ENABLED) { - WARN_ON(backend_csf->dump_state != - KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE); + WARN_ON(backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE); WARN_ON(!completion_done(&backend_csf->dump_completed)); - backend_csf->info->csf_if->unlock( - backend_csf->info->csf_if->ctx, flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); return; } - WARN_ON(backend_csf->dump_state != - KBASE_HWCNT_BACKEND_CSF_DUMP_ACCUMULATING); + WARN_ON(backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_ACCUMULATING); /* Our work here is done - set the wait object and unblock waiters. */ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED; complete_all(&backend_csf->dump_completed); - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, - flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); } /** @@ -832,23 +783,21 @@ static void kbasep_hwcnt_backend_csf_threshold_worker(struct work_struct *work) WARN_ON(!work); - backend_csf = container_of(work, struct kbase_hwcnt_backend_csf, - hwc_threshold_work); + backend_csf = container_of(work, struct kbase_hwcnt_backend_csf, hwc_threshold_work); backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags); /* Assert the backend is not destroyed. */ WARN_ON(backend_csf != backend_csf->info->backend); /* Read the raw extract and insert indexes from the CSF interface. */ - backend_csf->info->csf_if->get_indexes(backend_csf->info->csf_if->ctx, - &extract_index, &insert_index); + backend_csf->info->csf_if->get_indexes(backend_csf->info->csf_if->ctx, &extract_index, + &insert_index); /* The backend was disabled or had an error while the worker was being * launched. */ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_ENABLED) { - backend_csf->info->csf_if->unlock( - backend_csf->info->csf_if->ctx, flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); return; } @@ -857,14 +806,11 @@ static void kbasep_hwcnt_backend_csf_threshold_worker(struct work_struct *work) * interfere. */ if ((backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE) && - (backend_csf->dump_state != - KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED)) { - backend_csf->info->csf_if->unlock( - backend_csf->info->csf_if->ctx, flags); + (backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED)) { + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); return; } - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, - flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); /* Accumulate everything we possibly can. We grabbed the insert index * immediately after we acquired the lock but before we checked whether @@ -873,14 +819,13 @@ static void kbasep_hwcnt_backend_csf_threshold_worker(struct work_struct *work) * fact that our insert will not exceed the concurrent dump's * insert_to_accumulate, so we don't risk accumulating too much data. */ - kbasep_hwcnt_backend_csf_accumulate_samples(backend_csf, extract_index, - insert_index); + kbasep_hwcnt_backend_csf_accumulate_samples(backend_csf, extract_index, insert_index); /* No need to wake up anything since it is not a user dump request. */ } -static void kbase_hwcnt_backend_csf_submit_dump_worker( - struct kbase_hwcnt_backend_csf_info *csf_info) +static void +kbase_hwcnt_backend_csf_submit_dump_worker(struct kbase_hwcnt_backend_csf_info *csf_info) { u32 extract_index; @@ -888,31 +833,26 @@ static void kbase_hwcnt_backend_csf_submit_dump_worker( csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx); WARN_ON(!kbasep_hwcnt_backend_csf_backend_exists(csf_info)); - WARN_ON(csf_info->backend->enable_state != - KBASE_HWCNT_BACKEND_CSF_ENABLED); - WARN_ON(csf_info->backend->dump_state != - KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT); + WARN_ON(csf_info->backend->enable_state != KBASE_HWCNT_BACKEND_CSF_ENABLED); + WARN_ON(csf_info->backend->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT); /* Save insert index now so that the dump worker only accumulates the * HWC data associated with this request. Extract index is not stored * as that needs to be checked when accumulating to prevent re-reading * buffers that have already been read and returned to the GPU. */ - csf_info->csf_if->get_indexes( - csf_info->csf_if->ctx, &extract_index, - &csf_info->backend->insert_index_to_accumulate); - csf_info->backend->dump_state = - KBASE_HWCNT_BACKEND_CSF_DUMP_WORKER_LAUNCHED; + csf_info->csf_if->get_indexes(csf_info->csf_if->ctx, &extract_index, + &csf_info->backend->insert_index_to_accumulate); + csf_info->backend->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_WORKER_LAUNCHED; /* Submit the accumulator task into the work queue. */ - queue_work(csf_info->backend->hwc_dump_workq, - &csf_info->backend->hwc_dump_work); + queue_work(csf_info->backend->hwc_dump_workq, &csf_info->backend->hwc_dump_work); } -static void kbasep_hwcnt_backend_csf_get_physical_enable( - struct kbase_hwcnt_backend_csf *backend_csf, - const struct kbase_hwcnt_enable_map *enable_map, - struct kbase_hwcnt_backend_csf_if_enable *enable) +static void +kbasep_hwcnt_backend_csf_get_physical_enable(struct kbase_hwcnt_backend_csf *backend_csf, + const struct kbase_hwcnt_enable_map *enable_map, + struct kbase_hwcnt_backend_csf_if_enable *enable) { enum kbase_hwcnt_physical_set phys_counter_set; struct kbase_hwcnt_physical_enable_map phys_enable_map; @@ -924,8 +864,7 @@ static void kbasep_hwcnt_backend_csf_get_physical_enable( */ kbasep_hwcnt_backend_csf_process_enable_map(&phys_enable_map); - kbase_hwcnt_gpu_set_to_physical(&phys_counter_set, - backend_csf->info->counter_set); + kbase_hwcnt_gpu_set_to_physical(&phys_counter_set, backend_csf->info->counter_set); /* Use processed enable_map to enable HWC in HW level. */ enable->fe_bm = phys_enable_map.fe_bm; @@ -937,33 +876,29 @@ static void kbasep_hwcnt_backend_csf_get_physical_enable( } /* CSF backend implementation of kbase_hwcnt_backend_dump_enable_nolock_fn */ -static int kbasep_hwcnt_backend_csf_dump_enable_nolock( - struct kbase_hwcnt_backend *backend, - const struct kbase_hwcnt_enable_map *enable_map) +static int +kbasep_hwcnt_backend_csf_dump_enable_nolock(struct kbase_hwcnt_backend *backend, + const struct kbase_hwcnt_enable_map *enable_map) { - struct kbase_hwcnt_backend_csf *backend_csf = - (struct kbase_hwcnt_backend_csf *)backend; + struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend; struct kbase_hwcnt_backend_csf_if_enable enable; int err; - if (!backend_csf || !enable_map || - (enable_map->metadata != backend_csf->info->metadata)) + if (!backend_csf || !enable_map || (enable_map->metadata != backend_csf->info->metadata)) return -EINVAL; - backend_csf->info->csf_if->assert_lock_held( - backend_csf->info->csf_if->ctx); + backend_csf->info->csf_if->assert_lock_held(backend_csf->info->csf_if->ctx); - kbasep_hwcnt_backend_csf_get_physical_enable(backend_csf, enable_map, - &enable); + kbasep_hwcnt_backend_csf_get_physical_enable(backend_csf, enable_map, &enable); /* enable_state should be DISABLED before we transfer it to enabled */ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_DISABLED) return -EIO; - err = backend_csf->info->watchdog_if->enable( - backend_csf->info->watchdog_if->timer, - HWCNT_BACKEND_WATCHDOG_TIMER_INTERVAL_MS, - kbasep_hwcnt_backend_watchdog_timer_cb, backend_csf->info); + err = backend_csf->info->watchdog_if->enable(backend_csf->info->watchdog_if->timer, + HWCNT_BACKEND_WATCHDOG_TIMER_INTERVAL_MS, + kbasep_hwcnt_backend_watchdog_timer_cb, + backend_csf->info); if (err) return err; @@ -981,58 +916,46 @@ static int kbasep_hwcnt_backend_csf_dump_enable_nolock( } /* CSF backend implementation of kbase_hwcnt_backend_dump_enable_fn */ -static int kbasep_hwcnt_backend_csf_dump_enable( - struct kbase_hwcnt_backend *backend, - const struct kbase_hwcnt_enable_map *enable_map) +static int kbasep_hwcnt_backend_csf_dump_enable(struct kbase_hwcnt_backend *backend, + const struct kbase_hwcnt_enable_map *enable_map) { int errcode; unsigned long flags; - struct kbase_hwcnt_backend_csf *backend_csf = - (struct kbase_hwcnt_backend_csf *)backend; + struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend; if (!backend_csf) return -EINVAL; backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags); - errcode = kbasep_hwcnt_backend_csf_dump_enable_nolock(backend, - enable_map); - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, - flags); + errcode = kbasep_hwcnt_backend_csf_dump_enable_nolock(backend, enable_map); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); return errcode; } static void kbasep_hwcnt_backend_csf_wait_enable_transition_complete( struct kbase_hwcnt_backend_csf *backend_csf, unsigned long *lock_flags) { - backend_csf->info->csf_if->assert_lock_held( - backend_csf->info->csf_if->ctx); + backend_csf->info->csf_if->assert_lock_held(backend_csf->info->csf_if->ctx); - while ((backend_csf->enable_state == - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) || - (backend_csf->enable_state == - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED)) { - backend_csf->info->csf_if->unlock( - backend_csf->info->csf_if->ctx, *lock_flags); + while ((backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) || + (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED)) { + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, *lock_flags); - wait_event( - backend_csf->enable_state_waitq, - (backend_csf->enable_state != - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) && - (backend_csf->enable_state != - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED)); + wait_event(backend_csf->enable_state_waitq, + (backend_csf->enable_state != + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) && + (backend_csf->enable_state != + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED)); - backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, - lock_flags); + backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, lock_flags); } } /* CSF backend implementation of kbase_hwcnt_backend_dump_disable_fn */ -static void -kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *backend) +static void kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *backend) { unsigned long flags; - struct kbase_hwcnt_backend_csf *backend_csf = - (struct kbase_hwcnt_backend_csf *)backend; + struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend; bool do_disable = false; WARN_ON(!backend_csf); @@ -1042,24 +965,20 @@ kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *backend) /* Make sure we wait until any previous enable or disable have completed * before doing anything. */ - kbasep_hwcnt_backend_csf_wait_enable_transition_complete(backend_csf, - &flags); + kbasep_hwcnt_backend_csf_wait_enable_transition_complete(backend_csf, &flags); if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_DISABLED || - backend_csf->enable_state == - KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) { + backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) { /* If we are already disabled or in an unrecoverable error * state, there is nothing for us to do. */ - backend_csf->info->csf_if->unlock( - backend_csf->info->csf_if->ctx, flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); return; } if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) { kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED); + backend_csf, KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED); backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE; complete_all(&backend_csf->dump_completed); /* Only disable if we were previously enabled - in all other @@ -1071,15 +990,13 @@ kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *backend) WARN_ON(backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE); WARN_ON(!completion_done(&backend_csf->dump_completed)); - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, - flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); /* Deregister the timer and block until any timer callback has completed. * We've transitioned out of the ENABLED state so we can guarantee it * won't reschedule itself. */ - backend_csf->info->watchdog_if->disable( - backend_csf->info->watchdog_if->timer); + backend_csf->info->watchdog_if->disable(backend_csf->info->watchdog_if->timer); /* Block until any async work has completed. We have transitioned out of * the ENABLED state so we can guarantee no new work will concurrently @@ -1090,11 +1007,9 @@ kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *backend) backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags); if (do_disable) - backend_csf->info->csf_if->dump_disable( - backend_csf->info->csf_if->ctx); + backend_csf->info->csf_if->dump_disable(backend_csf->info->csf_if->ctx); - kbasep_hwcnt_backend_csf_wait_enable_transition_complete(backend_csf, - &flags); + kbasep_hwcnt_backend_csf_wait_enable_transition_complete(backend_csf, &flags); switch (backend_csf->enable_state) { case KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER: @@ -1103,8 +1018,7 @@ kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *backend) break; case KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER: kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, - KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR); + backend_csf, KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR); break; default: WARN_ON(true); @@ -1114,8 +1028,7 @@ kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *backend) backend_csf->user_requested = false; backend_csf->watchdog_last_seen_insert_idx = 0; - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, - flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); /* After disable, zero the header of all buffers in the ring buffer back * to 0 to prepare for the next enable. @@ -1123,9 +1036,9 @@ kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *backend) kbasep_hwcnt_backend_csf_zero_all_prfcnt_en_header(backend_csf); /* Sync zeroed buffers to avoid coherency issues on future use. */ - backend_csf->info->csf_if->ring_buf_sync( - backend_csf->info->csf_if->ctx, backend_csf->ring_buf, 0, - backend_csf->info->ring_buf_cnt, false); + backend_csf->info->csf_if->ring_buf_sync(backend_csf->info->csf_if->ctx, + backend_csf->ring_buf, 0, + backend_csf->info->ring_buf_cnt, false); /* Reset accumulator, old_sample_buf and user_sample to all-0 to prepare * for next enable. @@ -1134,13 +1047,11 @@ kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *backend) } /* CSF backend implementation of kbase_hwcnt_backend_dump_request_fn */ -static int -kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *backend, - u64 *dump_time_ns) +static int kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *backend, + u64 *dump_time_ns) { unsigned long flags; - struct kbase_hwcnt_backend_csf *backend_csf = - (struct kbase_hwcnt_backend_csf *)backend; + struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend; bool do_request = false; bool watchdog_dumping = false; @@ -1153,22 +1064,18 @@ kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *backend, * the user dump buffer is already zeroed. We can just short circuit to * the DUMP_COMPLETED state. */ - if (backend_csf->enable_state == - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) { - backend_csf->dump_state = - KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED; + if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) { + backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED; *dump_time_ns = kbasep_hwcnt_backend_csf_timestamp_ns(backend); kbasep_hwcnt_backend_csf_cc_update(backend_csf); backend_csf->user_requested = true; - backend_csf->info->csf_if->unlock( - backend_csf->info->csf_if->ctx, flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); return 0; } /* Otherwise, make sure we're already enabled. */ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_ENABLED) { - backend_csf->info->csf_if->unlock( - backend_csf->info->csf_if->ctx, flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); return -EIO; } @@ -1181,15 +1088,12 @@ kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *backend, * request can be processed instead of ignored. */ if ((backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE) && - (backend_csf->dump_state != - KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED) && - (backend_csf->dump_state != - KBASE_HWCNT_BACKEND_CSF_DUMP_WATCHDOG_REQUESTED)) { + (backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED) && + (backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_WATCHDOG_REQUESTED)) { /* HWC is disabled or another user dump is ongoing, * or we're on fault. */ - backend_csf->info->csf_if->unlock( - backend_csf->info->csf_if->ctx, flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); /* HWC is disabled or another dump is ongoing, or we are on * fault. */ @@ -1199,8 +1103,7 @@ kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *backend, /* Reset the completion so dump_wait() has something to wait on. */ reinit_completion(&backend_csf->dump_completed); - if (backend_csf->dump_state == - KBASE_HWCNT_BACKEND_CSF_DUMP_WATCHDOG_REQUESTED) + if (backend_csf->dump_state == KBASE_HWCNT_BACKEND_CSF_DUMP_WATCHDOG_REQUESTED) watchdog_dumping = true; if ((backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) && @@ -1208,15 +1111,13 @@ kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *backend, /* Only do the request if we are fully enabled and not in * protected mode. */ - backend_csf->dump_state = - KBASE_HWCNT_BACKEND_CSF_DUMP_REQUESTED; + backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_REQUESTED; do_request = true; } else { /* Skip the request and waiting for ack and go straight to * checking the insert and kicking off the worker to do the dump */ - backend_csf->dump_state = - KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT; + backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_QUERYING_INSERT; } /* CSF firmware might enter protected mode now, but still call request. @@ -1238,31 +1139,26 @@ kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *backend, * ownership of the sample which watchdog requested. */ if (!watchdog_dumping) - backend_csf->info->csf_if->dump_request( - backend_csf->info->csf_if->ctx); + backend_csf->info->csf_if->dump_request(backend_csf->info->csf_if->ctx); } else kbase_hwcnt_backend_csf_submit_dump_worker(backend_csf->info); - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, - flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); /* Modify watchdog timer to delay the regular check time since * just requested. */ - backend_csf->info->watchdog_if->modify( - backend_csf->info->watchdog_if->timer, - HWCNT_BACKEND_WATCHDOG_TIMER_INTERVAL_MS); + backend_csf->info->watchdog_if->modify(backend_csf->info->watchdog_if->timer, + HWCNT_BACKEND_WATCHDOG_TIMER_INTERVAL_MS); return 0; } /* CSF backend implementation of kbase_hwcnt_backend_dump_wait_fn */ -static int -kbasep_hwcnt_backend_csf_dump_wait(struct kbase_hwcnt_backend *backend) +static int kbasep_hwcnt_backend_csf_dump_wait(struct kbase_hwcnt_backend *backend) { unsigned long flags; - struct kbase_hwcnt_backend_csf *backend_csf = - (struct kbase_hwcnt_backend_csf *)backend; + struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend; int errcode; if (!backend_csf) @@ -1275,26 +1171,21 @@ kbasep_hwcnt_backend_csf_dump_wait(struct kbase_hwcnt_backend *backend) * set. */ if (backend_csf->user_requested && - ((backend_csf->dump_state == - KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED) || - (backend_csf->dump_state == - KBASE_HWCNT_BACKEND_CSF_DUMP_WATCHDOG_REQUESTED))) + ((backend_csf->dump_state == KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED) || + (backend_csf->dump_state == KBASE_HWCNT_BACKEND_CSF_DUMP_WATCHDOG_REQUESTED))) errcode = 0; else errcode = -EIO; - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, - flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); return errcode; } /* CSF backend implementation of kbase_hwcnt_backend_dump_clear_fn */ -static int -kbasep_hwcnt_backend_csf_dump_clear(struct kbase_hwcnt_backend *backend) +static int kbasep_hwcnt_backend_csf_dump_clear(struct kbase_hwcnt_backend *backend) { - struct kbase_hwcnt_backend_csf *backend_csf = - (struct kbase_hwcnt_backend_csf *)backend; + struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend; int errcode; u64 ts; @@ -1313,13 +1204,12 @@ kbasep_hwcnt_backend_csf_dump_clear(struct kbase_hwcnt_backend *backend) } /* CSF backend implementation of kbase_hwcnt_backend_dump_get_fn */ -static int kbasep_hwcnt_backend_csf_dump_get( - struct kbase_hwcnt_backend *backend, - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_enable_map *dst_enable_map, bool accumulate) +static int kbasep_hwcnt_backend_csf_dump_get(struct kbase_hwcnt_backend *backend, + struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_enable_map *dst_enable_map, + bool accumulate) { - struct kbase_hwcnt_backend_csf *backend_csf = - (struct kbase_hwcnt_backend_csf *)backend; + struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend; int ret; size_t clk; @@ -1329,9 +1219,9 @@ static int kbasep_hwcnt_backend_csf_dump_get( return -EINVAL; /* Extract elapsed cycle count for each clock domain if enabled. */ - kbase_hwcnt_metadata_for_each_clock(dst_enable_map->metadata, clk) { - if (!kbase_hwcnt_clk_enable_map_enabled( - dst_enable_map->clk_enable_map, clk)) + kbase_hwcnt_metadata_for_each_clock(dst_enable_map->metadata, clk) + { + if (!kbase_hwcnt_clk_enable_map_enabled(dst_enable_map->clk_enable_map, clk)) continue; /* Reset the counter to zero if accumulation is off. */ @@ -1344,8 +1234,7 @@ static int kbasep_hwcnt_backend_csf_dump_get( * as it is undefined to call this function without a prior succeeding * one to dump_wait(). */ - ret = kbase_hwcnt_csf_dump_get(dst, backend_csf->to_user_buf, - dst_enable_map, accumulate); + ret = kbase_hwcnt_csf_dump_get(dst, backend_csf->to_user_buf, dst_enable_map, accumulate); return ret; } @@ -1357,8 +1246,7 @@ static int kbasep_hwcnt_backend_csf_dump_get( * Can be safely called on a backend in any state of partial construction. * */ -static void -kbasep_hwcnt_backend_csf_destroy(struct kbase_hwcnt_backend_csf *backend_csf) +static void kbasep_hwcnt_backend_csf_destroy(struct kbase_hwcnt_backend_csf *backend_csf) { if (!backend_csf) return; @@ -1388,9 +1276,8 @@ kbasep_hwcnt_backend_csf_destroy(struct kbase_hwcnt_backend_csf *backend_csf) * * Return: 0 on success, else error code. */ -static int -kbasep_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_info *csf_info, - struct kbase_hwcnt_backend_csf **out_backend) +static int kbasep_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_info *csf_info, + struct kbase_hwcnt_backend_csf **out_backend) { struct kbase_hwcnt_backend_csf *backend_csf = NULL; int errcode = -ENOMEM; @@ -1403,27 +1290,23 @@ kbasep_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_info *csf_info, goto alloc_error; backend_csf->info = csf_info; - kbasep_hwcnt_backend_csf_init_layout(&csf_info->prfcnt_info, - &backend_csf->phys_layout); + kbasep_hwcnt_backend_csf_init_layout(&csf_info->prfcnt_info, &backend_csf->phys_layout); - backend_csf->accum_buf = - kzalloc(csf_info->metadata->dump_buf_bytes, GFP_KERNEL); + backend_csf->accum_buf = kzalloc(csf_info->metadata->dump_buf_bytes, GFP_KERNEL); if (!backend_csf->accum_buf) goto err_alloc_acc_buf; - backend_csf->old_sample_buf = - kzalloc(csf_info->prfcnt_info.dump_bytes, GFP_KERNEL); + backend_csf->old_sample_buf = kzalloc(csf_info->prfcnt_info.dump_bytes, GFP_KERNEL); if (!backend_csf->old_sample_buf) goto err_alloc_pre_sample_buf; - backend_csf->to_user_buf = - kzalloc(csf_info->metadata->dump_buf_bytes, GFP_KERNEL); + backend_csf->to_user_buf = kzalloc(csf_info->metadata->dump_buf_bytes, GFP_KERNEL); if (!backend_csf->to_user_buf) goto err_alloc_user_sample_buf; - errcode = csf_info->csf_if->ring_buf_alloc( - csf_info->csf_if->ctx, csf_info->ring_buf_cnt, - &backend_csf->ring_buf_cpu_base, &backend_csf->ring_buf); + errcode = csf_info->csf_if->ring_buf_alloc(csf_info->csf_if->ctx, csf_info->ring_buf_cnt, + &backend_csf->ring_buf_cpu_base, + &backend_csf->ring_buf); if (errcode) goto err_ring_buf_alloc; errcode = -ENOMEM; @@ -1432,9 +1315,9 @@ kbasep_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_info *csf_info, kbasep_hwcnt_backend_csf_zero_all_prfcnt_en_header(backend_csf); /* Sync zeroed buffers to avoid coherency issues on use. */ - backend_csf->info->csf_if->ring_buf_sync( - backend_csf->info->csf_if->ctx, backend_csf->ring_buf, 0, - backend_csf->info->ring_buf_cnt, false); + backend_csf->info->csf_if->ring_buf_sync(backend_csf->info->csf_if->ctx, + backend_csf->ring_buf, 0, + backend_csf->info->ring_buf_cnt, false); init_completion(&backend_csf->dump_completed); @@ -1448,10 +1331,8 @@ kbasep_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_info *csf_info, if (!backend_csf->hwc_dump_workq) goto err_alloc_workqueue; - INIT_WORK(&backend_csf->hwc_dump_work, - kbasep_hwcnt_backend_csf_dump_worker); - INIT_WORK(&backend_csf->hwc_threshold_work, - kbasep_hwcnt_backend_csf_threshold_worker); + INIT_WORK(&backend_csf->hwc_dump_work, kbasep_hwcnt_backend_csf_dump_worker); + INIT_WORK(&backend_csf->hwc_threshold_work, kbasep_hwcnt_backend_csf_threshold_worker); backend_csf->enable_state = KBASE_HWCNT_BACKEND_CSF_DISABLED; backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE; @@ -1481,14 +1362,12 @@ alloc_error: } /* CSF backend implementation of kbase_hwcnt_backend_init_fn */ -static int -kbasep_hwcnt_backend_csf_init(const struct kbase_hwcnt_backend_info *info, - struct kbase_hwcnt_backend **out_backend) +static int kbasep_hwcnt_backend_csf_init(const struct kbase_hwcnt_backend_info *info, + struct kbase_hwcnt_backend **out_backend) { unsigned long flags; struct kbase_hwcnt_backend_csf *backend_csf = NULL; - struct kbase_hwcnt_backend_csf_info *csf_info = - (struct kbase_hwcnt_backend_csf_info *)info; + struct kbase_hwcnt_backend_csf_info *csf_info = (struct kbase_hwcnt_backend_csf_info *)info; int errcode; bool success = false; @@ -1509,11 +1388,9 @@ kbasep_hwcnt_backend_csf_init(const struct kbase_hwcnt_backend_info *info, *out_backend = (struct kbase_hwcnt_backend *)backend_csf; success = true; if (csf_info->unrecoverable_error_happened) - backend_csf->enable_state = - KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR; + backend_csf->enable_state = KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR; } - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, - flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); /* Destroy the new created backend if the backend has already created * before. In normal case, this won't happen if the client call init() @@ -1531,8 +1408,7 @@ kbasep_hwcnt_backend_csf_init(const struct kbase_hwcnt_backend_info *info, static void kbasep_hwcnt_backend_csf_term(struct kbase_hwcnt_backend *backend) { unsigned long flags; - struct kbase_hwcnt_backend_csf *backend_csf = - (struct kbase_hwcnt_backend_csf *)backend; + struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend; if (!backend) return; @@ -1544,8 +1420,7 @@ static void kbasep_hwcnt_backend_csf_term(struct kbase_hwcnt_backend *backend) */ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags); backend_csf->info->backend = NULL; - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, - flags); + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); kbasep_hwcnt_backend_csf_destroy(backend_csf); } @@ -1557,8 +1432,7 @@ static void kbasep_hwcnt_backend_csf_term(struct kbase_hwcnt_backend *backend) * Can be safely called on a backend info in any state of partial construction. * */ -static void kbasep_hwcnt_backend_csf_info_destroy( - const struct kbase_hwcnt_backend_csf_info *info) +static void kbasep_hwcnt_backend_csf_info_destroy(const struct kbase_hwcnt_backend_csf_info *info) { if (!info) return; @@ -1585,10 +1459,10 @@ static void kbasep_hwcnt_backend_csf_info_destroy( * * Return: 0 on success, else error code. */ -static int kbasep_hwcnt_backend_csf_info_create( - struct kbase_hwcnt_backend_csf_if *csf_if, u32 ring_buf_cnt, - struct kbase_hwcnt_watchdog_interface *watchdog_if, - const struct kbase_hwcnt_backend_csf_info **out_info) +static int +kbasep_hwcnt_backend_csf_info_create(struct kbase_hwcnt_backend_csf_if *csf_if, u32 ring_buf_cnt, + struct kbase_hwcnt_watchdog_interface *watchdog_if, + const struct kbase_hwcnt_backend_csf_info **out_info) { struct kbase_hwcnt_backend_csf_info *info = NULL; @@ -1611,8 +1485,7 @@ static int kbasep_hwcnt_backend_csf_info_create( .counter_set = KBASE_HWCNT_SET_PRIMARY, #endif .backend = NULL, .csf_if = csf_if, .ring_buf_cnt = ring_buf_cnt, - .fw_in_protected_mode = false, - .unrecoverable_error_happened = false, + .fw_in_protected_mode = false, .unrecoverable_error_happened = false, .watchdog_if = watchdog_if, }; *out_info = info; @@ -1632,19 +1505,17 @@ kbasep_hwcnt_backend_csf_metadata(const struct kbase_hwcnt_backend_info *info) return ((const struct kbase_hwcnt_backend_csf_info *)info)->metadata; } -static void kbasep_hwcnt_backend_csf_handle_unrecoverable_error( - struct kbase_hwcnt_backend_csf *backend_csf) +static void +kbasep_hwcnt_backend_csf_handle_unrecoverable_error(struct kbase_hwcnt_backend_csf *backend_csf) { bool do_disable = false; - backend_csf->info->csf_if->assert_lock_held( - backend_csf->info->csf_if->ctx); + backend_csf->info->csf_if->assert_lock_held(backend_csf->info->csf_if->ctx); /* We are already in or transitioning to the unrecoverable error state. * Early out. */ - if ((backend_csf->enable_state == - KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) || + if ((backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) || (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER)) return; @@ -1654,8 +1525,7 @@ static void kbasep_hwcnt_backend_csf_handle_unrecoverable_error( */ if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_DISABLED) { kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, - KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR); + backend_csf, KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR); return; } @@ -1663,12 +1533,11 @@ static void kbasep_hwcnt_backend_csf_handle_unrecoverable_error( * disabled, we don't want to disable twice if an unrecoverable error * happens while we are disabling. */ - do_disable = (backend_csf->enable_state != - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED); + do_disable = + (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED); kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, - KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER); + backend_csf, KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER); /* Transition the dump to the IDLE state and unblock any waiters. The * IDLE state signifies an error. @@ -1681,15 +1550,13 @@ static void kbasep_hwcnt_backend_csf_handle_unrecoverable_error( * happens while we are disabling. */ if (do_disable) - backend_csf->info->csf_if->dump_disable( - backend_csf->info->csf_if->ctx); + backend_csf->info->csf_if->dump_disable(backend_csf->info->csf_if->ctx); } -static void kbasep_hwcnt_backend_csf_handle_recoverable_error( - struct kbase_hwcnt_backend_csf *backend_csf) +static void +kbasep_hwcnt_backend_csf_handle_recoverable_error(struct kbase_hwcnt_backend_csf *backend_csf) { - backend_csf->info->csf_if->assert_lock_held( - backend_csf->info->csf_if->ctx); + backend_csf->info->csf_if->assert_lock_held(backend_csf->info->csf_if->ctx); switch (backend_csf->enable_state) { case KBASE_HWCNT_BACKEND_CSF_DISABLED: @@ -1705,8 +1572,7 @@ static void kbasep_hwcnt_backend_csf_handle_recoverable_error( /* A seemingly recoverable error that occurs while we are * transitioning to enabled is probably unrecoverable. */ - kbasep_hwcnt_backend_csf_handle_unrecoverable_error( - backend_csf); + kbasep_hwcnt_backend_csf_handle_unrecoverable_error(backend_csf); return; case KBASE_HWCNT_BACKEND_CSF_ENABLED: /* Start transitioning to the disabled state. We can't wait for @@ -1715,22 +1581,19 @@ static void kbasep_hwcnt_backend_csf_handle_recoverable_error( * disable(). */ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED); + backend_csf, KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED); /* Transition the dump to the IDLE state and unblock any * waiters. The IDLE state signifies an error. */ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE; complete_all(&backend_csf->dump_completed); - backend_csf->info->csf_if->dump_disable( - backend_csf->info->csf_if->ctx); + backend_csf->info->csf_if->dump_disable(backend_csf->info->csf_if->ctx); return; } } -void kbase_hwcnt_backend_csf_protm_entered( - struct kbase_hwcnt_backend_interface *iface) +void kbase_hwcnt_backend_csf_protm_entered(struct kbase_hwcnt_backend_interface *iface) { struct kbase_hwcnt_backend_csf_info *csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info; @@ -1744,8 +1607,7 @@ void kbase_hwcnt_backend_csf_protm_entered( kbase_hwcnt_backend_csf_on_prfcnt_sample(iface); } -void kbase_hwcnt_backend_csf_protm_exited( - struct kbase_hwcnt_backend_interface *iface) +void kbase_hwcnt_backend_csf_protm_exited(struct kbase_hwcnt_backend_interface *iface) { struct kbase_hwcnt_backend_csf_info *csf_info; @@ -1755,8 +1617,7 @@ void kbase_hwcnt_backend_csf_protm_exited( csf_info->fw_in_protected_mode = false; } -void kbase_hwcnt_backend_csf_on_unrecoverable_error( - struct kbase_hwcnt_backend_interface *iface) +void kbase_hwcnt_backend_csf_on_unrecoverable_error(struct kbase_hwcnt_backend_interface *iface) { unsigned long flags; struct kbase_hwcnt_backend_csf_info *csf_info; @@ -1776,8 +1637,7 @@ void kbase_hwcnt_backend_csf_on_unrecoverable_error( csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); } -void kbase_hwcnt_backend_csf_on_before_reset( - struct kbase_hwcnt_backend_interface *iface) +void kbase_hwcnt_backend_csf_on_before_reset(struct kbase_hwcnt_backend_interface *iface) { unsigned long flags; struct kbase_hwcnt_backend_csf_info *csf_info; @@ -1795,8 +1655,7 @@ void kbase_hwcnt_backend_csf_on_before_reset( backend_csf = csf_info->backend; if ((backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_DISABLED) && - (backend_csf->enable_state != - KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR)) { + (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR)) { /* Before a reset occurs, we must either have been disabled * (else we lose data) or we should have encountered an * unrecoverable error. Either way, we will have disabled the @@ -1807,13 +1666,11 @@ void kbase_hwcnt_backend_csf_on_before_reset( * We can't wait for this disable to complete, but it doesn't * really matter, the power is being pulled. */ - kbasep_hwcnt_backend_csf_handle_unrecoverable_error( - csf_info->backend); + kbasep_hwcnt_backend_csf_handle_unrecoverable_error(csf_info->backend); } /* A reset is the only way to exit the unrecoverable error state */ - if (backend_csf->enable_state == - KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) { + if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) { kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( backend_csf, KBASE_HWCNT_BACKEND_CSF_DISABLED); } @@ -1821,8 +1678,7 @@ void kbase_hwcnt_backend_csf_on_before_reset( csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); } -void kbase_hwcnt_backend_csf_on_prfcnt_sample( - struct kbase_hwcnt_backend_interface *iface) +void kbase_hwcnt_backend_csf_on_prfcnt_sample(struct kbase_hwcnt_backend_interface *iface) { struct kbase_hwcnt_backend_csf_info *csf_info; struct kbase_hwcnt_backend_csf *backend_csf; @@ -1836,10 +1692,8 @@ void kbase_hwcnt_backend_csf_on_prfcnt_sample( backend_csf = csf_info->backend; /* Skip the dump_work if it's a watchdog request. */ - if (backend_csf->dump_state == - KBASE_HWCNT_BACKEND_CSF_DUMP_WATCHDOG_REQUESTED) { - backend_csf->dump_state = - KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED; + if (backend_csf->dump_state == KBASE_HWCNT_BACKEND_CSF_DUMP_WATCHDOG_REQUESTED) { + backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED; return; } @@ -1853,8 +1707,7 @@ void kbase_hwcnt_backend_csf_on_prfcnt_sample( kbase_hwcnt_backend_csf_submit_dump_worker(csf_info); } -void kbase_hwcnt_backend_csf_on_prfcnt_threshold( - struct kbase_hwcnt_backend_interface *iface) +void kbase_hwcnt_backend_csf_on_prfcnt_threshold(struct kbase_hwcnt_backend_interface *iface) { struct kbase_hwcnt_backend_csf_info *csf_info; struct kbase_hwcnt_backend_csf *backend_csf; @@ -1871,12 +1724,10 @@ void kbase_hwcnt_backend_csf_on_prfcnt_threshold( /* Submit the threshold work into the work queue to consume the * available samples. */ - queue_work(backend_csf->hwc_dump_workq, - &backend_csf->hwc_threshold_work); + queue_work(backend_csf->hwc_dump_workq, &backend_csf->hwc_threshold_work); } -void kbase_hwcnt_backend_csf_on_prfcnt_overflow( - struct kbase_hwcnt_backend_interface *iface) +void kbase_hwcnt_backend_csf_on_prfcnt_overflow(struct kbase_hwcnt_backend_interface *iface) { struct kbase_hwcnt_backend_csf_info *csf_info; @@ -1897,8 +1748,7 @@ void kbase_hwcnt_backend_csf_on_prfcnt_overflow( kbasep_hwcnt_backend_csf_handle_recoverable_error(csf_info->backend); } -void kbase_hwcnt_backend_csf_on_prfcnt_enable( - struct kbase_hwcnt_backend_interface *iface) +void kbase_hwcnt_backend_csf_on_prfcnt_enable(struct kbase_hwcnt_backend_interface *iface) { struct kbase_hwcnt_backend_csf_info *csf_info; struct kbase_hwcnt_backend_csf *backend_csf; @@ -1911,12 +1761,10 @@ void kbase_hwcnt_backend_csf_on_prfcnt_enable( return; backend_csf = csf_info->backend; - if (backend_csf->enable_state == - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) { + if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) { kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( backend_csf, KBASE_HWCNT_BACKEND_CSF_ENABLED); - } else if (backend_csf->enable_state == - KBASE_HWCNT_BACKEND_CSF_ENABLED) { + } else if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) { /* Unexpected, but we are already in the right state so just * ignore it. */ @@ -1924,13 +1772,11 @@ void kbase_hwcnt_backend_csf_on_prfcnt_enable( /* Unexpected state change, assume everything is broken until * we reset. */ - kbasep_hwcnt_backend_csf_handle_unrecoverable_error( - csf_info->backend); + kbasep_hwcnt_backend_csf_handle_unrecoverable_error(csf_info->backend); } } -void kbase_hwcnt_backend_csf_on_prfcnt_disable( - struct kbase_hwcnt_backend_interface *iface) +void kbase_hwcnt_backend_csf_on_prfcnt_disable(struct kbase_hwcnt_backend_interface *iface) { struct kbase_hwcnt_backend_csf_info *csf_info; struct kbase_hwcnt_backend_csf *backend_csf; @@ -1943,13 +1789,10 @@ void kbase_hwcnt_backend_csf_on_prfcnt_disable( return; backend_csf = csf_info->backend; - if (backend_csf->enable_state == - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED) { + if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED) { kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, - KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER); - } else if (backend_csf->enable_state == - KBASE_HWCNT_BACKEND_CSF_DISABLED) { + backend_csf, KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER); + } else if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_DISABLED) { /* Unexpected, but we are already in the right state so just * ignore it. */ @@ -1957,13 +1800,11 @@ void kbase_hwcnt_backend_csf_on_prfcnt_disable( /* Unexpected state change, assume everything is broken until * we reset. */ - kbasep_hwcnt_backend_csf_handle_unrecoverable_error( - csf_info->backend); + kbasep_hwcnt_backend_csf_handle_unrecoverable_error(csf_info->backend); } } -int kbase_hwcnt_backend_csf_metadata_init( - struct kbase_hwcnt_backend_interface *iface) +int kbase_hwcnt_backend_csf_metadata_init(struct kbase_hwcnt_backend_interface *iface) { struct kbase_hwcnt_backend_csf_info *csf_info; struct kbase_hwcnt_gpu_info gpu_info; @@ -1975,8 +1816,7 @@ int kbase_hwcnt_backend_csf_metadata_init( WARN_ON(!csf_info->csf_if->get_prfcnt_info); - csf_info->csf_if->get_prfcnt_info(csf_info->csf_if->ctx, - &csf_info->prfcnt_info); + csf_info->csf_if->get_prfcnt_info(csf_info->csf_if->ctx, &csf_info->prfcnt_info); /* The clock domain counts should not exceed the number of maximum * number of clock regulators. @@ -1988,14 +1828,12 @@ int kbase_hwcnt_backend_csf_metadata_init( gpu_info.core_mask = csf_info->prfcnt_info.core_mask; gpu_info.clk_cnt = csf_info->prfcnt_info.clk_cnt; gpu_info.prfcnt_values_per_block = - csf_info->prfcnt_info.prfcnt_block_size / - KBASE_HWCNT_VALUE_HW_BYTES; + csf_info->prfcnt_info.prfcnt_block_size / KBASE_HWCNT_VALUE_HW_BYTES; return kbase_hwcnt_csf_metadata_create(&gpu_info, csf_info->counter_set, &csf_info->metadata); } -void kbase_hwcnt_backend_csf_metadata_term( - struct kbase_hwcnt_backend_interface *iface) +void kbase_hwcnt_backend_csf_metadata_term(struct kbase_hwcnt_backend_interface *iface) { struct kbase_hwcnt_backend_csf_info *csf_info; @@ -2009,10 +1847,9 @@ void kbase_hwcnt_backend_csf_metadata_term( } } -int kbase_hwcnt_backend_csf_create( - struct kbase_hwcnt_backend_csf_if *csf_if, u32 ring_buf_cnt, - struct kbase_hwcnt_watchdog_interface *watchdog_if, - struct kbase_hwcnt_backend_interface *iface) +int kbase_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_if *csf_if, u32 ring_buf_cnt, + struct kbase_hwcnt_watchdog_interface *watchdog_if, + struct kbase_hwcnt_backend_interface *iface) { int errcode; const struct kbase_hwcnt_backend_csf_info *info = NULL; @@ -2024,8 +1861,7 @@ int kbase_hwcnt_backend_csf_create( if (!is_power_of_2(ring_buf_cnt)) return -EINVAL; - errcode = kbasep_hwcnt_backend_csf_info_create(csf_if, ring_buf_cnt, - watchdog_if, &info); + errcode = kbasep_hwcnt_backend_csf_info_create(csf_if, ring_buf_cnt, watchdog_if, &info); if (errcode) return errcode; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf.h b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf.h similarity index 77% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf.h rename to drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf.h index e0cafbe70660..9c5a5c996ebd 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf.h +++ b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf.h @@ -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 @@ -27,9 +27,9 @@ #ifndef _KBASE_HWCNT_BACKEND_CSF_H_ #define _KBASE_HWCNT_BACKEND_CSF_H_ -#include "mali_kbase_hwcnt_backend.h" -#include "mali_kbase_hwcnt_backend_csf_if.h" -#include "mali_kbase_hwcnt_watchdog_if.h" +#include "hwcnt/backend/mali_kbase_hwcnt_backend.h" +#include "hwcnt/backend/mali_kbase_hwcnt_backend_csf_if.h" +#include "hwcnt/mali_kbase_hwcnt_watchdog_if.h" /** * kbase_hwcnt_backend_csf_create() - Create a CSF hardware counter backend @@ -47,10 +47,9 @@ * * Return: 0 on success, else error code. */ -int kbase_hwcnt_backend_csf_create( - struct kbase_hwcnt_backend_csf_if *csf_if, u32 ring_buf_cnt, - struct kbase_hwcnt_watchdog_interface *watchdog_if, - struct kbase_hwcnt_backend_interface *iface); +int kbase_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_if *csf_if, u32 ring_buf_cnt, + struct kbase_hwcnt_watchdog_interface *watchdog_if, + struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_metadata_init() - Initialize the metadata for a CSF @@ -58,16 +57,14 @@ int kbase_hwcnt_backend_csf_create( * @iface: Non-NULL pointer to backend interface structure * Return: 0 on success, else error code. */ -int kbase_hwcnt_backend_csf_metadata_init( - struct kbase_hwcnt_backend_interface *iface); +int kbase_hwcnt_backend_csf_metadata_init(struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_metadata_term() - Terminate the metadata for a CSF * hardware counter backend. * @iface: Non-NULL pointer to backend interface structure. */ -void kbase_hwcnt_backend_csf_metadata_term( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_csf_metadata_term(struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_destroy() - Destroy a CSF hardware counter backend @@ -77,8 +74,7 @@ void kbase_hwcnt_backend_csf_metadata_term( * Can be safely called on an all-zeroed interface, or on an already destroyed * interface. */ -void kbase_hwcnt_backend_csf_destroy( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_csf_destroy(struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_protm_entered() - CSF HWC backend function to receive @@ -86,8 +82,7 @@ void kbase_hwcnt_backend_csf_destroy( * has been entered. * @iface: Non-NULL pointer to HWC backend interface. */ -void kbase_hwcnt_backend_csf_protm_entered( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_csf_protm_entered(struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_protm_exited() - CSF HWC backend function to receive @@ -95,8 +90,7 @@ void kbase_hwcnt_backend_csf_protm_entered( * been exited. * @iface: Non-NULL pointer to HWC backend interface. */ -void kbase_hwcnt_backend_csf_protm_exited( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_csf_protm_exited(struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_on_unrecoverable_error() - CSF HWC backend function @@ -108,8 +102,7 @@ void kbase_hwcnt_backend_csf_protm_exited( * with reset, or that may put HWC logic in state that could result in hang. For * example, on bus error, or when FW becomes unresponsive. */ -void kbase_hwcnt_backend_csf_on_unrecoverable_error( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_csf_on_unrecoverable_error(struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_on_before_reset() - CSF HWC backend function to be @@ -119,16 +112,14 @@ void kbase_hwcnt_backend_csf_on_unrecoverable_error( * were in it. * @iface: Non-NULL pointer to HWC backend interface. */ -void kbase_hwcnt_backend_csf_on_before_reset( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_csf_on_before_reset(struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_on_prfcnt_sample() - CSF performance counter sample * complete interrupt handler. * @iface: Non-NULL pointer to HWC backend interface. */ -void kbase_hwcnt_backend_csf_on_prfcnt_sample( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_csf_on_prfcnt_sample(struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_on_prfcnt_threshold() - CSF performance counter @@ -136,31 +127,27 @@ void kbase_hwcnt_backend_csf_on_prfcnt_sample( * interrupt handler. * @iface: Non-NULL pointer to HWC backend interface. */ -void kbase_hwcnt_backend_csf_on_prfcnt_threshold( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_csf_on_prfcnt_threshold(struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_on_prfcnt_overflow() - CSF performance counter buffer * overflow interrupt handler. * @iface: Non-NULL pointer to HWC backend interface. */ -void kbase_hwcnt_backend_csf_on_prfcnt_overflow( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_csf_on_prfcnt_overflow(struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_on_prfcnt_enable() - CSF performance counter enabled * interrupt handler. * @iface: Non-NULL pointer to HWC backend interface. */ -void kbase_hwcnt_backend_csf_on_prfcnt_enable( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_csf_on_prfcnt_enable(struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_csf_on_prfcnt_disable() - CSF performance counter * disabled interrupt handler. * @iface: Non-NULL pointer to HWC backend interface. */ -void kbase_hwcnt_backend_csf_on_prfcnt_disable( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_csf_on_prfcnt_disable(struct kbase_hwcnt_backend_interface *iface); #endif /* _KBASE_HWCNT_BACKEND_CSF_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if.h b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if.h similarity index 85% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if.h rename to drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if.h index 24b26c2bd6f4..382a3adaa127 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if.h +++ b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if.h @@ -85,8 +85,8 @@ struct kbase_hwcnt_backend_csf_if_prfcnt_info { * held. * @ctx: Non-NULL pointer to a CSF context. */ -typedef void kbase_hwcnt_backend_csf_if_assert_lock_held_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx); +typedef void +kbase_hwcnt_backend_csf_if_assert_lock_held_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx); /** * typedef kbase_hwcnt_backend_csf_if_lock_fn - Acquire backend spinlock. @@ -95,9 +95,8 @@ typedef void kbase_hwcnt_backend_csf_if_assert_lock_held_fn( * @flags: Pointer to the memory location that would store the previous * interrupt state. */ -typedef void kbase_hwcnt_backend_csf_if_lock_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, - unsigned long *flags); +typedef void kbase_hwcnt_backend_csf_if_lock_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + unsigned long *flags); /** * typedef kbase_hwcnt_backend_csf_if_unlock_fn - Release backend spinlock. @@ -106,9 +105,8 @@ typedef void kbase_hwcnt_backend_csf_if_lock_fn( * @flags: Previously stored interrupt state when Scheduler interrupt * spinlock was acquired. */ -typedef void kbase_hwcnt_backend_csf_if_unlock_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, - unsigned long flags); +typedef void kbase_hwcnt_backend_csf_if_unlock_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + unsigned long flags); /** * typedef kbase_hwcnt_backend_csf_if_get_prfcnt_info_fn - Get performance @@ -137,10 +135,10 @@ typedef void kbase_hwcnt_backend_csf_if_get_prfcnt_info_fn( * * Return: 0 on success, else error code. */ -typedef int kbase_hwcnt_backend_csf_if_ring_buf_alloc_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 buf_count, - void **cpu_dump_base, - struct kbase_hwcnt_backend_csf_if_ring_buf **ring_buf); +typedef int +kbase_hwcnt_backend_csf_if_ring_buf_alloc_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + u32 buf_count, void **cpu_dump_base, + struct kbase_hwcnt_backend_csf_if_ring_buf **ring_buf); /** * typedef kbase_hwcnt_backend_csf_if_ring_buf_sync_fn - Sync HWC dump buffers @@ -159,10 +157,10 @@ typedef int kbase_hwcnt_backend_csf_if_ring_buf_alloc_fn( * Flush cached HWC dump buffer data to ensure that all writes from GPU and CPU * are correctly observed. */ -typedef void kbase_hwcnt_backend_csf_if_ring_buf_sync_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, - struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf, - u32 buf_index_first, u32 buf_index_last, bool for_cpu); +typedef void +kbase_hwcnt_backend_csf_if_ring_buf_sync_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf, + u32 buf_index_first, u32 buf_index_last, bool for_cpu); /** * typedef kbase_hwcnt_backend_csf_if_ring_buf_free_fn - Free a ring buffer for @@ -171,9 +169,9 @@ typedef void kbase_hwcnt_backend_csf_if_ring_buf_sync_fn( * @ctx: Non-NULL pointer to a CSF interface context. * @ring_buf: Non-NULL pointer to the ring buffer which to be freed. */ -typedef void kbase_hwcnt_backend_csf_if_ring_buf_free_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, - struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf); +typedef void +kbase_hwcnt_backend_csf_if_ring_buf_free_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf); /** * typedef kbase_hwcnt_backend_csf_if_timestamp_ns_fn - Get the current @@ -183,8 +181,7 @@ typedef void kbase_hwcnt_backend_csf_if_ring_buf_free_fn( * * Return: CSF interface timestamp in nanoseconds. */ -typedef u64 kbase_hwcnt_backend_csf_if_timestamp_ns_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx); +typedef u64 kbase_hwcnt_backend_csf_if_timestamp_ns_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx); /** * typedef kbase_hwcnt_backend_csf_if_dump_enable_fn - Setup and enable hardware @@ -195,10 +192,10 @@ typedef u64 kbase_hwcnt_backend_csf_if_timestamp_ns_fn( * * Requires lock to be taken before calling. */ -typedef void kbase_hwcnt_backend_csf_if_dump_enable_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, - struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf, - struct kbase_hwcnt_backend_csf_if_enable *enable); +typedef void +kbase_hwcnt_backend_csf_if_dump_enable_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf, + struct kbase_hwcnt_backend_csf_if_enable *enable); /** * typedef kbase_hwcnt_backend_csf_if_dump_disable_fn - Disable hardware counter @@ -207,8 +204,7 @@ typedef void kbase_hwcnt_backend_csf_if_dump_enable_fn( * * Requires lock to be taken before calling. */ -typedef void kbase_hwcnt_backend_csf_if_dump_disable_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx); +typedef void kbase_hwcnt_backend_csf_if_dump_disable_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx); /** * typedef kbase_hwcnt_backend_csf_if_dump_request_fn - Request a HWC dump. @@ -217,8 +213,7 @@ typedef void kbase_hwcnt_backend_csf_if_dump_disable_fn( * * Requires lock to be taken before calling. */ -typedef void kbase_hwcnt_backend_csf_if_dump_request_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx); +typedef void kbase_hwcnt_backend_csf_if_dump_request_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx); /** * typedef kbase_hwcnt_backend_csf_if_get_indexes_fn - Get current extract and @@ -231,9 +226,8 @@ typedef void kbase_hwcnt_backend_csf_if_dump_request_fn( * * Requires lock to be taken before calling. */ -typedef void kbase_hwcnt_backend_csf_if_get_indexes_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 *extract_index, - u32 *insert_index); +typedef void kbase_hwcnt_backend_csf_if_get_indexes_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + u32 *extract_index, u32 *insert_index); /** * typedef kbase_hwcnt_backend_csf_if_set_extract_index_fn - Update the extract @@ -245,8 +239,9 @@ typedef void kbase_hwcnt_backend_csf_if_get_indexes_fn( * * Requires lock to be taken before calling. */ -typedef void kbase_hwcnt_backend_csf_if_set_extract_index_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 extract_index); +typedef void +kbase_hwcnt_backend_csf_if_set_extract_index_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + u32 extract_index); /** * typedef kbase_hwcnt_backend_csf_if_get_gpu_cycle_count_fn - Get the current @@ -260,9 +255,9 @@ typedef void kbase_hwcnt_backend_csf_if_set_extract_index_fn( * * Requires lock to be taken before calling. */ -typedef void kbase_hwcnt_backend_csf_if_get_gpu_cycle_count_fn( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, u64 *cycle_counts, - u64 clk_enable_map); +typedef void +kbase_hwcnt_backend_csf_if_get_gpu_cycle_count_fn(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + u64 *cycle_counts, u64 clk_enable_map); /** * struct kbase_hwcnt_backend_csf_if - Hardware counter backend CSF virtual diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if_fw.c b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.c similarity index 73% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if_fw.c rename to drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.c index ab33a0b26486..9985752a3748 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if_fw.c +++ b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.c @@ -26,12 +26,12 @@ #include #include #include -#include "mali_kbase_hwcnt_gpu.h" -#include "mali_kbase_hwcnt_types.h" +#include "hwcnt/mali_kbase_hwcnt_gpu.h" +#include "hwcnt/mali_kbase_hwcnt_types.h" #include #include "csf/mali_kbase_csf_firmware.h" -#include "mali_kbase_hwcnt_backend_csf_if_fw.h" +#include "hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.h" #include "mali_kbase_hwaccess_time.h" #include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h" @@ -42,9 +42,6 @@ #include #endif /* CONFIG_MALI_BIFROST_NO_MALI */ -/** The number of nanoseconds in a second. */ -#define NSECS_IN_SEC 1000000000ull /* ns */ - /* Ring buffer virtual address start at 4GB */ #define KBASE_HWC_CSF_RING_BUFFER_VA_START (1ull << 32) @@ -90,8 +87,8 @@ struct kbase_hwcnt_backend_csf_if_fw_ctx { struct kbase_ccswe ccswe_shader_cores; }; -static void kbasep_hwcnt_backend_csf_if_fw_assert_lock_held( - struct kbase_hwcnt_backend_csf_if_ctx *ctx) +static void +kbasep_hwcnt_backend_csf_if_fw_assert_lock_held(struct kbase_hwcnt_backend_csf_if_ctx *ctx) { struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx; struct kbase_device *kbdev; @@ -104,9 +101,8 @@ static void kbasep_hwcnt_backend_csf_if_fw_assert_lock_held( kbase_csf_scheduler_spin_lock_assert_held(kbdev); } -static void -kbasep_hwcnt_backend_csf_if_fw_lock(struct kbase_hwcnt_backend_csf_if_ctx *ctx, - unsigned long *flags) +static void kbasep_hwcnt_backend_csf_if_fw_lock(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + unsigned long *flags) { struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx; struct kbase_device *kbdev; @@ -119,8 +115,8 @@ kbasep_hwcnt_backend_csf_if_fw_lock(struct kbase_hwcnt_backend_csf_if_ctx *ctx, kbase_csf_scheduler_spin_lock(kbdev, flags); } -static void kbasep_hwcnt_backend_csf_if_fw_unlock( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, unsigned long flags) +static void kbasep_hwcnt_backend_csf_if_fw_unlock(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + unsigned long flags) { struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx; struct kbase_device *kbdev; @@ -141,22 +137,19 @@ static void kbasep_hwcnt_backend_csf_if_fw_unlock( * @clk_index: Clock index * @clk_rate_hz: Clock frequency(hz) */ -static void kbasep_hwcnt_backend_csf_if_fw_on_freq_change( - struct kbase_clk_rate_listener *rate_listener, u32 clk_index, - u32 clk_rate_hz) +static void +kbasep_hwcnt_backend_csf_if_fw_on_freq_change(struct kbase_clk_rate_listener *rate_listener, + u32 clk_index, u32 clk_rate_hz) { - struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx = - container_of(rate_listener, - struct kbase_hwcnt_backend_csf_if_fw_ctx, - rate_listener); + struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx = container_of( + rate_listener, struct kbase_hwcnt_backend_csf_if_fw_ctx, rate_listener); u64 timestamp_ns; if (clk_index != KBASE_CLOCK_DOMAIN_SHADER_CORES) return; timestamp_ns = ktime_get_raw_ns(); - kbase_ccswe_freq_change(&fw_ctx->ccswe_shader_cores, timestamp_ns, - clk_rate_hz); + kbase_ccswe_freq_change(&fw_ctx->ccswe_shader_cores, timestamp_ns, clk_rate_hz); } /** @@ -165,17 +158,16 @@ static void kbasep_hwcnt_backend_csf_if_fw_on_freq_change( * @fw_ctx: Non-NULL pointer to CSF firmware interface context. * @clk_enable_map: Non-NULL pointer to enable map specifying enabled counters. */ -static void kbasep_hwcnt_backend_csf_if_fw_cc_enable( - struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx, u64 clk_enable_map) +static void +kbasep_hwcnt_backend_csf_if_fw_cc_enable(struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx, + u64 clk_enable_map) { struct kbase_device *kbdev = fw_ctx->kbdev; - if (kbase_hwcnt_clk_enable_map_enabled( - clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) { + if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) { /* software estimation for non-top clock domains */ struct kbase_clk_rate_trace_manager *rtm = &kbdev->pm.clk_rtm; - const struct kbase_clk_data *clk_data = - rtm->clks[KBASE_CLOCK_DOMAIN_SHADER_CORES]; + const struct kbase_clk_data *clk_data = rtm->clks[KBASE_CLOCK_DOMAIN_SHADER_CORES]; u32 cur_freq; unsigned long flags; u64 timestamp_ns; @@ -186,11 +178,9 @@ static void kbasep_hwcnt_backend_csf_if_fw_cc_enable( cur_freq = (u32)clk_data->clock_val; kbase_ccswe_reset(&fw_ctx->ccswe_shader_cores); - kbase_ccswe_freq_change(&fw_ctx->ccswe_shader_cores, - timestamp_ns, cur_freq); + kbase_ccswe_freq_change(&fw_ctx->ccswe_shader_cores, timestamp_ns, cur_freq); - kbase_clk_rate_trace_manager_subscribe_no_lock( - rtm, &fw_ctx->rate_listener); + kbase_clk_rate_trace_manager_subscribe_no_lock(rtm, &fw_ctx->rate_listener); spin_unlock_irqrestore(&rtm->lock, flags); } @@ -203,17 +193,15 @@ static void kbasep_hwcnt_backend_csf_if_fw_cc_enable( * * @fw_ctx: Non-NULL pointer to CSF firmware interface context. */ -static void kbasep_hwcnt_backend_csf_if_fw_cc_disable( - struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx) +static void +kbasep_hwcnt_backend_csf_if_fw_cc_disable(struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx) { struct kbase_device *kbdev = fw_ctx->kbdev; struct kbase_clk_rate_trace_manager *rtm = &kbdev->pm.clk_rtm; u64 clk_enable_map = fw_ctx->clk_enable_map; - if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, - KBASE_CLOCK_DOMAIN_SHADER_CORES)) - kbase_clk_rate_trace_manager_unsubscribe( - rtm, &fw_ctx->rate_listener); + if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) + kbase_clk_rate_trace_manager_unsubscribe(rtm, &fw_ctx->rate_listener); } static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( @@ -244,8 +232,8 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( u32 prfcnt_size; u32 prfcnt_hw_size; u32 prfcnt_fw_size; - u32 prfcnt_block_size = KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK * - KBASE_HWCNT_VALUE_HW_BYTES; + u32 prfcnt_block_size = + KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK * KBASE_HWCNT_VALUE_HW_BYTES; WARN_ON(!ctx); WARN_ON(!prfcnt_info); @@ -262,10 +250,9 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( */ if ((kbdev->gpu_props.props.raw_props.gpu_id & GPU_ID2_PRODUCT_MODEL) >= GPU_ID2_PRODUCT_TTUX) { - prfcnt_block_size = - PRFCNT_FEATURES_COUNTER_BLOCK_SIZE_GET(kbase_reg_read( - kbdev, GPU_CONTROL_REG(PRFCNT_FEATURES))) - << 8; + prfcnt_block_size = PRFCNT_FEATURES_COUNTER_BLOCK_SIZE_GET( + kbase_reg_read(kbdev, GPU_CONTROL_REG(PRFCNT_FEATURES))) + << 8; } *prfcnt_info = (struct kbase_hwcnt_backend_csf_if_prfcnt_info){ @@ -280,17 +267,14 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( }; /* Block size must be multiple of counter size. */ - WARN_ON((prfcnt_info->prfcnt_block_size % KBASE_HWCNT_VALUE_HW_BYTES) != - 0); + WARN_ON((prfcnt_info->prfcnt_block_size % KBASE_HWCNT_VALUE_HW_BYTES) != 0); /* Total size must be multiple of block size. */ - WARN_ON((prfcnt_info->dump_bytes % prfcnt_info->prfcnt_block_size) != - 0); + WARN_ON((prfcnt_info->dump_bytes % prfcnt_info->prfcnt_block_size) != 0); #endif } static int kbasep_hwcnt_backend_csf_if_fw_ring_buf_alloc( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 buf_count, - void **cpu_dump_base, + struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 buf_count, void **cpu_dump_base, struct kbase_hwcnt_backend_csf_if_ring_buf **out_ring_buf) { struct kbase_device *kbdev; @@ -342,9 +326,8 @@ static int kbasep_hwcnt_backend_csf_if_fw_ring_buf_alloc( goto page_list_alloc_error; /* Get physical page for the buffer */ - ret = kbase_mem_pool_alloc_pages( - &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, - phys, false); + ret = kbase_mem_pool_alloc_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, + phys, false); if (ret != num_pages) goto phys_mem_pool_alloc_error; @@ -360,9 +343,8 @@ static int kbasep_hwcnt_backend_csf_if_fw_ring_buf_alloc( KBASE_REG_MEMATTR_INDEX(AS_MEMATTR_INDEX_NON_CACHEABLE); /* Update MMU table */ - ret = kbase_mmu_insert_pages(kbdev, &kbdev->csf.mcu_mmu, - gpu_va_base >> PAGE_SHIFT, phys, num_pages, - flags, MCU_AS_NR, KBASE_MEM_GROUP_CSF_FW, + ret = kbase_mmu_insert_pages(kbdev, &kbdev->csf.mcu_mmu, gpu_va_base >> PAGE_SHIFT, phys, + num_pages, flags, MCU_AS_NR, KBASE_MEM_GROUP_CSF_FW, mmu_sync_info); if (ret) goto mmu_insert_failed; @@ -381,17 +363,15 @@ static int kbasep_hwcnt_backend_csf_if_fw_ring_buf_alloc( fw_ring_buf->as_nr = MCU_AS_NR; *cpu_dump_base = fw_ring_buf->cpu_dump_base; - *out_ring_buf = - (struct kbase_hwcnt_backend_csf_if_ring_buf *)fw_ring_buf; + *out_ring_buf = (struct kbase_hwcnt_backend_csf_if_ring_buf *)fw_ring_buf; return 0; mmu_insert_failed: vunmap(cpu_addr); vmap_error: - kbase_mem_pool_free_pages( - &kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, - phys, false, false); + kbase_mem_pool_free_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, phys, + false, false); phys_mem_pool_alloc_error: kfree(page_list); page_list_alloc_error: @@ -401,10 +381,10 @@ phys_alloc_error: return -ENOMEM; } -static void kbasep_hwcnt_backend_csf_if_fw_ring_buf_sync( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, - struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf, - u32 buf_index_first, u32 buf_index_last, bool for_cpu) +static void +kbasep_hwcnt_backend_csf_if_fw_ring_buf_sync(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf, + u32 buf_index_first, u32 buf_index_last, bool for_cpu) { struct kbase_hwcnt_backend_csf_if_fw_ring_buf *fw_ring_buf = (struct kbase_hwcnt_backend_csf_if_fw_ring_buf *)ring_buf; @@ -435,8 +415,7 @@ static void kbasep_hwcnt_backend_csf_if_fw_ring_buf_sync( * inclusive at both ends so full flushes are not 0 -> 0. */ ring_buf_index_first = buf_index_first & (fw_ring_buf->buf_count - 1); - ring_buf_index_last = - (buf_index_last - 1) & (fw_ring_buf->buf_count - 1); + ring_buf_index_last = (buf_index_last - 1) & (fw_ring_buf->buf_count - 1); /* The start address is the offset of the first buffer. */ start_address = fw_ctx->buf_bytes * ring_buf_index_first; @@ -453,15 +432,11 @@ static void kbasep_hwcnt_backend_csf_if_fw_ring_buf_sync( struct page *pg = as_page(fw_ring_buf->phys[i]); if (for_cpu) { - kbase_sync_single_for_cpu(fw_ctx->kbdev, - kbase_dma_addr(pg), - PAGE_SIZE, - DMA_BIDIRECTIONAL); + kbase_sync_single_for_cpu(fw_ctx->kbdev, kbase_dma_addr(pg), + PAGE_SIZE, DMA_BIDIRECTIONAL); } else { - kbase_sync_single_for_device(fw_ctx->kbdev, - kbase_dma_addr(pg), - PAGE_SIZE, - DMA_BIDIRECTIONAL); + kbase_sync_single_for_device(fw_ctx->kbdev, kbase_dma_addr(pg), + PAGE_SIZE, DMA_BIDIRECTIONAL); } } @@ -473,28 +448,24 @@ static void kbasep_hwcnt_backend_csf_if_fw_ring_buf_sync( struct page *pg = as_page(fw_ring_buf->phys[i]); if (for_cpu) { - kbase_sync_single_for_cpu(fw_ctx->kbdev, - kbase_dma_addr(pg), PAGE_SIZE, + kbase_sync_single_for_cpu(fw_ctx->kbdev, kbase_dma_addr(pg), PAGE_SIZE, DMA_BIDIRECTIONAL); } else { - kbase_sync_single_for_device(fw_ctx->kbdev, - kbase_dma_addr(pg), - PAGE_SIZE, + kbase_sync_single_for_device(fw_ctx->kbdev, kbase_dma_addr(pg), PAGE_SIZE, DMA_BIDIRECTIONAL); } } } -static u64 kbasep_hwcnt_backend_csf_if_fw_timestamp_ns( - struct kbase_hwcnt_backend_csf_if_ctx *ctx) +static u64 kbasep_hwcnt_backend_csf_if_fw_timestamp_ns(struct kbase_hwcnt_backend_csf_if_ctx *ctx) { CSTD_UNUSED(ctx); return ktime_get_raw_ns(); } -static void kbasep_hwcnt_backend_csf_if_fw_ring_buf_free( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, - struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf) +static void +kbasep_hwcnt_backend_csf_if_fw_ring_buf_free(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf) { struct kbase_hwcnt_backend_csf_if_fw_ring_buf *fw_ring_buf = (struct kbase_hwcnt_backend_csf_if_fw_ring_buf *)ring_buf; @@ -513,10 +484,8 @@ static void kbasep_hwcnt_backend_csf_if_fw_ring_buf_free( vunmap(fw_ring_buf->cpu_dump_base); - kbase_mem_pool_free_pages( - &fw_ctx->kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], - fw_ring_buf->num_pages, fw_ring_buf->phys, false, - false); + kbase_mem_pool_free_pages(&fw_ctx->kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], + fw_ring_buf->num_pages, fw_ring_buf->phys, false, false); kfree(fw_ring_buf->phys); @@ -524,10 +493,10 @@ static void kbasep_hwcnt_backend_csf_if_fw_ring_buf_free( } } -static void kbasep_hwcnt_backend_csf_if_fw_dump_enable( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, - struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf, - struct kbase_hwcnt_backend_csf_if_enable *enable) +static void +kbasep_hwcnt_backend_csf_if_fw_dump_enable(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf, + struct kbase_hwcnt_backend_csf_if_enable *enable) { u32 prfcnt_config; struct kbase_device *kbdev; @@ -550,8 +519,7 @@ static void kbasep_hwcnt_backend_csf_if_fw_dump_enable( prfcnt_config = GLB_PRFCNT_CONFIG_SET_SELECT_SET(prfcnt_config, enable->counter_set); /* Configure the ring buffer base address */ - kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_JASID, - fw_ring_buf->as_nr); + kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_JASID, fw_ring_buf->as_nr); kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_BASE_LO, fw_ring_buf->gpu_dump_base & U32_MAX); kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_BASE_HI, @@ -561,38 +529,29 @@ static void kbasep_hwcnt_backend_csf_if_fw_dump_enable( kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_EXTRACT, 0); /* Configure the enable bitmap */ - kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_CSF_EN, - enable->fe_bm); - kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_SHADER_EN, - enable->shader_bm); - kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_MMU_L2_EN, - enable->mmu_l2_bm); - kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_TILER_EN, - enable->tiler_bm); + kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_CSF_EN, enable->fe_bm); + kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_SHADER_EN, enable->shader_bm); + kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_MMU_L2_EN, enable->mmu_l2_bm); + kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_TILER_EN, enable->tiler_bm); /* Configure the HWC set and buffer size */ - kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_CONFIG, - prfcnt_config); + kbase_csf_firmware_global_input(global_iface, GLB_PRFCNT_CONFIG, prfcnt_config); kbdev->csf.hwcnt.enable_pending = true; /* Unmask the interrupts */ - kbase_csf_firmware_global_input_mask( - global_iface, GLB_ACK_IRQ_MASK, - GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK, - GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK); - kbase_csf_firmware_global_input_mask( - global_iface, GLB_ACK_IRQ_MASK, - GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK, - GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK); - kbase_csf_firmware_global_input_mask( - global_iface, GLB_ACK_IRQ_MASK, - GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK, - GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK); - kbase_csf_firmware_global_input_mask( - global_iface, GLB_ACK_IRQ_MASK, - GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK, - GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK); + kbase_csf_firmware_global_input_mask(global_iface, GLB_ACK_IRQ_MASK, + GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK, + GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK); + kbase_csf_firmware_global_input_mask(global_iface, GLB_ACK_IRQ_MASK, + GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK, + GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK); + kbase_csf_firmware_global_input_mask(global_iface, GLB_ACK_IRQ_MASK, + GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK, + GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK); + kbase_csf_firmware_global_input_mask(global_iface, GLB_ACK_IRQ_MASK, + GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK, + GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK); /* Enable the HWC */ kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ, @@ -600,15 +559,12 @@ static void kbasep_hwcnt_backend_csf_if_fw_dump_enable( GLB_REQ_PRFCNT_ENABLE_MASK); kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR); - prfcnt_config = kbase_csf_firmware_global_input_read(global_iface, - GLB_PRFCNT_CONFIG); + prfcnt_config = kbase_csf_firmware_global_input_read(global_iface, GLB_PRFCNT_CONFIG); - kbasep_hwcnt_backend_csf_if_fw_cc_enable(fw_ctx, - enable->clk_enable_map); + kbasep_hwcnt_backend_csf_if_fw_cc_enable(fw_ctx, enable->clk_enable_map); } -static void kbasep_hwcnt_backend_csf_if_fw_dump_disable( - struct kbase_hwcnt_backend_csf_if_ctx *ctx) +static void kbasep_hwcnt_backend_csf_if_fw_dump_disable(struct kbase_hwcnt_backend_csf_if_ctx *ctx) { struct kbase_device *kbdev; struct kbase_csf_global_iface *global_iface; @@ -623,20 +579,16 @@ static void kbasep_hwcnt_backend_csf_if_fw_dump_disable( /* Disable the HWC */ kbdev->csf.hwcnt.enable_pending = true; - kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ, 0, - GLB_REQ_PRFCNT_ENABLE_MASK); + kbase_csf_firmware_global_input_mask(global_iface, GLB_REQ, 0, GLB_REQ_PRFCNT_ENABLE_MASK); kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR); /* mask the interrupts */ - kbase_csf_firmware_global_input_mask( - global_iface, GLB_ACK_IRQ_MASK, 0, - GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK); - kbase_csf_firmware_global_input_mask( - global_iface, GLB_ACK_IRQ_MASK, 0, - GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK); - kbase_csf_firmware_global_input_mask( - global_iface, GLB_ACK_IRQ_MASK, 0, - GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK); + kbase_csf_firmware_global_input_mask(global_iface, GLB_ACK_IRQ_MASK, 0, + GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK); + kbase_csf_firmware_global_input_mask(global_iface, GLB_ACK_IRQ_MASK, 0, + GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK); + kbase_csf_firmware_global_input_mask(global_iface, GLB_ACK_IRQ_MASK, 0, + GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK); /* In case we have a previous request in flight when the disable * happens. @@ -646,8 +598,7 @@ static void kbasep_hwcnt_backend_csf_if_fw_dump_disable( kbasep_hwcnt_backend_csf_if_fw_cc_disable(fw_ctx); } -static void kbasep_hwcnt_backend_csf_if_fw_dump_request( - struct kbase_hwcnt_backend_csf_if_ctx *ctx) +static void kbasep_hwcnt_backend_csf_if_fw_dump_request(struct kbase_hwcnt_backend_csf_if_ctx *ctx) { u32 glb_req; struct kbase_device *kbdev; @@ -670,9 +621,8 @@ static void kbasep_hwcnt_backend_csf_if_fw_dump_request( kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR); } -static void kbasep_hwcnt_backend_csf_if_fw_get_indexes( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 *extract_index, - u32 *insert_index) +static void kbasep_hwcnt_backend_csf_if_fw_get_indexes(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + u32 *extract_index, u32 *insert_index) { struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx = (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx; @@ -682,14 +632,15 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_indexes( WARN_ON(!insert_index); kbasep_hwcnt_backend_csf_if_fw_assert_lock_held(ctx); - *extract_index = kbase_csf_firmware_global_input_read( - &fw_ctx->kbdev->csf.global_iface, GLB_PRFCNT_EXTRACT); - *insert_index = kbase_csf_firmware_global_output( - &fw_ctx->kbdev->csf.global_iface, GLB_PRFCNT_INSERT); + *extract_index = kbase_csf_firmware_global_input_read(&fw_ctx->kbdev->csf.global_iface, + GLB_PRFCNT_EXTRACT); + *insert_index = kbase_csf_firmware_global_output(&fw_ctx->kbdev->csf.global_iface, + GLB_PRFCNT_INSERT); } -static void kbasep_hwcnt_backend_csf_if_fw_set_extract_index( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, u32 extract_idx) +static void +kbasep_hwcnt_backend_csf_if_fw_set_extract_index(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + u32 extract_idx) { struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx = (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx; @@ -700,13 +651,13 @@ static void kbasep_hwcnt_backend_csf_if_fw_set_extract_index( /* Set the raw extract index to release the buffer back to the ring * buffer. */ - kbase_csf_firmware_global_input(&fw_ctx->kbdev->csf.global_iface, - GLB_PRFCNT_EXTRACT, extract_idx); + kbase_csf_firmware_global_input(&fw_ctx->kbdev->csf.global_iface, GLB_PRFCNT_EXTRACT, + extract_idx); } -static void kbasep_hwcnt_backend_csf_if_fw_get_gpu_cycle_count( - struct kbase_hwcnt_backend_csf_if_ctx *ctx, u64 *cycle_counts, - u64 clk_enable_map) +static void +kbasep_hwcnt_backend_csf_if_fw_get_gpu_cycle_count(struct kbase_hwcnt_backend_csf_if_ctx *ctx, + u64 *cycle_counts, u64 clk_enable_map) { struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx = (struct kbase_hwcnt_backend_csf_if_fw_ctx *)ctx; @@ -723,12 +674,12 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_gpu_cycle_count( if (clk == KBASE_CLOCK_DOMAIN_TOP) { /* Read cycle count for top clock domain. */ - kbase_backend_get_gpu_time_norequest( - fw_ctx->kbdev, &cycle_counts[clk], NULL, NULL); + kbase_backend_get_gpu_time_norequest(fw_ctx->kbdev, &cycle_counts[clk], + NULL, NULL); } else { /* Estimate cycle count for non-top clock domain. */ - cycle_counts[clk] = kbase_ccswe_cycle_at( - &fw_ctx->ccswe_shader_cores, timestamp_ns); + cycle_counts[clk] = + kbase_ccswe_cycle_at(&fw_ctx->ccswe_shader_cores, timestamp_ns); } } } @@ -738,8 +689,8 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_gpu_cycle_count( * * @fw_ctx: Pointer to context to destroy. */ -static void kbasep_hwcnt_backend_csf_if_fw_ctx_destroy( - struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx) +static void +kbasep_hwcnt_backend_csf_if_fw_ctx_destroy(struct kbase_hwcnt_backend_csf_if_fw_ctx *fw_ctx) { if (!fw_ctx) return; @@ -754,9 +705,9 @@ static void kbasep_hwcnt_backend_csf_if_fw_ctx_destroy( * @out_ctx: Non-NULL pointer to where info is stored on success. * Return: 0 on success, else error code. */ -static int kbasep_hwcnt_backend_csf_if_fw_ctx_create( - struct kbase_device *kbdev, - struct kbase_hwcnt_backend_csf_if_fw_ctx **out_ctx) +static int +kbasep_hwcnt_backend_csf_if_fw_ctx_create(struct kbase_device *kbdev, + struct kbase_hwcnt_backend_csf_if_fw_ctx **out_ctx) { u8 clk; int errcode = -ENOMEM; @@ -780,8 +731,7 @@ static int kbasep_hwcnt_backend_csf_if_fw_ctx_create( ctx->clk_enable_map = 0; kbase_ccswe_init(&ctx->ccswe_shader_cores); - ctx->rate_listener.notify = - kbasep_hwcnt_backend_csf_if_fw_on_freq_change; + ctx->rate_listener.notify = kbasep_hwcnt_backend_csf_if_fw_on_freq_change; *out_ctx = ctx; @@ -791,8 +741,7 @@ error: return errcode; } -void kbase_hwcnt_backend_csf_if_fw_destroy( - struct kbase_hwcnt_backend_csf_if *if_fw) +void kbase_hwcnt_backend_csf_if_fw_destroy(struct kbase_hwcnt_backend_csf_if *if_fw) { if (!if_fw) return; @@ -802,8 +751,8 @@ void kbase_hwcnt_backend_csf_if_fw_destroy( memset(if_fw, 0, sizeof(*if_fw)); } -int kbase_hwcnt_backend_csf_if_fw_create( - struct kbase_device *kbdev, struct kbase_hwcnt_backend_csf_if *if_fw) +int kbase_hwcnt_backend_csf_if_fw_create(struct kbase_device *kbdev, + struct kbase_hwcnt_backend_csf_if *if_fw) { int errcode; struct kbase_hwcnt_backend_csf_if_fw_ctx *ctx = NULL; @@ -816,8 +765,7 @@ int kbase_hwcnt_backend_csf_if_fw_create( return errcode; if_fw->ctx = (struct kbase_hwcnt_backend_csf_if_ctx *)ctx; - if_fw->assert_lock_held = - kbasep_hwcnt_backend_csf_if_fw_assert_lock_held; + if_fw->assert_lock_held = kbasep_hwcnt_backend_csf_if_fw_assert_lock_held; if_fw->lock = kbasep_hwcnt_backend_csf_if_fw_lock; if_fw->unlock = kbasep_hwcnt_backend_csf_if_fw_unlock; if_fw->get_prfcnt_info = kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info; @@ -828,11 +776,9 @@ int kbase_hwcnt_backend_csf_if_fw_create( if_fw->dump_enable = kbasep_hwcnt_backend_csf_if_fw_dump_enable; if_fw->dump_disable = kbasep_hwcnt_backend_csf_if_fw_dump_disable; if_fw->dump_request = kbasep_hwcnt_backend_csf_if_fw_dump_request; - if_fw->get_gpu_cycle_count = - kbasep_hwcnt_backend_csf_if_fw_get_gpu_cycle_count; + if_fw->get_gpu_cycle_count = kbasep_hwcnt_backend_csf_if_fw_get_gpu_cycle_count; if_fw->get_indexes = kbasep_hwcnt_backend_csf_if_fw_get_indexes; - if_fw->set_extract_index = - kbasep_hwcnt_backend_csf_if_fw_set_extract_index; + if_fw->set_extract_index = kbasep_hwcnt_backend_csf_if_fw_set_extract_index; return 0; } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if_fw.h b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.h similarity index 82% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if_fw.h rename to drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.h index b69668b2e822..71d1506694f4 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_csf_if_fw.h +++ b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.h @@ -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 @@ -26,7 +26,7 @@ #ifndef _KBASE_HWCNT_BACKEND_CSF_IF_FW_H_ #define _KBASE_HWCNT_BACKEND_CSF_IF_FW_H_ -#include "mali_kbase_hwcnt_backend_csf_if.h" +#include "hwcnt/backend/mali_kbase_hwcnt_backend_csf_if.h" /** * kbase_hwcnt_backend_csf_if_fw_create() - Create a firmware CSF interface @@ -36,15 +36,14 @@ * creation success. * Return: 0 on success, else error code. */ -int kbase_hwcnt_backend_csf_if_fw_create( - struct kbase_device *kbdev, struct kbase_hwcnt_backend_csf_if *if_fw); +int kbase_hwcnt_backend_csf_if_fw_create(struct kbase_device *kbdev, + struct kbase_hwcnt_backend_csf_if *if_fw); /** * kbase_hwcnt_backend_csf_if_fw_destroy() - Destroy a firmware CSF interface of * hardware counter backend. * @if_fw: Pointer to a CSF interface to destroy. */ -void kbase_hwcnt_backend_csf_if_fw_destroy( - struct kbase_hwcnt_backend_csf_if *if_fw); +void kbase_hwcnt_backend_csf_if_fw_destroy(struct kbase_hwcnt_backend_csf_if *if_fw); #endif /* _KBASE_HWCNT_BACKEND_CSF_IF_FW_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm.c b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm.c similarity index 73% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm.c rename to drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm.c index c995a1923583..9d9889a0e426 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm.c +++ b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm.c @@ -19,9 +19,9 @@ * */ -#include "mali_kbase_hwcnt_backend_jm.h" -#include "mali_kbase_hwcnt_gpu.h" -#include "mali_kbase_hwcnt_types.h" +#include "hwcnt/backend/mali_kbase_hwcnt_backend_jm.h" +#include "hwcnt/mali_kbase_hwcnt_gpu.h" +#include "hwcnt/mali_kbase_hwcnt_types.h" #include "mali_kbase.h" #include "backend/gpu/mali_kbase_pm_ca.h" #include "mali_kbase_hwaccess_instr.h" @@ -136,9 +136,8 @@ struct kbase_hwcnt_backend_jm { * * Return: 0 on success, else error code. */ -static int -kbasep_hwcnt_backend_jm_gpu_info_init(struct kbase_device *kbdev, - struct kbase_hwcnt_gpu_info *info) +static int kbasep_hwcnt_backend_jm_gpu_info_init(struct kbase_device *kbdev, + struct kbase_hwcnt_gpu_info *info) { size_t clk; @@ -153,13 +152,11 @@ kbasep_hwcnt_backend_jm_gpu_info_init(struct kbase_device *kbdev, { const struct base_gpu_props *props = &kbdev->gpu_props.props; const size_t l2_count = props->l2_props.num_l2_slices; - const size_t core_mask = - props->coherency_info.group[0].core_mask; + const size_t core_mask = props->coherency_info.group[0].core_mask; info->l2_count = l2_count; info->core_mask = core_mask; - info->prfcnt_values_per_block = - KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK; + info->prfcnt_values_per_block = KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK; } #endif /* CONFIG_MALI_BIFROST_NO_MALI */ @@ -173,9 +170,8 @@ kbasep_hwcnt_backend_jm_gpu_info_init(struct kbase_device *kbdev, return 0; } -static void kbasep_hwcnt_backend_jm_init_layout( - const struct kbase_hwcnt_gpu_info *gpu_info, - struct kbase_hwcnt_jm_physical_layout *phys_layout) +static void kbasep_hwcnt_backend_jm_init_layout(const struct kbase_hwcnt_gpu_info *gpu_info, + struct kbase_hwcnt_jm_physical_layout *phys_layout) { u8 shader_core_cnt; @@ -189,32 +185,29 @@ static void kbasep_hwcnt_backend_jm_init_layout( .tiler_cnt = KBASE_HWCNT_V5_TILER_BLOCK_COUNT, .mmu_l2_cnt = gpu_info->l2_count, .shader_cnt = shader_core_cnt, - .block_cnt = KBASE_HWCNT_V5_FE_BLOCK_COUNT + - KBASE_HWCNT_V5_TILER_BLOCK_COUNT + + .block_cnt = KBASE_HWCNT_V5_FE_BLOCK_COUNT + KBASE_HWCNT_V5_TILER_BLOCK_COUNT + gpu_info->l2_count + shader_core_cnt, .shader_avail_mask = gpu_info->core_mask, .headers_per_block = KBASE_HWCNT_V5_HEADERS_PER_BLOCK, .values_per_block = gpu_info->prfcnt_values_per_block, - .counters_per_block = gpu_info->prfcnt_values_per_block - - KBASE_HWCNT_V5_HEADERS_PER_BLOCK, + .counters_per_block = + gpu_info->prfcnt_values_per_block - KBASE_HWCNT_V5_HEADERS_PER_BLOCK, .enable_mask_offset = KBASE_HWCNT_V5_PRFCNT_EN_HEADER, }; } -static void kbasep_hwcnt_backend_jm_dump_sample( - const struct kbase_hwcnt_backend_jm *const backend_jm) +static void +kbasep_hwcnt_backend_jm_dump_sample(const struct kbase_hwcnt_backend_jm *const backend_jm) { size_t block_idx; const u32 *new_sample_buf = backend_jm->cpu_dump_va; const u32 *new_block = new_sample_buf; u64 *dst_buf = backend_jm->to_user_buf; u64 *dst_block = dst_buf; - const size_t values_per_block = - backend_jm->phys_layout.values_per_block; + const size_t values_per_block = backend_jm->phys_layout.values_per_block; const size_t dump_bytes = backend_jm->info->dump_bytes; - for (block_idx = 0; block_idx < backend_jm->phys_layout.block_cnt; - block_idx++) { + for (block_idx = 0; block_idx < backend_jm->phys_layout.block_cnt; block_idx++) { size_t ctr_idx; for (ctr_idx = 0; ctr_idx < values_per_block; ctr_idx++) @@ -224,10 +217,8 @@ static void kbasep_hwcnt_backend_jm_dump_sample( dst_block += values_per_block; } - WARN_ON(new_block != - new_sample_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); - WARN_ON(dst_block != - dst_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); + WARN_ON(new_block != new_sample_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); + WARN_ON(dst_block != dst_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); } /** @@ -237,21 +228,18 @@ static void kbasep_hwcnt_backend_jm_dump_sample( * @clk_index: Clock index * @clk_rate_hz: Clock frequency(hz) */ -static void kbasep_hwcnt_backend_jm_on_freq_change( - struct kbase_clk_rate_listener *rate_listener, - u32 clk_index, - u32 clk_rate_hz) +static void kbasep_hwcnt_backend_jm_on_freq_change(struct kbase_clk_rate_listener *rate_listener, + u32 clk_index, u32 clk_rate_hz) { - struct kbase_hwcnt_backend_jm *backend_jm = container_of( - rate_listener, struct kbase_hwcnt_backend_jm, rate_listener); + struct kbase_hwcnt_backend_jm *backend_jm = + container_of(rate_listener, struct kbase_hwcnt_backend_jm, rate_listener); u64 timestamp_ns; if (clk_index != KBASE_CLOCK_DOMAIN_SHADER_CORES) return; timestamp_ns = ktime_get_raw_ns(); - kbase_ccswe_freq_change( - &backend_jm->ccswe_shader_cores, timestamp_ns, clk_rate_hz); + kbase_ccswe_freq_change(&backend_jm->ccswe_shader_cores, timestamp_ns, clk_rate_hz); } /** @@ -261,53 +249,42 @@ static void kbasep_hwcnt_backend_jm_on_freq_change( * @enable_map: Non-NULL pointer to enable map specifying enabled counters. * @timestamp_ns: Timestamp(ns) when HWCNT were enabled. */ -static void kbasep_hwcnt_backend_jm_cc_enable( - struct kbase_hwcnt_backend_jm *backend_jm, - const struct kbase_hwcnt_enable_map *enable_map, - u64 timestamp_ns) +static void kbasep_hwcnt_backend_jm_cc_enable(struct kbase_hwcnt_backend_jm *backend_jm, + const struct kbase_hwcnt_enable_map *enable_map, + u64 timestamp_ns) { struct kbase_device *kbdev = backend_jm->kctx->kbdev; u64 clk_enable_map = enable_map->clk_enable_map; u64 cycle_count; - if (kbase_hwcnt_clk_enable_map_enabled( - clk_enable_map, KBASE_CLOCK_DOMAIN_TOP)) { + if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, KBASE_CLOCK_DOMAIN_TOP)) { /* turn on the cycle counter */ kbase_pm_request_gpu_cycle_counter_l2_is_on(kbdev); /* Read cycle count for top clock domain. */ - kbase_backend_get_gpu_time_norequest( - kbdev, &cycle_count, NULL, NULL); + kbase_backend_get_gpu_time_norequest(kbdev, &cycle_count, NULL, NULL); - backend_jm->prev_cycle_count[KBASE_CLOCK_DOMAIN_TOP] = - cycle_count; + backend_jm->prev_cycle_count[KBASE_CLOCK_DOMAIN_TOP] = cycle_count; } - if (kbase_hwcnt_clk_enable_map_enabled( - clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) { + if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) { /* software estimation for non-top clock domains */ struct kbase_clk_rate_trace_manager *rtm = &kbdev->pm.clk_rtm; - const struct kbase_clk_data *clk_data = - rtm->clks[KBASE_CLOCK_DOMAIN_SHADER_CORES]; + const struct kbase_clk_data *clk_data = rtm->clks[KBASE_CLOCK_DOMAIN_SHADER_CORES]; u32 cur_freq; unsigned long flags; spin_lock_irqsave(&rtm->lock, flags); - cur_freq = (u32) clk_data->clock_val; + cur_freq = (u32)clk_data->clock_val; kbase_ccswe_reset(&backend_jm->ccswe_shader_cores); - kbase_ccswe_freq_change( - &backend_jm->ccswe_shader_cores, - timestamp_ns, - cur_freq); + kbase_ccswe_freq_change(&backend_jm->ccswe_shader_cores, timestamp_ns, cur_freq); - kbase_clk_rate_trace_manager_subscribe_no_lock( - rtm, &backend_jm->rate_listener); + kbase_clk_rate_trace_manager_subscribe_no_lock(rtm, &backend_jm->rate_listener); spin_unlock_irqrestore(&rtm->lock, flags); /* ccswe was reset. The estimated cycle is zero. */ - backend_jm->prev_cycle_count[ - KBASE_CLOCK_DOMAIN_SHADER_CORES] = 0; + backend_jm->prev_cycle_count[KBASE_CLOCK_DOMAIN_SHADER_CORES] = 0; } /* Keep clk_enable_map for dump_request. */ @@ -319,28 +296,22 @@ static void kbasep_hwcnt_backend_jm_cc_enable( * * @backend_jm: Non-NULL pointer to backend. */ -static void kbasep_hwcnt_backend_jm_cc_disable( - struct kbase_hwcnt_backend_jm *backend_jm) +static void kbasep_hwcnt_backend_jm_cc_disable(struct kbase_hwcnt_backend_jm *backend_jm) { struct kbase_device *kbdev = backend_jm->kctx->kbdev; struct kbase_clk_rate_trace_manager *rtm = &kbdev->pm.clk_rtm; u64 clk_enable_map = backend_jm->clk_enable_map; - if (kbase_hwcnt_clk_enable_map_enabled( - clk_enable_map, KBASE_CLOCK_DOMAIN_TOP)) { + if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, KBASE_CLOCK_DOMAIN_TOP)) { /* turn off the cycle counter */ kbase_pm_release_gpu_cycle_counter(kbdev); } - if (kbase_hwcnt_clk_enable_map_enabled( - clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) { - - kbase_clk_rate_trace_manager_unsubscribe( - rtm, &backend_jm->rate_listener); + if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) { + kbase_clk_rate_trace_manager_unsubscribe(rtm, &backend_jm->rate_listener); } } - /** * kbasep_hwcnt_gpu_update_curr_config() - Update the destination buffer with * current config information. @@ -356,38 +327,33 @@ static void kbasep_hwcnt_backend_jm_cc_disable( * * Return: 0 on success, else error code. */ -static int kbasep_hwcnt_gpu_update_curr_config( - struct kbase_device *kbdev, - struct kbase_hwcnt_curr_config *curr_config) +static int kbasep_hwcnt_gpu_update_curr_config(struct kbase_device *kbdev, + struct kbase_hwcnt_curr_config *curr_config) { if (WARN_ON(!kbdev) || WARN_ON(!curr_config)) return -EINVAL; lockdep_assert_held(&kbdev->hwaccess_lock); - curr_config->num_l2_slices = - kbdev->gpu_props.curr_config.l2_slices; - curr_config->shader_present = - kbdev->gpu_props.curr_config.shader_present; + curr_config->num_l2_slices = kbdev->gpu_props.curr_config.l2_slices; + curr_config->shader_present = kbdev->gpu_props.curr_config.shader_present; return 0; } /* JM backend implementation of kbase_hwcnt_backend_timestamp_ns_fn */ -static u64 kbasep_hwcnt_backend_jm_timestamp_ns( - struct kbase_hwcnt_backend *backend) +static u64 kbasep_hwcnt_backend_jm_timestamp_ns(struct kbase_hwcnt_backend *backend) { (void)backend; return ktime_get_raw_ns(); } /* JM backend implementation of kbase_hwcnt_backend_dump_enable_nolock_fn */ -static int kbasep_hwcnt_backend_jm_dump_enable_nolock( - struct kbase_hwcnt_backend *backend, - const struct kbase_hwcnt_enable_map *enable_map) +static int +kbasep_hwcnt_backend_jm_dump_enable_nolock(struct kbase_hwcnt_backend *backend, + const struct kbase_hwcnt_enable_map *enable_map) { int errcode; - struct kbase_hwcnt_backend_jm *backend_jm = - (struct kbase_hwcnt_backend_jm *)backend; + struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; struct kbase_context *kctx; struct kbase_device *kbdev; struct kbase_hwcnt_physical_enable_map phys_enable_map; @@ -406,8 +372,7 @@ static int kbasep_hwcnt_backend_jm_dump_enable_nolock( kbase_hwcnt_gpu_enable_map_to_physical(&phys_enable_map, enable_map); - kbase_hwcnt_gpu_set_to_physical(&phys_counter_set, - backend_jm->info->counter_set); + kbase_hwcnt_gpu_set_to_physical(&phys_counter_set, backend_jm->info->counter_set); enable.fe_bm = phys_enable_map.fe_bm; enable.shader_bm = phys_enable_map.shader_bm; @@ -425,8 +390,7 @@ static int kbasep_hwcnt_backend_jm_dump_enable_nolock( timestamp_ns = kbasep_hwcnt_backend_jm_timestamp_ns(backend); /* Update the current configuration information. */ - errcode = kbasep_hwcnt_gpu_update_curr_config(kbdev, - &backend_jm->curr_config); + errcode = kbasep_hwcnt_gpu_update_curr_config(kbdev, &backend_jm->curr_config); if (errcode) goto error; @@ -446,14 +410,12 @@ error: } /* JM backend implementation of kbase_hwcnt_backend_dump_enable_fn */ -static int kbasep_hwcnt_backend_jm_dump_enable( - struct kbase_hwcnt_backend *backend, - const struct kbase_hwcnt_enable_map *enable_map) +static int kbasep_hwcnt_backend_jm_dump_enable(struct kbase_hwcnt_backend *backend, + const struct kbase_hwcnt_enable_map *enable_map) { unsigned long flags; int errcode; - struct kbase_hwcnt_backend_jm *backend_jm = - (struct kbase_hwcnt_backend_jm *)backend; + struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; struct kbase_device *kbdev; if (!backend_jm) @@ -463,8 +425,7 @@ static int kbasep_hwcnt_backend_jm_dump_enable( spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - errcode = kbasep_hwcnt_backend_jm_dump_enable_nolock( - backend, enable_map); + errcode = kbasep_hwcnt_backend_jm_dump_enable_nolock(backend, enable_map); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); @@ -472,12 +433,10 @@ static int kbasep_hwcnt_backend_jm_dump_enable( } /* JM backend implementation of kbase_hwcnt_backend_dump_disable_fn */ -static void kbasep_hwcnt_backend_jm_dump_disable( - struct kbase_hwcnt_backend *backend) +static void kbasep_hwcnt_backend_jm_dump_disable(struct kbase_hwcnt_backend *backend) { int errcode; - struct kbase_hwcnt_backend_jm *backend_jm = - (struct kbase_hwcnt_backend_jm *)backend; + struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; if (WARN_ON(!backend_jm) || !backend_jm->enabled) return; @@ -491,11 +450,9 @@ static void kbasep_hwcnt_backend_jm_dump_disable( } /* JM backend implementation of kbase_hwcnt_backend_dump_clear_fn */ -static int kbasep_hwcnt_backend_jm_dump_clear( - struct kbase_hwcnt_backend *backend) +static int kbasep_hwcnt_backend_jm_dump_clear(struct kbase_hwcnt_backend *backend) { - struct kbase_hwcnt_backend_jm *backend_jm = - (struct kbase_hwcnt_backend_jm *)backend; + struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; if (!backend_jm || !backend_jm->enabled) return -EINVAL; @@ -504,12 +461,10 @@ static int kbasep_hwcnt_backend_jm_dump_clear( } /* JM backend implementation of kbase_hwcnt_backend_dump_request_fn */ -static int kbasep_hwcnt_backend_jm_dump_request( - struct kbase_hwcnt_backend *backend, - u64 *dump_time_ns) +static int kbasep_hwcnt_backend_jm_dump_request(struct kbase_hwcnt_backend *backend, + u64 *dump_time_ns) { - struct kbase_hwcnt_backend_jm *backend_jm = - (struct kbase_hwcnt_backend_jm *)backend; + struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; struct kbase_device *kbdev; const struct kbase_hwcnt_metadata *metadata; u64 current_cycle_count; @@ -528,28 +483,25 @@ static int kbasep_hwcnt_backend_jm_dump_request( *dump_time_ns = kbasep_hwcnt_backend_jm_timestamp_ns(backend); ret = kbase_instr_hwcnt_request_dump(backend_jm->kctx); - kbase_hwcnt_metadata_for_each_clock(metadata, clk) { - if (!kbase_hwcnt_clk_enable_map_enabled( - backend_jm->clk_enable_map, clk)) + kbase_hwcnt_metadata_for_each_clock(metadata, clk) + { + if (!kbase_hwcnt_clk_enable_map_enabled(backend_jm->clk_enable_map, clk)) continue; if (clk == KBASE_CLOCK_DOMAIN_TOP) { /* Read cycle count for top clock domain. */ - kbase_backend_get_gpu_time_norequest( - kbdev, ¤t_cycle_count, - NULL, NULL); + kbase_backend_get_gpu_time_norequest(kbdev, ¤t_cycle_count, + NULL, NULL); } else { /* * Estimate cycle count for non-top clock * domain. */ current_cycle_count = kbase_ccswe_cycle_at( - &backend_jm->ccswe_shader_cores, - *dump_time_ns); + &backend_jm->ccswe_shader_cores, *dump_time_ns); } backend_jm->cycle_count_elapsed[clk] = - current_cycle_count - - backend_jm->prev_cycle_count[clk]; + current_cycle_count - backend_jm->prev_cycle_count[clk]; /* * Keep the current cycle count for later calculation. @@ -563,11 +515,9 @@ static int kbasep_hwcnt_backend_jm_dump_request( } /* JM backend implementation of kbase_hwcnt_backend_dump_wait_fn */ -static int kbasep_hwcnt_backend_jm_dump_wait( - struct kbase_hwcnt_backend *backend) +static int kbasep_hwcnt_backend_jm_dump_wait(struct kbase_hwcnt_backend *backend) { - struct kbase_hwcnt_backend_jm *backend_jm = - (struct kbase_hwcnt_backend_jm *)backend; + struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; if (!backend_jm || !backend_jm->enabled) return -EINVAL; @@ -576,14 +526,12 @@ static int kbasep_hwcnt_backend_jm_dump_wait( } /* JM backend implementation of kbase_hwcnt_backend_dump_get_fn */ -static int kbasep_hwcnt_backend_jm_dump_get( - struct kbase_hwcnt_backend *backend, - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_enable_map *dst_enable_map, - bool accumulate) +static int kbasep_hwcnt_backend_jm_dump_get(struct kbase_hwcnt_backend *backend, + struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_enable_map *dst_enable_map, + bool accumulate) { - struct kbase_hwcnt_backend_jm *backend_jm = - (struct kbase_hwcnt_backend_jm *)backend; + struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; size_t clk; #if IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) struct kbase_device *kbdev; @@ -597,16 +545,15 @@ static int kbasep_hwcnt_backend_jm_dump_get( return -EINVAL; /* Invalidate the kernel buffer before reading from it. */ - kbase_sync_mem_regions( - backend_jm->kctx, backend_jm->vmap, KBASE_SYNC_TO_CPU); + kbase_sync_mem_regions(backend_jm->kctx, backend_jm->vmap, KBASE_SYNC_TO_CPU); /* Dump sample to the internal 64-bit user buffer. */ kbasep_hwcnt_backend_jm_dump_sample(backend_jm); /* Extract elapsed cycle count for each clock domain if enabled. */ - kbase_hwcnt_metadata_for_each_clock(dst_enable_map->metadata, clk) { - if (!kbase_hwcnt_clk_enable_map_enabled( - dst_enable_map->clk_enable_map, clk)) + kbase_hwcnt_metadata_for_each_clock(dst_enable_map->metadata, clk) + { + if (!kbase_hwcnt_clk_enable_map_enabled(dst_enable_map->clk_enable_map, clk)) continue; /* Reset the counter to zero if accumulation is off. */ @@ -621,17 +568,16 @@ static int kbasep_hwcnt_backend_jm_dump_get( spin_lock_irqsave(&kbdev->hwaccess_lock, flags); /* Update the current configuration information. */ - errcode = kbasep_hwcnt_gpu_update_curr_config(kbdev, - &backend_jm->curr_config); + errcode = kbasep_hwcnt_gpu_update_curr_config(kbdev, &backend_jm->curr_config); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); if (errcode) return errcode; #endif /* CONFIG_MALI_BIFROST_NO_MALI */ - return kbase_hwcnt_jm_dump_get(dst, backend_jm->to_user_buf, - dst_enable_map, backend_jm->pm_core_mask, - &backend_jm->curr_config, accumulate); + return kbase_hwcnt_jm_dump_get(dst, backend_jm->to_user_buf, dst_enable_map, + backend_jm->pm_core_mask, &backend_jm->curr_config, + accumulate); } /** @@ -643,10 +589,8 @@ static int kbasep_hwcnt_backend_jm_dump_get( * * Return: 0 on success, else error code. */ -static int kbasep_hwcnt_backend_jm_dump_alloc( - const struct kbase_hwcnt_backend_jm_info *info, - struct kbase_context *kctx, - u64 *gpu_dump_va) +static int kbasep_hwcnt_backend_jm_dump_alloc(const struct kbase_hwcnt_backend_jm_info *info, + struct kbase_context *kctx, u64 *gpu_dump_va) { struct kbase_va_region *reg; u64 flags; @@ -661,16 +605,12 @@ static int kbasep_hwcnt_backend_jm_dump_alloc( WARN_ON(!kctx); WARN_ON(!gpu_dump_va); - flags = BASE_MEM_PROT_CPU_RD | - BASE_MEM_PROT_GPU_WR | - BASEP_MEM_PERMANENT_KERNEL_MAPPING | - BASE_MEM_CACHED_CPU | - BASE_MEM_UNCACHED_GPU; + flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_WR | BASEP_MEM_PERMANENT_KERNEL_MAPPING | + BASE_MEM_CACHED_CPU | BASE_MEM_UNCACHED_GPU; nr_pages = PFN_UP(info->dump_bytes); - reg = kbase_mem_alloc(kctx, nr_pages, nr_pages, 0, &flags, gpu_dump_va, - mmu_sync_info); + reg = kbase_mem_alloc(kctx, nr_pages, nr_pages, 0, &flags, gpu_dump_va, mmu_sync_info); if (!reg) return -ENOMEM; @@ -683,9 +623,7 @@ static int kbasep_hwcnt_backend_jm_dump_alloc( * @kctx: Non-NULL pointer to kbase context. * @gpu_dump_va: GPU dump buffer virtual address. */ -static void kbasep_hwcnt_backend_jm_dump_free( - struct kbase_context *kctx, - u64 gpu_dump_va) +static void kbasep_hwcnt_backend_jm_dump_free(struct kbase_context *kctx, u64 gpu_dump_va) { WARN_ON(!kctx); if (gpu_dump_va) @@ -698,8 +636,7 @@ static void kbasep_hwcnt_backend_jm_dump_free( * * Can be safely called on a backend in any state of partial construction. */ -static void kbasep_hwcnt_backend_jm_destroy( - struct kbase_hwcnt_backend_jm *backend) +static void kbasep_hwcnt_backend_jm_destroy(struct kbase_hwcnt_backend_jm *backend) { if (!backend) return; @@ -712,8 +649,7 @@ static void kbasep_hwcnt_backend_jm_destroy( kbase_phy_alloc_mapping_put(kctx, backend->vmap); if (backend->gpu_dump_va) - kbasep_hwcnt_backend_jm_dump_free( - kctx, backend->gpu_dump_va); + kbasep_hwcnt_backend_jm_dump_free(kctx, backend->gpu_dump_va); kbasep_js_release_privileged_ctx(kbdev, kctx); kbase_destroy_context(kctx); @@ -731,9 +667,8 @@ static void kbasep_hwcnt_backend_jm_destroy( * * Return: 0 on success, else error code. */ -static int kbasep_hwcnt_backend_jm_create( - const struct kbase_hwcnt_backend_jm_info *info, - struct kbase_hwcnt_backend_jm **out_backend) +static int kbasep_hwcnt_backend_jm_create(const struct kbase_hwcnt_backend_jm_info *info, + struct kbase_hwcnt_backend_jm **out_backend) { int errcode; struct kbase_device *kbdev; @@ -749,28 +684,25 @@ static int kbasep_hwcnt_backend_jm_create( goto alloc_error; backend->info = info; - kbasep_hwcnt_backend_jm_init_layout(&info->hwcnt_gpu_info, - &backend->phys_layout); + kbasep_hwcnt_backend_jm_init_layout(&info->hwcnt_gpu_info, &backend->phys_layout); backend->kctx = kbase_create_context(kbdev, true, - BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED, 0, NULL); + BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED, 0, NULL); if (!backend->kctx) goto alloc_error; kbasep_js_schedule_privileged_ctx(kbdev, backend->kctx); - errcode = kbasep_hwcnt_backend_jm_dump_alloc( - info, backend->kctx, &backend->gpu_dump_va); + errcode = kbasep_hwcnt_backend_jm_dump_alloc(info, backend->kctx, &backend->gpu_dump_va); if (errcode) goto error; - backend->cpu_dump_va = kbase_phy_alloc_mapping_get(backend->kctx, - backend->gpu_dump_va, &backend->vmap); + backend->cpu_dump_va = + kbase_phy_alloc_mapping_get(backend->kctx, backend->gpu_dump_va, &backend->vmap); if (!backend->cpu_dump_va || !backend->vmap) goto alloc_error; - backend->to_user_buf = - kzalloc(info->metadata->dump_buf_bytes, GFP_KERNEL); + backend->to_user_buf = kzalloc(info->metadata->dump_buf_bytes, GFP_KERNEL); if (!backend->to_user_buf) goto alloc_error; @@ -798,9 +730,8 @@ kbasep_hwcnt_backend_jm_metadata(const struct kbase_hwcnt_backend_info *info) } /* JM backend implementation of kbase_hwcnt_backend_init_fn */ -static int kbasep_hwcnt_backend_jm_init( - const struct kbase_hwcnt_backend_info *info, - struct kbase_hwcnt_backend **out_backend) +static int kbasep_hwcnt_backend_jm_init(const struct kbase_hwcnt_backend_info *info, + struct kbase_hwcnt_backend **out_backend) { int errcode; struct kbase_hwcnt_backend_jm *backend = NULL; @@ -808,8 +739,8 @@ static int kbasep_hwcnt_backend_jm_init( if (!info || !out_backend) return -EINVAL; - errcode = kbasep_hwcnt_backend_jm_create( - (const struct kbase_hwcnt_backend_jm_info *) info, &backend); + errcode = kbasep_hwcnt_backend_jm_create((const struct kbase_hwcnt_backend_jm_info *)info, + &backend); if (errcode) return errcode; @@ -825,8 +756,7 @@ static void kbasep_hwcnt_backend_jm_term(struct kbase_hwcnt_backend *backend) return; kbasep_hwcnt_backend_jm_dump_disable(backend); - kbasep_hwcnt_backend_jm_destroy( - (struct kbase_hwcnt_backend_jm *)backend); + kbasep_hwcnt_backend_jm_destroy((struct kbase_hwcnt_backend_jm *)backend); } /** @@ -835,8 +765,7 @@ static void kbasep_hwcnt_backend_jm_term(struct kbase_hwcnt_backend *backend) * * Can be safely called on a backend info in any state of partial construction. */ -static void kbasep_hwcnt_backend_jm_info_destroy( - const struct kbase_hwcnt_backend_jm_info *info) +static void kbasep_hwcnt_backend_jm_info_destroy(const struct kbase_hwcnt_backend_jm_info *info) { if (!info) return; @@ -852,9 +781,8 @@ static void kbasep_hwcnt_backend_jm_info_destroy( * * Return: 0 on success, else error code. */ -static int kbasep_hwcnt_backend_jm_info_create( - struct kbase_device *kbdev, - const struct kbase_hwcnt_backend_jm_info **out_info) +static int kbasep_hwcnt_backend_jm_info_create(struct kbase_device *kbdev, + const struct kbase_hwcnt_backend_jm_info **out_info) { int errcode = -ENOMEM; struct kbase_hwcnt_backend_jm_info *info = NULL; @@ -877,15 +805,12 @@ static int kbasep_hwcnt_backend_jm_info_create( info->counter_set = KBASE_HWCNT_SET_PRIMARY; #endif - errcode = kbasep_hwcnt_backend_jm_gpu_info_init(kbdev, - &info->hwcnt_gpu_info); + errcode = kbasep_hwcnt_backend_jm_gpu_info_init(kbdev, &info->hwcnt_gpu_info); if (errcode) goto error; - errcode = kbase_hwcnt_jm_metadata_create(&info->hwcnt_gpu_info, - info->counter_set, - &info->metadata, - &info->dump_bytes); + errcode = kbase_hwcnt_jm_metadata_create(&info->hwcnt_gpu_info, info->counter_set, + &info->metadata, &info->dump_bytes); if (errcode) goto error; @@ -897,9 +822,8 @@ error: return errcode; } -int kbase_hwcnt_backend_jm_create( - struct kbase_device *kbdev, - struct kbase_hwcnt_backend_interface *iface) +int kbase_hwcnt_backend_jm_create(struct kbase_device *kbdev, + struct kbase_hwcnt_backend_interface *iface) { int errcode; const struct kbase_hwcnt_backend_jm_info *info = NULL; @@ -928,8 +852,7 @@ int kbase_hwcnt_backend_jm_create( return 0; } -void kbase_hwcnt_backend_jm_destroy( - struct kbase_hwcnt_backend_interface *iface) +void kbase_hwcnt_backend_jm_destroy(struct kbase_hwcnt_backend_interface *iface) { if (!iface) return; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm.h b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm.h similarity index 84% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm.h rename to drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm.h index 1bc39066b414..4a6293c25473 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm.h +++ b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2018, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 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 @@ -27,7 +27,7 @@ #ifndef _KBASE_HWCNT_BACKEND_JM_H_ #define _KBASE_HWCNT_BACKEND_JM_H_ -#include "mali_kbase_hwcnt_backend.h" +#include "hwcnt/backend/mali_kbase_hwcnt_backend.h" struct kbase_device; @@ -42,9 +42,8 @@ struct kbase_device; * * Return: 0 on success, else error code. */ -int kbase_hwcnt_backend_jm_create( - struct kbase_device *kbdev, - struct kbase_hwcnt_backend_interface *iface); +int kbase_hwcnt_backend_jm_create(struct kbase_device *kbdev, + struct kbase_hwcnt_backend_interface *iface); /** * kbase_hwcnt_backend_jm_destroy() - Destroy a JM hardware counter backend @@ -54,7 +53,6 @@ int kbase_hwcnt_backend_jm_create( * Can be safely called on an all-zeroed interface, or on an already destroyed * interface. */ -void kbase_hwcnt_backend_jm_destroy( - struct kbase_hwcnt_backend_interface *iface); +void kbase_hwcnt_backend_jm_destroy(struct kbase_hwcnt_backend_interface *iface); #endif /* _KBASE_HWCNT_BACKEND_JM_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm_watchdog.c b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.c similarity index 97% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm_watchdog.c rename to drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.c index 8bb7ccb49a64..564700b2d978 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm_watchdog.c +++ b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.c @@ -21,11 +21,12 @@ #include -#include -#include +#include +#include -#include -#include +#include +#include +#include #if IS_ENABLED(CONFIG_MALI_IS_FPGA) && !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) /* Backend watch dog timer interval in milliseconds: 18 seconds. */ @@ -118,8 +119,7 @@ enum backend_watchdog_state { */ enum wd_init_state { HWCNT_JM_WD_INIT_START, - HWCNT_JM_WD_INIT_ALLOC = HWCNT_JM_WD_INIT_START, - HWCNT_JM_WD_INIT_BACKEND, + HWCNT_JM_WD_INIT_BACKEND = HWCNT_JM_WD_INIT_START, HWCNT_JM_WD_INIT_ENABLE_MAP, HWCNT_JM_WD_INIT_DUMP_BUFFER, HWCNT_JM_WD_INIT_END @@ -296,16 +296,10 @@ kbasep_hwcnt_backend_jm_watchdog_term_partial(struct kbase_hwcnt_backend_jm_watc if (!wd_backend) return; - /* disable timer thread to avoid concurrent access to shared resources */ - wd_backend->info->dump_watchdog_iface->disable( - wd_backend->info->dump_watchdog_iface->timer); + WARN_ON(state > HWCNT_JM_WD_INIT_END); - /*will exit the loop when state reaches HWCNT_JM_WD_INIT_START*/ while (state-- > HWCNT_JM_WD_INIT_START) { switch (state) { - case HWCNT_JM_WD_INIT_ALLOC: - kfree(wd_backend); - break; case HWCNT_JM_WD_INIT_BACKEND: wd_backend->info->jm_backend_iface->term(wd_backend->jm_backend); break; @@ -319,6 +313,8 @@ kbasep_hwcnt_backend_jm_watchdog_term_partial(struct kbase_hwcnt_backend_jm_watc break; } } + + kfree(wd_backend); } /* Job manager watchdog backend, implementation of kbase_hwcnt_backend_term_fn @@ -326,11 +322,17 @@ kbasep_hwcnt_backend_jm_watchdog_term_partial(struct kbase_hwcnt_backend_jm_watc */ static void kbasep_hwcnt_backend_jm_watchdog_term(struct kbase_hwcnt_backend *backend) { + struct kbase_hwcnt_backend_jm_watchdog *wd_backend = + (struct kbase_hwcnt_backend_jm_watchdog *)backend; + if (!backend) return; - kbasep_hwcnt_backend_jm_watchdog_term_partial( - (struct kbase_hwcnt_backend_jm_watchdog *)backend, HWCNT_JM_WD_INIT_END); + /* disable timer thread to avoid concurrent access to shared resources */ + wd_backend->info->dump_watchdog_iface->disable( + wd_backend->info->dump_watchdog_iface->timer); + + kbasep_hwcnt_backend_jm_watchdog_term_partial(wd_backend, HWCNT_JM_WD_INIT_END); } /* Job manager watchdog backend, implementation of kbase_hwcnt_backend_init_fn */ @@ -350,20 +352,20 @@ static int kbasep_hwcnt_backend_jm_watchdog_init(const struct kbase_hwcnt_backen jm_info = wd_info->jm_backend_iface->info; metadata = wd_info->jm_backend_iface->metadata(wd_info->jm_backend_iface->info); + wd_backend = kmalloc(sizeof(*wd_backend), GFP_KERNEL); + if (!wd_backend) { + *out_backend = NULL; + return -ENOMEM; + } + + *wd_backend = (struct kbase_hwcnt_backend_jm_watchdog){ + .info = wd_info, + .timeout_ms = hwcnt_backend_watchdog_timer_interval_ms, + .locked = { .state = HWCNT_JM_WD_IDLE_BUFFER_EMPTY, .is_enabled = false } + }; + while (state < HWCNT_JM_WD_INIT_END && !errcode) { switch (state) { - case HWCNT_JM_WD_INIT_ALLOC: - wd_backend = kmalloc(sizeof(*wd_backend), GFP_KERNEL); - if (wd_backend) { - *wd_backend = (struct kbase_hwcnt_backend_jm_watchdog){ - .info = wd_info, - .timeout_ms = hwcnt_backend_watchdog_timer_interval_ms, - .locked = { .state = HWCNT_JM_WD_IDLE_BUFFER_EMPTY, - .is_enabled = false } - }; - } else - errcode = -ENOMEM; - break; case HWCNT_JM_WD_INIT_BACKEND: errcode = wd_info->jm_backend_iface->init(jm_info, &wd_backend->jm_backend); break; @@ -823,5 +825,5 @@ void kbase_hwcnt_backend_jm_watchdog_destroy(struct kbase_hwcnt_backend_interfac kfree((struct kbase_hwcnt_backend_jm_watchdog_info *)iface->info); /*blanking the watchdog backend interface*/ - *iface = (struct kbase_hwcnt_backend_interface){ NULL }; + memset(iface, 0, sizeof(*iface)); } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm_watchdog.h b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.h similarity index 94% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm_watchdog.h rename to drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.h index 5021b4fdb966..02a7952cced2 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_backend_jm_watchdog.h +++ b/drivers/gpu/arm/bifrost/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.h @@ -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 @@ -32,8 +32,8 @@ #ifndef _KBASE_HWCNT_BACKEND_JM_WATCHDOG_H_ #define _KBASE_HWCNT_BACKEND_JM_WATCHDOG_H_ -#include -#include +#include +#include /** * kbase_hwcnt_backend_jm_watchdog_create() - Create a job manager hardware counter watchdog diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt.c b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt.c similarity index 87% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt.c rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt.c index a54f005915ae..e724572560d5 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt.c +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt.c @@ -23,10 +23,10 @@ * Implementation of hardware counter context and accumulator APIs. */ -#include "mali_kbase_hwcnt_context.h" -#include "mali_kbase_hwcnt_accumulator.h" -#include "mali_kbase_hwcnt_backend.h" -#include "mali_kbase_hwcnt_types.h" +#include "hwcnt/mali_kbase_hwcnt_context.h" +#include "hwcnt/mali_kbase_hwcnt_accumulator.h" +#include "hwcnt/backend/mali_kbase_hwcnt_backend.h" +#include "hwcnt/mali_kbase_hwcnt_types.h" #include #include @@ -39,11 +39,7 @@ * @ACCUM_STATE_ENABLED: Enabled state, where dumping is enabled if there are * any enabled counters. */ -enum kbase_hwcnt_accum_state { - ACCUM_STATE_ERROR, - ACCUM_STATE_DISABLED, - ACCUM_STATE_ENABLED -}; +enum kbase_hwcnt_accum_state { ACCUM_STATE_ERROR, ACCUM_STATE_DISABLED, ACCUM_STATE_ENABLED }; /** * struct kbase_hwcnt_accumulator - Hardware counter accumulator structure. @@ -130,9 +126,8 @@ struct kbase_hwcnt_context { struct workqueue_struct *wq; }; -int kbase_hwcnt_context_init( - const struct kbase_hwcnt_backend_interface *iface, - struct kbase_hwcnt_context **out_hctx) +int kbase_hwcnt_context_init(const struct kbase_hwcnt_backend_interface *iface, + struct kbase_hwcnt_context **out_hctx) { struct kbase_hwcnt_context *hctx = NULL; @@ -149,8 +144,7 @@ int kbase_hwcnt_context_init( mutex_init(&hctx->accum_lock); hctx->accum_inited = false; - hctx->wq = - alloc_workqueue("mali_kbase_hwcnt", WQ_HIGHPRI | WQ_UNBOUND, 0); + hctx->wq = alloc_workqueue("mali_kbase_hwcnt", WQ_HIGHPRI | WQ_UNBOUND, 0); if (!hctx->wq) goto err_alloc_workqueue; @@ -208,35 +202,30 @@ static int kbasep_hwcnt_accumulator_init(struct kbase_hwcnt_context *hctx) WARN_ON(!hctx); WARN_ON(!hctx->accum_inited); - errcode = hctx->iface->init( - hctx->iface->info, &hctx->accum.backend); + errcode = hctx->iface->init(hctx->iface->info, &hctx->accum.backend); if (errcode) goto error; hctx->accum.metadata = hctx->iface->metadata(hctx->iface->info); hctx->accum.state = ACCUM_STATE_ERROR; - errcode = kbase_hwcnt_enable_map_alloc(hctx->accum.metadata, - &hctx->accum.enable_map); + errcode = kbase_hwcnt_enable_map_alloc(hctx->accum.metadata, &hctx->accum.enable_map); if (errcode) goto error; hctx->accum.enable_map_any_enabled = false; - errcode = kbase_hwcnt_dump_buffer_alloc(hctx->accum.metadata, - &hctx->accum.accum_buf); + errcode = kbase_hwcnt_dump_buffer_alloc(hctx->accum.metadata, &hctx->accum.accum_buf); if (errcode) goto error; - errcode = kbase_hwcnt_enable_map_alloc(hctx->accum.metadata, - &hctx->accum.scratch_map); + errcode = kbase_hwcnt_enable_map_alloc(hctx->accum.metadata, &hctx->accum.scratch_map); if (errcode) goto error; hctx->accum.accumulated = false; - hctx->accum.ts_last_dump_ns = - hctx->iface->timestamp_ns(hctx->accum.backend); + hctx->accum.ts_last_dump_ns = hctx->iface->timestamp_ns(hctx->accum.backend); return 0; @@ -252,8 +241,7 @@ error: * @hctx: Non-NULL pointer to hardware counter context. * @accumulate: True if we should accumulate before disabling, else false. */ -static void kbasep_hwcnt_accumulator_disable( - struct kbase_hwcnt_context *hctx, bool accumulate) +static void kbasep_hwcnt_accumulator_disable(struct kbase_hwcnt_context *hctx, bool accumulate) { int errcode = 0; bool backend_enabled = false; @@ -272,8 +260,7 @@ static void kbasep_hwcnt_accumulator_disable( WARN_ON(hctx->disable_count != 0); WARN_ON(hctx->accum.state == ACCUM_STATE_DISABLED); - if ((hctx->accum.state == ACCUM_STATE_ENABLED) && - (accum->enable_map_any_enabled)) + if ((hctx->accum.state == ACCUM_STATE_ENABLED) && (accum->enable_map_any_enabled)) backend_enabled = true; if (!backend_enabled) @@ -297,8 +284,8 @@ static void kbasep_hwcnt_accumulator_disable( if (errcode) goto disable; - errcode = hctx->iface->dump_get(accum->backend, - &accum->accum_buf, &accum->enable_map, accum->accumulated); + errcode = hctx->iface->dump_get(accum->backend, &accum->accum_buf, &accum->enable_map, + accum->accumulated); if (errcode) goto disable; @@ -336,8 +323,7 @@ static void kbasep_hwcnt_accumulator_enable(struct kbase_hwcnt_context *hctx) /* The backend only needs enabling if any counters are enabled */ if (accum->enable_map_any_enabled) - errcode = hctx->iface->dump_enable_nolock( - accum->backend, &accum->enable_map); + errcode = hctx->iface->dump_enable_nolock(accum->backend, &accum->enable_map); if (!errcode) accum->state = ACCUM_STATE_ENABLED; @@ -364,12 +350,9 @@ static void kbasep_hwcnt_accumulator_enable(struct kbase_hwcnt_context *hctx) * * Return: 0 on success, else error code. */ -static int kbasep_hwcnt_accumulator_dump( - struct kbase_hwcnt_context *hctx, - u64 *ts_start_ns, - u64 *ts_end_ns, - struct kbase_hwcnt_dump_buffer *dump_buf, - const struct kbase_hwcnt_enable_map *new_map) +static int kbasep_hwcnt_accumulator_dump(struct kbase_hwcnt_context *hctx, u64 *ts_start_ns, + u64 *ts_end_ns, struct kbase_hwcnt_dump_buffer *dump_buf, + const struct kbase_hwcnt_enable_map *new_map) { int errcode = 0; unsigned long flags; @@ -398,8 +381,7 @@ static int kbasep_hwcnt_accumulator_dump( kbase_hwcnt_enable_map_copy(cur_map, &accum->enable_map); if (new_map) - new_map_any_enabled = - kbase_hwcnt_enable_map_any_enabled(new_map); + new_map_any_enabled = kbase_hwcnt_enable_map_any_enabled(new_map); /* * We're holding accum_lock, so the accumulator state might transition @@ -426,8 +408,7 @@ static int kbasep_hwcnt_accumulator_dump( * then we'll do it ourselves after the dump. */ if (new_map) { - kbase_hwcnt_enable_map_copy( - &accum->enable_map, new_map); + kbase_hwcnt_enable_map_copy(&accum->enable_map, new_map); accum->enable_map_any_enabled = new_map_any_enabled; } @@ -440,12 +421,10 @@ static int kbasep_hwcnt_accumulator_dump( /* Initiate the dump if the backend is enabled. */ if ((state == ACCUM_STATE_ENABLED) && cur_map_any_enabled) { if (dump_buf) { - errcode = hctx->iface->dump_request( - accum->backend, &dump_time_ns); + errcode = hctx->iface->dump_request(accum->backend, &dump_time_ns); dump_requested = true; } else { - dump_time_ns = hctx->iface->timestamp_ns( - accum->backend); + dump_time_ns = hctx->iface->timestamp_ns(accum->backend); errcode = hctx->iface->dump_clear(accum->backend); } @@ -457,8 +436,7 @@ static int kbasep_hwcnt_accumulator_dump( /* Copy any accumulation into the dest buffer */ if (accum->accumulated && dump_buf) { - kbase_hwcnt_dump_buffer_copy( - dump_buf, &accum->accum_buf, cur_map); + kbase_hwcnt_dump_buffer_copy(dump_buf, &accum->accum_buf, cur_map); dump_written = true; } @@ -483,8 +461,7 @@ static int kbasep_hwcnt_accumulator_dump( * we're already enabled and holding accum_lock is impossible. */ if (new_map_any_enabled) { - errcode = hctx->iface->dump_enable( - accum->backend, new_map); + errcode = hctx->iface->dump_enable(accum->backend, new_map); if (errcode) goto error; } @@ -495,11 +472,8 @@ static int kbasep_hwcnt_accumulator_dump( /* If we dumped, copy or accumulate it into the destination */ if (dump_requested) { WARN_ON(state != ACCUM_STATE_ENABLED); - errcode = hctx->iface->dump_get( - accum->backend, - dump_buf, - cur_map, - dump_written); + errcode = hctx->iface->dump_get(accum->backend, dump_buf, cur_map, + dump_written); if (errcode) goto error; dump_written = true; @@ -540,8 +514,7 @@ error: * @hctx: Non-NULL pointer to hardware counter context. * @accumulate: True if we should accumulate before disabling, else false. */ -static void kbasep_hwcnt_context_disable( - struct kbase_hwcnt_context *hctx, bool accumulate) +static void kbasep_hwcnt_context_disable(struct kbase_hwcnt_context *hctx, bool accumulate) { unsigned long flags; @@ -563,9 +536,8 @@ static void kbasep_hwcnt_context_disable( } } -int kbase_hwcnt_accumulator_acquire( - struct kbase_hwcnt_context *hctx, - struct kbase_hwcnt_accumulator **accum) +int kbase_hwcnt_accumulator_acquire(struct kbase_hwcnt_context *hctx, + struct kbase_hwcnt_accumulator **accum) { int errcode = 0; unsigned long flags; @@ -618,9 +590,7 @@ int kbase_hwcnt_accumulator_acquire( * Regardless of initial state, counters don't need to be enabled via * the backend, as the initial enable map has no enabled counters. */ - hctx->accum.state = (hctx->disable_count == 0) ? - ACCUM_STATE_ENABLED : - ACCUM_STATE_DISABLED; + hctx->accum.state = (hctx->disable_count == 0) ? ACCUM_STATE_ENABLED : ACCUM_STATE_DISABLED; spin_unlock_irqrestore(&hctx->state_lock, flags); @@ -728,8 +698,7 @@ void kbase_hwcnt_context_enable(struct kbase_hwcnt_context *hctx) spin_unlock_irqrestore(&hctx->state_lock, flags); } -const struct kbase_hwcnt_metadata *kbase_hwcnt_context_metadata( - struct kbase_hwcnt_context *hctx) +const struct kbase_hwcnt_metadata *kbase_hwcnt_context_metadata(struct kbase_hwcnt_context *hctx) { if (!hctx) return NULL; @@ -737,8 +706,7 @@ const struct kbase_hwcnt_metadata *kbase_hwcnt_context_metadata( return hctx->iface->metadata(hctx->iface->info); } -bool kbase_hwcnt_context_queue_work(struct kbase_hwcnt_context *hctx, - struct work_struct *work) +bool kbase_hwcnt_context_queue_work(struct kbase_hwcnt_context *hctx, struct work_struct *work) { if (WARN_ON(!hctx) || WARN_ON(!work)) return false; @@ -746,12 +714,10 @@ bool kbase_hwcnt_context_queue_work(struct kbase_hwcnt_context *hctx, return queue_work(hctx->wq, work); } -int kbase_hwcnt_accumulator_set_counters( - struct kbase_hwcnt_accumulator *accum, - const struct kbase_hwcnt_enable_map *new_map, - u64 *ts_start_ns, - u64 *ts_end_ns, - struct kbase_hwcnt_dump_buffer *dump_buf) +int kbase_hwcnt_accumulator_set_counters(struct kbase_hwcnt_accumulator *accum, + const struct kbase_hwcnt_enable_map *new_map, + u64 *ts_start_ns, u64 *ts_end_ns, + struct kbase_hwcnt_dump_buffer *dump_buf) { int errcode; struct kbase_hwcnt_context *hctx; @@ -767,19 +733,15 @@ int kbase_hwcnt_accumulator_set_counters( mutex_lock(&hctx->accum_lock); - errcode = kbasep_hwcnt_accumulator_dump( - hctx, ts_start_ns, ts_end_ns, dump_buf, new_map); + errcode = kbasep_hwcnt_accumulator_dump(hctx, ts_start_ns, ts_end_ns, dump_buf, new_map); mutex_unlock(&hctx->accum_lock); return errcode; } -int kbase_hwcnt_accumulator_dump( - struct kbase_hwcnt_accumulator *accum, - u64 *ts_start_ns, - u64 *ts_end_ns, - struct kbase_hwcnt_dump_buffer *dump_buf) +int kbase_hwcnt_accumulator_dump(struct kbase_hwcnt_accumulator *accum, u64 *ts_start_ns, + u64 *ts_end_ns, struct kbase_hwcnt_dump_buffer *dump_buf) { int errcode; struct kbase_hwcnt_context *hctx; @@ -794,8 +756,7 @@ int kbase_hwcnt_accumulator_dump( mutex_lock(&hctx->accum_lock); - errcode = kbasep_hwcnt_accumulator_dump( - hctx, ts_start_ns, ts_end_ns, dump_buf, NULL); + errcode = kbasep_hwcnt_accumulator_dump(hctx, ts_start_ns, ts_end_ns, dump_buf, NULL); mutex_unlock(&hctx->accum_lock); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_accumulator.h b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_accumulator.h similarity index 90% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_accumulator.h rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_accumulator.h index af542ea5b56b..069e02068902 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_accumulator.h +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_accumulator.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2018, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 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 @@ -67,9 +67,8 @@ struct kbase_hwcnt_dump_buffer; * * Return: 0 on success or error code. */ -int kbase_hwcnt_accumulator_acquire( - struct kbase_hwcnt_context *hctx, - struct kbase_hwcnt_accumulator **accum); +int kbase_hwcnt_accumulator_acquire(struct kbase_hwcnt_context *hctx, + struct kbase_hwcnt_accumulator **accum); /** * kbase_hwcnt_accumulator_release() - Release a hardware counter accumulator. @@ -102,12 +101,10 @@ void kbase_hwcnt_accumulator_release(struct kbase_hwcnt_accumulator *accum); * * Return: 0 on success or error code. */ -int kbase_hwcnt_accumulator_set_counters( - struct kbase_hwcnt_accumulator *accum, - const struct kbase_hwcnt_enable_map *new_map, - u64 *ts_start_ns, - u64 *ts_end_ns, - struct kbase_hwcnt_dump_buffer *dump_buf); +int kbase_hwcnt_accumulator_set_counters(struct kbase_hwcnt_accumulator *accum, + const struct kbase_hwcnt_enable_map *new_map, + u64 *ts_start_ns, u64 *ts_end_ns, + struct kbase_hwcnt_dump_buffer *dump_buf); /** * kbase_hwcnt_accumulator_dump() - Perform a dump of the currently enabled @@ -127,11 +124,8 @@ int kbase_hwcnt_accumulator_set_counters( * * Return: 0 on success or error code. */ -int kbase_hwcnt_accumulator_dump( - struct kbase_hwcnt_accumulator *accum, - u64 *ts_start_ns, - u64 *ts_end_ns, - struct kbase_hwcnt_dump_buffer *dump_buf); +int kbase_hwcnt_accumulator_dump(struct kbase_hwcnt_accumulator *accum, u64 *ts_start_ns, + u64 *ts_end_ns, struct kbase_hwcnt_dump_buffer *dump_buf); /** * kbase_hwcnt_accumulator_timestamp_ns() - Get the current accumulator backend diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_context.h b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_context.h similarity index 95% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_context.h rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_context.h index 34423d1b60c7..89732a908789 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_context.h +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_context.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2018, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 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 @@ -43,9 +43,8 @@ struct kbase_hwcnt_context; * * Return: 0 on success, else error code. */ -int kbase_hwcnt_context_init( - const struct kbase_hwcnt_backend_interface *iface, - struct kbase_hwcnt_context **out_hctx); +int kbase_hwcnt_context_init(const struct kbase_hwcnt_backend_interface *iface, + struct kbase_hwcnt_context **out_hctx); /** * kbase_hwcnt_context_term() - Terminate a hardware counter context. @@ -61,8 +60,7 @@ void kbase_hwcnt_context_term(struct kbase_hwcnt_context *hctx); * * Return: Non-NULL pointer to metadata, or NULL on error. */ -const struct kbase_hwcnt_metadata *kbase_hwcnt_context_metadata( - struct kbase_hwcnt_context *hctx); +const struct kbase_hwcnt_metadata *kbase_hwcnt_context_metadata(struct kbase_hwcnt_context *hctx); /** * kbase_hwcnt_context_disable() - Increment the disable count of the context. @@ -145,7 +143,6 @@ void kbase_hwcnt_context_enable(struct kbase_hwcnt_context *hctx); * this meant progress through the power management states could be stalled * for however long that higher priority thread took. */ -bool kbase_hwcnt_context_queue_work(struct kbase_hwcnt_context *hctx, - struct work_struct *work); +bool kbase_hwcnt_context_queue_work(struct kbase_hwcnt_context *hctx, struct work_struct *work); #endif /* _KBASE_HWCNT_CONTEXT_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu.c b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu.c similarity index 78% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu.c rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu.c index 5f5c36f33d41..74916dab060d 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu.c +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu.c @@ -19,8 +19,8 @@ * */ -#include "mali_kbase_hwcnt_gpu.h" -#include "mali_kbase_hwcnt_types.h" +#include "hwcnt/mali_kbase_hwcnt_gpu.h" +#include "hwcnt/mali_kbase_hwcnt_types.h" #include @@ -32,8 +32,7 @@ enum enable_map_idx { EM_COUNT, }; -static void kbasep_get_fe_block_type(u64 *dst, enum kbase_hwcnt_set counter_set, - bool is_csf) +static void kbasep_get_fe_block_type(u64 *dst, enum kbase_hwcnt_set counter_set, bool is_csf) { switch (counter_set) { case KBASE_HWCNT_SET_PRIMARY: @@ -56,8 +55,7 @@ static void kbasep_get_fe_block_type(u64 *dst, enum kbase_hwcnt_set counter_set, } } -static void kbasep_get_tiler_block_type(u64 *dst, - enum kbase_hwcnt_set counter_set) +static void kbasep_get_tiler_block_type(u64 *dst, enum kbase_hwcnt_set counter_set) { switch (counter_set) { case KBASE_HWCNT_SET_PRIMARY: @@ -72,8 +70,7 @@ static void kbasep_get_tiler_block_type(u64 *dst, } } -static void kbasep_get_sc_block_type(u64 *dst, enum kbase_hwcnt_set counter_set, - bool is_csf) +static void kbasep_get_sc_block_type(u64 *dst, enum kbase_hwcnt_set counter_set, bool is_csf) { switch (counter_set) { case KBASE_HWCNT_SET_PRIMARY: @@ -93,8 +90,7 @@ static void kbasep_get_sc_block_type(u64 *dst, enum kbase_hwcnt_set counter_set, } } -static void kbasep_get_memsys_block_type(u64 *dst, - enum kbase_hwcnt_set counter_set) +static void kbasep_get_memsys_block_type(u64 *dst, enum kbase_hwcnt_set counter_set) { switch (counter_set) { case KBASE_HWCNT_SET_PRIMARY: @@ -122,15 +118,14 @@ static void kbasep_get_memsys_block_type(u64 *dst, * * Return: 0 on success, else error code. */ -static int kbasep_hwcnt_backend_gpu_metadata_create( - const struct kbase_hwcnt_gpu_info *gpu_info, const bool is_csf, - enum kbase_hwcnt_set counter_set, - const struct kbase_hwcnt_metadata **metadata) +static int kbasep_hwcnt_backend_gpu_metadata_create(const struct kbase_hwcnt_gpu_info *gpu_info, + const bool is_csf, + enum kbase_hwcnt_set counter_set, + const struct kbase_hwcnt_metadata **metadata) { struct kbase_hwcnt_description desc; struct kbase_hwcnt_group_description group; - struct kbase_hwcnt_block_description - blks[KBASE_HWCNT_V5_BLOCK_TYPE_COUNT]; + struct kbase_hwcnt_block_description blks[KBASE_HWCNT_V5_BLOCK_TYPE_COUNT]; size_t non_sc_block_count; size_t sc_block_count; @@ -156,22 +151,19 @@ static int kbasep_hwcnt_backend_gpu_metadata_create( kbasep_get_fe_block_type(&blks[0].type, counter_set, is_csf); blks[0].inst_cnt = 1; blks[0].hdr_cnt = KBASE_HWCNT_V5_HEADERS_PER_BLOCK; - blks[0].ctr_cnt = gpu_info->prfcnt_values_per_block - - KBASE_HWCNT_V5_HEADERS_PER_BLOCK; + blks[0].ctr_cnt = gpu_info->prfcnt_values_per_block - KBASE_HWCNT_V5_HEADERS_PER_BLOCK; /* One Tiler block */ kbasep_get_tiler_block_type(&blks[1].type, counter_set); blks[1].inst_cnt = 1; blks[1].hdr_cnt = KBASE_HWCNT_V5_HEADERS_PER_BLOCK; - blks[1].ctr_cnt = gpu_info->prfcnt_values_per_block - - KBASE_HWCNT_V5_HEADERS_PER_BLOCK; + blks[1].ctr_cnt = gpu_info->prfcnt_values_per_block - KBASE_HWCNT_V5_HEADERS_PER_BLOCK; /* l2_count memsys blks */ kbasep_get_memsys_block_type(&blks[2].type, counter_set); blks[2].inst_cnt = gpu_info->l2_count; blks[2].hdr_cnt = KBASE_HWCNT_V5_HEADERS_PER_BLOCK; - blks[2].ctr_cnt = gpu_info->prfcnt_values_per_block - - KBASE_HWCNT_V5_HEADERS_PER_BLOCK; + blks[2].ctr_cnt = gpu_info->prfcnt_values_per_block - KBASE_HWCNT_V5_HEADERS_PER_BLOCK; /* * There are as many shader cores in the system as there are bits set in @@ -192,8 +184,7 @@ static int kbasep_hwcnt_backend_gpu_metadata_create( kbasep_get_sc_block_type(&blks[3].type, counter_set, is_csf); blks[3].inst_cnt = sc_block_count; blks[3].hdr_cnt = KBASE_HWCNT_V5_HEADERS_PER_BLOCK; - blks[3].ctr_cnt = gpu_info->prfcnt_values_per_block - - KBASE_HWCNT_V5_HEADERS_PER_BLOCK; + blks[3].ctr_cnt = gpu_info->prfcnt_values_per_block - KBASE_HWCNT_V5_HEADERS_PER_BLOCK; WARN_ON(KBASE_HWCNT_V5_BLOCK_TYPE_COUNT != 4); @@ -220,8 +211,7 @@ static int kbasep_hwcnt_backend_gpu_metadata_create( * * Return: Size of buffer the GPU needs to perform a counter dump. */ -static size_t -kbasep_hwcnt_backend_jm_dump_bytes(const struct kbase_hwcnt_gpu_info *gpu_info) +static size_t kbasep_hwcnt_backend_jm_dump_bytes(const struct kbase_hwcnt_gpu_info *gpu_info) { WARN_ON(!gpu_info); @@ -229,11 +219,10 @@ kbasep_hwcnt_backend_jm_dump_bytes(const struct kbase_hwcnt_gpu_info *gpu_info) gpu_info->prfcnt_values_per_block * KBASE_HWCNT_VALUE_HW_BYTES; } -int kbase_hwcnt_jm_metadata_create( - const struct kbase_hwcnt_gpu_info *gpu_info, - enum kbase_hwcnt_set counter_set, - const struct kbase_hwcnt_metadata **out_metadata, - size_t *out_dump_bytes) +int kbase_hwcnt_jm_metadata_create(const struct kbase_hwcnt_gpu_info *gpu_info, + enum kbase_hwcnt_set counter_set, + const struct kbase_hwcnt_metadata **out_metadata, + size_t *out_dump_bytes) { int errcode; const struct kbase_hwcnt_metadata *metadata; @@ -250,8 +239,7 @@ int kbase_hwcnt_jm_metadata_create( * all the available L2 cache and Shader cores are allocated. */ dump_bytes = kbasep_hwcnt_backend_jm_dump_bytes(gpu_info); - errcode = kbasep_hwcnt_backend_gpu_metadata_create( - gpu_info, false, counter_set, &metadata); + errcode = kbasep_hwcnt_backend_gpu_metadata_create(gpu_info, false, counter_set, &metadata); if (errcode) return errcode; @@ -276,10 +264,9 @@ void kbase_hwcnt_jm_metadata_destroy(const struct kbase_hwcnt_metadata *metadata kbase_hwcnt_metadata_destroy(metadata); } -int kbase_hwcnt_csf_metadata_create( - const struct kbase_hwcnt_gpu_info *gpu_info, - enum kbase_hwcnt_set counter_set, - const struct kbase_hwcnt_metadata **out_metadata) +int kbase_hwcnt_csf_metadata_create(const struct kbase_hwcnt_gpu_info *gpu_info, + enum kbase_hwcnt_set counter_set, + const struct kbase_hwcnt_metadata **out_metadata) { int errcode; const struct kbase_hwcnt_metadata *metadata; @@ -287,8 +274,7 @@ int kbase_hwcnt_csf_metadata_create( if (!gpu_info || !out_metadata) return -EINVAL; - errcode = kbasep_hwcnt_backend_gpu_metadata_create( - gpu_info, true, counter_set, &metadata); + errcode = kbasep_hwcnt_backend_gpu_metadata_create(gpu_info, true, counter_set, &metadata); if (errcode) return errcode; @@ -297,8 +283,7 @@ int kbase_hwcnt_csf_metadata_create( return 0; } -void kbase_hwcnt_csf_metadata_destroy( - const struct kbase_hwcnt_metadata *metadata) +void kbase_hwcnt_csf_metadata_destroy(const struct kbase_hwcnt_metadata *metadata) { if (!metadata) return; @@ -306,10 +291,7 @@ void kbase_hwcnt_csf_metadata_destroy( kbase_hwcnt_metadata_destroy(metadata); } -static bool is_block_type_shader( - const u64 grp_type, - const u64 blk_type, - const size_t blk) +static bool is_block_type_shader(const u64 grp_type, const u64 blk_type, const size_t blk) { bool is_shader = false; @@ -326,9 +308,7 @@ static bool is_block_type_shader( return is_shader; } -static bool is_block_type_l2_cache( - const u64 grp_type, - const u64 blk_type) +static bool is_block_type_l2_cache(const u64 grp_type, const u64 blk_type) { bool is_l2_cache = false; @@ -348,10 +328,8 @@ static bool is_block_type_l2_cache( } int kbase_hwcnt_jm_dump_get(struct kbase_hwcnt_dump_buffer *dst, u64 *src, - const struct kbase_hwcnt_enable_map *dst_enable_map, - u64 pm_core_mask, - const struct kbase_hwcnt_curr_config *curr_config, - bool accumulate) + const struct kbase_hwcnt_enable_map *dst_enable_map, u64 pm_core_mask, + const struct kbase_hwcnt_curr_config *curr_config, bool accumulate) { const struct kbase_hwcnt_metadata *metadata; size_t grp, blk, blk_inst; @@ -362,28 +340,21 @@ int kbase_hwcnt_jm_dump_get(struct kbase_hwcnt_dump_buffer *dst, u64 *src, /* Variables to deal with the current configuration */ int l2_count = 0; - if (!dst || !src || !dst_enable_map || - (dst_enable_map->metadata != dst->metadata)) + if (!dst || !src || !dst_enable_map || (dst_enable_map->metadata != dst->metadata)) return -EINVAL; metadata = dst->metadata; - kbase_hwcnt_metadata_for_each_block( - metadata, grp, blk, blk_inst) { - const size_t hdr_cnt = - kbase_hwcnt_metadata_block_headers_count( - metadata, grp, blk); + kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) + { + const size_t hdr_cnt = kbase_hwcnt_metadata_block_headers_count(metadata, grp, blk); const size_t ctr_cnt = - kbase_hwcnt_metadata_block_counters_count( - metadata, grp, blk); - const u64 blk_type = kbase_hwcnt_metadata_block_type( - metadata, grp, blk); + kbase_hwcnt_metadata_block_counters_count(metadata, grp, blk); + const u64 blk_type = kbase_hwcnt_metadata_block_type(metadata, grp, blk); const bool is_shader_core = is_block_type_shader( - kbase_hwcnt_metadata_group_type(metadata, grp), - blk_type, blk); + kbase_hwcnt_metadata_group_type(metadata, grp), blk_type, blk); const bool is_l2_cache = is_block_type_l2_cache( - kbase_hwcnt_metadata_group_type(metadata, grp), - blk_type); + kbase_hwcnt_metadata_group_type(metadata, grp), blk_type); const bool is_undefined = kbase_hwcnt_is_block_type_undefined( kbase_hwcnt_metadata_group_type(metadata, grp), blk_type); bool hw_res_available = true; @@ -412,10 +383,9 @@ int kbase_hwcnt_jm_dump_get(struct kbase_hwcnt_dump_buffer *dst, u64 *src, /* * Skip block if no values in the destination block are enabled. */ - if (kbase_hwcnt_enable_map_block_enabled( - dst_enable_map, grp, blk, blk_inst)) { - u64 *dst_blk = kbase_hwcnt_dump_buffer_block_instance( - dst, grp, blk, blk_inst); + if (kbase_hwcnt_enable_map_block_enabled(dst_enable_map, grp, blk, blk_inst)) { + u64 *dst_blk = + kbase_hwcnt_dump_buffer_block_instance(dst, grp, blk, blk_inst); const u64 *src_blk = dump_src + src_offset; bool blk_powered; @@ -435,13 +405,11 @@ int kbase_hwcnt_jm_dump_get(struct kbase_hwcnt_dump_buffer *dst, u64 *src, if (blk_powered && !is_undefined && hw_res_available) { /* Only powered and defined blocks have valid data. */ if (accumulate) { - kbase_hwcnt_dump_buffer_block_accumulate( - dst_blk, src_blk, hdr_cnt, - ctr_cnt); + kbase_hwcnt_dump_buffer_block_accumulate(dst_blk, src_blk, + hdr_cnt, ctr_cnt); } else { - kbase_hwcnt_dump_buffer_block_copy( - dst_blk, src_blk, - (hdr_cnt + ctr_cnt)); + kbase_hwcnt_dump_buffer_block_copy(dst_blk, src_blk, + (hdr_cnt + ctr_cnt)); } } else { /* Even though the block might be undefined, the @@ -469,26 +437,23 @@ int kbase_hwcnt_jm_dump_get(struct kbase_hwcnt_dump_buffer *dst, u64 *src, } int kbase_hwcnt_csf_dump_get(struct kbase_hwcnt_dump_buffer *dst, u64 *src, - const struct kbase_hwcnt_enable_map *dst_enable_map, - bool accumulate) + const struct kbase_hwcnt_enable_map *dst_enable_map, bool accumulate) { const struct kbase_hwcnt_metadata *metadata; const u64 *dump_src = src; size_t src_offset = 0; size_t grp, blk, blk_inst; - if (!dst || !src || !dst_enable_map || - (dst_enable_map->metadata != dst->metadata)) + if (!dst || !src || !dst_enable_map || (dst_enable_map->metadata != dst->metadata)) return -EINVAL; metadata = dst->metadata; - kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) { - const size_t hdr_cnt = kbase_hwcnt_metadata_block_headers_count( - metadata, grp, blk); + kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) + { + const size_t hdr_cnt = kbase_hwcnt_metadata_block_headers_count(metadata, grp, blk); const size_t ctr_cnt = - kbase_hwcnt_metadata_block_counters_count(metadata, grp, - blk); + kbase_hwcnt_metadata_block_counters_count(metadata, grp, blk); const uint64_t blk_type = kbase_hwcnt_metadata_block_type(metadata, grp, blk); const bool is_undefined = kbase_hwcnt_is_block_type_undefined( kbase_hwcnt_metadata_group_type(metadata, grp), blk_type); @@ -496,10 +461,9 @@ int kbase_hwcnt_csf_dump_get(struct kbase_hwcnt_dump_buffer *dst, u64 *src, /* * Skip block if no values in the destination block are enabled. */ - if (kbase_hwcnt_enable_map_block_enabled(dst_enable_map, grp, - blk, blk_inst)) { - u64 *dst_blk = kbase_hwcnt_dump_buffer_block_instance( - dst, grp, blk, blk_inst); + if (kbase_hwcnt_enable_map_block_enabled(dst_enable_map, grp, blk, blk_inst)) { + u64 *dst_blk = + kbase_hwcnt_dump_buffer_block_instance(dst, grp, blk, blk_inst); const u64 *src_blk = dump_src + src_offset; if (!is_undefined) { @@ -542,12 +506,9 @@ int kbase_hwcnt_csf_dump_get(struct kbase_hwcnt_dump_buffer *dst, u64 *src, * @hi: Non-NULL pointer to where high 64 bits of block enable map abstraction * will be stored. */ -static inline void kbasep_hwcnt_backend_gpu_block_map_from_physical( - u32 phys, - u64 *lo, - u64 *hi) +static inline void kbasep_hwcnt_backend_gpu_block_map_from_physical(u32 phys, u64 *lo, u64 *hi) { - u64 dwords[2] = {0, 0}; + u64 dwords[2] = { 0, 0 }; size_t dword_idx; @@ -572,9 +533,8 @@ static inline void kbasep_hwcnt_backend_gpu_block_map_from_physical( *hi = dwords[1]; } -void kbase_hwcnt_gpu_enable_map_to_physical( - struct kbase_hwcnt_physical_enable_map *dst, - const struct kbase_hwcnt_enable_map *src) +void kbase_hwcnt_gpu_enable_map_to_physical(struct kbase_hwcnt_physical_enable_map *dst, + const struct kbase_hwcnt_enable_map *src) { const struct kbase_hwcnt_metadata *metadata; u64 fe_bm[EM_COUNT] = { 0 }; @@ -588,17 +548,13 @@ void kbase_hwcnt_gpu_enable_map_to_physical( metadata = src->metadata; - kbase_hwcnt_metadata_for_each_block( - metadata, grp, blk, blk_inst) { - const u64 grp_type = kbase_hwcnt_metadata_group_type( - metadata, grp); - const u64 blk_type = kbase_hwcnt_metadata_block_type( - metadata, grp, blk); - const u64 *blk_map = kbase_hwcnt_enable_map_block_instance( - src, grp, blk, blk_inst); + kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) + { + const u64 grp_type = kbase_hwcnt_metadata_group_type(metadata, grp); + const u64 blk_type = kbase_hwcnt_metadata_block_type(metadata, grp, blk); + const u64 *blk_map = kbase_hwcnt_enable_map_block_instance(src, grp, blk, blk_inst); - if ((enum kbase_hwcnt_gpu_group_type)grp_type == - KBASE_HWCNT_GPU_GROUP_TYPE_V5) { + if ((enum kbase_hwcnt_gpu_group_type)grp_type == KBASE_HWCNT_GPU_GROUP_TYPE_V5) { const size_t map_stride = kbase_hwcnt_metadata_block_enable_map_stride(metadata, grp, blk); size_t map_idx; @@ -649,8 +605,7 @@ void kbase_hwcnt_gpu_enable_map_to_physical( kbase_hwcnt_backend_gpu_block_map_to_physical(mmu_l2_bm[EM_LO], mmu_l2_bm[EM_HI]); } -void kbase_hwcnt_gpu_set_to_physical(enum kbase_hwcnt_physical_set *dst, - enum kbase_hwcnt_set src) +void kbase_hwcnt_gpu_set_to_physical(enum kbase_hwcnt_physical_set *dst, enum kbase_hwcnt_set src) { switch (src) { case KBASE_HWCNT_SET_PRIMARY: @@ -667,9 +622,8 @@ void kbase_hwcnt_gpu_set_to_physical(enum kbase_hwcnt_physical_set *dst, } } -void kbase_hwcnt_gpu_enable_map_from_physical( - struct kbase_hwcnt_enable_map *dst, - const struct kbase_hwcnt_physical_enable_map *src) +void kbase_hwcnt_gpu_enable_map_from_physical(struct kbase_hwcnt_enable_map *dst, + const struct kbase_hwcnt_physical_enable_map *src) { const struct kbase_hwcnt_metadata *metadata; @@ -692,16 +646,13 @@ void kbase_hwcnt_gpu_enable_map_from_physical( kbasep_hwcnt_backend_gpu_block_map_from_physical(src->mmu_l2_bm, &mmu_l2_bm[EM_LO], &mmu_l2_bm[EM_HI]); - kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) { - const u64 grp_type = kbase_hwcnt_metadata_group_type( - metadata, grp); - const u64 blk_type = kbase_hwcnt_metadata_block_type( - metadata, grp, blk); - u64 *blk_map = kbase_hwcnt_enable_map_block_instance( - dst, grp, blk, blk_inst); + kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) + { + const u64 grp_type = kbase_hwcnt_metadata_group_type(metadata, grp); + const u64 blk_type = kbase_hwcnt_metadata_block_type(metadata, grp, blk); + u64 *blk_map = kbase_hwcnt_enable_map_block_instance(dst, grp, blk, blk_inst); - if ((enum kbase_hwcnt_gpu_group_type)grp_type == - KBASE_HWCNT_GPU_GROUP_TYPE_V5) { + if ((enum kbase_hwcnt_gpu_group_type)grp_type == KBASE_HWCNT_GPU_GROUP_TYPE_V5) { const size_t map_stride = kbase_hwcnt_metadata_block_enable_map_stride(metadata, grp, blk); size_t map_idx; @@ -744,29 +695,25 @@ void kbase_hwcnt_gpu_enable_map_from_physical( } } -void kbase_hwcnt_gpu_patch_dump_headers( - struct kbase_hwcnt_dump_buffer *buf, - const struct kbase_hwcnt_enable_map *enable_map) +void kbase_hwcnt_gpu_patch_dump_headers(struct kbase_hwcnt_dump_buffer *buf, + const struct kbase_hwcnt_enable_map *enable_map) { const struct kbase_hwcnt_metadata *metadata; size_t grp, blk, blk_inst; - if (WARN_ON(!buf) || WARN_ON(!enable_map) || - WARN_ON(buf->metadata != enable_map->metadata)) + if (WARN_ON(!buf) || WARN_ON(!enable_map) || WARN_ON(buf->metadata != enable_map->metadata)) return; metadata = buf->metadata; - kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) { - const u64 grp_type = - kbase_hwcnt_metadata_group_type(metadata, grp); - u64 *buf_blk = kbase_hwcnt_dump_buffer_block_instance( - buf, grp, blk, blk_inst); - const u64 *blk_map = kbase_hwcnt_enable_map_block_instance( - enable_map, grp, blk, blk_inst); + kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) + { + const u64 grp_type = kbase_hwcnt_metadata_group_type(metadata, grp); + u64 *buf_blk = kbase_hwcnt_dump_buffer_block_instance(buf, grp, blk, blk_inst); + const u64 *blk_map = + kbase_hwcnt_enable_map_block_instance(enable_map, grp, blk, blk_inst); - if ((enum kbase_hwcnt_gpu_group_type)grp_type == - KBASE_HWCNT_GPU_GROUP_TYPE_V5) { + if ((enum kbase_hwcnt_gpu_group_type)grp_type == KBASE_HWCNT_GPU_GROUP_TYPE_V5) { const size_t map_stride = kbase_hwcnt_metadata_block_enable_map_stride(metadata, grp, blk); u64 prfcnt_bm[EM_COUNT] = { 0 }; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu.h b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu.h similarity index 92% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu.h rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu.h index f890d451c2c1..a49c31e52f98 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu.h +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu.h @@ -34,9 +34,8 @@ struct kbase_hwcnt_dump_buffer; #define KBASE_HWCNT_V5_BLOCK_TYPE_COUNT 4 #define KBASE_HWCNT_V5_HEADERS_PER_BLOCK 4 #define KBASE_HWCNT_V5_DEFAULT_COUNTERS_PER_BLOCK 60 -#define KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK \ - (KBASE_HWCNT_V5_HEADERS_PER_BLOCK + \ - KBASE_HWCNT_V5_DEFAULT_COUNTERS_PER_BLOCK) +#define KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK \ + (KBASE_HWCNT_V5_HEADERS_PER_BLOCK + KBASE_HWCNT_V5_DEFAULT_COUNTERS_PER_BLOCK) /* FrontEnd block count in V5 GPU hardware counter. */ #define KBASE_HWCNT_V5_FE_BLOCK_COUNT 1 @@ -228,19 +227,17 @@ static inline bool kbase_hwcnt_is_block_type_undefined(const uint64_t grp_type, * * Return: 0 on success, else error code. */ -int kbase_hwcnt_jm_metadata_create( - const struct kbase_hwcnt_gpu_info *info, - enum kbase_hwcnt_set counter_set, - const struct kbase_hwcnt_metadata **out_metadata, - size_t *out_dump_bytes); +int kbase_hwcnt_jm_metadata_create(const struct kbase_hwcnt_gpu_info *info, + enum kbase_hwcnt_set counter_set, + const struct kbase_hwcnt_metadata **out_metadata, + size_t *out_dump_bytes); /** * kbase_hwcnt_jm_metadata_destroy() - Destroy JM GPU hardware counter metadata. * * @metadata: Pointer to metadata to destroy. */ -void kbase_hwcnt_jm_metadata_destroy( - const struct kbase_hwcnt_metadata *metadata); +void kbase_hwcnt_jm_metadata_destroy(const struct kbase_hwcnt_metadata *metadata); /** * kbase_hwcnt_csf_metadata_create() - Create hardware counter metadata for the @@ -252,18 +249,16 @@ void kbase_hwcnt_jm_metadata_destroy( * * Return: 0 on success, else error code. */ -int kbase_hwcnt_csf_metadata_create( - const struct kbase_hwcnt_gpu_info *info, - enum kbase_hwcnt_set counter_set, - const struct kbase_hwcnt_metadata **out_metadata); +int kbase_hwcnt_csf_metadata_create(const struct kbase_hwcnt_gpu_info *info, + enum kbase_hwcnt_set counter_set, + const struct kbase_hwcnt_metadata **out_metadata); /** * kbase_hwcnt_csf_metadata_destroy() - Destroy CSF GPU hardware counter * metadata. * @metadata: Pointer to metadata to destroy. */ -void kbase_hwcnt_csf_metadata_destroy( - const struct kbase_hwcnt_metadata *metadata); +void kbase_hwcnt_csf_metadata_destroy(const struct kbase_hwcnt_metadata *metadata); /** * kbase_hwcnt_jm_dump_get() - Copy or accumulate enabled counters from the raw @@ -289,8 +284,7 @@ void kbase_hwcnt_csf_metadata_destroy( int kbase_hwcnt_jm_dump_get(struct kbase_hwcnt_dump_buffer *dst, u64 *src, const struct kbase_hwcnt_enable_map *dst_enable_map, const u64 pm_core_mask, - const struct kbase_hwcnt_curr_config *curr_config, - bool accumulate); + const struct kbase_hwcnt_curr_config *curr_config, bool accumulate); /** * kbase_hwcnt_csf_dump_get() - Copy or accumulate enabled counters from the raw @@ -310,8 +304,7 @@ int kbase_hwcnt_jm_dump_get(struct kbase_hwcnt_dump_buffer *dst, u64 *src, * Return: 0 on success, else error code. */ int kbase_hwcnt_csf_dump_get(struct kbase_hwcnt_dump_buffer *dst, u64 *src, - const struct kbase_hwcnt_enable_map *dst_enable_map, - bool accumulate); + const struct kbase_hwcnt_enable_map *dst_enable_map, bool accumulate); /** * kbase_hwcnt_backend_gpu_block_map_to_physical() - Convert from a block @@ -365,9 +358,8 @@ static inline u32 kbase_hwcnt_backend_gpu_block_map_to_physical(u64 lo, u64 hi) * individual counter block value, but the physical enable map uses 1 bit for * every 4 counters, shared over all instances of a block. */ -void kbase_hwcnt_gpu_enable_map_to_physical( - struct kbase_hwcnt_physical_enable_map *dst, - const struct kbase_hwcnt_enable_map *src); +void kbase_hwcnt_gpu_enable_map_to_physical(struct kbase_hwcnt_physical_enable_map *dst, + const struct kbase_hwcnt_enable_map *src); /** * kbase_hwcnt_gpu_set_to_physical() - Map counter set selection to physical @@ -376,8 +368,7 @@ void kbase_hwcnt_gpu_enable_map_to_physical( * @dst: Non-NULL pointer to destination physical SET_SELECT value. * @src: Non-NULL pointer to source counter set selection. */ -void kbase_hwcnt_gpu_set_to_physical(enum kbase_hwcnt_physical_set *dst, - enum kbase_hwcnt_set src); +void kbase_hwcnt_gpu_set_to_physical(enum kbase_hwcnt_physical_set *dst, enum kbase_hwcnt_set src); /** * kbase_hwcnt_gpu_enable_map_from_physical() - Convert a physical enable map to @@ -393,9 +384,8 @@ void kbase_hwcnt_gpu_set_to_physical(enum kbase_hwcnt_physical_set *dst, * more than 64, so the enable map abstraction has nowhere to store the enable * information for the 64 non-existent counters. */ -void kbase_hwcnt_gpu_enable_map_from_physical( - struct kbase_hwcnt_enable_map *dst, - const struct kbase_hwcnt_physical_enable_map *src); +void kbase_hwcnt_gpu_enable_map_from_physical(struct kbase_hwcnt_enable_map *dst, + const struct kbase_hwcnt_physical_enable_map *src); /** * kbase_hwcnt_gpu_patch_dump_headers() - Patch all the performance counter @@ -411,8 +401,7 @@ void kbase_hwcnt_gpu_enable_map_from_physical( * kernel-user boundary, to ensure the header is accurate for the enable map * used by the user. */ -void kbase_hwcnt_gpu_patch_dump_headers( - struct kbase_hwcnt_dump_buffer *buf, - const struct kbase_hwcnt_enable_map *enable_map); +void kbase_hwcnt_gpu_patch_dump_headers(struct kbase_hwcnt_dump_buffer *buf, + const struct kbase_hwcnt_enable_map *enable_map); #endif /* _KBASE_HWCNT_GPU_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu_narrow.c b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu_narrow.c similarity index 68% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu_narrow.c rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu_narrow.c index 2a1cde79709b..0cf2f94cfb87 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu_narrow.c +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu_narrow.c @@ -19,21 +19,19 @@ * */ -#include "mali_kbase_hwcnt_gpu.h" -#include "mali_kbase_hwcnt_gpu_narrow.h" +#include "hwcnt/mali_kbase_hwcnt_gpu.h" +#include "hwcnt/mali_kbase_hwcnt_gpu_narrow.h" #include #include #include -int kbase_hwcnt_gpu_metadata_narrow_create( - const struct kbase_hwcnt_metadata_narrow **dst_md_narrow, - const struct kbase_hwcnt_metadata *src_md) +int kbase_hwcnt_gpu_metadata_narrow_create(const struct kbase_hwcnt_metadata_narrow **dst_md_narrow, + const struct kbase_hwcnt_metadata *src_md) { struct kbase_hwcnt_description desc; struct kbase_hwcnt_group_description group; - struct kbase_hwcnt_block_description - blks[KBASE_HWCNT_V5_BLOCK_TYPE_COUNT]; + struct kbase_hwcnt_block_description blks[KBASE_HWCNT_V5_BLOCK_TYPE_COUNT]; size_t prfcnt_values_per_block; size_t blk; int err; @@ -47,18 +45,15 @@ int kbase_hwcnt_gpu_metadata_narrow_create( * count in the metadata. */ if ((kbase_hwcnt_metadata_group_count(src_md) != 1) || - (kbase_hwcnt_metadata_block_count(src_md, 0) != - KBASE_HWCNT_V5_BLOCK_TYPE_COUNT)) + (kbase_hwcnt_metadata_block_count(src_md, 0) != KBASE_HWCNT_V5_BLOCK_TYPE_COUNT)) return -EINVAL; /* Get the values count in the first block. */ - prfcnt_values_per_block = - kbase_hwcnt_metadata_block_values_count(src_md, 0, 0); + prfcnt_values_per_block = kbase_hwcnt_metadata_block_values_count(src_md, 0, 0); /* check all blocks should have same values count. */ for (blk = 1; blk < KBASE_HWCNT_V5_BLOCK_TYPE_COUNT; blk++) { - size_t val_cnt = - kbase_hwcnt_metadata_block_values_count(src_md, 0, blk); + size_t val_cnt = kbase_hwcnt_metadata_block_values_count(src_md, 0, blk); if (val_cnt != prfcnt_values_per_block) return -EINVAL; } @@ -75,12 +70,10 @@ int kbase_hwcnt_gpu_metadata_narrow_create( prfcnt_values_per_block = 64; for (blk = 0; blk < KBASE_HWCNT_V5_BLOCK_TYPE_COUNT; blk++) { - size_t blk_hdr_cnt = kbase_hwcnt_metadata_block_headers_count( - src_md, 0, blk); + size_t blk_hdr_cnt = kbase_hwcnt_metadata_block_headers_count(src_md, 0, blk); blks[blk] = (struct kbase_hwcnt_block_description){ .type = kbase_hwcnt_metadata_block_type(src_md, 0, blk), - .inst_cnt = kbase_hwcnt_metadata_block_instance_count( - src_md, 0, blk), + .inst_cnt = kbase_hwcnt_metadata_block_instance_count(src_md, 0, blk), .hdr_cnt = blk_hdr_cnt, .ctr_cnt = prfcnt_values_per_block - blk_hdr_cnt, }; @@ -105,8 +98,7 @@ int kbase_hwcnt_gpu_metadata_narrow_create( * only supports 32-bit but the created metadata uses 64-bit for * block entry. */ - metadata_narrow->dump_buf_bytes = - metadata_narrow->metadata->dump_buf_bytes >> 1; + metadata_narrow->dump_buf_bytes = metadata_narrow->metadata->dump_buf_bytes >> 1; *dst_md_narrow = metadata_narrow; } else { kfree(metadata_narrow); @@ -115,8 +107,7 @@ int kbase_hwcnt_gpu_metadata_narrow_create( return err; } -void kbase_hwcnt_gpu_metadata_narrow_destroy( - const struct kbase_hwcnt_metadata_narrow *md_narrow) +void kbase_hwcnt_gpu_metadata_narrow_destroy(const struct kbase_hwcnt_metadata_narrow *md_narrow) { if (!md_narrow) return; @@ -125,9 +116,8 @@ void kbase_hwcnt_gpu_metadata_narrow_destroy( kfree(md_narrow); } -int kbase_hwcnt_dump_buffer_narrow_alloc( - const struct kbase_hwcnt_metadata_narrow *md_narrow, - struct kbase_hwcnt_dump_buffer_narrow *dump_buf) +int kbase_hwcnt_dump_buffer_narrow_alloc(const struct kbase_hwcnt_metadata_narrow *md_narrow, + struct kbase_hwcnt_dump_buffer_narrow *dump_buf) { size_t dump_buf_bytes; size_t clk_cnt_buf_bytes; @@ -137,8 +127,7 @@ int kbase_hwcnt_dump_buffer_narrow_alloc( return -EINVAL; dump_buf_bytes = md_narrow->dump_buf_bytes; - clk_cnt_buf_bytes = - sizeof(*dump_buf->clk_cnt_buf) * md_narrow->metadata->clk_cnt; + clk_cnt_buf_bytes = sizeof(*dump_buf->clk_cnt_buf) * md_narrow->metadata->clk_cnt; /* Make a single allocation for both dump_buf and clk_cnt_buf. */ buf = kmalloc(dump_buf_bytes + clk_cnt_buf_bytes, GFP_KERNEL); @@ -154,14 +143,15 @@ int kbase_hwcnt_dump_buffer_narrow_alloc( return 0; } -void kbase_hwcnt_dump_buffer_narrow_free( - struct kbase_hwcnt_dump_buffer_narrow *dump_buf_narrow) +void kbase_hwcnt_dump_buffer_narrow_free(struct kbase_hwcnt_dump_buffer_narrow *dump_buf_narrow) { if (!dump_buf_narrow) return; kfree(dump_buf_narrow->dump_buf); - *dump_buf_narrow = (struct kbase_hwcnt_dump_buffer_narrow){ NULL }; + *dump_buf_narrow = (struct kbase_hwcnt_dump_buffer_narrow){ .md_narrow = NULL, + .dump_buf = NULL, + .clk_cnt_buf = NULL }; } int kbase_hwcnt_dump_buffer_narrow_array_alloc( @@ -180,8 +170,7 @@ int kbase_hwcnt_dump_buffer_narrow_array_alloc( return -EINVAL; dump_buf_bytes = md_narrow->dump_buf_bytes; - clk_cnt_buf_bytes = sizeof(*dump_bufs->bufs->clk_cnt_buf) * - md_narrow->metadata->clk_cnt; + clk_cnt_buf_bytes = sizeof(*dump_bufs->bufs->clk_cnt_buf) * md_narrow->metadata->clk_cnt; /* Allocate memory for the dump buffer struct array */ buffers = kmalloc_array(n, sizeof(*buffers), GFP_KERNEL); @@ -234,27 +223,22 @@ void kbase_hwcnt_dump_buffer_narrow_array_free( memset(dump_bufs, 0, sizeof(*dump_bufs)); } -void kbase_hwcnt_dump_buffer_block_copy_strict_narrow(u32 *dst_blk, - const u64 *src_blk, - const u64 *blk_em, - size_t val_cnt) +void kbase_hwcnt_dump_buffer_block_copy_strict_narrow(u32 *dst_blk, const u64 *src_blk, + const u64 *blk_em, size_t val_cnt) { size_t val; for (val = 0; val < val_cnt; val++) { - bool val_enabled = - kbase_hwcnt_enable_map_block_value_enabled(blk_em, val); - u32 src_val = - (src_blk[val] > U32_MAX) ? U32_MAX : (u32)src_blk[val]; + bool val_enabled = kbase_hwcnt_enable_map_block_value_enabled(blk_em, val); + u32 src_val = (src_blk[val] > U32_MAX) ? U32_MAX : (u32)src_blk[val]; dst_blk[val] = val_enabled ? src_val : 0; } } -void kbase_hwcnt_dump_buffer_copy_strict_narrow( - struct kbase_hwcnt_dump_buffer_narrow *dst_narrow, - const struct kbase_hwcnt_dump_buffer *src, - const struct kbase_hwcnt_enable_map *dst_enable_map) +void kbase_hwcnt_dump_buffer_copy_strict_narrow(struct kbase_hwcnt_dump_buffer_narrow *dst_narrow, + const struct kbase_hwcnt_dump_buffer *src, + const struct kbase_hwcnt_enable_map *dst_enable_map) { const struct kbase_hwcnt_metadata_narrow *metadata_narrow; size_t grp; @@ -262,68 +246,53 @@ void kbase_hwcnt_dump_buffer_copy_strict_narrow( if (WARN_ON(!dst_narrow) || WARN_ON(!src) || WARN_ON(!dst_enable_map) || WARN_ON(dst_narrow->md_narrow->metadata == src->metadata) || - WARN_ON(dst_narrow->md_narrow->metadata->grp_cnt != - src->metadata->grp_cnt) || + WARN_ON(dst_narrow->md_narrow->metadata->grp_cnt != src->metadata->grp_cnt) || WARN_ON(src->metadata->grp_cnt != 1) || WARN_ON(dst_narrow->md_narrow->metadata->grp_metadata[0].blk_cnt != src->metadata->grp_metadata[0].blk_cnt) || WARN_ON(dst_narrow->md_narrow->metadata->grp_metadata[0].blk_cnt != KBASE_HWCNT_V5_BLOCK_TYPE_COUNT) || - WARN_ON(dst_narrow->md_narrow->metadata->grp_metadata[0] - .blk_metadata[0] - .ctr_cnt > + WARN_ON(dst_narrow->md_narrow->metadata->grp_metadata[0].blk_metadata[0].ctr_cnt > src->metadata->grp_metadata[0].blk_metadata[0].ctr_cnt)) return; /* Don't use src metadata since src buffer is bigger than dst buffer. */ metadata_narrow = dst_narrow->md_narrow; - for (grp = 0; - grp < kbase_hwcnt_metadata_narrow_group_count(metadata_narrow); - grp++) { + for (grp = 0; grp < kbase_hwcnt_metadata_narrow_group_count(metadata_narrow); grp++) { size_t blk; - size_t blk_cnt = kbase_hwcnt_metadata_narrow_block_count( - metadata_narrow, grp); + size_t blk_cnt = kbase_hwcnt_metadata_narrow_block_count(metadata_narrow, grp); for (blk = 0; blk < blk_cnt; blk++) { size_t blk_inst; - size_t blk_inst_cnt = - kbase_hwcnt_metadata_narrow_block_instance_count( - metadata_narrow, grp, blk); + size_t blk_inst_cnt = kbase_hwcnt_metadata_narrow_block_instance_count( + metadata_narrow, grp, blk); - for (blk_inst = 0; blk_inst < blk_inst_cnt; - blk_inst++) { + for (blk_inst = 0; blk_inst < blk_inst_cnt; blk_inst++) { /* The narrowed down buffer is only 32-bit. */ - u32 *dst_blk = - kbase_hwcnt_dump_buffer_narrow_block_instance( - dst_narrow, grp, blk, blk_inst); - const u64 *src_blk = - kbase_hwcnt_dump_buffer_block_instance( - src, grp, blk, blk_inst); - const u64 *blk_em = - kbase_hwcnt_enable_map_block_instance( - dst_enable_map, grp, blk, - blk_inst); - size_t val_cnt = - kbase_hwcnt_metadata_narrow_block_values_count( - metadata_narrow, grp, blk); + u32 *dst_blk = kbase_hwcnt_dump_buffer_narrow_block_instance( + dst_narrow, grp, blk, blk_inst); + const u64 *src_blk = kbase_hwcnt_dump_buffer_block_instance( + src, grp, blk, blk_inst); + const u64 *blk_em = kbase_hwcnt_enable_map_block_instance( + dst_enable_map, grp, blk, blk_inst); + size_t val_cnt = kbase_hwcnt_metadata_narrow_block_values_count( + metadata_narrow, grp, blk); /* Align upwards to include padding bytes */ val_cnt = KBASE_HWCNT_ALIGN_UPWARDS( - val_cnt, - (KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT / - KBASE_HWCNT_VALUE_BYTES)); + val_cnt, (KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT / + KBASE_HWCNT_VALUE_BYTES)); - kbase_hwcnt_dump_buffer_block_copy_strict_narrow( - dst_blk, src_blk, blk_em, val_cnt); + kbase_hwcnt_dump_buffer_block_copy_strict_narrow(dst_blk, src_blk, + blk_em, val_cnt); } } } for (clk = 0; clk < metadata_narrow->metadata->clk_cnt; clk++) { - bool clk_enabled = kbase_hwcnt_clk_enable_map_enabled( - dst_enable_map->clk_enable_map, clk); + bool clk_enabled = + kbase_hwcnt_clk_enable_map_enabled(dst_enable_map->clk_enable_map, clk); - dst_narrow->clk_cnt_buf[clk] = - clk_enabled ? src->clk_cnt_buf[clk] : 0; + dst_narrow->clk_cnt_buf[clk] = clk_enabled ? src->clk_cnt_buf[clk] : 0; } } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu_narrow.h b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu_narrow.h similarity index 84% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu_narrow.h rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu_narrow.h index af6fa19f71e3..afd236d71a7c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_gpu_narrow.h +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_gpu_narrow.h @@ -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 @@ -22,7 +22,7 @@ #ifndef _KBASE_HWCNT_GPU_NARROW_H_ #define _KBASE_HWCNT_GPU_NARROW_H_ -#include "mali_kbase_hwcnt_types.h" +#include "hwcnt/mali_kbase_hwcnt_types.h" #include struct kbase_device; @@ -86,8 +86,8 @@ struct kbase_hwcnt_dump_buffer_narrow_array { * * Return: Number of hardware counter groups described by narrow metadata. */ -static inline size_t kbase_hwcnt_metadata_narrow_group_count( - const struct kbase_hwcnt_metadata_narrow *md_narrow) +static inline size_t +kbase_hwcnt_metadata_narrow_group_count(const struct kbase_hwcnt_metadata_narrow *md_narrow) { return kbase_hwcnt_metadata_group_count(md_narrow->metadata); } @@ -100,8 +100,9 @@ static inline size_t kbase_hwcnt_metadata_narrow_group_count( * * Return: Type of the group grp. */ -static inline u64 kbase_hwcnt_metadata_narrow_group_type( - const struct kbase_hwcnt_metadata_narrow *md_narrow, size_t grp) +static inline u64 +kbase_hwcnt_metadata_narrow_group_type(const struct kbase_hwcnt_metadata_narrow *md_narrow, + size_t grp) { return kbase_hwcnt_metadata_group_type(md_narrow->metadata, grp); } @@ -114,8 +115,9 @@ static inline u64 kbase_hwcnt_metadata_narrow_group_type( * * Return: Number of blocks in group grp. */ -static inline size_t kbase_hwcnt_metadata_narrow_block_count( - const struct kbase_hwcnt_metadata_narrow *md_narrow, size_t grp) +static inline size_t +kbase_hwcnt_metadata_narrow_block_count(const struct kbase_hwcnt_metadata_narrow *md_narrow, + size_t grp) { return kbase_hwcnt_metadata_block_count(md_narrow->metadata, grp); } @@ -131,11 +133,9 @@ static inline size_t kbase_hwcnt_metadata_narrow_block_count( * Return: Number of instances of block blk in group grp. */ static inline size_t kbase_hwcnt_metadata_narrow_block_instance_count( - const struct kbase_hwcnt_metadata_narrow *md_narrow, size_t grp, - size_t blk) + const struct kbase_hwcnt_metadata_narrow *md_narrow, size_t grp, size_t blk) { - return kbase_hwcnt_metadata_block_instance_count(md_narrow->metadata, - grp, blk); + return kbase_hwcnt_metadata_block_instance_count(md_narrow->metadata, grp, blk); } /** @@ -148,12 +148,11 @@ static inline size_t kbase_hwcnt_metadata_narrow_block_instance_count( * * Return: Number of counter headers in each instance of block blk in group grp. */ -static inline size_t kbase_hwcnt_metadata_narrow_block_headers_count( - const struct kbase_hwcnt_metadata_narrow *md_narrow, size_t grp, - size_t blk) +static inline size_t +kbase_hwcnt_metadata_narrow_block_headers_count(const struct kbase_hwcnt_metadata_narrow *md_narrow, + size_t grp, size_t blk) { - return kbase_hwcnt_metadata_block_headers_count(md_narrow->metadata, - grp, blk); + return kbase_hwcnt_metadata_block_headers_count(md_narrow->metadata, grp, blk); } /** @@ -167,11 +166,9 @@ static inline size_t kbase_hwcnt_metadata_narrow_block_headers_count( * Return: Number of counters in each instance of block blk in group grp. */ static inline size_t kbase_hwcnt_metadata_narrow_block_counters_count( - const struct kbase_hwcnt_metadata_narrow *md_narrow, size_t grp, - size_t blk) + const struct kbase_hwcnt_metadata_narrow *md_narrow, size_t grp, size_t blk) { - return kbase_hwcnt_metadata_block_counters_count(md_narrow->metadata, - grp, blk); + return kbase_hwcnt_metadata_block_counters_count(md_narrow->metadata, grp, blk); } /** @@ -184,14 +181,12 @@ static inline size_t kbase_hwcnt_metadata_narrow_block_counters_count( * Return: Number of headers plus counters in each instance of block blk * in group grp. */ -static inline size_t kbase_hwcnt_metadata_narrow_block_values_count( - const struct kbase_hwcnt_metadata_narrow *md_narrow, size_t grp, - size_t blk) +static inline size_t +kbase_hwcnt_metadata_narrow_block_values_count(const struct kbase_hwcnt_metadata_narrow *md_narrow, + size_t grp, size_t blk) { - return kbase_hwcnt_metadata_narrow_block_counters_count(md_narrow, grp, - blk) + - kbase_hwcnt_metadata_narrow_block_headers_count(md_narrow, grp, - blk); + return kbase_hwcnt_metadata_narrow_block_counters_count(md_narrow, grp, blk) + + kbase_hwcnt_metadata_narrow_block_headers_count(md_narrow, grp, blk); } /** @@ -205,18 +200,13 @@ static inline size_t kbase_hwcnt_metadata_narrow_block_values_count( * * Return: u32* to the dump buffer for the block instance. */ -static inline u32 *kbase_hwcnt_dump_buffer_narrow_block_instance( - const struct kbase_hwcnt_dump_buffer_narrow *buf, size_t grp, - size_t blk, size_t blk_inst) +static inline u32 * +kbase_hwcnt_dump_buffer_narrow_block_instance(const struct kbase_hwcnt_dump_buffer_narrow *buf, + size_t grp, size_t blk, size_t blk_inst) { - return buf->dump_buf + - buf->md_narrow->metadata->grp_metadata[grp].dump_buf_index + - buf->md_narrow->metadata->grp_metadata[grp] - .blk_metadata[blk] - .dump_buf_index + - (buf->md_narrow->metadata->grp_metadata[grp] - .blk_metadata[blk] - .dump_buf_stride * + return buf->dump_buf + buf->md_narrow->metadata->grp_metadata[grp].dump_buf_index + + buf->md_narrow->metadata->grp_metadata[grp].blk_metadata[blk].dump_buf_index + + (buf->md_narrow->metadata->grp_metadata[grp].blk_metadata[blk].dump_buf_stride * blk_inst); } @@ -239,17 +229,15 @@ static inline u32 *kbase_hwcnt_dump_buffer_narrow_block_instance( * * Return: 0 on success, else error code. */ -int kbase_hwcnt_gpu_metadata_narrow_create( - const struct kbase_hwcnt_metadata_narrow **dst_md_narrow, - const struct kbase_hwcnt_metadata *src_md); +int kbase_hwcnt_gpu_metadata_narrow_create(const struct kbase_hwcnt_metadata_narrow **dst_md_narrow, + const struct kbase_hwcnt_metadata *src_md); /** * kbase_hwcnt_gpu_metadata_narrow_destroy() - Destroy a hardware counter narrow * metadata object. * @md_narrow: Pointer to hardware counter narrow metadata. */ -void kbase_hwcnt_gpu_metadata_narrow_destroy( - const struct kbase_hwcnt_metadata_narrow *md_narrow); +void kbase_hwcnt_gpu_metadata_narrow_destroy(const struct kbase_hwcnt_metadata_narrow *md_narrow); /** * kbase_hwcnt_dump_buffer_narrow_alloc() - Allocate a narrow dump buffer. @@ -260,9 +248,8 @@ void kbase_hwcnt_gpu_metadata_narrow_destroy( * * Return: 0 on success, else error code. */ -int kbase_hwcnt_dump_buffer_narrow_alloc( - const struct kbase_hwcnt_metadata_narrow *md_narrow, - struct kbase_hwcnt_dump_buffer_narrow *dump_buf); +int kbase_hwcnt_dump_buffer_narrow_alloc(const struct kbase_hwcnt_metadata_narrow *md_narrow, + struct kbase_hwcnt_dump_buffer_narrow *dump_buf); /** * kbase_hwcnt_dump_buffer_narrow_free() - Free a narrow dump buffer. @@ -271,8 +258,7 @@ int kbase_hwcnt_dump_buffer_narrow_alloc( * Can be safely called on an all-zeroed narrow dump buffer structure, or on an * already freed narrow dump buffer. */ -void kbase_hwcnt_dump_buffer_narrow_free( - struct kbase_hwcnt_dump_buffer_narrow *dump_buf); +void kbase_hwcnt_dump_buffer_narrow_free(struct kbase_hwcnt_dump_buffer_narrow *dump_buf); /** * kbase_hwcnt_dump_buffer_narrow_array_alloc() - Allocate an array of narrow @@ -320,10 +306,8 @@ void kbase_hwcnt_dump_buffer_narrow_array_free( * source value is bigger than U32_MAX, or copy the value from source if the * corresponding source value is less than or equal to U32_MAX. */ -void kbase_hwcnt_dump_buffer_block_copy_strict_narrow(u32 *dst_blk, - const u64 *src_blk, - const u64 *blk_em, - size_t val_cnt); +void kbase_hwcnt_dump_buffer_block_copy_strict_narrow(u32 *dst_blk, const u64 *src_blk, + const u64 *blk_em, size_t val_cnt); /** * kbase_hwcnt_dump_buffer_copy_strict_narrow() - Copy all enabled values to a @@ -339,9 +323,8 @@ void kbase_hwcnt_dump_buffer_block_copy_strict_narrow(u32 *dst_blk, * corresponding source value is bigger than U32_MAX, or copy the value from * source if the corresponding source value is less than or equal to U32_MAX. */ -void kbase_hwcnt_dump_buffer_copy_strict_narrow( - struct kbase_hwcnt_dump_buffer_narrow *dst_narrow, - const struct kbase_hwcnt_dump_buffer *src, - const struct kbase_hwcnt_enable_map *dst_enable_map); +void kbase_hwcnt_dump_buffer_copy_strict_narrow(struct kbase_hwcnt_dump_buffer_narrow *dst_narrow, + const struct kbase_hwcnt_dump_buffer *src, + const struct kbase_hwcnt_enable_map *dst_enable_map); #endif /* _KBASE_HWCNT_GPU_NARROW_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_types.c b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_types.c similarity index 56% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_types.c rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_types.c index d925ed744d3d..763eb315d9a2 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_types.c +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_types.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2018, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 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 @@ -19,13 +19,12 @@ * */ -#include "mali_kbase_hwcnt_types.h" +#include "hwcnt/mali_kbase_hwcnt_types.h" #include -int kbase_hwcnt_metadata_create( - const struct kbase_hwcnt_description *desc, - const struct kbase_hwcnt_metadata **out_metadata) +int kbase_hwcnt_metadata_create(const struct kbase_hwcnt_description *desc, + const struct kbase_hwcnt_metadata **out_metadata) { char *buf; struct kbase_hwcnt_metadata *metadata; @@ -56,8 +55,7 @@ int kbase_hwcnt_metadata_create( /* Block metadata */ for (grp = 0; grp < desc->grp_cnt; grp++) { - size += sizeof(struct kbase_hwcnt_block_metadata) * - desc->grps[grp].blk_cnt; + size += sizeof(struct kbase_hwcnt_block_metadata) * desc->grps[grp].blk_cnt; } /* Single allocation for the entire metadata */ @@ -83,8 +81,7 @@ int kbase_hwcnt_metadata_create( for (grp = 0; grp < desc->grp_cnt; grp++) { size_t blk; - const struct kbase_hwcnt_group_description *grp_desc = - desc->grps + grp; + const struct kbase_hwcnt_group_description *grp_desc = desc->grps + grp; struct kbase_hwcnt_group_metadata *grp_md = grp_mds + grp; size_t group_enable_map_count = 0; @@ -94,37 +91,28 @@ int kbase_hwcnt_metadata_create( /* Bump allocate this group's block metadata */ struct kbase_hwcnt_block_metadata *blk_mds = (struct kbase_hwcnt_block_metadata *)(buf + offset); - offset += sizeof(struct kbase_hwcnt_block_metadata) * - grp_desc->blk_cnt; + offset += sizeof(struct kbase_hwcnt_block_metadata) * grp_desc->blk_cnt; /* Fill in each block in the group's information */ for (blk = 0; blk < grp_desc->blk_cnt; blk++) { - const struct kbase_hwcnt_block_description *blk_desc = - grp_desc->blks + blk; - struct kbase_hwcnt_block_metadata *blk_md = - blk_mds + blk; - const size_t n_values = - blk_desc->hdr_cnt + blk_desc->ctr_cnt; + const struct kbase_hwcnt_block_description *blk_desc = grp_desc->blks + blk; + struct kbase_hwcnt_block_metadata *blk_md = blk_mds + blk; + const size_t n_values = blk_desc->hdr_cnt + blk_desc->ctr_cnt; blk_md->type = blk_desc->type; blk_md->inst_cnt = blk_desc->inst_cnt; blk_md->hdr_cnt = blk_desc->hdr_cnt; blk_md->ctr_cnt = blk_desc->ctr_cnt; blk_md->enable_map_index = group_enable_map_count; - blk_md->enable_map_stride = - kbase_hwcnt_bitfield_count(n_values); + blk_md->enable_map_stride = kbase_hwcnt_bitfield_count(n_values); blk_md->dump_buf_index = group_dump_buffer_count; - blk_md->dump_buf_stride = - KBASE_HWCNT_ALIGN_UPWARDS( - n_values, - (KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT / - KBASE_HWCNT_VALUE_BYTES)); + blk_md->dump_buf_stride = KBASE_HWCNT_ALIGN_UPWARDS( + n_values, + (KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT / KBASE_HWCNT_VALUE_BYTES)); blk_md->avail_mask_index = group_avail_mask_bits; - group_enable_map_count += - blk_md->enable_map_stride * blk_md->inst_cnt; - group_dump_buffer_count += - blk_md->dump_buf_stride * blk_md->inst_cnt; + group_enable_map_count += blk_md->enable_map_stride * blk_md->inst_cnt; + group_dump_buffer_count += blk_md->dump_buf_stride * blk_md->inst_cnt; group_avail_mask_bits += blk_md->inst_cnt; } @@ -144,8 +132,7 @@ int kbase_hwcnt_metadata_create( /* Fill in the top level metadata's information */ metadata->grp_cnt = desc->grp_cnt; metadata->grp_metadata = grp_mds; - metadata->enable_map_bytes = - enable_map_count * KBASE_HWCNT_BITFIELD_BYTES; + metadata->enable_map_bytes = enable_map_count * KBASE_HWCNT_BITFIELD_BYTES; metadata->dump_buf_bytes = dump_buf_count * KBASE_HWCNT_VALUE_BYTES; metadata->avail_mask = desc->avail_mask; metadata->clk_cnt = desc->clk_cnt; @@ -155,8 +142,7 @@ int kbase_hwcnt_metadata_create( * bit per 4 bytes in the dump buffer. */ WARN_ON(metadata->dump_buf_bytes != - (metadata->enable_map_bytes * - BITS_PER_BYTE * KBASE_HWCNT_VALUE_BYTES)); + (metadata->enable_map_bytes * BITS_PER_BYTE * KBASE_HWCNT_VALUE_BYTES)); *out_metadata = metadata; return 0; @@ -167,9 +153,8 @@ void kbase_hwcnt_metadata_destroy(const struct kbase_hwcnt_metadata *metadata) kfree(metadata); } -int kbase_hwcnt_enable_map_alloc( - const struct kbase_hwcnt_metadata *metadata, - struct kbase_hwcnt_enable_map *enable_map) +int kbase_hwcnt_enable_map_alloc(const struct kbase_hwcnt_metadata *metadata, + struct kbase_hwcnt_enable_map *enable_map) { u64 *enable_map_buf; @@ -177,8 +162,7 @@ int kbase_hwcnt_enable_map_alloc( return -EINVAL; if (metadata->enable_map_bytes > 0) { - enable_map_buf = - kzalloc(metadata->enable_map_bytes, GFP_KERNEL); + enable_map_buf = kzalloc(metadata->enable_map_bytes, GFP_KERNEL); if (!enable_map_buf) return -ENOMEM; } else { @@ -200,9 +184,8 @@ void kbase_hwcnt_enable_map_free(struct kbase_hwcnt_enable_map *enable_map) enable_map->metadata = NULL; } -int kbase_hwcnt_dump_buffer_alloc( - const struct kbase_hwcnt_metadata *metadata, - struct kbase_hwcnt_dump_buffer *dump_buf) +int kbase_hwcnt_dump_buffer_alloc(const struct kbase_hwcnt_metadata *metadata, + struct kbase_hwcnt_dump_buffer *dump_buf) { size_t dump_buf_bytes; size_t clk_cnt_buf_bytes; @@ -235,10 +218,8 @@ void kbase_hwcnt_dump_buffer_free(struct kbase_hwcnt_dump_buffer *dump_buf) memset(dump_buf, 0, sizeof(*dump_buf)); } -int kbase_hwcnt_dump_buffer_array_alloc( - const struct kbase_hwcnt_metadata *metadata, - size_t n, - struct kbase_hwcnt_dump_buffer_array *dump_bufs) +int kbase_hwcnt_dump_buffer_array_alloc(const struct kbase_hwcnt_metadata *metadata, size_t n, + struct kbase_hwcnt_dump_buffer_array *dump_bufs) { struct kbase_hwcnt_dump_buffer *buffers; size_t buf_idx; @@ -251,8 +232,7 @@ int kbase_hwcnt_dump_buffer_array_alloc( return -EINVAL; dump_buf_bytes = metadata->dump_buf_bytes; - clk_cnt_buf_bytes = - sizeof(*dump_bufs->bufs->clk_cnt_buf) * metadata->clk_cnt; + clk_cnt_buf_bytes = sizeof(*dump_bufs->bufs->clk_cnt_buf) * metadata->clk_cnt; /* Allocate memory for the dump buffer struct array */ buffers = kmalloc_array(n, sizeof(*buffers), GFP_KERNEL); @@ -283,15 +263,13 @@ int kbase_hwcnt_dump_buffer_array_alloc( buffers[buf_idx].metadata = metadata; buffers[buf_idx].dump_buf = (u64 *)(addr + dump_buf_offset); - buffers[buf_idx].clk_cnt_buf = - (u64 *)(addr + clk_cnt_buf_offset); + buffers[buf_idx].clk_cnt_buf = (u64 *)(addr + clk_cnt_buf_offset); } return 0; } -void kbase_hwcnt_dump_buffer_array_free( - struct kbase_hwcnt_dump_buffer_array *dump_bufs) +void kbase_hwcnt_dump_buffer_array_free(struct kbase_hwcnt_dump_buffer_array *dump_bufs) { if (!dump_bufs) return; @@ -301,84 +279,71 @@ void kbase_hwcnt_dump_buffer_array_free( memset(dump_bufs, 0, sizeof(*dump_bufs)); } -void kbase_hwcnt_dump_buffer_zero( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_enable_map *dst_enable_map) +void kbase_hwcnt_dump_buffer_zero(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_enable_map *dst_enable_map) { const struct kbase_hwcnt_metadata *metadata; size_t grp, blk, blk_inst; - if (WARN_ON(!dst) || - WARN_ON(!dst_enable_map) || + if (WARN_ON(!dst) || WARN_ON(!dst_enable_map) || WARN_ON(dst->metadata != dst_enable_map->metadata)) return; metadata = dst->metadata; - kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) { + kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) + { u64 *dst_blk; size_t val_cnt; - if (!kbase_hwcnt_enable_map_block_enabled( - dst_enable_map, grp, blk, blk_inst)) + if (!kbase_hwcnt_enable_map_block_enabled(dst_enable_map, grp, blk, blk_inst)) continue; - dst_blk = kbase_hwcnt_dump_buffer_block_instance( - dst, grp, blk, blk_inst); - val_cnt = kbase_hwcnt_metadata_block_values_count( - metadata, grp, blk); + dst_blk = kbase_hwcnt_dump_buffer_block_instance(dst, grp, blk, blk_inst); + val_cnt = kbase_hwcnt_metadata_block_values_count(metadata, grp, blk); kbase_hwcnt_dump_buffer_block_zero(dst_blk, val_cnt); } - memset(dst->clk_cnt_buf, 0, - sizeof(*dst->clk_cnt_buf) * metadata->clk_cnt); + memset(dst->clk_cnt_buf, 0, sizeof(*dst->clk_cnt_buf) * metadata->clk_cnt); } -void kbase_hwcnt_dump_buffer_zero_strict( - struct kbase_hwcnt_dump_buffer *dst) +void kbase_hwcnt_dump_buffer_zero_strict(struct kbase_hwcnt_dump_buffer *dst) { if (WARN_ON(!dst)) return; memset(dst->dump_buf, 0, dst->metadata->dump_buf_bytes); - memset(dst->clk_cnt_buf, 0, - sizeof(*dst->clk_cnt_buf) * dst->metadata->clk_cnt); + memset(dst->clk_cnt_buf, 0, sizeof(*dst->clk_cnt_buf) * dst->metadata->clk_cnt); } -void kbase_hwcnt_dump_buffer_zero_non_enabled( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_enable_map *dst_enable_map) +void kbase_hwcnt_dump_buffer_zero_non_enabled(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_enable_map *dst_enable_map) { const struct kbase_hwcnt_metadata *metadata; size_t grp, blk, blk_inst; - if (WARN_ON(!dst) || - WARN_ON(!dst_enable_map) || + if (WARN_ON(!dst) || WARN_ON(!dst_enable_map) || WARN_ON(dst->metadata != dst_enable_map->metadata)) return; metadata = dst->metadata; - kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) { - u64 *dst_blk = kbase_hwcnt_dump_buffer_block_instance( - dst, grp, blk, blk_inst); - const u64 *blk_em = kbase_hwcnt_enable_map_block_instance( - dst_enable_map, grp, blk, blk_inst); - size_t val_cnt = kbase_hwcnt_metadata_block_values_count( - metadata, grp, blk); + kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) + { + u64 *dst_blk = kbase_hwcnt_dump_buffer_block_instance(dst, grp, blk, blk_inst); + const u64 *blk_em = + kbase_hwcnt_enable_map_block_instance(dst_enable_map, grp, blk, blk_inst); + size_t val_cnt = kbase_hwcnt_metadata_block_values_count(metadata, grp, blk); /* Align upwards to include padding bytes */ - val_cnt = KBASE_HWCNT_ALIGN_UPWARDS(val_cnt, - (KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT / - KBASE_HWCNT_VALUE_BYTES)); + val_cnt = KBASE_HWCNT_ALIGN_UPWARDS( + val_cnt, (KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT / KBASE_HWCNT_VALUE_BYTES)); - if (kbase_hwcnt_metadata_block_instance_avail( - metadata, grp, blk, blk_inst)) { + if (kbase_hwcnt_metadata_block_instance_avail(metadata, grp, blk, blk_inst)) { /* Block available, so only zero non-enabled values */ - kbase_hwcnt_dump_buffer_block_zero_non_enabled( - dst_blk, blk_em, val_cnt); + kbase_hwcnt_dump_buffer_block_zero_non_enabled(dst_blk, blk_em, val_cnt); } else { /* Block not available, so zero the entire thing */ kbase_hwcnt_dump_buffer_block_zero(dst_blk, val_cnt); @@ -386,188 +351,159 @@ void kbase_hwcnt_dump_buffer_zero_non_enabled( } } -void kbase_hwcnt_dump_buffer_copy( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_dump_buffer *src, - const struct kbase_hwcnt_enable_map *dst_enable_map) +void kbase_hwcnt_dump_buffer_copy(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_dump_buffer *src, + const struct kbase_hwcnt_enable_map *dst_enable_map) { const struct kbase_hwcnt_metadata *metadata; size_t grp, blk, blk_inst; size_t clk; - if (WARN_ON(!dst) || - WARN_ON(!src) || - WARN_ON(!dst_enable_map) || - WARN_ON(dst == src) || + if (WARN_ON(!dst) || WARN_ON(!src) || WARN_ON(!dst_enable_map) || WARN_ON(dst == src) || WARN_ON(dst->metadata != src->metadata) || WARN_ON(dst->metadata != dst_enable_map->metadata)) return; metadata = dst->metadata; - kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) { + kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) + { u64 *dst_blk; const u64 *src_blk; size_t val_cnt; - if (!kbase_hwcnt_enable_map_block_enabled( - dst_enable_map, grp, blk, blk_inst)) + if (!kbase_hwcnt_enable_map_block_enabled(dst_enable_map, grp, blk, blk_inst)) continue; - dst_blk = kbase_hwcnt_dump_buffer_block_instance( - dst, grp, blk, blk_inst); - src_blk = kbase_hwcnt_dump_buffer_block_instance( - src, grp, blk, blk_inst); - val_cnt = kbase_hwcnt_metadata_block_values_count( - metadata, grp, blk); + dst_blk = kbase_hwcnt_dump_buffer_block_instance(dst, grp, blk, blk_inst); + src_blk = kbase_hwcnt_dump_buffer_block_instance(src, grp, blk, blk_inst); + val_cnt = kbase_hwcnt_metadata_block_values_count(metadata, grp, blk); kbase_hwcnt_dump_buffer_block_copy(dst_blk, src_blk, val_cnt); } - kbase_hwcnt_metadata_for_each_clock(metadata, clk) { - if (kbase_hwcnt_clk_enable_map_enabled( - dst_enable_map->clk_enable_map, clk)) + kbase_hwcnt_metadata_for_each_clock(metadata, clk) + { + if (kbase_hwcnt_clk_enable_map_enabled(dst_enable_map->clk_enable_map, clk)) dst->clk_cnt_buf[clk] = src->clk_cnt_buf[clk]; } } -void kbase_hwcnt_dump_buffer_copy_strict( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_dump_buffer *src, - const struct kbase_hwcnt_enable_map *dst_enable_map) +void kbase_hwcnt_dump_buffer_copy_strict(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_dump_buffer *src, + const struct kbase_hwcnt_enable_map *dst_enable_map) { const struct kbase_hwcnt_metadata *metadata; size_t grp, blk, blk_inst; size_t clk; - if (WARN_ON(!dst) || - WARN_ON(!src) || - WARN_ON(!dst_enable_map) || - WARN_ON(dst == src) || + if (WARN_ON(!dst) || WARN_ON(!src) || WARN_ON(!dst_enable_map) || WARN_ON(dst == src) || WARN_ON(dst->metadata != src->metadata) || WARN_ON(dst->metadata != dst_enable_map->metadata)) return; metadata = dst->metadata; - kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) { - u64 *dst_blk = kbase_hwcnt_dump_buffer_block_instance( - dst, grp, blk, blk_inst); - const u64 *src_blk = kbase_hwcnt_dump_buffer_block_instance( - src, grp, blk, blk_inst); - const u64 *blk_em = kbase_hwcnt_enable_map_block_instance( - dst_enable_map, grp, blk, blk_inst); - size_t val_cnt = kbase_hwcnt_metadata_block_values_count( - metadata, grp, blk); + kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) + { + u64 *dst_blk = kbase_hwcnt_dump_buffer_block_instance(dst, grp, blk, blk_inst); + const u64 *src_blk = + kbase_hwcnt_dump_buffer_block_instance(src, grp, blk, blk_inst); + const u64 *blk_em = + kbase_hwcnt_enable_map_block_instance(dst_enable_map, grp, blk, blk_inst); + size_t val_cnt = kbase_hwcnt_metadata_block_values_count(metadata, grp, blk); /* Align upwards to include padding bytes */ - val_cnt = KBASE_HWCNT_ALIGN_UPWARDS(val_cnt, - (KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT / - KBASE_HWCNT_VALUE_BYTES)); + val_cnt = KBASE_HWCNT_ALIGN_UPWARDS( + val_cnt, (KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT / KBASE_HWCNT_VALUE_BYTES)); - kbase_hwcnt_dump_buffer_block_copy_strict( - dst_blk, src_blk, blk_em, val_cnt); + kbase_hwcnt_dump_buffer_block_copy_strict(dst_blk, src_blk, blk_em, val_cnt); } - kbase_hwcnt_metadata_for_each_clock(metadata, clk) { + kbase_hwcnt_metadata_for_each_clock(metadata, clk) + { bool clk_enabled = - kbase_hwcnt_clk_enable_map_enabled( - dst_enable_map->clk_enable_map, clk); + kbase_hwcnt_clk_enable_map_enabled(dst_enable_map->clk_enable_map, clk); dst->clk_cnt_buf[clk] = clk_enabled ? src->clk_cnt_buf[clk] : 0; } } -void kbase_hwcnt_dump_buffer_accumulate( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_dump_buffer *src, - const struct kbase_hwcnt_enable_map *dst_enable_map) +void kbase_hwcnt_dump_buffer_accumulate(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_dump_buffer *src, + const struct kbase_hwcnt_enable_map *dst_enable_map) { const struct kbase_hwcnt_metadata *metadata; size_t grp, blk, blk_inst; size_t clk; - if (WARN_ON(!dst) || - WARN_ON(!src) || - WARN_ON(!dst_enable_map) || - WARN_ON(dst == src) || + if (WARN_ON(!dst) || WARN_ON(!src) || WARN_ON(!dst_enable_map) || WARN_ON(dst == src) || WARN_ON(dst->metadata != src->metadata) || WARN_ON(dst->metadata != dst_enable_map->metadata)) return; metadata = dst->metadata; - kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) { + kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) + { u64 *dst_blk; const u64 *src_blk; size_t hdr_cnt; size_t ctr_cnt; - if (!kbase_hwcnt_enable_map_block_enabled( - dst_enable_map, grp, blk, blk_inst)) + if (!kbase_hwcnt_enable_map_block_enabled(dst_enable_map, grp, blk, blk_inst)) continue; - dst_blk = kbase_hwcnt_dump_buffer_block_instance( - dst, grp, blk, blk_inst); - src_blk = kbase_hwcnt_dump_buffer_block_instance( - src, grp, blk, blk_inst); - hdr_cnt = kbase_hwcnt_metadata_block_headers_count( - metadata, grp, blk); - ctr_cnt = kbase_hwcnt_metadata_block_counters_count( - metadata, grp, blk); + dst_blk = kbase_hwcnt_dump_buffer_block_instance(dst, grp, blk, blk_inst); + src_blk = kbase_hwcnt_dump_buffer_block_instance(src, grp, blk, blk_inst); + hdr_cnt = kbase_hwcnt_metadata_block_headers_count(metadata, grp, blk); + ctr_cnt = kbase_hwcnt_metadata_block_counters_count(metadata, grp, blk); - kbase_hwcnt_dump_buffer_block_accumulate( - dst_blk, src_blk, hdr_cnt, ctr_cnt); + kbase_hwcnt_dump_buffer_block_accumulate(dst_blk, src_blk, hdr_cnt, ctr_cnt); } - kbase_hwcnt_metadata_for_each_clock(metadata, clk) { - if (kbase_hwcnt_clk_enable_map_enabled( - dst_enable_map->clk_enable_map, clk)) + kbase_hwcnt_metadata_for_each_clock(metadata, clk) + { + if (kbase_hwcnt_clk_enable_map_enabled(dst_enable_map->clk_enable_map, clk)) dst->clk_cnt_buf[clk] += src->clk_cnt_buf[clk]; } } -void kbase_hwcnt_dump_buffer_accumulate_strict( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_dump_buffer *src, - const struct kbase_hwcnt_enable_map *dst_enable_map) +void kbase_hwcnt_dump_buffer_accumulate_strict(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_dump_buffer *src, + const struct kbase_hwcnt_enable_map *dst_enable_map) { const struct kbase_hwcnt_metadata *metadata; size_t grp, blk, blk_inst; size_t clk; - if (WARN_ON(!dst) || - WARN_ON(!src) || - WARN_ON(!dst_enable_map) || - WARN_ON(dst == src) || + if (WARN_ON(!dst) || WARN_ON(!src) || WARN_ON(!dst_enable_map) || WARN_ON(dst == src) || WARN_ON(dst->metadata != src->metadata) || WARN_ON(dst->metadata != dst_enable_map->metadata)) return; metadata = dst->metadata; - kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) { - u64 *dst_blk = kbase_hwcnt_dump_buffer_block_instance( - dst, grp, blk, blk_inst); - const u64 *src_blk = kbase_hwcnt_dump_buffer_block_instance( - src, grp, blk, blk_inst); - const u64 *blk_em = kbase_hwcnt_enable_map_block_instance( - dst_enable_map, grp, blk, blk_inst); - size_t hdr_cnt = kbase_hwcnt_metadata_block_headers_count( - metadata, grp, blk); - size_t ctr_cnt = kbase_hwcnt_metadata_block_counters_count( - metadata, grp, blk); + kbase_hwcnt_metadata_for_each_block(metadata, grp, blk, blk_inst) + { + u64 *dst_blk = kbase_hwcnt_dump_buffer_block_instance(dst, grp, blk, blk_inst); + const u64 *src_blk = + kbase_hwcnt_dump_buffer_block_instance(src, grp, blk, blk_inst); + const u64 *blk_em = + kbase_hwcnt_enable_map_block_instance(dst_enable_map, grp, blk, blk_inst); + size_t hdr_cnt = kbase_hwcnt_metadata_block_headers_count(metadata, grp, blk); + size_t ctr_cnt = kbase_hwcnt_metadata_block_counters_count(metadata, grp, blk); /* Align upwards to include padding bytes */ - ctr_cnt = KBASE_HWCNT_ALIGN_UPWARDS(hdr_cnt + ctr_cnt, - (KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT / - KBASE_HWCNT_VALUE_BYTES) - hdr_cnt); + ctr_cnt = KBASE_HWCNT_ALIGN_UPWARDS( + hdr_cnt + ctr_cnt, + (KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT / KBASE_HWCNT_VALUE_BYTES) - hdr_cnt); - kbase_hwcnt_dump_buffer_block_accumulate_strict( - dst_blk, src_blk, blk_em, hdr_cnt, ctr_cnt); + kbase_hwcnt_dump_buffer_block_accumulate_strict(dst_blk, src_blk, blk_em, hdr_cnt, + ctr_cnt); } - kbase_hwcnt_metadata_for_each_clock(metadata, clk) { - if (kbase_hwcnt_clk_enable_map_enabled( - dst_enable_map->clk_enable_map, clk)) + kbase_hwcnt_metadata_for_each_clock(metadata, clk) + { + if (kbase_hwcnt_clk_enable_map_enabled(dst_enable_map->clk_enable_map, clk)) dst->clk_cnt_buf[clk] += src->clk_cnt_buf[clk]; else dst->clk_cnt_buf[clk] = 0; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_types.h b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_types.h similarity index 84% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_types.h rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_types.h index 9397840146b4..5c5ada401768 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_types.h +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_types.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2018, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 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 @@ -104,8 +104,7 @@ #define KBASE_HWCNT_AVAIL_MASK_BITS (sizeof(u64) * BITS_PER_BYTE) /* Minimum alignment of each block of hardware counters */ -#define KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT \ - (KBASE_HWCNT_BITFIELD_BITS * KBASE_HWCNT_VALUE_BYTES) +#define KBASE_HWCNT_BLOCK_BYTE_ALIGNMENT (KBASE_HWCNT_BITFIELD_BITS * KBASE_HWCNT_VALUE_BYTES) /** * KBASE_HWCNT_ALIGN_UPWARDS() - Calculate next aligned value. @@ -115,7 +114,7 @@ * Return: Input value if already aligned to the specified boundary, or next * (incrementing upwards) aligned value. */ -#define KBASE_HWCNT_ALIGN_UPWARDS(value, alignment) \ +#define KBASE_HWCNT_ALIGN_UPWARDS(value, alignment) \ (value + ((alignment - (value % alignment)) % alignment)) /** @@ -307,9 +306,8 @@ struct kbase_hwcnt_dump_buffer_array { * * Return: 0 on success, else error code. */ -int kbase_hwcnt_metadata_create( - const struct kbase_hwcnt_description *desc, - const struct kbase_hwcnt_metadata **metadata); +int kbase_hwcnt_metadata_create(const struct kbase_hwcnt_description *desc, + const struct kbase_hwcnt_metadata **metadata); /** * kbase_hwcnt_metadata_destroy() - Destroy a hardware counter metadata object. @@ -323,8 +321,7 @@ void kbase_hwcnt_metadata_destroy(const struct kbase_hwcnt_metadata *metadata); * * Return: Number of hardware counter groups described by metadata. */ -static inline size_t -kbase_hwcnt_metadata_group_count(const struct kbase_hwcnt_metadata *metadata) +static inline size_t kbase_hwcnt_metadata_group_count(const struct kbase_hwcnt_metadata *metadata) { if (WARN_ON(!metadata)) return 0; @@ -339,9 +336,8 @@ kbase_hwcnt_metadata_group_count(const struct kbase_hwcnt_metadata *metadata) * * Return: Type of the group grp. */ -static inline u64 -kbase_hwcnt_metadata_group_type(const struct kbase_hwcnt_metadata *metadata, - size_t grp) +static inline u64 kbase_hwcnt_metadata_group_type(const struct kbase_hwcnt_metadata *metadata, + size_t grp) { if (WARN_ON(!metadata) || WARN_ON(grp >= metadata->grp_cnt)) return 0; @@ -356,9 +352,8 @@ kbase_hwcnt_metadata_group_type(const struct kbase_hwcnt_metadata *metadata, * * Return: Number of blocks in group grp. */ -static inline size_t -kbase_hwcnt_metadata_block_count(const struct kbase_hwcnt_metadata *metadata, - size_t grp) +static inline size_t kbase_hwcnt_metadata_block_count(const struct kbase_hwcnt_metadata *metadata, + size_t grp) { if (WARN_ON(!metadata) || WARN_ON(grp >= metadata->grp_cnt)) return 0; @@ -374,9 +369,8 @@ kbase_hwcnt_metadata_block_count(const struct kbase_hwcnt_metadata *metadata, * * Return: Type of the block blk in group grp. */ -static inline u64 -kbase_hwcnt_metadata_block_type(const struct kbase_hwcnt_metadata *metadata, - size_t grp, size_t blk) +static inline u64 kbase_hwcnt_metadata_block_type(const struct kbase_hwcnt_metadata *metadata, + size_t grp, size_t blk) { if (WARN_ON(!metadata) || WARN_ON(grp >= metadata->grp_cnt) || WARN_ON(blk >= metadata->grp_metadata[grp].blk_cnt)) @@ -394,8 +388,9 @@ kbase_hwcnt_metadata_block_type(const struct kbase_hwcnt_metadata *metadata, * * Return: Number of instances of block blk in group grp. */ -static inline size_t kbase_hwcnt_metadata_block_instance_count( - const struct kbase_hwcnt_metadata *metadata, size_t grp, size_t blk) +static inline size_t +kbase_hwcnt_metadata_block_instance_count(const struct kbase_hwcnt_metadata *metadata, size_t grp, + size_t blk) { if (WARN_ON(!metadata) || WARN_ON(grp >= metadata->grp_cnt) || WARN_ON(blk >= metadata->grp_metadata[grp].blk_cnt)) @@ -413,8 +408,9 @@ static inline size_t kbase_hwcnt_metadata_block_instance_count( * * Return: Number of counter headers in each instance of block blk in group grp. */ -static inline size_t kbase_hwcnt_metadata_block_headers_count( - const struct kbase_hwcnt_metadata *metadata, size_t grp, size_t blk) +static inline size_t +kbase_hwcnt_metadata_block_headers_count(const struct kbase_hwcnt_metadata *metadata, size_t grp, + size_t blk) { if (WARN_ON(!metadata) || WARN_ON(grp >= metadata->grp_cnt) || WARN_ON(blk >= metadata->grp_metadata[grp].blk_cnt)) @@ -431,8 +427,9 @@ static inline size_t kbase_hwcnt_metadata_block_headers_count( * * Return: Number of counters in each instance of block blk in group grp. */ -static inline size_t kbase_hwcnt_metadata_block_counters_count( - const struct kbase_hwcnt_metadata *metadata, size_t grp, size_t blk) +static inline size_t +kbase_hwcnt_metadata_block_counters_count(const struct kbase_hwcnt_metadata *metadata, size_t grp, + size_t blk) { if (WARN_ON(!metadata) || WARN_ON(grp >= metadata->grp_cnt) || WARN_ON(blk >= metadata->grp_metadata[grp].blk_cnt)) @@ -449,8 +446,9 @@ static inline size_t kbase_hwcnt_metadata_block_counters_count( * * Return: enable map stride in each instance of block blk in group grp. */ -static inline size_t kbase_hwcnt_metadata_block_enable_map_stride( - const struct kbase_hwcnt_metadata *metadata, size_t grp, size_t blk) +static inline size_t +kbase_hwcnt_metadata_block_enable_map_stride(const struct kbase_hwcnt_metadata *metadata, + size_t grp, size_t blk) { if (WARN_ON(!metadata) || WARN_ON(grp >= metadata->grp_cnt) || WARN_ON(blk >= metadata->grp_metadata[grp].blk_cnt)) @@ -468,8 +466,9 @@ static inline size_t kbase_hwcnt_metadata_block_enable_map_stride( * Return: Number of headers plus counters in each instance of block blk * in group grp. */ -static inline size_t kbase_hwcnt_metadata_block_values_count( - const struct kbase_hwcnt_metadata *metadata, size_t grp, size_t blk) +static inline size_t +kbase_hwcnt_metadata_block_values_count(const struct kbase_hwcnt_metadata *metadata, size_t grp, + size_t blk) { if (WARN_ON(!metadata) || WARN_ON(grp >= metadata->grp_cnt) || WARN_ON(blk >= metadata->grp_metadata[grp].blk_cnt)) @@ -490,10 +489,13 @@ static inline size_t kbase_hwcnt_metadata_block_values_count( * Iteration order is group, then block, then block instance (i.e. linearly * through memory). */ -#define kbase_hwcnt_metadata_for_each_block(md, grp, blk, blk_inst) \ - for ((grp) = 0; (grp) < kbase_hwcnt_metadata_group_count((md)); (grp)++) \ - for ((blk) = 0; (blk) < kbase_hwcnt_metadata_block_count((md), (grp)); (blk)++) \ - for ((blk_inst) = 0; (blk_inst) < kbase_hwcnt_metadata_block_instance_count((md), (grp), (blk)); (blk_inst)++) +#define kbase_hwcnt_metadata_for_each_block(md, grp, blk, blk_inst) \ + for ((grp) = 0; (grp) < kbase_hwcnt_metadata_group_count((md)); (grp)++) \ + for ((blk) = 0; (blk) < kbase_hwcnt_metadata_block_count((md), (grp)); (blk)++) \ + for ((blk_inst) = 0; \ + (blk_inst) < \ + kbase_hwcnt_metadata_block_instance_count((md), (grp), (blk)); \ + (blk_inst)++) /** * kbase_hwcnt_metadata_block_avail_bit() - Get the bit index into the avail @@ -504,10 +506,9 @@ static inline size_t kbase_hwcnt_metadata_block_values_count( * * Return: The bit index into the avail mask for the block. */ -static inline size_t kbase_hwcnt_metadata_block_avail_bit( - const struct kbase_hwcnt_metadata *metadata, - size_t grp, - size_t blk) +static inline size_t +kbase_hwcnt_metadata_block_avail_bit(const struct kbase_hwcnt_metadata *metadata, size_t grp, + size_t blk) { if (WARN_ON(!metadata) || WARN_ON(grp >= metadata->grp_cnt) || WARN_ON(blk >= metadata->grp_metadata[grp].blk_cnt)) @@ -527,11 +528,9 @@ static inline size_t kbase_hwcnt_metadata_block_avail_bit( * * Return: true if the block instance is available, else false. */ -static inline bool kbase_hwcnt_metadata_block_instance_avail( - const struct kbase_hwcnt_metadata *metadata, - size_t grp, - size_t blk, - size_t blk_inst) +static inline bool +kbase_hwcnt_metadata_block_instance_avail(const struct kbase_hwcnt_metadata *metadata, size_t grp, + size_t blk, size_t blk_inst) { size_t bit; u64 mask; @@ -553,9 +552,8 @@ static inline bool kbase_hwcnt_metadata_block_instance_avail( * * Return: 0 on success, else error code. */ -int kbase_hwcnt_enable_map_alloc( - const struct kbase_hwcnt_metadata *metadata, - struct kbase_hwcnt_enable_map *enable_map); +int kbase_hwcnt_enable_map_alloc(const struct kbase_hwcnt_metadata *metadata, + struct kbase_hwcnt_enable_map *enable_map); /** * kbase_hwcnt_enable_map_free() - Free an enable map. @@ -577,9 +575,8 @@ void kbase_hwcnt_enable_map_free(struct kbase_hwcnt_enable_map *enable_map); * Return: u64* to the bitfield(s) used as the enable map for the * block instance. */ -static inline u64 * -kbase_hwcnt_enable_map_block_instance(const struct kbase_hwcnt_enable_map *map, - size_t grp, size_t blk, size_t blk_inst) +static inline u64 *kbase_hwcnt_enable_map_block_instance(const struct kbase_hwcnt_enable_map *map, + size_t grp, size_t blk, size_t blk_inst) { if (WARN_ON(!map) || WARN_ON(!map->hwcnt_enable_map)) return NULL; @@ -589,15 +586,9 @@ kbase_hwcnt_enable_map_block_instance(const struct kbase_hwcnt_enable_map *map, WARN_ON(blk_inst >= map->metadata->grp_metadata[grp].blk_metadata[blk].inst_cnt)) return map->hwcnt_enable_map; - return map->hwcnt_enable_map + - map->metadata->grp_metadata[grp].enable_map_index + - map->metadata->grp_metadata[grp] - .blk_metadata[blk] - .enable_map_index + - (map->metadata->grp_metadata[grp] - .blk_metadata[blk] - .enable_map_stride * - blk_inst); + return map->hwcnt_enable_map + map->metadata->grp_metadata[grp].enable_map_index + + map->metadata->grp_metadata[grp].blk_metadata[blk].enable_map_index + + (map->metadata->grp_metadata[grp].blk_metadata[blk].enable_map_stride * blk_inst); } /** @@ -609,8 +600,7 @@ kbase_hwcnt_enable_map_block_instance(const struct kbase_hwcnt_enable_map *map, */ static inline size_t kbase_hwcnt_bitfield_count(size_t val_cnt) { - return (val_cnt + KBASE_HWCNT_BITFIELD_BITS - 1) / - KBASE_HWCNT_BITFIELD_BITS; + return (val_cnt + KBASE_HWCNT_BITFIELD_BITS - 1) / KBASE_HWCNT_BITFIELD_BITS; } /** @@ -620,11 +610,8 @@ static inline size_t kbase_hwcnt_bitfield_count(size_t val_cnt) * @blk: Index of the block in the group. * @blk_inst: Index of the block instance in the block. */ -static inline void kbase_hwcnt_enable_map_block_disable_all( - struct kbase_hwcnt_enable_map *dst, - size_t grp, - size_t blk, - size_t blk_inst) +static inline void kbase_hwcnt_enable_map_block_disable_all(struct kbase_hwcnt_enable_map *dst, + size_t grp, size_t blk, size_t blk_inst) { size_t val_cnt; size_t bitfld_cnt; @@ -644,15 +631,13 @@ static inline void kbase_hwcnt_enable_map_block_disable_all( * kbase_hwcnt_enable_map_disable_all() - Disable all values in the enable map. * @dst: Non-NULL pointer to enable map to zero. */ -static inline void kbase_hwcnt_enable_map_disable_all( - struct kbase_hwcnt_enable_map *dst) +static inline void kbase_hwcnt_enable_map_disable_all(struct kbase_hwcnt_enable_map *dst) { if (WARN_ON(!dst) || WARN_ON(!dst->metadata)) return; if (dst->hwcnt_enable_map != NULL) - memset(dst->hwcnt_enable_map, 0, - dst->metadata->enable_map_bytes); + memset(dst->hwcnt_enable_map, 0, dst->metadata->enable_map_bytes); dst->clk_enable_map = 0; } @@ -664,11 +649,8 @@ static inline void kbase_hwcnt_enable_map_disable_all( * @blk: Index of the block in the group. * @blk_inst: Index of the block instance in the block. */ -static inline void kbase_hwcnt_enable_map_block_enable_all( - struct kbase_hwcnt_enable_map *dst, - size_t grp, - size_t blk, - size_t blk_inst) +static inline void kbase_hwcnt_enable_map_block_enable_all(struct kbase_hwcnt_enable_map *dst, + size_t grp, size_t blk, size_t blk_inst) { size_t val_cnt; size_t bitfld_cnt; @@ -683,8 +665,7 @@ static inline void kbase_hwcnt_enable_map_block_enable_all( bitfld_cnt = kbase_hwcnt_bitfield_count(val_cnt); for (bitfld_idx = 0; bitfld_idx < bitfld_cnt; bitfld_idx++) { - const u64 remaining_values = val_cnt - - (bitfld_idx * KBASE_HWCNT_BITFIELD_BITS); + const u64 remaining_values = val_cnt - (bitfld_idx * KBASE_HWCNT_BITFIELD_BITS); u64 block_enable_map_mask = U64_MAX; if (remaining_values < KBASE_HWCNT_BITFIELD_BITS) @@ -699,8 +680,7 @@ static inline void kbase_hwcnt_enable_map_block_enable_all( * map. * @dst: Non-NULL pointer to enable map. */ -static inline void kbase_hwcnt_enable_map_enable_all( - struct kbase_hwcnt_enable_map *dst) +static inline void kbase_hwcnt_enable_map_enable_all(struct kbase_hwcnt_enable_map *dst) { size_t grp, blk, blk_inst; @@ -708,8 +688,7 @@ static inline void kbase_hwcnt_enable_map_enable_all( return; kbase_hwcnt_metadata_for_each_block(dst->metadata, grp, blk, blk_inst) - kbase_hwcnt_enable_map_block_enable_all( - dst, grp, blk, blk_inst); + kbase_hwcnt_enable_map_block_enable_all(dst, grp, blk, blk_inst); dst->clk_enable_map = (1ull << dst->metadata->clk_cnt) - 1; } @@ -721,9 +700,8 @@ static inline void kbase_hwcnt_enable_map_enable_all( * * The dst and src MUST have been created from the same metadata. */ -static inline void kbase_hwcnt_enable_map_copy( - struct kbase_hwcnt_enable_map *dst, - const struct kbase_hwcnt_enable_map *src) +static inline void kbase_hwcnt_enable_map_copy(struct kbase_hwcnt_enable_map *dst, + const struct kbase_hwcnt_enable_map *src) { if (WARN_ON(!dst) || WARN_ON(!src) || WARN_ON(!dst->metadata) || WARN_ON(dst->metadata != src->metadata)) @@ -733,8 +711,7 @@ static inline void kbase_hwcnt_enable_map_copy( if (WARN_ON(!src->hwcnt_enable_map)) return; - memcpy(dst->hwcnt_enable_map, - src->hwcnt_enable_map, + memcpy(dst->hwcnt_enable_map, src->hwcnt_enable_map, dst->metadata->enable_map_bytes); } @@ -748,9 +725,8 @@ static inline void kbase_hwcnt_enable_map_copy( * * The dst and src MUST have been created from the same metadata. */ -static inline void kbase_hwcnt_enable_map_union( - struct kbase_hwcnt_enable_map *dst, - const struct kbase_hwcnt_enable_map *src) +static inline void kbase_hwcnt_enable_map_union(struct kbase_hwcnt_enable_map *dst, + const struct kbase_hwcnt_enable_map *src) { if (WARN_ON(!dst) || WARN_ON(!src) || WARN_ON(!dst->metadata) || WARN_ON(dst->metadata != src->metadata)) @@ -781,11 +757,9 @@ static inline void kbase_hwcnt_enable_map_union( * * Return: true if any values in the block are enabled, else false. */ -static inline bool kbase_hwcnt_enable_map_block_enabled( - const struct kbase_hwcnt_enable_map *enable_map, - size_t grp, - size_t blk, - size_t blk_inst) +static inline bool +kbase_hwcnt_enable_map_block_enabled(const struct kbase_hwcnt_enable_map *enable_map, size_t grp, + size_t blk, size_t blk_inst) { bool any_enabled = false; size_t val_cnt; @@ -801,15 +775,13 @@ static inline bool kbase_hwcnt_enable_map_block_enabled( bitfld_cnt = kbase_hwcnt_bitfield_count(val_cnt); for (bitfld_idx = 0; bitfld_idx < bitfld_cnt; bitfld_idx++) { - const u64 remaining_values = val_cnt - - (bitfld_idx * KBASE_HWCNT_BITFIELD_BITS); + const u64 remaining_values = val_cnt - (bitfld_idx * KBASE_HWCNT_BITFIELD_BITS); u64 block_enable_map_mask = U64_MAX; if (remaining_values < KBASE_HWCNT_BITFIELD_BITS) block_enable_map_mask = (1ull << remaining_values) - 1; - any_enabled = any_enabled || - (block_enable_map[bitfld_idx] & block_enable_map_mask); + any_enabled = any_enabled || (block_enable_map[bitfld_idx] & block_enable_map_mask); } return any_enabled; @@ -821,8 +793,8 @@ static inline bool kbase_hwcnt_enable_map_block_enabled( * * Return: true if any values are enabled, else false. */ -static inline bool kbase_hwcnt_enable_map_any_enabled( - const struct kbase_hwcnt_enable_map *enable_map) +static inline bool +kbase_hwcnt_enable_map_any_enabled(const struct kbase_hwcnt_enable_map *enable_map) { size_t grp, blk, blk_inst; u64 clk_enable_map_mask; @@ -832,14 +804,12 @@ static inline bool kbase_hwcnt_enable_map_any_enabled( clk_enable_map_mask = (1ull << enable_map->metadata->clk_cnt) - 1; - if (enable_map->metadata->clk_cnt > 0 && - (enable_map->clk_enable_map & clk_enable_map_mask)) + if (enable_map->metadata->clk_cnt > 0 && (enable_map->clk_enable_map & clk_enable_map_mask)) return true; - kbase_hwcnt_metadata_for_each_block( - enable_map->metadata, grp, blk, blk_inst) { - if (kbase_hwcnt_enable_map_block_enabled( - enable_map, grp, blk, blk_inst)) + kbase_hwcnt_metadata_for_each_block(enable_map->metadata, grp, blk, blk_inst) + { + if (kbase_hwcnt_enable_map_block_enabled(enable_map, grp, blk, blk_inst)) return true; } @@ -855,9 +825,7 @@ static inline bool kbase_hwcnt_enable_map_any_enabled( * * Return: true if the value was enabled, else false. */ -static inline bool kbase_hwcnt_enable_map_block_value_enabled( - const u64 *bitfld, - size_t val_idx) +static inline bool kbase_hwcnt_enable_map_block_value_enabled(const u64 *bitfld, size_t val_idx) { const size_t idx = val_idx / KBASE_HWCNT_BITFIELD_BITS; const size_t bit = val_idx % KBASE_HWCNT_BITFIELD_BITS; @@ -873,9 +841,7 @@ static inline bool kbase_hwcnt_enable_map_block_value_enabled( * kbase_hwcnt_enable_map_block_instance. * @val_idx: Index of the value to enable in the block instance. */ -static inline void kbase_hwcnt_enable_map_block_enable_value( - u64 *bitfld, - size_t val_idx) +static inline void kbase_hwcnt_enable_map_block_enable_value(u64 *bitfld, size_t val_idx) { const size_t idx = val_idx / KBASE_HWCNT_BITFIELD_BITS; const size_t bit = val_idx % KBASE_HWCNT_BITFIELD_BITS; @@ -891,9 +857,7 @@ static inline void kbase_hwcnt_enable_map_block_enable_value( * kbase_hwcnt_enable_map_block_instance. * @val_idx: Index of the value to disable in the block instance. */ -static inline void kbase_hwcnt_enable_map_block_disable_value( - u64 *bitfld, - size_t val_idx) +static inline void kbase_hwcnt_enable_map_block_disable_value(u64 *bitfld, size_t val_idx) { const size_t idx = val_idx / KBASE_HWCNT_BITFIELD_BITS; const size_t bit = val_idx % KBASE_HWCNT_BITFIELD_BITS; @@ -911,9 +875,8 @@ static inline void kbase_hwcnt_enable_map_block_disable_value( * * Return: 0 on success, else error code. */ -int kbase_hwcnt_dump_buffer_alloc( - const struct kbase_hwcnt_metadata *metadata, - struct kbase_hwcnt_dump_buffer *dump_buf); +int kbase_hwcnt_dump_buffer_alloc(const struct kbase_hwcnt_metadata *metadata, + struct kbase_hwcnt_dump_buffer *dump_buf); /** * kbase_hwcnt_dump_buffer_free() - Free a dump buffer. @@ -936,10 +899,8 @@ void kbase_hwcnt_dump_buffer_free(struct kbase_hwcnt_dump_buffer *dump_buf); * * Return: 0 on success, else error code. */ -int kbase_hwcnt_dump_buffer_array_alloc( - const struct kbase_hwcnt_metadata *metadata, - size_t n, - struct kbase_hwcnt_dump_buffer_array *dump_bufs); +int kbase_hwcnt_dump_buffer_array_alloc(const struct kbase_hwcnt_metadata *metadata, size_t n, + struct kbase_hwcnt_dump_buffer_array *dump_bufs); /** * kbase_hwcnt_dump_buffer_array_free() - Free a dump buffer array. @@ -948,8 +909,7 @@ int kbase_hwcnt_dump_buffer_array_alloc( * Can be safely called on an all-zeroed dump buffer array structure, or on an * already freed dump buffer array. */ -void kbase_hwcnt_dump_buffer_array_free( - struct kbase_hwcnt_dump_buffer_array *dump_bufs); +void kbase_hwcnt_dump_buffer_array_free(struct kbase_hwcnt_dump_buffer_array *dump_bufs); /** * kbase_hwcnt_dump_buffer_block_instance() - Get the pointer to a block @@ -961,9 +921,8 @@ void kbase_hwcnt_dump_buffer_array_free( * * Return: u64* to the dump buffer for the block instance. */ -static inline u64 *kbase_hwcnt_dump_buffer_block_instance( - const struct kbase_hwcnt_dump_buffer *buf, size_t grp, size_t blk, - size_t blk_inst) +static inline u64 *kbase_hwcnt_dump_buffer_block_instance(const struct kbase_hwcnt_dump_buffer *buf, + size_t grp, size_t blk, size_t blk_inst) { if (WARN_ON(!buf) || WARN_ON(!buf->dump_buf)) return NULL; @@ -975,10 +934,7 @@ static inline u64 *kbase_hwcnt_dump_buffer_block_instance( return buf->dump_buf + buf->metadata->grp_metadata[grp].dump_buf_index + buf->metadata->grp_metadata[grp].blk_metadata[blk].dump_buf_index + - (buf->metadata->grp_metadata[grp] - .blk_metadata[blk] - .dump_buf_stride * - blk_inst); + (buf->metadata->grp_metadata[grp].blk_metadata[blk].dump_buf_stride * blk_inst); } /** @@ -990,9 +946,8 @@ static inline u64 *kbase_hwcnt_dump_buffer_block_instance( * * The dst and dst_enable_map MUST have been created from the same metadata. */ -void kbase_hwcnt_dump_buffer_zero( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_enable_map *dst_enable_map); +void kbase_hwcnt_dump_buffer_zero(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_enable_map *dst_enable_map); /** * kbase_hwcnt_dump_buffer_block_zero() - Zero all values in a block. @@ -1000,8 +955,7 @@ void kbase_hwcnt_dump_buffer_zero( * kbase_hwcnt_dump_buffer_block_instance. * @val_cnt: Number of values in the block. */ -static inline void kbase_hwcnt_dump_buffer_block_zero(u64 *dst_blk, - size_t val_cnt) +static inline void kbase_hwcnt_dump_buffer_block_zero(u64 *dst_blk, size_t val_cnt) { if (WARN_ON(!dst_blk)) return; @@ -1017,8 +971,7 @@ static inline void kbase_hwcnt_dump_buffer_block_zero(u64 *dst_blk, * Slower than the non-strict variant. * @dst: Non-NULL pointer to dump buffer. */ -void kbase_hwcnt_dump_buffer_zero_strict( - struct kbase_hwcnt_dump_buffer *dst); +void kbase_hwcnt_dump_buffer_zero_strict(struct kbase_hwcnt_dump_buffer *dst); /** * kbase_hwcnt_dump_buffer_zero_non_enabled() - Zero all non-enabled values in @@ -1031,9 +984,8 @@ void kbase_hwcnt_dump_buffer_zero_strict( * * The dst and dst_enable_map MUST have been created from the same metadata. */ -void kbase_hwcnt_dump_buffer_zero_non_enabled( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_enable_map *dst_enable_map); +void kbase_hwcnt_dump_buffer_zero_non_enabled(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_enable_map *dst_enable_map); /** * kbase_hwcnt_dump_buffer_block_zero_non_enabled() - Zero all non-enabled @@ -1047,9 +999,8 @@ void kbase_hwcnt_dump_buffer_zero_non_enabled( * kbase_hwcnt_enable_map_block_instance. * @val_cnt: Number of values in the block. */ -static inline void -kbase_hwcnt_dump_buffer_block_zero_non_enabled(u64 *dst_blk, const u64 *blk_em, - size_t val_cnt) +static inline void kbase_hwcnt_dump_buffer_block_zero_non_enabled(u64 *dst_blk, const u64 *blk_em, + size_t val_cnt) { size_t val; @@ -1073,10 +1024,9 @@ kbase_hwcnt_dump_buffer_block_zero_non_enabled(u64 *dst_blk, const u64 *blk_em, * The dst, src, and dst_enable_map MUST have been created from the same * metadata. */ -void kbase_hwcnt_dump_buffer_copy( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_dump_buffer *src, - const struct kbase_hwcnt_enable_map *dst_enable_map); +void kbase_hwcnt_dump_buffer_copy(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_dump_buffer *src, + const struct kbase_hwcnt_enable_map *dst_enable_map); /** * kbase_hwcnt_dump_buffer_block_copy() - Copy all block values from src to dst. @@ -1086,8 +1036,7 @@ void kbase_hwcnt_dump_buffer_copy( * kbase_hwcnt_dump_buffer_block_instance. * @val_cnt: Number of values in the block. */ -static inline void kbase_hwcnt_dump_buffer_block_copy(u64 *dst_blk, - const u64 *src_blk, +static inline void kbase_hwcnt_dump_buffer_block_copy(u64 *dst_blk, const u64 *src_blk, size_t val_cnt) { if (WARN_ON(!dst_blk) || WARN_ON(!src_blk)) @@ -1113,10 +1062,9 @@ static inline void kbase_hwcnt_dump_buffer_block_copy(u64 *dst_blk, * The dst, src, and dst_enable_map MUST have been created from the same * metadata. */ -void kbase_hwcnt_dump_buffer_copy_strict( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_dump_buffer *src, - const struct kbase_hwcnt_enable_map *dst_enable_map); +void kbase_hwcnt_dump_buffer_copy_strict(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_dump_buffer *src, + const struct kbase_hwcnt_enable_map *dst_enable_map); /** * kbase_hwcnt_dump_buffer_block_copy_strict() - Copy all enabled block values @@ -1134,10 +1082,8 @@ void kbase_hwcnt_dump_buffer_copy_strict( * * After the copy, any disabled values in dst will be zero. */ -static inline void kbase_hwcnt_dump_buffer_block_copy_strict(u64 *dst_blk, - const u64 *src_blk, - const u64 *blk_em, - size_t val_cnt) +static inline void kbase_hwcnt_dump_buffer_block_copy_strict(u64 *dst_blk, const u64 *src_blk, + const u64 *blk_em, size_t val_cnt) { size_t val; @@ -1145,8 +1091,7 @@ static inline void kbase_hwcnt_dump_buffer_block_copy_strict(u64 *dst_blk, return; for (val = 0; val < val_cnt; val++) { - bool val_enabled = kbase_hwcnt_enable_map_block_value_enabled( - blk_em, val); + bool val_enabled = kbase_hwcnt_enable_map_block_value_enabled(blk_em, val); dst_blk[val] = val_enabled ? src_blk[val] : 0; } @@ -1165,10 +1110,9 @@ static inline void kbase_hwcnt_dump_buffer_block_copy_strict(u64 *dst_blk, * The dst, src, and dst_enable_map MUST have been created from the same * metadata. */ -void kbase_hwcnt_dump_buffer_accumulate( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_dump_buffer *src, - const struct kbase_hwcnt_enable_map *dst_enable_map); +void kbase_hwcnt_dump_buffer_accumulate(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_dump_buffer *src, + const struct kbase_hwcnt_enable_map *dst_enable_map); /** * kbase_hwcnt_dump_buffer_block_accumulate() - Copy all block headers and @@ -1181,10 +1125,8 @@ void kbase_hwcnt_dump_buffer_accumulate( * @hdr_cnt: Number of headers in the block. * @ctr_cnt: Number of counters in the block. */ -static inline void kbase_hwcnt_dump_buffer_block_accumulate(u64 *dst_blk, - const u64 *src_blk, - size_t hdr_cnt, - size_t ctr_cnt) +static inline void kbase_hwcnt_dump_buffer_block_accumulate(u64 *dst_blk, const u64 *src_blk, + size_t hdr_cnt, size_t ctr_cnt) { size_t ctr; @@ -1219,10 +1161,9 @@ static inline void kbase_hwcnt_dump_buffer_block_accumulate(u64 *dst_blk, * The dst, src, and dst_enable_map MUST have been created from the same * metadata. */ -void kbase_hwcnt_dump_buffer_accumulate_strict( - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_dump_buffer *src, - const struct kbase_hwcnt_enable_map *dst_enable_map); +void kbase_hwcnt_dump_buffer_accumulate_strict(struct kbase_hwcnt_dump_buffer *dst, + const struct kbase_hwcnt_dump_buffer *src, + const struct kbase_hwcnt_enable_map *dst_enable_map); /** * kbase_hwcnt_dump_buffer_block_accumulate_strict() - Copy all enabled block @@ -1241,21 +1182,19 @@ void kbase_hwcnt_dump_buffer_accumulate_strict( * @hdr_cnt: Number of headers in the block. * @ctr_cnt: Number of counters in the block. */ -static inline void kbase_hwcnt_dump_buffer_block_accumulate_strict( - u64 *dst_blk, const u64 *src_blk, const u64 *blk_em, size_t hdr_cnt, - size_t ctr_cnt) +static inline void kbase_hwcnt_dump_buffer_block_accumulate_strict(u64 *dst_blk, const u64 *src_blk, + const u64 *blk_em, + size_t hdr_cnt, size_t ctr_cnt) { size_t ctr; if (WARN_ON(!dst_blk) || WARN_ON(!src_blk)) return; - kbase_hwcnt_dump_buffer_block_copy_strict( - dst_blk, src_blk, blk_em, hdr_cnt); + kbase_hwcnt_dump_buffer_block_copy_strict(dst_blk, src_blk, blk_em, hdr_cnt); for (ctr = hdr_cnt; ctr < ctr_cnt + hdr_cnt; ctr++) { - bool ctr_enabled = kbase_hwcnt_enable_map_block_value_enabled( - blk_em, ctr); + bool ctr_enabled = kbase_hwcnt_enable_map_block_value_enabled(blk_em, ctr); if (ctr_enabled) dst_blk[ctr] += src_blk[ctr]; @@ -1270,8 +1209,7 @@ static inline void kbase_hwcnt_dump_buffer_block_accumulate_strict( * @md: Non-NULL pointer to metadata. * @clk: size_t variable used as clock iterator. */ -#define kbase_hwcnt_metadata_for_each_clock(md, clk) \ - for ((clk) = 0; (clk) < (md)->clk_cnt; (clk)++) +#define kbase_hwcnt_metadata_for_each_clock(md, clk) for ((clk) = 0; (clk) < (md)->clk_cnt; (clk)++) /** * kbase_hwcnt_clk_enable_map_enabled() - Check if the given index is enabled @@ -1281,8 +1219,7 @@ static inline void kbase_hwcnt_dump_buffer_block_accumulate_strict( * * Return: true if the index of the clock domain is enabled, else false. */ -static inline bool kbase_hwcnt_clk_enable_map_enabled( - const u64 clk_enable_map, const size_t index) +static inline bool kbase_hwcnt_clk_enable_map_enabled(const u64 clk_enable_map, const size_t index) { if (WARN_ON(index >= 64)) return false; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_virtualizer.c b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_virtualizer.c similarity index 75% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_virtualizer.c rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_virtualizer.c index 52ecb7bed03f..d618764d3b32 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_virtualizer.c +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_virtualizer.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2018, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 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 @@ -19,10 +19,10 @@ * */ -#include "mali_kbase_hwcnt_virtualizer.h" -#include "mali_kbase_hwcnt_accumulator.h" -#include "mali_kbase_hwcnt_context.h" -#include "mali_kbase_hwcnt_types.h" +#include "hwcnt/mali_kbase_hwcnt_virtualizer.h" +#include "hwcnt/mali_kbase_hwcnt_accumulator.h" +#include "hwcnt/mali_kbase_hwcnt_context.h" +#include "hwcnt/mali_kbase_hwcnt_types.h" #include #include @@ -75,8 +75,8 @@ struct kbase_hwcnt_virtualizer_client { u64 ts_start_ns; }; -const struct kbase_hwcnt_metadata *kbase_hwcnt_virtualizer_metadata( - struct kbase_hwcnt_virtualizer *hvirt) +const struct kbase_hwcnt_metadata * +kbase_hwcnt_virtualizer_metadata(struct kbase_hwcnt_virtualizer *hvirt) { if (!hvirt) return NULL; @@ -90,8 +90,7 @@ const struct kbase_hwcnt_metadata *kbase_hwcnt_virtualizer_metadata( * * Will safely free a client in any partial state of construction. */ -static void kbasep_hwcnt_virtualizer_client_free( - struct kbase_hwcnt_virtualizer_client *hvcli) +static void kbasep_hwcnt_virtualizer_client_free(struct kbase_hwcnt_virtualizer_client *hvcli) { if (!hvcli) return; @@ -110,9 +109,8 @@ static void kbasep_hwcnt_virtualizer_client_free( * * Return: 0 on success, else error code. */ -static int kbasep_hwcnt_virtualizer_client_alloc( - const struct kbase_hwcnt_metadata *metadata, - struct kbase_hwcnt_virtualizer_client **out_hvcli) +static int kbasep_hwcnt_virtualizer_client_alloc(const struct kbase_hwcnt_metadata *metadata, + struct kbase_hwcnt_virtualizer_client **out_hvcli) { int errcode; struct kbase_hwcnt_virtualizer_client *hvcli = NULL; @@ -145,9 +143,9 @@ error: * @hvcli: Non-NULL pointer to virtualizer client. * @dump_buf: Non-NULL pointer to dump buffer to accumulate from. */ -static void kbasep_hwcnt_virtualizer_client_accumulate( - struct kbase_hwcnt_virtualizer_client *hvcli, - const struct kbase_hwcnt_dump_buffer *dump_buf) +static void +kbasep_hwcnt_virtualizer_client_accumulate(struct kbase_hwcnt_virtualizer_client *hvcli, + const struct kbase_hwcnt_dump_buffer *dump_buf) { WARN_ON(!hvcli); WARN_ON(!dump_buf); @@ -155,12 +153,10 @@ static void kbasep_hwcnt_virtualizer_client_accumulate( if (hvcli->has_accum) { /* If already some accumulation, accumulate */ - kbase_hwcnt_dump_buffer_accumulate( - &hvcli->accum_buf, dump_buf, &hvcli->enable_map); + kbase_hwcnt_dump_buffer_accumulate(&hvcli->accum_buf, dump_buf, &hvcli->enable_map); } else { /* If no accumulation, copy */ - kbase_hwcnt_dump_buffer_copy( - &hvcli->accum_buf, dump_buf, &hvcli->enable_map); + kbase_hwcnt_dump_buffer_copy(&hvcli->accum_buf, dump_buf, &hvcli->enable_map); } hvcli->has_accum = true; } @@ -173,8 +169,7 @@ static void kbasep_hwcnt_virtualizer_client_accumulate( * * Will safely terminate the accumulator in any partial state of initialisation. */ -static void kbasep_hwcnt_virtualizer_accumulator_term( - struct kbase_hwcnt_virtualizer *hvirt) +static void kbasep_hwcnt_virtualizer_accumulator_term(struct kbase_hwcnt_virtualizer *hvirt) { WARN_ON(!hvirt); lockdep_assert_held(&hvirt->lock); @@ -194,8 +189,7 @@ static void kbasep_hwcnt_virtualizer_accumulator_term( * * Return: 0 on success, else error code. */ -static int kbasep_hwcnt_virtualizer_accumulator_init( - struct kbase_hwcnt_virtualizer *hvirt) +static int kbasep_hwcnt_virtualizer_accumulator_init(struct kbase_hwcnt_virtualizer *hvirt) { int errcode; @@ -204,18 +198,15 @@ static int kbasep_hwcnt_virtualizer_accumulator_init( WARN_ON(hvirt->client_count); WARN_ON(hvirt->accum); - errcode = kbase_hwcnt_accumulator_acquire( - hvirt->hctx, &hvirt->accum); + errcode = kbase_hwcnt_accumulator_acquire(hvirt->hctx, &hvirt->accum); if (errcode) goto error; - errcode = kbase_hwcnt_enable_map_alloc( - hvirt->metadata, &hvirt->scratch_map); + errcode = kbase_hwcnt_enable_map_alloc(hvirt->metadata, &hvirt->scratch_map); if (errcode) goto error; - errcode = kbase_hwcnt_dump_buffer_alloc( - hvirt->metadata, &hvirt->scratch_buf); + errcode = kbase_hwcnt_dump_buffer_alloc(hvirt->metadata, &hvirt->scratch_buf); if (errcode) goto error; @@ -234,10 +225,9 @@ error: * * Return: 0 on success, else error code. */ -static int kbasep_hwcnt_virtualizer_client_add( - struct kbase_hwcnt_virtualizer *hvirt, - struct kbase_hwcnt_virtualizer_client *hvcli, - const struct kbase_hwcnt_enable_map *enable_map) +static int kbasep_hwcnt_virtualizer_client_add(struct kbase_hwcnt_virtualizer *hvirt, + struct kbase_hwcnt_virtualizer_client *hvcli, + const struct kbase_hwcnt_enable_map *enable_map) { int errcode = 0; u64 ts_start_ns; @@ -258,28 +248,25 @@ static int kbasep_hwcnt_virtualizer_client_add( if (hvirt->client_count == 1) { /* First client, so just pass the enable map onwards as is */ - errcode = kbase_hwcnt_accumulator_set_counters(hvirt->accum, - enable_map, &ts_start_ns, &ts_end_ns, NULL); + errcode = kbase_hwcnt_accumulator_set_counters(hvirt->accum, enable_map, + &ts_start_ns, &ts_end_ns, NULL); } else { struct kbase_hwcnt_virtualizer_client *pos; /* Make the scratch enable map the union of all enable maps */ - kbase_hwcnt_enable_map_copy( - &hvirt->scratch_map, enable_map); - list_for_each_entry(pos, &hvirt->clients, node) - kbase_hwcnt_enable_map_union( - &hvirt->scratch_map, &pos->enable_map); + kbase_hwcnt_enable_map_copy(&hvirt->scratch_map, enable_map); + list_for_each_entry (pos, &hvirt->clients, node) + kbase_hwcnt_enable_map_union(&hvirt->scratch_map, &pos->enable_map); /* Set the counters with the new union enable map */ - errcode = kbase_hwcnt_accumulator_set_counters(hvirt->accum, - &hvirt->scratch_map, - &ts_start_ns, &ts_end_ns, - &hvirt->scratch_buf); + errcode = kbase_hwcnt_accumulator_set_counters(hvirt->accum, &hvirt->scratch_map, + &ts_start_ns, &ts_end_ns, + &hvirt->scratch_buf); /* Accumulate into only existing clients' accumulation bufs */ if (!errcode) - list_for_each_entry(pos, &hvirt->clients, node) - kbasep_hwcnt_virtualizer_client_accumulate( - pos, &hvirt->scratch_buf); + list_for_each_entry (pos, &hvirt->clients, node) + kbasep_hwcnt_virtualizer_client_accumulate(pos, + &hvirt->scratch_buf); } if (errcode) goto error; @@ -307,9 +294,8 @@ error: * @hvirt: Non-NULL pointer to the hardware counter virtualizer. * @hvcli: Non-NULL pointer to the virtualizer client to remove. */ -static void kbasep_hwcnt_virtualizer_client_remove( - struct kbase_hwcnt_virtualizer *hvirt, - struct kbase_hwcnt_virtualizer_client *hvcli) +static void kbasep_hwcnt_virtualizer_client_remove(struct kbase_hwcnt_virtualizer *hvirt, + struct kbase_hwcnt_virtualizer_client *hvcli) { int errcode = 0; u64 ts_start_ns; @@ -329,22 +315,21 @@ static void kbasep_hwcnt_virtualizer_client_remove( struct kbase_hwcnt_virtualizer_client *pos; /* Make the scratch enable map the union of all enable maps */ kbase_hwcnt_enable_map_disable_all(&hvirt->scratch_map); - list_for_each_entry(pos, &hvirt->clients, node) - kbase_hwcnt_enable_map_union( - &hvirt->scratch_map, &pos->enable_map); + list_for_each_entry (pos, &hvirt->clients, node) + kbase_hwcnt_enable_map_union(&hvirt->scratch_map, &pos->enable_map); /* Set the counters with the new union enable map */ - errcode = kbase_hwcnt_accumulator_set_counters(hvirt->accum, - &hvirt->scratch_map, - &ts_start_ns, &ts_end_ns, - &hvirt->scratch_buf); + errcode = kbase_hwcnt_accumulator_set_counters(hvirt->accum, &hvirt->scratch_map, + &ts_start_ns, &ts_end_ns, + &hvirt->scratch_buf); /* Accumulate into remaining clients' accumulation bufs */ - if (!errcode) - list_for_each_entry(pos, &hvirt->clients, node) - kbasep_hwcnt_virtualizer_client_accumulate( - pos, &hvirt->scratch_buf); + if (!errcode) { + list_for_each_entry (pos, &hvirt->clients, node) + kbasep_hwcnt_virtualizer_client_accumulate(pos, + &hvirt->scratch_buf); - /* Store the most recent dump time for rate limiting */ - hvirt->ts_last_dump_ns = ts_end_ns; + /* Store the most recent dump time for rate limiting */ + hvirt->ts_last_dump_ns = ts_end_ns; + } } WARN_ON(errcode); } @@ -370,11 +355,8 @@ static void kbasep_hwcnt_virtualizer_client_remove( * Return: 0 on success or error code. */ static int kbasep_hwcnt_virtualizer_client_set_counters( - struct kbase_hwcnt_virtualizer *hvirt, - struct kbase_hwcnt_virtualizer_client *hvcli, - const struct kbase_hwcnt_enable_map *enable_map, - u64 *ts_start_ns, - u64 *ts_end_ns, + struct kbase_hwcnt_virtualizer *hvirt, struct kbase_hwcnt_virtualizer_client *hvcli, + const struct kbase_hwcnt_enable_map *enable_map, u64 *ts_start_ns, u64 *ts_end_ns, struct kbase_hwcnt_dump_buffer *dump_buf) { int errcode; @@ -391,32 +373,29 @@ static int kbasep_hwcnt_virtualizer_client_set_counters( /* Make the scratch enable map the union of all enable maps */ kbase_hwcnt_enable_map_copy(&hvirt->scratch_map, enable_map); - list_for_each_entry(pos, &hvirt->clients, node) + list_for_each_entry (pos, &hvirt->clients, node) /* Ignore the enable map of the selected client */ if (pos != hvcli) - kbase_hwcnt_enable_map_union( - &hvirt->scratch_map, &pos->enable_map); + kbase_hwcnt_enable_map_union(&hvirt->scratch_map, &pos->enable_map); /* Set the counters with the new union enable map */ - errcode = kbase_hwcnt_accumulator_set_counters(hvirt->accum, - &hvirt->scratch_map, ts_start_ns, ts_end_ns, - &hvirt->scratch_buf); + errcode = kbase_hwcnt_accumulator_set_counters(hvirt->accum, &hvirt->scratch_map, + ts_start_ns, ts_end_ns, &hvirt->scratch_buf); if (errcode) return errcode; /* Accumulate into all accumulation bufs except the selected client's */ - list_for_each_entry(pos, &hvirt->clients, node) + list_for_each_entry (pos, &hvirt->clients, node) if (pos != hvcli) - kbasep_hwcnt_virtualizer_client_accumulate( - pos, &hvirt->scratch_buf); + kbasep_hwcnt_virtualizer_client_accumulate(pos, &hvirt->scratch_buf); /* Finally, write into the dump buf */ if (dump_buf) { const struct kbase_hwcnt_dump_buffer *src = &hvirt->scratch_buf; if (hvcli->has_accum) { - kbase_hwcnt_dump_buffer_accumulate( - &hvcli->accum_buf, src, &hvcli->enable_map); + kbase_hwcnt_dump_buffer_accumulate(&hvcli->accum_buf, src, + &hvcli->enable_map); src = &hvcli->accum_buf; } kbase_hwcnt_dump_buffer_copy(dump_buf, src, &hvcli->enable_map); @@ -436,12 +415,10 @@ static int kbasep_hwcnt_virtualizer_client_set_counters( return errcode; } -int kbase_hwcnt_virtualizer_client_set_counters( - struct kbase_hwcnt_virtualizer_client *hvcli, - const struct kbase_hwcnt_enable_map *enable_map, - u64 *ts_start_ns, - u64 *ts_end_ns, - struct kbase_hwcnt_dump_buffer *dump_buf) +int kbase_hwcnt_virtualizer_client_set_counters(struct kbase_hwcnt_virtualizer_client *hvcli, + const struct kbase_hwcnt_enable_map *enable_map, + u64 *ts_start_ns, u64 *ts_end_ns, + struct kbase_hwcnt_dump_buffer *dump_buf) { int errcode; struct kbase_hwcnt_virtualizer *hvirt; @@ -464,14 +441,12 @@ int kbase_hwcnt_virtualizer_client_set_counters( * to the accumulator, saving a fair few copies and * accumulations. */ - errcode = kbase_hwcnt_accumulator_set_counters( - hvirt->accum, enable_map, - ts_start_ns, ts_end_ns, dump_buf); + errcode = kbase_hwcnt_accumulator_set_counters(hvirt->accum, enable_map, + ts_start_ns, ts_end_ns, dump_buf); if (!errcode) { /* Update the selected client's enable map */ - kbase_hwcnt_enable_map_copy( - &hvcli->enable_map, enable_map); + kbase_hwcnt_enable_map_copy(&hvcli->enable_map, enable_map); /* Fix up the timestamps */ *ts_start_ns = hvcli->ts_start_ns; @@ -483,8 +458,7 @@ int kbase_hwcnt_virtualizer_client_set_counters( } else { /* Otherwise, do the full virtualize */ errcode = kbasep_hwcnt_virtualizer_client_set_counters( - hvirt, hvcli, enable_map, - ts_start_ns, ts_end_ns, dump_buf); + hvirt, hvcli, enable_map, ts_start_ns, ts_end_ns, dump_buf); } mutex_unlock(&hvirt->lock); @@ -507,12 +481,10 @@ int kbase_hwcnt_virtualizer_client_set_counters( * * Return: 0 on success or error code. */ -static int kbasep_hwcnt_virtualizer_client_dump( - struct kbase_hwcnt_virtualizer *hvirt, - struct kbase_hwcnt_virtualizer_client *hvcli, - u64 *ts_start_ns, - u64 *ts_end_ns, - struct kbase_hwcnt_dump_buffer *dump_buf) +static int kbasep_hwcnt_virtualizer_client_dump(struct kbase_hwcnt_virtualizer *hvirt, + struct kbase_hwcnt_virtualizer_client *hvcli, + u64 *ts_start_ns, u64 *ts_end_ns, + struct kbase_hwcnt_dump_buffer *dump_buf) { int errcode; struct kbase_hwcnt_virtualizer_client *pos; @@ -525,24 +497,23 @@ static int kbasep_hwcnt_virtualizer_client_dump( lockdep_assert_held(&hvirt->lock); /* Perform the dump */ - errcode = kbase_hwcnt_accumulator_dump(hvirt->accum, - ts_start_ns, ts_end_ns, &hvirt->scratch_buf); + errcode = kbase_hwcnt_accumulator_dump(hvirt->accum, ts_start_ns, ts_end_ns, + &hvirt->scratch_buf); if (errcode) return errcode; /* Accumulate into all accumulation bufs except the selected client's */ - list_for_each_entry(pos, &hvirt->clients, node) + list_for_each_entry (pos, &hvirt->clients, node) if (pos != hvcli) - kbasep_hwcnt_virtualizer_client_accumulate( - pos, &hvirt->scratch_buf); + kbasep_hwcnt_virtualizer_client_accumulate(pos, &hvirt->scratch_buf); /* Finally, write into the dump buf */ if (dump_buf) { const struct kbase_hwcnt_dump_buffer *src = &hvirt->scratch_buf; if (hvcli->has_accum) { - kbase_hwcnt_dump_buffer_accumulate( - &hvcli->accum_buf, src, &hvcli->enable_map); + kbase_hwcnt_dump_buffer_accumulate(&hvcli->accum_buf, src, + &hvcli->enable_map); src = &hvcli->accum_buf; } kbase_hwcnt_dump_buffer_copy(dump_buf, src, &hvcli->enable_map); @@ -578,11 +549,8 @@ static int kbasep_hwcnt_virtualizer_client_dump( * Return: 0 on success or error code. */ static int kbasep_hwcnt_virtualizer_client_dump_rate_limited( - struct kbase_hwcnt_virtualizer *hvirt, - struct kbase_hwcnt_virtualizer_client *hvcli, - u64 *ts_start_ns, - u64 *ts_end_ns, - struct kbase_hwcnt_dump_buffer *dump_buf) + struct kbase_hwcnt_virtualizer *hvirt, struct kbase_hwcnt_virtualizer_client *hvcli, + u64 *ts_start_ns, u64 *ts_end_ns, struct kbase_hwcnt_dump_buffer *dump_buf) { bool rate_limited = true; @@ -602,10 +570,8 @@ static int kbasep_hwcnt_virtualizer_client_dump_rate_limited( */ rate_limited = false; } else { - const u64 ts_ns = - kbase_hwcnt_accumulator_timestamp_ns(hvirt->accum); - const u64 time_since_last_dump_ns = - ts_ns - hvirt->ts_last_dump_ns; + const u64 ts_ns = kbase_hwcnt_accumulator_timestamp_ns(hvirt->accum); + const u64 time_since_last_dump_ns = ts_ns - hvirt->ts_last_dump_ns; /* Dump period equals or exceeds the threshold */ if (time_since_last_dump_ns >= hvirt->dump_threshold_ns) @@ -613,8 +579,8 @@ static int kbasep_hwcnt_virtualizer_client_dump_rate_limited( } if (!rate_limited) - return kbasep_hwcnt_virtualizer_client_dump( - hvirt, hvcli, ts_start_ns, ts_end_ns, dump_buf); + return kbasep_hwcnt_virtualizer_client_dump(hvirt, hvcli, ts_start_ns, ts_end_ns, + dump_buf); /* If we've gotten this far, the client must have something accumulated * otherwise it is a logic error @@ -622,8 +588,7 @@ static int kbasep_hwcnt_virtualizer_client_dump_rate_limited( WARN_ON(!hvcli->has_accum); if (dump_buf) - kbase_hwcnt_dump_buffer_copy( - dump_buf, &hvcli->accum_buf, &hvcli->enable_map); + kbase_hwcnt_dump_buffer_copy(dump_buf, &hvcli->accum_buf, &hvcli->enable_map); hvcli->has_accum = false; *ts_start_ns = hvcli->ts_start_ns; @@ -633,11 +598,9 @@ static int kbasep_hwcnt_virtualizer_client_dump_rate_limited( return 0; } -int kbase_hwcnt_virtualizer_client_dump( - struct kbase_hwcnt_virtualizer_client *hvcli, - u64 *ts_start_ns, - u64 *ts_end_ns, - struct kbase_hwcnt_dump_buffer *dump_buf) +int kbase_hwcnt_virtualizer_client_dump(struct kbase_hwcnt_virtualizer_client *hvcli, + u64 *ts_start_ns, u64 *ts_end_ns, + struct kbase_hwcnt_dump_buffer *dump_buf) { int errcode; struct kbase_hwcnt_virtualizer *hvirt; @@ -659,8 +622,8 @@ int kbase_hwcnt_virtualizer_client_dump( * to the accumulator, saving a fair few copies and * accumulations. */ - errcode = kbase_hwcnt_accumulator_dump( - hvirt->accum, ts_start_ns, ts_end_ns, dump_buf); + errcode = kbase_hwcnt_accumulator_dump(hvirt->accum, ts_start_ns, ts_end_ns, + dump_buf); if (!errcode) { /* Fix up the timestamps */ @@ -681,20 +644,17 @@ int kbase_hwcnt_virtualizer_client_dump( return errcode; } -int kbase_hwcnt_virtualizer_client_create( - struct kbase_hwcnt_virtualizer *hvirt, - const struct kbase_hwcnt_enable_map *enable_map, - struct kbase_hwcnt_virtualizer_client **out_hvcli) +int kbase_hwcnt_virtualizer_client_create(struct kbase_hwcnt_virtualizer *hvirt, + const struct kbase_hwcnt_enable_map *enable_map, + struct kbase_hwcnt_virtualizer_client **out_hvcli) { int errcode; struct kbase_hwcnt_virtualizer_client *hvcli; - if (!hvirt || !enable_map || !out_hvcli || - (enable_map->metadata != hvirt->metadata)) + if (!hvirt || !enable_map || !out_hvcli || (enable_map->metadata != hvirt->metadata)) return -EINVAL; - errcode = kbasep_hwcnt_virtualizer_client_alloc( - hvirt->metadata, &hvcli); + errcode = kbasep_hwcnt_virtualizer_client_alloc(hvirt->metadata, &hvcli); if (errcode) return errcode; @@ -713,8 +673,7 @@ int kbase_hwcnt_virtualizer_client_create( return 0; } -void kbase_hwcnt_virtualizer_client_destroy( - struct kbase_hwcnt_virtualizer_client *hvcli) +void kbase_hwcnt_virtualizer_client_destroy(struct kbase_hwcnt_virtualizer_client *hvcli) { if (!hvcli) return; @@ -728,10 +687,8 @@ void kbase_hwcnt_virtualizer_client_destroy( kbasep_hwcnt_virtualizer_client_free(hvcli); } -int kbase_hwcnt_virtualizer_init( - struct kbase_hwcnt_context *hctx, - u64 dump_threshold_ns, - struct kbase_hwcnt_virtualizer **out_hvirt) +int kbase_hwcnt_virtualizer_init(struct kbase_hwcnt_context *hctx, u64 dump_threshold_ns, + struct kbase_hwcnt_virtualizer **out_hvirt) { struct kbase_hwcnt_virtualizer *virt; const struct kbase_hwcnt_metadata *metadata; @@ -758,8 +715,7 @@ int kbase_hwcnt_virtualizer_init( return 0; } -void kbase_hwcnt_virtualizer_term( - struct kbase_hwcnt_virtualizer *hvirt) +void kbase_hwcnt_virtualizer_term(struct kbase_hwcnt_virtualizer *hvirt) { if (!hvirt) return; @@ -768,7 +724,7 @@ void kbase_hwcnt_virtualizer_term( if (WARN_ON(hvirt->client_count != 0)) { struct kbase_hwcnt_virtualizer_client *pos, *n; - list_for_each_entry_safe(pos, n, &hvirt->clients, node) + list_for_each_entry_safe (pos, n, &hvirt->clients, node) kbase_hwcnt_virtualizer_client_destroy(pos); } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_virtualizer.h b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_virtualizer.h similarity index 83% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_virtualizer.h rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_virtualizer.h index 08e8e9f1d596..485ba74960f6 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_virtualizer.h +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_virtualizer.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2018, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 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 @@ -51,17 +51,14 @@ struct kbase_hwcnt_dump_buffer; * * Return: 0 on success, else error code. */ -int kbase_hwcnt_virtualizer_init( - struct kbase_hwcnt_context *hctx, - u64 dump_threshold_ns, - struct kbase_hwcnt_virtualizer **out_hvirt); +int kbase_hwcnt_virtualizer_init(struct kbase_hwcnt_context *hctx, u64 dump_threshold_ns, + struct kbase_hwcnt_virtualizer **out_hvirt); /** * kbase_hwcnt_virtualizer_term - Terminate a hardware counter virtualizer. * @hvirt: Pointer to virtualizer to be terminated. */ -void kbase_hwcnt_virtualizer_term( - struct kbase_hwcnt_virtualizer *hvirt); +void kbase_hwcnt_virtualizer_term(struct kbase_hwcnt_virtualizer *hvirt); /** * kbase_hwcnt_virtualizer_metadata - Get the hardware counter metadata used by @@ -71,8 +68,8 @@ void kbase_hwcnt_virtualizer_term( * * Return: Non-NULL pointer to metadata, or NULL on error. */ -const struct kbase_hwcnt_metadata *kbase_hwcnt_virtualizer_metadata( - struct kbase_hwcnt_virtualizer *hvirt); +const struct kbase_hwcnt_metadata * +kbase_hwcnt_virtualizer_metadata(struct kbase_hwcnt_virtualizer *hvirt); /** * kbase_hwcnt_virtualizer_client_create - Create a new virtualizer client. @@ -84,17 +81,15 @@ const struct kbase_hwcnt_metadata *kbase_hwcnt_virtualizer_metadata( * * Return: 0 on success, else error code. */ -int kbase_hwcnt_virtualizer_client_create( - struct kbase_hwcnt_virtualizer *hvirt, - const struct kbase_hwcnt_enable_map *enable_map, - struct kbase_hwcnt_virtualizer_client **out_hvcli); +int kbase_hwcnt_virtualizer_client_create(struct kbase_hwcnt_virtualizer *hvirt, + const struct kbase_hwcnt_enable_map *enable_map, + struct kbase_hwcnt_virtualizer_client **out_hvcli); /** * kbase_hwcnt_virtualizer_client_destroy() - Destroy a virtualizer client. * @hvcli: Pointer to the hardware counter client. */ -void kbase_hwcnt_virtualizer_client_destroy( - struct kbase_hwcnt_virtualizer_client *hvcli); +void kbase_hwcnt_virtualizer_client_destroy(struct kbase_hwcnt_virtualizer_client *hvcli); /** * kbase_hwcnt_virtualizer_client_set_counters - Perform a dump of the client's @@ -115,12 +110,10 @@ void kbase_hwcnt_virtualizer_client_destroy( * * Return: 0 on success or error code. */ -int kbase_hwcnt_virtualizer_client_set_counters( - struct kbase_hwcnt_virtualizer_client *hvcli, - const struct kbase_hwcnt_enable_map *enable_map, - u64 *ts_start_ns, - u64 *ts_end_ns, - struct kbase_hwcnt_dump_buffer *dump_buf); +int kbase_hwcnt_virtualizer_client_set_counters(struct kbase_hwcnt_virtualizer_client *hvcli, + const struct kbase_hwcnt_enable_map *enable_map, + u64 *ts_start_ns, u64 *ts_end_ns, + struct kbase_hwcnt_dump_buffer *dump_buf); /** * kbase_hwcnt_virtualizer_client_dump - Perform a dump of the client's @@ -136,11 +129,9 @@ int kbase_hwcnt_virtualizer_client_set_counters( * * Return: 0 on success or error code. */ -int kbase_hwcnt_virtualizer_client_dump( - struct kbase_hwcnt_virtualizer_client *hvcli, - u64 *ts_start_ns, - u64 *ts_end_ns, - struct kbase_hwcnt_dump_buffer *dump_buf); +int kbase_hwcnt_virtualizer_client_dump(struct kbase_hwcnt_virtualizer_client *hvcli, + u64 *ts_start_ns, u64 *ts_end_ns, + struct kbase_hwcnt_dump_buffer *dump_buf); /** * kbase_hwcnt_virtualizer_queue_work() - Queue hardware counter related async diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_watchdog_if.h b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_watchdog_if.h similarity index 84% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_watchdog_if.h rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_watchdog_if.h index 187331866428..501c0087b7e6 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_watchdog_if.h +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_watchdog_if.h @@ -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 @@ -50,17 +50,17 @@ typedef void kbase_hwcnt_watchdog_callback_fn(void *user_data); * * Return: 0 if the watchdog timer enabled successfully, error code otherwise. */ -typedef int kbase_hwcnt_watchdog_enable_fn( - const struct kbase_hwcnt_watchdog_info *timer, u32 period_ms, - kbase_hwcnt_watchdog_callback_fn *callback, void *user_data); +typedef int kbase_hwcnt_watchdog_enable_fn(const struct kbase_hwcnt_watchdog_info *timer, + u32 period_ms, + kbase_hwcnt_watchdog_callback_fn *callback, + void *user_data); /** * typedef kbase_hwcnt_watchdog_disable_fn - Disable watchdog timer * * @timer: Non-NULL pointer to a watchdog timer interface context */ -typedef void -kbase_hwcnt_watchdog_disable_fn(const struct kbase_hwcnt_watchdog_info *timer); +typedef void kbase_hwcnt_watchdog_disable_fn(const struct kbase_hwcnt_watchdog_info *timer); /** * typedef kbase_hwcnt_watchdog_modify_fn - Modify watchdog timer's timeout @@ -68,9 +68,8 @@ kbase_hwcnt_watchdog_disable_fn(const struct kbase_hwcnt_watchdog_info *timer); * @timer: Non-NULL pointer to a watchdog timer interface context * @delay_ms: Watchdog timer expiration in milliseconds */ -typedef void -kbase_hwcnt_watchdog_modify_fn(const struct kbase_hwcnt_watchdog_info *timer, - u32 delay_ms); +typedef void kbase_hwcnt_watchdog_modify_fn(const struct kbase_hwcnt_watchdog_info *timer, + u32 delay_ms); /** * struct kbase_hwcnt_watchdog_interface - Hardware counter watchdog virtual interface. diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_watchdog_if_timer.c b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_watchdog_if_timer.c similarity index 76% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_watchdog_if_timer.c rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_watchdog_if_timer.c index 69b957adc4dd..4caa832cd587 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_watchdog_if_timer.c +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_watchdog_if_timer.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 @@ -20,8 +20,8 @@ */ #include "mali_kbase.h" -#include "mali_kbase_hwcnt_watchdog_if.h" -#include "mali_kbase_hwcnt_watchdog_if_timer.h" +#include "hwcnt/mali_kbase_hwcnt_watchdog_if.h" +#include "hwcnt/mali_kbase_hwcnt_watchdog_if_timer.h" #include #include @@ -62,12 +62,10 @@ static void kbasep_hwcnt_watchdog_callback(struct work_struct *const work) } static int kbasep_hwcnt_watchdog_if_timer_enable( - const struct kbase_hwcnt_watchdog_info *const timer, - u32 const period_ms, kbase_hwcnt_watchdog_callback_fn *const callback, - void *const user_data) + const struct kbase_hwcnt_watchdog_info *const timer, u32 const period_ms, + kbase_hwcnt_watchdog_callback_fn *const callback, void *const user_data) { - struct kbase_hwcnt_watchdog_if_timer_info *const timer_info = - (void *)timer; + struct kbase_hwcnt_watchdog_if_timer_info *const timer_info = (void *)timer; if (WARN_ON(!timer) || WARN_ON(!callback) || WARN_ON(timer_info->timer_enabled)) return -EINVAL; @@ -81,11 +79,10 @@ static int kbasep_hwcnt_watchdog_if_timer_enable( return 0; } -static void kbasep_hwcnt_watchdog_if_timer_disable( - const struct kbase_hwcnt_watchdog_info *const timer) +static void +kbasep_hwcnt_watchdog_if_timer_disable(const struct kbase_hwcnt_watchdog_info *const timer) { - struct kbase_hwcnt_watchdog_if_timer_info *const timer_info = - (void *)timer; + struct kbase_hwcnt_watchdog_if_timer_info *const timer_info = (void *)timer; if (WARN_ON(!timer)) return; @@ -97,11 +94,11 @@ static void kbasep_hwcnt_watchdog_if_timer_disable( timer_info->timer_enabled = false; } -static void kbasep_hwcnt_watchdog_if_timer_modify( - const struct kbase_hwcnt_watchdog_info *const timer, u32 const delay_ms) +static void +kbasep_hwcnt_watchdog_if_timer_modify(const struct kbase_hwcnt_watchdog_info *const timer, + u32 const delay_ms) { - struct kbase_hwcnt_watchdog_if_timer_info *const timer_info = - (void *)timer; + struct kbase_hwcnt_watchdog_if_timer_info *const timer_info = (void *)timer; if (WARN_ON(!timer) || WARN_ON(!timer_info->timer_enabled)) return; @@ -109,8 +106,7 @@ static void kbasep_hwcnt_watchdog_if_timer_modify( mod_delayed_work(timer_info->workq, &timer_info->dwork, msecs_to_jiffies(delay_ms)); } -void kbase_hwcnt_watchdog_if_timer_destroy( - struct kbase_hwcnt_watchdog_interface *const watchdog_if) +void kbase_hwcnt_watchdog_if_timer_destroy(struct kbase_hwcnt_watchdog_interface *const watchdog_if) { struct kbase_hwcnt_watchdog_if_timer_info *timer_info; @@ -125,11 +121,12 @@ void kbase_hwcnt_watchdog_if_timer_destroy( destroy_workqueue(timer_info->workq); kfree(timer_info); - *watchdog_if = (struct kbase_hwcnt_watchdog_interface){ NULL }; + *watchdog_if = (struct kbase_hwcnt_watchdog_interface){ + .timer = NULL, .enable = NULL, .disable = NULL, .modify = NULL + }; } -int kbase_hwcnt_watchdog_if_timer_create( - struct kbase_hwcnt_watchdog_interface *const watchdog_if) +int kbase_hwcnt_watchdog_if_timer_create(struct kbase_hwcnt_watchdog_interface *const watchdog_if) { struct kbase_hwcnt_watchdog_if_timer_info *timer_info; @@ -140,9 +137,7 @@ int kbase_hwcnt_watchdog_if_timer_create( if (!timer_info) return -ENOMEM; - *timer_info = - (struct kbase_hwcnt_watchdog_if_timer_info){ .timer_enabled = - false }; + *timer_info = (struct kbase_hwcnt_watchdog_if_timer_info){ .timer_enabled = false }; INIT_DELAYED_WORK(&timer_info->dwork, kbasep_hwcnt_watchdog_callback); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_watchdog_if_timer.h b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_watchdog_if_timer.h similarity index 85% rename from drivers/gpu/arm/bifrost/mali_kbase_hwcnt_watchdog_if_timer.h rename to drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_watchdog_if_timer.h index 3bd69c3401c4..a545ad3e39e3 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hwcnt_watchdog_if_timer.h +++ b/drivers/gpu/arm/bifrost/hwcnt/mali_kbase_hwcnt_watchdog_if_timer.h @@ -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 @@ -35,8 +35,7 @@ struct kbase_hwcnt_watchdog_interface; * * Return: 0 on success, error otherwise. */ -int kbase_hwcnt_watchdog_if_timer_create( - struct kbase_hwcnt_watchdog_interface *watchdog_if); +int kbase_hwcnt_watchdog_if_timer_create(struct kbase_hwcnt_watchdog_interface *watchdog_if); /** * kbase_hwcnt_watchdog_if_timer_destroy() - Destroy a watchdog interface of hardware counter @@ -44,7 +43,6 @@ int kbase_hwcnt_watchdog_if_timer_create( * * @watchdog_if: Pointer to watchdog interface to destroy */ -void kbase_hwcnt_watchdog_if_timer_destroy( - struct kbase_hwcnt_watchdog_interface *watchdog_if); +void kbase_hwcnt_watchdog_if_timer_destroy(struct kbase_hwcnt_watchdog_interface *watchdog_if); #endif /* _KBASE_HWCNT_WATCHDOG_IF_TIMER_H_ */ diff --git a/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_common_jm.h b/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_common_jm.h index 4479a4b8665f..6089610847b4 100644 --- a/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_common_jm.h +++ b/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_common_jm.h @@ -23,8 +23,8 @@ #define _KBASE_IPA_COUNTER_COMMON_JM_H_ #include "mali_kbase.h" -#include "mali_kbase_hwcnt_virtualizer.h" -#include "mali_kbase_hwcnt_types.h" +#include "hwcnt/mali_kbase_hwcnt_virtualizer.h" +#include "hwcnt/mali_kbase_hwcnt_types.h" /* Maximum number of IPA groups for an IPA model. */ #define KBASE_IPA_MAX_GROUP_DEF_NUM 16 diff --git a/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_csf.c b/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_csf.c index 66e56e267e68..43cdf18a5e3b 100644 --- a/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_csf.c +++ b/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_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 @@ -59,9 +59,6 @@ .counter_block_type = block_type, \ } -#define CSHW_COUNTER_DEF(cnt_name, coeff, cnt_idx) \ - COUNTER_DEF(cnt_name, coeff, cnt_idx, KBASE_IPA_CORE_TYPE_CSHW) - #define MEMSYS_COUNTER_DEF(cnt_name, coeff, cnt_idx) \ COUNTER_DEF(cnt_name, coeff, cnt_idx, KBASE_IPA_CORE_TYPE_MEMSYS) diff --git a/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_jm.c b/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_jm.c index 4bb880e79b4a..a32a2c207163 100644 --- a/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_jm.c +++ b/drivers/gpu/arm/bifrost/ipa/backend/mali_kbase_ipa_counter_jm.c @@ -30,21 +30,15 @@ /* Performance counter blocks base offsets */ #define JM_BASE (0 * KBASE_IPA_NR_BYTES_PER_BLOCK) -#define TILER_BASE (1 * KBASE_IPA_NR_BYTES_PER_BLOCK) #define MEMSYS_BASE (2 * KBASE_IPA_NR_BYTES_PER_BLOCK) /* JM counter block offsets */ #define JM_GPU_ACTIVE (KBASE_IPA_NR_BYTES_PER_CNT * 6) -/* Tiler counter block offsets */ -#define TILER_ACTIVE (KBASE_IPA_NR_BYTES_PER_CNT * 45) - /* MEMSYS counter block offsets */ #define MEMSYS_L2_ANY_LOOKUP (KBASE_IPA_NR_BYTES_PER_CNT * 25) /* SC counter block offsets */ -#define SC_FRAG_ACTIVE (KBASE_IPA_NR_BYTES_PER_CNT * 4) -#define SC_EXEC_CORE_ACTIVE (KBASE_IPA_NR_BYTES_PER_CNT * 26) #define SC_EXEC_INSTR_FMA (KBASE_IPA_NR_BYTES_PER_CNT * 27) #define SC_EXEC_INSTR_COUNT (KBASE_IPA_NR_BYTES_PER_CNT * 28) #define SC_EXEC_INSTR_MSG (KBASE_IPA_NR_BYTES_PER_CNT * 30) @@ -52,10 +46,6 @@ #define SC_TEX_COORD_ISSUE (KBASE_IPA_NR_BYTES_PER_CNT * 40) #define SC_TEX_TFCH_NUM_OPERATIONS (KBASE_IPA_NR_BYTES_PER_CNT * 42) #define SC_VARY_INSTR (KBASE_IPA_NR_BYTES_PER_CNT * 49) -#define SC_VARY_SLOT_32 (KBASE_IPA_NR_BYTES_PER_CNT * 50) -#define SC_VARY_SLOT_16 (KBASE_IPA_NR_BYTES_PER_CNT * 51) -#define SC_BEATS_RD_LSC (KBASE_IPA_NR_BYTES_PER_CNT * 56) -#define SC_BEATS_WR_LSC (KBASE_IPA_NR_BYTES_PER_CNT * 61) #define SC_BEATS_WR_TIB (KBASE_IPA_NR_BYTES_PER_CNT * 62) /** diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h index f722f5fadff9..c875ffb4990e 100644 --- a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2016-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 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 @@ -271,7 +271,6 @@ int kbase_get_real_power(struct devfreq *df, u32 *power, unsigned long freq, unsigned long voltage); -#if MALI_UNIT_TEST /* Called by kbase_get_real_power() to invoke the power models. * Must be called with kbdev->ipa.lock held. * This function is only exposed for use by unit tests. @@ -279,7 +278,6 @@ int kbase_get_real_power(struct devfreq *df, u32 *power, int kbase_get_real_power_locked(struct kbase_device *kbdev, u32 *power, unsigned long freq, unsigned long voltage); -#endif /* MALI_UNIT_TEST */ extern struct devfreq_cooling_power kbase_ipa_power_model_ops; diff --git a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.c b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.c index 78c343cf249f..57508eb24749 100644 --- a/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.c +++ b/drivers/gpu/arm/bifrost/ipa/mali_kbase_ipa_simple.c @@ -34,6 +34,8 @@ #include "mali_kbase_ipa_simple.h" #include "mali_kbase_ipa_debugfs.h" +#if MALI_USE_CSF + /* This is used if the dynamic power for top-level is estimated separately * through the counter model. To roughly match the contribution of top-level * power in the total dynamic power, when calculated through counter model, @@ -44,6 +46,8 @@ */ #define TOP_LEVEL_DYN_COEFF_SCALER (3) +#endif /* MALI_USE_CSF */ + #if MALI_UNIT_TEST static int dummy_temp; 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 f9e0099a5cbf..e4316981e635 100644 --- a/drivers/gpu/arm/bifrost/jm/mali_kbase_jm_defs.h +++ b/drivers/gpu/arm/bifrost/jm/mali_kbase_jm_defs.h @@ -344,19 +344,6 @@ enum kbase_atom_exit_protected_state { KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT, }; -/** - * struct kbase_ext_res - Contains the info for external resources referred - * by an atom, which have been mapped on GPU side. - * @gpu_address: Start address of the memory region allocated for - * the resource from GPU virtual address space. - * @alloc: pointer to physical pages tracking object, set on - * mapping the external resource on GPU side. - */ -struct kbase_ext_res { - u64 gpu_address; - struct kbase_mem_phy_alloc *alloc; -}; - /** * struct kbase_jd_atom - object representing the atom, containing the complete * state and attributes of an atom. @@ -390,7 +377,8 @@ struct kbase_ext_res { * each allocation is read in order to enforce an * overall physical memory usage limit. * @nr_extres: number of external resources referenced by the atom. - * @extres: pointer to the location containing info about + * @extres: Pointer to @nr_extres VA regions containing the external + * resource allocation and other information. * @nr_extres external resources referenced by the atom. * @device_nr: indicates the coregroup with which the atom is * associated, when @@ -408,16 +396,21 @@ struct kbase_ext_res { * sync through soft jobs and for the implicit * synchronization required on access to external * resources. - * @dma_fence.fence_in: Input fence + * @dma_fence.fence_in: Points to the dma-buf input fence for this atom. + * The atom would complete only after the fence is + * signaled. * @dma_fence.fence: Points to the dma-buf output fence for this atom. + * @dma_fence.fence_cb: The object that is passed at the time of adding the + * callback that gets invoked when @dma_fence.fence_in + * is signaled. + * @dma_fence.fence_cb_added: Flag to keep a track if the callback was successfully + * added for @dma_fence.fence_in, which is supposed to be + * invoked on the signaling of fence. * @dma_fence.context: The dma-buf fence context number for this atom. A * unique context number is allocated to each katom in * the context on context creation. * @dma_fence.seqno: The dma-buf fence sequence number for this atom. This * is increased every time this katom uses dma-buf fence - * @dma_fence.callbacks: List of all callbacks set up to wait on other fences - * @dma_fence.dep_count: Atomic counter of number of outstandind dma-buf fence - * dependencies for this atom. * @event_code: Event code for the job chain represented by the atom, * both HW and low-level SW events are represented by * event codes. @@ -519,21 +512,17 @@ struct kbase_jd_atom { #endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ u16 nr_extres; - struct kbase_ext_res *extres; + struct kbase_va_region **extres; u32 device_nr; u64 jc; void *softjob_data; -#if defined(CONFIG_SYNC) - struct sync_fence *fence; - struct sync_fence_waiter sync_waiter; -#endif /* CONFIG_SYNC */ -#if defined(CONFIG_MALI_BIFROST_DMA_FENCE) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) struct { /* Use the functions/API defined in mali_kbase_fence.h to * when working with this sub struct */ -#if defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) struct fence *fence_in; #else @@ -556,38 +545,21 @@ struct kbase_jd_atom { #else struct dma_fence *fence; #endif + + /* This is the callback object that is registered for the fence_in. + * The callback is invoked when the fence_in is signaled. + */ +#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) + struct fence_cb fence_cb; +#else + struct dma_fence_cb fence_cb; +#endif + bool fence_cb_added; + unsigned int context; atomic_t seqno; - /* This contains a list of all callbacks set up to wait on - * other fences. This atom must be held back from JS until all - * these callbacks have been called and dep_count have reached - * 0. The initial value of dep_count must be equal to the - * number of callbacks on this list. - * - * This list is protected by jctx.lock. Callbacks are added to - * this list when the atom is built and the wait are set up. - * All the callbacks then stay on the list until all callbacks - * have been called and the atom is queued, or cancelled, and - * then all callbacks are taken off the list and freed. - */ - struct list_head callbacks; - /* Atomic counter of number of outstandind dma-buf fence - * dependencies for this atom. When dep_count reaches 0 the - * atom may be queued. - * - * The special value "-1" may only be set after the count - * reaches 0, while holding jctx.lock. This indicates that the - * atom has been handled, either queued in JS or cancelled. - * - * If anyone but the dma-fence worker sets this to -1 they must - * ensure that any potentially queued worker must have - * completed before allowing the atom to be marked as unused. - * This can be done by flushing the fence work queue: - * kctx->dma_fence.wq. - */ - atomic_t dep_count; } dma_fence; -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE || CONFIG_SYNC_FILE */ +#endif /* CONFIG_SYNC_FILE */ /* Note: refer to kbasep_js_atom_retained_state, which will take a copy * of some of the following members diff --git a/drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h b/drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h index 3669f7e23fa6..ea143ab49642 100644 --- a/drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h +++ b/drivers/gpu/arm/bifrost/mali_base_hwconfig_features.h @@ -39,6 +39,7 @@ enum base_hw_feature { BASE_HW_FEATURE_GPU_SLEEP, BASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER, BASE_HW_FEATURE_CORE_FEATURES, + BASE_HW_FEATURE_PBHA_HWU, BASE_HW_FEATURE_END }; @@ -177,5 +178,17 @@ __attribute__((unused)) static const enum base_hw_feature base_hw_features_tTUx[ BASE_HW_FEATURE_END }; +__attribute__((unused)) static const enum base_hw_feature base_hw_features_tTIx[] = { + BASE_HW_FEATURE_FLUSH_REDUCTION, + BASE_HW_FEATURE_PROTECTED_DEBUG_MODE, + BASE_HW_FEATURE_L2_CONFIG, + BASE_HW_FEATURE_CLEAN_ONLY_SAFE, + BASE_HW_FEATURE_ASN_HASH, + BASE_HW_FEATURE_GPU_SLEEP, + BASE_HW_FEATURE_CORE_FEATURES, + BASE_HW_FEATURE_PBHA_HWU, + BASE_HW_FEATURE_END +}; + #endif /* _BASE_HWCONFIG_FEATURES_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h b/drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h index 391730106f6d..a360984acca5 100644 --- a/drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h +++ b/drivers/gpu/arm/bifrost/mali_base_hwconfig_issues.h @@ -700,5 +700,35 @@ __attribute__((unused)) static const enum base_hw_issue base_hw_issues_tTUx_r1p1 BASE_HW_ISSUE_END }; +__attribute__((unused)) static const enum base_hw_issue base_hw_issues_tTUx_r1p2[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_TSIX_2033, + 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 +}; + +__attribute__((unused)) static const enum base_hw_issue base_hw_issues_model_tTIx[] = { + BASE_HW_ISSUE_5736, + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_TSIX_2033, + BASE_HW_ISSUE_TTRX_1337, + BASE_HW_ISSUE_TURSEHW_2716, + BASE_HW_ISSUE_GPU2021PRO_290, + BASE_HW_ISSUE_END +}; + +__attribute__((unused)) static const enum base_hw_issue base_hw_issues_tTIx_r0p0[] = { + BASE_HW_ISSUE_9435, + BASE_HW_ISSUE_TSIX_2033, + BASE_HW_ISSUE_TTRX_1337, + BASE_HW_ISSUE_TURSEHW_2716, + BASE_HW_ISSUE_GPU2021PRO_290, + BASE_HW_ISSUE_END +}; + #endif /* _BASE_HWCONFIG_ISSUES_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase.h b/drivers/gpu/arm/bifrost/mali_kbase.h index 7d0d0dae0279..8e4d36141368 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase.h +++ b/drivers/gpu/arm/bifrost/mali_kbase.h @@ -70,7 +70,9 @@ #include "mali_kbase_jd_debugfs.h" #include "mali_kbase_jm.h" #include "mali_kbase_js.h" -#endif /* !MALI_USE_CSF */ +#else /* !MALI_USE_CSF */ +#include "csf/mali_kbase_debug_csf_fault.h" +#endif /* MALI_USE_CSF */ #include "ipa/mali_kbase_ipa.h" @@ -466,7 +468,7 @@ void kbase_finish_soft_job(struct kbase_jd_atom *katom); void kbase_cancel_soft_job(struct kbase_jd_atom *katom); void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev); void kbasep_remove_waiting_soft_job(struct kbase_jd_atom *katom); -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) void kbase_soft_event_wait_callback(struct kbase_jd_atom *katom); #endif int kbase_soft_event_update(struct kbase_context *kctx, diff --git a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c index 0c8f653a9bff..480e693f3c61 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c @@ -35,7 +35,7 @@ #include "backend/gpu/mali_kbase_model_linux.h" #include #endif /* CONFIG_MALI_BIFROST_NO_MALI */ -#include "mali_kbase_mem_profile_debugfs_buf_size.h" +#include "uapi/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h" #include "mali_kbase_mem.h" #include "mali_kbase_mem_pool_debugfs.h" #include "mali_kbase_mem_pool_group.h" @@ -54,8 +54,8 @@ #if !MALI_USE_CSF #include "mali_kbase_kinstr_jm.h" #endif -#include "mali_kbase_hwcnt_context.h" -#include "mali_kbase_hwcnt_virtualizer.h" +#include "hwcnt/mali_kbase_hwcnt_context.h" +#include "hwcnt/mali_kbase_hwcnt_virtualizer.h" #include "mali_kbase_kinstr_prfcnt.h" #include "mali_kbase_vinstr.h" #if MALI_USE_CSF @@ -95,15 +95,16 @@ #include #include #include +#include #include #include /* is_compat_task/in_compat_syscall */ #include #include #include #include -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) #include -#endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ +#endif /* CONFIG_SYNC_FILE */ #include #include #include @@ -123,11 +124,6 @@ #include -/* GPU IRQ Tags */ -#define JOB_IRQ_TAG 0 -#define MMU_IRQ_TAG 1 -#define GPU_IRQ_TAG 2 - #define KERNEL_SIDE_DDK_VERSION_STRING "K:" MALI_RELEASE_NAME "(GPL)" /** @@ -139,9 +135,6 @@ (((minor) & 0xFFF) << 8) | \ ((0 & 0xFF) << 0)) -#define KBASE_API_MIN(api_version) ((api_version >> 8) & 0xFFF) -#define KBASE_API_MAJ(api_version) ((api_version >> 20) & 0xFFF) - /** * struct mali_kbase_capability_def - kbase capabilities table * @@ -173,6 +166,11 @@ static const struct mali_kbase_capability_def kbase_caps_table[MALI_KBASE_NUM_CA #endif }; +#if (KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE) +/* Mutex to synchronize the probe of multiple kbase instances */ +static struct mutex kbase_probe_mutex; +#endif + /** * mali_kbase_supports_cap - Query whether a kbase capability is supported * @@ -432,6 +430,12 @@ static struct kbase_device *to_kbase_device(struct device *dev) int assign_irqs(struct kbase_device *kbdev) { + static const char *const irq_names_caps[] = { "JOB", "MMU", "GPU" }; + +#if IS_ENABLED(CONFIG_OF) + static const char *const irq_names[] = { "job", "mmu", "gpu" }; +#endif + struct platform_device *pdev; int i; @@ -439,34 +443,31 @@ int assign_irqs(struct kbase_device *kbdev) return -ENODEV; pdev = to_platform_device(kbdev->dev); - /* 3 IRQ resources */ - for (i = 0; i < 3; i++) { - struct resource *irq_res; - int irqtag; - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!irq_res) { - dev_err(kbdev->dev, "No IRQ resource at index %d\n", i); - return -ENOENT; - } + for (i = 0; i < ARRAY_SIZE(irq_names_caps); i++) { + int irq; #if IS_ENABLED(CONFIG_OF) - if (!strncasecmp(irq_res->name, "JOB", 4)) { - irqtag = JOB_IRQ_TAG; - } else if (!strncasecmp(irq_res->name, "MMU", 4)) { - irqtag = MMU_IRQ_TAG; - } else if (!strncasecmp(irq_res->name, "GPU", 4)) { - irqtag = GPU_IRQ_TAG; - } else { - dev_err(&pdev->dev, "Invalid irq res name: '%s'\n", - irq_res->name); - return -EINVAL; - } + /* We recommend using Upper case for the irq names in dts, but if + * there are devices in the world using Lower case then we should + * avoid breaking support for them. So try using names in Upper case + * first then try using Lower case names. If both attempts fail then + * we assume there is no IRQ resource specified for the GPU. + */ + irq = platform_get_irq_byname(pdev, irq_names_caps[i]); + if (irq < 0) + irq = platform_get_irq_byname(pdev, irq_names[i]); #else - irqtag = i; + irq = platform_get_irq(pdev, i); #endif /* CONFIG_OF */ - kbdev->irqs[irqtag].irq = irq_res->start; - kbdev->irqs[irqtag].flags = irq_res->flags & IRQF_TRIGGER_MASK; + + if (irq < 0) { + dev_err(kbdev->dev, "No IRQ resource '%s'\n", irq_names_caps[i]); + return irq; + } + + kbdev->irqs[i].irq = irq; + kbdev->irqs[i].flags = irqd_get_trigger_type(irq_get_irq_data(irq)); } return 0; @@ -663,6 +664,9 @@ static int kbase_open(struct inode *inode, struct file *filp) if (!kbdev) return -ENODEV; + /* Set address space operation for page migration */ + kbase_mem_migrate_set_address_space_ops(kbdev, filp); + /* Device-wide firmware load is moved here from probing to comply with * Android GKI vendor guideline. */ @@ -1040,52 +1044,11 @@ static int kbase_api_get_ddk_version(struct kbase_context *kctx, return len; } -/* Defaults for legacy just-in-time memory allocator initialization - * kernel calls - */ -#define DEFAULT_MAX_JIT_ALLOCATIONS 255 -#define JIT_LEGACY_TRIM_LEVEL (0) /* No trimming */ - -static int kbase_api_mem_jit_init_10_2(struct kbase_context *kctx, - struct kbase_ioctl_mem_jit_init_10_2 *jit_init) -{ - kctx->jit_version = 1; - - /* since no phys_pages parameter, use the maximum: va_pages */ - return kbase_region_tracker_init_jit(kctx, jit_init->va_pages, - DEFAULT_MAX_JIT_ALLOCATIONS, - JIT_LEGACY_TRIM_LEVEL, BASE_MEM_GROUP_DEFAULT, - jit_init->va_pages); -} - -static int kbase_api_mem_jit_init_11_5(struct kbase_context *kctx, - struct kbase_ioctl_mem_jit_init_11_5 *jit_init) -{ - int i; - - kctx->jit_version = 2; - - for (i = 0; i < sizeof(jit_init->padding); i++) { - /* Ensure all padding bytes are 0 for potential future - * extension - */ - if (jit_init->padding[i]) - return -EINVAL; - } - - /* since no phys_pages parameter, use the maximum: va_pages */ - return kbase_region_tracker_init_jit(kctx, jit_init->va_pages, - jit_init->max_allocations, jit_init->trim_level, - jit_init->group_id, jit_init->va_pages); -} - static int kbase_api_mem_jit_init(struct kbase_context *kctx, struct kbase_ioctl_mem_jit_init *jit_init) { int i; - kctx->jit_version = 3; - for (i = 0; i < sizeof(jit_init->padding); i++) { /* Ensure all padding bytes are 0 for potential future * extension @@ -1243,7 +1206,7 @@ static int kbase_api_mem_flags_change(struct kbase_context *kctx, static int kbase_api_stream_create(struct kbase_context *kctx, struct kbase_ioctl_stream_create *stream) { -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) int fd, ret; /* Name must be NULL-terminated and padded with NULLs, so check last @@ -1265,7 +1228,7 @@ static int kbase_api_stream_create(struct kbase_context *kctx, static int kbase_api_fence_validate(struct kbase_context *kctx, struct kbase_ioctl_fence_validate *validate) { -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) return kbase_sync_fence_validate(validate->fd); #else return -ENOENT; @@ -1279,12 +1242,18 @@ static int kbase_api_mem_profile_add(struct kbase_context *kctx, int err; if (data->len > KBASE_MEM_PROFILE_MAX_BUF_SIZE) { - dev_err(kctx->kbdev->dev, "mem_profile_add: buffer too big\n"); + dev_err(kctx->kbdev->dev, "mem_profile_add: buffer too big"); return -EINVAL; } + if (!data->len) { + dev_err(kctx->kbdev->dev, "mem_profile_add: buffer size is 0"); + /* Should return -EINVAL, but returning -ENOMEM for backwards compat */ + return -ENOMEM; + } + buf = kmalloc(data->len, GFP_KERNEL); - if (ZERO_OR_NULL_PTR(buf)) + if (!buf) return -ENOMEM; err = copy_from_user(buf, u64_to_user_ptr(data->buffer), @@ -1494,9 +1463,22 @@ static int kbasep_cs_tiler_heap_init(struct kbase_context *kctx, kctx->jit_group_id = heap_init->in.group_id; return kbase_csf_tiler_heap_init(kctx, heap_init->in.chunk_size, - heap_init->in.initial_chunks, heap_init->in.max_chunks, - heap_init->in.target_in_flight, - &heap_init->out.gpu_heap_va, &heap_init->out.first_chunk_va); + heap_init->in.initial_chunks, heap_init->in.max_chunks, + heap_init->in.target_in_flight, heap_init->in.buf_desc_va, + &heap_init->out.gpu_heap_va, + &heap_init->out.first_chunk_va); +} + +static int kbasep_cs_tiler_heap_init_1_13(struct kbase_context *kctx, + union kbase_ioctl_cs_tiler_heap_init_1_13 *heap_init) +{ + kctx->jit_group_id = heap_init->in.group_id; + + return kbase_csf_tiler_heap_init(kctx, heap_init->in.chunk_size, + heap_init->in.initial_chunks, heap_init->in.max_chunks, + heap_init->in.target_in_flight, 0, + &heap_init->out.gpu_heap_va, + &heap_init->out.first_chunk_va); } static int kbasep_cs_tiler_heap_term(struct kbase_context *kctx, @@ -1578,6 +1560,31 @@ static int kbasep_ioctl_cs_cpu_queue_dump(struct kbase_context *kctx, cpu_queue_info->size); } +#define POWER_DOWN_LATEST_FLUSH_VALUE ((u32)1) +static int kbase_ioctl_read_user_page(struct kbase_context *kctx, + union kbase_ioctl_read_user_page *user_page) +{ + struct kbase_device *kbdev = kctx->kbdev; + unsigned long flags; + + /* As of now, only LATEST_FLUSH is supported */ + if (unlikely(user_page->in.offset != LATEST_FLUSH)) + return -EINVAL; + + /* Validating padding that must be zero */ + if (unlikely(user_page->in.padding != 0)) + return -EINVAL; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + if (!kbdev->pm.backend.gpu_powered) + user_page->out.val_lo = POWER_DOWN_LATEST_FLUSH_VALUE; + else + user_page->out.val_lo = kbase_reg_read(kbdev, USER_REG(LATEST_FLUSH)); + user_page->out.val_hi = 0; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + + return 0; +} #endif /* MALI_USE_CSF */ static int kbasep_ioctl_context_priority_check(struct kbase_context *kctx, @@ -1779,18 +1786,6 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct kbase_ioctl_get_ddk_version, kctx); break; - case KBASE_IOCTL_MEM_JIT_INIT_10_2: - KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_MEM_JIT_INIT_10_2, - kbase_api_mem_jit_init_10_2, - struct kbase_ioctl_mem_jit_init_10_2, - kctx); - break; - case KBASE_IOCTL_MEM_JIT_INIT_11_5: - KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_MEM_JIT_INIT_11_5, - kbase_api_mem_jit_init_11_5, - struct kbase_ioctl_mem_jit_init_11_5, - kctx); - break; case KBASE_IOCTL_MEM_JIT_INIT: KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_MEM_JIT_INIT, kbase_api_mem_jit_init, @@ -2028,6 +2023,11 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) union kbase_ioctl_cs_tiler_heap_init, kctx); break; + case KBASE_IOCTL_CS_TILER_HEAP_INIT_1_13: + KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_CS_TILER_HEAP_INIT_1_13, + kbasep_cs_tiler_heap_init_1_13, + union kbase_ioctl_cs_tiler_heap_init_1_13, kctx); + break; case KBASE_IOCTL_CS_TILER_HEAP_TERM: KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_CS_TILER_HEAP_TERM, kbasep_cs_tiler_heap_term, @@ -2046,6 +2046,10 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct kbase_ioctl_cs_cpu_queue_info, kctx); break; + case KBASE_IOCTL_READ_USER_PAGE: + KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_READ_USER_PAGE, kbase_ioctl_read_user_page, + union kbase_ioctl_read_user_page, kctx); + break; #endif /* MALI_USE_CSF */ #if MALI_UNIT_TEST case KBASE_IOCTL_TLSTREAM_STATS: @@ -2088,6 +2092,9 @@ static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, lof if (unlikely(!kctx)) return -EPERM; + if (count < data_size) + return -ENOBUFS; + if (atomic_read(&kctx->event_count)) read_event = true; else @@ -3185,10 +3192,10 @@ static ssize_t gpuinfo_show(struct device *dev, .name = "Mali-G510" }, { .id = GPU_ID2_PRODUCT_TVAX >> KBASE_GPU_ID_VERSION_PRODUCT_ID_SHIFT, .name = "Mali-G310" }, - { .id = GPU_ID2_PRODUCT_TTUX >> KBASE_GPU_ID_VERSION_PRODUCT_ID_SHIFT, - .name = "Mali-TTUX" }, - { .id = GPU_ID2_PRODUCT_LTUX >> KBASE_GPU_ID_VERSION_PRODUCT_ID_SHIFT, - .name = "Mali-LTUX" }, + { .id = GPU_ID2_PRODUCT_TTIX >> KBASE_GPU_ID_VERSION_PRODUCT_ID_SHIFT, + .name = "Mali-TTIX" }, + { .id = GPU_ID2_PRODUCT_LTIX >> KBASE_GPU_ID_VERSION_PRODUCT_ID_SHIFT, + .name = "Mali-LTIX" }, }; const char *product_name = "(Unknown Mali GPU)"; struct kbase_device *kbdev; @@ -3223,19 +3230,19 @@ static ssize_t gpuinfo_show(struct device *dev, GPU_FEATURES_RAY_TRACING_GET(gpu_props->props.raw_props.gpu_features); const u8 nr_cores = gpu_props->num_cores; - /* Mali-TTUX_B(ig) if 10 < number of cores with ray tracing supproted. - * Mali-TTUX if 10 < number of cores without ray tracing supported. - * Mali-TTUX if 7 <= number of cores <= 10 regardless ray tracing. - * Mali-LTUX if number of cores < 7. + /* Mali-G715-Immortalis if 10 < number of cores with ray tracing supproted. + * Mali-G715 if 10 < number of cores without ray tracing supported. + * Mali-G715 if 7 <= number of cores <= 10 regardless ray tracing. + * Mali-G615 if number of cores < 7. */ if ((nr_cores > 10) && rt_supported) - product_name = "Mali-TTUX_B"; + product_name = "Mali-G715-Immortalis"; else if (nr_cores >= 7) - product_name = "Mali-TTUX"; + product_name = "Mali-G715"; if (nr_cores < 7) { - dev_warn(kbdev->dev, "nr_cores(%u) GPU ID must be LTUX", nr_cores); - product_name = "Mali-LTUX"; + dev_warn(kbdev->dev, "nr_cores(%u) GPU ID must be G615", nr_cores); + product_name = "Mali-G615"; } else dev_dbg(kbdev->dev, "GPU ID_Name: %s, nr_cores(%u)\n", product_name, nr_cores); @@ -4511,7 +4518,7 @@ int power_control_init(struct kbase_device *kbdev) for (i = 0; i < ARRAY_SIZE(regulator_names); i++) { kbdev->regulators[i] = regulator_get_optional(kbdev->dev, regulator_names[i]); - if (IS_ERR_OR_NULL(kbdev->regulators[i])) { + if (IS_ERR(kbdev->regulators[i])) { err = PTR_ERR(kbdev->regulators[i]); kbdev->regulators[i] = NULL; break; @@ -4539,7 +4546,7 @@ int power_control_init(struct kbase_device *kbdev) */ for (i = 0; i < BASE_MAX_NR_CLOCKS_REGULATORS; i++) { kbdev->clocks[i] = of_clk_get(kbdev->dev->of_node, i); - if (IS_ERR_OR_NULL(kbdev->clocks[i])) { + if (IS_ERR(kbdev->clocks[i])) { err = PTR_ERR(kbdev->clocks[i]); kbdev->clocks[i] = NULL; break; @@ -4801,52 +4808,84 @@ static const struct file_operations .release = single_release, }; -int kbase_device_debugfs_init(struct kbase_device *kbdev) +/** + * debugfs_ctx_defaults_init - Create the default configuration of new contexts in debugfs + * @kbdev: An instance of the GPU platform device, allocated from the probe method of the driver. + * Return: A pointer to the last dentry that it tried to create, whether successful or not. + * Could be NULL or encode another error value. + */ +static struct dentry *debugfs_ctx_defaults_init(struct kbase_device *const kbdev) { - struct dentry *debugfs_ctx_defaults_directory; - int err; /* prevent unprivileged use of debug file system * in old kernel version */ const mode_t mode = 0644; + struct dentry *dentry = debugfs_create_dir("defaults", kbdev->debugfs_ctx_directory); + struct dentry *debugfs_ctx_defaults_directory = dentry; - kbdev->mali_debugfs_directory = debugfs_create_dir(kbdev->devname, - NULL); - if (IS_ERR_OR_NULL(kbdev->mali_debugfs_directory)) { + if (IS_ERR_OR_NULL(dentry)) { + dev_err(kbdev->dev, "Couldn't create mali debugfs ctx defaults directory\n"); + return dentry; + } + + debugfs_create_bool("infinite_cache", mode, + debugfs_ctx_defaults_directory, + &kbdev->infinite_cache_active_default); + + dentry = debugfs_create_file("mem_pool_max_size", mode, debugfs_ctx_defaults_directory, + &kbdev->mem_pool_defaults.small, + &kbase_device_debugfs_mem_pool_max_size_fops); + if (IS_ERR_OR_NULL(dentry)) { + dev_err(kbdev->dev, "Unable to create mem_pool_max_size debugfs entry\n"); + return dentry; + } + + dentry = debugfs_create_file("lp_mem_pool_max_size", mode, debugfs_ctx_defaults_directory, + &kbdev->mem_pool_defaults.large, + &kbase_device_debugfs_mem_pool_max_size_fops); + if (IS_ERR_OR_NULL(dentry)) + dev_err(kbdev->dev, "Unable to create lp_mem_pool_max_size debugfs entry\n"); + + return dentry; +} + +/** + * init_debugfs - Create device-wide debugfs directories and files for the Mali driver + * @kbdev: An instance of the GPU platform device, allocated from the probe method of the driver. + * Return: A pointer to the last dentry that it tried to create, whether successful or not. + * Could be NULL or encode another error value. + */ +static struct dentry *init_debugfs(struct kbase_device *kbdev) +{ + struct dentry *dentry = debugfs_create_dir(kbdev->devname, NULL); + + kbdev->mali_debugfs_directory = dentry; + if (IS_ERR_OR_NULL(dentry)) { dev_err(kbdev->dev, "Couldn't create mali debugfs directory: %s\n", kbdev->devname); - err = -ENOMEM; - goto out; + return dentry; } - kbdev->debugfs_ctx_directory = debugfs_create_dir("ctx", - kbdev->mali_debugfs_directory); - if (IS_ERR_OR_NULL(kbdev->debugfs_ctx_directory)) { + dentry = debugfs_create_dir("ctx", kbdev->mali_debugfs_directory); + kbdev->debugfs_ctx_directory = dentry; + if (IS_ERR_OR_NULL(dentry)) { dev_err(kbdev->dev, "Couldn't create mali debugfs ctx directory\n"); - err = -ENOMEM; - goto out; + return dentry; } - kbdev->debugfs_instr_directory = debugfs_create_dir("instrumentation", - kbdev->mali_debugfs_directory); - if (IS_ERR_OR_NULL(kbdev->debugfs_instr_directory)) { + dentry = debugfs_create_dir("instrumentation", kbdev->mali_debugfs_directory); + kbdev->debugfs_instr_directory = dentry; + if (IS_ERR_OR_NULL(dentry)) { dev_err(kbdev->dev, "Couldn't create mali debugfs instrumentation directory\n"); - err = -ENOMEM; - goto out; - } - - debugfs_ctx_defaults_directory = debugfs_create_dir("defaults", - kbdev->debugfs_ctx_directory); - if (IS_ERR_OR_NULL(debugfs_ctx_defaults_directory)) { - dev_err(kbdev->dev, "Couldn't create mali debugfs ctx defaults directory\n"); - err = -ENOMEM; - goto out; + return dentry; } kbasep_regs_history_debugfs_init(kbdev); -#if !MALI_USE_CSF +#if MALI_USE_CSF + kbase_debug_csf_fault_debugfs_init(kbdev); +#else /* MALI_USE_CSF */ kbase_debug_job_fault_debugfs_init(kbdev); #endif /* !MALI_USE_CSF */ @@ -4860,41 +4899,58 @@ int kbase_device_debugfs_init(struct kbase_device *kbdev) /* fops_* variables created by invocations of macro * MAKE_QUIRK_ACCESSORS() above. */ - debugfs_create_file("quirks_sc", 0644, + dentry = debugfs_create_file("quirks_sc", 0644, kbdev->mali_debugfs_directory, kbdev, &fops_sc_quirks); - debugfs_create_file("quirks_tiler", 0644, - kbdev->mali_debugfs_directory, kbdev, - &fops_tiler_quirks); - debugfs_create_file("quirks_mmu", 0644, - kbdev->mali_debugfs_directory, kbdev, - &fops_mmu_quirks); - debugfs_create_file("quirks_gpu", 0644, kbdev->mali_debugfs_directory, - kbdev, &fops_gpu_quirks); - - debugfs_create_bool("infinite_cache", mode, - debugfs_ctx_defaults_directory, - &kbdev->infinite_cache_active_default); - - debugfs_create_file("mem_pool_max_size", mode, - debugfs_ctx_defaults_directory, - &kbdev->mem_pool_defaults.small, - &kbase_device_debugfs_mem_pool_max_size_fops); - - debugfs_create_file("lp_mem_pool_max_size", mode, - debugfs_ctx_defaults_directory, - &kbdev->mem_pool_defaults.large, - &kbase_device_debugfs_mem_pool_max_size_fops); - - if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE)) { - debugfs_create_file("protected_debug_mode", 0444, - kbdev->mali_debugfs_directory, kbdev, - &fops_protected_debug_mode); + if (IS_ERR_OR_NULL(dentry)) { + dev_err(kbdev->dev, "Unable to create quirks_sc debugfs entry\n"); + return dentry; } - debugfs_create_file("reset", 0644, + dentry = debugfs_create_file("quirks_tiler", 0644, + kbdev->mali_debugfs_directory, kbdev, + &fops_tiler_quirks); + if (IS_ERR_OR_NULL(dentry)) { + dev_err(kbdev->dev, "Unable to create quirks_tiler debugfs entry\n"); + return dentry; + } + + dentry = debugfs_create_file("quirks_mmu", 0644, + kbdev->mali_debugfs_directory, kbdev, + &fops_mmu_quirks); + if (IS_ERR_OR_NULL(dentry)) { + dev_err(kbdev->dev, "Unable to create quirks_mmu debugfs entry\n"); + return dentry; + } + + dentry = debugfs_create_file("quirks_gpu", 0644, kbdev->mali_debugfs_directory, + kbdev, &fops_gpu_quirks); + if (IS_ERR_OR_NULL(dentry)) { + dev_err(kbdev->dev, "Unable to create quirks_gpu debugfs entry\n"); + return dentry; + } + + dentry = debugfs_ctx_defaults_init(kbdev); + if (IS_ERR_OR_NULL(dentry)) + return dentry; + + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PROTECTED_DEBUG_MODE)) { + dentry = debugfs_create_file("protected_debug_mode", 0444, + kbdev->mali_debugfs_directory, kbdev, + &fops_protected_debug_mode); + if (IS_ERR_OR_NULL(dentry)) { + dev_err(kbdev->dev, "Unable to create protected_debug_mode debugfs entry\n"); + return dentry; + } + } + + dentry = debugfs_create_file("reset", 0644, kbdev->mali_debugfs_directory, kbdev, &fops_trigger_reset); + if (IS_ERR_OR_NULL(dentry)) { + dev_err(kbdev->dev, "Unable to create reset debugfs entry\n"); + return dentry; + } kbase_ktrace_debugfs_init(kbdev); @@ -4907,19 +4963,30 @@ int kbase_device_debugfs_init(struct kbase_device *kbdev) #endif /* CONFIG_MALI_BIFROST_DEVFREQ */ #if !MALI_USE_CSF - debugfs_create_file("serialize_jobs", 0644, + dentry = debugfs_create_file("serialize_jobs", 0644, kbdev->mali_debugfs_directory, kbdev, &kbasep_serialize_jobs_debugfs_fops); - + if (IS_ERR_OR_NULL(dentry)) { + dev_err(kbdev->dev, "Unable to create serialize_jobs debugfs entry\n"); + return dentry; + } + kbase_timeline_io_debugfs_init(kbdev); #endif kbase_dvfs_status_debugfs_init(kbdev); - return 0; + return dentry; +} -out: - debugfs_remove_recursive(kbdev->mali_debugfs_directory); - return err; +int kbase_device_debugfs_init(struct kbase_device *kbdev) +{ + struct dentry *dentry = init_debugfs(kbdev); + + if (IS_ERR_OR_NULL(dentry)) { + debugfs_remove_recursive(kbdev->mali_debugfs_directory); + return IS_ERR(dentry) ? PTR_ERR(dentry) : -ENOMEM; + } + return 0; } void kbase_device_debugfs_term(struct kbase_device *kbdev) @@ -5441,7 +5508,9 @@ static int kbase_platform_device_probe(struct platform_device *pdev) kbdev->dev = &pdev->dev; dev_set_drvdata(kbdev->dev, kbdev); - +#if (KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE) + mutex_lock(&kbase_probe_mutex); +#endif err = kbase_device_init(kbdev); if (err) { @@ -5453,10 +5522,16 @@ static int kbase_platform_device_probe(struct platform_device *pdev) dev_set_drvdata(kbdev->dev, NULL); kbase_device_free(kbdev); +#if (KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE) + mutex_unlock(&kbase_probe_mutex); +#endif } else { dev_info(kbdev->dev, "Probed as %s\n", dev_name(kbdev->mdev.this_device)); kbase_increment_device_id(); +#if (KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE) + mutex_unlock(&kbase_probe_mutex); +#endif #ifdef CONFIG_MALI_ARBITER_SUPPORT mutex_lock(&kbdev->pm.lock); kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_INITIALIZED_EVT); @@ -5690,10 +5765,11 @@ static const struct dev_pm_ops kbase_pm_ops = { }; #if IS_ENABLED(CONFIG_OF) -static const struct of_device_id kbase_dt_ids[] = { - { .compatible = "arm,mali-bifrost" }, - { /* sentinel */ } -}; +static const struct of_device_id kbase_dt_ids[] = { { .compatible = "arm,malit6xx" }, + { .compatible = "arm,mali-midgard" }, + { .compatible = "arm,mali-bifrost" }, + { .compatible = "arm,mali-valhall" }, + { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, kbase_dt_ids); #endif @@ -5708,26 +5784,29 @@ static struct platform_driver kbase_platform_driver = { }, }; -/* - * The driver will not provide a shortcut to create the Mali platform device - * anymore when using Device Tree. - */ -#if IS_ENABLED(CONFIG_OF) +#if (KERNEL_VERSION(5, 3, 0) > LINUX_VERSION_CODE) && IS_ENABLED(CONFIG_OF) module_platform_driver(kbase_platform_driver); #else - static int __init kbase_driver_init(void) { int ret; +#if (KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE) + mutex_init(&kbase_probe_mutex); +#endif + +#ifndef CONFIG_OF ret = kbase_platform_register(); if (ret) return ret; - +#endif ret = platform_driver_register(&kbase_platform_driver); - - if (ret) +#ifndef CONFIG_OF + if (ret) { kbase_platform_unregister(); + return ret; + } +#endif return ret; } @@ -5735,14 +5814,14 @@ static int __init kbase_driver_init(void) static void __exit kbase_driver_exit(void) { platform_driver_unregister(&kbase_platform_driver); +#ifndef CONFIG_OF kbase_platform_unregister(); +#endif } module_init(kbase_driver_init); module_exit(kbase_driver_exit); - -#endif /* CONFIG_OF */ - +#endif MODULE_LICENSE("GPL"); MODULE_VERSION(MALI_RELEASE_NAME " (UK version " \ __stringify(BASE_UK_VERSION_MAJOR) "." \ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.c b/drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.c index f4a46c12ac92..60afde2ceb7f 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_ctx_sched.c @@ -327,16 +327,14 @@ struct kbase_context *kbase_ctx_sched_as_to_ctx_nolock( bool kbase_ctx_sched_inc_refcount_nolock(struct kbase_context *kctx) { bool result = false; - int as_nr; if (WARN_ON(kctx == NULL)) return result; lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - as_nr = kctx->as_nr; if (atomic_read(&kctx->refcount) > 0) { - KBASE_DEBUG_ASSERT(as_nr >= 0); + KBASE_DEBUG_ASSERT(kctx->as_nr >= 0); kbase_ctx_sched_retain_ctx_refcount(kctx); KBASE_KTRACE_ADD(kctx->kbdev, SCHED_RETAIN_CTX_NOLOCK, kctx, diff --git a/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_allocs.c b/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_allocs.c new file mode 100644 index 000000000000..598d8f594644 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_allocs.c @@ -0,0 +1,138 @@ +// 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. + * + */ + +/* + * Debugfs interface to dump information about GPU allocations in kctx + */ + +#include "mali_kbase_debug_mem_allocs.h" +#include "mali_kbase.h" + +#include +#include +#include + +#if IS_ENABLED(CONFIG_DEBUG_FS) + +/** + * debug_zone_mem_allocs_show - Show information from specific rbtree + * @zone: Name of GPU virtual memory zone + * @rbtree: Pointer to the root of the rbtree associated with @zone + * @sfile: The debugfs entry + * + * This function is called to show information about all the GPU allocations of a + * a particular zone within GPU virtual memory space of a context. + * The information like the start virtual address and size (in bytes) is shown for + * every GPU allocation mapped in the zone. + */ +static void debug_zone_mem_allocs_show(char *zone, struct rb_root *rbtree, struct seq_file *sfile) +{ + struct rb_node *p; + struct kbase_va_region *reg; + const char *type_names[5] = { + "Native", + "Imported UMM", + "Imported user buf", + "Alias", + "Raw" + }; + +#define MEM_ALLOCS_HEADER \ + " VA, VA size, Commit size, Flags, Mem type\n" + seq_printf(sfile, "Zone name: %s\n:", zone); + seq_printf(sfile, MEM_ALLOCS_HEADER); + for (p = rb_first(rbtree); p; p = rb_next(p)) { + reg = rb_entry(p, struct kbase_va_region, rblink); + if (!(reg->flags & KBASE_REG_FREE)) { + seq_printf(sfile, "%16llx, %16zx, %16zx, %8lx, %s\n", + reg->start_pfn << PAGE_SHIFT, reg->nr_pages << PAGE_SHIFT, + kbase_reg_current_backed_size(reg) << PAGE_SHIFT, + reg->flags, type_names[reg->gpu_alloc->type]); + } + } +} + +/** + * debug_ctx_mem_allocs_show - Show information about GPU allocations in a kctx + * @sfile: The debugfs entry + * @data: Data associated with the entry + * + * Return: + * 0 if successfully prints data in debugfs entry file + * -1 if it encountered an error + */ +static int debug_ctx_mem_allocs_show(struct seq_file *sfile, void *data) +{ + struct kbase_context *const kctx = sfile->private; + + kbase_gpu_vm_lock(kctx); + + debug_zone_mem_allocs_show("SAME_VA:", &kctx->reg_rbtree_same, sfile); + debug_zone_mem_allocs_show("CUSTOM_VA:", &kctx->reg_rbtree_custom, sfile); + debug_zone_mem_allocs_show("EXEC_VA:", &kctx->reg_rbtree_exec, sfile); + +#if MALI_USE_CSF + debug_zone_mem_allocs_show("EXEC_VA_FIXED:", &kctx->reg_rbtree_exec_fixed, sfile); + debug_zone_mem_allocs_show("FIXED_VA:", &kctx->reg_rbtree_fixed, sfile); +#endif /* MALI_USE_CSF */ + + kbase_gpu_vm_unlock(kctx); + return 0; +} + +/* + * File operations related to debugfs entry for mem_zones + */ +static int debug_mem_allocs_open(struct inode *in, struct file *file) +{ + return single_open(file, debug_ctx_mem_allocs_show, in->i_private); +} + +static const struct file_operations kbase_debug_mem_allocs_fops = { + .owner = THIS_MODULE, + .open = debug_mem_allocs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * Initialize debugfs entry for mem_allocs + */ +void kbase_debug_mem_allocs_init(struct kbase_context *const kctx) +{ + /* Caller already ensures this, but we keep the pattern for + * maintenance safety. + */ + if (WARN_ON(!kctx) || WARN_ON(IS_ERR_OR_NULL(kctx->kctx_dentry))) + return; + + debugfs_create_file("mem_allocs", 0400, kctx->kctx_dentry, kctx, + &kbase_debug_mem_allocs_fops); +} +#else +/* + * Stub functions for when debugfs is disabled + */ +void kbase_debug_mem_allocs_init(struct kbase_context *const kctx) +{ +} +#endif diff --git a/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.h b/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_allocs.h similarity index 56% rename from drivers/base/arm/dma_buf_lock/src/dma_buf_lock.h rename to drivers/gpu/arm/bifrost/mali_kbase_debug_mem_allocs.h index b5bb22553fe2..8cf69c2cbaf9 100644 --- a/drivers/base/arm/dma_buf_lock/src/dma_buf_lock.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_allocs.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2012, 2020-2021 ARM Limited. All rights reserved. + * (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 @@ -19,26 +19,21 @@ * */ -#ifndef _DMA_BUF_LOCK_H -#define _DMA_BUF_LOCK_H +#ifndef _KBASE_DEBUG_MEM_ALLOCS_H +#define _KBASE_DEBUG_MEM_ALLOCS_H -enum dma_buf_lock_exclusive { - DMA_BUF_LOCK_NONEXCLUSIVE = 0, - DMA_BUF_LOCK_EXCLUSIVE = -1 -}; +#include -struct dma_buf_lock_k_request { - int count; - int *list_of_dma_buf_fds; - int timeout; - enum dma_buf_lock_exclusive exclusive; -}; +/** + * kbase_debug_mem_allocs_init() - Initialize the mem_allocs debugfs file + * @kctx: Pointer to kernel base context + * + * This function creates a "mem_allocs" file for a context to show infor about the + * GPU allocations created for that context. + * + * The file is cleaned up by a call to debugfs_remove_recursive() deleting the + * parent directory. + */ +void kbase_debug_mem_allocs_init(struct kbase_context *kctx); -#define DMA_BUF_LOCK_IOC_MAGIC '~' - -#define DMA_BUF_LOCK_FUNC_LOCK_ASYNC _IOW(DMA_BUF_LOCK_IOC_MAGIC, 11, struct dma_buf_lock_k_request) - -#define DMA_BUF_LOCK_IOC_MINNR 11 -#define DMA_BUF_LOCK_IOC_MAXNR 11 - -#endif /* _DMA_BUF_LOCK_H */ +#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.h b/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.h index d03483219b08..cb8050d9b32c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_debug_mem_view.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2013-2015, 2019-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2013-2015, 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 @@ -25,7 +25,7 @@ #include /** - * kbase_debug_mem_view_init - Initialize the mem_view sysfs file + * kbase_debug_mem_view_init - Initialize the mem_view debugfs file * @kctx: Pointer to kernel base context * * This function creates a "mem_view" file which can be used to get a view of diff --git a/drivers/gpu/arm/bifrost/mali_kbase_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_defs.h index 9fafe96d14a8..1072eac6d186 100755 --- a/drivers/gpu/arm/bifrost/mali_kbase_defs.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_defs.h @@ -35,13 +35,13 @@ #include #include #include -#include +#include #if MALI_USE_CSF -#include +#include #else -#include -#include +#include +#include #endif #include @@ -53,11 +53,7 @@ #include -#if defined(CONFIG_SYNC) -#include -#else #include "mali_kbase_fence_defs.h" -#endif #if IS_ENABLED(CONFIG_DEBUG_FS) #include @@ -133,8 +129,7 @@ /* Maximum number of pages of memory that require a permanent mapping, per * kbase_context */ -#define KBASE_PERMANENTLY_MAPPED_MEM_LIMIT_PAGES ((32 * 1024ul * 1024ul) >> \ - PAGE_SHIFT) +#define KBASE_PERMANENTLY_MAPPED_MEM_LIMIT_PAGES ((64 * 1024ul * 1024ul) >> PAGE_SHIFT) /* Minimum threshold period for hwcnt dumps between different hwcnt virtualizer * clients, to reduce undesired system load. * If a virtualizer client requests a dump within this threshold period after @@ -446,36 +441,40 @@ struct kbase_pm_device_data { /** * struct kbase_mem_pool - Page based memory pool for kctx/kbdev - * @kbdev: Kbase device where memory is used - * @cur_size: Number of free pages currently in the pool (may exceed - * @max_size in some corner cases) - * @max_size: Maximum number of free pages in the pool - * @order: order = 0 refers to a pool of 4 KB pages - * order = 9 refers to a pool of 2 MB pages (2^9 * 4KB = 2 MB) - * @group_id: A memory group ID to be passed to a platform-specific - * memory group manager, if present. Immutable. - * Valid range is 0..(MEMORY_GROUP_MANAGER_NR_GROUPS-1). - * @pool_lock: Lock protecting the pool - must be held when modifying - * @cur_size and @page_list - * @page_list: List of free pages in the pool - * @reclaim: Shrinker for kernel reclaim of free pages - * @next_pool: Pointer to next pool where pages can be allocated when this - * pool is empty. Pages will spill over to the next pool when - * this pool is full. Can be NULL if there is no next pool. - * @dying: true if the pool is being terminated, and any ongoing - * operations should be abandoned - * @dont_reclaim: true if the shrinker is forbidden from reclaiming memory from - * this pool, eg during a grow operation + * @kbdev: Kbase device where memory is used + * @cur_size: Number of free pages currently in the pool (may exceed + * @max_size in some corner cases) + * @max_size: Maximum number of free pages in the pool + * @order: order = 0 refers to a pool of 4 KB pages + * order = 9 refers to a pool of 2 MB pages (2^9 * 4KB = 2 MB) + * @group_id: A memory group ID to be passed to a platform-specific + * memory group manager, if present. Immutable. + * Valid range is 0..(MEMORY_GROUP_MANAGER_NR_GROUPS-1). + * @pool_lock: Lock protecting the pool - must be held when modifying + * @cur_size and @page_list + * @page_list: List of free pages in the pool + * @reclaim: Shrinker for kernel reclaim of free pages + * @isolation_in_progress_cnt: Number of pages in pool undergoing page isolation. + * This is used to avoid race condition between pool termination + * and page isolation for page migration. + * @next_pool: Pointer to next pool where pages can be allocated when this + * pool is empty. Pages will spill over to the next pool when + * this pool is full. Can be NULL if there is no next pool. + * @dying: true if the pool is being terminated, and any ongoing + * operations should be abandoned + * @dont_reclaim: true if the shrinker is forbidden from reclaiming memory from + * this pool, eg during a grow operation */ struct kbase_mem_pool { struct kbase_device *kbdev; - size_t cur_size; - size_t max_size; - u8 order; - u8 group_id; - spinlock_t pool_lock; - struct list_head page_list; - struct shrinker reclaim; + size_t cur_size; + size_t max_size; + u8 order; + u8 group_id; + spinlock_t pool_lock; + struct list_head page_list; + struct shrinker reclaim; + atomic_t isolation_in_progress_cnt; struct kbase_mem_pool *next_pool; @@ -562,7 +561,7 @@ struct kbase_devfreq_opp { * @entry_set_pte: program the pte to be a valid entry to encode the physical * address of the next lower level page table and also update * the number of valid entries. - * @entry_invalidate: clear out or invalidate the pte. + * @entries_invalidate: clear out or invalidate a range of ptes. * @get_num_valid_entries: returns the number of valid entries for a specific pgd. * @set_num_valid_entries: sets the number of valid entries for a specific pgd * @flags: bitmask of MMU mode flags. Refer to KBASE_MMU_MODE_ constants. @@ -580,7 +579,7 @@ struct kbase_mmu_mode { void (*entry_set_ate)(u64 *entry, struct tagged_addr phy, unsigned long flags, int level); void (*entry_set_pte)(u64 *entry, phys_addr_t phy); - void (*entry_invalidate)(u64 *entry); + void (*entries_invalidate)(u64 *entry, u32 count); unsigned int (*get_num_valid_entries)(u64 *pgd); void (*set_num_valid_entries)(u64 *pgd, unsigned int num_of_valid_entries); @@ -647,6 +646,30 @@ struct kbase_process { struct rb_root dma_buf_root; }; +/** + * struct kbase_mem_migrate - Object representing an instance for managing + * page migration. + * + * @mapping: Pointer to address space struct used for page migration. + * @free_pages_list: List of deferred pages to free. Mostly used when page migration + * is enabled. Pages in memory pool that require migrating + * will be freed instead. However page cannot be freed + * right away as Linux will need to release the page lock. + * Therefore page will be added to this list and freed later. + * @free_pages_lock: This lock should be held when adding or removing pages + * from @free_pages_list. + * @free_pages_workq: Work queue to process the work items queued to free + * pages in @free_pages_list. + * @free_pages_work: Work item to free pages in @free_pages_list. + */ +struct kbase_mem_migrate { + struct address_space *mapping; + struct list_head free_pages_list; + spinlock_t free_pages_lock; + struct workqueue_struct *free_pages_workq; + struct work_struct free_pages_work; +}; + /** * struct kbase_device - Object representing an instance of GPU platform device, * allocated from the probe method of mali driver. @@ -962,6 +985,7 @@ struct kbase_process { * @pcm_dev: The priority control manager device. * @oom_notifier_block: notifier_block containing kernel-registered out-of- * memory handler. + * @mem_migrate: Per device object for managing page migration. */ struct kbase_device { u32 hw_quirks_sc; @@ -1029,6 +1053,12 @@ struct kbase_device { s8 nr_hw_address_spaces; s8 nr_user_address_spaces; + /** + * @pbha_propagate_bits: Record of Page-Based Hardware Attribute Propagate bits to + * restore to L2_CONFIG upon GPU reset. + */ + u8 pbha_propagate_bits; + #if MALI_USE_CSF struct kbase_hwcnt_backend_csf_if hwcnt_backend_csf_if_fw; #else @@ -1115,7 +1145,9 @@ struct kbase_device { #endif /* CONFIG_MALI_BIFROST_DEVFREQ */ unsigned long previous_frequency; +#if !MALI_USE_CSF atomic_t job_fault_debug; +#endif /* !MALI_USE_CSF */ #if IS_ENABLED(CONFIG_DEBUG_FS) struct dentry *mali_debugfs_directory; @@ -1126,11 +1158,13 @@ struct kbase_device { u64 debugfs_as_read_bitmap; #endif /* CONFIG_MALI_BIFROST_DEBUG */ +#if !MALI_USE_CSF wait_queue_head_t job_fault_wq; wait_queue_head_t job_fault_resume_wq; struct workqueue_struct *job_fault_resume_workq; struct list_head job_fault_event_list; spinlock_t job_fault_event_lock; +#endif /* !MALI_USE_CSF */ #if !MALI_CUSTOMER_RELEASE struct { @@ -1250,6 +1284,8 @@ struct kbase_device { */ u32 num_of_atoms_hw_completed; #endif + + struct kbase_mem_migrate mem_migrate; }; /** @@ -1332,10 +1368,6 @@ struct kbase_file { * * @KCTX_DYING: Set when the context process is in the process of being evicted. * - * @KCTX_NO_IMPLICIT_SYNC: Set when explicit Android fences are in use on this - * context, to disable use of implicit dma-buf fences. This is used to avoid - * potential synchronization deadlocks. - * * @KCTX_FORCE_SAME_VA: Set when BASE_MEM_SAME_VA should be forced on memory * allocations. For 64-bit clients it is enabled by default, and disabled by * default on 32-bit clients. Being able to clear this flag is only used for @@ -1378,7 +1410,6 @@ enum kbase_context_flags { KCTX_PRIVILEGED = 1U << 7, KCTX_SCHEDULED = 1U << 8, KCTX_DYING = 1U << 9, - KCTX_NO_IMPLICIT_SYNC = 1U << 10, KCTX_FORCE_SAME_VA = 1U << 11, KCTX_PULLED_SINCE_ACTIVE_JS0 = 1U << 12, KCTX_PULLED_SINCE_ACTIVE_JS1 = 1U << 13, @@ -1417,9 +1448,6 @@ enum kbase_context_flags { * * @KCTX_DYING: Set when the context process is in the process of being evicted. * - * @KCTX_NO_IMPLICIT_SYNC: Set when explicit Android fences are in use on this - * context, to disable use of implicit dma-buf fences. This is used to avoid - * potential synchronization deadlocks. * * @KCTX_FORCE_SAME_VA: Set when BASE_MEM_SAME_VA should be forced on memory * allocations. For 64-bit clients it is enabled by default, and disabled by @@ -1460,7 +1488,6 @@ enum kbase_context_flags { KCTX_PRIVILEGED = 1U << 7, KCTX_SCHEDULED = 1U << 8, KCTX_DYING = 1U << 9, - KCTX_NO_IMPLICIT_SYNC = 1U << 10, KCTX_FORCE_SAME_VA = 1U << 11, KCTX_PULLED_SINCE_ACTIVE_JS0 = 1U << 12, KCTX_PULLED_SINCE_ACTIVE_JS1 = 1U << 13, @@ -1667,12 +1694,6 @@ struct kbase_sub_alloc { * memory allocations. * @jit_current_allocations_per_bin: Current number of in-flight just-in-time * memory allocations per bin. - * @jit_version: Version number indicating whether userspace is using - * old or new version of interface for just-in-time - * memory allocations. - * 1 -> client used KBASE_IOCTL_MEM_JIT_INIT_10_2 - * 2 -> client used KBASE_IOCTL_MEM_JIT_INIT_11_5 - * 3 -> client used KBASE_IOCTL_MEM_JIT_INIT * @jit_group_id: A memory group ID to be passed to a platform-specific * memory group manager. * Valid range is 0..(MEMORY_GROUP_MANAGER_NR_GROUPS-1). @@ -1826,12 +1847,6 @@ struct kbase_context { struct list_head waiting_soft_jobs; spinlock_t waiting_soft_jobs_lock; -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - struct { - struct list_head waiting_resource; - struct workqueue_struct *wq; - } dma_fence; -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ int as_nr; @@ -1863,7 +1878,6 @@ struct kbase_context { u8 jit_max_allocations; u8 jit_current_allocations; u8 jit_current_allocations_per_bin[256]; - u8 jit_version; u8 jit_group_id; #if MALI_JIT_PRESSURE_LIMIT_BASE u64 jit_phys_pages_limit; @@ -1930,17 +1944,15 @@ struct kbasep_gwt_list_element { * to a @kbase_context. * @ext_res_node: List head for adding the metadata to a * @kbase_context. - * @alloc: The physical memory allocation structure - * which is mapped. - * @gpu_addr: The GPU virtual address the resource is - * mapped to. + * @reg: External resource information, containing + * the corresponding VA region * @ref: Reference count. * * External resources can be mapped into multiple contexts as well as the same * context multiple times. - * As kbase_va_region itself isn't refcounted we can't attach our extra - * information to it as it could be removed under our feet leaving external - * resources pinned. + * As kbase_va_region is refcounted, we guarantee that it will be available + * for the duration of the external resource, meaning it is sufficient to use + * it to rederive any additional data, like the GPU address. * This metadata structure binds a single external resource to a single * context, ensuring that per context mapping is tracked separately so it can * be overridden when needed and abuses by the application (freeing the resource @@ -1948,8 +1960,7 @@ struct kbasep_gwt_list_element { */ struct kbase_ctx_ext_res_meta { struct list_head ext_res_node; - struct kbase_mem_phy_alloc *alloc; - u64 gpu_addr; + struct kbase_va_region *reg; u32 ref; }; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c deleted file mode 100644 index d5f4fae091e8..000000000000 --- a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.c +++ /dev/null @@ -1,491 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2011-2016, 2020-2021 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 mali_kbase_dma_fence.h before checking for CONFIG_MALI_BIFROST_DMA_FENCE as - * it will be set there. - */ -#include "mali_kbase_dma_fence.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void -kbase_dma_fence_work(struct work_struct *pwork); - -static void -kbase_dma_fence_waiters_add(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - - list_add_tail(&katom->queue, &kctx->dma_fence.waiting_resource); -} - -static void -kbase_dma_fence_waiters_remove(struct kbase_jd_atom *katom) -{ - list_del(&katom->queue); -} - -static int -kbase_dma_fence_lock_reservations(struct kbase_dma_fence_resv_info *info, - struct ww_acquire_ctx *ctx) -{ -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - struct reservation_object *content_res = NULL; -#else - struct dma_resv *content_res = NULL; -#endif - unsigned int content_res_idx = 0; - unsigned int r; - int err = 0; - - ww_acquire_init(ctx, &reservation_ww_class); - -retry: - for (r = 0; r < info->dma_fence_resv_count; r++) { - if (info->resv_objs[r] == content_res) { - content_res = NULL; - continue; - } - - err = ww_mutex_lock(&info->resv_objs[r]->lock, ctx); - if (err) - goto error; - } - - ww_acquire_done(ctx); - return err; - -error: - content_res_idx = r; - - /* Unlock the locked one ones */ - while (r--) - ww_mutex_unlock(&info->resv_objs[r]->lock); - - if (content_res) - ww_mutex_unlock(&content_res->lock); - - /* If we deadlock try with lock_slow and retry */ - if (err == -EDEADLK) { - content_res = info->resv_objs[content_res_idx]; - ww_mutex_lock_slow(&content_res->lock, ctx); - goto retry; - } - - /* If we are here the function failed */ - ww_acquire_fini(ctx); - return err; -} - -static void -kbase_dma_fence_unlock_reservations(struct kbase_dma_fence_resv_info *info, - struct ww_acquire_ctx *ctx) -{ - unsigned int r; - - for (r = 0; r < info->dma_fence_resv_count; r++) - ww_mutex_unlock(&info->resv_objs[r]->lock); - ww_acquire_fini(ctx); -} - - - -/** - * kbase_dma_fence_queue_work() - Queue work to handle @katom - * @katom: Pointer to atom for which to queue work - * - * Queue kbase_dma_fence_work() for @katom to clean up the fence callbacks and - * submit the atom. - */ -static void -kbase_dma_fence_queue_work(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - bool ret; - - INIT_WORK(&katom->work, kbase_dma_fence_work); - ret = queue_work(kctx->dma_fence.wq, &katom->work); - /* Warn if work was already queued, that should not happen. */ - WARN_ON(!ret); -} - -/** - * kbase_dma_fence_cancel_atom() - Cancels waiting on an atom - * @katom: Katom to cancel - * - * Locking: katom->dma_fence.callbacks list assumes jctx.lock is held. - */ -static void -kbase_dma_fence_cancel_atom(struct kbase_jd_atom *katom) -{ - lockdep_assert_held(&katom->kctx->jctx.lock); - - /* Cancel callbacks and clean up. */ - kbase_fence_free_callbacks(katom); - - /* Mark the atom as handled in case all fences signaled just before - * canceling the callbacks and the worker was queued. - */ - kbase_fence_dep_count_set(katom, -1); - - /* Prevent job_done_nolock from being called twice on an atom when - * there is a race between job completion and cancellation. - */ - - if (katom->status == KBASE_JD_ATOM_STATE_QUEUED) { - /* Wait was cancelled - zap the atom */ - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - if (kbase_jd_done_nolock(katom, true)) - kbase_js_sched_all(katom->kctx->kbdev); - } -} - -/** - * kbase_dma_fence_work() - Worker thread called when a fence is signaled - * @pwork: work_struct containing a pointer to a katom - * - * This function will clean and mark all dependencies as satisfied - */ -static void -kbase_dma_fence_work(struct work_struct *pwork) -{ - struct kbase_jd_atom *katom; - struct kbase_jd_context *ctx; - - katom = container_of(pwork, struct kbase_jd_atom, work); - ctx = &katom->kctx->jctx; - - mutex_lock(&ctx->lock); - if (kbase_fence_dep_count_read(katom) != 0) - goto out; - - kbase_fence_dep_count_set(katom, -1); - - /* Remove atom from list of dma-fence waiting atoms. */ - kbase_dma_fence_waiters_remove(katom); - /* Cleanup callbacks. */ - kbase_fence_free_callbacks(katom); - /* - * Queue atom on GPU, unless it has already completed due to a failing - * dependency. Run kbase_jd_done_nolock() on the katom if it is completed. - */ - if (unlikely(katom->status == KBASE_JD_ATOM_STATE_COMPLETED)) - kbase_jd_done_nolock(katom, true); - else - kbase_jd_dep_clear_locked(katom); - -out: - mutex_unlock(&ctx->lock); -} - -static void -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) -kbase_dma_fence_cb(struct fence *fence, struct fence_cb *cb) -#else -kbase_dma_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb) -#endif -{ - struct kbase_fence_cb *kcb = container_of(cb, - struct kbase_fence_cb, - fence_cb); - struct kbase_jd_atom *katom = kcb->katom; - - /* If the atom is zapped dep_count will be forced to a negative number - * preventing this callback from ever scheduling work. Which in turn - * would reschedule the atom. - */ - - if (kbase_fence_dep_count_dec_and_test(katom)) - kbase_dma_fence_queue_work(katom); -} - -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) -static int -kbase_dma_fence_add_reservation_callback(struct kbase_jd_atom *katom, - struct reservation_object *resv, - bool exclusive) -#else -static int -kbase_dma_fence_add_reservation_callback(struct kbase_jd_atom *katom, - struct dma_resv *resv, - bool exclusive) -#endif -{ -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) - struct fence *excl_fence = NULL; - struct fence **shared_fences = NULL; -#else - struct dma_fence *excl_fence = NULL; - struct dma_fence **shared_fences = NULL; -#endif - unsigned int shared_count = 0; - int err, i; - -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - err = reservation_object_get_fences_rcu( -#elif (KERNEL_VERSION(5, 14, 0) > LINUX_VERSION_CODE) - err = dma_resv_get_fences_rcu( -#else - err = dma_resv_get_fences( -#endif - resv, - &excl_fence, - &shared_count, - &shared_fences); - if (err) - return err; - - if (excl_fence) { - err = kbase_fence_add_callback(katom, - excl_fence, - kbase_dma_fence_cb); - - /* Release our reference, taken by reservation_object_get_fences_rcu(), - * to the fence. We have set up our callback (if that was possible), - * and it's the fence's owner is responsible for singling the fence - * before allowing it to disappear. - */ - dma_fence_put(excl_fence); - - if (err) - goto out; - } - - if (exclusive) { - for (i = 0; i < shared_count; i++) { - err = kbase_fence_add_callback(katom, - shared_fences[i], - kbase_dma_fence_cb); - if (err) - goto out; - } - } - - /* Release all our references to the shared fences, taken by - * reservation_object_get_fences_rcu(). We have set up our callback (if - * that was possible), and it's the fence's owner is responsible for - * signaling the fence before allowing it to disappear. - */ -out: - for (i = 0; i < shared_count; i++) - dma_fence_put(shared_fences[i]); - kfree(shared_fences); - - if (err) { - /* - * On error, cancel and clean up all callbacks that was set up - * before the error. - */ - kbase_fence_free_callbacks(katom); - } - - return err; -} - -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) -void kbase_dma_fence_add_reservation(struct reservation_object *resv, - struct kbase_dma_fence_resv_info *info, - bool exclusive) -#else -void kbase_dma_fence_add_reservation(struct dma_resv *resv, - struct kbase_dma_fence_resv_info *info, - bool exclusive) -#endif -{ - unsigned int i; - - for (i = 0; i < info->dma_fence_resv_count; i++) { - /* Duplicate resource, ignore */ - if (info->resv_objs[i] == resv) - return; - } - - info->resv_objs[info->dma_fence_resv_count] = resv; - if (exclusive) - set_bit(info->dma_fence_resv_count, - info->dma_fence_excl_bitmap); - (info->dma_fence_resv_count)++; -} - -int kbase_dma_fence_wait(struct kbase_jd_atom *katom, - struct kbase_dma_fence_resv_info *info) -{ - int err, i; -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) - struct fence *fence; -#else - struct dma_fence *fence; -#endif - struct ww_acquire_ctx ww_ctx; - - lockdep_assert_held(&katom->kctx->jctx.lock); - - fence = kbase_fence_out_new(katom); - if (!fence) { - err = -ENOMEM; - dev_err(katom->kctx->kbdev->dev, - "Error %d creating fence.\n", err); - return err; - } - - kbase_fence_dep_count_set(katom, 1); - - err = kbase_dma_fence_lock_reservations(info, &ww_ctx); - if (err) { - dev_err(katom->kctx->kbdev->dev, - "Error %d locking reservations.\n", err); - kbase_fence_dep_count_set(katom, -1); - kbase_fence_out_remove(katom); - return err; - } - - for (i = 0; i < info->dma_fence_resv_count; i++) { -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - struct reservation_object *obj = info->resv_objs[i]; -#else - struct dma_resv *obj = info->resv_objs[i]; -#endif - if (!test_bit(i, info->dma_fence_excl_bitmap)) { -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - err = reservation_object_reserve_shared(obj); -#else - err = dma_resv_reserve_shared(obj, 0); -#endif - if (err) { - dev_err(katom->kctx->kbdev->dev, - "Error %d reserving space for shared fence.\n", err); - goto end; - } - - err = kbase_dma_fence_add_reservation_callback(katom, obj, false); - if (err) { - dev_err(katom->kctx->kbdev->dev, - "Error %d adding reservation to callback.\n", err); - goto end; - } - -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - reservation_object_add_shared_fence(obj, fence); -#else - dma_resv_add_shared_fence(obj, fence); -#endif - } else { - err = kbase_dma_fence_add_reservation_callback(katom, obj, true); - if (err) { - dev_err(katom->kctx->kbdev->dev, - "Error %d adding reservation to callback.\n", err); - goto end; - } - -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - reservation_object_add_excl_fence(obj, fence); -#else - dma_resv_add_excl_fence(obj, fence); -#endif - } - } - -end: - kbase_dma_fence_unlock_reservations(info, &ww_ctx); - - if (likely(!err)) { - /* Test if the callbacks are already triggered */ - if (kbase_fence_dep_count_dec_and_test(katom)) { - kbase_fence_dep_count_set(katom, -1); - kbase_fence_free_callbacks(katom); - } else { - /* Add katom to the list of dma-buf fence waiting atoms - * only if it is still waiting. - */ - kbase_dma_fence_waiters_add(katom); - } - } else { - /* There was an error, cancel callbacks, set dep_count to -1 to - * indicate that the atom has been handled (the caller will - * kill it for us), signal the fence, free callbacks and the - * fence. - */ - kbase_fence_free_callbacks(katom); - kbase_fence_dep_count_set(katom, -1); - kbase_dma_fence_signal(katom); - } - - return err; -} - -void kbase_dma_fence_cancel_all_atoms(struct kbase_context *kctx) -{ - struct list_head *list = &kctx->dma_fence.waiting_resource; - - while (!list_empty(list)) { - struct kbase_jd_atom *katom; - - katom = list_first_entry(list, struct kbase_jd_atom, queue); - kbase_dma_fence_waiters_remove(katom); - kbase_dma_fence_cancel_atom(katom); - } -} - -void kbase_dma_fence_cancel_callbacks(struct kbase_jd_atom *katom) -{ - /* Cancel callbacks and clean up. */ - if (kbase_fence_free_callbacks(katom)) - kbase_dma_fence_queue_work(katom); -} - -void kbase_dma_fence_signal(struct kbase_jd_atom *katom) -{ - if (!katom->dma_fence.fence) - return; - - /* Signal the atom's fence. */ - dma_fence_signal(katom->dma_fence.fence); - - kbase_fence_out_remove(katom); - - kbase_fence_free_callbacks(katom); -} - -void kbase_dma_fence_term(struct kbase_context *kctx) -{ - destroy_workqueue(kctx->dma_fence.wq); - kctx->dma_fence.wq = NULL; -} - -int kbase_dma_fence_init(struct kbase_context *kctx) -{ - INIT_LIST_HEAD(&kctx->dma_fence.waiting_resource); - - kctx->dma_fence.wq = alloc_workqueue("mali-fence-%d", - WQ_UNBOUND, 1, kctx->pid); - if (!kctx->dma_fence.wq) - return -ENOMEM; - - return 0; -} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h b/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h deleted file mode 100644 index f0c8d069b02c..000000000000 --- a/drivers/gpu/arm/bifrost/mali_kbase_dma_fence.h +++ /dev/null @@ -1,150 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2010-2016, 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. - * - */ - -#ifndef _KBASE_DMA_FENCE_H_ -#define _KBASE_DMA_FENCE_H_ - -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - -#include -#include -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) -#include -#else -#include -#endif -#include - -/* Forward declaration from mali_kbase_defs.h */ -struct kbase_jd_atom; -struct kbase_context; - -/** - * struct kbase_dma_fence_resv_info - Structure with list of reservation objects - * @resv_objs: Array of reservation objects to attach the - * new fence to. - * @dma_fence_resv_count: Number of reservation objects in the array. - * @dma_fence_excl_bitmap: Specifies which resv_obj are exclusive. - * - * This is used by some functions to pass around a collection of data about - * reservation objects. - */ -struct kbase_dma_fence_resv_info { -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - struct reservation_object **resv_objs; -#else - struct dma_resv **resv_objs; -#endif - unsigned int dma_fence_resv_count; - unsigned long *dma_fence_excl_bitmap; -}; - -/** - * kbase_dma_fence_add_reservation() - Adds a resv to the array of resv_objs - * @resv: Reservation object to add to the array. - * @info: Pointer to struct with current reservation info - * @exclusive: Boolean indicating if exclusive access is needed - * - * The function adds a new reservation_object to an existing array of - * reservation_objects. At the same time keeps track of which objects require - * exclusive access in dma_fence_excl_bitmap. - */ -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) -void kbase_dma_fence_add_reservation(struct reservation_object *resv, - struct kbase_dma_fence_resv_info *info, - bool exclusive); -#else -void kbase_dma_fence_add_reservation(struct dma_resv *resv, - struct kbase_dma_fence_resv_info *info, - bool exclusive); -#endif - -/** - * kbase_dma_fence_wait() - Creates a new fence and attaches it to the resv_objs - * @katom: Katom with the external dependency. - * @info: Pointer to struct with current reservation info - * - * Return: An error code or 0 if succeeds - */ -int kbase_dma_fence_wait(struct kbase_jd_atom *katom, - struct kbase_dma_fence_resv_info *info); - -/** - * kbase_dma_fence_cancel_all_atoms() - Cancel all dma-fences blocked atoms on kctx - * @kctx: Pointer to kbase context - * - * This function will cancel and clean up all katoms on @kctx that is waiting - * on dma-buf fences. - * - * Locking: jctx.lock needs to be held when calling this function. - */ -void kbase_dma_fence_cancel_all_atoms(struct kbase_context *kctx); - -/** - * kbase_dma_fence_cancel_callbacks() - Cancel only callbacks on katom - * @katom: Pointer to katom whose callbacks are to be canceled - * - * This function cancels all dma-buf fence callbacks on @katom, but does not - * cancel the katom itself. - * - * 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. - */ -void kbase_dma_fence_cancel_callbacks(struct kbase_jd_atom *katom); - -/** - * kbase_dma_fence_signal() - Signal katom's fence and clean up after wait - * @katom: Pointer to katom to signal and clean up - * - * This function will signal the @katom's fence, if it has one, and clean up - * the callback data from the katom's wait on earlier fences. - * - * Locking: jctx.lock must be held while calling this function. - */ -void kbase_dma_fence_signal(struct kbase_jd_atom *katom); - -/** - * kbase_dma_fence_term() - Terminate Mali dma-fence context - * @kctx: kbase context to terminate - */ -void kbase_dma_fence_term(struct kbase_context *kctx); - -/** - * kbase_dma_fence_init() - Initialize Mali dma-fence context - * @kctx: kbase context to initialize - * - * Return: 0 on success, error code otherwise. - */ -int kbase_dma_fence_init(struct kbase_context *kctx); - -#else /* CONFIG_MALI_BIFROST_DMA_FENCE */ -/* Dummy functions for when dma-buf fence isn't enabled. */ - -static inline int kbase_dma_fence_init(struct kbase_context *kctx) -{ - return 0; -} - -static inline void kbase_dma_fence_term(struct kbase_context *kctx) {} -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ -#endif diff --git a/drivers/gpu/arm/bifrost/mali_kbase_fence.c b/drivers/gpu/arm/bifrost/mali_kbase_fence.c index 01557cd3ba47..b16b27659e61 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_fence.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_fence.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 @@ -59,95 +59,3 @@ kbase_fence_out_new(struct kbase_jd_atom *katom) return fence; } -bool -kbase_fence_free_callbacks(struct kbase_jd_atom *katom) -{ - struct kbase_fence_cb *cb, *tmp; - bool res = false; - - lockdep_assert_held(&katom->kctx->jctx.lock); - - /* Clean up and free callbacks. */ - list_for_each_entry_safe(cb, tmp, &katom->dma_fence.callbacks, node) { - bool ret; - - /* Cancel callbacks that hasn't been called yet. */ - ret = dma_fence_remove_callback(cb->fence, &cb->fence_cb); - if (ret) { - int ret; - - /* Fence had not signaled, clean up after - * canceling. - */ - ret = atomic_dec_return(&katom->dma_fence.dep_count); - - if (unlikely(ret == 0)) - res = true; - } - - /* - * Release the reference taken in - * kbase_fence_add_callback(). - */ - dma_fence_put(cb->fence); - list_del(&cb->node); - kfree(cb); - } - - return res; -} - -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) -int -kbase_fence_add_callback(struct kbase_jd_atom *katom, - struct fence *fence, - fence_func_t callback) -#else -int -kbase_fence_add_callback(struct kbase_jd_atom *katom, - struct dma_fence *fence, - dma_fence_func_t callback) -#endif -{ - int err = 0; - struct kbase_fence_cb *kbase_fence_cb; - - if (!fence) - return -EINVAL; - - kbase_fence_cb = kmalloc(sizeof(*kbase_fence_cb), GFP_KERNEL); - if (!kbase_fence_cb) - return -ENOMEM; - - kbase_fence_cb->fence = fence; - kbase_fence_cb->katom = katom; - INIT_LIST_HEAD(&kbase_fence_cb->node); - atomic_inc(&katom->dma_fence.dep_count); - - err = dma_fence_add_callback(fence, &kbase_fence_cb->fence_cb, - callback); - if (err == -ENOENT) { - /* Fence signaled, get the completion result */ - err = dma_fence_get_status(fence); - - /* remap success completion to err code */ - if (err == 1) - err = 0; - - kfree(kbase_fence_cb); - atomic_dec(&katom->dma_fence.dep_count); - } else if (err) { - kfree(kbase_fence_cb); - atomic_dec(&katom->dma_fence.dep_count); - } else { - /* - * Get reference to fence that will be kept until callback gets - * cleaned up in kbase_fence_free_callbacks(). - */ - dma_fence_get(fence); - /* Add callback to katom's list of callbacks */ - list_add(&kbase_fence_cb->node, &katom->dma_fence.callbacks); - } - - return err; -} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_fence.h b/drivers/gpu/arm/bifrost/mali_kbase_fence.h index 4f952ad4d509..dfe33e52b4ce 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_fence.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_fence.h @@ -23,12 +23,11 @@ #define _KBASE_FENCE_H_ /* - * mali_kbase_fence.[hc] has common fence code used by both - * - CONFIG_MALI_BIFROST_DMA_FENCE - implicit DMA fences - * - CONFIG_SYNC_FILE - explicit fences beginning with 4.9 kernel + * mali_kbase_fence.[hc] has fence code used only by + * - CONFIG_SYNC_FILE - explicit fences */ -#if defined(CONFIG_MALI_BIFROST_DMA_FENCE) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) #include #include "mali_kbase_fence_defs.h" @@ -40,25 +39,6 @@ extern const struct fence_ops kbase_fence_ops; extern const struct dma_fence_ops kbase_fence_ops; #endif -/** - * struct kbase_fence_cb - Mali dma-fence callback data struct - * @fence_cb: Callback function - * @katom: Pointer to katom that is waiting on this callback - * @fence: Pointer to the fence object on which this callback is waiting - * @node: List head for linking this callback to the katom - */ -struct kbase_fence_cb { -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) - struct fence_cb fence_cb; - struct fence *fence; -#else - struct dma_fence_cb fence_cb; - struct dma_fence *fence; -#endif - struct kbase_jd_atom *katom; - struct list_head node; -}; - /** * kbase_fence_out_new() - Creates a new output fence and puts it on the atom * @katom: Atom to create an output fence for @@ -71,7 +51,7 @@ struct fence *kbase_fence_out_new(struct kbase_jd_atom *katom); struct dma_fence *kbase_fence_out_new(struct kbase_jd_atom *katom); #endif -#if defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) /** * kbase_fence_fence_in_set() - Assign input fence to atom * @katom: Atom to assign input fence to @@ -102,7 +82,7 @@ static inline void kbase_fence_out_remove(struct kbase_jd_atom *katom) } } -#if defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) /** * kbase_fence_in_remove() - Removes the input fence from atom * @katom: Atom to remove input fence for @@ -153,101 +133,7 @@ static inline int kbase_fence_out_signal(struct kbase_jd_atom *katom, return dma_fence_signal(katom->dma_fence.fence); } -/** - * kbase_fence_add_callback() - Add callback on @fence to block @katom - * @katom: Pointer to katom that will be blocked by @fence - * @fence: Pointer to fence on which to set up the callback - * @callback: Pointer to function to be called when fence is signaled - * - * Caller needs to hold a reference to @fence when calling this function, and - * the caller is responsible for releasing that reference. An additional - * reference to @fence will be taken when the callback was successfully set up - * and @fence needs to be kept valid until the callback has been called and - * cleanup have been done. - * - * Return: 0 on success: fence was either already signaled, or callback was - * set up. Negative error code is returned on error. - */ -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) -int kbase_fence_add_callback(struct kbase_jd_atom *katom, - struct fence *fence, - fence_func_t callback); -#else -int kbase_fence_add_callback(struct kbase_jd_atom *katom, - struct dma_fence *fence, - dma_fence_func_t callback); -#endif - -/** - * kbase_fence_dep_count_set() - Set dep_count value on atom to specified value - * @katom: Atom to set dep_count for - * @val: value to set dep_count to - * - * The dep_count is available to the users of this module so that they can - * synchronize completion of the wait with cancellation and adding of more - * callbacks. For instance, a user could do the following: - * - * dep_count set to 1 - * callback #1 added, dep_count is increased to 2 - * callback #1 happens, dep_count decremented to 1 - * since dep_count > 0, no completion is done - * callback #2 is added, dep_count is increased to 2 - * dep_count decremented to 1 - * callback #2 happens, dep_count decremented to 0 - * since dep_count now is zero, completion executes - * - * The dep_count can also be used to make sure that the completion only - * executes once. This is typically done by setting dep_count to -1 for the - * thread that takes on this responsibility. - */ -static inline void -kbase_fence_dep_count_set(struct kbase_jd_atom *katom, int val) -{ - atomic_set(&katom->dma_fence.dep_count, val); -} - -/** - * kbase_fence_dep_count_dec_and_test() - Decrements dep_count - * @katom: Atom to decrement dep_count for - * - * See @kbase_fence_dep_count_set for general description about dep_count - * - * Return: true if value was decremented to zero, otherwise false - */ -static inline bool -kbase_fence_dep_count_dec_and_test(struct kbase_jd_atom *katom) -{ - return atomic_dec_and_test(&katom->dma_fence.dep_count); -} - -/** - * kbase_fence_dep_count_read() - Returns the current dep_count value - * @katom: Pointer to katom - * - * See @kbase_fence_dep_count_set for general description about dep_count - * - * Return: The current dep_count value - */ -static inline int kbase_fence_dep_count_read(struct kbase_jd_atom *katom) -{ - return atomic_read(&katom->dma_fence.dep_count); -} - -/** - * kbase_fence_free_callbacks() - Free dma-fence callbacks on a katom - * @katom: Pointer to katom - * - * This function will free all fence callbacks on the katom's list of - * callbacks. Callbacks that have not yet been called, because their fence - * hasn't yet signaled, will first be removed from the fence. - * - * Locking: katom->dma_fence.callbacks list assumes jctx.lock is held. - * - * Return: true if dep_count reached 0, otherwise false. - */ -bool kbase_fence_free_callbacks(struct kbase_jd_atom *katom); - -#if defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) /** * kbase_fence_in_get() - Retrieve input fence for atom. * @katom: Atom to get input fence from @@ -288,6 +174,6 @@ bool kbase_fence_free_callbacks(struct kbase_jd_atom *katom); #define kbase_fence_put(fence) dma_fence_put(fence) -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE || defined(CONFIG_SYNC_FILE */ +#endif /* IS_ENABLED(CONFIG_SYNC_FILE) */ #endif /* _KBASE_FENCE_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c index 0bea655178d5..0282aaf8eb3a 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_gpuprops.c @@ -677,9 +677,11 @@ int kbase_gpuprops_update_l2_features(struct kbase_device *kbdev) int idx; const bool asn_he = regdump.l2_config & L2_CONFIG_ASN_HASH_ENABLE_MASK; +#if !IS_ENABLED(CONFIG_MALI_BIFROST_NO_MALI) if (!asn_he && kbdev->l2_hash_values_override) dev_err(kbdev->dev, "Failed to use requested ASN_HASH, fallback to default"); +#endif for (idx = 0; idx < ASN_HASH_COUNT; idx++) dev_info(kbdev->dev, "%s ASN_HASH[%d] is [0x%08x]\n", @@ -705,10 +707,6 @@ static struct { #define PROP(name, member) \ {KBASE_GPUPROP_ ## name, offsetof(struct base_gpu_props, member), \ sizeof(((struct base_gpu_props *)0)->member)} -#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), @@ -722,6 +720,10 @@ static struct { PROP(GPU_AVAILABLE_MEMORY_SIZE, core_props.gpu_available_memory_size), #if MALI_USE_CSF +#define BACKWARDS_COMPAT_PROP(name, type) \ + { \ + KBASE_GPUPROP_##name, SIZE_MAX, sizeof(type) \ + } BACKWARDS_COMPAT_PROP(NUM_EXEC_ENGINES, u8), #else PROP(NUM_EXEC_ENGINES, core_props.num_exec_engines), @@ -820,7 +822,7 @@ int kbase_gpuprops_populate_user_buffer(struct kbase_device *kbdev) } kprops->prop_buffer_size = size; - kprops->prop_buffer = kmalloc(size, GFP_KERNEL); + kprops->prop_buffer = kzalloc(size, GFP_KERNEL); if (!kprops->prop_buffer) { kprops->prop_buffer_size = 0; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_hw.c b/drivers/gpu/arm/bifrost/mali_kbase_hw.c index 1de1e29fcb75..b6a8a2e5608f 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_hw.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_hw.c @@ -85,6 +85,10 @@ void kbase_hw_set_features_mask(struct kbase_device *kbdev) case GPU_ID2_PRODUCT_LTUX: features = base_hw_features_tTUx; break; + case GPU_ID2_PRODUCT_TTIX: + case GPU_ID2_PRODUCT_LTIX: + features = base_hw_features_tTIx; + break; default: features = base_hw_features_generic; break; @@ -233,12 +237,22 @@ static const enum base_hw_issue *kbase_hw_get_issues_for_new_id( { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tTUx_r0p0 }, { GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tTUx_r1p0 }, { GPU_ID2_VERSION_MAKE(1, 1, 0), base_hw_issues_tTUx_r1p1 }, + { GPU_ID2_VERSION_MAKE(1, 2, 0), base_hw_issues_tTUx_r1p2 }, { U32_MAX, NULL } } }, { GPU_ID2_PRODUCT_LTUX, { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tTUx_r0p0 }, { GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tTUx_r1p0 }, { GPU_ID2_VERSION_MAKE(1, 1, 0), base_hw_issues_tTUx_r1p1 }, + { GPU_ID2_VERSION_MAKE(1, 2, 0), base_hw_issues_tTUx_r1p2 }, + { U32_MAX, NULL } } }, + + { GPU_ID2_PRODUCT_TTIX, + { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tTIx_r0p0 }, + { U32_MAX, NULL } } }, + + { GPU_ID2_PRODUCT_LTIX, + { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tTIx_r0p0 }, { U32_MAX, NULL } } }, }; @@ -396,6 +410,10 @@ int kbase_hw_set_issues_mask(struct kbase_device *kbdev) case GPU_ID2_PRODUCT_LTUX: issues = base_hw_issues_model_tTUx; break; + case GPU_ID2_PRODUCT_TTIX: + case GPU_ID2_PRODUCT_LTIX: + issues = base_hw_issues_model_tTIx; + break; default: dev_err(kbdev->dev, diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jd.c b/drivers/gpu/arm/bifrost/mali_kbase_jd.c index 5a96f924bfbd..f5faa92525c5 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_jd.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_jd.c @@ -35,7 +35,6 @@ #include #include -#include "mali_kbase_dma_fence.h" #include #include @@ -158,15 +157,6 @@ void kbase_jd_dep_clear_locked(struct kbase_jd_atom *katom) void kbase_jd_free_external_resources(struct kbase_jd_atom *katom) { -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - /* Flush dma-fence workqueue to ensure that any callbacks that may have - * been queued are done before continuing. - * Any successfully completed atom would have had all it's callbacks - * completed before the atom was run, so only flush for failed atoms. - */ - if (katom->event_code != BASE_JD_EVENT_DONE) - flush_workqueue(katom->kctx->dma_fence.wq); -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ } static void kbase_jd_post_external_resources(struct kbase_jd_atom *katom) @@ -174,10 +164,6 @@ static void kbase_jd_post_external_resources(struct kbase_jd_atom *katom) KBASE_DEBUG_ASSERT(katom); KBASE_DEBUG_ASSERT(katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES); -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - kbase_dma_fence_signal(katom); -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ - kbase_gpu_vm_lock(katom->kctx); /* only roll back if extres is non-NULL */ if (katom->extres) { @@ -185,13 +171,7 @@ static void kbase_jd_post_external_resources(struct kbase_jd_atom *katom) res_no = katom->nr_extres; while (res_no-- > 0) { - struct kbase_mem_phy_alloc *alloc = katom->extres[res_no].alloc; - struct kbase_va_region *reg; - - reg = kbase_region_tracker_find_region_base_address( - katom->kctx, - katom->extres[res_no].gpu_address); - kbase_unmap_external_resource(katom->kctx, reg, alloc); + kbase_unmap_external_resource(katom->kctx, katom->extres[res_no]); } kfree(katom->extres); katom->extres = NULL; @@ -207,26 +187,8 @@ static void kbase_jd_post_external_resources(struct kbase_jd_atom *katom) static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const struct base_jd_atom *user_atom) { - int err_ret_val = -EINVAL; + int err = -EINVAL; u32 res_no; -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - struct kbase_dma_fence_resv_info info = { - .resv_objs = NULL, - .dma_fence_resv_count = 0, - .dma_fence_excl_bitmap = NULL - }; -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) - /* - * When both dma-buf fence and Android native sync is enabled, we - * disable dma-buf fence for contexts that are using Android native - * fences. - */ - const bool implicit_sync = !kbase_ctx_flag(katom->kctx, - KCTX_NO_IMPLICIT_SYNC); -#else /* CONFIG_SYNC || CONFIG_SYNC_FILE*/ - const bool implicit_sync = true; -#endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ struct base_external_resource *input_extres; KBASE_DEBUG_ASSERT(katom); @@ -240,68 +202,32 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st if (!katom->extres) return -ENOMEM; - /* copy user buffer to the end of our real buffer. - * Make sure the struct sizes haven't changed in a way - * we don't support - */ - BUILD_BUG_ON(sizeof(*input_extres) > sizeof(*katom->extres)); - input_extres = (struct base_external_resource *) - (((unsigned char *)katom->extres) + - (sizeof(*katom->extres) - sizeof(*input_extres)) * - katom->nr_extres); + input_extres = kmalloc_array(katom->nr_extres, sizeof(*input_extres), GFP_KERNEL); + if (!input_extres) { + err = -ENOMEM; + goto failed_input_alloc; + } if (copy_from_user(input_extres, get_compat_pointer(katom->kctx, user_atom->extres_list), sizeof(*input_extres) * katom->nr_extres) != 0) { - err_ret_val = -EINVAL; - goto early_err_out; + err = -EINVAL; + goto failed_input_copy; } -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - if (implicit_sync) { - info.resv_objs = - kmalloc_array(katom->nr_extres, -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - sizeof(struct reservation_object *), -#else - sizeof(struct dma_resv *), -#endif - GFP_KERNEL); - if (!info.resv_objs) { - err_ret_val = -ENOMEM; - goto early_err_out; - } - - info.dma_fence_excl_bitmap = - kcalloc(BITS_TO_LONGS(katom->nr_extres), - sizeof(unsigned long), GFP_KERNEL); - if (!info.dma_fence_excl_bitmap) { - err_ret_val = -ENOMEM; - goto early_err_out; - } - } -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ - /* Take the processes mmap lock */ down_read(kbase_mem_get_process_mmap_lock()); /* need to keep the GPU VM locked while we set up UMM buffers */ kbase_gpu_vm_lock(katom->kctx); for (res_no = 0; res_no < katom->nr_extres; res_no++) { - struct base_external_resource *res = &input_extres[res_no]; + struct base_external_resource *user_res = &input_extres[res_no]; struct kbase_va_region *reg; - struct kbase_mem_phy_alloc *alloc; -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - bool exclusive; - exclusive = (res->ext_resource & BASE_EXT_RES_ACCESS_EXCLUSIVE) - ? true : false; -#endif reg = kbase_region_tracker_find_region_enclosing_address( - katom->kctx, - res->ext_resource & ~BASE_EXT_RES_ACCESS_EXCLUSIVE); + katom->kctx, user_res->ext_resource & ~BASE_EXT_RES_ACCESS_EXCLUSIVE); /* did we find a matching region object? */ - if (kbase_is_region_invalid_or_free(reg)) { + if (unlikely(kbase_is_region_invalid_or_free(reg))) { /* roll back */ goto failed_loop; } @@ -311,36 +237,11 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st katom->atom_flags |= KBASE_KATOM_FLAG_PROTECTED; } - alloc = kbase_map_external_resource(katom->kctx, reg, - current->mm); - if (!alloc) { - err_ret_val = -EINVAL; + err = kbase_map_external_resource(katom->kctx, reg, current->mm); + if (err) goto failed_loop; - } -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - if (implicit_sync && - reg->gpu_alloc->type == KBASE_MEM_TYPE_IMPORTED_UMM) { -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) - struct reservation_object *resv; -#else - struct dma_resv *resv; -#endif - resv = reg->gpu_alloc->imported.umm.dma_buf->resv; - if (resv) - kbase_dma_fence_add_reservation(resv, &info, - exclusive); - } -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ - - /* finish with updating out array with the data we found */ - /* NOTE: It is important that this is the last thing we do (or - * at least not before the first write) as we overwrite elements - * as we loop and could be overwriting ourself, so no writes - * until the last read for an element. - */ - katom->extres[res_no].gpu_address = reg->start_pfn << PAGE_SHIFT; /* save the start_pfn (as an address, not pfn) to use fast lookup later */ - katom->extres[res_no].alloc = alloc; + katom->extres[res_no] = reg; } /* successfully parsed the extres array */ /* drop the vm lock now */ @@ -349,57 +250,33 @@ static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, const st /* Release the processes mmap lock */ up_read(kbase_mem_get_process_mmap_lock()); -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - if (implicit_sync) { - if (info.dma_fence_resv_count) { - int ret; - - ret = kbase_dma_fence_wait(katom, &info); - if (ret < 0) - goto failed_dma_fence_setup; - } - - kfree(info.resv_objs); - kfree(info.dma_fence_excl_bitmap); - } -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ + /* Free the buffer holding data from userspace */ + kfree(input_extres); /* all done OK */ return 0; /* error handling section */ - -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE -failed_dma_fence_setup: - /* Lock the processes mmap lock */ - down_read(kbase_mem_get_process_mmap_lock()); - - /* lock before we unmap */ - kbase_gpu_vm_lock(katom->kctx); -#endif - - failed_loop: - /* undo the loop work */ +failed_loop: + /* undo the loop work. We are guaranteed to have access to the VA region + * as we hold a reference to it until it's unmapped + */ while (res_no-- > 0) { - struct kbase_mem_phy_alloc *alloc = katom->extres[res_no].alloc; + struct kbase_va_region *reg = katom->extres[res_no]; - kbase_unmap_external_resource(katom->kctx, NULL, alloc); + kbase_unmap_external_resource(katom->kctx, reg); } kbase_gpu_vm_unlock(katom->kctx); /* Release the processes mmap lock */ up_read(kbase_mem_get_process_mmap_lock()); - early_err_out: +failed_input_copy: + kfree(input_extres); +failed_input_alloc: kfree(katom->extres); katom->extres = NULL; -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - if (implicit_sync) { - kfree(info.resv_objs); - kfree(info.dma_fence_excl_bitmap); - } -#endif - return err_ret_val; + return err; } static inline void jd_resolve_dep(struct list_head *out_list, @@ -422,10 +299,6 @@ static inline void jd_resolve_dep(struct list_head *out_list, if (katom->event_code != BASE_JD_EVENT_DONE && (dep_type != BASE_JD_DEP_TYPE_ORDER)) { -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - kbase_dma_fence_cancel_callbacks(dep_atom); -#endif - dep_atom->event_code = katom->event_code; KBASE_DEBUG_ASSERT(dep_atom->status != KBASE_JD_ATOM_STATE_UNUSED); @@ -439,35 +312,8 @@ static inline void jd_resolve_dep(struct list_head *out_list, (IS_GPU_ATOM(dep_atom) && !ctx_is_dying && !dep_atom->will_fail_event_code && !other_dep_atom->will_fail_event_code))) { - bool dep_satisfied = true; -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - int dep_count; - - dep_count = kbase_fence_dep_count_read(dep_atom); - if (likely(dep_count == -1)) { - dep_satisfied = true; - } else { - /* - * There are either still active callbacks, or - * all fences for this @dep_atom has signaled, - * but the worker that will queue the atom has - * not yet run. - * - * Wait for the fences to signal and the fence - * worker to run and handle @dep_atom. If - * @dep_atom was completed due to error on - * @katom, then the fence worker will pick up - * the complete status and error code set on - * @dep_atom above. - */ - dep_satisfied = false; - } -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ - - if (dep_satisfied) { - dep_atom->in_jd_list = true; - list_add_tail(&dep_atom->jd_item, out_list); - } + dep_atom->in_jd_list = true; + list_add_tail(&dep_atom->jd_item, out_list); } } } @@ -526,33 +372,8 @@ static void jd_try_submitting_deps(struct list_head *out_list, dep_atom->dep[0].atom); bool dep1_valid = is_dep_valid( dep_atom->dep[1].atom); - bool dep_satisfied = true; -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - int dep_count; - dep_count = kbase_fence_dep_count_read( - dep_atom); - if (likely(dep_count == -1)) { - dep_satisfied = true; - } else { - /* - * There are either still active callbacks, or - * all fences for this @dep_atom has signaled, - * but the worker that will queue the atom has - * not yet run. - * - * Wait for the fences to signal and the fence - * worker to run and handle @dep_atom. If - * @dep_atom was completed due to error on - * @katom, then the fence worker will pick up - * the complete status and error code set on - * @dep_atom above. - */ - dep_satisfied = false; - } -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ - - if (dep0_valid && dep1_valid && dep_satisfied) { + if (dep0_valid && dep1_valid) { dep_atom->in_jd_list = true; list_add(&dep_atom->jd_item, out_list); } @@ -963,9 +784,6 @@ static bool jd_submit_atom(struct kbase_context *const kctx, INIT_LIST_HEAD(&katom->queue); INIT_LIST_HEAD(&katom->jd_item); -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - kbase_fence_dep_count_set(katom, -1); -#endif /* Don't do anything if there is a mess up with dependencies. * This is done in a separate cycle to check both the dependencies at ones, otherwise @@ -1185,12 +1003,6 @@ static bool jd_submit_atom(struct kbase_context *const kctx, if (queued && !IS_GPU_ATOM(katom)) return false; -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - if (kbase_fence_dep_count_read(katom) != -1) - return false; - -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ - if (katom->core_req & BASE_JD_REQ_SOFT_JOB) { if (kbase_process_soft_job(katom) == 0) { kbase_finish_soft_job(katom); @@ -1273,7 +1085,7 @@ int kbase_jd_submit(struct kbase_context *kctx, if (unlikely(jd_atom_is_v2)) { if (copy_from_user(&user_atom.jc, user_addr, sizeof(struct base_jd_atom_v2)) != 0) { dev_dbg(kbdev->dev, - "Invalid atom address %p passed to job_submit\n", + "Invalid atom address %pK passed to job_submit\n", user_addr); err = -EFAULT; break; @@ -1284,7 +1096,7 @@ int kbase_jd_submit(struct kbase_context *kctx, } else { if (copy_from_user(&user_atom, user_addr, stride) != 0) { dev_dbg(kbdev->dev, - "Invalid atom address %p passed to job_submit\n", + "Invalid atom address %pK passed to job_submit\n", user_addr); err = -EFAULT; break; @@ -1599,6 +1411,7 @@ static void jd_cancel_worker(struct work_struct *data) bool need_to_try_schedule_context; bool attr_state_changed; struct kbase_device *kbdev; + CSTD_UNUSED(need_to_try_schedule_context); /* Soft jobs should never reach this function */ KBASE_DEBUG_ASSERT((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0); @@ -1746,20 +1559,8 @@ void kbase_jd_zap_context(struct kbase_context *kctx) kbase_cancel_soft_job(katom); } - -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - kbase_dma_fence_cancel_all_atoms(kctx); -#endif - mutex_unlock(&kctx->jctx.lock); -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - /* Flush dma-fence workqueue to ensure that any callbacks that may have - * been queued are done before continuing. - */ - flush_workqueue(kctx->dma_fence.wq); -#endif - #if IS_ENABLED(CONFIG_DEBUG_FS) kbase_debug_job_fault_kctx_unblock(kctx); #endif @@ -1796,11 +1597,10 @@ int kbase_jd_init(struct kbase_context *kctx) kctx->jctx.atoms[i].event_code = BASE_JD_EVENT_JOB_INVALID; kctx->jctx.atoms[i].status = KBASE_JD_ATOM_STATE_UNUSED; -#if defined(CONFIG_MALI_BIFROST_DMA_FENCE) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) kctx->jctx.atoms[i].dma_fence.context = dma_fence_context_alloc(1); atomic_set(&kctx->jctx.atoms[i].dma_fence.seqno, 0); - INIT_LIST_HEAD(&kctx->jctx.atoms[i].dma_fence.callbacks); #endif } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c index 87c92330dfe2..6196c0985c7e 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_jd_debugfs.c @@ -24,8 +24,7 @@ #include #include #include -#include -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) #include #endif #include @@ -38,7 +37,7 @@ struct kbase_jd_debugfs_depinfo { static void kbase_jd_debugfs_fence_info(struct kbase_jd_atom *atom, struct seq_file *sfile) { -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) struct kbase_sync_fence_info info; int res; @@ -58,51 +57,7 @@ static void kbase_jd_debugfs_fence_info(struct kbase_jd_atom *atom, default: break; } -#endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ - -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - if (atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { - struct kbase_fence_cb *cb; - - if (atom->dma_fence.fence) { -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) - struct fence *fence = atom->dma_fence.fence; -#else - struct dma_fence *fence = atom->dma_fence.fence; -#endif - - seq_printf(sfile, -#if (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE) - "Sd(%llu#%u: %s) ", -#else - "Sd(%llu#%llu: %s) ", -#endif - fence->context, fence->seqno, - dma_fence_is_signaled(fence) ? "signaled" : - "active"); - } - - list_for_each_entry(cb, &atom->dma_fence.callbacks, - node) { -#if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) - struct fence *fence = cb->fence; -#else - struct dma_fence *fence = cb->fence; -#endif - - seq_printf(sfile, -#if (KERNEL_VERSION(5, 1, 0) > LINUX_VERSION_CODE) - "Wd(%llu#%u: %s) ", -#else - "Wd(%llu#%llu: %s) ", -#endif - fence->context, fence->seqno, - dma_fence_is_signaled(fence) ? "signaled" : - "active"); - } - } -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ - +#endif /* CONFIG_SYNC_FILE */ } static void kbasep_jd_debugfs_atom_deps( diff --git a/drivers/gpu/arm/bifrost/mali_kbase_js.c b/drivers/gpu/arm/bifrost/mali_kbase_js.c index 1991bfa9532d..a64d7327a76b 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_js.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_js.c @@ -621,6 +621,7 @@ void kbasep_js_devdata_term(struct kbase_device *kbdev) { struct kbasep_js_device_data *js_devdata; s8 zero_ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT] = { 0, }; + CSTD_UNUSED(js_devdata); KBASE_DEBUG_ASSERT(kbdev != NULL); @@ -638,15 +639,12 @@ void kbasep_js_devdata_term(struct kbase_device *kbdev) int kbasep_js_kctx_init(struct kbase_context *const kctx) { - struct kbase_device *kbdev; struct kbasep_js_kctx_info *js_kctx_info; int i, j; + CSTD_UNUSED(js_kctx_info); KBASE_DEBUG_ASSERT(kctx != NULL); - kbdev = kctx->kbdev; - KBASE_DEBUG_ASSERT(kbdev != NULL); - for (i = 0; i < BASE_JM_MAX_NR_SLOTS; ++i) INIT_LIST_HEAD(&kctx->jctx.sched_info.ctx.ctx_list_entry[i]); @@ -688,6 +686,7 @@ void kbasep_js_kctx_term(struct kbase_context *kctx) int js; bool update_ctx_count = false; unsigned long flags; + CSTD_UNUSED(js_kctx_info); KBASE_DEBUG_ASSERT(kctx != NULL); @@ -1800,6 +1799,7 @@ static kbasep_js_release_result kbasep_js_runpool_release_ctx_internal( bool runpool_ctx_attr_change = false; int kctx_as_nr; int new_ref_count; + CSTD_UNUSED(kctx_as_nr); KBASE_DEBUG_ASSERT(kbdev != NULL); KBASE_DEBUG_ASSERT(kctx != NULL); @@ -2183,6 +2183,7 @@ static bool kbasep_js_schedule_ctx(struct kbase_device *kbdev, #endif /* Cause it to leave at some later point */ bool retained; + CSTD_UNUSED(retained); retained = kbase_ctx_sched_inc_refcount_nolock(kctx); KBASE_DEBUG_ASSERT(retained); @@ -3918,6 +3919,7 @@ void kbase_js_zap_context(struct kbase_context *kctx) } else { unsigned long flags; bool was_retained; + CSTD_UNUSED(was_retained); /* Case c: didn't evict, but it is scheduled - it's in the Run * Pool diff --git a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.c b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.c index 78fa6f37ef6c..7b8961679a10 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_jm.c @@ -61,10 +61,6 @@ #define __static_assert(e, msg, ...) _Static_assert(e, msg) #endif -#ifndef ENOTSUP -#define ENOTSUP EOPNOTSUPP -#endif - /* The module printing prefix */ #define PR_ "mali_kbase_kinstr_jm: " @@ -224,11 +220,8 @@ static inline bool reader_changes_is_valid_size(const size_t size) * * Return: * (0, U16_MAX] - the number of data elements allocated - * -EINVAL - a pointer was invalid - * -ENOTSUP - we do not support allocation of the context * -ERANGE - the requested memory size was invalid * -ENOMEM - could not allocate the memory - * -EADDRINUSE - the buffer memory was already allocated */ static int reader_changes_init(struct reader_changes *const changes, const size_t size) @@ -623,31 +616,34 @@ exit: * * Return: * * 0 - no data ready - * * POLLIN - state changes have been buffered - * * -EBADF - the file descriptor did not have an attached reader - * * -EINVAL - the IO control arguments were invalid + * * EPOLLIN | EPOLLRDNORM - state changes have been buffered + * * EPOLLHUP | EPOLLERR - IO control arguments were invalid or the file + * descriptor did not have an attached reader. */ static __poll_t reader_poll(struct file *const file, struct poll_table_struct *const wait) { struct reader *reader; struct reader_changes *changes; + __poll_t mask = 0; if (unlikely(!file || !wait)) - return (__poll_t)-EINVAL; + return EPOLLHUP | EPOLLERR; reader = file->private_data; if (unlikely(!reader)) - return (__poll_t)-EBADF; + return EPOLLHUP | EPOLLERR; changes = &reader->changes; - if (reader_changes_count(changes) >= changes->threshold) - return POLLIN; + return EPOLLIN | EPOLLRDNORM; poll_wait(file, &reader->wait_queue, wait); - return (reader_changes_count(changes) > 0) ? POLLIN : 0; + if (reader_changes_count(changes) > 0) + mask |= EPOLLIN | EPOLLRDNORM; + + return mask; } /* The file operations virtual function table */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.c b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.c index 81758c32259c..5fb11b7b94c5 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.c @@ -21,8 +21,8 @@ #include "mali_kbase.h" #include "mali_kbase_kinstr_prfcnt.h" -#include "mali_kbase_hwcnt_virtualizer.h" -#include "mali_kbase_hwcnt_gpu.h" +#include "hwcnt/mali_kbase_hwcnt_virtualizer.h" +#include "hwcnt/mali_kbase_hwcnt_gpu.h" #include #include "mali_malisw.h" #include "mali_kbase_debug.h" @@ -47,9 +47,6 @@ /* The maximum allowed buffers per client */ #define MAX_BUFFER_COUNT 32 -/* The module printing prefix */ -#define KINSTR_PRFCNT_PREFIX "mali_kbase_kinstr_prfcnt: " - /** * struct kbase_kinstr_prfcnt_context - IOCTL interface for userspace hardware * counters. @@ -224,8 +221,8 @@ static struct prfcnt_enum_item kinstr_prfcnt_supported_requests[] = { * @filp: Non-NULL pointer to file structure. * @wait: Non-NULL pointer to poll table. * - * Return: POLLIN if data can be read without blocking, 0 if data can not be - * read without blocking, else error code. + * Return: EPOLLIN | EPOLLRDNORM if data can be read without blocking, 0 if + * data can not be read without blocking, else EPOLLHUP | EPOLLERR. */ static __poll_t kbasep_kinstr_prfcnt_hwcnt_reader_poll(struct file *filp, @@ -234,19 +231,19 @@ kbasep_kinstr_prfcnt_hwcnt_reader_poll(struct file *filp, struct kbase_kinstr_prfcnt_client *cli; if (!filp || !wait) - return (__poll_t)-EINVAL; + return EPOLLHUP | EPOLLERR; cli = filp->private_data; if (!cli) - return (__poll_t)-EINVAL; + return EPOLLHUP | EPOLLERR; poll_wait(filp, &cli->waitq, wait); if (atomic_read(&cli->write_idx) != atomic_read(&cli->fetch_idx)) - return POLLIN; + return EPOLLIN | EPOLLRDNORM; - return 0; + return (__poll_t)0; } /** diff --git a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.h b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.h index 0ffc10e5c496..bbe33796e62f 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_kinstr_prfcnt.h @@ -26,7 +26,7 @@ #ifndef _KBASE_KINSTR_PRFCNT_H_ #define _KBASE_KINSTR_PRFCNT_H_ -#include "mali_kbase_hwcnt_types.h" +#include "hwcnt/mali_kbase_hwcnt_types.h" #include struct kbase_kinstr_prfcnt_context; @@ -80,7 +80,6 @@ void kbase_kinstr_prfcnt_suspend(struct kbase_kinstr_prfcnt_context *kinstr_ctx) */ void kbase_kinstr_prfcnt_resume(struct kbase_kinstr_prfcnt_context *kinstr_ctx); -#if MALI_KERNEL_TEST_API /** * kbasep_kinstr_prfcnt_get_block_info_list() - Get list of all block types * with their information. @@ -158,7 +157,6 @@ int kbasep_kinstr_prfcnt_cmd(struct kbase_kinstr_prfcnt_client *cli, * @cli: kinstr_prfcnt client. Must not be attached to a kinstr_prfcnt context. */ void kbasep_kinstr_prfcnt_client_destroy(struct kbase_kinstr_prfcnt_client *cli); -#endif /* MALI_KERNEL_TEST_API */ /** * kbase_kinstr_prfcnt_enum_info - Enumerate performance counter information. diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem.c b/drivers/gpu/arm/bifrost/mali_kbase_mem.c index e0785793e26a..3743b4df999f 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem.c @@ -44,6 +44,8 @@ #include #include +#if MALI_JIT_PRESSURE_LIMIT_BASE + /* * Alignment of objects allocated by the GPU inside a just-in-time memory * region whose size is given by an end address @@ -66,6 +68,7 @@ */ #define KBASE_GPU_ALLOCATED_OBJECT_MAX_BYTES (512u) +#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ /* Forward declarations */ static void free_partial_locked(struct kbase_context *kctx, @@ -429,15 +432,15 @@ void kbase_remove_va_region(struct kbase_device *kbdev, next->nr_pages += reg->nr_pages; rb_erase(&(reg->rblink), reg_rbtree); merged_back = 1; - if (merged_front) { - /* We already merged with prev, free it */ - kfree(reg); - } } } - /* If we failed to merge then we need to add a new block */ - if (!(merged_front || merged_back)) { + if (merged_front && merged_back) { + /* We already merged with prev, free it */ + kfree(reg); + } else if (!(merged_front || merged_back)) { + /* If we failed to merge then we need to add a new block */ + /* * We didn't merge anything. Try to add a new free * placeholder, and in any case, remove the original one. @@ -1416,6 +1419,7 @@ int kbase_mem_init(struct kbase_device *kbdev) memdev = &kbdev->memdev; + kbase_mem_migrate_init(kbdev); kbase_mem_pool_group_config_set_max_size(&kbdev->mem_pool_defaults, KBASE_MEM_POOL_MAX_SIZE_KCTX); @@ -1478,8 +1482,7 @@ int kbase_mem_init(struct kbase_device *kbdev) kbase_mem_pool_group_config_set_max_size(&mem_pool_defaults, KBASE_MEM_POOL_MAX_SIZE_KBDEV); - err = kbase_mem_pool_group_init(&kbdev->mem_pools, kbdev, - &mem_pool_defaults, NULL); + err = kbase_mem_pool_group_init(&kbdev->mem_pools, kbdev, &mem_pool_defaults, NULL); } return err; @@ -1505,6 +1508,8 @@ void kbase_mem_term(struct kbase_device *kbdev) kbase_mem_pool_group_term(&kbdev->mem_pools); + kbase_mem_migrate_term(kbdev); + WARN_ON(kbdev->total_gpu_pages); WARN_ON(!RB_EMPTY_ROOT(&kbdev->process_root)); WARN_ON(!RB_EMPTY_ROOT(&kbdev->dma_buf_root)); @@ -1613,6 +1618,7 @@ static struct kbase_context *kbase_reg_flags_to_kctx( * alloc object will be released. * It is a bug if no alloc object exists for non-free regions. * + * If region is KBASE_REG_ZONE_MCU_SHARED it is freed */ void kbase_free_alloced_region(struct kbase_va_region *reg) { @@ -1636,6 +1642,13 @@ void kbase_free_alloced_region(struct kbase_va_region *reg) (void *)reg); #if MALI_USE_CSF if (reg->flags & KBASE_REG_CSF_EVENT) + /* + * This should not be reachable if called from 'mcu_shared' functions + * such as: + * kbase_csf_firmware_mcu_shared_mapping_init + * kbase_csf_firmware_mcu_shared_mapping_term + */ + kbase_unlink_event_mem_page(kctx, reg); #endif @@ -1649,8 +1662,6 @@ void kbase_free_alloced_region(struct kbase_va_region *reg) * on the list at termination time of the region tracker. */ if (!list_empty(®->gpu_alloc->evict_node)) { - mutex_unlock(&kctx->jit_evict_lock); - /* * Unlink the physical allocation before unmaking it * evictable so that the allocation isn't grown back to @@ -1661,6 +1672,8 @@ void kbase_free_alloced_region(struct kbase_va_region *reg) if (reg->cpu_alloc != reg->gpu_alloc) reg->gpu_alloc->reg = NULL; + mutex_unlock(&kctx->jit_evict_lock); + /* * If a region has been made evictable then we must * unmake it before trying to free it. @@ -1812,8 +1825,8 @@ bad_insert: KBASE_EXPORT_TEST_API(kbase_gpu_mmap); -static void kbase_jd_user_buf_unmap(struct kbase_context *kctx, - struct kbase_mem_phy_alloc *alloc, bool writeable); +static void kbase_jd_user_buf_unmap(struct kbase_context *kctx, struct kbase_mem_phy_alloc *alloc, + struct kbase_va_region *reg, bool writeable); int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg) { @@ -1879,7 +1892,7 @@ int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg) /* The allocation could still have active mappings. */ if (user_buf->current_mapping_usage_count == 0) { - kbase_jd_user_buf_unmap(kctx, alloc, + kbase_jd_user_buf_unmap(kctx, alloc, reg, (reg->flags & (KBASE_REG_CPU_WR | KBASE_REG_GPU_WR))); } @@ -2004,7 +2017,8 @@ void kbase_sync_single(struct kbase_context *kctx, BUG_ON(!cpu_page); BUG_ON(offset + size > PAGE_SIZE); - dma_addr = kbase_dma_addr(cpu_page) + offset; + dma_addr = kbase_dma_addr_from_tagged(t_cpu_pa) + offset; + if (sync_fn == KBASE_SYNC_TO_CPU) dma_sync_single_for_cpu(kctx->kbdev->dev, dma_addr, size, DMA_BIDIRECTIONAL); @@ -2015,19 +2029,20 @@ void kbase_sync_single(struct kbase_context *kctx, void *src = NULL; void *dst = NULL; struct page *gpu_page; + dma_addr_t dma_addr; if (WARN(!gpu_pa, "No GPU PA found for infinite cache op")) return; gpu_page = pfn_to_page(PFN_DOWN(gpu_pa)); + dma_addr = kbase_dma_addr_from_tagged(t_gpu_pa) + offset; if (sync_fn == KBASE_SYNC_TO_DEVICE) { src = ((unsigned char *)kmap(cpu_page)) + offset; dst = ((unsigned char *)kmap(gpu_page)) + offset; } else if (sync_fn == KBASE_SYNC_TO_CPU) { - dma_sync_single_for_cpu(kctx->kbdev->dev, - kbase_dma_addr(gpu_page) + offset, - size, DMA_BIDIRECTIONAL); + dma_sync_single_for_cpu(kctx->kbdev->dev, dma_addr, size, + DMA_BIDIRECTIONAL); src = ((unsigned char *)kmap(gpu_page)) + offset; dst = ((unsigned char *)kmap(cpu_page)) + offset; } @@ -2035,9 +2050,8 @@ void kbase_sync_single(struct kbase_context *kctx, kunmap(gpu_page); kunmap(cpu_page); if (sync_fn == KBASE_SYNC_TO_DEVICE) - dma_sync_single_for_device(kctx->kbdev->dev, - kbase_dma_addr(gpu_page) + offset, - size, DMA_BIDIRECTIONAL); + dma_sync_single_for_device(kctx->kbdev->dev, dma_addr, size, + DMA_BIDIRECTIONAL); } } @@ -2188,24 +2202,22 @@ int kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *re return -EINVAL; } - /* - * Unlink the physical allocation before unmaking it evictable so - * that the allocation isn't grown back to its last backed size - * as we're going to unmap it anyway. - */ - reg->cpu_alloc->reg = NULL; - if (reg->cpu_alloc != reg->gpu_alloc) - reg->gpu_alloc->reg = NULL; - - /* - * If a region has been made evictable then we must unmake it + /* If a region has been made evictable then we must unmake it * before trying to free it. * If the memory hasn't been reclaimed it will be unmapped and freed * below, if it has been reclaimed then the operations below are no-ops. */ if (reg->flags & KBASE_REG_DONT_NEED) { - KBASE_DEBUG_ASSERT(reg->cpu_alloc->type == - KBASE_MEM_TYPE_NATIVE); + WARN_ON(reg->cpu_alloc->type != KBASE_MEM_TYPE_NATIVE); + mutex_lock(&kctx->jit_evict_lock); + /* Unlink the physical allocation before unmaking it evictable so + * that the allocation isn't grown back to its last backed size + * as we're going to unmap it anyway. + */ + reg->cpu_alloc->reg = NULL; + if (reg->cpu_alloc != reg->gpu_alloc) + reg->gpu_alloc->reg = NULL; + mutex_unlock(&kctx->jit_evict_lock); kbase_mem_evictable_unmake(reg->gpu_alloc); } @@ -2464,11 +2476,8 @@ int kbase_alloc_phy_pages_helper(struct kbase_mem_phy_alloc *alloc, if (nr_left >= (SZ_2M / SZ_4K)) { int nr_lp = nr_left / (SZ_2M / SZ_4K); - res = kbase_mem_pool_alloc_pages( - &kctx->mem_pools.large[alloc->group_id], - nr_lp * (SZ_2M / SZ_4K), - tp, - true); + res = kbase_mem_pool_alloc_pages(&kctx->mem_pools.large[alloc->group_id], + nr_lp * (SZ_2M / SZ_4K), tp, true); if (res > 0) { nr_left -= res; @@ -2567,9 +2576,8 @@ no_new_partial: #endif if (nr_left) { - res = kbase_mem_pool_alloc_pages( - &kctx->mem_pools.small[alloc->group_id], - nr_left, tp, false); + res = kbase_mem_pool_alloc_pages(&kctx->mem_pools.small[alloc->group_id], nr_left, + tp, false); if (res <= 0) goto alloc_failed; } @@ -3061,6 +3069,13 @@ KBASE_EXPORT_TEST_API(kbase_free_phy_pages_helper_locked); /** * kbase_jd_user_buf_unpin_pages - Release the pinned pages of a user buffer. * @alloc: The allocation for the imported user buffer. + * + * This must only be called when terminating an alloc, when its refcount + * (number of users) has become 0. This also ensures it is only called once all + * CPU mappings have been closed. + * + * Instead call kbase_jd_user_buf_unmap() if you need to unpin pages on active + * allocations */ static void kbase_jd_user_buf_unpin_pages(struct kbase_mem_phy_alloc *alloc); #endif @@ -3434,10 +3449,6 @@ int kbase_check_alloc_sizes(struct kbase_context *kctx, unsigned long flags, #undef KBASE_MSG_PRE } -/** - * kbase_gpu_vm_lock() - Acquire the per-context region list lock - * @kctx: KBase context - */ void kbase_gpu_vm_lock(struct kbase_context *kctx) { KBASE_DEBUG_ASSERT(kctx != NULL); @@ -3446,10 +3457,6 @@ void kbase_gpu_vm_lock(struct kbase_context *kctx) KBASE_EXPORT_TEST_API(kbase_gpu_vm_lock); -/** - * kbase_gpu_vm_unlock() - Release the per-context region list lock - * @kctx: KBase context - */ void kbase_gpu_vm_unlock(struct kbase_context *kctx) { KBASE_DEBUG_ASSERT(kctx != NULL); @@ -3774,6 +3781,7 @@ int kbase_jit_init(struct kbase_context *kctx) INIT_WORK(&kctx->jit_work, kbase_jit_destroy_worker); #if MALI_USE_CSF + mutex_init(&kctx->csf.kcpu_queues.jit_lock); INIT_LIST_HEAD(&kctx->csf.kcpu_queues.jit_cmds_head); INIT_LIST_HEAD(&kctx->csf.kcpu_queues.jit_blocked_queues); #else /* !MALI_USE_CSF */ @@ -4211,11 +4219,11 @@ static bool jit_allow_allocate(struct kbase_context *kctx, const struct base_jit_alloc_info *info, bool ignore_pressure_limit) { -#if MALI_USE_CSF - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); -#else +#if !MALI_USE_CSF lockdep_assert_held(&kctx->jctx.lock); -#endif +#else /* MALI_USE_CSF */ + lockdep_assert_held(&kctx->csf.kcpu_queues.jit_lock); +#endif /* !MALI_USE_CSF */ #if MALI_JIT_PRESSURE_LIMIT_BASE if (!ignore_pressure_limit && @@ -4306,11 +4314,11 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx, */ const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_SYNC; -#if MALI_USE_CSF - lockdep_assert_held(&kctx->csf.kcpu_queues.lock); -#else +#if !MALI_USE_CSF lockdep_assert_held(&kctx->jctx.lock); -#endif +#else /* MALI_USE_CSF */ + lockdep_assert_held(&kctx->csf.kcpu_queues.jit_lock); +#endif /* !MALI_USE_CSF */ if (!jit_allow_allocate(kctx, info, ignore_pressure_limit)) return NULL; @@ -4518,6 +4526,12 @@ void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg) { u64 old_pages; +#if !MALI_USE_CSF + lockdep_assert_held(&kctx->jctx.lock); +#else /* MALI_USE_CSF */ + lockdep_assert_held(&kctx->csf.kcpu_queues.jit_lock); +#endif /* !MALI_USE_CSF */ + /* JIT id not immediately available here, so use 0u */ trace_mali_jit_free(reg, 0u); @@ -4764,7 +4778,23 @@ void kbase_unpin_user_buf_page(struct page *page) #if MALI_USE_CSF static void kbase_jd_user_buf_unpin_pages(struct kbase_mem_phy_alloc *alloc) { - if (alloc->nents) { + /* In CSF builds, we keep pages pinned until the last reference is + * released on the alloc. A refcount of 0 also means we can be sure + * that all CPU mappings have been closed on this alloc, and no more + * mappings of it will be created. + * + * Further, the WARN() below captures the restriction that this + * function will not handle anything other than the alloc termination + * path, because the caller of kbase_mem_phy_alloc_put() is not + * required to hold the kctx's reg_lock, and so we could not handle + * removing an existing CPU mapping here. + * + * Refer to this function's kernel-doc comments for alternatives for + * unpinning a User buffer. + */ + + if (alloc->nents && !WARN(kref_read(&alloc->kref) != 0, + "must only be called on terminating an allocation")) { struct page **pages = alloc->imported.user_buf.pages; long i; @@ -4772,6 +4802,8 @@ static void kbase_jd_user_buf_unpin_pages(struct kbase_mem_phy_alloc *alloc) for (i = 0; i < alloc->nents; i++) kbase_unpin_user_buf_page(pages[i]); + + alloc->nents = 0; } } #endif @@ -4787,6 +4819,8 @@ int kbase_jd_user_buf_pin_pages(struct kbase_context *kctx, long i; int write; + lockdep_assert_held(&kctx->reg_lock); + if (WARN_ON(alloc->type != KBASE_MEM_TYPE_IMPORTED_USER_BUF)) return -EINVAL; @@ -4817,6 +4851,9 @@ int kbase_jd_user_buf_pin_pages(struct kbase_context *kctx, return pinned_pages; if (pinned_pages != alloc->imported.user_buf.nr_pages) { + /* Above code already ensures there will not have been a CPU + * mapping by ensuring alloc->nents is 0 + */ for (i = 0; i < pinned_pages; i++) kbase_unpin_user_buf_page(pages[i]); return -ENOMEM; @@ -4830,23 +4867,26 @@ int kbase_jd_user_buf_pin_pages(struct kbase_context *kctx, static int kbase_jd_user_buf_map(struct kbase_context *kctx, struct kbase_va_region *reg) { - long pinned_pages; + int err; + long pinned_pages = 0; struct kbase_mem_phy_alloc *alloc; struct page **pages; struct tagged_addr *pa; - long i; + long i, dma_mapped_pages; unsigned long address; struct device *dev; - unsigned long offset; - unsigned long local_size; + unsigned long offset_within_page; + unsigned long remaining_size; unsigned long gwt_mask = ~0; - int err = kbase_jd_user_buf_pin_pages(kctx, reg); - /* 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; + lockdep_assert_held(&kctx->reg_lock); + + err = kbase_jd_user_buf_pin_pages(kctx, reg); + if (err) return err; @@ -4856,17 +4896,16 @@ static int kbase_jd_user_buf_map(struct kbase_context *kctx, pinned_pages = alloc->nents; pages = alloc->imported.user_buf.pages; dev = kctx->kbdev->dev; - offset = address & ~PAGE_MASK; - local_size = alloc->imported.user_buf.size; + offset_within_page = address & ~PAGE_MASK; + remaining_size = alloc->imported.user_buf.size; for (i = 0; i < pinned_pages; i++) { - dma_addr_t dma_addr; - unsigned long min; - - min = MIN(PAGE_SIZE - offset, local_size); - dma_addr = dma_map_page(dev, pages[i], - offset, min, + unsigned long map_size = + MIN(PAGE_SIZE - offset_within_page, remaining_size); + dma_addr_t dma_addr = dma_map_page(dev, pages[i], + offset_within_page, map_size, DMA_BIDIRECTIONAL); + err = dma_mapping_error(dev, dma_addr); if (err) goto unwind; @@ -4874,8 +4913,8 @@ static int kbase_jd_user_buf_map(struct kbase_context *kctx, alloc->imported.user_buf.dma_addrs[i] = dma_addr; pa[i] = as_tagged(page_to_phys(pages[i])); - local_size -= min; - offset = 0; + remaining_size -= map_size; + offset_within_page = 0; } #ifdef CONFIG_MALI_CINSTR_GWT @@ -4893,13 +4932,28 @@ static int kbase_jd_user_buf_map(struct kbase_context *kctx, /* fall down */ unwind: alloc->nents = 0; - while (i--) { + offset_within_page = address & ~PAGE_MASK; + remaining_size = alloc->imported.user_buf.size; + dma_mapped_pages = i; + /* Run the unmap loop in the same order as map loop */ + for (i = 0; i < dma_mapped_pages; i++) { + unsigned long unmap_size = + MIN(PAGE_SIZE - offset_within_page, remaining_size); + dma_unmap_page(kctx->kbdev->dev, alloc->imported.user_buf.dma_addrs[i], - PAGE_SIZE, DMA_BIDIRECTIONAL); + unmap_size, DMA_BIDIRECTIONAL); + remaining_size -= unmap_size; + offset_within_page = 0; } - while (++i < pinned_pages) { + /* The user buffer could already have been previously pinned before + * entering this function, and hence there could potentially be CPU + * mappings of it + */ + kbase_mem_shrink_cpu_mapping(kctx, reg, 0, pinned_pages); + + for (i = 0; i < pinned_pages; i++) { kbase_unpin_user_buf_page(pages[i]); pages[i] = NULL; } @@ -4911,21 +4965,31 @@ unwind: * GPUs, which implies that a call to kbase_jd_user_buf_pin_pages() will NOT * have a corresponding call to kbase_jd_user_buf_unpin_pages(). */ -static void kbase_jd_user_buf_unmap(struct kbase_context *kctx, - struct kbase_mem_phy_alloc *alloc, bool writeable) +static void kbase_jd_user_buf_unmap(struct kbase_context *kctx, struct kbase_mem_phy_alloc *alloc, + struct kbase_va_region *reg, bool writeable) { long i; struct page **pages; - unsigned long size = alloc->imported.user_buf.size; + unsigned long offset_within_page = alloc->imported.user_buf.address & ~PAGE_MASK; + unsigned long remaining_size = alloc->imported.user_buf.size; + + lockdep_assert_held(&kctx->reg_lock); KBASE_DEBUG_ASSERT(alloc->type == KBASE_MEM_TYPE_IMPORTED_USER_BUF); pages = alloc->imported.user_buf.pages; + +#if !MALI_USE_CSF + kbase_mem_shrink_cpu_mapping(kctx, reg, 0, alloc->nents); +#else + CSTD_UNUSED(reg); +#endif + for (i = 0; i < alloc->imported.user_buf.nr_pages; i++) { - unsigned long local_size; + unsigned long unmap_size = + MIN(remaining_size, PAGE_SIZE - offset_within_page); dma_addr_t dma_addr = alloc->imported.user_buf.dma_addrs[i]; - local_size = MIN(size, PAGE_SIZE - (dma_addr & ~PAGE_MASK)); - dma_unmap_page(kctx->kbdev->dev, dma_addr, local_size, + dma_unmap_page(kctx->kbdev->dev, dma_addr, unmap_size, DMA_BIDIRECTIONAL); if (writeable) set_page_dirty_lock(pages[i]); @@ -4934,7 +4998,8 @@ static void kbase_jd_user_buf_unmap(struct kbase_context *kctx, pages[i] = NULL; #endif - size -= local_size; + remaining_size -= unmap_size; + offset_within_page = 0; } #if !MALI_USE_CSF alloc->nents = 0; @@ -4981,11 +5046,11 @@ int kbase_mem_copy_to_pinned_user_pages(struct page **dest_pages, return 0; } -struct kbase_mem_phy_alloc *kbase_map_external_resource( - struct kbase_context *kctx, struct kbase_va_region *reg, - struct mm_struct *locked_mm) +int kbase_map_external_resource(struct kbase_context *kctx, struct kbase_va_region *reg, + struct mm_struct *locked_mm) { - int err; + int err = 0; + struct kbase_mem_phy_alloc *alloc = reg->gpu_alloc; lockdep_assert_held(&kctx->reg_lock); @@ -4994,7 +5059,7 @@ struct kbase_mem_phy_alloc *kbase_map_external_resource( case KBASE_MEM_TYPE_IMPORTED_USER_BUF: { if ((reg->gpu_alloc->imported.user_buf.mm != locked_mm) && (!reg->gpu_alloc->nents)) - goto exit; + return -EINVAL; reg->gpu_alloc->imported.user_buf.current_mapping_usage_count++; if (reg->gpu_alloc->imported.user_buf @@ -5002,7 +5067,7 @@ struct kbase_mem_phy_alloc *kbase_map_external_resource( err = kbase_jd_user_buf_map(kctx, reg); if (err) { reg->gpu_alloc->imported.user_buf.current_mapping_usage_count--; - goto exit; + return err; } } } @@ -5010,21 +5075,29 @@ struct kbase_mem_phy_alloc *kbase_map_external_resource( case KBASE_MEM_TYPE_IMPORTED_UMM: { err = kbase_mem_umm_map(kctx, reg); if (err) - goto exit; + return err; break; } default: - goto exit; + WARN(1, "Invalid external resource GPU allocation type (%x) on mapping", + alloc->type); + return -EINVAL; } - return kbase_mem_phy_alloc_get(reg->gpu_alloc); -exit: - return NULL; + kbase_va_region_alloc_get(kctx, reg); + kbase_mem_phy_alloc_get(alloc); + return err; } -void kbase_unmap_external_resource(struct kbase_context *kctx, - struct kbase_va_region *reg, struct kbase_mem_phy_alloc *alloc) +void kbase_unmap_external_resource(struct kbase_context *kctx, struct kbase_va_region *reg) { + /* gpu_alloc was used in kbase_map_external_resources, so we need to use it for the + * unmapping operation. + */ + struct kbase_mem_phy_alloc *alloc = reg->gpu_alloc; + + lockdep_assert_held(&kctx->reg_lock); + switch (alloc->type) { case KBASE_MEM_TYPE_IMPORTED_UMM: { kbase_mem_umm_unmap(kctx, reg, alloc); @@ -5036,24 +5109,32 @@ void kbase_unmap_external_resource(struct kbase_context *kctx, if (alloc->imported.user_buf.current_mapping_usage_count == 0) { bool writeable = true; - if (!kbase_is_region_invalid_or_free(reg) && - reg->gpu_alloc == alloc) + if (!kbase_is_region_invalid_or_free(reg)) { 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)) + if ((reg->flags & (KBASE_REG_CPU_WR | KBASE_REG_GPU_WR)) == 0) writeable = false; - kbase_jd_user_buf_unmap(kctx, alloc, writeable); + kbase_jd_user_buf_unmap(kctx, alloc, reg, writeable); + } } - } break; default: - break; + WARN(1, "Invalid external resource GPU allocation type (%x) on unmapping", + alloc->type); + return; } kbase_mem_phy_alloc_put(alloc); + kbase_va_region_alloc_put(kctx, reg); +} + +static inline u64 kbasep_get_va_gpu_addr(struct kbase_va_region *reg) +{ + return reg->start_pfn << PAGE_SHIFT; } struct kbase_ctx_ext_res_meta *kbase_sticky_resource_acquire( @@ -5069,7 +5150,7 @@ struct kbase_ctx_ext_res_meta *kbase_sticky_resource_acquire( * metadata which matches the region which is being acquired. */ list_for_each_entry(walker, &kctx->ext_res_meta_head, ext_res_node) { - if (walker->gpu_addr == gpu_addr) { + if (kbasep_get_va_gpu_addr(walker->reg) == gpu_addr) { meta = walker; meta->ref++; break; @@ -5081,8 +5162,7 @@ struct kbase_ctx_ext_res_meta *kbase_sticky_resource_acquire( struct kbase_va_region *reg; /* Find the region */ - reg = kbase_region_tracker_find_region_enclosing_address( - kctx, gpu_addr); + reg = kbase_region_tracker_find_region_enclosing_address(kctx, gpu_addr); if (kbase_is_region_invalid_or_free(reg)) goto failed; @@ -5090,18 +5170,18 @@ struct kbase_ctx_ext_res_meta *kbase_sticky_resource_acquire( meta = kzalloc(sizeof(*meta), GFP_KERNEL); if (!meta) goto failed; - /* * Fill in the metadata object and acquire a reference * for the physical resource. */ - meta->alloc = kbase_map_external_resource(kctx, reg, NULL); - meta->ref = 1; + meta->reg = reg; - if (!meta->alloc) + /* Map the external resource to the GPU allocation of the region + * and acquire the reference to the VA region + */ + if (kbase_map_external_resource(kctx, meta->reg, NULL)) goto fail_map; - - meta->gpu_addr = reg->start_pfn << PAGE_SHIFT; + meta->ref = 1; list_add(&meta->ext_res_node, &kctx->ext_res_meta_head); } @@ -5126,7 +5206,7 @@ find_sticky_resource_meta(struct kbase_context *kctx, u64 gpu_addr) * metadata which matches the region which is being released. */ list_for_each_entry(walker, &kctx->ext_res_meta_head, ext_res_node) - if (walker->gpu_addr == gpu_addr) + if (kbasep_get_va_gpu_addr(walker->reg) == gpu_addr) return walker; return NULL; @@ -5135,14 +5215,7 @@ find_sticky_resource_meta(struct kbase_context *kctx, u64 gpu_addr) static void release_sticky_resource_meta(struct kbase_context *kctx, struct kbase_ctx_ext_res_meta *meta) { - struct kbase_va_region *reg; - - /* Drop the physical memory reference and free the metadata. */ - reg = kbase_region_tracker_find_region_enclosing_address( - kctx, - meta->gpu_addr); - - kbase_unmap_external_resource(kctx, reg, meta->alloc); + kbase_unmap_external_resource(kctx, meta->reg); list_del(&meta->ext_res_node); kfree(meta); } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem.h b/drivers/gpu/arm/bifrost/mali_kbase_mem.h index f590a449504a..5820f6d8a556 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem.h @@ -37,6 +37,7 @@ #include "mali_kbase_defs.h" /* Required for kbase_mem_evictable_unmake */ #include "mali_kbase_mem_linux.h" +#include "mali_kbase_mem_migrate.h" static inline void kbase_process_page_usage_inc(struct kbase_context *kctx, int pages); @@ -182,6 +183,89 @@ struct kbase_mem_phy_alloc { } imported; }; +/** + * enum kbase_page_status - Status of a page used for page migration. + * + * @MEM_POOL: Stable state. Page is located in a memory pool and can safely + * be migrated. + * @ALLOCATE_IN_PROGRESS: Transitory state. A page is set to this status as + * soon as it leaves a memory pool. + * @SPILL_IN_PROGRESS: Transitory state. Corner case where pages in a memory + * pool of a dying context are being moved to the device + * memory pool. + * @ALLOCATED_MAPPED: Stable state. Page has been allocated, mapped to GPU + * and has reference to kbase_mem_phy_alloc object. + * @MULTI_MAPPED: Stable state. This state is used to manage all use cases + * where a page may have "unusual" mappings. + * @PT_MAPPED: Stable state. Similar to ALLOCATED_MAPPED, but page doesn't + * reference kbase_mem_phy_alloc object. Used as a page in MMU + * page table. + * @FREE_IN_PROGRESS: Transitory state. A page is set to this status as soon as + * the driver manages to acquire a lock on the page while + * unmapping it. This status means that a memory release is + * happening and it's still not complete. + * @FREE_ISOLATED_IN_PROGRESS: Transitory state. This is a very particular corner case. + * A page is isolated while it is in ALLOCATED_MAPPED or + * PT_MAPPED state, but then the driver tries to destroy the + * allocation. + * + * Pages can only be migrated in stable states. + */ +enum kbase_page_status { + MEM_POOL = 0, + ALLOCATE_IN_PROGRESS, + SPILL_IN_PROGRESS, + ALLOCATED_MAPPED, + MULTI_MAPPED, + PT_MAPPED, + FREE_IN_PROGRESS, + FREE_ISOLATED_IN_PROGRESS, +}; + +/** + * struct kbase_page_metadata - Metadata for each page in kbase + * + * @kbdev: Pointer to kbase device. + * @dma_addr: DMA address mapped to page. + * @migrate_lock: A spinlock to protect the private metadata. + * @status: Status to keep track if page can be migrated at any + * given moment. MSB will indicate if page is isolated. + * Protected by @migrate_lock. + * @data: Member in union valid based on @status. + * + * Each 4KB page will have a reference to this struct in the private field. + * This will be used to keep track of information required for Linux page + * migration functionality as well as address for DMA mapping. + */ +struct kbase_page_metadata { + dma_addr_t dma_addr; + spinlock_t migrate_lock; + u8 status; + + union { + struct { + struct kbase_mem_pool *pool; + /* Pool could be terminated after page is isolated and therefore + * won't be able to get reference to kbase device. + */ + struct kbase_device *kbdev; + } mem_pool; + struct { + struct kbase_mem_phy_alloc *phy_alloc; + struct kbase_va_region *reg; + struct kbase_mmu_table *mmut; + struct page *pgd; + u64 vpfn; + size_t page_array_index; + } mapped; + struct { + struct kbase_mmu_table *mmut; + struct page *pgd; + u16 entry_info; + } pt_mapped; + } data; +}; + /* The top bit of kbase_alloc_import_user_buf::current_mapping_usage_count is * used to signify that a buffer was pinned when it was imported. Since the * reference count is limited by the number of atoms that can be submitted at @@ -224,8 +308,9 @@ static inline void kbase_mem_phy_alloc_gpu_unmapped(struct kbase_mem_phy_alloc * } /** - * kbase_mem_phy_alloc_kernel_mapped - Increment kernel_mappings - * counter for a memory region to prevent commit and flag changes + * kbase_mem_phy_alloc_kernel_mapped - Increment kernel_mappings counter for a + * memory region to prevent commit and flag + * changes * * @alloc: Pointer to physical pages tracking object */ @@ -387,6 +472,13 @@ struct kbase_va_region { #define KBASE_REG_PROTECTED (1ul << 19) +/* Region belongs to a shrinker. + * + * This can either mean that it is part of the JIT/Ephemeral or tiler heap + * shrinker paths. Should be removed only after making sure that there are + * no references remaining to it in these paths, as it may cause the physical + * backing of the region to disappear during use. + */ #define KBASE_REG_DONT_NEED (1ul << 20) /* Imported buffer is padded? */ @@ -862,12 +954,9 @@ static inline size_t kbase_mem_pool_config_get_max_size( * * Return: 0 on success, negative -errno on error */ -int kbase_mem_pool_init(struct kbase_mem_pool *pool, - const struct kbase_mem_pool_config *config, - unsigned int order, - int group_id, - struct kbase_device *kbdev, - struct kbase_mem_pool *next_pool); +int kbase_mem_pool_init(struct kbase_mem_pool *pool, const struct kbase_mem_pool_config *config, + unsigned int order, int group_id, struct kbase_device *kbdev, + struct kbase_mem_pool *next_pool); /** * kbase_mem_pool_term - Destroy a memory pool @@ -963,7 +1052,7 @@ void kbase_mem_pool_free_locked(struct kbase_mem_pool *pool, struct page *p, * this lock, it should use kbase_mem_pool_alloc_pages_locked() instead. */ int kbase_mem_pool_alloc_pages(struct kbase_mem_pool *pool, size_t nr_4k_pages, - struct tagged_addr *pages, bool partial_allowed); + struct tagged_addr *pages, bool partial_allowed); /** * kbase_mem_pool_alloc_pages_locked - Allocate pages from memory pool @@ -1114,6 +1203,16 @@ void kbase_mem_pool_mark_dying(struct kbase_mem_pool *pool); */ struct page *kbase_mem_alloc_page(struct kbase_mem_pool *pool); +/** + * kbase_mem_pool_free_page - Free a page from a memory pool. + * @pool: Memory pool to free a page from + * @p: Page to free + * + * This will free any associated data stored for the page and release + * the page back to the kernel. + */ +void kbase_mem_pool_free_page(struct kbase_mem_pool *pool, struct page *p); + /** * kbase_region_tracker_init - Initialize the region tracker data structure * @kctx: kbase context @@ -1233,7 +1332,55 @@ int kbase_check_alloc_sizes(struct kbase_context *kctx, unsigned long flags, int kbase_update_region_flags(struct kbase_context *kctx, struct kbase_va_region *reg, unsigned long flags); +/** + * kbase_gpu_vm_lock() - Acquire the per-context region list lock + * @kctx: KBase context + * + * Care must be taken when making an allocation whilst holding this lock, because of interaction + * with the Kernel's OoM-killer and use of this lock in &vm_operations_struct close() handlers. + * + * If this lock is taken during a syscall, and/or the allocation is 'small' then it is safe to use. + * + * If the caller is not in a syscall, and the allocation is 'large', then it must not hold this + * lock. + * + * This is because the kernel OoM killer might target the process corresponding to that same kbase + * context, and attempt to call the context's close() handlers for its open VMAs. This is safe if + * the allocating caller is in a syscall, because the VMA close() handlers are delayed until all + * syscalls have finished (noting that no new syscalls can start as the remaining user threads will + * have been killed too), and so there is no possibility of contention between the thread + * allocating with this lock held, and the VMA close() handler. + * + * However, outside of a syscall (e.g. a kworker or other kthread), one of kbase's VMA close() + * handlers (kbase_cpu_vm_close()) also takes this lock, and so prevents the process from being + * killed until the caller of the function allocating memory has released this lock. On subsequent + * retries for allocating a page, the OoM killer would be re-invoked but skips over the process + * stuck in its close() handler. + * + * Also because the caller is not in a syscall, the page allocation code in the kernel is not aware + * that the allocation is being done on behalf of another process, and so does not realize that + * process has received a kill signal due to an OoM, and so will continually retry with the OoM + * killer until enough memory has been released, or until all other killable processes have been + * killed (at which point the kernel halts with a panic). + * + * However, if the allocation outside of a syscall is small enough to be satisfied by killing + * another process, then the allocation completes, the caller releases this lock, and + * kbase_cpu_vm_close() can unblock and allow the process to be killed. + * + * Hence, this is effectively a deadlock with kbase_cpu_vm_close(), except that if the memory + * allocation is small enough the deadlock can be resolved. For that reason, such a memory deadlock + * is NOT discovered with CONFIG_PROVE_LOCKING. + * + * If this may be called outside of a syscall, consider moving allocations outside of this lock, or + * use __GFP_NORETRY for such allocations (which will allow direct-reclaim attempts, but will + * prevent OoM kills to satisfy the allocation, and will just fail the allocation instead). + */ void kbase_gpu_vm_lock(struct kbase_context *kctx); + +/** + * kbase_gpu_vm_unlock() - Release the per-context region list lock + * @kctx: KBase context + */ void kbase_gpu_vm_unlock(struct kbase_context *kctx); int kbase_alloc_phy_pages(struct kbase_va_region *reg, size_t vsize, size_t size); @@ -1311,6 +1458,7 @@ void kbase_mmu_disable_as(struct kbase_device *kbdev, int as_nr); void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat); +#if defined(CONFIG_MALI_VECTOR_DUMP) /** * kbase_mmu_dump() - Dump the MMU tables to a buffer. * @@ -1330,6 +1478,7 @@ void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat); * (including if the @c nr_pages is too small) */ void *kbase_mmu_dump(struct kbase_context *kctx, int nr_pages); +#endif /** * kbase_sync_now - Perform cache maintenance on a memory region @@ -1449,15 +1598,21 @@ int kbasep_find_enclosing_gpu_mapping_start_and_offset( * @alloc: allocation object to add pages to * @nr_pages_requested: number of physical pages to allocate * - * Allocates \a nr_pages_requested and updates the alloc object. + * Allocates @nr_pages_requested and updates the alloc object. * - * Return: 0 if all pages have been successfully allocated. Error code otherwise + * Note: if kbase_gpu_vm_lock() is to be held around this function to ensure thread-safe updating + * of @alloc, then refer to the documentation of kbase_gpu_vm_lock() about the requirements of + * either calling during a syscall, or ensuring the allocation is small. These requirements prevent + * an effective deadlock between the kernel's OoM killer and kbase's VMA close() handlers, which + * could take kbase_gpu_vm_lock() too. * - * Note : The caller must not hold vm_lock, as this could cause a deadlock if - * the kernel OoM killer runs. If the caller must allocate pages while holding - * this lock, it should use kbase_mem_pool_alloc_pages_locked() instead. + * If the requirements of kbase_gpu_vm_lock() cannot be satisfied when calling this function, but + * @alloc must still be updated in a thread-safe way, then instead use + * kbase_alloc_phy_pages_helper_locked() and restructure callers into the sequence outlined there. * * This function cannot be used from interrupt context + * + * Return: 0 if all pages have been successfully allocated. Error code otherwise */ int kbase_alloc_phy_pages_helper(struct kbase_mem_phy_alloc *alloc, size_t nr_pages_requested); @@ -1467,17 +1622,19 @@ int kbase_alloc_phy_pages_helper(struct kbase_mem_phy_alloc *alloc, * @alloc: allocation object to add pages to * @pool: Memory pool to allocate from * @nr_pages_requested: number of physical pages to allocate - * @prealloc_sa: Information about the partial allocation if the amount - * of memory requested is not a multiple of 2MB. One - * instance of struct kbase_sub_alloc must be allocated by - * the caller iff CONFIG_MALI_2MB_ALLOC is enabled. * - * Allocates \a nr_pages_requested and updates the alloc object. This function - * does not allocate new pages from the kernel, and therefore will never trigger - * the OoM killer. Therefore, it can be run while the vm_lock is held. + * @prealloc_sa: Information about the partial allocation if the amount of memory requested + * is not a multiple of 2MB. One instance of struct kbase_sub_alloc must be + * allocated by the caller iff CONFIG_MALI_2MB_ALLOC is enabled. * - * As new pages can not be allocated, the caller must ensure there are - * sufficient pages in the pool. Usage of this function should look like : + * Allocates @nr_pages_requested and updates the alloc object. This function does not allocate new + * pages from the kernel, and therefore will never trigger the OoM killer. Therefore, it can be + * called whilst a thread operating outside of a syscall has held the region list lock + * (kbase_gpu_vm_lock()), as it will not cause an effective deadlock with VMA close() handlers used + * by the OoM killer. + * + * As new pages can not be allocated, the caller must ensure there are sufficient pages in the + * pool. Usage of this function should look like : * * kbase_gpu_vm_lock(kctx); * kbase_mem_pool_lock(pool) @@ -1490,24 +1647,24 @@ int kbase_alloc_phy_pages_helper(struct kbase_mem_phy_alloc *alloc, * } * kbase_alloc_phy_pages_helper_locked(pool) * kbase_mem_pool_unlock(pool) - * Perform other processing that requires vm_lock... + * // Perform other processing that requires vm_lock... * kbase_gpu_vm_unlock(kctx); * - * This ensures that the pool can be grown to the required size and that the - * allocation can complete without another thread using the newly grown pages. + * This ensures that the pool can be grown to the required size and that the allocation can + * complete without another thread using the newly grown pages. * - * If CONFIG_MALI_2MB_ALLOC is defined and the allocation is >= 2MB, then - * @pool must be alloc->imported.native.kctx->lp_mem_pool. Otherwise it must be - * alloc->imported.native.kctx->mem_pool. - * @prealloc_sa is used to manage the non-2MB sub-allocation. It has to be - * pre-allocated because we must not sleep (due to the usage of kmalloc()) - * whilst holding pool->pool_lock. - * @prealloc_sa shall be set to NULL if it has been consumed by this function - * to indicate that the caller must not free it. + * If CONFIG_MALI_2MB_ALLOC is defined and the allocation is >= 2MB, then @pool must be one of the + * pools from alloc->imported.native.kctx->mem_pools.large[]. Otherwise it must be one of the + * mempools from alloc->imported.native.kctx->mem_pools.small[]. + * + * @prealloc_sa is used to manage the non-2MB sub-allocation. It has to be pre-allocated because we + * must not sleep (due to the usage of kmalloc()) whilst holding pool->pool_lock. @prealloc_sa + * shall be set to NULL if it has been consumed by this function to indicate that the caller no + * longer owns it and should not access it further. + * + * Note: Caller must hold @pool->pool_lock * * Return: Pointer to array of allocated pages. NULL on failure. - * - * Note : Caller must hold pool->pool_lock */ struct tagged_addr *kbase_alloc_phy_pages_helper_locked( struct kbase_mem_phy_alloc *alloc, struct kbase_mem_pool *pool, @@ -1546,7 +1703,7 @@ void kbase_free_phy_pages_helper_locked(struct kbase_mem_phy_alloc *alloc, struct kbase_mem_pool *pool, struct tagged_addr *pages, size_t nr_pages_to_free); -static inline void kbase_set_dma_addr(struct page *p, dma_addr_t dma_addr) +static inline void kbase_set_dma_addr_as_priv(struct page *p, dma_addr_t dma_addr) { SetPagePrivate(p); if (sizeof(dma_addr_t) > sizeof(p->private)) { @@ -1562,7 +1719,7 @@ static inline void kbase_set_dma_addr(struct page *p, dma_addr_t dma_addr) } } -static inline dma_addr_t kbase_dma_addr(struct page *p) +static inline dma_addr_t kbase_dma_addr_as_priv(struct page *p) { if (sizeof(dma_addr_t) > sizeof(p->private)) return ((dma_addr_t)page_private(p)) << PAGE_SHIFT; @@ -1570,11 +1727,34 @@ static inline dma_addr_t kbase_dma_addr(struct page *p) return (dma_addr_t)page_private(p); } -static inline void kbase_clear_dma_addr(struct page *p) +static inline void kbase_clear_dma_addr_as_priv(struct page *p) { ClearPagePrivate(p); } +static inline struct kbase_page_metadata *kbase_page_private(struct page *p) +{ + return (struct kbase_page_metadata *)page_private(p); +} + +static inline dma_addr_t kbase_dma_addr(struct page *p) +{ + if (kbase_page_migration_enabled) + return kbase_page_private(p)->dma_addr; + + return kbase_dma_addr_as_priv(p); +} + +static inline dma_addr_t kbase_dma_addr_from_tagged(struct tagged_addr tagged_pa) +{ + phys_addr_t pa = as_phys_addr_t(tagged_pa); + struct page *page = pfn_to_page(PFN_DOWN(pa)); + dma_addr_t dma_addr = + is_huge(tagged_pa) ? kbase_dma_addr_as_priv(page) : kbase_dma_addr(page); + + return dma_addr; +} + /** * kbase_flush_mmu_wqs() - Flush MMU workqueues. * @kbdev: Device pointer. @@ -1868,28 +2048,36 @@ bool kbase_has_exec_va_zone(struct kbase_context *kctx); /** * kbase_map_external_resource - Map an external resource to the GPU. * @kctx: kbase context. - * @reg: The region to map. + * @reg: External resource to map. * @locked_mm: The mm_struct which has been locked for this operation. * - * Return: The physical allocation which backs the region on success or NULL - * on failure. + * On successful mapping, the VA region and the gpu_alloc refcounts will be + * increased, making it safe to use and store both values directly. + * + * Return: Zero on success, or negative error code. */ -struct kbase_mem_phy_alloc *kbase_map_external_resource( - struct kbase_context *kctx, struct kbase_va_region *reg, - struct mm_struct *locked_mm); +int kbase_map_external_resource(struct kbase_context *kctx, struct kbase_va_region *reg, + struct mm_struct *locked_mm); /** * kbase_unmap_external_resource - Unmap an external resource from the GPU. * @kctx: kbase context. - * @reg: The region to unmap or NULL if it has already been released. - * @alloc: The physical allocation being unmapped. + * @reg: VA region corresponding to external resource + * + * On successful unmapping, the VA region and the gpu_alloc refcounts will + * be decreased. If the refcount reaches zero, both @reg and the corresponding + * allocation may be freed, so using them after returning from this function + * requires the caller to explicitly check their state. */ -void kbase_unmap_external_resource(struct kbase_context *kctx, - struct kbase_va_region *reg, struct kbase_mem_phy_alloc *alloc); +void kbase_unmap_external_resource(struct kbase_context *kctx, struct kbase_va_region *reg); /** * kbase_unpin_user_buf_page - Unpin a page of a user buffer. * @page: page to unpin + * + * The caller must have ensured that there are no CPU mappings for @page (as + * might be created from the struct kbase_mem_phy_alloc that tracks @page), and + * that userspace will not be able to recreate the CPU mappings again. */ void kbase_unpin_user_buf_page(struct page *page); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c index c373cf82ea37..9899cef317ac 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -83,24 +84,18 @@ #define IR_THRESHOLD_STEPS (256u) #if MALI_USE_CSF -static int kbase_csf_cpu_mmap_user_reg_page(struct kbase_context *kctx, - struct vm_area_struct *vma); -static int kbase_csf_cpu_mmap_user_io_pages(struct kbase_context *kctx, - struct vm_area_struct *vma); +static int kbase_csf_cpu_mmap_user_reg_page(struct kbase_context *kctx, struct vm_area_struct *vma); +static int kbase_csf_cpu_mmap_user_io_pages(struct kbase_context *kctx, struct vm_area_struct *vma); #endif -static int kbase_vmap_phy_pages(struct kbase_context *kctx, - struct kbase_va_region *reg, u64 offset_bytes, size_t size, - struct kbase_vmap_struct *map); +static int kbase_vmap_phy_pages(struct kbase_context *kctx, struct kbase_va_region *reg, + u64 offset_bytes, size_t size, struct kbase_vmap_struct *map, + kbase_vmap_flag vmap_flags); static void kbase_vunmap_phy_pages(struct kbase_context *kctx, struct kbase_vmap_struct *map); static int kbase_tracking_page_setup(struct kbase_context *kctx, struct vm_area_struct *vma); -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 @@ -198,20 +193,12 @@ static int kbase_phy_alloc_mapping_init(struct kbase_context *kctx, reg->cpu_alloc->type != KBASE_MEM_TYPE_NATIVE) return -EINVAL; - if (size > (KBASE_PERMANENTLY_MAPPED_MEM_LIMIT_PAGES - - atomic_read(&kctx->permanent_mapped_pages))) { - dev_warn(kctx->kbdev->dev, "Request for %llu more pages mem needing a permanent mapping would breach limit %lu, currently at %d pages", - (u64)size, - KBASE_PERMANENTLY_MAPPED_MEM_LIMIT_PAGES, - atomic_read(&kctx->permanent_mapped_pages)); - return -ENOMEM; - } - kern_mapping = kzalloc(sizeof(*kern_mapping), GFP_KERNEL); if (!kern_mapping) return -ENOMEM; - err = kbase_vmap_phy_pages(kctx, reg, 0u, size_bytes, kern_mapping); + err = kbase_vmap_phy_pages(kctx, reg, 0u, size_bytes, kern_mapping, + KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING); if (err < 0) goto vmap_fail; @@ -219,7 +206,6 @@ static int kbase_phy_alloc_mapping_init(struct kbase_context *kctx, reg->flags &= ~KBASE_REG_GROWABLE; reg->cpu_alloc->permanent_map = kern_mapping; - atomic_add(size, &kctx->permanent_mapped_pages); return 0; vmap_fail: @@ -235,13 +221,6 @@ void kbase_phy_alloc_mapping_term(struct kbase_context *kctx, kfree(alloc->permanent_map); alloc->permanent_map = NULL; - - /* Mappings are only done on cpu_alloc, so don't need to worry about - * this being reduced a second time if a separate gpu_alloc is - * freed - */ - WARN_ON(alloc->nents > atomic_read(&kctx->permanent_mapped_pages)); - atomic_sub(alloc->nents, &kctx->permanent_mapped_pages); } void *kbase_phy_alloc_mapping_get(struct kbase_context *kctx, @@ -499,7 +478,25 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages *gpu_va = (u64) cookie; } else /* we control the VA */ { - if (kbase_gpu_mmap(kctx, reg, *gpu_va, va_pages, 1, + size_t align = 1; + +#ifdef CONFIG_MALI_2MB_ALLOC + /* If there's enough (> 33 bits) of GPU VA space, align to 2MB + * boundaries. The similar condition is used for mapping from + * the SAME_VA zone inside kbase_context_get_unmapped_area(). + */ + if (kctx->kbdev->gpu_props.mmu.va_bits > 33) { + if (va_pages >= (SZ_2M / SZ_4K)) + align = (SZ_2M / SZ_4K); + } + if (*gpu_va) + align = 1; +#if !MALI_USE_CSF + if (reg->flags & KBASE_REG_TILER_ALIGN_TOP) + align = 1; +#endif /* !MALI_USE_CSF */ +#endif /* CONFIG_MALI_2MB_ALLOC */ + if (kbase_gpu_mmap(kctx, reg, *gpu_va, va_pages, align, mmu_sync_info) != 0) { dev_warn(dev, "Failed to map memory on GPU"); kbase_gpu_vm_unlock(kctx); @@ -675,24 +672,36 @@ out_unlock: * @s: Shrinker * @sc: Shrinker control * - * Return: Number of pages which can be freed. + * Return: Number of pages which can be freed or SHRINK_EMPTY if no page remains. */ static unsigned long kbase_mem_evictable_reclaim_count_objects(struct shrinker *s, struct shrink_control *sc) { - struct kbase_context *kctx; - - kctx = container_of(s, struct kbase_context, reclaim); + struct kbase_context *kctx = container_of(s, struct kbase_context, reclaim); + int evict_nents = atomic_read(&kctx->evict_nents); + unsigned long nr_freeable_items; WARN((sc->gfp_mask & __GFP_ATOMIC), "Shrinkers cannot be called for GFP_ATOMIC allocations. Check kernel mm for problems. gfp_mask==%x\n", sc->gfp_mask); WARN(in_atomic(), - "Shrinker called whilst in atomic context. The caller must switch to using GFP_ATOMIC or similar. gfp_mask==%x\n", + "Shrinker called in atomic context. The caller must use GFP_ATOMIC or similar, then Shrinkers must not be called. gfp_mask==%x\n", sc->gfp_mask); - return atomic_read(&kctx->evict_nents); + if (unlikely(evict_nents < 0)) { + dev_err(kctx->kbdev->dev, "invalid evict_nents(%d)", evict_nents); + nr_freeable_items = 0; + } else { + nr_freeable_items = evict_nents; + } + +#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE + if (nr_freeable_items == 0) + nr_freeable_items = SHRINK_EMPTY; +#endif + + return nr_freeable_items; } /** @@ -701,8 +710,8 @@ unsigned long kbase_mem_evictable_reclaim_count_objects(struct shrinker *s, * @s: Shrinker * @sc: Shrinker control * - * Return: Number of pages freed (can be less then requested) or -1 if the - * shrinker failed to free pages in its pool. + * Return: Number of pages freed (can be less then requested) or + * SHRINK_STOP if reclaim isn't possible. * * Note: * This function accesses region structures without taking the region lock, @@ -730,17 +739,15 @@ unsigned long kbase_mem_evictable_reclaim_scan_objects(struct shrinker *s, list_for_each_entry_safe(alloc, tmp, &kctx->evict_list, evict_node) { int err; + if (!alloc->reg) + continue; + err = kbase_mem_shrink_gpu_mapping(kctx, alloc->reg, 0, alloc->nents); - if (err != 0) { - /* - * Failed to remove GPU mapping, tell the shrinker - * to stop trying to shrink our slab even though we - * have pages in it. - */ - freed = -1; - goto out_unlock; - } + + /* Failed to remove GPU mapping, proceed to next one. */ + if (err != 0) + continue; /* * Update alloc->evicted before freeing the backing so the @@ -764,7 +771,7 @@ unsigned long kbase_mem_evictable_reclaim_scan_objects(struct shrinker *s, if (freed > sc->nr_to_scan) break; } -out_unlock: + mutex_unlock(&kctx->jit_evict_lock); return freed; @@ -964,6 +971,15 @@ int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, unsigned in if (kbase_is_region_invalid_or_free(reg)) goto out_unlock; + /* There is no use case to support MEM_FLAGS_CHANGE ioctl for allocations + * that have NO_USER_FREE flag set, to mark them as evictable/reclaimable. + * This would usually include JIT allocations, Tiler heap related allocations + * & GPU queue ringbuffer and none of them needs to be explicitly marked + * as evictable by Userspace. + */ + if (reg->flags & KBASE_REG_NO_USER_FREE) + goto out_unlock; + /* Is the region being transitioning between not needed and needed? */ prev_needed = (KBASE_REG_DONT_NEED & reg->flags) == KBASE_REG_DONT_NEED; new_needed = (BASE_MEM_DONT_NEED & flags) == BASE_MEM_DONT_NEED; @@ -1536,13 +1552,15 @@ static struct kbase_va_region *kbase_mem_from_user_buffer( struct kbase_context *kctx, unsigned long address, unsigned long size, u64 *va_pages, u64 *flags) { - long i; + long i, dma_mapped_pages; struct kbase_va_region *reg; struct rb_root *rbtree; long faulted_pages; int zone = KBASE_REG_ZONE_CUSTOM_VA; bool shared_zone = false; u32 cache_line_alignment = kbase_get_cache_line_alignment(kctx->kbdev); + unsigned long offset_within_page; + unsigned long remaining_size; struct kbase_alloc_import_user_buf *user_buf; struct page **pages = NULL; int write; @@ -1688,29 +1706,27 @@ static struct kbase_va_region *kbase_mem_from_user_buffer( if (pages) { struct device *dev = kctx->kbdev->dev; - unsigned long local_size = user_buf->size; - unsigned long offset = user_buf->address & ~PAGE_MASK; struct tagged_addr *pa = kbase_get_gpu_phy_pages(reg); /* Top bit signifies that this was pinned on import */ user_buf->current_mapping_usage_count |= PINNED_ON_IMPORT; + offset_within_page = user_buf->address & ~PAGE_MASK; + remaining_size = user_buf->size; for (i = 0; i < faulted_pages; i++) { - dma_addr_t dma_addr; - unsigned long min; + unsigned long map_size = + MIN(PAGE_SIZE - offset_within_page, remaining_size); + dma_addr_t dma_addr = dma_map_page(dev, pages[i], + offset_within_page, map_size, DMA_BIDIRECTIONAL); - min = MIN(PAGE_SIZE - offset, local_size); - dma_addr = dma_map_page(dev, pages[i], - offset, min, - DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, dma_addr)) goto unwind_dma_map; user_buf->dma_addrs[i] = dma_addr; pa[i] = as_tagged(page_to_phys(pages[i])); - local_size -= min; - offset = 0; + remaining_size -= map_size; + offset_within_page = 0; } reg->gpu_alloc->nents = faulted_pages; @@ -1719,13 +1735,26 @@ static struct kbase_va_region *kbase_mem_from_user_buffer( return reg; unwind_dma_map: - while (i--) { + offset_within_page = user_buf->address & ~PAGE_MASK; + remaining_size = user_buf->size; + dma_mapped_pages = i; + /* Run the unmap loop in the same order as map loop */ + for (i = 0; i < dma_mapped_pages; i++) { + unsigned long unmap_size = + MIN(PAGE_SIZE - offset_within_page, remaining_size); + dma_unmap_page(kctx->kbdev->dev, user_buf->dma_addrs[i], - PAGE_SIZE, DMA_BIDIRECTIONAL); + unmap_size, DMA_BIDIRECTIONAL); + remaining_size -= unmap_size; + offset_within_page = 0; } fault_mismatch: if (pages) { + /* In this case, the region was not yet in the region tracker, + * and so there are no CPU mappings to remove before we unpin + * the page + */ for (i = 0; i < faulted_pages; i++) kbase_unpin_user_buf_page(pages[i]); } @@ -1750,6 +1779,7 @@ u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride, u64 gpu_va; size_t i; bool coherent; + uint64_t max_stride; /* Calls to this function are inherently asynchronous, with respect to * MMU operations. @@ -1782,7 +1812,9 @@ u64 kbase_mem_alias(struct kbase_context *kctx, u64 *flags, u64 stride, if (!nents) goto bad_nents; - if (stride > U64_MAX / nents) + max_stride = div64_u64(U64_MAX, nents); + + if (stride > max_stride) goto bad_size; if ((nents * stride) > (U64_MAX / PAGE_SIZE)) @@ -2156,22 +2188,9 @@ void kbase_mem_shrink_cpu_mapping(struct kbase_context *kctx, (old_pages - new_pages)<gpu_alloc; @@ -2242,10 +2261,13 @@ int kbase_mem_commit(struct kbase_context *kctx, u64 gpu_addr, u64 new_pages) if (atomic_read(®->cpu_alloc->kernel_mappings) > 0) goto out_unlock; - /* can't grow regions which are ephemeral */ + if (reg->flags & KBASE_REG_DONT_NEED) goto out_unlock; + if (reg->flags & KBASE_REG_NO_USER_FREE) + goto out_unlock; + #ifdef CONFIG_MALI_MEMORY_FULLY_BACKED /* Reject resizing commit size */ if (reg->flags & KBASE_REG_PF_GROW) @@ -2628,7 +2650,6 @@ static void kbase_free_unused_jit_allocations(struct kbase_context *kctx) while (kbase_jit_evict(kctx)) ; } -#endif static int kbase_mmu_dump_mmap(struct kbase_context *kctx, struct vm_area_struct *vma, @@ -2645,9 +2666,7 @@ static int kbase_mmu_dump_mmap(struct kbase_context *kctx, size = (vma->vm_end - vma->vm_start); nr_pages = size >> PAGE_SHIFT; -#ifdef CONFIG_MALI_VECTOR_DUMP kbase_free_unused_jit_allocations(kctx); -#endif kaddr = kbase_mmu_dump(kctx, nr_pages); @@ -2695,7 +2714,7 @@ out_va_region: out: return err; } - +#endif void kbase_os_mem_map_lock(struct kbase_context *kctx) { @@ -2836,6 +2855,7 @@ int kbase_context_mmap(struct kbase_context *const kctx, err = -EINVAL; goto out_unlock; case PFN_DOWN(BASE_MEM_MMU_DUMP_HANDLE): +#if defined(CONFIG_MALI_VECTOR_DUMP) /* MMU dump */ err = kbase_mmu_dump_mmap(kctx, vma, ®, &kaddr); if (err != 0) @@ -2843,6 +2863,11 @@ int kbase_context_mmap(struct kbase_context *const kctx, /* free the region on munmap */ free_on_close = 1; break; +#else + /* Illegal handle for direct map */ + err = -EINVAL; + goto out_unlock; +#endif /* defined(CONFIG_MALI_VECTOR_DUMP) */ #if MALI_USE_CSF case PFN_DOWN(BASEP_MEM_CSF_USER_REG_PAGE_HANDLE): kbase_gpu_vm_unlock(kctx); @@ -2930,7 +2955,7 @@ int kbase_context_mmap(struct kbase_context *const kctx, err = kbase_cpu_mmap(kctx, reg, vma, kaddr, nr_pages, aligned_offset, free_on_close); - +#if defined(CONFIG_MALI_VECTOR_DUMP) if (vma->vm_pgoff == PFN_DOWN(BASE_MEM_MMU_DUMP_HANDLE)) { /* MMU dump - userspace should now have a reference on * the pages, so we can now free the kernel mapping @@ -2949,7 +2974,7 @@ int kbase_context_mmap(struct kbase_context *const kctx, */ vma->vm_pgoff = PFN_DOWN(vma->vm_start); } - +#endif /* defined(CONFIG_MALI_VECTOR_DUMP) */ out_unlock: kbase_gpu_vm_unlock(kctx); out: @@ -2991,9 +3016,9 @@ void kbase_sync_mem_regions(struct kbase_context *kctx, } } -static int kbase_vmap_phy_pages(struct kbase_context *kctx, - struct kbase_va_region *reg, u64 offset_bytes, size_t size, - struct kbase_vmap_struct *map) +static int kbase_vmap_phy_pages(struct kbase_context *kctx, struct kbase_va_region *reg, + u64 offset_bytes, size_t size, struct kbase_vmap_struct *map, + kbase_vmap_flag vmap_flags) { unsigned long page_index; unsigned int offset_in_page = offset_bytes & ~PAGE_MASK; @@ -3004,6 +3029,12 @@ static int kbase_vmap_phy_pages(struct kbase_context *kctx, pgprot_t prot; size_t i; + if (WARN_ON(vmap_flags & ~KBASE_VMAP_INPUT_FLAGS)) + return -EINVAL; + + if (WARN_ON(kbase_is_region_invalid_or_free(reg))) + return -EINVAL; + if (!size || !map || !reg->cpu_alloc || !reg->gpu_alloc) return -EINVAL; @@ -3020,6 +3051,17 @@ static int kbase_vmap_phy_pages(struct kbase_context *kctx, if (page_index + page_count > kbase_reg_current_backed_size(reg)) return -ENOMEM; + if ((vmap_flags & KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING) && + (page_count > (KBASE_PERMANENTLY_MAPPED_MEM_LIMIT_PAGES - + atomic_read(&kctx->permanent_mapped_pages)))) { + dev_warn( + kctx->kbdev->dev, + "Request for %llu more pages mem needing a permanent mapping would breach limit %lu, currently at %d pages", + (u64)page_count, KBASE_PERMANENTLY_MAPPED_MEM_LIMIT_PAGES, + atomic_read(&kctx->permanent_mapped_pages)); + return -ENOMEM; + } + if (reg->flags & KBASE_REG_DONT_NEED) return -EINVAL; @@ -3058,59 +3100,73 @@ static int kbase_vmap_phy_pages(struct kbase_context *kctx, map->gpu_pages = &kbase_get_gpu_phy_pages(reg)[page_index]; map->addr = (void *)((uintptr_t)cpu_addr + offset_in_page); map->size = size; - map->sync_needed = ((reg->flags & KBASE_REG_CPU_CACHED) != 0) && - !kbase_mem_is_imported(map->gpu_alloc->type); + map->flags = vmap_flags; + if ((reg->flags & KBASE_REG_CPU_CACHED) && !kbase_mem_is_imported(map->gpu_alloc->type)) + map->flags |= KBASE_VMAP_FLAG_SYNC_NEEDED; - if (map->sync_needed) + if (map->flags & KBASE_VMAP_FLAG_SYNC_NEEDED) kbase_sync_mem_regions(kctx, map, KBASE_SYNC_TO_CPU); + if (vmap_flags & KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING) + atomic_add(page_count, &kctx->permanent_mapped_pages); + kbase_mem_phy_alloc_kernel_mapped(reg->cpu_alloc); return 0; } +void *kbase_vmap_reg(struct kbase_context *kctx, struct kbase_va_region *reg, u64 gpu_addr, + size_t size, unsigned long prot_request, struct kbase_vmap_struct *map, + kbase_vmap_flag vmap_flags) +{ + u64 offset_bytes; + struct kbase_mem_phy_alloc *cpu_alloc; + struct kbase_mem_phy_alloc *gpu_alloc; + int err; + + lockdep_assert_held(&kctx->reg_lock); + + if (WARN_ON(kbase_is_region_invalid_or_free(reg))) + return NULL; + + /* check access permissions can be satisfied + * Intended only for checking KBASE_REG_{CPU,GPU}_{RD,WR} + */ + if ((reg->flags & prot_request) != prot_request) + return NULL; + + offset_bytes = gpu_addr - (reg->start_pfn << PAGE_SHIFT); + cpu_alloc = kbase_mem_phy_alloc_get(reg->cpu_alloc); + gpu_alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc); + + err = kbase_vmap_phy_pages(kctx, reg, offset_bytes, size, map, vmap_flags); + if (err < 0) + goto fail_vmap_phy_pages; + + return map->addr; + +fail_vmap_phy_pages: + kbase_mem_phy_alloc_put(cpu_alloc); + kbase_mem_phy_alloc_put(gpu_alloc); + return NULL; +} + void *kbase_vmap_prot(struct kbase_context *kctx, u64 gpu_addr, size_t size, unsigned long prot_request, struct kbase_vmap_struct *map) { struct kbase_va_region *reg; void *addr = NULL; - u64 offset_bytes; - struct kbase_mem_phy_alloc *cpu_alloc; - struct kbase_mem_phy_alloc *gpu_alloc; - int err; kbase_gpu_vm_lock(kctx); - reg = kbase_region_tracker_find_region_enclosing_address(kctx, - gpu_addr); + reg = kbase_region_tracker_find_region_enclosing_address(kctx, gpu_addr); if (kbase_is_region_invalid_or_free(reg)) goto out_unlock; - /* check access permissions can be satisfied - * Intended only for checking KBASE_REG_{CPU,GPU}_{RD,WR} - */ - if ((reg->flags & prot_request) != prot_request) - goto out_unlock; - - offset_bytes = gpu_addr - (reg->start_pfn << PAGE_SHIFT); - cpu_alloc = kbase_mem_phy_alloc_get(reg->cpu_alloc); - gpu_alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc); - - err = kbase_vmap_phy_pages(kctx, reg, offset_bytes, size, map); - if (err < 0) - goto fail_vmap_phy_pages; - - addr = map->addr; + addr = kbase_vmap_reg(kctx, reg, gpu_addr, size, prot_request, map, 0u); out_unlock: kbase_gpu_vm_unlock(kctx); return addr; - -fail_vmap_phy_pages: - kbase_gpu_vm_unlock(kctx); - kbase_mem_phy_alloc_put(cpu_alloc); - kbase_mem_phy_alloc_put(gpu_alloc); - - return NULL; } void *kbase_vmap(struct kbase_context *kctx, u64 gpu_addr, size_t size, @@ -3133,16 +3189,23 @@ static void kbase_vunmap_phy_pages(struct kbase_context *kctx, vunmap(addr); - if (map->sync_needed) + if (map->flags & KBASE_VMAP_FLAG_SYNC_NEEDED) kbase_sync_mem_regions(kctx, map, KBASE_SYNC_TO_DEVICE); + if (map->flags & KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING) { + size_t page_count = PFN_UP(map->offset_in_page + map->size); + + WARN_ON(page_count > atomic_read(&kctx->permanent_mapped_pages)); + atomic_sub(page_count, &kctx->permanent_mapped_pages); + } kbase_mem_phy_alloc_kernel_unmapped(map->cpu_alloc); + map->offset_in_page = 0; map->cpu_pages = NULL; map->gpu_pages = NULL; map->addr = NULL; map->size = 0; - map->sync_needed = false; + map->flags = 0; } void kbase_vunmap(struct kbase_context *kctx, struct kbase_vmap_struct *map) @@ -3266,9 +3329,27 @@ static unsigned long get_queue_doorbell_pfn(struct kbase_device *kbdev, (u64)queue->doorbell_nr * CSF_HW_DOORBELL_PAGE_SIZE)); } +static int +#if (KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE || \ + KERNEL_VERSION(5, 11, 0) > LINUX_VERSION_CODE) +kbase_csf_user_io_pages_vm_mremap(struct vm_area_struct *vma) +#else +kbase_csf_user_io_pages_vm_mremap(struct vm_area_struct *vma, unsigned long flags) +#endif +{ + pr_debug("Unexpected call to mremap method for User IO pages mapping vma\n"); + return -EINVAL; +} + +static int kbase_csf_user_io_pages_vm_split(struct vm_area_struct *vma, unsigned long addr) +{ + pr_debug("Unexpected call to split method for User IO pages mapping vma\n"); + return -EINVAL; +} + static void kbase_csf_user_io_pages_vm_open(struct vm_area_struct *vma) { - WARN(1, "Unexpected attempt to clone private vma\n"); + pr_debug("Unexpected call to the open method for User IO pages mapping vma\n"); vma->vm_private_data = NULL; } @@ -3280,8 +3361,10 @@ static void kbase_csf_user_io_pages_vm_close(struct vm_area_struct *vma) int err; bool reset_prevented = false; - if (WARN_ON(!queue)) + if (!queue) { + pr_debug("Close method called for the new User IO pages mapping vma\n"); return; + } kctx = queue->kctx; kbdev = kctx->kbdev; @@ -3325,9 +3408,12 @@ static vm_fault_t kbase_csf_user_io_pages_vm_fault(struct vm_fault *vmf) struct memory_group_manager_device *mgm_dev; /* Few sanity checks up front */ - if ((nr_pages != BASEP_QUEUE_NR_MMAP_USER_PAGES) || - (vma->vm_pgoff != queue->db_file_offset)) + if (!queue || (nr_pages != BASEP_QUEUE_NR_MMAP_USER_PAGES) || + (vma->vm_pgoff != queue->db_file_offset)) { + pr_warn("Unexpected CPU page fault on User IO pages mapping for process %s tgid %d pid %d\n", + current->comm, current->tgid, current->pid); return VM_FAULT_SIGBUS; + } kbdev = queue->kctx->kbdev; mgm_dev = kbdev->mgm_dev; @@ -3382,6 +3468,12 @@ exit: static const struct vm_operations_struct kbase_csf_user_io_pages_vm_ops = { .open = kbase_csf_user_io_pages_vm_open, .close = kbase_csf_user_io_pages_vm_close, +#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE + .may_split = kbase_csf_user_io_pages_vm_split, +#else + .split = kbase_csf_user_io_pages_vm_split, +#endif + .mremap = kbase_csf_user_io_pages_vm_mremap, .fault = kbase_csf_user_io_pages_vm_fault }; @@ -3461,13 +3553,71 @@ map_failed: return err; } +/** + * kbase_csf_user_reg_vm_open - VMA open function for the USER page + * + * @vma: Pointer to the struct containing information about + * the userspace mapping of USER page. + * Note: + * This function isn't expected to be called. If called (i.e> mremap), + * set private_data as NULL to indicate to close() and fault() functions. + */ +static void kbase_csf_user_reg_vm_open(struct vm_area_struct *vma) +{ + pr_debug("Unexpected call to the open method for USER register mapping"); + vma->vm_private_data = NULL; +} + +/** + * kbase_csf_user_reg_vm_close - VMA close function for the USER page + * + * @vma: Pointer to the struct containing information about + * the userspace mapping of USER page. + */ static void kbase_csf_user_reg_vm_close(struct vm_area_struct *vma) { struct kbase_context *kctx = vma->vm_private_data; - WARN_ON(!kctx->csf.user_reg_vma); + if (!kctx) { + pr_debug("Close function called for the unexpected mapping"); + return; + } + + if (unlikely(!kctx->csf.user_reg_vma)) + dev_warn(kctx->kbdev->dev, "user_reg_vma pointer unexpectedly NULL"); kctx->csf.user_reg_vma = NULL; + + mutex_lock(&kctx->kbdev->csf.reg_lock); + if (unlikely(kctx->kbdev->csf.nr_user_page_mapped == 0)) + dev_warn(kctx->kbdev->dev, "Unexpected value for the USER page mapping counter"); + else + kctx->kbdev->csf.nr_user_page_mapped--; + mutex_unlock(&kctx->kbdev->csf.reg_lock); +} + +/** + * kbase_csf_user_reg_vm_mremap - VMA mremap function for the USER page + * + * @vma: Pointer to the struct containing information about + * the userspace mapping of USER page. + * + * Return: -EINVAL + * + * Note: + * User space must not attempt mremap on USER page mapping. + * This function will return an error to fail the attempt. + */ +static int +#if ((KERNEL_VERSION(5, 13, 0) <= LINUX_VERSION_CODE) || \ + (KERNEL_VERSION(5, 11, 0) > LINUX_VERSION_CODE)) +kbase_csf_user_reg_vm_mremap(struct vm_area_struct *vma) +#else +kbase_csf_user_reg_vm_mremap(struct vm_area_struct *vma, unsigned long flags) +#endif +{ + pr_debug("Unexpected call to mremap method for USER page mapping vma\n"); + return -EINVAL; } #if (KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE) @@ -3480,19 +3630,24 @@ static vm_fault_t kbase_csf_user_reg_vm_fault(struct vm_fault *vmf) struct vm_area_struct *vma = vmf->vma; #endif struct kbase_context *kctx = vma->vm_private_data; - struct kbase_device *kbdev = kctx->kbdev; - struct memory_group_manager_device *mgm_dev = kbdev->mgm_dev; - unsigned long pfn = PFN_DOWN(kbdev->reg_start + USER_BASE); + struct kbase_device *kbdev; + struct memory_group_manager_device *mgm_dev; + unsigned long pfn; size_t nr_pages = PFN_DOWN(vma->vm_end - vma->vm_start); vm_fault_t ret = VM_FAULT_SIGBUS; unsigned long flags; /* Few sanity checks up front */ - if (WARN_ON(nr_pages != 1) || - WARN_ON(vma != kctx->csf.user_reg_vma) || - WARN_ON(vma->vm_pgoff != - PFN_DOWN(BASEP_MEM_CSF_USER_REG_PAGE_HANDLE))) + if (!kctx || (nr_pages != 1) || (vma != kctx->csf.user_reg_vma) || + (vma->vm_pgoff != PFN_DOWN(BASEP_MEM_CSF_USER_REG_PAGE_HANDLE))) { + pr_warn("Unexpected CPU page fault on USER page mapping for process %s tgid %d pid %d\n", + current->comm, current->tgid, current->pid); return VM_FAULT_SIGBUS; + } + + kbdev = kctx->kbdev; + mgm_dev = kbdev->mgm_dev; + pfn = PFN_DOWN(kbdev->reg_start + USER_BASE); mutex_lock(&kbdev->csf.reg_lock); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); @@ -3517,14 +3672,31 @@ static vm_fault_t kbase_csf_user_reg_vm_fault(struct vm_fault *vmf) } static const struct vm_operations_struct kbase_csf_user_reg_vm_ops = { + .open = kbase_csf_user_reg_vm_open, .close = kbase_csf_user_reg_vm_close, + .mremap = kbase_csf_user_reg_vm_mremap, .fault = kbase_csf_user_reg_vm_fault }; +/** + * kbase_csf_cpu_mmap_user_reg_page - Memory map method for USER page. + * + * @kctx: Pointer of the kernel context. + * @vma: Pointer to the struct containing the information about + * the userspace mapping of USER page. + * + * Return: 0 on success, error code otherwise. + * + * Note: + * New Base will request Kbase to read the LATEST_FLUSH of USER page on its behalf. + * But this function needs to be kept for backward-compatibility as old Base (<=1.12) + * will try to mmap USER page for direct access when it creates a base context. + */ static int kbase_csf_cpu_mmap_user_reg_page(struct kbase_context *kctx, struct vm_area_struct *vma) { size_t nr_pages = PFN_DOWN(vma->vm_end - vma->vm_start); + struct kbase_device *kbdev = kctx->kbdev; /* Few sanity checks */ if (kctx->csf.user_reg_vma) @@ -3548,6 +3720,17 @@ static int kbase_csf_cpu_mmap_user_reg_page(struct kbase_context *kctx, kctx->csf.user_reg_vma = vma; + mutex_lock(&kbdev->csf.reg_lock); + kbdev->csf.nr_user_page_mapped++; + + if (!kbdev->csf.mali_file_inode) + kbdev->csf.mali_file_inode = kctx->filp->f_inode; + + if (unlikely(kbdev->csf.mali_file_inode != kctx->filp->f_inode)) + dev_warn(kbdev->dev, "Device file inode pointer not same for all contexts"); + + mutex_unlock(&kbdev->csf.reg_lock); + vma->vm_ops = &kbase_csf_user_reg_vm_ops; vma->vm_private_data = kctx; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h index 5e5d991105a6..5b12e181bf4c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_linux.h @@ -217,6 +217,26 @@ int kbase_mem_evictable_make(struct kbase_mem_phy_alloc *gpu_alloc); */ bool kbase_mem_evictable_unmake(struct kbase_mem_phy_alloc *alloc); +typedef unsigned int kbase_vmap_flag; + +/* Sync operations are needed on beginning and ending of access to kernel-mapped GPU memory. + * + * This is internal to the struct kbase_vmap_struct and should not be passed in by callers of + * kbase_vmap-related functions. + */ +#define KBASE_VMAP_FLAG_SYNC_NEEDED (((kbase_vmap_flag)1) << 0) + +/* Permanently mapped memory accounting (including enforcing limits) should be done on the + * kernel-mapped GPU memory. + * + * This should be used if the kernel mapping is going to live for a potentially long time, for + * example if it will persist after the caller has returned. + */ +#define KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING (((kbase_vmap_flag)1) << 1) + +/* Set of flags that can be passed into kbase_vmap-related functions */ +#define KBASE_VMAP_INPUT_FLAGS (KBASE_VMAP_FLAG_PERMANENT_MAP_ACCOUNTING) + struct kbase_vmap_struct { off_t offset_in_page; struct kbase_mem_phy_alloc *cpu_alloc; @@ -225,9 +245,55 @@ struct kbase_vmap_struct { struct tagged_addr *gpu_pages; void *addr; size_t size; - bool sync_needed; + kbase_vmap_flag flags; }; +/** + * kbase_mem_shrink_gpu_mapping - Shrink the GPU mapping of an allocation + * @kctx: Context the region belongs to + * @reg: The GPU region or NULL if there isn't one + * @new_pages: The number of pages after the shrink + * @old_pages: The number of pages before the shrink + * + * Return: 0 on success, negative -errno on error + * + * Unmap the shrunk pages from the GPU mapping. Note that the size of the region + * itself is unmodified as we still need to reserve the VA, only the page tables + * will be modified by this function. + */ +int kbase_mem_shrink_gpu_mapping(struct kbase_context *kctx, struct kbase_va_region *reg, + u64 new_pages, u64 old_pages); + +/** + * kbase_vmap_reg - Map part of an existing region into the kernel safely, only if the requested + * access permissions are supported + * @kctx: Context @reg belongs to + * @reg: The GPU region to map part of + * @gpu_addr: Start address of VA range to map, which must be within @reg + * @size: Size of VA range, which when added to @gpu_addr must be within @reg + * @prot_request: Flags indicating how the caller will then access the memory + * @map: Structure to be given to kbase_vunmap() on freeing + * @vmap_flags: Flags of type kbase_vmap_flag + * + * Return: Kernel-accessible CPU pointer to the VA range, or NULL on error + * + * Variant of kbase_vmap_prot() that can be used given an existing region. + * + * The caller must satisfy one of the following for @reg: + * * It must have been obtained by finding it on the region tracker, and the region lock must not + * have been released in the mean time. + * * Or, it must have been refcounted with a call to kbase_va_region_alloc_get(), and the region + * lock is now held again. + * * Or, @reg has had KBASE_REG_NO_USER_FREE set at creation time or under the region lock, and the + * region lock is now held again. + * + * The acceptable @vmap_flags are those in %KBASE_VMAP_INPUT_FLAGS. + * + * Refer to kbase_vmap_prot() for more information on the operation of this function. + */ +void *kbase_vmap_reg(struct kbase_context *kctx, struct kbase_va_region *reg, u64 gpu_addr, + size_t size, unsigned long prot_request, struct kbase_vmap_struct *map, + kbase_vmap_flag vmap_flags); /** * kbase_vmap_prot - Map a GPU VA range into the kernel safely, only if the diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_migrate.c b/drivers/gpu/arm/bifrost/mali_kbase_mem_migrate.c new file mode 100644 index 000000000000..dfa70252bcf1 --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_migrate.c @@ -0,0 +1,350 @@ +// 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. + * + */ + +/** + * DOC: Base kernel page migration implementation. + */ + +#include + +#include +#include + +/* Global integer used to determine if module parameter value has been + * provided and if page migration feature is enabled. + * Feature is disabled on all platforms by default. + */ +int kbase_page_migration_enabled; +module_param(kbase_page_migration_enabled, int, 0444); +KBASE_EXPORT_TEST_API(kbase_page_migration_enabled); + +bool kbase_alloc_page_metadata(struct kbase_device *kbdev, struct page *p, dma_addr_t dma_addr) +{ + struct kbase_page_metadata *page_md = + kzalloc(sizeof(struct kbase_page_metadata), GFP_KERNEL); + + if (!page_md) + return false; + + SetPagePrivate(p); + set_page_private(p, (unsigned long)page_md); + page_md->dma_addr = dma_addr; + page_md->status = PAGE_STATUS_SET(page_md->status, (u8)ALLOCATE_IN_PROGRESS); + spin_lock_init(&page_md->migrate_lock); + + lock_page(p); + if (kbdev->mem_migrate.mapping) + __SetPageMovable(p, kbdev->mem_migrate.mapping); + unlock_page(p); + + return true; +} + +static void kbase_free_page_metadata(struct kbase_device *kbdev, struct page *p) +{ + struct device *const dev = kbdev->dev; + struct kbase_page_metadata *page_md; + dma_addr_t dma_addr; + + page_md = kbase_page_private(p); + if (!page_md) + return; + + dma_addr = kbase_dma_addr(p); + dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL); + + kfree(page_md); + ClearPagePrivate(p); +} + +static void kbase_free_pages_worker(struct work_struct *work) +{ + struct kbase_mem_migrate *mem_migrate = + container_of(work, struct kbase_mem_migrate, free_pages_work); + struct kbase_device *kbdev = container_of(mem_migrate, struct kbase_device, mem_migrate); + struct page *p, *tmp; + LIST_HEAD(free_list); + + spin_lock(&mem_migrate->free_pages_lock); + list_splice_init(&mem_migrate->free_pages_list, &free_list); + spin_unlock(&mem_migrate->free_pages_lock); + + list_for_each_entry_safe(p, tmp, &free_list, lru) { + list_del_init(&p->lru); + + lock_page(p); + if (PageMovable(p)) + __ClearPageMovable(p); + unlock_page(p); + + kbase_free_page_metadata(kbdev, p); + __free_pages(p, 0); + } +} + +void kbase_free_page_later(struct kbase_device *kbdev, struct page *p) +{ + struct kbase_mem_migrate *mem_migrate = &kbdev->mem_migrate; + + spin_lock(&mem_migrate->free_pages_lock); + list_add(&p->lru, &mem_migrate->free_pages_list); + spin_unlock(&mem_migrate->free_pages_lock); +} + +/** + * kbase_page_isolate - Isolate a page for migration. + * + * @p: Pointer of the page struct of page to isolate. + * @mode: LRU Isolation modes. + * + * Callback function for Linux to isolate a page and prepare it for migration. + * + * Return: true on success, false otherwise. + */ +static bool kbase_page_isolate(struct page *p, isolate_mode_t mode) +{ + bool status_mem_pool = false; + struct kbase_mem_pool *mem_pool = NULL; + struct kbase_page_metadata *page_md = kbase_page_private(p); + + CSTD_UNUSED(mode); + + if (!spin_trylock(&page_md->migrate_lock)) + return false; + + if (WARN_ON(IS_PAGE_ISOLATED(page_md->status))) { + spin_unlock(&page_md->migrate_lock); + return false; + } + + switch (PAGE_STATUS_GET(page_md->status)) { + case MEM_POOL: + /* Prepare to remove page from memory pool later only if pool is not + * in the process of termination. + */ + mem_pool = page_md->data.mem_pool.pool; + status_mem_pool = true; + preempt_disable(); + atomic_inc(&mem_pool->isolation_in_progress_cnt); + break; + case ALLOCATED_MAPPED: + case PT_MAPPED: + /* Only pages in a memory pool can be isolated for now. */ + break; + case SPILL_IN_PROGRESS: + case ALLOCATE_IN_PROGRESS: + case FREE_IN_PROGRESS: + /* Transitory state: do nothing. */ + break; + default: + /* State should always fall in one of the previous cases! + * Also notice that FREE_ISOLATED_IN_PROGRESS is impossible because + * that state only applies to pages that are already isolated. + */ + page_md->status = PAGE_ISOLATE_SET(page_md->status, 0); + break; + } + + spin_unlock(&page_md->migrate_lock); + + /* If the page is still in the memory pool: try to remove it. This will fail + * if pool lock is taken which could mean page no longer exists in pool. + */ + if (status_mem_pool) { + if (!spin_trylock(&mem_pool->pool_lock)) { + atomic_dec(&mem_pool->isolation_in_progress_cnt); + preempt_enable(); + return false; + } + + spin_lock(&page_md->migrate_lock); + /* Check status again to ensure page has not been removed from memory pool. */ + if (PAGE_STATUS_GET(page_md->status) == MEM_POOL) { + page_md->status = PAGE_ISOLATE_SET(page_md->status, 1); + list_del_init(&p->lru); + mem_pool->cur_size--; + } + spin_unlock(&page_md->migrate_lock); + spin_unlock(&mem_pool->pool_lock); + atomic_dec(&mem_pool->isolation_in_progress_cnt); + preempt_enable(); + } + + return IS_PAGE_ISOLATED(page_md->status); +} + +/** + * kbase_page_migrate - Migrate content of old page to new page provided. + * + * @mapping: Pointer to address_space struct associated with pages. + * @new_page: Pointer to the page struct of new page. + * @old_page: Pointer to the page struct of old page. + * @mode: Mode to determine if migration will be synchronised. + * + * Callback function for Linux to migrate the content of the old page to the + * new page provided. + * + * Return: 0 on success, error code otherwise. + */ +static int kbase_page_migrate(struct address_space *mapping, struct page *new_page, + struct page *old_page, enum migrate_mode mode) +{ + int err = 0; + bool status_mem_pool = false; + struct kbase_page_metadata *page_md = kbase_page_private(old_page); + struct kbase_device *kbdev; + + CSTD_UNUSED(mapping); + CSTD_UNUSED(mode); + + if (!spin_trylock(&page_md->migrate_lock)) + return -EAGAIN; + + if (WARN_ON(!IS_PAGE_ISOLATED(page_md->status))) { + spin_unlock(&page_md->migrate_lock); + return -EINVAL; + } + + switch (PAGE_STATUS_GET(page_md->status)) { + case MEM_POOL: + status_mem_pool = true; + kbdev = page_md->data.mem_pool.kbdev; + break; + case ALLOCATED_MAPPED: + case PT_MAPPED: + case FREE_ISOLATED_IN_PROGRESS: + case MULTI_MAPPED: + /* So far, only pages in a memory pool can be migrated. */ + default: + /* State should always fall in one of the previous cases! */ + err = -EAGAIN; + break; + } + + spin_unlock(&page_md->migrate_lock); + + if (status_mem_pool) { + struct kbase_mem_migrate *mem_migrate = &kbdev->mem_migrate; + + kbase_free_page_metadata(kbdev, old_page); + __ClearPageMovable(old_page); + + /* Just free new page to avoid lock contention. */ + INIT_LIST_HEAD(&new_page->lru); + set_page_private(new_page, 0); + kbase_free_page_later(kbdev, new_page); + queue_work(mem_migrate->free_pages_workq, &mem_migrate->free_pages_work); + } + + return err; +} + +/** + * kbase_page_putback - Return isolated page back to kbase. + * + * @p: Pointer of the page struct of page. + * + * Callback function for Linux to return isolated page back to kbase. This + * will only be called for a page that has been isolated but failed to + * migrate. This function will put back the given page to the state it was + * in before it was isolated. + */ +static void kbase_page_putback(struct page *p) +{ + bool status_mem_pool = false; + struct kbase_page_metadata *page_md = kbase_page_private(p); + struct kbase_device *kbdev; + + spin_lock(&page_md->migrate_lock); + + /* Page must have been isolated to reach here but metadata is incorrect. */ + WARN_ON(!IS_PAGE_ISOLATED(page_md->status)); + + switch (PAGE_STATUS_GET(page_md->status)) { + case MEM_POOL: + status_mem_pool = true; + kbdev = page_md->data.mem_pool.kbdev; + break; + case ALLOCATED_MAPPED: + case PT_MAPPED: + case FREE_ISOLATED_IN_PROGRESS: + /* Only pages in a memory pool can be isolated for now. + * Therefore only pages in a memory pool can be 'putback'. + */ + break; + default: + /* State should always fall in one of the previous cases! */ + break; + } + + spin_unlock(&page_md->migrate_lock); + + /* If page was in a memory pool then just free it to avoid lock contention. */ + if (!WARN_ON(!status_mem_pool)) { + struct kbase_mem_migrate *mem_migrate = &kbdev->mem_migrate; + + __ClearPageMovable(p); + list_del_init(&p->lru); + kbase_free_page_later(kbdev, p); + queue_work(mem_migrate->free_pages_workq, &mem_migrate->free_pages_work); + } +} + +static const struct address_space_operations kbase_address_space_ops = { + .isolate_page = kbase_page_isolate, + .migratepage = kbase_page_migrate, + .putback_page = kbase_page_putback, +}; + +void kbase_mem_migrate_set_address_space_ops(struct kbase_device *kbdev, struct file *const filp) +{ + if (filp) { + filp->f_inode->i_mapping->a_ops = &kbase_address_space_ops; + + if (!kbdev->mem_migrate.mapping) + kbdev->mem_migrate.mapping = filp->f_inode->i_mapping; + else + WARN_ON(kbdev->mem_migrate.mapping != filp->f_inode->i_mapping); + } +} + +void kbase_mem_migrate_init(struct kbase_device *kbdev) +{ + struct kbase_mem_migrate *mem_migrate = &kbdev->mem_migrate; + + if (kbase_page_migration_enabled < 0) + kbase_page_migration_enabled = 0; + + spin_lock_init(&mem_migrate->free_pages_lock); + INIT_LIST_HEAD(&mem_migrate->free_pages_list); + + mem_migrate->free_pages_workq = + alloc_workqueue("free_pages_workq", WQ_UNBOUND | WQ_MEM_RECLAIM, 1); + INIT_WORK(&mem_migrate->free_pages_work, kbase_free_pages_worker); +} + +void kbase_mem_migrate_term(struct kbase_device *kbdev) +{ + struct kbase_mem_migrate *mem_migrate = &kbdev->mem_migrate; + + if (mem_migrate->free_pages_workq) + destroy_workqueue(mem_migrate->free_pages_workq); +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_migrate.h b/drivers/gpu/arm/bifrost/mali_kbase_mem_migrate.h new file mode 100644 index 000000000000..6610c0ccc40c --- /dev/null +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_migrate.h @@ -0,0 +1,94 @@ +/* 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. + * + */ + +/** + * DOC: Base kernel page migration implementation. + */ + +#define PAGE_STATUS_MASK ((u8)0x7F) +#define PAGE_STATUS_GET(status) (status & PAGE_STATUS_MASK) +#define PAGE_STATUS_SET(status, value) ((status & ~PAGE_STATUS_MASK) | (value & PAGE_STATUS_MASK)) +#define PAGE_ISOLATE_SHIFT (7) +#define PAGE_ISOLATE_SET(status, value) \ + ((status & PAGE_STATUS_MASK) | (value << PAGE_ISOLATE_SHIFT)) +#define IS_PAGE_ISOLATED(status) ((bool)(status & ~PAGE_STATUS_MASK)) + +/* Global integer used to determine if module parameter value has been + * provided and if page migration feature is enabled. + */ +extern int kbase_page_migration_enabled; + +/** + * kbase_alloc_page_metadata - Allocate and initialize page metadata + * @kbdev: Pointer to kbase device. + * @p: Page to assign metadata to. + * @dma_addr: DMA address mapped to paged. + * + * This will allocate memory for the page's metadata, initialize it and + * assign a reference to the page's private field. Importantly, once + * the metadata is set and ready this function will mark the page as + * movable. + * + * Return: true if successful or false otherwise. + */ +bool kbase_alloc_page_metadata(struct kbase_device *kbdev, struct page *p, dma_addr_t dma_addr); + +/** + * kbase_free_page_later - Defer freeing of given page. + * @kbdev: Pointer to kbase device + * @p: Page to free + * + * This will add given page to a list of pages which will be freed at + * a later time. + */ +void kbase_free_page_later(struct kbase_device *kbdev, struct page *p); + +/* + * kbase_mem_migrate_set_address_space_ops - Set address space operations + * + * @kbdev: Pointer to object representing an instance of GPU platform device. + * @filp: Pointer to the struct file corresponding to device file + * /dev/malixx instance, passed to the file's open method. + * + * Assign address space operations to the given file struct @filp and + * add a reference to @kbdev. + */ +void kbase_mem_migrate_set_address_space_ops(struct kbase_device *kbdev, struct file *const filp); + +/* + * kbase_mem_migrate_init - Initialise kbase page migration + * + * @kbdev: Pointer to kbase device + * + * Enables page migration by default based on GPU and setup work queue to + * defer freeing pages during page migration callbacks. + */ +void kbase_mem_migrate_init(struct kbase_device *kbdev); + +/* + * kbase_mem_migrate_term - Terminate kbase page migration + * + * @kbdev: Pointer to kbase device + * + * This will flush any work left to free pages from page migration + * and destroy workqueue associated. + */ +void kbase_mem_migrate_term(struct kbase_device *kbdev); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_pool.c b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool.c index 4103bd1c93d0..dce066db7385 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem_pool.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2015-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2015-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 @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -56,13 +57,36 @@ static bool kbase_mem_pool_is_empty(struct kbase_mem_pool *pool) return kbase_mem_pool_size(pool) == 0; } +static void set_pool_new_page_metadata(struct kbase_mem_pool *pool, struct page *p, + struct list_head *page_list, size_t *list_size) +{ + struct kbase_page_metadata *page_md = kbase_page_private(p); + + lockdep_assert_held(&pool->pool_lock); + + spin_lock(&page_md->migrate_lock); + /* Only update page status and add the page to the memory pool if it is not isolated */ + if (!WARN_ON(IS_PAGE_ISOLATED(page_md->status))) { + page_md->status = PAGE_STATUS_SET(page_md->status, (u8)MEM_POOL); + page_md->data.mem_pool.pool = pool; + page_md->data.mem_pool.kbdev = pool->kbdev; + list_move(&p->lru, page_list); + (*list_size)++; + } + spin_unlock(&page_md->migrate_lock); +} + static void kbase_mem_pool_add_locked(struct kbase_mem_pool *pool, struct page *p) { lockdep_assert_held(&pool->pool_lock); - list_add(&p->lru, &pool->page_list); - pool->cur_size++; + if (!pool->order && kbase_page_migration_enabled) + set_pool_new_page_metadata(pool, p, &pool->page_list, &pool->cur_size); + else { + list_add(&p->lru, &pool->page_list); + pool->cur_size++; + } pool_dbg(pool, "added page\n"); } @@ -79,8 +103,15 @@ static void kbase_mem_pool_add_list_locked(struct kbase_mem_pool *pool, { lockdep_assert_held(&pool->pool_lock); - list_splice(page_list, &pool->page_list); - pool->cur_size += nr_pages; + if (!pool->order && kbase_page_migration_enabled) { + struct page *p, *tmp; + + list_for_each_entry_safe(p, tmp, page_list, lru) + set_pool_new_page_metadata(pool, p, &pool->page_list, &pool->cur_size); + } else { + list_splice(page_list, &pool->page_list); + pool->cur_size += nr_pages; + } pool_dbg(pool, "added %zu pages\n", nr_pages); } @@ -93,7 +124,8 @@ static void kbase_mem_pool_add_list(struct kbase_mem_pool *pool, kbase_mem_pool_unlock(pool); } -static struct page *kbase_mem_pool_remove_locked(struct kbase_mem_pool *pool) +static struct page *kbase_mem_pool_remove_locked(struct kbase_mem_pool *pool, + enum kbase_page_status status) { struct page *p; @@ -103,6 +135,16 @@ static struct page *kbase_mem_pool_remove_locked(struct kbase_mem_pool *pool) return NULL; p = list_first_entry(&pool->page_list, struct page, lru); + + if (!pool->order && kbase_page_migration_enabled) { + struct kbase_page_metadata *page_md = kbase_page_private(p); + + spin_lock(&page_md->migrate_lock); + WARN_ON(PAGE_STATUS_GET(page_md->status) != (u8)MEM_POOL); + page_md->status = PAGE_STATUS_SET(page_md->status, (u8)status); + spin_unlock(&page_md->migrate_lock); + } + list_del_init(&p->lru); pool->cur_size--; @@ -111,12 +153,13 @@ static struct page *kbase_mem_pool_remove_locked(struct kbase_mem_pool *pool) return p; } -static struct page *kbase_mem_pool_remove(struct kbase_mem_pool *pool) +static struct page *kbase_mem_pool_remove(struct kbase_mem_pool *pool, + enum kbase_page_status status) { struct page *p; kbase_mem_pool_lock(pool); - p = kbase_mem_pool_remove_locked(pool); + p = kbase_mem_pool_remove_locked(pool, status); kbase_mem_pool_unlock(pool); return p; @@ -126,9 +169,9 @@ static void kbase_mem_pool_sync_page(struct kbase_mem_pool *pool, struct page *p) { struct device *dev = pool->kbdev->dev; + dma_addr_t dma_addr = pool->order ? kbase_dma_addr_as_priv(p) : kbase_dma_addr(p); - dma_sync_single_for_device(dev, kbase_dma_addr(p), - (PAGE_SIZE << pool->order), DMA_BIDIRECTIONAL); + dma_sync_single_for_device(dev, dma_addr, (PAGE_SIZE << pool->order), DMA_BIDIRECTIONAL); } static void kbase_mem_pool_zero_page(struct kbase_mem_pool *pool, @@ -154,7 +197,7 @@ static void kbase_mem_pool_spill(struct kbase_mem_pool *next_pool, struct page *kbase_mem_alloc_page(struct kbase_mem_pool *pool) { struct page *p; - gfp_t gfp = GFP_HIGHUSER | __GFP_ZERO; + gfp_t gfp = __GFP_ZERO; struct kbase_device *const kbdev = pool->kbdev; struct device *const dev = kbdev->dev; dma_addr_t dma_addr; @@ -162,7 +205,9 @@ struct page *kbase_mem_alloc_page(struct kbase_mem_pool *pool) /* don't warn on higher order failures */ if (pool->order) - gfp |= __GFP_NOWARN; + gfp |= GFP_HIGHUSER | __GFP_NOWARN; + else + gfp |= kbase_page_migration_enabled ? GFP_HIGHUSER_MOVABLE : GFP_HIGHUSER; p = kbdev->mgm_dev->ops.mgm_alloc_page(kbdev->mgm_dev, pool->group_id, gfp, pool->order); @@ -178,30 +223,52 @@ struct page *kbase_mem_alloc_page(struct kbase_mem_pool *pool) return NULL; } - WARN_ON(dma_addr != page_to_phys(p)); - for (i = 0; i < (1u << pool->order); i++) - kbase_set_dma_addr(p+i, dma_addr + PAGE_SIZE * i); + /* Setup page metadata for 4KB pages when page migration is enabled */ + if (!pool->order && kbase_page_migration_enabled) { + INIT_LIST_HEAD(&p->lru); + if (!kbase_alloc_page_metadata(kbdev, p, dma_addr)) { + dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL); + kbdev->mgm_dev->ops.mgm_free_page(kbdev->mgm_dev, pool->group_id, p, + pool->order); + return NULL; + } + } else { + WARN_ON(dma_addr != page_to_phys(p)); + for (i = 0; i < (1u << pool->order); i++) + kbase_set_dma_addr_as_priv(p + i, dma_addr + PAGE_SIZE * i); + } return p; } -static void kbase_mem_pool_free_page(struct kbase_mem_pool *pool, - struct page *p) +static void enqueue_free_pool_pages_work(struct kbase_mem_pool *pool) { - struct kbase_device *const kbdev = pool->kbdev; - struct device *const dev = kbdev->dev; - dma_addr_t dma_addr = kbase_dma_addr(p); - int i; + struct kbase_mem_migrate *mem_migrate = &pool->kbdev->mem_migrate; - dma_unmap_page(dev, dma_addr, (PAGE_SIZE << pool->order), - DMA_BIDIRECTIONAL); - for (i = 0; i < (1u << pool->order); i++) - kbase_clear_dma_addr(p+i); + if (!pool->order && kbase_page_migration_enabled) + queue_work(mem_migrate->free_pages_workq, &mem_migrate->free_pages_work); +} - kbdev->mgm_dev->ops.mgm_free_page(kbdev->mgm_dev, - pool->group_id, p, pool->order); +void kbase_mem_pool_free_page(struct kbase_mem_pool *pool, struct page *p) +{ + struct kbase_device *kbdev = pool->kbdev; - pool_dbg(pool, "freed page to kernel\n"); + if (!pool->order && kbase_page_migration_enabled) { + kbase_free_page_later(kbdev, p); + pool_dbg(pool, "page to be freed to kernel later\n"); + } else { + int i; + dma_addr_t dma_addr = kbase_dma_addr_as_priv(p); + + for (i = 0; i < (1u << pool->order); i++) + kbase_clear_dma_addr_as_priv(p + i); + + dma_unmap_page(kbdev->dev, dma_addr, (PAGE_SIZE << pool->order), DMA_BIDIRECTIONAL); + + kbdev->mgm_dev->ops.mgm_free_page(kbdev->mgm_dev, pool->group_id, p, pool->order); + + pool_dbg(pool, "freed page to kernel\n"); + } } static size_t kbase_mem_pool_shrink_locked(struct kbase_mem_pool *pool, @@ -213,10 +280,13 @@ static size_t kbase_mem_pool_shrink_locked(struct kbase_mem_pool *pool, lockdep_assert_held(&pool->pool_lock); for (i = 0; i < nr_to_shrink && !kbase_mem_pool_is_empty(pool); i++) { - p = kbase_mem_pool_remove_locked(pool); + p = kbase_mem_pool_remove_locked(pool, FREE_IN_PROGRESS); kbase_mem_pool_free_page(pool, p); } + /* Freeing of pages will be deferred when page migration is enabled. */ + enqueue_free_pool_pages_work(pool); + return i; } @@ -232,8 +302,7 @@ static size_t kbase_mem_pool_shrink(struct kbase_mem_pool *pool, return nr_freed; } -int kbase_mem_pool_grow(struct kbase_mem_pool *pool, - size_t nr_to_grow) +int kbase_mem_pool_grow(struct kbase_mem_pool *pool, size_t nr_to_grow) { struct page *p; size_t i; @@ -268,6 +337,7 @@ int kbase_mem_pool_grow(struct kbase_mem_pool *pool, return 0; } +KBASE_EXPORT_TEST_API(kbase_mem_pool_grow); void kbase_mem_pool_trim(struct kbase_mem_pool *pool, size_t new_size) { @@ -323,6 +393,9 @@ static unsigned long kbase_mem_pool_reclaim_count_objects(struct shrinker *s, kbase_mem_pool_lock(pool); if (pool->dont_reclaim && !pool->dying) { kbase_mem_pool_unlock(pool); + /* Tell shrinker to skip reclaim + * even though freeable pages are available + */ return 0; } pool_size = kbase_mem_pool_size(pool); @@ -342,7 +415,10 @@ static unsigned long kbase_mem_pool_reclaim_scan_objects(struct shrinker *s, kbase_mem_pool_lock(pool); if (pool->dont_reclaim && !pool->dying) { kbase_mem_pool_unlock(pool); - return 0; + /* Tell shrinker that reclaim can't be made and + * do not attempt again for this reclaim context. + */ + return SHRINK_STOP; } pool_dbg(pool, "reclaim scan %ld:\n", sc->nr_to_scan); @@ -356,12 +432,9 @@ static unsigned long kbase_mem_pool_reclaim_scan_objects(struct shrinker *s, return freed; } -int kbase_mem_pool_init(struct kbase_mem_pool *pool, - const struct kbase_mem_pool_config *config, - unsigned int order, - int group_id, - struct kbase_device *kbdev, - struct kbase_mem_pool *next_pool) +int kbase_mem_pool_init(struct kbase_mem_pool *pool, const struct kbase_mem_pool_config *config, + unsigned int order, int group_id, struct kbase_device *kbdev, + struct kbase_mem_pool *next_pool) { if (WARN_ON(group_id < 0) || WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS)) { @@ -375,6 +448,7 @@ int kbase_mem_pool_init(struct kbase_mem_pool *pool, pool->kbdev = kbdev; pool->next_pool = next_pool; pool->dying = false; + atomic_set(&pool->isolation_in_progress_cnt, 0); spin_lock_init(&pool->pool_lock); INIT_LIST_HEAD(&pool->page_list); @@ -392,6 +466,7 @@ int kbase_mem_pool_init(struct kbase_mem_pool *pool, return 0; } +KBASE_EXPORT_TEST_API(kbase_mem_pool_init); void kbase_mem_pool_mark_dying(struct kbase_mem_pool *pool) { @@ -423,14 +498,14 @@ void kbase_mem_pool_term(struct kbase_mem_pool *pool) /* Zero pages first without holding the next_pool lock */ for (i = 0; i < nr_to_spill; i++) { - p = kbase_mem_pool_remove_locked(pool); + p = kbase_mem_pool_remove_locked(pool, SPILL_IN_PROGRESS); list_add(&p->lru, &spill_list); } } while (!kbase_mem_pool_is_empty(pool)) { /* Free remaining pages to kernel */ - p = kbase_mem_pool_remove_locked(pool); + p = kbase_mem_pool_remove_locked(pool, FREE_IN_PROGRESS); list_add(&p->lru, &free_list); } @@ -451,8 +526,18 @@ void kbase_mem_pool_term(struct kbase_mem_pool *pool) kbase_mem_pool_free_page(pool, p); } + /* Freeing of pages will be deferred when page migration is enabled. */ + enqueue_free_pool_pages_work(pool); + + /* Before returning wait to make sure there are no pages undergoing page isolation + * which will require reference to this pool. + */ + while (atomic_read(&pool->isolation_in_progress_cnt)) + cpu_relax(); + pool_dbg(pool, "terminated\n"); } +KBASE_EXPORT_TEST_API(kbase_mem_pool_term); struct page *kbase_mem_pool_alloc(struct kbase_mem_pool *pool) { @@ -460,7 +545,7 @@ struct page *kbase_mem_pool_alloc(struct kbase_mem_pool *pool) do { pool_dbg(pool, "alloc()\n"); - p = kbase_mem_pool_remove(pool); + p = kbase_mem_pool_remove(pool, ALLOCATE_IN_PROGRESS); if (p) return p; @@ -478,7 +563,7 @@ struct page *kbase_mem_pool_alloc_locked(struct kbase_mem_pool *pool) lockdep_assert_held(&pool->pool_lock); pool_dbg(pool, "alloc_locked()\n"); - p = kbase_mem_pool_remove_locked(pool); + p = kbase_mem_pool_remove_locked(pool, ALLOCATE_IN_PROGRESS); if (p) return p; @@ -505,6 +590,8 @@ void kbase_mem_pool_free(struct kbase_mem_pool *pool, struct page *p, } else { /* Free page */ kbase_mem_pool_free_page(pool, p); + /* Freeing of pages will be deferred when page migration is enabled. */ + enqueue_free_pool_pages_work(pool); } } @@ -524,11 +611,13 @@ void kbase_mem_pool_free_locked(struct kbase_mem_pool *pool, struct page *p, } else { /* Free page */ kbase_mem_pool_free_page(pool, p); + /* Freeing of pages will be deferred when page migration is enabled. */ + enqueue_free_pool_pages_work(pool); } } int kbase_mem_pool_alloc_pages(struct kbase_mem_pool *pool, size_t nr_4k_pages, - struct tagged_addr *pages, bool partial_allowed) + struct tagged_addr *pages, bool partial_allowed) { struct page *p; size_t nr_from_pool; @@ -550,7 +639,7 @@ int kbase_mem_pool_alloc_pages(struct kbase_mem_pool *pool, size_t nr_4k_pages, while (nr_from_pool--) { int j; - p = kbase_mem_pool_remove_locked(pool); + p = kbase_mem_pool_remove_locked(pool, ALLOCATE_IN_PROGRESS); if (pool->order) { pages[i++] = as_tagged_tag(page_to_phys(p), HUGE_HEAD | HUGE_PAGE); @@ -566,8 +655,8 @@ int kbase_mem_pool_alloc_pages(struct kbase_mem_pool *pool, size_t nr_4k_pages, if (i != nr_4k_pages && pool->next_pool) { /* Allocate via next pool */ - err = kbase_mem_pool_alloc_pages(pool->next_pool, - nr_4k_pages - i, pages + i, partial_allowed); + err = kbase_mem_pool_alloc_pages(pool->next_pool, nr_4k_pages - i, pages + i, + partial_allowed); if (err < 0) goto err_rollback; @@ -638,7 +727,7 @@ int kbase_mem_pool_alloc_pages_locked(struct kbase_mem_pool *pool, for (i = 0; i < nr_pages_internal; i++) { int j; - p = kbase_mem_pool_remove_locked(pool); + p = kbase_mem_pool_remove_locked(pool, ALLOCATE_IN_PROGRESS); if (pool->order) { *pages++ = as_tagged_tag(page_to_phys(p), HUGE_HEAD | HUGE_PAGE); @@ -745,6 +834,7 @@ void kbase_mem_pool_free_pages(struct kbase_mem_pool *pool, size_t nr_pages, size_t nr_to_pool; LIST_HEAD(to_pool_list); size_t i = 0; + bool pages_released = false; pool_dbg(pool, "free_pages(%zu):\n", nr_pages); @@ -782,8 +872,13 @@ void kbase_mem_pool_free_pages(struct kbase_mem_pool *pool, size_t nr_pages, kbase_mem_pool_free_page(pool, p); pages[i] = as_tagged(0); + pages_released = true; } + /* Freeing of pages will be deferred when page migration is enabled. */ + if (pages_released) + enqueue_free_pool_pages_work(pool); + pool_dbg(pool, "free_pages(%zu) done\n", nr_pages); } @@ -796,6 +891,7 @@ void kbase_mem_pool_free_pages_locked(struct kbase_mem_pool *pool, size_t nr_to_pool; LIST_HEAD(to_pool_list); size_t i = 0; + bool pages_released = false; lockdep_assert_held(&pool->pool_lock); @@ -826,7 +922,12 @@ void kbase_mem_pool_free_pages_locked(struct kbase_mem_pool *pool, kbase_mem_pool_free_page(pool, p); pages[i] = as_tagged(0); + pages_released = true; } + /* Freeing of pages will be deferred when page migration is enabled. */ + if (pages_released) + enqueue_free_pool_pages_work(pool); + pool_dbg(pool, "free_pages_locked(%zu) done\n", nr_pages); } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_group.c b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_group.c index 8d7bb4d68854..49c4b041e13a 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_group.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_group.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 @@ -43,29 +43,22 @@ void kbase_mem_pool_group_config_set_max_size( } } -int kbase_mem_pool_group_init( - struct kbase_mem_pool_group *const mem_pools, - struct kbase_device *const kbdev, - const struct kbase_mem_pool_group_config *const configs, - struct kbase_mem_pool_group *next_pools) +int kbase_mem_pool_group_init(struct kbase_mem_pool_group *const mem_pools, + struct kbase_device *const kbdev, + const struct kbase_mem_pool_group_config *const configs, + struct kbase_mem_pool_group *next_pools) { int gid, err = 0; for (gid = 0; gid < MEMORY_GROUP_MANAGER_NR_GROUPS; ++gid) { - err = kbase_mem_pool_init(&mem_pools->small[gid], - &configs->small[gid], - KBASE_MEM_POOL_4KB_PAGE_TABLE_ORDER, - gid, - kbdev, - next_pools ? &next_pools->small[gid] : NULL); + err = kbase_mem_pool_init(&mem_pools->small[gid], &configs->small[gid], + KBASE_MEM_POOL_4KB_PAGE_TABLE_ORDER, gid, kbdev, + next_pools ? &next_pools->small[gid] : NULL); if (!err) { - err = kbase_mem_pool_init(&mem_pools->large[gid], - &configs->large[gid], - KBASE_MEM_POOL_2MB_PAGE_TABLE_ORDER, - gid, - kbdev, - next_pools ? &next_pools->large[gid] : NULL); + err = kbase_mem_pool_init(&mem_pools->large[gid], &configs->large[gid], + KBASE_MEM_POOL_2MB_PAGE_TABLE_ORDER, gid, kbdev, + next_pools ? &next_pools->large[gid] : NULL); if (err) kbase_mem_pool_term(&mem_pools->small[gid]); } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_group.h b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_group.h index f97f47d15b7d..fe8ce775258f 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_group.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_mem_pool_group.h @@ -86,10 +86,9 @@ void kbase_mem_pool_group_config_set_max_size( * * Return: 0 on success, otherwise a negative error code */ -int kbase_mem_pool_group_init(struct kbase_mem_pool_group *mem_pools, - struct kbase_device *kbdev, - const struct kbase_mem_pool_group_config *configs, - struct kbase_mem_pool_group *next_pools); +int kbase_mem_pool_group_init(struct kbase_mem_pool_group *mem_pools, struct kbase_device *kbdev, + const struct kbase_mem_pool_group_config *configs, + struct kbase_mem_pool_group *next_pools); /** * kbase_mem_pool_group_mark_dying - Mark a set of memory pools as dying diff --git a/drivers/gpu/arm/bifrost/mali_kbase_pbha.c b/drivers/gpu/arm/bifrost/mali_kbase_pbha.c index 90406b2bf1fe..b65f9e7b5162 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_pbha.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_pbha.c @@ -209,20 +209,13 @@ void kbase_pbha_write_settings(struct kbase_device *kbdev) } } -int kbase_pbha_read_dtb(struct kbase_device *kbdev) +static int kbase_pbha_read_int_id_override_property(struct kbase_device *kbdev, + const struct device_node *pbha_node) { u32 dtb_data[SYSC_ALLOC_COUNT * sizeof(u32) * DTB_SET_SIZE]; - const struct device_node *pbha_node; int sz, i; bool valid = true; - if (!kbasep_pbha_supported(kbdev)) - return 0; - - pbha_node = of_get_child_by_name(kbdev->dev->of_node, "pbha"); - if (!pbha_node) - return 0; - sz = of_property_count_elems_of_size(pbha_node, "int_id_override", sizeof(u32)); if (sz <= 0 || (sz % DTB_SET_SIZE != 0)) { @@ -256,3 +249,58 @@ int kbase_pbha_read_dtb(struct kbase_device *kbdev) } return 0; } + +#if MALI_USE_CSF +static int kbase_pbha_read_propagate_bits_property(struct kbase_device *kbdev, + const struct device_node *pbha_node) +{ + u32 bits; + int err; + + if (!kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PBHA_HWU)) + return 0; + + err = of_property_read_u32(pbha_node, "propagate_bits", &bits); + + if (err < 0) { + if (err != -EINVAL) { + dev_err(kbdev->dev, + "DTB value for propagate_bits is improperly formed (err=%d)\n", + err); + return err; + } + } + + if (bits > (L2_CONFIG_PBHA_HWU_MASK >> L2_CONFIG_PBHA_HWU_SHIFT)) { + dev_err(kbdev->dev, "Bad DTB value for propagate_bits: 0x%x\n", bits); + return -EINVAL; + } + + kbdev->pbha_propagate_bits = bits; + return 0; +} +#endif + +int kbase_pbha_read_dtb(struct kbase_device *kbdev) +{ + const struct device_node *pbha_node; + int err; + + if (!kbasep_pbha_supported(kbdev)) + return 0; + + pbha_node = of_get_child_by_name(kbdev->dev->of_node, "pbha"); + if (!pbha_node) + return 0; + + err = kbase_pbha_read_int_id_override_property(kbdev, pbha_node); + +#if MALI_USE_CSF + if (err < 0) + return err; + + err = kbase_pbha_read_propagate_bits_property(kbdev, pbha_node); +#endif + + return err; +} diff --git a/drivers/gpu/arm/bifrost/mali_kbase_pbha_debugfs.c b/drivers/gpu/arm/bifrost/mali_kbase_pbha_debugfs.c index 4130dd609157..1cc29c700e5a 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_pbha_debugfs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_pbha_debugfs.c @@ -20,13 +20,15 @@ */ #include "mali_kbase_pbha_debugfs.h" - #include "mali_kbase_pbha.h" - #include #include #include +#if MALI_USE_CSF +#include "backend/gpu/mali_kbase_pm_internal.h" +#endif + static int int_id_overrides_show(struct seq_file *sfile, void *data) { struct kbase_device *kbdev = sfile->private; @@ -108,6 +110,90 @@ static int int_id_overrides_open(struct inode *in, struct file *file) return single_open(file, int_id_overrides_show, in->i_private); } +#if MALI_USE_CSF +/** + * propagate_bits_show - Read PBHA bits from L2_CONFIG out to debugfs. + * + * @sfile: The debugfs entry. + * @data: Data associated with the entry. + * + * Return: 0 in all cases. + */ +static int propagate_bits_show(struct seq_file *sfile, void *data) +{ + struct kbase_device *kbdev = sfile->private; + u32 l2_config_val; + + kbase_csf_scheduler_pm_active(kbdev); + kbase_pm_wait_for_l2_powered(kbdev); + l2_config_val = L2_CONFIG_PBHA_HWU_GET(kbase_reg_read(kbdev, GPU_CONTROL_REG(L2_CONFIG))); + kbase_csf_scheduler_pm_idle(kbdev); + + seq_printf(sfile, "PBHA Propagate Bits: 0x%x\n", l2_config_val); + return 0; +} + +static int propagate_bits_open(struct inode *in, struct file *file) +{ + return single_open(file, propagate_bits_show, in->i_private); +} + +/** + * propagate_bits_write - Write input value from debugfs to PBHA bits of L2_CONFIG register. + * + * @file: Pointer to file struct of debugfs node. + * @ubuf: Pointer to user buffer with value to be written. + * @count: Size of user buffer. + * @ppos: Not used. + * + * Return: Size of buffer passed in when successful, but error code E2BIG/EINVAL otherwise. + */ +static ssize_t propagate_bits_write(struct file *file, const char __user *ubuf, size_t count, + loff_t *ppos) +{ + struct seq_file *sfile = file->private_data; + struct kbase_device *kbdev = sfile->private; + /* 32 characters should be enough for the input string in any base */ + char raw_str[32]; + unsigned long propagate_bits; + + if (count >= sizeof(raw_str)) + return -E2BIG; + if (copy_from_user(raw_str, ubuf, count)) + return -EINVAL; + raw_str[count] = '\0'; + if (kstrtoul(raw_str, 0, &propagate_bits)) + return -EINVAL; + + /* Check propagate_bits input argument does not + * exceed the maximum size of the propagate_bits mask. + */ + if (propagate_bits > (L2_CONFIG_PBHA_HWU_MASK >> L2_CONFIG_PBHA_HWU_SHIFT)) + return -EINVAL; + /* Cast to u8 is safe as check is done already to ensure size is within + * correct limits. + */ + kbdev->pbha_propagate_bits = (u8)propagate_bits; + + /* GPU Reset will set new values in L2 config */ + if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_NONE)) { + kbase_reset_gpu(kbdev); + kbase_reset_gpu_wait(kbdev); + } + + return count; +} + +static const struct file_operations pbha_propagate_bits_fops = { + .owner = THIS_MODULE, + .open = propagate_bits_open, + .read = seq_read, + .write = propagate_bits_write, + .llseek = seq_lseek, + .release = single_release, +}; +#endif /* MALI_USE_CSF */ + static const struct file_operations pbha_int_id_overrides_fops = { .owner = THIS_MODULE, .open = int_id_overrides_open, @@ -132,5 +218,10 @@ void kbase_pbha_debugfs_init(struct kbase_device *kbdev) debugfs_create_file("int_id_overrides", mode, debugfs_pbha_dir, kbdev, &pbha_int_id_overrides_fops); +#if MALI_USE_CSF + if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_PBHA_HWU)) + debugfs_create_file("propagate_bits", mode, debugfs_pbha_dir, kbdev, + &pbha_propagate_bits_fops); +#endif /* MALI_USE_CSF */ } } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_platform_fake.c b/drivers/gpu/arm/bifrost/mali_kbase_platform_fake.c index 761a636b4cbf..265c676f13fa 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_platform_fake.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_platform_fake.c @@ -32,12 +32,12 @@ */ #include +#ifndef CONFIG_OF + #define PLATFORM_CONFIG_RESOURCE_COUNT 4 -#define PLATFORM_CONFIG_IRQ_RES_COUNT 3 static struct platform_device *mali_device; -#ifndef CONFIG_OF /** * kbasep_config_parse_io_resources - Convert data in struct kbase_io_resources * struct to Linux-specific resources @@ -73,14 +73,11 @@ static void kbasep_config_parse_io_resources(const struct kbase_io_resources *io linux_resources[3].end = io_resources->gpu_irq_number; linux_resources[3].flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL; } -#endif /* CONFIG_OF */ int kbase_platform_register(void) { struct kbase_platform_config *config; -#ifndef CONFIG_OF struct resource resources[PLATFORM_CONFIG_RESOURCE_COUNT]; -#endif int err; config = kbase_get_platform_config(); /* declared in midgard/mali_kbase_config.h but defined in platform folder */ @@ -93,7 +90,6 @@ int kbase_platform_register(void) if (mali_device == NULL) return -ENOMEM; -#ifndef CONFIG_OF kbasep_config_parse_io_resources(config->io_resources, resources); err = platform_device_add_resources(mali_device, resources, PLATFORM_CONFIG_RESOURCE_COUNT); if (err) { @@ -101,7 +97,6 @@ int kbase_platform_register(void) mali_device = NULL; return err; } -#endif /* CONFIG_OF */ err = platform_device_add(mali_device); if (err) { @@ -120,3 +115,5 @@ void kbase_platform_unregister(void) platform_device_unregister(mali_device); } EXPORT_SYMBOL(kbase_platform_unregister); + +#endif /* CONFIG_OF */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_pm.c b/drivers/gpu/arm/bifrost/mali_kbase_pm.c index 68c1b9bb25e8..62a132816a42 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_pm.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_pm.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 @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/gpu/arm/bifrost/mali_kbase_reset_gpu.h b/drivers/gpu/arm/bifrost/mali_kbase_reset_gpu.h index ff631e91824f..48ea9954b17c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_reset_gpu.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_reset_gpu.h @@ -236,6 +236,18 @@ int kbase_reset_gpu_silent(struct kbase_device *kbdev); */ bool kbase_reset_gpu_is_active(struct kbase_device *kbdev); +/** + * kbase_reset_gpu_not_pending - Reports if the GPU reset isn't pending + * + * @kbdev: Device pointer + * + * Note that unless appropriate locks are held when using this function, the + * state could change immediately afterwards. + * + * Return: True if the GPU reset isn't pending. + */ +bool kbase_reset_gpu_is_not_pending(struct kbase_device *kbdev); + /** * kbase_reset_gpu_wait - Wait for a GPU reset to complete * @kbdev: Device pointer diff --git a/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c b/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c index 5808a2e893cc..b0c5126afcbe 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_softjobs.c @@ -23,7 +23,7 @@ #include #include -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) #include #endif #include @@ -204,7 +204,7 @@ static int kbase_dump_cpu_gpu_time(struct kbase_jd_atom *katom) return 0; } -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) /* Called by the explicit fence mechanism when a fence wait has completed */ void kbase_soft_event_wait_callback(struct kbase_jd_atom *katom) { @@ -925,26 +925,6 @@ int kbasep_jit_alloc_validate(struct kbase_context *kctx, #if !MALI_USE_CSF -/* - * Sizes of user data to copy for each just-in-time memory interface version - * - * In interface version 2 onwards this is the same as the struct size, allowing - * copying of arrays of structures from userspace. - * - * In interface version 1 the structure size was variable, and hence arrays of - * structures cannot be supported easily, and were not a feature present in - * version 1 anyway. - */ -static const size_t jit_info_copy_size_for_jit_version[] = { - /* in jit_version 1, the structure did not have any end padding, hence - * it could be a different size on 32 and 64-bit clients. We therefore - * do not copy past the last member - */ - [1] = offsetofend(struct base_jit_alloc_info_10_2, id), - [2] = sizeof(struct base_jit_alloc_info_11_5), - [3] = sizeof(struct base_jit_alloc_info) -}; - static int kbase_jit_allocate_prepare(struct kbase_jd_atom *katom) { __user u8 *data = (__user u8 *)(uintptr_t) katom->jc; @@ -954,18 +934,11 @@ static int kbase_jit_allocate_prepare(struct kbase_jd_atom *katom) u32 count; int ret; u32 i; - size_t jit_info_user_copy_size; - - WARN_ON(kctx->jit_version >= - ARRAY_SIZE(jit_info_copy_size_for_jit_version)); - jit_info_user_copy_size = - jit_info_copy_size_for_jit_version[kctx->jit_version]; - WARN_ON(jit_info_user_copy_size > sizeof(*info)); /* For backwards compatibility, and to prevent reading more than 1 jit * info struct on jit version 1 */ - if (katom->nr_extres == 0 || kctx->jit_version == 1) + if (katom->nr_extres == 0) katom->nr_extres = 1; count = katom->nr_extres; @@ -985,8 +958,8 @@ static int kbase_jit_allocate_prepare(struct kbase_jd_atom *katom) katom->softjob_data = info; - for (i = 0; i < count; i++, info++, data += jit_info_user_copy_size) { - if (copy_from_user(info, data, jit_info_user_copy_size) != 0) { + for (i = 0; i < count; i++, info++, data += sizeof(*info)) { + if (copy_from_user(info, data, sizeof(*info)) != 0) { ret = -EINVAL; goto free_info; } @@ -994,8 +967,7 @@ static int kbase_jit_allocate_prepare(struct kbase_jd_atom *katom) * kernel struct. For jit version 1, this also clears the * padding bytes */ - memset(((u8 *)info) + jit_info_user_copy_size, 0, - sizeof(*info) - jit_info_user_copy_size); + memset(((u8 *)info) + sizeof(*info), 0, sizeof(*info) - sizeof(*info)); ret = kbasep_jit_alloc_validate(kctx, info); if (ret) @@ -1476,10 +1448,11 @@ static void kbase_ext_res_process(struct kbase_jd_atom *katom, bool map) if (!kbase_sticky_resource_acquire(katom->kctx, gpu_addr)) goto failed_loop; - } else + } else { if (!kbase_sticky_resource_release_force(katom->kctx, NULL, gpu_addr)) failed = true; + } } /* @@ -1539,7 +1512,7 @@ int kbase_process_soft_job(struct kbase_jd_atom *katom) ret = kbase_dump_cpu_gpu_time(katom); break; -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) case BASE_JD_REQ_SOFT_FENCE_TRIGGER: katom->event_code = kbase_sync_fence_out_trigger(katom, katom->event_code == BASE_JD_EVENT_DONE ? @@ -1599,7 +1572,7 @@ int kbase_process_soft_job(struct kbase_jd_atom *katom) void kbase_cancel_soft_job(struct kbase_jd_atom *katom) { switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) case BASE_JD_REQ_SOFT_FENCE_WAIT: kbase_sync_fence_in_cancel_wait(katom); break; @@ -1622,7 +1595,7 @@ int kbase_prepare_soft_job(struct kbase_jd_atom *katom) return -EINVAL; } break; -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) case BASE_JD_REQ_SOFT_FENCE_TRIGGER: { struct base_fence fence; @@ -1668,20 +1641,9 @@ int kbase_prepare_soft_job(struct kbase_jd_atom *katom) fence.basep.fd); if (ret < 0) return ret; - -#ifdef CONFIG_MALI_BIFROST_DMA_FENCE - /* - * Set KCTX_NO_IMPLICIT_FENCE in the context the first - * time a soft fence wait job is observed. This will - * prevent the implicit dma-buf fence to conflict with - * the Android native sync fences. - */ - if (!kbase_ctx_flag(katom->kctx, KCTX_NO_IMPLICIT_SYNC)) - kbase_ctx_flag_set(katom->kctx, KCTX_NO_IMPLICIT_SYNC); -#endif /* CONFIG_MALI_BIFROST_DMA_FENCE */ } break; -#endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ +#endif /* CONFIG_SYNC_FILE */ case BASE_JD_REQ_SOFT_JIT_ALLOC: return kbase_jit_allocate_prepare(katom); case BASE_JD_REQ_SOFT_JIT_FREE: @@ -1714,7 +1676,7 @@ void kbase_finish_soft_job(struct kbase_jd_atom *katom) case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: /* Nothing to do */ break; -#if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) case BASE_JD_REQ_SOFT_FENCE_TRIGGER: /* If fence has not yet been signaled, do it now */ kbase_sync_fence_out_trigger(katom, katom->event_code == @@ -1724,7 +1686,7 @@ void kbase_finish_soft_job(struct kbase_jd_atom *katom) /* Release katom's reference to fence object */ kbase_sync_fence_in_remove(katom); break; -#endif /* CONFIG_SYNC || CONFIG_SYNC_FILE */ +#endif /* CONFIG_SYNC_FILE */ case BASE_JD_REQ_SOFT_DEBUG_COPY: kbase_debug_copy_finish(katom); break; diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync.h b/drivers/gpu/arm/bifrost/mali_kbase_sync.h index fcc9b6fe0195..3d2053bee08e 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_sync.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_sync.h @@ -30,9 +30,6 @@ #include #include -#if IS_ENABLED(CONFIG_SYNC) -#include -#endif #if IS_ENABLED(CONFIG_SYNC_FILE) #include "mali_kbase_fence_defs.h" #include @@ -181,7 +178,7 @@ int kbase_sync_fence_out_info_get(struct kbase_jd_atom *katom, struct kbase_sync_fence_info *info); #endif /* !MALI_USE_CSF */ -#if defined(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) #if (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE) void kbase_sync_fence_info_get(struct fence *fence, struct kbase_sync_fence_info *info); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c b/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c deleted file mode 100644 index 8c5cb6c3838e..000000000000 --- a/drivers/gpu/arm/bifrost/mali_kbase_sync_android.c +++ /dev/null @@ -1,514 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (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 - * 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. - * - */ - -/* - * Code for supporting explicit Android fences (CONFIG_SYNC) - * Known to be good for kernels 4.5 and earlier. - * Replaced with CONFIG_SYNC_FILE for 4.9 and later kernels - * (see mali_kbase_sync_file.c) - */ - -#include -#include -#include -#include -#include -#include -#include -#include "sync.h" -#include -#include - -struct mali_sync_timeline { - struct sync_timeline timeline; - atomic_t counter; - atomic_t signaled; -}; - -struct mali_sync_pt { - struct sync_pt pt; - int order; - int result; -}; - -static struct mali_sync_timeline *to_mali_sync_timeline( - struct sync_timeline *timeline) -{ - return container_of(timeline, struct mali_sync_timeline, timeline); -} - -static struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt) -{ - return container_of(pt, struct mali_sync_pt, pt); -} - -static struct sync_pt *timeline_dup(struct sync_pt *pt) -{ - struct mali_sync_pt *mpt = to_mali_sync_pt(pt); - struct mali_sync_pt *new_mpt; - struct sync_pt *new_pt = sync_pt_create(sync_pt_parent(pt), - sizeof(struct mali_sync_pt)); - - if (!new_pt) - return NULL; - - new_mpt = to_mali_sync_pt(new_pt); - new_mpt->order = mpt->order; - new_mpt->result = mpt->result; - - return new_pt; -} - -static int timeline_has_signaled(struct sync_pt *pt) -{ - struct mali_sync_pt *mpt = to_mali_sync_pt(pt); - struct mali_sync_timeline *mtl = to_mali_sync_timeline( - sync_pt_parent(pt)); - int result = mpt->result; - - int diff = atomic_read(&mtl->signaled) - mpt->order; - - if (diff >= 0) - return (result < 0) ? result : 1; - - return 0; -} - -static int timeline_compare(struct sync_pt *a, struct sync_pt *b) -{ - struct mali_sync_pt *ma = container_of(a, struct mali_sync_pt, pt); - struct mali_sync_pt *mb = container_of(b, struct mali_sync_pt, pt); - - int diff = ma->order - mb->order; - - if (diff == 0) - return 0; - - return (diff < 0) ? -1 : 1; -} - -static void timeline_value_str(struct sync_timeline *timeline, char *str, - int size) -{ - struct mali_sync_timeline *mtl = to_mali_sync_timeline(timeline); - - snprintf(str, size, "%d", atomic_read(&mtl->signaled)); -} - -static void pt_value_str(struct sync_pt *pt, char *str, int size) -{ - struct mali_sync_pt *mpt = to_mali_sync_pt(pt); - - snprintf(str, size, "%d(%d)", mpt->order, mpt->result); -} - -static struct sync_timeline_ops mali_timeline_ops = { - .driver_name = "Mali", - .dup = timeline_dup, - .has_signaled = timeline_has_signaled, - .compare = timeline_compare, - .timeline_value_str = timeline_value_str, - .pt_value_str = pt_value_str, -}; - -/* Allocates a timeline for Mali - * - * One timeline should be allocated per API context. - */ -static struct sync_timeline *mali_sync_timeline_alloc(const char *name) -{ - struct sync_timeline *tl; - struct mali_sync_timeline *mtl; - - tl = sync_timeline_create(&mali_timeline_ops, - sizeof(struct mali_sync_timeline), name); - if (!tl) - return NULL; - - /* Set the counter in our private struct */ - mtl = to_mali_sync_timeline(tl); - atomic_set(&mtl->counter, 0); - atomic_set(&mtl->signaled, 0); - - return tl; -} - -static int kbase_stream_close(struct inode *inode, struct file *file) -{ - struct sync_timeline *tl; - - tl = (struct sync_timeline *)file->private_data; - sync_timeline_destroy(tl); - return 0; -} - -static const struct file_operations stream_fops = { - .owner = THIS_MODULE, - .release = kbase_stream_close, -}; - -int kbase_sync_fence_stream_create(const char *name, int *const out_fd) -{ - struct sync_timeline *tl; - - if (!out_fd) - return -EINVAL; - - tl = mali_sync_timeline_alloc(name); - if (!tl) - return -EINVAL; - - *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY|O_CLOEXEC); - - if (*out_fd < 0) { - sync_timeline_destroy(tl); - return -EINVAL; - } - - return 0; -} - -#if !MALI_USE_CSF -/* Allocates a sync point within the timeline. - * - * The timeline must be the one allocated by kbase_sync_timeline_alloc - * - * Sync points must be triggered in *exactly* the same order as they are - * allocated. - */ -static struct sync_pt *kbase_sync_pt_alloc(struct sync_timeline *parent) -{ - struct sync_pt *pt = sync_pt_create(parent, - sizeof(struct mali_sync_pt)); - struct mali_sync_timeline *mtl = to_mali_sync_timeline(parent); - struct mali_sync_pt *mpt; - - if (!pt) - return NULL; - - mpt = to_mali_sync_pt(pt); - mpt->order = atomic_inc_return(&mtl->counter); - mpt->result = 0; - - return pt; -} - -int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int tl_fd) -{ - struct sync_timeline *tl; - struct sync_pt *pt; - struct sync_fence *fence; - int fd; - struct file *tl_file; - - tl_file = fget(tl_fd); - if (tl_file == NULL) - return -EBADF; - - if (tl_file->f_op != &stream_fops) { - fd = -EBADF; - goto out; - } - - tl = tl_file->private_data; - - pt = kbase_sync_pt_alloc(tl); - if (!pt) { - fd = -EFAULT; - goto out; - } - - fence = sync_fence_create("mali_fence", pt); - if (!fence) { - sync_pt_free(pt); - fd = -EFAULT; - goto out; - } - - /* from here the fence owns the sync_pt */ - - /* 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); -out: - fput(tl_file); - - return fd; -} - -int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd) -{ - katom->fence = sync_fence_fdget(fd); - return katom->fence ? 0 : -ENOENT; -} -#endif /* !MALI_USE_CSF */ - -int kbase_sync_fence_validate(int fd) -{ - struct sync_fence *fence; - - fence = sync_fence_fdget(fd); - if (!fence) - return -EINVAL; - - sync_fence_put(fence); - return 0; -} - -#if !MALI_USE_CSF -/* Returns true if the specified timeline is allocated by Mali */ -static int kbase_sync_timeline_is_ours(struct sync_timeline *timeline) -{ - return timeline->ops == &mali_timeline_ops; -} - -/* Signals a particular sync point - * - * Sync points must be triggered in *exactly* the same order as they are - * allocated. - * - * If they are signaled in the wrong order then a message will be printed in - * debug builds and otherwise attempts to signal order sync_pts will be ignored. - * - * result can be negative to indicate error, any other value is interpreted as - * success. - */ -static void kbase_sync_signal_pt(struct sync_pt *pt, int result) -{ - struct mali_sync_pt *mpt = to_mali_sync_pt(pt); - struct mali_sync_timeline *mtl = to_mali_sync_timeline( - sync_pt_parent(pt)); - int signaled; - int diff; - - mpt->result = result; - - do { - signaled = atomic_read(&mtl->signaled); - - diff = signaled - mpt->order; - - if (diff > 0) { - /* The timeline is already at or ahead of this point. - * This should not happen unless userspace has been - * signaling fences out of order, so warn but don't - * violate the sync_pt API. - * The warning is only in debug builds to prevent - * a malicious user being able to spam dmesg. - */ -#ifdef CONFIG_MALI_BIFROST_DEBUG - pr_err("Fences were triggered in a different order to allocation!"); -#endif /* CONFIG_MALI_BIFROST_DEBUG */ - return; - } - } while (atomic_cmpxchg(&mtl->signaled, - signaled, mpt->order) != signaled); -} - -enum base_jd_event_code -kbase_sync_fence_out_trigger(struct kbase_jd_atom *katom, int result) -{ - struct sync_pt *pt; - struct sync_timeline *timeline; - - if (!katom->fence) - return BASE_JD_EVENT_JOB_CANCELLED; - - if (katom->fence->num_fences != 1) { - /* Not exactly one item in the list - so it didn't (directly) - * come from us - */ - return BASE_JD_EVENT_JOB_CANCELLED; - } - - pt = container_of(katom->fence->cbs[0].sync_pt, struct sync_pt, base); - timeline = sync_pt_parent(pt); - - if (!kbase_sync_timeline_is_ours(timeline)) { - /* Fence has a sync_pt which isn't ours! */ - return BASE_JD_EVENT_JOB_CANCELLED; - } - - kbase_sync_signal_pt(pt, result); - - sync_timeline_signal(timeline); - - kbase_sync_fence_out_remove(katom); - - return (result < 0) ? BASE_JD_EVENT_JOB_CANCELLED : BASE_JD_EVENT_DONE; -} - -static inline int kbase_fence_get_status(struct sync_fence *fence) -{ - if (!fence) - return -ENOENT; - - return atomic_read(&fence->status); -} - -static void kbase_fence_wait_callback(struct sync_fence *fence, - struct sync_fence_waiter *waiter) -{ - struct kbase_jd_atom *katom = container_of(waiter, - struct kbase_jd_atom, sync_waiter); - struct kbase_context *kctx = katom->kctx; - - /* Propagate the fence status to the atom. - * If negative then cancel this atom and its dependencies. - */ - if (kbase_fence_get_status(fence) < 0) - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - - /* To prevent a potential deadlock we schedule the work onto the - * job_done_wq workqueue - * - * The issue is that we may signal the timeline while holding - * kctx->jctx.lock and the callbacks are run synchronously from - * sync_timeline_signal. So we simply defer the work. - */ - - INIT_WORK(&katom->work, kbase_sync_fence_wait_worker); - queue_work(kctx->jctx.job_done_wq, &katom->work); -} - -int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom) -{ - int ret; - - sync_fence_waiter_init(&katom->sync_waiter, kbase_fence_wait_callback); - - ret = sync_fence_wait_async(katom->fence, &katom->sync_waiter); - - if (ret == 1) { - /* Already signaled */ - return 0; - } - - if (ret < 0) { - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - /* We should cause the dependent jobs in the bag to be failed, - * to do this we schedule the work queue to complete this job - */ - INIT_WORK(&katom->work, kbase_sync_fence_wait_worker); - queue_work(katom->kctx->jctx.job_done_wq, &katom->work); - } - - return 1; -} - -void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom) -{ - if (sync_fence_cancel_async(katom->fence, &katom->sync_waiter) != 0) { - /* The wait wasn't cancelled - leave the cleanup for - * kbase_fence_wait_callback - */ - return; - } - - /* Wait was cancelled - zap the atoms */ - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - - kbasep_remove_waiting_soft_job(katom); - kbase_finish_soft_job(katom); - - if (kbase_jd_done_nolock(katom, true)) - kbase_js_sched_all(katom->kctx->kbdev); -} - -void kbase_sync_fence_out_remove(struct kbase_jd_atom *katom) -{ - if (katom->fence) { - sync_fence_put(katom->fence); - katom->fence = NULL; - } -} - -void kbase_sync_fence_in_remove(struct kbase_jd_atom *katom) -{ - if (katom->fence) { - sync_fence_put(katom->fence); - katom->fence = NULL; - } -} - -int kbase_sync_fence_in_info_get(struct kbase_jd_atom *katom, - struct kbase_sync_fence_info *info) -{ - u32 string_len; - - if (!katom->fence) - return -ENOENT; - - info->fence = katom->fence; - info->status = kbase_fence_get_status(katom->fence); - - string_len = strscpy(info->name, katom->fence->name, sizeof(info->name)); - string_len += sizeof(char); - /* Make sure that the source string fit into the buffer. */ - KBASE_DEBUG_ASSERT(string_len <= sizeof(info->name)); - CSTD_UNUSED(string_len); - - return 0; -} - -int kbase_sync_fence_out_info_get(struct kbase_jd_atom *katom, - struct kbase_sync_fence_info *info) -{ - u32 string_len; - - if (!katom->fence) - return -ENOENT; - - info->fence = katom->fence; - info->status = kbase_fence_get_status(katom->fence); - - string_len = strscpy(info->name, katom->fence->name, sizeof(info->name)); - string_len += sizeof(char); - /* Make sure that the source string fit into the buffer. */ - KBASE_DEBUG_ASSERT(string_len <= sizeof(info->name)); - CSTD_UNUSED(string_len); - - return 0; -} - -#ifdef CONFIG_MALI_BIFROST_FENCE_DEBUG -void kbase_sync_fence_in_dump(struct kbase_jd_atom *katom) -{ - /* Dump out the full state of all the Android sync fences. - * The function sync_dump() isn't exported to modules, so force - * sync_fence_wait() to time out to trigger sync_dump(). - */ - if (katom->fence) - sync_fence_wait(katom->fence, 1); -} -#endif -#endif /* !MALI_USE_CSF */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c b/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c index e08a87210fbc..9360324cfee6 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_sync_file.c @@ -21,9 +21,6 @@ /* * Code for supporting explicit Linux fences (CONFIG_SYNC_FILE) - * Introduced in kernel 4.9. - * Android explicit fences (CONFIG_SYNC) can be used for older kernels - * (see mali_kbase_sync_android.c) */ #include @@ -112,10 +109,13 @@ int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd) struct dma_fence *fence = sync_file_get_fence(fd); #endif + lockdep_assert_held(&katom->kctx->jctx.lock); + if (!fence) return -ENOENT; kbase_fence_fence_in_set(katom, fence); + katom->dma_fence.fence_cb_added = false; return 0; } @@ -167,36 +167,31 @@ static void kbase_fence_wait_callback(struct dma_fence *fence, struct dma_fence_cb *cb) #endif { - struct kbase_fence_cb *kcb = container_of(cb, - struct kbase_fence_cb, - fence_cb); - struct kbase_jd_atom *katom = kcb->katom; + struct kbase_jd_atom *katom = container_of(cb, struct kbase_jd_atom, + dma_fence.fence_cb); struct kbase_context *kctx = katom->kctx; /* Cancel atom if fence is erroneous */ + if (dma_fence_is_signaled(katom->dma_fence.fence_in) && #if (KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE || \ (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE && \ KERNEL_VERSION(4, 9, 68) <= LINUX_VERSION_CODE)) - if (dma_fence_is_signaled(kcb->fence) && kcb->fence->error < 0) + katom->dma_fence.fence_in->error < 0) #else - if (dma_fence_is_signaled(kcb->fence) && kcb->fence->status < 0) + katom->dma_fence.fence_in->status < 0) #endif katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - if (kbase_fence_dep_count_dec_and_test(katom)) { - /* We take responsibility of handling this */ - kbase_fence_dep_count_set(katom, -1); - /* To prevent a potential deadlock we schedule the work onto the - * job_done_wq workqueue - * - * The issue is that we may signal the timeline while holding - * kctx->jctx.lock and the callbacks are run synchronously from - * sync_timeline_signal. So we simply defer the work. - */ - INIT_WORK(&katom->work, kbase_sync_fence_wait_worker); - queue_work(kctx->jctx.job_done_wq, &katom->work); - } + /* To prevent a potential deadlock we schedule the work onto the + * job_done_wq workqueue + * + * The issue is that we may signal the timeline while holding + * kctx->jctx.lock and the callbacks are run synchronously from + * sync_timeline_signal. So we simply defer the work. + */ + INIT_WORK(&katom->work, kbase_sync_fence_wait_worker); + queue_work(kctx->jctx.job_done_wq, &katom->work); } int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom) @@ -208,53 +203,77 @@ int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom) struct dma_fence *fence; #endif - fence = kbase_fence_in_get(katom); + lockdep_assert_held(&katom->kctx->jctx.lock); + + fence = katom->dma_fence.fence_in; if (!fence) return 0; /* no input fence to wait for, good to go! */ - kbase_fence_dep_count_set(katom, 1); + err = dma_fence_add_callback(fence, &katom->dma_fence.fence_cb, + kbase_fence_wait_callback); + if (err == -ENOENT) { + int fence_status = dma_fence_get_status(fence); - err = kbase_fence_add_callback(katom, fence, kbase_fence_wait_callback); - - kbase_fence_put(fence); - - if (likely(!err)) { - /* Test if the callbacks are already triggered */ - if (kbase_fence_dep_count_dec_and_test(katom)) { - kbase_fence_free_callbacks(katom); - kbase_fence_dep_count_set(katom, -1); - return 0; /* Already signaled, good to go right now */ + if (fence_status == 1) { + /* Fence is already signaled with no error. The completion + * for FENCE_WAIT softjob can be done right away. + */ + return 0; } - /* Callback installed, so we just need to wait for it... */ - } else { - /* Failure */ - kbase_fence_free_callbacks(katom); - kbase_fence_dep_count_set(katom, -1); + /* Fence shouldn't be in not signaled state */ + if (!fence_status) { + struct kbase_sync_fence_info info; - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + kbase_sync_fence_in_info_get(katom, &info); - /* We should cause the dependent jobs in the bag to be failed, - * to do this we schedule the work queue to complete this job + dev_warn(katom->kctx->kbdev->dev, + "Unexpected status for fence %s of ctx:%d_%d atom:%d", + info.name, katom->kctx->tgid, katom->kctx->id, + kbase_jd_atom_id(katom->kctx, katom)); + } + + /* If fence is signaled with an error, then the FENCE_WAIT softjob is + * considered to be failed. */ - INIT_WORK(&katom->work, kbase_sync_fence_wait_worker); - queue_work(katom->kctx->jctx.job_done_wq, &katom->work); } - return 1; /* completion to be done later by callback/worker */ + if (unlikely(err)) { + /* We should cause the dependent jobs in the bag to be failed. */ + katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; + + /* The completion for FENCE_WAIT softjob can be done right away. */ + return 0; + } + + /* Callback was successfully installed */ + katom->dma_fence.fence_cb_added = true; + + /* Completion to be done later by callback/worker */ + return 1; } void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom) { - if (!kbase_fence_free_callbacks(katom)) { - /* The wait wasn't cancelled - - * leave the cleanup for kbase_fence_wait_callback - */ - return; - } + lockdep_assert_held(&katom->kctx->jctx.lock); - /* Take responsibility of completion */ - kbase_fence_dep_count_set(katom, -1); + if (katom->dma_fence.fence_cb_added) { + if (!dma_fence_remove_callback(katom->dma_fence.fence_in, + &katom->dma_fence.fence_cb)) { + /* The callback is already removed so leave the cleanup + * for kbase_fence_wait_callback. + */ + return; + } + } else { + struct kbase_sync_fence_info info; + + kbase_sync_fence_in_info_get(katom, &info); + dev_warn(katom->kctx->kbdev->dev, + "Callback was not added earlier for fence %s of ctx:%d_%d atom:%d", + info.name, katom->kctx->tgid, katom->kctx->id, + kbase_jd_atom_id(katom->kctx, katom)); + } /* Wait was cancelled - zap the atoms */ katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; @@ -273,8 +292,29 @@ void kbase_sync_fence_out_remove(struct kbase_jd_atom *katom) void kbase_sync_fence_in_remove(struct kbase_jd_atom *katom) { - kbase_fence_free_callbacks(katom); + lockdep_assert_held(&katom->kctx->jctx.lock); + + if (katom->dma_fence.fence_cb_added) { + bool removed = dma_fence_remove_callback(katom->dma_fence.fence_in, + &katom->dma_fence.fence_cb); + + /* Here it is expected that the callback should have already been removed + * previously either by kbase_sync_fence_in_cancel_wait() or when the fence + * was signaled and kbase_sync_fence_wait_worker() was called. + */ + if (removed) { + struct kbase_sync_fence_info info; + + kbase_sync_fence_in_info_get(katom, &info); + dev_warn(katom->kctx->kbdev->dev, + "Callback was not removed earlier for fence %s of ctx:%d_%d atom:%d", + info.name, katom->kctx->tgid, katom->kctx->id, + kbase_jd_atom_id(katom->kctx, katom)); + } + } + kbase_fence_in_remove(katom); + katom->dma_fence.fence_cb_added = false; } #endif /* !MALI_USE_CSF */ @@ -288,7 +328,7 @@ void kbase_sync_fence_info_get(struct dma_fence *fence, { info->fence = fence; - /* translate into CONFIG_SYNC status: + /* Translate into the following status, with support for error handling: * < 0 : error * 0 : active * 1 : signaled diff --git a/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c b/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c index abcf53041069..853c89796d44 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_vinstr.c @@ -20,11 +20,11 @@ */ #include "mali_kbase_vinstr.h" -#include "mali_kbase_hwcnt_virtualizer.h" -#include "mali_kbase_hwcnt_types.h" +#include "hwcnt/mali_kbase_hwcnt_virtualizer.h" +#include "hwcnt/mali_kbase_hwcnt_types.h" #include -#include "mali_kbase_hwcnt_gpu.h" -#include "mali_kbase_hwcnt_gpu_narrow.h" +#include "hwcnt/mali_kbase_hwcnt_gpu.h" +#include "hwcnt/mali_kbase_hwcnt_gpu_narrow.h" #include #include "mali_malisw.h" #include "mali_kbase_debug.h" @@ -1034,24 +1034,25 @@ static long kbasep_vinstr_hwcnt_reader_ioctl( * @filp: Non-NULL pointer to file structure. * @wait: Non-NULL pointer to poll table. * - * Return: POLLIN if data can be read without blocking, 0 if data can not be - * read without blocking, else error code. + * Return: EPOLLIN | EPOLLRDNORM if data can be read without blocking, 0 if + * data can not be read without blocking, else EPOLLHUP | EPOLLERR. */ static __poll_t kbasep_vinstr_hwcnt_reader_poll(struct file *filp, poll_table *wait) { struct kbase_vinstr_client *cli; if (!filp || !wait) - return (__poll_t)-EINVAL; + return EPOLLHUP | EPOLLERR; cli = filp->private_data; if (!cli) - return (__poll_t)-EINVAL; + return EPOLLHUP | EPOLLERR; poll_wait(filp, &cli->waitq, wait); if (kbasep_vinstr_hwcnt_reader_buffer_ready(cli)) - return POLLIN; - return 0; + return EPOLLIN | EPOLLRDNORM; + + return (__poll_t)0; } /** diff --git a/drivers/gpu/arm/bifrost/mali_malisw.h b/drivers/gpu/arm/bifrost/mali_malisw.h index d25c29fda63b..d9db189e8684 100644 --- a/drivers/gpu/arm/bifrost/mali_malisw.h +++ b/drivers/gpu/arm/bifrost/mali_malisw.h @@ -97,16 +97,12 @@ */ #define CSTD_STR2(x) CSTD_STR1(x) -/* LINUX_VERSION_CODE < 5.4 */ -#if (KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE) -#if defined(GCC_VERSION) && GCC_VERSION >= 70000 + #ifndef fallthrough + #define fallthrough __fallthrough + #endif /* fallthrough */ + #ifndef __fallthrough #define __fallthrough __attribute__((fallthrough)) #endif /* __fallthrough */ -#define fallthrough __fallthrough -#else -#define fallthrough CSTD_NOP(...) /* fallthrough */ -#endif /* GCC_VERSION >= 70000 */ -#endif /* KERNEL_VERSION(5, 4, 0) */ #endif /* _MALISW_H_ */ 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 04f5cdf42b84..db2086079c14 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 @@ -122,6 +122,8 @@ void kbase_mmu_report_mcu_as_fault_and_reset(struct kbase_device *kbdev, access_type, kbase_gpu_access_type_name(fault->status), source_id); + kbase_debug_csf_fault_notify(kbdev, NULL, DF_GPU_PAGE_FAULT); + /* Report MMU fault for all address spaces (except MCU_AS_NR) */ for (as_no = 1; as_no < kbdev->nr_hw_address_spaces; as_no++) submit_work_pagefault(kbdev, as_no, fault); @@ -188,6 +190,7 @@ void kbase_gpu_report_bus_fault_and_kill(struct kbase_context *kctx, kbase_reg_write(kbdev, GPU_CONTROL_REG(GPU_COMMAND), GPU_COMMAND_CLEAR_FAULT); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + } /* @@ -249,6 +252,7 @@ void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx, mutex_unlock(&kbdev->mmu_hw_mutex); /* AS transaction end */ + kbase_debug_csf_fault_notify(kbdev, kctx, DF_GPU_PAGE_FAULT); /* Switching to UNMAPPED mode above would have enabled the firmware to * recover from the fault (if the memory access was made by firmware) * and it can then respond to CSG termination requests to be sent now. @@ -262,6 +266,7 @@ void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx, KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED); kbase_mmu_hw_enable_fault(kbdev, as, KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED); + } /** 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 3130b332dec2..22786f0748ce 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 @@ -94,6 +94,7 @@ void kbase_gpu_report_bus_fault_and_kill(struct kbase_context *kctx, KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED); kbase_mmu_hw_enable_fault(kbdev, as, KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED); + } /* diff --git a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.c b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.c index fc7c8923ab07..8f261d439909 100644 --- a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.c +++ b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.c @@ -110,7 +110,8 @@ static void mmu_hw_operation_end(struct kbase_device *kbdev) /** * mmu_flush_cache_on_gpu_ctrl() - Check if cache flush needs to be done - * through GPU_CONTROL interface + * through GPU_CONTROL interface. + * * @kbdev: kbase device to check GPU model ID on. * * This function returns whether a cache flush for page table update should @@ -137,6 +138,42 @@ static bool mmu_flush_cache_on_gpu_ctrl(struct kbase_device *kbdev) * * Issue a cache flush physical range command. */ +#if MALI_USE_CSF +static void mmu_flush_pa_range(struct kbase_device *kbdev, phys_addr_t phys, size_t nr_bytes, + enum kbase_mmu_op_type op) +{ + u32 flush_op; + int ret; + + if (WARN_ON(kbdev == NULL)) + return; + + lockdep_assert_held(&kbdev->hwaccess_lock); + + /* Translate operation to command */ + if (op == KBASE_MMU_OP_FLUSH_PT) { + flush_op = GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_L2; + } else if (op == KBASE_MMU_OP_FLUSH_MEM) { + flush_op = GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_L2_LSC; + } else { + dev_warn(kbdev->dev, "Invalid flush request (op = %d)\n", op); + return; + } + + ret = kbase_gpu_cache_flush_pa_range_and_busy_wait(kbdev, phys, nr_bytes, flush_op); + + if (ret) { + /* Flush failed to complete, assume the GPU has hung and + * perform a reset to recover + */ + dev_err(kbdev->dev, + "Flush for physical address range 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); + } +} +#endif /** * mmu_invalidate() - Perform an invalidate operation on MMU caches. @@ -177,39 +214,15 @@ static void mmu_invalidate(struct kbase_device *kbdev, struct kbase_context *kct 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; + int err = 0; unsigned long flags; - 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); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - mmu_hw_operation_begin(kbdev); - err = kbase_mmu_hw_do_flush(kbdev, as, op_param); - mmu_hw_operation_end(kbdev); + if (kbdev->pm.backend.gpu_powered) + err = kbase_mmu_hw_do_flush_locked(kbdev, as, op_param); if (err) { /* Flush failed to complete, assume the GPU has hung and @@ -222,10 +235,9 @@ static void mmu_flush_invalidate_as(struct kbase_device *kbdev, struct kbase_as kbase_reset_gpu(kbdev); } + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); mutex_unlock(&kbdev->mmu_hw_mutex); /* AS transaction end */ - - kbase_pm_context_idle(kbdev); } /** @@ -246,9 +258,6 @@ static void mmu_flush_invalidate_as(struct kbase_device *kbdev, struct kbase_as * 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 mmu_flush_invalidate(struct kbase_device *kbdev, struct kbase_context *kctx, int as_nr, const struct kbase_mmu_hw_op_param *op_param) @@ -327,6 +336,31 @@ static void mmu_flush_invalidate_on_gpu_ctrl(struct kbase_device *kbdev, struct mutex_unlock(&kbdev->mmu_hw_mutex); } +static void kbase_mmu_sync_pgd_gpu(struct kbase_device *kbdev, struct kbase_context *kctx, + phys_addr_t phys, size_t size, + enum kbase_mmu_op_type flush_op) +{ +#if MALI_USE_CSF + unsigned long irq_flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); + if (mmu_flush_cache_on_gpu_ctrl(kbdev) && (flush_op != KBASE_MMU_OP_NONE) && + kbdev->pm.backend.gpu_powered && (!kctx || kctx->as_nr >= 0)) + mmu_flush_pa_range(kbdev, phys, size, KBASE_MMU_OP_FLUSH_PT); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); +#endif +} + +static void kbase_mmu_sync_pgd_cpu(struct kbase_device *kbdev, dma_addr_t handle, size_t size) +{ + /* In non-coherent system, ensure the GPU can read + * the pages from memory + */ + if (kbdev->system_coherency == COHERENCY_NONE) + dma_sync_single_for_device(kbdev->dev, handle, size, + DMA_TO_DEVICE); +} + /** * kbase_mmu_sync_pgd() - sync page directory to memory when needed. * @kbdev: Device pointer. @@ -350,13 +384,9 @@ static void kbase_mmu_sync_pgd(struct kbase_device *kbdev, struct kbase_context 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 - */ - if (kbdev->system_coherency == COHERENCY_NONE) - dma_sync_single_for_device(kbdev->dev, handle, size, - DMA_TO_DEVICE); + kbase_mmu_sync_pgd_cpu(kbdev, handle, size); + kbase_mmu_sync_pgd_gpu(kbdev, kctx, phys, size, flush_op); } /* @@ -383,22 +413,75 @@ static int kbase_mmu_update_pages_no_flush(struct kbase_context *kctx, u64 vpfn, * @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. + * @free_pgds_list: Linked list of the page directory pages to free. */ 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, - enum kbase_mmu_op_type flush_op, u64 *dirty_pgds); + enum kbase_mmu_op_type flush_op, u64 *dirty_pgds, + struct list_head *free_pgds_list); /** * kbase_mmu_free_pgd() - Free memory of the page directory * * @kbdev: Device pointer. * @mmut: GPU MMU page table. * @pgd: Physical address of page directory to be freed. - * @dirty: Flag to indicate whether the page may be dirty in the cache. + * + * This function is supposed to be called with mmu_lock held and after + * ensuring that GPU won't be able to access the page. */ -static void kbase_mmu_free_pgd(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, phys_addr_t pgd, - bool dirty); +static void kbase_mmu_free_pgd(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, + phys_addr_t pgd) +{ + struct page *p; + + lockdep_assert_held(&mmut->mmu_lock); + + p = pfn_to_page(PFN_DOWN(pgd)); + + kbase_mem_pool_free(&kbdev->mem_pools.small[mmut->group_id], p, true); + + atomic_sub(1, &kbdev->memdev.used_pages); + + /* If MMU tables belong to a context then pages will have been accounted + * against it, so we must decrement the usage counts here. + */ + if (mmut->kctx) { + kbase_process_page_usage_dec(mmut->kctx, 1); + atomic_sub(1, &mmut->kctx->used_pages); + } + + kbase_trace_gpu_mem_usage_dec(kbdev, mmut->kctx, 1); +} + +/** + * kbase_mmu_free_pgds_list() - Free the PGD pages present in the list + * + * @kbdev: Device pointer. + * @mmut: GPU MMU page table. + * @free_pgds_list: Linked list of the page directory pages to free. + * + * This function will call kbase_mmu_free_pgd() on each page directory page + * present in the @free_pgds_list. + * + * The function is supposed to be called after the GPU cache and MMU TLB has + * been invalidated post the teardown loop. + */ +static void kbase_mmu_free_pgds_list(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, + struct list_head *free_pgds_list) +{ + struct page *page, *next_page; + + mutex_lock(&mmut->mmu_lock); + + list_for_each_entry_safe(page, next_page, free_pgds_list, lru) { + list_del_init(&page->lru); + kbase_mmu_free_pgd(kbdev, mmut, page_to_phys(page)); + } + + mutex_unlock(&mmut->mmu_lock); +} + /** * reg_grow_calc_extra_pages() - Calculate the number of backed pages to add to * a region on a GPU page fault @@ -484,8 +567,6 @@ static void kbase_gpu_mmu_handle_write_faulting_as(struct kbase_device *kbdev, u64 start_pfn, size_t nr, u32 kctx_id, u64 dirty_pgds) { - int err; - /* Calls to this function are inherently synchronous, with respect to * MMU operations. */ @@ -509,12 +590,11 @@ static void kbase_gpu_mmu_handle_write_faulting_as(struct kbase_device *kbdev, spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); 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); + 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); - err = kbase_mmu_hw_do_flush(kbdev, faulting_as, &op_param); + kbase_mmu_hw_do_flush(kbdev, faulting_as, &op_param); mmu_hw_operation_end(kbdev); } @@ -552,7 +632,6 @@ static void kbase_gpu_mmu_handle_write_fault(struct kbase_context *kctx, struct tagged_addr *fault_phys_addr; struct kbase_fault *fault; u64 fault_pfn, pfn_offset; - int ret; int as_no; u64 dirty_pgds = 0; @@ -613,8 +692,8 @@ 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, &dirty_pgds); + 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, dirty_pgds); @@ -648,31 +727,68 @@ static void kbase_gpu_mmu_handle_permission_fault(struct kbase_context *kctx, } #endif -#define MAX_POOL_LEVEL 2 +/** + * estimate_pool_space_required - Determine how much a pool should be grown by to support a future + * allocation + * @pool: The memory pool to check, including its linked pools + * @pages_required: Number of 4KiB pages require for the pool to support a future allocation + * + * The value returned is accounting for the size of @pool and the size of each memory pool linked to + * @pool. Hence, the caller should use @pool and (if not already satisfied) all its linked pools to + * allocate from. + * + * Note: this is only an estimate, because even during the calculation the memory pool(s) involved + * can be updated to be larger or smaller. Hence, the result is only a guide as to whether an + * allocation could succeed, or an estimate of the correct amount to grow the pool by. The caller + * should keep attempting an allocation and then re-growing with a new value queried form this + * function until the allocation succeeds. + * + * Return: an estimate of the amount of extra 4KiB pages in @pool that are required to satisfy an + * allocation, or 0 if @pool (including its linked pools) is likely to already satisfy the + * allocation. + */ +static size_t estimate_pool_space_required(struct kbase_mem_pool *pool, const size_t pages_required) +{ + size_t pages_still_required; + + for (pages_still_required = pages_required; pool != NULL && pages_still_required; + pool = pool->next_pool) { + size_t pool_size_4k; + + kbase_mem_pool_lock(pool); + + pool_size_4k = kbase_mem_pool_size(pool) << pool->order; + if (pool_size_4k >= pages_still_required) + pages_still_required = 0; + else + pages_still_required -= pool_size_4k; + + kbase_mem_pool_unlock(pool); + } + return pages_still_required; +} /** * page_fault_try_alloc - Try to allocate memory from a context pool * @kctx: Context pointer * @region: Region to grow - * @new_pages: Number of 4 kB pages to allocate - * @pages_to_grow: Pointer to variable to store number of outstanding pages on - * failure. This can be either 4 kB or 2 MB pages, depending on - * the number of pages requested. - * @grow_2mb_pool: Pointer to variable to store which pool needs to grow - true - * for 2 MB, false for 4 kB. + * @new_pages: Number of 4 KiB pages to allocate + * @pages_to_grow: Pointer to variable to store number of outstanding pages on failure. This can be + * either 4 KiB or 2 MiB pages, depending on the number of pages requested. + * @grow_2mb_pool: Pointer to variable to store which pool needs to grow - true for 2 MiB, false for + * 4 KiB. * @prealloc_sas: Pointer to kbase_sub_alloc structures * - * This function will try to allocate as many pages as possible from the context - * pool, then if required will try to allocate the remaining pages from the - * device pool. + * This function will try to allocate as many pages as possible from the context pool, then if + * required will try to allocate the remaining pages from the device pool. * - * This function will not allocate any new memory beyond that is already - * present in the context or device pools. This is because it is intended to be - * called with the vm_lock held, which could cause recursive locking if the - * allocation caused the out-of-memory killer to run. + * This function will not allocate any new memory beyond that is already present in the context or + * device pools. This is because it is intended to be called whilst the thread has acquired the + * region list lock with kbase_gpu_vm_lock(), and a large enough memory allocation whilst that is + * held could invoke the OoM killer and cause an effective deadlock with kbase_cpu_vm_close(). * - * If 2 MB pages are enabled and new_pages is >= 2 MB then pages_to_grow will be - * a count of 2 MB pages, otherwise it will be a count of 4 kB pages. + * If 2 MiB pages are enabled and new_pages is >= 2 MiB then pages_to_grow will be a count of 2 MiB + * pages, otherwise it will be a count of 4 KiB pages. * * Return: true if successful, false on failure */ @@ -681,13 +797,15 @@ static bool page_fault_try_alloc(struct kbase_context *kctx, int *pages_to_grow, bool *grow_2mb_pool, struct kbase_sub_alloc **prealloc_sas) { - struct tagged_addr *gpu_pages[MAX_POOL_LEVEL] = {NULL}; - struct tagged_addr *cpu_pages[MAX_POOL_LEVEL] = {NULL}; - size_t pages_alloced[MAX_POOL_LEVEL] = {0}; + size_t total_gpu_pages_alloced = 0; + size_t total_cpu_pages_alloced = 0; struct kbase_mem_pool *pool, *root_pool; - int pool_level = 0; bool alloc_failed = false; size_t pages_still_required; + size_t total_mempools_free_4k = 0; + + lockdep_assert_held(&kctx->reg_lock); + lockdep_assert_held(&kctx->mem_partials_lock); if (WARN_ON(region->gpu_alloc->group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS)) { @@ -711,27 +829,10 @@ static bool page_fault_try_alloc(struct kbase_context *kctx, if (region->gpu_alloc != region->cpu_alloc) new_pages *= 2; - pages_still_required = new_pages; - /* Determine how many pages are in the pools before trying to allocate. * Don't attempt to allocate & free if the allocation can't succeed. */ - for (pool = root_pool; pool != NULL; pool = pool->next_pool) { - size_t pool_size_4k; - - kbase_mem_pool_lock(pool); - - pool_size_4k = kbase_mem_pool_size(pool) << pool->order; - if (pool_size_4k >= pages_still_required) - pages_still_required = 0; - else - pages_still_required -= pool_size_4k; - - kbase_mem_pool_unlock(pool); - - if (!pages_still_required) - break; - } + pages_still_required = estimate_pool_space_required(root_pool, new_pages); if (pages_still_required) { /* Insufficient pages in pools. Don't try to allocate - just @@ -742,11 +843,11 @@ static bool page_fault_try_alloc(struct kbase_context *kctx, return false; } - /* Since we've dropped the pool locks, the amount of memory in the pools - * may change between the above check and the actual allocation. + /* Since we're not holding any of the mempool locks, the amount of memory in the pools may + * change between the above estimate and the actual allocation. */ - pool = root_pool; - for (pool_level = 0; pool_level < MAX_POOL_LEVEL; pool_level++) { + pages_still_required = new_pages; + for (pool = root_pool; pool != NULL && pages_still_required; pool = pool->next_pool) { size_t pool_size_4k; size_t pages_to_alloc_4k; size_t pages_to_alloc_4k_per_alloc; @@ -755,93 +856,91 @@ static bool page_fault_try_alloc(struct kbase_context *kctx, /* Allocate as much as possible from this pool*/ pool_size_4k = kbase_mem_pool_size(pool) << pool->order; - pages_to_alloc_4k = MIN(new_pages, pool_size_4k); + total_mempools_free_4k += pool_size_4k; + pages_to_alloc_4k = MIN(pages_still_required, pool_size_4k); if (region->gpu_alloc == region->cpu_alloc) pages_to_alloc_4k_per_alloc = pages_to_alloc_4k; else pages_to_alloc_4k_per_alloc = pages_to_alloc_4k >> 1; - pages_alloced[pool_level] = pages_to_alloc_4k; if (pages_to_alloc_4k) { - gpu_pages[pool_level] = - kbase_alloc_phy_pages_helper_locked( - region->gpu_alloc, pool, - pages_to_alloc_4k_per_alloc, - &prealloc_sas[0]); + struct tagged_addr *gpu_pages = + kbase_alloc_phy_pages_helper_locked(region->gpu_alloc, pool, + pages_to_alloc_4k_per_alloc, + &prealloc_sas[0]); - if (!gpu_pages[pool_level]) { + if (!gpu_pages) alloc_failed = true; - } else if (region->gpu_alloc != region->cpu_alloc) { - cpu_pages[pool_level] = - kbase_alloc_phy_pages_helper_locked( - region->cpu_alloc, pool, - pages_to_alloc_4k_per_alloc, - &prealloc_sas[1]); + else + total_gpu_pages_alloced += pages_to_alloc_4k_per_alloc; - if (!cpu_pages[pool_level]) + if (!alloc_failed && region->gpu_alloc != region->cpu_alloc) { + struct tagged_addr *cpu_pages = kbase_alloc_phy_pages_helper_locked( + region->cpu_alloc, pool, pages_to_alloc_4k_per_alloc, + &prealloc_sas[1]); + + if (!cpu_pages) alloc_failed = true; + else + total_cpu_pages_alloced += pages_to_alloc_4k_per_alloc; } } kbase_mem_pool_unlock(pool); if (alloc_failed) { - WARN_ON(!new_pages); - WARN_ON(pages_to_alloc_4k >= new_pages); - WARN_ON(pages_to_alloc_4k_per_alloc >= new_pages); + WARN_ON(!pages_still_required); + WARN_ON(pages_to_alloc_4k >= pages_still_required); + WARN_ON(pages_to_alloc_4k_per_alloc >= pages_still_required); break; } - new_pages -= pages_to_alloc_4k; - - if (!new_pages) - break; - - pool = pool->next_pool; - if (!pool) - break; + pages_still_required -= pages_to_alloc_4k; } - if (new_pages) { - /* Allocation was unsuccessful */ - int max_pool_level = pool_level; - - pool = root_pool; - - /* Free memory allocated so far */ - for (pool_level = 0; pool_level <= max_pool_level; - pool_level++) { - kbase_mem_pool_lock(pool); - - if (region->gpu_alloc != region->cpu_alloc) { - if (pages_alloced[pool_level] && - cpu_pages[pool_level]) - kbase_free_phy_pages_helper_locked( - region->cpu_alloc, - pool, cpu_pages[pool_level], - pages_alloced[pool_level]); - } - - if (pages_alloced[pool_level] && gpu_pages[pool_level]) - kbase_free_phy_pages_helper_locked( - region->gpu_alloc, - pool, gpu_pages[pool_level], - pages_alloced[pool_level]); - - kbase_mem_pool_unlock(pool); - - pool = pool->next_pool; - } - - /* - * If the allocation failed despite there being enough memory in - * the pool, then just fail. Otherwise, try to grow the memory - * pool. + if (pages_still_required) { + /* Allocation was unsuccessful. We have dropped the mem_pool lock after allocation, + * so must in any case use kbase_free_phy_pages_helper() rather than + * kbase_free_phy_pages_helper_locked() */ - if (alloc_failed) + if (total_gpu_pages_alloced > 0) + kbase_free_phy_pages_helper(region->gpu_alloc, total_gpu_pages_alloced); + if (region->gpu_alloc != region->cpu_alloc && total_cpu_pages_alloced > 0) + kbase_free_phy_pages_helper(region->cpu_alloc, total_cpu_pages_alloced); + + if (alloc_failed) { + /* Note that in allocating from the above memory pools, we always ensure + * never to request more than is available in each pool with the pool's + * lock held. Hence failing to allocate in such situations would be unusual + * and we should cancel the growth instead (as re-growing the memory pool + * might not fix the situation) + */ + dev_warn( + kctx->kbdev->dev, + "Page allocation failure of %zu pages: managed %zu pages, mempool (inc linked pools) had %zu pages available\n", + new_pages, total_gpu_pages_alloced + total_cpu_pages_alloced, + total_mempools_free_4k); *pages_to_grow = 0; - else - *pages_to_grow = new_pages; + } else { + /* Tell the caller to try to grow the memory pool + * + * Freeing pages above may have spilled or returned them to the OS, so we + * have to take into account how many are still in the pool before giving a + * new estimate for growth required of the pool. We can just re-estimate a + * new value. + */ + pages_still_required = estimate_pool_space_required(root_pool, new_pages); + if (pages_still_required) { + *pages_to_grow = pages_still_required; + } else { + /* It's possible another thread could've grown the pool to be just + * big enough after we rolled back the allocation. Request at least + * one more page to ensure the caller doesn't fail the growth by + * conflating it with the alloc_failed case above + */ + *pages_to_grow = 1u; + } + } return false; } @@ -975,20 +1074,24 @@ void kbase_mmu_page_fault_worker(struct work_struct *data) goto fault_done; } +page_fault_retry: #ifdef CONFIG_MALI_2MB_ALLOC - /* Preallocate memory for the sub-allocation structs if necessary */ + /* Preallocate (or re-allocate) memory for the sub-allocation structs if necessary */ for (i = 0; i != ARRAY_SIZE(prealloc_sas); ++i) { - prealloc_sas[i] = kmalloc(sizeof(*prealloc_sas[i]), GFP_KERNEL); if (!prealloc_sas[i]) { - kbase_mmu_report_fault_and_kill(kctx, faulting_as, + prealloc_sas[i] = kmalloc(sizeof(*prealloc_sas[i]), GFP_KERNEL); + + if (!prealloc_sas[i]) { + kbase_mmu_report_fault_and_kill( + kctx, faulting_as, "Failed pre-allocating memory for sub-allocations' metadata", fault); - goto fault_done; + goto fault_done; + } } } #endif /* CONFIG_MALI_2MB_ALLOC */ -page_fault_retry: /* so we have a translation fault, * let's see if it is for growable memory */ @@ -1372,13 +1475,12 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev, struct kbase_mmu_table *mmut) { 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) - return 0; + return KBASE_MMU_INVALID_PGD_ADDRESS; page = kmap(p); if (page == NULL) @@ -1406,13 +1508,12 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev, kbase_trace_gpu_mem_usage_inc(kbdev, mmut->kctx, 1); - for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) - kbdev->mmu_mode->entry_invalidate(&page[i]); + kbdev->mmu_mode->entries_invalidate(page, KBASE_MMU_PAGE_ENTRIES); - /* 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. + /* As 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); + kbase_mmu_sync_pgd_cpu(kbdev, kbase_dma_addr(p), PAGE_SIZE); kunmap(p); return pgd; @@ -1420,7 +1521,7 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev, alloc_free: kbase_mem_pool_free(&kbdev->mem_pools.small[mmut->group_id], p, false); - return 0; + return KBASE_MMU_INVALID_PGD_ADDRESS; } /* Given PGD PFN for level N, return PGD PFN for level N+1, allocating the @@ -1452,16 +1553,12 @@ static int mmu_get_next_pgd(struct kbase_device *kbdev, struct kbase_mmu_table * return -EINVAL; } - 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; + if (!kbdev->mmu_mode->pte_is_valid(page[vpfn], level)) { unsigned int current_valid_entries; u64 managed_pte; + target_pgd = kbase_mmu_alloc_pgd(kbdev, mmut); - if (!target_pgd) { + if (target_pgd == KBASE_MMU_INVALID_PGD_ADDRESS) { dev_dbg(kbdev->dev, "%s: kbase_mmu_alloc_pgd failure\n", __func__); kunmap(p); @@ -1477,22 +1574,24 @@ static int mmu_get_next_pgd(struct kbase_device *kbdev, struct kbase_mmu_table * /* 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. + /* A new valid entry is added to an existing PGD. Perform the + * invalidate operation for GPU cache as it could be having a + * cacheline that contains the entry (in an invalid form). + * Even if the parent PGD was newly created, invalidation of + * GPU cache is still needed. For explanation, please refer + * the comment in kbase_mmu_insert_pages_no_flush(). */ - kbase_mmu_sync_pgd(kbdev, mmut->kctx, *pgd, kbase_dma_addr(p), PAGE_SIZE, flush_op); + kbase_mmu_sync_pgd(kbdev, mmut->kctx, *pgd + (vpfn * sizeof(u64)), + kbase_dma_addr(p) + (vpfn * sizeof(u64)), sizeof(u64), + KBASE_MMU_OP_FLUSH_PT); + } else { + 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])); } kunmap(p); @@ -1540,9 +1639,9 @@ static int mmu_get_bottom_pgd(struct kbase_device *kbdev, struct kbase_mmu_table static void mmu_insert_pages_failure_recovery(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, u64 from_vpfn, - u64 to_vpfn, u64 *dirty_pgds) + u64 to_vpfn, u64 *dirty_pgds, + struct list_head *free_pgds_list) { - phys_addr_t pgd; u64 vpfn = from_vpfn; struct kbase_mmu_mode const *mmu_mode; @@ -1555,7 +1654,6 @@ static void mmu_insert_pages_failure_recovery(struct kbase_device *kbdev, mmu_mode = kbdev->mmu_mode; while (vpfn < to_vpfn) { - unsigned int i; unsigned int idx = vpfn & 0x1FF; unsigned int count = KBASE_MMU_PAGE_ENTRIES - idx; unsigned int pcount = 0; @@ -1563,6 +1661,8 @@ static void mmu_insert_pages_failure_recovery(struct kbase_device *kbdev, int level; u64 *page; phys_addr_t pgds[MIDGARD_MMU_BOTTOMLEVEL + 1]; + phys_addr_t pgd = mmut->pgd; + struct page *p = phys_to_page(pgd); register unsigned int num_of_valid_entries; @@ -1570,18 +1670,17 @@ static void mmu_insert_pages_failure_recovery(struct kbase_device *kbdev, count = left; /* need to check if this is a 2MB page or a 4kB */ - pgd = mmut->pgd; - for (level = MIDGARD_MMU_TOPLEVEL; level <= MIDGARD_MMU_BOTTOMLEVEL; level++) { idx = (vpfn >> ((3 - level) * 9)) & 0x1FF; pgds[level] = pgd; - page = kmap(phys_to_page(pgd)); + page = kmap(p); if (mmu_mode->ate_is_valid(page[idx], level)) break; /* keep the mapping */ - kunmap(phys_to_page(pgd)); + kunmap(p); 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])); + p = phys_to_page(pgd); } switch (level) { @@ -1608,35 +1707,70 @@ static void mmu_insert_pages_failure_recovery(struct kbase_device *kbdev, else num_of_valid_entries -= pcount; - if (!num_of_valid_entries) { - kunmap(phys_to_page(pgd)); + /* Invalidate the entries we added */ + mmu_mode->entries_invalidate(&page[idx], pcount); - kbase_mmu_free_pgd(kbdev, mmut, pgd, true); + if (!num_of_valid_entries) { + kunmap(p); + + list_add(&p->lru, free_pgds_list); kbase_mmu_update_and_free_parent_pgds(kbdev, mmut, pgds, vpfn, level, - KBASE_MMU_OP_NONE, dirty_pgds); + KBASE_MMU_OP_NONE, dirty_pgds, + free_pgds_list); vpfn += count; continue; } - /* Invalidate the entries we added */ - for (i = 0; i < pcount; i++) - mmu_mode->entry_invalidate(&page[idx + i]); - mmu_mode->set_num_valid_entries(page, num_of_valid_entries); /* 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_dma_addr(p) + sizeof(u64) * idx, sizeof(u64) * pcount, KBASE_MMU_OP_NONE); - kunmap(phys_to_page(pgd)); + kunmap(p); next: vpfn += count; } } +static void mmu_flush_invalidate_insert_pages(struct kbase_device *kbdev, + struct kbase_mmu_table *mmut, const u64 vpfn, + size_t nr, u64 dirty_pgds, + enum kbase_caller_mmu_sync_info mmu_sync_info) +{ + struct kbase_mmu_hw_op_param op_param; + int as_nr = 0; + + 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); + +#if MALI_USE_CSF + as_nr = mmut->kctx ? mmut->kctx->as_nr : MCU_AS_NR; +#else + WARN_ON(!mmut->kctx); +#endif + + /* 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 therefore 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 + mmu_flush_invalidate(kbdev, mmut->kctx, as_nr, &op_param); +} + /* * Map the single page 'phys' 'nr' of times, starting at GPU PFN 'vpfn' */ @@ -1657,8 +1791,8 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, 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; + LIST_HEAD(free_pgds_list); if (WARN_ON(kctx == NULL)) return -EINVAL; @@ -1672,15 +1806,6 @@ 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) { @@ -1725,7 +1850,7 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, */ mmu_insert_pages_failure_recovery(kbdev, &kctx->mmu, start_vpfn, start_vpfn + recover_count, - &dirty_pgds); + &dirty_pgds, &free_pgds_list); } goto fail_unlock; } @@ -1740,7 +1865,7 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, */ mmu_insert_pages_failure_recovery(kbdev, &kctx->mmu, start_vpfn, start_vpfn + recover_count, - &dirty_pgds); + &dirty_pgds, &free_pgds_list); } err = -ENOMEM; goto fail_unlock; @@ -1791,53 +1916,21 @@ int kbase_mmu_insert_single_page(struct kbase_context *kctx, u64 vpfn, } mutex_unlock(&kctx->mmu.mmu_lock); - 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); + mmu_flush_invalidate_insert_pages(kbdev, &kctx->mmu, start_vpfn, nr, dirty_pgds, + mmu_sync_info); + return 0; fail_unlock: mutex_unlock(&kctx->mmu.mmu_lock); - 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); + + mmu_flush_invalidate_insert_pages(kbdev, &kctx->mmu, start_vpfn, nr, dirty_pgds, + mmu_sync_info); + kbase_mmu_free_pgds_list(kbdev, &kctx->mmu, &free_pgds_list); + return err; } -static void kbase_mmu_free_pgd(struct kbase_device *kbdev, - struct kbase_mmu_table *mmut, phys_addr_t pgd, - bool dirty) -{ - struct page *p; - - lockdep_assert_held(&mmut->mmu_lock); - - p = pfn_to_page(PFN_DOWN(pgd)); - - kbase_mem_pool_free(&kbdev->mem_pools.small[mmut->group_id], - p, dirty); - - atomic_sub(1, &kbdev->memdev.used_pages); - - /* If MMU tables belong to a context then pages will have been accounted - * against it, so we must decrement the usage counts here. - */ - if (mmut->kctx) { - kbase_process_page_usage_dec(mmut->kctx, 1); - atomic_sub(1, &mmut->kctx->used_pages); - } - - kbase_trace_gpu_mem_usage_dec(kbdev, mmut->kctx, 1); -} - u64 kbase_mmu_create_ate(struct kbase_device *const kbdev, struct tagged_addr const phy, unsigned long const flags, int const level, int const group_id) @@ -1859,6 +1952,7 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, struct kbase_mmu size_t remain = nr; int err; struct kbase_mmu_mode const *mmu_mode; + LIST_HEAD(free_pgds_list); /* Note that 0 is a valid start_vpfn */ /* 64-bit address range is the max */ @@ -1879,7 +1973,6 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, struct kbase_mmu 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) @@ -1919,7 +2012,8 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, struct kbase_mmu * completed */ mmu_insert_pages_failure_recovery(kbdev, mmut, start_vpfn, - insert_vpfn, dirty_pgds); + insert_vpfn, dirty_pgds, + &free_pgds_list); } goto fail_unlock; } @@ -1934,7 +2028,8 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, struct kbase_mmu * completed */ mmu_insert_pages_failure_recovery(kbdev, mmut, start_vpfn, - insert_vpfn, dirty_pgds); + insert_vpfn, dirty_pgds, + &free_pgds_list); } err = -ENOMEM; goto fail_unlock; @@ -1945,20 +2040,8 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, struct kbase_mmu if (cur_level == MIDGARD_MMU_LEVEL(2)) { int level_index = (insert_vpfn >> 9) & 0x1FF; - u64 *target = &pgd_page[level_index]; - - if (mmu_mode->pte_is_valid(*target, cur_level)) { - kbase_mmu_free_pgd( - kbdev, mmut, - kbdev->mmu_mode->pte_to_phy_addr( - kbdev->mgm_dev->ops.mgm_pte_to_original_pte( - kbdev->mgm_dev, MGM_DEFAULT_PTE_GROUP, - cur_level, *target)), - false); - num_of_valid_entries--; - } - *target = kbase_mmu_create_ate(kbdev, *phys, flags, - cur_level, group_id); + pgd_page[level_index] = + kbase_mmu_create_ate(kbdev, *phys, flags, cur_level, group_id); num_of_valid_entries++; } else { @@ -1983,36 +2066,48 @@ int kbase_mmu_insert_pages_no_flush(struct kbase_device *kbdev, struct kbase_mmu mmu_mode->set_num_valid_entries(pgd_page, num_of_valid_entries); - if (dirty_pgds && count > 0 && !newly_created_pgd) + if (dirty_pgds && !newly_created_pgd) *dirty_pgds |= 1ULL << cur_level; phys += count; insert_vpfn += count; remain -= count; - /* 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. + /* Even if mmu_get_pgd_at_level() allocated a new bottom level + * table page, the invalidation of L2 cache is still needed for + * for the valid entries written in that page. This is because a + * race can happen as soon as the entry of parent level table is + * updated to point to the page of bottom level table. + * GPU can try to access within the the same virtual range that + * is being mapped, before the valid entries of bottom level table + * page are flushed to the memory from the CPU's cache. And if that + * happens then the invalid entries from memory could get fetched + * into the L2 cache and so those entries won't be affected by the + * MMU TLB invalidation done by sending the UNLOCK command. + * If the memory is growable then this could result in unexpected + * page faults happening repeatedly, until the invalid entry is + * evicted from the L2 cache, as Driver would consider the page + * faults for mapped memory as duplicate and won't take any action + * effectively. */ - 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); + KBASE_MMU_OP_FLUSH_PT); kunmap(p); } - err = 0; + mutex_unlock(&mmut->mmu_lock); + + return 0; fail_unlock: mutex_unlock(&mmut->mmu_lock); + + mmu_flush_invalidate_insert_pages(kbdev, mmut, start_vpfn, nr, *dirty_pgds, + CALLER_MMU_ASYNC); + kbase_mmu_free_pgds_list(kbdev, mmut, &free_pgds_list); + return err; } @@ -2027,8 +2122,8 @@ 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; + LIST_HEAD(free_pgds_list); /* Early out if there is nothing to do */ if (nr == 0) @@ -2036,28 +2131,12 @@ int kbase_mmu_insert_pages(struct kbase_device *kbdev, err = kbase_mmu_insert_pages_no_flush(kbdev, mmut, vpfn, phys, nr, flags, group_id, &dirty_pgds); + if (err) + return err; - 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_flush_invalidate_insert_pages(kbdev, mmut, vpfn, nr, dirty_pgds, mmu_sync_info); - /* 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 - mmu_flush_invalidate(kbdev, mmut->kctx, as_nr, &op_param); - - return err; + return 0; } KBASE_EXPORT_TEST_API(kbase_mmu_insert_pages); @@ -2173,7 +2252,8 @@ 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, - enum kbase_mmu_op_type flush_op, u64 *dirty_pgds) + enum kbase_mmu_op_type flush_op, u64 *dirty_pgds, + struct list_head *free_pgds_list) { int current_level; @@ -2181,36 +2261,42 @@ static void kbase_mmu_update_and_free_parent_pgds(struct kbase_device *kbdev, for (current_level = level - 1; current_level >= MIDGARD_MMU_LEVEL(0); current_level--) { - u64 *current_page = kmap(phys_to_page(pgds[current_level])); + phys_addr_t current_pgd = pgds[current_level]; + struct page *p = phys_to_page(current_pgd); + u64 *current_page = kmap(p); unsigned int current_valid_entries = kbdev->mmu_mode->get_num_valid_entries(current_page); + int index = (vpfn >> ((3 - current_level) * 9)) & 0x1FF; /* We need to track every level that needs updating */ if (dirty_pgds) *dirty_pgds |= 1ULL << current_level; + kbdev->mmu_mode->entries_invalidate(¤t_page[index], 1); if (current_valid_entries == 1 && current_level != MIDGARD_MMU_LEVEL(0)) { - kunmap(phys_to_page(pgds[current_level])); + kunmap(p); - kbase_mmu_free_pgd(kbdev, mmut, pgds[current_level], - true); + /* Ensure the cacheline containing the last valid entry + * of PGD is invalidated from the GPU cache, before the + * PGD page is freed. + */ + kbase_mmu_sync_pgd_gpu(kbdev, mmut->kctx, + current_pgd + (index * sizeof(u64)), + sizeof(u64), flush_op); + + list_add(&p->lru, free_pgds_list); } else { - int index = (vpfn >> ((3 - current_level) * 9)) & 0x1FF; - - kbdev->mmu_mode->entry_invalidate(¤t_page[index]); - current_valid_entries--; kbdev->mmu_mode->set_num_valid_entries( current_page, current_valid_entries); - 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(p); - kunmap(phys_to_page(pgds[current_level])); + kbase_mmu_sync_pgd(kbdev, mmut->kctx, current_pgd + (index * sizeof(u64)), + kbase_dma_addr(p) + (index * sizeof(u64)), sizeof(u64), + flush_op); break; } } @@ -2239,15 +2325,33 @@ static void mmu_flush_invalidate_teardown_pages(struct kbase_device *kbdev, struct tagged_addr *phys, struct kbase_mmu_hw_op_param *op_param) { - if (!mmu_flush_cache_on_gpu_ctrl(kbdev)) { + /* Full cache flush through the MMU_COMMAND */ mmu_flush_invalidate(kbdev, kctx, as_nr, op_param); - return; } else if (op_param->op == KBASE_MMU_OP_FLUSH_MEM) { + /* Full cache flush through the GPU_CONTROL */ mmu_flush_invalidate_on_gpu_ctrl(kbdev, kctx, as_nr, op_param); - return; } +#if MALI_USE_CSF + else { + /* Partial GPU cache flush with MMU cache invalidation */ + unsigned long irq_flags; + unsigned int i; + bool flush_done = false; + mmu_invalidate(kbdev, kctx, as_nr, op_param); + + for (i = 0; !flush_done && i < op_param->nr; i++) { + spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); + if (kbdev->pm.backend.gpu_powered && (!kctx || kctx->as_nr >= 0)) + mmu_flush_pa_range(kbdev, as_phys_addr_t(phys[i]), PAGE_SIZE, + KBASE_MMU_OP_FLUSH_MEM); + else + flush_done = true; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); + } + } +#endif } /** @@ -2282,15 +2386,14 @@ static void mmu_flush_invalidate_teardown_pages(struct kbase_device *kbdev, 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; + LIST_HEAD(free_pgds_list); /* Calls to this function are inherently asynchronous, with respect to * MMU operations. @@ -2328,19 +2431,19 @@ int kbase_mmu_teardown_pages(struct kbase_device *kbdev, struct kbase_mmu_table u64 *page; phys_addr_t pgds[MIDGARD_MMU_BOTTOMLEVEL + 1]; register unsigned int num_of_valid_entries; + phys_addr_t pgd = mmut->pgd; + struct page *p = phys_to_page(pgd); if (count > nr) count = nr; - /* need to check if this is a 2MB or a 4kB page */ - pgd = mmut->pgd; - + /* need to check if this is a 2MB page or a 4kB */ for (level = MIDGARD_MMU_TOPLEVEL; level <= MIDGARD_MMU_BOTTOMLEVEL; level++) { phys_addr_t next_pgd; index = (vpfn >> ((3 - level) * 9)) & 0x1FF; - page = kmap(phys_to_page(pgd)); + page = kmap(p); if (mmu_mode->ate_is_valid(page[index], level)) break; /* keep the mapping */ else if (!mmu_mode->pte_is_valid(page[index], level)) { @@ -2366,9 +2469,10 @@ int kbase_mmu_teardown_pages(struct kbase_device *kbdev, struct kbase_mmu_table 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])); + kunmap(p); pgds[level] = pgd; - kunmap(phys_to_page(pgd)); pgd = next_pgd; + p = phys_to_page(pgd); } switch (level) { @@ -2377,7 +2481,7 @@ int kbase_mmu_teardown_pages(struct kbase_device *kbdev, struct kbase_mmu_table dev_warn(kbdev->dev, "%s: No support for ATEs at level %d\n", __func__, level); - kunmap(phys_to_page(pgd)); + kunmap(p); goto out; case MIDGARD_MMU_LEVEL(2): /* can only teardown if count >= 512 */ @@ -2412,30 +2516,38 @@ int kbase_mmu_teardown_pages(struct kbase_device *kbdev, struct kbase_mmu_table else num_of_valid_entries -= pcount; - if (!num_of_valid_entries) { - kunmap(phys_to_page(pgd)); + /* Invalidate the entries we added */ + mmu_mode->entries_invalidate(&page[index], pcount); - kbase_mmu_free_pgd(kbdev, mmut, pgd, true); + if (!num_of_valid_entries) { + kunmap(p); + + /* Ensure the cacheline(s) containing the last valid entries + * of PGD is invalidated from the GPU cache, before the + * PGD page is freed. + */ + kbase_mmu_sync_pgd_gpu(kbdev, mmut->kctx, + pgd + (index * sizeof(u64)), + pcount * sizeof(u64), flush_op); + + list_add(&p->lru, &free_pgds_list); kbase_mmu_update_and_free_parent_pgds(kbdev, mmut, pgds, vpfn, level, - flush_op, &dirty_pgds); + flush_op, &dirty_pgds, + &free_pgds_list); vpfn += count; nr -= count; continue; } - /* Invalidate the entries we added */ - for (i = 0; i < pcount; i++) - mmu_mode->entry_invalidate(&page[index + i]); - mmu_mode->set_num_valid_entries(page, num_of_valid_entries); kbase_mmu_sync_pgd(kbdev, mmut->kctx, pgd + (index * sizeof(u64)), - kbase_dma_addr(phys_to_page(pgd)) + 8 * index, 8 * pcount, + kbase_dma_addr(p) + (index * sizeof(u64)), pcount * sizeof(u64), flush_op); next: - kunmap(phys_to_page(pgd)); + kunmap(p); vpfn += count; nr -= count; } @@ -2454,6 +2566,8 @@ out: }; mmu_flush_invalidate_teardown_pages(kbdev, mmut->kctx, as_nr, phys, &op_param); + kbase_mmu_free_pgds_list(kbdev, mmut, &free_pgds_list); + return err; } @@ -2627,49 +2741,45 @@ static void mmu_teardown_level(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, phys_addr_t pgd, int level) { - phys_addr_t target_pgd; u64 *pgd_page; int i; - struct kbase_mmu_mode const *mmu_mode; - u64 *pgd_page_buffer; + struct memory_group_manager_device *mgm_dev = kbdev->mgm_dev; + struct kbase_mmu_mode const *mmu_mode = kbdev->mmu_mode; + u64 *pgd_page_buffer = NULL; lockdep_assert_held(&mmut->mmu_lock); - /* Early-out. No need to kmap to check entries for L3 PGD. */ - if (level == MIDGARD_MMU_BOTTOMLEVEL) { - kbase_mmu_free_pgd(kbdev, mmut, pgd, true); - return; - } - pgd_page = kmap_atomic(pfn_to_page(PFN_DOWN(pgd))); /* kmap_atomic should NEVER fail. */ if (WARN_ON(pgd_page == NULL)) return; - /* Copy the page to our preallocated buffer so that we can minimize - * kmap_atomic usage - */ - pgd_page_buffer = mmut->mmu_teardown_pages[level]; - memcpy(pgd_page_buffer, pgd_page, PAGE_SIZE); + if (level < MIDGARD_MMU_BOTTOMLEVEL) { + /* Copy the page to our preallocated buffer so that we can minimize + * kmap_atomic usage + */ + pgd_page_buffer = mmut->mmu_teardown_pages[level]; + memcpy(pgd_page_buffer, pgd_page, PAGE_SIZE); + } + + /* Invalidate page after copying */ + mmu_mode->entries_invalidate(pgd_page, KBASE_MMU_PAGE_ENTRIES); kunmap_atomic(pgd_page); pgd_page = pgd_page_buffer; - mmu_mode = kbdev->mmu_mode; - - for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; 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 (level < MIDGARD_MMU_BOTTOMLEVEL) { + for (i = 0; i < KBASE_MMU_PAGE_ENTRIES; i++) { if (mmu_mode->pte_is_valid(pgd_page[i], level)) { - mmu_teardown_level(kbdev, mmut, - target_pgd, - level + 1); + phys_addr_t target_pgd = mmu_mode->pte_to_phy_addr( + mgm_dev->ops.mgm_pte_to_original_pte(mgm_dev, + MGM_DEFAULT_PTE_GROUP, + level, pgd_page[i])); + + mmu_teardown_level(kbdev, mmut, target_pgd, level + 1); } } } - kbase_mmu_free_pgd(kbdev, mmut, pgd, true); + kbase_mmu_free_pgd(kbdev, mmut, pgd); } int kbase_mmu_init(struct kbase_device *const kbdev, @@ -2685,7 +2795,7 @@ int kbase_mmu_init(struct kbase_device *const kbdev, mmut->group_id = group_id; mutex_init(&mmut->mmu_lock); mmut->kctx = kctx; - mmut->pgd = 0; + mmut->pgd = KBASE_MMU_INVALID_PGD_ADDRESS; /* Preallocate MMU depth of 3 pages for mmu_teardown_level to use */ for (level = MIDGARD_MMU_TOPLEVEL; @@ -2703,7 +2813,7 @@ int kbase_mmu_init(struct kbase_device *const kbdev, * kbase_mmu_alloc_pgd will allocate out of that pool. This is done to * avoid allocations from the kernel happening with the lock held. */ - while (!mmut->pgd) { + while (mmut->pgd == KBASE_MMU_INVALID_PGD_ADDRESS) { int err; err = kbase_mem_pool_grow( @@ -2726,7 +2836,7 @@ void kbase_mmu_term(struct kbase_device *kbdev, struct kbase_mmu_table *mmut) { int level; - if (mmut->pgd) { + if (mmut->pgd != KBASE_MMU_INVALID_PGD_ADDRESS) { mutex_lock(&mmut->mmu_lock); mmu_teardown_level(kbdev, mmut, mmut->pgd, MIDGARD_MMU_TOPLEVEL); mutex_unlock(&mmut->mmu_lock); @@ -2750,6 +2860,7 @@ void kbase_mmu_as_term(struct kbase_device *kbdev, int i) destroy_workqueue(kbdev->as[i].pf_wq); } +#ifdef CONFIG_MALI_VECTOR_DUMP static size_t kbasep_mmu_dump_level(struct kbase_context *kctx, phys_addr_t pgd, int level, char ** const buffer, size_t *size_left) { @@ -2891,6 +3002,7 @@ fail_free: return NULL; } KBASE_EXPORT_TEST_API(kbase_mmu_dump); +#endif /* CONFIG_MALI_VECTOR_DUMP */ void kbase_mmu_bus_fault_worker(struct work_struct *data) { diff --git a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.h b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.h index 53d1d194eca7..848570f2a6dd 100644 --- a/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.h +++ b/drivers/gpu/arm/bifrost/mmu/mali_kbase_mmu.h @@ -25,6 +25,7 @@ #include #define KBASE_MMU_PAGE_ENTRIES 512 +#define KBASE_MMU_INVALID_PGD_ADDRESS (~(phys_addr_t)0) struct kbase_context; struct kbase_mmu_table; 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 c9e5ef288ff8..cc764b483f05 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 @@ -28,6 +28,26 @@ #include #include +#if MALI_USE_CSF +/** + * mmu_has_flush_skip_pgd_levels() - Check if the GPU has the feature + * AS_LOCKADDR_FLUSH_SKIP_LEVELS + * + * @gpu_props: GPU properties for the GPU instance. + * + * This function returns whether a cache flush can apply the skip flags of + * AS_LOCKADDR_FLUSH_SKIP_LEVELS. + * + * Return: True if cache flush has the said feature. + */ +static bool mmu_has_flush_skip_pgd_levels(struct kbase_gpu_props const *gpu_props) +{ + u32 const signature = + gpu_props->props.raw_props.gpu_id & (GPU_ID2_ARCH_MAJOR | GPU_ID2_ARCH_REV); + + return signature >= (u32)GPU_ID2_PRODUCT_MAKE(12, 0, 4, 0); +} +#endif /** * lock_region() - Generate lockaddr to lock memory region in MMU @@ -105,7 +125,7 @@ static int lock_region(struct kbase_gpu_props const *gpu_props, u64 *lockaddr, * therefore the highest bit that differs is bit #16 * and the region size (as a logarithm) is 16 + 1 = 17, i.e. 128 kB. */ - lockaddr_size_log2 = fls(lockaddr_base ^ lockaddr_end); + lockaddr_size_log2 = fls64(lockaddr_base ^ lockaddr_end); /* Cap the size against minimum and maximum values allowed. */ if (lockaddr_size_log2 > KBASE_LOCK_REGION_MAX_SIZE_LOG2) @@ -126,6 +146,13 @@ static int lock_region(struct kbase_gpu_props const *gpu_props, u64 *lockaddr, */ *lockaddr = lockaddr_base & ~((1ull << lockaddr_size_log2) - 1); *lockaddr |= lockaddr_size_log2 - 1; + +#if MALI_USE_CSF + if (mmu_has_flush_skip_pgd_levels(gpu_props)) + *lockaddr = + AS_LOCKADDR_FLUSH_SKIP_LEVELS_SET(*lockaddr, op_param->flush_skip_levels); +#endif + return 0; } @@ -207,21 +234,18 @@ static int wait_cores_power_trans_complete(struct kbase_device *kbdev) * 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 + * This function 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) +static int apply_hw_issue_GPU2019_3901_wa(struct kbase_device *kbdev, u32 *mmu_cmd, + unsigned int as_nr) { - unsigned long flags = 0; int ret = 0; - if (!hwaccess_locked) - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + lockdep_assert_held(&kbdev->hwaccess_lock); /* Check if L2 is OFF. The cores also must be OFF if L2 is not up, so * the workaround can be safely skipped. @@ -230,23 +254,22 @@ static int apply_hw_issue_GPU2019_3901_wa(struct kbase_device *kbdev, if (*mmu_cmd != AS_COMMAND_FLUSH_MEM) { dev_warn(kbdev->dev, "Unexpected mmu command received"); - ret = -EINVAL; - goto unlock; + return -EINVAL; } /* Wait for the LOCK MMU command to complete, issued by the caller */ ret = wait_ready(kbdev, as_nr); if (ret) - goto unlock; + return ret; ret = kbase_gpu_cache_flush_and_busy_wait(kbdev, GPU_COMMAND_CACHE_CLN_INV_LSC); if (ret) - goto unlock; + return ret; ret = wait_cores_power_trans_complete(kbdev); if (ret) - goto unlock; + return ret; /* As LSC is guaranteed to have been flushed we can use FLUSH_PT * MMU command to only flush the L2. @@ -254,10 +277,6 @@ static int apply_hw_issue_GPU2019_3901_wa(struct kbase_device *kbdev, *mmu_cmd = AS_COMMAND_FLUSH_PT; } -unlock: - if (!hwaccess_locked) - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - return ret; } #endif @@ -487,8 +506,16 @@ static int mmu_hw_do_flush(struct kbase_device *kbdev, struct kbase_as *as, * 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 (!hwaccess_locked) { + unsigned long flags = 0; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + ret = apply_hw_issue_GPU2019_3901_wa(kbdev, &mmu_cmd, as->number); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + } else { + ret = apply_hw_issue_GPU2019_3901_wa(kbdev, &mmu_cmd, as->number); + } + if (ret) return ret; } 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 dfbdee17782b..f2c627482c18 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 @@ -35,10 +35,8 @@ #define ENTRY_IS_INVAL 2ULL #define ENTRY_IS_PTE 3ULL -#define ENTRY_ATTR_BITS (7ULL << 2) /* bits 4:2 */ #define ENTRY_ACCESS_RW (1ULL << 6) /* bits 6:7 */ #define ENTRY_ACCESS_RO (3ULL << 6) -#define ENTRY_SHARE_BITS (3ULL << 8) /* bits 9:8 */ #define ENTRY_ACCESS_BIT (1ULL << 10) #define ENTRY_NX_BIT (1ULL << 54) @@ -194,25 +192,26 @@ static void entry_set_pte(u64 *entry, phys_addr_t phy) page_table_entry_set(entry, (phy & PAGE_MASK) | ENTRY_ACCESS_BIT | ENTRY_IS_PTE); } -static void entry_invalidate(u64 *entry) +static void entries_invalidate(u64 *entry, u32 count) { - page_table_entry_set(entry, ENTRY_IS_INVAL); + u32 i; + + for (i = 0; i < count; i++) + page_table_entry_set(entry + i, ENTRY_IS_INVAL); } -static const struct kbase_mmu_mode aarch64_mode = { - .update = mmu_update, - .get_as_setup = kbase_mmu_get_as_setup, - .disable_as = mmu_disable_as, - .pte_to_phy_addr = pte_to_phy_addr, - .ate_is_valid = ate_is_valid, - .pte_is_valid = pte_is_valid, - .entry_set_ate = entry_set_ate, - .entry_set_pte = entry_set_pte, - .entry_invalidate = entry_invalidate, - .get_num_valid_entries = get_num_valid_entries, - .set_num_valid_entries = set_num_valid_entries, - .flags = KBASE_MMU_MODE_HAS_NON_CACHEABLE -}; +static const struct kbase_mmu_mode aarch64_mode = { .update = mmu_update, + .get_as_setup = kbase_mmu_get_as_setup, + .disable_as = mmu_disable_as, + .pte_to_phy_addr = pte_to_phy_addr, + .ate_is_valid = ate_is_valid, + .pte_is_valid = pte_is_valid, + .entry_set_ate = entry_set_ate, + .entry_set_pte = entry_set_pte, + .entries_invalidate = entries_invalidate, + .get_num_valid_entries = get_num_valid_entries, + .set_num_valid_entries = set_num_valid_entries, + .flags = KBASE_MMU_MODE_HAS_NON_CACHEABLE }; struct kbase_mmu_mode const *kbase_mmu_mode_get_aarch64(void) { diff --git a/drivers/gpu/arm/bifrost/platform/devicetree/Kbuild b/drivers/gpu/arm/bifrost/platform/devicetree/Kbuild index 2eecd6635948..60a52d80fa8e 100644 --- a/drivers/gpu/arm/bifrost/platform/devicetree/Kbuild +++ b/drivers/gpu/arm/bifrost/platform/devicetree/Kbuild @@ -20,6 +20,5 @@ bifrost_kbase-y += \ platform/$(MALI_PLATFORM_DIR)/mali_kbase_config_devicetree.o \ - platform/$(MALI_PLATFORM_DIR)/mali_kbase_config_platform.o \ platform/$(MALI_PLATFORM_DIR)/mali_kbase_runtime_pm.o \ platform/$(MALI_PLATFORM_DIR)/mali_kbase_clk_rate_trace.o diff --git a/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.c b/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.c deleted file mode 100644 index 2eebed022a59..000000000000 --- a/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.c +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (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 - * 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 -#include -#include "mali_kbase_config_platform.h" -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -struct kbase_platform_funcs_conf platform_funcs = { - .platform_init_func = NULL, - .platform_term_func = NULL, - .platform_late_init_func = NULL, - .platform_late_term_func = NULL, -}; diff --git a/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.h b/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.h index 743885ffad0e..584a7217d300 100644 --- a/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.h +++ b/drivers/gpu/arm/bifrost/platform/devicetree/mali_kbase_config_platform.h @@ -33,13 +33,12 @@ * Attached value: pointer to @ref kbase_platform_funcs_conf * Default value: See @ref kbase_platform_funcs_conf */ -#define PLATFORM_FUNCS (&platform_funcs) +#define PLATFORM_FUNCS (NULL) #define CLK_RATE_TRACE_OPS (&clk_rate_trace_ops) extern struct kbase_pm_callback_conf pm_callbacks; extern struct kbase_clk_rate_trace_op_conf clk_rate_trace_ops; -extern struct kbase_platform_funcs_conf platform_funcs; /** * AUTO_SUSPEND_DELAY - Autosuspend delay * 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 07b09f868735..2687bee96ec9 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,7 +29,6 @@ #include "mali_kbase_config_platform.h" - static void enable_gpu_power_control(struct kbase_device *kbdev) { unsigned int i; @@ -82,8 +81,7 @@ static int pm_callback_power_on(struct kbase_device *kbdev) int error; unsigned long flags; - dev_dbg(kbdev->dev, "%s %p\n", __func__, - (void *)kbdev->dev->pm_domain); + dev_dbg(kbdev->dev, "%s %pK\n", __func__, (void *)kbdev->dev->pm_domain); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); WARN_ON(kbdev->pm.backend.gpu_powered); @@ -298,5 +296,3 @@ struct kbase_pm_callback_conf pm_callbacks = { .power_runtime_gpu_active_callback = NULL, #endif }; - - diff --git a/drivers/gpu/arm/bifrost/platform/meson/mali_kbase_runtime_pm.c b/drivers/gpu/arm/bifrost/platform/meson/mali_kbase_runtime_pm.c index c00cbcb17d39..910d4b4fd3e1 100644 --- a/drivers/gpu/arm/bifrost/platform/meson/mali_kbase_runtime_pm.c +++ b/drivers/gpu/arm/bifrost/platform/meson/mali_kbase_runtime_pm.c @@ -149,7 +149,7 @@ static int pm_callback_power_on(struct kbase_device *kbdev) int ret = 1; /* Assume GPU has been powered off */ int error; - dev_dbg(kbdev->dev, "%s %p\n", __func__, (void *)kbdev->dev->pm_domain); + dev_dbg(kbdev->dev, "%s %pK\n", __func__, (void *)kbdev->dev->pm_domain); #ifdef KBASE_PM_RUNTIME error = pm_runtime_get_sync(kbdev->dev); diff --git a/drivers/gpu/arm/bifrost/tests/Mconfig b/drivers/gpu/arm/bifrost/tests/Mconfig index 738dbd42aac7..67b38a28cf96 100644 --- a/drivers/gpu/arm/bifrost/tests/Mconfig +++ b/drivers/gpu/arm/bifrost/tests/Mconfig @@ -26,8 +26,8 @@ menuconfig MALI_KUTF This option will build the Mali testing framework modules. Modules: - - kutf.ko - - kutf_test.ko + - kutf.ko + - kutf_test.ko config MALI_KUTF_IRQ_TEST bool "Build Mali KUTF IRQ test module" @@ -38,7 +38,7 @@ config MALI_KUTF_IRQ_TEST It can determine the latency of the Mali GPU IRQ on your system. Modules: - - mali_kutf_irq_test.ko + - mali_kutf_irq_test.ko config MALI_KUTF_CLK_RATE_TRACE bool "Build Mali KUTF Clock rate trace test module" @@ -50,7 +50,7 @@ config MALI_KUTF_CLK_RATE_TRACE basic trace test in the system. Modules: - - mali_kutf_clk_rate_trace_test_portal.ko + - mali_kutf_clk_rate_trace_test_portal.ko config MALI_KUTF_MGM_INTEGRATION_TEST bool "Build Mali KUTF MGM integration test module" @@ -62,12 +62,12 @@ config MALI_KUTF_MGM_INTEGRATION_TEST group ids. Modules: - - mali_kutf_mgm_integration_test.ko + - mali_kutf_mgm_integration_test.ko # Enable MALI_BIFROST_DEBUG for KUTF modules support config UNIT_TEST_KERNEL_MODULES - bool - default y if UNIT_TEST_CODE && BACKEND_KERNEL - default n + bool + default y if UNIT_TEST_CODE && BACKEND_KERNEL + default n diff --git a/drivers/gpu/arm/bifrost/tests/build.bp b/drivers/gpu/arm/bifrost/tests/build.bp index 9d6137d17d5f..7abae237f9c3 100644 --- a/drivers/gpu/arm/bifrost/tests/build.bp +++ b/drivers/gpu/arm/bifrost/tests/build.bp @@ -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 @@ -25,7 +25,7 @@ bob_defaults { "include", "./../../", "./../", - "./" + "./", ], } 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 2d7289daca20..a6f54b61d4ad 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 @@ -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){ NULL }; + memset(data, 0, sizeof(*data)); pr_debug("Hooking up the test portal to kbdev clk rate trace\n"); spin_lock(&kbdev->pm.clk_rtm.lock); 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 2d6e68946c00..f2a014d9b5ca 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 @@ -51,8 +51,6 @@ struct kutf_irq_fixture_data { struct kbase_device *kbdev; }; -#define SEC_TO_NANO(s) ((s)*1000000000LL) - /* ID for the GPU IRQ */ #define GPU_IRQ_HANDLER 2 @@ -212,6 +210,11 @@ static void mali_kutf_irq_latency(struct kutf_context *context) average_time += irq_time - start_time; udelay(10); + /* Sleep for a ms, every 10000 iterations, to avoid misleading warning + * of CPU softlockup when all GPU IRQs keep going to the same CPU. + */ + if (!(i % 10000)) + msleep(1); } /* Go back to default handler */ 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 index 2e4a083863e4..8b995f8a0a07 100644 --- 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 @@ -38,4 +38,4 @@ bob_kernel_module { kbuild_options: ["CONFIG_MALI_KUTF_MGM_INTEGRATION_TEST=y"], enabled: true, }, -} \ No newline at end of file +} diff --git a/drivers/gpu/arm/bifrost/tl/Kbuild b/drivers/gpu/arm/bifrost/tl/Kbuild index 6e472dff8a78..1c684d489d6f 100644 --- a/drivers/gpu/arm/bifrost/tl/Kbuild +++ b/drivers/gpu/arm/bifrost/tl/Kbuild @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2021 ARM Limited. All rights reserved. +# (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 diff --git a/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline.c b/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline.c index 7160522a0be6..334248867c7c 100644 --- a/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline.c +++ b/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2015-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2015-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 @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -35,7 +34,7 @@ #include #include #include - +#include /* The period of autoflush checker execution in milliseconds. */ #define AUTOFLUSH_INTERVAL 1000 /* ms */ @@ -184,90 +183,109 @@ static void kbase_tlstream_current_devfreq_target(struct kbase_device *kbdev) } #endif /* CONFIG_MALI_BIFROST_DEVFREQ */ -int kbase_timeline_io_acquire(struct kbase_device *kbdev, u32 flags) +int kbase_timeline_acquire(struct kbase_device *kbdev, u32 flags) { - int ret = 0; + int err = 0; u32 timeline_flags = TLSTREAM_ENABLED | flags; - struct kbase_timeline *timeline = kbdev->timeline; + struct kbase_timeline *timeline; + int rcode; - if (!atomic_cmpxchg(timeline->timeline_flags, 0, timeline_flags)) { - int rcode; + if (WARN_ON(!kbdev) || WARN_ON(flags & ~BASE_TLSTREAM_FLAGS_MASK)) + return -EINVAL; + + timeline = kbdev->timeline; + if (WARN_ON(!timeline)) + return -EFAULT; + + if (atomic_cmpxchg(timeline->timeline_flags, 0, timeline_flags)) + return -EBUSY; #if MALI_USE_CSF - if (flags & BASE_TLSTREAM_ENABLE_CSFFW_TRACEPOINTS) { - ret = kbase_csf_tl_reader_start( - &timeline->csf_tl_reader, kbdev); - if (ret) { - atomic_set(timeline->timeline_flags, 0); - return ret; - } - } -#endif - ret = anon_inode_getfd( - "[mali_tlstream]", - &kbasep_tlstream_fops, - timeline, - O_RDONLY | O_CLOEXEC); - if (ret < 0) { + if (flags & BASE_TLSTREAM_ENABLE_CSFFW_TRACEPOINTS) { + err = kbase_csf_tl_reader_start(&timeline->csf_tl_reader, kbdev); + if (err) { atomic_set(timeline->timeline_flags, 0); -#if MALI_USE_CSF - kbase_csf_tl_reader_stop(&timeline->csf_tl_reader); -#endif - return ret; + return err; } + } +#endif - /* Reset and initialize header streams. */ - kbase_tlstream_reset( - &timeline->streams[TL_STREAM_TYPE_OBJ_SUMMARY]); + /* Reset and initialize header streams. */ + kbase_tlstream_reset(&timeline->streams[TL_STREAM_TYPE_OBJ_SUMMARY]); - timeline->obj_header_btc = obj_desc_header_size; - timeline->aux_header_btc = aux_desc_header_size; + timeline->obj_header_btc = obj_desc_header_size; + timeline->aux_header_btc = aux_desc_header_size; #if !MALI_USE_CSF - /* If job dumping is enabled, readjust the software event's - * timeout as the default value of 3 seconds is often - * insufficient. - */ - if (flags & BASE_TLSTREAM_JOB_DUMPING_ENABLED) { - dev_info(kbdev->dev, - "Job dumping is enabled, readjusting the software event's timeout\n"); - atomic_set(&kbdev->js_data.soft_job_timeout_ms, - 1800000); - } + /* If job dumping is enabled, readjust the software event's + * timeout as the default value of 3 seconds is often + * insufficient. + */ + if (flags & BASE_TLSTREAM_JOB_DUMPING_ENABLED) { + dev_info(kbdev->dev, + "Job dumping is enabled, readjusting the software event's timeout\n"); + atomic_set(&kbdev->js_data.soft_job_timeout_ms, 1800000); + } #endif /* !MALI_USE_CSF */ - /* Summary stream was cleared during acquire. - * Create static timeline objects that will be - * read by client. - */ - kbase_create_timeline_objects(kbdev); + /* Summary stream was cleared during acquire. + * Create static timeline objects that will be + * read by client. + */ + kbase_create_timeline_objects(kbdev); #ifdef CONFIG_MALI_BIFROST_DEVFREQ - /* Devfreq target tracepoints are only fired when the target - * changes, so we won't know the current target unless we - * send it now. - */ - kbase_tlstream_current_devfreq_target(kbdev); + /* Devfreq target tracepoints are only fired when the target + * changes, so we won't know the current target unless we + * send it now. + */ + kbase_tlstream_current_devfreq_target(kbdev); #endif /* CONFIG_MALI_BIFROST_DEVFREQ */ - /* Start the autoflush timer. - * We must do this after creating timeline objects to ensure we - * don't auto-flush the streams which will be reset during the - * summarization process. - */ - atomic_set(&timeline->autoflush_timer_active, 1); - rcode = mod_timer(&timeline->autoflush_timer, - jiffies + - msecs_to_jiffies(AUTOFLUSH_INTERVAL)); - CSTD_UNUSED(rcode); - } else { - ret = -EBUSY; - } + /* Start the autoflush timer. + * We must do this after creating timeline objects to ensure we + * don't auto-flush the streams which will be reset during the + * summarization process. + */ + atomic_set(&timeline->autoflush_timer_active, 1); + rcode = mod_timer(&timeline->autoflush_timer, + jiffies + msecs_to_jiffies(AUTOFLUSH_INTERVAL)); + CSTD_UNUSED(rcode); - if (ret >= 0) - timeline->last_acquire_time = ktime_get_raw(); + timeline->last_acquire_time = ktime_get_raw(); - return ret; + return err; +} + +void kbase_timeline_release(struct kbase_timeline *timeline) +{ + ktime_t elapsed_time; + s64 elapsed_time_ms, time_to_sleep; + + if (WARN_ON(!timeline) || WARN_ON(!atomic_read(timeline->timeline_flags))) + return; + + /* Get the amount of time passed since the timeline was acquired and ensure + * we sleep for long enough such that it has been at least + * TIMELINE_HYSTERESIS_TIMEOUT_MS amount of time between acquire and release. + * This prevents userspace from spamming acquire and release too quickly. + */ + elapsed_time = ktime_sub(ktime_get_raw(), timeline->last_acquire_time); + elapsed_time_ms = ktime_to_ms(elapsed_time); + time_to_sleep = (elapsed_time_ms < 0 ? TIMELINE_HYSTERESIS_TIMEOUT_MS : + TIMELINE_HYSTERESIS_TIMEOUT_MS - elapsed_time_ms); + if (time_to_sleep > 0) + msleep_interruptible(time_to_sleep); + +#if MALI_USE_CSF + kbase_csf_tl_reader_stop(&timeline->csf_tl_reader); +#endif + + /* Stop autoflush timer before releasing access to streams. */ + atomic_set(&timeline->autoflush_timer_active, 0); + del_timer_sync(&timeline->autoflush_timer); + + atomic_set(timeline->timeline_flags, 0); } int kbase_timeline_streams_flush(struct kbase_timeline *timeline) @@ -275,11 +293,17 @@ int kbase_timeline_streams_flush(struct kbase_timeline *timeline) enum tl_stream_type stype; bool has_bytes = false; size_t nbytes = 0; -#if MALI_USE_CSF - int ret = kbase_csf_tl_reader_flush_buffer(&timeline->csf_tl_reader); - if (ret > 0) - has_bytes = true; + if (WARN_ON(!timeline)) + return -EINVAL; + +#if MALI_USE_CSF + { + int ret = kbase_csf_tl_reader_flush_buffer(&timeline->csf_tl_reader); + + if (ret > 0) + has_bytes = true; + } #endif for (stype = 0; stype < TL_STREAM_TYPE_COUNT; stype++) { diff --git a/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline.h b/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline.h index 96a4b181a285..62be6c64c850 100644 --- a/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline.h +++ b/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline.h @@ -117,4 +117,12 @@ void kbase_timeline_post_kbase_context_destroy(struct kbase_context *kctx); void kbase_timeline_stats(struct kbase_timeline *timeline, u32 *bytes_collected, u32 *bytes_generated); #endif /* MALI_UNIT_TEST */ +/** + * kbase_timeline_io_debugfs_init - Add a debugfs entry for reading timeline stream data + * + * @kbdev: An instance of the GPU platform device, allocated from the probe + * method of the driver. + */ +void kbase_timeline_io_debugfs_init(struct kbase_device *kbdev); + #endif /* _KBASE_TIMELINE_H */ 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 af8b3d8c8c35..644d69bc209d 100644 --- a/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline_io.c +++ b/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline_io.c @@ -24,9 +24,11 @@ #include "mali_kbase_tracepoints.h" #include "mali_kbase_timeline.h" -#include +#include + #include #include +#include /* The timeline stream file operations functions. */ static ssize_t kbasep_timeline_io_read(struct file *filp, char __user *buffer, @@ -36,15 +38,6 @@ 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); -/* The timeline stream file operations structure. */ -const struct file_operations kbasep_tlstream_fops = { - .owner = THIS_MODULE, - .release = kbasep_timeline_io_release, - .read = kbasep_timeline_io_read, - .poll = kbasep_timeline_io_poll, - .fsync = kbasep_timeline_io_fsync, -}; - /** * kbasep_timeline_io_packet_pending - check timeline streams for pending * packets @@ -290,7 +283,8 @@ static ssize_t kbasep_timeline_io_read(struct file *filp, char __user *buffer, * @filp: Pointer to file structure * @wait: Pointer to poll table * - * Return: POLLIN if data can be read without blocking, otherwise zero + * Return: EPOLLIN | EPOLLRDNORM if data can be read without blocking, + * otherwise zero, or EPOLLHUP | EPOLLERR on error. */ static __poll_t kbasep_timeline_io_poll(struct file *filp, poll_table *wait) { @@ -302,20 +296,91 @@ static __poll_t kbasep_timeline_io_poll(struct file *filp, poll_table *wait) KBASE_DEBUG_ASSERT(wait); if (WARN_ON(!filp->private_data)) - return (__poll_t)-EFAULT; + return EPOLLHUP | EPOLLERR; timeline = (struct kbase_timeline *)filp->private_data; /* If there are header bytes to copy, read will not block */ if (kbasep_timeline_has_header_data(timeline)) - return POLLIN; + return EPOLLIN | EPOLLRDNORM; poll_wait(filp, &timeline->event_queue, wait); if (kbasep_timeline_io_packet_pending(timeline, &stream, &rb_idx)) - return POLLIN; - return 0; + return EPOLLIN | EPOLLRDNORM; + + return (__poll_t)0; } +int kbase_timeline_io_acquire(struct kbase_device *kbdev, u32 flags) +{ + /* The timeline stream file operations structure. */ + static const struct file_operations kbasep_tlstream_fops = { + .owner = THIS_MODULE, + .release = kbasep_timeline_io_release, + .read = kbasep_timeline_io_read, + .poll = kbasep_timeline_io_poll, + .fsync = kbasep_timeline_io_fsync, + }; + int err; + + if (WARN_ON(!kbdev) || (flags & ~BASE_TLSTREAM_FLAGS_MASK)) + return -EINVAL; + + err = kbase_timeline_acquire(kbdev, flags); + if (err) + return err; + + err = anon_inode_getfd("[mali_tlstream]", &kbasep_tlstream_fops, kbdev->timeline, + O_RDONLY | O_CLOEXEC); + if (err < 0) + kbase_timeline_release(kbdev->timeline); + + return err; +} + +#if IS_ENABLED(CONFIG_DEBUG_FS) +static int kbasep_timeline_io_open(struct inode *in, struct file *file) +{ + struct kbase_device *const kbdev = in->i_private; + + if (WARN_ON(!kbdev)) + return -EFAULT; + + file->private_data = kbdev->timeline; + return kbase_timeline_acquire(kbdev, BASE_TLSTREAM_FLAGS_MASK & + ~BASE_TLSTREAM_JOB_DUMPING_ENABLED); +} + +void kbase_timeline_io_debugfs_init(struct kbase_device *const kbdev) +{ + static const struct file_operations kbasep_tlstream_debugfs_fops = { + .owner = THIS_MODULE, + .open = kbasep_timeline_io_open, + .release = kbasep_timeline_io_release, + .read = kbasep_timeline_io_read, + .poll = kbasep_timeline_io_poll, + .fsync = kbasep_timeline_io_fsync, + }; + struct dentry *file; + + if (WARN_ON(!kbdev) || WARN_ON(IS_ERR_OR_NULL(kbdev->mali_debugfs_directory))) + return; + + file = debugfs_create_file("tlstream", 0444, kbdev->mali_debugfs_directory, kbdev, + &kbasep_tlstream_debugfs_fops); + + if (IS_ERR_OR_NULL(file)) + dev_warn(kbdev->dev, "Unable to create timeline debugfs entry"); +} +#else +/* + * Stub function for when debugfs is disabled + */ +void kbase_timeline_io_debugfs_init(struct kbase_device *const kbdev) +{ +} +#endif + /** * kbasep_timeline_io_release - release timeline stream descriptor * @inode: Pointer to inode structure @@ -325,55 +390,18 @@ 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) { - struct kbase_timeline *timeline; - ktime_t elapsed_time; - s64 elapsed_time_ms, time_to_sleep; - - KBASE_DEBUG_ASSERT(inode); - KBASE_DEBUG_ASSERT(filp); - KBASE_DEBUG_ASSERT(filp->private_data); - CSTD_UNUSED(inode); - timeline = (struct kbase_timeline *)filp->private_data; - - /* Get the amount of time passed since the timeline was acquired and ensure - * we sleep for long enough such that it has been at least - * TIMELINE_HYSTERESIS_TIMEOUT_MS amount of time between acquire and release. - * This prevents userspace from spamming acquire and release too quickly. - */ - elapsed_time = ktime_sub(ktime_get_raw(), timeline->last_acquire_time); - elapsed_time_ms = ktime_to_ms(elapsed_time); - time_to_sleep = MIN(TIMELINE_HYSTERESIS_TIMEOUT_MS, - TIMELINE_HYSTERESIS_TIMEOUT_MS - elapsed_time_ms); - if (time_to_sleep > 0) - msleep(time_to_sleep); - -#if MALI_USE_CSF - kbase_csf_tl_reader_stop(&timeline->csf_tl_reader); -#endif - - /* Stop autoflush timer before releasing access to streams. */ - atomic_set(&timeline->autoflush_timer_active, 0); - del_timer_sync(&timeline->autoflush_timer); - - atomic_set(timeline->timeline_flags, 0); + kbase_timeline_release(filp->private_data); return 0; } static int kbasep_timeline_io_fsync(struct file *filp, loff_t start, loff_t end, int datasync) { - struct kbase_timeline *timeline; - CSTD_UNUSED(start); CSTD_UNUSED(end); CSTD_UNUSED(datasync); - if (WARN_ON(!filp->private_data)) - return -EFAULT; - - timeline = (struct kbase_timeline *)filp->private_data; - - return kbase_timeline_streams_flush(timeline); + return kbase_timeline_streams_flush(filp->private_data); } diff --git a/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline_priv.h b/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline_priv.h index bf2c3855434a..de30bccc7cca 100644 --- a/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline_priv.h +++ b/drivers/gpu/arm/bifrost/tl/mali_kbase_timeline_priv.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 @@ -51,7 +51,7 @@ * @event_queue: Timeline stream event queue * @bytes_collected: Number of bytes read by user * @timeline_flags: Zero, if timeline is disabled. Timeline stream flags - * otherwise. See kbase_timeline_io_acquire(). + * otherwise. See kbase_timeline_acquire(). * @obj_header_btc: Remaining bytes to copy for the object stream header * @aux_header_btc: Remaining bytes to copy for the aux stream header * @last_acquire_time: The time at which timeline was last acquired. @@ -77,8 +77,27 @@ struct kbase_timeline { #endif }; -extern const struct file_operations kbasep_tlstream_fops; - void kbase_create_timeline_objects(struct kbase_device *kbdev); +/** + * kbase_timeline_acquire - acquire timeline for a userspace client. + * @kbdev: An instance of the GPU platform device, allocated from the probe + * method of the driver. + * @flags: Timeline stream flags + * + * Each timeline instance can be acquired by only one userspace client at a time. + * + * Return: Zero on success, error number on failure (e.g. if already acquired). + */ +int kbase_timeline_acquire(struct kbase_device *kbdev, u32 flags); + +/** + * kbase_timeline_release - release timeline for a userspace client. + * @timeline: Timeline instance to be stopped. It must be previously acquired + * with kbase_timeline_acquire(). + * + * Releasing the timeline instance allows it to be acquired by another userspace client. + */ +void kbase_timeline_release(struct kbase_timeline *timeline); + #endif /* _KBASE_TIMELINE_PRIV_H */ diff --git a/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.c b/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.c index 3ac78503ce1f..fd0d0c01adde 100644 --- a/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.c +++ b/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.c @@ -100,14 +100,14 @@ enum tl_msg_id_obj { KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT, KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT, KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE, - KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER, - KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND, KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC, KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_ALLOC, KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_ALLOC, KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_FREE, KBASE_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_FREE, KBASE_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_FREE, + KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER, + KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND, KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_START, KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_END, KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_START, @@ -416,14 +416,6 @@ enum tl_msg_id_obj { "KCPU Queue enqueues Unmap Import ignoring reference count", \ "@pL", \ "kcpu_queue,map_import_buf_gpu_addr") \ - TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER, \ - "KCPU Queue enqueues Error Barrier", \ - "@p", \ - "kcpu_queue") \ - TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND, \ - "KCPU Queue enqueues Group Suspend", \ - "@ppI", \ - "kcpu_queue,group_suspend_buf,gpu_cmdq_grp_handle") \ TRACEPOINT_DESC(KBASE_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC, \ "Begin array of KCPU Queue enqueues JIT Alloc", \ "@p", \ @@ -448,6 +440,14 @@ enum tl_msg_id_obj { "End array of KCPU Queue enqueues JIT Free", \ "@p", \ "kcpu_queue") \ + TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER, \ + "KCPU Queue enqueues Error Barrier", \ + "@p", \ + "kcpu_queue") \ + TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND, \ + "KCPU Queue enqueues Group Suspend", \ + "@ppI", \ + "kcpu_queue,group_suspend_buf,gpu_cmdq_grp_handle") \ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_START, \ "KCPU Queue starts a Signal on Fence", \ "@p", \ @@ -465,15 +465,15 @@ enum tl_msg_id_obj { "@pI", \ "kcpu_queue,execute_error") \ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START, \ - "KCPU Queue starts a Wait on an array of Cross Queue Sync Objects", \ + "KCPU Queue starts a Wait on Cross Queue Sync Object", \ "@p", \ "kcpu_queue") \ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END, \ - "KCPU Queue ends a Wait on an array of Cross Queue Sync Objects", \ + "KCPU Queue ends a Wait on Cross Queue Sync Object", \ "@pI", \ "kcpu_queue,execute_error") \ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET, \ - "KCPU Queue executes a Set on an array of Cross Queue Sync Objects", \ + "KCPU Queue executes a Set on Cross Queue Sync Object", \ "@pI", \ "kcpu_queue,execute_error") \ TRACEPOINT_DESC(KBASE_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_START, \ @@ -2540,60 +2540,6 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_unmap_import_force( kbase_tlstream_msgbuf_release(stream, acq_flags); } -void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_error_barrier( - struct kbase_tlstream *stream, - const void *kcpu_queue -) -{ - const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER; - const size_t msg_size = sizeof(msg_id) + sizeof(u64) - + sizeof(kcpu_queue) - ; - char *buffer; - unsigned long acq_flags; - size_t pos = 0; - - buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags); - - pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id)); - pos = kbasep_serialize_timestamp(buffer, pos); - pos = kbasep_serialize_bytes(buffer, - pos, &kcpu_queue, sizeof(kcpu_queue)); - - kbase_tlstream_msgbuf_release(stream, acq_flags); -} - -void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_group_suspend( - struct kbase_tlstream *stream, - const void *kcpu_queue, - const void *group_suspend_buf, - u32 gpu_cmdq_grp_handle -) -{ - const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND; - const size_t msg_size = sizeof(msg_id) + sizeof(u64) - + sizeof(kcpu_queue) - + sizeof(group_suspend_buf) - + sizeof(gpu_cmdq_grp_handle) - ; - char *buffer; - unsigned long acq_flags; - size_t pos = 0; - - buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags); - - pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id)); - pos = kbasep_serialize_timestamp(buffer, pos); - pos = kbasep_serialize_bytes(buffer, - pos, &kcpu_queue, sizeof(kcpu_queue)); - pos = kbasep_serialize_bytes(buffer, - pos, &group_suspend_buf, sizeof(group_suspend_buf)); - pos = kbasep_serialize_bytes(buffer, - pos, &gpu_cmdq_grp_handle, sizeof(gpu_cmdq_grp_handle)); - - kbase_tlstream_msgbuf_release(stream, acq_flags); -} - void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_enqueue_jit_alloc( struct kbase_tlstream *stream, const void *kcpu_queue @@ -2772,6 +2718,60 @@ void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_enqueue_jit_free( kbase_tlstream_msgbuf_release(stream, acq_flags); } +void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_error_barrier( + struct kbase_tlstream *stream, + const void *kcpu_queue +) +{ + const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER; + const size_t msg_size = sizeof(msg_id) + sizeof(u64) + + sizeof(kcpu_queue) + ; + char *buffer; + unsigned long acq_flags; + size_t pos = 0; + + buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags); + + pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_serialize_timestamp(buffer, pos); + pos = kbasep_serialize_bytes(buffer, + pos, &kcpu_queue, sizeof(kcpu_queue)); + + kbase_tlstream_msgbuf_release(stream, acq_flags); +} + +void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_group_suspend( + struct kbase_tlstream *stream, + const void *kcpu_queue, + const void *group_suspend_buf, + u32 gpu_cmdq_grp_handle +) +{ + const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND; + const size_t msg_size = sizeof(msg_id) + sizeof(u64) + + sizeof(kcpu_queue) + + sizeof(group_suspend_buf) + + sizeof(gpu_cmdq_grp_handle) + ; + char *buffer; + unsigned long acq_flags; + size_t pos = 0; + + buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags); + + pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id)); + pos = kbasep_serialize_timestamp(buffer, pos); + pos = kbasep_serialize_bytes(buffer, + pos, &kcpu_queue, sizeof(kcpu_queue)); + pos = kbasep_serialize_bytes(buffer, + pos, &group_suspend_buf, sizeof(group_suspend_buf)); + pos = kbasep_serialize_bytes(buffer, + pos, &gpu_cmdq_grp_handle, sizeof(gpu_cmdq_grp_handle)); + + kbase_tlstream_msgbuf_release(stream, acq_flags); +} + void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_signal_start( struct kbase_tlstream *stream, const void *kcpu_queue diff --git a/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.h b/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.h index cb1e63ef56f5..be0c62edecd7 100644 --- a/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.h +++ b/drivers/gpu/arm/bifrost/tl/mali_kbase_tracepoints.h @@ -77,7 +77,7 @@ extern const size_t aux_desc_header_size; #define TL_JS_EVENT_STOP GATOR_JOB_SLOT_STOP #define TL_JS_EVENT_SOFT_STOP GATOR_JOB_SLOT_SOFT_STOPPED -#define TLSTREAM_ENABLED (1 << 31) +#define TLSTREAM_ENABLED (1u << 31) void __kbase_tlstream_tl_new_ctx( struct kbase_tlstream *stream, @@ -496,18 +496,6 @@ void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_unmap_import_force( u64 map_import_buf_gpu_addr ); -void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_error_barrier( - struct kbase_tlstream *stream, - const void *kcpu_queue -); - -void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_group_suspend( - struct kbase_tlstream *stream, - const void *kcpu_queue, - const void *group_suspend_buf, - u32 gpu_cmdq_grp_handle -); - void __kbase_tlstream_tl_kbase_array_begin_kcpuqueue_enqueue_jit_alloc( struct kbase_tlstream *stream, const void *kcpu_queue @@ -548,6 +536,18 @@ void __kbase_tlstream_tl_kbase_array_end_kcpuqueue_enqueue_jit_free( const void *kcpu_queue ); +void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_error_barrier( + struct kbase_tlstream *stream, + const void *kcpu_queue +); + +void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_group_suspend( + struct kbase_tlstream *stream, + const void *kcpu_queue, + const void *group_suspend_buf, + u32 gpu_cmdq_grp_handle +); + void __kbase_tlstream_tl_kbase_kcpuqueue_execute_fence_signal_start( struct kbase_tlstream *stream, const void *kcpu_queue @@ -2493,68 +2493,6 @@ struct kbase_tlstream; do { } while (0) #endif /* MALI_USE_CSF */ -/** - * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER - KCPU Queue enqueues Error Barrier - * - * @kbdev: Kbase device - * @kcpu_queue: KCPU queue - */ -#if MALI_USE_CSF -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER( \ - kbdev, \ - kcpu_queue \ - ) \ - do { \ - int enabled = atomic_read(&kbdev->timeline_flags); \ - if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \ - __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_error_barrier( \ - __TL_DISPATCH_STREAM(kbdev, obj), \ - kcpu_queue \ - ); \ - } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ - -/** - * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND - KCPU Queue enqueues Group Suspend - * - * @kbdev: Kbase device - * @kcpu_queue: KCPU queue - * @group_suspend_buf: Pointer to the suspend buffer structure - * @gpu_cmdq_grp_handle: GPU Command Queue Group handle which will match userspace - */ -#if MALI_USE_CSF -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND( \ - kbdev, \ - kcpu_queue, \ - group_suspend_buf, \ - gpu_cmdq_grp_handle \ - ) \ - do { \ - int enabled = atomic_read(&kbdev->timeline_flags); \ - if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \ - __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_group_suspend( \ - __TL_DISPATCH_STREAM(kbdev, obj), \ - kcpu_queue, \ - group_suspend_buf, \ - gpu_cmdq_grp_handle \ - ); \ - } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND( \ - kbdev, \ - kcpu_queue, \ - group_suspend_buf, \ - gpu_cmdq_grp_handle \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ - /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC - Begin array of KCPU Queue enqueues JIT Alloc * @@ -2757,6 +2695,68 @@ struct kbase_tlstream; do { } while (0) #endif /* MALI_USE_CSF */ +/** + * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER - KCPU Queue enqueues Error Barrier + * + * @kbdev: Kbase device + * @kcpu_queue: KCPU queue + */ +#if MALI_USE_CSF +#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER( \ + kbdev, \ + kcpu_queue \ + ) \ + do { \ + int enabled = atomic_read(&kbdev->timeline_flags); \ + if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \ + __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_error_barrier( \ + __TL_DISPATCH_STREAM(kbdev, obj), \ + kcpu_queue \ + ); \ + } while (0) +#else +#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER( \ + kbdev, \ + kcpu_queue \ + ) \ + do { } while (0) +#endif /* MALI_USE_CSF */ + +/** + * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND - KCPU Queue enqueues Group Suspend + * + * @kbdev: Kbase device + * @kcpu_queue: KCPU queue + * @group_suspend_buf: Pointer to the suspend buffer structure + * @gpu_cmdq_grp_handle: GPU Command Queue Group handle which will match userspace + */ +#if MALI_USE_CSF +#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND( \ + kbdev, \ + kcpu_queue, \ + group_suspend_buf, \ + gpu_cmdq_grp_handle \ + ) \ + do { \ + int enabled = atomic_read(&kbdev->timeline_flags); \ + if (enabled & BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS) \ + __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_group_suspend( \ + __TL_DISPATCH_STREAM(kbdev, obj), \ + kcpu_queue, \ + group_suspend_buf, \ + gpu_cmdq_grp_handle \ + ); \ + } while (0) +#else +#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND( \ + kbdev, \ + kcpu_queue, \ + group_suspend_buf, \ + gpu_cmdq_grp_handle \ + ) \ + do { } while (0) +#endif /* MALI_USE_CSF */ + /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_START - KCPU Queue starts a Signal on Fence * @@ -2874,7 +2874,7 @@ struct kbase_tlstream; #endif /* MALI_USE_CSF */ /** - * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START - KCPU Queue starts a Wait on an array of Cross Queue Sync Objects + * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START - KCPU Queue starts a Wait on Cross Queue Sync Object * * @kbdev: Kbase device * @kcpu_queue: KCPU queue @@ -2901,7 +2901,7 @@ struct kbase_tlstream; #endif /* MALI_USE_CSF */ /** - * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END - KCPU Queue ends a Wait on an array of Cross Queue Sync Objects + * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END - KCPU Queue ends a Wait on Cross Queue Sync Object * * @kbdev: Kbase device * @kcpu_queue: KCPU queue @@ -2932,7 +2932,7 @@ struct kbase_tlstream; #endif /* MALI_USE_CSF */ /** - * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET - KCPU Queue executes a Set on an array of Cross Queue Sync Objects + * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET - KCPU Queue executes a Set on Cross Queue Sync Object * * @kbdev: Kbase device * @kcpu_queue: KCPU queue diff --git a/drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbiter_interface.h b/include/linux/mali_arbiter_interface.h similarity index 99% rename from drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbiter_interface.h rename to include/linux/mali_arbiter_interface.h index a0ca1ccddcc9..8e675ec2ad3b 100644 --- a/drivers/gpu/arm/bifrost/arbiter/mali_kbase_arbiter_interface.h +++ b/include/linux/mali_arbiter_interface.h @@ -41,7 +41,7 @@ * 4 - Added max_config support * 5 - Added GPU clock frequency reporting support from arbiter */ -#define MALI_KBASE_ARBITER_INTERFACE_VERSION 5 +#define MALI_ARBITER_INTERFACE_VERSION 5 /** * DOC: NO_FREQ is used in case platform doesn't support reporting frequency diff --git a/include/linux/memory_group_manager.h b/include/linux/memory_group_manager.h index c4667803b361..786e3b995f29 100644 --- a/include/linux/memory_group_manager.h +++ b/include/linux/memory_group_manager.h @@ -43,6 +43,8 @@ struct memory_group_manager_import_data; * @mgm_free_page: Callback to free physical memory in a group * @mgm_get_import_memory_id: Callback to get the group ID for imported memory * @mgm_update_gpu_pte: Callback to modify a GPU page table entry + * @mgm_pte_to_original_pte: Callback to get the original PTE entry as given + * to mgm_update_gpu_pte * @mgm_vmf_insert_pfn_prot: Callback to map a physical memory page for the CPU */ struct memory_group_manager_ops { @@ -120,7 +122,8 @@ struct memory_group_manager_ops { * This function allows the memory group manager to modify a GPU page * table entry before it is stored by the kbase module (controller * driver). It may set certain bits in the page table entry attributes - * or in the physical address, based on the physical memory group ID. + * or modify the physical address, based on the physical memory group ID + * and/or additional data in struct memory_group_manager_device. * * Return: A modified GPU page table entry to be stored in a page table. */ @@ -128,6 +131,17 @@ struct memory_group_manager_ops { int group_id, int mmu_level, u64 pte); /* + * mgm_pte_to_original_pte - Undo any modification done during mgm_update_gpu_pte() + * + * @mgm_dev: The memory group manager through which the request + * is being made. + * @group_id: A physical memory group ID. The meaning of this is + * defined by the systems integrator. Its valid range is + * 0 .. MEMORY_GROUP_MANAGER_NR_GROUPS-1. + * @mmu_level: The level of the page table entry in @ate. + * @pte: The page table entry to restore the original representation for, + * in LPAE or AArch64 format (depending on the driver's configuration). + * * 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(). diff --git a/include/linux/version_compat_defs.h b/include/linux/version_compat_defs.h index a8e08742069d..d0a09985c5ca 100644 --- a/include/linux/version_compat_defs.h +++ b/include/linux/version_compat_defs.h @@ -28,4 +28,20 @@ typedef unsigned int __poll_t; #endif +#ifndef EPOLLHUP +#define EPOLLHUP POLLHUP +#endif + +#ifndef EPOLLERR +#define EPOLLERR POLLERR +#endif + +#ifndef EPOLLIN +#define EPOLLIN POLLIN +#endif + +#ifndef EPOLLRDNORM +#define EPOLLRDNORM POLLRDNORM +#endif + #endif /* _VERSION_COMPAT_DEFS_H_ */ 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 3b02350c08bf..d9813c055809 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 @@ -573,6 +573,7 @@ struct base_csf_notification { * 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. + * @paddings: Padding bytes. * @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 @@ -590,6 +591,7 @@ struct mali_base_gpu_core_props { __u32 gpu_freq_khz_max; __u32 log2_program_counter_size; __u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + __u8 paddings[4]; __u64 gpu_available_memory_size; }; diff --git a/include/uapi/gpu/arm/bifrost/csf/mali_kbase_csf_errors_dumpfault.h b/include/uapi/gpu/arm/bifrost/csf/mali_kbase_csf_errors_dumpfault.h new file mode 100644 index 000000000000..f49ab0036fc3 --- /dev/null +++ b/include/uapi/gpu/arm/bifrost/csf/mali_kbase_csf_errors_dumpfault.h @@ -0,0 +1,81 @@ +/* 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_KBASE_CSF_ERRORS_DUMPFAULT_H_ +#define _UAPI_KBASE_CSF_ERRORS_DUMPFAULT_H_ + +/** + * enum dumpfault_error_type - Enumeration to define errors to be dumped + * + * @DF_NO_ERROR: No pending error + * @DF_CSG_SUSPEND_TIMEOUT: CSG suspension timeout + * @DF_CSG_TERMINATE_TIMEOUT: CSG group termination timeout + * @DF_CSG_START_TIMEOUT: CSG start timeout + * @DF_CSG_RESUME_TIMEOUT: CSG resume timeout + * @DF_CSG_EP_CFG_TIMEOUT: CSG end point configuration timeout + * @DF_CSG_STATUS_UPDATE_TIMEOUT: CSG status update timeout + * @DF_PROGRESS_TIMER_TIMEOUT: Progress timer timeout + * @DF_FW_INTERNAL_ERROR: Firmware internal error + * @DF_CS_FATAL: CS fatal error + * @DF_CS_FAULT: CS fault error + * @DF_FENCE_WAIT_TIMEOUT: Fence wait timeout + * @DF_PROTECTED_MODE_EXIT_TIMEOUT: P.mode exit timeout + * @DF_PROTECTED_MODE_ENTRY_FAILURE: P.mode entrance failure + * @DF_PING_REQUEST_TIMEOUT: Ping request timeout + * @DF_CORE_DOWNSCALE_REQUEST_TIMEOUT: DCS downscale request timeout + * @DF_TILER_OOM: Tiler Out-of-memory error + * @DF_GPU_PAGE_FAULT: GPU page fault + * @DF_BUS_FAULT: MMU BUS Fault + * @DF_GPU_PROTECTED_FAULT: GPU P.mode fault + * @DF_AS_ACTIVE_STUCK: AS active stuck + * @DF_GPU_SOFT_RESET_FAILURE: GPU soft reset falure + * + * This is used for kbase to notify error type of an event whereby + * user space client will dump relevant debugging information via debugfs. + * @DF_NO_ERROR is used to indicate no pending fault, thus the client will + * be blocked on reading debugfs file till a fault happens. + */ +enum dumpfault_error_type { + DF_NO_ERROR = 0, + DF_CSG_SUSPEND_TIMEOUT, + DF_CSG_TERMINATE_TIMEOUT, + DF_CSG_START_TIMEOUT, + DF_CSG_RESUME_TIMEOUT, + DF_CSG_EP_CFG_TIMEOUT, + DF_CSG_STATUS_UPDATE_TIMEOUT, + DF_PROGRESS_TIMER_TIMEOUT, + DF_FW_INTERNAL_ERROR, + DF_CS_FATAL, + DF_CS_FAULT, + DF_FENCE_WAIT_TIMEOUT, + DF_PROTECTED_MODE_EXIT_TIMEOUT, + DF_PROTECTED_MODE_ENTRY_FAILURE, + DF_PING_REQUEST_TIMEOUT, + DF_CORE_DOWNSCALE_REQUEST_TIMEOUT, + DF_TILER_OOM, + DF_GPU_PAGE_FAULT, + DF_BUS_FAULT, + DF_GPU_PROTECTED_FAULT, + DF_AS_ACTIVE_STUCK, + DF_GPU_SOFT_RESET_FAILURE, +}; + +#endif /* _UAPI_KBASE_CSF_ERRORS_DUMPFAULT_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 db7252605f06..d9a1867e13c3 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 @@ -60,10 +60,22 @@ * - 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 + * 1.13: + * - Added ioctl to query a register of USER page. + * 1.14: + * - Added support for passing down the buffer descriptor VA in tiler heap init + * 1.15: + * - Enable new sync_wait GE condition + * 1.16: + * - Remove legacy definitions: + * - base_jit_alloc_info_10_2 + * - base_jit_alloc_info_11_5 + * - kbase_ioctl_mem_jit_init_10_2 + * - kbase_ioctl_mem_jit_init_11_5 */ #define BASE_UK_VERSION_MAJOR 1 -#define BASE_UK_VERSION_MINOR 12 +#define BASE_UK_VERSION_MINOR 16 /** * struct kbase_ioctl_version_check - Check version compatibility between @@ -271,9 +283,9 @@ union kbase_ioctl_cs_queue_group_create { __u8 csi_handlers; __u8 padding[2]; /** - * @in.reserved: Reserved + * @in.dvs_buf: buffer for deferred vertex shader */ - __u64 reserved; + __u64 dvs_buf; } in; struct { __u8 group_handle; @@ -361,6 +373,7 @@ struct kbase_ioctl_kcpu_queue_enqueue { * allowed. * @in.group_id: Group ID to be used for physical allocations. * @in.padding: Padding + * @in.buf_desc_va: Buffer descriptor GPU VA for tiler heap reclaims. * @out: Output parameters * @out.gpu_heap_va: GPU VA (virtual address) of Heap context that was set up * for the heap. @@ -376,6 +389,7 @@ union kbase_ioctl_cs_tiler_heap_init { __u16 target_in_flight; __u8 group_id; __u8 padding; + __u64 buf_desc_va; } in; struct { __u64 gpu_heap_va; @@ -386,6 +400,43 @@ union kbase_ioctl_cs_tiler_heap_init { #define KBASE_IOCTL_CS_TILER_HEAP_INIT \ _IOWR(KBASE_IOCTL_TYPE, 48, union kbase_ioctl_cs_tiler_heap_init) +/** + * union kbase_ioctl_cs_tiler_heap_init_1_13 - Initialize chunked tiler memory heap, + * earlier version upto 1.13 + * @in: Input parameters + * @in.chunk_size: Size of each chunk. + * @in.initial_chunks: Initial number of chunks that heap will be created with. + * @in.max_chunks: Maximum number of chunks that the heap is allowed to use. + * @in.target_in_flight: Number of render-passes that the driver should attempt to + * keep in flight for which allocation of new chunks is + * allowed. + * @in.group_id: Group ID to be used for physical allocations. + * @in.padding: Padding + * @out: Output parameters + * @out.gpu_heap_va: GPU VA (virtual address) of Heap context that was set up + * for the heap. + * @out.first_chunk_va: GPU VA of the first chunk allocated for the heap, + * actually points to the header of heap chunk and not to + * the low address of free memory in the chunk. + */ +union kbase_ioctl_cs_tiler_heap_init_1_13 { + struct { + __u32 chunk_size; + __u32 initial_chunks; + __u32 max_chunks; + __u16 target_in_flight; + __u8 group_id; + __u8 padding; + } in; + struct { + __u64 gpu_heap_va; + __u64 first_chunk_va; + } out; +}; + +#define KBASE_IOCTL_CS_TILER_HEAP_INIT_1_13 \ + _IOWR(KBASE_IOCTL_TYPE, 48, union kbase_ioctl_cs_tiler_heap_init_1_13) + /** * struct kbase_ioctl_cs_tiler_heap_term - Terminate a chunked tiler heap * instance @@ -487,6 +538,29 @@ union kbase_ioctl_mem_alloc_ex { #define KBASE_IOCTL_MEM_ALLOC_EX _IOWR(KBASE_IOCTL_TYPE, 59, union kbase_ioctl_mem_alloc_ex) +/** + * union kbase_ioctl_read_user_page - Read a register of USER page + * + * @in: Input parameters. + * @in.offset: Register offset in USER page. + * @in.padding: Padding to round up to a multiple of 8 bytes, must be zero. + * @out: Output parameters. + * @out.val_lo: Value of 32bit register or the 1st half of 64bit register to be read. + * @out.val_hi: Value of the 2nd half of 64bit register to be read. + */ +union kbase_ioctl_read_user_page { + struct { + __u32 offset; + __u32 padding; + } in; + struct { + __u32 val_lo; + __u32 val_hi; + } out; +}; + +#define KBASE_IOCTL_READ_USER_PAGE _IOWR(KBASE_IOCTL_TYPE, 60, union kbase_ioctl_read_user_page) + /*************** * test ioctls * ***************/ diff --git a/drivers/base/arm/dma_buf_lock/src/build.bp b/include/uapi/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_csf.h similarity index 67% rename from drivers/base/arm/dma_buf_lock/src/build.bp rename to include/uapi/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_csf.h index dc49c0feb44d..75ae6a1a5409 100644 --- a/drivers/base/arm/dma_buf_lock/src/build.bp +++ b/include/uapi/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_csf.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2021 ARM Limited. All rights reserved. + * (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 @@ -19,19 +19,12 @@ * */ -bob_kernel_module { - name: "dma_buf_lock", - defaults: [ - "kernel_defaults" - ], - srcs: [ - "Kbuild", - "dma_buf_lock.c", - "dma_buf_lock.h", - ], - enabled: false, - dma_buf_lock: { - kbuild_options: ["CONFIG_DMA_BUF_LOCK=y"], - enabled: true, - }, -} +#ifndef _UAPI_KBASE_GPU_REGMAP_CSF_H_ +#define _UAPI_KBASE_GPU_REGMAP_CSF_H_ + +/* IPA control registers */ +#define IPA_CONTROL_BASE 0x40000 +#define IPA_CONTROL_REG(r) (IPA_CONTROL_BASE + (r)) +#define STATUS 0x004 /* (RO) Status register */ + +#endif /* _UAPI_KBASE_GPU_REGMAP_CSF_H_ */ diff --git a/include/uapi/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_jm.h b/include/uapi/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_jm.h index f46638947953..87f849d28c93 100644 --- a/include/uapi/gpu/arm/bifrost/gpu/backend/mali_kbase_gpu_regmap_jm.h +++ b/include/uapi/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 @@ -23,8 +23,24 @@ #define _UAPI_KBASE_GPU_REGMAP_JM_H_ /* GPU control registers */ -#define LATEST_FLUSH 0x038 /* (RO) Flush ID of latest - * clean-and-invalidate operation - */ + +#define LATEST_FLUSH 0x038 /* (RO) Flush ID of latest clean-and-invalidate operation */ + +/* Job control registers */ + +#define JS_HEAD_LO 0x00 /* (RO) Job queue head pointer for job slot n, low word */ +#define JS_HEAD_HI 0x04 /* (RO) Job queue head pointer for job slot n, high word */ +#define JS_TAIL_LO 0x08 /* (RO) Job queue tail pointer for job slot n, low word */ +#define JS_TAIL_HI 0x0C /* (RO) Job queue tail pointer for job slot n, high word */ +#define JS_AFFINITY_LO 0x10 /* (RO) Core affinity mask for job slot n, low word */ +#define JS_AFFINITY_HI 0x14 /* (RO) Core affinity mask for job slot n, high word */ +#define JS_CONFIG 0x18 /* (RO) Configuration settings for job slot n */ + +#define JS_HEAD_NEXT_LO 0x40 /* (RW) Next job queue head pointer for job slot n, low word */ +#define JS_HEAD_NEXT_HI 0x44 /* (RW) Next job queue head pointer for job slot n, high word */ +#define JS_AFFINITY_NEXT_LO 0x50 /* (RW) Next core affinity mask for job slot n, low word */ +#define JS_AFFINITY_NEXT_HI 0x54 /* (RW) Next core affinity mask for job slot n, high word */ +#define JS_CONFIG_NEXT 0x58 /* (RW) Next configuration settings for job slot n */ +#define JS_COMMAND_NEXT 0x60 /* (RW) Next command register for job slot n */ #endif /* _UAPI_KBASE_GPU_REGMAP_JM_H_ */ diff --git a/include/uapi/gpu/arm/bifrost/gpu/mali_kbase_gpu_id.h b/include/uapi/gpu/arm/bifrost/gpu/mali_kbase_gpu_id.h index 1a99e56b0910..1f34d99830fe 100644 --- a/include/uapi/gpu/arm/bifrost/gpu/mali_kbase_gpu_id.h +++ b/include/uapi/gpu/arm/bifrost/gpu/mali_kbase_gpu_id.h @@ -126,6 +126,8 @@ #define GPU_ID2_PRODUCT_LODX GPU_ID2_MODEL_MAKE(10, 7) #define GPU_ID2_PRODUCT_TTUX GPU_ID2_MODEL_MAKE(11, 2) #define GPU_ID2_PRODUCT_LTUX GPU_ID2_MODEL_MAKE(11, 3) +#define GPU_ID2_PRODUCT_TTIX GPU_ID2_MODEL_MAKE(12, 0) +#define GPU_ID2_PRODUCT_LTIX GPU_ID2_MODEL_MAKE(12, 1) /** * GPU_ID_MAKE - Helper macro to generate GPU_ID using id, major, minor, status diff --git a/include/uapi/gpu/arm/bifrost/gpu/mali_kbase_gpu_regmap.h b/include/uapi/gpu/arm/bifrost/gpu/mali_kbase_gpu_regmap.h index deca665df030..cdfcf8d3150e 100644 --- a/include/uapi/gpu/arm/bifrost/gpu/mali_kbase_gpu_regmap.h +++ b/include/uapi/gpu/arm/bifrost/gpu/mali_kbase_gpu_regmap.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 @@ -22,13 +22,70 @@ #ifndef _UAPI_KBASE_GPU_REGMAP_H_ #define _UAPI_KBASE_GPU_REGMAP_H_ -#if !MALI_USE_CSF +#if MALI_USE_CSF +#include "backend/mali_kbase_gpu_regmap_csf.h" +#else #include "backend/mali_kbase_gpu_regmap_jm.h" #endif /* !MALI_USE_CSF */ +/* Begin Register Offsets */ +/* GPU control registers */ + +#define GPU_CONTROL_BASE 0x0000 +#define GPU_CONTROL_REG(r) (GPU_CONTROL_BASE + (r)) + +#define GPU_ID 0x000 /* (RO) GPU and revision identifier */ + +#define SHADER_READY_LO 0x140 /* (RO) Shader core ready bitmap, low word */ +#define SHADER_READY_HI 0x144 /* (RO) Shader core ready bitmap, high word */ + +#define TILER_READY_LO 0x150 /* (RO) Tiler core ready bitmap, low word */ +#define TILER_READY_HI 0x154 /* (RO) Tiler core ready bitmap, high word */ + +#define L2_READY_LO 0x160 /* (RO) Level 2 cache ready bitmap, low word */ +#define L2_READY_HI 0x164 /* (RO) Level 2 cache ready bitmap, high word */ + +#define SHADER_PWRON_LO 0x180 /* (WO) Shader core power on bitmap, low word */ +#define SHADER_PWRON_HI 0x184 /* (WO) Shader core power on bitmap, high word */ + +#define TILER_PWRON_LO 0x190 /* (WO) Tiler core power on bitmap, low word */ +#define TILER_PWRON_HI 0x194 /* (WO) Tiler core power on bitmap, high word */ + +#define L2_PWRON_LO 0x1A0 /* (WO) Level 2 cache power on bitmap, low word */ +#define L2_PWRON_HI 0x1A4 /* (WO) Level 2 cache power on bitmap, high word */ + +/* Job control registers */ + +#define JOB_CONTROL_BASE 0x1000 + +#define JOB_CONTROL_REG(r) (JOB_CONTROL_BASE + (r)) + +#define JOB_IRQ_CLEAR 0x004 /* Interrupt clear register */ +#define JOB_IRQ_MASK 0x008 /* Interrupt mask register */ + /* MMU control registers */ + #define MEMORY_MANAGEMENT_BASE 0x2000 + #define MMU_REG(r) (MEMORY_MANAGEMENT_BASE + (r)) + #define MMU_IRQ_RAWSTAT 0x000 /* (RW) Raw interrupt status register */ +#define MMU_AS0 0x400 /* Configuration registers for address space 0 */ + +/* MMU address space control registers */ + +#define MMU_AS_REG(n, r) (MMU_REG(MMU_AS0 + ((n) << 6)) + (r)) + +#define AS_TRANSTAB_LO 0x00 /* (RW) Translation Table Base Address for address space n, low word */ +#define AS_TRANSTAB_HI 0x04 /* (RW) Translation Table Base Address for address space n, high word */ +#define AS_MEMATTR_LO 0x08 /* (RW) Memory attributes for address space n, low word. */ +#define AS_MEMATTR_HI 0x0C /* (RW) Memory attributes for address space n, high word. */ +#define AS_COMMAND 0x18 /* (WO) MMU command register for address space n */ + +/* (RW) Translation table configuration for address space n, low word */ +#define AS_TRANSCFG_LO 0x30 +/* (RW) Translation table configuration for address space n, high word */ +#define AS_TRANSCFG_HI 0x34 + #endif /* _UAPI_KBASE_GPU_REGMAP_H_ */ 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 ae43908b9360..1a3098d6cad8 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 @@ -1024,6 +1024,7 @@ struct base_dump_cpu_gpu_counters { * 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. + * @paddings_1: Padding bytes. * @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 @@ -1034,6 +1035,7 @@ struct base_dump_cpu_gpu_counters { * @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. + * @paddings_2: Padding bytes. */ struct mali_base_gpu_core_props { __u32 product_id; @@ -1044,8 +1046,10 @@ struct mali_base_gpu_core_props { __u32 gpu_freq_khz_max; __u32 log2_program_counter_size; __u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + __u8 paddings_1[4]; __u64 gpu_available_memory_size; __u8 num_exec_engines; + __u8 paddings_2[7]; }; #endif /* _UAPI_BASE_JM_KERNEL_H_ */ diff --git a/include/uapi/gpu/arm/bifrost/jm/mali_kbase_jm_ioctl.h b/include/uapi/gpu/arm/bifrost/jm/mali_kbase_jm_ioctl.h index 20d931adc9b8..9c7553ff2bd2 100644 --- a/include/uapi/gpu/arm/bifrost/jm/mali_kbase_jm_ioctl.h +++ b/include/uapi/gpu/arm/bifrost/jm/mali_kbase_jm_ioctl.h @@ -127,9 +127,15 @@ * - First release of new HW performance counters interface. * 11.35: * - Dummy model (no mali) backend will now clear HWC values after each sample + * 11.36: + * - Remove legacy definitions: + * - base_jit_alloc_info_10_2 + * - base_jit_alloc_info_11_5 + * - kbase_ioctl_mem_jit_init_10_2 + * - kbase_ioctl_mem_jit_init_11_5 */ #define BASE_UK_VERSION_MAJOR 11 -#define BASE_UK_VERSION_MINOR 35 +#define BASE_UK_VERSION_MINOR 36 /** * struct kbase_ioctl_version_check - Check version compatibility between diff --git a/include/uapi/gpu/arm/bifrost/mali_base_kernel.h b/include/uapi/gpu/arm/bifrost/mali_base_kernel.h index 6adbd81bcc70..e6cac0eb2a1a 100644 --- a/include/uapi/gpu/arm/bifrost/mali_base_kernel.h +++ b/include/uapi/gpu/arm/bifrost/mali_base_kernel.h @@ -197,55 +197,6 @@ struct base_mem_aliasing_info { */ #define BASE_JIT_ALLOC_COUNT (255) -/* base_jit_alloc_info in use for kernel driver versions 10.2 to early 11.5 - * - * jit_version is 1 - * - * Due to the lack of padding specified, user clients between 32 and 64-bit - * may have assumed a different size of the struct - * - * An array of structures was not supported - */ -struct base_jit_alloc_info_10_2 { - __u64 gpu_alloc_addr; - __u64 va_pages; - __u64 commit_pages; - __u64 extension; - __u8 id; -}; - -/* base_jit_alloc_info introduced by kernel driver version 11.5, and in use up - * to 11.19 - * - * This structure had a number of modifications during and after kernel driver - * version 11.5, but remains size-compatible throughout its version history, and - * with earlier variants compatible with future variants by requiring - * zero-initialization to the unused space in the structure. - * - * jit_version is 2 - * - * Kernel driver version history: - * 11.5: Initial introduction with 'usage_id' and padding[5]. All padding bytes - * must be zero. Kbase minor version was not incremented, so some - * versions of 11.5 do not have this change. - * 11.5: Added 'bin_id' and 'max_allocations', replacing 2 padding bytes (Kbase - * minor version not incremented) - * 11.6: Added 'flags', replacing 1 padding byte - * 11.10: Arrays of this structure are supported - */ -struct base_jit_alloc_info_11_5 { - __u64 gpu_alloc_addr; - __u64 va_pages; - __u64 commit_pages; - __u64 extension; - __u8 id; - __u8 bin_id; - __u8 max_allocations; - __u8 flags; - __u8 padding[2]; - __u16 usage_id; -}; - /** * struct base_jit_alloc_info - Structure which describes a JIT allocation * request. @@ -275,16 +226,6 @@ struct base_jit_alloc_info_11_5 { * @heap_info_gpu_addr: Pointer to an object in GPU memory describing * the actual usage of the region. * - * jit_version is 3. - * - * When modifications are made to this structure, it is still compatible with - * jit_version 3 when: a) the size is unchanged, and b) new members only - * replace the padding bytes. - * - * Previous jit_version history: - * jit_version == 1, refer to &base_jit_alloc_info_10_2 - * jit_version == 2, refer to &base_jit_alloc_info_11_5 - * * Kbase version history: * 11.20: added @heap_info_gpu_addr */ diff --git a/include/uapi/gpu/arm/bifrost/mali_kbase_hwcnt_reader.h b/include/uapi/gpu/arm/bifrost/mali_kbase_hwcnt_reader.h index 42d93ba4c150..962decc10efc 100644 --- a/include/uapi/gpu/arm/bifrost/mali_kbase_hwcnt_reader.h +++ b/include/uapi/gpu/arm/bifrost/mali_kbase_hwcnt_reader.h @@ -221,6 +221,7 @@ struct prfcnt_enum_sample_info { /** * struct prfcnt_enum_item - Performance counter enumeration item. + * @padding: Padding bytes. * @hdr: Header describing the type of item in the list. * @u: Structure containing discriptor for enumeration item type. * @u.block_counter: Performance counter block descriptor. @@ -229,6 +230,7 @@ struct prfcnt_enum_sample_info { */ struct prfcnt_enum_item { struct prfcnt_item_header hdr; + __u8 padding[4]; /** union u - union of block_counter and request */ union { struct prfcnt_enum_block_counter block_counter; @@ -305,6 +307,7 @@ struct prfcnt_request_scope { /** * struct prfcnt_request_item - Performance counter request item. + * @padding: Padding bytes. * @hdr: Header describing the type of item in the list. * @u: Structure containing descriptor for request type. * @u.req_mode: Mode request descriptor. @@ -313,6 +316,7 @@ struct prfcnt_request_scope { */ struct prfcnt_request_item { struct prfcnt_item_header hdr; + __u8 padding[4]; /** union u - union on req_mode and req_enable */ union { struct prfcnt_request_mode req_mode; @@ -417,6 +421,7 @@ struct prfcnt_block_metadata { /** * struct prfcnt_metadata - Performance counter metadata item. + * @padding: Padding bytes. * @hdr: Header describing the type of item in the list. * @u: Structure containing descriptor for metadata type. * @u.sample_md: Counter sample data metadata descriptor. @@ -425,6 +430,7 @@ struct prfcnt_block_metadata { */ struct prfcnt_metadata { struct prfcnt_item_header hdr; + __u8 padding[4]; union { struct prfcnt_sample_metadata sample_md; struct prfcnt_clock_metadata clock_md; diff --git a/include/uapi/gpu/arm/bifrost/mali_kbase_ioctl.h b/include/uapi/gpu/arm/bifrost/mali_kbase_ioctl.h index e691aea47b40..63bf48b603ef 100644 --- a/include/uapi/gpu/arm/bifrost/mali_kbase_ioctl.h +++ b/include/uapi/gpu/arm/bifrost/mali_kbase_ioctl.h @@ -218,52 +218,6 @@ struct kbase_ioctl_get_ddk_version { #define KBASE_IOCTL_GET_DDK_VERSION \ _IOW(KBASE_IOCTL_TYPE, 13, struct kbase_ioctl_get_ddk_version) -/** - * struct kbase_ioctl_mem_jit_init_10_2 - Initialize the just-in-time memory - * allocator (between kernel driver - * version 10.2--11.4) - * @va_pages: Number of VA pages to reserve for JIT - * - * Note that depending on the VA size of the application and GPU, the value - * specified in @va_pages may be ignored. - * - * New code should use KBASE_IOCTL_MEM_JIT_INIT instead, this is kept for - * backwards compatibility. - */ -struct kbase_ioctl_mem_jit_init_10_2 { - __u64 va_pages; -}; - -#define KBASE_IOCTL_MEM_JIT_INIT_10_2 \ - _IOW(KBASE_IOCTL_TYPE, 14, struct kbase_ioctl_mem_jit_init_10_2) - -/** - * struct kbase_ioctl_mem_jit_init_11_5 - Initialize the just-in-time memory - * allocator (between kernel driver - * version 11.5--11.19) - * @va_pages: Number of VA pages to reserve for JIT - * @max_allocations: Maximum number of concurrent allocations - * @trim_level: Level of JIT allocation trimming to perform on free (0 - 100%) - * @group_id: Group ID to be used for physical allocations - * @padding: Currently unused, must be zero - * - * Note that depending on the VA size of the application and GPU, the value - * specified in @va_pages may be ignored. - * - * New code should use KBASE_IOCTL_MEM_JIT_INIT instead, this is kept for - * backwards compatibility. - */ -struct kbase_ioctl_mem_jit_init_11_5 { - __u64 va_pages; - __u8 max_allocations; - __u8 trim_level; - __u8 group_id; - __u8 padding[5]; -}; - -#define KBASE_IOCTL_MEM_JIT_INIT_11_5 \ - _IOW(KBASE_IOCTL_TYPE, 14, struct kbase_ioctl_mem_jit_init_11_5) - /** * struct kbase_ioctl_mem_jit_init - Initialize the just-in-time memory * allocator diff --git a/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h b/include/uapi/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h similarity index 88% rename from drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h rename to include/uapi/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h index c2fb3f572f2d..329845005341 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h +++ b/include/uapi/gpu/arm/bifrost/mali_kbase_mem_profile_debugfs_buf_size.h @@ -23,8 +23,8 @@ * DOC: Header file for the size of the buffer to accumulate the histogram report text in */ -#ifndef _KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_ -#define _KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_ +#ifndef _UAPI_KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_ +#define _UAPI_KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_ /** * KBASE_MEM_PROFILE_MAX_BUF_SIZE - The size of the buffer to accumulate the histogram report text @@ -32,5 +32,4 @@ */ #define KBASE_MEM_PROFILE_MAX_BUF_SIZE ((size_t)(64 + ((80 + (56 * 64)) * 54) + 56)) -#endif /*_KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_*/ - +#endif /*_UAPI_KBASE_MEM_PROFILE_DEBUGFS_BUF_SIZE_H_*/ From 4bf27cc8c88fba9cac0301f04a9d8b3c46a3b93a Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Tue, 22 Nov 2022 10:31:29 +0800 Subject: [PATCH 109/235] ARM: dts: rockchip: rk3288-linux: fix rga to rockchip,rga2 Fix compatible of rga to "rockchip,rga2", and modify the clock names to work fine with current driver. Signed-off-by: Yu Qiaowei Change-Id: Icd30ef8e090aceedbc680eb39c4a0c5b00869102 --- arch/arm/boot/dts/rk3288-linux.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-linux.dtsi b/arch/arm/boot/dts/rk3288-linux.dtsi index 2ce2b059c1cb..7d048df9cac9 100644 --- a/arch/arm/boot/dts/rk3288-linux.dtsi +++ b/arch/arm/boot/dts/rk3288-linux.dtsi @@ -194,6 +194,13 @@ status = "okay"; }; +&rga { + compatible = "rockchip,rga2"; + clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>; + clock-names = "aclk_rga", "hclk_rga", "clk_rga"; + status = "okay"; +}; + &rng { status = "okay"; }; From 6a39dba2e58327fa73b2674f6208786b6d120014 Mon Sep 17 00:00:00 2001 From: Jian Zheng Date: Sat, 19 Nov 2022 16:00:39 +0800 Subject: [PATCH 110/235] ARM: configs: rv1106-cvr.config: based on rv1106-evb.config Separate the config for the cvr product definition Signed-off-by: Jian Zheng Change-Id: I94040ee07992e694df6d307dead7febea78b84ec --- arch/arm/configs/rv1106-cvr.config | 998 +++++++++++++++++++++++++++++ 1 file changed, 998 insertions(+) create mode 100644 arch/arm/configs/rv1106-cvr.config diff --git a/arch/arm/configs/rv1106-cvr.config b/arch/arm/configs/rv1106-cvr.config new file mode 100644 index 000000000000..b299b26a6f27 --- /dev/null +++ b/arch/arm/configs/rv1106-cvr.config @@ -0,0 +1,998 @@ +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_CONFIGFS_FS=y +CONFIG_CRC16=y +CONFIG_CRYPTO=y +CONFIG_DEBUG_FS=y +CONFIG_DRM=y +CONFIG_ELF_CORE=y +CONFIG_EXPORTFS_BLOCK_OPS=y +CONFIG_EXT4_FS=y +CONFIG_EXTCON=y +CONFIG_FB=y +CONFIG_FILE_LOCKING=y +CONFIG_I2C_GPIO=y +CONFIG_I2C_MUX=y +CONFIG_INPUT=y +CONFIG_IPV6=m +CONFIG_JFFS2_FS=y +CONFIG_KCMP=y +CONFIG_KEYS=y +CONFIG_MMC=y +CONFIG_MSDOS_PARTITION=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_UBI=y +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NVMEM_SYSFS=y +CONFIG_RK_CMA_PROCFS=y +CONFIG_RK_DMABUF_PROCFS=y +CONFIG_RK_MEMBLOCK_PROCFS=y +CONFIG_ROCKCHIP_OPP=y +CONFIG_ROCKCHIP_RGA_PROC_FS=y +CONFIG_ROCKCHIP_RVE_PROC_FS=y +CONFIG_ROCKCHIP_VENDOR_STORAGE=y +CONFIG_RTC_DRV_ROCKCHIP=y +CONFIG_SPI=y +CONFIG_USB_SUPPORT=y +CONFIG_VFAT_FS=y +CONFIG_VIDEO_OS04A10=m +CONFIG_VIDEO_SC3336=m +CONFIG_VIDEO_SC4336=m +CONFIG_VIDEO_SC530AI=m +CONFIG_WIRELESS=y +CONFIG_WLAN=y +# CONFIG_6LOWPAN is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set +# CONFIG_AD2S90 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5592R is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686_SPI is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5758 is not set +# CONFIG_AD5761 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5770R is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7124 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7266 is not set +# CONFIG_AD7280 is not set +# CONFIG_AD7292 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7303 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7606_IFACE_SPI is not set +# CONFIG_AD7766 is not set +# CONFIG_AD7768_1 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD7949 is not set +# CONFIG_AD8366 is not set +# CONFIG_AD8801 is not set +# CONFIG_AD9523 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_ADF4350 is not set +# CONFIG_ADF4371 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16460 is not set +# CONFIG_ADIS16475 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_ADXL345_SPI is not set +# CONFIG_ADXL372_SPI is not set +# CONFIG_ADXRS290 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_AFE4403 is not set +# CONFIG_AFS_FS is not set +# CONFIG_APPLE_MFI_FASTCHARGE is not set +# CONFIG_ARM_CRYPTO is not set +# CONFIG_AS3935 is not set +CONFIG_ASN1=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_ARCXCNN is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_KTD253 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_QCOM_WLED is not set +# CONFIG_BCMDHD is not set +CONFIG_BLK_DEBUG_FS=y +# CONFIG_BMA220 is not set +# CONFIG_BMC150_MAGN_SPI is not set +# CONFIG_BMI160_SPI is not set +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_CEPH_FS is not set +CONFIG_CFG80211=m +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_CRDA_SUPPORT=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y +CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y +# CONFIG_CFG80211_WEXT is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CIFS is not set +CONFIG_CLZ_TAB=y +# CONFIG_CMA_DEBUGFS is not set +# CONFIG_CODA_FS is not set +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +# CONFIG_CRYPTO_842 is not set +CONFIG_CRYPTO_ACOMP2=y +# CONFIG_CRYPTO_ADIANTUM is not set +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y +# CONFIG_CRYPTO_AEGIS128 is not set +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_AES_TI is not set +CONFIG_CRYPTO_AKCIPHER=y +CONFIG_CRYPTO_AKCIPHER2=y +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=m +# CONFIG_CRYPTO_CFB is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_CMAC=m +# 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=m +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_CURVE25519 is not set +CONFIG_CRYPTO_DEFLATE=y +# 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=m +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_GHASH=m +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_HASH_INFO=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_KPP2=y +CONFIG_CRYPTO_LIB_AES=m +CONFIG_CRYPTO_LIB_ARC4=m +# 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_LIB_SHA256=m +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +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=m +CONFIG_CRYPTO_NULL2=y +# 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_RNG2=y +CONFIG_CRYPTO_RSA=y +# 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=m +# CONFIG_CRYPTO_SHA3 is not set +# CONFIG_CRYPTO_SHA512 is not set +CONFIG_CRYPTO_SKCIPHER=m +CONFIG_CRYPTO_SKCIPHER2=y +# 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=y +# CONFIG_CYW_BCMDHD is not set +CONFIG_DEBUG_FS_ALLOW_ALL=y +# CONFIG_DEBUG_FS_ALLOW_NONE is not set +# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set +# CONFIG_DLM is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_DRM_ANALOGIX_ANX6345 is not set +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_ARCPGU is not set +# CONFIG_DRM_ARMADA is not set +CONFIG_DRM_BRIDGE=y +# CONFIG_DRM_CDNS_DSI is not set +# CONFIG_DRM_CDNS_MHDP8546 is not set +# CONFIG_DRM_CHRONTEL_CH7033 is not set +# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set +# CONFIG_DRM_DEBUG_MM is not set +# CONFIG_DRM_DEBUG_SELFTEST is not set +# CONFIG_DRM_DISPLAY_CONNECTOR is not set +# CONFIG_DRM_DP is not set +# CONFIG_DRM_DP_AUX_CHARDEV is not set +# CONFIG_DRM_DP_CEC is not set +CONFIG_DRM_EDID=y +# CONFIG_DRM_ETNAVIV is not set +# CONFIG_DRM_EXYNOS is not set +CONFIG_DRM_FBDEV_EMULATION=y +# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set +CONFIG_DRM_FBDEV_OVERALLOC=100 +# CONFIG_DRM_FSL_DCU is not set +CONFIG_DRM_GEM_CMA_HELPER=y +# CONFIG_DRM_GM12U320 is not set +# CONFIG_DRM_HDLCD is not set +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_NXP_TDA9950 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_IGNORE_IOTCL_PERMIT is not set +# CONFIG_DRM_ITE_IT6161 is not set +CONFIG_DRM_KMS_FB_HELPER=y +CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_KOMEDA is not set +# CONFIG_DRM_LEGACY is not set +# CONFIG_DRM_LIMA is not set +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +# CONFIG_DRM_LONTIUM_LT9611 is not set +# CONFIG_DRM_LVDS_CODEC is not set +# CONFIG_DRM_MALI_DISPLAY is not set +# CONFIG_DRM_MAXIM_MAX96745 is not set +# CONFIG_DRM_MAXIM_MAX96752F is not set +# CONFIG_DRM_MAXIM_MAX96755F is not set +# CONFIG_DRM_MAXIM_MAX96776 is not set +# CONFIG_DRM_MCDE is not set +# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set +# CONFIG_DRM_MXSFB is not set +# CONFIG_DRM_NWL_MIPI_DSI is not set +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_OMAP is not set +CONFIG_DRM_PANEL=y +# CONFIG_DRM_PANEL_ARM_VERSATILE is not set +CONFIG_DRM_PANEL_BRIDGE=y +# CONFIG_DRM_PANEL_ILITEK_IL9322 is not set +# CONFIG_DRM_PANEL_LG_LB035Q02 is not set +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_LVDS is not set +# CONFIG_DRM_PANEL_MAXIM_DESERIALIZER is not set +# CONFIG_DRM_PANEL_NEC_NL8048HL11 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set +# CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set +# CONFIG_DRM_PANEL_SHARP_LS037V7DW01 is not set +CONFIG_DRM_PANEL_SIMPLE=y +# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set +# CONFIG_DRM_PANEL_SONY_ACX565AKM is not set +# CONFIG_DRM_PANEL_TPO_TD028TTEC1 is not set +# CONFIG_DRM_PANEL_TPO_TD043MTEA1 is not set +# CONFIG_DRM_PANEL_TPO_TPG110 is not set +# CONFIG_DRM_PANFROST is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_PARADE_PS8640 is not set +# CONFIG_DRM_PL111 is not set +# CONFIG_DRM_RCAR_DW_HDMI is not set +# CONFIG_DRM_RCAR_LVDS is not set +# CONFIG_DRM_RK1000_TVE is not set +CONFIG_DRM_ROCKCHIP=y +# CONFIG_DRM_ROCKCHIP_VVOP is not set +# CONFIG_DRM_ROHM_BU18XL82 is not set +CONFIG_DRM_SII902X=y +# CONFIG_DRM_SII9234 is not set +# CONFIG_DRM_SIL_SII8620 is not set +# CONFIG_DRM_SIMPLE_BRIDGE is not set +# CONFIG_DRM_STI is not set +# CONFIG_DRM_STM is not set +# CONFIG_DRM_THINE_THC63LVD1024 is not set +# CONFIG_DRM_TIDSS is not set +# CONFIG_DRM_TILCDC is not set +# CONFIG_DRM_TI_SN65DSI86 is not set +# CONFIG_DRM_TI_TFP410 is not set +# CONFIG_DRM_TI_TPD12S015 is not set +# CONFIG_DRM_TOSHIBA_TC358762 is not set +# CONFIG_DRM_TOSHIBA_TC358764 is not set +# CONFIG_DRM_TOSHIBA_TC358767 is not set +# CONFIG_DRM_TOSHIBA_TC358768 is not set +# CONFIG_DRM_TOSHIBA_TC358775 is not set +# CONFIG_DRM_TVE200 is not set +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_VGEM is not set +# CONFIG_DRM_VKMS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_EXT4_DEBUG is not set +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_FSA9480 is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set +# CONFIG_EZX_PCAP is not set +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set +CONFIG_FAT_FS=y +# CONFIG_FB_ARMCLCD is not set +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_CMDLINE=y +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MODE_HELPERS is not set +CONFIG_FB_NOTIFY=y +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_SSD1307 is not set +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_FOPS=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_TFT is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +# CONFIG_FXOS8700_SPI is not set +# CONFIG_GCOV_KERNEL is not set +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_XRA1403 is not set +CONFIG_GRACE_PERIOD=y +CONFIG_HDMI=y +# CONFIG_HI8435 is not set +# CONFIG_HID is not set +# CONFIG_HID_PID is not set +# CONFIG_HISI_HIKEY_USB is not set +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_DEMUX_PINCTRL is not set +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set +# CONFIG_I2C_HID is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_GPMUX is not set +# CONFIG_I2C_MUX_LTC4306 is not set +# CONFIG_I2C_MUX_MLXCPLD is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_MUX_REG is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_IIO_SSP_SENSORHUB is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INFINEON_DHD is not set +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_JOYSTICK is not set +CONFIG_INPUT_KEYBOARD=y +# CONFIG_INPUT_MATRIXKMAP is not set +# CONFIG_INPUT_MISC is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INV_ICM42600_SPI is not set +# CONFIG_INV_MPU6050_SPI is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_RPL_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_VTI is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_LZO is not set +# CONFIG_JFFS2_RTIME is not set +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_KEYBOARD_ADC=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_BCM is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_QT1050 is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYS_REQUEST_CACHE is not set +# CONFIG_KEY_DH_OPERATIONS is not set +# CONFIG_KS7010 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_LOCK_EVENT_COUNTS is not set +# CONFIG_LOGO is not set +# CONFIG_LTC1660 is not set +# CONFIG_LTC2496 is not set +# CONFIG_LTC2632 is not set +# CONFIG_LTC2983 is not set +# CONFIG_LTE_GDM724X is not set +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MAC80211=m +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +# CONFIG_MANAGER_SBS is not set +CONFIG_MANDATORY_FILE_LOCKING=y +# CONFIG_MAX1027 is not set +# CONFIG_MAX11100 is not set +# CONFIG_MAX1118 is not set +# CONFIG_MAX1241 is not set +# CONFIG_MAX31856 is not set +# CONFIG_MAX5481 is not set +# CONFIG_MAX5487 is not set +# CONFIG_MAXIM_THERMOCOUPLE is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3911 is not set +# CONFIG_MCP41010 is not set +# CONFIG_MCP4131 is not set +# CONFIG_MCP4922 is not set +# CONFIG_MDIO_MVUSB is not set +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_INTEL_M10_BMC is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_RK806_SPI is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_MISC_RTSX_USB is not set +# CONFIG_MMA7455_SPI is not set +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +# CONFIG_MMC_CQHCI is not set +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_DW=y +# CONFIG_MMC_DW_BLUEFIELD is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_K3 is not set +CONFIG_MMC_DW_PLTFM=y +CONFIG_MMC_DW_ROCKCHIP=y +# CONFIG_MMC_HSQ is not set +# CONFIG_MMC_MTK is not set +CONFIG_MMC_QUEUE_DEPTH=1 +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_TEST is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MOST is not set +# CONFIG_MOXTET is not set +CONFIG_MPILIB=y +# CONFIG_MPL115_SPI is not set +CONFIG_MTD_BLKDEVS=y +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_MCHP23K256 is not set +CONFIG_MTD_NAND_BBT_USING_FLASH=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NOR=y +# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set +# CONFIG_MTD_SST25L is not set +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +# CONFIG_NETDEVSIM is not set +# CONFIG_NFSD is not set +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_NFS_DISABLE_UDP_SUPPORT=y +CONFIG_NFS_FS=y +CONFIG_NFS_USE_KERNEL_DNS=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_NVME_TARGET is not set +# CONFIG_OCFS2_FS is not set +CONFIG_OID_REGISTRY=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_PHY_CPCAP_USB is not set +# CONFIG_PHY_MAPPHONE_MDM6600 is not set +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +# CONFIG_PHY_ROCKCHIP_NANENG_USB2 is not set +# CONFIG_PI433 is not set +CONFIG_PKCS7_MESSAGE_PARSER=y +# CONFIG_PKCS7_TEST_KEY is not set +# CONFIG_PKCS8_PRIVATE_KEY_PARSER is not set +# CONFIG_PRISM2_USB is not set +# CONFIG_PWRSEQ_EMMC is not set +CONFIG_PWRSEQ_SIMPLE=y +# CONFIG_R8188EU is not set +# CONFIG_R8712U is not set +# CONFIG_RC_CORE is not set +CONFIG_REGMAP_SPI=y +# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_RMI4_CORE is not set +# CONFIG_ROCKCHIP_ANALOGIX_DP is not set +# CONFIG_ROCKCHIP_CDN_DP is not set +# CONFIG_ROCKCHIP_DRM_CUBIC_LUT is not set +# CONFIG_ROCKCHIP_DRM_DEBUG is not set +# CONFIG_ROCKCHIP_DRM_DIRECT_SHOW is not set +# CONFIG_ROCKCHIP_DW_DP is not set +# CONFIG_ROCKCHIP_DW_HDCP2 is not set +# CONFIG_ROCKCHIP_DW_HDMI is not set +# CONFIG_ROCKCHIP_DW_MIPI_DSI is not set +# CONFIG_ROCKCHIP_INNO_HDMI is not set +# CONFIG_ROCKCHIP_LVDS is not set +# CONFIG_ROCKCHIP_MMC_VENDOR_STORAGE is not set +CONFIG_ROCKCHIP_MTD_VENDOR_STORAGE=y +# CONFIG_ROCKCHIP_REMOTECTL is not set +CONFIG_ROCKCHIP_RGA_DEBUGGER=y +# CONFIG_ROCKCHIP_RGA_DEBUG_FS is not set +CONFIG_ROCKCHIP_RGB=y +# CONFIG_ROCKCHIP_RK3066_HDMI is not set +# CONFIG_ROCKCHIP_RKNPU_DEBUG_FS is not set +# CONFIG_ROCKCHIP_RKNPU_DRM_GEM is not set +CONFIG_ROCKCHIP_RVE_DEBUGGER=y +# CONFIG_ROCKCHIP_RVE_DEBUG_FS is not set +# CONFIG_ROCKCHIP_VCONN is not set +CONFIG_ROCKCHIP_VOP=y +# CONFIG_ROCKCHIP_VOP2 is not set +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_MCP795 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_RX6110 is not set +# CONFIG_RTL8723BS is not set +# CONFIG_RTLLIB is not set +# CONFIG_SCA3000 is not set +# CONFIG_SDIO_UART is not set +# CONFIG_SECONDARY_TRUSTED_KEYRING is not set +# CONFIG_SENSORS_HMC5843_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SENSOR_DEVICE is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +CONFIG_SGL_ALLOC=y +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set +# CONFIG_SND_BCD2000 is not set +CONFIG_SND_JACK_INPUT_DEV=y +# CONFIG_SND_SOC_ADAU1761_SPI is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_ES8328_SPI is not set +# CONFIG_SND_SOC_PCM179X_SPI is not set +# CONFIG_SND_SOC_PCM186X_SPI is not set +# CONFIG_SND_SOC_PCM3060_SPI is not set +# CONFIG_SND_SOC_PCM3168A_SPI is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RK3399_GRU_SOUND is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_ZL38060 is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB=y +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_VARIAX is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AMD is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_DEBUG is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_LOOPBACK_TEST is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +# CONFIG_SPI_MUX is not set +# CONFIG_SPI_MXIC is not set +# CONFIG_SPI_NXP_FLEXSPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +CONFIG_SPI_ROCKCHIP=y +# CONFIG_SPI_ROCKCHIP_MISCDEV is not set +CONFIG_SPI_ROCKCHIP_SFC=y +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_SLAVE is not set +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_DEBUG is not set +CONFIG_SUNRPC_GSS=y +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set +CONFIG_SYSTEM_DATA_VERIFICATION=y +# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +# CONFIG_TINYDRM_HX8357D is not set +# CONFIG_TINYDRM_ILI9225 is not set +# CONFIG_TINYDRM_ILI9341 is not set +# CONFIG_TINYDRM_ILI9486 is not set +# CONFIG_TINYDRM_MI0283QT is not set +# CONFIG_TINYDRM_REPAPER is not set +# CONFIG_TINYDRM_ST7586 is not set +# CONFIG_TINYDRM_ST7735R is not set +# CONFIG_TI_ADC0832 is not set +# CONFIG_TI_ADC084S021 is not set +# CONFIG_TI_ADC108S102 is not set +# CONFIG_TI_ADC12138 is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_TI_ADC161S626 is not set +# CONFIG_TI_ADS124S08 is not set +# CONFIG_TI_ADS7950 is not set +# CONFIG_TI_ADS8344 is not set +# CONFIG_TI_ADS8688 is not set +# CONFIG_TI_DAC082S085 is not set +# CONFIG_TI_DAC7311 is not set +# CONFIG_TI_DAC7612 is not set +# CONFIG_TI_TLC4541 is not set +# CONFIG_TYPEC is not set +# CONFIG_UBIFS_ATIME_SUPPORT is not set +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +# CONFIG_UBIFS_FS_AUTHENTICATION is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_SECURITY=y +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_ZSTD is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_USB=y +# CONFIG_USBIP_CORE is not set +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +# CONFIG_USB_APPLEDISPLAY is not set +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_AUDIO is not set +CONFIG_USB_AUTOSUSPEND_DELAY=2 +# CONFIG_USB_BDC_UDC is not set +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_CDNS3 is not set +# CONFIG_USB_CHAOSKEY is not set +# CONFIG_USB_CHIPIDEA is not set +CONFIG_USB_COMMON=y +CONFIG_USB_CONFIGFS=y +# CONFIG_USB_CONFIGFS_ACM is not set +# CONFIG_USB_CONFIGFS_ECM is not set +# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set +# CONFIG_USB_CONFIGFS_EEM is not set +# CONFIG_USB_CONFIGFS_F_AUDIO_SRC is not set +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_HID=y +# CONFIG_USB_CONFIGFS_F_LB_SS is not set +# CONFIG_USB_CONFIGFS_F_MIDI is not set +# CONFIG_USB_CONFIGFS_F_PRINTER is not set +CONFIG_USB_CONFIGFS_F_UAC1=y +# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set +CONFIG_USB_CONFIGFS_F_UAC2=y +CONFIG_USB_CONFIGFS_F_UVC=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +# CONFIG_USB_CONFIGFS_NCM is not set +# CONFIG_USB_CONFIGFS_OBEX is not set +# CONFIG_USB_CONFIGFS_RNDIS is not set +# CONFIG_USB_CONFIGFS_SERIAL is not set +CONFIG_USB_CONFIGFS_UEVENT=y +# CONFIG_USB_CONN_GPIO is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DUMMY_HCD is not set +# CONFIG_USB_DWC2 is not set +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_DUAL_ROLE=y +# CONFIG_USB_DWC3_GADGET is not set +# CONFIG_USB_DWC3_HOST is not set +CONFIG_USB_DWC3_OF_SIMPLE=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_FEW_INIT_RETRIES is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_FUSB300 is not set +CONFIG_USB_F_FS=y +CONFIG_USB_F_HID=y +CONFIG_USB_F_UAC1=y +CONFIG_USB_F_UAC2=y +CONFIG_USB_F_UVC=y +CONFIG_USB_F_MASS_STORAGE=y +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_USB_GADGET_VBUS_DRAW=2 +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_G_WEBCAM is not set +# CONFIG_USB_HCD_TEST_MODE is not set +# CONFIG_USB_HID is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set +# CONFIG_USB_HUB_USB251XB is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_ISP1760 is not set +# CONFIG_USB_KBD is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_LEGOTOWER is not set +CONFIG_USB_LIBCOMPOSITE=y +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_MAX3420_UDC is not set +# CONFIG_USB_MAX3421_HCD is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET_DRIVERS is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set +# CONFIG_USB_OTG_PRODUCTLIST is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_RAW_GADGET is not set +CONFIG_USB_ROLE_SWITCH=y +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_SNP_UDC_PLAT is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_TMC is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_ULPI is not set +# CONFIG_USB_ULPI_BUS is not set +CONFIG_USB_U_AUDIO=y +# CONFIG_USB_WDM is not set +# CONFIG_USB_XHCI_DBGCAP is not set +CONFIG_USB_XHCI_HCD=y +# CONFIG_USB_XHCI_PCI_RENESAS is not set +CONFIG_USB_XHCI_PLATFORM=y +# CONFIG_USB_YUREX is not set +# CONFIG_USB_ZERO is not set +CONFIG_VIDEOMODE_HELPERS=y +# CONFIG_VIDEO_GS1662 is not set +# CONFIG_VIDEO_MAX9286 is not set +# CONFIG_VIDEO_ROCKCHIP_PREISP is not set +# CONFIG_VIDEO_S5C73M3 is not set +# CONFIG_VIRT_WIFI is not set +# CONFIG_VT6656 is not set +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PRIV=y +CONFIG_WEXT_PROC=y +# CONFIG_WFX is not set +CONFIG_WIFI_BUILD_MODULE=y +# CONFIG_WIFI_GENERATE_RANDOM_MAC_ADDR is not set +# CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP is not set +CONFIG_WIRELESS_EXT=y +# CONFIG_WIRELESS_WDS is not set +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +CONFIG_WL_ROCKCHIP=m +CONFIG_X509_CERTIFICATE_PARSER=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y From deb783324d049b9ccefd95331d5a3f23d34a9eb3 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Mon, 21 Nov 2022 15:53:30 +0800 Subject: [PATCH 111/235] Revert "input: touchscreen: gt1x: ignore pin of reset and support power invert" This reverts commit 334791b0d3a2a25665393086b233189c0a1892b6. Reason for revert: The following warning appears on rk3588-evb1-lp4-v10 when suspend: [ 31.636037][ T414] unbalanced disables for vcc3v3_lcd0_n [ 31.636166][ T414] WARNING: CPU: 2 PID: 414 at drivers/regulator/core.c:2768 _regulator_disable+0x2e8/0x2f4 [ 31.636191][ T414] Modules linked in: bcmdhd dhd_static_buf [ 31.636256][ T414] CPU: 2 PID: 414 Comm: composer@2.1-se Not tainted 5.10.110 #116 [ 31.636279][ T414] Hardware name: Rockchip RK3588 EVB1 LP4 V10 Board (DT) [ 31.636309][ T414] pstate: 60400009 (nZCv daif +PAN -UAO -TCO BTYPE=--) [ 31.636338][ T414] pc : _regulator_disable+0x2e8/0x2f4 [ 31.636366][ T414] lr : _regulator_disable+0x2e8/0x2f4 ... [ 31.636950][ T414] Call trace: [ 31.636980][ T414] _regulator_disable+0x2e8/0x2f4 [ 31.637009][ T414] regulator_disable+0x40/0x84 [ 31.637036][ T414] panel_simple_unprepare+0x78/0xa4 [ 31.637064][ T414] drm_panel_unprepare+0x28/0x48 [ 31.637094][ T414] dw_mipi_dsi2_encoder_disable+0x70/0xbc [ 31.637123][ T414] drm_atomic_helper_commit_modeset_disables+0x174/0x4d0 [ 31.637154][ T414] rockchip_drm_atomic_helper_commit_tail_rpm+0x44/0x184 [ 31.637180][ T414] commit_tail+0x110/0x200 [ 31.637209][ T414] drm_atomic_helper_commit+0x1f0/0x210 [ 31.637238][ T414] drm_atomic_commit+0x50/0x64 [ 31.637268][ T414] drm_mode_atomic_ioctl+0x620/0x744 [ 31.637298][ T414] drm_ioctl+0x24c/0x3b8 [ 31.637328][ T414] __arm64_sys_ioctl+0x94/0xd0 [ 31.637359][ T414] el0_svc_common+0xc0/0x23c [ 31.637388][ T414] do_el0_svc+0x28/0x88 [ 31.637417][ T414] el0_svc+0x14/0x24 [ 31.637446][ T414] el0_sync_handler+0x88/0xec [ 31.637474][ T414] el0_sync+0x1a8/0x1c0 Signed-off-by: Tao Huang Change-Id: Id27946e0ef3a6c320214c961b8e9b02978a15f6b --- drivers/input/touchscreen/gt1x/gt1x.c | 53 +++++-------------- drivers/input/touchscreen/gt1x/gt1x_generic.c | 6 +-- 2 files changed, 14 insertions(+), 45 deletions(-) diff --git a/drivers/input/touchscreen/gt1x/gt1x.c b/drivers/input/touchscreen/gt1x/gt1x.c index 6fe0deaab785..f59b5c875803 100644 --- a/drivers/input/touchscreen/gt1x/gt1x.c +++ b/drivers/input/touchscreen/gt1x/gt1x.c @@ -33,7 +33,6 @@ static const struct dev_pm_ops gt1x_ts_pm_ops; bool gt1x_gt5688; int gt1x_rst_gpio; int gt1x_int_gpio; -static bool power_invert; #endif static int gt1x_register_powermanger(void); @@ -278,11 +277,6 @@ static void gt1x_ts_work_func(struct work_struct *work) #else ret = gt1x_touch_event_handler(point_data, input_dev, NULL); #endif - if (ret < 0) { -#if !GTP_ESD_PROTECT - gt1x_power_reset(); -#endif - } exit_work_func: if (!gt1x_rawdiff_mode && (ret >= 0 || ret == ERROR_VALUE)) { @@ -329,14 +323,9 @@ static int gt1x_parse_dt(struct device *dev) gt1x_int_gpio = of_get_named_gpio(np, "goodix,irq-gpio", 0); gt1x_rst_gpio = of_get_named_gpio(np, "goodix,rst-gpio", 0); - if (!gpio_is_valid(gt1x_rst_gpio)) { - GTP_INFO("Invalid GPIO, rst-gpio:%d", - gt1x_rst_gpio); - } - - if (!gpio_is_valid(gt1x_int_gpio)) { - GTP_ERROR("Invalid GPIO, irq-gpio:%d", - gt1x_int_gpio); + if (!gpio_is_valid(gt1x_int_gpio) || !gpio_is_valid(gt1x_rst_gpio)) { + GTP_ERROR("Invalid GPIO, irq-gpio:%d, rst-gpio:%d", + gt1x_int_gpio, gt1x_rst_gpio); return -EINVAL; } @@ -347,9 +336,6 @@ static int gt1x_parse_dt(struct device *dev) if (PTR_ERR(vdd_ana) == -ENODEV) { GTP_ERROR("power not specified, ignore power ctrl"); vdd_ana = NULL; - } else { - power_invert = of_property_read_bool(np, "power-invert"); - GTP_INFO("Power Invert,%s ", power_invert ? "yes" : "no"); } } if (IS_ERR(vdd_ana)) { @@ -378,7 +364,7 @@ static int gt1x_parse_dt(struct device *dev) */ int gt1x_power_switch(int on) { - int ret = 0; + int ret; struct i2c_client *client = gt1x_i2c_client; if (!client || !vdd_ana) @@ -386,22 +372,10 @@ int gt1x_power_switch(int on) if (on) { GTP_DEBUG("GTP power on."); - if (power_invert) { - if (regulator_is_enabled(vdd_ana) > 0) - ret = regulator_disable(vdd_ana); - } else { - if (!regulator_is_enabled(vdd_ana)) - ret = regulator_enable(vdd_ana); - } + ret = regulator_enable(vdd_ana); } else { GTP_DEBUG("GTP power off."); - if (power_invert) { - if (!regulator_is_enabled(vdd_ana)) - ret = regulator_enable(vdd_ana); - } else { - if (regulator_is_enabled(vdd_ana) > 0) - ret = regulator_disable(vdd_ana); - } + ret = regulator_disable(vdd_ana); } return ret; } @@ -437,17 +411,14 @@ static s32 gt1x_request_io_port(void) GTP_GPIO_AS_INT(GTP_INT_PORT); gt1x_i2c_client->irq = GTP_INT_IRQ; - if (gpio_is_valid(gt1x_rst_gpio)) { - ret = gpio_request(GTP_RST_PORT, "GTP_RST_PORT"); - if (ret < 0) { - GTP_ERROR("Failed to request GPIO:%d, ERRNO:%d", (s32) GTP_RST_PORT, ret); - gpio_free(GTP_INT_PORT); - return ret; - } - - GTP_GPIO_AS_INPUT(GTP_RST_PORT); + ret = gpio_request(GTP_RST_PORT, "GTP_RST_PORT"); + if (ret < 0) { + GTP_ERROR("Failed to request GPIO:%d, ERRNO:%d", (s32) GTP_RST_PORT, ret); + gpio_free(GTP_INT_PORT); + return ret; } + GTP_GPIO_AS_INPUT(GTP_RST_PORT); return 0; } diff --git a/drivers/input/touchscreen/gt1x/gt1x_generic.c b/drivers/input/touchscreen/gt1x/gt1x_generic.c index 4cb0d2e869a6..2531bf6e4d0a 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_generic.c +++ b/drivers/input/touchscreen/gt1x/gt1x_generic.c @@ -661,12 +661,10 @@ s32 gt1x_init_panel(void) void gt1x_select_addr(void) { - if (gpio_is_valid(gt1x_rst_gpio)) - GTP_GPIO_OUTPUT(GTP_RST_PORT, 0); + GTP_GPIO_OUTPUT(GTP_RST_PORT, 0); GTP_GPIO_OUTPUT(GTP_INT_PORT, gt1x_i2c_client->addr == 0x14); usleep_range(2000, 3000); - if (gpio_is_valid(gt1x_rst_gpio)) - GTP_GPIO_OUTPUT(GTP_RST_PORT, 1); + GTP_GPIO_OUTPUT(GTP_RST_PORT, 1); usleep_range(2000, 3000); } From 56f0ad9953fd0e34a11efbd0b735ac9fb05b4aa2 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Fri, 18 Nov 2022 01:11:59 +0000 Subject: [PATCH 112/235] drm/bridge: analogix_dp: Fix bpp value in analogix_dp_bandwidth_ok() Signed-off-by: Wyon Bi Change-Id: I38fc9c1d95966204c89afffe15ce551ae8c3f62f --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index bf41d8244fb4..fa0fb7bb3458 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -56,8 +56,16 @@ static bool analogix_dp_bandwidth_ok(struct analogix_dp_device *dp, const struct drm_display_mode *mode, unsigned int rate, unsigned int lanes) { + const struct drm_display_info *info; u32 max_bw, req_bw, bpp = 24; + if (dp->plat_data->skip_connector) + return true; + + info = &dp->connector.display_info; + if (info->bpc) + bpp = 3 * info->bpc; + req_bw = mode->clock * bpp / 8; max_bw = lanes * rate; if (req_bw > max_bw) From ed56e6902a911a0b7b523a23669c71eefc3d2d05 Mon Sep 17 00:00:00 2001 From: Alex Zhao Date: Fri, 11 Nov 2022 17:19:08 +0800 Subject: [PATCH 113/235] net: wireless: rockchip_wlan: bcmdhd: disable DHD_PKTID_AUDIT_ENABLED Signed-off-by: Alex Zhao Change-Id: I71f3a86d5a722739a03daef68c50e70de4968dd9 --- drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile index ef239e75a737..d5145294b73f 100755 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile @@ -113,7 +113,7 @@ BUS_TYPE := "pcie" DHDCFLAGS += -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1 \ -DDONGLE_ENABLE_ISOLATION DHDCFLAGS += -DDHD_LB -DDHD_LB_RXP -DDHD_LB_STATS -DDHD_LB_TXP -DHDCFLAGS += -DDHD_PKTID_AUDIT_ENABLED +#DHDCFLAGS += -DDHD_PKTID_AUDIT_ENABLED DHDCFLAGS += -DINSMOD_FW_LOAD DHDCFLAGS += -DCHIP_INTR_CONTROL #DHDCFLAGS += -DDHD_PCIE_RUNTIMEPM -DMAX_IDLE_COUNT=11 -DCUSTOM_DHD_RUNTIME_MS=100 From 7c5535c11ff9c684b1cfaf2b3906bf3496640841 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Mon, 21 Nov 2022 19:53:40 +0800 Subject: [PATCH 114/235] ASoC: codecs: rv1106_codec: add support properties to configure init gains Add support init gains: MIC Gain ALC Gain (0dB: 0x06) Lineout Gain (0dB: 0x1a) 0dB (0x01) min: -9.0dB (0x00) min: -39.0dB (0x00) 20dB (0x02) max: +37.5dB (0x1f) max: +6.0dB (0x1f) 12dB (0x03) step: +1.5dB step: +1.5dB Signed-off-by: Xing Zheng Change-Id: I827329e3b96c64a7a344dfc4094fea6d118503a5 --- sound/soc/codecs/rv1106_codec.c | 67 +++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/rv1106_codec.c b/sound/soc/codecs/rv1106_codec.c index a16f64b5cf43..3714bdcf0199 100644 --- a/sound/soc/codecs/rv1106_codec.c +++ b/sound/soc/codecs/rv1106_codec.c @@ -50,6 +50,8 @@ #define ADCL (1 << 0) #define ADCR (1 << 1) +#define NOT_SPECIFIED (-1) + enum soc_id_e { SOC_RV1103 = 0x1103, SOC_RV1106 = 0x1106, @@ -97,6 +99,11 @@ struct rv1106_codec_priv { /* For the high pass filter */ unsigned int hpf_cutoff; + /* Specify init gains after codec startup */ + unsigned int init_mic_gain; + unsigned int init_alc_gain; + unsigned int init_lineout_gain; + bool adc_enable; bool dac_enable; bool micbias_enable; @@ -1697,31 +1704,68 @@ out: static int rv1106_codec_default_gains(struct rv1106_codec_priv *rv1106) { + int gainl, gainr; + + /** + * MIC Gain + * 0dB (0x01) + * 20dB (0x02) + * 12dB (0x03) + */ + if (rv1106->init_mic_gain == NOT_SPECIFIED) { + gainl = ACODEC_ADC_L_MIC_GAIN_0DB; + gainr = ACODEC_ADC_R_MIC_GAIN_0DB; + } else { + gainl = ((rv1106->init_mic_gain >> 4) & 0x03) << ACODEC_ADC_L_MIC_GAIN_SFT; + gainr = ((rv1106->init_mic_gain >> 0) & 0x03) << ACODEC_ADC_R_MIC_GAIN_SFT; + } + /* Prepare ADC gains */ /* vendor step 12, set MIC PGA default gains */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL2, ACODEC_ADC_L_MIC_GAIN_MSK | ACODEC_ADC_R_MIC_GAIN_MSK, - ACODEC_ADC_L_MIC_GAIN_20DB | - ACODEC_ADC_R_MIC_GAIN_20DB); // TODO: using 20dB + gainl | gainr); + /** + * ALC Gain (0dB: 0x06) + * min: -9.0dB (0x00) + * max: +37.5dB (0x1f) + * step: +1.5dB + */ + if (rv1106->init_alc_gain == NOT_SPECIFIED) { + gainl = ACODEC_ADC_L_ALC_GAIN_0DB; + gainr = ACODEC_ADC_R_ALC_GAIN_0DB; + } else { + gainl = ((rv1106->init_alc_gain >> 4) & 0x1f); + gainr = ((rv1106->init_alc_gain >> 0) & 0x1f); + } /* vendor step 13, set ALC default gains */ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL4, ACODEC_ADC_L_ALC_GAIN_MSK, - ACODEC_ADC_L_ALC_GAIN_0DB); + gainl); regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL5, ACODEC_ADC_R_ALC_GAIN_MSK, - ACODEC_ADC_R_ALC_GAIN_0DB); + gainr); /* Prepare DAC gains */ /* Step 19, set LINEOUT default gains */ regmap_update_bits(rv1106->regmap, ACODEC_DAC_GAIN_SEL, ACODEC_DAC_DIG_GAIN_MSK, - ACODEC_DAC_DIG_GAIN(ACODEC_DAC_DIG_0DB)); + ACODEC_DAC_DIG_GAIN(ACODEC_DAC_DIG_0DB)); /* The calibrated fixed gain */ + /** + * Lineout Gain (0dB: 0x1a) + * min: -39.0dB (0x00) + * max: +6.0dB (0x1f) + * step: +1.5dB + */ + if (rv1106->init_lineout_gain == NOT_SPECIFIED) + gainl = ACODEC_DAC_LINEOUT_GAIN_0DB; + else + gainl = rv1106->init_lineout_gain & 0x1f; regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL2, ACODEC_DAC_LINEOUT_GAIN_MSK, - ACODEC_DAC_LINEOUT_GAIN_0DB); - + gainl); return 0; } @@ -2065,6 +2109,15 @@ static int rv1106_platform_probe(struct platform_device *pdev) rv1106->reset = NULL; } + rv1106->init_mic_gain = NOT_SPECIFIED; + of_property_read_u32(np, "init-mic-gain", &rv1106->init_mic_gain); + + rv1106->init_alc_gain = NOT_SPECIFIED; + of_property_read_u32(np, "init-alc-gain", &rv1106->init_alc_gain); + + rv1106->init_lineout_gain = NOT_SPECIFIED; + of_property_read_u32(np, "init-lineout-gain", &rv1106->init_lineout_gain); + rv1106->pa_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "pa-ctl", GPIOD_OUT_LOW); if (IS_ERR(rv1106->pa_ctl_gpio)) From 873d6962c4498ee2287d4a1f1f29f9fd10e6b56c Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Mon, 21 Nov 2022 20:04:35 +0800 Subject: [PATCH 115/235] ARM: dts: rockchip: rv1106: specify MIC Gain to 20dB by default Since most cases, we need to amplify the signal coming in from the ECM recording. Signed-off-by: Xing Zheng Change-Id: I7962d5bd604775f5de23209f13d21862145444f4 --- arch/arm/boot/dts/rv1106.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/rv1106.dtsi b/arch/arm/boot/dts/rv1106.dtsi index 95aa613423d7..4564909db8b2 100644 --- a/arch/arm/boot/dts/rv1106.dtsi +++ b/arch/arm/boot/dts/rv1106.dtsi @@ -815,6 +815,7 @@ resets = <&cru SRST_P_ACODEC>; reset-names = "acodec-reset"; acodec,micbias; + init-mic-gain = <0x22>; /* Left:20dB Right:20dB */ status = "disabled"; }; From 2c418fb7b98c3f6daf398cb396624a8996d8ff23 Mon Sep 17 00:00:00 2001 From: Wang Panzhenzhuan Date: Fri, 5 Aug 2022 08:08:38 +0000 Subject: [PATCH 116/235] arm64: configs: rockchip_defconfig: enable GC2053 & GC2093 enable gc2053 & gc2093 for rk3568-evb1 dual camera module Signed-off-by: Wang Panzhenzhuan Change-Id: I90b68722bb7a2faf6cc36675bae892be1fa6bc9b --- arch/arm64/configs/rockchip_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index 41acc0b8ec81..f3ab5c281e52 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -581,6 +581,8 @@ CONFIG_VIDEO_TC35874X=y CONFIG_VIDEO_THCV244=y CONFIG_VIDEO_RK_IRCUT=y CONFIG_VIDEO_GC0312=y +CONFIG_VIDEO_GC2053=y +CONFIG_VIDEO_GC2093=y CONFIG_VIDEO_GC2145=y CONFIG_VIDEO_GC2385=y CONFIG_VIDEO_GC4C33=y From 286b1fafa80c63f2a7a92082bb496827e720b4f0 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Mon, 7 Nov 2022 15:53:00 +0800 Subject: [PATCH 117/235] drm/rockchip: dw-dp: fixup the timing min limit Signed-off-by: Zhang Yubing Change-Id: I776ed1eaf38a7d91db3541bade02eac68908b977 --- drivers/gpu/drm/rockchip/dw-dp.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-dp.c b/drivers/gpu/drm/rockchip/dw-dp.c index b0f2c05f4c83..1330a149cdee 100644 --- a/drivers/gpu/drm/rockchip/dw-dp.c +++ b/drivers/gpu/drm/rockchip/dw-dp.c @@ -1854,6 +1854,26 @@ static void dw_dp_encoder_disable(struct drm_encoder *encoder) s->output_if &= ~(dp->id ? VOP_OUTPUT_IF_DP1 : VOP_OUTPUT_IF_DP0); } +static void dw_dp_mode_fixup(struct dw_dp *dp, struct drm_display_mode *adjusted_mode) +{ + int min_hbp = 16; + int min_hsync = 9; + + if (dp->split_mode) { + min_hbp *= 2; + min_hsync *= 2; + } + + if (adjusted_mode->hsync_end - adjusted_mode->hsync_start < min_hsync) { + adjusted_mode->hsync_end = adjusted_mode->hsync_start + min_hsync; + dev_warn(dp->dev, "hsync is too narrow, fixup to min hsync:%d\n", min_hsync); + } + if (adjusted_mode->htotal - adjusted_mode->hsync_end < min_hbp) { + adjusted_mode->htotal = adjusted_mode->hsync_end + min_hbp; + dev_warn(dp->dev, "hbp is too narrow, fixup to min hbp:%d\n", min_hbp); + } +} + static int dw_dp_encoder_atomic_check(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) @@ -1892,6 +1912,8 @@ static int dw_dp_encoder_atomic_check(struct drm_encoder *encoder, s->eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR; s->color_space = V4L2_COLORSPACE_DEFAULT; + dw_dp_mode_fixup(dp, &crtc_state->adjusted_mode); + return 0; } @@ -2032,9 +2054,6 @@ static int dw_dp_bridge_mode_valid(struct drm_bridge *bridge, if (dp->split_mode) drm_mode_convert_to_origin_mode(&m); - if (m.hsync_end - m.hsync_start <= 8) - return MODE_HSYNC_NARROW; - if (info->color_formats & DRM_COLOR_FORMAT_YCRCB420 && link->vsc_sdp_extension_for_colorimetry_supported && (drm_mode_is_420_only(info, &m) || drm_mode_is_420_also(info, &m))) From a8534cd7ac01a6c30d43f1e1ed90fc6c21c3f4a4 Mon Sep 17 00:00:00 2001 From: Yiqing Zeng Date: Tue, 22 Nov 2022 17:15:46 +0800 Subject: [PATCH 118/235] ARM: dts: rockchip: ov13850/gc8034 add power gpio for rk3288-evb-rk808-linux Change-Id: I15847124e126c7acf7e33d0aeb9430b003f37c57 Signed-off-by: Yiqing Zeng --- arch/arm/boot/dts/rk3288-evb-rk808-linux.dts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts b/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts index ef5899441582..50f1e8134db8 100644 --- a/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts +++ b/arch/arm/boot/dts/rk3288-evb-rk808-linux.dts @@ -437,7 +437,8 @@ /* reset-gpios = <>; */ pinctrl-names = "rockchip,camera_default"; pinctrl-0 = <&isp_mipi>; - power-gpio = <&gpio7 RK_PC5 GPIO_ACTIVE_HIGH>; + power-gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; + reset-gpio = <&gpio7 RK_PC5 GPIO_ACTIVE_HIGH>; pwdn-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; rockchip,camera-module-index = <0>; rockchip,camera-module-facing = "back"; @@ -459,6 +460,7 @@ clock-names = "xvclk"; pinctrl-names = "rockchip,camera_default"; pinctrl-0 = <&isp_mipi>; + power-gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; reset-gpios = <&gpio7 RK_PC5 GPIO_ACTIVE_LOW>; pwdn-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_LOW>; rockchip,camera-module-index = <0>; From 256063f27a890ba345142d2ea6dc65f24fdd0575 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 22 Nov 2022 08:22:11 +0000 Subject: [PATCH 119/235] Revert "gpio: Add support for Maxim MAX96752F GPIO controller" This reverts commit 673d3358b0b9ba9e75de4d4775cbfd33b9d93552. Delete this unused driver. Signed-off-by: Wyon Bi Change-Id: I157ef462ad5334c17389f39a71f109976896ca4f --- drivers/gpio/Kconfig | 7 --- drivers/gpio/Makefile | 1 - drivers/gpio/gpio-max96752f.c | 104 ---------------------------------- 3 files changed, 112 deletions(-) delete mode 100644 drivers/gpio/gpio-max96752f.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 88edf9d46b37..20bff29c27ff 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1250,13 +1250,6 @@ config GPIO_MAX77650 GPIO driver for MAX77650/77651 PMIC from Maxim Semiconductor. These chips have a single pin that can be configured as GPIO. -config GPIO_MAX96752F - tristate "MAX96752F GPIO" - depends on MFD_MAX96752F - help - Select this option to enable GPIO driver for the MAX96752F - chip. - config GPIO_MSIC bool "Intel MSIC mixed signal gpio support" depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 87c2046799cf..0a905ed33d0e 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -89,7 +89,6 @@ obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o obj-$(CONFIG_GPIO_MAX77620) += gpio-max77620.o obj-$(CONFIG_GPIO_MAX77650) += gpio-max77650.o -obj-$(CONFIG_GPIO_MAX96752F) += gpio-max96752f.o obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o diff --git a/drivers/gpio/gpio-max96752f.c b/drivers/gpio/gpio-max96752f.c deleted file mode 100644 index 1c3816737c55..000000000000 --- a/drivers/gpio/gpio-max96752f.c +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Maxim MAX96752F GPIO driver - * - * Copyright (C) 2022 Rockchip Electronics Co. Ltd. - */ - -#include -#include -#include -#include -#include - -struct max96752f_gpio { - struct device *dev; - struct regmap *regmap; - struct gpio_chip gpio_chip; -}; - -static int max96752f_gpio_direction_output(struct gpio_chip *gc, - unsigned int offset, int value) -{ - struct max96752f_gpio *gpio = gpiochip_get_data(gc); - - regmap_update_bits(gpio->regmap, GPIO_A_REG(offset), - GPIO_OUT_DIS | GPIO_OUT, - FIELD_PREP(GPIO_OUT_DIS, 0) | - FIELD_PREP(GPIO_OUT, value)); - - return 0; -} - -static void max96752f_gpio_set(struct gpio_chip *gc, unsigned int offset, - int value) -{ - struct max96752f_gpio *gpio = gpiochip_get_data(gc); - - regmap_update_bits(gpio->regmap, GPIO_A_REG(offset), GPIO_OUT, - FIELD_PREP(GPIO_OUT, value)); -} - -static int max96752f_gpio_get(struct gpio_chip *gc, unsigned int offset) -{ - struct max96752f_gpio *gpio = gpiochip_get_data(gc); - unsigned int value; - - regmap_read(gpio->regmap, GPIO_A_REG(offset), &value); - - return !!FIELD_GET(GPIO_OUT, value); -} - -static int max96752f_gpio_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct max96752f_gpio *gpio; - int ret; - - gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL); - if (!gpio) - return -ENOMEM; - - gpio->dev = dev; - platform_set_drvdata(pdev, gpio); - - gpio->regmap = dev_get_regmap(dev->parent, NULL); - if (!gpio->regmap) - return dev_err_probe(dev, -ENODEV, "failed to get regmap\n"); - - gpio->gpio_chip.of_node = dev->of_node; - gpio->gpio_chip.label = dev_name(dev); - gpio->gpio_chip.parent = dev->parent; - gpio->gpio_chip.direction_output = max96752f_gpio_direction_output; - gpio->gpio_chip.set = max96752f_gpio_set; - gpio->gpio_chip.get = max96752f_gpio_get; - gpio->gpio_chip.ngpio = 16; - gpio->gpio_chip.can_sleep = true; - gpio->gpio_chip.base = -1; - - ret = devm_gpiochip_add_data(dev, &gpio->gpio_chip, gpio); - if (ret) - return dev_err_probe(dev, ret, "failed to add gpio chip\n"); - - return 0; -} - -static const struct of_device_id max96752f_gpio_of_match[] = { - { .name = "maxim,max96752f-gpio", }, - {} -}; -MODULE_DEVICE_TABLE(of, max96752f_gpio_of_match); - -static struct platform_driver max96752f_gpio_driver = { - .driver = { - .name = "max96752f-gpio", - .of_match_table = max96752f_gpio_of_match, - }, - .probe = max96752f_gpio_probe, -}; - -module_platform_driver(max96752f_gpio_driver); - -MODULE_AUTHOR("Wyon Bi "); -MODULE_DESCRIPTION("Maxim MAX96752F GPIO driver"); -MODULE_LICENSE("GPL"); From eabac9aad46a271d3ed0b99b4e727d8ff9cd2338 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 22 Nov 2022 08:26:06 +0000 Subject: [PATCH 120/235] Revert "pinctrl: Add support for Maxim MAX96752F pin controller" This reverts commit 530d7e8c7cb103994f88f0599b61ce44ae7be8b2. Delete this unused driver. Change-Id: I5d478b7002bf1eb6aeba42ab2d1ccdb70c47367f Signed-off-by: Wyon Bi --- drivers/pinctrl/Kconfig | 11 - drivers/pinctrl/Makefile | 1 - drivers/pinctrl/pinctrl-max96752f.c | 642 ---------------------------- 3 files changed, 654 deletions(-) delete mode 100644 drivers/pinctrl/pinctrl-max96752f.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index f38f98fe55a7..fda4a167684c 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -320,17 +320,6 @@ config PINCTRL_MAX96745 help Say Yes here to enable Pin control support for Maxim MAX96745. -config PINCTRL_MAX96752F - tristate "MAX96752F Pincontrol support" - depends on MFD_MAX96752F && OF - select PINMUX - select PINCONF - select GENERIC_PINMUX_FUNCTIONS - select GENERIC_PINCTRL_GROUPS - select GENERIC_PINCONF - help - Say Yes here to enable Pin control support for Maxim MAX96752F. - config PINCTRL_MAX96755F tristate "MAX96755F Pincontrol support" depends on MFD_MAX96755F && OF diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index a3501477abc9..d8b32105bb4b 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -22,7 +22,6 @@ obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o obj-$(CONFIG_PINCTRL_GEMINI) += pinctrl-gemini.o obj-$(CONFIG_PINCTRL_MAX77620) += pinctrl-max77620.o obj-$(CONFIG_PINCTRL_MAX96745) += pinctrl-max96745.o -obj-$(CONFIG_PINCTRL_MAX96752F) += pinctrl-max96752f.o obj-$(CONFIG_PINCTRL_MAX96755F) += pinctrl-max96755f.o obj-$(CONFIG_PINCTRL_MCP23S08_I2C) += pinctrl-mcp23s08_i2c.o obj-$(CONFIG_PINCTRL_MCP23S08_SPI) += pinctrl-mcp23s08_spi.o diff --git a/drivers/pinctrl/pinctrl-max96752f.c b/drivers/pinctrl/pinctrl-max96752f.c deleted file mode 100644 index c2f815906137..000000000000 --- a/drivers/pinctrl/pinctrl-max96752f.c +++ /dev/null @@ -1,642 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Maxim MAX96752F pin control driver. - * - * Copyright (c) 2022 Rockchip Electronics Co. Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "core.h" -#include "pinconf.h" -#include "pinmux.h" - -struct max96752f_pinctrl { - struct device *dev; - struct pinctrl_dev *pctl; - struct regmap *regmap; -}; - -struct config_desc { - u16 reg; - u8 mask; - u8 val; -}; - -struct max96752f_group_data { - const struct config_desc *configs; - int num_configs; -}; - -struct max96752f_function_data { - u8 gpio_out_dis:1; - u8 gpio_tx_en:1; - u8 gpio_rx_en:1; - u8 gpio_tx_id; - u8 gpio_rx_id; -}; - -static int max96752f_pinmux_set_mux(struct pinctrl_dev *pctldev, - unsigned int function, unsigned int group) -{ - struct max96752f_pinctrl *mpctl = pinctrl_dev_get_drvdata(pctldev); - struct function_desc *func; - struct group_desc *grp; - int i; - - func = pinmux_generic_get_function(pctldev, function); - if (!func) - return -EINVAL; - - grp = pinctrl_generic_get_group(pctldev, group); - if (!grp) - return -EINVAL; - - if (func->data) { - struct max96752f_function_data *fdata = func->data; - - for (i = 0; i < grp->num_pins; i++) { - regmap_update_bits(mpctl->regmap, GPIO_A_REG(grp->pins[i]), - GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN, - FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | - FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | - FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en)); - - if (fdata->gpio_tx_en) - regmap_update_bits(mpctl->regmap, GPIO_B_REG(grp->pins[i]), - GPIO_TX_ID, - FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); - - if (fdata->gpio_rx_en) - regmap_update_bits(mpctl->regmap, GPIO_C_REG(grp->pins[i]), - GPIO_RX_ID, - FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); - } - } - - if (grp->data) { - struct max96752f_group_data *gdata = grp->data; - - for (i = 0; i < gdata->num_configs; i++) { - const struct config_desc *config = &gdata->configs[i]; - - regmap_update_bits(mpctl->regmap, config->reg, - config->mask, config->val); - } - } - - dev_info(mpctl->dev, "enable function %s group %s\n", - func->name, grp->name); - - return 0; -} - -#define PIN_CONFIG_OLDI_SPL_EN (PIN_CONFIG_END + 1) -#define PIN_CONFIG_OLDI_SWAP_AB (PIN_CONFIG_END + 2) - -static const struct pinconf_generic_params max96752f_custom_params[] = { - { "oldi-spl-en", PIN_CONFIG_OLDI_SPL_EN, 0 }, - { "oldi-swap-ab", PIN_CONFIG_OLDI_SWAP_AB, 0 }, -}; - -#ifdef CONFIG_DEBUG_FS -static const struct pin_config_item -max96752f_custom_conf_items[ARRAY_SIZE(max96752f_custom_params)] = { - PCONFDUMP(PIN_CONFIG_OLDI_SPL_EN, "OLDI Splitter Enable", NULL, false), - PCONFDUMP(PIN_CONFIG_OLDI_SWAP_AB, "Swaps OLDI ports A and B", NULL, false), -}; -#endif - -static int max96752f_pinconf_get(struct pinctrl_dev *pctldev, - unsigned int pin, unsigned long *config) -{ - struct max96752f_pinctrl *mpctl = pinctrl_dev_get_drvdata(pctldev); - unsigned int param = pinconf_to_config_param(*config); - unsigned int gpio_a_reg, gpio_b_reg, oldi; - u16 arg = 0; - - regmap_read(mpctl->regmap, GPIO_A_REG(pin), &gpio_a_reg); - regmap_read(mpctl->regmap, GPIO_B_REG(pin), &gpio_b_reg); - if (pin == 0) - regmap_read(mpctl->regmap, OLDI_REG(1), &oldi); - - switch (param) { - case PIN_CONFIG_DRIVE_OPEN_DRAIN: - if (FIELD_GET(OUT_TYPE, gpio_b_reg)) - return -EINVAL; - break; - case PIN_CONFIG_DRIVE_PUSH_PULL: - if (!FIELD_GET(OUT_TYPE, gpio_b_reg)) - return -EINVAL; - break; - case PIN_CONFIG_BIAS_DISABLE: - if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 0) - return -EINVAL; - break; - case PIN_CONFIG_BIAS_PULL_UP: - if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 1) - return -EINVAL; - switch (FIELD_GET(RES_CFG, gpio_a_reg)) { - case 0: - arg = 40000; - break; - case 1: - arg = 10000; - break; - } - break; - case PIN_CONFIG_BIAS_PULL_DOWN: - if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 2) - return -EINVAL; - switch (FIELD_GET(RES_CFG, gpio_a_reg)) { - case 0: - arg = 40000; - break; - case 1: - arg = 10000; - break; - } - break; - case PIN_CONFIG_OUTPUT: - if (FIELD_GET(GPIO_OUT_DIS, gpio_a_reg)) - return -EINVAL; - - arg = FIELD_GET(GPIO_OUT, gpio_a_reg); - break; - case PIN_CONFIG_OLDI_SPL_EN: - if (pin > 0) - return -EINVAL; - - if (!FIELD_GET(OLDI_SPL_EN, oldi)) - return -EINVAL; - break; - case PIN_CONFIG_OLDI_SWAP_AB: - if (pin > 0) - return -EINVAL; - - if (!FIELD_GET(OLDI_SWAP_AB, oldi)) - return -EINVAL; - break; - default: - return -ENOTSUPP; - } - - *config = pinconf_to_config_packed(param, arg); - - return 0; -} - -static int max96752f_pinconf_set(struct pinctrl_dev *pctldev, - unsigned int pin, unsigned long *configs, - unsigned int num_configs) -{ - struct max96752f_pinctrl *mpctl = pinctrl_dev_get_drvdata(pctldev); - unsigned int param; - u32 arg; - u8 res_cfg; - int i; - - for (i = 0; i < num_configs; i++) { - param = pinconf_to_config_param(configs[i]); - arg = pinconf_to_config_argument(configs[i]); - - switch (param) { - case PIN_CONFIG_DRIVE_OPEN_DRAIN: - regmap_update_bits(mpctl->regmap, GPIO_B_REG(pin), - OUT_TYPE, FIELD_PREP(OUT_TYPE, 0)); - break; - case PIN_CONFIG_DRIVE_PUSH_PULL: - regmap_update_bits(mpctl->regmap, GPIO_B_REG(pin), - OUT_TYPE, FIELD_PREP(OUT_TYPE, 1)); - break; - case PIN_CONFIG_BIAS_DISABLE: - regmap_update_bits(mpctl->regmap, GPIO_C_REG(pin), - PULL_UPDN_SEL, - FIELD_PREP(PULL_UPDN_SEL, 0)); - break; - case PIN_CONFIG_BIAS_PULL_UP: - switch (arg) { - case 40000: - res_cfg = 0; - break; - case 1000000: - res_cfg = 1; - break; - default: - return -EINVAL; - } - - regmap_update_bits(mpctl->regmap, GPIO_A_REG(pin), - RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); - regmap_update_bits(mpctl->regmap, GPIO_C_REG(pin), - PULL_UPDN_SEL, - FIELD_PREP(PULL_UPDN_SEL, 1)); - break; - case PIN_CONFIG_BIAS_PULL_DOWN: - switch (arg) { - case 40000: - res_cfg = 0; - break; - case 1000000: - res_cfg = 1; - break; - default: - return -EINVAL; - } - - regmap_update_bits(mpctl->regmap, GPIO_A_REG(pin), - RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); - regmap_update_bits(mpctl->regmap, GPIO_C_REG(pin), - PULL_UPDN_SEL, - FIELD_PREP(PULL_UPDN_SEL, 2)); - break; - case PIN_CONFIG_OUTPUT: - regmap_update_bits(mpctl->regmap, GPIO_A_REG(pin), - GPIO_OUT_DIS | GPIO_OUT, - FIELD_PREP(GPIO_OUT_DIS, 0) | - FIELD_PREP(GPIO_OUT, arg)); - break; - case PIN_CONFIG_OLDI_SPL_EN: - if (pin > 0) - return -ENOTSUPP; - - regmap_update_bits(mpctl->regmap, OLDI_REG(1), - OLDI_SPL_EN | OLDI_SPL_POL, - FIELD_PREP(OLDI_SPL_EN, 1) | - FIELD_PREP(OLDI_SPL_POL, 0)); - break; - case PIN_CONFIG_OLDI_SWAP_AB: - if (pin > 0) - return -ENOTSUPP; - - regmap_update_bits(mpctl->regmap, OLDI_REG(1), - OLDI_SWAP_AB, - FIELD_PREP(OLDI_SWAP_AB, 1)); - break; - default: - return -ENOTSUPP; - } - } - - return 0; -} - -static const struct pinconf_ops max96752f_pinconf_ops = { - .is_generic = true, - .pin_config_get = max96752f_pinconf_get, - .pin_config_set = max96752f_pinconf_set, -}; - -static const struct pinmux_ops max96752f_pinmux_ops = { - .get_functions_count = pinmux_generic_get_function_count, - .get_function_name = pinmux_generic_get_function_name, - .get_function_groups = pinmux_generic_get_function_groups, - .set_mux = max96752f_pinmux_set_mux, -}; - -static const struct pinctrl_ops max96752f_pinctrl_ops = { - .get_groups_count = pinctrl_generic_get_group_count, - .get_group_name = pinctrl_generic_get_group_name, - .get_group_pins = pinctrl_generic_get_group_pins, - .dt_node_to_map = pinconf_generic_dt_node_to_map_all, - .dt_free_map = pinconf_generic_dt_free_map, -}; - -static const struct pinctrl_pin_desc max96752f_pins_desc[] = { - PINCTRL_PIN(0, "oldi"), - PINCTRL_PIN(1, "gpio1"), - PINCTRL_PIN(2, "gpio2"), - PINCTRL_PIN(3, "gpio3"), - PINCTRL_PIN(4, "gpio4"), - PINCTRL_PIN(5, "gpio5"), - PINCTRL_PIN(6, "gpio6"), - PINCTRL_PIN(7, "gpio7"), - PINCTRL_PIN(8, "gpio8"), - PINCTRL_PIN(9, "gpio9"), - PINCTRL_PIN(10, "gpio10"), - PINCTRL_PIN(11, "gpio11"), - PINCTRL_PIN(12, "gpio12"), - PINCTRL_PIN(13, "gpio13"), - PINCTRL_PIN(14, "gpio14"), - PINCTRL_PIN(15, "gpio15"), -}; - -static int oldi_pins[] = {0}; -static int gpio1_pins[] = {1}; -static int gpio2_pins[] = {2}; -static int gpio3_pins[] = {3}; -static int gpio4_pins[] = {4}; -static int gpio5_pins[] = {5}; -static int gpio6_pins[] = {6}; -static int gpio7_pins[] = {7}; -static int gpio8_pins[] = {8}; -static int gpio9_pins[] = {9}; -static int gpio10_pins[] = {10}; -static int gpio11_pins[] = {11}; -static int gpio12_pins[] = {12}; -static int gpio13_pins[] = {13}; -static int gpio14_pins[] = {14}; -static int gpio15_pins[] = {15}; -static int aud_rx_pins[] = {6, 7, 8}; -static int aud_tx_pins[] = {11, 12, 13}; -static int i2c_pins[] = {14, 15}; -static int uart_pins[] = {14, 15}; - -#define GROUP_DESC(nm) \ -{ \ - .name = #nm, \ - .pins = nm ## _pins, \ - .num_pins = ARRAY_SIZE(nm ## _pins), \ -} - -#define GROUP_DESC_CONFIG(nm) \ -{ \ - .name = #nm, \ - .pins = nm ## _pins, \ - .num_pins = ARRAY_SIZE(nm ## _pins), \ - .data = (void *)(const struct max96752f_group_data []) { \ - { \ - .configs = nm ## _configs, \ - .num_configs = ARRAY_SIZE(nm ## _configs), \ - } \ - }, \ -} - -static const struct config_desc gpio6_configs[] = { - { 0x0001, IIC_2_EN, 0 }, - { 0x0002, AUD_TX_EN, 0 }, -}; -static const struct config_desc gpio7_configs[] = { - { 0x0002, AUD_TX_EN, 0 }, -}; -static const struct config_desc gpio8_configs[] = { - { 0x0001, IIC_2_EN, 0 }, - { 0x0002, AUD_TX_EN, 0 }, -}; -static const struct config_desc gpio11_configs[] = { - { 0x0140, AUD_RX_EN, 0 }, -}; -static const struct config_desc gpio12_configs[] = { - { 0x0140, AUD_RX_EN, 0 }, -}; -static const struct config_desc gpio13_configs[] = { - { 0x0140, AUD_RX_EN, 0 }, -}; -static const struct config_desc gpio14_configs[] = { - { 0x0002, DIS_LOCAL_CC, DIS_LOCAL_CC }, -}; -static const struct config_desc gpio15_configs[] = { - { 0x0002, DIS_LOCAL_CC, DIS_LOCAL_CC }, -}; -static const struct config_desc aud_tx_configs[] = { - { 0x0002, AUD_TX_EN, AUD_TX_EN }, -}; -static const struct config_desc aud_rx_configs[] = { - { 0x0140, AUD_RX_EN, AUD_RX_EN }, -}; -static const struct config_desc i2c_configs[] = { - { 0x0002, DIS_LOCAL_CC, 0 }, - { 0x0003, I2CSEL, I2CSEL }, -}; -static const struct config_desc uart_configs[] = { - { 0x0002, DIS_LOCAL_CC, 0 }, - { 0x0003, I2CSEL, 0 }, -}; - -static const struct group_desc max96752f_groups[] = { - GROUP_DESC(gpio1), - GROUP_DESC(gpio2), - GROUP_DESC(gpio3), - GROUP_DESC(gpio4), - GROUP_DESC(gpio5), - GROUP_DESC_CONFIG(gpio6), - GROUP_DESC_CONFIG(gpio7), - GROUP_DESC_CONFIG(gpio8), - GROUP_DESC(gpio9), - GROUP_DESC(gpio10), - GROUP_DESC_CONFIG(gpio11), - GROUP_DESC_CONFIG(gpio12), - GROUP_DESC_CONFIG(gpio13), - GROUP_DESC_CONFIG(gpio14), - GROUP_DESC_CONFIG(gpio15), - GROUP_DESC_CONFIG(aud_rx), - GROUP_DESC_CONFIG(aud_tx), - GROUP_DESC_CONFIG(i2c), - GROUP_DESC_CONFIG(uart), - GROUP_DESC(oldi), -}; -static const char *gpio_groups[] = { - "reserved", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", - "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", - "gpio11", "gpio12", "gpio13", "gpio14", "gpio15", -}; -static const char *aud_rx_groups[] = { "aud_rx" }; -static const char *aud_tx_groups[] = { "aud_tx" }; -static const char *i2c_groups[] = { "i2c" }; -static const char *uart_groups[] = { "uart" }; -static const char *oldi_groups[] = { "oldi" }; - -#define FUNCTION_DESC(fname, gname) \ -{ \ - .name = #fname, \ - .group_names = gname##_groups, \ - .num_group_names = ARRAY_SIZE(gname##_groups), \ -} \ - -#define FUNCTION_DESC_GPIO() \ -{ \ - .name = "GPIO", \ - .group_names = gpio_groups, \ - .num_group_names = ARRAY_SIZE(gpio_groups), \ - .data = (void *)(const struct max96752f_function_data []) { \ - { } \ - }, \ -} \ - -#define FUNCTION_DESC_GPIO_RX(id) \ -{ \ - .name = "GPIO_RX_"#id, \ - .group_names = gpio_groups, \ - .num_group_names = ARRAY_SIZE(gpio_groups), \ - .data = (void *)(const struct max96752f_function_data []) { \ - { .gpio_rx_en = 1, .gpio_rx_id = id } \ - }, \ -} \ - -#define FUNCTION_DESC_GPIO_TX(id) \ -{ \ - .name = "GPIO_TX_"#id, \ - .group_names = gpio_groups, \ - .num_group_names = ARRAY_SIZE(gpio_groups), \ - .data = (void *)(const struct max96752f_function_data []) { \ - { .gpio_out_dis = 1, .gpio_tx_en = 1, .gpio_tx_id = id } \ - }, \ -} \ - -static const struct function_desc max96752f_functions[] = { - FUNCTION_DESC_GPIO_TX(0), - FUNCTION_DESC_GPIO_TX(1), - FUNCTION_DESC_GPIO_TX(2), - FUNCTION_DESC_GPIO_TX(3), - FUNCTION_DESC_GPIO_TX(4), - FUNCTION_DESC_GPIO_TX(5), - FUNCTION_DESC_GPIO_TX(6), - FUNCTION_DESC_GPIO_TX(7), - FUNCTION_DESC_GPIO_TX(8), - FUNCTION_DESC_GPIO_TX(9), - FUNCTION_DESC_GPIO_TX(10), - FUNCTION_DESC_GPIO_TX(11), - FUNCTION_DESC_GPIO_TX(12), - FUNCTION_DESC_GPIO_TX(13), - FUNCTION_DESC_GPIO_TX(14), - FUNCTION_DESC_GPIO_TX(15), - FUNCTION_DESC_GPIO_TX(16), - FUNCTION_DESC_GPIO_TX(17), - FUNCTION_DESC_GPIO_TX(18), - FUNCTION_DESC_GPIO_TX(19), - FUNCTION_DESC_GPIO_TX(20), - FUNCTION_DESC_GPIO_TX(21), - FUNCTION_DESC_GPIO_TX(22), - FUNCTION_DESC_GPIO_TX(23), - FUNCTION_DESC_GPIO_TX(24), - FUNCTION_DESC_GPIO_TX(25), - FUNCTION_DESC_GPIO_TX(26), - FUNCTION_DESC_GPIO_TX(27), - FUNCTION_DESC_GPIO_TX(28), - FUNCTION_DESC_GPIO_TX(29), - FUNCTION_DESC_GPIO_TX(30), - FUNCTION_DESC_GPIO_TX(31), - FUNCTION_DESC_GPIO_RX(0), - FUNCTION_DESC_GPIO_RX(1), - FUNCTION_DESC_GPIO_RX(2), - FUNCTION_DESC_GPIO_RX(3), - FUNCTION_DESC_GPIO_RX(4), - FUNCTION_DESC_GPIO_RX(5), - FUNCTION_DESC_GPIO_RX(6), - FUNCTION_DESC_GPIO_RX(7), - FUNCTION_DESC_GPIO_RX(8), - FUNCTION_DESC_GPIO_RX(9), - FUNCTION_DESC_GPIO_RX(10), - FUNCTION_DESC_GPIO_RX(11), - FUNCTION_DESC_GPIO_RX(12), - FUNCTION_DESC_GPIO_RX(13), - FUNCTION_DESC_GPIO_RX(14), - FUNCTION_DESC_GPIO_RX(15), - FUNCTION_DESC_GPIO_RX(16), - FUNCTION_DESC_GPIO_RX(17), - FUNCTION_DESC_GPIO_RX(18), - FUNCTION_DESC_GPIO_RX(19), - FUNCTION_DESC_GPIO_RX(20), - FUNCTION_DESC_GPIO_RX(21), - FUNCTION_DESC_GPIO_RX(22), - FUNCTION_DESC_GPIO_RX(23), - FUNCTION_DESC_GPIO_RX(24), - FUNCTION_DESC_GPIO_RX(25), - FUNCTION_DESC_GPIO_RX(26), - FUNCTION_DESC_GPIO_RX(27), - FUNCTION_DESC_GPIO_RX(28), - FUNCTION_DESC_GPIO_RX(29), - FUNCTION_DESC_GPIO_RX(30), - FUNCTION_DESC_GPIO_RX(31), - FUNCTION_DESC_GPIO(), - FUNCTION_DESC(AUD_RX, aud_rx), - FUNCTION_DESC(AUD_TX, aud_tx), - FUNCTION_DESC(I2C, i2c), - FUNCTION_DESC(UART, uart), - FUNCTION_DESC(OLDI, oldi), -}; - -static int max96752f_pinctrl_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct max96752f_pinctrl *mpctl; - struct pinctrl_desc *pctl_desc; - int i, ret; - - mpctl = devm_kzalloc(dev, sizeof(*mpctl), GFP_KERNEL); - if (!mpctl) - return -ENOMEM; - - mpctl->dev = dev; - platform_set_drvdata(pdev, mpctl); - - mpctl->regmap = dev_get_regmap(dev->parent, NULL); - if (!mpctl->regmap) - return dev_err_probe(dev, -ENODEV, "failed to get regmap\n"); - - pctl_desc = devm_kzalloc(dev, sizeof(*pctl_desc), GFP_KERNEL); - if (!pctl_desc) - return -ENOMEM; - - pctl_desc->name = dev_name(dev); - pctl_desc->owner = THIS_MODULE; - pctl_desc->pctlops = &max96752f_pinctrl_ops; - pctl_desc->pmxops = &max96752f_pinmux_ops; - pctl_desc->confops = &max96752f_pinconf_ops; - pctl_desc->pins = max96752f_pins_desc; - pctl_desc->npins = ARRAY_SIZE(max96752f_pins_desc); - pctl_desc->custom_params = max96752f_custom_params; - pctl_desc->num_custom_params = ARRAY_SIZE(max96752f_custom_params); -#ifdef CONFIG_DEBUG_FS - pctl_desc->custom_conf_items = max96752f_custom_conf_items, -#endif - ret = devm_pinctrl_register_and_init(dev, pctl_desc, mpctl, - &mpctl->pctl); - if (ret) - return dev_err_probe(dev, ret, "failed to register pinctrl\n"); - - for (i = 0; i < ARRAY_SIZE(max96752f_groups); i++) { - const struct group_desc *group = &max96752f_groups[i]; - - ret = pinctrl_generic_add_group(mpctl->pctl, group->name, - group->pins, group->num_pins, - group->data); - if (ret < 0) - return dev_err_probe(dev, ret, - "failed to register group %s\n", - group->name); - } - - for (i = 0; i < ARRAY_SIZE(max96752f_functions); i++) { - const struct function_desc *func = &max96752f_functions[i]; - - ret = pinmux_generic_add_function(mpctl->pctl, func->name, - func->group_names, - func->num_group_names, - func->data); - if (ret < 0) - return dev_err_probe(dev, ret, - "failed to register function %s\n", - func->name); - } - - return pinctrl_enable(mpctl->pctl); -} - -static const struct of_device_id max96752f_pinctrl_of_match[] = { - { .compatible = "maxim,max96752f-pinctrl" }, - {} -}; -MODULE_DEVICE_TABLE(of, max96752f_pinctrl_of_match); - -static struct platform_driver max96752f_pinctrl_driver = { - .driver = { - .name = "max96752f-pinctrl", - .of_match_table = max96752f_pinctrl_of_match, - }, - .probe = max96752f_pinctrl_probe, -}; - -module_platform_driver(max96752f_pinctrl_driver); - -MODULE_AUTHOR("Wyon Bi "); -MODULE_DESCRIPTION("Maxim MAX96752F pin control driver"); -MODULE_LICENSE("GPL"); From 65358f283cbd31432c538b0bcd3feda0a318de81 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 22 Nov 2022 08:29:21 +0000 Subject: [PATCH 121/235] Revert "drm/bridge: Add support for Maxim MAX96752F" This reverts commit 24af5158d97872491ae610298f7ee6440ef17cd0. Delete this unused driver. Signed-off-by: Wyon Bi Change-Id: I8b674c8b65bcd83e3d1be3c0dcc68fdf0e7f07ed --- drivers/gpu/drm/bridge/Kconfig | 11 - drivers/gpu/drm/bridge/Makefile | 1 - drivers/gpu/drm/bridge/maxim-max96752f.c | 251 ----------------------- 3 files changed, 263 deletions(-) delete mode 100644 drivers/gpu/drm/bridge/maxim-max96752f.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 736dfc12e321..36d2b19dc034 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -93,17 +93,6 @@ config DRM_MAXIM_MAX96745 help Driver for Maxim MAX96745 GMSL2 Serializer with eDP1.4a/DP1.4 Input. -config DRM_MAXIM_MAX96752F - tristate "Maxim max96752F GMSL2 Deserializer" - depends on OF - select MFD_MAX96752F - select PINCTRL_MAX96752F - select GPIO_MAX96752F - select DRM_KMS_HELPER - select DRM_PANEL - help - Driver for Maxim MAX96752F GMSL2 Deserializer with Dual LVDS Output. - config DRM_MAXIM_MAX96755F tristate "Maxim max96755 GMSL2 Serializer" depends on OF diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index bf384678fc6d..96118fd44176 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -6,7 +6,6 @@ obj-$(CONFIG_DRM_ITE_IT6161) += ite-it6161.o obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o obj-$(CONFIG_DRM_MAXIM_MAX96745) += maxim-max96745.o -obj-$(CONFIG_DRM_MAXIM_MAX96752F) += maxim-max96752f.o obj-$(CONFIG_DRM_MAXIM_MAX96755F) += maxim-max96755f.o obj-$(CONFIG_DRM_MAXIM_MAX96776) += maxim-max96776.o obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o diff --git a/drivers/gpu/drm/bridge/maxim-max96752f.c b/drivers/gpu/drm/bridge/maxim-max96752f.c deleted file mode 100644 index c0980c03daaf..000000000000 --- a/drivers/gpu/drm/bridge/maxim-max96752f.c +++ /dev/null @@ -1,251 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Maxim MAX96752F GMSL2 Deserializer with Dual LVDS (OLDI) Output - * - * Copyright (c) 2022 Rockchip Electronics Co. Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -struct max96752f_bridge { - struct drm_bridge bridge; - struct drm_bridge *next_bridge; - struct drm_panel *panel; - - struct device *dev; - struct max96752f *parent; - struct regmap *regmap; -}; - -#define to_max96752f_bridge(x) container_of(x, struct max96752f_bridge, x) - -static int max96752f_bridge_get_modes(struct drm_bridge *bridge, - struct drm_connector *connector) -{ - struct max96752f_bridge *des = to_max96752f_bridge(bridge); - - if (des->next_bridge) - return drm_bridge_get_modes(des->next_bridge, connector); - - return drm_panel_get_modes(des->panel, connector); -} - -static void -max96752f_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) -{ - struct max96752f_bridge *des = to_max96752f_bridge(bridge); - struct drm_atomic_state *state = old_bridge_state->base.state; - const struct drm_bridge_state *bridge_state; - bool oldi_format; - - max96752f_init(des->parent); - - bridge_state = drm_atomic_get_new_bridge_state(state, bridge); - switch (bridge_state->output_bus_cfg.format) { - case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: - case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: - oldi_format = 0x0; - break; - case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: - oldi_format = 0x1; - break; - default: - oldi_format = 0x1; - dev_warn(des->dev, - "unsupported LVDS bus format 0x%04x, using VESA\n", - bridge_state->output_bus_cfg.format); - break; - } - - regmap_update_bits(des->regmap, OLDI_REG(1), OLDI_FORMAT, - FIELD_PREP(OLDI_FORMAT, oldi_format)); - - if (des->panel) - drm_panel_prepare(des->panel); -} - -static void -max96752f_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) -{ - struct max96752f_bridge *des = to_max96752f_bridge(bridge); - - regmap_update_bits(des->regmap, 0x0002, VID_EN, - FIELD_PREP(VID_EN, 1)); - - if (des->panel) - drm_panel_enable(des->panel); -} - -static void -max96752f_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) -{ - struct max96752f_bridge *des = to_max96752f_bridge(bridge); - - if (des->panel) - drm_panel_disable(des->panel); - - regmap_update_bits(des->regmap, 0x0002, VID_EN, - FIELD_PREP(VID_EN, 0)); -} - -static void -max96752f_bridge_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) -{ - struct max96752f_bridge *des = to_max96752f_bridge(bridge); - - if (des->panel) - drm_panel_unprepare(des->panel); -} - -static u32 * -max96752f_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state, - unsigned int *num_output_fmts) -{ - struct drm_connector *connector = conn_state->connector; - u32 *out_bus_fmts; - - out_bus_fmts = kzalloc(sizeof(*out_bus_fmts), GFP_KERNEL); - if (!out_bus_fmts) { - *num_output_fmts = 0; - return NULL; - } - - *num_output_fmts = 1; - - if (connector->display_info.num_bus_formats && connector->display_info.bus_formats) - out_bus_fmts[0] = connector->display_info.bus_formats[0]; - else - out_bus_fmts[0] = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG; - - return out_bus_fmts; -} - -static bool max96752f_bridge_video_locked(struct max96752f_bridge *des) -{ - u32 val; - - if (regmap_read(des->regmap, 0x0003, &val)) - return false; - - if (!FIELD_GET(VIDEO_LOCK, val)) - return false; - - return true; -} - -static int max96752f_bridge_attach(struct drm_bridge *bridge, - enum drm_bridge_attach_flags flags) -{ - struct max96752f_bridge *des = to_max96752f_bridge(bridge); - int ret; - - ret = drm_of_find_panel_or_bridge(bridge->of_node, 1, -1, &des->panel, - &des->next_bridge); - if (ret) - return ret; - - if (max96752f_bridge_video_locked(des)) { - if (des->panel) { - drm_panel_prepare(des->panel); - drm_panel_enable(des->panel); - } - } - - if (des->next_bridge) - return drm_bridge_attach(bridge->encoder, des->next_bridge, - bridge, 0); - - return 0; -} - -static const struct drm_bridge_funcs max96752f_bridge_funcs = { - .attach = max96752f_bridge_attach, - .get_modes = max96752f_bridge_get_modes, - .atomic_pre_enable = max96752f_bridge_atomic_pre_enable, - .atomic_post_disable = max96752f_bridge_atomic_post_disable, - .atomic_enable = max96752f_bridge_atomic_enable, - .atomic_disable = max96752f_bridge_atomic_disable, - .atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt, - .atomic_get_output_bus_fmts = max96752f_bridge_atomic_get_output_bus_fmts, - .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, - .atomic_reset = drm_atomic_helper_bridge_reset, -}; - -static int max96752f_bridge_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct max96752f_bridge *des; - - des = devm_kzalloc(dev, sizeof(*des), GFP_KERNEL); - if (!des) - return -ENOMEM; - - des->dev = dev; - des->parent = dev_get_drvdata(dev->parent); - platform_set_drvdata(pdev, des); - - des->regmap = dev_get_regmap(dev->parent, NULL); - if (!des->regmap) - return dev_err_probe(dev, -ENODEV, "failed to get regmap\n"); - - des->bridge.funcs = &max96752f_bridge_funcs; - des->bridge.of_node = dev->of_node; - des->bridge.ops = DRM_BRIDGE_OP_MODES; - des->bridge.type = DRM_MODE_CONNECTOR_LVDS; - - drm_bridge_add(&des->bridge); - - return 0; -} - -static int max96752f_bridge_remove(struct platform_device *pdev) -{ - struct max96752f_bridge *des = platform_get_drvdata(pdev); - - drm_bridge_remove(&des->bridge); - - return 0; -} - -static const struct of_device_id max96752f_bridge_of_match[] = { - { .compatible = "maxim,max96752f-bridge" }, - {} -}; -MODULE_DEVICE_TABLE(of, max96752f_bridge_of_match); - -static struct platform_driver max96752f_bridge_driver = { - .driver = { - .name = "max96752f-bridge", - .of_match_table = max96752f_bridge_of_match, - }, - .probe = max96752f_bridge_probe, - .remove = max96752f_bridge_remove, -}; - -module_platform_driver(max96752f_bridge_driver); - -MODULE_AUTHOR("Wyon Bi "); -MODULE_DESCRIPTION("Maxim MAX96752F GMSL2 Deserializer with Dual LVDS (OLDI) Output"); -MODULE_LICENSE("GPL"); From 9cd192293f95533131e237c23b2dd96e0e86b613 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 22 Nov 2022 08:06:35 +0000 Subject: [PATCH 122/235] Revert "mfd: Add support for Maxim MAX96752F" This reverts commit ad3d90b0bad420085c681ff8bb6db6365982c6ae. Delete this unused driver. Signed-off-by: Wyon Bi Change-Id: Ie3f71ea9cfb53751e7f1370ca95acfe9726e9696 --- drivers/mfd/Kconfig | 9 -- drivers/mfd/Makefile | 1 - drivers/mfd/max96752f.c | 205 ---------------------------------- include/linux/mfd/max96752f.h | 114 ------------------- 4 files changed, 329 deletions(-) delete mode 100644 drivers/mfd/max96752f.c delete mode 100644 include/linux/mfd/max96752f.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9d3d6ca083c2..72eabcbc742e 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -930,15 +930,6 @@ config MFD_MAX96745 help Say yes here to add support for Maxim Semiconductor MAX96745. -config MFD_MAX96752F - tristate "Maxim Semiconductor MAX96752F GMSL2 Deserializer Support" - depends on I2C - select MFD_CORE - select REGMAP_I2C - select I2C_MUX - help - Say yes here to add support for Maxim Semiconductor MAX96752F. - config MFD_MAX96755F tristate "Maxim Semiconductor MAX96755 GMSL2 Serializer Support" depends on I2C diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 6ae9047e3652..e723deea8f45 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -171,7 +171,6 @@ obj-$(CONFIG_MFD_MAX8925) += max8925.o obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o obj-$(CONFIG_MFD_MAX96745) += max96745.o -obj-$(CONFIG_MFD_MAX96752F) += max96752f.o obj-$(CONFIG_MFD_MAX96755F) += max96755f.o obj-$(CONFIG_MFD_MAX96776) += max96776.o diff --git a/drivers/mfd/max96752f.c b/drivers/mfd/max96752f.c deleted file mode 100644 index 4fe239f10fb5..000000000000 --- a/drivers/mfd/max96752f.c +++ /dev/null @@ -1,205 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Maxim MAX96752F MFD driver - * - * Copyright (C) 2022 Rockchip Electronics Co. Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static const struct mfd_cell max96752f_devs[] = { - { - .name = "max96752f-pinctrl", - .of_compatible = "maxim,max96752f-pinctrl", - }, { - .name = "max96752f-gpio", - .of_compatible = "maxim,max96752f-gpio", - }, { - .name = "max96752f-bridge", - .of_compatible = "maxim,max96752f-bridge", - }, -}; - -static int max96752f_select(struct i2c_mux_core *muxc, u32 chan) -{ - return 0; -} - -static const struct regmap_config max96752f_regmap_config = { - .name = "max96752f", - .reg_bits = 16, - .val_bits = 8, - .max_register = 0x25d, -}; - -static const unsigned short addr_list[] = { - 0x48, 0x4a, 0x4c, 0x68, 0x6a, 0x6c, 0x28, 0x2a, I2C_CLIENT_END -}; - -void max96752f_init(struct max96752f *max96752f) -{ - struct i2c_client *client = max96752f->client; - u16 addr = client->addr; - u32 id; - int i, ret; - - for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { - client->addr = addr_list[i]; - ret = regmap_read(max96752f->regmap, 0x000d, &id); - if (ret < 0) - continue; - - if (id == 0x82) { - regmap_write(max96752f->regmap, 0x0000, addr << 1); - break; - } - } - - client->addr = addr; - - regmap_update_bits(max96752f->regmap, 0x0050, STR_SEL, - FIELD_PREP(STR_SEL, max96752f->stream_id)); - regmap_update_bits(max96752f->regmap, 0x0073, TX_SRC_ID, - FIELD_PREP(TX_SRC_ID, max96752f->stream_id)); -} -EXPORT_SYMBOL(max96752f_init); - -static void max96752f_power_on(struct max96752f *max96752f) -{ - if (max96752f->enable_gpio) { - gpiod_direction_output(max96752f->enable_gpio, 1); - msleep(500); - } -} - -static void max96752f_power_off(struct max96752f *max96752f) -{ - if (max96752f->enable_gpio) - gpiod_direction_output(max96752f->enable_gpio, 0); -} - -static int max96752f_i2c_probe(struct i2c_client *client) -{ - struct device *dev = &client->dev; - struct device_node *child; - struct max96752f *max96752f; - unsigned int nr = 0; - int ret; - - for_each_available_child_of_node(dev->of_node, child) { - if (!of_find_property(child, "reg", NULL)) - continue; - - nr++; - } - - max96752f = devm_kzalloc(dev, sizeof(*max96752f), GFP_KERNEL); - if (!max96752f) - return -ENOMEM; - - max96752f->muxc = i2c_mux_alloc(client->adapter, dev, nr, 0, - I2C_MUX_LOCKED, max96752f_select, NULL); - if (!max96752f->muxc) - return -ENOMEM; - - max96752f->dev = dev; - max96752f->client = client; - - max96752f->enable_gpio = devm_gpiod_get_optional(dev, "enable", - GPIOD_ASIS); - if (IS_ERR(max96752f->enable_gpio)) - return dev_err_probe(dev, PTR_ERR(max96752f->enable_gpio), - "failed to get enable GPIO\n"); - - ret = device_property_read_u32(dev->parent, "reg", &max96752f->stream_id); - if (ret) - return dev_err_probe(dev, ret, "failed to get gmsl id\n"); - - i2c_set_clientdata(client, max96752f); - - max96752f->regmap = devm_regmap_init_i2c(client, - &max96752f_regmap_config); - if (IS_ERR(max96752f->regmap)) - return dev_err_probe(dev, PTR_ERR(max96752f->regmap), - "failed to initialize regmap\n"); - - max96752f_power_on(max96752f); - max96752f_init(max96752f); - - ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, max96752f_devs, - ARRAY_SIZE(max96752f_devs), NULL, 0, NULL); - if (ret) - return ret; - - for_each_available_child_of_node(dev->of_node, child) { - if (of_property_read_u32(child, "reg", &nr)) - continue; - - ret = i2c_mux_add_adapter(max96752f->muxc, 0, nr, 0); - if (ret) { - i2c_mux_del_adapters(max96752f->muxc); - return ret; - } - } - - return 0; -} - -static void max96752f_i2c_shutdown(struct i2c_client *client) -{ - struct max96752f *max96752f = i2c_get_clientdata(client); - - regmap_update_bits(max96752f->regmap, 0x0010, RESET_ALL, - FIELD_PREP(RESET_ALL, 1)); - - max96752f_power_off(max96752f); -} - -static int __maybe_unused max96752f_suspend(struct device *dev) -{ - struct max96752f *max96752f = dev_get_drvdata(dev); - - max96752f_power_off(max96752f); - - return 0; -} - -static int __maybe_unused max96752f_resume(struct device *dev) -{ - struct max96752f *max96752f = dev_get_drvdata(dev); - - max96752f_power_on(max96752f); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(max96752f_pm_ops, max96752f_suspend, max96752f_resume); - -static const struct of_device_id max96752f_of_match[] = { - { .compatible = "maxim,max96752f", }, - {} -}; -MODULE_DEVICE_TABLE(of, max96752f_of_match); - -static struct i2c_driver max96752f_i2c_driver = { - .driver = { - .name = "max96752f", - .of_match_table = of_match_ptr(max96752f_of_match), - .pm = &max96752f_pm_ops, - }, - .probe_new = max96752f_i2c_probe, - .shutdown = max96752f_i2c_shutdown, -}; - -module_i2c_driver(max96752f_i2c_driver); - -MODULE_AUTHOR("Wyon Bi "); -MODULE_DESCRIPTION("Maxim MAX96752F MFD driver"); -MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/max96752f.h b/include/linux/mfd/max96752f.h deleted file mode 100644 index 78cc3f6b7dae..000000000000 --- a/include/linux/mfd/max96752f.h +++ /dev/null @@ -1,114 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Defining registers address and its bit definitions of MAX96752F - * - * Copyright (c) 2022 Rockchip Electronics Co. Ltd. - */ - -#ifndef _MFD_MAX96752F_H_ -#define _MFD_MAX96752F_H_ - -#include - -#define GPIO_A_REG(gpio) (0x0200 + ((gpio) * 3)) -#define GPIO_B_REG(gpio) (0x0201 + ((gpio) * 3)) -#define GPIO_C_REG(gpio) (0x0202 + ((gpio) * 3)) -#define OLDI_REG(x) (0x01cd + (x)) - -/* 0000h */ -#define DEV_ADDR GENMASK(7, 1) -#define CFG_BLOCK BIT(0) - -/* 0001h */ -#define LVDS_HALFSW BIT(7) -#define IIC_2_EN BIT(5) -#define IIC_1_EN BIT(4) -#define TX_RATE GENMASK(3, 2) -#define RX_RATE GENMASK(1, 0) - -/* 0002h */ -#define LOCK_CFG BIT(7) -#define VID_EN BIT(6) -#define DIS_LOCAL_CC BIT(5) -#define DIS_REM_CC BIT(4) -#define AUD_TX_EN BIT(2) - -/* 0003h */ -#define GMSL2 BIT(5) -#define I2CSEL BIT(4) -#define UART_2_EN BIT(3) -#define UART_1_EN BIT(2) -#define VIDEO_LOCK BIT(0) - -/* 000Dh */ -#define DEV_ID GENMASK(7, 0) - -/* 000Eh */ -#define DEV_REV GENMASK(3, 0) - -/* 0010h */ -#define RESET_ALL BIT(7) -#define RESET_LINK BIT(6) -#define RESET_ONESHOT BIT(5) -#define AUTO_LINK BIT(4) -#define SLEEP BIT(3) -#define LINK_CFG GENMASK(1, 0) - -/* 0050h */ -#define STR_SEL GENMASK(1, 0) - -/* 0073h */ -#define TX_SRC_ID GENMASK(2, 0) - -/* 0108h */ -#define VID_LOCK BIT(6) - -/* 0140h */ -#define AUD_RX_EN BIT(0) - -/* 01CEh */ -#define OLDI_OUTSEL BIT(7) -#define OLDI_FORMAT BIT(6) -#define OLDI_4TH_LANE BIT(5) -#define OLDI_SWAP_AB BIT(4) -#define OLDI_SPL_EN BIT(3) -#define OLDI_SPL_MODE GENMASK(2, 1) -#define OLDI_SPL_POL BIT(0) - -/* 01CFh */ -#define PD_LVDS_B BIT(7) -#define PD_LVDS_A BIT(6) -#define OLDI_DUP BIT(1) -#define SSEN BIT(0) - -/* 0200h */ -#define RES_CFG BIT(7) -#define TX_PRIO BIT(6) -#define TX_COMP_EN BIT(5) -#define GPIO_OUT BIT(4) -#define GPIO_IN BIT(3) -#define GPIO_RX_EN BIT(2) -#define GPIO_TX_EN BIT(1) -#define GPIO_OUT_DIS BIT(0) - -/* 0201h */ -#define PULL_UPDN_SEL GENMASK(7, 6) -#define OUT_TYPE BIT(5) -#define GPIO_TX_ID GENMASK(4, 0) - -/* 0202h */ -#define OVR_RES_CFG BIT(7) -#define GPIO_RX_ID GENMASK(4, 0) - -struct max96752f { - struct device *dev; - struct regmap *regmap; - struct i2c_client *client; - struct i2c_mux_core *muxc; - struct gpio_desc *enable_gpio; - u32 stream_id; -}; - -void max96752f_init(struct max96752f *max96752f); - -#endif /* _MFD_MAX96752F_H_ */ From 027cd3ac124c9e5623c93050903e2a54a231415a Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 22 Nov 2022 08:37:13 +0000 Subject: [PATCH 123/235] Revert "drm/bridge: Add support for Maxim MAX96776" This reverts commit ecc6097c8dbda36061dbb3bdc5597f1838713f9e. Delete this unused driver. Signed-off-by: Wyon Bi Change-Id: Ie6af8864560413df85e14b5c1d00df19ca0142ba --- drivers/gpu/drm/bridge/Kconfig | 9 - drivers/gpu/drm/bridge/Makefile | 2 +- drivers/gpu/drm/bridge/maxim-max96776.c | 587 ------------------------ 3 files changed, 1 insertion(+), 597 deletions(-) delete mode 100644 drivers/gpu/drm/bridge/maxim-max96776.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 36d2b19dc034..3748bff9ba83 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -103,15 +103,6 @@ config DRM_MAXIM_MAX96755F help Driver for Maxim MAX96755F GMSL2 Serializer with MIPI-DSI Input. -config DRM_MAXIM_MAX96776 - tristate "Maxim max96776 GMSL2 Deserializer" - depends on OF - select MFD_MAX96776 - select DRM_KMS_HELPER - select DRM_PANEL - help - Driver for Maxim MAX96776 GMSL2 Deserializer with eDP Output. - config DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW tristate "MegaChips stdp4028-ge-b850v3-fw and stdp2690-ge-b850v3-fw" depends on OF diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 96118fd44176..834d4d3b812e 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o obj-$(CONFIG_DRM_MAXIM_MAX96745) += maxim-max96745.o obj-$(CONFIG_DRM_MAXIM_MAX96755F) += maxim-max96755f.o -obj-$(CONFIG_DRM_MAXIM_MAX96776) += maxim-max96776.o obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o @@ -30,6 +29,7 @@ obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o + obj-y += analogix/ obj-y += cadence/ obj-y += synopsys/ diff --git a/drivers/gpu/drm/bridge/maxim-max96776.c b/drivers/gpu/drm/bridge/maxim-max96776.c deleted file mode 100644 index 11afc02425df..000000000000 --- a/drivers/gpu/drm/bridge/maxim-max96776.c +++ /dev/null @@ -1,587 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Maxim max96776 GMSL2 Deserializer with eDP Output - * - * Copyright (c) 2022 Rockchip Electronics Co. Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff) -#define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff) -#define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f) -#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) - -enum link_lane_count { - USE_ONE_LINK = 1, - USE_TWO_LINK = 2, - USE_FOUR_LINK = 4 -}; - -enum link_rate { - BW_1_62, - BW_2_7, - BW_5_4, -}; - -struct max96776_bridge { - struct drm_bridge bridge; - struct drm_bridge *next_bridge; - struct drm_panel *panel; - struct drm_display_mode mode; - - struct device *dev; - struct max96776 *parent; - struct regmap *regmap; - struct drm_dp_aux aux; - u8 link_rate; - u8 lane_count; - int max_link_rate; - enum link_lane_count max_lane_count; -}; - -static const struct reg_sequence max96776_clk_ref[3][14] = { - /* 1.62Gbps */ - { - { 0xe7b2, 0x50 }, - { 0xe7b3, 0x00 }, - { 0xe7b4, 0xcc }, - { 0xe7b5, 0x44 }, - { 0xe7b6, 0x81 }, - { 0xe7b7, 0x30 }, - { 0xe7b8, 0x07 }, - { 0xe7b9, 0x10 }, - { 0xe7ba, 0x01 }, - { 0xe7bb, 0x00 }, - { 0xe7bc, 0x00 }, - { 0xe7bd, 0x00 }, - { 0xe7be, 0x52 }, - { 0xe7bf, 0x00 }, - }, - - /* 2.7Gbps */ - { - { 0xe7b2, 0x50 }, - { 0xe7b3, 0x00 }, - { 0xe7b4, 0x00 }, - { 0xe7b5, 0x40 }, - { 0xe7b6, 0x6c }, - { 0xe7b7, 0x20 }, - { 0xe7b8, 0x07 }, - { 0xe7b9, 0x00 }, - { 0xe7ba, 0x01 }, - { 0xe7bb, 0x00 }, - { 0xe7bc, 0x00 }, - { 0xe7bd, 0x00 }, - { 0xe7be, 0x52 }, - { 0xe7bf, 0x00 }, - }, - - /* 5.4Gbps */ - { - { 0xe7b2, 0x30 }, - { 0xe7b3, 0x00 }, - { 0xe7b4, 0x00 }, - { 0xe7b5, 0x40 }, - { 0xe7b6, 0x6c }, - { 0xe7b7, 0x20 }, - { 0xe7b8, 0x14 }, - { 0xe7b9, 0x00 }, - { 0xe7ba, 0x2e }, - { 0xe7bb, 0x00 }, - { 0xe7bc, 0x00 }, - { 0xe7bd, 0x01 }, - { 0xe7be, 0x32 }, - { 0xe7bf, 0x00 }, - }, - -}; - -#define to_max96776_bridge(x) container_of(x, struct max96776_bridge, x) - -static void -max96776_dp_aux_dpcd_addr_sel(struct max96776_bridge *des, unsigned int addr) -{ - u32 reg; - - reg = AUX_ADDR_7_0(addr); - regmap_write(des->regmap, 0xe778, FIELD_PREP(USER_DATA1_B0, reg)); - reg = AUX_ADDR_15_8(addr); - regmap_write(des->regmap, 0xe779, FIELD_PREP(USER_DATA1_B1, reg)); - - /* - * Most significant four bits of DPCD register address when performing - * a twenty bit AUX read or write command. - */ - reg = AUX_ADDR_19_16(addr); - regmap_write(des->regmap, 0xe77c, FIELD_PREP(USER_DATA3_B0, reg)); -} - -static ssize_t max96776_dp_aux_transfer(struct drm_dp_aux *aux, - struct drm_dp_aux_msg *msg) -{ - struct max96776_bridge *des = to_max96776_bridge(aux); - int num_transferred = 0; - u8 *buffer = msg->buffer; - u32 reg; - int i; - - /* - * as Spec if Burst data transfer is supported, - * The burst data size must be limited to a maximum - * of 16 bytes. - */ - if (WARN_ON(msg->size > 16)) - return -E2BIG; - - /* - * Write AUX channel - * - * this command writes a DPCD register on the eDP/DP sink device. The register - * address is specified by the user in address 0xe778 and 0xe779. The data (a byte) - * to be written is specified in 0xe77a. The AUX channel must be configured prior to - * using the command(this occurs at power-up). The example below writes DPCD sink - * register 0x0100 with data 0x0a, To issue command, write the following registers: - * - * 1. LSBs of write address: 0xe778 0x00 - * 2. MSBs of write address: 0xe779 0x01 - * 3. LSBs of data to write: 0xe77a 0x0a - * 4. command select: 0xe776 0x20 - * 5. Execute command: 0xe777 0x80 - */ - if (!(msg->request & DP_AUX_I2C_READ)) { - for (i = 0; i < msg->size; i++) { - max96776_dp_aux_dpcd_addr_sel(des, msg->address + i); - reg = buffer[i]; - regmap_write(des->regmap, 0xe77a, - FIELD_PREP(USER_DATA2_B0, reg)); - regmap_update_bits(des->regmap, 0xe776, AUX_WRITE, - FIELD_PREP(AUX_WRITE, 1)); - regmap_update_bits(des->regmap, 0xe777, RUN_COMMAND, - FIELD_PREP(RUN_COMMAND, 1)); - mdelay(10); - num_transferred++; - } - } - - /* - * Read AUX channel - * - * this command read DPCD register on the eDP/DP sink device. The register - * address is specified by the user in address 0xe778 and 0xe779. Once the - * command has executed, the return data (a byte) is stored in 0xe77a. The - * AUX channel must be configured prior to using the command(this occurs - * at power-up). The example, to read DPCD sink register 0x100 (main link - * bandwidth setting), write the following registers: - * - * 1. LSBs of write address: 0xe778 0x00 - * 2. MSBs of write address: 0xe779 0x01 - * 3. command select: 0xe776 0x10 - * 4. Execute command: 0xe777 0x80 - * 5. LSBs of return value read: 0xe77a - */ - if (msg->request & DP_AUX_I2C_READ) { - for (i = 0; i < msg->size; i++) { - max96776_dp_aux_dpcd_addr_sel(des, msg->address + i); - regmap_update_bits(des->regmap, 0xe776, AUX_READ, - FIELD_PREP(AUX_READ, 1)); - regmap_update_bits(des->regmap, 0xe777, RUN_COMMAND, - FIELD_PREP(RUN_COMMAND, 1)); - mdelay(10); - regmap_read(des->regmap, 0xe77a, ®); - buffer[i] = (u8)reg; - - num_transferred++; - } - } - - msg->reply = DP_AUX_I2C_REPLY_ACK; - return (num_transferred == msg->size) ? num_transferred : -EBUSY; -} - -static int max96776_bridge_get_modes(struct drm_bridge *bridge, - struct drm_connector *connector) -{ - struct max96776_bridge *des = to_max96776_bridge(bridge); - - if (des->next_bridge) - return drm_bridge_get_modes(des->next_bridge, connector); - - if (des->panel) - return drm_panel_get_modes(des->panel, connector); - - return drm_add_modes_noedid(connector, 1920, 1080); -} - -static void max96776_edp_timing_config(struct max96776_bridge *des) -{ - struct drm_display_mode *mode = &des->mode; - u32 hfp, hsa, hbp, hact; - u32 vact, vsa, vfp, vbp; - u64 hwords, mvid, link_rate; - bool hsync_pol, vsync_pol; - - vact = mode->vdisplay; - vsa = mode->vsync_end - mode->vsync_start; - vfp = mode->vsync_start - mode->vdisplay; - vbp = mode->vtotal - mode->vsync_end; - hact = mode->hdisplay; - hsa = mode->hsync_end - mode->hsync_start; - hfp = mode->hsync_start - mode->hdisplay; - hbp = mode->htotal - mode->hsync_end; - - regmap_write(des->regmap, 0xe794, FIELD_PREP(HRES_B0, hact)); - regmap_write(des->regmap, 0xe795, FIELD_PREP(HRES_B1, hact >> 8)); - regmap_write(des->regmap, 0xe796, FIELD_PREP(HFP_B0, hfp)); - regmap_write(des->regmap, 0xe797, FIELD_PREP(HFP_B1, hfp >> 8)); - regmap_write(des->regmap, 0xe798, FIELD_PREP(HSW_B0, hsa)); - regmap_write(des->regmap, 0xe799, FIELD_PREP(HSW_B1, hsa >> 8)); - regmap_write(des->regmap, 0xe79a, FIELD_PREP(HBP_B0, hbp)); - regmap_write(des->regmap, 0xe79b, FIELD_PREP(HBP_B1, hbp >> 8)); - regmap_write(des->regmap, 0xe79c, FIELD_PREP(VRES_B0, vact)); - regmap_write(des->regmap, 0xe79d, FIELD_PREP(VRES_B1, vact >> 8)); - regmap_write(des->regmap, 0xe79e, FIELD_PREP(VFP_B0, vfp)); - regmap_write(des->regmap, 0xe79f, FIELD_PREP(VFP_B1, vfp >> 8)); - regmap_write(des->regmap, 0xe7a0, FIELD_PREP(VSW_B0, vsa)); - regmap_write(des->regmap, 0xe7a1, FIELD_PREP(VSW_B1, vsa >> 8)); - regmap_write(des->regmap, 0xe7a2, FIELD_PREP(VBP_B0, vbp)); - regmap_write(des->regmap, 0xe7a3, FIELD_PREP(VBP_B1, vbp >> 8)); - - hsync_pol = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); - vsync_pol = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); - regmap_update_bits(des->regmap, 0xe7ac, HSYNC_POL | VSYNC_POL, - FIELD_PREP(HSYNC_POL, hsync_pol) | - FIELD_PREP(VSYNC_POL, vsync_pol)); - - /* NVID should always be set to 0x8000 */ - regmap_write(des->regmap, 0xe7a8, FIELD_PREP(NVID_B0, 0)); - regmap_write(des->regmap, 0xe7a9, FIELD_PREP(NVID_B1, 0x80)); - - /* HWORDS = ((HRES x bits/pixel)/16) - LANE_COUNT */ - hwords = DIV_ROUND_CLOSEST_ULL(hact * 24, 16) - des->lane_count; - regmap_write(des->regmap, 0xe7a4, FIELD_PREP(HWORDS_B0, hwords)); - regmap_write(des->regmap, 0xe7a5, FIELD_PREP(HWORDS_B1, hwords >> 8)); - - /* MVID = (PCLK x NVID) x 10 / Link Rate */ - link_rate = drm_dp_bw_code_to_link_rate(des->link_rate); - mvid = DIV_ROUND_CLOSEST_ULL((u64)mode->clock * 32768, link_rate); - regmap_write(des->regmap, 0xe7a6, FIELD_PREP(HWORDS_B0, mvid)); - regmap_write(des->regmap, 0xe7a7, FIELD_PREP(HWORDS_B1, mvid >> 8)); - - regmap_write(des->regmap, 0xe7aa, FIELD_PREP(TUC_VALUE_B0, 0x40)); - regmap_write(des->regmap, 0xe7ab, FIELD_PREP(TUC_VALUE_B1, 0)); -} - -static void max96776_get_edp_sink_max_lane_count(struct max96776_bridge *des) -{ - u8 data; - - /* - * For DP rev.1.1, Maximum number of Main Link lanes - * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes - */ - drm_dp_dpcd_readb(&des->aux, DP_MAX_LANE_COUNT, &data); - des->lane_count = DPCD_MAX_LANE_COUNT(data); -} - -static void max96776_get_edp_sink_max_bw(struct max96776_bridge *des) -{ - u8 data; - - /* - * For DP rev.1.1, Maximum link rate of Main Link lanes - * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps - * For DP rev.1.2, Maximum link rate of Main Link lanes - * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps, 0x14 = 5.4Gbps - * For DP rev.1.4, Maximum link rate of Main Link lanes - * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps, 0x14 = 5.4Gbps 0x1e = 8.1 Gbps - */ - drm_dp_dpcd_readb(&des->aux, DP_MAX_LINK_RATE, &data); - des->link_rate = data; -} - -static void max96776_edp_link_config(struct max96776_bridge *des) -{ - - max96776_get_edp_sink_max_bw(des); - max96776_get_edp_sink_max_lane_count(des); - - if ((des->link_rate != DP_LINK_BW_1_62) && - (des->link_rate != DP_LINK_BW_2_7) && - (des->link_rate != DP_LINK_BW_5_4) && - (des->link_rate != DP_LINK_BW_8_1)) { - dev_err(des->dev, "Rx Max Link Rate is abnormal :%x !\n", - des->link_rate); - des->link_rate = DP_LINK_BW_1_62; - } - - if (des->lane_count == 0) { - dev_err(des->dev, "Rx Max Lane count is abnormal :%x !\n", - des->lane_count); - des->lane_count = (u8)USE_ONE_LINK; - } - - /* Setup TX lane count & rate */ - if (des->lane_count > (u8)des->max_lane_count) - des->lane_count = (u8)des->max_lane_count; - if (des->link_rate > des->max_link_rate) - des->link_rate = des->max_link_rate; - - regmap_write(des->regmap, 0xe790, FIELD_PREP(LINK_RATE, des->link_rate)); - regmap_write(des->regmap, 0xe792, FIELD_PREP(LANE_COUNT, des->lane_count)); - dev_info(des->dev, "final bandwidth: 0x%02x, lane count: 0x%02x\n", - des->link_rate, des->lane_count); -} - -static void max96776_edp_pll_config(struct max96776_bridge *des) -{ - /* provides control for eDP PLL */ - switch (des->link_rate) { - case DP_LINK_BW_5_4: - regmap_multi_reg_write(des->regmap, max96776_clk_ref[BW_5_4], - ARRAY_SIZE(max96776_clk_ref[BW_5_4])); - break; - case DP_LINK_BW_2_7: - regmap_multi_reg_write(des->regmap, max96776_clk_ref[BW_2_7], - ARRAY_SIZE(max96776_clk_ref[BW_2_7])); - break; - case DP_LINK_BW_1_62: - default: - regmap_multi_reg_write(des->regmap, max96776_clk_ref[BW_1_62], - ARRAY_SIZE(max96776_clk_ref[BW_1_62])); - break; - } -} - -static void max96776_edp_full_training(struct max96776_bridge *des) -{ - u8 status[2]; - u32 sts; - int ret; - - regmap_update_bits(des->regmap, 0xe776, RUN_LINK_TRAINING, - FIELD_PREP(RUN_LINK_TRAINING, 0x1)); - regmap_update_bits(des->regmap, 0xe777, RUN_COMMAND, - FIELD_PREP(RUN_COMMAND, 0x1)); - ret = regmap_read_poll_timeout(des->regmap, 0x07f0, sts, - FIELD_PREP(TRAINING_SUCCESSFUL, sts), - MSEC_PER_SEC, 200 * MSEC_PER_SEC); - if (ret < 0) - dev_err(des->dev, "Link Training not successful\n"); - - drm_dp_dpcd_read(&des->aux, DP_LANE0_1_STATUS, status, 2); - dev_info(des->dev, "SINK LANE0_1_STATUS:0x%02x LANE2_3_STATUS:0x%02x\n", - status[0], status[1]); -} - -static void -max96776_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) -{ - struct max96776_bridge *des = to_max96776_bridge(bridge); - u8 dpcd; - - /* disable HDCP 2.2 on eDP Deserializer */ - regmap_update_bits(des->regmap, 0x1700, CMD_RESET, - FIELD_PREP(CMD_RESET, 0x01)); - - /* - * This bit must be set to allow waiting for the - * CMU to lock. It also should be set when using - * SSC. Otherwise, a fixed wait time of 20μS is - * used. - */ - regmap_update_bits(des->regmap, 0xe7b0, SS_ENABLE, - FIELD_PREP(SS_ENABLE, 0x01)); - - /* - * Determines whether spread spectrum clocking (SSC) - * is used with the DP sink device. - */ - drm_dp_dpcd_readb(&des->aux, DP_MAX_DOWNSPREAD, &dpcd); - if (!!(dpcd & DP_MAX_DOWNSPREAD_0_5)) - regmap_update_bits(des->regmap, 0xe7b1, SSC_ENABLE, - FIELD_PREP(SSC_ENABLE, 0x01)); - - max96776_edp_link_config(des); - max96776_edp_pll_config(des); - max96776_edp_timing_config(des); - - if (des->panel) - drm_panel_prepare(des->panel); -} - -static void -max96776_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) -{ - struct max96776_bridge *des = to_max96776_bridge(bridge); - - max96776_edp_full_training(des); - - if (des->panel) - drm_panel_enable(des->panel); -} - -static void -max96776_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) -{ - struct max96776_bridge *des = to_max96776_bridge(bridge); - - if (des->panel) - drm_panel_disable(des->panel); -} - -static void -max96776_bridge_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) -{ - struct max96776_bridge *des = to_max96776_bridge(bridge); - - if (des->panel) - drm_panel_unprepare(des->panel); -} - - -static int max96776_bridge_attach(struct drm_bridge *bridge, - enum drm_bridge_attach_flags flags) -{ - struct max96776_bridge *des = to_max96776_bridge(bridge); - int ret; - - ret = drm_of_find_panel_or_bridge(bridge->of_node, 1, -1, &des->panel, - &des->next_bridge); - if (ret < 0 && ret != -ENODEV) - return ret; - - if (des->next_bridge) - return drm_bridge_attach(bridge->encoder, des->next_bridge, - bridge, 0); - - return 0; -} - -static void max96776_bridge_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - const struct drm_display_mode *adj_mode) -{ - struct max96776_bridge *des = to_max96776_bridge(bridge); - - drm_mode_copy(&des->mode, adj_mode); -} - -static enum drm_connector_status -max96776_bridge_detect(struct drm_bridge *bridge) -{ - struct max96776_bridge *des = to_max96776_bridge(bridge); - u32 hpd; - - if (regmap_read(des->regmap, 0x6230, &hpd)) - return connector_status_disconnected; - - if (!FIELD_PREP(HPD_PRESENT, hpd)) - return connector_status_disconnected; - - return connector_status_connected; -} - -static const struct drm_bridge_funcs max96776_bridge_funcs = { - .attach = max96776_bridge_attach, - .detect = max96776_bridge_detect, - .get_modes = max96776_bridge_get_modes, - .atomic_pre_enable = max96776_bridge_atomic_pre_enable, - .atomic_post_disable = max96776_bridge_atomic_post_disable, - .atomic_enable = max96776_bridge_atomic_enable, - .atomic_disable = max96776_bridge_atomic_disable, - .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, - .atomic_reset = drm_atomic_helper_bridge_reset, - .mode_set = max96776_bridge_mode_set, -}; - -static int max96776_bridge_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct max96776_bridge *des; - int ret; - - des = devm_kzalloc(dev, sizeof(*des), GFP_KERNEL); - if (!des) - return -ENOMEM; - - des->dev = dev; - des->parent = dev_get_drvdata(dev->parent); - platform_set_drvdata(pdev, des); - - des->regmap = dev_get_regmap(dev->parent, NULL); - if (!des->regmap) - return dev_err_probe(dev, -ENODEV, "failed to get regmap\n"); - - des->max_link_rate = DP_LINK_BW_5_4; - des->max_lane_count = USE_FOUR_LINK; - - des->aux.name = "DP-AUX"; - des->aux.transfer = max96776_dp_aux_transfer; - des->aux.dev = des->dev; - - ret = drm_dp_aux_register(&des->aux); - if (ret) { - dev_err(dev, "failed to register dp aux\n"); - return ret; - } - - des->bridge.funcs = &max96776_bridge_funcs; - des->bridge.of_node = dev->of_node; - des->bridge.ops = DRM_BRIDGE_OP_MODES | DRM_BRIDGE_OP_DETECT; - des->bridge.type = DRM_MODE_CONNECTOR_eDP; - - drm_bridge_add(&des->bridge); - - return 0; -} - -static int max96776_bridge_remove(struct platform_device *pdev) -{ - struct max96776_bridge *des = platform_get_drvdata(pdev); - - drm_bridge_remove(&des->bridge); - - return 0; -} - -static const struct of_device_id max96776_bridge_of_match[] = { - { .compatible = "maxim,max96776-bridge" }, - {} -}; -MODULE_DEVICE_TABLE(of, max96776_bridge_of_match); - -static struct platform_driver max96776_bridge_driver = { - .driver = { - .name = "max96776-bridge", - .of_match_table = max96776_bridge_of_match, - }, - .probe = max96776_bridge_probe, - .remove = max96776_bridge_remove, -}; - -module_platform_driver(max96776_bridge_driver); - -MODULE_AUTHOR("Guochun Huang "); -MODULE_DESCRIPTION("Maxim max96776 GMSL2 Deserializer with eDP Output"); -MODULE_LICENSE("GPL"); From c1f870a930e67a05c104af146cf2ee736faf1429 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 22 Nov 2022 08:37:51 +0000 Subject: [PATCH 124/235] Revert "mfd: Add support for Maxim MAX96776" This reverts commit 4b9ba5d213cf06d38e2bb8abb62bc6986a31669c. Delete this unused driver. Signed-off-by: Wyon Bi Change-Id: I2ba96feb73c5ea98d3945478eb90773efe4eed0d --- drivers/mfd/Kconfig | 9 -- drivers/mfd/Makefile | 1 - drivers/mfd/max96776.c | 194 ----------------------------------- include/linux/mfd/max96776.h | 131 ----------------------- 4 files changed, 335 deletions(-) delete mode 100644 drivers/mfd/max96776.c delete mode 100644 include/linux/mfd/max96776.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 72eabcbc742e..1ec588cae247 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -938,15 +938,6 @@ config MFD_MAX96755F help Say yes here to add support for Maxim Semiconductor MAX96755. -config MFD_MAX96776 - tristate "Maxim Semiconductor MAX96776 GMSL2 Deserializer Support" - depends on I2C - select MFD_CORE - select REGMAP_I2C - select I2C_MUX - help - Say yes here to add support for Maxim Semiconductor MAX96776. - config MFD_MT6360 tristate "Mediatek MT6360 SubPMIC" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index e723deea8f45..1b45f971e083 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -172,7 +172,6 @@ obj-$(CONFIG_MFD_MAX8997) += max8997.o max8997-irq.o obj-$(CONFIG_MFD_MAX8998) += max8998.o max8998-irq.o obj-$(CONFIG_MFD_MAX96745) += max96745.o obj-$(CONFIG_MFD_MAX96755F) += max96755f.o -obj-$(CONFIG_MFD_MAX96776) += max96776.o obj-$(CONFIG_MFD_MP2629) += mp2629.o diff --git a/drivers/mfd/max96776.c b/drivers/mfd/max96776.c deleted file mode 100644 index abea0a25bfec..000000000000 --- a/drivers/mfd/max96776.c +++ /dev/null @@ -1,194 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Maxim MAX96776 MFD driver - * - * Copyright (C) 2022 Rockchip Electronics Co. Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct max96776 { - struct device *dev; - struct regmap *regmap; - struct i2c_client *client; - struct i2c_mux_core *muxc; - struct gpio_desc *enable_gpio; - u32 stream_id; -}; - -static const struct mfd_cell max96776_devs[] = { - { - .name = "max96776-bridge", - .of_compatible = "maxim,max96776-bridge", - }, -}; - -static int max96776_select(struct i2c_mux_core *muxc, u32 chan) -{ - return 0; -} - -static const struct regmap_range max96776_readable_ranges[] = { - regmap_reg_range(0x0000, 0x0026), - regmap_reg_range(0x0029, 0x002c), - regmap_reg_range(0x0050, 0x0050), - regmap_reg_range(0x0100, 0x0100), - regmap_reg_range(0x0103, 0x0103), - regmap_reg_range(0x0108, 0x0108), - regmap_reg_range(0x0600, 0x0600), - regmap_reg_range(0x07f0, 0x07f1), - regmap_reg_range(0x1700, 0x1700), - regmap_reg_range(0x4100, 0x4100), - regmap_reg_range(0x6230, 0x6230), - regmap_reg_range(0xe75e, 0xe75e), - regmap_reg_range(0xe776, 0xe7bf), -}; - -static const struct regmap_access_table max96776_readable_table = { - .yes_ranges = max96776_readable_ranges, - .n_yes_ranges = ARRAY_SIZE(max96776_readable_ranges), -}; - -static const struct regmap_config max96776_regmap_config = { - .name = "max96776", - .reg_bits = 16, - .val_bits = 8, - .rd_table = &max96776_readable_table, - .max_register = 0xff02, -}; - -static void max96776_power_on(struct max96776 *max96776) -{ - if (max96776->enable_gpio) { - gpiod_direction_output(max96776->enable_gpio, 1); - msleep(500); - } -} - -static void max96776_power_off(struct max96776 *max96776) -{ - if (max96776->enable_gpio) - gpiod_direction_output(max96776->enable_gpio, 0); -} - -static int max96776_i2c_probe(struct i2c_client *client) -{ - struct device *dev = &client->dev; - struct device_node *child; - struct max96776 *max96776; - unsigned int nr = 0; - int ret; - - for_each_available_child_of_node(dev->of_node, child) { - if (!of_find_property(child, "reg", NULL)) - continue; - - nr++; - } - - max96776 = devm_kzalloc(dev, sizeof(*max96776), GFP_KERNEL); - if (!max96776) - return -ENOMEM; - - max96776->muxc = i2c_mux_alloc(client->adapter, dev, nr, 0, - I2C_MUX_LOCKED, max96776_select, NULL); - if (!max96776->muxc) - return -ENOMEM; - - max96776->dev = dev; - max96776->client = client; - - max96776->enable_gpio = devm_gpiod_get_optional(dev, "enable", - GPIOD_ASIS); - if (IS_ERR(max96776->enable_gpio)) - return dev_err_probe(dev, PTR_ERR(max96776->enable_gpio), - "failed to get enable GPIO\n"); - - ret = device_property_read_u32(dev->parent, "reg", &max96776->stream_id); - if (ret) - return dev_err_probe(dev, ret, "failed to get gmsl id\n"); - - i2c_set_clientdata(client, max96776); - - max96776->regmap = devm_regmap_init_i2c(client, - &max96776_regmap_config); - if (IS_ERR(max96776->regmap)) - return dev_err_probe(dev, PTR_ERR(max96776->regmap), - "failed to initialize regmap\n"); - - max96776_power_on(max96776); - - ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, max96776_devs, - ARRAY_SIZE(max96776_devs), NULL, 0, NULL); - if (ret) - return ret; - - for_each_available_child_of_node(dev->of_node, child) { - if (of_property_read_u32(child, "reg", &nr)) - continue; - - ret = i2c_mux_add_adapter(max96776->muxc, 0, nr, 0); - if (ret) { - i2c_mux_del_adapters(max96776->muxc); - return ret; - } - } - - return 0; -} - -static void max96776_i2c_shutdown(struct i2c_client *client) -{ - struct max96776 *max96776 = i2c_get_clientdata(client); - - max96776_power_off(max96776); -} - -static int __maybe_unused max96776_suspend(struct device *dev) -{ - struct max96776 *max96776 = dev_get_drvdata(dev); - - max96776_power_off(max96776); - - return 0; -} - -static int __maybe_unused max96776_resume(struct device *dev) -{ - struct max96776 *max96776 = dev_get_drvdata(dev); - - max96776_power_on(max96776); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(max96776_pm_ops, max96776_suspend, max96776_resume); - -static const struct of_device_id max96776_of_match[] = { - { .compatible = "maxim,max96776", }, - {} -}; -MODULE_DEVICE_TABLE(of, max96776_of_match); - -static struct i2c_driver max96776_i2c_driver = { - .driver = { - .name = "max96776", - .of_match_table = of_match_ptr(max96776_of_match), - .pm = &max96776_pm_ops, - }, - .probe_new = max96776_i2c_probe, - .shutdown = max96776_i2c_shutdown, -}; - -module_i2c_driver(max96776_i2c_driver); - -MODULE_AUTHOR("Guochun Huang "); -MODULE_DESCRIPTION("Maxim max96776 MFD driver"); -MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/max96776.h b/include/linux/mfd/max96776.h deleted file mode 100644 index fd445a7ac4b5..000000000000 --- a/include/linux/mfd/max96776.h +++ /dev/null @@ -1,131 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Defining registers address and its bit definitions of MAX96776 - * - * Copyright (c) 2022 Rockchip Electronics Co. Ltd. - */ - -#ifndef _MFD_MAX96776_H_ -#define _MFD_MAX96776_H_ - -#include - -/* 07f0h */ -#define TRAINING_SUCCESSFUL BIT(0) - -/* 1700h */ -#define CMD_RESET BIT(7) - -/* 6230h */ -#define HPD_PRESENT BIT(0) - -/* e776h */ -#define REBOOT_TRAINNING BIT(0) -#define RUN_LINK_TRAINING BIT(1) -#define AUX_READ BIT(4) -#define AUX_WRITE BIT(5) - -/* e777h */ -#define RUN_COMMAND BIT(7) - -/* e778h */ -#define USER_DATA1_B0 GENMASK(7, 0) - -/* e779h */ -#define USER_DATA1_B1 GENMASK(7, 0) - -/* e77ah */ -#define USER_DATA2_B0 GENMASK(7, 0) - -/* e77ch */ -#define USER_DATA3_B0 GENMASK(7, 0) - -/* e790h */ -#define LINK_RATE GENMASK(4, 0) - -/* e792h */ -#define LANE_COUNT GENMASK(2, 0) - -/* e794h */ -#define HRES_B0 GENMASK(7, 0) - -/* e795h */ -#define HRES_B1 GENMASK(7, 0) - -/* e796h */ -#define HFP_B0 GENMASK(7, 0) - -/* e797h */ -#define HFP_B1 GENMASK(7, 0) - -/* e798h */ -#define HSW_B0 GENMASK(7, 0) - -/* e799h */ -#define HSW_B1 GENMASK(7, 0) - -/* e79ah */ -#define HBP_B0 GENMASK(7, 0) - -/* e79bh */ -#define HBP_B1 GENMASK(7, 0) - -/* e79ch */ -#define VRES_B0 GENMASK(7, 0) - -/* e79dh */ -#define VRES_B1 GENMASK(7, 0) - -/* e79eh */ -#define VFP_B0 GENMASK(7, 0) - -/* e79fh */ -#define VFP_B1 GENMASK(7, 0) - -/* e7a0h */ -#define VSW_B0 GENMASK(7, 0) - -/* e7a1h */ -#define VSW_B1 GENMASK(7, 0) - -/* e7a2h */ -#define VBP_B0 GENMASK(7, 0) - -/* e7a3h */ -#define VBP_B1 GENMASK(7, 0) - -/* e7a4h */ -#define HWORDS_B0 GENMASK(7, 0) - -/* e7a5h */ -#define HWORDS_B1 GENMASK(7, 0) - -/* e7a6h */ -#define MVID_B0 GENMASK(7, 0) - -/* e7a7h */ -#define MVID_B1 GENMASK(7, 0) - -/* e7a8h */ -#define NVID_B0 GENMASK(7, 0) - -/* e7a9h */ -#define NVID_B1 GENMASK(7, 0) - -/* e7aah */ -#define TUC_VALUE_B0 GENMASK(7, 0) - -/* e7abh */ -#define TUC_VALUE_B1 GENMASK(7, 0) - -/* e7ach */ -#define HSYNC_POL BIT(0) -#define VSYNC_POL BIT(1) - -/* e7b0h */ -#define SS_ENABLE BIT(0) - -/* e7b1h */ -#define SSC_ENABLE BIT(4) - -#endif /* _MFD_MAX96776_H_ */ From 51450af0edef07bce4e519a9932ab06f2643c8e8 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Tue, 22 Nov 2022 08:31:57 +0000 Subject: [PATCH 125/235] arm64: rockchip_defconfig: Disable CONFIG_DRM_MAXIM_MAX96752F Delete this unused config. Signed-off-by: Wyon Bi Change-Id: Iec1f9f2723146e83cadd3a9eda4e135ae029e739 --- arch/arm64/configs/rockchip_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig index f3ab5c281e52..85e9598f16a3 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -627,7 +627,6 @@ CONFIG_DRM_PANEL_SIMPLE=y CONFIG_DRM_PANEL_MAXIM_DESERIALIZER=y CONFIG_DRM_DISPLAY_CONNECTOR=y CONFIG_DRM_MAXIM_MAX96745=y -CONFIG_DRM_MAXIM_MAX96752F=y CONFIG_DRM_MAXIM_MAX96755F=y CONFIG_DRM_RK630_TVE=y CONFIG_DRM_RK1000_TVE=y From 1fda99416a632055d2f90d8936778fc37c7a6348 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 23 Nov 2022 09:55:52 +0800 Subject: [PATCH 126/235] arm64: rockchip_gki.config: Disable CONFIG_DRM_MAXIM_MAX96752F Delete this unused config. Signed-off-by: Tao Huang Change-Id: I97ba367145f90f98b23e96f38ed8d6b9cd833800 --- arch/arm64/configs/rockchip_gki.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/rockchip_gki.config b/arch/arm64/configs/rockchip_gki.config index e7fbedd7372b..72c625eb3bde 100644 --- a/arch/arm64/configs/rockchip_gki.config +++ b/arch/arm64/configs/rockchip_gki.config @@ -44,7 +44,6 @@ CONFIG_DRM_DISPLAY_CONNECTOR=m CONFIG_DRM_DW_HDMI_CEC=m CONFIG_DRM_DW_HDMI_I2S_AUDIO=m CONFIG_DRM_MAXIM_MAX96745=m -CONFIG_DRM_MAXIM_MAX96752F=m CONFIG_DRM_MAXIM_MAX96755F=m CONFIG_DRM_PANEL_SIMPLE=m CONFIG_DRM_RK1000_TVE=m From b0086261b62de15ca95fccae426da19d92c44742 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Tue, 8 Nov 2022 11:40:45 +0800 Subject: [PATCH 127/235] mmc: sdhci-of-dwmshc: Add software queue support Add newly added software queue support to improve random performance. Testing condition: rk3588-evb1 32GB eMMC, CPU & DRAM fixed frequency Random read test: fio -filename=/dev/block/mmcblk0 -direct=1 -iodepth 20 -thread -rw=randread \ -ioengine=psync -bs=4k -size=1G -numjobs=20 -runtime=40 -group_reporting \ -name=rand_100read_4k Random write test: fio -filename=/data/fio.bin -direct=1 -iodepth 20 -thread -rw=randwrite \ -ioengine=psync -bs=4k -size=1G -numjobs=20 -runtime=40 -group_reporting \ -name=rand_100write_4k ====================================================================== | - | W/O patch | With patch applied| improve percentage | | random read | 45624KB/s | 62542KB/s | +37% | | random write| 22548KB/s | 27977KB/s | +24% | ====================================================================== Signed-off-by: Shawn Lin Change-Id: I81dca2e9c45d1a1596ef810328f32c9a2779683c --- drivers/mmc/host/Kconfig | 1 + drivers/mmc/host/sdhci-of-dwcmshc.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 9daef0237382..3c308ba3aaeb 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -207,6 +207,7 @@ config MMC_SDHCI_OF_DWCMSHC depends on MMC_SDHCI_PLTFM depends on OF depends on COMMON_CLK + select MMC_HSQ help This selects Synopsys DesignWare Cores Mobile Storage Controller support. diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 3cb631766b80..fc3b19e87542 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -20,6 +20,7 @@ #include #include "sdhci-pltfm.h" +#include "mmc_hsq.h" #define SDHCI_DWCMSHC_ARG2_STUFF GENMASK(31, 16) @@ -331,6 +332,14 @@ static void rockchip_sdhci_reset(struct sdhci_host *host, u8 mask) sdhci_reset(host, mask); } +static void sdhci_dwcmshc_request_done(struct sdhci_host *host, struct mmc_request *mrq) +{ + if (mmc_hsq_finalize_request(host->mmc, mrq)) + return; + + mmc_request_done(host->mmc, mrq); +} + static const struct sdhci_ops sdhci_dwcmshc_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, @@ -347,6 +356,7 @@ static const struct sdhci_ops sdhci_dwcmshc_rk_ops = { .get_max_clock = sdhci_pltfm_clk_get_max_clock, .reset = rockchip_sdhci_reset, .adma_write_desc = dwcmshc_adma_write_desc, + .request_done = sdhci_dwcmshc_request_done, }; static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = { @@ -441,6 +451,7 @@ static int dwcmshc_probe(struct platform_device *pdev) struct sdhci_host *host; struct dwcmshc_priv *priv; const struct dwcmshc_driver_data *drv_data; + struct mmc_hsq *hsq; int err; u32 extra; @@ -494,6 +505,16 @@ static int dwcmshc_probe(struct platform_device *pdev) host->mmc_host_ops.request = dwcmshc_request; host->mmc_host_ops.hs400_enhanced_strobe = dwcmshc_hs400_enhanced_strobe; + hsq = devm_kzalloc(&pdev->dev, sizeof(*hsq), GFP_KERNEL); + if (!hsq) { + err = -ENOMEM; + goto err_clk; + } + + err = mmc_hsq_init(hsq, host->mmc); + if (err) + goto err_clk; + err = sdhci_add_host(host); if (err) goto err_clk; @@ -550,6 +571,8 @@ static int dwcmshc_suspend(struct device *dev) struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); int ret; + mmc_hsq_suspend(host->mmc); + ret = sdhci_suspend_host(host); if (ret) return ret; @@ -583,7 +606,11 @@ static int dwcmshc_resume(struct device *dev) if (ret) return ret; - return sdhci_resume_host(host); + ret = sdhci_resume_host(host); + if (ret) + return ret; + + return mmc_hsq_resume(host->mmc); } static int dwcmshc_runtime_suspend(struct device *dev) From e81b85944754e022cd5246cb47c90d389140c7d8 Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Wed, 23 Nov 2022 10:06:43 +0800 Subject: [PATCH 128/235] arm64: dts: rockchip: disable ss instances in park mode for usb3 The xHCI SuperSpeed instance in park mode would fail to recover, thus on Rockchip SoCs when there is high load on the xHCI port. Such as a USB3 HUB with two USB3 disks are plugged in and do write/read test continuously, the controller may crash like: xhci-hcd xhci-hcd.9.auto: xHCI host not responding to stop endpoint command. xhci-hcd xhci-hcd.9.auto: USBSTS: 0x00000000 xhci-hcd xhci-hcd.9.auto: xHCI host controller not responding, assume dead xhci-hcd xhci-hcd.9.auto: HC died; cleaning up xhci-hcd xhci-hcd.9.auto: xHCI host not responding to stop endpoint command. xhci-hcd xhci-hcd.9.auto: USBSTS: 0x00001001 HCHalted HCE usb 7-1: USB disconnect, device number 2 sd 2:0:0:0: [sdb] tag#0 FAILED Result: hostbyte=DID_TIME_OUT driverbyte=DRIVER_OK cmd_age=35s sd 2:0:0:0: [sdb] tag#0 CDB: Read(10) 28 00 00 12 cc 80 00 02 00 00 blk_update_request: I/O error, dev sdb, sector 1232000 op 0x0:(READ) flags 0x80700 phys_seg 8 prio class 0 So set the PARKMODE_DISABLE_SS bit in the DWC3_USB3_GUCTL1 to mitigate the issue. Signed-off-by: Frank Wang Change-Id: I57a180dbd820b105bd70d0d8834c163de1ac0597 --- arch/arm64/boot/dts/rockchip/rk1808.dtsi | 1 + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 1 + arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 ++ arch/arm64/boot/dts/rockchip/rk3568.dtsi | 2 ++ arch/arm64/boot/dts/rockchip/rk3588.dtsi | 1 + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 2 ++ 6 files changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk1808.dtsi b/arch/arm64/boot/dts/rockchip/rk1808.dtsi index 16d8fabe20f2..67f93f0c9d01 100644 --- a/arch/arm64/boot/dts/rockchip/rk1808.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk1808.dtsi @@ -379,6 +379,7 @@ snps,dis-del-phy-power-chg-quirk; snps,tx-ipgap-linecheck-dis-quirk; snps,xhci-trb-ent-quirk; + snps,parkmode-disable-ss-quirk; status = "disabled"; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index 503dba319e73..bcbadbae2910 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -1003,6 +1003,7 @@ snps,dis-u2-freeclk-exists-quirk; snps,dis_u2_susphy_quirk; snps,dis_u3_susphy_quirk; + snps,parkmode-disable-ss-quirk; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index b97879e82a11..e0ce7a3e053f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi @@ -455,6 +455,7 @@ snps,dis_u2_susphy_quirk; snps,dis-del-phy-power-chg-quirk; snps,dis-tx-ipgap-linecheck-quirk; + snps,parkmode-disable-ss-quirk; power-domains = <&power RK3399_PD_USB3>; status = "disabled"; }; @@ -491,6 +492,7 @@ snps,dis_u2_susphy_quirk; snps,dis-del-phy-power-chg-quirk; snps,dis-tx-ipgap-linecheck-quirk; + snps,parkmode-disable-ss-quirk; power-domains = <&power RK3399_PD_USB3>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3568.dtsi b/arch/arm64/boot/dts/rockchip/rk3568.dtsi index 7f4b108684cc..b31c76bbf9fb 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi @@ -583,6 +583,7 @@ snps,dis-tx-ipgap-linecheck-quirk; snps,dis_rxdet_inp3_quirk; snps,xhci-trb-ent-quirk; + snps,parkmode-disable-ss-quirk; quirk-skip-phy-init; status = "disabled"; }; @@ -616,6 +617,7 @@ snps,dis-tx-ipgap-linecheck-quirk; snps,dis_rxdet_inp3_quirk; snps,xhci-trb-ent-quirk; + snps,parkmode-disable-ss-quirk; status = "disabled"; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588.dtsi b/arch/arm64/boot/dts/rockchip/rk3588.dtsi index b2da34f03677..fb78ea6ad401 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi @@ -138,6 +138,7 @@ snps,dis-u2-freeclk-exists-quirk; snps,dis-del-phy-power-chg-quirk; snps,dis-tx-ipgap-linecheck-quirk; + snps,parkmode-disable-ss-quirk; status = "disabled"; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi index ea1986d2b229..1a67dec544bb 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -1902,6 +1902,7 @@ snps,dis-u2-freeclk-exists-quirk; snps,dis-del-phy-power-chg-quirk; snps,dis-tx-ipgap-linecheck-quirk; + snps,parkmode-disable-ss-quirk; quirk-skip-phy-init; status = "disabled"; }; @@ -2007,6 +2008,7 @@ snps,dis-del-phy-power-chg-quirk; snps,dis-tx-ipgap-linecheck-quirk; snps,dis_rxdet_inp3_quirk; + snps,parkmode-disable-ss-quirk; status = "disabled"; }; }; From fb738478a26aa57764a57b3260ae0b368954e87f Mon Sep 17 00:00:00 2001 From: Lin Jianhua Date: Wed, 23 Nov 2022 12:30:45 +0800 Subject: [PATCH 129/235] ARM: dts: rockchip: rk3288-linux: enable iep Change-Id: Ibd4299e2695cd0a2009befd81ba65fdd35135ac2 Signed-off-by: Lin Jianhua --- arch/arm/boot/dts/rk3288-linux.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/rk3288-linux.dtsi b/arch/arm/boot/dts/rk3288-linux.dtsi index 7d048df9cac9..c5d9dc214bab 100644 --- a/arch/arm/boot/dts/rk3288-linux.dtsi +++ b/arch/arm/boot/dts/rk3288-linux.dtsi @@ -194,6 +194,14 @@ status = "okay"; }; +&iep { + status = "okay"; +}; + +&iep_mmu { + status = "okay"; +}; + &rga { compatible = "rockchip,rga2"; clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>; From d39e7f58f7e7020f76657a0e3678b91bf17f51e6 Mon Sep 17 00:00:00 2001 From: Jianlong Wang Date: Wed, 23 Nov 2022 14:55:10 +0800 Subject: [PATCH 130/235] net: rfkill: rfkill-wlan: fix syntax errors in get_wifi_addr_vendor Change-Id: Ibc632671ba634af0d46341fbd3f91f01afa703b5 Signed-off-by: Jianlong Wang --- net/rfkill/rfkill-wlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/rfkill/rfkill-wlan.c b/net/rfkill/rfkill-wlan.c index b25fe96db09c..89d9787b9ad9 100644 --- a/net/rfkill/rfkill-wlan.c +++ b/net/rfkill/rfkill-wlan.c @@ -436,7 +436,7 @@ static int get_wifi_addr_vendor(unsigned char *addr) addr[5]); ret = rk_vendor_write(WIFI_MAC_ID, addr, 6); if (ret != 0) { - LOG("%s: rk_vendor_write failed %d\n" + LOG("%s: rk_vendor_write failed %d\n", __func__, ret); memset(addr, 0, 6); return -1; From caf146538fd8602d16f905a84a24f807ba978081 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Wed, 23 Nov 2022 17:41:52 +0800 Subject: [PATCH 131/235] media: rockchip: isp: fix self update config for isp30 Change-Id: I882affcf17ab0dc6e6497ea1fb1e9683ff88c3c9 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/capture_v30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/rockchip/isp/capture_v30.c b/drivers/media/platform/rockchip/isp/capture_v30.c index f11c99a3e4dc..0f1353774126 100644 --- a/drivers/media/platform/rockchip/isp/capture_v30.c +++ b/drivers/media/platform/rockchip/isp/capture_v30.c @@ -917,7 +917,7 @@ static void stream_self_update(struct rkisp_stream *stream) return; } - rkisp_unite_set_bits(dev, ISP3X_MI_WR_XTD_FORMAT_CTRL, mask, val, false, is_unite); + rkisp_unite_set_bits(dev, ISP3X_MI_WR_CTRL2, mask, val, false, is_unite); } static int mi_frame_start(struct rkisp_stream *stream, u32 mis) From 7f2c76d5a9bae3026c3468215a7a2601c6d25e56 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Tue, 11 Oct 2022 02:22:30 +0000 Subject: [PATCH 132/235] media: i2c: lt7911uxc: fix reset operation Signed-off-by: Jianwei Fan Change-Id: I0f3790c341c855ec1b1684813ad63383b2e6e51a --- drivers/media/i2c/lt7911uxc.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/media/i2c/lt7911uxc.c b/drivers/media/i2c/lt7911uxc.c index 8fea3659d1cd..21ba5062e8ae 100644 --- a/drivers/media/i2c/lt7911uxc.c +++ b/drivers/media/i2c/lt7911uxc.c @@ -1278,16 +1278,6 @@ static const struct v4l2_ctrl_config lt7911uxc_ctrl_audio_present = { .flags = V4L2_CTRL_FLAG_READ_ONLY, }; -static void lt7911uxc_reset(struct lt7911uxc *lt7911uxc) -{ - gpiod_set_value(lt7911uxc->reset_gpio, 0); - usleep_range(2000, 2100); - gpiod_set_value(lt7911uxc->reset_gpio, 1); - usleep_range(120*1000, 121*1000); - gpiod_set_value(lt7911uxc->reset_gpio, 0); - usleep_range(300*1000, 310*1000); -} - static int lt7911uxc_init_v4l2_ctrls(struct lt7911uxc *lt7911uxc) { const struct lt7911uxc_mode *mode; @@ -1419,7 +1409,9 @@ static int lt7911uxc_probe_of(struct lt7911uxc *lt7911uxc) lt7911uxc->enable_hdcp = false; gpiod_set_value(lt7911uxc->power_gpio, 1); - lt7911uxc_reset(lt7911uxc); + //delay 2~3ms before reset + usleep_range(2000, 3000); + gpiod_set_value(lt7911uxc->reset_gpio, 0); ret = 0; From b541c6aa8da445ed66575cd96a148975c1b2e02c Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Tue, 11 Oct 2022 02:29:31 +0000 Subject: [PATCH 133/235] media: i2c: lt7911d: fix reset operation Signed-off-by: Jianwei Fan Change-Id: I5d97e98c0b26848262fa39dd1b484b23567bd4c2 --- drivers/media/i2c/lt7911d.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/media/i2c/lt7911d.c b/drivers/media/i2c/lt7911d.c index 1803f681fede..4e295d4159a2 100644 --- a/drivers/media/i2c/lt7911d.c +++ b/drivers/media/i2c/lt7911d.c @@ -1035,16 +1035,6 @@ static const struct v4l2_ctrl_config lt7911d_ctrl_audio_present = { .flags = V4L2_CTRL_FLAG_READ_ONLY, }; -static void lt7911d_reset(struct lt7911d_state *lt7911d) -{ - gpiod_set_value(lt7911d->reset_gpio, 0); - usleep_range(2000, 2100); - gpiod_set_value(lt7911d->reset_gpio, 1); - usleep_range(120*1000, 121*1000); - gpiod_set_value(lt7911d->reset_gpio, 0); - usleep_range(300*1000, 310*1000); -} - static int lt7911d_init_v4l2_ctrls(struct lt7911d_state *lt7911d) { struct v4l2_subdev *sd; @@ -1175,7 +1165,8 @@ static int lt7911d_probe_of(struct lt7911d_state *lt7911d) lt7911d->enable_hdcp = false; gpiod_set_value(lt7911d->power_gpio, 1); - lt7911d_reset(lt7911d); + usleep_range(2000, 3000); + gpiod_set_value(lt7911d->reset_gpio, 0); ret = 0; @@ -1248,8 +1239,6 @@ static int lt7911d_probe(struct i2c_client *client, if (err < 0) return err; - lt7911d_reset(lt7911d); - mutex_init(<7911d->confctl_mutex); err = lt7911d_init_v4l2_ctrls(lt7911d); if (err) From b843cf6902d0d8a191299d8b79b55db6a5c4d608 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Wed, 23 Nov 2022 19:10:27 +0800 Subject: [PATCH 134/235] video: rockchip: rga3: add iommu fault irq_handler Signed-off-by: Yu Qiaowei Change-Id: I9c8159e48a9e7c7a01b8e9b155c52a7f57603ab2 --- .../video/rockchip/rga3/include/rga_iommu.h | 5 +++ drivers/video/rockchip/rga3/rga2_reg_info.c | 8 ++++ drivers/video/rockchip/rga3/rga3_reg_info.c | 12 +++--- drivers/video/rockchip/rga3/rga_iommu.c | 37 ++++++++++++++++++- 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/drivers/video/rockchip/rga3/include/rga_iommu.h b/drivers/video/rockchip/rga3/include/rga_iommu.h index fd37377a74ad..5654cfd4b59c 100644 --- a/drivers/video/rockchip/rga3/include/rga_iommu.h +++ b/drivers/video/rockchip/rga3/include/rga_iommu.h @@ -4,6 +4,11 @@ #include "rga_drv.h" +/* RGA_IOMMU_INT_* register fields */ +#define RGA_IOMMU_IRQ_PAGE_FAULT 0x01 /* page fault */ +#define RGA_IOMMU_IRQ_BUS_ERROR 0x02 /* bus read error */ +#define RGA_IOMMU_IRQ_MASK (RGA_IOMMU_IRQ_PAGE_FAULT | RGA_IOMMU_IRQ_BUS_ERROR) + /* * The maximum input is 8192*8192, the maximum output is 4096*4096 * The size of physical pages requested is: diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index 7bc277a0b85a..2465b86466bd 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -2546,6 +2546,9 @@ static int rga2_irq(struct rga_scheduler_t *scheduler) if (job == NULL) return IRQ_HANDLED; + if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) + return IRQ_WAKE_THREAD; + job->intr_status = rga_read(RGA2_INT, scheduler); job->hw_status = rga_read(RGA2_STATUS2, scheduler); job->cmd_status = rga_read(RGA2_STATUS1, scheduler); @@ -2596,6 +2599,11 @@ static int rga2_isr_thread(struct rga_job *job, struct rga_scheduler_t *schedule pr_err("mmu failed, please check size of the buffer or whether the buffer has been freed.\n"); job->ret = -EACCES; } + + if (job->ret == 0) { + pr_err("rga intr error[0x%x]!\n", job->intr_status); + job->ret = -EFAULT; + } } return IRQ_HANDLED; diff --git a/drivers/video/rockchip/rga3/rga3_reg_info.c b/drivers/video/rockchip/rga3/rga3_reg_info.c index 3fac6dbf3cfc..1b3d7e2f7ad6 100644 --- a/drivers/video/rockchip/rga3/rga3_reg_info.c +++ b/drivers/video/rockchip/rga3/rga3_reg_info.c @@ -2004,6 +2004,9 @@ static int rga3_irq(struct rga_scheduler_t *scheduler) if (job == NULL) return IRQ_HANDLED; + if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) + return IRQ_WAKE_THREAD; + job->intr_status = rga_read(RGA3_INT_RAW, scheduler); job->hw_status = rga_read(RGA3_STATUS0, scheduler); job->cmd_status = rga_read(RGA3_CMD_STATE, scheduler); @@ -2038,10 +2041,7 @@ static int rga3_isr_thread(struct rga_job *job, struct rga_scheduler_t *schedule rga_read(RGA3_CMD_STATE, scheduler)); if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) { - if (job->intr_status & m_RGA3_INT_RGA_MMU_INTR) { - pr_err("iommu error, please check size of the buffer or whether the buffer has been freed.\n"); - job->ret = -EACCES; - } else if (job->intr_status & m_RGA3_INT_RAG_MI_RD_BUS_ERR) { + if (job->intr_status & m_RGA3_INT_RAG_MI_RD_BUS_ERR) { pr_err("DMA read bus error, please check size of the input_buffer or whether the buffer has been freed.\n"); job->ret = -EFAULT; } else if (job->intr_status & m_RGA3_INT_WIN0_FBCD_DEC_ERR) { @@ -2053,7 +2053,9 @@ static int rga3_isr_thread(struct rga_job *job, struct rga_scheduler_t *schedule } else if (job->intr_status & m_RGA3_INT_RGA_MI_WR_BUS_ERR) { pr_err("wr buss error, please check size of the output_buffer or whether the buffer has been freed.\n"); job->ret = -EFAULT; - } else { + } + + if (job->ret == 0) { pr_err("rga intr error[0x%x]!\n", job->intr_status); job->ret = -EFAULT; } diff --git a/drivers/video/rockchip/rga3/rga_iommu.c b/drivers/video/rockchip/rga3/rga_iommu.c index 3b7a4ef88aa2..f4fb84aec604 100644 --- a/drivers/video/rockchip/rga3/rga_iommu.c +++ b/drivers/video/rockchip/rga3/rga_iommu.c @@ -5,7 +5,7 @@ * Author: Huang Lee */ -#define pr_fmt(fmt) "rga2_mmu: " fmt +#define pr_fmt(fmt) "rga_iommu: " fmt #include "rga_iommu.h" #include "rga_dma_buf.h" @@ -221,6 +221,38 @@ void rga_mmu_base_free(struct rga_mmu_base **mmu_base) *mmu_base = NULL; } +static int rga_iommu_intr_fault_handler(struct iommu_domain *iommu, struct device *iommu_dev, + unsigned long iova, int status, void *arg) +{ + struct rga_scheduler_t *scheduler = (struct rga_scheduler_t *)arg; + struct rga_job *job = scheduler->running_job; + + if (job == NULL) + return 0; + + pr_err("IOMMU intr fault, IOVA[0x%lx], STATUS[0x%x]\n", iova, status); + if (scheduler->ops->irq) + scheduler->ops->irq(scheduler); + + /* iommu interrupts on rga2 do not affect rga2 itself. */ + if (!test_bit(RGA_JOB_STATE_INTR_ERR, &job->state)) { + set_bit(RGA_JOB_STATE_INTR_ERR, &job->state); + scheduler->ops->soft_reset(scheduler); + } + + if (status & RGA_IOMMU_IRQ_PAGE_FAULT) { + pr_err("RGA IOMMU: page fault! Please check the memory size.\n"); + job->ret = -EACCES; + } else if (status & RGA_IOMMU_IRQ_BUS_ERROR) { + pr_err("RGA IOMMU: bus error! Please check if the memory is invalid or has been freed.\n"); + job->ret = -EACCES; + } else { + pr_err("RGA IOMMU: Wrong IOMMU interrupt signal!\n"); + } + + return 0; +} + int rga_iommu_detach(struct rga_iommu_info *info) { if (!info) @@ -306,6 +338,9 @@ int rga_iommu_bind(void) if (main_iommu == NULL) { main_iommu = scheduler->iommu_info; main_iommu_index = i; + iommu_set_fault_handler(main_iommu->domain, + rga_iommu_intr_fault_handler, + (void *)scheduler); } else { scheduler->iommu_info->domain = main_iommu->domain; scheduler->iommu_info->default_dev = main_iommu->default_dev; From 97e91ee429363c4fca3c18c2ba8f1921745e72b1 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Thu, 24 Nov 2022 15:47:32 +0800 Subject: [PATCH 135/235] video: rockchip: rga3: remove useless delay for rga3 software reset Signed-off-by: Yu Qiaowei Change-Id: I244542e3a2df37b2b9ecf2d95204aa575ec65ee4 --- .../rockchip/rga3/include/rga2_reg_info.h | 13 ----- .../rockchip/rga3/include/rga3_reg_info.h | 16 ++---- .../video/rockchip/rga3/include/rga_iommu.h | 37 +++++++++++-- drivers/video/rockchip/rga3/rga2_reg_info.c | 11 ++-- drivers/video/rockchip/rga3/rga3_reg_info.c | 54 +++++++------------ 5 files changed, 62 insertions(+), 69 deletions(-) diff --git a/drivers/video/rockchip/rga3/include/rga2_reg_info.h b/drivers/video/rockchip/rga3/include/rga2_reg_info.h index 37afb7640f8a..66c467d4df46 100644 --- a/drivers/video/rockchip/rga3/include/rga2_reg_info.h +++ b/drivers/video/rockchip/rga3/include/rga2_reg_info.h @@ -41,19 +41,6 @@ #define RGA2_OSD_CUR_FLAGS0 0x090 #define RGA2_OSD_CUR_FLAGS1 0x09c -/* iommu reg */ -#define RGA2_MMU_DTE_ADDR 0xf00 -#define RGA2_MMU_STATUS 0xf04 -#define RGA2_MMU_COMMAND 0xf08 -#define RGA2_MMU_PAGE_FAULT_ADDR 0xf0c -#define RGA2_MMU_ZAP_ONE_LINE 0xf10 -#define RGA2_MMU_INT_RAWSTAT 0xf14 -#define RGA2_MMU_INT_CLEAR 0xf18 -#define RGA2_MMU_INT_MASK 0xf1c -#define RGA2_MMU_INT_STATUS 0xf20 -#define RGA2_MMU_AUTO_GATING 0xf24 -#define RGA2_MMU_REG_LOAD_EN 0xf28 - /* mode ctrl */ #define RGA2_MODE_CTRL_OFFSET 0x000 #define RGA2_SRC_INFO_OFFSET 0x004 diff --git a/drivers/video/rockchip/rga3/include/rga3_reg_info.h b/drivers/video/rockchip/rga3/include/rga3_reg_info.h index 78baf74460e8..88d05a5beccb 100644 --- a/drivers/video/rockchip/rga3/include/rga3_reg_info.h +++ b/drivers/video/rockchip/rga3/include/rga3_reg_info.h @@ -21,19 +21,6 @@ #define RGA3_SCAN_CNT 0x038 #define RGA3_CMD_STATE 0x040 -/* iommu reg */ -#define RGA3_MMU_DTE_ADDR 0xf00 -#define RGA3_MMU_STATUS 0xf04 -#define RGA3_MMU_COMMAND 0xf08 -#define RGA3_MMU_PAGE_FAULT_ADDR 0xf0c -#define RGA3_MMU_ZAP_ONE_LINE 0xf10 -#define RGA3_MMU_INT_RAWSTAT 0xf14 -#define RGA3_MMU_INT_CLEAR 0xf18 -#define RGA3_MMU_INT_MASK 0xf1c -#define RGA3_MMU_INT_STATUS 0xf20 -#define RGA3_MMU_AUTO_GATING 0xf24 -#define RGA3_MMU_REG_LOAD_EN 0xf28 - /* cmd reg */ #define RGA3_WIN0_RD_CTRL_OFFSET 0x000 #define RGA3_WIN0_Y_BASE_OFFSET 0x010 @@ -152,6 +139,9 @@ #define m_RGA3_CMD_CTRL_CMD_INCR_VALID_P (0x1 << 1) #define m_RGA3_CMD_CTRL_CMD_LINE_ST_P (0x1 << 0) +/* RGA3_RO_SRST */ +#define m_RGA3_RO_SRST_RO_RST_DONE (0x3f << 0) + /* RGA3_CMD_STATE */ #define m_RGA3_CMD_STATE_CMD_CNT_CUR (0xfff << 16) #define m_RGA3_CMD_STATE_CMD_WORKING (0x1 << 0) diff --git a/drivers/video/rockchip/rga3/include/rga_iommu.h b/drivers/video/rockchip/rga3/include/rga_iommu.h index 5654cfd4b59c..b80a1f48bb25 100644 --- a/drivers/video/rockchip/rga3/include/rga_iommu.h +++ b/drivers/video/rockchip/rga3/include/rga_iommu.h @@ -4,10 +4,41 @@ #include "rga_drv.h" +/* RGA_IOMMU register offsets */ +#define RGA_IOMMU_BASE 0xf00 +#define RGA_IOMMU_DTE_ADDR (RGA_IOMMU_BASE + 0x00) /* Directory table address */ +#define RGA_IOMMU_STATUS (RGA_IOMMU_BASE + 0x04) +#define RGA_IOMMU_COMMAND (RGA_IOMMU_BASE + 0x08) +#define RGA_IOMMU_PAGE_FAULT_ADDR (RGA_IOMMU_BASE + 0x0C) /* IOVA of last page fault */ +#define RGA_IOMMU_ZAP_ONE_LINE (RGA_IOMMU_BASE + 0x10) /* Shootdown one IOTLB entry */ +#define RGA_IOMMU_INT_RAWSTAT (RGA_IOMMU_BASE + 0x14) /* IRQ status ignoring mask */ +#define RGA_IOMMU_INT_CLEAR (RGA_IOMMU_BASE + 0x18) /* Acknowledge and re-arm irq */ +#define RGA_IOMMU_INT_MASK (RGA_IOMMU_BASE + 0x1C) /* IRQ enable */ +#define RGA_IOMMU_INT_STATUS (RGA_IOMMU_BASE + 0x20) /* IRQ status after masking */ +#define RGA_IOMMU_AUTO_GATING (RGA_IOMMU_BASE + 0x24) + +/* RGA_IOMMU_STATUS fields */ +#define RGA_IOMMU_STATUS_PAGING_ENABLED BIT(0) +#define RGA_IOMMU_STATUS_PAGE_FAULT_ACTIVE BIT(1) +#define RGA_IOMMU_STATUS_STALL_ACTIVE BIT(2) +#define RGA_IOMMU_STATUS_IDLE BIT(3) +#define RGA_IOMMU_STATUS_REPLAY_BUFFER_EMPTY BIT(4) +#define RGA_IOMMU_STATUS_PAGE_FAULT_IS_WRITE BIT(5) +#define RGA_IOMMU_STATUS_STALL_NOT_ACTIVE BIT(31) + +/* RGA_IOMMU_COMMAND command values */ +#define RGA_IOMMU_CMD_ENABLE_PAGING 0 /* Enable memory translation */ +#define RGA_IOMMU_CMD_DISABLE_PAGING 1 /* Disable memory translation */ +#define RGA_IOMMU_CMD_ENABLE_STALL 2 /* Stall paging to allow other cmds */ +#define RGA_IOMMU_CMD_DISABLE_STALL 3 /* Stop stall re-enables paging */ +#define RGA_IOMMU_CMD_ZAP_CACHE 4 /* Shoot down entire IOTLB */ +#define RGA_IOMMU_CMD_PAGE_FAULT_DONE 5 /* Clear page fault */ +#define RGA_IOMMU_CMD_FORCE_RESET 6 /* Reset all registers */ + /* RGA_IOMMU_INT_* register fields */ -#define RGA_IOMMU_IRQ_PAGE_FAULT 0x01 /* page fault */ -#define RGA_IOMMU_IRQ_BUS_ERROR 0x02 /* bus read error */ -#define RGA_IOMMU_IRQ_MASK (RGA_IOMMU_IRQ_PAGE_FAULT | RGA_IOMMU_IRQ_BUS_ERROR) +#define RGA_IOMMU_IRQ_PAGE_FAULT 0x01 /* page fault */ +#define RGA_IOMMU_IRQ_BUS_ERROR 0x02 /* bus read error */ +#define RGA_IOMMU_IRQ_MASK (RGA_IOMMU_IRQ_PAGE_FAULT | RGA_IOMMU_IRQ_BUS_ERROR) /* * The maximum input is 8192*8192, the maximum output is 4096*4096 diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index 2465b86466bd..c95ea04be224 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -2062,7 +2062,7 @@ static void rga2_soft_reset(struct rga_scheduler_t *scheduler) u32 iommu_dte_addr; if (scheduler->data->mmu == RGA_IOMMU) - iommu_dte_addr = rga_read(0xf00, scheduler); + iommu_dte_addr = rga_read(RGA_IOMMU_DTE_ADDR, scheduler); rga_write(m_RGA2_SYS_CTRL_ACLK_SRESET_P | m_RGA2_SYS_CTRL_CCLK_SRESET_P | m_RGA2_SYS_CTRL_RST_PROTECT_P, @@ -2079,13 +2079,16 @@ static void rga2_soft_reset(struct rga_scheduler_t *scheduler) } if (scheduler->data->mmu == RGA_IOMMU) { - rga_write(iommu_dte_addr, RGA2_MMU_DTE_ADDR, scheduler); + rga_write(iommu_dte_addr, RGA_IOMMU_DTE_ADDR, scheduler); /* enable iommu */ - rga_write(0, RGA2_MMU_COMMAND, scheduler); + rga_write(RGA_IOMMU_CMD_ENABLE_PAGING, RGA_IOMMU_COMMAND, scheduler); } if (i == RGA_RESET_TIMEOUT) - pr_err("soft reset timeout.\n"); + pr_err("RAG2 soft reset timeout.\n"); + else + pr_info("RGA2 soft reset complete.\n"); + } static int rga2_check_param(const struct rga_hw_data *data, const struct rga2_req *req) diff --git a/drivers/video/rockchip/rga3/rga3_reg_info.c b/drivers/video/rockchip/rga3/rga3_reg_info.c index 1b3d7e2f7ad6..bc9fa49baa45 100644 --- a/drivers/video/rockchip/rga3/rga3_reg_info.c +++ b/drivers/video/rockchip/rga3/rga3_reg_info.c @@ -9,6 +9,7 @@ #include "rga3_reg_info.h" #include "rga_dma_buf.h" +#include "rga_iommu.h" #include "rga_common.h" #include "rga_debugger.h" #include "rga_hw_config.h" @@ -1593,54 +1594,35 @@ static void rga_cmd_to_rga3_cmd(struct rga_req *req_rga, struct rga3_req *req) static void rga3_soft_reset(struct rga_scheduler_t *scheduler) { u32 i; - u32 reg; - u32 mmu_addr; + u32 iommu_dte_addr; - mmu_addr = rga_read(0xf00, scheduler); + if (scheduler->data->mmu == RGA_IOMMU) + iommu_dte_addr = rga_read(RGA_IOMMU_DTE_ADDR, scheduler); rga_write(s_RGA3_SYS_CTRL_CCLK_SRESET(1) | s_RGA3_SYS_CTRL_ACLK_SRESET(1), RGA3_SYS_CTRL, scheduler); - pr_err("soft reset sys_ctrl = %x, ro_rest = %x", - rga_read(RGA3_SYS_CTRL, scheduler), - rga_read(RGA3_RO_SRST, scheduler)); - - mdelay(20); - - pr_err("soft reset sys_ctrl = %x, ro_rest = %x", - rga_read(RGA3_SYS_CTRL, scheduler), - rga_read(RGA3_RO_SRST, scheduler)); - - rga_write(s_RGA3_SYS_CTRL_CCLK_SRESET(0) | s_RGA3_SYS_CTRL_ACLK_SRESET(0), - RGA3_SYS_CTRL, scheduler); - - pr_err("soft after reset sys_ctrl = %x, ro_rest = %x", - rga_read(RGA3_SYS_CTRL, scheduler), - rga_read(RGA3_RO_SRST, scheduler)); - - rga_write(m_RGA3_INT_FRM_DONE | m_RGA3_INT_CMD_LINE_FINISH | m_RGA3_INT_ERROR_MASK, - RGA3_INT_CLR, scheduler); - - rga_write(mmu_addr, RGA3_MMU_DTE_ADDR, scheduler); - rga_write(0, RGA3_MMU_COMMAND, scheduler); - - if (DEBUGGER_EN(INT_FLAG)) - pr_info("soft reset, INTR[0x%x], HW_STATUS[0x%x], CMD_STATUS[0x%x]\n", - rga_read(RGA3_INT_RAW, scheduler), - rga_read(RGA3_STATUS0, scheduler), - rga_read(RGA3_CMD_STATE, scheduler)); - for (i = 0; i < RGA_RESET_TIMEOUT; i++) { - reg = rga_read(RGA3_SYS_CTRL, scheduler) & 1; - - if (reg == 0) + if (rga_read(RGA3_RO_SRST, scheduler) & m_RGA3_RO_SRST_RO_RST_DONE) break; udelay(1); } + rga_write(s_RGA3_SYS_CTRL_CCLK_SRESET(0) | s_RGA3_SYS_CTRL_ACLK_SRESET(0), + RGA3_SYS_CTRL, scheduler); + + if (scheduler->data->mmu == RGA_IOMMU) { + rga_write(iommu_dte_addr, RGA_IOMMU_DTE_ADDR, scheduler); + /* enable iommu */ + rga_write(RGA_IOMMU_CMD_ENABLE_PAGING, RGA_IOMMU_COMMAND, scheduler); + } + if (i == RGA_RESET_TIMEOUT) - pr_err("soft reset timeout.\n"); + pr_err("RGA3 soft reset timeout. SYS_CTRL[0x%x], RO_SRST[0x%x]\n", + rga_read(RGA3_SYS_CTRL, scheduler), rga_read(RGA3_RO_SRST, scheduler)); + else + pr_info("RGA3 soft reset complete.\n"); } static int rga3_scale_check(const struct rga3_req *req) From fc49bfda1be215c7c1e589b9beb0374c970dbb4f Mon Sep 17 00:00:00 2001 From: Sisyphean Zhou Date: Tue, 6 Sep 2022 10:50:50 +0800 Subject: [PATCH 136/235] media: i2c: gc2093 support fastboot Signed-off-by: Sisyphean Zhou Change-Id: I3245ba187df5ddcc8c5a97e3098e1436e62d7e9d --- drivers/media/i2c/gc2093.c | 75 ++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/drivers/media/i2c/gc2093.c b/drivers/media/i2c/gc2093.c index 00018279b8b9..70d75167bb98 100644 --- a/drivers/media/i2c/gc2093.c +++ b/drivers/media/i2c/gc2093.c @@ -32,6 +32,7 @@ #include #include #include +#include "../platform/rockchip/isp/rkisp_tb_helper.h" #define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) #define GC2093_NAME "gc2093" @@ -151,6 +152,8 @@ struct gc2093 { u32 cur_vts; bool has_init_exp; + bool is_thunderboot; + bool is_first_streamoff; struct preisp_hdrae_exp_s init_hdrae_exp; }; @@ -717,6 +720,9 @@ static int __gc2093_power_on(struct gc2093 *gc2093) return ret; } + if (gc2093->is_thunderboot) + return 0; + ret = regulator_bulk_enable(GC2093_NUM_SUPPLIES, gc2093->supplies); if (ret < 0) { dev_err(dev, "Failed to enable regulators\n"); @@ -744,6 +750,16 @@ disable_clk: static void __gc2093_power_off(struct gc2093 *gc2093) { + clk_disable_unprepare(gc2093->xvclk); + if (gc2093->is_thunderboot) { + if (gc2093->is_first_streamoff) { + gc2093->is_thunderboot = false; + gc2093->is_first_streamoff = false; + } else { + return; + } + } + if (!IS_ERR(gc2093->reset_gpio)) gpiod_set_value_cansleep(gc2093->reset_gpio, 1); if (!IS_ERR(gc2093->pwdn_gpio)) @@ -755,10 +771,16 @@ static void __gc2093_power_off(struct gc2093 *gc2093) static int gc2093_check_sensor_id(struct gc2093 *gc2093) { + struct device *dev = gc2093->dev; u8 id_h = 0, id_l = 0; u16 id = 0; int ret = 0; + if (gc2093->is_thunderboot) { + dev_info(dev, "Enable thunderboot mode, skip sensor id check\n"); + return 0; + } + ret = gc2093_read_reg(gc2093, GC2093_REG_CHIP_ID_H, &id_h); ret |= gc2093_read_reg(gc2093, GC2093_REG_CHIP_ID_L, &id_l); if (ret) { @@ -933,26 +955,27 @@ static int __gc2093_start_stream(struct gc2093 *gc2093) { int ret; - ret = regmap_multi_reg_write(gc2093->regmap, - gc2093->cur_mode->reg_list, - gc2093->cur_mode->reg_num); - if (ret) - return ret; - - /* Apply customized control from user */ - mutex_unlock(&gc2093->lock); - v4l2_ctrl_handler_setup(&gc2093->ctrl_handler); - mutex_lock(&gc2093->lock); - - if (gc2093->has_init_exp && gc2093->cur_mode->hdr_mode != NO_HDR) { - ret = gc2093_ioctl(&gc2093->subdev, PREISP_CMD_SET_HDRAE_EXP, - &gc2093->init_hdrae_exp); - if (ret) { - dev_err(gc2093->dev, "init exp fail in hdr mode\n"); + if (!gc2093->is_thunderboot) { + ret = regmap_multi_reg_write(gc2093->regmap, + gc2093->cur_mode->reg_list, + gc2093->cur_mode->reg_num); + if (ret) return ret; + + /* Apply customized control from user */ + mutex_unlock(&gc2093->lock); + v4l2_ctrl_handler_setup(&gc2093->ctrl_handler); + mutex_lock(&gc2093->lock); + + if (gc2093->has_init_exp && gc2093->cur_mode->hdr_mode != NO_HDR) { + ret = gc2093_ioctl(&gc2093->subdev, PREISP_CMD_SET_HDRAE_EXP, + &gc2093->init_hdrae_exp); + if (ret) { + dev_err(gc2093->dev, "init exp fail in hdr mode\n"); + return ret; + } } } - return gc2093_write_reg(gc2093, GC2093_REG_CTRL_MODE, GC2093_MODE_STREAMING); } @@ -960,6 +983,10 @@ static int __gc2093_start_stream(struct gc2093 *gc2093) static int __gc2093_stop_stream(struct gc2093 *gc2093) { gc2093->has_init_exp = false; + if (gc2093->is_thunderboot) { + gc2093->is_first_streamoff = true; + return 0; + } return gc2093_write_reg(gc2093, GC2093_REG_CTRL_MODE, GC2093_MODE_SW_STANDBY); } @@ -1070,6 +1097,10 @@ static int gc2093_s_stream(struct v4l2_subdev *sd, int on) goto unlock_and_return; if (on) { + if (gc2093->is_thunderboot && rkisp_tb_get_state() == RKISP_TB_NG) { + gc2093->is_thunderboot = false; + __gc2093_power_on(gc2093); + } ret = pm_runtime_get_sync(gc2093->dev); if (ret < 0) { pm_runtime_put_noidle(gc2093->dev); @@ -1395,17 +1426,19 @@ static int gc2093_probe(struct i2c_client *client, return -EINVAL; } + gc2093->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); + gc2093->xvclk = devm_clk_get(gc2093->dev, "xvclk"); if (IS_ERR(gc2093->xvclk)) { dev_err(gc2093->dev, "Failed to get xvclk\n"); return -EINVAL; } - gc2093->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + gc2093->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS); if (IS_ERR(gc2093->reset_gpio)) dev_warn(dev, "Failed to get reset-gpios\n"); - gc2093->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_HIGH); + gc2093->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_ASIS); if (IS_ERR(gc2093->pwdn_gpio)) dev_warn(dev, "Failed to get pwdn-gpios\n"); @@ -1535,7 +1568,11 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&gc2093_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("Galaxycore GC2093 Image Sensor driver"); From 39115e823ead36f4320fd113bbc98e3b9374c43d Mon Sep 17 00:00:00 2001 From: Wang Xiaobin Date: Thu, 22 Sep 2022 17:55:28 +0800 Subject: [PATCH 137/235] media: i2c: gc2093 support get real fps Signed-off-by: Wang Xiaobin Change-Id: I452732edf63ed913360d309ace457097ff8afedd --- drivers/media/i2c/gc2093.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/gc2093.c b/drivers/media/i2c/gc2093.c index 70d75167bb98..0edb5bf12944 100644 --- a/drivers/media/i2c/gc2093.c +++ b/drivers/media/i2c/gc2093.c @@ -149,9 +149,11 @@ struct gc2093 { const char *module_facing; const char *module_name; const char *len_name; - u32 cur_vts; - bool has_init_exp; + struct v4l2_fract cur_fps; + u32 cur_vts; + + bool has_init_exp; bool is_thunderboot; bool is_first_streamoff; struct preisp_hdrae_exp_s init_hdrae_exp; @@ -551,6 +553,14 @@ static int gc2093_set_gain(struct gc2093 *gc2093, u32 gain) return ret; } +static void gc2093_modify_fps_info(struct gc2093 *gc2093) +{ + const struct gc2093_mode *mode = gc2093->cur_mode; + + gc2093->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / + gc2093->cur_vts; +} + static int gc2093_set_ctrl(struct v4l2_ctrl *ctrl) { struct gc2093 *gc2093 = container_of(ctrl->handler, @@ -596,6 +606,8 @@ static int gc2093_set_ctrl(struct v4l2_ctrl *ctrl) (vts >> 8) & 0x3f); ret |= gc2093_write_reg(gc2093, GC2093_REG_VTS_L, vts & 0xff); + if (gc2093->cur_vts != gc2093->cur_mode->vts_def) + gc2093_modify_fps_info(gc2093); dev_dbg(gc2093->dev, " set blank value 0x%x\n", ctrl->val); break; case V4L2_CID_HFLIP: @@ -694,6 +706,8 @@ static int gc2093_initialize_controls(struct gc2093 *gc2093) gc2093->subdev.ctrl_handler = handler; gc2093->has_init_exp = false; + gc2093->cur_vts = mode->vts_def; + gc2093->cur_fps = mode->max_fps; return 0; @@ -921,6 +935,7 @@ static long gc2093_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) GC2093_VTS_MAX - gc2093->cur_mode->height, 1, h); gc2093->cur_vts = gc2093->cur_mode->vts_def; + gc2093->cur_fps = gc2093->cur_mode->max_fps; dev_info(gc2093->dev, "sensor mode: %d\n", gc2093->cur_mode->hdr_mode); } @@ -1242,6 +1257,8 @@ static int gc2093_set_fmt(struct v4l2_subdev *sd, __v4l2_ctrl_modify_range(gc2093->vblank, vblank_def, GC2093_VTS_MAX - mode->height, 1, vblank_def); + gc2093->cur_vts = mode->vts_def; + gc2093->cur_fps = mode->max_fps; } mutex_unlock(&gc2093->lock); From fea2e9f574e7a491cf9486bee6b8b31985d15724 Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Thu, 17 Nov 2022 11:32:57 +0800 Subject: [PATCH 138/235] media: i2c: gc2093: pm_runtime_put device until stream_off for thunderboot The camera device should keep *power on* until stream off, that make sure the mclk is enable. Signed-off-by: Lin Jinhan Change-Id: Iad14d6648b24c5e9202ba2cef2199e35fbe18fbb --- drivers/media/i2c/gc2093.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/gc2093.c b/drivers/media/i2c/gc2093.c index 0edb5bf12944..a85a2a696bab 100644 --- a/drivers/media/i2c/gc2093.c +++ b/drivers/media/i2c/gc2093.c @@ -1000,7 +1000,7 @@ static int __gc2093_stop_stream(struct gc2093 *gc2093) gc2093->has_init_exp = false; if (gc2093->is_thunderboot) { gc2093->is_first_streamoff = true; - return 0; + pm_runtime_put(gc2093->dev); } return gc2093_write_reg(gc2093, GC2093_REG_CTRL_MODE, GC2093_MODE_SW_STANDBY); @@ -1517,7 +1517,10 @@ static int gc2093_probe(struct i2c_client *client, pm_runtime_set_active(dev); pm_runtime_enable(dev); - pm_runtime_idle(dev); + if (gc2093->is_thunderboot) + pm_runtime_get_sync(dev); + else + pm_runtime_idle(dev); return 0; From 2365d6f63807c4870402429e8b76fee2c75452f2 Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Wed, 28 Sep 2022 10:43:33 +0800 Subject: [PATCH 139/235] ARM: dts: rockchip: rv1106g-smart-door: add gc2093 thunder boot support Signed-off-by: Lin Jinhan Change-Id: I2578c1d45a037f0920dbc92f9973d7b8031eede4 --- arch/arm/boot/dts/rv1106-smd-cam.dtsi | 18 ++++++++++++++++++ .../dts/rv1106g-smart-door-lock-rmsl-v10.dts | 5 +++++ 2 files changed, 23 insertions(+) diff --git a/arch/arm/boot/dts/rv1106-smd-cam.dtsi b/arch/arm/boot/dts/rv1106-smd-cam.dtsi index 7238b22f6a05..ee12cd83c919 100644 --- a/arch/arm/boot/dts/rv1106-smd-cam.dtsi +++ b/arch/arm/boot/dts/rv1106-smd-cam.dtsi @@ -9,6 +9,8 @@ / { vcc1v2_dvdd: vcc1v8_dovdd: vcc2v8_avdd: vcc-camera { compatible = "regulator-fixed"; + regulator-boot-on; + regulator-always-on; regulator-name = "vcc_camera"; pinctrl-names = "default"; pinctrl-0 = <&cam_pwren>; @@ -151,6 +153,8 @@ }; &i2c4 { + rockchip,amp-shared; + status = "okay"; clock-frequency = <400000>; pinctrl-names = "default"; @@ -227,6 +231,7 @@ &rkcif_mipi_lvds { status = "okay"; + memory-region-thunderboot = <&rkisp_thunderboot>; port { /* MIPI CSI-2 endpoint */ cif_mipi0_in: endpoint { @@ -313,6 +318,19 @@ max-input = <1920 1280 30>; }; +&mailbox { + status = "okay"; +}; + +&thunder_boot_service { + status = "okay"; +}; + +&rkisp_thunderboot { + /* vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num) */ + reg = <0x00860000 0xa8c000>; +}; + &rkisp_vir0 { status = "okay"; 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 16b9fb261d17..258cff792f76 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 @@ -14,6 +14,7 @@ model = "Rockchip RV1106G Smart Door Lock RMSL V10 Board"; compatible = "rockchip,rv1106g-smart-door-lock-rmsl-v10", "rockchip,rv1106"; + /* rkaiq_prd_type: 1 for one camera, 2 for multi camera */ chosen { bootargs = "loglevel=0 rootfstype=erofs rootflags=dax console=ttyFIQ0 root=/dev/rd0 snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0 driver_async_probe=dwmmc_rockchip"; }; @@ -146,6 +147,10 @@ }; }; +&thunder_boot_service { + status = "okay"; +}; + &u2phy_otg { status = "okay"; }; From cac789f29a4acd5641a8d70b67c0c19b6a02d8aa Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Fri, 28 Oct 2022 16:31:54 +0800 Subject: [PATCH 140/235] ARM: configs: rv1106-smart-door: enable camera thunder boot CONFIG_MAILBOX=y CONFIG_ROCKCHIP_MBOX=y CONFIG_ROCKCHIP_THUNDER_BOOT_SERVICE=y SPI_NOR compiled as module. Signed-off-by: Lin Jinhan Change-Id: I1ab9ed6265f233875451ef5cf9daf50bae1e4632 --- arch/arm/configs/rv1106-smart-door.config | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/rv1106-smart-door.config b/arch/arm/configs/rv1106-smart-door.config index 054a0a8cb5de..a6e88490018c 100644 --- a/arch/arm/configs/rv1106-smart-door.config +++ b/arch/arm/configs/rv1106-smart-door.config @@ -14,11 +14,14 @@ CONFIG_EEPROM_AT24=y CONFIG_EXTCON=m CONFIG_JFFS2_FS=y CONFIG_KEYS=y +CONFIG_MAILBOX=y +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m CONFIG_NVMEM_SYSFS=y CONFIG_RFKILL=y CONFIG_RK803=y CONFIG_ROCKCHIP_HW_DECOMPRESS_USER=y -CONFIG_ROCKCHIP_VENDOR_STORAGE=y +CONFIG_ROCKCHIP_VENDOR_STORAGE=m CONFIG_SPI=y # CONFIG_SQUASHFS is not set CONFIG_USB_SUPPORT=y @@ -85,6 +88,10 @@ CONFIG_WLAN=y # CONFIG_ADXRS290 is not set # CONFIG_ADXRS450 is not set # CONFIG_AFE4403 is not set +# CONFIG_ALTERA_MBOX is not set +# CONFIG_ARM_MHU is not set +# CONFIG_ARM_SCMI_PROTOCOL is not set +# CONFIG_ARM_SCPI_PROTOCOL is not set # CONFIG_AS3935 is not set CONFIG_ASN1=y CONFIG_ASSOCIATIVE_ARRAY=y @@ -183,6 +190,7 @@ CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y CONFIG_MAC80211_RC_MINSTREL=y CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +# CONFIG_MAILBOX_TEST is not set # CONFIG_MAX1027 is not set # CONFIG_MAX11100 is not set # CONFIG_MAX1118 is not set @@ -211,10 +219,11 @@ CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 # CONFIG_MOXTET is not set CONFIG_MPILIB=y # CONFIG_MPL115_SPI is not set +# CONFIG_MTD_BLOCK_RO is not set # CONFIG_MTD_DATAFLASH is not set # CONFIG_MTD_MCHP23K256 is not set # CONFIG_MTD_SPI_NAND is not set -CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR=m # CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set # CONFIG_MTD_SST25L is not set # CONFIG_NL80211_TESTMODE is not set @@ -230,12 +239,17 @@ CONFIG_PHY_ROCKCHIP_INNO_USB2=m # CONFIG_PI433 is not set CONFIG_PKCS7_MESSAGE_PARSER=y # CONFIG_PKCS8_PRIVATE_KEY_PARSER is not set +# CONFIG_PL320_MBOX is not set +# CONFIG_PLATFORM_MHU is not set CONFIG_REGMAP_SPI=y # CONFIG_REGULATOR_TPS6524X is not set # CONFIG_RFKILL_GPIO is not set CONFIG_RFKILL_RK=y +CONFIG_ROCKCHIP_MBOX=y # CONFIG_ROCKCHIP_MMC_VENDOR_STORAGE is not set -CONFIG_ROCKCHIP_MTD_VENDOR_STORAGE=y +CONFIG_ROCKCHIP_MTD_VENDOR_STORAGE=m +CONFIG_ROCKCHIP_THUNDER_BOOT_SERVICE=y +# CONFIG_RPMSG_QCOM_GLINK_RPM is not set # CONFIG_RTC_DRV_DS1302 is not set # CONFIG_RTC_DRV_DS1305 is not set # CONFIG_RTC_DRV_DS1343 is not set From 4612b633c967011f377ebbd714a7a3c8d73fb516 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Thu, 24 Nov 2022 09:21:04 +0000 Subject: [PATCH 141/235] media: i2c: Lontium bridge: add CSI BGR888 media bus format Change-Id: I0da2e6e9c6683ae6ac4c0a900b9d3bb6291d0a4c Signed-off-by: Jianwei Fan --- drivers/media/i2c/lt6911uxc.c | 16 +++++++++++----- drivers/media/i2c/lt7911d.c | 16 +++++++++++----- drivers/media/i2c/lt7911uxc.c | 21 ++++++++++++++------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/drivers/media/i2c/lt6911uxc.c b/drivers/media/i2c/lt6911uxc.c index 86e2c93a0909..07ada7454eca 100644 --- a/drivers/media/i2c/lt6911uxc.c +++ b/drivers/media/i2c/lt6911uxc.c @@ -42,6 +42,12 @@ #define I2C_MAX_XFER_SIZE 128 +#ifdef LT6911UXC_OUT_RGB +#define LT6911UXC_MEDIA_BUS_FMT MEDIA_BUS_FMT_BGR888_1X24 +#else +#define LT6911UXC_MEDIA_BUS_FMT MEDIA_BUS_FMT_UYVY8_2X8 +#endif + static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "debug level (0-2)"); @@ -784,7 +790,7 @@ static int lt6911uxc_enum_mbus_code(struct v4l2_subdev *sd, { switch (code->index) { case 0: - code->code = MEDIA_BUS_FMT_UYVY8_2X8; + code->code = LT6911UXC_MEDIA_BUS_FMT; break; default: @@ -801,7 +807,7 @@ static int lt6911uxc_enum_frame_sizes(struct v4l2_subdev *sd, if (fse->index >= ARRAY_SIZE(supported_modes)) return -EINVAL; - if (fse->code != MEDIA_BUS_FMT_UYVY8_2X8) + if (fse->code != LT6911UXC_MEDIA_BUS_FMT) return -EINVAL; fse->min_width = supported_modes[fse->index].width; @@ -819,7 +825,7 @@ static int lt6911uxc_enum_frame_interval(struct v4l2_subdev *sd, if (fie->index >= ARRAY_SIZE(supported_modes)) return -EINVAL; - if (fie->code != MEDIA_BUS_FMT_UYVY8_2X8) + if (fie->code != LT6911UXC_MEDIA_BUS_FMT) return -EINVAL; fie->width = supported_modes[fie->index].width; @@ -897,7 +903,7 @@ static int lt6911uxc_set_fmt(struct v4l2_subdev *sd, return ret; switch (code) { - case MEDIA_BUS_FMT_UYVY8_2X8: + case LT6911UXC_MEDIA_BUS_FMT: break; default: @@ -1295,7 +1301,7 @@ static int lt6911uxc_probe(struct i2c_client *client, sd = <6911uxc->sd; lt6911uxc->i2c_client = client; lt6911uxc->cur_mode = &supported_modes[0]; - lt6911uxc->mbus_fmt_code = MEDIA_BUS_FMT_UYVY8_2X8; + lt6911uxc->mbus_fmt_code = LT6911UXC_MEDIA_BUS_FMT; err = lt6911uxc_parse_of(lt6911uxc); if (err) { diff --git a/drivers/media/i2c/lt7911d.c b/drivers/media/i2c/lt7911d.c index 4e295d4159a2..f2a479946174 100644 --- a/drivers/media/i2c/lt7911d.c +++ b/drivers/media/i2c/lt7911d.c @@ -49,6 +49,12 @@ MODULE_PARM_DESC(debug, "debug level (0-3)"); #define LT7911D_LINK_FREQ 400000000 #define LT7911D_PIXEL_RATE 400000000 +#ifdef LT7911D_OUT_RGB +#define LT7911D_MEDIA_BUS_FMT MEDIA_BUS_FMT_BGR888_1X24 +#else +#define LT7911D_MEDIA_BUS_FMT MEDIA_BUS_FMT_UYVY8_2X8 +#endif + #define LT7911D_NAME "LT7911D" static const s64 link_freq_menu_items[] = { @@ -756,7 +762,7 @@ static int lt7911d_enum_mbus_code(struct v4l2_subdev *sd, { switch (code->index) { case 0: - code->code = MEDIA_BUS_FMT_UYVY8_2X8; + code->code = LT7911D_MEDIA_BUS_FMT; break; default: @@ -773,7 +779,7 @@ static int lt7911d_enum_frame_sizes(struct v4l2_subdev *sd, if (fse->index >= ARRAY_SIZE(supported_modes)) return -EINVAL; - if (fse->code != MEDIA_BUS_FMT_UYVY8_2X8) + if (fse->code != LT7911D_MEDIA_BUS_FMT) return -EINVAL; fse->min_width = supported_modes[fse->index].width; @@ -814,7 +820,7 @@ static int lt7911d_enum_frame_interval(struct v4l2_subdev *sd, if (fie->index >= ARRAY_SIZE(supported_modes)) return -EINVAL; - if (fie->code != MEDIA_BUS_FMT_UYVY8_2X8) + if (fie->code != LT7911D_MEDIA_BUS_FMT) return -EINVAL; fie->width = supported_modes[fie->index].width; @@ -868,7 +874,7 @@ static int lt7911d_set_fmt(struct v4l2_subdev *sd, return ret; switch (code) { - case MEDIA_BUS_FMT_UYVY8_2X8: + case LT7911D_MEDIA_BUS_FMT: break; default: @@ -1227,7 +1233,7 @@ static int lt7911d_probe(struct i2c_client *client, sd = <7911d->sd; lt7911d->i2c_client = client; lt7911d->cur_mode = &supported_modes[0]; - lt7911d->mbus_fmt_code = MEDIA_BUS_FMT_UYVY8_2X8; + lt7911d->mbus_fmt_code = LT7911D_MEDIA_BUS_FMT; err = lt7911d_probe_of(lt7911d); if (err) { diff --git a/drivers/media/i2c/lt7911uxc.c b/drivers/media/i2c/lt7911uxc.c index 21ba5062e8ae..f89aa0f272e3 100644 --- a/drivers/media/i2c/lt7911uxc.c +++ b/drivers/media/i2c/lt7911uxc.c @@ -11,6 +11,7 @@ * V0.0X01.0X02 add CPHY support. * V0.0X01.0X03 add rk3588 dcphy param. * V0.0X01.0X04 add 5K60 support for CPHY. + * V0.0X01.0X05 add CSI BGR888 fmt. * */ @@ -38,7 +39,7 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x04) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x05) static int debug; module_param(debug, int, 0644); @@ -93,6 +94,12 @@ MODULE_PARM_DESC(debug, "debug level (0-3)"); #define ENABLE_STREAM 0x01 #define DISABLE_STREAM 0x00 +#ifdef LT7911UXC_OUT_RGB +#define LT7911UXC_MEDIA_BUS_FMT MEDIA_BUS_FMT_BGR888_1X24 +#else +#define LT7911UXC_MEDIA_BUS_FMT MEDIA_BUS_FMT_UYVY8_2X8 +#endif + #define LT7911UXC_NAME "LT7911UXC" static const s64 link_freq_menu_items[] = { @@ -893,7 +900,7 @@ static int lt7911uxc_enum_mbus_code(struct v4l2_subdev *sd, { switch (code->index) { case 0: - code->code = MEDIA_BUS_FMT_UYVY8_2X8; + code->code = LT7911UXC_MEDIA_BUS_FMT; break; default: @@ -912,7 +919,7 @@ static int lt7911uxc_enum_frame_sizes(struct v4l2_subdev *sd, if (fse->index >= lt7911uxc->cfg_num) return -EINVAL; - if (fse->code != MEDIA_BUS_FMT_UYVY8_2X8) + if (fse->code != LT7911UXC_MEDIA_BUS_FMT) return -EINVAL; fse->min_width = lt7911uxc->support_modes[fse->index].width; @@ -955,7 +962,7 @@ static int lt7911uxc_enum_frame_interval(struct v4l2_subdev *sd, if (fie->index >= lt7911uxc->cfg_num) return -EINVAL; - if (fie->code != MEDIA_BUS_FMT_UYVY8_2X8) + if (fie->code != LT7911UXC_MEDIA_BUS_FMT) return -EINVAL; fie->width = lt7911uxc->support_modes[fie->index].width; @@ -1009,7 +1016,7 @@ static int lt7911uxc_set_fmt(struct v4l2_subdev *sd, return ret; switch (code) { - case MEDIA_BUS_FMT_UYVY8_2X8: + case LT7911UXC_MEDIA_BUS_FMT: break; default: @@ -1205,7 +1212,7 @@ static int lt7911uxc_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) /* Initialize try_fmt */ try_fmt->width = def_mode->width; try_fmt->height = def_mode->height; - try_fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; + try_fmt->code = LT7911UXC_MEDIA_BUS_FMT; try_fmt->field = V4L2_FIELD_NONE; mutex_unlock(<7911uxc->confctl_mutex); @@ -1469,7 +1476,7 @@ static int lt7911uxc_probe(struct i2c_client *client, sd = <7911uxc->sd; lt7911uxc->i2c_client = client; - lt7911uxc->mbus_fmt_code = MEDIA_BUS_FMT_UYVY8_2X8; + lt7911uxc->mbus_fmt_code = LT7911UXC_MEDIA_BUS_FMT; err = lt7911uxc_probe_of(lt7911uxc); if (err) { From d9cadd60bee2bf953da7b15ab2d0438dea049ab7 Mon Sep 17 00:00:00 2001 From: Herman Chen Date: Fri, 25 Nov 2022 10:04:03 +0800 Subject: [PATCH 142/235] arm64: dts: rockchip: rk3588: Add avsd skip pmu idle Signed-off-by: Herman Chen Change-Id: Ia71449a6a2d5e5e0fd4d0cdc1a433d1cb0ea7113 --- arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi index 1a67dec544bb..9020e7a9999d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -2965,6 +2965,7 @@ clock-names = "aclk_vcodec", "hclk_vcodec"; resets = <&cru SRST_A_VPU>, <&cru SRST_H_VPU>; reset-names = "shared_video_a", "shared_video_h"; + rockchip,skip-pmu-idle-request; iommus = <&vdpu_mmu>; power-domains = <&power RK3588_PD_VDPU>; rockchip,srv = <&mpp_srv>; From b63c12102a1bdf55e103946efc66de46b7c5736d Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 24 Nov 2022 11:23:08 +0800 Subject: [PATCH 143/235] ARM: dts: rockchip: rk3288: move psci node to core dtsi Currently the psci node is in rk3288-linx/android.dtsi file, move them into the core dt file. Signed-off-by: Jianqun Xu Change-Id: I0265719ab4eb6b05cb3c9414fd54f916fcce9d77 --- arch/arm/boot/dts/rk3288-android.dtsi | 21 --------------------- arch/arm/boot/dts/rk3288-firefly-rk808.dts | 21 --------------------- arch/arm/boot/dts/rk3288-linux.dtsi | 21 --------------------- arch/arm/boot/dts/rk3288.dtsi | 9 +++++++++ 4 files changed, 9 insertions(+), 63 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-android.dtsi b/arch/arm/boot/dts/rk3288-android.dtsi index b1d9d742c835..4922f3c00bae 100644 --- a/arch/arm/boot/dts/rk3288-android.dtsi +++ b/arch/arm/boot/dts/rk3288-android.dtsi @@ -152,11 +152,6 @@ }; }; - psci { - compatible = "arm,psci-1.0"; - method = "smc"; - }; - /delete-node/ timer@ff810000; display-subsystem { @@ -243,22 +238,6 @@ }; }; -&cpu0 { - enable-method = "psci"; -}; - -&cpu1 { - enable-method = "psci"; -}; - -&cpu2 { - enable-method = "psci"; -}; - -&cpu3 { - enable-method = "psci"; -}; - &dmac_bus_s { /* change to non-secure dmac */ reg = <0x0 0xff600000 0x0 0x4000>; diff --git a/arch/arm/boot/dts/rk3288-firefly-rk808.dts b/arch/arm/boot/dts/rk3288-firefly-rk808.dts index 0990c326f465..dc418937de2d 100644 --- a/arch/arm/boot/dts/rk3288-firefly-rk808.dts +++ b/arch/arm/boot/dts/rk3288-firefly-rk808.dts @@ -217,11 +217,6 @@ clock-names = "ext_clock"; }; - psci { - compatible = "arm,psci-1.0"; - method = "smc"; - }; - rk_key: rockchip-key { compatible = "rockchip,key"; status = "okay"; @@ -632,22 +627,6 @@ status = "okay"; }; -&cpu0 { - enable-method = "psci"; -}; - -&cpu1 { - enable-method = "psci"; -}; - -&cpu2 { - enable-method = "psci"; -}; - -&cpu3 { - enable-method = "psci"; -}; - &dfi { status = "okay"; }; diff --git a/arch/arm/boot/dts/rk3288-linux.dtsi b/arch/arm/boot/dts/rk3288-linux.dtsi index c5d9dc214bab..8262a19d8b52 100644 --- a/arch/arm/boot/dts/rk3288-linux.dtsi +++ b/arch/arm/boot/dts/rk3288-linux.dtsi @@ -95,11 +95,6 @@ pinctrl-0 = <&uart2_xfer>; }; - psci { - compatible = "arm,psci-1.0"; - method = "smc"; - }; - /delete-node/ timer@ff810000; display-subsystem { @@ -157,22 +152,6 @@ }; }; -&cpu0 { - enable-method = "psci"; -}; - -&cpu1 { - enable-method = "psci"; -}; - -&cpu2 { - enable-method = "psci"; -}; - -&cpu3 { - enable-method = "psci"; -}; - &dmac_bus_s { /* change to non-secure dmac */ reg = <0x0 0xff600000 0x0 0x4000>; diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index b37075bc74f7..2b05d31b4df3 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -60,6 +60,11 @@ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; }; + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -70,6 +75,7 @@ device_type = "cpu"; compatible = "arm,cortex-a12"; reg = <0x500>; + enable-method = "psci"; resets = <&cru SRST_CORE0>; operating-points-v2 = <&cpu_opp_table>; #cooling-cells = <2>; /* min followed by max */ @@ -81,6 +87,7 @@ device_type = "cpu"; compatible = "arm,cortex-a12"; reg = <0x501>; + enable-method = "psci"; resets = <&cru SRST_CORE1>; operating-points-v2 = <&cpu_opp_table>; #cooling-cells = <2>; /* min followed by max */ @@ -92,6 +99,7 @@ device_type = "cpu"; compatible = "arm,cortex-a12"; reg = <0x502>; + enable-method = "psci"; resets = <&cru SRST_CORE2>; operating-points-v2 = <&cpu_opp_table>; #cooling-cells = <2>; /* min followed by max */ @@ -103,6 +111,7 @@ device_type = "cpu"; compatible = "arm,cortex-a12"; reg = <0x503>; + enable-method = "psci"; resets = <&cru SRST_CORE3>; operating-points-v2 = <&cpu_opp_table>; #cooling-cells = <2>; /* min followed by max */ From 1d10186b4c947c7db19a7c2a25ff509c34c8f309 Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Thu, 24 Nov 2022 11:38:17 +0800 Subject: [PATCH 144/235] mmc: mmc_ops: Skip checking ocr for thunder boot In order to make eMMC boot more fast. Signed-off-by: Weiwen Chen Change-Id: Ib8b076f30746c9b0043e464581985f10867e9054 --- drivers/mmc/core/mmc_ops.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 2715e5031843..db9474c9b740 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -184,6 +184,12 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) if (err) break; +#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT + /* if we're just probing, do a single pass */ + if (ocr == 0) + break; +#endif + /* * According to eMMC specification v5.1 section A6.1, the R3 * response value should be 0x00FF8080, 0x40FF8080, 0x80FF8080 From 7ea35f7e2952cd902353b5abf2ea422d0eab65f6 Mon Sep 17 00:00:00 2001 From: Herman Chen Date: Fri, 25 Nov 2022 10:15:22 +0800 Subject: [PATCH 145/235] arm64: dts: rockchip: rk3588-evb: enable avs+ decoder Signed-off-by: Herman Chen Change-Id: Iee041320e2b24769f28895d126657c30f9c4925e --- arch/arm64/boot/dts/rockchip/rk3588-evb.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb.dtsi index 4882092c2ea5..412b2b3f889e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb.dtsi @@ -218,6 +218,10 @@ status = "okay"; }; +&avsd { + status = "okay"; +}; + &cpu_l0 { cpu-supply = <&vdd_cpu_lit_s0>; mem-supply = <&vdd_cpu_lit_mem_s0>; From b1657c60d088ba555847521ce697d05264b8597d Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Tue, 30 Aug 2022 06:18:12 +0000 Subject: [PATCH 146/235] media: i2c: lt6911uxe: add lt6911uxe HDMI to MIPI-CSI2 bridge driver Signed-off-by: Jianwei Fan Change-Id: I8310c61a4dedfee6d0b38f4f7eb34da937dd0530 --- drivers/media/i2c/Kconfig | 11 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/lt6911uxe.c | 1560 +++++++++++++++++++++++++++++++++ 3 files changed, 1572 insertions(+) create mode 100644 drivers/media/i2c/lt6911uxe.c diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 5ed7c572bb86..f4981e72c46d 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -368,6 +368,17 @@ config VIDEO_LT6911UXC To compile this driver as a module, choose M here: the module will be called lt6911uxc. +config VIDEO_LT6911UXE + tristate "Lontium LT6911UXE decoder" + depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API + select HDMI + select V4L2_FWNODE + help + Support for the Lontium LT6911UXE series HDMI to MIPI CSI-2 bridge. + + To compile this driver as a module, choose M here: the + module will be called lt6911uxe. + config VIDEO_LT7911D tristate "Lontium LT7911D decoder" depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 557ab737a7c3..6d11fdfa478f 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -155,6 +155,7 @@ obj-$(CONFIG_VIDEO_LM3560) += lm3560.o obj-$(CONFIG_VIDEO_LM3646) += lm3646.o obj-$(CONFIG_VIDEO_SGM3784) += sgm3784.o obj-$(CONFIG_VIDEO_LT6911UXC) += lt6911uxc.o +obj-$(CONFIG_VIDEO_LT6911UXE) += lt6911uxe.o obj-$(CONFIG_VIDEO_IT6616) += it6616.o obj-$(CONFIG_VIDEO_LT7911D) += lt7911d.o obj-$(CONFIG_VIDEO_LT7911UXC) += lt7911uxc.o diff --git a/drivers/media/i2c/lt6911uxe.c b/drivers/media/i2c/lt6911uxe.c new file mode 100644 index 000000000000..786d794c7a81 --- /dev/null +++ b/drivers/media/i2c/lt6911uxe.c @@ -0,0 +1,1560 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 Rockchip Electronics Co. Ltd. + * + * lt6911uxe HDMI to MIPI CSI-2 bridge driver. + * + * Author: Jianwei Fan + * + * V0.0X01.0X00 first version. + * V0.0X01.0X01 support DPHY 4K60. + * V0.0X01.0X02 support BGR888 format. + * + */ +// #define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "debug level (0-3)"); + +#define I2C_MAX_XFER_SIZE 128 +#define POLL_INTERVAL_MS 1000 + +#define LT6911UXE_LINK_FREQ_HIGH 1250000000 +#define LT6911UXE_LINK_FREQ_MID 400000000 +#define LT6911UXE_LINK_FREQ_LOW 200000000 +#define LT6911UXE_PIXEL_RATE 800000000 + +#define LT6911UXE_CHIPID 0x0221 +#define CHIPID_REGH 0xe101 +#define CHIPID_REGL 0xe100 +#define I2C_EN_REG 0xe0ee +#define I2C_ENABLE 0x1 +#define I2C_DISABLE 0x0 + +#define HTOTAL_H 0xe088 +#define HTOTAL_L 0xe089 +#define HACT_H 0xe08c +#define HACT_L 0xe08d + +#define VTOTAL_H 0xe08a +#define VTOTAL_L 0xe08b +#define VACT_H 0xe08e +#define VACT_L 0xe08f + +#define PCLK_H 0xe085 +#define PCLK_M 0xe086 +#define PCLK_L 0xe087 + +#define BYTE_PCLK_H 0xe092 +#define BYTE_PCLK_M 0xe093 +#define BYTE_PCLK_L 0xe094 + +#define AUDIO_FS_VALUE_H 0xe090 +#define AUDIO_FS_VALUE_L 0xe091 + +#define LNAE_NUM 0xe095 +#define BUS_FMT 0xe096 + +#define STREAM_CTL 0xe0b0 +#define ENABLE_STREAM 0x01 +#define DISABLE_STREAM 0x00 + +// #define LT6911UXE_OUT_RGB +#ifdef LT6911UXE_OUT_RGB +#define LT6911UXE_MEDIA_BUS_FMT MEDIA_BUS_FMT_BGR888_1X24 +#else +#define LT6911UXE_MEDIA_BUS_FMT MEDIA_BUS_FMT_UYVY8_2X8 +#endif + +#define LT6911UXE_NAME "LT6911UXE" + +static const s64 link_freq_menu_items[] = { + LT6911UXE_LINK_FREQ_HIGH, + LT6911UXE_LINK_FREQ_MID, + LT6911UXE_LINK_FREQ_LOW, +}; + +struct lt6911uxe { + struct v4l2_fwnode_bus_mipi_csi2 bus; + struct v4l2_subdev sd; + struct media_pad pad; + struct v4l2_ctrl_handler hdl; + struct i2c_client *i2c_client; + struct mutex confctl_mutex; + struct v4l2_ctrl *detect_tx_5v_ctrl; + struct v4l2_ctrl *audio_sampling_rate_ctrl; + struct v4l2_ctrl *audio_present_ctrl; + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate; + struct delayed_work delayed_work_hotplug; + struct delayed_work delayed_work_res_change; + struct v4l2_dv_timings timings; + struct clk *xvclk; + struct gpio_desc *reset_gpio; + struct gpio_desc *plugin_det_gpio; + struct gpio_desc *power_gpio; + struct work_struct work_i2c_poll; + struct timer_list timer; + const char *module_facing; + const char *module_name; + const char *len_name; + const struct lt6911uxe_mode *cur_mode; + const struct lt6911uxe_mode *support_modes; + u32 cfg_num; + struct v4l2_fwnode_endpoint bus_cfg; + bool nosignal; + bool enable_hdcp; + bool is_audio_present; + bool power_on; + int plugin_irq; + u32 mbus_fmt_code; + u32 module_index; + u32 audio_sampling_rate; + int lane_in_use; +}; + +static const struct v4l2_dv_timings_cap lt6911uxe_timings_cap = { + .type = V4L2_DV_BT_656_1120, + .reserved = { 0 }, + 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 | + V4L2_DV_BT_CAP_REDUCED_BLANKING | + V4L2_DV_BT_CAP_CUSTOM) +}; + +struct lt6911uxe_mode { + u32 width; + u32 height; + struct v4l2_fract max_fps; + u32 hts_def; + u32 vts_def; + u32 exp_def; + u32 mipi_freq_idx; +}; + +static struct rkmodule_csi_dphy_param rk3588_dcphy_param = { + .vendor = PHY_VENDOR_SAMSUNG, + .lp_vol_ref = 3, + .lp_hys_sw = {0, 0, 0, 0}, + .lp_escclk_pol_sel = {1, 0, 0, 0}, + .skew_data_cal_clk = {0, 0, 0, 0}, + .clk_hs_term_sel = 2, + .data_hs_term_sel = {2, 2, 2, 2}, + .reserved = {0}, +}; + +static const struct lt6911uxe_mode supported_modes_dphy[] = { + { + .width = 3840, + .height = 2160, + .max_fps = { + .numerator = 10000, + .denominator = 600000, + }, + .hts_def = 4400, + .vts_def = 2250, + .mipi_freq_idx = 0, + }, { + .width = 1920, + .height = 1080, + .max_fps = { + .numerator = 10000, + .denominator = 600000, + }, + .hts_def = 2200, + .vts_def = 1125, + .mipi_freq_idx = 1, + }, { + .width = 1280, + .height = 720, + .max_fps = { + .numerator = 10000, + .denominator = 600000, + }, + .hts_def = 1650, + .vts_def = 750, + .mipi_freq_idx = 1, + }, { + .width = 720, + .height = 576, + .max_fps = { + .numerator = 10000, + .denominator = 500000, + }, + .hts_def = 864, + .vts_def = 625, + .mipi_freq_idx = 2, + }, { + .width = 720, + .height = 480, + .max_fps = { + .numerator = 10000, + .denominator = 600000, + }, + .hts_def = 858, + .vts_def = 525, + .mipi_freq_idx = 2, + }, +}; + +static void lt6911uxe_format_change(struct v4l2_subdev *sd); +static int lt6911uxe_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd); +static int lt6911uxe_s_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings); + +static inline struct lt6911uxe *to_lt6911uxe(struct v4l2_subdev *sd) +{ + return container_of(sd, struct lt6911uxe, sd); +} + +static void i2c_rd(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + struct i2c_client *client = lt6911uxe->i2c_client; + int err; + u8 buf[2] = { 0xFF, reg >> 8}; + u8 reg_addr = reg & 0xFF; + struct i2c_msg msgs[3]; + + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = 2; + msgs[0].buf = buf; + + msgs[1].addr = client->addr; + msgs[1].flags = 0; + msgs[1].len = 1; + msgs[1].buf = ®_addr; + + msgs[2].addr = client->addr; + msgs[2].flags = I2C_M_RD; + msgs[2].len = n; + msgs[2].buf = values; + + err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (err != ARRAY_SIZE(msgs)) { + v4l2_err(sd, "%s: reading register 0x%x from 0x%x failed\n", + __func__, reg, client->addr); + } + + if (!debug) + return; + + switch (n) { + case 1: + v4l2_info(sd, "I2C read 0x%04x = 0x%02x\n", + reg, values[0]); + break; + case 2: + v4l2_info(sd, "I2C read 0x%04x = 0x%02x%02x\n", + reg, values[1], values[0]); + break; + case 4: + v4l2_info(sd, "I2C read 0x%04x = 0x%02x%02x%02x%02x\n", + reg, values[3], values[2], values[1], values[0]); + break; + default: + v4l2_info(sd, "I2C read %d bytes from address 0x%04x\n", + n, reg); + } +} + +static void i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + struct i2c_client *client = lt6911uxe->i2c_client; + int err, i; + struct i2c_msg msgs[2]; + u8 data[I2C_MAX_XFER_SIZE]; + u8 buf[2] = { 0xFF, reg >> 8}; + + if ((1 + n) > I2C_MAX_XFER_SIZE) { + n = I2C_MAX_XFER_SIZE - 1; + v4l2_warn(sd, "i2c wr reg=%04x: len=%d is too big!\n", + reg, 1 + n); + } + + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = 2; + msgs[0].buf = buf; + + msgs[1].addr = client->addr; + msgs[1].flags = 0; + msgs[1].len = 1 + n; + msgs[1].buf = data; + + data[0] = reg & 0xff; + for (i = 0; i < n; i++) + data[1 + i] = values[i]; + + err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (err < 0) { + v4l2_err(sd, "%s: writing register 0x%x from 0x%x failed\n", + __func__, reg, client->addr); + return; + } + + if (!debug) + return; + + switch (n) { + case 1: + v4l2_info(sd, "I2C write 0x%04x = 0x%02x\n", + reg, data[1]); + break; + case 2: + v4l2_info(sd, "I2C write 0x%04x = 0x%02x%02x\n", + reg, data[2], data[1]); + break; + case 4: + v4l2_info(sd, "I2C write 0x%04x = 0x%02x%02x%02x%02x\n", + reg, data[4], data[3], data[2], data[1]); + break; + default: + v4l2_info(sd, "I2C write %d bytes from address 0x%04x\n", + n, reg); + } +} + +static u8 i2c_rd8(struct v4l2_subdev *sd, u16 reg) +{ + u32 val; + + i2c_rd(sd, reg, (u8 __force *)&val, 1); + return val; +} + +static void i2c_wr8(struct v4l2_subdev *sd, u16 reg, u8 val) +{ + i2c_wr(sd, reg, &val, 1); +} + +static void lt6911uxe_i2c_enable(struct v4l2_subdev *sd) +{ + i2c_wr8(sd, I2C_EN_REG, I2C_ENABLE); +} + +static void lt6911uxe_i2c_disable(struct v4l2_subdev *sd) +{ + i2c_wr8(sd, I2C_EN_REG, I2C_DISABLE); +} + +static inline bool tx_5v_power_present(struct v4l2_subdev *sd) +{ + bool ret; + int val, i, cnt; + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + /* if not use plugin det gpio */ + if (!lt6911uxe->plugin_det_gpio) + return true; + + cnt = 0; + for (i = 0; i < 5; i++) { + val = gpiod_get_value(lt6911uxe->plugin_det_gpio); + if (val > 0) + cnt++; + usleep_range(500, 600); + } + + ret = (cnt >= 4) ? true : false; + v4l2_dbg(1, debug, sd, "%s: %d\n", __func__, ret); + + return ret; +} + +static inline bool no_signal(struct v4l2_subdev *sd) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + v4l2_dbg(1, debug, sd, "%s no signal:%d\n", __func__, + lt6911uxe->nosignal); + + return lt6911uxe->nosignal; +} + +static inline bool audio_present(struct v4l2_subdev *sd) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + return lt6911uxe->is_audio_present; +} + +static int get_audio_sampling_rate(struct v4l2_subdev *sd) +{ + static const int code_to_rate[] = { + 44100, 0, 48000, 32000, 22050, 384000, 24000, 352800, + 88200, 768000, 96000, 705600, 176400, 0, 192000, 0 + }; + + if (no_signal(sd)) + return 0; + + return code_to_rate[2]; +} + +static inline unsigned int fps_calc(const struct v4l2_bt_timings *t) +{ + if (!V4L2_DV_BT_FRAME_HEIGHT(t) || !V4L2_DV_BT_FRAME_WIDTH(t)) + return 0; + + return DIV_ROUND_CLOSEST((unsigned int)t->pixelclock, + V4L2_DV_BT_FRAME_HEIGHT(t) * V4L2_DV_BT_FRAME_WIDTH(t)); +} + +static bool lt6911uxe_rcv_supported_res(struct v4l2_subdev *sd, u32 width, + u32 height) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + u32 i; + + for (i = 0; i < lt6911uxe->cfg_num; i++) { + if ((lt6911uxe->support_modes[i].width == width) && + (lt6911uxe->support_modes[i].height == height)) { + break; + } + } + + if (i == lt6911uxe->cfg_num) { + v4l2_err(sd, "%s do not support res wxh: %dx%d\n", __func__, + width, height); + return false; + } else { + return true; + } +} + +static int lt6911uxe_get_detected_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + struct v4l2_bt_timings *bt = &timings->bt; + u32 hact, vact, htotal, vtotal; + u32 pixel_clock, fps, halt_pix_clk; + u8 clk_h, clk_m, clk_l; + u8 val_h, val_l; + u32 byte_clk, mipi_clk, mipi_data_rate; + + memset(timings, 0, sizeof(struct v4l2_dv_timings)); + + clk_h = i2c_rd8(sd, PCLK_H); + clk_m = i2c_rd8(sd, PCLK_M); + clk_l = i2c_rd8(sd, PCLK_L); + halt_pix_clk = ((clk_h << 16) | (clk_m << 8) | clk_l); + pixel_clock = halt_pix_clk * 1000 * 2; + + clk_h = i2c_rd8(sd, BYTE_PCLK_H); + clk_m = i2c_rd8(sd, BYTE_PCLK_M); + clk_l = i2c_rd8(sd, BYTE_PCLK_L); + byte_clk = ((clk_h << 16) | (clk_m << 8) | clk_l) * 1000; + mipi_clk = byte_clk * 4; + mipi_data_rate = byte_clk * 8; + + val_h = i2c_rd8(sd, HTOTAL_H); + val_l = i2c_rd8(sd, HTOTAL_L); + htotal = ((val_h << 8) | val_l) * 2; + + val_h = i2c_rd8(sd, VTOTAL_H); + val_l = i2c_rd8(sd, VTOTAL_L); + vtotal = (val_h << 8) | val_l; + + val_h = i2c_rd8(sd, HACT_H); + val_l = i2c_rd8(sd, HACT_L); + hact = ((val_h << 8) | val_l) * 2; + + val_h = i2c_rd8(sd, VACT_H); + val_l = i2c_rd8(sd, VACT_L); + vact = (val_h << 8) | val_l; + + if (!lt6911uxe_rcv_supported_res(sd, hact, vact)) { + lt6911uxe->nosignal = true; + v4l2_err(sd, "%s: rcv err res, return no signal!\n", __func__); + return -EINVAL; + } + + lt6911uxe->nosignal = false; + lt6911uxe->is_audio_present = true; + timings->type = V4L2_DV_BT_656_1120; + bt->interlaced = V4L2_DV_PROGRESSIVE; + bt->width = hact; + bt->height = vact; + bt->pixelclock = pixel_clock; + fps = pixel_clock / (htotal * vtotal); + + v4l2_info(sd, "act:%dx%d, total:%dx%d, pixclk:%d, fps:%d\n", + hact, vact, htotal, vtotal, pixel_clock, fps); + v4l2_info(sd, "byte_clk:%d, mipi_clk:%d, mipi_data_rate:%d\n", + byte_clk, mipi_clk, mipi_data_rate); + v4l2_info(sd, "inerlaced:%d\n", bt->interlaced); + + return 0; +} + +static void lt6911uxe_delayed_work_hotplug(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct lt6911uxe *lt6911uxe = container_of(dwork, + struct lt6911uxe, delayed_work_hotplug); + struct v4l2_subdev *sd = <6911uxe->sd; + + lt6911uxe_s_ctrl_detect_tx_5v(sd); +} + +static void lt6911uxe_delayed_work_res_change(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct lt6911uxe *lt6911uxe = container_of(dwork, + struct lt6911uxe, delayed_work_res_change); + struct v4l2_subdev *sd = <6911uxe->sd; + + lt6911uxe_format_change(sd); +} + +static int lt6911uxe_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + return v4l2_ctrl_s_ctrl(lt6911uxe->detect_tx_5v_ctrl, + tx_5v_power_present(sd)); +} + +static int lt6911uxe_s_ctrl_audio_sampling_rate(struct v4l2_subdev *sd) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + return v4l2_ctrl_s_ctrl(lt6911uxe->audio_sampling_rate_ctrl, + get_audio_sampling_rate(sd)); +} + +static int lt6911uxe_s_ctrl_audio_present(struct v4l2_subdev *sd) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + return v4l2_ctrl_s_ctrl(lt6911uxe->audio_present_ctrl, + audio_present(sd)); +} + +static int lt6911uxe_update_controls(struct v4l2_subdev *sd) +{ + int ret = 0; + + ret |= lt6911uxe_s_ctrl_detect_tx_5v(sd); + ret |= lt6911uxe_s_ctrl_audio_sampling_rate(sd); + ret |= lt6911uxe_s_ctrl_audio_present(sd); + + return ret; +} + +static bool lt6911uxe_match_timings(const struct v4l2_dv_timings *t1, + const struct v4l2_dv_timings *t2) +{ + if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120) + return false; + if (t1->bt.width == t2->bt.width && + t1->bt.height == t2->bt.height && + t1->bt.interlaced == t2->bt.interlaced) + return true; + + return false; +} + +static inline void enable_stream(struct v4l2_subdev *sd, bool enable) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + if (enable) + i2c_wr8(<6911uxe->sd, STREAM_CTL, ENABLE_STREAM); + else + i2c_wr8(<6911uxe->sd, STREAM_CTL, DISABLE_STREAM); + msleep(50); + + v4l2_dbg(2, debug, sd, "%s: %sable\n", + __func__, enable ? "en" : "dis"); +} + +static void lt6911uxe_format_change(struct v4l2_subdev *sd) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + struct v4l2_dv_timings timings; + const struct v4l2_event lt6911uxe_ev_fmt = { + .type = V4L2_EVENT_SOURCE_CHANGE, + .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, + }; + + if (lt6911uxe_get_detected_timings(sd, &timings)) { + enable_stream(sd, false); + v4l2_dbg(1, debug, sd, "%s: No signal\n", __func__); + } + + if (!lt6911uxe_match_timings(<6911uxe->timings, &timings)) { + enable_stream(sd, false); + /* automatically set timing rather than set by user */ + lt6911uxe_s_dv_timings(sd, &timings); + v4l2_print_dv_timings(sd->name, + "Format_change: New format: ", + &timings, false); + if (sd->devnode) + v4l2_subdev_notify_event(sd, <6911uxe_ev_fmt); + } +} + +static int lt6911uxe_isr(struct v4l2_subdev *sd, u32 status, bool *handled) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + schedule_delayed_work(<6911uxe->delayed_work_res_change, HZ / 20); + *handled = true; + + return 0; +} + +static irqreturn_t lt6911uxe_res_change_irq_handler(int irq, void *dev_id) +{ + struct lt6911uxe *lt6911uxe = dev_id; + bool handled; + + lt6911uxe_isr(<6911uxe->sd, 0, &handled); + + return handled ? IRQ_HANDLED : IRQ_NONE; +} + +static irqreturn_t plugin_detect_irq_handler(int irq, void *dev_id) +{ + struct lt6911uxe *lt6911uxe = dev_id; + + /* control hpd output level after 25ms */ + schedule_delayed_work(<6911uxe->delayed_work_hotplug, + HZ / 40); + + return IRQ_HANDLED; +} + +static void lt6911uxe_irq_poll_timer(struct timer_list *t) +{ + struct lt6911uxe *lt6911uxe = from_timer(lt6911uxe, t, timer); + + schedule_work(<6911uxe->work_i2c_poll); + mod_timer(<6911uxe->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS)); +} + +static void lt6911uxe_work_i2c_poll(struct work_struct *work) +{ + struct lt6911uxe *lt6911uxe = container_of(work, + struct lt6911uxe, work_i2c_poll); + struct v4l2_subdev *sd = <6911uxe->sd; + + lt6911uxe_format_change(sd); +} + +static int lt6911uxe_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + switch (sub->type) { + case V4L2_EVENT_SOURCE_CHANGE: + return v4l2_src_change_event_subdev_subscribe(sd, fh, sub); + case V4L2_EVENT_CTRL: + return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub); + default: + return -EINVAL; + } +} + +static int lt6911uxe_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + *status = 0; + *status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0; + + v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status); + + return 0; +} + +static int lt6911uxe_s_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + if (!timings) + return -EINVAL; + + if (debug) + v4l2_print_dv_timings(sd->name, "s_dv_timings: ", + timings, false); + + if (lt6911uxe_match_timings(<6911uxe->timings, timings)) { + v4l2_dbg(1, debug, sd, "%s: no change\n", __func__); + return 0; + } + + if (!v4l2_valid_dv_timings(timings, + <6911uxe_timings_cap, NULL, NULL)) { + v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__); + return -ERANGE; + } + + lt6911uxe->timings = *timings; + + enable_stream(sd, false); + + return 0; +} + +static int lt6911uxe_g_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + *timings = lt6911uxe->timings; + + return 0; +} + +static int lt6911uxe_enum_dv_timings(struct v4l2_subdev *sd, + struct v4l2_enum_dv_timings *timings) +{ + if (timings->pad != 0) + return -EINVAL; + + return v4l2_enum_dv_timings_cap(timings, + <6911uxe_timings_cap, NULL, NULL); +} + +static int lt6911uxe_query_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + *timings = lt6911uxe->timings; + if (debug) + v4l2_print_dv_timings(sd->name, + "query_dv_timings: ", timings, false); + + if (!v4l2_valid_dv_timings(timings, <6911uxe_timings_cap, NULL, + NULL)) { + v4l2_dbg(1, debug, sd, "%s: timings out of range\n", + __func__); + + return -ERANGE; + } + + return 0; +} + +static int lt6911uxe_dv_timings_cap(struct v4l2_subdev *sd, + struct v4l2_dv_timings_cap *cap) +{ + if (cap->pad != 0) + return -EINVAL; + + *cap = lt6911uxe_timings_cap; + + return 0; +} + +static int lt6911uxe_g_mbus_config(struct v4l2_subdev *sd, + unsigned int pad, struct v4l2_mbus_config *cfg) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + u32 lane_num = lt6911uxe->bus_cfg.bus.mipi_csi2.num_data_lanes; + u32 val = 0; + + val = 1 << (lane_num - 1) | + V4L2_MBUS_CSI2_CHANNEL_0 | + V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; + + cfg->type = lt6911uxe->bus_cfg.bus_type; + cfg->flags = val; + + return 0; +} + +static int lt6911uxe_s_stream(struct v4l2_subdev *sd, int on) +{ + enable_stream(sd, on); + + return 0; +} + +static int lt6911uxe_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + switch (code->index) { + case 0: + code->code = LT6911UXE_MEDIA_BUS_FMT; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int lt6911uxe_enum_frame_sizes(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + if (fse->index >= lt6911uxe->cfg_num) + return -EINVAL; + + if (fse->code != LT6911UXE_MEDIA_BUS_FMT) + return -EINVAL; + + fse->min_width = lt6911uxe->support_modes[fse->index].width; + fse->max_width = lt6911uxe->support_modes[fse->index].width; + fse->max_height = lt6911uxe->support_modes[fse->index].height; + fse->min_height = lt6911uxe->support_modes[fse->index].height; + + return 0; +} + +static int lt6911uxe_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + if (fie->index >= lt6911uxe->cfg_num) + return -EINVAL; + + if (fie->code != LT6911UXE_MEDIA_BUS_FMT) + return -EINVAL; + + fie->width = lt6911uxe->support_modes[fie->index].width; + fie->height = lt6911uxe->support_modes[fie->index].height; + fie->interval = lt6911uxe->support_modes[fie->index].max_fps; + + return 0; +} + +static int lt6911uxe_get_reso_dist(const struct lt6911uxe_mode *mode, + struct v4l2_mbus_framefmt *framefmt) +{ + return abs(mode->width - framefmt->width) + + abs(mode->height - framefmt->height); +} + +static const struct lt6911uxe_mode * +lt6911uxe_find_best_fit(struct lt6911uxe *lt6911uxe, struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *framefmt = &fmt->format; + int dist; + int cur_best_fit = 0; + int cur_best_fit_dist = -1; + unsigned int i; + + for (i = 0; i < lt6911uxe->cfg_num; i++) { + dist = lt6911uxe_get_reso_dist(<6911uxe->support_modes[i], framefmt); + if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) { + cur_best_fit_dist = dist; + cur_best_fit = i; + } + } + + return <6911uxe->support_modes[cur_best_fit]; +} + +static int lt6911uxe_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + const struct lt6911uxe_mode *mode; + + mutex_lock(<6911uxe->confctl_mutex); + format->format.code = lt6911uxe->mbus_fmt_code; + format->format.width = lt6911uxe->timings.bt.width; + format->format.height = lt6911uxe->timings.bt.height; + format->format.field = + lt6911uxe->timings.bt.interlaced ? + V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE; + format->format.colorspace = V4L2_COLORSPACE_SRGB; + + mode = lt6911uxe_find_best_fit(lt6911uxe, format); + __v4l2_ctrl_s_ctrl_int64(lt6911uxe->pixel_rate, + LT6911UXE_PIXEL_RATE); + __v4l2_ctrl_s_ctrl(lt6911uxe->link_freq, + mode->mipi_freq_idx); + mutex_unlock(<6911uxe->confctl_mutex); + + v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field code:%d\n", + __func__, format->format.code, format->format.width, + format->format.height, format->format.field); + + return 0; +} + +static int lt6911uxe_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + const struct lt6911uxe_mode *mode; + + /* is overwritten by get_fmt */ + u32 code = format->format.code; + int ret = lt6911uxe_get_fmt(sd, cfg, format); + + format->format.code = code; + + if (ret) + return ret; + + switch (code) { + case LT6911UXE_MEDIA_BUS_FMT: + break; + + default: + return -EINVAL; + } + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) + return 0; + + lt6911uxe->mbus_fmt_code = format->format.code; + mode = lt6911uxe_find_best_fit(lt6911uxe, format); + lt6911uxe->cur_mode = mode; + + enable_stream(sd, false); + + dev_info(<6911uxe->i2c_client->dev, "%s: mode->mipi_freq_idx(%d)", + __func__, mode->mipi_freq_idx); + + return 0; +} + +static int lt6911uxe_g_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + const struct lt6911uxe_mode *mode = lt6911uxe->cur_mode; + + mutex_lock(<6911uxe->confctl_mutex); + fi->interval = mode->max_fps; + mutex_unlock(<6911uxe->confctl_mutex); + + return 0; +} + +static void lt6911uxe_get_module_inf(struct lt6911uxe *lt6911uxe, + struct rkmodule_inf *inf) +{ + memset(inf, 0, sizeof(*inf)); + strscpy(inf->base.sensor, LT6911UXE_NAME, sizeof(inf->base.sensor)); + strscpy(inf->base.module, lt6911uxe->module_name, sizeof(inf->base.module)); + strscpy(inf->base.lens, lt6911uxe->len_name, sizeof(inf->base.lens)); +} + +static long lt6911uxe_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + long ret = 0; + struct rkmodule_csi_dphy_param *dphy_param; + + switch (cmd) { + case RKMODULE_GET_MODULE_INFO: + lt6911uxe_get_module_inf(lt6911uxe, (struct rkmodule_inf *)arg); + break; + case RKMODULE_GET_HDMI_MODE: + *(int *)arg = RKMODULE_HDMIIN_MODE; + break; + case RKMODULE_SET_CSI_DPHY_PARAM: + dphy_param = (struct rkmodule_csi_dphy_param *)arg; + if (dphy_param->vendor == rk3588_dcphy_param.vendor) + rk3588_dcphy_param = *dphy_param; + dev_dbg(<6911uxe->i2c_client->dev, + "sensor set dphy param\n"); + break; + case RKMODULE_GET_CSI_DPHY_PARAM: + dphy_param = (struct rkmodule_csi_dphy_param *)arg; + if (dphy_param->vendor == rk3588_dcphy_param.vendor) + *dphy_param = rk3588_dcphy_param; + dev_dbg(<6911uxe->i2c_client->dev, + "sensor get dphy param\n"); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + + return ret; +} + +static int lt6911uxe_s_power(struct v4l2_subdev *sd, int on) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + int ret = 0; + + mutex_lock(<6911uxe->confctl_mutex); + + if (lt6911uxe->power_on == !!on) + goto unlock_and_return; + + if (on) + lt6911uxe->power_on = true; + else + lt6911uxe->power_on = false; + +unlock_and_return: + mutex_unlock(<6911uxe->confctl_mutex); + + return ret; +} + +#ifdef CONFIG_COMPAT +static long lt6911uxe_compat_ioctl32(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + void __user *up = compat_ptr(arg); + struct rkmodule_inf *inf; + long ret; + int *seq; + struct rkmodule_csi_dphy_param *dphy_param; + + switch (cmd) { + case RKMODULE_GET_MODULE_INFO: + inf = kzalloc(sizeof(*inf), GFP_KERNEL); + if (!inf) { + ret = -ENOMEM; + return ret; + } + + ret = lt6911uxe_ioctl(sd, cmd, inf); + if (!ret) { + ret = copy_to_user(up, inf, sizeof(*inf)); + if (ret) + ret = -EFAULT; + } + kfree(inf); + break; + case RKMODULE_GET_HDMI_MODE: + seq = kzalloc(sizeof(*seq), GFP_KERNEL); + if (!seq) { + ret = -ENOMEM; + return ret; + } + + ret = lt6911uxe_ioctl(sd, cmd, seq); + if (!ret) { + ret = copy_to_user(up, seq, sizeof(*seq)); + if (ret) + ret = -EFAULT; + } + kfree(seq); + break; + case RKMODULE_SET_CSI_DPHY_PARAM: + dphy_param = kzalloc(sizeof(*dphy_param), GFP_KERNEL); + if (!dphy_param) { + ret = -ENOMEM; + return ret; + } + + ret = copy_from_user(dphy_param, up, sizeof(*dphy_param)); + if (!ret) + ret = lt6911uxe_ioctl(sd, cmd, dphy_param); + else + ret = -EFAULT; + kfree(dphy_param); + break; + case RKMODULE_GET_CSI_DPHY_PARAM: + dphy_param = kzalloc(sizeof(*dphy_param), GFP_KERNEL); + if (!dphy_param) { + ret = -ENOMEM; + return ret; + } + + ret = lt6911uxe_ioctl(sd, cmd, dphy_param); + if (!ret) { + ret = copy_to_user(up, dphy_param, sizeof(*dphy_param)); + if (ret) + ret = -EFAULT; + } + kfree(dphy_param); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + + return ret; +} +#endif + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static int lt6911uxe_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->pad, 0); + const struct lt6911uxe_mode *def_mode = <6911uxe->support_modes[0]; + + mutex_lock(<6911uxe->confctl_mutex); + /* Initialize try_fmt */ + try_fmt->width = def_mode->width; + try_fmt->height = def_mode->height; + try_fmt->code = LT6911UXE_MEDIA_BUS_FMT; + try_fmt->field = V4L2_FIELD_NONE; + mutex_unlock(<6911uxe->confctl_mutex); + + return 0; +} +#endif + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static const struct v4l2_subdev_internal_ops lt6911uxe_internal_ops = { + .open = lt6911uxe_open, +}; +#endif + +static const struct v4l2_subdev_core_ops lt6911uxe_core_ops = { + .s_power = lt6911uxe_s_power, + .interrupt_service_routine = lt6911uxe_isr, + .subscribe_event = lt6911uxe_subscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, + .ioctl = lt6911uxe_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = lt6911uxe_compat_ioctl32, +#endif +}; + +static const struct v4l2_subdev_video_ops lt6911uxe_video_ops = { + .g_input_status = lt6911uxe_g_input_status, + .s_dv_timings = lt6911uxe_s_dv_timings, + .g_dv_timings = lt6911uxe_g_dv_timings, + .query_dv_timings = lt6911uxe_query_dv_timings, + .s_stream = lt6911uxe_s_stream, + .g_frame_interval = lt6911uxe_g_frame_interval, +}; + +static const struct v4l2_subdev_pad_ops lt6911uxe_pad_ops = { + .enum_mbus_code = lt6911uxe_enum_mbus_code, + .enum_frame_size = lt6911uxe_enum_frame_sizes, + .enum_frame_interval = lt6911uxe_enum_frame_interval, + .set_fmt = lt6911uxe_set_fmt, + .get_fmt = lt6911uxe_get_fmt, + .enum_dv_timings = lt6911uxe_enum_dv_timings, + .dv_timings_cap = lt6911uxe_dv_timings_cap, + .get_mbus_config = lt6911uxe_g_mbus_config, +}; + +static const struct v4l2_subdev_ops lt6911uxe_ops = { + .core = <6911uxe_core_ops, + .video = <6911uxe_video_ops, + .pad = <6911uxe_pad_ops, +}; + +static const struct v4l2_ctrl_config lt6911uxe_ctrl_audio_sampling_rate = { + .id = RK_V4L2_CID_AUDIO_SAMPLING_RATE, + .name = "Audio sampling rate", + .type = V4L2_CTRL_TYPE_INTEGER, + .min = 0, + .max = 768000, + .step = 1, + .def = 0, + .flags = V4L2_CTRL_FLAG_READ_ONLY, +}; + +static const struct v4l2_ctrl_config lt6911uxe_ctrl_audio_present = { + .id = RK_V4L2_CID_AUDIO_PRESENT, + .name = "Audio present", + .type = V4L2_CTRL_TYPE_BOOLEAN, + .min = 0, + .max = 1, + .step = 1, + .def = 0, + .flags = V4L2_CTRL_FLAG_READ_ONLY, +}; + +static void lt6911uxe_reset(struct lt6911uxe *lt6911uxe) +{ + gpiod_set_value(lt6911uxe->reset_gpio, 0); + usleep_range(2000, 2100); + gpiod_set_value(lt6911uxe->reset_gpio, 1); + usleep_range(120*1000, 121*1000); + gpiod_set_value(lt6911uxe->reset_gpio, 0); + usleep_range(300*1000, 310*1000); +} + +static int lt6911uxe_init_v4l2_ctrls(struct lt6911uxe *lt6911uxe) +{ + const struct lt6911uxe_mode *mode; + struct v4l2_subdev *sd; + int ret; + + mode = lt6911uxe->cur_mode; + sd = <6911uxe->sd; + ret = v4l2_ctrl_handler_init(<6911uxe->hdl, 5); + if (ret) + return ret; + + lt6911uxe->link_freq = v4l2_ctrl_new_int_menu(<6911uxe->hdl, NULL, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(link_freq_menu_items) - 1, 0, + link_freq_menu_items); + lt6911uxe->pixel_rate = v4l2_ctrl_new_std(<6911uxe->hdl, NULL, + V4L2_CID_PIXEL_RATE, + 0, LT6911UXE_PIXEL_RATE, 1, LT6911UXE_PIXEL_RATE); + + lt6911uxe->detect_tx_5v_ctrl = v4l2_ctrl_new_std(<6911uxe->hdl, + NULL, V4L2_CID_DV_RX_POWER_PRESENT, + 0, 1, 0, 0); + + lt6911uxe->audio_sampling_rate_ctrl = + v4l2_ctrl_new_custom(<6911uxe->hdl, + <6911uxe_ctrl_audio_sampling_rate, NULL); + lt6911uxe->audio_present_ctrl = v4l2_ctrl_new_custom(<6911uxe->hdl, + <6911uxe_ctrl_audio_present, NULL); + + sd->ctrl_handler = <6911uxe->hdl; + if (lt6911uxe->hdl.error) { + ret = lt6911uxe->hdl.error; + v4l2_err(sd, "cfg v4l2 ctrls failed! ret:%d\n", ret); + return ret; + } + + __v4l2_ctrl_s_ctrl(lt6911uxe->link_freq, mode->mipi_freq_idx); + __v4l2_ctrl_s_ctrl_int64(lt6911uxe->pixel_rate, LT6911UXE_PIXEL_RATE); + + if (lt6911uxe_update_controls(sd)) { + ret = -ENODEV; + v4l2_err(sd, "update v4l2 ctrls failed! ret:%d\n", ret); + return ret; + } + + return 0; +} + +#ifdef CONFIG_OF +static int lt6911uxe_probe_of(struct lt6911uxe *lt6911uxe) +{ + struct device *dev = <6911uxe->i2c_client->dev; + struct device_node *node = dev->of_node; + struct device_node *ep; + int ret; + + ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, + <6911uxe->module_index); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, + <6911uxe->module_facing); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME, + <6911uxe->module_name); + ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME, + <6911uxe->len_name); + if (ret) { + dev_err(dev, "could not get module information!\n"); + return -EINVAL; + } + + lt6911uxe->power_gpio = devm_gpiod_get_optional(dev, "power", + GPIOD_OUT_LOW); + if (IS_ERR(lt6911uxe->power_gpio)) { + dev_err(dev, "failed to get power gpio\n"); + ret = PTR_ERR(lt6911uxe->power_gpio); + return ret; + } + + lt6911uxe->reset_gpio = devm_gpiod_get_optional(dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(lt6911uxe->reset_gpio)) { + dev_err(dev, "failed to get reset gpio\n"); + ret = PTR_ERR(lt6911uxe->reset_gpio); + return ret; + } + + lt6911uxe->plugin_det_gpio = devm_gpiod_get_optional(dev, "plugin-det", + GPIOD_IN); + if (IS_ERR(lt6911uxe->plugin_det_gpio)) { + dev_err(dev, "failed to get plugin det gpio\n"); + ret = PTR_ERR(lt6911uxe->plugin_det_gpio); + return ret; + } + + ep = of_graph_get_next_endpoint(dev->of_node, NULL); + if (!ep) { + dev_err(dev, "missing endpoint node\n"); + return -EINVAL; + } + + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), + <6911uxe->bus_cfg); + if (ret) { + dev_err(dev, "failed to parse endpoint\n"); + goto put_node; + } + + lt6911uxe->support_modes = supported_modes_dphy; + lt6911uxe->cfg_num = ARRAY_SIZE(supported_modes_dphy); + + lt6911uxe->xvclk = devm_clk_get(dev, "xvclk"); + if (IS_ERR(lt6911uxe->xvclk)) { + dev_err(dev, "failed to get xvclk\n"); + ret = -EINVAL; + goto put_node; + } + + ret = clk_prepare_enable(lt6911uxe->xvclk); + if (ret) { + dev_err(dev, "Failed! to enable xvclk\n"); + goto put_node; + } + + lt6911uxe->enable_hdcp = false; + + gpiod_set_value(lt6911uxe->power_gpio, 1); + lt6911uxe_reset(lt6911uxe); + + ret = 0; + +put_node: + of_node_put(ep); + return ret; +} +#else +static inline int lt6911uxe_probe_of(struct lt6911uxe *state) +{ + return -ENODEV; +} +#endif +static int lt6911uxe_check_chip_id(struct lt6911uxe *lt6911uxe) +{ + struct device *dev = <6911uxe->i2c_client->dev; + struct v4l2_subdev *sd = <6911uxe->sd; + u8 id_h, id_l; + u32 chipid; + int ret = 0; + + lt6911uxe_i2c_enable(sd); + id_l = i2c_rd8(sd, CHIPID_REGL); + id_h = i2c_rd8(sd, CHIPID_REGH); + lt6911uxe_i2c_disable(sd); + + chipid = (id_h << 8) | id_l; + if (chipid != LT6911UXE_CHIPID) { + dev_err(dev, "chipid err, read:%#x, expect:%#x\n", + chipid, LT6911UXE_CHIPID); + return -EINVAL; + } + dev_info(dev, "check chipid ok, id:%#x", chipid); + + return ret; +} + +static int lt6911uxe_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct lt6911uxe *lt6911uxe; + struct v4l2_subdev *sd; + struct device *dev = &client->dev; + char facing[2]; + int err; + + dev_info(dev, "driver version: %02x.%02x.%02x", + DRIVER_VERSION >> 16, + (DRIVER_VERSION & 0xff00) >> 8, + DRIVER_VERSION & 0x00ff); + + lt6911uxe = devm_kzalloc(dev, sizeof(struct lt6911uxe), GFP_KERNEL); + if (!lt6911uxe) + return -ENOMEM; + + sd = <6911uxe->sd; + lt6911uxe->i2c_client = client; + lt6911uxe->mbus_fmt_code = LT6911UXE_MEDIA_BUS_FMT; + + err = lt6911uxe_probe_of(lt6911uxe); + if (err) { + v4l2_err(sd, "lt6911uxe_parse_of failed! err:%d\n", err); + return err; + } + + lt6911uxe->cur_mode = <6911uxe->support_modes[0]; + err = lt6911uxe_check_chip_id(lt6911uxe); + if (err < 0) + return err; + + mutex_init(<6911uxe->confctl_mutex); + err = lt6911uxe_init_v4l2_ctrls(lt6911uxe); + if (err) + goto err_free_hdl; + + client->flags |= I2C_CLIENT_SCCB; +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + v4l2_i2c_subdev_init(sd, client, <6911uxe_ops); + sd->internal_ops = <6911uxe_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; +#endif + +#if defined(CONFIG_MEDIA_CONTROLLER) + lt6911uxe->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + err = media_entity_pads_init(&sd->entity, 1, <6911uxe->pad); + if (err < 0) { + v4l2_err(sd, "media entity init failed! err:%d\n", err); + goto err_free_hdl; + } +#endif + memset(facing, 0, sizeof(facing)); + if (strcmp(lt6911uxe->module_facing, "back") == 0) + facing[0] = 'b'; + else + facing[0] = 'f'; + + snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", + lt6911uxe->module_index, facing, + LT6911UXE_NAME, dev_name(sd->dev)); + err = v4l2_async_register_subdev_sensor_common(sd); + if (err < 0) { + v4l2_err(sd, "v4l2 register subdev failed! err:%d\n", err); + goto err_clean_entity; + } + + INIT_DELAYED_WORK(<6911uxe->delayed_work_hotplug, + lt6911uxe_delayed_work_hotplug); + INIT_DELAYED_WORK(<6911uxe->delayed_work_res_change, + lt6911uxe_delayed_work_res_change); + + if (lt6911uxe->i2c_client->irq) { + v4l2_dbg(1, debug, sd, "cfg lt6911uxe irq!\n"); + err = devm_request_threaded_irq(dev, + lt6911uxe->i2c_client->irq, + NULL, lt6911uxe_res_change_irq_handler, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "lt6911uxe", lt6911uxe); + if (err) { + v4l2_err(sd, "request irq failed! err:%d\n", err); + goto err_work_queues; + } + } else { + v4l2_dbg(1, debug, sd, "no irq, cfg poll!\n"); + INIT_WORK(<6911uxe->work_i2c_poll, lt6911uxe_work_i2c_poll); + timer_setup(<6911uxe->timer, lt6911uxe_irq_poll_timer, 0); + lt6911uxe->timer.expires = jiffies + + msecs_to_jiffies(POLL_INTERVAL_MS); + add_timer(<6911uxe->timer); + } + + lt6911uxe->plugin_irq = gpiod_to_irq(lt6911uxe->plugin_det_gpio); + if (lt6911uxe->plugin_irq < 0) + dev_err(dev, "failed to get plugin det irq, maybe no use\n"); + + err = devm_request_threaded_irq(dev, lt6911uxe->plugin_irq, NULL, + plugin_detect_irq_handler, IRQF_TRIGGER_FALLING | + IRQF_TRIGGER_RISING | IRQF_ONESHOT, "lt6911uxe", + lt6911uxe); + if (err) + dev_err(dev, "failed to register plugin det irq (%d), maybe no use\n", err); + + err = v4l2_ctrl_handler_setup(sd->ctrl_handler); + if (err) { + v4l2_err(sd, "v4l2 ctrl handler setup failed! err:%d\n", err); + goto err_work_queues; + } + + v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, + client->addr << 1, client->adapter->name); + + return 0; + +err_work_queues: + if (!lt6911uxe->i2c_client->irq) + flush_work(<6911uxe->work_i2c_poll); + cancel_delayed_work(<6911uxe->delayed_work_hotplug); + cancel_delayed_work(<6911uxe->delayed_work_res_change); +err_clean_entity: +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif +err_free_hdl: + v4l2_ctrl_handler_free(<6911uxe->hdl); + mutex_destroy(<6911uxe->confctl_mutex); + return err; +} + +static int lt6911uxe_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); + + if (!lt6911uxe->i2c_client->irq) { + del_timer_sync(<6911uxe->timer); + flush_work(<6911uxe->work_i2c_poll); + } + cancel_delayed_work_sync(<6911uxe->delayed_work_hotplug); + cancel_delayed_work_sync(<6911uxe->delayed_work_res_change); + v4l2_async_unregister_subdev(sd); + v4l2_device_unregister_subdev(sd); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif + v4l2_ctrl_handler_free(<6911uxe->hdl); + mutex_destroy(<6911uxe->confctl_mutex); + clk_disable_unprepare(lt6911uxe->xvclk); + + return 0; +} + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id lt6911uxe_of_match[] = { + { .compatible = "lontium,lt6911uxe" }, + {}, +}; +MODULE_DEVICE_TABLE(of, lt6911uxe_of_match); +#endif + +static struct i2c_driver lt6911uxe_driver = { + .driver = { + .name = LT6911UXE_NAME, + .of_match_table = of_match_ptr(lt6911uxe_of_match), + }, + .probe = lt6911uxe_probe, + .remove = lt6911uxe_remove, +}; + +static int __init lt6911uxe_driver_init(void) +{ + return i2c_add_driver(<6911uxe_driver); +} + +static void __exit lt6911uxe_driver_exit(void) +{ + i2c_del_driver(<6911uxe_driver); +} + +device_initcall_sync(lt6911uxe_driver_init); +module_exit(lt6911uxe_driver_exit); + +MODULE_DESCRIPTION("Lontium lt6911uxe HDMI to CSI-2 bridge driver"); +MODULE_AUTHOR("Jianwei Fan "); +MODULE_LICENSE("GPL"); From 64e13c9628e5937b6b1266ed2b227d786e6bd7f1 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Tue, 30 Aug 2022 06:16:12 +0000 Subject: [PATCH 147/235] arm64: dts: rockchip: rk3588-evb1-lt6911uxe: add lt6911uxe configuration for rk3588 evb1 extboard Signed-off-by: Jianwei Fan Change-Id: I6a1a0fd0bc25a5ce18089d4d7804d785745225b5 --- arch/arm64/boot/dts/rockchip/Makefile | 1 + .../rk3588-evb1-lp4-v10-lt6911uxe.dts | 277 ++++++++++++++++++ 2 files changed, 278 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-lt6911uxe.dts diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index fc4ecac37e81..6ab5692a0922 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -115,6 +115,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-lp4-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-lp4-v10-ipc-6x-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-lp4-v10-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-lp4-v10-linux-ipc.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-lp4-v10-lt6911uxe.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb2-lp4-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb2-lp4-v10-edp.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb2-lp4-v10-edp2dp.dtb diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-lt6911uxe.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-lt6911uxe.dts new file mode 100644 index 000000000000..d33e2bf449c2 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-lt6911uxe.dts @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + * + */ +/dts-v1/; + +#include "rk3588-evb1-lp4.dtsi" +#include "rk3588-android.dtsi" + +/ { + model = "Rockchip RK3588 EVB1 LP4 V10 Board + Rockchip RK3588 EVB V10 Extboard"; + compatible = "rockchip,rk3588-evb1-lp4-v10-lt6911uxe", "rockchip,rk3588"; + + vcc_mipicsi0: vcc-mipicsi0-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipicsi0_pwr>; + regulator-name = "vcc_mipicsi0"; + enable-active-high; + regulator-boot-on; + regulator-always-on; + }; + + vcc_mipidcphy0: vcc-mipidcphy0-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio2 RK_PC4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipidcphy0_pwr>; + regulator-name = "vcc_mipidcphy0"; + enable-active-high; + regulator-boot-on; + regulator-always-on; + }; + + ext_cam_clk: external-camera-clock { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "CLK_CAMERA_24MHZ"; + #clock-cells = <0>; + }; +}; + +&csi2_dphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + hdmi_mipi2_in: endpoint@1 { + reg = <1>; + remote-endpoint = <<6911uxe_out1>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi2_csi2_input>; + }; + }; + }; +}; + +&csi2_dphy0_hw { + status = "okay"; +}; + +&csi2_dcphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + hdmi_mipi0_in: endpoint@1 { + reg = <1>; + remote-endpoint = <<6911uxe_out0>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi0_csi2_input>; + }; + }; + }; +}; + +&i2c3 { + status = "okay"; + + lt6911uxe_1: lt6911uxe_1@2b { + compatible = "lontium,lt6911uxe"; + status = "okay"; + reg = <0x2b>; + clocks = <&ext_cam_clk>; + clock-names = "xvclk"; + power-domains = <&power RK3588_PD_VI>; + pinctrl-names = "default"; + pinctrl-0 = <<6911uxe_pin_1>; + interrupt-parent = <&gpio1>; + interrupts = ; + // reset-gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_LOW>; + // power-gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_HIGH>; + plugin-det-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_HIGH>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "HDMI-MIPI2"; + rockchip,camera-module-lens-name = "LT6911UXE-2"; + port { + lt6911uxe_out1: endpoint { + remote-endpoint = <&hdmi_mipi2_in>; + data-lanes = <1 2 3 4>; + }; + }; + }; +}; + +&i2c5 { + status = "okay"; + + lt6911uxe: lt6911uxe@2b { + compatible = "lontium,lt6911uxe"; + status = "okay"; + reg = <0x2b>; + clocks = <&ext_cam_clk>; + clock-names = "xvclk"; + power-domains = <&power RK3588_PD_VI>; + pinctrl-names = "default"; + pinctrl-0 = <<6911uxe_pin>; + interrupt-parent = <&gpio1>; + interrupts = ; + // reset-gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_LOW>; + // power-gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_HIGH>; + // plugin-det-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>; + plugin-det-gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>; + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "front"; + rockchip,camera-module-name = "HDMI-MIPI0"; + rockchip,camera-module-lens-name = "LT6911UXC-0"; + + port { + lt6911uxe_out0: endpoint { + remote-endpoint = <&hdmi_mipi0_in>; + data-lanes = <1 2 3 4>; + }; + }; + }; +}; + +&mipi_dcphy0 { + status = "okay"; +}; + +&mipi0_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in0>; + }; + }; + }; +}; + +&mipi2_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi2_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi2_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in2>; + }; + }; + }; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_mipi_lvds { + status = "okay"; + + port { + cif_mipi_in0: endpoint { + remote-endpoint = <&mipi0_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds2 { + status = "okay"; + + port { + cif_mipi_in2: endpoint { + remote-endpoint = <&mipi2_csi2_output>; + }; + }; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + hdmiin { + lt6911uxe_pin: lt6911uxe-pin { + rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>, + <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + lt6911uxe_pin_1: lt6911uxe-pin-1 { + rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>, + <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; From 55d671ad128bbf945d035fe56afea11942cd4818 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Tue, 30 Aug 2022 03:40:40 +0000 Subject: [PATCH 148/235] arm64: rockchip_defconfig: enable CONFIG_VIDEO_LT6911UXE for rk3588 evb1 extboard Signed-off-by: Jianwei Fan Change-Id: Ib47b113ff10a13fb0b23e19567ec84767f1b880b --- 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 85e9598f16a3..706982fe9739 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -573,6 +573,7 @@ CONFIG_VIDEO_ROCKCHIP_ISP=y CONFIG_VIDEO_ROCKCHIP_ISPP=y CONFIG_VIDEO_ROCKCHIP_HDMIRX=y CONFIG_VIDEO_LT6911UXC=y +CONFIG_VIDEO_LT6911UXE=y CONFIG_VIDEO_LT7911D=y CONFIG_VIDEO_NVP6188=y CONFIG_VIDEO_RK628_CSI=y From 3196fead2cdf95f0492a36aebd539ddd8f5ca3bf Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Thu, 24 Nov 2022 16:09:49 +0800 Subject: [PATCH 149/235] ARM: dts: rockchip: rk3288: add rk3288-pinctrl.dtsi Move rk3288 pinctrl functions to rk3288-pinctrl.dtsi. Signed-off-by: Jianqun Xu Change-Id: I358b4311ac47cb3c88cf372fb6662dfe4d9e6bd7 --- arch/arm/boot/dts/rk3288-pinctrl.dtsi | 678 ++++++++++++++++++++++++++ arch/arm/boot/dts/rk3288.dtsi | 595 +--------------------- 2 files changed, 680 insertions(+), 593 deletions(-) create mode 100644 arch/arm/boot/dts/rk3288-pinctrl.dtsi diff --git a/arch/arm/boot/dts/rk3288-pinctrl.dtsi b/arch/arm/boot/dts/rk3288-pinctrl.dtsi new file mode 100644 index 000000000000..42882bbfbc4d --- /dev/null +++ b/arch/arm/boot/dts/rk3288-pinctrl.dtsi @@ -0,0 +1,678 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +#include +#include "rockchip-pinconf.dtsi" + +&pinctrl { + hdmi { + hdmi_gpio: hdmi-gpio { + rockchip,pins = + <7 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>, + <7 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + hdmi_cec_c0: hdmi-cec-c0 { + rockchip,pins = + <7 RK_PC0 2 &pcfg_pull_none>; + }; + + hdmi_cec_c7: hdmi-cec-c7 { + rockchip,pins = + <7 RK_PC7 4 &pcfg_pull_none>; + }; + + hdmi_ddc: hdmi-ddc { + rockchip,pins = + <7 RK_PC3 2 &pcfg_pull_none>, + <7 RK_PC4 2 &pcfg_pull_none>; + }; + + hdmi_ddc_unwedge: hdmi-ddc-unwedge { + rockchip,pins = + <7 RK_PC3 RK_FUNC_GPIO &pcfg_output_low>, + <7 RK_PC4 2 &pcfg_pull_none>; + }; + }; + + suspend { + global_pwroff: global-pwroff { + rockchip,pins = + <0 RK_PA0 1 &pcfg_pull_none>; + }; + + ddrio_pwroff: ddrio-pwroff { + rockchip,pins = + <0 RK_PA1 1 &pcfg_pull_none>; + }; + + ddr0_retention: ddr0-retention { + rockchip,pins = + <0 RK_PA2 1 &pcfg_pull_up>; + }; + + ddr1_retention: ddr1-retention { + rockchip,pins = + <0 RK_PA3 1 &pcfg_pull_up>; + }; + }; + + edp { + edp_hpd: edp-hpd { + rockchip,pins = + <7 RK_PB3 2 &pcfg_pull_down>; + }; + }; + + i2c0 { + i2c0_xfer: i2c0-xfer { + rockchip,pins = + <0 RK_PB7 1 &pcfg_pull_none>, + <0 RK_PC0 1 &pcfg_pull_none>; + }; + }; + + i2c1 { + i2c1_xfer: i2c1-xfer { + rockchip,pins = + <8 RK_PA4 1 &pcfg_pull_none>, + <8 RK_PA5 1 &pcfg_pull_none>; + }; + }; + + i2c2 { + i2c2_xfer: i2c2-xfer { + rockchip,pins = + <6 RK_PB1 1 &pcfg_pull_none>, + <6 RK_PB2 1 &pcfg_pull_none>; + }; + }; + + i2c3 { + i2c3_xfer: i2c3-xfer { + rockchip,pins = + <2 RK_PC0 1 &pcfg_pull_none>, + <2 RK_PC1 1 &pcfg_pull_none>; + }; + }; + + i2c4 { + i2c4_xfer: i2c4-xfer { + rockchip,pins = + <7 RK_PC1 1 &pcfg_pull_none>, + <7 RK_PC2 1 &pcfg_pull_none>; + }; + }; + + i2c5 { + i2c5_xfer: i2c5-xfer { + rockchip,pins = + <7 RK_PC3 1 &pcfg_pull_none>, + <7 RK_PC4 1 &pcfg_pull_none>; + }; + }; + + i2s0 { + i2s0_bus: i2s0-bus { + rockchip,pins = + <6 RK_PA0 1 &pcfg_pull_none>, + <6 RK_PA1 1 &pcfg_pull_none>, + <6 RK_PA2 1 &pcfg_pull_none>, + <6 RK_PA3 1 &pcfg_pull_none>, + <6 RK_PA4 1 &pcfg_pull_none>; + }; + + i2s0_mclk: i2s0-mclk { + rockchip,pins = + <6 RK_PB0 1 &pcfg_pull_none>; + }; + }; + + lcdc { + lcdc_rgb_pins: lcdc-rgb-pins { + rockchip,pins = + <1 RK_PD3 1 &pcfg_pull_none>, /* LCDC_DCLK */ + <1 RK_PD2 1 &pcfg_pull_none>, /* LCDC_DEN */ + <1 RK_PD1 1 &pcfg_pull_none>, /* LCDC_VSYNC */ + <1 RK_PD0 1 &pcfg_pull_none>; /* LCDC_HSYNC */ + }; + + lcdc_sleep_pins: lcdc-sleep-pins { + rockchip,pins = + <1 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>, /* LCDC_DCLK */ + <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>, /* LCDC_DEN */ + <1 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>, /* LCDC_VSYNC */ + <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; /* LCDC_HSYNC */ + }; + }; + + sdmmc { + sdmmc_clk: sdmmc-clk { + rockchip,pins = + <6 RK_PC4 1 &pcfg_pull_none>; + }; + + sdmmc_cmd: sdmmc-cmd { + rockchip,pins = + <6 RK_PC5 1 &pcfg_pull_up>; + }; + + sdmmc_cd: sdmmc-cd { + rockchip,pins = + <6 RK_PC6 1 &pcfg_pull_up>; + }; + + sdmmc_bus1: sdmmc-bus1 { + rockchip,pins = + <6 RK_PC0 1 &pcfg_pull_up>; + }; + + sdmmc_bus4: sdmmc-bus4 { + rockchip,pins = + <6 RK_PC0 1 &pcfg_pull_up>, + <6 RK_PC1 1 &pcfg_pull_up>, + <6 RK_PC2 1 &pcfg_pull_up>, + <6 RK_PC3 1 &pcfg_pull_up>; + }; + }; + + sdio0 { + sdio0_bus1: sdio0-bus1 { + rockchip,pins = + <4 RK_PC4 1 &pcfg_pull_up>; + }; + + sdio0_bus4: sdio0-bus4 { + rockchip,pins = + <4 RK_PC4 1 &pcfg_pull_up>, + <4 RK_PC5 1 &pcfg_pull_up>, + <4 RK_PC6 1 &pcfg_pull_up>, + <4 RK_PC7 1 &pcfg_pull_up>; + }; + + sdio0_cmd: sdio0-cmd { + rockchip,pins = + <4 RK_PD0 1 &pcfg_pull_up>; + }; + + sdio0_clk: sdio0-clk { + rockchip,pins = + <4 RK_PD1 1 &pcfg_pull_none>; + }; + + sdio0_cd: sdio0-cd { + rockchip,pins = + <4 RK_PD2 1 &pcfg_pull_up>; + }; + + sdio0_wp: sdio0-wp { + rockchip,pins = + <4 RK_PD3 1 &pcfg_pull_up>; + }; + + sdio0_pwr: sdio0-pwr { + rockchip,pins = + <4 RK_PD4 1 &pcfg_pull_up>; + }; + + sdio0_bkpwr: sdio0-bkpwr { + rockchip,pins = + <4 RK_PD5 1 &pcfg_pull_up>; + }; + + sdio0_int: sdio0-int { + rockchip,pins = + <4 RK_PD6 1 &pcfg_pull_up>; + }; + }; + + sdio1 { + sdio1_bus1: sdio1-bus1 { + rockchip,pins = + <3 RK_PD0 4 &pcfg_pull_up>; + }; + + sdio1_bus4: sdio1-bus4 { + rockchip,pins = + <3 RK_PD0 4 &pcfg_pull_up>, + <3 RK_PD1 4 &pcfg_pull_up>, + <3 RK_PD2 4 &pcfg_pull_up>, + <3 RK_PD3 4 &pcfg_pull_up>; + }; + + sdio1_cd: sdio1-cd { + rockchip,pins = + <3 RK_PD4 4 &pcfg_pull_up>; + }; + + sdio1_wp: sdio1-wp { + rockchip,pins = + <3 RK_PD5 4 &pcfg_pull_up>; + }; + + sdio1_bkpwr: sdio1-bkpwr { + rockchip,pins = + <3 RK_PD6 4 &pcfg_pull_up>; + }; + + sdio1_int: sdio1-int { + rockchip,pins = + <3 RK_PD7 4 &pcfg_pull_up>; + }; + + sdio1_cmd: sdio1-cmd { + rockchip,pins = + <4 RK_PA6 4 &pcfg_pull_up>; + }; + + sdio1_clk: sdio1-clk { + rockchip,pins = + <4 RK_PA7 4 &pcfg_pull_none>; + }; + + sdio1_pwr: sdio1-pwr { + rockchip,pins = + <4 RK_PB1 4 &pcfg_pull_up>; + }; + }; + + emmc { + emmc_clk: emmc-clk { + rockchip,pins = + <3 RK_PC2 2 &pcfg_pull_none>; + }; + + emmc_cmd: emmc-cmd { + rockchip,pins = + <3 RK_PC0 2 &pcfg_pull_up>; + }; + + emmc_pwr: emmc-pwr { + rockchip,pins = + <3 RK_PB1 2 &pcfg_pull_up>; + }; + + emmc_bus1: emmc-bus1 { + rockchip,pins = + <3 RK_PA0 2 &pcfg_pull_up>; + }; + + emmc_bus4: emmc-bus4 { + rockchip,pins = + <3 RK_PA0 2 &pcfg_pull_up>, + <3 RK_PA1 2 &pcfg_pull_up>, + <3 RK_PA2 2 &pcfg_pull_up>, + <3 RK_PA3 2 &pcfg_pull_up>; + }; + + emmc_bus8: emmc-bus8 { + rockchip,pins = + <3 RK_PA0 2 &pcfg_pull_up>, + <3 RK_PA1 2 &pcfg_pull_up>, + <3 RK_PA2 2 &pcfg_pull_up>, + <3 RK_PA3 2 &pcfg_pull_up>, + <3 RK_PA4 2 &pcfg_pull_up>, + <3 RK_PA5 2 &pcfg_pull_up>, + <3 RK_PA6 2 &pcfg_pull_up>, + <3 RK_PA7 2 &pcfg_pull_up>; + }; + }; + + spi0 { + spi0_clk: spi0-clk { + rockchip,pins = + <5 RK_PB4 1 &pcfg_pull_up>; + }; + spi0_cs0: spi0-cs0 { + rockchip,pins = + <5 RK_PB5 1 &pcfg_pull_up>; + }; + spi0_tx: spi0-tx { + rockchip,pins = + <5 RK_PB6 1 &pcfg_pull_up>; + }; + spi0_rx: spi0-rx { + rockchip,pins = + <5 RK_PB7 1 &pcfg_pull_up>; + }; + spi0_cs1: spi0-cs1 { + rockchip,pins = + <5 RK_PC0 1 &pcfg_pull_up>; + }; + }; + spi1 { + spi1_clk: spi1-clk { + rockchip,pins = + <7 RK_PB4 2 &pcfg_pull_up>; + }; + spi1_cs0: spi1-cs0 { + rockchip,pins = + <7 RK_PB5 2 &pcfg_pull_up>; + }; + spi1_rx: spi1-rx { + rockchip,pins = + <7 RK_PB6 2 &pcfg_pull_up>; + }; + spi1_tx: spi1-tx { + rockchip,pins = + <7 RK_PB7 2 &pcfg_pull_up>; + }; + }; + + spi2 { + spi2_cs1: spi2-cs1 { + rockchip,pins = + <8 RK_PA3 1 &pcfg_pull_up>; + }; + spi2_clk: spi2-clk { + rockchip,pins = + <8 RK_PA6 1 &pcfg_pull_up>; + }; + spi2_cs0: spi2-cs0 { + rockchip,pins = + <8 RK_PA7 1 &pcfg_pull_up>; + }; + spi2_rx: spi2-rx { + rockchip,pins = + <8 RK_PB0 1 &pcfg_pull_up>; + }; + spi2_tx: spi2-tx { + rockchip,pins = + <8 RK_PB1 1 &pcfg_pull_up>; + }; + }; + + uart0 { + uart0_xfer: uart0-xfer { + rockchip,pins = + <4 RK_PC0 1 &pcfg_pull_up>, + <4 RK_PC1 1 &pcfg_pull_up>; + }; + + uart0_cts: uart0-cts { + rockchip,pins = + <4 RK_PC2 1 &pcfg_pull_up>; + }; + + uart0_rts: uart0-rts { + rockchip,pins = + <4 RK_PC3 1 &pcfg_pull_none>; + }; + }; + + uart1 { + uart1_xfer: uart1-xfer { + rockchip,pins = + <5 RK_PB0 1 &pcfg_pull_up>, + <5 RK_PB1 1 &pcfg_pull_up>; + }; + + uart1_cts: uart1-cts { + rockchip,pins = + <5 RK_PB2 1 &pcfg_pull_up>; + }; + + uart1_rts: uart1-rts { + rockchip,pins = + <5 RK_PB3 1 &pcfg_pull_none>; + }; + }; + + uart2 { + uart2_xfer: uart2-xfer { + rockchip,pins = + <7 RK_PC6 1 &pcfg_pull_up>, + <7 RK_PC7 1 &pcfg_pull_up>; + }; + /* no rts / cts for uart2 */ + }; + + uart3 { + uart3_xfer: uart3-xfer { + rockchip,pins = + <7 RK_PA7 1 &pcfg_pull_up>, + <7 RK_PB0 1 &pcfg_pull_up>; + }; + + uart3_cts: uart3-cts { + rockchip,pins = + <7 RK_PB1 1 &pcfg_pull_up>; + }; + + uart3_rts: uart3-rts { + rockchip,pins = + <7 RK_PB2 1 &pcfg_pull_none>; + }; + }; + + uart4 { + uart4_xfer: uart4-xfer { + rockchip,pins = + <5 RK_PB7 3 &pcfg_pull_up>, + <5 RK_PB6 3 &pcfg_pull_up>; + }; + + uart4_cts: uart4-cts { + rockchip,pins = + <5 RK_PB4 3 &pcfg_pull_up>; + }; + + uart4_rts: uart4-rts { + rockchip,pins = + <5 RK_PB5 3 &pcfg_pull_none>; + }; + }; + + tsadc { + otp_pin: otp-pin { + rockchip,pins = + <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + otp_out: otp-out { + rockchip,pins = + <0 RK_PB2 1 &pcfg_pull_none>; + }; + }; + + pwm0 { + pwm0_pin: pwm0-pin { + rockchip,pins = + <7 RK_PA0 1 &pcfg_pull_none>; + }; + + pwm0_pin_pull_down: pwm0-pin-pull-down { + rockchip,pins = + <7 RK_PA0 1 &pcfg_pull_down>; + }; + + }; + + pwm1 { + pwm1_pin: pwm1-pin { + rockchip,pins = + <7 RK_PA1 1 &pcfg_pull_none>; + }; + + pwm1_pin_pull_down: pwm1-pin-pull-down { + rockchip,pins = + <7 RK_PA1 1 &pcfg_pull_down>; + }; + }; + + pwm2 { + pwm2_pin: pwm2-pin { + rockchip,pins = + <7 RK_PC6 3 &pcfg_pull_none>; + }; + + pwm2_pin_pull_down: pwm2-pin-pull-down { + rockchip,pins = + <7 RK_PC6 3 &pcfg_pull_down>; + }; + }; + + pwm3 { + pwm3_pin: pwm3-pin { + rockchip,pins = + <7 RK_PC7 3 &pcfg_pull_none>; + }; + + pwm3_pin_pull_down: pwm3-pin-pull-down { + rockchip,pins = + <7 RK_PC7 3 &pcfg_pull_down>; + }; + }; + + gmac { + rgmii_pins: rgmii-pins { + rockchip,pins = + <3 RK_PD6 3 &pcfg_pull_none>, + <3 RK_PD7 3 &pcfg_pull_none>, + <3 RK_PD2 3 &pcfg_pull_none>, + <3 RK_PD3 3 &pcfg_pull_none>, + <3 RK_PD4 3 &pcfg_pull_none_drv_level_12>, + <3 RK_PD5 3 &pcfg_pull_none_drv_level_12>, + <3 RK_PD0 3 &pcfg_pull_none_drv_level_12>, + <3 RK_PD1 3 &pcfg_pull_none_drv_level_12>, + <4 RK_PA0 3 &pcfg_pull_none>, + <4 RK_PA5 3 &pcfg_pull_none>, + <4 RK_PA6 3 &pcfg_pull_none>, + <4 RK_PB1 3 &pcfg_pull_none_drv_level_12>, + <4 RK_PA4 3 &pcfg_pull_none_drv_level_12>, + <4 RK_PA1 3 &pcfg_pull_none>, + <4 RK_PA3 3 &pcfg_pull_none>; + }; + + rmii_pins: rmii-pins { + rockchip,pins = + <3 RK_PD6 3 &pcfg_pull_none>, + <3 RK_PD7 3 &pcfg_pull_none>, + <3 RK_PD4 3 &pcfg_pull_none>, + <3 RK_PD5 3 &pcfg_pull_none>, + <4 RK_PA0 3 &pcfg_pull_none>, + <4 RK_PA5 3 &pcfg_pull_none>, + <4 RK_PA4 3 &pcfg_pull_none>, + <4 RK_PA1 3 &pcfg_pull_none>, + <4 RK_PA2 3 &pcfg_pull_none>, + <4 RK_PA3 3 &pcfg_pull_none>; + }; + }; + + spdif { + spdif_tx: spdif-tx { + rockchip,pins = + <6 RK_PB3 1 &pcfg_pull_none>; + }; + }; + + isp_pin { + isp_mipi: isp-mipi { + rockchip,pins = + /* cif_clkout */ + <2 RK_PB3 1 &pcfg_pull_none>; + }; + + isp_dvp_d2d9: isp-d2d9 { + rockchip,pins = + /* cif_data2 ... cif_data9 */ + <2 RK_PA0 1 &pcfg_pull_none>, + <2 RK_PA1 1 &pcfg_pull_none>, + <2 RK_PA2 1 &pcfg_pull_none>, + <2 RK_PA3 1 &pcfg_pull_none>, + <2 RK_PA4 1 &pcfg_pull_none>, + <2 RK_PA5 1 &pcfg_pull_none>, + <2 RK_PA6 1 &pcfg_pull_none>, + <2 RK_PA7 1 &pcfg_pull_none>, + /* cif_sync, cif_href */ + <2 RK_PB0 1 &pcfg_pull_none>, + <2 RK_PB1 1 &pcfg_pull_none>, + /* cif_clkin */ + <2 RK_PB2 1 &pcfg_pull_none>; + }; + + isp_dvp_d0d1: isp-d0d1 { + rockchip,pins = + /* cif_data0, cif_data1 */ + <2 RK_PB4 1 &pcfg_pull_none>, + <2 RK_PB5 1 &pcfg_pull_none>; + }; + + isp_dvp_d10d11: isp-d10d11 { + rockchip,pins = + /* cif_data10, cif_data11 */ + <2 RK_PB6 1 &pcfg_pull_none>, + <2 RK_PB7 1 &pcfg_pull_none>; + }; + + isp_dvp_d0d7: isp-d0d7 { + rockchip,pins = + /* cif_data0 ... cif_data7 */ + <2 RK_PB4 1 &pcfg_pull_none>, + <2 RK_PB5 1 &pcfg_pull_none>, + <2 RK_PA0 1 &pcfg_pull_none>, + <2 RK_PA1 1 &pcfg_pull_none>, + <2 RK_PA2 1 &pcfg_pull_none>, + <2 RK_PA3 1 &pcfg_pull_none>, + <2 RK_PA4 1 &pcfg_pull_none>, + <2 RK_PA5 1 &pcfg_pull_none>; + }; + + isp_shutter: isp-shutter { + rockchip,pins = + /* SHUTTEREN, SHUTTERTRIG */ + <7 RK_PB4 2 &pcfg_pull_none>, + <7 RK_PB7 2 &pcfg_pull_none>; + }; + + isp_flash_trigger: isp-flash-trigger { + rockchip,pins = + /* ISP_FLASHTRIGOU */ + <7 RK_PB5 2 &pcfg_pull_none>; + }; + + isp_prelight: isp-prelight { + rockchip,pins = + /* ISP_PRELIGHTTRIG */ + <7 RK_PB6 2 &pcfg_pull_none>; + }; + + isp_flash_trigger_as_gpio: isp-flash-trigger-as-gpio { + rockchip,pins = + /* ISP_FLASHTRIGOU */ + <7 RK_PB5 2 &pcfg_pull_none>; + }; + }; + + cif_pin { + cif_dvp_d0d1: cif-dvp-d0d1 { + rockchip,pins = + <2 RK_PB4 1 &pcfg_pull_none>, /* cif_data0 */ + <2 RK_PB5 1 &pcfg_pull_none>; /* cif_data1 */ + }; + + cif_dvp_d2d9: cif-dvp-d2d9 { + rockchip,pins = + <2 RK_PA0 1 &pcfg_pull_none>, /* cif_data2 */ + <2 RK_PA1 1 &pcfg_pull_none>, /* cif_data3 */ + <2 RK_PA2 1 &pcfg_pull_none>, /* cif_data4 */ + <2 RK_PA3 1 &pcfg_pull_none>, /* cif_data5 */ + <2 RK_PA4 1 &pcfg_pull_none>, /* cif_data6 */ + <2 RK_PA5 1 &pcfg_pull_none>, /* cif_data7 */ + <2 RK_PA6 1 &pcfg_pull_none>, /* cif_data8 */ + <2 RK_PA7 1 &pcfg_pull_none>, /* cif_data9 */ + <2 RK_PB0 1 &pcfg_pull_none>, /* cif_sync */ + <2 RK_PB1 1 &pcfg_pull_none>, /* cif_href */ + <2 RK_PB2 1 &pcfg_pull_none>, /* cif_clkin */ + <2 RK_PB3 1 &pcfg_pull_none>; /* cif_clkout */ + }; + + cif_dvp_d10d11: cif-dvp-d10d11 { + rockchip,pins = + <2 RK_PB6 1 &pcfg_pull_none>, /* cif_data10 */ + <2 RK_PB7 1 &pcfg_pull_none>; /* cif_data11 */ + }; + }; +}; diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 2b05d31b4df3..2ed45b0d03d2 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -2076,602 +2076,11 @@ #interrupt-cells = <2>; }; - hdmi { - hdmi_gpio: hdmi-gpio { - rockchip,pins = <7 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>, - <7 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - hdmi_cec_c0: hdmi-cec-c0 { - rockchip,pins = <7 RK_PC0 2 &pcfg_pull_none>; - }; - - hdmi_cec_c7: hdmi-cec-c7 { - rockchip,pins = <7 RK_PC7 4 &pcfg_pull_none>; - }; - - hdmi_ddc: hdmi-ddc { - rockchip,pins = <7 RK_PC3 2 &pcfg_pull_none>, - <7 RK_PC4 2 &pcfg_pull_none>; - }; - - hdmi_ddc_unwedge: hdmi-ddc-unwedge { - rockchip,pins = <7 RK_PC3 RK_FUNC_GPIO &pcfg_output_low>, - <7 RK_PC4 2 &pcfg_pull_none>; - }; - }; - - pcfg_output_low: pcfg-output-low { - output-low; - }; - - pcfg_pull_up: pcfg-pull-up { - bias-pull-up; - }; - - pcfg_pull_down: pcfg-pull-down { - bias-pull-down; - }; - - pcfg_pull_none: pcfg-pull-none { - bias-disable; - }; - pcfg_pull_none_12ma: pcfg-pull-none-12ma { bias-disable; drive-strength = <12>; }; - - suspend { - global_pwroff: global-pwroff { - rockchip,pins = <0 RK_PA0 1 &pcfg_pull_none>; - }; - - ddrio_pwroff: ddrio-pwroff { - rockchip,pins = <0 RK_PA1 1 &pcfg_pull_none>; - }; - - ddr0_retention: ddr0-retention { - rockchip,pins = <0 RK_PA2 1 &pcfg_pull_up>; - }; - - ddr1_retention: ddr1-retention { - rockchip,pins = <0 RK_PA3 1 &pcfg_pull_up>; - }; - }; - - edp { - edp_hpd: edp-hpd { - rockchip,pins = <7 RK_PB3 2 &pcfg_pull_down>; - }; - }; - - i2c0 { - i2c0_xfer: i2c0-xfer { - rockchip,pins = <0 RK_PB7 1 &pcfg_pull_none>, - <0 RK_PC0 1 &pcfg_pull_none>; - }; - }; - - i2c1 { - i2c1_xfer: i2c1-xfer { - rockchip,pins = <8 RK_PA4 1 &pcfg_pull_none>, - <8 RK_PA5 1 &pcfg_pull_none>; - }; - }; - - i2c2 { - i2c2_xfer: i2c2-xfer { - rockchip,pins = <6 RK_PB1 1 &pcfg_pull_none>, - <6 RK_PB2 1 &pcfg_pull_none>; - }; - }; - - i2c3 { - i2c3_xfer: i2c3-xfer { - rockchip,pins = <2 RK_PC0 1 &pcfg_pull_none>, - <2 RK_PC1 1 &pcfg_pull_none>; - }; - }; - - i2c4 { - i2c4_xfer: i2c4-xfer { - rockchip,pins = <7 RK_PC1 1 &pcfg_pull_none>, - <7 RK_PC2 1 &pcfg_pull_none>; - }; - }; - - i2c5 { - i2c5_xfer: i2c5-xfer { - rockchip,pins = <7 RK_PC3 1 &pcfg_pull_none>, - <7 RK_PC4 1 &pcfg_pull_none>; - }; - }; - - i2s0 { - i2s0_bus: i2s0-bus { - rockchip,pins = <6 RK_PA0 1 &pcfg_pull_none>, - <6 RK_PA1 1 &pcfg_pull_none>, - <6 RK_PA2 1 &pcfg_pull_none>, - <6 RK_PA3 1 &pcfg_pull_none>, - <6 RK_PA4 1 &pcfg_pull_none>; - }; - - i2s0_mclk: i2s0-mclk { - rockchip,pins = <6 RK_PB0 1 &pcfg_pull_none>; - }; - }; - - lcdc { - lcdc_rgb_pins: lcdc-rgb-pins { - rockchip,pins = <1 RK_PD3 1 &pcfg_pull_none>, /* LCDC_DCLK */ - <1 RK_PD2 1 &pcfg_pull_none>, /* LCDC_DEN */ - <1 RK_PD1 1 &pcfg_pull_none>, /* LCDC_VSYNC */ - <1 RK_PD0 1 &pcfg_pull_none>; /* LCDC_HSYNC */ - }; - - lcdc_sleep_pins: lcdc-sleep-pins { - rockchip,pins = <1 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>, /* LCDC_DCLK */ - <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>, /* LCDC_DEN */ - <1 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>, /* LCDC_VSYNC */ - <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; /* LCDC_HSYNC */ - }; - }; - - sdmmc { - sdmmc_clk: sdmmc-clk { - rockchip,pins = <6 RK_PC4 1 &pcfg_pull_none>; - }; - - sdmmc_cmd: sdmmc-cmd { - rockchip,pins = <6 RK_PC5 1 &pcfg_pull_up>; - }; - - sdmmc_cd: sdmmc-cd { - rockchip,pins = <6 RK_PC6 1 &pcfg_pull_up>; - }; - - sdmmc_bus1: sdmmc-bus1 { - rockchip,pins = <6 RK_PC0 1 &pcfg_pull_up>; - }; - - sdmmc_bus4: sdmmc-bus4 { - rockchip,pins = <6 RK_PC0 1 &pcfg_pull_up>, - <6 RK_PC1 1 &pcfg_pull_up>, - <6 RK_PC2 1 &pcfg_pull_up>, - <6 RK_PC3 1 &pcfg_pull_up>; - }; - }; - - sdio0 { - sdio0_bus1: sdio0-bus1 { - rockchip,pins = <4 RK_PC4 1 &pcfg_pull_up>; - }; - - sdio0_bus4: sdio0-bus4 { - rockchip,pins = <4 RK_PC4 1 &pcfg_pull_up>, - <4 RK_PC5 1 &pcfg_pull_up>, - <4 RK_PC6 1 &pcfg_pull_up>, - <4 RK_PC7 1 &pcfg_pull_up>; - }; - - sdio0_cmd: sdio0-cmd { - rockchip,pins = <4 RK_PD0 1 &pcfg_pull_up>; - }; - - sdio0_clk: sdio0-clk { - rockchip,pins = <4 RK_PD1 1 &pcfg_pull_none>; - }; - - sdio0_cd: sdio0-cd { - rockchip,pins = <4 RK_PD2 1 &pcfg_pull_up>; - }; - - sdio0_wp: sdio0-wp { - rockchip,pins = <4 RK_PD3 1 &pcfg_pull_up>; - }; - - sdio0_pwr: sdio0-pwr { - rockchip,pins = <4 RK_PD4 1 &pcfg_pull_up>; - }; - - sdio0_bkpwr: sdio0-bkpwr { - rockchip,pins = <4 RK_PD5 1 &pcfg_pull_up>; - }; - - sdio0_int: sdio0-int { - rockchip,pins = <4 RK_PD6 1 &pcfg_pull_up>; - }; - }; - - sdio1 { - sdio1_bus1: sdio1-bus1 { - rockchip,pins = <3 RK_PD0 4 &pcfg_pull_up>; - }; - - sdio1_bus4: sdio1-bus4 { - rockchip,pins = <3 RK_PD0 4 &pcfg_pull_up>, - <3 RK_PD1 4 &pcfg_pull_up>, - <3 RK_PD2 4 &pcfg_pull_up>, - <3 RK_PD3 4 &pcfg_pull_up>; - }; - - sdio1_cd: sdio1-cd { - rockchip,pins = <3 RK_PD4 4 &pcfg_pull_up>; - }; - - sdio1_wp: sdio1-wp { - rockchip,pins = <3 RK_PD5 4 &pcfg_pull_up>; - }; - - sdio1_bkpwr: sdio1-bkpwr { - rockchip,pins = <3 RK_PD6 4 &pcfg_pull_up>; - }; - - sdio1_int: sdio1-int { - rockchip,pins = <3 RK_PD7 4 &pcfg_pull_up>; - }; - - sdio1_cmd: sdio1-cmd { - rockchip,pins = <4 RK_PA6 4 &pcfg_pull_up>; - }; - - sdio1_clk: sdio1-clk { - rockchip,pins = <4 RK_PA7 4 &pcfg_pull_none>; - }; - - sdio1_pwr: sdio1-pwr { - rockchip,pins = <4 RK_PB1 4 &pcfg_pull_up>; - }; - }; - - emmc { - emmc_clk: emmc-clk { - rockchip,pins = <3 RK_PC2 2 &pcfg_pull_none>; - }; - - emmc_cmd: emmc-cmd { - rockchip,pins = <3 RK_PC0 2 &pcfg_pull_up>; - }; - - emmc_pwr: emmc-pwr { - rockchip,pins = <3 RK_PB1 2 &pcfg_pull_up>; - }; - - emmc_bus1: emmc-bus1 { - rockchip,pins = <3 RK_PA0 2 &pcfg_pull_up>; - }; - - emmc_bus4: emmc-bus4 { - rockchip,pins = <3 RK_PA0 2 &pcfg_pull_up>, - <3 RK_PA1 2 &pcfg_pull_up>, - <3 RK_PA2 2 &pcfg_pull_up>, - <3 RK_PA3 2 &pcfg_pull_up>; - }; - - emmc_bus8: emmc-bus8 { - rockchip,pins = <3 RK_PA0 2 &pcfg_pull_up>, - <3 RK_PA1 2 &pcfg_pull_up>, - <3 RK_PA2 2 &pcfg_pull_up>, - <3 RK_PA3 2 &pcfg_pull_up>, - <3 RK_PA4 2 &pcfg_pull_up>, - <3 RK_PA5 2 &pcfg_pull_up>, - <3 RK_PA6 2 &pcfg_pull_up>, - <3 RK_PA7 2 &pcfg_pull_up>; - }; - }; - - spi0 { - spi0_clk: spi0-clk { - rockchip,pins = <5 RK_PB4 1 &pcfg_pull_up>; - }; - spi0_cs0: spi0-cs0 { - rockchip,pins = <5 RK_PB5 1 &pcfg_pull_up>; - }; - spi0_tx: spi0-tx { - rockchip,pins = <5 RK_PB6 1 &pcfg_pull_up>; - }; - spi0_rx: spi0-rx { - rockchip,pins = <5 RK_PB7 1 &pcfg_pull_up>; - }; - spi0_cs1: spi0-cs1 { - rockchip,pins = <5 RK_PC0 1 &pcfg_pull_up>; - }; - }; - spi1 { - spi1_clk: spi1-clk { - rockchip,pins = <7 RK_PB4 2 &pcfg_pull_up>; - }; - spi1_cs0: spi1-cs0 { - rockchip,pins = <7 RK_PB5 2 &pcfg_pull_up>; - }; - spi1_rx: spi1-rx { - rockchip,pins = <7 RK_PB6 2 &pcfg_pull_up>; - }; - spi1_tx: spi1-tx { - rockchip,pins = <7 RK_PB7 2 &pcfg_pull_up>; - }; - }; - - spi2 { - spi2_cs1: spi2-cs1 { - rockchip,pins = <8 RK_PA3 1 &pcfg_pull_up>; - }; - spi2_clk: spi2-clk { - rockchip,pins = <8 RK_PA6 1 &pcfg_pull_up>; - }; - spi2_cs0: spi2-cs0 { - rockchip,pins = <8 RK_PA7 1 &pcfg_pull_up>; - }; - spi2_rx: spi2-rx { - rockchip,pins = <8 RK_PB0 1 &pcfg_pull_up>; - }; - spi2_tx: spi2-tx { - rockchip,pins = <8 RK_PB1 1 &pcfg_pull_up>; - }; - }; - - uart0 { - uart0_xfer: uart0-xfer { - rockchip,pins = <4 RK_PC0 1 &pcfg_pull_up>, - <4 RK_PC1 1 &pcfg_pull_up>; - }; - - uart0_cts: uart0-cts { - rockchip,pins = <4 RK_PC2 1 &pcfg_pull_up>; - }; - - uart0_rts: uart0-rts { - rockchip,pins = <4 RK_PC3 1 &pcfg_pull_none>; - }; - }; - - uart1 { - uart1_xfer: uart1-xfer { - rockchip,pins = <5 RK_PB0 1 &pcfg_pull_up>, - <5 RK_PB1 1 &pcfg_pull_up>; - }; - - uart1_cts: uart1-cts { - rockchip,pins = <5 RK_PB2 1 &pcfg_pull_up>; - }; - - uart1_rts: uart1-rts { - rockchip,pins = <5 RK_PB3 1 &pcfg_pull_none>; - }; - }; - - uart2 { - uart2_xfer: uart2-xfer { - rockchip,pins = <7 RK_PC6 1 &pcfg_pull_up>, - <7 RK_PC7 1 &pcfg_pull_up>; - }; - /* no rts / cts for uart2 */ - }; - - uart3 { - uart3_xfer: uart3-xfer { - rockchip,pins = <7 RK_PA7 1 &pcfg_pull_up>, - <7 RK_PB0 1 &pcfg_pull_up>; - }; - - uart3_cts: uart3-cts { - rockchip,pins = <7 RK_PB1 1 &pcfg_pull_up>; - }; - - uart3_rts: uart3-rts { - rockchip,pins = <7 RK_PB2 1 &pcfg_pull_none>; - }; - }; - - uart4 { - uart4_xfer: uart4-xfer { - rockchip,pins = <5 RK_PB7 3 &pcfg_pull_up>, - <5 RK_PB6 3 &pcfg_pull_up>; - }; - - uart4_cts: uart4-cts { - rockchip,pins = <5 RK_PB4 3 &pcfg_pull_up>; - }; - - uart4_rts: uart4-rts { - rockchip,pins = <5 RK_PB5 3 &pcfg_pull_none>; - }; - }; - - tsadc { - otp_pin: otp-pin { - rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - otp_out: otp-out { - rockchip,pins = <0 RK_PB2 1 &pcfg_pull_none>; - }; - }; - - pwm0 { - pwm0_pin: pwm0-pin { - rockchip,pins = <7 RK_PA0 1 &pcfg_pull_none>; - }; - - pwm0_pin_pull_down: pwm0-pin-pull-down { - rockchip,pins = <7 RK_PA0 1 &pcfg_pull_down>; - }; - - }; - - pwm1 { - pwm1_pin: pwm1-pin { - rockchip,pins = <7 RK_PA1 1 &pcfg_pull_none>; - }; - - pwm1_pin_pull_down: pwm1-pin-pull-down { - rockchip,pins = <7 RK_PA1 1 &pcfg_pull_down>; - }; - }; - - pwm2 { - pwm2_pin: pwm2-pin { - rockchip,pins = <7 RK_PC6 3 &pcfg_pull_none>; - }; - - pwm2_pin_pull_down: pwm2-pin-pull-down { - rockchip,pins = <7 RK_PC6 3 &pcfg_pull_down>; - }; - }; - - pwm3 { - pwm3_pin: pwm3-pin { - rockchip,pins = <7 RK_PC7 3 &pcfg_pull_none>; - }; - - pwm3_pin_pull_down: pwm3-pin-pull-down { - rockchip,pins = <7 RK_PC7 3 &pcfg_pull_down>; - }; - }; - - gmac { - rgmii_pins: rgmii-pins { - rockchip,pins = <3 RK_PD6 3 &pcfg_pull_none>, - <3 RK_PD7 3 &pcfg_pull_none>, - <3 RK_PD2 3 &pcfg_pull_none>, - <3 RK_PD3 3 &pcfg_pull_none>, - <3 RK_PD4 3 &pcfg_pull_none_12ma>, - <3 RK_PD5 3 &pcfg_pull_none_12ma>, - <3 RK_PD0 3 &pcfg_pull_none_12ma>, - <3 RK_PD1 3 &pcfg_pull_none_12ma>, - <4 RK_PA0 3 &pcfg_pull_none>, - <4 RK_PA5 3 &pcfg_pull_none>, - <4 RK_PA6 3 &pcfg_pull_none>, - <4 RK_PB1 3 &pcfg_pull_none_12ma>, - <4 RK_PA4 3 &pcfg_pull_none_12ma>, - <4 RK_PA1 3 &pcfg_pull_none>, - <4 RK_PA3 3 &pcfg_pull_none>; - }; - - rmii_pins: rmii-pins { - rockchip,pins = <3 RK_PD6 3 &pcfg_pull_none>, - <3 RK_PD7 3 &pcfg_pull_none>, - <3 RK_PD4 3 &pcfg_pull_none>, - <3 RK_PD5 3 &pcfg_pull_none>, - <4 RK_PA0 3 &pcfg_pull_none>, - <4 RK_PA5 3 &pcfg_pull_none>, - <4 RK_PA4 3 &pcfg_pull_none>, - <4 RK_PA1 3 &pcfg_pull_none>, - <4 RK_PA2 3 &pcfg_pull_none>, - <4 RK_PA3 3 &pcfg_pull_none>; - }; - }; - - spdif { - spdif_tx: spdif-tx { - rockchip,pins = <6 RK_PB3 1 &pcfg_pull_none>; - }; - }; - - isp_pin { - isp_mipi: isp-mipi { - rockchip,pins = - /* cif_clkout */ - <2 RK_PB3 1 &pcfg_pull_none>; - }; - - isp_dvp_d2d9: isp-d2d9 { - rockchip,pins = - /* cif_data2 ... cif_data9 */ - <2 RK_PA0 1 &pcfg_pull_none>, - <2 RK_PA1 1 &pcfg_pull_none>, - <2 RK_PA2 1 &pcfg_pull_none>, - <2 RK_PA3 1 &pcfg_pull_none>, - <2 RK_PA4 1 &pcfg_pull_none>, - <2 RK_PA5 1 &pcfg_pull_none>, - <2 RK_PA6 1 &pcfg_pull_none>, - <2 RK_PA7 1 &pcfg_pull_none>, - /* cif_sync, cif_href */ - <2 RK_PB0 1 &pcfg_pull_none>, - <2 RK_PB1 1 &pcfg_pull_none>, - /* cif_clkin */ - <2 RK_PB2 1 &pcfg_pull_none>; - }; - - isp_dvp_d0d1: isp-d0d1 { - rockchip,pins = - /* cif_data0, cif_data1 */ - <2 RK_PB4 1 &pcfg_pull_none>, - <2 RK_PB5 1 &pcfg_pull_none>; - }; - - isp_dvp_d10d11: isp-d10d11 { - rockchip,pins = - /* cif_data10, cif_data11 */ - <2 RK_PB6 1 &pcfg_pull_none>, - <2 RK_PB7 1 &pcfg_pull_none>; - }; - - isp_dvp_d0d7: isp-d0d7 { - rockchip,pins = - /* cif_data0 ... cif_data7 */ - <2 RK_PB4 1 &pcfg_pull_none>, - <2 RK_PB5 1 &pcfg_pull_none>, - <2 RK_PA0 1 &pcfg_pull_none>, - <2 RK_PA1 1 &pcfg_pull_none>, - <2 RK_PA2 1 &pcfg_pull_none>, - <2 RK_PA3 1 &pcfg_pull_none>, - <2 RK_PA4 1 &pcfg_pull_none>, - <2 RK_PA5 1 &pcfg_pull_none>; - }; - - isp_shutter: isp-shutter { - rockchip,pins = - /* SHUTTEREN, SHUTTERTRIG */ - <7 RK_PB4 2 &pcfg_pull_none>, - <7 RK_PB7 2 &pcfg_pull_none>; - }; - - isp_flash_trigger: isp-flash-trigger { - rockchip,pins = - /* ISP_FLASHTRIGOU */ - <7 RK_PB5 2 &pcfg_pull_none>; - }; - - isp_prelight: isp-prelight { - rockchip,pins = - /* ISP_PRELIGHTTRIG */ - <7 RK_PB6 2 &pcfg_pull_none>; - }; - - isp_flash_trigger_as_gpio: isp-flash-trigger-as-gpio { - rockchip,pins = - /* ISP_FLASHTRIGOU */ - <7 RK_PB5 2 &pcfg_pull_none>; - }; - }; - - cif_pin { - cif_dvp_d0d1: cif-dvp-d0d1 { - rockchip,pins = <2 RK_PB4 1 &pcfg_pull_none>, /* cif_data0 */ - <2 RK_PB5 1 &pcfg_pull_none>; /* cif_data1 */ - }; - - cif_dvp_d2d9: cif-dvp-d2d9 { - rockchip,pins = <2 RK_PA0 1 &pcfg_pull_none>, /* cif_data2 */ - <2 RK_PA1 1 &pcfg_pull_none>, /* cif_data3 */ - <2 RK_PA2 1 &pcfg_pull_none>, /* cif_data4 */ - <2 RK_PA3 1 &pcfg_pull_none>, /* cif_data5 */ - <2 RK_PA4 1 &pcfg_pull_none>, /* cif_data6 */ - <2 RK_PA5 1 &pcfg_pull_none>, /* cif_data7 */ - <2 RK_PA6 1 &pcfg_pull_none>, /* cif_data8 */ - <2 RK_PA7 1 &pcfg_pull_none>, /* cif_data9 */ - <2 RK_PB0 1 &pcfg_pull_none>, /* cif_sync */ - <2 RK_PB1 1 &pcfg_pull_none>, /* cif_href */ - <2 RK_PB2 1 &pcfg_pull_none>, /* cif_clkin */ - <2 RK_PB3 1 &pcfg_pull_none>; /* cif_clkout */ - }; - - cif_dvp_d10d11: cif-dvp-d10d11 { - rockchip,pins = <2 RK_PB6 1 &pcfg_pull_none>, /* cif_data10 */ - <2 RK_PB7 1 &pcfg_pull_none>; /* cif_data11 */ - }; - }; }; }; + +#include "rk3288-pinctrl.dtsi" From bbc9d3fcf69bfda06000e9dadd806833871750d9 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Wed, 9 Nov 2022 16:56:25 +0800 Subject: [PATCH 150/235] media: rockchip: vicap disable dma capture in fs intr before stop stream if disable dma capture in fe intr, register write to device may delay after real fs, the register need effect in next real fs, may cause iommu error or size error Signed-off-by: Zefa Chen Change-Id: I451c18f175e89c5ddf7c8a31f2f288dd8c01a8f1 --- drivers/media/platform/rockchip/cif/capture.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 75aaa69a74d4..edcb7e2edacf 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -9071,8 +9071,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) cif_dev->sditf[0]->mode.rdbk_mode) stream->buf_wake_up_cnt++; - if (stream->stopping && - !(stream->cur_stream_mode & RKCIF_STREAM_MODE_TOISP)) { + if (stream->stopping && (!stream->dma_en)) { rkcif_stream_stop(stream); stream->stopping = false; wake_up(&stream->wq_stopped); @@ -9181,6 +9180,12 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) spin_unlock_irqrestore(&stream->fps_lock, flags); } stream->is_in_vblank = false; + if (stream->stopping && stream->dma_en) { + if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) + stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP; + else if (stream->dma_en & RKCIF_DMAEN_BY_ISP) + stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; + } if (stream->to_stop_dma) { ret = rkcif_stop_dma_capture(stream); if (!ret) From 97ca52bdc034e1e16f3ce31f822da0e2284f3e5f Mon Sep 17 00:00:00 2001 From: ZiHan Huang Date: Sat, 26 Nov 2022 16:09:26 +0800 Subject: [PATCH 151/235] ARM: dts: rockchip: rk3036: fix compatible of pwm nodes PWM in rk3036 is the same as rk3288 Change-Id: I078e068c8e6fe64fd2f53b0fde1b1fb9984c76bc Signed-off-by: ZiHan Huang --- arch/arm/boot/dts/rk3036.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 08a284dc6673..471270a09fef 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -560,7 +560,7 @@ }; pwm0: pwm@20050000 { - compatible = "rockchip,rk3036-pwm", "rockchip,rk2928-pwm"; + compatible = "rockchip,rk3036-pwm", "rockchip,rk3288-pwm"; reg = <0x20050000 0x10>; #pwm-cells = <3>; clocks = <&cru PCLK_PWM>; @@ -571,7 +571,7 @@ }; pwm1: pwm@20050010 { - compatible = "rockchip,rk3036-pwm", "rockchip,rk2928-pwm"; + compatible = "rockchip,rk3036-pwm", "rockchip,rk3288-pwm"; reg = <0x20050010 0x10>; #pwm-cells = <3>; clocks = <&cru PCLK_PWM>; @@ -582,7 +582,7 @@ }; pwm2: pwm@20050020 { - compatible = "rockchip,rk3036-pwm", "rockchip,rk2928-pwm"; + compatible = "rockchip,rk3036-pwm", "rockchip,rk3288-pwm"; reg = <0x20050020 0x10>; #pwm-cells = <3>; clocks = <&cru PCLK_PWM>; @@ -593,9 +593,9 @@ }; pwm3: pwm@20050030 { - compatible = "rockchip,rk3036-pwm", "rockchip,rk2928-pwm"; + compatible = "rockchip,rk3036-pwm", "rockchip,rk3288-pwm"; reg = <0x20050030 0x10>; - #pwm-cells = <2>; + #pwm-cells = <3>; clocks = <&cru PCLK_PWM>; clock-names = "pwm"; pinctrl-names = "active"; From 2dd6530d31999e057527292ea98b6737827545cc Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Mon, 28 Nov 2022 11:03:49 +0800 Subject: [PATCH 152/235] video/rockchip: rga: remove ^m Signed-off-by: Yu Qiaowei Change-Id: I2d3945442ef45b6baa9be9d286c1d7b4c70918c8 --- drivers/video/rockchip/rga/RGA_API.c | 400 +-- drivers/video/rockchip/rga/RGA_API.h | 28 +- drivers/video/rockchip/rga/rga.h | 978 +++---- drivers/video/rockchip/rga/rga_drv.c | 1010 +++---- drivers/video/rockchip/rga/rga_mmu_info.c | 2316 ++++++++-------- drivers/video/rockchip/rga/rga_mmu_info.h | 34 +- drivers/video/rockchip/rga/rga_reg_info.c | 3058 ++++++++++----------- drivers/video/rockchip/rga/rga_reg_info.h | 932 +++---- drivers/video/rockchip/rga/rga_rop.h | 110 +- drivers/video/rockchip/rga/rga_type.h | 96 +- 10 files changed, 4481 insertions(+), 4481 deletions(-) diff --git a/drivers/video/rockchip/rga/RGA_API.c b/drivers/video/rockchip/rga/RGA_API.c index 947a9b925f60..4359a6d50379 100644 --- a/drivers/video/rockchip/rga/RGA_API.c +++ b/drivers/video/rockchip/rga/RGA_API.c @@ -1,201 +1,201 @@ /* SPDX-License-Identifier: GPL-2.0 */ - -#include -#include "RGA_API.h" -#include "rga.h" -//#include "rga_angle.h" - -#define IS_YUV_420(format) \ - ((format == RK_FORMAT_YCbCr_420_P) | (format == RK_FORMAT_YCbCr_420_SP) | \ - (format == RK_FORMAT_YCrCb_420_P) | (format == RK_FORMAT_YCrCb_420_SP)) - -#define IS_YUV_422(format) \ - ((format == RK_FORMAT_YCbCr_422_P) | (format == RK_FORMAT_YCbCr_422_SP) | \ - (format == RK_FORMAT_YCrCb_422_P) | (format == RK_FORMAT_YCrCb_422_SP)) - -#define IS_YUV(format) \ - ((format == RK_FORMAT_YCbCr_420_P) | (format == RK_FORMAT_YCbCr_420_SP) | \ - (format == RK_FORMAT_YCrCb_420_P) | (format == RK_FORMAT_YCrCb_420_SP) | \ - (format == RK_FORMAT_YCbCr_422_P) | (format == RK_FORMAT_YCbCr_422_SP) | \ - (format == RK_FORMAT_YCrCb_422_P) | (format == RK_FORMAT_YCrCb_422_SP)) - - -extern rga_service_info rga_service; - - -void -matrix_cal(const struct rga_req *msg, TILE_INFO *tile) -{ - uint64_t x_time, y_time; - uint64_t sina, cosa; - - int s_act_w, s_act_h, d_act_w, d_act_h; - - s_act_w = msg->src.act_w; - s_act_h = msg->src.act_h; - d_act_w = msg->dst.act_w; - d_act_h = msg->dst.act_h; - - if (s_act_w == 1) s_act_w += 1; - if (s_act_h == 1) s_act_h += 1; - if (d_act_h == 1) d_act_h += 1; - if (d_act_w == 1) d_act_w += 1; - - x_time = ((s_act_w - 1)<<16) / (d_act_w - 1); - y_time = ((s_act_h - 1)<<16) / (d_act_h - 1); - - sina = msg->sina; - cosa = msg->cosa; - - switch(msg->rotate_mode) - { - /* 16.16 x 16.16 */ - /* matrix[] is 64 bit wide */ - case 1 : - tile->matrix[0] = cosa*x_time; - tile->matrix[1] = -sina*y_time; - tile->matrix[2] = sina*x_time; - tile->matrix[3] = cosa*y_time; - break; - case 2 : - tile->matrix[0] = -(x_time<<16); - tile->matrix[1] = 0; - tile->matrix[2] = 0; - tile->matrix[3] = (y_time<<16); - break; - case 3 : - tile->matrix[0] = (x_time<<16); - tile->matrix[1] = 0; - tile->matrix[2] = 0; - tile->matrix[3] = -(y_time<<16); - break; - default : - tile->matrix[0] = (uint64_t)1<<32; - tile->matrix[1] = 0; - tile->matrix[2] = 0; - tile->matrix[3] = (uint64_t)1<<32; - break; - } -} - - -int32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1) -{ - - struct rga_req *mp; - uint32_t w_ratio, h_ratio; - uint32_t stride; - - uint32_t daw, dah; - uint32_t pl; - - daw = dah = 0; - - mp = msg1; - - if(msg->dst.act_w == 0) - { - printk("%s, [%d] rga dst act_w is zero\n", __FUNCTION__, __LINE__); - return -EINVAL; - } - - if (msg->dst.act_h == 0) - { - printk("%s, [%d] rga dst act_w is zero\n", __FUNCTION__, __LINE__); - return -EINVAL; - } - w_ratio = (msg->src.act_w << 16) / msg->dst.act_w; - h_ratio = (msg->src.act_h << 16) / msg->dst.act_h; - - memcpy(msg1, msg, sizeof(struct rga_req)); - - msg->dst.format = msg->src.format; - - /*pre_scale_w cal*/ - if ((w_ratio >= (2<<16)) && (w_ratio < (4<<16))) { - daw = (msg->src.act_w + 1) >> 1; - if((IS_YUV_420(msg->dst.format)) && (daw & 1)) { - daw -= 1; - msg->src.act_w = daw << 1; - } - } - else if ((w_ratio >= (4<<16)) && (w_ratio < (8<<16))) { - daw = (msg->src.act_w + 3) >> 2; - if((IS_YUV_420(msg->dst.format)) && (daw & 1)) { - daw -= 1; - msg->src.act_w = daw << 2; - } - } - else if ((w_ratio >= (8<<16)) && (w_ratio < (16<<16))) { - daw = (msg->src.act_w + 7) >> 3; - if((IS_YUV_420(msg->dst.format)) && (daw & 1)) { - daw -= 1; - msg->src.act_w = daw << 3; - } - } - else - { - daw = msg->src.act_w; - } - - pl = (RGA_pixel_width_init(msg->src.format)); - stride = (pl * daw + 3) & (~3); - msg->dst.act_w = daw; - msg->dst.vir_w = stride / pl; - - /*pre_scale_h cal*/ - if ((h_ratio >= (2<<16)) && (h_ratio < (4<<16))) { - dah = (msg->src.act_h + 1) >> 1; - if((IS_YUV(msg->dst.format)) && (dah & 1)) { - dah -= 1; - msg->src.act_h = dah << 1; - } - } - else if ((h_ratio >= (4<<16)) && (h_ratio < (8<<16))) { - dah = (msg->src.act_h + 3) >> 2; - if((IS_YUV(msg->dst.format)) && (dah & 1)) { - dah -= 1; - msg->src.act_h = dah << 2; - - } - } - else if ((h_ratio >= (8<<16)) && (h_ratio < (16<<16))) { - dah = (msg->src.act_h + 7) >> 3; - if((IS_YUV(msg->dst.format)) && (dah & 1)) { - dah -= 1; - msg->src.act_h = dah << 3; - } - } - else - { - dah = msg->src.act_h; - } - - msg->dst.act_h = dah; - msg->dst.vir_h = dah; - - msg->dst.x_offset = 0; - msg->dst.y_offset = 0; - - msg->dst.yrgb_addr = (unsigned long)rga_service.pre_scale_buf; - msg->dst.uv_addr = msg->dst.yrgb_addr + stride * dah; - msg->dst.v_addr = msg->dst.uv_addr + ((stride * dah) >> 1); - - msg->render_mode = pre_scaling_mode; - - msg1->src.yrgb_addr = msg->dst.yrgb_addr; - msg1->src.uv_addr = msg->dst.uv_addr; - msg1->src.v_addr = msg->dst.v_addr; - - msg1->src.act_w = msg->dst.act_w; - msg1->src.act_h = msg->dst.act_h; - msg1->src.vir_w = msg->dst.vir_w; - msg1->src.vir_h = msg->dst.vir_h; - - msg1->src.x_offset = 0; - msg1->src.y_offset = 0; - - return 0; -} - - + +#include +#include "RGA_API.h" +#include "rga.h" +//#include "rga_angle.h" + +#define IS_YUV_420(format) \ + ((format == RK_FORMAT_YCbCr_420_P) | (format == RK_FORMAT_YCbCr_420_SP) | \ + (format == RK_FORMAT_YCrCb_420_P) | (format == RK_FORMAT_YCrCb_420_SP)) + +#define IS_YUV_422(format) \ + ((format == RK_FORMAT_YCbCr_422_P) | (format == RK_FORMAT_YCbCr_422_SP) | \ + (format == RK_FORMAT_YCrCb_422_P) | (format == RK_FORMAT_YCrCb_422_SP)) + +#define IS_YUV(format) \ + ((format == RK_FORMAT_YCbCr_420_P) | (format == RK_FORMAT_YCbCr_420_SP) | \ + (format == RK_FORMAT_YCrCb_420_P) | (format == RK_FORMAT_YCrCb_420_SP) | \ + (format == RK_FORMAT_YCbCr_422_P) | (format == RK_FORMAT_YCbCr_422_SP) | \ + (format == RK_FORMAT_YCrCb_422_P) | (format == RK_FORMAT_YCrCb_422_SP)) + + +extern rga_service_info rga_service; + + +void +matrix_cal(const struct rga_req *msg, TILE_INFO *tile) +{ + uint64_t x_time, y_time; + uint64_t sina, cosa; + + int s_act_w, s_act_h, d_act_w, d_act_h; + + s_act_w = msg->src.act_w; + s_act_h = msg->src.act_h; + d_act_w = msg->dst.act_w; + d_act_h = msg->dst.act_h; + + if (s_act_w == 1) s_act_w += 1; + if (s_act_h == 1) s_act_h += 1; + if (d_act_h == 1) d_act_h += 1; + if (d_act_w == 1) d_act_w += 1; + + x_time = ((s_act_w - 1)<<16) / (d_act_w - 1); + y_time = ((s_act_h - 1)<<16) / (d_act_h - 1); + + sina = msg->sina; + cosa = msg->cosa; + + switch(msg->rotate_mode) + { + /* 16.16 x 16.16 */ + /* matrix[] is 64 bit wide */ + case 1 : + tile->matrix[0] = cosa*x_time; + tile->matrix[1] = -sina*y_time; + tile->matrix[2] = sina*x_time; + tile->matrix[3] = cosa*y_time; + break; + case 2 : + tile->matrix[0] = -(x_time<<16); + tile->matrix[1] = 0; + tile->matrix[2] = 0; + tile->matrix[3] = (y_time<<16); + break; + case 3 : + tile->matrix[0] = (x_time<<16); + tile->matrix[1] = 0; + tile->matrix[2] = 0; + tile->matrix[3] = -(y_time<<16); + break; + default : + tile->matrix[0] = (uint64_t)1<<32; + tile->matrix[1] = 0; + tile->matrix[2] = 0; + tile->matrix[3] = (uint64_t)1<<32; + break; + } +} + + +int32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1) +{ + + struct rga_req *mp; + uint32_t w_ratio, h_ratio; + uint32_t stride; + + uint32_t daw, dah; + uint32_t pl; + + daw = dah = 0; + + mp = msg1; + + if(msg->dst.act_w == 0) + { + printk("%s, [%d] rga dst act_w is zero\n", __FUNCTION__, __LINE__); + return -EINVAL; + } + + if (msg->dst.act_h == 0) + { + printk("%s, [%d] rga dst act_w is zero\n", __FUNCTION__, __LINE__); + return -EINVAL; + } + w_ratio = (msg->src.act_w << 16) / msg->dst.act_w; + h_ratio = (msg->src.act_h << 16) / msg->dst.act_h; + + memcpy(msg1, msg, sizeof(struct rga_req)); + + msg->dst.format = msg->src.format; + + /*pre_scale_w cal*/ + if ((w_ratio >= (2<<16)) && (w_ratio < (4<<16))) { + daw = (msg->src.act_w + 1) >> 1; + if((IS_YUV_420(msg->dst.format)) && (daw & 1)) { + daw -= 1; + msg->src.act_w = daw << 1; + } + } + else if ((w_ratio >= (4<<16)) && (w_ratio < (8<<16))) { + daw = (msg->src.act_w + 3) >> 2; + if((IS_YUV_420(msg->dst.format)) && (daw & 1)) { + daw -= 1; + msg->src.act_w = daw << 2; + } + } + else if ((w_ratio >= (8<<16)) && (w_ratio < (16<<16))) { + daw = (msg->src.act_w + 7) >> 3; + if((IS_YUV_420(msg->dst.format)) && (daw & 1)) { + daw -= 1; + msg->src.act_w = daw << 3; + } + } + else + { + daw = msg->src.act_w; + } + + pl = (RGA_pixel_width_init(msg->src.format)); + stride = (pl * daw + 3) & (~3); + msg->dst.act_w = daw; + msg->dst.vir_w = stride / pl; + + /*pre_scale_h cal*/ + if ((h_ratio >= (2<<16)) && (h_ratio < (4<<16))) { + dah = (msg->src.act_h + 1) >> 1; + if((IS_YUV(msg->dst.format)) && (dah & 1)) { + dah -= 1; + msg->src.act_h = dah << 1; + } + } + else if ((h_ratio >= (4<<16)) && (h_ratio < (8<<16))) { + dah = (msg->src.act_h + 3) >> 2; + if((IS_YUV(msg->dst.format)) && (dah & 1)) { + dah -= 1; + msg->src.act_h = dah << 2; + + } + } + else if ((h_ratio >= (8<<16)) && (h_ratio < (16<<16))) { + dah = (msg->src.act_h + 7) >> 3; + if((IS_YUV(msg->dst.format)) && (dah & 1)) { + dah -= 1; + msg->src.act_h = dah << 3; + } + } + else + { + dah = msg->src.act_h; + } + + msg->dst.act_h = dah; + msg->dst.vir_h = dah; + + msg->dst.x_offset = 0; + msg->dst.y_offset = 0; + + msg->dst.yrgb_addr = (unsigned long)rga_service.pre_scale_buf; + msg->dst.uv_addr = msg->dst.yrgb_addr + stride * dah; + msg->dst.v_addr = msg->dst.uv_addr + ((stride * dah) >> 1); + + msg->render_mode = pre_scaling_mode; + + msg1->src.yrgb_addr = msg->dst.yrgb_addr; + msg1->src.uv_addr = msg->dst.uv_addr; + msg1->src.v_addr = msg->dst.v_addr; + + msg1->src.act_w = msg->dst.act_w; + msg1->src.act_h = msg->dst.act_h; + msg1->src.vir_w = msg->dst.vir_w; + msg1->src.vir_h = msg->dst.vir_h; + + msg1->src.x_offset = 0; + msg1->src.y_offset = 0; + + return 0; +} + + diff --git a/drivers/video/rockchip/rga/RGA_API.h b/drivers/video/rockchip/rga/RGA_API.h index ade17d03e85c..96ca5240ad83 100644 --- a/drivers/video/rockchip/rga/RGA_API.h +++ b/drivers/video/rockchip/rga/RGA_API.h @@ -1,14 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __RGA_API_H__ -#define __RGA_API_H__ +#ifndef __RGA_API_H__ +#define __RGA_API_H__ #include #include - -#include "rga_reg_info.h" -#include "rga.h" - -#define ENABLE 1 + +#include "rga_reg_info.h" +#include "rga.h" + +#define ENABLE 1 #define DISABLE 0 struct rga_drvdata { @@ -31,10 +31,10 @@ struct rga_drvdata { char *version; }; -int32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1); - - - - - -#endif +int32_t RGA_gen_two_pro(struct rga_req *msg, struct rga_req *msg1); + + + + + +#endif diff --git a/drivers/video/rockchip/rga/rga.h b/drivers/video/rockchip/rga/rga.h index e54a6efba39f..9e39dc2aa2d1 100644 --- a/drivers/video/rockchip/rga/rga.h +++ b/drivers/video/rockchip/rga/rga.h @@ -1,508 +1,508 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _RGA_DRIVER_H_ -#define _RGA_DRIVER_H_ - -#include -#include - - -#define RGA_BLIT_SYNC 0x5017 -#define RGA_BLIT_ASYNC 0x5018 -#define RGA_FLUSH 0x5019 -#define RGA_GET_RESULT 0x501a -#define RGA_GET_VERSION 0x501b - - -#define RGA_REG_CTRL_LEN 0x8 /* 8 */ -#define RGA_REG_CMD_LEN 0x20 /* 32 */ -#define RGA_CMD_BUF_SIZE 0x700 /* 16*28*4 */ - -#define RGA_OUT_OF_RESOURCES -10 -#define RGA_MALLOC_ERROR -11 - +#ifndef _RGA_DRIVER_H_ +#define _RGA_DRIVER_H_ + +#include +#include + + +#define RGA_BLIT_SYNC 0x5017 +#define RGA_BLIT_ASYNC 0x5018 +#define RGA_FLUSH 0x5019 +#define RGA_GET_RESULT 0x501a +#define RGA_GET_VERSION 0x501b + + +#define RGA_REG_CTRL_LEN 0x8 /* 8 */ +#define RGA_REG_CMD_LEN 0x20 /* 32 */ +#define RGA_CMD_BUF_SIZE 0x700 /* 16*28*4 */ + +#define RGA_OUT_OF_RESOURCES -10 +#define RGA_MALLOC_ERROR -11 + #define RGA_BUF_GEM_TYPE_MASK 0xC0 - -#define rgaIS_ERROR(status) (status < 0) -#define rgaNO_ERROR(status) (status >= 0) -#define rgaIS_SUCCESS(status) (status == 0) - + +#define rgaIS_ERROR(status) (status < 0) +#define rgaNO_ERROR(status) (status >= 0) +#define rgaIS_SUCCESS(status) (status == 0) + #define RGA_DEBUGFS 1 - -/* RGA process mode enum */ -enum -{ - bitblt_mode = 0x0, - color_palette_mode = 0x1, - color_fill_mode = 0x2, - line_point_drawing_mode = 0x3, - blur_sharp_filter_mode = 0x4, - pre_scaling_mode = 0x5, - update_palette_table_mode = 0x6, - update_patten_buff_mode = 0x7, -}; - - -enum -{ - rop_enable_mask = 0x2, - dither_enable_mask = 0x8, - fading_enable_mask = 0x10, - PD_enbale_mask = 0x20, -}; - -enum -{ - yuv2rgb_mode0 = 0x0, /* BT.601 MPEG */ - yuv2rgb_mode1 = 0x1, /* BT.601 JPEG */ - yuv2rgb_mode2 = 0x2, /* BT.709 */ -}; - - -/* RGA rotate mode */ -enum -{ - rotate_mode0 = 0x0, /* no rotate */ - rotate_mode1 = 0x1, /* rotate */ - rotate_mode2 = 0x2, /* x_mirror */ - rotate_mode3 = 0x3, /* y_mirror */ -}; - -enum -{ - color_palette_mode0 = 0x0, /* 1K */ - color_palette_mode1 = 0x1, /* 2K */ - color_palette_mode2 = 0x2, /* 4K */ - color_palette_mode3 = 0x3, /* 8K */ -}; - - - -/* -// Alpha Red Green Blue -{ 4, 32, {{32,24, 8, 0, 16, 8, 24,16 }}, GGL_RGBA }, // RK_FORMAT_RGBA_8888 -{ 4, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // RK_FORMAT_RGBX_8888 -{ 3, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // RK_FORMAT_RGB_888 -{ 4, 32, {{32,24, 24,16, 16, 8, 8, 0 }}, GGL_BGRA }, // RK_FORMAT_BGRA_8888 -{ 2, 16, {{ 0, 0, 16,11, 11, 5, 5, 0 }}, GGL_RGB }, // RK_FORMAT_RGB_565 -{ 2, 16, {{ 1, 0, 16,11, 11, 6, 6, 1 }}, GGL_RGBA }, // RK_FORMAT_RGBA_5551 -{ 2, 16, {{ 4, 0, 16,12, 12, 8, 8, 4 }}, GGL_RGBA }, // RK_FORMAT_RGBA_4444 -{ 3, 24, {{ 0, 0, 24,16, 16, 8, 8, 0 }}, GGL_BGR }, // RK_FORMAT_BGB_888 - -*/ -enum -{ - RK_FORMAT_RGBA_8888 = 0x0, - RK_FORMAT_RGBX_8888 = 0x1, - RK_FORMAT_RGB_888 = 0x2, - RK_FORMAT_BGRA_8888 = 0x3, - RK_FORMAT_RGB_565 = 0x4, - RK_FORMAT_RGBA_5551 = 0x5, - RK_FORMAT_RGBA_4444 = 0x6, - RK_FORMAT_BGR_888 = 0x7, - - RK_FORMAT_YCbCr_422_SP = 0x8, - RK_FORMAT_YCbCr_422_P = 0x9, - RK_FORMAT_YCbCr_420_SP = 0xa, - RK_FORMAT_YCbCr_420_P = 0xb, - - RK_FORMAT_YCrCb_422_SP = 0xc, - RK_FORMAT_YCrCb_422_P = 0xd, - RK_FORMAT_YCrCb_420_SP = 0xe, - RK_FORMAT_YCrCb_420_P = 0xf, - - RK_FORMAT_BPP1 = 0x10, - RK_FORMAT_BPP2 = 0x11, - RK_FORMAT_BPP4 = 0x12, - RK_FORMAT_BPP8 = 0x13, - RK_FORMAT_YCbCr_420_SP_10B = 0x20, - RK_FORMAT_YCrCb_420_SP_10B = 0x21, -}; - - -typedef struct rga_img_info_t -{ - unsigned long yrgb_addr; /* yrgb mem addr */ - unsigned long uv_addr; /* cb/cr mem addr */ - unsigned long v_addr; /* cr mem addr */ - unsigned int format; //definition by RK_FORMAT - - unsigned short act_w; - unsigned short act_h; - unsigned short x_offset; - unsigned short y_offset; - - unsigned short vir_w; - unsigned short vir_h; - - unsigned short endian_mode; //for BPP - unsigned short alpha_swap; -} -rga_img_info_t; - - -typedef struct mdp_img_act -{ - unsigned short w; // width - unsigned short h; // height - short x_off; // x offset for the vir - short y_off; // y offset for the vir -} -mdp_img_act; - - - -typedef struct RANGE -{ - unsigned short min; - unsigned short max; -} -RANGE; - -typedef struct POINT -{ - unsigned short x; - unsigned short y; -} -POINT; - -typedef struct RECT -{ - unsigned short xmin; - unsigned short xmax; // width - 1 - unsigned short ymin; - unsigned short ymax; // height - 1 -} RECT; - -typedef struct RGB -{ - unsigned char r; - unsigned char g; - unsigned char b; - unsigned char res; -}RGB; - - -typedef struct MMU -{ - unsigned char mmu_en; - unsigned long base_addr; + +/* RGA process mode enum */ +enum +{ + bitblt_mode = 0x0, + color_palette_mode = 0x1, + color_fill_mode = 0x2, + line_point_drawing_mode = 0x3, + blur_sharp_filter_mode = 0x4, + pre_scaling_mode = 0x5, + update_palette_table_mode = 0x6, + update_patten_buff_mode = 0x7, +}; + + +enum +{ + rop_enable_mask = 0x2, + dither_enable_mask = 0x8, + fading_enable_mask = 0x10, + PD_enbale_mask = 0x20, +}; + +enum +{ + yuv2rgb_mode0 = 0x0, /* BT.601 MPEG */ + yuv2rgb_mode1 = 0x1, /* BT.601 JPEG */ + yuv2rgb_mode2 = 0x2, /* BT.709 */ +}; + + +/* RGA rotate mode */ +enum +{ + rotate_mode0 = 0x0, /* no rotate */ + rotate_mode1 = 0x1, /* rotate */ + rotate_mode2 = 0x2, /* x_mirror */ + rotate_mode3 = 0x3, /* y_mirror */ +}; + +enum +{ + color_palette_mode0 = 0x0, /* 1K */ + color_palette_mode1 = 0x1, /* 2K */ + color_palette_mode2 = 0x2, /* 4K */ + color_palette_mode3 = 0x3, /* 8K */ +}; + + + +/* +// Alpha Red Green Blue +{ 4, 32, {{32,24, 8, 0, 16, 8, 24,16 }}, GGL_RGBA }, // RK_FORMAT_RGBA_8888 +{ 4, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // RK_FORMAT_RGBX_8888 +{ 3, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // RK_FORMAT_RGB_888 +{ 4, 32, {{32,24, 24,16, 16, 8, 8, 0 }}, GGL_BGRA }, // RK_FORMAT_BGRA_8888 +{ 2, 16, {{ 0, 0, 16,11, 11, 5, 5, 0 }}, GGL_RGB }, // RK_FORMAT_RGB_565 +{ 2, 16, {{ 1, 0, 16,11, 11, 6, 6, 1 }}, GGL_RGBA }, // RK_FORMAT_RGBA_5551 +{ 2, 16, {{ 4, 0, 16,12, 12, 8, 8, 4 }}, GGL_RGBA }, // RK_FORMAT_RGBA_4444 +{ 3, 24, {{ 0, 0, 24,16, 16, 8, 8, 0 }}, GGL_BGR }, // RK_FORMAT_BGB_888 + +*/ +enum +{ + RK_FORMAT_RGBA_8888 = 0x0, + RK_FORMAT_RGBX_8888 = 0x1, + RK_FORMAT_RGB_888 = 0x2, + RK_FORMAT_BGRA_8888 = 0x3, + RK_FORMAT_RGB_565 = 0x4, + RK_FORMAT_RGBA_5551 = 0x5, + RK_FORMAT_RGBA_4444 = 0x6, + RK_FORMAT_BGR_888 = 0x7, + + RK_FORMAT_YCbCr_422_SP = 0x8, + RK_FORMAT_YCbCr_422_P = 0x9, + RK_FORMAT_YCbCr_420_SP = 0xa, + RK_FORMAT_YCbCr_420_P = 0xb, + + RK_FORMAT_YCrCb_422_SP = 0xc, + RK_FORMAT_YCrCb_422_P = 0xd, + RK_FORMAT_YCrCb_420_SP = 0xe, + RK_FORMAT_YCrCb_420_P = 0xf, + + RK_FORMAT_BPP1 = 0x10, + RK_FORMAT_BPP2 = 0x11, + RK_FORMAT_BPP4 = 0x12, + RK_FORMAT_BPP8 = 0x13, + RK_FORMAT_YCbCr_420_SP_10B = 0x20, + RK_FORMAT_YCrCb_420_SP_10B = 0x21, +}; + + +typedef struct rga_img_info_t +{ + unsigned long yrgb_addr; /* yrgb mem addr */ + unsigned long uv_addr; /* cb/cr mem addr */ + unsigned long v_addr; /* cr mem addr */ + unsigned int format; //definition by RK_FORMAT + + unsigned short act_w; + unsigned short act_h; + unsigned short x_offset; + unsigned short y_offset; + + unsigned short vir_w; + unsigned short vir_h; + + unsigned short endian_mode; //for BPP + unsigned short alpha_swap; +} +rga_img_info_t; + + +typedef struct mdp_img_act +{ + unsigned short w; // width + unsigned short h; // height + short x_off; // x offset for the vir + short y_off; // y offset for the vir +} +mdp_img_act; + + + +typedef struct RANGE +{ + unsigned short min; + unsigned short max; +} +RANGE; + +typedef struct POINT +{ + unsigned short x; + unsigned short y; +} +POINT; + +typedef struct RECT +{ + unsigned short xmin; + unsigned short xmax; // width - 1 + unsigned short ymin; + unsigned short ymax; // height - 1 +} RECT; + +typedef struct RGB +{ + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char res; +}RGB; + + +typedef struct MMU +{ + unsigned char mmu_en; + unsigned long base_addr; uint32_t mmu_flag; -} MMU; - - - - -typedef struct COLOR_FILL -{ - short gr_x_a; - short gr_y_a; - short gr_x_b; - short gr_y_b; - short gr_x_g; - short gr_y_g; - short gr_x_r; - short gr_y_r; - - //u8 cp_gr_saturation; -} -COLOR_FILL; - -typedef struct FADING -{ - uint8_t b; - uint8_t g; - uint8_t r; - uint8_t res; -} -FADING; - - -typedef struct line_draw_t -{ - POINT start_point; /* LineDraw_start_point */ - POINT end_point; /* LineDraw_end_point */ - uint32_t color; /* LineDraw_color */ - uint32_t flag; /* (enum) LineDrawing mode sel */ - uint32_t line_width; /* range 1~16 */ -} -line_draw_t; - - - -struct rga_req { - uint8_t render_mode; /* (enum) process mode sel */ - - rga_img_info_t src; /* src image info */ - rga_img_info_t dst; /* dst image info */ - rga_img_info_t pat; /* patten image info */ - - unsigned long rop_mask_addr; /* rop4 mask addr */ - unsigned long LUT_addr; /* LUT addr */ - - RECT clip; /* dst clip window default value is dst_vir */ - /* value from [0, w-1] / [0, h-1]*/ - - int32_t sina; /* dst angle default value 0 16.16 scan from table */ - int32_t cosa; /* dst angle default value 0 16.16 scan from table */ - - uint16_t alpha_rop_flag; /* alpha rop process flag */ - /* ([0] = 1 alpha_rop_enable) */ - /* ([1] = 1 rop enable) */ - /* ([2] = 1 fading_enable) */ - /* ([3] = 1 PD_enable) */ - /* ([4] = 1 alpha cal_mode_sel) */ - /* ([5] = 1 dither_enable) */ - /* ([6] = 1 gradient fill mode sel) */ - /* ([7] = 1 AA_enable) */ - - uint8_t scale_mode; /* 0 nearst / 1 bilnear / 2 bicubic */ - - uint32_t color_key_max; /* color key max */ - uint32_t color_key_min; /* color key min */ - - uint32_t fg_color; /* foreground color */ - uint32_t bg_color; /* background color */ - - COLOR_FILL gr_color; /* color fill use gradient */ - - line_draw_t line_draw_info; - - FADING fading; - - uint8_t PD_mode; /* porter duff alpha mode sel */ - - uint8_t alpha_global_value; /* global alpha value */ - - uint16_t rop_code; /* rop2/3/4 code scan from rop code table*/ - - uint8_t bsfilter_flag; /* [2] 0 blur 1 sharp / [1:0] filter_type*/ - - uint8_t palette_mode; /* (enum) color palatte 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/ - - uint8_t yuv2rgb_mode; /* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */ - - uint8_t endian_mode; /* 0/big endian 1/little endian*/ - - uint8_t rotate_mode; /* (enum) rotate mode */ - /* 0x0, no rotate */ - /* 0x1, rotate */ - /* 0x2, x_mirror */ - /* 0x3, y_mirror */ - - uint8_t color_fill_mode; /* 0 solid color / 1 patten color */ - - MMU mmu_info; /* mmu information */ - - uint8_t alpha_rop_mode; /* ([0~1] alpha mode) */ - /* ([2~3] rop mode) */ - /* ([4] zero mode en) */ - /* ([5] dst alpha mode) */ - - uint8_t src_trans_mode; - - struct sg_table *sg_src; +} MMU; + + + + +typedef struct COLOR_FILL +{ + short gr_x_a; + short gr_y_a; + short gr_x_b; + short gr_y_b; + short gr_x_g; + short gr_y_g; + short gr_x_r; + short gr_y_r; + + //u8 cp_gr_saturation; +} +COLOR_FILL; + +typedef struct FADING +{ + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t res; +} +FADING; + + +typedef struct line_draw_t +{ + POINT start_point; /* LineDraw_start_point */ + POINT end_point; /* LineDraw_end_point */ + uint32_t color; /* LineDraw_color */ + uint32_t flag; /* (enum) LineDrawing mode sel */ + uint32_t line_width; /* range 1~16 */ +} +line_draw_t; + + + +struct rga_req { + uint8_t render_mode; /* (enum) process mode sel */ + + rga_img_info_t src; /* src image info */ + rga_img_info_t dst; /* dst image info */ + rga_img_info_t pat; /* patten image info */ + + unsigned long rop_mask_addr; /* rop4 mask addr */ + unsigned long LUT_addr; /* LUT addr */ + + RECT clip; /* dst clip window default value is dst_vir */ + /* value from [0, w-1] / [0, h-1]*/ + + int32_t sina; /* dst angle default value 0 16.16 scan from table */ + int32_t cosa; /* dst angle default value 0 16.16 scan from table */ + + uint16_t alpha_rop_flag; /* alpha rop process flag */ + /* ([0] = 1 alpha_rop_enable) */ + /* ([1] = 1 rop enable) */ + /* ([2] = 1 fading_enable) */ + /* ([3] = 1 PD_enable) */ + /* ([4] = 1 alpha cal_mode_sel) */ + /* ([5] = 1 dither_enable) */ + /* ([6] = 1 gradient fill mode sel) */ + /* ([7] = 1 AA_enable) */ + + uint8_t scale_mode; /* 0 nearst / 1 bilnear / 2 bicubic */ + + uint32_t color_key_max; /* color key max */ + uint32_t color_key_min; /* color key min */ + + uint32_t fg_color; /* foreground color */ + uint32_t bg_color; /* background color */ + + COLOR_FILL gr_color; /* color fill use gradient */ + + line_draw_t line_draw_info; + + FADING fading; + + uint8_t PD_mode; /* porter duff alpha mode sel */ + + uint8_t alpha_global_value; /* global alpha value */ + + uint16_t rop_code; /* rop2/3/4 code scan from rop code table*/ + + uint8_t bsfilter_flag; /* [2] 0 blur 1 sharp / [1:0] filter_type*/ + + uint8_t palette_mode; /* (enum) color palatte 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/ + + uint8_t yuv2rgb_mode; /* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */ + + uint8_t endian_mode; /* 0/big endian 1/little endian*/ + + uint8_t rotate_mode; /* (enum) rotate mode */ + /* 0x0, no rotate */ + /* 0x1, rotate */ + /* 0x2, x_mirror */ + /* 0x3, y_mirror */ + + uint8_t color_fill_mode; /* 0 solid color / 1 patten color */ + + MMU mmu_info; /* mmu information */ + + uint8_t alpha_rop_mode; /* ([0~1] alpha mode) */ + /* ([2~3] rop mode) */ + /* ([4] zero mode en) */ + /* ([5] dst alpha mode) */ + + uint8_t src_trans_mode; + + struct sg_table *sg_src; struct sg_table *sg_dst; struct dma_buf_attachment *attach_src; struct dma_buf_attachment *attach_dst; -}; - - -typedef struct TILE_INFO -{ - int64_t matrix[4]; - - uint16_t tile_x_num; /* x axis tile num / tile size is 8x8 pixel */ - uint16_t tile_y_num; /* y axis tile num */ - - int16_t dst_x_tmp; /* dst pos x = (xstart - xoff) default value 0 */ - int16_t dst_y_tmp; /* dst pos y = (ystart - yoff) default value 0 */ - - uint16_t tile_w; - uint16_t tile_h; - int16_t tile_start_x_coor; - int16_t tile_start_y_coor; - int32_t tile_xoff; - int32_t tile_yoff; - - int32_t tile_temp_xstart; - int32_t tile_temp_ystart; - - /* src tile incr */ - int32_t x_dx; - int32_t x_dy; - int32_t y_dx; - int32_t y_dy; - - mdp_img_act dst_ctrl; - -} -TILE_INFO; - -struct rga_mmu_buf_t { - int32_t front; - int32_t back; - int32_t size; - int32_t curr; - unsigned int *buf; - unsigned int *buf_virtual; - - struct page **pages; -}; - -/** - * struct for process session which connect to rga - * - * @author ZhangShengqin (2012-2-15) - */ -typedef struct rga_session { - /* a linked list of data so we can access them for debugging */ - struct list_head list_session; - /* a linked list of register data waiting for process */ - struct list_head waiting; - /* a linked list of register data in processing */ - struct list_head running; - /* all coommand this thread done */ - atomic_t done; - wait_queue_head_t wait; - pid_t pid; - atomic_t task_running; - atomic_t num_done; -} rga_session; - -struct rga_reg { - rga_session *session; - struct list_head session_link; /* link to rga service session */ - struct list_head status_link; /* link to register set list */ - uint32_t sys_reg[RGA_REG_CTRL_LEN]; - uint32_t cmd_reg[RGA_REG_CMD_LEN]; - - uint32_t *MMU_base; - uint32_t MMU_len; - //atomic_t int_enable; - - //struct rga_req req; +}; + + +typedef struct TILE_INFO +{ + int64_t matrix[4]; + + uint16_t tile_x_num; /* x axis tile num / tile size is 8x8 pixel */ + uint16_t tile_y_num; /* y axis tile num */ + + int16_t dst_x_tmp; /* dst pos x = (xstart - xoff) default value 0 */ + int16_t dst_y_tmp; /* dst pos y = (ystart - yoff) default value 0 */ + + uint16_t tile_w; + uint16_t tile_h; + int16_t tile_start_x_coor; + int16_t tile_start_y_coor; + int32_t tile_xoff; + int32_t tile_yoff; + + int32_t tile_temp_xstart; + int32_t tile_temp_ystart; + + /* src tile incr */ + int32_t x_dx; + int32_t x_dy; + int32_t y_dx; + int32_t y_dy; + + mdp_img_act dst_ctrl; + +} +TILE_INFO; + +struct rga_mmu_buf_t { + int32_t front; + int32_t back; + int32_t size; + int32_t curr; + unsigned int *buf; + unsigned int *buf_virtual; + + struct page **pages; +}; + +/** + * struct for process session which connect to rga + * + * @author ZhangShengqin (2012-2-15) + */ +typedef struct rga_session { + /* a linked list of data so we can access them for debugging */ + struct list_head list_session; + /* a linked list of register data waiting for process */ + struct list_head waiting; + /* a linked list of register data in processing */ + struct list_head running; + /* all coommand this thread done */ + atomic_t done; + wait_queue_head_t wait; + pid_t pid; + atomic_t task_running; + atomic_t num_done; +} rga_session; + +struct rga_reg { + rga_session *session; + struct list_head session_link; /* link to rga service session */ + struct list_head status_link; /* link to register set list */ + uint32_t sys_reg[RGA_REG_CTRL_LEN]; + uint32_t cmd_reg[RGA_REG_CMD_LEN]; + + uint32_t *MMU_base; + uint32_t MMU_len; + //atomic_t int_enable; + + //struct rga_req req; struct sg_table *sg_src; struct sg_table *sg_dst; struct dma_buf_attachment *attach_src; struct dma_buf_attachment *attach_dst; -}; - - - -typedef struct rga_service_info { - struct mutex lock; - struct timer_list timer; /* timer for power off */ - struct list_head waiting; /* link to link_reg in struct vpu_reg */ - struct list_head running; /* link to link_reg in struct vpu_reg */ - struct list_head done; /* link to link_reg in struct vpu_reg */ - struct list_head session; /* link to list_session in struct vpu_session */ - atomic_t total_running; - - struct rga_reg *reg; - - uint32_t cmd_buff[28*8];/* cmd_buff for rga */ - uint32_t *pre_scale_buf; - unsigned long *pre_scale_buf_virtual; +}; + + + +typedef struct rga_service_info { + struct mutex lock; + struct timer_list timer; /* timer for power off */ + struct list_head waiting; /* link to link_reg in struct vpu_reg */ + struct list_head running; /* link to link_reg in struct vpu_reg */ + struct list_head done; /* link to link_reg in struct vpu_reg */ + struct list_head session; /* link to list_session in struct vpu_session */ + atomic_t total_running; + + struct rga_reg *reg; + + uint32_t cmd_buff[28*8];/* cmd_buff for rga */ + uint32_t *pre_scale_buf; + unsigned long *pre_scale_buf_virtual; atomic_t int_disable; /* 0 int enable 1 int disable */ - atomic_t cmd_num; + atomic_t cmd_num; atomic_t src_format_swt; int last_prc_src_format; atomic_t rga_working; - bool enable; + bool enable; u32 dev_mode; - - //struct rga_req req[10]; - - struct mutex mutex; // mutex -} rga_service_info; - - - -#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) || defined(CONFIG_ARCH_RK312x) -#define RGA_BASE 0x1010c000 -#elif defined(CONFIG_ARCH_RK30) -#define RGA_BASE 0x10114000 -#endif - -//General Registers -#define RGA_SYS_CTRL 0x000 -#define RGA_CMD_CTRL 0x004 -#define RGA_CMD_ADDR 0x008 -#define RGA_STATUS 0x00c -#define RGA_INT 0x010 -#define RGA_AXI_ID 0x014 -#define RGA_MMU_STA_CTRL 0x018 -#define RGA_MMU_STA 0x01c + + //struct rga_req req[10]; + + struct mutex mutex; // mutex +} rga_service_info; + + + +#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) || defined(CONFIG_ARCH_RK312x) +#define RGA_BASE 0x1010c000 +#elif defined(CONFIG_ARCH_RK30) +#define RGA_BASE 0x10114000 +#endif + +//General Registers +#define RGA_SYS_CTRL 0x000 +#define RGA_CMD_CTRL 0x004 +#define RGA_CMD_ADDR 0x008 +#define RGA_STATUS 0x00c +#define RGA_INT 0x010 +#define RGA_AXI_ID 0x014 +#define RGA_MMU_STA_CTRL 0x018 +#define RGA_MMU_STA 0x01c #define RGA_VERSION 0x028 - -//Command code start -#define RGA_MODE_CTRL 0x100 - -//Source Image Registers -#define RGA_SRC_Y_MST 0x104 -#define RGA_SRC_CB_MST 0x108 -#define RGA_MASK_READ_MST 0x108 //repeat -#define RGA_SRC_CR_MST 0x10c -#define RGA_SRC_VIR_INFO 0x110 -#define RGA_SRC_ACT_INFO 0x114 -#define RGA_SRC_X_PARA 0x118 -#define RGA_SRC_Y_PARA 0x11c -#define RGA_SRC_TILE_XINFO 0x120 -#define RGA_SRC_TILE_YINFO 0x124 -#define RGA_SRC_TILE_H_INCR 0x128 -#define RGA_SRC_TILE_V_INCR 0x12c -#define RGA_SRC_TILE_OFFSETX 0x130 -#define RGA_SRC_TILE_OFFSETY 0x134 -#define RGA_SRC_BG_COLOR 0x138 -#define RGA_SRC_FG_COLOR 0x13c -#define RGA_LINE_DRAWING_COLOR 0x13c //repeat -#define RGA_SRC_TR_COLOR0 0x140 -#define RGA_CP_GR_A 0x140 //repeat -#define RGA_SRC_TR_COLOR1 0x144 -#define RGA_CP_GR_B 0x144 //repeat - -#define RGA_LINE_DRAW 0x148 -#define RGA_PAT_START_POINT 0x148 //repeat - -//Destination Image Registers -#define RGA_DST_MST 0x14c -#define RGA_LUT_MST 0x14c //repeat -#define RGA_PAT_MST 0x14c //repeat -#define RGA_LINE_DRAWING_MST 0x14c //repeat - -#define RGA_DST_VIR_INFO 0x150 - -#define RGA_DST_CTR_INFO 0x154 -#define RGA_LINE_DRAW_XY_INFO 0x154 //repeat - -//Alpha/ROP Registers -#define RGA_ALPHA_CON 0x158 - -#define RGA_PAT_CON 0x15c -#define RGA_DST_VIR_WIDTH_PIX 0x15c //repeat - -#define RGA_ROP_CON0 0x160 -#define RGA_CP_GR_G 0x160 //repeat -#define RGA_PRESCL_CB_MST 0x160 //repeat - -#define RGA_ROP_CON1 0x164 -#define RGA_CP_GR_R 0x164 //repeat -#define RGA_PRESCL_CR_MST 0x164 //repeat - -//MMU Register -#define RGA_FADING_CON 0x168 -#define RGA_MMU_CTRL 0x168 //repeat - -#define RGA_MMU_TBL 0x16c //repeat - -#define RGA_YUV_OUT_CFG 0x170 -#define RGA_DST_UV_MST 0x174 - - -#define RGA_BLIT_COMPLETE_EVENT 1 - -long rga_ioctl_kernel(struct rga_req *req); - -#endif /*_RK29_IPP_DRIVER_H_*/ + +//Command code start +#define RGA_MODE_CTRL 0x100 + +//Source Image Registers +#define RGA_SRC_Y_MST 0x104 +#define RGA_SRC_CB_MST 0x108 +#define RGA_MASK_READ_MST 0x108 //repeat +#define RGA_SRC_CR_MST 0x10c +#define RGA_SRC_VIR_INFO 0x110 +#define RGA_SRC_ACT_INFO 0x114 +#define RGA_SRC_X_PARA 0x118 +#define RGA_SRC_Y_PARA 0x11c +#define RGA_SRC_TILE_XINFO 0x120 +#define RGA_SRC_TILE_YINFO 0x124 +#define RGA_SRC_TILE_H_INCR 0x128 +#define RGA_SRC_TILE_V_INCR 0x12c +#define RGA_SRC_TILE_OFFSETX 0x130 +#define RGA_SRC_TILE_OFFSETY 0x134 +#define RGA_SRC_BG_COLOR 0x138 +#define RGA_SRC_FG_COLOR 0x13c +#define RGA_LINE_DRAWING_COLOR 0x13c //repeat +#define RGA_SRC_TR_COLOR0 0x140 +#define RGA_CP_GR_A 0x140 //repeat +#define RGA_SRC_TR_COLOR1 0x144 +#define RGA_CP_GR_B 0x144 //repeat + +#define RGA_LINE_DRAW 0x148 +#define RGA_PAT_START_POINT 0x148 //repeat + +//Destination Image Registers +#define RGA_DST_MST 0x14c +#define RGA_LUT_MST 0x14c //repeat +#define RGA_PAT_MST 0x14c //repeat +#define RGA_LINE_DRAWING_MST 0x14c //repeat + +#define RGA_DST_VIR_INFO 0x150 + +#define RGA_DST_CTR_INFO 0x154 +#define RGA_LINE_DRAW_XY_INFO 0x154 //repeat + +//Alpha/ROP Registers +#define RGA_ALPHA_CON 0x158 + +#define RGA_PAT_CON 0x15c +#define RGA_DST_VIR_WIDTH_PIX 0x15c //repeat + +#define RGA_ROP_CON0 0x160 +#define RGA_CP_GR_G 0x160 //repeat +#define RGA_PRESCL_CB_MST 0x160 //repeat + +#define RGA_ROP_CON1 0x164 +#define RGA_CP_GR_R 0x164 //repeat +#define RGA_PRESCL_CR_MST 0x164 //repeat + +//MMU Register +#define RGA_FADING_CON 0x168 +#define RGA_MMU_CTRL 0x168 //repeat + +#define RGA_MMU_TBL 0x16c //repeat + +#define RGA_YUV_OUT_CFG 0x170 +#define RGA_DST_UV_MST 0x174 + + +#define RGA_BLIT_COMPLETE_EVENT 1 + +long rga_ioctl_kernel(struct rga_req *req); + +#endif /*_RK29_IPP_DRIVER_H_*/ diff --git a/drivers/video/rockchip/rga/rga_drv.c b/drivers/video/rockchip/rga/rga_drv.c index a5d43f90f21b..c5583736e54a 100644 --- a/drivers/video/rockchip/rga/rga_drv.c +++ b/drivers/video/rockchip/rga/rga_drv.c @@ -1,47 +1,47 @@ -/* - * Copyright (C) 2012 ROCKCHIP, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * - */ - -#define pr_fmt(fmt) "rga: " fmt -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +/* + * Copyright (C) 2012 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#define pr_fmt(fmt) "rga: " fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) @@ -53,41 +53,41 @@ #include #endif -#include "rga.h" -#include "rga_reg_info.h" -#include "rga_mmu_info.h" -#include "RGA_API.h" - -#define RGA_TEST_CASE 0 - -#define RGA_TEST_FLUSH_TIME 0 -#define RGA_INFO_BUS_ERROR 1 - -#define PRE_SCALE_BUF_SIZE 2048*1024*4 - -#define RGA_POWER_OFF_DELAY 4*HZ /* 4s */ -#define RGA_TIMEOUT_DELAY 2*HZ /* 2s */ - -#define RGA_MAJOR 255 - -#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) -#define RK30_RGA_PHYS RK2928_RGA_PHYS -#define RK30_RGA_SIZE RK2928_RGA_SIZE -#endif -#define RGA_RESET_TIMEOUT 1000 - -/* Driver information */ -#define DRIVER_DESC "RGA Device Driver" -#define DRIVER_NAME "rga" - - -ktime_t rga_start; -ktime_t rga_end; - -rga_session rga_session_global; - -long (*rga_ioctl_kernel_p)(struct rga_req *); - +#include "rga.h" +#include "rga_reg_info.h" +#include "rga_mmu_info.h" +#include "RGA_API.h" + +#define RGA_TEST_CASE 0 + +#define RGA_TEST_FLUSH_TIME 0 +#define RGA_INFO_BUS_ERROR 1 + +#define PRE_SCALE_BUF_SIZE 2048*1024*4 + +#define RGA_POWER_OFF_DELAY 4*HZ /* 4s */ +#define RGA_TIMEOUT_DELAY 2*HZ /* 2s */ + +#define RGA_MAJOR 255 + +#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) +#define RK30_RGA_PHYS RK2928_RGA_PHYS +#define RK30_RGA_SIZE RK2928_RGA_SIZE +#endif +#define RGA_RESET_TIMEOUT 1000 + +/* Driver information */ +#define DRIVER_DESC "RGA Device Driver" +#define DRIVER_NAME "rga" + + +ktime_t rga_start; +ktime_t rga_end; + +rga_session rga_session_global; + +long (*rga_ioctl_kernel_p)(struct rga_req *); + #if RGA_DEBUGFS unsigned char RGA_TEST_REG; unsigned char RGA_TEST_MSG; @@ -96,36 +96,36 @@ unsigned char RGA_CHECK_MODE; unsigned char RGA_NONUSE; unsigned char RGA_INT_FLAG; #endif - + struct rga_drvdata *drvdata; -rga_service_info rga_service; -struct rga_mmu_buf_t rga_mmu_buf; - - -#if defined(CONFIG_ION_ROCKCHIP) -extern struct ion_client *rockchip_ion_client_create(const char * name); -#endif - -static int rga_blit_async(rga_session *session, struct rga_req *req); -static void rga_del_running_list(void); -static void rga_del_running_list_timeout(void); -static void rga_try_set_reg(void); - - -/* Logging */ -#define RGA_DEBUG 1 -#if RGA_DEBUG -#define DBG(format, args...) printk(KERN_DEBUG "%s: " format, DRIVER_NAME, ## args) -#define ERR(format, args...) printk(KERN_ERR "%s: " format, DRIVER_NAME, ## args) -#define WARNING(format, args...) printk(KERN_WARN "%s: " format, DRIVER_NAME, ## args) -#define INFO(format, args...) printk(KERN_INFO "%s: " format, DRIVER_NAME, ## args) -#else -#define DBG(format, args...) -#define ERR(format, args...) -#define WARNING(format, args...) -#define INFO(format, args...) -#endif - +rga_service_info rga_service; +struct rga_mmu_buf_t rga_mmu_buf; + + +#if defined(CONFIG_ION_ROCKCHIP) +extern struct ion_client *rockchip_ion_client_create(const char * name); +#endif + +static int rga_blit_async(rga_session *session, struct rga_req *req); +static void rga_del_running_list(void); +static void rga_del_running_list_timeout(void); +static void rga_try_set_reg(void); + + +/* Logging */ +#define RGA_DEBUG 1 +#if RGA_DEBUG +#define DBG(format, args...) printk(KERN_DEBUG "%s: " format, DRIVER_NAME, ## args) +#define ERR(format, args...) printk(KERN_ERR "%s: " format, DRIVER_NAME, ## args) +#define WARNING(format, args...) printk(KERN_WARN "%s: " format, DRIVER_NAME, ## args) +#define INFO(format, args...) printk(KERN_INFO "%s: " format, DRIVER_NAME, ## args) +#else +#define DBG(format, args...) +#define ERR(format, args...) +#define WARNING(format, args...) +#define INFO(format, args...) +#endif + #if RGA_DEBUGFS static const char *rga_get_cmd_mode_str(u32 cmd) { @@ -408,127 +408,127 @@ static int rga_memory_check(void *vaddr, u32 w, u32 h, u32 format, int fd) } #endif -static inline void rga_write(u32 b, u32 r) -{ - __raw_writel(b, drvdata->rga_base + r); -} - -static inline u32 rga_read(u32 r) -{ - return __raw_readl(drvdata->rga_base + r); -} - -static void rga_soft_reset(void) -{ - u32 i; - u32 reg; - - rga_write(1, RGA_SYS_CTRL); //RGA_SYS_CTRL - - for(i = 0; i < RGA_RESET_TIMEOUT; i++) - { - reg = rga_read(RGA_SYS_CTRL) & 1; //RGA_SYS_CTRL - - if(reg == 0) - break; - - udelay(1); - } - - if(i == RGA_RESET_TIMEOUT) - ERR("soft reset timeout.\n"); -} - -static void rga_dump(void) -{ - int running; - struct rga_reg *reg, *reg_tmp; - rga_session *session, *session_tmp; - - running = atomic_read(&rga_service.total_running); - printk("rga total_running %d\n", running); - - #if 0 - - /* Dump waiting list info */ - if (!list_empty(&rga_service.waiting)) - { - list_head *next; - - next = &rga_service.waiting; - - printk("rga_service dump waiting list\n"); - - do - { - reg = list_entry(next->next, struct rga_reg, status_link); - running = atomic_read(®->session->task_running); - num_done = atomic_read(®->session->num_done); - printk("rga session pid %d, done %d, running %d\n", reg->session->pid, num_done, running); - next = next->next; - } - while(!list_empty(next)); - } - - /* Dump running list info */ - if (!list_empty(&rga_service.running)) - { - printk("rga_service dump running list\n"); - - list_head *next; - - next = &rga_service.running; - do - { - reg = list_entry(next->next, struct rga_reg, status_link); - running = atomic_read(®->session->task_running); - num_done = atomic_read(®->session->num_done); - printk("rga session pid %d, done %d, running %d:\n", reg->session->pid, num_done, running); - next = next->next; - } - while(!list_empty(next)); - } - #endif - - list_for_each_entry_safe(session, session_tmp, &rga_service.session, list_session) - { - printk("session pid %d:\n", session->pid); - running = atomic_read(&session->task_running); - printk("task_running %d\n", running); - list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) - { +static inline void rga_write(u32 b, u32 r) +{ + __raw_writel(b, drvdata->rga_base + r); +} + +static inline u32 rga_read(u32 r) +{ + return __raw_readl(drvdata->rga_base + r); +} + +static void rga_soft_reset(void) +{ + u32 i; + u32 reg; + + rga_write(1, RGA_SYS_CTRL); //RGA_SYS_CTRL + + for(i = 0; i < RGA_RESET_TIMEOUT; i++) + { + reg = rga_read(RGA_SYS_CTRL) & 1; //RGA_SYS_CTRL + + if(reg == 0) + break; + + udelay(1); + } + + if(i == RGA_RESET_TIMEOUT) + ERR("soft reset timeout.\n"); +} + +static void rga_dump(void) +{ + int running; + struct rga_reg *reg, *reg_tmp; + rga_session *session, *session_tmp; + + running = atomic_read(&rga_service.total_running); + printk("rga total_running %d\n", running); + + #if 0 + + /* Dump waiting list info */ + if (!list_empty(&rga_service.waiting)) + { + list_head *next; + + next = &rga_service.waiting; + + printk("rga_service dump waiting list\n"); + + do + { + reg = list_entry(next->next, struct rga_reg, status_link); + running = atomic_read(®->session->task_running); + num_done = atomic_read(®->session->num_done); + printk("rga session pid %d, done %d, running %d\n", reg->session->pid, num_done, running); + next = next->next; + } + while(!list_empty(next)); + } + + /* Dump running list info */ + if (!list_empty(&rga_service.running)) + { + printk("rga_service dump running list\n"); + + list_head *next; + + next = &rga_service.running; + do + { + reg = list_entry(next->next, struct rga_reg, status_link); + running = atomic_read(®->session->task_running); + num_done = atomic_read(®->session->num_done); + printk("rga session pid %d, done %d, running %d:\n", reg->session->pid, num_done, running); + next = next->next; + } + while(!list_empty(next)); + } + #endif + + list_for_each_entry_safe(session, session_tmp, &rga_service.session, list_session) + { + printk("session pid %d:\n", session->pid); + running = atomic_read(&session->task_running); + printk("task_running %d\n", running); + list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) + { printk("waiting register set 0x %.lu\n", (unsigned long)reg); - } - list_for_each_entry_safe(reg, reg_tmp, &session->running, session_link) - { + } + list_for_each_entry_safe(reg, reg_tmp, &session->running, session_link) + { printk("running register set 0x %.lu\n", (unsigned long)reg); - } - } -} - -static inline void rga_queue_power_off_work(void) -{ + } + } +} + +static inline void rga_queue_power_off_work(void) +{ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) - queue_delayed_work(system_wq, &drvdata->power_off_work, RGA_POWER_OFF_DELAY); + queue_delayed_work(system_wq, &drvdata->power_off_work, RGA_POWER_OFF_DELAY); #else queue_delayed_work(system_nrt_wq, &drvdata->power_off_work, RGA_POWER_OFF_DELAY); #endif -} - -/* Caller must hold rga_service.lock */ -static void rga_power_on(void) -{ - static ktime_t last; - ktime_t now = ktime_get(); - - if (ktime_to_ns(ktime_sub(now, last)) > NSEC_PER_SEC) { - cancel_delayed_work_sync(&drvdata->power_off_work); - rga_queue_power_off_work(); - last = now; - } - if (rga_service.enable) - return; - +} + +/* Caller must hold rga_service.lock */ +static void rga_power_on(void) +{ + static ktime_t last; + ktime_t now = ktime_get(); + + if (ktime_to_ns(ktime_sub(now, last)) > NSEC_PER_SEC) { + cancel_delayed_work_sync(&drvdata->power_off_work); + rga_queue_power_off_work(); + last = now; + } + if (rga_service.enable) + return; + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) clk_prepare_enable(drvdata->aclk_rga); clk_prepare_enable(drvdata->hclk_rga); @@ -540,27 +540,27 @@ static void rga_power_on(void) clk_prepare_enable(drvdata->pd_rga); #endif - wake_lock(&drvdata->wake_lock); - rga_service.enable = true; -} + wake_lock(&drvdata->wake_lock); + rga_service.enable = true; +} + +/* Caller must hold rga_service.lock */ +static void rga_power_off(void) +{ + int total_running; + + if (!rga_service.enable) { + return; + } + + total_running = atomic_read(&rga_service.total_running); + if (total_running) { + pr_err("power off when %d task running!!\n", total_running); + mdelay(50); + pr_err("delay 50 ms for running task\n"); + rga_dump(); + } -/* Caller must hold rga_service.lock */ -static void rga_power_off(void) -{ - int total_running; - - if (!rga_service.enable) { - return; - } - - total_running = atomic_read(&rga_service.total_running); - if (total_running) { - pr_err("power off when %d task running!!\n", total_running); - mdelay(50); - pr_err("delay 50 ms for running task\n"); - rga_dump(); - } - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) pm_runtime_put(drvdata->dev); clk_disable_unprepare(drvdata->aclk_rga); @@ -571,17 +571,17 @@ static void rga_power_off(void) clk_disable_unprepare(drvdata->aclk_rga); clk_disable_unprepare(drvdata->hclk_rga); #endif - wake_unlock(&drvdata->wake_lock); - rga_service.enable = false; -} - -static void rga_power_off_work(struct work_struct *work) -{ - if (mutex_trylock(&rga_service.lock)) { - rga_power_off(); - mutex_unlock(&rga_service.lock); - } else { - /* Come back later if the device is busy... */ + wake_unlock(&drvdata->wake_lock); + rga_service.enable = false; +} + +static void rga_power_off_work(struct work_struct *work) +{ + if (mutex_trylock(&rga_service.lock)) { + rga_power_off(); + mutex_unlock(&rga_service.lock); + } else { + /* Come back later if the device is busy... */ rga_queue_power_off_work(); } @@ -715,7 +715,7 @@ static void rga_copy_reg(struct rga_reg *reg, uint32_t offset) cmd_buf = (uint32_t *)rga_service.cmd_buff + offset*32; reg_p = (uint32_t *)reg->cmd_reg; - for(i=0; i<32; i++) + for(i=0; i<32; i++) cmd_buf[i] = reg_p[i]; } @@ -2272,279 +2272,279 @@ void rga_slt(void) } #endif #endif - -void rga_test_0(void); -void rga_test_1(void); - -static int __init rga_init(void) -{ - int ret; - uint32_t *mmu_buf; - unsigned long *mmu_buf_virtual; - uint32_t i; - uint32_t *buf_p; + +void rga_test_0(void); +void rga_test_1(void); + +static int __init rga_init(void) +{ + int ret; + uint32_t *mmu_buf; + unsigned long *mmu_buf_virtual; + uint32_t i; + uint32_t *buf_p; uint32_t *buf; - /* malloc pre scale mid buf mmu table */ - mmu_buf = kzalloc(1024*8, GFP_KERNEL); - mmu_buf_virtual = kzalloc(1024*2*sizeof(unsigned long), GFP_KERNEL); - if(mmu_buf == NULL) { - printk(KERN_ERR "RGA get Pre Scale buff failed. \n"); - return -1; - } - if (mmu_buf_virtual == NULL) { - return -1; - } - - /* malloc 4 M buf */ - for(i=0; i<1024; i++) { - buf_p = (uint32_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO); - if(buf_p == NULL) { - printk(KERN_ERR "RGA init pre scale buf falied\n"); - return -ENOMEM; - } - mmu_buf[i] = virt_to_phys((void *)((unsigned long)buf_p)); - mmu_buf_virtual[i] = (unsigned long)buf_p; - } - - rga_service.pre_scale_buf = (uint32_t *)mmu_buf; - rga_service.pre_scale_buf_virtual = (unsigned long *)mmu_buf_virtual; - - buf_p = kmalloc(1024*256, GFP_KERNEL); - rga_mmu_buf.buf_virtual = buf_p; + /* malloc pre scale mid buf mmu table */ + mmu_buf = kzalloc(1024*8, GFP_KERNEL); + mmu_buf_virtual = kzalloc(1024*2*sizeof(unsigned long), GFP_KERNEL); + if(mmu_buf == NULL) { + printk(KERN_ERR "RGA get Pre Scale buff failed. \n"); + return -1; + } + if (mmu_buf_virtual == NULL) { + return -1; + } + + /* malloc 4 M buf */ + for(i=0; i<1024; i++) { + buf_p = (uint32_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO); + if(buf_p == NULL) { + printk(KERN_ERR "RGA init pre scale buf falied\n"); + return -ENOMEM; + } + mmu_buf[i] = virt_to_phys((void *)((unsigned long)buf_p)); + mmu_buf_virtual[i] = (unsigned long)buf_p; + } + + rga_service.pre_scale_buf = (uint32_t *)mmu_buf; + rga_service.pre_scale_buf_virtual = (unsigned long *)mmu_buf_virtual; + + buf_p = kmalloc(1024*256, GFP_KERNEL); + rga_mmu_buf.buf_virtual = buf_p; #if (defined(CONFIG_ARM) && defined(CONFIG_ARM_LPAE)) buf = (uint32_t *)(uint32_t)virt_to_phys((void *)((unsigned long)buf_p)); #else buf = (uint32_t *)virt_to_phys((void *)((unsigned long)buf_p)); #endif rga_mmu_buf.buf = buf; - rga_mmu_buf.front = 0; - rga_mmu_buf.back = 64*1024; - rga_mmu_buf.size = 64*1024; - - rga_mmu_buf.pages = kmalloc((32768)* sizeof(struct page *), GFP_KERNEL); - - if ((ret = platform_driver_register(&rga_driver)) != 0) - { - printk(KERN_ERR "Platform device register failed (%d).\n", ret); - return ret; - } - - { - rga_session_global.pid = 0x0000ffff; - INIT_LIST_HEAD(&rga_session_global.waiting); - INIT_LIST_HEAD(&rga_session_global.running); - INIT_LIST_HEAD(&rga_session_global.list_session); - - INIT_LIST_HEAD(&rga_service.waiting); - INIT_LIST_HEAD(&rga_service.running); - INIT_LIST_HEAD(&rga_service.done); - INIT_LIST_HEAD(&rga_service.session); - - init_waitqueue_head(&rga_session_global.wait); - //mutex_lock(&rga_service.lock); - list_add_tail(&rga_session_global.list_session, &rga_service.session); - //mutex_unlock(&rga_service.lock); - atomic_set(&rga_session_global.task_running, 0); - atomic_set(&rga_session_global.num_done, 0); - } - + rga_mmu_buf.front = 0; + rga_mmu_buf.back = 64*1024; + rga_mmu_buf.size = 64*1024; + + rga_mmu_buf.pages = kmalloc((32768)* sizeof(struct page *), GFP_KERNEL); + + if ((ret = platform_driver_register(&rga_driver)) != 0) + { + printk(KERN_ERR "Platform device register failed (%d).\n", ret); + return ret; + } + + { + rga_session_global.pid = 0x0000ffff; + INIT_LIST_HEAD(&rga_session_global.waiting); + INIT_LIST_HEAD(&rga_session_global.running); + INIT_LIST_HEAD(&rga_session_global.list_session); + + INIT_LIST_HEAD(&rga_service.waiting); + INIT_LIST_HEAD(&rga_service.running); + INIT_LIST_HEAD(&rga_service.done); + INIT_LIST_HEAD(&rga_service.session); + + init_waitqueue_head(&rga_session_global.wait); + //mutex_lock(&rga_service.lock); + list_add_tail(&rga_session_global.list_session, &rga_service.session); + //mutex_unlock(&rga_service.lock); + atomic_set(&rga_session_global.task_running, 0); + atomic_set(&rga_session_global.num_done, 0); + } + #if RGA_TEST_CASE rga_test_0(); #endif #if RGA_DEBUGFS rga_debugfs_add(); #endif - - INFO("Module initialized.\n"); - - return 0; -} - -static void __exit rga_exit(void) -{ - uint32_t i; - - rga_power_off(); - - for(i=0; i<1024; i++) - { - if((unsigned long)rga_service.pre_scale_buf_virtual[i]) - { - __free_page((void *)rga_service.pre_scale_buf_virtual[i]); - } - } - - if(rga_service.pre_scale_buf != NULL) { - kfree((uint8_t *)rga_service.pre_scale_buf); - } - + + INFO("Module initialized.\n"); + + return 0; +} + +static void __exit rga_exit(void) +{ + uint32_t i; + + rga_power_off(); + + for(i=0; i<1024; i++) + { + if((unsigned long)rga_service.pre_scale_buf_virtual[i]) + { + __free_page((void *)rga_service.pre_scale_buf_virtual[i]); + } + } + + if(rga_service.pre_scale_buf != NULL) { + kfree((uint8_t *)rga_service.pre_scale_buf); + } + kfree(rga_mmu_buf.buf_virtual); kfree(rga_mmu_buf.pages); - platform_driver_unregister(&rga_driver); -} + platform_driver_unregister(&rga_driver); +} #if RGA_TEST_CASE -extern struct fb_info * rk_get_fb(int fb_id); -EXPORT_SYMBOL(rk_get_fb); - -extern void rk_direct_fb_show(struct fb_info * fbi); -EXPORT_SYMBOL(rk_direct_fb_show); - -unsigned int src_buf[1920*1080]; -unsigned int dst_buf[1920*1080]; -//unsigned int tmp_buf[1920*1080 * 2]; - -void rga_test_0(void) -{ - struct rga_req req; - rga_session session; - unsigned int *src, *dst; - uint32_t i, j; - uint8_t *p; - uint8_t t; - uint32_t *dst0, *dst1, *dst2; - - struct fb_info *fb; - - session.pid = current->pid; - INIT_LIST_HEAD(&session.waiting); - INIT_LIST_HEAD(&session.running); - INIT_LIST_HEAD(&session.list_session); - init_waitqueue_head(&session.wait); - /* no need to protect */ - list_add_tail(&session.list_session, &rga_service.session); - atomic_set(&session.task_running, 0); - atomic_set(&session.num_done, 0); - //file->private_data = (void *)session; - - fb = rk_get_fb(0); - - memset(&req, 0, sizeof(struct rga_req)); - src = src_buf; - dst = dst_buf; - - memset(src_buf, 0x80, 1024*600*4); - - dmac_flush_range(&src_buf[0], &src_buf[1024*600]); - outer_flush_range(virt_to_phys(&src_buf[0]),virt_to_phys(&src_buf[1024*600])); - - - #if 0 - memset(src_buf, 0x80, 800*480*4); - memset(dst_buf, 0xcc, 800*480*4); - - dmac_flush_range(&dst_buf[0], &dst_buf[800*480]); - outer_flush_range(virt_to_phys(&dst_buf[0]),virt_to_phys(&dst_buf[800*480])); - #endif - - dst0 = &dst_buf[0]; - //dst1 = &dst_buf[1280*800*4]; - //dst2 = &dst_buf[1280*800*4*2]; - - i = j = 0; - - printk("\n********************************\n"); - printk("************ RGA_TEST ************\n"); - printk("********************************\n\n"); - - req.src.act_w = 1024; - req.src.act_h = 600; - - req.src.vir_w = 1024; - req.src.vir_h = 600; - req.src.yrgb_addr = (uint32_t)virt_to_phys(src); - req.src.uv_addr = (uint32_t)(req.src.yrgb_addr + 1080*1920); - req.src.v_addr = (uint32_t)virt_to_phys(src); - req.src.format = RK_FORMAT_RGBA_8888; - - req.dst.act_w = 600; - req.dst.act_h = 352; - - req.dst.vir_w = 1280; - req.dst.vir_h = 800; - req.dst.x_offset = 600; - req.dst.y_offset = 0; - - dst = dst0; - - req.dst.yrgb_addr = ((uint32_t)virt_to_phys(dst)); - - //req.dst.format = RK_FORMAT_RGB_565; - - req.clip.xmin = 0; - req.clip.xmax = 1279; - req.clip.ymin = 0; - req.clip.ymax = 799; - - //req.render_mode = color_fill_mode; - //req.fg_color = 0x80ffffff; - - req.rotate_mode = 1; - //req.scale_mode = 2; - - //req.alpha_rop_flag = 0; - //req.alpha_rop_mode = 0x19; - //req.PD_mode = 3; - - req.sina = 65536; - req.cosa = 0; - - //req.mmu_info.mmu_flag = 0x21; - //req.mmu_info.mmu_en = 1; - - //printk("src = %.8x\n", req.src.yrgb_addr); - //printk("src = %.8x\n", req.src.uv_addr); - //printk("dst = %.8x\n", req.dst.yrgb_addr); - - - rga_blit_sync(&session, &req); - - #if 1 - fb->var.bits_per_pixel = 32; - - fb->var.xres = 1280; - fb->var.yres = 800; - - fb->var.red.length = 8; - fb->var.red.offset = 0; - fb->var.red.msb_right = 0; - - fb->var.green.length = 8; - fb->var.green.offset = 8; - fb->var.green.msb_right = 0; - - fb->var.blue.length = 8; - - fb->var.blue.offset = 16; - fb->var.blue.msb_right = 0; - - fb->var.transp.length = 8; - fb->var.transp.offset = 24; - fb->var.transp.msb_right = 0; - - fb->var.nonstd &= (~0xff); - fb->var.nonstd |= 1; - - fb->fix.smem_start = virt_to_phys(dst); - - rk_direct_fb_show(fb); - #endif - -} - -#endif +extern struct fb_info * rk_get_fb(int fb_id); +EXPORT_SYMBOL(rk_get_fb); + +extern void rk_direct_fb_show(struct fb_info * fbi); +EXPORT_SYMBOL(rk_direct_fb_show); + +unsigned int src_buf[1920*1080]; +unsigned int dst_buf[1920*1080]; +//unsigned int tmp_buf[1920*1080 * 2]; + +void rga_test_0(void) +{ + struct rga_req req; + rga_session session; + unsigned int *src, *dst; + uint32_t i, j; + uint8_t *p; + uint8_t t; + uint32_t *dst0, *dst1, *dst2; + + struct fb_info *fb; + + session.pid = current->pid; + INIT_LIST_HEAD(&session.waiting); + INIT_LIST_HEAD(&session.running); + INIT_LIST_HEAD(&session.list_session); + init_waitqueue_head(&session.wait); + /* no need to protect */ + list_add_tail(&session.list_session, &rga_service.session); + atomic_set(&session.task_running, 0); + atomic_set(&session.num_done, 0); + //file->private_data = (void *)session; + + fb = rk_get_fb(0); + + memset(&req, 0, sizeof(struct rga_req)); + src = src_buf; + dst = dst_buf; + + memset(src_buf, 0x80, 1024*600*4); + + dmac_flush_range(&src_buf[0], &src_buf[1024*600]); + outer_flush_range(virt_to_phys(&src_buf[0]),virt_to_phys(&src_buf[1024*600])); + + + #if 0 + memset(src_buf, 0x80, 800*480*4); + memset(dst_buf, 0xcc, 800*480*4); + + dmac_flush_range(&dst_buf[0], &dst_buf[800*480]); + outer_flush_range(virt_to_phys(&dst_buf[0]),virt_to_phys(&dst_buf[800*480])); + #endif + + dst0 = &dst_buf[0]; + //dst1 = &dst_buf[1280*800*4]; + //dst2 = &dst_buf[1280*800*4*2]; + + i = j = 0; + + printk("\n********************************\n"); + printk("************ RGA_TEST ************\n"); + printk("********************************\n\n"); + + req.src.act_w = 1024; + req.src.act_h = 600; + + req.src.vir_w = 1024; + req.src.vir_h = 600; + req.src.yrgb_addr = (uint32_t)virt_to_phys(src); + req.src.uv_addr = (uint32_t)(req.src.yrgb_addr + 1080*1920); + req.src.v_addr = (uint32_t)virt_to_phys(src); + req.src.format = RK_FORMAT_RGBA_8888; + + req.dst.act_w = 600; + req.dst.act_h = 352; + + req.dst.vir_w = 1280; + req.dst.vir_h = 800; + req.dst.x_offset = 600; + req.dst.y_offset = 0; + + dst = dst0; + + req.dst.yrgb_addr = ((uint32_t)virt_to_phys(dst)); + + //req.dst.format = RK_FORMAT_RGB_565; + + req.clip.xmin = 0; + req.clip.xmax = 1279; + req.clip.ymin = 0; + req.clip.ymax = 799; + + //req.render_mode = color_fill_mode; + //req.fg_color = 0x80ffffff; + + req.rotate_mode = 1; + //req.scale_mode = 2; + + //req.alpha_rop_flag = 0; + //req.alpha_rop_mode = 0x19; + //req.PD_mode = 3; + + req.sina = 65536; + req.cosa = 0; + + //req.mmu_info.mmu_flag = 0x21; + //req.mmu_info.mmu_en = 1; + + //printk("src = %.8x\n", req.src.yrgb_addr); + //printk("src = %.8x\n", req.src.uv_addr); + //printk("dst = %.8x\n", req.dst.yrgb_addr); + + + rga_blit_sync(&session, &req); + + #if 1 + fb->var.bits_per_pixel = 32; + + fb->var.xres = 1280; + fb->var.yres = 800; + + fb->var.red.length = 8; + fb->var.red.offset = 0; + fb->var.red.msb_right = 0; + + fb->var.green.length = 8; + fb->var.green.offset = 8; + fb->var.green.msb_right = 0; + + fb->var.blue.length = 8; + + fb->var.blue.offset = 16; + fb->var.blue.msb_right = 0; + + fb->var.transp.length = 8; + fb->var.transp.offset = 24; + fb->var.transp.msb_right = 0; + + fb->var.nonstd &= (~0xff); + fb->var.nonstd |= 1; + + fb->fix.smem_start = virt_to_phys(dst); + + rk_direct_fb_show(fb); + #endif + +} + +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)) fs_initcall(rga_init); #else module_init(rga_init); #endif -module_exit(rga_exit); - -/* Module information */ -MODULE_AUTHOR("zsq@rock-chips.com"); -MODULE_DESCRIPTION("Driver for rga device"); -MODULE_LICENSE("GPL"); +module_exit(rga_exit); + +/* Module information */ +MODULE_AUTHOR("zsq@rock-chips.com"); +MODULE_DESCRIPTION("Driver for rga device"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/rockchip/rga/rga_mmu_info.c b/drivers/video/rockchip/rga/rga_mmu_info.c index 8825183d92fc..cdd1fcd7bbcb 100644 --- a/drivers/video/rockchip/rga/rga_mmu_info.c +++ b/drivers/video/rockchip/rga/rga_mmu_info.c @@ -1,258 +1,258 @@ /* SPDX-License-Identifier: GPL-2.0 */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rga_mmu_info.h" -#include - -extern rga_service_info rga_service; -extern struct rga_mmu_buf_t rga_mmu_buf; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rga_mmu_info.h" +#include + +extern rga_service_info rga_service; +extern struct rga_mmu_buf_t rga_mmu_buf; #if RGA_DEBUGFS extern int RGA_CHECK_MODE; #endif - + #define KERNEL_SPACE_VALID 0xc0000000 void rga_dma_flush_range(void *pstart, void *pend) { dma_sync_single_for_device(drvdata->dev, virt_to_phys(pstart), pend - pstart, DMA_TO_DEVICE); } - -static int rga_mmu_buf_get(struct rga_mmu_buf_t *t, uint32_t size) -{ - mutex_lock(&rga_service.lock); - t->front += size; - mutex_unlock(&rga_service.lock); - - return 0; -} - -static int rga_mmu_buf_get_try(struct rga_mmu_buf_t *t, uint32_t size) -{ - int ret = 0; - - mutex_lock(&rga_service.lock); - if ((t->back - t->front) > t->size) { - if(t->front + size > t->back - t->size) { - ret = -ENOMEM; - goto out; - } - } else { - if ((t->front + size) > t->back) { - ret = -ENOMEM; - goto out; - } - if (t->front + size > t->size) { - if (size > (t->back - t->size)) { - ret = -ENOMEM; - goto out; - } - t->front = 0; - } - } - -out: - mutex_unlock(&rga_service.lock); - return ret; -} - -static int rga_mem_size_cal(unsigned long Mem, uint32_t MemSize, unsigned long *StartAddr) -{ - unsigned long start, end; - uint32_t pageCount; - - end = (Mem + (MemSize + PAGE_SIZE - 1)) >> PAGE_SHIFT; - start = Mem >> PAGE_SHIFT; - pageCount = end - start; - *StartAddr = start; - return pageCount; -} - -static int rga_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr, unsigned long v_addr, - int format, uint32_t w, uint32_t h, unsigned long *StartAddr ) -{ - uint32_t size_yrgb = 0; - uint32_t size_uv = 0; - uint32_t size_v = 0; - uint32_t stride = 0; - unsigned long start, end; - uint32_t pageCount; - - switch(format) - { - case RK_FORMAT_RGBA_8888 : - stride = (w * 4 + 3) & (~3); - size_yrgb = stride*h; - start = yrgb_addr >> PAGE_SHIFT; - pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; - break; - case RK_FORMAT_RGBX_8888 : - stride = (w * 4 + 3) & (~3); - size_yrgb = stride*h; - start = yrgb_addr >> PAGE_SHIFT; - pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; - break; - case RK_FORMAT_RGB_888 : - stride = (w * 3 + 3) & (~3); - size_yrgb = stride*h; - start = yrgb_addr >> PAGE_SHIFT; - pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; - break; - case RK_FORMAT_BGRA_8888 : - size_yrgb = w*h*4; - start = yrgb_addr >> PAGE_SHIFT; - pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; - break; - case RK_FORMAT_RGB_565 : - stride = (w*2 + 3) & (~3); - size_yrgb = stride * h; - start = yrgb_addr >> PAGE_SHIFT; - pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; - break; - case RK_FORMAT_RGBA_5551 : - stride = (w*2 + 3) & (~3); - size_yrgb = stride * h; - start = yrgb_addr >> PAGE_SHIFT; - pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; - break; - case RK_FORMAT_RGBA_4444 : - stride = (w*2 + 3) & (~3); - size_yrgb = stride * h; - start = yrgb_addr >> PAGE_SHIFT; - pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; - break; - case RK_FORMAT_BGR_888 : - stride = (w*3 + 3) & (~3); - size_yrgb = stride * h; - start = yrgb_addr >> PAGE_SHIFT; - pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; - break; - - /* YUV FORMAT */ - case RK_FORMAT_YCbCr_422_SP : - stride = (w + 3) & (~3); - size_yrgb = stride * h; - size_uv = stride * h; - start = MIN(yrgb_addr, uv_addr); - - start >>= PAGE_SHIFT; - end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)); - end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - pageCount = end - start; - break; - case RK_FORMAT_YCbCr_422_P : - stride = (w + 3) & (~3); - size_yrgb = stride * h; - size_uv = ((stride >> 1) * h); - size_v = ((stride >> 1) * h); - start = MIN(MIN(yrgb_addr, uv_addr), v_addr); - start = start >> PAGE_SHIFT; - end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v)); - end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - pageCount = end - start; - break; - case RK_FORMAT_YCbCr_420_SP : - stride = (w + 3) & (~3); - size_yrgb = stride * h; - size_uv = (stride * (h >> 1)); - start = MIN(yrgb_addr, uv_addr); - start >>= PAGE_SHIFT; - end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)); - end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - pageCount = end - start; - break; - case RK_FORMAT_YCbCr_420_P : - stride = (w + 3) & (~3); - size_yrgb = stride * h; - size_uv = ((stride >> 1) * (h >> 1)); - size_v = ((stride >> 1) * (h >> 1)); - start = MIN(MIN(yrgb_addr, uv_addr), v_addr); - start >>= PAGE_SHIFT; - end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v)); - end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - pageCount = end - start; - break; - - case RK_FORMAT_YCrCb_422_SP : - stride = (w + 3) & (~3); - size_yrgb = stride * h; - size_uv = stride * h; - start = MIN(yrgb_addr, uv_addr); - start >>= PAGE_SHIFT; - end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)); - end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - pageCount = end - start; - break; - case RK_FORMAT_YCrCb_422_P : - stride = (w + 3) & (~3); - size_yrgb = stride * h; - size_uv = ((stride >> 1) * h); - size_v = ((stride >> 1) * h); - start = MIN(MIN(yrgb_addr, uv_addr), v_addr); - start >>= PAGE_SHIFT; - end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v)); - end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - pageCount = end - start; - break; - - case RK_FORMAT_YCrCb_420_SP : - stride = (w + 3) & (~3); - size_yrgb = stride * h; - size_uv = (stride * (h >> 1)); - start = MIN(yrgb_addr, uv_addr); - start >>= PAGE_SHIFT; - end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)); - end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - pageCount = end - start; - break; - case RK_FORMAT_YCrCb_420_P : - stride = (w + 3) & (~3); - size_yrgb = stride * h; - size_uv = ((stride >> 1) * (h >> 1)); - size_v = ((stride >> 1) * (h >> 1)); - start = MIN(MIN(yrgb_addr, uv_addr), v_addr); - start >>= PAGE_SHIFT; - end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v)); - end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - pageCount = end - start; - break; - #if 0 - case RK_FORMAT_BPP1 : - break; - case RK_FORMAT_BPP2 : - break; - case RK_FORMAT_BPP4 : - break; - case RK_FORMAT_BPP8 : - break; - #endif - default : - pageCount = 0; - start = 0; - break; - } - - *StartAddr = start; - return pageCount; -} - + +static int rga_mmu_buf_get(struct rga_mmu_buf_t *t, uint32_t size) +{ + mutex_lock(&rga_service.lock); + t->front += size; + mutex_unlock(&rga_service.lock); + + return 0; +} + +static int rga_mmu_buf_get_try(struct rga_mmu_buf_t *t, uint32_t size) +{ + int ret = 0; + + mutex_lock(&rga_service.lock); + if ((t->back - t->front) > t->size) { + if(t->front + size > t->back - t->size) { + ret = -ENOMEM; + goto out; + } + } else { + if ((t->front + size) > t->back) { + ret = -ENOMEM; + goto out; + } + if (t->front + size > t->size) { + if (size > (t->back - t->size)) { + ret = -ENOMEM; + goto out; + } + t->front = 0; + } + } + +out: + mutex_unlock(&rga_service.lock); + return ret; +} + +static int rga_mem_size_cal(unsigned long Mem, uint32_t MemSize, unsigned long *StartAddr) +{ + unsigned long start, end; + uint32_t pageCount; + + end = (Mem + (MemSize + PAGE_SIZE - 1)) >> PAGE_SHIFT; + start = Mem >> PAGE_SHIFT; + pageCount = end - start; + *StartAddr = start; + return pageCount; +} + +static int rga_buf_size_cal(unsigned long yrgb_addr, unsigned long uv_addr, unsigned long v_addr, + int format, uint32_t w, uint32_t h, unsigned long *StartAddr ) +{ + uint32_t size_yrgb = 0; + uint32_t size_uv = 0; + uint32_t size_v = 0; + uint32_t stride = 0; + unsigned long start, end; + uint32_t pageCount; + + switch(format) + { + case RK_FORMAT_RGBA_8888 : + stride = (w * 4 + 3) & (~3); + size_yrgb = stride*h; + start = yrgb_addr >> PAGE_SHIFT; + pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; + break; + case RK_FORMAT_RGBX_8888 : + stride = (w * 4 + 3) & (~3); + size_yrgb = stride*h; + start = yrgb_addr >> PAGE_SHIFT; + pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; + break; + case RK_FORMAT_RGB_888 : + stride = (w * 3 + 3) & (~3); + size_yrgb = stride*h; + start = yrgb_addr >> PAGE_SHIFT; + pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; + break; + case RK_FORMAT_BGRA_8888 : + size_yrgb = w*h*4; + start = yrgb_addr >> PAGE_SHIFT; + pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; + break; + case RK_FORMAT_RGB_565 : + stride = (w*2 + 3) & (~3); + size_yrgb = stride * h; + start = yrgb_addr >> PAGE_SHIFT; + pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; + break; + case RK_FORMAT_RGBA_5551 : + stride = (w*2 + 3) & (~3); + size_yrgb = stride * h; + start = yrgb_addr >> PAGE_SHIFT; + pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; + break; + case RK_FORMAT_RGBA_4444 : + stride = (w*2 + 3) & (~3); + size_yrgb = stride * h; + start = yrgb_addr >> PAGE_SHIFT; + pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; + break; + case RK_FORMAT_BGR_888 : + stride = (w*3 + 3) & (~3); + size_yrgb = stride * h; + start = yrgb_addr >> PAGE_SHIFT; + pageCount = (size_yrgb + PAGE_SIZE - 1) >> PAGE_SHIFT; + break; + + /* YUV FORMAT */ + case RK_FORMAT_YCbCr_422_SP : + stride = (w + 3) & (~3); + size_yrgb = stride * h; + size_uv = stride * h; + start = MIN(yrgb_addr, uv_addr); + + start >>= PAGE_SHIFT; + end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)); + end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + pageCount = end - start; + break; + case RK_FORMAT_YCbCr_422_P : + stride = (w + 3) & (~3); + size_yrgb = stride * h; + size_uv = ((stride >> 1) * h); + size_v = ((stride >> 1) * h); + start = MIN(MIN(yrgb_addr, uv_addr), v_addr); + start = start >> PAGE_SHIFT; + end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v)); + end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + pageCount = end - start; + break; + case RK_FORMAT_YCbCr_420_SP : + stride = (w + 3) & (~3); + size_yrgb = stride * h; + size_uv = (stride * (h >> 1)); + start = MIN(yrgb_addr, uv_addr); + start >>= PAGE_SHIFT; + end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)); + end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + pageCount = end - start; + break; + case RK_FORMAT_YCbCr_420_P : + stride = (w + 3) & (~3); + size_yrgb = stride * h; + size_uv = ((stride >> 1) * (h >> 1)); + size_v = ((stride >> 1) * (h >> 1)); + start = MIN(MIN(yrgb_addr, uv_addr), v_addr); + start >>= PAGE_SHIFT; + end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v)); + end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + pageCount = end - start; + break; + + case RK_FORMAT_YCrCb_422_SP : + stride = (w + 3) & (~3); + size_yrgb = stride * h; + size_uv = stride * h; + start = MIN(yrgb_addr, uv_addr); + start >>= PAGE_SHIFT; + end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)); + end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + pageCount = end - start; + break; + case RK_FORMAT_YCrCb_422_P : + stride = (w + 3) & (~3); + size_yrgb = stride * h; + size_uv = ((stride >> 1) * h); + size_v = ((stride >> 1) * h); + start = MIN(MIN(yrgb_addr, uv_addr), v_addr); + start >>= PAGE_SHIFT; + end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v)); + end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + pageCount = end - start; + break; + + case RK_FORMAT_YCrCb_420_SP : + stride = (w + 3) & (~3); + size_yrgb = stride * h; + size_uv = (stride * (h >> 1)); + start = MIN(yrgb_addr, uv_addr); + start >>= PAGE_SHIFT; + end = MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)); + end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + pageCount = end - start; + break; + case RK_FORMAT_YCrCb_420_P : + stride = (w + 3) & (~3); + size_yrgb = stride * h; + size_uv = ((stride >> 1) * (h >> 1)); + size_v = ((stride >> 1) * (h >> 1)); + start = MIN(MIN(yrgb_addr, uv_addr), v_addr); + start >>= PAGE_SHIFT; + end = MAX(MAX((yrgb_addr + size_yrgb), (uv_addr + size_uv)), (v_addr + size_v)); + end = (end + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + pageCount = end - start; + break; + #if 0 + case RK_FORMAT_BPP1 : + break; + case RK_FORMAT_BPP2 : + break; + case RK_FORMAT_BPP4 : + break; + case RK_FORMAT_BPP8 : + break; + #endif + default : + pageCount = 0; + start = 0; + break; + } + + *StartAddr = start; + return pageCount; +} + #if RGA_DEBUGFS static int rga_usermemory_cheeck(struct page **pages, u32 w, u32 h, u32 format, int flag) { @@ -319,20 +319,20 @@ static int rga_usermemory_cheeck(struct page **pages, u32 w, u32 h, u32 format, } #endif -static int rga_MapUserMemory(struct page **pages, - uint32_t *pageTable, - unsigned long Memory, - uint32_t pageCount) -{ - int32_t result; - uint32_t i; - uint32_t status; - unsigned long Address; - - status = 0; - Address = 0; - - do { +static int rga_MapUserMemory(struct page **pages, + uint32_t *pageTable, + unsigned long Memory, + uint32_t pageCount) +{ + int32_t result; + uint32_t i; + uint32_t status; + unsigned long Address; + + status = 0; + Address = 0; + + do { #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) mmap_read_lock(current->mm); #else @@ -356,72 +356,72 @@ static int rga_MapUserMemory(struct page **pages, #else up_read(¤t->mm->mmap_sem); #endif - - #if 0 - if(result <= 0 || result < pageCount) - { - status = 0; - - for(i=0; i0) { + + #if 0 + if(result <= 0 || result < pageCount) + { + status = 0; + + for(i=0; i0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) mmap_read_lock(current->mm); #else down_read(¤t->mm->mmap_sem); #endif - for (i = 0; i < result; i++) - put_page(pages[i]); + for (i = 0; i < result; i++) + put_page(pages[i]); #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) mmap_read_unlock(current->mm); #else up_read(¤t->mm->mmap_sem); #endif - } - - for(i=0; imm, (Memory + i) << PAGE_SHIFT); - - if (vma)//&& (vma->vm_flags & VM_PFNMAP) ) - { - do - { - pte_t * pte; - spinlock_t * ptl; - unsigned long pfn; + } + + for(i=0; imm, (Memory + i) << PAGE_SHIFT); + + if (vma)//&& (vma->vm_flags & VM_PFNMAP) ) + { + do + { + pte_t * pte; + spinlock_t * ptl; + unsigned long pfn; pgd_t * pgd; #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) p4d_t * p4d; #endif - pud_t * pud; - - pgd = pgd_offset(current->mm, (Memory + i) << PAGE_SHIFT); - - if(pgd_val(*pgd) == 0) - { - //printk("rga pgd value is zero \n"); - break; - } - + pud_t * pud; + + pgd = pgd_offset(current->mm, (Memory + i) << PAGE_SHIFT); + + if(pgd_val(*pgd) == 0) + { + //printk("rga pgd value is zero \n"); + break; + } + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) /* In the four-level page table, it will do nothing and return pgd. */ p4d = p4d_offset(pgd, (Memory + i) << PAGE_SHIFT); @@ -436,217 +436,217 @@ static int rga_MapUserMemory(struct page **pages, #else pud = pud_offset(pgd, (Memory + i) << PAGE_SHIFT); #endif - if (pud) - { - pmd_t * pmd = pmd_offset(pud, (Memory + i) << PAGE_SHIFT); - if (pmd) - { - pte = pte_offset_map_lock(current->mm, pmd, (Memory + i) << PAGE_SHIFT, &ptl); - if (!pte) - { - pte_unmap_unlock(pte, ptl); - break; - } - } - else - { - break; - } - } - else - { - break; - } - - pfn = pte_pfn(*pte); - Address = ((pfn << PAGE_SHIFT) | (((unsigned long)((Memory + i) << PAGE_SHIFT)) & ~PAGE_MASK)); - pte_unmap_unlock(pte, ptl); - } - while (0); - - pageTable[i] = Address; - } - else - { - status = RGA_OUT_OF_RESOURCES; - break; - } - } - - return status; - } - #endif - - /* Fill the page table. */ - for(i=0; imm, pmd, (Memory + i) << PAGE_SHIFT, &ptl); + if (!pte) + { + pte_unmap_unlock(pte, ptl); + break; + } + } + else + { + break; + } + } + else + { + break; + } + + pfn = pte_pfn(*pte); + Address = ((pfn << PAGE_SHIFT) | (((unsigned long)((Memory + i) << PAGE_SHIFT)) & ~PAGE_MASK)); + pte_unmap_unlock(pte, ptl); + } + while (0); + + pageTable[i] = Address; + } + else + { + status = RGA_OUT_OF_RESOURCES; + break; + } + } + + return status; + } + #endif + + /* Fill the page table. */ + for(i=0; i= KERNEL_VERSION(5, 10, 0) mmap_read_lock(current->mm); #else down_read(¤t->mm->mmap_sem); #endif - for (i = 0; i < result; i++) - put_page(pages[i]); + for (i = 0; i < result; i++) + put_page(pages[i]); #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) mmap_read_unlock(current->mm); #else up_read(¤t->mm->mmap_sem); #endif - - return 0; - } - while(0); - - return status; -} - -static int rga_MapION(struct sg_table *sg, - uint32_t *Memory, - int32_t pageCount, - uint32_t offset) -{ - uint32_t i; - uint32_t status; - unsigned long Address; - uint32_t mapped_size = 0; - uint32_t len = 0; - struct scatterlist *sgl = sg->sgl; - uint32_t sg_num = 0; - - status = 0; - Address = 0; - offset = offset >> PAGE_SHIFT; - if (offset != 0) { - do { - len += (sg_dma_len(sgl) >> PAGE_SHIFT); - if (len == offset) { - sg_num += 1; - break; - } - else { - if (len > offset) - break; - } - sg_num += 1; - } - while((sgl = sg_next(sgl)) && (mapped_size < pageCount) && (sg_num < sg->nents)); - - sgl = sg->sgl; - len = 0; - do { - len += (sg_dma_len(sgl) >> PAGE_SHIFT); - sgl = sg_next(sgl); - } - while(--sg_num); - - offset -= len; - - len = sg_dma_len(sgl) >> PAGE_SHIFT; - Address = sg_phys(sgl); - Address += offset; - - for(i=offset; i> PAGE_SHIFT; - Address = sg_phys(sgl); - - for(i=0; inents)); - } - else { - do { - len = sg_dma_len(sgl) >> PAGE_SHIFT; - Address = sg_phys(sgl); - for(i=0; inents)); - } - return 0; -} - - -static int rga_mmu_info_BitBlt_mode(struct rga_reg *reg, struct rga_req *req) -{ - int SrcMemSize, DstMemSize; - unsigned long SrcStart, DstStart; - uint32_t i; - uint32_t AllSize; - uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys; - int ret; - int status; - uint32_t uv_size, v_size; - - struct page **pages = NULL; - - MMU_Base = NULL; - - SrcMemSize = 0; - DstMemSize = 0; - - do { - /* cal src buf mmu info */ - SrcMemSize = rga_buf_size_cal(req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr, - req->src.format, req->src.vir_w, req->src.act_h + req->src.y_offset, - &SrcStart); - if(SrcMemSize == 0) { - return -EINVAL; - } - - /* cal dst buf mmu info */ - - DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr, - req->dst.format, req->dst.vir_w, req->dst.vir_h, - &DstStart); - if(DstMemSize == 0) - return -EINVAL; - - /* Cal out the needed mem size */ - SrcMemSize = (SrcMemSize + 15) & (~15); - DstMemSize = (DstMemSize + 15) & (~15); - AllSize = SrcMemSize + DstMemSize; - - if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) { - pr_err("RGA Get MMU mem failed\n"); - status = RGA_MALLOC_ERROR; - break; - } - - mutex_lock(&rga_service.lock); - MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); - MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); - mutex_unlock(&rga_service.lock); - - pages = rga_mmu_buf.pages; - - if((req->mmu_info.mmu_flag >> 8) & 1) { - if (req->sg_src) { - ret = rga_MapION(req->sg_src, &MMU_Base[0], SrcMemSize, req->line_draw_info.flag); - } - else { - ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], SrcStart, SrcMemSize); - if (ret < 0) { - pr_err("rga map src memory failed\n"); - status = ret; - break; + + return 0; + } + while(0); + + return status; +} + +static int rga_MapION(struct sg_table *sg, + uint32_t *Memory, + int32_t pageCount, + uint32_t offset) +{ + uint32_t i; + uint32_t status; + unsigned long Address; + uint32_t mapped_size = 0; + uint32_t len = 0; + struct scatterlist *sgl = sg->sgl; + uint32_t sg_num = 0; + + status = 0; + Address = 0; + offset = offset >> PAGE_SHIFT; + if (offset != 0) { + do { + len += (sg_dma_len(sgl) >> PAGE_SHIFT); + if (len == offset) { + sg_num += 1; + break; + } + else { + if (len > offset) + break; + } + sg_num += 1; + } + while((sgl = sg_next(sgl)) && (mapped_size < pageCount) && (sg_num < sg->nents)); + + sgl = sg->sgl; + len = 0; + do { + len += (sg_dma_len(sgl) >> PAGE_SHIFT); + sgl = sg_next(sgl); + } + while(--sg_num); + + offset -= len; + + len = sg_dma_len(sgl) >> PAGE_SHIFT; + Address = sg_phys(sgl); + Address += offset; + + for(i=offset; i> PAGE_SHIFT; + Address = sg_phys(sgl); + + for(i=0; inents)); + } + else { + do { + len = sg_dma_len(sgl) >> PAGE_SHIFT; + Address = sg_phys(sgl); + for(i=0; inents)); + } + return 0; +} + + +static int rga_mmu_info_BitBlt_mode(struct rga_reg *reg, struct rga_req *req) +{ + int SrcMemSize, DstMemSize; + unsigned long SrcStart, DstStart; + uint32_t i; + uint32_t AllSize; + uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys; + int ret; + int status; + uint32_t uv_size, v_size; + + struct page **pages = NULL; + + MMU_Base = NULL; + + SrcMemSize = 0; + DstMemSize = 0; + + do { + /* cal src buf mmu info */ + SrcMemSize = rga_buf_size_cal(req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr, + req->src.format, req->src.vir_w, req->src.act_h + req->src.y_offset, + &SrcStart); + if(SrcMemSize == 0) { + return -EINVAL; + } + + /* cal dst buf mmu info */ + + DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr, + req->dst.format, req->dst.vir_w, req->dst.vir_h, + &DstStart); + if(DstMemSize == 0) + return -EINVAL; + + /* Cal out the needed mem size */ + SrcMemSize = (SrcMemSize + 15) & (~15); + DstMemSize = (DstMemSize + 15) & (~15); + AllSize = SrcMemSize + DstMemSize; + + if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) { + pr_err("RGA Get MMU mem failed\n"); + status = RGA_MALLOC_ERROR; + break; + } + + mutex_lock(&rga_service.lock); + MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); + MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); + mutex_unlock(&rga_service.lock); + + pages = rga_mmu_buf.pages; + + if((req->mmu_info.mmu_flag >> 8) & 1) { + if (req->sg_src) { + ret = rga_MapION(req->sg_src, &MMU_Base[0], SrcMemSize, req->line_draw_info.flag); + } + else { + ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], SrcStart, SrcMemSize); + if (ret < 0) { + pr_err("rga map src memory failed\n"); + status = ret; + break; } #if RGA_DEBUGFS @@ -654,662 +654,662 @@ static int rga_mmu_info_BitBlt_mode(struct rga_reg *reg, struct rga_req *req) rga_usermemory_cheeck(&pages[0], req->src.vir_w, req->src.vir_h, req->src.format, 1); #endif - } - } - else { - MMU_p = MMU_Base; - - if(req->src.yrgb_addr == (unsigned long)rga_service.pre_scale_buf) { - for(i=0; immu_info.mmu_flag >> 10) & 1) { - if (req->sg_dst) { - ret = rga_MapION(req->sg_dst, &MMU_Base[SrcMemSize], DstMemSize, req->line_draw_info.line_width); - } - else { - ret = rga_MapUserMemory(&pages[SrcMemSize], &MMU_Base[SrcMemSize], DstStart, DstMemSize); - if (ret < 0) { - pr_err("rga map dst memory failed\n"); - status = ret; - break; - } + } + } + else { + MMU_p = MMU_Base; + + if(req->src.yrgb_addr == (unsigned long)rga_service.pre_scale_buf) { + for(i=0; immu_info.mmu_flag >> 10) & 1) { + if (req->sg_dst) { + ret = rga_MapION(req->sg_dst, &MMU_Base[SrcMemSize], DstMemSize, req->line_draw_info.line_width); + } + else { + ret = rga_MapUserMemory(&pages[SrcMemSize], &MMU_Base[SrcMemSize], DstStart, DstMemSize); + if (ret < 0) { + pr_err("rga map dst memory failed\n"); + status = ret; + break; + } #if RGA_DEBUGFS if (RGA_CHECK_MODE) rga_usermemory_cheeck(&pages[0], req->src.vir_w, req->src.vir_h, req->src.format, 2); #endif - } - } - else { - MMU_p = MMU_Base + SrcMemSize; - for(i=0; immu_info.base_addr = (unsigned long)MMU_Base_phys >> 2; - - uv_size = (req->src.uv_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT; - v_size = (req->src.v_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT; - - req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)); - req->src.uv_addr = (req->src.uv_addr & (~PAGE_MASK)) | (uv_size << PAGE_SHIFT); - req->src.v_addr = (req->src.v_addr & (~PAGE_MASK)) | (v_size << PAGE_SHIFT); - - uv_size = (req->dst.uv_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT; - - req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | (SrcMemSize << PAGE_SHIFT); - req->dst.uv_addr = (req->dst.uv_addr & (~PAGE_MASK)) | ((SrcMemSize + uv_size) << PAGE_SHIFT); - - /* flush data to DDR */ + } + } + else { + MMU_p = MMU_Base + SrcMemSize; + for(i=0; immu_info.base_addr = (unsigned long)MMU_Base_phys >> 2; + + uv_size = (req->src.uv_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT; + v_size = (req->src.v_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT; + + req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)); + req->src.uv_addr = (req->src.uv_addr & (~PAGE_MASK)) | (uv_size << PAGE_SHIFT); + req->src.v_addr = (req->src.v_addr & (~PAGE_MASK)) | (v_size << PAGE_SHIFT); + + uv_size = (req->dst.uv_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT; + + req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | (SrcMemSize << PAGE_SHIFT); + req->dst.uv_addr = (req->dst.uv_addr & (~PAGE_MASK)) | ((SrcMemSize + uv_size) << PAGE_SHIFT); + + /* flush data to DDR */ rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1)); - - rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16); - reg->MMU_len = AllSize + 16; - - status = 0; - - return status; - } - while(0); - - return status; -} - -static int rga_mmu_info_color_palette_mode(struct rga_reg *reg, struct rga_req *req) -{ - int SrcMemSize, DstMemSize, CMDMemSize; - unsigned long SrcStart, DstStart, CMDStart; - struct page **pages = NULL; - uint32_t i; - uint32_t AllSize; - uint32_t *MMU_Base = NULL, *MMU_Base_phys = NULL; - uint32_t *MMU_p; - int ret, status = 0; - uint32_t stride; - - uint8_t shift; - uint16_t sw, byte_num; - - shift = 3 - (req->palette_mode & 3); - sw = req->src.vir_w; - byte_num = sw >> shift; - stride = (byte_num + 3) & (~3); - - do { - SrcMemSize = rga_mem_size_cal(req->src.yrgb_addr, stride, &SrcStart); - if(SrcMemSize == 0) { - return -EINVAL; - } - - DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr, - req->dst.format, req->dst.vir_w, req->dst.vir_h, - &DstStart); - if(DstMemSize == 0) { - return -EINVAL; - } - - CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart); - if(CMDMemSize == 0) { - return -EINVAL; - } - - SrcMemSize = (SrcMemSize + 15) & (~15); - DstMemSize = (DstMemSize + 15) & (~15); - CMDMemSize = (CMDMemSize + 15) & (~15); - - AllSize = SrcMemSize + DstMemSize + CMDMemSize; - - if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) { - pr_err("RGA Get MMU mem failed\n"); - status = RGA_MALLOC_ERROR; - break; - } - - mutex_lock(&rga_service.lock); - MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); - MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); - mutex_unlock(&rga_service.lock); - - pages = rga_mmu_buf.pages; - - /* map CMD addr */ - for(i=0; isrc.yrgb_addr < KERNEL_SPACE_VALID) { - ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize); - if (ret < 0) { - pr_err("rga map src memory failed\n"); - status = ret; - break; - } - } - else { - MMU_p = MMU_Base + CMDMemSize; - - for(i=0; isrc.yrgb_addr < KERNEL_SPACE_VALID) { - ret = rga_MapUserMemory(&pages[CMDMemSize + SrcMemSize], &MMU_Base[CMDMemSize + SrcMemSize], DstStart, DstMemSize); - if (ret < 0) { - pr_err("rga map dst memory failed\n"); - status = ret; - break; - } - } - else { - MMU_p = MMU_Base + CMDMemSize + SrcMemSize; - for(i=0; immu_info.base_addr = (virt_to_phys(MMU_Base)>>2); - req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT); - req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | ((CMDMemSize + SrcMemSize) << PAGE_SHIFT); - - /*record the malloc buf for the cmd end to release*/ - reg->MMU_base = MMU_Base; - - /* flush data to DDR */ - rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1)); - - rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16); - reg->MMU_len = AllSize + 16; - + + rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16); + reg->MMU_len = AllSize + 16; + + status = 0; + return status; - - } - while(0); - - return 0; -} - -static int rga_mmu_info_color_fill_mode(struct rga_reg *reg, struct rga_req *req) -{ - int DstMemSize; - unsigned long DstStart; - struct page **pages = NULL; - uint32_t i; - uint32_t AllSize; - uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys; - int ret; - int status; - - MMU_Base = NULL; - - do { - DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr, - req->dst.format, req->dst.vir_w, req->dst.vir_h, - &DstStart); - if(DstMemSize == 0) { - return -EINVAL; - } - - AllSize = (DstMemSize + 15) & (~15); - - pages = rga_mmu_buf.pages; - - if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) { - pr_err("RGA Get MMU mem failed\n"); - status = RGA_MALLOC_ERROR; - break; - } - - mutex_lock(&rga_service.lock); - MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); - MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); - mutex_unlock(&rga_service.lock); - - if (req->dst.yrgb_addr < KERNEL_SPACE_VALID) { - if (req->sg_dst) { - ret = rga_MapION(req->sg_dst, &MMU_Base[0], DstMemSize, req->line_draw_info.line_width); - } - else { - ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], DstStart, DstMemSize); - if (ret < 0) { - pr_err("rga map dst memory failed\n"); - status = ret; - break; - } - } - } - else { - MMU_p = MMU_Base; - for(i=0; immu_info.base_addr = ((unsigned long)(MMU_Base_phys)>>2); - req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)); - - /*record the malloc buf for the cmd end to release*/ - reg->MMU_base = MMU_Base; - - /* flush data to DDR */ + } + while(0); + + return status; +} + +static int rga_mmu_info_color_palette_mode(struct rga_reg *reg, struct rga_req *req) +{ + int SrcMemSize, DstMemSize, CMDMemSize; + unsigned long SrcStart, DstStart, CMDStart; + struct page **pages = NULL; + uint32_t i; + uint32_t AllSize; + uint32_t *MMU_Base = NULL, *MMU_Base_phys = NULL; + uint32_t *MMU_p; + int ret, status = 0; + uint32_t stride; + + uint8_t shift; + uint16_t sw, byte_num; + + shift = 3 - (req->palette_mode & 3); + sw = req->src.vir_w; + byte_num = sw >> shift; + stride = (byte_num + 3) & (~3); + + do { + SrcMemSize = rga_mem_size_cal(req->src.yrgb_addr, stride, &SrcStart); + if(SrcMemSize == 0) { + return -EINVAL; + } + + DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr, + req->dst.format, req->dst.vir_w, req->dst.vir_h, + &DstStart); + if(DstMemSize == 0) { + return -EINVAL; + } + + CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart); + if(CMDMemSize == 0) { + return -EINVAL; + } + + SrcMemSize = (SrcMemSize + 15) & (~15); + DstMemSize = (DstMemSize + 15) & (~15); + CMDMemSize = (CMDMemSize + 15) & (~15); + + AllSize = SrcMemSize + DstMemSize + CMDMemSize; + + if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) { + pr_err("RGA Get MMU mem failed\n"); + status = RGA_MALLOC_ERROR; + break; + } + + mutex_lock(&rga_service.lock); + MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); + MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); + mutex_unlock(&rga_service.lock); + + pages = rga_mmu_buf.pages; + + /* map CMD addr */ + for(i=0; isrc.yrgb_addr < KERNEL_SPACE_VALID) { + ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize); + if (ret < 0) { + pr_err("rga map src memory failed\n"); + status = ret; + break; + } + } + else { + MMU_p = MMU_Base + CMDMemSize; + + for(i=0; isrc.yrgb_addr < KERNEL_SPACE_VALID) { + ret = rga_MapUserMemory(&pages[CMDMemSize + SrcMemSize], &MMU_Base[CMDMemSize + SrcMemSize], DstStart, DstMemSize); + if (ret < 0) { + pr_err("rga map dst memory failed\n"); + status = ret; + break; + } + } + else { + MMU_p = MMU_Base + CMDMemSize + SrcMemSize; + for(i=0; immu_info.base_addr = (virt_to_phys(MMU_Base)>>2); + req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT); + req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | ((CMDMemSize + SrcMemSize) << PAGE_SHIFT); + + /*record the malloc buf for the cmd end to release*/ + reg->MMU_base = MMU_Base; + + /* flush data to DDR */ rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1)); - - rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16); - reg->MMU_len = AllSize + 16; - - return 0; - } - while(0); - - return status; -} - - -static int rga_mmu_info_line_point_drawing_mode(struct rga_reg *reg, struct rga_req *req) -{ - return 0; -} - -static int rga_mmu_info_blur_sharp_filter_mode(struct rga_reg *reg, struct rga_req *req) -{ - return 0; -} - - - -static int rga_mmu_info_pre_scale_mode(struct rga_reg *reg, struct rga_req *req) -{ - int SrcMemSize, DstMemSize; - unsigned long SrcStart, DstStart; - struct page **pages = NULL; - uint32_t i; - uint32_t AllSize; - uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys; - int ret; - int status; - uint32_t uv_size, v_size; - - MMU_Base = NULL; - - do { - /* cal src buf mmu info */ - SrcMemSize = rga_buf_size_cal(req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr, - req->src.format, req->src.vir_w, req->src.vir_h, - &SrcStart); - if(SrcMemSize == 0) { - return -EINVAL; - } - - /* cal dst buf mmu info */ - DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr, - req->dst.format, req->dst.vir_w, req->dst.vir_h, - &DstStart); - if(DstMemSize == 0) { - return -EINVAL; - } - - SrcMemSize = (SrcMemSize + 15) & (~15); - DstMemSize = (DstMemSize + 15) & (~15); - - AllSize = SrcMemSize + DstMemSize; - - pages = rga_mmu_buf.pages; - - if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) { - pr_err("RGA Get MMU mem failed\n"); - status = RGA_MALLOC_ERROR; - break; - } - - mutex_lock(&rga_service.lock); - MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); - MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); - mutex_unlock(&rga_service.lock); - - /* map src pages */ - if ((req->mmu_info.mmu_flag >> 8) & 1) { - if (req->sg_src) { - ret = rga_MapION(req->sg_src, &MMU_Base[0], SrcMemSize,req->line_draw_info.flag); - } - else { - ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], SrcStart, SrcMemSize); - if (ret < 0) { - pr_err("rga map src memory failed\n"); - status = ret; - break; - } - } - } - else { - MMU_p = MMU_Base; - - for(i=0; immu_info.mmu_flag >> 10) & 1) { - if (req->sg_dst) { - ret = rga_MapION(req->sg_dst, &MMU_Base[SrcMemSize], DstMemSize, req->line_draw_info.line_width); - } - else { - ret = rga_MapUserMemory(&pages[SrcMemSize], &MMU_Base[SrcMemSize], DstStart, DstMemSize); - if (ret < 0) { - pr_err("rga map dst memory failed\n"); - status = ret; - break; - } - } - } - else - { - /* kernel space */ - MMU_p = MMU_Base + SrcMemSize; - - if(req->dst.yrgb_addr == (unsigned long)rga_service.pre_scale_buf) { - for(i=0; immu_info.base_addr = ((unsigned long)(MMU_Base_phys)>>2); - - uv_size = (req->src.uv_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT; - v_size = (req->src.v_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT; - - req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)); - req->src.uv_addr = (req->src.uv_addr & (~PAGE_MASK)) | (uv_size << PAGE_SHIFT); - req->src.v_addr = (req->src.v_addr & (~PAGE_MASK)) | (v_size << PAGE_SHIFT); - - uv_size = (req->dst.uv_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT; - v_size = (req->dst.v_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT; - - req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | ((SrcMemSize) << PAGE_SHIFT); - req->dst.uv_addr = (req->dst.uv_addr & (~PAGE_MASK)) | ((SrcMemSize + uv_size) << PAGE_SHIFT); - req->dst.v_addr = (req->dst.v_addr & (~PAGE_MASK)) | ((SrcMemSize + v_size) << PAGE_SHIFT); - - /*record the malloc buf for the cmd end to release*/ - reg->MMU_base = MMU_Base; - - /* flush data to DDR */ + + rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16); + reg->MMU_len = AllSize + 16; + + return status; + + } + while(0); + + return 0; +} + +static int rga_mmu_info_color_fill_mode(struct rga_reg *reg, struct rga_req *req) +{ + int DstMemSize; + unsigned long DstStart; + struct page **pages = NULL; + uint32_t i; + uint32_t AllSize; + uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys; + int ret; + int status; + + MMU_Base = NULL; + + do { + DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr, + req->dst.format, req->dst.vir_w, req->dst.vir_h, + &DstStart); + if(DstMemSize == 0) { + return -EINVAL; + } + + AllSize = (DstMemSize + 15) & (~15); + + pages = rga_mmu_buf.pages; + + if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) { + pr_err("RGA Get MMU mem failed\n"); + status = RGA_MALLOC_ERROR; + break; + } + + mutex_lock(&rga_service.lock); + MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); + MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); + mutex_unlock(&rga_service.lock); + + if (req->dst.yrgb_addr < KERNEL_SPACE_VALID) { + if (req->sg_dst) { + ret = rga_MapION(req->sg_dst, &MMU_Base[0], DstMemSize, req->line_draw_info.line_width); + } + else { + ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], DstStart, DstMemSize); + if (ret < 0) { + pr_err("rga map dst memory failed\n"); + status = ret; + break; + } + } + } + else { + MMU_p = MMU_Base; + for(i=0; immu_info.base_addr = ((unsigned long)(MMU_Base_phys)>>2); + req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)); + + /*record the malloc buf for the cmd end to release*/ + reg->MMU_base = MMU_Base; + + /* flush data to DDR */ rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1)); - - rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16); - reg->MMU_len = AllSize + 16; - - return 0; - } - while(0); - - return status; -} - - -static int rga_mmu_info_update_palette_table_mode(struct rga_reg *reg, struct rga_req *req) -{ - int SrcMemSize, CMDMemSize; - unsigned long SrcStart, CMDStart; - struct page **pages = NULL; - uint32_t i; - uint32_t AllSize; - uint32_t *MMU_Base, *MMU_p; - int ret, status; - - MMU_Base = NULL; - - do { - /* cal src buf mmu info */ - SrcMemSize = rga_mem_size_cal(req->src.yrgb_addr, req->src.vir_w * req->src.vir_h, &SrcStart); - if(SrcMemSize == 0) { - return -EINVAL; - } - - /* cal cmd buf mmu info */ - CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart); - if(CMDMemSize == 0) { - return -EINVAL; - } - - AllSize = SrcMemSize + CMDMemSize; - - pages = kzalloc(AllSize * sizeof(struct page *), GFP_KERNEL); - if(pages == NULL) { - pr_err("RGA MMU malloc pages mem failed\n"); - status = RGA_MALLOC_ERROR; - break; - } - - MMU_Base = kzalloc((AllSize + 1)* sizeof(uint32_t), GFP_KERNEL); - if(pages == NULL) { - pr_err("RGA MMU malloc MMU_Base point failed\n"); - status = RGA_MALLOC_ERROR; - break; - } - - for(i=0; isrc.yrgb_addr < KERNEL_SPACE_VALID) - { - ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize); - if (ret < 0) { - pr_err("rga map src memory failed\n"); - return -EINVAL; - } - } - else - { - MMU_p = MMU_Base + CMDMemSize; - - for(i=0; immu_info.base_addr = (virt_to_phys(MMU_Base) >> 2); - - req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT); - - /*record the malloc buf for the cmd end to release*/ - reg->MMU_base = MMU_Base; - - /* flush data to DDR */ + + rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16); + reg->MMU_len = AllSize + 16; + + return 0; + } + while(0); + + return status; +} + + +static int rga_mmu_info_line_point_drawing_mode(struct rga_reg *reg, struct rga_req *req) +{ + return 0; +} + +static int rga_mmu_info_blur_sharp_filter_mode(struct rga_reg *reg, struct rga_req *req) +{ + return 0; +} + + + +static int rga_mmu_info_pre_scale_mode(struct rga_reg *reg, struct rga_req *req) +{ + int SrcMemSize, DstMemSize; + unsigned long SrcStart, DstStart; + struct page **pages = NULL; + uint32_t i; + uint32_t AllSize; + uint32_t *MMU_Base, *MMU_p, *MMU_Base_phys; + int ret; + int status; + uint32_t uv_size, v_size; + + MMU_Base = NULL; + + do { + /* cal src buf mmu info */ + SrcMemSize = rga_buf_size_cal(req->src.yrgb_addr, req->src.uv_addr, req->src.v_addr, + req->src.format, req->src.vir_w, req->src.vir_h, + &SrcStart); + if(SrcMemSize == 0) { + return -EINVAL; + } + + /* cal dst buf mmu info */ + DstMemSize = rga_buf_size_cal(req->dst.yrgb_addr, req->dst.uv_addr, req->dst.v_addr, + req->dst.format, req->dst.vir_w, req->dst.vir_h, + &DstStart); + if(DstMemSize == 0) { + return -EINVAL; + } + + SrcMemSize = (SrcMemSize + 15) & (~15); + DstMemSize = (DstMemSize + 15) & (~15); + + AllSize = SrcMemSize + DstMemSize; + + pages = rga_mmu_buf.pages; + + if (rga_mmu_buf_get_try(&rga_mmu_buf, AllSize + 16)) { + pr_err("RGA Get MMU mem failed\n"); + status = RGA_MALLOC_ERROR; + break; + } + + mutex_lock(&rga_service.lock); + MMU_Base = rga_mmu_buf.buf_virtual + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); + MMU_Base_phys = rga_mmu_buf.buf + (rga_mmu_buf.front & (rga_mmu_buf.size - 1)); + mutex_unlock(&rga_service.lock); + + /* map src pages */ + if ((req->mmu_info.mmu_flag >> 8) & 1) { + if (req->sg_src) { + ret = rga_MapION(req->sg_src, &MMU_Base[0], SrcMemSize,req->line_draw_info.flag); + } + else { + ret = rga_MapUserMemory(&pages[0], &MMU_Base[0], SrcStart, SrcMemSize); + if (ret < 0) { + pr_err("rga map src memory failed\n"); + status = ret; + break; + } + } + } + else { + MMU_p = MMU_Base; + + for(i=0; immu_info.mmu_flag >> 10) & 1) { + if (req->sg_dst) { + ret = rga_MapION(req->sg_dst, &MMU_Base[SrcMemSize], DstMemSize, req->line_draw_info.line_width); + } + else { + ret = rga_MapUserMemory(&pages[SrcMemSize], &MMU_Base[SrcMemSize], DstStart, DstMemSize); + if (ret < 0) { + pr_err("rga map dst memory failed\n"); + status = ret; + break; + } + } + } + else + { + /* kernel space */ + MMU_p = MMU_Base + SrcMemSize; + + if(req->dst.yrgb_addr == (unsigned long)rga_service.pre_scale_buf) { + for(i=0; immu_info.base_addr = ((unsigned long)(MMU_Base_phys)>>2); + + uv_size = (req->src.uv_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT; + v_size = (req->src.v_addr - (SrcStart << PAGE_SHIFT)) >> PAGE_SHIFT; + + req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)); + req->src.uv_addr = (req->src.uv_addr & (~PAGE_MASK)) | (uv_size << PAGE_SHIFT); + req->src.v_addr = (req->src.v_addr & (~PAGE_MASK)) | (v_size << PAGE_SHIFT); + + uv_size = (req->dst.uv_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT; + v_size = (req->dst.v_addr - (DstStart << PAGE_SHIFT)) >> PAGE_SHIFT; + + req->dst.yrgb_addr = (req->dst.yrgb_addr & (~PAGE_MASK)) | ((SrcMemSize) << PAGE_SHIFT); + req->dst.uv_addr = (req->dst.uv_addr & (~PAGE_MASK)) | ((SrcMemSize + uv_size) << PAGE_SHIFT); + req->dst.v_addr = (req->dst.v_addr & (~PAGE_MASK)) | ((SrcMemSize + v_size) << PAGE_SHIFT); + + /*record the malloc buf for the cmd end to release*/ + reg->MMU_base = MMU_Base; + + /* flush data to DDR */ + rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize + 1)); + + rga_mmu_buf_get(&rga_mmu_buf, AllSize + 16); + reg->MMU_len = AllSize + 16; + + return 0; + } + while(0); + + return status; +} + + +static int rga_mmu_info_update_palette_table_mode(struct rga_reg *reg, struct rga_req *req) +{ + int SrcMemSize, CMDMemSize; + unsigned long SrcStart, CMDStart; + struct page **pages = NULL; + uint32_t i; + uint32_t AllSize; + uint32_t *MMU_Base, *MMU_p; + int ret, status; + + MMU_Base = NULL; + + do { + /* cal src buf mmu info */ + SrcMemSize = rga_mem_size_cal(req->src.yrgb_addr, req->src.vir_w * req->src.vir_h, &SrcStart); + if(SrcMemSize == 0) { + return -EINVAL; + } + + /* cal cmd buf mmu info */ + CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart); + if(CMDMemSize == 0) { + return -EINVAL; + } + + AllSize = SrcMemSize + CMDMemSize; + + pages = kzalloc(AllSize * sizeof(struct page *), GFP_KERNEL); + if(pages == NULL) { + pr_err("RGA MMU malloc pages mem failed\n"); + status = RGA_MALLOC_ERROR; + break; + } + + MMU_Base = kzalloc((AllSize + 1)* sizeof(uint32_t), GFP_KERNEL); + if(pages == NULL) { + pr_err("RGA MMU malloc MMU_Base point failed\n"); + status = RGA_MALLOC_ERROR; + break; + } + + for(i=0; isrc.yrgb_addr < KERNEL_SPACE_VALID) + { + ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize); + if (ret < 0) { + pr_err("rga map src memory failed\n"); + return -EINVAL; + } + } + else + { + MMU_p = MMU_Base + CMDMemSize; + + for(i=0; immu_info.base_addr = (virt_to_phys(MMU_Base) >> 2); + + req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT); + + /*record the malloc buf for the cmd end to release*/ + reg->MMU_base = MMU_Base; + + /* flush data to DDR */ rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize)); - - - if (pages != NULL) { - /* Free the page table */ - kfree(pages); - } - - return 0; - } - while(0); - - if (pages != NULL) - kfree(pages); - - if (MMU_Base != NULL) - kfree(MMU_Base); - - return status; -} - -static int rga_mmu_info_update_patten_buff_mode(struct rga_reg *reg, struct rga_req *req) -{ - int SrcMemSize, CMDMemSize; - unsigned long SrcStart, CMDStart; - struct page **pages = NULL; - uint32_t i; - uint32_t AllSize; - uint32_t *MMU_Base, *MMU_p; - int ret, status; - - MMU_Base = MMU_p = 0; - - do - { - - /* cal src buf mmu info */ - SrcMemSize = rga_mem_size_cal(req->pat.yrgb_addr, req->pat.vir_w * req->pat.vir_h * 4, &SrcStart); - if(SrcMemSize == 0) { - return -EINVAL; - } - - /* cal cmd buf mmu info */ - CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart); - if(CMDMemSize == 0) { - return -EINVAL; - } - - AllSize = SrcMemSize + CMDMemSize; - - pages = kzalloc(AllSize * sizeof(struct page *), GFP_KERNEL); - if(pages == NULL) { - pr_err("RGA MMU malloc pages mem failed\n"); - status = RGA_MALLOC_ERROR; - break; - } - - MMU_Base = kzalloc(AllSize * sizeof(uint32_t), GFP_KERNEL); - if(MMU_Base == NULL) { - pr_err("RGA MMU malloc MMU_Base point failed\n"); - status = RGA_MALLOC_ERROR; - break; - } - - for(i=0; isrc.yrgb_addr < KERNEL_SPACE_VALID) - { - ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize); - if (ret < 0) { - pr_err("rga map src memory failed\n"); - status = ret; - break; - } - } - else - { - MMU_p = MMU_Base + CMDMemSize; - - for(i=0; immu_info.base_addr = (virt_to_phys(MMU_Base) >> 2); - - req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT); - - /*record the malloc buf for the cmd end to release*/ - reg->MMU_base = MMU_Base; - - /* flush data to DDR */ + + + if (pages != NULL) { + /* Free the page table */ + kfree(pages); + } + + return 0; + } + while(0); + + if (pages != NULL) + kfree(pages); + + if (MMU_Base != NULL) + kfree(MMU_Base); + + return status; +} + +static int rga_mmu_info_update_patten_buff_mode(struct rga_reg *reg, struct rga_req *req) +{ + int SrcMemSize, CMDMemSize; + unsigned long SrcStart, CMDStart; + struct page **pages = NULL; + uint32_t i; + uint32_t AllSize; + uint32_t *MMU_Base, *MMU_p; + int ret, status; + + MMU_Base = MMU_p = 0; + + do + { + + /* cal src buf mmu info */ + SrcMemSize = rga_mem_size_cal(req->pat.yrgb_addr, req->pat.vir_w * req->pat.vir_h * 4, &SrcStart); + if(SrcMemSize == 0) { + return -EINVAL; + } + + /* cal cmd buf mmu info */ + CMDMemSize = rga_mem_size_cal((unsigned long)rga_service.cmd_buff, RGA_CMD_BUF_SIZE, &CMDStart); + if(CMDMemSize == 0) { + return -EINVAL; + } + + AllSize = SrcMemSize + CMDMemSize; + + pages = kzalloc(AllSize * sizeof(struct page *), GFP_KERNEL); + if(pages == NULL) { + pr_err("RGA MMU malloc pages mem failed\n"); + status = RGA_MALLOC_ERROR; + break; + } + + MMU_Base = kzalloc(AllSize * sizeof(uint32_t), GFP_KERNEL); + if(MMU_Base == NULL) { + pr_err("RGA MMU malloc MMU_Base point failed\n"); + status = RGA_MALLOC_ERROR; + break; + } + + for(i=0; isrc.yrgb_addr < KERNEL_SPACE_VALID) + { + ret = rga_MapUserMemory(&pages[CMDMemSize], &MMU_Base[CMDMemSize], SrcStart, SrcMemSize); + if (ret < 0) { + pr_err("rga map src memory failed\n"); + status = ret; + break; + } + } + else + { + MMU_p = MMU_Base + CMDMemSize; + + for(i=0; immu_info.base_addr = (virt_to_phys(MMU_Base) >> 2); + + req->src.yrgb_addr = (req->src.yrgb_addr & (~PAGE_MASK)) | (CMDMemSize << PAGE_SHIFT); + + /*record the malloc buf for the cmd end to release*/ + reg->MMU_base = MMU_Base; + + /* flush data to DDR */ rga_dma_flush_range(MMU_Base, (MMU_Base + AllSize)); - - if (pages != NULL) { - /* Free the page table */ - kfree(pages); - } - - return 0; - - } - while(0); - - if (pages != NULL) - kfree(pages); - - if (MMU_Base != NULL) - kfree(MMU_Base); - - return status; -} - -int rga_set_mmu_info(struct rga_reg *reg, struct rga_req *req) -{ - int ret; - - switch (req->render_mode) { - case bitblt_mode : - ret = rga_mmu_info_BitBlt_mode(reg, req); - break; - case color_palette_mode : - ret = rga_mmu_info_color_palette_mode(reg, req); - break; - case color_fill_mode : - ret = rga_mmu_info_color_fill_mode(reg, req); - break; - case line_point_drawing_mode : - ret = rga_mmu_info_line_point_drawing_mode(reg, req); - break; - case blur_sharp_filter_mode : - ret = rga_mmu_info_blur_sharp_filter_mode(reg, req); - break; - case pre_scaling_mode : - ret = rga_mmu_info_pre_scale_mode(reg, req); - break; - case update_palette_table_mode : - ret = rga_mmu_info_update_palette_table_mode(reg, req); - break; - case update_patten_buff_mode : - ret = rga_mmu_info_update_patten_buff_mode(reg, req); - break; - default : - ret = -1; - break; - } - - return ret; -} - + + if (pages != NULL) { + /* Free the page table */ + kfree(pages); + } + + return 0; + + } + while(0); + + if (pages != NULL) + kfree(pages); + + if (MMU_Base != NULL) + kfree(MMU_Base); + + return status; +} + +int rga_set_mmu_info(struct rga_reg *reg, struct rga_req *req) +{ + int ret; + + switch (req->render_mode) { + case bitblt_mode : + ret = rga_mmu_info_BitBlt_mode(reg, req); + break; + case color_palette_mode : + ret = rga_mmu_info_color_palette_mode(reg, req); + break; + case color_fill_mode : + ret = rga_mmu_info_color_fill_mode(reg, req); + break; + case line_point_drawing_mode : + ret = rga_mmu_info_line_point_drawing_mode(reg, req); + break; + case blur_sharp_filter_mode : + ret = rga_mmu_info_blur_sharp_filter_mode(reg, req); + break; + case pre_scaling_mode : + ret = rga_mmu_info_pre_scale_mode(reg, req); + break; + case update_palette_table_mode : + ret = rga_mmu_info_update_palette_table_mode(reg, req); + break; + case update_patten_buff_mode : + ret = rga_mmu_info_update_patten_buff_mode(reg, req); + break; + default : + ret = -1; + break; + } + + return ret; +} + diff --git a/drivers/video/rockchip/rga/rga_mmu_info.h b/drivers/video/rockchip/rga/rga_mmu_info.h index 3e70894c7ee7..ff57089b955a 100644 --- a/drivers/video/rockchip/rga/rga_mmu_info.h +++ b/drivers/video/rockchip/rga/rga_mmu_info.h @@ -1,24 +1,24 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __RGA_MMU_INFO_H__ -#define __RGA_MMU_INFO_H__ - +#ifndef __RGA_MMU_INFO_H__ +#define __RGA_MMU_INFO_H__ + #include "rga.h" #include "RGA_API.h" - -#ifndef MIN -#define MIN(X, Y) ((X)<(Y)?(X):(Y)) -#endif - -#ifndef MAX -#define MAX(X, Y) ((X)>(Y)?(X):(Y)) -#endif + +#ifndef MIN +#define MIN(X, Y) ((X)<(Y)?(X):(Y)) +#endif + +#ifndef MAX +#define MAX(X, Y) ((X)>(Y)?(X):(Y)) +#endif extern struct rga_drvdata *drvdata; void rga_dma_flush_range(void *pstart, void *pend); -int rga_set_mmu_info(struct rga_reg *reg, struct rga_req *req); - - -#endif - - +int rga_set_mmu_info(struct rga_reg *reg, struct rga_req *req); + + +#endif + + diff --git a/drivers/video/rockchip/rga/rga_reg_info.c b/drivers/video/rockchip/rga/rga_reg_info.c index 94a6305b870b..563eaab7bb9a 100644 --- a/drivers/video/rockchip/rga/rga_reg_info.c +++ b/drivers/video/rockchip/rga/rga_reg_info.c @@ -1,708 +1,708 @@ /* SPDX-License-Identifier: GPL-2.0 */ - -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include - -#include "rga_reg_info.h" -#include "rga_rop.h" -#include "rga.h" - - -/************************************************************* -Func: - RGA_pixel_width_init -Description: - select pixel_width form data format -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ -unsigned char -RGA_pixel_width_init(unsigned int format) -{ - unsigned char pixel_width; - - pixel_width = 0; - - switch(format) - { - /* RGB FORMAT */ - case RK_FORMAT_RGBA_8888 : pixel_width = 4; break; - case RK_FORMAT_RGBX_8888 : pixel_width = 4; break; - case RK_FORMAT_RGB_888 : pixel_width = 3; break; - case RK_FORMAT_BGRA_8888 : pixel_width = 4; break; - case RK_FORMAT_RGB_565 : pixel_width = 2; break; - case RK_FORMAT_RGBA_5551 : pixel_width = 2; break; - case RK_FORMAT_RGBA_4444 : pixel_width = 2; break; - case RK_FORMAT_BGR_888 : pixel_width = 3; break; - - /* YUV FORMAT */ - case RK_FORMAT_YCbCr_422_SP : pixel_width = 1; break; - case RK_FORMAT_YCbCr_422_P : pixel_width = 1; break; - case RK_FORMAT_YCbCr_420_SP : pixel_width = 1; break; - case RK_FORMAT_YCbCr_420_P : pixel_width = 1; break; - case RK_FORMAT_YCrCb_422_SP : pixel_width = 1; break; - case RK_FORMAT_YCrCb_422_P : pixel_width = 1; break; - case RK_FORMAT_YCrCb_420_SP : pixel_width = 1; break; - case RK_FORMAT_YCrCb_420_P : pixel_width = 1; break; - //case default : pixel_width = 0; break; - } - - return pixel_width; -} - -/************************************************************* -Func: - dst_ctrl_cal -Description: - calculate dst act window position / width / height - and set the tile struct -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ + +#include "rga_reg_info.h" +#include "rga_rop.h" +#include "rga.h" + + +/************************************************************* +Func: + RGA_pixel_width_init +Description: + select pixel_width form data format +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ +unsigned char +RGA_pixel_width_init(unsigned int format) +{ + unsigned char pixel_width; + + pixel_width = 0; + + switch(format) + { + /* RGB FORMAT */ + case RK_FORMAT_RGBA_8888 : pixel_width = 4; break; + case RK_FORMAT_RGBX_8888 : pixel_width = 4; break; + case RK_FORMAT_RGB_888 : pixel_width = 3; break; + case RK_FORMAT_BGRA_8888 : pixel_width = 4; break; + case RK_FORMAT_RGB_565 : pixel_width = 2; break; + case RK_FORMAT_RGBA_5551 : pixel_width = 2; break; + case RK_FORMAT_RGBA_4444 : pixel_width = 2; break; + case RK_FORMAT_BGR_888 : pixel_width = 3; break; + + /* YUV FORMAT */ + case RK_FORMAT_YCbCr_422_SP : pixel_width = 1; break; + case RK_FORMAT_YCbCr_422_P : pixel_width = 1; break; + case RK_FORMAT_YCbCr_420_SP : pixel_width = 1; break; + case RK_FORMAT_YCbCr_420_P : pixel_width = 1; break; + case RK_FORMAT_YCrCb_422_SP : pixel_width = 1; break; + case RK_FORMAT_YCrCb_422_P : pixel_width = 1; break; + case RK_FORMAT_YCrCb_420_SP : pixel_width = 1; break; + case RK_FORMAT_YCrCb_420_P : pixel_width = 1; break; + //case default : pixel_width = 0; break; + } + + return pixel_width; +} + +/************************************************************* +Func: + dst_ctrl_cal +Description: + calculate dst act window position / width / height + and set the tile struct +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ static void -dst_ctrl_cal(const struct rga_req *msg, TILE_INFO *tile) -{ - u32 width = msg->dst.act_w; - u32 height = msg->dst.act_h; - s32 xoff = msg->dst.x_offset; - s32 yoff = msg->dst.y_offset; - - s32 x0, y0, x1, y1, x2, y2; - s32 x00,y00,x10,y10,x20,y20; - s32 xx, xy, yx, yy; - s32 pos[8]; - - s32 xmax, xmin, ymax, ymin; - - s32 sina = msg->sina; /* 16.16 */ - s32 cosa = msg->cosa; /* 16.16 */ - - xmax = xmin = ymax = ymin = 0; - - if((msg->rotate_mode == 0)||(msg->rotate_mode == 2)||(msg->rotate_mode == 3)) - { - pos[0] = xoff; - pos[1] = yoff; - - pos[2] = xoff; - pos[3] = yoff + height - 1; - - pos[4] = xoff + width - 1; - pos[5] = yoff + height - 1; - - pos[6] = xoff + width - 1; - pos[7] = yoff; - - xmax = MIN(MAX(MAX(MAX(pos[0], pos[2]), pos[4]), pos[6]), msg->clip.xmax); - xmin = MAX(MIN(MIN(MIN(pos[0], pos[2]), pos[4]), pos[6]), msg->clip.xmin); - - ymax = MIN(MAX(MAX(MAX(pos[1], pos[3]), pos[5]), pos[7]), msg->clip.ymax); - ymin = MAX(MIN(MIN(MIN(pos[1], pos[3]), pos[5]), pos[7]), msg->clip.ymin); - - //printk("xmax = %d, xmin = %d, ymin = %d, ymax = %d\n", xmax, xmin, ymin, ymax); - } - else if(msg->rotate_mode == 1) - { - if((sina == 0) || (cosa == 0)) - { - if((sina == 0) && (cosa == -65536)) - { - /* 180 */ - pos[0] = xoff - width + 1; - pos[1] = yoff - height + 1; - - pos[2] = xoff - width + 1; - pos[3] = yoff; - - pos[4] = xoff; - pos[5] = yoff; - - pos[6] = xoff; - pos[7] = yoff - height + 1; - } - else if((cosa == 0)&&(sina == 65536)) - { - /* 90 */ - pos[0] = xoff - height + 1; - pos[1] = yoff; - - pos[2] = xoff - height + 1; - pos[3] = yoff + width - 1; - - pos[4] = xoff; - pos[5] = yoff + width - 1; - - pos[6] = xoff; - pos[7] = yoff; - } - else if((cosa == 0)&&(sina == -65536)) - { - /* 270 */ - pos[0] = xoff; - pos[1] = yoff - width + 1; - - pos[2] = xoff; - pos[3] = yoff; - - pos[4] = xoff + height - 1; - pos[5] = yoff; - - pos[6] = xoff + height - 1; - pos[7] = yoff - width + 1; - } - else - { - /* 0 */ - pos[0] = xoff; - pos[1] = yoff; - - pos[2] = xoff; - pos[3] = yoff + height - 1; - - pos[4] = xoff + width - 1; - pos[5] = yoff + height - 1; - - pos[6] = xoff + width - 1; - pos[7] = yoff; - } - - xmax = MIN(MAX(MAX(MAX(pos[0], pos[2]), pos[4]), pos[6]), msg->clip.xmax); - xmin = MAX(MIN(MIN(MIN(pos[0], pos[2]), pos[4]), pos[6]), msg->clip.xmin); - - ymax = MIN(MAX(MAX(MAX(pos[1], pos[3]), pos[5]), pos[7]), msg->clip.ymax); - ymin = MAX(MIN(MIN(MIN(pos[1], pos[3]), pos[5]), pos[7]), msg->clip.ymin); - } - else - { - xx = msg->cosa; - xy = msg->sina; - yx = xy; - yy = xx; - - x0 = width + xoff; - y0 = yoff; - - x1 = xoff; - y1 = height + yoff; - - x2 = width + xoff; - y2 = height + yoff; - - pos[0] = xoff; - pos[1] = yoff; - - pos[2] = x00 = (((x0 - xoff)*xx - (y0 - yoff)*xy)>>16) + xoff; - pos[3] = y00 = (((x0 - xoff)*yx + (y0 - yoff)*yy)>>16) + yoff; - - pos[4] = x10 = (((x1 - xoff)*xx - (y1 - yoff)*xy)>>16) + xoff; - pos[5] = y10 = (((x1 - xoff)*yx + (y1 - yoff)*yy)>>16) + yoff; - - pos[6] = x20 = (((x2 - xoff)*xx - (y2 - yoff)*xy)>>16) + xoff; - pos[7] = y20 = (((x2 - xoff)*yx + (y2 - yoff)*yy)>>16) + yoff; - - xmax = MAX(MAX(MAX(x00, xoff), x10), x20) + 2; - xmin = MIN(MIN(MIN(x00, xoff), x10), x20) - 1; - - ymax = MAX(MAX(MAX(y00, yoff), y10), y20) + 2; - ymin = MIN(MIN(MIN(y00, yoff), y10), y20) - 1; - - xmax = MIN(xmax, msg->clip.xmax); - xmin = MAX(xmin, msg->clip.xmin); - - ymax = MIN(ymax, msg->clip.ymax); - ymin = MAX(ymin, msg->clip.ymin); - - //printk("xmin = %d, xmax = %d, ymin = %d, ymax = %d\n", xmin, xmax, ymin, ymax); - } - } - - if ((xmax < xmin) || (ymax < ymin)) { - xmin = xmax; - ymin = ymax; - } - - if ((xmin >= msg->dst.vir_w)||(xmax < 0)||(ymin >= msg->dst.vir_h)||(ymax < 0)) { - xmin = xmax = ymin = ymax = 0; - } - - //printk("xmin = %d, xmax = %d, ymin = %d, ymax = %d\n", xmin, xmax, ymin, ymax); - - tile->dst_ctrl.w = (xmax - xmin); - tile->dst_ctrl.h = (ymax - ymin); - tile->dst_ctrl.x_off = xmin; - tile->dst_ctrl.y_off = ymin; - - //printk("tile->dst_ctrl.w = %x, tile->dst_ctrl.h = %x\n", tile->dst_ctrl.w, tile->dst_ctrl.h); - - tile->tile_x_num = (xmax - xmin + 1 + 7)>>3; - tile->tile_y_num = (ymax - ymin + 1 + 7)>>3; - - tile->dst_x_tmp = xmin - msg->dst.x_offset; - tile->dst_y_tmp = ymin - msg->dst.y_offset; -} - -/************************************************************* -Func: - src_tile_info_cal -Description: - calculate src remap window position / width / height - and set the tile struct -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ - +dst_ctrl_cal(const struct rga_req *msg, TILE_INFO *tile) +{ + u32 width = msg->dst.act_w; + u32 height = msg->dst.act_h; + s32 xoff = msg->dst.x_offset; + s32 yoff = msg->dst.y_offset; + + s32 x0, y0, x1, y1, x2, y2; + s32 x00,y00,x10,y10,x20,y20; + s32 xx, xy, yx, yy; + s32 pos[8]; + + s32 xmax, xmin, ymax, ymin; + + s32 sina = msg->sina; /* 16.16 */ + s32 cosa = msg->cosa; /* 16.16 */ + + xmax = xmin = ymax = ymin = 0; + + if((msg->rotate_mode == 0)||(msg->rotate_mode == 2)||(msg->rotate_mode == 3)) + { + pos[0] = xoff; + pos[1] = yoff; + + pos[2] = xoff; + pos[3] = yoff + height - 1; + + pos[4] = xoff + width - 1; + pos[5] = yoff + height - 1; + + pos[6] = xoff + width - 1; + pos[7] = yoff; + + xmax = MIN(MAX(MAX(MAX(pos[0], pos[2]), pos[4]), pos[6]), msg->clip.xmax); + xmin = MAX(MIN(MIN(MIN(pos[0], pos[2]), pos[4]), pos[6]), msg->clip.xmin); + + ymax = MIN(MAX(MAX(MAX(pos[1], pos[3]), pos[5]), pos[7]), msg->clip.ymax); + ymin = MAX(MIN(MIN(MIN(pos[1], pos[3]), pos[5]), pos[7]), msg->clip.ymin); + + //printk("xmax = %d, xmin = %d, ymin = %d, ymax = %d\n", xmax, xmin, ymin, ymax); + } + else if(msg->rotate_mode == 1) + { + if((sina == 0) || (cosa == 0)) + { + if((sina == 0) && (cosa == -65536)) + { + /* 180 */ + pos[0] = xoff - width + 1; + pos[1] = yoff - height + 1; + + pos[2] = xoff - width + 1; + pos[3] = yoff; + + pos[4] = xoff; + pos[5] = yoff; + + pos[6] = xoff; + pos[7] = yoff - height + 1; + } + else if((cosa == 0)&&(sina == 65536)) + { + /* 90 */ + pos[0] = xoff - height + 1; + pos[1] = yoff; + + pos[2] = xoff - height + 1; + pos[3] = yoff + width - 1; + + pos[4] = xoff; + pos[5] = yoff + width - 1; + + pos[6] = xoff; + pos[7] = yoff; + } + else if((cosa == 0)&&(sina == -65536)) + { + /* 270 */ + pos[0] = xoff; + pos[1] = yoff - width + 1; + + pos[2] = xoff; + pos[3] = yoff; + + pos[4] = xoff + height - 1; + pos[5] = yoff; + + pos[6] = xoff + height - 1; + pos[7] = yoff - width + 1; + } + else + { + /* 0 */ + pos[0] = xoff; + pos[1] = yoff; + + pos[2] = xoff; + pos[3] = yoff + height - 1; + + pos[4] = xoff + width - 1; + pos[5] = yoff + height - 1; + + pos[6] = xoff + width - 1; + pos[7] = yoff; + } + + xmax = MIN(MAX(MAX(MAX(pos[0], pos[2]), pos[4]), pos[6]), msg->clip.xmax); + xmin = MAX(MIN(MIN(MIN(pos[0], pos[2]), pos[4]), pos[6]), msg->clip.xmin); + + ymax = MIN(MAX(MAX(MAX(pos[1], pos[3]), pos[5]), pos[7]), msg->clip.ymax); + ymin = MAX(MIN(MIN(MIN(pos[1], pos[3]), pos[5]), pos[7]), msg->clip.ymin); + } + else + { + xx = msg->cosa; + xy = msg->sina; + yx = xy; + yy = xx; + + x0 = width + xoff; + y0 = yoff; + + x1 = xoff; + y1 = height + yoff; + + x2 = width + xoff; + y2 = height + yoff; + + pos[0] = xoff; + pos[1] = yoff; + + pos[2] = x00 = (((x0 - xoff)*xx - (y0 - yoff)*xy)>>16) + xoff; + pos[3] = y00 = (((x0 - xoff)*yx + (y0 - yoff)*yy)>>16) + yoff; + + pos[4] = x10 = (((x1 - xoff)*xx - (y1 - yoff)*xy)>>16) + xoff; + pos[5] = y10 = (((x1 - xoff)*yx + (y1 - yoff)*yy)>>16) + yoff; + + pos[6] = x20 = (((x2 - xoff)*xx - (y2 - yoff)*xy)>>16) + xoff; + pos[7] = y20 = (((x2 - xoff)*yx + (y2 - yoff)*yy)>>16) + yoff; + + xmax = MAX(MAX(MAX(x00, xoff), x10), x20) + 2; + xmin = MIN(MIN(MIN(x00, xoff), x10), x20) - 1; + + ymax = MAX(MAX(MAX(y00, yoff), y10), y20) + 2; + ymin = MIN(MIN(MIN(y00, yoff), y10), y20) - 1; + + xmax = MIN(xmax, msg->clip.xmax); + xmin = MAX(xmin, msg->clip.xmin); + + ymax = MIN(ymax, msg->clip.ymax); + ymin = MAX(ymin, msg->clip.ymin); + + //printk("xmin = %d, xmax = %d, ymin = %d, ymax = %d\n", xmin, xmax, ymin, ymax); + } + } + + if ((xmax < xmin) || (ymax < ymin)) { + xmin = xmax; + ymin = ymax; + } + + if ((xmin >= msg->dst.vir_w)||(xmax < 0)||(ymin >= msg->dst.vir_h)||(ymax < 0)) { + xmin = xmax = ymin = ymax = 0; + } + + //printk("xmin = %d, xmax = %d, ymin = %d, ymax = %d\n", xmin, xmax, ymin, ymax); + + tile->dst_ctrl.w = (xmax - xmin); + tile->dst_ctrl.h = (ymax - ymin); + tile->dst_ctrl.x_off = xmin; + tile->dst_ctrl.y_off = ymin; + + //printk("tile->dst_ctrl.w = %x, tile->dst_ctrl.h = %x\n", tile->dst_ctrl.w, tile->dst_ctrl.h); + + tile->tile_x_num = (xmax - xmin + 1 + 7)>>3; + tile->tile_y_num = (ymax - ymin + 1 + 7)>>3; + + tile->dst_x_tmp = xmin - msg->dst.x_offset; + tile->dst_y_tmp = ymin - msg->dst.y_offset; +} + +/************************************************************* +Func: + src_tile_info_cal +Description: + calculate src remap window position / width / height + and set the tile struct +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ + static void -src_tile_info_cal(const struct rga_req *msg, TILE_INFO *tile) -{ - s32 x0, x1, x2, x3, y0, y1, y2, y3; - - int64_t xx, xy, yx, yy; - - int64_t pos[8]; - int64_t epos[8]; - - int64_t x_dx, x_dy, y_dx, y_dy; - int64_t x_temp_start, y_temp_start; - int64_t xmax, xmin, ymax, ymin; - - int64_t t_xoff, t_yoff; - - xx = tile->matrix[0]; /* 32.32 */ - xy = tile->matrix[1]; /* 32.32 */ - yx = tile->matrix[2]; /* 32.32 */ - yy = tile->matrix[3]; /* 32.32 */ - - if(msg->rotate_mode == 1) - { - x0 = tile->dst_x_tmp; - y0 = tile->dst_y_tmp; - - x1 = x0; - y1 = y0 + 8; - - x2 = x0 + 8; - y2 = y0 + 8; - - x3 = x0 + 8; - y3 = y0; - - pos[0] = (x0*xx + y0*yx); - pos[1] = (x0*xy + y0*yy); - - pos[2] = (x1*xx + y1*yx); - pos[3] = (x1*xy + y1*yy); - - pos[4] = (x2*xx + y2*yx); - pos[5] = (x2*xy + y2*yy); - - pos[6] = (x3*xx + y3*yx); - pos[7] = (x3*xy + y3*yy); - - y1 = y0 + 7; - x2 = x0 + 7; - y2 = y0 + 7; - x3 = x0 + 7; - - epos[0] = pos[0]; - epos[1] = pos[1]; - - epos[2] = (x1*xx + y1*yx); - epos[3] = (x1*xy + y1*yy); - - epos[4] = (x2*xx + y2*yx); - epos[5] = (x2*xy + y2*yy); - - epos[6] = (x3*xx + y3*yx); - epos[7] = (x3*xy + y3*yy); - - x_dx = pos[6] - pos[0]; - x_dy = pos[7] - pos[1]; - - y_dx = pos[2] - pos[0]; - y_dy = pos[3] - pos[1]; - - tile->x_dx = (s32)(x_dx >> 22 ); - tile->x_dy = (s32)(x_dy >> 22 ); - tile->y_dx = (s32)(y_dx >> 22 ); - tile->y_dy = (s32)(y_dy >> 22 ); - - x_temp_start = x0*xx + y0*yx; - y_temp_start = x0*xy + y0*yy; - - xmax = (MAX(MAX(MAX(epos[0], epos[2]), epos[4]), epos[6])); - xmin = (MIN(MIN(MIN(epos[0], epos[2]), epos[4]), epos[6])); - - ymax = (MAX(MAX(MAX(epos[1], epos[3]), epos[5]), epos[7])); - ymin = (MIN(MIN(MIN(epos[1], epos[3]), epos[5]), epos[7])); - - t_xoff = (x_temp_start - xmin)>>18; - t_yoff = (y_temp_start - ymin)>>18; - - tile->tile_xoff = (s32)t_xoff; - tile->tile_yoff = (s32)t_yoff; - - tile->tile_w = (u16)((xmax - xmin)>>21); //.11 - tile->tile_h = (u16)((ymax - ymin)>>21); //.11 - - tile->tile_start_x_coor = (s16)(xmin>>29); //.3 - tile->tile_start_y_coor = (s16)(ymin>>29); //.3 - } - else if (msg->rotate_mode == 2) - { - tile->x_dx = (s32)((8*xx)>>22); - tile->x_dy = 0; - tile->y_dx = 0; - tile->y_dy = (s32)((8*yy)>>22); - - tile->tile_w = ABS((s32)((7*xx)>>21)); - tile->tile_h = ABS((s32)((7*yy)>>21)); - - tile->tile_xoff = ABS((s32)((7*xx)>>18)); - tile->tile_yoff = 0; - - tile->tile_start_x_coor = (((msg->src.act_w - 1)<<11) - (tile->tile_w))>>8; - tile->tile_start_y_coor = 0; - } - else if (msg->rotate_mode == 3) - { - tile->x_dx = (s32)((8*xx)>>22); - tile->x_dy = 0; - tile->y_dx = 0; - tile->y_dy = (s32)((8*yy)>>22); - - tile->tile_w = ABS((s32)((7*xx)>>21)); - tile->tile_h = ABS((s32)((7*yy)>>21)); - - tile->tile_xoff = 0; - tile->tile_yoff = ABS((s32)((7*yy)>>18)); - - tile->tile_start_x_coor = 0; - tile->tile_start_y_coor = (((msg->src.act_h - 1)<<11) - (tile->tile_h))>>8; - } - - if ((msg->scale_mode == 2)||(msg->alpha_rop_flag >> 7)) - { - tile->tile_start_x_coor -= (1<<3); - tile->tile_start_y_coor -= (1<<3); - tile->tile_w += (2 << 11); - tile->tile_h += (2 << 11); - tile->tile_xoff += (1<<14); - tile->tile_yoff += (1<<14); - } -} - - -/************************************************************* -Func: - RGA_set_mode_ctrl -Description: - fill mode ctrl reg info -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ - +src_tile_info_cal(const struct rga_req *msg, TILE_INFO *tile) +{ + s32 x0, x1, x2, x3, y0, y1, y2, y3; + + int64_t xx, xy, yx, yy; + + int64_t pos[8]; + int64_t epos[8]; + + int64_t x_dx, x_dy, y_dx, y_dy; + int64_t x_temp_start, y_temp_start; + int64_t xmax, xmin, ymax, ymin; + + int64_t t_xoff, t_yoff; + + xx = tile->matrix[0]; /* 32.32 */ + xy = tile->matrix[1]; /* 32.32 */ + yx = tile->matrix[2]; /* 32.32 */ + yy = tile->matrix[3]; /* 32.32 */ + + if(msg->rotate_mode == 1) + { + x0 = tile->dst_x_tmp; + y0 = tile->dst_y_tmp; + + x1 = x0; + y1 = y0 + 8; + + x2 = x0 + 8; + y2 = y0 + 8; + + x3 = x0 + 8; + y3 = y0; + + pos[0] = (x0*xx + y0*yx); + pos[1] = (x0*xy + y0*yy); + + pos[2] = (x1*xx + y1*yx); + pos[3] = (x1*xy + y1*yy); + + pos[4] = (x2*xx + y2*yx); + pos[5] = (x2*xy + y2*yy); + + pos[6] = (x3*xx + y3*yx); + pos[7] = (x3*xy + y3*yy); + + y1 = y0 + 7; + x2 = x0 + 7; + y2 = y0 + 7; + x3 = x0 + 7; + + epos[0] = pos[0]; + epos[1] = pos[1]; + + epos[2] = (x1*xx + y1*yx); + epos[3] = (x1*xy + y1*yy); + + epos[4] = (x2*xx + y2*yx); + epos[5] = (x2*xy + y2*yy); + + epos[6] = (x3*xx + y3*yx); + epos[7] = (x3*xy + y3*yy); + + x_dx = pos[6] - pos[0]; + x_dy = pos[7] - pos[1]; + + y_dx = pos[2] - pos[0]; + y_dy = pos[3] - pos[1]; + + tile->x_dx = (s32)(x_dx >> 22 ); + tile->x_dy = (s32)(x_dy >> 22 ); + tile->y_dx = (s32)(y_dx >> 22 ); + tile->y_dy = (s32)(y_dy >> 22 ); + + x_temp_start = x0*xx + y0*yx; + y_temp_start = x0*xy + y0*yy; + + xmax = (MAX(MAX(MAX(epos[0], epos[2]), epos[4]), epos[6])); + xmin = (MIN(MIN(MIN(epos[0], epos[2]), epos[4]), epos[6])); + + ymax = (MAX(MAX(MAX(epos[1], epos[3]), epos[5]), epos[7])); + ymin = (MIN(MIN(MIN(epos[1], epos[3]), epos[5]), epos[7])); + + t_xoff = (x_temp_start - xmin)>>18; + t_yoff = (y_temp_start - ymin)>>18; + + tile->tile_xoff = (s32)t_xoff; + tile->tile_yoff = (s32)t_yoff; + + tile->tile_w = (u16)((xmax - xmin)>>21); //.11 + tile->tile_h = (u16)((ymax - ymin)>>21); //.11 + + tile->tile_start_x_coor = (s16)(xmin>>29); //.3 + tile->tile_start_y_coor = (s16)(ymin>>29); //.3 + } + else if (msg->rotate_mode == 2) + { + tile->x_dx = (s32)((8*xx)>>22); + tile->x_dy = 0; + tile->y_dx = 0; + tile->y_dy = (s32)((8*yy)>>22); + + tile->tile_w = ABS((s32)((7*xx)>>21)); + tile->tile_h = ABS((s32)((7*yy)>>21)); + + tile->tile_xoff = ABS((s32)((7*xx)>>18)); + tile->tile_yoff = 0; + + tile->tile_start_x_coor = (((msg->src.act_w - 1)<<11) - (tile->tile_w))>>8; + tile->tile_start_y_coor = 0; + } + else if (msg->rotate_mode == 3) + { + tile->x_dx = (s32)((8*xx)>>22); + tile->x_dy = 0; + tile->y_dx = 0; + tile->y_dy = (s32)((8*yy)>>22); + + tile->tile_w = ABS((s32)((7*xx)>>21)); + tile->tile_h = ABS((s32)((7*yy)>>21)); + + tile->tile_xoff = 0; + tile->tile_yoff = ABS((s32)((7*yy)>>18)); + + tile->tile_start_x_coor = 0; + tile->tile_start_y_coor = (((msg->src.act_h - 1)<<11) - (tile->tile_h))>>8; + } + + if ((msg->scale_mode == 2)||(msg->alpha_rop_flag >> 7)) + { + tile->tile_start_x_coor -= (1<<3); + tile->tile_start_y_coor -= (1<<3); + tile->tile_w += (2 << 11); + tile->tile_h += (2 << 11); + tile->tile_xoff += (1<<14); + tile->tile_yoff += (1<<14); + } +} + + +/************************************************************* +Func: + RGA_set_mode_ctrl +Description: + fill mode ctrl reg info +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ + static void -RGA_set_mode_ctrl(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_MODE_CTL; - u32 reg = 0; - - u8 src_rgb_pack = 0; - u8 src_format = 0; - u8 src_rb_swp = 0; - u8 src_a_swp = 0; - u8 src_cbcr_swp = 0; - - u8 dst_rgb_pack = 0; - u8 dst_format = 0; - u8 dst_rb_swp = 0; - u8 dst_a_swp = 0; - - bRGA_MODE_CTL = (u32 *)(base + RGA_MODE_CTRL_OFFSET); - - reg = ((reg & (~m_RGA_MODE_CTRL_2D_RENDER_MODE)) | (s_RGA_MODE_CTRL_2D_RENDER_MODE(msg->render_mode))); - - /* src info set */ - - if (msg->render_mode == color_palette_mode || msg->render_mode == update_palette_table_mode) - { - src_format = 0x10 | (msg->palette_mode & 3); - } - else - { - switch (msg->src.format) - { - case RK_FORMAT_RGBA_8888 : src_format = 0x0; break; - case RK_FORMAT_RGBA_4444 : src_format = 0x3; break; - case RK_FORMAT_RGBA_5551 : src_format = 0x2; break; - case RK_FORMAT_BGRA_8888 : src_format = 0x0; src_rb_swp = 0x1; break; - case RK_FORMAT_RGBX_8888 : src_format = 0x0; break; - case RK_FORMAT_RGB_565 : src_format = 0x1; break; - case RK_FORMAT_RGB_888 : src_format = 0x0; src_rgb_pack = 1; break; - case RK_FORMAT_BGR_888 : src_format = 0x0; src_rgb_pack = 1; src_rb_swp = 1; break; - - case RK_FORMAT_YCbCr_422_SP : src_format = 0x4; break; - case RK_FORMAT_YCbCr_422_P : src_format = 0x5; break; - case RK_FORMAT_YCbCr_420_SP : src_format = 0x6; break; - case RK_FORMAT_YCbCr_420_P : src_format = 0x7; break; - - case RK_FORMAT_YCrCb_422_SP : src_format = 0x4; src_cbcr_swp = 1; break; - case RK_FORMAT_YCrCb_422_P : src_format = 0x5; src_cbcr_swp = 1; break; - case RK_FORMAT_YCrCb_420_SP : src_format = 0x6; src_cbcr_swp = 1; break; - case RK_FORMAT_YCrCb_420_P : src_format = 0x7; src_cbcr_swp = 1; break; - } - } - - src_a_swp = msg->src.alpha_swap & 1; - - reg = ((reg & (~m_RGA_MODE_CTRL_SRC_RGB_PACK)) | (s_RGA_MODE_CTRL_SRC_RGB_PACK(src_rgb_pack))); - reg = ((reg & (~m_RGA_MODE_CTRL_SRC_FORMAT)) | (s_RGA_MODE_CTRL_SRC_FORMAT(src_format))); - reg = ((reg & (~m_RGA_MODE_CTRL_SRC_RB_SWAP)) | (s_RGA_MODE_CTRL_SRC_RB_SWAP(src_rb_swp))); - reg = ((reg & (~m_RGA_MODE_CTRL_SRC_ALPHA_SWAP)) | (s_RGA_MODE_CTRL_SRC_ALPHA_SWAP(src_a_swp))); - reg = ((reg & (~m_RGA_MODE_CTRL_SRC_UV_SWAP_MODE )) | (s_RGA_MODE_CTRL_SRC_UV_SWAP_MODE (src_cbcr_swp))); - - - /* YUV2RGB MODE */ - reg = ((reg & (~m_RGA_MODE_CTRL_YUV2RGB_CON_MODE)) | (s_RGA_MODE_CTRL_YUV2RGB_CON_MODE(msg->yuv2rgb_mode))); - - /* ROTATE MODE */ - reg = ((reg & (~m_RGA_MODE_CTRL_ROTATE_MODE)) | (s_RGA_MODE_CTRL_ROTATE_MODE(msg->rotate_mode))); - - /* SCALE MODE */ - reg = ((reg & (~m_RGA_MODE_CTRL_SCALE_MODE)) | (s_RGA_MODE_CTRL_SCALE_MODE(msg->scale_mode))); - - /* COLOR FILL MODE */ - reg = ((reg & (~m_RGA_MODE_CTRL_PAT_SEL)) | (s_RGA_MODE_CTRL_PAT_SEL(msg->color_fill_mode))); - - - if ((msg->render_mode == update_palette_table_mode)||(msg->render_mode == update_patten_buff_mode)) - { - dst_format = msg->pat.format; - } - else - { - dst_format = (u8)msg->dst.format; - } - - /* dst info set */ - switch (dst_format) - { - case RK_FORMAT_BGRA_8888 : dst_format = 0x0; dst_rb_swp = 0x1; break; - case RK_FORMAT_RGBA_4444 : dst_format = 0x3; break; - case RK_FORMAT_RGBA_5551 : dst_format = 0x2; break; - case RK_FORMAT_RGBA_8888 : dst_format = 0x0; break; - case RK_FORMAT_RGB_565 : dst_format = 0x1; break; - case RK_FORMAT_RGB_888 : dst_format = 0x0; dst_rgb_pack = 0x1; break; - case RK_FORMAT_BGR_888 : dst_format = 0x0; dst_rgb_pack = 0x1; dst_rb_swp = 1; break; - case RK_FORMAT_RGBX_8888 : dst_format = 0x0; break; - } - - dst_a_swp = msg->dst.alpha_swap & 1; - - reg = ((reg & (~m_RGA_MODE_CTRL_DST_FORMAT)) | (s_RGA_MODE_CTRL_DST_FORMAT(dst_format))); - reg = ((reg & (~m_RGA_MODE_CTRL_DST_RGB_PACK)) | (s_RGA_MODE_CTRL_DST_RGB_PACK(dst_rgb_pack))); - reg = ((reg & (~m_RGA_MODE_CTRL_DST_RB_SWAP)) | (s_RGA_MODE_CTRL_DST_RB_SWAP(dst_rb_swp))); - reg = ((reg & (~m_RGA_MODE_CTRL_DST_ALPHA_SWAP)) | (s_RGA_MODE_CTRL_DST_ALPHA_SWAP(dst_a_swp))); - reg = ((reg & (~m_RGA_MODE_CTRL_LUT_ENDIAN_MODE)) | (s_RGA_MODE_CTRL_LUT_ENDIAN_MODE(msg->endian_mode & 1))); - reg = ((reg & (~m_RGA_MODE_CTRL_SRC_TRANS_MODE)) | (s_RGA_MODE_CTRL_SRC_TRANS_MODE(msg->src_trans_mode))); - reg = ((reg & (~m_RGA_MODE_CTRL_ZERO_MODE_ENABLE)) | (s_RGA_MODE_CTRL_ZERO_MODE_ENABLE(msg->alpha_rop_mode >> 4))); - reg = ((reg & (~m_RGA_MODE_CTRL_DST_ALPHA_ENABLE)) | (s_RGA_MODE_CTRL_DST_ALPHA_ENABLE(msg->alpha_rop_mode >> 5))); - - *bRGA_MODE_CTL = reg; - -} - - - -/************************************************************* -Func: - RGA_set_src -Description: - fill src relate reg info -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ - +RGA_set_mode_ctrl(u8 *base, const struct rga_req *msg) +{ + u32 *bRGA_MODE_CTL; + u32 reg = 0; + + u8 src_rgb_pack = 0; + u8 src_format = 0; + u8 src_rb_swp = 0; + u8 src_a_swp = 0; + u8 src_cbcr_swp = 0; + + u8 dst_rgb_pack = 0; + u8 dst_format = 0; + u8 dst_rb_swp = 0; + u8 dst_a_swp = 0; + + bRGA_MODE_CTL = (u32 *)(base + RGA_MODE_CTRL_OFFSET); + + reg = ((reg & (~m_RGA_MODE_CTRL_2D_RENDER_MODE)) | (s_RGA_MODE_CTRL_2D_RENDER_MODE(msg->render_mode))); + + /* src info set */ + + if (msg->render_mode == color_palette_mode || msg->render_mode == update_palette_table_mode) + { + src_format = 0x10 | (msg->palette_mode & 3); + } + else + { + switch (msg->src.format) + { + case RK_FORMAT_RGBA_8888 : src_format = 0x0; break; + case RK_FORMAT_RGBA_4444 : src_format = 0x3; break; + case RK_FORMAT_RGBA_5551 : src_format = 0x2; break; + case RK_FORMAT_BGRA_8888 : src_format = 0x0; src_rb_swp = 0x1; break; + case RK_FORMAT_RGBX_8888 : src_format = 0x0; break; + case RK_FORMAT_RGB_565 : src_format = 0x1; break; + case RK_FORMAT_RGB_888 : src_format = 0x0; src_rgb_pack = 1; break; + case RK_FORMAT_BGR_888 : src_format = 0x0; src_rgb_pack = 1; src_rb_swp = 1; break; + + case RK_FORMAT_YCbCr_422_SP : src_format = 0x4; break; + case RK_FORMAT_YCbCr_422_P : src_format = 0x5; break; + case RK_FORMAT_YCbCr_420_SP : src_format = 0x6; break; + case RK_FORMAT_YCbCr_420_P : src_format = 0x7; break; + + case RK_FORMAT_YCrCb_422_SP : src_format = 0x4; src_cbcr_swp = 1; break; + case RK_FORMAT_YCrCb_422_P : src_format = 0x5; src_cbcr_swp = 1; break; + case RK_FORMAT_YCrCb_420_SP : src_format = 0x6; src_cbcr_swp = 1; break; + case RK_FORMAT_YCrCb_420_P : src_format = 0x7; src_cbcr_swp = 1; break; + } + } + + src_a_swp = msg->src.alpha_swap & 1; + + reg = ((reg & (~m_RGA_MODE_CTRL_SRC_RGB_PACK)) | (s_RGA_MODE_CTRL_SRC_RGB_PACK(src_rgb_pack))); + reg = ((reg & (~m_RGA_MODE_CTRL_SRC_FORMAT)) | (s_RGA_MODE_CTRL_SRC_FORMAT(src_format))); + reg = ((reg & (~m_RGA_MODE_CTRL_SRC_RB_SWAP)) | (s_RGA_MODE_CTRL_SRC_RB_SWAP(src_rb_swp))); + reg = ((reg & (~m_RGA_MODE_CTRL_SRC_ALPHA_SWAP)) | (s_RGA_MODE_CTRL_SRC_ALPHA_SWAP(src_a_swp))); + reg = ((reg & (~m_RGA_MODE_CTRL_SRC_UV_SWAP_MODE )) | (s_RGA_MODE_CTRL_SRC_UV_SWAP_MODE (src_cbcr_swp))); + + + /* YUV2RGB MODE */ + reg = ((reg & (~m_RGA_MODE_CTRL_YUV2RGB_CON_MODE)) | (s_RGA_MODE_CTRL_YUV2RGB_CON_MODE(msg->yuv2rgb_mode))); + + /* ROTATE MODE */ + reg = ((reg & (~m_RGA_MODE_CTRL_ROTATE_MODE)) | (s_RGA_MODE_CTRL_ROTATE_MODE(msg->rotate_mode))); + + /* SCALE MODE */ + reg = ((reg & (~m_RGA_MODE_CTRL_SCALE_MODE)) | (s_RGA_MODE_CTRL_SCALE_MODE(msg->scale_mode))); + + /* COLOR FILL MODE */ + reg = ((reg & (~m_RGA_MODE_CTRL_PAT_SEL)) | (s_RGA_MODE_CTRL_PAT_SEL(msg->color_fill_mode))); + + + if ((msg->render_mode == update_palette_table_mode)||(msg->render_mode == update_patten_buff_mode)) + { + dst_format = msg->pat.format; + } + else + { + dst_format = (u8)msg->dst.format; + } + + /* dst info set */ + switch (dst_format) + { + case RK_FORMAT_BGRA_8888 : dst_format = 0x0; dst_rb_swp = 0x1; break; + case RK_FORMAT_RGBA_4444 : dst_format = 0x3; break; + case RK_FORMAT_RGBA_5551 : dst_format = 0x2; break; + case RK_FORMAT_RGBA_8888 : dst_format = 0x0; break; + case RK_FORMAT_RGB_565 : dst_format = 0x1; break; + case RK_FORMAT_RGB_888 : dst_format = 0x0; dst_rgb_pack = 0x1; break; + case RK_FORMAT_BGR_888 : dst_format = 0x0; dst_rgb_pack = 0x1; dst_rb_swp = 1; break; + case RK_FORMAT_RGBX_8888 : dst_format = 0x0; break; + } + + dst_a_swp = msg->dst.alpha_swap & 1; + + reg = ((reg & (~m_RGA_MODE_CTRL_DST_FORMAT)) | (s_RGA_MODE_CTRL_DST_FORMAT(dst_format))); + reg = ((reg & (~m_RGA_MODE_CTRL_DST_RGB_PACK)) | (s_RGA_MODE_CTRL_DST_RGB_PACK(dst_rgb_pack))); + reg = ((reg & (~m_RGA_MODE_CTRL_DST_RB_SWAP)) | (s_RGA_MODE_CTRL_DST_RB_SWAP(dst_rb_swp))); + reg = ((reg & (~m_RGA_MODE_CTRL_DST_ALPHA_SWAP)) | (s_RGA_MODE_CTRL_DST_ALPHA_SWAP(dst_a_swp))); + reg = ((reg & (~m_RGA_MODE_CTRL_LUT_ENDIAN_MODE)) | (s_RGA_MODE_CTRL_LUT_ENDIAN_MODE(msg->endian_mode & 1))); + reg = ((reg & (~m_RGA_MODE_CTRL_SRC_TRANS_MODE)) | (s_RGA_MODE_CTRL_SRC_TRANS_MODE(msg->src_trans_mode))); + reg = ((reg & (~m_RGA_MODE_CTRL_ZERO_MODE_ENABLE)) | (s_RGA_MODE_CTRL_ZERO_MODE_ENABLE(msg->alpha_rop_mode >> 4))); + reg = ((reg & (~m_RGA_MODE_CTRL_DST_ALPHA_ENABLE)) | (s_RGA_MODE_CTRL_DST_ALPHA_ENABLE(msg->alpha_rop_mode >> 5))); + + *bRGA_MODE_CTL = reg; + +} + + + +/************************************************************* +Func: + RGA_set_src +Description: + fill src relate reg info +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ + static void -RGA_set_src(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_SRC_VIR_INFO; - u32 *bRGA_SRC_ACT_INFO; - u32 *bRGA_SRC_Y_MST; - u32 *bRGA_SRC_CB_MST; - u32 *bRGA_SRC_CR_MST; - - s16 x_off, y_off, stride; - s16 uv_x_off, uv_y_off, uv_stride; - u32 pixel_width; - - uv_x_off = uv_y_off = uv_stride = 0; - - bRGA_SRC_Y_MST = (u32 *)(base + RGA_SRC_Y_MST_OFFSET); - bRGA_SRC_CB_MST = (u32 *)(base + RGA_SRC_CB_MST_OFFSET); - bRGA_SRC_CR_MST = (u32 *)(base + RGA_SRC_CR_MST_OFFSET); - bRGA_SRC_VIR_INFO = (u32 *)(base + RGA_SRC_VIR_INFO_OFFSET); - bRGA_SRC_ACT_INFO = (u32 *)(base + RGA_SRC_ACT_INFO_OFFSET); - - x_off = msg->src.x_offset; - y_off = msg->src.y_offset; - - pixel_width = RGA_pixel_width_init(msg->src.format); - - stride = ((msg->src.vir_w * pixel_width) + 3) & (~3); - - switch(msg->src.format) - { - case RK_FORMAT_YCbCr_422_SP : - uv_stride = stride; - uv_x_off = x_off; - uv_y_off = y_off; - break; - case RK_FORMAT_YCbCr_422_P : - uv_stride = stride >> 1; - uv_x_off = x_off >> 1; - uv_y_off = y_off; - break; - case RK_FORMAT_YCbCr_420_SP : - uv_stride = stride; - uv_x_off = x_off; - uv_y_off = y_off >> 1; - break; - case RK_FORMAT_YCbCr_420_P : - uv_stride = stride >> 1; - uv_x_off = x_off >> 1; - uv_y_off = y_off >> 1; - break; - case RK_FORMAT_YCrCb_422_SP : - uv_stride = stride; - uv_x_off = x_off; - uv_y_off = y_off; - break; - case RK_FORMAT_YCrCb_422_P : - uv_stride = stride >> 1; - uv_x_off = x_off >> 1; - uv_y_off = y_off; - break; - case RK_FORMAT_YCrCb_420_SP : - uv_stride = stride; - uv_x_off = x_off; - uv_y_off = y_off >> 1; - break; - case RK_FORMAT_YCrCb_420_P : - uv_stride = stride >> 1; - uv_x_off = x_off >> 1; - uv_y_off = y_off >> 1; - break; - } - - - /* src addr set */ - *bRGA_SRC_Y_MST = msg->src.yrgb_addr + (y_off * stride) + (x_off * pixel_width); - *bRGA_SRC_CB_MST = msg->src.uv_addr + uv_y_off * uv_stride + uv_x_off; - *bRGA_SRC_CR_MST = msg->src.v_addr + uv_y_off * uv_stride + uv_x_off; - - if((msg->alpha_rop_flag >> 1) & 1) - *bRGA_SRC_CB_MST = (u32)msg->rop_mask_addr; - - if (msg->render_mode == color_palette_mode) - { - u8 shift; - u16 sw, byte_num; - shift = 3 - (msg->palette_mode & 3); - sw = msg->src.vir_w; - - byte_num = sw >> shift; - stride = (byte_num + 3) & (~3); - } - - /* src act window / vir window set */ - *bRGA_SRC_VIR_INFO = ((stride >> 2) | (msg->src.vir_h)<<16); - *bRGA_SRC_ACT_INFO = ((msg->src.act_w-1) | (msg->src.act_h-1)<<16); -} - - -/************************************************************* -Func: - RGA_set_dst -Description: - fill dst relate reg info -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ +RGA_set_src(u8 *base, const struct rga_req *msg) +{ + u32 *bRGA_SRC_VIR_INFO; + u32 *bRGA_SRC_ACT_INFO; + u32 *bRGA_SRC_Y_MST; + u32 *bRGA_SRC_CB_MST; + u32 *bRGA_SRC_CR_MST; + + s16 x_off, y_off, stride; + s16 uv_x_off, uv_y_off, uv_stride; + u32 pixel_width; + + uv_x_off = uv_y_off = uv_stride = 0; + + bRGA_SRC_Y_MST = (u32 *)(base + RGA_SRC_Y_MST_OFFSET); + bRGA_SRC_CB_MST = (u32 *)(base + RGA_SRC_CB_MST_OFFSET); + bRGA_SRC_CR_MST = (u32 *)(base + RGA_SRC_CR_MST_OFFSET); + bRGA_SRC_VIR_INFO = (u32 *)(base + RGA_SRC_VIR_INFO_OFFSET); + bRGA_SRC_ACT_INFO = (u32 *)(base + RGA_SRC_ACT_INFO_OFFSET); + + x_off = msg->src.x_offset; + y_off = msg->src.y_offset; + + pixel_width = RGA_pixel_width_init(msg->src.format); + + stride = ((msg->src.vir_w * pixel_width) + 3) & (~3); + + switch(msg->src.format) + { + case RK_FORMAT_YCbCr_422_SP : + uv_stride = stride; + uv_x_off = x_off; + uv_y_off = y_off; + break; + case RK_FORMAT_YCbCr_422_P : + uv_stride = stride >> 1; + uv_x_off = x_off >> 1; + uv_y_off = y_off; + break; + case RK_FORMAT_YCbCr_420_SP : + uv_stride = stride; + uv_x_off = x_off; + uv_y_off = y_off >> 1; + break; + case RK_FORMAT_YCbCr_420_P : + uv_stride = stride >> 1; + uv_x_off = x_off >> 1; + uv_y_off = y_off >> 1; + break; + case RK_FORMAT_YCrCb_422_SP : + uv_stride = stride; + uv_x_off = x_off; + uv_y_off = y_off; + break; + case RK_FORMAT_YCrCb_422_P : + uv_stride = stride >> 1; + uv_x_off = x_off >> 1; + uv_y_off = y_off; + break; + case RK_FORMAT_YCrCb_420_SP : + uv_stride = stride; + uv_x_off = x_off; + uv_y_off = y_off >> 1; + break; + case RK_FORMAT_YCrCb_420_P : + uv_stride = stride >> 1; + uv_x_off = x_off >> 1; + uv_y_off = y_off >> 1; + break; + } + + + /* src addr set */ + *bRGA_SRC_Y_MST = msg->src.yrgb_addr + (y_off * stride) + (x_off * pixel_width); + *bRGA_SRC_CB_MST = msg->src.uv_addr + uv_y_off * uv_stride + uv_x_off; + *bRGA_SRC_CR_MST = msg->src.v_addr + uv_y_off * uv_stride + uv_x_off; + + if((msg->alpha_rop_flag >> 1) & 1) + *bRGA_SRC_CB_MST = (u32)msg->rop_mask_addr; + + if (msg->render_mode == color_palette_mode) + { + u8 shift; + u16 sw, byte_num; + shift = 3 - (msg->palette_mode & 3); + sw = msg->src.vir_w; + + byte_num = sw >> shift; + stride = (byte_num + 3) & (~3); + } + + /* src act window / vir window set */ + *bRGA_SRC_VIR_INFO = ((stride >> 2) | (msg->src.vir_h)<<16); + *bRGA_SRC_ACT_INFO = ((msg->src.act_w-1) | (msg->src.act_h-1)<<16); +} + + +/************************************************************* +Func: + RGA_set_dst +Description: + fill dst relate reg info +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ static s32 RGA_set_dst(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_DST_MST; - u32 *bRGA_DST_UV_MST; - u32 *bRGA_DST_VIR_INFO; - u32 *bRGA_DST_CTR_INFO; - u32 *bRGA_PRESCL_CB_MST; - u32 *bRGA_PRESCL_CR_MST; - u32 *bRGA_YUV_OUT_CFG; - - u32 reg = 0; - - u8 pw; - s16 x_off = msg->dst.x_offset; - s16 y_off = msg->dst.y_offset; - u16 stride, rop_mask_stride; - - bRGA_DST_MST = (u32 *)(base + RGA_DST_MST_OFFSET); - bRGA_DST_UV_MST = (u32 *)(base + RGA_DST_UV_MST_OFFSET); - bRGA_DST_VIR_INFO = (u32 *)(base + RGA_DST_VIR_INFO_OFFSET); - bRGA_DST_CTR_INFO = (u32 *)(base + RGA_DST_CTR_INFO_OFFSET); - bRGA_PRESCL_CB_MST = (u32 *)(base + RGA_PRESCL_CB_MST_OFFSET); - bRGA_PRESCL_CR_MST = (u32 *)(base + RGA_PRESCL_CR_MST_OFFSET); - bRGA_YUV_OUT_CFG = (u32 *)(base + RGA_YUV_OUT_CFG_OFFSET); - - pw = RGA_pixel_width_init(msg->dst.format); - - stride = (msg->dst.vir_w * pw + 3) & (~3); - - *bRGA_DST_MST = (u32)msg->dst.yrgb_addr + (y_off * stride) + (x_off * pw); - +{ + u32 *bRGA_DST_MST; + u32 *bRGA_DST_UV_MST; + u32 *bRGA_DST_VIR_INFO; + u32 *bRGA_DST_CTR_INFO; + u32 *bRGA_PRESCL_CB_MST; + u32 *bRGA_PRESCL_CR_MST; + u32 *bRGA_YUV_OUT_CFG; + + u32 reg = 0; + + u8 pw; + s16 x_off = msg->dst.x_offset; + s16 y_off = msg->dst.y_offset; + u16 stride, rop_mask_stride; + + bRGA_DST_MST = (u32 *)(base + RGA_DST_MST_OFFSET); + bRGA_DST_UV_MST = (u32 *)(base + RGA_DST_UV_MST_OFFSET); + bRGA_DST_VIR_INFO = (u32 *)(base + RGA_DST_VIR_INFO_OFFSET); + bRGA_DST_CTR_INFO = (u32 *)(base + RGA_DST_CTR_INFO_OFFSET); + bRGA_PRESCL_CB_MST = (u32 *)(base + RGA_PRESCL_CB_MST_OFFSET); + bRGA_PRESCL_CR_MST = (u32 *)(base + RGA_PRESCL_CR_MST_OFFSET); + bRGA_YUV_OUT_CFG = (u32 *)(base + RGA_YUV_OUT_CFG_OFFSET); + + pw = RGA_pixel_width_init(msg->dst.format); + + stride = (msg->dst.vir_w * pw + 3) & (~3); + + *bRGA_DST_MST = (u32)msg->dst.yrgb_addr + (y_off * stride) + (x_off * pw); + *bRGA_DST_UV_MST = 0; *bRGA_YUV_OUT_CFG = 0; if (msg->rotate_mode == 1) { @@ -719,869 +719,869 @@ static s32 RGA_set_dst(u8 *base, const struct rga_req *msg) } } - switch(msg->dst.format) - { - case RK_FORMAT_YCbCr_422_SP : - *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off) * stride) + ((x_off) * pw); + switch(msg->dst.format) + { + case RK_FORMAT_YCbCr_422_SP : + *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off) * stride) + ((x_off) * pw); *bRGA_DST_UV_MST = (u32)msg->dst.uv_addr + (y_off * stride) + x_off; *bRGA_YUV_OUT_CFG |= (((msg->yuv2rgb_mode >> 2) & 3) << 4) | (0 << 3) | (0 << 1) | 1; - break; - case RK_FORMAT_YCbCr_422_P : - *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off) * stride) + ((x_off>>1) * pw); - *bRGA_PRESCL_CR_MST = (u32)msg->dst.v_addr + ((y_off) * stride) + ((x_off>>1) * pw); - break; - case RK_FORMAT_YCbCr_420_SP : - *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off>>1) * stride) + ((x_off) * pw); + break; + case RK_FORMAT_YCbCr_422_P : + *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off) * stride) + ((x_off>>1) * pw); + *bRGA_PRESCL_CR_MST = (u32)msg->dst.v_addr + ((y_off) * stride) + ((x_off>>1) * pw); + break; + case RK_FORMAT_YCbCr_420_SP : + *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off>>1) * stride) + ((x_off) * pw); *bRGA_DST_UV_MST = (u32)msg->dst.uv_addr + ((y_off>>1) * stride) + x_off; *bRGA_YUV_OUT_CFG |= (((msg->yuv2rgb_mode >> 2) & 3) << 4) | (0 << 3) | (1 << 1) | 1; - break; - case RK_FORMAT_YCbCr_420_P : - *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off>>1) * stride) + ((x_off>>1) * pw); - *bRGA_PRESCL_CR_MST = (u32)msg->dst.v_addr + ((y_off>>1) * stride) + ((x_off>>1) * pw); - break; - case RK_FORMAT_YCrCb_422_SP : - *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off) * stride) + ((x_off) * pw); + break; + case RK_FORMAT_YCbCr_420_P : + *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off>>1) * stride) + ((x_off>>1) * pw); + *bRGA_PRESCL_CR_MST = (u32)msg->dst.v_addr + ((y_off>>1) * stride) + ((x_off>>1) * pw); + break; + case RK_FORMAT_YCrCb_422_SP : + *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off) * stride) + ((x_off) * pw); *bRGA_DST_UV_MST = (u32)msg->dst.uv_addr + (y_off * stride) + x_off; *bRGA_YUV_OUT_CFG |= (((msg->yuv2rgb_mode >> 2) & 3) << 4) | (1 << 3) | (0 << 1) | 1; - break; - case RK_FORMAT_YCrCb_422_P : - *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off) * stride) + ((x_off>>1) * pw); - *bRGA_PRESCL_CR_MST = (u32)msg->dst.v_addr + ((y_off) * stride) + ((x_off>>1) * pw); - break; - case RK_FORMAT_YCrCb_420_SP : - *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off>>1) * stride) + ((x_off) * pw); + break; + case RK_FORMAT_YCrCb_422_P : + *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off) * stride) + ((x_off>>1) * pw); + *bRGA_PRESCL_CR_MST = (u32)msg->dst.v_addr + ((y_off) * stride) + ((x_off>>1) * pw); + break; + case RK_FORMAT_YCrCb_420_SP : + *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off>>1) * stride) + ((x_off) * pw); *bRGA_DST_UV_MST = (u32)msg->dst.uv_addr + ((y_off>>1) * stride) + x_off; *bRGA_YUV_OUT_CFG |= (((msg->yuv2rgb_mode >> 2) & 3) << 4) | (1 << 3) | (1 << 1) | 1; - break; - case RK_FORMAT_YCrCb_420_P : - *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off>>1) * stride) + ((x_off>>1) * pw); - *bRGA_PRESCL_CR_MST = (u32)msg->dst.v_addr + ((y_off>>1) * stride) + ((x_off>>1) * pw); - break; - } - - rop_mask_stride = (((msg->src.vir_w + 7)>>3) + 3) & (~3);//not dst_vir.w,hxx,2011.7.21 - - reg = (stride >> 2) & 0xffff; - reg = reg | ((rop_mask_stride>>2) << 16); - - #if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3188) - //reg = reg | ((msg->alpha_rop_mode & 3) << 28); - reg = reg | (1 << 28); - #endif - - if (msg->render_mode == line_point_drawing_mode) - { - reg &= 0xffff; - reg = reg | (msg->dst.vir_h << 16); - } - - *bRGA_DST_VIR_INFO = reg; - *bRGA_DST_CTR_INFO = (msg->dst.act_w - 1) | ((msg->dst.act_h - 1) << 16); + break; + case RK_FORMAT_YCrCb_420_P : + *bRGA_PRESCL_CB_MST = (u32)msg->dst.uv_addr + ((y_off>>1) * stride) + ((x_off>>1) * pw); + *bRGA_PRESCL_CR_MST = (u32)msg->dst.v_addr + ((y_off>>1) * stride) + ((x_off>>1) * pw); + break; + } + + rop_mask_stride = (((msg->src.vir_w + 7)>>3) + 3) & (~3);//not dst_vir.w,hxx,2011.7.21 + + reg = (stride >> 2) & 0xffff; + reg = reg | ((rop_mask_stride>>2) << 16); + + #if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3188) + //reg = reg | ((msg->alpha_rop_mode & 3) << 28); + reg = reg | (1 << 28); + #endif + + if (msg->render_mode == line_point_drawing_mode) + { + reg &= 0xffff; + reg = reg | (msg->dst.vir_h << 16); + } + + *bRGA_DST_VIR_INFO = reg; + *bRGA_DST_CTR_INFO = (msg->dst.act_w - 1) | ((msg->dst.act_h - 1) << 16); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)) - if (msg->render_mode == pre_scaling_mode) { - *bRGA_YUV_OUT_CFG &= 0xfffffffe; - } + if (msg->render_mode == pre_scaling_mode) { + *bRGA_YUV_OUT_CFG &= 0xfffffffe; + } #endif - return 0; -} - - -/************************************************************* -Func: - RGA_set_alpha_rop -Description: - fill alpha rop some relate reg bit -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ + return 0; +} + + +/************************************************************* +Func: + RGA_set_alpha_rop +Description: + fill alpha rop some relate reg bit +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ static void -RGA_set_alpha_rop(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_ALPHA_CON; - u32 *bRGA_ROP_CON0; - u32 *bRGA_ROP_CON1; - u32 reg = 0; - u32 rop_con0, rop_con1; - - u8 rop_mode = (msg->alpha_rop_mode) & 3; - u8 alpha_mode = msg->alpha_rop_mode & 3; - - rop_con0 = rop_con1 = 0; - - bRGA_ALPHA_CON = (u32 *)(base + RGA_ALPHA_CON_OFFSET); - - reg = ((reg & (~m_RGA_ALPHA_CON_ENABLE) )| (s_RGA_ALPHA_CON_ENABLE(msg->alpha_rop_flag & 1))); - reg = ((reg & (~m_RGA_ALPHA_CON_A_OR_R_SEL)) | (s_RGA_ALPHA_CON_A_OR_R_SEL((msg->alpha_rop_flag >> 1) & 1))); - reg = ((reg & (~m_RGA_ALPHA_CON_ALPHA_MODE)) | (s_RGA_ALPHA_CON_ALPHA_MODE(alpha_mode))); - reg = ((reg & (~m_RGA_ALPHA_CON_PD_MODE)) | (s_RGA_ALPHA_CON_PD_MODE(msg->PD_mode))); - reg = ((reg & (~m_RGA_ALPHA_CON_SET_CONSTANT_VALUE)) | (s_RGA_ALPHA_CON_SET_CONSTANT_VALUE(msg->alpha_global_value))); - reg = ((reg & (~m_RGA_ALPHA_CON_PD_M_SEL)) | (s_RGA_ALPHA_CON_PD_M_SEL(msg->alpha_rop_flag >> 3))); - reg = ((reg & (~m_RGA_ALPHA_CON_FADING_ENABLE)) | (s_RGA_ALPHA_CON_FADING_ENABLE(msg->alpha_rop_flag >> 2))); - reg = ((reg & (~m_RGA_ALPHA_CON_ROP_MODE_SEL)) | (s_RGA_ALPHA_CON_ROP_MODE_SEL(rop_mode))); - reg = ((reg & (~m_RGA_ALPHA_CON_CAL_MODE_SEL)) | (s_RGA_ALPHA_CON_CAL_MODE_SEL(msg->alpha_rop_flag >> 4))); - reg = ((reg & (~m_RGA_ALPHA_CON_DITHER_ENABLE)) | (s_RGA_ALPHA_CON_DITHER_ENABLE(msg->alpha_rop_flag >> 5))); - reg = ((reg & (~m_RGA_ALPHA_CON_GRADIENT_CAL_MODE)) | (s_RGA_ALPHA_CON_GRADIENT_CAL_MODE(msg->alpha_rop_flag >> 6))); - reg = ((reg & (~m_RGA_ALPHA_CON_AA_SEL)) | (s_RGA_ALPHA_CON_AA_SEL(msg->alpha_rop_flag >> 7))); - - *bRGA_ALPHA_CON = reg; - - if(rop_mode == 0) { - rop_con0 = ROP3_code[(msg->rop_code & 0xff)]; - } - else if(rop_mode == 1) { - rop_con0 = ROP3_code[(msg->rop_code & 0xff)]; - } - else if(rop_mode == 2) { - rop_con0 = ROP3_code[(msg->rop_code & 0xff)]; - rop_con1 = ROP3_code[(msg->rop_code & 0xff00)>>8]; - } - - bRGA_ROP_CON0 = (u32 *)(base + RGA_ROP_CON0_OFFSET); - bRGA_ROP_CON1 = (u32 *)(base + RGA_ROP_CON1_OFFSET); - - *bRGA_ROP_CON0 = (u32)rop_con0; - *bRGA_ROP_CON1 = (u32)rop_con1; -} - - -/************************************************************* -Func: - RGA_set_color -Description: - fill color some relate reg bit - bg_color/fg_color -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ +RGA_set_alpha_rop(u8 *base, const struct rga_req *msg) +{ + u32 *bRGA_ALPHA_CON; + u32 *bRGA_ROP_CON0; + u32 *bRGA_ROP_CON1; + u32 reg = 0; + u32 rop_con0, rop_con1; + + u8 rop_mode = (msg->alpha_rop_mode) & 3; + u8 alpha_mode = msg->alpha_rop_mode & 3; + + rop_con0 = rop_con1 = 0; + + bRGA_ALPHA_CON = (u32 *)(base + RGA_ALPHA_CON_OFFSET); + + reg = ((reg & (~m_RGA_ALPHA_CON_ENABLE) )| (s_RGA_ALPHA_CON_ENABLE(msg->alpha_rop_flag & 1))); + reg = ((reg & (~m_RGA_ALPHA_CON_A_OR_R_SEL)) | (s_RGA_ALPHA_CON_A_OR_R_SEL((msg->alpha_rop_flag >> 1) & 1))); + reg = ((reg & (~m_RGA_ALPHA_CON_ALPHA_MODE)) | (s_RGA_ALPHA_CON_ALPHA_MODE(alpha_mode))); + reg = ((reg & (~m_RGA_ALPHA_CON_PD_MODE)) | (s_RGA_ALPHA_CON_PD_MODE(msg->PD_mode))); + reg = ((reg & (~m_RGA_ALPHA_CON_SET_CONSTANT_VALUE)) | (s_RGA_ALPHA_CON_SET_CONSTANT_VALUE(msg->alpha_global_value))); + reg = ((reg & (~m_RGA_ALPHA_CON_PD_M_SEL)) | (s_RGA_ALPHA_CON_PD_M_SEL(msg->alpha_rop_flag >> 3))); + reg = ((reg & (~m_RGA_ALPHA_CON_FADING_ENABLE)) | (s_RGA_ALPHA_CON_FADING_ENABLE(msg->alpha_rop_flag >> 2))); + reg = ((reg & (~m_RGA_ALPHA_CON_ROP_MODE_SEL)) | (s_RGA_ALPHA_CON_ROP_MODE_SEL(rop_mode))); + reg = ((reg & (~m_RGA_ALPHA_CON_CAL_MODE_SEL)) | (s_RGA_ALPHA_CON_CAL_MODE_SEL(msg->alpha_rop_flag >> 4))); + reg = ((reg & (~m_RGA_ALPHA_CON_DITHER_ENABLE)) | (s_RGA_ALPHA_CON_DITHER_ENABLE(msg->alpha_rop_flag >> 5))); + reg = ((reg & (~m_RGA_ALPHA_CON_GRADIENT_CAL_MODE)) | (s_RGA_ALPHA_CON_GRADIENT_CAL_MODE(msg->alpha_rop_flag >> 6))); + reg = ((reg & (~m_RGA_ALPHA_CON_AA_SEL)) | (s_RGA_ALPHA_CON_AA_SEL(msg->alpha_rop_flag >> 7))); + + *bRGA_ALPHA_CON = reg; + + if(rop_mode == 0) { + rop_con0 = ROP3_code[(msg->rop_code & 0xff)]; + } + else if(rop_mode == 1) { + rop_con0 = ROP3_code[(msg->rop_code & 0xff)]; + } + else if(rop_mode == 2) { + rop_con0 = ROP3_code[(msg->rop_code & 0xff)]; + rop_con1 = ROP3_code[(msg->rop_code & 0xff00)>>8]; + } + + bRGA_ROP_CON0 = (u32 *)(base + RGA_ROP_CON0_OFFSET); + bRGA_ROP_CON1 = (u32 *)(base + RGA_ROP_CON1_OFFSET); + + *bRGA_ROP_CON0 = (u32)rop_con0; + *bRGA_ROP_CON1 = (u32)rop_con1; +} + + +/************************************************************* +Func: + RGA_set_color +Description: + fill color some relate reg bit + bg_color/fg_color +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ static void -RGA_set_color(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_SRC_TR_COLOR0; - u32 *bRGA_SRC_TR_COLOR1; - u32 *bRGA_SRC_BG_COLOR; - u32 *bRGA_SRC_FG_COLOR; - - - bRGA_SRC_BG_COLOR = (u32 *)(base + RGA_SRC_BG_COLOR_OFFSET); - bRGA_SRC_FG_COLOR = (u32 *)(base + RGA_SRC_FG_COLOR_OFFSET); - - *bRGA_SRC_BG_COLOR = msg->bg_color; /* 1bpp 0 */ - *bRGA_SRC_FG_COLOR = msg->fg_color; /* 1bpp 1 */ - - bRGA_SRC_TR_COLOR0 = (u32 *)(base + RGA_SRC_TR_COLOR0_OFFSET); - bRGA_SRC_TR_COLOR1 = (u32 *)(base + RGA_SRC_TR_COLOR1_OFFSET); - - *bRGA_SRC_TR_COLOR0 = msg->color_key_min; - *bRGA_SRC_TR_COLOR1 = msg->color_key_max; -} - - -/************************************************************* -Func: - RGA_set_fading -Description: - fill fading some relate reg bit -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ +RGA_set_color(u8 *base, const struct rga_req *msg) +{ + u32 *bRGA_SRC_TR_COLOR0; + u32 *bRGA_SRC_TR_COLOR1; + u32 *bRGA_SRC_BG_COLOR; + u32 *bRGA_SRC_FG_COLOR; + + + bRGA_SRC_BG_COLOR = (u32 *)(base + RGA_SRC_BG_COLOR_OFFSET); + bRGA_SRC_FG_COLOR = (u32 *)(base + RGA_SRC_FG_COLOR_OFFSET); + + *bRGA_SRC_BG_COLOR = msg->bg_color; /* 1bpp 0 */ + *bRGA_SRC_FG_COLOR = msg->fg_color; /* 1bpp 1 */ + + bRGA_SRC_TR_COLOR0 = (u32 *)(base + RGA_SRC_TR_COLOR0_OFFSET); + bRGA_SRC_TR_COLOR1 = (u32 *)(base + RGA_SRC_TR_COLOR1_OFFSET); + + *bRGA_SRC_TR_COLOR0 = msg->color_key_min; + *bRGA_SRC_TR_COLOR1 = msg->color_key_max; +} + + +/************************************************************* +Func: + RGA_set_fading +Description: + fill fading some relate reg bit +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ static s32 -RGA_set_fading(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_FADING_CON; - u8 r, g, b; - u32 reg = 0; - - bRGA_FADING_CON = (u32 *)(base + RGA_FADING_CON_OFFSET); - - b = msg->fading.b; - g = msg->fading.g; - r = msg->fading.r; - - reg = (r<<8) | (g<<16) | (b<<24) | reg; - - *bRGA_FADING_CON = reg; - - return 0; -} - - -/************************************************************* -Func: - RGA_set_pat -Description: - fill patten some relate reg bit -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ +RGA_set_fading(u8 *base, const struct rga_req *msg) +{ + u32 *bRGA_FADING_CON; + u8 r, g, b; + u32 reg = 0; + + bRGA_FADING_CON = (u32 *)(base + RGA_FADING_CON_OFFSET); + + b = msg->fading.b; + g = msg->fading.g; + r = msg->fading.r; + + reg = (r<<8) | (g<<16) | (b<<24) | reg; + + *bRGA_FADING_CON = reg; + + return 0; +} + + +/************************************************************* +Func: + RGA_set_pat +Description: + fill patten some relate reg bit +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ static s32 -RGA_set_pat(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_PAT_CON; - u32 *bRGA_PAT_START_POINT; - u32 reg = 0; - - bRGA_PAT_START_POINT = (u32 *)(base + RGA_PAT_START_POINT_OFFSET); - - bRGA_PAT_CON = (u32 *)(base + RGA_PAT_CON_OFFSET); - - *bRGA_PAT_START_POINT = (msg->pat.act_w * msg->pat.y_offset) + msg->pat.x_offset; - - reg = (msg->pat.act_w - 1) | ((msg->pat.act_h - 1) << 8) | (msg->pat.x_offset << 16) | (msg->pat.y_offset << 24); - *bRGA_PAT_CON = reg; - - return 0; -} - - - - -/************************************************************* -Func: - RGA_set_bitblt_reg_info -Description: - fill bitblt mode relate ren info -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ +RGA_set_pat(u8 *base, const struct rga_req *msg) +{ + u32 *bRGA_PAT_CON; + u32 *bRGA_PAT_START_POINT; + u32 reg = 0; + + bRGA_PAT_START_POINT = (u32 *)(base + RGA_PAT_START_POINT_OFFSET); + + bRGA_PAT_CON = (u32 *)(base + RGA_PAT_CON_OFFSET); + + *bRGA_PAT_START_POINT = (msg->pat.act_w * msg->pat.y_offset) + msg->pat.x_offset; + + reg = (msg->pat.act_w - 1) | ((msg->pat.act_h - 1) << 8) | (msg->pat.x_offset << 16) | (msg->pat.y_offset << 24); + *bRGA_PAT_CON = reg; + + return 0; +} + + + + +/************************************************************* +Func: + RGA_set_bitblt_reg_info +Description: + fill bitblt mode relate ren info +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ static void -RGA_set_bitblt_reg_info(u8 *base, const struct rga_req * msg, TILE_INFO *tile) -{ - u32 *bRGA_SRC_Y_MST; - u32 *bRGA_SRC_CB_MST; - u32 *bRGA_SRC_CR_MST; - u32 *bRGA_SRC_X_PARA; - u32 *bRGA_SRC_Y_PARA; - u32 *bRGA_SRC_TILE_XINFO; - u32 *bRGA_SRC_TILE_YINFO; - u32 *bRGA_SRC_TILE_H_INCR; - u32 *bRGA_SRC_TILE_V_INCR; - u32 *bRGA_SRC_TILE_OFFSETX; - u32 *bRGA_SRC_TILE_OFFSETY; - - u32 *bRGA_DST_MST; - u32 *bRGA_DST_CTR_INFO; - - s32 m0, m1, m2, m3; - s32 pos[8]; - //s32 x_dx, x_dy, y_dx, y_dy; - s32 xmin, xmax, ymin, ymax; - s32 xp, yp; - u32 y_addr, u_addr, v_addr; - u32 pixel_width, stride; - - u_addr = v_addr = 0; - - /* src info */ - - bRGA_SRC_Y_MST = (u32 *)(base + RGA_SRC_Y_MST_OFFSET); - bRGA_SRC_CB_MST = (u32 *)(base + RGA_SRC_CB_MST_OFFSET); - bRGA_SRC_CR_MST = (u32 *)(base + RGA_SRC_CR_MST_OFFSET); - - bRGA_SRC_X_PARA = (u32 *)(base + RGA_SRC_X_PARA_OFFSET); - bRGA_SRC_Y_PARA = (u32 *)(base + RGA_SRC_Y_PARA_OFFSET); - - bRGA_SRC_TILE_XINFO = (u32 *)(base + RGA_SRC_TILE_XINFO_OFFSET); - bRGA_SRC_TILE_YINFO = (u32 *)(base + RGA_SRC_TILE_YINFO_OFFSET); - bRGA_SRC_TILE_H_INCR = (u32 *)(base + RGA_SRC_TILE_H_INCR_OFFSET); - bRGA_SRC_TILE_V_INCR = (u32 *)(base + RGA_SRC_TILE_V_INCR_OFFSET); - bRGA_SRC_TILE_OFFSETX = (u32 *)(base + RGA_SRC_TILE_OFFSETX_OFFSET); - bRGA_SRC_TILE_OFFSETY = (u32 *)(base + RGA_SRC_TILE_OFFSETY_OFFSET); - - bRGA_DST_MST = (u32 *)(base + RGA_DST_MST_OFFSET); - bRGA_DST_CTR_INFO = (u32 *)(base + RGA_DST_CTR_INFO_OFFSET); - - /* Matrix reg fill */ - m0 = (s32)(tile->matrix[0] >> 18); - m1 = (s32)(tile->matrix[1] >> 18); - m2 = (s32)(tile->matrix[2] >> 18); - m3 = (s32)(tile->matrix[3] >> 18); - - *bRGA_SRC_X_PARA = (m0 & 0xffff) | (m2 << 16); - *bRGA_SRC_Y_PARA = (m1 & 0xffff) | (m3 << 16); - - /* src tile information setting */ - if(msg->rotate_mode != 0)//add by hxx,2011.7.12,for rtl0707,when line scanning ,do not calc src tile info - { - *bRGA_SRC_TILE_XINFO = (tile->tile_start_x_coor & 0xffff) | (tile->tile_w << 16); - *bRGA_SRC_TILE_YINFO = (tile->tile_start_y_coor & 0xffff) | (tile->tile_h << 16); - - *bRGA_SRC_TILE_H_INCR = ((tile->x_dx) & 0xffff) | ((tile->x_dy) << 16); - *bRGA_SRC_TILE_V_INCR = ((tile->y_dx) & 0xffff) | ((tile->y_dy) << 16); - - *bRGA_SRC_TILE_OFFSETX = tile->tile_xoff; - *bRGA_SRC_TILE_OFFSETY = tile->tile_yoff; - } - - pixel_width = RGA_pixel_width_init(msg->src.format); - - stride = ((msg->src.vir_w * pixel_width) + 3) & (~3); - - if ((msg->rotate_mode == 1)||(msg->rotate_mode == 2)||(msg->rotate_mode == 3)) - { - pos[0] = tile->tile_start_x_coor<<8; - pos[1] = tile->tile_start_y_coor<<8; - - pos[2] = pos[0]; - pos[3] = pos[1] + tile->tile_h; - - pos[4] = pos[0] + tile->tile_w; - pos[5] = pos[1] + tile->tile_h; - - pos[6] = pos[0] + tile->tile_w; - pos[7] = pos[1]; - - pos[0] >>= 11; - pos[1] >>= 11; - - pos[2] >>= 11; - pos[3] >>= 11; - - pos[4] >>= 11; - pos[5] >>= 11; - - pos[6] >>= 11; - pos[7] >>= 11; - - xmax = (MAX(MAX(MAX(pos[0], pos[2]), pos[4]), pos[6]) + 1); - xmin = (MIN(MIN(MIN(pos[0], pos[2]), pos[4]), pos[6])); - - ymax = (MAX(MAX(MAX(pos[1], pos[3]), pos[5]), pos[7]) + 1); - ymin = (MIN(MIN(MIN(pos[1], pos[3]), pos[5]), pos[7])); - - xp = xmin + msg->src.x_offset; - yp = ymin + msg->src.y_offset; - - if (!((xmax < 0)||(xmin > msg->src.act_w - 1)||(ymax < 0)||(ymin > msg->src.act_h - 1))) - { - xp = CLIP(xp, msg->src.x_offset, msg->src.x_offset + msg->src.act_w - 1); - yp = CLIP(yp, msg->src.y_offset, msg->src.y_offset + msg->src.act_h - 1); - } - - switch(msg->src.format) - { - case RK_FORMAT_YCbCr_420_P : - y_addr = msg->src.yrgb_addr + yp*stride + xp; - u_addr = msg->src.uv_addr + (yp>>1)*(stride>>1) + (xp>>1); - v_addr = msg->src.v_addr + (yp>>1)*(stride>>1) + (xp>>1); - break; - case RK_FORMAT_YCbCr_420_SP : - y_addr = msg->src.yrgb_addr + yp*stride + xp; - u_addr = msg->src.uv_addr + (yp>>1)*stride + ((xp>>1)<<1); - break; - case RK_FORMAT_YCbCr_422_P : - y_addr = msg->src.yrgb_addr + yp*stride + xp; - u_addr = msg->src.uv_addr + (yp)*(stride>>1) + (xp>>1); - v_addr = msg->src.v_addr + (yp)*(stride>>1) + (xp>>1); - break; - case RK_FORMAT_YCbCr_422_SP: - y_addr = msg->src.yrgb_addr + yp*stride + xp; - u_addr = msg->src.uv_addr + yp*stride + ((xp>>1)<<1); - break; - case RK_FORMAT_YCrCb_420_P : - y_addr = msg->src.yrgb_addr + yp*stride + xp; - u_addr = msg->src.uv_addr + (yp>>1)*(stride>>1) + (xp>>1); - v_addr = msg->src.v_addr + (yp>>1)*(stride>>1) + (xp>>1); - break; - case RK_FORMAT_YCrCb_420_SP : - y_addr = msg->src.yrgb_addr + yp*stride + xp; - u_addr = msg->src.uv_addr + (yp>>1)*stride + ((xp>>1)<<1); - break; - case RK_FORMAT_YCrCb_422_P : - y_addr = msg->src.yrgb_addr + yp*stride + xp; - u_addr = msg->src.uv_addr + (yp)*(stride>>1) + (xp>>1); - v_addr = msg->src.v_addr + (yp)*(stride>>1) + (xp>>1); - break; - case RK_FORMAT_YCrCb_422_SP: - y_addr = msg->src.yrgb_addr + yp*stride + xp; - u_addr = msg->src.uv_addr + yp*stride + ((xp>>1)<<1); - break; - default : - y_addr = msg->src.yrgb_addr + yp*stride + xp*pixel_width; - break; - } - - *bRGA_SRC_Y_MST = y_addr; - *bRGA_SRC_CB_MST = u_addr; - *bRGA_SRC_CR_MST = v_addr; - } - - /*dst info*/ - pixel_width = RGA_pixel_width_init(msg->dst.format); - stride = (msg->dst.vir_w * pixel_width + 3) & (~3); - *bRGA_DST_MST = (u32)msg->dst.yrgb_addr + (tile->dst_ctrl.y_off * stride) + (tile->dst_ctrl.x_off * pixel_width); - *bRGA_DST_CTR_INFO = (tile->dst_ctrl.w) | ((tile->dst_ctrl.h) << 16); - - *bRGA_DST_CTR_INFO |= ((1<<29) | (1<<28)); -} - - - - -/************************************************************* -Func: - RGA_set_color_palette_reg_info -Description: - fill color palette process some relate reg bit -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ +RGA_set_bitblt_reg_info(u8 *base, const struct rga_req * msg, TILE_INFO *tile) +{ + u32 *bRGA_SRC_Y_MST; + u32 *bRGA_SRC_CB_MST; + u32 *bRGA_SRC_CR_MST; + u32 *bRGA_SRC_X_PARA; + u32 *bRGA_SRC_Y_PARA; + u32 *bRGA_SRC_TILE_XINFO; + u32 *bRGA_SRC_TILE_YINFO; + u32 *bRGA_SRC_TILE_H_INCR; + u32 *bRGA_SRC_TILE_V_INCR; + u32 *bRGA_SRC_TILE_OFFSETX; + u32 *bRGA_SRC_TILE_OFFSETY; + + u32 *bRGA_DST_MST; + u32 *bRGA_DST_CTR_INFO; + + s32 m0, m1, m2, m3; + s32 pos[8]; + //s32 x_dx, x_dy, y_dx, y_dy; + s32 xmin, xmax, ymin, ymax; + s32 xp, yp; + u32 y_addr, u_addr, v_addr; + u32 pixel_width, stride; + + u_addr = v_addr = 0; + + /* src info */ + + bRGA_SRC_Y_MST = (u32 *)(base + RGA_SRC_Y_MST_OFFSET); + bRGA_SRC_CB_MST = (u32 *)(base + RGA_SRC_CB_MST_OFFSET); + bRGA_SRC_CR_MST = (u32 *)(base + RGA_SRC_CR_MST_OFFSET); + + bRGA_SRC_X_PARA = (u32 *)(base + RGA_SRC_X_PARA_OFFSET); + bRGA_SRC_Y_PARA = (u32 *)(base + RGA_SRC_Y_PARA_OFFSET); + + bRGA_SRC_TILE_XINFO = (u32 *)(base + RGA_SRC_TILE_XINFO_OFFSET); + bRGA_SRC_TILE_YINFO = (u32 *)(base + RGA_SRC_TILE_YINFO_OFFSET); + bRGA_SRC_TILE_H_INCR = (u32 *)(base + RGA_SRC_TILE_H_INCR_OFFSET); + bRGA_SRC_TILE_V_INCR = (u32 *)(base + RGA_SRC_TILE_V_INCR_OFFSET); + bRGA_SRC_TILE_OFFSETX = (u32 *)(base + RGA_SRC_TILE_OFFSETX_OFFSET); + bRGA_SRC_TILE_OFFSETY = (u32 *)(base + RGA_SRC_TILE_OFFSETY_OFFSET); + + bRGA_DST_MST = (u32 *)(base + RGA_DST_MST_OFFSET); + bRGA_DST_CTR_INFO = (u32 *)(base + RGA_DST_CTR_INFO_OFFSET); + + /* Matrix reg fill */ + m0 = (s32)(tile->matrix[0] >> 18); + m1 = (s32)(tile->matrix[1] >> 18); + m2 = (s32)(tile->matrix[2] >> 18); + m3 = (s32)(tile->matrix[3] >> 18); + + *bRGA_SRC_X_PARA = (m0 & 0xffff) | (m2 << 16); + *bRGA_SRC_Y_PARA = (m1 & 0xffff) | (m3 << 16); + + /* src tile information setting */ + if(msg->rotate_mode != 0)//add by hxx,2011.7.12,for rtl0707,when line scanning ,do not calc src tile info + { + *bRGA_SRC_TILE_XINFO = (tile->tile_start_x_coor & 0xffff) | (tile->tile_w << 16); + *bRGA_SRC_TILE_YINFO = (tile->tile_start_y_coor & 0xffff) | (tile->tile_h << 16); + + *bRGA_SRC_TILE_H_INCR = ((tile->x_dx) & 0xffff) | ((tile->x_dy) << 16); + *bRGA_SRC_TILE_V_INCR = ((tile->y_dx) & 0xffff) | ((tile->y_dy) << 16); + + *bRGA_SRC_TILE_OFFSETX = tile->tile_xoff; + *bRGA_SRC_TILE_OFFSETY = tile->tile_yoff; + } + + pixel_width = RGA_pixel_width_init(msg->src.format); + + stride = ((msg->src.vir_w * pixel_width) + 3) & (~3); + + if ((msg->rotate_mode == 1)||(msg->rotate_mode == 2)||(msg->rotate_mode == 3)) + { + pos[0] = tile->tile_start_x_coor<<8; + pos[1] = tile->tile_start_y_coor<<8; + + pos[2] = pos[0]; + pos[3] = pos[1] + tile->tile_h; + + pos[4] = pos[0] + tile->tile_w; + pos[5] = pos[1] + tile->tile_h; + + pos[6] = pos[0] + tile->tile_w; + pos[7] = pos[1]; + + pos[0] >>= 11; + pos[1] >>= 11; + + pos[2] >>= 11; + pos[3] >>= 11; + + pos[4] >>= 11; + pos[5] >>= 11; + + pos[6] >>= 11; + pos[7] >>= 11; + + xmax = (MAX(MAX(MAX(pos[0], pos[2]), pos[4]), pos[6]) + 1); + xmin = (MIN(MIN(MIN(pos[0], pos[2]), pos[4]), pos[6])); + + ymax = (MAX(MAX(MAX(pos[1], pos[3]), pos[5]), pos[7]) + 1); + ymin = (MIN(MIN(MIN(pos[1], pos[3]), pos[5]), pos[7])); + + xp = xmin + msg->src.x_offset; + yp = ymin + msg->src.y_offset; + + if (!((xmax < 0)||(xmin > msg->src.act_w - 1)||(ymax < 0)||(ymin > msg->src.act_h - 1))) + { + xp = CLIP(xp, msg->src.x_offset, msg->src.x_offset + msg->src.act_w - 1); + yp = CLIP(yp, msg->src.y_offset, msg->src.y_offset + msg->src.act_h - 1); + } + + switch(msg->src.format) + { + case RK_FORMAT_YCbCr_420_P : + y_addr = msg->src.yrgb_addr + yp*stride + xp; + u_addr = msg->src.uv_addr + (yp>>1)*(stride>>1) + (xp>>1); + v_addr = msg->src.v_addr + (yp>>1)*(stride>>1) + (xp>>1); + break; + case RK_FORMAT_YCbCr_420_SP : + y_addr = msg->src.yrgb_addr + yp*stride + xp; + u_addr = msg->src.uv_addr + (yp>>1)*stride + ((xp>>1)<<1); + break; + case RK_FORMAT_YCbCr_422_P : + y_addr = msg->src.yrgb_addr + yp*stride + xp; + u_addr = msg->src.uv_addr + (yp)*(stride>>1) + (xp>>1); + v_addr = msg->src.v_addr + (yp)*(stride>>1) + (xp>>1); + break; + case RK_FORMAT_YCbCr_422_SP: + y_addr = msg->src.yrgb_addr + yp*stride + xp; + u_addr = msg->src.uv_addr + yp*stride + ((xp>>1)<<1); + break; + case RK_FORMAT_YCrCb_420_P : + y_addr = msg->src.yrgb_addr + yp*stride + xp; + u_addr = msg->src.uv_addr + (yp>>1)*(stride>>1) + (xp>>1); + v_addr = msg->src.v_addr + (yp>>1)*(stride>>1) + (xp>>1); + break; + case RK_FORMAT_YCrCb_420_SP : + y_addr = msg->src.yrgb_addr + yp*stride + xp; + u_addr = msg->src.uv_addr + (yp>>1)*stride + ((xp>>1)<<1); + break; + case RK_FORMAT_YCrCb_422_P : + y_addr = msg->src.yrgb_addr + yp*stride + xp; + u_addr = msg->src.uv_addr + (yp)*(stride>>1) + (xp>>1); + v_addr = msg->src.v_addr + (yp)*(stride>>1) + (xp>>1); + break; + case RK_FORMAT_YCrCb_422_SP: + y_addr = msg->src.yrgb_addr + yp*stride + xp; + u_addr = msg->src.uv_addr + yp*stride + ((xp>>1)<<1); + break; + default : + y_addr = msg->src.yrgb_addr + yp*stride + xp*pixel_width; + break; + } + + *bRGA_SRC_Y_MST = y_addr; + *bRGA_SRC_CB_MST = u_addr; + *bRGA_SRC_CR_MST = v_addr; + } + + /*dst info*/ + pixel_width = RGA_pixel_width_init(msg->dst.format); + stride = (msg->dst.vir_w * pixel_width + 3) & (~3); + *bRGA_DST_MST = (u32)msg->dst.yrgb_addr + (tile->dst_ctrl.y_off * stride) + (tile->dst_ctrl.x_off * pixel_width); + *bRGA_DST_CTR_INFO = (tile->dst_ctrl.w) | ((tile->dst_ctrl.h) << 16); + + *bRGA_DST_CTR_INFO |= ((1<<29) | (1<<28)); +} + + + + +/************************************************************* +Func: + RGA_set_color_palette_reg_info +Description: + fill color palette process some relate reg bit +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ static void -RGA_set_color_palette_reg_info(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_SRC_Y_MST; - u32 p; - s16 x_off, y_off; - u16 src_stride; - u8 shift; - u16 sw, byte_num; - - x_off = msg->src.x_offset; - y_off = msg->src.y_offset; - - sw = msg->src.vir_w; - shift = 3 - (msg->palette_mode & 3); - byte_num = sw >> shift; - src_stride = (byte_num + 3) & (~3); - - p = msg->src.yrgb_addr; - p = p + (x_off>>shift) + y_off*src_stride; - - bRGA_SRC_Y_MST = (u32 *)(base + RGA_SRC_Y_MST_OFFSET); - *bRGA_SRC_Y_MST = (u32)p; -} - - -/************************************************************* -Func: - RGA_set_color_fill_reg_info -Description: - fill color fill process some relate reg bit -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ +RGA_set_color_palette_reg_info(u8 *base, const struct rga_req *msg) +{ + u32 *bRGA_SRC_Y_MST; + u32 p; + s16 x_off, y_off; + u16 src_stride; + u8 shift; + u16 sw, byte_num; + + x_off = msg->src.x_offset; + y_off = msg->src.y_offset; + + sw = msg->src.vir_w; + shift = 3 - (msg->palette_mode & 3); + byte_num = sw >> shift; + src_stride = (byte_num + 3) & (~3); + + p = msg->src.yrgb_addr; + p = p + (x_off>>shift) + y_off*src_stride; + + bRGA_SRC_Y_MST = (u32 *)(base + RGA_SRC_Y_MST_OFFSET); + *bRGA_SRC_Y_MST = (u32)p; +} + + +/************************************************************* +Func: + RGA_set_color_fill_reg_info +Description: + fill color fill process some relate reg bit +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ static void -RGA_set_color_fill_reg_info(u8 *base, const struct rga_req *msg) -{ - - u32 *bRGA_CP_GR_A; - u32 *bRGA_CP_GR_B; - u32 *bRGA_CP_GR_G; - u32 *bRGA_CP_GR_R; - - u32 *bRGA_PAT_CON; - - bRGA_CP_GR_A = (u32 *)(base + RGA_CP_GR_A_OFFSET); - bRGA_CP_GR_B = (u32 *)(base + RGA_CP_GR_B_OFFSET); - bRGA_CP_GR_G = (u32 *)(base + RGA_CP_GR_G_OFFSET); - bRGA_CP_GR_R = (u32 *)(base + RGA_CP_GR_R_OFFSET); - - bRGA_PAT_CON = (u32 *)(base + RGA_PAT_CON_OFFSET); - - *bRGA_CP_GR_A = (msg->gr_color.gr_x_a & 0xffff) | (msg->gr_color.gr_y_a << 16); - *bRGA_CP_GR_B = (msg->gr_color.gr_x_b & 0xffff) | (msg->gr_color.gr_y_b << 16); - *bRGA_CP_GR_G = (msg->gr_color.gr_x_g & 0xffff) | (msg->gr_color.gr_y_g << 16); - *bRGA_CP_GR_R = (msg->gr_color.gr_x_r & 0xffff) | (msg->gr_color.gr_y_r << 16); - - *bRGA_PAT_CON = (msg->pat.vir_w-1) | ((msg->pat.vir_h-1) << 8) | (msg->pat.x_offset << 16) | (msg->pat.y_offset << 24); - -} - - -/************************************************************* -Func: - RGA_set_line_drawing_reg_info -Description: - fill line drawing process some relate reg bit -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ +RGA_set_color_fill_reg_info(u8 *base, const struct rga_req *msg) +{ + + u32 *bRGA_CP_GR_A; + u32 *bRGA_CP_GR_B; + u32 *bRGA_CP_GR_G; + u32 *bRGA_CP_GR_R; + + u32 *bRGA_PAT_CON; + + bRGA_CP_GR_A = (u32 *)(base + RGA_CP_GR_A_OFFSET); + bRGA_CP_GR_B = (u32 *)(base + RGA_CP_GR_B_OFFSET); + bRGA_CP_GR_G = (u32 *)(base + RGA_CP_GR_G_OFFSET); + bRGA_CP_GR_R = (u32 *)(base + RGA_CP_GR_R_OFFSET); + + bRGA_PAT_CON = (u32 *)(base + RGA_PAT_CON_OFFSET); + + *bRGA_CP_GR_A = (msg->gr_color.gr_x_a & 0xffff) | (msg->gr_color.gr_y_a << 16); + *bRGA_CP_GR_B = (msg->gr_color.gr_x_b & 0xffff) | (msg->gr_color.gr_y_b << 16); + *bRGA_CP_GR_G = (msg->gr_color.gr_x_g & 0xffff) | (msg->gr_color.gr_y_g << 16); + *bRGA_CP_GR_R = (msg->gr_color.gr_x_r & 0xffff) | (msg->gr_color.gr_y_r << 16); + + *bRGA_PAT_CON = (msg->pat.vir_w-1) | ((msg->pat.vir_h-1) << 8) | (msg->pat.x_offset << 16) | (msg->pat.y_offset << 24); + +} + + +/************************************************************* +Func: + RGA_set_line_drawing_reg_info +Description: + fill line drawing process some relate reg bit +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ static s32 RGA_set_line_drawing_reg_info(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_LINE_DRAW; - u32 *bRGA_DST_VIR_INFO; - u32 *bRGA_LINE_DRAW_XY_INFO; - u32 *bRGA_LINE_DRAW_WIDTH; - u32 *bRGA_LINE_DRAWING_COLOR; - u32 *bRGA_LINE_DRAWING_MST; - - u32 reg = 0; - - s16 x_width, y_width; - u16 abs_x, abs_y, delta; - u16 stride; - u8 pw; - u32 start_addr; - u8 line_dir, dir_major, dir_semi_major; - u16 major_width; - - bRGA_LINE_DRAW = (u32 *)(base + RGA_LINE_DRAW_OFFSET); - bRGA_DST_VIR_INFO = (u32 *)(base + RGA_DST_VIR_INFO_OFFSET); - bRGA_LINE_DRAW_XY_INFO = (u32 *)(base + RGA_LINE_DRAW_XY_INFO_OFFSET); - bRGA_LINE_DRAW_WIDTH = (u32 *)(base + RGA_LINE_DRAWING_WIDTH_OFFSET); - bRGA_LINE_DRAWING_COLOR = (u32 *)(base + RGA_LINE_DRAWING_COLOR_OFFSET); - bRGA_LINE_DRAWING_MST = (u32 *)(base + RGA_LINE_DRAWING_MST_OFFSET); - - pw = RGA_pixel_width_init(msg->dst.format); - - stride = (msg->dst.vir_w * pw + 3) & (~3); - - start_addr = msg->dst.yrgb_addr - + (msg->line_draw_info.start_point.y * stride) - + (msg->line_draw_info.start_point.x * pw); - - x_width = msg->line_draw_info.start_point.x - msg->line_draw_info.end_point.x; - y_width = msg->line_draw_info.start_point.y - msg->line_draw_info.end_point.y; - - abs_x = abs(x_width); - abs_y = abs(y_width); - - if (abs_x >= abs_y) - { - if (y_width > 0) - dir_semi_major = 1; - else - dir_semi_major = 0; - - if (x_width > 0) - dir_major = 1; - else - dir_major = 0; - - if((abs_x == 0)||(abs_y == 0)) - delta = 0; - else - delta = (abs_y<<12)/abs_x; - - if (delta >> 12) - delta -= 1; - - major_width = abs_x; - line_dir = 0; - } - else - { - if (x_width > 0) - dir_semi_major = 1; - else - dir_semi_major = 0; - - if (y_width > 0) - dir_major = 1; - else - dir_major = 0; - - delta = (abs_x<<12)/abs_y; - major_width = abs_y; - line_dir = 1; - } - - reg = (reg & (~m_RGA_LINE_DRAW_MAJOR_WIDTH)) | (s_RGA_LINE_DRAW_MAJOR_WIDTH(major_width)); - reg = (reg & (~m_RGA_LINE_DRAW_LINE_DIRECTION)) | (s_RGA_LINE_DRAW_LINE_DIRECTION(line_dir)); - reg = (reg & (~m_RGA_LINE_DRAW_LINE_WIDTH)) | (s_RGA_LINE_DRAW_LINE_WIDTH(msg->line_draw_info.line_width - 1)); - reg = (reg & (~m_RGA_LINE_DRAW_INCR_VALUE)) | (s_RGA_LINE_DRAW_INCR_VALUE(delta)); - reg = (reg & (~m_RGA_LINE_DRAW_DIR_SEMI_MAJOR)) | (s_RGA_LINE_DRAW_DIR_SEMI_MAJOR(dir_semi_major)); - reg = (reg & (~m_RGA_LINE_DRAW_DIR_MAJOR)) | (s_RGA_LINE_DRAW_DIR_MAJOR(dir_major)); - reg = (reg & (~m_RGA_LINE_DRAW_LAST_POINT)) | (s_RGA_LINE_DRAW_LAST_POINT(msg->line_draw_info.flag >> 1)); - reg = (reg & (~m_RGA_LINE_DRAW_ANTI_ALISING)) | (s_RGA_LINE_DRAW_ANTI_ALISING(msg->line_draw_info.flag)); - - *bRGA_LINE_DRAW = reg; - - reg = (msg->line_draw_info.start_point.x & 0xfff) | ((msg->line_draw_info.start_point.y & 0xfff) << 16); - *bRGA_LINE_DRAW_XY_INFO = reg; - - *bRGA_LINE_DRAW_WIDTH = msg->dst.vir_w; - - *bRGA_LINE_DRAWING_COLOR = msg->line_draw_info.color; - - *bRGA_LINE_DRAWING_MST = (u32)start_addr; - - return 0; -} - - +{ + u32 *bRGA_LINE_DRAW; + u32 *bRGA_DST_VIR_INFO; + u32 *bRGA_LINE_DRAW_XY_INFO; + u32 *bRGA_LINE_DRAW_WIDTH; + u32 *bRGA_LINE_DRAWING_COLOR; + u32 *bRGA_LINE_DRAWING_MST; + + u32 reg = 0; + + s16 x_width, y_width; + u16 abs_x, abs_y, delta; + u16 stride; + u8 pw; + u32 start_addr; + u8 line_dir, dir_major, dir_semi_major; + u16 major_width; + + bRGA_LINE_DRAW = (u32 *)(base + RGA_LINE_DRAW_OFFSET); + bRGA_DST_VIR_INFO = (u32 *)(base + RGA_DST_VIR_INFO_OFFSET); + bRGA_LINE_DRAW_XY_INFO = (u32 *)(base + RGA_LINE_DRAW_XY_INFO_OFFSET); + bRGA_LINE_DRAW_WIDTH = (u32 *)(base + RGA_LINE_DRAWING_WIDTH_OFFSET); + bRGA_LINE_DRAWING_COLOR = (u32 *)(base + RGA_LINE_DRAWING_COLOR_OFFSET); + bRGA_LINE_DRAWING_MST = (u32 *)(base + RGA_LINE_DRAWING_MST_OFFSET); + + pw = RGA_pixel_width_init(msg->dst.format); + + stride = (msg->dst.vir_w * pw + 3) & (~3); + + start_addr = msg->dst.yrgb_addr + + (msg->line_draw_info.start_point.y * stride) + + (msg->line_draw_info.start_point.x * pw); + + x_width = msg->line_draw_info.start_point.x - msg->line_draw_info.end_point.x; + y_width = msg->line_draw_info.start_point.y - msg->line_draw_info.end_point.y; + + abs_x = abs(x_width); + abs_y = abs(y_width); + + if (abs_x >= abs_y) + { + if (y_width > 0) + dir_semi_major = 1; + else + dir_semi_major = 0; + + if (x_width > 0) + dir_major = 1; + else + dir_major = 0; + + if((abs_x == 0)||(abs_y == 0)) + delta = 0; + else + delta = (abs_y<<12)/abs_x; + + if (delta >> 12) + delta -= 1; + + major_width = abs_x; + line_dir = 0; + } + else + { + if (x_width > 0) + dir_semi_major = 1; + else + dir_semi_major = 0; + + if (y_width > 0) + dir_major = 1; + else + dir_major = 0; + + delta = (abs_x<<12)/abs_y; + major_width = abs_y; + line_dir = 1; + } + + reg = (reg & (~m_RGA_LINE_DRAW_MAJOR_WIDTH)) | (s_RGA_LINE_DRAW_MAJOR_WIDTH(major_width)); + reg = (reg & (~m_RGA_LINE_DRAW_LINE_DIRECTION)) | (s_RGA_LINE_DRAW_LINE_DIRECTION(line_dir)); + reg = (reg & (~m_RGA_LINE_DRAW_LINE_WIDTH)) | (s_RGA_LINE_DRAW_LINE_WIDTH(msg->line_draw_info.line_width - 1)); + reg = (reg & (~m_RGA_LINE_DRAW_INCR_VALUE)) | (s_RGA_LINE_DRAW_INCR_VALUE(delta)); + reg = (reg & (~m_RGA_LINE_DRAW_DIR_SEMI_MAJOR)) | (s_RGA_LINE_DRAW_DIR_SEMI_MAJOR(dir_semi_major)); + reg = (reg & (~m_RGA_LINE_DRAW_DIR_MAJOR)) | (s_RGA_LINE_DRAW_DIR_MAJOR(dir_major)); + reg = (reg & (~m_RGA_LINE_DRAW_LAST_POINT)) | (s_RGA_LINE_DRAW_LAST_POINT(msg->line_draw_info.flag >> 1)); + reg = (reg & (~m_RGA_LINE_DRAW_ANTI_ALISING)) | (s_RGA_LINE_DRAW_ANTI_ALISING(msg->line_draw_info.flag)); + + *bRGA_LINE_DRAW = reg; + + reg = (msg->line_draw_info.start_point.x & 0xfff) | ((msg->line_draw_info.start_point.y & 0xfff) << 16); + *bRGA_LINE_DRAW_XY_INFO = reg; + + *bRGA_LINE_DRAW_WIDTH = msg->dst.vir_w; + + *bRGA_LINE_DRAWING_COLOR = msg->line_draw_info.color; + + *bRGA_LINE_DRAWING_MST = (u32)start_addr; + + return 0; +} + + /*full*/ static s32 RGA_set_filter_reg_info(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_BLUR_SHARP_INFO; - u32 reg = 0; - - bRGA_BLUR_SHARP_INFO = (u32 *)(base + RGA_ALPHA_CON_OFFSET); - - reg = *bRGA_BLUR_SHARP_INFO; - - reg = ((reg & (~m_RGA_BLUR_SHARP_FILTER_TYPE)) | (s_RGA_BLUR_SHARP_FILTER_TYPE(msg->bsfilter_flag & 3))); - reg = ((reg & (~m_RGA_BLUR_SHARP_FILTER_MODE)) | (s_RGA_BLUR_SHARP_FILTER_MODE(msg->bsfilter_flag >>2))); - - *bRGA_BLUR_SHARP_INFO = reg; - - return 0; -} - - -/*full*/ +{ + u32 *bRGA_BLUR_SHARP_INFO; + u32 reg = 0; + + bRGA_BLUR_SHARP_INFO = (u32 *)(base + RGA_ALPHA_CON_OFFSET); + + reg = *bRGA_BLUR_SHARP_INFO; + + reg = ((reg & (~m_RGA_BLUR_SHARP_FILTER_TYPE)) | (s_RGA_BLUR_SHARP_FILTER_TYPE(msg->bsfilter_flag & 3))); + reg = ((reg & (~m_RGA_BLUR_SHARP_FILTER_MODE)) | (s_RGA_BLUR_SHARP_FILTER_MODE(msg->bsfilter_flag >>2))); + + *bRGA_BLUR_SHARP_INFO = reg; + + return 0; +} + + +/*full*/ static s32 -RGA_set_pre_scale_reg_info(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_PRE_SCALE_INFO; - u32 reg = 0; - u32 h_ratio = 0; - u32 v_ratio = 0; - u32 ps_yuv_flag = 0; - u32 src_width, src_height; - u32 dst_width, dst_height; - - src_width = msg->src.act_w; - src_height = msg->src.act_h; - - dst_width = msg->dst.act_w; - dst_height = msg->dst.act_h; - - if((dst_width == 0) || (dst_height == 0)) - { - printk("pre scale reg info error ratio is divide zero\n"); - return -EINVAL; - } - - h_ratio = (src_width <<16) / dst_width; - v_ratio = (src_height<<16) / dst_height; - - if (h_ratio <= (1<<16)) - h_ratio = 0; - else if (h_ratio <= (2<<16)) - h_ratio = 1; - else if (h_ratio <= (4<<16)) - h_ratio = 2; - else if (h_ratio <= (8<<16)) - h_ratio = 3; - - if (v_ratio <= (1<<16)) - v_ratio = 0; - else if (v_ratio <= (2<<16)) - v_ratio = 1; - else if (v_ratio <= (4<<16)) - v_ratio = 2; - else if (v_ratio <= (8<<16)) - v_ratio = 3; - - if(msg->src.format == msg->dst.format) - ps_yuv_flag = 0; - else - ps_yuv_flag = 1; - - bRGA_PRE_SCALE_INFO = (u32 *)(base + RGA_ALPHA_CON_OFFSET); - - reg = *bRGA_PRE_SCALE_INFO; - reg = ((reg & (~m_RGA_PRE_SCALE_HOR_RATIO)) | (s_RGA_PRE_SCALE_HOR_RATIO((u8)h_ratio))); - reg = ((reg & (~m_RGA_PRE_SCALE_VER_RATIO)) | (s_RGA_PRE_SCALE_VER_RATIO((u8)v_ratio))); - reg = ((reg & (~m_RGA_PRE_SCALE_OUTPUT_FORMAT)) | (s_RGA_PRE_SCALE_OUTPUT_FORMAT(ps_yuv_flag))); - - *bRGA_PRE_SCALE_INFO = reg; - - return 0; -} - - - +RGA_set_pre_scale_reg_info(u8 *base, const struct rga_req *msg) +{ + u32 *bRGA_PRE_SCALE_INFO; + u32 reg = 0; + u32 h_ratio = 0; + u32 v_ratio = 0; + u32 ps_yuv_flag = 0; + u32 src_width, src_height; + u32 dst_width, dst_height; + + src_width = msg->src.act_w; + src_height = msg->src.act_h; + + dst_width = msg->dst.act_w; + dst_height = msg->dst.act_h; + + if((dst_width == 0) || (dst_height == 0)) + { + printk("pre scale reg info error ratio is divide zero\n"); + return -EINVAL; + } + + h_ratio = (src_width <<16) / dst_width; + v_ratio = (src_height<<16) / dst_height; + + if (h_ratio <= (1<<16)) + h_ratio = 0; + else if (h_ratio <= (2<<16)) + h_ratio = 1; + else if (h_ratio <= (4<<16)) + h_ratio = 2; + else if (h_ratio <= (8<<16)) + h_ratio = 3; + + if (v_ratio <= (1<<16)) + v_ratio = 0; + else if (v_ratio <= (2<<16)) + v_ratio = 1; + else if (v_ratio <= (4<<16)) + v_ratio = 2; + else if (v_ratio <= (8<<16)) + v_ratio = 3; + + if(msg->src.format == msg->dst.format) + ps_yuv_flag = 0; + else + ps_yuv_flag = 1; + + bRGA_PRE_SCALE_INFO = (u32 *)(base + RGA_ALPHA_CON_OFFSET); + + reg = *bRGA_PRE_SCALE_INFO; + reg = ((reg & (~m_RGA_PRE_SCALE_HOR_RATIO)) | (s_RGA_PRE_SCALE_HOR_RATIO((u8)h_ratio))); + reg = ((reg & (~m_RGA_PRE_SCALE_VER_RATIO)) | (s_RGA_PRE_SCALE_VER_RATIO((u8)v_ratio))); + reg = ((reg & (~m_RGA_PRE_SCALE_OUTPUT_FORMAT)) | (s_RGA_PRE_SCALE_OUTPUT_FORMAT(ps_yuv_flag))); + + *bRGA_PRE_SCALE_INFO = reg; + + return 0; +} + + + /*full*/ static int -RGA_set_update_palette_table_reg_info(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_LUT_MST; - - if (!msg->LUT_addr) { - return -1; - } - - bRGA_LUT_MST = (u32 *)(base + RGA_LUT_MST_OFFSET); - - *bRGA_LUT_MST = (u32)msg->LUT_addr; - - return 0; -} - - - +RGA_set_update_palette_table_reg_info(u8 *base, const struct rga_req *msg) +{ + u32 *bRGA_LUT_MST; + + if (!msg->LUT_addr) { + return -1; + } + + bRGA_LUT_MST = (u32 *)(base + RGA_LUT_MST_OFFSET); + + *bRGA_LUT_MST = (u32)msg->LUT_addr; + + return 0; +} + + + /*full*/ static int -RGA_set_update_patten_buff_reg_info(u8 *base, const struct rga_req *msg) -{ - u32 *bRGA_PAT_MST; - u32 *bRGA_PAT_CON; - u32 *bRGA_PAT_START_POINT; - u32 reg = 0; - rga_img_info_t *pat; - - pat = (rga_img_info_t *)&msg->pat; - - bRGA_PAT_START_POINT = (u32 *)(base + RGA_PAT_START_POINT_OFFSET); - bRGA_PAT_MST = (u32 *)(base + RGA_PAT_MST_OFFSET); - bRGA_PAT_CON = (u32 *)(base + RGA_PAT_CON_OFFSET); - - if ( !pat->yrgb_addr ) { - return -1; - } - *bRGA_PAT_MST = (u32)pat->yrgb_addr; - - if ((pat->vir_w > 256)||(pat->x_offset > 256)||(pat->y_offset > 256)) { - return -1; - } - *bRGA_PAT_START_POINT = (pat->vir_w * pat->y_offset) + pat->x_offset; - - reg = (pat->vir_w-1) | ((pat->vir_h-1) << 8) | (pat->x_offset << 16) | (pat->y_offset << 24); - *bRGA_PAT_CON = reg; - - return 0; -} - - -/************************************************************* -Func: - RGA_set_mmu_ctrl_reg_info -Description: - fill mmu relate some reg info -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ +RGA_set_update_patten_buff_reg_info(u8 *base, const struct rga_req *msg) +{ + u32 *bRGA_PAT_MST; + u32 *bRGA_PAT_CON; + u32 *bRGA_PAT_START_POINT; + u32 reg = 0; + rga_img_info_t *pat; + + pat = (rga_img_info_t *)&msg->pat; + + bRGA_PAT_START_POINT = (u32 *)(base + RGA_PAT_START_POINT_OFFSET); + bRGA_PAT_MST = (u32 *)(base + RGA_PAT_MST_OFFSET); + bRGA_PAT_CON = (u32 *)(base + RGA_PAT_CON_OFFSET); + + if ( !pat->yrgb_addr ) { + return -1; + } + *bRGA_PAT_MST = (u32)pat->yrgb_addr; + + if ((pat->vir_w > 256)||(pat->x_offset > 256)||(pat->y_offset > 256)) { + return -1; + } + *bRGA_PAT_START_POINT = (pat->vir_w * pat->y_offset) + pat->x_offset; + + reg = (pat->vir_w-1) | ((pat->vir_h-1) << 8) | (pat->x_offset << 16) | (pat->y_offset << 24); + *bRGA_PAT_CON = reg; + + return 0; +} + + +/************************************************************* +Func: + RGA_set_mmu_ctrl_reg_info +Description: + fill mmu relate some reg info +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ static s32 -RGA_set_mmu_ctrl_reg_info(u8 *base, const struct rga_req *msg) -{ - u32 *RGA_MMU_TLB, *RGA_MMU_CTRL_ADDR; - u32 mmu_addr; - u8 TLB_size, mmu_enable, src_flag, dst_flag, CMD_flag; - u32 reg = 0; - - mmu_addr = (u32)msg->mmu_info.base_addr; - TLB_size = (msg->mmu_info.mmu_flag >> 4) & 0x3; - mmu_enable = msg->mmu_info.mmu_flag & 0x1; - - src_flag = (msg->mmu_info.mmu_flag >> 1) & 0x1; - dst_flag = (msg->mmu_info.mmu_flag >> 2) & 0x1; - CMD_flag = (msg->mmu_info.mmu_flag >> 3) & 0x1; - - RGA_MMU_TLB = (u32 *)(base + RGA_MMU_TLB_OFFSET); - RGA_MMU_CTRL_ADDR = (u32 *)(base + RGA_FADING_CON_OFFSET); - - reg = ((reg & (~m_RGA_MMU_CTRL_TLB_ADDR)) | s_RGA_MMU_CTRL_TLB_ADDR(mmu_addr)); - *RGA_MMU_TLB = reg; - - reg = *RGA_MMU_CTRL_ADDR; - reg = ((reg & (~m_RGA_MMU_CTRL_PAGE_TABLE_SIZE)) | s_RGA_MMU_CTRL_PAGE_TABLE_SIZE(TLB_size)); - reg = ((reg & (~m_RGA_MMU_CTRL_MMU_ENABLE)) | s_RGA_MMU_CTRL_MMU_ENABLE(mmu_enable)); - reg = ((reg & (~m_RGA_MMU_CTRL_SRC_FLUSH)) | s_RGA_MMU_CTRL_SRC_FLUSH(1)); - reg = ((reg & (~m_RGA_MMU_CTRL_DST_FLUSH)) | s_RGA_MMU_CTRL_DST_FLUSH(1)); - reg = ((reg & (~m_RGA_MMU_CTRL_CMD_CHAN_FLUSH)) | s_RGA_MMU_CTRL_CMD_CHAN_FLUSH(1)); - *RGA_MMU_CTRL_ADDR = reg; - - return 0; -} - - - -/************************************************************* -Func: - RGA_gen_reg_info -Description: - Generate RGA command reg list from rga_req struct. -Author: - ZhangShengqin -Date: - 20012-2-2 10:59:25 -**************************************************************/ -int -RGA_gen_reg_info(const struct rga_req *msg, unsigned char *base) -{ - TILE_INFO tile; - - memset(base, 0x0, 28*4); - RGA_set_mode_ctrl(base, msg); - - switch(msg->render_mode) - { - case bitblt_mode : - RGA_set_alpha_rop(base, msg); - RGA_set_src(base, msg); - RGA_set_dst(base, msg); - RGA_set_color(base, msg); - RGA_set_fading(base, msg); - RGA_set_pat(base, msg); - matrix_cal(msg, &tile); - dst_ctrl_cal(msg, &tile); - src_tile_info_cal(msg, &tile); - RGA_set_bitblt_reg_info(base, msg, &tile); - break; - case color_palette_mode : - RGA_set_src(base, msg); - RGA_set_dst(base, msg); - RGA_set_color(base, msg); - RGA_set_color_palette_reg_info(base, msg); - break; - case color_fill_mode : - RGA_set_alpha_rop(base, msg); - RGA_set_dst(base, msg); - RGA_set_color(base, msg); - RGA_set_pat(base, msg); - RGA_set_color_fill_reg_info(base, msg); - break; - case line_point_drawing_mode : - RGA_set_alpha_rop(base, msg); - RGA_set_dst(base, msg); - RGA_set_color(base, msg); - RGA_set_line_drawing_reg_info(base, msg); - break; - case blur_sharp_filter_mode : - RGA_set_src(base, msg); - RGA_set_dst(base, msg); - RGA_set_filter_reg_info(base, msg); - break; - case pre_scaling_mode : - RGA_set_src(base, msg); - RGA_set_dst(base, msg); - if(RGA_set_pre_scale_reg_info(base, msg) == -EINVAL) - return -1; - break; - case update_palette_table_mode : - if (RGA_set_update_palette_table_reg_info(base, msg)) { - return -1; - } - break; - case update_patten_buff_mode: - if (RGA_set_update_patten_buff_reg_info(base, msg)){ - return -1; - } - - break; - } - - RGA_set_mmu_ctrl_reg_info(base, msg); - - return 0; -} - - - +RGA_set_mmu_ctrl_reg_info(u8 *base, const struct rga_req *msg) +{ + u32 *RGA_MMU_TLB, *RGA_MMU_CTRL_ADDR; + u32 mmu_addr; + u8 TLB_size, mmu_enable, src_flag, dst_flag, CMD_flag; + u32 reg = 0; + + mmu_addr = (u32)msg->mmu_info.base_addr; + TLB_size = (msg->mmu_info.mmu_flag >> 4) & 0x3; + mmu_enable = msg->mmu_info.mmu_flag & 0x1; + + src_flag = (msg->mmu_info.mmu_flag >> 1) & 0x1; + dst_flag = (msg->mmu_info.mmu_flag >> 2) & 0x1; + CMD_flag = (msg->mmu_info.mmu_flag >> 3) & 0x1; + + RGA_MMU_TLB = (u32 *)(base + RGA_MMU_TLB_OFFSET); + RGA_MMU_CTRL_ADDR = (u32 *)(base + RGA_FADING_CON_OFFSET); + + reg = ((reg & (~m_RGA_MMU_CTRL_TLB_ADDR)) | s_RGA_MMU_CTRL_TLB_ADDR(mmu_addr)); + *RGA_MMU_TLB = reg; + + reg = *RGA_MMU_CTRL_ADDR; + reg = ((reg & (~m_RGA_MMU_CTRL_PAGE_TABLE_SIZE)) | s_RGA_MMU_CTRL_PAGE_TABLE_SIZE(TLB_size)); + reg = ((reg & (~m_RGA_MMU_CTRL_MMU_ENABLE)) | s_RGA_MMU_CTRL_MMU_ENABLE(mmu_enable)); + reg = ((reg & (~m_RGA_MMU_CTRL_SRC_FLUSH)) | s_RGA_MMU_CTRL_SRC_FLUSH(1)); + reg = ((reg & (~m_RGA_MMU_CTRL_DST_FLUSH)) | s_RGA_MMU_CTRL_DST_FLUSH(1)); + reg = ((reg & (~m_RGA_MMU_CTRL_CMD_CHAN_FLUSH)) | s_RGA_MMU_CTRL_CMD_CHAN_FLUSH(1)); + *RGA_MMU_CTRL_ADDR = reg; + + return 0; +} + + + +/************************************************************* +Func: + RGA_gen_reg_info +Description: + Generate RGA command reg list from rga_req struct. +Author: + ZhangShengqin +Date: + 20012-2-2 10:59:25 +**************************************************************/ +int +RGA_gen_reg_info(const struct rga_req *msg, unsigned char *base) +{ + TILE_INFO tile; + + memset(base, 0x0, 28*4); + RGA_set_mode_ctrl(base, msg); + + switch(msg->render_mode) + { + case bitblt_mode : + RGA_set_alpha_rop(base, msg); + RGA_set_src(base, msg); + RGA_set_dst(base, msg); + RGA_set_color(base, msg); + RGA_set_fading(base, msg); + RGA_set_pat(base, msg); + matrix_cal(msg, &tile); + dst_ctrl_cal(msg, &tile); + src_tile_info_cal(msg, &tile); + RGA_set_bitblt_reg_info(base, msg, &tile); + break; + case color_palette_mode : + RGA_set_src(base, msg); + RGA_set_dst(base, msg); + RGA_set_color(base, msg); + RGA_set_color_palette_reg_info(base, msg); + break; + case color_fill_mode : + RGA_set_alpha_rop(base, msg); + RGA_set_dst(base, msg); + RGA_set_color(base, msg); + RGA_set_pat(base, msg); + RGA_set_color_fill_reg_info(base, msg); + break; + case line_point_drawing_mode : + RGA_set_alpha_rop(base, msg); + RGA_set_dst(base, msg); + RGA_set_color(base, msg); + RGA_set_line_drawing_reg_info(base, msg); + break; + case blur_sharp_filter_mode : + RGA_set_src(base, msg); + RGA_set_dst(base, msg); + RGA_set_filter_reg_info(base, msg); + break; + case pre_scaling_mode : + RGA_set_src(base, msg); + RGA_set_dst(base, msg); + if(RGA_set_pre_scale_reg_info(base, msg) == -EINVAL) + return -1; + break; + case update_palette_table_mode : + if (RGA_set_update_palette_table_reg_info(base, msg)) { + return -1; + } + break; + case update_patten_buff_mode: + if (RGA_set_update_patten_buff_reg_info(base, msg)){ + return -1; + } + + break; + } + + RGA_set_mmu_ctrl_reg_info(base, msg); + + return 0; +} + + + diff --git a/drivers/video/rockchip/rga/rga_reg_info.h b/drivers/video/rockchip/rga/rga_reg_info.h index 565e8f72d7f0..8edbd5c3d419 100644 --- a/drivers/video/rockchip/rga/rga_reg_info.h +++ b/drivers/video/rockchip/rga/rga_reg_info.h @@ -1,467 +1,467 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __REG_INFO_H__ -#define __REG_INFO_H__ - - -//#include "chip_register.h" - -//#include "rga_struct.h" -#include "rga.h" - -#ifndef MIN -#define MIN(X, Y) ((X)<(Y)?(X):(Y)) -#endif - -#ifndef MAX -#define MAX(X, Y) ((X)>(Y)?(X):(Y)) -#endif - -#ifndef ABS -#define ABS(X) (((X) < 0) ? (-(X)) : (X)) -#endif - -#ifndef CLIP -#define CLIP(x, a, b) ((x) < (a)) ? (a) : (((x) > (b)) ? (b) : (x)) -#endif - -//RGA register map - -//General Registers -#define rRGA_SYS_CTRL (*(volatile uint32_t *)(RGA_BASE + RGA_SYS_CTRL)) -#define rRGA_CMD_CTRL (*(volatile uint32_t *)(RGA_BASE + RGA_CMD_CTRL)) -#define rRGA_CMD_ADDR (*(volatile uint32_t *)(RGA_BASE + RGA_CMD_ADDR)) -#define rRGA_STATUS (*(volatile uint32_t *)(RGA_BASE + RGA_STATUS)) -#define rRGA_INT (*(volatile uint32_t *)(RGA_BASE + RGA_INT)) -#define rRGA_AXI_ID (*(volatile uint32_t *)(RGA_BASE + RGA_AXI_ID)) -#define rRGA_MMU_STA_CTRL (*(volatile uint32_t *)(RGA_BASE + RGA_MMU_STA_CTRL)) -#define rRGA_MMU_STA (*(volatile uint32_t *)(RGA_BASE + RGA_MMU_STA)) - -//Command code start -#define rRGA_MODE_CTRL (*(volatile uint32_t *)(RGA_BASE + RGA_MODE_CTRL)) - -//Source Image Registers -#define rRGA_SRC_Y_MST (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_Y_MST)) -#define rRGA_SRC_CB_MST (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_CB_MST)) -#define rRGA_MASK_READ_MST (*(volatile uint32_t *)(RGA_BASE + RGA_MASK_READ_MST)) //repeat -#define rRGA_SRC_CR_MST (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_CR_MST)) -#define rRGA_SRC_VIR_INFO (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_VIR_INFO)) -#define rRGA_SRC_ACT_INFO (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_ACT_INFO)) -#define rRGA_SRC_X_PARA (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_X_PARA)) -#define rRGA_SRC_Y_PARA (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_Y_PARA)) -#define rRGA_SRC_TILE_XINFO (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_XINFO)) -#define rRGA_SRC_TILE_YINFO (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_YINFO)) -#define rRGA_SRC_TILE_H_INCR (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_H_INCR)) -#define rRGA_SRC_TILE_V_INCR (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_V_INCR)) -#define rRGA_SRC_TILE_OFFSETX (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_OFFSETX)) -#define rRGA_SRC_TILE_OFFSETY (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_OFFSETY)) -#define rRGA_SRC_BG_COLOR (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_BG_COLOR)) -#define rRGA_SRC_FG_COLOR (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_FG_COLOR)) -#define rRGA_LINE_DRAWING_COLOR (*(volatile uint32_t *)(RGA_BASE + RGA_LINE_DRAWING_COLOR)) //repeat -#define rRGA_SRC_TR_COLOR0 (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TR_COLOR0)) -#define rRGA_CP_GR_A (*(volatile uint32_t *)(RGA_BASE + RGA_CP_GR_A)) //repeat -#define rRGA_SRC_TR_COLOR1 (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TR_COLOR1)) -#define rRGA_CP_GR_B (*(volatile uint32_t *)(RGA_BASE + RGA_CP_GR_B)) //repeat - -#define rRGA_LINE_DRAW (*(volatile uint32_t *)(RGA_BASE + RGA_LINE_DRAW)) -#define rRGA_PAT_START_POINT (*(volatile uint32_t *)(RGA_BASE + RGA_PAT_START_POINT)) //repeat - -//Destination Image Registers -#define rRGA_DST_MST (*(volatile uint32_t *)(RGA_BASE + RGA_DST_MST)) -#define rRGA_LUT_MST (*(volatile uint32_t *)(RGA_BASE + RGA_LUT_MST)) //repeat -#define rRGA_PAT_MST (*(volatile uint32_t *)(RGA_BASE + RGA_PAT_MST)) //repeat -#define rRGA_LINE_DRAWING_MST (*(volatile uint32_t *)(RGA_BASE + RGA_LINE_DRAWING_MST)) //repeat - -#define rRGA_DST_VIR_INFO (*(volatile uint32_t *)(RGA_BASE + RGA_DST_VIR_INFO)) - -#define rRGA_DST_CTR_INFO (*(volatile uint32_t *)(RGA_BASE + RGA_DST_CTR_INFO)) -#define rRGA_LINE_DRAW_XY_INFO (*(volatile uint32_t *)(RGA_BASE + RGA_LINE_DRAW_XY_INFO)) //repeat - -//Alpha/ROP Registers -#define rRGA_ALPHA_CON (*(volatile uint32_t *)(RGA_BASE + RGA_ALPHA_CON)) -#define rRGA_FADING_CON (*(volatile uint32_t *)(RGA_BASE + RGA_FADING_CON)) - -#define rRGA_PAT_CON (*(volatile uint32_t *)(RGA_BASE + RGA_PAT_CON)) -#define rRGA_DST_VIR_WIDTH_PIX (*(volatile uint32_t *)(RGA_BASE + RGA_DST_VIR_WIDTH_PIX)) //repeat - -#define rRGA_ROP_CON0 (*(volatile uint32_t *)(RGA_BASE + RGA_ROP_CON0)) -#define rRGA_CP_GR_G (*(volatile uint32_t *)(RGA_BASE + RGA_CP_GR_G)) //repeat -#define rRGA_PRESCL_CB_MST (*(volatile uint32_t *)(RGA_BASE + RGA_PRESCL_CB_MST)) //repeat - -#define rRGA_ROP_CON1 (*(volatile uint32_t *)(RGA_BASE + RGA_ROP_CON1)) -#define rRGA_CP_GR_R (*(volatile uint32_t *)(RGA_BASE + RGA_CP_GR_R)) //repeat -#define rRGA_PRESCL_CR_MST (*(volatile uint32_t *)(RGA_BASE + RGA_PRESCL_CR_MST)) //repeat - -//MMU Register -#define rRGA_MMU_CTRL (*(volatile uint32_t *)(RGA_BASE + RGA_MMU_CTRL)) - - - - -//----------------------------------------------------------------- -//reg detail definition -//----------------------------------------------------------------- -/*RGA_SYS_CTRL*/ -#define m_RGA_SYS_CTRL_CMD_MODE ( 1<<2 ) -#define m_RGA_SYS_CTRL_OP_ST_SLV ( 1<<1 ) -#define m_RGA_sys_CTRL_SOFT_RESET ( 1<<0 ) - -#define s_RGA_SYS_CTRL_CMD_MODE(x) ( (x&0x1)<<2 ) -#define s_RGA_SYS_CTRL_OP_ST_SLV(x) ( (x&0x1)<<1 ) -#define s_RGA_sys_CTRL_SOFT_RESET(x) ( (x&0x1)<<0 ) - - -/*RGA_CMD_CTRL*/ -#define m_RGA_CMD_CTRL_CMD_INCR_NUM ( 0x3ff<<3 ) -#define m_RGA_CMD_CTRL_CMD_STOP_MODE ( 1<<2 ) -#define m_RGA_CMD_CTRL_CMD_INCR_VALID ( 1<<1 ) -#define m_RGA_CMD_CTRL_CMD_LINE_FET_ST ( 1<<0 ) - -#define s_RGA_CMD_CTRL_CMD_INCR_NUM(x) ( (x&0x3ff)<<3 ) -#define s_RGA_CMD_CTRL_CMD_STOP_MODE(x) ( (x&0x1)<<2 ) -#define s_RGA_CMD_CTRL_CMD_INCR_VALID(x) ( (x&0x1)<<1 ) -#define s_RGA_CMD_CTRL_CMD_LINE_FET_ST(x) ( (x*0x1)<<0 ) - - -/*RGA_STATUS*/ -#define m_RGA_CMD_STATUS_CMD_TOTAL_NUM ( 0xfff<<20 ) -#define m_RGA_CMD_STATUS_NOW_CMD_NUM ( 0xfff<<8 ) -#define m_RGA_CMD_STATUS_ENGINE_STATUS ( 1<<0 ) - - -/*RGA_INT*/ -#define m_RGA_INT_ALL_CMD_DONE_INT_EN ( 1<<10 ) -#define m_RGA_INT_MMU_INT_EN ( 1<<9 ) -#define m_RGA_INT_ERROR_INT_EN ( 1<<8 ) -#define m_RGA_INT_NOW_CMD_DONE_INT_CLEAR ( 1<<7 ) -#define m_RGA_INT_ALL_CMD_DONE_INT_CLEAR ( 1<<6 ) -#define m_RGA_INT_MMU_INT_CLEAR ( 1<<5 ) -#define m_RGA_INT_ERROR_INT_CLEAR ( 1<<4 ) -#define m_RGA_INT_NOW_CMD_DONE_INT_FLAG ( 1<<3 ) -#define m_RGA_INT_ALL_CMD_DONE_INT_FLAG ( 1<<2 ) -#define m_RGA_INT_MMU_INT_FLAG ( 1<<1 ) -#define m_RGA_INT_ERROR_INT_FLAG ( 1<<0 ) - -#define s_RGA_INT_ALL_CMD_DONE_INT_EN(x) ( (x&0x1)<<10 ) -#define s_RGA_INT_MMU_INT_EN(x) ( (x&0x1)<<9 ) -#define s_RGA_INT_ERROR_INT_EN(x) ( (x&0x1)<<8 ) -#define s_RGA_INT_NOW_CMD_DONE_INT_CLEAR(x) ( (x&0x1)<<7 ) -#define s_RGA_INT_ALL_CMD_DONE_INT_CLEAR(x) ( (x&0x1)<<6 ) -#define s_RGA_INT_MMU_INT_CLEAR(x) ( (x&0x1)<<5 ) -#define s_RGA_INT_ERROR_INT_CLEAR(x) ( (x&0x1)<<4 ) - - -/*RGA_AXI_ID*/ -#define m_RGA_AXI_ID_MMU_READ ( 3<<30 ) -#define m_RGA_AXI_ID_MMU_WRITE ( 3<<28 ) -#define m_RGA_AXI_ID_MASK_READ ( 0xf<<24 ) -#define m_RGA_AXI_ID_CMD_FET ( 0xf<<20 ) -#define m_RGA_AXI_ID_DST_WRITE ( 0xf<<16 ) -#define m_RGA_AXI_ID_DST_READ ( 0xf<<12 ) -#define m_RGA_AXI_ID_SRC_CR_READ ( 0xf<<8 ) -#define m_RGA_AXI_ID_SRC_CB_READ ( 0xf<<4 ) -#define m_RGA_AXI_ID_SRC_Y_READ ( 0xf<<0 ) - -#define s_RGA_AXI_ID_MMU_READ(x) ( (x&0x3)<<30 ) -#define s_RGA_AXI_ID_MMU_WRITE(x) ( (x&0x3)<<28 ) -#define s_RGA_AXI_ID_MASK_READ(x) ( (x&0xf)<<24 ) -#define s_RGA_AXI_ID_CMD_FET(x) ( (x&0xf)<<20 ) -#define s_RGA_AXI_ID_DST_WRITE(x) ( (x&0xf)<<16 ) -#define s_RGA_AXI_ID_DST_READ(x) ( (x&0xf)<<12 ) -#define s_RGA_AXI_ID_SRC_CR_READ(x) ( (x&0xf)<<8 ) -#define s_RGA_AXI_ID_SRC_CB_READ(x) ( (x&0xf)<<4 ) -#define s_RGA_AXI_ID_SRC_Y_READ(x) ( (x&0xf)<<0 ) - - -/*RGA_MMU_STA_CTRL*/ -#define m_RGA_MMU_STA_CTRL_TLB_STA_CLEAR ( 1<<3 ) -#define m_RGA_MMU_STA_CTRL_TLB_STA_RESUME ( 1<<2 ) -#define m_RGA_MMU_STA_CTRL_TLB_STA_PAUSE ( 1<<1 ) -#define m_RGA_MMU_STA_CTRL_TLB_STA_EN ( 1<<0 ) - -#define s_RGA_MMU_STA_CTRL_TLB_STA_CLEAR(x) ( (x&0x1)<<3 ) -#define s_RGA_MMU_STA_CTRL_TLB_STA_RESUME(x) ( (x&0x1)<<2 ) -#define s_RGA_MMU_STA_CTRL_TLB_STA_PAUSE(x) ( (x&0x1)<<1 ) -#define s_RGA_MMU_STA_CTRL_TLB_STA_EN(x) ( (x&0x1)<<0 ) - - - -/* RGA_MODE_CTRL */ -#define m_RGA_MODE_CTRL_2D_RENDER_MODE ( 7<<0 ) -#define m_RGA_MODE_CTRL_SRC_RGB_PACK ( 1<<3 ) -#define m_RGA_MODE_CTRL_SRC_FORMAT ( 15<<4 ) -#define m_RGA_MODE_CTRL_SRC_RB_SWAP ( 1<<8 ) -#define m_RGA_MODE_CTRL_SRC_ALPHA_SWAP ( 1<<9 ) -#define m_RGA_MODE_CTRL_SRC_UV_SWAP_MODE ( 1<<10 ) -#define m_RGA_MODE_CTRL_YUV2RGB_CON_MODE ( 3<<11 ) -#define m_RGA_MODE_CTRL_SRC_TRANS_MODE (0x1f<<13 ) -#define m_RGA_MODE_CTRL_SRC_TR_MODE ( 1<<13 ) -#define m_RGA_MODE_CTRL_SRC_TR_R_EN ( 1<<14 ) -#define m_RGA_MODE_CTRL_SRC_TR_G_EN ( 1<<15 ) -#define m_RGA_MODE_CTRL_SRC_TR_B_EN ( 1<<16 ) -#define m_RGA_MODE_CTRL_SRC_TR_A_EN ( 1<<17 ) -#define m_RGA_MODE_CTRL_ROTATE_MODE ( 3<<18 ) -#define m_RGA_MODE_CTRL_SCALE_MODE ( 3<<20 ) -#define m_RGA_MODE_CTRL_PAT_SEL ( 1<<22 ) -#define m_RGA_MODE_CTRL_DST_FORMAT ( 3<<23 ) -#define m_RGA_MODE_CTRL_DST_RGB_PACK ( 1<<25 ) -#define m_RGA_MODE_CTRL_DST_RB_SWAP ( 1<<26 ) -#define m_RGA_MODE_CTRL_DST_ALPHA_SWAP ( 1<<27 ) -#define m_RGA_MODE_CTRL_LUT_ENDIAN_MODE ( 1<<28 ) -#define m_RGA_MODE_CTRL_CMD_INT_ENABLE ( 1<<29 ) -#define m_RGA_MODE_CTRL_ZERO_MODE_ENABLE ( 1<<30 ) -#define m_RGA_MODE_CTRL_DST_ALPHA_ENABLE ( 1<<30 ) - - - -#define s_RGA_MODE_CTRL_2D_RENDER_MODE(x) ( (x&0x7)<<0 ) -#define s_RGA_MODE_CTRL_SRC_RGB_PACK(x) ( (x&0x1)<<3 ) -#define s_RGA_MODE_CTRL_SRC_FORMAT(x) ( (x&0xf)<<4 ) -#define s_RGA_MODE_CTRL_SRC_RB_SWAP(x) ( (x&0x1)<<8 ) -#define s_RGA_MODE_CTRL_SRC_ALPHA_SWAP(x) ( (x&0x1)<<9 ) -#define s_RGA_MODE_CTRL_SRC_UV_SWAP_MODE(x) ( (x&0x1)<<10 ) -#define s_RGA_MODE_CTRL_YUV2RGB_CON_MODE(x) ( (x&0x3)<<11 ) -#define s_RGA_MODE_CTRL_SRC_TRANS_MODE(x) ( (x&0x1f)<<13 ) -#define s_RGA_MODE_CTRL_SRC_TR_MODE(x) ( (x&0x1)<<13 ) -#define s_RGA_MODE_CTRL_SRC_TR_R_EN(x) ( (x&0x1)<<14 ) -#define s_RGA_MODE_CTRL_SRC_TR_G_EN(x) ( (x&0x1)<<15 ) -#define s_RGA_MODE_CTRL_SRC_TR_B_EN(x) ( (x&0x1)<<16 ) -#define s_RGA_MODE_CTRL_SRC_TR_A_EN(x) ( (x&0x1)<<17 ) -#define s_RGA_MODE_CTRL_ROTATE_MODE(x) ( (x&0x3)<<18 ) -#define s_RGA_MODE_CTRL_SCALE_MODE(x) ( (x&0x3)<<20 ) -#define s_RGA_MODE_CTRL_PAT_SEL(x) ( (x&0x1)<<22 ) -#define s_RGA_MODE_CTRL_DST_FORMAT(x) ( (x&0x3)<<23 ) -#define s_RGA_MODE_CTRL_DST_RGB_PACK(x) ( (x&0x1)<<25 ) -#define s_RGA_MODE_CTRL_DST_RB_SWAP(x) ( (x&0x1)<<26 ) -#define s_RGA_MODE_CTRL_DST_ALPHA_SWAP(x) ( (x&0x1)<<27 ) -#define s_RGA_MODE_CTRL_LUT_ENDIAN_MODE(x) ( (x&0x1)<<28 ) -#define s_RGA_MODE_CTRL_CMD_INT_ENABLE(x) ( (x&0x1)<<29 ) -#define s_RGA_MODE_CTRL_ZERO_MODE_ENABLE(x) ( (x&0x1)<<30 ) -#define s_RGA_MODE_CTRL_DST_ALPHA_ENABLE(x) ( (x&0x1)<<31 ) - - - -/* RGA_LINE_DRAW */ -#define m_RGA_LINE_DRAW_MAJOR_WIDTH ( 0x7ff<<0 ) -#define m_RGA_LINE_DRAW_LINE_DIRECTION ( 0x1<<11) -#define m_RGA_LINE_DRAW_LINE_WIDTH ( 0xf<<12) -#define m_RGA_LINE_DRAW_INCR_VALUE ( 0xfff<<16) -#define m_RGA_LINE_DRAW_DIR_MAJOR ( 0x1<<28) -#define m_RGA_LINE_DRAW_DIR_SEMI_MAJOR ( 0x1<<29) -#define m_RGA_LINE_DRAW_LAST_POINT ( 0x1<<30) -#define m_RGA_LINE_DRAW_ANTI_ALISING ( 0x1<<31) - -#define s_RGA_LINE_DRAW_MAJOR_WIDTH(x) (((x)&0x7ff)<<0 ) -#define s_RGA_LINE_DRAW_LINE_DIRECTION(x) ( ((x)&0x1)<<11) -#define s_RGA_LINE_DRAW_LINE_WIDTH(x) ( ((x)&0xf)<<12) -#define s_RGA_LINE_DRAW_INCR_VALUE(x) (((x)&0xfff)<<16) -#define s_RGA_LINE_DRAW_DIR_MAJOR(x) ( ((x)&0x1)<<28) -#define s_RGA_LINE_DRAW_DIR_SEMI_MAJOR(x) ( ((x)&0x1)<<29) -#define s_RGA_LINE_DRAW_LAST_POINT(x) ( ((x)&0x1)<<30) -#define s_RGA_LINE_DRAW_ANTI_ALISING(x) ( ((x)&0x1)<<31) - - -/* RGA_ALPHA_CON */ -#define m_RGA_ALPHA_CON_ENABLE ( 0x1<<0 ) -#define m_RGA_ALPHA_CON_A_OR_R_SEL ( 0x1<<1 ) -#define m_RGA_ALPHA_CON_ALPHA_MODE ( 0x3<<2 ) -#define m_RGA_ALPHA_CON_PD_MODE ( 0xf<<4 ) -#define m_RGA_ALPHA_CON_SET_CONSTANT_VALUE (0xff<<8 ) -#define m_RGA_ALPHA_CON_PD_M_SEL ( 0x1<<16) -#define m_RGA_ALPHA_CON_FADING_ENABLE ( 0x1<<17) -#define m_RGA_ALPHA_CON_ROP_MODE_SEL ( 0x3<<18) -#define m_RGA_ALPHA_CON_CAL_MODE_SEL ( 0x1<<28) -#define m_RGA_ALPHA_CON_DITHER_ENABLE ( 0x1<<29) -#define m_RGA_ALPHA_CON_GRADIENT_CAL_MODE ( 0x1<<30) -#define m_RGA_ALPHA_CON_AA_SEL ( 0x1<<31) - -#define s_RGA_ALPHA_CON_ENABLE(x) ( (x&0x1)<<0 ) -#define s_RGA_ALPHA_CON_A_OR_R_SEL(x) ( (x&0x1)<<1 ) -#define s_RGA_ALPHA_CON_ALPHA_MODE(x) ( (x&0x3)<<2 ) -#define s_RGA_ALPHA_CON_PD_MODE(x) ( (x&0xf)<<4 ) -#define s_RGA_ALPHA_CON_SET_CONSTANT_VALUE(x) ((x&0xff)<<8 ) -#define s_RGA_ALPHA_CON_PD_M_SEL(x) ( (x&0x1)<<16) -#define s_RGA_ALPHA_CON_FADING_ENABLE(x) ( (x&0x1)<<17) -#define s_RGA_ALPHA_CON_ROP_MODE_SEL(x) ( (x&0x3)<<18) -#define s_RGA_ALPHA_CON_CAL_MODE_SEL(x) ( (x&0x1)<<28) -#define s_RGA_ALPHA_CON_DITHER_ENABLE(x) ( (x&0x1)<<29) -#define s_RGA_ALPHA_CON_GRADIENT_CAL_MODE(x) ( (x&0x1)<<30) -#define s_RGA_ALPHA_CON_AA_SEL(x) ( (x&0x1)<<31) - - -/* blur sharp mode */ -#define m_RGA_BLUR_SHARP_FILTER_MODE ( 0x1<<25 ) -#define m_RGA_BLUR_SHARP_FILTER_TYPE ( 0x3<<26 ) - -#define s_RGA_BLUR_SHARP_FILTER_MODE(x) ( (x&0x1)<<25 ) -#define s_RGA_BLUR_SHARP_FILTER_TYPE(x) ( (x&0x3)<<26 ) - - -/* pre scale mode */ -#define m_RGA_PRE_SCALE_HOR_RATIO ( 0x3 <<20 ) -#define m_RGA_PRE_SCALE_VER_RATIO ( 0x3 <<22 ) -#define m_RGA_PRE_SCALE_OUTPUT_FORMAT ( 0x1 <<24 ) - -#define s_RGA_PRE_SCALE_HOR_RATIO(x) ( (x&0x3) <<20 ) -#define s_RGA_PRE_SCALE_VER_RATIO(x) ( (x&0x3) <<22 ) -#define s_RGA_PRE_SCALE_OUTPUT_FORMAT(x) ( (x&0x1) <<24 ) - - - -/* RGA_MMU_CTRL*/ -#define m_RGA_MMU_CTRL_TLB_ADDR ( 0xffffffff<<0) -#define m_RGA_MMU_CTRL_PAGE_TABLE_SIZE ( 0x3<<4 ) -#define m_RGA_MMU_CTRL_MMU_ENABLE ( 0x1<<0 ) -#define m_RGA_MMU_CTRL_SRC_FLUSH ( 0x1<<1 ) -#define m_RGA_MMU_CTRL_DST_FLUSH ( 0x1<<2 ) -#define m_RGA_MMU_CTRL_CMD_CHAN_FLUSH ( 0x1<<3 ) - -#define s_RGA_MMU_CTRL_TLB_ADDR(x) ((x&0xffffffff)) -#define s_RGA_MMU_CTRL_PAGE_TABLE_SIZE(x) ((x&0x3)<<4) -#define s_RGA_MMU_CTRL_MMU_ENABLE(x) ((x&0x1)<<0) -#define s_RGA_MMU_CTRL_SRC_FLUSH(x) ((x&0x1)<<1) -#define s_RGA_MMU_CTRL_DST_FLUSH(x) ((x&0x1)<<2) -#define s_RGA_MMU_CTRL_CMD_CHAN_FLUSH(x) ((x&0x1)<<3) - -#endif - -/* -#define RGA_MODE_CTRL_OFFSET 0x0 -#define RGA_SRC_Y_MST_OFFSET 0x4 -#define RGA_SRC_CB_MST_OFFSET 0x8 -#define RGA_SRC_CR_MST_OFFSET 0xc -#define RGA_SRC_VIR_INFO_OFFSET 0x10 -#define RGA_SRC_ACT_INFO_OFFSET 0x14 -#define RGA_SRC_X_PARA_OFFSET 0x18 -#define RGA_SRC_Y_PARA_OFFSET 0x1c -#define RGA_SRC_TILE_XINFO_OFFSET 0x20 -#define RGA_SRC_TILE_YINFO_OFFSET 0x24 -#define RGA_SRC_TILE_H_INCR_OFFSET 0x28 -#define RGA_SRC_TILE_V_INCR_OFFSET 0x2c -#define RGA_SRC_TILE_OFFSETX_OFFSET 0x30 -#define RGA_SRC_TILE_OFFSETY_OFFSET 0x34 -#define RGA_SRC_BG_COLOR_OFFSET 0x38 - -#define RGA_SRC_FG_COLOR_OFFSET 0x3c -#define RGA_LINE_DRAWING_COLOR_OFFSET 0x3c - -#define RGA_SRC_TR_COLOR0_OFFSET 0x40 -#define RGA_CP_GR_A_OFFSET 0x40 //repeat - -#define RGA_SRC_TR_COLOR1_OFFSET 0x44 -#define RGA_CP_GR_B_OFFSET 0x44 //repeat - -#define RGA_LINE_DRAW_OFFSET 0x48 -#define RGA_PAT_START_POINT_OFFSET 0x48 //repeat - -#define RGA_DST_MST_OFFSET 0x4c -#define RGA_LUT_MST_OFFSET 0x4c //repeat -#define RGA_PAT_MST_OFFSET 0x4c //repeat -#define RGA_LINE_DRAWING_MST_OFFSET 0x4c //repeat - -#define RGA_DST_VIR_INFO_OFFSET 0x50 - -#define RGA_DST_CTR_INFO_OFFSET 0x54 -#define RGA_LINE_DRAW_XY_INFO_OFFSET 0x54 //repeat - -#define RGA_ALPHA_CON_OFFSET 0x58 -#define RGA_FADING_CON_OFFSET 0x5c - -#define RGA_PAT_CON_OFFSET 0x60 -#define RGA_LINE_DRAWING_WIDTH_OFFSET 0x60 //repeat - -#define RGA_ROP_CON0_OFFSET 0x64 -#define RGA_CP_GR_G_OFFSET 0x64 //repeat -#define RGA_PRESCL_CB_MST_OFFSET 0x64 //repeat - -#define RGA_ROP_CON1_OFFSET 0x68 -#define RGA_CP_GR_R_OFFSET 0x68 //repeat -#define RGA_PRESCL_CR_MST_OFFSET 0x68 //repeat - -#define RGA_MMU_CTRL_OFFSET 0x6c - - -#define RGA_SYS_CTRL_OFFSET 0x000 -#define RGA_CMD_CTRL_OFFSET 0x004 -#define RGA_CMD_ADDR_OFFSET 0x008 -#define RGA_STATUS_OFFSET 0x00c -#define RGA_INT_OFFSET 0x010 -#define RGA_AXI_ID_OFFSET 0x014 -#define RGA_MMU_STA_CTRL_OFFSET 0x018 -#define RGA_MMU_STA_OFFSET 0x01c -*/ -//hxx - -#define RGA_SYS_CTRL_OFFSET (RGA_SYS_CTRL-0x100) -#define RGA_CMD_CTRL_OFFSET (RGA_CMD_CTRL-0x100) -#define RGA_CMD_ADDR_OFFSET (RGA_CMD_ADDR-0x100) -#define RGA_STATUS_OFFSET (RGA_STATUS-0x100) -#define RGA_INT_OFFSET (RGA_INT-0x100) -#define RGA_AXI_ID_OFFSET (RGA_AXI_ID-0x100) -#define RGA_MMU_STA_CTRL_OFFSET (RGA_MMU_STA_CTRL-0x100) -#define RGA_MMU_STA_OFFSET (RGA_MMU_STA-0x100) - -#define RGA_MODE_CTRL_OFFSET (RGA_MODE_CTRL-0x100) -#define RGA_SRC_Y_MST_OFFSET (RGA_SRC_Y_MST-0x100) -#define RGA_SRC_CB_MST_OFFSET (RGA_SRC_CB_MST-0x100) -#define RGA_SRC_CR_MST_OFFSET (RGA_SRC_CR_MST-0x100) -#define RGA_SRC_VIR_INFO_OFFSET (RGA_SRC_VIR_INFO-0x100) -#define RGA_SRC_ACT_INFO_OFFSET (RGA_SRC_ACT_INFO-0x100) -#define RGA_SRC_X_PARA_OFFSET (RGA_SRC_X_PARA-0x100) -#define RGA_SRC_Y_PARA_OFFSET (RGA_SRC_Y_PARA-0x100) -#define RGA_SRC_TILE_XINFO_OFFSET (RGA_SRC_TILE_XINFO-0x100) -#define RGA_SRC_TILE_YINFO_OFFSET (RGA_SRC_TILE_YINFO-0x100) -#define RGA_SRC_TILE_H_INCR_OFFSET (RGA_SRC_TILE_H_INCR-0x100) -#define RGA_SRC_TILE_V_INCR_OFFSET (RGA_SRC_TILE_V_INCR-0x100) -#define RGA_SRC_TILE_OFFSETX_OFFSET (RGA_SRC_TILE_OFFSETX-0x100) -#define RGA_SRC_TILE_OFFSETY_OFFSET (RGA_SRC_TILE_OFFSETY-0x100) -#define RGA_SRC_BG_COLOR_OFFSET (RGA_SRC_BG_COLOR-0x100) - -#define RGA_SRC_FG_COLOR_OFFSET (RGA_SRC_FG_COLOR-0x100) -#define RGA_LINE_DRAWING_COLOR_OFFSET (RGA_LINE_DRAWING_COLOR-0x100) - -#define RGA_SRC_TR_COLOR0_OFFSET (RGA_SRC_TR_COLOR0-0x100) -#define RGA_CP_GR_A_OFFSET (RGA_CP_GR_A-0x100) //repeat - -#define RGA_SRC_TR_COLOR1_OFFSET (RGA_SRC_TR_COLOR1-0x100) -#define RGA_CP_GR_B_OFFSET (RGA_CP_GR_B-0x100) //repeat - -#define RGA_LINE_DRAW_OFFSET (RGA_LINE_DRAW-0x100) -#define RGA_PAT_START_POINT_OFFSET (RGA_PAT_START_POINT-0x100) //repeat - -#define RGA_DST_MST_OFFSET (RGA_DST_MST-0x100) -#define RGA_LUT_MST_OFFSET (RGA_LUT_MST-0x100) //repeat -#define RGA_PAT_MST_OFFSET (RGA_PAT_MST-0x100) //repeat -#define RGA_LINE_DRAWING_MST_OFFSET (RGA_LINE_DRAWING_MST-0x100) //repeat - -#define RGA_DST_VIR_INFO_OFFSET (RGA_DST_VIR_INFO-0x100) - -#define RGA_DST_CTR_INFO_OFFSET (RGA_DST_CTR_INFO-0x100) -#define RGA_LINE_DRAW_XY_INFO_OFFSET (RGA_LINE_DRAW_XY_INFO-0x100) //repeat - -#define RGA_ALPHA_CON_OFFSET (RGA_ALPHA_CON-0x100) - -#define RGA_PAT_CON_OFFSET (RGA_PAT_CON-0x100) -#define RGA_LINE_DRAWING_WIDTH_OFFSET (RGA_DST_VIR_WIDTH_PIX-0x100) //repeat - -#define RGA_ROP_CON0_OFFSET (RGA_ROP_CON0-0x100) -#define RGA_CP_GR_G_OFFSET (RGA_CP_GR_G-0x100) //repeat -#define RGA_PRESCL_CB_MST_OFFSET (RGA_PRESCL_CB_MST-0x100) //repeat - -#define RGA_ROP_CON1_OFFSET (RGA_ROP_CON1-0x100) -#define RGA_CP_GR_R_OFFSET (RGA_CP_GR_R-0x100) //repeat -#define RGA_PRESCL_CR_MST_OFFSET (RGA_PRESCL_CR_MST-0x100) //repeat - -#define RGA_FADING_CON_OFFSET (RGA_FADING_CON-0x100) -#define RGA_MMU_TLB_OFFSET (RGA_MMU_TBL-0x100) - -#define RGA_YUV_OUT_CFG_OFFSET (RGA_YUV_OUT_CFG-0x100) -#define RGA_DST_UV_MST_OFFSET (RGA_DST_UV_MST-0x100) - - - -void matrix_cal(const struct rga_req *msg, TILE_INFO *tile); - - -int RGA_gen_reg_info(const struct rga_req *msg, unsigned char *base); -uint8_t RGA_pixel_width_init(uint32_t format); - +#ifndef __REG_INFO_H__ +#define __REG_INFO_H__ + + +//#include "chip_register.h" + +//#include "rga_struct.h" +#include "rga.h" + +#ifndef MIN +#define MIN(X, Y) ((X)<(Y)?(X):(Y)) +#endif + +#ifndef MAX +#define MAX(X, Y) ((X)>(Y)?(X):(Y)) +#endif + +#ifndef ABS +#define ABS(X) (((X) < 0) ? (-(X)) : (X)) +#endif + +#ifndef CLIP +#define CLIP(x, a, b) ((x) < (a)) ? (a) : (((x) > (b)) ? (b) : (x)) +#endif + +//RGA register map + +//General Registers +#define rRGA_SYS_CTRL (*(volatile uint32_t *)(RGA_BASE + RGA_SYS_CTRL)) +#define rRGA_CMD_CTRL (*(volatile uint32_t *)(RGA_BASE + RGA_CMD_CTRL)) +#define rRGA_CMD_ADDR (*(volatile uint32_t *)(RGA_BASE + RGA_CMD_ADDR)) +#define rRGA_STATUS (*(volatile uint32_t *)(RGA_BASE + RGA_STATUS)) +#define rRGA_INT (*(volatile uint32_t *)(RGA_BASE + RGA_INT)) +#define rRGA_AXI_ID (*(volatile uint32_t *)(RGA_BASE + RGA_AXI_ID)) +#define rRGA_MMU_STA_CTRL (*(volatile uint32_t *)(RGA_BASE + RGA_MMU_STA_CTRL)) +#define rRGA_MMU_STA (*(volatile uint32_t *)(RGA_BASE + RGA_MMU_STA)) + +//Command code start +#define rRGA_MODE_CTRL (*(volatile uint32_t *)(RGA_BASE + RGA_MODE_CTRL)) + +//Source Image Registers +#define rRGA_SRC_Y_MST (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_Y_MST)) +#define rRGA_SRC_CB_MST (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_CB_MST)) +#define rRGA_MASK_READ_MST (*(volatile uint32_t *)(RGA_BASE + RGA_MASK_READ_MST)) //repeat +#define rRGA_SRC_CR_MST (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_CR_MST)) +#define rRGA_SRC_VIR_INFO (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_VIR_INFO)) +#define rRGA_SRC_ACT_INFO (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_ACT_INFO)) +#define rRGA_SRC_X_PARA (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_X_PARA)) +#define rRGA_SRC_Y_PARA (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_Y_PARA)) +#define rRGA_SRC_TILE_XINFO (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_XINFO)) +#define rRGA_SRC_TILE_YINFO (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_YINFO)) +#define rRGA_SRC_TILE_H_INCR (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_H_INCR)) +#define rRGA_SRC_TILE_V_INCR (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_V_INCR)) +#define rRGA_SRC_TILE_OFFSETX (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_OFFSETX)) +#define rRGA_SRC_TILE_OFFSETY (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TILE_OFFSETY)) +#define rRGA_SRC_BG_COLOR (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_BG_COLOR)) +#define rRGA_SRC_FG_COLOR (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_FG_COLOR)) +#define rRGA_LINE_DRAWING_COLOR (*(volatile uint32_t *)(RGA_BASE + RGA_LINE_DRAWING_COLOR)) //repeat +#define rRGA_SRC_TR_COLOR0 (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TR_COLOR0)) +#define rRGA_CP_GR_A (*(volatile uint32_t *)(RGA_BASE + RGA_CP_GR_A)) //repeat +#define rRGA_SRC_TR_COLOR1 (*(volatile uint32_t *)(RGA_BASE + RGA_SRC_TR_COLOR1)) +#define rRGA_CP_GR_B (*(volatile uint32_t *)(RGA_BASE + RGA_CP_GR_B)) //repeat + +#define rRGA_LINE_DRAW (*(volatile uint32_t *)(RGA_BASE + RGA_LINE_DRAW)) +#define rRGA_PAT_START_POINT (*(volatile uint32_t *)(RGA_BASE + RGA_PAT_START_POINT)) //repeat + +//Destination Image Registers +#define rRGA_DST_MST (*(volatile uint32_t *)(RGA_BASE + RGA_DST_MST)) +#define rRGA_LUT_MST (*(volatile uint32_t *)(RGA_BASE + RGA_LUT_MST)) //repeat +#define rRGA_PAT_MST (*(volatile uint32_t *)(RGA_BASE + RGA_PAT_MST)) //repeat +#define rRGA_LINE_DRAWING_MST (*(volatile uint32_t *)(RGA_BASE + RGA_LINE_DRAWING_MST)) //repeat + +#define rRGA_DST_VIR_INFO (*(volatile uint32_t *)(RGA_BASE + RGA_DST_VIR_INFO)) + +#define rRGA_DST_CTR_INFO (*(volatile uint32_t *)(RGA_BASE + RGA_DST_CTR_INFO)) +#define rRGA_LINE_DRAW_XY_INFO (*(volatile uint32_t *)(RGA_BASE + RGA_LINE_DRAW_XY_INFO)) //repeat + +//Alpha/ROP Registers +#define rRGA_ALPHA_CON (*(volatile uint32_t *)(RGA_BASE + RGA_ALPHA_CON)) +#define rRGA_FADING_CON (*(volatile uint32_t *)(RGA_BASE + RGA_FADING_CON)) + +#define rRGA_PAT_CON (*(volatile uint32_t *)(RGA_BASE + RGA_PAT_CON)) +#define rRGA_DST_VIR_WIDTH_PIX (*(volatile uint32_t *)(RGA_BASE + RGA_DST_VIR_WIDTH_PIX)) //repeat + +#define rRGA_ROP_CON0 (*(volatile uint32_t *)(RGA_BASE + RGA_ROP_CON0)) +#define rRGA_CP_GR_G (*(volatile uint32_t *)(RGA_BASE + RGA_CP_GR_G)) //repeat +#define rRGA_PRESCL_CB_MST (*(volatile uint32_t *)(RGA_BASE + RGA_PRESCL_CB_MST)) //repeat + +#define rRGA_ROP_CON1 (*(volatile uint32_t *)(RGA_BASE + RGA_ROP_CON1)) +#define rRGA_CP_GR_R (*(volatile uint32_t *)(RGA_BASE + RGA_CP_GR_R)) //repeat +#define rRGA_PRESCL_CR_MST (*(volatile uint32_t *)(RGA_BASE + RGA_PRESCL_CR_MST)) //repeat + +//MMU Register +#define rRGA_MMU_CTRL (*(volatile uint32_t *)(RGA_BASE + RGA_MMU_CTRL)) + + + + +//----------------------------------------------------------------- +//reg detail definition +//----------------------------------------------------------------- +/*RGA_SYS_CTRL*/ +#define m_RGA_SYS_CTRL_CMD_MODE ( 1<<2 ) +#define m_RGA_SYS_CTRL_OP_ST_SLV ( 1<<1 ) +#define m_RGA_sys_CTRL_SOFT_RESET ( 1<<0 ) + +#define s_RGA_SYS_CTRL_CMD_MODE(x) ( (x&0x1)<<2 ) +#define s_RGA_SYS_CTRL_OP_ST_SLV(x) ( (x&0x1)<<1 ) +#define s_RGA_sys_CTRL_SOFT_RESET(x) ( (x&0x1)<<0 ) + + +/*RGA_CMD_CTRL*/ +#define m_RGA_CMD_CTRL_CMD_INCR_NUM ( 0x3ff<<3 ) +#define m_RGA_CMD_CTRL_CMD_STOP_MODE ( 1<<2 ) +#define m_RGA_CMD_CTRL_CMD_INCR_VALID ( 1<<1 ) +#define m_RGA_CMD_CTRL_CMD_LINE_FET_ST ( 1<<0 ) + +#define s_RGA_CMD_CTRL_CMD_INCR_NUM(x) ( (x&0x3ff)<<3 ) +#define s_RGA_CMD_CTRL_CMD_STOP_MODE(x) ( (x&0x1)<<2 ) +#define s_RGA_CMD_CTRL_CMD_INCR_VALID(x) ( (x&0x1)<<1 ) +#define s_RGA_CMD_CTRL_CMD_LINE_FET_ST(x) ( (x*0x1)<<0 ) + + +/*RGA_STATUS*/ +#define m_RGA_CMD_STATUS_CMD_TOTAL_NUM ( 0xfff<<20 ) +#define m_RGA_CMD_STATUS_NOW_CMD_NUM ( 0xfff<<8 ) +#define m_RGA_CMD_STATUS_ENGINE_STATUS ( 1<<0 ) + + +/*RGA_INT*/ +#define m_RGA_INT_ALL_CMD_DONE_INT_EN ( 1<<10 ) +#define m_RGA_INT_MMU_INT_EN ( 1<<9 ) +#define m_RGA_INT_ERROR_INT_EN ( 1<<8 ) +#define m_RGA_INT_NOW_CMD_DONE_INT_CLEAR ( 1<<7 ) +#define m_RGA_INT_ALL_CMD_DONE_INT_CLEAR ( 1<<6 ) +#define m_RGA_INT_MMU_INT_CLEAR ( 1<<5 ) +#define m_RGA_INT_ERROR_INT_CLEAR ( 1<<4 ) +#define m_RGA_INT_NOW_CMD_DONE_INT_FLAG ( 1<<3 ) +#define m_RGA_INT_ALL_CMD_DONE_INT_FLAG ( 1<<2 ) +#define m_RGA_INT_MMU_INT_FLAG ( 1<<1 ) +#define m_RGA_INT_ERROR_INT_FLAG ( 1<<0 ) + +#define s_RGA_INT_ALL_CMD_DONE_INT_EN(x) ( (x&0x1)<<10 ) +#define s_RGA_INT_MMU_INT_EN(x) ( (x&0x1)<<9 ) +#define s_RGA_INT_ERROR_INT_EN(x) ( (x&0x1)<<8 ) +#define s_RGA_INT_NOW_CMD_DONE_INT_CLEAR(x) ( (x&0x1)<<7 ) +#define s_RGA_INT_ALL_CMD_DONE_INT_CLEAR(x) ( (x&0x1)<<6 ) +#define s_RGA_INT_MMU_INT_CLEAR(x) ( (x&0x1)<<5 ) +#define s_RGA_INT_ERROR_INT_CLEAR(x) ( (x&0x1)<<4 ) + + +/*RGA_AXI_ID*/ +#define m_RGA_AXI_ID_MMU_READ ( 3<<30 ) +#define m_RGA_AXI_ID_MMU_WRITE ( 3<<28 ) +#define m_RGA_AXI_ID_MASK_READ ( 0xf<<24 ) +#define m_RGA_AXI_ID_CMD_FET ( 0xf<<20 ) +#define m_RGA_AXI_ID_DST_WRITE ( 0xf<<16 ) +#define m_RGA_AXI_ID_DST_READ ( 0xf<<12 ) +#define m_RGA_AXI_ID_SRC_CR_READ ( 0xf<<8 ) +#define m_RGA_AXI_ID_SRC_CB_READ ( 0xf<<4 ) +#define m_RGA_AXI_ID_SRC_Y_READ ( 0xf<<0 ) + +#define s_RGA_AXI_ID_MMU_READ(x) ( (x&0x3)<<30 ) +#define s_RGA_AXI_ID_MMU_WRITE(x) ( (x&0x3)<<28 ) +#define s_RGA_AXI_ID_MASK_READ(x) ( (x&0xf)<<24 ) +#define s_RGA_AXI_ID_CMD_FET(x) ( (x&0xf)<<20 ) +#define s_RGA_AXI_ID_DST_WRITE(x) ( (x&0xf)<<16 ) +#define s_RGA_AXI_ID_DST_READ(x) ( (x&0xf)<<12 ) +#define s_RGA_AXI_ID_SRC_CR_READ(x) ( (x&0xf)<<8 ) +#define s_RGA_AXI_ID_SRC_CB_READ(x) ( (x&0xf)<<4 ) +#define s_RGA_AXI_ID_SRC_Y_READ(x) ( (x&0xf)<<0 ) + + +/*RGA_MMU_STA_CTRL*/ +#define m_RGA_MMU_STA_CTRL_TLB_STA_CLEAR ( 1<<3 ) +#define m_RGA_MMU_STA_CTRL_TLB_STA_RESUME ( 1<<2 ) +#define m_RGA_MMU_STA_CTRL_TLB_STA_PAUSE ( 1<<1 ) +#define m_RGA_MMU_STA_CTRL_TLB_STA_EN ( 1<<0 ) + +#define s_RGA_MMU_STA_CTRL_TLB_STA_CLEAR(x) ( (x&0x1)<<3 ) +#define s_RGA_MMU_STA_CTRL_TLB_STA_RESUME(x) ( (x&0x1)<<2 ) +#define s_RGA_MMU_STA_CTRL_TLB_STA_PAUSE(x) ( (x&0x1)<<1 ) +#define s_RGA_MMU_STA_CTRL_TLB_STA_EN(x) ( (x&0x1)<<0 ) + + + +/* RGA_MODE_CTRL */ +#define m_RGA_MODE_CTRL_2D_RENDER_MODE ( 7<<0 ) +#define m_RGA_MODE_CTRL_SRC_RGB_PACK ( 1<<3 ) +#define m_RGA_MODE_CTRL_SRC_FORMAT ( 15<<4 ) +#define m_RGA_MODE_CTRL_SRC_RB_SWAP ( 1<<8 ) +#define m_RGA_MODE_CTRL_SRC_ALPHA_SWAP ( 1<<9 ) +#define m_RGA_MODE_CTRL_SRC_UV_SWAP_MODE ( 1<<10 ) +#define m_RGA_MODE_CTRL_YUV2RGB_CON_MODE ( 3<<11 ) +#define m_RGA_MODE_CTRL_SRC_TRANS_MODE (0x1f<<13 ) +#define m_RGA_MODE_CTRL_SRC_TR_MODE ( 1<<13 ) +#define m_RGA_MODE_CTRL_SRC_TR_R_EN ( 1<<14 ) +#define m_RGA_MODE_CTRL_SRC_TR_G_EN ( 1<<15 ) +#define m_RGA_MODE_CTRL_SRC_TR_B_EN ( 1<<16 ) +#define m_RGA_MODE_CTRL_SRC_TR_A_EN ( 1<<17 ) +#define m_RGA_MODE_CTRL_ROTATE_MODE ( 3<<18 ) +#define m_RGA_MODE_CTRL_SCALE_MODE ( 3<<20 ) +#define m_RGA_MODE_CTRL_PAT_SEL ( 1<<22 ) +#define m_RGA_MODE_CTRL_DST_FORMAT ( 3<<23 ) +#define m_RGA_MODE_CTRL_DST_RGB_PACK ( 1<<25 ) +#define m_RGA_MODE_CTRL_DST_RB_SWAP ( 1<<26 ) +#define m_RGA_MODE_CTRL_DST_ALPHA_SWAP ( 1<<27 ) +#define m_RGA_MODE_CTRL_LUT_ENDIAN_MODE ( 1<<28 ) +#define m_RGA_MODE_CTRL_CMD_INT_ENABLE ( 1<<29 ) +#define m_RGA_MODE_CTRL_ZERO_MODE_ENABLE ( 1<<30 ) +#define m_RGA_MODE_CTRL_DST_ALPHA_ENABLE ( 1<<30 ) + + + +#define s_RGA_MODE_CTRL_2D_RENDER_MODE(x) ( (x&0x7)<<0 ) +#define s_RGA_MODE_CTRL_SRC_RGB_PACK(x) ( (x&0x1)<<3 ) +#define s_RGA_MODE_CTRL_SRC_FORMAT(x) ( (x&0xf)<<4 ) +#define s_RGA_MODE_CTRL_SRC_RB_SWAP(x) ( (x&0x1)<<8 ) +#define s_RGA_MODE_CTRL_SRC_ALPHA_SWAP(x) ( (x&0x1)<<9 ) +#define s_RGA_MODE_CTRL_SRC_UV_SWAP_MODE(x) ( (x&0x1)<<10 ) +#define s_RGA_MODE_CTRL_YUV2RGB_CON_MODE(x) ( (x&0x3)<<11 ) +#define s_RGA_MODE_CTRL_SRC_TRANS_MODE(x) ( (x&0x1f)<<13 ) +#define s_RGA_MODE_CTRL_SRC_TR_MODE(x) ( (x&0x1)<<13 ) +#define s_RGA_MODE_CTRL_SRC_TR_R_EN(x) ( (x&0x1)<<14 ) +#define s_RGA_MODE_CTRL_SRC_TR_G_EN(x) ( (x&0x1)<<15 ) +#define s_RGA_MODE_CTRL_SRC_TR_B_EN(x) ( (x&0x1)<<16 ) +#define s_RGA_MODE_CTRL_SRC_TR_A_EN(x) ( (x&0x1)<<17 ) +#define s_RGA_MODE_CTRL_ROTATE_MODE(x) ( (x&0x3)<<18 ) +#define s_RGA_MODE_CTRL_SCALE_MODE(x) ( (x&0x3)<<20 ) +#define s_RGA_MODE_CTRL_PAT_SEL(x) ( (x&0x1)<<22 ) +#define s_RGA_MODE_CTRL_DST_FORMAT(x) ( (x&0x3)<<23 ) +#define s_RGA_MODE_CTRL_DST_RGB_PACK(x) ( (x&0x1)<<25 ) +#define s_RGA_MODE_CTRL_DST_RB_SWAP(x) ( (x&0x1)<<26 ) +#define s_RGA_MODE_CTRL_DST_ALPHA_SWAP(x) ( (x&0x1)<<27 ) +#define s_RGA_MODE_CTRL_LUT_ENDIAN_MODE(x) ( (x&0x1)<<28 ) +#define s_RGA_MODE_CTRL_CMD_INT_ENABLE(x) ( (x&0x1)<<29 ) +#define s_RGA_MODE_CTRL_ZERO_MODE_ENABLE(x) ( (x&0x1)<<30 ) +#define s_RGA_MODE_CTRL_DST_ALPHA_ENABLE(x) ( (x&0x1)<<31 ) + + + +/* RGA_LINE_DRAW */ +#define m_RGA_LINE_DRAW_MAJOR_WIDTH ( 0x7ff<<0 ) +#define m_RGA_LINE_DRAW_LINE_DIRECTION ( 0x1<<11) +#define m_RGA_LINE_DRAW_LINE_WIDTH ( 0xf<<12) +#define m_RGA_LINE_DRAW_INCR_VALUE ( 0xfff<<16) +#define m_RGA_LINE_DRAW_DIR_MAJOR ( 0x1<<28) +#define m_RGA_LINE_DRAW_DIR_SEMI_MAJOR ( 0x1<<29) +#define m_RGA_LINE_DRAW_LAST_POINT ( 0x1<<30) +#define m_RGA_LINE_DRAW_ANTI_ALISING ( 0x1<<31) + +#define s_RGA_LINE_DRAW_MAJOR_WIDTH(x) (((x)&0x7ff)<<0 ) +#define s_RGA_LINE_DRAW_LINE_DIRECTION(x) ( ((x)&0x1)<<11) +#define s_RGA_LINE_DRAW_LINE_WIDTH(x) ( ((x)&0xf)<<12) +#define s_RGA_LINE_DRAW_INCR_VALUE(x) (((x)&0xfff)<<16) +#define s_RGA_LINE_DRAW_DIR_MAJOR(x) ( ((x)&0x1)<<28) +#define s_RGA_LINE_DRAW_DIR_SEMI_MAJOR(x) ( ((x)&0x1)<<29) +#define s_RGA_LINE_DRAW_LAST_POINT(x) ( ((x)&0x1)<<30) +#define s_RGA_LINE_DRAW_ANTI_ALISING(x) ( ((x)&0x1)<<31) + + +/* RGA_ALPHA_CON */ +#define m_RGA_ALPHA_CON_ENABLE ( 0x1<<0 ) +#define m_RGA_ALPHA_CON_A_OR_R_SEL ( 0x1<<1 ) +#define m_RGA_ALPHA_CON_ALPHA_MODE ( 0x3<<2 ) +#define m_RGA_ALPHA_CON_PD_MODE ( 0xf<<4 ) +#define m_RGA_ALPHA_CON_SET_CONSTANT_VALUE (0xff<<8 ) +#define m_RGA_ALPHA_CON_PD_M_SEL ( 0x1<<16) +#define m_RGA_ALPHA_CON_FADING_ENABLE ( 0x1<<17) +#define m_RGA_ALPHA_CON_ROP_MODE_SEL ( 0x3<<18) +#define m_RGA_ALPHA_CON_CAL_MODE_SEL ( 0x1<<28) +#define m_RGA_ALPHA_CON_DITHER_ENABLE ( 0x1<<29) +#define m_RGA_ALPHA_CON_GRADIENT_CAL_MODE ( 0x1<<30) +#define m_RGA_ALPHA_CON_AA_SEL ( 0x1<<31) + +#define s_RGA_ALPHA_CON_ENABLE(x) ( (x&0x1)<<0 ) +#define s_RGA_ALPHA_CON_A_OR_R_SEL(x) ( (x&0x1)<<1 ) +#define s_RGA_ALPHA_CON_ALPHA_MODE(x) ( (x&0x3)<<2 ) +#define s_RGA_ALPHA_CON_PD_MODE(x) ( (x&0xf)<<4 ) +#define s_RGA_ALPHA_CON_SET_CONSTANT_VALUE(x) ((x&0xff)<<8 ) +#define s_RGA_ALPHA_CON_PD_M_SEL(x) ( (x&0x1)<<16) +#define s_RGA_ALPHA_CON_FADING_ENABLE(x) ( (x&0x1)<<17) +#define s_RGA_ALPHA_CON_ROP_MODE_SEL(x) ( (x&0x3)<<18) +#define s_RGA_ALPHA_CON_CAL_MODE_SEL(x) ( (x&0x1)<<28) +#define s_RGA_ALPHA_CON_DITHER_ENABLE(x) ( (x&0x1)<<29) +#define s_RGA_ALPHA_CON_GRADIENT_CAL_MODE(x) ( (x&0x1)<<30) +#define s_RGA_ALPHA_CON_AA_SEL(x) ( (x&0x1)<<31) + + +/* blur sharp mode */ +#define m_RGA_BLUR_SHARP_FILTER_MODE ( 0x1<<25 ) +#define m_RGA_BLUR_SHARP_FILTER_TYPE ( 0x3<<26 ) + +#define s_RGA_BLUR_SHARP_FILTER_MODE(x) ( (x&0x1)<<25 ) +#define s_RGA_BLUR_SHARP_FILTER_TYPE(x) ( (x&0x3)<<26 ) + + +/* pre scale mode */ +#define m_RGA_PRE_SCALE_HOR_RATIO ( 0x3 <<20 ) +#define m_RGA_PRE_SCALE_VER_RATIO ( 0x3 <<22 ) +#define m_RGA_PRE_SCALE_OUTPUT_FORMAT ( 0x1 <<24 ) + +#define s_RGA_PRE_SCALE_HOR_RATIO(x) ( (x&0x3) <<20 ) +#define s_RGA_PRE_SCALE_VER_RATIO(x) ( (x&0x3) <<22 ) +#define s_RGA_PRE_SCALE_OUTPUT_FORMAT(x) ( (x&0x1) <<24 ) + + + +/* RGA_MMU_CTRL*/ +#define m_RGA_MMU_CTRL_TLB_ADDR ( 0xffffffff<<0) +#define m_RGA_MMU_CTRL_PAGE_TABLE_SIZE ( 0x3<<4 ) +#define m_RGA_MMU_CTRL_MMU_ENABLE ( 0x1<<0 ) +#define m_RGA_MMU_CTRL_SRC_FLUSH ( 0x1<<1 ) +#define m_RGA_MMU_CTRL_DST_FLUSH ( 0x1<<2 ) +#define m_RGA_MMU_CTRL_CMD_CHAN_FLUSH ( 0x1<<3 ) + +#define s_RGA_MMU_CTRL_TLB_ADDR(x) ((x&0xffffffff)) +#define s_RGA_MMU_CTRL_PAGE_TABLE_SIZE(x) ((x&0x3)<<4) +#define s_RGA_MMU_CTRL_MMU_ENABLE(x) ((x&0x1)<<0) +#define s_RGA_MMU_CTRL_SRC_FLUSH(x) ((x&0x1)<<1) +#define s_RGA_MMU_CTRL_DST_FLUSH(x) ((x&0x1)<<2) +#define s_RGA_MMU_CTRL_CMD_CHAN_FLUSH(x) ((x&0x1)<<3) + +#endif + +/* +#define RGA_MODE_CTRL_OFFSET 0x0 +#define RGA_SRC_Y_MST_OFFSET 0x4 +#define RGA_SRC_CB_MST_OFFSET 0x8 +#define RGA_SRC_CR_MST_OFFSET 0xc +#define RGA_SRC_VIR_INFO_OFFSET 0x10 +#define RGA_SRC_ACT_INFO_OFFSET 0x14 +#define RGA_SRC_X_PARA_OFFSET 0x18 +#define RGA_SRC_Y_PARA_OFFSET 0x1c +#define RGA_SRC_TILE_XINFO_OFFSET 0x20 +#define RGA_SRC_TILE_YINFO_OFFSET 0x24 +#define RGA_SRC_TILE_H_INCR_OFFSET 0x28 +#define RGA_SRC_TILE_V_INCR_OFFSET 0x2c +#define RGA_SRC_TILE_OFFSETX_OFFSET 0x30 +#define RGA_SRC_TILE_OFFSETY_OFFSET 0x34 +#define RGA_SRC_BG_COLOR_OFFSET 0x38 + +#define RGA_SRC_FG_COLOR_OFFSET 0x3c +#define RGA_LINE_DRAWING_COLOR_OFFSET 0x3c + +#define RGA_SRC_TR_COLOR0_OFFSET 0x40 +#define RGA_CP_GR_A_OFFSET 0x40 //repeat + +#define RGA_SRC_TR_COLOR1_OFFSET 0x44 +#define RGA_CP_GR_B_OFFSET 0x44 //repeat + +#define RGA_LINE_DRAW_OFFSET 0x48 +#define RGA_PAT_START_POINT_OFFSET 0x48 //repeat + +#define RGA_DST_MST_OFFSET 0x4c +#define RGA_LUT_MST_OFFSET 0x4c //repeat +#define RGA_PAT_MST_OFFSET 0x4c //repeat +#define RGA_LINE_DRAWING_MST_OFFSET 0x4c //repeat + +#define RGA_DST_VIR_INFO_OFFSET 0x50 + +#define RGA_DST_CTR_INFO_OFFSET 0x54 +#define RGA_LINE_DRAW_XY_INFO_OFFSET 0x54 //repeat + +#define RGA_ALPHA_CON_OFFSET 0x58 +#define RGA_FADING_CON_OFFSET 0x5c + +#define RGA_PAT_CON_OFFSET 0x60 +#define RGA_LINE_DRAWING_WIDTH_OFFSET 0x60 //repeat + +#define RGA_ROP_CON0_OFFSET 0x64 +#define RGA_CP_GR_G_OFFSET 0x64 //repeat +#define RGA_PRESCL_CB_MST_OFFSET 0x64 //repeat + +#define RGA_ROP_CON1_OFFSET 0x68 +#define RGA_CP_GR_R_OFFSET 0x68 //repeat +#define RGA_PRESCL_CR_MST_OFFSET 0x68 //repeat + +#define RGA_MMU_CTRL_OFFSET 0x6c + + +#define RGA_SYS_CTRL_OFFSET 0x000 +#define RGA_CMD_CTRL_OFFSET 0x004 +#define RGA_CMD_ADDR_OFFSET 0x008 +#define RGA_STATUS_OFFSET 0x00c +#define RGA_INT_OFFSET 0x010 +#define RGA_AXI_ID_OFFSET 0x014 +#define RGA_MMU_STA_CTRL_OFFSET 0x018 +#define RGA_MMU_STA_OFFSET 0x01c +*/ +//hxx + +#define RGA_SYS_CTRL_OFFSET (RGA_SYS_CTRL-0x100) +#define RGA_CMD_CTRL_OFFSET (RGA_CMD_CTRL-0x100) +#define RGA_CMD_ADDR_OFFSET (RGA_CMD_ADDR-0x100) +#define RGA_STATUS_OFFSET (RGA_STATUS-0x100) +#define RGA_INT_OFFSET (RGA_INT-0x100) +#define RGA_AXI_ID_OFFSET (RGA_AXI_ID-0x100) +#define RGA_MMU_STA_CTRL_OFFSET (RGA_MMU_STA_CTRL-0x100) +#define RGA_MMU_STA_OFFSET (RGA_MMU_STA-0x100) + +#define RGA_MODE_CTRL_OFFSET (RGA_MODE_CTRL-0x100) +#define RGA_SRC_Y_MST_OFFSET (RGA_SRC_Y_MST-0x100) +#define RGA_SRC_CB_MST_OFFSET (RGA_SRC_CB_MST-0x100) +#define RGA_SRC_CR_MST_OFFSET (RGA_SRC_CR_MST-0x100) +#define RGA_SRC_VIR_INFO_OFFSET (RGA_SRC_VIR_INFO-0x100) +#define RGA_SRC_ACT_INFO_OFFSET (RGA_SRC_ACT_INFO-0x100) +#define RGA_SRC_X_PARA_OFFSET (RGA_SRC_X_PARA-0x100) +#define RGA_SRC_Y_PARA_OFFSET (RGA_SRC_Y_PARA-0x100) +#define RGA_SRC_TILE_XINFO_OFFSET (RGA_SRC_TILE_XINFO-0x100) +#define RGA_SRC_TILE_YINFO_OFFSET (RGA_SRC_TILE_YINFO-0x100) +#define RGA_SRC_TILE_H_INCR_OFFSET (RGA_SRC_TILE_H_INCR-0x100) +#define RGA_SRC_TILE_V_INCR_OFFSET (RGA_SRC_TILE_V_INCR-0x100) +#define RGA_SRC_TILE_OFFSETX_OFFSET (RGA_SRC_TILE_OFFSETX-0x100) +#define RGA_SRC_TILE_OFFSETY_OFFSET (RGA_SRC_TILE_OFFSETY-0x100) +#define RGA_SRC_BG_COLOR_OFFSET (RGA_SRC_BG_COLOR-0x100) + +#define RGA_SRC_FG_COLOR_OFFSET (RGA_SRC_FG_COLOR-0x100) +#define RGA_LINE_DRAWING_COLOR_OFFSET (RGA_LINE_DRAWING_COLOR-0x100) + +#define RGA_SRC_TR_COLOR0_OFFSET (RGA_SRC_TR_COLOR0-0x100) +#define RGA_CP_GR_A_OFFSET (RGA_CP_GR_A-0x100) //repeat + +#define RGA_SRC_TR_COLOR1_OFFSET (RGA_SRC_TR_COLOR1-0x100) +#define RGA_CP_GR_B_OFFSET (RGA_CP_GR_B-0x100) //repeat + +#define RGA_LINE_DRAW_OFFSET (RGA_LINE_DRAW-0x100) +#define RGA_PAT_START_POINT_OFFSET (RGA_PAT_START_POINT-0x100) //repeat + +#define RGA_DST_MST_OFFSET (RGA_DST_MST-0x100) +#define RGA_LUT_MST_OFFSET (RGA_LUT_MST-0x100) //repeat +#define RGA_PAT_MST_OFFSET (RGA_PAT_MST-0x100) //repeat +#define RGA_LINE_DRAWING_MST_OFFSET (RGA_LINE_DRAWING_MST-0x100) //repeat + +#define RGA_DST_VIR_INFO_OFFSET (RGA_DST_VIR_INFO-0x100) + +#define RGA_DST_CTR_INFO_OFFSET (RGA_DST_CTR_INFO-0x100) +#define RGA_LINE_DRAW_XY_INFO_OFFSET (RGA_LINE_DRAW_XY_INFO-0x100) //repeat + +#define RGA_ALPHA_CON_OFFSET (RGA_ALPHA_CON-0x100) + +#define RGA_PAT_CON_OFFSET (RGA_PAT_CON-0x100) +#define RGA_LINE_DRAWING_WIDTH_OFFSET (RGA_DST_VIR_WIDTH_PIX-0x100) //repeat + +#define RGA_ROP_CON0_OFFSET (RGA_ROP_CON0-0x100) +#define RGA_CP_GR_G_OFFSET (RGA_CP_GR_G-0x100) //repeat +#define RGA_PRESCL_CB_MST_OFFSET (RGA_PRESCL_CB_MST-0x100) //repeat + +#define RGA_ROP_CON1_OFFSET (RGA_ROP_CON1-0x100) +#define RGA_CP_GR_R_OFFSET (RGA_CP_GR_R-0x100) //repeat +#define RGA_PRESCL_CR_MST_OFFSET (RGA_PRESCL_CR_MST-0x100) //repeat + +#define RGA_FADING_CON_OFFSET (RGA_FADING_CON-0x100) +#define RGA_MMU_TLB_OFFSET (RGA_MMU_TBL-0x100) + +#define RGA_YUV_OUT_CFG_OFFSET (RGA_YUV_OUT_CFG-0x100) +#define RGA_DST_UV_MST_OFFSET (RGA_DST_UV_MST-0x100) + + + +void matrix_cal(const struct rga_req *msg, TILE_INFO *tile); + + +int RGA_gen_reg_info(const struct rga_req *msg, unsigned char *base); +uint8_t RGA_pixel_width_init(uint32_t format); + diff --git a/drivers/video/rockchip/rga/rga_rop.h b/drivers/video/rockchip/rga/rga_rop.h index ed9758711022..c38f05a13dfe 100644 --- a/drivers/video/rockchip/rga/rga_rop.h +++ b/drivers/video/rockchip/rga/rga_rop.h @@ -1,56 +1,56 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __RGA_ROP_H__ -#define __RGA_ROP_H__ - -unsigned int ROP3_code[256] = -{ - 0x00000007, 0x00000451, 0x00006051, 0x00800051, 0x00007041, 0x00800041, 0x00804830, 0x000004f0,//0 - 0x00800765, 0x000004b0, 0x00000065, 0x000004f4, 0x00000075, 0x000004e6, 0x00804850, 0x00800005, - - 0x00006850, 0x00800050, 0x00805028, 0x00000568, 0x00804031, 0x00000471, 0x002b6071, 0x018037aa,//1 - 0x008007aa, 0x00036071, 0x00002c6a, 0x00803631, 0x00002d68, 0x00802721, 0x008002d0, 0x000006d0, - - 0x0080066e, 0x00000528, 0x00000066, 0x0000056c, 0x018007aa, 0x0002e06a, 0x00003471, 0x00834031,//2 - 0x00800631, 0x0002b471, 0x00006071, 0x008037aa, 0x000036d0, 0x008002d4, 0x00002d28, 0x000006d4, - - 0x0000006e, 0x00000565, 0x00003451, 0x00800006, 0x000034f0, 0x00834830, 0x00800348, 0x00000748,//3 - 0x00002f48, 0x0080034c, 0x000034b0, 0x0000074c, 0x00000031, 0x00834850, 0x000034e6, 0x00800071, - - 0x008006f4, 0x00000431, 0x018007a1, 0x00b6e870, 0x00000074, 0x0000046e, 0x00002561, 0x00802f28,//4 - 0x00800728, 0x0002a561, 0x000026c2, 0x008002c6, 0x00007068, 0x018035aa, 0x00002c2a, 0x000006c6, - - 0x0000006c, 0x00000475, 0x000024e2, 0x008036b0, 0x00804051, 0x00800004, 0x00800251, 0x00000651, - 0x00002e4a, 0x0080024e, 0x00000028, 0x00824842, 0x000024a2, 0x0000064e, 0x000024f4, 0x00800068,//5 - - 0x008006b0, 0x000234f0, 0x00002741, 0x00800345, 0x00003651, 0x00800255, 0x00000030, 0x00834051, - 0x00a34842, 0x000002b0, 0x00800271, 0x0002b651, 0x00800368, 0x0002a741, 0x0000364e, 0x00806830,//6 - - 0x00006870, 0x008037a2, 0x00003431, 0x00000745, 0x00002521, 0x00000655, 0x0000346e, 0x00800062, - 0x008002f0, 0x000236d0, 0x000026d4, 0x00807028, 0x000036c6, 0x00806031, 0x008005aa, 0x00000671,//7 - - 0x00800671, 0x000005aa, 0x00006031, 0x008036c6, 0x00007028, 0x00802e55, 0x008236d0, 0x000002f0, - 0x00000070, 0x0080346e, 0x00800655, 0x00802521, 0x00800745, 0x00803431, 0x000037a2, 0x00806870,//8 - - 0x00006830, 0x0080364e, 0x00822f48, 0x00000361, 0x0082b651, 0x00000271, 0x00800231, 0x002b4051, - 0x00034051, 0x00800030, 0x0080026e, 0x00803651, 0x0080036c, 0x00802741, 0x008234f0, 0x000006b0,//9 - - 0x00000068, 0x00802c75, 0x0080064e, 0x008024a2, 0x0002c04a, 0x00800021, 0x00800275, 0x00802e51, - 0x00800651, 0x00000251, 0x00800000, 0x00004051, 0x000036b0, 0x008024e2, 0x00800475, 0x00000045,//a - - 0x008006c6, 0x00802c2a, 0x000035aa, 0x00807068, 0x008002f4, 0x008026c2, 0x00822d68, 0x00000728, - 0x00002f28, 0x00802561, 0x0080046e, 0x00000046, 0x00836870, 0x000007a2, 0x00800431, 0x00004071,//b - - 0x00000071, 0x008034e6, 0x00034850, 0x00800031, 0x0080074c, 0x008034b0, 0x00800365, 0x00802f48, - 0x00800748, 0x00000341, 0x000026a2, 0x008034f0, 0x00800002, 0x00005048, 0x00800565, 0x00000055,//c - - 0x008006d4, 0x00802d28, 0x008002e6, 0x008036d0, 0x000037aa, 0x00806071, 0x0082b471, 0x00000631, - 0x00002e2a, 0x00803471, 0x00826862, 0x010007aa, 0x0080056c, 0x00000054, 0x00800528, 0x00005068,//d - - 0x008006d0, 0x000002d0, 0x00002721, 0x00802d68, 0x00003631, 0x00802c6a, 0x00836071, 0x000007aa, - 0x010037aa, 0x00a36870, 0x00800471, 0x00004031, 0x00800568, 0x00005028, 0x00000050, 0x00800545,//e - - 0x00800001, 0x00004850, 0x008004e6, 0x0000004e, 0x008004f4, 0x0000004c, 0x008004b0, 0x00004870, - 0x008004f0, 0x00004830, 0x00000048, 0x0080044e, 0x00000051, 0x008004d4, 0x00800451, 0x00800007,//f -}; - -#endif +#ifndef __RGA_ROP_H__ +#define __RGA_ROP_H__ + +unsigned int ROP3_code[256] = +{ + 0x00000007, 0x00000451, 0x00006051, 0x00800051, 0x00007041, 0x00800041, 0x00804830, 0x000004f0,//0 + 0x00800765, 0x000004b0, 0x00000065, 0x000004f4, 0x00000075, 0x000004e6, 0x00804850, 0x00800005, + + 0x00006850, 0x00800050, 0x00805028, 0x00000568, 0x00804031, 0x00000471, 0x002b6071, 0x018037aa,//1 + 0x008007aa, 0x00036071, 0x00002c6a, 0x00803631, 0x00002d68, 0x00802721, 0x008002d0, 0x000006d0, + + 0x0080066e, 0x00000528, 0x00000066, 0x0000056c, 0x018007aa, 0x0002e06a, 0x00003471, 0x00834031,//2 + 0x00800631, 0x0002b471, 0x00006071, 0x008037aa, 0x000036d0, 0x008002d4, 0x00002d28, 0x000006d4, + + 0x0000006e, 0x00000565, 0x00003451, 0x00800006, 0x000034f0, 0x00834830, 0x00800348, 0x00000748,//3 + 0x00002f48, 0x0080034c, 0x000034b0, 0x0000074c, 0x00000031, 0x00834850, 0x000034e6, 0x00800071, + + 0x008006f4, 0x00000431, 0x018007a1, 0x00b6e870, 0x00000074, 0x0000046e, 0x00002561, 0x00802f28,//4 + 0x00800728, 0x0002a561, 0x000026c2, 0x008002c6, 0x00007068, 0x018035aa, 0x00002c2a, 0x000006c6, + + 0x0000006c, 0x00000475, 0x000024e2, 0x008036b0, 0x00804051, 0x00800004, 0x00800251, 0x00000651, + 0x00002e4a, 0x0080024e, 0x00000028, 0x00824842, 0x000024a2, 0x0000064e, 0x000024f4, 0x00800068,//5 + + 0x008006b0, 0x000234f0, 0x00002741, 0x00800345, 0x00003651, 0x00800255, 0x00000030, 0x00834051, + 0x00a34842, 0x000002b0, 0x00800271, 0x0002b651, 0x00800368, 0x0002a741, 0x0000364e, 0x00806830,//6 + + 0x00006870, 0x008037a2, 0x00003431, 0x00000745, 0x00002521, 0x00000655, 0x0000346e, 0x00800062, + 0x008002f0, 0x000236d0, 0x000026d4, 0x00807028, 0x000036c6, 0x00806031, 0x008005aa, 0x00000671,//7 + + 0x00800671, 0x000005aa, 0x00006031, 0x008036c6, 0x00007028, 0x00802e55, 0x008236d0, 0x000002f0, + 0x00000070, 0x0080346e, 0x00800655, 0x00802521, 0x00800745, 0x00803431, 0x000037a2, 0x00806870,//8 + + 0x00006830, 0x0080364e, 0x00822f48, 0x00000361, 0x0082b651, 0x00000271, 0x00800231, 0x002b4051, + 0x00034051, 0x00800030, 0x0080026e, 0x00803651, 0x0080036c, 0x00802741, 0x008234f0, 0x000006b0,//9 + + 0x00000068, 0x00802c75, 0x0080064e, 0x008024a2, 0x0002c04a, 0x00800021, 0x00800275, 0x00802e51, + 0x00800651, 0x00000251, 0x00800000, 0x00004051, 0x000036b0, 0x008024e2, 0x00800475, 0x00000045,//a + + 0x008006c6, 0x00802c2a, 0x000035aa, 0x00807068, 0x008002f4, 0x008026c2, 0x00822d68, 0x00000728, + 0x00002f28, 0x00802561, 0x0080046e, 0x00000046, 0x00836870, 0x000007a2, 0x00800431, 0x00004071,//b + + 0x00000071, 0x008034e6, 0x00034850, 0x00800031, 0x0080074c, 0x008034b0, 0x00800365, 0x00802f48, + 0x00800748, 0x00000341, 0x000026a2, 0x008034f0, 0x00800002, 0x00005048, 0x00800565, 0x00000055,//c + + 0x008006d4, 0x00802d28, 0x008002e6, 0x008036d0, 0x000037aa, 0x00806071, 0x0082b471, 0x00000631, + 0x00002e2a, 0x00803471, 0x00826862, 0x010007aa, 0x0080056c, 0x00000054, 0x00800528, 0x00005068,//d + + 0x008006d0, 0x000002d0, 0x00002721, 0x00802d68, 0x00003631, 0x00802c6a, 0x00836071, 0x000007aa, + 0x010037aa, 0x00a36870, 0x00800471, 0x00004031, 0x00800568, 0x00005028, 0x00000050, 0x00800545,//e + + 0x00800001, 0x00004850, 0x008004e6, 0x0000004e, 0x008004f4, 0x0000004c, 0x008004b0, 0x00004870, + 0x008004f0, 0x00004830, 0x00000048, 0x0080044e, 0x00000051, 0x008004d4, 0x00800451, 0x00800007,//f +}; + +#endif diff --git a/drivers/video/rockchip/rga/rga_type.h b/drivers/video/rockchip/rga/rga_type.h index ce3610ab9b67..30f5df2f38e5 100644 --- a/drivers/video/rockchip/rga/rga_type.h +++ b/drivers/video/rockchip/rga/rga_type.h @@ -1,49 +1,49 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __RGA_TYPE_H__ -#define __RGA_TYPE_H__ - - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif /* __cplusplus */ - -typedef unsigned int UWORD32; -typedef unsigned int uint32; -typedef unsigned int RK_U32; - -typedef unsigned short UWORD16; -typedef unsigned short RK_U16; - -typedef unsigned char UBYTE; -typedef unsigned char RK_U8; - -typedef int WORD32; -typedef int RK_S32; - -typedef short WORD16; -typedef short RK_S16; - -typedef char BYTE; -typedef char RK_S8; - - -#ifndef NULL -#define NULL 0L -#endif - -#ifndef TRUE -#define TRUE 1L -#endif - - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif /* __cplusplus */ - - -#endif /* __RGA_TYPR_H__ */ - +#ifndef __RGA_TYPE_H__ +#define __RGA_TYPE_H__ + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +typedef unsigned int UWORD32; +typedef unsigned int uint32; +typedef unsigned int RK_U32; + +typedef unsigned short UWORD16; +typedef unsigned short RK_U16; + +typedef unsigned char UBYTE; +typedef unsigned char RK_U8; + +typedef int WORD32; +typedef int RK_S32; + +typedef short WORD16; +typedef short RK_S16; + +typedef char BYTE; +typedef char RK_S8; + + +#ifndef NULL +#define NULL 0L +#endif + +#ifndef TRUE +#define TRUE 1L +#endif + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + + +#endif /* __RGA_TYPR_H__ */ + From 475afae8106b3562bb08f12c04da72bd1fdb541a Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Fri, 25 Nov 2022 14:35:06 +0800 Subject: [PATCH 153/235] video/rockchip: rga: adapt to kernel 4.4 Signed-off-by: Yu Qiaowei Change-Id: Ic1f8e21e5d1841d3533d0d74d46caf668c48645e --- drivers/video/rockchip/rga/rga_mmu_info.c | 102 ++++++++++++---------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/drivers/video/rockchip/rga/rga_mmu_info.c b/drivers/video/rockchip/rga/rga_mmu_info.c index cdd1fcd7bbcb..1380b811c2e5 100644 --- a/drivers/video/rockchip/rga/rga_mmu_info.c +++ b/drivers/video/rockchip/rga/rga_mmu_info.c @@ -44,6 +44,46 @@ static int rga_mmu_buf_get(struct rga_mmu_buf_t *t, uint32_t size) return 0; } +static void rga_current_mm_read_lock(struct mm_struct *mm) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) + mmap_read_lock(mm); +#else + down_read(&mm->mmap_sem); +#endif +} + +static void rga_current_mm_read_unlock(struct mm_struct *mm) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) + mmap_read_unlock(mm); +#else + up_read(&mm->mmap_sem); +#endif +} + +static long rga_get_user_pages(struct page **pages, unsigned long Memory, + uint32_t pageCount, int writeFlag, + struct mm_struct *current_mm) +{ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 168) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0) + return get_user_pages(current, current_mm, Memory << PAGE_SHIFT, + pageCount, writeFlag ? FOLL_WRITE : 0, pages, NULL); + #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) + return get_user_pages(current, current_mm, Memory << PAGE_SHIFT, + pageCount, writeFlag ? FOLL_WRITE : 0, 0, pages, NULL); + #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) + return get_user_pages_remote(current, current_mm, Memory << PAGE_SHIFT, + pageCount, writeFlag ? FOLL_WRITE : 0, pages, + NULL, NULL); + #else + return get_user_pages_remote(current_mm, Memory << PAGE_SHIFT, + pageCount, writeFlag ? FOLL_WRITE : 0, pages, + NULL, NULL); + #endif +} + static int rga_mmu_buf_get_try(struct rga_mmu_buf_t *t, uint32_t size) { int ret = 0; @@ -333,29 +373,11 @@ static int rga_MapUserMemory(struct page **pages, Address = 0; do { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) - mmap_read_lock(current->mm); -#else - down_read(¤t->mm->mmap_sem); -#endif + rga_current_mm_read_lock(current->mm); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) - result = get_user_pages(current, current->mm, - Memory << PAGE_SHIFT, pageCount, 1, 0, - pages, NULL); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0) - result = get_user_pages_remote(current, current->mm, - Memory << PAGE_SHIFT, pageCount, 1, pages, NULL, NULL); -#else - result = get_user_pages_remote(current->mm, Memory << PAGE_SHIFT, - pageCount, 1, pages, NULL, NULL); -#endif + result = rga_get_user_pages(pages, Memory, pageCount, 1, current->mm); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) - mmap_read_unlock(current->mm); -#else - up_read(¤t->mm->mmap_sem); -#endif + rga_current_mm_read_unlock(current->mm); #if 0 if(result <= 0 || result < pageCount) @@ -383,19 +405,13 @@ static int rga_MapUserMemory(struct page **pages, struct vm_area_struct *vma; if (result>0) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) - mmap_read_lock(current->mm); -#else - down_read(¤t->mm->mmap_sem); -#endif - for (i = 0; i < result; i++) - put_page(pages[i]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) - mmap_read_unlock(current->mm); -#else - up_read(¤t->mm->mmap_sem); -#endif - } + rga_current_mm_read_lock(current->mm); + + for (i = 0; i < result; i++) + put_page(pages[i]); + + rga_current_mm_read_unlock(current->mm); + } for(i=0; i= KERNEL_VERSION(5, 10, 0) - mmap_read_lock(current->mm); -#else - down_read(¤t->mm->mmap_sem); -#endif - for (i = 0; i < result; i++) - put_page(pages[i]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) - mmap_read_unlock(current->mm); -#else - up_read(¤t->mm->mmap_sem); -#endif + rga_current_mm_read_lock(current->mm); + + for (i = 0; i < result; i++) + put_page(pages[i]); + + rga_current_mm_read_unlock(current->mm); return 0; } From f0e546653b04cc83854e481a255d6e9aed75fdd1 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Mon, 28 Nov 2022 11:17:59 +0800 Subject: [PATCH 154/235] video/rockchip: rga: fix bug with time debug nodes Signed-off-by: Yu Qiaowei Change-Id: Ie58a83af91c79e79cd6b85eeea78cf7ff820393c --- drivers/video/rockchip/rga/rga_drv.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/video/rockchip/rga/rga_drv.c b/drivers/video/rockchip/rga/rga_drv.c index c5583736e54a..28275d48900a 100644 --- a/drivers/video/rockchip/rga/rga_drv.c +++ b/drivers/video/rockchip/rga/rga_drv.c @@ -853,7 +853,7 @@ static void rga_try_set_reg(void) rga_write(rga_read(RGA_INT)|(0x1<<10)|(0x1<<8), RGA_INT); #if RGA_DEBUGFS - if (RGA_TEST_REG) + if (RGA_TEST_TIME) rga_start = ktime_get(); #endif @@ -1566,7 +1566,7 @@ static int rga_blit_sync(rga_session *session, struct rga_req *req) if (RGA_TEST_TIME) { rga_end = ktime_get(); rga_end = ktime_sub(rga_end, rga_start); - DBG("sync one cmd end time %d\n", (int)ktime_to_us(rga_end)); + DBG("sync one cmd end time %d us\n", (int)ktime_to_us(rga_end)); } #endif @@ -1740,7 +1740,6 @@ static int rga_release(struct inode *inode, struct file *file) { pr_err("rga_service session %d still has %d task running when closing\n", session->pid, task_running); msleep(100); - /*ͬ²½*/ } wake_up(&session->wait); @@ -2356,7 +2355,7 @@ static int __init rga_init(void) rga_debugfs_add(); #endif - INFO("Module initialized.\n"); + INFO("RGA Module initialized.\n"); return 0; } From f60012eb97a7bf5aa6ac5964edbe0edf86d8a1c0 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Mon, 28 Nov 2022 11:22:54 +0800 Subject: [PATCH 155/235] video/rockchip: rga: rename drvdata to rga_drvdata Signed-off-by: Yu Qiaowei Change-Id: I28e7255f1e08a2c85476053395172bcd0a6615bf --- drivers/video/rockchip/rga/rga_drv.c | 90 +++++++++++------------ drivers/video/rockchip/rga/rga_mmu_info.c | 2 +- drivers/video/rockchip/rga/rga_mmu_info.h | 2 +- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/drivers/video/rockchip/rga/rga_drv.c b/drivers/video/rockchip/rga/rga_drv.c index 28275d48900a..4cda1908a9c5 100644 --- a/drivers/video/rockchip/rga/rga_drv.c +++ b/drivers/video/rockchip/rga/rga_drv.c @@ -84,7 +84,7 @@ ktime_t rga_start; ktime_t rga_end; -rga_session rga_session_global; +static rga_session rga_session_global; long (*rga_ioctl_kernel_p)(struct rga_req *); @@ -97,7 +97,7 @@ unsigned char RGA_NONUSE; unsigned char RGA_INT_FLAG; #endif -struct rga_drvdata *drvdata; +struct rga_drvdata *rga_drvdata; rga_service_info rga_service; struct rga_mmu_buf_t rga_mmu_buf; @@ -410,12 +410,12 @@ static int rga_memory_check(void *vaddr, u32 w, u32 h, u32 format, int fd) static inline void rga_write(u32 b, u32 r) { - __raw_writel(b, drvdata->rga_base + r); + __raw_writel(b, rga_drvdata->rga_base + r); } static inline u32 rga_read(u32 r) { - return __raw_readl(drvdata->rga_base + r); + return __raw_readl(rga_drvdata->rga_base + r); } static void rga_soft_reset(void) @@ -509,9 +509,9 @@ static void rga_dump(void) static inline void rga_queue_power_off_work(void) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) - queue_delayed_work(system_wq, &drvdata->power_off_work, RGA_POWER_OFF_DELAY); + queue_delayed_work(system_wq, &rga_drvdata->power_off_work, RGA_POWER_OFF_DELAY); #else - queue_delayed_work(system_nrt_wq, &drvdata->power_off_work, RGA_POWER_OFF_DELAY); + queue_delayed_work(system_nrt_wq, &rga_drvdata->power_off_work, RGA_POWER_OFF_DELAY); #endif } @@ -522,7 +522,7 @@ static void rga_power_on(void) ktime_t now = ktime_get(); if (ktime_to_ns(ktime_sub(now, last)) > NSEC_PER_SEC) { - cancel_delayed_work_sync(&drvdata->power_off_work); + cancel_delayed_work_sync(&rga_drvdata->power_off_work); rga_queue_power_off_work(); last = now; } @@ -530,17 +530,17 @@ static void rga_power_on(void) return; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) - clk_prepare_enable(drvdata->aclk_rga); - clk_prepare_enable(drvdata->hclk_rga); - pm_runtime_get_sync(drvdata->dev); + clk_prepare_enable(rga_drvdata->aclk_rga); + clk_prepare_enable(rga_drvdata->hclk_rga); + pm_runtime_get_sync(rga_drvdata->dev); #else - clk_prepare_enable(drvdata->aclk_rga); - clk_prepare_enable(drvdata->hclk_rga); - if (drvdata->pd_rga) - clk_prepare_enable(drvdata->pd_rga); + clk_prepare_enable(rga_drvdata->aclk_rga); + clk_prepare_enable(rga_drvdata->hclk_rga); + if (rga_drvdata->pd_rga) + clk_prepare_enable(rga_drvdata->pd_rga); #endif - wake_lock(&drvdata->wake_lock); + wake_lock(&rga_drvdata->wake_lock); rga_service.enable = true; } @@ -562,16 +562,16 @@ static void rga_power_off(void) } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) - pm_runtime_put(drvdata->dev); - clk_disable_unprepare(drvdata->aclk_rga); - clk_disable_unprepare(drvdata->hclk_rga); + pm_runtime_put(rga_drvdata->dev); + clk_disable_unprepare(rga_drvdata->aclk_rga); + clk_disable_unprepare(rga_drvdata->hclk_rga); #else - if (drvdata->pd_rga) - clk_disable_unprepare(drvdata->pd_rga); - clk_disable_unprepare(drvdata->aclk_rga); - clk_disable_unprepare(drvdata->hclk_rga); + if (rga_drvdata->pd_rga) + clk_disable_unprepare(rga_drvdata->pd_rga); + clk_disable_unprepare(rga_drvdata->aclk_rga); + clk_disable_unprepare(rga_drvdata->hclk_rga); #endif - wake_unlock(&drvdata->wake_lock); + wake_unlock(&rga_drvdata->wake_lock); rga_service.enable = false; } @@ -628,7 +628,7 @@ static int rga_flush(rga_session *session, unsigned long arg) static int rga_get_result(rga_session *session, unsigned long arg) { - //printk("rga_get_result %d\n",drvdata->rga_result); + //printk("rga_get_result %d\n",rga_drvdata->rga_result); int ret = 0; @@ -1010,7 +1010,7 @@ static int rga_convert_dma_buf(struct rga_req *req) dst_offset = req->line_draw_info.line_width; if (req->src.yrgb_addr) { - hdl = ion_import_dma_buf(drvdata->ion_client, req->src.yrgb_addr); + hdl = ion_import_dma_buf(rga_drvdata->ion_client, req->src.yrgb_addr); if (IS_ERR(hdl)) { ret = PTR_ERR(hdl); pr_err("RGA ERROR ion buf handle\n"); @@ -1025,26 +1025,26 @@ static int rga_convert_dma_buf(struct rga_req *req) #if RGA_DEBUGFS if (RGA_CHECK_MODE) { - vaddr = ion_map_kernel(drvdata->ion_client, hdl); + vaddr = ion_map_kernel(rga_drvdata->ion_client, hdl); if (vaddr) rga_memory_check(vaddr, req->src.vir_h, req->src.vir_w, req->src.format, req->src.yrgb_addr); - ion_unmap_kernel(drvdata->ion_client, hdl); + ion_unmap_kernel(rga_drvdata->ion_client, hdl); } #endif if ((req->mmu_info.mmu_flag >> 8) & 1) { - req->sg_src = ion_sg_table(drvdata->ion_client, hdl); + req->sg_src = ion_sg_table(rga_drvdata->ion_client, hdl); req->src.yrgb_addr = req->src.uv_addr; req->src.uv_addr = req->src.yrgb_addr + (req->src.vir_w * req->src.vir_h); req->src.v_addr = req->src.uv_addr + (req->src.vir_w * req->src.vir_h)/4; } else { - ion_phys(drvdata->ion_client, hdl, &phy_addr, &len); + ion_phys(rga_drvdata->ion_client, hdl, &phy_addr, &len); req->src.yrgb_addr = phy_addr + src_offset; req->src.uv_addr = req->src.yrgb_addr + (req->src.vir_w * req->src.vir_h); req->src.v_addr = req->src.uv_addr + (req->src.vir_w * req->src.vir_h)/4; } - ion_free(drvdata->ion_client, hdl); + ion_free(rga_drvdata->ion_client, hdl); } else { req->src.yrgb_addr = req->src.uv_addr; @@ -1053,7 +1053,7 @@ static int rga_convert_dma_buf(struct rga_req *req) } if(req->dst.yrgb_addr) { - hdl = ion_import_dma_buf(drvdata->ion_client, req->dst.yrgb_addr); + hdl = ion_import_dma_buf(rga_drvdata->ion_client, req->dst.yrgb_addr); if (IS_ERR(hdl)) { ret = PTR_ERR(hdl); printk("RGA2 ERROR ion buf handle\n"); @@ -1068,26 +1068,26 @@ static int rga_convert_dma_buf(struct rga_req *req) #if RGA_DEBUGFS if (RGA_CHECK_MODE) { - vaddr = ion_map_kernel(drvdata->ion_client, hdl); + vaddr = ion_map_kernel(rga_drvdata->ion_client, hdl); if (vaddr) rga_memory_check(vaddr, req->src.vir_h, req->src.vir_w, req->src.format, req->src.yrgb_addr); - ion_unmap_kernel(drvdata->ion_client, hdl); + ion_unmap_kernel(rga_drvdata->ion_client, hdl); } #endif if ((req->mmu_info.mmu_flag >> 10) & 1) { - req->sg_dst = ion_sg_table(drvdata->ion_client, hdl); + req->sg_dst = ion_sg_table(rga_drvdata->ion_client, hdl); req->dst.yrgb_addr = req->dst.uv_addr; req->dst.uv_addr = req->dst.yrgb_addr + (req->dst.vir_w * req->dst.vir_h); req->dst.v_addr = req->dst.uv_addr + (req->dst.vir_w * req->dst.vir_h)/4; } else { - ion_phys(drvdata->ion_client, hdl, &phy_addr, &len); + ion_phys(rga_drvdata->ion_client, hdl, &phy_addr, &len); req->dst.yrgb_addr = phy_addr + dst_offset; req->dst.uv_addr = req->dst.yrgb_addr + (req->dst.vir_w * req->dst.vir_h); req->dst.v_addr = req->dst.uv_addr + (req->dst.vir_w * req->dst.vir_h)/4; } - ion_free(drvdata->ion_client, hdl); + ion_free(rga_drvdata->ion_client, hdl); } else { req->dst.yrgb_addr = req->dst.uv_addr; @@ -1114,7 +1114,7 @@ static int rga_get_img_info(rga_img_info_t *img, int ret = 0; void *vaddr = NULL; - rga_dev = drvdata->dev; + rga_dev = rga_drvdata->dev; yrgb_addr = (int)img->yrgb_addr; vir_w = img->vir_w; vir_h = img->vir_h; @@ -1634,21 +1634,21 @@ static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg) ret = rga_get_result(session, arg); break; case RGA_GET_VERSION: - if (!drvdata->version) { - drvdata->version = kzalloc(16, GFP_KERNEL); - if (!drvdata->version) { + if (!rga_drvdata->version) { + rga_drvdata->version = kzalloc(16, GFP_KERNEL); + if (!rga_drvdata->version) { ret = -ENOMEM; break; } rga_power_on(); udelay(1); if (rga_read(RGA_VERSION) == 0x02018632) - snprintf(drvdata->version, 16, "1.6"); + snprintf(rga_drvdata->version, 16, "1.6"); else - snprintf(drvdata->version, 16, "1.003"); + snprintf(rga_drvdata->version, 16, "1.003"); } - ret = copy_to_user((void *)arg, drvdata->version, 16); + ret = copy_to_user((void *)arg, rga_drvdata->version, 16); break; default: ERR("unknown ioctl cmd!\n"); @@ -1867,7 +1867,7 @@ static int rga_drv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); data->dev = &pdev->dev; - drvdata = data; + rga_drvdata = data; #if defined(CONFIG_ION_ROCKCHIP) data->ion_client = rockchip_ion_client_create("rga"); @@ -2069,7 +2069,7 @@ void rga_slt(void) unsigned int *pstd; unsigned int *pnow; - data = drvdata; + data = rga_drvdata; srcW = 1280; srcH = 720; dstW = 1280; diff --git a/drivers/video/rockchip/rga/rga_mmu_info.c b/drivers/video/rockchip/rga/rga_mmu_info.c index 1380b811c2e5..9dcffa50a1e2 100644 --- a/drivers/video/rockchip/rga/rga_mmu_info.c +++ b/drivers/video/rockchip/rga/rga_mmu_info.c @@ -32,7 +32,7 @@ extern int RGA_CHECK_MODE; void rga_dma_flush_range(void *pstart, void *pend) { - dma_sync_single_for_device(drvdata->dev, virt_to_phys(pstart), pend - pstart, DMA_TO_DEVICE); + dma_sync_single_for_device(rga_drvdata->dev, virt_to_phys(pstart), pend - pstart, DMA_TO_DEVICE); } static int rga_mmu_buf_get(struct rga_mmu_buf_t *t, uint32_t size) diff --git a/drivers/video/rockchip/rga/rga_mmu_info.h b/drivers/video/rockchip/rga/rga_mmu_info.h index ff57089b955a..502f6594c29d 100644 --- a/drivers/video/rockchip/rga/rga_mmu_info.h +++ b/drivers/video/rockchip/rga/rga_mmu_info.h @@ -13,7 +13,7 @@ #define MAX(X, Y) ((X)>(Y)?(X):(Y)) #endif -extern struct rga_drvdata *drvdata; +extern struct rga_drvdata *rga_drvdata; void rga_dma_flush_range(void *pstart, void *pend); int rga_set_mmu_info(struct rga_reg *reg, struct rga_req *req); From 0960de8b28fc69bcb574c05b738079f8a2363b7b Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Fri, 25 Nov 2022 15:13:13 +0800 Subject: [PATCH 156/235] ARM: dts: rockchip: Remove dma-coherent on RK312x RGA2. Signed-off-by: Yu Qiaowei Change-Id: Ie46c49fe6d672ae1f32da300a1f072b0d478ebb0 --- arch/arm/boot/dts/rk312x.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/rk312x.dtsi b/arch/arm/boot/dts/rk312x.dtsi index 895b737b6896..899a501f3dc9 100644 --- a/arch/arm/boot/dts/rk312x.dtsi +++ b/arch/arm/boot/dts/rk312x.dtsi @@ -616,7 +616,6 @@ clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>; clock-names = "aclk_rga", "hclk_rga", "sclk_rga"; power-domains = <&power RK3128_PD_VIO>; - dma-coherent; status = "disabled"; }; From 5df41387b9efd81aed1f5d9c8d7da48c1ac1b0bd Mon Sep 17 00:00:00 2001 From: Jianwei Zheng Date: Thu, 24 Nov 2022 10:47:27 +0800 Subject: [PATCH 157/235] phy: rockchip: inno-usb2: fix phy power off causes usb controller abnormal Usb controller require the clk from phy to work normally. In the current code, if the dr_mode is set to peripheral and limit to high speed, there are two cases that usb controller will work abnormally due to phy power off. 1. The USB cable is not plug in when system start up, at this time, the otg_sm_work will call rockchip_usb2phy_power_off to suspend phy. However, if the upper layer uses configfs to operate the controller after phy power off, controller will work abnormally. 2. Plug in the usb cable and start up the system, the controller works in peripheral mode and PC recongnize it. IF we unplug the usb cable, the vbus will not detected, otg_sm_work will also call rockchip_usb2phy_power_off to suspend phy, when the upper layer use configfs to operate the controller, phy has been suspended, controller will work abnormally. To fix these cases, this patch add a new property "rockchip,dis-u2- susphy" to avoid phy power off. Signed-off-by: Jianwei Zheng Change-Id: I6c9921c8060747667d7bedb2cf76a38a896c05f5 --- .../bindings/phy/phy-rockchip-inno-usb2.yaml | 4 ++++ drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml index 731f9a1f8dbf..dc4ca36a62c2 100644 --- a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml @@ -166,6 +166,10 @@ properties: controller. It's used when the usb3 phy is disabled, and it needs to combine with the usbctrl-grf. + rockchip,dis-u2-susphy: + $ref: /schemas/types.yaml#/definitions/flag + description: when set, disable the usb2 phy enter suspend automatically. + required: - "#phy-cells" - interrupts diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 2b3dec923248..66e5e10c0321 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -243,6 +243,7 @@ struct rockchip_usb2phy_cfg { * @vbus_enabled: vbus regulator status. * @bypass_uart_en: usb bypass uart enable, passed from DT. * @host_disconnect: usb host disconnect status. + * @dis_u2_susphy: disable usb2 phy suspend. * @bvalid_irq: IRQ number assigned for vbus valid rise detection. * @ls_irq: IRQ number assigned for linestate detection. * @id_irq: IRQ number assigned for id fall or rise detection. @@ -275,6 +276,7 @@ struct rockchip_usb2phy_port { bool vbus_enabled; bool bypass_uart_en; bool host_disconnect; + bool dis_u2_susphy; int bvalid_irq; int ls_irq; int id_irq; @@ -1184,7 +1186,8 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) rport->state = OTG_STATE_B_IDLE; if (!rport->vbus_attached) { mutex_unlock(&rport->mutex); - rockchip_usb2phy_power_off(rport->phy); + if (!rport->dis_u2_susphy) + rockchip_usb2phy_power_off(rport->phy); mutex_lock(&rport->mutex); } fallthrough; @@ -1245,7 +1248,8 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) rphy->chg_state = USB_CHG_STATE_UNDEFINED; rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; mutex_unlock(&rport->mutex); - rockchip_usb2phy_power_off(rport->phy); + if (!rport->dis_u2_susphy) + rockchip_usb2phy_power_off(rport->phy); mutex_lock(&rport->mutex); } break; @@ -2054,6 +2058,8 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, of_property_read_bool(child_np, "rockchip,vbus-always-on"); rport->utmi_avalid = of_property_read_bool(child_np, "rockchip,utmi-avalid"); + rport->dis_u2_susphy = + of_property_read_bool(child_np, "rockchip,dis-u2-susphy"); /* enter lower power state when suspend */ rport->low_power_en = From 0c27529b177b57dbff94e8f313ea7194ca27eb6b Mon Sep 17 00:00:00 2001 From: Wu Liangqing Date: Sat, 19 Nov 2022 03:18:15 +0000 Subject: [PATCH 158/235] arm64: dts: rockchip: add rk3588-h0-v10.dts Change-Id: I3bd61b436eb4c6fde6069f327b6467591d2e4fc3 Signed-off-by: Wu Liangqing --- arch/arm64/boot/dts/rockchip/Makefile | 2 + .../boot/dts/rockchip/rk3588-h0-imx415.dtsi | 176 ++++ .../boot/dts/rockchip/rk3588-h0-v10-linux.dts | 16 + .../arm64/boot/dts/rockchip/rk3588-h0-v10.dts | 16 + arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi | 936 ++++++++++++++++++ 5 files changed, 1146 insertions(+) create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-h0-imx415.dtsi create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-h0-v10-linux.dts create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-h0-v10.dts create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index 6ab5692a0922..68fd62d6b572 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -133,6 +133,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb6-lp4-v10-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb7-lp4-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb7-lp4-v10-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb7-lp4-v10-rk1608-ipc-8x-linux.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-h0-v10.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-h0-v10-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nvr-demo-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nvr-demo-v10-android.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nvr-demo-v10-spi-nand.dtb diff --git a/arch/arm64/boot/dts/rockchip/rk3588-h0-imx415.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-h0-imx415.dtsi new file mode 100644 index 000000000000..f5389891113d --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-h0-imx415.dtsi @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + * + */ + +/ { + cam_ircut0: cam_ircut { + status = "okay"; + compatible = "rockchip,ircut"; + ircut-open-gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_HIGH>; + ircut-close-gpios = <&gpio4 RK_PA1 GPIO_ACTIVE_HIGH>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + }; + vcc_mipidphy0: vcc-mipidcphy0-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipidphy0_pwr>; + regulator-name = "vcc_mipidphy0"; + enable-active-high; + }; +}; + +&csi2_dphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipidphy0_in_ucam0: endpoint@1 { + reg = <1>; + remote-endpoint = <&imx415_out0>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi2_csi2_input>; + }; + }; + }; +}; + +&csi2_dphy0_hw { + status = "okay"; +}; + +&i2c3 { + status = "okay"; + + imx415: imx415@1a { + compatible = "sony,imx415"; + reg = <0x1a>; + clocks = <&cru CLK_MIPI_CAMARAOUT_M3>; + clock-names = "xvclk"; + pinctrl-names = "default"; + pinctrl-0 = <&mipim0_camera3_clk>; + power-domains = <&power RK3588_PD_VI>; + pwdn-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; + avdd-supply = <&vcc_mipidphy0>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "CMK-OT2022-PX1"; + rockchip,camera-module-lens-name = "IR0147-50IRC-8M-F20"; + lens-focus = <&cam_ircut0>; + port { + imx415_out0: endpoint { + remote-endpoint = <&mipidphy0_in_ucam0>; + data-lanes = <1 2 3 4>; + }; + }; + }; +}; + +&mipi2_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi2_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi2_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi2_in0>; + }; + }; + }; +}; + +&pinctrl { + cam { + mipidphy0_pwr: mipidphy0-pwr { + rockchip,pins = + /* camera power en */ + <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_mipi_lvds2 { + status = "okay"; + + port { + cif_mipi2_in0: endpoint { + remote-endpoint = <&mipi2_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds2_sditf { + status = "okay"; + + port { + mipi_lvds2_sditf: endpoint { + remote-endpoint = <&isp0_vir0>; + }; + }; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&rkisp0 { + status = "okay"; +}; + +&isp0_mmu { + status = "okay"; +}; + +&rkisp0_vir0 { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp0_vir0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds2_sditf>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-h0-v10-linux.dts b/arch/arm64/boot/dts/rockchip/rk3588-h0-v10-linux.dts new file mode 100644 index 000000000000..047c51448985 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-h0-v10-linux.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include "rk3588-h0.dtsi" +#include "rk3588-h0-imx415.dtsi" +#include "rk3588-linux.dtsi" + +/ { + model = "Rockchip RK3588 H0 V10 Board"; + compatible = "rockchip,rk3588-h0-v10", "rockchip,rk3588"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-h0-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-h0-v10.dts new file mode 100644 index 000000000000..8037e39cdef9 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-h0-v10.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include "rk3588-h0.dtsi" +#include "rk3588-h0-imx415.dtsi" +#include "rk3588-android.dtsi" + +/ { + model = "Rockchip RK3588 H0 V10 Board"; + compatible = "rockchip,rk3588-h0-v10", "rockchip,rk3588"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi new file mode 100644 index 000000000000..6f2b94b1b3df --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi @@ -0,0 +1,936 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + * + */ + +#include "dt-bindings/usb/pd.h" +#include "rk3588.dtsi" +#include "rk3588-evb.dtsi" +#include "rk3588-rk806-single.dtsi" + +/ { + /* If hdmirx node is disabled, delete the reserved-memory node here. */ + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* Reserve 128MB memory for hdmirx-controller@fdee0000 */ + cma { + compatible = "shared-dma-pool"; + reusable; + reg = <0x0 (256 * 0x100000) 0x0 (128 * 0x100000)>; + linux,cma-default; + }; + }; + + es8388_sound: es8388-sound { + status = "okay"; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "rockchip-es8388"; + hp-det-gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_LOW>; + io-channels = <&saradc 3>; + io-channel-names = "adc-detect"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + spk-con-gpio = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + hp-con-gpio = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,cpu = <&i2s0_8ch>; + rockchip,codec = <&es8388>; + rockchip,audio-routing = + "Headphone", "LOUT1", + "Headphone", "ROUT1", + "Speaker", "LOUT2", + "Speaker", "ROUT2", + "Headphone", "Headphone Power", + "Headphone", "Headphone Power", + "Speaker", "Speaker Power", + "Speaker", "Speaker Power", + "LINPUT1", "Main Mic", + "LINPUT2", "Main Mic", + "RINPUT1", "Headset Mic", + "RINPUT2", "Headset Mic"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + play-pause-key { + label = "playpause"; + linux,code = ; + press-threshold-microvolt = <2000>; + }; + }; + + fan: pwm-fan { + 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-sound { + compatible = "rockchip,hdmi"; + rockchip,mclk-fs = <128>; + rockchip,format = "i2s"; + rockchip,bitclock-master = <&hdmirx_ctrler>; + rockchip,frame-master = <&hdmirx_ctrler>; + rockchip,card-name = "rockchip,hdmiin"; + rockchip,cpu = <&i2s7_8ch>; + rockchip,codec = <&hdmirx_ctrler 0>; + rockchip,jack-det; + }; + + pcie20_avdd0v85: pcie20-avdd0v85 { + compatible = "regulator-fixed"; + regulator-name = "pcie20_avdd0v85"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + vin-supply = <&vdd_0v85_s0>; + }; + + pcie20_avdd1v8: pcie20-avdd1v8 { + compatible = "regulator-fixed"; + regulator-name = "pcie20_avdd1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&avcc_1v8_s0>; + }; + + pcie30_avdd0v75: pcie30-avdd0v75 { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd0v75"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + vin-supply = <&avdd_0v75_s0>; + }; + + pcie30_avdd1v8: pcie30-avdd1v8 { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&avcc_1v8_s0>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&hym8563>; + 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) + */ + post-power-on-delay-ms = <200>; + reset-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_LOW>; + }; + + rk_headset: rk-headset { + status = "disabled"; + compatible = "rockchip_headset"; + headset_gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det>; + io-channels = <&saradc 3>; + }; + + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; + + vbus5v0_typec: vbus5v0-typec { + compatible = "regulator-fixed"; + regulator-name = "vbus5v0_typec"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_usb>; + pinctrl-names = "default"; + pinctrl-0 = <&typec5v_pwren>; + }; + + vcc3v3_lcd_n: vcc3v3-lcd0-n { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_lcd0_n"; + regulator-boot-on; + enable-active-high; + gpio = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc_1v8_s0>; + }; + + vcc3v3_pcie30: vcc3v3-pcie30 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pcie30"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>; + startup-delay-us = <5000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_host: vcc5v0-host { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_usb>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + }; + + vcc_mipicsi0: vcc-mipicsi0-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipicsi0_pwr>; + regulator-name = "vcc_mipicsi0"; + enable-active-high; + }; + + vcc_mipicsi1: vcc-mipicsi1-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio1 RK_PD3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipicsi1_pwr>; + regulator-name = "vcc_mipicsi1"; + enable-active-high; + }; + + vcc_mipidcphy0: vcc-mipidcphy0-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio2 RK_PC4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipidcphy0_pwr>; + regulator-name = "vcc_mipidcphy0"; + enable-active-high; + }; + + vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&sd_s0_pwr>; + regulator-name = "vcc_3v3_sd_s0"; + enable-active-high; + }; + + wireless_bluetooth: wireless-bluetooth { + compatible = "bluetooth-platdata"; + clocks = <&hym8563>; + clock-names = "ext_clock"; + uart_rts_gpios = <&gpio4 RK_PC4 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart9m0_rtsn>, <&bt_reset_gpio>, <&bt_wake_gpio>, <&bt_irq_gpio>; + pinctrl-1 = <&uart9_gpios>; + BT,reset_gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; + BT,wake_gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + BT,wake_host_irq = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + wireless_wlan: wireless-wlan { + compatible = "wlan-platdata"; + wifi_chip_type = "ap6398s"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_host_wake_irq>; + WIFI,host_wake_irq = <&gpio0 RK_PB2 GPIO_ACTIVE_HIGH>; + WIFI,poweren_gpio = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + +&backlight { + pwms = <&pwm1 0 25000 0>; + status = "okay"; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy1_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&dp0 { + status = "okay"; +}; +&dp0_in_vp2 { + status = "okay"; +}; + +&dp0_sound{ + status = "okay"; +}; +&dp1 { + pinctrl-names = "default"; + pinctrl-0 = <&dp1m0_pins>; + status = "okay"; +}; + +&dp1_in_vp2 { + status = "okay"; +}; + +/* + * mipi_dcphy0 needs to be enabled + * when dsi0 is enabled + */ +&dsi0 { + status = "okay"; +}; + +&dsi0_in_vp2 { + status = "disabled"; +}; + +&dsi0_in_vp3 { + status = "okay"; +}; + +&dsi0_panel { + power-supply = <&vcc3v3_lcd_n>; + reset-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_rst_gpio>; +}; + +/* + * mipi_dcphy1 needs to be enabled + * when dsi1 is enabled + */ +&dsi1 { + status = "disabled"; +}; + +&dsi1_in_vp2 { + status = "disabled"; +}; + +&dsi1_in_vp3 { + status = "disabled"; +}; + +&dsi1_panel { + power-supply = <&vcc3v3_lcd_n>; + + /* + * because in hardware, the two screens share the reset pin, + * so reset-gpios need only in dsi1 enable and dsi0 disabled + * case. + */ + + //reset-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_LOW>; + //pinctrl-names = "default"; + //pinctrl-0 = <&lcd_rst_gpio>; +}; + +&gmac1 { + /* Use rgmii-rxid mode to disable rx delay inside Soc */ + phy-mode = "rgmii-rxid"; + clock_in_out = "output"; + + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + + pinctrl-names = "default"; + pinctrl-0 = <&gmac1_miim + &gmac1_tx_bus2 + &gmac1_rx_bus2 + &gmac1_rgmii_clk + &gmac1_rgmii_bus>; + + tx_delay = <0x43>; + /* rx_delay = <0x3f>; */ + + phy-handle = <&rgmii_phy>; + status = "okay"; +}; + +&hdmi0 { + enable-gpios = <&gpio4 RK_PB1 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&hdmi0_in_vp0 { + status = "okay"; +}; + +&hdmi0_sound { + status = "okay"; +}; + +&hdmi1 { + enable-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&hdmi1_in_vp1 { + status = "okay"; +}; + +&hdmi1_sound { + status = "okay"; +}; + +/* Should work with at least 128MB cma reserved above. */ +&hdmirx_ctrler { + status = "okay"; + + #sound-dai-cells = <1>; + /* Effective level used to trigger HPD: 0-low, 1-high */ + hpd-trigger-level = <1>; + hdmirx-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&hdmim1_rx &hdmirx_det>; +}; + +&hdptxphy_hdmi0 { + status = "okay"; +}; + +&hdptxphy_hdmi1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + + vdd_cpu_big0_s0: vdd_cpu_big0_mem_s0: rk8602@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_cpu_big0_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: vdd_cpu_big1_mem_s0: rk8603@43 { + compatible = "rockchip,rk8603"; + reg = <0x43>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_cpu_big1_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1m2_xfer>; + + vdd_npu_s0: vdd_npu_mem_s0: rk8602@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_npu_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c4 { + status = "okay"; + pinctrl-0 = <&i2c4m1_xfer>; + + ls_stk3332: light@47 { + compatible = "ls_stk3332"; + status = "disabled"; + reg = <0x47>; + type = ; + irq_enable = <0>; + als_threshold_high = <100>; + als_threshold_low = <10>; + als_ctrl_gain = <2>; /* 0:x1 1:x4 2:x16 3:x64 */ + poll_delay_ms = <100>; + }; + + ps_stk3332: proximity@47 { + compatible = "ps_stk3332"; + status = "disabled"; + reg = <0x47>; + type = ; + //pinctrl-names = "default"; + //pinctrl-0 = <&gpio3_c6>; + //irq-gpio = <&gpio3 RK_PC6 IRQ_TYPE_LEVEL_LOW>; + //irq_enable = <1>; + ps_threshold_high = <0x200>; + ps_threshold_low = <0x100>; + ps_ctrl_gain = <3>; /* 0:x1 1:x2 2:x5 3:x8 */ + ps_led_current = <4>; /* 0:3.125mA 1:6.25mA 2:12.5mA 3:25mA 4:50mA 5:100mA*/ + poll_delay_ms = <100>; + }; + + mpu6500_acc: mpu_acc@68 { + compatible = "mpu6500_acc"; + reg = <0x68>; + irq-gpio = <&gpio4 RK_PC2 IRQ_TYPE_EDGE_RISING>; + irq_enable = <0>; + poll_delay_ms = <30>; + type = ; + layout = <5>; + }; + + mpu6500_gyro: mpu_gyro@68 { + compatible = "mpu6500_gyro"; + reg = <0x68>; + poll_delay_ms = <30>; + type = ; + layout = <5>; + }; +}; + +&i2c5 { + status = "okay"; + gt1x: gt1x@14 { + compatible = "goodix,gt1x"; + reg = <0x14>; + pinctrl-names = "default"; + pinctrl-0 = <&touch_gpio>; + goodix,rst-gpio = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; + goodix,irq-gpio = <&gpio3 RK_PC0 IRQ_TYPE_LEVEL_LOW>; + power-supply = <&vcc3v3_lcd_n>; + }; +}; + +&i2c6 { + status = "okay"; + + usbc0: fusb302@22 { + compatible = "fcs,fusb302"; + reg = <0x22>; + interrupt-parent = <&gpio3>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&usbc0_int>; + vbus-supply = <&vbus5v0_typec>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_role_sw: endpoint@0 { + remote-endpoint = <&dwc3_0_role_switch>; + }; + }; + }; + + usb_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + data-role = "dual"; + power-role = "dual"; + try-power-role = "sink"; + op-sink-microwatt = <1000000>; + sink-pdos = + ; + source-pdos = + ; + + altmodes { + #address-cells = <1>; + #size-cells = <0>; + + altmode@0 { + reg = <0>; + svid = <0xff01>; + vdo = <0xffffffff>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_orien_sw: endpoint { + remote-endpoint = <&usbdp_phy0_orientation_switch>; + }; + }; + + port@1 { + reg = <1>; + dp_altmode_mux: endpoint { + remote-endpoint = <&usbdp_phy0_dp_altmode_mux>; + }; + }; + }; + }; + }; + + hym8563: hym8563@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "hym8563"; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + interrupt-parent = <&gpio0>; + interrupts = ; + wakeup-source; + }; +}; + +&i2c7 { + status = "okay"; + es8388: es8388@11 { + status = "okay"; + #sound-dai-cells = <0>; + compatible = "everest,es8388", "everest,es8323"; + reg = <0x11>; + clocks = <&cru I2S0_8CH_MCLKOUT>; + clock-names = "mclk"; + assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; + assigned-clock-rates = <12288000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_mclk>; + }; +}; + +&i2s5_8ch { + status = "okay"; +}; + +&i2s6_8ch { + status = "okay"; +}; + +&i2s7_8ch { + status = "okay"; +}; + +&mdio1 { + rgmii_phy: phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x1>; + }; +}; + +&mipi_dcphy0 { + status = "okay"; +}; + +&mipi_dcphy1 { + status = "disabled"; +}; + +&pcie2x1l0 { + reset-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&pcie30phy { + rockchip,pcie30-phymode = ; + status = "okay"; +}; + +&pcie3x4 { + reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie30>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie20x1_0_clkreqn_m1>; + supports-clkreq; + status = "okay"; +}; + +&pinctrl { + cam { + mipicsi0_pwr: mipicsi0-pwr { + rockchip,pins = + /* camera power en */ + <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + mipicsi1_pwr: mipicsi1-pwr { + rockchip,pins = + /* camera power en */ + <1 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + mipidcphy0_pwr: mipidcphy0-pwr { + rockchip,pins = + /* camera power en */ + <2 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + + hdmi { + hdmirx_det: hdmirx-det { + rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + headphone { + hp_det: hp-det { + rockchip,pins = <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + lcd { + lcd_rst_gpio: lcd-rst-gpio { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sdmmc { + sd_s0_pwr: sd-s0-pwr { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + touch { + touch_gpio: touch-gpio { + rockchip,pins = + <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>, + <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins = <3 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + typec5v_pwren: typec5v-pwren { + rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-bluetooth { + uart9_gpios: uart9-gpios { + rockchip,pins = <4 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_reset_gpio: bt-reset-gpio { + rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_wake_gpio: bt-wake-gpio { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + bt_irq_gpio: bt-irq-gpio { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-wlan { + wifi_host_wake_irq: wifi-host-wake-irq { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + pcie { + pcie20x1_0_clkreqn_m1: pcie20x1-0-clkreqn-m1 { + rockchip,pins = <4 RK_PB4 4 &pcfg_pull_up>; + }; + }; +}; + +&pwm1 { + status = "okay"; +}; + +&pwm3 { + pinctrl-0 = <&pwm3m1_pins>; + status = "okay"; +}; + +&route_dsi0 { + status = "okay"; + connect = <&vp3_out_dsi0>; +}; + +&route_dsi1 { + status = "disabled"; + connect = <&vp3_out_dsi1>; +}; + +&route_hdmi0 { + status = "okay"; +}; + +&route_hdmi1 { + status = "okay"; +}; + +&sata0 { + status = "okay"; +}; + +&sdio { + max-frequency = <150000000>; + no-sd; + no-mmc; + bus-width = <4>; + disable-wp; + cap-sd-highspeed; + cap-sdio-irq; + keep-power-in-suspend; + mmc-pwrseq = <&sdio_pwrseq>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&sdiom0_pins>; + sd-uhs-sdr104; + status = "okay"; +}; + +&sdmmc { + status = "okay"; + vmmc-supply = <&vcc_3v3_sd_s0>; +}; + +&uart9 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart9m0_xfer &uart9m0_ctsn>; +}; + +&u2phy0_otg { + rockchip,typec-vbus-det; +}; + +&u2phy1_otg { + phy-supply = <&vcc5v0_host>; +}; + +&u2phy2_host { + phy-supply = <&vcc5v0_host>; +}; + +&u2phy3_host { + phy-supply = <&vcc5v0_host>; +}; + +&usbdp_phy0 { + orientation-switch; + svid = <0xff01>; + sbu1-dc-gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_HIGH>; + sbu2-dc-gpios = <&gpio4 RK_PA1 GPIO_ACTIVE_HIGH>; + + port { + #address-cells = <1>; + #size-cells = <0>; + usbdp_phy0_orientation_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_orien_sw>; + }; + + usbdp_phy0_dp_altmode_mux: endpoint@1 { + reg = <1>; + remote-endpoint = <&dp_altmode_mux>; + }; + }; +}; + +&usbdp_phy1 { + rockchip,dp-lane-mux = <2 3>; +}; + +&usbdrd_dwc3_0 { + dr_mode = "otg"; + usb-role-switch; + port { + #address-cells = <1>; + #size-cells = <0>; + dwc3_0_role_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_role_sw>; + }; + }; +}; + +&usbhost3_0 { + status = "disabled"; +}; + +&usbhost_dwc3_0 { + status = "disabled"; +}; From c2297457393d8311694dfc27a4764b46ee11153d Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Tue, 2 Aug 2022 17:39:05 +0800 Subject: [PATCH 159/235] soc: rockchip: Adds CPU_RK3528 config Signed-off-by: Sandy Huang Change-Id: I13cdad34e43b9e75944a267d4c6c83c1a55eacdc --- drivers/soc/rockchip/Kconfig.cpu | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/soc/rockchip/Kconfig.cpu b/drivers/soc/rockchip/Kconfig.cpu index 3775e73e32cb..368fa6f9ad44 100644 --- a/drivers/soc/rockchip/Kconfig.cpu +++ b/drivers/soc/rockchip/Kconfig.cpu @@ -57,6 +57,9 @@ config CPU_RK3368 config CPU_RK3399 bool "RK3399" +config CPU_RK3528 + bool "RK3528" + config CPU_RK3568 bool "RK3566/8" From e8af16cf5a7ca21ecfbfbf85efd7b567d49b0cbf Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Tue, 2 Aug 2022 17:40:10 +0800 Subject: [PATCH 160/235] arm64: configs: rockchip_defconfig: enable CPU_RK3528 Signed-off-by: Sandy Huang Change-Id: I9b03f85c9637e5377608dd02ed4e5244e6f33071 --- 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 706982fe9739..ec9746b89c46 100644 --- a/arch/arm64/configs/rockchip_defconfig +++ b/arch/arm64/configs/rockchip_defconfig @@ -878,6 +878,7 @@ CONFIG_CPU_PX30=y CONFIG_CPU_RK3328=y CONFIG_CPU_RK3368=y CONFIG_CPU_RK3399=y +CONFIG_CPU_RK3528=y CONFIG_CPU_RK3568=y CONFIG_CPU_RK3588=y CONFIG_ROCKCHIP_CPUINFO=y From eabcc7ba3691a49c2f250fbd1a53fc587726e2a0 Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Mon, 28 Nov 2022 14:10:04 +0800 Subject: [PATCH 161/235] ARM: dts: rockchip: add rv1106g-evb2-v11-emmc.dts Signed-off-by: Weiwen Chen Change-Id: I113a63a7be946c40a314269eda36f3f36b652a39 --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/rv1106g-evb2-v11-emmc.dts | 283 ++++++++++++++++++++ 2 files changed, 284 insertions(+) create mode 100644 arch/arm/boot/dts/rv1106g-evb2-v11-emmc.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index c4e531c1b0f6..dbad1bc4facd 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -993,6 +993,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rv1106g-evb1-v10-spi-nand.dtb \ rv1106g-evb1-v10-spi-nor.dtb \ rv1106g-evb2-v10.dtb \ + rv1106g-evb2-v11-emmc.dtb \ rv1106g-smart-door-lock-rmsl-v10.dtb \ rv1106g-uvc-demo-v10.dtb \ rv1106g-uvc-demo-v10-spi-nor.dtb \ diff --git a/arch/arm/boot/dts/rv1106g-evb2-v11-emmc.dts b/arch/arm/boot/dts/rv1106g-evb2-v11-emmc.dts new file mode 100644 index 000000000000..50b7378a7b72 --- /dev/null +++ b/arch/arm/boot/dts/rv1106g-evb2-v11-emmc.dts @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; + +#include "rv1106.dtsi" +#include "rv1106-evb-v10.dtsi" +#include "rv1106-thunder-boot-emmc.dtsi" + +/ { + model = "Rockchip RV1106G EVB2 V11 EMMC Board"; + compatible = "rockchip,rv1106g-evb2-v11-emmc", "rockchip,rv1106"; + + chosen { + bootargs = "loglevel=0 rootfstype=erofs rootflags=dax console=ttyFIQ0 root=/dev/rd0 snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0 driver_async_probe=dwmmc_rockchip"; + }; + + vcc_1v8: vcc-1v8 { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vcc_3v3: vcc-3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vcc3v3_sd: vcc3v3-sd { + compatible = "regulator-fixed"; + gpio = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>; + regulator-name = "vcc3v3_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_pwren>; + }; + +}; + +&csi2_dphy_hw { + status = "okay"; +}; + +&csi2_dphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + csi_dphy_input0: endpoint@0 { + reg = <0>; + remote-endpoint = <&sc3338_out>; + data-lanes = <1 2>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csi_dphy_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_csi2_input>; + }; + }; + }; +}; + +&emmc { + status = "okay"; +}; + +&fiq_debugger { + rockchip,baudrate = <1500000>; + pinctrl-names = "default"; + pinctrl-0 = <&uart2m1_xfer>; +}; + +&i2c4 { + rockchip,amp-shared; + + sc3338: sc3338@30 { + compatible = "smartsens,sc3338"; + status = "okay"; + reg = <0x30>; + clocks = <&cru MCLK_REF_MIPI0>; + clock-names = "xvclk"; + pwdn-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipi_refclk_out0>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "FKO1"; + rockchip,camera-module-lens-name = "30IRC-F16"; + port { + sc3338_out: endpoint { + remote-endpoint = <&csi_dphy_input0>; + data-lanes = <1 2>; + }; + }; + }; +}; + +&mipi0_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csi_dphy_output>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in>; + }; + }; + }; +}; + +&mailbox { + status = "okay"; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_mipi_lvds { + status = "okay"; + memory-region-thunderboot = <&rkisp_thunderboot>; + + pinctrl-names = "default"; + pinctrl-0 = <&mipi_pins>; + port { + /* MIPI CSI-2 endpoint */ + cif_mipi_in: endpoint { + remote-endpoint = <&mipi_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds_sditf { + status = "okay"; + + port { + /* MIPI CSI-2 endpoint */ + mipi_lvds_sditf: endpoint { + remote-endpoint = <&isp_in>; + }; + }; +}; + +&rkisp { + status = "okay"; +}; + +&rkisp_vir0 { + status = "okay"; + + port@0 { + isp_in: endpoint { + remote-endpoint = <&mipi_lvds_sditf>; + }; + }; +}; + +&thunder_boot_service { + status = "okay"; +}; + +&rkisp_thunderboot { + /* reg's offset MUST match with RTOS */ + /* + * vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num) + * e.g. 2304x1296: 0xf30000 + */ + reg = <0x00860000 0xf30000>; +}; + +&ramdisk_r { + reg = <0x1790000 (20 * 0x00100000)>; +}; + +&ramdisk_c { + reg = <0x2b90000 (10 * 0x00100000)>; +}; + +&pinctrl { + sdmmc { + /omit-if-no-ref/ + sdmmc_pwren: sdmmc-pwren { + rockchip,pins = <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm10 { + status = "okay"; +}; + +&pwm11 { + status = "okay"; +}; + +&sdio { + max-frequency = <50000000>; + bus-width = <1>; + cap-sd-highspeed; + cap-sdio-irq; + keep-power-in-suspend; + non-removable; + rockchip,default-sample-phase = <90>; + no-sd; + no-mmc; + supports-sdio; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1m0_cmd &sdmmc1m0_clk &sdmmc1m0_bus4>; + status = "okay"; +}; + +&sdmmc { + max-frequency = <200000000>; + no-sdio; + no-mmc; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>; + vmmc-supply = <&vcc3v3_sd>; + status = "okay"; +}; + +&sfc { + assigned-clocks = <&cru SCLK_SFC>; + assigned-clock-rates = <125000000>; + status = "disabled"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <125000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&usbdrd_dwc3 { + dr_mode = "peripheral"; +}; From aaf9337e4616d15ace2983c07699f46a3f0d9865 Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Mon, 28 Nov 2022 14:12:03 +0800 Subject: [PATCH 162/235] ARM: configs: rockchip: rv1106-battery-ipc.config support ext4 insmod ext4 filesystem support: insmod jbd2.ko insmod crc16.ko insmod mbcache.ko insmod ext4.ko Updated by: make ARCH=arm rv1106_defconfig rv1106-tb.config cp .config rv1106.config make ARCH=arm rv1106_defconfig rv1106-tb.config rv1106-battery-ipc.config make ARCH=arm menuconfig ./scripts/diffconfig -m rv1106.config .config > arch/arm/configs/rv1106-battery-ipc.config Signed-off-by: Weiwen Chen Change-Id: Ibc2295e5376949c8e65863b594cce8d0cb848167 --- arch/arm/configs/rv1106-battery-ipc.config | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/configs/rv1106-battery-ipc.config b/arch/arm/configs/rv1106-battery-ipc.config index 73a839747d62..da7cc623d559 100644 --- a/arch/arm/configs/rv1106-battery-ipc.config +++ b/arch/arm/configs/rv1106-battery-ipc.config @@ -1,3 +1,5 @@ +CONFIG_CRC16=m +CONFIG_EXT4_FS=m CONFIG_FILE_LOCKING=y CONFIG_JFFS2_FS=y CONFIG_MAILBOX=y @@ -87,11 +89,16 @@ CONFIG_VIDEO_SC3338=y # CONFIG_BSD_DISKLABEL is not set # CONFIG_EEPROM_93XX46 is not set # CONFIG_EEPROM_AT25 is not set +# CONFIG_EXT4_DEBUG is not set +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +CONFIG_EXT4_USE_FOR_EXT2=y # CONFIG_EZX_PCAP is not set CONFIG_FAT_DEFAULT_CODEPAGE=936 CONFIG_FAT_DEFAULT_IOCHARSET="cp936" CONFIG_FAT_DEFAULT_UTF8=y CONFIG_FAT_FS=m +CONFIG_FS_MBCACHE=m # CONFIG_FXOS8700_SPI is not set # CONFIG_GPIO_74X164 is not set # CONFIG_GPIO_MAX3191X is not set @@ -103,6 +110,8 @@ CONFIG_FAT_FS=m # CONFIG_IIO_SSP_SENSORHUB is not set # CONFIG_INV_ICM42600_SPI is not set # CONFIG_INV_MPU6050_SPI is not set +CONFIG_JBD2=m +# CONFIG_JBD2_DEBUG is not set # CONFIG_JFFS2_CMODE_FAVOURLZO is not set # CONFIG_JFFS2_CMODE_NONE is not set CONFIG_JFFS2_CMODE_PRIORITY=y @@ -156,6 +165,7 @@ CONFIG_MANDATORY_FILE_LOCKING=y # CONFIG_MTD_MCHP23K256 is not set # CONFIG_MTD_SPI_NAND is not set CONFIG_MTD_SPI_NOR=m +# CONFIG_MTD_SPI_NOR_MISC is not set # CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set # CONFIG_MTD_SST25L is not set # CONFIG_PI433 is not set From 4ebfe9018ee7edfaf3d6d53bca9fdd6ad3997d7a Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Sat, 26 Nov 2022 03:30:06 +0000 Subject: [PATCH 163/235] media: i2c: lt6911uxe: fix source change event report Change-Id: I311f5f9fc8398e3db4fb43ee19de071fe6ddd0ca Signed-off-by: Jianwei Fan --- drivers/media/i2c/lt6911uxe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/lt6911uxe.c b/drivers/media/i2c/lt6911uxe.c index 786d794c7a81..1ec879b3d92b 100644 --- a/drivers/media/i2c/lt6911uxe.c +++ b/drivers/media/i2c/lt6911uxe.c @@ -622,9 +622,9 @@ static void lt6911uxe_format_change(struct v4l2_subdev *sd) v4l2_print_dv_timings(sd->name, "Format_change: New format: ", &timings, false); - if (sd->devnode) - v4l2_subdev_notify_event(sd, <6911uxe_ev_fmt); } + if (sd->devnode) + v4l2_subdev_notify_event(sd, <6911uxe_ev_fmt); } static int lt6911uxe_isr(struct v4l2_subdev *sd, u32 status, bool *handled) From d7fe3090a1e37d5b5c1a1ae3dc7a4ea1c812dce4 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Sat, 26 Nov 2022 03:31:38 +0000 Subject: [PATCH 164/235] media: i2c: lt7911uxc: fix source change event report Change-Id: Ib90bf34ed75270c9de71973bcb2315cd7ae11c5b Signed-off-by: Jianwei Fan --- drivers/media/i2c/lt7911uxc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/lt7911uxc.c b/drivers/media/i2c/lt7911uxc.c index f89aa0f272e3..df91719199eb 100644 --- a/drivers/media/i2c/lt7911uxc.c +++ b/drivers/media/i2c/lt7911uxc.c @@ -712,9 +712,9 @@ static void lt7911uxc_format_change(struct v4l2_subdev *sd) v4l2_print_dv_timings(sd->name, "Format_change: New format: ", &timings, false); - if (sd->devnode) - v4l2_subdev_notify_event(sd, <7911uxc_ev_fmt); } + if (sd->devnode) + v4l2_subdev_notify_event(sd, <7911uxc_ev_fmt); } static int lt7911uxc_isr(struct v4l2_subdev *sd, u32 status, bool *handled) From 5e2e107ee608ba0b8e27da1af28597da5e0ee2eb Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Fri, 8 Nov 2019 20:14:48 +0800 Subject: [PATCH 165/235] arm64: dts: rockchip: px30: add SFC node Change-Id: Ia7ef02ee734f148deb2b626526c3cb615e9daaf2 Signed-off-by: Jon Lin --- arch/arm64/boot/dts/rockchip/px30.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index b958c5d08728..5a43a617a30f 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -41,6 +41,7 @@ serial5 = &uart5; spi0 = &spi0; spi1 = &spi1; + spi2 = &sfc; }; cpus { @@ -1422,6 +1423,17 @@ status = "disabled"; }; + sfc: spi@ff3a0000 { + compatible = "rockchip,sfc"; + reg = <0x0 0xff3a0000 0x0 0x4000>; + interrupts = ; + clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>; + clock-names = "clk_sfc", "hclk_sfc"; + assigned-clocks = <&cru SCLK_SFC>; + assigned-clock-rates = <100000000>; + status = "disabled"; + }; + nandc0: nandc@ff3b0000 { compatible = "rockchip,rk-nandc"; reg = <0x0 0xff3b0000 0x0 0x4000>; From 2645ecd2d718edc98d49c72ad6afe92b24259640 Mon Sep 17 00:00:00 2001 From: ZiHan Huang Date: Tue, 29 Nov 2022 10:05:42 +0800 Subject: [PATCH 166/235] ARM: dts: rockchip: rk3036-echo/kylin delete old vpu node 5.10 kernel use vdec node Change-Id: I0dd1ac897a82e84e1770287bb2edd2a1efb30b87 Signed-off-by: ZiHan Huang --- arch/arm/boot/dts/rk3036-echo.dts | 8 -------- arch/arm/boot/dts/rk3036-kylin.dts | 8 -------- 2 files changed, 16 deletions(-) diff --git a/arch/arm/boot/dts/rk3036-echo.dts b/arch/arm/boot/dts/rk3036-echo.dts index 0d0b43829162..14bcae229e55 100644 --- a/arch/arm/boot/dts/rk3036-echo.dts +++ b/arch/arm/boot/dts/rk3036-echo.dts @@ -701,14 +701,6 @@ status = "okay"; }; -&vpu_combo { - status = "okay"; -}; - -&vpu_mmu { - status = "okay"; -}; - &wdt { status = "okay"; }; diff --git a/arch/arm/boot/dts/rk3036-kylin.dts b/arch/arm/boot/dts/rk3036-kylin.dts index 0b11411ea75c..56676267b43d 100644 --- a/arch/arm/boot/dts/rk3036-kylin.dts +++ b/arch/arm/boot/dts/rk3036-kylin.dts @@ -429,14 +429,6 @@ status = "okay"; }; -&vpu_combo { - status = "okay"; -}; - -&vpu_mmu { - status = "okay"; -}; - &wdt { status = "okay"; }; From d48e1e297a8119963c84d5618690458a88534942 Mon Sep 17 00:00:00 2001 From: ZiHan Huang Date: Mon, 28 Nov 2022 17:54:41 +0800 Subject: [PATCH 167/235] ARM: dts: rockchip: rk3036.dtsi vdec adapts to the 5.10 kernel Change-Id: I1a10dfd9af01d83bb78cf889ffc1cd27e7d0dda5 Signed-off-by: ZiHan Huang --- arch/arm/boot/dts/rk3036.dtsi | 81 ++++++++++++++++------------------- 1 file changed, 36 insertions(+), 45 deletions(-) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 471270a09fef..72dbfabd388f 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -188,34 +188,32 @@ }; }; - vpu: video-codec@10108000 { - compatible = "rockchip,rk3036-vpu", "rockchip,rk3288-vpu"; - reg = <0x10108000 0x800>; - interrupts = , - ; - interrupt-names = "vepu", "vdpu"; - clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; - clock-names = "aclk", "hclk"; - iommus = <&vpu_mmu>; - /* - * 3036's vpu could not run higher than 300M - */ - assigned-clocks = <&cru ACLK_VCODEC>; - assigned-clock-rates = <297000000>; - assigned-clock-parents = <&cru PLL_GPLL>; - power-domains = <&power RK3036_PD_VPU>; + mpp_srv: mpp-srv { + compatible = "rockchip,mpp-service"; + rockchip,taskqueue-count = <1>; + rockchip,resetgroup-count = <1>; status = "disabled"; }; - vpu_service: vpu-service@10108400 { - compatible = "rockchip,sub"; + vdpu: vdpu@10108400 { + compatible = "rockchip,vpu-decoder-v1"; reg = <0x10108400 0x400>; - dev_mode = <0>; interrupts = ; interrupt-names = "irq_dec"; + clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; + clock-names = "aclk_vcodec", "hclk_vcodec"; + rockchip,normal-rates = <297000000>, <0>; + assigned-clocks = <&cru ACLK_VCODEC>; + assigned-clock-rates = <297000000>; + assigned-clock-parents = <&cru PLL_GPLL>; + resets = <&cru SRST_VCODEC_A>, <&cru SRST_VCODEC_H>; + reset-names = "shared_video_a", "shared_video_h"; iommus = <&vpu_mmu>; - allocator = <1>; power-domains = <&power RK3036_PD_VPU>; + rockchip,srv = <&mpp_srv>; + rockchip,taskqueue-node = <0>; + rockchip,resetgroup-node = <0>; + status = "disabled"; }; vpu_mmu: iommu@10108800 { @@ -223,20 +221,32 @@ reg = <0x10108800 0x100>; interrupts = ; interrupt-names = "vpu_mmu"; + clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; + clock-names = "aclk", "iface"; #iommu-cells = <0>; power-domains = <&power RK3036_PD_VPU>; status = "disabled"; }; - hevc_service: hevc-service@1010c000 { - compatible = "rockchip,sub"; + hevc: hevc_service@1010c000 { + compatible = "rockchip,hevc-decoder"; reg = <0x1010c000 0x400>; - dev_mode = <1>; interrupts = ; interrupt-names = "irq_dec"; - allocator = <1>; + clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>, <&cru ACLK_HEVC>; + clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core"; + rockchip,normal-rates = <297000000>, <0>, <200000000>; + assigned-clocks = <&cru ACLK_VCODEC>; + assigned-clock-rates = <297000000>; + assigned-clock-parents = <&cru PLL_GPLL>; + resets = <&cru SRST_VCODEC_A>, <&cru SRST_VCODEC_H>, <&cru SRST_HEVC>; + reset-names = "shared_video_a", "shared_video_h", "video_core"; iommus = <&hevc_mmu>; + rockchip,srv = <&mpp_srv>; + rockchip,taskqueue-node = <0>; + rockchip,resetgroup-node = <0>; power-domains = <&power RK3036_PD_VPU>; + status = "disabled"; }; hevc_mmu: iommu@1010c440 { @@ -244,32 +254,13 @@ reg = <0x1010c440 0x40>, <0x1010c480 0x40>; interrupts = ; interrupt-names = "hevc_mmu"; + clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; + clock-names = "aclk", "iface"; #iommu-cells = <0>; power-domains = <&power RK3036_PD_VPU>; status = "disabled"; }; - vpu_combo: vpu-combo { - compatible = "rockchip,vpu_combo"; - rockchip,grf = <&grf>; - subcnt = <2>; - rockchip,sub = <&hevc_service>, <&vpu_service>; - mode_bit = <3>; - mode_ctrl = <0x144>; - clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>, - <&cru ACLK_HEVC>; - clock-names = "aclk_vcodec", "hclk_vcodec", "clk_core"; - /* RK3036's vpu could not run higher than 300M */ - assigned-clocks = <&cru ACLK_VCODEC>; - assigned-clock-rates = <297000000>; - assigned-clock-parents = <&cru PLL_GPLL>; - resets = <&cru SRST_VCODEC_A>, <&cru SRST_VCODEC_H>, - <&cru SRST_HEVC>; - reset-names = "video_a", "video_h", "video"; - power-domains = <&power RK3036_PD_VPU>; - status = "disabled"; - }; - vop: vop@10118000 { compatible = "rockchip,rk3036-vop"; reg = <0x10118000 0x19c>; From e8870aba924ea2725a39623f036dd2ce169f4ece Mon Sep 17 00:00:00 2001 From: ZiHan Huang Date: Tue, 29 Nov 2022 10:09:09 +0800 Subject: [PATCH 168/235] ARM: dts: rockchip: rk3036-echo/kylin use new mpp_srv node Change-Id: I4328f42bda41ff34dda1fef4bc205cc1be0d4b14 Signed-off-by: ZiHan Huang --- arch/arm/boot/dts/rk3036-echo.dts | 16 ++++++++++++++++ arch/arm/boot/dts/rk3036-kylin.dts | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/arch/arm/boot/dts/rk3036-echo.dts b/arch/arm/boot/dts/rk3036-echo.dts index 14bcae229e55..140c93c6c444 100644 --- a/arch/arm/boot/dts/rk3036-echo.dts +++ b/arch/arm/boot/dts/rk3036-echo.dts @@ -167,6 +167,10 @@ status = "okay"; }; +&hevc { + status = "okay"; +}; + &hevc_mmu { status = "okay"; }; @@ -644,6 +648,10 @@ status = "okay"; }; +&mpp_srv { + status = "okay"; +}; + &sdio { status = "okay"; @@ -693,6 +701,14 @@ status = "okay"; }; +&vdpu { + status = "okay"; +}; + +&vpu_mmu { + status = "okay"; +}; + &vop { status = "okay"; }; diff --git a/arch/arm/boot/dts/rk3036-kylin.dts b/arch/arm/boot/dts/rk3036-kylin.dts index 56676267b43d..41480890bb6a 100644 --- a/arch/arm/boot/dts/rk3036-kylin.dts +++ b/arch/arm/boot/dts/rk3036-kylin.dts @@ -175,6 +175,10 @@ status = "okay"; }; +&hevc { + status = "okay"; +}; + &hevc_mmu { status = "okay"; }; @@ -372,6 +376,10 @@ status = "okay"; }; +&mpp_srv { + status = "okay"; +}; + &sdio { status = "okay"; @@ -421,6 +429,14 @@ status = "okay"; }; +&vdpu { + status = "okay"; +}; + +&vpu_mmu { + status = "okay"; +}; + &vop { status = "okay"; }; From e1b13f917c7d315623b275fa38c29d48e2f52234 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Tue, 17 Aug 2021 20:38:51 +0800 Subject: [PATCH 169/235] cpufreq: rockchip: do not select CONFIG_CPUFREQ_DT_PLATDEV for cpufreq-dt cpufreq-dt-platdev.c is useless on rockchip platform, remove it and save memory. $ ./scripts/bloat-o-meter vmlinux_before vmlinux add/remove: 0/4 grow/shrink: 0/0 up/down: 0/-18284 (-18284) Function old new delta __initcall_cpufreq_dt_platdev_init6 4 - -4 cpufreq_dt_platdev_init 248 - -248 blacklist 8232 - -8232 whitelist 9800 - -9800 Total: Before=10211366, After=10193082, chg -0.18% Change-Id: Ibcc15aa3a8b13afa208c77979b75c617aeaef5fb Signed-off-by: Liang Chen --- drivers/cpufreq/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 434e3d0371ea..6f2b6c17c948 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -247,7 +247,7 @@ comment "CPU frequency scaling drivers" config CPUFREQ_DT tristate "Generic DT based cpufreq driver" depends on HAVE_CLK && OF - select CPUFREQ_DT_PLATDEV + select CPUFREQ_DT_PLATDEV if !ARM_ROCKCHIP_CPUFREQ select PM_OPP help This adds a generic DT based cpufreq driver for frequency management. From 6452e5b5145bab0d4da8f5394678d7dc6268c3aa Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Mon, 28 Nov 2022 08:18:48 +0000 Subject: [PATCH 170/235] arm64: dts: rockchip: px30-mini-evb-ddr3-v11-avb: Add a delay after exiting panel sleep mode Signed-off-by: Wyon Bi Change-Id: Id1d092635b6fe08f547784caa3b570f622bb9d6b --- arch/arm64/boot/dts/rockchip/px30-mini-evb-ddr3-v11-avb.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/px30-mini-evb-ddr3-v11-avb.dts b/arch/arm64/boot/dts/rockchip/px30-mini-evb-ddr3-v11-avb.dts index c47101d4e7f9..bcaea43fdc18 100644 --- a/arch/arm64/boot/dts/rockchip/px30-mini-evb-ddr3-v11-avb.dts +++ b/arch/arm64/boot/dts/rockchip/px30-mini-evb-ddr3-v11-avb.dts @@ -246,7 +246,7 @@ 15 00 02 d2 32 15 00 02 d3 00 39 00 04 ff 98 81 00 - 05 00 01 11 + 05 78 01 11 05 01 01 29 ]; From c6ec87e1a423ee749257e31ae65350bcfa3eb790 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Mon, 28 Nov 2022 08:20:50 +0000 Subject: [PATCH 171/235] arm64: dts: rockchip: rk3326-evb-lp3-v11-avb: Add a delay after exiting panel sleep mode Signed-off-by: Wyon Bi Change-Id: I20fbfd917bb4effdba05482690a513a43e613785 --- arch/arm64/boot/dts/rockchip/rk3326-evb-lp3-v11-avb.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 88dc225f4f01..4b1c4ea13fcf 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 @@ -242,7 +242,7 @@ 15 00 02 d2 32 15 00 02 d3 00 39 00 04 ff 98 81 00 - 05 00 01 11 + 05 78 01 11 05 01 01 29 ]; From 4a26cfea46990f1277709770cf6273c73e544102 Mon Sep 17 00:00:00 2001 From: David Wu Date: Mon, 28 Nov 2022 16:46:03 +0800 Subject: [PATCH 172/235] net: phy: rk630phy: Add Tx mos drive strength Signed-off-by: David Wu Change-Id: I8d4deef87d6e9be91100edfcbea40c0b8bd8c808 --- drivers/net/phy/rk630phy.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/phy/rk630phy.c b/drivers/net/phy/rk630phy.c index 42662f3d39f2..8d7265e891cd 100644 --- a/drivers/net/phy/rk630phy.c +++ b/drivers/net/phy/rk630phy.c @@ -53,6 +53,7 @@ #define REG_PAGE6_CP_CURRENT 0x17 #define REG_PAGE6_ADC_OP_BIAS 0x18 #define REG_PAGE6_RX_DECTOR 0x19 +#define REG_PAGE6_TX_MOS_DRV 0x1B #define REG_PAGE6_AFE_PDCW 0x1c /* PAGE 8 */ @@ -238,6 +239,8 @@ static void rk630_phy_t22_config_init(struct phy_device *phydev) phy_write(phydev, REG_PAGE6_RX_DECTOR, 0x0408); /* PHYAFE PDCW optimization */ phy_write(phydev, REG_PAGE6_AFE_PDCW, 0x8880); + /* Add PHY Tx mos drive, reduce power noise/jitter */ + phy_write(phydev, REG_PAGE6_TX_MOS_DRV, 0x888e); /* Switch to page 8 */ phy_write(phydev, REG_PAGE_SEL, 0x0800); From 8362e44f2f710987979389548ab5e884aaddb938 Mon Sep 17 00:00:00 2001 From: ZiHan Huang Date: Sat, 26 Nov 2022 16:14:22 +0800 Subject: [PATCH 173/235] ARM: dts: rockchip: rk3036: add pd_gpu Change-Id: I2850c18283f125b79429ca6799d9a53a86462ff3 Signed-off-by: ZiHan Huang --- arch/arm/boot/dts/rk3036.dtsi | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 72dbfabd388f..27f75a16e10f 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -479,7 +479,10 @@ <&cru ACLK_HEVC>; pm_qos = <&qos_vpu>; }; - + pd_gpu@RK3036_PD_GPU { + reg = ; + clocks = <&cru SCLK_GPU>; + }; }; }; From fa5530debc90ac1b243f47858c591c7d5e691ffb Mon Sep 17 00:00:00 2001 From: Li Huang Date: Mon, 28 Nov 2022 10:14:07 +0800 Subject: [PATCH 174/235] ARM: dts: rockchip: rk3036: update GPU node Change-Id: I43e646bf73f1d8252a6cad332d89126f535e34cf Signed-off-by: Li Huang --- arch/arm/boot/dts/rk3036.dtsi | 38 +++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index 27f75a16e10f..ba715b7e46ed 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -155,24 +155,40 @@ }; gpu: gpu@10090000 { - compatible = "rockchip,rk3036-mali", "arm,mali-400"; + compatible = "arm,mali400"; reg = <0x10090000 0x10000>; + upthreshold = <40>; + downdifferential = <10>; + interrupts = , - , - , - ; - interrupt-names = "gp", - "gpmmu", - "pp0", - "ppmmu0"; + , + , + ; + + interrupt-names = "Mali_GP_IRQ", + "Mali_GP_MMU_IRQ", + "Mali_PP0_IRQ", + "Mali_PP0_MMU_IRQ"; + + clocks = <&cru SCLK_GPU>; + clock-names = "clk_mali"; assigned-clocks = <&cru SCLK_GPU>; assigned-clock-rates = <400000000>; assigned-clock-parents = <&cru PLL_DPLL>; + power-domains = <&power RK3036_PD_GPU>; operating-points-v2 = <&gpu_opp_table>; - clocks = <&cru SCLK_GPU>, <&cru SCLK_GPU>; - clock-names = "bus", "core"; - resets = <&cru SRST_GPU>; + status = "disabled"; + + gpu_power_model: power_model { + compatible = "arm,mali-simple-power-model"; + voltage = <900>; + frequency = <500>; + static-power = <300>; + dynamic-power = <396>; + ts = <32000 4700 (-80) 2>; + thermal-zone = "soc-thermal"; + }; }; gpu_opp_table: opp-table1 { From 7b00a6d6dc57d0d09ffc2e5f34a69de0cefda72b Mon Sep 17 00:00:00 2001 From: Weiwen Chen Date: Tue, 29 Nov 2022 10:15:33 +0800 Subject: [PATCH 175/235] ARM: configs: rockchip: rv1106/rv1103 enable CONFIG_MTD_SPI_NOR_MISC for spi nor Signed-off-by: Weiwen Chen Change-Id: Ib0c3ee9974f4403bf077091c00227c5a6fa673cf --- arch/arm/configs/rv1106-battery-ipc.config | 2 +- arch/arm/configs/rv1106-evb.config | 3 +-- arch/arm/configs/rv1106-ipc.config | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/rv1106-battery-ipc.config b/arch/arm/configs/rv1106-battery-ipc.config index da7cc623d559..926a1e727a6a 100644 --- a/arch/arm/configs/rv1106-battery-ipc.config +++ b/arch/arm/configs/rv1106-battery-ipc.config @@ -165,7 +165,7 @@ CONFIG_MANDATORY_FILE_LOCKING=y # CONFIG_MTD_MCHP23K256 is not set # CONFIG_MTD_SPI_NAND is not set CONFIG_MTD_SPI_NOR=m -# CONFIG_MTD_SPI_NOR_MISC is not set +CONFIG_MTD_SPI_NOR_MISC=y # CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set # CONFIG_MTD_SST25L is not set # CONFIG_PI433 is not set diff --git a/arch/arm/configs/rv1106-evb.config b/arch/arm/configs/rv1106-evb.config index 4d120e187565..10716e6f5117 100644 --- a/arch/arm/configs/rv1106-evb.config +++ b/arch/arm/configs/rv1106-evb.config @@ -302,9 +302,7 @@ CONFIG_DRM_KMS_HELPER=y # CONFIG_DRM_LVDS_CODEC is not set # CONFIG_DRM_MALI_DISPLAY is not set # CONFIG_DRM_MAXIM_MAX96745 is not set -# CONFIG_DRM_MAXIM_MAX96752F is not set # CONFIG_DRM_MAXIM_MAX96755F is not set -# CONFIG_DRM_MAXIM_MAX96776 is not set # CONFIG_DRM_MCDE is not set # CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set # CONFIG_DRM_MXSFB is not set @@ -610,6 +608,7 @@ CONFIG_MTD_NAND_BBT_USING_FLASH=y CONFIG_MTD_NAND_CORE=y CONFIG_MTD_SPI_NAND=y CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_MISC=y # CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set # CONFIG_MTD_SST25L is not set CONFIG_MTD_UBI_BEB_LIMIT=20 diff --git a/arch/arm/configs/rv1106-ipc.config b/arch/arm/configs/rv1106-ipc.config index 663eafdb5a8f..fbd21938a8b7 100644 --- a/arch/arm/configs/rv1106-ipc.config +++ b/arch/arm/configs/rv1106-ipc.config @@ -161,6 +161,7 @@ CONFIG_MTD_BLKDEVS=y # CONFIG_MTD_MCHP23K256 is not set # CONFIG_MTD_SPI_NAND is not set CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_MISC=y # CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set # CONFIG_MTD_SST25L is not set # CONFIG_PI433 is not set From e356fea7b28bccd68ca2b619a6c01866b04aa77f Mon Sep 17 00:00:00 2001 From: ZiHan Huang Date: Tue, 29 Nov 2022 18:08:00 +0800 Subject: [PATCH 176/235] ARM: configs: rockchip_linux_defconfig: add remotectl pwm Change-Id: I62ec4985381e16b19d8dc00a16bdefa7258f2ff3 Signed-off-by: ZiHan Huang --- arch/arm/configs/rockchip_linux_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/rockchip_linux_defconfig b/arch/arm/configs/rockchip_linux_defconfig index dcd5e71914a0..98a0f13e5fe4 100644 --- a/arch/arm/configs/rockchip_linux_defconfig +++ b/arch/arm/configs/rockchip_linux_defconfig @@ -220,6 +220,8 @@ CONFIG_TOUCHSCREEN_GSL3673=y CONFIG_TOUCHSCREEN_GT1X=y CONFIG_TOUCHSCREEN_ELAN=y CONFIG_TOUCHSCREEN_USB_COMPOSITE=y +CONFIG_ROCKCHIP_REMOTECTL=y +CONFIG_ROCKCHIP_REMOTECTL_PWM=y CONFIG_INPUT_MISC=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_RK805_PWRKEY=y From 8a99863c84521eddfd4aa40e586185cb105af780 Mon Sep 17 00:00:00 2001 From: ZiHan Huang Date: Tue, 29 Nov 2022 18:09:37 +0800 Subject: [PATCH 177/235] ARM: dts: rockchip: rk3036 adaptive pwm3 Infrared function Change-Id: Idb6251f109900c4c2956688a849aced0e9872a10 Signed-off-by: ZiHan Huang --- arch/arm/boot/dts/rk3036.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index ba715b7e46ed..d912da5316eb 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -605,6 +605,7 @@ pwm3: pwm@20050030 { compatible = "rockchip,rk3036-pwm", "rockchip,rk3288-pwm"; reg = <0x20050030 0x10>; + interrupts = ; #pwm-cells = <3>; clocks = <&cru PCLK_PWM>; clock-names = "pwm"; From 593076a7067fc3ba9ee28f0f657619e84e7520ac Mon Sep 17 00:00:00 2001 From: David Wu Date: Mon, 28 Nov 2022 19:00:04 +0800 Subject: [PATCH 178/235] net: phy: motorcomm: Add 100m BGS voltage for RK631 Signed-off-by: David Wu Change-Id: I1a8fd4d428e0d3d6c8a0c6b3e2dd63c5d53590a5 --- drivers/net/phy/motorcomm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c index 3cb8ea0a9c9d..dbae7daefe3a 100644 --- a/drivers/net/phy/motorcomm.c +++ b/drivers/net/phy/motorcomm.c @@ -563,7 +563,7 @@ static int yt8531S_config_init(struct phy_device *phydev) static int yt8531_config_init(struct phy_device *phydev) { - int ret = 0; + int ret = 0, val; #if (YTPHY8531A_XTAL_INIT) ret = yt8531a_xtal_init(phydev); @@ -588,6 +588,13 @@ static int yt8531_config_init(struct phy_device *phydev) if (ret < 0) return ret; + /* Change 100M default BGS voltage from 0x294c to 0x274c */ + val = ytphy_read_ext(phydev, 0x57); + val = (val & ~(0xf << 8)) | (7 << 8); + ret = ytphy_write_ext(phydev, 0x57, val); + if (ret < 0) + return ret; + return ret; } From d331f0f14e73207543e70904046684bfc18583e4 Mon Sep 17 00:00:00 2001 From: Elon Zhang Date: Tue, 29 Nov 2022 16:04:20 +0800 Subject: [PATCH 179/235] ARM: dts: rockchip: rv1106-pinctrl: add sdmmc1m0_bus1 Signed-off-by: Elon Zhang Change-Id: I7e727eca6ece4d84d5cbd438c33c8be1ca72a263 --- arch/arm/boot/dts/rv1106-pinctrl.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/rv1106-pinctrl.dtsi b/arch/arm/boot/dts/rv1106-pinctrl.dtsi index dfbfbb3bf70d..37a46383174b 100644 --- a/arch/arm/boot/dts/rv1106-pinctrl.dtsi +++ b/arch/arm/boot/dts/rv1106-pinctrl.dtsi @@ -734,6 +734,13 @@ }; sdmmc1 { + /omit-if-no-ref/ + sdmmc1m0_bus1: sdmmc1m0-bus1 { + rockchip,pins = + /* sdmmc1_d0_m0 */ + <2 RK_PA1 1 &pcfg_pull_up_drv_level_2>; + }; + /omit-if-no-ref/ sdmmc1m0_bus4: sdmmc1m0-bus4 { rockchip,pins = From 0700444da44de9d4e1cfb24b8548b3d405fbb17d Mon Sep 17 00:00:00 2001 From: Elon Zhang Date: Mon, 28 Nov 2022 16:17:06 +0800 Subject: [PATCH 180/235] ARM: dts: rockchip: add rv1106g-smart-door-lock-rmsl-v12.dts Major changes from v10: 1) Change WiFi sdio from SDMMC0 to SDIO_M0. 2) RK803 Flood&PRO GPIO pin changes due to 1). Signed-off-by: Elon Zhang Change-Id: If264d2ec1ff7421a5089244b116cd3bac9bcbf70 --- arch/arm/boot/dts/Makefile | 1 + .../dts/rv1106g-smart-door-lock-rmsl-v12.dts | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v12.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index dbad1bc4facd..c9c729eb3243 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -995,6 +995,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rv1106g-evb2-v10.dtb \ rv1106g-evb2-v11-emmc.dtb \ rv1106g-smart-door-lock-rmsl-v10.dtb \ + rv1106g-smart-door-lock-rmsl-v12.dtb \ rv1106g-uvc-demo-v10.dtb \ rv1106g-uvc-demo-v10-spi-nor.dtb \ rv1108-elgin-r1.dtb \ diff --git a/arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v12.dts b/arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v12.dts new file mode 100644 index 000000000000..416592ee052d --- /dev/null +++ b/arch/arm/boot/dts/rv1106g-smart-door-lock-rmsl-v12.dts @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; + +#include "rv1106g-smart-door-lock-rmsl-v10.dts" + +/ { + model = "Rockchip RV1106G Smart Door Lock RMSL V12 Board"; + compatible = "rockchip,rv1106g-smart-door-lock-rmsl-v12", "rockchip,rv1106"; +}; + +&sdio { + max-frequency = <50000000>; + bus-width = <1>; + cap-sd-highspeed; + cap-sdio-irq; + keep-power-in-suspend; + non-removable; + rockchip,default-sample-phase = <90>; + no-mmc; + no-sd; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1m0_cmd &sdmmc1m0_clk &sdmmc1m0_bus1>; + status = "okay"; +}; + +&sdmmc { + status = "disabled"; +}; + +&vcsel_rk803 { + gpio-encc1-gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_HIGH>; //Flood + gpio-encc2-gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_HIGH>; //PRO +}; From e79faf3c91921054db7b52b23d0cb99cdfc9816d Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 29 Nov 2022 09:20:18 +0800 Subject: [PATCH 181/235] media: rockchip: vicap fixed data type error for Y8/Y10/Y12 Signed-off-by: Zefa Chen Change-Id: I9aa8841b5a0925eaa99117dd28c36d9929a4745a --- drivers/media/platform/rockchip/cif/capture.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index edcb7e2edacf..2f5cd3d3b2fa 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -607,18 +607,21 @@ static unsigned char get_data_type(u32 pixelformat, u8 cmd_mode_en, u8 dsi_input case MEDIA_BUS_FMT_SGBRG8_1X8: case MEDIA_BUS_FMT_SGRBG8_1X8: case MEDIA_BUS_FMT_SRGGB8_1X8: + case MEDIA_BUS_FMT_Y8_1X8: return 0x2a; /* csi raw10 */ case MEDIA_BUS_FMT_SBGGR10_1X10: case MEDIA_BUS_FMT_SGBRG10_1X10: case MEDIA_BUS_FMT_SGRBG10_1X10: case MEDIA_BUS_FMT_SRGGB10_1X10: + case MEDIA_BUS_FMT_Y10_1X10: return 0x2b; /* csi raw12 */ case MEDIA_BUS_FMT_SBGGR12_1X12: case MEDIA_BUS_FMT_SGBRG12_1X12: case MEDIA_BUS_FMT_SGRBG12_1X12: case MEDIA_BUS_FMT_SRGGB12_1X12: + case MEDIA_BUS_FMT_Y12_1X12: return 0x2c; /* csi uyvy 422 */ case MEDIA_BUS_FMT_UYVY8_2X8: From 9409e07a0110d8ea0f1a89df5f9b767106b935e6 Mon Sep 17 00:00:00 2001 From: Jianwei Fan Date: Thu, 24 Nov 2022 08:43:46 +0000 Subject: [PATCH 182/235] media: rockchip: cif: add BGR888 format support Change-Id: I1368917d0899f4f972c9ea3548b01dd9b9d1d6e8 Signed-off-by: Jianwei Fan --- drivers/media/platform/rockchip/cif/capture.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 2f5cd3d3b2fa..740e3dab25d1 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -149,6 +149,13 @@ static const struct cif_output_fmt out_fmts[] = { .bpp = { 24 }, .csi_fmt_val = CSI_WRDDR_TYPE_RGB888, .fmt_type = CIF_FMT_TYPE_RAW, + }, { + .fourcc = V4L2_PIX_FMT_BGR24, + .cplanes = 1, + .mplanes = 1, + .bpp = { 24 }, + .csi_fmt_val = CSI_WRDDR_TYPE_RGB888, + .fmt_type = CIF_FMT_TYPE_RAW, }, { .fourcc = V4L2_PIX_FMT_RGB565, .cplanes = 1, @@ -476,6 +483,10 @@ static const struct cif_input_fmt in_fmts[] = { .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, .csi_fmt_val = CSI_WRDDR_TYPE_RGB888, .field = V4L2_FIELD_NONE, + }, { + .mbus_code = MEDIA_BUS_FMT_BGR888_1X24, + .csi_fmt_val = CSI_WRDDR_TYPE_RGB888, + .field = V4L2_FIELD_NONE, }, { .mbus_code = MEDIA_BUS_FMT_RGB565_1X16, .csi_fmt_val = CSI_WRDDR_TYPE_RGB565, @@ -630,6 +641,7 @@ static unsigned char get_data_type(u32 pixelformat, u8 cmd_mode_en, u8 dsi_input case MEDIA_BUS_FMT_YVYU8_2X8: return 0x1e; case MEDIA_BUS_FMT_RGB888_1X24: + case MEDIA_BUS_FMT_BGR888_1X24: if (dsi_input) { if (cmd_mode_en) /* dsi command mode*/ return 0x39; @@ -3002,6 +3014,7 @@ static int rkcif_csi_get_output_type_mask(struct rkcif_stream *stream) mask = CSI_WRDDR_TYPE_YUV_PACKET | CSI_YUV_OUTPUT_ORDER_VYUY; break; case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_BGR666: mask = CSI_WRDDR_TYPE_RAW_COMPACT; @@ -3086,6 +3099,7 @@ static int rkcif_lvds_get_output_type_mask(struct rkcif_stream *stream) (CSI_YUV_OUTPUT_ORDER_VYUY << yuvout_offset); break; case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_BGR666: mask = CSI_WRDDR_TYPE_RAW_COMPACT << wr_type_offset; @@ -3875,7 +3889,8 @@ static int rkcif_create_dummy_buf(struct rkcif_stream *stream) if (tmp_dev->terminal_sensor.sd) { input_fmt = get_input_fmt(tmp_dev->terminal_sensor.sd, &rect, i, &csi_info); - if (input_fmt && input_fmt->mbus_code == MEDIA_BUS_FMT_RGB888_1X24) + if (input_fmt && (input_fmt->mbus_code == MEDIA_BUS_FMT_RGB888_1X24 || + input_fmt->mbus_code == MEDIA_BUS_FMT_BGR888_1X24)) size = rect.width * rect.height * 3; else size = rect.width * rect.height * 2; @@ -4375,6 +4390,7 @@ static u32 rkcif_align_bits_per_pixel(struct rkcif_stream *stream, bpp = fmt->bpp[plane_index + 1]; break; case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_BGR666: case V4L2_PIX_FMT_SRGGB8: @@ -4679,6 +4695,7 @@ static int rkcif_dvp_get_output_type_mask(struct rkcif_stream *stream) (CSI_YUV_OUTPUT_ORDER_VYUY << 1); break; case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_BGR666: mask = CSI_WRDDR_TYPE_RAW_COMPACT << 11; From 5151d5723aef82195e86f5ed0625a502c3318f88 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Tue, 29 Nov 2022 16:10:22 +0800 Subject: [PATCH 183/235] ARM: dts: rockchip: rk312x-android: enable irq mode for fiq-debugger Fiq mode is not ready on kernel-5.10. Signed-off-by: Liang Chen Change-Id: I658582c00b055fcab938e3ac479bb26b69c70201 --- arch/arm/boot/dts/rk312x-android.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk312x-android.dtsi b/arch/arm/boot/dts/rk312x-android.dtsi index ab026fa9f53a..6c9ec7e604f3 100644 --- a/arch/arm/boot/dts/rk312x-android.dtsi +++ b/arch/arm/boot/dts/rk312x-android.dtsi @@ -24,7 +24,7 @@ rockchip,signal-irq = <159>; rockchip,wake-irq = <0>; /* If enable uart uses irq instead of fiq */ - rockchip,irq-mode-enable = <0>; + rockchip,irq-mode-enable = <1>; rockchip,baudrate = <115200>; /* Only 115200 and 1500000 */ interrupts = ; status = "okay"; From 17dc73a159f2086a47030550de0527a9fd454341 Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Mon, 28 Nov 2022 15:04:06 +0800 Subject: [PATCH 184/235] drm/rockchip: logo: fix rockchip_free_loader_memory Add "mem=0x40000000" to COMMAND LINE, kernel will crash: [ 18.379633][ T35] Unable to handle kernel paging request at virtual address ffffffff01d7c000 [ 18.380412][ T35] Mem abort info: [ 18.380726][ T35] ESR = 0x96000006 [ 18.381060][ T35] EC = 0x25: DABT (current EL), IL = 32 bits [ 18.381587][ T35] SET = 0, FnV = 0 [ 18.381920][ T35] EA = 0, S1PTW = 0 [ 18.382264][ T35] Data abort info: [ 18.382585][ T35] ISV = 0, ISS = 0x00000006 [ 18.383029][ T35] CM = 0, WnR = 0 [ 18.383360][ T35] swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000001c47000 [ 18.384014][ T35] [ffffffff01d7c000] pgd=0000000040f2f003, p4d=0000000040f2f003, pud=0000000040f2f003, pmd=0000000000000000 [ 18.385299][ T35] Internal error: Oops: 96000006 [#1] PREEMPT SMP [ 18.385862][ T35] Modules linked in: [ 18.386205][ T35] CPU: 2 PID: 35 Comm: kworker/2:1 Not tainted 5.10.110 #324 [ 18.386843][ T35] Hardware name: Rockchip RK3568 EVB1 DDR4 V10 Board (DT) [ 18.387470][ T35] Workqueue: events rockchip_drm_fb_destroy_work [ 18.388026][ T35] pstate: 80c00009 (Nzcv daif +PAN +UAO -TCO BTYPE=--) [ 18.388626][ T35] pc : rockchip_free_loader_memory+0x100/0x1a0 [ 18.389156][ T35] lr : rockchip_free_loader_memory+0xc8/0x1a0 [ 18.389683][ T35] sp : ffffffc0125abd00 [ 18.390039][ T35] x29: ffffffc0125abd00 x28: 0000000000001000 [ 18.390570][ T35] x27: ffffff807df00000 x26: 0000008000000000 [ 18.391099][ T35] x25: fffffffeffe00000 x24: 0000000000000001 [ 18.391628][ T35] x23: ffffff80043d6300 x22: ffffff807df00000 [ 18.392157][ T35] x21: ffffff807dfb7000 x20: ffffff80043a8480 [ 18.392686][ T35] x19: ffffffff01d7c000 x18: 0000000000000000 [ 18.393215][ T35] x17: 0000000000000000 x16: 0000000000000000 [ 18.393744][ T35] x15: 00000072e03fbb78 x14: 0000000000000000 [ 18.394273][ T35] x13: 000000000000003d x12: 0000000000000000 [ 18.394802][ T35] x11: 00000000fffffff6 x10: ffffffc0122f8000 [ 18.395330][ T35] x9 : 0000000000010000 x8 : 0000000000000008 [ 18.395859][ T35] x7 : 0000000000818000 x6 : ffffff801ad909f0 [ 18.396387][ T35] x5 : 0000000000000039 x4 : ffffffc0122d01b8 [ 18.396917][ T35] x3 : 0000000000000000 x2 : 0000000000000000 [ 18.397445][ T35] x1 : ffffff80032622d8 x0 : 0000000000001000 [ 18.397975][ T35] Call trace: [ 18.398255][ T35] rockchip_free_loader_memory+0x100/0x1a0 [ 18.398762][ T35] __rockchip_drm_fb_destroy+0xa4/0xc8 [ 18.399233][ T35] rockchip_drm_fb_destroy_work+0x14/0x20 [ 18.399728][ T35] process_one_work+0x1b0/0x490 [ 18.400142][ T35] worker_thread+0x4c/0x3f8 [ 18.400534][ T35] kthread+0x140/0x160 [ 18.400882][ T35] ret_from_fork+0x10/0x30 Logo buffer allocated from Uboot which may removed in kernel for any purpose such as "debug". So, before freeing to the buddy system, we must check if the buffer are valid. Change-Id: I9a27c4552a3c7f450b034d2a6c6c3a321bb2fc54 Signed-off-by: Simon Xue --- drivers/gpu/drm/rockchip/rockchip_drm_logo.c | 21 ++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c index e50453ebae8d..f1dd87f9fb0f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c @@ -148,17 +148,19 @@ static int rockchip_drm_reserve_vm(struct drm_device *drm, struct drm_mm *mm, } static unsigned long -rockchip_drm_free_reserved_area(void *start, void *end, int poison, const char *s) +rockchip_drm_free_reserved_area(phys_addr_t start, phys_addr_t end, int poison, const char *s) { - void *pos; unsigned long pages = 0; - start = (void *)PAGE_ALIGN((unsigned long)start); - end = (void *)((unsigned long)end & PAGE_MASK); - for (pos = start; pos < end; pos += PAGE_SIZE, pages++) { - struct page *page = virt_to_page(pos); + start = ALIGN_DOWN(start, PAGE_SIZE); + end = PAGE_ALIGN(end); + for (; start < end; start += PAGE_SIZE) { + struct page *page = phys_to_page(start); void *direct_map_addr; + if (!pfn_valid(__phys_to_pfn(start))) + continue; + /* * 'direct_map_addr' might be different from 'pos' * because some architectures' virt_to_page() @@ -176,6 +178,7 @@ rockchip_drm_free_reserved_area(void *start, void *end, int poison, const char * memset(direct_map_addr, poison, PAGE_SIZE); free_reserved_page(page); + pages++; } if (pages && s) @@ -188,14 +191,11 @@ void rockchip_free_loader_memory(struct drm_device *drm) { struct rockchip_drm_private *private = drm->dev_private; struct rockchip_logo *logo; - void *start, *end; if (!private || !private->logo || --private->logo->count) return; logo = private->logo; - start = phys_to_virt(logo->dma_addr); - end = phys_to_virt(logo->dma_addr + logo->size); if (private->domain) { u32 pg_size = 1UL << __ffs(private->domain->pgsize_bitmap); @@ -205,7 +205,8 @@ void rockchip_free_loader_memory(struct drm_device *drm) } memblock_free(logo->start, logo->size); - rockchip_drm_free_reserved_area(start, end, -1, "drm_logo"); + rockchip_drm_free_reserved_area(logo->dma_addr, logo->dma_addr + logo->size, + -1, "drm_logo"); kfree(logo); private->logo = NULL; private->loader_protect = false; From 649f030b09b854d2bd3867766372062d462a0fd8 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Tue, 29 Nov 2022 15:54:39 +0800 Subject: [PATCH 185/235] video: rockchip: mpp: fix gcc-6 compile error without AV1DEC driver drivers/video/rockchip/mpp/mpp_service.o: In function `mpp_add_driver': drivers/video/rockchip/mpp/mpp_service.c:102: undefined reference to `av1dec_driver_register' Signed-off-by: Jianqun Xu Change-Id: Ibf2effb98ce7c0c2219d3bbd762dd8c34530626f --- drivers/video/rockchip/mpp/mpp_service.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_service.c b/drivers/video/rockchip/mpp/mpp_service.c index ffd30b33f053..beba6c3c18c4 100644 --- a/drivers/video/rockchip/mpp/mpp_service.c +++ b/drivers/video/rockchip/mpp/mpp_service.c @@ -98,7 +98,7 @@ static int mpp_add_driver(struct mpp_service *srv, &srv->grf_infos[type], grf_name); - if (type == MPP_DRIVER_AV1DEC) + if (IS_ENABLED(CONFIG_ROCKCHIP_MPP_AV1DEC) && type == MPP_DRIVER_AV1DEC) ret = av1dec_driver_register(driver); else ret = platform_driver_register(driver); @@ -116,11 +116,9 @@ static int mpp_remove_driver(struct mpp_service *srv, int i) if (i != MPP_DRIVER_AV1DEC) { mpp_set_grf(&srv->grf_infos[i]); platform_driver_unregister(srv->sub_drivers[i]); - } -#if IS_ENABLED(CONFIG_ROCKCHIP_MPP_AV1DEC) - else + } else if (IS_ENABLED(CONFIG_ROCKCHIP_MPP_AV1DEC)) { av1dec_driver_unregister(srv->sub_drivers[i]); -#endif + } srv->sub_drivers[i] = NULL; } From 37158d1f2b8335575e8e7adea28ebf2aa021bdd5 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 21 Oct 2019 16:13:03 +0800 Subject: [PATCH 186/235] clk: rockchip: rk3128: Change SCLK_DDRC to composite Change-Id: I6aeae7103c1eaed0b4515d8d11863c4b190b6918 Signed-off-by: Liang Chen Signed-off-by: Finley Xiao --- drivers/clk/rockchip/clk-rk3128.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3128.c b/drivers/clk/rockchip/clk-rk3128.c index 2bcbfe0a9795..34b3695ef582 100644 --- a/drivers/clk/rockchip/clk-rk3128.c +++ b/drivers/clk/rockchip/clk-rk3128.c @@ -212,9 +212,9 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKGATE_CON(0), 2, GFLAGS), GATE(0, "gpll_div2_ddr", "gpll_div2", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(0), 2, GFLAGS), - COMPOSITE_NOGATE(0, "ddrphy2x", mux_ddrphy_p, CLK_IGNORE_UNUSED, - RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO), - FACTOR(SCLK_DDRC, "clk_ddrc", "ddrphy2x", 0, 1, 2), + COMPOSITE_DDRCLK(SCLK_DDRC, "clk_ddrc", mux_ddrphy_p, 0, + RK2928_CLKSEL_CON(26), 8, 2, 0, 2, + ROCKCHIP_DDRCLK_SIP_V2), FACTOR(0, "clk_ddrphy", "ddrphy2x", 0, 1, 2), /* PD_CORE */ From cd10522093877da6a67be3a4e448b46aa5907c05 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 24 Nov 2022 16:24:45 +0800 Subject: [PATCH 187/235] clk: rockchip: fix up frac clk parent no update For some special conditions, the parent clock of fractional is not updated correctly. before clk summary: clk_spdif2_dp0_src clk_spdif2_dp0 mclk_spdif2 mclk_spdif2_dp0 clk_spdif2_dp0_frac after clk summary: clk_spdif2_dp0_src clk_spdif2_dp0_frac clk_spdif2_dp0 mclk_spdif2 mclk_spdif2_dp0 Signed-off-by: Elaine Zhang Change-Id: I9e9027774bf25f0f0ea6d8df6491a7feef4ffc48 --- drivers/clk/rockchip/clk.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 2e41b346ea31..5b2bdb33d327 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -154,6 +154,9 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, frac->mux_ops->set_parent(&frac_mux->hw, frac->mux_frac_idx); frac->rate_change_remuxed = 1; + clk_hw_set_parent(&frac_mux->hw, + clk_hw_get_parent_by_index(&frac_mux->hw, + frac->mux_frac_idx)); } } else if (event == POST_RATE_CHANGE) { /* From f07500720b299f379446f79ae7e94bf6cbe43efc Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Wed, 30 Nov 2022 09:49:38 +0800 Subject: [PATCH 188/235] phy: rockchip: usbdp: init flip variable in fixed lane mux case It should be initialized the USB flip for fixed lane mapping case if the USB lanes are assigned. The ln0/ln1 is normal (!flip) and ln2/ln3 is reverse (flip). This also amend "rx cdr lock timeout" log level to notice since it may not cause the functional defect in most cases. Signed-off-by: Frank Wang Change-Id: I693f772b87df97581a60f89219ec4dc6cafb79a3 --- drivers/phy/rockchip/phy-rockchip-usbdp.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c index 202ffc8c8ebf..f1a5169e16d3 100644 --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c @@ -668,14 +668,15 @@ static int udphy_disable(struct rockchip_udphy *udphy) return 0; } -static int udphy_parse_lane_mux_data(struct rockchip_udphy *udphy, struct device_node *np) +static int udphy_parse_lane_mux_data(struct rockchip_udphy *udphy, struct device *dev) { + struct device_node *np = dev->of_node; struct property *prop; int ret, i, len, num_lanes; prop = of_find_property(np, "rockchip,dp-lane-mux", &len); if (!prop) { - dev_dbg(udphy->dev, "failed to find dp lane mux, following dp alt mode\n"); + dev_dbg(dev, "failed to find dp lane mux, following dp alt mode\n"); udphy->mode = UDPHY_MODE_USB; return 0; } @@ -683,13 +684,13 @@ static int udphy_parse_lane_mux_data(struct rockchip_udphy *udphy, struct device num_lanes = len / sizeof(u32); if (num_lanes != 2 && num_lanes != 4) { - dev_err(udphy->dev, "invalid number of lane mux\n"); + dev_err(dev, "invalid number of lane mux\n"); return -EINVAL; } ret = of_property_read_u32_array(np, "rockchip,dp-lane-mux", udphy->dp_lane_sel, num_lanes); if (ret) { - dev_err(udphy->dev, "get dp lane mux failed\n"); + dev_err(dev, "get dp lane mux failed\n"); return -EINVAL; } @@ -697,7 +698,7 @@ static int udphy_parse_lane_mux_data(struct rockchip_udphy *udphy, struct device int j; if (udphy->dp_lane_sel[i] > 3) { - dev_err(udphy->dev, "lane mux between 0 and 3, exceeding the range\n"); + dev_err(dev, "lane mux between 0 and 3, exceeding the range\n"); return -EINVAL; } @@ -705,15 +706,17 @@ static int udphy_parse_lane_mux_data(struct rockchip_udphy *udphy, struct device for (j = i + 1; j < num_lanes; j++) { if (udphy->dp_lane_sel[i] == udphy->dp_lane_sel[j]) { - dev_err(udphy->dev, "set repeat lane mux value\n"); + dev_err(dev, "set repeat lane mux value\n"); return -EINVAL; } } } udphy->mode = UDPHY_MODE_DP; - if (num_lanes == 2) + if (num_lanes == 2) { udphy->mode |= UDPHY_MODE_USB; + udphy->flip = udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP ? true : false; + } return 0; } @@ -788,7 +791,7 @@ static int udphy_parse_dt(struct rockchip_udphy *udphy, struct device *dev) } } - ret = udphy_parse_lane_mux_data(udphy, np); + ret = udphy_parse_lane_mux_data(udphy, dev); if (ret) return ret; @@ -1341,14 +1344,14 @@ static int rk3588_udphy_status_check(struct rockchip_udphy *udphy) val & TRSV_LN0_MON_RX_CDR_LOCK_DONE, 200, 100000); if (ret) - dev_err(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n"); + dev_notice(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n"); } else { ret = regmap_read_poll_timeout(udphy->pma_regmap, TRSV_LN2_MON_RX_CDR_DONE_OFFSET, val, val & TRSV_LN2_MON_RX_CDR_LOCK_DONE, 200, 100000); if (ret) - dev_err(udphy->dev, "trsv ln2 mon rx cdr lock timeout\n"); + dev_notice(udphy->dev, "trsv ln2 mon rx cdr lock timeout\n"); } } From 22dccf0395202d294feb4d60bd12c6686c8be1aa Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Thu, 1 Dec 2022 10:17:54 +0800 Subject: [PATCH 189/235] iommu/rockchip: fix devm_free_irq RK3128 vop-iommu skip request the irq due to register read issue. So don't free irq when shut down or belowing error will output [ 102.107589] WARNING: CPU: 3 PID: 1013 at kernel/irq/devres.c:143 devm_free_irq+0x68/0x9c [ 102.115720] Modules linked in: [ 102.118862] CPU: 3 PID: 1013 Comm: init Not tainted 5.10.110 #15 [ 102.124907] Hardware name: Generic DT based system [ 102.129732] Backtrace: [ 102.132230] [] (dump_backtrace) from [] (show_stack+0x20/0x24) [ 102.139843] r7:600f0013 r6:c0e96442 r5:00000000 r4:c1219d6c [ 102.145553] [] (show_stack) from [] (dump_stack_lvl+0x94/0xac) [ 102.153171] [] (dump_stack_lvl) from [] (dump_stack+0x14/0x1c) [ 102.160780] r7:00000000 r6:00000000 r5:00000009 r4:c017ac34 [ 102.166488] [] (dump_stack) from [] (__warn+0xd4/0x100) [ 102.173497] [] (__warn) from [] (warn_slowpath_fmt+0x8c/0xc4) [ 102.181026] r9:00000000 r8:00000009 r7:c017ac34 r6:0000008f r5:c0df4ea4 r4:c353c000 [ 102.188820] [] (warn_slowpath_fmt) from [] (devm_free_irq+0x68/0x9c) [ 102.196962] r9:c0e44260 r8:c128d018 r7:c12ea690 r6:c1a17f40 r5:0000002e r4:c353c000 [ 102.204759] [] (devm_free_irq) from [] (rk_iommu_shutdown+0x58/0x5c) [ 102.212895] r6:c1a17f40 r5:00000001 r4:c197ec00 [ 102.217558] [] (rk_iommu_shutdown) from [] (platform_drv_shutdown+0x2c/0x30) [ 102.226385] r7:c12ea690 r6:c12285f0 r5:c197ec10 r4:c197ec14 [ 102.232094] [] (platform_drv_shutdown) from [] (device_shutdown+0x15c/0x1dc) [ 102.240938] [] (device_shutdown) from [] (kernel_restart_prepare+0x3c/0x48) [ 102.249684] r10:00000058 r9:01234567 r8:00000010 r7:c353c000 r6:4321fedc r5:c11168ec [ 102.257548] r4:00000000 [ 102.260124] [] (kernel_restart_prepare) from [] (kernel_restart+0x1c/0x60) [ 102.268785] [] (kernel_restart) from [] (__do_sys_reboot+0x154/0x1e0) [ 102.277004] r5:c11168ec r4:00000000 [ 102.280617] [] (__do_sys_reboot) from [] (sys_reboot+0x18/0x1c) [ 102.288326] r9:c353c000 r8:c01002c4 r7:00000058 r6:005241c4 r5:00524140 r4:00000000 [ 102.296121] [] (sys_reboot) from [] (ret_fast_syscall+0x0/0x54) [ 102.303821] Exception stack(0xc353dfa8 to 0xc353dff0) [ 102.308912] dfa0: 00000000 00524140 fee1dead 28121969 01234567 00000010 [ 102.317141] dfc0: 00000000 00524140 005241c4 00000058 beddbefc 0044b1a8 b6f39d00 b6f3a010 [ 102.325364] dfe0: 00523b5c beddbc90 004dadf4 b6e584c8 [ 102.330545] ---[ end trace adc766c58fa6634f ]--- [ 102.335275] ------------[ cut here ]------------ [ 102.339948] WARNING: CPU: 3 PID: 1013 at kernel/irq/manage.c:1756 free_irq+0x26c/0x29c [ 102.347907] Trying to free already-free IRQ 46 [ 102.352381] Modules linked in: [ 102.355479] CPU: 3 PID: 1013 Comm: init Tainted: G W 5.10.110 #15 [ 102.362907] Hardware name: Generic DT based system [ 102.367721] Backtrace: [ 102.370212] [] (dump_backtrace) from [] (show_stack+0x20/0x24) [ 102.377824] r7:600f0093 r6:c0e96442 r5:00000000 r4:c1219d6c [ 102.383532] [] (show_stack) from [] (dump_stack_lvl+0x94/0xac) [ 102.391150] [] (dump_stack_lvl) from [] (dump_stack+0x14/0x1c) [ 102.398759] r7:c353dd34 r6:00000000 r5:00000009 r4:c017823c [ 102.404466] [] (dump_stack) from [] (__warn+0xd4/0x100) [ 102.411473] [] (__warn) from [] (warn_slowpath_fmt+0x8c/0xc4) [ 102.419002] r9:c0df48e7 r8:00000009 r7:c017823c r6:000006dc r5:c0df4854 r4:c353c000 [ 102.426799] [] (warn_slowpath_fmt) from [] (free_irq+0x26c/0x29c) [ 102.434676] r9:600f0013 r8:0000002e r7:c1a17f40 r6:c1978a6c r5:00000000 r4:c1978a00 [ 102.442471] [] (free_irq) from [] (devm_free_irq+0x74/0x9c) [ 102.449832] r10:c197ec54 r9:c0e44260 r8:c128d018 r7:c12ea690 r6:c1a17f40 r5:0000002e [ 102.457700] r4:c353c000 [ 102.460278] [] (devm_free_irq) from [] (rk_iommu_shutdown+0x58/0x5c) [ 102.468414] r6:c1a17f40 r5:00000001 r4:c197ec00 [ 102.473075] [] (rk_iommu_shutdown) from [] (platform_drv_shutdown+0x2c/0x30) [ 102.481901] r7:c12ea690 r6:c12285f0 r5:c197ec10 r4:c197ec14 [ 102.487611] [] (platform_drv_shutdown) from [] (device_shutdown+0x15c/0x1dc) [ 102.496453] [] (device_shutdown) from [] (kernel_restart_prepare+0x3c/0x48) [ 102.505200] r10:00000058 r9:01234567 r8:00000010 r7:c353c000 r6:4321fedc r5:c11168ec [ 102.513066] r4:00000000 [ 102.515642] [] (kernel_restart_prepare) from [] (kernel_restart+0x1c/0x60) [ 102.524302] [] (kernel_restart) from [] (__do_sys_reboot+0x154/0x1e0) [ 102.532521] r5:c11168ec r4:00000000 [ 102.536134] [] (__do_sys_reboot) from [] (sys_reboot+0x18/0x1c) [ 102.543833] r9:c353c000 r8:c01002c4 r7:00000058 r6:005241c4 r5:00524140 r4:00000000 [ 102.551626] [] (sys_reboot) from [] (ret_fast_syscall+0x0/0x54) [ 102.559324] Exception stack(0xc353dfa8 to 0xc353dff0) [ 102.564414] dfa0: 00000000 00524140 fee1dead 28121969 01234567 00000010 [ 102.572641] dfc0: 00000000 00524140 005241c4 00000058 beddbefc 0044b1a8 b6f39d00 b6f3a010 [ 102.580864] dfe0: 00523b5c beddbc90 004dadf4 b6e584c8 [ 102.585947] ---[ end trace adc766c58fa66350 ]--- Change-Id: Ic0603d4d00528dc6b5ef6d480b15d3c14585dec3 Signed-off-by: Simon Xue --- drivers/iommu/rockchip-iommu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 5d22c575b295..541fbf22ce56 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -1960,12 +1960,16 @@ static void rk_iommu_shutdown(struct platform_device *pdev) struct rk_iommu *iommu = platform_get_drvdata(pdev); int i; + if (iommu->skip_read) + goto skip_free_irq; + for (i = 0; i < iommu->num_irq; i++) { int irq = platform_get_irq(pdev, i); devm_free_irq(iommu->dev, irq, iommu); } +skip_free_irq: pm_runtime_force_suspend(&pdev->dev); } From 9368d304795eab874674d0d4c15c0c12f528d6a5 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Wed, 30 Nov 2022 19:42:06 +0800 Subject: [PATCH 190/235] ARM: dts: rockchip: rk3128-evb-ddr3-v10-linux: correct node name for rk805 regualtors error log: [ 3.079253] rk808 0-0018: using lookup tables for GPIO lookup [ 3.079269] rk808 0-0018: No GPIO consumer dvs found [ 3.079285] rk808-regulator rk808-regulator: there is no dvs1 gpio [ 3.086236] DCDC_REG1: supplied by regulator-dummy [ 3.092350] DCDC_REG2: supplied by regulator-dummy [ 3.092948] <>[gt1x_get_chip_type:903] Chip Type: GT1X [ 3.097899] DCDC_REG3: supplied by regulator-dummy [ 3.109098] DCDC_REG4: supplied by regulator-dummy [ 3.112873] <>[gt1x_read_version:859] IC VERSION:GT917S_000203(Patch)_0101(Mask)_00(SensorID) [ 3.123382] <>[gt1x_init_panel:604] Config group0 used, length:239 [ 3.123744] LDO_REG1: supplied by regulator-dummy [ 3.130454] <>[gt1x_init_panel:655] X_MAX=720,Y_MAX=1280,TRIGGER=0x01,WAKEUP_LEVEL=1 [ 3.144571] LDO_REG2: supplied by regulator-dummy [ 3.150481] LDO_REG3: supplied by regulator-dummy [ 3.160549] rk808-rtc rk808-rtc: registered as rtc1 root@rk312x:/# root@rk312x:/# ls /sys/kernel/debug/regulator/ 0-0018-DCDC_REG1 supply_map 0-0018-DCDC_REG2 vcc3v3_lcd_n 0-0018-DCDC_REG3 vcc5v0_sys 0-0018-DCDC_REG4 vcc_2v8_cam 0-0018-LDO_REG1 vcc_host_5v 0-0018-LDO_REG2 vcc_hub_5v 0-0018-LDO_REG3 vcc_phy reg-dummy-regulator-dummy vcc_sdmmc regulator_summary vccio_wifi Signed-off-by: Liang Chen Change-Id: Iac0857006b09b56981c6033f74318eb80a2936e0 --- .../boot/dts/rk3128-evb-ddr3-v10-linux.dts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/rk3128-evb-ddr3-v10-linux.dts b/arch/arm/boot/dts/rk3128-evb-ddr3-v10-linux.dts index 9a0a2f154fa8..7fe966946769 100644 --- a/arch/arm/boot/dts/rk3128-evb-ddr3-v10-linux.dts +++ b/arch/arm/boot/dts/rk3128-evb-ddr3-v10-linux.dts @@ -615,6 +615,13 @@ #clock-cells = <1>; clock-output-names = "rk805-clkout1", "rk805-clkout2"; + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc_io>; + vcc6-supply = <&vcc_io>; + rtc { status = "okay"; }; @@ -633,7 +640,7 @@ #address-cells = <1>; #size-cells = <0>; - vdd_arm: RK805_DCDC1@0 { + vdd_arm: DCDC_REG1 { regulator-name = "vdd_arm"; regulator-min-microvolt = <700000>; regulator-max-microvolt = <1500000>; @@ -648,7 +655,7 @@ }; }; - vdd_logic: RK805_DCDC2@1 { + vdd_logic: DCDC_REG2 { regulator-name = "vdd_logic"; regulator-min-microvolt = <700000>; regulator-max-microvolt = <1500000>; @@ -663,7 +670,7 @@ }; }; - vcc_ddr: RK805_DCDC3@2 { + vcc_ddr: DCDC_REG3 { regulator-name = "vcc_ddr"; regulator-initial-mode = <0x1>; regulator-boot-on; @@ -674,7 +681,7 @@ }; }; - vcc_io: RK805_DCDC4@3 { + vcc_io: DCDC_REG4 { regulator-name = "vcc_io"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; @@ -688,7 +695,7 @@ }; }; - vcca_33: RK805_LDO1@4 { + vcca_33: LDO_REG1 { regulator-name = "vcca_33"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; @@ -701,7 +708,7 @@ }; }; - vcc_1v8_cam: RK805_LDO2@5 { + vcc_1v8_cam: LDO_REG2 { regulator-name = "vcc_1v8_cam"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; @@ -713,7 +720,7 @@ }; }; - vdd10_pmu: RK805_LDO3@6 { + vdd10_pmu: LDO_REG3 { regulator-name = "vdd10_pmu"; regulator-min-microvolt = <1100000>; regulator-max-microvolt = <1100000>; From ea5fb2601103a48a98fa7ab638837a1ff5d89a91 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 30 Nov 2022 18:06:00 +0800 Subject: [PATCH 191/235] drm/rockchip: tve: Fix shutdown panic when no bind Unable to handle kernel access to user memory outside uaccess routines at virtual address 0000000000000830 Mem abort info: ESR = 0x96000005 Exception class = DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 Data abort info: ISV = 0, ISS = 0x00000005 CM = 0, WnR = 0 user pgtable: 4k pages, 39-bit VAs, pgdp = 00000000aaff8145 [0000000000000830] pgd=000000007a5c9003, pud=000000007a5c9003, pmd=0000000000000000 Internal error: Oops: 96000005 [#1] PREEMPT SMP Modules linked in: Process init (pid: 1, stack limit = 0x00000000722656e6) CPU: 3 PID: 1 Comm: init Not tainted 4.19.232 #72 Hardware name: Rockchip RK3528 EVB1 DDR4 V10 Board (DT) pstate: 60400005 (nZCv daif +PAN -UAO) pc : __ll_sc___cmpxchg_case_acq_8+0x4/0x20 lr : mutex_lock+0x18/0x40 sp : ffffff800802bc60 x29: ffffff800802bc60 x28: ffffffc07c8e0000 x27: 0000000000000000 x26: 0000000000000000 x25: ffffff8009510d78 x24: ffffff8009cde040 x23: ffffffc07c9e3890 x22: ffffff8009d89000 x21: ffffff8009b73b30 x20: 0000000000000000 x19: 0000000000000830 x18: ffffffffffffffff x17: 0000000000000000 x16: 0000000000000002 x15: ffffff80095ed278 x14: ffffff8089ce4196 x13: ffffff8009ce41b0 x12: ffffff8009ce45d0 x11: ffffff8009adf3b8 x10: 0000000005f5e0ff x9 : 00000000ffffffd0 x8 : 6873203a73756c70 x7 : 0000000000000058 x6 : 0000000000000001 x5 : 0000000000000005 x4 : 0000000000000004 x3 : 0000000000000830 x2 : ffffffc07c8e0000 x1 : 0000000000000000 x0 : 0000000000000830 Call trace: __ll_sc___cmpxchg_case_acq_8+0x4/0x20 rockchip_tve_shutdown+0x1c/0x38 platform_drv_shutdown+0x20/0x30 device_shutdown+0x118/0x200 kernel_restart_prepare+0x34/0x40 kernel_restart+0x14/0x78 __se_sys_reboot+0x1cc/0x208 __arm64_sys_reboot+0x18/0x20 el0_svc_common.constprop.0+0x64/0x178 el0_svc_handler+0x28/0x78 el0_svc+0x8/0xc Signed-off-by: Tao Huang Change-Id: Ic1e85b963548e5e66ef78fae5af8dcc12e928fa2 --- drivers/gpu/drm/rockchip/rockchip_drm_tve.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c index 0acf55916056..5039b877385b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c @@ -483,7 +483,6 @@ static int rockchip_tve_bind(struct device *dev, struct device *master, } tve->enable = 0; - platform_set_drvdata(pdev, tve); tve->drm_dev = drm_dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); tve->reg_phy_base = res->start; @@ -544,6 +543,7 @@ static int rockchip_tve_bind(struct device *dev, struct device *master, rockchip_drm_register_sub_dev(&tve->sub_dev); pm_runtime_enable(dev); + dev_set_drvdata(dev, tve); dev_dbg(tve->dev, "%s tv encoder probe ok\n", match->compatible); return 0; @@ -567,6 +567,7 @@ static void rockchip_tve_unbind(struct device *dev, struct device *master, drm_encoder_cleanup(&tve->encoder); pm_runtime_disable(dev); + dev_set_drvdata(dev, NULL); } static const struct component_ops rockchip_tve_component_ops = { @@ -585,6 +586,9 @@ static void rockchip_tve_shutdown(struct platform_device *pdev) { struct rockchip_tve *tve = dev_get_drvdata(&pdev->dev); + if (!tve) + return; + mutex_lock(&tve->suspend_lock); dev_dbg(tve->dev, "tve shutdown\n"); From e50ad473dbe35fbb758fc9d7c9138d944bd023e9 Mon Sep 17 00:00:00 2001 From: Zhihuan He Date: Tue, 8 Nov 2022 11:09:59 +0800 Subject: [PATCH 192/235] PM / devfreq: rockchip-dfi: rk3588: fix total counter get err for lp5 Signed-off-by: Zhihuan He Change-Id: I5e267a3ed4eb5d501d5634111f67ec4cc6d690d6 --- drivers/devfreq/event/rockchip-dfi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c index 80bdfea5bb7b..0708535bda18 100644 --- a/drivers/devfreq/event/rockchip-dfi.c +++ b/drivers/devfreq/event/rockchip-dfi.c @@ -537,7 +537,10 @@ static __maybe_unused __init int rk3588_dfi_init(struct platform_device *pdev, data->dram_type = READ_DRAMTYPE_INFO(val_2); data->mon_idx = 0x4000; - data->count_rate = 2; + if (data->dram_type == LPDDR5) + data->count_rate = 1; + else + data->count_rate = 2; data->dram_dynamic_info_reg = RK3588_PMUGRF_OS_REG(6); data->ch_msk = READ_CH_INFO(val_2) | READ_CH_INFO(val_4) << 2; data->clk = NULL; From d0fdfb8dcdd28548ba39e01b1e12cc9115bbf0e6 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Thu, 1 Dec 2022 15:02:22 +0800 Subject: [PATCH 193/235] soc: rockchip: rockchip_system_monitor: Add support set video 4k 60fps status Signed-off-by: Liang Chen Change-Id: If3250c44e8340585003a64b9b3a3145292086cd6 --- drivers/soc/rockchip/rockchip_system_monitor.c | 8 ++++++-- include/dt-bindings/soc/rockchip-system-status.h | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/soc/rockchip/rockchip_system_monitor.c b/drivers/soc/rockchip/rockchip_system_monitor.c index 4f3f46364355..e5350b3dd60e 100644 --- a/drivers/soc/rockchip/rockchip_system_monitor.c +++ b/drivers/soc/rockchip/rockchip_system_monitor.c @@ -297,6 +297,7 @@ static void rockchip_update_video_info(void) { struct video_info *video_info; unsigned int max_res = 0, max_stream_bitrate = 0, res = 0; + unsigned int max_video_framerate = 0; mutex_lock(&video_info_mutex); if (list_empty(&video_info_list)) { @@ -311,6 +312,8 @@ static void rockchip_update_video_info(void) max_res = res; if (video_info->streamBitrate > max_stream_bitrate) max_stream_bitrate = video_info->streamBitrate; + if (video_info->videoFramerate > max_video_framerate) + max_video_framerate = video_info->videoFramerate; } mutex_unlock(&video_info_mutex); @@ -319,8 +322,9 @@ static void rockchip_update_video_info(void) } else { if (max_stream_bitrate == 10) rockchip_set_system_status(SYS_STATUS_VIDEO_4K_10B); - else - rockchip_set_system_status(SYS_STATUS_VIDEO_4K); + if (max_video_framerate == 60) + rockchip_set_system_status(SYS_STATUS_VIDEO_4K_60P); + rockchip_set_system_status(SYS_STATUS_VIDEO_4K); } } diff --git a/include/dt-bindings/soc/rockchip-system-status.h b/include/dt-bindings/soc/rockchip-system-status.h index b6689e969672..fefd62642e42 100644 --- a/include/dt-bindings/soc/rockchip-system-status.h +++ b/include/dt-bindings/soc/rockchip-system-status.h @@ -36,10 +36,12 @@ #define SYS_STATUS_LOW_POWER (1 << 17) #define SYS_STATUS_HDMIRX (1 << 18) #define SYS_STATUS_VIDEO_SVEP (1 << 19) +#define SYS_STATUS_VIDEO_4K_60P (1 << 20) #define SYS_STATUS_VIDEO (SYS_STATUS_VIDEO_4K | \ SYS_STATUS_VIDEO_1080P | \ - SYS_STATUS_VIDEO_4K_10B) + SYS_STATUS_VIDEO_4K_10B | \ + SYS_STATUS_VIDEO_4K_60P) #define SYS_STATUS_DUALVIEW (SYS_STATUS_LCDC0 | SYS_STATUS_LCDC1) #define DMC_FREQ_LEVEL_LOW (0x1 << 0) From 545e8565ef9b6ca62c576273a632737de8130e7a Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Thu, 1 Dec 2022 15:03:59 +0800 Subject: [PATCH 194/235] PM / devfreq: rockchip_dmc: Add SYS_STATUS_VIDEO_4K_60P Signed-off-by: Liang Chen Change-Id: I091f395dfcf8f6b11f77d03b860f4ea8450678b2 --- drivers/devfreq/rockchip_dmc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 0b3625010747..f2579aff9781 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -136,6 +136,7 @@ struct rockchip_dmcfreq { unsigned long video_1080p_rate; unsigned long video_4k_rate; unsigned long video_4k_10b_rate; + unsigned long video_4k_60p_rate; unsigned long video_svep_rate; unsigned long performance_rate; unsigned long hdmi_rate; @@ -2461,6 +2462,11 @@ static int rockchip_get_system_status_level(struct device_node *np, dev_info(dmcfreq->dev, "video_4k_10b_rate = %ld\n", dmcfreq->video_4k_10b_rate); break; + case SYS_STATUS_VIDEO_4K_60P: + dmcfreq->video_4k_60p_rate = rockchip_freq_level_2_rate(dmcfreq, level); + dev_info(dmcfreq->dev, "video_4k_60p_rate = %ld\n", + dmcfreq->video_4k_60p_rate); + break; case SYS_STATUS_VIDEO_SVEP: dmcfreq->video_svep_rate = rockchip_freq_level_2_rate(dmcfreq, level); dev_info(dmcfreq->dev, "video_svep_rate = %ld\n", @@ -2584,6 +2590,11 @@ static int rockchip_dmcfreq_system_status_notifier(struct notifier_block *nb, target_rate = dmcfreq->video_4k_10b_rate; } + if (dmcfreq->video_4k_60p_rate && (status & SYS_STATUS_VIDEO_4K_60P)) { + if (dmcfreq->video_4k_60p_rate > target_rate) + target_rate = dmcfreq->video_4k_60p_rate; + } + if (dmcfreq->video_1080p_rate && (status & SYS_STATUS_VIDEO_1080P)) { if (dmcfreq->video_1080p_rate > target_rate) target_rate = dmcfreq->video_1080p_rate; From 7c2d6bfd55b66d4f507e12b947e894cf6ed5b7ab Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Thu, 1 Dec 2022 22:30:56 +0800 Subject: [PATCH 195/235] drivers: rkflash: Fix the error definition of SFC dll cells Change-Id: I7429a115df0719c918834886c4f6ef7823ef1414 Signed-off-by: Jon Lin --- drivers/rkflash/sfc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rkflash/sfc.h b/drivers/rkflash/sfc.h index 703072d52086..8e91c376acf0 100644 --- a/drivers/rkflash/sfc.h +++ b/drivers/rkflash/sfc.h @@ -68,8 +68,8 @@ /* SFC_DLL_CTRL Register */ #define SCLK_SMP_SEL_EN BIT(15) /* SCLK Sampling Selection */ -#define SCLK_SMP_SEL_MAX_V4 0x1FF -#define SCLK_SMP_SEL_MAX_V5 0xFF +#define SCLK_SMP_SEL_MAX_V4 0xFF +#define SCLK_SMP_SEL_MAX_V5 0x1FF #define SFC_DLL_TRANING_STEP 10 /* Training step */ #define SFC_DLL_TRANING_VALID_WINDOW 80 /* Valid DLL winbow */ From ea5e44076e2a7a7bbc6be9ba59fa0c99e9dca0f4 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 30 Nov 2022 19:50:34 +0800 Subject: [PATCH 196/235] soc: rockchip: grf: allow insmod to succeed if no DT match Signed-off-by: Tao Huang Change-Id: I1bc31e2e67bfcedf91f890780bcbae62d538b6d9 --- drivers/soc/rockchip/grf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/rockchip/grf.c b/drivers/soc/rockchip/grf.c index 97c276b6b416..7b1f24d279b4 100644 --- a/drivers/soc/rockchip/grf.c +++ b/drivers/soc/rockchip/grf.c @@ -319,7 +319,7 @@ static int __init rockchip_grf_init(void) np = of_find_matching_node_and_match(NULL, rockchip_grf_dt_match, &match); if (!np) - return -ENODEV; + return 0; if (!match || !match->data) { pr_err("%s: missing grf data\n", __func__); return -EINVAL; From 5305ba28603d43be2a430bc61db963509e842fa0 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Thu, 1 Dec 2022 18:44:09 +0800 Subject: [PATCH 197/235] clk: rockchip: rk3568: allow insmod to succeed if no DT match Signed-off-by: Tao Huang Change-Id: I3e6326773603509ae076229fb71f188b2edae3fe --- drivers/clk/rockchip/clk-rk3568.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c index 66076d68bb39..fa4dd1e39205 100644 --- a/drivers/clk/rockchip/clk-rk3568.c +++ b/drivers/clk/rockchip/clk-rk3568.c @@ -1699,6 +1699,7 @@ static void __init rk3568_clk_init(struct device_node *np) CLK_OF_DECLARE(rk3568_cru, "rockchip,rk3568-cru", rk3568_clk_init); +#ifdef MODULE struct clk_rk3568_inits { void (*inits)(struct device_node *np); }; @@ -1723,7 +1724,7 @@ static const struct of_device_id clk_rk3568_match_table[] = { }; MODULE_DEVICE_TABLE(of, clk_rk3568_match_table); -static int __init clk_rk3568_probe(struct platform_device *pdev) +static int clk_rk3568_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; @@ -1741,14 +1742,16 @@ static int __init clk_rk3568_probe(struct platform_device *pdev) } static struct platform_driver clk_rk3568_driver = { + .probe = clk_rk3568_probe, .driver = { .name = "clk-rk3568", .of_match_table = clk_rk3568_match_table, .suppress_bind_attrs = true, }, }; -builtin_platform_driver_probe(clk_rk3568_driver, clk_rk3568_probe); +module_platform_driver(clk_rk3568_driver); MODULE_DESCRIPTION("Rockchip RK3568 Clock Driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:clk-rk3568"); +#endif /* MODULE */ From e5e0f7afd8705ec95c60ce4e83ac1f66f69a7fbf Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Thu, 1 Dec 2022 18:53:57 +0800 Subject: [PATCH 198/235] clk: rockchip: rk3588: allow insmod to succeed if no DT match Signed-off-by: Tao Huang Change-Id: I175e3200a41fd3a81059b90d1d6b77d47ea39913 --- drivers/clk/rockchip/clk-rk3588.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c index a7b25c1d309b..1331452fbd46 100644 --- a/drivers/clk/rockchip/clk-rk3588.c +++ b/drivers/clk/rockchip/clk-rk3588.c @@ -2456,6 +2456,7 @@ static void __init rk3588_clk_init(struct device_node *np) CLK_OF_DECLARE(rk3588_cru, "rockchip,rk3588-cru", rk3588_clk_init); +#ifdef MODULE struct clk_rk3588_inits { void (*inits)(struct device_node *np); }; @@ -2473,7 +2474,7 @@ static const struct of_device_id clk_rk3588_match_table[] = { }; MODULE_DEVICE_TABLE(of, clk_rk3588_match_table); -static int __init clk_rk3588_probe(struct platform_device *pdev) +static int clk_rk3588_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; @@ -2491,13 +2492,15 @@ static int __init clk_rk3588_probe(struct platform_device *pdev) } static struct platform_driver clk_rk3588_driver = { + .probe = clk_rk3588_probe, .driver = { .name = "clk-rk3588", .of_match_table = clk_rk3588_match_table, .suppress_bind_attrs = true, }, }; -builtin_platform_driver_probe(clk_rk3588_driver, clk_rk3588_probe); +module_platform_driver(clk_rk3588_driver); MODULE_DESCRIPTION("Rockchip RK3588 Clock Driver"); MODULE_LICENSE("GPL"); +#endif /* MODULE */ From 567e355611666ee3a91572d8faa5739df4f60a4a Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Fri, 2 Dec 2022 18:11:00 +0800 Subject: [PATCH 199/235] arm64: dts: rockchip: rk3588: Add memory read margin for litcore and dsu It may improve stability. Signed-off-by: Finley Xiao Change-Id: I8d41ee7348bff9d280b5d22e42d8ad356d2db7eb --- arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi index 9020e7a9999d..3242b514f80b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -596,8 +596,16 @@ rockchip,pvtm-thermal-zone = "soc-thermal"; rockchip,grf = <&litcore_grf>; - - rockchip,reboot-freq = <1416000>; + rockchip,dsu-grf = <&dsu_grf>; + volt-mem-read-margin = < + 855000 1 + 765000 2 + 675000 3 + 495000 4 + >; + low-volt-mem-read-margin = <4>; + intermediate-threshold-freq = <1008000>; /* KHz */ + rockchip,reboot-freq = <1416000>; /* KHz */ rockchip,temp-hysteresis = <5000>; rockchip,low-temp = <10000>; From 24ae565a727d8ea763f3dcd192be7251eafb4523 Mon Sep 17 00:00:00 2001 From: Wenchao Chen Date: Fri, 16 Sep 2022 17:05:06 +0800 Subject: [PATCH 200/235] UPSTREAM: mmc: hsq: Fix data stomping during mmc recovery The block device uses multiple queues to access emmc. There will be up to 3 requests in the hsq of the host. The current code will check whether there is a request doing recovery before entering the queue, but it will not check whether there is a request when the lock is issued. The request is in recovery mode. If there is a request in recovery, then a read and write request is initiated at this time, and the conflict between the request and the recovery request will cause the data to be trampled. Signed-off-by: Wenchao Chen Fixes: 511ce378e16f ("mmc: Add MMC host software queue support") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20220916090506.10662-1-wenchao.chen666@gmail.com Signed-off-by: Ulf Hansson Signed-off-by: Shawn Lin Change-Id: I879d746f578ba7c6f27029d81c980c743c3215ba (cherry picked from commit e7afa79a3b35a27a046a2139f8b20bd6b98155c2) --- drivers/mmc/host/mmc_hsq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/mmc_hsq.c b/drivers/mmc/host/mmc_hsq.c index a5e05ed0fda3..9d35453e7371 100644 --- a/drivers/mmc/host/mmc_hsq.c +++ b/drivers/mmc/host/mmc_hsq.c @@ -34,7 +34,7 @@ static void mmc_hsq_pump_requests(struct mmc_hsq *hsq) spin_lock_irqsave(&hsq->lock, flags); /* Make sure we are not already running a request now */ - if (hsq->mrq) { + if (hsq->mrq || hsq->recovery_halt) { spin_unlock_irqrestore(&hsq->lock, flags); return; } From 00b877ac98cef98d35ef1666868f4a80ff58850d Mon Sep 17 00:00:00 2001 From: David Wu Date: Fri, 2 Dec 2022 19:38:12 +0800 Subject: [PATCH 201/235] ethernet: arc: Fix the device for dma_map_single/dma_unmap_single The ndev->dev and pdev->dev aren't the same device, use ndev->dev.parent which has dma_mask, ndev->dev.parent is just pdev->dev. Or it would cause the following issue: [ 39.933526] ------------[ cut here ]------------ [ 39.938414] WARNING: CPU: 1 PID: 501 at kernel/dma/mapping.c:149 dma_map_page_attrs+0x90/0x1f8 Signed-off-by: David Wu Change-Id: I18e9b655524d2aba9fbde654c54c0bde9fc32aa7 --- drivers/net/ethernet/arc/emac_main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index bdd7a06e8eb5..f1263a258708 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -140,7 +140,7 @@ static void arc_emac_tx_clean(struct net_device *ndev) stats->tx_bytes += skb->len; } - dma_unmap_single(&ndev->dev, dma_unmap_addr(tx_buff, addr), + dma_unmap_single(ndev->dev.parent, dma_unmap_addr(tx_buff, addr), dma_unmap_len(tx_buff, len), DMA_TO_DEVICE); /* return the sk_buff to system */ @@ -223,9 +223,9 @@ static int arc_emac_rx(struct net_device *ndev, int budget) continue; } - addr = dma_map_single(&ndev->dev, (void *)skb->data, + addr = dma_map_single(ndev->dev.parent, (void *)skb->data, EMAC_BUFFER_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(&ndev->dev, addr)) { + if (dma_mapping_error(ndev->dev.parent, addr)) { if (net_ratelimit()) netdev_err(ndev, "cannot map dma buffer\n"); dev_kfree_skb(skb); @@ -237,7 +237,7 @@ static int arc_emac_rx(struct net_device *ndev, int budget) } /* unmap previosly mapped skb */ - dma_unmap_single(&ndev->dev, dma_unmap_addr(rx_buff, addr), + dma_unmap_single(ndev->dev.parent, dma_unmap_addr(rx_buff, addr), dma_unmap_len(rx_buff, len), DMA_FROM_DEVICE); pktlen = info & LEN_MASK; @@ -444,9 +444,9 @@ static int arc_emac_open(struct net_device *ndev) if (unlikely(!rx_buff->skb)) return -ENOMEM; - addr = dma_map_single(&ndev->dev, (void *)rx_buff->skb->data, + addr = dma_map_single(ndev->dev.parent, (void *)rx_buff->skb->data, EMAC_BUFFER_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(&ndev->dev, addr)) { + if (dma_mapping_error(ndev->dev.parent, addr)) { netdev_err(ndev, "cannot dma map\n"); dev_kfree_skb(rx_buff->skb); return -ENOMEM; @@ -554,7 +554,7 @@ static void arc_free_tx_queue(struct net_device *ndev) struct buffer_state *tx_buff = &priv->tx_buff[i]; if (tx_buff->skb) { - dma_unmap_single(&ndev->dev, + dma_unmap_single(ndev->dev.parent, dma_unmap_addr(tx_buff, addr), dma_unmap_len(tx_buff, len), DMA_TO_DEVICE); @@ -585,7 +585,7 @@ static void arc_free_rx_queue(struct net_device *ndev) struct buffer_state *rx_buff = &priv->rx_buff[i]; if (rx_buff->skb) { - dma_unmap_single(&ndev->dev, + dma_unmap_single(ndev->dev.parent, dma_unmap_addr(rx_buff, addr), dma_unmap_len(rx_buff, len), DMA_FROM_DEVICE); @@ -693,10 +693,10 @@ static netdev_tx_t arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_BUSY; } - addr = dma_map_single(&ndev->dev, (void *)skb->data, len, + addr = dma_map_single(ndev->dev.parent, (void *)skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(&ndev->dev, addr))) { + if (unlikely(dma_mapping_error(ndev->dev.parent, addr))) { stats->tx_dropped++; stats->tx_errors++; dev_kfree_skb_any(skb); From 35bcabc5025a790a2f233979e4bc59658ada17bc Mon Sep 17 00:00:00 2001 From: Lin Jianhua Date: Mon, 20 Jun 2022 09:34:17 +0800 Subject: [PATCH 202/235] ARM: dts: rk312x: dmc disable 200M freq DDR Dvfs tress test failed, disable 200M freq to test OK. so disabled temporary. Signed-off-by: Lin Jianhua Change-Id: I2f41b1f9c8bfbb33b399a49bbc6a730b87ce9b3d --- arch/arm/boot/dts/rk312x.dtsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk312x.dtsi b/arch/arm/boot/dts/rk312x.dtsi index 899a501f3dc9..528df389ba52 100644 --- a/arch/arm/boot/dts/rk312x.dtsi +++ b/arch/arm/boot/dts/rk312x.dtsi @@ -234,7 +234,7 @@ system-status-freq = < /*system status freq(KHz)*/ SYS_STATUS_NORMAL 456000 - SYS_STATUS_SUSPEND 456000 + SYS_STATUS_SUSPEND 300000 SYS_STATUS_REBOOT 456000 >; auto-min-freq = <456000>; @@ -248,6 +248,7 @@ opp-200000000 { opp-hz = /bits/ 64 <200000000>; opp-microvolt = <1025000>; + status = "disabled"; }; opp-300000000 { opp-hz = /bits/ 64 <300000000>; From f6989fdac878cd0d2188fe2ca142f771110c28c8 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Thu, 1 Dec 2022 14:32:14 +0800 Subject: [PATCH 203/235] pcie: rockchip: dw: Fix the error of repeatedly initializing dma object Change-Id: I215e38d0b78403fd688a8a9d4afd6c4a7b5460bb Signed-off-by: Jon Lin --- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index e084f37c4edc..f3511c91e865 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -847,6 +847,8 @@ static int rk_pcie_init_dma_trx(struct rk_pcie *rk_pcie) if (IS_ERR(rk_pcie->dma_obj)) { dev_err(rk_pcie->pci->dev, "failed to prepare dma object\n"); return -EINVAL; + } else if (rk_pcie->dma_obj) { + goto out; } rk_pcie->dma_obj = pcie_dw_dmatest_register(rk_pcie->pci, true); @@ -854,7 +856,7 @@ static int rk_pcie_init_dma_trx(struct rk_pcie *rk_pcie) dev_err(rk_pcie->pci->dev, "failed to prepare dmatest\n"); return -EINVAL; } - +out: /* Enable client write and read interrupt */ rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0xc000000); @@ -1192,12 +1194,6 @@ static int rk_pcie_add_ep(struct rk_pcie *rk_pcie) if (!rk_pcie_udma_enabled(rk_pcie)) return 0; - rk_pcie->dma_obj = rk_pcie_dma_obj_probe(dev); - if (IS_ERR(rk_pcie->dma_obj)) { - dev_err(dev, "failed to prepare dma object\n"); - return -EINVAL; - } - return 0; } From 061c3834059c59689f7d89573a86854e9d7689b3 Mon Sep 17 00:00:00 2001 From: William Wu Date: Sun, 4 Dec 2022 16:52:07 +0800 Subject: [PATCH 204/235] phy: rockchip-naneng-combo: config usb3 port in phy init Rockchip platforms support to force usb3 to usb2 only via the property "rockchip,dis-u3otg*-port". With this property, we can disable the usb3 port and select the clk utmi for the source clk of usb3 controller. However, during system PM suspend, the related registers may lost power, so the usb3 port configurations will lost. This patch initializes the usb3 port in the usb3 phy init, and it doesn't need to configure the usb3 mode if the property "rockchip,dis-u3otg*-port" is set. Change-Id: If82cfb9e3e34dc799db32b2b84f843fce2028df5 Signed-off-by: William Wu --- drivers/phy/rockchip/phy-rockchip-naneng-combphy.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c index f32b831b941b..08ce2eb7f513 100644 --- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c @@ -154,8 +154,19 @@ static int rockchip_combphy_pcie_init(struct rockchip_combphy_priv *priv) static int rockchip_combphy_usb3_init(struct rockchip_combphy_priv *priv) { + const struct rockchip_combphy_cfg *phy_cfg = priv->cfg; int ret = 0; + if (device_property_present(priv->dev, "rockchip,dis-u3otg0-port")) { + ret = param_write(priv->pipe_grf, &phy_cfg->grfcfg->u3otg0_port_en, + false); + return ret; + } else if (device_property_present(priv->dev, "rockchip,dis-u3otg1-port")) { + ret = param_write(priv->pipe_grf, &phy_cfg->grfcfg->u3otg1_port_en, + false); + return ret; + } + if (priv->cfg->combphy_cfg) { ret = priv->cfg->combphy_cfg(priv); if (ret) { From b160d2b44f10cec1f7e3159de5d9ff7ec5ef6fb9 Mon Sep 17 00:00:00 2001 From: Wu Liangqing Date: Mon, 5 Dec 2022 08:02:40 +0000 Subject: [PATCH 205/235] arm64: dts: rockchip: rk3588-h0: set dp-lane-mux=<0 1 2 3> Change-Id: I5ada157b4e5cd35feca0dc082f8ea355faeabe14 Signed-off-by: Wu Liangqing --- arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi index 6f2b94b1b3df..e8130f133afc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi @@ -911,7 +911,7 @@ }; &usbdp_phy1 { - rockchip,dp-lane-mux = <2 3>; + rockchip,dp-lane-mux = <0 1 2 3>; }; &usbdrd_dwc3_0 { From 697dac415b940e60b4963baff627b727c6c5c61d Mon Sep 17 00:00:00 2001 From: Guochun Huang Date: Mon, 5 Dec 2022 06:09:43 +0000 Subject: [PATCH 206/235] drm/rockchip: dsi: compatible for GKI Signed-off-by: Guochun Huang Change-Id: I64f7b209a5121ef3f4d4b7b1f27358ec56430e1d --- .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 015f983ad39e..83001753ddf0 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -1051,10 +1051,8 @@ static const struct component_ops dw_mipi_dsi_rockchip_ops = { .unbind = dw_mipi_dsi_rockchip_unbind, }; -static int dw_mipi_dsi_rockchip_host_attach(void *priv_data, - struct mipi_dsi_device *device) +static int dw_mipi_dsi_rockchip_component_add(struct dw_mipi_dsi_rockchip *dsi) { - struct dw_mipi_dsi_rockchip *dsi = priv_data; struct device *second; int ret; @@ -1081,10 +1079,8 @@ static int dw_mipi_dsi_rockchip_host_attach(void *priv_data, return 0; } -static int dw_mipi_dsi_rockchip_host_detach(void *priv_data, - struct mipi_dsi_device *device) +static int dw_mipi_dsi_rockchip_component_del(struct dw_mipi_dsi_rockchip *dsi) { - struct dw_mipi_dsi_rockchip *dsi = priv_data; struct device *second; second = dw_mipi_dsi_rockchip_find_second(dsi); @@ -1096,11 +1092,6 @@ static int dw_mipi_dsi_rockchip_host_detach(void *priv_data, return 0; } -static const struct dw_mipi_dsi_host_ops dw_mipi_dsi_rockchip_host_ops = { - .attach = dw_mipi_dsi_rockchip_host_attach, - .detach = dw_mipi_dsi_rockchip_host_detach, -}; - static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1208,7 +1199,6 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev) dsi->pdata.base = dsi->base; dsi->pdata.max_data_lanes = dsi->cdata->max_data_lanes; dsi->pdata.phy_ops = &dw_mipi_dsi_rockchip_phy_ops; - dsi->pdata.host_ops = &dw_mipi_dsi_rockchip_host_ops; dsi->pdata.priv_data = dsi; platform_set_drvdata(pdev, dsi); @@ -1221,6 +1211,12 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev) goto err_clkdisable; } + ret = dw_mipi_dsi_rockchip_component_add(dsi); + if (ret < 0) { + dw_mipi_dsi_remove(dsi->dmd); + goto err_clkdisable; + } + return 0; err_clkdisable: @@ -1232,9 +1228,8 @@ static int dw_mipi_dsi_rockchip_remove(struct platform_device *pdev) { struct dw_mipi_dsi_rockchip *dsi = platform_get_drvdata(pdev); - if (dsi->devcnt == 0) - component_del(dsi->dev, &dw_mipi_dsi_rockchip_ops); + dw_mipi_dsi_rockchip_component_del(dsi); dw_mipi_dsi_remove(dsi->dmd); return 0; From 9461447888dfd13cebbca605e6df311391a13d9b Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Mon, 5 Dec 2022 20:57:32 +0800 Subject: [PATCH 207/235] media: rockchip: vicap fixs toisp ctrl register updata fail Signed-off-by: Zefa Chen Change-Id: I1d96ff04ae1b9372476f7d03ad1f015b67862c7d --- drivers/media/platform/rockchip/cif/subdev-itf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 5c838395570a..5b5a065db6b7 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -450,7 +450,7 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user) if (user == 0) { if (priv->toisp_inf.link_mode == TOISP_UNITE) width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; - rkcif_write_register_or(cif_dev, CIF_REG_TOISP0_CTRL, ctrl_val); + rkcif_write_register(cif_dev, CIF_REG_TOISP0_CTRL, ctrl_val); if (width && height) { rkcif_write_register(cif_dev, CIF_REG_TOISP0_CROP, offset_x | (offset_y << 16)); @@ -464,7 +464,7 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user) offset_x = priv->cap_info.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL; width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; } - rkcif_write_register_or(cif_dev, CIF_REG_TOISP1_CTRL, ctrl_val); + rkcif_write_register(cif_dev, CIF_REG_TOISP1_CTRL, ctrl_val); if (width && height) { rkcif_write_register(cif_dev, CIF_REG_TOISP1_CROP, offset_x | (offset_y << 16)); From 56353bf1182b28b22077fbb4b12acb7252a88d07 Mon Sep 17 00:00:00 2001 From: Yandong Lin Date: Tue, 29 Nov 2022 21:49:41 +0800 Subject: [PATCH 208/235] video: rockchip: mpp: fix jpege dma coherence issue Allocate multiple jpeg enc cores to encode the same frame at the same time, and than there is a dma cache coherence issue when the user space copies bitstream data to another buffer. So, need to invalid cache after every core encoding done. Signed-off-by: Yandong Lin Change-Id: I0868398f09787cdbd2be6f6a2cd3c1adbe61e4b5 --- drivers/video/rockchip/mpp/mpp_vepu2.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_vepu2.c b/drivers/video/rockchip/mpp/mpp_vepu2.c index f767c533515d..f57d4dff6d08 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu2.c +++ b/drivers/video/rockchip/mpp/mpp_vepu2.c @@ -202,12 +202,13 @@ static int vepu_process_reg_fd(struct mpp_session *session, if (fmt == VEPU2_FMT_JPEGE) { task->offset_bs = mpp_query_reg_offset_info(&task->off_inf, VEPU2_REG_OUT_INDEX); - if (task->offset_bs > 0) - task->dmabuf_bs = dma_buf_get(fd_bs); + task->dmabuf_bs = dma_buf_get(fd_bs); - if (IS_ERR_OR_NULL(task->dmabuf_bs)) + if (IS_ERR_OR_NULL(task->dmabuf_bs)) { task->dmabuf_bs = NULL; - else + return 0; + } + if (task->offset_bs > 0) dma_buf_end_cpu_access_partial(task->dmabuf_bs, DMA_TO_DEVICE, 0, task->offset_bs); } From 8a3d4599c64e578712b4a1d8a953d779868ff9f7 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Mon, 31 Oct 2022 15:23:28 +0800 Subject: [PATCH 209/235] media: rockchip: isp: fix dmatx loss first buf Change-Id: I7355529f6ff4f39cba7206b3201d434d110bd4a6 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/capture.c | 2 +- drivers/media/platform/rockchip/isp/rkisp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/capture.c b/drivers/media/platform/rockchip/isp/capture.c index 7bb7a8f6cd67..f186229c807f 100644 --- a/drivers/media/platform/rockchip/isp/capture.c +++ b/drivers/media/platform/rockchip/isp/capture.c @@ -366,7 +366,7 @@ void rkisp_config_dmatx_valid_buf(struct rkisp_device *dev) continue; for (j = RKISP_STREAM_DMATX0; j < RKISP_MAX_STREAM; j++) { stream = &isp->cap_dev.stream[j]; - if (!stream->linked || stream->u.dmatx.is_config) + if (!stream->linked || stream->curr_buf || stream->next_buf) continue; mi_set_y_addr(stream, hw->dummy_buf.dma_addr); } diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index f3b0948237b1..6afa85ce16b8 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -2737,7 +2737,7 @@ static void rkisp_global_update_mi(struct rkisp_device *dev) if (stream->id == RKISP_STREAM_VIR || stream->id == RKISP_STREAM_LUMA) continue; - if (stream->streaming) + if (stream->streaming && !stream->next_buf) stream->ops->frame_end(stream); } } From 1b493c541226695901245b4dbc5cb75fad8e200c Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Wed, 30 Nov 2022 09:44:13 +0800 Subject: [PATCH 210/235] Revert "phy: phy-rockchip-snps-pcie3: Update calibration controls for rk356x" This reverts commit 8e908294a52a1328e75c12408f27d1b746877066. Signed-off-by: Kever Yang Change-Id: I063f98312f5fa94309fc72c983516f222d0addf7 --- drivers/phy/rockchip/phy-rockchip-snps-pcie3.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c index bb5fed0c03ca..0ea57ee16bad 100644 --- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c +++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c @@ -96,12 +96,6 @@ static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv) reset_control_deassert(priv->p30phy); - udelay(10); - /* Updata RX VCO calibration controls */ - writel(0x2800, priv->mmio + (0x104a << 2)); - writel(0x2800, priv->mmio + (0x114a << 2)); - udelay(10); - ret = regmap_read_poll_timeout(priv->phy_grf, GRF_PCIE30PHY_STATUS0, reg, SRAM_INIT_DONE(reg), From cbf3eb9b7f89d5d88cf9ea3c44ce66ac084ce607 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Fri, 13 May 2022 09:54:12 +0800 Subject: [PATCH 211/235] phy: rockchip-snps-pcie3: update fw when init This fw fix some RX issue: 1. connect detect error; 2. transfer error in ssd huge data write(more than 10GB). Signed-off-by: Kever Yang Change-Id: If9b8d7fbe4414ae4d28ff6bbd4415d88b582113d --- .../phy/rockchip/phy-rockchip-snps-pcie3.c | 28 +- .../phy/rockchip/phy-rockchip-snps-pcie3.fw | 8192 +++++++++++++++++ 2 files changed, 8218 insertions(+), 2 deletions(-) create mode 100644 drivers/phy/rockchip/phy-rockchip-snps-pcie3.fw diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c index 0ea57ee16bad..aff349b75c9f 100644 --- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c +++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c @@ -21,6 +21,7 @@ /* Register for RK3568 */ #define GRF_PCIE30PHY_CON1 0x4 +#define GRF_PCIE30PHY_CON4 0x10 #define GRF_PCIE30PHY_CON6 0x18 #define GRF_PCIE30PHY_CON9 0x24 #define GRF_PCIE30PHY_STATUS0 0x80 @@ -78,8 +79,13 @@ static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int subm return 0; } +static const u16 phy_fw[] = { + #include "phy-rockchip-snps-pcie3.fw" +}; + static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv) { + int i; int ret = 0; u32 reg; @@ -93,16 +99,34 @@ static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv) regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1, (0x1 << 15) | (0x1 << 31)); } + regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON4, + (0x0 << 14) | (0x1 << (14 + 16))); //sdram_ld_done + regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON4, + (0x0 << 13) | (0x1 << (13 + 16))); //sdram_bypass reset_control_deassert(priv->p30phy); - ret = regmap_read_poll_timeout(priv->phy_grf, GRF_PCIE30PHY_STATUS0, reg, SRAM_INIT_DONE(reg), 0, 500); - if (ret) + if (ret) { pr_err("%s: lock failed 0x%x, check input refclk and power supply\n", __func__, reg); + goto out; + } + + regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, + (0x3 << 8) | (0x3 << (8 + 16))); //map to access sram + for (i = 0; i < ARRAY_SIZE(phy_fw); i++) + writel(phy_fw[i], priv->mmio + (i<<2)); + pr_info("snps pcie3phy FW update! size %ld\n", ARRAY_SIZE(phy_fw)); + + regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, + (0x0 << 8) | (0x3 << (8 + 16))); + regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON4, + (0x1 << 14) | (0x1 << (14 + 16))); //sdram_ld_done + +out: return ret; } diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.fw b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.fw new file mode 100644 index 000000000000..301c42837ad9 --- /dev/null +++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.fw @@ -0,0 +1,8192 @@ +0x081D, +0xFFFF, +0x33AF, +0x33AE, +0x0C4F, +0xD10D, +0x0D0F, +0xD306, +0x0C8F, +0xDB06, +0x33AF, +0xD38D, +0x01AC, +0x2000, +0x0C1E, +0x014A, +0x2800, +0x1B80, +0xA0B2, +0x0806, +0x0016, +0x8CC7, +0xD1AE, +0x0C2E, +0x1B75, +0x33AE, +0xA01C, +0x8026, +0x0C2F, +0xD375, +0x33AF, +0x1B81, +0xA022, +0x8026, +0x0D8F, +0x03A6, +0x0003, +0x33AF, +0x0C6F, +0xDBA6, +0x33AF, +0x0C4F, +0xD10D, +0x33AF, +0x0D8F, +0xDBA6, +0x33AF, +0x1B81, +0xA032, +0x8048, +0xDB87, +0x038D, +0x0020, +0xD310, +0x080F, +0x0020, +0xD106, +0x33AF, +0xDB8B, +0xDB8C, +0x1B0F, +0xA03A, +0x0807, +0x0044, +0x33FE, +0x0C01, +0x0C3F, +0x80BA, +0x0C4F, +0xD30E, +0x33AF, +0xD38D, +0x1B82, +0xA04B, +0x8061, +0xDB88, +0x080F, +0x0020, +0xD106, +0x33AF, +0x1B8E, +0xA053, +0x8061, +0x1BA7, +0xA056, +0x8053, +0x0807, +0x005C, +0x33FE, +0x0C01, +0x0C3F, +0x80BA, +0xDB8F, +0x0C2E, +0x1B09, +0xA05D, +0x33AE, +0x1B86, +0xA07B, +0x1B85, +0xA0A7, +0x080E, +0x0200, +0x1BF6, +0x33AE, +0xA074, +0x1B5E, +0xA06D, +0x8077, +0x0C4E, +0x1BF6, +0x33AE, +0xA077, +0x0806, +0x0000, +0x89A4, +0x0C4F, +0xDBF6, +0x33AF, +0x1B2F, +0xA07A, +0x89DF, +0x8000, +0x080F, +0x0020, +0xD106, +0x33AF, +0x0807, +0x0085, +0x33FE, +0x0C01, +0x0C3F, +0x80BA, +0xD35E, +0x038D, +0x0020, +0xD10D, +0x010D, +0x0002, +0x0C8F, +0xDB06, +0x33AF, +0x0D0F, +0xDB06, +0x33AF, +0x0C2E, +0x1919, +0xA095, +0x8092, +0x33AE, +0x0C8F, +0xD306, +0x33AF, +0x0C2E, +0x1919, +0xA09D, +0x33AE, +0x0D0F, +0xD306, +0x33AF, +0xD10D, +0xD38D, +0xDB10, +0xDB8C, +0xDB8B, +0xD310, +0x8000, +0xDB8B, +0xD35E, +0x0806, +0x0000, +0x1B28, +0xA995, +0x0806, +0x0000, +0x038D, +0x0020, +0x86F1, +0xD380, +0x1B59, +0xA19E, +0x80C8, +0x0C4F, +0xD3F6, +0x33AF, +0x080E, +0x01FC, +0x1BF6, +0x33AE, +0xA0C3, +0x080F, +0x01FC, +0x03F6, +0x0032, +0x33AF, +0x0806, +0x0157, +0x1B27, +0xA641, +0x822B, +0x0367, +0x003F, +0x0368, +0x0C09, +0x0369, +0x7928, +0xD36A, +0x036B, +0x007F, +0x036C, +0x0C13, +0x036D, +0x7803, +0xD36E, +0x037C, +0x003F, +0x037D, +0x0C01, +0x037E, +0x7818, +0xD37F, +0x03E0, +0x007F, +0x03E1, +0x0C2F, +0x03E2, +0x7828, +0x03E3, +0x36DC, +0x03E4, +0x007F, +0x03E5, +0x0C09, +0x03E6, +0x7818, +0x03E7, +0x124A, +0x080E, +0xFF00, +0x191E, +0x33AE, +0x080F, +0x00FF, +0x291D, +0x0CCF, +0xD11D, +0x080F, +0x0100, +0xD91D, +0x33AF, +0x0C2F, +0xD375, +0x33AF, +0x0349, +0x0017, +0x0353, +0x0017, +0x1B4A, +0x29B4, +0xD9B8, +0x0229, +0x1060, +0x022A, +0x0E24, +0x080E, +0x4000, +0x1B09, +0xA108, +0x0C2E, +0x1B02, +0xA10C, +0x33AE, +0xD317, +0x1B29, +0xA115, +0x705E, +0x8115, +0x1B2D, +0xA118, +0x811A, +0x014B, +0x2DAB, +0x1B2E, +0xA11D, +0x811F, +0x014C, +0x004B, +0x1B2A, +0xA123, +0x0125, +0x065A, +0x1B2B, +0xA126, +0x8128, +0x0127, +0x0D07, +0x0063, +0x7F00, +0x0073, +0x7F00, +0x1A28, +0xA145, +0xDA28, +0x1B29, +0xA137, +0x0060, +0x0008, +0x0070, +0x0008, +0xDBA8, +0x8140, +0x0C2F, +0xD881, +0x080F, +0xFFFF, +0xDBA8, +0x0061, +0x0018, +0x0071, +0x0018, +0x0301, +0x0F05, +0x03A0, +0x0007, +0x8147, +0x0301, +0x0F05, +0x1B2C, +0xA14C, +0x0144, +0x0100, +0x8152, +0x080F, +0x0200, +0xD944, +0x33AF, +0x0145, +0x6DB4, +0x0306, +0x0006, +0x1B0F, +0xA154, +0x80B6, +0x0305, +0x000C, +0x0306, +0x0007, +0x0317, +0x0003, +0x0306, +0x0006, +0x1B0F, +0xA15F, +0x0306, +0x0004, +0xDB87, +0x1A28, +0x5C6D, +0xA168, +0x816E, +0x13A3, +0x5CEC, +0xA168, +0x0228, +0x0003, +0x816E, +0x0C2E, +0x1A11, +0x33AE, +0xA177, +0x1867, +0x080C, +0x0100, +0x518D, +0x2B54, +0x0C4E, +0x1A11, +0x33AE, +0xA180, +0x1877, +0x080C, +0x0100, +0x518D, +0x2B55, +0x1867, +0x2868, +0x1877, +0x2878, +0x1886, +0x2B56, +0x1888, +0x2B58, +0x1887, +0x2B57, +0x0060, +0x0018, +0x0070, +0x0018, +0xDA12, +0xD3A0, +0xD3A8, +0xDB59, +0x7005, +0x0C4F, +0xD081, +0x080F, +0xFFFF, +0x0C8F, +0xD303, +0x33AF, +0x0C4F, +0xD30E, +0x33AF, +0x8000, +0x1B54, +0x2868, +0x1B55, +0x2878, +0x705E, +0x1B2D, +0xA1A6, +0x81A8, +0x014B, +0x2DAB, +0x1B2E, +0xA1AB, +0x81AD, +0x014C, +0x004B, +0x1B29, +0xA1B0, +0x81B8, +0x0C2F, +0xD881, +0x080F, +0xFFFF, +0x0061, +0x0018, +0x0071, +0x0018, +0x1B56, +0x2883, +0x1B58, +0x2885, +0x1B57, +0x2884, +0x0301, +0x0F05, +0xD9AE, +0x01AD, +0x0080, +0xD1AF, +0xD9B6, +0x1B40, +0x29AD, +0xD9AF, +0xD9B6, +0x1B41, +0x29AD, +0x01AF, +0x0002, +0xD9B6, +0x1B42, +0x29AD, +0x01AF, +0x0003, +0xD9B6, +0x1B45, +0x29AD, +0x01AF, +0x0014, +0xD9B6, +0x1B46, +0x29AD, +0x01AF, +0x0015, +0xD9B6, +0x01A8, +0x0140, +0x1B4B, +0x2973, +0x1B4C, +0x2974, +0x1B51, +0x2979, +0x1B4D, +0x2975, +0x1B4E, +0x2976, +0x1B52, +0x297A, +0x1BF2, +0x5C6D, +0xA1F1, +0x0C4F, +0xD9BA, +0x33AF, +0x0C8E, +0x1B24, +0x33AE, +0xA1F6, +0x81F9, +0x0C2F, +0xD9BA, +0x33AF, +0x1B4F, +0x080F, +0xFF00, +0x297F, +0x080F, +0xFFFF, +0x1B50, +0x080F, +0x00FF, +0x297F, +0x080F, +0xFFFF, +0x1B4A, +0x29B4, +0xD9B8, +0xD1AE, +0xD1A8, +0x018E, +0x0019, +0x0305, +0x000C, +0xD306, +0x1B0F, +0xA20F, +0x1B2C, +0xA214, +0x821A, +0x080F, +0x0200, +0xD944, +0x33AF, +0x0145, +0x6DB4, +0x1B04, +0xA21A, +0x1B2A, +0xA220, +0x0125, +0x065A, +0x1B2B, +0xA223, +0x8225, +0x0127, +0x0D07, +0xDA12, +0x0229, +0x1060, +0x022A, +0xE24 , +0x8193, +0x01A8, +0x0140, +0x0100, +0x0004, +0x018E, +0x0019, +0xD9AE, +0xD9B6, +0x01B0, +0x0B37, +0x01B1, +0x00FA, +0xD9B7, +0x0180, +0x03FF, +0xD981, +0xD182, +0xD183, +0x0184, +0x4000, +0x0185, +0x2408, +0x1B31, +0xA254, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0xA060, +0xD9AF, +0x0340, +0x0080, +0x0800, +0x0340, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x0254, +0x0C03, +0x864B, +0x1B31, +0xA268, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0xA080, +0x01AF, +0x0002, +0x0341, +0x0080, +0x0800, +0x0341, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x0268, +0x0C03, +0x864B, +0x01B1, +0x0062, +0xD9B7, +0x1B31, +0xA27E, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0xA080, +0xD9AF, +0x0340, +0x0080, +0x0800, +0x0340, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x027E, +0x0C03, +0x864B, +0x1B31, +0xA292, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0xA0C0, +0x01AF, +0x0003, +0x0342, +0x0080, +0x0800, +0x0342, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x0292, +0x0C03, +0x864B, +0x080E, +0xF800, +0x1B0C, +0x31A1, +0x080E, +0x07FF, +0x1B0C, +0x31A2, +0xD11D, +0x0CEE, +0x1B0D, +0x31A3, +0x33AE, +0x304D, +0x080F, +0x07FF, +0x29B0, +0x33AF, +0x302D, +0x080F, +0x00F8, +0x29B1, +0x33AF, +0x306D, +0x0CEF, +0x29B1, +0x33AF, +0xD9B7, +0x0C2E, +0x1BF6, +0x33AE, +0xA2CD, +0x0180, +0x03FF, +0xD981, +0xD182, +0xD183, +0x0184, +0x4000, +0x0185, +0x2408, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0xB080, +0x01AF, +0x0002, +0x03F7, +0x0080, +0x0800, +0x03F7, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x02CD, +0x0C03, +0x864B, +0x0C8E, +0x1BF4, +0x33AE, +0xA2EC, +0x0180, +0x03FF, +0xD981, +0xD182, +0xD183, +0x0184, +0x4000, +0x0185, +0x2408, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0xB0C0, +0x01AF, +0x0003, +0x03EC, +0x0080, +0x0800, +0x03EC, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x02EC, +0x0C03, +0x864B, +0x01B3, +0x0177, +0xD3F2, +0x0C2E, +0x1BF4, +0x33AE, +0xA313, +0x0180, +0x01FF, +0x0181, +0xAAAA, +0x0182, +0x2800, +0xD183, +0x0184, +0x6C00, +0x0185, +0x2408, +0x0807, +0x0301, +0x8DC7, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0016, +0x0179, +0x0080, +0x0800, +0x0179, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x0313, +0x0C23, +0x864B, +0x0800, +0x0179, +0x3801, +0x0802, +0x003F, +0x0803, +0x00C0, +0x5461, +0xB31F, +0x5422, +0xB31F, +0x8329, +0x0C4E, +0x19BA, +0x33AE, +0xA329, +0x1B33, +0xA329, +0x0C4F, +0xD9BA, +0x33AF, +0x82EF, +0x0C2E, +0x1BF4, +0x33AE, +0xA34D, +0x0180, +0x01FF, +0x0181, +0x5555, +0x0182, +0x1400, +0xD183, +0x0184, +0x6C00, +0x0185, +0x2408, +0x0807, +0x033B, +0x8E5B, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0018, +0x017A, +0x0080, +0x0800, +0x017A, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x034D, +0x0C23, +0x864B, +0x0800, +0x017A, +0x3801, +0x0802, +0x003F, +0x0803, +0x00C0, +0x5461, +0xB359, +0x5422, +0xB359, +0x8363, +0x0C4E, +0x19BA, +0x33AE, +0xA363, +0x1B33, +0xA363, +0x0C4F, +0xD9BA, +0x33AF, +0x82EF, +0x080E, +0x0400, +0x1B6F, +0x33AE, +0xA38D, +0x0C4E, +0x19BA, +0x33AE, +0xA38B, +0x0800, +0x009B, +0x1979, +0x31A1, +0x197A, +0x31A2, +0x5420, +0xB375, +0x8379, +0x5440, +0xB379, +0xDBF2, +0x838D, +0x5420, +0xB381, +0x5440, +0xB37E, +0x8381, +0x03F2, +0x0002, +0x838D, +0x5420, +0xB38D, +0x5440, +0xB38D, +0x03F2, +0x0003, +0x0C4F, +0xD9BA, +0x33AF, +0x82EF, +0x03F2, +0x0003, +0x1BF2, +0x5C6D, +0xA395, +0x03ED, +0x0025, +0x03EE, +0x0025, +0x8399, +0x03ED, +0x0037, +0x03EE, +0x0037, +0x1B32, +0xA3BB, +0x0180, +0x01FF, +0x0181, +0xAAAA, +0x0182, +0x2800, +0xD183, +0x0184, +0x7000, +0x0185, +0x2408, +0x0807, +0x03A9, +0x8D7D, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0010, +0x0173, +0x0080, +0x0800, +0x0173, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x03BB, +0x0C23, +0x864B, +0x0800, +0x0173, +0x3801, +0x0802, +0x003F, +0x0803, +0x00C0, +0x5423, +0xB3C5, +0x83C7, +0x5441, +0xB3D1, +0x0C4E, +0x19BA, +0x33AE, +0xA3D1, +0x1B33, +0xA3D1, +0x0C4F, +0xD9BA, +0x33AF, +0x82EF, +0x1B32, +0xA3F3, +0x0180, +0x01FF, +0x0181, +0xAAAA, +0x0182, +0x2800, +0xD183, +0x0184, +0x7000, +0x0185, +0x2408, +0x0807, +0x03E1, +0x8DA1, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0011, +0x0174, +0x0080, +0x0800, +0x0174, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x03F3, +0x0C23, +0x864B, +0x0800, +0x0174, +0x3801, +0x0802, +0x003F, +0x0803, +0x00C0, +0x5423, +0xB3FD, +0x83FF, +0x5441, +0xB409, +0x0C4E, +0x19BA, +0x33AE, +0xA409, +0x1B33, +0xA409, +0x0C4F, +0xD9BA, +0x33AF, +0x82EF, +0x1B32, +0xA42B, +0x0180, +0x01FF, +0x0181, +0x5555, +0x0182, +0x1400, +0xD183, +0x0184, +0x7000, +0x0185, +0x2408, +0x0807, +0x0419, +0x8E11, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0012, +0x0175, +0x0080, +0x0800, +0x0175, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x042B, +0x0C23, +0x864B, +0x0800, +0x0175, +0x3801, +0x0802, +0x003F, +0x0803, +0x00C0, +0x5423, +0xB435, +0x8437, +0x5441, +0xB441, +0x0C4E, +0x19BA, +0x33AE, +0xA441, +0x1B33, +0xA441, +0x0C4F, +0xD9BA, +0x33AF, +0x82EF, +0x1B32, +0xA463, +0x0180, +0x01FF, +0x0181, +0x5555, +0x0182, +0x1400, +0xD183, +0x0184, +0x7000, +0x0185, +0x2408, +0x0807, +0x0451, +0x8E35, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0013, +0x0176, +0x0080, +0x0800, +0x0176, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x0463, +0x0C23, +0x864B, +0x0800, +0x0176, +0x3801, +0x0802, +0x003F, +0x0803, +0x00C0, +0x5423, +0xB46D, +0x846F, +0x5441, +0xB479, +0x0C4E, +0x19BA, +0x33AE, +0xA479, +0x1B33, +0xA479, +0x0C4F, +0xD9BA, +0x33AF, +0x82EF, +0x0C8F, +0xD324, +0x33AF, +0x1B3D, +0xA49E, +0x0180, +0x01FF, +0x0181, +0xAAAA, +0x0182, +0x2800, +0xD183, +0x0184, +0x6800, +0x0185, +0x2408, +0x0807, +0x048C, +0x8DEC, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0014, +0x0345, +0x0080, +0x0800, +0x0345, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x049E, +0x0C23, +0x864B, +0x1B3D, +0xA4C0, +0x0180, +0x01FF, +0x0181, +0x5555, +0x0182, +0x1400, +0xD183, +0x0184, +0x6800, +0x0185, +0x2408, +0x0807, +0x04AE, +0x8E80, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0015, +0x0346, +0x0080, +0x0800, +0x0346, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x04C0, +0x0C23, +0x864B, +0x1B3E, +0xA4DD, +0x0800, +0x00FB, +0x1B45, +0x31A1, +0x1B46, +0x31A2, +0x5401, +0xB4D2, +0x5402, +0xB4D2, +0x0C80, +0x5420, +0xB4D2, +0x5440, +0xB4D2, +0x84DD, +0x0C2E, +0x19BA, +0x33AE, +0xA4DD, +0x0C8F, +0xDB24, +0x33AF, +0x0C2F, +0xD9BA, +0x33AF, +0x847C, +0x0C4E, +0x1BF4, +0x33AE, +0xA508, +0x0180, +0x01FF, +0x0181, +0xAAAA, +0x0182, +0x2800, +0xD183, +0x0184, +0x7000, +0x0185, +0x2408, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0010, +0x0807, +0x04F6, +0x8EA5, +0x01A8, +0x0100, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0010, +0x034F, +0x0080, +0x0800, +0x034F, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x0508, +0x0C23, +0x864B, +0x1B4F, +0x080F, +0xFF00, +0x297F, +0x080F, +0xFFFF, +0x0C4E, +0x1BF4, +0x33AE, +0xA539, +0x0180, +0x01FF, +0x0181, +0x5555, +0x0182, +0x1400, +0xD183, +0x0184, +0x7000, +0x0185, +0x2408, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0012, +0x0807, +0x0527, +0x8EC9, +0x01A8, +0x0100, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0012, +0x0350, +0x0080, +0x0800, +0x0350, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x0539, +0x0C23, +0x864B, +0x1B50, +0x080F, +0x00FF, +0x297F, +0x080F, +0xFFFF, +0x0C2E, +0x1B6F, +0x33AE, +0xA5CF, +0x0CEE, +0x1B0C, +0x33AE, +0x0800, +0x0080, +0x51A0, +0x080F, +0x07FF, +0x29B0, +0x33AF, +0xD9B7, +0x0800, +0x0080, +0x1BED, +0x51A0, +0x2969, +0x31A0, +0x01AF, +0x0016, +0x21AD, +0xD9B6, +0x0180, +0x03FF, +0xD981, +0xD182, +0xD183, +0x0184, +0x4000, +0x0185, +0x2408, +0x01A8, +0x0100, +0xD1B5, +0x01AC, +0x9346, +0x01AF, +0x001B, +0x03FC, +0x0080, +0x0800, +0x03FC, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x0573, +0x0C23, +0x864B, +0x01A8, +0x0100, +0xD1B5, +0x01AC, +0x90DA, +0x01AF, +0x0003, +0x03FD, +0x0080, +0x0800, +0x03FD, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x0585, +0x0C03, +0x864B, +0x0180, +0x01FF, +0x0181, +0xAAAA, +0x0182, +0x2800, +0xD183, +0x0184, +0x6C00, +0x0185, +0x2408, +0x0807, +0x0593, +0x8DC7, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0016, +0x03ED, +0x0080, +0x0800, +0x03ED, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x05A5, +0x0C23, +0x864B, +0x0180, +0x01FF, +0x0181, +0x5555, +0x0182, +0x1400, +0xD183, +0x0184, +0x6C00, +0x0185, +0x2408, +0x0807, +0x05B3, +0x8E5B, +0x01A8, +0x0140, +0xD1B5, +0x01AC, +0x3000, +0x01AF, +0x0018, +0x03EE, +0x0080, +0x0800, +0x03EE, +0x01AD, +0x0080, +0xD9B6, +0x0807, +0x05C5, +0x0C23, +0x864B, +0x1BEE, +0x31A0, +0x1BED, +0x31A1, +0x197A, +0x55A0, +0x2BEE, +0x1979, +0x55A1, +0x2BED, +0x080E, +0x07F8, +0x1B0C, +0x33AE, +0x080F, +0x07F8, +0x29B0, +0x33AF, +0xD9B7, +0x080F, +0x0800, +0xD1B0, +0x33AF, +0xD9B7, +0x01A8, +0x0140, +0x1973, +0x29AD, +0x01AF, +0x0010, +0xD9B6, +0x1974, +0x29AD, +0x01AF, +0x0011, +0xD9B6, +0x1979, +0x29AD, +0x01AF, +0x0016, +0xD9B6, +0x1B45, +0x29AD, +0x01AF, +0x0014, +0xD9B6, +0x1975, +0x29AD, +0x01AF, +0x0012, +0xD9B6, +0x1976, +0x29AD, +0x01AF, +0x0013, +0xD9B6, +0x197A, +0x29AD, +0x01AF, +0x0018, +0xD9B6, +0x1B46, +0x29AD, +0x01AF, +0x0015, +0xD9B6, +0x1973, +0x2B4B, +0x1974, +0x2B4C, +0x1979, +0x2B51, +0x080F, +0xFF00, +0x2BEF, +0x080F, +0x00FF, +0x2BEF, +0x33AF, +0x1975, +0x2B4D, +0x1976, +0x2B4E, +0x197A, +0x2B52, +0x080F, +0xFF00, +0x2BF0, +0x080F, +0x00FF, +0x2BF0, +0x33AF, +0x01A8, +0x0100, +0x1B4F, +0x29AD, +0x01AF, +0x0010, +0xD9B6, +0x1B50, +0x29AD, +0x01AF, +0x0012, +0xD9B6, +0x1B41, +0x29AD, +0x01AF, +0x0002, +0xD9B6, +0x1B42, +0x29AD, +0x01AF, +0x0003, +0xD9B6, +0x33FE, +0x0C3F, +0x804B, +0xD1AC, +0x01B3, +0x0077, +0xD100, +0xD1A8, +0xD1AE, +0x8646, +0x33FE, +0x0C3F, +0x804D, +0xD1A8, +0xD9B6, +0x080F, +0x0400, +0xD185, +0x33AF, +0x9006, +0x0804, +0x0040, +0x5C03, +0xA650, +0x8653, +0x0CE1, +0x7080, +0x8655, +0x0CC1, +0x7080, +0x6660, +0x0C42, +0x5443, +0xB65B, +0x6260, +0x8678, +0xA669, +0x080E, +0x7FFF, +0x198A, +0x33AE, +0x31A2, +0x4022, +0x080E, +0x7FFF, +0x1986, +0x33AE, +0x426D, +0x55A2, +0x8678, +0x080E, +0x7FFF, +0x1986, +0x33AE, +0x31A2, +0x4022, +0x426D, +0x55A2, +0x31A2, +0x080E, +0x7FFF, +0x198A, +0x33AE, +0x402D, +0x544D, +0xB680, +0x0C02, +0x55A2, +0x31A5, +0x380D, +0x3802, +0x548D, +0x8686, +0x31A5, +0x3802, +0xA684, +0x8691, +0x380D, +0x508D, +0x35A0, +0x29AD, +0xD9B6, +0x5C03, +0xA68E, +0x0C37, +0x700F, +0x8693, +0x0C17, +0x700F, +0x8693, +0x31A5, +0x3802, +0x4224, +0x5C21, +0xA655, +0x0C81, +0x6660, +0x0C44, +0x5483, +0xB69D, +0x6260, +0x86BA, +0xA6AB, +0x080E, +0x7FFF, +0x198A, +0x33AE, +0x31A4, +0x4024, +0x080E, +0x7FFF, +0x1986, +0x33AE, +0x426D, +0x55A4, +0x86BA, +0x080E, +0x7FFF, +0x1986, +0x33AE, +0x31A4, +0x4024, +0x426D, +0x55A4, +0x31A4, +0x080E, +0x7FFF, +0x198A, +0x33AE, +0x402D, +0x548D, +0x31A4, +0xB6CD, +0x0C04, +0x55A4, +0x31A4, +0x54A4, +0xB6C3, +0x3085, +0x3802, +0x32ED, +0xA6C8, +0x380D, +0x5C2D, +0x86CA, +0x380D, +0x5C4D, +0x31A4, +0xB6DB, +0x86EF, +0x54A4, +0xB6D1, +0x3085, +0x3802, +0x32ED, +0xA6D6, +0x380D, +0x582D, +0x86D8, +0x380D, +0x584D, +0x31A4, +0x430D, +0xA6EF, +0x5C21, +0xA6E4, +0x3804, +0x5482, +0xA6E1, +0x86EF, +0x3440, +0x304D, +0x86E6, +0x3480, +0x308D, +0x29AD, +0xD9B6, +0x5C03, +0xA6EC, +0x700F, +0x86ED, +0x700F, +0x5C01, +0xA697, +0x33DF, +0x9007, +0x1B36, +0xA709, +0xD35E, +0x038D, +0x0030, +0xD10D, +0x010D, +0x0002, +0x0306, +0x000C, +0x0C2E, +0x1919, +0x33AE, +0xA700, +0x86FB, +0x0306, +0x0008, +0x0C2E, +0x1919, +0x33AE, +0xA702, +0x0305, +0x000C, +0xD10D, +0x038D, +0x0030, +0x1B38, +0xA711, +0x080F, +0x0080, +0xD37B, +0x33AF, +0xD38D, +0x1B38, +0xA716, +0x0C6C, +0x871E, +0x1B34, +0xA71D, +0x080E, +0x01E0, +0x131C, +0x33AE, +0x871E, +0x0C0C, +0x33FE, +0x0C3F, +0x8946, +0x1B49, +0x2B47, +0x038D, +0x0030, +0xD1A8, +0xD161, +0x0162, +0x0042, +0x0163, +0x0060, +0xD164, +0xD165, +0x0167, +0x21A2, +0x1BEE, +0x2BCD, +0x1BED, +0x2BCC, +0x13CD, +0x1B52, +0x518D, +0x31AC, +0x430D, +0xA73B, +0x318D, +0x873D, +0x080D, +0x00FF, +0x31A1, +0x080F, +0xFF00, +0x2969, +0x33AF, +0x13CC, +0x1B51, +0x518D, +0x31AC, +0x430D, +0xA74A, +0x318D, +0x874C, +0x080D, +0x00FF, +0x31A1, +0x080F, +0x00FF, +0x2969, +0x33AF, +0x0181, +0xFFFF, +0x0182, +0x3C02, +0x0183, +0x0800, +0x0184, +0x7060, +0x0185, +0x2402, +0x1B67, +0x2980, +0x1B68, +0x2960, +0x1B69, +0x2966, +0x1B6A, +0x2968, +0x1B36, +0xA76B, +0x0807, +0x076A, +0x33FE, +0x0C1F, +0x89C5, +0x6C00, +0xD162, +0x0163, +0x001F, +0x0182, +0x3C23, +0x0183, +0x0087, +0x0184, +0x7068, +0x0185, +0x247C, +0x1B6B, +0x2980, +0x1B6C, +0x2960, +0x1B6D, +0x2966, +0x1B6E, +0x2968, +0x1B36, +0xA781, +0x6C00, +0x0182, +0x3C02, +0x0183, +0x0800, +0x0184, +0x7060, +0x0185, +0x2402, +0x0162, +0x0042, +0x0163, +0x0060, +0x0167, +0x39C0, +0x1B7C, +0x2980, +0x1B7D, +0x2960, +0x1B7E, +0x2966, +0x1B7F, +0x2968, +0x1B36, +0xA7E0, +0x0807, +0x079E, +0x33FE, +0x0C1F, +0x89C5, +0x6C00, +0x080E, +0x4000, +0x1B6F, +0x33AE, +0xA7E0, +0x080E, +0x03C0, +0x196C, +0x33AE, +0x5CED, +0xB7E0, +0x0180, +0x01FF, +0x080F, +0x03E0, +0x0182, +0x0002, +0x33AF, +0x6620, +0xB7B4, +0x87E0, +0xA7B6, +0x87E0, +0x080F, +0x3FFF, +0xD160, +0x33AF, +0x080F, +0x0038, +0x0166, +0x0005, +0x33AF, +0x080E, +0x03C0, +0x196C, +0x33AE, +0x402D, +0x31A0, +0x080E, +0x003F, +0x196C, +0x33AE, +0xA7CC, +0x5820, +0x87CD, +0x5840, +0x31A0, +0x080F, +0x7C00, +0x2167, +0x080F, +0x03E0, +0x2167, +0x33AF, +0x1169, +0x3181, +0x080F, +0x1000, +0xD166, +0x33AF, +0x0169, +0xFFFF, +0x6C00, +0x302D, +0x2969, +0x1969, +0x2BF7, +0x080E, +0x0020, +0x1B6F, +0x33AE, +0xA7EA, +0x33FE, +0x0C3F, +0x8BA3, +0x080F, +0x7C00, +0xD3F6, +0x33AF, +0xD3F8, +0xD3F9, +0xD3FA, +0x080E, +0x8000, +0x1BF6, +0x33AE, +0xA891, +0x0CC0, +0x0D61, +0x0C22, +0x0C23, +0x0804, +0x00F5, +0x0807, +0x0801, +0x33FE, +0x0C3F, +0x89E6, +0x31B8, +0x080F, +0xFF00, +0x2BF8, +0x33AF, +0x0CC0, +0x0D61, +0x0C22, +0x0C23, +0x0804, +0x00F5, +0x0807, +0x0811, +0x33FE, +0x0C3F, +0x8A57, +0x31B9, +0x080F, +0x00FF, +0x2BF8, +0x33AF, +0x0C40, +0x0D61, +0x0C22, +0x0C23, +0x0804, +0x00F5, +0x0807, +0x0821, +0x33FE, +0x0C3F, +0x89E6, +0x31BA, +0x080F, +0xFF00, +0x2BF9, +0x33AF, +0x0C40, +0x0D61, +0x0C22, +0x0C23, +0x0804, +0x00F5, +0x0807, +0x0831, +0x33FE, +0x0C3F, +0x8A57, +0x31BB, +0x080F, +0x00FF, +0x2BF9, +0x33AF, +0x0807, +0x083B, +0x33FE, +0x0C3F, +0x8AC8, +0x080E, +0x0400, +0x1BF6, +0x33AE, +0xA841, +0x8891, +0x080E, +0x6000, +0x1BF6, +0x33AE, +0x5C2D, +0xA848, +0x8868, +0x0CC0, +0x0C61, +0x0D02, +0x0C03, +0x0804, +0x00FF, +0x0807, +0x0853, +0x33FE, +0x0C3F, +0x89E6, +0x31B8, +0x080F, +0xFF00, +0x2BFA, +0x33AF, +0x0C80, +0x0D61, +0x0D02, +0x0C03, +0x0C04, +0x0807, +0x0862, +0x33FE, +0x0C3F, +0x89E6, +0x31BA, +0x080F, +0x00FF, +0x2BFA, +0x33AF, +0x8887, +0x0CC0, +0x0C61, +0x0D02, +0x0C03, +0x0804, +0x00FF, +0x0807, +0x0873, +0x33FE, +0x0C3F, +0x8A57, +0x31B9, +0x080F, +0xFF00, +0x2BFA, +0x33AF, +0x0C80, +0x0D61, +0x0D02, +0x0C03, +0x0C04, +0x0807, +0x0882, +0x33FE, +0x0C3F, +0x8A57, +0x31BB, +0x080F, +0x00FF, +0x2BFA, +0x33AF, +0x0807, +0x088C, +0x33FE, +0x0C3F, +0x8B11, +0x0807, +0x0891, +0x33FE, +0x0C3F, +0x8B34, +0x080E, +0x0400, +0x1BF6, +0x33AE, +0xA8E9, +0x0181, +0xFFFF, +0x0182, +0x3C06, +0x0183, +0x0800, +0x0184, +0x7060, +0x0185, +0x247E, +0x0161, +0x0009, +0x0162, +0x00C2, +0x0163, +0x7F80, +0xD164, +0xD165, +0x0167, +0x21A2, +0x1BF7, +0x2969, +0x1BE0, +0x2980, +0x1BE1, +0x2960, +0x1BE2, +0x2966, +0x1BE3, +0x2968, +0x1B37, +0xA8E9, +0x0807, +0x08BB, +0x33FE, +0x0C1F, +0x89C5, +0x6C00, +0x080E, +0xFF00, +0x197B, +0x33AE, +0x31A1, +0x080E, +0x4000, +0x1963, +0x33AE, +0xA8C7, +0x88D0, +0x0807, +0x08CA, +0x8D52, +0x31A2, +0xA8CE, +0x5461, +0x88CF, +0x5061, +0x31A1, +0x1351, +0x302D, +0x558D, +0x2BCC, +0x080E, +0x00FF, +0x197B, +0x33AE, +0x31A1, +0x080E, +0x4000, +0x1963, +0x33AE, +0xA8DF, +0x88E5, +0x304D, +0xA8E3, +0x5461, +0x88E4, +0x5061, +0x31A1, +0x1352, +0x302D, +0x558D, +0x2BCD, +0x33FE, +0x0C3F, +0x86CB, +0x0182, +0x3C06, +0x0183, +0x0800, +0x0185, +0x247E, +0x0163, +0x7F80, +0x1BE4, +0x2980, +0x1BE5, +0x2960, +0x1BE6, +0x2966, +0x1BE7, +0x2968, +0x080E, +0x0400, +0x1BF6, +0x33AE, +0xA902, +0x891D, +0x080F, +0x0F80, +0x0163, +0x001E, +0x33AF, +0x080E, +0x0800, +0x1BF6, +0x33AE, +0xA912, +0x080E, +0x1000, +0x1BF6, +0x33AE, +0xA918, +0x891D, +0x080F, +0x03E0, +0x0182, +0x0002, +0x33AF, +0x891D, +0x080F, +0x03E0, +0x0182, +0x0006, +0x33AF, +0x1B37, +0xA962, +0x13CD, +0x410C, +0x1BCC, +0x518D, +0x31A1, +0x1352, +0x410C, +0x502C, +0x31A2, +0x1352, +0x410C, +0x502C, +0x31A2, +0x1351, +0x504C, +0x2969, +0x0807, +0x0934, +0x33FE, +0x0C1F, +0x89C5, +0x6C00, +0x080E, +0xFF00, +0x197B, +0x33AE, +0x31A1, +0x080E, +0x4000, +0x1963, +0x33AE, +0xA940, +0x8949, +0x0807, +0x0943, +0x8D52, +0x31A2, +0xA947, +0x5461, +0x8948, +0x5061, +0x31A1, +0x1351, +0x302D, +0x558D, +0x2BCC, +0x080E, +0x00FF, +0x197B, +0x33AE, +0x31A1, +0x080E, +0x4000, +0x1963, +0x33AE, +0xA958, +0x895E, +0x304D, +0xA95C, +0x5461, +0x895D, +0x5061, +0x31A1, +0x1352, +0x302D, +0x558D, +0x2BCD, +0x080E, +0x0020, +0x1B6F, +0x33AE, +0xA96A, +0x33FE, +0x0C3F, +0x8C25, +0x080E, +0x0020, +0x1B6F, +0x33AE, +0xA976, +0x33FE, +0x0C3F, +0x8D47, +0x2BCB, +0x13CB, +0x3180, +0x2311, +0x33FE, +0x0C3F, +0x80F0, +0x038D, +0x0030, +0xDB5E, +0x1B38, +0xA982, +0x080F, +0x0080, +0xDB7B, +0x33AF, +0xD10D, +0x010D, +0x0002, +0x0306, +0x000C, +0x0C2E, +0x1919, +0x33AE, +0xA98C, +0x8987, +0xD306, +0x0C2E, +0x1919, +0x33AE, +0xA98D, +0x0305, +0x000C, +0xD10D, +0x8998, +0x038D, +0x0030, +0xDB5E, +0xD38D, +0xDB10, +0x1B86, +0xA99D, +0x899A, +0xD310, +0xDB8C, +0x080F, +0x0400, +0xD185, +0x33AF, +0x9006, +0x038D, +0x0029, +0x1BC5, +0xA9A9, +0x89BE, +0x1B5E, +0xA9AC, +0x89BE, +0x0D0E, +0x1913, +0x33AE, +0xA9AC, +0x080E, +0x01FC, +0x1BF6, +0x33AE, +0x31B7, +0xAA12, +0x89BB, +0x0C2D, +0x55B7, +0x31B7, +0xAA1C, +0x0C4F, +0xDBF6, +0x33AF, +0x080F, +0x0400, +0xD185, +0x33AF, +0x8A77, +0x0167, +0x21A2, +0x1B33, +0xA9DD, +0x0C21, +0x0C42, +0x13F2, +0x542C, +0xA9D4, +0x0181, +0xAAAA, +0x080F, +0x3C00, +0x0182, +0x000A, +0x33AF, +0x89DD, +0x544C, +0xA9DD, +0x0181, +0x5555, +0x080F, +0x3C00, +0x0182, +0x0005, +0x33AF, +0x33DF, +0x9007, +0x038D, +0x0029, +0x1BC5, +0xA9E6, +0x1BC6, +0xA9E6, +0x8A09, +0x7FFF, +0x0D0E, +0x1913, +0x33AE, +0xA9E7, +0x1BC5, +0xA9EE, +0x89F1, +0x0806, +0x09F1, +0x8A0F, +0x1BC6, +0xA9F4, +0x8A09, +0x1BF1, +0x31BC, +0x2BCC, +0x430D, +0x2BCD, +0x0806, +0x0A03, +0x080E, +0x0020, +0x1BF3, +0x33AE, +0xAA03, +0x33FE, +0x0C3F, +0x82BD, +0x0806, +0x0A08, +0x1B30, +0xAA08, +0x8AB4, +0x8EED, +0xD38D, +0x080F, +0x0400, +0xD185, +0x33AF, +0x807A, +0x1B59, +0xAA12, +0x8A09, +0x0C2F, +0xDB75, +0x33AF, +0x0C6F, +0x010D, +0x0002, +0x33AF, +0xD3A6, +0x03A6, +0x000A, +0x0180, +0x7D00, +0xD981, +0xD182, +0xD183, +0xD184, +0x0185, +0x2408, +0x01AC, +0xA080, +0x01AF, +0x0002, +0x0800, +0x0341, +0x0C01, +0x0C62, +0xD9AE, +0x0807, +0x0A32, +0x1B3A, +0xAA32, +0x8A82, +0x01AC, +0xA0C0, +0x01AF, +0x0003, +0x0800, +0x0342, +0x0C01, +0x0C62, +0x0807, +0x0A3F, +0x1B3A, +0xAA3F, +0x8A82, +0x0C4E, +0x1BF6, +0x33AE, +0xAA45, +0x1B5E, +0xA9B7, +0x01AC, +0x2000, +0x0180, +0x7D00, +0x0181, +0x5555, +0x0182, +0x1446, +0x0183, +0x010D, +0x0184, +0x2800, +0x0185, +0x6410, +0xD1AC, +0x01AF, +0x0014, +0x0800, +0x0345, +0x0C21, +0x0C62, +0x0807, +0x0A5F, +0x1B39, +0xAA5F, +0x8A82, +0x0180, +0x7D00, +0x0181, +0xAAAA, +0x0182, +0x2846, +0x0183, +0x010D, +0x0184, +0x2800, +0x0185, +0x6410, +0xD1AC, +0x01AF, +0x0015, +0x0800, +0x0346, +0x0C21, +0x0C62, +0x0807, +0x0A77, +0x1B39, +0xAA77, +0x8A82, +0xD1AE, +0xD1AC, +0xD3A6, +0x7000, +0x0C6F, +0xD10D, +0x33AF, +0x0C2F, +0xD375, +0x33AF, +0x9006, +0x380D, +0x29AD, +0xD9B6, +0x7080, +0x667C, +0x302D, +0xAA8F, +0x080E, +0x7FFF, +0x198A, +0x1186, +0x33AE, +0x8A94, +0x080E, +0x7FFF, +0x198B, +0x1186, +0x33AE, +0x402D, +0x31A3, +0x3184, +0x3185, +0x304D, +0xAA9B, +0x8A9E, +0x4225, +0x5C22, +0x8A98, +0x5085, +0x546D, +0xBAA2, +0x8AAB, +0x54A4, +0x55A3, +0xBAA6, +0x8AA7, +0x9007, +0x5E20, +0xBAB0, +0x3580, +0x9007, +0x5A20, +0x31A2, +0x430D, +0xAAA9, +0x304D, +0x29AD, +0xD9B6, +0x700F, +0x9007, +0x1B5E, +0xAAB7, +0x8A09, +0x080E, +0x8000, +0x1BEB, +0x33AE, +0xAB44, +0x0180, +0x7D00, +0x0181, +0xFFFF, +0x0182, +0x3C23, +0x0183, +0x0087, +0x0184, +0x3068, +0x0185, +0x647C, +0xD160, +0xD161, +0xD162, +0x0163, +0x001F, +0x0164, +0x000A, +0xD165, +0x0166, +0x7800, +0x0167, +0x21A2, +0xD168, +0x0169, +0xB7B7, +0x0D0C, +0x080E, +0x03E0, +0x196D, +0x33AE, +0x55AC, +0xAB42, +0x0180, +0x1964, +0x6620, +0x0C00, +0x0C01, +0x080E, +0x7FFF, +0x1186, +0x33AE, +0x080D, +0x0100, +0x518D, +0x31AC, +0x0C2E, +0x1963, +0x33AE, +0xAAF0, +0x8AF8, +0x080E, +0x7FFF, +0x1989, +0x33AE, +0x500D, +0x31A0, +0x5181, +0x31A1, +0x0C4E, +0x1963, +0x33AE, +0xAAFD, +0x8B05, +0x080E, +0x7FFF, +0x198A, +0x33AE, +0x500D, +0x31A0, +0x5181, +0x31A1, +0x0C8E, +0x1963, +0x33AE, +0xAB0A, +0x8B12, +0x080E, +0x7FFF, +0x198B, +0x33AE, +0x500D, +0x31A0, +0x5181, +0x31A1, +0x0D0E, +0x1963, +0x33AE, +0xAB17, +0x8B1F, +0x080E, +0x7FFF, +0x198C, +0x33AE, +0x500D, +0x31A0, +0x5181, +0x31A1, +0x0E0E, +0x1963, +0x33AE, +0xAB24, +0x8B2C, +0x080E, +0x7FFF, +0x198D, +0x33AE, +0x500D, +0x31A0, +0x5181, +0x31A1, +0x422D, +0x540D, +0xBB44, +0x080F, +0x03FF, +0x0182, +0x0084, +0x33AF, +0x0C2F, +0xD183, +0x33AF, +0x080F, +0x0020, +0xD184, +0x33AF, +0x0FEF, +0xD963, +0x33AF, +0x0180, +0x7D00, +0x6C00, +0x8B44, +0xBB44, +0x6C00, +0x13EE, +0x319A, +0x410C, +0x1BED, +0x31BB, +0x518D, +0x31BC, +0x1B3C, +0xAC2C, +0x0180, +0x07FF, +0x0181, +0xFFFF, +0x0182, +0x3C06, +0x0183, +0x0800, +0x0184, +0x3060, +0x0185, +0x6402, +0x0160, +0x0C07, +0xD161, +0x0162, +0x0042, +0x0163, +0x3000, +0xD164, +0xD165, +0x0166, +0x7828, +0x0167, +0x21A2, +0xD168, +0x0807, +0x0B6C, +0x33FE, +0x0C1F, +0x89C5, +0x0FEF, +0x0182, +0x0002, +0x33AF, +0x1352, +0x1BEE, +0x518D, +0x31AC, +0x430D, +0xAB78, +0x318D, +0x8B7A, +0x080D, +0x00FF, +0x31A1, +0x080F, +0xFF00, +0x2969, +0x33AF, +0x1351, +0x1BED, +0x518D, +0x31AC, +0x430D, +0xAB87, +0x318D, +0x8B89, +0x080D, +0x00FF, +0x31A1, +0x080F, +0x00FF, +0x2969, +0x33AF, +0x6C00, +0x1351, +0x080E, +0xFF00, +0x197B, +0x33AE, +0x558D, +0xBB98, +0x0C1B, +0x8B99, +0x31BB, +0x1352, +0x080E, +0x00FF, +0x197B, +0x33AE, +0x558D, +0xBBA2, +0x0C1A, +0x8BA3, +0x31BA, +0x0180, +0x7D00, +0x0181, +0xFFFF, +0x0182, +0x3C02, +0x0183, +0x0800, +0x0184, +0x3060, +0x0185, +0x6402, +0xD160, +0xD161, +0x0162, +0x0042, +0x0163, +0x0060, +0x0164, +0x00D0, +0xD165, +0x0166, +0x7800, +0x0167, +0x21A2, +0xD168, +0x13CD, +0x1B52, +0x518D, +0x31AC, +0x430D, +0xABC5, +0x318D, +0x8BC7, +0x080D, +0x00FF, +0x31A1, +0x080F, +0xFF00, +0x2969, +0x33AF, +0x13CC, +0x1B51, +0x518D, +0x31AC, +0x430D, +0xABD4, +0x318D, +0x8BD6, +0x080D, +0x00FF, +0x31A1, +0x080F, +0x00FF, +0x2969, +0x33AF, +0x0807, +0x0BE0, +0x33FE, +0x0C1F, +0x89C5, +0xD160, +0x080F, +0x0038, +0x0166, +0x0005, +0x080F, +0x1000, +0xD166, +0x080F, +0x0E00, +0x0166, +0x0004, +0x33AF, +0x1BED, +0x31A2, +0x545B, +0xBC0E, +0x080E, +0x03C0, +0x196C, +0x33AE, +0x402D, +0x31A0, +0x080E, +0x003F, +0x196C, +0x33AE, +0xABFE, +0x5820, +0x8BFF, +0x5840, +0x31A0, +0x0DC4, +0x5404, +0xBC04, +0x0DC0, +0x080F, +0x7C00, +0x2167, +0x080F, +0x03E0, +0x2167, +0x33AF, +0x0169, +0xFFFF, +0x8C2B, +0x1BED, +0x590D, +0x576D, +0xBC2C, +0x080E, +0x03C0, +0x196C, +0x33AE, +0x402D, +0x31A0, +0x080E, +0x003F, +0x196C, +0x33AE, +0xAC21, +0x5C20, +0xBC20, +0x0C0D, +0x31A0, +0x080F, +0x7C00, +0x2167, +0x080F, +0x03E0, +0x2167, +0x0FEF, +0x2167, +0x33AF, +0xD169, +0x6C00, +0x1B3B, +0xAC7E, +0x0180, +0x07FF, +0x0181, +0xFFFF, +0x0182, +0x3C06, +0x0183, +0x0800, +0x0184, +0x3060, +0x0185, +0x6402, +0x0160, +0x0C07, +0xD161, +0x0162, +0x0042, +0x0163, +0x3000, +0xD164, +0xD165, +0x0166, +0x7828, +0x0167, +0x21A2, +0xD168, +0x1352, +0x519A, +0x31AC, +0x430D, +0xAC4F, +0x318D, +0x8C51, +0x080D, +0x00FF, +0x31A1, +0x080F, +0xFF00, +0x2969, +0x33AF, +0x1351, +0x519B, +0x31AC, +0x430D, +0xAC5D, +0x318D, +0x8C5F, +0x080D, +0x00FF, +0x31A1, +0x080F, +0x00FF, +0x2969, +0x33AF, +0x0807, +0x0C69, +0x33FE, +0x0C1F, +0x89C5, +0x6C00, +0x1351, +0x080E, +0xFF00, +0x197B, +0x33AE, +0x558D, +0xBC73, +0x0C1B, +0x8C74, +0x31BB, +0x1352, +0x080E, +0x00FF, +0x197B, +0x33AE, +0x558D, +0xBC7D, +0x0C1A, +0x8C7E, +0x31BA, +0x080E, +0x0040, +0x1BF3, +0x33AE, +0xACB2, +0x0180, +0x7D00, +0x0181, +0xFFFF, +0x0182, +0x3C06, +0x0183, +0x0800, +0x0184, +0x3060, +0x0185, +0x647C, +0xD160, +0x0161, +0x0009, +0x0162, +0x0042, +0x0163, +0x0F00, +0x0164, +0xA000, +0x0165, +0x0999, +0x0166, +0x7800, +0x0167, +0x21A2, +0xD168, +0x334C, +0x410C, +0x336D, +0x518D, +0x31BC, +0x1352, +0x410C, +0x3381, +0x502C, +0x31A2, +0x1351, +0x504C, +0x2969, +0x0807, +0x0CB1, +0x33FE, +0x0C1F, +0x89C5, +0x6C00, +0x196B, +0x2B5A, +0x196D, +0x2B5C, +0x196C, +0x2B5B, +0x196E, +0x2B5D, +0x196F, +0x2B60, +0x1970, +0x2B61, +0x1971, +0x2B62, +0x1972, +0x2B63, +0x8CC3, +0x33FE, +0x0C3F, +0x8000, +0x9006, +0x080E, +0x3000, +0x1913, +0x080E, +0xFFFF, +0xACCE, +0x9006, +0x19B3, +0x0800, +0x0077, +0x540D, +0xACD4, +0x8D51, +0xD9AE, +0x01AF, +0x0010, +0x0800, +0x0348, +0x0801, +0x0347, +0x0802, +0x034B, +0x3C40, +0x0807, +0x0CE1, +0x8D52, +0x0807, +0x0CE5, +0x0C04, +0x8D64, +0x01AF, +0x0012, +0x0800, +0x0348, +0x0801, +0x0348, +0x0802, +0x034D, +0x3C40, +0x0807, +0x0CF1, +0x8D52, +0x0807, +0x0CF5, +0x0C04, +0x8D64, +0x01AF, +0x0011, +0x0800, +0x0348, +0x0801, +0x0347, +0x0802, +0x034C, +0x3C40, +0x0807, +0x0D01, +0x8D52, +0x0807, +0x0D05, +0x0C24, +0x8D64, +0x01AF, +0x0013, +0x0800, +0x0348, +0x0801, +0x0348, +0x0802, +0x034E, +0x3C40, +0x0807, +0x0D11, +0x8D52, +0x0807, +0x0D15, +0x0C24, +0x8D64, +0x19B3, +0x31A4, +0x0805, +0x01EE, +0x54A4, +0xAD1C, +0x8D3F, +0x0805, +0x01CC, +0x54A4, +0xAD21, +0x8D41, +0x0805, +0x0144, +0x54A4, +0xAD26, +0x8D43, +0x0805, +0x0188, +0x54A4, +0xAD2B, +0x8D46, +0x0805, +0x0100, +0x54A4, +0xAD30, +0x8D48, +0x0805, +0x0111, +0x54A4, +0xAD35, +0x8D4A, +0x0805, +0x0155, +0x54A4, +0xAD3A, +0x8D4C, +0x0805, +0x0177, +0x54A4, +0xAD4E, +0x8D4E, +0x01B3, +0x01CC, +0x01B3, +0x0144, +0x01B3, +0x0155, +0x8D4C, +0x01B3, +0x0100, +0x01B3, +0x0111, +0x01B3, +0x0155, +0x01B3, +0x0177, +0x01B3, +0x0077, +0xD1AE, +0x9006, +0x080E, +0x1FE0, +0x196E, +0x33AE, +0x31A3, +0x080E, +0x1000, +0x196E, +0x33AE, +0x31A4, +0xAD5E, +0x8D62, +0x080D, +0x0100, +0x546D, +0x31A3, +0x308D, +0x9007, +0xAD68, +0x308D, +0xAD72, +0x8D6B, +0x308D, +0xAD6B, +0x8D72, +0x3805, +0x5065, +0x31A4, +0x430D, +0xAD79, +0x308D, +0x8D76, +0x3805, +0x5465, +0xBD76, +0x8D79, +0x3C02, +0x35A1, +0x8D7A, +0x384D, +0x29AD, +0xD9B6, +0x9007, +0x01AF, +0x0010, +0x01AD, +0x0080, +0xD9B6, +0x01AF, +0x0011, +0xD1AD, +0xD9B6, +0x01AF, +0x0016, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0014, +0xD1AD, +0xD9B6, +0x01AF, +0x0012, +0xD1AD, +0xD9B6, +0x01AF, +0x0013, +0xD1AD, +0xD9B6, +0x01AF, +0x0018, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0015, +0xD1AD, +0xD9B6, +0x9007, +0x01AF, +0x0010, +0xD1AD, +0xD9B6, +0x01AF, +0x0011, +0x01AD, +0x0080, +0xD9B6, +0x01AF, +0x0016, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0014, +0xD1AD, +0xD9B6, +0x01AF, +0x0012, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0013, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0018, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0015, +0xD1AD, +0xD9B6, +0x9007, +0x01AF, +0x0010, +0xD1AD, +0xD9B6, +0x01AF, +0x0011, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0016, +0x01AD, +0x0080, +0xD9B6, +0x01AF, +0x0014, +0xD1AD, +0xD9B6, +0x01AF, +0x0012, +0xD1AD, +0xD9B6, +0x01AF, +0x0013, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0018, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0015, +0xD1AD, +0xD9B6, +0x9007, +0x01AF, +0x0010, +0xD1AD, +0xD9B6, +0x01AF, +0x0011, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0016, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0014, +0x01AD, +0x0080, +0xD9B6, +0x01AF, +0x0012, +0xD1AD, +0xD9B6, +0x01AF, +0x0013, +0xD1AD, +0xD9B6, +0x01AF, +0x0018, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0015, +0xD1AD, +0xD9B6, +0x9007, +0x01AF, +0x0010, +0xD1AD, +0xD9B6, +0x01AF, +0x0011, +0xD1AD, +0xD9B6, +0x01AF, +0x0016, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0014, +0xD1AD, +0xD9B6, +0x01AF, +0x0012, +0x01AD, +0x0080, +0xD9B6, +0x01AF, +0x0013, +0xD1AD, +0xD9B6, +0x01AF, +0x0018, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0015, +0xD1AD, +0xD9B6, +0x9007, +0x01AF, +0x0010, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0011, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0016, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0014, +0xD1AD, +0xD9B6, +0x01AF, +0x0012, +0xD1AD, +0xD9B6, +0x01AF, +0x0013, +0x01AD, +0x0080, +0xD9B6, +0x01AF, +0x0018, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0015, +0xD1AD, +0xD9B6, +0x9007, +0x01AF, +0x0010, +0xD1AD, +0xD9B6, +0x01AF, +0x0011, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0016, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0014, +0xD1AD, +0xD9B6, +0x01AF, +0x0012, +0xD1AD, +0xD9B6, +0x01AF, +0x0013, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0018, +0x01AD, +0x0080, +0xD9B6, +0x01AF, +0x0015, +0xD1AD, +0xD9B6, +0x9007, +0x01AF, +0x0010, +0xD1AD, +0xD9B6, +0x01AF, +0x0011, +0xD1AD, +0xD9B6, +0x01AF, +0x0016, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0014, +0xD1AD, +0xD9B6, +0x01AF, +0x0012, +0xD1AD, +0xD9B6, +0x01AF, +0x0013, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0018, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0015, +0x01AD, +0x0080, +0xD9B6, +0x9007, +0x01AF, +0x0010, +0x01AD, +0x0080, +0xD9B6, +0x01AF, +0x0011, +0xD1AD, +0xD9B6, +0x01AF, +0x0016, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0014, +0xD1AD, +0xD9B6, +0x01AF, +0x0012, +0xD1AD, +0xD9B6, +0x01AF, +0x0013, +0xD1AD, +0xD9B6, +0x01AF, +0x0018, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0015, +0xD1AD, +0xD9B6, +0x9007, +0x01AF, +0x0010, +0xD1AD, +0xD9B6, +0x01AF, +0x0011, +0xD1AD, +0xD9B6, +0x01AF, +0x0016, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0014, +0xD1AD, +0xD9B6, +0x01AF, +0x0012, +0x01AD, +0x0080, +0xD9B6, +0x01AF, +0x0013, +0xD1AD, +0xD9B6, +0x01AF, +0x0018, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0015, +0xD1AD, +0xD9B6, +0x9007, +0x0C4E, +0x1B24, +0x33AE, +0xAEF2, +0x8F27, +0x038D, +0x0029, +0x0C2F, +0xDB75, +0x33AF, +0x0C6F, +0x010D, +0x0002, +0x33AF, +0xD3A6, +0x03A6, +0x000A, +0x0C2E, +0x1B24, +0x33AE, +0xAF10, +0xD9AE, +0x01AF, +0x0016, +0xD1AD, +0xD9B6, +0x01AF, +0x0018, +0x01AD, +0x00FF, +0xD9B6, +0x0C2F, +0xDB24, +0x33AF, +0x8F1D, +0xD9AE, +0x01AF, +0x0016, +0x01AD, +0x00FF, +0xD9B6, +0x01AF, +0x0018, +0xD1AD, +0xD9B6, +0x0C2F, +0xD324, +0x33AF, +0xD1AE, +0xD3A6, +0x7000, +0x0C6F, +0xD10D, +0x33AF, +0x0C2F, +0xD375, +0x33AF, +0xD38D, +0x8A09, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0180, +0x7D00, +0x0181, +0xAAAA, +0x0182, +0x2802, +0x0183, +0x0800, +0x0184, +0x3060, +0x0185, +0x6402, +0x0160, +0x0C1F, +0xD161, +0x0162, +0x0042, +0x0163, +0x3000, +0xD164, +0x0165, +0x3000, +0x0166, +0x7828, +0x0167, +0x21A2, +0xD168, +0x0169, +0xB7B7, +0x6E00, +0x197B, +0x430D, +0x31BA, +0x0180, +0x7D00, +0x0181, +0xAAAA, +0x0182, +0x2802, +0x0183, +0x0800, +0x0184, +0x3060, +0x0185, +0x6402, +0x0160, +0x0C1F, +0xD161, +0xD162, +0x0163, +0x3000, +0xD164, +0x0165, +0xB000, +0x0166, +0x7828, +0x0167, +0x21A2, +0xD168, +0x0169, +0x4949, +0x6E00, +0x197B, +0x430D, +0x55BA, +0xB043, +0x0C0D, +0x080F, +0x00FF, +0x2BE9, +0x33AE, +0x8D47, +0x2BCA, +0x33DF, +0x8CC6, +0x01A8, +0x0140, +0xD9B5, +0x01AC, +0xA200, +0x0180, +0x03FF, +0xD981, +0xD182, +0xD183, +0x0184, +0x4000, +0x0185, +0x2408, +0x0800, +0x0349, +0x0802, +0x034A, +0x0803, +0x01B4, +0x080E, +0x01E0, +0x1B1C, +0x33AE, +0x31A4, +0x0EED, +0x35A0, +0x3C43, +0xD9B8, +0x0816, +0x006B, +0x8071, +0xD1B5, +0x33DF, +0x1B27, +0xA070, +0x863A, +0x8644, +0x7080, +0x1B27, +0xA084, +0x1B35, +0xA084, +0x0801, +0x0022, +0x3805, +0x0DCD, +0x54AD, +0xA07D, +0x8081, +0x5E20, +0x3C43, +0xD9B8, +0x8078, +0x6670, +0xB084, +0x80AF, +0x380D, +0x2B53, +0x1B34, +0xA0AE, +0x308D, +0xA08B, +0x80AE, +0x3805, +0x0CED, +0x54AD, +0xA090, +0x80A3, +0x0DED, +0x54AD, +0xA094, +0x80A3, +0x0EED, +0x54AD, +0xA098, +0x80A3, +0x0FED, +0x54AD, +0xA09C, +0x80A3, +0x080D, +0x0027, +0x54AD, +0xA0A1, +0x80A3, +0x5C24, +0x31A4, +0x5A20, +0x3805, +0x0818, +0x002F, +0x54B8, +0xB0AB, +0x5E20, +0x80AE, +0x3C43, +0xD9B8, +0x8088, +0x9016, +0x5A20, +0x55A1, +0xB0B6, +0x3580, +0x318D, +0x2B53, +0x8084, +0x3C43, +0xD9B8, +0x700F, +0x8081, +0x0800, +0x0349, +0x0802, +0x034A, +0x0803, +0x01B4, +0x302D, +0xA0C4, +0x13C9, +0x80C5, +0x308C, +0x80CB, +0x3C43, +0xD9B8, +0xD1B5, +0x33DF, +0x9007, +0x3804, +0x5584, +0xB0E0, +0x548C, +0x31A4, +0x0801, +0x002F, +0x308D, +0xA0D5, +0x80DF, +0x5C24, +0x31A4, +0x5A20, +0x3805, +0x54A1, +0xB0DC, +0x80DF, +0x3C43, +0xD9B8, +0x80D2, +0x80C6, +0x31A4, +0x0C01, +0x308D, +0xA0E5, +0x80EF, +0x5C24, +0x31A4, +0x5E20, +0x3805, +0x5425, +0xB0EC, +0x80EF, +0x3C43, +0xD9B8, +0x80E2, +0x80C6, +0x0E0E, +0x1B6F, +0x33AE, +0xA275, +0x0180, +0x03FF, +0x0181, +0xFFFF, +0x0182, +0x3C46, +0xD183, +0x0184, +0x7020, +0x0185, +0x2404, +0x0160, +0x0C10, +0x0161, +0x0009, +0x0162, +0x00C2, +0xD163, +0xD164, +0xD165, +0x0166, +0x792B, +0x0167, +0x21A2, +0x0168, +0x4925, +0xD169, +0x1B33, +0xA127, +0x0C21, +0x0C42, +0x13F2, +0x542C, +0xA11E, +0x0181, +0xAAAA, +0x080F, +0x3C00, +0x0182, +0x000A, +0x33AF, +0x8127, +0x544C, +0xA127, +0x0181, +0x5555, +0x080F, +0x3C00, +0x0182, +0x0005, +0x33AF, +0x080E, +0x8000, +0x1963, +0x33AE, +0xA131, +0x080E, +0x0FE0, +0x116E, +0x33AE, +0x8135, +0x080E, +0x0FC0, +0x116E, +0x33AE, +0x3184, +0x080E, +0x1000, +0x116E, +0x33AE, +0x3185, +0x13CC, +0x3181, +0x1351, +0x502C, +0x31AC, +0x0C23, +0x5465, +0xB148, +0x548C, +0x31A2, +0xB15C, +0x0C02, +0x815C, +0x080E, +0x8000, +0x1963, +0x33AE, +0xA150, +0x0803, +0x0080, +0x8152, +0x0803, +0x0040, +0x548C, +0x506D, +0x31A2, +0x0803, +0x0100, +0x546D, +0xB15A, +0x815C, +0x0802, +0x00FF, +0x0C2F, +0xDB75, +0x33AF, +0x0C6F, +0x010D, +0x0002, +0x33AF, +0xD3A6, +0x03A6, +0x000A, +0x4102, +0x4302, +0x304D, +0xD9AE, +0x29AD, +0x01AF, +0x0016, +0xD9B6, +0x13CD, +0x3181, +0x1352, +0x502C, +0x31AC, +0x0C23, +0x5465, +0xB17B, +0x548C, +0x31A2, +0xB18F, +0x0C02, +0x818F, +0x080E, +0x8000, +0x1963, +0x33AE, +0xA183, +0x0803, +0x0080, +0x8185, +0x0803, +0x0040, +0x548C, +0x506D, +0x31A2, +0x0803, +0x0100, +0x546D, +0xB18D, +0x818F, +0x0802, +0x00FF, +0x4102, +0x4302, +0x304D, +0x29AD, +0x01AF, +0x0018, +0xD9B6, +0xD1AE, +0xD3A6, +0x7000, +0x0C6F, +0xD10D, +0x33AF, +0x0C2F, +0xD375, +0x33AF, +0x6647, +0x080E, +0x7FFF, +0x1989, +0x33AE, +0x402D, +0x31A3, +0x080E, +0x7FFF, +0x1986, +0x31A2, +0x31A4, +0x31AC, +0x080E, +0x01E0, +0x1B76, +0x33AE, +0xA1B2, +0x81B5, +0x422C, +0x5C2D, +0x81B0, +0x3181, +0x4282, +0x0C05, +0x0DEE, +0x1B76, +0x33AE, +0x31B7, +0xA1BE, +0x81C3, +0x5045, +0x31A5, +0x5C37, +0x31B7, +0x81BC, +0x0E0E, +0x1B76, +0x33AE, +0xA1CA, +0x50A4, +0x31A2, +0x81CC, +0x54A4, +0x31A2, +0x5022, +0x546D, +0xB1D0, +0x81D6, +0x5422, +0xB1D3, +0x81DB, +0x55A3, +0xB1DB, +0x81D8, +0xDB12, +0x81DC, +0x0312, +0x0002, +0x81DC, +0xD312, +0x080E, +0x0038, +0x1B77, +0x33AE, +0x31AC, +0x0CEE, +0x1B77, +0x33AE, +0x31A0, +0x080E, +0x00F0, +0x1B78, +0x33AE, +0x31A1, +0x0DEE, +0x1B78, +0x33AE, +0x31A2, +0x080E, +0x00E0, +0x196B, +0x33AE, +0x31A3, +0x080E, +0x03C0, +0x196C, +0x33AE, +0x31A4, +0x4024, +0x080E, +0x003F, +0x196C, +0x33AE, +0xA1FF, +0x8201, +0x5824, +0x31A4, +0x546C, +0xB206, +0x5444, +0xB206, +0x820B, +0x5403, +0xB210, +0x5481, +0xB210, +0x820E, +0x0313, +0x0002, +0x8211, +0xDB13, +0x8211, +0xD313, +0x080E, +0x03E0, +0x1379, +0x33AE, +0x3180, +0x0FEE, +0x1379, +0x33AE, +0x3181, +0x080E, +0x7F00, +0x137A, +0x33AE, +0x3184, +0x080E, +0x8000, +0x137A, +0x33AE, +0x3197, +0x080E, +0x007F, +0x137A, +0x33AE, +0x3185, +0x080E, +0x0080, +0x137A, +0x33AE, +0x3198, +0x080E, +0x03E0, +0x116D, +0x33AE, +0x3182, +0x0807, +0x0236, +0x82AB, +0x5440, +0xB239, +0x8272, +0x332D, +0xA241, +0x32ED, +0xA240, +0x5464, +0xB247, +0x8272, +0x8272, +0x32ED, +0xA244, +0x8247, +0x5483, +0xB247, +0x8272, +0x5422, +0xB24A, +0x826F, +0x332D, +0xA251, +0x330D, +0xA257, +0x54A3, +0xB257, +0x826F, +0x330D, +0xA254, +0x826F, +0x5465, +0xB257, +0x826F, +0x080E, +0x03C0, +0x196C, +0x33AE, +0x5CED, +0xA274, +0x1BED, +0x5C8D, +0x31AC, +0x1BCC, +0x55AC, +0xA264, +0x8266, +0xB26F, +0x8266, +0x1BEE, +0x5C8D, +0x31AC, +0x1BCD, +0x55AC, +0xA26D, +0x8274, +0xB26F, +0x8274, +0x0314, +0x0002, +0x8275, +0xDB14, +0x8275, +0xD314, +0x0C2F, +0xDB75, +0x33AF, +0x0C6F, +0x010D, +0x0002, +0x33AF, +0xD3A6, +0x03A6, +0x000A, +0x1B51, +0x1352, +0x3180, +0xD9AE, +0x29AD, +0x01AF, +0x0016, +0xD9B6, +0x21AD, +0x01AF, +0x0018, +0xD9B6, +0xD1AE, +0xD3A6, +0x7000, +0x0C6F, +0xD10D, +0x33AF, +0x0C2F, +0xD375, +0x33AF, +0x196B, +0x2B5A, +0x196D, +0x2B5C, +0x196C, +0x2B5B, +0x196E, +0x2B5D, +0x196F, +0x2B60, +0x1970, +0x2B61, +0x1971, +0x2B62, +0x1972, +0x2B63, +0x13CD, +0x410C, +0x1BCC, +0x518D, +0x2BF1, +0x33DF, +0x8979, +0x080E, +0x1FE0, +0x196E, +0x33AE, +0x31A3, +0x080E, +0x1000, +0x196E, +0x33AE, +0x31B9, +0xA2B7, +0x82BB, +0x080D, +0x0100, +0x546D, +0x31A3, +0x332D, +0x9007, +0x0C2F, +0xDB75, +0x33AF, +0x0C6F, +0x010D, +0x0002, +0x33AF, +0xD3A6, +0x03A6, +0x000A, +0x01B3, +0x0177, +0xD9AE, +0x82FB, +0x01B3, +0x0155, +0x01B3, +0x0144, +0x01B3, +0x01CC, +0x01B3, +0x01EE, +0x83DA, +0x01B3, +0x01CC, +0x01B3, +0x0144, +0x01B3, +0x0155, +0x01B3, +0x0177, +0x84AB, +0x01B3, +0x0155, +0x01B3, +0x0111, +0x01B3, +0x0100, +0x01B3, +0x0188, +0x859D, +0x01B3, +0x0100, +0x01B3, +0x0111, +0x01B3, +0x0155, +0x01B3, +0x0177, +0x01B3, +0x0077, +0xD1AE, +0xD3A6, +0x7000, +0x0C6F, +0xD10D, +0x33AF, +0x0C2F, +0xD375, +0x33AF, +0x0C1F, +0x9006, +0x0180, +0x7D00, +0x0181, +0xAAAA, +0x0182, +0x28C6, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0016, +0xD9B6, +0x0807, +0x0313, +0x33FE, +0x0C1F, +0x0C63, +0x864B, +0x19AD, +0x2B47, +0x0180, +0x7D00, +0x0181, +0xAAAA, +0x0182, +0x2886, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0016, +0xD9B6, +0x0807, +0x032D, +0x33FE, +0x0C1F, +0x0C43, +0x864B, +0x0807, +0x0330, +0x868A, +0x31A5, +0x0801, +0x0020, +0x5023, +0x31A1, +0x080E, +0x00FF, +0x13EF, +0x33AE, +0x3180, +0x2179, +0x2348, +0x5581, +0x43ED, +0x31B8, +0x080D, +0x00FF, +0x542D, +0x55AC, +0x43ED, +0x31B9, +0x0800, +0x0179, +0x30AD, +0x0807, +0x034C, +0x0C04, +0x86B5, +0x080E, +0x00FF, +0x1BEF, +0x33AE, +0x2B48, +0x0800, +0x0348, +0x0801, +0x0347, +0x0807, +0x0358, +0x866E, +0x1B48, +0x080F, +0x00FF, +0x2BEF, +0x33AF, +0x0800, +0x0348, +0x0801, +0x0347, +0x0802, +0x0179, +0x0807, +0x0366, +0x868A, +0x0807, +0x036A, +0x0C04, +0x869C, +0x0180, +0x7D00, +0x0181, +0x5555, +0x0182, +0x14C6, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0018, +0xD9B6, +0x0807, +0x0382, +0x33FE, +0x0C1F, +0x0C63, +0x864B, +0x19AD, +0x2B47, +0x0180, +0x7D00, +0x0181, +0x5555, +0x0182, +0x1486, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0018, +0xD9B6, +0x0807, +0x039C, +0x33FE, +0x0C1F, +0x0C43, +0x864B, +0x0807, +0x039F, +0x868A, +0x31A5, +0x0801, +0x0020, +0x5023, +0x31A1, +0x080E, +0x00FF, +0x13F0, +0x33AE, +0x3180, +0x217A, +0x2348, +0x5581, +0x43ED, +0x31B8, +0x080D, +0x00FF, +0x542D, +0x55AC, +0x43ED, +0x31B9, +0x0800, +0x017A, +0x30AD, +0x0807, +0x03BB, +0x0C04, +0x86B5, +0x080E, +0x00FF, +0x1BF0, +0x33AE, +0x2B48, +0x0800, +0x0348, +0x0801, +0x0347, +0x0807, +0x03C7, +0x866E, +0x1B48, +0x080F, +0x00FF, +0x2BF0, +0x33AF, +0x0800, +0x0348, +0x0801, +0x0347, +0x0802, +0x017A, +0x0807, +0x03D5, +0x868A, +0x0807, +0x03D9, +0x0C04, +0x869C, +0x82CB, +0x0180, +0x7D00, +0x0181, +0xAAAA, +0x0182, +0x28C6, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0010, +0xD9B6, +0x0807, +0x03F2, +0x33FE, +0x0C1F, +0x0C63, +0x864B, +0x19AD, +0x2B47, +0x0180, +0x7D00, +0x0181, +0xAAAA, +0x0182, +0x2886, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0010, +0xD9B6, +0x0807, +0x040C, +0x33FE, +0x0C1F, +0x0C43, +0x864B, +0x0807, +0x040F, +0x868A, +0x31A5, +0x0801, +0x0020, +0x5023, +0x134B, +0x3180, +0x2173, +0x2348, +0x558D, +0x43ED, +0x31B8, +0x0801, +0x0020, +0x5061, +0x0801, +0x00FF, +0x55A1, +0x55AC, +0x43ED, +0x31B9, +0x0800, +0x0173, +0x30AD, +0x0807, +0x042A, +0x0C04, +0x86B5, +0x1B4B, +0x2B48, +0x0800, +0x0348, +0x0801, +0x0347, +0x0807, +0x0433, +0x866E, +0x1B48, +0x2B4B, +0x0800, +0x0348, +0x0801, +0x0347, +0x0802, +0x0173, +0x0807, +0x043E, +0x868A, +0x0807, +0x0442, +0x0C04, +0x869C, +0x0180, +0x7D00, +0x0181, +0x5555, +0x0182, +0x14C6, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0012, +0xD9B6, +0x0807, +0x045A, +0x33FE, +0x0C1F, +0x0C63, +0x864B, +0x19AD, +0x2B47, +0x0180, +0x7D00, +0x0181, +0x5555, +0x0182, +0x1486, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0012, +0xD9B6, +0x0807, +0x0474, +0x33FE, +0x0C1F, +0x0C43, +0x864B, +0x0807, +0x0477, +0x868A, +0x31A5, +0x0801, +0x0020, +0x5023, +0x134D, +0x3180, +0x2175, +0x2348, +0x558D, +0x43ED, +0x31B8, +0x0801, +0x0020, +0x5061, +0x0801, +0x00FF, +0x55A1, +0x55AC, +0x43ED, +0x31B9, +0x0800, +0x0175, +0x30AD, +0x0807, +0x0492, +0x0C04, +0x86B5, +0x1B4D, +0x2B48, +0x0800, +0x0348, +0x0801, +0x0347, +0x0807, +0x049B, +0x866E, +0x1B48, +0x2B4D, +0x0800, +0x0348, +0x0801, +0x0347, +0x0802, +0x0175, +0x0807, +0x04A6, +0x868A, +0x0807, +0x04AA, +0x0C04, +0x869C, +0x82D4, +0x0180, +0x7D00, +0x0181, +0xAAAA, +0x0182, +0x2846, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0016, +0xD9B6, +0x0807, +0x04C3, +0x33FE, +0x0C1F, +0x0C63, +0x864B, +0x19AD, +0x2B47, +0x0180, +0x7D00, +0x0181, +0xAAAA, +0x0182, +0x2806, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0016, +0xD9B6, +0x0807, +0x04DD, +0x33FE, +0x0C1F, +0x0C43, +0x864B, +0x0807, +0x04E0, +0x868A, +0x31A5, +0x0801, +0x0020, +0x5023, +0x080E, +0xFF00, +0x13EF, +0x33AE, +0x3180, +0x2179, +0x2348, +0x558D, +0x43ED, +0x31B8, +0x080D, +0x00FF, +0x542D, +0x55AC, +0x43ED, +0x31B9, +0x0800, +0x0179, +0x30AD, +0x0807, +0x04FB, +0x0C24, +0x86B5, +0x080E, +0xFF00, +0x1BEF, +0x33AE, +0x2B48, +0x0800, +0x0348, +0x0801, +0x0347, +0x0807, +0x0507, +0x866E, +0x1B48, +0x080F, +0xFF00, +0x2BEF, +0x33AF, +0x0800, +0x0348, +0x0801, +0x0347, +0x0802, +0x0179, +0x0807, +0x0515, +0x868A, +0x0807, +0x0519, +0x0C24, +0x869C, +0x0180, +0x7D00, +0x0181, +0x5555, +0x0182, +0x1446, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0018, +0xD9B6, +0x0807, +0x0531, +0x33FE, +0x0C1F, +0x0C63, +0x864B, +0x19AD, +0x2B47, +0x0180, +0x7D00, +0x0181, +0x5555, +0x0182, +0x1406, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0018, +0xD9B6, +0x0807, +0x054B, +0x33FE, +0x0C1F, +0x0C43, +0x864B, +0x0807, +0x054E, +0x868A, +0x31A5, +0x0801, +0x0020, +0x5023, +0x31A1, +0x080E, +0xFF00, +0x13F0, +0x33AE, +0x3180, +0x217A, +0x2348, +0x5581, +0x43ED, +0x31B8, +0x080D, +0x00FF, +0x542D, +0x55AC, +0x43ED, +0x31B9, +0x0800, +0x017A, +0x30AD, +0x0807, +0x056A, +0x0C24, +0x86B5, +0x080E, +0xFF00, +0x1BF0, +0x33AE, +0x2B48, +0x0800, +0x0348, +0x0801, +0x0347, +0x0807, +0x0576, +0x866E, +0x1B48, +0x080F, +0xFF00, +0x2BF0, +0x33AF, +0x0800, +0x0348, +0x0801, +0x0347, +0x0802, +0x017A, +0x0807, +0x0584, +0x868A, +0x0807, +0x0588, +0x0C24, +0x869C, +0x080E, +0xFF00, +0x1BEF, +0x080E, +0x00FF, +0x13EF, +0x33AE, +0x518D, +0x422D, +0x2B51, +0x080E, +0xFF00, +0x1BF0, +0x080E, +0x00FF, +0x13F0, +0x33AE, +0x518D, +0x422D, +0x2B52, +0x82DD, +0x0180, +0x7D00, +0x0181, +0xAAAA, +0x0182, +0x2846, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0011, +0xD9B6, +0x0807, +0x05B5, +0x33FE, +0x0C1F, +0x0C63, +0x864B, +0x19AD, +0x2B47, +0x0180, +0x7D00, +0x0181, +0xAAAA, +0x0182, +0x2806, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0011, +0xD9B6, +0x0807, +0x05CF, +0x33FE, +0x0C1F, +0x0C43, +0x864B, +0x0807, +0x05D2, +0x868A, +0x31A5, +0x0801, +0x0020, +0x5023, +0x134C, +0x3180, +0x2174, +0x2348, +0x558D, +0x43ED, +0x31B8, +0x0801, +0x0020, +0x5061, +0x0801, +0x00FF, +0x55A1, +0x55AC, +0x43ED, +0x31B9, +0x0800, +0x0174, +0x30AD, +0x0807, +0x05ED, +0x0C24, +0x86B5, +0x1B4C, +0x2B48, +0x0800, +0x0348, +0x0801, +0x0347, +0x0807, +0x05F6, +0x866E, +0x1B48, +0x2B4C, +0x0800, +0x0348, +0x0801, +0x0347, +0x0802, +0x0174, +0x0807, +0x0601, +0x868A, +0x0807, +0x0605, +0x0C24, +0x869C, +0x0180, +0x7D00, +0x0181, +0x5555, +0x0182, +0x1446, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0013, +0xD9B6, +0x0807, +0x061D, +0x33FE, +0x0C1F, +0x0C63, +0x864B, +0x19AD, +0x2B47, +0x0180, +0x7D00, +0x0181, +0x5555, +0x0182, +0x1406, +0xD183, +0x0184, +0x2C00, +0x0185, +0x6408, +0x0800, +0x01AD, +0x01AD, +0x0080, +0x01AF, +0x0013, +0xD9B6, +0x0807, +0x0637, +0x33FE, +0x0C1F, +0x0C43, +0x864B, +0x0807, +0x063A, +0x868A, +0x31A5, +0x0801, +0x0020, +0x5023, +0x134E, +0x3180, +0x2176, +0x2348, +0x558D, +0x43ED, +0x31B8, +0x0801, +0x0020, +0x5061, +0x0801, +0x00FF, +0x55A1, +0x55AC, +0x43ED, +0x31B9, +0x0800, +0x0176, +0x30AD, +0x0807, +0x0655, +0x0C24, +0x86B5, +0x1B4E, +0x2B48, +0x0800, +0x0348, +0x0801, +0x0347, +0x0807, +0x065E, +0x866E, +0x1B48, +0x2B4E, +0x0800, +0x0348, +0x0801, +0x0347, +0x0802, +0x0176, +0x0807, +0x0669, +0x868A, +0x0807, +0x066D, +0x0C24, +0x869C, +0x82E6, +0x19AD, +0x31A4, +0x3825, +0x5085, +0x31A5, +0x4225, +0x3C01, +0x338D, +0x55A5, +0xB67B, +0x330D, +0xA67E, +0x8689, +0xA682, +0x380D, +0x8689, +0x5E20, +0xB689, +0x3580, +0x8689, +0x332D, +0xA685, +0x8689, +0x5A20, +0x31A2, +0x430D, +0xA680, +0x9007, +0x080E, +0x1FE0, +0x196E, +0x33AE, +0x31A3, +0x080E, +0x1000, +0x196E, +0x33AE, +0x31A4, +0xA696, +0x869A, +0x080D, +0x0100, +0x546D, +0x31A3, +0x308D, +0x9007, +0xA6A0, +0x308D, +0xA6AA, +0x86A3, +0x308D, +0xA6A3, +0x86AA, +0x3805, +0x5065, +0x31A4, +0x430D, +0xA6B1, +0x308D, +0x86AE, +0x3805, +0x5465, +0xB6AE, +0x86B1, +0x3C02, +0x35A1, +0x86B2, +0x384D, +0x29AD, +0xD9B6, +0x9007, +0xA6B9, +0x308D, +0xA6C3, +0x86BC, +0x308D, +0xA6BC, +0x86C3, +0x3805, +0x5065, +0x31A4, +0x430D, +0xA6C9, +0x308D, +0x86C7, +0x3805, +0x5465, +0xB6C7, +0x86C9, +0x31BC, +0x86CA, +0x30BC, +0x9007, +0x0180, +0x00FF, +0x0181, +0xAAAA, +0x0182, +0x2806, +0x0183, +0x0800, +0x0184, +0x7060, +0x0185, +0x2402, +0x0160, +0x0C07, +0xD161, +0x0162, +0x00C6, +0x0163, +0x1000, +0xD164, +0x0165, +0x3000, +0x0166, +0x7828, +0x0167, +0x21A2, +0xD168, +0x1B38, +0xA712, +0x1BCC, +0x31A1, +0x1B51, +0x502D, +0x31A1, +0x0807, +0x06F0, +0x8DF4, +0xA6F3, +0x5061, +0x86F4, +0x5461, +0xB6F6, +0x86FE, +0x31A1, +0x430D, +0xA6FB, +0x302D, +0x86FF, +0x080D, +0x00FF, +0x86FF, +0x0C0D, +0x080F, +0x00FF, +0x2969, +0x33AF, +0x1BCD, +0x31A1, +0x1B52, +0x502D, +0x31A1, +0x080F, +0xFF00, +0x2969, +0x33AF, +0x6C00, +0x080E, +0xFF00, +0x197B, +0x33AE, +0x31B8, +0x0180, +0x00FF, +0x0162, +0x0084, +0x0165, +0xB000, +0x1B38, +0xA73B, +0x1B51, +0x31A1, +0x13CC, +0x0807, +0x0720, +0x8DF4, +0xA724, +0x5061, +0x558D, +0x8726, +0x506C, +0x55A1, +0x31A1, +0xB729, +0x8730, +0x430D, +0xA72D, +0x302D, +0x8731, +0x080D, +0x00FF, +0x8731, +0x0C0D, +0x080F, +0x00FF, +0x2969, +0x33AF, +0x6C00, +0x080E, +0xFF00, +0x197B, +0x33AE, +0x31B9, +0x0180, +0x00FF, +0x0181, +0x5555, +0x0182, +0x1406, +0x0162, +0x00C6, +0x0163, +0x2000, +0x0165, +0x3000, +0x080F, +0x03FF, +0xD960, +0x33AF, +0x1B38, +0xA759, +0x1352, +0x1B51, +0x55B8, +0x518D, +0x410D, +0x2969, +0x6C00, +0x080E, +0x00FF, +0x197B, +0x33AE, +0x31BA, +0x0180, +0x00FF, +0x0162, +0x0084, +0x0165, +0xB000, +0x080F, +0x03FF, +0xD960, +0x33AF, +0x1B38, +0xA793, +0x1352, +0x1B51, +0x55B9, +0x51AC, +0x410D, +0x2969, +0x6C00, +0x080E, +0x00FF, +0x197B, +0x33AE, +0x31BB, +0x0C2F, +0xDB75, +0x33AF, +0x0C6F, +0x010D, +0x0002, +0x33AF, +0xD3A6, +0x03A6, +0x000A, +0x5738, +0x424D, +0x532D, +0xD9AE, +0x29AD, +0x01AF, +0x0016, +0xD9B6, +0x577A, +0x424D, +0x536D, +0x29AD, +0x01AF, +0x0018, +0xD9B6, +0xD1AE, +0xD3A6, +0x7000, +0x0C6F, +0xD10D, +0x33AF, +0x0C2F, +0xD375, +0x33AF, +0x0180, +0x01FF, +0x0181, +0xFFFF, +0x0182, +0x3C86, +0xD183, +0x0160, +0x0C10, +0x0161, +0x0009, +0x0162, +0x00C2, +0xD163, +0xD165, +0x0166, +0x792B, +0x0168, +0x4925, +0x1B38, +0xA82D, +0x0807, +0x07AD, +0x33FE, +0x0C1F, +0x89C5, +0x1959, +0x1959, +0x31B6, +0x0807, +0x07B3, +0x8931, +0x081C, +0x0349, +0x0EA1, +0x0C17, +0x3B85, +0x080D, +0x002F, +0x5C2D, +0x54AD, +0xB7BE, +0x87F9, +0x302D, +0xA7C1, +0x87F9, +0x3B85, +0x0CED, +0x54AD, +0xA7C6, +0x87DB, +0x0DED, +0x54AD, +0xA7CA, +0x87DB, +0x0EED, +0x54AD, +0xA7CE, +0x87DB, +0x0FED, +0x54AD, +0xA7D2, +0x87DB, +0x080D, +0x0027, +0x54AD, +0xA7D7, +0x87DB, +0x5C21, +0x31A1, +0x5837, +0x31B7, +0x5A3C, +0x1B4A, +0x29B4, +0xD9B8, +0x1959, +0x1959, +0x31A2, +0x5444, +0xB7E5, +0x87F9, +0x5462, +0xB7E8, +0x87F9, +0x6620, +0x080E, +0x7FFF, +0x1988, +0x33AE, +0x31A2, +0x4022, +0x080E, +0x7FFF, +0x1986, +0x33AE, +0x31A5, +0x4025, +0x426D, +0x55A5, +0x55A2, +0xB7B7, +0x32E0, +0x3B81, +0x1B47, +0x55A1, +0xA7FF, +0x8807, +0xB802, +0x5A3C, +0x8803, +0x5E3C, +0x1B4A, +0x29B4, +0xD9B8, +0x87FA, +0x0C17, +0x1959, +0x1959, +0x31A2, +0x5444, +0xB80E, +0x8810, +0x5462, +0xB813, +0x0807, +0x0813, +0x8917, +0x1959, +0x1959, +0x31A2, +0x5444, +0xB81F, +0x5E3C, +0x1B4A, +0x29B4, +0xD9B8, +0x5E3C, +0x5857, +0x8827, +0x5462, +0xB82D, +0x5A3C, +0x1B4A, +0x29B4, +0xD9B8, +0x5A3C, +0x5840, +0x1B4A, +0x29B4, +0xD9B8, +0x0807, +0x082D, +0x8917, +0x0180, +0x01FF, +0x0182, +0x3CC6, +0x1B38, +0xA8BF, +0x0807, +0x0838, +0x33FE, +0x0C1F, +0x89C5, +0x0C2F, +0xDB75, +0x33AF, +0x0C6F, +0x010D, +0x0002, +0x33AF, +0xD3A6, +0x03A6, +0x000A, +0x5738, +0x424D, +0x55B8, +0xD9AE, +0x29AD, +0x01AF, +0x0016, +0xD9B6, +0x577A, +0x424D, +0x55BA, +0x29AD, +0x01AF, +0x0018, +0xD9B6, +0xD1AE, +0xD3A6, +0x7000, +0x0C6F, +0xD10D, +0x33AF, +0x0C2F, +0xD375, +0x33AF, +0x081C, +0x0349, +0x0EA1, +0x3B85, +0x0C0D, +0x582D, +0x55A5, +0xB863, +0x889C, +0x302D, +0xA866, +0x889C, +0x3B85, +0x0D0D, +0x54AD, +0xA86B, +0x8881, +0x0E0D, +0x54AD, +0xA86F, +0x8881, +0x0F0D, +0x54AD, +0xA873, +0x8881, +0x080D, +0x0020, +0x54AD, +0xA878, +0x8881, +0x080D, +0x0028, +0x54AD, +0xA87D, +0x8881, +0x5C21, +0x31A1, +0x5837, +0x31B7, +0x5E3C, +0x1B4A, +0x29B4, +0xD9B8, +0x1959, +0x1959, +0x31A2, +0x5444, +0xB88B, +0x889C, +0x5462, +0xB88E, +0x889C, +0x6620, +0x080E, +0x7FFF, +0x1988, +0x33AE, +0x31A2, +0x4022, +0x080E, +0x7FFF, +0x1986, +0x33AE, +0x426D, +0x544D, +0xB85D, +0x32ED, +0x300D, +0x080F, +0xFF00, +0x2BEA, +0x33AF, +0x32ED, +0x080F, +0x00FF, +0x2BEA, +0x33AF, +0x56E0, +0xB8B5, +0x5417, +0x5C2D, +0x422D, +0x31A0, +0x5C6D, +0xB8B3, +0x0C6C, +0x540C, +0x31AC, +0x88B9, +0x0C0C, +0x88BE, +0x582D, +0x422D, +0x586D, +0x31AC, +0x5D2D, +0xB8BC, +0x88BE, +0x0D2C, +0x88BE, +0x8998, +0x1B38, +0xA8D3, +0x3B8D, +0x331C, +0x31B8, +0x2B7B, +0x0807, +0x08C9, +0x32CD, +0x8931, +0x1959, +0x1959, +0x31A2, +0x5482, +0xB8D0, +0x5462, +0xB8D3, +0x0807, +0x08D3, +0x8917, +0x0807, +0x08D6, +0x8DF4, +0x31A2, +0xA8E0, +0x573C, +0xB8DC, +0x462D, +0x88DD, +0x422D, +0x532D, +0x546D, +0x88E7, +0x573C, +0xB8E4, +0x462D, +0x88E5, +0x422D, +0x532D, +0x506D, +0x31A1, +0xB8EB, +0x0C0D, +0x88F1, +0x430D, +0xA8EF, +0x302D, +0x88F1, +0x080D, +0x00FF, +0x080F, +0x00FF, +0x2BE8, +0x33AF, +0x304D, +0xA8FF, +0x577A, +0xB8FB, +0x462D, +0x88FC, +0x422D, +0x536D, +0x546D, +0x8906, +0x577A, +0xB903, +0x462D, +0x8904, +0x422D, +0x536D, +0x506D, +0x31A1, +0xB90A, +0x0C0D, +0x8910, +0x430D, +0xA90E, +0x302D, +0x8910, +0x080D, +0x00FF, +0x080F, +0xFF00, +0x2BE8, +0x33AF, +0x0C1F, +0x33FE, +0x88EC, +0x32CD, +0x2959, +0x080F, +0x0020, +0xD906, +0x33AF, +0x0E0F, +0xD106, +0x33AF, +0x0C8E, +0x1919, +0x33AE, +0xA920, +0x0E0F, +0xD906, +0x33AF, +0x0C8E, +0x1919, +0x33AE, +0xA92C, +0x8927, +0x080F, +0x0020, +0xD106, +0x33AF, +0x9007, +0x31A0, +0x0803, +0x1000, +0x546D, +0xB938, +0x0C03, +0x8939, +0x31A3, +0x0804, +0x1000, +0x5080, +0x31A0, +0x0804, +0x4000, +0x55A4, +0xB944, +0x0804, +0x4000, +0x8945, +0x3004, +0x9007, +0x1B53, +0x31A5, +0x3181, +0x302D, +0xA94C, +0x8965, +0x0CED, +0x54AD, +0xA950, +0x8963, +0x0DED, +0x54AD, +0xA954, +0x8963, +0x0EED, +0x54AD, +0xA958, +0x8963, +0x0FED, +0x54AD, +0xA95C, +0x8963, +0x080D, +0x0027, +0x54AD, +0xA961, +0x8963, +0x5C21, +0x31A1, +0x5825, +0x8949, +0x1B49, +0x31A0, +0x54AD, +0xB981, +0x5405, +0x31A1, +0x081C, +0x0349, +0x3B85, +0x080D, +0x002F, +0x5C2D, +0x54AD, +0xB974, +0x897E, +0x302D, +0xA977, +0x897E, +0x5C21, +0x31A1, +0x5A3C, +0x1B4A, +0x29B4, +0xD9B8, +0x896D, +0x0C1F, +0x33FE, +0x8721, +0x54A0, +0x31A1, +0x081C, +0x0349, +0x3B85, +0x0C0D, +0x582D, +0x55A5, +0xB98B, +0x8995, +0x302D, +0xA98E, +0x8995, +0x5C21, +0x31A1, +0x5E3C, +0x1B4A, +0x29B4, +0xD9B8, +0x8985, +0x0C1F, +0x33FE, +0x8721, +0x1B53, +0x31A5, +0x3181, +0x302D, +0xA99E, +0x89B7, +0x0CED, +0x54AD, +0xA9A2, +0x89B5, +0x0DED, +0x54AD, +0xA9A6, +0x89B5, +0x0EED, +0x54AD, +0xA9AA, +0x89B5, +0x0FED, +0x54AD, +0xA9AE, +0x89B5, +0x080D, +0x0027, +0x54AD, +0xA9B3, +0x89B5, +0x5C21, +0x31A1, +0x5825, +0x899B, +0x1B49, +0x31A0, +0x54AD, +0xB9D1, +0x5405, +0x31A1, +0x081C, +0x0349, +0x3B85, +0x080D, +0x002F, +0x5C2D, +0x54AD, +0xB9C6, +0x89D0, +0x302D, +0xA9C9, +0x89D0, +0x5C21, +0x31A1, +0x5A3C, +0x1B4A, +0x29B4, +0xD9B8, +0x89BF, +0x88BF, +0x54A0, +0x31A1, +0x081C, +0x0349, +0x3B85, +0x0C0D, +0x582D, +0x55A5, +0xB9DB, +0x89E5, +0x302D, +0xA9DE, +0x89E5, +0x5C21, +0x31A1, +0x5E3C, +0x1B4A, +0x29B4, +0xD9B8, +0x89D5, +0x88BF, +0x0180, +0x00FF, +0x0181, +0xAAAA, +0x0182, +0x2806, +0x0183, +0x0800, +0x0184, +0x7060, +0x0185, +0x2402, +0x300D, +0x080F, +0x03E0, +0x2982, +0x33AF, +0x0FEF, +0x0182, +0x0006, +0x33AF, +0x080F, +0x0800, +0xD183, +0x33AF, +0x0160, +0x0C07, +0xD161, +0x0162, +0x00C6, +0x0163, +0x1000, +0xD164, +0x0165, +0x3000, +0x0166, +0x7828, +0x0167, +0x21A2, +0xD168, +0x302D, +0x080F, +0xF000, +0x2965, +0x33AF, +0x304D, +0x080F, +0x03FF, +0x2960, +0x33AF, +0x306D, +0xAA4B, +0x300D, +0x5CCD, +0xAA1E, +0x8A21, +0x300D, +0x5C4D, +0xAA33, +0x1B51, +0x13CC, +0x518D, +0x31B7, +0x430D, +0xAA2B, +0x32ED, +0xBA2D, +0x0C17, +0x8A2D, +0x0817, +0x00FF, +0x32ED, +0x080F, +0x00FF, +0x2969, +0x33AF, +0x8A50, +0x300D, +0x5C8D, +0xAA37, +0x8A39, +0x300D, +0xAA50, +0x1B51, +0x13CC, +0x558D, +0x31B7, +0xBA40, +0x0C17, +0x8A45, +0x430D, +0xAA43, +0x8A45, +0x0817, +0x00FF, +0x32ED, +0x080F, +0x00FF, +0x2969, +0x33AF, +0x8A50, +0x308D, +0x080F, +0x00FF, +0x2969, +0x33AF, +0x6C00, +0x080E, +0xFF00, +0x197B, +0x33AE, +0x0C1F, +0x9007, +0x0180, +0x00FF, +0x0181, +0x5555, +0x0182, +0x1406, +0x0183, +0x0800, +0x0184, +0x7060, +0x0185, +0x2402, +0x300D, +0x080F, +0x03E0, +0x2982, +0x33AF, +0x0FEF, +0x0182, +0x0006, +0x33AF, +0x080F, +0x0800, +0xD183, +0x33AF, +0x0160, +0x0C07, +0xD161, +0x0162, +0x00C6, +0x0163, +0x2000, +0xD164, +0x0165, +0x3000, +0x0166, +0x7828, +0x0167, +0x21A2, +0xD168, +0x302D, +0x080F, +0xF000, +0x2965, +0x33AF, +0x304D, +0x080F, +0x03FF, +0x2960, +0x33AF, +0x306D, +0xAABC, +0x300D, +0x5CCD, +0xAA8F, +0x8A92, +0x300D, +0x5C4D, +0xAAA4, +0x1B52, +0x13CD, +0x518D, +0x31B7, +0x430D, +0xAA9C, +0x32ED, +0xBA9E, +0x0C17, +0x8A9E, +0x0817, +0x00FF, +0x32ED, +0x080F, +0xFF00, +0x2969, +0x33AF, +0x8AC1, +0x300D, +0x5C8D, +0xAAA8, +0x8AAA, +0x300D, +0xAAC1, +0x1B52, +0x13CD, +0x558D, +0x31B7, +0xBAB1, +0x0C17, +0x8AB6, +0x430D, +0xAAB4, +0x8AB6, +0x0817, +0x00FF, +0x32ED, +0x080F, +0xFF00, +0x2969, +0x33AF, +0x8AC1, +0x308D, +0x080F, +0xFF00, +0x2969, +0x33AF, +0x6C00, +0x080E, +0x00FF, +0x197B, +0x33AE, +0x0C1F, +0x9007, +0x0800, +0x00F5, +0x5418, +0xBACF, +0x5419, +0xBACF, +0x8AD5, +0x080F, +0x1C00, +0x03F6, +0x0003, +0x33AF, +0x8AE3, +0x541A, +0xBADE, +0x541B, +0xBADE, +0x080F, +0x1C00, +0xD3F6, +0x33AF, +0x8AE3, +0x080F, +0x1C00, +0x03F6, +0x0005, +0x33AF, +0x0800, +0x00F5, +0x5418, +0xBAEA, +0x541A, +0xBAEA, +0x8AF3, +0x5419, +0xBAF3, +0x541B, +0xBAF3, +0x080F, +0x6000, +0xDBF6, +0x33AF, +0x8B0F, +0x5419, +0xBAF8, +0x541B, +0xBAF8, +0x8B02, +0x5418, +0xBB02, +0x541A, +0xBB02, +0x080F, +0x6000, +0x03F6, +0x0002, +0x33AF, +0x8B0F, +0x571A, +0xBB06, +0x3302, +0x8B07, +0x3342, +0x573B, +0xBB0B, +0x3323, +0x8B0C, +0x3363, +0x5443, +0xBAFC, +0x8AEE, +0x0C1F, +0x9007, +0x080E, +0x6000, +0x1BF6, +0x33AE, +0x5C2D, +0xAB1C, +0x1352, +0x5379, +0x422D, +0x558D, +0x8B27, +0x080E, +0x6000, +0x1BF6, +0x33AE, +0x5C4D, +0xAB27, +0x1351, +0x5358, +0x422D, +0x558D, +0x8B27, +0xBB2C, +0x410D, +0x430D, +0x31B7, +0x8B32, +0x31B7, +0x430D, +0xAB30, +0x8B32, +0x0817, +0x00FF, +0x0C1F, +0x9007, +0x080E, +0x00FF, +0x196B, +0x33AE, +0x42AD, +0x0CEF, +0x290B, +0x33AF, +0x080E, +0x03E0, +0x196D, +0x33AE, +0x080F, +0xF800, +0x290B, +0x33AF, +0x080E, +0x1C00, +0x196D, +0x33AE, +0x0CEF, +0x290C, +0x33AF, +0x080E, +0x03C0, +0x196C, +0x33AE, +0x31A0, +0x080F, +0x0078, +0x290B, +0x33AF, +0x080E, +0x003F, +0x196C, +0x33AE, +0xAB5A, +0x8B5C, +0x5820, +0x31A0, +0x300D, +0x080F, +0x0780, +0x290B, +0x33AF, +0x32ED, +0x080F, +0x07F8, +0x290C, +0x33AF, +0x080E, +0x0FFF, +0x196F, +0x33AE, +0x42AD, +0x080F, +0x007F, +0x291A, +0x33AF, +0x080E, +0x0FFF, +0x1970, +0x33AE, +0x42AD, +0x080F, +0x3F80, +0x291A, +0x33AF, +0x080E, +0x0FFF, +0x1971, +0x33AE, +0x42AD, +0x080F, +0x007F, +0x291B, +0x33AF, +0x080E, +0x0FFF, +0x1972, +0x33AE, +0x42AD, +0x080F, +0x3F80, +0x291B, +0x33AF, +0x080F, +0x0800, +0xD90C, +0x33AF, +0x0C4F, +0xD90D, +0x33AF, +0x0306, +0x000C, +0x0C2E, +0x1919, +0x33AE, +0xAB98, +0x8B93, +0x0306, +0x0008, +0x080F, +0x0800, +0xD10C, +0x33AF, +0x0C4F, +0xD10D, +0x33AF, +0x0C1F, +0x9007, +0x080E, +0x0020, +0x1B6F, +0x33AE, +0xABF4, +0x8BF7, +0x1B53, +0x31A1, +0x1B49, +0x31B7, +0x0802, +0x0349, +0x0C25, +0x0807, +0x0BB3, +0x8C0F, +0x0180, +0x003F, +0x0181, +0xAAAA, +0x0182, +0x2802, +0x0183, +0x0800, +0x0184, +0x7060, +0x0185, +0x2402, +0x0807, +0x0BC4, +0x33FE, +0x0C1F, +0x89C5, +0x0160, +0x0C07, +0xD161, +0x0162, +0x0042, +0x0163, +0x3000, +0xD164, +0x0165, +0x3000, +0x0166, +0x7828, +0x0167, +0x21A2, +0xD168, +0x330D, +0x410D, +0x530D, +0x2969, +0x6E00, +0x197B, +0x430D, +0x31BA, +0xD162, +0x0165, +0xB000, +0x332D, +0x410D, +0x532D, +0x2969, +0x6E00, +0x197B, +0x430D, +0x31BB, +0x577A, +0xBBE9, +0x0C0D, +0x080F, +0x00FF, +0x2BE9, +0x33AE, +0x32E1, +0x0C05, +0x0802, +0x0349, +0x0807, +0x0BF4, +0x8C0F, +0x33FE, +0x0C1F, +0x87EA, +0x1BF2, +0x5C4D, +0xABFD, +0x1B52, +0x13CD, +0x8BFF, +0x1B51, +0x13CC, +0x31A1, +0x518D, +0x31A0, +0x430D, +0xAC06, +0x300D, +0x8C08, +0x080D, +0x00FF, +0x31B8, +0x302D, +0x558D, +0xBC0D, +0x0C0D, +0x31B9, +0x8BA9, +0x1B49, +0x31A0, +0x30AD, +0xAC18, +0x5401, +0xAC16, +0x8C24, +0xBC1D, +0x8C24, +0x5420, +0xAC1B, +0x8C24, +0xBC1F, +0x8C24, +0x5A22, +0x8C20, +0x5E22, +0x1B4A, +0x29B4, +0xD9B8, +0x8C0F, +0x9007, +0x080F, +0xFF00, +0xD3E9, +0x33AF, +0x080E, +0x00FF, +0x13E8, +0x33AE, +0x0D4D, +0x518D, +0x31A2, +0x080E, +0xFF00, +0x13E8, +0x33AE, +0x0D4D, +0x518D, +0x31A5, +0x0807, +0x0C3A, +0x8DF4, +0xAC40, +0x5062, +0x31A2, +0x5065, +0x31A5, +0x8C48, +0x5462, +0x31A2, +0xBC44, +0x0C02, +0x5465, +0x31A5, +0xBC48, +0x0C05, +0x304D, +0x430D, +0xAC4C, +0x8C4E, +0x0802, +0x00FF, +0x30AD, +0x430D, +0xAC52, +0x8C54, +0x0805, +0x00FF, +0x0807, +0x0C57, +0x8CCB, +0x0800, +0x0349, +0x0802, +0x034A, +0x0803, +0x01B4, +0x3818, +0x0C01, +0x0CA4, +0x0C37, +0x0807, +0x0C64, +0x8D18, +0x080F, +0x03E0, +0x0182, +0x0006, +0x33AF, +0x0807, +0x0C6C, +0x8CD9, +0x080E, +0x00FF, +0x13E8, +0x33AE, +0x0D4D, +0x55AC, +0x31A2, +0x080E, +0xFF00, +0x13E8, +0x33AE, +0x0D4D, +0x55AC, +0x31A5, +0x0807, +0x0C7D, +0x8DF4, +0xAC83, +0x5062, +0x31A2, +0x5065, +0x31A5, +0x8C8B, +0x5462, +0x31A2, +0xBC87, +0x0C02, +0x5465, +0x31A5, +0xBC8B, +0x0C05, +0x0C0D, +0x304D, +0x43ED, +0xAC96, +0x304D, +0x430D, +0xAC93, +0x8C97, +0x0802, +0x00FF, +0x8C97, +0x0C02, +0x30AD, +0x43ED, +0xACA1, +0x30AD, +0x430D, +0xAC9E, +0x8CA2, +0x0805, +0x00FF, +0x8CA2, +0x0C05, +0x0807, +0x0CA5, +0x8CCB, +0x0800, +0x0349, +0x0802, +0x034A, +0x0803, +0x01B4, +0x3818, +0x0801, +0x002F, +0x0D44, +0x0C17, +0x0807, +0x0CB3, +0x8D18, +0x080F, +0x03E0, +0x0182, +0x0004, +0x33AF, +0x0807, +0x0CBB, +0x8CD9, +0x0800, +0x0349, +0x0802, +0x034A, +0x0803, +0x01B4, +0x3818, +0x0C01, +0x0CA4, +0x0C37, +0x0807, +0x0CC8, +0x8D18, +0x33FE, +0x0C1F, +0x896A, +0xD9AE, +0x01AF, +0x0016, +0x304D, +0x29AD, +0xD9B6, +0x01AF, +0x0018, +0x30AD, +0x29AD, +0xD9B6, +0x700F, +0xD1AE, +0x9007, +0x080F, +0x7FFF, +0x0180, +0x07CF, +0x33AF, +0x0181, +0xFFFF, +0x0FEF, +0x0182, +0x0006, +0x080F, +0x4000, +0xD984, +0x080F, +0x1C00, +0x0184, +0x0004, +0x080F, +0x0020, +0xD984, +0x0F0F, +0xD184, +0x33AF, +0x080F, +0x03C0, +0xD184, +0x33AF, +0x080F, +0x0800, +0xD183, +0x33AF, +0x0E81, +0x6660, +0x080E, +0x7FFF, +0x198A, +0x33AE, +0x31A2, +0x080E, +0x7FFF, +0x1986, +0x33AE, +0x544D, +0x31A2, +0x080E, +0xFF00, +0x1BE9, +0x33AE, +0x504D, +0x31A2, +0x430D, +0xAD0E, +0x8D10, +0x0802, +0x00FF, +0x304D, +0x080F, +0xFF00, +0x2BE9, +0x33AF, +0x5C21, +0xACF9, +0x9007, +0x3805, +0x0CED, +0x52ED, +0x54AD, +0xAD1E, +0x8D39, +0x0DED, +0x52ED, +0x54AD, +0xAD23, +0x8D39, +0x0EED, +0x52ED, +0x54AD, +0xAD28, +0x8D39, +0x0FED, +0x52ED, +0x54AD, +0xAD2D, +0x8D39, +0x080D, +0x0027, +0x52ED, +0x54AD, +0xAD33, +0x8D39, +0x308D, +0xAD36, +0x8D46, +0x5C24, +0x31A4, +0x8D3E, +0x32ED, +0xAD3E, +0x308D, +0xAD3E, +0x8D46, +0x32ED, +0xAD42, +0x5A20, +0x8D43, +0x5E20, +0x3C43, +0xD9B8, +0x8D18, +0x9007, +0x1959, +0x1959, +0x31A1, +0x0800, +0x3000, +0x5401, +0xBD54, +0x0800, +0x1000, +0x5420, +0xBD54, +0x0C25, +0x8D5C, +0x1B5E, +0xAD59, +0x0807, +0x0D59, +0x8917, +0x0C05, +0x0C04, +0x8DEC, +0x080E, +0x00FF, +0x1BE9, +0x33AE, +0x31A0, +0x080E, +0xFF00, +0x13EA, +0x080E, +0x00FF, +0x1BEA, +0x33AE, +0x51AC, +0xBD6C, +0x0C01, +0x8D73, +0x31A1, +0x0804, +0x002A, +0x55A4, +0xBD73, +0x0801, +0x002A, +0x302D, +0x080F, +0x00FF, +0x2BEB, +0x33AF, +0x0807, +0x0D7B, +0x8DF4, +0xAD7E, +0x0C03, +0x8D7F, +0x4223, +0x080E, +0x0FE0, +0x196F, +0x33AE, +0x31A2, +0x0804, +0x0040, +0x5482, +0xBD89, +0x0C0D, +0x31A2, +0x4222, +0x5062, +0x55A0, +0x31A0, +0x0C04, +0x0C2E, +0x1BEB, +0xAD93, +0x8D96, +0x300D, +0x51A4, +0x31A4, +0x0C4E, +0x1BEB, +0xAD9A, +0x8D9E, +0x300D, +0x442D, +0x51A4, +0x31A4, +0x0C8E, +0x1BEB, +0xADA2, +0x8DA6, +0x300D, +0x444D, +0x51A4, +0x31A4, +0x0D0E, +0x1BEB, +0xADAA, +0x8DAE, +0x300D, +0x446D, +0x51A4, +0x31A4, +0x0E0E, +0x1BEB, +0xADB2, +0x8DB6, +0x300D, +0x448D, +0x51A4, +0x31A4, +0x080E, +0x0020, +0x1BEB, +0xADBB, +0x8DBF, +0x300D, +0x44AD, +0x51A4, +0x31A4, +0x33AE, +0x308D, +0x46AD, +0x31A4, +0x080E, +0xFF00, +0x1BE9, +0x33AE, +0x31A1, +0x1B5E, +0xADDC, +0x0CA0, +0x5401, +0xBDD0, +0x0805, +0x0060, +0x8DDD, +0x0D40, +0x5401, +0xBDD6, +0x0805, +0x0040, +0x8DDD, +0x0DE0, +0x5401, +0xBDDC, +0x0805, +0x0020, +0x8DDD, +0x0C05, +0x5085, +0x31A4, +0x0C0D, +0x308D, +0x43ED, +0xADE4, +0x8DE6, +0x0C04, +0x8DEC, +0x308D, +0x430D, +0xADEA, +0x8DEC, +0x0804, +0x00FF, +0x1B5E, +0xADF2, +0x308D, +0x33FE, +0x0C1F, +0x8972, +0x308D, +0x8048, +0x080E, +0x1FE0, +0x196E, +0x33AE, +0x31A3, +0x080E, +0x1000, +0x196E, +0x33AE, +0x31A4, +0xAE00, +0x8E04, +0x080D, +0x0100, +0x546D, +0x31A3, +0x308D, +0x9007, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000 From 79c73e2fb579dcea505d763e914dbe168d064d7a Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Wed, 30 Nov 2022 18:01:39 +0800 Subject: [PATCH 212/235] arm64: dts: rockchip: rk3588-h0: Set clkreq as gpio property The clkreq is recommended: 1.Set as gpio property 2.Set as function io with supports-clkreq property enable Change-Id: Idc72fa9190a3ec51876f3f5dce09d7e7a5201009 Signed-off-by: Jon Lin --- arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi index e8130f133afc..2ff1c7629638 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-h0.dtsi @@ -695,11 +695,10 @@ }; &pcie3x4 { - reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; vpcie3v3-supply = <&vcc3v3_pcie30>; pinctrl-names = "default"; pinctrl-0 = <&pcie20x1_0_clkreqn_m1>; - supports-clkreq; status = "okay"; }; @@ -809,7 +808,7 @@ pcie { pcie20x1_0_clkreqn_m1: pcie20x1-0-clkreqn-m1 { - rockchip,pins = <4 RK_PB4 4 &pcfg_pull_up>; + rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_output_low>; }; }; }; From d2293b5e0c54d7f3f8219a31a42d65b635ee6d46 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Thu, 1 Dec 2022 14:49:09 +0800 Subject: [PATCH 213/235] media: rockchip: vicap do dma reset before dma capture enable Signed-off-by: Zefa Chen Change-Id: I0450794d584bb7918e1c1e21f099ee649e76d736 --- drivers/media/platform/rockchip/cif/capture.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 740e3dab25d1..6ead58576621 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -8610,13 +8610,12 @@ void rkcif_enable_dma_capture(struct rkcif_stream *stream, bool is_only_enable) RKCIF_YUV_ADDR_STATE_INIT, stream->id); } - } else if (stream->cur_stream_mode == RKCIF_STREAM_MODE_CAPTURE) { - if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || - mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) - rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000); - else - rkcif_write_register_or(cif_dev, CIF_REG_DVP_CTRL, 0x000A0000); } + if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || + mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) + rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, 0x00010000); + else + rkcif_write_register_or(cif_dev, CIF_REG_DVP_CTRL, 0x00010000); if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) { val = rkcif_read_register(cif_dev, get_reg_index_of_id_ctrl0(stream->id)); From 6564f48d22992bc3a353b47f7644d315efc3d1a9 Mon Sep 17 00:00:00 2001 From: Su Yuefu Date: Thu, 1 Dec 2022 16:48:34 +0800 Subject: [PATCH 214/235] media: rockchip: fix vicap captures raw not responding caused by commit of thunderboot support be07e90202262ebfe8b008e7ec5b0142ee54a99c Signed-off-by: Su Yuefu Change-Id: I54c19bd9084a004bb15fc6f9054138f2c81ff059 --- drivers/media/platform/rockchip/cif/subdev-itf.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 5b5a065db6b7..d37a5a713689 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -531,12 +531,22 @@ void sditf_change_to_online(struct sditf_priv *priv) sditf_channel_enable(priv, 0); sditf_channel_enable(priv, 1); } - if (priv->hdr_cfg.hdr_mode == NO_HDR) + 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) + cif_dev->stream[0].is_line_wake_up = false; + } 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) + cif_dev->stream[0].is_line_wake_up = false; + cif_dev->stream[1].is_line_wake_up = false; + } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { rkcif_free_rx_buf(&cif_dev->stream[2], priv->buf_num); + cif_dev->stream[0].is_line_wake_up = false; + cif_dev->stream[1].is_line_wake_up = false; + cif_dev->stream[2].is_line_wake_up = false; + } + cif_dev->wait_line_cache = 0; + cif_dev->wait_line = 0; + cif_dev->wait_line_bak = 0; } static void sditf_check_capture_mode(struct rkcif_device *cif_dev) From 25cbf08d91ede330ce226b03c947e3401ad7fbb7 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Tue, 6 Dec 2022 15:33:10 +0800 Subject: [PATCH 215/235] media: rockchip: isp: fix rockit stream pause if readback mode Change-Id: I8482c9cd365f34adbb6ded979cd4d58d4b299776 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/capture_v32.c | 3 ++- drivers/media/platform/rockchip/isp/isp_rockit.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index b3b35eb327bf..6ef94a149be3 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -1357,7 +1357,8 @@ static int rkisp_start(struct rkisp_stream *stream) if (ret) return ret; } - stream_self_update(stream); + if (dev->hw_dev->is_single) + stream_self_update(stream); if (stream->ops->enable_mi) stream->ops->enable_mi(stream); diff --git a/drivers/media/platform/rockchip/isp/isp_rockit.c b/drivers/media/platform/rockchip/isp/isp_rockit.c index 149fbda73376..32fed276e21f 100644 --- a/drivers/media/platform/rockchip/isp/isp_rockit.c +++ b/drivers/media/platform/rockchip/isp/isp_rockit.c @@ -369,6 +369,10 @@ int rkisp_rockit_resume_stream(struct rockit_cfg *input_rockit_cfg) pr_err("stream id %d start failed\n", stream->id); return -EINVAL; } + if (stream->ispdev->isp_state == ISP_STOP) { + stream->ispdev->isp_state = ISP_START; + rkisp_rdbk_trigger_event(stream->ispdev, T_CMD_QUEUE, NULL); + } return 0; } From 657133eb06196181b299e635dfbfc51f0f39a87f Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Mon, 6 Jun 2022 17:43:55 +0800 Subject: [PATCH 216/235] ARM: dts: rockchip: rk3036: add tve node Signed-off-by: Damon Ding Change-Id: Ia912356862fc30ad79506dc75c9bc105ca3bba6e --- arch/arm/boot/dts/rk3036.dtsi | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi index d912da5316eb..98427574b674 100644 --- a/arch/arm/boot/dts/rk3036.dtsi +++ b/arch/arm/boot/dts/rk3036.dtsi @@ -295,6 +295,37 @@ reg = <0>; remote-endpoint = <&hdmi_in_vop>; }; + vop_out_tve: endpoint@1 { + reg = <1>; + remote-endpoint = <&tve_in_vop>; + }; + }; + }; + + tve: tve@10118200 { + compatible = "rockchip,rk3036-tve"; + reg = <0x10118200 0x100>; + clocks = <&cru ACLK_VIO>; + clock-names = "aclk"; + rockchip,saturation = <0x00386346>; + rockchip,brightcontrast = <0x00008b00>; + rockchip,adjtiming = <0xa6c00880>; + rockchip,lumafilter0 = <0x02ff0000>; + rockchip,lumafilter1 = <0xf40202fd>; + rockchip,lumafilter2 = <0xf332d919>; + rockchip,daclevel = <0x3e>; + rockchip,grf = <&grf>; + status = "disabled"; + + ports { + tve_in: port { + #address-cells = <1>; + #size-cells = <0>; + tve_in_vop: endpoint@0 { + reg = <0>; + remote-endpoint = <&vop_out_tve>; + }; + }; }; }; From 7ffd80939ab48275b0d5d182462f2325c7671d36 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Wed, 1 Jun 2022 22:03:26 +0800 Subject: [PATCH 217/235] drm/rockchip: tve: add tve support for rk3036/rk312x/rk322x The related codes are ported from kernel-3.10. Tve interface function has been tested on rk3036/rk3128/rk3228. Signed-off-by: Damon Ding Change-Id: I5395bdccd7c645dfd34e9ccf166f3c94086e3134 --- drivers/gpu/drm/rockchip/rockchip_drm_tve.c | 198 ++++++++++++++------ drivers/gpu/drm/rockchip/rockchip_drm_tve.h | 15 +- 2 files changed, 154 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c index 5039b877385b..e919b57d1cb2 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c @@ -1,17 +1,20 @@ /* SPDX-License-Identifier: GPL-2.0 */ #include +#include #include #include #include #include +#include #include #include #include +#include -#include #include #include #include +#include #include @@ -26,23 +29,31 @@ static const struct drm_display_mode cvbs_mode[] = { 816, 864, 0, 576, 580, 586, 625, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - .vrefresh = 50, 0, }, + 0, }, { DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, 720, 753, 815, 858, 0, 480, 480, 486, 525, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK), - .vrefresh = 60, 0, }, + 0, }, }; -#define tve_writel(offset, v) writel_relaxed(v, tve->regbase + (offset)) -#define tve_readl(offset) readl_relaxed(tve->regbase + (offset)) +#define tve_writel(offset, v) writel_relaxed(v, tve->regbase + (offset)) +#define tve_readl(offset) readl_relaxed(tve->regbase + (offset)) -#define tve_dac_writel(offset, v) writel_relaxed(v, tve->vdacbase + (offset)) -#define tve_dac_readl(offset) readl_relaxed(tve->vdacbase + (offset)) +#define tve_dac_writel(offset, v) writel_relaxed(v, tve->vdacbase + (offset)) +#define tve_dac_readl(offset) readl_relaxed(tve->vdacbase + (offset)) -#define connector_to_tve(x) container_of(x, struct rockchip_tve, connector) -#define encoder_to_tve(x) container_of(x, struct rockchip_tve, encoder) +#define tve_dac_grf_writel(offset, v) regmap_write(tve->dac_grf, offset, v) +#define tve_dac_grf_readl(offset, v) regmap_read(tve->dac_grf, offset, v) + +#define connector_to_tve(x) container_of(x, struct rockchip_tve, connector) +#define encoder_to_tve(x) container_of(x, struct rockchip_tve, encoder) + +struct rockchip_tve_data { + int input_format; + int soc_type; +}; static int rockchip_tve_get_modes(struct drm_connector *connector) @@ -99,7 +110,7 @@ static void tve_set_mode(struct rockchip_tve *tve) int mode = tve->tv_format; dev_dbg(tve->dev, "tve set mode:%d\n", mode); - if (tve->inputformat == INPUT_FORMAT_RGB) + if (tve->input_format == INPUT_FORMAT_RGB) tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) | v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) | v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(0)); @@ -164,17 +175,38 @@ static void dac_init(struct rockchip_tve *tve) static void dac_enable(struct rockchip_tve *tve, bool enable) { - u32 val; + u32 mask = 0; + u32 val = 0; + u32 grfreg = 0; if (enable) { dev_dbg(tve->dev, "dac enable\n"); - val = 0x70; + + mask = m_VBG_EN | m_DAC_EN | m_DAC_GAIN; + if (tve->soc_type == SOC_RK3036) { + val = m_VBG_EN | m_DAC_EN | v_DAC_GAIN(tve->daclevel); + grfreg = RK3036_GRF_SOC_CON3; + } else if (tve->soc_type == SOC_RK312X) { + val = m_VBG_EN | m_DAC_EN | v_DAC_GAIN(tve->daclevel); + grfreg = RK312X_GRF_TVE_CON; + } else if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) { + val = v_CUR_REG(tve->dac1level) | v_DR_PWR_DOWN(0) | v_BG_PWR_DOWN(0); + } } else { dev_dbg(tve->dev, "dac disable\n"); - val = v_CUR_REG(0x7) | m_DR_PWR_DOWN | m_BG_PWR_DOWN; + + mask = m_VBG_EN | m_DAC_EN; + if (tve->soc_type == SOC_RK312X) + grfreg = RK312X_GRF_TVE_CON; + else if (tve->soc_type == SOC_RK3036) + grfreg = RK3036_GRF_SOC_CON3; + else if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) + val = v_CUR_REG(tve->dac1level) | m_DR_PWR_DOWN | m_BG_PWR_DOWN; } - if (tve->vdacbase) + if (grfreg) + tve_dac_grf_writel(grfreg, (mask << 16) | val); + else if (tve->vdacbase) tve_dac_writel(VDAC_VDAC1, val); } @@ -375,33 +407,37 @@ static int tve_parse_dt(struct device_node *np, return -EINVAL; } else { tve->daclevel = val; - cell = nvmem_cell_get(tve->dev, "tve_dac_adj"); - if (IS_ERR(cell)) { - dev_dbg(tve->dev, - "failed to get id cell: %ld\n", PTR_ERR(cell)); - } else { - efuse_buf = nvmem_cell_read(cell, &len); - nvmem_cell_put(cell); - if (len == 1) - getdac = efuse_buf[0]; - kfree(efuse_buf); + if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) { + cell = nvmem_cell_get(tve->dev, "tve_dac_adj"); + if (IS_ERR(cell)) { + dev_dbg(tve->dev, "failed to get id cell: %ld\n", PTR_ERR(cell)); + } else { + efuse_buf = nvmem_cell_read(cell, &len); + nvmem_cell_put(cell); + if (IS_ERR(efuse_buf)) + return PTR_ERR(efuse_buf); + if (len == 1) + getdac = efuse_buf[0]; + kfree(efuse_buf); - if (getdac > 0) { - tve->daclevel = - getdac + 5 + val - RK322X_VDAC_STANDARD; - if (tve->daclevel > 0x3f) { - dev_err(tve->dev, - "rk322x daclevel error!\n"); - tve->daclevel = val; + if (getdac > 0) { + tve->daclevel = getdac + 5 + val - RK322X_VDAC_STANDARD; + if (tve->daclevel > 0x3f) { + dev_err(tve->dev, "rk322x daclevel error!\n"); + tve->daclevel = val; + } } } } } - ret = of_property_read_u32(np, "rockchip,dac1level", &val); - if ((val == 0) || (ret < 0)) - return -EINVAL; - tve->dac1level = val; + if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) { + ret = of_property_read_u32(np, "rockchip,dac1level", &val); + if ((val == 0) || (ret < 0)) + return -EINVAL; + tve->dac1level = val; + } + return 0; } @@ -410,11 +446,13 @@ static void check_uboot_logo(struct rockchip_tve *tve) { int lumafilter0, lumafilter1, lumafilter2, vdac; - vdac = tve_dac_readl(VDAC_VDAC1); - /* Whether the dac power has been turned down. */ - if (vdac & m_DR_PWR_DOWN) { - tve->connector.dpms = DRM_MODE_DPMS_OFF; - return; + if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) { + vdac = tve_dac_readl(VDAC_VDAC1); + /* Whether the dac power has been turned down. */ + if (vdac & m_DR_PWR_DOWN) { + tve->connector.dpms = DRM_MODE_DPMS_OFF; + return; + } } lumafilter0 = tve_readl(TV_LUMA_FILTER0); @@ -432,14 +470,37 @@ static void check_uboot_logo(struct rockchip_tve *tve) return; } - dac_init(tve); + if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) + dac_init(tve); + tve->connector.dpms = DRM_MODE_DPMS_OFF; } +static const struct rockchip_tve_data rk3036_tve = { + .soc_type = SOC_RK3036, + .input_format = INPUT_FORMAT_RGB, +}; + +static const struct rockchip_tve_data rk312x_tve = { + .soc_type = SOC_RK312X, + .input_format = INPUT_FORMAT_RGB, +}; + +static const struct rockchip_tve_data rk322x_tve = { + .soc_type = SOC_RK322X, + .input_format = INPUT_FORMAT_YUV, +}; + +static const struct rockchip_tve_data rk3328_tve = { + .soc_type = SOC_RK3328, + .input_format = INPUT_FORMAT_YUV, +}; + static const struct of_device_id rockchip_tve_dt_ids[] = { - { - .compatible = "rockchip,rk3328-tve", - }, + { .compatible = "rockchip,rk3036-tve", .data = &rk3036_tve }, + { .compatible = "rockchip,rk312x-tve", .data = &rk312x_tve }, + { .compatible = "rockchip,rk322x-tve", .data = &rk322x_tve }, + { .compatible = "rockchip,rk3328-tve", .data = &rk3328_tve }, {} }; @@ -452,6 +513,7 @@ static int rockchip_tve_bind(struct device *dev, struct device *master, struct drm_device *drm_dev = data; struct device_node *np = dev->of_node; const struct of_device_id *match; + const struct rockchip_tve_data *tve_data; struct rockchip_tve *tve; struct resource *res; struct drm_encoder *encoder; @@ -469,11 +531,10 @@ static int rockchip_tve_bind(struct device *dev, struct device *master, } tve->dev = &pdev->dev; - if (!strcmp(match->compatible, "rockchip,rk3328-tve")) { - tve->inputformat = INPUT_FORMAT_YUV; - } else { - dev_err(tve->dev, "It is not a valid tv encoder! "); - return -ENOMEM; + tve_data = of_device_get_match_data(dev); + if (tve_data) { + tve->soc_type = tve_data->soc_type; + tve->input_format = tve_data->input_format; } ret = tve_parse_dt(np, tve); @@ -490,19 +551,36 @@ static int rockchip_tve_bind(struct device *dev, struct device *master, tve->regbase = devm_ioremap(tve->dev, res->start, tve->len); if (IS_ERR(tve->regbase)) { dev_err(tve->dev, - "rk3328 tv encoder device map registers failed!"); + "tv encoder device map registers failed!"); return PTR_ERR(tve->regbase); } - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - tve->len = resource_size(res); - tve->vdacbase = devm_ioremap(tve->dev, res->start, tve->len); - if (IS_ERR(tve->vdacbase)) { - dev_err(tve->dev, - "rk3328 tv encoder device dac map registers failed!"); - return PTR_ERR(tve->vdacbase); + if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + tve->len = resource_size(res); + tve->vdacbase = devm_ioremap(tve->dev, res->start, tve->len); + if (IS_ERR(tve->vdacbase)) { + dev_err(tve->dev, "tv encoder device dac map registers failed!"); + return PTR_ERR(tve->vdacbase); + } } + if (tve->soc_type == SOC_RK3036) { + tve->aclk = devm_clk_get(tve->dev, "aclk"); + if (IS_ERR(tve->aclk)) { + dev_err(tve->dev, "Unable to get tve aclk\n"); + return PTR_ERR(tve->aclk); + } + + ret = clk_prepare_enable(tve->aclk); + if (ret) { + dev_err(tve->dev, "Cannot enable tve aclk: %d\n", ret); + return ret; + } + } + + tve->dac_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); + mutex_init(&tve->suspend_lock); check_uboot_logo(tve); tve->tv_format = TVOUT_CVBS_PAL; @@ -515,7 +593,7 @@ static int rockchip_tve_bind(struct device *dev, struct device *master, DRM_MODE_ENCODER_TVDAC, NULL); if (ret < 0) { dev_err(tve->dev, "failed to initialize encoder with drm\n"); - return ret; + goto err_disable_aclk; } drm_encoder_helper_add(encoder, &rockchip_tve_encoder_helper_funcs); @@ -552,6 +630,10 @@ err_free_connector: drm_connector_cleanup(connector); err_free_encoder: drm_encoder_cleanup(encoder); +err_disable_aclk: + if (tve->soc_type == SOC_RK3036) + clk_disable_unprepare(tve->aclk); + return ret; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_tve.h b/drivers/gpu/drm/rockchip/rockchip_drm_tve.h index cd0bcb1a32fc..e7d3acc3fd52 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_tve.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_tve.h @@ -15,6 +15,9 @@ #ifndef __ROCKCHIP_DRM_TVE_H__ #define __ROCKCHIP_DRM_TVE_H__ +#define RK3036_GRF_SOC_CON3 0x0154 +#define RK312X_GRF_TVE_CON 0x0170 + #define TV_CTRL (0x00) #define m_CVBS_MODE BIT(24) #define m_CLK_UPSTREAM_EN (3 << 18) @@ -129,6 +132,13 @@ enum { INPUT_FORMAT_YUV }; +enum { + SOC_RK3036 = 0, + SOC_RK312X, + SOC_RK322X, + SOC_RK3328 +}; + #define grf_writel(offset, v) do { \ writel_relaxed(v, RK_GRF_VIRT + (offset)); \ dsb(sy); \ @@ -143,10 +153,13 @@ struct rockchip_tve { u32 tv_format; void __iomem *regbase; void __iomem *vdacbase; + struct clk *aclk; struct clk *dac_clk; + struct regmap *dac_grf; u32 reg_phy_base; u32 len; - int inputformat; + int input_format; + int soc_type; bool enable; u32 test_mode; u32 saturation; From 47855807ea84f1135c34272b874efe305a357072 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Mon, 5 Dec 2022 20:56:46 +0800 Subject: [PATCH 218/235] ARM: configs: rockchip_linux_defconfig: enable tve Signed-off-by: Damon Ding Change-Id: I6c1b81809b31873e751207c29feb045fdcfc1a63 --- arch/arm/configs/rockchip_linux_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/rockchip_linux_defconfig b/arch/arm/configs/rockchip_linux_defconfig index 98a0f13e5fe4..6e356c7533a3 100644 --- a/arch/arm/configs/rockchip_linux_defconfig +++ b/arch/arm/configs/rockchip_linux_defconfig @@ -289,6 +289,7 @@ CONFIG_DRM_IGNORE_IOTCL_PERMIT=y CONFIG_DRM_LOAD_EDID_FIRMWARE=y CONFIG_DRM_ROCKCHIP=y CONFIG_ROCKCHIP_ANALOGIX_DP=y +CONFIG_ROCKCHIP_DRM_TVE=y CONFIG_ROCKCHIP_DW_HDMI=y CONFIG_ROCKCHIP_DW_MIPI_DSI=y CONFIG_ROCKCHIP_INNO_HDMI=y From c9d18638d6ee9bb1df2486db3b97ebb86086e715 Mon Sep 17 00:00:00 2001 From: ZhiZhan Chen Date: Mon, 5 Dec 2022 17:22:22 +0800 Subject: [PATCH 219/235] drm/rockchip: add config options of TVE driver Change-Id: I059808111bfa96724eb629b6fc37915a4852e234 Signed-off-by: ZhiZhan Chen Signed-off-by: Damon Ding --- drivers/gpu/drm/rockchip/Kconfig | 7 +++++++ drivers/gpu/drm/rockchip/Makefile | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index ca02c1804e81..b772476ee7c0 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -82,6 +82,13 @@ config ROCKCHIP_CDN_DP RK3399 based SoC, you should select this option. +config ROCKCHIP_DRM_TVE + bool "Rockchip TVE support" + depends on DRM_ROCKCHIP + help + Choose this option to enable support for Rockchip TVE controllers. + say Y to enable its driver. + config ROCKCHIP_DW_HDMI bool "Rockchip specific extensions for Synopsys DW HDMI" help diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index 97116e397de4..4d730f9d7d3c 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile @@ -17,6 +17,7 @@ rockchipdrm-$(CONFIG_ROCKCHIP_DRM_SELF_TEST) += rockchip_drm_display_pattern.o \ rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o +rockchipdrm-$(CONFIG_ROCKCHIP_DRM_TVE) += rockchip_drm_tve.o rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi-rockchip.o \ dw-mipi-dsi2-rockchip.o From e327d3bb1af590b7c556c23c2a6fd7436d9206e2 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Mon, 5 Dec 2022 21:19:36 +0800 Subject: [PATCH 220/235] drm/rockchip: drv: register rockchip tve driver Signed-off-by: Damon Ding Change-Id: I40cce413d738ad16473eb35ce6c2adf4897380d6 --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 + drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 582fa1390d5c..3d559123026d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -1977,6 +1977,7 @@ static int __init rockchip_drm_init(void) ADD_ROCKCHIP_SUB_DRIVER(rk3066_hdmi_driver, CONFIG_ROCKCHIP_RK3066_HDMI); ADD_ROCKCHIP_SUB_DRIVER(rockchip_rgb_driver, CONFIG_ROCKCHIP_RGB); + ADD_ROCKCHIP_SUB_DRIVER(rockchip_tve_driver, CONFIG_ROCKCHIP_DRM_TVE); ADD_ROCKCHIP_SUB_DRIVER(dw_dp_driver, CONFIG_ROCKCHIP_DW_DP); #endif diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index f470d798e916..3dd30880f6a2 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -513,6 +513,7 @@ extern struct platform_driver vop_platform_driver; extern struct platform_driver vop2_platform_driver; extern struct platform_driver rk3066_hdmi_driver; extern struct platform_driver rockchip_rgb_driver; +extern struct platform_driver rockchip_tve_driver; extern struct platform_driver dw_dp_driver; extern struct platform_driver vconn_platform_driver; extern struct platform_driver vvop_platform_driver; From ffa6d4f255f6843fb75c4e317b0af157343811aa Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Wed, 1 Jun 2022 21:57:14 +0800 Subject: [PATCH 221/235] drm/rockchip: vop: add support for cvbs interface on rk3036 CVBS only support for 480i and 576i display mode. It is needed for rk3036 to enable scaling when using interlace mode, which also updated in this commit. Signed-off-by: Damon Ding Change-Id: I1d131ec71c0b31680280353e1690f8c01eb3c94e --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 17 ++++++++++++++++- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 10 ++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 9cbb35c289de..d7ea1f80ea12 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -826,11 +826,22 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win *win, uint16_t lb_mode; uint32_t val; const struct vop_data *vop_data = vop->data; + struct drm_display_mode *adjusted_mode = &vop->rockchip_crtc.crtc.state->adjusted_mode; int vskiplines; if (!win->phy->scl) return; + if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2)) { + VOP_SCL_SET(vop, win, scale_yrgb_x, ((src_w << 12) / dst_w)); + VOP_SCL_SET(vop, win, scale_yrgb_y, ((src_h << 12) / dst_h)); + if (is_yuv) { + VOP_SCL_SET(vop, win, scale_cbcr_x, ((cbcr_src_w << 12) / dst_w)); + VOP_SCL_SET(vop, win, scale_cbcr_y, ((cbcr_src_h << 12) / dst_h)); + } + return; + } + if (!(vop_data->feature & VOP_FEATURE_ALPHA_SCALE)) { if (is_alpha_support(pixel_format) && (src_w != dst_w || src_h != dst_h)) @@ -2011,6 +2022,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane, dsp_h = 4; actual_h = dsp_h * actual_h / drm_rect_height(dest); } + if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2)) + dsp_h = dsp_h / 2; act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); @@ -2019,6 +2032,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane, dsp_stx = dest->x1 + mode->crtc_htotal - mode->crtc_hsync_start; dsp_sty = dest->y1 + mode->crtc_vtotal - mode->crtc_vsync_start; + if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2)) + dsp_sty = dest->y1 / 2 + mode->crtc_vtotal - mode->crtc_vsync_start; dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); s = to_rockchip_crtc_state(crtc->state); @@ -2046,7 +2061,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, if (win->phy->scl) scl_vop_cal_scl_fac(vop, win, actual_w, actual_h, - drm_rect_width(dest), drm_rect_height(dest), + drm_rect_width(dest), dsp_h, fb->format->format); if (VOP_WIN_SUPPORT(vop, win, color_key)) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index bedf2a99a793..280faffeded9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -254,6 +254,7 @@ struct vop_ctrl { struct vop_reg post_scl_factor; struct vop_reg post_scl_ctrl; struct vop_reg dsp_interlace; + struct vop_reg dsp_interlace_pol; struct vop_reg global_regdone_en; struct vop_reg auto_gate_en; struct vop_reg post_lb_mode; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index ba43530af653..e47f5e865537 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -1239,19 +1239,27 @@ static const struct vop_intr rk3036_intr = { static const struct vop_ctrl rk3036_ctrl_data = { .standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30), + .sw_dac_sel = VOP_REG(RK3036_SYS_CTRL, 0x1, 29), .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0), + .dsp_interlace = VOP_REG(RK3036_DSP_CTRL0, 0x1, 12), .dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24), + .dsp_background = VOP_REG(RK3036_DSP_CTRL1, 0xffffff, 0), .dclk_pol = VOP_REG(RK3036_DSP_CTRL0, 0x1, 7), .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0x7, 4), .dither_down_sel = VOP_REG(RK3036_DSP_CTRL0, 0x1, 27), + .tve_sw_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 25), + .dsp_interlace_pol = VOP_REG(RK3036_DSP_CTRL0, 0x1, 13), .dither_down_en = VOP_REG(RK3036_DSP_CTRL0, 0x1, 11), .dither_down_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 10), .dither_up_en = VOP_REG(RK3036_DSP_CTRL0, 0x1, 9), .dsp_layer_sel = VOP_REG(RK3036_DSP_CTRL0, 0x1, 8), .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0), + .tve_dclk_en = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 20), + .tve_dclk_pol = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 21), .hdmi_en = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 22), .hdmi_dclk_pol = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 23), + .core_dclk_div = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 30), .hdmi_pin_pol = VOP_REG(RK3036_INT_SCALER, 0x7, 4), .rgb_en = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 24), .rgb_dclk_pol = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 25), @@ -1261,6 +1269,8 @@ static const struct vop_ctrl rk3036_ctrl_data = { .mipi_dclk_pol = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 29), .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0), + .vs_st_end_f1 = VOP_REG(RK3036_DSP_VS_ST_END_F1, 0x1fff1fff, 0), + .vact_st_end_f1 = VOP_REG(RK3036_DSP_VACT_ST_END_F1, 0x1fff1fff, 0), .cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0), }; From 1abf5c42d2106108ed02bee8f43095280a1b6437 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Tue, 6 Dec 2022 19:11:12 +0800 Subject: [PATCH 222/235] drm/rockchip: drv: split pre mapping into two mapping At 32 bit platform size_t maximum value is 0xffffffff, SZ_4G(0x100000000) will be cliped to 0, so we split into two mapping. Fixes: 0da77f77c0b9 ("drm/rockchip: drv: add support pre mapping for vop iommu") Signed-off-by: Sandy Huang Change-Id: I4066b1e20cfb9e29033b72f2035bf5e24a1f1f23 --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 3d559123026d..edb540d34cb7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -1055,10 +1055,19 @@ static int rockchip_drm_init_iommu(struct drm_device *drm_dev) drm_dev); if (iommu_reserve_map) { - ret = iommu_map(private->domain, 0, 0, (size_t)SZ_4G, + /* + * At 32 bit platform size_t maximum value is 0xffffffff, SZ_4G(0x100000000) will be + * cliped to 0, so we split into two mapping + */ + ret = iommu_map(private->domain, 0, 0, (size_t)SZ_2G, IOMMU_WRITE | IOMMU_READ | IOMMU_PRIV); if (ret) - dev_err(drm_dev->dev, "failed to create pre mapping\n"); + dev_err(drm_dev->dev, "failed to create 0-2G pre mapping\n"); + + ret = iommu_map(private->domain, SZ_2G, SZ_2G, (size_t)SZ_2G, + IOMMU_WRITE | IOMMU_READ | IOMMU_PRIV); + if (ret) + dev_err(drm_dev->dev, "failed to create 2G-4G pre mapping\n"); } return ret; @@ -1071,8 +1080,10 @@ static void rockchip_iommu_cleanup(struct drm_device *drm_dev) if (!is_support_iommu) return; - if (iommu_reserve_map) - iommu_unmap(private->domain, 0, (size_t)SZ_4G); + if (iommu_reserve_map) { + iommu_unmap(private->domain, 0, (size_t)SZ_2G); + iommu_unmap(private->domain, SZ_2G, (size_t)SZ_2G); + } drm_mm_takedown(&private->mm); iommu_domain_free(private->domain); } From 1a04192711f993720250678ad32867231738d138 Mon Sep 17 00:00:00 2001 From: Herman Chen Date: Mon, 5 Dec 2022 10:15:16 +0800 Subject: [PATCH 223/235] video: rockchip: mpp: vepu2: Fix core id limit Signed-off-by: Herman Chen Change-Id: I52268e292c8527bd377da1574a64ff09621d4971 --- drivers/video/rockchip/mpp/mpp_vepu2.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_vepu2.c b/drivers/video/rockchip/mpp/mpp_vepu2.c index f57d4dff6d08..d87f7788dbc0 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu2.c +++ b/drivers/video/rockchip/mpp/mpp_vepu2.c @@ -319,16 +319,30 @@ fail: static void *vepu_prepare(struct mpp_dev *mpp, struct mpp_task *mpp_task) { - unsigned long flags; - s32 core_id; + struct mpp_taskqueue *queue = mpp->queue; struct vepu_dev *enc = to_vepu_dev(mpp); struct vepu_ccu *ccu = enc->ccu; + unsigned long core_idle; + unsigned long flags; + u32 core_id_max; + s32 core_id; + u32 i; spin_lock_irqsave(&ccu->lock, flags); + core_idle = queue->core_idle; + core_id_max = queue->core_id_max; + + for (i = 0; i <= core_id_max; i++) { + struct mpp_dev *mpp = queue->cores[i]; + + if (mpp && mpp->disable) + clear_bit(i, &core_idle); + } + core_id = find_first_bit(&ccu->core_idle, ccu->core_num); - if (core_id >= ccu->core_num) { + if (core_id >= core_id_max + 1 || !queue->cores[core_id]) { mpp_task = NULL; mpp_dbg_core("core %d all busy %lx\n", core_id, ccu->core_idle); } else { From 7a22993077b30cdda0c2f987219bf0b35ac6325f Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Tue, 6 Dec 2022 16:44:49 +0800 Subject: [PATCH 224/235] clk: rockchip: update the frac clk parent Fixes: cd1052209387 ("clk: rockchip: fix up frac clk parent no update") Signed-off-by: Elaine Zhang Change-Id: I9fd76eb118f925ec4eeb8b928a7acb3ee2b93deb --- drivers/clk/rockchip/clk.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 5b2bdb33d327..09762ce82d67 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -168,6 +168,9 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, if (frac->rate_change_remuxed) { frac->mux_ops->set_parent(&frac_mux->hw, frac->rate_change_idx); + clk_hw_set_parent(&frac_mux->hw, + clk_hw_get_parent_by_index(&frac_mux->hw, + frac->rate_change_idx)); frac->rate_change_remuxed = 0; } } From ee7c3ab6b5a4d284a04f110792508a7f8decd7f7 Mon Sep 17 00:00:00 2001 From: William Wu Date: Tue, 6 Dec 2022 14:45:54 +0800 Subject: [PATCH 225/235] usb: dwc2: fix waiting time for host only mode The current code uses 50ms sleep to wait for host only mode, the delay time is not enough for some Rockchip platforms (e.g RK3036G EVB1). Test on RK3036G EVB1, the dwc2 host only controller reg GOTGCTL.ConIDSts = 1'b1 (device mode) if only wait for 50ms. And the host fails to detect usb2 device with the following error log: usb usb2-port1: connect-debounce failed This patch checks the GOTGCTL.ConIDSts for host only mode and increases the maximum waiting time to 200ms. Signed-off-by: William Wu Change-Id: Ie28299934aba09907ea08f5fd3b34bf2fb35822e --- drivers/usb/dwc2/core.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 15911ac7582b..cbd5f1142f35 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -656,14 +656,24 @@ static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg) */ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg) { + u32 count = 0; + switch (hsotg->dr_mode) { case USB_DR_MODE_HOST: /* * NOTE: This is required for some rockchip soc based * platforms on their host-only dwc2. */ - if (!dwc2_hw_is_otg(hsotg)) - msleep(50); + if (!dwc2_hw_is_otg(hsotg)) { + while (dwc2_readl(hsotg, GOTGCTL) & GOTGCTL_CONID_B) { + msleep(20); + if (++count > 10) + break; + } + if (count > 10) + dev_err(hsotg->dev, + "Waiting for Host Mode timed out"); + } break; case USB_DR_MODE_PERIPHERAL: From c25a99d05fcde784fb71a156b488a72b1fb55018 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 5 Dec 2022 15:43:29 +0800 Subject: [PATCH 226/235] cpufreq: rockchip: Add support for rk3588j Signed-off-by: Finley Xiao Change-Id: I13d2ffae1253c7e5b3513c6aefcf15fb8e16eb5d --- drivers/cpufreq/rockchip-cpufreq.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index 699f53e15ece..179999a37b8c 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -206,6 +206,9 @@ static int rk3588_get_soc_info(struct device *dev, struct device_node *np, /* RK3588M */ if (value == 0xd) *bin = 1; + /* RK3588J */ + else if (value == 0xa) + *bin = 2; } if (*bin < 0) *bin = 0; @@ -213,6 +216,7 @@ static int rk3588_get_soc_info(struct device *dev, struct device_node *np, return ret; } + static int rk3588_change_length(struct device *dev, struct device_node *np, int bin, int process, int volt_sel) { From 1e655030ce808addbf42c8749fbde57f4a54180d Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 5 Dec 2022 17:06:40 +0800 Subject: [PATCH 227/235] soc: rockchip: opp_select: Add support to set soc info Signed-off-by: Finley Xiao Change-Id: I101ff42d9e175535cfab9b58781c472b00b700e1 --- drivers/soc/rockchip/rockchip_opp_select.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/rockchip/rockchip_opp_select.c b/drivers/soc/rockchip/rockchip_opp_select.c index 4a50b4a6a347..34a19c753730 100644 --- a/drivers/soc/rockchip/rockchip_opp_select.c +++ b/drivers/soc/rockchip/rockchip_opp_select.c @@ -1709,6 +1709,8 @@ int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info, next: rockchip_get_scale_volt_sel(dev, lkg_name, reg_name, bin, process, &scale, &volt_sel); + if (info && info->data && info->data->set_soc_info) + info->data->set_soc_info(dev, np, bin, process, volt_sel); rockchip_set_opp_prop_name(dev, process, volt_sel); ret = dev_pm_opp_of_add_table(dev); if (ret) { From b1bae8a36b527cae375875b8121aa637e8e6d81c Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 5 Dec 2022 17:05:55 +0800 Subject: [PATCH 228/235] MALI: bifrost: Implement set_soc_info and set_soc_info for rk3588 Signed-off-by: Finley Xiao Change-Id: Ic5dddbd667b63b61f60b80270ba8bae8b1086852 --- .../platform/rk/mali_kbase_config_rk.c | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c index 4452c3f3ed0f..495bcc36b1df 100755 --- a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c +++ b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c @@ -506,6 +506,66 @@ static void kbase_platform_rk_remove_sysfs_files(struct device *dev) device_remove_file(dev, &dev_attr_utilisation); } +static int rk3588_gpu_get_soc_info(struct device *dev, struct device_node *np, + int *bin, int *process) +{ + int ret = 0; + u8 value = 0; + + if (!bin) + return 0; + + if (of_property_match_string(np, "nvmem-cell-names", + "specification_serial_number") >= 0) { + ret = rockchip_nvmem_cell_read_u8(np, + "specification_serial_number", + &value); + if (ret) { + dev_err(dev, + "Failed to get specification_serial_number\n"); + return ret; + } + /* RK3588M */ + if (value == 0xd) + *bin = 1; + /* RK3588J */ + else if (value == 0xa) + *bin = 2; + } + if (*bin < 0) + *bin = 0; + dev_info(dev, "bin=%d\n", *bin); + + return ret; +} + +static int rk3588_gpu_set_soc_info(struct device *dev, struct device_node *np, + int bin, int process, int volt_sel) +{ + struct opp_table *opp_table; + u32 supported_hw[2]; + + if (volt_sel < 0) + return 0; + if (bin < 0) + bin = 0; + + if (!of_property_read_bool(np, "rockchip,supported-hw")) + return 0; + + /* SoC Version */ + supported_hw[0] = BIT(bin); + /* Speed Grade */ + supported_hw[1] = BIT(volt_sel); + opp_table = dev_pm_opp_set_supported_hw(dev, supported_hw, 2); + if (IS_ERR(opp_table)) { + dev_err(dev, "failed to set supported opp\n"); + return PTR_ERR(opp_table); + } + + return 0; +} + static int rk3588_gpu_set_read_margin(struct device *dev, struct rockchip_opp_info *opp_info, u32 rm) @@ -542,6 +602,8 @@ static int rk3588_gpu_set_read_margin(struct device *dev, } static const struct rockchip_opp_data rk3588_gpu_opp_data = { + .get_soc_info = rk3588_gpu_get_soc_info, + .set_soc_info = rk3588_gpu_set_soc_info, .set_read_margin = rk3588_gpu_set_read_margin, }; From 63e89b6e6345048c8e3cc31e1da86e59b2720869 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 5 Dec 2022 17:13:44 +0800 Subject: [PATCH 229/235] driver: rknpu: Implement set_soc_info and set_soc_info for rk3588 Signed-off-by: Finley Xiao Change-Id: I8cfe13ffded798363388153bfbf305f6fc9f9f33 --- drivers/rknpu/rknpu_drv.c | 62 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/drivers/rknpu/rknpu_drv.c b/drivers/rknpu/rknpu_drv.c index 30dfc38f76c9..26d10c233cc9 100644 --- a/drivers/rknpu/rknpu_drv.c +++ b/drivers/rknpu/rknpu_drv.c @@ -1107,6 +1107,66 @@ static struct devfreq_cooling_power npu_cooling_power = { }; #if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE +static int rk3588_npu_get_soc_info(struct device *dev, struct device_node *np, + int *bin, int *process) +{ + int ret = 0; + u8 value = 0; + + if (!bin) + return 0; + + if (of_property_match_string(np, "nvmem-cell-names", + "specification_serial_number") >= 0) { + ret = rockchip_nvmem_cell_read_u8(np, + "specification_serial_number", + &value); + if (ret) { + dev_err(dev, + "Failed to get specification_serial_number\n"); + return ret; + } + /* RK3588M */ + if (value == 0xd) + *bin = 1; + /* RK3588J */ + else if (value == 0xa) + *bin = 2; + } + if (*bin < 0) + *bin = 0; + dev_info(dev, "bin=%d\n", *bin); + + return ret; +} + +static int rk3588_npu_set_soc_info(struct device *dev, struct device_node *np, + int bin, int process, int volt_sel) +{ + struct opp_table *opp_table; + u32 supported_hw[2]; + + if (volt_sel < 0) + return 0; + if (bin < 0) + bin = 0; + + if (!of_property_read_bool(np, "rockchip,supported-hw")) + return 0; + + /* SoC Version */ + supported_hw[0] = BIT(bin); + /* Speed Grade */ + supported_hw[1] = BIT(volt_sel); + opp_table = dev_pm_opp_set_supported_hw(dev, supported_hw, 2); + if (IS_ERR(opp_table)) { + dev_err(dev, "failed to set supported opp\n"); + return PTR_ERR(opp_table); + } + + return 0; +} + static int rk3588_npu_set_read_margin(struct device *dev, struct rockchip_opp_info *opp_info, u32 rm) @@ -1139,6 +1199,8 @@ static int rk3588_npu_set_read_margin(struct device *dev, } static const struct rockchip_opp_data rk3588_npu_opp_data = { + .get_soc_info = rk3588_npu_get_soc_info, + .set_soc_info = rk3588_npu_set_soc_info, .set_read_margin = rk3588_npu_set_read_margin, }; From 2438e9436453248e9d16ac54ce08947d1fe8c1c3 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 5 Dec 2022 15:37:58 +0800 Subject: [PATCH 230/235] arm64: dts: rockchip: rk3588s: Add hardware version for rk3588m and rk3588j Signed-off-by: Finley Xiao Change-Id: Ide13f6d0c8d38c1e46be52c4b407b1147a08ad8a --- arch/arm64/boot/dts/rockchip/rk3588j.dtsi | 1 + arch/arm64/boot/dts/rockchip/rk3588m.dtsi | 20 ------ arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 77 +++++++++++++++++------ 3 files changed, 58 insertions(+), 40 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi index 6f8b262965be..097c7ce386b7 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588j.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588j.dtsi @@ -8,6 +8,7 @@ &cluster0_opp_table { /delete-node/ opp-1608000000; + /delete-node/ opp-1704000000; /delete-node/ opp-1800000000; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588m.dtsi b/arch/arm64/boot/dts/rockchip/rk3588m.dtsi index ca2250be0dd9..1a30a0375033 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588m.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588m.dtsi @@ -8,26 +8,6 @@ &cluster0_opp_table { /delete-node/ opp-1800000000; - - opp-1704000000 { - opp-supported-hw = <0x02 0xffff>; - opp-hz = /bits/ 64 <1704000000>; - opp-microvolt = <900000 900000 950000>, - <900000 900000 950000>; - opp-microvolt-L1 = <887500 887500 950000>, - <887500 887500 950000>; - opp-microvolt-L2 = <875000 875000 950000>, - <875000 875000 950000>; - opp-microvolt-L3 = <862500 862500 950000>, - <862500 862500 950000>; - opp-microvolt-L4 = <850000 850000 950000>, - <850000 850000 950000>; - opp-microvolt-L5 = <837500 837500 950000>, - <837500 837500 950000>; - opp-microvolt-L6 = <825000 825000 950000>, - <825000 825000 950000>; - clock-latency-ns = <40000>; - }; }; &cluster1_opp_table { diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi index 3242b514f80b..b31b388a1918 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -681,7 +681,7 @@ opp-suspend; }; opp-1608000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xfb 0xffff>; opp-hz = /bits/ 64 <1608000000>; opp-microvolt = <850000 850000 950000>, <850000 850000 950000>; @@ -699,8 +699,27 @@ <787500 787500 950000>; clock-latency-ns = <40000>; }; + opp-1704000000 { + opp-supported-hw = <0x02 0xffff>; + opp-hz = /bits/ 64 <1704000000>; + opp-microvolt = <900000 900000 950000>, + <900000 900000 950000>; + opp-microvolt-L1 = <887500 887500 950000>, + <887500 887500 950000>; + opp-microvolt-L2 = <875000 875000 950000>, + <875000 875000 950000>; + opp-microvolt-L3 = <862500 862500 950000>, + <862500 862500 950000>; + opp-microvolt-L4 = <850000 850000 950000>, + <850000 850000 950000>; + opp-microvolt-L5 = <837500 837500 950000>, + <837500 837500 950000>; + opp-microvolt-L6 = <825000 825000 950000>, + <825000 825000 950000>; + clock-latency-ns = <40000>; + }; opp-1800000000 { - opp-supported-hw = <0xfd 0xffff>; + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1800000000>; opp-microvolt = <950000 950000 950000>, <950000 950000 950000>; @@ -841,7 +860,7 @@ clock-latency-ns = <40000>; }; opp-1800000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xfb 0xffff>; opp-hz = /bits/ 64 <1800000000>; opp-microvolt = <850000 850000 1000000>, <850000 850000 1000000>; @@ -862,7 +881,7 @@ clock-latency-ns = <40000>; }; opp-2016000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xfb 0xffff>; opp-hz = /bits/ 64 <2016000000>; opp-microvolt = <925000 925000 1000000>, <925000 925000 1000000>; @@ -883,7 +902,7 @@ clock-latency-ns = <40000>; }; opp-2208000000 { - opp-supported-hw = <0xfd 0xffff>; + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <2208000000>; opp-microvolt = <987500 987500 1000000>, <987500 987500 1000000>; @@ -904,28 +923,28 @@ clock-latency-ns = <40000>; }; opp-2256000000 { - opp-supported-hw = <0xfd 0x13>; + opp-supported-hw = <0xf9 0x13>; opp-hz = /bits/ 64 <2256000000>; opp-microvolt = <1000000 1000000 1000000>, <1000000 1000000 1000000>; clock-latency-ns = <40000>; }; opp-2304000000 { - opp-supported-hw = <0xfd 0x24>; + opp-supported-hw = <0xf9 0x24>; opp-hz = /bits/ 64 <2304000000>; opp-microvolt = <1000000 1000000 1000000>, <1000000 1000000 1000000>; clock-latency-ns = <40000>; }; opp-2352000000 { - opp-supported-hw = <0xfd 0x48>; + opp-supported-hw = <0xf9 0x48>; opp-hz = /bits/ 64 <2352000000>; opp-microvolt = <1000000 1000000 1000000>, <1000000 1000000 1000000>; clock-latency-ns = <40000>; }; opp-2400000000 { - opp-supported-hw = <0xfd 0x80>; + opp-supported-hw = <0xf9 0x80>; opp-hz = /bits/ 64 <2400000000>; opp-microvolt = <1000000 1000000 1000000>, <1000000 1000000 1000000>; @@ -1054,7 +1073,7 @@ clock-latency-ns = <40000>; }; opp-1800000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xfb 0xffff>; opp-hz = /bits/ 64 <1800000000>; opp-microvolt = <850000 850000 1000000>, <850000 850000 1000000>; @@ -1075,7 +1094,7 @@ clock-latency-ns = <40000>; }; opp-2016000000 { - opp-supported-hw = <0xff 0xffff>; + opp-supported-hw = <0xfb 0xffff>; opp-hz = /bits/ 64 <2016000000>; opp-microvolt = <925000 925000 1000000>, <925000 925000 1000000>; @@ -1096,7 +1115,7 @@ clock-latency-ns = <40000>; }; opp-2208000000 { - opp-supported-hw = <0xfd 0xffff>; + opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <2208000000>; opp-microvolt = <987500 987500 1000000>, <987500 987500 1000000>; @@ -1113,28 +1132,28 @@ clock-latency-ns = <40000>; }; opp-2256000000 { - opp-supported-hw = <0xfd 0x13>; + opp-supported-hw = <0xf9 0x13>; opp-hz = /bits/ 64 <2256000000>; opp-microvolt = <1000000 1000000 1000000>, <1000000 1000000 1000000>; clock-latency-ns = <40000>; }; opp-2304000000 { - opp-supported-hw = <0xfd 0x24>; + opp-supported-hw = <0xf9 0x24>; opp-hz = /bits/ 64 <2304000000>; opp-microvolt = <1000000 1000000 1000000>, <1000000 1000000 1000000>; clock-latency-ns = <40000>; }; opp-2352000000 { - opp-supported-hw = <0xfd 0x48>; + opp-supported-hw = <0xf9 0x48>; opp-hz = /bits/ 64 <2352000000>; opp-microvolt = <1000000 1000000 1000000>, <1000000 1000000 1000000>; clock-latency-ns = <40000>; }; opp-2400000000 { - opp-supported-hw = <0xfd 0x80>; + opp-supported-hw = <0xf9 0x80>; opp-hz = /bits/ 64 <2400000000>; opp-microvolt = <1000000 1000000 1000000>, <1000000 1000000 1000000>; @@ -1765,8 +1784,9 @@ gpu_opp_table: gpu-opp-table { compatible = "operating-points-v2"; - nvmem-cells = <&gpu_leakage>; - nvmem-cell-names = "leakage"; + nvmem-cells = <&gpu_leakage>, <&specification_serial_number>; + nvmem-cell-names = "leakage", "specification_serial_number"; + rockchip,supported-hw; rockchip,pvtm-voltage-sel = < 0 815 0 @@ -1804,26 +1824,31 @@ rockchip,high-temp-max-freq = <800000>; opp-300000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <300000000>; opp-microvolt = <675000 675000 850000>, <675000 675000 850000>; }; opp-400000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <400000000>; opp-microvolt = <675000 675000 850000>, <675000 675000 850000>; }; opp-500000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <500000000>; opp-microvolt = <675000 675000 850000>, <675000 675000 850000>; }; opp-600000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <600000000>; opp-microvolt = <675000 675000 850000>, <675000 675000 850000>; }; opp-700000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <700000000>; opp-microvolt = <700000 700000 850000>, <700000 700000 850000>; @@ -1837,6 +1862,7 @@ <675000 675000 850000>; }; opp-800000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <800000000>; opp-microvolt = <750000 750000 850000>, <750000 750000 850000>; @@ -1852,6 +1878,7 @@ <700000 700000 850000>; }; opp-900000000 { + opp-supported-hw = <0xfb 0xffff>; opp-hz = /bits/ 64 <900000000>; opp-microvolt = <800000 800000 850000>, <800000 800000 850000>; @@ -1867,6 +1894,7 @@ <737500 737500 850000>; }; opp-1000000000 { + opp-supported-hw = <0xfb 0xffff>; opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <850000 850000 850000>, <850000 850000 850000>; @@ -2737,8 +2765,9 @@ npu_opp_table: npu-opp-table { compatible = "operating-points-v2"; - nvmem-cells = <&npu_leakage>; - nvmem-cell-names = "leakage"; + nvmem-cells = <&npu_leakage>, <&specification_serial_number>; + nvmem-cell-names = "leakage", "specification_serial_number"; + rockchip,supported-hw; rockchip,pvtm-voltage-sel = < 0 815 0 @@ -2777,6 +2806,7 @@ rockchip,high-temp-max-freq = <800000>; opp-300000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <300000000>; opp-microvolt = <700000 700000 850000>, <700000 700000 850000>; @@ -2792,6 +2822,7 @@ <675000 675000 850000>; }; opp-400000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <400000000>; opp-microvolt = <700000 700000 850000>, <700000 700000 850000>; @@ -2807,6 +2838,7 @@ <675000 675000 850000>; }; opp-500000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <500000000>; opp-microvolt = <700000 700000 850000>, <700000 700000 850000>; @@ -2822,6 +2854,7 @@ <675000 675000 850000>; }; opp-600000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <600000000>; opp-microvolt = <700000 700000 850000>, <700000 700000 850000>; @@ -2837,6 +2870,7 @@ <675000 675000 850000>; }; opp-700000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <700000000>; opp-microvolt = <700000 700000 850000>, <700000 700000 850000>; @@ -2848,6 +2882,7 @@ <675000 675000 850000>; }; opp-800000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <800000000>; opp-microvolt = <750000 750000 850000>, <750000 750000 850000>; @@ -2861,6 +2896,7 @@ <700000 700000 850000>; }; opp-900000000 { + opp-supported-hw = <0xfb 0xffff>; opp-hz = /bits/ 64 <900000000>; opp-microvolt = <800000 800000 850000>, <800000 800000 850000>; @@ -2876,6 +2912,7 @@ <737500 737500 850000>; }; opp-1000000000 { + opp-supported-hw = <0xfb 0xffff>; opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <850000 850000 850000>, <850000 850000 850000>; From f8080404dfa194882d18dfe99c9bec136b3eac1d Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Wed, 7 Dec 2022 09:06:05 +0000 Subject: [PATCH 231/235] soc: rockchip: debug: rockchip_show_interrupts print all cpu Signed-off-by: Huibin Hong Change-Id: I929a9cee5d596a8d9f1280f8232eefc2fecf2f31 --- drivers/soc/rockchip/rockchip_debug.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/soc/rockchip/rockchip_debug.c b/drivers/soc/rockchip/rockchip_debug.c index 37abfb79a483..1599b7a29808 100644 --- a/drivers/soc/rockchip/rockchip_debug.c +++ b/drivers/soc/rockchip/rockchip_debug.c @@ -433,7 +433,7 @@ static int rockchip_show_interrupts(char *p, int irq) j *= 10; buf += sprintf(buf, "%*s", prec + 8, ""); - for_each_online_cpu(j) + for_each_possible_cpu(j) buf += sprintf(buf, "CPU%-8d", j); buf += sprintf(buf, "\n"); } @@ -443,14 +443,14 @@ static int rockchip_show_interrupts(char *p, int irq) goto outsparse; if (desc->kstat_irqs) - for_each_online_cpu(j) + for_each_possible_cpu(j) any_count |= *per_cpu_ptr(desc->kstat_irqs, j); if ((!desc->action) && !any_count) goto outsparse; buf += sprintf(buf, "%*d: ", prec, i); - for_each_online_cpu(j) + for_each_possible_cpu(j) buf += sprintf(buf, "%10u ", desc->kstat_irqs ? *per_cpu_ptr(desc->kstat_irqs, j) : 0); From 0b2f07b37848cd90b6ee2a442aca173e0c8ca2a9 Mon Sep 17 00:00:00 2001 From: Guochun Huang Date: Wed, 7 Dec 2022 07:19:56 +0000 Subject: [PATCH 232/235] drm/rockchip: dsi: driver may retry bind when panel or bridge not register Signed-off-by: Guochun Huang Change-Id: I8687da829e61a170e52c83f8565c2db879fd958a --- drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 83001753ddf0..3d6a1ed7599e 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -296,6 +296,7 @@ struct dw_mipi_dsi_rockchip { int devcnt; struct rockchip_drm_sub_dev sub_dev; struct drm_panel *panel; + struct drm_bridge *bridge; }; struct dphy_pll_parameter_map { @@ -974,6 +975,13 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev, struct device *second; int ret; + ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, + &dsi->panel, &dsi->bridge); + if (ret) { + dev_err(dsi->dev, "failed to find panel or bridge: %d\n", ret); + return ret; + } + second = dw_mipi_dsi_rockchip_find_second(dsi); if (IS_ERR(second)) return PTR_ERR(second); @@ -1012,12 +1020,8 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev, return ret; } - ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, - &dsi->panel, NULL); - if (ret) - dev_err(dsi->dev, "failed to find panel\n"); - - dw_mipi_dsi_get_dsc_info_from_sink(dsi, dsi->panel, NULL); + if (dsi->panel) + dw_mipi_dsi_get_dsc_info_from_sink(dsi, dsi->panel, NULL); dsi->sub_dev.connector = dw_mipi_dsi_get_connector(dsi->dmd); if (dsi->sub_dev.connector) { From ebc7e6d8486401906b41c6bdd2bf85afbd08033c Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Tue, 16 Mar 2021 10:00:13 +0800 Subject: [PATCH 233/235] irqchip/gic-v3: get free page instead of kmalloc for itt Since kmalloc may not care about GFP_DMA32, change to use get free pages for itt on its device. To reduce the impact of this change, we only applied it to rk3566/rk3568. Change-Id: I2e91c97bd4d61d2542cf437363fc3dd1d9fa669c Signed-off-by: Jianqun Xu Signed-off-by: XiaoDong Huang --- drivers/irqchip/irq-gic-v3-its.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index d6482c72b65f..88debe2abc29 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -161,6 +161,7 @@ struct its_device { struct its_node *its; struct event_lpi_map event_map; void *itt; + u32 itt_sz; u32 nr_ites; u32 device_id; bool shared; @@ -3403,9 +3404,13 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1); sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; gfp_flags = GFP_KERNEL; - if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566")) + if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566")) { gfp_flags |= GFP_DMA32; - itt = kzalloc_node(sz, gfp_flags, its->numa_node); + itt = (void *)__get_free_pages(gfp_flags, get_order(sz)); + } else { + itt = kzalloc_node(sz, gfp_flags, its->numa_node); + } + if (alloc_lpis) { lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis); if (lpi_map) @@ -3419,7 +3424,13 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) { kfree(dev); - kfree(itt); + + if (of_machine_is_compatible("rockchip,rk3568") || + of_machine_is_compatible("rockchip,rk3566")) + free_pages((unsigned long)itt, get_order(sz)); + else + kfree(itt); + kfree(lpi_map); kfree(col_map); return NULL; @@ -3429,6 +3440,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, dev->its = its; dev->itt = itt; + dev->itt_sz = sz; dev->nr_ites = nr_ites; dev->event_map.lpi_map = lpi_map; dev->event_map.col_map = col_map; @@ -3456,7 +3468,13 @@ static void its_free_device(struct its_device *its_dev) list_del(&its_dev->entry); raw_spin_unlock_irqrestore(&its_dev->its->lock, flags); kfree(its_dev->event_map.col_map); - kfree(its_dev->itt); + + if (of_machine_is_compatible("rockchip,rk3568") || + of_machine_is_compatible("rockchip,rk3566")) + free_pages((unsigned long)its_dev->itt, get_order(its_dev->itt_sz)); + else + kfree(its_dev->itt); + kfree(its_dev); } From a60cc4348985cc0a3446b8a2900d763e45e9d305 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 7 Dec 2022 18:17:42 +0800 Subject: [PATCH 234/235] arm64: rockchip_gki.config: Enable CONFIG_CPU_RK3568 Signed-off-by: Tao Huang Change-Id: Ied70ff781c200aed42cf6ca9f4a33ccb0ab281d5 --- arch/arm64/configs/rockchip_gki.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_gki.config b/arch/arm64/configs/rockchip_gki.config index 72c625eb3bde..59e6794b214f 100644 --- a/arch/arm64/configs/rockchip_gki.config +++ b/arch/arm64/configs/rockchip_gki.config @@ -29,6 +29,7 @@ CONFIG_COMPASS_DEVICE=m CONFIG_CPUFREQ_DT=m CONFIG_CPU_FREQ_GOV_ONDEMAND=m CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_RK3568=y CONFIG_CPU_RK3588=y CONFIG_CRYPTO_AES_ARM64_CE_CCM=m CONFIG_CRYPTO_DEV_ROCKCHIP=m From 914877f7c16228434d09b83f65b59b2503e8b3cf Mon Sep 17 00:00:00 2001 From: Wu Liangqing Date: Wed, 7 Dec 2022 18:19:31 +0800 Subject: [PATCH 235/235] arm64: configs: rockchip_gki: Enable CONFIG_PWRSEQ_SIMPLE Change-Id: I95a39f35eecc2139e894b8d9b8c1730d674ddf6c Signed-off-by: Wu Liangqing --- arch/arm64/configs/rockchip_gki.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/rockchip_gki.config b/arch/arm64/configs/rockchip_gki.config index 59e6794b214f..d726d030a647 100644 --- a/arch/arm64/configs/rockchip_gki.config +++ b/arch/arm64/configs/rockchip_gki.config @@ -1,3 +1,4 @@ +CONFIG_PWRSEQ_SIMPLE=m CONFIG_AP6XXX=m CONFIG_ARCH_ROCKCHIP=y CONFIG_ARM_ROCKCHIP_BUS_DEVFREQ=m