| /**************************************************************************** |
| * arch/risc-v/src/mpfs/hardware/mpfs_ihc.h |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you 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. |
| * |
| ****************************************************************************/ |
| |
| #ifndef __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_IHC_H |
| #define __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_IHC_H |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| enum mpfs_irq_type_e |
| { |
| MP_IRQ = 0x1, |
| ACK_IRQ = 0x2, |
| }; |
| |
| #define IHC_MAX_MESSAGE_SIZE 2 |
| |
| struct mpfs_ihc_msg_s |
| { |
| uint32_t msg[IHC_MAX_MESSAGE_SIZE]; |
| }; |
| |
| /* Used to store information for the remote via ecall (eg. Linux) */ |
| |
| struct ihc_sbi_rx_msg_s |
| { |
| uint8_t irq_type; |
| struct mpfs_ihc_msg_s ihc_msg; |
| }; |
| |
| #define MPFS_NUM_HARTS 5 |
| #define UNDEFINED_HART_ID 99 |
| |
| #define LIBERO_SETTING_CONTEXT_A_HART_EN ((CONFIG_MPFS_IHC_LINUX_ON_HART4 << 4) | \ |
| (CONFIG_MPFS_IHC_LINUX_ON_HART3 << 3) | \ |
| (CONFIG_MPFS_IHC_LINUX_ON_HART2 << 2) | \ |
| (CONFIG_MPFS_IHC_LINUX_ON_HART1 << 1)) |
| |
| #define LIBERO_SETTING_CONTEXT_B_HART_EN ((CONFIG_MPFS_IHC_NUTTX_ON_HART4 << 4) | \ |
| (CONFIG_MPFS_IHC_NUTTX_ON_HART3 << 3) | \ |
| (CONFIG_MPFS_IHC_NUTTX_ON_HART2 << 2) | \ |
| (CONFIG_MPFS_IHC_NUTTX_ON_HART1 << 1)) |
| |
| #if (LIBERO_SETTING_CONTEXT_A_HART_EN & LIBERO_SETTING_CONTEXT_B_HART_EN) |
| # error Harts misconfigured. Cannot use the same harts. |
| #endif |
| |
| /* Contex A and B hart ID's used in this system. Context A is the master. */ |
| |
| #if CONFIG_MPFS_IHC_LINUX_ON_HART1 == 1 |
| #define CONTEXTA_HARTID 0x01 |
| #elif CONFIG_MPFS_IHC_LINUX_ON_HART2 == 1 |
| #define CONTEXTA_HARTID 0x02 |
| #elif CONFIG_MPFS_IHC_LINUX_ON_HART3 == 1 |
| #define CONTEXTA_HARTID 0x03 |
| #elif CONFIG_MPFS_IHC_LINUX_ON_HART4 == 1 |
| #define CONTEXTA_HARTID 0x04 |
| #else |
| # error Context A is required |
| #endif |
| |
| #if CONFIG_MPFS_IHC_NUTTX_ON_HART1 == 1 |
| #define CONTEXTB_HARTID 0x01 |
| #elif CONFIG_MPFS_IHC_NUTTX_ON_HART2 == 1 |
| #define CONTEXTB_HARTID 0x02 |
| #elif CONFIG_MPFS_IHC_NUTTX_ON_HART3 == 1 |
| #define CONTEXTB_HARTID 0x03 |
| #elif CONFIG_MPFS_IHC_NUTTX_ON_HART4 == 1 |
| #define CONTEXTB_HARTID 0x04 |
| #else |
| # error Context B is required |
| #endif |
| |
| /* We currently support only C = B + 1, eg. NuttX or other RPMSG slaves on |
| * consecutive harts n and (n + 1). This only has to do with more than one |
| * RPMSG channel. |
| */ |
| |
| #define CONTEXTC_HARTID (CONTEXTB_HARTID + 1) |
| |
| #if (CONTEXTA_HARTID == CONTEXTB_HARTID) |
| # error Context A cannot be the same as Context B |
| #endif |
| |
| /* My Hart 0 */ |
| |
| #define IHC_LOCAL_H0_REMOTE_H1 0x50000000UL |
| #define IHC_LOCAL_H0_REMOTE_H2 0x50000100UL |
| #define IHC_LOCAL_H0_REMOTE_H3 0x50000200UL |
| #define IHC_LOCAL_H0_REMOTE_H4 0x50000300UL |
| #define IHCIA_LOCAL_H0 0x50000400UL |
| |
| /* My Hart 1 */ |
| |
| #define IHC_LOCAL_H1_REMOTE_H0 0x50000500UL |
| #define IHC_LOCAL_H1_REMOTE_H2 0x50000600UL |
| #define IHC_LOCAL_H1_REMOTE_H3 0x50000700UL |
| #define IHC_LOCAL_H1_REMOTE_H4 0x50000800UL |
| #define IHCIA_LOCAL_H1 0x50000900UL |
| |
| /* My Hart 2 */ |
| |
| #define IHC_LOCAL_H2_REMOTE_H0 0x50000a00UL |
| #define IHC_LOCAL_H2_REMOTE_H1 0x50000b00UL |
| #define IHC_LOCAL_H2_REMOTE_H3 0x50000c00UL |
| #define IHC_LOCAL_H2_REMOTE_H4 0x50000d00UL |
| #define IHCIA_LOCAL_H2 0x50000e00UL |
| |
| /* My Hart 3 */ |
| |
| #define IHC_LOCAL_H3_REMOTE_H0 0x50000f00UL |
| #define IHC_LOCAL_H3_REMOTE_H1 0x50001000UL |
| #define IHC_LOCAL_H3_REMOTE_H2 0x50001100UL |
| #define IHC_LOCAL_H3_REMOTE_H4 0x50001200UL |
| #define IHCIA_LOCAL_H3 0x50001300UL |
| |
| /* My Hart 4 */ |
| |
| #define IHC_LOCAL_H4_REMOTE_H0 0x50001400UL |
| #define IHC_LOCAL_H4_REMOTE_H1 0x50001500UL |
| #define IHC_LOCAL_H4_REMOTE_H2 0x50001600UL |
| #define IHC_LOCAL_H4_REMOTE_H3 0x50001700UL |
| #define IHCIA_LOCAL_H4 0x50001800UL |
| |
| #define MPFS_IHC_VERSION_OFFSET 0x00 |
| #define MPFS_IHC_CTRL_OFFSET 0x04 |
| #define MPFS_IHC_LOCAL_HARTID_OFFSET 0x08 |
| #define MPFS_IHC_MSG_SIZE_OFFSET 0x0c |
| #define MPFS_IHC_MSG_UNUSED_OFFSET 0x10 |
| #define MPFS_IHC_MSG_IN_OFFSET 0x20 |
| #define MPFS_IHC_MSG_OUT_OFFSET 0x30 |
| |
| #define MPFS_IHC_INT_EN_OFFSET 0x04 |
| #define MPFS_IHC_MSG_AVAIL_OFFSET 0x08 |
| |
| #define MPFS_LOCAL_REMOTE_OFFSET(l, r) (0x500 * (l) + 0x100 * (r)) |
| |
| /* The registers don't go linearly in all cases, use a fixup */ |
| |
| #define MPFS_L_R_FIXUP(l, r) ((((l) > 0 && (l) < 4) && ((l) < (r))) ? -0x100 : 0) |
| |
| #define MPFS_IHC_VERSION(l, r) (IHC_LOCAL_H0_REMOTE_H1 + MPFS_IHC_VERSION_OFFSET + MPFS_LOCAL_REMOTE_OFFSET(l, r) + MPFS_L_R_FIXUP(l, r)) |
| #define MPFS_IHC_CTRL(l, r) (IHC_LOCAL_H0_REMOTE_H1 + MPFS_IHC_CTRL_OFFSET + MPFS_LOCAL_REMOTE_OFFSET(l, r) + MPFS_L_R_FIXUP(l, r)) |
| #define MPFS_IHC_LOCAL_HARTID(l, r) (IHC_LOCAL_H0_REMOTE_H1 + MPFS_IHC_LOCAL_HARTID_OFFSET + MPFS_LOCAL_REMOTE_OFFSET(l, r) + MPFS_L_R_FIXUP(l, r)) |
| #define MPFS_IHC_MSG_SIZE(l, r) (IHC_LOCAL_H0_REMOTE_H1 + MPFS_IHC_MSG_SIZE_OFFSET + MPFS_LOCAL_REMOTE_OFFSET(l, r) + MPFS_L_R_FIXUP(l, r)) |
| #define MPFS_IHC_MSG_IN(l, r) (IHC_LOCAL_H0_REMOTE_H1 + MPFS_IHC_MSG_IN_OFFSET + MPFS_LOCAL_REMOTE_OFFSET(l, r) + MPFS_L_R_FIXUP(l, r)) |
| #define MPFS_IHC_MSG_OUT(l, r) (IHC_LOCAL_H0_REMOTE_H1 + MPFS_IHC_MSG_OUT_OFFSET + MPFS_LOCAL_REMOTE_OFFSET(l, r) + MPFS_L_R_FIXUP(l, r)) |
| |
| #define MPFS_IHC_INT_EN(l) (IHCIA_LOCAL_H0 + MPFS_IHC_INT_EN_OFFSET + 0x500 * (l)) |
| #define MPFS_IHC_MSG_AVAIL(l) (IHCIA_LOCAL_H0 + MPFS_IHC_MSG_AVAIL_OFFSET + 0x500 * (l)) |
| |
| /* Hart mask defines */ |
| |
| #define HART0_ID 0 |
| #define HART1_ID 1 |
| #define HART2_ID 2 |
| #define HART3_ID 3 |
| #define HART4_ID 4 |
| |
| #define HART0_MASK 1 |
| #define HART1_MASK 2 |
| #define HART2_MASK 4 |
| #define HART3_MASK 8 |
| #define HART4_MASK 0x10 |
| |
| /* Monitor hart (HSS hart) used in our system */ |
| |
| #define HSS_HART_MASK HART0_MASK |
| #define HSS_HART_ID HART0_ID |
| |
| /* HSS_REMOTE_HARTS_MASK: This is used to define the harts the HSS is |
| * communicating with |
| */ |
| |
| #define HSS_REMOTE_HARTS_MASK (HART1_MASK | HART2_MASK | HART3_MASK | HART4_MASK) |
| |
| /* Define which harts are connected via comms channels to a particular hart |
| * user defined. |
| */ |
| |
| #define IHCIA_H0_REMOTE_HARTS ((~HSS_HART_MASK) & HSS_REMOTE_HARTS_MASK) |
| |
| #define IHCIA_H1_REMOTE_HARTS (HSS_HART_MASK | (1 << CONTEXTA_HARTID)) |
| #define IHCIA_H2_REMOTE_HARTS (HSS_HART_MASK | (1 << CONTEXTA_HARTID)) |
| #define IHCIA_H3_REMOTE_HARTS (HSS_HART_MASK | (1 << CONTEXTA_HARTID)) |
| #define IHCIA_H4_REMOTE_HARTS (HSS_HART_MASK | (1 << CONTEXTA_HARTID)) |
| |
| #define HSS_HART_DEFAULT_INT_EN (0 << 0) |
| |
| #define HSS_HART_MP_INT_EN (1 << 0) |
| #define HSS_HART_ACK_INT_EN (1 << 1) |
| |
| #define HART1_MP_INT_EN (1 << 2) |
| #define HART1_ACK_INT_EN (1 << 3) |
| |
| #define HART2_MP_INT_EN (1 << 4) |
| #define HART2_ACK_INT_EN (1 << 5) |
| |
| #define HART3_MP_INT_EN (1 << 6) |
| #define HART3_ACK_INT_EN (1 << 7) |
| |
| #define HART4_MP_INT_EN (1 << 8) |
| #define HART4_ACK_INT_EN (1 << 9) |
| |
| /* Connected to all harts */ |
| |
| #define IHCIA_H0_REMOTE_HARTS_INTS HSS_HART_DEFAULT_INT_EN |
| |
| /* HSS and Context B connected */ |
| |
| #define IHCIA_CONTEXTA_INTS (HSS_HART_MP_INT_EN | \ |
| HSS_HART_ACK_INT_EN | \ |
| (1 << (CONTEXTB_HARTID * 2)) | \ |
| (1 << (CONTEXTB_HARTID * 2 + 1))) |
| |
| #define IHCIA_CONTEXTA2_INTS (HSS_HART_MP_INT_EN | \ |
| HSS_HART_ACK_INT_EN | \ |
| (1 << (CONTEXTC_HARTID * 2)) | \ |
| (1 << (CONTEXTC_HARTID * 2 + 1))) |
| |
| #define IHCIA_CONTEXTB_INTS (HSS_HART_MP_INT_EN | \ |
| HSS_HART_ACK_INT_EN | \ |
| (1 << (CONTEXTA_HARTID * 2)) | \ |
| (1 << (CONTEXTA_HARTID * 2 + 1))) |
| |
| /* Context B interrupts */ |
| |
| #if CONTEXTB_HARTID == 1 |
| #define IHCIA_H1_REMOTE_HARTS_INTS IHCIA_CONTEXTB_INTS |
| #endif |
| |
| #if CONTEXTB_HARTID == 2 |
| #define IHCIA_H2_REMOTE_HARTS_INTS IHCIA_CONTEXTB_INTS |
| #endif |
| |
| #if CONTEXTB_HARTID == 3 |
| #define IHCIA_H3_REMOTE_HARTS_INTS IHCIA_CONTEXTB_INTS |
| #endif |
| |
| #if CONTEXTB_HARTID == 4 |
| #define IHCIA_H4_REMOTE_HARTS_INTS IHCIA_CONTEXTB_INTS |
| #endif |
| |
| /* Context A interrupts */ |
| |
| #if CONTEXTA_HARTID == 1 |
| #define IHCIA_H1_REMOTE_HARTS_INTS IHCIA_CONTEXTA_INTS |
| #endif |
| |
| #if CONTEXTA_HARTID == 2 |
| #define IHCIA_H2_REMOTE_HARTS_INTS IHCIA_CONTEXTA_INTS |
| #endif |
| |
| #if CONTEXTA_HARTID == 3 |
| #define IHCIA_H3_REMOTE_HARTS_INTS IHCIA_CONTEXTA_INTS |
| #endif |
| |
| #if CONTEXTA_HARTID == 4 |
| #define IHCIA_H4_REMOTE_HARTS_INTS IHCIA_CONTEXTA_INTS |
| #endif |
| |
| #ifndef IHCIA_H1_REMOTE_HARTS_INTS |
| #define IHCIA_H1_REMOTE_HARTS_INTS HSS_HART_DEFAULT_INT_EN |
| #endif |
| |
| #ifndef IHCIA_H2_REMOTE_HARTS_INTS |
| #define IHCIA_H2_REMOTE_HARTS_INTS HSS_HART_DEFAULT_INT_EN |
| #endif |
| |
| #ifndef IHCIA_H3_REMOTE_HARTS_INTS |
| #define IHCIA_H3_REMOTE_HARTS_INTS HSS_HART_DEFAULT_INT_EN |
| #endif |
| |
| #ifndef IHCIA_H4_REMOTE_HARTS_INTS |
| #define IHCIA_H4_REMOTE_HARTS_INTS HSS_HART_DEFAULT_INT_EN |
| #endif |
| |
| /* MiV-IHCC register bit definitions */ |
| |
| #define RMP_MESSAGE_PRESENT (1 << 0) /* Remote side message present */ |
| #define MP_MESSAGE_PRESENT (1 << 1) /* Local side message present */ |
| #define MPIE_EN (1 << 2) /* Enable MP interrupt */ |
| #define ACK_INT (1 << 3) /* Incoming ACK */ |
| #define ACK_CLR (1 << 4) /* Clear ACK */ |
| #define ACKIE_EN (1 << 5) /* Enable Ack Interrupt */ |
| |
| /* Control register bit MASKS */ |
| |
| #define RMP_MASK (1 << 0) |
| #define MP_MASK (1 << 1) |
| #define MPIE_MASK (1 << 2) |
| #define ACK_INT_MASK (1 << 3) |
| |
| enum ihc_channel_e |
| { |
| IHC_CHANNEL_TO_HART0 = 0x00, /* Your hart to hart 0 */ |
| IHC_CHANNEL_TO_HART1 = 0x01, /* Your hart to hart 1 */ |
| IHC_CHANNEL_TO_HART2 = 0x02, /* Your hart to hart 2 */ |
| IHC_CHANNEL_TO_HART3 = 0x03, /* Your hart to hart 3 */ |
| IHC_CHANNEL_TO_HART4 = 0x04, /* Your hart to hart 4 */ |
| IHC_CHANNEL_TO_CONTEXTA = 0x05, /* Your hart to context A */ |
| IHC_CHANNEL_TO_CONTEXTB = 0x06, /* Your hart to context B */ |
| IHC_CHANNEL_TO_CONTEXTC = 0x07, /* Your hart to context C */ |
| }; |
| |
| typedef enum ihc_channel_e ihc_channel_t; |
| |
| #endif /* __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_IHC_H */ |