drm next for 6.18-rc1
cross-subsystem: - i2c-hid: Make elan touch controllers power on after panel is enabled - dt bindings for STM32MP25 SoC - pci vgaarb: use screen_info helpers - rust pin-init updates - add MEI driver for late binding firmware update/load uapi: - add ioctl for reassigning GEM handles - provide boot_display attribute on boot-up devices core: - document DRM_MODE_PAGE_FLIP_EVENT - add vendor specific recovery method to drm device wedged uevent gem: - Simplify gpuvm locking ttm: - add interface to populate buffers sched: - Fix race condition in trace code atomic: - Reallow no-op async page flips display: - dp: Fix command length video: - Improve pixel-format handling for struct screen_info rust: - drop Opaque<> from ioctl args - Alloc: - BorrowedPage type and AsPageIter traits - Implement Vmalloc::to_page() and VmallocPageIter - DMA/Scatterlist: - Add dma::DataDirection and type alias for dma_addr_t - Abstraction for struct scatterlist and sg_table - DRM: - simplify use of generics - add DriverFile type alias - drop Object::SIZE - Rust: - pin-init tree merge - Various methods for AsBytes and FromBytes traits gpuvm: - Support madvice in Xe driver gpusvm: - fix hmm_pfn_to_map_order usage in gpusvm bridge: - Improve and fix ref counting on bridge management - cdns-dsi: Various improvements to mode setting - Support Solomon SSD2825 plus DT bindings - Support Waveshare DSI2DPI plus DT bindings - Support Content Protection property - display-connector: Improve DP display detection - Add support for Radxa Ra620 plus DT bindings - adv7511: Provide SPD and HDMI infoframes - it6505: Replace crypto_shash with sha() - synopsys: Add support for DW DPTX Controller plus DT bindings - adv7511: Write full Audio infoframe - ite6263: Support vendor-specific infoframes - simple: Add support for Realtek RTD2171 DP-to-HDMI plus DT bindings panel: - panel-edp: Support mt8189 Chromebooks; Support BOE NV140WUM-N64; Support SHP LQ134Z1; Fixes - panel-simple: Support Olimex LCD-OLinuXino-5CTS plus DT bindings - Support Samsung AMS561RA01 - Support Hydis HV101HD1 plus DT bindings - ilitek-ili9881c: Refactor mode setting; Add support for Bestar BSD1218-A101KL68 LCD plus DT bindings - lvds: Add support for Ampire AMP19201200B5TZQW-T03 to DT bindings - edp: Add support for additonal mt8189 Chromebook panels - lvds: Add DT bindings for EDT ETML0700Z8DHA amdgpu: - add CRIU support for gem objects - RAS updates - VCN SRAM load fixes - EDID read fixes - eDP ALPM support - Documentation updates - Rework PTE flag generation - DCE6 fixes - VCN devcoredump cleanup - MMHUB client id fixes - VCN 5.0.1 RAS support - SMU 13.0.x updates - Expanded PCIe DPC support - Expanded VCN reset support - VPE per queue reset support - give kernel jobs unique id for tracing - pre-populate exported buffers - cyan skillfish updates - make vbios build number available in sysfs - userq updates - HDCP updates - support MMIO remap page as ttm pool - JPEG parser updates - DCE6 DC updates - use devm for i2c buses - GPUVM locking updates - Drop non-DC DCE11 code - improve fallback handling for pixel encoding amdkfd: - SVM/page migration fixes - debugfs fixes - add CRIO support for gem objects - SVM updates radeon: - use dev_warn_once in CS parsers xe: - add madvise interface - add DRM_IOCTL_XE_VM_QUERY_MEMORY_RANGE_ATTRS to query VMA count and memory attributes - drop L# bank mask reporting from media GT3 on Xe3+. - add SLPC power_profile sysfs interface - add configs attribs to add post/mid context-switch commands - handle firmware reported hardware errors notifying userspace with device wedged uevent - use same dir structure across sysfs/debugfs - cleanup and future proof vram region init - add G-states and PCI link states to debugfs - Add SRIOV support for CCS surfaces on Xe2+ - Enable SRIOV PF mode by default on supported platforms - move flush to common code - extended core workarounds for Xe2/3 - use DRM scheduler for delayed GT TLB invalidations - configs improvements and allow VF device enablement - prep work to expose mmio regions to userspace - VF migration support added - prepare GPU SVM for THP migration - start fixing XE_PAGE_SIZE vs PAGE_SIZE - add PSMI support for hw validation - resize VF bars to max possible size according to number of VFs - Ensure GT is in C0 during resume - pre-populate exported buffers - replace xe_hmm with gpusvm - add more SVM GT stats to debugfs - improve fake pci and WA kunnit handle for new platform testing - Test GuC to GuC comms to add debugging - use attribute groups to simplify sysfs registration - add Late Binding firmware code to interact with MEI i915: - apply multiple JSL/EHL/Gen7/Gen6 workarounds properly - protect against overflow in active_engine() - Use try_cmpxchg64() in __active_lookup() - include GuC registers in error state - get rid of dev->struct_mutex - iopoll: generalize read_poll_timout - lots more display refactoring - Reject HBR3 in any eDP Panel - Prune modes for YUV420 - Display Wa fix, additions, and updates - DP: Fix 2.7 Gbps link training on g4x - DP: Adjust the idle pattern handling - DP: Shuffle the link training code a bit - Don't set/read the DSI C clock divider on GLK - Enable_psr kernel parameter changes - Type-C enabled/disconnected dp-alt sink - Wildcat Lake enabling - DP HDR updates - DRAM detection - wait PSR idle on dsb commit - Remove FBC modulo 4 restriction for ADL-P+ - panic: refactor framebuffer allocation habanalabs: - debug/visibility improvements - vmalloc-backed coherent mmap support - HLDIO infrastructure nova-core: - various register!() macro improvements - minor vbios/firmware fixes/refactoring - advance firmware boot stages; process Booter and patch signatures - process GSP and GSP bootloader - Add r570.144 firmware bindings and update to it - Move GSP boot code to own module - Use new pin-init features to store driver's private data in a single allocation - Update ARef import from sync::aref nova-drm: - Update ARef import from sync::aref tyr: - initial driver skeleton for a rust driver for ARM Mali GPUs - capable of powering up, query metadata and provide it to userspace. msm: - GPU and Core: - in DT bindings describe clocks per GPU type - GMU bandwidth voting for x1-85 - a623/a663 speedbins - cleanup some remaining no-iommu leftovers after VM_BIND conversion - fix GEM obj 32b size truncation - add missing VM_BIND param validation - IFPC for x1-85 and a750 - register xml and gen_header.py sync from mesa - Display: - add missing bindings for display on SC8180X - added DisplayPort MST bindings - conversion from round_rate() to determine_rate() amdxdna: - add IOCTL_AMDXDNA_GET_ARRAY - support user space allocated buffers - streamline PM interfaces - Refactoring wrt. hardware contexts - improve error reporting nouveau: - use GSP firmware by default - improve error reporting - Pre-populate exported buffers ast: - Clean up detection of DRAM config exynos: - add DSIM bridge driver support for Exynos7870 - Document Exynos7870 DSIM compatible in dt-binding panthor: - Print task/pid on errors - Add support for Mali G710, G510, G310, Gx15, Gx20, Gx25 - Improve cache flushing - Fail VM bind if BO has offset renesas: - convert to RUNTIME_PM_OPS rcar-du: - Make number of lanes configurable - Use RUNTIME_PM_OPS - Add support for DSI commands rocket: - Add driver for Rockchip NPU plus DT bindings - Use kfree() and sizeof() correctly - Test DMA status rockchip: - dsi2: Add support for RK3576 plus DT bindings - Add support for RK3588 DPTX output tidss: - Use crtc_ fields for programming display mode - Remove other drivers from aperture pixpaper: - Add support for Mayqueen Pixpaper plus DT bindings v3d: - Support querying nubmer of GPU resets for KHR_robustness stm: - Clean up logging - ltdc: Add support support for STM32MP257F-EV1 plus DT bindings sitronix: - st7571-i2c: Add support for inverted displays and 2-bit grayscale tidss: - Convert to kernel's FIELD_ macros vesadrm: - Support 8-bit palette mode imagination: - Improve power management - Add support for TH1520 GPU - Support Risc-V architectures v3d: - Improve job management and locking vkms: - Support variants of ARGB8888, ARGB16161616, RGB565, RGB888 and P01x - Spport YUV with 16-bit components -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmjcpjkACgkQDHTzWXnE hr7Q7g/5AcxXqLUx7wvmDga9TpzIjDD+C+MOt568RpFQ9cYprI+/86ma7ELCpuNe dVgeobxQb/jyhf4acdBU+t5aZz+j8VPhPtIPrPY2kOVDuL1NfeQNS8VmGNpFhR+0 6hqVrtfvbYdLBrAHrU/V/RwZlBJvI/D/I2QGuvZZwWzCBgYd4u4bGuRyBCvGDxOD CTPaEqYyzjvpVuzu7AGQk655WkZQnyPmiezIl2lit1meEMMMv80HePkyWHclZo7Q hMqsEasSp5w5Q5EpYqVr1z5IdBAV1O53oor9W573J3kEoB4o1zEsTPfLO4N1dgXo bfvc24uW3zyChWY2hWyRKvOzvAoClnjfY6whv9NRP0Qi4UjzhLlNOpmhm9cst/J+ uj2Nn8UJtyvFJbTmDvoocpgdhq2mkGKdIVhVQ6tG7PjihFmyQRF7PJZjb+0Vee7L 53F0c4d6HiBI4DHa+lH6fgQUBspIvSfmcnR0ACg29NByib+JEoPSPb4ET+uZ8lLd IbQvNiCdnUduYDCKfo5ea/FesP8AXy1KfSa+z7oEEFYHbbkc7PSztUagEyZdS/yS FnnYqmo/DidmyM4nxDQUII+UDqjng7fo+l4BzIhL12pR693KzCf0mexMr6SA24ny gasN97923OTle1J9xrPrKavkx6WjswZCvOaG7ZbnJB47ydJVu5w= =ZVKY -----END PGP SIGNATURE----- Merge tag 'drm-next-2025-10-01' of https://gitlab.freedesktop.org/drm/kernel Pull drm updates from Dave Airlie: "cross-subsystem: - i2c-hid: Make elan touch controllers power on after panel is enabled - dt bindings for STM32MP25 SoC - pci vgaarb: use screen_info helpers - rust pin-init updates - add MEI driver for late binding firmware update/load uapi: - add ioctl for reassigning GEM handles - provide boot_display attribute on boot-up devices core: - document DRM_MODE_PAGE_FLIP_EVENT - add vendor specific recovery method to drm device wedged uevent gem: - Simplify gpuvm locking ttm: - add interface to populate buffers sched: - Fix race condition in trace code atomic: - Reallow no-op async page flips display: - dp: Fix command length video: - Improve pixel-format handling for struct screen_info rust: - drop Opaque<> from ioctl args - Alloc: - BorrowedPage type and AsPageIter traits - Implement Vmalloc::to_page() and VmallocPageIter - DMA/Scatterlist: - Add dma::DataDirection and type alias for dma_addr_t - Abstraction for struct scatterlist and sg_table - DRM: - simplify use of generics - add DriverFile type alias - drop Object::SIZE - Rust: - pin-init tree merge - Various methods for AsBytes and FromBytes traits gpuvm: - Support madvice in Xe driver gpusvm: - fix hmm_pfn_to_map_order usage in gpusvm bridge: - Improve and fix ref counting on bridge management - cdns-dsi: Various improvements to mode setting - Support Solomon SSD2825 plus DT bindings - Support Waveshare DSI2DPI plus DT bindings - Support Content Protection property - display-connector: Improve DP display detection - Add support for Radxa Ra620 plus DT bindings - adv7511: Provide SPD and HDMI infoframes - it6505: Replace crypto_shash with sha() - synopsys: Add support for DW DPTX Controller plus DT bindings - adv7511: Write full Audio infoframe - ite6263: Support vendor-specific infoframes - simple: Add support for Realtek RTD2171 DP-to-HDMI plus DT bindings panel: - panel-edp: Support mt8189 Chromebooks; Support BOE NV140WUM-N64; Support SHP LQ134Z1; Fixes - panel-simple: Support Olimex LCD-OLinuXino-5CTS plus DT bindings - Support Samsung AMS561RA01 - Support Hydis HV101HD1 plus DT bindings - ilitek-ili9881c: Refactor mode setting; Add support for Bestar BSD1218-A101KL68 LCD plus DT bindings - lvds: Add support for Ampire AMP19201200B5TZQW-T03 to DT bindings - edp: Add support for additonal mt8189 Chromebook panels - lvds: Add DT bindings for EDT ETML0700Z8DHA amdgpu: - add CRIU support for gem objects - RAS updates - VCN SRAM load fixes - EDID read fixes - eDP ALPM support - Documentation updates - Rework PTE flag generation - DCE6 fixes - VCN devcoredump cleanup - MMHUB client id fixes - VCN 5.0.1 RAS support - SMU 13.0.x updates - Expanded PCIe DPC support - Expanded VCN reset support - VPE per queue reset support - give kernel jobs unique id for tracing - pre-populate exported buffers - cyan skillfish updates - make vbios build number available in sysfs - userq updates - HDCP updates - support MMIO remap page as ttm pool - JPEG parser updates - DCE6 DC updates - use devm for i2c buses - GPUVM locking updates - Drop non-DC DCE11 code - improve fallback handling for pixel encoding amdkfd: - SVM/page migration fixes - debugfs fixes - add CRIO support for gem objects - SVM updates radeon: - use dev_warn_once in CS parsers xe: - add madvise interface - add DRM_IOCTL_XE_VM_QUERY_MEMORY_RANGE_ATTRS to query VMA count and memory attributes - drop L# bank mask reporting from media GT3 on Xe3+. - add SLPC power_profile sysfs interface - add configs attribs to add post/mid context-switch commands - handle firmware reported hardware errors notifying userspace with device wedged uevent - use same dir structure across sysfs/debugfs - cleanup and future proof vram region init - add G-states and PCI link states to debugfs - Add SRIOV support for CCS surfaces on Xe2+ - Enable SRIOV PF mode by default on supported platforms - move flush to common code - extended core workarounds for Xe2/3 - use DRM scheduler for delayed GT TLB invalidations - configs improvements and allow VF device enablement - prep work to expose mmio regions to userspace - VF migration support added - prepare GPU SVM for THP migration - start fixing XE_PAGE_SIZE vs PAGE_SIZE - add PSMI support for hw validation - resize VF bars to max possible size according to number of VFs - Ensure GT is in C0 during resume - pre-populate exported buffers - replace xe_hmm with gpusvm - add more SVM GT stats to debugfs - improve fake pci and WA kunnit handle for new platform testing - Test GuC to GuC comms to add debugging - use attribute groups to simplify sysfs registration - add Late Binding firmware code to interact with MEI i915: - apply multiple JSL/EHL/Gen7/Gen6 workarounds properly - protect against overflow in active_engine() - Use try_cmpxchg64() in __active_lookup() - include GuC registers in error state - get rid of dev->struct_mutex - iopoll: generalize read_poll_timout - lots more display refactoring - Reject HBR3 in any eDP Panel - Prune modes for YUV420 - Display Wa fix, additions, and updates - DP: Fix 2.7 Gbps link training on g4x - DP: Adjust the idle pattern handling - DP: Shuffle the link training code a bit - Don't set/read the DSI C clock divider on GLK - Enable_psr kernel parameter changes - Type-C enabled/disconnected dp-alt sink - Wildcat Lake enabling - DP HDR updates - DRAM detection - wait PSR idle on dsb commit - Remove FBC modulo 4 restriction for ADL-P+ - panic: refactor framebuffer allocation habanalabs: - debug/visibility improvements - vmalloc-backed coherent mmap support - HLDIO infrastructure nova-core: - various register!() macro improvements - minor vbios/firmware fixes/refactoring - advance firmware boot stages; process Booter and patch signatures - process GSP and GSP bootloader - Add r570.144 firmware bindings and update to it - Move GSP boot code to own module - Use new pin-init features to store driver's private data in a single allocation - Update ARef import from sync::aref nova-drm: - Update ARef import from sync::aref tyr: - initial driver skeleton for a rust driver for ARM Mali GPUs - capable of powering up, query metadata and provide it to userspace. msm: - GPU and Core: - in DT bindings describe clocks per GPU type - GMU bandwidth voting for x1-85 - a623/a663 speedbins - cleanup some remaining no-iommu leftovers after VM_BIND conversion - fix GEM obj 32b size truncation - add missing VM_BIND param validation - IFPC for x1-85 and a750 - register xml and gen_header.py sync from mesa - Display: - add missing bindings for display on SC8180X - added DisplayPort MST bindings - conversion from round_rate() to determine_rate() amdxdna: - add IOCTL_AMDXDNA_GET_ARRAY - support user space allocated buffers - streamline PM interfaces - Refactoring wrt. hardware contexts - improve error reporting nouveau: - use GSP firmware by default - improve error reporting - Pre-populate exported buffers ast: - Clean up detection of DRAM config exynos: - add DSIM bridge driver support for Exynos7870 - Document Exynos7870 DSIM compatible in dt-binding panthor: - Print task/pid on errors - Add support for Mali G710, G510, G310, Gx15, Gx20, Gx25 - Improve cache flushing - Fail VM bind if BO has offset renesas: - convert to RUNTIME_PM_OPS rcar-du: - Make number of lanes configurable - Use RUNTIME_PM_OPS - Add support for DSI commands rocket: - Add driver for Rockchip NPU plus DT bindings - Use kfree() and sizeof() correctly - Test DMA status rockchip: - dsi2: Add support for RK3576 plus DT bindings - Add support for RK3588 DPTX output tidss: - Use crtc_ fields for programming display mode - Remove other drivers from aperture pixpaper: - Add support for Mayqueen Pixpaper plus DT bindings v3d: - Support querying nubmer of GPU resets for KHR_robustness stm: - Clean up logging - ltdc: Add support support for STM32MP257F-EV1 plus DT bindings sitronix: - st7571-i2c: Add support for inverted displays and 2-bit grayscale tidss: - Convert to kernel's FIELD_ macros vesadrm: - Support 8-bit palette mode imagination: - Improve power management - Add support for TH1520 GPU - Support Risc-V architectures v3d: - Improve job management and locking vkms: - Support variants of ARGB8888, ARGB16161616, RGB565, RGB888 and P01x - Spport YUV with 16-bit components" * tag 'drm-next-2025-10-01' of https://gitlab.freedesktop.org/drm/kernel: (1455 commits) drm/amd: Add name to modes from amdgpu_connector_add_common_modes() drm/amd: Drop some common modes from amdgpu_connector_add_common_modes() drm/amdgpu: update MODULE_PARM_DESC for freesync_video drm/amd: Use dynamic array size declaration for amdgpu_connector_add_common_modes() drm/amd/display: Share dce100_validate_global with DCE6-8 drm/amd/display: Share dce100_validate_bandwidth with DCE6-8 drm/amdgpu: Fix fence signaling race condition in userqueue amd/amdkfd: enhance kfd process check in switch partition amd/amdkfd: resolve a race in amdgpu_amdkfd_device_fini_sw drm/amd/display: Reject modes with too high pixel clock on DCE6-10 drm/amd: Drop unnecessary check in amdgpu_connector_add_common_modes() drm/amd/display: Only enable common modes for eDP and LVDS drm/amdgpu: remove the redeclaration of variable i drm/amdgpu/userq: assign an error code for invalid userq va drm/amdgpu: revert "rework reserved VMID handling" v2 drm/amdgpu: remove leftover from enforcing isolation by VMID drm/amdgpu: Add fallback to pipe reset if KCQ ring reset fails accel/habanalabs: add Infineon version check accel/habanalabs/gaudi2: read preboot status after recovering from dirty state accel/habanalabs: add HL_GET_P_STATE passthrough type ...pull/1354/merge
commit
58809f614e
2
.mailmap
2
.mailmap
|
|
@ -165,6 +165,8 @@ Casey Connolly <casey.connolly@linaro.org> <caleb@connolly.tech>
|
||||||
Casey Connolly <casey.connolly@linaro.org> <caleb@postmarketos.org>
|
Casey Connolly <casey.connolly@linaro.org> <caleb@postmarketos.org>
|
||||||
Can Guo <quic_cang@quicinc.com> <cang@codeaurora.org>
|
Can Guo <quic_cang@quicinc.com> <cang@codeaurora.org>
|
||||||
Carl Huang <quic_cjhuang@quicinc.com> <cjhuang@codeaurora.org>
|
Carl Huang <quic_cjhuang@quicinc.com> <cjhuang@codeaurora.org>
|
||||||
|
Carl Vanderlip <carl.vanderlip@oss.qualcomm.com> <carlv@codeaurora.org>
|
||||||
|
Carl Vanderlip <carl.vanderlip@oss.qualcomm.com> <quic_carlv@quicinc.com>
|
||||||
Carlos Bilbao <carlos.bilbao@kernel.org> <carlos.bilbao@amd.com>
|
Carlos Bilbao <carlos.bilbao@kernel.org> <carlos.bilbao@amd.com>
|
||||||
Carlos Bilbao <carlos.bilbao@kernel.org> <carlos.bilbao.osdev@gmail.com>
|
Carlos Bilbao <carlos.bilbao@kernel.org> <carlos.bilbao.osdev@gmail.com>
|
||||||
Carlos Bilbao <carlos.bilbao@kernel.org> <bilbao@vt.edu>
|
Carlos Bilbao <carlos.bilbao@kernel.org> <bilbao@vt.edu>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
What: /sys/class/drm/.../boot_display
|
||||||
|
Date: January 2026
|
||||||
|
Contact: Linux DRI developers <dri-devel@vger.kernel.org>
|
||||||
|
Description:
|
||||||
|
This file indicates that displays connected to the device were
|
||||||
|
used to display the boot sequence. If a display connected to
|
||||||
|
the device was used to display the boot sequence the file will
|
||||||
|
be present and contain "1".
|
||||||
|
|
@ -223,13 +223,13 @@ Userspace components
|
||||||
Compiler
|
Compiler
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Peano is an LLVM based open-source compiler for AMD XDNA Array compute tile
|
Peano is an LLVM based open-source single core compiler for AMD XDNA Array
|
||||||
available at:
|
compute tile. Peano is available at:
|
||||||
https://github.com/Xilinx/llvm-aie
|
https://github.com/Xilinx/llvm-aie
|
||||||
|
|
||||||
The open-source IREE compiler supports graph compilation of ML models for AMD
|
IRON is an open-source array compiler for AMD XDNA Array based NPU which uses
|
||||||
NPU and uses Peano underneath. It is available at:
|
Peano underneath. IRON is available at:
|
||||||
https://github.com/nod-ai/iree-amd-aie
|
https://github.com/Xilinx/mlir-aie
|
||||||
|
|
||||||
Usermode Driver (UMD)
|
Usermode Driver (UMD)
|
||||||
---------------------
|
---------------------
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ Compute Accelerators
|
||||||
introduction
|
introduction
|
||||||
amdxdna/index
|
amdxdna/index
|
||||||
qaic/index
|
qaic/index
|
||||||
|
rocket/index
|
||||||
|
|
||||||
.. only:: subproject and html
|
.. only:: subproject and html
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
.. SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
=====================================
|
||||||
|
accel/rocket Rockchip NPU driver
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
The accel/rocket driver supports the Neural Processing Units (NPUs) inside some
|
||||||
|
Rockchip SoCs such as the RK3588. Rockchip calls it RKNN and sometimes RKNPU.
|
||||||
|
|
||||||
|
The hardware is described in chapter 36 in the RK3588 TRM.
|
||||||
|
|
||||||
|
This driver just powers the hardware on and off, allocates and maps buffers to
|
||||||
|
the device and submits jobs to the frontend unit. Everything else is done in
|
||||||
|
userspace, as a Gallium driver (also called rocket) that is part of the Mesa3D
|
||||||
|
project.
|
||||||
|
|
||||||
|
Hardware currently supported:
|
||||||
|
|
||||||
|
* RK3588
|
||||||
|
|
@ -36,20 +36,31 @@ properties:
|
||||||
clocks:
|
clocks:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
"#clock-cells":
|
||||||
|
const: 0
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
|
||||||
if:
|
allOf:
|
||||||
|
- if:
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
contains:
|
contains:
|
||||||
enum:
|
enum:
|
||||||
- st,stm32mp157-syscfg
|
- st,stm32mp157-syscfg
|
||||||
- st,stm32f4-gcan
|
- st,stm32f4-gcan
|
||||||
then:
|
then:
|
||||||
required:
|
required:
|
||||||
- clocks
|
- clocks
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: st,stm32mp25-syscfg
|
||||||
|
then:
|
||||||
|
required:
|
||||||
|
- "#clock-cells"
|
||||||
|
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ properties:
|
||||||
- samsung,exynos5410-mipi-dsi
|
- samsung,exynos5410-mipi-dsi
|
||||||
- samsung,exynos5422-mipi-dsi
|
- samsung,exynos5422-mipi-dsi
|
||||||
- samsung,exynos5433-mipi-dsi
|
- samsung,exynos5433-mipi-dsi
|
||||||
|
- samsung,exynos7870-mipi-dsi
|
||||||
- fsl,imx8mm-mipi-dsim
|
- fsl,imx8mm-mipi-dsim
|
||||||
- fsl,imx8mp-mipi-dsim
|
- fsl,imx8mp-mipi-dsim
|
||||||
- items:
|
- items:
|
||||||
|
|
@ -144,6 +145,32 @@ required:
|
||||||
|
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: ../dsi-controller.yaml#
|
- $ref: ../dsi-controller.yaml#
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
const: samsung,exynos7870-mipi-dsi
|
||||||
|
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 4
|
||||||
|
maxItems: 4
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: bus
|
||||||
|
- const: pll
|
||||||
|
- const: byte
|
||||||
|
- const: esc
|
||||||
|
|
||||||
|
ports:
|
||||||
|
required:
|
||||||
|
- port@0
|
||||||
|
|
||||||
|
required:
|
||||||
|
- ports
|
||||||
|
|
||||||
- if:
|
- if:
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ properties:
|
||||||
- enum:
|
- enum:
|
||||||
- adi,adv7123
|
- adi,adv7123
|
||||||
- dumb-vga-dac
|
- dumb-vga-dac
|
||||||
|
- radxa,ra620
|
||||||
|
- realtek,rtd2171
|
||||||
- ti,opa362
|
- ti,opa362
|
||||||
- ti,ths8134
|
- ti,ths8134
|
||||||
- ti,ths8135
|
- ti,ths8135
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/bridge/solomon,ssd2825.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Solomon SSD2825 RGB to MIPI-DSI bridge
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Svyatoslav Ryhel <clamor95@gmail.com>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: solomon,ssd2825
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
reset-gpios: true
|
||||||
|
|
||||||
|
dvdd-supply:
|
||||||
|
description: Regulator for 1.2V digital power supply.
|
||||||
|
|
||||||
|
avdd-supply:
|
||||||
|
description: Regulator for 1.2V analog power supply.
|
||||||
|
|
||||||
|
vddio-supply:
|
||||||
|
description: Regulator for 1.8V IO power supply.
|
||||||
|
|
||||||
|
spi-max-frequency:
|
||||||
|
maximum: 1000000
|
||||||
|
|
||||||
|
spi-cpha: true
|
||||||
|
spi-cpol: true
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
maxItems: 1
|
||||||
|
description: Reference TX_CLK used before PLL is locked.
|
||||||
|
|
||||||
|
solomon,hs-zero-delay-ns:
|
||||||
|
description:
|
||||||
|
HS zero delay period
|
||||||
|
minimum: 0
|
||||||
|
maximum: 1700
|
||||||
|
default: 133
|
||||||
|
|
||||||
|
solomon,hs-prep-delay-ns:
|
||||||
|
description:
|
||||||
|
HS prep delay period
|
||||||
|
minimum: 0
|
||||||
|
maximum: 1728
|
||||||
|
default: 40
|
||||||
|
|
||||||
|
ports:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/ports
|
||||||
|
|
||||||
|
properties:
|
||||||
|
port@0:
|
||||||
|
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||||
|
unevaluatedProperties: false
|
||||||
|
description:
|
||||||
|
Video port for RGB input
|
||||||
|
|
||||||
|
properties:
|
||||||
|
endpoint:
|
||||||
|
$ref: /schemas/graph.yaml#/$defs/endpoint-base
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
properties:
|
||||||
|
bus-width:
|
||||||
|
enum: [ 16, 18, 24 ]
|
||||||
|
|
||||||
|
port@1:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
|
description:
|
||||||
|
Video port for DSI output (panel or connector)
|
||||||
|
|
||||||
|
required:
|
||||||
|
- port@0
|
||||||
|
- port@1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- ports
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
spi {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
dsi@2 {
|
||||||
|
compatible = "solomon,ssd2825";
|
||||||
|
reg = <2>;
|
||||||
|
|
||||||
|
spi-max-frequency = <1000000>;
|
||||||
|
|
||||||
|
spi-cpha;
|
||||||
|
spi-cpol;
|
||||||
|
|
||||||
|
reset-gpios = <&gpio 114 GPIO_ACTIVE_LOW>;
|
||||||
|
|
||||||
|
dvdd-supply = <&vdd_1v2>;
|
||||||
|
avdd-supply = <&vdd_1v2>;
|
||||||
|
vddio-supply = <&vdd_1v8_io>;
|
||||||
|
|
||||||
|
solomon,hs-zero-delay-ns = <300>;
|
||||||
|
solomon,hs-prep-delay-ns = <65>;
|
||||||
|
|
||||||
|
clocks = <&ssd2825_tx_clk>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
bridge_input: endpoint {
|
||||||
|
remote-endpoint = <&dpi_output>;
|
||||||
|
bus-width = <24>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
|
||||||
|
bridge_output: endpoint {
|
||||||
|
remote-endpoint = <&panel_input>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/bridge/waveshare,dsi2dpi.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Waveshare MIPI-DSI to DPI Converter bridge
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Joseph Guo <qijian.guo@nxp.com>
|
||||||
|
|
||||||
|
description:
|
||||||
|
Waveshare bridge board is part of Waveshare panel which converts DSI to DPI.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: waveshare,dsi2dpi
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
description: base I2C address of the device
|
||||||
|
|
||||||
|
power-supply: true
|
||||||
|
|
||||||
|
ports:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/ports
|
||||||
|
|
||||||
|
properties:
|
||||||
|
port@0:
|
||||||
|
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||||
|
unevaluatedProperties: false
|
||||||
|
description:
|
||||||
|
Video port for MIPI DSI input
|
||||||
|
|
||||||
|
properties:
|
||||||
|
endpoint:
|
||||||
|
$ref: /schemas/media/video-interfaces.yaml#
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
properties:
|
||||||
|
data-lanes:
|
||||||
|
description: array of physical DSI data lane indexes.
|
||||||
|
items:
|
||||||
|
- const: 1
|
||||||
|
- const: 2
|
||||||
|
|
||||||
|
required:
|
||||||
|
- data-lanes
|
||||||
|
|
||||||
|
port@1:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
|
description:
|
||||||
|
Video port for MIPI DPI output panel.
|
||||||
|
|
||||||
|
required:
|
||||||
|
- port@0
|
||||||
|
- port@1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- ports
|
||||||
|
- power-supply
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
|
||||||
|
i2c {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
bridge@45 {
|
||||||
|
compatible = "waveshare,dsi2dpi";
|
||||||
|
reg = <0x45>;
|
||||||
|
power-supply = <®_3p3v>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
waveshare_from_dsim: endpoint {
|
||||||
|
data-lanes = <1 2>;
|
||||||
|
remote-endpoint = <&dsim_to_waveshare>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
|
||||||
|
waveshare_to_panel: endpoint {
|
||||||
|
remote-endpoint = <&panel_to_waveshare>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/mayqueen,pixpaper.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Mayqueen Pixpaper e-ink display panel
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- LiangCheng Wang <zaq14760@gmail.com>
|
||||||
|
|
||||||
|
description:
|
||||||
|
The Pixpaper is an e-ink display panel controlled via an SPI interface.
|
||||||
|
The panel has a resolution of 122x250 pixels and requires GPIO pins for
|
||||||
|
reset, busy, and data/command control.
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: mayqueen,pixpaper
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
spi-max-frequency:
|
||||||
|
maximum: 1000000
|
||||||
|
default: 1000000
|
||||||
|
|
||||||
|
reset-gpios:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
busy-gpios:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
dc-gpios:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- reset-gpios
|
||||||
|
- busy-gpios
|
||||||
|
- dc-gpios
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
spi {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
display@0 {
|
||||||
|
compatible = "mayqueen,pixpaper";
|
||||||
|
reg = <0>;
|
||||||
|
spi-max-frequency = <1000000>;
|
||||||
|
reset-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
|
||||||
|
busy-gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>;
|
||||||
|
dc-gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -29,15 +29,30 @@ properties:
|
||||||
- qcom,sdm845-dp
|
- qcom,sdm845-dp
|
||||||
- qcom,sm8350-dp
|
- qcom,sm8350-dp
|
||||||
- qcom,sm8650-dp
|
- qcom,sm8650-dp
|
||||||
|
- qcom,x1e80100-dp
|
||||||
|
|
||||||
|
- items:
|
||||||
|
- enum:
|
||||||
|
- qcom,sm6350-dp
|
||||||
|
- const: qcom,sc7180-dp
|
||||||
|
|
||||||
|
# deprecated entry for compatibility with old DT
|
||||||
|
- items:
|
||||||
|
- enum:
|
||||||
|
- qcom,sm6350-dp
|
||||||
|
- const: qcom,sm8350-dp
|
||||||
|
deprecated: true
|
||||||
|
|
||||||
- items:
|
- items:
|
||||||
- enum:
|
- enum:
|
||||||
- qcom,sar2130p-dp
|
- qcom,sar2130p-dp
|
||||||
- qcom,sm6350-dp
|
- qcom,sm7150-dp
|
||||||
- qcom,sm8150-dp
|
- qcom,sm8150-dp
|
||||||
- qcom,sm8250-dp
|
- qcom,sm8250-dp
|
||||||
- qcom,sm8450-dp
|
- qcom,sm8450-dp
|
||||||
- qcom,sm8550-dp
|
- qcom,sm8550-dp
|
||||||
- const: qcom,sm8350-dp
|
- const: qcom,sm8350-dp
|
||||||
|
|
||||||
- items:
|
- items:
|
||||||
- enum:
|
- enum:
|
||||||
- qcom,sm8750-dp
|
- qcom,sm8750-dp
|
||||||
|
|
@ -51,35 +66,37 @@ properties:
|
||||||
- description: link register block
|
- description: link register block
|
||||||
- description: p0 register block
|
- description: p0 register block
|
||||||
- description: p1 register block
|
- description: p1 register block
|
||||||
|
- description: p2 register block
|
||||||
|
- description: p3 register block
|
||||||
|
- description: mst2link register block
|
||||||
|
- description: mst3link register block
|
||||||
|
|
||||||
interrupts:
|
interrupts:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
clocks:
|
clocks:
|
||||||
|
minItems: 5
|
||||||
items:
|
items:
|
||||||
- description: AHB clock to enable register access
|
- description: AHB clock to enable register access
|
||||||
- description: Display Port AUX clock
|
- description: Display Port AUX clock
|
||||||
- description: Display Port Link clock
|
- description: Display Port Link clock
|
||||||
- description: Link interface clock between DP and PHY
|
- description: Link interface clock between DP and PHY
|
||||||
- description: Display Port Pixel clock
|
- description: Display Port stream 0 Pixel clock
|
||||||
|
- description: Display Port stream 1 Pixel clock
|
||||||
|
- description: Display Port stream 2 Pixel clock
|
||||||
|
- description: Display Port stream 3 Pixel clock
|
||||||
|
|
||||||
clock-names:
|
clock-names:
|
||||||
|
minItems: 5
|
||||||
items:
|
items:
|
||||||
- const: core_iface
|
- const: core_iface
|
||||||
- const: core_aux
|
- const: core_aux
|
||||||
- const: ctrl_link
|
- const: ctrl_link
|
||||||
- const: ctrl_link_iface
|
- const: ctrl_link_iface
|
||||||
- const: stream_pixel
|
- const: stream_pixel
|
||||||
|
- const: stream_1_pixel
|
||||||
assigned-clocks:
|
- const: stream_2_pixel
|
||||||
items:
|
- const: stream_3_pixel
|
||||||
- description: link clock source
|
|
||||||
- description: pixel clock source
|
|
||||||
|
|
||||||
assigned-clock-parents:
|
|
||||||
items:
|
|
||||||
- description: phy 0 parent
|
|
||||||
- description: phy 1 parent
|
|
||||||
|
|
||||||
phys:
|
phys:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
@ -161,7 +178,6 @@ required:
|
||||||
allOf:
|
allOf:
|
||||||
# AUX BUS does not exist on DP controllers
|
# AUX BUS does not exist on DP controllers
|
||||||
# Audio output also is present only on DP output
|
# Audio output also is present only on DP output
|
||||||
# p1 regions is present on DP, but not on eDP
|
|
||||||
- if:
|
- if:
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
|
|
@ -173,14 +189,112 @@ allOf:
|
||||||
then:
|
then:
|
||||||
properties:
|
properties:
|
||||||
"#sound-dai-cells": false
|
"#sound-dai-cells": false
|
||||||
|
else:
|
||||||
|
if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- qcom,sa8775p-dp
|
||||||
|
- qcom,x1e80100-dp
|
||||||
|
then:
|
||||||
|
oneOf:
|
||||||
|
- required:
|
||||||
|
- aux-bus
|
||||||
|
- required:
|
||||||
|
- "#sound-dai-cells"
|
||||||
else:
|
else:
|
||||||
properties:
|
properties:
|
||||||
aux-bus: false
|
aux-bus: false
|
||||||
reg:
|
|
||||||
minItems: 5
|
|
||||||
required:
|
required:
|
||||||
- "#sound-dai-cells"
|
- "#sound-dai-cells"
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
# these platforms support SST only
|
||||||
|
- qcom,sc7180-dp
|
||||||
|
- qcom,sc7280-dp
|
||||||
|
- qcom,sc7280-edp
|
||||||
|
- qcom,sc8180x-edp
|
||||||
|
- qcom,sc8280xp-edp
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
minItems: 5
|
||||||
|
maxItems: 5
|
||||||
|
clocks:
|
||||||
|
minItems: 5
|
||||||
|
maxItems: 5
|
||||||
|
clocks-names:
|
||||||
|
minItems: 5
|
||||||
|
maxItems: 5
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
# these platforms support 2 streams MST on some interfaces,
|
||||||
|
# others are SST only
|
||||||
|
- qcom,sc8280xp-dp
|
||||||
|
- qcom,x1e80100-dp
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
minItems: 5
|
||||||
|
maxItems: 5
|
||||||
|
clocks:
|
||||||
|
minItems: 5
|
||||||
|
maxItems: 6
|
||||||
|
clocks-names:
|
||||||
|
minItems: 5
|
||||||
|
maxItems: 6
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
# 2 streams MST
|
||||||
|
enum:
|
||||||
|
- qcom,sc8180x-dp
|
||||||
|
- qcom,sdm845-dp
|
||||||
|
- qcom,sm8350-dp
|
||||||
|
- qcom,sm8650-dp
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
minItems: 5
|
||||||
|
maxItems: 5
|
||||||
|
clocks:
|
||||||
|
minItems: 6
|
||||||
|
maxItems: 6
|
||||||
|
clocks-names:
|
||||||
|
minItems: 6
|
||||||
|
maxItems: 6
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
# these platforms support 4 stream MST on first DP,
|
||||||
|
# 2 streams MST on the second one.
|
||||||
|
- qcom,sa8775p-dp
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
minItems: 9
|
||||||
|
maxItems: 9
|
||||||
|
clocks:
|
||||||
|
minItems: 6
|
||||||
|
maxItems: 8
|
||||||
|
clocks-names:
|
||||||
|
minItems: 6
|
||||||
|
maxItems: 8
|
||||||
|
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ properties:
|
||||||
- qcom,sar2130p-dsi-ctrl
|
- qcom,sar2130p-dsi-ctrl
|
||||||
- qcom,sc7180-dsi-ctrl
|
- qcom,sc7180-dsi-ctrl
|
||||||
- qcom,sc7280-dsi-ctrl
|
- qcom,sc7280-dsi-ctrl
|
||||||
|
- qcom,sc8180x-dsi-ctrl
|
||||||
- qcom,sdm660-dsi-ctrl
|
- qcom,sdm660-dsi-ctrl
|
||||||
- qcom,sdm670-dsi-ctrl
|
- qcom,sdm670-dsi-ctrl
|
||||||
- qcom,sdm845-dsi-ctrl
|
- qcom,sdm845-dsi-ctrl
|
||||||
|
|
@ -332,6 +333,7 @@ allOf:
|
||||||
- qcom,sar2130p-dsi-ctrl
|
- qcom,sar2130p-dsi-ctrl
|
||||||
- qcom,sc7180-dsi-ctrl
|
- qcom,sc7180-dsi-ctrl
|
||||||
- qcom,sc7280-dsi-ctrl
|
- qcom,sc7280-dsi-ctrl
|
||||||
|
- qcom,sc8180x-dsi-ctrl
|
||||||
- qcom,sdm845-dsi-ctrl
|
- qcom,sdm845-dsi-ctrl
|
||||||
- qcom,sm6115-dsi-ctrl
|
- qcom,sm6115-dsi-ctrl
|
||||||
- qcom,sm6125-dsi-ctrl
|
- qcom,sm6125-dsi-ctrl
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,40 @@ allOf:
|
||||||
contains:
|
contains:
|
||||||
enum:
|
enum:
|
||||||
- qcom,adreno-gmu-623.0
|
- qcom,adreno-gmu-623.0
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
items:
|
||||||
|
- description: Core GMU registers
|
||||||
|
- description: Resource controller registers
|
||||||
|
- description: GMU PDC registers
|
||||||
|
reg-names:
|
||||||
|
items:
|
||||||
|
- const: gmu
|
||||||
|
- const: rscc
|
||||||
|
- const: gmu_pdc
|
||||||
|
clocks:
|
||||||
|
items:
|
||||||
|
- description: GMU clock
|
||||||
|
- description: GPU CX clock
|
||||||
|
- description: GPU AXI clock
|
||||||
|
- description: GPU MEMNOC clock
|
||||||
|
- description: GPU AHB clock
|
||||||
|
- description: GPU HUB CX clock
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: gmu
|
||||||
|
- const: cxo
|
||||||
|
- const: axi
|
||||||
|
- const: memnoc
|
||||||
|
- const: ahb
|
||||||
|
- const: hub
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
- qcom,adreno-gmu-635.0
|
- qcom,adreno-gmu-635.0
|
||||||
- qcom,adreno-gmu-660.1
|
- qcom,adreno-gmu-660.1
|
||||||
- qcom,adreno-gmu-663.0
|
- qcom,adreno-gmu-663.0
|
||||||
|
|
|
||||||
|
|
@ -146,17 +146,93 @@ allOf:
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
contains:
|
contains:
|
||||||
pattern: '^qcom,adreno-[3-5][0-9][0-9]\.[0-9]+$'
|
oneOf:
|
||||||
|
- pattern: '^qcom,adreno-305\.[0-9]+$'
|
||||||
|
- pattern: '^qcom,adreno-330\.[0-9]+$'
|
||||||
then:
|
then:
|
||||||
properties:
|
properties:
|
||||||
clocks:
|
clocks:
|
||||||
minItems: 2
|
minItems: 3
|
||||||
maxItems: 7
|
maxItems: 3
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: core
|
||||||
|
description: GPU Core clock
|
||||||
|
- const: iface
|
||||||
|
description: GPU Interface clock
|
||||||
|
- const: mem_iface
|
||||||
|
description: GPU Memory Interface clock
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
pattern: '^qcom,adreno-306\.[0-9]+$'
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 5
|
||||||
|
maxItems: 6
|
||||||
|
clock-names:
|
||||||
|
oneOf:
|
||||||
|
- items:
|
||||||
|
- const: core
|
||||||
|
description: GPU Core clock
|
||||||
|
- const: iface
|
||||||
|
description: GPU Interface clock
|
||||||
|
- const: mem_iface
|
||||||
|
description: GPU Memory Interface clock
|
||||||
|
- const: alt_mem_iface
|
||||||
|
description: GPU Alternative Memory Interface clock
|
||||||
|
- const: gfx3d
|
||||||
|
description: GPU 3D engine clock
|
||||||
|
- items:
|
||||||
|
- const: core
|
||||||
|
description: GPU Core clock
|
||||||
|
- const: iface
|
||||||
|
description: GPU Interface clock
|
||||||
|
- const: mem
|
||||||
|
description: GPU Memory clock
|
||||||
|
- const: mem_iface
|
||||||
|
description: GPU Memory Interface clock
|
||||||
|
- const: alt_mem_iface
|
||||||
|
description: GPU Alternative Memory Interface clock
|
||||||
|
- const: gfx3d
|
||||||
|
description: GPU 3D engine clock
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
pattern: '^qcom,adreno-320\.[0-9]+$'
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 4
|
||||||
|
maxItems: 4
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: core
|
||||||
|
description: GPU Core clock
|
||||||
|
- const: iface
|
||||||
|
description: GPU Interface clock
|
||||||
|
- const: mem
|
||||||
|
description: GPU Memory clock
|
||||||
|
- const: mem_iface
|
||||||
|
description: GPU Memory Interface clock
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
pattern: '^qcom,adreno-405\.[0-9]+$'
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 7
|
||||||
|
maxItems: 7
|
||||||
clock-names:
|
clock-names:
|
||||||
items:
|
items:
|
||||||
anyOf:
|
|
||||||
- const: core
|
- const: core
|
||||||
description: GPU Core clock
|
description: GPU Core clock
|
||||||
- const: iface
|
- const: iface
|
||||||
|
|
@ -171,14 +247,108 @@ allOf:
|
||||||
description: GPU 3D engine clock
|
description: GPU 3D engine clock
|
||||||
- const: rbbmtimer
|
- const: rbbmtimer
|
||||||
description: GPU RBBM Timer for Adreno 5xx series
|
description: GPU RBBM Timer for Adreno 5xx series
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
pattern: '^qcom,adreno-50[56]\.[0-9]+$'
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 6
|
||||||
|
maxItems: 6
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: core
|
||||||
|
description: GPU Core clock
|
||||||
|
- const: iface
|
||||||
|
description: GPU Interface clock
|
||||||
|
- const: mem_iface
|
||||||
|
description: GPU Memory Interface clock
|
||||||
|
- const: alt_mem_iface
|
||||||
|
description: GPU Alternative Memory Interface clock
|
||||||
|
- const: rbbmtimer
|
||||||
|
description: GPU RBBM Timer for Adreno 5xx series
|
||||||
|
- const: alwayson
|
||||||
|
description: GPU AON clock
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
oneOf:
|
||||||
|
- pattern: '^qcom,adreno-508\.[0-9]+$'
|
||||||
|
- pattern: '^qcom,adreno-509\.[0-9]+$'
|
||||||
|
- pattern: '^qcom,adreno-512\.[0-9]+$'
|
||||||
|
- pattern: '^qcom,adreno-540\.[0-9]+$'
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 6
|
||||||
|
maxItems: 6
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: iface
|
||||||
|
description: GPU Interface clock
|
||||||
|
- const: rbbmtimer
|
||||||
|
description: GPU RBBM Timer for Adreno 5xx series
|
||||||
|
- const: mem
|
||||||
|
description: GPU Memory clock
|
||||||
|
- const: mem_iface
|
||||||
|
description: GPU Memory Interface clock
|
||||||
- const: rbcpr
|
- const: rbcpr
|
||||||
description: GPU RB Core Power Reduction clock
|
description: GPU RB Core Power Reduction clock
|
||||||
minItems: 2
|
- const: core
|
||||||
maxItems: 7
|
description: GPU Core clock
|
||||||
|
|
||||||
required:
|
- if:
|
||||||
- clocks
|
properties:
|
||||||
- clock-names
|
compatible:
|
||||||
|
contains:
|
||||||
|
pattern: '^qcom,adreno-510\.[0-9]+$'
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 6
|
||||||
|
maxItems: 6
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: core
|
||||||
|
description: GPU Core clock
|
||||||
|
- const: iface
|
||||||
|
description: GPU Interface clock
|
||||||
|
- const: mem
|
||||||
|
description: GPU Memory clock
|
||||||
|
- const: mem_iface
|
||||||
|
description: GPU Memory Interface clock
|
||||||
|
- const: rbbmtimer
|
||||||
|
description: GPU RBBM Timer for Adreno 5xx series
|
||||||
|
- const: alwayson
|
||||||
|
description: GPU AON clock
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
pattern: '^qcom,adreno-530\.[0-9]+$'
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 5
|
||||||
|
maxItems: 5
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: core
|
||||||
|
description: GPU Core clock
|
||||||
|
- const: iface
|
||||||
|
description: GPU Interface clock
|
||||||
|
- const: rbbmtimer
|
||||||
|
description: GPU RBBM Timer for Adreno 5xx series
|
||||||
|
- const: mem
|
||||||
|
description: GPU Memory clock
|
||||||
|
- const: mem_iface
|
||||||
|
description: GPU Memory Interface clock
|
||||||
|
|
||||||
- if:
|
- if:
|
||||||
properties:
|
properties:
|
||||||
|
|
@ -187,6 +357,7 @@ allOf:
|
||||||
enum:
|
enum:
|
||||||
- qcom,adreno-610.0
|
- qcom,adreno-610.0
|
||||||
- qcom,adreno-619.1
|
- qcom,adreno-619.1
|
||||||
|
- qcom,adreno-07000200
|
||||||
then:
|
then:
|
||||||
properties:
|
properties:
|
||||||
clocks:
|
clocks:
|
||||||
|
|
@ -222,7 +393,9 @@ allOf:
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
contains:
|
contains:
|
||||||
pattern: '^qcom,adreno-[67][0-9][0-9]\.[0-9]+$'
|
oneOf:
|
||||||
|
- pattern: '^qcom,adreno-[67][0-9][0-9]\.[0-9]+$'
|
||||||
|
- pattern: '^qcom,adreno-[0-9a-f]{8}$'
|
||||||
|
|
||||||
then: # Starting with A6xx, the clocks are usually defined in the GMU node
|
then: # Starting with A6xx, the clocks are usually defined in the GMU node
|
||||||
properties:
|
properties:
|
||||||
|
|
|
||||||
|
|
@ -375,7 +375,11 @@ examples:
|
||||||
<0xaf54200 0x0c0>,
|
<0xaf54200 0x0c0>,
|
||||||
<0xaf55000 0x770>,
|
<0xaf55000 0x770>,
|
||||||
<0xaf56000 0x09c>,
|
<0xaf56000 0x09c>,
|
||||||
<0xaf57000 0x09c>;
|
<0xaf57000 0x09c>,
|
||||||
|
<0xaf58000 0x09c>,
|
||||||
|
<0xaf59000 0x09c>,
|
||||||
|
<0xaf5a000 0x23c>,
|
||||||
|
<0xaf5b000 0x23c>;
|
||||||
|
|
||||||
interrupt-parent = <&mdss0>;
|
interrupt-parent = <&mdss0>;
|
||||||
interrupts = <12>;
|
interrupts = <12>;
|
||||||
|
|
@ -384,16 +388,28 @@ examples:
|
||||||
<&dispcc_dptx0_aux_clk>,
|
<&dispcc_dptx0_aux_clk>,
|
||||||
<&dispcc_dptx0_link_clk>,
|
<&dispcc_dptx0_link_clk>,
|
||||||
<&dispcc_dptx0_link_intf_clk>,
|
<&dispcc_dptx0_link_intf_clk>,
|
||||||
<&dispcc_dptx0_pixel0_clk>;
|
<&dispcc_dptx0_pixel0_clk>,
|
||||||
|
<&dispcc_dptx0_pixel1_clk>,
|
||||||
|
<&dispcc_dptx0_pixel2_clk>,
|
||||||
|
<&dispcc_dptx0_pixel3_clk>;
|
||||||
clock-names = "core_iface",
|
clock-names = "core_iface",
|
||||||
"core_aux",
|
"core_aux",
|
||||||
"ctrl_link",
|
"ctrl_link",
|
||||||
"ctrl_link_iface",
|
"ctrl_link_iface",
|
||||||
"stream_pixel";
|
"stream_pixel",
|
||||||
|
"stream_1_pixel",
|
||||||
|
"stream_2_pixel",
|
||||||
|
"stream_3_pixel";
|
||||||
|
|
||||||
assigned-clocks = <&dispcc_mdss_dptx0_link_clk_src>,
|
assigned-clocks = <&dispcc_mdss_dptx0_link_clk_src>,
|
||||||
<&dispcc_mdss_dptx0_pixel0_clk_src>;
|
<&dispcc_mdss_dptx0_pixel0_clk_src>,
|
||||||
assigned-clock-parents = <&mdss0_dp0_phy 0>, <&mdss0_dp0_phy 1>;
|
<&dispcc_mdss_dptx0_pixel1_clk_src>,
|
||||||
|
<&dispcc_mdss_dptx0_pixel2_clk_src>,
|
||||||
|
<&dispcc_mdss_dptx0_pixel3_clk_src>;
|
||||||
|
assigned-clock-parents = <&mdss0_dp0_phy 0>,
|
||||||
|
<&mdss0_dp0_phy 1>,
|
||||||
|
<&mdss0_dp0_phy 1>,
|
||||||
|
<&mdss0_dp0_phy 1>;
|
||||||
|
|
||||||
phys = <&mdss0_dp0_phy>;
|
phys = <&mdss0_dp0_phy>;
|
||||||
phy-names = "dp";
|
phy-names = "dp";
|
||||||
|
|
|
||||||
|
|
@ -207,16 +207,20 @@ examples:
|
||||||
<&dispcc_disp_cc_mdss_dptx0_aux_clk>,
|
<&dispcc_disp_cc_mdss_dptx0_aux_clk>,
|
||||||
<&dispcc_disp_cc_mdss_dptx0_link_clk>,
|
<&dispcc_disp_cc_mdss_dptx0_link_clk>,
|
||||||
<&dispcc_disp_cc_mdss_dptx0_link_intf_clk>,
|
<&dispcc_disp_cc_mdss_dptx0_link_intf_clk>,
|
||||||
<&dispcc_disp_cc_mdss_dptx0_pixel0_clk>;
|
<&dispcc_disp_cc_mdss_dptx0_pixel0_clk>,
|
||||||
|
<&dispcc_disp_cc_mdss_dptx0_pixel1_clk>;
|
||||||
clock-names = "core_iface",
|
clock-names = "core_iface",
|
||||||
"core_aux",
|
"core_aux",
|
||||||
"ctrl_link",
|
"ctrl_link",
|
||||||
"ctrl_link_iface",
|
"ctrl_link_iface",
|
||||||
"stream_pixel";
|
"stream_pixel",
|
||||||
|
"stream_1_pixel";
|
||||||
|
|
||||||
assigned-clocks = <&dispcc_disp_cc_mdss_dptx0_link_clk_src>,
|
assigned-clocks = <&dispcc_disp_cc_mdss_dptx0_link_clk_src>,
|
||||||
<&dispcc_disp_cc_mdss_dptx0_pixel0_clk_src>;
|
<&dispcc_disp_cc_mdss_dptx0_pixel0_clk_src>,
|
||||||
|
<&dispcc_disp_cc_mdss_dptx0_pixel1_clk_src>;
|
||||||
assigned-clock-parents = <&usb_dp_qmpphy_QMP_USB43DP_DP_LINK_CLK>,
|
assigned-clock-parents = <&usb_dp_qmpphy_QMP_USB43DP_DP_LINK_CLK>,
|
||||||
|
<&usb_dp_qmpphy_QMP_USB43DP_DP_VCO_DIV_CLK>,
|
||||||
<&usb_dp_qmpphy_QMP_USB43DP_DP_VCO_DIV_CLK>;
|
<&usb_dp_qmpphy_QMP_USB43DP_DP_VCO_DIV_CLK>;
|
||||||
|
|
||||||
phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>;
|
phys = <&usb_dp_qmpphy QMP_USB43DP_DP_PHY>;
|
||||||
|
|
|
||||||
|
|
@ -281,7 +281,8 @@ examples:
|
||||||
reg = <0xaea0000 0x200>,
|
reg = <0xaea0000 0x200>,
|
||||||
<0xaea0200 0x200>,
|
<0xaea0200 0x200>,
|
||||||
<0xaea0400 0xc00>,
|
<0xaea0400 0xc00>,
|
||||||
<0xaea1000 0x400>;
|
<0xaea1000 0x400>,
|
||||||
|
<0xaea1400 0x400>;
|
||||||
|
|
||||||
interrupt-parent = <&mdss>;
|
interrupt-parent = <&mdss>;
|
||||||
interrupts = <14>;
|
interrupts = <14>;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/msm/qcom,sc8180x-dpu.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Qualcomm SC8180X Display DPU
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||||
|
|
||||||
|
$ref: /schemas/display/msm/dpu-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: qcom,sc8180x-dpu
|
||||||
|
|
||||||
|
reg:
|
||||||
|
items:
|
||||||
|
- description: Address offset and size for mdp register set
|
||||||
|
- description: Address offset and size for vbif register set
|
||||||
|
|
||||||
|
reg-names:
|
||||||
|
items:
|
||||||
|
- const: mdp
|
||||||
|
- const: vbif
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
items:
|
||||||
|
- description: Display AHB clock
|
||||||
|
- description: Display HF AXI clock
|
||||||
|
- description: Display core clock
|
||||||
|
- description: Display vsync clock
|
||||||
|
- description: Display rotator clock
|
||||||
|
- description: Display LUT clock
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: iface
|
||||||
|
- const: bus
|
||||||
|
- const: core
|
||||||
|
- const: vsync
|
||||||
|
- const: rot
|
||||||
|
- const: lut
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/clock/qcom,dispcc-sm8250.h>
|
||||||
|
#include <dt-bindings/clock/qcom,gcc-sc8180x.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <dt-bindings/interconnect/qcom,sc8180x.h>
|
||||||
|
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||||
|
|
||||||
|
display-controller@ae01000 {
|
||||||
|
compatible = "qcom,sc8180x-dpu";
|
||||||
|
reg = <0x0ae01000 0x8f000>,
|
||||||
|
<0x0aeb0000 0x2008>;
|
||||||
|
reg-names = "mdp", "vbif";
|
||||||
|
|
||||||
|
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||||
|
<&gcc GCC_DISP_HF_AXI_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_MDP_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_VSYNC_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_ROT_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_MDP_LUT_CLK>;
|
||||||
|
clock-names = "iface",
|
||||||
|
"bus",
|
||||||
|
"core",
|
||||||
|
"vsync",
|
||||||
|
"rot",
|
||||||
|
"lut";
|
||||||
|
|
||||||
|
assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||||
|
assigned-clock-rates = <19200000>;
|
||||||
|
|
||||||
|
operating-points-v2 = <&mdp_opp_table>;
|
||||||
|
power-domains = <&rpmhpd SC8180X_MMCX>;
|
||||||
|
|
||||||
|
interrupt-parent = <&mdss>;
|
||||||
|
interrupts = <0>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
endpoint {
|
||||||
|
remote-endpoint = <&dsi0_in>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
endpoint {
|
||||||
|
remote-endpoint = <&dsi1_in>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
||||||
|
|
@ -0,0 +1,359 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/msm/qcom,sc8180x-mdss.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Qualcomm SC8180X Display MDSS
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||||
|
|
||||||
|
description:
|
||||||
|
Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
|
||||||
|
sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
|
||||||
|
bindings of MDSS are mentioned for SC8180X target.
|
||||||
|
|
||||||
|
$ref: /schemas/display/msm/mdss-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- const: qcom,sc8180x-mdss
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
items:
|
||||||
|
- description: Display AHB clock from gcc
|
||||||
|
- description: Display hf axi clock
|
||||||
|
- description: Display sf axi clock
|
||||||
|
- description: Display core clock
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: iface
|
||||||
|
- const: bus
|
||||||
|
- const: nrt_bus
|
||||||
|
- const: core
|
||||||
|
|
||||||
|
iommus:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interconnects:
|
||||||
|
maxItems: 3
|
||||||
|
|
||||||
|
interconnect-names:
|
||||||
|
maxItems: 3
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
"^display-controller@[0-9a-f]+$":
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: qcom,sc8180x-dpu
|
||||||
|
|
||||||
|
"^displayport-controller@[0-9a-f]+$":
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- qcom,sc8180x-dp
|
||||||
|
- qcom,sc8180x-edp
|
||||||
|
|
||||||
|
"^dsi@[0-9a-f]+$":
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
const: qcom,sc8180x-dsi-ctrl
|
||||||
|
|
||||||
|
"^phy@[0-9a-f]+$":
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: qcom,dsi-phy-7nm
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/clock/qcom,dispcc-sm8250.h>
|
||||||
|
#include <dt-bindings/clock/qcom,gcc-sc8180x.h>
|
||||||
|
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <dt-bindings/interconnect/qcom,sc8180x.h>
|
||||||
|
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||||
|
|
||||||
|
display-subsystem@ae00000 {
|
||||||
|
compatible = "qcom,sc8180x-mdss";
|
||||||
|
reg = <0x0ae00000 0x1000>;
|
||||||
|
reg-names = "mdss";
|
||||||
|
|
||||||
|
interconnects = <&mmss_noc MASTER_MDP_PORT0 &mc_virt SLAVE_EBI_CH0>,
|
||||||
|
<&mmss_noc MASTER_MDP_PORT1 &mc_virt SLAVE_EBI_CH0>,
|
||||||
|
<&gem_noc MASTER_AMPSS_M0 &config_noc SLAVE_DISPLAY_CFG>;
|
||||||
|
interconnect-names = "mdp0-mem",
|
||||||
|
"mdp1-mem",
|
||||||
|
"cpu-cfg";
|
||||||
|
|
||||||
|
power-domains = <&dispcc MDSS_GDSC>;
|
||||||
|
|
||||||
|
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||||
|
<&gcc GCC_DISP_HF_AXI_CLK>,
|
||||||
|
<&gcc GCC_DISP_SF_AXI_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_MDP_CLK>;
|
||||||
|
clock-names = "iface", "bus", "nrt_bus", "core";
|
||||||
|
|
||||||
|
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
interrupt-controller;
|
||||||
|
#interrupt-cells = <1>;
|
||||||
|
|
||||||
|
iommus = <&apps_smmu 0x800 0x420>;
|
||||||
|
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
ranges;
|
||||||
|
|
||||||
|
display-controller@ae01000 {
|
||||||
|
compatible = "qcom,sc8180x-dpu";
|
||||||
|
reg = <0x0ae01000 0x8f000>,
|
||||||
|
<0x0aeb0000 0x2008>;
|
||||||
|
reg-names = "mdp", "vbif";
|
||||||
|
|
||||||
|
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||||
|
<&gcc GCC_DISP_HF_AXI_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_MDP_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_VSYNC_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_ROT_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_MDP_LUT_CLK>;
|
||||||
|
clock-names = "iface",
|
||||||
|
"bus",
|
||||||
|
"core",
|
||||||
|
"vsync",
|
||||||
|
"rot",
|
||||||
|
"lut";
|
||||||
|
|
||||||
|
assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
|
||||||
|
assigned-clock-rates = <19200000>;
|
||||||
|
|
||||||
|
operating-points-v2 = <&mdp_opp_table>;
|
||||||
|
power-domains = <&rpmhpd SC8180X_MMCX>;
|
||||||
|
|
||||||
|
interrupt-parent = <&mdss>;
|
||||||
|
interrupts = <0>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
dpu_intf1_out: endpoint {
|
||||||
|
remote-endpoint = <&dsi0_in>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
dpu_intf2_out: endpoint {
|
||||||
|
remote-endpoint = <&dsi1_in>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mdp_opp_table: opp-table {
|
||||||
|
compatible = "operating-points-v2";
|
||||||
|
|
||||||
|
opp-171428571 {
|
||||||
|
opp-hz = /bits/ 64 <171428571>;
|
||||||
|
required-opps = <&rpmhpd_opp_low_svs>;
|
||||||
|
};
|
||||||
|
|
||||||
|
opp-300000000 {
|
||||||
|
opp-hz = /bits/ 64 <300000000>;
|
||||||
|
required-opps = <&rpmhpd_opp_svs>;
|
||||||
|
};
|
||||||
|
|
||||||
|
opp-345000000 {
|
||||||
|
opp-hz = /bits/ 64 <345000000>;
|
||||||
|
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
opp-460000000 {
|
||||||
|
opp-hz = /bits/ 64 <460000000>;
|
||||||
|
required-opps = <&rpmhpd_opp_nom>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
dsi@ae94000 {
|
||||||
|
compatible = "qcom,sc8180x-dsi-ctrl",
|
||||||
|
"qcom,mdss-dsi-ctrl";
|
||||||
|
reg = <0x0ae94000 0x400>;
|
||||||
|
reg-names = "dsi_ctrl";
|
||||||
|
|
||||||
|
interrupt-parent = <&mdss>;
|
||||||
|
interrupts = <4>;
|
||||||
|
|
||||||
|
clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_PCLK0_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_ESC0_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||||
|
<&gcc GCC_DISP_HF_AXI_CLK>;
|
||||||
|
clock-names = "byte",
|
||||||
|
"byte_intf",
|
||||||
|
"pixel",
|
||||||
|
"core",
|
||||||
|
"iface",
|
||||||
|
"bus";
|
||||||
|
|
||||||
|
assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
|
||||||
|
<&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
|
||||||
|
assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>;
|
||||||
|
|
||||||
|
operating-points-v2 = <&dsi_opp_table>;
|
||||||
|
power-domains = <&rpmhpd SC8180X_MMCX>;
|
||||||
|
|
||||||
|
phys = <&dsi0_phy>;
|
||||||
|
phy-names = "dsi";
|
||||||
|
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
dsi0_in: endpoint {
|
||||||
|
remote-endpoint = <&dpu_intf1_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
dsi0_out: endpoint {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
dsi_opp_table: opp-table {
|
||||||
|
compatible = "operating-points-v2";
|
||||||
|
|
||||||
|
opp-187500000 {
|
||||||
|
opp-hz = /bits/ 64 <187500000>;
|
||||||
|
required-opps = <&rpmhpd_opp_low_svs>;
|
||||||
|
};
|
||||||
|
|
||||||
|
opp-300000000 {
|
||||||
|
opp-hz = /bits/ 64 <300000000>;
|
||||||
|
required-opps = <&rpmhpd_opp_svs>;
|
||||||
|
};
|
||||||
|
|
||||||
|
opp-358000000 {
|
||||||
|
opp-hz = /bits/ 64 <358000000>;
|
||||||
|
required-opps = <&rpmhpd_opp_svs_l1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
dsi0_phy: phy@ae94400 {
|
||||||
|
compatible = "qcom,dsi-phy-7nm";
|
||||||
|
reg = <0x0ae94400 0x200>,
|
||||||
|
<0x0ae94600 0x280>,
|
||||||
|
<0x0ae94900 0x260>;
|
||||||
|
reg-names = "dsi_phy",
|
||||||
|
"dsi_phy_lane",
|
||||||
|
"dsi_pll";
|
||||||
|
|
||||||
|
#clock-cells = <1>;
|
||||||
|
#phy-cells = <0>;
|
||||||
|
|
||||||
|
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||||
|
<&rpmhcc RPMH_CXO_CLK>;
|
||||||
|
clock-names = "iface", "ref";
|
||||||
|
vdds-supply = <&vreg_dsi_phy>;
|
||||||
|
};
|
||||||
|
|
||||||
|
dsi@ae96000 {
|
||||||
|
compatible = "qcom,sc8180x-dsi-ctrl",
|
||||||
|
"qcom,mdss-dsi-ctrl";
|
||||||
|
reg = <0x0ae96000 0x400>;
|
||||||
|
reg-names = "dsi_ctrl";
|
||||||
|
|
||||||
|
interrupt-parent = <&mdss>;
|
||||||
|
interrupts = <5>;
|
||||||
|
|
||||||
|
clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_PCLK1_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_ESC1_CLK>,
|
||||||
|
<&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||||
|
<&gcc GCC_DISP_HF_AXI_CLK>;
|
||||||
|
clock-names = "byte",
|
||||||
|
"byte_intf",
|
||||||
|
"pixel",
|
||||||
|
"core",
|
||||||
|
"iface",
|
||||||
|
"bus";
|
||||||
|
|
||||||
|
assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>,
|
||||||
|
<&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>;
|
||||||
|
assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>;
|
||||||
|
|
||||||
|
operating-points-v2 = <&dsi_opp_table>;
|
||||||
|
power-domains = <&rpmhpd SC8180X_MMCX>;
|
||||||
|
|
||||||
|
phys = <&dsi1_phy>;
|
||||||
|
phy-names = "dsi";
|
||||||
|
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
dsi1_in: endpoint {
|
||||||
|
remote-endpoint = <&dpu_intf2_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
dsi1_out: endpoint {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
dsi1_phy: phy@ae96400 {
|
||||||
|
compatible = "qcom,dsi-phy-7nm";
|
||||||
|
reg = <0x0ae96400 0x200>,
|
||||||
|
<0x0ae96600 0x280>,
|
||||||
|
<0x0ae96900 0x260>;
|
||||||
|
reg-names = "dsi_phy",
|
||||||
|
"dsi_phy_lane",
|
||||||
|
"dsi_pll";
|
||||||
|
|
||||||
|
#clock-cells = <1>;
|
||||||
|
#phy-cells = <0>;
|
||||||
|
|
||||||
|
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
|
||||||
|
<&rpmhcc RPMH_CXO_CLK>;
|
||||||
|
clock-names = "iface", "ref";
|
||||||
|
vdds-supply = <&vreg_dsi_phy>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
||||||
|
|
@ -61,6 +61,7 @@ patternProperties:
|
||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
|
contains:
|
||||||
const: qcom,sm7150-dp
|
const: qcom,sm7150-dp
|
||||||
|
|
||||||
"^dsi@[0-9a-f]+$":
|
"^dsi@[0-9a-f]+$":
|
||||||
|
|
@ -378,7 +379,8 @@ examples:
|
||||||
};
|
};
|
||||||
|
|
||||||
displayport-controller@ae90000 {
|
displayport-controller@ae90000 {
|
||||||
compatible = "qcom,sm7150-dp";
|
compatible = "qcom,sm7150-dp",
|
||||||
|
"qcom,sm8350-dp";
|
||||||
reg = <0xae90000 0x200>,
|
reg = <0xae90000 0x200>,
|
||||||
<0xae90200 0x200>,
|
<0xae90200 0x200>,
|
||||||
<0xae90400 0xc00>,
|
<0xae90400 0xc00>,
|
||||||
|
|
@ -392,16 +394,20 @@ examples:
|
||||||
<&dispcc_mdss_dp_aux_clk>,
|
<&dispcc_mdss_dp_aux_clk>,
|
||||||
<&dispcc_mdss_dp_link_clk>,
|
<&dispcc_mdss_dp_link_clk>,
|
||||||
<&dispcc_mdss_dp_link_intf_clk>,
|
<&dispcc_mdss_dp_link_intf_clk>,
|
||||||
<&dispcc_mdss_dp_pixel_clk>;
|
<&dispcc_mdss_dp_pixel_clk>,
|
||||||
|
<&dispcc_mdss_dp_pixel1_clk>;
|
||||||
clock-names = "core_iface",
|
clock-names = "core_iface",
|
||||||
"core_aux",
|
"core_aux",
|
||||||
"ctrl_link",
|
"ctrl_link",
|
||||||
"ctrl_link_iface",
|
"ctrl_link_iface",
|
||||||
"stream_pixel";
|
"stream_pixel",
|
||||||
|
"stream_1_pixel";
|
||||||
|
|
||||||
assigned-clocks = <&dispcc_mdss_dp_link_clk_src>,
|
assigned-clocks = <&dispcc_mdss_dp_link_clk_src>,
|
||||||
<&dispcc_mdss_dp_pixel_clk_src>;
|
<&dispcc_mdss_dp_pixel_clk_src>,
|
||||||
|
<&dispcc_mdss_dp_pixel1_clk_src>;
|
||||||
assigned-clock-parents = <&dp_phy 0>,
|
assigned-clock-parents = <&dp_phy 0>,
|
||||||
|
<&dp_phy 1>,
|
||||||
<&dp_phy 1>;
|
<&dp_phy 1>;
|
||||||
|
|
||||||
operating-points-v2 = <&dp_opp_table>;
|
operating-points-v2 = <&dp_opp_table>;
|
||||||
|
|
|
||||||
|
|
@ -401,16 +401,20 @@ examples:
|
||||||
<&disp_cc_mdss_dptx0_aux_clk>,
|
<&disp_cc_mdss_dptx0_aux_clk>,
|
||||||
<&disp_cc_mdss_dptx0_link_clk>,
|
<&disp_cc_mdss_dptx0_link_clk>,
|
||||||
<&disp_cc_mdss_dptx0_link_intf_clk>,
|
<&disp_cc_mdss_dptx0_link_intf_clk>,
|
||||||
<&disp_cc_mdss_dptx0_pixel0_clk>;
|
<&disp_cc_mdss_dptx0_pixel0_clk>,
|
||||||
|
<&disp_cc_mdss_dptx0_pixel1_clk>;
|
||||||
clock-names = "core_iface",
|
clock-names = "core_iface",
|
||||||
"core_aux",
|
"core_aux",
|
||||||
"ctrl_link",
|
"ctrl_link",
|
||||||
"ctrl_link_iface",
|
"ctrl_link_iface",
|
||||||
"stream_pixel";
|
"stream_pixel",
|
||||||
|
"stream_1_pixel";
|
||||||
|
|
||||||
assigned-clocks = <&disp_cc_mdss_dptx0_link_clk_src>,
|
assigned-clocks = <&disp_cc_mdss_dptx0_link_clk_src>,
|
||||||
<&disp_cc_mdss_dptx0_pixel0_clk_src>;
|
<&disp_cc_mdss_dptx0_pixel0_clk_src>,
|
||||||
|
<&disp_cc_mdss_dptx0_pixel1_clk_src>;
|
||||||
assigned-clock-parents = <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>,
|
assigned-clock-parents = <&usb_dp_qmpphy QMP_USB43DP_DP_LINK_CLK>,
|
||||||
|
<&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>,
|
||||||
<&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
|
<&usb_dp_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
|
||||||
|
|
||||||
operating-points-v2 = <&dp_opp_table>;
|
operating-points-v2 = <&dp_opp_table>;
|
||||||
|
|
|
||||||
|
|
@ -170,11 +170,11 @@ examples:
|
||||||
|
|
||||||
displayport-controller@ae90000 {
|
displayport-controller@ae90000 {
|
||||||
compatible = "qcom,x1e80100-dp";
|
compatible = "qcom,x1e80100-dp";
|
||||||
reg = <0 0xae90000 0 0x200>,
|
reg = <0xae90000 0x200>,
|
||||||
<0 0xae90200 0 0x200>,
|
<0xae90200 0x200>,
|
||||||
<0 0xae90400 0 0x600>,
|
<0xae90400 0x600>,
|
||||||
<0 0xae91000 0 0x400>,
|
<0xae91000 0x400>,
|
||||||
<0 0xae91400 0 0x400>;
|
<0xae91400 0x400>;
|
||||||
|
|
||||||
interrupt-parent = <&mdss>;
|
interrupt-parent = <&mdss>;
|
||||||
interrupts = <12>;
|
interrupts = <12>;
|
||||||
|
|
@ -183,15 +183,19 @@ examples:
|
||||||
<&dispcc_dptx0_aux_clk>,
|
<&dispcc_dptx0_aux_clk>,
|
||||||
<&dispcc_dptx0_link_clk>,
|
<&dispcc_dptx0_link_clk>,
|
||||||
<&dispcc_dptx0_link_intf_clk>,
|
<&dispcc_dptx0_link_intf_clk>,
|
||||||
<&dispcc_dptx0_pixel0_clk>;
|
<&dispcc_dptx0_pixel0_clk>,
|
||||||
|
<&dispcc_dptx0_pixel1_clk>;
|
||||||
clock-names = "core_iface", "core_aux",
|
clock-names = "core_iface", "core_aux",
|
||||||
"ctrl_link",
|
"ctrl_link",
|
||||||
"ctrl_link_iface",
|
"ctrl_link_iface",
|
||||||
"stream_pixel";
|
"stream_pixel",
|
||||||
|
"stream_1_pixel";
|
||||||
|
|
||||||
assigned-clocks = <&dispcc_mdss_dptx0_link_clk_src>,
|
assigned-clocks = <&dispcc_mdss_dptx0_link_clk_src>,
|
||||||
<&dispcc_mdss_dptx0_pixel0_clk_src>;
|
<&dispcc_mdss_dptx0_pixel0_clk_src>,
|
||||||
|
<&dispcc_mdss_dptx0_pixel1_clk_src>;
|
||||||
assigned-clock-parents = <&usb_1_ss0_qmpphy QMP_USB43DP_DP_LINK_CLK>,
|
assigned-clock-parents = <&usb_1_ss0_qmpphy QMP_USB43DP_DP_LINK_CLK>,
|
||||||
|
<&usb_1_ss0_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>,
|
||||||
<&usb_1_ss0_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
|
<&usb_1_ss0_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
|
||||||
|
|
||||||
operating-points-v2 = <&mdss_dp0_opp_table>;
|
operating-points-v2 = <&mdss_dp0_opp_table>;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/panel/hydis,hv101hd1.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Hydis HV101HD1 DSI Display Panel
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Svyatoslav Ryhel <clamor95@gmail.com>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: panel-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: hydis,hv101hd1
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
vdd-supply: true
|
||||||
|
vio-supply: true
|
||||||
|
|
||||||
|
backlight: true
|
||||||
|
port: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- vdd-supply
|
||||||
|
- vio-supply
|
||||||
|
- backlight
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
dsi {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
panel@0 {
|
||||||
|
compatible = "hydis,hv101hd1";
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
vdd-supply = <&vdd_lcd>;
|
||||||
|
vio-supply = <&vddio_lcd>;
|
||||||
|
|
||||||
|
backlight = <&backlight>;
|
||||||
|
|
||||||
|
port {
|
||||||
|
panel_in: endpoint {
|
||||||
|
remote-endpoint = <&dsi_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
||||||
|
|
@ -18,6 +18,7 @@ properties:
|
||||||
- enum:
|
- enum:
|
||||||
- ampire,am8001280g
|
- ampire,am8001280g
|
||||||
- bananapi,lhr050h41
|
- bananapi,lhr050h41
|
||||||
|
- bestar,bsd1218-a101kl68
|
||||||
- feixin,k101-im2byl02
|
- feixin,k101-im2byl02
|
||||||
- raspberrypi,dsi-7inch
|
- raspberrypi,dsi-7inch
|
||||||
- startek,kd050hdfia020
|
- startek,kd050hdfia020
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,15 @@ properties:
|
||||||
- enum:
|
- enum:
|
||||||
# Admatec 9904379 10.1" 1024x600 LVDS panel
|
# Admatec 9904379 10.1" 1024x600 LVDS panel
|
||||||
- admatec,9904379
|
- admatec,9904379
|
||||||
|
# Ampire AMP19201200B5TZQW-T03 10.1" WUXGA (1920x1200) color TFT LCD panel
|
||||||
|
- ampire,amp19201200b5tzqw-t03
|
||||||
- auo,b101ew05
|
- auo,b101ew05
|
||||||
# AUO G084SN05 V9 8.4" 800x600 LVDS panel
|
# AUO G084SN05 V9 8.4" 800x600 LVDS panel
|
||||||
- auo,g084sn05
|
- auo,g084sn05
|
||||||
# Chunghwa Picture Tubes Ltd. 7" WXGA (800x1280) TFT LCD LVDS panel
|
# Chunghwa Picture Tubes Ltd. 7" WXGA (800x1280) TFT LCD LVDS panel
|
||||||
- chunghwa,claa070wp03xg
|
- chunghwa,claa070wp03xg
|
||||||
|
# EDT ETML0700Z8DHA 7.0" Full HD (1920x1080) color TFT LCD LVDS panel
|
||||||
|
- edt,etml0700z8dha
|
||||||
# EDT ETML0700Z9NDHA 7.0" WSVGA (1024x600) color TFT LCD LVDS panel
|
# EDT ETML0700Z9NDHA 7.0" WSVGA (1024x600) color TFT LCD LVDS panel
|
||||||
- edt,etml0700z9ndha
|
- edt,etml0700z9ndha
|
||||||
# HannStar Display Corp. HSD101PWW2 10.1" WXGA (1280x800) LVDS panel
|
# HannStar Display Corp. HSD101PWW2 10.1" WXGA (1280x800) LVDS panel
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,8 @@ properties:
|
||||||
- okaya,rs800480t-7x0gp
|
- okaya,rs800480t-7x0gp
|
||||||
# Olimex 4.3" TFT LCD panel
|
# Olimex 4.3" TFT LCD panel
|
||||||
- olimex,lcd-olinuxino-43-ts
|
- olimex,lcd-olinuxino-43-ts
|
||||||
|
# Olimex 5.0" TFT LCD panel
|
||||||
|
- olimex,lcd-olinuxino-5-cts
|
||||||
# On Tat Industrial Company 5" DPI TFT panel.
|
# On Tat Industrial Company 5" DPI TFT panel.
|
||||||
- ontat,kd50g21-40nt-a1
|
- ontat,kd50g21-40nt-a1
|
||||||
# On Tat Industrial Company 7" DPI TFT panel.
|
# On Tat Industrial Company 7" DPI TFT panel.
|
||||||
|
|
@ -325,6 +327,10 @@ properties:
|
||||||
- vivax,tpc9150-panel
|
- vivax,tpc9150-panel
|
||||||
# VXT 800x480 color TFT LCD panel
|
# VXT 800x480 color TFT LCD panel
|
||||||
- vxt,vl050-8048nt-c01
|
- vxt,vl050-8048nt-c01
|
||||||
|
# Waveshare 13.3" FHD (1920x1080) LCD panel
|
||||||
|
- waveshare,13.3inch-panel
|
||||||
|
# Waveshare 7.0" WSVGA (1024x600) LCD panel
|
||||||
|
- waveshare,7.0inch-c-panel
|
||||||
# Winstar Display Corporation 3.5" QVGA (320x240) TFT LCD panel
|
# Winstar Display Corporation 3.5" QVGA (320x240) TFT LCD panel
|
||||||
- winstar,wf35ltiacd
|
- winstar,wf35ltiacd
|
||||||
# Yes Optoelectronics YTC700TLAG-05-201C 7" TFT LCD panel
|
# Yes Optoelectronics YTC700TLAG-05-201C 7" TFT LCD panel
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@ properties:
|
||||||
- enum:
|
- enum:
|
||||||
# Samsung 13" 3K (2880×1920 pixels) eDP AMOLED panel
|
# Samsung 13" 3K (2880×1920 pixels) eDP AMOLED panel
|
||||||
- samsung,atna30dw01
|
- samsung,atna30dw01
|
||||||
|
# Samsung 14" FHD+ (1920x1200 pixels) eDP AMOLED panel
|
||||||
|
- samsung,atna40ct06
|
||||||
|
# Samsung 14" WQXGA+ (2880x1800 pixels) eDP AMOLED panel
|
||||||
|
- samsung,atna40cu11
|
||||||
# Samsung 14" WQXGA+ (2880×1800 pixels) eDP AMOLED panel
|
# Samsung 14" WQXGA+ (2880×1800 pixels) eDP AMOLED panel
|
||||||
- samsung,atna40yk20
|
- samsung,atna40yk20
|
||||||
# Samsung 14.5" WQXGA+ (2880x1800 pixels) eDP AMOLED panel
|
# Samsung 14.5" WQXGA+ (2880x1800 pixels) eDP AMOLED panel
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/panel/samsung,s6e8aa5x01-ams561ra01.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Samsung AMS561RA01 panel with S6E8AA5X01 controller
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Kaustabh Chakraborty <kauschluss@disroot.org>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: panel-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: samsung,s6e8aa5x01-ams561ra01
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
vdd-supply:
|
||||||
|
description: core voltage supply
|
||||||
|
|
||||||
|
vci-supply:
|
||||||
|
description: voltage supply for analog circuits
|
||||||
|
|
||||||
|
reset-gpios: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
dsi {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
panel@0 {
|
||||||
|
compatible = "samsung,s6e8aa5x01-ams561ra01";
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
vdd-supply = <&panel_vdd_reg>;
|
||||||
|
vci-supply = <&panel_vci_reg>;
|
||||||
|
|
||||||
|
reset-gpios = <&gpd3 4 GPIO_ACTIVE_HIGH>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
||||||
|
|
@ -0,0 +1,150 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/rockchip/rockchip,dw-dp.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Rockchip DW DisplayPort Transmitter
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Andy Yan <andy.yan@rock-chips.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
The Rockchip RK3588 SoC integrates the Synopsys DesignWare DPTX controller
|
||||||
|
which is compliant with the DisplayPort Specification Version 1.4 with the
|
||||||
|
following features:
|
||||||
|
|
||||||
|
* DisplayPort 1.4a
|
||||||
|
* Main Link: 1/2/4 lanes
|
||||||
|
* Main Link Support 1.62Gbps, 2.7Gbps, 5.4Gbps and 8.1Gbps
|
||||||
|
* AUX channel 1Mbps
|
||||||
|
* Single Stream Transport(SST)
|
||||||
|
* Multistream Transport (MST)
|
||||||
|
* Type-C support (alternate mode)
|
||||||
|
* HDCP 2.2, HDCP 1.3
|
||||||
|
* Supports up to 8/10 bits per color component
|
||||||
|
* Supports RBG, YCbCr4:4:4, YCbCr4:2:2, YCbCr4:2:0
|
||||||
|
* Pixel clock up to 594MHz
|
||||||
|
* I2S, SPDIF audio interface
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: /schemas/sound/dai-common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- rockchip,rk3588-dp
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
items:
|
||||||
|
- description: Peripheral/APB bus clock
|
||||||
|
- description: DisplayPort AUX clock
|
||||||
|
- description: HDCP clock
|
||||||
|
- description: I2S interface clock
|
||||||
|
- description: SPDIF interfce clock
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: apb
|
||||||
|
- const: aux
|
||||||
|
- const: hdcp
|
||||||
|
- const: i2s
|
||||||
|
- const: spdif
|
||||||
|
|
||||||
|
phys:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
ports:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/ports
|
||||||
|
|
||||||
|
properties:
|
||||||
|
port@0:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
|
description: Video port for RGB/YUV input.
|
||||||
|
|
||||||
|
port@1:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
|
description: Video port for DP output.
|
||||||
|
|
||||||
|
required:
|
||||||
|
- port@0
|
||||||
|
- port@1
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
resets:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
"#sound-dai-cells":
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- clocks
|
||||||
|
- clock-names
|
||||||
|
- interrupts
|
||||||
|
- phys
|
||||||
|
- ports
|
||||||
|
- resets
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/clock/rockchip,rk3588-cru.h>
|
||||||
|
#include <dt-bindings/phy/phy.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
#include <dt-bindings/power/rk3588-power.h>
|
||||||
|
#include <dt-bindings/reset/rockchip,rk3588-cru.h>
|
||||||
|
|
||||||
|
soc {
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
|
||||||
|
dp@fde50000 {
|
||||||
|
compatible = "rockchip,rk3588-dp";
|
||||||
|
reg = <0x0 0xfde50000 0x0 0x4000>;
|
||||||
|
interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||||
|
clocks = <&cru PCLK_DP0>, <&cru CLK_AUX16M_0>,
|
||||||
|
<&cru CLK_DP0>, <&cru MCLK_I2S4_8CH_TX>,
|
||||||
|
<&cru MCLK_SPDIF2_DP0>;
|
||||||
|
clock-names = "apb", "aux", "hdcp", "i2s", "spdif";
|
||||||
|
assigned-clocks = <&cru CLK_AUX16M_0>;
|
||||||
|
assigned-clock-rates = <16000000>;
|
||||||
|
resets = <&cru SRST_DP0>;
|
||||||
|
phys = <&usbdp_phy0 PHY_TYPE_DP>;
|
||||||
|
power-domains = <&power RK3588_PD_VO0>;
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
dp0_in_vp2: endpoint {
|
||||||
|
remote-endpoint = <&vp2_out_dp0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
|
||||||
|
dp0_out_con0: endpoint {
|
||||||
|
remote-endpoint = <&dp_con0_in>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -12,6 +12,7 @@ maintainers:
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
enum:
|
enum:
|
||||||
|
- rockchip,rk3576-mipi-dsi2
|
||||||
- rockchip,rk3588-mipi-dsi2
|
- rockchip,rk3588-mipi-dsi2
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,21 @@ properties:
|
||||||
- const: vsync
|
- const: vsync
|
||||||
- const: lcd_sys
|
- const: lcd_sys
|
||||||
|
|
||||||
|
iommus:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
memory-region:
|
||||||
|
maxItems: 1
|
||||||
|
description:
|
||||||
|
A phandle to a node describing a reserved framebuffer memory region.
|
||||||
|
For example, the splash memory region set up by the bootloader.
|
||||||
|
|
||||||
|
port:
|
||||||
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
|
description:
|
||||||
|
Output port which is connected to either a Mobile Image Compressor
|
||||||
|
(MIC) or a DSI Master device.
|
||||||
|
|
||||||
power-domains:
|
power-domains:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
|
@ -92,6 +107,7 @@ required:
|
||||||
- clock-names
|
- clock-names
|
||||||
- interrupts
|
- interrupts
|
||||||
- interrupt-names
|
- interrupt-names
|
||||||
|
- port
|
||||||
- reg
|
- reg
|
||||||
|
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
@ -118,4 +134,9 @@ examples:
|
||||||
"decon0_vclk";
|
"decon0_vclk";
|
||||||
pinctrl-0 = <&lcd_clk &pwm1_out>;
|
pinctrl-0 = <&lcd_clk &pwm1_out>;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
|
port {
|
||||||
|
decon_to_dsi: endpoint {
|
||||||
|
remote-endpoint = <&dsi_to_decon>;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,11 @@ properties:
|
||||||
reg:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
sitronix,inverted:
|
||||||
|
type: boolean
|
||||||
|
description:
|
||||||
|
Display pixels are inverted, i.e. 0 is white and 1 is black.
|
||||||
|
|
||||||
width-mm: true
|
width-mm: true
|
||||||
height-mm: true
|
height-mm: true
|
||||||
panel-timing: true
|
panel-timing: true
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,11 @@ properties:
|
||||||
description:
|
description:
|
||||||
Display supports 4-level grayscale.
|
Display supports 4-level grayscale.
|
||||||
|
|
||||||
|
sitronix,inverted:
|
||||||
|
type: boolean
|
||||||
|
description:
|
||||||
|
Display pixels are inverted, i.e. 0 is white and 1 is black.
|
||||||
|
|
||||||
reset-gpios: true
|
reset-gpios: true
|
||||||
width-mm: true
|
width-mm: true
|
||||||
height-mm: true
|
height-mm: true
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,10 @@ maintainers:
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
const: st,stm32-ltdc
|
enum:
|
||||||
|
- st,stm32-ltdc
|
||||||
|
- st,stm32mp251-ltdc
|
||||||
|
- st,stm32mp255-ltdc
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
@ -24,15 +27,23 @@ properties:
|
||||||
minItems: 1
|
minItems: 1
|
||||||
|
|
||||||
clocks:
|
clocks:
|
||||||
maxItems: 1
|
minItems: 1
|
||||||
|
maxItems: 4
|
||||||
|
|
||||||
clock-names:
|
clock-names:
|
||||||
items:
|
items:
|
||||||
- const: lcd
|
- const: lcd
|
||||||
|
- const: bus
|
||||||
|
- const: ref
|
||||||
|
- const: lvds
|
||||||
|
minItems: 1
|
||||||
|
|
||||||
resets:
|
resets:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
access-controllers:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
port:
|
port:
|
||||||
$ref: /schemas/graph.yaml#/properties/port
|
$ref: /schemas/graph.yaml#/properties/port
|
||||||
description: |
|
description: |
|
||||||
|
|
@ -51,6 +62,46 @@ required:
|
||||||
- resets
|
- resets
|
||||||
- port
|
- port
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- st,stm32-ltdc
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
maxItems: 1
|
||||||
|
clock-names:
|
||||||
|
maxItems: 1
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- st,stm32mp251-ltdc
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 2
|
||||||
|
maxItems: 2
|
||||||
|
clock-names:
|
||||||
|
minItems: 2
|
||||||
|
maxItems: 2
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- st,stm32mp255-ltdc
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 4
|
||||||
|
clock-names:
|
||||||
|
minItems: 4
|
||||||
|
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,12 @@ description: |
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
const: st,stm32mp25-lvds
|
oneOf:
|
||||||
|
- items:
|
||||||
|
- enum:
|
||||||
|
- st,stm32mp255-lvds
|
||||||
|
- const: st,stm32mp25-lvds
|
||||||
|
- const: st,stm32mp25-lvds
|
||||||
|
|
||||||
"#clock-cells":
|
"#clock-cells":
|
||||||
const: 0
|
const: 0
|
||||||
|
|
@ -54,6 +59,12 @@ properties:
|
||||||
resets:
|
resets:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
access-controllers:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
$ref: /schemas/graph.yaml#/properties/ports
|
$ref: /schemas/graph.yaml#/properties/ports
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,11 @@ properties:
|
||||||
# work with newer dts.
|
# work with newer dts.
|
||||||
- const: img,img-axe
|
- const: img,img-axe
|
||||||
- const: img,img-rogue
|
- const: img,img-rogue
|
||||||
|
- items:
|
||||||
|
- enum:
|
||||||
|
- thead,th1520-gpu
|
||||||
|
- const: img,img-bxm-4-64
|
||||||
|
- const: img,img-rogue
|
||||||
- items:
|
- items:
|
||||||
- enum:
|
- enum:
|
||||||
- ti,j721s2-gpu
|
- ti,j721s2-gpu
|
||||||
|
|
@ -77,18 +82,6 @@ required:
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
allOf:
|
allOf:
|
||||||
# Constraints added alongside the new compatible strings that would otherwise
|
|
||||||
# create an ABI break.
|
|
||||||
- if:
|
|
||||||
properties:
|
|
||||||
compatible:
|
|
||||||
contains:
|
|
||||||
const: img,img-rogue
|
|
||||||
then:
|
|
||||||
required:
|
|
||||||
- power-domains
|
|
||||||
- power-domain-names
|
|
||||||
|
|
||||||
- if:
|
- if:
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
|
|
@ -97,9 +90,32 @@ allOf:
|
||||||
then:
|
then:
|
||||||
properties:
|
properties:
|
||||||
power-domains:
|
power-domains:
|
||||||
maxItems: 1
|
items:
|
||||||
|
- description: Power domain A
|
||||||
power-domain-names:
|
power-domain-names:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
required:
|
||||||
|
- power-domains
|
||||||
|
- power-domain-names
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
const: thead,th1520-gpu
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 3
|
||||||
|
clock-names:
|
||||||
|
minItems: 3
|
||||||
|
power-domains:
|
||||||
|
items:
|
||||||
|
- description: The single, unified power domain for the GPU on the
|
||||||
|
TH1520 SoC, integrating all internal IP power domains.
|
||||||
|
power-domain-names: false
|
||||||
|
required:
|
||||||
|
- power-domains
|
||||||
|
|
||||||
- if:
|
- if:
|
||||||
properties:
|
properties:
|
||||||
|
|
@ -109,9 +125,14 @@ allOf:
|
||||||
then:
|
then:
|
||||||
properties:
|
properties:
|
||||||
power-domains:
|
power-domains:
|
||||||
minItems: 2
|
items:
|
||||||
|
- description: Power domain A
|
||||||
|
- description: Power domain B
|
||||||
power-domain-names:
|
power-domain-names:
|
||||||
minItems: 2
|
minItems: 2
|
||||||
|
required:
|
||||||
|
- power-domains
|
||||||
|
- power-domain-names
|
||||||
|
|
||||||
- if:
|
- if:
|
||||||
properties:
|
properties:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/npu/rockchip,rk3588-rknn-core.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Neural Processing Unit IP from Rockchip
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Tomeu Vizoso <tomeu@tomeuvizoso.net>
|
||||||
|
|
||||||
|
description:
|
||||||
|
Rockchip IP for accelerating inference of neural networks.
|
||||||
|
|
||||||
|
There is to be a node per each NPU core in the SoC, and each core should reference all the
|
||||||
|
resources that it needs to function, such as clocks, power domains, and resets.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
$nodename:
|
||||||
|
pattern: '^npu@[a-f0-9]+$'
|
||||||
|
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- rockchip,rk3588-rknn-core
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 3
|
||||||
|
|
||||||
|
reg-names:
|
||||||
|
items:
|
||||||
|
- const: pc # Program Control-related registers
|
||||||
|
- const: cna # Convolution Neural Network Accelerator registers
|
||||||
|
- const: core # Main NPU core processing unit registers
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
maxItems: 4
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: aclk
|
||||||
|
- const: hclk
|
||||||
|
- const: npu
|
||||||
|
- const: pclk
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
iommus:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
npu-supply: true
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
resets:
|
||||||
|
maxItems: 2
|
||||||
|
|
||||||
|
reset-names:
|
||||||
|
items:
|
||||||
|
- const: srst_a
|
||||||
|
- const: srst_h
|
||||||
|
|
||||||
|
sram-supply: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- reg-names
|
||||||
|
- clocks
|
||||||
|
- clock-names
|
||||||
|
- interrupts
|
||||||
|
- iommus
|
||||||
|
- power-domains
|
||||||
|
- resets
|
||||||
|
- reset-names
|
||||||
|
- npu-supply
|
||||||
|
- sram-supply
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/clock/rockchip,rk3588-cru.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <dt-bindings/power/rk3588-power.h>
|
||||||
|
#include <dt-bindings/reset/rockchip,rk3588-cru.h>
|
||||||
|
|
||||||
|
bus {
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
|
||||||
|
npu@fdab0000 {
|
||||||
|
compatible = "rockchip,rk3588-rknn-core";
|
||||||
|
reg = <0x0 0xfdab0000 0x0 0x1000>,
|
||||||
|
<0x0 0xfdab1000 0x0 0x1000>,
|
||||||
|
<0x0 0xfdab3000 0x0 0x1000>;
|
||||||
|
reg-names = "pc", "cna", "core";
|
||||||
|
clocks = <&cru ACLK_NPU0>, <&cru HCLK_NPU0>,
|
||||||
|
<&scmi_clk SCMI_CLK_NPU>, <&cru PCLK_NPU_ROOT>;
|
||||||
|
clock-names = "aclk", "hclk", "npu", "pclk";
|
||||||
|
interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||||
|
iommus = <&rknn_mmu_0>;
|
||||||
|
npu-supply = <&vdd_npu_s0>;
|
||||||
|
power-domains = <&power RK3588_PD_NPUTOP>;
|
||||||
|
resets = <&cru SRST_A_RKNN0>, <&cru SRST_H_RKNN0>;
|
||||||
|
reset-names = "srst_a", "srst_h";
|
||||||
|
sram-supply = <&vdd_npu_mem_s0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
||||||
|
|
@ -225,6 +225,8 @@ patternProperties:
|
||||||
description: BeagleBoard.org Foundation
|
description: BeagleBoard.org Foundation
|
||||||
"^belling,.*":
|
"^belling,.*":
|
||||||
description: Shanghai Belling Co., Ltd.
|
description: Shanghai Belling Co., Ltd.
|
||||||
|
"^bestar,.*":
|
||||||
|
description: Shenzhen Bestar Electronic Technology Co., Ltd.
|
||||||
"^bhf,.*":
|
"^bhf,.*":
|
||||||
description: Beckhoff Automation GmbH & Co. KG
|
description: Beckhoff Automation GmbH & Co. KG
|
||||||
"^bigtreetech,.*":
|
"^bigtreetech,.*":
|
||||||
|
|
@ -967,6 +969,8 @@ patternProperties:
|
||||||
description: MaxLinear Inc.
|
description: MaxLinear Inc.
|
||||||
"^maxtor,.*":
|
"^maxtor,.*":
|
||||||
description: Maxtor Corporation
|
description: Maxtor Corporation
|
||||||
|
"^mayqueen,.*":
|
||||||
|
description: Mayqueen Technologies Ltd.
|
||||||
"^mbvl,.*":
|
"^mbvl,.*":
|
||||||
description: Mobiveil Inc.
|
description: Mobiveil Inc.
|
||||||
"^mcube,.*":
|
"^mcube,.*":
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ Accelerated Processing Units (APU) Info
|
||||||
|
|
||||||
.. csv-table::
|
.. csv-table::
|
||||||
:header-rows: 1
|
:header-rows: 1
|
||||||
:widths: 3, 2, 2, 1, 1, 1, 1
|
:widths: 3, 2, 2, 1, 1, 1, 1, 1
|
||||||
:file: ./apu-asic-info-table.csv
|
:file: ./apu-asic-info-table.csv
|
||||||
|
|
||||||
Discrete GPU Info
|
Discrete GPU Info
|
||||||
|
|
@ -18,6 +18,6 @@ Discrete GPU Info
|
||||||
|
|
||||||
.. csv-table::
|
.. csv-table::
|
||||||
:header-rows: 1
|
:header-rows: 1
|
||||||
:widths: 3, 2, 2, 1, 1, 1
|
:widths: 3, 2, 2, 1, 1, 1, 1, 1
|
||||||
:file: ./dgpu-asic-info-table.csv
|
:file: ./dgpu-asic-info-table.csv
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
Product Name, Code Reference, DCN/DCE version, GC version, VCE/UVD/VCN version, SDMA version, MP0 version
|
Product Name, Code Reference, DCN/DCE version, GC version, VCE/UVD/VCN version, SDMA version, MP0 version, MP1 version
|
||||||
Radeon R* Graphics, CARRIZO/STONEY, DCE 11, 8, VCE 3 / UVD 6, 3, n/a
|
Radeon R* Graphics, CARRIZO/STONEY, DCE 11, 8, VCE 3 / UVD 6, 3, n/a, 8
|
||||||
Ryzen 3000 series / AMD Ryzen Embedded V1*/R1* with Radeon Vega Gfx, RAVEN/PICASSO, DCN 1.0, 9.1.0, VCN 1.0, 4.1.0, 10.0.0
|
Ryzen 3000 series / AMD Ryzen Embedded V1*/R1* with Radeon Vega Gfx, RAVEN/PICASSO, DCN 1.0, 9.1.0, VCN 1.0, 4.1.0, 10.0.0, 10.0.0
|
||||||
Ryzen 4000 series, RENOIR, DCN 2.1, 9.3, VCN 2.2, 4.1.2, 11.0.3
|
Ryzen 4000 series, RENOIR, DCN 2.1, 9.3, VCN 2.2, 4.1.2, 11.0.3, 12.0.1
|
||||||
Ryzen 3000 series / AMD Ryzen Embedded V1*/R1* with Radeon Vega Gfx, RAVEN2, DCN 1.0, 9.2.2, VCN 1.0.1, 4.1.1, 10.0.1
|
Ryzen 3000 series / AMD Ryzen Embedded V1*/R1* with Radeon Vega Gfx, RAVEN2, DCN 1.0, 9.2.2, VCN 1.0.1, 4.1.1, 10.0.1, 10.0.1
|
||||||
SteamDeck, VANGOGH, DCN 3.0.1, 10.3.1, VCN 3.1.0, 5.2.1, 11.5.0
|
SteamDeck, VANGOGH, DCN 3.0.1, 10.3.1, VCN 3.1.0, 5.2.1, 11.5.0, 11.5.0
|
||||||
Ryzen 5000 series / Ryzen 7x30 series, GREEN SARDINE / Cezanne / Barcelo / Barcelo-R, DCN 2.1, 9.3, VCN 2.2, 4.1.1, 12.0.1
|
Ryzen 5000 series / Ryzen 7x30 series, GREEN SARDINE / Cezanne / Barcelo / Barcelo-R, DCN 2.1, 9.3, VCN 2.2, 4.1.1, 12.0.1, 12.0.1
|
||||||
Ryzen 6000 series / Ryzen 7x35 series / Ryzen 7x36 series, YELLOW CARP / Rembrandt / Rembrandt-R, 3.1.2, 10.3.3, VCN 3.1.1, 5.2.3, 13.0.3
|
Ryzen 6000 series / Ryzen 7x35 series / Ryzen 7x36 series, YELLOW CARP / Rembrandt / Rembrandt-R, 3.1.2, 10.3.3, VCN 3.1.1, 5.2.3, 13.0.3, 13.0.3
|
||||||
Ryzen 7000 series (AM5), Raphael, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5
|
Ryzen 7000 series (AM5), Raphael, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5, 13.0.5
|
||||||
Ryzen 9000 series (AM5), Granite Ridge, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5
|
Ryzen 9000 series (AM5), Granite Ridge, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5, 13.0.5
|
||||||
Ryzen 7x45 series (FL1), Dragon Range, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5
|
Ryzen 7x45 series (FL1), Dragon Range, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5, 13.0.5
|
||||||
Ryzen 7x20 series, Mendocino, 3.1.6, 10.3.7, 3.1.1, 5.2.7, 13.0.8
|
Ryzen 7x20 series, Mendocino, 3.1.6, 10.3.7, 3.1.1, 5.2.7, 13.0.8, 13.0.8
|
||||||
Ryzen 7x40 series, Phoenix, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11
|
Ryzen 7x40 series, Phoenix, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11, 13.0.4 / 13.0.11
|
||||||
Ryzen 8x40 series, Hawk Point, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11
|
Ryzen 8x40 series, Hawk Point, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11, 13.0.4 / 13.0.11
|
||||||
Ryzen AI 300 series, Strix Point, 3.5.0, 11.5.0, 4.0.5, 6.1.0, 14.0.0
|
Ryzen AI 300 series, Strix Point, 3.5.0, 11.5.0, 4.0.5, 6.1.0, 14.0.0, 14.0.0
|
||||||
Ryzen AI 350 series, Krackan Point, 3.5.0, 11.5.2, 4.0.5, 6.1.2, 14.0.4
|
Ryzen AI 330 series, Krackan Point, 3.6.0, 11.5.3, 4.0.5, 6.1.3, 14.0.5, 14.0.5
|
||||||
Ryzen AI Max 300 series, Strix Halo, 3.5.1, 11.5.1, 4.0.6, 6.1.1, 14.0.1
|
Ryzen AI 350 series, Krackan Point, 3.5.0, 11.5.2, 4.0.5, 6.1.2, 14.0.4, 14.0.4
|
||||||
|
Ryzen AI Max 300 series, Strix Halo, 3.5.1, 11.5.1, 4.0.6, 6.1.1, 14.0.1, 14.0.1
|
||||||
|
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ amdgpu_error_<name>
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Provides an interface to set an error code on the dma fences associated with
|
Provides an interface to set an error code on the dma fences associated with
|
||||||
ring <name>. The error code specified is propogated to all fences associated
|
ring <name>. The error code specified is propagated to all fences associated
|
||||||
with the ring. Use this to inject a fence error into a ring.
|
with the ring. Use this to inject a fence error into a ring.
|
||||||
|
|
||||||
amdgpu_pm_info
|
amdgpu_pm_info
|
||||||
|
|
@ -165,7 +165,7 @@ GTT memory.
|
||||||
amdgpu_regs_*
|
amdgpu_regs_*
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Provides direct access to various register aperatures on the GPU. Used
|
Provides direct access to various register apertures on the GPU. Used
|
||||||
by tools like UMR to access GPU registers.
|
by tools like UMR to access GPU registers.
|
||||||
|
|
||||||
amdgpu_regs2
|
amdgpu_regs2
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,30 @@
|
||||||
Product Name, Code Reference, DCN/DCE version, GC version, VCN version, SDMA version
|
Product Name, Code Reference, DCN/DCE version, GC version, VCN version, SDMA version, MP0 version, MP1 version
|
||||||
AMD Radeon (TM) HD 8500M/ 8600M /M200 /M320 /M330 /M335 Series, HAINAN, --, 6, --, --
|
AMD Radeon (TM) HD 8500M/ 8600M /M200 /M320 /M330 /M335 Series, HAINAN, --, 6, --, --, --, 6
|
||||||
AMD Radeon HD 7800 /7900 /FireGL Series, TAHITI, DCE 6, 6, VCE 1 / UVD 3, --
|
AMD Radeon HD 7800 /7900 /FireGL Series, TAHITI, DCE 6, 6, VCE 1 / UVD 3, --, --, 6
|
||||||
AMD Radeon R7 (TM|HD) M265 /M370 /8500M /8600 /8700 /8700M, OLAND, DCE 6, 6, VCE 1 / UVD 3, --
|
AMD Radeon R7 (TM|HD) M265 /M370 /8500M /8600 /8700 /8700M, OLAND, DCE 6, 6, -- / UVD 3, --, --, 6
|
||||||
AMD Radeon (TM) (HD|R7) 7800 /7970 /8800 /8970 /370/ Series, PITCAIRN, DCE 6, 6, VCE 1 / UVD 3, --
|
AMD Radeon (TM) (HD|R7) 7800 /7970 /8800 /8970 /370/ Series, PITCAIRN, DCE 6, 6, VCE 1 / UVD 3, --, --, 6
|
||||||
AMD Radeon (TM|R7|R9|HD) E8860 /M360 /7700 /7800 /8800 /9000(M) /W4100 Series, VERDE, DCE 6, 6, VCE 1 / UVD 3, --
|
AMD Radeon (TM|R7|R9|HD) E8860 /M360 /7700 /7800 /8800 /9000(M) /W4100 Series, VERDE, DCE 6, 6, VCE 1 / UVD 3, --, --, 6
|
||||||
AMD Radeon HD M280X /M380 /7700 /8950 /W5100, BONAIRE, DCE 8, 7, VCE 2 / UVD 4.2, 1
|
AMD Radeon HD M280X /M380 /7700 /8950 /W5100, BONAIRE, DCE 8, 7, VCE 2 / UVD 4.2, 1, --, 7
|
||||||
AMD Radeon (R9|TM) 200 /390 /W8100 /W9100 Series, HAWAII, DCE 8, 7, VCE 2 / UVD 4.2, 1
|
AMD Radeon (R9|TM) 200 /390 /W8100 /W9100 Series, HAWAII, DCE 8, 7, VCE 2 / UVD 4.2, 1, --, 7
|
||||||
AMD Radeon (TM) R(5|7) M315 /M340 /M360, TOPAZ, *, 8, --, 2
|
AMD Radeon (TM) R(5|7) M315 /M340 /M360, TOPAZ, *, 8, --, 2, n/a, 7
|
||||||
AMD Radeon (TM) R9 200 /380 /W7100 /S7150 /M390 /M395 Series, TONGA, DCE 10, 8, VCE 3 / UVD 5, 3
|
AMD Radeon (TM) R9 200 /380 /W7100 /S7150 /M390 /M395 Series, TONGA, DCE 10, 8, VCE 3 / UVD 5, 3, n/a, 7
|
||||||
AMD Radeon (FirePro) (TM) R9 Fury Series, FIJI, DCE 10, 8, VCE 3 / UVD 6, 3
|
AMD Radeon (FirePro) (TM) R9 Fury Series, FIJI, DCE 10, 8, VCE 3 / UVD 6, 3, n/a, 7
|
||||||
Radeon RX 470 /480 /570 /580 /590 Series - AMD Radeon (TM) (Pro WX) 5100 /E9390 /E9560 /E9565 /V7350 /7100 /P30PH, POLARIS10, DCE 11.2, 8, VCE 3.4 / UVD 6.3, 3
|
Radeon RX 470 /480 /570 /580 /590 Series - AMD Radeon (TM) (Pro WX) 5100 /E9390 /E9560 /E9565 /V7350 /7100 /P30PH, POLARIS10, DCE 11.2, 8, VCE 3.4 / UVD 6.3, 3, n/a, 7
|
||||||
Radeon (TM) (RX|Pro WX) E9260 /460 /V5300X /550 /560(X) Series, POLARIS11, DCE 11.2, 8, VCE 3.4 / UVD 6.3, 3
|
Radeon (TM) (RX|Pro WX) E9260 /460 /V5300X /550 /560(X) Series, POLARIS11, DCE 11.2, 8, VCE 3.4 / UVD 6.3, 3, n/a, 7
|
||||||
Radeon (RX/Pro) 500 /540(X) /550 /640 /WX2100 /WX3100 /WX200 Series, POLARIS12, DCE 11.2, 8, VCE 3.4 / UVD 6.3, 3
|
Radeon (RX/Pro) 500 /540(X) /550 /640 /WX2100 /WX3100 /WX200 Series, POLARIS12, DCE 11.2, 8, VCE 3.4 / UVD 6.3, 3, n/a, 7
|
||||||
Radeon (RX|TM) (PRO|WX) Vega /MI25 /V320 /V340L /8200 /9100 /SSG MxGPU, VEGA10, DCE 12, 9.0.1, VCE 4.0.0 / UVD 7.0.0, 4.0.0
|
Radeon (RX|TM) (PRO|WX) Vega /MI25 /V320 /V340L /8200 /9100 /SSG MxGPU, VEGA10, DCE 12, 9.0.1, VCE 4.0.0 / UVD 7.0.0, 4.0.0, 9.0.0, 9.0.0
|
||||||
AMD Radeon (Pro) VII /MI50 /MI60, VEGA20, DCE 12, 9.4.0, VCE 4.1.0 / UVD 7.2.0, 4.2.0
|
AMD Radeon (Pro) VII /MI50 /MI60, VEGA20, DCE 12, 9.4.0, VCE 4.1.0 / UVD 7.2.0, 4.2.0, 11.0.2, 11.0.2
|
||||||
MI100, ARCTURUS, *, 9.4.1, VCN 2.5.0, 4.2.2
|
MI100, ARCTURUS, *, 9.4.1, VCN 2.5.0, 4.2.2, 11.0.4, 11.0.2
|
||||||
MI200 Series, ALDEBARAN, *, 9.4.2, VCN 2.6.0, 4.4.0
|
MI200 Series, ALDEBARAN, *, 9.4.2, VCN 2.6.0, 4.4.0, 13.0.2, 13.0.2
|
||||||
MI300 Series, AQUA_VANJARAM, *, 9.4.3, VCN 4.0.3, 4.4.2
|
MI300 Series, AQUA_VANJARAM, *, 9.4.3, VCN 4.0.3, 4.4.2, 13.0.6, 13.0.6
|
||||||
AMD Radeon (RX|Pro) 5600(M|XT) /5700 (M|XT|XTB) /W5700, NAVI10, DCN 2.0.0, 10.1.10, VCN 2.0.0, 5.0.0
|
AMD Radeon (RX|Pro) 5600(M|XT) /5700 (M|XT|XTB) /W5700, NAVI10, DCN 2.0.0, 10.1.10, VCN 2.0.0, 5.0.0, 11.0.0, 11.0.0
|
||||||
AMD Radeon (Pro) 5300 /5500XTB/5500(XT|M) /W5500M /W5500, NAVI14, DCN 2.0.0, 10.1.1, VCN 2.0.2, 5.0.2
|
AMD Radeon (Pro) 5300 /5500XTB/5500(XT|M) /W5500M /W5500, NAVI14, DCN 2.0.0, 10.1.1, VCN 2.0.2, 5.0.2, 11.0.5, 11.0.5
|
||||||
AMD Radeon RX 6800(XT) /6900(XT) /W6800, SIENNA_CICHLID, DCN 3.0.0, 10.3.0, VCN 3.0.0, 5.2.0
|
AMD Radeon RX 6800(XT) /6900(XT) /W6800, SIENNA_CICHLID, DCN 3.0.0, 10.3.0, VCN 3.0.0, 5.2.0, 11.0.7, 11.0.7
|
||||||
AMD Radeon RX 6700 XT / 6800M / 6700M, NAVY_FLOUNDER, DCN 3.0.0, 10.3.2, VCN 3.0.0, 5.2.2
|
AMD Radeon RX 6700 XT / 6800M / 6700M, NAVY_FLOUNDER, DCN 3.0.0, 10.3.2, VCN 3.0.0, 5.2.2, 11.0.11, 11.0.11
|
||||||
AMD Radeon RX 6600(XT) /6600M /W6600 /W6600M, DIMGREY_CAVEFISH, DCN 3.0.2, 10.3.4, VCN 3.0.16, 5.2.4
|
AMD Radeon RX 6600(XT) /6600M /W6600 /W6600M, DIMGREY_CAVEFISH, DCN 3.0.2, 10.3.4, VCN 3.0.16, 5.2.4, 11.0.12, 11.0.12
|
||||||
AMD Radeon RX 6500M /6300M /W6500M /W6300M, BEIGE_GOBY, DCN 3.0.3, 10.3.5, VCN 3.0.33, 5.2.5
|
AMD Radeon RX 6500M /6300M /W6500M /W6300M, BEIGE_GOBY, DCN 3.0.3, 10.3.5, VCN 3.0.33, 5.2.5, 11.0.13, 11.0.13
|
||||||
AMD Radeon RX 7900 XT /XTX, , DCN 3.2.0, 11.0.0, VCN 4.0.0, 6.0.0
|
AMD Radeon RX 7900 XT /XTX, , DCN 3.2.0, 11.0.0, VCN 4.0.0, 6.0.0, 13.0.0, 13.0.0
|
||||||
AMD Radeon RX 7800 XT, , DCN 3.2.0, 11.0.3, VCN 4.0.0, 6.0.3
|
AMD Radeon RX 7800 XT, , DCN 3.2.0, 11.0.3, VCN 4.0.0, 6.0.3, 13.0.10, 13.0.10
|
||||||
AMD Radeon RX 7600M (XT) /7700S /7600S, , DCN 3.2.1, 11.0.2, VCN 4.0.4, 6.0.2
|
AMD Radeon RX 7600M (XT) /7700S /7600S, , DCN 3.2.1, 11.0.2, VCN 4.0.4, 6.0.2, 13.0.7, 13.0.7
|
||||||
|
AMD Radeon RX 9070 (XT), , DCN 4.0.1, 12.0.1, VCN 5.0.0, 7.0.1, 14.0.3, 14.0.3
|
||||||
|
AMD Radeon RX 9060 XT, , DCN 4.0.1, 12.0.0, VCN 5.0.0, 7.0.0, 14.0.2, 14.0.2
|
||||||
|
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ DC Glossary
|
||||||
On this page, we try to keep track of acronyms related to the display
|
On this page, we try to keep track of acronyms related to the display
|
||||||
component. If you do not find what you are looking for, look at the
|
component. If you do not find what you are looking for, look at the
|
||||||
'Documentation/gpu/amdgpu/amdgpu-glossary.rst'; if you cannot find it anywhere,
|
'Documentation/gpu/amdgpu/amdgpu-glossary.rst'; if you cannot find it anywhere,
|
||||||
consider asking in the amdgfx and update this page.
|
consider asking on the amd-gfx mailing list and update this page.
|
||||||
|
|
||||||
.. glossary::
|
.. glossary::
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ contribution to the display code, and for that, we say thank you :)
|
||||||
|
|
||||||
This page summarizes some of the issues you can help with; keep in mind that
|
This page summarizes some of the issues you can help with; keep in mind that
|
||||||
this is a static page, and it is always a good idea to try to reach developers
|
this is a static page, and it is always a good idea to try to reach developers
|
||||||
in the amdgfx or some of the maintainers. Finally, this page follows the DRM
|
on the amd-gfx mailing list or some of the maintainers. Finally, this page
|
||||||
way of creating a TODO list; for more information, check
|
follows the DRM way of creating a TODO list; for more information, check
|
||||||
'Documentation/gpu/todo.rst'.
|
'Documentation/gpu/todo.rst'.
|
||||||
|
|
||||||
Gitlab issues
|
Gitlab issues
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ represents the connected display.
|
||||||
For historical reasons, we used the name `dc_link`, which gives the
|
For historical reasons, we used the name `dc_link`, which gives the
|
||||||
wrong impression that this abstraction only deals with physical connections
|
wrong impression that this abstraction only deals with physical connections
|
||||||
that the developer can easily manipulate. However, this also covers
|
that the developer can easily manipulate. However, this also covers
|
||||||
conections like eDP or cases where the output is connected to other devices.
|
connections like eDP or cases where the output is connected to other devices.
|
||||||
|
|
||||||
There are two structs that are not represented in the diagram since they were
|
There are two structs that are not represented in the diagram since they were
|
||||||
elaborated in the DCN overview page (check the DCN block diagram :ref:`Display
|
elaborated in the DCN overview page (check the DCN block diagram :ref:`Display
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ SDMA (System DMA)
|
||||||
|
|
||||||
GC (Graphics and Compute)
|
GC (Graphics and Compute)
|
||||||
This is the graphics and compute engine, i.e., the block that
|
This is the graphics and compute engine, i.e., the block that
|
||||||
encompasses the 3D pipeline and and shader blocks. This is by far the
|
encompasses the 3D pipeline and shader blocks. This is by far the
|
||||||
largest block on the GPU. The 3D pipeline has tons of sub-blocks. In
|
largest block on the GPU. The 3D pipeline has tons of sub-blocks. In
|
||||||
addition to that, it also contains the CP microcontrollers (ME, PFP, CE,
|
addition to that, it also contains the CP microcontrollers (ME, PFP, CE,
|
||||||
MEC) and the RLC microcontroller. It's exposed to userspace for user mode
|
MEC) and the RLC microcontroller. It's exposed to userspace for user mode
|
||||||
|
|
@ -210,4 +210,4 @@ IP Blocks
|
||||||
:doc: IP Blocks
|
:doc: IP Blocks
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h
|
.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h
|
||||||
:identifiers: amd_ip_block_type amd_ip_funcs DC_DEBUG_MASK
|
:identifiers: amd_ip_block_type amd_ip_funcs DC_FEATURE_MASK DC_DEBUG_MASK
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ Next (GCN), Radeon DNA (RDNA), and Compute DNA (CDNA) architectures.
|
||||||
module-parameters
|
module-parameters
|
||||||
gc/index
|
gc/index
|
||||||
display/index
|
display/index
|
||||||
|
userq
|
||||||
flashing
|
flashing
|
||||||
xgmi
|
xgmi
|
||||||
ras
|
ras
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ Example of enabling enforce isolation on a GPU with multiple partitions:
|
||||||
$ cat /sys/class/drm/card0/device/enforce_isolation
|
$ cat /sys/class/drm/card0/device/enforce_isolation
|
||||||
1 0 1 0
|
1 0 1 0
|
||||||
|
|
||||||
The output indicates that enforce isolation is enabled on zeroth and second parition and disabled on first and fourth parition.
|
The output indicates that enforce isolation is enabled on zeroth and second partition and disabled on first and third partition.
|
||||||
|
|
||||||
For devices with a single partition or those that do not support partitions, there will be only one element:
|
For devices with a single partition or those that do not support partitions, there will be only one element:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,203 @@
|
||||||
|
==================
|
||||||
|
User Mode Queues
|
||||||
|
==================
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
Similar to the KFD, GPU engine queues move into userspace. The idea is to let
|
||||||
|
user processes manage their submissions to the GPU engines directly, bypassing
|
||||||
|
IOCTL calls to the driver to submit work. This reduces overhead and also allows
|
||||||
|
the GPU to submit work to itself. Applications can set up work graphs of jobs
|
||||||
|
across multiple GPU engines without needing trips through the CPU.
|
||||||
|
|
||||||
|
UMDs directly interface with firmware via per application shared memory areas.
|
||||||
|
The main vehicle for this is queue. A queue is a ring buffer with a read
|
||||||
|
pointer (rptr) and a write pointer (wptr). The UMD writes IP specific packets
|
||||||
|
into the queue and the firmware processes those packets, kicking off work on the
|
||||||
|
GPU engines. The CPU in the application (or another queue or device) updates
|
||||||
|
the wptr to tell the firmware how far into the ring buffer to process packets
|
||||||
|
and the rtpr provides feedback to the UMD on how far the firmware has progressed
|
||||||
|
in executing those packets. When the wptr and the rptr are equal, the queue is
|
||||||
|
idle.
|
||||||
|
|
||||||
|
Theory of Operation
|
||||||
|
===================
|
||||||
|
|
||||||
|
The various engines on modern AMD GPUs support multiple queues per engine with a
|
||||||
|
scheduling firmware which handles dynamically scheduling user queues on the
|
||||||
|
available hardware queue slots. When the number of user queues outnumbers the
|
||||||
|
available hardware queue slots, the scheduling firmware dynamically maps and
|
||||||
|
unmaps queues based on priority and time quanta. The state of each user queue
|
||||||
|
is managed in the kernel driver in an MQD (Memory Queue Descriptor). This is a
|
||||||
|
buffer in GPU accessible memory that stores the state of a user queue. The
|
||||||
|
scheduling firmware uses the MQD to load the queue state into an HQD (Hardware
|
||||||
|
Queue Descriptor) when a user queue is mapped. Each user queue requires a
|
||||||
|
number of additional buffers which represent the ring buffer and any metadata
|
||||||
|
needed by the engine for runtime operation. On most engines this consists of
|
||||||
|
the ring buffer itself, a rptr buffer (where the firmware will shadow the rptr
|
||||||
|
to userspace), a wptr buffer (where the application will write the wptr for the
|
||||||
|
firmware to fetch it), and a doorbell. A doorbell is a piece of one of the
|
||||||
|
device's MMIO BARs which can be mapped to specific user queues. When the
|
||||||
|
application writes to the doorbell, it will signal the firmware to take some
|
||||||
|
action. Writing to the doorbell wakes the firmware and causes it to fetch the
|
||||||
|
wptr and start processing the packets in the queue. Each 4K page of the doorbell
|
||||||
|
BAR supports specific offset ranges for specific engines. The doorbell of a
|
||||||
|
queue must be mapped into the aperture aligned to the IP used by the queue
|
||||||
|
(e.g., GFX, VCN, SDMA, etc.). These doorbell apertures are set up via NBIO
|
||||||
|
registers. Doorbells are 32 bit or 64 bit (depending on the engine) chunks of
|
||||||
|
the doorbell BAR. A 4K doorbell page provides 512 64-bit doorbells for up to
|
||||||
|
512 user queues. A subset of each page is reserved for each IP type supported
|
||||||
|
on the device. The user can query the doorbell ranges for each IP via the INFO
|
||||||
|
IOCTL. See the IOCTL Interfaces section for more information.
|
||||||
|
|
||||||
|
When an application wants to create a user queue, it allocates the necessary
|
||||||
|
buffers for the queue (ring buffer, wptr and rptr, context save areas, etc.).
|
||||||
|
These can be separate buffers or all part of one larger buffer. The application
|
||||||
|
would map the buffer(s) into its GPUVM and use the GPU virtual addresses of for
|
||||||
|
the areas of memory they want to use for the user queue. They would also
|
||||||
|
allocate a doorbell page for the doorbells used by the user queues. The
|
||||||
|
application would then populate the MQD in the USERQ IOCTL structure with the
|
||||||
|
GPU virtual addresses and doorbell index they want to use. The user can also
|
||||||
|
specify the attributes for the user queue (priority, whether the queue is secure
|
||||||
|
for protected content, etc.). The application would then call the USERQ
|
||||||
|
CREATE IOCTL to create the queue using the specified MQD details in the IOCTL.
|
||||||
|
The kernel driver then validates the MQD provided by the application and
|
||||||
|
translates the MQD into the engine specific MQD format for the IP. The IP
|
||||||
|
specific MQD would be allocated and the queue would be added to the run list
|
||||||
|
maintained by the scheduling firmware. Once the queue has been created, the
|
||||||
|
application can write packets directly into the queue, update the wptr, and
|
||||||
|
write to the doorbell offset to kick off work in the user queue.
|
||||||
|
|
||||||
|
When the application is done with the user queue, it would call the USERQ
|
||||||
|
FREE IOCTL to destroy it. The kernel driver would preempt the queue and
|
||||||
|
remove it from the scheduling firmware's run list. Then the IP specific MQD
|
||||||
|
would be freed and the user queue state would be cleaned up.
|
||||||
|
|
||||||
|
Some engines may require the aggregated doorbell too if the engine does not
|
||||||
|
support doorbells from unmapped queues. The aggregated doorbell is a special
|
||||||
|
page of doorbell space which wakes the scheduler. In cases where the engine may
|
||||||
|
be oversubscribed, some queues may not be mapped. If the doorbell is rung when
|
||||||
|
the queue is not mapped, the engine firmware may miss the request. Some
|
||||||
|
scheduling firmware may work around this by polling wptr shadows when the
|
||||||
|
hardware is oversubscribed, other engines may support doorbell updates from
|
||||||
|
unmapped queues. In the event that one of these options is not available, the
|
||||||
|
kernel driver will map a page of aggregated doorbell space into each GPUVM
|
||||||
|
space. The UMD will then update the doorbell and wptr as normal and then write
|
||||||
|
to the aggregated doorbell as well.
|
||||||
|
|
||||||
|
Special Packets
|
||||||
|
---------------
|
||||||
|
|
||||||
|
In order to support legacy implicit synchronization, as well as mixed user and
|
||||||
|
kernel queues, we need a synchronization mechanism that is secure. Because
|
||||||
|
kernel queues or memory management tasks depend on kernel fences, we need a way
|
||||||
|
for user queues to update memory that the kernel can use for a fence, that can't
|
||||||
|
be messed with by a bad actor. To support this, we've added a protected fence
|
||||||
|
packet. This packet works by writing a monotonically increasing value to
|
||||||
|
a memory location that only privileged clients have write access to. User
|
||||||
|
queues only have read access. When this packet is executed, the memory location
|
||||||
|
is updated and other queues (kernel or user) can see the results. The
|
||||||
|
user application would submit this packet in their command stream. The actual
|
||||||
|
packet format varies from IP to IP (GFX/Compute, SDMA, VCN, etc.), but the
|
||||||
|
behavior is the same. The packet submission is handled in userspace. The
|
||||||
|
kernel driver sets up the privileged memory used for each user queue when it
|
||||||
|
sets the queues up when the application creates them.
|
||||||
|
|
||||||
|
|
||||||
|
Memory Management
|
||||||
|
=================
|
||||||
|
|
||||||
|
It is assumed that all buffers mapped into the GPUVM space for the process are
|
||||||
|
valid when engines on the GPU are running. The kernel driver will only allow
|
||||||
|
user queues to run when all buffers are mapped. If there is a memory event that
|
||||||
|
requires buffer migration, the kernel driver will preempt the user queues,
|
||||||
|
migrate buffers to where they need to be, update the GPUVM page tables and
|
||||||
|
invaldidate the TLB, and then resume the user queues.
|
||||||
|
|
||||||
|
Interaction with Kernel Queues
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Depending on the IP and the scheduling firmware, you can enable kernel queues
|
||||||
|
and user queues at the same time, however, you are limited by the HQD slots.
|
||||||
|
Kernel queues are always mapped so any work that goes into kernel queues will
|
||||||
|
take priority. This limits the available HQD slots for user queues.
|
||||||
|
|
||||||
|
Not all IPs will support user queues on all GPUs. As such, UMDs will need to
|
||||||
|
support both user queues and kernel queues depending on the IP. For example, a
|
||||||
|
GPU may support user queues for GFX, compute, and SDMA, but not for VCN, JPEG,
|
||||||
|
and VPE. UMDs need to support both. The kernel driver provides a way to
|
||||||
|
determine if user queues and kernel queues are supported on a per IP basis.
|
||||||
|
UMDs can query this information via the INFO IOCTL and determine whether to use
|
||||||
|
kernel queues or user queues for each IP.
|
||||||
|
|
||||||
|
Queue Resets
|
||||||
|
============
|
||||||
|
|
||||||
|
For most engines, queues can be reset individually. GFX, compute, and SDMA
|
||||||
|
queues can be reset individually. When a hung queue is detected, it can be
|
||||||
|
reset either via the scheduling firmware or MMIO. Since there are no kernel
|
||||||
|
fences for most user queues, they will usually only be detected when some other
|
||||||
|
event happens; e.g., a memory event which requires migration of buffers. When
|
||||||
|
the queues are preempted, if the queue is hung, the preemption will fail.
|
||||||
|
Driver will then look up the queues that failed to preempt and reset them and
|
||||||
|
record which queues are hung.
|
||||||
|
|
||||||
|
On the UMD side, we will add a USERQ QUERY_STATUS IOCTL to query the queue
|
||||||
|
status. UMD will provide the queue id in the IOCTL and the kernel driver
|
||||||
|
will check if it has already recorded the queue as hung (e.g., due to failed
|
||||||
|
peemption) and report back the status.
|
||||||
|
|
||||||
|
IOCTL Interfaces
|
||||||
|
================
|
||||||
|
|
||||||
|
GPU virtual addresses used for queues and related data (rptrs, wptrs, context
|
||||||
|
save areas, etc.) should be validated by the kernel mode driver to prevent the
|
||||||
|
user from specifying invalid GPU virtual addresses. If the user provides
|
||||||
|
invalid GPU virtual addresses or doorbell indicies, the IOCTL should return an
|
||||||
|
error message. These buffers should also be tracked in the kernel driver so
|
||||||
|
that if the user attempts to unmap the buffer(s) from the GPUVM, the umap call
|
||||||
|
would return an error.
|
||||||
|
|
||||||
|
INFO
|
||||||
|
----
|
||||||
|
There are several new INFO queries related to user queues in order to query the
|
||||||
|
size of user queue meta data needed for a user queue (e.g., context save areas
|
||||||
|
or shadow buffers), whether kernel or user queues or both are supported
|
||||||
|
for each IP type, and the offsets for each IP type in each doorbell page.
|
||||||
|
|
||||||
|
USERQ
|
||||||
|
-----
|
||||||
|
The USERQ IOCTL is used for creating, freeing, and querying the status of user
|
||||||
|
queues. It supports 3 opcodes:
|
||||||
|
|
||||||
|
1. CREATE - Create a user queue. The application provides an MQD-like structure
|
||||||
|
that defines the type of queue and associated metadata and flags for that
|
||||||
|
queue type. Returns the queue id.
|
||||||
|
2. FREE - Free a user queue.
|
||||||
|
3. QUERY_STATUS - Query that status of a queue. Used to check if the queue is
|
||||||
|
healthy or not. E.g., if the queue has been reset. (WIP)
|
||||||
|
|
||||||
|
USERQ_SIGNAL
|
||||||
|
------------
|
||||||
|
The USERQ_SIGNAL IOCTL is used to provide a list of sync objects to be signaled.
|
||||||
|
|
||||||
|
USERQ_WAIT
|
||||||
|
----------
|
||||||
|
The USERQ_WAIT IOCTL is used to provide a list of sync object to be waited on.
|
||||||
|
|
||||||
|
Kernel and User Queues
|
||||||
|
======================
|
||||||
|
|
||||||
|
In order to properly validate and test performance, we have a driver option to
|
||||||
|
select what type of queues are enabled (kernel queues, user queues or both).
|
||||||
|
The user_queue driver parameter allows you to enable kernel queues only (0),
|
||||||
|
user queues and kernel queues (1), and user queues only (2). Enabling user
|
||||||
|
queues only will free up static queue assignments that would otherwise be used
|
||||||
|
by kernel queues for use by the scheduling firmware. Some kernel queues are
|
||||||
|
required for kernel driver operation and they will always be created. When the
|
||||||
|
kernel queues are not enabled, they are not registered with the drm scheduler
|
||||||
|
and the CS IOCTL will reject any incoming command submissions which target those
|
||||||
|
queue types. Kernel queues only mirrors the behavior on all existing GPUs.
|
||||||
|
Enabling both queues allows for backwards compatibility with old userspace while
|
||||||
|
still supporting user queues.
|
||||||
|
|
@ -418,13 +418,12 @@ needed.
|
||||||
Recovery
|
Recovery
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Current implementation defines three recovery methods, out of which, drivers
|
Current implementation defines four recovery methods, out of which, drivers
|
||||||
can use any one, multiple or none. Method(s) of choice will be sent in the
|
can use any one, multiple or none. Method(s) of choice will be sent in the
|
||||||
uevent environment as ``WEDGED=<method1>[,..,<methodN>]`` in order of less to
|
uevent environment as ``WEDGED=<method1>[,..,<methodN>]`` in order of less to
|
||||||
more side-effects. If driver is unsure about recovery or method is unknown
|
more side-effects. See the section `Vendor Specific Recovery`_
|
||||||
(like soft/hard system reboot, firmware flashing, physical device replacement
|
for ``WEDGED=vendor-specific``. If driver is unsure about recovery or
|
||||||
or any other procedure which can't be attempted on the fly), ``WEDGED=unknown``
|
method is unknown, ``WEDGED=unknown`` will be sent instead.
|
||||||
will be sent instead.
|
|
||||||
|
|
||||||
Userspace consumers can parse this event and attempt recovery as per the
|
Userspace consumers can parse this event and attempt recovery as per the
|
||||||
following expectations.
|
following expectations.
|
||||||
|
|
@ -435,6 +434,7 @@ following expectations.
|
||||||
none optional telemetry collection
|
none optional telemetry collection
|
||||||
rebind unbind + bind driver
|
rebind unbind + bind driver
|
||||||
bus-reset unbind + bus reset/re-enumeration + bind
|
bus-reset unbind + bus reset/re-enumeration + bind
|
||||||
|
vendor-specific vendor specific recovery method
|
||||||
unknown consumer policy
|
unknown consumer policy
|
||||||
=============== ========================================
|
=============== ========================================
|
||||||
|
|
||||||
|
|
@ -446,6 +446,35 @@ telemetry information (devcoredump, syslog). This is useful because the first
|
||||||
hang is usually the most critical one which can result in consequential hangs or
|
hang is usually the most critical one which can result in consequential hangs or
|
||||||
complete wedging.
|
complete wedging.
|
||||||
|
|
||||||
|
|
||||||
|
Vendor Specific Recovery
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
When ``WEDGED=vendor-specific`` is sent, it indicates that the device requires
|
||||||
|
a recovery procedure specific to the hardware vendor and is not one of the
|
||||||
|
standardized approaches.
|
||||||
|
|
||||||
|
``WEDGED=vendor-specific`` may be used to indicate different cases within a
|
||||||
|
single vendor driver, each requiring a distinct recovery procedure.
|
||||||
|
In such scenarios, the vendor driver must provide comprehensive documentation
|
||||||
|
that describes each case, include additional hints to identify specific case and
|
||||||
|
outline the corresponding recovery procedure. The documentation includes:
|
||||||
|
|
||||||
|
Case - A list of all cases that sends the ``WEDGED=vendor-specific`` recovery method.
|
||||||
|
|
||||||
|
Hints - Additional Information to assist the userspace consumer in identifying and
|
||||||
|
differentiating between different cases. This can be exposed through sysfs, debugfs,
|
||||||
|
traces, dmesg etc.
|
||||||
|
|
||||||
|
Recovery Procedure - Clear instructions and guidance for recovering each case.
|
||||||
|
This may include userspace scripts, tools needed for the recovery procedure.
|
||||||
|
|
||||||
|
It is the responsibility of the admin/userspace consumer to identify the case and
|
||||||
|
verify additional identification hints before attempting a recovery procedure.
|
||||||
|
|
||||||
|
Example: If the device uses the Xe driver, then userspace consumer should refer to
|
||||||
|
:ref:`Xe Device Wedging <xe-device-wedging>` for the detailed documentation.
|
||||||
|
|
||||||
Task information
|
Task information
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|
@ -472,8 +501,12 @@ erroring out, all device memory should be unmapped and file descriptors should
|
||||||
be closed to prevent leaks or undefined behaviour. The idea here is to clear the
|
be closed to prevent leaks or undefined behaviour. The idea here is to clear the
|
||||||
device of all user context beforehand and set the stage for a clean recovery.
|
device of all user context beforehand and set the stage for a clean recovery.
|
||||||
|
|
||||||
Example
|
For ``WEDGED=vendor-specific`` recovery method, it is the responsibility of the
|
||||||
-------
|
consumer to check the driver documentation and the usecase before attempting
|
||||||
|
a recovery.
|
||||||
|
|
||||||
|
Example - rebind
|
||||||
|
----------------
|
||||||
|
|
||||||
Udev rule::
|
Udev rule::
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -358,8 +358,6 @@ Locking Guidelines
|
||||||
#. All locking rules and interface contracts with cross-driver interfaces
|
#. All locking rules and interface contracts with cross-driver interfaces
|
||||||
(dma-buf, dma_fence) need to be followed.
|
(dma-buf, dma_fence) need to be followed.
|
||||||
|
|
||||||
#. No struct_mutex anywhere in the code
|
|
||||||
|
|
||||||
#. dma_resv will be the outermost lock (when needed) and ww_acquire_ctx
|
#. dma_resv will be the outermost lock (when needed) and ww_acquire_ctx
|
||||||
is to be hoisted at highest level and passed down within i915_gem_ctx
|
is to be hoisted at highest level and passed down within i915_gem_ctx
|
||||||
in the call chain
|
in the call chain
|
||||||
|
|
@ -367,11 +365,6 @@ Locking Guidelines
|
||||||
#. While holding lru/memory manager (buddy, drm_mm, whatever) locks
|
#. While holding lru/memory manager (buddy, drm_mm, whatever) locks
|
||||||
system memory allocations are not allowed
|
system memory allocations are not allowed
|
||||||
|
|
||||||
* Enforce this by priming lockdep (with fs_reclaim). If we
|
|
||||||
allocate memory while holding these looks we get a rehash
|
|
||||||
of the shrinker vs. struct_mutex saga, and that would be
|
|
||||||
real bad.
|
|
||||||
|
|
||||||
#. Do not nest different lru/memory manager locks within each other.
|
#. Do not nest different lru/memory manager locks within each other.
|
||||||
Take them in turn to update memory allocations, relying on the object’s
|
Take them in turn to update memory allocations, relying on the object’s
|
||||||
dma_resv ww_mutex to serialize against other operations.
|
dma_resv ww_mutex to serialize against other operations.
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,6 @@ crate so it can be used by other components as well.
|
||||||
|
|
||||||
Features desired before this happens:
|
Features desired before this happens:
|
||||||
|
|
||||||
* Relative register with build-time base address validation,
|
|
||||||
* Arrays of registers with build-time index validation,
|
|
||||||
* Make I/O optional I/O (for field values that are not registers),
|
* Make I/O optional I/O (for field values that are not registers),
|
||||||
* Support other sizes than `u32`,
|
* Support other sizes than `u32`,
|
||||||
* Allow visibility control for registers and individual fields,
|
* Allow visibility control for registers and individual fields,
|
||||||
|
|
@ -231,23 +229,6 @@ Rust abstraction for debugfs APIs.
|
||||||
GPU (general)
|
GPU (general)
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Parse firmware headers
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Parse ELF headers from the firmware files loaded from the filesystem.
|
|
||||||
|
|
||||||
| Reference: ELF utils
|
|
||||||
| Complexity: Beginner
|
|
||||||
| Contact: Abdiel Janulgue
|
|
||||||
|
|
||||||
Build radix3 page table
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
Build the radix3 page table to map the firmware.
|
|
||||||
|
|
||||||
| Complexity: Intermediate
|
|
||||||
| Contact: Abdiel Janulgue
|
|
||||||
|
|
||||||
Initial Devinit support
|
Initial Devinit support
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -173,31 +173,6 @@ Contact: Simona Vetter
|
||||||
|
|
||||||
Level: Intermediate
|
Level: Intermediate
|
||||||
|
|
||||||
Get rid of dev->struct_mutex from GEM drivers
|
|
||||||
---------------------------------------------
|
|
||||||
|
|
||||||
``dev->struct_mutex`` is the Big DRM Lock from legacy days and infested
|
|
||||||
everything. Nowadays in modern drivers the only bit where it's mandatory is
|
|
||||||
serializing GEM buffer object destruction. Which unfortunately means drivers
|
|
||||||
have to keep track of that lock and either call ``unreference`` or
|
|
||||||
``unreference_locked`` depending upon context.
|
|
||||||
|
|
||||||
Core GEM doesn't have a need for ``struct_mutex`` any more since kernel 4.8,
|
|
||||||
and there's a GEM object ``free`` callback for any drivers which are
|
|
||||||
entirely ``struct_mutex`` free.
|
|
||||||
|
|
||||||
For drivers that need ``struct_mutex`` it should be replaced with a driver-
|
|
||||||
private lock. The tricky part is the BO free functions, since those can't
|
|
||||||
reliably take that lock any more. Instead state needs to be protected with
|
|
||||||
suitable subordinate locks or some cleanup work pushed to a worker thread. For
|
|
||||||
performance-critical drivers it might also be better to go with a more
|
|
||||||
fine-grained per-buffer object and per-context lockings scheme. Currently only
|
|
||||||
the ``msm`` and `i915` drivers use ``struct_mutex``.
|
|
||||||
|
|
||||||
Contact: Simona Vetter, respective driver maintainers
|
|
||||||
|
|
||||||
Level: Advanced
|
|
||||||
|
|
||||||
Move Buffer Object Locking to dma_resv_lock()
|
Move Buffer Object Locking to dma_resv_lock()
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
|
|
@ -497,19 +472,19 @@ Contact: Douglas Anderson <dianders@chromium.org>
|
||||||
|
|
||||||
Level: Intermediate
|
Level: Intermediate
|
||||||
|
|
||||||
Transition away from using mipi_dsi_*_write_seq()
|
Transition away from using deprecated MIPI DSI functions
|
||||||
-------------------------------------------------
|
--------------------------------------------------------
|
||||||
|
|
||||||
The macros mipi_dsi_generic_write_seq() and mipi_dsi_dcs_write_seq() are
|
There are many functions defined in ``drm_mipi_dsi.c`` which have been
|
||||||
non-intuitive because, if there are errors, they return out of the *caller's*
|
deprecated. Each deprecated function was deprecated in favor of its `multi`
|
||||||
function. We should move all callers to use mipi_dsi_generic_write_seq_multi()
|
variant (e.g. `mipi_dsi_generic_write()` and `mipi_dsi_generic_write_multi()`).
|
||||||
and mipi_dsi_dcs_write_seq_multi() macros instead.
|
The `multi` variant of a function includes improved error handling and logic
|
||||||
|
which makes it more convenient to make several calls in a row, as most MIPI
|
||||||
|
drivers do.
|
||||||
|
|
||||||
Once all callers are transitioned, the macros and the functions that they call,
|
Drivers should be updated to use undeprecated functions. Once all usages of the
|
||||||
mipi_dsi_generic_write_chatty() and mipi_dsi_dcs_write_buffer_chatty(), can
|
deprecated MIPI DSI functions have been removed, their definitions may be
|
||||||
probably be removed. Alternatively, if people feel like the _multi() variants
|
removed from ``drm_mipi_dsi.c``.
|
||||||
are overkill for some use cases, we could keep the mipi_dsi_*_write_seq()
|
|
||||||
variants but change them not to return out of the caller.
|
|
||||||
|
|
||||||
Contact: Douglas Anderson <dianders@chromium.org>
|
Contact: Douglas Anderson <dianders@chromium.org>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,6 @@ DG2, etc is provided to prototype the driver.
|
||||||
xe_tile
|
xe_tile
|
||||||
xe_debugging
|
xe_debugging
|
||||||
xe_devcoredump
|
xe_devcoredump
|
||||||
|
xe_device
|
||||||
xe-drm-usage-stats.rst
|
xe-drm-usage-stats.rst
|
||||||
xe_configfs
|
xe_configfs
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
.. SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||||
|
|
||||||
|
.. _xe-device-wedging:
|
||||||
|
|
||||||
|
==================
|
||||||
|
Xe Device Wedging
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. kernel-doc:: drivers/gpu/drm/xe/xe_device.c
|
||||||
|
:doc: Xe Device Wedging
|
||||||
|
|
@ -13,9 +13,11 @@ Internal API
|
||||||
.. kernel-doc:: drivers/gpu/drm/xe/xe_pcode.c
|
.. kernel-doc:: drivers/gpu/drm/xe/xe_pcode.c
|
||||||
:internal:
|
:internal:
|
||||||
|
|
||||||
|
.. _xe-survivability-mode:
|
||||||
|
|
||||||
==================
|
==================
|
||||||
Boot Survivability
|
Survivability Mode
|
||||||
==================
|
==================
|
||||||
|
|
||||||
.. kernel-doc:: drivers/gpu/drm/xe/xe_survivability_mode.c
|
.. kernel-doc:: drivers/gpu/drm/xe/xe_survivability_mode.c
|
||||||
:doc: Xe Boot Survivability
|
:doc: Survivability Mode
|
||||||
|
|
|
||||||
50
MAINTAINERS
50
MAINTAINERS
|
|
@ -1243,7 +1243,7 @@ F: drivers/spi/spi-amd.c
|
||||||
F: drivers/spi/spi-amd.h
|
F: drivers/spi/spi-amd.h
|
||||||
|
|
||||||
AMD XDNA DRIVER
|
AMD XDNA DRIVER
|
||||||
M: Min Ma <min.ma@amd.com>
|
M: Min Ma <mamin506@gmail.com>
|
||||||
M: Lizhi Hou <lizhi.hou@amd.com>
|
M: Lizhi Hou <lizhi.hou@amd.com>
|
||||||
L: dri-devel@lists.freedesktop.org
|
L: dri-devel@lists.freedesktop.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
@ -2096,6 +2096,19 @@ F: Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
|
||||||
F: drivers/gpu/drm/panthor/
|
F: drivers/gpu/drm/panthor/
|
||||||
F: include/uapi/drm/panthor_drm.h
|
F: include/uapi/drm/panthor_drm.h
|
||||||
|
|
||||||
|
ARM MALI TYR DRM DRIVER
|
||||||
|
M: Daniel Almeida <daniel.almeida@collabora.com>
|
||||||
|
M: Alice Ryhl <aliceryhl@google.com>
|
||||||
|
L: dri-devel@lists.freedesktop.org
|
||||||
|
S: Supported
|
||||||
|
W: https://rust-for-linux.com/tyr-gpu-driver
|
||||||
|
W https://drm.pages.freedesktop.org/maintainer-tools/drm-rust.html
|
||||||
|
B: https://gitlab.freedesktop.org/panfrost/linux/-/issues
|
||||||
|
T: git https://gitlab.freedesktop.org/drm/rust/kernel.git
|
||||||
|
F: Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml
|
||||||
|
F: drivers/gpu/drm/tyr/
|
||||||
|
F: include/uapi/drm/panthor_drm.h
|
||||||
|
|
||||||
ARM MALI-DP DRM DRIVER
|
ARM MALI-DP DRM DRIVER
|
||||||
M: Liviu Dudau <liviu.dudau@arm.com>
|
M: Liviu Dudau <liviu.dudau@arm.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
@ -7297,7 +7310,7 @@ F: include/linux/dma-mapping.h
|
||||||
F: include/linux/swiotlb.h
|
F: include/linux/swiotlb.h
|
||||||
F: kernel/dma/
|
F: kernel/dma/
|
||||||
|
|
||||||
DMA MAPPING HELPERS DEVICE DRIVER API [RUST]
|
DMA MAPPING & SCATTERLIST API [RUST]
|
||||||
M: Danilo Krummrich <dakr@kernel.org>
|
M: Danilo Krummrich <dakr@kernel.org>
|
||||||
R: Abdiel Janulgue <abdiel.janulgue@gmail.com>
|
R: Abdiel Janulgue <abdiel.janulgue@gmail.com>
|
||||||
R: Daniel Almeida <daniel.almeida@collabora.com>
|
R: Daniel Almeida <daniel.almeida@collabora.com>
|
||||||
|
|
@ -7308,7 +7321,9 @@ S: Supported
|
||||||
W: https://rust-for-linux.com
|
W: https://rust-for-linux.com
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
|
||||||
F: rust/helpers/dma.c
|
F: rust/helpers/dma.c
|
||||||
|
F: rust/helpers/scatterlist.c
|
||||||
F: rust/kernel/dma.rs
|
F: rust/kernel/dma.rs
|
||||||
|
F: rust/kernel/scatterlist.rs
|
||||||
F: samples/rust/rust_dma.rs
|
F: samples/rust/rust_dma.rs
|
||||||
|
|
||||||
DMA-BUF HEAPS FRAMEWORK
|
DMA-BUF HEAPS FRAMEWORK
|
||||||
|
|
@ -7553,14 +7568,24 @@ F: drivers/soc/ti/smartreflex.c
|
||||||
F: include/linux/power/smartreflex.h
|
F: include/linux/power/smartreflex.h
|
||||||
|
|
||||||
DRM ACCEL DRIVERS FOR INTEL VPU
|
DRM ACCEL DRIVERS FOR INTEL VPU
|
||||||
M: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
|
|
||||||
M: Maciej Falkowski <maciej.falkowski@linux.intel.com>
|
M: Maciej Falkowski <maciej.falkowski@linux.intel.com>
|
||||||
|
M: Karol Wachowski <karol.wachowski@linux.intel.com>
|
||||||
L: dri-devel@lists.freedesktop.org
|
L: dri-devel@lists.freedesktop.org
|
||||||
S: Supported
|
S: Supported
|
||||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||||
F: drivers/accel/ivpu/
|
F: drivers/accel/ivpu/
|
||||||
F: include/uapi/drm/ivpu_accel.h
|
F: include/uapi/drm/ivpu_accel.h
|
||||||
|
|
||||||
|
DRM ACCEL DRIVER FOR ROCKCHIP NPU
|
||||||
|
M: Tomeu Vizoso <tomeu@tomeuvizoso.net>
|
||||||
|
L: dri-devel@lists.freedesktop.org
|
||||||
|
S: Supported
|
||||||
|
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||||
|
F: Documentation/accel/rocket/
|
||||||
|
F: Documentation/devicetree/bindings/npu/rockchip,rk3588-rknn-core.yaml
|
||||||
|
F: drivers/accel/rocket/
|
||||||
|
F: include/uapi/drm/rocket_accel.h
|
||||||
|
|
||||||
DRM COMPUTE ACCELERATORS DRIVERS AND FRAMEWORK
|
DRM COMPUTE ACCELERATORS DRIVERS AND FRAMEWORK
|
||||||
M: Oded Gabbay <ogabbay@kernel.org>
|
M: Oded Gabbay <ogabbay@kernel.org>
|
||||||
L: dri-devel@lists.freedesktop.org
|
L: dri-devel@lists.freedesktop.org
|
||||||
|
|
@ -7892,6 +7917,7 @@ M: Danilo Krummrich <dakr@kernel.org>
|
||||||
M: Alexandre Courbot <acourbot@nvidia.com>
|
M: Alexandre Courbot <acourbot@nvidia.com>
|
||||||
L: nouveau@lists.freedesktop.org
|
L: nouveau@lists.freedesktop.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
W: https://rust-for-linux.com/nova-gpu-driver
|
||||||
Q: https://patchwork.freedesktop.org/project/nouveau/
|
Q: https://patchwork.freedesktop.org/project/nouveau/
|
||||||
B: https://gitlab.freedesktop.org/drm/nova/-/issues
|
B: https://gitlab.freedesktop.org/drm/nova/-/issues
|
||||||
C: irc://irc.oftc.net/nouveau
|
C: irc://irc.oftc.net/nouveau
|
||||||
|
|
@ -7903,6 +7929,7 @@ DRM DRIVER FOR NVIDIA GPUS [RUST]
|
||||||
M: Danilo Krummrich <dakr@kernel.org>
|
M: Danilo Krummrich <dakr@kernel.org>
|
||||||
L: nouveau@lists.freedesktop.org
|
L: nouveau@lists.freedesktop.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
W: https://rust-for-linux.com/nova-gpu-driver
|
||||||
Q: https://patchwork.freedesktop.org/project/nouveau/
|
Q: https://patchwork.freedesktop.org/project/nouveau/
|
||||||
B: https://gitlab.freedesktop.org/drm/nova/-/issues
|
B: https://gitlab.freedesktop.org/drm/nova/-/issues
|
||||||
C: irc://irc.oftc.net/nouveau
|
C: irc://irc.oftc.net/nouveau
|
||||||
|
|
@ -7929,6 +7956,13 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||||
F: Documentation/devicetree/bindings/display/repaper.txt
|
F: Documentation/devicetree/bindings/display/repaper.txt
|
||||||
F: drivers/gpu/drm/tiny/repaper.c
|
F: drivers/gpu/drm/tiny/repaper.c
|
||||||
|
|
||||||
|
DRM DRIVER FOR PIXPAPER E-INK PANEL
|
||||||
|
M: LiangCheng Wang <zaq14760@gmail.com>
|
||||||
|
L: dri-devel@lists.freedesktop.org
|
||||||
|
S: Maintained
|
||||||
|
F: Documentation/devicetree/bindings/display/mayqueen,pixpaper.yaml
|
||||||
|
F: drivers/gpu/drm/tiny/pixpaper.c
|
||||||
|
|
||||||
DRM DRIVER FOR QEMU'S CIRRUS DEVICE
|
DRM DRIVER FOR QEMU'S CIRRUS DEVICE
|
||||||
M: Dave Airlie <airlied@redhat.com>
|
M: Dave Airlie <airlied@redhat.com>
|
||||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
|
@ -8051,6 +8085,14 @@ S: Maintained
|
||||||
F: Documentation/devicetree/bindings/display/panel/synaptics,r63353.yaml
|
F: Documentation/devicetree/bindings/display/panel/synaptics,r63353.yaml
|
||||||
F: drivers/gpu/drm/panel/panel-synaptics-r63353.c
|
F: drivers/gpu/drm/panel/panel-synaptics-r63353.c
|
||||||
|
|
||||||
|
DRM DRIVER FOR SYNOPSYS DESIGNWARE DISPLAYPORT BRIDGE
|
||||||
|
M: Andy Yan <andy.yan@rock-chips.com>
|
||||||
|
S: Maintained
|
||||||
|
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||||
|
F: Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
|
||||||
|
F: drivers/gpu/drm/bridge/synopsys/dw-dp.c
|
||||||
|
F: include/drm/bridge/dw_dp.h
|
||||||
|
|
||||||
DRM DRIVER FOR TI DLPC3433 MIPI DSI TO DMD BRIDGE
|
DRM DRIVER FOR TI DLPC3433 MIPI DSI TO DMD BRIDGE
|
||||||
M: Jagan Teki <jagan@amarulasolutions.com>
|
M: Jagan Teki <jagan@amarulasolutions.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
@ -20869,7 +20911,7 @@ F: include/dt-bindings/clock/qcom,*
|
||||||
|
|
||||||
QUALCOMM CLOUD AI (QAIC) DRIVER
|
QUALCOMM CLOUD AI (QAIC) DRIVER
|
||||||
M: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
|
M: Jeff Hugo <jeff.hugo@oss.qualcomm.com>
|
||||||
R: Carl Vanderlip <quic_carlv@quicinc.com>
|
R: Carl Vanderlip <carl.vanderlip@oss.qualcomm.com>
|
||||||
L: linux-arm-msm@vger.kernel.org
|
L: linux-arm-msm@vger.kernel.org
|
||||||
L: dri-devel@lists.freedesktop.org
|
L: dri-devel@lists.freedesktop.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
struct device;
|
struct device;
|
||||||
|
|
||||||
#if defined(CONFIG_STI_CORE)
|
#if defined(CONFIG_STI_CORE) && defined(CONFIG_VIDEO)
|
||||||
bool video_is_primary_device(struct device *dev);
|
bool video_is_primary_device(struct device *dev);
|
||||||
#define video_is_primary_device video_is_primary_device
|
#define video_is_primary_device video_is_primary_device
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,10 @@ static inline pgprot_t pgprot_framebuffer(pgprot_t prot,
|
||||||
#define pgprot_framebuffer pgprot_framebuffer
|
#define pgprot_framebuffer pgprot_framebuffer
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_VIDEO
|
||||||
bool video_is_primary_device(struct device *dev);
|
bool video_is_primary_device(struct device *dev);
|
||||||
#define video_is_primary_device video_is_primary_device
|
#define video_is_primary_device video_is_primary_device
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void fb_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
|
static inline void fb_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,10 @@ pgprot_t pgprot_framebuffer(pgprot_t prot,
|
||||||
unsigned long offset);
|
unsigned long offset);
|
||||||
#define pgprot_framebuffer pgprot_framebuffer
|
#define pgprot_framebuffer pgprot_framebuffer
|
||||||
|
|
||||||
|
#ifdef CONFIG_VIDEO
|
||||||
bool video_is_primary_device(struct device *dev);
|
bool video_is_primary_device(struct device *dev);
|
||||||
#define video_is_primary_device video_is_primary_device
|
#define video_is_primary_device video_is_primary_device
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <asm-generic/video.h>
|
#include <asm-generic/video.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
#include <linux/screen_info.h>
|
||||||
#include <linux/vgaarb.h>
|
#include <linux/vgaarb.h>
|
||||||
|
|
||||||
#include <asm/video.h>
|
#include <asm/video.h>
|
||||||
|
|
@ -27,6 +28,11 @@ EXPORT_SYMBOL(pgprot_framebuffer);
|
||||||
|
|
||||||
bool video_is_primary_device(struct device *dev)
|
bool video_is_primary_device(struct device *dev)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SCREEN_INFO
|
||||||
|
struct screen_info *si = &screen_info;
|
||||||
|
struct resource res[SCREEN_INFO_MAX_RESOURCES];
|
||||||
|
ssize_t i, numres;
|
||||||
|
#endif
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
if (!dev_is_pci(dev))
|
if (!dev_is_pci(dev))
|
||||||
|
|
@ -34,7 +40,24 @@ bool video_is_primary_device(struct device *dev)
|
||||||
|
|
||||||
pdev = to_pci_dev(dev);
|
pdev = to_pci_dev(dev);
|
||||||
|
|
||||||
return (pdev == vga_default_device());
|
if (!pci_is_display(pdev))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (pdev == vga_default_device())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCREEN_INFO
|
||||||
|
numres = screen_info_resources(si, res, ARRAY_SIZE(res));
|
||||||
|
for (i = 0; i < numres; ++i) {
|
||||||
|
if (!(res[i].flags & IORESOURCE_MEM))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pci_find_resource(pdev, &res[i]))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(video_is_primary_device);
|
EXPORT_SYMBOL(video_is_primary_device);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,5 +28,6 @@ source "drivers/accel/amdxdna/Kconfig"
|
||||||
source "drivers/accel/habanalabs/Kconfig"
|
source "drivers/accel/habanalabs/Kconfig"
|
||||||
source "drivers/accel/ivpu/Kconfig"
|
source "drivers/accel/ivpu/Kconfig"
|
||||||
source "drivers/accel/qaic/Kconfig"
|
source "drivers/accel/qaic/Kconfig"
|
||||||
|
source "drivers/accel/rocket/Kconfig"
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,4 @@ obj-$(CONFIG_DRM_ACCEL_AMDXDNA) += amdxdna/
|
||||||
obj-$(CONFIG_DRM_ACCEL_HABANALABS) += habanalabs/
|
obj-$(CONFIG_DRM_ACCEL_HABANALABS) += habanalabs/
|
||||||
obj-$(CONFIG_DRM_ACCEL_IVPU) += ivpu/
|
obj-$(CONFIG_DRM_ACCEL_IVPU) += ivpu/
|
||||||
obj-$(CONFIG_DRM_ACCEL_QAIC) += qaic/
|
obj-$(CONFIG_DRM_ACCEL_QAIC) += qaic/
|
||||||
|
obj-$(CONFIG_DRM_ACCEL_ROCKET) += rocket/
|
||||||
|
|
@ -15,6 +15,7 @@ amdxdna-y := \
|
||||||
amdxdna_mailbox_helper.o \
|
amdxdna_mailbox_helper.o \
|
||||||
amdxdna_pci_drv.o \
|
amdxdna_pci_drv.o \
|
||||||
amdxdna_sysfs.o \
|
amdxdna_sysfs.o \
|
||||||
|
amdxdna_ubuf.o \
|
||||||
npu1_regs.o \
|
npu1_regs.o \
|
||||||
npu2_regs.o \
|
npu2_regs.o \
|
||||||
npu4_regs.o \
|
npu4_regs.o \
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,17 @@ static void aie2_job_put(struct amdxdna_sched_job *job)
|
||||||
kref_put(&job->refcnt, aie2_job_release);
|
kref_put(&job->refcnt, aie2_job_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void aie2_hwctx_status_shift_stop(struct amdxdna_hwctx *hwctx)
|
||||||
|
{
|
||||||
|
hwctx->old_status = hwctx->status;
|
||||||
|
hwctx->status = HWCTX_STAT_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aie2_hwctx_status_restore(struct amdxdna_hwctx *hwctx)
|
||||||
|
{
|
||||||
|
hwctx->status = hwctx->old_status;
|
||||||
|
}
|
||||||
|
|
||||||
/* The bad_job is used in aie2_sched_job_timedout, otherwise, set it to NULL */
|
/* The bad_job is used in aie2_sched_job_timedout, otherwise, set it to NULL */
|
||||||
static void aie2_hwctx_stop(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx,
|
static void aie2_hwctx_stop(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx,
|
||||||
struct drm_sched_job *bad_job)
|
struct drm_sched_job *bad_job)
|
||||||
|
|
@ -89,25 +100,6 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void aie2_restart_ctx(struct amdxdna_client *client)
|
|
||||||
{
|
|
||||||
struct amdxdna_dev *xdna = client->xdna;
|
|
||||||
struct amdxdna_hwctx *hwctx;
|
|
||||||
unsigned long hwctx_id;
|
|
||||||
|
|
||||||
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
|
||||||
mutex_lock(&client->hwctx_lock);
|
|
||||||
amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
|
|
||||||
if (hwctx->status != HWCTX_STAT_STOP)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
hwctx->status = hwctx->old_status;
|
|
||||||
XDNA_DBG(xdna, "Resetting %s", hwctx->name);
|
|
||||||
aie2_hwctx_restart(xdna, hwctx);
|
|
||||||
}
|
|
||||||
mutex_unlock(&client->hwctx_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct dma_fence *aie2_cmd_get_out_fence(struct amdxdna_hwctx *hwctx, u64 seq)
|
static struct dma_fence *aie2_cmd_get_out_fence(struct amdxdna_hwctx *hwctx, u64 seq)
|
||||||
{
|
{
|
||||||
struct dma_fence *fence, *out_fence = NULL;
|
struct dma_fence *fence, *out_fence = NULL;
|
||||||
|
|
@ -141,34 +133,49 @@ static void aie2_hwctx_wait_for_idle(struct amdxdna_hwctx *hwctx)
|
||||||
dma_fence_put(fence);
|
dma_fence_put(fence);
|
||||||
}
|
}
|
||||||
|
|
||||||
void aie2_hwctx_suspend(struct amdxdna_hwctx *hwctx)
|
static int aie2_hwctx_suspend_cb(struct amdxdna_hwctx *hwctx, void *arg)
|
||||||
{
|
{
|
||||||
struct amdxdna_dev *xdna = hwctx->client->xdna;
|
struct amdxdna_dev *xdna = hwctx->client->xdna;
|
||||||
|
|
||||||
|
aie2_hwctx_wait_for_idle(hwctx);
|
||||||
|
aie2_hwctx_stop(xdna, hwctx, NULL);
|
||||||
|
aie2_hwctx_status_shift_stop(hwctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void aie2_hwctx_suspend(struct amdxdna_client *client)
|
||||||
|
{
|
||||||
|
struct amdxdna_dev *xdna = client->xdna;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Command timeout is unlikely. But if it happens, it doesn't
|
* Command timeout is unlikely. But if it happens, it doesn't
|
||||||
* break the system. aie2_hwctx_stop() will destroy mailbox
|
* break the system. aie2_hwctx_stop() will destroy mailbox
|
||||||
* and abort all commands.
|
* and abort all commands.
|
||||||
*/
|
*/
|
||||||
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
||||||
aie2_hwctx_wait_for_idle(hwctx);
|
amdxdna_hwctx_walk(client, NULL, aie2_hwctx_suspend_cb);
|
||||||
aie2_hwctx_stop(xdna, hwctx, NULL);
|
|
||||||
hwctx->old_status = hwctx->status;
|
|
||||||
hwctx->status = HWCTX_STAT_STOP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void aie2_hwctx_resume(struct amdxdna_hwctx *hwctx)
|
static int aie2_hwctx_resume_cb(struct amdxdna_hwctx *hwctx, void *arg)
|
||||||
{
|
{
|
||||||
struct amdxdna_dev *xdna = hwctx->client->xdna;
|
struct amdxdna_dev *xdna = hwctx->client->xdna;
|
||||||
|
|
||||||
|
aie2_hwctx_status_restore(hwctx);
|
||||||
|
return aie2_hwctx_restart(xdna, hwctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int aie2_hwctx_resume(struct amdxdna_client *client)
|
||||||
|
{
|
||||||
|
struct amdxdna_dev *xdna = client->xdna;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The resume path cannot guarantee that mailbox channel can be
|
* The resume path cannot guarantee that mailbox channel can be
|
||||||
* regenerated. If this happen, when submit message to this
|
* regenerated. If this happen, when submit message to this
|
||||||
* mailbox channel, error will return.
|
* mailbox channel, error will return.
|
||||||
*/
|
*/
|
||||||
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
||||||
hwctx->status = hwctx->old_status;
|
return amdxdna_hwctx_walk(client, NULL, aie2_hwctx_resume_cb);
|
||||||
aie2_hwctx_restart(xdna, hwctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -192,7 +199,7 @@ aie2_sched_resp_handler(void *handle, void __iomem *data, size_t size)
|
||||||
{
|
{
|
||||||
struct amdxdna_sched_job *job = handle;
|
struct amdxdna_sched_job *job = handle;
|
||||||
struct amdxdna_gem_obj *cmd_abo;
|
struct amdxdna_gem_obj *cmd_abo;
|
||||||
u32 ret = 0;
|
int ret = 0;
|
||||||
u32 status;
|
u32 status;
|
||||||
|
|
||||||
cmd_abo = job->cmd_bo;
|
cmd_abo = job->cmd_bo;
|
||||||
|
|
@ -222,7 +229,7 @@ static int
|
||||||
aie2_sched_nocmd_resp_handler(void *handle, void __iomem *data, size_t size)
|
aie2_sched_nocmd_resp_handler(void *handle, void __iomem *data, size_t size)
|
||||||
{
|
{
|
||||||
struct amdxdna_sched_job *job = handle;
|
struct amdxdna_sched_job *job = handle;
|
||||||
u32 ret = 0;
|
int ret = 0;
|
||||||
u32 status;
|
u32 status;
|
||||||
|
|
||||||
if (unlikely(!data))
|
if (unlikely(!data))
|
||||||
|
|
@ -250,7 +257,7 @@ aie2_sched_cmdlist_resp_handler(void *handle, void __iomem *data, size_t size)
|
||||||
u32 fail_cmd_status;
|
u32 fail_cmd_status;
|
||||||
u32 fail_cmd_idx;
|
u32 fail_cmd_idx;
|
||||||
u32 cmd_status;
|
u32 cmd_status;
|
||||||
u32 ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
cmd_abo = job->cmd_bo;
|
cmd_abo = job->cmd_bo;
|
||||||
if (unlikely(!data) || unlikely(size != sizeof(u32) * 3)) {
|
if (unlikely(!data) || unlikely(size != sizeof(u32) * 3)) {
|
||||||
|
|
|
||||||
|
|
@ -290,18 +290,25 @@ int aie2_map_host_buf(struct amdxdna_dev_hdl *ndev, u32 context_id, u64 addr, u6
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int amdxdna_hwctx_col_map(struct amdxdna_hwctx *hwctx, void *arg)
|
||||||
|
{
|
||||||
|
u32 *bitmap = arg;
|
||||||
|
|
||||||
|
*bitmap |= GENMASK(hwctx->start_col + hwctx->num_col - 1, hwctx->start_col);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf,
|
int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf,
|
||||||
u32 size, u32 *cols_filled)
|
u32 size, u32 *cols_filled)
|
||||||
{
|
{
|
||||||
DECLARE_AIE2_MSG(aie_column_info, MSG_OP_QUERY_COL_STATUS);
|
DECLARE_AIE2_MSG(aie_column_info, MSG_OP_QUERY_COL_STATUS);
|
||||||
struct amdxdna_dev *xdna = ndev->xdna;
|
struct amdxdna_dev *xdna = ndev->xdna;
|
||||||
struct amdxdna_client *client;
|
struct amdxdna_client *client;
|
||||||
struct amdxdna_hwctx *hwctx;
|
|
||||||
unsigned long hwctx_id;
|
|
||||||
dma_addr_t dma_addr;
|
dma_addr_t dma_addr;
|
||||||
u32 aie_bitmap = 0;
|
u32 aie_bitmap = 0;
|
||||||
u8 *buff_addr;
|
u8 *buff_addr;
|
||||||
int ret, idx;
|
int ret;
|
||||||
|
|
||||||
buff_addr = dma_alloc_noncoherent(xdna->ddev.dev, size, &dma_addr,
|
buff_addr = dma_alloc_noncoherent(xdna->ddev.dev, size, &dma_addr,
|
||||||
DMA_FROM_DEVICE, GFP_KERNEL);
|
DMA_FROM_DEVICE, GFP_KERNEL);
|
||||||
|
|
@ -309,12 +316,8 @@ int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Go through each hardware context and mark the AIE columns that are active */
|
/* Go through each hardware context and mark the AIE columns that are active */
|
||||||
list_for_each_entry(client, &xdna->client_list, node) {
|
list_for_each_entry(client, &xdna->client_list, node)
|
||||||
idx = srcu_read_lock(&client->hwctx_srcu);
|
amdxdna_hwctx_walk(client, &aie_bitmap, amdxdna_hwctx_col_map);
|
||||||
amdxdna_for_each_hwctx(client, hwctx_id, hwctx)
|
|
||||||
aie_bitmap |= amdxdna_hwctx_col_map(hwctx);
|
|
||||||
srcu_read_unlock(&client->hwctx_srcu, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
*cols_filled = 0;
|
*cols_filled = 0;
|
||||||
req.dump_buff_addr = dma_addr;
|
req.dump_buff_addr = dma_addr;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <drm/drm_managed.h>
|
#include <drm/drm_managed.h>
|
||||||
#include <drm/drm_print.h>
|
#include <drm/drm_print.h>
|
||||||
#include <drm/gpu_scheduler.h>
|
#include <drm/gpu_scheduler.h>
|
||||||
|
#include <linux/cleanup.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/iommu.h>
|
#include <linux/iommu.h>
|
||||||
|
|
@ -440,6 +441,40 @@ disable_dev:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int aie2_hw_suspend(struct amdxdna_dev *xdna)
|
||||||
|
{
|
||||||
|
struct amdxdna_client *client;
|
||||||
|
|
||||||
|
guard(mutex)(&xdna->dev_lock);
|
||||||
|
list_for_each_entry(client, &xdna->client_list, node)
|
||||||
|
aie2_hwctx_suspend(client);
|
||||||
|
|
||||||
|
aie2_hw_stop(xdna);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int aie2_hw_resume(struct amdxdna_dev *xdna)
|
||||||
|
{
|
||||||
|
struct amdxdna_client *client;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
guard(mutex)(&xdna->dev_lock);
|
||||||
|
ret = aie2_hw_start(xdna);
|
||||||
|
if (ret) {
|
||||||
|
XDNA_ERR(xdna, "Start hardware failed, %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(client, &xdna->client_list, node) {
|
||||||
|
ret = aie2_hwctx_resume(client);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int aie2_init(struct amdxdna_dev *xdna)
|
static int aie2_init(struct amdxdna_dev *xdna)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
|
struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
|
||||||
|
|
@ -520,14 +555,14 @@ static int aie2_init(struct amdxdna_dev *xdna)
|
||||||
if (!ndev->psp_hdl) {
|
if (!ndev->psp_hdl) {
|
||||||
XDNA_ERR(xdna, "failed to create psp");
|
XDNA_ERR(xdna, "failed to create psp");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto free_irq;
|
goto release_fw;
|
||||||
}
|
}
|
||||||
xdna->dev_handle = ndev;
|
xdna->dev_handle = ndev;
|
||||||
|
|
||||||
ret = aie2_hw_start(xdna);
|
ret = aie2_hw_start(xdna);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XDNA_ERR(xdna, "start npu failed, ret %d", ret);
|
XDNA_ERR(xdna, "start npu failed, ret %d", ret);
|
||||||
goto free_irq;
|
goto release_fw;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = aie2_mgmt_fw_query(ndev);
|
ret = aie2_mgmt_fw_query(ndev);
|
||||||
|
|
@ -578,8 +613,6 @@ async_event_free:
|
||||||
aie2_error_async_events_free(ndev);
|
aie2_error_async_events_free(ndev);
|
||||||
stop_hw:
|
stop_hw:
|
||||||
aie2_hw_stop(xdna);
|
aie2_hw_stop(xdna);
|
||||||
free_irq:
|
|
||||||
pci_free_irq_vectors(pdev);
|
|
||||||
release_fw:
|
release_fw:
|
||||||
release_firmware(fw);
|
release_firmware(fw);
|
||||||
|
|
||||||
|
|
@ -588,12 +621,10 @@ release_fw:
|
||||||
|
|
||||||
static void aie2_fini(struct amdxdna_dev *xdna)
|
static void aie2_fini(struct amdxdna_dev *xdna)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
|
|
||||||
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
|
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
|
||||||
|
|
||||||
aie2_hw_stop(xdna);
|
aie2_hw_stop(xdna);
|
||||||
aie2_error_async_events_free(ndev);
|
aie2_error_async_events_free(ndev);
|
||||||
pci_free_irq_vectors(pdev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aie2_get_aie_status(struct amdxdna_client *client,
|
static int aie2_get_aie_status(struct amdxdna_client *client,
|
||||||
|
|
@ -752,65 +783,68 @@ static int aie2_get_clock_metadata(struct amdxdna_client *client,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aie2_get_hwctx_status(struct amdxdna_client *client,
|
static int aie2_hwctx_status_cb(struct amdxdna_hwctx *hwctx, void *arg)
|
||||||
struct amdxdna_drm_get_info *args)
|
|
||||||
{
|
{
|
||||||
struct amdxdna_drm_query_hwctx __user *buf;
|
struct amdxdna_drm_hwctx_entry *tmp __free(kfree) = NULL;
|
||||||
struct amdxdna_dev *xdna = client->xdna;
|
struct amdxdna_drm_get_array *array_args = arg;
|
||||||
struct amdxdna_drm_query_hwctx *tmp;
|
struct amdxdna_drm_hwctx_entry __user *buf;
|
||||||
struct amdxdna_client *tmp_client;
|
u32 size;
|
||||||
struct amdxdna_hwctx *hwctx;
|
|
||||||
unsigned long hwctx_id;
|
|
||||||
bool overflow = false;
|
|
||||||
u32 req_bytes = 0;
|
|
||||||
u32 hw_i = 0;
|
|
||||||
int ret = 0;
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
if (!array_args->num_element)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
buf = u64_to_user_ptr(args->buffer);
|
tmp->pid = hwctx->client->pid;
|
||||||
list_for_each_entry(tmp_client, &xdna->client_list, node) {
|
|
||||||
idx = srcu_read_lock(&tmp_client->hwctx_srcu);
|
|
||||||
amdxdna_for_each_hwctx(tmp_client, hwctx_id, hwctx) {
|
|
||||||
req_bytes += sizeof(*tmp);
|
|
||||||
if (args->buffer_size < req_bytes) {
|
|
||||||
/* Continue iterating to get the required size */
|
|
||||||
overflow = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(tmp, 0, sizeof(*tmp));
|
|
||||||
tmp->pid = tmp_client->pid;
|
|
||||||
tmp->context_id = hwctx->id;
|
tmp->context_id = hwctx->id;
|
||||||
tmp->start_col = hwctx->start_col;
|
tmp->start_col = hwctx->start_col;
|
||||||
tmp->num_col = hwctx->num_col;
|
tmp->num_col = hwctx->num_col;
|
||||||
tmp->command_submissions = hwctx->priv->seq;
|
tmp->command_submissions = hwctx->priv->seq;
|
||||||
tmp->command_completions = hwctx->priv->completed;
|
tmp->command_completions = hwctx->priv->completed;
|
||||||
|
tmp->pasid = hwctx->client->pasid;
|
||||||
|
tmp->priority = hwctx->qos.priority;
|
||||||
|
tmp->gops = hwctx->qos.gops;
|
||||||
|
tmp->fps = hwctx->qos.fps;
|
||||||
|
tmp->dma_bandwidth = hwctx->qos.dma_bandwidth;
|
||||||
|
tmp->latency = hwctx->qos.latency;
|
||||||
|
tmp->frame_exec_time = hwctx->qos.frame_exec_time;
|
||||||
|
tmp->state = AMDXDNA_HWCTX_STATE_ACTIVE;
|
||||||
|
|
||||||
if (copy_to_user(&buf[hw_i], tmp, sizeof(*tmp))) {
|
buf = u64_to_user_ptr(array_args->buffer);
|
||||||
ret = -EFAULT;
|
size = min(sizeof(*tmp), array_args->element_size);
|
||||||
srcu_read_unlock(&tmp_client->hwctx_srcu, idx);
|
|
||||||
goto out;
|
if (copy_to_user(buf, tmp, size))
|
||||||
}
|
return -EFAULT;
|
||||||
hw_i++;
|
|
||||||
}
|
array_args->buffer += size;
|
||||||
srcu_read_unlock(&tmp_client->hwctx_srcu, idx);
|
array_args->num_element--;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int aie2_get_hwctx_status(struct amdxdna_client *client,
|
||||||
|
struct amdxdna_drm_get_info *args)
|
||||||
|
{
|
||||||
|
struct amdxdna_drm_get_array array_args;
|
||||||
|
struct amdxdna_dev *xdna = client->xdna;
|
||||||
|
struct amdxdna_client *tmp_client;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
||||||
|
|
||||||
|
array_args.element_size = sizeof(struct amdxdna_drm_query_hwctx);
|
||||||
|
array_args.buffer = args->buffer;
|
||||||
|
array_args.num_element = args->buffer_size / array_args.element_size;
|
||||||
|
list_for_each_entry(tmp_client, &xdna->client_list, node) {
|
||||||
|
ret = amdxdna_hwctx_walk(tmp_client, &array_args,
|
||||||
|
aie2_hwctx_status_cb);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overflow) {
|
args->buffer_size -= (u32)(array_args.buffer - args->buffer);
|
||||||
XDNA_ERR(xdna, "Invalid buffer size. Given: %u Need: %u.",
|
|
||||||
args->buffer_size, req_bytes);
|
|
||||||
ret = -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
kfree(tmp);
|
|
||||||
args->buffer_size = req_bytes;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -854,6 +888,58 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int aie2_query_ctx_status_array(struct amdxdna_client *client,
|
||||||
|
struct amdxdna_drm_get_array *args)
|
||||||
|
{
|
||||||
|
struct amdxdna_drm_get_array array_args;
|
||||||
|
struct amdxdna_dev *xdna = client->xdna;
|
||||||
|
struct amdxdna_client *tmp_client;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
||||||
|
|
||||||
|
array_args.element_size = min(args->element_size,
|
||||||
|
sizeof(struct amdxdna_drm_hwctx_entry));
|
||||||
|
array_args.buffer = args->buffer;
|
||||||
|
array_args.num_element = args->num_element * args->element_size /
|
||||||
|
array_args.element_size;
|
||||||
|
list_for_each_entry(tmp_client, &xdna->client_list, node) {
|
||||||
|
ret = amdxdna_hwctx_walk(tmp_client, &array_args,
|
||||||
|
aie2_hwctx_status_cb);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
args->element_size = array_args.element_size;
|
||||||
|
args->num_element = (u32)((array_args.buffer - args->buffer) /
|
||||||
|
args->element_size);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int aie2_get_array(struct amdxdna_client *client,
|
||||||
|
struct amdxdna_drm_get_array *args)
|
||||||
|
{
|
||||||
|
struct amdxdna_dev *xdna = client->xdna;
|
||||||
|
int ret, idx;
|
||||||
|
|
||||||
|
if (!drm_dev_enter(&xdna->ddev, &idx))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
switch (args->param) {
|
||||||
|
case DRM_AMDXDNA_HW_CONTEXT_ALL:
|
||||||
|
ret = aie2_query_ctx_status_array(client, args);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
XDNA_ERR(xdna, "Not supported request parameter %u", args->param);
|
||||||
|
ret = -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
XDNA_DBG(xdna, "Got param %d", args->param);
|
||||||
|
|
||||||
|
drm_dev_exit(idx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int aie2_set_power_mode(struct amdxdna_client *client,
|
static int aie2_set_power_mode(struct amdxdna_client *client,
|
||||||
struct amdxdna_drm_set_state *args)
|
struct amdxdna_drm_set_state *args)
|
||||||
{
|
{
|
||||||
|
|
@ -905,8 +991,8 @@ static int aie2_set_state(struct amdxdna_client *client,
|
||||||
const struct amdxdna_dev_ops aie2_ops = {
|
const struct amdxdna_dev_ops aie2_ops = {
|
||||||
.init = aie2_init,
|
.init = aie2_init,
|
||||||
.fini = aie2_fini,
|
.fini = aie2_fini,
|
||||||
.resume = aie2_hw_start,
|
.resume = aie2_hw_resume,
|
||||||
.suspend = aie2_hw_stop,
|
.suspend = aie2_hw_suspend,
|
||||||
.get_aie_info = aie2_get_info,
|
.get_aie_info = aie2_get_info,
|
||||||
.set_aie_state = aie2_set_state,
|
.set_aie_state = aie2_set_state,
|
||||||
.hwctx_init = aie2_hwctx_init,
|
.hwctx_init = aie2_hwctx_init,
|
||||||
|
|
@ -914,6 +1000,5 @@ const struct amdxdna_dev_ops aie2_ops = {
|
||||||
.hwctx_config = aie2_hwctx_config,
|
.hwctx_config = aie2_hwctx_config,
|
||||||
.cmd_submit = aie2_cmd_submit,
|
.cmd_submit = aie2_cmd_submit,
|
||||||
.hmm_invalidate = aie2_hmm_invalidate,
|
.hmm_invalidate = aie2_hmm_invalidate,
|
||||||
.hwctx_suspend = aie2_hwctx_suspend,
|
.get_array = aie2_get_array,
|
||||||
.hwctx_resume = aie2_hwctx_resume,
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -288,10 +288,9 @@ int aie2_sync_bo(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
|
||||||
int aie2_hwctx_init(struct amdxdna_hwctx *hwctx);
|
int aie2_hwctx_init(struct amdxdna_hwctx *hwctx);
|
||||||
void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx);
|
void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx);
|
||||||
int aie2_hwctx_config(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void *buf, u32 size);
|
int aie2_hwctx_config(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void *buf, u32 size);
|
||||||
void aie2_hwctx_suspend(struct amdxdna_hwctx *hwctx);
|
void aie2_hwctx_suspend(struct amdxdna_client *client);
|
||||||
void aie2_hwctx_resume(struct amdxdna_hwctx *hwctx);
|
int aie2_hwctx_resume(struct amdxdna_client *client);
|
||||||
int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq);
|
int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq);
|
||||||
void aie2_hmm_invalidate(struct amdxdna_gem_obj *abo, unsigned long cur_seq);
|
void aie2_hmm_invalidate(struct amdxdna_gem_obj *abo, unsigned long cur_seq);
|
||||||
void aie2_restart_ctx(struct amdxdna_client *client);
|
|
||||||
|
|
||||||
#endif /* _AIE2_PCI_H_ */
|
#endif /* _AIE2_PCI_H_ */
|
||||||
|
|
|
||||||
|
|
@ -60,32 +60,6 @@ static struct dma_fence *amdxdna_fence_create(struct amdxdna_hwctx *hwctx)
|
||||||
return &fence->base;
|
return &fence->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
void amdxdna_hwctx_suspend(struct amdxdna_client *client)
|
|
||||||
{
|
|
||||||
struct amdxdna_dev *xdna = client->xdna;
|
|
||||||
struct amdxdna_hwctx *hwctx;
|
|
||||||
unsigned long hwctx_id;
|
|
||||||
|
|
||||||
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
|
||||||
mutex_lock(&client->hwctx_lock);
|
|
||||||
amdxdna_for_each_hwctx(client, hwctx_id, hwctx)
|
|
||||||
xdna->dev_info->ops->hwctx_suspend(hwctx);
|
|
||||||
mutex_unlock(&client->hwctx_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void amdxdna_hwctx_resume(struct amdxdna_client *client)
|
|
||||||
{
|
|
||||||
struct amdxdna_dev *xdna = client->xdna;
|
|
||||||
struct amdxdna_hwctx *hwctx;
|
|
||||||
unsigned long hwctx_id;
|
|
||||||
|
|
||||||
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
|
|
||||||
mutex_lock(&client->hwctx_lock);
|
|
||||||
amdxdna_for_each_hwctx(client, hwctx_id, hwctx)
|
|
||||||
xdna->dev_info->ops->hwctx_resume(hwctx);
|
|
||||||
mutex_unlock(&client->hwctx_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void amdxdna_hwctx_destroy_rcu(struct amdxdna_hwctx *hwctx,
|
static void amdxdna_hwctx_destroy_rcu(struct amdxdna_hwctx *hwctx,
|
||||||
struct srcu_struct *ss)
|
struct srcu_struct *ss)
|
||||||
{
|
{
|
||||||
|
|
@ -94,14 +68,30 @@ static void amdxdna_hwctx_destroy_rcu(struct amdxdna_hwctx *hwctx,
|
||||||
synchronize_srcu(ss);
|
synchronize_srcu(ss);
|
||||||
|
|
||||||
/* At this point, user is not able to submit new commands */
|
/* At this point, user is not able to submit new commands */
|
||||||
mutex_lock(&xdna->dev_lock);
|
|
||||||
xdna->dev_info->ops->hwctx_fini(hwctx);
|
xdna->dev_info->ops->hwctx_fini(hwctx);
|
||||||
mutex_unlock(&xdna->dev_lock);
|
|
||||||
|
|
||||||
kfree(hwctx->name);
|
kfree(hwctx->name);
|
||||||
kfree(hwctx);
|
kfree(hwctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int amdxdna_hwctx_walk(struct amdxdna_client *client, void *arg,
|
||||||
|
int (*walk)(struct amdxdna_hwctx *hwctx, void *arg))
|
||||||
|
{
|
||||||
|
struct amdxdna_hwctx *hwctx;
|
||||||
|
unsigned long hwctx_id;
|
||||||
|
int ret = 0, idx;
|
||||||
|
|
||||||
|
idx = srcu_read_lock(&client->hwctx_srcu);
|
||||||
|
amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
|
||||||
|
ret = walk(hwctx, arg);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
srcu_read_unlock(&client->hwctx_srcu, idx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size)
|
void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size)
|
||||||
{
|
{
|
||||||
struct amdxdna_cmd *cmd = abo->mem.kva;
|
struct amdxdna_cmd *cmd = abo->mem.kva;
|
||||||
|
|
@ -152,16 +142,12 @@ void amdxdna_hwctx_remove_all(struct amdxdna_client *client)
|
||||||
struct amdxdna_hwctx *hwctx;
|
struct amdxdna_hwctx *hwctx;
|
||||||
unsigned long hwctx_id;
|
unsigned long hwctx_id;
|
||||||
|
|
||||||
mutex_lock(&client->hwctx_lock);
|
|
||||||
amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
|
amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
|
||||||
XDNA_DBG(client->xdna, "PID %d close HW context %d",
|
XDNA_DBG(client->xdna, "PID %d close HW context %d",
|
||||||
client->pid, hwctx->id);
|
client->pid, hwctx->id);
|
||||||
xa_erase(&client->hwctx_xa, hwctx->id);
|
xa_erase(&client->hwctx_xa, hwctx->id);
|
||||||
mutex_unlock(&client->hwctx_lock);
|
|
||||||
amdxdna_hwctx_destroy_rcu(hwctx, &client->hwctx_srcu);
|
amdxdna_hwctx_destroy_rcu(hwctx, &client->hwctx_srcu);
|
||||||
mutex_lock(&client->hwctx_lock);
|
|
||||||
}
|
}
|
||||||
mutex_unlock(&client->hwctx_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||||
|
|
@ -251,6 +237,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d
|
||||||
if (!drm_dev_enter(dev, &idx))
|
if (!drm_dev_enter(dev, &idx))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
mutex_lock(&xdna->dev_lock);
|
||||||
hwctx = xa_erase(&client->hwctx_xa, args->handle);
|
hwctx = xa_erase(&client->hwctx_xa, args->handle);
|
||||||
if (!hwctx) {
|
if (!hwctx) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
|
@ -267,6 +254,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d
|
||||||
|
|
||||||
XDNA_DBG(xdna, "PID %d destroyed HW context %d", client->pid, args->handle);
|
XDNA_DBG(xdna, "PID %d destroyed HW context %d", client->pid, args->handle);
|
||||||
out:
|
out:
|
||||||
|
mutex_unlock(&xdna->dev_lock);
|
||||||
drm_dev_exit(idx);
|
drm_dev_exit(idx);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -139,16 +139,10 @@ amdxdna_cmd_get_state(struct amdxdna_gem_obj *abo)
|
||||||
void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size);
|
void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size);
|
||||||
int amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo);
|
int amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo);
|
||||||
|
|
||||||
static inline u32 amdxdna_hwctx_col_map(struct amdxdna_hwctx *hwctx)
|
|
||||||
{
|
|
||||||
return GENMASK(hwctx->start_col + hwctx->num_col - 1,
|
|
||||||
hwctx->start_col);
|
|
||||||
}
|
|
||||||
|
|
||||||
void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job);
|
void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job);
|
||||||
void amdxdna_hwctx_remove_all(struct amdxdna_client *client);
|
void amdxdna_hwctx_remove_all(struct amdxdna_client *client);
|
||||||
void amdxdna_hwctx_suspend(struct amdxdna_client *client);
|
int amdxdna_hwctx_walk(struct amdxdna_client *client, void *arg,
|
||||||
void amdxdna_hwctx_resume(struct amdxdna_client *client);
|
int (*walk)(struct amdxdna_hwctx *hwctx, void *arg));
|
||||||
|
|
||||||
int amdxdna_cmd_submit(struct amdxdna_client *client,
|
int amdxdna_cmd_submit(struct amdxdna_client *client,
|
||||||
u32 cmd_bo_hdls, u32 *arg_bo_hdls, u32 arg_bo_cnt,
|
u32 cmd_bo_hdls, u32 *arg_bo_hdls, u32 arg_bo_cnt,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#include "amdxdna_ctx.h"
|
#include "amdxdna_ctx.h"
|
||||||
#include "amdxdna_gem.h"
|
#include "amdxdna_gem.h"
|
||||||
#include "amdxdna_pci_drv.h"
|
#include "amdxdna_pci_drv.h"
|
||||||
|
#include "amdxdna_ubuf.h"
|
||||||
|
|
||||||
#define XDNA_MAX_CMD_BO_SIZE SZ_32K
|
#define XDNA_MAX_CMD_BO_SIZE SZ_32K
|
||||||
|
|
||||||
|
|
@ -296,7 +297,7 @@ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
|
||||||
|
|
||||||
vma->vm_private_data = NULL;
|
vma->vm_private_data = NULL;
|
||||||
vma->vm_ops = NULL;
|
vma->vm_ops = NULL;
|
||||||
ret = dma_buf_mmap(to_gobj(abo)->dma_buf, vma, 0);
|
ret = dma_buf_mmap(abo->dma_buf, vma, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XDNA_ERR(xdna, "Failed to mmap dma buf %d", ret);
|
XDNA_ERR(xdna, "Failed to mmap dma buf %d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -391,10 +392,47 @@ static const struct dma_buf_ops amdxdna_dmabuf_ops = {
|
||||||
.vunmap = drm_gem_dmabuf_vunmap,
|
.vunmap = drm_gem_dmabuf_vunmap,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int amdxdna_gem_obj_vmap(struct drm_gem_object *obj, struct iosys_map *map)
|
||||||
|
{
|
||||||
|
struct amdxdna_gem_obj *abo = to_xdna_obj(obj);
|
||||||
|
|
||||||
|
iosys_map_clear(map);
|
||||||
|
|
||||||
|
dma_resv_assert_held(obj->resv);
|
||||||
|
|
||||||
|
if (is_import_bo(abo))
|
||||||
|
dma_buf_vmap(abo->dma_buf, map);
|
||||||
|
else
|
||||||
|
drm_gem_shmem_object_vmap(obj, map);
|
||||||
|
|
||||||
|
if (!map->vaddr)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amdxdna_gem_obj_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
|
||||||
|
{
|
||||||
|
struct amdxdna_gem_obj *abo = to_xdna_obj(obj);
|
||||||
|
|
||||||
|
dma_resv_assert_held(obj->resv);
|
||||||
|
|
||||||
|
if (is_import_bo(abo))
|
||||||
|
dma_buf_vunmap(abo->dma_buf, map);
|
||||||
|
else
|
||||||
|
drm_gem_shmem_object_vunmap(obj, map);
|
||||||
|
}
|
||||||
|
|
||||||
static struct dma_buf *amdxdna_gem_prime_export(struct drm_gem_object *gobj, int flags)
|
static struct dma_buf *amdxdna_gem_prime_export(struct drm_gem_object *gobj, int flags)
|
||||||
{
|
{
|
||||||
|
struct amdxdna_gem_obj *abo = to_xdna_obj(gobj);
|
||||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||||
|
|
||||||
|
if (abo->dma_buf) {
|
||||||
|
get_dma_buf(abo->dma_buf);
|
||||||
|
return abo->dma_buf;
|
||||||
|
}
|
||||||
|
|
||||||
exp_info.ops = &amdxdna_dmabuf_ops;
|
exp_info.ops = &amdxdna_dmabuf_ops;
|
||||||
exp_info.size = gobj->size;
|
exp_info.size = gobj->size;
|
||||||
exp_info.flags = flags;
|
exp_info.flags = flags;
|
||||||
|
|
@ -451,8 +489,8 @@ static const struct drm_gem_object_funcs amdxdna_gem_shmem_funcs = {
|
||||||
.pin = drm_gem_shmem_object_pin,
|
.pin = drm_gem_shmem_object_pin,
|
||||||
.unpin = drm_gem_shmem_object_unpin,
|
.unpin = drm_gem_shmem_object_unpin,
|
||||||
.get_sg_table = drm_gem_shmem_object_get_sg_table,
|
.get_sg_table = drm_gem_shmem_object_get_sg_table,
|
||||||
.vmap = drm_gem_shmem_object_vmap,
|
.vmap = amdxdna_gem_obj_vmap,
|
||||||
.vunmap = drm_gem_shmem_object_vunmap,
|
.vunmap = amdxdna_gem_obj_vunmap,
|
||||||
.mmap = amdxdna_gem_obj_mmap,
|
.mmap = amdxdna_gem_obj_mmap,
|
||||||
.vm_ops = &drm_gem_shmem_vm_ops,
|
.vm_ops = &drm_gem_shmem_vm_ops,
|
||||||
.export = amdxdna_gem_prime_export,
|
.export = amdxdna_gem_prime_export,
|
||||||
|
|
@ -494,6 +532,68 @@ amdxdna_gem_create_object_cb(struct drm_device *dev, size_t size)
|
||||||
return to_gobj(abo);
|
return to_gobj(abo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct amdxdna_gem_obj *
|
||||||
|
amdxdna_gem_create_shmem_object(struct drm_device *dev, size_t size)
|
||||||
|
{
|
||||||
|
struct drm_gem_shmem_object *shmem = drm_gem_shmem_create(dev, size);
|
||||||
|
|
||||||
|
if (IS_ERR(shmem))
|
||||||
|
return ERR_CAST(shmem);
|
||||||
|
|
||||||
|
shmem->map_wc = false;
|
||||||
|
return to_xdna_obj(&shmem->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct amdxdna_gem_obj *
|
||||||
|
amdxdna_gem_create_ubuf_object(struct drm_device *dev, struct amdxdna_drm_create_bo *args)
|
||||||
|
{
|
||||||
|
struct amdxdna_dev *xdna = to_xdna_dev(dev);
|
||||||
|
enum amdxdna_ubuf_flag flags = 0;
|
||||||
|
struct amdxdna_drm_va_tbl va_tbl;
|
||||||
|
struct drm_gem_object *gobj;
|
||||||
|
struct dma_buf *dma_buf;
|
||||||
|
|
||||||
|
if (copy_from_user(&va_tbl, u64_to_user_ptr(args->vaddr), sizeof(va_tbl))) {
|
||||||
|
XDNA_DBG(xdna, "Access va table failed");
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (va_tbl.num_entries) {
|
||||||
|
if (args->type == AMDXDNA_BO_CMD)
|
||||||
|
flags |= AMDXDNA_UBUF_FLAG_MAP_DMA;
|
||||||
|
|
||||||
|
dma_buf = amdxdna_get_ubuf(dev, flags, va_tbl.num_entries,
|
||||||
|
u64_to_user_ptr(args->vaddr + sizeof(va_tbl)));
|
||||||
|
} else {
|
||||||
|
dma_buf = dma_buf_get(va_tbl.dmabuf_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ERR(dma_buf))
|
||||||
|
return ERR_CAST(dma_buf);
|
||||||
|
|
||||||
|
gobj = amdxdna_gem_prime_import(dev, dma_buf);
|
||||||
|
if (IS_ERR(gobj)) {
|
||||||
|
dma_buf_put(dma_buf);
|
||||||
|
return ERR_CAST(gobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_buf_put(dma_buf);
|
||||||
|
|
||||||
|
return to_xdna_obj(gobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct amdxdna_gem_obj *
|
||||||
|
amdxdna_gem_create_object(struct drm_device *dev,
|
||||||
|
struct amdxdna_drm_create_bo *args)
|
||||||
|
{
|
||||||
|
size_t aligned_sz = PAGE_ALIGN(args->size);
|
||||||
|
|
||||||
|
if (args->vaddr)
|
||||||
|
return amdxdna_gem_create_ubuf_object(dev, args);
|
||||||
|
|
||||||
|
return amdxdna_gem_create_shmem_object(dev, aligned_sz);
|
||||||
|
}
|
||||||
|
|
||||||
struct drm_gem_object *
|
struct drm_gem_object *
|
||||||
amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
|
amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf)
|
||||||
{
|
{
|
||||||
|
|
@ -545,16 +645,12 @@ amdxdna_drm_alloc_shmem(struct drm_device *dev,
|
||||||
struct drm_file *filp)
|
struct drm_file *filp)
|
||||||
{
|
{
|
||||||
struct amdxdna_client *client = filp->driver_priv;
|
struct amdxdna_client *client = filp->driver_priv;
|
||||||
struct drm_gem_shmem_object *shmem;
|
|
||||||
struct amdxdna_gem_obj *abo;
|
struct amdxdna_gem_obj *abo;
|
||||||
|
|
||||||
shmem = drm_gem_shmem_create(dev, args->size);
|
abo = amdxdna_gem_create_object(dev, args);
|
||||||
if (IS_ERR(shmem))
|
if (IS_ERR(abo))
|
||||||
return ERR_CAST(shmem);
|
return ERR_CAST(abo);
|
||||||
|
|
||||||
shmem->map_wc = false;
|
|
||||||
|
|
||||||
abo = to_xdna_obj(&shmem->base);
|
|
||||||
abo->client = client;
|
abo->client = client;
|
||||||
abo->type = AMDXDNA_BO_SHMEM;
|
abo->type = AMDXDNA_BO_SHMEM;
|
||||||
|
|
||||||
|
|
@ -569,7 +665,6 @@ amdxdna_drm_create_dev_heap(struct drm_device *dev,
|
||||||
struct amdxdna_client *client = filp->driver_priv;
|
struct amdxdna_client *client = filp->driver_priv;
|
||||||
struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
|
struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
|
||||||
struct amdxdna_dev *xdna = to_xdna_dev(dev);
|
struct amdxdna_dev *xdna = to_xdna_dev(dev);
|
||||||
struct drm_gem_shmem_object *shmem;
|
|
||||||
struct amdxdna_gem_obj *abo;
|
struct amdxdna_gem_obj *abo;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
@ -586,14 +681,12 @@ amdxdna_drm_create_dev_heap(struct drm_device *dev,
|
||||||
goto mm_unlock;
|
goto mm_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
shmem = drm_gem_shmem_create(dev, args->size);
|
abo = amdxdna_gem_create_object(dev, args);
|
||||||
if (IS_ERR(shmem)) {
|
if (IS_ERR(abo)) {
|
||||||
ret = PTR_ERR(shmem);
|
ret = PTR_ERR(abo);
|
||||||
goto mm_unlock;
|
goto mm_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
shmem->map_wc = false;
|
|
||||||
abo = to_xdna_obj(&shmem->base);
|
|
||||||
abo->type = AMDXDNA_BO_DEV_HEAP;
|
abo->type = AMDXDNA_BO_DEV_HEAP;
|
||||||
abo->client = client;
|
abo->client = client;
|
||||||
abo->mem.dev_addr = client->xdna->dev_info->dev_mem_base;
|
abo->mem.dev_addr = client->xdna->dev_info->dev_mem_base;
|
||||||
|
|
@ -657,7 +750,6 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
|
||||||
{
|
{
|
||||||
struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
|
struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
|
||||||
struct amdxdna_dev *xdna = to_xdna_dev(dev);
|
struct amdxdna_dev *xdna = to_xdna_dev(dev);
|
||||||
struct drm_gem_shmem_object *shmem;
|
|
||||||
struct amdxdna_gem_obj *abo;
|
struct amdxdna_gem_obj *abo;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
@ -671,12 +763,9 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
shmem = drm_gem_shmem_create(dev, args->size);
|
abo = amdxdna_gem_create_object(dev, args);
|
||||||
if (IS_ERR(shmem))
|
if (IS_ERR(abo))
|
||||||
return ERR_CAST(shmem);
|
return ERR_CAST(abo);
|
||||||
|
|
||||||
shmem->map_wc = false;
|
|
||||||
abo = to_xdna_obj(&shmem->base);
|
|
||||||
|
|
||||||
abo->type = AMDXDNA_BO_CMD;
|
abo->type = AMDXDNA_BO_CMD;
|
||||||
abo->client = filp->driver_priv;
|
abo->client = filp->driver_priv;
|
||||||
|
|
@ -691,7 +780,7 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
|
||||||
return abo;
|
return abo;
|
||||||
|
|
||||||
release_obj:
|
release_obj:
|
||||||
drm_gem_shmem_free(shmem);
|
drm_gem_object_put(to_gobj(abo));
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -702,7 +791,7 @@ int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_f
|
||||||
struct amdxdna_gem_obj *abo;
|
struct amdxdna_gem_obj *abo;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (args->flags || args->vaddr || !args->size)
|
if (args->flags)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
XDNA_DBG(xdna, "BO arg type %d vaddr 0x%llx size 0x%llx flags 0x%llx",
|
XDNA_DBG(xdna, "BO arg type %d vaddr 0x%llx size 0x%llx flags 0x%llx",
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,13 @@ MODULE_FIRMWARE("amdnpu/17f0_10/npu.sbin");
|
||||||
MODULE_FIRMWARE("amdnpu/17f0_11/npu.sbin");
|
MODULE_FIRMWARE("amdnpu/17f0_11/npu.sbin");
|
||||||
MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin");
|
MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 0.0: Initial version
|
||||||
|
* 0.1: Support getting all hardware contexts by DRM_IOCTL_AMDXDNA_GET_ARRAY
|
||||||
|
*/
|
||||||
|
#define AMDXDNA_DRIVER_MAJOR 0
|
||||||
|
#define AMDXDNA_DRIVER_MINOR 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bind the driver base on (vendor_id, device_id) pair and later use the
|
* Bind the driver base on (vendor_id, device_id) pair and later use the
|
||||||
* (device_id, rev_id) pair as a key to select the devices. The devices with
|
* (device_id, rev_id) pair as a key to select the devices. The devices with
|
||||||
|
|
@ -81,7 +88,6 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto unbind_sva;
|
goto unbind_sva;
|
||||||
}
|
}
|
||||||
mutex_init(&client->hwctx_lock);
|
|
||||||
init_srcu_struct(&client->hwctx_srcu);
|
init_srcu_struct(&client->hwctx_srcu);
|
||||||
xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC);
|
xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC);
|
||||||
mutex_init(&client->mm_lock);
|
mutex_init(&client->mm_lock);
|
||||||
|
|
@ -116,7 +122,6 @@ static void amdxdna_drm_close(struct drm_device *ddev, struct drm_file *filp)
|
||||||
|
|
||||||
xa_destroy(&client->hwctx_xa);
|
xa_destroy(&client->hwctx_xa);
|
||||||
cleanup_srcu_struct(&client->hwctx_srcu);
|
cleanup_srcu_struct(&client->hwctx_srcu);
|
||||||
mutex_destroy(&client->hwctx_lock);
|
|
||||||
mutex_destroy(&client->mm_lock);
|
mutex_destroy(&client->mm_lock);
|
||||||
if (client->dev_heap)
|
if (client->dev_heap)
|
||||||
drm_gem_object_put(to_gobj(client->dev_heap));
|
drm_gem_object_put(to_gobj(client->dev_heap));
|
||||||
|
|
@ -142,8 +147,8 @@ static int amdxdna_flush(struct file *f, fl_owner_t id)
|
||||||
|
|
||||||
mutex_lock(&xdna->dev_lock);
|
mutex_lock(&xdna->dev_lock);
|
||||||
list_del_init(&client->node);
|
list_del_init(&client->node);
|
||||||
mutex_unlock(&xdna->dev_lock);
|
|
||||||
amdxdna_hwctx_remove_all(client);
|
amdxdna_hwctx_remove_all(client);
|
||||||
|
mutex_unlock(&xdna->dev_lock);
|
||||||
|
|
||||||
drm_dev_exit(idx);
|
drm_dev_exit(idx);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -166,6 +171,23 @@ static int amdxdna_drm_get_info_ioctl(struct drm_device *dev, void *data, struct
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int amdxdna_drm_get_array_ioctl(struct drm_device *dev, void *data,
|
||||||
|
struct drm_file *filp)
|
||||||
|
{
|
||||||
|
struct amdxdna_client *client = filp->driver_priv;
|
||||||
|
struct amdxdna_dev *xdna = to_xdna_dev(dev);
|
||||||
|
struct amdxdna_drm_get_array *args = data;
|
||||||
|
|
||||||
|
if (!xdna->dev_info->ops->get_array)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (args->pad || !args->num_element || !args->element_size)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
guard(mutex)(&xdna->dev_lock);
|
||||||
|
return xdna->dev_info->ops->get_array(client, args);
|
||||||
|
}
|
||||||
|
|
||||||
static int amdxdna_drm_set_state_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
static int amdxdna_drm_set_state_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||||
{
|
{
|
||||||
struct amdxdna_client *client = filp->driver_priv;
|
struct amdxdna_client *client = filp->driver_priv;
|
||||||
|
|
@ -197,6 +219,7 @@ static const struct drm_ioctl_desc amdxdna_drm_ioctls[] = {
|
||||||
DRM_IOCTL_DEF_DRV(AMDXDNA_EXEC_CMD, amdxdna_drm_submit_cmd_ioctl, 0),
|
DRM_IOCTL_DEF_DRV(AMDXDNA_EXEC_CMD, amdxdna_drm_submit_cmd_ioctl, 0),
|
||||||
/* AIE hardware */
|
/* AIE hardware */
|
||||||
DRM_IOCTL_DEF_DRV(AMDXDNA_GET_INFO, amdxdna_drm_get_info_ioctl, 0),
|
DRM_IOCTL_DEF_DRV(AMDXDNA_GET_INFO, amdxdna_drm_get_info_ioctl, 0),
|
||||||
|
DRM_IOCTL_DEF_DRV(AMDXDNA_GET_ARRAY, amdxdna_drm_get_array_ioctl, 0),
|
||||||
DRM_IOCTL_DEF_DRV(AMDXDNA_SET_STATE, amdxdna_drm_set_state_ioctl, DRM_ROOT_ONLY),
|
DRM_IOCTL_DEF_DRV(AMDXDNA_SET_STATE, amdxdna_drm_set_state_ioctl, DRM_ROOT_ONLY),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -220,6 +243,8 @@ const struct drm_driver amdxdna_drm_drv = {
|
||||||
.fops = &amdxdna_fops,
|
.fops = &amdxdna_fops,
|
||||||
.name = "amdxdna_accel_driver",
|
.name = "amdxdna_accel_driver",
|
||||||
.desc = "AMD XDNA DRM implementation",
|
.desc = "AMD XDNA DRM implementation",
|
||||||
|
.major = AMDXDNA_DRIVER_MAJOR,
|
||||||
|
.minor = AMDXDNA_DRIVER_MINOR,
|
||||||
.open = amdxdna_drm_open,
|
.open = amdxdna_drm_open,
|
||||||
.postclose = amdxdna_drm_close,
|
.postclose = amdxdna_drm_close,
|
||||||
.ioctls = amdxdna_drm_ioctls,
|
.ioctls = amdxdna_drm_ioctls,
|
||||||
|
|
@ -330,11 +355,8 @@ static void amdxdna_remove(struct pci_dev *pdev)
|
||||||
struct amdxdna_client, node);
|
struct amdxdna_client, node);
|
||||||
while (client) {
|
while (client) {
|
||||||
list_del_init(&client->node);
|
list_del_init(&client->node);
|
||||||
mutex_unlock(&xdna->dev_lock);
|
|
||||||
|
|
||||||
amdxdna_hwctx_remove_all(client);
|
amdxdna_hwctx_remove_all(client);
|
||||||
|
|
||||||
mutex_lock(&xdna->dev_lock);
|
|
||||||
client = list_first_entry_or_null(&xdna->client_list,
|
client = list_first_entry_or_null(&xdna->client_list,
|
||||||
struct amdxdna_client, node);
|
struct amdxdna_client, node);
|
||||||
}
|
}
|
||||||
|
|
@ -343,89 +365,29 @@ static void amdxdna_remove(struct pci_dev *pdev)
|
||||||
mutex_unlock(&xdna->dev_lock);
|
mutex_unlock(&xdna->dev_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int amdxdna_dev_suspend_nolock(struct amdxdna_dev *xdna)
|
|
||||||
{
|
|
||||||
if (xdna->dev_info->ops->suspend)
|
|
||||||
xdna->dev_info->ops->suspend(xdna);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int amdxdna_dev_resume_nolock(struct amdxdna_dev *xdna)
|
|
||||||
{
|
|
||||||
if (xdna->dev_info->ops->resume)
|
|
||||||
return xdna->dev_info->ops->resume(xdna);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int amdxdna_pmops_suspend(struct device *dev)
|
static int amdxdna_pmops_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));
|
struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));
|
||||||
struct amdxdna_client *client;
|
|
||||||
|
|
||||||
mutex_lock(&xdna->dev_lock);
|
if (!xdna->dev_info->ops->suspend)
|
||||||
list_for_each_entry(client, &xdna->client_list, node)
|
return -EOPNOTSUPP;
|
||||||
amdxdna_hwctx_suspend(client);
|
|
||||||
|
|
||||||
amdxdna_dev_suspend_nolock(xdna);
|
return xdna->dev_info->ops->suspend(xdna);
|
||||||
mutex_unlock(&xdna->dev_lock);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int amdxdna_pmops_resume(struct device *dev)
|
static int amdxdna_pmops_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));
|
struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));
|
||||||
struct amdxdna_client *client;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
XDNA_INFO(xdna, "firmware resuming...");
|
if (!xdna->dev_info->ops->resume)
|
||||||
mutex_lock(&xdna->dev_lock);
|
return -EOPNOTSUPP;
|
||||||
ret = amdxdna_dev_resume_nolock(xdna);
|
|
||||||
if (ret) {
|
|
||||||
XDNA_ERR(xdna, "resume NPU firmware failed");
|
|
||||||
mutex_unlock(&xdna->dev_lock);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
XDNA_INFO(xdna, "hardware context resuming...");
|
return xdna->dev_info->ops->resume(xdna);
|
||||||
list_for_each_entry(client, &xdna->client_list, node)
|
|
||||||
amdxdna_hwctx_resume(client);
|
|
||||||
mutex_unlock(&xdna->dev_lock);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int amdxdna_rpmops_suspend(struct device *dev)
|
|
||||||
{
|
|
||||||
struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
mutex_lock(&xdna->dev_lock);
|
|
||||||
ret = amdxdna_dev_suspend_nolock(xdna);
|
|
||||||
mutex_unlock(&xdna->dev_lock);
|
|
||||||
|
|
||||||
XDNA_DBG(xdna, "Runtime suspend done ret: %d", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int amdxdna_rpmops_resume(struct device *dev)
|
|
||||||
{
|
|
||||||
struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
mutex_lock(&xdna->dev_lock);
|
|
||||||
ret = amdxdna_dev_resume_nolock(xdna);
|
|
||||||
mutex_unlock(&xdna->dev_lock);
|
|
||||||
|
|
||||||
XDNA_DBG(xdna, "Runtime resume done ret: %d", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct dev_pm_ops amdxdna_pm_ops = {
|
static const struct dev_pm_ops amdxdna_pm_ops = {
|
||||||
SYSTEM_SLEEP_PM_OPS(amdxdna_pmops_suspend, amdxdna_pmops_resume)
|
SYSTEM_SLEEP_PM_OPS(amdxdna_pmops_suspend, amdxdna_pmops_resume)
|
||||||
RUNTIME_PM_OPS(amdxdna_rpmops_suspend, amdxdna_rpmops_resume, NULL)
|
RUNTIME_PM_OPS(amdxdna_pmops_suspend, amdxdna_pmops_resume, NULL)
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pci_driver amdxdna_pci_driver = {
|
static struct pci_driver amdxdna_pci_driver = {
|
||||||
|
|
|
||||||
|
|
@ -50,16 +50,15 @@ struct amdxdna_dev_ops {
|
||||||
int (*init)(struct amdxdna_dev *xdna);
|
int (*init)(struct amdxdna_dev *xdna);
|
||||||
void (*fini)(struct amdxdna_dev *xdna);
|
void (*fini)(struct amdxdna_dev *xdna);
|
||||||
int (*resume)(struct amdxdna_dev *xdna);
|
int (*resume)(struct amdxdna_dev *xdna);
|
||||||
void (*suspend)(struct amdxdna_dev *xdna);
|
int (*suspend)(struct amdxdna_dev *xdna);
|
||||||
int (*hwctx_init)(struct amdxdna_hwctx *hwctx);
|
int (*hwctx_init)(struct amdxdna_hwctx *hwctx);
|
||||||
void (*hwctx_fini)(struct amdxdna_hwctx *hwctx);
|
void (*hwctx_fini)(struct amdxdna_hwctx *hwctx);
|
||||||
int (*hwctx_config)(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void *buf, u32 size);
|
int (*hwctx_config)(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void *buf, u32 size);
|
||||||
void (*hmm_invalidate)(struct amdxdna_gem_obj *abo, unsigned long cur_seq);
|
void (*hmm_invalidate)(struct amdxdna_gem_obj *abo, unsigned long cur_seq);
|
||||||
void (*hwctx_suspend)(struct amdxdna_hwctx *hwctx);
|
|
||||||
void (*hwctx_resume)(struct amdxdna_hwctx *hwctx);
|
|
||||||
int (*cmd_submit)(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq);
|
int (*cmd_submit)(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq);
|
||||||
int (*get_aie_info)(struct amdxdna_client *client, struct amdxdna_drm_get_info *args);
|
int (*get_aie_info)(struct amdxdna_client *client, struct amdxdna_drm_get_info *args);
|
||||||
int (*set_aie_state)(struct amdxdna_client *client, struct amdxdna_drm_set_state *args);
|
int (*set_aie_state)(struct amdxdna_client *client, struct amdxdna_drm_set_state *args);
|
||||||
|
int (*get_array)(struct amdxdna_client *client, struct amdxdna_drm_get_array *args);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -118,8 +117,6 @@ struct amdxdna_device_id {
|
||||||
struct amdxdna_client {
|
struct amdxdna_client {
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
struct mutex hwctx_lock; /* protect hwctx */
|
|
||||||
/* do NOT wait this srcu when hwctx_lock is held */
|
|
||||||
struct srcu_struct hwctx_srcu;
|
struct srcu_struct hwctx_srcu;
|
||||||
struct xarray hwctx_xa;
|
struct xarray hwctx_xa;
|
||||||
u32 next_hwctxid;
|
u32 next_hwctxid;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,232 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025, Advanced Micro Devices, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <drm/amdxdna_accel.h>
|
||||||
|
#include <drm/drm_device.h>
|
||||||
|
#include <drm/drm_print.h>
|
||||||
|
#include <linux/dma-buf.h>
|
||||||
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
|
||||||
|
#include "amdxdna_pci_drv.h"
|
||||||
|
#include "amdxdna_ubuf.h"
|
||||||
|
|
||||||
|
struct amdxdna_ubuf_priv {
|
||||||
|
struct page **pages;
|
||||||
|
u64 nr_pages;
|
||||||
|
enum amdxdna_ubuf_flag flags;
|
||||||
|
struct mm_struct *mm;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sg_table *amdxdna_ubuf_map(struct dma_buf_attachment *attach,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
{
|
||||||
|
struct amdxdna_ubuf_priv *ubuf = attach->dmabuf->priv;
|
||||||
|
struct sg_table *sg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sg = kzalloc(sizeof(*sg), GFP_KERNEL);
|
||||||
|
if (!sg)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
ret = sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->nr_pages, 0,
|
||||||
|
ubuf->nr_pages << PAGE_SHIFT, GFP_KERNEL);
|
||||||
|
if (ret)
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
|
if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA) {
|
||||||
|
ret = dma_map_sgtable(attach->dev, sg, direction, 0);
|
||||||
|
if (ret)
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amdxdna_ubuf_unmap(struct dma_buf_attachment *attach,
|
||||||
|
struct sg_table *sg,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
{
|
||||||
|
struct amdxdna_ubuf_priv *ubuf = attach->dmabuf->priv;
|
||||||
|
|
||||||
|
if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA)
|
||||||
|
dma_unmap_sgtable(attach->dev, sg, direction, 0);
|
||||||
|
|
||||||
|
sg_free_table(sg);
|
||||||
|
kfree(sg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amdxdna_ubuf_release(struct dma_buf *dbuf)
|
||||||
|
{
|
||||||
|
struct amdxdna_ubuf_priv *ubuf = dbuf->priv;
|
||||||
|
|
||||||
|
unpin_user_pages(ubuf->pages, ubuf->nr_pages);
|
||||||
|
kvfree(ubuf->pages);
|
||||||
|
atomic64_sub(ubuf->nr_pages, &ubuf->mm->pinned_vm);
|
||||||
|
mmdrop(ubuf->mm);
|
||||||
|
kfree(ubuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static vm_fault_t amdxdna_ubuf_vm_fault(struct vm_fault *vmf)
|
||||||
|
{
|
||||||
|
struct vm_area_struct *vma = vmf->vma;
|
||||||
|
struct amdxdna_ubuf_priv *ubuf;
|
||||||
|
unsigned long pfn;
|
||||||
|
pgoff_t pgoff;
|
||||||
|
|
||||||
|
ubuf = vma->vm_private_data;
|
||||||
|
pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
pfn = page_to_pfn(ubuf->pages[pgoff]);
|
||||||
|
return vmf_insert_pfn(vma, vmf->address, pfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct vm_operations_struct amdxdna_ubuf_vm_ops = {
|
||||||
|
.fault = amdxdna_ubuf_vm_fault,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int amdxdna_ubuf_mmap(struct dma_buf *dbuf, struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
struct amdxdna_ubuf_priv *ubuf = dbuf->priv;
|
||||||
|
|
||||||
|
vma->vm_ops = &amdxdna_ubuf_vm_ops;
|
||||||
|
vma->vm_private_data = ubuf;
|
||||||
|
vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int amdxdna_ubuf_vmap(struct dma_buf *dbuf, struct iosys_map *map)
|
||||||
|
{
|
||||||
|
struct amdxdna_ubuf_priv *ubuf = dbuf->priv;
|
||||||
|
void *kva;
|
||||||
|
|
||||||
|
kva = vmap(ubuf->pages, ubuf->nr_pages, VM_MAP, PAGE_KERNEL);
|
||||||
|
if (!kva)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
iosys_map_set_vaddr(map, kva);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amdxdna_ubuf_vunmap(struct dma_buf *dbuf, struct iosys_map *map)
|
||||||
|
{
|
||||||
|
vunmap(map->vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dma_buf_ops amdxdna_ubuf_dmabuf_ops = {
|
||||||
|
.map_dma_buf = amdxdna_ubuf_map,
|
||||||
|
.unmap_dma_buf = amdxdna_ubuf_unmap,
|
||||||
|
.release = amdxdna_ubuf_release,
|
||||||
|
.mmap = amdxdna_ubuf_mmap,
|
||||||
|
.vmap = amdxdna_ubuf_vmap,
|
||||||
|
.vunmap = amdxdna_ubuf_vunmap,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
|
||||||
|
enum amdxdna_ubuf_flag flags,
|
||||||
|
u32 num_entries, void __user *va_entries)
|
||||||
|
{
|
||||||
|
struct amdxdna_dev *xdna = to_xdna_dev(dev);
|
||||||
|
unsigned long lock_limit, new_pinned;
|
||||||
|
struct amdxdna_drm_va_entry *va_ent;
|
||||||
|
struct amdxdna_ubuf_priv *ubuf;
|
||||||
|
u32 npages, start = 0;
|
||||||
|
struct dma_buf *dbuf;
|
||||||
|
int i, ret;
|
||||||
|
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||||
|
|
||||||
|
if (!can_do_mlock())
|
||||||
|
return ERR_PTR(-EPERM);
|
||||||
|
|
||||||
|
ubuf = kzalloc(sizeof(*ubuf), GFP_KERNEL);
|
||||||
|
if (!ubuf)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
ubuf->flags = flags;
|
||||||
|
ubuf->mm = current->mm;
|
||||||
|
mmgrab(ubuf->mm);
|
||||||
|
|
||||||
|
va_ent = kvcalloc(num_entries, sizeof(*va_ent), GFP_KERNEL);
|
||||||
|
if (!va_ent) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto free_ubuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_from_user(va_ent, va_entries, sizeof(*va_ent) * num_entries)) {
|
||||||
|
XDNA_DBG(xdna, "Access va entries failed");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto free_ent;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, exp_info.size = 0; i < num_entries; i++) {
|
||||||
|
if (!IS_ALIGNED(va_ent[i].vaddr, PAGE_SIZE) ||
|
||||||
|
!IS_ALIGNED(va_ent[i].len, PAGE_SIZE)) {
|
||||||
|
XDNA_ERR(xdna, "Invalid address or len %llx, %llx",
|
||||||
|
va_ent[i].vaddr, va_ent[i].len);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto free_ent;
|
||||||
|
}
|
||||||
|
|
||||||
|
exp_info.size += va_ent[i].len;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubuf->nr_pages = exp_info.size >> PAGE_SHIFT;
|
||||||
|
lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
|
||||||
|
new_pinned = atomic64_add_return(ubuf->nr_pages, &ubuf->mm->pinned_vm);
|
||||||
|
if (new_pinned > lock_limit && !capable(CAP_IPC_LOCK)) {
|
||||||
|
XDNA_DBG(xdna, "New pin %ld, limit %ld, cap %d",
|
||||||
|
new_pinned, lock_limit, capable(CAP_IPC_LOCK));
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto sub_pin_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubuf->pages = kvmalloc_array(ubuf->nr_pages, sizeof(*ubuf->pages), GFP_KERNEL);
|
||||||
|
if (!ubuf->pages) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto sub_pin_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_entries; i++) {
|
||||||
|
npages = va_ent[i].len >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
ret = pin_user_pages_fast(va_ent[i].vaddr, npages,
|
||||||
|
FOLL_WRITE | FOLL_LONGTERM,
|
||||||
|
&ubuf->pages[start]);
|
||||||
|
if (ret < 0 || ret != npages) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
XDNA_ERR(xdna, "Failed to pin pages ret %d", ret);
|
||||||
|
goto destroy_pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
start += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
exp_info.ops = &amdxdna_ubuf_dmabuf_ops;
|
||||||
|
exp_info.priv = ubuf;
|
||||||
|
exp_info.flags = O_RDWR | O_CLOEXEC;
|
||||||
|
|
||||||
|
dbuf = dma_buf_export(&exp_info);
|
||||||
|
if (IS_ERR(dbuf)) {
|
||||||
|
ret = PTR_ERR(dbuf);
|
||||||
|
goto destroy_pages;
|
||||||
|
}
|
||||||
|
kvfree(va_ent);
|
||||||
|
|
||||||
|
return dbuf;
|
||||||
|
|
||||||
|
destroy_pages:
|
||||||
|
if (start)
|
||||||
|
unpin_user_pages(ubuf->pages, start);
|
||||||
|
kvfree(ubuf->pages);
|
||||||
|
sub_pin_cnt:
|
||||||
|
atomic64_sub(ubuf->nr_pages, &ubuf->mm->pinned_vm);
|
||||||
|
free_ent:
|
||||||
|
kvfree(va_ent);
|
||||||
|
free_ubuf:
|
||||||
|
mmdrop(ubuf->mm);
|
||||||
|
kfree(ubuf);
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025, Advanced Micro Devices, Inc.
|
||||||
|
*/
|
||||||
|
#ifndef _AMDXDNA_UBUF_H_
|
||||||
|
#define _AMDXDNA_UBUF_H_
|
||||||
|
|
||||||
|
#include <drm/drm_device.h>
|
||||||
|
#include <linux/dma-buf.h>
|
||||||
|
|
||||||
|
enum amdxdna_ubuf_flag {
|
||||||
|
AMDXDNA_UBUF_FLAG_MAP_DMA = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
|
||||||
|
enum amdxdna_ubuf_flag flags,
|
||||||
|
u32 num_entries, void __user *va_entries);
|
||||||
|
|
||||||
|
#endif /* _AMDXDNA_UBUF_H_ */
|
||||||
|
|
@ -27,3 +27,26 @@ config DRM_ACCEL_HABANALABS
|
||||||
|
|
||||||
To compile this driver as a module, choose M here: the
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called habanalabs.
|
module will be called habanalabs.
|
||||||
|
|
||||||
|
if DRM_ACCEL_HABANALABS
|
||||||
|
|
||||||
|
config HL_HLDIO
|
||||||
|
bool "Habanalabs NVMe Direct I/O (HLDIO)"
|
||||||
|
depends on PCI_P2PDMA
|
||||||
|
depends on BLOCK
|
||||||
|
help
|
||||||
|
Enable NVMe peer-to-peer direct I/O support for Habanalabs AI
|
||||||
|
accelerators.
|
||||||
|
|
||||||
|
This allows direct data transfers between NVMe storage devices
|
||||||
|
and Habanalabs accelerators without involving system memory,
|
||||||
|
using PCI peer-to-peer DMA capabilities.
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
- CONFIG_PCI_P2PDMA=y
|
||||||
|
- NVMe device and Habanalabs accelerator under same PCI root complex
|
||||||
|
- IOMMU disabled or in passthrough mode
|
||||||
|
- Hardware supporting PCI P2P DMA
|
||||||
|
|
||||||
|
If unsure, say N
|
||||||
|
endif # DRM_ACCEL_HABANALABS
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,8 @@ HL_COMMON_FILES := common/habanalabs_drv.o common/device.o common/context.o \
|
||||||
common/command_submission.o common/firmware_if.o \
|
common/command_submission.o common/firmware_if.o \
|
||||||
common/security.o common/state_dump.o \
|
common/security.o common/state_dump.o \
|
||||||
common/memory_mgr.o common/decoder.o
|
common/memory_mgr.o common/decoder.o
|
||||||
|
|
||||||
|
# Conditionally add HLDIO support
|
||||||
|
ifdef CONFIG_HL_HLDIO
|
||||||
|
HL_COMMON_FILES += common/hldio.o
|
||||||
|
endif
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "habanalabs.h"
|
#include "habanalabs.h"
|
||||||
|
#include "hldio.h"
|
||||||
#include "../include/hw_ip/mmu/mmu_general.h"
|
#include "../include/hw_ip/mmu/mmu_general.h"
|
||||||
|
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
|
@ -602,6 +603,198 @@ static int engines_show(struct seq_file *s, void *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_HL_HLDIO
|
||||||
|
/* DIO debugfs functions following the standard pattern */
|
||||||
|
static int dio_ssd2hl_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
struct hl_debugfs_entry *entry = s->private;
|
||||||
|
struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
|
||||||
|
struct hl_device *hdev = dev_entry->hdev;
|
||||||
|
|
||||||
|
if (!hdev->asic_prop.supports_nvme) {
|
||||||
|
seq_puts(s, "NVMe Direct I/O not supported\\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
seq_puts(s, "Usage: echo \"fd=N va=0xADDR off=N len=N\" > dio_ssd2hl\n");
|
||||||
|
seq_printf(s, "Last transfer: %zu bytes\\n", dev_entry->dio_stats.last_len_read);
|
||||||
|
seq_puts(s, "Note: All parameters must be page-aligned (4KB)\\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t dio_ssd2hl_write(struct file *file, const char __user *buf,
|
||||||
|
size_t count, loff_t *f_pos)
|
||||||
|
{
|
||||||
|
struct seq_file *s = file->private_data;
|
||||||
|
struct hl_debugfs_entry *entry = s->private;
|
||||||
|
struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
|
||||||
|
struct hl_device *hdev = dev_entry->hdev;
|
||||||
|
struct hl_ctx *ctx = hdev->kernel_ctx;
|
||||||
|
char kbuf[128];
|
||||||
|
u64 device_va = 0, off_bytes = 0, len_bytes = 0;
|
||||||
|
u32 fd = 0;
|
||||||
|
size_t len_read = 0;
|
||||||
|
int rc, parsed;
|
||||||
|
|
||||||
|
if (!hdev->asic_prop.supports_nvme)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (count >= sizeof(kbuf))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (copy_from_user(kbuf, buf, count))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
kbuf[count] = 0;
|
||||||
|
|
||||||
|
/* Parse: fd=N va=0xADDR off=N len=N */
|
||||||
|
parsed = sscanf(kbuf, "fd=%u va=0x%llx off=%llu len=%llu",
|
||||||
|
&fd, &device_va, &off_bytes, &len_bytes);
|
||||||
|
if (parsed != 4) {
|
||||||
|
dev_err(hdev->dev, "Invalid format. Expected: fd=N va=0xADDR off=N len=N\\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate file descriptor */
|
||||||
|
if (fd == 0) {
|
||||||
|
dev_err(hdev->dev, "Invalid file descriptor: %u\\n", fd);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate alignment requirements */
|
||||||
|
if (!IS_ALIGNED(device_va, PAGE_SIZE) ||
|
||||||
|
!IS_ALIGNED(off_bytes, PAGE_SIZE) ||
|
||||||
|
!IS_ALIGNED(len_bytes, PAGE_SIZE)) {
|
||||||
|
dev_err(hdev->dev,
|
||||||
|
"All parameters must be page-aligned (4KB)\\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate transfer size */
|
||||||
|
if (len_bytes == 0 || len_bytes > SZ_1G) {
|
||||||
|
dev_err(hdev->dev, "Invalid length: %llu (max 1GB)\\n",
|
||||||
|
len_bytes);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(hdev->dev, "DIO SSD2HL: fd=%u va=0x%llx off=%llu len=%llu\\n",
|
||||||
|
fd, device_va, off_bytes, len_bytes);
|
||||||
|
|
||||||
|
rc = hl_dio_ssd2hl(hdev, ctx, fd, device_va, off_bytes, len_bytes, &len_read);
|
||||||
|
if (rc < 0) {
|
||||||
|
dev_entry->dio_stats.failed_ops++;
|
||||||
|
dev_err(hdev->dev, "SSD2HL operation failed: %d\\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update statistics */
|
||||||
|
dev_entry->dio_stats.total_ops++;
|
||||||
|
dev_entry->dio_stats.successful_ops++;
|
||||||
|
dev_entry->dio_stats.bytes_transferred += len_read;
|
||||||
|
dev_entry->dio_stats.last_len_read = len_read;
|
||||||
|
|
||||||
|
dev_dbg(hdev->dev, "DIO SSD2HL completed: %zu bytes transferred\\n", len_read);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dio_hl2ssd_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
seq_puts(s, "HL2SSD (device-to-SSD) transfers not implemented\\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t dio_hl2ssd_write(struct file *file, const char __user *buf,
|
||||||
|
size_t count, loff_t *f_pos)
|
||||||
|
{
|
||||||
|
struct seq_file *s = file->private_data;
|
||||||
|
struct hl_debugfs_entry *entry = s->private;
|
||||||
|
struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
|
||||||
|
struct hl_device *hdev = dev_entry->hdev;
|
||||||
|
|
||||||
|
if (!hdev->asic_prop.supports_nvme)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
dev_dbg(hdev->dev, "HL2SSD operation not implemented\\n");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dio_stats_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
struct hl_debugfs_entry *entry = s->private;
|
||||||
|
struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
|
||||||
|
struct hl_device *hdev = dev_entry->hdev;
|
||||||
|
struct hl_dio_stats *stats = &dev_entry->dio_stats;
|
||||||
|
u64 avg_bytes_per_op = 0, success_rate = 0;
|
||||||
|
|
||||||
|
if (!hdev->asic_prop.supports_nvme) {
|
||||||
|
seq_puts(s, "NVMe Direct I/O not supported\\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats->successful_ops > 0)
|
||||||
|
avg_bytes_per_op = stats->bytes_transferred / stats->successful_ops;
|
||||||
|
|
||||||
|
if (stats->total_ops > 0)
|
||||||
|
success_rate = (stats->successful_ops * 100) / stats->total_ops;
|
||||||
|
|
||||||
|
seq_puts(s, "=== Habanalabs Direct I/O Statistics ===\\n");
|
||||||
|
seq_printf(s, "Total operations: %llu\\n", stats->total_ops);
|
||||||
|
seq_printf(s, "Successful ops: %llu\\n", stats->successful_ops);
|
||||||
|
seq_printf(s, "Failed ops: %llu\\n", stats->failed_ops);
|
||||||
|
seq_printf(s, "Success rate: %llu%%\\n", success_rate);
|
||||||
|
seq_printf(s, "Total bytes: %llu\\n", stats->bytes_transferred);
|
||||||
|
seq_printf(s, "Avg bytes per op: %llu\\n", avg_bytes_per_op);
|
||||||
|
seq_printf(s, "Last transfer: %zu bytes\\n", stats->last_len_read);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dio_reset_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
seq_puts(s, "Write '1' to reset DIO statistics\\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t dio_reset_write(struct file *file, const char __user *buf,
|
||||||
|
size_t count, loff_t *f_pos)
|
||||||
|
{
|
||||||
|
struct seq_file *s = file->private_data;
|
||||||
|
struct hl_debugfs_entry *entry = s->private;
|
||||||
|
struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
|
||||||
|
struct hl_device *hdev = dev_entry->hdev;
|
||||||
|
char kbuf[8];
|
||||||
|
unsigned long val;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!hdev->asic_prop.supports_nvme)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (count >= sizeof(kbuf))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (copy_from_user(kbuf, buf, count))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
kbuf[count] = 0;
|
||||||
|
|
||||||
|
rc = kstrtoul(kbuf, 0, &val);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (val == 1) {
|
||||||
|
memset(&dev_entry->dio_stats, 0, sizeof(dev_entry->dio_stats));
|
||||||
|
dev_dbg(hdev->dev, "DIO statistics reset\\n");
|
||||||
|
} else {
|
||||||
|
dev_err(hdev->dev, "Write '1' to reset statistics\\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static ssize_t hl_memory_scrub(struct file *f, const char __user *buf,
|
static ssize_t hl_memory_scrub(struct file *f, const char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
|
|
@ -788,6 +981,113 @@ static void hl_access_host_mem(struct hl_device *hdev, u64 addr, u64 *val,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_cfg_access_entry(struct hl_device *hdev,
|
||||||
|
struct hl_debugfs_cfg_access_entry *entry)
|
||||||
|
{
|
||||||
|
char *access_type = "";
|
||||||
|
struct tm tm;
|
||||||
|
|
||||||
|
switch (entry->debugfs_type) {
|
||||||
|
case DEBUGFS_READ32:
|
||||||
|
access_type = "READ32 from";
|
||||||
|
break;
|
||||||
|
case DEBUGFS_WRITE32:
|
||||||
|
access_type = "WRITE32 to";
|
||||||
|
break;
|
||||||
|
case DEBUGFS_READ64:
|
||||||
|
access_type = "READ64 from";
|
||||||
|
break;
|
||||||
|
case DEBUGFS_WRITE64:
|
||||||
|
access_type = "WRITE64 to";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(hdev->dev, "Invalid DEBUGFS access type (%u)\n", entry->debugfs_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
time64_to_tm(entry->seconds_since_epoch, 0, &tm);
|
||||||
|
dev_info(hdev->dev,
|
||||||
|
"%ld-%02d-%02d %02d:%02d:%02d (UTC): %s %#llx\n", tm.tm_year + 1900, tm.tm_mon + 1,
|
||||||
|
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, access_type, entry->addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hl_debugfs_cfg_access_history_dump(struct hl_device *hdev)
|
||||||
|
{
|
||||||
|
struct hl_debugfs_cfg_access *dbgfs = &hdev->debugfs_cfg_accesses;
|
||||||
|
u32 i, head, count = 0;
|
||||||
|
time64_t entry_time, now;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
now = ktime_get_real_seconds();
|
||||||
|
|
||||||
|
spin_lock_irqsave(&dbgfs->lock, flags);
|
||||||
|
head = dbgfs->head;
|
||||||
|
if (head == 0)
|
||||||
|
i = HL_DBGFS_CFG_ACCESS_HIST_LEN - 1;
|
||||||
|
else
|
||||||
|
i = head - 1;
|
||||||
|
|
||||||
|
/* Walk back until timeout or invalid entry */
|
||||||
|
while (dbgfs->cfg_access_list[i].valid) {
|
||||||
|
entry_time = dbgfs->cfg_access_list[i].seconds_since_epoch;
|
||||||
|
/* Stop when entry is older than timeout */
|
||||||
|
if (now - entry_time > HL_DBGFS_CFG_ACCESS_HIST_TIMEOUT_SEC)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* print single entry under lock */
|
||||||
|
{
|
||||||
|
struct hl_debugfs_cfg_access_entry entry = dbgfs->cfg_access_list[i];
|
||||||
|
/*
|
||||||
|
* We copy the entry out under lock and then print after
|
||||||
|
* releasing the lock to minimize time under lock.
|
||||||
|
*/
|
||||||
|
spin_unlock_irqrestore(&dbgfs->lock, flags);
|
||||||
|
dump_cfg_access_entry(hdev, &entry);
|
||||||
|
spin_lock_irqsave(&dbgfs->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mark consumed */
|
||||||
|
dbgfs->cfg_access_list[i].valid = false;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
i = HL_DBGFS_CFG_ACCESS_HIST_LEN - 1;
|
||||||
|
else
|
||||||
|
i--;
|
||||||
|
count++;
|
||||||
|
if (count >= HL_DBGFS_CFG_ACCESS_HIST_LEN)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&dbgfs->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_if_cfg_access_and_log(struct hl_device *hdev, u64 addr, size_t access_size,
|
||||||
|
enum debugfs_access_type access_type)
|
||||||
|
{
|
||||||
|
struct hl_debugfs_cfg_access *dbgfs_cfg_accesses = &hdev->debugfs_cfg_accesses;
|
||||||
|
struct pci_mem_region *mem_reg = &hdev->pci_mem_region[PCI_REGION_CFG];
|
||||||
|
struct hl_debugfs_cfg_access_entry *new_entry;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
/* Check if address is in config memory */
|
||||||
|
if (addr >= mem_reg->region_base &&
|
||||||
|
mem_reg->region_size >= access_size &&
|
||||||
|
addr <= mem_reg->region_base + mem_reg->region_size - access_size) {
|
||||||
|
|
||||||
|
spin_lock_irqsave(&dbgfs_cfg_accesses->lock, flags);
|
||||||
|
|
||||||
|
new_entry = &dbgfs_cfg_accesses->cfg_access_list[dbgfs_cfg_accesses->head];
|
||||||
|
new_entry->seconds_since_epoch = ktime_get_real_seconds();
|
||||||
|
new_entry->addr = addr;
|
||||||
|
new_entry->debugfs_type = access_type;
|
||||||
|
new_entry->valid = true;
|
||||||
|
dbgfs_cfg_accesses->head = (dbgfs_cfg_accesses->head + 1)
|
||||||
|
% HL_DBGFS_CFG_ACCESS_HIST_LEN;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&dbgfs_cfg_accesses->lock, flags);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int hl_access_mem(struct hl_device *hdev, u64 addr, u64 *val,
|
static int hl_access_mem(struct hl_device *hdev, u64 addr, u64 *val,
|
||||||
enum debugfs_access_type acc_type)
|
enum debugfs_access_type acc_type)
|
||||||
{
|
{
|
||||||
|
|
@ -805,6 +1105,7 @@ static int hl_access_mem(struct hl_device *hdev, u64 addr, u64 *val,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_if_cfg_access_and_log(hdev, addr, acc_size, acc_type);
|
||||||
rc = hl_access_dev_mem_by_region(hdev, addr, val, acc_type, &found);
|
rc = hl_access_dev_mem_by_region(hdev, addr, val, acc_type, &found);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dev_err(hdev->dev,
|
dev_err(hdev->dev,
|
||||||
|
|
@ -1525,6 +1826,13 @@ static const struct hl_info_list hl_debugfs_list[] = {
|
||||||
{"mmu", mmu_show, mmu_asid_va_write},
|
{"mmu", mmu_show, mmu_asid_va_write},
|
||||||
{"mmu_error", mmu_ack_error, mmu_ack_error_value_write},
|
{"mmu_error", mmu_ack_error, mmu_ack_error_value_write},
|
||||||
{"engines", engines_show, NULL},
|
{"engines", engines_show, NULL},
|
||||||
|
#ifdef CONFIG_HL_HLDIO
|
||||||
|
/* DIO entries - only created if NVMe is supported */
|
||||||
|
{"dio_ssd2hl", dio_ssd2hl_show, dio_ssd2hl_write},
|
||||||
|
{"dio_stats", dio_stats_show, NULL},
|
||||||
|
{"dio_reset", dio_reset_show, dio_reset_write},
|
||||||
|
{"dio_hl2ssd", dio_hl2ssd_show, dio_hl2ssd_write},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static int hl_debugfs_open(struct inode *inode, struct file *file)
|
static int hl_debugfs_open(struct inode *inode, struct file *file)
|
||||||
|
|
@ -1723,6 +2031,11 @@ static void add_files_to_device(struct hl_device *hdev, struct hl_dbg_device_ent
|
||||||
&hdev->asic_prop.server_type);
|
&hdev->asic_prop.server_type);
|
||||||
|
|
||||||
for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) {
|
for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) {
|
||||||
|
/* Skip DIO entries if NVMe is not supported */
|
||||||
|
if (strncmp(hl_debugfs_list[i].name, "dio_", 4) == 0 &&
|
||||||
|
!hdev->asic_prop.supports_nvme)
|
||||||
|
continue;
|
||||||
|
|
||||||
debugfs_create_file(hl_debugfs_list[i].name,
|
debugfs_create_file(hl_debugfs_list[i].name,
|
||||||
0644,
|
0644,
|
||||||
root,
|
root,
|
||||||
|
|
@ -1762,6 +2075,14 @@ int hl_debugfs_device_init(struct hl_device *hdev)
|
||||||
spin_lock_init(&dev_entry->userptr_spinlock);
|
spin_lock_init(&dev_entry->userptr_spinlock);
|
||||||
mutex_init(&dev_entry->ctx_mem_hash_mutex);
|
mutex_init(&dev_entry->ctx_mem_hash_mutex);
|
||||||
|
|
||||||
|
spin_lock_init(&hdev->debugfs_cfg_accesses.lock);
|
||||||
|
hdev->debugfs_cfg_accesses.head = 0; /* already zero by alloc but explicit init is fine */
|
||||||
|
|
||||||
|
#ifdef CONFIG_HL_HLDIO
|
||||||
|
/* Initialize DIO statistics */
|
||||||
|
memset(&dev_entry->dio_stats, 0, sizeof(dev_entry->dio_stats));
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1780,6 +2101,7 @@ void hl_debugfs_device_fini(struct hl_device *hdev)
|
||||||
vfree(entry->state_dump[i]);
|
vfree(entry->state_dump[i]);
|
||||||
|
|
||||||
kfree(entry->entry_arr);
|
kfree(entry->entry_arr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hl_debugfs_add_device(struct hl_device *hdev)
|
void hl_debugfs_add_device(struct hl_device *hdev)
|
||||||
|
|
@ -1792,6 +2114,7 @@ void hl_debugfs_add_device(struct hl_device *hdev)
|
||||||
|
|
||||||
if (!hdev->asic_prop.fw_security_enabled)
|
if (!hdev->asic_prop.fw_security_enabled)
|
||||||
add_secured_nodes(dev_entry, dev_entry->root);
|
add_secured_nodes(dev_entry, dev_entry->root);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hl_debugfs_add_file(struct hl_fpriv *hpriv)
|
void hl_debugfs_add_file(struct hl_fpriv *hpriv)
|
||||||
|
|
@ -1924,3 +2247,4 @@ void hl_debugfs_set_state_dump(struct hl_device *hdev, char *data,
|
||||||
|
|
||||||
up_write(&dev_entry->state_dump_sem);
|
up_write(&dev_entry->state_dump_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1630,6 +1630,11 @@ int hl_device_reset(struct hl_device *hdev, u32 flags)
|
||||||
from_watchdog_thread = !!(flags & HL_DRV_RESET_FROM_WD_THR);
|
from_watchdog_thread = !!(flags & HL_DRV_RESET_FROM_WD_THR);
|
||||||
reset_upon_device_release = hdev->reset_upon_device_release && from_dev_release;
|
reset_upon_device_release = hdev->reset_upon_device_release && from_dev_release;
|
||||||
|
|
||||||
|
if (hdev->cpld_shutdown) {
|
||||||
|
dev_err(hdev->dev, "Cannot reset device, cpld is shutdown! Device is NOT usable\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
if (!hard_reset && (hl_device_status(hdev) == HL_DEVICE_STATUS_MALFUNCTION)) {
|
if (!hard_reset && (hl_device_status(hdev) == HL_DEVICE_STATUS_MALFUNCTION)) {
|
||||||
dev_dbg(hdev->dev, "soft-reset isn't supported on a malfunctioning device\n");
|
dev_dbg(hdev->dev, "soft-reset isn't supported on a malfunctioning device\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2576,6 +2581,14 @@ void hl_device_fini(struct hl_device *hdev)
|
||||||
if (rc)
|
if (rc)
|
||||||
dev_err(hdev->dev, "hw_fini failed in device fini while removing device %d\n", rc);
|
dev_err(hdev->dev, "hw_fini failed in device fini while removing device %d\n", rc);
|
||||||
|
|
||||||
|
/* Reset the H/W (if it accessible). It will be in idle state after this returns */
|
||||||
|
if (!hdev->cpld_shutdown) {
|
||||||
|
rc = hdev->asic_funcs->hw_fini(hdev, true, false);
|
||||||
|
if (rc)
|
||||||
|
dev_err(hdev->dev,
|
||||||
|
"hw_fini failed in device fini while removing device %d\n", rc);
|
||||||
|
}
|
||||||
|
|
||||||
hdev->fw_loader.fw_comp_loaded = FW_TYPE_NONE;
|
hdev->fw_loader.fw_comp_loaded = FW_TYPE_NONE;
|
||||||
|
|
||||||
/* Release kernel context */
|
/* Release kernel context */
|
||||||
|
|
@ -2943,3 +2956,13 @@ void hl_handle_clk_change_event(struct hl_device *hdev, u16 event_type, u64 *eve
|
||||||
|
|
||||||
mutex_unlock(&clk_throttle->lock);
|
mutex_unlock(&clk_throttle->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hl_eq_cpld_shutdown_event_handle(struct hl_device *hdev, u16 event_id, u64 *event_mask)
|
||||||
|
{
|
||||||
|
hl_handle_critical_hw_err(hdev, event_id, event_mask);
|
||||||
|
*event_mask |= HL_NOTIFIER_EVENT_DEVICE_UNAVAILABLE;
|
||||||
|
|
||||||
|
/* Avoid any new accesses to the H/W */
|
||||||
|
hdev->disabled = true;
|
||||||
|
hdev->cpld_shutdown = true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,8 @@ struct hl_fpriv;
|
||||||
#define HL_COMMON_DEC_INTERRUPT_ID 0xFFE
|
#define HL_COMMON_DEC_INTERRUPT_ID 0xFFE
|
||||||
|
|
||||||
#define HL_STATE_DUMP_HIST_LEN 5
|
#define HL_STATE_DUMP_HIST_LEN 5
|
||||||
|
#define HL_DBGFS_CFG_ACCESS_HIST_LEN 20
|
||||||
|
#define HL_DBGFS_CFG_ACCESS_HIST_TIMEOUT_SEC 2 /* 2s */
|
||||||
|
|
||||||
/* Default value for device reset trigger , an invalid value */
|
/* Default value for device reset trigger , an invalid value */
|
||||||
#define HL_RESET_TRIGGER_DEFAULT 0xFF
|
#define HL_RESET_TRIGGER_DEFAULT 0xFF
|
||||||
|
|
@ -702,6 +704,7 @@ struct hl_hints_range {
|
||||||
* @supports_advanced_cpucp_rc: true if new cpucp opcodes are supported.
|
* @supports_advanced_cpucp_rc: true if new cpucp opcodes are supported.
|
||||||
* @supports_engine_modes: true if changing engines/engine_cores modes is supported.
|
* @supports_engine_modes: true if changing engines/engine_cores modes is supported.
|
||||||
* @support_dynamic_resereved_fw_size: true if we support dynamic reserved size for fw.
|
* @support_dynamic_resereved_fw_size: true if we support dynamic reserved size for fw.
|
||||||
|
* @supports_nvme: indicates whether the asic supports NVMe P2P DMA.
|
||||||
*/
|
*/
|
||||||
struct asic_fixed_properties {
|
struct asic_fixed_properties {
|
||||||
struct hw_queue_properties *hw_queues_props;
|
struct hw_queue_properties *hw_queues_props;
|
||||||
|
|
@ -822,6 +825,7 @@ struct asic_fixed_properties {
|
||||||
u8 supports_advanced_cpucp_rc;
|
u8 supports_advanced_cpucp_rc;
|
||||||
u8 supports_engine_modes;
|
u8 supports_engine_modes;
|
||||||
u8 support_dynamic_resereved_fw_size;
|
u8 support_dynamic_resereved_fw_size;
|
||||||
|
u8 supports_nvme;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -2274,6 +2278,9 @@ struct hl_vm {
|
||||||
u8 init_done;
|
u8 init_done;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_HL_HLDIO
|
||||||
|
#include "hldio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DEBUG, PROFILING STRUCTURE
|
* DEBUG, PROFILING STRUCTURE
|
||||||
|
|
@ -2344,7 +2351,6 @@ struct hl_fpriv {
|
||||||
struct mutex ctx_lock;
|
struct mutex ctx_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DebugFS
|
* DebugFS
|
||||||
*/
|
*/
|
||||||
|
|
@ -2372,6 +2378,7 @@ struct hl_debugfs_entry {
|
||||||
struct hl_dbg_device_entry *dev_entry;
|
struct hl_dbg_device_entry *dev_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct hl_dbg_device_entry - ASIC specific debugfs manager.
|
* struct hl_dbg_device_entry - ASIC specific debugfs manager.
|
||||||
* @root: root dentry.
|
* @root: root dentry.
|
||||||
|
|
@ -2403,6 +2410,7 @@ struct hl_debugfs_entry {
|
||||||
* @i2c_addr: generic u8 debugfs file for address value to use in i2c_data_read.
|
* @i2c_addr: generic u8 debugfs file for address value to use in i2c_data_read.
|
||||||
* @i2c_reg: generic u8 debugfs file for register value to use in i2c_data_read.
|
* @i2c_reg: generic u8 debugfs file for register value to use in i2c_data_read.
|
||||||
* @i2c_len: generic u8 debugfs file for length value to use in i2c_data_read.
|
* @i2c_len: generic u8 debugfs file for length value to use in i2c_data_read.
|
||||||
|
* @dio_stats: Direct I/O statistics
|
||||||
*/
|
*/
|
||||||
struct hl_dbg_device_entry {
|
struct hl_dbg_device_entry {
|
||||||
struct dentry *root;
|
struct dentry *root;
|
||||||
|
|
@ -2434,6 +2442,35 @@ struct hl_dbg_device_entry {
|
||||||
u8 i2c_addr;
|
u8 i2c_addr;
|
||||||
u8 i2c_reg;
|
u8 i2c_reg;
|
||||||
u8 i2c_len;
|
u8 i2c_len;
|
||||||
|
#ifdef CONFIG_HL_HLDIO
|
||||||
|
struct hl_dio_stats dio_stats;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct hl_debugfs_cfg_access_entry - single debugfs config access object, member of
|
||||||
|
* hl_debugfs_cfg_access.
|
||||||
|
* @seconds_since_epoch: seconds since January 1, 1970, used for time comparisons.
|
||||||
|
* @debugfs_type: the debugfs operation requested, can be READ32, WRITE32, READ64 or WRITE64.
|
||||||
|
* @addr: the requested address to access.
|
||||||
|
* @valid: if set, this entry has valid data for dumping at interrupt time.
|
||||||
|
*/
|
||||||
|
struct hl_debugfs_cfg_access_entry {
|
||||||
|
ktime_t seconds_since_epoch;
|
||||||
|
enum debugfs_access_type debugfs_type;
|
||||||
|
u64 addr;
|
||||||
|
bool valid;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct hl_debugfs_cfg_access - saves debugfs config region access requests history.
|
||||||
|
* @cfg_access_list: list of objects describing config region access requests.
|
||||||
|
* @head: next valid index to add new entry to in cfg_access_list.
|
||||||
|
*/
|
||||||
|
struct hl_debugfs_cfg_access {
|
||||||
|
struct hl_debugfs_cfg_access_entry cfg_access_list[HL_DBGFS_CFG_ACCESS_HIST_LEN];
|
||||||
|
u32 head;
|
||||||
|
spinlock_t lock; /* protects head and entries */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -3281,6 +3318,7 @@ struct eq_heartbeat_debug_info {
|
||||||
* @hl_chip_info: ASIC's sensors information.
|
* @hl_chip_info: ASIC's sensors information.
|
||||||
* @device_status_description: device status description.
|
* @device_status_description: device status description.
|
||||||
* @hl_debugfs: device's debugfs manager.
|
* @hl_debugfs: device's debugfs manager.
|
||||||
|
* @debugfs_cfg_accesses: list of last debugfs config region accesses.
|
||||||
* @cb_pool: list of pre allocated CBs.
|
* @cb_pool: list of pre allocated CBs.
|
||||||
* @cb_pool_lock: protects the CB pool.
|
* @cb_pool_lock: protects the CB pool.
|
||||||
* @internal_cb_pool_virt_addr: internal command buffer pool virtual address.
|
* @internal_cb_pool_virt_addr: internal command buffer pool virtual address.
|
||||||
|
|
@ -3305,6 +3343,7 @@ struct eq_heartbeat_debug_info {
|
||||||
* @captured_err_info: holds information about errors.
|
* @captured_err_info: holds information about errors.
|
||||||
* @reset_info: holds current device reset information.
|
* @reset_info: holds current device reset information.
|
||||||
* @heartbeat_debug_info: counters used to debug heartbeat failures.
|
* @heartbeat_debug_info: counters used to debug heartbeat failures.
|
||||||
|
* @hldio: describes habanalabs direct storage interaction interface.
|
||||||
* @irq_affinity_mask: mask of available CPU cores for user and decoder interrupt handling.
|
* @irq_affinity_mask: mask of available CPU cores for user and decoder interrupt handling.
|
||||||
* @stream_master_qid_arr: pointer to array with QIDs of master streams.
|
* @stream_master_qid_arr: pointer to array with QIDs of master streams.
|
||||||
* @fw_inner_major_ver: the major of current loaded preboot inner version.
|
* @fw_inner_major_ver: the major of current loaded preboot inner version.
|
||||||
|
|
@ -3357,6 +3396,7 @@ struct eq_heartbeat_debug_info {
|
||||||
* addresses.
|
* addresses.
|
||||||
* @is_in_dram_scrub: true if dram scrub operation is on going.
|
* @is_in_dram_scrub: true if dram scrub operation is on going.
|
||||||
* @disabled: is device disabled.
|
* @disabled: is device disabled.
|
||||||
|
* @cpld_shutdown: is cpld shutdown.
|
||||||
* @late_init_done: is late init stage was done during initialization.
|
* @late_init_done: is late init stage was done during initialization.
|
||||||
* @hwmon_initialized: is H/W monitor sensors was initialized.
|
* @hwmon_initialized: is H/W monitor sensors was initialized.
|
||||||
* @reset_on_lockup: true if a reset should be done in case of stuck CS, false
|
* @reset_on_lockup: true if a reset should be done in case of stuck CS, false
|
||||||
|
|
@ -3461,6 +3501,7 @@ struct hl_device {
|
||||||
struct hwmon_chip_info *hl_chip_info;
|
struct hwmon_chip_info *hl_chip_info;
|
||||||
|
|
||||||
struct hl_dbg_device_entry hl_debugfs;
|
struct hl_dbg_device_entry hl_debugfs;
|
||||||
|
struct hl_debugfs_cfg_access debugfs_cfg_accesses;
|
||||||
|
|
||||||
struct list_head cb_pool;
|
struct list_head cb_pool;
|
||||||
spinlock_t cb_pool_lock;
|
spinlock_t cb_pool_lock;
|
||||||
|
|
@ -3496,7 +3537,9 @@ struct hl_device {
|
||||||
struct hl_reset_info reset_info;
|
struct hl_reset_info reset_info;
|
||||||
|
|
||||||
struct eq_heartbeat_debug_info heartbeat_debug_info;
|
struct eq_heartbeat_debug_info heartbeat_debug_info;
|
||||||
|
#ifdef CONFIG_HL_HLDIO
|
||||||
|
struct hl_dio hldio;
|
||||||
|
#endif
|
||||||
cpumask_t irq_affinity_mask;
|
cpumask_t irq_affinity_mask;
|
||||||
|
|
||||||
u32 *stream_master_qid_arr;
|
u32 *stream_master_qid_arr;
|
||||||
|
|
@ -3532,6 +3575,7 @@ struct hl_device {
|
||||||
u16 cpu_pci_msb_addr;
|
u16 cpu_pci_msb_addr;
|
||||||
u8 is_in_dram_scrub;
|
u8 is_in_dram_scrub;
|
||||||
u8 disabled;
|
u8 disabled;
|
||||||
|
u8 cpld_shutdown;
|
||||||
u8 late_init_done;
|
u8 late_init_done;
|
||||||
u8 hwmon_initialized;
|
u8 hwmon_initialized;
|
||||||
u8 reset_on_lockup;
|
u8 reset_on_lockup;
|
||||||
|
|
@ -4089,6 +4133,7 @@ void hl_init_cpu_for_irq(struct hl_device *hdev);
|
||||||
void hl_set_irq_affinity(struct hl_device *hdev, int irq);
|
void hl_set_irq_affinity(struct hl_device *hdev, int irq);
|
||||||
void hl_eq_heartbeat_event_handle(struct hl_device *hdev);
|
void hl_eq_heartbeat_event_handle(struct hl_device *hdev);
|
||||||
void hl_handle_clk_change_event(struct hl_device *hdev, u16 event_type, u64 *event_mask);
|
void hl_handle_clk_change_event(struct hl_device *hdev, u16 event_type, u64 *event_mask);
|
||||||
|
void hl_eq_cpld_shutdown_event_handle(struct hl_device *hdev, u16 event_id, u64 *event_mask);
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|
||||||
|
|
@ -4110,6 +4155,7 @@ void hl_debugfs_add_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx);
|
||||||
void hl_debugfs_remove_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx);
|
void hl_debugfs_remove_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx);
|
||||||
void hl_debugfs_set_state_dump(struct hl_device *hdev, char *data,
|
void hl_debugfs_set_state_dump(struct hl_device *hdev, char *data,
|
||||||
unsigned long length);
|
unsigned long length);
|
||||||
|
void hl_debugfs_cfg_access_history_dump(struct hl_device *hdev);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
@ -4185,6 +4231,10 @@ static inline void hl_debugfs_set_state_dump(struct hl_device *hdev,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void hl_debugfs_cfg_access_history_dump(struct hl_device *hdev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Security */
|
/* Security */
|
||||||
|
|
|
||||||
|
|
@ -961,6 +961,12 @@ static int send_fw_generic_request(struct hl_device *hdev, struct hl_info_args *
|
||||||
case HL_PASSTHROUGH_VERSIONS:
|
case HL_PASSTHROUGH_VERSIONS:
|
||||||
need_input_buff = false;
|
need_input_buff = false;
|
||||||
break;
|
break;
|
||||||
|
case HL_GET_ERR_COUNTERS_CMD:
|
||||||
|
need_input_buff = true;
|
||||||
|
break;
|
||||||
|
case HL_GET_P_STATE:
|
||||||
|
need_input_buff = false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,437 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2024 HabanaLabs, Ltd.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "habanalabs.h"
|
||||||
|
#include "hldio.h"
|
||||||
|
#include <generated/uapi/linux/version.h>
|
||||||
|
#include <linux/pci-p2pdma.h>
|
||||||
|
#include <linux/blkdev.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NVMe Direct I/O implementation for habanalabs driver
|
||||||
|
*
|
||||||
|
* ASSUMPTIONS
|
||||||
|
* ===========
|
||||||
|
* 1. No IOMMU (well, technically it can work with IOMMU, but it is *almost useless).
|
||||||
|
* 2. Only READ operations (can extend in the future).
|
||||||
|
* 3. No sparse files (can overcome this in the future).
|
||||||
|
* 4. Kernel version >= 6.9
|
||||||
|
* 5. Requiring page alignment is OK (I don't see a solution to this one right,
|
||||||
|
* now, how do we read partial pages?)
|
||||||
|
* 6. Kernel compiled with CONFIG_PCI_P2PDMA. This requires a CUSTOM kernel.
|
||||||
|
* Theoretically I have a slight idea on how this could be solvable, but it
|
||||||
|
* is probably inacceptable for the upstream. Also may not work in the end.
|
||||||
|
* 7. Either make sure our cards and disks are under the same PCI bridge, or
|
||||||
|
* compile a custom kernel to hack around this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IO_STABILIZE_TIMEOUT 10000000 /* 10 seconds in microseconds */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This struct contains all the useful data I could milk out of the file handle
|
||||||
|
* provided by the user.
|
||||||
|
* @TODO: right now it is retrieved on each IO, but can be done once with some
|
||||||
|
* dedicated IOCTL, call it for example HL_REGISTER_HANDLE.
|
||||||
|
*/
|
||||||
|
struct hl_dio_fd {
|
||||||
|
/* Back pointer in case we need it in async completion */
|
||||||
|
struct hl_ctx *ctx;
|
||||||
|
/* Associated fd struct */
|
||||||
|
struct file *filp;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a single IO descriptor
|
||||||
|
*/
|
||||||
|
struct hl_direct_io {
|
||||||
|
struct hl_dio_fd f;
|
||||||
|
struct kiocb kio;
|
||||||
|
struct bio_vec *bv;
|
||||||
|
struct iov_iter iter;
|
||||||
|
u64 device_va;
|
||||||
|
u64 off_bytes;
|
||||||
|
u64 len_bytes;
|
||||||
|
u32 type;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool hl_device_supports_nvme(struct hl_device *hdev)
|
||||||
|
{
|
||||||
|
return hdev->asic_prop.supports_nvme;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hl_dio_fd_register(struct hl_ctx *ctx, int fd, struct hl_dio_fd *f)
|
||||||
|
{
|
||||||
|
struct hl_device *hdev = ctx->hdev;
|
||||||
|
struct block_device *bd;
|
||||||
|
struct super_block *sb;
|
||||||
|
struct inode *inode;
|
||||||
|
struct gendisk *gd;
|
||||||
|
struct device *disk_dev;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
f->filp = fget(fd);
|
||||||
|
if (!f->filp) {
|
||||||
|
rc = -ENOENT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(f->filp->f_flags & O_DIRECT)) {
|
||||||
|
dev_err(hdev->dev, "file is not in the direct mode\n");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto fput;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!f->filp->f_op->read_iter) {
|
||||||
|
dev_err(hdev->dev, "read iter is not supported, need to fall back to legacy\n");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto fput;
|
||||||
|
}
|
||||||
|
|
||||||
|
inode = file_inode(f->filp);
|
||||||
|
sb = inode->i_sb;
|
||||||
|
bd = sb->s_bdev;
|
||||||
|
gd = bd->bd_disk;
|
||||||
|
|
||||||
|
if (inode->i_blocks << sb->s_blocksize_bits < i_size_read(inode)) {
|
||||||
|
dev_err(hdev->dev, "sparse files are not currently supported\n");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto fput;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bd || !gd) {
|
||||||
|
dev_err(hdev->dev, "invalid block device\n");
|
||||||
|
rc = -ENODEV;
|
||||||
|
goto fput;
|
||||||
|
}
|
||||||
|
/* Get the underlying device from the block device */
|
||||||
|
disk_dev = disk_to_dev(gd);
|
||||||
|
if (!dma_pci_p2pdma_supported(disk_dev)) {
|
||||||
|
dev_err(hdev->dev, "device does not support PCI P2P DMA\n");
|
||||||
|
rc = -EOPNOTSUPP;
|
||||||
|
goto fput;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @TODO: Maybe we need additional checks here
|
||||||
|
*/
|
||||||
|
|
||||||
|
f->ctx = ctx;
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
|
goto out;
|
||||||
|
fput:
|
||||||
|
fput(f->filp);
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hl_dio_fd_unregister(struct hl_dio_fd *f)
|
||||||
|
{
|
||||||
|
fput(f->filp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long hl_dio_count_io(struct hl_device *hdev)
|
||||||
|
{
|
||||||
|
s64 sum = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for_each_possible_cpu(i)
|
||||||
|
sum += per_cpu(*hdev->hldio.inflight_ios, i);
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hl_dio_get_iopath(struct hl_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct hl_device *hdev = ctx->hdev;
|
||||||
|
|
||||||
|
if (hdev->hldio.io_enabled) {
|
||||||
|
this_cpu_inc(*hdev->hldio.inflight_ios);
|
||||||
|
|
||||||
|
/* Avoid race conditions */
|
||||||
|
if (!hdev->hldio.io_enabled) {
|
||||||
|
this_cpu_dec(*hdev->hldio.inflight_ios);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hl_ctx_get(ctx);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hl_dio_put_iopath(struct hl_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct hl_device *hdev = ctx->hdev;
|
||||||
|
|
||||||
|
hl_ctx_put(ctx);
|
||||||
|
this_cpu_dec(*hdev->hldio.inflight_ios);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hl_dio_set_io_enabled(struct hl_device *hdev, bool enabled)
|
||||||
|
{
|
||||||
|
hdev->hldio.io_enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hl_dio_validate_io(struct hl_device *hdev, struct hl_direct_io *io)
|
||||||
|
{
|
||||||
|
if ((u64)io->device_va & ~PAGE_MASK) {
|
||||||
|
dev_dbg(hdev->dev, "device address must be 4K aligned\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (io->len_bytes & ~PAGE_MASK) {
|
||||||
|
dev_dbg(hdev->dev, "IO length must be 4K aligned\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (io->off_bytes & ~PAGE_MASK) {
|
||||||
|
dev_dbg(hdev->dev, "IO offset must be 4K aligned\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct page *hl_dio_va2page(struct hl_device *hdev, struct hl_ctx *ctx, u64 device_va)
|
||||||
|
{
|
||||||
|
struct hl_dio *hldio = &hdev->hldio;
|
||||||
|
u64 device_pa;
|
||||||
|
int rc, i;
|
||||||
|
|
||||||
|
rc = hl_mmu_va_to_pa(ctx, device_va, &device_pa);
|
||||||
|
if (rc) {
|
||||||
|
dev_err(hdev->dev, "device virtual address translation error: %#llx (%d)",
|
||||||
|
device_va, rc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0 ; i < hldio->np2prs ; ++i) {
|
||||||
|
if (device_pa >= hldio->p2prs[i].device_pa &&
|
||||||
|
device_pa < hldio->p2prs[i].device_pa + hldio->p2prs[i].size)
|
||||||
|
return hldio->p2prs[i].p2ppages[(device_pa - hldio->p2prs[i].device_pa) >>
|
||||||
|
PAGE_SHIFT];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t hl_direct_io(struct hl_device *hdev, struct hl_direct_io *io)
|
||||||
|
{
|
||||||
|
u64 npages, device_va;
|
||||||
|
ssize_t rc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!hl_dio_validate_io(hdev, io))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!hl_dio_get_iopath(io->f.ctx)) {
|
||||||
|
dev_info(hdev->dev, "can't schedule a new IO, IO is disabled\n");
|
||||||
|
return -ESHUTDOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_sync_kiocb(&io->kio, io->f.filp);
|
||||||
|
io->kio.ki_pos = io->off_bytes;
|
||||||
|
|
||||||
|
npages = (io->len_bytes >> PAGE_SHIFT);
|
||||||
|
|
||||||
|
/* @TODO: this can be implemented smarter, vmalloc in iopath is not
|
||||||
|
* ideal. Maybe some variation of genpool. Number of pages may differ
|
||||||
|
* greatly, so maybe even use pools of different sizes and chose the
|
||||||
|
* closest one.
|
||||||
|
*/
|
||||||
|
io->bv = vzalloc(npages * sizeof(struct bio_vec));
|
||||||
|
if (!io->bv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (i = 0, device_va = io->device_va; i < npages ; ++i, device_va += PAGE_SIZE) {
|
||||||
|
io->bv[i].bv_page = hl_dio_va2page(hdev, io->f.ctx, device_va);
|
||||||
|
if (!io->bv[i].bv_page) {
|
||||||
|
dev_err(hdev->dev, "error getting page struct for device va %#llx",
|
||||||
|
device_va);
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
io->bv[i].bv_offset = 0;
|
||||||
|
io->bv[i].bv_len = PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
iov_iter_bvec(&io->iter, io->type, io->bv, 1, io->len_bytes);
|
||||||
|
if (io->f.filp->f_op && io->f.filp->f_op->read_iter)
|
||||||
|
rc = io->f.filp->f_op->read_iter(&io->kio, &io->iter);
|
||||||
|
else
|
||||||
|
rc = -EINVAL;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
vfree(io->bv);
|
||||||
|
hl_dio_put_iopath(io->f.ctx);
|
||||||
|
|
||||||
|
dev_dbg(hdev->dev, "IO ended with %ld\n", rc);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @TODO: This function can be used as a callback for io completion under
|
||||||
|
* kio->ki_complete in order to implement async IO.
|
||||||
|
* Note that on more recent kernels there is no ret2.
|
||||||
|
*/
|
||||||
|
__maybe_unused static void hl_direct_io_complete(struct kiocb *kio, long ret, long ret2)
|
||||||
|
{
|
||||||
|
struct hl_direct_io *io = container_of(kio, struct hl_direct_io, kio);
|
||||||
|
|
||||||
|
dev_dbg(io->f.ctx->hdev->dev, "IO completed with %ld\n", ret);
|
||||||
|
|
||||||
|
/* Do something to copy result to user / notify completion */
|
||||||
|
|
||||||
|
hl_dio_put_iopath(io->f.ctx);
|
||||||
|
|
||||||
|
hl_dio_fd_unregister(&io->f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DMA disk to ASIC, wait for results. Must be invoked from the user context
|
||||||
|
*/
|
||||||
|
int hl_dio_ssd2hl(struct hl_device *hdev, struct hl_ctx *ctx, int fd,
|
||||||
|
u64 device_va, off_t off_bytes, size_t len_bytes,
|
||||||
|
size_t *len_read)
|
||||||
|
{
|
||||||
|
struct hl_direct_io *io;
|
||||||
|
ssize_t rc;
|
||||||
|
|
||||||
|
dev_dbg(hdev->dev, "SSD2HL fd=%d va=%#llx len=%#lx\n", fd, device_va, len_bytes);
|
||||||
|
|
||||||
|
io = kzalloc(sizeof(*io), GFP_KERNEL);
|
||||||
|
if (!io) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
*io = (struct hl_direct_io){
|
||||||
|
.device_va = device_va,
|
||||||
|
.len_bytes = len_bytes,
|
||||||
|
.off_bytes = off_bytes,
|
||||||
|
.type = READ,
|
||||||
|
};
|
||||||
|
|
||||||
|
rc = hl_dio_fd_register(ctx, fd, &io->f);
|
||||||
|
if (rc)
|
||||||
|
goto kfree_io;
|
||||||
|
|
||||||
|
rc = hl_direct_io(hdev, io);
|
||||||
|
if (rc >= 0) {
|
||||||
|
*len_read = rc;
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This shall be called only in the case of a sync IO */
|
||||||
|
hl_dio_fd_unregister(&io->f);
|
||||||
|
kfree_io:
|
||||||
|
kfree(io);
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hl_p2p_region_fini(struct hl_device *hdev, struct hl_p2p_region *p2pr)
|
||||||
|
{
|
||||||
|
if (p2pr->p2ppages) {
|
||||||
|
vfree(p2pr->p2ppages);
|
||||||
|
p2pr->p2ppages = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p2pr->p2pmem) {
|
||||||
|
dev_dbg(hdev->dev, "freeing P2P mem from %p, size=%#llx\n",
|
||||||
|
p2pr->p2pmem, p2pr->size);
|
||||||
|
pci_free_p2pmem(hdev->pdev, p2pr->p2pmem, p2pr->size);
|
||||||
|
p2pr->p2pmem = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hl_p2p_region_fini_all(struct hl_device *hdev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0 ; i < hdev->hldio.np2prs ; ++i)
|
||||||
|
hl_p2p_region_fini(hdev, &hdev->hldio.p2prs[i]);
|
||||||
|
|
||||||
|
kvfree(hdev->hldio.p2prs);
|
||||||
|
hdev->hldio.p2prs = NULL;
|
||||||
|
hdev->hldio.np2prs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hl_p2p_region_init(struct hl_device *hdev, struct hl_p2p_region *p2pr)
|
||||||
|
{
|
||||||
|
void *addr;
|
||||||
|
int rc, i;
|
||||||
|
|
||||||
|
/* Start by publishing our p2p memory */
|
||||||
|
rc = pci_p2pdma_add_resource(hdev->pdev, p2pr->bar, p2pr->size, p2pr->bar_offset);
|
||||||
|
if (rc) {
|
||||||
|
dev_err(hdev->dev, "error adding p2p resource: %d\n", rc);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alloc all p2p mem */
|
||||||
|
p2pr->p2pmem = pci_alloc_p2pmem(hdev->pdev, p2pr->size);
|
||||||
|
if (!p2pr->p2pmem) {
|
||||||
|
dev_err(hdev->dev, "error allocating p2p memory\n");
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
p2pr->p2ppages = vmalloc((p2pr->size >> PAGE_SHIFT) * sizeof(struct page *));
|
||||||
|
if (!p2pr->p2ppages) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, addr = p2pr->p2pmem ; i < (p2pr->size >> PAGE_SHIFT) ; ++i, addr += PAGE_SIZE) {
|
||||||
|
p2pr->p2ppages[i] = virt_to_page(addr);
|
||||||
|
if (!p2pr->p2ppages[i]) {
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
hl_p2p_region_fini(hdev, p2pr);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hl_dio_start(struct hl_device *hdev)
|
||||||
|
{
|
||||||
|
dev_dbg(hdev->dev, "initializing HLDIO\n");
|
||||||
|
|
||||||
|
/* Initialize the IO counter and enable IO */
|
||||||
|
hdev->hldio.inflight_ios = alloc_percpu(s64);
|
||||||
|
if (!hdev->hldio.inflight_ios)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
hl_dio_set_io_enabled(hdev, true);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hl_dio_stop(struct hl_device *hdev)
|
||||||
|
{
|
||||||
|
dev_dbg(hdev->dev, "deinitializing HLDIO\n");
|
||||||
|
|
||||||
|
if (hdev->hldio.io_enabled) {
|
||||||
|
/* Wait for all the IO to finish */
|
||||||
|
hl_dio_set_io_enabled(hdev, false);
|
||||||
|
hl_poll_timeout_condition(hdev, !hl_dio_count_io(hdev), 1000, IO_STABILIZE_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdev->hldio.inflight_ios) {
|
||||||
|
free_percpu(hdev->hldio.inflight_ios);
|
||||||
|
hdev->hldio.inflight_ios = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* hldio.h - NVMe Direct I/O (HLDIO) infrastructure for Habana Labs Driver
|
||||||
|
*
|
||||||
|
* This feature requires specific hardware setup and must not be built
|
||||||
|
* under COMPILE_TEST.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HL_HLDIO_H__
|
||||||
|
#define __HL_HLDIO_H__
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
#include <linux/ktime.h> /* ktime functions */
|
||||||
|
#include <linux/delay.h> /* usleep_range */
|
||||||
|
#include <linux/kernel.h> /* might_sleep_if */
|
||||||
|
#include <linux/errno.h> /* error codes */
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
struct hl_device;
|
||||||
|
struct file;
|
||||||
|
|
||||||
|
/* Enable only if Kconfig selected */
|
||||||
|
#ifdef CONFIG_HL_HLDIO
|
||||||
|
/**
|
||||||
|
* struct hl_p2p_region - describes a single P2P memory region
|
||||||
|
* @p2ppages: array of page structs for the P2P memory
|
||||||
|
* @p2pmem: virtual address of the P2P memory region
|
||||||
|
* @device_pa: physical address on the device
|
||||||
|
* @bar_offset: offset within the BAR
|
||||||
|
* @size: size of the region in bytes
|
||||||
|
* @bar: BAR number containing this region
|
||||||
|
*/
|
||||||
|
struct hl_p2p_region {
|
||||||
|
struct page **p2ppages;
|
||||||
|
void *p2pmem;
|
||||||
|
u64 device_pa;
|
||||||
|
u64 bar_offset;
|
||||||
|
u64 size;
|
||||||
|
int bar;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct hl_dio_stats - Direct I/O statistics
|
||||||
|
* @total_ops: total number of operations attempted
|
||||||
|
* @successful_ops: number of successful operations
|
||||||
|
* @failed_ops: number of failed operations
|
||||||
|
* @bytes_transferred: total bytes successfully transferred
|
||||||
|
* @last_len_read: length of the last read operation
|
||||||
|
*/
|
||||||
|
struct hl_dio_stats {
|
||||||
|
u64 total_ops;
|
||||||
|
u64 successful_ops;
|
||||||
|
u64 failed_ops;
|
||||||
|
u64 bytes_transferred;
|
||||||
|
size_t last_len_read;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct hl_dio - describes habanalabs direct storage interaction interface
|
||||||
|
* @p2prs: array of p2p regions
|
||||||
|
* @inflight_ios: percpu counter for inflight ios
|
||||||
|
* @np2prs: number of elements in p2prs
|
||||||
|
* @io_enabled: 1 if io is enabled 0 otherwise
|
||||||
|
*/
|
||||||
|
struct hl_dio {
|
||||||
|
struct hl_p2p_region *p2prs;
|
||||||
|
s64 __percpu *inflight_ios;
|
||||||
|
u8 np2prs;
|
||||||
|
u8 io_enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
int hl_dio_ssd2hl(struct hl_device *hdev, struct hl_ctx *ctx, int fd,
|
||||||
|
u64 device_va, off_t off_bytes, size_t len_bytes,
|
||||||
|
size_t *len_read);
|
||||||
|
void hl_p2p_region_fini_all(struct hl_device *hdev);
|
||||||
|
int hl_p2p_region_init(struct hl_device *hdev, struct hl_p2p_region *p2pr);
|
||||||
|
int hl_dio_start(struct hl_device *hdev);
|
||||||
|
void hl_dio_stop(struct hl_device *hdev);
|
||||||
|
|
||||||
|
/* Init/teardown */
|
||||||
|
int hl_hldio_init(struct hl_device *hdev);
|
||||||
|
void hl_hldio_fini(struct hl_device *hdev);
|
||||||
|
|
||||||
|
/* File operations */
|
||||||
|
long hl_hldio_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
|
||||||
|
|
||||||
|
/* DebugFS hooks */
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
void hl_hldio_debugfs_init(struct hl_device *hdev);
|
||||||
|
void hl_hldio_debugfs_fini(struct hl_device *hdev);
|
||||||
|
#else
|
||||||
|
static inline void hl_hldio_debugfs_init(struct hl_device *hdev) { }
|
||||||
|
static inline void hl_hldio_debugfs_fini(struct hl_device *hdev) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* !CONFIG_HL_HLDIO */
|
||||||
|
|
||||||
|
struct hl_p2p_region;
|
||||||
|
/* Stubs when HLDIO is disabled */
|
||||||
|
static inline int hl_dio_ssd2hl(struct hl_device *hdev, struct hl_ctx *ctx, int fd,
|
||||||
|
u64 device_va, off_t off_bytes, size_t len_bytes,
|
||||||
|
size_t *len_read)
|
||||||
|
{ return -EOPNOTSUPP; }
|
||||||
|
static inline void hl_p2p_region_fini_all(struct hl_device *hdev) {}
|
||||||
|
static inline int hl_p2p_region_init(struct hl_device *hdev, struct hl_p2p_region *p2pr)
|
||||||
|
{ return -EOPNOTSUPP; }
|
||||||
|
static inline int hl_dio_start(struct hl_device *hdev) { return -EOPNOTSUPP; }
|
||||||
|
static inline void hl_dio_stop(struct hl_device *hdev) {}
|
||||||
|
|
||||||
|
static inline int hl_hldio_init(struct hl_device *hdev) { return 0; }
|
||||||
|
static inline void hl_hldio_fini(struct hl_device *hdev) { }
|
||||||
|
static inline long hl_hldio_ioctl(struct file *f, unsigned int c,
|
||||||
|
unsigned long a)
|
||||||
|
{ return -ENOTTY; }
|
||||||
|
static inline void hl_hldio_debugfs_init(struct hl_device *hdev) { }
|
||||||
|
static inline void hl_hldio_debugfs_fini(struct hl_device *hdev) { }
|
||||||
|
|
||||||
|
#endif /* CONFIG_HL_HLDIO */
|
||||||
|
|
||||||
|
/* Simplified polling macro for HLDIO (no simulator support) */
|
||||||
|
#define hl_poll_timeout_condition(hdev, cond, sleep_us, timeout_us) \
|
||||||
|
({ \
|
||||||
|
ktime_t __timeout = ktime_add_us(ktime_get(), timeout_us); \
|
||||||
|
might_sleep_if(sleep_us); \
|
||||||
|
(void)(hdev); /* keep signature consistent, hdev unused */ \
|
||||||
|
for (;;) { \
|
||||||
|
mb(); /* ensure ordering of memory operations */ \
|
||||||
|
if (cond) \
|
||||||
|
break; \
|
||||||
|
if (timeout_us && ktime_compare(ktime_get(), __timeout) > 0) \
|
||||||
|
break; \
|
||||||
|
if (sleep_us) \
|
||||||
|
usleep_range((sleep_us >> 2) + 1, sleep_us); \
|
||||||
|
} \
|
||||||
|
(cond) ? 0 : -ETIMEDOUT; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#ifdef CONFIG_HL_HLDIO
|
||||||
|
bool hl_device_supports_nvme(struct hl_device *hdev);
|
||||||
|
#else
|
||||||
|
static inline bool hl_device_supports_nvme(struct hl_device *hdev) { return false; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __HL_HLDIO_H__ */
|
||||||
|
|
@ -1837,7 +1837,12 @@ static void hl_release_dmabuf(struct dma_buf *dmabuf)
|
||||||
atomic_dec(&ctx->hdev->dmabuf_export_cnt);
|
atomic_dec(&ctx->hdev->dmabuf_export_cnt);
|
||||||
hl_ctx_put(ctx);
|
hl_ctx_put(ctx);
|
||||||
|
|
||||||
/* Paired with get_file() in export_dmabuf() */
|
/*
|
||||||
|
* Paired with get_file() in export_dmabuf().
|
||||||
|
* 'ctx' can be still used here to get the file pointer, even after hl_ctx_put() was called,
|
||||||
|
* because releasing the compute device file involves another reference decrement, and it
|
||||||
|
* would be possible only after calling fput().
|
||||||
|
*/
|
||||||
fput(ctx->hpriv->file_priv->filp);
|
fput(ctx->hpriv->file_priv->filp);
|
||||||
|
|
||||||
kfree(hl_dmabuf);
|
kfree(hl_dmabuf);
|
||||||
|
|
@ -2332,7 +2337,7 @@ static int get_user_memory(struct hl_device *hdev, u64 addr, u64 size,
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto destroy_pages;
|
goto destroy_pages;
|
||||||
npages = rc;
|
npages = rc;
|
||||||
rc = -EFAULT;
|
rc = -ENOMEM;
|
||||||
goto put_pages;
|
goto put_pages;
|
||||||
}
|
}
|
||||||
userptr->npages = npages;
|
userptr->npages = npages;
|
||||||
|
|
|
||||||
|
|
@ -259,13 +259,8 @@ int hl_mem_mgr_mmap(struct hl_mem_mgr *mmg, struct vm_area_struct *vma,
|
||||||
goto put_mem;
|
goto put_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _HAS_TYPE_ARG_IN_ACCESS_OK
|
|
||||||
if (!access_ok(VERIFY_WRITE, (void __user *)(uintptr_t)vma->vm_start,
|
|
||||||
user_mem_size)) {
|
|
||||||
#else
|
|
||||||
if (!access_ok((void __user *)(uintptr_t)vma->vm_start,
|
if (!access_ok((void __user *)(uintptr_t)vma->vm_start,
|
||||||
user_mem_size)) {
|
user_mem_size)) {
|
||||||
#endif
|
|
||||||
dev_err(mmg->dev, "%s: User pointer is invalid - 0x%lx\n",
|
dev_err(mmg->dev, "%s: User pointer is invalid - 0x%lx\n",
|
||||||
buf->behavior->topic, vma->vm_start);
|
buf->behavior->topic, vma->vm_start);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,14 +96,21 @@ static ssize_t vrm_ver_show(struct device *dev, struct device_attribute *attr, c
|
||||||
infineon_second_stage_third_instance =
|
infineon_second_stage_third_instance =
|
||||||
(infineon_second_stage_version >> 16) & mask;
|
(infineon_second_stage_version >> 16) & mask;
|
||||||
|
|
||||||
if (cpucp_info->infineon_second_stage_version)
|
if (cpucp_info->infineon_version && cpucp_info->infineon_second_stage_version)
|
||||||
return sprintf(buf, "%#04x %#04x:%#04x:%#04x\n",
|
return sprintf(buf, "%#04x %#04x:%#04x:%#04x\n",
|
||||||
le32_to_cpu(cpucp_info->infineon_version),
|
le32_to_cpu(cpucp_info->infineon_version),
|
||||||
infineon_second_stage_first_instance,
|
infineon_second_stage_first_instance,
|
||||||
infineon_second_stage_second_instance,
|
infineon_second_stage_second_instance,
|
||||||
infineon_second_stage_third_instance);
|
infineon_second_stage_third_instance);
|
||||||
else
|
else if (cpucp_info->infineon_second_stage_version)
|
||||||
|
return sprintf(buf, "%#04x:%#04x:%#04x\n",
|
||||||
|
infineon_second_stage_first_instance,
|
||||||
|
infineon_second_stage_second_instance,
|
||||||
|
infineon_second_stage_third_instance);
|
||||||
|
else if (cpucp_info->infineon_version)
|
||||||
return sprintf(buf, "%#04x\n", le32_to_cpu(cpucp_info->infineon_version));
|
return sprintf(buf, "%#04x\n", le32_to_cpu(cpucp_info->infineon_version));
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR_RO(vrm_ver);
|
static DEVICE_ATTR_RO(vrm_ver);
|
||||||
|
|
|
||||||
|
|
@ -4168,10 +4168,29 @@ static int gaudi_mmap(struct hl_device *hdev, struct vm_area_struct *vma,
|
||||||
vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP |
|
vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP |
|
||||||
VM_DONTCOPY | VM_NORESERVE);
|
VM_DONTCOPY | VM_NORESERVE);
|
||||||
|
|
||||||
|
#ifdef _HAS_DMA_MMAP_COHERENT
|
||||||
|
/*
|
||||||
|
* If dma_alloc_coherent() returns a vmalloc address, set VM_MIXEDMAP
|
||||||
|
* so vm_insert_page() can handle it safely. Without this, the kernel
|
||||||
|
* may BUG_ON due to VM_PFNMAP.
|
||||||
|
*/
|
||||||
|
if (is_vmalloc_addr(cpu_addr))
|
||||||
|
vm_flags_set(vma, VM_MIXEDMAP);
|
||||||
|
|
||||||
rc = dma_mmap_coherent(hdev->dev, vma, cpu_addr,
|
rc = dma_mmap_coherent(hdev->dev, vma, cpu_addr,
|
||||||
(dma_addr - HOST_PHYS_BASE), size);
|
(dma_addr - HOST_PHYS_BASE), size);
|
||||||
if (rc)
|
if (rc)
|
||||||
dev_err(hdev->dev, "dma_mmap_coherent error %d", rc);
|
dev_err(hdev->dev, "dma_mmap_coherent error %d", rc);
|
||||||
|
#else
|
||||||
|
|
||||||
|
rc = remap_pfn_range(vma, vma->vm_start,
|
||||||
|
virt_to_phys(cpu_addr) >> PAGE_SHIFT,
|
||||||
|
size, vma->vm_page_prot);
|
||||||
|
if (rc)
|
||||||
|
dev_err(hdev->dev, "remap_pfn_range error %d", rc);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -728,6 +728,354 @@ static const int gaudi2_dma_core_async_event_id[] = {
|
||||||
[DMA_CORE_ID_KDMA] = GAUDI2_EVENT_KDMA0_CORE,
|
[DMA_CORE_ID_KDMA] = GAUDI2_EVENT_KDMA0_CORE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *gaudi2_engine_id_str[] = {
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_EDMA_0),
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_EDMA_1),
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_MME),
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_TPC_0),
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_TPC_1),
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_TPC_2),
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_TPC_3),
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_TPC_4),
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_TPC_5),
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_DEC_0),
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_DEC_1),
|
||||||
|
__stringify(GAUDI2_DCORE1_ENGINE_ID_EDMA_0),
|
||||||
|
__stringify(GAUDI2_DCORE1_ENGINE_ID_EDMA_1),
|
||||||
|
__stringify(GAUDI2_DCORE1_ENGINE_ID_MME),
|
||||||
|
__stringify(GAUDI2_DCORE1_ENGINE_ID_TPC_0),
|
||||||
|
__stringify(GAUDI2_DCORE1_ENGINE_ID_TPC_1),
|
||||||
|
__stringify(GAUDI2_DCORE1_ENGINE_ID_TPC_2),
|
||||||
|
__stringify(GAUDI2_DCORE1_ENGINE_ID_TPC_3),
|
||||||
|
__stringify(GAUDI2_DCORE1_ENGINE_ID_TPC_4),
|
||||||
|
__stringify(GAUDI2_DCORE1_ENGINE_ID_TPC_5),
|
||||||
|
__stringify(GAUDI2_DCORE1_ENGINE_ID_DEC_0),
|
||||||
|
__stringify(GAUDI2_DCORE1_ENGINE_ID_DEC_1),
|
||||||
|
__stringify(GAUDI2_DCORE2_ENGINE_ID_EDMA_0),
|
||||||
|
__stringify(GAUDI2_DCORE2_ENGINE_ID_EDMA_1),
|
||||||
|
__stringify(GAUDI2_DCORE2_ENGINE_ID_MME),
|
||||||
|
__stringify(GAUDI2_DCORE2_ENGINE_ID_TPC_0),
|
||||||
|
__stringify(GAUDI2_DCORE2_ENGINE_ID_TPC_1),
|
||||||
|
__stringify(GAUDI2_DCORE2_ENGINE_ID_TPC_2),
|
||||||
|
__stringify(GAUDI2_DCORE2_ENGINE_ID_TPC_3),
|
||||||
|
__stringify(GAUDI2_DCORE2_ENGINE_ID_TPC_4),
|
||||||
|
__stringify(GAUDI2_DCORE2_ENGINE_ID_TPC_5),
|
||||||
|
__stringify(GAUDI2_DCORE2_ENGINE_ID_DEC_0),
|
||||||
|
__stringify(GAUDI2_DCORE2_ENGINE_ID_DEC_1),
|
||||||
|
__stringify(GAUDI2_DCORE3_ENGINE_ID_EDMA_0),
|
||||||
|
__stringify(GAUDI2_DCORE3_ENGINE_ID_EDMA_1),
|
||||||
|
__stringify(GAUDI2_DCORE3_ENGINE_ID_MME),
|
||||||
|
__stringify(GAUDI2_DCORE3_ENGINE_ID_TPC_0),
|
||||||
|
__stringify(GAUDI2_DCORE3_ENGINE_ID_TPC_1),
|
||||||
|
__stringify(GAUDI2_DCORE3_ENGINE_ID_TPC_2),
|
||||||
|
__stringify(GAUDI2_DCORE3_ENGINE_ID_TPC_3),
|
||||||
|
__stringify(GAUDI2_DCORE3_ENGINE_ID_TPC_4),
|
||||||
|
__stringify(GAUDI2_DCORE3_ENGINE_ID_TPC_5),
|
||||||
|
__stringify(GAUDI2_DCORE3_ENGINE_ID_DEC_0),
|
||||||
|
__stringify(GAUDI2_DCORE3_ENGINE_ID_DEC_1),
|
||||||
|
__stringify(GAUDI2_DCORE0_ENGINE_ID_TPC_6),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_PDMA_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_PDMA_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_ROT_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_ROT_1),
|
||||||
|
__stringify(GAUDI2_PCIE_ENGINE_ID_DEC_0),
|
||||||
|
__stringify(GAUDI2_PCIE_ENGINE_ID_DEC_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC0_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC0_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC1_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC1_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC2_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC2_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC3_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC3_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC4_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC4_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC5_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC5_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC6_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC6_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC7_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC7_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC8_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC8_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC9_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC9_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC10_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC10_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC11_0),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_NIC11_1),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_PCIE),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_PSOC),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_ARC_FARM),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_KDMA),
|
||||||
|
__stringify(GAUDI2_ENGINE_ID_SIZE),
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *gaudi2_queue_id_str[] = {
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_PDMA_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_PDMA_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_PDMA_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_PDMA_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_PDMA_1_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_PDMA_1_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_PDMA_1_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_PDMA_1_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_EDMA_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_EDMA_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_EDMA_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_EDMA_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_EDMA_1_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_EDMA_1_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_EDMA_1_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_EDMA_1_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_MME_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_MME_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_MME_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_MME_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_1_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_1_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_1_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_1_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_2_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_2_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_2_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_2_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_3_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_3_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_3_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_3_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_4_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_4_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_4_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_4_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_5_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_5_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_5_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_5_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_6_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_6_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_6_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE0_TPC_6_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_EDMA_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_EDMA_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_EDMA_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_EDMA_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_EDMA_1_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_EDMA_1_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_EDMA_1_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_EDMA_1_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_MME_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_MME_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_MME_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_MME_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_1_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_1_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_1_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_1_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_2_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_2_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_2_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_2_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_3_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_3_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_3_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_3_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_4_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_4_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_4_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_4_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_5_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_5_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_5_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE1_TPC_5_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_EDMA_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_EDMA_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_EDMA_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_EDMA_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_EDMA_1_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_EDMA_1_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_EDMA_1_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_EDMA_1_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_MME_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_MME_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_MME_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_MME_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_1_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_1_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_1_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_1_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_2_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_2_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_2_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_2_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_3_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_3_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_3_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_3_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_4_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_4_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_4_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_4_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_5_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_5_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_5_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE2_TPC_5_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_EDMA_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_EDMA_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_EDMA_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_EDMA_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_EDMA_1_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_EDMA_1_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_EDMA_1_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_EDMA_1_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_MME_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_MME_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_MME_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_MME_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_1_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_1_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_1_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_1_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_2_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_2_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_2_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_2_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_3_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_3_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_3_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_3_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_4_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_4_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_4_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_4_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_5_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_5_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_5_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_DCORE3_TPC_5_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_1_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_1_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_1_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_1_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_2_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_2_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_2_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_2_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_3_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_3_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_3_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_3_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_4_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_4_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_4_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_4_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_5_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_5_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_5_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_5_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_6_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_6_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_6_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_6_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_7_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_7_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_7_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_7_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_8_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_8_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_8_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_8_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_9_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_9_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_9_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_9_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_10_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_10_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_10_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_10_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_11_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_11_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_11_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_11_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_12_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_12_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_12_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_12_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_13_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_13_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_13_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_13_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_14_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_14_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_14_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_14_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_15_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_15_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_15_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_15_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_16_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_16_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_16_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_16_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_17_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_17_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_17_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_17_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_18_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_18_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_18_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_18_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_19_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_19_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_19_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_19_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_20_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_20_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_20_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_20_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_21_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_21_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_21_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_21_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_22_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_22_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_22_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_22_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_23_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_23_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_23_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_NIC_23_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_ROT_0_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_ROT_0_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_ROT_0_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_ROT_0_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_ROT_1_0),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_ROT_1_1),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_ROT_1_2),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_ROT_1_3),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_CPU_PQ),
|
||||||
|
__stringify(GAUDI2_QUEUE_ID_SIZE),
|
||||||
|
};
|
||||||
|
|
||||||
static const char * const gaudi2_qm_sei_error_cause[GAUDI2_NUM_OF_QM_SEI_ERR_CAUSE] = {
|
static const char * const gaudi2_qm_sei_error_cause[GAUDI2_NUM_OF_QM_SEI_ERR_CAUSE] = {
|
||||||
"qman sei intr",
|
"qman sei intr",
|
||||||
"arc sei intr"
|
"arc sei intr"
|
||||||
|
|
@ -3150,7 +3498,6 @@ static int gaudi2_early_init(struct hl_device *hdev)
|
||||||
rc = hl_fw_read_preboot_status(hdev);
|
rc = hl_fw_read_preboot_status(hdev);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (hdev->reset_on_preboot_fail)
|
if (hdev->reset_on_preboot_fail)
|
||||||
/* we are already on failure flow, so don't check if hw_fini fails. */
|
|
||||||
hdev->asic_funcs->hw_fini(hdev, true, false);
|
hdev->asic_funcs->hw_fini(hdev, true, false);
|
||||||
goto pci_fini;
|
goto pci_fini;
|
||||||
}
|
}
|
||||||
|
|
@ -3162,6 +3509,13 @@ static int gaudi2_early_init(struct hl_device *hdev)
|
||||||
dev_err(hdev->dev, "failed to reset HW in dirty state (%d)\n", rc);
|
dev_err(hdev->dev, "failed to reset HW in dirty state (%d)\n", rc);
|
||||||
goto pci_fini;
|
goto pci_fini;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = hl_fw_read_preboot_status(hdev);
|
||||||
|
if (rc) {
|
||||||
|
if (hdev->reset_on_preboot_fail)
|
||||||
|
hdev->asic_funcs->hw_fini(hdev, true, false);
|
||||||
|
goto pci_fini;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -4836,7 +5190,7 @@ static void gaudi2_halt_engines(struct hl_device *hdev, bool hard_reset, bool fw
|
||||||
else
|
else
|
||||||
wait_timeout_ms = GAUDI2_RESET_WAIT_MSEC;
|
wait_timeout_ms = GAUDI2_RESET_WAIT_MSEC;
|
||||||
|
|
||||||
if (fw_reset)
|
if (fw_reset || hdev->cpld_shutdown)
|
||||||
goto skip_engines;
|
goto skip_engines;
|
||||||
|
|
||||||
gaudi2_stop_dma_qmans(hdev);
|
gaudi2_stop_dma_qmans(hdev);
|
||||||
|
|
@ -6484,6 +6838,13 @@ static int gaudi2_mmap(struct hl_device *hdev, struct vm_area_struct *vma,
|
||||||
VM_DONTCOPY | VM_NORESERVE);
|
VM_DONTCOPY | VM_NORESERVE);
|
||||||
|
|
||||||
#ifdef _HAS_DMA_MMAP_COHERENT
|
#ifdef _HAS_DMA_MMAP_COHERENT
|
||||||
|
/*
|
||||||
|
* If dma_alloc_coherent() returns a vmalloc address, set VM_MIXEDMAP
|
||||||
|
* so vm_insert_page() can handle it safely. Without this, the kernel
|
||||||
|
* may BUG_ON due to VM_PFNMAP.
|
||||||
|
*/
|
||||||
|
if (is_vmalloc_addr(cpu_addr))
|
||||||
|
vm_flags_set(vma, VM_MIXEDMAP);
|
||||||
|
|
||||||
rc = dma_mmap_coherent(hdev->dev, vma, cpu_addr, dma_addr, size);
|
rc = dma_mmap_coherent(hdev->dev, vma, cpu_addr, dma_addr, size);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
|
@ -6774,7 +7135,8 @@ static int gaudi2_validate_cb_address(struct hl_device *hdev, struct hl_cs_parse
|
||||||
struct gaudi2_device *gaudi2 = hdev->asic_specific;
|
struct gaudi2_device *gaudi2 = hdev->asic_specific;
|
||||||
|
|
||||||
if (!gaudi2_is_queue_enabled(hdev, parser->hw_queue_id)) {
|
if (!gaudi2_is_queue_enabled(hdev, parser->hw_queue_id)) {
|
||||||
dev_err(hdev->dev, "h/w queue %d is disabled\n", parser->hw_queue_id);
|
dev_err(hdev->dev, "h/w queue %s is disabled\n",
|
||||||
|
GAUDI2_QUEUE_ID_TO_STR(parser->hw_queue_id));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7026,7 +7388,8 @@ static int gaudi2_test_queue_send_msg_short(struct hl_device *hdev, u32 hw_queue
|
||||||
rc = hl_hw_queue_send_cb_no_cmpl(hdev, hw_queue_id, pkt_size, msg_info->dma_addr);
|
rc = hl_hw_queue_send_cb_no_cmpl(hdev, hw_queue_id, pkt_size, msg_info->dma_addr);
|
||||||
if (rc)
|
if (rc)
|
||||||
dev_err(hdev->dev,
|
dev_err(hdev->dev,
|
||||||
"Failed to send msg_short packet to H/W queue %d\n", hw_queue_id);
|
"Failed to send msg_short packet to H/W queue %s\n",
|
||||||
|
GAUDI2_QUEUE_ID_TO_STR(hw_queue_id));
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
@ -7052,8 +7415,8 @@ static int gaudi2_test_queue_wait_completion(struct hl_device *hdev, u32 hw_queu
|
||||||
timeout_usec);
|
timeout_usec);
|
||||||
|
|
||||||
if (rc == -ETIMEDOUT) {
|
if (rc == -ETIMEDOUT) {
|
||||||
dev_err(hdev->dev, "H/W queue %d test failed (SOB_OBJ_0 == 0x%x)\n",
|
dev_err(hdev->dev, "H/W queue %s test failed (SOB_OBJ_0 == 0x%x)\n",
|
||||||
hw_queue_id, tmp);
|
GAUDI2_QUEUE_ID_TO_STR(hw_queue_id), tmp);
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -9603,8 +9966,8 @@ static int hl_arc_event_handle(struct hl_device *hdev, u16 event_type,
|
||||||
q = (struct hl_engine_arc_dccm_queue_full_irq *) &payload;
|
q = (struct hl_engine_arc_dccm_queue_full_irq *) &payload;
|
||||||
|
|
||||||
gaudi2_print_event(hdev, event_type, true,
|
gaudi2_print_event(hdev, event_type, true,
|
||||||
"ARC DCCM Full event: EngId: %u, Intr_type: %u, Qidx: %u",
|
"ARC DCCM Full event: Eng: %s, Intr_type: %u, Qidx: %u",
|
||||||
engine_id, intr_type, q->queue_index);
|
GAUDI2_ENG_ID_TO_STR(engine_id), intr_type, q->queue_index);
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
gaudi2_print_event(hdev, event_type, true, "Unknown ARC event type");
|
gaudi2_print_event(hdev, event_type, true, "Unknown ARC event type");
|
||||||
|
|
@ -10172,7 +10535,7 @@ static void gaudi2_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_ent
|
||||||
dev_err(hdev->dev, "CPLD shutdown event, reset reason: 0x%llx\n",
|
dev_err(hdev->dev, "CPLD shutdown event, reset reason: 0x%llx\n",
|
||||||
le64_to_cpu(eq_entry->data[0]));
|
le64_to_cpu(eq_entry->data[0]));
|
||||||
error_count = GAUDI2_NA_EVENT_CAUSE;
|
error_count = GAUDI2_NA_EVENT_CAUSE;
|
||||||
event_mask |= HL_NOTIFIER_EVENT_GENERAL_HW_ERR;
|
hl_eq_cpld_shutdown_event_handle(hdev, event_type, &event_mask);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GAUDI2_EVENT_CPU_PKT_SANITY_FAILED:
|
case GAUDI2_EVENT_CPU_PKT_SANITY_FAILED:
|
||||||
|
|
@ -10260,6 +10623,7 @@ reset_device:
|
||||||
if (event_mask & HL_NOTIFIER_EVENT_GENERAL_HW_ERR)
|
if (event_mask & HL_NOTIFIER_EVENT_GENERAL_HW_ERR)
|
||||||
hl_handle_critical_hw_err(hdev, event_type, &event_mask);
|
hl_handle_critical_hw_err(hdev, event_type, &event_mask);
|
||||||
|
|
||||||
|
hl_debugfs_cfg_access_history_dump(hdev);
|
||||||
event_mask |= HL_NOTIFIER_EVENT_DEVICE_RESET;
|
event_mask |= HL_NOTIFIER_EVENT_DEVICE_RESET;
|
||||||
hl_device_cond_reset(hdev, reset_flags, event_mask);
|
hl_device_cond_reset(hdev, reset_flags, event_mask);
|
||||||
}
|
}
|
||||||
|
|
@ -10296,8 +10660,8 @@ static int gaudi2_memset_memory_chunk_using_edma_qm(struct hl_device *hdev,
|
||||||
|
|
||||||
rc = hl_hw_queue_send_cb_no_cmpl(hdev, hw_queue_id, pkt_size, phys_addr);
|
rc = hl_hw_queue_send_cb_no_cmpl(hdev, hw_queue_id, pkt_size, phys_addr);
|
||||||
if (rc)
|
if (rc)
|
||||||
dev_err(hdev->dev, "Failed to send lin_dma packet to H/W queue %d\n",
|
dev_err(hdev->dev, "Failed to send lin_dma packet to H/W queue %s\n",
|
||||||
hw_queue_id);
|
GAUDI2_QUEUE_ID_TO_STR(hw_queue_id));
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,15 @@
|
||||||
#define GAUDI2_NUM_TESTED_QS (GAUDI2_QUEUE_ID_CPU_PQ - GAUDI2_QUEUE_ID_PDMA_0_0)
|
#define GAUDI2_NUM_TESTED_QS (GAUDI2_QUEUE_ID_CPU_PQ - GAUDI2_QUEUE_ID_PDMA_0_0)
|
||||||
|
|
||||||
|
|
||||||
|
extern const char *gaudi2_engine_id_str[];
|
||||||
|
extern const char *gaudi2_queue_id_str[];
|
||||||
|
|
||||||
|
#define GAUDI2_ENG_ID_TO_STR(initiator) ((initiator) >= GAUDI2_ENGINE_ID_SIZE ? "not found" : \
|
||||||
|
gaudi2_engine_id_str[initiator])
|
||||||
|
|
||||||
|
#define GAUDI2_QUEUE_ID_TO_STR(initiator) ((initiator) >= GAUDI2_QUEUE_ID_SIZE ? "not found" : \
|
||||||
|
gaudi2_queue_id_str[initiator])
|
||||||
|
|
||||||
enum gaudi2_reserved_sob_id {
|
enum gaudi2_reserved_sob_id {
|
||||||
GAUDI2_RESERVED_SOB_CS_COMPLETION_FIRST,
|
GAUDI2_RESERVED_SOB_CS_COMPLETION_FIRST,
|
||||||
GAUDI2_RESERVED_SOB_CS_COMPLETION_LAST =
|
GAUDI2_RESERVED_SOB_CS_COMPLETION_LAST =
|
||||||
|
|
|
||||||
|
|
@ -2426,7 +2426,7 @@ static int gaudi2_config_bmon(struct hl_device *hdev, struct hl_debug_params *pa
|
||||||
WREG32(base_reg + mmBMON_ADDRH_E3_OFFSET, 0);
|
WREG32(base_reg + mmBMON_ADDRH_E3_OFFSET, 0);
|
||||||
WREG32(base_reg + mmBMON_REDUCTION_OFFSET, 0);
|
WREG32(base_reg + mmBMON_REDUCTION_OFFSET, 0);
|
||||||
WREG32(base_reg + mmBMON_STM_TRC_OFFSET, 0x7 | (0xA << 8));
|
WREG32(base_reg + mmBMON_STM_TRC_OFFSET, 0x7 | (0xA << 8));
|
||||||
WREG32(base_reg + mmBMON_CR_OFFSET, 0x77 | 0xf << 24);
|
WREG32(base_reg + mmBMON_CR_OFFSET, 0x41);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ struct ivpu_fw_info {
|
||||||
int ivpu_fw_init(struct ivpu_device *vdev);
|
int ivpu_fw_init(struct ivpu_device *vdev);
|
||||||
void ivpu_fw_fini(struct ivpu_device *vdev);
|
void ivpu_fw_fini(struct ivpu_device *vdev);
|
||||||
void ivpu_fw_load(struct ivpu_device *vdev);
|
void ivpu_fw_load(struct ivpu_device *vdev);
|
||||||
void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params *bp);
|
void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params *boot_params);
|
||||||
|
|
||||||
static inline bool ivpu_fw_is_cold_boot(struct ivpu_device *vdev)
|
static inline bool ivpu_fw_is_cold_boot(struct ivpu_device *vdev)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@
|
||||||
|
|
||||||
#define PLL_CDYN_DEFAULT 0x80
|
#define PLL_CDYN_DEFAULT 0x80
|
||||||
#define PLL_EPP_DEFAULT 0x80
|
#define PLL_EPP_DEFAULT 0x80
|
||||||
#define PLL_CONFIG_DEFAULT 0x0
|
|
||||||
#define PLL_REF_CLK_FREQ 50000000ull
|
#define PLL_REF_CLK_FREQ 50000000ull
|
||||||
#define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ)
|
#define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ)
|
||||||
|
|
||||||
|
|
@ -303,7 +302,7 @@ static void prepare_wp_request(struct ivpu_device *vdev, struct wp_request *wp,
|
||||||
wp->epp = 0;
|
wp->epp = 0;
|
||||||
} else {
|
} else {
|
||||||
wp->target = hw->pll.pn_ratio;
|
wp->target = hw->pll.pn_ratio;
|
||||||
wp->cfg = enable ? PLL_CONFIG_DEFAULT : 0;
|
wp->cfg = 0;
|
||||||
wp->cdyn = enable ? PLL_CDYN_DEFAULT : 0;
|
wp->cdyn = enable ? PLL_CDYN_DEFAULT : 0;
|
||||||
wp->epp = enable ? PLL_EPP_DEFAULT : 0;
|
wp->epp = enable ? PLL_EPP_DEFAULT : 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ u32 ivpu_hw_btrs_dpu_freq_get(struct ivpu_device *vdev);
|
||||||
bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq);
|
bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq);
|
||||||
bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq);
|
bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq);
|
||||||
int ivpu_hw_btrs_dct_get_request(struct ivpu_device *vdev, bool *enable);
|
int ivpu_hw_btrs_dct_get_request(struct ivpu_device *vdev, bool *enable);
|
||||||
void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u32 dct_percent);
|
void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u32 active_percent);
|
||||||
u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev);
|
u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev);
|
||||||
u32 ivpu_hw_btrs_telemetry_size_get(struct ivpu_device *vdev);
|
u32 ivpu_hw_btrs_telemetry_size_get(struct ivpu_device *vdev);
|
||||||
u32 ivpu_hw_btrs_telemetry_enable_get(struct ivpu_device *vdev);
|
u32 ivpu_hw_btrs_telemetry_enable_get(struct ivpu_device *vdev);
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,6 @@ ivpu_ipc_rx_msg_add(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
|
||||||
struct ivpu_ipc_rx_msg *rx_msg;
|
struct ivpu_ipc_rx_msg *rx_msg;
|
||||||
|
|
||||||
lockdep_assert_held(&ipc->cons_lock);
|
lockdep_assert_held(&ipc->cons_lock);
|
||||||
lockdep_assert_irqs_disabled();
|
|
||||||
|
|
||||||
rx_msg = kzalloc(sizeof(*rx_msg), GFP_ATOMIC);
|
rx_msg = kzalloc(sizeof(*rx_msg), GFP_ATOMIC);
|
||||||
if (!rx_msg) {
|
if (!rx_msg) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
config DRM_ACCEL_ROCKET
|
||||||
|
tristate "Rocket (support for Rockchip NPUs)"
|
||||||
|
depends on DRM_ACCEL
|
||||||
|
depends on (ARCH_ROCKCHIP && ARM64) || COMPILE_TEST
|
||||||
|
depends on ROCKCHIP_IOMMU || COMPILE_TEST
|
||||||
|
depends on MMU
|
||||||
|
select DRM_SCHED
|
||||||
|
select DRM_GEM_SHMEM_HELPER
|
||||||
|
help
|
||||||
|
Choose this option if you have a Rockchip SoC that contains a
|
||||||
|
compatible Neural Processing Unit (NPU), such as the RK3588. Called by
|
||||||
|
Rockchip either RKNN or RKNPU, it accelerates inference of neural
|
||||||
|
networks.
|
||||||
|
|
||||||
|
The interface exposed to userspace is described in
|
||||||
|
include/uapi/drm/rocket_accel.h and is used by the Rocket userspace
|
||||||
|
driver in Mesa3D.
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the
|
||||||
|
module will be called rocket.
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
obj-$(CONFIG_DRM_ACCEL_ROCKET) := rocket.o
|
||||||
|
|
||||||
|
rocket-y := \
|
||||||
|
rocket_core.o \
|
||||||
|
rocket_device.o \
|
||||||
|
rocket_drv.o \
|
||||||
|
rocket_gem.o \
|
||||||
|
rocket_job.o
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/* Copyright 2024-2025 Tomeu Vizoso <tomeu@tomeuvizoso.net> */
|
||||||
|
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/dev_printk.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/iommu.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
|
||||||
|
#include "rocket_core.h"
|
||||||
|
#include "rocket_job.h"
|
||||||
|
|
||||||
|
int rocket_core_init(struct rocket_core *core)
|
||||||
|
{
|
||||||
|
struct device *dev = core->dev;
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
u32 version;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
core->resets[0].id = "srst_a";
|
||||||
|
core->resets[1].id = "srst_h";
|
||||||
|
err = devm_reset_control_bulk_get_exclusive(&pdev->dev, ARRAY_SIZE(core->resets),
|
||||||
|
core->resets);
|
||||||
|
if (err)
|
||||||
|
return dev_err_probe(dev, err, "failed to get resets for core %d\n", core->index);
|
||||||
|
|
||||||
|
err = devm_clk_bulk_get(dev, ARRAY_SIZE(core->clks), core->clks);
|
||||||
|
if (err)
|
||||||
|
return dev_err_probe(dev, err, "failed to get clocks for core %d\n", core->index);
|
||||||
|
|
||||||
|
core->pc_iomem = devm_platform_ioremap_resource_byname(pdev, "pc");
|
||||||
|
if (IS_ERR(core->pc_iomem)) {
|
||||||
|
dev_err(dev, "couldn't find PC registers %ld\n", PTR_ERR(core->pc_iomem));
|
||||||
|
return PTR_ERR(core->pc_iomem);
|
||||||
|
}
|
||||||
|
|
||||||
|
core->cna_iomem = devm_platform_ioremap_resource_byname(pdev, "cna");
|
||||||
|
if (IS_ERR(core->cna_iomem)) {
|
||||||
|
dev_err(dev, "couldn't find CNA registers %ld\n", PTR_ERR(core->cna_iomem));
|
||||||
|
return PTR_ERR(core->cna_iomem);
|
||||||
|
}
|
||||||
|
|
||||||
|
core->core_iomem = devm_platform_ioremap_resource_byname(pdev, "core");
|
||||||
|
if (IS_ERR(core->core_iomem)) {
|
||||||
|
dev_err(dev, "couldn't find CORE registers %ld\n", PTR_ERR(core->core_iomem));
|
||||||
|
return PTR_ERR(core->core_iomem);
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_set_max_seg_size(dev, UINT_MAX);
|
||||||
|
|
||||||
|
err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
core->iommu_group = iommu_group_get(dev);
|
||||||
|
|
||||||
|
err = rocket_job_init(core);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
pm_runtime_use_autosuspend(dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As this NPU will be most often used as part of a media pipeline that
|
||||||
|
* ends presenting in a display, choose 50 ms (~3 frames at 60Hz) as an
|
||||||
|
* autosuspend delay as that will keep the device powered up while the
|
||||||
|
* pipeline is running.
|
||||||
|
*/
|
||||||
|
pm_runtime_set_autosuspend_delay(dev, 50);
|
||||||
|
|
||||||
|
pm_runtime_enable(dev);
|
||||||
|
|
||||||
|
err = pm_runtime_resume_and_get(dev);
|
||||||
|
if (err) {
|
||||||
|
rocket_job_fini(core);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
version = rocket_pc_readl(core, VERSION);
|
||||||
|
version += rocket_pc_readl(core, VERSION_NUM) & 0xffff;
|
||||||
|
|
||||||
|
pm_runtime_mark_last_busy(dev);
|
||||||
|
pm_runtime_put_autosuspend(dev);
|
||||||
|
|
||||||
|
dev_info(dev, "Rockchip NPU core %d version: %d\n", core->index, version);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rocket_core_fini(struct rocket_core *core)
|
||||||
|
{
|
||||||
|
pm_runtime_dont_use_autosuspend(core->dev);
|
||||||
|
pm_runtime_disable(core->dev);
|
||||||
|
iommu_group_put(core->iommu_group);
|
||||||
|
core->iommu_group = NULL;
|
||||||
|
rocket_job_fini(core);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rocket_core_reset(struct rocket_core *core)
|
||||||
|
{
|
||||||
|
reset_control_bulk_assert(ARRAY_SIZE(core->resets), core->resets);
|
||||||
|
|
||||||
|
udelay(10);
|
||||||
|
|
||||||
|
reset_control_bulk_deassert(ARRAY_SIZE(core->resets), core->resets);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/* Copyright 2024-2025 Tomeu Vizoso <tomeu@tomeuvizoso.net> */
|
||||||
|
|
||||||
|
#ifndef __ROCKET_CORE_H__
|
||||||
|
#define __ROCKET_CORE_H__
|
||||||
|
|
||||||
|
#include <drm/gpu_scheduler.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/mutex_types.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
|
||||||
|
#include "rocket_registers.h"
|
||||||
|
|
||||||
|
#define rocket_pc_readl(core, reg) \
|
||||||
|
readl((core)->pc_iomem + (REG_PC_##reg))
|
||||||
|
#define rocket_pc_writel(core, reg, value) \
|
||||||
|
writel(value, (core)->pc_iomem + (REG_PC_##reg))
|
||||||
|
|
||||||
|
#define rocket_cna_readl(core, reg) \
|
||||||
|
readl((core)->cna_iomem + (REG_CNA_##reg) - REG_CNA_S_STATUS)
|
||||||
|
#define rocket_cna_writel(core, reg, value) \
|
||||||
|
writel(value, (core)->cna_iomem + (REG_CNA_##reg) - REG_CNA_S_STATUS)
|
||||||
|
|
||||||
|
#define rocket_core_readl(core, reg) \
|
||||||
|
readl((core)->core_iomem + (REG_CORE_##reg) - REG_CORE_S_STATUS)
|
||||||
|
#define rocket_core_writel(core, reg, value) \
|
||||||
|
writel(value, (core)->core_iomem + (REG_CORE_##reg) - REG_CORE_S_STATUS)
|
||||||
|
|
||||||
|
struct rocket_core {
|
||||||
|
struct device *dev;
|
||||||
|
struct rocket_device *rdev;
|
||||||
|
unsigned int index;
|
||||||
|
|
||||||
|
int irq;
|
||||||
|
void __iomem *pc_iomem;
|
||||||
|
void __iomem *cna_iomem;
|
||||||
|
void __iomem *core_iomem;
|
||||||
|
struct clk_bulk_data clks[4];
|
||||||
|
struct reset_control_bulk_data resets[2];
|
||||||
|
|
||||||
|
struct iommu_group *iommu_group;
|
||||||
|
|
||||||
|
struct mutex job_lock;
|
||||||
|
struct rocket_job *in_flight_job;
|
||||||
|
|
||||||
|
spinlock_t fence_lock;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct workqueue_struct *wq;
|
||||||
|
struct work_struct work;
|
||||||
|
atomic_t pending;
|
||||||
|
} reset;
|
||||||
|
|
||||||
|
struct drm_gpu_scheduler sched;
|
||||||
|
u64 fence_context;
|
||||||
|
u64 emit_seqno;
|
||||||
|
};
|
||||||
|
|
||||||
|
int rocket_core_init(struct rocket_core *core);
|
||||||
|
void rocket_core_fini(struct rocket_core *core);
|
||||||
|
void rocket_core_reset(struct rocket_core *core);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/* Copyright 2024-2025 Tomeu Vizoso <tomeu@tomeuvizoso.net> */
|
||||||
|
|
||||||
|
#include <drm/drm_drv.h>
|
||||||
|
#include <linux/array_size.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
|
||||||
|
#include "rocket_device.h"
|
||||||
|
|
||||||
|
struct rocket_device *rocket_device_init(struct platform_device *pdev,
|
||||||
|
const struct drm_driver *rocket_drm_driver)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct device_node *core_node;
|
||||||
|
struct rocket_device *rdev;
|
||||||
|
struct drm_device *ddev;
|
||||||
|
unsigned int num_cores = 0;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
rdev = devm_drm_dev_alloc(dev, rocket_drm_driver, struct rocket_device, ddev);
|
||||||
|
if (IS_ERR(rdev))
|
||||||
|
return rdev;
|
||||||
|
|
||||||
|
ddev = &rdev->ddev;
|
||||||
|
dev_set_drvdata(dev, rdev);
|
||||||
|
|
||||||
|
for_each_compatible_node(core_node, NULL, "rockchip,rk3588-rknn-core")
|
||||||
|
if (of_device_is_available(core_node))
|
||||||
|
num_cores++;
|
||||||
|
|
||||||
|
rdev->cores = devm_kcalloc(dev, num_cores, sizeof(*rdev->cores), GFP_KERNEL);
|
||||||
|
if (!rdev->cores)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
dma_set_max_seg_size(dev, UINT_MAX);
|
||||||
|
|
||||||
|
err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
|
||||||
|
if (err)
|
||||||
|
return ERR_PTR(err);
|
||||||
|
|
||||||
|
err = devm_mutex_init(dev, &rdev->sched_lock);
|
||||||
|
if (err)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
err = drm_dev_register(ddev, 0);
|
||||||
|
if (err)
|
||||||
|
return ERR_PTR(err);
|
||||||
|
|
||||||
|
return rdev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rocket_device_fini(struct rocket_device *rdev)
|
||||||
|
{
|
||||||
|
WARN_ON(rdev->num_cores > 0);
|
||||||
|
|
||||||
|
drm_dev_unregister(&rdev->ddev);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue