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#include <utils/util.h> 14#include <platsupport/irq_combiner.h> 15#include "../../services.h" 16 17 18#define NGROUPS 32 19 20struct combiner_gmap { 21 uint32_t enable_set; 22 uint32_t enable_clr; 23 uint32_t status; 24 uint32_t masked_status; 25}; 26 27struct irq_combiner_map { 28 struct combiner_gmap g[NGROUPS / 4]; 29 uint32_t res[32]; 30 uint32_t pending; 31}; 32 33volatile struct irq_combiner_map *_combiner_regs = NULL; 34 35#define GROUP_INDEX(cirq) (COMBINER_IRQ_GET_GROUP(cirq) >> 2) 36#define GROUP_SHIFT(cirq) ((COMBINER_IRQ_GET_GROUP(cirq) & 0x3) * 8) 37#define IRQ_SHIFT(cirq) (COMBINER_IRQ_GET_INDEX(cirq)) 38#define GROUP_INDEX_MASK 0xff 39 40static volatile struct irq_combiner_map* 41irq_combiner_get_regs(irq_combiner_t* combiner) { 42 assert(combiner); 43 assert(combiner->priv); 44 return (volatile struct irq_combiner_map*)combiner->priv; 45} 46 47static int 48exynos_irq_combiner_is_pending(irq_combiner_t* combiner, combiner_irq_t cirq) 49{ 50 volatile struct irq_combiner_map* regs; 51 int gidx, shift; 52 regs = irq_combiner_get_regs(combiner); 53 gidx = GROUP_INDEX(cirq); 54 shift = GROUP_SHIFT(cirq) + IRQ_SHIFT(cirq); 55 return !!(regs->g[gidx].masked_status & BIT(shift)); 56} 57 58static int 59exynos_irq_combiner_is_enabled(irq_combiner_t* combiner, combiner_irq_t cirq) 60{ 61 volatile struct irq_combiner_map* regs; 62 int gidx, shift; 63 regs = irq_combiner_get_regs(combiner); 64 gidx = GROUP_INDEX(cirq); 65 shift = GROUP_SHIFT(cirq) + IRQ_SHIFT(cirq); 66 return !!(regs->g[gidx].enable_set & BIT(shift)); 67} 68 69static int 70exynos_irq_combiner_set_enabled(irq_combiner_t* combiner, combiner_irq_t cirq, int v) 71{ 72 volatile struct irq_combiner_map* regs; 73 int gidx, shift; 74 regs = irq_combiner_get_regs(combiner); 75 gidx = GROUP_INDEX(cirq); 76 shift = GROUP_SHIFT(cirq) + IRQ_SHIFT(cirq); 77 if (v) { 78 regs->g[gidx].enable_set = BIT(shift); 79 } else { 80 regs->g[gidx].enable_clr = BIT(shift); 81 } 82 return 0; 83} 84 85static uint32_t 86exynos_irq_combiner_grp_pending(irq_combiner_t* combiner, int group) 87{ 88 volatile struct irq_combiner_map* regs; 89 combiner_irq_t cirq; 90 int gidx, shift; 91 uint32_t v; 92 regs = irq_combiner_get_regs(combiner); 93 cirq = COMBINER_IRQ(group, 0); 94 gidx = GROUP_INDEX(cirq); 95 shift = GROUP_SHIFT(cirq); 96 v = regs->g[gidx].masked_status; 97 return (v >> shift) & GROUP_INDEX_MASK; 98} 99 100static int 101irq_combiner_init_common(irq_combiner_t* combiner) 102{ 103 if (_combiner_regs == NULL) { 104 return -1; 105 } else { 106 /* Initialise the structure */ 107 combiner->priv = (void*)_combiner_regs; 108 combiner->is_pending = &exynos_irq_combiner_is_pending; 109 combiner->is_enabled = &exynos_irq_combiner_is_enabled; 110 combiner->set_enabled = &exynos_irq_combiner_set_enabled; 111 combiner->grp_pending = &exynos_irq_combiner_grp_pending; 112 return 0; 113 } 114} 115 116int 117exynos_irq_combiner_init(void* base, irq_combiner_t* combiner) 118{ 119 if (base) { 120 _combiner_regs = (volatile struct irq_combiner_map *)base; 121 } 122 return irq_combiner_init_common(combiner); 123} 124 125int 126irq_combiner_init(enum irq_combiner_id id, ps_io_ops_t* io_ops, irq_combiner_t* combiner) 127{ 128 /* Map memory */ 129 ZF_LOGD("Mapping device ID %d\n", id); 130 switch (id) { 131 case IRQ_COMBINER0: 132 MAP_IF_NULL(io_ops, EXYNOS_IRQ_COMBINER, _combiner_regs); 133 break; 134 default: 135 return -1; 136 } 137 138 return irq_combiner_init_common(combiner); 139} 140 141int 142irq_combiner_nirqs(enum irq_combiner_id id) 143{ 144 switch (id) { 145 case IRQ_COMBINER0: 146 return 32; 147 default: 148 return -1; 149 } 150} 151 152int irq_combiner_irq(enum irq_combiner_id id, int group) 153{ 154 switch (id) { 155 case IRQ_COMBINER0: 156 return group + 32; 157 default: 158 return -1; 159 } 160} 161