Software APIs
dif_i2c.c
1 // Copyright lowRISC contributors.
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  if (a == 0) {
22  return 0;
23  }
24 
25  return ((a - 1) / b) + 1;
26 }
27 
28 /**
29  * Computes default timing parameters for a particular I2C speed, given the
30  * clock period, in nanoseconds.
31  *
32  * Returns an unspecified value for an invalid speed.
33  */
34 static dif_i2c_config_t default_timing_for_speed(dif_i2c_speed_t speed,
35  uint32_t clock_period_nanos) {
36  // NOTE: All constants below are lifted from Table 10 of the I2C spec.
37  // All literal values are given in nanoseconds; we don't bother putting
38  // these into constants since they are not used anywhere else.
39  switch (speed) {
41  return (dif_i2c_config_t){
42  .scl_time_high_cycles = round_up_divide(4000, clock_period_nanos),
43  .scl_time_low_cycles = round_up_divide(4700, clock_period_nanos),
44  .start_signal_setup_cycles =
45  round_up_divide(4700, clock_period_nanos),
46  .start_signal_hold_cycles = round_up_divide(4000, clock_period_nanos),
47  .data_signal_setup_cycles = round_up_divide(250, clock_period_nanos),
48  .data_signal_hold_cycles = 0,
49  .stop_signal_setup_cycles = round_up_divide(4000, clock_period_nanos),
50  .stop_signal_hold_cycles = round_up_divide(4700, clock_period_nanos),
51  };
52  case kDifI2cSpeedFast:
53  return (dif_i2c_config_t){
54  .scl_time_high_cycles = round_up_divide(600, clock_period_nanos),
55  .scl_time_low_cycles = round_up_divide(1300, clock_period_nanos),
56  .start_signal_setup_cycles = round_up_divide(600, clock_period_nanos),
57  .start_signal_hold_cycles = round_up_divide(600, clock_period_nanos),
58  .data_signal_setup_cycles = round_up_divide(100, clock_period_nanos),
59  .data_signal_hold_cycles = 0,
60  .stop_signal_setup_cycles = round_up_divide(600, clock_period_nanos),
61  .stop_signal_hold_cycles = round_up_divide(1300, clock_period_nanos),
62  };
64  return (dif_i2c_config_t){
65  .scl_time_high_cycles = round_up_divide(260, clock_period_nanos),
66  .scl_time_low_cycles = round_up_divide(500, clock_period_nanos),
67  .start_signal_setup_cycles = round_up_divide(260, clock_period_nanos),
68  .start_signal_hold_cycles = round_up_divide(260, clock_period_nanos),
69  .data_signal_setup_cycles = round_up_divide(50, clock_period_nanos),
70  .data_signal_hold_cycles = 0,
71  .stop_signal_setup_cycles = round_up_divide(260, clock_period_nanos),
72  .stop_signal_hold_cycles = round_up_divide(500, clock_period_nanos),
73  };
74  default:
75  return (dif_i2c_config_t){0};
76  }
77 }
78 
79 static const uint32_t kNanosPerKBaud = 1000000; // One million.
80 
82  dif_i2c_config_t *config) {
83  if (config == NULL) {
84  return kDifBadArg;
85  }
86  uint32_t lowest_target_device_speed_khz;
87  switch (timing_config.lowest_target_device_speed) {
89  lowest_target_device_speed_khz = 100;
90  break;
91  case kDifI2cSpeedFast:
92  lowest_target_device_speed_khz = 400;
93  break;
95  lowest_target_device_speed_khz = 1000;
96  break;
97  default:
98  return kDifBadArg;
99  }
100 
101  // This code follows the algorithm given in
102  // https://docs.opentitan.org/hw/ip/i2c/doc/index.html#initialization
103 
104  *config = default_timing_for_speed(timing_config.lowest_target_device_speed,
105  timing_config.clock_period_nanos);
106 
107  config->rise_cycles = round_up_divide(timing_config.sda_rise_nanos,
108  timing_config.clock_period_nanos);
109  config->fall_cycles = round_up_divide(timing_config.sda_fall_nanos,
110  timing_config.clock_period_nanos);
111 
112  uint32_t scl_period_nanos = timing_config.scl_period_nanos;
113  uint32_t slowest_scl_period_nanos =
114  kNanosPerKBaud / lowest_target_device_speed_khz;
115  if (scl_period_nanos < slowest_scl_period_nanos) {
116  scl_period_nanos = slowest_scl_period_nanos;
117  }
118  uint16_t scl_period_cycles =
119  round_up_divide(scl_period_nanos, timing_config.clock_period_nanos);
120 
121  // Lengthen the SCL high period to accommodate the desired SCL period.
122  uint16_t lengthened_high_cycles = scl_period_cycles -
123  config->scl_time_low_cycles -
124  config->rise_cycles - config->fall_cycles;
125  if (lengthened_high_cycles > config->scl_time_high_cycles) {
126  config->scl_time_high_cycles = lengthened_high_cycles;
127  }
128 
129  return kDifOk;
130 }
131 
133  if (i2c == NULL) {
134  return kDifBadArg;
135  }
136 
137  uint32_t timing0 = 0;
138  timing0 = bitfield_field32_write(timing0, I2C_TIMING0_THIGH_FIELD,
139  config.scl_time_high_cycles);
140  timing0 = bitfield_field32_write(timing0, I2C_TIMING0_TLOW_FIELD,
141  config.scl_time_low_cycles);
142  mmio_region_write32(i2c->base_addr, I2C_TIMING0_REG_OFFSET, timing0);
143 
144  uint32_t timing1 = 0;
145  timing1 = bitfield_field32_write(timing1, I2C_TIMING1_T_R_FIELD,
146  config.rise_cycles);
147  timing1 = bitfield_field32_write(timing1, I2C_TIMING1_T_F_FIELD,
148  config.fall_cycles);
149  mmio_region_write32(i2c->base_addr, I2C_TIMING1_REG_OFFSET, timing1);
150 
151  uint32_t timing2 = 0;
152  timing2 = bitfield_field32_write(timing2, I2C_TIMING2_TSU_STA_FIELD,
153  config.start_signal_setup_cycles);
154  timing2 = bitfield_field32_write(timing2, I2C_TIMING2_THD_STA_FIELD,
155  config.start_signal_hold_cycles);
156  mmio_region_write32(i2c->base_addr, I2C_TIMING2_REG_OFFSET, timing2);
157 
158  uint32_t timing3 = 0;
159  timing3 = bitfield_field32_write(timing3, I2C_TIMING3_TSU_DAT_FIELD,
160  config.data_signal_setup_cycles);
161  timing3 = bitfield_field32_write(timing3, I2C_TIMING3_THD_DAT_FIELD,
162  config.data_signal_hold_cycles);
163  mmio_region_write32(i2c->base_addr, I2C_TIMING3_REG_OFFSET, timing3);
164 
165  uint32_t timing4 = 0;
166  timing4 = bitfield_field32_write(timing4, I2C_TIMING4_TSU_STO_FIELD,
167  config.stop_signal_setup_cycles);
168  timing4 = bitfield_field32_write(timing4, I2C_TIMING4_T_BUF_FIELD,
169  config.stop_signal_hold_cycles);
170  mmio_region_write32(i2c->base_addr, I2C_TIMING4_REG_OFFSET, timing4);
171 
172  return kDifOk;
173 }
174 
176  if (i2c == NULL) {
177  return kDifBadArg;
178  }
179 
180  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
181  reg = bitfield_bit32_write(reg, I2C_FIFO_CTRL_RXRST_BIT, true);
182  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, reg);
183 
184  return kDifOk;
185 }
186 
188  if (i2c == NULL) {
189  return kDifBadArg;
190  }
191 
192  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
193  reg = bitfield_bit32_write(reg, I2C_FIFO_CTRL_FMTRST_BIT, true);
194  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, reg);
195 
196  return kDifOk;
197 }
198 
200  dif_i2c_level_t rx_level,
201  dif_i2c_level_t fmt_level) {
202  if (i2c == NULL) {
203  return kDifBadArg;
204  }
205 
206  ptrdiff_t rx_level_value;
207  switch (rx_level) {
208  case kDifI2cLevel1Byte:
209  rx_level_value = I2C_FIFO_CTRL_RXILVL_VALUE_RXLVL1;
210  break;
211  case kDifI2cLevel4Byte:
212  rx_level_value = I2C_FIFO_CTRL_RXILVL_VALUE_RXLVL4;
213  break;
214  case kDifI2cLevel8Byte:
215  rx_level_value = I2C_FIFO_CTRL_RXILVL_VALUE_RXLVL8;
216  break;
217  case kDifI2cLevel16Byte:
218  rx_level_value = I2C_FIFO_CTRL_RXILVL_VALUE_RXLVL16;
219  break;
220  case kDifI2cLevel30Byte:
221  rx_level_value = I2C_FIFO_CTRL_RXILVL_VALUE_RXLVL30;
222  break;
223  default:
224  return kDifBadArg;
225  }
226 
227  ptrdiff_t fmt_level_value;
228  switch (fmt_level) {
229  case kDifI2cLevel1Byte:
230  fmt_level_value = I2C_FIFO_CTRL_FMTILVL_VALUE_FMTLVL1;
231  break;
232  case kDifI2cLevel4Byte:
233  fmt_level_value = I2C_FIFO_CTRL_FMTILVL_VALUE_FMTLVL4;
234  break;
235  case kDifI2cLevel8Byte:
236  fmt_level_value = I2C_FIFO_CTRL_FMTILVL_VALUE_FMTLVL8;
237  break;
238  case kDifI2cLevel16Byte:
239  fmt_level_value = I2C_FIFO_CTRL_FMTILVL_VALUE_FMTLVL16;
240  break;
241  default:
242  return kDifBadArg;
243  }
244 
245  uint32_t ctrl_value =
246  mmio_region_read32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET);
247  ctrl_value = bitfield_field32_write(ctrl_value, I2C_FIFO_CTRL_RXILVL_FIELD,
248  rx_level_value);
249  ctrl_value = bitfield_field32_write(ctrl_value, I2C_FIFO_CTRL_FMTILVL_FIELD,
250  fmt_level_value);
251  mmio_region_write32(i2c->base_addr, I2C_FIFO_CTRL_REG_OFFSET, ctrl_value);
252 
253  return kDifOk;
254 }
255 
257  dif_toggle_t state) {
258  if (i2c == NULL) {
259  return kDifBadArg;
260  }
261 
262  bool flag;
263  switch (state) {
264  case kDifToggleEnabled:
265  flag = true;
266  break;
267  case kDifToggleDisabled:
268  flag = false;
269  break;
270  default:
271  return kDifBadArg;
272  }
273 
274  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_CTRL_REG_OFFSET);
275  reg = bitfield_bit32_write(reg, I2C_CTRL_ENABLEHOST_BIT, flag);
276  mmio_region_write32(i2c->base_addr, I2C_CTRL_REG_OFFSET, reg);
277 
278  return kDifOk;
279 }
280 
282  dif_toggle_t state) {
283  if (i2c == NULL) {
284  return kDifBadArg;
285  }
286 
287  bool flag;
288  switch (state) {
289  case kDifToggleEnabled:
290  flag = true;
291  break;
292  case kDifToggleDisabled:
293  flag = false;
294  break;
295  default:
296  return kDifBadArg;
297  }
298 
299  uint32_t reg = mmio_region_read32(i2c->base_addr, I2C_OVRD_REG_OFFSET);
300  reg = bitfield_bit32_write(reg, I2C_OVRD_TXOVRDEN_BIT, flag);
301  mmio_region_write32(i2c->base_addr, I2C_OVRD_REG_OFFSET, reg);
302 
303  return kDifOk;
304 }
305 
307  bool sda) {
308  if (i2c == NULL) {
309  return kDifBadArg;
310  }
311 
312  uint32_t override_val =
313  mmio_region_read32(i2c->base_addr, I2C_OVRD_REG_OFFSET);
314  override_val = bitfield_bit32_write(override_val, I2C_OVRD_SCLVAL_BIT, scl);
315  override_val = bitfield_bit32_write(override_val, I2C_OVRD_SDAVAL_BIT, sda);
316  mmio_region_write32(i2c->base_addr, I2C_OVRD_REG_OFFSET, override_val);
317 
318  return kDifOk;
319 }
320 
322  uint16_t *scl_samples,
323  uint16_t *sda_samples) {
324  if (i2c == NULL) {
325  return kDifBadArg;
326  }
327 
328  uint32_t samples = mmio_region_read32(i2c->base_addr, I2C_VAL_REG_OFFSET);
329  if (scl_samples != NULL) {
330  *scl_samples = bitfield_field32_read(samples, I2C_VAL_SCL_RX_FIELD);
331  }
332 
333  if (sda_samples != NULL) {
334  *sda_samples = bitfield_field32_read(samples, I2C_VAL_SDA_RX_FIELD);
335  }
336 
337  return kDifOk;
338 }
339 
341  uint8_t *fmt_fifo_level,
342  uint8_t *rx_fifo_level) {
343  if (i2c == NULL) {
344  return kDifBadArg;
345  }
346 
347  uint32_t values =
348  mmio_region_read32(i2c->base_addr, I2C_FIFO_STATUS_REG_OFFSET);
349  if (fmt_fifo_level != NULL) {
350  *fmt_fifo_level =
351  bitfield_field32_read(values, I2C_FIFO_STATUS_FMTLVL_FIELD);
352  }
353  if (rx_fifo_level != NULL) {
354  *rx_fifo_level = bitfield_field32_read(values, I2C_FIFO_STATUS_RXLVL_FIELD);
355  }
356 
357  return kDifOk;
358 }
359 
360 dif_result_t dif_i2c_read_byte(const dif_i2c_t *i2c, uint8_t *byte) {
361  if (i2c == NULL) {
362  return kDifBadArg;
363  }
364 
365  uint32_t values = mmio_region_read32(i2c->base_addr, I2C_RDATA_REG_OFFSET);
366  if (byte != NULL) {
367  *byte = bitfield_field32_read(values, I2C_RDATA_RDATA_FIELD);
368  }
369 
370  return kDifOk;
371 }
372 
374  dif_i2c_fmt_flags_t flags) {
375  if (i2c == NULL) {
376  return kDifBadArg;
377  }
378  // Validate that "write only" flags and "read only" flags are not set
379  // simultaneously.
380  bool has_write_flags = flags.start || flags.stop || flags.suppress_nak_irq;
381  bool has_read_flags = flags.read || flags.read_cont;
382  if (has_write_flags && has_read_flags) {
383  return kDifBadArg;
384  }
385  // Also, read_cont requires read.
386  if (flags.read_cont && !flags.read) {
387  return kDifBadArg;
388  }
389 
390  uint32_t fmt_byte = 0;
391  fmt_byte = bitfield_field32_write(fmt_byte, I2C_FDATA_FBYTE_FIELD, byte);
392  fmt_byte = bitfield_bit32_write(fmt_byte, I2C_FDATA_START_BIT, flags.start);
393  fmt_byte = bitfield_bit32_write(fmt_byte, I2C_FDATA_STOP_BIT, flags.stop);
394  fmt_byte = bitfield_bit32_write(fmt_byte, I2C_FDATA_READ_BIT, flags.read);
395  fmt_byte =
396  bitfield_bit32_write(fmt_byte, I2C_FDATA_RCONT_BIT, flags.read_cont);
397  fmt_byte = bitfield_bit32_write(fmt_byte, I2C_FDATA_NAKOK_BIT,
398  flags.suppress_nak_irq);
399  mmio_region_write32(i2c->base_addr, I2C_FDATA_REG_OFFSET, fmt_byte);
400 
401  return kDifOk;
402 }
403 
404 dif_result_t dif_i2c_write_byte(const dif_i2c_t *i2c, uint8_t byte,
405  dif_i2c_fmt_t code, bool suppress_nak_irq) {
406  if (i2c == NULL) {
407  return kDifBadArg;
408  }
409 
410  // Validate that `suppress_nak_irq` has not been mixed with an Rx code.
411  if (suppress_nak_irq) {
412  switch (code) {
413  case kDifI2cFmtRx:
415  case kDifI2cFmtRxStop:
416  return kDifBadArg;
417  default:
418  break;
419  }
420  }
421 
422  // Convert the format code into flags.
423  dif_i2c_fmt_flags_t flags = {.suppress_nak_irq = suppress_nak_irq};
424  switch (code) {
425  case kDifI2cFmtStart:
426  flags.start = true;
427  break;
428  case kDifI2cFmtTx:
429  break;
430  case kDifI2cFmtTxStop:
431  flags.stop = true;
432  break;
433  case kDifI2cFmtRx:
434  flags.read = true;
435  break;
437  flags.read = true;
438  flags.read_cont = true;
439  break;
440  case kDifI2cFmtRxStop:
441  flags.read = true;
442  flags.stop = true;
443  break;
444  default:
445  return kDifBadArg;
446  }
447 
448  return dif_i2c_write_byte_raw(i2c, byte, flags);
449 }