2 * Support for Intel Camera Imaging ISP subsystem.
3 * Copyright (c) 2010 - 2015, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 #include "ia_css_types.h"
19 #include "memory_access.h"
20 #include "assert_support.h"
21 #include "ia_css_spctrl.h"
22 #include "ia_css_debug.h"
24 struct spctrl_context_info {
25 struct ia_css_sp_init_dmem_cfg dmem_config;
26 u32 spctrl_config_dmem_addr; /* location of dmem_cfg in SP dmem */
27 u32 spctrl_state_dmem_addr;
28 unsigned int sp_entry; /* entry function ptr on SP */
29 hrt_vaddress code_addr; /* sp firmware location in host mem-DDR*/
31 char *program_name; /* used in case of PLATFORM_SIM */
34 static struct spctrl_context_info spctrl_cofig_info[N_SP_ID];
35 static bool spctrl_loaded[N_SP_ID] = {0};
38 enum ia_css_err ia_css_spctrl_load_fw(sp_ID_t sp_id,
39 ia_css_spctrl_cfg *spctrl_cfg)
41 hrt_vaddress code_addr = mmgr_NULL;
42 struct ia_css_sp_init_dmem_cfg *init_dmem_cfg;
44 if ((sp_id >= N_SP_ID) || (!spctrl_cfg))
45 return IA_CSS_ERR_INVALID_ARGUMENTS;
47 spctrl_cofig_info[sp_id].code_addr = mmgr_NULL;
49 init_dmem_cfg = &spctrl_cofig_info[sp_id].dmem_config;
50 init_dmem_cfg->dmem_data_addr = spctrl_cfg->dmem_data_addr;
51 init_dmem_cfg->dmem_bss_addr = spctrl_cfg->dmem_bss_addr;
52 init_dmem_cfg->data_size = spctrl_cfg->data_size;
53 init_dmem_cfg->bss_size = spctrl_cfg->bss_size;
54 init_dmem_cfg->sp_id = sp_id;
56 spctrl_cofig_info[sp_id].spctrl_config_dmem_addr =
57 spctrl_cfg->spctrl_config_dmem_addr;
58 spctrl_cofig_info[sp_id].spctrl_state_dmem_addr =
59 spctrl_cfg->spctrl_state_dmem_addr;
61 /* store code (text + icache) and data to DDR
63 * Data used to be stored separately, because of access alignment constraints,
64 * fix the FW generation instead
66 code_addr = mmgr_malloc(spctrl_cfg->code_size);
67 if (code_addr == mmgr_NULL)
68 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
69 mmgr_store(code_addr, spctrl_cfg->code, spctrl_cfg->code_size);
71 if (sizeof(hrt_vaddress) > sizeof(hrt_data)) {
72 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
73 "size of hrt_vaddress can not be greater than hrt_data\n");
75 code_addr = mmgr_NULL;
76 return IA_CSS_ERR_INTERNAL_ERROR;
79 init_dmem_cfg->ddr_data_addr = code_addr + spctrl_cfg->ddr_data_offset;
80 if ((init_dmem_cfg->ddr_data_addr % HIVE_ISP_DDR_WORD_BYTES) != 0) {
81 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
82 "DDR address pointer is not properly aligned for DMA transfer\n");
84 code_addr = mmgr_NULL;
85 return IA_CSS_ERR_INTERNAL_ERROR;
88 spctrl_cofig_info[sp_id].sp_entry = spctrl_cfg->sp_entry;
89 spctrl_cofig_info[sp_id].code_addr = code_addr;
90 spctrl_cofig_info[sp_id].program_name = spctrl_cfg->program_name;
92 /* now we program the base address into the icache and
93 * invalidate the cache.
95 sp_ctrl_store(sp_id, SP_ICACHE_ADDR_REG,
96 (hrt_data)spctrl_cofig_info[sp_id].code_addr);
97 sp_ctrl_setbit(sp_id, SP_ICACHE_INV_REG, SP_ICACHE_INV_BIT);
98 spctrl_loaded[sp_id] = true;
99 return IA_CSS_SUCCESS;
103 /* reload pre-loaded FW */
104 void sh_css_spctrl_reload_fw(sp_ID_t sp_id)
106 /* now we program the base address into the icache and
107 * invalidate the cache.
109 sp_ctrl_store(sp_id, SP_ICACHE_ADDR_REG,
110 (hrt_data)spctrl_cofig_info[sp_id].code_addr);
111 sp_ctrl_setbit(sp_id, SP_ICACHE_INV_REG, SP_ICACHE_INV_BIT);
112 spctrl_loaded[sp_id] = true;
115 hrt_vaddress get_sp_code_addr(sp_ID_t sp_id)
117 return spctrl_cofig_info[sp_id].code_addr;
120 enum ia_css_err ia_css_spctrl_unload_fw(sp_ID_t sp_id)
122 if ((sp_id >= N_SP_ID) || ((sp_id < N_SP_ID) && (!spctrl_loaded[sp_id])))
123 return IA_CSS_ERR_INVALID_ARGUMENTS;
125 /* freeup the resource */
126 if (spctrl_cofig_info[sp_id].code_addr)
127 hmm_free(spctrl_cofig_info[sp_id].code_addr);
128 spctrl_loaded[sp_id] = false;
129 return IA_CSS_SUCCESS;
132 /* Initialize dmem_cfg in SP dmem and start SP program*/
133 enum ia_css_err ia_css_spctrl_start(sp_ID_t sp_id)
135 if ((sp_id >= N_SP_ID) || ((sp_id < N_SP_ID) && (!spctrl_loaded[sp_id])))
136 return IA_CSS_ERR_INVALID_ARGUMENTS;
138 /* Set descr in the SP to initialize the SP DMEM */
140 * The FW stores user-space pointers to the FW, the ISP pointer
141 * is only available here
144 assert(sizeof(unsigned int) <= sizeof(hrt_data));
147 spctrl_cofig_info[sp_id].spctrl_config_dmem_addr,
148 &spctrl_cofig_info[sp_id].dmem_config,
149 sizeof(spctrl_cofig_info[sp_id].dmem_config));
150 /* set the start address */
151 sp_ctrl_store(sp_id, SP_START_ADDR_REG,
152 (hrt_data)spctrl_cofig_info[sp_id].sp_entry);
153 sp_ctrl_setbit(sp_id, SP_SC_REG, SP_RUN_BIT);
154 sp_ctrl_setbit(sp_id, SP_SC_REG, SP_START_BIT);
155 return IA_CSS_SUCCESS;
158 /* Query the state of SP1 */
159 ia_css_spctrl_sp_sw_state ia_css_spctrl_get_state(sp_ID_t sp_id)
161 ia_css_spctrl_sp_sw_state state = 0;
162 unsigned int HIVE_ADDR_sp_sw_state;
164 if (sp_id >= N_SP_ID)
165 return IA_CSS_SP_SW_TERMINATED;
167 HIVE_ADDR_sp_sw_state = spctrl_cofig_info[sp_id].spctrl_state_dmem_addr;
168 (void)HIVE_ADDR_sp_sw_state; /* Suppres warnings in CRUN */
170 state = sp_dmem_load_uint32(sp_id, (unsigned int)sp_address_of(sp_sw_state));
174 int ia_css_spctrl_is_idle(sp_ID_t sp_id)
178 assert(sp_id < N_SP_ID);
180 state = sp_ctrl_getbit(sp_id, SP_SC_REG, SP_IDLE_BIT);