1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#pragma once 14 15#include <platsupport/io.h> 16 17typedef struct irq_combiner irq_combiner_t; 18typedef int combiner_irq_t; 19 20struct irq_combiner { 21 int (*is_pending)(irq_combiner_t* combiner, combiner_irq_t cirq); 22 int (*is_enabled)(irq_combiner_t* combiner, combiner_irq_t cirq); 23 int (*set_enabled)(irq_combiner_t* combiner, combiner_irq_t cirq, int v); 24 uint32_t (*grp_pending)(irq_combiner_t* combiner, int group); 25 void* priv; 26}; 27 28#include <platsupport/plat/irq_combiner.h> 29 30#define COMBINER_IRQ_FLAG 0x8000 31#define IS_COMBINER_IRQ(x) !!((x) & COMBINER_IRQ_FLAG) 32#define COMBINER_IRQ(grp, idx) (((grp) << 8) | (idx) | COMBINER_IRQ_FLAG) 33#define COMBINER_IRQ_GET_GROUP(x) (((x) & ~COMBINER_IRQ_FLAG) >> 8) 34#define COMBINER_IRQ_GET_INDEX(x) (((x) & ~COMBINER_IRQ_FLAG) & 0xff) 35 36/** 37 * Initialise the IRQ combiner 38 * @param[in] id The combiner device ID 39 * @param[in] io_ops IO operations for accessing this device 40 * @param[out] combiner An IRQ combiner structure to populate 41 * @return 0 on success. 42 */ 43int irq_combiner_init(enum irq_combiner_id id, ps_io_ops_t* io_ops, irq_combiner_t* combiner); 44 45/** 46 * Find the number of IRQ groups managed by the combiner. This will typically 47 * be the number of IRQ groups. 48 * @param[in] id The combiner device ID 49 * @return The number of IRQ lines that this combiner manages. 50 * -1 if the combiner id is invalid 51 */ 52int irq_combiner_nirqs(enum irq_combiner_id id); 53 54/** 55 * Find the IRQ mapped to the requested group 56 * @param[in] id The combiner device ID 57 * @param[in] group The Combiner group number to query 58 * @return The IRQ number for the provided IRQ group 59 * -1 if the combiner id is invalid 60 */ 61int irq_combiner_irq(enum irq_combiner_id id, int group); 62 63/** 64 * Determine if a combiner IRQ is pending 65 * @param[in] combiner A handle to an IRQ combiner 66 * @param[in] cirq A combiner IRQ id as constructed from COMBINER_IRQ(grp, idx) 67 * @return 0 if the IRQ is not pending, 1 if the IRQ is pending, or 68 * -1 on error. 69 */ 70static inline int irq_combiner_is_pending(irq_combiner_t* combiner, combiner_irq_t cirq) 71{ 72 assert(combiner); 73 assert(combiner->is_pending); 74 return combiner->is_pending(combiner, cirq); 75} 76 77/** 78 * Determine if a combiner IRQ is enabled 79 * @param[in] combiner A handle to an IRQ combiner 80 * @param[in] cirq A combiner IRQ id as constructed from COMBINER_IRQ(grp, idx) 81 * @return 0 if the IRQ is not enabled, 1 if the IRQ is enabled, or 82 * -1 on error. 83 */ 84static inline int irq_combiner_is_enabled(irq_combiner_t* combiner, combiner_irq_t cirq) 85{ 86 assert(combiner); 87 assert(combiner->is_pending); 88 return combiner->is_enabled(combiner, cirq); 89} 90 91/** 92 * Enable a combiner IRQ index within a group. Does not enable the entire group 93 * at the primary interrupt controller. 94 * @param[in] combiner A handle to an IRQ combiner 95 * @param[in] cirq A combiner IRQ id as constructed from COMBINER_IRQ(grp, idx) 96 * @return 0 on success. 97 */ 98static inline int irq_combiner_enable_irq(irq_combiner_t* combiner, combiner_irq_t cirq) 99{ 100 assert(combiner); 101 assert(combiner->is_pending); 102 return combiner->set_enabled(combiner, cirq, 1); 103} 104 105/** 106 * Disable a combiner IRQ within a group. Does not disable the entire group 107 * at the primary interrupt controller. 108 * @param[in] combiner A handle to an IRQ combiner 109 * @param[in] cirq A combiner IRQ id as constructed from COMBINER_IRQ(grp, idx) 110 * @return 0 on success. 111 */ 112static inline int irq_combiner_disable_irq(irq_combiner_t* combiner, combiner_irq_t cirq) 113{ 114 assert(combiner); 115 assert(combiner->is_pending); 116 return combiner->set_enabled(combiner, cirq, 0); 117} 118 119/** 120 * Determine which IRQs in a Combiner group are pending 121 * @param[in] combiner A handle to an IRQ combiner 122 * @param[in] group The Combiner group number to query 123 * @return A bitfield of pending IRQs for this group. 124 */ 125static inline uint32_t irq_combiner_group_pending(irq_combiner_t* combiner, int group) 126{ 127 assert(combiner); 128 assert(combiner->is_pending); 129 return combiner->grp_pending(combiner, group); 130} 131 132