Lines Matching +full:i2c +full:- +full:retry +full:- +full:count
7 * Copyright (C) 2016 T-Platforms. All Rights Reserved.
36 * IDT PCIe-switch NTB Linux driver
39 * Serge Semin <fancer.lancer@gmail.com>, <Sergey.Semin@t-platforms.ru>
42 * NOTE of the IDT 89HPESx SMBus-slave interface driver
44 * IDT PCIe-switches. IDT provides a simple SMBus interface to perform IO-
47 * binary sysfs-file in the device directory:
48 * /sys/bus/i2c/devices/<bus>-<devaddr>/eeprom
49 * In case if read-only flag is specified in the dts-node of device desription,
50 * User-space applications won't be able to write to the EEPROM sysfs-node.
52 * data of device CSRs. This driver exposes debugf-file to perform simple IO
54 * next file is created in the specific debugfs-directory:
56 * Format of the debugfs-node is:
57 * $ cat /sys/kernel/debug/idt_csr/<bus>-<devaddr>/<devname>;
60 * If User-space application wishes to change current CSR address,
61 * it can just write a proper value to the sysfs-file:
62 * $ echo "<CSR address>" > /sys/kernel/debug/idt_csr/<bus>-<devaddr>/<devname>
66 * /sys/kernel/debug/idt_csr/<bus>-<devaddr>/<devname>;
81 #include <linux/i2c.h>
86 #define IDT_89HPESX_DESC "IDT 89HPESx SMBus-slave interface driver"
92 MODULE_AUTHOR("T-platforms");
95 * csr_dbgdir - CSR read/write operations Debugfs directory
100 * struct idt_89hpesx_dev - IDT 89HPESx device data structure
102 * @eero: EEPROM Read-only flag
107 * @iniccode: Initialial command code value for IO-operations
115 * @client: i2c client used to perform IO operations
117 * @ee_file: EEPROM read/write sysfs-file
142 * struct idt_smb_seq - sequence of data to be read/written from/to IDT 89HPESx
144 * @bytecnt: Byte count of operation
154 * struct idt_eeprom_seq - sequence of data to be read/written from/to EEPROM
168 * struct idt_csr_seq - sequence of data to be read/written from/to CSR
207 * @EEPROM_WR_CNT: Bytes count to perform write operation
208 * @EEPROM_WRRD_CNT: Bytes count to write before reading
209 * @EEPROM_RD_CNT: Bytes count to perform read operation
212 * @EEPROM_TOUT: Timeout before retry read operation if eeprom is busy
234 * @CSR_WR_CNT: Bytes count to perform write operation
235 * @CSR_WRRD_CNT: Bytes count to write before reading
236 * @CSR_RD_CNT: Bytes count to perform read operation
266 * @idt_smb_safe: Generate a retry loop on corresponding SMBus method
274 } while (__retry-- && __sts < 0); \
279 * i2c bus level IO-operations
284 * idt_smb_write_byte() - SMBus write method when I2C_SMBUS_BYTE_DATA operation
296 /* Loop over the supplied data sending byte one-by-one */ in idt_smb_write_byte()
297 for (idx = 0; idx < seq->bytecnt; idx++) { in idt_smb_write_byte()
299 ccode = seq->ccode | CCODE_BYTE; in idt_smb_write_byte()
302 if (idx == seq->bytecnt - 1) in idt_smb_write_byte()
306 sts = idt_smb_safe(write_byte, pdev->client, ccode, in idt_smb_write_byte()
307 seq->data[idx]); in idt_smb_write_byte()
316 * idt_smb_read_byte() - SMBus read method when I2C_SMBUS_BYTE_DATA operation
328 /* Loop over the supplied buffer receiving byte one-by-one */ in idt_smb_read_byte()
329 for (idx = 0; idx < seq->bytecnt; idx++) { in idt_smb_read_byte()
331 ccode = seq->ccode | CCODE_BYTE; in idt_smb_read_byte()
334 if (idx == seq->bytecnt - 1) in idt_smb_read_byte()
338 sts = idt_smb_safe(read_byte, pdev->client, ccode); in idt_smb_read_byte()
342 seq->data[idx] = (u8)sts; in idt_smb_read_byte()
349 * idt_smb_write_word() - SMBus write method when I2C_SMBUS_BYTE_DATA and
361 /* Calculate the even count of data to send */ in idt_smb_write_word()
362 evencnt = seq->bytecnt - (seq->bytecnt % 2); in idt_smb_write_word()
367 ccode = seq->ccode | CCODE_WORD; in idt_smb_write_word()
370 if (idx == evencnt - 2) in idt_smb_write_word()
374 sts = idt_smb_safe(write_word, pdev->client, ccode, in idt_smb_write_word()
375 *(u16 *)&seq->data[idx]); in idt_smb_write_word()
381 if (seq->bytecnt != evencnt) { in idt_smb_write_word()
383 ccode = seq->ccode | CCODE_BYTE | CCODE_END; in idt_smb_write_word()
388 sts = idt_smb_safe(write_byte, pdev->client, ccode, in idt_smb_write_word()
389 seq->data[idx]); in idt_smb_write_word()
398 * idt_smb_read_word() - SMBus read method when I2C_SMBUS_BYTE_DATA and
410 /* Calculate the even count of data to send */ in idt_smb_read_word()
411 evencnt = seq->bytecnt - (seq->bytecnt % 2); in idt_smb_read_word()
416 ccode = seq->ccode | CCODE_WORD; in idt_smb_read_word()
419 if (idx == evencnt - 2) in idt_smb_read_word()
423 sts = idt_smb_safe(read_word, pdev->client, ccode); in idt_smb_read_word()
427 *(u16 *)&seq->data[idx] = (u16)sts; in idt_smb_read_word()
431 if (seq->bytecnt != evencnt) { in idt_smb_read_word()
433 ccode = seq->ccode | CCODE_BYTE | CCODE_END; in idt_smb_read_word()
438 sts = idt_smb_safe(read_byte, pdev->client, ccode); in idt_smb_read_word()
442 seq->data[idx] = (u8)sts; in idt_smb_read_word()
449 * idt_smb_write_block() - SMBus write method when I2C_SMBUS_BLOCK_DATA
460 if (seq->bytecnt > I2C_SMBUS_BLOCK_MAX) in idt_smb_write_block()
461 return -EINVAL; in idt_smb_write_block()
464 ccode = seq->ccode | CCODE_BLOCK | CCODE_START | CCODE_END; in idt_smb_write_block()
467 return idt_smb_safe(write_block, pdev->client, ccode, seq->bytecnt, in idt_smb_write_block()
468 seq->data); in idt_smb_write_block()
472 * idt_smb_read_block() - SMBus read method when I2C_SMBUS_BLOCK_DATA
484 if (seq->bytecnt > I2C_SMBUS_BLOCK_MAX) in idt_smb_read_block()
485 return -EINVAL; in idt_smb_read_block()
488 ccode = seq->ccode | CCODE_BLOCK | CCODE_START | CCODE_END; in idt_smb_read_block()
491 sts = idt_smb_safe(read_block, pdev->client, ccode, seq->data); in idt_smb_read_block()
492 if (sts != seq->bytecnt) in idt_smb_read_block()
493 return (sts < 0 ? sts : -ENODATA); in idt_smb_read_block()
499 * idt_smb_write_i2c_block() - SMBus write method when I2C_SMBUS_I2C_BLOCK_DATA
513 if (seq->bytecnt > I2C_SMBUS_BLOCK_MAX) in idt_smb_write_i2c_block()
514 return -EINVAL; in idt_smb_write_i2c_block()
517 buf[0] = seq->bytecnt; in idt_smb_write_i2c_block()
518 memcpy(&buf[1], seq->data, seq->bytecnt); in idt_smb_write_i2c_block()
521 ccode = seq->ccode | CCODE_BLOCK | CCODE_START | CCODE_END; in idt_smb_write_i2c_block()
524 return idt_smb_safe(write_i2c_block, pdev->client, ccode, in idt_smb_write_i2c_block()
525 seq->bytecnt + 1, buf); in idt_smb_write_i2c_block()
529 * idt_smb_read_i2c_block() - SMBus read method when I2C_SMBUS_I2C_BLOCK_DATA
544 if (seq->bytecnt > I2C_SMBUS_BLOCK_MAX) in idt_smb_read_i2c_block()
545 return -EINVAL; in idt_smb_read_i2c_block()
548 ccode = seq->ccode | CCODE_BLOCK | CCODE_START | CCODE_END; in idt_smb_read_i2c_block()
551 sts = idt_smb_safe(read_i2c_block, pdev->client, ccode, in idt_smb_read_i2c_block()
552 seq->bytecnt + 1, buf); in idt_smb_read_i2c_block()
553 if (sts != seq->bytecnt + 1) in idt_smb_read_i2c_block()
554 return (sts < 0 ? sts : -ENODATA); in idt_smb_read_i2c_block()
555 if (buf[0] != seq->bytecnt) in idt_smb_read_i2c_block()
556 return -ENODATA; in idt_smb_read_i2c_block()
559 memcpy(seq->data, &buf[1], seq->bytecnt); in idt_smb_read_i2c_block()
565 * EEPROM IO-operations
570 * idt_eeprom_read_byte() - read just one byte from EEPROM
578 struct device *dev = &pdev->client->dev; in idt_eeprom_read_byte()
581 int ret, retry; in idt_eeprom_read_byte() local
584 smbseq.ccode = pdev->iniccode | CCODE_EEPROM; in idt_eeprom_read_byte()
591 retry = RETRY_CNT; in idt_eeprom_read_byte()
595 eeseq.cmd = pdev->inieecmd | EEPROM_OP_READ; in idt_eeprom_read_byte()
596 eeseq.eeaddr = pdev->eeaddr; in idt_eeprom_read_byte()
598 ret = pdev->smb_write(pdev, &smbseq); in idt_eeprom_read_byte()
607 ret = pdev->smb_read(pdev, &smbseq); in idt_eeprom_read_byte()
615 if (retry && (eeseq.cmd & EEPROM_NAERR)) { in idt_eeprom_read_byte()
616 dev_dbg(dev, "EEPROM busy, retry reading after %d ms", in idt_eeprom_read_byte()
627 ret = -EREMOTEIO; in idt_eeprom_read_byte()
634 } while (retry--); in idt_eeprom_read_byte()
641 * idt_eeprom_write() - EEPROM write operation
650 struct device *dev = &pdev->client->dev; in idt_eeprom_write()
657 smbseq.ccode = pdev->iniccode | CCODE_EEPROM; in idt_eeprom_write()
660 /* Send data byte-by-byte, checking if it is successfully written */ in idt_eeprom_write()
663 mutex_lock(&pdev->smb_mtx); in idt_eeprom_write()
667 eeseq.cmd = pdev->inieecmd | EEPROM_OP_WRITE; in idt_eeprom_write()
668 eeseq.eeaddr = pdev->eeaddr; in idt_eeprom_write()
671 ret = pdev->smb_write(pdev, &smbseq); in idt_eeprom_write()
692 ret = -EREMOTEIO; in idt_eeprom_write()
698 mutex_unlock(&pdev->smb_mtx); in idt_eeprom_write()
707 * idt_eeprom_read() - EEPROM read operation
719 /* Read data byte-by-byte, retrying if it wasn't successful */ in idt_eeprom_read()
722 mutex_lock(&pdev->smb_mtx); in idt_eeprom_read()
728 mutex_unlock(&pdev->smb_mtx); in idt_eeprom_read()
739 * CSR IO-operations
744 * idt_csr_write() - CSR write operation
752 struct device *dev = &pdev->client->dev; in idt_csr_write()
758 smbseq.ccode = pdev->iniccode | CCODE_CSR; in idt_csr_write()
762 mutex_lock(&pdev->smb_mtx); in idt_csr_write()
766 csrseq.cmd = pdev->inicsrcmd | CSR_OP_WRITE; in idt_csr_write()
769 ret = pdev->smb_write(pdev, &smbseq); in idt_csr_write()
778 csrseq.cmd = pdev->inicsrcmd | CSR_OP_READ; in idt_csr_write()
779 ret = pdev->smb_write(pdev, &smbseq); in idt_csr_write()
788 ret = pdev->smb_read(pdev, &smbseq); in idt_csr_write()
798 ret = -EREMOTEIO; in idt_csr_write()
804 mutex_unlock(&pdev->smb_mtx); in idt_csr_write()
810 * idt_csr_read() - CSR read operation
817 struct device *dev = &pdev->client->dev; in idt_csr_read()
823 smbseq.ccode = pdev->iniccode | CCODE_CSR; in idt_csr_read()
827 mutex_lock(&pdev->smb_mtx); in idt_csr_read()
831 csrseq.cmd = pdev->inicsrcmd | CSR_OP_READ; in idt_csr_read()
833 ret = pdev->smb_write(pdev, &smbseq); in idt_csr_read()
842 ret = pdev->smb_read(pdev, &smbseq); in idt_csr_read()
852 ret = -EREMOTEIO; in idt_csr_read()
861 mutex_unlock(&pdev->smb_mtx); in idt_csr_read()
867 * Sysfs/debugfs-nodes IO-operations
872 * eeprom_write() - EEPROM sysfs-node write callback
874 * @kobj: Pointer to the kernel object related to the sysfs-node
878 * @count: Number of bytes to write
882 char *buf, loff_t off, size_t count) in eeprom_write() argument
891 ret = idt_eeprom_write(pdev, (u16)off, (u16)count, (u8 *)buf); in eeprom_write()
892 return (ret != 0 ? ret : count); in eeprom_write()
896 * eeprom_read() - EEPROM sysfs-node read callback
898 * @kobj: Pointer to the kernel object related to the sysfs-node
902 * @count: Number of bytes to write
906 char *buf, loff_t off, size_t count) in eeprom_read() argument
915 ret = idt_eeprom_read(pdev, (u16)off, (u16)count, (u8 *)buf); in eeprom_read()
916 return (ret != 0 ? ret : count); in eeprom_read()
920 * idt_dbgfs_csr_write() - CSR debugfs-node write callback
923 * @count: Size of the buffer
935 size_t count, loff_t *offp) in idt_dbgfs_csr_write() argument
937 struct idt_89hpesx_dev *pdev = filep->private_data; in idt_dbgfs_csr_write()
943 /* Copy data from User-space */ in idt_dbgfs_csr_write()
944 buf = kmalloc(count + 1, GFP_KERNEL); in idt_dbgfs_csr_write()
946 return -ENOMEM; in idt_dbgfs_csr_write()
948 ret = simple_write_to_buffer(buf, count, offp, ubuf, count); in idt_dbgfs_csr_write()
951 buf[count] = 0; in idt_dbgfs_csr_write()
954 colon_ch = strnchr(buf, count, ':'); in idt_dbgfs_csr_write()
963 csraddr_len = colon_ch - buf; in idt_dbgfs_csr_write()
967 ret = -ENOMEM; in idt_dbgfs_csr_write()
977 csraddr_len = strnlen(csraddr_str, count); in idt_dbgfs_csr_write()
988 ret = -EINVAL; in idt_dbgfs_csr_write()
993 pdev->csr = (csraddr >> 2); in idt_dbgfs_csr_write()
1001 ret = idt_csr_write(pdev, pdev->csr, csrval); in idt_dbgfs_csr_write()
1011 /* Free buffer allocated for data retrieved from User-space */ in idt_dbgfs_csr_write()
1015 return (ret != 0 ? ret : count); in idt_dbgfs_csr_write()
1019 * idt_dbgfs_csr_read() - CSR debugfs-node read callback
1022 * @count: Size of the buffer
1029 size_t count, loff_t *offp) in idt_dbgfs_csr_read() argument
1031 struct idt_89hpesx_dev *pdev = filep->private_data; in idt_dbgfs_csr_read()
1037 ret = idt_csr_read(pdev, pdev->csr, &csrval); in idt_dbgfs_csr_read()
1042 csraddr = ((u32)pdev->csr << 2); in idt_dbgfs_csr_read()
1048 /* Copy data to User-space */ in idt_dbgfs_csr_read()
1049 return simple_read_from_buffer(ubuf, count, offp, buf, size); in idt_dbgfs_csr_read()
1053 * eeprom_attribute - EEPROM sysfs-node attributes
1056 * be read-only as well if the corresponding flag is specified in OF node.
1061 * csr_dbgfs_ops - CSR debugfs-node read/write operations
1076 * idt_set_defval() - disable EEPROM access by default
1082 pdev->eesize = 0; in idt_set_defval()
1083 pdev->eero = true; in idt_set_defval()
1084 pdev->inieecmd = 0; in idt_set_defval()
1085 pdev->eeaddr = 0; in idt_set_defval()
1091 * idt_ee_match_id() - check whether the node belongs to compatible EEPROMs
1107 while (id->name[0]) { in idt_ee_match_id()
1108 if (strcmp(devname, id->name) == 0) in idt_ee_match_id()
1116 * idt_get_fw_data() - get IDT i2c-device parameters from device tree
1121 struct device *dev = &pdev->client->dev; in idt_get_fw_data()
1144 pdev->eesize = (u32)ee_id->driver_data; in idt_get_fw_data()
1151 pdev->inieecmd = 0; in idt_get_fw_data()
1152 pdev->eeaddr = EEPROM_DEF_ADDR << 1; in idt_get_fw_data()
1154 pdev->inieecmd = EEPROM_USA; in idt_get_fw_data()
1155 pdev->eeaddr = eeprom_addr << 1; in idt_get_fw_data()
1158 /* Check EEPROM 'read-only' flag */ in idt_get_fw_data()
1159 if (fwnode_property_read_bool(fwnode, "read-only")) in idt_get_fw_data()
1160 pdev->eero = true; in idt_get_fw_data()
1161 else /* if (!fwnode_property_read_bool(node, "read-only")) */ in idt_get_fw_data()
1162 pdev->eero = false; in idt_get_fw_data()
1165 pdev->eesize, pdev->eeaddr); in idt_get_fw_data()
1169 * idt_create_pdev() - create and init data structure of the driver
1170 * @client: i2c client of IDT PCIe-switch device
1177 pdev = devm_kmalloc(&client->dev, sizeof(struct idt_89hpesx_dev), in idt_create_pdev()
1180 return ERR_PTR(-ENOMEM); in idt_create_pdev()
1183 pdev->client = client; in idt_create_pdev()
1189 /* Initialize basic CSR CMD field - use full DWORD-sized r/w ops */ in idt_create_pdev()
1190 pdev->inicsrcmd = CSR_DWE; in idt_create_pdev()
1191 pdev->csr = CSR_DEF; in idt_create_pdev()
1194 if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_PEC)) { in idt_create_pdev()
1195 pdev->iniccode = CCODE_PEC; in idt_create_pdev()
1196 client->flags |= I2C_CLIENT_PEC; in idt_create_pdev()
1198 pdev->iniccode = 0; in idt_create_pdev()
1205 * idt_free_pdev() - free data structure of the driver
1211 i2c_set_clientdata(pdev->client, NULL); in idt_free_pdev()
1215 * idt_set_smbus_ops() - set supported SMBus operations
1221 struct i2c_adapter *adapter = pdev->client->adapter; in idt_set_smbus_ops()
1222 struct device *dev = &pdev->client->dev; in idt_set_smbus_ops()
1224 /* Check i2c adapter read functionality */ in idt_set_smbus_ops()
1227 pdev->smb_read = idt_smb_read_block; in idt_set_smbus_ops()
1228 dev_dbg(dev, "SMBus block-read op chosen"); in idt_set_smbus_ops()
1231 pdev->smb_read = idt_smb_read_i2c_block; in idt_set_smbus_ops()
1232 dev_dbg(dev, "SMBus i2c-block-read op chosen"); in idt_set_smbus_ops()
1237 pdev->smb_read = idt_smb_read_word; in idt_set_smbus_ops()
1241 pdev->smb_read = idt_smb_read_byte; in idt_set_smbus_ops()
1245 return -EPFNOSUPPORT; in idt_set_smbus_ops()
1248 /* Check i2c adapter write functionality */ in idt_set_smbus_ops()
1251 pdev->smb_write = idt_smb_write_block; in idt_set_smbus_ops()
1252 dev_dbg(dev, "SMBus block-write op chosen"); in idt_set_smbus_ops()
1255 pdev->smb_write = idt_smb_write_i2c_block; in idt_set_smbus_ops()
1256 dev_dbg(dev, "SMBus i2c-block-write op chosen"); in idt_set_smbus_ops()
1261 pdev->smb_write = idt_smb_write_word; in idt_set_smbus_ops()
1265 pdev->smb_write = idt_smb_write_byte; in idt_set_smbus_ops()
1269 return -EPFNOSUPPORT; in idt_set_smbus_ops()
1273 mutex_init(&pdev->smb_mtx); in idt_set_smbus_ops()
1279 * idt_check_dev() - check whether it's really IDT 89HPESx device
1281 * Return status of i2c adapter check operation
1285 struct device *dev = &pdev->client->dev; in idt_check_dev()
1299 return -ENODEV; in idt_check_dev()
1309 * idt_create_sysfs_files() - create sysfs attribute files
1315 struct device *dev = &pdev->client->dev; in idt_create_sysfs_files()
1319 if (pdev->eesize == 0) { in idt_create_sysfs_files()
1320 dev_dbg(dev, "Skip creating sysfs-files"); in idt_create_sysfs_files()
1325 pdev->ee_file = devm_kmalloc(dev, sizeof(*pdev->ee_file), GFP_KERNEL); in idt_create_sysfs_files()
1326 if (!pdev->ee_file) in idt_create_sysfs_files()
1327 return -ENOMEM; in idt_create_sysfs_files()
1330 memcpy(pdev->ee_file, &bin_attr_eeprom, sizeof(*pdev->ee_file)); in idt_create_sysfs_files()
1332 /* In case of read-only EEPROM get rid of write ability */ in idt_create_sysfs_files()
1333 if (pdev->eero) { in idt_create_sysfs_files()
1334 pdev->ee_file->attr.mode &= ~0200; in idt_create_sysfs_files()
1335 pdev->ee_file->write = NULL; in idt_create_sysfs_files()
1338 pdev->ee_file->size = pdev->eesize; in idt_create_sysfs_files()
1339 ret = sysfs_create_bin_file(&dev->kobj, pdev->ee_file); in idt_create_sysfs_files()
1341 dev_err(dev, "Failed to create EEPROM sysfs-node"); in idt_create_sysfs_files()
1349 * idt_remove_sysfs_files() - remove sysfs attribute files
1354 struct device *dev = &pdev->client->dev; in idt_remove_sysfs_files()
1357 if (pdev->eesize == 0) in idt_remove_sysfs_files()
1361 sysfs_remove_bin_file(&dev->kobj, pdev->ee_file); in idt_remove_sysfs_files()
1365 * idt_create_dbgfs_files() - create debugfs files
1371 struct i2c_client *cli = pdev->client; in idt_create_dbgfs_files()
1375 snprintf(fname, CSRNAME_LEN, "%d-%04hx", cli->adapter->nr, cli->addr); in idt_create_dbgfs_files()
1376 pdev->csr_dir = debugfs_create_dir(fname, csr_dbgdir); in idt_create_dbgfs_files()
1379 debugfs_create_file(cli->name, 0600, pdev->csr_dir, pdev, in idt_create_dbgfs_files()
1384 * idt_remove_dbgfs_files() - remove debugfs files
1389 /* Remove CSR directory and it sysfs-node */ in idt_remove_dbgfs_files()
1390 debugfs_remove_recursive(pdev->csr_dir); in idt_remove_dbgfs_files()
1394 * idt_probe() - IDT 89HPESx driver probe() callback method
1433 * idt_remove() - IDT 89HPESx driver remove() callback method
1452 * ee_ids - array of supported EEPROMs
1462 MODULE_DEVICE_TABLE(i2c, ee_ids);
1465 * idt_ids - supported IDT 89HPESx devices
1499 /* { "89hpes3t3", 0 }, // No SMBus-slave iface */
1502 /* { "89hpes4t4", 0 }, // No SMBus-slave iface */
1522 MODULE_DEVICE_TABLE(i2c, idt_ids);
1581 * idt_driver - IDT 89HPESx driver structure
1594 * idt_init() - IDT 89HPESx driver init() callback method
1602 /* Add new i2c-device driver */ in idt_init()
1608 * idt_exit() - IDT 89HPESx driver exit() callback method
1615 /* Unregister i2c-device driver */ in idt_exit()