qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

grlib_ahb_apb_pnp.c (10648B)


      1 /*
      2  * GRLIB AHB APB PNP
      3  *
      4  *  Copyright (C) 2019 AdaCore
      5  *
      6  *  Developed by :
      7  *  Frederic Konrad   <frederic.konrad@adacore.com>
      8  *
      9  * This program is free software; you can redistribute it and/or modify
     10  * it under the terms of the GNU General Public License as published by
     11  * the Free Software Foundation, either version 2 of the License, or
     12  * (at your option) any later version.
     13  *
     14  * This program is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  * GNU General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU General Public License along
     20  * with this program; if not, see <http://www.gnu.org/licenses/>.
     21  *
     22  */
     23 
     24 #include "qemu/osdep.h"
     25 #include "qemu/log.h"
     26 #include "hw/sysbus.h"
     27 #include "hw/misc/grlib_ahb_apb_pnp.h"
     28 #include "trace.h"
     29 
     30 #define GRLIB_PNP_VENDOR_SHIFT (24)
     31 #define GRLIB_PNP_VENDOR_SIZE   (8)
     32 #define GRLIB_PNP_DEV_SHIFT    (12)
     33 #define GRLIB_PNP_DEV_SIZE     (12)
     34 #define GRLIB_PNP_VER_SHIFT     (5)
     35 #define GRLIB_PNP_VER_SIZE      (5)
     36 #define GRLIB_PNP_IRQ_SHIFT     (0)
     37 #define GRLIB_PNP_IRQ_SIZE      (5)
     38 #define GRLIB_PNP_ADDR_SHIFT   (20)
     39 #define GRLIB_PNP_ADDR_SIZE    (12)
     40 #define GRLIB_PNP_MASK_SHIFT    (4)
     41 #define GRLIB_PNP_MASK_SIZE    (12)
     42 
     43 #define GRLIB_AHB_DEV_ADDR_SHIFT   (20)
     44 #define GRLIB_AHB_DEV_ADDR_SIZE    (12)
     45 #define GRLIB_AHB_ENTRY_SIZE       (0x20)
     46 #define GRLIB_AHB_MAX_DEV          (64)
     47 #define GRLIB_AHB_SLAVE_OFFSET     (0x800)
     48 
     49 #define GRLIB_APB_DEV_ADDR_SHIFT   (8)
     50 #define GRLIB_APB_DEV_ADDR_SIZE    (12)
     51 #define GRLIB_APB_ENTRY_SIZE       (0x08)
     52 #define GRLIB_APB_MAX_DEV          (512)
     53 
     54 #define GRLIB_PNP_MAX_REGS         (0x1000)
     55 
     56 typedef struct AHBPnp {
     57     SysBusDevice parent_obj;
     58     MemoryRegion iomem;
     59 
     60     uint32_t regs[GRLIB_PNP_MAX_REGS >> 2];
     61     uint8_t master_count;
     62     uint8_t slave_count;
     63 } AHBPnp;
     64 
     65 void grlib_ahb_pnp_add_entry(AHBPnp *dev, uint32_t address, uint32_t mask,
     66                              uint8_t vendor, uint16_t device, int slave,
     67                              int type)
     68 {
     69     unsigned int reg_start;
     70 
     71     /*
     72      * AHB entries look like this:
     73      *
     74      * 31 -------- 23 -------- 11 ----- 9 -------- 4 --- 0
     75      *  | VENDOR ID | DEVICE ID | IRQ ? | VERSION  | IRQ |
     76      *  --------------------------------------------------
     77      *  |                      USER                      |
     78      *  --------------------------------------------------
     79      *  |                      USER                      |
     80      *  --------------------------------------------------
     81      *  |                      USER                      |
     82      *  --------------------------------------------------
     83      *  |                      USER                      |
     84      *  --------------------------------------------------
     85      * 31 ----------- 20 --- 15 ----------------- 3 ---- 0
     86      *  | ADDR[31..12] | 00PC |        MASK       | TYPE |
     87      *  --------------------------------------------------
     88      * 31 ----------- 20 --- 15 ----------------- 3 ---- 0
     89      *  | ADDR[31..12] | 00PC |        MASK       | TYPE |
     90      *  --------------------------------------------------
     91      * 31 ----------- 20 --- 15 ----------------- 3 ---- 0
     92      *  | ADDR[31..12] | 00PC |        MASK       | TYPE |
     93      *  --------------------------------------------------
     94      * 31 ----------- 20 --- 15 ----------------- 3 ---- 0
     95      *  | ADDR[31..12] | 00PC |        MASK       | TYPE |
     96      *  --------------------------------------------------
     97      */
     98 
     99     if (slave) {
    100         assert(dev->slave_count < GRLIB_AHB_MAX_DEV);
    101         reg_start = (GRLIB_AHB_SLAVE_OFFSET
    102                   + (dev->slave_count * GRLIB_AHB_ENTRY_SIZE)) >> 2;
    103         dev->slave_count++;
    104     } else {
    105         assert(dev->master_count < GRLIB_AHB_MAX_DEV);
    106         reg_start = (dev->master_count * GRLIB_AHB_ENTRY_SIZE) >> 2;
    107         dev->master_count++;
    108     }
    109 
    110     dev->regs[reg_start] = deposit32(dev->regs[reg_start],
    111                                      GRLIB_PNP_VENDOR_SHIFT,
    112                                      GRLIB_PNP_VENDOR_SIZE,
    113                                      vendor);
    114     dev->regs[reg_start] = deposit32(dev->regs[reg_start],
    115                                      GRLIB_PNP_DEV_SHIFT,
    116                                      GRLIB_PNP_DEV_SIZE,
    117                                      device);
    118     reg_start += 4;
    119     /* AHB Memory Space */
    120     dev->regs[reg_start] = type;
    121     dev->regs[reg_start] = deposit32(dev->regs[reg_start],
    122                                      GRLIB_PNP_ADDR_SHIFT,
    123                                      GRLIB_PNP_ADDR_SIZE,
    124                                      extract32(address,
    125                                                GRLIB_AHB_DEV_ADDR_SHIFT,
    126                                                GRLIB_AHB_DEV_ADDR_SIZE));
    127     dev->regs[reg_start] = deposit32(dev->regs[reg_start],
    128                                      GRLIB_PNP_MASK_SHIFT,
    129                                      GRLIB_PNP_MASK_SIZE,
    130                                      mask);
    131 }
    132 
    133 static uint64_t grlib_ahb_pnp_read(void *opaque, hwaddr offset, unsigned size)
    134 {
    135     AHBPnp *ahb_pnp = GRLIB_AHB_PNP(opaque);
    136     uint32_t val;
    137 
    138     val = ahb_pnp->regs[offset >> 2];
    139     val = extract32(val, (4 - (offset & 3) - size) * 8, size * 8);
    140     trace_grlib_ahb_pnp_read(offset, size, val);
    141 
    142     return val;
    143 }
    144 
    145 static void grlib_ahb_pnp_write(void *opaque, hwaddr addr,
    146                                 uint64_t val, unsigned size)
    147 {
    148     qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__);
    149 }
    150 
    151 static const MemoryRegionOps grlib_ahb_pnp_ops = {
    152     .read       = grlib_ahb_pnp_read,
    153     .write      = grlib_ahb_pnp_write,
    154     .endianness = DEVICE_BIG_ENDIAN,
    155     .impl = {
    156         .min_access_size = 1,
    157         .max_access_size = 4,
    158     },
    159 };
    160 
    161 static void grlib_ahb_pnp_realize(DeviceState *dev, Error **errp)
    162 {
    163     AHBPnp *ahb_pnp = GRLIB_AHB_PNP(dev);
    164     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    165 
    166     memory_region_init_io(&ahb_pnp->iomem, OBJECT(dev), &grlib_ahb_pnp_ops,
    167                           ahb_pnp, TYPE_GRLIB_AHB_PNP, GRLIB_PNP_MAX_REGS);
    168     sysbus_init_mmio(sbd, &ahb_pnp->iomem);
    169 }
    170 
    171 static void grlib_ahb_pnp_class_init(ObjectClass *klass, void *data)
    172 {
    173     DeviceClass *dc = DEVICE_CLASS(klass);
    174 
    175     dc->realize = grlib_ahb_pnp_realize;
    176 }
    177 
    178 static const TypeInfo grlib_ahb_pnp_info = {
    179     .name          = TYPE_GRLIB_AHB_PNP,
    180     .parent        = TYPE_SYS_BUS_DEVICE,
    181     .instance_size = sizeof(AHBPnp),
    182     .class_init    = grlib_ahb_pnp_class_init,
    183 };
    184 
    185 /* APBPnp */
    186 
    187 typedef struct APBPnp {
    188     SysBusDevice parent_obj;
    189     MemoryRegion iomem;
    190 
    191     uint32_t regs[GRLIB_PNP_MAX_REGS >> 2];
    192     uint32_t entry_count;
    193 } APBPnp;
    194 
    195 void grlib_apb_pnp_add_entry(APBPnp *dev, uint32_t address, uint32_t mask,
    196                              uint8_t vendor, uint16_t device, uint8_t version,
    197                              uint8_t irq, int type)
    198 {
    199     unsigned int reg_start;
    200 
    201     /*
    202      * APB entries look like this:
    203      *
    204      * 31 -------- 23 -------- 11 ----- 9 ------- 4 --- 0
    205      *  | VENDOR ID | DEVICE ID | IRQ ? | VERSION | IRQ |
    206      *
    207      * 31 ---------- 20 --- 15 ----------------- 3 ---- 0
    208      *  | ADDR[20..8] | 0000 |        MASK       | TYPE |
    209      */
    210 
    211     assert(dev->entry_count < GRLIB_APB_MAX_DEV);
    212     reg_start = (dev->entry_count * GRLIB_APB_ENTRY_SIZE) >> 2;
    213     dev->entry_count++;
    214 
    215     dev->regs[reg_start] = deposit32(dev->regs[reg_start],
    216                                      GRLIB_PNP_VENDOR_SHIFT,
    217                                      GRLIB_PNP_VENDOR_SIZE,
    218                                      vendor);
    219     dev->regs[reg_start] = deposit32(dev->regs[reg_start],
    220                                      GRLIB_PNP_DEV_SHIFT,
    221                                      GRLIB_PNP_DEV_SIZE,
    222                                      device);
    223     dev->regs[reg_start] = deposit32(dev->regs[reg_start],
    224                                      GRLIB_PNP_VER_SHIFT,
    225                                      GRLIB_PNP_VER_SIZE,
    226                                      version);
    227     dev->regs[reg_start] = deposit32(dev->regs[reg_start],
    228                                      GRLIB_PNP_IRQ_SHIFT,
    229                                      GRLIB_PNP_IRQ_SIZE,
    230                                      irq);
    231     reg_start += 1;
    232     dev->regs[reg_start] = type;
    233     dev->regs[reg_start] = deposit32(dev->regs[reg_start],
    234                                      GRLIB_PNP_ADDR_SHIFT,
    235                                      GRLIB_PNP_ADDR_SIZE,
    236                                      extract32(address,
    237                                                GRLIB_APB_DEV_ADDR_SHIFT,
    238                                                GRLIB_APB_DEV_ADDR_SIZE));
    239     dev->regs[reg_start] = deposit32(dev->regs[reg_start],
    240                                      GRLIB_PNP_MASK_SHIFT,
    241                                      GRLIB_PNP_MASK_SIZE,
    242                                      mask);
    243 }
    244 
    245 static uint64_t grlib_apb_pnp_read(void *opaque, hwaddr offset, unsigned size)
    246 {
    247     APBPnp *apb_pnp = GRLIB_APB_PNP(opaque);
    248     uint32_t val;
    249 
    250     val = apb_pnp->regs[offset >> 2];
    251     val = extract32(val, (4 - (offset & 3) - size) * 8, size * 8);
    252     trace_grlib_apb_pnp_read(offset, size, val);
    253 
    254     return val;
    255 }
    256 
    257 static void grlib_apb_pnp_write(void *opaque, hwaddr addr,
    258                                 uint64_t val, unsigned size)
    259 {
    260     qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__);
    261 }
    262 
    263 static const MemoryRegionOps grlib_apb_pnp_ops = {
    264     .read       = grlib_apb_pnp_read,
    265     .write      = grlib_apb_pnp_write,
    266     .endianness = DEVICE_BIG_ENDIAN,
    267     .impl = {
    268         .min_access_size = 1,
    269         .max_access_size = 4,
    270     },
    271 };
    272 
    273 static void grlib_apb_pnp_realize(DeviceState *dev, Error **errp)
    274 {
    275     APBPnp *apb_pnp = GRLIB_APB_PNP(dev);
    276     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    277 
    278     memory_region_init_io(&apb_pnp->iomem, OBJECT(dev), &grlib_apb_pnp_ops,
    279                           apb_pnp, TYPE_GRLIB_APB_PNP, GRLIB_PNP_MAX_REGS);
    280     sysbus_init_mmio(sbd, &apb_pnp->iomem);
    281 }
    282 
    283 static void grlib_apb_pnp_class_init(ObjectClass *klass, void *data)
    284 {
    285     DeviceClass *dc = DEVICE_CLASS(klass);
    286 
    287     dc->realize = grlib_apb_pnp_realize;
    288 }
    289 
    290 static const TypeInfo grlib_apb_pnp_info = {
    291     .name          = TYPE_GRLIB_APB_PNP,
    292     .parent        = TYPE_SYS_BUS_DEVICE,
    293     .instance_size = sizeof(APBPnp),
    294     .class_init    = grlib_apb_pnp_class_init,
    295 };
    296 
    297 static void grlib_ahb_apb_pnp_register_types(void)
    298 {
    299     type_register_static(&grlib_ahb_pnp_info);
    300     type_register_static(&grlib_apb_pnp_info);
    301 }
    302 
    303 type_init(grlib_ahb_apb_pnp_register_types)