Software APIs
ast.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 
5 #include "sw/device/silicon_creator/lib/drivers/ast.h"
6 
10 #include "sw/device/lib/base/multibits.h"
11 #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
12 #include "sw/device/silicon_creator/lib/drivers/otp.h"
13 
14 #include "ast_regs.h"
16 #include "otp_ctrl_regs.h"
17 #include "sensor_ctrl_regs.h"
18 
19 #ifndef OT_PLATFORM_RV32
20 // Provide a definition for off-target unit tests.
21 const uint32_t kAstCheckPollCpuCycles = 10000;
22 #endif
23 
24 enum {
26  kBaseAst = TOP_EARLGREY_AST_BASE_ADDR,
27 
28  /**
29  * AST Calibration Data Size - Bank 0, Page 0
30  *
31  * Number of AST calibration words that will be stored in flash / OTP.
32  *
33  * Must match `kFlashInfoAstCalibrationDataSizeIn32BitWords` in
34  * //sw/device/silicon_creator/manuf/lib/flash_info_fields.h.
35  */
36  kAstCalibrationDataSizeIn32BitWords =
37  (AST_REGAL_REG_OFFSET + sizeof(uint32_t)) / sizeof(uint32_t),
38 
39  /**
40  * The starting offset of the AST calibration data within the
41  * `kFlashCtrlInfoPageFactoryId` info flash page.
42  *
43  * Must be compatible to the `kFlashInfoFieldAstCalibrationData` byte offset
44  * in //sw/device/silicon_creator/manuf/lib/flash_info_fields.c.
45  */
46  kAstCalibrationDataInfoFlashByteOffset =
47  OTP_CTRL_PARAM_DEVICE_ID_SIZE + OTP_CTRL_PARAM_MANUF_STATE_SIZE,
48 };
49 
50 rom_error_t ast_check(lifecycle_state_t lc_state) {
51  // In some lifecycle states we want to continue the boot process even if the
52  // AST is not initialized. Note that in these states OTP may not have been
53  // configured.
54  switch (launder32(lc_state)) {
55  case kLcStateTest:
56  HARDENED_CHECK_EQ(lc_state, kLcStateTest);
57  return kErrorOk;
58  case kLcStateRma:
59  HARDENED_CHECK_EQ(lc_state, kLcStateRma);
60  return kErrorOk;
61  case kLcStateDev:
62  HARDENED_CHECK_EQ(lc_state, kLcStateDev);
63  break;
64  case kLcStateProd:
65  HARDENED_CHECK_EQ(lc_state, kLcStateProd);
66  break;
67  case kLcStateProdEnd:
68  HARDENED_CHECK_EQ(lc_state, kLcStateProdEnd);
69  break;
70  default:
71  HARDENED_TRAP();
72  }
73 
74  // OTP can be configured to skip AST initialization. In this situation we do
75  // not check that AST_INIT_DONE is set.
76  uint32_t en = otp_read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_AST_INIT_EN_OFFSET);
77  if (launder32(en) == kMultiBitBool4False) {
78  HARDENED_CHECK_EQ(en, kMultiBitBool4False);
79  return kErrorOk;
80  }
81 
82  // AST initialization may take up to 100us. It is most likely already complete
83  // at this point but for resilience poll for up to 100us.
84  uint32_t mcycle;
85  rom_error_t res = kErrorAstInitNotDone;
86  CSR_WRITE(CSR_REG_MCYCLE, 0);
87  do {
88  CSR_READ(CSR_REG_MCYCLE, &mcycle);
89  hardened_bool_t init_done = ast_init_done();
90  if (init_done != kHardenedBoolFalse) {
91  static_assert(kErrorOk == (rom_error_t)kHardenedBoolTrue,
92  "kErrorOk must be equal to kHardenedBoolTrue");
93  res = (rom_error_t)init_done;
94  break;
95  }
96  } while (mcycle < kAstCheckPollCpuCycles);
97 
98  return res;
99 }
100 
102 static bool done_bit_get(void) {
103  uint32_t reg =
104  abs_mmio_read32(kBaseSensorCtrl + SENSOR_CTRL_STATUS_REG_OFFSET);
105  return bitfield_bit32_read(reg, SENSOR_CTRL_STATUS_AST_INIT_DONE_BIT);
106 }
107 
108 hardened_bool_t ast_init_done(void) {
109  static_assert(kHardenedBoolTrue == 0x739,
110  "This function expects kHardenedBoolTrue to be 0x739");
111 
112  // The code below reads the AST_INIT_DONE bit twice and modifies `res` with
113  // the result of each attempt. `res` should be `kHardenedBoolTrue` if all
114  // attempts return true.
115  hardened_bool_t res = 0x631;
116  res |= (hardened_bool_t)done_bit_get() << 3;
117  res |= (hardened_bool_t)done_bit_get() << 8;
118 
119  if (res != kHardenedBoolTrue) {
120  return kHardenedBoolFalse;
121  }
122  return res;
123 }
124 
125 /**
126  * Loads AST patch from kFlashCtrlInfoPageFactoryId page.
127  *
128  * The `ast_data` offset must be equivalent to the one used in
129  * //sw/device/silicon_creator/manuf/lib/ast_program.c.
130  *
131  * The info flash configuration must also be the same used to program the page,
132  * otherwise the data read will be garbled.
133  *
134  * @param[out] ast_data Pointer to the buffer used to store the data read.
135  *
136  * @return The result of the operation.
137  */
139 static rom_error_t load_ast_config_from_flash(uint32_t *ast_data) {
140  flash_ctrl_info_perms_set(&kFlashCtrlInfoPageFactoryId,
142  .read = kMultiBitBool4True,
143  .write = kMultiBitBool4False,
144  .erase = kMultiBitBool4False,
145  });
146  flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageFactoryId,
148  .scrambling = kMultiBitBool4False,
149  .ecc = kMultiBitBool4True,
150  .he = kMultiBitBool4False,
151  });
152  return flash_ctrl_info_read(&kFlashCtrlInfoPageFactoryId,
153  kAstCalibrationDataInfoFlashByteOffset,
154  kAstCalibrationDataSizeIn32BitWords, ast_data);
155 }
156 
157 rom_error_t ast_patch(lifecycle_state_t lc_state) {
158  uint32_t ast_data[kAstCalibrationDataSizeIn32BitWords];
159  HARDENED_RETURN_IF_ERROR(load_ast_config_from_flash(ast_data));
160 
161  // Skip patching logic if either of the first two words don't seem to be
162  // configured.
163  if (ast_data[0] == 0 || ast_data[0] == UINT32_MAX) {
164  return ast_check(lc_state);
165  }
166 
167  if (ast_data[1] == 0 || ast_data[1] == UINT32_MAX) {
168  return ast_check(lc_state);
169  }
170 
171  for (size_t i = 0; i < kAstCalibrationDataSizeIn32BitWords; ++i) {
172  abs_mmio_write32(kBaseAst + i * sizeof(uint32_t), ast_data[i]);
173  }
174 
175  return ast_check(lc_state);
176 }