1 /*
2  * Copyright (c) 2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef ZEPHYR_SOC_INTEL_ADSP_CAVS_IDC_H_
7 #define ZEPHYR_SOC_INTEL_ADSP_CAVS_IDC_H_
8 
9 #include <intel_adsp_ipc_devtree.h>
10 
11 /*
12  * (I)ntra (D)SP (C)ommunication is the facility for sending
13  * interrupts directly between DSP cores.  The interface
14  * is... somewhat needlessly complicated.
15  *
16  * Each core has a set of registers its is supposed to use, but all
17  * registers seem to behave symmetrically regardless of which CPU does
18  * the access.
19  *
20  * Each core has a "ITC" register associated with each other core in
21  * the system (including itself).  When the high bit becomes 1 in an
22  * ITC register, an IDC interrupt is latched for the target core.
23  * Data in other bits is stored but otherwise ignored, it's merely
24  * data to be transmitted along with the interrupt.
25  *
26  * On the target core, there is a "TFC" register for each core that
27  * reflects the same value written to ITC.  In fact experimentally
28  * these seem to be the same register at different addresses.  When
29  * the high bit of TFC is written with a 1, the value becomes ZERO,
30  * indicating an acknowledgment of the interrupt.  This action can
31  * also latch an interrupt to send back to the originator if unmasked
32  * (see below).
33  *
34  * (There is also an IETC/TEFC register pair that stores 30 bits of
35  * data but otherwise has no hardware behavior.  This is probably best
36  * ignored for new protocols, as experimentally it seems to provide no
37  * performance benefit vs. storing a message in RAM.  The cAVS 1.5/1.8
38  * ROM boot protocol uses it to store an entry point address, though.)
39  *
40  * So you can send a synchronous message from core "src" (where src is
41  * the PRID of the CPU, equal to arch_curr_cpu()->id in Zephyr) to
42  * core "dst" with:
43  *
44  *     IDC[src].core[dst].itc = BIT(31) | message;
45  *     while (IDC[src].core[dst].itc & BIT(31)) {}
46  *
47  * And the other side (on cpu "dst", generally in the IDC interrupt
48  * handler) will read and acknowledge those same values via:
49  *
50  *     uint32_t my_msg = IDC[dst].core[src].tfc & 0x7fffffff;
51  *     IDC[dst].core[src].tfc = BIT(31); // clear high bit to signal completion
52  *
53  * And for clarity, at all times and for all cores and all pairs of src/dst:
54  *
55  *     IDC[src].core[dst].itc == IDC[dst].core[src].tfc
56  *
57  * Finally note the two control registers at the end of each core's
58  * register block, which store a bitmask of cores that it is allowed
59  * to signal with an interrupt via either ITC (set high "BUSY" bit) or
60  * TFC (clear high "DONE" bit).  This masking is in ADDITION to the
61  * level 2 bit for IDC in the per-core INTCTRL DSP register AND the
62  * Xtensa architectural INTENABLE SR.  You must enable IDC interrupts
63  * form core "src" to core "dst" with:
64  *
65  *     IDC[src].busy_int |= BIT(dst)  // Or disable with "&= ~BIT(dst)" of course
66  */
67 struct cavs_idc {
68 	struct {
69 		uint32_t tfc;  /* (T)arget (F)rom (C)ore  */
70 		uint32_t tefc; /*  ^^ + (E)xtension       */
71 		uint32_t itc;  /* (I)nitiator (T)o (C)ore */
72 		uint32_t ietc; /*  ^^ + (E)xtension       */
73 	} core[4];
74 	uint32_t unused0[4];
75 	uint8_t  busy_int;     /* bitmask of cores that can IDC via ITC */
76 	uint8_t  done_int;     /* bitmask of cores that can IDC via TFC */
77 	uint8_t  unused1;
78 	uint8_t  unused2;
79 	uint32_t unused3[11];
80 };
81 
82 #define IDC ((volatile struct cavs_idc *)INTEL_ADSP_IDC_REG_ADDRESS)
83 
84 extern void soc_idc_init(void);
85 
86 /* cAVS interrupt mask bits.  Each core has one of these structs
87  * indexed in the intctrl[] array.  Each external interrupt source
88  * indexes one bit in one of the state substructs (one each for Xtensa
89  * level 2-5 interrupts).  The "mask" field shows the current masking
90  * state, with a 1 representing "interrupt disabled".  The "status"
91  * field indicates interrupts that are currently latched and awaiting
92  * delivery.  Write bits to "set" to set the mask bit to 1 and disable
93  * interrupts.  Write a 1 bit to "clear" to force the mask bit to 0
94  * and enable them.  For example, for core "c":
95  *
96  *     INTCTRL[c].l2.clear = 0x10;     // unmask IDC interrupt
97  *
98  *     INTCTRL[c].l3.set = 0xffffffff; // Mask all L3 interrupts
99  *
100  * Note that this interrupt controller is separate from the Xtensa
101  * architectural interrupt hardware controlled by the
102  * INTENABLE/INTERRUPT/INTSET/INTCLEAR special registers on each core
103  * which much also be configured for interrupts to arrive.  Note also
104  * that some hardware (like IDC, see above) implements a third (!)
105  * layer of interrupt masking.
106  */
107 struct cavs_intctrl {
108 	struct {
109 		uint32_t set, clear, mask, status;
110 	} l2, l3, l4, l5;
111 };
112 
113 /* Named interrupt bits in the above registers */
114 #define CAVS_L2_HPGPDMA    BIT(24)	/* HP General Purpose DMA */
115 #define CAVS_L2_DWCT1      BIT(23)	/* DSP Wall Clock Timer 1 */
116 #define CAVS_L2_DWCT0      BIT(22)	/* DSP Wall Clock Timer 0 */
117 #define CAVS_L2_L2ME       BIT(21)	/* L2 Memory Error */
118 #define CAVS_L2_DTS        BIT(20)	/* DSP Timestamping */
119 #define CAVS_L2_SHA        BIT(16)	/* SHA-256 */
120 #define CAVS_L2_DCLC       BIT(15)	/* Demand Cache Line Command */
121 #define CAVS_L2_IDC        BIT(8)	/* IDC */
122 #define CAVS_L2_HIPC       BIT(7)	/* Host IPC */
123 #define CAVS_L2_MIPC       BIT(6)	/* CSME IPC */
124 #define CAVS_L2_PIPC       BIT(5)	/* PMC IPC */
125 #define CAVS_L2_SIPC       BIT(4)	/* Sensor Hub IPC */
126 
127 #define CAVS_L3_DSPGCL     BIT(31)	/* DSP Gateway Code Loader */
128 #define CAVS_L3_DSPGHOS(n) BIT(16 + n)	/* DSP Gateway Host Output Stream */
129 #define CAVS_L3_HPGPDMA    BIT(15)	/* HP General Purpose DMA */
130 #define CAVS_L3_DSPGHIS(n) BIT(n)	/* DSP Gateway Host Input Stream */
131 
132 #define CAVS_L4_DSPGLOS(n) BIT(16 + n)	/* DSP Gateway Link Output Stream */
133 #define CAVS_L4_LPGPGMA    BIT(15)	/* LP General Purpose DMA */
134 #define CAVS_L4_DSPGLIS(n) BIT(n)	/* DSP Gateway Link Input Stream */
135 
136 #define CAVS_L5_LPGPDMA    BIT(16)	/* LP General Purpose DMA */
137 #define CAVS_L5_DWCT1      BIT(15)	/* DSP Wall CLock Timer 1 */
138 #define CAVS_L5_DWCT0      BIT(14)	/* DSP Wall Clock Timer 0 */
139 #define CAVS_L5_DMIX       BIT(13)	/* Digital Mixer */
140 #define CAVS_L5_ANC        BIT(12)	/* Active Noise Cancellation */
141 #define CAVS_L5_SNDW       BIT(11)	/* SoundWire */
142 #define CAVS_L5_SLIM       BIT(10)	/* Slimbus */
143 #define CAVS_L5_DSPK       BIT(9)	/* Digital Speaker */
144 #define CAVS_L5_DMIC       BIT(8)	/* Digital Mic */
145 #define CAVS_L5_I2S(n)     BIT(n)	/* I2S */
146 
147 #define CAVS_INTCTRL \
148 	((volatile struct cavs_intctrl *)DT_REG_ADDR(DT_NODELABEL(cavs_intc0)))
149 
150 #endif /* ZEPHYR_SOC_INTEL_ADSP_CAVS_IDC_H_ */
151