aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm
diff options
context:
space:
mode:
authorPeter Huewe <peter.huewe@infineon.com>2013-03-04 09:41:46 -0500
committerKent Yoder <key@linux.vnet.ibm.com>2013-04-12 13:17:28 -0400
commitc61c86dd6e0a8037be73cf27212f389e46af60a4 (patch)
tree61714e9263eaf51758f54316effd0814a29eabf1 /drivers/char/tpm
parenteef8b6291987c059dacb07dd516d4ada0e3362af (diff)
tpm: Add support for new Infineon I2C TPM (SLB 9645 TT 1.2 I2C)
This driver adds support for Infineon's new SLB 9645 TT 1.2 I2C TPMs, which supports clockstretching, combined reads and a bus speed of up to 400khz. The device also has a new device id. The driver works now also fine with device trees, so you can instantiate your device by adding: + tpm { + compatible = "infineon,slb9645tt"; + reg = <0x20>; + }; for SLB 9645 devices or + tpm { + compatible = "infineon,slb9635tt"; + reg = <0x20>; + }; for SLB 9635 devices to your device tree. tpm_i2c_infineon is also retained as a compatible id as a fallback to slb9635 protocol. The driver was tested on Beaglebone. Signed-off-by: Peter Huewe <peter.huewe@infineon.com> Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
Diffstat (limited to 'drivers/char/tpm')
-rw-r--r--drivers/char/tpm/tpm_i2c_infineon.c137
1 files changed, 97 insertions, 40 deletions
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
index 8e47e2b99efc..bd9a2958dc39 100644
--- a/drivers/char/tpm/tpm_i2c_infineon.c
+++ b/drivers/char/tpm/tpm_i2c_infineon.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2012 Infineon Technologies 2 * Copyright (C) 2012,2013 Infineon Technologies
3 * 3 *
4 * Authors: 4 * Authors:
5 * Peter Huewe <peter.huewe@infineon.com> 5 * Peter Huewe <peter.huewe@infineon.com>
@@ -56,13 +56,21 @@
56#define TPM_TIMEOUT_US_HI (TPM_TIMEOUT_US_LOW + 2000) 56#define TPM_TIMEOUT_US_HI (TPM_TIMEOUT_US_LOW + 2000)
57 57
58/* expected value for DIDVID register */ 58/* expected value for DIDVID register */
59#define TPM_TIS_I2C_DID_VID 0x000b15d1L 59#define TPM_TIS_I2C_DID_VID_9635 0xd1150b00L
60#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L
61
62enum i2c_chip_type {
63 SLB9635,
64 SLB9645,
65 UNKNOWN,
66};
60 67
61/* Structure to store I2C TPM specific stuff */ 68/* Structure to store I2C TPM specific stuff */
62struct tpm_inf_dev { 69struct tpm_inf_dev {
63 struct i2c_client *client; 70 struct i2c_client *client;
64 u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ 71 u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */
65 struct tpm_chip *chip; 72 struct tpm_chip *chip;
73 enum i2c_chip_type chip_type;
66}; 74};
67 75
68static struct tpm_inf_dev tpm_dev; 76static struct tpm_inf_dev tpm_dev;
@@ -101,8 +109,9 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len)
101 .len = len, 109 .len = len,
102 .buf = buffer 110 .buf = buffer
103 }; 111 };
112 struct i2c_msg msgs[] = {msg1, msg2};
104 113
105 int rc; 114 int rc = 0;
106 int count; 115 int count;
107 116
108 /* Lock the adapter for the duration of the whole sequence. */ 117 /* Lock the adapter for the duration of the whole sequence. */
@@ -110,30 +119,49 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len)
110 return -EOPNOTSUPP; 119 return -EOPNOTSUPP;
111 i2c_lock_adapter(tpm_dev.client->adapter); 120 i2c_lock_adapter(tpm_dev.client->adapter);
112 121
113 for (count = 0; count < MAX_COUNT; count++) { 122 if (tpm_dev.chip_type == SLB9645) {
114 rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); 123 /* use a combined read for newer chips
115 if (rc > 0) 124 * unfortunately the smbus functions are not suitable due to
116 break; /* break here to skip sleep */ 125 * the 32 byte limit of the smbus.
117 126 * retries should usually not be needed, but are kept just to
118 usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); 127 * be on the safe side.
119 } 128 */
120 129 for (count = 0; count < MAX_COUNT; count++) {
121 if (rc <= 0) 130 rc = __i2c_transfer(tpm_dev.client->adapter, msgs, 2);
122 goto out; 131 if (rc > 0)
123 132 break; /* break here to skip sleep */
124 /* After the TPM has successfully received the register address it needs 133 usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
125 * some time, thus we're sleeping here again, before retrieving the data 134 }
126 */ 135 } else {
127 for (count = 0; count < MAX_COUNT; count++) { 136 /* slb9635 protocol should work in all cases */
128 usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); 137 for (count = 0; count < MAX_COUNT; count++) {
129 rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1); 138 rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
130 if (rc > 0) 139 if (rc > 0)
131 break; 140 break; /* break here to skip sleep */
141
142 usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
143 }
132 144
145 if (rc <= 0)
146 goto out;
147
148 /* After the TPM has successfully received the register address
149 * it needs some time, thus we're sleeping here again, before
150 * retrieving the data
151 */
152 for (count = 0; count < MAX_COUNT; count++) {
153 usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
154 rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1);
155 if (rc > 0)
156 break;
157 }
133 } 158 }
134 159
135out: 160out:
136 i2c_unlock_adapter(tpm_dev.client->adapter); 161 i2c_unlock_adapter(tpm_dev.client->adapter);
162 /* take care of 'guard time' */
163 usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
164
137 if (rc <= 0) 165 if (rc <= 0)
138 return -EIO; 166 return -EIO;
139 167
@@ -167,16 +195,19 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len,
167 /* 195 /*
168 * NOTE: We have to use these special mechanisms here and unfortunately 196 * NOTE: We have to use these special mechanisms here and unfortunately
169 * cannot rely on the standard behavior of i2c_transfer. 197 * cannot rely on the standard behavior of i2c_transfer.
198 * Even for newer chips the smbus functions are not
199 * suitable due to the 32 byte limit of the smbus.
170 */ 200 */
171 for (count = 0; count < max_count; count++) { 201 for (count = 0; count < max_count; count++) {
172 rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); 202 rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
173 if (rc > 0) 203 if (rc > 0)
174 break; 204 break;
175
176 usleep_range(sleep_low, sleep_hi); 205 usleep_range(sleep_low, sleep_hi);
177 } 206 }
178 207
179 i2c_unlock_adapter(tpm_dev.client->adapter); 208 i2c_unlock_adapter(tpm_dev.client->adapter);
209 /* take care of 'guard time' */
210 usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
180 if (rc <= 0) 211 if (rc <= 0)
181 return -EIO; 212 return -EIO;
182 213
@@ -296,11 +327,18 @@ static int request_locality(struct tpm_chip *chip, int loc)
296static u8 tpm_tis_i2c_status(struct tpm_chip *chip) 327static u8 tpm_tis_i2c_status(struct tpm_chip *chip)
297{ 328{
298 /* NOTE: since I2C read may fail, return 0 in this case --> time-out */ 329 /* NOTE: since I2C read may fail, return 0 in this case --> time-out */
299 u8 buf; 330 u8 buf = 0xFF;
300 if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) 331 u8 i = 0;
301 return 0; 332
302 else 333 do {
303 return buf; 334 if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0)
335 return 0;
336
337 i++;
338 /* if locallity is set STS should not be 0xFF */
339 } while ((buf == 0xFF) && i < 10);
340
341 return buf;
304} 342}
305 343
306static void tpm_tis_i2c_ready(struct tpm_chip *chip) 344static void tpm_tis_i2c_ready(struct tpm_chip *chip)
@@ -341,7 +379,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
341 379
342 /* check current status */ 380 /* check current status */
343 *status = tpm_tis_i2c_status(chip); 381 *status = tpm_tis_i2c_status(chip);
344 if ((*status & mask) == mask) 382 if ((*status != 0xFF) && (*status & mask) == mask)
345 return 0; 383 return 0;
346 384
347 stop = jiffies + timeout; 385 stop = jiffies + timeout;
@@ -385,7 +423,6 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
385 /* avoid endless loop in case of broken HW */ 423 /* avoid endless loop in case of broken HW */
386 if (retries > MAX_COUNT_LONG) 424 if (retries > MAX_COUNT_LONG)
387 return -EIO; 425 return -EIO;
388
389 } 426 }
390 return size; 427 return size;
391} 428}
@@ -493,7 +530,6 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
493 rc = -EIO; 530 rc = -EIO;
494 goto out_err; 531 goto out_err;
495 } 532 }
496
497 } 533 }
498 534
499 /* write last byte */ 535 /* write last byte */
@@ -581,6 +617,7 @@ static int tpm_tis_i2c_init(struct device *dev)
581 617
582 chip = tpm_register_hardware(dev, &tpm_tis_i2c); 618 chip = tpm_register_hardware(dev, &tpm_tis_i2c);
583 if (!chip) { 619 if (!chip) {
620 dev_err(dev, "could not register hardware\n");
584 rc = -ENODEV; 621 rc = -ENODEV;
585 goto out_err; 622 goto out_err;
586 } 623 }
@@ -595,20 +632,24 @@ static int tpm_tis_i2c_init(struct device *dev)
595 chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); 632 chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
596 633
597 if (request_locality(chip, 0) != 0) { 634 if (request_locality(chip, 0) != 0) {
635 dev_err(dev, "could not request locality\n");
598 rc = -ENODEV; 636 rc = -ENODEV;
599 goto out_vendor; 637 goto out_vendor;
600 } 638 }
601 639
602 /* read four bytes from DID_VID register */ 640 /* read four bytes from DID_VID register */
603 if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) { 641 if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) {
642 dev_err(dev, "could not read vendor id\n");
604 rc = -EIO; 643 rc = -EIO;
605 goto out_release; 644 goto out_release;
606 } 645 }
607 646
608 /* create DID_VID register value, after swapping to little-endian */ 647 if (vendor == TPM_TIS_I2C_DID_VID_9645) {
609 vendor = be32_to_cpu((__be32) vendor); 648 tpm_dev.chip_type = SLB9645;
610 649 } else if (vendor == TPM_TIS_I2C_DID_VID_9635) {
611 if (vendor != TPM_TIS_I2C_DID_VID) { 650 tpm_dev.chip_type = SLB9635;
651 } else {
652 dev_err(dev, "vendor id did not match! ID was %08x\n", vendor);
612 rc = -ENODEV; 653 rc = -ENODEV;
613 goto out_release; 654 goto out_release;
614 } 655 }
@@ -644,22 +685,38 @@ out_err:
644 685
645static const struct i2c_device_id tpm_tis_i2c_table[] = { 686static const struct i2c_device_id tpm_tis_i2c_table[] = {
646 {"tpm_i2c_infineon", 0}, 687 {"tpm_i2c_infineon", 0},
688 {"slb9635tt", 0},
689 {"slb9645tt", 1},
647 {}, 690 {},
648}; 691};
649 692
650MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table); 693MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
694
695#ifdef CONFIG_OF
696static const struct of_device_id tpm_tis_i2c_of_match[] = {
697 { .compatible = "infineon,tpm_i2c_infineon", .data = (void *)0 },
698 { .compatible = "infineon,slb9635tt", .data = (void *)0 },
699 { .compatible = "infineon,slb9645tt", .data = (void *)1 },
700 {},
701};
702MODULE_DEVICE_TABLE(of, tpm_tis_i2c_of_match);
703#endif
704
651static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume); 705static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
652 706
653static int tpm_tis_i2c_probe(struct i2c_client *client, 707static int tpm_tis_i2c_probe(struct i2c_client *client,
654 const struct i2c_device_id *id) 708 const struct i2c_device_id *id)
655{ 709{
656 int rc; 710 int rc;
657 if (tpm_dev.client != NULL) 711 struct device *dev = &(client->dev);
712
713 if (tpm_dev.client != NULL) {
714 dev_err(dev, "This driver only supports one client at a time\n");
658 return -EBUSY; /* We only support one client */ 715 return -EBUSY; /* We only support one client */
716 }
659 717
660 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 718 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
661 dev_err(&client->dev, 719 dev_err(dev, "no algorithms associated to the i2c bus\n");
662 "no algorithms associated to the i2c bus\n");
663 return -ENODEV; 720 return -ENODEV;
664 } 721 }
665 722
@@ -695,7 +752,6 @@ static int tpm_tis_i2c_remove(struct i2c_client *client)
695} 752}
696 753
697static struct i2c_driver tpm_tis_i2c_driver = { 754static struct i2c_driver tpm_tis_i2c_driver = {
698
699 .id_table = tpm_tis_i2c_table, 755 .id_table = tpm_tis_i2c_table,
700 .probe = tpm_tis_i2c_probe, 756 .probe = tpm_tis_i2c_probe,
701 .remove = tpm_tis_i2c_remove, 757 .remove = tpm_tis_i2c_remove,
@@ -703,11 +759,12 @@ static struct i2c_driver tpm_tis_i2c_driver = {
703 .name = "tpm_i2c_infineon", 759 .name = "tpm_i2c_infineon",
704 .owner = THIS_MODULE, 760 .owner = THIS_MODULE,
705 .pm = &tpm_tis_i2c_ops, 761 .pm = &tpm_tis_i2c_ops,
762 .of_match_table = of_match_ptr(tpm_tis_i2c_of_match),
706 }, 763 },
707}; 764};
708 765
709module_i2c_driver(tpm_tis_i2c_driver); 766module_i2c_driver(tpm_tis_i2c_driver);
710MODULE_AUTHOR("Peter Huewe <peter.huewe@infineon.com>"); 767MODULE_AUTHOR("Peter Huewe <peter.huewe@infineon.com>");
711MODULE_DESCRIPTION("TPM TIS I2C Infineon Driver"); 768MODULE_DESCRIPTION("TPM TIS I2C Infineon Driver");
712MODULE_VERSION("2.1.5"); 769MODULE_VERSION("2.2.0");
713MODULE_LICENSE("GPL"); 770MODULE_LICENSE("GPL");