Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/char/tpm/tpm_infineon.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Description:
4
* Device Driver for the Infineon Technologies
5
* SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module
6
* Specifications at www.trustedcomputinggroup.org
7
*
8
* Copyright (C) 2005, Marcel Selhorst <[email protected]>
9
* Sirrix AG - security technologies <[email protected]> and
10
* Applied Data Security Group, Ruhr-University Bochum, Germany
11
* Project-Homepage: http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/
12
*/
13
14
#include <linux/init.h>
15
#include <linux/pnp.h>
16
#include "tpm.h"
17
18
/* Infineon specific definitions */
19
/* maximum number of WTX-packages */
20
#define TPM_MAX_WTX_PACKAGES 50
21
/* msleep-Time for WTX-packages */
22
#define TPM_WTX_MSLEEP_TIME 20
23
/* msleep-Time --> Interval to check status register */
24
#define TPM_MSLEEP_TIME 3
25
/* gives number of max. msleep()-calls before throwing timeout */
26
#define TPM_MAX_TRIES 5000
27
#define TPM_INFINEON_DEV_VEN_VALUE 0x15D1
28
29
#define TPM_INF_IO_PORT 0x0
30
#define TPM_INF_IO_MEM 0x1
31
32
#define TPM_INF_ADDR 0x0
33
#define TPM_INF_DATA 0x1
34
35
struct tpm_inf_dev {
36
int iotype;
37
38
void __iomem *mem_base; /* MMIO ioremap'd addr */
39
unsigned long map_base; /* phys MMIO base */
40
unsigned long map_size; /* MMIO region size */
41
unsigned int index_off; /* index register offset */
42
43
unsigned int data_regs; /* Data registers */
44
unsigned int data_size;
45
46
unsigned int config_port; /* IO Port config index reg */
47
unsigned int config_size;
48
};
49
50
static struct tpm_inf_dev tpm_dev;
51
52
static inline void tpm_data_out(unsigned char data, unsigned char offset)
53
{
54
#ifdef CONFIG_HAS_IOPORT
55
if (tpm_dev.iotype == TPM_INF_IO_PORT)
56
outb(data, tpm_dev.data_regs + offset);
57
else
58
#endif
59
writeb(data, tpm_dev.mem_base + tpm_dev.data_regs + offset);
60
}
61
62
static inline unsigned char tpm_data_in(unsigned char offset)
63
{
64
#ifdef CONFIG_HAS_IOPORT
65
if (tpm_dev.iotype == TPM_INF_IO_PORT)
66
return inb(tpm_dev.data_regs + offset);
67
#endif
68
return readb(tpm_dev.mem_base + tpm_dev.data_regs + offset);
69
}
70
71
static inline void tpm_config_out(unsigned char data, unsigned char offset)
72
{
73
#ifdef CONFIG_HAS_IOPORT
74
if (tpm_dev.iotype == TPM_INF_IO_PORT)
75
outb(data, tpm_dev.config_port + offset);
76
else
77
#endif
78
writeb(data, tpm_dev.mem_base + tpm_dev.index_off + offset);
79
}
80
81
static inline unsigned char tpm_config_in(unsigned char offset)
82
{
83
#ifdef CONFIG_HAS_IOPORT
84
if (tpm_dev.iotype == TPM_INF_IO_PORT)
85
return inb(tpm_dev.config_port + offset);
86
#endif
87
return readb(tpm_dev.mem_base + tpm_dev.index_off + offset);
88
}
89
90
/* TPM header definitions */
91
enum infineon_tpm_header {
92
TPM_VL_VER = 0x01,
93
TPM_VL_CHANNEL_CONTROL = 0x07,
94
TPM_VL_CHANNEL_PERSONALISATION = 0x0A,
95
TPM_VL_CHANNEL_TPM = 0x0B,
96
TPM_VL_CONTROL = 0x00,
97
TPM_INF_NAK = 0x15,
98
TPM_CTRL_WTX = 0x10,
99
TPM_CTRL_WTX_ABORT = 0x18,
100
TPM_CTRL_WTX_ABORT_ACK = 0x18,
101
TPM_CTRL_ERROR = 0x20,
102
TPM_CTRL_CHAININGACK = 0x40,
103
TPM_CTRL_CHAINING = 0x80,
104
TPM_CTRL_DATA = 0x04,
105
TPM_CTRL_DATA_CHA = 0x84,
106
TPM_CTRL_DATA_CHA_ACK = 0xC4
107
};
108
109
enum infineon_tpm_register {
110
WRFIFO = 0x00,
111
RDFIFO = 0x01,
112
STAT = 0x02,
113
CMD = 0x03
114
};
115
116
enum infineon_tpm_command_bits {
117
CMD_DIS = 0x00,
118
CMD_LP = 0x01,
119
CMD_RES = 0x02,
120
CMD_IRQC = 0x06
121
};
122
123
enum infineon_tpm_status_bits {
124
STAT_XFE = 0x00,
125
STAT_LPA = 0x01,
126
STAT_FOK = 0x02,
127
STAT_TOK = 0x03,
128
STAT_IRQA = 0x06,
129
STAT_RDA = 0x07
130
};
131
132
/* some outgoing values */
133
enum infineon_tpm_values {
134
CHIP_ID1 = 0x20,
135
CHIP_ID2 = 0x21,
136
TPM_DAR = 0x30,
137
RESET_LP_IRQC_DISABLE = 0x41,
138
ENABLE_REGISTER_PAIR = 0x55,
139
IOLIMH = 0x60,
140
IOLIML = 0x61,
141
DISABLE_REGISTER_PAIR = 0xAA,
142
IDVENL = 0xF1,
143
IDVENH = 0xF2,
144
IDPDL = 0xF3,
145
IDPDH = 0xF4
146
};
147
148
static int number_of_wtx;
149
150
static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
151
{
152
int status;
153
int check = 0;
154
int i;
155
156
if (clear_wrfifo) {
157
for (i = 0; i < 4096; i++) {
158
status = tpm_data_in(WRFIFO);
159
if (status == 0xff) {
160
if (check == 5)
161
break;
162
else
163
check++;
164
}
165
}
166
}
167
/* Note: The values which are currently in the FIFO of the TPM
168
are thrown away since there is no usage for them. Usually,
169
this has nothing to say, since the TPM will give its answer
170
immediately or will be aborted anyway, so the data here is
171
usually garbage and useless.
172
We have to clean this, because the next communication with
173
the TPM would be rubbish, if there is still some old data
174
in the Read FIFO.
175
*/
176
i = 0;
177
do {
178
status = tpm_data_in(RDFIFO);
179
status = tpm_data_in(STAT);
180
i++;
181
if (i == TPM_MAX_TRIES)
182
return -EIO;
183
} while ((status & (1 << STAT_RDA)) != 0);
184
return 0;
185
}
186
187
static int wait(struct tpm_chip *chip, int wait_for_bit)
188
{
189
int status;
190
int i;
191
for (i = 0; i < TPM_MAX_TRIES; i++) {
192
status = tpm_data_in(STAT);
193
/* check the status-register if wait_for_bit is set */
194
if (status & 1 << wait_for_bit)
195
break;
196
tpm_msleep(TPM_MSLEEP_TIME);
197
}
198
if (i == TPM_MAX_TRIES) { /* timeout occurs */
199
if (wait_for_bit == STAT_XFE)
200
dev_err(&chip->dev, "Timeout in wait(STAT_XFE)\n");
201
if (wait_for_bit == STAT_RDA)
202
dev_err(&chip->dev, "Timeout in wait(STAT_RDA)\n");
203
return -EIO;
204
}
205
return 0;
206
};
207
208
static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
209
{
210
wait(chip, STAT_XFE);
211
tpm_data_out(sendbyte, WRFIFO);
212
}
213
214
/* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
215
calculation time, it sends a WTX-package, which has to be acknowledged
216
or aborted. This usually occurs if you are hammering the TPM with key
217
creation. Set the maximum number of WTX-packages in the definitions
218
above, if the number is reached, the waiting-time will be denied
219
and the TPM command has to be resend.
220
*/
221
222
static void tpm_wtx(struct tpm_chip *chip)
223
{
224
number_of_wtx++;
225
dev_info(&chip->dev, "Granting WTX (%02d / %02d)\n",
226
number_of_wtx, TPM_MAX_WTX_PACKAGES);
227
wait_and_send(chip, TPM_VL_VER);
228
wait_and_send(chip, TPM_CTRL_WTX);
229
wait_and_send(chip, 0x00);
230
wait_and_send(chip, 0x00);
231
tpm_msleep(TPM_WTX_MSLEEP_TIME);
232
}
233
234
static void tpm_wtx_abort(struct tpm_chip *chip)
235
{
236
dev_info(&chip->dev, "Aborting WTX\n");
237
wait_and_send(chip, TPM_VL_VER);
238
wait_and_send(chip, TPM_CTRL_WTX_ABORT);
239
wait_and_send(chip, 0x00);
240
wait_and_send(chip, 0x00);
241
number_of_wtx = 0;
242
tpm_msleep(TPM_WTX_MSLEEP_TIME);
243
}
244
245
static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
246
{
247
int i;
248
int ret;
249
u32 size = 0;
250
number_of_wtx = 0;
251
252
recv_begin:
253
/* start receiving header */
254
for (i = 0; i < 4; i++) {
255
ret = wait(chip, STAT_RDA);
256
if (ret)
257
return -EIO;
258
buf[i] = tpm_data_in(RDFIFO);
259
}
260
261
if (buf[0] != TPM_VL_VER) {
262
dev_err(&chip->dev,
263
"Wrong transport protocol implementation!\n");
264
return -EIO;
265
}
266
267
if (buf[1] == TPM_CTRL_DATA) {
268
/* size of the data received */
269
size = ((buf[2] << 8) | buf[3]);
270
271
for (i = 0; i < size; i++) {
272
wait(chip, STAT_RDA);
273
buf[i] = tpm_data_in(RDFIFO);
274
}
275
276
if ((size == 0x6D00) && (buf[1] == 0x80)) {
277
dev_err(&chip->dev, "Error handling on vendor layer!\n");
278
return -EIO;
279
}
280
281
for (i = 0; i < size; i++)
282
buf[i] = buf[i + 6];
283
284
size = size - 6;
285
return size;
286
}
287
288
if (buf[1] == TPM_CTRL_WTX) {
289
dev_info(&chip->dev, "WTX-package received\n");
290
if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
291
tpm_wtx(chip);
292
goto recv_begin;
293
} else {
294
tpm_wtx_abort(chip);
295
goto recv_begin;
296
}
297
}
298
299
if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
300
dev_info(&chip->dev, "WTX-abort acknowledged\n");
301
return size;
302
}
303
304
if (buf[1] == TPM_CTRL_ERROR) {
305
dev_err(&chip->dev, "ERROR-package received:\n");
306
if (buf[4] == TPM_INF_NAK)
307
dev_err(&chip->dev,
308
"-> Negative acknowledgement"
309
" - retransmit command!\n");
310
return -EIO;
311
}
312
return -EIO;
313
}
314
315
static int tpm_inf_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz,
316
size_t count)
317
{
318
int i;
319
int ret;
320
u8 count_high, count_low, count_4, count_3, count_2, count_1;
321
322
/* Disabling Reset, LP and IRQC */
323
tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
324
325
ret = empty_fifo(chip, 1);
326
if (ret) {
327
dev_err(&chip->dev, "Timeout while clearing FIFO\n");
328
return -EIO;
329
}
330
331
ret = wait(chip, STAT_XFE);
332
if (ret)
333
return -EIO;
334
335
count_4 = (count & 0xff000000) >> 24;
336
count_3 = (count & 0x00ff0000) >> 16;
337
count_2 = (count & 0x0000ff00) >> 8;
338
count_1 = (count & 0x000000ff);
339
count_high = ((count + 6) & 0xffffff00) >> 8;
340
count_low = ((count + 6) & 0x000000ff);
341
342
/* Sending Header */
343
wait_and_send(chip, TPM_VL_VER);
344
wait_and_send(chip, TPM_CTRL_DATA);
345
wait_and_send(chip, count_high);
346
wait_and_send(chip, count_low);
347
348
/* Sending Data Header */
349
wait_and_send(chip, TPM_VL_VER);
350
wait_and_send(chip, TPM_VL_CHANNEL_TPM);
351
wait_and_send(chip, count_4);
352
wait_and_send(chip, count_3);
353
wait_and_send(chip, count_2);
354
wait_and_send(chip, count_1);
355
356
/* Sending Data */
357
for (i = 0; i < count; i++) {
358
wait_and_send(chip, buf[i]);
359
}
360
return 0;
361
}
362
363
static void tpm_inf_cancel(struct tpm_chip *chip)
364
{
365
/*
366
Since we are using the legacy mode to communicate
367
with the TPM, we have no cancel functions, but have
368
a workaround for interrupting the TPM through WTX.
369
*/
370
}
371
372
static u8 tpm_inf_status(struct tpm_chip *chip)
373
{
374
return tpm_data_in(STAT);
375
}
376
377
static const struct tpm_class_ops tpm_inf = {
378
.recv = tpm_inf_recv,
379
.send = tpm_inf_send,
380
.cancel = tpm_inf_cancel,
381
.status = tpm_inf_status,
382
.req_complete_mask = 0,
383
.req_complete_val = 0,
384
};
385
386
static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
387
/* Infineon TPMs */
388
{"IFX0101", 0},
389
{"IFX0102", 0},
390
{"", 0}
391
};
392
393
MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
394
395
static int tpm_inf_pnp_probe(struct pnp_dev *dev,
396
const struct pnp_device_id *dev_id)
397
{
398
int rc = 0;
399
u8 iol, ioh;
400
int vendorid[2];
401
int version[2];
402
int productid[2];
403
const char *chipname;
404
struct tpm_chip *chip;
405
406
/* read IO-ports through PnP */
407
if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
408
!(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
409
410
tpm_dev.iotype = TPM_INF_IO_PORT;
411
412
tpm_dev.config_port = pnp_port_start(dev, 0);
413
tpm_dev.config_size = pnp_port_len(dev, 0);
414
tpm_dev.data_regs = pnp_port_start(dev, 1);
415
tpm_dev.data_size = pnp_port_len(dev, 1);
416
if ((tpm_dev.data_size < 4) || (tpm_dev.config_size < 2)) {
417
rc = -EINVAL;
418
goto err_last;
419
}
420
dev_info(&dev->dev, "Found %s with ID %s\n",
421
dev->name, dev_id->id);
422
if (!((tpm_dev.data_regs >> 8) & 0xff)) {
423
rc = -EINVAL;
424
goto err_last;
425
}
426
/* publish my base address and request region */
427
if (request_region(tpm_dev.data_regs, tpm_dev.data_size,
428
"tpm_infineon0") == NULL) {
429
rc = -EINVAL;
430
goto err_last;
431
}
432
if (request_region(tpm_dev.config_port, tpm_dev.config_size,
433
"tpm_infineon0") == NULL) {
434
release_region(tpm_dev.data_regs, tpm_dev.data_size);
435
rc = -EINVAL;
436
goto err_last;
437
}
438
} else if (pnp_mem_valid(dev, 0) &&
439
!(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) {
440
441
tpm_dev.iotype = TPM_INF_IO_MEM;
442
443
tpm_dev.map_base = pnp_mem_start(dev, 0);
444
tpm_dev.map_size = pnp_mem_len(dev, 0);
445
446
dev_info(&dev->dev, "Found %s with ID %s\n",
447
dev->name, dev_id->id);
448
449
/* publish my base address and request region */
450
if (request_mem_region(tpm_dev.map_base, tpm_dev.map_size,
451
"tpm_infineon0") == NULL) {
452
rc = -EINVAL;
453
goto err_last;
454
}
455
456
tpm_dev.mem_base = ioremap(tpm_dev.map_base, tpm_dev.map_size);
457
if (tpm_dev.mem_base == NULL) {
458
release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
459
rc = -EINVAL;
460
goto err_last;
461
}
462
463
/*
464
* The only known MMIO based Infineon TPM system provides
465
* a single large mem region with the device config
466
* registers at the default TPM_ADDR. The data registers
467
* seem like they could be placed anywhere within the MMIO
468
* region, but lets just put them at zero offset.
469
*/
470
tpm_dev.index_off = TPM_ADDR;
471
tpm_dev.data_regs = 0x0;
472
} else {
473
rc = -EINVAL;
474
goto err_last;
475
}
476
477
/* query chip for its vendor, its version number a.s.o. */
478
tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
479
tpm_config_out(IDVENL, TPM_INF_ADDR);
480
vendorid[1] = tpm_config_in(TPM_INF_DATA);
481
tpm_config_out(IDVENH, TPM_INF_ADDR);
482
vendorid[0] = tpm_config_in(TPM_INF_DATA);
483
tpm_config_out(IDPDL, TPM_INF_ADDR);
484
productid[1] = tpm_config_in(TPM_INF_DATA);
485
tpm_config_out(IDPDH, TPM_INF_ADDR);
486
productid[0] = tpm_config_in(TPM_INF_DATA);
487
tpm_config_out(CHIP_ID1, TPM_INF_ADDR);
488
version[1] = tpm_config_in(TPM_INF_DATA);
489
tpm_config_out(CHIP_ID2, TPM_INF_ADDR);
490
version[0] = tpm_config_in(TPM_INF_DATA);
491
492
switch ((productid[0] << 8) | productid[1]) {
493
case 6:
494
chipname = " (SLD 9630 TT 1.1)";
495
break;
496
case 11:
497
chipname = " (SLB 9635 TT 1.2)";
498
break;
499
default:
500
chipname = " (unknown chip)";
501
break;
502
}
503
504
if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
505
506
/* configure TPM with IO-ports */
507
tpm_config_out(IOLIMH, TPM_INF_ADDR);
508
tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
509
tpm_config_out(IOLIML, TPM_INF_ADDR);
510
tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
511
512
/* control if IO-ports are set correctly */
513
tpm_config_out(IOLIMH, TPM_INF_ADDR);
514
ioh = tpm_config_in(TPM_INF_DATA);
515
tpm_config_out(IOLIML, TPM_INF_ADDR);
516
iol = tpm_config_in(TPM_INF_DATA);
517
518
if ((ioh << 8 | iol) != tpm_dev.data_regs) {
519
dev_err(&dev->dev,
520
"Could not set IO-data registers to 0x%x\n",
521
tpm_dev.data_regs);
522
rc = -EIO;
523
goto err_release_region;
524
}
525
526
/* activate register */
527
tpm_config_out(TPM_DAR, TPM_INF_ADDR);
528
tpm_config_out(0x01, TPM_INF_DATA);
529
tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
530
531
/* disable RESET, LP and IRQC */
532
tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
533
534
/* Finally, we're done, print some infos */
535
dev_info(&dev->dev, "TPM found: "
536
"config base 0x%lx, "
537
"data base 0x%lx, "
538
"chip version 0x%02x%02x, "
539
"vendor id 0x%x%x (Infineon), "
540
"product id 0x%02x%02x"
541
"%s\n",
542
tpm_dev.iotype == TPM_INF_IO_PORT ?
543
tpm_dev.config_port :
544
tpm_dev.map_base + tpm_dev.index_off,
545
tpm_dev.iotype == TPM_INF_IO_PORT ?
546
tpm_dev.data_regs :
547
tpm_dev.map_base + tpm_dev.data_regs,
548
version[0], version[1],
549
vendorid[0], vendorid[1],
550
productid[0], productid[1], chipname);
551
552
chip = tpmm_chip_alloc(&dev->dev, &tpm_inf);
553
if (IS_ERR(chip)) {
554
rc = PTR_ERR(chip);
555
goto err_release_region;
556
}
557
558
rc = tpm_chip_register(chip);
559
if (rc)
560
goto err_release_region;
561
562
return 0;
563
} else {
564
rc = -ENODEV;
565
goto err_release_region;
566
}
567
568
err_release_region:
569
if (tpm_dev.iotype == TPM_INF_IO_PORT) {
570
release_region(tpm_dev.data_regs, tpm_dev.data_size);
571
release_region(tpm_dev.config_port, tpm_dev.config_size);
572
} else {
573
iounmap(tpm_dev.mem_base);
574
release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
575
}
576
577
err_last:
578
return rc;
579
}
580
581
static void tpm_inf_pnp_remove(struct pnp_dev *dev)
582
{
583
struct tpm_chip *chip = pnp_get_drvdata(dev);
584
585
tpm_chip_unregister(chip);
586
587
if (tpm_dev.iotype == TPM_INF_IO_PORT) {
588
release_region(tpm_dev.data_regs, tpm_dev.data_size);
589
release_region(tpm_dev.config_port,
590
tpm_dev.config_size);
591
} else {
592
iounmap(tpm_dev.mem_base);
593
release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
594
}
595
}
596
597
#ifdef CONFIG_PM_SLEEP
598
static int tpm_inf_resume(struct device *dev)
599
{
600
/* Re-configure TPM after suspending */
601
tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
602
tpm_config_out(IOLIMH, TPM_INF_ADDR);
603
tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
604
tpm_config_out(IOLIML, TPM_INF_ADDR);
605
tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
606
/* activate register */
607
tpm_config_out(TPM_DAR, TPM_INF_ADDR);
608
tpm_config_out(0x01, TPM_INF_DATA);
609
tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
610
/* disable RESET, LP and IRQC */
611
tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
612
return tpm_pm_resume(dev);
613
}
614
#endif
615
static SIMPLE_DEV_PM_OPS(tpm_inf_pm, tpm_pm_suspend, tpm_inf_resume);
616
617
static struct pnp_driver tpm_inf_pnp_driver = {
618
.name = "tpm_inf_pnp",
619
.id_table = tpm_inf_pnp_tbl,
620
.probe = tpm_inf_pnp_probe,
621
.remove = tpm_inf_pnp_remove,
622
.driver = {
623
.pm = &tpm_inf_pm,
624
}
625
};
626
627
module_pnp_driver(tpm_inf_pnp_driver);
628
629
MODULE_AUTHOR("Marcel Selhorst <[email protected]>");
630
MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
631
MODULE_VERSION("1.9.2");
632
MODULE_LICENSE("GPL");
633
634