/* * Copyright (c) 1997-2015, Actions Semi Co., Inc. * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include "dsp_inner.h" #include "dsp_image.h" int dsp_acts_request_image(struct device *dev, const struct dsp_imageinfo *image, int type) { uint32_t entry_point = UINT32_MAX; struct dsp_acts_data *dsp_data = dev->data; dsp_powergate_enable(); if (type >= ARRAY_SIZE(dsp_data->images)) { printk("%s: dsp image <%s> invalid type %d\n", __func__, image->name, type); return -EINVAL; } #ifdef CONFIG_LOAD_IMAGE_FROM_FS if (load_dsp_image_from_file((void *)&image->filp, &entry_point)) { printk("%s: cannot load dsp image <%s>\n", __func__, image->name); return -EINVAL; } #else if (load_dsp_image(image->ptr, image->size, &entry_point)) { printk("%s: cannot load dsp image <%s>\n", __func__, image->name); return -EINVAL; } #endif #if 0 printk("%s: dsp image <%s> loaded, type=%d, entry_point=0x%x\n", __func__, image->name, type, entry_point); #endif if (type == DSP_IMAGE_MAIN) { clear_dsp_pageaddr(); /* set DSP_VECTOR_ADDRESS */ set_dsp_vector_addr(entry_point); } #if 0 SYS_LOG_INF(" DSP_VCT_ADDR=0x%x 0x%x\n", sys_read32(DSP_VCT_ADDR), entry_point); #endif memcpy(&dsp_data->images[type], image, sizeof(*image)); dsp_data->images[type].entry_point = entry_point; return 0; } int dsp_acts_release_image(struct device *dev, int type) { struct dsp_acts_data *dsp_data = dev->data; if (type >= ARRAY_SIZE(dsp_data->images)) return -EINVAL; printk("%s: dsp image <%s> free, type=%d\n", __func__, dsp_data->images[type].name, type); memset(&dsp_data->images[type], 0, sizeof(dsp_data->images[0])); dsp_powergate_disable(); return 0; } static void dsp_acts_handle_invalid_epc(struct device *dev, uint32_t epc) { const struct dsp_acts_config *dsp_cfg = dev->config; struct dsp_protocol_userinfo *dsp_userinfo = dsp_cfg->dsp_userinfo; dsp_userinfo->error_code = DSP_BAD_COMMAND; dsp_poweroff(dev); } static int dsp_acts_is_valid_epc(uint32_t epc) { uint32_t real_address = IMG_BANK_INNER_ADDR(epc); /* if bank flag is zero,epc is invalid */ if(!(epc & (IMG_BANK_FLAG_MASK))){ return false; } real_address = dsp_to_mcu_address(real_address, 1); if(real_address != -1){ return true; }else{ return false; } } int dsp_acts_handle_image_pagemiss(struct device *dev, uint32_t epc) { unsigned int bank_group = IMG_BANK_GROUP(epc); unsigned int bank_index = IMG_BANK_INDEX(epc); unsigned int bank_no = BANK_NO(bank_group, bank_index); unsigned int type = IMG_TYPE(epc); struct dsp_acts_data *dsp_data = dev->data; const struct dsp_imageinfo *image; if (type >= DSP_NUM_IMAGE_TYPES) { printk("%s: invalid epc 0x%08x\n", __func__, epc); dsp_acts_handle_invalid_epc(dev, epc); return -EFAULT; } image = &dsp_data->images[type]; /* if image->name is null, dsp lib is invalid*/ if (!image || !image->name || !dsp_acts_is_valid_epc(epc)){ printk("%s: invalid epc 0x%08x\n", __func__, epc); dsp_acts_handle_invalid_epc(dev, epc); return -EFAULT; } #if 0 printk("%s: dsp image <%s> page miss, epc=0x%08x, type=%x, bank_group=%u, bank_index=%u\n", __func__, image->name, epc, type, bank_group, bank_index); #endif #ifdef CONFIG_LOAD_IMAGE_FROM_FS if (load_dsp_image_bank_from_file((void *)&image->filp, bank_no)) { printk("cannot load bank[%u] for epc 0x%08x\n", bank_no, epc); dsp_acts_handle_invalid_epc(dev, epc); return DSP_FAIL; } #else if (load_dsp_image_bank(image->ptr, image->size, bank_no)) { printk("cannot load bank[%u] for epc 0x%08x\n", bank_no, epc); dsp_acts_handle_invalid_epc(dev, epc); return DSP_FAIL; } #endif /* epc is word unit */ unsigned int page_addr = (epc * 2) & 0xfff80000; //check tlb is bit19~bit31 if (sys_read32(DSP_PAGE_ADDR0 + (bank_group << 2)) == page_addr) return -EBUSY; else sys_write32(page_addr, DSP_PAGE_ADDR0 + (bank_group << 2)); #if 0 printk("page addr %x target page add %x bank_group %d epc %x \n",sys_read32(DSP_PAGE_ADDR0 + (bank_group << 2)),page_addr,bank_group,epc); #endif return DSP_DONE; } int dsp_acts_handle_image_pageflush(struct device *dev, uint32_t epc) { unsigned int bank_group = IMG_BANK_GROUP(epc); //unsigned int bank_index = IMG_BANK_INDEX(epc); unsigned int type = IMG_TYPE(epc); struct dsp_acts_data *dsp_data = dev->data; const struct dsp_imageinfo *image; if (type >= DSP_NUM_IMAGE_TYPES) { printk("%s: invalid epc 0x%08x\n", __func__, epc); dsp_acts_handle_invalid_epc(dev, epc); return -EFAULT; } image = &dsp_data->images[type]; /* if image->name is null, dsp lib is invalid*/ if (!image || !image->name || !dsp_acts_is_valid_epc(epc)){ printk("%s: invalid epc 0x%08x\n", __func__, epc); dsp_acts_handle_invalid_epc(dev, epc); return -EFAULT; } #if 0 printk("%s: dsp image <%s> page flush, epc=0x%08x, type=%x, bank_group=%u, bank_index=%u\n", __func__, image->name, epc, type, bank_group, bank_index); #endif sys_write32(0, DSP_PAGE_ADDR0 + (bank_group << 2)); return DSP_DONE; }