|
| 1 | +/* |
| 2 | + * Copyright (c) 2023 TOKITTA Hiroshi <[email protected]> |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + */ |
| 6 | + |
| 7 | +#define DT_DRV_COMPAT renesas_ra_interrupt_controller_unit |
| 8 | + |
| 9 | +#include <zephyr/device.h> |
| 10 | +#include <zephyr/irq.h> |
| 11 | +#include <soc.h> |
| 12 | +#include <zephyr/drivers/interrupt_controller/intc_ra_icu.h> |
| 13 | +#include <zephyr/sw_isr_table.h> |
| 14 | +#include <errno.h> |
| 15 | + |
| 16 | +#define IELSRn_REG(n) (DT_INST_REG_ADDR(0) + IELSRn_OFFSET + (n * 4)) |
| 17 | +#define IRQCRi_REG(i) (DT_INST_REG_ADDR(0) + IRQCRi_OFFSET + (i)) |
| 18 | + |
| 19 | +#define IRQCRi_IRQMD_POS 0 |
| 20 | +#define IRQCRi_IRQMD_MASK BIT_MASK(2) |
| 21 | +#define IELSRn_IR_POS 16 |
| 22 | +#define IELSRn_IR_MASK BIT_MASK(1) |
| 23 | + |
| 24 | +enum { |
| 25 | + IRQCRi_OFFSET = 0x0, |
| 26 | + IELSRn_OFFSET = 0x300, |
| 27 | +}; |
| 28 | + |
| 29 | +int ra_icu_query_exists_irq(uint32_t event) |
| 30 | +{ |
| 31 | + for (uint32_t i = 0; i < CONFIG_NUM_IRQS; i++) { |
| 32 | + uint32_t els = sys_read32(IELSRn_REG(i)) & UINT8_MAX; |
| 33 | + |
| 34 | + if (event == els) { |
| 35 | + return i; |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + return -EINVAL; |
| 40 | +} |
| 41 | + |
| 42 | +int ra_icu_query_available_irq(uint32_t event) |
| 43 | +{ |
| 44 | + int irq = -EINVAL; |
| 45 | + |
| 46 | + if (ra_icu_query_exists_irq(event) > 0) { |
| 47 | + return -EINVAL; |
| 48 | + } |
| 49 | + |
| 50 | + for (uint32_t i = 0; i < CONFIG_NUM_IRQS; i++) { |
| 51 | + if (_sw_isr_table[i].isr == z_irq_spurious) { |
| 52 | + irq = i; |
| 53 | + break; |
| 54 | + } |
| 55 | + } |
| 56 | + |
| 57 | + return irq; |
| 58 | +} |
| 59 | + |
| 60 | +void ra_icu_clear_int_flag(unsigned int irqn) |
| 61 | +{ |
| 62 | + uint32_t cfg = sys_read32(IELSRn_REG(irqn)); |
| 63 | + |
| 64 | + sys_write32(cfg & ~BIT(IELSRn_IR_POS), IELSRn_REG(irqn)); |
| 65 | +} |
| 66 | + |
| 67 | +void ra_icu_query_irq_config(unsigned int irq, uint32_t *intcfg, ra_isr_handler *cb, |
| 68 | + const void **cbarg) |
| 69 | +{ |
| 70 | + *intcfg = sys_read32(IELSRn_REG(irq)); |
| 71 | + *cb = _sw_isr_table[irq].isr; |
| 72 | + *cbarg = (void *)_sw_isr_table[irq].arg; |
| 73 | +} |
| 74 | + |
| 75 | +static void ra_icu_irq_configure(unsigned int irqn, uint32_t intcfg) |
| 76 | +{ |
| 77 | + uint8_t reg = sys_read8(IRQCRi_REG(irqn)) & ~(IRQCRi_IRQMD_MASK); |
| 78 | + |
| 79 | + sys_write8(reg | (intcfg & IRQCRi_IRQMD_MASK), IRQCRi_REG(irqn)); |
| 80 | +} |
| 81 | + |
| 82 | +int ra_icu_irq_connect_dynamic(unsigned int irq, unsigned int priority, |
| 83 | + void (*routine)(const void *parameter), const void *parameter, |
| 84 | + uint32_t flags) |
| 85 | +{ |
| 86 | + uint32_t event = ((flags & RA_ICU_FLAG_EVENT_MASK) >> RA_ICU_FLAG_EVENT_OFFSET); |
| 87 | + uint32_t intcfg = ((flags & RA_ICU_FLAG_INTCFG_MASK) >> RA_ICU_FLAG_INTCFG_OFFSET); |
| 88 | + int irqn = irq; |
| 89 | + |
| 90 | + if (irq == RA_ICU_IRQ_UNSPECIFIED) { |
| 91 | + irqn = ra_icu_query_available_irq(event); |
| 92 | + if (irqn < 0) { |
| 93 | + return irqn; |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | + irq_disable(irqn); |
| 98 | + sys_write32(event, IELSRn_REG(irqn)); |
| 99 | + z_isr_install(irqn, routine, parameter); |
| 100 | + z_arm_irq_priority_set(irqn, priority, flags); |
| 101 | + ra_icu_irq_configure(event, intcfg); |
| 102 | + irq_enable(irqn); |
| 103 | + |
| 104 | + return irqn; |
| 105 | +} |
| 106 | + |
| 107 | +DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, |
| 108 | + NULL); |
0 commit comments