27 #include "../switchtec_priv.h" 32 #include <sys/types.h> 34 #include <sys/ioctl.h> 36 #include <sys/sysmacros.h> 45 #include <linux/i2c.h> 46 #include <linux/i2c-dev.h> 48 struct switchtec_i2c {
49 struct switchtec_dev dev;
55 #define CMD_GET_CAP 0xE0 56 #define CMD_GAS_WRITE 0xEA 57 #define CMD_GET_WRITE_STATUS 0xE2 58 #define CMD_GAS_WRITE_WITH_STATUS 0xE8 59 #define CMD_GAS_READ 0xE9 61 #define MAX_RETRY_COUNT 100 62 #define MAX_STATUS_GET_RETRY 50 63 #define PEC_BYTE_COUNT 1 64 #define TWI_ENHANCED_MODE 0x80 65 #define GAS_TWI_MRPC_ERR 0x20 66 #define DATA_TAIL_BYTE_COUNT 2 68 #define to_switchtec_i2c(d) \ 69 ((struct switchtec_i2c *) \ 70 ((char *)d - offsetof(struct switchtec_i2c, dev))) 72 static uint8_t get_tag(
struct switchtec_i2c *idev)
81 static uint8_t i2c_msg_pec(
struct i2c_msg *msg, uint8_t byte_count,
82 uint8_t oldchksum,
bool init)
85 uint8_t addr = (msg->addr << 1) | msg->flags;
86 uint8_t pec = crc8(&addr, 1, oldchksum, init);
87 return crc8(msg->buf, byte_count, pec,
false);
90 static int dev_to_sysfs_path(
struct switchtec_i2c *idev,
const char *suffix,
91 char *buf,
size_t buflen)
96 ret = fstat(idev->fd, &stat);
100 snprintf(buf, buflen,
101 "/sys/dev/char/%d:%d/%s",
102 major(stat.st_rdev), minor(stat.st_rdev), suffix);
107 static int check_i2c_device_supported(
struct switchtec_i2c *idev)
112 ret = ioctl(idev->fd, I2C_FUNCS, &funcs);
116 if (!(funcs & I2C_FUNC_I2C)) {
124 static int check_i2c_device(
struct switchtec_i2c *idev)
127 char syspath[PATH_MAX];
129 ret = dev_to_sysfs_path(idev,
"device/i2c-dev", syspath,
134 ret = access(syspath, F_OK);
138 return check_i2c_device_supported(idev);
141 static int i2c_set_addr(
struct switchtec_i2c *idev,
int i2c_addr)
143 idev->i2c_addr = i2c_addr;
145 return ioctl(idev->fd, I2C_SLAVE, i2c_addr);
148 static int i2c_set_timeout(
struct switchtec_i2c *idev,
int time)
150 return ioctl(idev->fd, I2C_TIMEOUT, time);
154 #define __force __attribute__((force)) 159 static void i2c_close(
struct switchtec_dev *dev)
161 struct switchtec_i2c *idev = to_switchtec_i2c(dev);
164 munmap((
void __force *)dev->gas_map, dev->gas_map_size);
170 static int map_gas(
struct switchtec_dev *dev)
173 dev->gas_map_size = 4 << 20;
184 addr = mmap(NULL, dev->gas_map_size, PROT_NONE,
185 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
186 if (addr == MAP_FAILED)
189 dev->gas_map = (
gasptr_t __force)addr;
196 static gasptr_t i2c_gas_map(
struct switchtec_dev *dev,
int writeable,
200 *map_size = dev->gas_map_size;
205 static uint8_t i2c_gas_cap_get(
struct switchtec_dev *dev)
208 struct switchtec_i2c *idev = to_switchtec_i2c(dev);
210 struct i2c_msg msgs[2];
211 struct i2c_rdwr_ioctl_data rwdata = {
216 uint8_t command_code = CMD_GET_CAP;
218 uint8_t msg_0_pec, pec;
219 uint8_t retry_count = 0;
221 msgs[0].addr = msgs[1].addr = idev->i2c_addr;
224 msgs[0].buf = &command_code;
226 msgs[1].flags = I2C_M_RD;
228 msgs[1].buf = rx_buf;
231 ret = ioctl(idev->fd, I2C_RDWR, &rwdata);
235 msg_0_pec = i2c_msg_pec(&msgs[0], msgs[0].len, 0,
true);
236 pec = i2c_msg_pec(&msgs[1], msgs[1].len - PEC_BYTE_COUNT,
238 if (rx_buf[1] == pec)
242 }
while(retry_count < MAX_RETRY_COUNT);
245 if (retry_count == MAX_RETRY_COUNT)
248 return (rx_buf[0] & TWI_ENHANCED_MODE);
258 #define I2C_MAX_WRITE 24 263 #define I2C_MAX_READ 24 265 static uint8_t i2c_gas_data_write(
struct switchtec_dev *dev,
void __gas *dest,
266 const void *src,
size_t n, uint8_t tag)
269 struct switchtec_i2c *idev = to_switchtec_i2c(dev);
272 struct i2c_rdwr_ioctl_data wdata = {
278 uint8_t command_code;
283 } __attribute__((packed)) *i2c_data;
285 uint32_t gas_addr = (uint32_t)(dest - (
void __gas *)dev->gas_map);
286 assert(n <= I2C_MAX_WRITE);
289 i2c_data = malloc(
sizeof(*i2c_data) + n + PEC_BYTE_COUNT);
291 i2c_data->command_code = CMD_GAS_WRITE;
292 i2c_data->byte_count = (
sizeof(i2c_data->tag)
293 +
sizeof(i2c_data->offset)
297 gas_addr = htobe32(gas_addr);
298 i2c_data->offset = gas_addr;
299 memcpy(&i2c_data->data, src, n);
300 msg.addr = idev->i2c_addr;
302 msg.len =
sizeof(*i2c_data) + n + PEC_BYTE_COUNT;
303 msg.buf = (uint8_t *)i2c_data;
305 i2c_data->data[n] = i2c_msg_pec(&msg, msg.len - PEC_BYTE_COUNT, 0,
308 ret = ioctl(idev->fd, I2C_RDWR, &wdata);
320 static uint8_t i2c_gas_write_status_get(
struct switchtec_dev *dev,
324 struct switchtec_i2c *idev = to_switchtec_i2c(dev);
325 struct i2c_msg msgs[2];
326 struct i2c_rdwr_ioctl_data rwdata = {
331 uint8_t command_code = CMD_GET_WRITE_STATUS;
334 uint8_t msg_0_pec, pec;
335 uint8_t retry_count = 0;
337 msgs[0].addr = msgs[1].addr = idev->i2c_addr;
340 msgs[0].buf = &command_code;
342 msgs[1].flags = I2C_M_RD;
344 msgs[1].buf = rx_buf;
347 ret = ioctl(idev->fd, I2C_RDWR, &rwdata);
355 msg_0_pec = i2c_msg_pec(&msgs[0], msgs[0].len, 0,
true);
356 pec = i2c_msg_pec(&msgs[1], msgs[1].len - PEC_BYTE_COUNT,
358 if (rx_buf[0] == tag && rx_buf[2] == pec &&
359 (rx_buf[1] == 0 || rx_buf[1] == GAS_TWI_MRPC_ERR))
365 }
while(retry_count < MAX_STATUS_GET_RETRY);
370 static void i2c_gas_write(
struct switchtec_dev *dev,
void __gas *dest,
371 const void *src,
size_t n)
373 struct switchtec_i2c *idev = to_switchtec_i2c(dev);
376 uint8_t retry_count = 0;
380 i2c_gas_data_write(dev, dest, src, n, tag);
381 status = i2c_gas_write_status_get(dev, tag);
382 if (status == 0 || status == GAS_TWI_MRPC_ERR)
388 }
while (retry_count < MAX_RETRY_COUNT);
390 if (retry_count == MAX_RETRY_COUNT)
394 static void i2c_gas_write_no_retry(
struct switchtec_dev *dev,
void __gas *dest,
395 const void *src,
size_t n)
397 struct switchtec_i2c *idev = to_switchtec_i2c(dev);
402 i2c_gas_data_write(dev, dest, src, n, tag);
403 status = i2c_gas_write_status_get(dev, tag);
404 if (status == 0 || status == GAS_TWI_MRPC_ERR)
410 static void i2c_memcpy_to_gas(
struct switchtec_dev *dev,
void __gas *dest,
411 const void *src,
size_t n)
416 cnt = n > I2C_MAX_WRITE ? I2C_MAX_WRITE : n;
417 i2c_gas_write(dev, dest, src, cnt);
425 static uint8_t i2c_gas_data_read(
struct switchtec_dev *dev,
void *dest,
426 const void __gas *src,
size_t n)
429 int pec_index, status_index;
430 uint8_t msg_0_pec, pec;
431 uint8_t retry_count = 0;
433 struct switchtec_i2c *idev = to_switchtec_i2c(dev);
434 uint32_t gas_addr = (uint32_t)(src - (
void __gas *)dev->gas_map);
437 struct i2c_msg msgs[2];
438 struct i2c_rdwr_ioctl_data rwdata = {
444 uint8_t command_code;
448 } __attribute__((packed)) *read_command;
453 uint8_t data_and_tail[];
456 read_command = malloc(
sizeof(*read_command));
457 read_response = malloc(
sizeof(*read_response) + n \
458 + DATA_TAIL_BYTE_COUNT);
460 msgs[0].addr = msgs[1].addr = idev->i2c_addr;
462 msgs[0].len =
sizeof(*read_command);
464 read_command->command_code = CMD_GAS_READ;
465 read_command->byte_count =
sizeof(read_command->offset) \
466 +
sizeof(read_command->data_length);
467 gas_addr = htobe32(gas_addr);
468 read_command->offset = gas_addr;
469 read_command->data_length = n;
470 msgs[0].buf = (uint8_t *)read_command;
472 msgs[1].flags = I2C_M_RD;
473 msgs[1].len =
sizeof(read_response->byte_count) + n + \
474 DATA_TAIL_BYTE_COUNT;
475 msgs[1].buf = (uint8_t *)read_response;
478 ret = ioctl(idev->fd, I2C_RDWR, &rwdata);
482 msg_0_pec = i2c_msg_pec(&msgs[0], msgs[0].len, 0,
true);
483 pec = i2c_msg_pec(&msgs[1], msgs[1].len - PEC_BYTE_COUNT, \
485 pec_index = msgs[1].len -
sizeof(read_response->byte_count) \
487 if (read_response->data_and_tail[ pec_index ] == pec)
491 }
while(retry_count < MAX_RETRY_COUNT);
493 if (retry_count == MAX_RETRY_COUNT)
496 memcpy(dest, read_response->data_and_tail, n);
497 status_index = msgs[1].len -
sizeof(read_response->byte_count) \
498 - DATA_TAIL_BYTE_COUNT;
499 status = read_response->data_and_tail[ status_index ];
511 static void i2c_gas_read(
struct switchtec_dev *dev,
void *dest,
512 const void __gas *src,
size_t n)
515 uint8_t retry_count = 0;
518 status = i2c_gas_data_read(dev, dest, src, n);
519 if (status == 0 || status == GAS_TWI_MRPC_ERR)
522 }
while(retry_count < MAX_RETRY_COUNT);
524 if (retry_count == MAX_RETRY_COUNT)
528 static void i2c_memcpy_from_gas(
struct switchtec_dev *dev,
void *dest,
529 const void __gas *src,
size_t n)
534 cnt = n > I2C_MAX_READ ? I2C_MAX_READ : n;
535 i2c_gas_read(dev, dest, src, cnt);
543 static ssize_t i2c_write_from_gas(
struct switchtec_dev *dev,
int fd,
544 const void __gas *src,
size_t n)
551 i2c_memcpy_from_gas(dev, buf, src, n);
553 ret = write(fd, buf, n);
560 #define create_gas_read(type, suffix) \ 561 static type i2c_gas_read ## suffix(struct switchtec_dev *dev, \ 565 i2c_memcpy_from_gas(dev, &ret, addr, sizeof(ret)); \ 569 create_gas_read(uint8_t, 8);
570 create_gas_read(uint16_t, 16);
571 create_gas_read(uint32_t, 32);
572 create_gas_read(uint64_t, 64);
574 static void i2c_gas_write8(
struct switchtec_dev *dev, uint8_t val,
577 i2c_gas_write(dev, addr, &val,
sizeof(uint8_t));
580 static void i2c_gas_write16(
struct switchtec_dev *dev, uint16_t val,
581 uint16_t __gas *addr)
583 i2c_gas_write(dev, addr, &val,
sizeof(uint16_t));
586 static void i2c_gas_write32(
struct switchtec_dev *dev, uint32_t val,
587 uint32_t __gas *addr)
589 i2c_gas_write(dev, addr, &val,
sizeof(uint32_t));
592 static void i2c_gas_write32_no_retry(
struct switchtec_dev *dev, uint32_t val,
593 uint32_t __gas *addr)
595 i2c_gas_write_no_retry(dev, addr, &val,
sizeof(uint32_t));
598 static void i2c_gas_write64(
struct switchtec_dev *dev, uint64_t val,
599 uint64_t __gas *addr)
601 i2c_gas_write(dev, addr, &val,
sizeof(uint64_t));
604 static const struct switchtec_ops i2c_ops = {
606 .gas_map = i2c_gas_map,
609 .get_device_id = gasop_get_device_id,
610 .get_fw_version = gasop_get_fw_version,
611 .pff_to_port = gasop_pff_to_port,
612 .port_to_pff = gasop_port_to_pff,
613 .flash_part = gasop_flash_part,
614 .event_summary = gasop_event_summary,
615 .event_ctl = gasop_event_ctl,
616 .event_wait_for = gasop_event_wait_for,
618 .gas_read8 = i2c_gas_read8,
619 .gas_read16 = i2c_gas_read16,
620 .gas_read32 = i2c_gas_read32,
621 .gas_read64 = i2c_gas_read64,
622 .gas_write8 = i2c_gas_write8,
623 .gas_write16 = i2c_gas_write16,
624 .gas_write32 = i2c_gas_write32,
625 .gas_write32_no_retry = i2c_gas_write32_no_retry,
626 .gas_write64 = i2c_gas_write64,
627 .memcpy_to_gas = i2c_memcpy_to_gas,
628 .memcpy_from_gas = i2c_memcpy_from_gas,
629 .write_from_gas = i2c_write_from_gas,
634 struct switchtec_i2c *idev;
636 idev = malloc(
sizeof(*idev));
640 idev->fd = open(path, O_RDWR | O_CLOEXEC);
644 if (check_i2c_device(idev))
647 if (i2c_set_addr(idev, i2c_addr))
650 if (i2c_set_timeout(idev, 10))
653 if (i2c_gas_cap_get(&idev->dev) != TWI_ENHANCED_MODE)
656 if (map_gas(&idev->dev))
659 idev->dev.ops = &i2c_ops;
661 gasop_set_partition_info(&idev->dev);
672 struct switchtec_dev *switchtec_open_i2c_by_adapter(
int adapter,
int i2c_addr)
676 sprintf(path,
"/dev/i2c-%d", adapter);
__gas struct switchtec_gas * gasptr_t
Shortform for a pointer to the GAS register space.
struct switchtec_dev * switchtec_open_i2c(const char *path, int i2c_addr)
Open a switchtec device behind an I2C device.