Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. |
| 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
| 6 | |
| 7 | #include <arch.h> |
| 8 | #include <arch_helpers.h> |
| 9 | #include <common/debug.h> |
| 10 | #include <common/interrupt_props.h> |
| 11 | #include <drivers/arm/gicv3.h> |
| 12 | #include "gicv3_private.h" |
| 13 | |
| 14 | /******************************************************************************* |
| 15 | * GIC Redistributor functions |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 16 | * Note: The raw register values correspond to multiple interrupt `id`s and |
| 17 | * the number of interrupt `id`s involved depends on the register accessed. |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 18 | ******************************************************************************/ |
| 19 | |
| 20 | /* |
Alexei Fedorov | c7510c5 | 2020-04-07 18:16:18 +0100 | [diff] [blame] | 21 | * Accessors to read/write the GIC Redistributor IPRIORITYR and IPRIORITYRE |
| 22 | * register corresponding to the interrupt `id`, 4 interrupts IDs at a time. |
| 23 | */ |
| 24 | unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id) |
| 25 | { |
| 26 | return GICR_READ(IPRIORITY, base, id); |
| 27 | } |
| 28 | |
| 29 | void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val) |
| 30 | { |
| 31 | GICR_WRITE(IPRIORITY, base, id, val); |
| 32 | } |
| 33 | |
| 34 | /* |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 35 | * Accessor to set the byte corresponding to interrupt `id` |
| 36 | * in GIC Redistributor IPRIORITYR and IPRIORITYRE. |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 37 | */ |
| 38 | void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) |
| 39 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 40 | GICR_WRITE_8(IPRIORITY, base, id, (uint8_t)(pri & GIC_PRI_MASK)); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | /* |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 44 | * Accessors to get/set/clear the bit corresponding to interrupt `id` |
| 45 | * from GIC Redistributor IGROUPR0 and IGROUPRE |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 46 | */ |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 47 | unsigned int gicr_get_igroupr(uintptr_t base, unsigned int id) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 48 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 49 | return GICR_GET_BIT(IGROUP, base, id); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 50 | } |
| 51 | |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 52 | void gicr_set_igroupr(uintptr_t base, unsigned int id) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 53 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 54 | GICR_SET_BIT(IGROUP, base, id); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 55 | } |
| 56 | |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 57 | void gicr_clr_igroupr(uintptr_t base, unsigned int id) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 58 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 59 | GICR_CLR_BIT(IGROUP, base, id); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | /* |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 63 | * Accessors to get/set/clear the bit corresponding to interrupt `id` |
| 64 | * from GIC Redistributor IGRPMODR0 and IGRPMODRE |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 65 | */ |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 66 | unsigned int gicr_get_igrpmodr(uintptr_t base, unsigned int id) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 67 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 68 | return GICR_GET_BIT(IGRPMOD, base, id); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 69 | } |
| 70 | |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 71 | void gicr_set_igrpmodr(uintptr_t base, unsigned int id) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 72 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 73 | GICR_SET_BIT(IGRPMOD, base, id); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 74 | } |
| 75 | |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 76 | void gicr_clr_igrpmodr(uintptr_t base, unsigned int id) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 77 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 78 | GICR_CLR_BIT(IGRPMOD, base, id); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 79 | } |
| 80 | |
| 81 | /* |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 82 | * Accessor to write the bit corresponding to interrupt `id` |
| 83 | * in GIC Redistributor ISENABLER0 and ISENABLERE |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 84 | */ |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 85 | void gicr_set_isenabler(uintptr_t base, unsigned int id) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 86 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 87 | GICR_WRITE_BIT(ISENABLE, base, id); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 88 | } |
| 89 | |
| 90 | /* |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 91 | * Accessor to write the bit corresponding to interrupt `id` |
| 92 | * in GIC Redistributor ICENABLER0 and ICENABLERE |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 93 | */ |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 94 | void gicr_set_icenabler(uintptr_t base, unsigned int id) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 95 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 96 | GICR_WRITE_BIT(ICENABLE, base, id); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 97 | } |
| 98 | |
| 99 | /* |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 100 | * Accessor to get the bit corresponding to interrupt `id` |
| 101 | * in GIC Redistributor ISACTIVER0 and ISACTIVERE |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 102 | */ |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 103 | unsigned int gicr_get_isactiver(uintptr_t base, unsigned int id) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 104 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 105 | return GICR_GET_BIT(ISACTIVE, base, id); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | /* |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 109 | * Accessor to clear the bit corresponding to interrupt `id` |
| 110 | * in GIC Redistributor ICPENDR0 and ICPENDRE |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 111 | */ |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 112 | void gicr_set_icpendr(uintptr_t base, unsigned int id) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 113 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 114 | GICR_WRITE_BIT(ICPEND, base, id); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 115 | } |
| 116 | |
| 117 | /* |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 118 | * Accessor to write the bit corresponding to interrupt `id` |
| 119 | * in GIC Redistributor ISPENDR0 and ISPENDRE |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 120 | */ |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 121 | void gicr_set_ispendr(uintptr_t base, unsigned int id) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 122 | { |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 123 | GICR_WRITE_BIT(ISPEND, base, id); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | /* |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 127 | * Accessor to set the bit fields corresponding to interrupt `id` |
| 128 | * in GIC Redistributor ICFGR0, ICFGR1 and ICFGRE |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 129 | */ |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 130 | void gicr_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg) |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 131 | { |
| 132 | /* Interrupt configuration is a 2-bit field */ |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 133 | unsigned int bit_shift = BIT_NUM(ICFG, id) << 1U; |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 134 | |
| 135 | /* Clear the field, and insert required configuration */ |
Alexei Fedorov | a6e6ae0 | 2020-04-06 16:27:54 +0100 | [diff] [blame] | 136 | mmio_clrsetbits_32(base + GICR_OFFSET(ICFG, id), |
| 137 | (uint32_t)GIC_CFG_MASK << bit_shift, |
| 138 | (cfg & GIC_CFG_MASK) << bit_shift); |
Alexei Fedorov | 2f13d6c | 2020-02-21 10:17:26 +0000 | [diff] [blame] | 139 | } |