Intel® Quark™ Microcontroller Software Interface 1.4.0 Intel® Quark™ Microcontroller BSP

- Main Page
- Modules
- Data Structures
- Files

- File List

qm_mailbox_se.c
1 /*
2 * {% copyright %}
3 */
4
5 #include "qm_common.h"
6 #include "qm_mailbox.h"
7 #include "qm_interrupt.h"
8 #include "qm_interrupt_router.h"
9
10 /**
11 * The Active core can be either Lakemont or the Sensor Sub-System.
12 * The active core depends on a compilation flag indicating which
13 * core is being used.
14 *
15 * Core specific mailbox #defines are grouped here to prevent
16 * duplication below.
17 */
18
19 #if HAS_MAILBOX_LAKEMONT_DEST
20 #if QM_LAKEMONT
21 #define ACTIVE_CORE_DEST QM_MBOX_TO_LMT
22 #define MBOX_ACTIVE_CORE_ALL_INT_MASK QM_IR_MBOX_LMT_ALL_INT_MASK
23 #define MBOX_INT_LOCK_MASK(N) QM_IR_MBOX_LMT_INT_LOCK_MASK(N)
24 #define MBOX_INT_LOCK_HALT_MASK(N) QM_IR_MBOX_LMT_INT_LOCK_HALT_MASK(N)
25 #define MBOX_IS_INT_MASK_EN(N) QM_IR_MBOX_IS_LMT_INT_MASK_EN(N)
26 #define MBOX_ENABLE_INT_MASK(N) QM_IR_MBOX_ENABLE_LMT_INT_MASK(N)
27 #define MBOX_DISABLE_INT_MASK(N) QM_IR_MBOX_DISABLE_LMT_INT_MASK(N)
28 #endif /* QM_LAKEMONT */
29 #endif /* HAS_MAILBOX_LAKEMONT_DEST */
30
31 #if HAS_MAILBOX_SENSOR_SUB_SYSTEM_DEST
32 #if QM_SENSOR
33 #define ACTIVE_CORE_DEST QM_MBOX_TO_SS
34 #define MBOX_ACTIVE_CORE_ALL_INT_MASK QM_IR_MBOX_SS_ALL_INT_MASK
35 #define MBOX_INT_LOCK_MASK(N) QM_IR_MBOX_SS_INT_LOCK_HALT_MASK(N)
36 #define MBOX_INT_LOCK_HALT_MASK(N) QM_IR_MBOX_SS_INT_LOCK_MASK(N)
37 #define MBOX_IS_INT_MASK_EN(N) QM_IR_MBOX_IS_SS_INT_MASK_EN(N)
38 #define MBOX_ENABLE_INT_MASK(N) QM_IR_MBOX_ENABLE_SS_INT_MASK(N)
39 #define MBOX_DISABLE_INT_MASK(N) QM_IR_MBOX_DISABLE_SS_INT_MASK(N)
40 #endif /* QM_SENSOR */
41 #endif /* HAS_MAILBOX_SENSOR_SUB_SYSTEM_DEST */
42
43 #define MBOX_CHECK_DESTINATION(_dest) (ACTIVE_CORE_DEST == (_dest))
44 #define MBOX_CHECK_POLLING_MODE(_mode) (QM_MBOX_POLLING_MODE == (_mode))
45
46 static void mailbox_isr_handler(void);
47
48 /**
49 * Private data structure maintained by the driver
50 */
51 typedef struct {
52 /** Destination of the mailbox channel. */
53 qm_mbox_destination_t dest;
54 /** Defines if the mailbox channel operates in interrupt
55 * mode or polling mode. */
56 qm_mbox_mode_t mode;
57 /** Callback function registered with the application. */
58 qm_mbox_callback_t callback;
59 /** Callback function data return via the callback function. */
60 void *callback_data;
61 } qm_mailbox_info_t;
62
63 /* Mailbox channels private data structures */
64 static qm_mailbox_info_t mailbox_devs[NUM_MAILBOXES];
65
66 QM_ISR_DECLARE(qm_mailbox_0_isr)
67 {
68 mailbox_isr_handler();
69 QM_ISR_EOI(QM_IRQ_MAILBOX_0_INT_VECTOR);
70 }
71
72 static void mailbox_isr_handler(void)
73 {
74 qm_mailbox_t *const mbox_reg = (qm_mailbox_t *)QM_MAILBOX;
75 uint8_t i = 0;
76 uint8_t mask;
77 uint16_t chall_sts = QM_MAILBOX->mbox_chall_sts;
78
79 mask = MBOX_ACTIVE_CORE_ALL_INT_MASK;
80 for (i = 0; chall_sts; i++, chall_sts >>= 2) {
81 if ((chall_sts & QM_MBOX_CH_STS_CTRL_INT) == 0) {
82 continue;
83 }
84 if (mask & BIT(i)) {
85 continue;
86 }
87 if (mbox_reg[i].ch_sts & QM_MBOX_CH_STS_CTRL_INT) {
88 if (NULL != mailbox_devs[i].callback) {
89 /* Callback */
90 mailbox_devs[i].callback(
91 mailbox_devs[i].callback_data);
92 }
93 /* Clear the interrupt */
94 mbox_reg[i].ch_sts = QM_MBOX_CH_STS_CTRL_INT;
95 }
96 }
97 }
98
99 int qm_mbox_ch_set_config(const qm_mbox_ch_t mbox_ch,
100 const qm_mbox_config_t *const config)
101 {
102
103 QM_CHECK((QM_MBOX_CH_0 <= mbox_ch) && (mbox_ch < NUM_MAILBOXES),
104 -EINVAL);
105 qm_mailbox_info_t *device = &mailbox_devs[mbox_ch];
106
107 /* Block interrupts while configuring MBOX */
108 QM_IR_MASK_INT(QM_IRQ_MAILBOX_0_INT);
109
110 /* Store the device destination */
111 device->dest = config->dest;
112
113 /* Check if we are enabling or disabling the channel. */
114 if (QM_MBOX_UNUSED != config->dest) {
115
116 if (QM_MBOX_INTERRUPT_MODE == config->mode) {
117 QM_CHECK(NULL != config->callback, -EINVAL);
118
119 /* Register callback function */
120 device->callback = config->callback;
121 /* Register callback function data */
122 device->callback_data = config->callback_data;
123 /* Update the mode of operation for the mailbox channel.
124 */
125 device->mode = QM_MBOX_INTERRUPT_MODE;
126
127 /* Enable the mailbox interrupt if the lock is not set.
128 */
129 if (!(MBOX_INT_LOCK_MASK(mbox_ch))) {
130 /* Note: Routing is done now, cannot be done in
131 * irq_request! */
132 MBOX_ENABLE_INT_MASK(mbox_ch);
133 } else {
134 /* The lock is set, but we need to check if the
135 * interrupt is routed */
136 QM_CHECK(MBOX_IS_INT_MASK_EN(mbox_ch), -EIO);
137 }
138 } else {
139 device->mode = QM_MBOX_POLLING_MODE;
140 /* Disable the mailbox interrupt if the lock is not set.
141 */
142 if (!(MBOX_INT_LOCK_MASK(mbox_ch))) {
143 /* Note: Routing is done now, cannot be done in
144 * irq_request! */
145 MBOX_DISABLE_INT_MASK(mbox_ch);
146 }
147
148 device->callback = NULL;
149 device->callback_data = 0;
150 }
151 } else {
152 /* Disable the mailbox interrupt if the lock is not set. */
153 if (!(MBOX_INT_LOCK_MASK(mbox_ch))) {
154 /* Note: Routing is done now, cannot be done in
155 * irq_request! */
156 MBOX_DISABLE_INT_MASK(mbox_ch);
157 }
158
159 /* Set the mailbox channel to its default configuration. */
160 device->dest = QM_MBOX_UNUSED;
161 device->mode = QM_MBOX_INTERRUPT_MODE;
162 device->callback = NULL;
163 device->callback_data = 0;
164 }
165
166 /* UnBlock MBOX interrupts. */
167 QM_IR_UNMASK_INT(QM_IRQ_MAILBOX_0_INT);
168 return 0;
169 }
170
171 int qm_mbox_ch_write(const qm_mbox_ch_t mbox_ch, const qm_mbox_msg_t *const msg)
172 {
173 QM_CHECK((QM_MBOX_CH_0 <= mbox_ch) && (mbox_ch < NUM_MAILBOXES),
174 -EINVAL);
175 QM_CHECK(NULL != msg, -EINVAL);
176 qm_mailbox_t *const mbox_reg = (qm_mailbox_t *)QM_MAILBOX + mbox_ch;
177
178 uint32_t status = 0;
179
180 status = QM_MAILBOX->mbox[mbox_ch].ch_sts;
181
182 /* Check if the previous message has been consumed. */
183 if (false == (status & (QM_MBOX_CH_STS_CTRL_INT | QM_MBOX_CH_STS))) {
184 /* Write the payload data to the mailbox channel. */
185 mbox_reg->ch_data[0] = msg->data[QM_MBOX_PAYLOAD_0];
186 mbox_reg->ch_data[1] = msg->data[QM_MBOX_PAYLOAD_1];
187 mbox_reg->ch_data[2] = msg->data[QM_MBOX_PAYLOAD_2];
188 mbox_reg->ch_data[3] = msg->data[QM_MBOX_PAYLOAD_3];
189 /* Write the control word and trigger the channel interrupt. */
190 mbox_reg->ch_ctrl = msg->ctrl | QM_MBOX_CH_CTRL_INT;
191 return 0;
192 }
193
194 /* Previous message has not been consumed. */
195 return -EIO;
196 }
197
198 int qm_mbox_ch_read(const qm_mbox_ch_t mbox_ch, qm_mbox_msg_t *const msg)
199 {
200 QM_CHECK((QM_MBOX_CH_0 <= mbox_ch) && (mbox_ch < NUM_MAILBOXES),
201 -EINVAL);
202 QM_CHECK(NULL != msg, -EINVAL);
203
204 int rc = 0;
205 uint32_t status = 0;
206
207 qm_mailbox_t *mbox_reg = &QM_MAILBOX->mbox[mbox_ch];
208
209 if (MBOX_CHECK_DESTINATION(mailbox_devs[mbox_ch].dest)) {
210 status = mbox_reg->ch_sts;
211
212 /* If there is data pending consume it */
213 if (status & QM_MBOX_CH_STS) {
214 /* Read data from the mailbox channel and clear bit 31
215 * of the control word. */
216 msg->ctrl = mbox_reg->ch_ctrl & (~QM_MBOX_CH_CTRL_INT);
217 msg->data[0] = mbox_reg->ch_data[0];
218 msg->data[1] = mbox_reg->ch_data[1];
219 msg->data[2] = mbox_reg->ch_data[2];
220 msg->data[3] = mbox_reg->ch_data[3];
221
222 if (MBOX_CHECK_POLLING_MODE(
223 mailbox_devs[mbox_ch].mode)) {
224 /* In polling mode the interrupt status still
225 * needs to be cleared since we are not using
226 * the ISR. Note we write 1 to clear the bit.
227 */
228 mbox_reg->ch_sts = QM_MBOX_CH_STS_CTRL_INT;
229 }
230
231 /* Clear data status bit. This indicates to others that
232 * the mailbox data has been consumed and a new message
233 * can be sent on the channel */
234 mbox_reg->ch_sts = QM_MBOX_CH_STS;
235 } else {
236 /* there is no pending data in the mailbox */
237 rc = -EIO;
238 }
239 } else {
240 /* Active destination has not been configured to consume data
241 * from this channel */
242 rc = -EINVAL;
243 }
244
245 return rc;
246 }
247
248 int qm_mbox_ch_get_status(const qm_mbox_ch_t mbox_ch,
249 qm_mbox_ch_status_t *const status)
250 {
251 QM_CHECK((QM_MBOX_CH_0 <= mbox_ch) && (mbox_ch < NUM_MAILBOXES),
252 -EINVAL);
253 QM_CHECK(NULL != status, -EINVAL);
254
255 *status = QM_MAILBOX->mbox[mbox_ch].ch_sts;
256
257 return 0;
258 }
qm_mbox_callback_t
void(* qm_mbox_callback_t)(void *data)
Definition of the mailbox callback function prototype.
Definition: qm_mailbox.h:78
QM_MBOX_PAYLOAD_1
Payload index value 1.
Definition: qm_mailbox.h:45
qm_mbox_ch_read
int qm_mbox_ch_read(const qm_mbox_ch_t mbox_ch, qm_mbox_msg_t *const msg)
Read specified mailbox channel.
Definition: qm_mailbox_se.c:198
qm_mbox_ch_t
qm_mbox_ch_t
Mailbox channel identifiers.
Definition: qm_mailbox_defs.h:18
qm_mailbox_t::ch_data
QM_RW uint32_t ch_data[4]
Channel Payload Data Word 0.
Definition: qm_soc_regs.h:636
qm_mbox_config_t::dest
qm_mbox_destination_t dest
< Mailbox Destination
Definition: qm_mailbox.h:85
qm_mailbox_t::ch_ctrl
QM_RW uint32_t ch_ctrl
Channel Control Word.
Definition: qm_soc_regs.h:635
QM_MBOX_POLLING_MODE
Mailbox channel operates in polling mode.
Definition: qm_mailbox.h:58
qm_mbox_msg_t::data
uint32_t data[QM_MBOX_PAYLOAD_NUM]
Mailbox data buffer.
Definition: qm_mailbox.h:70
QM_MBOX_PAYLOAD_2
Payload index value 2.
Definition: qm_mailbox.h:46
qm_mbox_ch_write
int qm_mbox_ch_write(const qm_mbox_ch_t mbox_ch, const qm_mbox_msg_t *const msg)
Write to a specified mailbox channel.
Definition: qm_mailbox_se.c:171
qm_mbox_ch_get_status
int qm_mbox_ch_get_status(const qm_mbox_ch_t mbox_ch, qm_mbox_ch_status_t *const status)
Retrieve the specified mailbox channel status.
Definition: qm_mailbox_se.c:248
qm_mbox_msg_t::ctrl
uint32_t ctrl
Control word - bits 30 to 0 used as data/message id, bit 31 triggers channel interrupt when set by th...
Definition: qm_mailbox.h:68
qm_mbox_msg_t
Definition of the mailbox message.
Definition: qm_mailbox.h:64
QM_ISR_DECLARE
QM_ISR_DECLARE(qm_mailbox_0_isr)
ISR for Mailbox interrupt.
Definition: qm_mailbox_se.c:66
qm_mailbox_t::ch_sts
QM_RW uint32_t ch_sts
Channel status.
Definition: qm_soc_regs.h:637
qm_mbox_ch_set_config
int qm_mbox_ch_set_config(const qm_mbox_ch_t mbox_ch, const qm_mbox_config_t *const config)
Set the mailbox channel configuration.
Definition: qm_mailbox_se.c:99
qm_mailbox_t
Mailbox register structure.
Definition: qm_soc_regs.h:634
qm_mbox_destination_t
qm_mbox_destination_t
Definition of the mailbox direction of operation The direction of communication for each channel is c...
Definition: qm_mailbox_defs.h:35
QM_MBOX_INTERRUPT_MODE
Mailbox channel operates in interrupt mode.
Definition: qm_mailbox.h:56
qm_mbox_config_t::mode
qm_mbox_mode_t mode
Message callback.
Definition: qm_mailbox.h:87
qm_mbox_mode_t
qm_mbox_mode_t
Definition of the mailbox mode of operation, interrupt mode or polling mode.
Definition: qm_mailbox.h:54
QM_MBOX_PAYLOAD_3
Payload index value 3.
Definition: qm_mailbox.h:47
QM_MBOX_PAYLOAD_0
Payload index value 0.
Definition: qm_mailbox.h:44
qm_mbox_config_t
Mailbox Configuration Structure.
Definition: qm_mailbox.h:83
qm_mbox_config_t::callback
qm_mbox_callback_t callback
Callback function data to return via the callback function.
Definition: qm_mailbox.h:99
QM_MBOX_CH_0
Channel 0.
Definition: qm_mailbox_defs.h:19
qm_mbox_ch_status_t
qm_mbox_ch_status_t
Mailbox channel status return codes.
Definition: qm_mailbox.h:23