[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [PATCH v4 19/20] ppc/pnv: Add Naples chip support for LPC
From: |
David Gibson |
Subject: |
Re: [Qemu-ppc] [PATCH v4 19/20] ppc/pnv: Add Naples chip support for LPC interrupts |
Date: |
Fri, 14 Oct 2016 17:36:52 +1100 |
User-agent: |
Mutt/1.7.0 (2016-08-17) |
On Mon, Oct 03, 2016 at 09:24:55AM +0200, Cédric Le Goater wrote:
> From: Benjamin Herrenschmidt <address@hidden>
>
> It adds the Naples chip which supports proper LPC interrupts via the
> LPC controller rather than via an external CPLD.
>
> Signed-off-by: Benjamin Herrenschmidt <address@hidden>
> [clg: - updated for qemu-2.7
> - ported on latest PowerNV patchset (v3) ]
> Signed-off-by: Cédric Le Goater <address@hidden>
> ---
> hw/ppc/pnv.c | 18 +++++++++++++++++-
> hw/ppc/pnv_lpc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
> include/hw/ppc/pnv_lpc.h | 7 +++++++
> 3 files changed, 69 insertions(+), 3 deletions(-)
>
> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> index e805e97d4d87..5b70ccf66fac 100644
> --- a/hw/ppc/pnv.c
> +++ b/hw/ppc/pnv.c
> @@ -340,7 +340,17 @@ static void pnv_lpc_isa_irq_handler_cpld(void *opaque,
> int n, int level)
>
> static void pnv_lpc_isa_irq_handler(void *opaque, int n, int level)
> {
> - /* XXX TODO */
> + PnvLpcController *lpc = opaque;
> +
> + if (n >= ISA_NUM_IRQS) {
> + return;
> + }
How could n >= ISA_NUM_IRQS arise? Would it have to mean a bug
elsewhere in your code? If so this should be an assert().
> +
> + /* The Naples HW latches the 1 levels, clearing is done by SW */
> + if (level) {
> + lpc->lpc_hc_irqstat |= LPC_HC_IRQ_SERIRQ0 >> n;
> + pnv_lpc_eval_irqs(lpc);
> + }
> }
>
> static ISABus *pnv_isa_create(PnvChip *chip)
> @@ -656,6 +666,12 @@ static void pnv_chip_init(Object *obj)
> object_property_add_child(obj, "occ", OBJECT(&chip->occ), NULL);
> object_property_add_const_link(OBJECT(&chip->occ), "psi",
> OBJECT(&chip->psi), &error_abort);
> +
> + /*
> + * The LPC controller needs PSI to generate interrupts
> + */
> + object_property_add_const_link(OBJECT(&chip->lpc), "psi",
> + OBJECT(&chip->psi), &error_abort);
> }
>
> static void pnv_chip_realize(DeviceState *dev, Error **errp)
> diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
> index 210cc1cff167..8b78b0a1e414 100644
> --- a/hw/ppc/pnv_lpc.c
> +++ b/hw/ppc/pnv_lpc.c
> @@ -249,6 +249,34 @@ static const MemoryRegionOps pnv_lpc_xscom_ops = {
> .endianness = DEVICE_BIG_ENDIAN,
> };
>
> +void pnv_lpc_eval_irqs(PnvLpcController *lpc)
> +{
> + bool lpc_to_opb_irq = false;
> +
> + /* Update LPC controller to OPB line */
> + if (lpc->lpc_hc_irqser_ctrl & LPC_HC_IRQSER_EN) {
> + uint32_t irqs;
> +
> + irqs = lpc->lpc_hc_irqstat & lpc->lpc_hc_irqmask;
> + lpc_to_opb_irq = (irqs != 0);
> + }
> +
> + /* We don't honor the polarity register, it's pointless and unused
> + * anyway
> + */
> + if (lpc_to_opb_irq) {
> + lpc->opb_irq_input |= OPB_MASTER_IRQ_LPC;
> + } else {
> + lpc->opb_irq_input &= ~OPB_MASTER_IRQ_LPC;
> + }
> +
> + /* Update OPB internal latch */
> + lpc->opb_irq_stat |= lpc->opb_irq_input & lpc->opb_irq_mask;
> +
> + /* Reflect the interrupt */
> + pnv_psi_irq_set(lpc->psi, PSIHB_IRQ_LPC_I2C, lpc->opb_irq_stat != 0);
> +}
> +
> static uint64_t lpc_hc_read(void *opaque, hwaddr addr, unsigned size)
> {
> PnvLpcController *lpc = opaque;
> @@ -299,12 +327,15 @@ static void lpc_hc_write(void *opaque, hwaddr addr,
> uint64_t val,
> break;
> case LPC_HC_IRQSER_CTRL:
> lpc->lpc_hc_irqser_ctrl = val;
> + pnv_lpc_eval_irqs(lpc);
> break;
> case LPC_HC_IRQMASK:
> lpc->lpc_hc_irqmask = val;
> + pnv_lpc_eval_irqs(lpc);
> break;
> case LPC_HC_IRQSTAT:
> lpc->lpc_hc_irqstat &= ~val;
> + pnv_lpc_eval_irqs(lpc);
> break;
> case LPC_HC_ERROR_ADDRESS:
> break;
> @@ -362,14 +393,15 @@ static void opb_master_write(void *opaque, hwaddr addr,
> switch (addr) {
> case OPB_MASTER_LS_IRQ_STAT:
> lpc->opb_irq_stat &= ~val;
> + pnv_lpc_eval_irqs(lpc);
> break;
> case OPB_MASTER_LS_IRQ_MASK:
> - /* XXX Filter out reserved bits */
> lpc->opb_irq_mask = val;
> + pnv_lpc_eval_irqs(lpc);
> break;
> case OPB_MASTER_LS_IRQ_POL:
> - /* XXX Filter out reserved bits */
> lpc->opb_irq_pol = val;
> + pnv_lpc_eval_irqs(lpc);
> break;
> case OPB_MASTER_LS_IRQ_INPUT:
> /* Read only */
> @@ -397,6 +429,8 @@ static const MemoryRegionOps opb_master_ops = {
> static void pnv_lpc_realize(DeviceState *dev, Error **errp)
> {
> PnvLpcController *lpc = PNV_LPC(dev);
> + Object *obj;
> + Error *error = NULL;
>
> /* Reg inits */
> lpc->lpc_hc_fw_rd_acc_size = LPC_HC_FW_RD_4B;
> @@ -440,6 +474,15 @@ static void pnv_lpc_realize(DeviceState *dev, Error
> **errp)
> memory_region_init_io(&lpc->xscom_regs, OBJECT(dev),
> &pnv_lpc_xscom_ops, lpc, "xscom-lpc",
> PNV_XSCOM_LPC_SIZE << 3);
> +
> + /* get PSI object from chip */
> + obj = object_property_get_link(OBJECT(dev), "psi", &error);
> + if (!obj) {
> + error_setg(errp, "%s: required link 'psi' not found: %s",
> + __func__, error_get_pretty(error));
> + return;
> + }
> + lpc->psi = PNV_PSI(obj);
> }
>
> static void pnv_lpc_class_init(ObjectClass *klass, void *data)
> diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h
> index 38e5506975aa..fc348dca50ca 100644
> --- a/include/hw/ppc/pnv_lpc.h
> +++ b/include/hw/ppc/pnv_lpc.h
> @@ -23,9 +23,13 @@
> #define PNV_LPC(obj) \
> OBJECT_CHECK(PnvLpcController, (obj), TYPE_PNV_LPC)
>
> +typedef struct PnvPsiController PnvPsiController;
> +
> typedef struct PnvLpcController {
> DeviceState parent;
>
> + PnvPsiController *psi;
> +
> uint64_t eccb_stat_reg;
> uint32_t eccb_data_reg;
>
> @@ -64,4 +68,7 @@ typedef struct PnvLpcController {
> MemoryRegion xscom_regs;
> } PnvLpcController;
>
> +#define LPC_HC_IRQ_SERIRQ0 0x80000000 /* all bits down to ... */
> +void pnv_lpc_eval_irqs(PnvLpcController *lpc);
> +
> #endif /* _PPC_PNV_LPC_H */
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
signature.asc
Description: PGP signature
- Re: [Qemu-ppc] [PATCH v4 16/20] ppc/pnv: add a XICS native to each PowerNV chip, (continued)
[Qemu-ppc] [PATCH v4 18/20] ppc/pnv: Add OCC model stub with interrupt support, Cédric Le Goater, 2016/10/03
[Qemu-ppc] [PATCH v4 19/20] ppc/pnv: Add Naples chip support for LPC interrupts, Cédric Le Goater, 2016/10/03
- Re: [Qemu-ppc] [PATCH v4 19/20] ppc/pnv: Add Naples chip support for LPC interrupts,
David Gibson <=
[Qemu-ppc] [PATCH v4 20/20] ppc/pnv: add support for POWER9 LPC Controller, Cédric Le Goater, 2016/10/03
Re: [Qemu-ppc] [Qemu-devel] [PATCH v4 00/20] ppc/pnv: booting the kernel and reaching user space, no-reply, 2016/10/03