From: Yang Yingliang yangyingliang@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8NULW CVE: N/A
-------------------------------------------------
Now with 5052875 ("irqchip/gic-v3: Add support for Message Based Interrupts as an MSI controller"), we can support MBIGEN to generate message based SPIs by writing GICD_SETSPIR.
The first 64-pins of each MBIGEN chip is used to generate SPIs, and each MBIGEN chip has several MBIGEN nodes, every node has 128 pins for generating LPIs. The total pins are: 64(SPIs) + 128 * node_nr(LPIs). So we can translate the pin index in a unified way in mbigen_domain_translate().
Also Add TYPE and VEC registers that used by generating SPIs, the driver can access them when MBIGEN is used to generate SPIs.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Hanjun Guo guohanjun@huawei.com Signed-off-by: zhangyi (F) yi.zhang@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Chen Jun chenjun102@huawei.com conflict: drivers/irqchip/irq-mbigen.c Signed-off-by: Yuntao Liu liuyuntao12@huawei.com --- drivers/irqchip/irq-mbigen.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c index c0aabfee847b..ecb7f16a7c68 100644 --- a/drivers/irqchip/irq-mbigen.c +++ b/drivers/irqchip/irq-mbigen.c @@ -37,6 +37,7 @@ #define MBIGEN_NODE_OFFSET 0x1000
/* offset of vector register in mbigen node */ +#define REG_MBIGEN_SPI_VEC_OFFSET 0x500 #define REG_MBIGEN_LPI_VEC_OFFSET 0x200 /* * offset of clear register in mbigen node @@ -50,6 +51,7 @@ * This register is used to configure interrupt * trigger type */ +#define REG_MBIGEN_SPI_TYPE_OFFSET 0x400 #define REG_MBIGEN_LPI_TYPE_OFFSET 0x0
/** @@ -67,6 +69,9 @@ static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq) { unsigned int nid, pin;
+ if (hwirq < SPI_NUM_PER_MBIGEN_CHIP) + return (hwirq * 4 + REG_MBIGEN_SPI_VEC_OFFSET); + hwirq -= SPI_NUM_PER_MBIGEN_CHIP; nid = hwirq / IRQS_PER_MBIGEN_NODE + 1; pin = hwirq % IRQS_PER_MBIGEN_NODE; @@ -80,6 +85,13 @@ static inline void get_mbigen_type_reg(irq_hw_number_t hwirq, { unsigned int nid, irq_ofst, ofst;
+ if (hwirq < SPI_NUM_PER_MBIGEN_CHIP) { + *mask = 1 << (hwirq % 32); + ofst = hwirq / 32 * 4; + *addr = ofst + REG_MBIGEN_SPI_TYPE_OFFSET; + return; + } + hwirq -= SPI_NUM_PER_MBIGEN_CHIP; nid = hwirq / IRQS_PER_MBIGEN_NODE + 1; irq_ofst = hwirq % IRQS_PER_MBIGEN_NODE; @@ -151,8 +163,14 @@ static void mbigen_write_msg(struct msi_desc *desc, struct msi_msg *msg)
if (!msg->address_lo && !msg->address_hi) return; - + base += get_mbigen_vec_reg(d->hwirq); + + if (d->hwirq < SPI_NUM_PER_MBIGEN_CHIP) { + writel_relaxed(msg->data, base); + return; + } + val = readl_relaxed(base);
val &= ~(IRQ_EVENT_ID_MASK << IRQ_EVENT_ID_SHIFT); @@ -173,8 +191,7 @@ static int mbigen_domain_translate(struct irq_domain *d, if (fwspec->param_count != 2) return -EINVAL;
- if ((fwspec->param[0] > MAXIMUM_IRQ_PIN_NUM) || - (fwspec->param[0] < SPI_NUM_PER_MBIGEN_CHIP)) + if (fwspec->param[0] > MAXIMUM_IRQ_PIN_NUM) return -EINVAL; else *hwirq = fwspec->param[0];