Software APIs
dif_pattgen.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 
9 
10 #include "pattgen_regs.h" // Generated.
11 
13  const dif_pattgen_t *pattgen, dif_pattgen_channel_t channel,
15  if (pattgen == NULL || config.polarity >= kDifPattgenPolarityCount ||
16  config.seed_pattern_length == 0 || config.seed_pattern_length > 64 ||
17  config.num_pattern_repetitions == 0 ||
18  config.num_pattern_repetitions > 1024) {
19  return kDifBadArg;
20  }
21 
22  bitfield_bit32_index_t enable_bit_idx;
23  bitfield_bit32_index_t polarity_bit_idx;
24  ptrdiff_t clock_divisor_reg_offset;
25  ptrdiff_t seed_lower_reg_offset;
26  ptrdiff_t seed_upper_reg_offset;
27  bitfield_field32_t seed_pattern_length_field;
28  bitfield_field32_t num_pattern_repetitions_field;
29 
30 #define DIF_PATTGEN_CHANNEL_CONFIG_CASE_(channel_) \
31  case kDifPattgenChannel##channel_: \
32  enable_bit_idx = PATTGEN_CTRL_ENABLE_CH##channel_##_BIT; \
33  polarity_bit_idx = PATTGEN_CTRL_POLARITY_CH##channel_##_BIT; \
34  clock_divisor_reg_offset = PATTGEN_PREDIV_CH##channel_##_REG_OFFSET; \
35  seed_lower_reg_offset = PATTGEN_DATA_CH##channel_##_0_REG_OFFSET; \
36  seed_upper_reg_offset = PATTGEN_DATA_CH##channel_##_1_REG_OFFSET; \
37  seed_pattern_length_field = PATTGEN_SIZE_LEN_CH##channel_##_FIELD; \
38  num_pattern_repetitions_field = PATTGEN_SIZE_REPS_CH##channel_##_FIELD; \
39  break;
40 
41  switch (channel) {
42  DIF_PATTGEN_CHANNEL_LIST(DIF_PATTGEN_CHANNEL_CONFIG_CASE_)
43  default:
44  return kDifBadArg;
45  }
46 #undef DIF_PATTGEN_CHANNEL_CONFIG_CASE_
47 
48  uint32_t ctrl_reg =
49  mmio_region_read32(pattgen->base_addr, PATTGEN_CTRL_REG_OFFSET);
50 
51  // Check if channel is enabled. We cannot configure the channel if so.
52  if (bitfield_bit32_read(ctrl_reg, enable_bit_idx)) {
53  return kDifError;
54  }
55 
56  // Set the polarity.
57  ctrl_reg = bitfield_bit32_write(ctrl_reg, polarity_bit_idx, config.polarity);
58  mmio_region_write32(pattgen->base_addr, PATTGEN_CTRL_REG_OFFSET, ctrl_reg);
59 
60  // Set the clock divisor.
61  mmio_region_write32(pattgen->base_addr, clock_divisor_reg_offset,
62  config.clock_divisor);
63 
64  // Write the seed data.
65  mmio_region_write32(pattgen->base_addr, seed_lower_reg_offset,
67  if (config.seed_pattern_length > 31) {
68  mmio_region_write32(pattgen->base_addr, seed_upper_reg_offset,
70  }
71 
72  // Set the size and repetition values.
73  uint32_t size_reg =
74  mmio_region_read32(pattgen->base_addr, PATTGEN_SIZE_REG_OFFSET);
75  size_reg = bitfield_field32_write(size_reg, seed_pattern_length_field,
76  config.seed_pattern_length - 1);
77  size_reg = bitfield_field32_write(size_reg, num_pattern_repetitions_field,
78  config.num_pattern_repetitions - 1);
79  mmio_region_write32(pattgen->base_addr, PATTGEN_SIZE_REG_OFFSET, size_reg);
80 
81  return kDifOk;
82 }
83 
85  dif_pattgen_channel_t channel,
86  dif_toggle_t enabled) {
87  if (pattgen == NULL || !dif_is_valid_toggle(enabled)) {
88  return kDifBadArg;
89  }
90 
91  bitfield_bit32_index_t enable_bit_idx;
92 
93 #define DIF_PATTGEN_CHANNEL_SET_ENABLED_CASE_(channel_) \
94  case kDifPattgenChannel##channel_: \
95  enable_bit_idx = PATTGEN_CTRL_ENABLE_CH##channel_##_BIT; \
96  break;
97 
98  switch (channel) {
99  DIF_PATTGEN_CHANNEL_LIST(DIF_PATTGEN_CHANNEL_SET_ENABLED_CASE_)
100  default:
101  return kDifBadArg;
102  }
103 #undef DIF_PATTGEN_CHANNEL_SET_ENABLED_CASE_
104 
105  uint32_t ctrl_reg =
106  mmio_region_read32(pattgen->base_addr, PATTGEN_CTRL_REG_OFFSET);
107  ctrl_reg = bitfield_bit32_write(ctrl_reg, enable_bit_idx,
108  dif_toggle_to_bool(enabled));
109  mmio_region_write32(pattgen->base_addr, PATTGEN_CTRL_REG_OFFSET, ctrl_reg);
110 
111  return kDifOk;
112 }
113 
115  dif_pattgen_channel_t channel,
116  dif_toggle_t *is_enabled) {
117  if (pattgen == NULL || is_enabled == NULL) {
118  return kDifBadArg;
119  }
120 
121  bitfield_bit32_index_t enable_bit_idx;
122 
123 #define DIF_PATTGEN_CHANNEL_SET_ENABLED_CASE_(channel_) \
124  case kDifPattgenChannel##channel_: \
125  enable_bit_idx = PATTGEN_CTRL_ENABLE_CH##channel_##_BIT; \
126  break;
127 
128  switch (channel) {
129  DIF_PATTGEN_CHANNEL_LIST(DIF_PATTGEN_CHANNEL_SET_ENABLED_CASE_)
130  default:
131  return kDifBadArg;
132  }
133 #undef DIF_PATTGEN_CHANNEL_SET_ENABLED_CASE_
134 
135  uint32_t ctrl_reg =
136  mmio_region_read32(pattgen->base_addr, PATTGEN_CTRL_REG_OFFSET);
137  *is_enabled =
138  dif_bool_to_toggle(bitfield_bit32_read(ctrl_reg, enable_bit_idx));
139 
140  return kDifOk;
141 }