From nobody Sun Nov 24 04:59:55 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1727422727; cv=none; d=zohomail.com; s=zohoarc; b=az6rAS5iKll9cfU5vaJub9HBbTLqENcAwlbtwkqwkB1mn+svzSLBRgtJaGdP6xsUatMohppTsgPyD8jqOX/M7o8SMUUNNl+r/mkSaVCKjWJgjaU5CVyZI0WGxsJqyEONPMYNNsb/JKUfGw1LyVKhclljI7EWjWIlBmF05jTiHQ8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1727422727; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=+StOGo4K1Dl44bqd4Uo7/oijQw4w9tpvjfKwm7UbaCE=; b=jnNwwEXkd9hHNPGovfpEXpSNFHBwuL1WvMYshKpFQzINtMtPG6b1DNTAy8cNT3o6e3cqSKA5n2JX9yMO7RY1XMUSyScG70cyjFl4EANUoLrXRmi5wuAmWuWDfkpzxt0u9Hmq3J2Mur9jdq23WuLb9WIT4hxsYjpx8l1ApTEFbus= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1727422727560514.2072193543211; Fri, 27 Sep 2024 00:38:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1su5Sc-00029w-PJ; Fri, 27 Sep 2024 03:32:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1su5Sa-0001z1-0i; Fri, 27 Sep 2024 03:32:16 -0400 Received: from mail.aspeedtech.com ([211.20.114.72] helo=TWMBX01.aspeed.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1su5SX-0004DY-ML; Fri, 27 Sep 2024 03:32:15 -0400 Received: from TWMBX01.aspeed.com (192.168.0.62) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1258.12; Fri, 27 Sep 2024 15:31:45 +0800 Received: from localhost.localdomain (192.168.10.10) by TWMBX01.aspeed.com (192.168.0.62) with Microsoft SMTP Server id 15.2.1258.12 via Frontend Transport; Fri, 27 Sep 2024 15:31:45 +0800 To: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , Peter Maydell , Steven Lee , Troy Lee , Andrew Jeffery , "Joel Stanley" , Thomas Huth , Laurent Vivier , Paolo Bonzini , "open list:ASPEED BMCs" , "open list:All patches CC here" CC: , , Subject: [PATCH v4 5/7] hw/gpio/aspeed: Add AST2700 support Date: Fri, 27 Sep 2024 15:31:42 +0800 Message-ID: <20240927073144.2303522-6-jamin_lin@aspeedtech.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240927073144.2303522-1-jamin_lin@aspeedtech.com> References: <20240927073144.2303522-1-jamin_lin@aspeedtech.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=211.20.114.72; envelope-from=jamin_lin@aspeedtech.com; helo=TWMBX01.aspeed.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_FAIL=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: Jamin Lin From: Jamin Lin via Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1727422745240116600 AST2700 integrates two set of Parallel GPIO Controller with maximum 212 control pins, which are 27 groups. (H, exclude pin: H7 H6 H5 H4) In the previous design of ASPEED SOCs, one register is used for setting one function for one set which are 32 pins and 4 groups. ex: GPIO000 is used for setting data value for GPIO A, B, C and D in AST260= 0. ex: GPIO004 is used for setting direction for GPIO A, B, C and D in AST2600. However, the register set have a significant change since AST2700. Each GPIO pin has their own individual control register. In other words, users are able to set one GPIO pin=E2=80=99s direction, interrupt enable, input mask and so on in the same one register. Currently, aspeed_gpio_read and aspeed_gpio_write callback functions are not compatible AST2700. Introduce new aspeed_gpio_2700_read and aspeed_gpio_2700_write callback functions and aspeed_gpio_2700_ops memory region operation for AST2700. Introduce a new ast2700 class to support AST2700. Signed-off-by: Jamin Lin Reviewed-by: Andrew Jeffery --- hw/gpio/aspeed_gpio.c | 380 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 380 insertions(+) diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c index 16c18ea2f7..a5b3f454e8 100644 --- a/hw/gpio/aspeed_gpio.c +++ b/hw/gpio/aspeed_gpio.c @@ -227,6 +227,38 @@ REG32(GPIO_INDEX_REG, 0x2AC) FIELD(GPIO_INDEX_REG, COMMAND_SRC_1, 21, 1) FIELD(GPIO_INDEX_REG, INPUT_MASK, 20, 1) =20 +/* AST2700 GPIO Register Address Offsets */ +REG32(GPIO_2700_DEBOUNCE_TIME_1, 0x000) +REG32(GPIO_2700_DEBOUNCE_TIME_2, 0x004) +REG32(GPIO_2700_DEBOUNCE_TIME_3, 0x008) +REG32(GPIO_2700_INT_STATUS_1, 0x100) +REG32(GPIO_2700_INT_STATUS_2, 0x104) +REG32(GPIO_2700_INT_STATUS_3, 0x108) +REG32(GPIO_2700_INT_STATUS_4, 0x10C) +REG32(GPIO_2700_INT_STATUS_5, 0x110) +REG32(GPIO_2700_INT_STATUS_6, 0x114) +REG32(GPIO_2700_INT_STATUS_7, 0x118) +/* GPIOA0 - GPIOAA7 Control Register */ +REG32(GPIO_A0_CONTROL, 0x180) + SHARED_FIELD(GPIO_CONTROL_OUT_DATA, 0, 1) + SHARED_FIELD(GPIO_CONTROL_DIRECTION, 1, 1) + SHARED_FIELD(GPIO_CONTROL_INT_ENABLE, 2, 1) + SHARED_FIELD(GPIO_CONTROL_INT_SENS_0, 3, 1) + SHARED_FIELD(GPIO_CONTROL_INT_SENS_1, 4, 1) + SHARED_FIELD(GPIO_CONTROL_INT_SENS_2, 5, 1) + SHARED_FIELD(GPIO_CONTROL_RESET_TOLERANCE, 6, 1) + SHARED_FIELD(GPIO_CONTROL_DEBOUNCE_1, 7, 1) + SHARED_FIELD(GPIO_CONTROL_DEBOUNCE_2, 8, 1) + SHARED_FIELD(GPIO_CONTROL_INPUT_MASK, 9, 1) + SHARED_FIELD(GPIO_CONTROL_BLINK_COUNTER_1, 10, 1) + SHARED_FIELD(GPIO_CONTROL_BLINK_COUNTER_2, 11, 1) + SHARED_FIELD(GPIO_CONTROL_INT_STATUS, 12, 1) + SHARED_FIELD(GPIO_CONTROL_IN_DATA, 13, 1) + SHARED_FIELD(GPIO_CONTROL_RESERVED, 14, 18) +REG32(GPIO_AA7_CONTROL, 0x4DC) +#define GPIO_2700_MEM_SIZE 0x4E0 +#define GPIO_2700_REG_ARRAY_SIZE (GPIO_2700_MEM_SIZE >> 2) + static int aspeed_evaluate_irq(GPIOSets *regs, int gpio_prev_high, int gpi= o) { uint32_t falling_edge =3D 0, rising_edge =3D 0; @@ -970,6 +1002,316 @@ static void aspeed_gpio_set_pin(Object *obj, Visitor= *v, const char *name, aspeed_gpio_set_pin_level(s, set_idx, pin, level); } =20 +static uint64_t aspeed_gpio_2700_read_control_reg(AspeedGPIOState *s, + uint32_t pin) +{ + AspeedGPIOClass *agc =3D ASPEED_GPIO_GET_CLASS(s); + GPIOSets *set; + uint64_t value =3D 0; + uint32_t set_idx; + uint32_t pin_idx; + + set_idx =3D pin / ASPEED_GPIOS_PER_SET; + pin_idx =3D pin % ASPEED_GPIOS_PER_SET; + + if (set_idx >=3D agc->nr_gpio_sets) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: set index: %d, out of bounds\n= ", + __func__, set_idx); + return 0; + } + + set =3D &s->sets[set_idx]; + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_OUT_DATA, + extract32(set->data_read, pin_idx, 1)); + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_DIRECTION, + extract32(set->direction, pin_idx, 1)); + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_INT_ENABLE, + extract32(set->int_enable, pin_idx, 1)); + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_INT_SENS_0, + extract32(set->int_sens_0, pin_idx, 1)); + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_INT_SENS_1, + extract32(set->int_sens_1, pin_idx, 1)); + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_INT_SENS_2, + extract32(set->int_sens_2, pin_idx, 1)); + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_RESET_TOLERANCE, + extract32(set->reset_tol, pin_idx, 1)); + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_DEBOUNCE_1, + extract32(set->debounce_1, pin_idx, 1)); + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_DEBOUNCE_2, + extract32(set->debounce_2, pin_idx, 1)); + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_INPUT_MASK, + extract32(set->input_mask, pin_idx, 1)); + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_INT_STATUS, + extract32(set->int_status, pin_idx, 1)); + value =3D SHARED_FIELD_DP32(value, GPIO_CONTROL_IN_DATA, + extract32(set->data_value, pin_idx, 1)); + return value; +} + +static void aspeed_gpio_2700_write_control_reg(AspeedGPIOState *s, + uint32_t pin, uint64_t data) +{ + AspeedGPIOClass *agc =3D ASPEED_GPIO_GET_CLASS(s); + const GPIOSetProperties *props; + GPIOSets *set; + uint32_t set_idx; + uint32_t pin_idx; + uint32_t group_value =3D 0; + uint32_t pending =3D 0; + + set_idx =3D pin / ASPEED_GPIOS_PER_SET; + pin_idx =3D pin % ASPEED_GPIOS_PER_SET; + + if (set_idx >=3D agc->nr_gpio_sets) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: set index: %d, out of bounds\n= ", + __func__, set_idx); + return; + } + + set =3D &s->sets[set_idx]; + props =3D &agc->props[set_idx]; + + /* direction */ + group_value =3D set->direction; + group_value =3D deposit32(group_value, pin_idx, 1, + SHARED_FIELD_EX32(data, GPIO_CONTROL_DIRECTION= )); + /* + * where data is the value attempted to be written to the pin: + * pin type | input mask | output mask | expected value + * ------------------------------------------------------------ + * bidirectional | 1 | 1 | data + * input only | 1 | 0 | 0 + * output only | 0 | 1 | 1 + * no pin | 0 | 0 | 0 + * + * which is captured by: + * data =3D ( data | ~input) & output; + */ + group_value =3D (group_value | ~props->input) & props->output; + set->direction =3D update_value_control_source(set, set->direction, + group_value); + + /* out data */ + group_value =3D set->data_read; + group_value =3D deposit32(group_value, pin_idx, 1, + SHARED_FIELD_EX32(data, GPIO_CONTROL_OUT_DATA)= ); + group_value &=3D props->output; + group_value =3D update_value_control_source(set, set->data_read, + group_value); + set->data_read =3D group_value; + + /* interrupt enable */ + group_value =3D set->int_enable; + group_value =3D deposit32(group_value, pin_idx, 1, + SHARED_FIELD_EX32(data, GPIO_CONTROL_INT_ENABL= E)); + set->int_enable =3D update_value_control_source(set, set->int_enable, + group_value); + + /* interrupt sensitivity type 0 */ + group_value =3D set->int_sens_0; + group_value =3D deposit32(group_value, pin_idx, 1, + SHARED_FIELD_EX32(data, GPIO_CONTROL_INT_SENS_= 0)); + set->int_sens_0 =3D update_value_control_source(set, set->int_sens_0, + group_value); + + /* interrupt sensitivity type 1 */ + group_value =3D set->int_sens_1; + group_value =3D deposit32(group_value, pin_idx, 1, + SHARED_FIELD_EX32(data, GPIO_CONTROL_INT_SENS_= 1)); + set->int_sens_1 =3D update_value_control_source(set, set->int_sens_1, + group_value); + + /* interrupt sensitivity type 2 */ + group_value =3D set->int_sens_2; + group_value =3D deposit32(group_value, pin_idx, 1, + SHARED_FIELD_EX32(data, GPIO_CONTROL_INT_SENS_= 2)); + set->int_sens_2 =3D update_value_control_source(set, set->int_sens_2, + group_value); + + /* reset tolerance enable */ + group_value =3D set->reset_tol; + group_value =3D deposit32(group_value, pin_idx, 1, + SHARED_FIELD_EX32(data, GPIO_CONTROL_RESET_TOLERAN= CE)); + set->reset_tol =3D update_value_control_source(set, set->reset_tol, + group_value); + + /* debounce 1 */ + group_value =3D set->debounce_1; + group_value =3D deposit32(group_value, pin_idx, 1, + SHARED_FIELD_EX32(data, GPIO_CONTROL_DEBOUNCE_= 1)); + set->debounce_1 =3D update_value_control_source(set, set->debounce_1, + group_value); + + /* debounce 2 */ + group_value =3D set->debounce_2; + group_value =3D deposit32(group_value, pin_idx, 1, + SHARED_FIELD_EX32(data, GPIO_CONTROL_DEBOUNCE_= 2)); + set->debounce_2 =3D update_value_control_source(set, set->debounce_2, + group_value); + + /* input mask */ + group_value =3D set->input_mask; + group_value =3D deposit32(group_value, pin_idx, 1, + SHARED_FIELD_EX32(data, GPIO_CONTROL_INPUT_MAS= K)); + /* + * feeds into interrupt generation + * 0: read from data value reg will be updated + * 1: read from data value reg will not be updated + */ + set->input_mask =3D group_value & props->input; + + /* blink counter 1 */ + /* blink counter 2 */ + /* unimplement */ + + /* interrupt status */ + if (SHARED_FIELD_EX32(data, GPIO_CONTROL_INT_STATUS)) { + /* pending is either 1 or 0 for a 1-bit field */ + pending =3D extract32(set->int_status, pin_idx, 1); + + assert(s->pending >=3D pending); + + /* No change to s->pending if pending is 0 */ + s->pending -=3D pending; + + /* + * The write acknowledged the interrupt regardless of whether it + * was pending or not. The post-condition is that it mustn't be + * pending. Unconditionally clear the status bit. + */ + set->int_status =3D deposit32(set->int_status, pin_idx, 1, 0); + } + + aspeed_gpio_update(s, set, set->data_value, UINT32_MAX); + return; +} + +static uint64_t aspeed_gpio_2700_read(void *opaque, hwaddr offset, + uint32_t size) +{ + AspeedGPIOState *s =3D ASPEED_GPIO(opaque); + AspeedGPIOClass *agc =3D ASPEED_GPIO_GET_CLASS(s); + GPIOSets *set; + uint64_t value; + uint64_t reg; + uint32_t pin; + uint32_t idx; + + reg =3D offset >> 2; + + if (reg >=3D agc->reg_table_count) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: offset 0x%" PRIx64 " out of bounds\n", + __func__, offset); + return 0; + } + + switch (reg) { + case R_GPIO_2700_DEBOUNCE_TIME_1 ... R_GPIO_2700_DEBOUNCE_TIME_3: + idx =3D reg - R_GPIO_2700_DEBOUNCE_TIME_1; + + if (idx >=3D ASPEED_GPIO_NR_DEBOUNCE_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: debounce index: %d, out of bounds\n", + __func__, idx); + return 0; + } + + value =3D (uint64_t) s->debounce_regs[idx]; + break; + case R_GPIO_2700_INT_STATUS_1 ... R_GPIO_2700_INT_STATUS_7: + idx =3D reg - R_GPIO_2700_INT_STATUS_1; + + if (idx >=3D agc->nr_gpio_sets) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: interrupt status index: %d, out of bounds\n= ", + __func__, idx); + return 0; + } + + set =3D &s->sets[idx]; + value =3D (uint64_t) set->int_status; + break; + case R_GPIO_A0_CONTROL ... R_GPIO_AA7_CONTROL: + pin =3D reg - R_GPIO_A0_CONTROL; + + if (pin >=3D agc->nr_gpio_pins) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid pin number: %d\n", + __func__, pin); + return 0; + } + + value =3D aspeed_gpio_2700_read_control_reg(s, pin); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%" + PRIx64"\n", __func__, offset); + return 0; + } + + trace_aspeed_gpio_read(offset, value); + return value; +} + +static void aspeed_gpio_2700_write(void *opaque, hwaddr offset, + uint64_t data, uint32_t size) +{ + AspeedGPIOState *s =3D ASPEED_GPIO(opaque); + AspeedGPIOClass *agc =3D ASPEED_GPIO_GET_CLASS(s); + uint64_t reg; + uint32_t pin; + uint32_t idx; + + trace_aspeed_gpio_write(offset, data); + + reg =3D offset >> 2; + + if (reg >=3D agc->reg_table_count) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: offset 0x%" PRIx64 " out of bounds\n", + __func__, offset); + return; + } + + switch (reg) { + case R_GPIO_2700_DEBOUNCE_TIME_1 ... R_GPIO_2700_DEBOUNCE_TIME_3: + idx =3D reg - R_GPIO_2700_DEBOUNCE_TIME_1; + + if (idx >=3D ASPEED_GPIO_NR_DEBOUNCE_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: debounce index: %d out of bounds\n", + __func__, idx); + return; + } + + s->debounce_regs[idx] =3D (uint32_t) data; + break; + case R_GPIO_A0_CONTROL ... R_GPIO_AA7_CONTROL: + pin =3D reg - R_GPIO_A0_CONTROL; + + if (pin >=3D agc->nr_gpio_pins) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid pin number: %d\n", + __func__, pin); + return; + } + + if (SHARED_FIELD_EX32(data, GPIO_CONTROL_RESERVED)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid reserved data: 0x%" + PRIx64"\n", __func__, data); + return; + } + + aspeed_gpio_2700_write_control_reg(s, pin, data); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%" + PRIx64"\n", __func__, offset); + break; + } + + return; +} + /* Setup functions */ static const GPIOSetProperties ast2400_set_props[ASPEED_GPIO_MAX_NR_SETS] = =3D { [0] =3D {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} }, @@ -1016,6 +1358,16 @@ static GPIOSetProperties ast1030_set_props[ASPEED_GP= IO_MAX_NR_SETS] =3D { [5] =3D {0x000000ff, 0x00000000, {"U"} }, }; =20 +static GPIOSetProperties ast2700_set_props[ASPEED_GPIO_MAX_NR_SETS] =3D { + [0] =3D {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} }, + [1] =3D {0x0fffffff, 0x0fffffff, {"E", "F", "G", "H"} }, + [2] =3D {0xffffffff, 0xffffffff, {"I", "J", "K", "L"} }, + [3] =3D {0xffffffff, 0xffffffff, {"M", "N", "O", "P"} }, + [4] =3D {0xffffffff, 0xffffffff, {"Q", "R", "S", "T"} }, + [5] =3D {0xffffffff, 0xffffffff, {"U", "V", "W", "X"} }, + [6] =3D {0x00ffffff, 0x00ffffff, {"Y", "Z", "AA"} }, +}; + static const MemoryRegionOps aspeed_gpio_ops =3D { .read =3D aspeed_gpio_read, .write =3D aspeed_gpio_write, @@ -1024,6 +1376,14 @@ static const MemoryRegionOps aspeed_gpio_ops =3D { .valid.max_access_size =3D 4, }; =20 +static const MemoryRegionOps aspeed_gpio_2700_ops =3D { + .read =3D aspeed_gpio_2700_read, + .write =3D aspeed_gpio_2700_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid.min_access_size =3D 4, + .valid.max_access_size =3D 4, +}; + static void aspeed_gpio_reset(DeviceState *dev) { AspeedGPIOState *s =3D ASPEED_GPIO(dev); @@ -1193,6 +1553,18 @@ static void aspeed_gpio_1030_class_init(ObjectClass = *klass, void *data) agc->reg_ops =3D &aspeed_gpio_ops; } =20 +static void aspeed_gpio_2700_class_init(ObjectClass *klass, void *data) +{ + AspeedGPIOClass *agc =3D ASPEED_GPIO_CLASS(klass); + + agc->props =3D ast2700_set_props; + agc->nr_gpio_pins =3D 216; + agc->nr_gpio_sets =3D 7; + agc->reg_table_count =3D GPIO_2700_REG_ARRAY_SIZE; + agc->mem_size =3D 0x1000; + agc->reg_ops =3D &aspeed_gpio_2700_ops; +} + static const TypeInfo aspeed_gpio_info =3D { .name =3D TYPE_ASPEED_GPIO, .parent =3D TYPE_SYS_BUS_DEVICE, @@ -1237,6 +1609,13 @@ static const TypeInfo aspeed_gpio_ast1030_info =3D { .instance_init =3D aspeed_gpio_init, }; =20 +static const TypeInfo aspeed_gpio_ast2700_info =3D { + .name =3D TYPE_ASPEED_GPIO "-ast2700", + .parent =3D TYPE_ASPEED_GPIO, + .class_init =3D aspeed_gpio_2700_class_init, + .instance_init =3D aspeed_gpio_init, +}; + static void aspeed_gpio_register_types(void) { type_register_static(&aspeed_gpio_info); @@ -1245,6 +1624,7 @@ static void aspeed_gpio_register_types(void) type_register_static(&aspeed_gpio_ast2600_3_3v_info); type_register_static(&aspeed_gpio_ast2600_1_8v_info); type_register_static(&aspeed_gpio_ast1030_info); + type_register_static(&aspeed_gpio_ast2700_info); } =20 type_init(aspeed_gpio_register_types); --=20 2.34.1