kendryte-standalone-sdk/lib/drivers/include/clint.h

324 lines
8.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* @brief The CLINT block holds memory-mapped control and status registers
* associated with local interrupts for a Coreplex.
*
* @note CLINT RAM Layout
*
* | Address -| Description |
* |------------|---------------------------------|
* | 0x02000000 | msip for hart 0 |
* | 0x02000004 | msip for hart 1 |
* | ... | ... |
* | 0x02003FF8 | msip for hart 4094 |
* | | |
* | 0x02004000 | mtimecmp for hart 0 |
* | 0x02004008 | mtimecmp for hart 1 |
* | ... | ... |
* | 0x0200BFF0 | mtimecmp For hart 4094 |
* | 0x0200BFF8 | mtime |
* | | |
* | 0x0200C000 | Reserved |
* | ... | ... |
* | 0x0200EFFC | Reserved |
*/
#ifndef _DRIVER_CLINT_H
#define _DRIVER_CLINT_H
#include <stddef.h>
#include <stdint.h>
#include "platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
/* Register address offsets */
#define CLINT_MSIP (0x0000)
#define CLINT_MSIP_SIZE (0x4)
#define CLINT_MTIMECMP (0x4000)
#define CLINT_MTIMECMP_SIZE (0x8)
#define CLINT_MTIME (0xBFF8)
#define CLINT_MTIME_SIZE (0x8)
/* Max number of cores */
#define CLINT_MAX_HARTS (4095)
/* Real number of cores */
#define CLINT_NUM_HARTS (2)
/* Clock frequency division factor */
#define CLINT_CLOCK_DIV (50)
/* clang-format on */
/**
* @brief MSIP Registers
*
* Machine-mode software interrupts are generated by writing to a
* per-hart memory-mapped control register. The msip registers are
* 32-bit wide WARL registers, where the LSB is reflected in the
* msip bit of the associated harts mip register. Other bits in
* the msip registers are hardwired to zero. The mapping supports
* up to 4095 machine-mode harts.
*/
struct clint_msip_t
{
uint32_t msip : 1; /*!< Bit 0 is msip */
uint32_t zero : 31; /*!< Bits [32:1] is 0 */
} __attribute__((packed, aligned(4)));
/**
* @brief Timer compare Registers Machine-mode timer interrupts are
* generated by a real-time counter and a per-hart comparator. The
* mtime register is a 64-bit read-only register that contains the
* current value of the real-time counter. Each mtimecmp register
* holds its harts time comparator. A timer interrupt is pending
* whenever mtime is greater than or equal to the value in a
* harts mtimecmp register. The timer interrupt is reflected in
* the mtip bit of the associated harts mip register.
*/
typedef uint64_t clint_mtimecmp_t;
/**
* @brief Timer Registers
*
* The mtime register has a 64-bit precision on all RV32, RV64,
* and RV128 systems. Platforms provide a 64-bit memory-mapped
* machine-mode timer compare register (mtimecmp), which causes a
* timer interrupt to be posted when the mtime register contains a
* value greater than or equal to the value in the mtimecmp
* register. The interrupt remains posted until it is cleared by
* writing the mtimecmp register. The interrupt will only be taken
* if interrupts are enabled and the MTIE bit is set in the mie
* register.
*/
typedef uint64_t clint_mtime_t;
/**
* @brief CLINT object
*
* Coreplex-Local INTerrupts, which includes software interrupts,
* local timer interrupts, and other interrupts routed directly to
* a core.
*/
struct clint_t
{
/* 0x0000 to 0x3FF8, MSIP Registers */
struct clint_msip_t msip[CLINT_MAX_HARTS];
/* Resverd space, do not use */
uint32_t resv0;
/* 0x4000 to 0xBFF0, Timer Compare Registers */
clint_mtimecmp_t mtimecmp[CLINT_MAX_HARTS];
/* 0xBFF8, Time Register */
clint_mtime_t mtime;
} __attribute__((packed, aligned(4)));
/**
* @brief Clint object instanse
*/
extern volatile struct clint_t* const clint;
/**
* @brief Definitions for the timer callbacks
*/
typedef int (*clint_timer_callback_t)(void* ctx);
/**
* @brief Definitions for local interprocessor interrupt callbacks
*/
typedef int (*clint_ipi_callback_t)(void* ctx);
/**
* @brief Get the time form CLINT timer register
*
* @note The CLINT must init to get right time
*
* @return 64bit Time
*/
uint64_t clint_get_time(void);
/**
* @brief Init the CLINT timer
*
* @note MIP_MTIP will be clear after init. The MSTATUS_MIE must set by
* user.
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_init(void);
/**
* @brief Stop the CLINT timer
*
* @note MIP_MTIP will be clear after stop
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_stop(void);
/**
* @brief Start the CLINT timer
*
* @param[in] interval The interval with Millisecond(ms)
* @param[in] single_shot Single shot or repeat
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_start(uint64_t interval, int single_shot);
/**
* @brief Get the interval of timer
*
* @return The interval with Millisecond(ms)
*/
uint64_t clint_timer_get_interval(void);
/**
* @brief Set the interval with Millisecond(ms)
*
* @param[in] interval The interval with Millisecond(ms)
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_set_interval(uint64_t interval);
/**
* @brief Get whether the timer is a single shot timer
*
* @return result
* - 0 It is a repeat timer
* - 1 It is a single shot timer
*/
int clint_timer_get_single_shot(void);
/**
* @brief Set the timer working as a single shot timer or repeat timer
*
* @param[in] single_shot Single shot or repeat
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_set_single_shot(int single_shot);
/**
* @brief Set user callback function when timer is timeout
*
* @param[in] callback The callback function
* @param[in] ctx The context
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_register(clint_timer_callback_t callback, void* ctx);
/**
* @brief Deregister user callback function
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_timer_deregister(void);
/**
* @brief Initialize local interprocessor interrupt
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_init(void);
/**
* @brief Enable local interprocessor interrupt
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_enable(void);
/**
* @brief Disable local interprocessor interrupt
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_disable(void);
/**
* @brief Send local interprocessor interrupt to core by hart id
*
* @param[in] hart_id The hart identifier
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_send(size_t hart_id);
/**
* @brief Clear local interprocessor interrupt
*
* @param[in] hart_id The hart identifier
*
* @return result
* - 1 An IPI was pending
* - 0 Non IPI was pending
* - -1 Fail
*/
int clint_ipi_clear(size_t hart_id);
/**
* @brief Set user callback function when interprocessor interrupt
*
* @param[in] callback The callback function
* @param[in] ctx The context
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_register(clint_ipi_callback_t callback, void* ctx);
/**
* @brief Deregister user callback function
*
* @return result
* - 0 Success
* - Other Fail
*/
int clint_ipi_deregister(void);
#ifdef __cplusplus
}
#endif
#endif /* _DRIVER_CLINT_H */