Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fd100dab authored by Minghuan Lian's avatar Minghuan Lian Committed by Marc Zyngier
Browse files

irqchip/ls-scfg-msi: Add LS1043a v1.1 MSI support



A MSI controller of LS1043a v1.0 only includes one MSIR and
is assigned one GIC interrupt. In order to support affinity,
LS1043a v1.1 MSI is assigned 4 MSIRs and 4 GIC interrupts.
But the MSIR has the different offset and only supports 8 MSIs.
The bits between variable bit_start and bit_end in structure
ls_scfg_msir are used to show 8 MSI interrupts. msir_irqs and
msir_base are added to describe the difference of MSI between
LS1043a v1.1 and other SoCs.

Acked-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarMinghuan Lian <Minghuan.Lian@nxp.com>
Signed-off-by: default avatarHou Zhiqiang <Zhiqiang.Hou@nxp.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent 4dd5da65
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -7,6 +7,7 @@ Required properties:
              "fsl,ls1021a-msi"
              "fsl,ls1021a-msi"
              "fsl,ls1043a-msi"
              "fsl,ls1043a-msi"
              "fsl,ls1046a-msi"
              "fsl,ls1046a-msi"
              "fsl,ls1043a-v1.1-msi"
- msi-controller: indicates that this is a PCIe MSI controller node
- msi-controller: indicates that this is a PCIe MSI controller node
- reg: physical base address of the controller and length of memory mapped.
- reg: physical base address of the controller and length of memory mapped.
- interrupts: an interrupt to the parent interrupt controller.
- interrupts: an interrupt to the parent interrupt controller.
+39 −6
Original line number Original line Diff line number Diff line
@@ -25,14 +25,21 @@
#define MSI_IRQS_PER_MSIR	32
#define MSI_IRQS_PER_MSIR	32
#define MSI_MSIR_OFFSET		4
#define MSI_MSIR_OFFSET		4


#define MSI_LS1043V1_1_IRQS_PER_MSIR	8
#define MSI_LS1043V1_1_MSIR_OFFSET	0x10

struct ls_scfg_msi_cfg {
struct ls_scfg_msi_cfg {
	u32 ibs_shift; /* Shift of interrupt bit select */
	u32 ibs_shift; /* Shift of interrupt bit select */
	u32 msir_irqs; /* The irq number per MSIR */
	u32 msir_base; /* The base address of MSIR */
};
};


struct ls_scfg_msir {
struct ls_scfg_msir {
	struct ls_scfg_msi *msi_data;
	struct ls_scfg_msi *msi_data;
	unsigned int index;
	unsigned int index;
	unsigned int gic_irq;
	unsigned int gic_irq;
	unsigned int bit_start;
	unsigned int bit_end;
	void __iomem *reg;
	void __iomem *reg;
};
};


@@ -140,13 +147,18 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
	struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
	struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
	struct ls_scfg_msi *msi_data = msir->msi_data;
	struct ls_scfg_msi *msi_data = msir->msi_data;
	unsigned long val;
	unsigned long val;
	int pos, virq, hwirq;
	int pos, size, virq, hwirq;


	chained_irq_enter(irq_desc_get_chip(desc), desc);
	chained_irq_enter(irq_desc_get_chip(desc), desc);


	val = ioread32be(msir->reg);
	val = ioread32be(msir->reg);
	for_each_set_bit(pos, &val, MSI_IRQS_PER_MSIR) {

		hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index;
	pos = msir->bit_start;
	size = msir->bit_end + 1;

	for_each_set_bit_from(pos, &val, size) {
		hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) |
			msir->index;
		virq = irq_find_mapping(msi_data->parent, hwirq);
		virq = irq_find_mapping(msi_data->parent, hwirq);
		if (virq)
		if (virq)
			generic_handle_irq(virq);
			generic_handle_irq(virq);
@@ -193,14 +205,24 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index)
	msir->index = index;
	msir->index = index;
	msir->msi_data = msi_data;
	msir->msi_data = msi_data;
	msir->gic_irq = virq;
	msir->gic_irq = virq;
	msir->reg = msi_data->regs + MSI_MSIR_OFFSET + 4 * index;
	msir->reg = msi_data->regs + msi_data->cfg->msir_base + 4 * index;

	if (msi_data->cfg->msir_irqs == MSI_LS1043V1_1_IRQS_PER_MSIR) {
		msir->bit_start = 32 - ((msir->index + 1) *
				  MSI_LS1043V1_1_IRQS_PER_MSIR);
		msir->bit_end = msir->bit_start +
				MSI_LS1043V1_1_IRQS_PER_MSIR - 1;
	} else {
		msir->bit_start = 0;
		msir->bit_end = msi_data->cfg->msir_irqs - 1;
	}


	irq_set_chained_handler_and_data(msir->gic_irq,
	irq_set_chained_handler_and_data(msir->gic_irq,
					 ls_scfg_msi_irq_handler,
					 ls_scfg_msi_irq_handler,
					 msir);
					 msir);


	/* Release the hwirqs corresponding to this MSIR */
	/* Release the hwirqs corresponding to this MSIR */
	for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
	for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
		hwirq = i << msi_data->cfg->ibs_shift | msir->index;
		hwirq = i << msi_data->cfg->ibs_shift | msir->index;
		bitmap_clear(msi_data->used, hwirq, 1);
		bitmap_clear(msi_data->used, hwirq, 1);
	}
	}
@@ -216,7 +238,7 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir)
	if (msir->gic_irq > 0)
	if (msir->gic_irq > 0)
		irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL);
		irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL);


	for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
	for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
		hwirq = i << msi_data->cfg->ibs_shift | msir->index;
		hwirq = i << msi_data->cfg->ibs_shift | msir->index;
		bitmap_set(msi_data->used, hwirq, 1);
		bitmap_set(msi_data->used, hwirq, 1);
	}
	}
@@ -226,10 +248,20 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir)


static struct ls_scfg_msi_cfg ls1021_msi_cfg = {
static struct ls_scfg_msi_cfg ls1021_msi_cfg = {
	.ibs_shift = 3,
	.ibs_shift = 3,
	.msir_irqs = MSI_IRQS_PER_MSIR,
	.msir_base = MSI_MSIR_OFFSET,
};
};


static struct ls_scfg_msi_cfg ls1046_msi_cfg = {
static struct ls_scfg_msi_cfg ls1046_msi_cfg = {
	.ibs_shift = 2,
	.ibs_shift = 2,
	.msir_irqs = MSI_IRQS_PER_MSIR,
	.msir_base = MSI_MSIR_OFFSET,
};

static struct ls_scfg_msi_cfg ls1043_v1_1_msi_cfg = {
	.ibs_shift = 2,
	.msir_irqs = MSI_LS1043V1_1_IRQS_PER_MSIR,
	.msir_base = MSI_LS1043V1_1_MSIR_OFFSET,
};
};


static const struct of_device_id ls_scfg_msi_id[] = {
static const struct of_device_id ls_scfg_msi_id[] = {
@@ -239,6 +271,7 @@ static const struct of_device_id ls_scfg_msi_id[] = {


	{ .compatible = "fsl,ls1021a-msi", .data = &ls1021_msi_cfg },
	{ .compatible = "fsl,ls1021a-msi", .data = &ls1021_msi_cfg },
	{ .compatible = "fsl,ls1043a-msi", .data = &ls1021_msi_cfg },
	{ .compatible = "fsl,ls1043a-msi", .data = &ls1021_msi_cfg },
	{ .compatible = "fsl,ls1043a-v1.1-msi", .data = &ls1043_v1_1_msi_cfg },
	{ .compatible = "fsl,ls1046a-msi", .data = &ls1046_msi_cfg },
	{ .compatible = "fsl,ls1046a-msi", .data = &ls1046_msi_cfg },
	{},
	{},
};
};