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