qemu/hw/gpio/aspeed_gpio.c
<<
>>
Prefs
   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);
 997