2019-06-03 08:44:50 +03:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
irqchip/mgigen: Add platform device driver for mbigen device
Mbigen means Message Based Interrupt Generator(MBIGEN).
Its a kind of interrupt controller that collects
the interrupts from external devices and generate msi interrupt.
Mbigen is applied to reduce the number of wire connected interrupts.
As the peripherals increasing, the interrupts lines needed is
increasing much, especially on the Arm64 server SOC.
Therefore, the interrupt pin in GIC is not enough to cover so
many peripherals.
Mbigen is designed to fix this problem.
Mbigen chip locates in ITS or outside of ITS.
Mbigen chip hardware structure shows as below:
mbigen chip
|---------------------|-------------------|
mgn_node0 mgn_node1 mgn_node2
| |-------| |-------|------|
dev1 dev1 dev2 dev1 dev3 dev4
Each mbigen chip contains several mbigen nodes.
External devices can connect to mbigen node through wire connecting way.
Because a mbigen node only can support 128 interrupt maximum, depends
on the interrupt lines number of devices, a device can connects to one
more mbigen nodes.
Also, several different devices can connect to a same mbigen node.
When devices triggered interrupt,mbigen chip detects and collects
the interrupts and generates the MBI interrupts by writing the ITS
Translator register.
To simplify mbigen driver,I used a new conception--mbigen device.
Each mbigen device is initialized as a platform device.
Mbigen device presents the parts(register, pin definition etc.) in
mbigen chip corresponding to a peripheral device.
So from software view, the structure likes below
mbigen chip
|---------------------|-----------------|
mbigen device1 mbigen device2 mbigen device3
| | |
dev1 dev2 dev3
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Ma Jun <majun258@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2015-12-17 14:56:35 +03:00
|
|
|
/*
|
2021-03-30 09:46:20 +03:00
|
|
|
* Copyright (C) 2015 HiSilicon Limited, All Rights Reserved.
|
irqchip/mgigen: Add platform device driver for mbigen device
Mbigen means Message Based Interrupt Generator(MBIGEN).
Its a kind of interrupt controller that collects
the interrupts from external devices and generate msi interrupt.
Mbigen is applied to reduce the number of wire connected interrupts.
As the peripherals increasing, the interrupts lines needed is
increasing much, especially on the Arm64 server SOC.
Therefore, the interrupt pin in GIC is not enough to cover so
many peripherals.
Mbigen is designed to fix this problem.
Mbigen chip locates in ITS or outside of ITS.
Mbigen chip hardware structure shows as below:
mbigen chip
|---------------------|-------------------|
mgn_node0 mgn_node1 mgn_node2
| |-------| |-------|------|
dev1 dev1 dev2 dev1 dev3 dev4
Each mbigen chip contains several mbigen nodes.
External devices can connect to mbigen node through wire connecting way.
Because a mbigen node only can support 128 interrupt maximum, depends
on the interrupt lines number of devices, a device can connects to one
more mbigen nodes.
Also, several different devices can connect to a same mbigen node.
When devices triggered interrupt,mbigen chip detects and collects
the interrupts and generates the MBI interrupts by writing the ITS
Translator register.
To simplify mbigen driver,I used a new conception--mbigen device.
Each mbigen device is initialized as a platform device.
Mbigen device presents the parts(register, pin definition etc.) in
mbigen chip corresponding to a peripheral device.
So from software view, the structure likes below
mbigen chip
|---------------------|-----------------|
mbigen device1 mbigen device2 mbigen device3
| | |
dev1 dev2 dev3
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Ma Jun <majun258@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2015-12-17 14:56:35 +03:00
|
|
|
* Author: Jun Ma <majun258@huawei.com>
|
|
|
|
* Author: Yun Wu <wuyun.wu@huawei.com>
|
|
|
|
*/
|
|
|
|
|
irqchip/mbigen: Add ACPI support
With the preparation of platform msi support and interrupt producer
in commit d44fa3d46079 ("ACPI: Add support for ResourceSource/IRQ
domain mapping"), we can add mbigen ACPI support now.
Now that the major framework changes are ready, we just need to add
the ACPI probe code which creates the irqdomain for devices connecting
to it.
In order to create the irqdomain, we need to know the number of hw
irqs as input which is provided by mbigen. In DT case, we are using
"num-pins" property to describe it, and we will take advantage of
that too using _DSD in ACPI as there is no standard way of describe
it in ACPI way, also according to the _DSD rule described in
Documentation/acpi/DSD-properties-rules.txt, it doesn't break
the rules.
The DSDT is represented as below:
For mbigen,
Device(MBI0) {
Name(_HID, "HISI0152")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xa0080000, 0x10000)
})
Name(_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"num-pins", 378}
}
})
}
For devices,
Device(SAS0) {
Name(_HID, "HISIxxxx")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xb0030000, 0x10000)
Interrupt(ResourceConsumer,..., "\_SB.MBI0") {12, ...}
})
}
So for the devices connected to the mbigen, as we clearly say that
it refers to a specific interrupt controller (mbigen), we can get
the virq from mbigen's irqdomain once it's created successfully.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: MaJun <majun258@huawei.com>
Cc: Al Stone <ahs3@redhat.com>
Cc: Darren Hart <dvhart@infradead.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2017-03-28 15:21:05 +03:00
|
|
|
#include <linux/acpi.h>
|
2015-12-17 14:56:36 +03:00
|
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <linux/irqchip.h>
|
irqchip/mgigen: Add platform device driver for mbigen device
Mbigen means Message Based Interrupt Generator(MBIGEN).
Its a kind of interrupt controller that collects
the interrupts from external devices and generate msi interrupt.
Mbigen is applied to reduce the number of wire connected interrupts.
As the peripherals increasing, the interrupts lines needed is
increasing much, especially on the Arm64 server SOC.
Therefore, the interrupt pin in GIC is not enough to cover so
many peripherals.
Mbigen is designed to fix this problem.
Mbigen chip locates in ITS or outside of ITS.
Mbigen chip hardware structure shows as below:
mbigen chip
|---------------------|-------------------|
mgn_node0 mgn_node1 mgn_node2
| |-------| |-------|------|
dev1 dev1 dev2 dev1 dev3 dev4
Each mbigen chip contains several mbigen nodes.
External devices can connect to mbigen node through wire connecting way.
Because a mbigen node only can support 128 interrupt maximum, depends
on the interrupt lines number of devices, a device can connects to one
more mbigen nodes.
Also, several different devices can connect to a same mbigen node.
When devices triggered interrupt,mbigen chip detects and collects
the interrupts and generates the MBI interrupts by writing the ITS
Translator register.
To simplify mbigen driver,I used a new conception--mbigen device.
Each mbigen device is initialized as a platform device.
Mbigen device presents the parts(register, pin definition etc.) in
mbigen chip corresponding to a peripheral device.
So from software view, the structure likes below
mbigen chip
|---------------------|-----------------|
mbigen device1 mbigen device2 mbigen device3
| | |
dev1 dev2 dev3
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Ma Jun <majun258@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2015-12-17 14:56:35 +03:00
|
|
|
#include <linux/module.h>
|
2015-12-17 14:56:36 +03:00
|
|
|
#include <linux/msi.h>
|
irqchip/mgigen: Add platform device driver for mbigen device
Mbigen means Message Based Interrupt Generator(MBIGEN).
Its a kind of interrupt controller that collects
the interrupts from external devices and generate msi interrupt.
Mbigen is applied to reduce the number of wire connected interrupts.
As the peripherals increasing, the interrupts lines needed is
increasing much, especially on the Arm64 server SOC.
Therefore, the interrupt pin in GIC is not enough to cover so
many peripherals.
Mbigen is designed to fix this problem.
Mbigen chip locates in ITS or outside of ITS.
Mbigen chip hardware structure shows as below:
mbigen chip
|---------------------|-------------------|
mgn_node0 mgn_node1 mgn_node2
| |-------| |-------|------|
dev1 dev1 dev2 dev1 dev3 dev4
Each mbigen chip contains several mbigen nodes.
External devices can connect to mbigen node through wire connecting way.
Because a mbigen node only can support 128 interrupt maximum, depends
on the interrupt lines number of devices, a device can connects to one
more mbigen nodes.
Also, several different devices can connect to a same mbigen node.
When devices triggered interrupt,mbigen chip detects and collects
the interrupts and generates the MBI interrupts by writing the ITS
Translator register.
To simplify mbigen driver,I used a new conception--mbigen device.
Each mbigen device is initialized as a platform device.
Mbigen device presents the parts(register, pin definition etc.) in
mbigen chip corresponding to a peripheral device.
So from software view, the structure likes below
mbigen chip
|---------------------|-----------------|
mbigen device1 mbigen device2 mbigen device3
| | |
dev1 dev2 dev3
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Ma Jun <majun258@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2015-12-17 14:56:35 +03:00
|
|
|
#include <linux/of_address.h>
|
|
|
|
#include <linux/of_irq.h>
|
|
|
|
#include <linux/of_platform.h>
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <linux/slab.h>
|
|
|
|
|
2015-12-17 14:56:36 +03:00
|
|
|
/* Interrupt numbers per mbigen node supported */
|
|
|
|
#define IRQS_PER_MBIGEN_NODE 128
|
|
|
|
|
|
|
|
/* 64 irqs (Pin0-pin63) are reserved for each mbigen chip */
|
|
|
|
#define RESERVED_IRQ_PER_MBIGEN_CHIP 64
|
|
|
|
|
|
|
|
/* The maximum IRQ pin number of mbigen chip(start from 0) */
|
|
|
|
#define MAXIMUM_IRQ_PIN_NUM 1407
|
|
|
|
|
2021-09-05 06:36:44 +03:00
|
|
|
/*
|
2015-12-17 14:56:36 +03:00
|
|
|
* In mbigen vector register
|
|
|
|
* bit[21:12]: event id value
|
|
|
|
* bit[11:0]: device id
|
|
|
|
*/
|
|
|
|
#define IRQ_EVENT_ID_SHIFT 12
|
|
|
|
#define IRQ_EVENT_ID_MASK 0x3ff
|
|
|
|
|
|
|
|
/* register range of each mbigen node */
|
|
|
|
#define MBIGEN_NODE_OFFSET 0x1000
|
|
|
|
|
|
|
|
/* offset of vector register in mbigen node */
|
|
|
|
#define REG_MBIGEN_VEC_OFFSET 0x200
|
|
|
|
|
2021-09-05 06:36:44 +03:00
|
|
|
/*
|
2015-12-17 14:56:37 +03:00
|
|
|
* offset of clear register in mbigen node
|
|
|
|
* This register is used to clear the status
|
|
|
|
* of interrupt
|
|
|
|
*/
|
|
|
|
#define REG_MBIGEN_CLEAR_OFFSET 0xa000
|
|
|
|
|
2021-09-05 06:36:44 +03:00
|
|
|
/*
|
2015-12-17 14:56:37 +03:00
|
|
|
* offset of interrupt type register
|
|
|
|
* This register is used to configure interrupt
|
|
|
|
* trigger type
|
|
|
|
*/
|
|
|
|
#define REG_MBIGEN_TYPE_OFFSET 0x0
|
|
|
|
|
irqchip/mgigen: Add platform device driver for mbigen device
Mbigen means Message Based Interrupt Generator(MBIGEN).
Its a kind of interrupt controller that collects
the interrupts from external devices and generate msi interrupt.
Mbigen is applied to reduce the number of wire connected interrupts.
As the peripherals increasing, the interrupts lines needed is
increasing much, especially on the Arm64 server SOC.
Therefore, the interrupt pin in GIC is not enough to cover so
many peripherals.
Mbigen is designed to fix this problem.
Mbigen chip locates in ITS or outside of ITS.
Mbigen chip hardware structure shows as below:
mbigen chip
|---------------------|-------------------|
mgn_node0 mgn_node1 mgn_node2
| |-------| |-------|------|
dev1 dev1 dev2 dev1 dev3 dev4
Each mbigen chip contains several mbigen nodes.
External devices can connect to mbigen node through wire connecting way.
Because a mbigen node only can support 128 interrupt maximum, depends
on the interrupt lines number of devices, a device can connects to one
more mbigen nodes.
Also, several different devices can connect to a same mbigen node.
When devices triggered interrupt,mbigen chip detects and collects
the interrupts and generates the MBI interrupts by writing the ITS
Translator register.
To simplify mbigen driver,I used a new conception--mbigen device.
Each mbigen device is initialized as a platform device.
Mbigen device presents the parts(register, pin definition etc.) in
mbigen chip corresponding to a peripheral device.
So from software view, the structure likes below
mbigen chip
|---------------------|-----------------|
mbigen device1 mbigen device2 mbigen device3
| | |
dev1 dev2 dev3
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Ma Jun <majun258@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2015-12-17 14:56:35 +03:00
|
|
|
/**
|
|
|
|
* struct mbigen_device - holds the information of mbigen device.
|
|
|
|
*
|
|
|
|
* @pdev: pointer to the platform device structure of mbigen chip.
|
|
|
|
* @base: mapped address of this mbigen chip.
|
|
|
|
*/
|
|
|
|
struct mbigen_device {
|
|
|
|
struct platform_device *pdev;
|
|
|
|
void __iomem *base;
|
|
|
|
};
|
|
|
|
|
2015-12-17 14:56:36 +03:00
|
|
|
static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
|
|
|
|
{
|
|
|
|
unsigned int nid, pin;
|
|
|
|
|
|
|
|
hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
|
|
|
|
nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
|
|
|
|
pin = hwirq % IRQS_PER_MBIGEN_NODE;
|
|
|
|
|
|
|
|
return pin * 4 + nid * MBIGEN_NODE_OFFSET
|
|
|
|
+ REG_MBIGEN_VEC_OFFSET;
|
|
|
|
}
|
|
|
|
|
2015-12-17 14:56:37 +03:00
|
|
|
static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
|
|
|
|
u32 *mask, u32 *addr)
|
|
|
|
{
|
|
|
|
unsigned int nid, irq_ofst, ofst;
|
|
|
|
|
|
|
|
hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
|
|
|
|
nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
|
|
|
|
irq_ofst = hwirq % IRQS_PER_MBIGEN_NODE;
|
|
|
|
|
|
|
|
*mask = 1 << (irq_ofst % 32);
|
|
|
|
ofst = irq_ofst / 32 * 4;
|
|
|
|
|
|
|
|
*addr = ofst + nid * MBIGEN_NODE_OFFSET
|
|
|
|
+ REG_MBIGEN_TYPE_OFFSET;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
|
|
|
|
u32 *mask, u32 *addr)
|
|
|
|
{
|
2017-05-12 06:55:28 +03:00
|
|
|
unsigned int ofst = (hwirq / 32) * 4;
|
2015-12-17 14:56:37 +03:00
|
|
|
|
|
|
|
*mask = 1 << (hwirq % 32);
|
|
|
|
*addr = ofst + REG_MBIGEN_CLEAR_OFFSET;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mbigen_eoi_irq(struct irq_data *data)
|
|
|
|
{
|
|
|
|
void __iomem *base = data->chip_data;
|
|
|
|
u32 mask, addr;
|
|
|
|
|
|
|
|
get_mbigen_clear_reg(data->hwirq, &mask, &addr);
|
|
|
|
|
|
|
|
writel_relaxed(mask, base + addr);
|
|
|
|
|
|
|
|
irq_chip_eoi_parent(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mbigen_set_type(struct irq_data *data, unsigned int type)
|
|
|
|
{
|
|
|
|
void __iomem *base = data->chip_data;
|
|
|
|
u32 mask, addr, val;
|
|
|
|
|
|
|
|
if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
get_mbigen_type_reg(data->hwirq, &mask, &addr);
|
|
|
|
|
|
|
|
val = readl_relaxed(base + addr);
|
|
|
|
|
|
|
|
if (type == IRQ_TYPE_LEVEL_HIGH)
|
|
|
|
val |= mask;
|
|
|
|
else
|
|
|
|
val &= ~mask;
|
|
|
|
|
|
|
|
writel_relaxed(val, base + addr);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-12-17 14:56:36 +03:00
|
|
|
static struct irq_chip mbigen_irq_chip = {
|
|
|
|
.name = "mbigen-v2",
|
2015-12-17 14:56:37 +03:00
|
|
|
.irq_mask = irq_chip_mask_parent,
|
|
|
|
.irq_unmask = irq_chip_unmask_parent,
|
|
|
|
.irq_eoi = mbigen_eoi_irq,
|
|
|
|
.irq_set_type = mbigen_set_type,
|
|
|
|
.irq_set_affinity = irq_chip_set_affinity_parent,
|
2015-12-17 14:56:36 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static void mbigen_write_msg(struct msi_desc *desc, struct msi_msg *msg)
|
|
|
|
{
|
|
|
|
struct irq_data *d = irq_get_irq_data(desc->irq);
|
|
|
|
void __iomem *base = d->chip_data;
|
|
|
|
u32 val;
|
|
|
|
|
2019-03-20 21:54:21 +03:00
|
|
|
if (!msg->address_lo && !msg->address_hi)
|
|
|
|
return;
|
|
|
|
|
2015-12-17 14:56:36 +03:00
|
|
|
base += get_mbigen_vec_reg(d->hwirq);
|
|
|
|
val = readl_relaxed(base);
|
|
|
|
|
|
|
|
val &= ~(IRQ_EVENT_ID_MASK << IRQ_EVENT_ID_SHIFT);
|
|
|
|
val |= (msg->data << IRQ_EVENT_ID_SHIFT);
|
|
|
|
|
|
|
|
/* The address of doorbell is encoded in mbigen register by default
|
|
|
|
* So,we don't need to program the doorbell address at here
|
|
|
|
*/
|
|
|
|
writel_relaxed(val, base);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mbigen_domain_translate(struct irq_domain *d,
|
|
|
|
struct irq_fwspec *fwspec,
|
|
|
|
unsigned long *hwirq,
|
|
|
|
unsigned int *type)
|
|
|
|
{
|
irqchip/mbigen: Add ACPI support
With the preparation of platform msi support and interrupt producer
in commit d44fa3d46079 ("ACPI: Add support for ResourceSource/IRQ
domain mapping"), we can add mbigen ACPI support now.
Now that the major framework changes are ready, we just need to add
the ACPI probe code which creates the irqdomain for devices connecting
to it.
In order to create the irqdomain, we need to know the number of hw
irqs as input which is provided by mbigen. In DT case, we are using
"num-pins" property to describe it, and we will take advantage of
that too using _DSD in ACPI as there is no standard way of describe
it in ACPI way, also according to the _DSD rule described in
Documentation/acpi/DSD-properties-rules.txt, it doesn't break
the rules.
The DSDT is represented as below:
For mbigen,
Device(MBI0) {
Name(_HID, "HISI0152")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xa0080000, 0x10000)
})
Name(_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"num-pins", 378}
}
})
}
For devices,
Device(SAS0) {
Name(_HID, "HISIxxxx")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xb0030000, 0x10000)
Interrupt(ResourceConsumer,..., "\_SB.MBI0") {12, ...}
})
}
So for the devices connected to the mbigen, as we clearly say that
it refers to a specific interrupt controller (mbigen), we can get
the virq from mbigen's irqdomain once it's created successfully.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: MaJun <majun258@huawei.com>
Cc: Al Stone <ahs3@redhat.com>
Cc: Darren Hart <dvhart@infradead.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2017-03-28 15:21:05 +03:00
|
|
|
if (is_of_node(fwspec->fwnode) || is_acpi_device_node(fwspec->fwnode)) {
|
2015-12-17 14:56:36 +03:00
|
|
|
if (fwspec->param_count != 2)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if ((fwspec->param[0] > MAXIMUM_IRQ_PIN_NUM) ||
|
|
|
|
(fwspec->param[0] < RESERVED_IRQ_PER_MBIGEN_CHIP))
|
|
|
|
return -EINVAL;
|
|
|
|
else
|
|
|
|
*hwirq = fwspec->param[0];
|
|
|
|
|
|
|
|
/* If there is no valid irq type, just use the default type */
|
|
|
|
if ((fwspec->param[1] == IRQ_TYPE_EDGE_RISING) ||
|
|
|
|
(fwspec->param[1] == IRQ_TYPE_LEVEL_HIGH))
|
|
|
|
*type = fwspec->param[1];
|
|
|
|
else
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mbigen_irq_domain_alloc(struct irq_domain *domain,
|
|
|
|
unsigned int virq,
|
|
|
|
unsigned int nr_irqs,
|
|
|
|
void *args)
|
|
|
|
{
|
|
|
|
struct irq_fwspec *fwspec = args;
|
|
|
|
irq_hw_number_t hwirq;
|
|
|
|
unsigned int type;
|
|
|
|
struct mbigen_device *mgn_chip;
|
|
|
|
int i, err;
|
|
|
|
|
|
|
|
err = mbigen_domain_translate(domain, fwspec, &hwirq, &type);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
err = platform_msi_domain_alloc(domain, virq, nr_irqs);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
mgn_chip = platform_msi_get_host_data(domain);
|
|
|
|
|
|
|
|
for (i = 0; i < nr_irqs; i++)
|
|
|
|
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
|
|
|
|
&mbigen_irq_chip, mgn_chip->base);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-08 14:43:52 +03:00
|
|
|
static void mbigen_irq_domain_free(struct irq_domain *domain, unsigned int virq,
|
|
|
|
unsigned int nr_irqs)
|
|
|
|
{
|
|
|
|
platform_msi_domain_free(domain, virq, nr_irqs);
|
|
|
|
}
|
|
|
|
|
2017-06-02 11:20:55 +03:00
|
|
|
static const struct irq_domain_ops mbigen_domain_ops = {
|
2015-12-17 14:56:36 +03:00
|
|
|
.translate = mbigen_domain_translate,
|
|
|
|
.alloc = mbigen_irq_domain_alloc,
|
2020-04-08 14:43:52 +03:00
|
|
|
.free = mbigen_irq_domain_free,
|
2015-12-17 14:56:36 +03:00
|
|
|
};
|
|
|
|
|
2017-03-07 15:40:09 +03:00
|
|
|
static int mbigen_of_create_domain(struct platform_device *pdev,
|
|
|
|
struct mbigen_device *mgn_chip)
|
irqchip/mgigen: Add platform device driver for mbigen device
Mbigen means Message Based Interrupt Generator(MBIGEN).
Its a kind of interrupt controller that collects
the interrupts from external devices and generate msi interrupt.
Mbigen is applied to reduce the number of wire connected interrupts.
As the peripherals increasing, the interrupts lines needed is
increasing much, especially on the Arm64 server SOC.
Therefore, the interrupt pin in GIC is not enough to cover so
many peripherals.
Mbigen is designed to fix this problem.
Mbigen chip locates in ITS or outside of ITS.
Mbigen chip hardware structure shows as below:
mbigen chip
|---------------------|-------------------|
mgn_node0 mgn_node1 mgn_node2
| |-------| |-------|------|
dev1 dev1 dev2 dev1 dev3 dev4
Each mbigen chip contains several mbigen nodes.
External devices can connect to mbigen node through wire connecting way.
Because a mbigen node only can support 128 interrupt maximum, depends
on the interrupt lines number of devices, a device can connects to one
more mbigen nodes.
Also, several different devices can connect to a same mbigen node.
When devices triggered interrupt,mbigen chip detects and collects
the interrupts and generates the MBI interrupts by writing the ITS
Translator register.
To simplify mbigen driver,I used a new conception--mbigen device.
Each mbigen device is initialized as a platform device.
Mbigen device presents the parts(register, pin definition etc.) in
mbigen chip corresponding to a peripheral device.
So from software view, the structure likes below
mbigen chip
|---------------------|-----------------|
mbigen device1 mbigen device2 mbigen device3
| | |
dev1 dev2 dev3
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Ma Jun <majun258@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2015-12-17 14:56:35 +03:00
|
|
|
{
|
2017-03-07 15:40:09 +03:00
|
|
|
struct device *parent;
|
2016-03-17 11:34:01 +03:00
|
|
|
struct platform_device *child;
|
2015-12-17 14:56:36 +03:00
|
|
|
struct irq_domain *domain;
|
2016-03-17 11:34:01 +03:00
|
|
|
struct device_node *np;
|
2015-12-17 14:56:36 +03:00
|
|
|
u32 num_pins;
|
irqchip/mgigen: Add platform device driver for mbigen device
Mbigen means Message Based Interrupt Generator(MBIGEN).
Its a kind of interrupt controller that collects
the interrupts from external devices and generate msi interrupt.
Mbigen is applied to reduce the number of wire connected interrupts.
As the peripherals increasing, the interrupts lines needed is
increasing much, especially on the Arm64 server SOC.
Therefore, the interrupt pin in GIC is not enough to cover so
many peripherals.
Mbigen is designed to fix this problem.
Mbigen chip locates in ITS or outside of ITS.
Mbigen chip hardware structure shows as below:
mbigen chip
|---------------------|-------------------|
mgn_node0 mgn_node1 mgn_node2
| |-------| |-------|------|
dev1 dev1 dev2 dev1 dev3 dev4
Each mbigen chip contains several mbigen nodes.
External devices can connect to mbigen node through wire connecting way.
Because a mbigen node only can support 128 interrupt maximum, depends
on the interrupt lines number of devices, a device can connects to one
more mbigen nodes.
Also, several different devices can connect to a same mbigen node.
When devices triggered interrupt,mbigen chip detects and collects
the interrupts and generates the MBI interrupts by writing the ITS
Translator register.
To simplify mbigen driver,I used a new conception--mbigen device.
Each mbigen device is initialized as a platform device.
Mbigen device presents the parts(register, pin definition etc.) in
mbigen chip corresponding to a peripheral device.
So from software view, the structure likes below
mbigen chip
|---------------------|-----------------|
mbigen device1 mbigen device2 mbigen device3
| | |
dev1 dev2 dev3
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Ma Jun <majun258@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2015-12-17 14:56:35 +03:00
|
|
|
|
2016-03-17 11:34:01 +03:00
|
|
|
for_each_child_of_node(pdev->dev.of_node, np) {
|
|
|
|
if (!of_property_read_bool(np, "interrupt-controller"))
|
|
|
|
continue;
|
2015-12-17 14:56:36 +03:00
|
|
|
|
2016-03-17 11:34:01 +03:00
|
|
|
parent = platform_bus_type.dev_root;
|
|
|
|
child = of_platform_device_create(np, NULL, parent);
|
2019-07-23 13:39:10 +03:00
|
|
|
if (!child) {
|
|
|
|
of_node_put(np);
|
2016-04-04 14:17:36 +03:00
|
|
|
return -ENOMEM;
|
2019-07-23 13:39:10 +03:00
|
|
|
}
|
2015-12-17 14:56:36 +03:00
|
|
|
|
2016-03-17 11:34:01 +03:00
|
|
|
if (of_property_read_u32(child->dev.of_node, "num-pins",
|
|
|
|
&num_pins) < 0) {
|
|
|
|
dev_err(&pdev->dev, "No num-pins property\n");
|
2019-07-23 13:39:10 +03:00
|
|
|
of_node_put(np);
|
2016-03-17 11:34:01 +03:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
domain = platform_msi_create_device_domain(&child->dev, num_pins,
|
|
|
|
mbigen_write_msg,
|
|
|
|
&mbigen_domain_ops,
|
|
|
|
mgn_chip);
|
2019-07-23 13:39:10 +03:00
|
|
|
if (!domain) {
|
|
|
|
of_node_put(np);
|
2016-03-17 11:34:01 +03:00
|
|
|
return -ENOMEM;
|
2019-07-23 13:39:10 +03:00
|
|
|
}
|
2016-03-17 11:34:01 +03:00
|
|
|
}
|
2015-12-17 14:56:36 +03:00
|
|
|
|
2017-03-07 15:40:09 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
irqchip/mbigen: Add ACPI support
With the preparation of platform msi support and interrupt producer
in commit d44fa3d46079 ("ACPI: Add support for ResourceSource/IRQ
domain mapping"), we can add mbigen ACPI support now.
Now that the major framework changes are ready, we just need to add
the ACPI probe code which creates the irqdomain for devices connecting
to it.
In order to create the irqdomain, we need to know the number of hw
irqs as input which is provided by mbigen. In DT case, we are using
"num-pins" property to describe it, and we will take advantage of
that too using _DSD in ACPI as there is no standard way of describe
it in ACPI way, also according to the _DSD rule described in
Documentation/acpi/DSD-properties-rules.txt, it doesn't break
the rules.
The DSDT is represented as below:
For mbigen,
Device(MBI0) {
Name(_HID, "HISI0152")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xa0080000, 0x10000)
})
Name(_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"num-pins", 378}
}
})
}
For devices,
Device(SAS0) {
Name(_HID, "HISIxxxx")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xb0030000, 0x10000)
Interrupt(ResourceConsumer,..., "\_SB.MBI0") {12, ...}
})
}
So for the devices connected to the mbigen, as we clearly say that
it refers to a specific interrupt controller (mbigen), we can get
the virq from mbigen's irqdomain once it's created successfully.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: MaJun <majun258@huawei.com>
Cc: Al Stone <ahs3@redhat.com>
Cc: Darren Hart <dvhart@infradead.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2017-03-28 15:21:05 +03:00
|
|
|
#ifdef CONFIG_ACPI
|
2021-05-19 08:04:55 +03:00
|
|
|
static const struct acpi_device_id mbigen_acpi_match[] = {
|
|
|
|
{ "HISI0152", 0 },
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(acpi, mbigen_acpi_match);
|
|
|
|
|
irqchip/mbigen: Add ACPI support
With the preparation of platform msi support and interrupt producer
in commit d44fa3d46079 ("ACPI: Add support for ResourceSource/IRQ
domain mapping"), we can add mbigen ACPI support now.
Now that the major framework changes are ready, we just need to add
the ACPI probe code which creates the irqdomain for devices connecting
to it.
In order to create the irqdomain, we need to know the number of hw
irqs as input which is provided by mbigen. In DT case, we are using
"num-pins" property to describe it, and we will take advantage of
that too using _DSD in ACPI as there is no standard way of describe
it in ACPI way, also according to the _DSD rule described in
Documentation/acpi/DSD-properties-rules.txt, it doesn't break
the rules.
The DSDT is represented as below:
For mbigen,
Device(MBI0) {
Name(_HID, "HISI0152")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xa0080000, 0x10000)
})
Name(_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"num-pins", 378}
}
})
}
For devices,
Device(SAS0) {
Name(_HID, "HISIxxxx")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xb0030000, 0x10000)
Interrupt(ResourceConsumer,..., "\_SB.MBI0") {12, ...}
})
}
So for the devices connected to the mbigen, as we clearly say that
it refers to a specific interrupt controller (mbigen), we can get
the virq from mbigen's irqdomain once it's created successfully.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: MaJun <majun258@huawei.com>
Cc: Al Stone <ahs3@redhat.com>
Cc: Darren Hart <dvhart@infradead.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2017-03-28 15:21:05 +03:00
|
|
|
static int mbigen_acpi_create_domain(struct platform_device *pdev,
|
|
|
|
struct mbigen_device *mgn_chip)
|
|
|
|
{
|
|
|
|
struct irq_domain *domain;
|
|
|
|
u32 num_pins = 0;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "num-pins" is the total number of interrupt pins implemented in
|
|
|
|
* this mbigen instance, and mbigen is an interrupt controller
|
|
|
|
* connected to ITS converting wired interrupts into MSI, so we
|
|
|
|
* use "num-pins" to alloc MSI vectors which are needed by client
|
|
|
|
* devices connected to it.
|
|
|
|
*
|
|
|
|
* Here is the DSDT device node used for mbigen in firmware:
|
|
|
|
* Device(MBI0) {
|
|
|
|
* Name(_HID, "HISI0152")
|
|
|
|
* Name(_UID, Zero)
|
|
|
|
* Name(_CRS, ResourceTemplate() {
|
|
|
|
* Memory32Fixed(ReadWrite, 0xa0080000, 0x10000)
|
|
|
|
* })
|
|
|
|
*
|
|
|
|
* Name(_DSD, Package () {
|
|
|
|
* ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
|
|
|
* Package () {
|
|
|
|
* Package () {"num-pins", 378}
|
|
|
|
* }
|
|
|
|
* })
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
ret = device_property_read_u32(&pdev->dev, "num-pins", &num_pins);
|
|
|
|
if (ret || num_pins == 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
domain = platform_msi_create_device_domain(&pdev->dev, num_pins,
|
|
|
|
mbigen_write_msg,
|
|
|
|
&mbigen_domain_ops,
|
|
|
|
mgn_chip);
|
|
|
|
if (!domain)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline int mbigen_acpi_create_domain(struct platform_device *pdev,
|
|
|
|
struct mbigen_device *mgn_chip)
|
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-03-07 15:40:09 +03:00
|
|
|
static int mbigen_device_probe(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
struct mbigen_device *mgn_chip;
|
|
|
|
struct resource *res;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL);
|
|
|
|
if (!mgn_chip)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
mgn_chip->pdev = pdev;
|
|
|
|
|
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
2017-05-12 06:55:27 +03:00
|
|
|
if (!res)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2017-05-12 06:55:26 +03:00
|
|
|
mgn_chip->base = devm_ioremap(&pdev->dev, res->start,
|
|
|
|
resource_size(res));
|
|
|
|
if (!mgn_chip->base) {
|
|
|
|
dev_err(&pdev->dev, "failed to ioremap %pR\n", res);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2017-03-07 15:40:09 +03:00
|
|
|
|
irqchip/mbigen: Add ACPI support
With the preparation of platform msi support and interrupt producer
in commit d44fa3d46079 ("ACPI: Add support for ResourceSource/IRQ
domain mapping"), we can add mbigen ACPI support now.
Now that the major framework changes are ready, we just need to add
the ACPI probe code which creates the irqdomain for devices connecting
to it.
In order to create the irqdomain, we need to know the number of hw
irqs as input which is provided by mbigen. In DT case, we are using
"num-pins" property to describe it, and we will take advantage of
that too using _DSD in ACPI as there is no standard way of describe
it in ACPI way, also according to the _DSD rule described in
Documentation/acpi/DSD-properties-rules.txt, it doesn't break
the rules.
The DSDT is represented as below:
For mbigen,
Device(MBI0) {
Name(_HID, "HISI0152")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xa0080000, 0x10000)
})
Name(_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"num-pins", 378}
}
})
}
For devices,
Device(SAS0) {
Name(_HID, "HISIxxxx")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xb0030000, 0x10000)
Interrupt(ResourceConsumer,..., "\_SB.MBI0") {12, ...}
})
}
So for the devices connected to the mbigen, as we clearly say that
it refers to a specific interrupt controller (mbigen), we can get
the virq from mbigen's irqdomain once it's created successfully.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: MaJun <majun258@huawei.com>
Cc: Al Stone <ahs3@redhat.com>
Cc: Darren Hart <dvhart@infradead.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2017-03-28 15:21:05 +03:00
|
|
|
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
|
|
|
|
err = mbigen_of_create_domain(pdev, mgn_chip);
|
|
|
|
else if (ACPI_COMPANION(&pdev->dev))
|
|
|
|
err = mbigen_acpi_create_domain(pdev, mgn_chip);
|
|
|
|
else
|
|
|
|
err = -EINVAL;
|
|
|
|
|
|
|
|
if (err) {
|
2019-06-18 12:15:05 +03:00
|
|
|
dev_err(&pdev->dev, "Failed to create mbi-gen irqdomain\n");
|
2017-03-07 15:40:09 +03:00
|
|
|
return err;
|
irqchip/mbigen: Add ACPI support
With the preparation of platform msi support and interrupt producer
in commit d44fa3d46079 ("ACPI: Add support for ResourceSource/IRQ
domain mapping"), we can add mbigen ACPI support now.
Now that the major framework changes are ready, we just need to add
the ACPI probe code which creates the irqdomain for devices connecting
to it.
In order to create the irqdomain, we need to know the number of hw
irqs as input which is provided by mbigen. In DT case, we are using
"num-pins" property to describe it, and we will take advantage of
that too using _DSD in ACPI as there is no standard way of describe
it in ACPI way, also according to the _DSD rule described in
Documentation/acpi/DSD-properties-rules.txt, it doesn't break
the rules.
The DSDT is represented as below:
For mbigen,
Device(MBI0) {
Name(_HID, "HISI0152")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xa0080000, 0x10000)
})
Name(_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"num-pins", 378}
}
})
}
For devices,
Device(SAS0) {
Name(_HID, "HISIxxxx")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xb0030000, 0x10000)
Interrupt(ResourceConsumer,..., "\_SB.MBI0") {12, ...}
})
}
So for the devices connected to the mbigen, as we clearly say that
it refers to a specific interrupt controller (mbigen), we can get
the virq from mbigen's irqdomain once it's created successfully.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: MaJun <majun258@huawei.com>
Cc: Al Stone <ahs3@redhat.com>
Cc: Darren Hart <dvhart@infradead.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2017-03-28 15:21:05 +03:00
|
|
|
}
|
2017-03-07 15:40:09 +03:00
|
|
|
|
irqchip/mgigen: Add platform device driver for mbigen device
Mbigen means Message Based Interrupt Generator(MBIGEN).
Its a kind of interrupt controller that collects
the interrupts from external devices and generate msi interrupt.
Mbigen is applied to reduce the number of wire connected interrupts.
As the peripherals increasing, the interrupts lines needed is
increasing much, especially on the Arm64 server SOC.
Therefore, the interrupt pin in GIC is not enough to cover so
many peripherals.
Mbigen is designed to fix this problem.
Mbigen chip locates in ITS or outside of ITS.
Mbigen chip hardware structure shows as below:
mbigen chip
|---------------------|-------------------|
mgn_node0 mgn_node1 mgn_node2
| |-------| |-------|------|
dev1 dev1 dev2 dev1 dev3 dev4
Each mbigen chip contains several mbigen nodes.
External devices can connect to mbigen node through wire connecting way.
Because a mbigen node only can support 128 interrupt maximum, depends
on the interrupt lines number of devices, a device can connects to one
more mbigen nodes.
Also, several different devices can connect to a same mbigen node.
When devices triggered interrupt,mbigen chip detects and collects
the interrupts and generates the MBI interrupts by writing the ITS
Translator register.
To simplify mbigen driver,I used a new conception--mbigen device.
Each mbigen device is initialized as a platform device.
Mbigen device presents the parts(register, pin definition etc.) in
mbigen chip corresponding to a peripheral device.
So from software view, the structure likes below
mbigen chip
|---------------------|-----------------|
mbigen device1 mbigen device2 mbigen device3
| | |
dev1 dev2 dev3
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Ma Jun <majun258@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2015-12-17 14:56:35 +03:00
|
|
|
platform_set_drvdata(pdev, mgn_chip);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct of_device_id mbigen_of_match[] = {
|
|
|
|
{ .compatible = "hisilicon,mbigen-v2" },
|
|
|
|
{ /* END */ }
|
|
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(of, mbigen_of_match);
|
|
|
|
|
|
|
|
static struct platform_driver mbigen_platform_driver = {
|
|
|
|
.driver = {
|
|
|
|
.name = "Hisilicon MBIGEN-V2",
|
|
|
|
.of_match_table = mbigen_of_match,
|
irqchip/mbigen: Add ACPI support
With the preparation of platform msi support and interrupt producer
in commit d44fa3d46079 ("ACPI: Add support for ResourceSource/IRQ
domain mapping"), we can add mbigen ACPI support now.
Now that the major framework changes are ready, we just need to add
the ACPI probe code which creates the irqdomain for devices connecting
to it.
In order to create the irqdomain, we need to know the number of hw
irqs as input which is provided by mbigen. In DT case, we are using
"num-pins" property to describe it, and we will take advantage of
that too using _DSD in ACPI as there is no standard way of describe
it in ACPI way, also according to the _DSD rule described in
Documentation/acpi/DSD-properties-rules.txt, it doesn't break
the rules.
The DSDT is represented as below:
For mbigen,
Device(MBI0) {
Name(_HID, "HISI0152")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xa0080000, 0x10000)
})
Name(_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"num-pins", 378}
}
})
}
For devices,
Device(SAS0) {
Name(_HID, "HISIxxxx")
Name(_UID, Zero)
Name(_CRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xb0030000, 0x10000)
Interrupt(ResourceConsumer,..., "\_SB.MBI0") {12, ...}
})
}
So for the devices connected to the mbigen, as we clearly say that
it refers to a specific interrupt controller (mbigen), we can get
the virq from mbigen's irqdomain once it's created successfully.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: MaJun <majun258@huawei.com>
Cc: Al Stone <ahs3@redhat.com>
Cc: Darren Hart <dvhart@infradead.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2017-03-28 15:21:05 +03:00
|
|
|
.acpi_match_table = ACPI_PTR(mbigen_acpi_match),
|
irqchip/mbigen: Set driver .suppress_bind_attrs to avoid remove problems
The following crash can be seen for setting
CONFIG_DEBUG_TEST_DRIVER_REMOVE=y for DT FW (which some people still use):
Hisilicon MBIGEN-V2 60080000.interrupt-controller: Failed to create mbi-gen irqdomain
Hisilicon MBIGEN-V2: probe of 60080000.interrupt-controller failed with error -12
[...]
Unable to handle kernel paging request at virtual address 0000000000005008
Mem abort info:
ESR = 0x96000004
EC = 0x25: DABT (current EL), IL = 32 bits
SET = 0, FnV = 0
EA = 0, S1PTW = 0
Data abort info:
ISV = 0, ISS = 0x00000004
CM = 0, WnR = 0
user pgtable: 4k pages, 48-bit VAs, pgdp=0000041fb9990000
[0000000000005008] pgd=0000000000000000
Internal error: Oops: 96000004 [#1] PREEMPT SMP
Modules linked in:
CPU: 7 PID: 1 Comm: swapper/0 Not tainted 5.5.0-rc6-00002-g3fc42638a506-dirty #1622
Hardware name: Huawei Taishan 2280 /D05, BIOS Hisilicon D05 IT21 Nemo 2.0 RC0 04/18/2018
pstate: 40000085 (nZcv daIf -PAN -UAO)
pc : mbigen_set_type+0x38/0x60
lr : __irq_set_trigger+0x6c/0x188
sp : ffff800014b4b400
x29: ffff800014b4b400 x28: 0000000000000007
x27: 0000000000000000 x26: 0000000000000000
x25: ffff041fd83bd0d4 x24: ffff041fd83bd188
x23: 0000000000000000 x22: ffff80001193ce00
x21: 0000000000000004 x20: 0000000000000000
x19: ffff041fd83bd000 x18: ffffffffffffffff
x17: 0000000000000000 x16: 0000000000000000
x15: ffff8000119098c8 x14: ffff041fb94ec91c
x13: ffff041fb94ec1a1 x12: 0000000000000030
x11: 0101010101010101 x10: 0000000000000040
x9 : 0000000000000000 x8 : ffff041fb98c6680
x7 : ffff800014b4b380 x6 : ffff041fd81636c8
x5 : 0000000000000000 x4 : 000000000000025f
x3 : 0000000000005000 x2 : 0000000000005008
x1 : 0000000000000004 x0 : 0000000080000000
Call trace:
mbigen_set_type+0x38/0x60
__setup_irq+0x744/0x900
request_threaded_irq+0xe0/0x198
pcie_pme_probe+0x98/0x118
pcie_port_probe_service+0x38/0x78
really_probe+0xa0/0x3e0
driver_probe_device+0x58/0x100
__device_attach_driver+0x90/0xb0
bus_for_each_drv+0x64/0xc8
__device_attach+0xd8/0x138
device_initial_probe+0x10/0x18
bus_probe_device+0x90/0x98
device_add+0x4c4/0x770
device_register+0x1c/0x28
pcie_port_device_register+0x1e4/0x4f0
pcie_portdrv_probe+0x34/0xd8
local_pci_probe+0x3c/0xa0
pci_device_probe+0x128/0x1c0
really_probe+0xa0/0x3e0
driver_probe_device+0x58/0x100
__device_attach_driver+0x90/0xb0
bus_for_each_drv+0x64/0xc8
__device_attach+0xd8/0x138
device_attach+0x10/0x18
pci_bus_add_device+0x4c/0xb8
pci_bus_add_devices+0x38/0x88
pci_host_probe+0x3c/0xc0
pci_host_common_probe+0xf0/0x208
hisi_pcie_almost_ecam_probe+0x24/0x30
platform_drv_probe+0x50/0xa0
really_probe+0xa0/0x3e0
driver_probe_device+0x58/0x100
device_driver_attach+0x6c/0x90
__driver_attach+0x84/0xc8
bus_for_each_dev+0x74/0xc8
driver_attach+0x20/0x28
bus_add_driver+0x148/0x1f0
driver_register+0x60/0x110
__platform_driver_register+0x40/0x48
hisi_pcie_almost_ecam_driver_init+0x1c/0x24
The specific problem here is that the mbigen driver real probe has failed
as the mbigen_of_create_domain()->of_platform_device_create() call fails,
the reason for that being that we never destroyed the platform device
created during the remove test dry run and there is some conflict.
Since we generally would never want to unbind this driver, and to save
adding a driver tear down path for that, just set the driver
.suppress_bind_attrs member to avoid this possibility.
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Hanjun Guo <guohanjun@huawei.com>
Link: https://lore.kernel.org/r/1579196323-180137-1-git-send-email-john.garry@huawei.com
2020-01-16 20:38:43 +03:00
|
|
|
.suppress_bind_attrs = true,
|
irqchip/mgigen: Add platform device driver for mbigen device
Mbigen means Message Based Interrupt Generator(MBIGEN).
Its a kind of interrupt controller that collects
the interrupts from external devices and generate msi interrupt.
Mbigen is applied to reduce the number of wire connected interrupts.
As the peripherals increasing, the interrupts lines needed is
increasing much, especially on the Arm64 server SOC.
Therefore, the interrupt pin in GIC is not enough to cover so
many peripherals.
Mbigen is designed to fix this problem.
Mbigen chip locates in ITS or outside of ITS.
Mbigen chip hardware structure shows as below:
mbigen chip
|---------------------|-------------------|
mgn_node0 mgn_node1 mgn_node2
| |-------| |-------|------|
dev1 dev1 dev2 dev1 dev3 dev4
Each mbigen chip contains several mbigen nodes.
External devices can connect to mbigen node through wire connecting way.
Because a mbigen node only can support 128 interrupt maximum, depends
on the interrupt lines number of devices, a device can connects to one
more mbigen nodes.
Also, several different devices can connect to a same mbigen node.
When devices triggered interrupt,mbigen chip detects and collects
the interrupts and generates the MBI interrupts by writing the ITS
Translator register.
To simplify mbigen driver,I used a new conception--mbigen device.
Each mbigen device is initialized as a platform device.
Mbigen device presents the parts(register, pin definition etc.) in
mbigen chip corresponding to a peripheral device.
So from software view, the structure likes below
mbigen chip
|---------------------|-----------------|
mbigen device1 mbigen device2 mbigen device3
| | |
dev1 dev2 dev3
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Ma Jun <majun258@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2015-12-17 14:56:35 +03:00
|
|
|
},
|
|
|
|
.probe = mbigen_device_probe,
|
|
|
|
};
|
|
|
|
|
|
|
|
module_platform_driver(mbigen_platform_driver);
|
|
|
|
|
|
|
|
MODULE_AUTHOR("Jun Ma <majun258@huawei.com>");
|
|
|
|
MODULE_AUTHOR("Yun Wu <wuyun.wu@huawei.com>");
|
|
|
|
MODULE_LICENSE("GPL");
|
2021-03-30 09:46:20 +03:00
|
|
|
MODULE_DESCRIPTION("HiSilicon MBI Generator driver");
|