drivers: Introduce new OTP subsystem

Introduce a new OTP subsystem to be able to interact with One Time
Programmable(OTP) memory. For now, add basic read()/program() APIs.
Program() API is default disabled due to its sensitivity.

File drivers/otp.h is inspired by drivers/eeprom.h as the basic
features are similar.

Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
This commit is contained in:
Gatien Chevallier
2025-10-15 15:21:08 +02:00
committed by Fabio Baltieri
parent 89b097428d
commit 7db8328b08
8 changed files with 195 additions and 0 deletions

View File

@@ -45,6 +45,7 @@ Peripherals
mspi.rst
mbox.rst
opamp.rst
otp/index.rst
pcie.rst
peci.rst
ps2.rst

View File

@@ -0,0 +1,23 @@
.. _otp_api:
OTP API
#######
Overview
********
The OTP API provides means to provision and read
:abbr:`OTP(One Time Programmable)` memory devices
API implementation Reference
****************************
.. doxygengroup:: otp_interface
Configuration Options
*********************
OTP related configuration options:
* :kconfig:option:`CONFIG_OTP`
* :kconfig:option:`CONFIG_OTP_PROGRAM`
* :kconfig:option:`CONFIG_OTP_INIT_PRIORITY`

View File

@@ -0,0 +1,17 @@
.. _otp:
One Time Programmable (OTP) memory devices
##########################################
Overview
********
OTP memory devices handle memory that is expected to be permanent. This memory
is usually provisioned during manufacturing, but there are some use-cases in
which one needs to program the OTP memory at a later lifecycle state (e.g:
monotonic counters, cryptographic keys, etc...).
.. toctree::
:maxdepth: 2
api.rst

View File

@@ -71,6 +71,7 @@ add_subdirectory_ifdef(CONFIG_MODEM modem)
add_subdirectory_ifdef(CONFIG_MSPI mspi)
add_subdirectory_ifdef(CONFIG_NET_DRIVERS net)
add_subdirectory_ifdef(CONFIG_OPAMP opamp)
add_subdirectory_ifdef(CONFIG_OTP otp)
add_subdirectory_ifdef(CONFIG_PECI peci)
add_subdirectory_ifdef(CONFIG_PINCTRL pinctrl)
add_subdirectory_ifdef(CONFIG_PM_CPU_OPS pm_cpu_ops)

View File

@@ -67,6 +67,7 @@ source "drivers/modem/Kconfig"
source "drivers/mspi/Kconfig"
source "drivers/net/Kconfig"
source "drivers/opamp/Kconfig"
source "drivers/otp/Kconfig"
source "drivers/pcie/Kconfig"
source "drivers/peci/Kconfig"
source "drivers/pinctrl/Kconfig"

View File

@@ -0,0 +1,3 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_library()

35
drivers/otp/Kconfig Normal file
View File

@@ -0,0 +1,35 @@
# OTP driver configuration options
# Copyright (c) 2025 STMicroelectronics
# SPDX-License-Identifier: Apache-2.0
menuconfig OTP
bool "One Time Programmable (OTP) drivers [EXPERIMENTAL]"
select EXPERIMENTAL
help
Enable support for hardware OTP. The OTP technology can be anything
from fuses to flash memory option bytes as long as it stays one time
programmable.
if OTP
module = OTP
module-str = otp
source "subsys/logging/Kconfig.template.log_config"
config OTP_INIT_PRIORITY
int "OTP init priority"
default KERNEL_INIT_PRIORITY_DEVICE
help
OTP device drivers initialization priority. This initialization
priority is used unless the driver implementation has its own
initialization priority.
config OTP_PROGRAM
bool "Support OTP programming through Zephyr API"
help
Allowing the programming of OTPs may cause irreversible damage
to a platform. Use it very carefully and at your own risk.
endif # OTP

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2025 STMicroelectronics
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @ingroup otp_interface
* @brief Main header file for OTP driver API.
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_OTP_H_
#define ZEPHYR_INCLUDE_DRIVERS_OTP_H_
/**
* @brief Interfaces for One Time Programmable (OTP) Memory.
* @defgroup otp_interface One Time Programmable Memory
* @since 4.4
* @version 0.1.0
* @ingroup io_interfaces
* @{
*/
#include <stddef.h>
#include <sys/types.h>
#include <zephyr/device.h>
#include <zephyr/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @cond INTERNAL_HIDDEN
*
* For internal driver use only, skip these in public documentation.
*/
/**
* @brief Callback API upon reading from the OTP memory.
* See @a otp_read() for argument description
*/
typedef int (*otp_api_read)(const struct device *dev, off_t offset, void *data, size_t len);
/**
* @brief Callback API upon writing to the OTP memory.
* See @a otp_program() for argument description
*/
typedef int (*otp_api_program)(const struct device *dev, off_t offset, const void *data,
size_t len);
__subsystem struct otp_driver_api {
otp_api_read read;
#if defined(CONFIG_OTP_PROGRAM) || defined(__DOXYGEN__)
otp_api_program program;
#endif
};
/** @endcond */
/**
* @brief Read data from OTP memory
*
* @param dev OTP device
* @param offset Address offset to read from.
* @param data Buffer to store read data.
* @param len Number of bytes to read.
*
* @return 0 on success, negative errno code on failure.
*/
__syscall int otp_read(const struct device *dev, off_t offset, void *data, size_t len);
static inline int z_impl_otp_read(const struct device *dev, off_t offset, void *data, size_t len)
{
return DEVICE_API_GET(otp, dev)->read(dev, offset, data, len);
}
#if defined(CONFIG_OTP_PROGRAM) || defined(__DOXYGEN__)
/**
* @brief Program data to the given OTP memory
*
* @param dev OTP device
* @param offset Address offset to program data to.
* @param data Buffer with data to program.
* @param len Number of bytes to program.
*
* @return 0 on success, negative errno code on failure.
*/
__syscall int otp_program(const struct device *dev, off_t offset, const void *data, size_t len);
static inline int z_impl_otp_program(const struct device *dev, off_t offset, const void *data,
size_t len)
{
const struct otp_driver_api *api = DEVICE_API_GET(otp, dev);
if (api->program == NULL) {
return -ENOSYS;
}
return api->program(dev, offset, data, len);
}
#endif
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#include <zephyr/syscalls/otp.h>
#endif /* ZEPHYR_INCLUDE_DRIVERS_OTP_H_ */