mirror of https://github.com/wolfSSL/wolfTPM.git
Implementation for TPM2_IoCb_MicrochipHarmony_I2C.
parent
6e1205b1e1
commit
eb079ee22a
|
@ -148,6 +148,9 @@ int TPM2_IoCb(TPM2_CTX* ctx, INT32 isRead, UINT32 addr,
|
|||
ret = TPM2_IoCb_Infineon_I2C(ctx, isRead, addr, buf, size, userCtx);
|
||||
#elif defined(WOLFSSL_ESPIDF)
|
||||
ret = TPM2_IoCb_Espressif_I2C(ctx, isRead, addr, buf, size, userCtx);
|
||||
#elif defined(WOLFTPM_MICROCHIP_HARMONY)
|
||||
/* Use MicrochipHarmony I2C */
|
||||
ret = TPM2_IoCb_MicrochipHarmony_I2C(ctx, isRead, addr, buf, size, userCtx);
|
||||
#else
|
||||
/* TODO: Add your platform here for HW I2C interface */
|
||||
printf("Add your platform here for HW I2C interface\n");
|
||||
|
|
|
@ -88,6 +88,9 @@ WOLFTPM_LOCAL int TPM2_IoCb_Infineon_I2C(TPM2_CTX* ctx, int isRead, word32 addr,
|
|||
#elif defined(WOLFSSL_ESPIDF)
|
||||
WOLFTPM_LOCAL int TPM2_IoCb_Espressif_I2C(TPM2_CTX* ctx, int isRead, word32 addr,
|
||||
byte* buf, word16 size, void* userCtx);
|
||||
#elif defined(WOLFTPM_MICROCHIP_HARMONY)
|
||||
WOLFTPM_LOCAL int TPM2_IoCb_MicrochipHarmony_I2C(TPM2_CTX* ctx, int isRead, word32 addr,
|
||||
byte* buf, word16 size, void* userCtx);
|
||||
#endif /* __linux__ */
|
||||
|
||||
#else /* SPI */
|
||||
|
|
|
@ -49,13 +49,232 @@
|
|||
|
||||
#if defined(WOLFTPM_MICROCHIP_HARMONY)
|
||||
|
||||
#include "configuration.h"
|
||||
#include "definitions.h"
|
||||
|
||||
#ifdef WOLFTPM_I2C /* Microchip Harmony Hal I2C */
|
||||
/* We are using the I2C bitbang library. */
|
||||
#include <i2cbb/i2c_bb.h>
|
||||
/* Use sys_time to implement delay. */
|
||||
#include "system/time/sys_time.h"
|
||||
|
||||
#ifndef TPM_I2C_TRIES
|
||||
#define TPM_I2C_TRIES 10
|
||||
#endif
|
||||
#ifndef TPM2_I2C_ADDR
|
||||
#define TPM2_I2C_ADDR 0x2e
|
||||
#endif
|
||||
|
||||
static uintptr_t dummy_context;
|
||||
|
||||
static void dummy_callback(uintptr_t context)
|
||||
{
|
||||
(void) context;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait for time_ms using Micochip Harmony SYS_TIME API. */
|
||||
static void microchip_wait(uint32_t time_ms)
|
||||
{
|
||||
/* Microchip Harmony example from documentation.
|
||||
* SYS_TIME_DelayMS will internally create the timer,
|
||||
* and SYS_TIME_DelayIsComplete will delete it when
|
||||
* the delay has completed. */
|
||||
SYS_TIME_HANDLE timer = SYS_TIME_HANDLE_INVALID;
|
||||
|
||||
if (SYS_TIME_DelayMS(time_ms, &timer) != SYS_TIME_SUCCESS) {
|
||||
printf("error: microchip_wait: SYS_TIME_DelayMS failed\n");
|
||||
}
|
||||
else if(SYS_TIME_DelayIsComplete(timer) != true) {
|
||||
/* Loop until delay is complete. */
|
||||
while (SYS_TIME_DelayIsComplete(timer) == false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Microchip Harmony I2C */
|
||||
static int i2c_read(void* userCtx, word32 reg, byte* data, int len)
|
||||
{
|
||||
int ret = TPM_RC_FAILURE;
|
||||
I2CBB_ERROR status = I2CBB_ERROR_NONE;
|
||||
bool queued = false;
|
||||
int timeout = TPM_I2C_TRIES;
|
||||
int busy_retry = TPM_I2C_TRIES;
|
||||
byte buf[1];
|
||||
|
||||
if (I2C_BB_IsBusy()) {
|
||||
printf("error: i2c_read: already busy\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TIS layer should never provide a buffer larger than this,
|
||||
but double check for good coding practice */
|
||||
if (len > MAX_SPI_FRAMESIZE) {
|
||||
printf("error: i2c_read: len too large: %d\n", len);
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
buf[0] = (reg & 0xFF); /* convert to simple 8-bit address for I2C */
|
||||
|
||||
do {
|
||||
/* Queue the write with I2C_BB. */
|
||||
queued = I2C_BB_Write(TPM2_I2C_ADDR, buf, sizeof(buf));
|
||||
|
||||
if (!queued) {
|
||||
printf("error: i2c_read: I2C_BB_Write failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
busy_retry = TPM_I2C_TRIES;
|
||||
|
||||
while (I2C_BB_IsBusy() && --busy_retry > 0) {
|
||||
microchip_wait(250);
|
||||
}
|
||||
|
||||
if (I2C_BB_IsBusy()) {
|
||||
printf("error: i2c_read: busy wait timed out\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = I2C_BB_ErrorGet();
|
||||
if (status == I2CBB_ERROR_NAK) {
|
||||
microchip_wait(250);
|
||||
}
|
||||
} while (status == I2CBB_ERROR_NAK && --timeout > 0);
|
||||
|
||||
if (status != I2CBB_ERROR_NONE) {
|
||||
if (status == I2CBB_ERROR_NAK) {
|
||||
printf("error: i2c_read: I2C_BB_Write failed with NAK: %d\n",
|
||||
status);
|
||||
}
|
||||
else {
|
||||
printf("error: i2c_read: I2C_BB_Write failed: %d\n", status);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
timeout = TPM_I2C_TRIES;
|
||||
|
||||
do {
|
||||
/* Queue the read with I2C_BB. */
|
||||
queued = I2C_BB_Read(TPM2_I2C_ADDR, data, len);
|
||||
|
||||
if (!queued) {
|
||||
printf("error: i2c_read: I2C_BB_Read failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
busy_retry = TPM_I2C_TRIES;
|
||||
|
||||
while (I2C_BB_IsBusy() && --busy_retry > 0) {
|
||||
microchip_wait(250);
|
||||
}
|
||||
|
||||
status = I2C_BB_ErrorGet();
|
||||
if (status == I2CBB_ERROR_NAK) {
|
||||
microchip_wait(250);
|
||||
}
|
||||
} while (status == I2CBB_ERROR_NAK && --timeout > 0);
|
||||
|
||||
if (status == I2CBB_ERROR_NONE) {
|
||||
ret = TPM_RC_SUCCESS;
|
||||
}
|
||||
else {
|
||||
printf("error: I2C Read failure %d (tries %d)\n",
|
||||
status, TPM_I2C_TRIES - timeout);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i2c_write(void* userCtx, word32 reg, byte* data, int len)
|
||||
{
|
||||
int ret = TPM_RC_FAILURE;
|
||||
I2CBB_ERROR status = I2CBB_ERROR_NONE;
|
||||
bool queued = false;
|
||||
int timeout = TPM_I2C_TRIES;
|
||||
int busy_retry = TPM_I2C_TRIES;
|
||||
byte buf[MAX_SPI_FRAMESIZE+1];
|
||||
|
||||
/* TIS layer should never provide a buffer larger than this,
|
||||
but double check for good coding practice */
|
||||
if (len > MAX_SPI_FRAMESIZE) {
|
||||
printf("error: i2c_write: len too large: %d\n", len);
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (I2C_BB_IsBusy()) {
|
||||
printf("error: i2c_write: already busy\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Build packet with TPM register and data */
|
||||
buf[0] = (reg & 0xFF); /* convert to simple 8-bit address for I2C */
|
||||
XMEMCPY(buf + 1, data, len);
|
||||
|
||||
do {
|
||||
/* Queue the write with I2C_BB. */
|
||||
queued = I2C_BB_Write(TPM2_I2C_ADDR, buf, len + 1);
|
||||
|
||||
if (!queued) {
|
||||
printf("error: i2c_write: I2C_BB_Write failed: %d\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (I2C_BB_IsBusy() && --busy_retry > 0) {
|
||||
microchip_wait(250);
|
||||
}
|
||||
|
||||
status = I2C_BB_ErrorGet();
|
||||
|
||||
if (status == I2CBB_ERROR_NAK) {
|
||||
microchip_wait(250);
|
||||
}
|
||||
} while (status == I2CBB_ERROR_NAK && --timeout > 0);
|
||||
|
||||
if (status == I2CBB_ERROR_NONE) {
|
||||
ret = TPM_RC_SUCCESS;
|
||||
}
|
||||
else {
|
||||
printf("I2C Write failure %d\n", status);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int TPM2_IoCb_MicrochipHarmony_I2C(TPM2_CTX* ctx, int isRead, word32 addr,
|
||||
byte* buf, word16 size, void* userCtx)
|
||||
{
|
||||
int ret = TPM_RC_FAILURE;
|
||||
|
||||
/* Set callback to null to do time based polling of
|
||||
* I2C_BB_IsBusy instead.
|
||||
*
|
||||
* Note: Apparently a callback is actually required,
|
||||
* even if not used.
|
||||
* */
|
||||
I2C_BB_Initialize();
|
||||
I2C_BB_CallbackRegister(dummy_callback, dummy_context);
|
||||
|
||||
if (isRead) {
|
||||
ret = i2c_read(userCtx, addr, buf, size);
|
||||
}
|
||||
else {
|
||||
ret = i2c_write(userCtx, addr, buf, size);
|
||||
}
|
||||
|
||||
(void)userCtx;
|
||||
(void)ctx;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else /* Microchip Harmony Hal SPI */
|
||||
|
||||
#ifdef WOLFTPM_CHECK_WAIT_STATE
|
||||
#error This driver does not support check wait state yet
|
||||
#endif
|
||||
|
||||
#include "configuration.h"
|
||||
#include "definitions.h"
|
||||
|
||||
/* TPM Chip Select Pin (default PC5) */
|
||||
#ifndef TPM_SPI_PIN
|
||||
#define SYS_PORT_PIN_PC5
|
||||
|
@ -98,6 +317,7 @@ int TPM2_IoCb_Microchip_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#endif /* WOLFTPM_I2C */
|
||||
#endif /* WOLFTPM_MICROCHIP_HARMONY */
|
||||
#endif /* !(WOLFTPM_LINUX_DEV || WOLFTPM_SWTPM || WOLFTPM_WINAPI) */
|
||||
#endif /* WOLFTPM_INCLUDE_IO_FILE */
|
||||
|
|
Loading…
Reference in New Issue