2 * Copyright (c) 2015 Google, Inc
3 * Written by Simon Glass <sjg@chromium.org>
5 * SPDX-License-Identifier: GPL-2.0+
11 #include <linux/unaligned/be_byteshift.h>
12 #include "tpm_internal.h"
14 int tpm_open(struct udevice
*dev
)
16 struct tpm_ops
*ops
= tpm_get_ops(dev
);
21 return ops
->open(dev
);
24 int tpm_close(struct udevice
*dev
)
26 struct tpm_ops
*ops
= tpm_get_ops(dev
);
31 return ops
->close(dev
);
34 int tpm_get_desc(struct udevice
*dev
, char *buf
, int size
)
36 struct tpm_ops
*ops
= tpm_get_ops(dev
);
41 return ops
->get_desc(dev
, buf
, size
);
44 /* Returns max number of milliseconds to wait */
45 static ulong
tpm_tis_i2c_calc_ordinal_duration(struct tpm_chip_priv
*priv
,
48 int duration_idx
= TPM_UNDEFINED
;
51 if (ordinal
< TPM_MAX_ORDINAL
) {
52 duration_idx
= tpm_ordinal_duration
[ordinal
];
53 } else if ((ordinal
& TPM_PROTECTED_ORDINAL_MASK
) <
54 TPM_MAX_PROTECTED_ORDINAL
) {
55 duration_idx
= tpm_protected_ordinal_duration
[
56 ordinal
& TPM_PROTECTED_ORDINAL_MASK
];
59 if (duration_idx
!= TPM_UNDEFINED
)
60 duration
= priv
->duration_ms
[duration_idx
];
63 return 2 * 60 * 1000; /* Two minutes timeout */
68 int tpm_xfer(struct udevice
*dev
, const uint8_t *sendbuf
, size_t send_size
,
69 uint8_t *recvbuf
, size_t *recv_size
)
71 struct tpm_chip_priv
*priv
= dev_get_uclass_priv(dev
);
72 struct tpm_ops
*ops
= tpm_get_ops(dev
);
78 return ops
->xfer(dev
, sendbuf
, send_size
, recvbuf
, recv_size
);
80 if (!ops
->send
|| !ops
->recv
)
83 /* switch endianess: big->little */
84 count
= get_unaligned_be32(sendbuf
+ TPM_CMD_COUNT_BYTE
);
85 ordinal
= get_unaligned_be32(sendbuf
+ TPM_CMD_ORDINAL_BYTE
);
91 if (count
> send_size
) {
92 debug("invalid count value %x %zx\n", count
, send_size
);
96 debug("%s: Calling send\n", __func__
);
97 ret
= ops
->send(dev
, sendbuf
, send_size
);
101 start
= get_timer(0);
102 stop
= tpm_tis_i2c_calc_ordinal_duration(priv
, ordinal
);
104 ret
= ops
->recv(dev
, priv
->buf
, sizeof(priv
->buf
));
106 if (ret
> *recv_size
)
108 memcpy(recvbuf
, priv
->buf
, ret
);
112 } else if (ret
!= -EAGAIN
) {
116 mdelay(priv
->retry_time_ms
);
117 if (get_timer(start
) > stop
) {
123 ret2
= ops
->cleanup
? ops
->cleanup(dev
) : 0;
125 return ret2
? ret2
: ret
;
128 UCLASS_DRIVER(tpm
) = {
131 .flags
= DM_UC_FLAG_SEQ_ALIAS
,
132 .per_device_auto_alloc_size
= sizeof(struct tpm_chip_priv
),