Software APIs
dif_i2c.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 
11 
12 #include "i2c_regs.h" // Generated
13 
14 /**
15  * Performs a 32-bit integer unsigned division, rounding up. The bottom
16  * 16 bits of the result are then returned.
17  *
18  * As usual, a divisor of 0 is still Undefined Behavior.
19  */
20 static uint16_t round_up_divide(uint32_t a, uint32_t b) {
21  const uint32_t result = ((a - 1) / b) + 1;
22  return (uint16_t)result;
23 }
24 
25 static void spin_while_status_bit(const dif_i2c_t *i2c, uint32_t bit,
26  bool set) {
27  uint32_t reg = 0;
28  do {
29  reg = mmio_region_read32(i2c->base_addr, I2C_STATUS_REG_OFFSET);
30  } while (bitfield_bit32_read(reg, bit) == set);
31 }
32 
33 /**
34  * Reads i2c status bits from registers
35  */
38  if (i2c == NULL || status == NULL) {
39  return kDifBadArg;
40  }
41 
42  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_CTRL_REG_OFFSET);
43  status->enable_host = bitfield_bit32_read(reg, I2C_CTRL_ENABLEHOST_BIT);
44  status->enable_target = bitfield_bit32_read(reg, I2C_CTRL_ENABLETARGET_BIT);
45  status->line_loopback = bitfield_bit32_read(reg, I2C_CTRL_LLPBK_BIT);
46  status->ack_control_en = bitfield_bit32_read(reg, I2C_CTRL_ACK_CTRL_EN_BIT);
47  reg = mmio_region_read32(i2c->base_addr, I2C_STATUS_REG_OFFSET);
48  status->fmt_fifo_full = bitfield_bit32_read(reg, I2C_STATUS_FMTFULL_BIT);
49  status->rx_fifo_full = bitfield_bit32_read(reg, I2C_STATUS_RXFULL_BIT);
50  status->fmt_fifo_empty = bitfield_bit32_read(reg, I2C_STATUS_FMTEMPTY_BIT);
51  status->rx_fifo_empty = bitfield_bit32_read(reg, I2C_STATUS_RXEMPTY_BIT);
52  status->host_idle = bitfield_bit32_read(reg, I2C_STATUS_HOSTIDLE_BIT);
53  status->target_idle = bitfield_bit32_read(reg, I2C_STATUS_TARGETIDLE_BIT);
54  status->tx_fifo_full = bitfield_bit32_read(reg, I2C_STATUS_TXFULL_BIT);
55  status->acq_fifo_full = bitfield_bit32_read(reg, I2C_STATUS_ACQFULL_BIT);
56  status->tx_fifo_empty = bitfield_bit32_read(reg, I2C_STATUS_TXEMPTY_BIT);
57  status->acq_fifo_empty = bitfield_bit32_read(reg, I2C_STATUS_ACQEMPTY_BIT);
58  status->ack_ctrl_stretch =
59  bitfield_bit32_read(reg, I2C_STATUS_ACK_CTRL_STRETCH_BIT);
60 
61  return kDifOk;
62 }
63 
65  const dif_i2c_t *i2c, dif_i2c_controller_halt_events_t *events) {
66  if (i2c == NULL || events == NULL) {
67  return kDifBadArg;
68  }
69  uint32_t reg =
70  mmio_region_read32(i2c->base_addr, I2C_CONTROLLER_EVENTS_REG_OFFSET);
71  events->nack_received =
72  bitfield_bit32_read(reg, I2C_CONTROLLER_EVENTS_NACK_BIT);
74  reg, I2C_CONTROLLER_EVENTS_UNHANDLED_NACK_TIMEOUT_BIT);
75  return kDifOk;
76 }
77 
79  const dif_i2c_t *i2c, dif_i2c_controller_halt_events_t events) {
80  if (i2c == NULL) {
81  return kDifBadArg;
82  }
83  uint32_t reg = 0;
84  reg = bitfield_bit32_write(reg, I2C_CONTROLLER_EVENTS_NACK_BIT,
85  events.nack_received);
86  reg = bitfield_bit32_write(reg,
87  I2C_CONTROLLER_EVENTS_UNHANDLED_NACK_TIMEOUT_BIT,
88  events.unhandled_nack_timeout);
89  mmio_region_write32(i2c->base_addr, I2C_CONTROLLER_EVENTS_REG_OFFSET, reg);
90  return kDifOk;
91 }
92 
93 /**
94  * Computes default timing parameters for a particular I2C speed, given the
95  * clock period, in nanoseconds.
96  *
97  * Returns an unspecified value for an invalid speed.
98  */
99 static dif_i2c_config_t default_timing_for_speed(dif_i2c_speed_t speed,
100  uint32_t clock_period_nanos) {
101  // NOTE: All constants below are lifted from Table 10 of the I2C spec.
102  // All literal values are given in nanoseconds; we don't bother putting
103  // these into constants since they are not used anywhere else.
104  switch (speed) {
106  return (dif_i2c_config_t){
107  .scl_time_high_cycles = round_up_divide(4000, clock_period_nanos),
108  .scl_time_low_cycles = round_up_divide(4700, clock_period_nanos),
109  .start_signal_setup_cycles =
110  round_up_divide(4700, clock_period_nanos),
111  .start_signal_hold_cycles = round_up_divide(4000, clock_period_nanos),
112  .data_signal_setup_cycles = round_up_divide(250, clock_period_nanos),
113  .data_signal_hold_cycles = 1,
114  .stop_signal_setup_cycles = round_up_divide(4000, clock_period_nanos),
115  .stop_signal_hold_cycles = round_up_divide(4700, clock_period_nanos),
116  };
117  case kDifI2cSpeedFast:
118  return (dif_i2c_config_t){
119  .scl_time_high_cycles = round_up_divide(600, clock_period_nanos),
120  .scl_time_low_cycles = round_up_divide(1300, clock_period_nanos),
121  .start_signal_setup_cycles = round_up_divide(600, clock_period_nanos),
122  .start_signal_hold_cycles = round_up_divide(600, clock_period_nanos),
123  .data_signal_setup_cycles = round_up_divide(100, clock_period_nanos),
124  .data_signal_hold_cycles = 1,
125  .stop_signal_setup_cycles = round_up_divide(600, clock_period_nanos),
126  .stop_signal_hold_cycles = round_up_divide(1300, clock_period_nanos),
127  };
129  return (dif_i2c_config_t){
130  .scl_time_high_cycles = round_up_divide(260, clock_period_nanos),
131  .scl_time_low_cycles = round_up_divide(500, clock_period_nanos),
132  .start_signal_setup_cycles = round_up_divide(260, clock_period_nanos),
133  .start_signal_hold_cycles = round_up_divide(260, clock_period_nanos),
134  .data_signal_setup_cycles = round_up_divide(50, clock_period_nanos),
135  .data_signal_hold_cycles = 1,
136  .stop_signal_setup_cycles = round_up_divide(260, clock_period_nanos),
137  .stop_signal_hold_cycles = round_up_divide(500, clock_period_nanos),
138  };
139  default:
140  return (dif_i2c_config_t){0};
141  }
142 }
143 
144 static const uint32_t kNanosPerKBaud = 1000000; // One million.
145 
147  dif_i2c_config_t *config) {
148  if (config == NULL) {
149  return kDifBadArg;
150  }
151  uint32_t lowest_target_device_speed_khz;
152  switch (timing_config.lowest_target_device_speed) {
154  lowest_target_device_speed_khz = 100;
155  break;
156  case kDifI2cSpeedFast:
157  lowest_target_device_speed_khz = 400;
158  break;
160  lowest_target_device_speed_khz = 1000;
161  break;
162  default:
163  return kDifBadArg;
164  }
165 
166  // This code follows the algorithm given in
167  // https://docs.opentitan.org/hw/ip/i2c/doc/index.html#initialization
168 
169  *config = default_timing_for_speed(timing_config.lowest_target_device_speed,
170  timing_config.clock_period_nanos);
171 
172  config->rise_cycles = round_up_divide(timing_config.sda_rise_nanos,
173  timing_config.clock_period_nanos);
174  config->fall_cycles = round_up_divide(timing_config.sda_fall_nanos,
175  timing_config.clock_period_nanos);
176 
177  uint32_t scl_period_nanos = timing_config.scl_period_nanos;
178  uint32_t slowest_scl_period_nanos =
179  kNanosPerKBaud / lowest_target_device_speed_khz;
180  if (scl_period_nanos < slowest_scl_period_nanos) {
181  scl_period_nanos = slowest_scl_period_nanos;
182  }
183  uint16_t scl_period_cycles =
184  round_up_divide(scl_period_nanos, timing_config.clock_period_nanos);
185 
186  // Lengthen the SCL high period to accommodate the desired SCL period.
187  int32_t lengthened_high_cycles = scl_period_cycles -
188  config->scl_time_low_cycles -
189  config->rise_cycles - config->fall_cycles;
190  if (lengthened_high_cycles > (int32_t)config->scl_time_high_cycles) {
191  if (lengthened_high_cycles < 0 || lengthened_high_cycles > UINT16_MAX) {
192  return kDifOutOfRange;
193  }
194  config->scl_time_high_cycles = (uint16_t)lengthened_high_cycles;
195  }
196 
197  return kDifOk;
198 }
199 
201  if (i2c == NULL) {
202  return kDifBadArg;
203  }
204 
205  uint32_t timing0 = 0;
206  timing0 = bitfield_field32_write(timing0, I2C_TIMING0_THIGH_FIELD,
207  config.scl_time_high_cycles);
208  timing0 = bitfield_field32_write(timing0, I2C_TIMING0_TLOW_FIELD,
209  config.scl_time_low_cycles);
210  mmio_region_write32(i2c->base_addr, I2C_TIMING0_REG_OFFSET, timing0);
211 
212  uint32_t timing1 = 0;
213  timing1 = bitfield_field32_write(timing1, I2C_TIMING1_T_R_FIELD,
214  config.rise_cycles);
215  timing1 = bitfield_field32_write(timing1, I2C_TIMING1_T_F_FIELD,
216  config.fall_cycles);
217  mmio_region_write32(i2c->base_addr, I2C_TIMING1_REG_OFFSET, timing1);
218 
219  uint32_t timing2 = 0;
220  timing2 = bitfield_field32_write(timing2, I2C_TIMING2_TSU_STA_FIELD,
221  config.start_signal_setup_cycles);
222  timing2 = bitfield_field32_write(timing2, I2C_TIMING2_THD_STA_FIELD,
223  config.start_signal_hold_cycles);
224  mmio_region_write32(i2c->base_addr, I2C_TIMING2_REG_OFFSET, timing2);
225 
226  uint32_t timing3 = 0;
227  timing3 = bitfield_field32_write(timing3, I2C_TIMING3_TSU_DAT_FIELD,
228  config.data_signal_setup_cycles);
229  timing3 = bitfield_field32_write(timing3, I2C_TIMING3_THD_DAT_FIELD,
230  config.data_signal_hold_cycles);
231  mmio_region_write32(i2c->base_addr, I2C_TIMING3_REG_OFFSET, timing3);
232 
233  uint32_t timing4 = 0;
234  timing4 = bitfield_field32_write(timing4, I2C_TIMING4_TSU_STO_FIELD,
235  config.stop_signal_setup_cycles);
236  timing4 = bitfield_field32_write(timing4, I2C_TIMING4_T_BUF_FIELD,
237  config.stop_signal_hold_cycles);
238  mmio_region_write32(i2c->base_addr, I2C_TIMING4_REG_OFFSET, timing4);
239 
240  return kDifOk;
241 }
242 
244  if (i2c == NULL) {
245  return kDifBadArg;
246  }
247 
248  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
249  reg = bitfield_bit32_write(reg, I2C_FIFO_CTRL_RXRST_BIT, true);
250  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, reg);
251 
252  return kDifOk;
253 }
254 
256  if (i2c == NULL) {
257  return kDifBadArg;
258  }
259 
260  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
261  reg = bitfield_bit32_write(reg, I2C_FIFO_CTRL_FMTRST_BIT, true);
262  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, reg);
263 
264  return kDifOk;
265 }
266 
268  if (i2c == NULL) {
269  return kDifBadArg;
270  }
271 
272  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
273  reg = bitfield_bit32_write(reg, I2C_FIFO_CTRL_TXRST_BIT, true);
274  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, reg);
275 
276  return kDifOk;
277 }
278 
280  if (i2c == NULL) {
281  return kDifBadArg;
282  }
283 
284  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
285  reg = bitfield_bit32_write(reg, I2C_FIFO_CTRL_ACQRST_BIT, true);
286  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, reg);
287 
288  return kDifOk;
289 }
290 
292  dif_i2c_level_t rx_level,
293  dif_i2c_level_t fmt_level) {
294  // Check that the FIFO levels are sensible; setting RX level equal to the
295  // depth deactivates its interrupt, but setting FMT level to that would result
296  // in continual interrupt assertion.
297  if (i2c == NULL || rx_level > I2C_PARAM_FIFO_DEPTH ||
298  fmt_level >= I2C_PARAM_FIFO_DEPTH) {
299  return kDifBadArg;
300  }
301 
302  uint32_t ctrl_value =
303  mmio_region_read32(i2c->base_addr, I2C_HOST_FIFO_CONFIG_REG_OFFSET);
304  ctrl_value = bitfield_field32_write(
305  ctrl_value, I2C_HOST_FIFO_CONFIG_RX_THRESH_FIELD, rx_level);
306  ctrl_value = bitfield_field32_write(
307  ctrl_value, I2C_HOST_FIFO_CONFIG_FMT_THRESH_FIELD, fmt_level);
308  mmio_region_write32(i2c->base_addr, I2C_HOST_FIFO_CONFIG_REG_OFFSET,
309  ctrl_value);
310 
311  return kDifOk;
312 }
313 
315  dif_i2c_level_t tx_level,
316  dif_i2c_level_t acq_level) {
317  // Check that the FIFO levels are sensible; setting ACQ level equal to the
318  // depth deactivates its interrupt, but setting TX level to that would result
319  // in continual interrupt assertion.
320  if (i2c == NULL || acq_level > I2C_PARAM_ACQ_FIFO_DEPTH ||
321  tx_level >= I2C_PARAM_FIFO_DEPTH) {
322  return kDifBadArg;
323  }
324 
325  uint32_t ctrl_value =
326  mmio_region_read32(i2c->base_addr, I2C_TARGET_FIFO_CONFIG_REG_OFFSET);
327  ctrl_value = bitfield_field32_write(
328  ctrl_value, I2C_TARGET_FIFO_CONFIG_TX_THRESH_FIELD, tx_level);
329  ctrl_value = bitfield_field32_write(
330  ctrl_value, I2C_TARGET_FIFO_CONFIG_ACQ_THRESH_FIELD, acq_level);
331  mmio_region_write32(i2c->base_addr, I2C_TARGET_FIFO_CONFIG_REG_OFFSET,
332  ctrl_value);
333 
334  return kDifOk;
335 }
336 
338  dif_toggle_t state) {
339  if (i2c == NULL) {
340  return kDifBadArg;
341  }
342 
343  if (!dif_is_valid_toggle(state)) {
344  return kDifBadArg;
345  }
346  bool flag = dif_toggle_to_bool(state);
347 
348  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_CTRL_REG_OFFSET);
349  reg = bitfield_bit32_write(reg, I2C_CTRL_ENABLEHOST_BIT, flag);
350  mmio_region_write32(i2c->base_addr, I2C_CTRL_REG_OFFSET, reg);
351 
352  return kDifOk;
353 }
354 
356  dif_toggle_t state) {
357  if (i2c == NULL) {
358  return kDifBadArg;
359  }
360 
361  if (!dif_is_valid_toggle(state)) {
362  return kDifBadArg;
363  }
364  bool flag = dif_toggle_to_bool(state);
365 
366  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_CTRL_REG_OFFSET);
367  reg = bitfield_bit32_write(reg, I2C_CTRL_ENABLETARGET_BIT, flag);
368  mmio_region_write32(i2c->base_addr, I2C_CTRL_REG_OFFSET, reg);
369 
370  return kDifOk;
371 }
372 
374  dif_toggle_t state) {
375  if (i2c == NULL) {
376  return kDifBadArg;
377  }
378 
379  if (!dif_is_valid_toggle(state)) {
380  return kDifBadArg;
381  }
382  bool flag = dif_toggle_to_bool(state);
383 
384  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_CTRL_REG_OFFSET);
385  reg = bitfield_bit32_write(reg, I2C_CTRL_LLPBK_BIT, flag);
386  mmio_region_write32(i2c->base_addr, I2C_CTRL_REG_OFFSET, reg);
387 
388  return kDifOk;
389 }
390 
392  dif_toggle_t state) {
393  if (i2c == NULL) {
394  return kDifBadArg;
395  }
396 
397  if (!dif_is_valid_toggle(state)) {
398  return kDifBadArg;
399  }
400  bool flag = dif_toggle_to_bool(state);
401 
402  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_CTRL_REG_OFFSET);
403  reg = bitfield_bit32_write(reg, I2C_CTRL_NACK_ADDR_AFTER_TIMEOUT_BIT, flag);
404  mmio_region_write32(i2c->base_addr, I2C_CTRL_REG_OFFSET, reg);
405 
406  return kDifOk;
407 }
408 
410  dif_toggle_t state) {
411  if (i2c == NULL) {
412  return kDifBadArg;
413  }
414 
415  if (!dif_is_valid_toggle(state)) {
416  return kDifBadArg;
417  }
418  bool flag = dif_toggle_to_bool(state);
419 
420  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_CTRL_REG_OFFSET);
421  reg = bitfield_bit32_write(reg, I2C_CTRL_ACK_CTRL_EN_BIT, flag);
422  mmio_region_write32(i2c->base_addr, I2C_CTRL_REG_OFFSET, reg);
423 
424  return kDifOk;
425 }
426 
428  dif_toggle_t state) {
429  if (i2c == NULL) {
430  return kDifBadArg;
431  }
432 
433  if (!dif_is_valid_toggle(state)) {
434  return kDifBadArg;
435  }
436  bool flag = dif_toggle_to_bool(state);
437 
438  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_OVRD_REG_OFFSET);
439  reg = bitfield_bit32_write(reg, I2C_OVRD_TXOVRDEN_BIT, flag);
440  mmio_region_write32(i2c->base_addr, I2C_OVRD_REG_OFFSET, reg);
441 
442  return kDifOk;
443 }
444 
446  bool sda) {
447  if (i2c == NULL) {
448  return kDifBadArg;
449  }
450 
451  uint32_t override_val =
452  mmio_region_read32(i2c->base_addr, I2C_OVRD_REG_OFFSET);
453  override_val = bitfield_bit32_write(override_val, I2C_OVRD_SCLVAL_BIT, scl);
454  override_val = bitfield_bit32_write(override_val, I2C_OVRD_SDAVAL_BIT, sda);
455  mmio_region_write32(i2c->base_addr, I2C_OVRD_REG_OFFSET, override_val);
456 
457  return kDifOk;
458 }
459 
461  uint16_t *scl_samples,
462  uint16_t *sda_samples) {
463  if (i2c == NULL) {
464  return kDifBadArg;
465  }
466 
467  uint32_t samples = mmio_region_read32(i2c->base_addr, I2C_VAL_REG_OFFSET);
468  if (scl_samples != NULL) {
469  *scl_samples =
470  (uint16_t)bitfield_field32_read(samples, I2C_VAL_SCL_RX_FIELD);
471  }
472 
473  if (sda_samples != NULL) {
474  *sda_samples =
475  (uint16_t)bitfield_field32_read(samples, I2C_VAL_SDA_RX_FIELD);
476  }
477 
478  return kDifOk;
479 }
480 
482  dif_i2c_level_t *fmt_fifo_level,
483  dif_i2c_level_t *rx_fifo_level,
484  dif_i2c_level_t *tx_fifo_level,
485  dif_i2c_level_t *acq_fifo_level) {
486  if (i2c == NULL) {
487  return kDifBadArg;
488  }
489 
490  // Host-side FIFO levels
491  uint32_t values =
492  mmio_region_read32(i2c->base_addr, I2C_HOST_FIFO_STATUS_REG_OFFSET);
493  if (fmt_fifo_level != NULL) {
494  *fmt_fifo_level = (dif_i2c_level_t)bitfield_field32_read(
495  values, I2C_HOST_FIFO_STATUS_FMTLVL_FIELD);
496  }
497  if (rx_fifo_level != NULL) {
498  *rx_fifo_level = (dif_i2c_level_t)bitfield_field32_read(
499  values, I2C_HOST_FIFO_STATUS_RXLVL_FIELD);
500  }
501 
502  // Target-side FIFO levels
503  values =
504  mmio_region_read32(i2c->base_addr, I2C_TARGET_FIFO_STATUS_REG_OFFSET);
505  if (tx_fifo_level != NULL) {
506  *tx_fifo_level = (dif_i2c_level_t)bitfield_field32_read(
507  values, I2C_TARGET_FIFO_STATUS_TXLVL_FIELD);
508  }
509  if (acq_fifo_level != NULL) {
510  *acq_fifo_level = (dif_i2c_level_t)bitfield_field32_read(
511  values, I2C_TARGET_FIFO_STATUS_ACQLVL_FIELD);
512  }
513 
514  return kDifOk;
515 }
516 
517 dif_result_t dif_i2c_get_auto_ack_count(const dif_i2c_t *i2c, uint16_t *count) {
518  if (i2c == NULL || count == NULL) {
519  return kDifBadArg;
520  }
521 
522  uint32_t reg =
523  mmio_region_read32(i2c->base_addr, I2C_TARGET_ACK_CTRL_REG_OFFSET);
524  *count =
525  (uint16_t)bitfield_field32_read(reg, I2C_TARGET_ACK_CTRL_NBYTES_FIELD);
526 
527  return kDifOk;
528 }
529 
530 dif_result_t dif_i2c_set_auto_ack_count(const dif_i2c_t *i2c, uint16_t count) {
531  if (i2c == NULL) {
532  return kDifBadArg;
533  }
534  if (count > I2C_TARGET_ACK_CTRL_NBYTES_MASK) {
535  return kDifBadArg;
536  }
537 
538  uint32_t reg =
539  bitfield_field32_write(0, I2C_TARGET_ACK_CTRL_NBYTES_FIELD, count);
540  mmio_region_write32(i2c->base_addr, I2C_TARGET_ACK_CTRL_REG_OFFSET, reg);
541 
542  return kDifOk;
543 }
544 
546  if (i2c == NULL) {
547  return kDifBadArg;
548  }
549 
550  uint32_t reg = bitfield_bit32_write(0, I2C_TARGET_ACK_CTRL_NACK_BIT, true);
551  mmio_region_write32(i2c->base_addr, I2C_TARGET_ACK_CTRL_REG_OFFSET, reg);
552 
553  return kDifOk;
554 }
555 
557  if (i2c == NULL || data == NULL) {
558  return kDifBadArg;
559  }
560 
561  *data = 0xffu &
562  mmio_region_read32(i2c->base_addr, I2C_ACQ_FIFO_NEXT_DATA_REG_OFFSET);
563 
564  return kDifOk;
565 }
566 
567 dif_result_t dif_i2c_read_byte(const dif_i2c_t *i2c, uint8_t *byte) {
568  if (i2c == NULL) {
569  return kDifBadArg;
570  }
571 
572  uint32_t values = mmio_region_read32(i2c->base_addr, I2C_RDATA_REG_OFFSET);
573  if (byte != NULL) {
574  *byte = (uint8_t)bitfield_field32_read(values, I2C_RDATA_RDATA_FIELD);
575  }
576 
577  return kDifOk;
578 }
579 
580 dif_result_t dif_i2c_read_bytes(const dif_i2c_t *i2c, size_t size,
581  uint8_t *buffer) {
582  if (i2c == NULL || buffer == NULL) {
583  return kDifBadArg;
584  }
585 
586  while (size--) {
587  spin_while_status_bit(i2c, I2C_STATUS_RXEMPTY_BIT, /*set*/ true);
588  uint32_t values = mmio_region_read32(i2c->base_addr, I2C_RDATA_REG_OFFSET);
589  *(buffer++) = (uint8_t)bitfield_field32_read(values, I2C_RDATA_RDATA_FIELD);
590  }
591 
592  return kDifOk;
593 }
594 
595 static inline dif_result_t parse_flags(dif_i2c_fmt_flags_t flags,
596  uint32_t *fmt_byte) {
597  // Validate that "write only" flags and "read only" flags are not set
598  // simultaneously.
599  bool has_write_flags = flags.start || flags.suppress_nak_irq;
600  bool has_read_flags = flags.read || flags.read_cont;
601  if (has_write_flags && has_read_flags) {
602  return kDifBadArg;
603  }
604  // Also, read_cont requires read.
605  if (flags.read_cont && !flags.read) {
606  return kDifBadArg;
607  }
608 
609  *fmt_byte = bitfield_bit32_write(*fmt_byte, 8, flags.start);
610  *fmt_byte = bitfield_bit32_write(*fmt_byte, I2C_FDATA_STOP_BIT, flags.stop);
611  *fmt_byte = bitfield_bit32_write(*fmt_byte, I2C_FDATA_READB_BIT, flags.read);
612  *fmt_byte =
613  bitfield_bit32_write(*fmt_byte, I2C_FDATA_RCONT_BIT, flags.read_cont);
614  *fmt_byte = bitfield_bit32_write(*fmt_byte, I2C_FDATA_NAKOK_BIT,
615  flags.suppress_nak_irq);
616 
617  return kDifOk;
618 }
620  const uint8_t *bytes,
621  dif_i2c_fmt_flags_t flags) {
622  if (i2c == NULL || bytes == NULL || size == 0) {
623  return kDifBadArg;
624  }
625  uint32_t fmt_byte = 0;
626  DIF_RETURN_IF_ERROR(parse_flags(flags, &fmt_byte));
627 
628  for (size_t i = 0; i < size; ++i) {
629  uint32_t reg =
630  bitfield_field32_write(fmt_byte, I2C_FDATA_FBYTE_FIELD, bytes[i]);
631  mmio_region_write32(i2c->base_addr, I2C_FDATA_REG_OFFSET, reg);
632  spin_while_status_bit(i2c, I2C_STATUS_FMTFULL_BIT, /*set*/ true);
633  }
634 
635  return kDifOk;
636 }
637 
639  dif_i2c_fmt_flags_t flags) {
640  if (i2c == NULL) {
641  return kDifBadArg;
642  }
643 
644  uint32_t fmt_byte = 0;
645  DIF_RETURN_IF_ERROR(parse_flags(flags, &fmt_byte));
646  fmt_byte = bitfield_field32_write(fmt_byte, I2C_FDATA_FBYTE_FIELD, byte);
647  mmio_region_write32(i2c->base_addr, I2C_FDATA_REG_OFFSET, fmt_byte);
648 
649  return kDifOk;
650 }
651 
652 dif_result_t dif_i2c_write_byte(const dif_i2c_t *i2c, uint8_t byte,
653  dif_i2c_fmt_t code, bool suppress_nak_irq) {
654  if (i2c == NULL) {
655  return kDifBadArg;
656  }
657 
658  // Validate that `suppress_nak_irq` has not been mixed with an Rx code.
659  if (suppress_nak_irq) {
660  switch (code) {
661  case kDifI2cFmtRx:
663  case kDifI2cFmtRxStop:
664  return kDifBadArg;
665  default:
666  break;
667  }
668  }
669 
670  // Convert the format code into flags.
671  dif_i2c_fmt_flags_t flags = {.suppress_nak_irq = suppress_nak_irq};
672  switch (code) {
673  case kDifI2cFmtStart:
674  flags.start = true;
675  break;
676  case kDifI2cFmtTx:
677  break;
678  case kDifI2cFmtTxStop:
679  flags.stop = true;
680  break;
681  case kDifI2cFmtRx:
682  flags.read = true;
683  break;
685  flags.read = true;
686  flags.read_cont = true;
687  break;
688  case kDifI2cFmtRxStop:
689  flags.read = true;
690  flags.stop = true;
691  break;
692  default:
693  return kDifBadArg;
694  }
695 
696  return dif_i2c_write_byte_raw(i2c, byte, flags);
697 }
698 
699 dif_result_t dif_i2c_transmit_byte(const dif_i2c_t *i2c, uint8_t byte) {
700  if (i2c == NULL) {
701  return kDifBadArg;
702  }
703 
704  uint32_t tx_byte = 0;
705  tx_byte = bitfield_field32_write(tx_byte, I2C_TXDATA_TXDATA_FIELD, byte);
706  mmio_region_write32(i2c->base_addr, I2C_TXDATA_REG_OFFSET, tx_byte);
707 
708  return kDifOk;
709 }
710 
711 dif_result_t dif_i2c_acquire_byte(const dif_i2c_t *i2c, uint8_t *byte,
712  dif_i2c_signal_t *signal) {
713  if (i2c == NULL) {
714  return kDifBadArg;
715  }
716 
717  uint32_t acq_byte =
718  mmio_region_read32(i2c->base_addr, I2C_ACQDATA_REG_OFFSET);
719  if (byte != NULL) {
720  *byte = (uint8_t)bitfield_field32_read(acq_byte, I2C_ACQDATA_ABYTE_FIELD);
721  }
722  if (signal != NULL) {
723  *signal = bitfield_field32_read(acq_byte, I2C_ACQDATA_SIGNAL_FIELD);
724  }
725  return kDifOk;
726 }
727 
729  dif_toggle_t enable,
730  uint32_t cycles) {
731  if (i2c == NULL) {
732  return kDifBadArg;
733  }
734 
735  if (!dif_is_valid_toggle(enable)) {
736  return kDifBadArg;
737  }
738  bool flag = dif_toggle_to_bool(enable);
739 
740  uint32_t config = 0;
741  config = bitfield_bit32_write(config, I2C_TIMEOUT_CTRL_EN_BIT, flag);
742  config = bitfield_field32_write(config, I2C_TIMEOUT_CTRL_VAL_FIELD, cycles);
743  mmio_region_write32(i2c->base_addr, I2C_TIMEOUT_CTRL_REG_OFFSET, config);
744  return kDifOk;
745 }
746 
748  const dif_i2c_id_t *id0,
749  const dif_i2c_id_t *id1) {
750  if (i2c == NULL) {
751  return kDifBadArg;
752  }
753 
754  uint32_t config = 0;
755  if (id0 != NULL) {
756  config = bitfield_field32_write(config, I2C_TARGET_ID_ADDRESS0_FIELD,
757  id0->address);
758  config =
759  bitfield_field32_write(config, I2C_TARGET_ID_MASK0_FIELD, id0->mask);
760  } else {
761  // Don't listen by default
762  config = bitfield_field32_write(config, I2C_TARGET_ID_ADDRESS0_FIELD, 0x7f);
763  }
764 
765  if (id1 != NULL) {
766  config = bitfield_field32_write(config, I2C_TARGET_ID_ADDRESS1_FIELD,
767  id1->address);
768  config =
769  bitfield_field32_write(config, I2C_TARGET_ID_MASK1_FIELD, id1->mask);
770  } else {
771  // Don't listen by default
772  config = bitfield_field32_write(config, I2C_TARGET_ID_ADDRESS1_FIELD, 0x7f);
773  }
774 
775  mmio_region_write32(i2c->base_addr, I2C_TARGET_ID_REG_OFFSET, config);
776  return kDifOk;
777 }
778 
779 dif_result_t dif_i2c_set_host_timeout(const dif_i2c_t *i2c, uint32_t cycles) {
780  if (i2c == NULL) {
781  return kDifBadArg;
782  }
783 
784  mmio_region_write32(i2c->base_addr, I2C_HOST_TIMEOUT_CTRL_REG_OFFSET, cycles);
785  return kDifOk;
786 }