driver/kmd/armchina-aipu/aipu_mm.c
/**
 * @aipu_init_mm() - initialize mm module during driver probe phase
 * @mm:      pointer to memory manager struct to be initialized
 * @p_dev:   pointer to the platform device struct
 * @version: AIPU ISA version
 *
 * Return: 0 on success and error code otherwise.
 */
@aipu_init_mm() - initialize mm module during driver probe phase
@mm:      pointer to memory manager struct to be initialized
@p_dev:   pointer to the platform device struct
@version: AIPU ISA version

0 on success and error code otherwise.
@aipu_init_mm () - initialize mm module during driver probe phase @mm : pointer to memory manager struct to be initialized @p_dev : pointer to the platform device struct @version : AIPU ISA version 0 on success and error code otherwise .
int aipu_init_mm(struct aipu_memory_manager *mm, struct platform_device *p_dev, int version)
{
	int ret = 0;
	int reg_id = 0;
	struct iommu_group *group = NULL;
	struct device_node *np = NULL;
	struct resource res;
	bool bypass_iommu = false;
	if (!mm || !p_dev)
		return -EINVAL;
	memset(mm, 0, sizeof(*mm));
	mm->version = version;
	mm->limit = 0xC0000000;
	mm->dev = &p_dev->dev;
	mutex_init(&mm->lock);
	mm->sram_dft_dtype = AIPU_MM_DATA_TYPE_NONE;
	mm->sram_disable = false;
	mm->sram_disable_head = devm_kzalloc(mm->dev, sizeof(*mm->sram_disable_head), GFP_KERNEL);
	if (!mm->sram_disable_head)
		return -ENOMEM;
	INIT_LIST_HEAD(&mm->sram_disable_head->list);
	if (of_property_read_u64(mm->dev->of_node, "host-aipu-offset", &mm->host_aipu_offset))
		mm->host_aipu_offset = 0;
	group = iommu_group_get(mm->dev);
	if (group)
		mm->has_iommu = true;
	iommu_group_put(group);
	dev_info(mm->dev, "AIPU is%s behind an IOMMU\n", mm->has_iommu ? "" : " not");
	for (reg_id = 0; reg_id < AIPU_MEM_REGION_MAX_ID; reg_id++) {
		np = of_parse_phandle(mm->dev->of_node, "memory-region", reg_id);
		if (!np)
			continue;
		if (of_device_is_compatible(np, "shared-dma-pool")) {
			if (IS_ENABLED(CONFIG_CMA) && of_property_read_bool(np, "reusable")) {
				mm->reg[reg_id].type = AIPU_MEM_TYPE_CMA_RESERVED;
				dev_info(mm->dev, "AIPU %s mem type is [CMA reserved]\n",
					 reg_id ? "SRAM" : "DRAM");
			} else if (of_property_read_bool(np, "no-map")) {
				mm->reg[reg_id].type = AIPU_MEM_TYPE_DMA_RESERVED;
				dev_info(mm->dev, "AIPU %s mem type is [DMA reserved]\n",
					 reg_id ? "SRAM" : "DRAM");
			}
		} else {
			mm->reg[reg_id].type = AIPU_MEM_TYPE_DEV_RESERVED;
			dev_info(mm->dev, "AIPU %s mem type is [Reserved]\n",
				 reg_id ? "SRAM" : "DRAM");
		}
		if (of_address_to_resource(np, 0, &res)) {
			of_node_put(np);
			return -EINVAL;
		}
		mm->reg[reg_id].base_pa = res.start;
		mm->reg[reg_id].bytes = res.end - res.start + 1;
		of_node_put(np);
	}
	if (!mm->reg[AIPU_MEM_REGION_DRAM_ID].bytes) {
		if (mm->has_iommu) {
			mm->reg[AIPU_MEM_REGION_DRAM_ID].type = AIPU_MEM_TYPE_KERNEL;
			dev_info(mm->dev, "AIPU DRAM mem type is [Kernel]\n");
		} else {
			mm->reg[AIPU_MEM_REGION_DRAM_ID].type = AIPU_MEM_TYPE_CMA_DEFAULT;
			dev_info(mm->dev, "AIPU DRAM mem type is [CMA default]\n");
		}
	}
	if (mm->has_iommu &&
	    mm->reg[AIPU_MEM_REGION_DRAM_ID].type == AIPU_MEM_TYPE_CMA_RESERVED &&
	    (mm->reg[AIPU_MEM_REGION_SRAM_ID].type == AIPU_MEM_TYPE_DEV_RESERVED ||
	     mm->reg[AIPU_MEM_REGION_SRAM_ID].type == AIPU_MEM_TYPE_DMA_RESERVED)) {
		dev_err(mm->dev, "AIPU is behind an IOMMU and cannot issue SRAM PA\n");
		return -EINVAL;
	}
	bypass_iommu = mm->has_iommu &&
		(mm->reg[AIPU_MEM_REGION_DRAM_ID].type == AIPU_MEM_TYPE_DEV_RESERVED ||
		 mm->reg[AIPU_MEM_REGION_DRAM_ID].type == AIPU_MEM_TYPE_DMA_RESERVED);
	if (bypass_iommu) {
		dev_info(mm->dev, "%s reserved memory is used and IOMMU will be bypassed\n",
			 (mm->reg[AIPU_MEM_REGION_DRAM_ID].type == AIPU_MEM_TYPE_DEV_RESERVED) ?
			 "Native" : "DMA");
	}
	if ((!mm->has_iommu || bypass_iommu) && mm->reg[AIPU_MEM_REGION_SRAM_ID].bytes &&
	    ((mm->reg[AIPU_MEM_REGION_SRAM_ID].base_pa >> 32) !=
	     (mm->reg[AIPU_MEM_REGION_DRAM_ID].base_pa >> 32))) {
		mm->reg[AIPU_MEM_REGION_SRAM_ID].bytes = 0;
		mm->reg[AIPU_MEM_REGION_SRAM_ID].base_pa = 0;
		dev_err(mm->dev, "SRAM is not in the same 4GB region with DRAM and cannot be used\n");
	}
	ret = aipu_mm_init_mem_region(mm, AIPU_MEM_REGION_DRAM_ID);
	if (ret)
		return ret;
	ret = aipu_mm_init_mem_region(mm, AIPU_MEM_REGION_SRAM_ID);
	if (ret)
		goto err;
	goto finish;
err:
	aipu_mm_deinit_mem_region(mm, AIPU_MEM_REGION_DRAM_ID);
finish:
	return ret;
}
int aipu_init_mm ( struct aipu_memory_manager * mm , struct platform_device * p_dev , int version ) { int ret = 0 ; int reg_id = 0 ; struct iommu_group * group = NULL ; struct device_node * np = NULL ; struct resource res ; bool bypass_iommu = false ; if ( ! mm || ! p_dev ) return - EINVAL ; memset ( mm , 0 , sizeof ( * mm ) ) ; mm -> version = version ; mm -> limit = 0xC0000000 ; mm -> dev = & p_dev -> dev ; mutex_init ( & mm -> lock ) ; mm -> sram_dft_dtype = AIPU_MM_DATA_TYPE_NONE ; mm -> sram_disable = false ; mm -> sram_disable_head = devm_kzalloc ( mm -> dev , sizeof ( * mm -> sram_disable_head ) , GFP_KERNEL ) ; if ( ! mm -> sram_disable_head ) return - ENOMEM ; INIT_LIST_HEAD ( & mm -> sram_disable_head -> list ) ; if ( of_property_read_u64 ( mm -> dev -> of_node , " " , & mm -> host_aipu_offset ) ) mm -> host_aipu_offset = 0 ; group = iommu_group_get ( mm -> dev ) ; if ( group ) mm -> has_iommu = true ; iommu_group_put ( group ) ; dev_info ( mm -> dev , " \n " , mm -> has_iommu ? " " : " " ) ; for ( reg_id = 0 ; reg_id < AIPU_MEM_REGION_MAX_ID ; reg_id ++ ) { np = of_parse_phandle ( mm -> dev -> of_node , " " , reg_id ) ; if ( ! np ) continue ; if ( of_device_is_compatible ( np , " " ) ) { if ( IS_ENABLED ( CONFIG_CMA ) && of_property_read_bool ( np , " " ) ) { mm -> reg [ reg_id ] . type = AIPU_MEM_TYPE_CMA_RESERVED ; dev_info ( mm -> dev , " \n " , reg_id ? " " : " " ) ; } else if ( of_property_read_bool ( np , " " ) ) { mm -> reg [ reg_id ] . type = AIPU_MEM_TYPE_DMA_RESERVED ; dev_info ( mm -> dev , " \n " , reg_id ? " " : " " ) ; } } else { mm -> reg [ reg_id ] . type = AIPU_MEM_TYPE_DEV_RESERVED ; dev_info ( mm -> dev , " \n " , reg_id ? " " : " " ) ; } if ( of_address_to_resource ( np , 0 , & res ) ) { of_node_put ( np ) ; return - EINVAL ; } mm -> reg [ reg_id ] . base_pa = res . start ; mm -> reg [ reg_id ] . bytes = res . end - res . start + 1 ; of_node_put ( np ) ; } if ( ! mm -> reg [ AIPU_MEM_REGION_DRAM_ID ] . bytes ) { if ( mm -> has_iommu ) { mm -> reg [ AIPU_MEM_REGION_DRAM_ID ] . type = AIPU_MEM_TYPE_KERNEL ; dev_info ( mm -> dev , " \n " ) ; } else { mm -> reg [ AIPU_MEM_REGION_DRAM_ID ] . type = AIPU_MEM_TYPE_CMA_DEFAULT ; dev_info ( mm -> dev , " \n " ) ; } } if ( mm -> has_iommu && mm -> reg [ AIPU_MEM_REGION_DRAM_ID ] . type == AIPU_MEM_TYPE_CMA_RESERVED && ( mm -> reg [ AIPU_MEM_REGION_SRAM_ID ] . type == AIPU_MEM_TYPE_DEV_RESERVED || mm -> reg [ AIPU_MEM_REGION_SRAM_ID ] . type == AIPU_MEM_TYPE_DMA_RESERVED ) ) { dev_err ( mm -> dev , " \n " ) ; return - EINVAL ; } bypass_iommu = mm -> has_iommu && ( mm -> reg [ AIPU_MEM_REGION_DRAM_ID ] . type == AIPU_MEM_TYPE_DEV_RESERVED || mm -> reg [ AIPU_MEM_REGION_DRAM_ID ] . type == AIPU_MEM_TYPE_DMA_RESERVED ) ; if ( bypass_iommu ) { dev_info ( mm -> dev , " \n " , ( mm -> reg [ AIPU_MEM_REGION_DRAM_ID ] . type == AIPU_MEM_TYPE_DEV_RESERVED ) ? " " : " " ) ; } if ( ( ! mm -> has_iommu || bypass_iommu ) && mm -> reg [ AIPU_MEM_REGION_SRAM_ID ] . bytes && ( ( mm -> reg [ AIPU_MEM_REGION_SRAM_ID ] . base_pa >> 32 ) != ( mm -> reg [ AIPU_MEM_REGION_DRAM_ID ] . base_pa >> 32 ) ) ) { mm -> reg [ AIPU_MEM_REGION_SRAM_ID ] . bytes = 0 ; mm -> reg [ AIPU_MEM_REGION_SRAM_ID ] . base_pa = 0 ; dev_err ( mm -> dev , " \n " ) ; } ret = aipu_mm_init_mem_region ( mm , AIPU_MEM_REGION_DRAM_ID ) ; if ( ret ) return ret ; ret = aipu_mm_init_mem_region ( mm , AIPU_MEM_REGION_SRAM_ID ) ; if ( ret ) goto err ; goto finish ; err : aipu_mm_deinit_mem_region ( mm , AIPU_MEM_REGION_DRAM_ID ) ; finish : return ret ; }
@aipu_init_mm() - initialize mm module during driver probe phase
 @mm:      pointer to memory manager struct to be initialized
 @p_dev:   pointer to the platform device struct
 @version: AIPU ISA version
@aipu_init_mm () - initialize mm module during driver probe phase @mm : pointer to memory manager struct to be initialized @p_dev : pointer to the platform device struct @version : AIPU ISA version
/*
	 * If AIPU is behind an IOMMU, in devicetree, memory-region attribute of DRAM is optional;
	 * otherwise DRAM must be specified;
	 *
	 * SRAM is always optional and should be specified after DRAM if any;
	 *
	 * KMD accepts at maximum one DRAM memory-region and one SRAM region;
	 */