111 lines
3.1 KiB
C
111 lines
3.1 KiB
C
/*
|
|
* Copyright (c) 2018 Foundries.io Ltd
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifndef SOC_RISCV32_OPENISA_RV32M1_SOC_H_
|
|
#define SOC_RISCV32_OPENISA_RV32M1_SOC_H_
|
|
|
|
#ifndef _ASMLANGUAGE
|
|
|
|
#include "fsl_device_registers.h"
|
|
#include <zephyr/types.h>
|
|
|
|
/*
|
|
* Helpers related to interrupt handling. This SoC has two levels of
|
|
* interrupts.
|
|
*
|
|
* Level 1 interrupts go straight to the SoC. Level 2 interrupts must
|
|
* go through one of the 8 channels in the INTMUX
|
|
* peripheral. There are 32 level 1 interrupts, including 8 INTMUX
|
|
* interrupts. Each INTMUX interrupt can mux at most
|
|
* CONFIG_MAX_IRQ_PER_AGGREGATOR (which happens to be 32) interrupts
|
|
* to its level 1 interrupt.
|
|
*
|
|
* See gen_isr_tables.py for details on the Zephyr multi-level IRQ
|
|
* number encoding, which determines how these helpers work.
|
|
*/
|
|
|
|
/**
|
|
* @brief Get an IRQ's level
|
|
* @param irq The IRQ number in the Zephyr irq.h numbering system
|
|
* @return IRQ level, either 1 or 2
|
|
*/
|
|
static inline unsigned int rv32m1_irq_level(unsigned int irq)
|
|
{
|
|
return ((irq >> 8) & 0xff) == 0U ? 1 : 2;
|
|
}
|
|
|
|
/**
|
|
* @brief Level 1 interrupt line associated with an IRQ
|
|
*
|
|
* Results are undefined if rv32m1_irq_level(irq) is not 1.
|
|
*
|
|
* @param The IRQ number in the Zephyr <irq.h> numbering system
|
|
* @return Level 1 (i.e. event unit) IRQ number associated with irq
|
|
*/
|
|
static inline uint32_t rv32m1_level1_irq(unsigned int irq)
|
|
{
|
|
/*
|
|
* There's no need to do any math; the precondition is that
|
|
* it's a level 1 IRQ.
|
|
*/
|
|
return irq;
|
|
}
|
|
|
|
/**
|
|
* @brief INTMUX channel (i.e. level 2 aggregator number) for an IRQ
|
|
*
|
|
* Results are undefined if rv32m1_irq_level(irq) is not 2.
|
|
*
|
|
* @param irq The IRQ number whose INTMUX channel / level 2 aggregator
|
|
* to get, in the Zephyr <irq.h> numbering system
|
|
* @return INTMUX channel number associated with the IRQ
|
|
*/
|
|
static inline uint32_t rv32m1_intmux_channel(unsigned int irq)
|
|
{
|
|
/*
|
|
* Here we make use of these facts:
|
|
*
|
|
* - the INTMUX output IRQ numbers are arranged consecutively
|
|
* by channel in the event unit IRQ numbering assignment,
|
|
* starting from channel 0.
|
|
*
|
|
* - CONFIG_2ND_LVL_INTR_00_OFFSET is defined to
|
|
* be the offset of the first level 2 aggregator in the parent
|
|
* interrupt controller's IRQ numbers, i.e. channel 0's
|
|
* IRQ number in the event unit.
|
|
*/
|
|
return (irq & 0xff) - CONFIG_2ND_LVL_INTR_00_OFFSET;
|
|
}
|
|
|
|
/**
|
|
* @brief INTMUX interrupt ID number for an IRQ
|
|
*
|
|
* Results are undefined if rv32m1_irq_level(irq) is not 2.
|
|
*
|
|
* @param The IRQ number whose INTMUX interrupt ID to get, in the Zephyr
|
|
* <irq.h> numbering system
|
|
* @return The INTMUX interrupt ID, in the inclusive range 0 to 31
|
|
*/
|
|
static inline uint32_t rv32m1_intmux_line(unsigned int irq)
|
|
{
|
|
return ((irq >> 8) & 0xff) - 1;
|
|
}
|
|
|
|
#endif /* !_ASMLANGUAGE */
|
|
|
|
#if defined(CONFIG_SOC_OPENISA_RV32M1_RI5CY)
|
|
#include "soc_ri5cy.h"
|
|
#elif defined(CONFIG_SOC_OPENISA_RV32M1_ZERO_RISCY)
|
|
#include "soc_zero_riscy.h"
|
|
#endif
|
|
|
|
/* helper macro to convert from a DT_INST to HAL clock_ip_name */
|
|
#define INST_DT_CLOCK_IP_NAME(n) \
|
|
MAKE_PCC_REGADDR(DT_REG_ADDR(DT_INST_PHANDLE(n, clocks)), \
|
|
DT_INST_CLOCKS_CELL(n, name))
|
|
|
|
#endif /* SOC_RISCV32_OPENISA_RV32M1_SOC_H_ */
|