1 /* 2 * Support for Intel Camera Imaging ISP subsystem. 3 * Copyright (c) 2010 - 2015, Intel Corporation. 4 * 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. 8 * 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 12 * more details. 13 */ 14 15 #include "hmm.h" 16 17 #include "ia_css_types.h" 18 #define __INLINE_SP__ 19 #include "sp.h" 20 21 #include "assert_support.h" 22 #include "ia_css_spctrl.h" 23 #include "ia_css_debug.h" 24 25 struct spctrl_context_info { 26 struct ia_css_sp_init_dmem_cfg dmem_config; 27 u32 spctrl_config_dmem_addr; /* location of dmem_cfg in SP dmem */ 28 u32 spctrl_state_dmem_addr; 29 unsigned int sp_entry; /* entry function ptr on SP */ 30 ia_css_ptr code_addr; /* sp firmware location in host mem-DDR*/ 31 u32 code_size; 32 char *program_name; /* used in case of PLATFORM_SIM */ 33 }; 34 35 static struct spctrl_context_info spctrl_cofig_info[N_SP_ID]; 36 static bool spctrl_loaded[N_SP_ID] = {0}; 37 38 /* Load firmware */ 39 enum ia_css_err ia_css_spctrl_load_fw(sp_ID_t sp_id, 40 ia_css_spctrl_cfg *spctrl_cfg) 41 { 42 ia_css_ptr code_addr = mmgr_NULL; 43 struct ia_css_sp_init_dmem_cfg *init_dmem_cfg; 44 45 if ((sp_id >= N_SP_ID) || (!spctrl_cfg)) 46 return IA_CSS_ERR_INVALID_ARGUMENTS; 47 48 spctrl_cofig_info[sp_id].code_addr = mmgr_NULL; 49 50 init_dmem_cfg = &spctrl_cofig_info[sp_id].dmem_config; 51 init_dmem_cfg->dmem_data_addr = spctrl_cfg->dmem_data_addr; 52 init_dmem_cfg->dmem_bss_addr = spctrl_cfg->dmem_bss_addr; 53 init_dmem_cfg->data_size = spctrl_cfg->data_size; 54 init_dmem_cfg->bss_size = spctrl_cfg->bss_size; 55 init_dmem_cfg->sp_id = sp_id; 56 57 spctrl_cofig_info[sp_id].spctrl_config_dmem_addr = 58 spctrl_cfg->spctrl_config_dmem_addr; 59 spctrl_cofig_info[sp_id].spctrl_state_dmem_addr = 60 spctrl_cfg->spctrl_state_dmem_addr; 61 62 /* store code (text + icache) and data to DDR 63 * 64 * Data used to be stored separately, because of access alignment constraints, 65 * fix the FW generation instead 66 */ 67 code_addr = hmm_alloc(spctrl_cfg->code_size, HMM_BO_PRIVATE, 0, NULL, 0); 68 if (code_addr == mmgr_NULL) 69 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; 70 hmm_store(code_addr, spctrl_cfg->code, spctrl_cfg->code_size); 71 72 if (sizeof(ia_css_ptr) > sizeof(hrt_data)) { 73 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, 74 "size of ia_css_ptr can not be greater than hrt_data\n"); 75 hmm_free(code_addr); 76 code_addr = mmgr_NULL; 77 return IA_CSS_ERR_INTERNAL_ERROR; 78 } 79 80 init_dmem_cfg->ddr_data_addr = code_addr + spctrl_cfg->ddr_data_offset; 81 if ((init_dmem_cfg->ddr_data_addr % HIVE_ISP_DDR_WORD_BYTES) != 0) { 82 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, 83 "DDR address pointer is not properly aligned for DMA transfer\n"); 84 hmm_free(code_addr); 85 code_addr = mmgr_NULL; 86 return IA_CSS_ERR_INTERNAL_ERROR; 87 } 88 89 spctrl_cofig_info[sp_id].sp_entry = spctrl_cfg->sp_entry; 90 spctrl_cofig_info[sp_id].code_addr = code_addr; 91 spctrl_cofig_info[sp_id].program_name = spctrl_cfg->program_name; 92 93 /* now we program the base address into the icache and 94 * invalidate the cache. 95 */ 96 sp_ctrl_store(sp_id, SP_ICACHE_ADDR_REG, 97 (hrt_data)spctrl_cofig_info[sp_id].code_addr); 98 sp_ctrl_setbit(sp_id, SP_ICACHE_INV_REG, SP_ICACHE_INV_BIT); 99 spctrl_loaded[sp_id] = true; 100 return IA_CSS_SUCCESS; 101 } 102 103 /* ISP2401 */ 104 /* reload pre-loaded FW */ 105 void sh_css_spctrl_reload_fw(sp_ID_t sp_id) 106 { 107 /* now we program the base address into the icache and 108 * invalidate the cache. 109 */ 110 sp_ctrl_store(sp_id, SP_ICACHE_ADDR_REG, 111 (hrt_data)spctrl_cofig_info[sp_id].code_addr); 112 sp_ctrl_setbit(sp_id, SP_ICACHE_INV_REG, SP_ICACHE_INV_BIT); 113 spctrl_loaded[sp_id] = true; 114 } 115 116 ia_css_ptr get_sp_code_addr(sp_ID_t sp_id) 117 { 118 return spctrl_cofig_info[sp_id].code_addr; 119 } 120 121 enum ia_css_err ia_css_spctrl_unload_fw(sp_ID_t sp_id) 122 { 123 if ((sp_id >= N_SP_ID) || ((sp_id < N_SP_ID) && (!spctrl_loaded[sp_id]))) 124 return IA_CSS_ERR_INVALID_ARGUMENTS; 125 126 /* freeup the resource */ 127 if (spctrl_cofig_info[sp_id].code_addr) { 128 hmm_free(spctrl_cofig_info[sp_id].code_addr); 129 spctrl_cofig_info[sp_id].code_addr = mmgr_NULL; 130 } 131 spctrl_loaded[sp_id] = false; 132 return IA_CSS_SUCCESS; 133 } 134 135 /* Initialize dmem_cfg in SP dmem and start SP program*/ 136 enum ia_css_err ia_css_spctrl_start(sp_ID_t sp_id) 137 { 138 if ((sp_id >= N_SP_ID) || ((sp_id < N_SP_ID) && (!spctrl_loaded[sp_id]))) 139 return IA_CSS_ERR_INVALID_ARGUMENTS; 140 141 /* Set descr in the SP to initialize the SP DMEM */ 142 /* 143 * The FW stores user-space pointers to the FW, the ISP pointer 144 * is only available here 145 * 146 */ 147 assert(sizeof(unsigned int) <= sizeof(hrt_data)); 148 149 sp_dmem_store(sp_id, 150 spctrl_cofig_info[sp_id].spctrl_config_dmem_addr, 151 &spctrl_cofig_info[sp_id].dmem_config, 152 sizeof(spctrl_cofig_info[sp_id].dmem_config)); 153 /* set the start address */ 154 sp_ctrl_store(sp_id, SP_START_ADDR_REG, 155 (hrt_data)spctrl_cofig_info[sp_id].sp_entry); 156 sp_ctrl_setbit(sp_id, SP_SC_REG, SP_RUN_BIT); 157 sp_ctrl_setbit(sp_id, SP_SC_REG, SP_START_BIT); 158 return IA_CSS_SUCCESS; 159 } 160 161 /* Query the state of SP1 */ 162 ia_css_spctrl_sp_sw_state ia_css_spctrl_get_state(sp_ID_t sp_id) 163 { 164 ia_css_spctrl_sp_sw_state state = 0; 165 unsigned int HIVE_ADDR_sp_sw_state; 166 167 if (sp_id >= N_SP_ID) 168 return IA_CSS_SP_SW_TERMINATED; 169 170 HIVE_ADDR_sp_sw_state = spctrl_cofig_info[sp_id].spctrl_state_dmem_addr; 171 (void)HIVE_ADDR_sp_sw_state; /* Suppres warnings in CRUN */ 172 if (sp_id == SP0_ID) 173 state = sp_dmem_load_uint32(sp_id, (unsigned int)sp_address_of(sp_sw_state)); 174 return state; 175 } 176 177 int ia_css_spctrl_is_idle(sp_ID_t sp_id) 178 { 179 int state = 0; 180 181 assert(sp_id < N_SP_ID); 182 183 state = sp_ctrl_getbit(sp_id, SP_SC_REG, SP_IDLE_BIT); 184 return state; 185 } 186