1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2025 Advanced Micro Devices, Inc. 4 */ 5 6 #include <linux/irq.h> 7 #include <linux/pm_runtime.h> 8 #include <linux/vmalloc.h> 9 #include <media/v4l2-ioctl.h> 10 11 #include "isp4.h" 12 #include "isp4_hw_reg.h" 13 14 #define ISP4_DRV_NAME "amd_isp_capture" 15 #define ISP4_FW_RESP_RB_IRQ_STATUS_MASK \ 16 (ISP_SYS_INT0_STATUS__SYS_INT_RINGBUFFER_WPT9_INT_MASK | \ 17 ISP_SYS_INT0_STATUS__SYS_INT_RINGBUFFER_WPT12_INT_MASK) 18 19 static const struct { 20 const char *name; 21 u32 status_mask; 22 u32 en_mask; 23 u32 ack_mask; 24 u32 rb_int_num; 25 } isp4_irq[ISP4SD_MAX_FW_RESP_STREAM_NUM] = { 26 /* The IRQ order is aligned with the isp4_subdev.fw_resp_thread order */ 27 { 28 .name = "isp_irq_global", 29 .status_mask = 30 ISP_SYS_INT0_STATUS__SYS_INT_RINGBUFFER_WPT12_INT_MASK, 31 .en_mask = ISP_SYS_INT0_EN__SYS_INT_RINGBUFFER_WPT12_EN_MASK, 32 .ack_mask = ISP_SYS_INT0_ACK__SYS_INT_RINGBUFFER_WPT12_ACK_MASK, 33 .rb_int_num = 4, /* ISP_4_1__SRCID__ISP_RINGBUFFER_WPT12 */ 34 }, 35 { 36 .name = "isp_irq_stream1", 37 .status_mask = 38 ISP_SYS_INT0_STATUS__SYS_INT_RINGBUFFER_WPT9_INT_MASK, 39 .en_mask = ISP_SYS_INT0_EN__SYS_INT_RINGBUFFER_WPT9_EN_MASK, 40 .ack_mask = ISP_SYS_INT0_ACK__SYS_INT_RINGBUFFER_WPT9_ACK_MASK, 41 .rb_int_num = 0, /* ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9 */ 42 }, 43 }; 44 45 void isp4_intr_enable(struct isp4_subdev *isp_subdev, u32 index, bool enable) 46 { 47 u32 intr_en; 48 49 /* Synchronize ISP_SYS_INT0_EN writes with the IRQ handler's writes */ 50 spin_lock_irq(&isp_subdev->irq_lock); 51 intr_en = isp4hw_rreg(isp_subdev->mmio, ISP_SYS_INT0_EN); 52 if (enable) 53 intr_en |= isp4_irq[index].en_mask; 54 else 55 intr_en &= ~isp4_irq[index].en_mask; 56 57 isp4hw_wreg(isp_subdev->mmio, ISP_SYS_INT0_EN, intr_en); 58 spin_unlock_irq(&isp_subdev->irq_lock); 59 } 60 61 static void isp4_wake_up_resp_thread(struct isp4_subdev *isp_subdev, u32 index) 62 { 63 struct isp4sd_thread_handler *thread_ctx = 64 &isp_subdev->fw_resp_thread[index]; 65 66 thread_ctx->resp_ready = true; 67 wake_up_interruptible(&thread_ctx->waitq); 68 } 69 70 static irqreturn_t isp4_irq_handler(int irq, void *arg) 71 { 72 struct isp4_subdev *isp_subdev = arg; 73 u32 intr_ack = 0, intr_en = 0, intr_status; 74 int seen = 0; 75 76 /* Get the ISP_SYS interrupt status */ 77 intr_status = isp4hw_rreg(isp_subdev->mmio, ISP_SYS_INT0_STATUS); 78 intr_status &= ISP4_FW_RESP_RB_IRQ_STATUS_MASK; 79 80 /* Find which ISP_SYS interrupts fired */ 81 for (size_t i = 0; i < ARRAY_SIZE(isp4_irq); i++) { 82 if (intr_status & isp4_irq[i].status_mask) { 83 intr_ack |= isp4_irq[i].ack_mask; 84 intr_en |= isp4_irq[i].en_mask; 85 seen |= BIT(i); 86 } 87 } 88 89 /* 90 * Disable the ISP_SYS interrupts that fired. Must be done before waking 91 * the response threads, since they re-enable interrupts when finished. 92 * The lock synchronizes RMW of INT0_EN with isp4_enable_interrupt(). 93 */ 94 spin_lock(&isp_subdev->irq_lock); 95 intr_en = isp4hw_rreg(isp_subdev->mmio, ISP_SYS_INT0_EN) & ~intr_en; 96 isp4hw_wreg(isp_subdev->mmio, ISP_SYS_INT0_EN, intr_en); 97 spin_unlock(&isp_subdev->irq_lock); 98 99 /* 100 * Clear the ISP_SYS interrupts. This must be done after the interrupts 101 * are disabled, so that ISP FW won't flag any new interrupts on these 102 * streams, and thus we don't need to clear interrupts again before 103 * re-enabling them in the response thread. 104 */ 105 isp4hw_wreg(isp_subdev->mmio, ISP_SYS_INT0_ACK, intr_ack); 106 107 /* 108 * The operation `(seen >> i) << i` is logically equivalent to 109 * `seen &= ~BIT(i)`, with fewer instructions after compilation. 110 */ 111 for (int i; (i = ffs(seen)); seen = (seen >> i) << i) 112 isp4_wake_up_resp_thread(isp_subdev, i - 1); 113 114 return IRQ_HANDLED; 115 } 116 117 static int isp4_capture_probe(struct platform_device *pdev) 118 { 119 int irq[ISP4SD_MAX_FW_RESP_STREAM_NUM]; 120 struct device *dev = &pdev->dev; 121 struct isp4_subdev *isp_subdev; 122 struct isp4_device *isp_dev; 123 int ret; 124 125 isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL); 126 if (!isp_dev) 127 return -ENOMEM; 128 129 dev->init_name = ISP4_DRV_NAME; 130 131 isp_subdev = &isp_dev->isp_subdev; 132 isp_subdev->mmio = devm_platform_ioremap_resource(pdev, 0); 133 if (IS_ERR(isp_subdev->mmio)) 134 return dev_err_probe(dev, PTR_ERR(isp_subdev->mmio), 135 "isp ioremap fail\n"); 136 137 for (size_t i = 0; i < ARRAY_SIZE(isp4_irq); i++) { 138 irq[i] = platform_get_irq(pdev, isp4_irq[i].rb_int_num); 139 if (irq[i] < 0) 140 return dev_err_probe(dev, irq[i], 141 "fail to get irq %d\n", 142 isp4_irq[i].rb_int_num); 143 144 ret = devm_request_irq(dev, irq[i], isp4_irq_handler, 145 IRQF_NO_AUTOEN, isp4_irq[i].name, 146 isp_subdev); 147 if (ret) 148 return dev_err_probe(dev, ret, "fail to req irq %d\n", 149 irq[i]); 150 } 151 152 isp_dev->v4l2_dev.mdev = &isp_dev->mdev; 153 154 strscpy(isp_dev->mdev.model, "amd_isp41_mdev", 155 sizeof(isp_dev->mdev.model)); 156 isp_dev->mdev.dev = dev; 157 media_device_init(&isp_dev->mdev); 158 159 snprintf(isp_dev->v4l2_dev.name, sizeof(isp_dev->v4l2_dev.name), 160 "AMD-V4L2-ROOT"); 161 ret = v4l2_device_register(dev, &isp_dev->v4l2_dev); 162 if (ret) { 163 dev_err_probe(dev, ret, "fail register v4l2 device\n"); 164 goto err_clean_media; 165 } 166 167 pm_runtime_set_suspended(dev); 168 pm_runtime_enable(dev); 169 spin_lock_init(&isp_subdev->irq_lock); 170 ret = isp4sd_init(&isp_dev->isp_subdev, &isp_dev->v4l2_dev, irq); 171 if (ret) { 172 dev_err_probe(dev, ret, "fail init isp4 sub dev\n"); 173 goto err_pm_disable; 174 } 175 176 ret = media_create_pad_link(&isp_dev->isp_subdev.sdev.entity, 177 0, 178 &isp_dev->isp_subdev.isp_vdev.vdev.entity, 179 0, 180 MEDIA_LNK_FL_ENABLED | 181 MEDIA_LNK_FL_IMMUTABLE); 182 if (ret) { 183 dev_err_probe(dev, ret, "fail to create pad link\n"); 184 goto err_isp4_deinit; 185 } 186 187 ret = media_device_register(&isp_dev->mdev); 188 if (ret) { 189 dev_err_probe(dev, ret, "fail to register media device\n"); 190 goto err_isp4_deinit; 191 } 192 193 platform_set_drvdata(pdev, isp_dev); 194 195 return 0; 196 197 err_isp4_deinit: 198 isp4sd_deinit(&isp_dev->isp_subdev); 199 err_pm_disable: 200 pm_runtime_disable(dev); 201 v4l2_device_unregister(&isp_dev->v4l2_dev); 202 err_clean_media: 203 media_device_cleanup(&isp_dev->mdev); 204 205 return ret; 206 } 207 208 static void isp4_capture_remove(struct platform_device *pdev) 209 { 210 struct isp4_device *isp_dev = platform_get_drvdata(pdev); 211 struct device *dev = &pdev->dev; 212 213 media_device_unregister(&isp_dev->mdev); 214 isp4sd_deinit(&isp_dev->isp_subdev); 215 pm_runtime_disable(dev); 216 v4l2_device_unregister(&isp_dev->v4l2_dev); 217 media_device_cleanup(&isp_dev->mdev); 218 } 219 220 static struct platform_driver isp4_capture_drv = { 221 .probe = isp4_capture_probe, 222 .remove = isp4_capture_remove, 223 .driver = { 224 .name = ISP4_DRV_NAME, 225 } 226 }; 227 228 module_platform_driver(isp4_capture_drv); 229 230 MODULE_ALIAS("platform:" ISP4_DRV_NAME); 231 MODULE_IMPORT_NS("DMA_BUF"); 232 233 MODULE_DESCRIPTION("AMD ISP4 Driver"); 234 MODULE_AUTHOR("Bin Du <bin.du@amd.com>"); 235 MODULE_AUTHOR("Pratap Nirujogi <pratap.nirujogi@amd.com>"); 236 MODULE_LICENSE("GPL"); 237