示例#1
0
文件: pnv_lpc.c 项目: Dovgalyuk/qemu
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;

    /* Create address space and backing MR for the OPB bus */
    memory_region_init(&lpc->opb_mr, OBJECT(dev), "lpc-opb", 0x100000000ull);
    address_space_init(&lpc->opb_as, &lpc->opb_mr, "lpc-opb");

    /* Create ISA IO and Mem space regions which are the root of
     * the ISA bus (ie, ISA address spaces). We don't create a
     * separate one for FW which we alias to memory.
     */
    memory_region_init(&lpc->isa_io, OBJECT(dev), "isa-io", ISA_IO_SIZE);
    memory_region_init(&lpc->isa_mem, OBJECT(dev), "isa-mem", ISA_MEM_SIZE);
    memory_region_init(&lpc->isa_fw, OBJECT(dev),  "isa-fw", ISA_FW_SIZE);

    /* Create windows from the OPB space to the ISA space */
    memory_region_init_alias(&lpc->opb_isa_io, OBJECT(dev), "lpc-isa-io",
                             &lpc->isa_io, 0, LPC_IO_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_IO_OPB_ADDR,
                                &lpc->opb_isa_io);
    memory_region_init_alias(&lpc->opb_isa_mem, OBJECT(dev), "lpc-isa-mem",
                             &lpc->isa_mem, 0, LPC_MEM_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_MEM_OPB_ADDR,
                                &lpc->opb_isa_mem);
    memory_region_init_alias(&lpc->opb_isa_fw, OBJECT(dev), "lpc-isa-fw",
                             &lpc->isa_fw, 0, LPC_FW_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_FW_OPB_ADDR,
                                &lpc->opb_isa_fw);

    /* Create MMIO regions for LPC HC and OPB registers */
    memory_region_init_io(&lpc->opb_master_regs, OBJECT(dev), &opb_master_ops,
                          lpc, "lpc-opb-master", LPC_OPB_REGS_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_OPB_REGS_OPB_ADDR,
                                &lpc->opb_master_regs);
    memory_region_init_io(&lpc->lpc_hc_regs, OBJECT(dev), &lpc_hc_ops, lpc,
                          "lpc-hc", LPC_HC_REGS_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_HC_REGS_OPB_ADDR,
                                &lpc->lpc_hc_regs);

    /* XScom region for LPC registers */
    pnv_xscom_region_init(&lpc->xscom_regs, OBJECT(dev),
                          &pnv_lpc_xscom_ops, lpc, "xscom-lpc",
                          PNV_XSCOM_LPC_SIZE);

    /* 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);
}
示例#2
0
static void pnv_lpc_isa_irq_handler(void *opaque, int n, int level)
{
    PnvLpcController *lpc = PNV_LPC(opaque);

    /* 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);
    }
}
示例#3
0
/* If we don't use the built-in LPC interrupt deserializer, we need
 * to provide a set of qirqs for the ISA bus or things will go bad.
 *
 * Most machines using pre-Naples chips (without said deserializer)
 * have a CPLD that will collect the SerIRQ and shoot them as a
 * single level interrupt to the P8 chip. So let's setup a hook
 * for doing just that.
 */
static void pnv_lpc_isa_irq_handler_cpld(void *opaque, int n, int level)
{
    PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
    uint32_t old_state = pnv->cpld_irqstate;
    PnvLpcController *lpc = PNV_LPC(opaque);

    if (level) {
        pnv->cpld_irqstate |= 1u << n;
    } else {
        pnv->cpld_irqstate &= ~(1u << n);
    }

    if (pnv->cpld_irqstate != old_state) {
        pnv_psi_irq_set(lpc->psi, PSIHB_IRQ_EXTERNAL, pnv->cpld_irqstate != 0);
    }
}
示例#4
0
文件: pnv_lpc.c 项目: AmesianX/panda
static void pnv_lpc_realize(DeviceState *dev, Error **errp)
{
    PnvLpcController *lpc = PNV_LPC(dev);

    /* Reg inits */
    lpc->lpc_hc_fw_rd_acc_size = LPC_HC_FW_RD_4B;

    /* Create address space and backing MR for the OPB bus */
    memory_region_init(&lpc->opb_mr, OBJECT(dev), "lpc-opb", 0x100000000ull);
    address_space_init(&lpc->opb_as, &lpc->opb_mr, "lpc-opb");

    /* Create ISA IO and Mem space regions which are the root of
     * the ISA bus (ie, ISA address spaces). We don't create a
     * separate one for FW which we alias to memory.
     */
    memory_region_init(&lpc->isa_io, OBJECT(dev), "isa-io", ISA_IO_SIZE);
    memory_region_init(&lpc->isa_mem, OBJECT(dev), "isa-mem", ISA_MEM_SIZE);

    /* Create windows from the OPB space to the ISA space */
    memory_region_init_alias(&lpc->opb_isa_io, OBJECT(dev), "lpc-isa-io",
                             &lpc->isa_io, 0, LPC_IO_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_IO_OPB_ADDR,
                                &lpc->opb_isa_io);
    memory_region_init_alias(&lpc->opb_isa_mem, OBJECT(dev), "lpc-isa-mem",
                             &lpc->isa_mem, 0, LPC_MEM_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_MEM_OPB_ADDR,
                                &lpc->opb_isa_mem);
    memory_region_init_alias(&lpc->opb_isa_fw, OBJECT(dev), "lpc-isa-fw",
                             &lpc->isa_mem, 0, LPC_FW_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_FW_OPB_ADDR,
                                &lpc->opb_isa_fw);

    /* Create MMIO regions for LPC HC and OPB registers */
    memory_region_init_io(&lpc->opb_master_regs, OBJECT(dev), &opb_master_ops,
                          lpc, "lpc-opb-master", LPC_OPB_REGS_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_OPB_REGS_OPB_ADDR,
                                &lpc->opb_master_regs);
    memory_region_init_io(&lpc->lpc_hc_regs, OBJECT(dev), &lpc_hc_ops, lpc,
                          "lpc-hc", LPC_HC_REGS_OPB_SIZE);
    memory_region_add_subregion(&lpc->opb_mr, LPC_HC_REGS_OPB_ADDR,
                                &lpc->lpc_hc_regs);

    /* XScom region for LPC registers */
    pnv_xscom_region_init(&lpc->xscom_regs, OBJECT(dev),
                          &pnv_lpc_xscom_ops, lpc, "xscom-lpc",
                          PNV_XSCOM_LPC_SIZE);
}
示例#5
0
static void pnv_lpc_xscom_write(void *opaque, hwaddr addr,
                                uint64_t val, unsigned size)
{
    PnvLpcController *lpc = PNV_LPC(opaque);
    uint32_t offset = addr >> 3;

    switch (offset & 3) {
    case ECCB_CTL:
        pnv_lpc_do_eccb(lpc, val);
        break;
    case ECCB_RESET:
        /*  XXXX  */
        break;
    case ECCB_STAT:
        break;
    case ECCB_DATA:
        lpc->eccb_data_reg = val >> 32;
        break;
    }
}
示例#6
0
static uint64_t pnv_lpc_xscom_read(void *opaque, hwaddr addr, unsigned size)
{
    PnvLpcController *lpc = PNV_LPC(opaque);
    uint32_t offset = addr >> 3;
    uint64_t val = 0;

    switch (offset & 3) {
    case ECCB_CTL:
    case ECCB_RESET:
        val = 0;
        break;
    case ECCB_STAT:
        val = lpc->eccb_stat_reg;
        lpc->eccb_stat_reg = 0;
        break;
    case ECCB_DATA:
        val = ((uint64_t)lpc->eccb_data_reg) << 32;
        break;
    }
    return val;
}