diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 3044e89..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,93 +0,0 @@ -![](https://raw.githubusercontent.com/TexasInstruments/texasinstruments.github.io/main/documents/TI_document_header.png) - -# Scope - -This Code of Conduct applies to all community spaces on the Texas Instruments -Organizational page. It further applies when an individual is officially -representing the community in public spaces. Examples of representing our -community include using an official e-mail address, posting via an official -social media account, or acting as an appointed representative at an online or -offline event. - -## Version - -This is version 1.0 of the Code of Conduct. - -# Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, caste, color, religion, or sexual -identity and orientation. - -We further pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -# Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the overall - community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or advances of - any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email address, - without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -# Enforcement - -The Texas Instruments Project maintainers have the right and responsibility to -remove, edit, or reject comments, commits, code, wiki edits, issues, and other -contributions that are not aligned to this Code of Conduct, and will -communicate reasons for moderation decisions when appropriate. - -Texas Instruments Project maintainers who do not follow or enforce the Code of -Conduct in good faith may face temporary or permanent repercussions as -determined by other members of the Texas Instruments Oversight Team. - -## Enforcement Guidelines - -The Project Maintainers will take appropriate action as deemed necessary based -upon a review of the incident. These actions can include: - -* Removal of the content in question -* A warning to those involved and a review of how it volated the Code of Conduct -* A temporary ban from the Community -* A permanent ban from the Community - -## Reporting a Code of Conduct Issue - -The Project Maintainers from Texas Instruments will review and investigate all -complaints, and will respond in a way, as noted in the Enforcement Guidelines -above, that they deem appropriate to the circumstances. All complaints will -be reviewed and investigated promptly and fairly. - -They are further obligated to maintain confidentiality with regard to the -reporter of an incident. Further details of specific enforcement policies may -be posted separately. - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the Project Maintainers responsible for enforcement at: -**tiosscoc@list.ti.com**. - -# Attribution - -This Code of Conduct is adapted from the Contributor Covenant available at: - -- Homepage: https://www.contributor-covenant.org -- v2.1: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e32cd54 --- /dev/null +++ b/Makefile @@ -0,0 +1,122 @@ +# Copyright (c) 2024, Texas Instruments Incorporated +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Texas Instruments Incorporated nor the names of +# its contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +ifdef OS +RM = rm +RMDIR = rmdir +MKDIR = mkdir +unix_to_dos = $(subst /,\,$1) +OSP = windows +else +ifeq ($(shell uname), Linux) +RM = rm -f +RMDIR = rm -rf +MKDIR = mkdir -p +OSP = unix +else +RM = rm -f +RMDIR = rm -rf +MKDIR = mkdir -p +OSP = macos +ifeq ($(CC),) +CC := clang +endif +endif +endif + +ifeq ($(CC),) +CC := gcc +endif + +INC = -I./include + +CFLAGS = -fPIC $(INC) -Weverything \ + -Wno-documentation \ + -Wno-padded \ + -Wno-poison-system-directories +LDFLAGS = -shared +LIB_DIR = lib + +DEBUGFLAGS = -O0 -g -D _DEBUG +RELEASEFLAGS = -O2 -D NDEBUG +build ?= release + +ifeq ($(build), debug) + CFLAGS += $(DEBUGFLAGS) + TARGET = $(LIB_DIR)/libpmic.so +endif + +ifeq ($(build), release) + CFLAGS += $(RELEASEFLAGS) + TARGET = $(LIB_DIR)/libpmic.so +endif + +SOURCES = \ + src/pmic.c \ + src/pmic_core.c \ + src/pmic_io.c + +OBJECTS = $(SOURCES:.c=.o) + +.PHONY: docs clean help + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(MKDIR) $(LIB_DIR) + $(call $(CC) $(CFLAGS) $(LDFLAGS) -o $(TARGET) $(OBJECTS)) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(TARGET) $(OBJECTS) + $(RM) $(OBJECTS) + +docs: + doxygen docs/ti.doxyfile + +help: + @echo "# make help" + @echo "# ------------------------------------------------------" + @echo "# make [OPTIONAL MAKE VARIABLES] Note: use gmake for windows" + @echo "Supported targets: " + @echo "------------------" + @echo "all : Builds the library" + @echo "clean : Cleans the library" + @echo "Optional make variables:" + @echo "------------------------" + @echo "CC=[Cross-compiler to be used]" + @echo " Default: gcc" + @echo "BUILD_PROFILE=[release debug]" + @echo " Default: release" + @echo "OS=[Windows_NT linux]" + @echo " Default: Windows_NT" + +clean: + $(RM) $(TARGET) + $(RM) $(OBJECTS) + $(RMDIR) docs/html/ + $(RMDIR) $(LIB_DIR) diff --git a/include/pmic.h b/include/pmic.h new file mode 100644 index 0000000..c7e1408 --- /dev/null +++ b/include/pmic.h @@ -0,0 +1,179 @@ +/****************************************************************************** + * Copyright (c) 2024 Texas Instruments Incorporated - http://www.ti.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/** + * @defgroup DRV_PMIC_MODULE PMIC Driver + * + * @file pmic.h + * + * @brief Top level include file for PMIC LLD. + */ +#ifndef __PMIC_H__ +#define __PMIC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* Include Files */ +/* ========================================================================== */ +#include "pmic_common.h" +#include "pmic_io.h" +#include "pmic_core.h" +#include "pmic_irq.h" + +/* ========================================================================== */ +/* Macros & Typedefs */ +/* ========================================================================== */ + +/** + * @anchor Pmic_errorCodes + * @name PMIC LLD Error Codes + * + * @brief Error codes returned by PMIC LLD APIs. + * + * @{ + */ +#define PMIC_ST_SUCCESS ((int32_t)0) +#define PMIC_ST_ERR_SPI_COMM_FAIL (-((int32_t)1)) +#define PMIC_ST_ERR_INV_PARAM (-((int32_t)2)) +#define PMIC_ST_ERR_NULL_PARAM (-((int32_t)3)) +#define PMIC_ST_ERR_INV_CRC (-((int32_t)4)) +#define PMIC_ST_ERR_REG_LOCKED (-((int32_t)5)) +#define PMIC_ST_ERR_INV_HANDLE (-((int32_t)6)) +#define PMIC_ST_ERR_FAIL (-((int32_t)7)) +#define PMIC_ST_ERR_NOT_SUPPORTED (-((int32_t)8)) +#define PMIC_ST_WARN_NO_IRQ_REMAINING (-((int32_t)9)) +/** @} */ + +/** + * @anchor Pmic_CoreCfgValidParams + * @name PMIC LLD Configuration Valid Parameters + * + * @brief Indication of which parameters are valid within the Pmic_CoreCfg_t struct. + * + * @details For more information on the parameters, refer to @ref Pmic_CoreCfg. + * + * @note End-user could combine multiple valid parameters using the OR operator. + * + * @{ + */ +#define PMIC_COMM_HANDLE_VALID ((uint32_t)(1U << 0U)) +#define PMIC_IO_TRANSFER_VALID ((uint32_t)(1U << 1U)) +#define PMIC_CRIT_SEC_START_VALID ((uint32_t)(1U << 2U)) +#define PMIC_CRIT_SEC_STOP_VALID ((uint32_t)(1U << 3U)) +#define PMIC_IRQ_RESPONSE_VALID ((uint32_t)(1U << 4U)) +/** @} */ + +/* ========================================================================== */ +/* Structures and Enums */ +/* ========================================================================== */ + +/** + * @anchor Pmic_CoreCfg + * @name PMIC LLD Configuration + * + * @brief Configuration struct holding end-user settings/parameters relating to + * the PMIC handle. + * + * @attention All parameters of the struct must be set by the end-user. Otherwise, + * an error may occur during the Pmic_init() API call. + * + * @note Once the user sets all struct members, the struct should be passed into + * Pmic_init() so that the PMIC driver handle can be initialized with the user's + * desired configurations. + * + * @param validParams Each bit in this variable represents whether a struct member + * is valid. For valid values, refer to @ref Pmic_CoreCfgValidParams. + * + * @param commHandle Pointer to platform-specific transport layer communication handle. + * + * @param ioTransfer Function pointer to platform-specific SPI read/write API. + * Platform-specific API must be capable of transmiting 24 bits and receiving 24 + * bits at once (a single SPI frame). The length parameter is specified in + * number of bytes to be transmitted. + * + * @param critSecStart Function pointer to platform-specific critical section start API. + * + * @param critSecStop Function pointer to platform-specific critical section stop API. + * + * @param irqResponse Function pointer to application-specific response to detected PMIC + * IRQ. Upon each SPI transaction, the driver checks the PMIC status for faults/IRQs; if + * at least one is detected, this API hook will be called in response. + */ +typedef struct Pmic_CoreCfg_s +{ + uint32_t validParams; + + void *commHandle; + int32_t (*ioTransfer)(const struct Pmic_CoreHandle_s *pmicHandle, uint32_t *txBuf, uint32_t *rxBuf, uint8_t length); + void (*critSecStart)(void); + void (*critSecStop)(void); + void (*irqResponse)(void); +} Pmic_CoreCfg_t; + +/* ========================================================================== */ +/* Function Declarations */ +/* ========================================================================== */ + +/** + * @brief Initialize PMIC LLD and validate the MCU connection with the TPS65385x + * PMIC. This API should be called before calling any other TPS65385x LLD APIs. + * + * @param pmicCfg [IN] PMIC handle configuration struct. End-user will input + * their settings/parameters in this struct to initialize the PMIC handle. + * + * @param pmicHandle [OUT] PMIC interface handle. + * + * @return Success code if PMIC LLD is initialized, error code otherwise. For + * valid success/error codes, refer to @ref Pmic_errorCodes. + */ +int32_t Pmic_init(const Pmic_CoreCfg_t *pmicCfg, Pmic_CoreHandle_t *pmicHandle); + +/** + * @brief De-initialize PMIC LLD. This API should be called once the end-user + * application is complete and/or the end-user wants to close communication with + * the PMIC. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @return Success code if PMIC LLD is de-initialized, error code otherwise. For + * valid success/error codes, refer to @ref Pmic_errorCodes. + */ +int32_t Pmic_deinit(Pmic_CoreHandle_t *pmicHandle); + +#ifdef __cplusplus +} + +#endif /* __cplusplus */ +#endif /* __PMIC_H__ */ diff --git a/include/pmic_common.h b/include/pmic_common.h new file mode 100644 index 0000000..23dcf26 --- /dev/null +++ b/include/pmic_common.h @@ -0,0 +1,280 @@ +/****************************************************************************** + * Copyright (c) 2024 Texas Instruments Incorporated - http://www.ti.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/** + * @file pmic_common.h + * + * @brief This file contains declarations/definitions of common macros/defines, + * data structures, and APIs used throughout PMIC LLD. + */ +#ifndef __PMIC_COMMON_H__ +#define __PMIC_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* Include Files */ +/* ========================================================================== */ +#include +#include +#include +#include + +/* ========================================================================== */ +/* Macros & Typedefs */ +/* ========================================================================== */ + +/** + * @anchor Pmic_arraySizeMacro + * @name PMIC Array Size Macro + * + * @brief Macro used to find the size of an array. + * + * @{ + */ +#define COUNT(x) (sizeof(x) / sizeof(x[0])) +/** @} */ + +/** + * @anchor Pmic_commonDefines + * @name PMIC LLD Common Defines + * + * @brief Common defines used throughout PMIC LLD. + * + * @{ + */ +#define PMIC_DISABLE ((bool)false) +#define PMIC_ENABLE ((bool)true) +/** @} */ + +/* ========================================================================== */ +/* Structures and Enums */ +/* ========================================================================== */ + +/** + * @anchor Pmic_CoreHandle + * @name TPS65385x PMIC Handle + * + * @brief Handle to TPS65385x PMIC that is used as input to all driver APIs. + * + * @details The handle contains information related to the TPS65385x PMIC and API + * hooks that serve to abstract platform-specific information, such as the transport + * layer write/read APIs and critical section start/stop. + * + * @attention Once a struct of type Pmic_CoreHandle_t is initialized via the Pmic_init() + * API, end-user must ensure members of the struct are unchanged throughout application + * runtime. + * + * @param drvInitStat Driver initialization status. When the driver is initialized, + * the value comes out to be decimal value 1347242307, hex value 0x504D4943. When + * converting to ASCII, the value reads "PMIC". + * + * @param devId Binary representation of the last two digits of the part number. + * + * @param devRev PMIC device revision identifier. + * + * @param commHandle Pointer to platform-specific transport layer communication handle. + * + * @param ioTransfer Function pointer to platform-specific SPI read/write API. + * Platform-specific API must be capable of transmiting 24 bits and receiving 24 + * bits at once (a single SPI frame). The length parameter is specified in + * number of bytes transmitted. + * + * @param critSecStart Function pointer to platform-specific critical section start API. + * + * @param critSecStop Function pointer to platform-specific critical section stop API. + * + * @param irqResponse Function pointer to application-specific response to detected PMIC + * IRQ. Upon each SPI transaction, the driver checks the PMIC status for faults/IRQs; if + * at least one is detected, this API hook will be called in response. + */ +typedef struct Pmic_CoreHandle_s +{ + uint32_t drvInitStat; + uint8_t devId; + uint8_t devRev; + void *commHandle; + int32_t (*ioTransfer)(const struct Pmic_CoreHandle_s *pmicHandle, uint32_t *txBuf, uint32_t *rxBuf, uint8_t length); + void (*critSecStart)(void); + void (*critSecStop)(void); + void (*irqResponse)(void); +} Pmic_CoreHandle_t; + +/*========================================================================== */ +/* Function Declarations */ +/* ========================================================================== */ + +/** + * @brief Check whether the PMIC handle is valid. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @return Success code if the PMIC handle is valid, error code otherwise. For + * valid success/error codes, refer to @ref Pmic_errorCodes. + */ +int32_t Pmic_checkPmicCoreHandle(const Pmic_CoreHandle_t *pmicHandle); + +/** + * @brief Check whether a validParam is set. + * + * @param validParamVal [IN] Set of valid parameters. + * + * @param bitMask [IN] validParam to check for. + * + * @return True if validParam is set, false if validParam is not set. + */ +static inline bool Pmic_validParamCheck(uint32_t validParamVal, uint32_t bitMask) +{ + return ((validParamVal & bitMask) != 0U); +} + +/** + * @brief Check whether status is equal to the success code and whether a + * parameter \p vpv (validParam value) has parameter \p bMask (bit mask) set. + */ +#define Pmic_validParamStatusCheck(vpv, bMask, status) \ + (((int32_t)status == PMIC_ST_SUCCESS) && Pmic_validParamCheck((uint32_t)vpv, (uint32_t)bMask)) + +/** + * @brief Set a bit field of a register to a desired value. + * + * @param regVal [OUT] Pointer to variable holding register value. + * + * @param regFieldShift [IN] Target bit field position. + * + * @param regFieldMask [IN] Target bit field mask. + * + * @param fieldVal [IN] Desired bit field value. + */ +static inline void Pmic_setBitField( + uint8_t *regVal, uint8_t regFieldShift, uint8_t regFieldMask, uint8_t fieldVal) +{ + *regVal = (((*regVal) & (~regFieldMask)) | ((fieldVal << regFieldShift) & regFieldMask)); +} + +/** + * @brief Set a bit field of a register to a desired value, given a boolean. + * + * @param regVal [OUT] Pointer to variable holding register value. + * + * @param regFieldShift [IN] Target bit field position. + * + * @param fieldVal_b [IN] Desired bit field value. When parameter set to true, + * bit field value will be set to 1. Otherwise, bit field value will be set to 0. + */ +static inline void Pmic_setBitField_b( + uint8_t *regVal, uint8_t regFieldShift, bool fieldVal_b) +{ + const uint8_t fieldVal = fieldVal_b ? 1U : 0U; + const uint8_t fieldMask = (1U << regFieldShift) & 0xFFU; + + *regVal = ((*regVal & ~fieldMask) | ((fieldVal << regFieldShift) & fieldMask)); +} + +/** + * @brief Get a bit field value of a register. + * + * @param regData [IN] Register data/value. + * + * @param regFieldShift [IN] Target bit field position. + * + * @param regFieldMask [IN] Target bit field mask. + * + * @return Desired bit field value. + */ +static inline uint8_t Pmic_getBitField(uint8_t regData, uint8_t regFieldShift, uint8_t regFieldMask) +{ + return ((regData & regFieldMask) >> regFieldShift); +} + +/** + * @brief Get a bit field value of a register cast as boolean. + * + * @param regData [IN] Register data/value. + * + * @param regFieldShift [IN] Target bit field position. + * + * @return Desired bit field value cast as a boolean. + */ +static inline bool Pmic_getBitField_b(uint8_t regData, uint8_t regFieldShift) +{ + const uint8_t bitVal = ((regData & (1U << regFieldShift)) >> regFieldShift); + + return (bitVal == 1U); +} + +/** + * @brief Start a critical section. + * + * @param pmicHandle [IN] PMIC interface handle. + */ +static inline void Pmic_criticalSectionStart(const Pmic_CoreHandle_t *pmicHandle) +{ + if ((pmicHandle != NULL) && (pmicHandle->critSecStart != NULL)) + { + pmicHandle->critSecStart(); + } +} + +/** + * @brief Stop a critical section. + * + * @param pmicHandle [IN] PMIC interface handle. + */ +static inline void Pmic_criticalSectionStop(const Pmic_CoreHandle_t *pmicHandle) +{ + if ((pmicHandle != NULL) && (pmicHandle->critSecStop != NULL)) + { + pmicHandle->critSecStop(); + } +} + +/** + * @brief Execute application-specific IRQ response. + * + * @param pmicHandle [IN] PMIC interface handle. + */ +static inline void Pmic_irqResponse(const Pmic_CoreHandle_t *pmicHandle) +{ + if ((pmicHandle != NULL) && (pmicHandle->irqResponse != NULL)) + { + pmicHandle->irqResponse(); + } +} + +#ifdef __cplusplus +} + +#endif /* __cplusplus */ +#endif /* __PMIC_COMMON_H__ */ diff --git a/include/pmic_core.h b/include/pmic_core.h new file mode 100644 index 0000000..20765a2 --- /dev/null +++ b/include/pmic_core.h @@ -0,0 +1,139 @@ +/****************************************************************************** + * Copyright (c) 2024 Texas Instruments Incorporated - http://www.ti.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/** + * @file pmic_core.h + * + * @brief PMIC LLD Core module header file. + * + * @details This module contains declarations/definitions of macros, data + * structures, and APIs used to interact with PMIC core functionalities. + */ +#ifndef __PMIC_CORE_H__ +#define __PMIC_CORE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* Include Files */ +/* ========================================================================== */ +#include "pmic_common.h" + +/* ========================================================================== */ +/* Macros & Typedefs */ +/* ========================================================================== */ + +/** + * @anchor Pmic_drvInitValues + * @name PMIC LLD Initialization Values + * + * @brief Indication of whether the driver is initialized or not. + * + * @details The value is used to help prevent corrupt PMIC handle usage. When + * converting \p PMIC_DRV_INIT to ASCII, the value reads out to be "PMIC". + * + * @{ + */ +#define PMIC_DRV_INIT ((uint32_t)0x504D4943U) +#define PMIC_DRV_UNINIT ((uint32_t)0U) + +/** + * @anchor Pmic_regLockUnlockValues + * @name TPS65385x Register Lock/Unlock Values + * + * @brief Values to be passed into the `lock` parameter of the Pmic_setRegLock() + * API. + * + * @{ + */ +#define PMIC_LOCK ((bool)true) +#define PMIC_UNLOCK ((bool)false) +/** @} */ + +/* ========================================================================== */ +/* Function Declarations */ +/* ========================================================================== */ + +/** + * @brief Unlock/lock PMIC registers. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @param lock [IN] This parameter decides whether the API locks or unlocks PMIC + * registers. For valid values, refer to @ref Pmic_regLockUnlockValues + * + * @return Success code if the register unlock/lock key has been sent to the + * PMIC, error code otherwise. For valid success/error codes, refer to + * @ref Pmic_errorCodes. + */ +int32_t Pmic_setRegLock(const Pmic_CoreHandle_t *pmicHandle, bool lock); + +/** + * @brief Get the PMIC register lock status. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @param locked [OUT] PMIC register lock status. Value is set to true if PMIC + * configuration registers are locked, else value is set to false. + * + * @return Success code if the PMIC register lock status has been read, error code + * otherwise. For valid success/error codes, refer to @ref Pmic_errorCodes. + */ +int32_t Pmic_getRegLock(const Pmic_CoreHandle_t *pmicHandle, bool *locked); + +/** + * @brief Unlock PMIC registers. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @return Success code if the register unlock key has been sent to the PMIC, error + * code otherwise. For valid success/error codes, refer to @ref Pmic_errorCodes. + */ +int32_t Pmic_unlockRegs(const Pmic_CoreHandle_t *pmicHandle); + +/** + * @brief Lock PMIC registers. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @return Success code if the register lock key has been sent to the PMIC, error + * code otherwise. for valid success/error codes, refer to @ref Pmic_errorCodes. + */ +int32_t Pmic_lockRegs(const Pmic_CoreHandle_t *pmicHandle); + +#ifdef __cplusplus +} + +#endif /* __cplusplus */ +#endif /* __PMIC_CORE_H__ */ diff --git a/include/pmic_io.h b/include/pmic_io.h new file mode 100644 index 0000000..34797de --- /dev/null +++ b/include/pmic_io.h @@ -0,0 +1,236 @@ +/****************************************************************************** + * Copyright (c) 2024 Texas Instruments Incorporated - http://www.ti.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/** + * @file pmic_io.h + * + * @brief LLD-Communication header file containing communication wrapper read/write + * API used internally by PMIC LLD. + */ +#ifndef __PMIC_IO_H__ +#define __PMIC_IO_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* ========================================================================== */ +/* Include Files */ +/* ========================================================================== */ +#include "pmic_common.h" + +/* ========================================================================== */ +/* Macros & Typedefs */ +/* ========================================================================== */ + +/** + * @anchor Pmic_CommandCodes + * @name TPS65385xx PMIC Command Codes + * + * @brief SPI command codes supported by the TPS65385xx PMIC. + * @{ + */ +#define PMIC_CMD_MCU_RST_RQ ((uint8_t)0x04U) +#define PMIC_CMD_MCU_RST_RQ_DATA ((uint8_t)0x5AU) +#define PMIC_CMD_SAFE_EXIT ((uint8_t)0x9AU) +#define PMIC_CMD_SAFE_EXIT_DATA ((uint8_t)0xA5U) +#define PMIC_CMD_SW_UNLOCK ((uint8_t)0xBBU) +#define PMIC_CMD_SW_UNLOCK_DATA ((uint8_t)0x55U) +#define PMIC_CMD_SW_LOCK ((uint8_t)0xBDU) +#define PMIC_CMD_SW_LOCK_DATA ((uint8_t)0xAAU) +#define PMIC_CMD_WR_WD_WIN1_CFG ((uint8_t)0xEDU) +#define PMIC_CMD_WR_WD_WIN2_CFG ((uint8_t)0x09U) +#define PMIC_CMD_WR_WD_QUESTION_FDBCK ((uint8_t)0x77U) +#define PMIC_CMD_WR_WD_ANSWER ((uint8_t)0xE1U) +#define PMIC_CMD_WR_SAFETY_ERR_STAT_1 ((uint8_t)0xA9U) +#define PMIC_CMD_WR_SAFETY_CHECK_CTRL ((uint8_t)0x93U) +#define PMIC_CMD_WR_SAFETY_FUNC_CFG ((uint8_t)0x35U) +#define PMIC_CMD_RD_DEV_ID ((uint8_t)0x06U) +#define PMIC_CMD_RD_DEV_REV ((uint8_t)0x0CU) +#define PMIC_CMD_RD_DEV_STAT ((uint8_t)0x11U) +#define PMIC_CMD_RD_SAM_STAT ((uint8_t)0x31U) +#define PMIC_CMD_RD_SAM_SIG_STAT ((uint8_t)0xB9U) +#define PMIC_CMD_RD_VMON_STAT_1 ((uint8_t)0x12U) +#define PMIC_CMD_RD_VMON_STAT_2 ((uint8_t)0xA6U) +#define PMIC_CMD_RD_VMON_STAT_3 ((uint8_t)0xDAU) +#define PMIC_CMD_RD_SAFETY_STAT_1 ((uint8_t)0x24U) +#define PMIC_CMD_RD_SAFETY_STAT_2 ((uint8_t)0x4AU) +#define PMIC_CMD_RD_SAFETY_STAT_3 ((uint8_t)0xA3U) +#define PMIC_CMD_RD_SAFETY_STAT_4 ((uint8_t)0xA5U) +#define PMIC_CMD_RD_SAFETY_STAT_5 ((uint8_t)0xC0U) +#define PMIC_CMD_RD_SAFETY_ERR_STAT_1 ((uint8_t)0xAAU) +#define PMIC_CMD_RD_SAFETY_ERR_STAT_2 ((uint8_t)0x4AU) +#define PMIC_CMD_RD_SPI_INV_TRAN_STAT ((uint8_t)0xB3U) +#define PMIC_CMD_RD_SAFETY_ERR_CFG_1 ((uint8_t)0x30U) +#define PMIC_CMD_RD_SAFETY_ERR_CFG_2 ((uint8_t)0xE9U) +#define PMIC_CMD_RD_SAFETY_CHECK_CTRL ((uint8_t)0x44U) +#define PMIC_CMD_RD_SAFETY_FUNC_CFG ((uint8_t)0x3AU) +#define PMIC_CMD_RD_WD_QUESTION_FDBCK ((uint8_t)0x78U) +#define PMIC_CMD_RD_WD_QUESTION ((uint8_t)0x36U) +#define PMIC_CMD_RD_WD_STATUS ((uint8_t)0x4EU) +#define PMIC_CMD_RD_WD_WIN1_CFG ((uint8_t)0x2EU) +#define PMIC_CMD_RD_WD_WIN2_CFG ((uint8_t)0x05U) +/** @} */ + +/** + * @anchor Pmic_invalidData + * @name TPS65385xx PMIC Invalid Data + * + * @brief Used in Pmic_ioTransfer() and Pmic_ioTransfer_CS() to indicate invalid + * write/read data. + * @{ + */ +#define PMIC_NO_WRITE_DATA ((uint8_t)0U) +#define PMIC_NO_READ_DATA (NULL) +/** @} */ + +/* ========================================================================== */ +/* Function Declarations */ +/* ========================================================================== */ + +/** + * @brief Transfer serial data (i.e., conduct a write and/or read). End-users could + * use this API for direct register access. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @param cmd [IN] PMIC command. For valid values, refer to \ref Pmic_CommandCodes. + * + * @param wData [IN] Write data. If \p cmd is a read command, the appropriate macro + * defined under \ref Pmic_invalidData can be passed as input to this parameter. + * Otherwise, the value of \p wData is ignored by the PMIC. + * + * @param rData [OUT] Read data. If \p cmd is a write command, the appropriate macro + * defined under \ref Pmic_invalidData can be passed as input to this parameter. + * Otherwise, the dereferenced value of \p rData is set to zero by the PMIC. + * + * @return Success code if the SPI transfer is complete, error code otherwise. + * For valid success/error codes, refer to \ref Pmic_errorCodes. + */ +int32_t Pmic_ioTransfer(const Pmic_CoreHandle_t *pmicHandle, uint8_t cmd, uint8_t wData, uint8_t *rData); + +/** + * @brief Write a single byte to the PMIC. End-users could use this API for + * direct register access. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @param cmd [IN] PMIC command. For valid values, refer to \ref Pmic_CommandCodes. + * + * @param wData [IN] Data to be written to the PMIC. + * + * @return Success code if the SPI write is complete, error code otherwise. + * For valid success/error codes, refer to \ref Pmic_errorCodes. + */ +static inline int32_t Pmic_ioTxByte(const Pmic_CoreHandle_t *pmicHandle, uint8_t cmd, uint8_t wData) +{ + return Pmic_ioTransfer(pmicHandle, cmd, wData, PMIC_NO_READ_DATA); +} + +/** + * @brief Read a single byte from the PMIC. End-users could use this API for + * direct register access. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @param cmd [IN] PMIC command. For valid values, refer to \ref Pmic_CommandCodes. + * + * @param rData [OUT] Data received from the PMIC. + * + * @return Success code if the SPI read is complete, error code otherwise. + * For valid success/error codes, refer to \ref Pmic_errorCodes. + */ +static inline int32_t Pmic_ioRxByte(const Pmic_CoreHandle_t *pmicHandle, uint8_t cmd, uint8_t *rData) +{ + return Pmic_ioTransfer(pmicHandle, cmd, PMIC_NO_WRITE_DATA, rData); +} + +/** + * @brief Identical to Pmic_ioTransfer(), however, a critical section is started + * before the I/O transaction operation occurs. After the operation, the + * critical section is stopped. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @param cmd [IN] PMIC command. For valid values, refer to \ref Pmic_CommandCodes. + * + * @param wData [IN] Write data. If \p cmd is a read command, the appropriate macro + * defined under \ref Pmic_invalidData can be passed as input to this parameter. + * Otherwise, the value of \p wData is ignored by the PMIC. + * + * @param rData [OUT] Read data. If \p cmd is a write command, the appropriate macro + * defined under \ref Pmic_invalidData can be passed as input to this parameter. + * Otherwise, the dereferenced value of \p rData is set to zero by the PMIC. + * + * @return Success code if the SPI transfer is complete, error code otherwise. + * For valid success/error codes, refer to \ref Pmic_errorCodes. + */ +int32_t Pmic_ioTransfer_CS(const Pmic_CoreHandle_t *pmicHandle, uint8_t cmd, uint8_t wData, uint8_t *rData); + +/** + * @brief Identical to Pmic_ioTxByte(), however, a critical section is started + * before the I/O operation occurs. After the operation, the critical section + * is stopped. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @param cmd [IN] PMIC command. For valid values, refer to \ref Pmic_CommandCodes. + * + * @param wData [IN] Data to be written to the PMIC. + * + * @return Success code if the SPI write is complete, error code otherwise. + * For valid success/error codes, refer to \ref Pmic_errorCodes. + */ +int32_t Pmic_ioTxByte_CS(const Pmic_CoreHandle_t *pmicHandle, uint8_t cmd, uint8_t wData); + +/** + * @brief Identical to Pmic_ioRxByte(), however, a critical section is started + * before the I/O operation occurs. After the operation, the critical section + * is stopped. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @param cmd [IN] PMIC command. For valid values, refer to \ref Pmic_CommandCodes. + * + * @param rData [OUT] Data received from the PMIC. + * + * @return Success code if the SPI read is complete, error code otherwise. + * For valid success/error codes, refer to \ref Pmic_errorCodes. + */ +int32_t Pmic_ioRxByte_CS(const Pmic_CoreHandle_t *pmicHandle, uint8_t cmd, uint8_t *rData); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* PMIC_IO_H */ diff --git a/include/pmic_irq.h b/include/pmic_irq.h new file mode 100644 index 0000000..bc6292d --- /dev/null +++ b/include/pmic_irq.h @@ -0,0 +1,246 @@ +/****************************************************************************** + * Copyright (c) 2024 Texas Instruments Incorporated - http://www.ti.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/** + * @file pmic_irq.h + * + * @brief PMIC LLD IRQ module header file. + * + * @details This module contains declarations/definitions of macros, data + * structures, and APIs used to interact with PMIC interrupt requests (IRQs). + */ +#ifndef __PMIC_IRQ_H__ +#define __PMIC_IRQ_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* Include Files */ +/* ========================================================================== */ +#include "pmic_common.h" + +/* ========================================================================== */ +/* Macros & Typedefs */ +/* ========================================================================== */ + +/** + * @anchor Pmic_IRQs + * @name TPS65385x Interrupt Requests + * + * @brief Definitions of the PMIC statuses that can be indicated in each PMIC + * response within the status byte during an I/O transfer. Passed as input into + * IRQ APIs to accomplish various tasks such as getting IRQ statuses and + * clearing IRQ flags. + * + * @attention All statuses listed are nonmaskable. + * + * @{ + */ +#define PMIC_IRQ_VBATL_OV ((uint8_t)0U) +#define PMIC_IRQ_VBATL_UV ((uint8_t)1U) +#define PMIC_IRQ_VCP_UV ((uint8_t)2U) +#define PMIC_IRQ_VDD6_OV ((uint8_t)3U) +#define PMIC_IRQ_VDD6_UV ((uint8_t)4U) +#define PMIC_IRQ_VDD5_OV ((uint8_t)5U) +#define PMIC_IRQ_VDD5_UV ((uint8_t)6U) +#define PMIC_IRQ_VDD_3P5_OV ((uint8_t)7U) +#define PMIC_IRQ_VDD_3P5_UV ((uint8_t)8U) +#define PMIC_IRQ_VREG_UV ((uint8_t)9U) +#define PMIC_IRQ_VDD6_LP_UV ((uint8_t)10U) +#define PMIC_IRQ_VSOUT2_OV ((uint8_t)11U) +#define PMIC_IRQ_VSOUT2_UV ((uint8_t)12U) +#define PMIC_IRQ_VSOUT1_OV ((uint8_t)13U) +#define PMIC_IRQ_VSOUT1_UV ((uint8_t)14U) +#define PMIC_IRQ_VDD6_OT_FLAG ((uint8_t)15U) +#define PMIC_IRQ_VDD6_TP ((uint8_t)16U) +#define PMIC_IRQ_VDD5_ILIM ((uint8_t)17U) +#define PMIC_IRQ_VDD5_OT_FLAG ((uint8_t)18U) +#define PMIC_IRQ_VDD5_TP ((uint8_t)19U) +#define PMIC_IRQ_VDD_3P5_ILIM ((uint8_t)20U) +#define PMIC_IRQ_VDD_3P5_OT_FLAG ((uint8_t)21U) +#define PMIC_IRQ_VDD_3P5_TP ((uint8_t)22U) +#define PMIC_IRQ_VDD6_ILIM ((uint8_t)23U) +#define PMIC_IRQ_VSOUT2_ILIM ((uint8_t)24U) +#define PMIC_IRQ_VSOUT2_OT_FLAG ((uint8_t)25U) +#define PMIC_IRQ_VSOUT2_TP ((uint8_t)26U) +#define PMIC_IRQ_VSOUT1_ILIM ((uint8_t)27U) +#define PMIC_IRQ_VSOUT1_OT_FLAG ((uint8_t)28U) +#define PMIC_IRQ_VSOUT1_TP ((uint8_t)29U) +#define PMIC_IRQ_CFG_CRC_ERR ((uint8_t)30U) +#define PMIC_IRQ_EE_CRC_ERR ((uint8_t)31U) +#define PMIC_IRQ_NRES_ERR ((uint8_t)32U) +#define PMIC_IRQ_LBIST_ERR ((uint8_t)33U) +#define PMIC_IRQ_ABIST_ERR ((uint8_t)34U) +#define PMIC_IRQ_SPI_CMD_ERR ((uint8_t)35U) +#define PMIC_IRQ_SPI_FORMAT_ERR ((uint8_t)36U) +#define PMIC_IRQ_SPI_DATA_OUTPUT_MISMATCH ((uint8_t)37U) +#define PMIC_IRQ_LO_LPMCLK ((uint8_t)38U) +#define PMIC_IRQ_ENDRV_ERR ((uint8_t)39U) +#define PMIC_IRQ_TRIM_ERR_VMON ((uint8_t)40U) +#define PMIC_IRQ_INVALID_CMD ((uint8_t)41U) +#define PMIC_IRQ_UNDEF_CMD ((uint8_t)42U) +#define PMIC_IRQ_CRC_ERR ((uint8_t)43U) +#define PMIC_IRQ_LONG_FRM ((uint8_t)44U) +#define PMIC_IRQ_SHORT_FRM ((uint8_t)45U) +#define PMIC_IRQ_ERROR_PIN_FAIL ((uint8_t)46U) +#define PMIC_IRQ_WD_FAIL ((uint8_t)47U) +#define PMIC_IRQ_DIAG_STATE_TO ((uint8_t)48U) +#define PMIC_IRQ_SAM_BIST_FAIL ((uint8_t)49U) +#define PMIC_IRQ_POWER_ON_RESET ((uint8_t)50U) +#define PMIC_IRQ_SAM_CNT_ERR ((uint8_t)51U) +#define PMIC_IRQ_COS_P_OV ((uint8_t)52U) +#define PMIC_IRQ_COS_P_UV ((uint8_t)53U) +#define PMIC_IRQ_COS_N_OV ((uint8_t)54U) +#define PMIC_IRQ_COS_N_UV ((uint8_t)55U) +#define PMIC_IRQ_SIN_P_OV ((uint8_t)56U) +#define PMIC_IRQ_SIN_P_UV ((uint8_t)57U) +#define PMIC_IRQ_SIN_N_OV ((uint8_t)58U) +#define PMIC_IRQ_SIN_N_UV ((uint8_t)59U) +#define PMIC_IRQ_MAX (PMIC_IRQ_SIN_N_UV) +#define PMIC_IRQ_NUM (PMIC_IRQ_MAX + 1U) +/** @} */ + +/** + * @brief Defines used internally by PMIC LLD for the IRQ module. + * + * @{ + */ +#define PMIC_NUM_ELEM_IN_INTR_STAT ((uint8_t)2U) +#define PMIC_NUM_BITS_IN_INTR_STAT ((uint8_t)32U) +/** @} */ + +/* ========================================================================== */ +/* Structures and Enums */ +/* ========================================================================== */ + +/** + * @anchor Pmic_IrqStat + * @name PMIC IRQ Status Struct + * + * @brief Struct used to hold the status of all PMIC IRQs. + * + * @param intrStat For each element in this array, an individual bit represents + * whether a PMIC IRQ is set. For instance, Bit 0 of element 0 is the 1st PMIC + * IRQ status, bit 0 of element 1 is the 32nd PMIC IRQ status. + */ +typedef struct Pmic_IrqStat_s +{ + uint32_t intrStat[PMIC_NUM_ELEM_IN_INTR_STAT]; +} Pmic_IrqStat_t; + +/* ========================================================================== */ +/* Function Declarations */ +/* ========================================================================== */ + +/** + * @brief Get the status of all PMIC IRQs. + * + * @attention End-user must call this API first before calling `Pmic_irqGetNextFlag()`. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @param irqStat [OUT] Status of all PMIC IRQs. + * + * @return Success code if all PMIC IRQ statuses have been obtained, error code + * otherwise. For valid success/error codes, refer to @ref Pmic_errorCodes. + */ +int32_t Pmic_irqGetStat(const Pmic_CoreHandle_t *pmicHandle, Pmic_IrqStat_t *irqStat); + +/** + * @brief Get the next PMIC IRQ that has its flag set (status bit set to 1). + * + * @attention End-user must call `Pmic_irqGetStat()` first to get all PMIC IRQ + * statuses. Once the IRQ statuses have been obtained, it is passed as input to + * this API so that the next IRQ flag can be discovered. Once the next flag is + * found, end-user can call `Pmic_irqClrFlag()` to clear the flag. + * + * @param irqStat [IN/OUT] Status of all PMIC IRQs. Once the next IRQ flag has + * been found, the corresponding status bit in struct member `intrStat` will be + * cleared. + * + * @param irqNum [OUT] The next IRQ that has its flag set. For valid values, + * refer to @ref Pmic_IRQs. + * + * @return Success code if the next IRQ that has its flag set has been obtained, + * error code otherwise. For valid success/error codes, refer to @ref Pmic_errorCodes. + */ +int32_t Pmic_irqGetNextFlag(Pmic_IrqStat_t *irqStat, uint8_t *irqNum); + +/** + * @brief Get the flag status of a specific IRQ. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @param irqNum [IN] Target PMIC IRQ. For valid values, refer to @ref Pmic_IRQs. + * + * @param flag [OUT] Status flag of the target PMIC IRQ. This parameter returned + * as true indicates that the target IRQ's status flag is set to 1. Otherwise, + * the target IRQ's status flag is set to 0. + * + * @return Success code if the PMIC IRQ flag has been obtained, error code + * otherwise. For valid success/error codes, refer to @ref Pmic_errorCodes. + */ +int32_t Pmic_irqGetFlag(const Pmic_CoreHandle_t *pmicHandle, uint8_t irqNum, bool *flag); + +/** + * @brief Clear a specific PMIC IRQ flag. + * + * @attention This API is meant to be called after getting the next flag status from + * `Pmic_irqGetNextFlag()` or getting a specific flag status from `Pmic_irqGetFlag()`. + * + * @param pmicHandle [IN] PMIC interface handle. + * + * @param irqNum [IN] Target PMIC IRQ to clear. For valid values, refer to + * @ref Pmic_IRQs. + * + * @return Success code if the PMIC IRQ flag has been cleared, error code + * otherwise. For valid success/error codes, refer to @ref Pmic_errorCodes. + */ +int32_t Pmic_irqClrFlag(const Pmic_CoreHandle_t *pmicHandle, uint8_t irqNum); + +/** + * @brief Clear all PMIC IRQ flags. + * + * @param handle [IN] PMIC interface handle. + * + * @return Success code if all PMIC IRQ flags have been cleared, error code + * otherwise. For valid success/error codes, refer to @ref Pmic_errorCodes. + */ +int32_t Pmic_irqClrAllFlags(const Pmic_CoreHandle_t *handle); + +#ifdef __cplusplus +} + +#endif /* __cplusplus */ +#endif /* __PMIC_IRQ_H__ */ diff --git a/include/regmap/core.h b/include/regmap/core.h new file mode 100644 index 0000000..e47c6ce --- /dev/null +++ b/include/regmap/core.h @@ -0,0 +1,108 @@ +/****************************************************************************** + * Copyright (c) 2024 Texas Instruments Incorporated - http://www.ti.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/** + * @file core.h + * + * @brief PMIC LLD register bit fields pertaining to the Core module. + */ +#ifndef __CORE_H__ +#define __CORE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* Include Files */ +/* ========================================================================== */ +#include "pmic_common.h" + +/* ========================================================================== */ +/* Macros & Typedefs */ +/* ========================================================================== */ + +// SAFETY_ERR_CFG_1 register bit field shifts and masks. +#define SAFE_TO_SHIFT ((uint8_t)5U) +#define SAFE_TO_MASK ((uint8_t)7U << SAFE_TO_SHIFT) +#define SAFE_LOCK_THR_SHIFT ((uint8_t)1U) +#define SAFE_LOCK_THR_MASK ((uint8_t)0xFU << SAFE_LOCK_THR_SHIFT) +#define CFG_LOCK_SHIFT ((uint8_t)0U) +#define CFG_LOCK_MASK ((uint8_t)1U << CFG_LOCK_SHIFT) + +// SAFETY_ERR_CFG_2 register bit field shifts and masks. +#define MCU_ERR_CNT_TH_SHIFT ((uint8_t)0U) +#define MCU_ERR_CNT_TH_MASK ((uint8_t)7U << MCU_ERR_CNT_TH_SHIFT) + +// SAFETY_BIST_CTRL register bit field shifts and masks. +#define AUTO_BIST_DIS_SHIFT ((uint8_t)5U) +#define AUTO_BIST_DIS_MASK ((uint8_t)1U << AUTO_BIST_DIS_SHIFT) +#define EE_CRC_CHK_SHIFT ((uint8_t)4U) +#define EE_CRC_CHK_MASK ((uint8_t)1U << EE_CRC_CHK_SHIFT) +#define LBIST_EN_SHIFT ((uint8_t)2U) +#define LBIST_EN_MASK ((uint8_t)1U << LBIST_EN_SHIFT) +#define ABIST_EN_SHIFT ((uint8_t)1U) +#define ABIST_EN_MASK ((uint8_t)1U << ABIST_EN_SHIFT) + +// SAFETY_CHECK_CTRL register bit field shifts and masks. +#define CFG_CRC_EN_SHIFT ((uint8_t)7U) +#define CFG_CRC_EN_MASK ((uint8_t)1U << CFG_CRC_EN_SHIFT) +#define ENABLE_DRV_SHIFT ((uint8_t)5U) +#define ENABLE_DRV_MASK ((uint8_t)1U << ENABLE_DRV_SHIFT) +#define NO_ERROR_SHIFT ((uint8_t)2U) +#define NO_ERROR_MASK ((uint8_t)1U << NO_ERROR_SHIFT) +#define DIAG_EXIT_MASK_SHIFT ((uint8_t)1U) +#define DIAG_EXIT_MASK_MASK ((uint8_t)1U << DIAG_EXIT_MASK_SHIFT) +#define DIAG_EXIT_SHIFT ((uint8_t)0U) +#define DIAG_EXIT_MASK ((uint8_t)1U << DIAG_EXIT_SHIFT) + +// SAFETY_FUNC_CFG register bit field shifts and masks. +#define SAFE_LOCK_TO_DIS_SHIFT ((uint8_t)7U) +#define SAFE_LOCK_TO_DIS_MASK ((uint8_t)1U << SAFE_LOCK_TO_DIS_SHIFT) +#define ESM_CFG_SHIFT ((uint8_t)6U) +#define ESM_CFG_MASK ((uint8_t)1U << ESM_CFG_SHIFT) +#define WD_CFG_SHIFT ((uint8_t)5U) +#define WD_CFG_MASK ((uint8_t)1U << WD_CFG_SHIFT) +#define WD_RST_EN_SHIFT ((uint8_t)3U) +#define WD_RST_EN_MASK ((uint8_t)1U << WD_RST_EN_SHIFT) +#define DIS_NRES_MON_SHIFT ((uint8_t)2U) +#define DIS_NRES_MON_MASK ((uint8_t)1U << DIS_NRES_MON_SHIFT) +#define LOCK_STEP_RST_EN_SHIFT ((uint8_t)1U) +#define LOCK_STEP_RST_EN_MASK ((uint8_t)1U << LOCK_STEP_RST_EN_SHIFT) +#define WARM_RST_CFG_SHIFT ((uint8_t)0U) +#define WARM_RST_CFG_MASK ((uint8_t)1U << WARM_RST_CFG_SHIFT) + +#ifdef __cplusplus +} + +#endif /* __cplusplus */ +#endif /* __CORE_H__ */ diff --git a/include/regmap/irq.h b/include/regmap/irq.h new file mode 100644 index 0000000..f7c0aba --- /dev/null +++ b/include/regmap/irq.h @@ -0,0 +1,224 @@ +/****************************************************************************** + * Copyright (c) 2024 Texas Instruments Incorporated - http://www.ti.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/** + * @file irq.h + * + * @brief PMIC LLD register bit fields pertaining to the IRQ module. + */ +#ifndef __IRQ_H__ +#define __IRQ_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* Include Files */ +/* ========================================================================== */ +#include "pmic_common.h" + +/* ========================================================================== */ +/* Macros & Typedefs */ +/* ========================================================================== */ + +// SAFETY_STAT_1 register bit field shifts and masks. +#define VDD6_OT_FLAG_SHIFT ((uint8_t)7U) +#define VDD6_OT_FLAG_MASK ((uint8_t)(1U << VDD6_OT_FLAG_SHIFT)) +#define VDD6_TP_SHIFT ((uint8_t)6U) +#define VDD6_TP_MASK ((uint8_t)(1U << VDD6_TP_SHIFT)) +#define VDD5_ILIM_SHIFT ((uint8_t)5U) +#define VDD5_ILIM_MASK ((uint8_t)(1U << VDD5_ILIM_SHIFT)) +#define VDD5_OT_FLAG_SHIFT ((uint8_t)4U) +#define VDD5_OT_FLAG_MASK ((uint8_t)(1U << VDD5_OT_FLAG_SHIFT)) +#define VDD5_TP_SHIFT ((uint8_t)3U) +#define VDD5_TP_MASK ((uint8_t)(1U << VDD5_TP_SHIFT)) +#define VDD_3P5_ILIM_SHIFT ((uint8_t)2U) +#define VDD_3P5_ILIM_MASK ((uint8_t)(1U << VDD_3P5_ILIM_SHIFT)) +#define VDD_3P5_OT_FLAG_SHIFT ((uint8_t)1U) +#define VDD_3P5_OT_FLAG_MASK ((uint8_t)(1U << VDD_3P5_OT_FLAG_SHIFT)) +#define VDD_3P5_TP_SHIFT ((uint8_t)0U) +#define VDD_3P5_TP_MASK ((uint8_t)(1U << VDD_3P5_TP_SHIFT)) + +// SAFETY_STAT_2 register bit field shifts and masks. +#define VDD6_ILIM_SHIFT ((uint8_t)6U) +#define VDD6_ILIM_MASK ((uint8_t)(1U << VDD6_ILIM_SHIFT)) +#define VSOUT2_ILIM_SHIFT ((uint8_t)5U) +#define VSOUT2_ILIM_MASK ((uint8_t)(1U << VSOUT2_ILIM_SHIFT)) +#define VSOUT2_OT_FLAG_SHIFT ((uint8_t)4U) +#define VSOUT2_OT_FLAG_MASK ((uint8_t)(1U << VSOUT2_OT_FLAG_SHIFT)) +#define VSOUT2_TP_SHIFT ((uint8_t)3U) +#define VSOUT2_TP_MASK ((uint8_t)(1U << VSOUT2_TP_SHIFT)) +#define VSOUT1_ILIM_SHIFT ((uint8_t)2U) +#define VSOUT1_ILIM_MASK ((uint8_t)(1U << VSOUT1_ILIM_SHIFT)) +#define VSOUT1_OT_FLAG_SHIFT ((uint8_t)1U) +#define VSOUT1_OT_FLAG_MASK ((uint8_t)(1U << VSOUT1_OT_FLAG_SHIFT)) +#define VSOUT1_TP_SHIFT ((uint8_t)0U) +#define VSOUT1_TP_MASK ((uint8_t)(1U << VSOUT1_TP_SHIFT)) + +// SAFETY_STAT_3 register bit field shifts and masks. +#define CFG_CRC_ERR_SHIFT ((uint8_t)6U) +#define CFG_CRC_ERR_MASK ((uint8_t)(1U << CFG_CRC_ERR_SHIFT)) +#define EE_CRC_ERR_SHIFT ((uint8_t)5U) +#define EE_CRC_ERR_MASK ((uint8_t)(1U << EE_CRC_ERR_SHIFT)) +#define NRES_ERR_SHIFT ((uint8_t)4U) +#define NRES_ERR_MASK ((uint8_t)(1U << NRES_ERR_SHIFT)) +#define LBIST_ERR_SHIFT ((uint8_t)3U) +#define LBIST_ERR_MASK ((uint8_t)(1U << LBIST_ERR_SHIFT)) +#define ABIST_ERR_SHIFT ((uint8_t)2U) +#define ABIST_ERR_MASK ((uint8_t)(1U << ABIST_ERR_SHIFT)) +#define LBIST_DONE_SHIFT ((uint8_t)1U) +#define LBIST_DONE_MASK ((uint8_t)(1U << LBIST_DONE_SHIFT)) +#define ABIST_DONE_SHIFT ((uint8_t)0U) +#define ABIST_DONE_MASK ((uint8_t)(1U << ABIST_DONE_SHIFT)) + +// SAFETY_STAT_4 register bit field shifts and masks. +#define SPI_ERR_SHIFT ((uint8_t)6U) +#define SPI_ERR_MASK ((uint8_t)(3U << SPI_ERR_SHIFT)) +#define LO_LPMCLK_SHIFT ((uint8_t)5U) +#define LO_LPMCLK_MASK ((uint8_t)(1U << LO_LPMCLK_SHIFT)) +#define ENDRV_ERR_SHIFT ((uint8_t)1U) +#define ENDRV_ERR_MASK ((uint8_t)(1U <validParams, PMIC_COMM_HANDLE_VALID)) + { + if (pmicCfg->commHandle != NULL) + { + pmicHandle->commHandle = pmicCfg->commHandle; + } + else + { + status = PMIC_ST_ERR_NULL_PARAM; + } + } + + if (Pmic_validParamCheck(pmicCfg->validParams, PMIC_IO_TRANSFER_VALID)) + { + if (pmicCfg->ioTransfer != NULL) + { + pmicHandle->ioTransfer = pmicCfg->ioTransfer; + } + else + { + status = PMIC_ST_ERR_NULL_PARAM; + } + } + + if (Pmic_validParamCheck(pmicCfg->validParams, PMIC_IRQ_RESPONSE_VALID)) + { + if (pmicCfg->irqResponse != NULL) + { + pmicHandle->irqResponse = pmicCfg->irqResponse; + } + else + { + status = PMIC_ST_ERR_NULL_PARAM; + } + } + + return status; +} + +static inline int32_t setPmicSysHandleMembers(const Pmic_CoreCfg_t *pmicCfg, Pmic_CoreHandle_t *pmicHandle) +{ + int32_t status = PMIC_ST_SUCCESS; + + if (Pmic_validParamCheck(pmicCfg->validParams, PMIC_CRIT_SEC_START_VALID)) + { + if (pmicCfg->critSecStart != NULL) + { + pmicHandle->critSecStart = pmicCfg->critSecStart; + } + else + { + status = PMIC_ST_ERR_NULL_PARAM; + } + } + + if (Pmic_validParamCheck(pmicCfg->validParams, PMIC_CRIT_SEC_STOP_VALID)) + { + if (pmicCfg->critSecStop != NULL) + { + pmicHandle->critSecStop = pmicCfg->critSecStop; + } + else + { + status = PMIC_ST_ERR_NULL_PARAM; + } + } + + return status; +} + +static int32_t getPmicInfo(Pmic_CoreHandle_t *pmicHandle) +{ + uint8_t regData = 0U; + int32_t status = PMIC_ST_SUCCESS; + + if (status == PMIC_ST_SUCCESS) + { + // Read DEV_ID register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_DEV_ID, ®Data); + } + + if (status == PMIC_ST_SUCCESS) + { + // Extract DEV_ID bit field (the entire register is the bit field) + pmicHandle->devId = regData; + + // Read DEV_REV register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_DEV_REV, ®Data); + } + + if (status == PMIC_ST_SUCCESS) + { + // Extract DEV_REV bit field (the entire register is the bit field) + pmicHandle->devRev = regData; + } + + return status; +} + +int32_t Pmic_init(const Pmic_CoreCfg_t *pmicCfg, Pmic_CoreHandle_t *pmicHandle) +{ + int32_t status = PMIC_ST_SUCCESS; + + // Check whether parameters are valid + if ((pmicHandle == NULL) || (pmicCfg == NULL)) + { + status = PMIC_ST_ERR_NULL_PARAM; + } + + if ((status == PMIC_ST_SUCCESS) && (pmicCfg->validParams == 0U)) + { + status = PMIC_ST_ERR_INV_PARAM; + } + + // Initialize PMIC handle with values from pmicCfg + if (status == PMIC_ST_SUCCESS) + { + setPmicCommsHandleMembers(pmicCfg, pmicHandle); + } + + if (status == PMIC_ST_SUCCESS) + { + setPmicSysHandleMembers(pmicCfg, pmicHandle); + } + + // Initialize PMIC command lookup table and obtain information about the PMIC + if (status == PMIC_ST_SUCCESS) + { + status = getPmicInfo(pmicHandle); + } + + // Set the driver initialization status + if (status == PMIC_ST_SUCCESS) + { + pmicHandle->drvInitStat = PMIC_DRV_INIT; + } + + return status; +} + +int32_t Pmic_deinit(Pmic_CoreHandle_t *pmicHandle) +{ + int32_t status = PMIC_ST_SUCCESS; + + if (pmicHandle == NULL) + { + status = PMIC_ST_ERR_NULL_PARAM; + } + + if (status == PMIC_ST_SUCCESS) + { + pmicHandle->drvInitStat = PMIC_DRV_UNINIT; + pmicHandle->devRev = 0U; + pmicHandle->devId = 0U; + pmicHandle->commHandle = NULL; + pmicHandle->ioTransfer = NULL; + pmicHandle->critSecStart = NULL; + pmicHandle->critSecStop = NULL; + pmicHandle->irqResponse = NULL; + } + + return status; +} diff --git a/src/pmic_core.c b/src/pmic_core.c new file mode 100644 index 0000000..f503afa --- /dev/null +++ b/src/pmic_core.c @@ -0,0 +1,116 @@ +/****************************************************************************** + * Copyright (c) 2024 Texas Instruments Incorporated - http://www.ti.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/** + * @file pmic_core.c + * + * @brief This file contains definitions to APIs that interact with the PMIC Core. + */ +#include "pmic.h" +#include "pmic_io.h" +#include "pmic_core.h" + +#include "regmap/core.h" + +int32_t Pmic_checkPmicCoreHandle(const Pmic_CoreHandle_t *pmicHandle) +{ + int32_t status = PMIC_ST_SUCCESS; + const bool invalidHandleConditions = ( + (pmicHandle->ioTransfer == NULL) || + (pmicHandle->drvInitStat != PMIC_DRV_INIT)); + + if (pmicHandle == NULL) + { + status = PMIC_ST_ERR_NULL_PARAM; + } + + if ((status == PMIC_ST_SUCCESS) && invalidHandleConditions) + { + status = PMIC_ST_ERR_INV_HANDLE; + } + + return status; +} + +int32_t Pmic_setRegLock(const Pmic_CoreHandle_t *pmicHandle, bool lock) +{ + int32_t status = Pmic_checkPmicCoreHandle(pmicHandle); + + if (status == PMIC_ST_SUCCESS) + { + if (lock) + { + status = Pmic_ioTxByte_CS(pmicHandle, PMIC_CMD_SW_LOCK, PMIC_CMD_SW_LOCK_DATA); + } + else + { + status = Pmic_ioTxByte_CS(pmicHandle, PMIC_CMD_SW_UNLOCK, PMIC_CMD_SW_UNLOCK_DATA); + } + } + + return status; +} + +int32_t Pmic_unlockRegs(const Pmic_CoreHandle_t *pmicHandle) +{ + return Pmic_setRegLock(pmicHandle, PMIC_UNLOCK); +} + +int32_t Pmic_lockRegs(const Pmic_CoreHandle_t *pmicHandle) +{ + return Pmic_setRegLock(pmicHandle, PMIC_LOCK); +} + +int32_t Pmic_getRegLock(const Pmic_CoreHandle_t *pmicHandle, bool *locked) +{ + uint8_t regData = 0U; + int32_t status = Pmic_checkPmicCoreHandle(pmicHandle); + + if ((status == PMIC_ST_SUCCESS) && (locked == NULL)) + { + status = PMIC_ST_ERR_NULL_PARAM; + } + + // Read SAFETY_ERR_CFG_1 register + if (status == PMIC_ST_SUCCESS) + { + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_SAFETY_ERR_CFG_1, ®Data); + } + + // Extract CFG_LOCK bit field + if (status == PMIC_ST_SUCCESS) + { + *locked = Pmic_getBitField_b(regData, CFG_LOCK_SHIFT); + } + + return status; +} diff --git a/src/pmic_io.c b/src/pmic_io.c new file mode 100644 index 0000000..a9b25d3 --- /dev/null +++ b/src/pmic_io.c @@ -0,0 +1,241 @@ +/****************************************************************************** + * Copyright (c) 2024 Texas Instruments Incorporated - http://www.ti.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/** + * @file pmic_io.c + * + * @brief PMIC I/O source file containing definitions to I/O related + * functionalities. + */ +#include "pmic.h" +#include "pmic_io.h" + +/** + * @brief Types of errors that can be indicated by the PMIC in its response + * during an I/O transaction. + */ +#define PMIC_STATUS_ERR ((uint8_t)1U << 7U) +#define PMIC_WDG_ERR ((uint8_t)1U << 6U) +#define PMIC_VMON_SAM_ERR ((uint8_t)1U << 5U) +#define PMIC_ESM_ERR ((uint8_t)1U << 3U) +#define PMIC_SDO_RDBK_ERR ((uint8_t)1U << 1U) +#define PMIC_PREV_SPI_FRAME_INV_ERR ((uint8_t)1U << 0U) + +/** + * @brief Bytes of a TPS65385XX SPI frame. + * + * @{ + */ +#define PMIC_M_CMD_BYTE ((uint8_t)0U) +#define PMIC_M_DATA_BYTE ((uint8_t)1U) +#define PMIC_M_MCRC_BYTE ((uint8_t)2U) +#define PMIC_S_STATUS_BYTE ((uint8_t)0U) +#define PMIC_S_RESPONSE_BYTE ((uint8_t)1U) +#define PMIC_S_SCRC_BYTE ((uint8_t)2U) +#define PMIC_NUM_BYTES_IN_SPI_FRAME ((uint8_t)3U) +/** @} */ + +// Number of bytes in a standard SPI transfer +#define SPI_BYTE_XFER_COUNT ((uint8_t)(3U)) + +/** + * Used CRC Polynomial: x^8 + x^2 + x + 1 + * Evalution of CRC Polynomial value from equation: + * 1*x^8 + 0*x^7 + 0*x^6 + 0*x^5 + 0*x^4 + 0*x^3 + 1*x^2 + 1*x + 1 + * = 1 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + * = 0x107(After discarding most significant bit) = 0x7 + * + * CRC Polynomial value: 0x07, Initial Value: 0x00, Final Value: 0x00 + * link to generate custom CRC table from polynomial: + * http://www.sunshine2k.de/coding/javascript/crc/crc_js.html + */ +static const uint8_t CRC_8_TABLE[] = +{ + 0x00U, 0x07U, 0x0eU, 0x09U, 0x1cU, 0x1bU, 0x12U, 0x15U, + 0x38U, 0x3fU, 0x36U, 0x31U, 0x24U, 0x23U, 0x2aU, 0x2dU, + 0x70U, 0x77U, 0x7eU, 0x79U, 0x6cU, 0x6bU, 0x62U, 0x65U, + 0x48U, 0x4fU, 0x46U, 0x41U, 0x54U, 0x53U, 0x5aU, 0x5dU, + 0xe0U, 0xe7U, 0xeeU, 0xe9U, 0xfcU, 0xfbU, 0xf2U, 0xf5U, + 0xd8U, 0xdfU, 0xd6U, 0xd1U, 0xc4U, 0xc3U, 0xcaU, 0xcdU, + 0x90U, 0x97U, 0x9eU, 0x99U, 0x8cU, 0x8bU, 0x82U, 0x85U, + 0xa8U, 0xafU, 0xa6U, 0xa1U, 0xb4U, 0xb3U, 0xbaU, 0xbdU, + 0xc7U, 0xc0U, 0xc9U, 0xceU, 0xdbU, 0xdcU, 0xd5U, 0xd2U, + 0xffU, 0xf8U, 0xf1U, 0xf6U, 0xe3U, 0xe4U, 0xedU, 0xeaU, + 0xb7U, 0xb0U, 0xb9U, 0xbeU, 0xabU, 0xacU, 0xa5U, 0xa2U, + 0x8fU, 0x88U, 0x81U, 0x86U, 0x93U, 0x94U, 0x9dU, 0x9aU, + 0x27U, 0x20U, 0x29U, 0x2eU, 0x3bU, 0x3cU, 0x35U, 0x32U, + 0x1fU, 0x18U, 0x11U, 0x16U, 0x03U, 0x04U, 0x0dU, 0x0aU, + 0x57U, 0x50U, 0x59U, 0x5eU, 0x4bU, 0x4cU, 0x45U, 0x42U, + 0x6fU, 0x68U, 0x61U, 0x66U, 0x73U, 0x74U, 0x7dU, 0x7aU, + 0x89U, 0x8eU, 0x87U, 0x80U, 0x95U, 0x92U, 0x9bU, 0x9cU, + 0xb1U, 0xb6U, 0xbfU, 0xb8U, 0xadU, 0xaaU, 0xa3U, 0xa4U, + 0xf9U, 0xfeU, 0xf7U, 0xf0U, 0xe5U, 0xe2U, 0xebU, 0xecU, + 0xc1U, 0xc6U, 0xcfU, 0xc8U, 0xddU, 0xdaU, 0xd3U, 0xd4U, + 0x69U, 0x6eU, 0x67U, 0x60U, 0x75U, 0x72U, 0x7bU, 0x7cU, + 0x51U, 0x56U, 0x5fU, 0x58U, 0x4dU, 0x4aU, 0x43U, 0x44U, + 0x19U, 0x1eU, 0x17U, 0x10U, 0x05U, 0x02U, 0x0bU, 0x0cU, + 0x21U, 0x26U, 0x2fU, 0x28U, 0x3dU, 0x3aU, 0x33U, 0x34U, + 0x4eU, 0x49U, 0x40U, 0x47U, 0x52U, 0x55U, 0x5cU, 0x5bU, + 0x76U, 0x71U, 0x78U, 0x7fU, 0x6aU, 0x6dU, 0x64U, 0x63U, + 0x3eU, 0x39U, 0x30U, 0x37U, 0x22U, 0x25U, 0x2cU, 0x2bU, + 0x06U, 0x01U, 0x08U, 0x0fU, 0x1aU, 0x1dU, 0x14U, 0x13U, + 0xaeU, 0xa9U, 0xa0U, 0xa7U, 0xb2U, 0xb5U, 0xbcU, 0xbbU, + 0x96U, 0x91U, 0x98U, 0x9fU, 0x8aU, 0x8dU, 0x84U, 0x83U, + 0xdeU, 0xd9U, 0xd0U, 0xd7U, 0xc2U, 0xc5U, 0xccU, 0xcbU, + 0xe6U, 0xe1U, 0xe8U, 0xefU, 0xfaU, 0xfdU, 0xf4U, 0xf3U +}; + +/** + * @brief API to Get CRC8 data. + */ +static uint8_t IO_getCRC8Val(const uint8_t *data, uint8_t length) +{ + uint8_t crc = 0xFFU; + + for (uint8_t i = 0U; i < length; i++) + { + crc = CRC_8_TABLE[data[i] ^ crc]; + } + + return crc; +} + +/** + * @brief Check the PMIC status for fault/error indication(s). + */ +static inline bool Pmic_ioStatusCheck(uint8_t pmicStatus) +{ + const uint8_t statusErrors = (PMIC_STATUS_ERR | PMIC_WDG_ERR | PMIC_VMON_SAM_ERR | + PMIC_ESM_ERR | PMIC_SDO_RDBK_ERR | PMIC_PREV_SPI_FRAME_INV_ERR); + + return ((bool)((pmicStatus & statusErrors) != 0U)); +} + +int32_t Pmic_ioTransfer(const Pmic_CoreHandle_t *pmicHandle, uint8_t cmd, uint8_t wData, uint8_t *rData) +{ + int32_t status = PMIC_ST_SUCCESS; + uint32_t spiTxBuf = 0U, spiRxBuf = 0xFFU; + uint8_t spiFrame[PMIC_NUM_BYTES_IN_SPI_FRAME] = {0U}; + + // Check parameters + if ((pmicHandle == NULL) || (pmicHandle->commHandle == NULL) || (pmicHandle->ioTransfer == NULL)) + { + status = PMIC_ST_ERR_NULL_PARAM; + } + + // Perform SPI transfer + if (status == PMIC_ST_SUCCESS) + { + spiFrame[PMIC_M_CMD_BYTE] = cmd; + spiFrame[PMIC_M_DATA_BYTE] = wData; + + // Get the CRC of the command and write data; form the transmit data. + // Bits 23-16: CMD, bits 15-8: data, bits 7-4: Reserved, bits 3-0: MCRC + spiFrame[PMIC_M_MCRC_BYTE] = IO_getCRC8Val(spiFrame, 2U); + spiTxBuf = (((uint32_t)spiFrame[PMIC_M_CMD_BYTE] << 16U) | + ((uint32_t)spiFrame[PMIC_M_DATA_BYTE] << 8U) | + ((uint32_t)spiFrame[PMIC_M_MCRC_BYTE] & 0xFU)); + + // SPI transfer + status = pmicHandle->ioTransfer(pmicHandle, &spiTxBuf, &spiRxBuf, SPI_BYTE_XFER_COUNT); + } + + // Convert platform specific error code to driver error code + if (status != PMIC_ST_SUCCESS) + { + status = PMIC_ST_ERR_SPI_COMM_FAIL; + } + + if (status == PMIC_ST_SUCCESS) + { + // Decompose received SPI frame + spiFrame[PMIC_S_STATUS_BYTE] = (spiRxBuf >> 16U) & 0xFFU; + spiFrame[PMIC_S_RESPONSE_BYTE] = (spiRxBuf >> 8U) & 0xFFU; + spiFrame[PMIC_S_SCRC_BYTE] = spiRxBuf & 0xFFU; + + // Compare SCRC against calculated CRC + if ((IO_getCRC8Val(spiFrame, 2U) & 0xFU) != (spiFrame[PMIC_S_SCRC_BYTE] & 0xFU)) + { + status = PMIC_ST_ERR_INV_CRC; + } + } + + if (status == PMIC_ST_SUCCESS) + { + // Check for PMIC faults/errors + if (Pmic_ioStatusCheck(spiFrame[PMIC_S_STATUS_BYTE])) + { + Pmic_irqResponse(pmicHandle); + } + + // Store PMIC response + if (rData != NULL) + { + *rData = spiFrame[PMIC_S_RESPONSE_BYTE]; + } + } + + return status; +} + +int32_t Pmic_ioTransfer_CS(const Pmic_CoreHandle_t *pmicHandle, uint8_t cmd, uint8_t wData, uint8_t *rData) +{ + int32_t status = PMIC_ST_SUCCESS; + + Pmic_criticalSectionStart(pmicHandle); + status = Pmic_ioTransfer(pmicHandle, cmd, wData, rData); + Pmic_criticalSectionStop(pmicHandle); + + return status; +} + +int32_t Pmic_ioTxByte_CS(const Pmic_CoreHandle_t *pmicHandle, uint8_t cmd, uint8_t wData) +{ + int32_t status = PMIC_ST_SUCCESS; + + Pmic_criticalSectionStart(pmicHandle); + status = Pmic_ioTxByte(pmicHandle, cmd, wData); + Pmic_criticalSectionStop(pmicHandle); + + return status; +} + +int32_t Pmic_ioRxByte_CS(const Pmic_CoreHandle_t *pmicHandle, uint8_t cmd, uint8_t *rData) +{ + int32_t status = PMIC_ST_SUCCESS; + + Pmic_criticalSectionStart(pmicHandle); + status = Pmic_ioRxByte(pmicHandle, cmd, rData); + Pmic_criticalSectionStop(pmicHandle); + + return status; +} diff --git a/src/pmic_irq.c b/src/pmic_irq.c new file mode 100644 index 0000000..9598c26 --- /dev/null +++ b/src/pmic_irq.c @@ -0,0 +1,631 @@ +/****************************************************************************** + * Copyright (c) 2024 Texas Instruments Incorporated - http://www.ti.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/** + * @file pmic_irq.c + * + * @brief PMIC LLD IRQ module source file containing definitions to APIs that + * interact with PMIC IRQs. + */ +#include "pmic.h" +#include "pmic_irq.h" +#include "pmic_io.h" + +#include "regmap/irq.h" + +#define NUM_CLEARABLE_REGISTERS ((uint8_t)12U) + +/** @brief SPI errors */ +#define PMIC_SPI_ERR_CMD ((uint8_t)1U) +#define PMIC_SPI_ERR_FORMAT ((uint8_t)2U) +#define PMIC_SPI_ERR_OUTPUT_MISMATCH ((uint8_t)3U) + +/** + * @anchor Pmic_IrqInfo + * @name PMIC IRQ Information Struct + * + * @brief This struct is used to hold information regarding an IRQ. + * + * @param regCmd Read command to access the register holding the IRQ status bit. + * @param bitShift Position of the IRQ status/mask bit. + */ +typedef struct Pmic_IrqInfo_s +{ + uint8_t regCmd; + uint8_t bitShift; +} Pmic_IrqInfo_t; + +static const uint8_t ClearableRegCmd[NUM_CLEARABLE_REGISTERS] = { + PMIC_CMD_RD_SAM_STAT, + PMIC_CMD_RD_SAM_SIG_STAT, + PMIC_CMD_RD_VMON_STAT_1, + PMIC_CMD_RD_VMON_STAT_2, + PMIC_CMD_RD_VMON_STAT_3, + PMIC_CMD_RD_SAFETY_STAT_1, + PMIC_CMD_RD_SAFETY_STAT_2, + PMIC_CMD_RD_SAFETY_STAT_3, + PMIC_CMD_RD_SAFETY_STAT_4, + PMIC_CMD_RD_SAFETY_ERR_STAT_1, + PMIC_CMD_RD_SAFETY_ERR_STAT_2, + PMIC_CMD_RD_SPI_INV_TRAN_STAT +}; + +/** + * @brief All IRQ statuses that affect the status byte of the PMIC response + * during an I/O transfer. + */ +static const Pmic_IrqInfo_t pmicIRQs[PMIC_IRQ_NUM] = { + {PMIC_CMD_RD_VMON_STAT_1, VBATL_OV_SHIFT}, // 0 + {PMIC_CMD_RD_VMON_STAT_1, VBATL_UV_SHIFT}, // 1 + {PMIC_CMD_RD_VMON_STAT_1, VCP_UV_SHIFT}, // 2 + {PMIC_CMD_RD_VMON_STAT_2, VDD6_OV_SHIFT}, // 3 + {PMIC_CMD_RD_VMON_STAT_2, VDD6_UV_SHIFT}, // 4 + {PMIC_CMD_RD_VMON_STAT_2, VDD5_OV_SHIFT}, // 5 + {PMIC_CMD_RD_VMON_STAT_2, VDD5_UV_SHIFT}, // 6 + {PMIC_CMD_RD_VMON_STAT_2, VDD_3P5_OV_SHIFT}, // 7 + {PMIC_CMD_RD_VMON_STAT_2, VDD_3P5_UV_SHIFT}, // 8 + {PMIC_CMD_RD_VMON_STAT_3, VREG_UV_SHIFT}, // 9 + {PMIC_CMD_RD_VMON_STAT_3, VDD6_LP_UV_SHIFT}, // 10 + {PMIC_CMD_RD_VMON_STAT_3, VSOUT2_OV_SHIFT}, // 11 + {PMIC_CMD_RD_VMON_STAT_3, VSOUT2_UV_SHIFT}, // 12 + {PMIC_CMD_RD_VMON_STAT_3, VSOUT1_OV_SHIFT}, // 13 + {PMIC_CMD_RD_VMON_STAT_3, VSOUT1_UV_SHIFT}, // 14 + {PMIC_CMD_RD_SAFETY_STAT_1, VDD6_OT_FLAG_SHIFT}, // 15 + {PMIC_CMD_RD_SAFETY_STAT_1, VDD6_TP_SHIFT}, // 16 + {PMIC_CMD_RD_SAFETY_STAT_1, VDD5_ILIM_SHIFT}, // 17 + {PMIC_CMD_RD_SAFETY_STAT_1, VDD5_OT_FLAG_SHIFT}, // 18 + {PMIC_CMD_RD_SAFETY_STAT_1, VDD5_TP_SHIFT}, // 19 + {PMIC_CMD_RD_SAFETY_STAT_1, VDD_3P5_ILIM_SHIFT}, // 20 + {PMIC_CMD_RD_SAFETY_STAT_1, VDD_3P5_OT_FLAG_SHIFT}, // 21 + {PMIC_CMD_RD_SAFETY_STAT_1, VDD_3P5_TP_SHIFT}, // 22 + {PMIC_CMD_RD_SAFETY_STAT_2, VDD6_ILIM_SHIFT}, // 23 + {PMIC_CMD_RD_SAFETY_STAT_2, VSOUT2_ILIM_SHIFT}, // 24 + {PMIC_CMD_RD_SAFETY_STAT_2, VSOUT2_OT_FLAG_SHIFT}, // 25 + {PMIC_CMD_RD_SAFETY_STAT_2, VSOUT2_TP_SHIFT}, // 26 + {PMIC_CMD_RD_SAFETY_STAT_2, VSOUT1_ILIM_SHIFT}, // 27 + {PMIC_CMD_RD_SAFETY_STAT_2, VSOUT1_OT_FLAG_SHIFT}, // 28 + {PMIC_CMD_RD_SAFETY_STAT_2, VSOUT1_TP_SHIFT}, // 29 + {PMIC_CMD_RD_SAFETY_STAT_3, CFG_CRC_ERR_SHIFT}, // 30 + {PMIC_CMD_RD_SAFETY_STAT_3, EE_CRC_ERR_SHIFT}, // 31 + {PMIC_CMD_RD_SAFETY_STAT_3, NRES_ERR_SHIFT}, // 32 + {PMIC_CMD_RD_SAFETY_STAT_3, LBIST_ERR_SHIFT}, // 33 + {PMIC_CMD_RD_SAFETY_STAT_3, ABIST_ERR_SHIFT}, // 34 + {PMIC_CMD_RD_SAFETY_STAT_4, SPI_ERR_SHIFT}, // 35 + {PMIC_CMD_RD_SAFETY_STAT_4, SPI_ERR_SHIFT}, // 36 + {PMIC_CMD_RD_SAFETY_STAT_4, SPI_ERR_SHIFT}, // 37 + {PMIC_CMD_RD_SAFETY_STAT_4, LO_LPMCLK_SHIFT}, // 38 + {PMIC_CMD_RD_SAFETY_STAT_4, ENDRV_ERR_SHIFT}, // 39 + {PMIC_CMD_RD_SAFETY_STAT_4, TRIM_ERR_VMON_SHIFT}, // 40 + {PMIC_CMD_RD_SPI_INV_TRAN_STAT, INVALID_CMD_SHIFT}, // 41 + {PMIC_CMD_RD_SPI_INV_TRAN_STAT, UNDEF_CMD_SHIFT}, // 42 + {PMIC_CMD_RD_SPI_INV_TRAN_STAT, CRC_ERR_SHIFT}, // 43 + {PMIC_CMD_RD_SPI_INV_TRAN_STAT, LONG_FRM_SHIFT}, // 44 + {PMIC_CMD_RD_SPI_INV_TRAN_STAT, SHORT_FRM_SHIFT}, // 45 + {PMIC_CMD_RD_SAFETY_ERR_STAT_1, ERROR_PIN_FAIL_SHIFT}, // 46 + {PMIC_CMD_RD_SAFETY_ERR_STAT_1, WD_FAIL_SHIFT}, // 47 + {PMIC_CMD_RD_SAFETY_ERR_STAT_2, DIAG_STATE_TO_SHIFT}, // 48 + {PMIC_CMD_RD_SAM_STAT, SAM_BIST_FAIL_SHIFT}, // 49 + {PMIC_CMD_RD_SAM_STAT, POWER_ON_RESET_SHIFT}, // 50 + {PMIC_CMD_RD_SAM_STAT, SAM_CNT_ERR_SHIFT}, // 51 + {PMIC_CMD_RD_SAM_SIG_STAT, COS_P_OV_SHIFT}, // 52 + {PMIC_CMD_RD_SAM_SIG_STAT, COS_P_UV_SHIFT}, // 53 + {PMIC_CMD_RD_SAM_SIG_STAT, COS_N_OV_SHIFT}, // 54 + {PMIC_CMD_RD_SAM_SIG_STAT, COS_N_UV_SHIFT}, // 55 + {PMIC_CMD_RD_SAM_SIG_STAT, SIN_P_OV_SHIFT}, // 56 + {PMIC_CMD_RD_SAM_SIG_STAT, SIN_P_UV_SHIFT}, // 57 + {PMIC_CMD_RD_SAM_SIG_STAT, SIN_N_OV_SHIFT}, // 58 + {PMIC_CMD_RD_SAM_SIG_STAT, SIN_N_UV_SHIFT} // 59 +}; + +/*! + * @brief Function to set the intrStat bit position. + */ +static inline void IRQ_setIntrStat(Pmic_IrqStat_t *irqStat, uint32_t irqNum) +{ + if (irqNum <= PMIC_IRQ_MAX) + { + // IRQs 0-31 are assigned to index 0, IRQs 32-63 are assigned to index 1. + // At an index, the IRQ is stored at its corresponding bit position + // (e.g., IRQ 49's status will be stored at bit 17 at index 1) + irqStat->intrStat[irqNum / PMIC_NUM_BITS_IN_INTR_STAT] |= ((uint32_t)1U << (irqNum % PMIC_NUM_BITS_IN_INTR_STAT)); + } +} + +static inline void IRQ_setIntrBits(Pmic_IrqStat_t *irqStat, uint8_t regData, const uint8_t irqs[], uint8_t numIrqs) +{ + for (uint8_t i = 0U; i < numIrqs; i++) + { + if (Pmic_getBitField_b(regData, pmicIRQs[irqs[i]].bitShift)) + { + IRQ_setIntrStat(irqStat, irqs[i]); + } + } +} + +static int32_t IRQ_readVmonStat(const Pmic_CoreHandle_t *pmicHandle, Pmic_IrqStat_t *irqStat) +{ + uint8_t regData = 0U; + int32_t status = PMIC_ST_SUCCESS; + const uint8_t vmonStat1Irq[] = { + PMIC_IRQ_VBATL_OV, + PMIC_IRQ_VBATL_UV, + PMIC_IRQ_VCP_UV + }; + const uint8_t vmonStat2Irq[] = { + PMIC_IRQ_VDD6_OV, + PMIC_IRQ_VDD6_UV, + PMIC_IRQ_VDD5_OV, + PMIC_IRQ_VDD5_UV, + PMIC_IRQ_VDD_3P5_OV, + PMIC_IRQ_VDD_3P5_UV + }; + const uint8_t vmonStat3Irq[] = { + PMIC_IRQ_VREG_UV, + PMIC_IRQ_VDD6_LP_UV, + PMIC_IRQ_VSOUT2_OV, + PMIC_IRQ_VSOUT2_UV, + PMIC_IRQ_VSOUT1_OV, + PMIC_IRQ_VSOUT1_UV + }; + + // Read VMON_STAT_1 register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_VMON_STAT_1, ®Data); + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bits in irqStat + IRQ_setIntrBits(irqStat, regData, vmonStat1Irq, COUNT(vmonStat1Irq)); + + // Read VMON_STAT_2 register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_VMON_STAT_2, ®Data); + } + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bits in irqStat + IRQ_setIntrBits(irqStat, regData, vmonStat2Irq, COUNT(vmonStat2Irq)); + + // Read VMON_STAT_3 register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_VMON_STAT_3, ®Data); + } + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bits in irqStat + IRQ_setIntrBits(irqStat, regData, vmonStat3Irq, COUNT(vmonStat3Irq)); + } + + return status; +} + +static int32_t IRQ_readSafetyStat1_2(const Pmic_CoreHandle_t *pmicHandle, Pmic_IrqStat_t *irqStat) +{ + uint8_t regData = 0U; + int32_t status = PMIC_ST_SUCCESS; + const uint8_t safetyStat1Irq[] = { + PMIC_IRQ_VDD6_OT_FLAG, + PMIC_IRQ_VDD6_TP, + PMIC_IRQ_VDD5_ILIM, + PMIC_IRQ_VDD5_OT_FLAG, + PMIC_IRQ_VDD5_TP, + PMIC_IRQ_VDD_3P5_ILIM, + PMIC_IRQ_VDD_3P5_OT_FLAG, + PMIC_IRQ_VDD_3P5_TP + }; + const uint8_t safetyStat2Irq[] = { + PMIC_IRQ_VDD6_ILIM, + PMIC_IRQ_VSOUT2_ILIM, + PMIC_IRQ_VSOUT2_OT_FLAG, + PMIC_IRQ_VSOUT2_TP, + PMIC_IRQ_VSOUT1_ILIM, + PMIC_IRQ_VSOUT1_OT_FLAG, + PMIC_IRQ_VSOUT1_TP + }; + + // Read SAFETY_STAT_1 register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_SAFETY_STAT_1, ®Data); + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bits in irqStat + IRQ_setIntrBits(irqStat, regData, safetyStat1Irq, COUNT(safetyStat1Irq)); + + // Read SAFETY_STAT_2 register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_SAFETY_STAT_2, ®Data); + } + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bits in irqStat + IRQ_setIntrBits(irqStat, regData, safetyStat2Irq, COUNT(safetyStat2Irq)); + } + + return status; +} + +static int32_t IRQ_readSafetyStat3_4(const Pmic_CoreHandle_t *pmicHandle, Pmic_IrqStat_t *irqStat) +{ + uint8_t regData = 0U; + int32_t status = PMIC_ST_SUCCESS; + const uint8_t safetyStat3Irq[] = { + PMIC_IRQ_CFG_CRC_ERR, + PMIC_IRQ_EE_CRC_ERR, + PMIC_IRQ_NRES_ERR, + PMIC_IRQ_LBIST_ERR, + PMIC_IRQ_ABIST_ERR + }; + const uint8_t safetyStat4Irq[] = { + PMIC_IRQ_LO_LPMCLK, + PMIC_IRQ_ENDRV_ERR, + PMIC_IRQ_TRIM_ERR_VMON + }; + + // Read SAFETY_STAT_3 register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_SAFETY_STAT_3, ®Data); + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bits in irqStat + IRQ_setIntrBits(irqStat, regData, safetyStat3Irq, COUNT(safetyStat3Irq)); + + // Read SAFETY_STAT_4 register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_SAFETY_STAT_4, ®Data); + } + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bits in irqStat + IRQ_setIntrBits(irqStat, regData, safetyStat4Irq, COUNT(safetyStat4Irq)); + + // Special case; certain SPI status errors share the same bit field + switch (Pmic_getBitField(regData, SPI_ERR_SHIFT, SPI_ERR_MASK)) + { + case PMIC_SPI_ERR_CMD: + { + IRQ_setIntrStat(irqStat, PMIC_IRQ_SPI_CMD_ERR); + break; + } + case PMIC_SPI_ERR_FORMAT: + { + IRQ_setIntrStat(irqStat, PMIC_IRQ_SPI_FORMAT_ERR); + break; + } + case PMIC_SPI_ERR_OUTPUT_MISMATCH: + { + IRQ_setIntrStat(irqStat, PMIC_IRQ_SPI_DATA_OUTPUT_MISMATCH); + break; + } + default: + { + /* No error */ + break; + } + } + } + + return status; +} + +static int32_t IRQ_readSafetyStat(const Pmic_CoreHandle_t *pmicHandle, Pmic_IrqStat_t *irqStat) +{ + int32_t status = IRQ_readSafetyStat1_2(pmicHandle, irqStat); + + if (status == PMIC_ST_SUCCESS) + { + status = IRQ_readSafetyStat3_4(pmicHandle, irqStat); + } + + return status; +} + +static int32_t IRQ_readSafetyErrStat(const Pmic_CoreHandle_t *pmicHandle, Pmic_IrqStat_t *irqStat) +{ + uint8_t regData = 0U; + int32_t status = PMIC_ST_SUCCESS; + const uint8_t safetyErrStat1Irq[] = { + PMIC_IRQ_ERROR_PIN_FAIL, + PMIC_IRQ_WD_FAIL + }; + + // Read SAFETY_ERR_STAT_1 register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_SAFETY_ERR_STAT_1, ®Data); + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bits in irqStat + IRQ_setIntrBits(irqStat, regData, safetyErrStat1Irq, COUNT(safetyErrStat1Irq)); + + // Read SAFETY_ERR_STAT_2 register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_SAFETY_ERR_STAT_2, ®Data); + } + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bit in irqStat + IRQ_setIntrStat(irqStat, PMIC_IRQ_DIAG_STATE_TO); + } + + return status; +} + +static int32_t IRQ_readSamStatus(const Pmic_CoreHandle_t *pmicHandle, Pmic_IrqStat_t *irqStat) +{ + uint8_t regData = 0U; + int32_t status = PMIC_ST_SUCCESS; + const uint8_t samStatIrq[] = { + PMIC_IRQ_SAM_BIST_FAIL, + PMIC_IRQ_POWER_ON_RESET, + PMIC_IRQ_SAM_CNT_ERR + }; + const uint8_t samSigStatIrq[] = { + PMIC_IRQ_COS_P_OV, + PMIC_IRQ_COS_P_UV, + PMIC_IRQ_COS_N_OV, + PMIC_IRQ_COS_N_UV, + PMIC_IRQ_SIN_P_OV, + PMIC_IRQ_SIN_P_UV, + PMIC_IRQ_SIN_N_OV, + PMIC_IRQ_SIN_N_UV + }; + + // Read SAM_STAT register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_SAM_STAT, ®Data); + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bit in irqStat + IRQ_setIntrBits(irqStat, regData, samStatIrq, COUNT(samStatIrq)); + + // Read SAM_SIG_STAT register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_SAM_SIG_STAT, ®Data); + } + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bit in irqStat + IRQ_setIntrBits(irqStat, regData, samSigStatIrq, COUNT(samSigStatIrq)); + } + + return status; +} + +static int32_t IRQ_readSpiInvTranStat(const Pmic_CoreHandle_t *pmicHandle, Pmic_IrqStat_t *irqStat) +{ + uint8_t regData = 0U; + uint8_t irq[5U] = {0U}; + int32_t status = PMIC_ST_SUCCESS; + const uint8_t spiInvTranStatIrq[] = { + PMIC_IRQ_INVALID_CMD, + PMIC_IRQ_UNDEF_CMD, + PMIC_IRQ_CRC_ERR, + PMIC_IRQ_LONG_FRM, + PMIC_IRQ_SHORT_FRM + }; + + // Read SPI_INV_TRAN_STAT register + status = Pmic_ioRxByte_CS(pmicHandle, PMIC_CMD_RD_SPI_INV_TRAN_STAT, ®Data); + + if (status == PMIC_ST_SUCCESS) + { + // Set the corresponding bit in irqStat + IRQ_setIntrBits(irqStat, regData, spiInvTranStatIrq, COUNT(spiInvTranStatIrq)); + } +} + +int32_t Pmic_irqGetStat(const Pmic_CoreHandle_t *pmicHandle, Pmic_IrqStat_t *irqStat) +{ + int32_t status = Pmic_checkPmicCoreHandle(pmicHandle); + + if ((status == PMIC_ST_SUCCESS) && (irqStat == NULL)) + { + status = PMIC_ST_ERR_NULL_PARAM; + } + + if (status == PMIC_ST_SUCCESS) + { + memset(irqStat->intrStat, 0U, PMIC_NUM_ELEM_IN_INTR_STAT); + + status = IRQ_readVmonStat(pmicHandle, irqStat); + } + + if (status == PMIC_ST_SUCCESS) + { + status = IRQ_readSafetyStat(pmicHandle, irqStat); + } + + if (status == PMIC_ST_SUCCESS) + { + status = IRQ_readSafetyErrStat(pmicHandle, irqStat); + } + + if (status == PMIC_ST_SUCCESS) + { + status = IRQ_readSamStatus(pmicHandle, irqStat); + } + + if (status == PMIC_ST_SUCCESS) + { + status = IRQ_readSpiInvTranStat(pmicHandle, irqStat); + } + + // Clear irqStat if there was an error at any point + if ((status != PMIC_ST_SUCCESS) && (irqStat != NULL)) + { + memset(irqStat->intrStat, 0U, PMIC_NUM_ELEM_IN_INTR_STAT); + } + + return status; +} + +static uint8_t IRQ_getNextFlag(Pmic_IrqStat_t *irqStat) +{ + uint8_t index = 0U, bitPos = 0U; + bool foundFlag = (bool)false; + + // For each element in struct member intrStat of irqStat... + for (index = 0U; index < PMIC_NUM_ELEM_IN_INTR_STAT; index++) + { + // If current element has no IRQ statuses set, move onto next element + if (irqStat->intrStat[index] == 0U) + { + continue; + } + + // For each bit in the element... + for (bitPos = 0U; bitPos < PMIC_NUM_BITS_IN_INTR_STAT; bitPos++) + { + // If the bit is set... + if ((irqStat->intrStat[index] & (1U << bitPos)) != 0U) + { + // Clear bit in intrStat element and exit loop + irqStat->intrStat[index] &= ~(1U << bitPos); + foundFlag = (bool)true; + break; + } + } + + if (foundFlag) + { + break; + } + } + + // Return the corresponding IRQ number + return (bitPos + (PMIC_NUM_BITS_IN_INTR_STAT * index)); +} + +int32_t Pmic_irqGetNextFlag(Pmic_IrqStat_t *irqStat, uint8_t *irqNum) +{ + int32_t status = PMIC_ST_SUCCESS; + + if (((irqStat == NULL) || (irqNum == NULL))) + { + status = PMIC_ST_ERR_NULL_PARAM; + } + + if ((status == PMIC_ST_SUCCESS) && (irqStat->intrStat[0U] == 0U) && (irqStat->intrStat[1U] == 0U)) + { + status = PMIC_ST_WARN_NO_IRQ_REMAINING; + } + + if (status == PMIC_ST_SUCCESS) + { + *irqNum = IRQ_getNextFlag(irqStat); + } + + return status; +} + +int32_t Pmic_irqGetFlag(const Pmic_CoreHandle_t *pmicHandle, uint8_t irqNum, bool *flag) +{ + uint8_t regData = 0U; + int32_t status = Pmic_checkPmicCoreHandle(pmicHandle); + + if ((status == PMIC_ST_SUCCESS) && (irqNum > PMIC_IRQ_MAX)) + { + status = PMIC_ST_ERR_INV_PARAM; + } + + if ((status == PMIC_ST_SUCCESS) && (flag == NULL)) + { + status = PMIC_ST_ERR_NULL_PARAM; + } + + // Read IRQ status register + if (status == PMIC_ST_SUCCESS) + { + status = Pmic_ioRxByte_CS(pmicHandle, pmicIRQs[irqNum].regCmd, ®Data); + } + + // Extract IRQ status + if (status == PMIC_ST_SUCCESS) + { + // Special case; certain SPI status errors share the same bit field + if ((irqNum >= PMIC_IRQ_SPI_CMD_ERR) && (irqNum <= PMIC_IRQ_SPI_DATA_OUTPUT_MISMATCH)) + { + uint8_t spiErr = Pmic_getBitField(regData, SPI_ERR_SHIFT, SPI_ERR_MASK); + + if (((irqNum == PMIC_IRQ_SPI_CMD_ERR) && (spiErr == PMIC_SPI_ERR_CMD)) || + ((irqNum == PMIC_IRQ_SPI_FORMAT_ERR) && (spiErr == PMIC_SPI_ERR_FORMAT)) || + ((irqNum == PMIC_IRQ_SPI_DATA_OUTPUT_MISMATCH) && (spiErr == PMIC_SPI_ERR_OUTPUT_MISMATCH))) + { + *flag = (bool)true; + } + } + else + { + *flag = Pmic_getBitField_b(regData, pmicIRQs[irqNum].bitShift); + } + } + + return status; +} + +int32_t Pmic_irqClrFlag(const Pmic_CoreHandle_t *pmicHandle, uint8_t irqNum) +{ + uint8_t regData = 0U; + int32_t status = Pmic_checkPmicCoreHandle(pmicHandle); + + if ((status == PMIC_ST_SUCCESS) && (irqNum > PMIC_IRQ_MAX)) + { + status = PMIC_ST_ERR_INV_PARAM; + } + + if (status == PMIC_ST_SUCCESS) + { + // Read status register to clear the IRQ + status = Pmic_ioRxByte_CS(pmicHandle, pmicIRQs[irqNum].regCmd, ®Data); + } + + return status; +} + +int32_t Pmic_irqClrAllFlags(const Pmic_CoreHandle_t *handle) +{ + uint8_t regData = 0U; + int32_t status = Pmic_checkPmicCoreHandle(handle); + + // Clear IRQ statuses by reading their register + Pmic_criticalSectionStart(handle); + for (uint8_t i = 0U; i < NUM_CLEARABLE_REGISTERS; i++) + { + if (status != PMIC_ST_SUCCESS) + { + break; + } + + status = Pmic_ioTransfer(handle, ClearableRegCmd[i], PMIC_NO_WRITE_DATA, ®Data); + } + Pmic_criticalSectionStop(handle); + + return status; +}