Software APIs
dif_mbx.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
6 
10 
11 #include "mbx_regs.h" // Generated.
12 
14  dif_mbx_range_config_t config) {
15  if (mbx == NULL) {
16  return kDifBadArg;
17  }
18  // Note: the limit addresses are _inclusive_, specifying the start address of
19  // the final valid DWORD.
20  if (config.imbx_base_addr > config.imbx_limit_addr) {
21  return kDifBadArg;
22  }
23  if (config.ombx_base_addr > config.ombx_limit_addr) {
24  return kDifBadArg;
25  }
26  // Check that the inbound mailbox and outbound mailbox memory ranges do not
27  // collide with each other.
28  if ((config.imbx_base_addr <= config.ombx_limit_addr) &&
29  (config.ombx_base_addr <= config.imbx_limit_addr)) {
30  return kDifBadArg;
31  }
32 
33  mmio_region_write32(mbx->base_addr, MBX_INBOUND_BASE_ADDRESS_REG_OFFSET,
34  config.imbx_base_addr);
35  mmio_region_write32(mbx->base_addr, MBX_INBOUND_LIMIT_ADDRESS_REG_OFFSET,
36  config.imbx_limit_addr);
37  mmio_region_write32(mbx->base_addr, MBX_OUTBOUND_BASE_ADDRESS_REG_OFFSET,
38  config.ombx_base_addr);
39  mmio_region_write32(mbx->base_addr, MBX_OUTBOUND_LIMIT_ADDRESS_REG_OFFSET,
40  config.ombx_limit_addr);
41  // Indicate the range configuration to be valid.
42  mmio_region_write32(mbx->base_addr, MBX_ADDRESS_RANGE_VALID_REG_OFFSET, 1);
43 
44  return kDifOk;
45 }
46 
48  dif_mbx_range_config_t *config) {
49  if (mbx == NULL || config == NULL) {
50  return kDifBadArg;
51  }
52 
53  config->imbx_base_addr =
54  mmio_region_read32(mbx->base_addr, MBX_INBOUND_BASE_ADDRESS_REG_OFFSET);
55  config->imbx_limit_addr =
56  mmio_region_read32(mbx->base_addr, MBX_INBOUND_LIMIT_ADDRESS_REG_OFFSET);
57  config->ombx_base_addr =
58  mmio_region_read32(mbx->base_addr, MBX_OUTBOUND_BASE_ADDRESS_REG_OFFSET);
59  config->ombx_limit_addr =
60  mmio_region_read32(mbx->base_addr, MBX_OUTBOUND_LIMIT_ADDRESS_REG_OFFSET);
61  return kDifOk;
62 }
63 
64 dif_result_t dif_mbx_is_busy(const dif_mbx_t *mbx, bool *is_busy) {
65  if (mbx == NULL || is_busy == NULL) {
66  return kDifBadArg;
67  }
68 
69  *is_busy = (bitfield_bit32_read(
70  mmio_region_read32(mbx->base_addr, MBX_STATUS_REG_OFFSET),
71  MBX_STATUS_BUSY_BIT) == 1);
72  return kDifOk;
73 }
74 
76  uint32_t *doe_intr_addr,
77  uint32_t *doe_intr_data) {
78  if (mbx == NULL || doe_intr_addr == NULL || doe_intr_data == NULL) {
79  return kDifBadArg;
80  }
81 
82  *doe_intr_addr =
83  mmio_region_read32(mbx->base_addr, MBX_DOE_INTR_MSG_ADDR_REG_OFFSET);
84  *doe_intr_data =
85  mmio_region_read32(mbx->base_addr, MBX_DOE_INTR_MSG_DATA_REG_OFFSET);
86 
87  return kDifOk;
88 }
89 
91  dif_mbx_transaction_t *request) {
92  if (mbx == NULL || request == NULL || request->data_dwords == NULL) {
93  return kDifBadArg;
94  }
95 
96  uint32_t curr_ptr =
97  mmio_region_read32(mbx->base_addr, MBX_INBOUND_BASE_ADDRESS_REG_OFFSET);
98  uint32_t imbx_wr_ptr =
99  mmio_region_read32(mbx->base_addr, MBX_INBOUND_WRITE_PTR_REG_OFFSET);
100 
101  // Read from base until the write pointer or we hit the limit of maximum
102  // dwords.
103  uint32_t read_dwords = 0;
104  while (curr_ptr < imbx_wr_ptr && read_dwords < request->nr_dwords) {
105  request->data_dwords[read_dwords++] = abs_mmio_read32(curr_ptr);
106  curr_ptr += sizeof(uint32_t);
107  }
108 
109  // Pass back the actual number of read words
110  request->nr_dwords = read_dwords;
111 
112  // If the read pointer didn't hit the write pointer, it means we hit the limit
113  // of maximum dwords supported by the destination
114  if (curr_ptr < imbx_wr_ptr) {
115  return kDifOutOfRange;
116  }
117 
118  return kDifOk;
119 }
120 
122  const dif_mbx_transaction_t response) {
123  uint32_t curr_ptr;
124 
125  if (mbx == NULL || response.data_dwords == NULL ||
126  response.nr_dwords > DOE_MAILBOX_MAX_OBJECT_SIZE) {
127  return kDifBadArg;
128  }
129 
130  curr_ptr =
131  mmio_region_read32(mbx->base_addr, MBX_OUTBOUND_READ_PTR_REG_OFFSET);
132  for (uint32_t i = 0; i < response.nr_dwords; ++i) {
133  abs_mmio_write32(curr_ptr, response.data_dwords[i]);
134  curr_ptr += sizeof(uint32_t);
135  }
136 
137  mmio_region_write32(mbx->base_addr, MBX_OUTBOUND_OBJECT_SIZE_REG_OFFSET,
138  response.nr_dwords);
139 
140  return kDifOk;
141 }