blob: ec840d725dbf10ac4a9d2b9c6908865ee4903d8d [file] [log] [blame]
/*
* Copyright (c) 2024 Brill Power Ltd.
* Copyright (c) 2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief CRC public API header file.
* @ingroup crc_interface
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_CRC_H
#define ZEPHYR_INCLUDE_DRIVERS_CRC_H
#include <zephyr/device.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/crc.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Interfaces for Cyclic Redundancy Check (CRC) devices.
* @defgroup crc_interface CRC driver APIs
* @ingroup io_interfaces
* @{
*/
/**
* @name CRC input/output string flags
* @anchor CRC_FLAGS
*
* @{
*/
/**
* @brief Reverse input string
*/
#define CRC_FLAG_REVERSE_INPUT BIT(0)
/**
* @brief Reverse output string
*/
#define CRC_FLAG_REVERSE_OUTPUT BIT(1)
/** @} */
/**
* @cond INTERNAL_HIDDEN
* Internally seed values for CRC algorithms are defined.
* These values are used to initialize the CRC calculation.
*/
/** CRC4 initial value */
#define CRC4_INIT_VAL 0x0
/** CRC4_TI initial value */
#define CRC4_TI_INIT_VAL 0x0
/** CRC7_BE initial value */
#define CRC7_BE_INIT_VAL 0x0
/** CRC8 initial value */
#define CRC8_INIT_VAL 0x0
/** CRC8_CCITT initial value */
#define CRC8_CCITT_INIT_VAL 0xFF
/** CRC8_ROHC initial value */
#define CRC8_ROHC_INIT_VAL 0xFF
/** CRC16 initial value */
#define CRC16_INIT_VAL 0x0
/** CRC16_ANSI initial value */
#define CRC16_ANSI_INIT_VAL 0x0
/** CRC16_CCITT initial value */
#define CRC16_CCITT_INIT_VAL 0x0000
/** CRC16_ITU_T initial value */
#define CRC16_ITU_T_INIT_VAL 0x0000
/** CRC24_PGP initial value */
#define CRC24_PGP_INIT_VALUE 0x00B704CEU
/** CRC32_C initial value */
#define CRC32_IEEE_INIT_VAL 0xFFFFFFFFU
/** CRC32_K_4_2 initial value */
#define CRC32_C_INIT_VAL 0xFFFFFFFFU
/** @endcond */
/**
* @brief CRC state enumeration
*/
enum crc_state {
/** CRC device is in IDLE state. */
CRC_STATE_IDLE = 0,
/** CRC calculation is in-progress. */
CRC_STATE_IN_PROGRESS
};
/**
* @brief Provides a type to hold CRC initial seed value
*/
typedef uint32_t crc_init_val_t;
/**
* @brief Provides a type to hold CRC polynomial value.
* See @a CRC_POLYNOMIAL for predefined polynomial values.
*/
typedef uint32_t crc_poly_t;
/**
* @brief Provides a type to hold CRC result value
*/
typedef uint32_t crc_result_t;
/**
* @brief CRC context structure
*
* This structure holds the state of the CRC calculation, including
* the type of CRC being calculated, the current state, the polynomial,
* the initial seed value, and the result of the CRC calculation.
*/
struct crc_ctx {
/** CRC calculation type */
enum crc_type type;
/** Current CRC device state */
enum crc_state state;
/** CRC input/output reverse flags */
uint32_t reversed;
/** CRC polynomial */
crc_poly_t polynomial;
/** CRC initial seed value */
crc_init_val_t seed;
/** CRC result */
crc_result_t result;
};
/**
* @brief Callback API upon CRC calculation begin
* See @a crc_begin() for argument description
*/
typedef int (*crc_api_begin)(const struct device *dev, struct crc_ctx *ctx);
/**
* @brief Callback API upon CRC calculation stream update
* See @a crc_update() for argument description
*/
typedef int (*crc_api_update)(const struct device *dev, struct crc_ctx *ctx, const void *buffer,
size_t bufsize);
/**
* @brief Callback API upon CRC calculation finish
* See @a crc_finish() for argument description
*/
typedef int (*crc_api_finish)(const struct device *dev, struct crc_ctx *ctx);
__subsystem struct crc_driver_api {
crc_api_begin begin;
crc_api_update update;
crc_api_finish finish;
};
/**
* @brief Configure CRC unit for calculation
*
* @param dev Pointer to the device structure
* @param ctx Pointer to the CRC context structure
*
* @retval 0 if successful
* @retval -ENOSYS if function is not implemented
* @retval errno code on failure
*/
__syscall int crc_begin(const struct device *dev, struct crc_ctx *ctx);
static inline int z_impl_crc_begin(const struct device *dev, struct crc_ctx *ctx)
{
const struct crc_driver_api *api = (const struct crc_driver_api *)dev->api;
if (api->begin == NULL) {
return -ENOSYS;
}
return api->begin(dev, ctx);
}
/**
* @brief Perform CRC calculation on the provided data buffer and retrieve result
*
* @param dev Pointer to the device structure
* @param ctx Pointer to the CRC context structure
* @param buffer Pointer to input data buffer
* @param bufsize Number of bytes in *buffer
*
* @retval 0 if successful
* @retval -ENOSYS if function is not implemented
* @retval errno code on failure
*/
__syscall int crc_update(const struct device *dev, struct crc_ctx *ctx, const void *buffer,
size_t bufsize);
static inline int z_impl_crc_update(const struct device *dev, struct crc_ctx *ctx,
const void *buffer, size_t bufsize)
{
const struct crc_driver_api *api = (const struct crc_driver_api *)dev->api;
if (api->update == NULL) {
return -ENOSYS;
}
return api->update(dev, ctx, buffer, bufsize);
}
/**
* @brief Finalize CRC calculation
*
* @param dev Pointer to the device structure
* @param ctx Pointer to the CRC context structure
*
* @retval 0 if successful
* @retval -ENOSYS if function is not implemented
* @retval errno code on failure
*/
__syscall int crc_finish(const struct device *dev, struct crc_ctx *ctx);
static inline int z_impl_crc_finish(const struct device *dev, struct crc_ctx *ctx)
{
const struct crc_driver_api *api = (const struct crc_driver_api *)dev->api;
if (api->finish == NULL) {
return -ENOSYS;
}
return api->finish(dev, ctx);
}
/**
* @brief Verify CRC result
*
* @param ctx Pointer to the CRC context structure
* @param expected Expected CRC result
*
* @retval 0 if successful
* @retval -EBUSY if CRC calculation is not completed
* @retval -EPERM if CRC verification failed
*/
static inline int crc_verify(struct crc_ctx *ctx, crc_result_t expected)
{
if (ctx == NULL) {
return -EINVAL;
}
if (ctx->state == CRC_STATE_IN_PROGRESS) {
return -EBUSY;
}
if (expected != ctx->result) {
return -EPERM;
}
return 0;
}
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#include <zephyr/syscalls/crc.h>
#endif /* ZEPHYR_INCLUDE_DRIVERS_CRC_H */