2828#include "cam_icp_context.h"
2929#include "cam_hw_mgr_intf.h"
3030#include "cam_icp_hw_mgr_intf.h"
31+ #include "cam_icp_hw_intf.h"
3132#include "cam_debug_util.h"
3233#include "cam_smmu_api.h"
3334#include "camera_main.h"
@@ -50,6 +51,7 @@ struct cam_icp_subdev {
5051 int32_t reserved ;
5152};
5253
54+ struct camera_firmware cam_fw ;
5355static DEFINE_MUTEX (g_dev_lock );
5456static struct cam_icp_subdev * g_icp_dev [CAM_ICP_SUBDEV_MAX ];
5557
@@ -257,6 +259,89 @@ static inline int cam_icp_subdev_clean_up(uint32_t device_idx)
257259 return 0 ;
258260}
259261
262+ void cam_put_domain_for_fw (struct camera_firmware * fw )
263+ {
264+ if (!fw )
265+ return ;
266+
267+ if (fw -> iommu_domain ) {
268+ /*
269+ * No explicit release function for iommu_get_domain_for_dev,
270+ * but if you attached a domain, detach it here.
271+ */
272+ iommu_detach_device (fw -> iommu_domain , fw -> dev );
273+ fw -> iommu_domain = NULL ;
274+ }
275+
276+ if (fw -> dev ) {
277+ of_node_put (fw -> dev -> of_node );
278+ platform_device_unregister (to_platform_device (fw -> dev ));
279+ fw -> dev = NULL ;
280+ }
281+
282+ fw -> has_el2_iommu = false;
283+ }
284+
285+ static int cam_get_domain_for_fw (struct device * dev , struct camera_firmware * fw )
286+ {
287+ struct platform_device * pdev_fw = NULL ;
288+ struct platform_device_info info ;
289+ struct device_node * np = NULL ;
290+ int rc = 0 ;
291+
292+ np = of_get_child_by_name (dev -> of_node , "camera-firmware" );
293+ if (!np ) {
294+ CAM_INFO (CAM_ICP , "camera-firmware, not overlayed. no KVM" );
295+ fw -> has_el2_iommu = false;
296+ return 0 ;
297+ }
298+
299+ fw -> has_el2_iommu = true;
300+ memset (& info , 0 , sizeof (info ));
301+ info .fwnode = & np -> fwnode ;
302+ info .parent = dev ;
303+ info .name = np -> name ;
304+ info .dma_mask = DMA_BIT_MASK (32 );
305+
306+ pdev_fw = platform_device_register_full (& info );
307+ if (IS_ERR (pdev_fw )) {
308+ rc = PTR_ERR (pdev_fw );
309+ CAM_ERR (CAM_ICP , "platform_device_register_full failed: %d" , rc );
310+ goto cleanup_np ;
311+ }
312+
313+ pdev_fw -> dev .of_node = np ;
314+
315+ rc = of_dma_configure (& pdev_fw -> dev , np , true);
316+ if (rc ) {
317+ CAM_ERR (CAM_ICP , "DMA configuration failed: %d" , rc );
318+ pdev_fw -> dev .of_node = NULL ;
319+ goto unregister_pdev ;
320+ }
321+
322+ fw -> dev = & pdev_fw -> dev ;
323+
324+ fw -> iommu_domain = iommu_get_domain_for_dev (fw -> dev );
325+ if (!fw -> iommu_domain ) {
326+ CAM_ERR (CAM_ICP , "Failed to get IOMMU domain" );
327+ rc = - ENOMEM ;
328+ goto unregister_pdev ;
329+ }
330+
331+ CAM_INFO (CAM_ICP , "KVM Enabled - fw.dev: %p, fw.iommu_domain: %p" , fw -> dev ,
332+ fw -> iommu_domain );
333+ return 0 ;
334+
335+ unregister_pdev :
336+ platform_device_unregister (pdev_fw );
337+ fw -> dev = NULL ;
338+
339+ cleanup_np :
340+ of_node_put (np );
341+ fw -> has_el2_iommu = false;
342+ return rc ;
343+ }
344+
260345static int cam_icp_component_bind (struct device * dev ,
261346 struct device * master_dev , void * data )
262347{
@@ -356,6 +441,12 @@ static int cam_icp_component_bind(struct device *dev,
356441 goto ctx_fail ;
357442 }
358443
444+ rc = cam_get_domain_for_fw (dev , & cam_fw );
445+ if (rc ) {
446+ CAM_ERR (CAM_ICP , "device[%s] get domain for fw failed: %d" , subdev_name , rc );
447+ goto ctx_fail ;
448+ }
449+
359450 cam_common_register_evt_inject_cb (cam_icp_dev_evt_inject_cb ,
360451 CAM_COMMON_EVT_INJECT_HW_ICP );
361452
@@ -364,12 +455,18 @@ static int cam_icp_component_bind(struct device *dev,
364455
365456 icp_dev -> open_cnt = 0 ;
366457 rc = cam_subdev_register (& icp_dev -> sd , pdev );
458+ if (rc ) {
459+ CAM_ERR (CAM_ICP , "device[%s] subdev register failed: %d" , subdev_name , rc );
460+ goto fw_cleanup ;
461+ }
367462
368463 CAM_DBG (CAM_ICP , "device[%s] id: %u component bound successfully" ,
369464 subdev_name , device_idx );
370465
371466 return rc ;
372467
468+ fw_cleanup :
469+ cam_put_domain_for_fw (& cam_fw );
373470ctx_fail :
374471 for (-- i ; i >= 0 ; i -- )
375472 cam_icp_context_deinit (& icp_dev -> ctx_icp [i ]);
0 commit comments