1 /*
2  * Copyright (c) 2020 ITE Corporation. All Rights Reserved
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/arch/cpu.h>
9 #include <zephyr/init.h>
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(intc_it8xxx2, LOG_LEVEL_DBG);
12 #include <zephyr/sys/printk.h>
13 #include <zephyr/sw_isr_table.h>
14 #include "intc_ite_it8xxx2.h"
15 
16 #define MAX_REGISR_IRQ_NUM		8
17 #define IVECT_OFFSET_WITH_IRQ		0x10
18 
19 /* Interrupt number of INTC module */
20 static uint8_t intc_irq;
21 
22 static volatile uint8_t *const reg_status[] = {
23 	&ISR0, &ISR1, &ISR2, &ISR3,
24 	&ISR4, &ISR5, &ISR6, &ISR7,
25 	&ISR8, &ISR9, &ISR10, &ISR11,
26 	&ISR12, &ISR13, &ISR14, &ISR15,
27 	&ISR16, &ISR17, &ISR18, &ISR19,
28 	&ISR20, &ISR21, &ISR22, &ISR23
29 };
30 
31 static volatile uint8_t *const reg_enable[] = {
32 	&IER0, &IER1, &IER2, &IER3,
33 	&IER4, &IER5, &IER6, &IER7,
34 	&IER8, &IER9, &IER10, &IER11,
35 	&IER12, &IER13, &IER14, &IER15,
36 	&IER16, &IER17, &IER18, &IER19,
37 	&IER20, &IER21, &IER22, &IER23
38 };
39 
40 /* edge/level trigger register */
41 static volatile uint8_t *const reg_ielmr[] = {
42 	&IELMR0, &IELMR1, &IELMR2, &IELMR3,
43 	&IELMR4, &IELMR5, &IELMR6, &IELMR7,
44 	&IELMR8, &IELMR9, &IELMR10, &IELMR11,
45 	&IELMR12, &IELMR13, &IELMR14, &IELMR15,
46 	&IELMR16, &IELMR17, &IELMR18, &IELMR19,
47 	&IELMR20, &IELMR21, &IELMR22, &IELMR23,
48 };
49 
50 /* high/low trigger register */
51 static volatile uint8_t *const reg_ipolr[] = {
52 	&IPOLR0, &IPOLR1, &IPOLR2, &IPOLR3,
53 	&IPOLR4, &IPOLR5, &IPOLR6, &IPOLR7,
54 	&IPOLR8, &IPOLR9, &IPOLR10, &IPOLR11,
55 	&IPOLR12, &IPOLR13, &IPOLR14, &IPOLR15,
56 	&IPOLR16, &IPOLR17, &IPOLR18, &IPOLR19,
57 	&IPOLR20, &IPOLR21, &IPOLR22, &IPOLR23
58 };
59 
60 #define IT8XXX2_IER_COUNT ARRAY_SIZE(reg_enable)
61 static uint8_t ier_setting[IT8XXX2_IER_COUNT];
62 
ite_intc_save_and_disable_interrupts(void)63 void ite_intc_save_and_disable_interrupts(void)
64 {
65 	volatile uint8_t _ier __unused;
66 	/* Disable global interrupt for critical section */
67 	unsigned int key = irq_lock();
68 
69 	/* Save and disable interrupts */
70 	for (int i = 0; i < IT8XXX2_IER_COUNT; i++) {
71 		ier_setting[i] = *reg_enable[i];
72 		*reg_enable[i] = 0;
73 	}
74 	/*
75 	 * This load operation will guarantee the above modification of
76 	 * SOC's register can be seen by any following instructions.
77 	 * Note: Barrier instruction can not synchronize chip register,
78 	 * so we introduce workaround here.
79 	 */
80 	_ier = *reg_enable[IT8XXX2_IER_COUNT - 1];
81 	irq_unlock(key);
82 }
83 
ite_intc_restore_interrupts(void)84 void ite_intc_restore_interrupts(void)
85 {
86 	/*
87 	 * Ensure the highest priority interrupt will be the first fired
88 	 * interrupt when soc is ready to go.
89 	 */
90 	unsigned int key = irq_lock();
91 
92 	/* Restore interrupt state */
93 	for (int i = 0; i < IT8XXX2_IER_COUNT; i++) {
94 		*reg_enable[i] = ier_setting[i];
95 	}
96 	irq_unlock(key);
97 }
98 
ite_intc_isr_clear(unsigned int irq)99 void ite_intc_isr_clear(unsigned int irq)
100 {
101 	uint32_t g, i;
102 	volatile uint8_t *isr;
103 
104 	if (irq > CONFIG_NUM_IRQS) {
105 		return;
106 	}
107 	g = irq / MAX_REGISR_IRQ_NUM;
108 	i = irq % MAX_REGISR_IRQ_NUM;
109 	isr = reg_status[g];
110 	*isr = BIT(i);
111 }
112 
ite_intc_irq_enable(unsigned int irq)113 void __soc_ram_code ite_intc_irq_enable(unsigned int irq)
114 {
115 	uint32_t g, i;
116 	volatile uint8_t *en;
117 
118 	if (irq > CONFIG_NUM_IRQS) {
119 		return;
120 	}
121 	g = irq / MAX_REGISR_IRQ_NUM;
122 	i = irq % MAX_REGISR_IRQ_NUM;
123 	en = reg_enable[g];
124 
125 	/* critical section due to run a bit-wise OR operation */
126 	unsigned int key = irq_lock();
127 	SET_MASK(*en, BIT(i));
128 	irq_unlock(key);
129 }
130 
ite_intc_irq_disable(unsigned int irq)131 void __soc_ram_code ite_intc_irq_disable(unsigned int irq)
132 {
133 	uint32_t g, i;
134 	volatile uint8_t *en;
135 	volatile uint8_t _ier __unused;
136 
137 	if (irq > CONFIG_NUM_IRQS) {
138 		return;
139 	}
140 	g = irq / MAX_REGISR_IRQ_NUM;
141 	i = irq % MAX_REGISR_IRQ_NUM;
142 	en = reg_enable[g];
143 
144 	/* critical section due to run a bit-wise OR operation */
145 	unsigned int key = irq_lock();
146 	CLEAR_MASK(*en, BIT(i));
147 	/*
148 	 * This load operation will guarantee the above modification of
149 	 * SOC's register can be seen by any following instructions.
150 	 */
151 	_ier = *en;
152 	irq_unlock(key);
153 }
154 
ite_intc_irq_polarity_set(unsigned int irq,unsigned int flags)155 void ite_intc_irq_polarity_set(unsigned int irq, unsigned int flags)
156 {
157 	uint32_t g, i;
158 	volatile uint8_t *tri;
159 
160 	if ((irq > CONFIG_NUM_IRQS) || ((flags&IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)) {
161 		return;
162 	}
163 	g = irq / MAX_REGISR_IRQ_NUM;
164 	i = irq % MAX_REGISR_IRQ_NUM;
165 	tri = reg_ipolr[g];
166 	if ((flags&IRQ_TYPE_LEVEL_HIGH) || (flags&IRQ_TYPE_EDGE_RISING)) {
167 		CLEAR_MASK(*tri, BIT(i));
168 	} else {
169 		SET_MASK(*tri, BIT(i));
170 	}
171 	tri = reg_ielmr[g];
172 	if ((flags&IRQ_TYPE_LEVEL_LOW) || (flags&IRQ_TYPE_LEVEL_HIGH)) {
173 		CLEAR_MASK(*tri, BIT(i));
174 	} else {
175 		SET_MASK(*tri, BIT(i));
176 	}
177 }
178 
ite_intc_irq_is_enable(unsigned int irq)179 int __soc_ram_code ite_intc_irq_is_enable(unsigned int irq)
180 {
181 	uint32_t g, i;
182 	volatile uint8_t *en;
183 
184 	if (irq > CONFIG_NUM_IRQS) {
185 		return 0;
186 	}
187 	g = irq / MAX_REGISR_IRQ_NUM;
188 	i = irq % MAX_REGISR_IRQ_NUM;
189 	en = reg_enable[g];
190 	return IS_MASK_SET(*en, BIT(i));
191 }
192 
ite_intc_get_irq_num(void)193 uint8_t __soc_ram_code ite_intc_get_irq_num(void)
194 {
195 	return intc_irq;
196 }
197 
ite_intc_no_irq(void)198 bool __soc_ram_code ite_intc_no_irq(void)
199 {
200 	return (IVECT == IVECT_OFFSET_WITH_IRQ);
201 }
202 
get_irq(void * arg)203 uint8_t __soc_ram_code get_irq(void *arg)
204 {
205 	ARG_UNUSED(arg);
206 
207 	/* wait until two equal interrupt values are read */
208 	do {
209 		/* Read interrupt number from interrupt vector register */
210 		intc_irq = IVECT;
211 		/*
212 		 * WORKAROUND: when the interrupt vector register (IVECT)
213 		 * isn't latched in a load operation, we read it again to make
214 		 * sure the value we got is the correct value.
215 		 */
216 	} while (intc_irq != IVECT);
217 	/* determine interrupt number */
218 	intc_irq -= IVECT_OFFSET_WITH_IRQ;
219 	/*
220 	 * Look for pending interrupt if there's interrupt number 0 from
221 	 * the AIVECT register.
222 	 */
223 	if (intc_irq == 0) {
224 		uint8_t int_pending;
225 
226 		for (int i = (IT8XXX2_IER_COUNT - 1); i >= 0; i--) {
227 			int_pending = (*reg_status[i] & *reg_enable[i]);
228 			if (int_pending != 0) {
229 				intc_irq = (MAX_REGISR_IRQ_NUM * i) +
230 						find_msb_set(int_pending) - 1;
231 				LOG_DBG("Pending interrupt found: %d",
232 						intc_irq);
233 				LOG_DBG("CPU mepc: 0x%lx", csr_read(mepc));
234 				break;
235 			}
236 		}
237 	}
238 	/* clear interrupt status */
239 	ite_intc_isr_clear(intc_irq);
240 	/* return interrupt number */
241 	return intc_irq;
242 }
243 
soc_interrupt_init(void)244 void soc_interrupt_init(void)
245 {
246 #ifdef CONFIG_ZTEST
247 	/*
248 	 * After flashed EC image, we needed to manually press the reset button
249 	 * on it8xxx2_evb, then run the test. Now, without pressing the button,
250 	 * we can disable debug mode and trigger a watchdog hard reset then
251 	 * run tests.
252 	 */
253 	struct wdt_it8xxx2_regs *const wdt_regs = WDT_IT8XXX2_REGS_BASE;
254 	struct gctrl_it8xxx2_regs *const gctrl_regs = GCTRL_IT8XXX2_REGS_BASE;
255 
256 	if (gctrl_regs->GCTRL_DBGROS & IT8XXX2_GCTRL_SMB_DBGR) {
257 		/* Disable debug mode through i2c */
258 		IT8XXX2_SMB_SLVISELR |= BIT(4);
259 		/* Enable ETWD reset */
260 		wdt_regs->ETWCFG = 0;
261 		wdt_regs->ET1PSR = IT8XXX2_WDT_ETPS_1P024_KHZ;
262 		wdt_regs->ETWCFG = (IT8XXX2_WDT_EWDKEYEN | IT8XXX2_WDT_EWDSRC);
263 		/* Enable ETWD hardware reset */
264 		gctrl_regs->GCTRL_ETWDUARTCR |= IT8XXX2_GCTRL_ETWD_HW_RST_EN;
265 		/* Trigger ETWD reset */
266 		wdt_regs->EWDKEYR = 0;
267 
268 		/* Spin and wait for reboot */
269 		while (1)
270 			;
271 	} else {
272 		/* Disable ETWD hardware reset */
273 		gctrl_regs->GCTRL_ETWDUARTCR &= ~IT8XXX2_GCTRL_ETWD_HW_RST_EN;
274 	}
275 #endif
276 
277 	/* Ensure interrupts of soc are disabled at default */
278 	for (int i = 0; i < ARRAY_SIZE(reg_enable); i++) {
279 		*reg_enable[i] = 0;
280 	}
281 
282 	/* Enable M-mode external interrupt */
283 	csr_set(mie, MIP_MEIP);
284 }
285