Blame view

drivers/tpm/tpm_tis_lpc.c 12.3 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
5e1247247   Vadim Bendebury   Introduce generic...
2
3
  /*
   * Copyright (c) 2011 The Chromium OS Authors.
5e1247247   Vadim Bendebury   Introduce generic...
4
5
6
7
8
9
10
11
12
13
14
15
   */
  
  /*
   * The code in this file is based on the article "Writing a TPM Device Driver"
   * published on http://ptgmedia.pearsoncmg.com.
   *
   * One principal difference is that in the simplest config the other than 0
   * TPM localities do not get mapped by some devices (for instance, by Infineon
   * slb9635), so this driver provides access to locality 0 only.
   */
  
  #include <common.h>
d616ba5f5   Simon Glass   dm: tpm: Convert ...
16
17
  #include <dm.h>
  #include <mapmem.h>
d677bfe2f   Miquel Raynal   tpm: disociate TP...
18
  #include <tpm-v1.h>
d616ba5f5   Simon Glass   dm: tpm: Convert ...
19
  #include <asm/io.h>
5e1247247   Vadim Bendebury   Introduce generic...
20
21
  
  #define PREFIX "lpc_tpm: "
a982b6f51   George McCollister   tpm: tpm_tis_lpc:...
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  enum i2c_chip_type {
  	SLB9635,
  	AT97SC3204,
  };
  
  static const char * const chip_name[] = {
  	[SLB9635] = "Infineon SLB9635 TT 1.2",
  	[AT97SC3204] = "Atmel AT97SC3204",
  };
  
  static const u32 chip_didvid[] = {
  	[SLB9635] = 0xb15d1,
  	[AT97SC3204] = 0x32041114,
  };
5e1247247   Vadim Bendebury   Introduce generic...
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  struct tpm_locality {
  	u32 access;
  	u8 padding0[4];
  	u32 int_enable;
  	u8 vector;
  	u8 padding1[3];
  	u32 int_status;
  	u32 int_capability;
  	u32 tpm_status;
  	u8 padding2[8];
  	u8 data;
  	u8 padding3[3803];
  	u32 did_vid;
  	u8 rid;
  	u8 padding4[251];
  };
d616ba5f5   Simon Glass   dm: tpm: Convert ...
52
53
54
  struct tpm_tis_lpc_priv {
  	struct tpm_locality *regs;
  };
5e1247247   Vadim Bendebury   Introduce generic...
55
56
57
58
59
  /*
   * This pointer refers to the TPM chip, 5 of its localities are mapped as an
   * array.
   */
  #define TPM_TOTAL_LOCALITIES	5
5e1247247   Vadim Bendebury   Introduce generic...
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  
  /* Some registers' bit field definitions */
  #define TIS_STS_VALID                  (1 << 7) /* 0x80 */
  #define TIS_STS_COMMAND_READY          (1 << 6) /* 0x40 */
  #define TIS_STS_TPM_GO                 (1 << 5) /* 0x20 */
  #define TIS_STS_DATA_AVAILABLE         (1 << 4) /* 0x10 */
  #define TIS_STS_EXPECT                 (1 << 3) /* 0x08 */
  #define TIS_STS_RESPONSE_RETRY         (1 << 1) /* 0x02 */
  
  #define TIS_ACCESS_TPM_REG_VALID_STS   (1 << 7) /* 0x80 */
  #define TIS_ACCESS_ACTIVE_LOCALITY     (1 << 5) /* 0x20 */
  #define TIS_ACCESS_BEEN_SEIZED         (1 << 4) /* 0x10 */
  #define TIS_ACCESS_SEIZE               (1 << 3) /* 0x08 */
  #define TIS_ACCESS_PENDING_REQUEST     (1 << 2) /* 0x04 */
  #define TIS_ACCESS_REQUEST_USE         (1 << 1) /* 0x02 */
  #define TIS_ACCESS_TPM_ESTABLISHMENT   (1 << 0) /* 0x01 */
  
  #define TIS_STS_BURST_COUNT_MASK       (0xffff)
  #define TIS_STS_BURST_COUNT_SHIFT      (8)
5e1247247   Vadim Bendebury   Introduce generic...
79
80
81
82
83
84
   /* 1 second is plenty for anything TPM does. */
  #define MAX_DELAY_US	(1000 * 1000)
  
  /* Retrieve burst count value out of the status register contents. */
  static u16 burst_count(u32 status)
  {
d616ba5f5   Simon Glass   dm: tpm: Convert ...
85
86
  	return (status >> TIS_STS_BURST_COUNT_SHIFT) &
  			TIS_STS_BURST_COUNT_MASK;
5e1247247   Vadim Bendebury   Introduce generic...
87
  }
5e1247247   Vadim Bendebury   Introduce generic...
88
  /* TPM access wrappers to support tracing */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
89
  static u8 tpm_read_byte(struct tpm_tis_lpc_priv *priv, const u8 *ptr)
5e1247247   Vadim Bendebury   Introduce generic...
90
91
92
93
  {
  	u8  ret = readb(ptr);
  	debug(PREFIX "Read reg 0x%4.4x returns 0x%2.2x
  ",
d616ba5f5   Simon Glass   dm: tpm: Convert ...
94
  	      (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, ret);
5e1247247   Vadim Bendebury   Introduce generic...
95
96
  	return ret;
  }
d616ba5f5   Simon Glass   dm: tpm: Convert ...
97
  static u32 tpm_read_word(struct tpm_tis_lpc_priv *priv, const u32 *ptr)
5e1247247   Vadim Bendebury   Introduce generic...
98
99
100
101
  {
  	u32  ret = readl(ptr);
  	debug(PREFIX "Read reg 0x%4.4x returns 0x%8.8x
  ",
d616ba5f5   Simon Glass   dm: tpm: Convert ...
102
  	      (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, ret);
5e1247247   Vadim Bendebury   Introduce generic...
103
104
  	return ret;
  }
d616ba5f5   Simon Glass   dm: tpm: Convert ...
105
  static void tpm_write_byte(struct tpm_tis_lpc_priv *priv, u8 value, u8 *ptr)
5e1247247   Vadim Bendebury   Introduce generic...
106
107
108
  {
  	debug(PREFIX "Write reg 0x%4.4x with 0x%2.2x
  ",
d616ba5f5   Simon Glass   dm: tpm: Convert ...
109
  	      (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, value);
5e1247247   Vadim Bendebury   Introduce generic...
110
111
  	writeb(value, ptr);
  }
d616ba5f5   Simon Glass   dm: tpm: Convert ...
112
113
  static void tpm_write_word(struct tpm_tis_lpc_priv *priv, u32 value,
  			   u32 *ptr)
5e1247247   Vadim Bendebury   Introduce generic...
114
115
116
  {
  	debug(PREFIX "Write reg 0x%4.4x with 0x%8.8x
  ",
d616ba5f5   Simon Glass   dm: tpm: Convert ...
117
  	      (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, value);
5e1247247   Vadim Bendebury   Introduce generic...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  	writel(value, ptr);
  }
  
  /*
   * tis_wait_reg()
   *
   * Wait for at least a second for a register to change its state to match the
   * expected state. Normally the transition happens within microseconds.
   *
   * @reg - pointer to the TPM register
   * @mask - bitmask for the bitfield(s) to watch
   * @expected - value the field(s) are supposed to be set to
   *
   * Returns the register contents in case the expected value was found in the
d616ba5f5   Simon Glass   dm: tpm: Convert ...
132
   * appropriate register bits, or -ETIMEDOUT on timeout.
5e1247247   Vadim Bendebury   Introduce generic...
133
   */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
134
135
  static int tis_wait_reg(struct tpm_tis_lpc_priv *priv, u32 *reg, u8 mask,
  			u8 expected)
5e1247247   Vadim Bendebury   Introduce generic...
136
137
138
139
  {
  	u32 time_us = MAX_DELAY_US;
  
  	while (time_us > 0) {
d616ba5f5   Simon Glass   dm: tpm: Convert ...
140
  		u32 value = tpm_read_word(priv, reg);
5e1247247   Vadim Bendebury   Introduce generic...
141
142
143
144
145
  		if ((value & mask) == expected)
  			return value;
  		udelay(1); /* 1 us */
  		time_us--;
  	}
d616ba5f5   Simon Glass   dm: tpm: Convert ...
146
147
  
  	return -ETIMEDOUT;
5e1247247   Vadim Bendebury   Introduce generic...
148
149
150
151
152
  }
  
  /*
   * Probe the TPM device and try determining its manufacturer/device name.
   *
d616ba5f5   Simon Glass   dm: tpm: Convert ...
153
   * Returns 0 on success, -ve on error
5e1247247   Vadim Bendebury   Introduce generic...
154
   */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
155
  static int tpm_tis_lpc_probe(struct udevice *dev)
5e1247247   Vadim Bendebury   Introduce generic...
156
  {
d616ba5f5   Simon Glass   dm: tpm: Convert ...
157
  	struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
158
159
  	fdt_addr_t addr;
  	u32 didvid;
a982b6f51   George McCollister   tpm: tpm_tis_lpc:...
160
  	ulong chip_type = dev_get_driver_data(dev);
5e1247247   Vadim Bendebury   Introduce generic...
161

c89d32a7b   Simon Glass   tpm: Use livetree...
162
  	addr = dev_read_addr(dev);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
163
164
165
166
  	if (addr == FDT_ADDR_T_NONE)
  		return -EINVAL;
  	priv->regs = map_sysmem(addr, 0);
  	didvid = tpm_read_word(priv, &priv->regs[0].did_vid);
5e1247247   Vadim Bendebury   Introduce generic...
167

a982b6f51   George McCollister   tpm: tpm_tis_lpc:...
168
169
170
171
  	if (didvid != chip_didvid[chip_type]) {
  		u32 vid, did;
  		vid = didvid & 0xffff;
  		did = (didvid >> 16) & 0xffff;
d616ba5f5   Simon Glass   dm: tpm: Convert ...
172
173
  		debug("Invalid vendor/device ID %04x/%04x
  ", vid, did);
a982b6f51   George McCollister   tpm: tpm_tis_lpc:...
174
  		return -ENODEV;
5e1247247   Vadim Bendebury   Introduce generic...
175
  	}
a982b6f51   George McCollister   tpm: tpm_tis_lpc:...
176
177
  	debug("Found TPM: %s
  ", chip_name[chip_type]);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
178

5e1247247   Vadim Bendebury   Introduce generic...
179
180
181
182
183
184
185
186
187
188
189
  	return 0;
  }
  
  /*
   * tis_senddata()
   *
   * send the passed in data to the TPM device.
   *
   * @data - address of the data to send, byte by byte
   * @len - length of the data to send
   *
d616ba5f5   Simon Glass   dm: tpm: Convert ...
190
191
   * Returns 0 on success, -ve on error (in case the device does not accept
   * the entire command).
5e1247247   Vadim Bendebury   Introduce generic...
192
   */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
193
  static int tis_senddata(struct udevice *dev, const u8 *data, size_t len)
5e1247247   Vadim Bendebury   Introduce generic...
194
  {
d616ba5f5   Simon Glass   dm: tpm: Convert ...
195
196
  	struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
  	struct tpm_locality *regs = priv->regs;
5e1247247   Vadim Bendebury   Introduce generic...
197
198
199
200
201
  	u32 offset = 0;
  	u16 burst = 0;
  	u32 max_cycles = 0;
  	u8 locality = 0;
  	u32 value;
d616ba5f5   Simon Glass   dm: tpm: Convert ...
202
  	value = tis_wait_reg(priv, &regs[locality].tpm_status,
5e1247247   Vadim Bendebury   Introduce generic...
203
  			     TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
204
  	if (value == -ETIMEDOUT) {
5e1247247   Vadim Bendebury   Introduce generic...
205
206
207
  		printf("%s:%d - failed to get 'command_ready' status
  ",
  		       __FILE__, __LINE__);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
208
  		return value;
5e1247247   Vadim Bendebury   Introduce generic...
209
210
211
212
213
214
215
216
217
  	}
  	burst = burst_count(value);
  
  	while (1) {
  		unsigned count;
  
  		/* Wait till the device is ready to accept more data. */
  		while (!burst) {
  			if (max_cycles++ == MAX_DELAY_US) {
22230e916   Simon Glass   tpm: Tidy up use ...
218
219
  				printf("%s:%d failed to feed %zd bytes of %zd
  ",
5e1247247   Vadim Bendebury   Introduce generic...
220
  				       __FILE__, __LINE__, len - offset, len);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
221
  				return -ETIMEDOUT;
5e1247247   Vadim Bendebury   Introduce generic...
222
223
  			}
  			udelay(1);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
224
225
  			burst = burst_count(tpm_read_word(priv,
  					&regs[locality].tpm_status));
5e1247247   Vadim Bendebury   Introduce generic...
226
227
228
229
230
231
232
233
234
235
236
237
238
  		}
  
  		max_cycles = 0;
  
  		/*
  		 * Calculate number of bytes the TPM is ready to accept in one
  		 * shot.
  		 *
  		 * We want to send the last byte outside of the loop (hence
  		 * the -1 below) to make sure that the 'expected' status bit
  		 * changes to zero exactly after the last byte is fed into the
  		 * FIFO.
  		 */
22230e916   Simon Glass   tpm: Tidy up use ...
239
  		count = min((size_t)burst, len - offset - 1);
5e1247247   Vadim Bendebury   Introduce generic...
240
  		while (count--)
d616ba5f5   Simon Glass   dm: tpm: Convert ...
241
242
  			tpm_write_byte(priv, data[offset++],
  				       &regs[locality].data);
5e1247247   Vadim Bendebury   Introduce generic...
243

d616ba5f5   Simon Glass   dm: tpm: Convert ...
244
  		value = tis_wait_reg(priv, &regs[locality].tpm_status,
5e1247247   Vadim Bendebury   Introduce generic...
245
  				     TIS_STS_VALID, TIS_STS_VALID);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
246
  		if ((value == -ETIMEDOUT) || !(value & TIS_STS_EXPECT)) {
5e1247247   Vadim Bendebury   Introduce generic...
247
248
249
  			printf("%s:%d TPM command feed overflow
  ",
  			       __FILE__, __LINE__);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
250
  			return value == -ETIMEDOUT ? value : -EIO;
5e1247247   Vadim Bendebury   Introduce generic...
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  		}
  
  		burst = burst_count(value);
  		if ((offset == (len - 1)) && burst) {
  			/*
  			 * We need to be able to send the last byte to the
  			 * device, so burst size must be nonzero before we
  			 * break out.
  			 */
  			break;
  		}
  	}
  
  	/* Send the last byte. */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
265
  	tpm_write_byte(priv, data[offset++], &regs[locality].data);
5e1247247   Vadim Bendebury   Introduce generic...
266
267
268
269
  	/*
  	 * Verify that TPM does not expect any more data as part of this
  	 * command.
  	 */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
270
  	value = tis_wait_reg(priv, &regs[locality].tpm_status,
5e1247247   Vadim Bendebury   Introduce generic...
271
  			     TIS_STS_VALID, TIS_STS_VALID);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
272
  	if ((value == -ETIMEDOUT) || (value & TIS_STS_EXPECT)) {
5e1247247   Vadim Bendebury   Introduce generic...
273
274
275
  		printf("%s:%d unexpected TPM status 0x%x
  ",
  		       __FILE__, __LINE__, value);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
276
  		return value == -ETIMEDOUT ? value : -EIO;
5e1247247   Vadim Bendebury   Introduce generic...
277
278
279
  	}
  
  	/* OK, sitting pretty, let's start the command execution. */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
280
  	tpm_write_word(priv, TIS_STS_TPM_GO, &regs[locality].tpm_status);
5e1247247   Vadim Bendebury   Introduce generic...
281
282
283
284
285
286
287
288
289
290
291
292
293
  	return 0;
  }
  
  /*
   * tis_readresponse()
   *
   * read the TPM device response after a command was issued.
   *
   * @buffer - address where to read the response, byte by byte.
   * @len - pointer to the size of buffer
   *
   * On success stores the number of received bytes to len and returns 0. On
   * errors (misformatted TPM data or synchronization problems) returns
d616ba5f5   Simon Glass   dm: tpm: Convert ...
294
   * -ve value.
5e1247247   Vadim Bendebury   Introduce generic...
295
   */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
296
  static int tis_readresponse(struct udevice *dev, u8 *buffer, size_t len)
5e1247247   Vadim Bendebury   Introduce generic...
297
  {
d616ba5f5   Simon Glass   dm: tpm: Convert ...
298
299
  	struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
  	struct tpm_locality *regs = priv->regs;
5e1247247   Vadim Bendebury   Introduce generic...
300
301
302
303
304
  	u16 burst;
  	u32 value;
  	u32 offset = 0;
  	u8 locality = 0;
  	const u32 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
d616ba5f5   Simon Glass   dm: tpm: Convert ...
305
  	u32 expected_count = len;
5e1247247   Vadim Bendebury   Introduce generic...
306
307
308
  	int max_cycles = 0;
  
  	/* Wait for the TPM to process the command. */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
309
  	value = tis_wait_reg(priv, &regs[locality].tpm_status,
5e1247247   Vadim Bendebury   Introduce generic...
310
  			      has_data, has_data);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
311
  	if (value == -ETIMEDOUT) {
5e1247247   Vadim Bendebury   Introduce generic...
312
313
314
  		printf("%s:%d failed processing command
  ",
  		       __FILE__, __LINE__);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
315
  		return value;
5e1247247   Vadim Bendebury   Introduce generic...
316
317
318
319
320
321
322
323
  	}
  
  	do {
  		while ((burst = burst_count(value)) == 0) {
  			if (max_cycles++ == MAX_DELAY_US) {
  				printf("%s:%d TPM stuck on read
  ",
  				       __FILE__, __LINE__);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
324
  				return -EIO;
5e1247247   Vadim Bendebury   Introduce generic...
325
326
  			}
  			udelay(1);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
327
  			value = tpm_read_word(priv, &regs[locality].tpm_status);
5e1247247   Vadim Bendebury   Introduce generic...
328
329
330
331
332
  		}
  
  		max_cycles = 0;
  
  		while (burst-- && (offset < expected_count)) {
d616ba5f5   Simon Glass   dm: tpm: Convert ...
333
334
  			buffer[offset++] = tpm_read_byte(priv,
  						&regs[locality].data);
5e1247247   Vadim Bendebury   Introduce generic...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
  
  			if (offset == 6) {
  				/*
  				 * We got the first six bytes of the reply,
  				 * let's figure out how many bytes to expect
  				 * total - it is stored as a 4 byte number in
  				 * network order, starting with offset 2 into
  				 * the body of the reply.
  				 */
  				u32 real_length;
  				memcpy(&real_length,
  				       buffer + 2,
  				       sizeof(real_length));
  				expected_count = be32_to_cpu(real_length);
  
  				if ((expected_count < offset) ||
d616ba5f5   Simon Glass   dm: tpm: Convert ...
351
  				    (expected_count > len)) {
5e1247247   Vadim Bendebury   Introduce generic...
352
353
354
355
  					printf("%s:%d bad response size %d
  ",
  					       __FILE__, __LINE__,
  					       expected_count);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
356
  					return -ENOSPC;
5e1247247   Vadim Bendebury   Introduce generic...
357
358
359
360
361
  				}
  			}
  		}
  
  		/* Wait for the next portion. */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
362
  		value = tis_wait_reg(priv, &regs[locality].tpm_status,
5e1247247   Vadim Bendebury   Introduce generic...
363
  				     TIS_STS_VALID, TIS_STS_VALID);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
364
  		if (value == -ETIMEDOUT) {
5e1247247   Vadim Bendebury   Introduce generic...
365
366
367
  			printf("%s:%d failed to read response
  ",
  			       __FILE__, __LINE__);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
368
  			return value;
5e1247247   Vadim Bendebury   Introduce generic...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
  		}
  
  		if (offset == expected_count)
  			break;	/* We got all we needed. */
  
  	} while ((value & has_data) == has_data);
  
  	/*
  	 * Make sure we indeed read all there was. The TIS_STS_VALID bit is
  	 * known to be set.
  	 */
  	if (value & TIS_STS_DATA_AVAILABLE) {
  		printf("%s:%d wrong receive status %x
  ",
  		       __FILE__, __LINE__, value);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
384
  		return -EBADMSG;
5e1247247   Vadim Bendebury   Introduce generic...
385
386
387
  	}
  
  	/* Tell the TPM that we are done. */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
388
389
390
391
  	tpm_write_word(priv, TIS_STS_COMMAND_READY,
  		       &regs[locality].tpm_status);
  
  	return offset;
5e1247247   Vadim Bendebury   Introduce generic...
392
  }
51f00c170   Simon Glass   tpm: Export the o...
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
  static int tpm_tis_lpc_close(struct udevice *dev)
  {
  	struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
  	struct tpm_locality *regs = priv->regs;
  	u8 locality = 0;
  
  	if (tpm_read_word(priv, &regs[locality].access) &
  	    TIS_ACCESS_ACTIVE_LOCALITY) {
  		tpm_write_word(priv, TIS_ACCESS_ACTIVE_LOCALITY,
  			       &regs[locality].access);
  
  		if (tis_wait_reg(priv, &regs[locality].access,
  				 TIS_ACCESS_ACTIVE_LOCALITY, 0) == -ETIMEDOUT) {
  			printf("%s:%d - failed to release locality %d
  ",
  			       __FILE__, __LINE__, locality);
  			return -ETIMEDOUT;
  		}
  	}
  	return 0;
  }
d616ba5f5   Simon Glass   dm: tpm: Convert ...
414
  static int tpm_tis_lpc_open(struct udevice *dev)
5e1247247   Vadim Bendebury   Introduce generic...
415
  {
d616ba5f5   Simon Glass   dm: tpm: Convert ...
416
417
  	struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
  	struct tpm_locality *regs = priv->regs;
5e1247247   Vadim Bendebury   Introduce generic...
418
  	u8 locality = 0; /* we use locality zero for everything. */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
419
  	int ret;
5e1247247   Vadim Bendebury   Introduce generic...
420

51f00c170   Simon Glass   tpm: Export the o...
421
422
423
424
425
426
  	ret = tpm_tis_lpc_close(dev);
  	if (ret) {
  		printf("%s: Failed to close TPM
  ", __func__);
  		return ret;
  	}
5e1247247   Vadim Bendebury   Introduce generic...
427
  	/* now request access to locality. */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
428
  	tpm_write_word(priv, TIS_ACCESS_REQUEST_USE, &regs[locality].access);
5e1247247   Vadim Bendebury   Introduce generic...
429
430
  
  	/* did we get a lock? */
d616ba5f5   Simon Glass   dm: tpm: Convert ...
431
  	ret = tis_wait_reg(priv, &regs[locality].access,
5e1247247   Vadim Bendebury   Introduce generic...
432
  			 TIS_ACCESS_ACTIVE_LOCALITY,
d616ba5f5   Simon Glass   dm: tpm: Convert ...
433
434
  			 TIS_ACCESS_ACTIVE_LOCALITY);
  	if (ret == -ETIMEDOUT) {
5e1247247   Vadim Bendebury   Introduce generic...
435
436
437
  		printf("%s:%d - failed to lock locality %d
  ",
  		       __FILE__, __LINE__, locality);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
438
  		return ret;
5e1247247   Vadim Bendebury   Introduce generic...
439
  	}
d616ba5f5   Simon Glass   dm: tpm: Convert ...
440
441
  	tpm_write_word(priv, TIS_STS_COMMAND_READY,
  		       &regs[locality].tpm_status);
5e1247247   Vadim Bendebury   Introduce generic...
442

5e1247247   Vadim Bendebury   Introduce generic...
443
444
  	return 0;
  }
d616ba5f5   Simon Glass   dm: tpm: Convert ...
445
  static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size)
5e1247247   Vadim Bendebury   Introduce generic...
446
  {
a982b6f51   George McCollister   tpm: tpm_tis_lpc:...
447
  	ulong chip_type = dev_get_driver_data(dev);
d616ba5f5   Simon Glass   dm: tpm: Convert ...
448
449
  	if (size < 50)
  		return -ENOSPC;
5e1247247   Vadim Bendebury   Introduce generic...
450

a982b6f51   George McCollister   tpm: tpm_tis_lpc:...
451
452
  	return snprintf(buf, size, "1.2 TPM (%s)",
  			chip_name[chip_type]);
5e1247247   Vadim Bendebury   Introduce generic...
453
  }
d616ba5f5   Simon Glass   dm: tpm: Convert ...
454
455
456
457
458
459
460
461
462
463
464
  
  
  static const struct tpm_ops tpm_tis_lpc_ops = {
  	.open		= tpm_tis_lpc_open,
  	.close		= tpm_tis_lpc_close,
  	.get_desc	= tpm_tis_get_desc,
  	.send		= tis_senddata,
  	.recv		= tis_readresponse,
  };
  
  static const struct udevice_id tpm_tis_lpc_ids[] = {
a982b6f51   George McCollister   tpm: tpm_tis_lpc:...
465
466
  	{ .compatible = "infineon,slb9635lpc", .data = SLB9635 },
  	{ .compatible = "atmel,at97sc3204", .data = AT97SC3204 },
d616ba5f5   Simon Glass   dm: tpm: Convert ...
467
468
469
470
471
472
473
474
475
476
477
  	{ }
  };
  
  U_BOOT_DRIVER(tpm_tis_lpc) = {
  	.name   = "tpm_tis_lpc",
  	.id     = UCLASS_TPM,
  	.of_match = tpm_tis_lpc_ids,
  	.ops    = &tpm_tis_lpc_ops,
  	.probe	= tpm_tis_lpc_probe,
  	.priv_auto_alloc_size = sizeof(struct tpm_tis_lpc_priv),
  };