Velocity Userspace
linux-i2c.c
1 /*
2  * Microsemi Switchtec(tm) PCIe Management Library
3  * Copyright (c) 2017, Microsemi Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  */
24 
25 #ifdef __linux__
26 
27 #include "../switchtec_priv.h"
28 #include "../crc.h"
29 #include "switchtec/switchtec.h"
30 #include "gasops.h"
31 
32 #include <endian.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/ioctl.h>
36 #include <sys/mman.h>
37 #include <sys/sysmacros.h>
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <errno.h>
41 #include <signal.h>
42 #include <stddef.h>
43 #include <assert.h>
44 #include <string.h>
45 
46 #include <linux/i2c.h>
47 #include <linux/i2c-dev.h>
48 
49 struct switchtec_i2c {
50  struct switchtec_dev dev;
51  int fd;
52  int i2c_addr;
53  uint8_t tag;
54 };
55 
56 #define CMD_GET_CAP 0xE0
57 #define CMD_GAS_WRITE 0xEA
58 #define CMD_GET_WRITE_STATUS 0xE2
59 #define CMD_GAS_WRITE_WITH_STATUS 0xE8
60 #define CMD_GAS_READ 0xE9
61 
62 #define MAX_RETRY_COUNT 100
63 #define MAX_STATUS_GET_RETRY 50
64 #define PEC_BYTE_COUNT 1
65 #define TWI_ENHANCED_MODE 0x80
66 #define GAS_TWI_MRPC_ERR 0x20
67 #define DATA_TAIL_BYTE_COUNT 2
68 
69 #define to_switchtec_i2c(d) \
70  ((struct switchtec_i2c *) \
71  ((char *)d - offsetof(struct switchtec_i2c, dev)))
72 
73 static uint8_t get_tag(struct switchtec_i2c *idev)
74 {
75  /* Valid tag is 0x01 ~ 0xff */
76  idev->tag++;
77  if (!idev->tag)
78  idev->tag = 1;
79  return idev->tag;
80 }
81 
82 static uint8_t i2c_msg_pec(struct i2c_msg *msg, uint8_t byte_count,
83  uint8_t oldchksum, bool init)
84 {
85  /* This function just supports 7-bits I2C address */
86  uint8_t addr = (msg->addr << 1) | msg->flags;
87  uint8_t pec = crc8(&addr, 1, oldchksum, init);
88  return crc8(msg->buf, byte_count, pec, false);
89 }
90 
91 static int dev_to_sysfs_path(struct switchtec_i2c *idev, const char *suffix,
92  char *buf, size_t buflen)
93 {
94  int ret;
95  struct stat stat;
96 
97  ret = fstat(idev->fd, &stat);
98  if (ret < 0)
99  return ret;
100 
101  snprintf(buf, buflen,
102  "/sys/dev/char/%d:%d/%s",
103  major(stat.st_rdev), minor(stat.st_rdev), suffix);
104 
105  return 0;
106 }
107 
108 static int check_i2c_device_supported(struct switchtec_i2c *idev)
109 {
110  unsigned long funcs;
111  int ret;
112 
113  ret = ioctl(idev->fd, I2C_FUNCS, &funcs);
114  if (ret < 0)
115  return ret;
116 
117  if (!(funcs & I2C_FUNC_I2C)) {
118  errno = ENOPROTOOPT;
119  return -errno;
120  }
121 
122  return 0;
123 }
124 
125 static int check_i2c_device(struct switchtec_i2c *idev)
126 {
127  int ret;
128  char syspath[PATH_MAX];
129 
130  ret = dev_to_sysfs_path(idev, "device/i2c-dev", syspath,
131  sizeof(syspath));
132  if (ret)
133  return ret;
134 
135  ret = access(syspath, F_OK);
136  if (ret)
137  errno = ENOTTY;
138 
139  return check_i2c_device_supported(idev);
140 }
141 
142 static int i2c_set_addr(struct switchtec_i2c *idev, int i2c_addr)
143 {
144  idev->i2c_addr = i2c_addr;
145 
146  return ioctl(idev->fd, I2C_SLAVE, i2c_addr);
147 }
148 
149 static int i2c_set_timeout(struct switchtec_i2c *idev, int time)
150 {
151  return ioctl(idev->fd, I2C_TIMEOUT, time);
152 }
153 
154 #ifdef __CHECKER__
155 #define __force __attribute__((force))
156 #else
157 #define __force
158 #endif
159 
160 static void i2c_close(struct switchtec_dev *dev)
161 {
162  struct switchtec_i2c *idev = to_switchtec_i2c(dev);
163 
164  if (dev->gas_map)
165  munmap((void __force *)dev->gas_map, dev->gas_map_size);
166 
167  close(idev->fd);
168  free(idev);
169 }
170 
171 static int map_gas(struct switchtec_dev *dev)
172 {
173  void *addr;
174  dev->gas_map_size = 4 << 20;
175 
176  /*
177  * Ensure that if someone tries to do something stupid,
178  * like dereference the GAS directly we fail without
179  * trashing random memory somewhere. We do this by
180  * allocating an innaccessible range in the virtual
181  * address space and use that as the GAS address which
182  * will be subtracted by subsequent operations
183  */
184 
185  addr = mmap(NULL, dev->gas_map_size, PROT_NONE,
186  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
187  if (addr == MAP_FAILED)
188  return -1;
189 
190  dev->gas_map = (gasptr_t __force)addr;
191 
192  return 0;
193 }
194 
195 #undef __force
196 
197 static gasptr_t i2c_gas_map(struct switchtec_dev *dev, int writeable,
198  size_t *map_size)
199 {
200  if (map_size)
201  *map_size = dev->gas_map_size;
202 
203  return dev->gas_map;
204 }
205 
206 static uint8_t i2c_gas_cap_get(struct switchtec_dev *dev)
207 {
208  int ret;
209  struct switchtec_i2c *idev = to_switchtec_i2c(dev);
210 
211  struct i2c_msg msgs[2];
212  struct i2c_rdwr_ioctl_data rwdata = {
213  .msgs = msgs,
214  .nmsgs = 2,
215  };
216 
217  uint8_t command_code = CMD_GET_CAP;
218  uint8_t rx_buf[2];
219  uint8_t msg_0_pec, pec;
220  uint8_t retry_count = 0;
221 
222  msgs[0].addr = msgs[1].addr = idev->i2c_addr;
223  msgs[0].flags = 0;
224  msgs[0].len = 1;
225  msgs[0].buf = &command_code;
226 
227  msgs[1].flags = I2C_M_RD;
228  msgs[1].len = 2;
229  msgs[1].buf = rx_buf;
230 
231  do {
232  ret = ioctl(idev->fd, I2C_RDWR, &rwdata);
233  if (ret < 0)
234  goto i2c_ioctl_fail;
235 
236  msg_0_pec = i2c_msg_pec(&msgs[0], msgs[0].len, 0, true);
237  pec = i2c_msg_pec(&msgs[1], msgs[1].len - PEC_BYTE_COUNT,
238  msg_0_pec, false);
239  if (rx_buf[1] == pec)
240  break;
241 
242  retry_count++;
243  } while(retry_count < MAX_RETRY_COUNT);
244 
245  /* return capability */
246  if (retry_count == MAX_RETRY_COUNT)
247  return -1;
248  else
249  return (rx_buf[0] & TWI_ENHANCED_MODE);
250 
251 i2c_ioctl_fail:
252  return -1;
253 }
254 
255 /*
256  * One I2C transaction can write a maximum of 26 bytes, but it is better to
257  * write the GAS with dword.
258  */
259 #define I2C_MAX_WRITE 24
260 /*
261  * One I2C transaction can read a maximum of 27 bytes, but it is better to
262  * read GAS with dword.
263  */
264 #define I2C_MAX_READ 24
265 
266 static uint8_t i2c_gas_data_write(struct switchtec_dev *dev, void __gas *dest,
267  const void *src, size_t n, uint8_t tag)
268 {
269  int ret;
270  struct switchtec_i2c *idev = to_switchtec_i2c(dev);
271 
272  struct i2c_msg msg;
273  struct i2c_rdwr_ioctl_data wdata = {
274  .msgs = &msg,
275  .nmsgs = 1,
276  };
277 
278  struct {
279  uint8_t command_code;
280  uint8_t byte_count;
281  uint8_t tag;
282  uint32_t offset;
283  uint8_t data[];
284  } __attribute__((packed)) *i2c_data;
285 
286  uint32_t gas_addr = (uint32_t)(dest - (void __gas *)dev->gas_map);
287  assert(n <= I2C_MAX_WRITE);
288 
289  /* PEC is the last byte */
290  i2c_data = malloc(sizeof(*i2c_data) + n + PEC_BYTE_COUNT);
291 
292  i2c_data->command_code = CMD_GAS_WRITE;
293  i2c_data->byte_count = (sizeof(i2c_data->tag)
294  + sizeof(i2c_data->offset)
295  + n);
296  i2c_data->tag = tag;
297 
298  gas_addr = htobe32(gas_addr);
299  i2c_data->offset = gas_addr;
300  memcpy(&i2c_data->data, src, n);
301  msg.addr = idev->i2c_addr;
302  msg.flags = 0;
303  msg.len = sizeof(*i2c_data) + n + PEC_BYTE_COUNT;
304  msg.buf = (uint8_t *)i2c_data;
305 
306  i2c_data->data[n] = i2c_msg_pec(&msg, msg.len - PEC_BYTE_COUNT, 0,
307  true);
308 
309  ret = ioctl(idev->fd, I2C_RDWR, &wdata);
310  if (ret < 0)
311  goto i2c_write_fail;
312 
313  free(i2c_data);
314  return 0;
315 
316 i2c_write_fail:
317  free(i2c_data);
318  return -1;
319 }
320 
321 static uint8_t i2c_gas_write_status_get(struct switchtec_dev *dev,
322  uint8_t tag)
323 {
324  int ret;
325  struct switchtec_i2c *idev = to_switchtec_i2c(dev);
326  struct i2c_msg msgs[2];
327  struct i2c_rdwr_ioctl_data rwdata = {
328  .msgs = msgs,
329  .nmsgs = 2,
330  };
331 
332  uint8_t command_code = CMD_GET_WRITE_STATUS;
333  uint8_t rx_buf[3];
334 
335  uint8_t msg_0_pec, pec;
336  uint8_t retry_count = 0;
337 
338  msgs[0].addr = msgs[1].addr = idev->i2c_addr;
339  msgs[0].flags = 0;
340  msgs[0].len = 1;
341  msgs[0].buf = &command_code;
342 
343  msgs[1].flags = I2C_M_RD;
344  msgs[1].len = 3;
345  msgs[1].buf = rx_buf;
346 
347  do {
348  ret = ioctl(idev->fd, I2C_RDWR, &rwdata);
349  if (ret < 0) {
350  retry_count++;
351  /* Delay is typically only needed for BL1/2 phase */
352  usleep(20000);
353  continue;
354  }
355 
356  msg_0_pec = i2c_msg_pec(&msgs[0], msgs[0].len, 0, true);
357  pec = i2c_msg_pec(&msgs[1], msgs[1].len - PEC_BYTE_COUNT,
358  msg_0_pec, false);
359  if (rx_buf[0] == tag && rx_buf[2] == pec &&
360  (rx_buf[1] == 0 || rx_buf[1] == GAS_TWI_MRPC_ERR))
361  return rx_buf[1];
362 
363  /* Extra delay is typically only needed for BL1/2 phase */
364  usleep(20000);
365  retry_count++;
366  } while(retry_count < MAX_STATUS_GET_RETRY);
367 
368  return -1;
369 }
370 
371 static void i2c_gas_write(struct switchtec_dev *dev, void __gas *dest,
372  const void *src, size_t n)
373 {
374  struct switchtec_i2c *idev = to_switchtec_i2c(dev);
375  uint8_t tag;
376  uint8_t status;
377  uint8_t retry_count = 0;
378 
379  do {
380  tag = get_tag(idev);
381  i2c_gas_data_write(dev, dest, src, n, tag);
382  status = i2c_gas_write_status_get(dev, tag);
383  if (status == 0 || status == GAS_TWI_MRPC_ERR)
384  break;
385 
386  /* Extra delay is typically only needed for BL1/2 phase */
387  usleep(1000);
388  retry_count++;
389  } while (retry_count < MAX_RETRY_COUNT);
390 
391  if (retry_count == MAX_RETRY_COUNT)
392  raise(SIGBUS);
393 }
394 
395 static void i2c_gas_write_no_retry(struct switchtec_dev *dev, void __gas *dest,
396  const void *src, size_t n)
397 {
398  struct switchtec_i2c *idev = to_switchtec_i2c(dev);
399  uint8_t tag;
400  uint8_t status;
401  uint8_t retry_count = 0;
402 
403  tag = get_tag(idev);
404  i2c_gas_data_write(dev, dest, src, n, tag);
405  do {
406  status = i2c_gas_write_status_get(dev, tag);
407  if (status == 0 || status == GAS_TWI_MRPC_ERR)
408  return;
409 
410  /* Extra delay is typically only needed for BL1/2 phase */
411  usleep(1000);
412  retry_count++;
413  } while (retry_count < MAX_RETRY_COUNT);
414 
415  raise(SIGBUS);
416 }
417 
418 static void i2c_memcpy_to_gas(struct switchtec_dev *dev, void __gas *dest,
419  const void *src, size_t n)
420 {
421  size_t cnt;
422 
423  while (n) {
424  cnt = n > I2C_MAX_WRITE ? I2C_MAX_WRITE : n;
425  i2c_gas_write(dev, dest, src, cnt);
426 
427  dest += cnt;
428  src += cnt;
429  n -= cnt;
430  }
431 }
432 
433 static uint8_t i2c_gas_data_read(struct switchtec_dev *dev, void *dest,
434  const void __gas *src, size_t n)
435 {
436  int ret;
437  int pec_index, status_index;
438  uint8_t msg_0_pec, pec;
439  uint8_t retry_count = 0;
440 
441  struct switchtec_i2c *idev = to_switchtec_i2c(dev);
442  uint32_t gas_addr = (uint32_t)(src - (void __gas *)dev->gas_map);
443  uint8_t status;
444 
445  struct i2c_msg msgs[2];
446  struct i2c_rdwr_ioctl_data rwdata = {
447  .msgs = msgs,
448  .nmsgs = 2,
449  };
450 
451  struct {
452  uint8_t command_code;
453  uint8_t byte_count;
454  uint32_t offset;
455  uint8_t data_length;
456  } __attribute__((packed)) *read_command;
457 
458  struct {
459  uint8_t byte_count;
460  /* tail is one byte status and one byte pec */
461  uint8_t data_and_tail[];
462  }*read_response;
463 
464  read_command = malloc(sizeof(*read_command));
465  read_response = malloc(sizeof(*read_response) + n \
466  + DATA_TAIL_BYTE_COUNT);
467 
468  msgs[0].addr = msgs[1].addr = idev->i2c_addr;
469  msgs[0].flags = 0;
470  msgs[0].len = sizeof(*read_command);
471 
472  read_command->command_code = CMD_GAS_READ;
473  read_command->byte_count = sizeof(read_command->offset) \
474  + sizeof(read_command->data_length);
475  gas_addr = htobe32(gas_addr);
476  read_command->offset = gas_addr;
477  read_command->data_length = n;
478  msgs[0].buf = (uint8_t *)read_command;
479 
480  msgs[1].flags = I2C_M_RD;
481  msgs[1].len = sizeof(read_response->byte_count) + n + \
482  DATA_TAIL_BYTE_COUNT;
483  msgs[1].buf = (uint8_t *)read_response;
484 
485  do {
486  ret = ioctl(idev->fd, I2C_RDWR, &rwdata);
487  if (ret < 0)
488  goto i2c_read_fail;
489 
490  msg_0_pec = i2c_msg_pec(&msgs[0], msgs[0].len, 0, true);
491  pec = i2c_msg_pec(&msgs[1], msgs[1].len - PEC_BYTE_COUNT, \
492  msg_0_pec, false);
493  pec_index = msgs[1].len - sizeof(read_response->byte_count) \
494  - PEC_BYTE_COUNT;
495  if (read_response->data_and_tail[ pec_index ] == pec)
496  break;
497 
498  retry_count++;
499  } while(retry_count < MAX_RETRY_COUNT);
500 
501  if (retry_count == MAX_RETRY_COUNT)
502  goto i2c_read_fail;
503 
504  memcpy(dest, read_response->data_and_tail, n);
505  status_index = msgs[1].len - sizeof(read_response->byte_count) \
506  - DATA_TAIL_BYTE_COUNT;
507  status = read_response->data_and_tail[ status_index ];
508 
509  free(read_command);
510  free(read_response);
511  return status;
512 
513 i2c_read_fail:
514  free(read_command);
515  free(read_response);
516  return -1;
517 }
518 
519 static void i2c_gas_read(struct switchtec_dev *dev, void *dest,
520  const void __gas *src, size_t n)
521 {
522  uint8_t status;
523  uint8_t retry_count = 0;
524 
525  do {
526  status = i2c_gas_data_read(dev, dest, src, n);
527  if (status == 0 || status == GAS_TWI_MRPC_ERR)
528  break;
529  retry_count++;
530  }while(retry_count < MAX_RETRY_COUNT);
531 
532  if (retry_count == MAX_RETRY_COUNT)
533  raise(SIGBUS);
534 }
535 
536 static void i2c_memcpy_from_gas(struct switchtec_dev *dev, void *dest,
537  const void __gas *src, size_t n)
538 {
539  size_t cnt;
540 
541  while (n) {
542  cnt = n > I2C_MAX_READ ? I2C_MAX_READ : n;
543  i2c_gas_read(dev, dest, src, cnt);
544 
545  dest += cnt;
546  src += cnt;
547  n -= cnt;
548  }
549 }
550 
551 static ssize_t i2c_write_from_gas(struct switchtec_dev *dev, int fd,
552  const void __gas *src, size_t n)
553 {
554  ssize_t ret;
555  void *buf;
556 
557  buf = malloc(n);
558 
559  i2c_memcpy_from_gas(dev, buf, src, n);
560 
561  ret = write(fd, buf, n);
562 
563  free(buf);
564 
565  return ret;
566 }
567 
568 // noop conversion functions to make macros below work
569 static inline uint8_t le8toh(uint8_t x) { return x; }
570 
571 #define create_gas_read(type, suffix) \
572  static type i2c_gas_read ## suffix(struct switchtec_dev *dev, \
573  type __gas *addr) \
574  { \
575  type ret; \
576  i2c_memcpy_from_gas(dev, &ret, addr, sizeof(ret)); \
577  return le##suffix##toh(ret); \
578  }
579 
580 create_gas_read(uint8_t, 8);
581 create_gas_read(uint16_t, 16);
582 create_gas_read(uint32_t, 32);
583 create_gas_read(uint64_t, 64);
584 
585 static void i2c_gas_write8(struct switchtec_dev *dev, uint8_t val,
586  uint8_t __gas *addr)
587 {
588  i2c_gas_write(dev, addr, &val, sizeof(uint8_t));
589 }
590 
591 static void i2c_gas_write16(struct switchtec_dev *dev, uint16_t val,
592  uint16_t __gas *addr)
593 {
594  val = htole16(val);
595  i2c_gas_write(dev, addr, &val, sizeof(uint16_t));
596 }
597 
598 static void i2c_gas_write32(struct switchtec_dev *dev, uint32_t val,
599  uint32_t __gas *addr)
600 {
601  val = htole32(val);
602  i2c_gas_write(dev, addr, &val, sizeof(uint32_t));
603 }
604 
605 static void i2c_gas_write32_no_retry(struct switchtec_dev *dev, uint32_t val,
606  uint32_t __gas *addr)
607 {
608  val = htole32(val);
609  i2c_gas_write_no_retry(dev, addr, &val, sizeof(uint32_t));
610 }
611 
612 static void i2c_gas_write64(struct switchtec_dev *dev, uint64_t val,
613  uint64_t __gas *addr)
614 {
615  val = htole64(val);
616  i2c_gas_write(dev, addr, &val, sizeof(uint64_t));
617 }
618 
619 static const struct switchtec_ops i2c_ops = {
620  .close = i2c_close,
621  .gas_map = i2c_gas_map,
622 
623  .cmd = gasop_cmd,
624  .get_device_id = gasop_get_device_id,
625  .get_fw_version = gasop_get_fw_version,
626  .pff_to_port = gasop_pff_to_port,
627  .port_to_pff = gasop_port_to_pff,
628  .flash_part = gasop_flash_part,
629  .event_summary = gasop_event_summary,
630  .event_ctl = gasop_event_ctl,
631  .event_wait_for = gasop_event_wait_for,
632 
633  .gas_read8 = i2c_gas_read8,
634  .gas_read16 = i2c_gas_read16,
635  .gas_read32 = i2c_gas_read32,
636  .gas_read64 = i2c_gas_read64,
637  .gas_write8 = i2c_gas_write8,
638  .gas_write16 = i2c_gas_write16,
639  .gas_write32 = i2c_gas_write32,
640  .gas_write32_no_retry = i2c_gas_write32_no_retry,
641  .gas_write64 = i2c_gas_write64,
642  .memcpy_to_gas = i2c_memcpy_to_gas,
643  .memcpy_from_gas = i2c_memcpy_from_gas,
644  .write_from_gas = i2c_write_from_gas,
645 };
646 
647 struct switchtec_dev *switchtec_open_i2c(const char *path, int i2c_addr)
648 {
649  struct switchtec_i2c *idev;
650 
651  idev = malloc(sizeof(*idev));
652  if (!idev)
653  return NULL;
654 
655  idev->fd = open(path, O_RDWR | O_CLOEXEC);
656  if (idev->fd < 0)
657  goto err_free;
658 
659  if (check_i2c_device(idev))
660  goto err_close_free;
661 
662  if (i2c_set_addr(idev, i2c_addr))
663  goto err_close_free;
664 
665  if (i2c_set_timeout(idev, 10))
666  goto err_close_free;
667 
668  if (i2c_gas_cap_get(&idev->dev) != TWI_ENHANCED_MODE)
669  goto err_close_free;
670 
671  if (map_gas(&idev->dev))
672  goto err_close_free;
673 
674  idev->dev.ops = &i2c_ops;
675 
676  gasop_set_partition_info(&idev->dev);
677 
678  return &idev->dev;
679 
680 err_close_free:
681  close(idev->fd);
682 err_free:
683  free(idev);
684  return NULL;
685 }
686 
687 struct switchtec_dev *switchtec_open_i2c_by_adapter(int adapter, int i2c_addr)
688 {
689  char path[PATH_MAX];
690 
691  sprintf(path, "/dev/i2c-%d", adapter);
692 
693  return switchtec_open_i2c(path, i2c_addr);
694 }
695 
696 #endif
switchtec.h
Main Switchtec header.
switchtec_open_i2c
struct switchtec_dev * switchtec_open_i2c(const char *path, int i2c_addr)
Open a switchtec device behind an I2C device.
Definition: linux-i2c.c:647
gasptr_t
__gas struct switchtec_gas * gasptr_t
Shortform for a pointer to the GAS register space.
Definition: switchtec.h:83
switchtec_i2c
Definition: linux-i2c.c:49