Software APIs
rom_e2e_c_init_test.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 
13 #include "sw/device/silicon_creator/lib/drivers/otp.h"
14 #include "sw/device/silicon_creator/lib/drivers/pinmux.h"
15 #include "sw/device/silicon_creator/lib/drivers/uart.h"
16 #include "sw/device/silicon_creator/lib/error.h"
17 #include "sw/device/silicon_creator/lib/manifest_def.h"
18 
20 #include "otp_ctrl_regs.h"
21 #include "pinmux_regs.h"
22 #include "uart_regs.h"
23 
24 enum {
25  /**
26  * Base address of the pinmux registers.
27  */
29  /**
30  * Base address of the UART registers.
31  */
32  kUartBase = TOP_EARLGREY_UART0_BASE_ADDR,
33 };
34 
35 /**
36  * Set up peripherals for printing.
37  *
38  * This clobbers the existing pinmux/UART configuration and should only be used
39  * at the very end of the test (e.g. to print a message saying whether the
40  * tests passed or failed).
41  *
42  * Must be called before using `LOG_INFO` or `LOG_ERROR`.
43  */
44 static void setup_stdout(void) {
45  pinmux_init();
46  uart_init(kUartNCOValue);
48  .data = NULL,
49  .sink = uart_sink,
50  });
51 }
52 
53 /**
54  * Trigger an instruction access fault.
55  */
56 static void fault(void) {
58 }
59 
60 /**
61  * Trigger an instruction access fault if the values are not equal.
62  */
63 #define CHECK_EQ(lhs_, rhs_, name_) \
64  do { \
65  if (lhs_ != rhs_) { \
66  setup_stdout(); \
67  LOG_ERROR("Check failed: %s (0x%08x != 0x%08x)", name_, lhs_, rhs_); \
68  fault(); \
69  } \
70  } while (false)
71 
72 /**
73  * Get device-specific mask for MIO pad attributes.
74  *
75  * Bits are set if the attribute is legal for the current device. This mask
76  * should match the result of writing UINT32_MAX to the pad attribute register
77  * and then reading back, because the pad attribute registers have
78  * write-any-read-legal behavior.
79  */
80 static uint32_t pad_attr_mask_get(void) {
81  CHECK_EQ(kDeviceType, kDeviceFpgaCw310,
82  "This test is only supported for CW310");
83 
84  // The only legal attributes on CW310 are `invert`, `virtual_od_en`, and
85  // `input_disable`.
86  uint32_t mask = 0;
87  mask = bitfield_bit32_write(mask, PINMUX_MIO_PAD_ATTR_0_INVERT_0_BIT, true);
88  mask = bitfield_bit32_write(mask, PINMUX_MIO_PAD_ATTR_0_VIRTUAL_OD_EN_0_BIT,
89  true);
90  mask = bitfield_bit32_write(mask, PINMUX_MIO_PAD_ATTR_0_INPUT_DISABLE_0_BIT,
91  true);
92 
93  // Save the original attributes for pad 0.
94  uint32_t attr0_orig =
95  abs_mmio_read32(kPinmuxBase + PINMUX_MIO_PAD_ATTR_0_REG_OFFSET);
96 
97  // Check that the mask is correct by writing UINT32_MAX to the attribute
98  // register for pad 0, and then reading back.
99  abs_mmio_write32(kPinmuxBase + PINMUX_MIO_PAD_ATTR_0_REG_OFFSET, UINT32_MAX);
100  uint32_t attr0_legal =
101  abs_mmio_read32(kPinmuxBase + PINMUX_MIO_PAD_ATTR_0_REG_OFFSET);
102  CHECK_EQ(attr0_legal, mask, "Pad attribute mask check");
103 
104  // Restore the original register value.
105  abs_mmio_write32(kPinmuxBase + PINMUX_MIO_PAD_ATTR_0_REG_OFFSET, attr0_orig);
106 
107  return mask;
108 }
109 
110 /**
111  * Check that the pinmux has been initialized correctly.
112  *
113  * Expected configuration:
114  * - If the OTP BOOTSTRAP_EN option is set, then pinmux should be configured
115  * with the following peripheral/pad mapping, with pull-down enabled for all
116  * pads:
117  * * GPIO22 -> IOC0
118  * * GPIO23 -> IOC1
119  * * GPIO24 -> IOC2
120  * - Regardless of the OTP values, the pinmux should be configured with the
121  * following mapping for UART0:
122  * * UART RX -> IOC3
123  * * IOC4 -> UART TX (output)
124  */
125 static void pinmux_init_test(void) {
126  uint32_t bootstrap_dis =
127  otp_read32(OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_BOOTSTRAP_DIS_OFFSET);
128  if (bootstrap_dis != kHardenedBoolTrue) {
129  uint32_t attr_mask = pad_attr_mask_get();
130 
131  // GPIO 22 (input 22) -> IOC0 (MIO pad 22)
132  uint32_t insel_gpio22 =
133  abs_mmio_read32(kPinmuxBase + PINMUX_MIO_PERIPH_INSEL_22_REG_OFFSET);
134  CHECK_EQ(insel_gpio22, kTopEarlgreyPinmuxInselIoc0,
135  "GPIO 22 input selector");
136 
137  // Pad 22 attributes: pull-down selected and enabled (if legal).
138  uint32_t attr22 =
139  abs_mmio_read32(kPinmuxBase + PINMUX_MIO_PAD_ATTR_22_REG_OFFSET);
140  CHECK_EQ(
141  bitfield_bit32_read(attr22, PINMUX_MIO_PAD_ATTR_22_PULL_EN_22_BIT),
142  bitfield_bit32_read(attr_mask, PINMUX_MIO_PAD_ATTR_22_PULL_EN_22_BIT),
143  "GPIO 22 pull enable");
144  CHECK_EQ(
145  bitfield_bit32_read(attr22, PINMUX_MIO_PAD_ATTR_22_PULL_SELECT_22_BIT),
146  false, "GPIO 22 pull select");
147 
148  // GPIO 23 (input 23) -> IOC1 (MIO pad 23)
149  uint32_t insel_gpio23 =
150  abs_mmio_read32(kPinmuxBase + PINMUX_MIO_PERIPH_INSEL_23_REG_OFFSET);
151  CHECK_EQ(insel_gpio23, kTopEarlgreyPinmuxInselIoc1,
152  "GPIO 23 input selector");
153 
154  // Pad 23 attributes: pull-down selected and enabled (if legal).
155  uint32_t attr23 =
156  abs_mmio_read32(kPinmuxBase + PINMUX_MIO_PAD_ATTR_23_REG_OFFSET);
157  CHECK_EQ(
158  bitfield_bit32_read(attr23, PINMUX_MIO_PAD_ATTR_23_PULL_EN_23_BIT),
159  bitfield_bit32_read(attr_mask, PINMUX_MIO_PAD_ATTR_23_PULL_EN_23_BIT),
160  "GPIO 23 pull enable");
161  CHECK_EQ(
162  bitfield_bit32_read(attr23, PINMUX_MIO_PAD_ATTR_23_PULL_SELECT_23_BIT),
163  false, "GPIO 23 pull select");
164 
165  // GPIO 24 (input 24) -> IOC2 (MIO pad 24)
166  uint32_t insel_gpio24 =
167  abs_mmio_read32(kPinmuxBase + PINMUX_MIO_PERIPH_INSEL_24_REG_OFFSET);
168  CHECK_EQ(insel_gpio24, kTopEarlgreyPinmuxInselIoc2,
169  "GPIO 24 input selector");
170 
171  // Pad 24 attributes: pull-down selected and enabled (if legal).
172  uint32_t attr24 =
173  abs_mmio_read32(kPinmuxBase + PINMUX_MIO_PAD_ATTR_24_REG_OFFSET);
174  CHECK_EQ(
175  bitfield_bit32_read(attr24, PINMUX_MIO_PAD_ATTR_24_PULL_EN_24_BIT),
176  bitfield_bit32_read(attr_mask, PINMUX_MIO_PAD_ATTR_24_PULL_EN_24_BIT),
177  "GPIO 24 pull enable");
178  CHECK_EQ(
179  bitfield_bit32_read(attr24, PINMUX_MIO_PAD_ATTR_24_PULL_SELECT_24_BIT),
180  false, "GPIO 24 pull select");
181  }
182 
183  // UART RX (input 42) -> IOC3 (MIO pad 25)
184  uint32_t insel_uartrx =
185  abs_mmio_read32(kPinmuxBase + PINMUX_MIO_PERIPH_INSEL_42_REG_OFFSET);
186  CHECK_EQ(insel_uartrx, kTopEarlgreyPinmuxInselIoc3, "UART Rx input selector");
187 
188  // IOC4 (MIO pad 26) -> UART TX (output 42)
189  uint32_t outsel_ioc4 =
190  abs_mmio_read32(kPinmuxBase + PINMUX_MIO_OUTSEL_26_REG_OFFSET);
191  CHECK_EQ(outsel_ioc4, kTopEarlgreyPinmuxOutselUart0Tx,
192  "UART Tx output selector");
193 }
194 
195 /**
196  * Check that the UART has been initialized correctly.
197  *
198  * Expected configuration:
199  * - `CTRL.TX` (TX enable) bit is true
200  * - `CTRL.RX` (RX enable) bit is false
201  * - `CTRL.SLPBK` (system loopback) bit is false
202  * - `CTRL.LLPBK` (line loopback) bit is false
203  * - `CTRL.NCO` is set to the precomputed `kUartNCOValue` for this device
204  * - `CTRL.PARITY_EN` (parity enable) bit is false
205  * - All interrupts are disabled
206  * - All FIFOs have been cleared (both Rx and Tx are empty)
207  */
208 static void uart_init_test(void) {
209  // Check the control register values.
210  uint32_t ctrl = abs_mmio_read32(kUartBase + UART_CTRL_REG_OFFSET);
211  CHECK_EQ(bitfield_bit32_read(ctrl, UART_CTRL_TX_BIT), true,
212  "UART.CTRL.TX_BIT");
213  CHECK_EQ(bitfield_bit32_read(ctrl, UART_CTRL_RX_BIT), false,
214  "UART.CTRL.RX_BIT");
215  CHECK_EQ(bitfield_bit32_read(ctrl, UART_CTRL_SLPBK_BIT), false,
216  "UART.CTRL.SLPBK_BIT");
217  CHECK_EQ(bitfield_bit32_read(ctrl, UART_CTRL_LLPBK_BIT), false,
218  "UART.CTRL.LLPBK_BIT");
219  CHECK_EQ(bitfield_field32_read(ctrl, UART_CTRL_NCO_FIELD), kUartNCOValue,
220  "UART.CTRL.NCO_FIELD");
221  CHECK_EQ(bitfield_bit32_read(ctrl, UART_CTRL_PARITY_EN_BIT), false,
222  "UART.CTRL.PARITY_EN_BIT");
223 
224  // Check that all interrupts are disabled.
225  uint32_t intr_enable =
226  abs_mmio_read32(kUartBase + UART_INTR_ENABLE_REG_OFFSET);
227  CHECK_EQ(intr_enable, 0x0, "UART.INTR_ENABLE");
228 
229  // Check that both FIFOs are idle and empty.
230  uint32_t status = abs_mmio_read32(kUartBase + UART_STATUS_REG_OFFSET);
231  CHECK_EQ(bitfield_bit32_read(status, UART_STATUS_TXIDLE_BIT), true,
232  "UART.STATUS.TXIDLE_BIT");
233  CHECK_EQ(bitfield_bit32_read(status, UART_STATUS_RXIDLE_BIT), true,
234  "UART.STATUS.RXIDLE_BIT");
235  CHECK_EQ(bitfield_bit32_read(status, UART_STATUS_TXEMPTY_BIT), true,
236  "UART.STATUS.TXEMPTY_BIT");
237  CHECK_EQ(bitfield_bit32_read(status, UART_STATUS_RXEMPTY_BIT), true,
238  "UART.STATUS.RXEMPTY_BIT");
239 }
240 
241 /**
242  * Check that the CPUCTRL CSR has been initialized correctly.
243  *
244  * Expected configuration:
245  * - Bits 0:5 of the CPUCTRL CSR should match the value specified in OTP.
246  */
247 static void cpuctrl_init_test(void) {
248  uint32_t expected_value =
249  otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_CPUCTRL_OFFSET);
250  bitfield_field32_t cpuctrl_mask = {.mask = 0x3f, .index = 0};
251  uint32_t cpuctrl_csr;
252  CSR_READ(CSR_REG_CPUCTRL, &cpuctrl_csr);
253  CHECK_EQ(bitfield_field32_read(cpuctrl_csr, cpuctrl_mask), expected_value,
254  "CPUCTRL CSR");
255 }
256 
257 /**
258  * Test entrypoint.
259  *
260  * Because this function becomes the entrypoint for the manifest, it must be
261  * word-aligned, otherwise it will trigger a `kManifestBadEntryPoint` boot
262  * fault.
263  */
264 void __attribute__((aligned(4))) _ottf_start(void) {
265  pinmux_init_test();
266  uart_init_test();
267  cpuctrl_init_test();
268 
269  setup_stdout();
270  LOG_INFO("PASS!");
272 }