blob: ce9efb73c144be2b9cdb4daa77c180d150534811 [file] [log] [blame]
Thomas Gleixner1ccea772019-05-19 15:51:43 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Christophe Ricardbf38b872015-03-08 11:17:14 +01002/*
3 * STMicroelectronics TPM Linux driver for TPM ST33ZP24
Christophe RICARD2c2b2172016-02-13 16:15:31 +01004 * Copyright (C) 2009 - 2016 STMicroelectronics
Christophe Ricardbf38b872015-03-08 11:17:14 +01005 */
6
7#include <linux/module.h>
8#include <linux/fs.h>
Christophe Ricardbf38b872015-03-08 11:17:14 +01009#include <linux/kernel.h>
10#include <linux/delay.h>
11#include <linux/wait.h>
12#include <linux/freezer.h>
13#include <linux/string.h>
14#include <linux/interrupt.h>
15#include <linux/gpio.h>
16#include <linux/sched.h>
17#include <linux/uaccess.h>
18#include <linux/io.h>
19#include <linux/slab.h>
20
21#include "../tpm.h"
22#include "st33zp24.h"
23
24#define TPM_ACCESS 0x0
25#define TPM_STS 0x18
26#define TPM_DATA_FIFO 0x24
27#define TPM_INTF_CAPABILITY 0x14
28#define TPM_INT_STATUS 0x10
29#define TPM_INT_ENABLE 0x08
30
31#define LOCALITY0 0
32
33enum st33zp24_access {
34 TPM_ACCESS_VALID = 0x80,
35 TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
36 TPM_ACCESS_REQUEST_PENDING = 0x04,
37 TPM_ACCESS_REQUEST_USE = 0x02,
38};
39
40enum st33zp24_status {
41 TPM_STS_VALID = 0x80,
42 TPM_STS_COMMAND_READY = 0x40,
43 TPM_STS_GO = 0x20,
44 TPM_STS_DATA_AVAIL = 0x10,
45 TPM_STS_DATA_EXPECT = 0x08,
46};
47
48enum st33zp24_int_flags {
49 TPM_GLOBAL_INT_ENABLE = 0x80,
50 TPM_INTF_CMD_READY_INT = 0x080,
51 TPM_INTF_FIFO_AVALAIBLE_INT = 0x040,
52 TPM_INTF_WAKE_UP_READY_INT = 0x020,
53 TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
54 TPM_INTF_STS_VALID_INT = 0x002,
55 TPM_INTF_DATA_AVAIL_INT = 0x001,
56};
57
58enum tis_defaults {
59 TIS_SHORT_TIMEOUT = 750,
60 TIS_LONG_TIMEOUT = 2000,
61};
62
Christophe Ricardbf38b872015-03-08 11:17:14 +010063/*
Sohaib Mohamedf04510f2021-10-13 11:21:50 +020064 * clear the pending interrupt.
Christophe Ricardbf38b872015-03-08 11:17:14 +010065 */
66static u8 clear_interruption(struct st33zp24_dev *tpm_dev)
67{
68 u8 interrupt;
69
70 tpm_dev->ops->recv(tpm_dev->phy_id, TPM_INT_STATUS, &interrupt, 1);
71 tpm_dev->ops->send(tpm_dev->phy_id, TPM_INT_STATUS, &interrupt, 1);
72 return interrupt;
Sohaib Mohamedf04510f2021-10-13 11:21:50 +020073}
Christophe Ricardbf38b872015-03-08 11:17:14 +010074
75/*
Sohaib Mohamedf04510f2021-10-13 11:21:50 +020076 * cancel the current command execution or set STS to COMMAND READY.
Christophe Ricardbf38b872015-03-08 11:17:14 +010077 */
78static void st33zp24_cancel(struct tpm_chip *chip)
79{
Christophe Ricard9e0d39d2016-03-31 22:57:00 +020080 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +010081 u8 data;
82
Christophe Ricardbf38b872015-03-08 11:17:14 +010083 data = TPM_STS_COMMAND_READY;
84 tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1);
Sohaib Mohamedf04510f2021-10-13 11:21:50 +020085}
Christophe Ricardbf38b872015-03-08 11:17:14 +010086
87/*
Sohaib Mohamedf04510f2021-10-13 11:21:50 +020088 * return the TPM_STS register
Christophe Ricardbf38b872015-03-08 11:17:14 +010089 */
90static u8 st33zp24_status(struct tpm_chip *chip)
91{
Christophe Ricard9e0d39d2016-03-31 22:57:00 +020092 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +010093 u8 data;
94
Christophe Ricardbf38b872015-03-08 11:17:14 +010095 tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1);
96 return data;
Sohaib Mohamedf04510f2021-10-13 11:21:50 +020097}
Christophe Ricardbf38b872015-03-08 11:17:14 +010098
99/*
Sohaib Mohamedf04510f2021-10-13 11:21:50 +0200100 * if the locality is active
Christophe Ricardbf38b872015-03-08 11:17:14 +0100101 */
Jerry Snitselaar84d25942017-03-18 01:59:57 -0700102static bool check_locality(struct tpm_chip *chip)
Christophe Ricardbf38b872015-03-08 11:17:14 +0100103{
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200104 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100105 u8 data;
106 u8 status;
107
Christophe Ricardbf38b872015-03-08 11:17:14 +0100108 status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
109 if (status && (data &
110 (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
111 (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
Jerry Snitselaar84d25942017-03-18 01:59:57 -0700112 return true;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100113
Jerry Snitselaar84d25942017-03-18 01:59:57 -0700114 return false;
Sohaib Mohamedf04510f2021-10-13 11:21:50 +0200115}
Christophe Ricardbf38b872015-03-08 11:17:14 +0100116
Christophe Ricardbf38b872015-03-08 11:17:14 +0100117static int request_locality(struct tpm_chip *chip)
118{
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200119 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100120 unsigned long stop;
121 long ret;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100122 u8 data;
123
Jerry Snitselaar84d25942017-03-18 01:59:57 -0700124 if (check_locality(chip))
Christophe Ricard56671c82016-03-31 22:56:58 +0200125 return tpm_dev->locality;
126
Christophe Ricardbf38b872015-03-08 11:17:14 +0100127 data = TPM_ACCESS_REQUEST_USE;
128 ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
129 if (ret < 0)
130 return ret;
131
Christophe Ricardaf782f32016-03-31 22:56:59 +0200132 stop = jiffies + chip->timeout_a;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100133
134 /* Request locality is usually effective after the request */
135 do {
Jerry Snitselaar84d25942017-03-18 01:59:57 -0700136 if (check_locality(chip))
Christophe Ricard56671c82016-03-31 22:56:58 +0200137 return tpm_dev->locality;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100138 msleep(TPM_TIMEOUT);
139 } while (time_before(jiffies, stop));
140
141 /* could not get locality */
142 return -EACCES;
Sohaib Mohamedf04510f2021-10-13 11:21:50 +0200143}
Christophe Ricardbf38b872015-03-08 11:17:14 +0100144
Christophe Ricardbf38b872015-03-08 11:17:14 +0100145static void release_locality(struct tpm_chip *chip)
146{
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200147 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100148 u8 data;
149
Christophe Ricardbf38b872015-03-08 11:17:14 +0100150 data = TPM_ACCESS_ACTIVE_LOCALITY;
151
152 tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
153}
154
155/*
156 * get_burstcount return the burstcount value
Christophe Ricardbf38b872015-03-08 11:17:14 +0100157 */
158static int get_burstcount(struct tpm_chip *chip)
159{
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200160 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100161 unsigned long stop;
162 int burstcnt, status;
Christophe Ricardddab0e32016-03-23 08:55:34 +0100163 u8 temp;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100164
Christophe Ricardaf782f32016-03-31 22:56:59 +0200165 stop = jiffies + chip->timeout_d;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100166 do {
Christophe Ricardddab0e32016-03-23 08:55:34 +0100167 status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS + 1,
168 &temp, 1);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100169 if (status < 0)
170 return -EBUSY;
171
Christophe Ricardbf38b872015-03-08 11:17:14 +0100172 burstcnt = temp;
Christophe Ricardddab0e32016-03-23 08:55:34 +0100173 status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS + 2,
174 &temp, 1);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100175 if (status < 0)
176 return -EBUSY;
177
178 burstcnt |= temp << 8;
179 if (burstcnt)
180 return burstcnt;
181 msleep(TPM_TIMEOUT);
182 } while (time_before(jiffies, stop));
183 return -EBUSY;
Sohaib Mohamedf04510f2021-10-13 11:21:50 +0200184}
Christophe Ricardbf38b872015-03-08 11:17:14 +0100185
Christophe Ricardbf38b872015-03-08 11:17:14 +0100186static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
187 bool check_cancel, bool *canceled)
188{
189 u8 status = chip->ops->status(chip);
190
191 *canceled = false;
192 if ((status & mask) == mask)
193 return true;
194 if (check_cancel && chip->ops->req_canceled(chip, status)) {
195 *canceled = true;
196 return true;
197 }
198 return false;
199}
200
201/*
Sohaib Mohamedf04510f2021-10-13 11:21:50 +0200202 * wait for a TPM_STS value
Christophe Ricardbf38b872015-03-08 11:17:14 +0100203 */
204static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
205 wait_queue_head_t *queue, bool check_cancel)
206{
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200207 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100208 unsigned long stop;
209 int ret = 0;
210 bool canceled = false;
211 bool condition;
212 u32 cur_intrs;
213 u8 status;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100214
215 /* check current status */
216 status = st33zp24_status(chip);
217 if ((status & mask) == mask)
218 return 0;
219
220 stop = jiffies + timeout;
221
Christophe Ricard570a3602016-03-31 22:56:56 +0200222 if (chip->flags & TPM_CHIP_FLAG_IRQ) {
Christophe Ricardbf38b872015-03-08 11:17:14 +0100223 cur_intrs = tpm_dev->intrs;
224 clear_interruption(tpm_dev);
Christophe Ricard570a3602016-03-31 22:56:56 +0200225 enable_irq(tpm_dev->irq);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100226
227 do {
228 if (ret == -ERESTARTSYS && freezing(current))
229 clear_thread_flag(TIF_SIGPENDING);
230
231 timeout = stop - jiffies;
232 if ((long) timeout <= 0)
233 return -1;
234
235 ret = wait_event_interruptible_timeout(*queue,
236 cur_intrs != tpm_dev->intrs,
237 timeout);
238 clear_interruption(tpm_dev);
239 condition = wait_for_tpm_stat_cond(chip, mask,
240 check_cancel, &canceled);
241 if (ret >= 0 && condition) {
242 if (canceled)
243 return -ECANCELED;
244 return 0;
245 }
246 } while (ret == -ERESTARTSYS && freezing(current));
247
Christophe Ricard570a3602016-03-31 22:56:56 +0200248 disable_irq_nosync(tpm_dev->irq);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100249
250 } else {
251 do {
252 msleep(TPM_TIMEOUT);
253 status = chip->ops->status(chip);
254 if ((status & mask) == mask)
255 return 0;
256 } while (time_before(jiffies, stop));
257 }
258
259 return -ETIME;
Sohaib Mohamedf04510f2021-10-13 11:21:50 +0200260}
Christophe Ricardbf38b872015-03-08 11:17:14 +0100261
Christophe Ricardbf38b872015-03-08 11:17:14 +0100262static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
263{
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200264 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100265 int size = 0, burstcnt, len, ret;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100266
267 while (size < count &&
268 wait_for_stat(chip,
269 TPM_STS_DATA_AVAIL | TPM_STS_VALID,
Christophe Ricardaf782f32016-03-31 22:56:59 +0200270 chip->timeout_c,
Christophe Ricard6e599f62016-03-31 22:56:57 +0200271 &tpm_dev->read_queue, true) == 0) {
Christophe Ricardbf38b872015-03-08 11:17:14 +0100272 burstcnt = get_burstcount(chip);
273 if (burstcnt < 0)
274 return burstcnt;
275 len = min_t(int, burstcnt, count - size);
276 ret = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_DATA_FIFO,
277 buf + size, len);
278 if (ret < 0)
279 return ret;
280
281 size += len;
282 }
283 return size;
284}
285
Christophe Ricardbf38b872015-03-08 11:17:14 +0100286static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id)
287{
288 struct tpm_chip *chip = dev_id;
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200289 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100290
291 tpm_dev->intrs++;
Christophe Ricard6e599f62016-03-31 22:56:57 +0200292 wake_up_interruptible(&tpm_dev->read_queue);
Christophe Ricard570a3602016-03-31 22:56:56 +0200293 disable_irq_nosync(tpm_dev->irq);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100294
295 return IRQ_HANDLED;
Sohaib Mohamedf04510f2021-10-13 11:21:50 +0200296}
Christophe Ricardbf38b872015-03-08 11:17:14 +0100297
298/*
Sohaib Mohamedf04510f2021-10-13 11:21:50 +0200299 * send TPM commands through the I2C bus.
Christophe Ricardbf38b872015-03-08 11:17:14 +0100300 */
301static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
302 size_t len)
303{
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200304 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricard7216ebc2015-03-23 22:29:56 +0100305 u32 status, i, size, ordinal;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100306 int burstcnt = 0;
307 int ret;
308 u8 data;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100309
Christophe Ricardbf38b872015-03-08 11:17:14 +0100310 if (len < TPM_HEADER_SIZE)
311 return -EBUSY;
312
Christophe Ricardbf38b872015-03-08 11:17:14 +0100313 ret = request_locality(chip);
314 if (ret < 0)
315 return ret;
316
317 status = st33zp24_status(chip);
318 if ((status & TPM_STS_COMMAND_READY) == 0) {
319 st33zp24_cancel(chip);
320 if (wait_for_stat
Christophe Ricardaf782f32016-03-31 22:56:59 +0200321 (chip, TPM_STS_COMMAND_READY, chip->timeout_b,
Christophe Ricard6e599f62016-03-31 22:56:57 +0200322 &tpm_dev->read_queue, false) < 0) {
Christophe Ricardbf38b872015-03-08 11:17:14 +0100323 ret = -ETIME;
324 goto out_err;
325 }
326 }
327
328 for (i = 0; i < len - 1;) {
329 burstcnt = get_burstcount(chip);
330 if (burstcnt < 0)
331 return burstcnt;
332 size = min_t(int, len - i - 1, burstcnt);
333 ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_DATA_FIFO,
334 buf + i, size);
335 if (ret < 0)
336 goto out_err;
337
338 i += size;
339 }
340
341 status = st33zp24_status(chip);
342 if ((status & TPM_STS_DATA_EXPECT) == 0) {
343 ret = -EIO;
344 goto out_err;
345 }
346
347 ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_DATA_FIFO,
348 buf + len - 1, 1);
349 if (ret < 0)
350 goto out_err;
351
352 status = st33zp24_status(chip);
353 if ((status & TPM_STS_DATA_EXPECT) != 0) {
354 ret = -EIO;
355 goto out_err;
356 }
357
358 data = TPM_STS_GO;
359 ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1);
360 if (ret < 0)
361 goto out_err;
362
Christophe Ricard570a3602016-03-31 22:56:56 +0200363 if (chip->flags & TPM_CHIP_FLAG_IRQ) {
Christophe Ricard7216ebc2015-03-23 22:29:56 +0100364 ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
365
366 ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
Tomas Winklerd856c002018-10-19 21:22:51 +0300367 tpm_calc_ordinal_duration(chip, ordinal),
Christophe Ricard6e599f62016-03-31 22:56:57 +0200368 &tpm_dev->read_queue, false);
Christophe Ricard7216ebc2015-03-23 22:29:56 +0100369 if (ret < 0)
370 goto out_err;
371 }
372
Jarkko Sakkinenf5595f52019-02-08 18:30:58 +0200373 return 0;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100374out_err:
375 st33zp24_cancel(chip);
376 release_locality(chip);
377 return ret;
378}
379
Christophe Ricardbf38b872015-03-08 11:17:14 +0100380static int st33zp24_recv(struct tpm_chip *chip, unsigned char *buf,
381 size_t count)
382{
383 int size = 0;
Jeremy Boone6d24cd12018-02-08 12:29:09 -0800384 u32 expected;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100385
386 if (!chip)
387 return -EBUSY;
388
389 if (count < TPM_HEADER_SIZE) {
390 size = -EIO;
391 goto out;
392 }
393
394 size = recv_data(chip, buf, TPM_HEADER_SIZE);
395 if (size < TPM_HEADER_SIZE) {
396 dev_err(&chip->dev, "Unable to read header\n");
397 goto out;
398 }
399
400 expected = be32_to_cpu(*(__be32 *)(buf + 2));
Jeremy Boone6d24cd12018-02-08 12:29:09 -0800401 if (expected > count || expected < TPM_HEADER_SIZE) {
Christophe Ricardbf38b872015-03-08 11:17:14 +0100402 size = -EIO;
403 goto out;
404 }
405
406 size += recv_data(chip, &buf[TPM_HEADER_SIZE],
407 expected - TPM_HEADER_SIZE);
408 if (size < expected) {
409 dev_err(&chip->dev, "Unable to read remainder of result\n");
410 size = -ETIME;
411 }
412
413out:
414 st33zp24_cancel(chip);
415 release_locality(chip);
416 return size;
417}
418
Christophe Ricardbf38b872015-03-08 11:17:14 +0100419static bool st33zp24_req_canceled(struct tpm_chip *chip, u8 status)
420{
421 return (status == TPM_STS_COMMAND_READY);
422}
423
424static const struct tpm_class_ops st33zp24_tpm = {
Jason Gunthorpecae8b442016-07-12 11:41:49 -0600425 .flags = TPM_OPS_AUTO_STARTUP,
Christophe Ricardbf38b872015-03-08 11:17:14 +0100426 .send = st33zp24_send,
427 .recv = st33zp24_recv,
428 .cancel = st33zp24_cancel,
429 .status = st33zp24_status,
430 .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
431 .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
432 .req_canceled = st33zp24_req_canceled,
433};
434
435/*
Sohaib Mohamedf04510f2021-10-13 11:21:50 +0200436 * initialize the TPM device
Christophe Ricardbf38b872015-03-08 11:17:14 +0100437 */
438int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
439 struct device *dev, int irq, int io_lpcpd)
440{
441 int ret;
442 u8 intmask = 0;
443 struct tpm_chip *chip;
444 struct st33zp24_dev *tpm_dev;
445
446 chip = tpmm_chip_alloc(dev, &st33zp24_tpm);
447 if (IS_ERR(chip))
448 return PTR_ERR(chip);
449
450 tpm_dev = devm_kzalloc(dev, sizeof(struct st33zp24_dev),
451 GFP_KERNEL);
452 if (!tpm_dev)
453 return -ENOMEM;
454
Christophe Ricardbf38b872015-03-08 11:17:14 +0100455 tpm_dev->phy_id = phy_id;
456 tpm_dev->ops = ops;
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200457 dev_set_drvdata(&chip->dev, tpm_dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100458
Christophe Ricardaf782f32016-03-31 22:56:59 +0200459 chip->timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
460 chip->timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
461 chip->timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
462 chip->timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100463
Christophe Ricard56671c82016-03-31 22:56:58 +0200464 tpm_dev->locality = LOCALITY0;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100465
466 if (irq) {
467 /* INTERRUPT Setup */
Christophe Ricard6e599f62016-03-31 22:56:57 +0200468 init_waitqueue_head(&tpm_dev->read_queue);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100469 tpm_dev->intrs = 0;
470
471 if (request_locality(chip) != LOCALITY0) {
472 ret = -ENODEV;
473 goto _tpm_clean_answer;
474 }
475
476 clear_interruption(tpm_dev);
477 ret = devm_request_irq(dev, irq, tpm_ioserirq_handler,
478 IRQF_TRIGGER_HIGH, "TPM SERIRQ management",
479 chip);
480 if (ret < 0) {
481 dev_err(&chip->dev, "TPM SERIRQ signals %d not available\n",
482 irq);
483 goto _tpm_clean_answer;
484 }
485
486 intmask |= TPM_INTF_CMD_READY_INT
487 | TPM_INTF_STS_VALID_INT
488 | TPM_INTF_DATA_AVAIL_INT;
489
490 ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_INT_ENABLE,
491 &intmask, 1);
492 if (ret < 0)
493 goto _tpm_clean_answer;
494
495 intmask = TPM_GLOBAL_INT_ENABLE;
496 ret = tpm_dev->ops->send(tpm_dev->phy_id, (TPM_INT_ENABLE + 3),
497 &intmask, 1);
498 if (ret < 0)
499 goto _tpm_clean_answer;
500
Christophe Ricard570a3602016-03-31 22:56:56 +0200501 tpm_dev->irq = irq;
502 chip->flags |= TPM_CHIP_FLAG_IRQ;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100503
Christophe Ricard570a3602016-03-31 22:56:56 +0200504 disable_irq_nosync(tpm_dev->irq);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100505 }
506
Christophe Ricardbf38b872015-03-08 11:17:14 +0100507 return tpm_chip_register(chip);
508_tpm_clean_answer:
509 dev_info(&chip->dev, "TPM initialization fail\n");
510 return ret;
511}
512EXPORT_SYMBOL(st33zp24_probe);
513
Christophe Ricardbf38b872015-03-08 11:17:14 +0100514int st33zp24_remove(struct tpm_chip *chip)
515{
516 tpm_chip_unregister(chip);
517 return 0;
518}
519EXPORT_SYMBOL(st33zp24_remove);
520
521#ifdef CONFIG_PM_SLEEP
Christophe Ricardbf38b872015-03-08 11:17:14 +0100522int st33zp24_pm_suspend(struct device *dev)
523{
524 struct tpm_chip *chip = dev_get_drvdata(dev);
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200525 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100526
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200527 int ret = 0;
Christophe Ricardbf38b872015-03-08 11:17:14 +0100528
529 if (gpio_is_valid(tpm_dev->io_lpcpd))
530 gpio_set_value(tpm_dev->io_lpcpd, 0);
531 else
532 ret = tpm_pm_suspend(dev);
533
534 return ret;
Sohaib Mohamedf04510f2021-10-13 11:21:50 +0200535}
Christophe Ricardbf38b872015-03-08 11:17:14 +0100536EXPORT_SYMBOL(st33zp24_pm_suspend);
537
Christophe Ricardbf38b872015-03-08 11:17:14 +0100538int st33zp24_pm_resume(struct device *dev)
539{
540 struct tpm_chip *chip = dev_get_drvdata(dev);
Christophe Ricard9e0d39d2016-03-31 22:57:00 +0200541 struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100542 int ret = 0;
543
Christophe Ricardbf38b872015-03-08 11:17:14 +0100544 if (gpio_is_valid(tpm_dev->io_lpcpd)) {
545 gpio_set_value(tpm_dev->io_lpcpd, 1);
546 ret = wait_for_stat(chip,
Christophe Ricardaf782f32016-03-31 22:56:59 +0200547 TPM_STS_VALID, chip->timeout_b,
Christophe Ricard6e599f62016-03-31 22:56:57 +0200548 &tpm_dev->read_queue, false);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100549 } else {
550 ret = tpm_pm_resume(dev);
551 if (!ret)
Tomas Winklerd4a317562018-10-19 21:22:56 +0300552 tpm1_do_selftest(chip);
Christophe Ricardbf38b872015-03-08 11:17:14 +0100553 }
554 return ret;
Sohaib Mohamedf04510f2021-10-13 11:21:50 +0200555}
Christophe Ricardbf38b872015-03-08 11:17:14 +0100556EXPORT_SYMBOL(st33zp24_pm_resume);
557#endif
558
559MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)");
560MODULE_DESCRIPTION("ST33ZP24 TPM 1.2 driver");
561MODULE_VERSION("1.3.0");
562MODULE_LICENSE("GPL");