cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

aspeed_gpio.c (39109B)


      1/*
      2 *  ASPEED GPIO Controller
      3 *
      4 *  Copyright (C) 2017-2019 IBM Corp.
      5 *
      6 * SPDX-License-Identifier: GPL-2.0-or-later
      7 */
      8
      9#include "qemu/osdep.h"
     10#include "qemu/host-utils.h"
     11#include "qemu/log.h"
     12#include "hw/gpio/aspeed_gpio.h"
     13#include "hw/misc/aspeed_scu.h"
     14#include "qapi/error.h"
     15#include "qapi/visitor.h"
     16#include "hw/irq.h"
     17#include "migration/vmstate.h"
     18
     19#define GPIOS_PER_GROUP 8
     20
     21/* GPIO Source Types */
     22#define ASPEED_CMD_SRC_MASK         0x01010101
     23#define ASPEED_SOURCE_ARM           0
     24#define ASPEED_SOURCE_LPC           1
     25#define ASPEED_SOURCE_COPROCESSOR   2
     26#define ASPEED_SOURCE_RESERVED      3
     27
     28/* GPIO Interrupt Triggers */
     29/*
     30 *  For each set of gpios there are three sensitivity registers that control
     31 *  the interrupt trigger mode.
     32 *
     33 *  | 2 | 1 | 0 | trigger mode
     34 *  -----------------------------
     35 *  | 0 | 0 | 0 | falling-edge
     36 *  | 0 | 0 | 1 | rising-edge
     37 *  | 0 | 1 | 0 | level-low
     38 *  | 0 | 1 | 1 | level-high
     39 *  | 1 | X | X | dual-edge
     40 */
     41#define ASPEED_FALLING_EDGE 0
     42#define ASPEED_RISING_EDGE  1
     43#define ASPEED_LEVEL_LOW    2
     44#define ASPEED_LEVEL_HIGH   3
     45#define ASPEED_DUAL_EDGE    4
     46
     47/* GPIO Register Address Offsets */
     48#define GPIO_ABCD_DATA_VALUE       (0x000 >> 2)
     49#define GPIO_ABCD_DIRECTION        (0x004 >> 2)
     50#define GPIO_ABCD_INT_ENABLE       (0x008 >> 2)
     51#define GPIO_ABCD_INT_SENS_0       (0x00C >> 2)
     52#define GPIO_ABCD_INT_SENS_1       (0x010 >> 2)
     53#define GPIO_ABCD_INT_SENS_2       (0x014 >> 2)
     54#define GPIO_ABCD_INT_STATUS       (0x018 >> 2)
     55#define GPIO_ABCD_RESET_TOLERANT   (0x01C >> 2)
     56#define GPIO_EFGH_DATA_VALUE       (0x020 >> 2)
     57#define GPIO_EFGH_DIRECTION        (0x024 >> 2)
     58#define GPIO_EFGH_INT_ENABLE       (0x028 >> 2)
     59#define GPIO_EFGH_INT_SENS_0       (0x02C >> 2)
     60#define GPIO_EFGH_INT_SENS_1       (0x030 >> 2)
     61#define GPIO_EFGH_INT_SENS_2       (0x034 >> 2)
     62#define GPIO_EFGH_INT_STATUS       (0x038 >> 2)
     63#define GPIO_EFGH_RESET_TOLERANT   (0x03C >> 2)
     64#define GPIO_ABCD_DEBOUNCE_1       (0x040 >> 2)
     65#define GPIO_ABCD_DEBOUNCE_2       (0x044 >> 2)
     66#define GPIO_EFGH_DEBOUNCE_1       (0x048 >> 2)
     67#define GPIO_EFGH_DEBOUNCE_2       (0x04C >> 2)
     68#define GPIO_DEBOUNCE_TIME_1       (0x050 >> 2)
     69#define GPIO_DEBOUNCE_TIME_2       (0x054 >> 2)
     70#define GPIO_DEBOUNCE_TIME_3       (0x058 >> 2)
     71#define GPIO_ABCD_COMMAND_SRC_0    (0x060 >> 2)
     72#define GPIO_ABCD_COMMAND_SRC_1    (0x064 >> 2)
     73#define GPIO_EFGH_COMMAND_SRC_0    (0x068 >> 2)
     74#define GPIO_EFGH_COMMAND_SRC_1    (0x06C >> 2)
     75#define GPIO_IJKL_DATA_VALUE       (0x070 >> 2)
     76#define GPIO_IJKL_DIRECTION        (0x074 >> 2)
     77#define GPIO_MNOP_DATA_VALUE       (0x078 >> 2)
     78#define GPIO_MNOP_DIRECTION        (0x07C >> 2)
     79#define GPIO_QRST_DATA_VALUE       (0x080 >> 2)
     80#define GPIO_QRST_DIRECTION        (0x084 >> 2)
     81#define GPIO_UVWX_DATA_VALUE       (0x088 >> 2)
     82#define GPIO_UVWX_DIRECTION        (0x08C >> 2)
     83#define GPIO_IJKL_COMMAND_SRC_0    (0x090 >> 2)
     84#define GPIO_IJKL_COMMAND_SRC_1    (0x094 >> 2)
     85#define GPIO_IJKL_INT_ENABLE       (0x098 >> 2)
     86#define GPIO_IJKL_INT_SENS_0       (0x09C >> 2)
     87#define GPIO_IJKL_INT_SENS_1       (0x0A0 >> 2)
     88#define GPIO_IJKL_INT_SENS_2       (0x0A4 >> 2)
     89#define GPIO_IJKL_INT_STATUS       (0x0A8 >> 2)
     90#define GPIO_IJKL_RESET_TOLERANT   (0x0AC >> 2)
     91#define GPIO_IJKL_DEBOUNCE_1       (0x0B0 >> 2)
     92#define GPIO_IJKL_DEBOUNCE_2       (0x0B4 >> 2)
     93#define GPIO_IJKL_INPUT_MASK       (0x0B8 >> 2)
     94#define GPIO_ABCD_DATA_READ        (0x0C0 >> 2)
     95#define GPIO_EFGH_DATA_READ        (0x0C4 >> 2)
     96#define GPIO_IJKL_DATA_READ        (0x0C8 >> 2)
     97#define GPIO_MNOP_DATA_READ        (0x0CC >> 2)
     98#define GPIO_QRST_DATA_READ        (0x0D0 >> 2)
     99#define GPIO_UVWX_DATA_READ        (0x0D4 >> 2)
    100#define GPIO_YZAAAB_DATA_READ      (0x0D8 >> 2)
    101#define GPIO_AC_DATA_READ          (0x0DC >> 2)
    102#define GPIO_MNOP_COMMAND_SRC_0    (0x0E0 >> 2)
    103#define GPIO_MNOP_COMMAND_SRC_1    (0x0E4 >> 2)
    104#define GPIO_MNOP_INT_ENABLE       (0x0E8 >> 2)
    105#define GPIO_MNOP_INT_SENS_0       (0x0EC >> 2)
    106#define GPIO_MNOP_INT_SENS_1       (0x0F0 >> 2)
    107#define GPIO_MNOP_INT_SENS_2       (0x0F4 >> 2)
    108#define GPIO_MNOP_INT_STATUS       (0x0F8 >> 2)
    109#define GPIO_MNOP_RESET_TOLERANT   (0x0FC >> 2)
    110#define GPIO_MNOP_DEBOUNCE_1       (0x100 >> 2)
    111#define GPIO_MNOP_DEBOUNCE_2       (0x104 >> 2)
    112#define GPIO_MNOP_INPUT_MASK       (0x108 >> 2)
    113#define GPIO_QRST_COMMAND_SRC_0    (0x110 >> 2)
    114#define GPIO_QRST_COMMAND_SRC_1    (0x114 >> 2)
    115#define GPIO_QRST_INT_ENABLE       (0x118 >> 2)
    116#define GPIO_QRST_INT_SENS_0       (0x11C >> 2)
    117#define GPIO_QRST_INT_SENS_1       (0x120 >> 2)
    118#define GPIO_QRST_INT_SENS_2       (0x124 >> 2)
    119#define GPIO_QRST_INT_STATUS       (0x128 >> 2)
    120#define GPIO_QRST_RESET_TOLERANT   (0x12C >> 2)
    121#define GPIO_QRST_DEBOUNCE_1       (0x130 >> 2)
    122#define GPIO_QRST_DEBOUNCE_2       (0x134 >> 2)
    123#define GPIO_QRST_INPUT_MASK       (0x138 >> 2)
    124#define GPIO_UVWX_COMMAND_SRC_0    (0x140 >> 2)
    125#define GPIO_UVWX_COMMAND_SRC_1    (0x144 >> 2)
    126#define GPIO_UVWX_INT_ENABLE       (0x148 >> 2)
    127#define GPIO_UVWX_INT_SENS_0       (0x14C >> 2)
    128#define GPIO_UVWX_INT_SENS_1       (0x150 >> 2)
    129#define GPIO_UVWX_INT_SENS_2       (0x154 >> 2)
    130#define GPIO_UVWX_INT_STATUS       (0x158 >> 2)
    131#define GPIO_UVWX_RESET_TOLERANT   (0x15C >> 2)
    132#define GPIO_UVWX_DEBOUNCE_1       (0x160 >> 2)
    133#define GPIO_UVWX_DEBOUNCE_2       (0x164 >> 2)
    134#define GPIO_UVWX_INPUT_MASK       (0x168 >> 2)
    135#define GPIO_YZAAAB_COMMAND_SRC_0  (0x170 >> 2)
    136#define GPIO_YZAAAB_COMMAND_SRC_1  (0x174 >> 2)
    137#define GPIO_YZAAAB_INT_ENABLE     (0x178 >> 2)
    138#define GPIO_YZAAAB_INT_SENS_0     (0x17C >> 2)
    139#define GPIO_YZAAAB_INT_SENS_1     (0x180 >> 2)
    140#define GPIO_YZAAAB_INT_SENS_2     (0x184 >> 2)
    141#define GPIO_YZAAAB_INT_STATUS     (0x188 >> 2)
    142#define GPIO_YZAAAB_RESET_TOLERANT (0x18C >> 2)
    143#define GPIO_YZAAAB_DEBOUNCE_1     (0x190 >> 2)
    144#define GPIO_YZAAAB_DEBOUNCE_2     (0x194 >> 2)
    145#define GPIO_YZAAAB_INPUT_MASK     (0x198 >> 2)
    146#define GPIO_AC_COMMAND_SRC_0      (0x1A0 >> 2)
    147#define GPIO_AC_COMMAND_SRC_1      (0x1A4 >> 2)
    148#define GPIO_AC_INT_ENABLE         (0x1A8 >> 2)
    149#define GPIO_AC_INT_SENS_0         (0x1AC >> 2)
    150#define GPIO_AC_INT_SENS_1         (0x1B0 >> 2)
    151#define GPIO_AC_INT_SENS_2         (0x1B4 >> 2)
    152#define GPIO_AC_INT_STATUS         (0x1B8 >> 2)
    153#define GPIO_AC_RESET_TOLERANT     (0x1BC >> 2)
    154#define GPIO_AC_DEBOUNCE_1         (0x1C0 >> 2)
    155#define GPIO_AC_DEBOUNCE_2         (0x1C4 >> 2)
    156#define GPIO_AC_INPUT_MASK         (0x1C8 >> 2)
    157#define GPIO_ABCD_INPUT_MASK       (0x1D0 >> 2)
    158#define GPIO_EFGH_INPUT_MASK       (0x1D4 >> 2)
    159#define GPIO_YZAAAB_DATA_VALUE     (0x1E0 >> 2)
    160#define GPIO_YZAAAB_DIRECTION      (0x1E4 >> 2)
    161#define GPIO_AC_DATA_VALUE         (0x1E8 >> 2)
    162#define GPIO_AC_DIRECTION          (0x1EC >> 2)
    163#define GPIO_3_3V_MEM_SIZE         0x1F0
    164#define GPIO_3_3V_REG_ARRAY_SIZE   (GPIO_3_3V_MEM_SIZE >> 2)
    165
    166/* AST2600 only - 1.8V gpios */
    167/*
    168 * The AST2600 two copies of the GPIO controller: the same 3.3V gpios as the
    169 * AST2400 (memory offsets 0x0-0x198) and a second controller with 1.8V gpios
    170 * (memory offsets 0x800-0x9D4).
    171 */
    172#define GPIO_1_8V_ABCD_DATA_VALUE     (0x000 >> 2)
    173#define GPIO_1_8V_ABCD_DIRECTION      (0x004 >> 2)
    174#define GPIO_1_8V_ABCD_INT_ENABLE     (0x008 >> 2)
    175#define GPIO_1_8V_ABCD_INT_SENS_0     (0x00C >> 2)
    176#define GPIO_1_8V_ABCD_INT_SENS_1     (0x010 >> 2)
    177#define GPIO_1_8V_ABCD_INT_SENS_2     (0x014 >> 2)
    178#define GPIO_1_8V_ABCD_INT_STATUS     (0x018 >> 2)
    179#define GPIO_1_8V_ABCD_RESET_TOLERANT (0x01C >> 2)
    180#define GPIO_1_8V_E_DATA_VALUE        (0x020 >> 2)
    181#define GPIO_1_8V_E_DIRECTION         (0x024 >> 2)
    182#define GPIO_1_8V_E_INT_ENABLE        (0x028 >> 2)
    183#define GPIO_1_8V_E_INT_SENS_0        (0x02C >> 2)
    184#define GPIO_1_8V_E_INT_SENS_1        (0x030 >> 2)
    185#define GPIO_1_8V_E_INT_SENS_2        (0x034 >> 2)
    186#define GPIO_1_8V_E_INT_STATUS        (0x038 >> 2)
    187#define GPIO_1_8V_E_RESET_TOLERANT    (0x03C >> 2)
    188#define GPIO_1_8V_ABCD_DEBOUNCE_1     (0x040 >> 2)
    189#define GPIO_1_8V_ABCD_DEBOUNCE_2     (0x044 >> 2)
    190#define GPIO_1_8V_E_DEBOUNCE_1        (0x048 >> 2)
    191#define GPIO_1_8V_E_DEBOUNCE_2        (0x04C >> 2)
    192#define GPIO_1_8V_DEBOUNCE_TIME_1     (0x050 >> 2)
    193#define GPIO_1_8V_DEBOUNCE_TIME_2     (0x054 >> 2)
    194#define GPIO_1_8V_DEBOUNCE_TIME_3     (0x058 >> 2)
    195#define GPIO_1_8V_ABCD_COMMAND_SRC_0  (0x060 >> 2)
    196#define GPIO_1_8V_ABCD_COMMAND_SRC_1  (0x064 >> 2)
    197#define GPIO_1_8V_E_COMMAND_SRC_0     (0x068 >> 2)
    198#define GPIO_1_8V_E_COMMAND_SRC_1     (0x06C >> 2)
    199#define GPIO_1_8V_ABCD_DATA_READ      (0x0C0 >> 2)
    200#define GPIO_1_8V_E_DATA_READ         (0x0C4 >> 2)
    201#define GPIO_1_8V_ABCD_INPUT_MASK     (0x1D0 >> 2)
    202#define GPIO_1_8V_E_INPUT_MASK        (0x1D4 >> 2)
    203#define GPIO_1_8V_MEM_SIZE            0x1D8
    204#define GPIO_1_8V_REG_ARRAY_SIZE      (GPIO_1_8V_MEM_SIZE >> 2)
    205
    206static int aspeed_evaluate_irq(GPIOSets *regs, int gpio_prev_high, int gpio)
    207{
    208    uint32_t falling_edge = 0, rising_edge = 0;
    209    uint32_t int_trigger = extract32(regs->int_sens_0, gpio, 1)
    210                           | extract32(regs->int_sens_1, gpio, 1) << 1
    211                           | extract32(regs->int_sens_2, gpio, 1) << 2;
    212    uint32_t gpio_curr_high = extract32(regs->data_value, gpio, 1);
    213    uint32_t gpio_int_enabled = extract32(regs->int_enable, gpio, 1);
    214
    215    if (!gpio_int_enabled) {
    216        return 0;
    217    }
    218
    219    /* Detect edges */
    220    if (gpio_curr_high && !gpio_prev_high) {
    221        rising_edge = 1;
    222    } else if (!gpio_curr_high && gpio_prev_high) {
    223        falling_edge = 1;
    224    }
    225
    226    if (((int_trigger == ASPEED_FALLING_EDGE)  && falling_edge)  ||
    227        ((int_trigger == ASPEED_RISING_EDGE)  && rising_edge)    ||
    228        ((int_trigger == ASPEED_LEVEL_LOW)  && !gpio_curr_high)  ||
    229        ((int_trigger == ASPEED_LEVEL_HIGH)  && gpio_curr_high)  ||
    230        ((int_trigger >= ASPEED_DUAL_EDGE)  && (rising_edge || falling_edge)))
    231    {
    232        regs->int_status = deposit32(regs->int_status, gpio, 1, 1);
    233        return 1;
    234    }
    235    return 0;
    236}
    237
    238#define nested_struct_index(ta, pa, m, tb, pb) \
    239        (pb - ((tb *)(((char *)pa) + offsetof(ta, m))))
    240
    241static ptrdiff_t aspeed_gpio_set_idx(AspeedGPIOState *s, GPIOSets *regs)
    242{
    243    return nested_struct_index(AspeedGPIOState, s, sets, GPIOSets, regs);
    244}
    245
    246static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs,
    247                               uint32_t value)
    248{
    249    uint32_t input_mask = regs->input_mask;
    250    uint32_t direction = regs->direction;
    251    uint32_t old = regs->data_value;
    252    uint32_t new = value;
    253    uint32_t diff;
    254    int gpio;
    255
    256    diff = old ^ new;
    257    if (diff) {
    258        for (gpio = 0; gpio < ASPEED_GPIOS_PER_SET; gpio++) {
    259            uint32_t mask = 1 << gpio;
    260
    261            /* If the gpio needs to be updated... */
    262            if (!(diff & mask)) {
    263                continue;
    264            }
    265
    266            /* ...and we're output or not input-masked... */
    267            if (!(direction & mask) && (input_mask & mask)) {
    268                continue;
    269            }
    270
    271            /* ...then update the state. */
    272            if (mask & new) {
    273                regs->data_value |= mask;
    274            } else {
    275                regs->data_value &= ~mask;
    276            }
    277
    278            /* If the gpio is set to output... */
    279            if (direction & mask) {
    280                /* ...trigger the line-state IRQ */
    281                ptrdiff_t set = aspeed_gpio_set_idx(s, regs);
    282                qemu_set_irq(s->gpios[set][gpio], !!(new & mask));
    283            } else {
    284                /* ...otherwise if we meet the line's current IRQ policy... */
    285                if (aspeed_evaluate_irq(regs, old & mask, gpio)) {
    286                    /* ...trigger the VIC IRQ */
    287                    s->pending++;
    288                }
    289            }
    290        }
    291    }
    292    qemu_set_irq(s->irq, !!(s->pending));
    293}
    294
    295static bool aspeed_gpio_get_pin_level(AspeedGPIOState *s, uint32_t set_idx,
    296                                      uint32_t pin)
    297{
    298    uint32_t reg_val;
    299    uint32_t pin_mask = 1 << pin;
    300
    301    reg_val = s->sets[set_idx].data_value;
    302
    303    return !!(reg_val & pin_mask);
    304}
    305
    306static void aspeed_gpio_set_pin_level(AspeedGPIOState *s, uint32_t set_idx,
    307                                      uint32_t pin, bool level)
    308{
    309    uint32_t value = s->sets[set_idx].data_value;
    310    uint32_t pin_mask = 1 << pin;
    311
    312    if (level) {
    313        value |= pin_mask;
    314    } else {
    315        value &= !pin_mask;
    316    }
    317
    318    aspeed_gpio_update(s, &s->sets[set_idx], value);
    319}
    320
    321/*
    322 *  | src_1 | src_2 |  source     |
    323 *  |-----------------------------|
    324 *  |   0   |   0   |  ARM        |
    325 *  |   0   |   1   |  LPC        |
    326 *  |   1   |   0   |  Coprocessor|
    327 *  |   1   |   1   |  Reserved   |
    328 *
    329 *  Once the source of a set is programmed, corresponding bits in the
    330 *  data_value, direction, interrupt [enable, sens[0-2]], reset_tol and
    331 *  debounce registers can only be written by the source.
    332 *
    333 *  Source is ARM by default
    334 *  only bits 24, 16, 8, and 0 can be set
    335 *
    336 *  we don't currently have a model for the LPC or Coprocessor
    337 */
    338static uint32_t update_value_control_source(GPIOSets *regs, uint32_t old_value,
    339                                            uint32_t value)
    340{
    341    int i;
    342    int cmd_source;
    343
    344    /* assume the source is always ARM for now */
    345    int source = ASPEED_SOURCE_ARM;
    346
    347    uint32_t new_value = 0;
    348
    349    /* for each group in set */
    350    for (i = 0; i < ASPEED_GPIOS_PER_SET; i += GPIOS_PER_GROUP) {
    351        cmd_source = extract32(regs->cmd_source_0, i, 1)
    352                | (extract32(regs->cmd_source_1, i, 1) << 1);
    353
    354        if (source == cmd_source) {
    355            new_value |= (0xff << i) & value;
    356        } else {
    357            new_value |= (0xff << i) & old_value;
    358        }
    359    }
    360    return new_value;
    361}
    362
    363static const AspeedGPIOReg aspeed_3_3v_gpios[GPIO_3_3V_REG_ARRAY_SIZE] = {
    364    /* Set ABCD */
    365    [GPIO_ABCD_DATA_VALUE] =     { 0, gpio_reg_data_value },
    366    [GPIO_ABCD_DIRECTION] =      { 0, gpio_reg_direction },
    367    [GPIO_ABCD_INT_ENABLE] =     { 0, gpio_reg_int_enable },
    368    [GPIO_ABCD_INT_SENS_0] =     { 0, gpio_reg_int_sens_0 },
    369    [GPIO_ABCD_INT_SENS_1] =     { 0, gpio_reg_int_sens_1 },
    370    [GPIO_ABCD_INT_SENS_2] =     { 0, gpio_reg_int_sens_2 },
    371    [GPIO_ABCD_INT_STATUS] =     { 0, gpio_reg_int_status },
    372    [GPIO_ABCD_RESET_TOLERANT] = { 0, gpio_reg_reset_tolerant },
    373    [GPIO_ABCD_DEBOUNCE_1] =     { 0, gpio_reg_debounce_1 },
    374    [GPIO_ABCD_DEBOUNCE_2] =     { 0, gpio_reg_debounce_2 },
    375    [GPIO_ABCD_COMMAND_SRC_0] =  { 0, gpio_reg_cmd_source_0 },
    376    [GPIO_ABCD_COMMAND_SRC_1] =  { 0, gpio_reg_cmd_source_1 },
    377    [GPIO_ABCD_DATA_READ] =      { 0, gpio_reg_data_read },
    378    [GPIO_ABCD_INPUT_MASK] =     { 0, gpio_reg_input_mask },
    379    /* Set EFGH */
    380    [GPIO_EFGH_DATA_VALUE] =     { 1, gpio_reg_data_value },
    381    [GPIO_EFGH_DIRECTION] =      { 1, gpio_reg_direction },
    382    [GPIO_EFGH_INT_ENABLE] =     { 1, gpio_reg_int_enable },
    383    [GPIO_EFGH_INT_SENS_0] =     { 1, gpio_reg_int_sens_0 },
    384    [GPIO_EFGH_INT_SENS_1] =     { 1, gpio_reg_int_sens_1 },
    385    [GPIO_EFGH_INT_SENS_2] =     { 1, gpio_reg_int_sens_2 },
    386    [GPIO_EFGH_INT_STATUS] =     { 1, gpio_reg_int_status },
    387    [GPIO_EFGH_RESET_TOLERANT] = { 1, gpio_reg_reset_tolerant },
    388    [GPIO_EFGH_DEBOUNCE_1] =     { 1, gpio_reg_debounce_1 },
    389    [GPIO_EFGH_DEBOUNCE_2] =     { 1, gpio_reg_debounce_2 },
    390    [GPIO_EFGH_COMMAND_SRC_0] =  { 1, gpio_reg_cmd_source_0 },
    391    [GPIO_EFGH_COMMAND_SRC_1] =  { 1, gpio_reg_cmd_source_1 },
    392    [GPIO_EFGH_DATA_READ] =      { 1, gpio_reg_data_read },
    393    [GPIO_EFGH_INPUT_MASK] =     { 1, gpio_reg_input_mask },
    394    /* Set IJKL */
    395    [GPIO_IJKL_DATA_VALUE] =     { 2, gpio_reg_data_value },
    396    [GPIO_IJKL_DIRECTION] =      { 2, gpio_reg_direction },
    397    [GPIO_IJKL_INT_ENABLE] =     { 2, gpio_reg_int_enable },
    398    [GPIO_IJKL_INT_SENS_0] =     { 2, gpio_reg_int_sens_0 },
    399    [GPIO_IJKL_INT_SENS_1] =     { 2, gpio_reg_int_sens_1 },
    400    [GPIO_IJKL_INT_SENS_2] =     { 2, gpio_reg_int_sens_2 },
    401    [GPIO_IJKL_INT_STATUS] =     { 2, gpio_reg_int_status },
    402    [GPIO_IJKL_RESET_TOLERANT] = { 2, gpio_reg_reset_tolerant },
    403    [GPIO_IJKL_DEBOUNCE_1] =     { 2, gpio_reg_debounce_1 },
    404    [GPIO_IJKL_DEBOUNCE_2] =     { 2, gpio_reg_debounce_2 },
    405    [GPIO_IJKL_COMMAND_SRC_0] =  { 2, gpio_reg_cmd_source_0 },
    406    [GPIO_IJKL_COMMAND_SRC_1] =  { 2, gpio_reg_cmd_source_1 },
    407    [GPIO_IJKL_DATA_READ] =      { 2, gpio_reg_data_read },
    408    [GPIO_IJKL_INPUT_MASK] =     { 2, gpio_reg_input_mask },
    409    /* Set MNOP */
    410    [GPIO_MNOP_DATA_VALUE] =     { 3, gpio_reg_data_value },
    411    [GPIO_MNOP_DIRECTION] =      { 3, gpio_reg_direction },
    412    [GPIO_MNOP_INT_ENABLE] =     { 3, gpio_reg_int_enable },
    413    [GPIO_MNOP_INT_SENS_0] =     { 3, gpio_reg_int_sens_0 },
    414    [GPIO_MNOP_INT_SENS_1] =     { 3, gpio_reg_int_sens_1 },
    415    [GPIO_MNOP_INT_SENS_2] =     { 3, gpio_reg_int_sens_2 },
    416    [GPIO_MNOP_INT_STATUS] =     { 3, gpio_reg_int_status },
    417    [GPIO_MNOP_RESET_TOLERANT] = { 3, gpio_reg_reset_tolerant },
    418    [GPIO_MNOP_DEBOUNCE_1] =     { 3, gpio_reg_debounce_1 },
    419    [GPIO_MNOP_DEBOUNCE_2] =     { 3, gpio_reg_debounce_2 },
    420    [GPIO_MNOP_COMMAND_SRC_0] =  { 3, gpio_reg_cmd_source_0 },
    421    [GPIO_MNOP_COMMAND_SRC_1] =  { 3, gpio_reg_cmd_source_1 },
    422    [GPIO_MNOP_DATA_READ] =      { 3, gpio_reg_data_read },
    423    [GPIO_MNOP_INPUT_MASK] =     { 3, gpio_reg_input_mask },
    424    /* Set QRST */
    425    [GPIO_QRST_DATA_VALUE] =     { 4, gpio_reg_data_value },
    426    [GPIO_QRST_DIRECTION] =      { 4, gpio_reg_direction },
    427    [GPIO_QRST_INT_ENABLE] =     { 4, gpio_reg_int_enable },
    428    [GPIO_QRST_INT_SENS_0] =     { 4, gpio_reg_int_sens_0 },
    429    [GPIO_QRST_INT_SENS_1] =     { 4, gpio_reg_int_sens_1 },
    430    [GPIO_QRST_INT_SENS_2] =     { 4, gpio_reg_int_sens_2 },
    431    [GPIO_QRST_INT_STATUS] =     { 4, gpio_reg_int_status },
    432    [GPIO_QRST_RESET_TOLERANT] = { 4, gpio_reg_reset_tolerant },
    433    [GPIO_QRST_DEBOUNCE_1] =     { 4, gpio_reg_debounce_1 },
    434    [GPIO_QRST_DEBOUNCE_2] =     { 4, gpio_reg_debounce_2 },
    435    [GPIO_QRST_COMMAND_SRC_0] =  { 4, gpio_reg_cmd_source_0 },
    436    [GPIO_QRST_COMMAND_SRC_1] =  { 4, gpio_reg_cmd_source_1 },
    437    [GPIO_QRST_DATA_READ] =      { 4, gpio_reg_data_read },
    438    [GPIO_QRST_INPUT_MASK] =     { 4, gpio_reg_input_mask },
    439    /* Set UVWX */
    440    [GPIO_UVWX_DATA_VALUE] =     { 5, gpio_reg_data_value },
    441    [GPIO_UVWX_DIRECTION] =      { 5, gpio_reg_direction },
    442    [GPIO_UVWX_INT_ENABLE] =     { 5, gpio_reg_int_enable },
    443    [GPIO_UVWX_INT_SENS_0] =     { 5, gpio_reg_int_sens_0 },
    444    [GPIO_UVWX_INT_SENS_1] =     { 5, gpio_reg_int_sens_1 },
    445    [GPIO_UVWX_INT_SENS_2] =     { 5, gpio_reg_int_sens_2 },
    446    [GPIO_UVWX_INT_STATUS] =     { 5, gpio_reg_int_status },
    447    [GPIO_UVWX_RESET_TOLERANT] = { 5, gpio_reg_reset_tolerant },
    448    [GPIO_UVWX_DEBOUNCE_1] =     { 5, gpio_reg_debounce_1 },
    449    [GPIO_UVWX_DEBOUNCE_2] =     { 5, gpio_reg_debounce_2 },
    450    [GPIO_UVWX_COMMAND_SRC_0] =  { 5, gpio_reg_cmd_source_0 },
    451    [GPIO_UVWX_COMMAND_SRC_1] =  { 5, gpio_reg_cmd_source_1 },
    452    [GPIO_UVWX_DATA_READ] =      { 5, gpio_reg_data_read },
    453    [GPIO_UVWX_INPUT_MASK] =     { 5, gpio_reg_input_mask },
    454    /* Set YZAAAB */
    455    [GPIO_YZAAAB_DATA_VALUE] =     { 6, gpio_reg_data_value },
    456    [GPIO_YZAAAB_DIRECTION] =      { 6, gpio_reg_direction },
    457    [GPIO_YZAAAB_INT_ENABLE] =     { 6, gpio_reg_int_enable },
    458    [GPIO_YZAAAB_INT_SENS_0] =     { 6, gpio_reg_int_sens_0 },
    459    [GPIO_YZAAAB_INT_SENS_1] =     { 6, gpio_reg_int_sens_1 },
    460    [GPIO_YZAAAB_INT_SENS_2] =     { 6, gpio_reg_int_sens_2 },
    461    [GPIO_YZAAAB_INT_STATUS] =     { 6, gpio_reg_int_status },
    462    [GPIO_YZAAAB_RESET_TOLERANT] = { 6, gpio_reg_reset_tolerant },
    463    [GPIO_YZAAAB_DEBOUNCE_1] =     { 6, gpio_reg_debounce_1 },
    464    [GPIO_YZAAAB_DEBOUNCE_2] =     { 6, gpio_reg_debounce_2 },
    465    [GPIO_YZAAAB_COMMAND_SRC_0] =  { 6, gpio_reg_cmd_source_0 },
    466    [GPIO_YZAAAB_COMMAND_SRC_1] =  { 6, gpio_reg_cmd_source_1 },
    467    [GPIO_YZAAAB_DATA_READ] =      { 6, gpio_reg_data_read },
    468    [GPIO_YZAAAB_INPUT_MASK] =     { 6, gpio_reg_input_mask },
    469    /* Set AC  (ast2500 only) */
    470    [GPIO_AC_DATA_VALUE] =         { 7, gpio_reg_data_value },
    471    [GPIO_AC_DIRECTION] =          { 7, gpio_reg_direction },
    472    [GPIO_AC_INT_ENABLE] =         { 7, gpio_reg_int_enable },
    473    [GPIO_AC_INT_SENS_0] =         { 7, gpio_reg_int_sens_0 },
    474    [GPIO_AC_INT_SENS_1] =         { 7, gpio_reg_int_sens_1 },
    475    [GPIO_AC_INT_SENS_2] =         { 7, gpio_reg_int_sens_2 },
    476    [GPIO_AC_INT_STATUS] =         { 7, gpio_reg_int_status },
    477    [GPIO_AC_RESET_TOLERANT] =     { 7, gpio_reg_reset_tolerant },
    478    [GPIO_AC_DEBOUNCE_1] =         { 7, gpio_reg_debounce_1 },
    479    [GPIO_AC_DEBOUNCE_2] =         { 7, gpio_reg_debounce_2 },
    480    [GPIO_AC_COMMAND_SRC_0] =      { 7, gpio_reg_cmd_source_0 },
    481    [GPIO_AC_COMMAND_SRC_1] =      { 7, gpio_reg_cmd_source_1 },
    482    [GPIO_AC_DATA_READ] =          { 7, gpio_reg_data_read },
    483    [GPIO_AC_INPUT_MASK] =         { 7, gpio_reg_input_mask },
    484};
    485
    486static const AspeedGPIOReg aspeed_1_8v_gpios[GPIO_1_8V_REG_ARRAY_SIZE] = {
    487    /* 1.8V Set ABCD */
    488    [GPIO_1_8V_ABCD_DATA_VALUE] =     {0, gpio_reg_data_value},
    489    [GPIO_1_8V_ABCD_DIRECTION] =      {0, gpio_reg_direction},
    490    [GPIO_1_8V_ABCD_INT_ENABLE] =     {0, gpio_reg_int_enable},
    491    [GPIO_1_8V_ABCD_INT_SENS_0] =     {0, gpio_reg_int_sens_0},
    492    [GPIO_1_8V_ABCD_INT_SENS_1] =     {0, gpio_reg_int_sens_1},
    493    [GPIO_1_8V_ABCD_INT_SENS_2] =     {0, gpio_reg_int_sens_2},
    494    [GPIO_1_8V_ABCD_INT_STATUS] =     {0, gpio_reg_int_status},
    495    [GPIO_1_8V_ABCD_RESET_TOLERANT] = {0, gpio_reg_reset_tolerant},
    496    [GPIO_1_8V_ABCD_DEBOUNCE_1] =     {0, gpio_reg_debounce_1},
    497    [GPIO_1_8V_ABCD_DEBOUNCE_2] =     {0, gpio_reg_debounce_2},
    498    [GPIO_1_8V_ABCD_COMMAND_SRC_0] =  {0, gpio_reg_cmd_source_0},
    499    [GPIO_1_8V_ABCD_COMMAND_SRC_1] =  {0, gpio_reg_cmd_source_1},
    500    [GPIO_1_8V_ABCD_DATA_READ] =      {0, gpio_reg_data_read},
    501    [GPIO_1_8V_ABCD_INPUT_MASK] =     {0, gpio_reg_input_mask},
    502    /* 1.8V Set E */
    503    [GPIO_1_8V_E_DATA_VALUE] =     {1, gpio_reg_data_value},
    504    [GPIO_1_8V_E_DIRECTION] =      {1, gpio_reg_direction},
    505    [GPIO_1_8V_E_INT_ENABLE] =     {1, gpio_reg_int_enable},
    506    [GPIO_1_8V_E_INT_SENS_0] =     {1, gpio_reg_int_sens_0},
    507    [GPIO_1_8V_E_INT_SENS_1] =     {1, gpio_reg_int_sens_1},
    508    [GPIO_1_8V_E_INT_SENS_2] =     {1, gpio_reg_int_sens_2},
    509    [GPIO_1_8V_E_INT_STATUS] =     {1, gpio_reg_int_status},
    510    [GPIO_1_8V_E_RESET_TOLERANT] = {1, gpio_reg_reset_tolerant},
    511    [GPIO_1_8V_E_DEBOUNCE_1] =     {1, gpio_reg_debounce_1},
    512    [GPIO_1_8V_E_DEBOUNCE_2] =     {1, gpio_reg_debounce_2},
    513    [GPIO_1_8V_E_COMMAND_SRC_0] =  {1, gpio_reg_cmd_source_0},
    514    [GPIO_1_8V_E_COMMAND_SRC_1] =  {1, gpio_reg_cmd_source_1},
    515    [GPIO_1_8V_E_DATA_READ] =      {1, gpio_reg_data_read},
    516    [GPIO_1_8V_E_INPUT_MASK] =     {1, gpio_reg_input_mask},
    517};
    518
    519static uint64_t aspeed_gpio_read(void *opaque, hwaddr offset, uint32_t size)
    520{
    521    AspeedGPIOState *s = ASPEED_GPIO(opaque);
    522    AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
    523    uint64_t idx = -1;
    524    const AspeedGPIOReg *reg;
    525    GPIOSets *set;
    526
    527    idx = offset >> 2;
    528    if (idx >= GPIO_DEBOUNCE_TIME_1 && idx <= GPIO_DEBOUNCE_TIME_3) {
    529        idx -= GPIO_DEBOUNCE_TIME_1;
    530        return (uint64_t) s->debounce_regs[idx];
    531    }
    532
    533    reg = &agc->reg_table[idx];
    534    if (reg->set_idx >= agc->nr_gpio_sets) {
    535        qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%"
    536                      HWADDR_PRIx"\n", __func__, offset);
    537        return 0;
    538    }
    539
    540    set = &s->sets[reg->set_idx];
    541    switch (reg->type) {
    542    case gpio_reg_data_value:
    543        return set->data_value;
    544    case gpio_reg_direction:
    545        return set->direction;
    546    case gpio_reg_int_enable:
    547        return set->int_enable;
    548    case gpio_reg_int_sens_0:
    549        return set->int_sens_0;
    550    case gpio_reg_int_sens_1:
    551        return set->int_sens_1;
    552    case gpio_reg_int_sens_2:
    553        return set->int_sens_2;
    554    case gpio_reg_int_status:
    555        return set->int_status;
    556    case gpio_reg_reset_tolerant:
    557        return set->reset_tol;
    558    case gpio_reg_debounce_1:
    559        return set->debounce_1;
    560    case gpio_reg_debounce_2:
    561        return set->debounce_2;
    562    case gpio_reg_cmd_source_0:
    563        return set->cmd_source_0;
    564    case gpio_reg_cmd_source_1:
    565        return set->cmd_source_1;
    566    case gpio_reg_data_read:
    567        return set->data_read;
    568    case gpio_reg_input_mask:
    569        return set->input_mask;
    570    default:
    571        qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%"
    572                      HWADDR_PRIx"\n", __func__, offset);
    573        return 0;
    574    };
    575}
    576
    577static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data,
    578                              uint32_t size)
    579{
    580    AspeedGPIOState *s = ASPEED_GPIO(opaque);
    581    AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
    582    const GPIOSetProperties *props;
    583    uint64_t idx = -1;
    584    const AspeedGPIOReg *reg;
    585    GPIOSets *set;
    586    uint32_t cleared;
    587
    588    idx = offset >> 2;
    589    if (idx >= GPIO_DEBOUNCE_TIME_1 && idx <= GPIO_DEBOUNCE_TIME_3) {
    590        idx -= GPIO_DEBOUNCE_TIME_1;
    591        s->debounce_regs[idx] = (uint32_t) data;
    592        return;
    593    }
    594
    595    reg = &agc->reg_table[idx];
    596    if (reg->set_idx >= agc->nr_gpio_sets) {
    597        qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%"
    598                      HWADDR_PRIx"\n", __func__, offset);
    599        return;
    600    }
    601
    602    set = &s->sets[reg->set_idx];
    603    props = &agc->props[reg->set_idx];
    604
    605    switch (reg->type) {
    606    case gpio_reg_data_value:
    607        data &= props->output;
    608        data = update_value_control_source(set, set->data_value, data);
    609        set->data_read = data;
    610        aspeed_gpio_update(s, set, data);
    611        return;
    612    case gpio_reg_direction:
    613        /*
    614         *   where data is the value attempted to be written to the pin:
    615         *    pin type      | input mask | output mask | expected value
    616         *    ------------------------------------------------------------
    617         *   bidirectional  |   1       |   1        |  data
    618         *   input only     |   1       |   0        |   0
    619         *   output only    |   0       |   1        |   1
    620         *   no pin         |   0       |   0        |   0
    621         *
    622         *  which is captured by:
    623         *  data = ( data | ~input) & output;
    624         */
    625        data = (data | ~props->input) & props->output;
    626        set->direction = update_value_control_source(set, set->direction, data);
    627        break;
    628    case gpio_reg_int_enable:
    629        set->int_enable = update_value_control_source(set, set->int_enable,
    630                                                      data);
    631        break;
    632    case gpio_reg_int_sens_0:
    633        set->int_sens_0 = update_value_control_source(set, set->int_sens_0,
    634                                                      data);
    635        break;
    636    case gpio_reg_int_sens_1:
    637        set->int_sens_1 = update_value_control_source(set, set->int_sens_1,
    638                                                      data);
    639        break;
    640    case gpio_reg_int_sens_2:
    641        set->int_sens_2 = update_value_control_source(set, set->int_sens_2,
    642                                                      data);
    643        break;
    644    case gpio_reg_int_status:
    645        cleared = ctpop32(data & set->int_status);
    646        if (s->pending && cleared) {
    647            assert(s->pending >= cleared);
    648            s->pending -= cleared;
    649        }
    650        set->int_status &= ~data;
    651        break;
    652    case gpio_reg_reset_tolerant:
    653        set->reset_tol = update_value_control_source(set, set->reset_tol,
    654                                                     data);
    655        return;
    656    case gpio_reg_debounce_1:
    657        set->debounce_1 = update_value_control_source(set, set->debounce_1,
    658                                                      data);
    659        return;
    660    case gpio_reg_debounce_2:
    661        set->debounce_2 = update_value_control_source(set, set->debounce_2,
    662                                                      data);
    663        return;
    664    case gpio_reg_cmd_source_0:
    665        set->cmd_source_0 = data & ASPEED_CMD_SRC_MASK;
    666        return;
    667    case gpio_reg_cmd_source_1:
    668        set->cmd_source_1 = data & ASPEED_CMD_SRC_MASK;
    669        return;
    670    case gpio_reg_data_read:
    671        /* Read only register */
    672        return;
    673    case gpio_reg_input_mask:
    674        /*
    675         * feeds into interrupt generation
    676         * 0: read from data value reg will be updated
    677         * 1: read from data value reg will not be updated
    678         */
    679         set->input_mask = data & props->input;
    680        break;
    681    default:
    682        qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%"
    683                      HWADDR_PRIx"\n", __func__, offset);
    684        return;
    685    }
    686    aspeed_gpio_update(s, set, set->data_value);
    687    return;
    688}
    689
    690static int get_set_idx(AspeedGPIOState *s, const char *group, int *group_idx)
    691{
    692    AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
    693    int set_idx, g_idx;
    694
    695    for (set_idx = 0; set_idx < agc->nr_gpio_sets; set_idx++) {
    696        const GPIOSetProperties *set_props = &agc->props[set_idx];
    697        for (g_idx = 0; g_idx < ASPEED_GROUPS_PER_SET; g_idx++) {
    698            if (!strncmp(group, set_props->group_label[g_idx], strlen(group))) {
    699                *group_idx = g_idx;
    700                return set_idx;
    701            }
    702        }
    703    }
    704    return -1;
    705}
    706
    707static void aspeed_gpio_get_pin(Object *obj, Visitor *v, const char *name,
    708                                void *opaque, Error **errp)
    709{
    710    int pin = 0xfff;
    711    bool level = true;
    712    char group[4];
    713    AspeedGPIOState *s = ASPEED_GPIO(obj);
    714    int set_idx, group_idx = 0;
    715
    716    if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
    717        /* 1.8V gpio */
    718        if (sscanf(name, "gpio%3[18A-E]%1d", group, &pin) != 2) {
    719            error_setg(errp, "%s: error reading %s", __func__, name);
    720            return;
    721        }
    722    }
    723    set_idx = get_set_idx(s, group, &group_idx);
    724    if (set_idx == -1) {
    725        error_setg(errp, "%s: invalid group %s", __func__, group);
    726        return;
    727    }
    728    pin =  pin + group_idx * GPIOS_PER_GROUP;
    729    level = aspeed_gpio_get_pin_level(s, set_idx, pin);
    730    visit_type_bool(v, name, &level, errp);
    731}
    732
    733static void aspeed_gpio_set_pin(Object *obj, Visitor *v, const char *name,
    734                               void *opaque, Error **errp)
    735{
    736    bool level;
    737    int pin = 0xfff;
    738    char group[4];
    739    AspeedGPIOState *s = ASPEED_GPIO(obj);
    740    int set_idx, group_idx = 0;
    741
    742    if (!visit_type_bool(v, name, &level, errp)) {
    743        return;
    744    }
    745    if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
    746        /* 1.8V gpio */
    747        if (sscanf(name, "gpio%3[18A-E]%1d", group, &pin) != 2) {
    748            error_setg(errp, "%s: error reading %s", __func__, name);
    749            return;
    750        }
    751    }
    752    set_idx = get_set_idx(s, group, &group_idx);
    753    if (set_idx == -1) {
    754        error_setg(errp, "%s: invalid group %s", __func__, group);
    755        return;
    756    }
    757    pin =  pin + group_idx * GPIOS_PER_GROUP;
    758    aspeed_gpio_set_pin_level(s, set_idx, pin, level);
    759}
    760
    761/****************** Setup functions ******************/
    762static const GPIOSetProperties ast2400_set_props[ASPEED_GPIO_MAX_NR_SETS] = {
    763    [0] = {0xffffffff,  0xffffffff,  {"A", "B", "C", "D"} },
    764    [1] = {0xffffffff,  0xffffffff,  {"E", "F", "G", "H"} },
    765    [2] = {0xffffffff,  0xffffffff,  {"I", "J", "K", "L"} },
    766    [3] = {0xffffffff,  0xffffffff,  {"M", "N", "O", "P"} },
    767    [4] = {0xffffffff,  0xffffffff,  {"Q", "R", "S", "T"} },
    768    [5] = {0xffffffff,  0x0000ffff,  {"U", "V", "W", "X"} },
    769    [6] = {0x0000000f,  0x0fffff0f,  {"Y", "Z", "AA", "AB"} },
    770};
    771
    772static const GPIOSetProperties ast2500_set_props[ASPEED_GPIO_MAX_NR_SETS] = {
    773    [0] = {0xffffffff,  0xffffffff,  {"A", "B", "C", "D"} },
    774    [1] = {0xffffffff,  0xffffffff,  {"E", "F", "G", "H"} },
    775    [2] = {0xffffffff,  0xffffffff,  {"I", "J", "K", "L"} },
    776    [3] = {0xffffffff,  0xffffffff,  {"M", "N", "O", "P"} },
    777    [4] = {0xffffffff,  0xffffffff,  {"Q", "R", "S", "T"} },
    778    [5] = {0xffffffff,  0x0000ffff,  {"U", "V", "W", "X"} },
    779    [6] = {0x0fffffff,  0x0fffffff,  {"Y", "Z", "AA", "AB"} },
    780    [7] = {0x000000ff,  0x000000ff,  {"AC"} },
    781};
    782
    783static GPIOSetProperties ast2600_3_3v_set_props[ASPEED_GPIO_MAX_NR_SETS] = {
    784    [0] = {0xffffffff,  0xffffffff,  {"A", "B", "C", "D"} },
    785    [1] = {0xffffffff,  0xffffffff,  {"E", "F", "G", "H"} },
    786    [2] = {0xffffffff,  0xffffffff,  {"I", "J", "K", "L"} },
    787    [3] = {0xffffffff,  0xffffffff,  {"M", "N", "O", "P"} },
    788    [4] = {0xffffffff,  0x00ffffff,  {"Q", "R", "S", "T"} },
    789    [5] = {0xffffffff,  0xffffff00,  {"U", "V", "W", "X"} },
    790    [6] = {0x0000ffff,  0x0000ffff,  {"Y", "Z"} },
    791};
    792
    793static GPIOSetProperties ast2600_1_8v_set_props[ASPEED_GPIO_MAX_NR_SETS] = {
    794    [0] = {0xffffffff,  0xffffffff,  {"18A", "18B", "18C", "18D"} },
    795    [1] = {0x0000000f,  0x0000000f,  {"18E"} },
    796};
    797
    798static const MemoryRegionOps aspeed_gpio_ops = {
    799    .read       = aspeed_gpio_read,
    800    .write      = aspeed_gpio_write,
    801    .endianness = DEVICE_LITTLE_ENDIAN,
    802    .valid.min_access_size = 4,
    803    .valid.max_access_size = 4,
    804};
    805
    806static void aspeed_gpio_reset(DeviceState *dev)
    807{
    808    AspeedGPIOState *s = ASPEED_GPIO(dev);
    809
    810    /* TODO: respect the reset tolerance registers */
    811    memset(s->sets, 0, sizeof(s->sets));
    812}
    813
    814static void aspeed_gpio_realize(DeviceState *dev, Error **errp)
    815{
    816    AspeedGPIOState *s = ASPEED_GPIO(dev);
    817    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    818    AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
    819
    820    /* Interrupt parent line */
    821    sysbus_init_irq(sbd, &s->irq);
    822
    823    /* Individual GPIOs */
    824    for (int i = 0; i < ASPEED_GPIO_MAX_NR_SETS; i++) {
    825        const GPIOSetProperties *props = &agc->props[i];
    826        uint32_t skip = ~(props->input | props->output);
    827        for (int j = 0; j < ASPEED_GPIOS_PER_SET; j++) {
    828            if (skip >> j & 1) {
    829                continue;
    830            }
    831            sysbus_init_irq(sbd, &s->gpios[i][j]);
    832        }
    833    }
    834
    835    memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_gpio_ops, s,
    836            TYPE_ASPEED_GPIO, 0x800);
    837
    838    sysbus_init_mmio(sbd, &s->iomem);
    839}
    840
    841static void aspeed_gpio_init(Object *obj)
    842{
    843    AspeedGPIOState *s = ASPEED_GPIO(obj);
    844    AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
    845
    846    for (int i = 0; i < ASPEED_GPIO_MAX_NR_SETS; i++) {
    847        const GPIOSetProperties *props = &agc->props[i];
    848        uint32_t skip = ~(props->input | props->output);
    849        for (int j = 0; j < ASPEED_GPIOS_PER_SET; j++) {
    850            if (skip >> j & 1) {
    851                continue;
    852            }
    853            int group_idx = j / GPIOS_PER_GROUP;
    854            int pin_idx = j % GPIOS_PER_GROUP;
    855            const char *group = &props->group_label[group_idx][0];
    856            char *name = g_strdup_printf("gpio%s%d", group, pin_idx);
    857            object_property_add(obj, name, "bool", aspeed_gpio_get_pin,
    858                                aspeed_gpio_set_pin, NULL, NULL);
    859            g_free(name);
    860        }
    861    }
    862}
    863
    864static const VMStateDescription vmstate_gpio_regs = {
    865    .name = TYPE_ASPEED_GPIO"/regs",
    866    .version_id = 1,
    867    .minimum_version_id = 1,
    868    .fields = (VMStateField[]) {
    869        VMSTATE_UINT32(data_value,   GPIOSets),
    870        VMSTATE_UINT32(data_read,    GPIOSets),
    871        VMSTATE_UINT32(direction,    GPIOSets),
    872        VMSTATE_UINT32(int_enable,   GPIOSets),
    873        VMSTATE_UINT32(int_sens_0,   GPIOSets),
    874        VMSTATE_UINT32(int_sens_1,   GPIOSets),
    875        VMSTATE_UINT32(int_sens_2,   GPIOSets),
    876        VMSTATE_UINT32(int_status,   GPIOSets),
    877        VMSTATE_UINT32(reset_tol,    GPIOSets),
    878        VMSTATE_UINT32(cmd_source_0, GPIOSets),
    879        VMSTATE_UINT32(cmd_source_1, GPIOSets),
    880        VMSTATE_UINT32(debounce_1,   GPIOSets),
    881        VMSTATE_UINT32(debounce_2,   GPIOSets),
    882        VMSTATE_UINT32(input_mask,   GPIOSets),
    883        VMSTATE_END_OF_LIST(),
    884    }
    885};
    886
    887static const VMStateDescription vmstate_aspeed_gpio = {
    888    .name = TYPE_ASPEED_GPIO,
    889    .version_id = 1,
    890    .minimum_version_id = 1,
    891    .fields = (VMStateField[]) {
    892        VMSTATE_STRUCT_ARRAY(sets, AspeedGPIOState, ASPEED_GPIO_MAX_NR_SETS,
    893                             1, vmstate_gpio_regs, GPIOSets),
    894        VMSTATE_UINT32_ARRAY(debounce_regs, AspeedGPIOState,
    895                             ASPEED_GPIO_NR_DEBOUNCE_REGS),
    896        VMSTATE_END_OF_LIST(),
    897   }
    898};
    899
    900static void aspeed_gpio_class_init(ObjectClass *klass, void *data)
    901{
    902    DeviceClass *dc = DEVICE_CLASS(klass);
    903
    904    dc->realize = aspeed_gpio_realize;
    905    dc->reset = aspeed_gpio_reset;
    906    dc->desc = "Aspeed GPIO Controller";
    907    dc->vmsd = &vmstate_aspeed_gpio;
    908}
    909
    910static void aspeed_gpio_ast2400_class_init(ObjectClass *klass, void *data)
    911{
    912    AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass);
    913
    914    agc->props = ast2400_set_props;
    915    agc->nr_gpio_pins = 216;
    916    agc->nr_gpio_sets = 7;
    917    agc->reg_table = aspeed_3_3v_gpios;
    918}
    919
    920static void aspeed_gpio_2500_class_init(ObjectClass *klass, void *data)
    921{
    922    AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass);
    923
    924    agc->props = ast2500_set_props;
    925    agc->nr_gpio_pins = 228;
    926    agc->nr_gpio_sets = 8;
    927    agc->reg_table = aspeed_3_3v_gpios;
    928}
    929
    930static void aspeed_gpio_ast2600_3_3v_class_init(ObjectClass *klass, void *data)
    931{
    932    AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass);
    933
    934    agc->props = ast2600_3_3v_set_props;
    935    agc->nr_gpio_pins = 208;
    936    agc->nr_gpio_sets = 7;
    937    agc->reg_table = aspeed_3_3v_gpios;
    938}
    939
    940static void aspeed_gpio_ast2600_1_8v_class_init(ObjectClass *klass, void *data)
    941{
    942    AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass);
    943
    944    agc->props = ast2600_1_8v_set_props;
    945    agc->nr_gpio_pins = 36;
    946    agc->nr_gpio_sets = 2;
    947    agc->reg_table = aspeed_1_8v_gpios;
    948}
    949
    950static const TypeInfo aspeed_gpio_info = {
    951    .name           = TYPE_ASPEED_GPIO,
    952    .parent         = TYPE_SYS_BUS_DEVICE,
    953    .instance_size  = sizeof(AspeedGPIOState),
    954    .class_size     = sizeof(AspeedGPIOClass),
    955    .class_init     = aspeed_gpio_class_init,
    956    .abstract       = true,
    957};
    958
    959static const TypeInfo aspeed_gpio_ast2400_info = {
    960    .name           = TYPE_ASPEED_GPIO "-ast2400",
    961    .parent         = TYPE_ASPEED_GPIO,
    962    .class_init     = aspeed_gpio_ast2400_class_init,
    963    .instance_init  = aspeed_gpio_init,
    964};
    965
    966static const TypeInfo aspeed_gpio_ast2500_info = {
    967    .name           = TYPE_ASPEED_GPIO "-ast2500",
    968    .parent         = TYPE_ASPEED_GPIO,
    969    .class_init     = aspeed_gpio_2500_class_init,
    970    .instance_init  = aspeed_gpio_init,
    971};
    972
    973static const TypeInfo aspeed_gpio_ast2600_3_3v_info = {
    974    .name           = TYPE_ASPEED_GPIO "-ast2600",
    975    .parent         = TYPE_ASPEED_GPIO,
    976    .class_init     = aspeed_gpio_ast2600_3_3v_class_init,
    977    .instance_init  = aspeed_gpio_init,
    978};
    979
    980static const TypeInfo aspeed_gpio_ast2600_1_8v_info = {
    981    .name           = TYPE_ASPEED_GPIO "-ast2600-1_8v",
    982    .parent         = TYPE_ASPEED_GPIO,
    983    .class_init     = aspeed_gpio_ast2600_1_8v_class_init,
    984    .instance_init  = aspeed_gpio_init,
    985};
    986
    987static void aspeed_gpio_register_types(void)
    988{
    989    type_register_static(&aspeed_gpio_info);
    990    type_register_static(&aspeed_gpio_ast2400_info);
    991    type_register_static(&aspeed_gpio_ast2500_info);
    992    type_register_static(&aspeed_gpio_ast2600_3_3v_info);
    993    type_register_static(&aspeed_gpio_ast2600_1_8v_info);
    994}
    995
    996type_init(aspeed_gpio_register_types);