diff options
Diffstat (limited to 'drivers/char/tpm/tpm_i2c_stm_st33.c')
-rw-r--r-- | drivers/char/tpm/tpm_i2c_stm_st33.c | 887 |
1 files changed, 887 insertions, 0 deletions
diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c new file mode 100644 index 000000000000..1f5f71e14abe --- /dev/null +++ b/drivers/char/tpm/tpm_i2c_stm_st33.c | |||
@@ -0,0 +1,887 @@ | |||
1 | /* | ||
2 | * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24 | ||
3 | * Copyright (C) 2009, 2010 STMicroelectronics | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * | ||
19 | * STMicroelectronics version 1.2.0, Copyright (C) 2010 | ||
20 | * STMicroelectronics comes with ABSOLUTELY NO WARRANTY. | ||
21 | * This is free software, and you are welcome to redistribute it | ||
22 | * under certain conditions. | ||
23 | * | ||
24 | * @Author: Christophe RICARD tpmsupport@st.com | ||
25 | * | ||
26 | * @File: tpm_stm_st33_i2c.c | ||
27 | * | ||
28 | * @Synopsis: | ||
29 | * 09/15/2010: First shot driver tpm_tis driver for | ||
30 | lpc is used as model. | ||
31 | */ | ||
32 | |||
33 | #include <linux/pci.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/platform_device.h> | ||
36 | #include <linux/i2c.h> | ||
37 | #include <linux/fs.h> | ||
38 | #include <linux/miscdevice.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/kernel.h> | ||
41 | #include <linux/delay.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/wait.h> | ||
44 | #include <linux/string.h> | ||
45 | #include <linux/interrupt.h> | ||
46 | #include <linux/spinlock.h> | ||
47 | #include <linux/sysfs.h> | ||
48 | #include <linux/gpio.h> | ||
49 | #include <linux/sched.h> | ||
50 | #include <linux/uaccess.h> | ||
51 | #include <linux/io.h> | ||
52 | #include <linux/slab.h> | ||
53 | #include <linux/sched.h> | ||
54 | |||
55 | #include "tpm.h" | ||
56 | #include "tpm_i2c_stm_st33.h" | ||
57 | |||
58 | enum stm33zp24_access { | ||
59 | TPM_ACCESS_VALID = 0x80, | ||
60 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, | ||
61 | TPM_ACCESS_REQUEST_PENDING = 0x04, | ||
62 | TPM_ACCESS_REQUEST_USE = 0x02, | ||
63 | }; | ||
64 | |||
65 | enum stm33zp24_status { | ||
66 | TPM_STS_VALID = 0x80, | ||
67 | TPM_STS_COMMAND_READY = 0x40, | ||
68 | TPM_STS_GO = 0x20, | ||
69 | TPM_STS_DATA_AVAIL = 0x10, | ||
70 | TPM_STS_DATA_EXPECT = 0x08, | ||
71 | }; | ||
72 | |||
73 | enum stm33zp24_int_flags { | ||
74 | TPM_GLOBAL_INT_ENABLE = 0x80, | ||
75 | TPM_INTF_CMD_READY_INT = 0x080, | ||
76 | TPM_INTF_FIFO_AVALAIBLE_INT = 0x040, | ||
77 | TPM_INTF_WAKE_UP_READY_INT = 0x020, | ||
78 | TPM_INTF_LOCALITY_CHANGE_INT = 0x004, | ||
79 | TPM_INTF_STS_VALID_INT = 0x002, | ||
80 | TPM_INTF_DATA_AVAIL_INT = 0x001, | ||
81 | }; | ||
82 | |||
83 | enum tis_defaults { | ||
84 | TIS_SHORT_TIMEOUT = 750, | ||
85 | TIS_LONG_TIMEOUT = 2000, | ||
86 | }; | ||
87 | |||
88 | /* | ||
89 | * write8_reg | ||
90 | * Send byte to the TIS register according to the ST33ZP24 I2C protocol. | ||
91 | * @param: tpm_register, the tpm tis register where the data should be written | ||
92 | * @param: tpm_data, the tpm_data to write inside the tpm_register | ||
93 | * @param: tpm_size, The length of the data | ||
94 | * @return: Returns negative errno, or else the number of bytes written. | ||
95 | */ | ||
96 | static int write8_reg(struct i2c_client *client, u8 tpm_register, | ||
97 | u8 *tpm_data, u16 tpm_size) | ||
98 | { | ||
99 | struct st33zp24_platform_data *pin_infos; | ||
100 | |||
101 | pin_infos = client->dev.platform_data; | ||
102 | |||
103 | pin_infos->tpm_i2c_buffer[0][0] = tpm_register; | ||
104 | memcpy(&pin_infos->tpm_i2c_buffer[0][1], tpm_data, tpm_size); | ||
105 | return i2c_master_send(client, pin_infos->tpm_i2c_buffer[0], | ||
106 | tpm_size + 1); | ||
107 | } /* write8_reg() */ | ||
108 | |||
109 | /* | ||
110 | * read8_reg | ||
111 | * Recv byte from the TIS register according to the ST33ZP24 I2C protocol. | ||
112 | * @param: tpm_register, the tpm tis register where the data should be read | ||
113 | * @param: tpm_data, the TPM response | ||
114 | * @param: tpm_size, tpm TPM response size to read. | ||
115 | * @return: number of byte read successfully: should be one if success. | ||
116 | */ | ||
117 | static int read8_reg(struct i2c_client *client, u8 tpm_register, | ||
118 | u8 *tpm_data, int tpm_size) | ||
119 | { | ||
120 | u8 status = 0; | ||
121 | u8 data; | ||
122 | |||
123 | data = TPM_DUMMY_BYTE; | ||
124 | status = write8_reg(client, tpm_register, &data, 1); | ||
125 | if (status == 2) | ||
126 | status = i2c_master_recv(client, tpm_data, tpm_size); | ||
127 | return status; | ||
128 | } /* read8_reg() */ | ||
129 | |||
130 | /* | ||
131 | * I2C_WRITE_DATA | ||
132 | * Send byte to the TIS register according to the ST33ZP24 I2C protocol. | ||
133 | * @param: client, the chip description | ||
134 | * @param: tpm_register, the tpm tis register where the data should be written | ||
135 | * @param: tpm_data, the tpm_data to write inside the tpm_register | ||
136 | * @param: tpm_size, The length of the data | ||
137 | * @return: number of byte written successfully: should be one if success. | ||
138 | */ | ||
139 | #define I2C_WRITE_DATA(client, tpm_register, tpm_data, tpm_size) \ | ||
140 | (write8_reg(client, tpm_register | \ | ||
141 | TPM_WRITE_DIRECTION, tpm_data, tpm_size)) | ||
142 | |||
143 | /* | ||
144 | * I2C_READ_DATA | ||
145 | * Recv byte from the TIS register according to the ST33ZP24 I2C protocol. | ||
146 | * @param: tpm, the chip description | ||
147 | * @param: tpm_register, the tpm tis register where the data should be read | ||
148 | * @param: tpm_data, the TPM response | ||
149 | * @param: tpm_size, tpm TPM response size to read. | ||
150 | * @return: number of byte read successfully: should be one if success. | ||
151 | */ | ||
152 | #define I2C_READ_DATA(client, tpm_register, tpm_data, tpm_size) \ | ||
153 | (read8_reg(client, tpm_register, tpm_data, tpm_size)) | ||
154 | |||
155 | /* | ||
156 | * clear_interruption | ||
157 | * clear the TPM interrupt register. | ||
158 | * @param: tpm, the chip description | ||
159 | */ | ||
160 | static void clear_interruption(struct i2c_client *client) | ||
161 | { | ||
162 | u8 interrupt; | ||
163 | I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1); | ||
164 | I2C_WRITE_DATA(client, TPM_INT_STATUS, &interrupt, 1); | ||
165 | I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1); | ||
166 | } /* clear_interruption() */ | ||
167 | |||
168 | /* | ||
169 | * _wait_for_interrupt_serirq_timeout | ||
170 | * @param: tpm, the chip description | ||
171 | * @param: timeout, the timeout of the interrupt | ||
172 | * @return: the status of the interruption. | ||
173 | */ | ||
174 | static long _wait_for_interrupt_serirq_timeout(struct tpm_chip *chip, | ||
175 | unsigned long timeout) | ||
176 | { | ||
177 | long status; | ||
178 | struct i2c_client *client; | ||
179 | struct st33zp24_platform_data *pin_infos; | ||
180 | |||
181 | client = (struct i2c_client *) TPM_VPRIV(chip); | ||
182 | pin_infos = client->dev.platform_data; | ||
183 | |||
184 | status = wait_for_completion_interruptible_timeout( | ||
185 | &pin_infos->irq_detection, | ||
186 | timeout); | ||
187 | if (status > 0) | ||
188 | enable_irq(gpio_to_irq(pin_infos->io_serirq)); | ||
189 | gpio_direction_input(pin_infos->io_serirq); | ||
190 | |||
191 | return status; | ||
192 | } /* wait_for_interrupt_serirq_timeout() */ | ||
193 | |||
194 | static int wait_for_serirq_timeout(struct tpm_chip *chip, bool condition, | ||
195 | unsigned long timeout) | ||
196 | { | ||
197 | int status = 2; | ||
198 | struct i2c_client *client; | ||
199 | |||
200 | client = (struct i2c_client *) TPM_VPRIV(chip); | ||
201 | |||
202 | status = _wait_for_interrupt_serirq_timeout(chip, timeout); | ||
203 | if (!status) { | ||
204 | status = -EBUSY; | ||
205 | } else{ | ||
206 | clear_interruption(client); | ||
207 | if (condition) | ||
208 | status = 1; | ||
209 | } | ||
210 | return status; | ||
211 | } | ||
212 | |||
213 | /* | ||
214 | * tpm_stm_i2c_cancel, cancel is not implemented. | ||
215 | * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h | ||
216 | */ | ||
217 | static void tpm_stm_i2c_cancel(struct tpm_chip *chip) | ||
218 | { | ||
219 | struct i2c_client *client; | ||
220 | u8 data; | ||
221 | |||
222 | client = (struct i2c_client *) TPM_VPRIV(chip); | ||
223 | |||
224 | data = TPM_STS_COMMAND_READY; | ||
225 | I2C_WRITE_DATA(client, TPM_STS, &data, 1); | ||
226 | if (chip->vendor.irq) | ||
227 | wait_for_serirq_timeout(chip, 1, chip->vendor.timeout_a); | ||
228 | } /* tpm_stm_i2c_cancel() */ | ||
229 | |||
230 | /* | ||
231 | * tpm_stm_spi_status return the TPM_STS register | ||
232 | * @param: chip, the tpm chip description | ||
233 | * @return: the TPM_STS register value. | ||
234 | */ | ||
235 | static u8 tpm_stm_i2c_status(struct tpm_chip *chip) | ||
236 | { | ||
237 | struct i2c_client *client; | ||
238 | u8 data; | ||
239 | client = (struct i2c_client *) TPM_VPRIV(chip); | ||
240 | |||
241 | I2C_READ_DATA(client, TPM_STS, &data, 1); | ||
242 | return data; | ||
243 | } /* tpm_stm_i2c_status() */ | ||
244 | |||
245 | |||
246 | /* | ||
247 | * check_locality if the locality is active | ||
248 | * @param: chip, the tpm chip description | ||
249 | * @return: the active locality or -EACCESS. | ||
250 | */ | ||
251 | static int check_locality(struct tpm_chip *chip) | ||
252 | { | ||
253 | struct i2c_client *client; | ||
254 | u8 data; | ||
255 | u8 status; | ||
256 | |||
257 | client = (struct i2c_client *) TPM_VPRIV(chip); | ||
258 | |||
259 | status = I2C_READ_DATA(client, TPM_ACCESS, &data, 1); | ||
260 | if (status && (data & | ||
261 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == | ||
262 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) | ||
263 | return chip->vendor.locality; | ||
264 | |||
265 | return -EACCES; | ||
266 | |||
267 | } /* check_locality() */ | ||
268 | |||
269 | /* | ||
270 | * request_locality request the TPM locality | ||
271 | * @param: chip, the chip description | ||
272 | * @return: the active locality or EACCESS. | ||
273 | */ | ||
274 | static int request_locality(struct tpm_chip *chip) | ||
275 | { | ||
276 | unsigned long stop; | ||
277 | long rc; | ||
278 | struct i2c_client *client; | ||
279 | u8 data; | ||
280 | |||
281 | client = (struct i2c_client *) TPM_VPRIV(chip); | ||
282 | |||
283 | if (check_locality(chip) == chip->vendor.locality) | ||
284 | return chip->vendor.locality; | ||
285 | |||
286 | data = TPM_ACCESS_REQUEST_USE; | ||
287 | rc = I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1); | ||
288 | if (rc < 0) | ||
289 | goto end; | ||
290 | |||
291 | if (chip->vendor.irq) { | ||
292 | rc = wait_for_serirq_timeout(chip, (check_locality | ||
293 | (chip) >= 0), | ||
294 | chip->vendor.timeout_a); | ||
295 | if (rc > 0) | ||
296 | return chip->vendor.locality; | ||
297 | } else{ | ||
298 | stop = jiffies + chip->vendor.timeout_a; | ||
299 | do { | ||
300 | if (check_locality(chip) >= 0) | ||
301 | return chip->vendor.locality; | ||
302 | msleep(TPM_TIMEOUT); | ||
303 | } while (time_before(jiffies, stop)); | ||
304 | } | ||
305 | rc = -EACCES; | ||
306 | end: | ||
307 | return rc; | ||
308 | } /* request_locality() */ | ||
309 | |||
310 | /* | ||
311 | * release_locality release the active locality | ||
312 | * @param: chip, the tpm chip description. | ||
313 | */ | ||
314 | static void release_locality(struct tpm_chip *chip) | ||
315 | { | ||
316 | struct i2c_client *client; | ||
317 | u8 data; | ||
318 | |||
319 | client = (struct i2c_client *) TPM_VPRIV(chip); | ||
320 | data = TPM_ACCESS_ACTIVE_LOCALITY; | ||
321 | |||
322 | I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1); | ||
323 | } | ||
324 | |||
325 | /* | ||
326 | * get_burstcount return the burstcount address 0x19 0x1A | ||
327 | * @param: chip, the chip description | ||
328 | * return: the burstcount. | ||
329 | */ | ||
330 | static int get_burstcount(struct tpm_chip *chip) | ||
331 | { | ||
332 | unsigned long stop; | ||
333 | int burstcnt, status; | ||
334 | u8 tpm_reg, temp; | ||
335 | |||
336 | struct i2c_client *client = (struct i2c_client *) TPM_VPRIV(chip); | ||
337 | |||
338 | stop = jiffies + chip->vendor.timeout_d; | ||
339 | do { | ||
340 | tpm_reg = TPM_STS + 1; | ||
341 | status = I2C_READ_DATA(client, tpm_reg, &temp, 1); | ||
342 | if (status < 0) | ||
343 | goto end; | ||
344 | |||
345 | tpm_reg = tpm_reg + 1; | ||
346 | burstcnt = temp; | ||
347 | status = I2C_READ_DATA(client, tpm_reg, &temp, 1); | ||
348 | if (status < 0) | ||
349 | goto end; | ||
350 | |||
351 | burstcnt |= temp << 8; | ||
352 | if (burstcnt) | ||
353 | return burstcnt; | ||
354 | msleep(TPM_TIMEOUT); | ||
355 | } while (time_before(jiffies, stop)); | ||
356 | |||
357 | end: | ||
358 | return -EBUSY; | ||
359 | } /* get_burstcount() */ | ||
360 | |||
361 | /* | ||
362 | * wait_for_stat wait for a TPM_STS value | ||
363 | * @param: chip, the tpm chip description | ||
364 | * @param: mask, the value mask to wait | ||
365 | * @param: timeout, the timeout | ||
366 | * @param: queue, the wait queue. | ||
367 | * @return: the tpm status, 0 if success, -ETIME if timeout is reached. | ||
368 | */ | ||
369 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
370 | wait_queue_head_t *queue) | ||
371 | { | ||
372 | unsigned long stop; | ||
373 | long rc; | ||
374 | u8 status; | ||
375 | |||
376 | if (chip->vendor.irq) { | ||
377 | rc = wait_for_serirq_timeout(chip, ((tpm_stm_i2c_status | ||
378 | (chip) & mask) == | ||
379 | mask), timeout); | ||
380 | if (rc > 0) | ||
381 | return 0; | ||
382 | } else{ | ||
383 | stop = jiffies + timeout; | ||
384 | do { | ||
385 | msleep(TPM_TIMEOUT); | ||
386 | status = tpm_stm_i2c_status(chip); | ||
387 | if ((status & mask) == mask) | ||
388 | return 0; | ||
389 | } while (time_before(jiffies, stop)); | ||
390 | } | ||
391 | return -ETIME; | ||
392 | } /* wait_for_stat() */ | ||
393 | |||
394 | /* | ||
395 | * recv_data receive data | ||
396 | * @param: chip, the tpm chip description | ||
397 | * @param: buf, the buffer where the data are received | ||
398 | * @param: count, the number of data to receive | ||
399 | * @return: the number of bytes read from TPM FIFO. | ||
400 | */ | ||
401 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | ||
402 | { | ||
403 | int size = 0, burstcnt, len; | ||
404 | struct i2c_client *client; | ||
405 | |||
406 | client = (struct i2c_client *) TPM_VPRIV(chip); | ||
407 | |||
408 | while (size < count && | ||
409 | wait_for_stat(chip, | ||
410 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
411 | chip->vendor.timeout_c, | ||
412 | &chip->vendor.read_queue) | ||
413 | == 0) { | ||
414 | burstcnt = get_burstcount(chip); | ||
415 | len = min_t(int, burstcnt, count - size); | ||
416 | I2C_READ_DATA(client, TPM_DATA_FIFO, buf + size, len); | ||
417 | size += len; | ||
418 | } | ||
419 | return size; | ||
420 | } | ||
421 | |||
422 | /* | ||
423 | * tpm_ioserirq_handler the serirq irq handler | ||
424 | * @param: irq, the tpm chip description | ||
425 | * @param: dev_id, the description of the chip | ||
426 | * @return: the status of the handler. | ||
427 | */ | ||
428 | static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) | ||
429 | { | ||
430 | struct tpm_chip *chip = dev_id; | ||
431 | struct i2c_client *client; | ||
432 | struct st33zp24_platform_data *pin_infos; | ||
433 | |||
434 | disable_irq_nosync(irq); | ||
435 | |||
436 | client = (struct i2c_client *) TPM_VPRIV(chip); | ||
437 | pin_infos = client->dev.platform_data; | ||
438 | |||
439 | complete(&pin_infos->irq_detection); | ||
440 | return IRQ_HANDLED; | ||
441 | } /* tpm_ioserirq_handler() */ | ||
442 | |||
443 | |||
444 | /* | ||
445 | * tpm_stm_i2c_send send TPM commands through the I2C bus. | ||
446 | * | ||
447 | * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h | ||
448 | * @param: buf, the buffer to send. | ||
449 | * @param: count, the number of bytes to send. | ||
450 | * @return: In case of success the number of bytes sent. | ||
451 | * In other case, a < 0 value describing the issue. | ||
452 | */ | ||
453 | static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, | ||
454 | size_t len) | ||
455 | { | ||
456 | u32 status, | ||
457 | burstcnt = 0, i, size; | ||
458 | int ret; | ||
459 | u8 data; | ||
460 | struct i2c_client *client; | ||
461 | |||
462 | if (chip == NULL) | ||
463 | return -EBUSY; | ||
464 | if (len < TPM_HEADER_SIZE) | ||
465 | return -EBUSY; | ||
466 | |||
467 | client = (struct i2c_client *)TPM_VPRIV(chip); | ||
468 | |||
469 | client->flags = 0; | ||
470 | |||
471 | ret = request_locality(chip); | ||
472 | if (ret < 0) | ||
473 | return ret; | ||
474 | |||
475 | status = tpm_stm_i2c_status(chip); | ||
476 | if ((status & TPM_STS_COMMAND_READY) == 0) { | ||
477 | tpm_stm_i2c_cancel(chip); | ||
478 | if (wait_for_stat | ||
479 | (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, | ||
480 | &chip->vendor.int_queue) < 0) { | ||
481 | ret = -ETIME; | ||
482 | goto out_err; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | for (i = 0 ; i < len - 1 ;) { | ||
487 | burstcnt = get_burstcount(chip); | ||
488 | size = min_t(int, len - i - 1, burstcnt); | ||
489 | ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size); | ||
490 | if (ret < 0) | ||
491 | goto out_err; | ||
492 | |||
493 | i += size; | ||
494 | } | ||
495 | |||
496 | status = tpm_stm_i2c_status(chip); | ||
497 | if ((status & TPM_STS_DATA_EXPECT) == 0) { | ||
498 | ret = -EIO; | ||
499 | goto out_err; | ||
500 | } | ||
501 | |||
502 | ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf + len - 1, 1); | ||
503 | if (ret < 0) | ||
504 | goto out_err; | ||
505 | |||
506 | status = tpm_stm_i2c_status(chip); | ||
507 | if ((status & TPM_STS_DATA_EXPECT) != 0) { | ||
508 | ret = -EIO; | ||
509 | goto out_err; | ||
510 | } | ||
511 | |||
512 | data = TPM_STS_GO; | ||
513 | I2C_WRITE_DATA(client, TPM_STS, &data, 1); | ||
514 | |||
515 | return len; | ||
516 | out_err: | ||
517 | tpm_stm_i2c_cancel(chip); | ||
518 | release_locality(chip); | ||
519 | return ret; | ||
520 | } | ||
521 | |||
522 | /* | ||
523 | * tpm_stm_i2c_recv received TPM response through the I2C bus. | ||
524 | * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h. | ||
525 | * @param: buf, the buffer to store datas. | ||
526 | * @param: count, the number of bytes to send. | ||
527 | * @return: In case of success the number of bytes received. | ||
528 | * In other case, a < 0 value describing the issue. | ||
529 | */ | ||
530 | static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf, | ||
531 | size_t count) | ||
532 | { | ||
533 | int size = 0; | ||
534 | int expected; | ||
535 | |||
536 | if (chip == NULL) | ||
537 | return -EBUSY; | ||
538 | |||
539 | if (count < TPM_HEADER_SIZE) { | ||
540 | size = -EIO; | ||
541 | goto out; | ||
542 | } | ||
543 | |||
544 | size = recv_data(chip, buf, TPM_HEADER_SIZE); | ||
545 | if (size < TPM_HEADER_SIZE) { | ||
546 | dev_err(chip->dev, "Unable to read header\n"); | ||
547 | goto out; | ||
548 | } | ||
549 | |||
550 | expected = be32_to_cpu(*(__be32 *) (buf + 2)); | ||
551 | if (expected > count) { | ||
552 | size = -EIO; | ||
553 | goto out; | ||
554 | } | ||
555 | |||
556 | size += recv_data(chip, &buf[TPM_HEADER_SIZE], | ||
557 | expected - TPM_HEADER_SIZE); | ||
558 | if (size < expected) { | ||
559 | dev_err(chip->dev, "Unable to read remainder of result\n"); | ||
560 | size = -ETIME; | ||
561 | goto out; | ||
562 | } | ||
563 | |||
564 | out: | ||
565 | chip->vendor.cancel(chip); | ||
566 | release_locality(chip); | ||
567 | return size; | ||
568 | } | ||
569 | |||
570 | static bool tpm_st33_i2c_req_canceled(struct tpm_chip *chip, u8 status) | ||
571 | { | ||
572 | return (status == TPM_STS_COMMAND_READY); | ||
573 | } | ||
574 | |||
575 | static const struct file_operations tpm_st33_i2c_fops = { | ||
576 | .owner = THIS_MODULE, | ||
577 | .llseek = no_llseek, | ||
578 | .read = tpm_read, | ||
579 | .write = tpm_write, | ||
580 | .open = tpm_open, | ||
581 | .release = tpm_release, | ||
582 | }; | ||
583 | |||
584 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | ||
585 | static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); | ||
586 | static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); | ||
587 | static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); | ||
588 | static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); | ||
589 | static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL); | ||
590 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); | ||
591 | static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); | ||
592 | |||
593 | static struct attribute *stm_tpm_attrs[] = { | ||
594 | &dev_attr_pubek.attr, | ||
595 | &dev_attr_pcrs.attr, | ||
596 | &dev_attr_enabled.attr, | ||
597 | &dev_attr_active.attr, | ||
598 | &dev_attr_owned.attr, | ||
599 | &dev_attr_temp_deactivated.attr, | ||
600 | &dev_attr_caps.attr, | ||
601 | &dev_attr_cancel.attr, NULL, | ||
602 | }; | ||
603 | |||
604 | static struct attribute_group stm_tpm_attr_grp = { | ||
605 | .attrs = stm_tpm_attrs | ||
606 | }; | ||
607 | |||
608 | static struct tpm_vendor_specific st_i2c_tpm = { | ||
609 | .send = tpm_stm_i2c_send, | ||
610 | .recv = tpm_stm_i2c_recv, | ||
611 | .cancel = tpm_stm_i2c_cancel, | ||
612 | .status = tpm_stm_i2c_status, | ||
613 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
614 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
615 | .req_canceled = tpm_st33_i2c_req_canceled, | ||
616 | .attr_group = &stm_tpm_attr_grp, | ||
617 | .miscdev = {.fops = &tpm_st33_i2c_fops,}, | ||
618 | }; | ||
619 | |||
620 | static int interrupts ; | ||
621 | module_param(interrupts, int, 0444); | ||
622 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); | ||
623 | |||
624 | static int power_mgt = 1; | ||
625 | module_param(power_mgt, int, 0444); | ||
626 | MODULE_PARM_DESC(power_mgt, "Power Management"); | ||
627 | |||
628 | /* | ||
629 | * tpm_st33_i2c_probe initialize the TPM device | ||
630 | * @param: client, the i2c_client drescription (TPM I2C description). | ||
631 | * @param: id, the i2c_device_id struct. | ||
632 | * @return: 0 in case of success. | ||
633 | * -1 in other case. | ||
634 | */ | ||
635 | static int | ||
636 | tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
637 | { | ||
638 | int err; | ||
639 | u8 intmask; | ||
640 | struct tpm_chip *chip; | ||
641 | struct st33zp24_platform_data *platform_data; | ||
642 | |||
643 | if (client == NULL) { | ||
644 | pr_info("%s: i2c client is NULL. Device not accessible.\n", | ||
645 | __func__); | ||
646 | err = -ENODEV; | ||
647 | goto end; | ||
648 | } | ||
649 | |||
650 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
651 | dev_info(&client->dev, "client not i2c capable\n"); | ||
652 | err = -ENODEV; | ||
653 | goto end; | ||
654 | } | ||
655 | |||
656 | chip = tpm_register_hardware(&client->dev, &st_i2c_tpm); | ||
657 | if (!chip) { | ||
658 | dev_info(&client->dev, "fail chip\n"); | ||
659 | err = -ENODEV; | ||
660 | goto end; | ||
661 | } | ||
662 | |||
663 | platform_data = client->dev.platform_data; | ||
664 | |||
665 | if (!platform_data) { | ||
666 | dev_info(&client->dev, "chip not available\n"); | ||
667 | err = -ENODEV; | ||
668 | goto _tpm_clean_answer; | ||
669 | } | ||
670 | |||
671 | platform_data->tpm_i2c_buffer[0] = | ||
672 | kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); | ||
673 | if (platform_data->tpm_i2c_buffer[0] == NULL) { | ||
674 | err = -ENOMEM; | ||
675 | goto _tpm_clean_answer; | ||
676 | } | ||
677 | platform_data->tpm_i2c_buffer[1] = | ||
678 | kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); | ||
679 | if (platform_data->tpm_i2c_buffer[1] == NULL) { | ||
680 | err = -ENOMEM; | ||
681 | goto _tpm_clean_response1; | ||
682 | } | ||
683 | |||
684 | TPM_VPRIV(chip) = client; | ||
685 | |||
686 | chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
687 | chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); | ||
688 | chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
689 | chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
690 | |||
691 | chip->vendor.locality = LOCALITY0; | ||
692 | |||
693 | if (power_mgt) { | ||
694 | err = gpio_request(platform_data->io_lpcpd, "TPM IO_LPCPD"); | ||
695 | if (err) | ||
696 | goto _gpio_init1; | ||
697 | gpio_set_value(platform_data->io_lpcpd, 1); | ||
698 | } | ||
699 | |||
700 | if (interrupts) { | ||
701 | init_completion(&platform_data->irq_detection); | ||
702 | if (request_locality(chip) != LOCALITY0) { | ||
703 | err = -ENODEV; | ||
704 | goto _tpm_clean_response2; | ||
705 | } | ||
706 | err = gpio_request(platform_data->io_serirq, "TPM IO_SERIRQ"); | ||
707 | if (err) | ||
708 | goto _gpio_init2; | ||
709 | |||
710 | clear_interruption(client); | ||
711 | err = request_irq(gpio_to_irq(platform_data->io_serirq), | ||
712 | &tpm_ioserirq_handler, | ||
713 | IRQF_TRIGGER_HIGH, | ||
714 | "TPM SERIRQ management", chip); | ||
715 | if (err < 0) { | ||
716 | dev_err(chip->dev , "TPM SERIRQ signals %d not available\n", | ||
717 | gpio_to_irq(platform_data->io_serirq)); | ||
718 | goto _irq_set; | ||
719 | } | ||
720 | |||
721 | err = I2C_READ_DATA(client, TPM_INT_ENABLE, &intmask, 1); | ||
722 | if (err < 0) | ||
723 | goto _irq_set; | ||
724 | |||
725 | intmask |= TPM_INTF_CMD_READY_INT | ||
726 | | TPM_INTF_FIFO_AVALAIBLE_INT | ||
727 | | TPM_INTF_WAKE_UP_READY_INT | ||
728 | | TPM_INTF_LOCALITY_CHANGE_INT | ||
729 | | TPM_INTF_STS_VALID_INT | ||
730 | | TPM_INTF_DATA_AVAIL_INT; | ||
731 | |||
732 | err = I2C_WRITE_DATA(client, TPM_INT_ENABLE, &intmask, 1); | ||
733 | if (err < 0) | ||
734 | goto _irq_set; | ||
735 | |||
736 | intmask = TPM_GLOBAL_INT_ENABLE; | ||
737 | err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1); | ||
738 | if (err < 0) | ||
739 | goto _irq_set; | ||
740 | |||
741 | err = I2C_READ_DATA(client, TPM_INT_STATUS, &intmask, 1); | ||
742 | if (err < 0) | ||
743 | goto _irq_set; | ||
744 | |||
745 | chip->vendor.irq = interrupts; | ||
746 | |||
747 | tpm_gen_interrupt(chip); | ||
748 | } | ||
749 | |||
750 | tpm_get_timeouts(chip); | ||
751 | |||
752 | i2c_set_clientdata(client, chip); | ||
753 | |||
754 | dev_info(chip->dev, "TPM I2C Initialized\n"); | ||
755 | return 0; | ||
756 | _irq_set: | ||
757 | free_irq(gpio_to_irq(platform_data->io_serirq), (void *) chip); | ||
758 | _gpio_init2: | ||
759 | if (interrupts) | ||
760 | gpio_free(platform_data->io_serirq); | ||
761 | _gpio_init1: | ||
762 | if (power_mgt) | ||
763 | gpio_free(platform_data->io_lpcpd); | ||
764 | _tpm_clean_response2: | ||
765 | kzfree(platform_data->tpm_i2c_buffer[1]); | ||
766 | platform_data->tpm_i2c_buffer[1] = NULL; | ||
767 | _tpm_clean_response1: | ||
768 | kzfree(platform_data->tpm_i2c_buffer[0]); | ||
769 | platform_data->tpm_i2c_buffer[0] = NULL; | ||
770 | _tpm_clean_answer: | ||
771 | tpm_remove_hardware(chip->dev); | ||
772 | end: | ||
773 | pr_info("TPM I2C initialisation fail\n"); | ||
774 | return err; | ||
775 | } | ||
776 | |||
777 | /* | ||
778 | * tpm_st33_i2c_remove remove the TPM device | ||
779 | * @param: client, the i2c_client drescription (TPM I2C description). | ||
780 | clear_bit(0, &chip->is_open); | ||
781 | * @return: 0 in case of success. | ||
782 | */ | ||
783 | static int tpm_st33_i2c_remove(struct i2c_client *client) | ||
784 | { | ||
785 | struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client); | ||
786 | struct st33zp24_platform_data *pin_infos = | ||
787 | ((struct i2c_client *) TPM_VPRIV(chip))->dev.platform_data; | ||
788 | |||
789 | if (pin_infos != NULL) { | ||
790 | free_irq(pin_infos->io_serirq, chip); | ||
791 | |||
792 | gpio_free(pin_infos->io_serirq); | ||
793 | gpio_free(pin_infos->io_lpcpd); | ||
794 | |||
795 | tpm_remove_hardware(chip->dev); | ||
796 | |||
797 | if (pin_infos->tpm_i2c_buffer[1] != NULL) { | ||
798 | kzfree(pin_infos->tpm_i2c_buffer[1]); | ||
799 | pin_infos->tpm_i2c_buffer[1] = NULL; | ||
800 | } | ||
801 | if (pin_infos->tpm_i2c_buffer[0] != NULL) { | ||
802 | kzfree(pin_infos->tpm_i2c_buffer[0]); | ||
803 | pin_infos->tpm_i2c_buffer[0] = NULL; | ||
804 | } | ||
805 | } | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | #ifdef CONFIG_PM_SLEEP | ||
811 | /* | ||
812 | * tpm_st33_i2c_pm_suspend suspend the TPM device | ||
813 | * Added: Work around when suspend and no tpm application is running, suspend | ||
814 | * may fail because chip->data_buffer is not set (only set in tpm_open in Linux | ||
815 | * TPM core) | ||
816 | * @param: client, the i2c_client drescription (TPM I2C description). | ||
817 | * @param: mesg, the power management message. | ||
818 | * @return: 0 in case of success. | ||
819 | */ | ||
820 | static int tpm_st33_i2c_pm_suspend(struct device *dev) | ||
821 | { | ||
822 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
823 | struct st33zp24_platform_data *pin_infos = dev->platform_data; | ||
824 | int ret = 0; | ||
825 | |||
826 | if (power_mgt) | ||
827 | gpio_set_value(pin_infos->io_lpcpd, 0); | ||
828 | else{ | ||
829 | if (chip->data_buffer == NULL) | ||
830 | chip->data_buffer = pin_infos->tpm_i2c_buffer[0]; | ||
831 | ret = tpm_pm_suspend(dev); | ||
832 | } | ||
833 | return ret; | ||
834 | } /* tpm_st33_i2c_suspend() */ | ||
835 | |||
836 | /* | ||
837 | * tpm_st33_i2c_pm_resume resume the TPM device | ||
838 | * @param: client, the i2c_client drescription (TPM I2C description). | ||
839 | * @return: 0 in case of success. | ||
840 | */ | ||
841 | static int tpm_st33_i2c_pm_resume(struct device *dev) | ||
842 | { | ||
843 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
844 | struct st33zp24_platform_data *pin_infos = dev->platform_data; | ||
845 | |||
846 | int ret = 0; | ||
847 | |||
848 | if (power_mgt) { | ||
849 | gpio_set_value(pin_infos->io_lpcpd, 1); | ||
850 | ret = wait_for_serirq_timeout(chip, | ||
851 | (chip->vendor.status(chip) & | ||
852 | TPM_STS_VALID) == TPM_STS_VALID, | ||
853 | chip->vendor.timeout_b); | ||
854 | } else{ | ||
855 | if (chip->data_buffer == NULL) | ||
856 | chip->data_buffer = pin_infos->tpm_i2c_buffer[0]; | ||
857 | ret = tpm_pm_resume(dev); | ||
858 | if (!ret) | ||
859 | tpm_do_selftest(chip); | ||
860 | } | ||
861 | return ret; | ||
862 | } /* tpm_st33_i2c_pm_resume() */ | ||
863 | #endif | ||
864 | |||
865 | static const struct i2c_device_id tpm_st33_i2c_id[] = { | ||
866 | {TPM_ST33_I2C, 0}, | ||
867 | {} | ||
868 | }; | ||
869 | MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id); | ||
870 | static SIMPLE_DEV_PM_OPS(tpm_st33_i2c_ops, tpm_st33_i2c_pm_suspend, tpm_st33_i2c_pm_resume); | ||
871 | static struct i2c_driver tpm_st33_i2c_driver = { | ||
872 | .driver = { | ||
873 | .owner = THIS_MODULE, | ||
874 | .name = TPM_ST33_I2C, | ||
875 | .pm = &tpm_st33_i2c_ops, | ||
876 | }, | ||
877 | .probe = tpm_st33_i2c_probe, | ||
878 | .remove = tpm_st33_i2c_remove, | ||
879 | .id_table = tpm_st33_i2c_id | ||
880 | }; | ||
881 | |||
882 | module_i2c_driver(tpm_st33_i2c_driver); | ||
883 | |||
884 | MODULE_AUTHOR("Christophe Ricard (tpmsupport@st.com)"); | ||
885 | MODULE_DESCRIPTION("STM TPM I2C ST33 Driver"); | ||
886 | MODULE_VERSION("1.2.0"); | ||
887 | MODULE_LICENSE("GPL"); | ||