]>
Commit | Line | Data |
---|---|---|
41a5e1cf CR |
1 | /* |
2 | * Copyright (C) 2005, 2006 IBM Corporation | |
3 | * Copyright (C) 2014, 2015 Intel Corporation | |
4 | * | |
5 | * Authors: | |
6 | * Leendert van Doorn <leendert@watson.ibm.com> | |
7 | * Kylene Hall <kjhall@us.ibm.com> | |
8 | * | |
9 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | |
10 | * | |
11 | * Device driver for TCG/TCPA TPM (trusted platform module). | |
12 | * Specifications at www.trustedcomputinggroup.org | |
13 | * | |
14 | * This device driver implements the TPM interface as defined in | |
15 | * the TCG TPM Interface Spec version 1.2, revision 1.0. | |
16 | * | |
17 | * This program is free software; you can redistribute it and/or | |
18 | * modify it under the terms of the GNU General Public License as | |
19 | * published by the Free Software Foundation, version 2 of the | |
20 | * License. | |
21 | */ | |
22 | #include <linux/init.h> | |
23 | #include <linux/module.h> | |
24 | #include <linux/moduleparam.h> | |
25 | #include <linux/pnp.h> | |
26 | #include <linux/slab.h> | |
27 | #include <linux/interrupt.h> | |
28 | #include <linux/wait.h> | |
29 | #include <linux/acpi.h> | |
30 | #include <linux/freezer.h> | |
31 | #include "tpm.h" | |
32 | #include "tpm_tis_core.h" | |
33 | ||
34 | /* Before we attempt to access the TPM we must see that the valid bit is set. | |
35 | * The specification says that this bit is 0 at reset and remains 0 until the | |
36 | * 'TPM has gone through its self test and initialization and has established | |
37 | * correct values in the other bits.' | |
38 | */ | |
39 | static int wait_startup(struct tpm_chip *chip, int l) | |
40 | { | |
41 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
42 | unsigned long stop = jiffies + chip->timeout_a; | |
43 | ||
44 | do { | |
45 | int rc; | |
46 | u8 access; | |
47 | ||
48 | rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); | |
49 | if (rc < 0) | |
50 | return rc; | |
51 | ||
52 | if (access & TPM_ACCESS_VALID) | |
53 | return 0; | |
9f3fc7bc | 54 | tpm_msleep(TPM_TIMEOUT); |
41a5e1cf CR |
55 | } while (time_before(jiffies, stop)); |
56 | return -1; | |
57 | } | |
58 | ||
84d25940 | 59 | static bool check_locality(struct tpm_chip *chip, int l) |
41a5e1cf CR |
60 | { |
61 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
62 | int rc; | |
63 | u8 access; | |
64 | ||
65 | rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); | |
66 | if (rc < 0) | |
84d25940 | 67 | return false; |
41a5e1cf CR |
68 | |
69 | if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == | |
84d25940 JS |
70 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { |
71 | priv->locality = l; | |
72 | return true; | |
73 | } | |
41a5e1cf | 74 | |
84d25940 | 75 | return false; |
41a5e1cf CR |
76 | } |
77 | ||
e6aef069 | 78 | static void release_locality(struct tpm_chip *chip, int l) |
41a5e1cf CR |
79 | { |
80 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
41a5e1cf | 81 | |
e6aef069 | 82 | tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); |
41a5e1cf CR |
83 | } |
84 | ||
85 | static int request_locality(struct tpm_chip *chip, int l) | |
86 | { | |
87 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
88 | unsigned long stop, timeout; | |
89 | long rc; | |
90 | ||
84d25940 | 91 | if (check_locality(chip, l)) |
41a5e1cf CR |
92 | return l; |
93 | ||
94 | rc = tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_REQUEST_USE); | |
95 | if (rc < 0) | |
96 | return rc; | |
97 | ||
98 | stop = jiffies + chip->timeout_a; | |
99 | ||
100 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { | |
101 | again: | |
102 | timeout = stop - jiffies; | |
103 | if ((long)timeout <= 0) | |
104 | return -1; | |
105 | rc = wait_event_interruptible_timeout(priv->int_queue, | |
106 | (check_locality | |
84d25940 | 107 | (chip, l)), |
41a5e1cf CR |
108 | timeout); |
109 | if (rc > 0) | |
110 | return l; | |
111 | if (rc == -ERESTARTSYS && freezing(current)) { | |
112 | clear_thread_flag(TIF_SIGPENDING); | |
113 | goto again; | |
114 | } | |
115 | } else { | |
116 | /* wait for burstcount */ | |
117 | do { | |
84d25940 | 118 | if (check_locality(chip, l)) |
41a5e1cf | 119 | return l; |
9f3fc7bc | 120 | tpm_msleep(TPM_TIMEOUT); |
41a5e1cf CR |
121 | } while (time_before(jiffies, stop)); |
122 | } | |
123 | return -1; | |
124 | } | |
125 | ||
126 | static u8 tpm_tis_status(struct tpm_chip *chip) | |
127 | { | |
128 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
129 | int rc; | |
130 | u8 status; | |
131 | ||
132 | rc = tpm_tis_read8(priv, TPM_STS(priv->locality), &status); | |
133 | if (rc < 0) | |
134 | return 0; | |
135 | ||
136 | return status; | |
137 | } | |
138 | ||
139 | static void tpm_tis_ready(struct tpm_chip *chip) | |
140 | { | |
141 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
142 | ||
143 | /* this causes the current command to be aborted */ | |
144 | tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_COMMAND_READY); | |
145 | } | |
146 | ||
147 | static int get_burstcount(struct tpm_chip *chip) | |
148 | { | |
149 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
150 | unsigned long stop; | |
151 | int burstcnt, rc; | |
9754d45e | 152 | u32 value; |
41a5e1cf CR |
153 | |
154 | /* wait for burstcount */ | |
302a6ad7 AS |
155 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
156 | stop = jiffies + chip->timeout_a; | |
157 | else | |
158 | stop = jiffies + chip->timeout_d; | |
41a5e1cf | 159 | do { |
9754d45e | 160 | rc = tpm_tis_read32(priv, TPM_STS(priv->locality), &value); |
41a5e1cf CR |
161 | if (rc < 0) |
162 | return rc; | |
163 | ||
9754d45e | 164 | burstcnt = (value >> 8) & 0xFFFF; |
41a5e1cf CR |
165 | if (burstcnt) |
166 | return burstcnt; | |
9f3fc7bc | 167 | tpm_msleep(TPM_TIMEOUT); |
41a5e1cf CR |
168 | } while (time_before(jiffies, stop)); |
169 | return -EBUSY; | |
170 | } | |
171 | ||
172 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | |
173 | { | |
174 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
175 | int size = 0, burstcnt, rc; | |
176 | ||
2c97f6f2 PH |
177 | while (size < count) { |
178 | rc = wait_for_tpm_stat(chip, | |
41a5e1cf CR |
179 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
180 | chip->timeout_c, | |
2c97f6f2 PH |
181 | &priv->read_queue, true); |
182 | if (rc < 0) | |
183 | return rc; | |
26a137e3 JZ |
184 | burstcnt = get_burstcount(chip); |
185 | if (burstcnt < 0) { | |
186 | dev_err(&chip->dev, "Unable to read burstcount\n"); | |
187 | return burstcnt; | |
188 | } | |
189 | burstcnt = min_t(int, burstcnt, count - size); | |
41a5e1cf CR |
190 | |
191 | rc = tpm_tis_read_bytes(priv, TPM_DATA_FIFO(priv->locality), | |
192 | burstcnt, buf + size); | |
193 | if (rc < 0) | |
194 | return rc; | |
195 | ||
196 | size += burstcnt; | |
197 | } | |
198 | return size; | |
199 | } | |
200 | ||
201 | static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |
202 | { | |
203 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
204 | int size = 0; | |
205 | int expected, status; | |
206 | ||
207 | if (count < TPM_HEADER_SIZE) { | |
208 | size = -EIO; | |
209 | goto out; | |
210 | } | |
211 | ||
212 | size = recv_data(chip, buf, TPM_HEADER_SIZE); | |
213 | /* read first 10 bytes, including tag, paramsize, and result */ | |
214 | if (size < TPM_HEADER_SIZE) { | |
215 | dev_err(&chip->dev, "Unable to read header\n"); | |
216 | goto out; | |
217 | } | |
218 | ||
219 | expected = be32_to_cpu(*(__be32 *) (buf + 2)); | |
220 | if (expected > count) { | |
221 | size = -EIO; | |
222 | goto out; | |
223 | } | |
224 | ||
225 | size += recv_data(chip, &buf[TPM_HEADER_SIZE], | |
226 | expected - TPM_HEADER_SIZE); | |
227 | if (size < expected) { | |
228 | dev_err(&chip->dev, "Unable to read remainder of result\n"); | |
229 | size = -ETIME; | |
230 | goto out; | |
231 | } | |
232 | ||
2c97f6f2 PH |
233 | if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, |
234 | &priv->int_queue, false) < 0) { | |
235 | size = -ETIME; | |
236 | goto out; | |
237 | } | |
41a5e1cf CR |
238 | status = tpm_tis_status(chip); |
239 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ | |
240 | dev_err(&chip->dev, "Error left over data\n"); | |
241 | size = -EIO; | |
242 | goto out; | |
243 | } | |
244 | ||
245 | out: | |
246 | tpm_tis_ready(chip); | |
41a5e1cf CR |
247 | return size; |
248 | } | |
249 | ||
250 | /* | |
251 | * If interrupts are used (signaled by an irq set in the vendor structure) | |
252 | * tpm.c can skip polling for the data to be available as the interrupt is | |
253 | * waited for here | |
254 | */ | |
255 | static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |
256 | { | |
257 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
258 | int rc, status, burstcnt; | |
259 | size_t count = 0; | |
1d70fe9d | 260 | bool itpm = priv->flags & TPM_TIS_ITPM_WORKAROUND; |
41a5e1cf | 261 | |
41a5e1cf CR |
262 | status = tpm_tis_status(chip); |
263 | if ((status & TPM_STS_COMMAND_READY) == 0) { | |
264 | tpm_tis_ready(chip); | |
265 | if (wait_for_tpm_stat | |
266 | (chip, TPM_STS_COMMAND_READY, chip->timeout_b, | |
267 | &priv->int_queue, false) < 0) { | |
268 | rc = -ETIME; | |
269 | goto out_err; | |
270 | } | |
271 | } | |
272 | ||
273 | while (count < len - 1) { | |
26a137e3 JZ |
274 | burstcnt = get_burstcount(chip); |
275 | if (burstcnt < 0) { | |
276 | dev_err(&chip->dev, "Unable to read burstcount\n"); | |
277 | rc = burstcnt; | |
278 | goto out_err; | |
279 | } | |
280 | burstcnt = min_t(int, burstcnt, len - count - 1); | |
41a5e1cf CR |
281 | rc = tpm_tis_write_bytes(priv, TPM_DATA_FIFO(priv->locality), |
282 | burstcnt, buf + count); | |
283 | if (rc < 0) | |
284 | goto out_err; | |
285 | ||
286 | count += burstcnt; | |
287 | ||
2c97f6f2 PH |
288 | if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, |
289 | &priv->int_queue, false) < 0) { | |
290 | rc = -ETIME; | |
291 | goto out_err; | |
292 | } | |
41a5e1cf CR |
293 | status = tpm_tis_status(chip); |
294 | if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { | |
295 | rc = -EIO; | |
296 | goto out_err; | |
297 | } | |
298 | } | |
299 | ||
300 | /* write last byte */ | |
301 | rc = tpm_tis_write8(priv, TPM_DATA_FIFO(priv->locality), buf[count]); | |
302 | if (rc < 0) | |
303 | goto out_err; | |
304 | ||
2c97f6f2 PH |
305 | if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, |
306 | &priv->int_queue, false) < 0) { | |
307 | rc = -ETIME; | |
308 | goto out_err; | |
309 | } | |
41a5e1cf CR |
310 | status = tpm_tis_status(chip); |
311 | if (!itpm && (status & TPM_STS_DATA_EXPECT) != 0) { | |
312 | rc = -EIO; | |
313 | goto out_err; | |
314 | } | |
315 | ||
316 | return 0; | |
317 | ||
318 | out_err: | |
319 | tpm_tis_ready(chip); | |
41a5e1cf CR |
320 | return rc; |
321 | } | |
322 | ||
323 | static void disable_interrupts(struct tpm_chip *chip) | |
324 | { | |
325 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
326 | u32 intmask; | |
327 | int rc; | |
328 | ||
329 | rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); | |
330 | if (rc < 0) | |
331 | intmask = 0; | |
332 | ||
333 | intmask &= ~TPM_GLOBAL_INT_ENABLE; | |
334 | rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); | |
335 | ||
336 | devm_free_irq(chip->dev.parent, priv->irq, chip); | |
337 | priv->irq = 0; | |
338 | chip->flags &= ~TPM_CHIP_FLAG_IRQ; | |
339 | } | |
340 | ||
341 | /* | |
342 | * If interrupts are used (signaled by an irq set in the vendor structure) | |
343 | * tpm.c can skip polling for the data to be available as the interrupt is | |
344 | * waited for here | |
345 | */ | |
346 | static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) | |
347 | { | |
348 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
349 | int rc; | |
350 | u32 ordinal; | |
351 | unsigned long dur; | |
352 | ||
353 | rc = tpm_tis_send_data(chip, buf, len); | |
354 | if (rc < 0) | |
355 | return rc; | |
356 | ||
357 | /* go and do it */ | |
358 | rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO); | |
359 | if (rc < 0) | |
360 | goto out_err; | |
361 | ||
362 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { | |
363 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | |
364 | ||
365 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | |
366 | dur = tpm2_calc_ordinal_duration(chip, ordinal); | |
367 | else | |
368 | dur = tpm_calc_ordinal_duration(chip, ordinal); | |
369 | ||
370 | if (wait_for_tpm_stat | |
371 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, | |
372 | &priv->read_queue, false) < 0) { | |
373 | rc = -ETIME; | |
374 | goto out_err; | |
375 | } | |
376 | } | |
377 | return len; | |
378 | out_err: | |
379 | tpm_tis_ready(chip); | |
41a5e1cf CR |
380 | return rc; |
381 | } | |
382 | ||
383 | static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | |
384 | { | |
385 | int rc, irq; | |
386 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
387 | ||
388 | if (!(chip->flags & TPM_CHIP_FLAG_IRQ) || priv->irq_tested) | |
389 | return tpm_tis_send_main(chip, buf, len); | |
390 | ||
391 | /* Verify receipt of the expected IRQ */ | |
392 | irq = priv->irq; | |
393 | priv->irq = 0; | |
394 | chip->flags &= ~TPM_CHIP_FLAG_IRQ; | |
395 | rc = tpm_tis_send_main(chip, buf, len); | |
396 | priv->irq = irq; | |
397 | chip->flags |= TPM_CHIP_FLAG_IRQ; | |
398 | if (!priv->irq_tested) | |
9f3fc7bc | 399 | tpm_msleep(1); |
41a5e1cf CR |
400 | if (!priv->irq_tested) |
401 | disable_interrupts(chip); | |
402 | priv->irq_tested = true; | |
403 | return rc; | |
404 | } | |
405 | ||
406 | struct tis_vendor_timeout_override { | |
407 | u32 did_vid; | |
408 | unsigned long timeout_us[4]; | |
409 | }; | |
410 | ||
411 | static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = { | |
412 | /* Atmel 3204 */ | |
413 | { 0x32041114, { (TIS_SHORT_TIMEOUT*1000), (TIS_LONG_TIMEOUT*1000), | |
414 | (TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } }, | |
415 | }; | |
416 | ||
417 | static bool tpm_tis_update_timeouts(struct tpm_chip *chip, | |
418 | unsigned long *timeout_cap) | |
419 | { | |
420 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
421 | int i, rc; | |
422 | u32 did_vid; | |
423 | ||
424 | rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); | |
425 | if (rc < 0) | |
426 | return rc; | |
427 | ||
428 | for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { | |
429 | if (vendor_timeout_overrides[i].did_vid != did_vid) | |
430 | continue; | |
431 | memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, | |
432 | sizeof(vendor_timeout_overrides[i].timeout_us)); | |
433 | return true; | |
434 | } | |
435 | ||
436 | return false; | |
437 | } | |
438 | ||
439 | /* | |
440 | * Early probing for iTPM with STS_DATA_EXPECT flaw. | |
441 | * Try sending command without itpm flag set and if that | |
442 | * fails, repeat with itpm flag set. | |
443 | */ | |
444 | static int probe_itpm(struct tpm_chip *chip) | |
445 | { | |
446 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
447 | int rc = 0; | |
448 | u8 cmd_getticks[] = { | |
449 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, | |
450 | 0x00, 0x00, 0x00, 0xf1 | |
451 | }; | |
452 | size_t len = sizeof(cmd_getticks); | |
41a5e1cf CR |
453 | u16 vendor; |
454 | ||
419a16d9 MS |
455 | if (priv->flags & TPM_TIS_ITPM_WORKAROUND) |
456 | return 0; | |
457 | ||
41a5e1cf CR |
458 | rc = tpm_tis_read16(priv, TPM_DID_VID(0), &vendor); |
459 | if (rc < 0) | |
460 | return rc; | |
461 | ||
462 | /* probe only iTPMS */ | |
463 | if (vendor != TPM_VID_INTEL) | |
464 | return 0; | |
465 | ||
e6aef069 JS |
466 | if (request_locality(chip, 0) != 0) |
467 | return -EBUSY; | |
468 | ||
41a5e1cf CR |
469 | rc = tpm_tis_send_data(chip, cmd_getticks, len); |
470 | if (rc == 0) | |
471 | goto out; | |
472 | ||
473 | tpm_tis_ready(chip); | |
41a5e1cf | 474 | |
419a16d9 MS |
475 | priv->flags |= TPM_TIS_ITPM_WORKAROUND; |
476 | ||
41a5e1cf | 477 | rc = tpm_tis_send_data(chip, cmd_getticks, len); |
419a16d9 | 478 | if (rc == 0) |
41a5e1cf | 479 | dev_info(&chip->dev, "Detected an iTPM.\n"); |
419a16d9 MS |
480 | else { |
481 | priv->flags &= ~TPM_TIS_ITPM_WORKAROUND; | |
41a5e1cf | 482 | rc = -EFAULT; |
419a16d9 | 483 | } |
41a5e1cf CR |
484 | |
485 | out: | |
486 | tpm_tis_ready(chip); | |
e6aef069 | 487 | release_locality(chip, priv->locality); |
41a5e1cf CR |
488 | |
489 | return rc; | |
490 | } | |
491 | ||
492 | static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status) | |
493 | { | |
494 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
495 | ||
496 | switch (priv->manufacturer_id) { | |
497 | case TPM_VID_WINBOND: | |
498 | return ((status == TPM_STS_VALID) || | |
499 | (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY))); | |
500 | case TPM_VID_STM: | |
501 | return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)); | |
502 | default: | |
503 | return (status == TPM_STS_COMMAND_READY); | |
504 | } | |
505 | } | |
506 | ||
507 | static irqreturn_t tis_int_handler(int dummy, void *dev_id) | |
508 | { | |
509 | struct tpm_chip *chip = dev_id; | |
510 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
511 | u32 interrupt; | |
512 | int i, rc; | |
513 | ||
514 | rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt); | |
515 | if (rc < 0) | |
516 | return IRQ_NONE; | |
517 | ||
518 | if (interrupt == 0) | |
519 | return IRQ_NONE; | |
520 | ||
521 | priv->irq_tested = true; | |
522 | if (interrupt & TPM_INTF_DATA_AVAIL_INT) | |
523 | wake_up_interruptible(&priv->read_queue); | |
524 | if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) | |
525 | for (i = 0; i < 5; i++) | |
84d25940 | 526 | if (check_locality(chip, i)) |
41a5e1cf CR |
527 | break; |
528 | if (interrupt & | |
529 | (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | | |
530 | TPM_INTF_CMD_READY_INT)) | |
531 | wake_up_interruptible(&priv->int_queue); | |
532 | ||
533 | /* Clear interrupts handled with TPM_EOI */ | |
534 | rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt); | |
535 | if (rc < 0) | |
536 | return IRQ_NONE; | |
537 | ||
538 | tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt); | |
539 | return IRQ_HANDLED; | |
540 | } | |
541 | ||
eb5854e7 JS |
542 | static int tpm_tis_gen_interrupt(struct tpm_chip *chip) |
543 | { | |
544 | const char *desc = "attempting to generate an interrupt"; | |
545 | u32 cap2; | |
546 | cap_t cap; | |
547 | ||
548 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | |
549 | return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc); | |
550 | else | |
c659af78 SB |
551 | return tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, |
552 | 0); | |
eb5854e7 JS |
553 | } |
554 | ||
41a5e1cf CR |
555 | /* Register the IRQ and issue a command that will cause an interrupt. If an |
556 | * irq is seen then leave the chip setup for IRQ operation, otherwise reverse | |
557 | * everything and leave in polling mode. Returns 0 on success. | |
558 | */ | |
559 | static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask, | |
560 | int flags, int irq) | |
561 | { | |
562 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
563 | u8 original_int_vec; | |
564 | int rc; | |
565 | u32 int_status; | |
566 | ||
567 | if (devm_request_irq(chip->dev.parent, irq, tis_int_handler, flags, | |
568 | dev_name(&chip->dev), chip) != 0) { | |
569 | dev_info(&chip->dev, "Unable to request irq: %d for probe\n", | |
570 | irq); | |
571 | return -1; | |
572 | } | |
573 | priv->irq = irq; | |
574 | ||
575 | rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality), | |
576 | &original_int_vec); | |
577 | if (rc < 0) | |
578 | return rc; | |
579 | ||
580 | rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq); | |
581 | if (rc < 0) | |
582 | return rc; | |
583 | ||
584 | rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status); | |
585 | if (rc < 0) | |
586 | return rc; | |
587 | ||
588 | /* Clear all existing */ | |
589 | rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status); | |
590 | if (rc < 0) | |
591 | return rc; | |
592 | ||
593 | /* Turn on */ | |
594 | rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), | |
595 | intmask | TPM_GLOBAL_INT_ENABLE); | |
596 | if (rc < 0) | |
597 | return rc; | |
598 | ||
599 | priv->irq_tested = false; | |
600 | ||
601 | /* Generate an interrupt by having the core call through to | |
602 | * tpm_tis_send | |
603 | */ | |
eb5854e7 JS |
604 | rc = tpm_tis_gen_interrupt(chip); |
605 | if (rc < 0) | |
606 | return rc; | |
41a5e1cf CR |
607 | |
608 | /* tpm_tis_send will either confirm the interrupt is working or it | |
609 | * will call disable_irq which undoes all of the above. | |
610 | */ | |
611 | if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { | |
612 | rc = tpm_tis_write8(priv, original_int_vec, | |
613 | TPM_INT_VECTOR(priv->locality)); | |
614 | if (rc < 0) | |
615 | return rc; | |
616 | ||
617 | return 1; | |
618 | } | |
619 | ||
620 | return 0; | |
621 | } | |
622 | ||
623 | /* Try to find the IRQ the TPM is using. This is for legacy x86 systems that | |
624 | * do not have ACPI/etc. We typically expect the interrupt to be declared if | |
625 | * present. | |
626 | */ | |
627 | static void tpm_tis_probe_irq(struct tpm_chip *chip, u32 intmask) | |
628 | { | |
629 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
630 | u8 original_int_vec; | |
631 | int i, rc; | |
632 | ||
633 | rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality), | |
634 | &original_int_vec); | |
635 | if (rc < 0) | |
636 | return; | |
637 | ||
638 | if (!original_int_vec) { | |
639 | if (IS_ENABLED(CONFIG_X86)) | |
640 | for (i = 3; i <= 15; i++) | |
641 | if (!tpm_tis_probe_irq_single(chip, intmask, 0, | |
642 | i)) | |
643 | return; | |
644 | } else if (!tpm_tis_probe_irq_single(chip, intmask, 0, | |
645 | original_int_vec)) | |
646 | return; | |
647 | } | |
648 | ||
649 | void tpm_tis_remove(struct tpm_chip *chip) | |
650 | { | |
651 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
652 | u32 reg = TPM_INT_ENABLE(priv->locality); | |
653 | u32 interrupt; | |
654 | int rc; | |
655 | ||
656 | rc = tpm_tis_read32(priv, reg, &interrupt); | |
657 | if (rc < 0) | |
658 | interrupt = 0; | |
659 | ||
660 | tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt); | |
41a5e1cf CR |
661 | } |
662 | EXPORT_SYMBOL_GPL(tpm_tis_remove); | |
663 | ||
664 | static const struct tpm_class_ops tpm_tis = { | |
cae8b441 | 665 | .flags = TPM_OPS_AUTO_STARTUP, |
41a5e1cf CR |
666 | .status = tpm_tis_status, |
667 | .recv = tpm_tis_recv, | |
668 | .send = tpm_tis_send, | |
669 | .cancel = tpm_tis_ready, | |
670 | .update_timeouts = tpm_tis_update_timeouts, | |
671 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | |
672 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | |
673 | .req_canceled = tpm_tis_req_canceled, | |
e6aef069 JS |
674 | .request_locality = request_locality, |
675 | .relinquish_locality = release_locality, | |
41a5e1cf CR |
676 | }; |
677 | ||
678 | int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, | |
679 | const struct tpm_tis_phy_ops *phy_ops, | |
680 | acpi_handle acpi_dev_handle) | |
681 | { | |
682 | u32 vendor, intfcaps, intmask; | |
683 | u8 rid; | |
684 | int rc, probe; | |
685 | struct tpm_chip *chip; | |
686 | ||
687 | chip = tpmm_chip_alloc(dev, &tpm_tis); | |
688 | if (IS_ERR(chip)) | |
689 | return PTR_ERR(chip); | |
690 | ||
691 | #ifdef CONFIG_ACPI | |
692 | chip->acpi_dev_handle = acpi_dev_handle; | |
693 | #endif | |
694 | ||
695 | /* Maximum timeouts */ | |
79b591c0 | 696 | chip->timeout_a = msecs_to_jiffies(TIS_TIMEOUT_A_MAX); |
697 | chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX); | |
698 | chip->timeout_c = msecs_to_jiffies(TIS_TIMEOUT_C_MAX); | |
699 | chip->timeout_d = msecs_to_jiffies(TIS_TIMEOUT_D_MAX); | |
41a5e1cf CR |
700 | priv->phy_ops = phy_ops; |
701 | dev_set_drvdata(&chip->dev, priv); | |
702 | ||
703 | if (wait_startup(chip, 0) != 0) { | |
704 | rc = -ENODEV; | |
705 | goto out_err; | |
706 | } | |
707 | ||
708 | /* Take control of the TPM's interrupt hardware and shut it off */ | |
709 | rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); | |
710 | if (rc < 0) | |
711 | goto out_err; | |
712 | ||
713 | intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT | | |
714 | TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT; | |
715 | intmask &= ~TPM_GLOBAL_INT_ENABLE; | |
716 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); | |
717 | ||
41a5e1cf CR |
718 | rc = tpm2_probe(chip); |
719 | if (rc) | |
720 | goto out_err; | |
721 | ||
722 | rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor); | |
723 | if (rc < 0) | |
724 | goto out_err; | |
725 | ||
726 | priv->manufacturer_id = vendor; | |
727 | ||
728 | rc = tpm_tis_read8(priv, TPM_RID(0), &rid); | |
729 | if (rc < 0) | |
730 | goto out_err; | |
731 | ||
732 | dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", | |
733 | (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", | |
734 | vendor >> 16, rid); | |
735 | ||
419a16d9 MS |
736 | probe = probe_itpm(chip); |
737 | if (probe < 0) { | |
738 | rc = -ENODEV; | |
739 | goto out_err; | |
41a5e1cf CR |
740 | } |
741 | ||
742 | /* Figure out the capabilities */ | |
743 | rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps); | |
744 | if (rc < 0) | |
745 | goto out_err; | |
746 | ||
747 | dev_dbg(dev, "TPM interface capabilities (0x%x):\n", | |
748 | intfcaps); | |
749 | if (intfcaps & TPM_INTF_BURST_COUNT_STATIC) | |
750 | dev_dbg(dev, "\tBurst Count Static\n"); | |
751 | if (intfcaps & TPM_INTF_CMD_READY_INT) | |
752 | dev_dbg(dev, "\tCommand Ready Int Support\n"); | |
753 | if (intfcaps & TPM_INTF_INT_EDGE_FALLING) | |
754 | dev_dbg(dev, "\tInterrupt Edge Falling\n"); | |
755 | if (intfcaps & TPM_INTF_INT_EDGE_RISING) | |
756 | dev_dbg(dev, "\tInterrupt Edge Rising\n"); | |
757 | if (intfcaps & TPM_INTF_INT_LEVEL_LOW) | |
758 | dev_dbg(dev, "\tInterrupt Level Low\n"); | |
759 | if (intfcaps & TPM_INTF_INT_LEVEL_HIGH) | |
760 | dev_dbg(dev, "\tInterrupt Level High\n"); | |
761 | if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) | |
762 | dev_dbg(dev, "\tLocality Change Int Support\n"); | |
763 | if (intfcaps & TPM_INTF_STS_VALID_INT) | |
764 | dev_dbg(dev, "\tSts Valid Int Support\n"); | |
765 | if (intfcaps & TPM_INTF_DATA_AVAIL_INT) | |
766 | dev_dbg(dev, "\tData Avail Int Support\n"); | |
767 | ||
41a5e1cf CR |
768 | /* INTERRUPT Setup */ |
769 | init_waitqueue_head(&priv->read_queue); | |
770 | init_waitqueue_head(&priv->int_queue); | |
771 | if (irq != -1) { | |
d1d253cf JG |
772 | /* Before doing irq testing issue a command to the TPM in polling mode |
773 | * to make sure it works. May as well use that command to set the | |
774 | * proper timeouts for the driver. | |
775 | */ | |
776 | if (tpm_get_timeouts(chip)) { | |
777 | dev_err(dev, "Could not get TPM timeouts and durations\n"); | |
778 | rc = -ENODEV; | |
779 | goto out_err; | |
780 | } | |
781 | ||
41a5e1cf CR |
782 | if (irq) { |
783 | tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED, | |
784 | irq); | |
785 | if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) | |
786 | dev_err(&chip->dev, FW_BUG | |
787 | "TPM interrupt not working, polling instead\n"); | |
788 | } else { | |
789 | tpm_tis_probe_irq(chip, intmask); | |
790 | } | |
791 | } | |
792 | ||
41a5e1cf CR |
793 | return tpm_chip_register(chip); |
794 | out_err: | |
795 | tpm_tis_remove(chip); | |
796 | return rc; | |
797 | } | |
798 | EXPORT_SYMBOL_GPL(tpm_tis_core_init); | |
799 | ||
800 | #ifdef CONFIG_PM_SLEEP | |
801 | static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) | |
802 | { | |
803 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
804 | u32 intmask; | |
805 | int rc; | |
806 | ||
807 | /* reenable interrupts that device may have lost or | |
808 | * BIOS/firmware may have disabled | |
809 | */ | |
810 | rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq); | |
811 | if (rc < 0) | |
812 | return; | |
813 | ||
814 | rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); | |
815 | if (rc < 0) | |
816 | return; | |
817 | ||
818 | intmask |= TPM_INTF_CMD_READY_INT | |
819 | | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT | |
820 | | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE; | |
821 | ||
822 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); | |
823 | } | |
824 | ||
825 | int tpm_tis_resume(struct device *dev) | |
826 | { | |
827 | struct tpm_chip *chip = dev_get_drvdata(dev); | |
828 | int ret; | |
829 | ||
830 | if (chip->flags & TPM_CHIP_FLAG_IRQ) | |
831 | tpm_tis_reenable_interrupts(chip); | |
832 | ||
833 | ret = tpm_pm_resume(dev); | |
834 | if (ret) | |
835 | return ret; | |
836 | ||
837 | /* TPM 1.2 requires self-test on resume. This function actually returns | |
838 | * an error code but for unknown reason it isn't handled. | |
839 | */ | |
840 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) | |
841 | tpm_do_selftest(chip); | |
842 | ||
843 | return 0; | |
844 | } | |
845 | EXPORT_SYMBOL_GPL(tpm_tis_resume); | |
846 | #endif | |
847 | ||
848 | MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); | |
849 | MODULE_DESCRIPTION("TPM Driver"); | |
850 | MODULE_VERSION("2.0"); | |
851 | MODULE_LICENSE("GPL"); |