1*5a5e9c02SRob Herring (Arm) // SPDX-License-Identifier: GPL-2.0-only or MIT 2*5a5e9c02SRob Herring (Arm) // Copyright (C) 2025 Arm, Ltd. 3*5a5e9c02SRob Herring (Arm) 4*5a5e9c02SRob Herring (Arm) #include <linux/bitfield.h> 5*5a5e9c02SRob Herring (Arm) #include <linux/clk.h> 6*5a5e9c02SRob Herring (Arm) #include <linux/genalloc.h> 7*5a5e9c02SRob Herring (Arm) #include <linux/io.h> 8*5a5e9c02SRob Herring (Arm) #include <linux/iopoll.h> 9*5a5e9c02SRob Herring (Arm) #include <linux/module.h> 10*5a5e9c02SRob Herring (Arm) #include <linux/mod_devicetable.h> 11*5a5e9c02SRob Herring (Arm) #include <linux/platform_device.h> 12*5a5e9c02SRob Herring (Arm) #include <linux/pm_runtime.h> 13*5a5e9c02SRob Herring (Arm) 14*5a5e9c02SRob Herring (Arm) #include <drm/drm_drv.h> 15*5a5e9c02SRob Herring (Arm) #include <drm/drm_ioctl.h> 16*5a5e9c02SRob Herring (Arm) #include <drm/drm_utils.h> 17*5a5e9c02SRob Herring (Arm) #include <drm/drm_gem.h> 18*5a5e9c02SRob Herring (Arm) #include <drm/drm_accel.h> 19*5a5e9c02SRob Herring (Arm) #include <drm/ethosu_accel.h> 20*5a5e9c02SRob Herring (Arm) 21*5a5e9c02SRob Herring (Arm) #include "ethosu_drv.h" 22*5a5e9c02SRob Herring (Arm) #include "ethosu_device.h" 23*5a5e9c02SRob Herring (Arm) #include "ethosu_gem.h" 24*5a5e9c02SRob Herring (Arm) #include "ethosu_job.h" 25*5a5e9c02SRob Herring (Arm) 26*5a5e9c02SRob Herring (Arm) static int ethosu_ioctl_dev_query(struct drm_device *ddev, void *data, 27*5a5e9c02SRob Herring (Arm) struct drm_file *file) 28*5a5e9c02SRob Herring (Arm) { 29*5a5e9c02SRob Herring (Arm) struct ethosu_device *ethosudev = to_ethosu_device(ddev); 30*5a5e9c02SRob Herring (Arm) struct drm_ethosu_dev_query *args = data; 31*5a5e9c02SRob Herring (Arm) 32*5a5e9c02SRob Herring (Arm) if (!args->pointer) { 33*5a5e9c02SRob Herring (Arm) switch (args->type) { 34*5a5e9c02SRob Herring (Arm) case DRM_ETHOSU_DEV_QUERY_NPU_INFO: 35*5a5e9c02SRob Herring (Arm) args->size = sizeof(ethosudev->npu_info); 36*5a5e9c02SRob Herring (Arm) return 0; 37*5a5e9c02SRob Herring (Arm) default: 38*5a5e9c02SRob Herring (Arm) return -EINVAL; 39*5a5e9c02SRob Herring (Arm) } 40*5a5e9c02SRob Herring (Arm) } 41*5a5e9c02SRob Herring (Arm) 42*5a5e9c02SRob Herring (Arm) switch (args->type) { 43*5a5e9c02SRob Herring (Arm) case DRM_ETHOSU_DEV_QUERY_NPU_INFO: 44*5a5e9c02SRob Herring (Arm) if (args->size < offsetofend(struct drm_ethosu_npu_info, sram_size)) 45*5a5e9c02SRob Herring (Arm) return -EINVAL; 46*5a5e9c02SRob Herring (Arm) return copy_struct_to_user(u64_to_user_ptr(args->pointer), 47*5a5e9c02SRob Herring (Arm) args->size, 48*5a5e9c02SRob Herring (Arm) ðosudev->npu_info, 49*5a5e9c02SRob Herring (Arm) sizeof(ethosudev->npu_info), NULL); 50*5a5e9c02SRob Herring (Arm) default: 51*5a5e9c02SRob Herring (Arm) return -EINVAL; 52*5a5e9c02SRob Herring (Arm) } 53*5a5e9c02SRob Herring (Arm) } 54*5a5e9c02SRob Herring (Arm) 55*5a5e9c02SRob Herring (Arm) #define ETHOSU_BO_FLAGS DRM_ETHOSU_BO_NO_MMAP 56*5a5e9c02SRob Herring (Arm) 57*5a5e9c02SRob Herring (Arm) static int ethosu_ioctl_bo_create(struct drm_device *ddev, void *data, 58*5a5e9c02SRob Herring (Arm) struct drm_file *file) 59*5a5e9c02SRob Herring (Arm) { 60*5a5e9c02SRob Herring (Arm) struct drm_ethosu_bo_create *args = data; 61*5a5e9c02SRob Herring (Arm) int cookie, ret; 62*5a5e9c02SRob Herring (Arm) 63*5a5e9c02SRob Herring (Arm) if (!drm_dev_enter(ddev, &cookie)) 64*5a5e9c02SRob Herring (Arm) return -ENODEV; 65*5a5e9c02SRob Herring (Arm) 66*5a5e9c02SRob Herring (Arm) if (!args->size || (args->flags & ~ETHOSU_BO_FLAGS)) { 67*5a5e9c02SRob Herring (Arm) ret = -EINVAL; 68*5a5e9c02SRob Herring (Arm) goto out_dev_exit; 69*5a5e9c02SRob Herring (Arm) } 70*5a5e9c02SRob Herring (Arm) 71*5a5e9c02SRob Herring (Arm) ret = ethosu_gem_create_with_handle(file, ddev, &args->size, 72*5a5e9c02SRob Herring (Arm) args->flags, &args->handle); 73*5a5e9c02SRob Herring (Arm) 74*5a5e9c02SRob Herring (Arm) out_dev_exit: 75*5a5e9c02SRob Herring (Arm) drm_dev_exit(cookie); 76*5a5e9c02SRob Herring (Arm) return ret; 77*5a5e9c02SRob Herring (Arm) } 78*5a5e9c02SRob Herring (Arm) 79*5a5e9c02SRob Herring (Arm) static int ethosu_ioctl_bo_wait(struct drm_device *ddev, void *data, 80*5a5e9c02SRob Herring (Arm) struct drm_file *file) 81*5a5e9c02SRob Herring (Arm) { 82*5a5e9c02SRob Herring (Arm) struct drm_ethosu_bo_wait *args = data; 83*5a5e9c02SRob Herring (Arm) int cookie, ret; 84*5a5e9c02SRob Herring (Arm) unsigned long timeout = drm_timeout_abs_to_jiffies(args->timeout_ns); 85*5a5e9c02SRob Herring (Arm) 86*5a5e9c02SRob Herring (Arm) if (args->pad) 87*5a5e9c02SRob Herring (Arm) return -EINVAL; 88*5a5e9c02SRob Herring (Arm) 89*5a5e9c02SRob Herring (Arm) if (!drm_dev_enter(ddev, &cookie)) 90*5a5e9c02SRob Herring (Arm) return -ENODEV; 91*5a5e9c02SRob Herring (Arm) 92*5a5e9c02SRob Herring (Arm) ret = drm_gem_dma_resv_wait(file, args->handle, true, timeout); 93*5a5e9c02SRob Herring (Arm) 94*5a5e9c02SRob Herring (Arm) drm_dev_exit(cookie); 95*5a5e9c02SRob Herring (Arm) return ret; 96*5a5e9c02SRob Herring (Arm) } 97*5a5e9c02SRob Herring (Arm) 98*5a5e9c02SRob Herring (Arm) static int ethosu_ioctl_bo_mmap_offset(struct drm_device *ddev, void *data, 99*5a5e9c02SRob Herring (Arm) struct drm_file *file) 100*5a5e9c02SRob Herring (Arm) { 101*5a5e9c02SRob Herring (Arm) struct drm_ethosu_bo_mmap_offset *args = data; 102*5a5e9c02SRob Herring (Arm) struct drm_gem_object *obj; 103*5a5e9c02SRob Herring (Arm) 104*5a5e9c02SRob Herring (Arm) if (args->pad) 105*5a5e9c02SRob Herring (Arm) return -EINVAL; 106*5a5e9c02SRob Herring (Arm) 107*5a5e9c02SRob Herring (Arm) obj = drm_gem_object_lookup(file, args->handle); 108*5a5e9c02SRob Herring (Arm) if (!obj) 109*5a5e9c02SRob Herring (Arm) return -ENOENT; 110*5a5e9c02SRob Herring (Arm) 111*5a5e9c02SRob Herring (Arm) args->offset = drm_vma_node_offset_addr(&obj->vma_node); 112*5a5e9c02SRob Herring (Arm) drm_gem_object_put(obj); 113*5a5e9c02SRob Herring (Arm) return 0; 114*5a5e9c02SRob Herring (Arm) } 115*5a5e9c02SRob Herring (Arm) 116*5a5e9c02SRob Herring (Arm) static int ethosu_ioctl_cmdstream_bo_create(struct drm_device *ddev, void *data, 117*5a5e9c02SRob Herring (Arm) struct drm_file *file) 118*5a5e9c02SRob Herring (Arm) { 119*5a5e9c02SRob Herring (Arm) struct drm_ethosu_cmdstream_bo_create *args = data; 120*5a5e9c02SRob Herring (Arm) int cookie, ret; 121*5a5e9c02SRob Herring (Arm) 122*5a5e9c02SRob Herring (Arm) if (!drm_dev_enter(ddev, &cookie)) 123*5a5e9c02SRob Herring (Arm) return -ENODEV; 124*5a5e9c02SRob Herring (Arm) 125*5a5e9c02SRob Herring (Arm) if (!args->size || !args->data || args->pad || args->flags) { 126*5a5e9c02SRob Herring (Arm) ret = -EINVAL; 127*5a5e9c02SRob Herring (Arm) goto out_dev_exit; 128*5a5e9c02SRob Herring (Arm) } 129*5a5e9c02SRob Herring (Arm) 130*5a5e9c02SRob Herring (Arm) args->flags |= DRM_ETHOSU_BO_NO_MMAP; 131*5a5e9c02SRob Herring (Arm) 132*5a5e9c02SRob Herring (Arm) ret = ethosu_gem_cmdstream_create(file, ddev, args->size, args->data, 133*5a5e9c02SRob Herring (Arm) args->flags, &args->handle); 134*5a5e9c02SRob Herring (Arm) 135*5a5e9c02SRob Herring (Arm) out_dev_exit: 136*5a5e9c02SRob Herring (Arm) drm_dev_exit(cookie); 137*5a5e9c02SRob Herring (Arm) return ret; 138*5a5e9c02SRob Herring (Arm) } 139*5a5e9c02SRob Herring (Arm) 140*5a5e9c02SRob Herring (Arm) static int ethosu_open(struct drm_device *ddev, struct drm_file *file) 141*5a5e9c02SRob Herring (Arm) { 142*5a5e9c02SRob Herring (Arm) int ret = 0; 143*5a5e9c02SRob Herring (Arm) 144*5a5e9c02SRob Herring (Arm) if (!try_module_get(THIS_MODULE)) 145*5a5e9c02SRob Herring (Arm) return -EINVAL; 146*5a5e9c02SRob Herring (Arm) 147*5a5e9c02SRob Herring (Arm) struct ethosu_file_priv __free(kfree) *priv = kzalloc(sizeof(*priv), GFP_KERNEL); 148*5a5e9c02SRob Herring (Arm) if (!priv) { 149*5a5e9c02SRob Herring (Arm) ret = -ENOMEM; 150*5a5e9c02SRob Herring (Arm) goto err_put_mod; 151*5a5e9c02SRob Herring (Arm) } 152*5a5e9c02SRob Herring (Arm) priv->edev = to_ethosu_device(ddev); 153*5a5e9c02SRob Herring (Arm) 154*5a5e9c02SRob Herring (Arm) ret = ethosu_job_open(priv); 155*5a5e9c02SRob Herring (Arm) if (ret) 156*5a5e9c02SRob Herring (Arm) goto err_put_mod; 157*5a5e9c02SRob Herring (Arm) 158*5a5e9c02SRob Herring (Arm) file->driver_priv = no_free_ptr(priv); 159*5a5e9c02SRob Herring (Arm) return 0; 160*5a5e9c02SRob Herring (Arm) 161*5a5e9c02SRob Herring (Arm) err_put_mod: 162*5a5e9c02SRob Herring (Arm) module_put(THIS_MODULE); 163*5a5e9c02SRob Herring (Arm) return ret; 164*5a5e9c02SRob Herring (Arm) } 165*5a5e9c02SRob Herring (Arm) 166*5a5e9c02SRob Herring (Arm) static void ethosu_postclose(struct drm_device *ddev, struct drm_file *file) 167*5a5e9c02SRob Herring (Arm) { 168*5a5e9c02SRob Herring (Arm) ethosu_job_close(file->driver_priv); 169*5a5e9c02SRob Herring (Arm) kfree(file->driver_priv); 170*5a5e9c02SRob Herring (Arm) module_put(THIS_MODULE); 171*5a5e9c02SRob Herring (Arm) } 172*5a5e9c02SRob Herring (Arm) 173*5a5e9c02SRob Herring (Arm) static const struct drm_ioctl_desc ethosu_drm_driver_ioctls[] = { 174*5a5e9c02SRob Herring (Arm) #define ETHOSU_IOCTL(n, func, flags) \ 175*5a5e9c02SRob Herring (Arm) DRM_IOCTL_DEF_DRV(ETHOSU_##n, ethosu_ioctl_##func, flags) 176*5a5e9c02SRob Herring (Arm) 177*5a5e9c02SRob Herring (Arm) ETHOSU_IOCTL(DEV_QUERY, dev_query, 0), 178*5a5e9c02SRob Herring (Arm) ETHOSU_IOCTL(BO_CREATE, bo_create, 0), 179*5a5e9c02SRob Herring (Arm) ETHOSU_IOCTL(BO_WAIT, bo_wait, 0), 180*5a5e9c02SRob Herring (Arm) ETHOSU_IOCTL(BO_MMAP_OFFSET, bo_mmap_offset, 0), 181*5a5e9c02SRob Herring (Arm) ETHOSU_IOCTL(CMDSTREAM_BO_CREATE, cmdstream_bo_create, 0), 182*5a5e9c02SRob Herring (Arm) ETHOSU_IOCTL(SUBMIT, submit, 0), 183*5a5e9c02SRob Herring (Arm) }; 184*5a5e9c02SRob Herring (Arm) 185*5a5e9c02SRob Herring (Arm) DEFINE_DRM_ACCEL_FOPS(ethosu_drm_driver_fops); 186*5a5e9c02SRob Herring (Arm) 187*5a5e9c02SRob Herring (Arm) /* 188*5a5e9c02SRob Herring (Arm) * Ethosu driver version: 189*5a5e9c02SRob Herring (Arm) * - 1.0 - initial interface 190*5a5e9c02SRob Herring (Arm) */ 191*5a5e9c02SRob Herring (Arm) static const struct drm_driver ethosu_drm_driver = { 192*5a5e9c02SRob Herring (Arm) .driver_features = DRIVER_COMPUTE_ACCEL | DRIVER_GEM, 193*5a5e9c02SRob Herring (Arm) .open = ethosu_open, 194*5a5e9c02SRob Herring (Arm) .postclose = ethosu_postclose, 195*5a5e9c02SRob Herring (Arm) .ioctls = ethosu_drm_driver_ioctls, 196*5a5e9c02SRob Herring (Arm) .num_ioctls = ARRAY_SIZE(ethosu_drm_driver_ioctls), 197*5a5e9c02SRob Herring (Arm) .fops = ðosu_drm_driver_fops, 198*5a5e9c02SRob Herring (Arm) .name = "ethosu", 199*5a5e9c02SRob Herring (Arm) .desc = "Arm Ethos-U Accel driver", 200*5a5e9c02SRob Herring (Arm) .major = 1, 201*5a5e9c02SRob Herring (Arm) .minor = 0, 202*5a5e9c02SRob Herring (Arm) 203*5a5e9c02SRob Herring (Arm) .gem_create_object = ethosu_gem_create_object, 204*5a5e9c02SRob Herring (Arm) }; 205*5a5e9c02SRob Herring (Arm) 206*5a5e9c02SRob Herring (Arm) #define U65_DRAM_AXI_LIMIT_CFG 0x1f3f0002 207*5a5e9c02SRob Herring (Arm) #define U65_SRAM_AXI_LIMIT_CFG 0x1f3f00b0 208*5a5e9c02SRob Herring (Arm) #define U85_AXI_EXT_CFG 0x00021f3f 209*5a5e9c02SRob Herring (Arm) #define U85_AXI_SRAM_CFG 0x00021f3f 210*5a5e9c02SRob Herring (Arm) #define U85_MEM_ATTR0_CFG 0x00000000 211*5a5e9c02SRob Herring (Arm) #define U85_MEM_ATTR2_CFG 0x000000b7 212*5a5e9c02SRob Herring (Arm) 213*5a5e9c02SRob Herring (Arm) static int ethosu_reset(struct ethosu_device *ethosudev) 214*5a5e9c02SRob Herring (Arm) { 215*5a5e9c02SRob Herring (Arm) int ret; 216*5a5e9c02SRob Herring (Arm) u32 reg; 217*5a5e9c02SRob Herring (Arm) 218*5a5e9c02SRob Herring (Arm) writel_relaxed(RESET_PENDING_CSL, ethosudev->regs + NPU_REG_RESET); 219*5a5e9c02SRob Herring (Arm) ret = readl_poll_timeout(ethosudev->regs + NPU_REG_STATUS, reg, 220*5a5e9c02SRob Herring (Arm) !FIELD_GET(STATUS_RESET_STATUS, reg), 221*5a5e9c02SRob Herring (Arm) USEC_PER_MSEC, USEC_PER_SEC); 222*5a5e9c02SRob Herring (Arm) if (ret) 223*5a5e9c02SRob Herring (Arm) return ret; 224*5a5e9c02SRob Herring (Arm) 225*5a5e9c02SRob Herring (Arm) if (!FIELD_GET(PROT_ACTIVE_CSL, readl_relaxed(ethosudev->regs + NPU_REG_PROT))) { 226*5a5e9c02SRob Herring (Arm) dev_warn(ethosudev->base.dev, "Could not reset to non-secure mode (PROT = %x)\n", 227*5a5e9c02SRob Herring (Arm) readl_relaxed(ethosudev->regs + NPU_REG_PROT)); 228*5a5e9c02SRob Herring (Arm) } 229*5a5e9c02SRob Herring (Arm) 230*5a5e9c02SRob Herring (Arm) /* 231*5a5e9c02SRob Herring (Arm) * Assign region 2 (SRAM) to AXI M0 (AXILIMIT0), 232*5a5e9c02SRob Herring (Arm) * everything else to AXI M1 (AXILIMIT2) 233*5a5e9c02SRob Herring (Arm) */ 234*5a5e9c02SRob Herring (Arm) writel_relaxed(0x0000aa8a, ethosudev->regs + NPU_REG_REGIONCFG); 235*5a5e9c02SRob Herring (Arm) if (ethosu_is_u65(ethosudev)) { 236*5a5e9c02SRob Herring (Arm) writel_relaxed(U65_SRAM_AXI_LIMIT_CFG, ethosudev->regs + NPU_REG_AXILIMIT0); 237*5a5e9c02SRob Herring (Arm) writel_relaxed(U65_DRAM_AXI_LIMIT_CFG, ethosudev->regs + NPU_REG_AXILIMIT2); 238*5a5e9c02SRob Herring (Arm) } else { 239*5a5e9c02SRob Herring (Arm) writel_relaxed(U85_AXI_SRAM_CFG, ethosudev->regs + NPU_REG_AXI_SRAM); 240*5a5e9c02SRob Herring (Arm) writel_relaxed(U85_AXI_EXT_CFG, ethosudev->regs + NPU_REG_AXI_EXT); 241*5a5e9c02SRob Herring (Arm) writel_relaxed(U85_MEM_ATTR0_CFG, ethosudev->regs + NPU_REG_MEM_ATTR0); // SRAM 242*5a5e9c02SRob Herring (Arm) writel_relaxed(U85_MEM_ATTR2_CFG, ethosudev->regs + NPU_REG_MEM_ATTR2); // DRAM 243*5a5e9c02SRob Herring (Arm) } 244*5a5e9c02SRob Herring (Arm) 245*5a5e9c02SRob Herring (Arm) if (ethosudev->sram) 246*5a5e9c02SRob Herring (Arm) memset_io(ethosudev->sram, 0, ethosudev->npu_info.sram_size); 247*5a5e9c02SRob Herring (Arm) 248*5a5e9c02SRob Herring (Arm) return 0; 249*5a5e9c02SRob Herring (Arm) } 250*5a5e9c02SRob Herring (Arm) 251*5a5e9c02SRob Herring (Arm) static int ethosu_device_resume(struct device *dev) 252*5a5e9c02SRob Herring (Arm) { 253*5a5e9c02SRob Herring (Arm) struct ethosu_device *ethosudev = dev_get_drvdata(dev); 254*5a5e9c02SRob Herring (Arm) int ret; 255*5a5e9c02SRob Herring (Arm) 256*5a5e9c02SRob Herring (Arm) ret = clk_bulk_prepare_enable(ethosudev->num_clks, ethosudev->clks); 257*5a5e9c02SRob Herring (Arm) if (ret) 258*5a5e9c02SRob Herring (Arm) return ret; 259*5a5e9c02SRob Herring (Arm) 260*5a5e9c02SRob Herring (Arm) ret = ethosu_reset(ethosudev); 261*5a5e9c02SRob Herring (Arm) if (!ret) 262*5a5e9c02SRob Herring (Arm) return 0; 263*5a5e9c02SRob Herring (Arm) 264*5a5e9c02SRob Herring (Arm) clk_bulk_disable_unprepare(ethosudev->num_clks, ethosudev->clks); 265*5a5e9c02SRob Herring (Arm) return ret; 266*5a5e9c02SRob Herring (Arm) } 267*5a5e9c02SRob Herring (Arm) 268*5a5e9c02SRob Herring (Arm) static int ethosu_device_suspend(struct device *dev) 269*5a5e9c02SRob Herring (Arm) { 270*5a5e9c02SRob Herring (Arm) struct ethosu_device *ethosudev = dev_get_drvdata(dev); 271*5a5e9c02SRob Herring (Arm) 272*5a5e9c02SRob Herring (Arm) clk_bulk_disable_unprepare(ethosudev->num_clks, ethosudev->clks); 273*5a5e9c02SRob Herring (Arm) return 0; 274*5a5e9c02SRob Herring (Arm) } 275*5a5e9c02SRob Herring (Arm) 276*5a5e9c02SRob Herring (Arm) static int ethosu_sram_init(struct ethosu_device *ethosudev) 277*5a5e9c02SRob Herring (Arm) { 278*5a5e9c02SRob Herring (Arm) ethosudev->npu_info.sram_size = 0; 279*5a5e9c02SRob Herring (Arm) 280*5a5e9c02SRob Herring (Arm) ethosudev->srampool = of_gen_pool_get(ethosudev->base.dev->of_node, "sram", 0); 281*5a5e9c02SRob Herring (Arm) if (!ethosudev->srampool) 282*5a5e9c02SRob Herring (Arm) return 0; 283*5a5e9c02SRob Herring (Arm) 284*5a5e9c02SRob Herring (Arm) ethosudev->npu_info.sram_size = gen_pool_size(ethosudev->srampool); 285*5a5e9c02SRob Herring (Arm) 286*5a5e9c02SRob Herring (Arm) ethosudev->sram = (void __iomem *)gen_pool_dma_alloc(ethosudev->srampool, 287*5a5e9c02SRob Herring (Arm) ethosudev->npu_info.sram_size, 288*5a5e9c02SRob Herring (Arm) ðosudev->sramphys); 289*5a5e9c02SRob Herring (Arm) if (!ethosudev->sram) { 290*5a5e9c02SRob Herring (Arm) dev_err(ethosudev->base.dev, "failed to allocate from SRAM pool\n"); 291*5a5e9c02SRob Herring (Arm) return -ENOMEM; 292*5a5e9c02SRob Herring (Arm) } 293*5a5e9c02SRob Herring (Arm) 294*5a5e9c02SRob Herring (Arm) return 0; 295*5a5e9c02SRob Herring (Arm) } 296*5a5e9c02SRob Herring (Arm) 297*5a5e9c02SRob Herring (Arm) static int ethosu_init(struct ethosu_device *ethosudev) 298*5a5e9c02SRob Herring (Arm) { 299*5a5e9c02SRob Herring (Arm) int ret; 300*5a5e9c02SRob Herring (Arm) u32 id, config; 301*5a5e9c02SRob Herring (Arm) 302*5a5e9c02SRob Herring (Arm) ret = ethosu_device_resume(ethosudev->base.dev); 303*5a5e9c02SRob Herring (Arm) if (ret) 304*5a5e9c02SRob Herring (Arm) return ret; 305*5a5e9c02SRob Herring (Arm) 306*5a5e9c02SRob Herring (Arm) pm_runtime_set_autosuspend_delay(ethosudev->base.dev, 50); 307*5a5e9c02SRob Herring (Arm) pm_runtime_use_autosuspend(ethosudev->base.dev); 308*5a5e9c02SRob Herring (Arm) ret = devm_pm_runtime_set_active_enabled(ethosudev->base.dev); 309*5a5e9c02SRob Herring (Arm) if (ret) 310*5a5e9c02SRob Herring (Arm) return ret; 311*5a5e9c02SRob Herring (Arm) pm_runtime_get_noresume(ethosudev->base.dev); 312*5a5e9c02SRob Herring (Arm) 313*5a5e9c02SRob Herring (Arm) ethosudev->npu_info.id = id = readl_relaxed(ethosudev->regs + NPU_REG_ID); 314*5a5e9c02SRob Herring (Arm) ethosudev->npu_info.config = config = readl_relaxed(ethosudev->regs + NPU_REG_CONFIG); 315*5a5e9c02SRob Herring (Arm) 316*5a5e9c02SRob Herring (Arm) ethosu_sram_init(ethosudev); 317*5a5e9c02SRob Herring (Arm) 318*5a5e9c02SRob Herring (Arm) dev_info(ethosudev->base.dev, 319*5a5e9c02SRob Herring (Arm) "Ethos-U NPU, arch v%ld.%ld.%ld, rev r%ldp%ld, cmd stream ver%ld, %d MACs, %dKB SRAM\n", 320*5a5e9c02SRob Herring (Arm) FIELD_GET(ID_ARCH_MAJOR_MASK, id), 321*5a5e9c02SRob Herring (Arm) FIELD_GET(ID_ARCH_MINOR_MASK, id), 322*5a5e9c02SRob Herring (Arm) FIELD_GET(ID_ARCH_PATCH_MASK, id), 323*5a5e9c02SRob Herring (Arm) FIELD_GET(ID_VER_MAJOR_MASK, id), 324*5a5e9c02SRob Herring (Arm) FIELD_GET(ID_VER_MINOR_MASK, id), 325*5a5e9c02SRob Herring (Arm) FIELD_GET(CONFIG_CMD_STREAM_VER_MASK, config), 326*5a5e9c02SRob Herring (Arm) 1 << FIELD_GET(CONFIG_MACS_PER_CC_MASK, config), 327*5a5e9c02SRob Herring (Arm) ethosudev->npu_info.sram_size / 1024); 328*5a5e9c02SRob Herring (Arm) 329*5a5e9c02SRob Herring (Arm) return 0; 330*5a5e9c02SRob Herring (Arm) } 331*5a5e9c02SRob Herring (Arm) 332*5a5e9c02SRob Herring (Arm) static int ethosu_probe(struct platform_device *pdev) 333*5a5e9c02SRob Herring (Arm) { 334*5a5e9c02SRob Herring (Arm) int ret; 335*5a5e9c02SRob Herring (Arm) struct ethosu_device *ethosudev; 336*5a5e9c02SRob Herring (Arm) 337*5a5e9c02SRob Herring (Arm) ethosudev = devm_drm_dev_alloc(&pdev->dev, ðosu_drm_driver, 338*5a5e9c02SRob Herring (Arm) struct ethosu_device, base); 339*5a5e9c02SRob Herring (Arm) if (IS_ERR(ethosudev)) 340*5a5e9c02SRob Herring (Arm) return -ENOMEM; 341*5a5e9c02SRob Herring (Arm) platform_set_drvdata(pdev, ethosudev); 342*5a5e9c02SRob Herring (Arm) 343*5a5e9c02SRob Herring (Arm) dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40)); 344*5a5e9c02SRob Herring (Arm) 345*5a5e9c02SRob Herring (Arm) ethosudev->regs = devm_platform_ioremap_resource(pdev, 0); 346*5a5e9c02SRob Herring (Arm) 347*5a5e9c02SRob Herring (Arm) ethosudev->num_clks = devm_clk_bulk_get_all(&pdev->dev, ðosudev->clks); 348*5a5e9c02SRob Herring (Arm) if (ethosudev->num_clks < 0) 349*5a5e9c02SRob Herring (Arm) return ethosudev->num_clks; 350*5a5e9c02SRob Herring (Arm) 351*5a5e9c02SRob Herring (Arm) ret = ethosu_job_init(ethosudev); 352*5a5e9c02SRob Herring (Arm) if (ret) 353*5a5e9c02SRob Herring (Arm) return ret; 354*5a5e9c02SRob Herring (Arm) 355*5a5e9c02SRob Herring (Arm) ret = ethosu_init(ethosudev); 356*5a5e9c02SRob Herring (Arm) if (ret) 357*5a5e9c02SRob Herring (Arm) return ret; 358*5a5e9c02SRob Herring (Arm) 359*5a5e9c02SRob Herring (Arm) ret = drm_dev_register(ðosudev->base, 0); 360*5a5e9c02SRob Herring (Arm) if (ret) 361*5a5e9c02SRob Herring (Arm) pm_runtime_dont_use_autosuspend(ethosudev->base.dev); 362*5a5e9c02SRob Herring (Arm) 363*5a5e9c02SRob Herring (Arm) pm_runtime_put_autosuspend(ethosudev->base.dev); 364*5a5e9c02SRob Herring (Arm) return ret; 365*5a5e9c02SRob Herring (Arm) } 366*5a5e9c02SRob Herring (Arm) 367*5a5e9c02SRob Herring (Arm) static void ethosu_remove(struct platform_device *pdev) 368*5a5e9c02SRob Herring (Arm) { 369*5a5e9c02SRob Herring (Arm) struct ethosu_device *ethosudev = dev_get_drvdata(&pdev->dev); 370*5a5e9c02SRob Herring (Arm) 371*5a5e9c02SRob Herring (Arm) drm_dev_unregister(ðosudev->base); 372*5a5e9c02SRob Herring (Arm) ethosu_job_fini(ethosudev); 373*5a5e9c02SRob Herring (Arm) if (ethosudev->sram) 374*5a5e9c02SRob Herring (Arm) gen_pool_free(ethosudev->srampool, (unsigned long)ethosudev->sram, 375*5a5e9c02SRob Herring (Arm) ethosudev->npu_info.sram_size); 376*5a5e9c02SRob Herring (Arm) } 377*5a5e9c02SRob Herring (Arm) 378*5a5e9c02SRob Herring (Arm) static const struct of_device_id dt_match[] = { 379*5a5e9c02SRob Herring (Arm) { .compatible = "arm,ethos-u65" }, 380*5a5e9c02SRob Herring (Arm) { .compatible = "arm,ethos-u85" }, 381*5a5e9c02SRob Herring (Arm) {} 382*5a5e9c02SRob Herring (Arm) }; 383*5a5e9c02SRob Herring (Arm) MODULE_DEVICE_TABLE(of, dt_match); 384*5a5e9c02SRob Herring (Arm) 385*5a5e9c02SRob Herring (Arm) static DEFINE_RUNTIME_DEV_PM_OPS(ethosu_pm_ops, 386*5a5e9c02SRob Herring (Arm) ethosu_device_suspend, 387*5a5e9c02SRob Herring (Arm) ethosu_device_resume, 388*5a5e9c02SRob Herring (Arm) NULL); 389*5a5e9c02SRob Herring (Arm) 390*5a5e9c02SRob Herring (Arm) static struct platform_driver ethosu_driver = { 391*5a5e9c02SRob Herring (Arm) .probe = ethosu_probe, 392*5a5e9c02SRob Herring (Arm) .remove = ethosu_remove, 393*5a5e9c02SRob Herring (Arm) .driver = { 394*5a5e9c02SRob Herring (Arm) .name = "ethosu", 395*5a5e9c02SRob Herring (Arm) .pm = pm_ptr(ðosu_pm_ops), 396*5a5e9c02SRob Herring (Arm) .of_match_table = dt_match, 397*5a5e9c02SRob Herring (Arm) }, 398*5a5e9c02SRob Herring (Arm) }; 399*5a5e9c02SRob Herring (Arm) module_platform_driver(ethosu_driver); 400*5a5e9c02SRob Herring (Arm) 401*5a5e9c02SRob Herring (Arm) MODULE_AUTHOR("Rob Herring <robh@kernel.org>"); 402*5a5e9c02SRob Herring (Arm) MODULE_DESCRIPTION("Arm Ethos-U Accel Driver"); 403*5a5e9c02SRob Herring (Arm) MODULE_LICENSE("Dual MIT/GPL"); 404