Skip to content

Commit 703b728

Browse files
authored
Merge pull request #340 from philljj/iocb_microchipharmony_i2c
Iocb microchipharmony i2c
2 parents 6e1205b + a2fede3 commit 703b728

File tree

3 files changed

+229
-3
lines changed

3 files changed

+229
-3
lines changed

hal/tpm_io.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ int TPM2_IoCb(TPM2_CTX* ctx, INT32 isRead, UINT32 addr,
148148
ret = TPM2_IoCb_Infineon_I2C(ctx, isRead, addr, buf, size, userCtx);
149149
#elif defined(WOLFSSL_ESPIDF)
150150
ret = TPM2_IoCb_Espressif_I2C(ctx, isRead, addr, buf, size, userCtx);
151+
#elif defined(WOLFTPM_MICROCHIP_HARMONY)
152+
/* Use Microchip Harmony I2C */
153+
ret = TPM2_IoCb_MicrochipHarmony_I2C(ctx, isRead, addr, buf, size, userCtx);
151154
#else
152155
/* TODO: Add your platform here for HW I2C interface */
153156
printf("Add your platform here for HW I2C interface\n");

hal/tpm_io.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ WOLFTPM_LOCAL int TPM2_IoCb_Infineon_I2C(TPM2_CTX* ctx, int isRead, word32 addr,
8888
#elif defined(WOLFSSL_ESPIDF)
8989
WOLFTPM_LOCAL int TPM2_IoCb_Espressif_I2C(TPM2_CTX* ctx, int isRead, word32 addr,
9090
byte* buf, word16 size, void* userCtx);
91+
#elif defined(WOLFTPM_MICROCHIP_HARMONY)
92+
WOLFTPM_LOCAL int TPM2_IoCb_MicrochipHarmony_I2C(TPM2_CTX* ctx, int isRead, word32 addr,
93+
byte* buf, word16 size, void* userCtx);
9194
#endif /* __linux__ */
9295

9396
#else /* SPI */

hal/tpm_io_microchip.c

Lines changed: 223 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,232 @@
4949

5050
#if defined(WOLFTPM_MICROCHIP_HARMONY)
5151

52+
#include "configuration.h"
53+
#include "definitions.h"
54+
55+
#ifdef WOLFTPM_I2C /* Microchip Harmony Hal I2C */
56+
/* We are using the I2C bit-bang library. */
57+
#include <i2cbb/i2c_bb.h>
58+
/* Use sys_time to implement delay. */
59+
#include "system/time/sys_time.h"
60+
61+
#ifndef TPM_I2C_TRIES
62+
#define TPM_I2C_TRIES 10
63+
#endif
64+
#ifndef TPM2_I2C_ADDR
65+
#define TPM2_I2C_ADDR 0x2e
66+
#endif
67+
68+
static uintptr_t dummy_context;
69+
70+
static void dummy_callback(uintptr_t context)
71+
{
72+
(void) context;
73+
return;
74+
}
75+
76+
/* Wait for time_ms using Microchip Harmony SYS_TIME API. */
77+
static void microchip_wait(uint32_t time_ms)
78+
{
79+
/* Microchip Harmony example from documentation.
80+
* SYS_TIME_DelayMS will internally create the timer,
81+
* and SYS_TIME_DelayIsComplete will delete it when
82+
* the delay has completed. */
83+
SYS_TIME_HANDLE timer = SYS_TIME_HANDLE_INVALID;
84+
85+
if (SYS_TIME_DelayMS(time_ms, &timer) != SYS_TIME_SUCCESS) {
86+
printf("error: microchip_wait: SYS_TIME_DelayMS failed\n");
87+
}
88+
else if(SYS_TIME_DelayIsComplete(timer) != true) {
89+
/* Loop until delay is complete. */
90+
while (SYS_TIME_DelayIsComplete(timer) == false);
91+
}
92+
93+
return;
94+
}
95+
96+
/* Microchip Harmony I2C */
97+
static int i2c_read(void* userCtx, word32 reg, byte* data, int len)
98+
{
99+
int ret = TPM_RC_FAILURE;
100+
I2CBB_ERROR status = I2CBB_ERROR_NONE;
101+
bool queued = false;
102+
int timeout = TPM_I2C_TRIES;
103+
int busy_retry = TPM_I2C_TRIES;
104+
byte buf[1];
105+
106+
if (I2C_BB_IsBusy()) {
107+
printf("error: i2c_read: already busy\n");
108+
return -1;
109+
}
110+
111+
/* TIS layer should never provide a buffer larger than this,
112+
but double check for good coding practice */
113+
if (len > MAX_SPI_FRAMESIZE) {
114+
printf("error: i2c_read: len too large: %d\n", len);
115+
return BAD_FUNC_ARG;
116+
}
117+
118+
buf[0] = (reg & 0xFF); /* convert to simple 8-bit address for I2C */
119+
120+
do {
121+
/* Queue the write with I2C_BB. */
122+
queued = I2C_BB_Write(TPM2_I2C_ADDR, buf, sizeof(buf));
123+
124+
if (!queued) {
125+
printf("error: i2c_read: I2C_BB_Write failed\n");
126+
return -1;
127+
}
128+
129+
busy_retry = TPM_I2C_TRIES;
130+
131+
while (I2C_BB_IsBusy() && --busy_retry > 0) {
132+
microchip_wait(250);
133+
}
134+
135+
if (I2C_BB_IsBusy()) {
136+
printf("error: i2c_read: busy wait timed out\n");
137+
return -1;
138+
}
139+
140+
status = I2C_BB_ErrorGet();
141+
if (status == I2CBB_ERROR_NAK) {
142+
microchip_wait(250);
143+
}
144+
} while (status == I2CBB_ERROR_NAK && --timeout > 0);
145+
146+
if (status != I2CBB_ERROR_NONE) {
147+
if (status == I2CBB_ERROR_NAK) {
148+
printf("error: i2c_read: I2C_BB_Write failed with NAK: %d\n",
149+
status);
150+
}
151+
else {
152+
printf("error: i2c_read: I2C_BB_Write failed: %d\n", status);
153+
}
154+
155+
return -1;
156+
}
157+
158+
timeout = TPM_I2C_TRIES;
159+
160+
do {
161+
/* Queue the read with I2C_BB. */
162+
queued = I2C_BB_Read(TPM2_I2C_ADDR, data, len);
163+
164+
if (!queued) {
165+
printf("error: i2c_read: I2C_BB_Read failed\n");
166+
return -1;
167+
}
168+
169+
busy_retry = TPM_I2C_TRIES;
170+
171+
while (I2C_BB_IsBusy() && --busy_retry > 0) {
172+
microchip_wait(250);
173+
}
174+
175+
status = I2C_BB_ErrorGet();
176+
if (status == I2CBB_ERROR_NAK) {
177+
microchip_wait(250);
178+
}
179+
} while (status == I2CBB_ERROR_NAK && --timeout > 0);
180+
181+
if (status == I2CBB_ERROR_NONE) {
182+
ret = TPM_RC_SUCCESS;
183+
}
184+
else {
185+
printf("error: I2C Read failure %d (tries %d)\n",
186+
status, TPM_I2C_TRIES - timeout);
187+
}
188+
189+
return ret;
190+
}
191+
192+
static int i2c_write(void* userCtx, word32 reg, byte* data, int len)
193+
{
194+
int ret = TPM_RC_FAILURE;
195+
I2CBB_ERROR status = I2CBB_ERROR_NONE;
196+
bool queued = false;
197+
int timeout = TPM_I2C_TRIES;
198+
int busy_retry = TPM_I2C_TRIES;
199+
byte buf[MAX_SPI_FRAMESIZE+1];
200+
201+
/* TIS layer should never provide a buffer larger than this,
202+
but double check for good coding practice */
203+
if (len > MAX_SPI_FRAMESIZE) {
204+
printf("error: i2c_write: len too large: %d\n", len);
205+
return BAD_FUNC_ARG;
206+
}
207+
208+
if (I2C_BB_IsBusy()) {
209+
printf("error: i2c_write: already busy\n");
210+
return -1;
211+
}
212+
213+
/* Build packet with TPM register and data */
214+
buf[0] = (reg & 0xFF); /* convert to simple 8-bit address for I2C */
215+
XMEMCPY(buf + 1, data, len);
216+
217+
do {
218+
/* Queue the write with I2C_BB. */
219+
queued = I2C_BB_Write(TPM2_I2C_ADDR, buf, len + 1);
220+
221+
if (!queued) {
222+
printf("error: i2c_write: I2C_BB_Write failed: %d\n", status);
223+
return -1;
224+
}
225+
226+
while (I2C_BB_IsBusy() && --busy_retry > 0) {
227+
microchip_wait(250);
228+
}
229+
230+
status = I2C_BB_ErrorGet();
231+
232+
if (status == I2CBB_ERROR_NAK) {
233+
microchip_wait(250);
234+
}
235+
} while (status == I2CBB_ERROR_NAK && --timeout > 0);
236+
237+
if (status == I2CBB_ERROR_NONE) {
238+
ret = TPM_RC_SUCCESS;
239+
}
240+
else {
241+
printf("I2C Write failure %d\n", status);
242+
}
243+
return ret;
244+
}
245+
246+
int TPM2_IoCb_MicrochipHarmony_I2C(TPM2_CTX* ctx, int isRead, word32 addr,
247+
byte* buf, word16 size, void* userCtx)
248+
{
249+
int ret = TPM_RC_FAILURE;
250+
251+
/* Set callback to null to do time based polling of
252+
* I2C_BB_IsBusy instead.
253+
*
254+
* Note: Apparently a callback is actually required,
255+
* even if not used.
256+
* */
257+
I2C_BB_Initialize();
258+
I2C_BB_CallbackRegister(dummy_callback, dummy_context);
259+
260+
if (isRead) {
261+
ret = i2c_read(userCtx, addr, buf, size);
262+
}
263+
else {
264+
ret = i2c_write(userCtx, addr, buf, size);
265+
}
266+
267+
(void)userCtx;
268+
(void)ctx;
269+
270+
return ret;
271+
}
272+
#else /* Microchip Harmony Hal SPI */
273+
52274
#ifdef WOLFTPM_CHECK_WAIT_STATE
53275
#error This driver does not support check wait state yet
54276
#endif
55277

56-
#include "configuration.h"
57-
#include "definitions.h"
58-
59278
/* TPM Chip Select Pin (default PC5) */
60279
#ifndef TPM_SPI_PIN
61280
#define SYS_PORT_PIN_PC5
@@ -98,6 +317,7 @@ int TPM2_IoCb_Microchip_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf,
98317
return ret;
99318
}
100319

320+
#endif /* WOLFTPM_I2C */
101321
#endif /* WOLFTPM_MICROCHIP_HARMONY */
102322
#endif /* !(WOLFTPM_LINUX_DEV || WOLFTPM_SWTPM || WOLFTPM_WINAPI) */
103323
#endif /* WOLFTPM_INCLUDE_IO_FILE */

0 commit comments

Comments
 (0)