11// SPDX-License-Identifier: GPL-2.0-only
22/* Copyright 2023 Eileen Yoon <[email protected] > */ 33
4+ #include "isp-fw.h"
5+
46#include <linux/delay.h>
57#include <linux/pm_runtime.h>
68
@@ -37,6 +39,35 @@ static inline void isp_gpio_write32(struct apple_isp *isp, u32 reg, u32 val)
3739 writel (val , isp -> gpio + reg );
3840}
3941
42+ void * apple_isp_translate (struct apple_isp * isp , struct isp_surf * surf ,
43+ dma_addr_t iova , size_t size )
44+ {
45+ dma_addr_t end = iova + size ;
46+ if (!surf ) {
47+ dev_err (isp -> dev ,
48+ "Failed to translate IPC iova 0x%llx (0x%zx): No surface\n" ,
49+ (long long )iova , size );
50+ return NULL ;
51+ }
52+
53+ if (end < iova || iova < surf -> iova ||
54+ end > (surf -> iova + surf -> size )) {
55+ dev_err (isp -> dev ,
56+ "Failed to translate IPC iova 0x%llx (0x%zx): Out of bounds\n" ,
57+ (long long )iova , size );
58+ return NULL ;
59+ }
60+
61+ if (!surf -> virt ) {
62+ dev_err (isp -> dev ,
63+ "Failed to translate IPC iova 0x%llx (0x%zx): No VMap\n" ,
64+ (long long )iova , size );
65+ return NULL ;
66+ }
67+
68+ return surf -> virt + (iova - surf -> iova );
69+ }
70+
4071struct isp_firmware_bootargs {
4172 u32 pad_0 [2 ];
4273 u64 ipc_iova ;
@@ -231,13 +262,17 @@ int apple_isp_alloc_firmware_surface(struct apple_isp *isp)
231262 isp_err (isp , "failed to alloc shared surface for ipc\n" );
232263 return - ENOMEM ;
233264 }
265+ dev_info (isp -> dev , "IPC surface iova: 0x%llx\n" ,
266+ (long long )isp -> ipc_surf -> iova );
234267
235268 isp -> data_surf = isp_alloc_surface_vmap (isp , ISP_FIRMWARE_DATA_SIZE );
236269 if (!isp -> data_surf ) {
237270 isp_err (isp , "failed to alloc shared surface for data files\n" );
238271 isp_free_surface (isp , isp -> ipc_surf );
239272 return - ENOMEM ;
240273 }
274+ dev_info (isp -> dev , "Data surface iova: 0x%llx\n" ,
275+ (long long )isp -> data_surf -> iova );
241276
242277 return 0 ;
243278}
@@ -257,6 +292,7 @@ static int isp_firmware_boot_stage2(struct apple_isp *isp)
257292{
258293 struct isp_firmware_bootargs args ;
259294 dma_addr_t args_iova ;
295+ void * args_virt ;
260296 int err , retries ;
261297
262298 u32 num_ipc_chans = isp_gpio_read32 (isp , ISP_GPIO_0 );
@@ -280,7 +316,9 @@ static int isp_firmware_boot_stage2(struct apple_isp *isp)
280316 }
281317
282318 args_iova = isp -> ipc_surf -> iova + args_offset + 0x40 ;
319+ args_virt = isp -> ipc_surf -> virt + args_offset + 0x40 ;
283320 isp -> cmd_iova = args_iova + sizeof (args ) + 0x40 ;
321+ isp -> cmd_virt = args_virt + sizeof (args ) + 0x40 ;
284322
285323 memset (& args , 0 , sizeof (args ));
286324 args .ipc_iova = isp -> ipc_surf -> iova ;
@@ -294,7 +332,7 @@ static int isp_firmware_boot_stage2(struct apple_isp *isp)
294332 args .unk7 = 0x1 ; // 0?
295333 args .unk_iova1 = args_iova + sizeof (args ) - 0xc ;
296334 args .unk9 = 0x3 ;
297- isp_iowrite ( isp , args_iova , & args , sizeof (args ));
335+ memcpy ( args_virt , & args , sizeof (args ));
298336
299337 isp_gpio_write32 (isp , ISP_GPIO_0 , args_iova );
300338 isp_gpio_write32 (isp , ISP_GPIO_1 , args_iova >> 32 );
@@ -354,7 +392,15 @@ static void isp_free_channel_info(struct apple_isp *isp)
354392static int isp_fill_channel_info (struct apple_isp * isp )
355393{
356394 u64 table_iova = isp_gpio_read32 (isp , ISP_GPIO_0 ) |
357- ((u64 )isp_gpio_read32 (isp , ISP_GPIO_1 )) << 32 ;
395+ ((u64 )isp_gpio_read32 (isp , ISP_GPIO_1 )) << 32 ;
396+ void * table_virt = apple_isp_ipc_translate (
397+ isp , table_iova ,
398+ sizeof (struct isp_chan_desc ) * isp -> num_ipc_chans );
399+
400+ if (!table_virt ) {
401+ dev_err (isp -> dev , "Failed to find channel table\n" );
402+ return - EIO ;
403+ }
358404
359405 isp -> ipc_chans = kcalloc (isp -> num_ipc_chans ,
360406 sizeof (struct isp_channel * ), GFP_KERNEL );
@@ -363,24 +409,31 @@ static int isp_fill_channel_info(struct apple_isp *isp)
363409
364410 for (int i = 0 ; i < isp -> num_ipc_chans ; i ++ ) {
365411 struct isp_chan_desc desc ;
366- dma_addr_t desc_iova = table_iova + (i * sizeof (desc ));
412+ void * desc_virt = table_virt + (i * sizeof (desc ));
367413 struct isp_channel * chan =
368414 kzalloc (sizeof (struct isp_channel ), GFP_KERNEL );
369415 if (!chan )
370416 goto out ;
371417 isp -> ipc_chans [i ] = chan ;
372418
373- isp_ioread ( isp , desc_iova , & desc , sizeof (desc ));
419+ memcpy ( & desc , desc_virt , sizeof (desc ));
374420 chan -> name = kstrdup (desc .name , GFP_KERNEL );
375421 chan -> type = desc .type ;
376422 chan -> src = desc .src ;
377423 chan -> doorbell = 1 << chan -> src ;
378424 chan -> num = desc .num ;
379425 chan -> size = desc .num * ISP_IPC_MESSAGE_SIZE ;
380426 chan -> iova = desc .iova ;
427+ chan -> virt =
428+ apple_isp_ipc_translate (isp , desc .iova , chan -> size );
381429 chan -> cursor = 0 ;
382430 spin_lock_init (& chan -> lock );
383431
432+ if (!chan -> virt ) {
433+ dev_err (isp -> dev , "Failed to find channel buffer\n" );
434+ goto out ;
435+ }
436+
384437 if ((chan -> type != ISP_IPC_CHAN_TYPE_COMMAND ) &&
385438 (chan -> type != ISP_IPC_CHAN_TYPE_REPLY ) &&
386439 (chan -> type != ISP_IPC_CHAN_TYPE_REPORT )) {
@@ -438,11 +491,11 @@ static int isp_firmware_boot_stage3(struct apple_isp *isp)
438491 continue ;
439492 for (int j = 0 ; j < chan -> num ; j ++ ) {
440493 struct isp_message msg ;
441- dma_addr_t msg_iova = chan -> iova + (j * sizeof (msg ));
494+ void * msg_virt = chan -> virt + (j * sizeof (msg ));
442495
443496 memset (& msg , 0 , sizeof (msg ));
444497 msg .arg0 = ISP_IPC_FLAG_ACK ;
445- isp_iowrite ( isp , msg_iova , & msg , sizeof (msg ));
498+ memcpy ( msg_virt , & msg , sizeof (msg ));
446499 }
447500 }
448501 wmb ();
@@ -546,6 +599,10 @@ static int isp_start_command_processor(struct apple_isp *isp)
546599static void isp_collect_gc_surface (struct apple_isp * isp )
547600{
548601 struct isp_surf * tmp , * surf ;
602+
603+ isp -> log_surf = NULL ;
604+ isp -> bt_surf = NULL ;
605+
549606 list_for_each_entry_safe_reverse (surf , tmp , & isp -> gc , head ) {
550607 isp_dbg (isp , "freeing iova: 0x%llx size: 0x%llx virt: %pS\n" ,
551608 surf -> iova , surf -> size , (void * )surf -> virt );
0 commit comments