1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Support for Intel Camera Imaging ISP subsystem. 4 * Copyright (c) 2010-2015, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 */ 15 16 #include "assert_support.h" 17 #include "irq.h" 18 19 #ifndef __INLINE_GP_DEVICE__ 20 #define __INLINE_GP_DEVICE__ 21 #endif 22 #include "gp_device.h" /* _REG_GP_IRQ_REQUEST_ADDR */ 23 24 static inline void irq_wait_for_write_complete( 25 const irq_ID_t ID); 26 27 static inline bool any_irq_channel_enabled( 28 const irq_ID_t ID); 29 30 static inline irq_ID_t virq_get_irq_id(const enum virq_id irq_ID, 31 unsigned int *channel_ID); 32 33 #ifndef __INLINE_IRQ__ 34 #include "irq_private.h" 35 #endif /* __INLINE_IRQ__ */ 36 37 static unsigned short IRQ_N_CHANNEL[N_IRQ_ID] = { 38 IRQ0_ID_N_CHANNEL, 39 IRQ1_ID_N_CHANNEL, 40 IRQ2_ID_N_CHANNEL, 41 IRQ3_ID_N_CHANNEL 42 }; 43 44 static unsigned short IRQ_N_ID_OFFSET[N_IRQ_ID + 1] = { 45 IRQ0_ID_OFFSET, 46 IRQ1_ID_OFFSET, 47 IRQ2_ID_OFFSET, 48 IRQ3_ID_OFFSET, 49 IRQ_END_OFFSET 50 }; 51 52 static enum virq_id IRQ_NESTING_ID[N_IRQ_ID] = { 53 N_virq_id, 54 virq_ifmt, 55 virq_isys, 56 virq_isel 57 }; 58 59 void irq_clear_all( 60 const irq_ID_t ID) 61 { 62 hrt_data mask = 0xFFFFFFFF; 63 64 assert(ID < N_IRQ_ID); 65 assert(IRQ_N_CHANNEL[ID] <= HRT_DATA_WIDTH); 66 67 if (IRQ_N_CHANNEL[ID] < HRT_DATA_WIDTH) { 68 mask = ~((~(hrt_data)0) >> IRQ_N_CHANNEL[ID]); 69 } 70 71 irq_reg_store(ID, 72 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, mask); 73 return; 74 } 75 76 /* 77 * Do we want the user to be able to set the signalling method ? 78 */ 79 void irq_enable_channel( 80 const irq_ID_t ID, 81 const unsigned int irq_id) 82 { 83 unsigned int mask = irq_reg_load(ID, 84 _HRT_IRQ_CONTROLLER_MASK_REG_IDX); 85 unsigned int enable = irq_reg_load(ID, 86 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX); 87 unsigned int edge_in = irq_reg_load(ID, 88 _HRT_IRQ_CONTROLLER_EDGE_REG_IDX); 89 unsigned int me = 1U << irq_id; 90 91 assert(ID < N_IRQ_ID); 92 assert(irq_id < IRQ_N_CHANNEL[ID]); 93 94 mask |= me; 95 enable |= me; 96 edge_in |= me; /* rising edge */ 97 98 /* to avoid mishaps configuration must follow the following order */ 99 100 /* mask this interrupt */ 101 irq_reg_store(ID, 102 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask & ~me); 103 /* rising edge at input */ 104 irq_reg_store(ID, 105 _HRT_IRQ_CONTROLLER_EDGE_REG_IDX, edge_in); 106 /* enable interrupt to output */ 107 irq_reg_store(ID, 108 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX, enable); 109 /* clear current irq only */ 110 irq_reg_store(ID, 111 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, me); 112 /* unmask interrupt from input */ 113 irq_reg_store(ID, 114 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask); 115 116 irq_wait_for_write_complete(ID); 117 118 return; 119 } 120 121 void irq_enable_pulse( 122 const irq_ID_t ID, 123 bool pulse) 124 { 125 unsigned int edge_out = 0x0; 126 127 if (pulse) { 128 edge_out = 0xffffffff; 129 } 130 /* output is given as edge, not pulse */ 131 irq_reg_store(ID, 132 _HRT_IRQ_CONTROLLER_EDGE_NOT_PULSE_REG_IDX, edge_out); 133 return; 134 } 135 136 void irq_disable_channel( 137 const irq_ID_t ID, 138 const unsigned int irq_id) 139 { 140 unsigned int mask = irq_reg_load(ID, 141 _HRT_IRQ_CONTROLLER_MASK_REG_IDX); 142 unsigned int enable = irq_reg_load(ID, 143 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX); 144 unsigned int me = 1U << irq_id; 145 146 assert(ID < N_IRQ_ID); 147 assert(irq_id < IRQ_N_CHANNEL[ID]); 148 149 mask &= ~me; 150 enable &= ~me; 151 152 /* enable interrupt to output */ 153 irq_reg_store(ID, 154 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX, enable); 155 /* unmask interrupt from input */ 156 irq_reg_store(ID, 157 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask); 158 /* clear current irq only */ 159 irq_reg_store(ID, 160 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, me); 161 162 irq_wait_for_write_complete(ID); 163 164 return; 165 } 166 167 enum hrt_isp_css_irq_status irq_get_channel_id( 168 const irq_ID_t ID, 169 unsigned int *irq_id) 170 { 171 unsigned int irq_status = irq_reg_load(ID, 172 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX); 173 unsigned int idx; 174 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_success; 175 176 assert(ID < N_IRQ_ID); 177 assert(irq_id); 178 179 /* find the first irq bit */ 180 for (idx = 0; idx < IRQ_N_CHANNEL[ID]; idx++) { 181 if (irq_status & (1U << idx)) 182 break; 183 } 184 if (idx == IRQ_N_CHANNEL[ID]) 185 return hrt_isp_css_irq_status_error; 186 187 /* now check whether there are more bits set */ 188 if (irq_status != (1U << idx)) 189 status = hrt_isp_css_irq_status_more_irqs; 190 191 irq_reg_store(ID, 192 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, 1U << idx); 193 194 irq_wait_for_write_complete(ID); 195 196 if (irq_id) 197 *irq_id = (unsigned int)idx; 198 199 return status; 200 } 201 202 static const hrt_address IRQ_REQUEST_ADDR[N_IRQ_SW_CHANNEL_ID] = { 203 _REG_GP_IRQ_REQUEST0_ADDR, 204 _REG_GP_IRQ_REQUEST1_ADDR 205 }; 206 207 void irq_raise( 208 const irq_ID_t ID, 209 const irq_sw_channel_id_t irq_id) 210 { 211 hrt_address addr; 212 213 OP___assert(ID == IRQ0_ID); 214 OP___assert(IRQ_BASE[ID] != (hrt_address)-1); 215 OP___assert(irq_id < N_IRQ_SW_CHANNEL_ID); 216 217 (void)ID; 218 219 addr = IRQ_REQUEST_ADDR[irq_id]; 220 /* The SW IRQ pins are remapped to offset zero */ 221 gp_device_reg_store(GP_DEVICE0_ID, 222 (unsigned int)addr, 1); 223 gp_device_reg_store(GP_DEVICE0_ID, 224 (unsigned int)addr, 0); 225 return; 226 } 227 228 bool any_virq_signal(void) 229 { 230 unsigned int irq_status = irq_reg_load(IRQ0_ID, 231 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX); 232 233 return (irq_status != 0); 234 } 235 236 void cnd_virq_enable_channel( 237 const enum virq_id irq_ID, 238 const bool en) 239 { 240 irq_ID_t i; 241 unsigned int channel_ID; 242 irq_ID_t ID = virq_get_irq_id(irq_ID, &channel_ID); 243 244 assert(ID < N_IRQ_ID); 245 246 for (i = IRQ1_ID; i < N_IRQ_ID; i++) { 247 /* It is not allowed to enable the pin of a nested IRQ directly */ 248 assert(irq_ID != IRQ_NESTING_ID[i]); 249 } 250 251 if (en) { 252 irq_enable_channel(ID, channel_ID); 253 if (IRQ_NESTING_ID[ID] != N_virq_id) { 254 /* Single level nesting, otherwise we'd need to recurse */ 255 irq_enable_channel(IRQ0_ID, IRQ_NESTING_ID[ID]); 256 } 257 } else { 258 irq_disable_channel(ID, channel_ID); 259 if ((IRQ_NESTING_ID[ID] != N_virq_id) && !any_irq_channel_enabled(ID)) { 260 /* Only disable the top if the nested ones are empty */ 261 irq_disable_channel(IRQ0_ID, IRQ_NESTING_ID[ID]); 262 } 263 } 264 return; 265 } 266 267 void virq_clear_all(void) 268 { 269 irq_ID_t irq_id; 270 271 for (irq_id = (irq_ID_t)0; irq_id < N_IRQ_ID; irq_id++) { 272 irq_clear_all(irq_id); 273 } 274 return; 275 } 276 277 enum hrt_isp_css_irq_status 278 virq_get_channel_signals(struct virq_info *irq_info) 279 { 280 enum hrt_isp_css_irq_status irq_status = hrt_isp_css_irq_status_error; 281 irq_ID_t ID; 282 283 assert(irq_info); 284 285 for (ID = (irq_ID_t)0 ; ID < N_IRQ_ID; ID++) { 286 if (any_irq_channel_enabled(ID)) { 287 hrt_data irq_data = irq_reg_load(ID, 288 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX); 289 290 if (irq_data != 0) { 291 /* The error condition is an IRQ pulse received with no IRQ status written */ 292 irq_status = hrt_isp_css_irq_status_success; 293 } 294 295 irq_info->irq_status_reg[ID] |= irq_data; 296 297 irq_reg_store(ID, 298 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, irq_data); 299 300 irq_wait_for_write_complete(ID); 301 } 302 } 303 304 return irq_status; 305 } 306 307 void virq_clear_info(struct virq_info *irq_info) 308 { 309 irq_ID_t ID; 310 311 assert(irq_info); 312 313 for (ID = (irq_ID_t)0 ; ID < N_IRQ_ID; ID++) { 314 irq_info->irq_status_reg[ID] = 0; 315 } 316 return; 317 } 318 319 enum hrt_isp_css_irq_status virq_get_channel_id( 320 enum virq_id *irq_id) 321 { 322 unsigned int irq_status = irq_reg_load(IRQ0_ID, 323 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX); 324 unsigned int idx; 325 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_success; 326 irq_ID_t ID; 327 328 assert(irq_id); 329 330 /* find the first irq bit on device 0 */ 331 for (idx = 0; idx < IRQ_N_CHANNEL[IRQ0_ID]; idx++) { 332 if (irq_status & (1U << idx)) 333 break; 334 } 335 336 if (idx == IRQ_N_CHANNEL[IRQ0_ID]) { 337 return hrt_isp_css_irq_status_error; 338 } 339 340 /* Check whether there are more bits set on device 0 */ 341 if (irq_status != (1U << idx)) { 342 status = hrt_isp_css_irq_status_more_irqs; 343 } 344 345 /* Check whether we have an IRQ on one of the nested devices */ 346 for (ID = N_IRQ_ID - 1 ; ID > (irq_ID_t)0; ID--) { 347 if (IRQ_NESTING_ID[ID] == (enum virq_id)idx) { 348 break; 349 } 350 } 351 352 /* If we have a nested IRQ, load that state, discard the device 0 state */ 353 if (ID != IRQ0_ID) { 354 irq_status = irq_reg_load(ID, 355 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX); 356 /* find the first irq bit on device "id" */ 357 for (idx = 0; idx < IRQ_N_CHANNEL[ID]; idx++) { 358 if (irq_status & (1U << idx)) 359 break; 360 } 361 362 if (idx == IRQ_N_CHANNEL[ID]) { 363 return hrt_isp_css_irq_status_error; 364 } 365 366 /* Alternatively check whether there are more bits set on this device */ 367 if (irq_status != (1U << idx)) { 368 status = hrt_isp_css_irq_status_more_irqs; 369 } else { 370 /* If this device is empty, clear the state on device 0 */ 371 irq_reg_store(IRQ0_ID, 372 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, 1U << IRQ_NESTING_ID[ID]); 373 } 374 } /* if (ID != IRQ0_ID) */ 375 376 /* Here we proceed to clear the IRQ on detected device, if no nested IRQ, this is device 0 */ 377 irq_reg_store(ID, 378 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, 1U << idx); 379 380 irq_wait_for_write_complete(ID); 381 382 idx += IRQ_N_ID_OFFSET[ID]; 383 if (irq_id) 384 *irq_id = (enum virq_id)idx; 385 386 return status; 387 } 388 389 static inline void irq_wait_for_write_complete( 390 const irq_ID_t ID) 391 { 392 assert(ID < N_IRQ_ID); 393 assert(IRQ_BASE[ID] != (hrt_address)-1); 394 (void)ia_css_device_load_uint32(IRQ_BASE[ID] + 395 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX * sizeof(hrt_data)); 396 } 397 398 static inline bool any_irq_channel_enabled( 399 const irq_ID_t ID) 400 { 401 hrt_data en_reg; 402 403 assert(ID < N_IRQ_ID); 404 405 en_reg = irq_reg_load(ID, 406 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX); 407 408 return (en_reg != 0); 409 } 410 411 static inline irq_ID_t virq_get_irq_id( 412 const enum virq_id irq_ID, 413 unsigned int *channel_ID) 414 { 415 irq_ID_t ID; 416 417 assert(channel_ID); 418 419 for (ID = (irq_ID_t)0 ; ID < N_IRQ_ID; ID++) { 420 if (irq_ID < IRQ_N_ID_OFFSET[ID + 1]) { 421 break; 422 } 423 } 424 425 *channel_ID = (unsigned int)irq_ID - IRQ_N_ID_OFFSET[ID]; 426 427 return ID; 428 } 429