blob: 0e6bff78e9ba7a7d9fd9dd7d3be8130db50f01aa [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PLIC_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PLIC_H_
/**
* @file
* @brief <a href="/hw/ip/rv_plic/doc/">PLIC</a> Device Interface Functions
*/
#include <stdbool.h>
#include <stdint.h>
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_warn_unused_result.h"
// Header Extern Guard (so header can be used from C and C++)
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/** The lowest interrupt priority. */
extern const uint32_t kDifPlicMinPriority;
/** The highest interrupt priority. */
extern const uint32_t kDifPlicMaxPriority;
/**
* PLIC interrupt source identifier.
*
* This corresponds to a specific interrupt, and not the device it originates
* from.
*
* This is an unsigned 32-bit value that is at least zero and is less than the
* `NumSrc` instantiation parameterof the `rv_plic` device.
*
* The value 0 corresponds to "No Interrupt".
*/
typedef uint32_t dif_plic_irq_id_t;
/**
* PLIC interrupt target.
*
* This corresponds to a specific system that can service an interrupt. In
* OpenTitan's case, that is the Ibex core. If there were multiple cores in the
* system, each core would have its own specific interrupt target ID.
*
* This is an unsigned 32-bit value that is at least 0 and is less than the
* `NumTarget` instantiation parameter of the `rv_plic` device.
*/
typedef uint32_t dif_plic_target_t;
/**
* Generic enable/disable enumeration.
*
* Enumeration used to enable/disable bits, flags, ...
*/
typedef enum dif_plic_enable {
kDifPlicEnable = 0,
kDifPlicDisable,
} dif_plic_enable_t;
/**
* Generic set/unset enumeration.
*
* Enumeration used to set/unset, or get the state of bits,flags ...
*/
typedef enum dif_plic_flag {
kDifPlicSet = 0,
kDifPlicUnset,
} dif_plic_flag_t;
/**
* PLIC instance state.
*
* PLIC persistent data that is required by all the PLIC API.
*/
typedef struct dif_plic {
mmio_region_t base_addr; /**< PLIC instance base address. */
} dif_plic_t;
/**
* PLIC generic status codes.
*
* These error codes can be used by any function. However if a function
* requires additional status codes, it must define a set of status codes to
* be used exclusicvely by such function.
*/
typedef enum dif_plic_result {
kDifPlicOk = 0, /**< Success. */
kDifPlicError, /**< General error. */
kDifPlicBadArg, /**< Input parameter is not valid. */
} dif_plic_result_t;
/**
* Initialises an instance of PLIC.
*
* Information that must be retained, and is required to program PLIC, shall
* be stored in `plic`.
*
* @param base_addr Base address of an instance of the PLIC IP block.
* @param[out] plic PLIC state data.
* @return `dif_plic_result_t`.
*/
DIF_WARN_UNUSED_RESULT
dif_plic_result_t dif_plic_init(mmio_region_t base_addr, dif_plic_t *plic);
/**
* Enables/disables handling of IRQ source in PLIC.
*
* This operation does not affect the IRQ generation in the peripherals, which
* must be configured in a corresponding peripheral itself.
* @param plic PLIC state data.
* @param irq Interrupt Source ID.
* @param target Target to enable the IRQ for.
* @param enable Enable/disable the IRQ handling.
* @return `dif_plic_result_t`.
*/
DIF_WARN_UNUSED_RESULT
dif_plic_result_t dif_plic_irq_enable_set(const dif_plic_t *plic,
dif_plic_irq_id_t irq,
dif_plic_target_t target,
dif_plic_enable_t enable);
/**
* Sets the IRQ trigger type (edge/level).
*
* Sets the behaviour of the Interrupt Gateway for a particular IRQ to be edge
* or level triggered.
* @param plic PLIC state data.
* @param irq Interrupt source ID.
* @param enable Enable for the edge triggered, disable for level triggered
* IRQs.
* @return `dif_plic_result_t`.
*/
DIF_WARN_UNUSED_RESULT
dif_plic_result_t dif_plic_irq_trigger_type_set(const dif_plic_t *plic,
dif_plic_irq_id_t irq,
dif_plic_enable_t enable);
/**
* Sets IRQ source priority (0-3).
*
* In order for PLIC to set a CC register and assert the external interrupt line
* to the target (Ibex, ...), the priority of an IRQ source must be higher than
* the threshold for this source.
* @param plic PLIC state data.
* @param irq Interrupt source ID.
* @param priority Priority to be set.
* @return `dif_plic_result_t`.
*/
DIF_WARN_UNUSED_RESULT
dif_plic_result_t dif_plic_irq_priority_set(const dif_plic_t *plic,
dif_plic_irq_id_t irq,
uint32_t priority);
/**
* Sets the target priority threshold.
*
* Sets the target priority threshold. PLIC will only interrupt a target when
* IRQ source priority is set higher than the priority threshold for the
* corresponding target.
* @param plic PLIC state data.
* @param target Target to set the IRQ priority threshold for.
* @param threshold IRQ priority threshold to be set.
* @return `dif_plic_result_t`.
*/
DIF_WARN_UNUSED_RESULT
dif_plic_result_t dif_plic_target_threshold_set(const dif_plic_t *plic,
dif_plic_target_t target,
uint32_t threshold);
/**
* Checks the Interrupt Pending bit.
*
* Gets the status of the PLIC Interrupt Pending register bit for a specific IRQ
* source.
* @param plic PLIC state data.
* @param irq Interrupt source ID.
* @param[out] status Flag indicating whether the IRQ pending bit is set in
* PLIC.
* @return `dif_plic_result_t`.
*/
DIF_WARN_UNUSED_RESULT
dif_plic_result_t dif_plic_irq_pending_status_get(const dif_plic_t *plic,
dif_plic_irq_id_t irq,
dif_plic_flag_t *status);
/**
* Claims an IRQ and gets the information about the source.
*
* Claims an IRQ and returns the IRQ related data to the caller. This function
* reads a target specific CC register. dif_plic_irq_complete must be called
* after the claimed IRQ has been serviced.
*
* @param plic PLIC state data.
* @param target Target that claimed the IRQ.
* @param[out] claim_data Data that describes the origin of the IRQ.
* @return `dif_plic_result_t`.
*/
DIF_WARN_UNUSED_RESULT
dif_plic_result_t dif_plic_irq_claim(const dif_plic_t *plic,
dif_plic_target_t target,
dif_plic_irq_id_t *claim_data);
/**
* Completes the claimed IRQ.
*
* Finishes servicing of the claimed IRQ by writing the IRQ source ID back to a
* target specific CC register. This function must be called after
* dif_plic_claim_irq, when a caller has finished servicing the IRQ.
*
* @param plic PLIC state data.
* @param target Target that claimed the IRQ.
* @param[out] complete_data Previously claimed IRQ data that is used to signal
* PLIC of the IRQ servicing completion.
* @return `dif_plic_result_t`.
*/
DIF_WARN_UNUSED_RESULT
dif_plic_result_t dif_plic_irq_complete(const dif_plic_t *plic,
dif_plic_target_t target,
const dif_plic_irq_id_t *complete_data);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_PLIC_H_