Intel® Quark™ Microcontroller Software Interface  1.4.0
Intel® Quark™ Microcontroller BSP
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. */
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 
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 
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 }
void(* qm_mbox_callback_t)(void *data)
Definition of the mailbox callback function prototype.
Definition: qm_mailbox.h:78
Payload index value 1.
Definition: qm_mailbox.h:45
int qm_mbox_ch_read(const qm_mbox_ch_t mbox_ch, qm_mbox_msg_t *const msg)
Read specified mailbox channel.
qm_mbox_ch_t
Mailbox channel identifiers.
QM_RW uint32_t ch_data[4]
Channel Payload Data Word 0.
Definition: qm_soc_regs.h:636
qm_mbox_destination_t dest
< Mailbox Destination
Definition: qm_mailbox.h:85
QM_RW uint32_t ch_ctrl
Channel Control Word.
Definition: qm_soc_regs.h:635
Mailbox channel operates in polling mode.
Definition: qm_mailbox.h:58
uint32_t data[QM_MBOX_PAYLOAD_NUM]
Mailbox data buffer.
Definition: qm_mailbox.h:70
Payload index value 2.
Definition: qm_mailbox.h:46
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.
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.
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
Definition of the mailbox message.
Definition: qm_mailbox.h:64
QM_ISR_DECLARE(qm_mailbox_0_isr)
ISR for Mailbox interrupt.
Definition: qm_mailbox_se.c:66
QM_RW uint32_t ch_sts
Channel status.
Definition: qm_soc_regs.h:637
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
Mailbox register structure.
Definition: qm_soc_regs.h:634
qm_mbox_destination_t
Definition of the mailbox direction of operation The direction of communication for each channel is c...
Mailbox channel operates in interrupt mode.
Definition: qm_mailbox.h:56
qm_mbox_mode_t mode
Message callback.
Definition: qm_mailbox.h:87
qm_mbox_mode_t
Definition of the mailbox mode of operation, interrupt mode or polling mode.
Definition: qm_mailbox.h:54
Payload index value 3.
Definition: qm_mailbox.h:47
Payload index value 0.
Definition: qm_mailbox.h:44
Mailbox Configuration Structure.
Definition: qm_mailbox.h:83
qm_mbox_callback_t callback
Callback function data to return via the callback function.
Definition: qm_mailbox.h:99
Channel 0.
qm_mbox_ch_status_t
Mailbox channel status return codes.
Definition: qm_mailbox.h:23