1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * STMicroelectronics TPM Linux driver for TPM ST33ZP24 |
4 | * Copyright (C) 2009 - 2016 STMicroelectronics |
5 | */ |
6 | |
7 | #include <linux/acpi.h> |
8 | #include <linux/module.h> |
9 | #include <linux/fs.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/delay.h> |
12 | #include <linux/wait.h> |
13 | #include <linux/freezer.h> |
14 | #include <linux/string.h> |
15 | #include <linux/interrupt.h> |
16 | #include <linux/gpio/consumer.h> |
17 | #include <linux/sched.h> |
18 | #include <linux/uaccess.h> |
19 | #include <linux/io.h> |
20 | #include <linux/slab.h> |
21 | |
22 | #include "../tpm.h" |
23 | #include "st33zp24.h" |
24 | |
25 | #define TPM_ACCESS 0x0 |
26 | #define TPM_STS 0x18 |
27 | #define TPM_DATA_FIFO 0x24 |
28 | #define TPM_INTF_CAPABILITY 0x14 |
29 | #define TPM_INT_STATUS 0x10 |
30 | #define TPM_INT_ENABLE 0x08 |
31 | |
32 | #define LOCALITY0 0 |
33 | |
34 | enum st33zp24_access { |
35 | TPM_ACCESS_VALID = 0x80, |
36 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, |
37 | TPM_ACCESS_REQUEST_PENDING = 0x04, |
38 | TPM_ACCESS_REQUEST_USE = 0x02, |
39 | }; |
40 | |
41 | enum st33zp24_status { |
42 | TPM_STS_VALID = 0x80, |
43 | TPM_STS_COMMAND_READY = 0x40, |
44 | TPM_STS_GO = 0x20, |
45 | TPM_STS_DATA_AVAIL = 0x10, |
46 | TPM_STS_DATA_EXPECT = 0x08, |
47 | }; |
48 | |
49 | enum st33zp24_int_flags { |
50 | TPM_GLOBAL_INT_ENABLE = 0x80, |
51 | TPM_INTF_CMD_READY_INT = 0x080, |
52 | TPM_INTF_FIFO_AVALAIBLE_INT = 0x040, |
53 | TPM_INTF_WAKE_UP_READY_INT = 0x020, |
54 | TPM_INTF_LOCALITY_CHANGE_INT = 0x004, |
55 | TPM_INTF_STS_VALID_INT = 0x002, |
56 | TPM_INTF_DATA_AVAIL_INT = 0x001, |
57 | }; |
58 | |
59 | enum tis_defaults { |
60 | TIS_SHORT_TIMEOUT = 750, |
61 | TIS_LONG_TIMEOUT = 2000, |
62 | }; |
63 | |
64 | /* |
65 | * clear the pending interrupt. |
66 | */ |
67 | static u8 clear_interruption(struct st33zp24_dev *tpm_dev) |
68 | { |
69 | u8 interrupt; |
70 | |
71 | tpm_dev->ops->recv(tpm_dev->phy_id, TPM_INT_STATUS, &interrupt, 1); |
72 | tpm_dev->ops->send(tpm_dev->phy_id, TPM_INT_STATUS, &interrupt, 1); |
73 | return interrupt; |
74 | } |
75 | |
76 | /* |
77 | * cancel the current command execution or set STS to COMMAND READY. |
78 | */ |
79 | static void st33zp24_cancel(struct tpm_chip *chip) |
80 | { |
81 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
82 | u8 data; |
83 | |
84 | data = TPM_STS_COMMAND_READY; |
85 | tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1); |
86 | } |
87 | |
88 | /* |
89 | * return the TPM_STS register |
90 | */ |
91 | static u8 st33zp24_status(struct tpm_chip *chip) |
92 | { |
93 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
94 | u8 data; |
95 | |
96 | tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1); |
97 | return data; |
98 | } |
99 | |
100 | /* |
101 | * if the locality is active |
102 | */ |
103 | static bool check_locality(struct tpm_chip *chip) |
104 | { |
105 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
106 | u8 data; |
107 | u8 status; |
108 | |
109 | status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS, &data, 1); |
110 | if (status && (data & |
111 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == |
112 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) |
113 | return true; |
114 | |
115 | return false; |
116 | } |
117 | |
118 | static int request_locality(struct tpm_chip *chip) |
119 | { |
120 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
121 | unsigned long stop; |
122 | long ret; |
123 | u8 data; |
124 | |
125 | if (check_locality(chip)) |
126 | return tpm_dev->locality; |
127 | |
128 | data = TPM_ACCESS_REQUEST_USE; |
129 | ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1); |
130 | if (ret < 0) |
131 | return ret; |
132 | |
133 | stop = jiffies + chip->timeout_a; |
134 | |
135 | /* Request locality is usually effective after the request */ |
136 | do { |
137 | if (check_locality(chip)) |
138 | return tpm_dev->locality; |
139 | msleep(msecs: TPM_TIMEOUT); |
140 | } while (time_before(jiffies, stop)); |
141 | |
142 | /* could not get locality */ |
143 | return -EACCES; |
144 | } |
145 | |
146 | static void release_locality(struct tpm_chip *chip) |
147 | { |
148 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
149 | u8 data; |
150 | |
151 | data = TPM_ACCESS_ACTIVE_LOCALITY; |
152 | |
153 | tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1); |
154 | } |
155 | |
156 | /* |
157 | * get_burstcount return the burstcount value |
158 | */ |
159 | static int get_burstcount(struct tpm_chip *chip) |
160 | { |
161 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
162 | unsigned long stop; |
163 | int burstcnt, status; |
164 | u8 temp; |
165 | |
166 | stop = jiffies + chip->timeout_d; |
167 | do { |
168 | status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS + 1, |
169 | &temp, 1); |
170 | if (status < 0) |
171 | return -EBUSY; |
172 | |
173 | burstcnt = temp; |
174 | status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS + 2, |
175 | &temp, 1); |
176 | if (status < 0) |
177 | return -EBUSY; |
178 | |
179 | burstcnt |= temp << 8; |
180 | if (burstcnt) |
181 | return burstcnt; |
182 | msleep(msecs: TPM_TIMEOUT); |
183 | } while (time_before(jiffies, stop)); |
184 | return -EBUSY; |
185 | } |
186 | |
187 | static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, |
188 | bool check_cancel, bool *canceled) |
189 | { |
190 | u8 status = chip->ops->status(chip); |
191 | |
192 | *canceled = false; |
193 | if ((status & mask) == mask) |
194 | return true; |
195 | if (check_cancel && chip->ops->req_canceled(chip, status)) { |
196 | *canceled = true; |
197 | return true; |
198 | } |
199 | return false; |
200 | } |
201 | |
202 | /* |
203 | * wait for a TPM_STS value |
204 | */ |
205 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, |
206 | wait_queue_head_t *queue, bool check_cancel) |
207 | { |
208 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
209 | unsigned long stop; |
210 | int ret = 0; |
211 | bool canceled = false; |
212 | bool condition; |
213 | u32 cur_intrs; |
214 | u8 status; |
215 | |
216 | /* check current status */ |
217 | status = st33zp24_status(chip); |
218 | if ((status & mask) == mask) |
219 | return 0; |
220 | |
221 | stop = jiffies + timeout; |
222 | |
223 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { |
224 | cur_intrs = tpm_dev->intrs; |
225 | clear_interruption(tpm_dev); |
226 | enable_irq(irq: tpm_dev->irq); |
227 | |
228 | do { |
229 | if (ret == -ERESTARTSYS && freezing(current)) |
230 | clear_thread_flag(TIF_SIGPENDING); |
231 | |
232 | timeout = stop - jiffies; |
233 | if ((long) timeout <= 0) |
234 | return -1; |
235 | |
236 | ret = wait_event_interruptible_timeout(*queue, |
237 | cur_intrs != tpm_dev->intrs, |
238 | timeout); |
239 | clear_interruption(tpm_dev); |
240 | condition = wait_for_tpm_stat_cond(chip, mask, |
241 | check_cancel, canceled: &canceled); |
242 | if (ret >= 0 && condition) { |
243 | if (canceled) |
244 | return -ECANCELED; |
245 | return 0; |
246 | } |
247 | } while (ret == -ERESTARTSYS && freezing(current)); |
248 | |
249 | disable_irq_nosync(irq: tpm_dev->irq); |
250 | |
251 | } else { |
252 | do { |
253 | msleep(msecs: TPM_TIMEOUT); |
254 | status = chip->ops->status(chip); |
255 | if ((status & mask) == mask) |
256 | return 0; |
257 | } while (time_before(jiffies, stop)); |
258 | } |
259 | |
260 | return -ETIME; |
261 | } |
262 | |
263 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) |
264 | { |
265 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
266 | int size = 0, burstcnt, len, ret; |
267 | |
268 | while (size < count && |
269 | wait_for_stat(chip, |
270 | mask: TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
271 | timeout: chip->timeout_c, |
272 | queue: &tpm_dev->read_queue, check_cancel: true) == 0) { |
273 | burstcnt = get_burstcount(chip); |
274 | if (burstcnt < 0) |
275 | return burstcnt; |
276 | len = min_t(int, burstcnt, count - size); |
277 | ret = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_DATA_FIFO, |
278 | buf + size, len); |
279 | if (ret < 0) |
280 | return ret; |
281 | |
282 | size += len; |
283 | } |
284 | return size; |
285 | } |
286 | |
287 | static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) |
288 | { |
289 | struct tpm_chip *chip = dev_id; |
290 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
291 | |
292 | tpm_dev->intrs++; |
293 | wake_up_interruptible(&tpm_dev->read_queue); |
294 | disable_irq_nosync(irq: tpm_dev->irq); |
295 | |
296 | return IRQ_HANDLED; |
297 | } |
298 | |
299 | /* |
300 | * send TPM commands through the I2C bus. |
301 | */ |
302 | static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf, |
303 | size_t len) |
304 | { |
305 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
306 | u32 status, i, size, ordinal; |
307 | int burstcnt = 0; |
308 | int ret; |
309 | u8 data; |
310 | |
311 | if (len < TPM_HEADER_SIZE) |
312 | return -EBUSY; |
313 | |
314 | ret = request_locality(chip); |
315 | if (ret < 0) |
316 | return ret; |
317 | |
318 | status = st33zp24_status(chip); |
319 | if ((status & TPM_STS_COMMAND_READY) == 0) { |
320 | st33zp24_cancel(chip); |
321 | if (wait_for_stat |
322 | (chip, mask: TPM_STS_COMMAND_READY, timeout: chip->timeout_b, |
323 | queue: &tpm_dev->read_queue, check_cancel: false) < 0) { |
324 | ret = -ETIME; |
325 | goto out_err; |
326 | } |
327 | } |
328 | |
329 | for (i = 0; i < len - 1;) { |
330 | burstcnt = get_burstcount(chip); |
331 | if (burstcnt < 0) |
332 | return burstcnt; |
333 | size = min_t(int, len - i - 1, burstcnt); |
334 | ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_DATA_FIFO, |
335 | buf + i, size); |
336 | if (ret < 0) |
337 | goto out_err; |
338 | |
339 | i += size; |
340 | } |
341 | |
342 | status = st33zp24_status(chip); |
343 | if ((status & TPM_STS_DATA_EXPECT) == 0) { |
344 | ret = -EIO; |
345 | goto out_err; |
346 | } |
347 | |
348 | ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_DATA_FIFO, |
349 | buf + len - 1, 1); |
350 | if (ret < 0) |
351 | goto out_err; |
352 | |
353 | status = st33zp24_status(chip); |
354 | if ((status & TPM_STS_DATA_EXPECT) != 0) { |
355 | ret = -EIO; |
356 | goto out_err; |
357 | } |
358 | |
359 | data = TPM_STS_GO; |
360 | ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1); |
361 | if (ret < 0) |
362 | goto out_err; |
363 | |
364 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { |
365 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); |
366 | |
367 | ret = wait_for_stat(chip, mask: TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
368 | timeout: tpm_calc_ordinal_duration(chip, ordinal), |
369 | queue: &tpm_dev->read_queue, check_cancel: false); |
370 | if (ret < 0) |
371 | goto out_err; |
372 | } |
373 | |
374 | return 0; |
375 | out_err: |
376 | st33zp24_cancel(chip); |
377 | release_locality(chip); |
378 | return ret; |
379 | } |
380 | |
381 | static int st33zp24_recv(struct tpm_chip *chip, unsigned char *buf, |
382 | size_t count) |
383 | { |
384 | int size = 0; |
385 | u32 expected; |
386 | |
387 | if (!chip) |
388 | return -EBUSY; |
389 | |
390 | if (count < TPM_HEADER_SIZE) { |
391 | size = -EIO; |
392 | goto out; |
393 | } |
394 | |
395 | size = recv_data(chip, buf, TPM_HEADER_SIZE); |
396 | if (size < TPM_HEADER_SIZE) { |
397 | dev_err(&chip->dev, "Unable to read header\n" ); |
398 | goto out; |
399 | } |
400 | |
401 | expected = be32_to_cpu(*(__be32 *)(buf + 2)); |
402 | if (expected > count || expected < TPM_HEADER_SIZE) { |
403 | size = -EIO; |
404 | goto out; |
405 | } |
406 | |
407 | size += recv_data(chip, buf: &buf[TPM_HEADER_SIZE], |
408 | count: expected - TPM_HEADER_SIZE); |
409 | if (size < expected) { |
410 | dev_err(&chip->dev, "Unable to read remainder of result\n" ); |
411 | size = -ETIME; |
412 | } |
413 | |
414 | out: |
415 | st33zp24_cancel(chip); |
416 | release_locality(chip); |
417 | return size; |
418 | } |
419 | |
420 | static bool st33zp24_req_canceled(struct tpm_chip *chip, u8 status) |
421 | { |
422 | return (status == TPM_STS_COMMAND_READY); |
423 | } |
424 | |
425 | static const struct tpm_class_ops st33zp24_tpm = { |
426 | .flags = TPM_OPS_AUTO_STARTUP, |
427 | .send = st33zp24_send, |
428 | .recv = st33zp24_recv, |
429 | .cancel = st33zp24_cancel, |
430 | .status = st33zp24_status, |
431 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
432 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
433 | .req_canceled = st33zp24_req_canceled, |
434 | }; |
435 | |
436 | static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false }; |
437 | |
438 | static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = { |
439 | { "lpcpd-gpios" , &lpcpd_gpios, 1 }, |
440 | { }, |
441 | }; |
442 | |
443 | /* |
444 | * initialize the TPM device |
445 | */ |
446 | int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops, |
447 | struct device *dev, int irq) |
448 | { |
449 | int ret; |
450 | u8 intmask = 0; |
451 | struct tpm_chip *chip; |
452 | struct st33zp24_dev *tpm_dev; |
453 | |
454 | chip = tpmm_chip_alloc(pdev: dev, ops: &st33zp24_tpm); |
455 | if (IS_ERR(ptr: chip)) |
456 | return PTR_ERR(ptr: chip); |
457 | |
458 | tpm_dev = devm_kzalloc(dev, size: sizeof(struct st33zp24_dev), |
459 | GFP_KERNEL); |
460 | if (!tpm_dev) |
461 | return -ENOMEM; |
462 | |
463 | tpm_dev->phy_id = phy_id; |
464 | tpm_dev->ops = ops; |
465 | dev_set_drvdata(dev: &chip->dev, data: tpm_dev); |
466 | |
467 | chip->timeout_a = msecs_to_jiffies(m: TIS_SHORT_TIMEOUT); |
468 | chip->timeout_b = msecs_to_jiffies(m: TIS_LONG_TIMEOUT); |
469 | chip->timeout_c = msecs_to_jiffies(m: TIS_SHORT_TIMEOUT); |
470 | chip->timeout_d = msecs_to_jiffies(m: TIS_SHORT_TIMEOUT); |
471 | |
472 | tpm_dev->locality = LOCALITY0; |
473 | |
474 | if (ACPI_COMPANION(dev)) { |
475 | ret = devm_acpi_dev_add_driver_gpios(dev, gpios: acpi_st33zp24_gpios); |
476 | if (ret) |
477 | return ret; |
478 | } |
479 | |
480 | /* |
481 | * Get LPCPD GPIO. If lpcpd pin is not specified. This is not an |
482 | * issue as power management can be also managed by TPM specific |
483 | * commands. |
484 | */ |
485 | tpm_dev->io_lpcpd = devm_gpiod_get_optional(dev, con_id: "lpcpd" , |
486 | flags: GPIOD_OUT_HIGH); |
487 | ret = PTR_ERR_OR_ZERO(ptr: tpm_dev->io_lpcpd); |
488 | if (ret) { |
489 | dev_err(dev, "failed to request lpcpd gpio: %d\n" , ret); |
490 | return ret; |
491 | } |
492 | |
493 | if (irq) { |
494 | /* INTERRUPT Setup */ |
495 | init_waitqueue_head(&tpm_dev->read_queue); |
496 | tpm_dev->intrs = 0; |
497 | |
498 | if (request_locality(chip) != LOCALITY0) { |
499 | ret = -ENODEV; |
500 | goto _tpm_clean_answer; |
501 | } |
502 | |
503 | clear_interruption(tpm_dev); |
504 | ret = devm_request_irq(dev, irq, handler: tpm_ioserirq_handler, |
505 | IRQF_TRIGGER_HIGH, devname: "TPM SERIRQ management" , |
506 | dev_id: chip); |
507 | if (ret < 0) { |
508 | dev_err(&chip->dev, "TPM SERIRQ signals %d not available\n" , |
509 | irq); |
510 | goto _tpm_clean_answer; |
511 | } |
512 | |
513 | intmask |= TPM_INTF_CMD_READY_INT |
514 | | TPM_INTF_STS_VALID_INT |
515 | | TPM_INTF_DATA_AVAIL_INT; |
516 | |
517 | ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_INT_ENABLE, |
518 | &intmask, 1); |
519 | if (ret < 0) |
520 | goto _tpm_clean_answer; |
521 | |
522 | intmask = TPM_GLOBAL_INT_ENABLE; |
523 | ret = tpm_dev->ops->send(tpm_dev->phy_id, (TPM_INT_ENABLE + 3), |
524 | &intmask, 1); |
525 | if (ret < 0) |
526 | goto _tpm_clean_answer; |
527 | |
528 | tpm_dev->irq = irq; |
529 | chip->flags |= TPM_CHIP_FLAG_IRQ; |
530 | |
531 | disable_irq_nosync(irq: tpm_dev->irq); |
532 | } |
533 | |
534 | return tpm_chip_register(chip); |
535 | _tpm_clean_answer: |
536 | dev_info(&chip->dev, "TPM initialization fail\n" ); |
537 | return ret; |
538 | } |
539 | EXPORT_SYMBOL(st33zp24_probe); |
540 | |
541 | void st33zp24_remove(struct tpm_chip *chip) |
542 | { |
543 | tpm_chip_unregister(chip); |
544 | } |
545 | EXPORT_SYMBOL(st33zp24_remove); |
546 | |
547 | #ifdef CONFIG_PM_SLEEP |
548 | int st33zp24_pm_suspend(struct device *dev) |
549 | { |
550 | struct tpm_chip *chip = dev_get_drvdata(dev); |
551 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
552 | |
553 | int ret = 0; |
554 | |
555 | if (tpm_dev->io_lpcpd) |
556 | gpiod_set_value_cansleep(desc: tpm_dev->io_lpcpd, value: 0); |
557 | else |
558 | ret = tpm_pm_suspend(dev); |
559 | |
560 | return ret; |
561 | } |
562 | EXPORT_SYMBOL(st33zp24_pm_suspend); |
563 | |
564 | int st33zp24_pm_resume(struct device *dev) |
565 | { |
566 | struct tpm_chip *chip = dev_get_drvdata(dev); |
567 | struct st33zp24_dev *tpm_dev = dev_get_drvdata(dev: &chip->dev); |
568 | int ret = 0; |
569 | |
570 | if (tpm_dev->io_lpcpd) { |
571 | gpiod_set_value_cansleep(desc: tpm_dev->io_lpcpd, value: 1); |
572 | ret = wait_for_stat(chip, |
573 | mask: TPM_STS_VALID, timeout: chip->timeout_b, |
574 | queue: &tpm_dev->read_queue, check_cancel: false); |
575 | } else { |
576 | ret = tpm_pm_resume(dev); |
577 | if (!ret) |
578 | tpm1_do_selftest(chip); |
579 | } |
580 | return ret; |
581 | } |
582 | EXPORT_SYMBOL(st33zp24_pm_resume); |
583 | #endif |
584 | |
585 | MODULE_AUTHOR("TPM support <TPMsupport@list.st.com>" ); |
586 | MODULE_DESCRIPTION("ST33ZP24 TPM 1.2 driver" ); |
587 | MODULE_VERSION("1.3.0" ); |
588 | MODULE_LICENSE("GPL" ); |
589 | |