blob: 6fdc86c9e339ec4da35c86b3e75f3018f54219f1 [file] [log] [blame]
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +05301/*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
Kumar Galaf74ddd32020-03-27 05:46:12 -05007#define DT_DRV_COMPAT snps_designware_intc
8
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +05309/* This implementation supports only the regular irqs
10 * No support for priority filtering
11 * No support for vectored interrupts
12 * Firqs are also not supported
13 * This implementation works only when sw_isr_table is enabled in zephyr
14 */
15
16#include <device.h>
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053017#include <irq_nextlevel.h>
Tomasz Bursztykac30600d2019-12-18 09:31:56 +010018#include "intc_dw.h"
Anas Nashif238b6642018-11-01 16:24:48 -040019#include <soc.h>
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053020
Kumar Galaa1b77fd2020-05-27 11:26:57 -050021static ALWAYS_INLINE void dw_ictl_dispatch_child_isrs(uint32_t intr_status,
22 uint32_t isr_base_offset)
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053023{
Kumar Galaa1b77fd2020-05-27 11:26:57 -050024 uint32_t intr_bitpos, intr_offset;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053025
26 /* Dispatch lower level ISRs depending upon the bit set */
27 while (intr_status) {
28 intr_bitpos = find_lsb_set(intr_status) - 1;
29 intr_status &= ~(1 << intr_bitpos);
30 intr_offset = isr_base_offset + intr_bitpos;
31 _sw_isr_table[intr_offset].isr(
32 _sw_isr_table[intr_offset].arg);
33 }
34}
35
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +020036static int dw_ictl_initialize(const struct device *dev)
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053037{
Tomasz Bursztykaaf6140c2020-05-28 20:44:16 +020038 const struct dw_ictl_config *config = dev->config;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053039 volatile struct dw_ictl_registers * const regs =
Tomasz Bursztyka25114152019-12-17 15:48:00 +010040 (struct dw_ictl_registers *)config->base_addr;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053041
42 /* disable all interrupts */
Patrik Flykt8ff96b52018-11-29 11:12:22 -080043 regs->irq_inten_l = 0U;
44 regs->irq_inten_h = 0U;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053045
46 return 0;
47}
48
Tomasz Bursztyka4dcfb552020-06-17 14:58:56 +020049static void dw_ictl_isr(const struct device *dev)
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053050{
Tomasz Bursztykaaf6140c2020-05-28 20:44:16 +020051 const struct dw_ictl_config *config = dev->config;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053052 volatile struct dw_ictl_registers * const regs =
Tomasz Bursztyka25114152019-12-17 15:48:00 +010053 (struct dw_ictl_registers *)config->base_addr;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053054
Daniel Leung40138c92021-09-21 13:37:34 -070055 dw_ictl_dispatch_child_isrs(regs->irq_finalstatus_l,
Tomasz Bursztyka4b946682019-12-17 15:30:09 +010056 config->isr_table_offset);
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053057
58 if (config->numirqs > 32) {
Daniel Leung40138c92021-09-21 13:37:34 -070059 dw_ictl_dispatch_child_isrs(regs->irq_finalstatus_h,
Tomasz Bursztyka4b946682019-12-17 15:30:09 +010060 config->isr_table_offset + 32);
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053061 }
62}
63
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +020064static inline void dw_ictl_intr_enable(const struct device *dev,
65 unsigned int irq)
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053066{
Tomasz Bursztykaaf6140c2020-05-28 20:44:16 +020067 const struct dw_ictl_config *config = dev->config;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053068 volatile struct dw_ictl_registers * const regs =
Tomasz Bursztyka25114152019-12-17 15:48:00 +010069 (struct dw_ictl_registers *)config->base_addr;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053070
71 if (irq < 32) {
72 regs->irq_inten_l |= (1 << irq);
73 } else {
74 regs->irq_inten_h |= (1 << (irq - 32));
75 }
76}
77
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +020078static inline void dw_ictl_intr_disable(const struct device *dev,
79 unsigned int irq)
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053080{
Tomasz Bursztykaaf6140c2020-05-28 20:44:16 +020081 const struct dw_ictl_config *config = dev->config;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053082 volatile struct dw_ictl_registers * const regs =
Tomasz Bursztyka25114152019-12-17 15:48:00 +010083 (struct dw_ictl_registers *)config->base_addr;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053084
85 if (irq < 32) {
86 regs->irq_inten_l &= ~(1 << irq);
87 } else {
88 regs->irq_inten_h &= ~(1 << (irq - 32));
89 }
90}
91
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +020092static inline unsigned int dw_ictl_intr_get_state(const struct device *dev)
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053093{
Tomasz Bursztykaaf6140c2020-05-28 20:44:16 +020094 const struct dw_ictl_config *config = dev->config;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053095 volatile struct dw_ictl_registers * const regs =
Tomasz Bursztyka25114152019-12-17 15:48:00 +010096 (struct dw_ictl_registers *)config->base_addr;
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +053097
98 if (regs->irq_inten_l) {
99 return 1;
100 }
101
102 if (config->numirqs > 32) {
103 if (regs->irq_inten_h) {
104 return 1;
105 }
106 }
107 return 0;
108}
109
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200110static int dw_ictl_intr_get_line_state(const struct device *dev,
111 unsigned int irq)
Daniel Leung635aadc2019-08-27 11:07:19 -0700112{
Tomasz Bursztykaaf6140c2020-05-28 20:44:16 +0200113 const struct dw_ictl_config *config = dev->config;
Daniel Leung635aadc2019-08-27 11:07:19 -0700114 volatile struct dw_ictl_registers * const regs =
Tomasz Bursztyka25114152019-12-17 15:48:00 +0100115 (struct dw_ictl_registers *)config->base_addr;
Daniel Leung635aadc2019-08-27 11:07:19 -0700116
117 if (config->numirqs > 32) {
118 if ((regs->irq_inten_h & BIT(irq - 32)) != 0) {
119 return 1;
120 }
121 } else {
122 if ((regs->irq_inten_l & BIT(irq)) != 0) {
123 return 1;
124 }
125 }
126
127 return 0;
128}
129
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200130static void dw_ictl_config_irq(const struct device *dev);
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +0530131
132static const struct dw_ictl_config dw_config = {
Kumar Galaf74ddd32020-03-27 05:46:12 -0500133 .base_addr = DT_INST_REG_ADDR(0),
134 .numirqs = DT_INST_PROP(0, num_irqs),
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +0530135 .isr_table_offset = CONFIG_DW_ISR_TBL_OFFSET,
136 .config_func = dw_ictl_config_irq,
137};
138
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +0530139static const struct irq_next_level_api dw_ictl_apis = {
140 .intr_enable = dw_ictl_intr_enable,
141 .intr_disable = dw_ictl_intr_disable,
142 .intr_get_state = dw_ictl_intr_get_state,
Daniel Leung635aadc2019-08-27 11:07:19 -0700143 .intr_get_line_state = dw_ictl_intr_get_line_state,
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +0530144};
145
Gerard Marull-Paretase6170a42021-04-28 11:06:54 +0200146DEVICE_DT_INST_DEFINE(0, dw_ictl_initialize, NULL,
Kumar Gala2d754332020-12-17 11:14:17 -0600147 NULL, &dw_config, PRE_KERNEL_1,
148 CONFIG_DW_ICTL_INIT_PRIORITY, &dw_ictl_apis);
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +0530149
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200150static void dw_ictl_config_irq(const struct device *port)
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +0530151{
Kumar Galaf74ddd32020-03-27 05:46:12 -0500152 IRQ_CONNECT(DT_INST_IRQN(0),
153 DT_INST_IRQ(0, priority),
Kumar Galae2d71c92020-02-13 14:13:51 -0600154 dw_ictl_isr,
Kumar Gala2d754332020-12-17 11:14:17 -0600155 DEVICE_DT_INST_GET(0),
Kumar Galaf74ddd32020-03-27 05:46:12 -0500156 DT_INST_IRQ(0, sense));
Rajavardhan Gundie3f2fa42017-10-12 15:44:48 +0530157}