VPU stands for Versatile Processing Unit and it's a CPU-integrated inference accelerator for Computer Vision and Deep Learning applications. The VPU device consist of following components: - Buttress - provides CPU to VPU integration, interrupt, frequency and power management. - Memory Management Unit (based on ARM MMU-600) - translates VPU to host DMA addresses, isolates user workloads. - RISC based microcontroller - executes firmware that provides job execution API for the kernel-mode driver - Neural Compute Subsystem (NCS) - does the actual work, provides Compute and Copy engines. - Network on Chip (NoC) - network fabric connecting all the components This driver supports VPU IP v2.7 integrated into Intel Meteor Lake client CPUs (14th generation). Module sources are at drivers/accel/ivpu and module name is "intel_vpu.ko". This patch includes only very besic functionality: - module, PCI device and IRQ initialization - register definitions and low level register manipulation functions - SET/GET_PARAM ioctls - power up without firmware
Unified · Split
| @@ -6894,6 +6894,15 @@ T: git https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/accel.git · 6893 unmodified lines | |||
| 6894 | F: Documentation/accel/ | 6894 | F: Documentation/accel/ |
| 6895 | F: drivers/accel/ | 6895 | F: drivers/accel/ |
| 6896 | 6896 | ||
| 6897 | DRM ACCEL DRIVERS FOR INTEL VPU | ||
| 6898 | M: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com> | ||
| 6899 | M: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com> | ||
| 6900 | L: dri-devel@lists.freedesktop.org | ||
| 6901 | S: Supported | ||
| 6902 | T: git git://anongit.freedesktop.org/drm/drm-misc | ||
| 6903 | F: drivers/accel/ivpu/ | ||
| 6904 | F: include/uapi/drm/ivpu_accel.h | ||
| 6905 | |||
| 6897 | DRM DRIVERS FOR ALLWINNER A10 | 6906 | DRM DRIVERS FOR ALLWINNER A10 |
| 6898 | M: Maxime Ripard <mripard@kernel.org> | 6907 | M: Maxime Ripard <mripard@kernel.org> |
| 6899 | M: Chen-Yu Tsai <wens@csie.org> | 6908 | M: Chen-Yu Tsai <wens@csie.org> |
| @@ -189,3 +189,4 @@ obj-$(CONFIG_COUNTER) += counter/ · 188 unmodified lines | |||
| 189 | obj-$(CONFIG_MOST) += most/ | 189 | obj-$(CONFIG_MOST) += most/ |
| 190 | obj-$(CONFIG_PECI) += peci/ | 190 | obj-$(CONFIG_PECI) += peci/ |
| 191 | obj-$(CONFIG_HTE) += hte/ | 191 | obj-$(CONFIG_HTE) += hte/ |
| 192 | obj-$(CONFIG_DRM_ACCEL) += accel/ | ||
| @@ -22,3 +22,5 @@ menuconfig DRM_ACCEL · 21 unmodified lines | |||
| 22 | major number than GPUs, and will be exposed to user-space using | 22 | major number than GPUs, and will be exposed to user-space using |
| 23 | different device files, called accel/accel* (in /dev, sysfs | 23 | different device files, called accel/accel* (in /dev, sysfs |
| 24 | and debugfs). | 24 | and debugfs). |
| 25 | |||
| 26 | source "drivers/accel/ivpu/Kconfig" | ||
| @@ -0,0 +1,3 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | |||
| 3 | obj-y += ivpu/ | ||
| @@ -0,0 +1,15 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | |||
| 3 | config DRM_ACCEL_IVPU | ||
| 4 | tristate "Intel VPU for Meteor Lake and newer" | ||
| 5 | depends on DRM_ACCEL | ||
| 6 | depends on X86_64 && !UML | ||
| 7 | depends on PCI && PCI_MSI | ||
| 8 | select FW_LOADER | ||
| 9 | select SHMEM | ||
| 10 | help | ||
| 11 | Choose this option if you have a system that has an 14th generation Intel CPU | ||
| 12 | or newer. VPU stands for Versatile Processing Unit and it's a CPU-integrated | ||
| 13 | inference accelerator for Computer Vision and Deep Learning applications. | ||
| 14 | |||
| 15 | If "M" is selected, the module will be called intel_vpu. | ||
| @@ -0,0 +1,8 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | # Copyright (C) 2023 Intel Corporation | ||
| 3 | |||
| 4 | intel_vpu-y := \ | ||
| 5 | ivpu_drv.o \ | ||
| 6 | ivpu_hw_mtl.o | ||
| 7 | |||
| 8 | obj-$(CONFIG_DRM_ACCEL_IVPU) += intel_vpu.o | ||
| @@ -0,0 +1,11 @@ | |||
| 1 | - Move to threaded_irqs to mitigate potential infinite loop in ivpu_ipc_irq_handler() | ||
| 2 | - Implement support for BLOB IDs | ||
| 3 | - Add debugfs support to improve debugging and testing | ||
| 4 | - Add tracing events for performance debugging | ||
| 5 | - Implement HW based scheduling support | ||
| 6 | - Use syncobjs for submit/sync | ||
| 7 | - Refactor IPC protocol to improve message latency | ||
| 8 | - Implement BO cache and MADVISE IOCTL | ||
| 9 | - Add support for user allocated buffers using prime import and dma-buf heaps | ||
| 10 | - Refactor struct ivpu_bo to use struct drm_gem_shmem_object | ||
| 11 | - Add driver/device documentation | ||
| @@ -0,0 +1,353 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2020-2023 Intel Corporation | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/firmware.h> | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/pci.h> | ||
| 9 | |||
| 10 | #include <drm/drm_accel.h> | ||
| 11 | #include <drm/drm_drv.h> | ||
| 12 | #include <drm/drm_file.h> | ||
| 13 | #include <drm/drm_gem.h> | ||
| 14 | #include <drm/drm_ioctl.h> | ||
| 15 | |||
| 16 | #include "ivpu_drv.h" | ||
| 17 | #include "ivpu_hw.h" | ||
| 18 | |||
| 19 | #ifndef DRIVER_VERSION_STR | ||
| 20 | #define DRIVER_VERSION_STR __stringify(DRM_IVPU_DRIVER_MAJOR) "." \ | ||
| 21 | __stringify(DRM_IVPU_DRIVER_MINOR) "." | ||
| 22 | #endif | ||
| 23 | |||
| 24 | static const struct drm_driver driver; | ||
| 25 | |||
| 26 | int ivpu_dbg_mask; | ||
| 27 | module_param_named(dbg_mask, ivpu_dbg_mask, int, 0644); | ||
| 28 | MODULE_PARM_DESC(dbg_mask, "Driver debug mask. See IVPU_DBG_* macros."); | ||
| 29 | |||
| 30 | u8 ivpu_pll_min_ratio; | ||
| 31 | module_param_named(pll_min_ratio, ivpu_pll_min_ratio, byte, 0644); | ||
| 32 | MODULE_PARM_DESC(pll_min_ratio, "Minimum PLL ratio used to set VPU frequency"); | ||
| 33 | |||
| 34 | u8 ivpu_pll_max_ratio = U8_MAX; | ||
| 35 | module_param_named(pll_max_ratio, ivpu_pll_max_ratio, byte, 0644); | ||
| 36 | MODULE_PARM_DESC(pll_max_ratio, "Maximum PLL ratio used to set VPU frequency"); | ||
| 37 | |||
| 38 | struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv) | ||
| 39 | { | ||
| 40 | kref_get(&file_priv->ref); | ||
| 41 | return file_priv; | ||
| 42 | } | ||
| 43 | |||
| 44 | static void file_priv_release(struct kref *ref) | ||
| 45 | { | ||
| 46 | struct ivpu_file_priv *file_priv = container_of(ref, struct ivpu_file_priv, ref); | ||
| 47 | |||
| 48 | kfree(file_priv); | ||
| 49 | } | ||
| 50 | |||
| 51 | void ivpu_file_priv_put(struct ivpu_file_priv **link) | ||
| 52 | { | ||
| 53 | struct ivpu_file_priv *file_priv = *link; | ||
| 54 | |||
| 55 | WARN_ON(!file_priv); | ||
| 56 | |||
| 57 | *link = NULL; | ||
| 58 | kref_put(&file_priv->ref, file_priv_release); | ||
| 59 | } | ||
| 60 | |||
| 61 | static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_file *file) | ||
| 62 | { | ||
| 63 | struct ivpu_file_priv *file_priv = file->driver_priv; | ||
| 64 | struct ivpu_device *vdev = file_priv->vdev; | ||
| 65 | struct pci_dev *pdev = to_pci_dev(vdev->drm.dev); | ||
| 66 | struct drm_ivpu_param *args = data; | ||
| 67 | int ret = 0; | ||
| 68 | |||
| 69 | switch (args->param) { | ||
| 70 | case DRM_IVPU_PARAM_DEVICE_ID: | ||
| 71 | args->value = pdev->device; | ||
| 72 | break; | ||
| 73 | case DRM_IVPU_PARAM_DEVICE_REVISION: | ||
| 74 | args->value = pdev->revision; | ||
| 75 | break; | ||
| 76 | case DRM_IVPU_PARAM_PLATFORM_TYPE: | ||
| 77 | args->value = vdev->platform; | ||
| 78 | break; | ||
| 79 | case DRM_IVPU_PARAM_CORE_CLOCK_RATE: | ||
| 80 | args->value = ivpu_hw_reg_pll_freq_get(vdev); | ||
| 81 | break; | ||
| 82 | case DRM_IVPU_PARAM_NUM_CONTEXTS: | ||
| 83 | args->value = ivpu_get_context_count(vdev); | ||
| 84 | break; | ||
| 85 | case DRM_IVPU_PARAM_CONTEXT_BASE_ADDRESS: | ||
| 86 | args->value = vdev->hw->ranges.user_low.start; | ||
| 87 | break; | ||
| 88 | case DRM_IVPU_PARAM_CONTEXT_PRIORITY: | ||
| 89 | args->value = file_priv->priority; | ||
| 90 | break; | ||
| 91 | default: | ||
| 92 | ret = -EINVAL; | ||
| 93 | break; | ||
| 94 | } | ||
| 95 | |||
| 96 | return ret; | ||
| 97 | } | ||
| 98 | |||
| 99 | static int ivpu_set_param_ioctl(struct drm_device *dev, void *data, struct drm_file *file) | ||
| 100 | { | ||
| 101 | struct ivpu_file_priv *file_priv = file->driver_priv; | ||
| 102 | struct drm_ivpu_param *args = data; | ||
| 103 | int ret = 0; | ||
| 104 | |||
| 105 | switch (args->param) { | ||
| 106 | case DRM_IVPU_PARAM_CONTEXT_PRIORITY: | ||
| 107 | if (args->value <= DRM_IVPU_CONTEXT_PRIORITY_REALTIME) | ||
| 108 | file_priv->priority = args->value; | ||
| 109 | else | ||
| 110 | ret = -EINVAL; | ||
| 111 | break; | ||
| 112 | default: | ||
| 113 | ret = -EINVAL; | ||
| 114 | } | ||
| 115 | |||
| 116 | return ret; | ||
| 117 | } | ||
| 118 | |||
| 119 | static int ivpu_open(struct drm_device *dev, struct drm_file *file) | ||
| 120 | { | ||
| 121 | struct ivpu_device *vdev = to_ivpu_device(dev); | ||
| 122 | struct ivpu_file_priv *file_priv; | ||
| 123 | |||
| 124 | file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); | ||
| 125 | if (!file_priv) | ||
| 126 | return -ENOMEM; | ||
| 127 | |||
| 128 | file_priv->vdev = vdev; | ||
| 129 | file_priv->priority = DRM_IVPU_CONTEXT_PRIORITY_NORMAL; | ||
| 130 | kref_init(&file_priv->ref); | ||
| 131 | |||
| 132 | file->driver_priv = file_priv; | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | static void ivpu_postclose(struct drm_device *dev, struct drm_file *file) | ||
| 137 | { | ||
| 138 | struct ivpu_file_priv *file_priv = file->driver_priv; | ||
| 139 | |||
| 140 | ivpu_file_priv_put(&file_priv); | ||
| 141 | } | ||
| 142 | |||
| 143 | static const struct drm_ioctl_desc ivpu_drm_ioctls[] = { | ||
| 144 | DRM_IOCTL_DEF_DRV(IVPU_GET_PARAM, ivpu_get_param_ioctl, 0), | ||
| 145 | DRM_IOCTL_DEF_DRV(IVPU_SET_PARAM, ivpu_set_param_ioctl, 0), | ||
| 146 | }; | ||
| 147 | |||
| 148 | int ivpu_shutdown(struct ivpu_device *vdev) | ||
| 149 | { | ||
| 150 | int ret; | ||
| 151 | |||
| 152 | ivpu_hw_irq_disable(vdev); | ||
| 153 | |||
| 154 | ret = ivpu_hw_power_down(vdev); | ||
| 155 | if (ret) | ||
| 156 | ivpu_warn(vdev, "Failed to power down HW: %d\n", ret); | ||
| 157 | |||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | static const struct file_operations ivpu_fops = { | ||
| 162 | .owner = THIS_MODULE, | ||
| 163 | .mmap = drm_gem_mmap, | ||
| 164 | DRM_ACCEL_FOPS, | ||
| 165 | }; | ||
| 166 | |||
| 167 | static const struct drm_driver driver = { | ||
| 168 | .driver_features = DRIVER_GEM | DRIVER_COMPUTE_ACCEL, | ||
| 169 | |||
| 170 | .open = ivpu_open, | ||
| 171 | .postclose = ivpu_postclose, | ||
| 172 | |||
| 173 | .ioctls = ivpu_drm_ioctls, | ||
| 174 | .num_ioctls = ARRAY_SIZE(ivpu_drm_ioctls), | ||
| 175 | .fops = &ivpu_fops, | ||
| 176 | |||
| 177 | .name = DRIVER_NAME, | ||
| 178 | .desc = DRIVER_DESC, | ||
| 179 | .date = DRIVER_DATE, | ||
| 180 | .major = DRM_IVPU_DRIVER_MAJOR, | ||
| 181 | .minor = DRM_IVPU_DRIVER_MINOR, | ||
| 182 | }; | ||
| 183 | |||
| 184 | static int ivpu_irq_init(struct ivpu_device *vdev) | ||
| 185 | { | ||
| 186 | struct pci_dev *pdev = to_pci_dev(vdev->drm.dev); | ||
| 187 | int ret; | ||
| 188 | |||
| 189 | ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI | PCI_IRQ_MSIX); | ||
| 190 | if (ret < 0) { | ||
| 191 | ivpu_err(vdev, "Failed to allocate a MSI IRQ: %d\n", ret); | ||
| 192 | return ret; | ||
| 193 | } | ||
| 194 | |||
| 195 | vdev->irq = pci_irq_vector(pdev, 0); | ||
| 196 | |||
| 197 | ret = devm_request_irq(vdev->drm.dev, vdev->irq, vdev->hw->ops->irq_handler, | ||
| 198 | IRQF_NO_AUTOEN, DRIVER_NAME, vdev); | ||
| 199 | if (ret) | ||
| 200 | ivpu_err(vdev, "Failed to request an IRQ %d\n", ret); | ||
| 201 | |||
| 202 | return ret; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int ivpu_pci_init(struct ivpu_device *vdev) | ||
| 206 | { | ||
| 207 | struct pci_dev *pdev = to_pci_dev(vdev->drm.dev); | ||
| 208 | struct resource *bar0 = &pdev->resource[0]; | ||
| 209 | struct resource *bar4 = &pdev->resource[4]; | ||
| 210 | int ret; | ||
| 211 | |||
| 212 | ivpu_dbg(vdev, MISC, "Mapping BAR0 (RegV) %pR\n", bar0); | ||
| 213 | vdev->regv = devm_ioremap_resource(vdev->drm.dev, bar0); | ||
| 214 | if (IS_ERR(vdev->regv)) { | ||
| 215 | ivpu_err(vdev, "Failed to map bar 0: %pe\n", vdev->regv); | ||
| 216 | return PTR_ERR(vdev->regv); | ||
| 217 | } | ||
| 218 | |||
| 219 | ivpu_dbg(vdev, MISC, "Mapping BAR4 (RegB) %pR\n", bar4); | ||
| 220 | vdev->regb = devm_ioremap_resource(vdev->drm.dev, bar4); | ||
| 221 | if (IS_ERR(vdev->regb)) { | ||
| 222 | ivpu_err(vdev, "Failed to map bar 4: %pe\n", vdev->regb); | ||
| 223 | return PTR_ERR(vdev->regb); | ||
| 224 | } | ||
| 225 | |||
| 226 | ret = dma_set_mask_and_coherent(vdev->drm.dev, DMA_BIT_MASK(38)); | ||
| 227 | if (ret) { | ||
| 228 | ivpu_err(vdev, "Failed to set DMA mask: %d\n", ret); | ||
| 229 | return ret; | ||
| 230 | } | ||
| 231 | |||
| 232 | /* Clear any pending errors */ | ||
| 233 | pcie_capability_clear_word(pdev, PCI_EXP_DEVSTA, 0x3f); | ||
| 234 | |||
| 235 | ret = pcim_enable_device(pdev); | ||
| 236 | if (ret) { | ||
| 237 | ivpu_err(vdev, "Failed to enable PCI device: %d\n", ret); | ||
| 238 | return ret; | ||
| 239 | } | ||
| 240 | |||
| 241 | pci_set_master(pdev); | ||
| 242 | |||
| 243 | return 0; | ||
| 244 | } | ||
| 245 | |||
| 246 | static int ivpu_dev_init(struct ivpu_device *vdev) | ||
| 247 | { | ||
| 248 | int ret; | ||
| 249 | |||
| 250 | vdev->hw = drmm_kzalloc(&vdev->drm, sizeof(*vdev->hw), GFP_KERNEL); | ||
| 251 | if (!vdev->hw) | ||
| 252 | return -ENOMEM; | ||
| 253 | |||
| 254 | vdev->hw->ops = &ivpu_hw_mtl_ops; | ||
| 255 | vdev->platform = IVPU_PLATFORM_INVALID; | ||
| 256 | vdev->context_xa_limit.min = IVPU_GLOBAL_CONTEXT_MMU_SSID + 1; | ||
| 257 | vdev->context_xa_limit.max = IVPU_CONTEXT_LIMIT; | ||
| 258 | xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC); | ||
| 259 | |||
| 260 | ret = ivpu_pci_init(vdev); | ||
| 261 | if (ret) { | ||
| 262 | ivpu_err(vdev, "Failed to initialize PCI device: %d\n", ret); | ||
| 263 | goto err_xa_destroy; | ||
| 264 | } | ||
| 265 | |||
| 266 | ret = ivpu_irq_init(vdev); | ||
| 267 | if (ret) { | ||
| 268 | ivpu_err(vdev, "Failed to initialize IRQs: %d\n", ret); | ||
| 269 | goto err_xa_destroy; | ||
| 270 | } | ||
| 271 | |||
| 272 | /* Init basic HW info based on buttress registers which are accessible before power up */ | ||
| 273 | ret = ivpu_hw_info_init(vdev); | ||
| 274 | if (ret) { | ||
| 275 | ivpu_err(vdev, "Failed to initialize HW info: %d\n", ret); | ||
| 276 | goto err_xa_destroy; | ||
| 277 | } | ||
| 278 | |||
| 279 | /* Power up early so the rest of init code can access VPU registers */ | ||
| 280 | ret = ivpu_hw_power_up(vdev); | ||
| 281 | if (ret) { | ||
| 282 | ivpu_err(vdev, "Failed to power up HW: %d\n", ret); | ||
| 283 | goto err_xa_destroy; | ||
| 284 | } | ||
| 285 | |||
| 286 | return 0; | ||
| 287 | |||
| 288 | err_xa_destroy: | ||
| 289 | xa_destroy(&vdev->context_xa); | ||
| 290 | return ret; | ||
| 291 | } | ||
| 292 | |||
| 293 | static void ivpu_dev_fini(struct ivpu_device *vdev) | ||
| 294 | { | ||
| 295 | ivpu_shutdown(vdev); | ||
| 296 | |||
| 297 | drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->context_xa)); | ||
| 298 | xa_destroy(&vdev->context_xa); | ||
| 299 | } | ||
| 300 | |||
| 301 | static struct pci_device_id ivpu_pci_ids[] = { | ||
| 302 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_MTL) }, | ||
| 303 | { } | ||
| 304 | }; | ||
| 305 | MODULE_DEVICE_TABLE(pci, ivpu_pci_ids); | ||
| 306 | |||
| 307 | static int ivpu_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
| 308 | { | ||
| 309 | struct ivpu_device *vdev; | ||
| 310 | int ret; | ||
| 311 | |||
| 312 | vdev = devm_drm_dev_alloc(&pdev->dev, &driver, struct ivpu_device, drm); | ||
| 313 | if (IS_ERR(vdev)) | ||
| 314 | return PTR_ERR(vdev); | ||
| 315 | |||
| 316 | pci_set_drvdata(pdev, vdev); | ||
| 317 | |||
| 318 | ret = ivpu_dev_init(vdev); | ||
| 319 | if (ret) { | ||
| 320 | dev_err(&pdev->dev, "Failed to initialize VPU device: %d\n", ret); | ||
| 321 | return ret; | ||
| 322 | } | ||
| 323 | |||
| 324 | ret = drm_dev_register(&vdev->drm, 0); | ||
| 325 | if (ret) { | ||
| 326 | dev_err(&pdev->dev, "Failed to register DRM device: %d\n", ret); | ||
| 327 | ivpu_dev_fini(vdev); | ||
| 328 | } | ||
| 329 | |||
| 330 | return ret; | ||
| 331 | } | ||
| 332 | |||
| 333 | static void ivpu_remove(struct pci_dev *pdev) | ||
| 334 | { | ||
| 335 | struct ivpu_device *vdev = pci_get_drvdata(pdev); | ||
| 336 | |||
| 337 | drm_dev_unregister(&vdev->drm); | ||
| 338 | ivpu_dev_fini(vdev); | ||
| 339 | } | ||
| 340 | |||
| 341 | static struct pci_driver ivpu_pci_driver = { | ||
| 342 | .name = KBUILD_MODNAME, | ||
| 343 | .id_table = ivpu_pci_ids, | ||
| 344 | .probe = ivpu_probe, | ||
| 345 | .remove = ivpu_remove, | ||
| 346 | }; | ||
| 347 | |||
| 348 | module_pci_driver(ivpu_pci_driver); | ||
| 349 | |||
| 350 | MODULE_AUTHOR("Intel Corporation"); | ||
| 351 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 352 | MODULE_LICENSE("GPL and additional rights"); | ||
| 353 | MODULE_VERSION(DRIVER_VERSION_STR); | ||
| @@ -0,0 +1,162 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2020-2023 Intel Corporation | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __IVPU_DRV_H__ | ||
| 7 | #define __IVPU_DRV_H__ | ||
| 8 | |||
| 9 | #include <drm/drm_device.h> | ||
| 10 | #include <drm/drm_managed.h> | ||
| 11 | #include <drm/drm_mm.h> | ||
| 12 | #include <drm/drm_print.h> | ||
| 13 | |||
| 14 | #include <linux/pci.h> | ||
| 15 | #include <linux/xarray.h> | ||
| 16 | #include <uapi/drm/ivpu_accel.h> | ||
| 17 | |||
| 18 | #define DRIVER_NAME "intel_vpu" | ||
| 19 | #define DRIVER_DESC "Driver for Intel Versatile Processing Unit (VPU)" | ||
| 20 | #define DRIVER_DATE "20230117" | ||
| 21 | |||
| 22 | #define PCI_DEVICE_ID_MTL 0x7d1d | ||
| 23 | |||
| 24 | #define IVPU_GLOBAL_CONTEXT_MMU_SSID 0 | ||
| 25 | #define IVPU_CONTEXT_LIMIT 64 | ||
| 26 | #define IVPU_NUM_ENGINES 2 | ||
| 27 | |||
| 28 | #define IVPU_PLATFORM_SILICON 0 | ||
| 29 | #define IVPU_PLATFORM_SIMICS 2 | ||
| 30 | #define IVPU_PLATFORM_FPGA 3 | ||
| 31 | #define IVPU_PLATFORM_INVALID 8 | ||
| 32 | |||
| 33 | #define IVPU_DBG_REG BIT(0) | ||
| 34 | #define IVPU_DBG_IRQ BIT(1) | ||
| 35 | #define IVPU_DBG_MMU BIT(2) | ||
| 36 | #define IVPU_DBG_FILE BIT(3) | ||
| 37 | #define IVPU_DBG_MISC BIT(4) | ||
| 38 | #define IVPU_DBG_FW_BOOT BIT(5) | ||
| 39 | #define IVPU_DBG_PM BIT(6) | ||
| 40 | #define IVPU_DBG_IPC BIT(7) | ||
| 41 | #define IVPU_DBG_BO BIT(8) | ||
| 42 | #define IVPU_DBG_JOB BIT(9) | ||
| 43 | #define IVPU_DBG_JSM BIT(10) | ||
| 44 | #define IVPU_DBG_KREF BIT(11) | ||
| 45 | #define IVPU_DBG_RPM BIT(12) | ||
| 46 | |||
| 47 | #define ivpu_err(vdev, fmt, ...) \ | ||
| 48 | drm_err(&(vdev)->drm, "%s(): " fmt, __func__, ##__VA_ARGS__) | ||
| 49 | |||
| 50 | #define ivpu_err_ratelimited(vdev, fmt, ...) \ | ||
| 51 | drm_err_ratelimited(&(vdev)->drm, "%s(): " fmt, __func__, ##__VA_ARGS__) | ||
| 52 | |||
| 53 | #define ivpu_warn(vdev, fmt, ...) \ | ||
| 54 | drm_warn(&(vdev)->drm, "%s(): " fmt, __func__, ##__VA_ARGS__) | ||
| 55 | |||
| 56 | #define ivpu_warn_ratelimited(vdev, fmt, ...) \ | ||
| 57 | drm_err_ratelimited(&(vdev)->drm, "%s(): " fmt, __func__, ##__VA_ARGS__) | ||
| 58 | |||
| 59 | #define ivpu_info(vdev, fmt, ...) drm_info(&(vdev)->drm, fmt, ##__VA_ARGS__) | ||
| 60 | |||
| 61 | #define ivpu_dbg(vdev, type, fmt, args...) do { \ | ||
| 62 | if (unlikely(IVPU_DBG_##type & ivpu_dbg_mask)) \ | ||
| 63 | dev_dbg((vdev)->drm.dev, "[%s] " fmt, #type, ##args); \ | ||
| 64 | } while (0) | ||
| 65 | |||
| 66 | #define IVPU_WA(wa_name) (vdev->wa.wa_name) | ||
| 67 | |||
| 68 | struct ivpu_wa_table { | ||
| 69 | bool punit_disabled; | ||
| 70 | bool clear_runtime_mem; | ||
| 71 | }; | ||
| 72 | |||
| 73 | struct ivpu_hw_info; | ||
| 74 | |||
| 75 | struct ivpu_device { | ||
| 76 | struct drm_device drm; | ||
| 77 | void __iomem *regb; | ||
| 78 | void __iomem *regv; | ||
| 79 | u32 platform; | ||
| 80 | u32 irq; | ||
| 81 | |||
| 82 | struct ivpu_wa_table wa; | ||
| 83 | struct ivpu_hw_info *hw; | ||
| 84 | |||
| 85 | struct xarray context_xa; | ||
| 86 | struct xa_limit context_xa_limit; | ||
| 87 | |||
| 88 | struct { | ||
| 89 | int boot; | ||
| 90 | int jsm; | ||
| 91 | int tdr; | ||
| 92 | int reschedule_suspend; | ||
| 93 | } timeout; | ||
| 94 | }; | ||
| 95 | |||
| 96 | /* | ||
| 97 | * file_priv has its own refcount (ref) that allows user space to close the fd | ||
| 98 | * without blocking even if VPU is still processing some jobs. | ||
| 99 | */ | ||
| 100 | struct ivpu_file_priv { | ||
| 101 | struct kref ref; | ||
| 102 | struct ivpu_device *vdev; | ||
| 103 | u32 priority; | ||
| 104 | }; | ||
| 105 | |||
| 106 | extern int ivpu_dbg_mask; | ||
| 107 | extern u8 ivpu_pll_min_ratio; | ||
| 108 | extern u8 ivpu_pll_max_ratio; | ||
| 109 | |||
| 110 | struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv); | ||
| 111 | void ivpu_file_priv_put(struct ivpu_file_priv **link); | ||
| 112 | int ivpu_shutdown(struct ivpu_device *vdev); | ||
| 113 | |||
| 114 | static inline bool ivpu_is_mtl(struct ivpu_device *vdev) | ||
| 115 | { | ||
| 116 | return to_pci_dev(vdev->drm.dev)->device == PCI_DEVICE_ID_MTL; | ||
| 117 | } | ||
| 118 | |||
| 119 | static inline u8 ivpu_revision(struct ivpu_device *vdev) | ||
| 120 | { | ||
| 121 | return to_pci_dev(vdev->drm.dev)->revision; | ||
| 122 | } | ||
| 123 | |||
| 124 | static inline u16 ivpu_device_id(struct ivpu_device *vdev) | ||
| 125 | { | ||
| 126 | return to_pci_dev(vdev->drm.dev)->device; | ||
| 127 | } | ||
| 128 | |||
| 129 | static inline struct ivpu_device *to_ivpu_device(struct drm_device *dev) | ||
| 130 | { | ||
| 131 | return container_of(dev, struct ivpu_device, drm); | ||
| 132 | } | ||
| 133 | |||
| 134 | static inline u32 ivpu_get_context_count(struct ivpu_device *vdev) | ||
| 135 | { | ||
| 136 | struct xa_limit ctx_limit = vdev->context_xa_limit; | ||
| 137 | |||
| 138 | return (ctx_limit.max - ctx_limit.min + 1); | ||
| 139 | } | ||
| 140 | |||
| 141 | static inline u32 ivpu_get_platform(struct ivpu_device *vdev) | ||
| 142 | { | ||
| 143 | WARN_ON_ONCE(vdev->platform == IVPU_PLATFORM_INVALID); | ||
| 144 | return vdev->platform; | ||
| 145 | } | ||
| 146 | |||
| 147 | static inline bool ivpu_is_silicon(struct ivpu_device *vdev) | ||
| 148 | { | ||
| 149 | return ivpu_get_platform(vdev) == IVPU_PLATFORM_SILICON; | ||
| 150 | } | ||
| 151 | |||
| 152 | static inline bool ivpu_is_simics(struct ivpu_device *vdev) | ||
| 153 | { | ||
| 154 | return ivpu_get_platform(vdev) == IVPU_PLATFORM_SIMICS; | ||
| 155 | } | ||
| 156 | |||
| 157 | static inline bool ivpu_is_fpga(struct ivpu_device *vdev) | ||
| 158 | { | ||
| 159 | return ivpu_get_platform(vdev) == IVPU_PLATFORM_FPGA; | ||
| 160 | } | ||
| 161 | |||
| 162 | #endif /* __IVPU_DRV_H__ */ | ||
| @@ -0,0 +1,170 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2020-2023 Intel Corporation | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __IVPU_HW_H__ | ||
| 7 | #define __IVPU_HW_H__ | ||
| 8 | |||
| 9 | #include "ivpu_drv.h" | ||
| 10 | |||
| 11 | struct ivpu_hw_ops { | ||
| 12 | int (*info_init)(struct ivpu_device *vdev); | ||
| 13 | int (*power_up)(struct ivpu_device *vdev); | ||
| 14 | int (*boot_fw)(struct ivpu_device *vdev); | ||
| 15 | int (*power_down)(struct ivpu_device *vdev); | ||
| 16 | bool (*is_idle)(struct ivpu_device *vdev); | ||
| 17 | void (*wdt_disable)(struct ivpu_device *vdev); | ||
| 18 | void (*diagnose_failure)(struct ivpu_device *vdev); | ||
| 19 | u32 (*reg_pll_freq_get)(struct ivpu_device *vdev); | ||
| 20 | u32 (*reg_telemetry_offset_get)(struct ivpu_device *vdev); | ||
| 21 | u32 (*reg_telemetry_size_get)(struct ivpu_device *vdev); | ||
| 22 | u32 (*reg_telemetry_enable_get)(struct ivpu_device *vdev); | ||
| 23 | void (*reg_db_set)(struct ivpu_device *vdev, u32 db_id); | ||
| 24 | u32 (*reg_ipc_rx_addr_get)(struct ivpu_device *vdev); | ||
| 25 | u32 (*reg_ipc_rx_count_get)(struct ivpu_device *vdev); | ||
| 26 | void (*reg_ipc_tx_set)(struct ivpu_device *vdev, u32 vpu_addr); | ||
| 27 | void (*irq_clear)(struct ivpu_device *vdev); | ||
| 28 | void (*irq_enable)(struct ivpu_device *vdev); | ||
| 29 | void (*irq_disable)(struct ivpu_device *vdev); | ||
| 30 | irqreturn_t (*irq_handler)(int irq, void *ptr); | ||
| 31 | }; | ||
| 32 | |||
| 33 | struct ivpu_addr_range { | ||
| 34 | resource_size_t start; | ||
| 35 | resource_size_t end; | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct ivpu_hw_info { | ||
| 39 | const struct ivpu_hw_ops *ops; | ||
| 40 | struct { | ||
| 41 | struct ivpu_addr_range global_low; | ||
| 42 | struct ivpu_addr_range global_high; | ||
| 43 | struct ivpu_addr_range user_low; | ||
| 44 | struct ivpu_addr_range user_high; | ||
| 45 | struct ivpu_addr_range global_aliased_pio; | ||
| 46 | } ranges; | ||
| 47 | struct { | ||
| 48 | u8 min_ratio; | ||
| 49 | u8 max_ratio; | ||
| 50 | /* | ||
| 51 | * Pll ratio for the efficiency frequency. The VPU has optimum | ||
| 52 | * performance to power ratio at this frequency. | ||
| 53 | */ | ||
| 54 | u8 pn_ratio; | ||
| 55 | u32 profiling_freq; | ||
| 56 | } pll; | ||
| 57 | u32 tile_fuse; | ||
| 58 | u32 sku; | ||
| 59 | u16 config; | ||
| 60 | }; | ||
| 61 | |||
| 62 | extern const struct ivpu_hw_ops ivpu_hw_mtl_ops; | ||
| 63 | |||
| 64 | static inline int ivpu_hw_info_init(struct ivpu_device *vdev) | ||
| 65 | { | ||
| 66 | return vdev->hw->ops->info_init(vdev); | ||
| 67 | }; | ||
| 68 | |||
| 69 | static inline int ivpu_hw_power_up(struct ivpu_device *vdev) | ||
| 70 | { | ||
| 71 | ivpu_dbg(vdev, PM, "HW power up\n"); | ||
| 72 | |||
| 73 | return vdev->hw->ops->power_up(vdev); | ||
| 74 | }; | ||
| 75 | |||
| 76 | static inline int ivpu_hw_boot_fw(struct ivpu_device *vdev) | ||
| 77 | { | ||
| 78 | return vdev->hw->ops->boot_fw(vdev); | ||
| 79 | }; | ||
| 80 | |||
| 81 | static inline bool ivpu_hw_is_idle(struct ivpu_device *vdev) | ||
| 82 | { | ||
| 83 | return vdev->hw->ops->is_idle(vdev); | ||
| 84 | }; | ||
| 85 | |||
| 86 | static inline int ivpu_hw_power_down(struct ivpu_device *vdev) | ||
| 87 | { | ||
| 88 | ivpu_dbg(vdev, PM, "HW power down\n"); | ||
| 89 | |||
| 90 | return vdev->hw->ops->power_down(vdev); | ||
| 91 | }; | ||
| 92 | |||
| 93 | static inline void ivpu_hw_wdt_disable(struct ivpu_device *vdev) | ||
| 94 | { | ||
| 95 | vdev->hw->ops->wdt_disable(vdev); | ||
| 96 | }; | ||
| 97 | |||
| 98 | /* Register indirect accesses */ | ||
| 99 | static inline u32 ivpu_hw_reg_pll_freq_get(struct ivpu_device *vdev) | ||
| 100 | { | ||
| 101 | return vdev->hw->ops->reg_pll_freq_get(vdev); | ||
| 102 | }; | ||
| 103 | |||
| 104 | static inline u32 ivpu_hw_reg_telemetry_offset_get(struct ivpu_device *vdev) | ||
| 105 | { | ||
| 106 | return vdev->hw->ops->reg_telemetry_offset_get(vdev); | ||
| 107 | }; | ||
| 108 | |||
| 109 | static inline u32 ivpu_hw_reg_telemetry_size_get(struct ivpu_device *vdev) | ||
| 110 | { | ||
| 111 | return vdev->hw->ops->reg_telemetry_size_get(vdev); | ||
| 112 | }; | ||
| 113 | |||
| 114 | static inline u32 ivpu_hw_reg_telemetry_enable_get(struct ivpu_device *vdev) | ||
| 115 | { | ||
| 116 | return vdev->hw->ops->reg_telemetry_enable_get(vdev); | ||
| 117 | }; | ||
| 118 | |||
| 119 | static inline void ivpu_hw_reg_db_set(struct ivpu_device *vdev, u32 db_id) | ||
| 120 | { | ||
| 121 | vdev->hw->ops->reg_db_set(vdev, db_id); | ||
| 122 | }; | ||
| 123 | |||
| 124 | static inline u32 ivpu_hw_reg_ipc_rx_addr_get(struct ivpu_device *vdev) | ||
| 125 | { | ||
| 126 | return vdev->hw->ops->reg_ipc_rx_addr_get(vdev); | ||
| 127 | }; | ||
| 128 | |||
| 129 | static inline u32 ivpu_hw_reg_ipc_rx_count_get(struct ivpu_device *vdev) | ||
| 130 | { | ||
| 131 | return vdev->hw->ops->reg_ipc_rx_count_get(vdev); | ||
| 132 | }; | ||
| 133 | |||
| 134 | static inline void ivpu_hw_reg_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr) | ||
| 135 | { | ||
| 136 | vdev->hw->ops->reg_ipc_tx_set(vdev, vpu_addr); | ||
| 137 | }; | ||
| 138 | |||
| 139 | static inline void ivpu_hw_irq_clear(struct ivpu_device *vdev) | ||
| 140 | { | ||
| 141 | vdev->hw->ops->irq_clear(vdev); | ||
| 142 | }; | ||
| 143 | |||
| 144 | static inline void ivpu_hw_irq_enable(struct ivpu_device *vdev) | ||
| 145 | { | ||
| 146 | vdev->hw->ops->irq_enable(vdev); | ||
| 147 | }; | ||
| 148 | |||
| 149 | static inline void ivpu_hw_irq_disable(struct ivpu_device *vdev) | ||
| 150 | { | ||
| 151 | vdev->hw->ops->irq_disable(vdev); | ||
| 152 | }; | ||
| 153 | |||
| 154 | static inline void ivpu_hw_init_range(struct ivpu_addr_range *range, u64 start, u64 size) | ||
| 155 | { | ||
| 156 | range->start = start; | ||
| 157 | range->end = start + size; | ||
| 158 | } | ||
| 159 | |||
| 160 | static inline u64 ivpu_hw_range_size(const struct ivpu_addr_range *range) | ||
| 161 | { | ||
| 162 | return range->end - range->start; | ||
| 163 | } | ||
| 164 | |||
| 165 | static inline void ivpu_hw_diagnose_failure(struct ivpu_device *vdev) | ||
| 166 | { | ||
| 167 | vdev->hw->ops->diagnose_failure(vdev); | ||
| 168 | } | ||
| 169 | |||
| 170 | #endif /* __IVPU_HW_H__ */ | ||
| @@ -0,0 +1,1048 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2020-2023 Intel Corporation | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include "ivpu_drv.h" | ||
| 7 | #include "ivpu_hw_mtl_reg.h" | ||
| 8 | #include "ivpu_hw_reg_io.h" | ||
| 9 | #include "ivpu_hw.h" | ||
| 10 | |||
| 11 | #define TILE_FUSE_ENABLE_BOTH 0x0 | ||
| 12 | #define TILE_FUSE_ENABLE_UPPER 0x1 | ||
| 13 | #define TILE_FUSE_ENABLE_LOWER 0x2 | ||
| 14 | |||
| 15 | #define TILE_SKU_BOTH_MTL 0x3630 | ||
| 16 | #define TILE_SKU_LOWER_MTL 0x3631 | ||
| 17 | #define TILE_SKU_UPPER_MTL 0x3632 | ||
| 18 | |||
| 19 | /* Work point configuration values */ | ||
| 20 | #define WP_CONFIG_1_TILE_5_3_RATIO 0x0101 | ||
| 21 | #define WP_CONFIG_1_TILE_4_3_RATIO 0x0102 | ||
| 22 | #define WP_CONFIG_2_TILE_5_3_RATIO 0x0201 | ||
| 23 | #define WP_CONFIG_2_TILE_4_3_RATIO 0x0202 | ||
| 24 | #define WP_CONFIG_0_TILE_PLL_OFF 0x0000 | ||
| 25 | |||
| 26 | #define PLL_REF_CLK_FREQ (50 * 1000000) | ||
| 27 | #define PLL_SIMULATION_FREQ (10 * 1000000) | ||
| 28 | #define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ) | ||
| 29 | #define PLL_DEFAULT_EPP_VALUE 0x80 | ||
| 30 | |||
| 31 | #define TIM_SAFE_ENABLE 0xf1d0dead | ||
| 32 | #define TIM_WATCHDOG_RESET_VALUE 0xffffffff | ||
| 33 | |||
| 34 | #define TIMEOUT_US (150 * USEC_PER_MSEC) | ||
| 35 | #define PWR_ISLAND_STATUS_TIMEOUT_US (5 * USEC_PER_MSEC) | ||
| 36 | #define PLL_TIMEOUT_US (1500 * USEC_PER_MSEC) | ||
| 37 | #define IDLE_TIMEOUT_US (500 * USEC_PER_MSEC) | ||
| 38 | |||
| 39 | #define ICB_0_IRQ_MASK ((REG_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT)) | \ | ||
| 40 | (REG_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, MMU_IRQ_0_INT)) | \ | ||
| 41 | (REG_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT)) | \ | ||
| 42 | (REG_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, MMU_IRQ_2_INT)) | \ | ||
| 43 | (REG_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT)) | \ | ||
| 44 | (REG_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT)) | \ | ||
| 45 | (REG_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT))) | ||
| 46 | |||
| 47 | #define ICB_1_IRQ_MASK ((REG_FLD(MTL_VPU_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_2_INT)) | \ | ||
| 48 | (REG_FLD(MTL_VPU_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_3_INT)) | \ | ||
| 49 | (REG_FLD(MTL_VPU_HOST_SS_ICB_STATUS_1, CPU_INT_REDIRECT_4_INT))) | ||
| 50 | |||
| 51 | #define ICB_0_1_IRQ_MASK ((((u64)ICB_1_IRQ_MASK) << 32) | ICB_0_IRQ_MASK) | ||
| 52 | |||
| 53 | #define BUTTRESS_IRQ_MASK ((REG_FLD(MTL_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE)) | \ | ||
| 54 | (REG_FLD(MTL_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \ | ||
| 55 | (REG_FLD(MTL_BUTTRESS_INTERRUPT_STAT, UFI_ERR))) | ||
| 56 | |||
| 57 | #define BUTTRESS_IRQ_ENABLE_MASK ((u32)~BUTTRESS_IRQ_MASK) | ||
| 58 | #define BUTTRESS_IRQ_DISABLE_MASK ((u32)-1) | ||
| 59 | |||
| 60 | #define ITF_FIREWALL_VIOLATION_MASK ((REG_FLD(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, CSS_ROM_CMX)) | \ | ||
| 61 | (REG_FLD(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, CSS_DBG)) | \ | ||
| 62 | (REG_FLD(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, CSS_CTRL)) | \ | ||
| 63 | (REG_FLD(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, DEC400)) | \ | ||
| 64 | (REG_FLD(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, MSS_NCE)) | \ | ||
| 65 | (REG_FLD(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI)) | \ | ||
| 66 | (REG_FLD(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, MSS_MBI_CMX))) | ||
| 67 | |||
| 68 | static char *ivpu_platform_to_str(u32 platform) | ||
| 69 | { | ||
| 70 | switch (platform) { | ||
| 71 | case IVPU_PLATFORM_SILICON: | ||
| 72 | return "IVPU_PLATFORM_SILICON"; | ||
| 73 | case IVPU_PLATFORM_SIMICS: | ||
| 74 | return "IVPU_PLATFORM_SIMICS"; | ||
| 75 | case IVPU_PLATFORM_FPGA: | ||
| 76 | return "IVPU_PLATFORM_FPGA"; | ||
| 77 | default: | ||
| 78 | return "Invalid platform"; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | static void ivpu_hw_read_platform(struct ivpu_device *vdev) | ||
| 83 | { | ||
| 84 | u32 gen_ctrl = REGV_RD32(MTL_VPU_HOST_SS_GEN_CTRL); | ||
| 85 | u32 platform = REG_GET_FLD(MTL_VPU_HOST_SS_GEN_CTRL, PS, gen_ctrl); | ||
| 86 | |||
| 87 | if (platform == IVPU_PLATFORM_SIMICS || platform == IVPU_PLATFORM_FPGA) | ||
| 88 | vdev->platform = platform; | ||
| 89 | else | ||
| 90 | vdev->platform = IVPU_PLATFORM_SILICON; | ||
| 91 | |||
| 92 | ivpu_dbg(vdev, MISC, "Platform type: %s (%d)\n", | ||
| 93 | ivpu_platform_to_str(vdev->platform), vdev->platform); | ||
| 94 | } | ||
| 95 | |||
| 96 | static void ivpu_hw_wa_init(struct ivpu_device *vdev) | ||
| 97 | { | ||
| 98 | vdev->wa.punit_disabled = ivpu_is_fpga(vdev); | ||
| 99 | vdev->wa.clear_runtime_mem = false; | ||
| 100 | } | ||
| 101 | |||
| 102 | static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) | ||
| 103 | { | ||
| 104 | if (ivpu_is_simics(vdev) || ivpu_is_fpga(vdev)) { | ||
| 105 | vdev->timeout.boot = 100000; | ||
| 106 | vdev->timeout.jsm = 50000; | ||
| 107 | vdev->timeout.tdr = 2000000; | ||
| 108 | vdev->timeout.reschedule_suspend = 1000; | ||
| 109 | } else { | ||
| 110 | vdev->timeout.boot = 1000; | ||
| 111 | vdev->timeout.jsm = 500; | ||
| 112 | vdev->timeout.tdr = 2000; | ||
| 113 | vdev->timeout.reschedule_suspend = 10; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | static int ivpu_pll_wait_for_cmd_send(struct ivpu_device *vdev) | ||
| 118 | { | ||
| 119 | return REGB_POLL_FLD(MTL_BUTTRESS_WP_REQ_CMD, SEND, 0, PLL_TIMEOUT_US); | ||
| 120 | } | ||
| 121 | |||
| 122 | /* Send KMD initiated workpoint change */ | ||
| 123 | static int ivpu_pll_cmd_send(struct ivpu_device *vdev, u16 min_ratio, u16 max_ratio, | ||
| 124 | u16 target_ratio, u16 config) | ||
| 125 | { | ||
| 126 | int ret; | ||
| 127 | u32 val; | ||
| 128 | |||
| 129 | ret = ivpu_pll_wait_for_cmd_send(vdev); | ||
| 130 | if (ret) { | ||
| 131 | ivpu_err(vdev, "Failed to sync before WP request: %d\n", ret); | ||
| 132 | return ret; | ||
| 133 | } | ||
| 134 | |||
| 135 | val = REGB_RD32(MTL_BUTTRESS_WP_REQ_PAYLOAD0); | ||
| 136 | val = REG_SET_FLD_NUM(MTL_BUTTRESS_WP_REQ_PAYLOAD0, MIN_RATIO, min_ratio, val); | ||
| 137 | val = REG_SET_FLD_NUM(MTL_BUTTRESS_WP_REQ_PAYLOAD0, MAX_RATIO, max_ratio, val); | ||
| 138 | REGB_WR32(MTL_BUTTRESS_WP_REQ_PAYLOAD0, val); | ||
| 139 | |||
| 140 | val = REGB_RD32(MTL_BUTTRESS_WP_REQ_PAYLOAD1); | ||
| 141 | val = REG_SET_FLD_NUM(MTL_BUTTRESS_WP_REQ_PAYLOAD1, TARGET_RATIO, target_ratio, val); | ||
| 142 | val = REG_SET_FLD_NUM(MTL_BUTTRESS_WP_REQ_PAYLOAD1, EPP, PLL_DEFAULT_EPP_VALUE, val); | ||
| 143 | REGB_WR32(MTL_BUTTRESS_WP_REQ_PAYLOAD1, val); | ||
| 144 | |||
| 145 | val = REGB_RD32(MTL_BUTTRESS_WP_REQ_PAYLOAD2); | ||
| 146 | val = REG_SET_FLD_NUM(MTL_BUTTRESS_WP_REQ_PAYLOAD2, CONFIG, config, val); | ||
| 147 | REGB_WR32(MTL_BUTTRESS_WP_REQ_PAYLOAD2, val); | ||
| 148 | |||
| 149 | val = REGB_RD32(MTL_BUTTRESS_WP_REQ_CMD); | ||
| 150 | val = REG_SET_FLD(MTL_BUTTRESS_WP_REQ_CMD, SEND, val); | ||
| 151 | REGB_WR32(MTL_BUTTRESS_WP_REQ_CMD, val); | ||
| 152 | |||
| 153 | ret = ivpu_pll_wait_for_cmd_send(vdev); | ||
| 154 | if (ret) | ||
| 155 | ivpu_err(vdev, "Failed to sync after WP request: %d\n", ret); | ||
| 156 | |||
| 157 | return ret; | ||
| 158 | } | ||
| 159 | |||
| 160 | static int ivpu_pll_wait_for_lock(struct ivpu_device *vdev, bool enable) | ||
| 161 | { | ||
| 162 | u32 exp_val = enable ? 0x1 : 0x0; | ||
| 163 | |||
| 164 | if (IVPU_WA(punit_disabled)) | ||
| 165 | return 0; | ||
| 166 | |||
| 167 | return REGB_POLL_FLD(MTL_BUTTRESS_PLL_STATUS, LOCK, exp_val, PLL_TIMEOUT_US); | ||
| 168 | } | ||
| 169 | |||
| 170 | static int ivpu_pll_wait_for_status_ready(struct ivpu_device *vdev) | ||
| 171 | { | ||
| 172 | if (IVPU_WA(punit_disabled)) | ||
| 173 | return 0; | ||
| 174 | |||
| 175 | return REGB_POLL_FLD(MTL_BUTTRESS_VPU_STATUS, READY, 1, PLL_TIMEOUT_US); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void ivpu_pll_init_frequency_ratios(struct ivpu_device *vdev) | ||
| 179 | { | ||
| 180 | struct ivpu_hw_info *hw = vdev->hw; | ||
| 181 | u8 fuse_min_ratio, fuse_max_ratio, fuse_pn_ratio; | ||
| 182 | u32 fmin_fuse, fmax_fuse; | ||
| 183 | |||
| 184 | fmin_fuse = REGB_RD32(MTL_BUTTRESS_FMIN_FUSE); | ||
| 185 | fuse_min_ratio = REG_GET_FLD(MTL_BUTTRESS_FMIN_FUSE, MIN_RATIO, fmin_fuse); | ||
| 186 | fuse_pn_ratio = REG_GET_FLD(MTL_BUTTRESS_FMIN_FUSE, PN_RATIO, fmin_fuse); | ||
| 187 | |||
| 188 | fmax_fuse = REGB_RD32(MTL_BUTTRESS_FMAX_FUSE); | ||
| 189 | fuse_max_ratio = REG_GET_FLD(MTL_BUTTRESS_FMAX_FUSE, MAX_RATIO, fmax_fuse); | ||
| 190 | |||
| 191 | hw->pll.min_ratio = clamp_t(u8, ivpu_pll_min_ratio, fuse_min_ratio, fuse_max_ratio); | ||
| 192 | hw->pll.max_ratio = clamp_t(u8, ivpu_pll_max_ratio, hw->pll.min_ratio, fuse_max_ratio); | ||
| 193 | hw->pll.pn_ratio = clamp_t(u8, fuse_pn_ratio, hw->pll.min_ratio, hw->pll.max_ratio); | ||
| 194 | } | ||
| 195 | |||
| 196 | static int ivpu_pll_drive(struct ivpu_device *vdev, bool enable) | ||
| 197 | { | ||
| 198 | struct ivpu_hw_info *hw = vdev->hw; | ||
| 199 | u16 target_ratio; | ||
| 200 | u16 config; | ||
| 201 | int ret; | ||
| 202 | |||
| 203 | if (IVPU_WA(punit_disabled)) { | ||
| 204 | ivpu_dbg(vdev, PM, "Skipping PLL request on %s\n", | ||
| 205 | ivpu_platform_to_str(vdev->platform)); | ||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | if (enable) { | ||
| 210 | target_ratio = hw->pll.pn_ratio; | ||
| 211 | config = hw->config; | ||
| 212 | } else { | ||
| 213 | target_ratio = 0; | ||
| 214 | config = 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | ivpu_dbg(vdev, PM, "PLL workpoint request: %d Hz\n", PLL_RATIO_TO_FREQ(target_ratio)); | ||
| 218 | |||
| 219 | ret = ivpu_pll_cmd_send(vdev, hw->pll.min_ratio, hw->pll.max_ratio, target_ratio, config); | ||
| 220 | if (ret) { | ||
| 221 | ivpu_err(vdev, "Failed to send PLL workpoint request: %d\n", ret); | ||
| 222 | return ret; | ||
| 223 | } | ||
| 224 | |||
| 225 | ret = ivpu_pll_wait_for_lock(vdev, enable); | ||
| 226 | if (ret) { | ||
| 227 | ivpu_err(vdev, "Timed out waiting for PLL lock\n"); | ||
| 228 | return ret; | ||
| 229 | } | ||
| 230 | |||
| 231 | if (enable) { | ||
| 232 | ret = ivpu_pll_wait_for_status_ready(vdev); | ||
| 233 | if (ret) { | ||
| 234 | ivpu_err(vdev, "Timed out waiting for PLL ready status\n"); | ||
| 235 | return ret; | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | static int ivpu_pll_enable(struct ivpu_device *vdev) | ||
| 243 | { | ||
| 244 | return ivpu_pll_drive(vdev, true); | ||
| 245 | } | ||
| 246 | |||
| 247 | static int ivpu_pll_disable(struct ivpu_device *vdev) | ||
| 248 | { | ||
| 249 | return ivpu_pll_drive(vdev, false); | ||
| 250 | } | ||
| 251 | |||
| 252 | static void ivpu_boot_host_ss_rst_clr_assert(struct ivpu_device *vdev) | ||
| 253 | { | ||
| 254 | u32 val = REGV_RD32(MTL_VPU_HOST_SS_CPR_RST_CLR); | ||
| 255 | |||
| 256 | val = REG_SET_FLD(MTL_VPU_HOST_SS_CPR_RST_CLR, TOP_NOC, val); | ||
| 257 | val = REG_SET_FLD(MTL_VPU_HOST_SS_CPR_RST_CLR, DSS_MAS, val); | ||
| 258 | val = REG_SET_FLD(MTL_VPU_HOST_SS_CPR_RST_CLR, MSS_MAS, val); | ||
| 259 | |||
| 260 | REGV_WR32(MTL_VPU_HOST_SS_CPR_RST_CLR, val); | ||
| 261 | } | ||
| 262 | |||
| 263 | static void ivpu_boot_host_ss_rst_drive(struct ivpu_device *vdev, bool enable) | ||
| 264 | { | ||
| 265 | u32 val = REGV_RD32(MTL_VPU_HOST_SS_CPR_RST_SET); | ||
| 266 | |||
| 267 | if (enable) { | ||
| 268 | val = REG_SET_FLD(MTL_VPU_HOST_SS_CPR_RST_SET, TOP_NOC, val); | ||
| 269 | val = REG_SET_FLD(MTL_VPU_HOST_SS_CPR_RST_SET, DSS_MAS, val); | ||
| 270 | val = REG_SET_FLD(MTL_VPU_HOST_SS_CPR_RST_SET, MSS_MAS, val); | ||
| 271 | } else { | ||
| 272 | val = REG_CLR_FLD(MTL_VPU_HOST_SS_CPR_RST_SET, TOP_NOC, val); | ||
| 273 | val = REG_CLR_FLD(MTL_VPU_HOST_SS_CPR_RST_SET, DSS_MAS, val); | ||
| 274 | val = REG_CLR_FLD(MTL_VPU_HOST_SS_CPR_RST_SET, MSS_MAS, val); | ||
| 275 | } | ||
| 276 | |||
| 277 | REGV_WR32(MTL_VPU_HOST_SS_CPR_RST_SET, val); | ||
| 278 | } | ||
| 279 | |||
| 280 | static void ivpu_boot_host_ss_clk_drive(struct ivpu_device *vdev, bool enable) | ||
| 281 | { | ||
| 282 | u32 val = REGV_RD32(MTL_VPU_HOST_SS_CPR_CLK_SET); | ||
| 283 | |||
| 284 | if (enable) { | ||
| 285 | val = REG_SET_FLD(MTL_VPU_HOST_SS_CPR_CLK_SET, TOP_NOC, val); | ||
| 286 | val = REG_SET_FLD(MTL_VPU_HOST_SS_CPR_CLK_SET, DSS_MAS, val); | ||
| 287 | val = REG_SET_FLD(MTL_VPU_HOST_SS_CPR_CLK_SET, MSS_MAS, val); | ||
| 288 | } else { | ||
| 289 | val = REG_CLR_FLD(MTL_VPU_HOST_SS_CPR_CLK_SET, TOP_NOC, val); | ||
| 290 | val = REG_CLR_FLD(MTL_VPU_HOST_SS_CPR_CLK_SET, DSS_MAS, val); | ||
| 291 | val = REG_CLR_FLD(MTL_VPU_HOST_SS_CPR_CLK_SET, MSS_MAS, val); | ||
| 292 | } | ||
| 293 | |||
| 294 | REGV_WR32(MTL_VPU_HOST_SS_CPR_CLK_SET, val); | ||
| 295 | } | ||
| 296 | |||
| 297 | static int ivpu_boot_noc_qreqn_check(struct ivpu_device *vdev, u32 exp_val) | ||
| 298 | { | ||
| 299 | u32 val = REGV_RD32(MTL_VPU_HOST_SS_NOC_QREQN); | ||
| 300 | |||
| 301 | if (!REG_TEST_FLD_NUM(MTL_VPU_HOST_SS_NOC_QREQN, TOP_SOCMMIO, exp_val, val)) | ||
| 302 | return -EIO; | ||
| 303 | |||
| 304 | return 0; | ||
| 305 | } | ||
| 306 | |||
| 307 | static int ivpu_boot_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) | ||
| 308 | { | ||
| 309 | u32 val = REGV_RD32(MTL_VPU_HOST_SS_NOC_QACCEPTN); | ||
| 310 | |||
| 311 | if (!REG_TEST_FLD_NUM(MTL_VPU_HOST_SS_NOC_QACCEPTN, TOP_SOCMMIO, exp_val, val)) | ||
| 312 | return -EIO; | ||
| 313 | |||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | static int ivpu_boot_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) | ||
| 318 | { | ||
| 319 | u32 val = REGV_RD32(MTL_VPU_HOST_SS_NOC_QDENY); | ||
| 320 | |||
| 321 | if (!REG_TEST_FLD_NUM(MTL_VPU_HOST_SS_NOC_QDENY, TOP_SOCMMIO, exp_val, val)) | ||
| 322 | return -EIO; | ||
| 323 | |||
| 324 | return 0; | ||
| 325 | } | ||
| 326 | |||
| 327 | static int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val) | ||
| 328 | { | ||
| 329 | u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QREQN); | ||
| 330 | |||
| 331 | if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) || | ||
| 332 | !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val)) | ||
| 333 | return -EIO; | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | static int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) | ||
| 339 | { | ||
| 340 | u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QACCEPTN); | ||
| 341 | |||
| 342 | if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) || | ||
| 343 | !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val)) | ||
| 344 | return -EIO; | ||
| 345 | |||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | |||
| 349 | static int ivpu_boot_top_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) | ||
| 350 | { | ||
| 351 | u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QDENY); | ||
| 352 | |||
| 353 | if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) || | ||
| 354 | !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val)) | ||
| 355 | return -EIO; | ||
| 356 | |||
| 357 | return 0; | ||
| 358 | } | ||
| 359 | |||
| 360 | static int ivpu_boot_host_ss_configure(struct ivpu_device *vdev) | ||
| 361 | { | ||
| 362 | ivpu_boot_host_ss_rst_clr_assert(vdev); | ||
| 363 | |||
| 364 | return ivpu_boot_noc_qreqn_check(vdev, 0x0); | ||
| 365 | } | ||
| 366 | |||
| 367 | static void ivpu_boot_vpu_idle_gen_disable(struct ivpu_device *vdev) | ||
| 368 | { | ||
| 369 | REGV_WR32(MTL_VPU_HOST_SS_AON_VPU_IDLE_GEN, 0x0); | ||
| 370 | } | ||
| 371 | |||
| 372 | static int ivpu_boot_host_ss_axi_drive(struct ivpu_device *vdev, bool enable) | ||
| 373 | { | ||
| 374 | int ret; | ||
| 375 | u32 val; | ||
| 376 | |||
| 377 | val = REGV_RD32(MTL_VPU_HOST_SS_NOC_QREQN); | ||
| 378 | if (enable) | ||
| 379 | val = REG_SET_FLD(MTL_VPU_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); | ||
| 380 | else | ||
| 381 | val = REG_CLR_FLD(MTL_VPU_HOST_SS_NOC_QREQN, TOP_SOCMMIO, val); | ||
| 382 | REGV_WR32(MTL_VPU_HOST_SS_NOC_QREQN, val); | ||
| 383 | |||
| 384 | ret = ivpu_boot_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); | ||
| 385 | if (ret) { | ||
| 386 | ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); | ||
| 387 | return ret; | ||
| 388 | } | ||
| 389 | |||
| 390 | ret = ivpu_boot_noc_qdeny_check(vdev, 0x0); | ||
| 391 | if (ret) | ||
| 392 | ivpu_err(vdev, "Failed qdeny check: %d\n", ret); | ||
| 393 | |||
| 394 | return ret; | ||
| 395 | } | ||
| 396 | |||
| 397 | static int ivpu_boot_host_ss_axi_enable(struct ivpu_device *vdev) | ||
| 398 | { | ||
| 399 | return ivpu_boot_host_ss_axi_drive(vdev, true); | ||
| 400 | } | ||
| 401 | |||
| 402 | static int ivpu_boot_host_ss_axi_disable(struct ivpu_device *vdev) | ||
| 403 | { | ||
| 404 | return ivpu_boot_host_ss_axi_drive(vdev, false); | ||
| 405 | } | ||
| 406 | |||
| 407 | static int ivpu_boot_host_ss_top_noc_drive(struct ivpu_device *vdev, bool enable) | ||
| 408 | { | ||
| 409 | int ret; | ||
| 410 | u32 val; | ||
| 411 | |||
| 412 | val = REGV_RD32(MTL_VPU_TOP_NOC_QREQN); | ||
| 413 | if (enable) { | ||
| 414 | val = REG_SET_FLD(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, val); | ||
| 415 | val = REG_SET_FLD(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); | ||
| 416 | } else { | ||
| 417 | val = REG_CLR_FLD(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, val); | ||
| 418 | val = REG_CLR_FLD(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); | ||
| 419 | } | ||
| 420 | REGV_WR32(MTL_VPU_TOP_NOC_QREQN, val); | ||
| 421 | |||
| 422 | ret = ivpu_boot_top_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); | ||
| 423 | if (ret) { | ||
| 424 | ivpu_err(vdev, "Failed qacceptn check: %d\n", ret); | ||
| 425 | return ret; | ||
| 426 | } | ||
| 427 | |||
| 428 | ret = ivpu_boot_top_noc_qdeny_check(vdev, 0x0); | ||
| 429 | if (ret) | ||
| 430 | ivpu_err(vdev, "Failed qdeny check: %d\n", ret); | ||
| 431 | |||
| 432 | return ret; | ||
| 433 | } | ||
| 434 | |||
| 435 | static int ivpu_boot_host_ss_top_noc_enable(struct ivpu_device *vdev) | ||
| 436 | { | ||
| 437 | return ivpu_boot_host_ss_top_noc_drive(vdev, true); | ||
| 438 | } | ||
| 439 | |||
| 440 | static int ivpu_boot_host_ss_top_noc_disable(struct ivpu_device *vdev) | ||
| 441 | { | ||
| 442 | return ivpu_boot_host_ss_top_noc_drive(vdev, false); | ||
| 443 | } | ||
| 444 | |||
| 445 | static void ivpu_boot_pwr_island_trickle_drive(struct ivpu_device *vdev, bool enable) | ||
| 446 | { | ||
| 447 | u32 val = REGV_RD32(MTL_VPU_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0); | ||
| 448 | |||
| 449 | if (enable) | ||
| 450 | val = REG_SET_FLD(MTL_VPU_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val); | ||
| 451 | else | ||
| 452 | val = REG_CLR_FLD(MTL_VPU_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, MSS_CPU, val); | ||
| 453 | |||
| 454 | REGV_WR32(MTL_VPU_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0, val); | ||
| 455 | } | ||
| 456 | |||
| 457 | static void ivpu_boot_pwr_island_drive(struct ivpu_device *vdev, bool enable) | ||
| 458 | { | ||
| 459 | u32 val = REGV_RD32(MTL_VPU_HOST_SS_AON_PWR_ISLAND_EN0); | ||
| 460 | |||
| 461 | if (enable) | ||
| 462 | val = REG_SET_FLD(MTL_VPU_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val); | ||
| 463 | else | ||
| 464 | val = REG_CLR_FLD(MTL_VPU_HOST_SS_AON_PWR_ISLAND_EN0, MSS_CPU, val); | ||
| 465 | |||
| 466 | REGV_WR32(MTL_VPU_HOST_SS_AON_PWR_ISLAND_EN0, val); | ||
| 467 | } | ||
| 468 | |||
| 469 | static int ivpu_boot_wait_for_pwr_island_status(struct ivpu_device *vdev, u32 exp_val) | ||
| 470 | { | ||
| 471 | /* FPGA model (UPF) is not power aware, skipped Power Island polling */ | ||
| 472 | if (ivpu_is_fpga(vdev)) | ||
| 473 | return 0; | ||
| 474 | |||
| 475 | return REGV_POLL_FLD(MTL_VPU_HOST_SS_AON_PWR_ISLAND_STATUS0, MSS_CPU, | ||
| 476 | exp_val, PWR_ISLAND_STATUS_TIMEOUT_US); | ||
| 477 | } | ||
| 478 | |||
| 479 | static void ivpu_boot_pwr_island_isolation_drive(struct ivpu_device *vdev, bool enable) | ||
| 480 | { | ||
| 481 | u32 val = REGV_RD32(MTL_VPU_HOST_SS_AON_PWR_ISO_EN0); | ||
| 482 | |||
| 483 | if (enable) | ||
| 484 | val = REG_SET_FLD(MTL_VPU_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val); | ||
| 485 | else | ||
| 486 | val = REG_CLR_FLD(MTL_VPU_HOST_SS_AON_PWR_ISO_EN0, MSS_CPU, val); | ||
| 487 | |||
| 488 | REGV_WR32(MTL_VPU_HOST_SS_AON_PWR_ISO_EN0, val); | ||
| 489 | } | ||
| 490 | |||
| 491 | static void ivpu_boot_dpu_active_drive(struct ivpu_device *vdev, bool enable) | ||
| 492 | { | ||
| 493 | u32 val = REGV_RD32(MTL_VPU_HOST_SS_AON_DPU_ACTIVE); | ||
| 494 | |||
| 495 | if (enable) | ||
| 496 | val = REG_SET_FLD(MTL_VPU_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val); | ||
| 497 | else | ||
| 498 | val = REG_CLR_FLD(MTL_VPU_HOST_SS_AON_DPU_ACTIVE, DPU_ACTIVE, val); | ||
| 499 | |||
| 500 | REGV_WR32(MTL_VPU_HOST_SS_AON_DPU_ACTIVE, val); | ||
| 501 | } | ||
| 502 | |||
| 503 | static int ivpu_boot_pwr_domain_disable(struct ivpu_device *vdev) | ||
| 504 | { | ||
| 505 | ivpu_boot_dpu_active_drive(vdev, false); | ||
| 506 | ivpu_boot_pwr_island_isolation_drive(vdev, true); | ||
| 507 | ivpu_boot_pwr_island_trickle_drive(vdev, false); | ||
| 508 | ivpu_boot_pwr_island_drive(vdev, false); | ||
| 509 | |||
| 510 | return ivpu_boot_wait_for_pwr_island_status(vdev, 0x0); | ||
| 511 | } | ||
| 512 | |||
| 513 | static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev) | ||
| 514 | { | ||
| 515 | int ret; | ||
| 516 | |||
| 517 | ivpu_boot_pwr_island_trickle_drive(vdev, true); | ||
| 518 | ivpu_boot_pwr_island_drive(vdev, true); | ||
| 519 | |||
| 520 | ret = ivpu_boot_wait_for_pwr_island_status(vdev, 0x1); | ||
| 521 | if (ret) { | ||
| 522 | ivpu_err(vdev, "Timed out waiting for power island status\n"); | ||
| 523 | return ret; | ||
| 524 | } | ||
| 525 | |||
| 526 | ret = ivpu_boot_top_noc_qrenqn_check(vdev, 0x0); | ||
| 527 | if (ret) { | ||
| 528 | ivpu_err(vdev, "Failed qrenqn check %d\n", ret); | ||
| 529 | return ret; | ||
| 530 | } | ||
| 531 | |||
| 532 | ivpu_boot_host_ss_clk_drive(vdev, true); | ||
| 533 | ivpu_boot_pwr_island_isolation_drive(vdev, false); | ||
| 534 | ivpu_boot_host_ss_rst_drive(vdev, true); | ||
| 535 | ivpu_boot_dpu_active_drive(vdev, true); | ||
| 536 | |||
| 537 | return ret; | ||
| 538 | } | ||
| 539 | |||
| 540 | static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev) | ||
| 541 | { | ||
| 542 | u32 val = REGV_RD32(MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES); | ||
| 543 | |||
| 544 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES, NOSNOOP_OVERRIDE_EN, val); | ||
| 545 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val); | ||
| 546 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES, AR_NOSNOOP_OVERRIDE, val); | ||
| 547 | |||
| 548 | REGV_WR32(MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES, val); | ||
| 549 | } | ||
| 550 | |||
| 551 | static void ivpu_boot_tbu_mmu_enable(struct ivpu_device *vdev) | ||
| 552 | { | ||
| 553 | u32 val = REGV_RD32(MTL_VPU_HOST_IF_TBU_MMUSSIDV); | ||
| 554 | |||
| 555 | if (ivpu_is_fpga(vdev)) { | ||
| 556 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU0_AWMMUSSIDV, val); | ||
| 557 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU0_ARMMUSSIDV, val); | ||
| 558 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU2_AWMMUSSIDV, val); | ||
| 559 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU2_ARMMUSSIDV, val); | ||
| 560 | } else { | ||
| 561 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU0_AWMMUSSIDV, val); | ||
| 562 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU0_ARMMUSSIDV, val); | ||
| 563 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU1_AWMMUSSIDV, val); | ||
| 564 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU1_ARMMUSSIDV, val); | ||
| 565 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU2_AWMMUSSIDV, val); | ||
| 566 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU2_ARMMUSSIDV, val); | ||
| 567 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU3_AWMMUSSIDV, val); | ||
| 568 | val = REG_SET_FLD(MTL_VPU_HOST_IF_TBU_MMUSSIDV, TBU3_ARMMUSSIDV, val); | ||
| 569 | } | ||
| 570 | |||
| 571 | REGV_WR32(MTL_VPU_HOST_IF_TBU_MMUSSIDV, val); | ||
| 572 | } | ||
| 573 | |||
| 574 | static void ivpu_boot_soc_cpu_boot(struct ivpu_device *vdev) | ||
| 575 | { | ||
| 576 | u32 val; | ||
| 577 | |||
| 578 | val = REGV_RD32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC); | ||
| 579 | val = REG_SET_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val); | ||
| 580 | |||
| 581 | val = REG_CLR_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val); | ||
| 582 | REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); | ||
| 583 | |||
| 584 | val = REG_SET_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); | ||
| 585 | REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); | ||
| 586 | |||
| 587 | val = REG_CLR_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); | ||
| 588 | REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); | ||
| 589 | } | ||
| 590 | |||
| 591 | static int ivpu_boot_d0i3_drive(struct ivpu_device *vdev, bool enable) | ||
| 592 | { | ||
| 593 | int ret; | ||
| 594 | u32 val; | ||
| 595 | |||
| 596 | ret = REGB_POLL_FLD(MTL_BUTTRESS_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); | ||
| 597 | if (ret) { | ||
| 598 | ivpu_err(vdev, "Failed to sync before D0i3 tansition: %d\n", ret); | ||
| 599 | return ret; | ||
| 600 | } | ||
| 601 | |||
| 602 | val = REGB_RD32(MTL_BUTTRESS_VPU_D0I3_CONTROL); | ||
| 603 | if (enable) | ||
| 604 | val = REG_SET_FLD(MTL_BUTTRESS_VPU_D0I3_CONTROL, I3, val); | ||
| 605 | else | ||
| 606 | val = REG_CLR_FLD(MTL_BUTTRESS_VPU_D0I3_CONTROL, I3, val); | ||
| 607 | REGB_WR32(MTL_BUTTRESS_VPU_D0I3_CONTROL, val); | ||
| 608 | |||
| 609 | ret = REGB_POLL_FLD(MTL_BUTTRESS_VPU_D0I3_CONTROL, INPROGRESS, 0, TIMEOUT_US); | ||
| 610 | if (ret) | ||
| 611 | ivpu_err(vdev, "Failed to sync after D0i3 tansition: %d\n", ret); | ||
| 612 | |||
| 613 | return ret; | ||
| 614 | } | ||
| 615 | |||
| 616 | static int ivpu_hw_mtl_info_init(struct ivpu_device *vdev) | ||
| 617 | { | ||
| 618 | struct ivpu_hw_info *hw = vdev->hw; | ||
| 619 | u32 tile_fuse; | ||
| 620 | |||
| 621 | tile_fuse = REGB_RD32(MTL_BUTTRESS_TILE_FUSE); | ||
| 622 | if (!REG_TEST_FLD(MTL_BUTTRESS_TILE_FUSE, VALID, tile_fuse)) | ||
| 623 | ivpu_warn(vdev, "Tile Fuse: Invalid (0x%x)\n", tile_fuse); | ||
| 624 | |||
| 625 | hw->tile_fuse = REG_GET_FLD(MTL_BUTTRESS_TILE_FUSE, SKU, tile_fuse); | ||
| 626 | switch (hw->tile_fuse) { | ||
| 627 | case TILE_FUSE_ENABLE_LOWER: | ||
| 628 | hw->sku = TILE_SKU_LOWER_MTL; | ||
| 629 | hw->config = WP_CONFIG_1_TILE_5_3_RATIO; | ||
| 630 | ivpu_dbg(vdev, MISC, "Tile Fuse: Enable Lower\n"); | ||
| 631 | break; | ||
| 632 | case TILE_FUSE_ENABLE_UPPER: | ||
| 633 | hw->sku = TILE_SKU_UPPER_MTL; | ||
| 634 | hw->config = WP_CONFIG_1_TILE_4_3_RATIO; | ||
| 635 | ivpu_dbg(vdev, MISC, "Tile Fuse: Enable Upper\n"); | ||
| 636 | break; | ||
| 637 | case TILE_FUSE_ENABLE_BOTH: | ||
| 638 | hw->sku = TILE_SKU_BOTH_MTL; | ||
| 639 | hw->config = WP_CONFIG_2_TILE_5_3_RATIO; | ||
| 640 | ivpu_dbg(vdev, MISC, "Tile Fuse: Enable Both\n"); | ||
| 641 | break; | ||
| 642 | default: | ||
| 643 | hw->config = WP_CONFIG_0_TILE_PLL_OFF; | ||
| 644 | ivpu_dbg(vdev, MISC, "Tile Fuse: Disable\n"); | ||
| 645 | break; | ||
| 646 | } | ||
| 647 | |||
| 648 | ivpu_pll_init_frequency_ratios(vdev); | ||
| 649 | |||
| 650 | ivpu_hw_init_range(&hw->ranges.global_low, 0x80000000, SZ_512M); | ||
| 651 | ivpu_hw_init_range(&hw->ranges.global_high, 0x180000000, SZ_2M); | ||
| 652 | ivpu_hw_init_range(&hw->ranges.user_low, 0xc0000000, 255 * SZ_1M); | ||
| 653 | ivpu_hw_init_range(&hw->ranges.user_high, 0x180000000, SZ_2G); | ||
| 654 | hw->ranges.global_aliased_pio = hw->ranges.user_low; | ||
| 655 | |||
| 656 | return 0; | ||
| 657 | } | ||
| 658 | |||
| 659 | static int ivpu_hw_mtl_reset(struct ivpu_device *vdev) | ||
| 660 | { | ||
| 661 | int ret; | ||
| 662 | u32 val; | ||
| 663 | |||
| 664 | if (IVPU_WA(punit_disabled)) | ||
| 665 | return 0; | ||
| 666 | |||
| 667 | ret = REGB_POLL_FLD(MTL_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US); | ||
| 668 | if (ret) { | ||
| 669 | ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n"); | ||
| 670 | return ret; | ||
| 671 | } | ||
| 672 | |||
| 673 | val = REGB_RD32(MTL_BUTTRESS_VPU_IP_RESET); | ||
| 674 | val = REG_SET_FLD(MTL_BUTTRESS_VPU_IP_RESET, TRIGGER, val); | ||
| 675 | REGB_WR32(MTL_BUTTRESS_VPU_IP_RESET, val); | ||
| 676 | |||
| 677 | ret = REGB_POLL_FLD(MTL_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US); | ||
| 678 | if (ret) | ||
| 679 | ivpu_err(vdev, "Timed out waiting for RESET completion\n"); | ||
| 680 | |||
| 681 | return ret; | ||
| 682 | } | ||
| 683 | |||
| 684 | static int ivpu_hw_mtl_d0i3_enable(struct ivpu_device *vdev) | ||
| 685 | { | ||
| 686 | int ret; | ||
| 687 | |||
| 688 | ret = ivpu_boot_d0i3_drive(vdev, true); | ||
| 689 | if (ret) | ||
| 690 | ivpu_err(vdev, "Failed to enable D0i3: %d\n", ret); | ||
| 691 | |||
| 692 | udelay(5); /* VPU requires 5 us to complete the transition */ | ||
| 693 | |||
| 694 | return ret; | ||
| 695 | } | ||
| 696 | |||
| 697 | static int ivpu_hw_mtl_d0i3_disable(struct ivpu_device *vdev) | ||
| 698 | { | ||
| 699 | int ret; | ||
| 700 | |||
| 701 | ret = ivpu_boot_d0i3_drive(vdev, false); | ||
| 702 | if (ret) | ||
| 703 | ivpu_err(vdev, "Failed to disable D0i3: %d\n", ret); | ||
| 704 | |||
| 705 | return ret; | ||
| 706 | } | ||
| 707 | |||
| 708 | static int ivpu_hw_mtl_power_up(struct ivpu_device *vdev) | ||
| 709 | { | ||
| 710 | int ret; | ||
| 711 | |||
| 712 | ivpu_hw_read_platform(vdev); | ||
| 713 | ivpu_hw_wa_init(vdev); | ||
| 714 | ivpu_hw_timeouts_init(vdev); | ||
| 715 | |||
| 716 | ret = ivpu_hw_mtl_reset(vdev); | ||
| 717 | if (ret) | ||
| 718 | ivpu_warn(vdev, "Failed to reset HW: %d\n", ret); | ||
| 719 | |||
| 720 | ret = ivpu_hw_mtl_d0i3_disable(vdev); | ||
| 721 | if (ret) | ||
| 722 | ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret); | ||
| 723 | |||
| 724 | ret = ivpu_pll_enable(vdev); | ||
| 725 | if (ret) { | ||
| 726 | ivpu_err(vdev, "Failed to enable PLL: %d\n", ret); | ||
| 727 | return ret; | ||
| 728 | } | ||
| 729 | |||
| 730 | ret = ivpu_boot_host_ss_configure(vdev); | ||
| 731 | if (ret) { | ||
| 732 | ivpu_err(vdev, "Failed to configure host SS: %d\n", ret); | ||
| 733 | return ret; | ||
| 734 | } | ||
| 735 | |||
| 736 | /* | ||
| 737 | * The control circuitry for vpu_idle indication logic powers up active. | ||
| 738 | * To ensure unnecessary low power mode signal from LRT during bring up, | ||
| 739 | * KMD disables the circuitry prior to bringing up the Main Power island. | ||
| 740 | */ | ||
| 741 | ivpu_boot_vpu_idle_gen_disable(vdev); | ||
| 742 | |||
| 743 | ret = ivpu_boot_pwr_domain_enable(vdev); | ||
| 744 | if (ret) { | ||
| 745 | ivpu_err(vdev, "Failed to enable power domain: %d\n", ret); | ||
| 746 | return ret; | ||
| 747 | } | ||
| 748 | |||
| 749 | ret = ivpu_boot_host_ss_axi_enable(vdev); | ||
| 750 | if (ret) { | ||
| 751 | ivpu_err(vdev, "Failed to enable AXI: %d\n", ret); | ||
| 752 | return ret; | ||
| 753 | } | ||
| 754 | |||
| 755 | ret = ivpu_boot_host_ss_top_noc_enable(vdev); | ||
| 756 | if (ret) | ||
| 757 | ivpu_err(vdev, "Failed to enable TOP NOC: %d\n", ret); | ||
| 758 | |||
| 759 | return ret; | ||
| 760 | } | ||
| 761 | |||
| 762 | static int ivpu_hw_mtl_boot_fw(struct ivpu_device *vdev) | ||
| 763 | { | ||
| 764 | ivpu_boot_no_snoop_enable(vdev); | ||
| 765 | ivpu_boot_tbu_mmu_enable(vdev); | ||
| 766 | ivpu_boot_soc_cpu_boot(vdev); | ||
| 767 | |||
| 768 | return 0; | ||
| 769 | } | ||
| 770 | |||
| 771 | static bool ivpu_hw_mtl_is_idle(struct ivpu_device *vdev) | ||
| 772 | { | ||
| 773 | u32 val; | ||
| 774 | |||
| 775 | if (IVPU_WA(punit_disabled)) | ||
| 776 | return true; | ||
| 777 | |||
| 778 | val = REGB_RD32(MTL_BUTTRESS_VPU_STATUS); | ||
| 779 | return REG_TEST_FLD(MTL_BUTTRESS_VPU_STATUS, READY, val) && | ||
| 780 | REG_TEST_FLD(MTL_BUTTRESS_VPU_STATUS, IDLE, val); | ||
| 781 | } | ||
| 782 | |||
| 783 | static int ivpu_hw_mtl_power_down(struct ivpu_device *vdev) | ||
| 784 | { | ||
| 785 | int ret = 0; | ||
| 786 | |||
| 787 | /* FPGA requires manual clearing of IP_Reset bit by enabling quiescent state */ | ||
| 788 | if (ivpu_is_fpga(vdev)) { | ||
| 789 | if (ivpu_boot_host_ss_top_noc_disable(vdev)) { | ||
| 790 | ivpu_err(vdev, "Failed to disable TOP NOC\n"); | ||
| 791 | ret = -EIO; | ||
| 792 | } | ||
| 793 | |||
| 794 | if (ivpu_boot_host_ss_axi_disable(vdev)) { | ||
| 795 | ivpu_err(vdev, "Failed to disable AXI\n"); | ||
| 796 | ret = -EIO; | ||
| 797 | } | ||
| 798 | } | ||
| 799 | |||
| 800 | if (ivpu_boot_pwr_domain_disable(vdev)) { | ||
| 801 | ivpu_err(vdev, "Failed to disable power domain\n"); | ||
| 802 | ret = -EIO; | ||
| 803 | } | ||
| 804 | |||
| 805 | if (ivpu_pll_disable(vdev)) { | ||
| 806 | ivpu_err(vdev, "Failed to disable PLL\n"); | ||
| 807 | ret = -EIO; | ||
| 808 | } | ||
| 809 | |||
| 810 | if (ivpu_hw_mtl_d0i3_enable(vdev)) | ||
| 811 | ivpu_warn(vdev, "Failed to enable D0I3\n"); | ||
| 812 | |||
| 813 | return ret; | ||
| 814 | } | ||
| 815 | |||
| 816 | static void ivpu_hw_mtl_wdt_disable(struct ivpu_device *vdev) | ||
| 817 | { | ||
| 818 | u32 val; | ||
| 819 | |||
| 820 | /* Enable writing and set non-zero WDT value */ | ||
| 821 | REGV_WR32(MTL_VPU_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); | ||
| 822 | REGV_WR32(MTL_VPU_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE); | ||
| 823 | |||
| 824 | /* Enable writing and disable watchdog timer */ | ||
| 825 | REGV_WR32(MTL_VPU_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); | ||
| 826 | REGV_WR32(MTL_VPU_CPU_SS_TIM_WDOG_EN, 0); | ||
| 827 | |||
| 828 | /* Now clear the timeout interrupt */ | ||
| 829 | val = REGV_RD32(MTL_VPU_CPU_SS_TIM_GEN_CONFIG); | ||
| 830 | val = REG_CLR_FLD(MTL_VPU_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val); | ||
| 831 | REGV_WR32(MTL_VPU_CPU_SS_TIM_GEN_CONFIG, val); | ||
| 832 | } | ||
| 833 | |||
| 834 | /* Register indirect accesses */ | ||
| 835 | static u32 ivpu_hw_mtl_reg_pll_freq_get(struct ivpu_device *vdev) | ||
| 836 | { | ||
| 837 | u32 pll_curr_ratio; | ||
| 838 | |||
| 839 | pll_curr_ratio = REGB_RD32(MTL_BUTTRESS_CURRENT_PLL); | ||
| 840 | pll_curr_ratio &= MTL_BUTTRESS_CURRENT_PLL_RATIO_MASK; | ||
| 841 | |||
| 842 | if (!ivpu_is_silicon(vdev)) | ||
| 843 | return PLL_SIMULATION_FREQ; | ||
| 844 | |||
| 845 | return PLL_RATIO_TO_FREQ(pll_curr_ratio); | ||
| 846 | } | ||
| 847 | |||
| 848 | static u32 ivpu_hw_mtl_reg_telemetry_offset_get(struct ivpu_device *vdev) | ||
| 849 | { | ||
| 850 | return REGB_RD32(MTL_BUTTRESS_VPU_TELEMETRY_OFFSET); | ||
| 851 | } | ||
| 852 | |||
| 853 | static u32 ivpu_hw_mtl_reg_telemetry_size_get(struct ivpu_device *vdev) | ||
| 854 | { | ||
| 855 | return REGB_RD32(MTL_BUTTRESS_VPU_TELEMETRY_SIZE); | ||
| 856 | } | ||
| 857 | |||
| 858 | static u32 ivpu_hw_mtl_reg_telemetry_enable_get(struct ivpu_device *vdev) | ||
| 859 | { | ||
| 860 | return REGB_RD32(MTL_BUTTRESS_VPU_TELEMETRY_ENABLE); | ||
| 861 | } | ||
| 862 | |||
| 863 | static void ivpu_hw_mtl_reg_db_set(struct ivpu_device *vdev, u32 db_id) | ||
| 864 | { | ||
| 865 | u32 reg_stride = MTL_VPU_CPU_SS_DOORBELL_1 - MTL_VPU_CPU_SS_DOORBELL_0; | ||
| 866 | u32 val = REG_FLD(MTL_VPU_CPU_SS_DOORBELL_0, SET); | ||
| 867 | |||
| 868 | REGV_WR32I(MTL_VPU_CPU_SS_DOORBELL_0, reg_stride, db_id, val); | ||
| 869 | } | ||
| 870 | |||
| 871 | static u32 ivpu_hw_mtl_reg_ipc_rx_addr_get(struct ivpu_device *vdev) | ||
| 872 | { | ||
| 873 | return REGV_RD32(MTL_VPU_HOST_SS_TIM_IPC_FIFO_ATM); | ||
| 874 | } | ||
| 875 | |||
| 876 | static u32 ivpu_hw_mtl_reg_ipc_rx_count_get(struct ivpu_device *vdev) | ||
| 877 | { | ||
| 878 | u32 count = REGV_RD32_SILENT(MTL_VPU_HOST_SS_TIM_IPC_FIFO_STAT); | ||
| 879 | |||
| 880 | return REG_GET_FLD(MTL_VPU_HOST_SS_TIM_IPC_FIFO_STAT, FILL_LEVEL, count); | ||
| 881 | } | ||
| 882 | |||
| 883 | static void ivpu_hw_mtl_reg_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr) | ||
| 884 | { | ||
| 885 | REGV_WR32(MTL_VPU_CPU_SS_TIM_IPC_FIFO, vpu_addr); | ||
| 886 | } | ||
| 887 | |||
| 888 | static void ivpu_hw_mtl_irq_clear(struct ivpu_device *vdev) | ||
| 889 | { | ||
| 890 | REGV_WR64(MTL_VPU_HOST_SS_ICB_CLEAR_0, ICB_0_1_IRQ_MASK); | ||
| 891 | } | ||
| 892 | |||
| 893 | static void ivpu_hw_mtl_irq_enable(struct ivpu_device *vdev) | ||
| 894 | { | ||
| 895 | REGV_WR32(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, ITF_FIREWALL_VIOLATION_MASK); | ||
| 896 | REGV_WR64(MTL_VPU_HOST_SS_ICB_ENABLE_0, ICB_0_1_IRQ_MASK); | ||
| 897 | REGB_WR32(MTL_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_ENABLE_MASK); | ||
| 898 | REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x0); | ||
| 899 | } | ||
| 900 | |||
| 901 | static void ivpu_hw_mtl_irq_disable(struct ivpu_device *vdev) | ||
| 902 | { | ||
| 903 | REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x1); | ||
| 904 | REGB_WR32(MTL_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_DISABLE_MASK); | ||
| 905 | REGV_WR64(MTL_VPU_HOST_SS_ICB_ENABLE_0, 0x0ull); | ||
| 906 | REGB_WR32(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, 0x0); | ||
| 907 | } | ||
| 908 | |||
| 909 | static void ivpu_hw_mtl_irq_wdt_nce_handler(struct ivpu_device *vdev) | ||
| 910 | { | ||
| 911 | ivpu_err_ratelimited(vdev, "WDT NCE irq\n"); | ||
| 912 | } | ||
| 913 | |||
| 914 | static void ivpu_hw_mtl_irq_wdt_mss_handler(struct ivpu_device *vdev) | ||
| 915 | { | ||
| 916 | ivpu_err_ratelimited(vdev, "WDT MSS irq\n"); | ||
| 917 | |||
| 918 | ivpu_hw_wdt_disable(vdev); | ||
| 919 | } | ||
| 920 | |||
| 921 | static void ivpu_hw_mtl_irq_noc_firewall_handler(struct ivpu_device *vdev) | ||
| 922 | { | ||
| 923 | ivpu_err_ratelimited(vdev, "NOC Firewall irq\n"); | ||
| 924 | } | ||
| 925 | |||
| 926 | /* Handler for IRQs from VPU core (irqV) */ | ||
| 927 | static u32 ivpu_hw_mtl_irqv_handler(struct ivpu_device *vdev, int irq) | ||
| 928 | { | ||
| 929 | u32 status = REGV_RD32(MTL_VPU_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK; | ||
| 930 | |||
| 931 | REGV_WR32(MTL_VPU_HOST_SS_ICB_CLEAR_0, status); | ||
| 932 | |||
| 933 | if (REG_TEST_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, status)) | ||
| 934 | ivpu_hw_mtl_irq_wdt_mss_handler(vdev); | ||
| 935 | |||
| 936 | if (REG_TEST_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, status)) | ||
| 937 | ivpu_hw_mtl_irq_wdt_nce_handler(vdev); | ||
| 938 | |||
| 939 | if (REG_TEST_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, status)) | ||
| 940 | ivpu_hw_mtl_irq_noc_firewall_handler(vdev); | ||
| 941 | |||
| 942 | return status; | ||
| 943 | } | ||
| 944 | |||
| 945 | /* Handler for IRQs from Buttress core (irqB) */ | ||
| 946 | static u32 ivpu_hw_mtl_irqb_handler(struct ivpu_device *vdev, int irq) | ||
| 947 | { | ||
| 948 | u32 status = REGB_RD32(MTL_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK; | ||
| 949 | |||
| 950 | if (status == 0) | ||
| 951 | return 0; | ||
| 952 | |||
| 953 | /* Disable global interrupt before handling local buttress interrupts */ | ||
| 954 | REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x1); | ||
| 955 | |||
| 956 | if (REG_TEST_FLD(MTL_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE, status)) | ||
| 957 | ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x", REGB_RD32(MTL_BUTTRESS_CURRENT_PLL)); | ||
| 958 | |||
| 959 | if (REG_TEST_FLD(MTL_BUTTRESS_INTERRUPT_STAT, ATS_ERR, status)) { | ||
| 960 | ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(MTL_BUTTRESS_ATS_ERR_LOG_0)); | ||
| 961 | REGB_WR32(MTL_BUTTRESS_ATS_ERR_CLEAR, 0x1); | ||
| 962 | } | ||
| 963 | |||
| 964 | if (REG_TEST_FLD(MTL_BUTTRESS_INTERRUPT_STAT, UFI_ERR, status)) { | ||
| 965 | u32 ufi_log = REGB_RD32(MTL_BUTTRESS_UFI_ERR_LOG); | ||
| 966 | |||
| 967 | ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx", | ||
| 968 | ufi_log, REG_GET_FLD(MTL_BUTTRESS_UFI_ERR_LOG, OPCODE, ufi_log), | ||
| 969 | REG_GET_FLD(MTL_BUTTRESS_UFI_ERR_LOG, AXI_ID, ufi_log), | ||
| 970 | REG_GET_FLD(MTL_BUTTRESS_UFI_ERR_LOG, CQ_ID, ufi_log)); | ||
| 971 | REGB_WR32(MTL_BUTTRESS_UFI_ERR_CLEAR, 0x1); | ||
| 972 | } | ||
| 973 | |||
| 974 | /* | ||
| 975 | * Clear local interrupt status by writing 0 to all bits. | ||
| 976 | * This must be done after interrupts are cleared at the source. | ||
| 977 | * Writing 1 triggers an interrupt, so we can't perform read update write. | ||
| 978 | */ | ||
| 979 | REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, 0x0); | ||
| 980 | |||
| 981 | /* Re-enable global interrupt */ | ||
| 982 | REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x0); | ||
| 983 | |||
| 984 | return status; | ||
| 985 | } | ||
| 986 | |||
| 987 | static irqreturn_t ivpu_hw_mtl_irq_handler(int irq, void *ptr) | ||
| 988 | { | ||
| 989 | struct ivpu_device *vdev = ptr; | ||
| 990 | u32 ret_irqv, ret_irqb; | ||
| 991 | |||
| 992 | ret_irqv = ivpu_hw_mtl_irqv_handler(vdev, irq); | ||
| 993 | ret_irqb = ivpu_hw_mtl_irqb_handler(vdev, irq); | ||
| 994 | |||
| 995 | return IRQ_RETVAL(ret_irqb | ret_irqv); | ||
| 996 | } | ||
| 997 | |||
| 998 | static void ivpu_hw_mtl_diagnose_failure(struct ivpu_device *vdev) | ||
| 999 | { | ||
| 1000 | u32 irqv = REGV_RD32(MTL_VPU_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK; | ||
| 1001 | u32 irqb = REGB_RD32(MTL_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK; | ||
| 1002 | |||
| 1003 | if (ivpu_hw_mtl_reg_ipc_rx_count_get(vdev)) | ||
| 1004 | ivpu_err(vdev, "IPC FIFO queue not empty, missed IPC IRQ"); | ||
| 1005 | |||
| 1006 | if (REG_TEST_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_0_INT, irqv)) | ||
| 1007 | ivpu_err(vdev, "WDT MSS timeout detected\n"); | ||
| 1008 | |||
| 1009 | if (REG_TEST_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, CPU_INT_REDIRECT_1_INT, irqv)) | ||
| 1010 | ivpu_err(vdev, "WDT NCE timeout detected\n"); | ||
| 1011 | |||
| 1012 | if (REG_TEST_FLD(MTL_VPU_HOST_SS_ICB_STATUS_0, NOC_FIREWALL_INT, irqv)) | ||
| 1013 | ivpu_err(vdev, "NOC Firewall irq detected\n"); | ||
| 1014 | |||
| 1015 | if (REG_TEST_FLD(MTL_BUTTRESS_INTERRUPT_STAT, ATS_ERR, irqb)) | ||
| 1016 | ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(MTL_BUTTRESS_ATS_ERR_LOG_0)); | ||
| 1017 | |||
| 1018 | if (REG_TEST_FLD(MTL_BUTTRESS_INTERRUPT_STAT, UFI_ERR, irqb)) { | ||
| 1019 | u32 ufi_log = REGB_RD32(MTL_BUTTRESS_UFI_ERR_LOG); | ||
| 1020 | |||
| 1021 | ivpu_err(vdev, "UFI_ERR irq (0x%08x) opcode: 0x%02lx axi_id: 0x%02lx cq_id: 0x%03lx", | ||
| 1022 | ufi_log, REG_GET_FLD(MTL_BUTTRESS_UFI_ERR_LOG, OPCODE, ufi_log), | ||
| 1023 | REG_GET_FLD(MTL_BUTTRESS_UFI_ERR_LOG, AXI_ID, ufi_log), | ||
| 1024 | REG_GET_FLD(MTL_BUTTRESS_UFI_ERR_LOG, CQ_ID, ufi_log)); | ||
| 1025 | } | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | const struct ivpu_hw_ops ivpu_hw_mtl_ops = { | ||
| 1029 | .info_init = ivpu_hw_mtl_info_init, | ||
| 1030 | .power_up = ivpu_hw_mtl_power_up, | ||
| 1031 | .is_idle = ivpu_hw_mtl_is_idle, | ||
| 1032 | .power_down = ivpu_hw_mtl_power_down, | ||
| 1033 | .boot_fw = ivpu_hw_mtl_boot_fw, | ||
| 1034 | .wdt_disable = ivpu_hw_mtl_wdt_disable, | ||
| 1035 | .diagnose_failure = ivpu_hw_mtl_diagnose_failure, | ||
| 1036 | .reg_pll_freq_get = ivpu_hw_mtl_reg_pll_freq_get, | ||
| 1037 | .reg_telemetry_offset_get = ivpu_hw_mtl_reg_telemetry_offset_get, | ||
| 1038 | .reg_telemetry_size_get = ivpu_hw_mtl_reg_telemetry_size_get, | ||
| 1039 | .reg_telemetry_enable_get = ivpu_hw_mtl_reg_telemetry_enable_get, | ||
| 1040 | .reg_db_set = ivpu_hw_mtl_reg_db_set, | ||
| 1041 | .reg_ipc_rx_addr_get = ivpu_hw_mtl_reg_ipc_rx_addr_get, | ||
| 1042 | .reg_ipc_rx_count_get = ivpu_hw_mtl_reg_ipc_rx_count_get, | ||
| 1043 | .reg_ipc_tx_set = ivpu_hw_mtl_reg_ipc_tx_set, | ||
| 1044 | .irq_clear = ivpu_hw_mtl_irq_clear, | ||
| 1045 | .irq_enable = ivpu_hw_mtl_irq_enable, | ||
| 1046 | .irq_disable = ivpu_hw_mtl_irq_disable, | ||
| 1047 | .irq_handler = ivpu_hw_mtl_irq_handler, | ||
| 1048 | }; | ||
| @@ -0,0 +1,280 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2020-2023 Intel Corporation | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __IVPU_HW_MTL_REG_H__ | ||
| 7 | #define __IVPU_HW_MTL_REG_H__ | ||
| 8 | |||
| 9 | #include <linux/bits.h> | ||
| 10 | |||
| 11 | #define MTL_BUTTRESS_INTERRUPT_TYPE 0x00000000u | ||
| 12 | |||
| 13 | #define MTL_BUTTRESS_INTERRUPT_STAT 0x00000004u | ||
| 14 | #define MTL_BUTTRESS_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0) | ||
| 15 | #define MTL_BUTTRESS_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1) | ||
| 16 | #define MTL_BUTTRESS_INTERRUPT_STAT_UFI_ERR_MASK BIT_MASK(2) | ||
| 17 | |||
| 18 | #define MTL_BUTTRESS_WP_REQ_PAYLOAD0 0x00000008u | ||
| 19 | #define MTL_BUTTRESS_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0) | ||
| 20 | #define MTL_BUTTRESS_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16) | ||
| 21 | |||
| 22 | #define MTL_BUTTRESS_WP_REQ_PAYLOAD1 0x0000000cu | ||
| 23 | #define MTL_BUTTRESS_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0) | ||
| 24 | #define MTL_BUTTRESS_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16) | ||
| 25 | |||
| 26 | #define MTL_BUTTRESS_WP_REQ_PAYLOAD2 0x00000010u | ||
| 27 | #define MTL_BUTTRESS_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0) | ||
| 28 | |||
| 29 | #define MTL_BUTTRESS_WP_REQ_CMD 0x00000014u | ||
| 30 | #define MTL_BUTTRESS_WP_REQ_CMD_SEND_MASK BIT_MASK(0) | ||
| 31 | |||
| 32 | #define MTL_BUTTRESS_WP_DOWNLOAD 0x00000018u | ||
| 33 | #define MTL_BUTTRESS_WP_DOWNLOAD_TARGET_RATIO_MASK GENMASK(15, 0) | ||
| 34 | |||
| 35 | #define MTL_BUTTRESS_CURRENT_PLL 0x0000001cu | ||
| 36 | #define MTL_BUTTRESS_CURRENT_PLL_RATIO_MASK GENMASK(15, 0) | ||
| 37 | |||
| 38 | #define MTL_BUTTRESS_PLL_ENABLE 0x00000020u | ||
| 39 | |||
| 40 | #define MTL_BUTTRESS_FMIN_FUSE 0x00000024u | ||
| 41 | #define MTL_BUTTRESS_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0) | ||
| 42 | #define MTL_BUTTRESS_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8) | ||
| 43 | |||
| 44 | #define MTL_BUTTRESS_FMAX_FUSE 0x00000028u | ||
| 45 | #define MTL_BUTTRESS_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0) | ||
| 46 | |||
| 47 | #define MTL_BUTTRESS_TILE_FUSE 0x0000002cu | ||
| 48 | #define MTL_BUTTRESS_TILE_FUSE_VALID_MASK BIT_MASK(0) | ||
| 49 | #define MTL_BUTTRESS_TILE_FUSE_SKU_MASK GENMASK(3, 2) | ||
| 50 | |||
| 51 | #define MTL_BUTTRESS_LOCAL_INT_MASK 0x00000030u | ||
| 52 | #define MTL_BUTTRESS_GLOBAL_INT_MASK 0x00000034u | ||
| 53 | |||
| 54 | #define MTL_BUTTRESS_PLL_STATUS 0x00000040u | ||
| 55 | #define MTL_BUTTRESS_PLL_STATUS_LOCK_MASK BIT_MASK(1) | ||
| 56 | |||
| 57 | #define MTL_BUTTRESS_VPU_STATUS 0x00000044u | ||
| 58 | #define MTL_BUTTRESS_VPU_STATUS_READY_MASK BIT_MASK(0) | ||
| 59 | #define MTL_BUTTRESS_VPU_STATUS_IDLE_MASK BIT_MASK(1) | ||
| 60 | |||
| 61 | #define MTL_BUTTRESS_VPU_D0I3_CONTROL 0x00000060u | ||
| 62 | #define MTL_BUTTRESS_VPU_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0) | ||
| 63 | #define MTL_BUTTRESS_VPU_D0I3_CONTROL_I3_MASK BIT_MASK(2) | ||
| 64 | |||
| 65 | #define MTL_BUTTRESS_VPU_IP_RESET 0x00000050u | ||
| 66 | #define MTL_BUTTRESS_VPU_IP_RESET_TRIGGER_MASK BIT_MASK(0) | ||
| 67 | |||
| 68 | #define MTL_BUTTRESS_VPU_TELEMETRY_OFFSET 0x00000080u | ||
| 69 | #define MTL_BUTTRESS_VPU_TELEMETRY_SIZE 0x00000084u | ||
| 70 | #define MTL_BUTTRESS_VPU_TELEMETRY_ENABLE 0x00000088u | ||
| 71 | |||
| 72 | #define MTL_BUTTRESS_ATS_ERR_LOG_0 0x000000a0u | ||
| 73 | #define MTL_BUTTRESS_ATS_ERR_LOG_1 0x000000a4u | ||
| 74 | #define MTL_BUTTRESS_ATS_ERR_CLEAR 0x000000a8u | ||
| 75 | |||
| 76 | #define MTL_BUTTRESS_UFI_ERR_LOG 0x000000b0u | ||
| 77 | #define MTL_BUTTRESS_UFI_ERR_LOG_CQ_ID_MASK GENMASK(11, 0) | ||
| 78 | #define MTL_BUTTRESS_UFI_ERR_LOG_AXI_ID_MASK GENMASK(19, 12) | ||
| 79 | #define MTL_BUTTRESS_UFI_ERR_LOG_OPCODE_MASK GENMASK(24, 20) | ||
| 80 | |||
| 81 | #define MTL_BUTTRESS_UFI_ERR_CLEAR 0x000000b4u | ||
| 82 | |||
| 83 | #define MTL_VPU_HOST_SS_CPR_CLK_SET 0x00000084u | ||
| 84 | #define MTL_VPU_HOST_SS_CPR_CLK_SET_TOP_NOC_MASK BIT_MASK(1) | ||
| 85 | #define MTL_VPU_HOST_SS_CPR_CLK_SET_DSS_MAS_MASK BIT_MASK(10) | ||
| 86 | #define MTL_VPU_HOST_SS_CPR_CLK_SET_MSS_MAS_MASK BIT_MASK(11) | ||
| 87 | |||
| 88 | #define MTL_VPU_HOST_SS_CPR_RST_SET 0x00000094u | ||
| 89 | #define MTL_VPU_HOST_SS_CPR_RST_SET_TOP_NOC_MASK BIT_MASK(1) | ||
| 90 | #define MTL_VPU_HOST_SS_CPR_RST_SET_DSS_MAS_MASK BIT_MASK(10) | ||
| 91 | #define MTL_VPU_HOST_SS_CPR_RST_SET_MSS_MAS_MASK BIT_MASK(11) | ||
| 92 | |||
| 93 | #define MTL_VPU_HOST_SS_CPR_RST_CLR 0x00000098u | ||
| 94 | #define MTL_VPU_HOST_SS_CPR_RST_CLR_TOP_NOC_MASK BIT_MASK(1) | ||
| 95 | #define MTL_VPU_HOST_SS_CPR_RST_CLR_DSS_MAS_MASK BIT_MASK(10) | ||
| 96 | #define MTL_VPU_HOST_SS_CPR_RST_CLR_MSS_MAS_MASK BIT_MASK(11) | ||
| 97 | |||
| 98 | #define MTL_VPU_HOST_SS_HW_VERSION 0x00000108u | ||
| 99 | #define MTL_VPU_HOST_SS_HW_VERSION_SOC_REVISION_MASK GENMASK(7, 0) | ||
| 100 | #define MTL_VPU_HOST_SS_HW_VERSION_SOC_NUMBER_MASK GENMASK(15, 8) | ||
| 101 | #define MTL_VPU_HOST_SS_HW_VERSION_VPU_GENERATION_MASK GENMASK(23, 16) | ||
| 102 | |||
| 103 | #define MTL_VPU_HOST_SS_GEN_CTRL 0x00000118u | ||
| 104 | #define MTL_VPU_HOST_SS_GEN_CTRL_PS_MASK GENMASK(31, 29) | ||
| 105 | |||
| 106 | #define MTL_VPU_HOST_SS_NOC_QREQN 0x00000154u | ||
| 107 | #define MTL_VPU_HOST_SS_NOC_QREQN_TOP_SOCMMIO_MASK BIT_MASK(0) | ||
| 108 | |||
| 109 | #define MTL_VPU_HOST_SS_NOC_QACCEPTN 0x00000158u | ||
| 110 | #define MTL_VPU_HOST_SS_NOC_QACCEPTN_TOP_SOCMMIO_MASK BIT_MASK(0) | ||
| 111 | |||
| 112 | #define MTL_VPU_HOST_SS_NOC_QDENY 0x0000015cu | ||
| 113 | #define MTL_VPU_HOST_SS_NOC_QDENY_TOP_SOCMMIO_MASK BIT_MASK(0) | ||
| 114 | |||
| 115 | #define MTL_VPU_TOP_NOC_QREQN 0x00000160u | ||
| 116 | #define MTL_VPU_TOP_NOC_QREQN_CPU_CTRL_MASK BIT_MASK(0) | ||
| 117 | #define MTL_VPU_TOP_NOC_QREQN_HOSTIF_L2CACHE_MASK BIT_MASK(1) | ||
| 118 | |||
| 119 | #define MTL_VPU_TOP_NOC_QACCEPTN 0x00000164u | ||
| 120 | #define MTL_VPU_TOP_NOC_QACCEPTN_CPU_CTRL_MASK BIT_MASK(0) | ||
| 121 | #define MTL_VPU_TOP_NOC_QACCEPTN_HOSTIF_L2CACHE_MASK BIT_MASK(1) | ||
| 122 | |||
| 123 | #define MTL_VPU_TOP_NOC_QDENY 0x00000168u | ||
| 124 | #define MTL_VPU_TOP_NOC_QDENY_CPU_CTRL_MASK BIT_MASK(0) | ||
| 125 | #define MTL_VPU_TOP_NOC_QDENY_HOSTIF_L2CACHE_MASK BIT_MASK(1) | ||
| 126 | |||
| 127 | #define MTL_VPU_HOST_SS_FW_SOC_IRQ_EN 0x00000170u | ||
| 128 | #define MTL_VPU_HOST_SS_FW_SOC_IRQ_EN_CSS_ROM_CMX_MASK BIT_MASK(0) | ||
| 129 | #define MTL_VPU_HOST_SS_FW_SOC_IRQ_EN_CSS_DBG_MASK BIT_MASK(1) | ||
| 130 | #define MTL_VPU_HOST_SS_FW_SOC_IRQ_EN_CSS_CTRL_MASK BIT_MASK(2) | ||
| 131 | #define MTL_VPU_HOST_SS_FW_SOC_IRQ_EN_DEC400_MASK BIT_MASK(3) | ||
| 132 | #define MTL_VPU_HOST_SS_FW_SOC_IRQ_EN_MSS_NCE_MASK BIT_MASK(4) | ||
| 133 | #define MTL_VPU_HOST_SS_FW_SOC_IRQ_EN_MSS_MBI_MASK BIT_MASK(5) | ||
| 134 | #define MTL_VPU_HOST_SS_FW_SOC_IRQ_EN_MSS_MBI_CMX_MASK BIT_MASK(6) | ||
| 135 | |||
| 136 | #define MTL_VPU_HOST_SS_ICB_STATUS_0 0x00010210u | ||
| 137 | #define MTL_VPU_HOST_SS_ICB_STATUS_0_TIMER_0_INT_MASK BIT_MASK(0) | ||
| 138 | #define MTL_VPU_HOST_SS_ICB_STATUS_0_TIMER_1_INT_MASK BIT_MASK(1) | ||
| 139 | #define MTL_VPU_HOST_SS_ICB_STATUS_0_TIMER_2_INT_MASK BIT_MASK(2) | ||
| 140 | #define MTL_VPU_HOST_SS_ICB_STATUS_0_TIMER_3_INT_MASK BIT_MASK(3) | ||
| 141 | #define MTL_VPU_HOST_SS_ICB_STATUS_0_HOST_IPC_FIFO_INT_MASK BIT_MASK(4) | ||
| 142 | #define MTL_VPU_HOST_SS_ICB_STATUS_0_MMU_IRQ_0_INT_MASK BIT_MASK(5) | ||
| 143 | #define MTL_VPU_HOST_SS_ICB_STATUS_0_MMU_IRQ_1_INT_MASK BIT_MASK(6) | ||
| 144 | #define MTL_VPU_HOST_SS_ICB_STATUS_0_MMU_IRQ_2_INT_MASK BIT_MASK(7) | ||
| 145 | #define MTL_VPU_HOST_SS_ICB_STATUS_0_NOC_FIREWALL_INT_MASK BIT_MASK(8) | ||
| 146 | #define MTL_VPU_HOST_SS_ICB_STATUS_0_CPU_INT_REDIRECT_0_INT_MASK BIT_MASK(30) | ||
| 147 | #define MTL_VPU_HOST_SS_ICB_STATUS_0_CPU_INT_REDIRECT_1_INT_MASK BIT_MASK(31) | ||
| 148 | |||
| 149 | #define MTL_VPU_HOST_SS_ICB_STATUS_1 0x00010214u | ||
| 150 | #define MTL_VPU_HOST_SS_ICB_STATUS_1_CPU_INT_REDIRECT_2_INT_MASK BIT_MASK(0) | ||
| 151 | #define MTL_VPU_HOST_SS_ICB_STATUS_1_CPU_INT_REDIRECT_3_INT_MASK BIT_MASK(1) | ||
| 152 | #define MTL_VPU_HOST_SS_ICB_STATUS_1_CPU_INT_REDIRECT_4_INT_MASK BIT_MASK(2) | ||
| 153 | |||
| 154 | #define MTL_VPU_HOST_SS_ICB_CLEAR_0 0x00010220u | ||
| 155 | #define MTL_VPU_HOST_SS_ICB_CLEAR_1 0x00010224u | ||
| 156 | #define MTL_VPU_HOST_SS_ICB_ENABLE_0 0x00010240u | ||
| 157 | |||
| 158 | #define MTL_VPU_HOST_SS_TIM_IPC_FIFO_ATM 0x000200f4u | ||
| 159 | |||
| 160 | #define MTL_VPU_HOST_SS_TIM_IPC_FIFO_STAT 0x000200fcu | ||
| 161 | #define MTL_VPU_HOST_SS_TIM_IPC_FIFO_STAT_READ_POINTER_MASK GENMASK(7, 0) | ||
| 162 | #define MTL_VPU_HOST_SS_TIM_IPC_FIFO_STAT_WRITE_POINTER_MASK GENMASK(15, 8) | ||
| 163 | #define MTL_VPU_HOST_SS_TIM_IPC_FIFO_STAT_FILL_LEVEL_MASK GENMASK(23, 16) | ||
| 164 | #define MTL_VPU_HOST_SS_TIM_IPC_FIFO_STAT_RSVD0_MASK GENMASK(31, 24) | ||
| 165 | |||
| 166 | #define MTL_VPU_HOST_SS_AON_PWR_ISO_EN0 0x00030020u | ||
| 167 | #define MTL_VPU_HOST_SS_AON_PWR_ISO_EN0_MSS_CPU_MASK BIT_MASK(3) | ||
| 168 | |||
| 169 | #define MTL_VPU_HOST_SS_AON_PWR_ISLAND_EN0 0x00030024u | ||
| 170 | #define MTL_VPU_HOST_SS_AON_PWR_ISLAND_EN0_MSS_CPU_MASK BIT_MASK(3) | ||
| 171 | |||
| 172 | #define MTL_VPU_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0 0x00030028u | ||
| 173 | #define MTL_VPU_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0_MSS_CPU_MASK BIT_MASK(3) | ||
| 174 | |||
| 175 | #define MTL_VPU_HOST_SS_AON_PWR_ISLAND_STATUS0 0x0003002cu | ||
| 176 | #define MTL_VPU_HOST_SS_AON_PWR_ISLAND_STATUS0_MSS_CPU_MASK BIT_MASK(3) | ||
| 177 | |||
| 178 | #define MTL_VPU_HOST_SS_AON_VPU_IDLE_GEN 0x00030200u | ||
| 179 | #define MTL_VPU_HOST_SS_AON_VPU_IDLE_GEN_EN_MASK BIT_MASK(0) | ||
| 180 | |||
| 181 | #define MTL_VPU_HOST_SS_AON_DPU_ACTIVE 0x00030204u | ||
| 182 | #define MTL_VPU_HOST_SS_AON_DPU_ACTIVE_DPU_ACTIVE_MASK BIT_MASK(0) | ||
| 183 | |||
| 184 | #define MTL_VPU_HOST_SS_LOADING_ADDRESS_LO 0x00041040u | ||
| 185 | #define MTL_VPU_HOST_SS_LOADING_ADDRESS_LO_DONE_MASK BIT_MASK(0) | ||
| 186 | #define MTL_VPU_HOST_SS_LOADING_ADDRESS_LO_IOSF_RS_ID_MASK GENMASK(2, 1) | ||
| 187 | #define MTL_VPU_HOST_SS_LOADING_ADDRESS_LO_IMAGE_LOCATION_MASK GENMASK(31, 3) | ||
| 188 | |||
| 189 | #define MTL_VPU_HOST_SS_WORKPOINT_CONFIG_MIRROR 0x00082020u | ||
| 190 | #define MTL_VPU_HOST_SS_WORKPOINT_CONFIG_MIRROR_FINAL_PLL_FREQ_MASK GENMASK(15, 0) | ||
| 191 | #define MTL_VPU_HOST_SS_WORKPOINT_CONFIG_MIRROR_CONFIG_ID_MASK GENMASK(31, 16) | ||
| 192 | |||
| 193 | #define MTL_VPU_HOST_MMU_IDR0 0x00200000u | ||
| 194 | #define MTL_VPU_HOST_MMU_IDR1 0x00200004u | ||
| 195 | #define MTL_VPU_HOST_MMU_IDR3 0x0020000cu | ||
| 196 | #define MTL_VPU_HOST_MMU_IDR5 0x00200014u | ||
| 197 | #define MTL_VPU_HOST_MMU_CR0 0x00200020u | ||
| 198 | #define MTL_VPU_HOST_MMU_CR0ACK 0x00200024u | ||
| 199 | #define MTL_VPU_HOST_MMU_CR1 0x00200028u | ||
| 200 | #define MTL_VPU_HOST_MMU_CR2 0x0020002cu | ||
| 201 | #define MTL_VPU_HOST_MMU_IRQ_CTRL 0x00200050u | ||
| 202 | #define MTL_VPU_HOST_MMU_IRQ_CTRLACK 0x00200054u | ||
| 203 | |||
| 204 | #define MTL_VPU_HOST_MMU_GERROR 0x00200060u | ||
| 205 | #define MTL_VPU_HOST_MMU_GERROR_CMDQ_MASK BIT_MASK(0) | ||
| 206 | #define MTL_VPU_HOST_MMU_GERROR_EVTQ_ABT_MASK BIT_MASK(2) | ||
| 207 | #define MTL_VPU_HOST_MMU_GERROR_PRIQ_ABT_MASK BIT_MASK(3) | ||
| 208 | #define MTL_VPU_HOST_MMU_GERROR_MSI_CMDQ_ABT_MASK BIT_MASK(4) | ||
| 209 | #define MTL_VPU_HOST_MMU_GERROR_MSI_EVTQ_ABT_MASK BIT_MASK(5) | ||
| 210 | #define MTL_VPU_HOST_MMU_GERROR_MSI_PRIQ_ABT_MASK BIT_MASK(6) | ||
| 211 | #define MTL_VPU_HOST_MMU_GERROR_MSI_ABT_MASK BIT_MASK(7) | ||
| 212 | |||
| 213 | #define MTL_VPU_HOST_MMU_GERRORN 0x00200064u | ||
| 214 | |||
| 215 | #define MTL_VPU_HOST_MMU_STRTAB_BASE 0x00200080u | ||
| 216 | #define MTL_VPU_HOST_MMU_STRTAB_BASE_CFG 0x00200088u | ||
| 217 | #define MTL_VPU_HOST_MMU_CMDQ_BASE 0x00200090u | ||
| 218 | #define MTL_VPU_HOST_MMU_CMDQ_PROD 0x00200098u | ||
| 219 | #define MTL_VPU_HOST_MMU_CMDQ_CONS 0x0020009cu | ||
| 220 | #define MTL_VPU_HOST_MMU_EVTQ_BASE 0x002000a0u | ||
| 221 | #define MTL_VPU_HOST_MMU_EVTQ_PROD 0x002000a8u | ||
| 222 | #define MTL_VPU_HOST_MMU_EVTQ_CONS 0x002000acu | ||
| 223 | #define MTL_VPU_HOST_MMU_EVTQ_PROD_SEC (0x002000a8u + SZ_64K) | ||
| 224 | #define MTL_VPU_HOST_MMU_EVTQ_CONS_SEC (0x002000acu + SZ_64K) | ||
| 225 | |||
| 226 | #define MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES 0x00360000u | ||
| 227 | #define MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES_CACHE_OVERRIDE_EN_MASK BIT_MASK(0) | ||
| 228 | #define MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES_AWCACHE_OVERRIDE_MASK BIT_MASK(1) | ||
| 229 | #define MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES_ARCACHE_OVERRIDE_MASK BIT_MASK(2) | ||
| 230 | #define MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES_NOSNOOP_OVERRIDE_EN_MASK BIT_MASK(3) | ||
| 231 | #define MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES_AW_NOSNOOP_OVERRIDE_MASK BIT_MASK(4) | ||
| 232 | #define MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES_AR_NOSNOOP_OVERRIDE_MASK BIT_MASK(5) | ||
| 233 | #define MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES_PTW_AW_CONTEXT_FLAG_MASK GENMASK(10, 6) | ||
| 234 | #define MTL_VPU_HOST_IF_TCU_PTW_OVERRIDES_PTW_AR_CONTEXT_FLAG_MASK GENMASK(15, 11) | ||
| 235 | |||
| 236 | #define MTL_VPU_HOST_IF_TBU_MMUSSIDV 0x00360004u | ||
| 237 | #define MTL_VPU_HOST_IF_TBU_MMUSSIDV_TBU0_AWMMUSSIDV_MASK BIT_MASK(0) | ||
| 238 | #define MTL_VPU_HOST_IF_TBU_MMUSSIDV_TBU0_ARMMUSSIDV_MASK BIT_MASK(1) | ||
| 239 | #define MTL_VPU_HOST_IF_TBU_MMUSSIDV_TBU1_AWMMUSSIDV_MASK BIT_MASK(2) | ||
| 240 | #define MTL_VPU_HOST_IF_TBU_MMUSSIDV_TBU1_ARMMUSSIDV_MASK BIT_MASK(3) | ||
| 241 | #define MTL_VPU_HOST_IF_TBU_MMUSSIDV_TBU2_AWMMUSSIDV_MASK BIT_MASK(4) | ||
| 242 | #define MTL_VPU_HOST_IF_TBU_MMUSSIDV_TBU2_ARMMUSSIDV_MASK BIT_MASK(5) | ||
| 243 | #define MTL_VPU_HOST_IF_TBU_MMUSSIDV_TBU3_AWMMUSSIDV_MASK BIT_MASK(6) | ||
| 244 | #define MTL_VPU_HOST_IF_TBU_MMUSSIDV_TBU3_ARMMUSSIDV_MASK BIT_MASK(7) | ||
| 245 | #define MTL_VPU_HOST_IF_TBU_MMUSSIDV_TBU4_AWMMUSSIDV_MASK BIT_MASK(8) | ||
| 246 | #define MTL_VPU_HOST_IF_TBU_MMUSSIDV_TBU4_ARMMUSSIDV_MASK BIT_MASK(9) | ||
| 247 | |||
| 248 | #define MTL_VPU_CPU_SS_DSU_LEON_RT_BASE 0x04000000u | ||
| 249 | #define MTL_VPU_CPU_SS_DSU_LEON_RT_DSU_CTRL 0x04000000u | ||
| 250 | #define MTL_VPU_CPU_SS_DSU_LEON_RT_PC_REG 0x04400010u | ||
| 251 | #define MTL_VPU_CPU_SS_DSU_LEON_RT_NPC_REG 0x04400014u | ||
| 252 | #define MTL_VPU_CPU_SS_DSU_LEON_RT_DSU_TRAP_REG 0x04400020u | ||
| 253 | |||
| 254 | #define MTL_VPU_CPU_SS_MSSCPU_CPR_CLK_SET 0x06010004u | ||
| 255 | #define MTL_VPU_CPU_SS_MSSCPU_CPR_CLK_SET_CPU_DSU_MASK BIT_MASK(1) | ||
| 256 | |||
| 257 | #define MTL_VPU_CPU_SS_MSSCPU_CPR_RST_CLR 0x06010018u | ||
| 258 | #define MTL_VPU_CPU_SS_MSSCPU_CPR_RST_CLR_CPU_DSU_MASK BIT_MASK(1) | ||
| 259 | |||
| 260 | #define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC 0x06010040u | ||
| 261 | #define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTRUN0_MASK BIT_MASK(0) | ||
| 262 | #define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RESUME0_MASK BIT_MASK(1) | ||
| 263 | #define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTRUN1_MASK BIT_MASK(2) | ||
| 264 | #define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RESUME1_MASK BIT_MASK(3) | ||
| 265 | #define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTVEC_MASK GENMASK(31, 4) | ||
| 266 | |||
| 267 | #define MTL_VPU_CPU_SS_TIM_WATCHDOG 0x0602009cu | ||
| 268 | #define MTL_VPU_CPU_SS_TIM_WDOG_EN 0x060200a4u | ||
| 269 | #define MTL_VPU_CPU_SS_TIM_SAFE 0x060200a8u | ||
| 270 | #define MTL_VPU_CPU_SS_TIM_IPC_FIFO 0x060200f0u | ||
| 271 | |||
| 272 | #define MTL_VPU_CPU_SS_TIM_GEN_CONFIG 0x06021008u | ||
| 273 | #define MTL_VPU_CPU_SS_TIM_GEN_CONFIG_WDOG_TO_INT_CLR_MASK BIT_MASK(9) | ||
| 274 | |||
| 275 | #define MTL_VPU_CPU_SS_DOORBELL_0 0x06300000u | ||
| 276 | #define MTL_VPU_CPU_SS_DOORBELL_0_SET_MASK BIT_MASK(0) | ||
| 277 | |||
| 278 | #define MTL_VPU_CPU_SS_DOORBELL_1 0x06301000u | ||
| 279 | |||
| 280 | #endif /* __IVPU_HW_MTL_REG_H__ */ | ||
| @@ -0,0 +1,115 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2020-2023 Intel Corporation | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __IVPU_HW_REG_IO_H__ | ||
| 7 | #define __IVPU_HW_REG_IO_H__ | ||
| 8 | |||
| 9 | #include <linux/bitfield.h> | ||
| 10 | #include <linux/io.h> | ||
| 11 | #include <linux/iopoll.h> | ||
| 12 | |||
| 13 | #include "ivpu_drv.h" | ||
| 14 | |||
| 15 | #define REG_POLL_SLEEP_US 50 | ||
| 16 | #define REG_IO_ERROR 0xffffffff | ||
| 17 | |||
| 18 | #define REGB_RD32(reg) ivpu_hw_reg_rd32(vdev, vdev->regb, (reg), #reg, __func__) | ||
| 19 | #define REGB_RD32_SILENT(reg) readl(vdev->regb + (reg)) | ||
| 20 | #define REGB_RD64(reg) ivpu_hw_reg_rd64(vdev, vdev->regb, (reg), #reg, __func__) | ||
| 21 | #define REGB_WR32(reg, val) ivpu_hw_reg_wr32(vdev, vdev->regb, (reg), (val), #reg, __func__) | ||
| 22 | #define REGB_WR64(reg, val) ivpu_hw_reg_wr64(vdev, vdev->regb, (reg), (val), #reg, __func__) | ||
| 23 | |||
| 24 | #define REGV_RD32(reg) ivpu_hw_reg_rd32(vdev, vdev->regv, (reg), #reg, __func__) | ||
| 25 | #define REGV_RD32_SILENT(reg) readl(vdev->regv + (reg)) | ||
| 26 | #define REGV_RD64(reg) ivpu_hw_reg_rd64(vdev, vdev->regv, (reg), #reg, __func__) | ||
| 27 | #define REGV_WR32(reg, val) ivpu_hw_reg_wr32(vdev, vdev->regv, (reg), (val), #reg, __func__) | ||
| 28 | #define REGV_WR64(reg, val) ivpu_hw_reg_wr64(vdev, vdev->regv, (reg), (val), #reg, __func__) | ||
| 29 | |||
| 30 | #define REGV_WR32I(reg, stride, index, val) \ | ||
| 31 | ivpu_hw_reg_wr32_index(vdev, vdev->regv, (reg), (stride), (index), (val), #reg, __func__) | ||
| 32 | |||
| 33 | #define REG_FLD(REG, FLD) \ | ||
| 34 | (REG##_##FLD##_MASK) | ||
| 35 | #define REG_FLD_NUM(REG, FLD, num) \ | ||
| 36 | FIELD_PREP(REG##_##FLD##_MASK, num) | ||
| 37 | #define REG_GET_FLD(REG, FLD, val) \ | ||
| 38 | FIELD_GET(REG##_##FLD##_MASK, val) | ||
| 39 | #define REG_CLR_FLD(REG, FLD, val) \ | ||
| 40 | ((val) & ~(REG##_##FLD##_MASK)) | ||
| 41 | #define REG_SET_FLD(REG, FLD, val) \ | ||
| 42 | ((val) | (REG##_##FLD##_MASK)) | ||
| 43 | #define REG_SET_FLD_NUM(REG, FLD, num, val) \ | ||
| 44 | (((val) & ~(REG##_##FLD##_MASK)) | FIELD_PREP(REG##_##FLD##_MASK, num)) | ||
| 45 | #define REG_TEST_FLD(REG, FLD, val) \ | ||
| 46 | ((REG##_##FLD##_MASK) == ((val) & (REG##_##FLD##_MASK))) | ||
| 47 | #define REG_TEST_FLD_NUM(REG, FLD, num, val) \ | ||
| 48 | ((num) == FIELD_GET(REG##_##FLD##_MASK, val)) | ||
| 49 | |||
| 50 | #define REGB_POLL(reg, var, cond, timeout_us) \ | ||
| 51 | read_poll_timeout(REGB_RD32_SILENT, var, cond, REG_POLL_SLEEP_US, timeout_us, false, reg) | ||
| 52 | |||
| 53 | #define REGV_POLL(reg, var, cond, timeout_us) \ | ||
| 54 | read_poll_timeout(REGV_RD32_SILENT, var, cond, REG_POLL_SLEEP_US, timeout_us, false, reg) | ||
| 55 | |||
| 56 | #define REGB_POLL_FLD(reg, fld, val, timeout_us) \ | ||
| 57 | ({ \ | ||
| 58 | u32 var; \ | ||
| 59 | REGB_POLL(reg, var, (FIELD_GET(reg##_##fld##_MASK, var) == (val)), timeout_us); \ | ||
| 60 | }) | ||
| 61 | |||
| 62 | #define REGV_POLL_FLD(reg, fld, val, timeout_us) \ | ||
| 63 | ({ \ | ||
| 64 | u32 var; \ | ||
| 65 | REGV_POLL(reg, var, (FIELD_GET(reg##_##fld##_MASK, var) == (val)), timeout_us); \ | ||
| 66 | }) | ||
| 67 | |||
| 68 | static inline u32 | ||
| 69 | ivpu_hw_reg_rd32(struct ivpu_device *vdev, void __iomem *base, u32 reg, | ||
| 70 | const char *name, const char *func) | ||
| 71 | { | ||
| 72 | u32 val = readl(base + reg); | ||
| 73 | |||
| 74 | ivpu_dbg(vdev, REG, "%s RD: %s (0x%08x) => 0x%08x\n", func, name, reg, val); | ||
| 75 | return val; | ||
| 76 | } | ||
| 77 | |||
| 78 | static inline u64 | ||
| 79 | ivpu_hw_reg_rd64(struct ivpu_device *vdev, void __iomem *base, u32 reg, | ||
| 80 | const char *name, const char *func) | ||
| 81 | { | ||
| 82 | u64 val = readq(base + reg); | ||
| 83 | |||
| 84 | ivpu_dbg(vdev, REG, "%s RD: %s (0x%08x) => 0x%016llx\n", func, name, reg, val); | ||
| 85 | return val; | ||
| 86 | } | ||
| 87 | |||
| 88 | static inline void | ||
| 89 | ivpu_hw_reg_wr32(struct ivpu_device *vdev, void __iomem *base, u32 reg, u32 val, | ||
| 90 | const char *name, const char *func) | ||
| 91 | { | ||
| 92 | ivpu_dbg(vdev, REG, "%s WR: %s (0x%08x) <= 0x%08x\n", func, name, reg, val); | ||
| 93 | writel(val, base + reg); | ||
| 94 | } | ||
| 95 | |||
| 96 | static inline void | ||
| 97 | ivpu_hw_reg_wr64(struct ivpu_device *vdev, void __iomem *base, u32 reg, u64 val, | ||
| 98 | const char *name, const char *func) | ||
| 99 | { | ||
| 100 | ivpu_dbg(vdev, REG, "%s WR: %s (0x%08x) <= 0x%016llx\n", func, name, reg, val); | ||
| 101 | writeq(val, base + reg); | ||
| 102 | } | ||
| 103 | |||
| 104 | static inline void | ||
| 105 | ivpu_hw_reg_wr32_index(struct ivpu_device *vdev, void __iomem *base, u32 reg, | ||
| 106 | u32 stride, u32 index, u32 val, const char *name, | ||
| 107 | const char *func) | ||
| 108 | { | ||
| 109 | reg += index * stride; | ||
| 110 | |||
| 111 | ivpu_dbg(vdev, REG, "%s WR: %s_%d (0x%08x) <= 0x%08x\n", func, name, index, reg, val); | ||
| 112 | writel(val, base + reg); | ||
| 113 | } | ||
| 114 | |||
| 115 | #endif /* __IVPU_HW_REG_IO_H__ */ | ||
| @@ -0,0 +1,95 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2020-2023 Intel Corporation | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __UAPI_IVPU_DRM_H__ | ||
| 7 | #define __UAPI_IVPU_DRM_H__ | ||
| 8 | |||
| 9 | #include "drm.h" | ||
| 10 | |||
| 11 | #if defined(__cplusplus) | ||
| 12 | extern "C" { | ||
| 13 | #endif | ||
| 14 | |||
| 15 | #define DRM_IVPU_DRIVER_MAJOR 1 | ||
| 16 | #define DRM_IVPU_DRIVER_MINOR 0 | ||
| 17 | |||
| 18 | #define DRM_IVPU_GET_PARAM 0x00 | ||
| 19 | #define DRM_IVPU_SET_PARAM 0x01 | ||
| 20 | |||
| 21 | #define DRM_IOCTL_IVPU_GET_PARAM \ | ||
| 22 | DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_GET_PARAM, struct drm_ivpu_param) | ||
| 23 | |||
| 24 | #define DRM_IOCTL_IVPU_SET_PARAM \ | ||
| 25 | DRM_IOW(DRM_COMMAND_BASE + DRM_IVPU_SET_PARAM, struct drm_ivpu_param) | ||
| 26 | |||
| 27 | /** | ||
| 28 | * DOC: contexts | ||
| 29 | * | ||
| 30 | * VPU contexts have private virtual address space, job queues and priority. | ||
| 31 | * Each context is identified by an unique ID. Context is created on open(). | ||
| 32 | */ | ||
| 33 | |||
| 34 | #define DRM_IVPU_PARAM_DEVICE_ID 0 | ||
| 35 | #define DRM_IVPU_PARAM_DEVICE_REVISION 1 | ||
| 36 | #define DRM_IVPU_PARAM_PLATFORM_TYPE 2 | ||
| 37 | #define DRM_IVPU_PARAM_CORE_CLOCK_RATE 3 | ||
| 38 | #define DRM_IVPU_PARAM_NUM_CONTEXTS 4 | ||
| 39 | #define DRM_IVPU_PARAM_CONTEXT_BASE_ADDRESS 5 | ||
| 40 | #define DRM_IVPU_PARAM_CONTEXT_PRIORITY 6 | ||
| 41 | |||
| 42 | #define DRM_IVPU_PLATFORM_TYPE_SILICON 0 | ||
| 43 | |||
| 44 | #define DRM_IVPU_CONTEXT_PRIORITY_IDLE 0 | ||
| 45 | #define DRM_IVPU_CONTEXT_PRIORITY_NORMAL 1 | ||
| 46 | #define DRM_IVPU_CONTEXT_PRIORITY_FOCUS 2 | ||
| 47 | #define DRM_IVPU_CONTEXT_PRIORITY_REALTIME 3 | ||
| 48 | |||
| 49 | /** | ||
| 50 | * struct drm_ivpu_param - Get/Set VPU parameters | ||
| 51 | */ | ||
| 52 | struct drm_ivpu_param { | ||
| 53 | /** | ||
| 54 | * @param: | ||
| 55 | * | ||
| 56 | * Supported params: | ||
| 57 | * | ||
| 58 | * %DRM_IVPU_PARAM_DEVICE_ID: | ||
| 59 | * PCI Device ID of the VPU device (read-only) | ||
| 60 | * | ||
| 61 | * %DRM_IVPU_PARAM_DEVICE_REVISION: | ||
| 62 | * VPU device revision (read-only) | ||
| 63 | * | ||
| 64 | * %DRM_IVPU_PARAM_PLATFORM_TYPE: | ||
| 65 | * Returns %DRM_IVPU_PLATFORM_TYPE_SILICON on real hardware or device specific | ||
| 66 | * platform type when executing on a simulator or emulator (read-only) | ||
| 67 | * | ||
| 68 | * %DRM_IVPU_PARAM_CORE_CLOCK_RATE: | ||
| 69 | * Current PLL frequency (read-only) | ||
| 70 | * | ||
| 71 | * %DRM_IVPU_PARAM_NUM_CONTEXTS: | ||
| 72 | * Maximum number of simultaneously existing contexts (read-only) | ||
| 73 | * | ||
| 74 | * %DRM_IVPU_PARAM_CONTEXT_BASE_ADDRESS: | ||
| 75 | * Lowest VPU virtual address available in the current context (read-only) | ||
| 76 | * | ||
| 77 | * %DRM_IVPU_PARAM_CONTEXT_PRIORITY: | ||
| 78 | * Value of current context scheduling priority (read-write). | ||
| 79 | * See DRM_IVPU_CONTEXT_PRIORITY_* for possible values. | ||
| 80 | * | ||
| 81 | */ | ||
| 82 | __u32 param; | ||
| 83 | |||
| 84 | /** @index: Index for params that have multiple instances */ | ||
| 85 | __u32 index; | ||
| 86 | |||
| 87 | /** @value: Param value */ | ||
| 88 | __u64 value; | ||
| 89 | }; | ||
| 90 | |||
| 91 | #if defined(__cplusplus) | ||
| 92 | } | ||
| 93 | #endif | ||
| 94 | |||
| 95 | #endif /* __UAPI_IVPU_DRM_H__ */ | ||