Hi Cedric, 

> >> and the register array as:
> >>
> >>     uint32_t regs[ASPEED_INTC_NR_REGS];
> >>
> >> The number of regs looks pretty big for me. Are the registers
> >> covering the whole MMIO aperture ?
> >>
> > According to the datasheet, the entire register address space size of
> > INTC (CPU DIE) is 16KB (0x12100000-0x12103FFF). Therefore, I set the
> memory size to 0x4000.
> > Currently, we need to use the "GICINT192-201 raw status and clear" register
> INTC1B04.
> > Thus, an array size of 0x2000 is sufficient.
> 
> yes but we are only using these regs :
> 
> REG32(GICINT128_EN,         0x1000)
> REG32(GICINT128_STATUS,     0x1004)
> REG32(GICINT129_EN,         0x1100)
> REG32(GICINT129_STATUS,     0x1104)
> REG32(GICINT130_EN,         0x1200)
> REG32(GICINT130_STATUS,     0x1204)
> REG32(GICINT131_EN,         0x1300)
> REG32(GICINT131_STATUS,     0x1304)
> REG32(GICINT132_EN,         0x1400)
> REG32(GICINT132_STATUS,     0x1404)
> REG32(GICINT133_EN,         0x1500)
> REG32(GICINT133_STATUS,     0x1504)
> REG32(GICINT134_EN,         0x1600)
> REG32(GICINT134_STATUS,     0x1604)
> REG32(GICINT135_EN,         0x1700)
> REG32(GICINT135_STATUS,     0x1704)
> REG32(GICINT136_EN,         0x1800)
> REG32(GICINT136_STATUS,     0x1804)
> REG32(GICINT192_201_EN,         0x1B00)
> REG32(GICINT192_201_STATUS,     0x1B04)
> 
> so the first 0x1000 are unused.
> 
> 
> >
> > However, we are going to increase the size to 0x3000 to support the
> > co-processors SSP and TSP In the another patch series.
> > We also need to include the following register definitions:
> >
> > /* SSP INTC Registers */
> > REG32(SSPINT128_EN,             0x2000)
> > REG32(SSPINT128_STATUS,         0x2004)
> > REG32(SSPINT129_EN,             0x2100)
> > REG32(SSPINT129_STATUS,         0x2104)
> > REG32(SSPINT130_EN,             0x2200)
> > REG32(SSPINT130_STATUS,         0x2204)
> > REG32(SSPINT131_EN,             0x2300)
> > REG32(SSPINT131_STATUS,         0x2304)
> > REG32(SSPINT132_EN,             0x2400)
> > REG32(SSPINT132_STATUS,         0x2404)
> > REG32(SSPINT133_EN,             0x2500)
> > REG32(SSPINT133_STATUS,         0x2504)
> > REG32(SSPINT134_EN,             0x2600)
> > REG32(SSPINT134_STATUS,         0x2604)
> > REG32(SSPINT135_EN,             0x2700)
> > REG32(SSPINT135_STATUS,         0x2704)
> > REG32(SSPINT136_EN,             0x2800)
> > REG32(SSPINT136_STATUS,         0x2804)
> > REG32(SSPINT137_EN,             0x2900)
> > REG32(SSPINT137_STATUS,         0x2904)
> > REG32(SSPINT138_EN,             0x2A00)
> > REG32(SSPINT138_STATUS,         0x2A04)
> > REG32(SSPINT160_169_EN,         0x2B00)
> > REG32(SSPINT160_169_STATUS,     0x2B04)
> >
> >>
> >>> +    if (offset >= aic->reg_size) {
> >>
> >> This is dead code since the MMIO aperture has the same size. You
> >> could remove the check.
> >
> > Will remove.
> >>
> >>>            qemu_log_mask(LOG_GUEST_ERROR,
> >>>                          "%s: Out-of-bounds read at offset 0x%"
> >> HWADDR_PRIx "\n",
> >>>                          __func__, offset); @@ -143,7 +144,7 @@
> >> static
> >>> void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
> >>>        uint32_t change;
> >>>        uint32_t irq;
> >>>
> >>> -    if (addr >= ASPEED_INTC_NR_REGS) {
> >>> +    if (offset >= aic->reg_size) {
> >>>            qemu_log_mask(LOG_GUEST_ERROR,
> >>>                          "%s: Out-of-bounds write at offset 0x%"
> >> HWADDR_PRIx "\n",
> >>>                          __func__, offset); @@ -302,10 +303,16
> @@
> >>> static void aspeed_intc_realize(DeviceState *dev, Error **errp)
> >>>        AspeedINTCClass *aic = ASPEED_INTC_GET_CLASS(s);
> >>>        int i;
> >>>
> >>> +    memory_region_init(&s->iomem_container, OBJECT(s),
> >>> +            TYPE_ASPEED_INTC ".container", aic->mem_size);
> >>> +
> >>> +    sysbus_init_mmio(sbd, &s->iomem_container);
> >>
> >> Why introduce a container ? Do you plan to have multiple sub-regions ?
> >>
> > I created a container to save the entire register address space of
> > INTC and its sub-region to place the actual used register address space.
> > 0000000012100000-0000000012103fff (prio 0, i/o): aspeed.intc.container
> >        0000000012100000-0000000012101fff (prio 0, i/o):
> > aspeed.intc.regs 0000000014c18000-0000000014c183ff (prio 0, i/o):
> aspeed.intc.container
> >        0000000014c18000-0000000014c183d7 (prio 0, i/o):
> > aspeed.intc.regs
> >
> > If I misunderstood this design, I will change it to have two memory regions
> for INTC and INTCIO, respectively.
> > If need, I will change to the following memory regions.  --> it removes
> containers.
> >        0000000012100000-0000000012101fff (prio 0, i/o):
> aspeed.intc.regs
> >        0000000014c18000-0000000014c183d7 (prio 0, i/o):
> > aspeed.intc.regs
> 
> I don't think the region container is useful in that case since there is only 
> a
> single region per model.
> 
> However, we could "optimize" a bit the MMIO apertures to avoid mapping
> huge unused gaps and only map the useful set of registers :
> 
>    INTC Registers      [ 0x1000 - 0x1B04 ]
>    SSP INTC Registers  [ 0x2000 - 0x2B04 ]
>    INTCIO Registers    [ 0x0100 - 0x0154 ]
> 
> Each set would be associated with a subregion which would be mapped at the
> right offset in the region container.
> 
> This is just a suggestion.
> 

I followed your suggestion to reduce the size of the register array. Here's 
what I've done:

0000000012100000-0000000012103fff (prio 0, i/o): aspeed.intc.container
      0000000012101000-0000000012101b07 (prio 0, i/o): aspeed.intc.regs

A solution:
1.      I created an INTC Register sub-region mapped at offset 0x1000 with a 
size of 0xb08.
This change adjusted the following register offsets to their original values 
minus 0x1000:

REG32(GICINT128_EN,         0x000)
REG32(GICINT128_STATUS,     0x004)
REG32(GICINT129_EN,         0x100)
REG32(GICINT129_STATUS,     0x104)
REG32(GICINT130_EN,         0x200)
REG32(GICINT130_STATUS,     0x204)
REG32(GICINT131_EN,         0x300)
REG32(GICINT131_STATUS,     0x304)
REG32(GICINT132_EN,         0x400)
REG32(GICINT132_STATUS,     0x404)
REG32(GICINT133_EN,         0x500)
REG32(GICINT133_STATUS,     0x504)
REG32(GICINT134_EN,         0x600)
REG32(GICINT134_STATUS,     0x604)
REG32(GICINT135_EN,         0x700)
REG32(GICINT135_STATUS,     0x704)
REG32(GICINT136_EN,         0x800)
REG32(GICINT136_STATUS,     0x804)
REG32(GICINT192_201_EN,         0xB00)
REG32(GICINT192_201_STATUS,     0xB04)

2.      To support multiple sub-regions, such as for SSP, I created a new 
sub-region mapped at offset 0x2000. 
This adjustment changed the register offsets to their original values minus 
0x2000:

/* SSP INTC Registers */
> REG32(SSPINT128_EN,             0x000)
> REG32(SSPINT128_STATUS,         0x004)
> REG32(SSPINT129_EN,             0x100)
> REG32(SSPINT129_STATUS,         0x104)
> REG32(SSPINT130_EN,             0x200)
> REG32(SSPINT130_STATUS,         0x204)
> REG32(SSPINT131_EN,             0x300)
> REG32(SSPINT131_STATUS,         0x304)
> REG32(SSPINT132_EN,             0x400)
> REG32(SSPINT132_STATUS,         0x404)
> REG32(SSPINT133_EN,             0x500)
> REG32(SSPINT133_STATUS,         0x504)
> REG32(SSPINT134_EN,             0x600)
> REG32(SSPINT134_STATUS,         0x604)
> REG32(SSPINT135_EN,             0x700)
> REG32(SSPINT135_STATUS,         0x704)
> REG32(SSPINT136_EN,             0x800)
> REG32(SSPINT136_STATUS,         0x804)
> REG32(SSPINT137_EN,             0x900)
> REG32(SSPINT137_STATUS,         0x904)
> REG32(SSPINT138_EN,             0xA00)
> REG32(SSPINT138_STATUS,         0xA04)
> REG32(SSPINT160_169_EN,         0xB00)
> REG32(SSPINT160_169_STATUS,     0xB04)

Regarding handling identical offsets like SSPINT128_EN and GICINT128_EN, which 
both use offset 0x00,
they currently share the same aspeed_intc_ops and IRQ handler functions like 
aspeed_intc_status_handler.

How can I check whether the offset belongs to the SSP or INTC region?
Can I create new aspeed_intc_ssp_write and aspeed_intc_ssp_read callback 
functions specifically for
reading and writing to the SSP region, and then add new parameters to the IRQ 
handler to distinguish
between the SSP and INTC regions?

B solution:

There is another solution where we don't consider multiple sub-regions and only 
support a single sub-region.
Since the SSP runs on a co-processor, we've created a new SSP class:
static void aspeed_intc_register_types(void)
{
    type_register_static(&aspeed_intc_info);
    type_register_static(&aspeed_2700_intc_info);
    type_register_static(&aspeed_2700_intcio_info);
+    type_register_static(&aspeed_2700_ssp_intc_info);
+    type_register_static(&aspeed_2700_ssp_intcio_info);
}

In this solution, we don’t need to make many changes because the SSP has its 
own AspeedINTCState register array. 
As a result, most functions can be reused to support SSP.
The SSP uses the same callback function as the INTC:

static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data,
                                        unsigned size)
{
    switch (addr) {
    case R_GICINT128_EN:
    case R_GICINT129_EN:
    case R_GICINT130_EN:
    case R_GICINT131_EN:
    case R_GICINT132_EN:
    case R_GICINT133_EN:
    case R_GICINT134_EN:
    case R_GICINT135_EN:
    case R_GICINT136_EN:
    case R_GICINT192_201_EN:
+    case R_SSPINT128_STATUS:
+    case R_SSPINT129_STATUS:
+    case R_SSPINT130_STATUS:

Since both GICINT128_EN and SSPINT128_EN share the same offset of 0, I will 
modify the code to handle INT128 for both.

Could you please give me any suggestion?

Thanks-Jamin

> 
> Thanks,
> 
> C.
> 
> 
> 
> > Do you expect the above memory regions for INTC?
> >
> > Thanks for your review and suggestion.
> > Jamin
> >>
> >> Thanks,
> >>
> >> C.
> >>
> >>
> >>
> >>> +
> >>>        memory_region_init_io(&s->iomem, OBJECT(s),
> &aspeed_intc_ops,
> >> s,
> >>> -                          TYPE_ASPEED_INTC ".regs",
> >> ASPEED_INTC_NR_REGS << 2);
> >>> +                          TYPE_ASPEED_INTC ".regs",
> aic->reg_size);
> >>> +
> >>> +    memory_region_add_subregion(&s->iomem_container, 0x0,
> >> &s->iomem);
> >>>
> >>> -    sysbus_init_mmio(sbd, &s->iomem);
> >>>        qdev_init_gpio_in(dev, aspeed_intc_set_irq, aic->num_ints);
> >>>
> >>>        for (i = 0; i < aic->num_ints; i++) { @@ -344,6 +351,8 @@
> >>> static void aspeed_2700_intc_class_init(ObjectClass *klass, void *data)
> >>>        dc->desc = "ASPEED 2700 INTC Controller";
> >>>        aic->num_lines = 32;
> >>>        aic->num_ints = 9;
> >>> +    aic->mem_size = 0x4000;
> >>> +    aic->reg_size = 0x2000;
> >>>    }
> >>>
> >>>    static const TypeInfo aspeed_2700_intc_info = { diff --git
> >>> a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
> >>> index 18cb43476c..ecaeb15aea 100644
> >>> --- a/include/hw/intc/aspeed_intc.h
> >>> +++ b/include/hw/intc/aspeed_intc.h
> >>> @@ -25,6 +25,8 @@ struct AspeedINTCState {
> >>>
> >>>        /*< public >*/
> >>>        MemoryRegion iomem;
> >>> +    MemoryRegion iomem_container;
> >>> +
> >>>        uint32_t regs[ASPEED_INTC_NR_REGS];
> >>>        OrIRQState orgates[ASPEED_INTC_NR_INTS];
> >>>        qemu_irq output_pins[ASPEED_INTC_NR_INTS]; @@ -39,6 +41,8
> @@
> >>> struct AspeedINTCClass {
> >>>
> >>>        uint32_t num_lines;
> >>>        uint32_t num_ints;
> >>> +    uint64_t mem_size;
> >>> +    uint64_t reg_size;
> >>>    };
> >>>
> >>>    #endif /* ASPEED_INTC_H */
> >

Reply via email to