drivers/staging/media/atomisp/pci/runtime/spctrl/src/spctrl.c

Source file repositories/reference/linux-study-clean/drivers/staging/media/atomisp/pci/runtime/spctrl/src/spctrl.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/media/atomisp/pci/runtime/spctrl/src/spctrl.c
Extension
.c
Size
5279 bytes
Lines
177
Domain
Driver Families
Bucket
drivers/staging
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct spctrl_context_info {
	struct ia_css_sp_init_dmem_cfg dmem_config;
	u32        spctrl_config_dmem_addr; /* location of dmem_cfg  in SP dmem */
	u32        spctrl_state_dmem_addr;
	unsigned int    sp_entry;           /* entry function ptr on SP */
	ia_css_ptr    code_addr;          /* sp firmware location in host mem-DDR*/
	u32        code_size;
	char           *program_name;       /* used in case of PLATFORM_SIM */
};

static struct spctrl_context_info spctrl_cofig_info[N_SP_ID];
static bool spctrl_loaded[N_SP_ID] = {0};

/* Load firmware */
int ia_css_spctrl_load_fw(sp_ID_t sp_id, ia_css_spctrl_cfg *spctrl_cfg)
{
	ia_css_ptr code_addr = mmgr_NULL;
	struct ia_css_sp_init_dmem_cfg *init_dmem_cfg;

	if ((sp_id >= N_SP_ID) || (!spctrl_cfg))
		return -EINVAL;

	spctrl_cofig_info[sp_id].code_addr = mmgr_NULL;

	init_dmem_cfg = &spctrl_cofig_info[sp_id].dmem_config;
	init_dmem_cfg->dmem_data_addr = spctrl_cfg->dmem_data_addr;
	init_dmem_cfg->dmem_bss_addr  = spctrl_cfg->dmem_bss_addr;
	init_dmem_cfg->data_size      = spctrl_cfg->data_size;
	init_dmem_cfg->bss_size       = spctrl_cfg->bss_size;
	init_dmem_cfg->sp_id          = sp_id;

	spctrl_cofig_info[sp_id].spctrl_config_dmem_addr =
	    spctrl_cfg->spctrl_config_dmem_addr;
	spctrl_cofig_info[sp_id].spctrl_state_dmem_addr =
	    spctrl_cfg->spctrl_state_dmem_addr;

	/* store code (text + icache) and data to DDR
	 *
	 * Data used to be stored separately, because of access alignment constraints,
	 * fix the FW generation instead
	 */
	code_addr = hmm_alloc(spctrl_cfg->code_size);
	if (code_addr == mmgr_NULL)
		return -ENOMEM;
	hmm_store(code_addr, spctrl_cfg->code, spctrl_cfg->code_size);

	if (sizeof(ia_css_ptr) > sizeof(hrt_data)) {
		ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
				    "size of ia_css_ptr can not be greater than hrt_data\n");
		hmm_free(code_addr);
		code_addr = mmgr_NULL;
		return -EINVAL;
	}

	init_dmem_cfg->ddr_data_addr  = code_addr + spctrl_cfg->ddr_data_offset;
	if ((init_dmem_cfg->ddr_data_addr % HIVE_ISP_DDR_WORD_BYTES) != 0) {
		ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
				    "DDR address pointer is not properly aligned for DMA transfer\n");
		hmm_free(code_addr);
		code_addr = mmgr_NULL;
		return -EINVAL;
	}

	spctrl_cofig_info[sp_id].sp_entry = spctrl_cfg->sp_entry;
	spctrl_cofig_info[sp_id].code_addr = code_addr;
	spctrl_cofig_info[sp_id].program_name = spctrl_cfg->program_name;

	/* now we program the base address into the icache and
	 * invalidate the cache.
	 */
	sp_ctrl_store(sp_id, SP_ICACHE_ADDR_REG,
		      (hrt_data)spctrl_cofig_info[sp_id].code_addr);
	sp_ctrl_setbit(sp_id, SP_ICACHE_INV_REG, SP_ICACHE_INV_BIT);
	spctrl_loaded[sp_id] = true;
	return 0;
}

/* ISP2401 */
/* reload pre-loaded FW */
void sh_css_spctrl_reload_fw(sp_ID_t sp_id)
{
	/* now we program the base address into the icache and
	 * invalidate the cache.
	 */
	sp_ctrl_store(sp_id, SP_ICACHE_ADDR_REG,
		      (hrt_data)spctrl_cofig_info[sp_id].code_addr);
	sp_ctrl_setbit(sp_id, SP_ICACHE_INV_REG, SP_ICACHE_INV_BIT);
	spctrl_loaded[sp_id] = true;
}

Annotation

Implementation Notes