From patchwork Wed Jan 18 08:29:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: ~luhux X-Patchwork-Id: 1728195 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4NxlVB54zqz23g6 for ; Wed, 18 Jan 2023 23:30:58 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pI7ZW-0007Fk-ED; Wed, 18 Jan 2023 07:29:42 -0500 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 1pI7ZU-0007FR-V5 for qemu-devel@nongnu.org; Wed, 18 Jan 2023 07:29:41 -0500 Received: from mail-b.sr.ht ([173.195.146.151]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pI7ZS-0004Ed-So for qemu-devel@nongnu.org; Wed, 18 Jan 2023 07:29:40 -0500 Authentication-Results: mail-b.sr.ht; dkim=none Received: from git.sr.ht (unknown [173.195.146.142]) by mail-b.sr.ht (Postfix) with ESMTPSA id F3FD311EF15 for ; Wed, 18 Jan 2023 12:29:36 +0000 (UTC) From: ~luhux Date: Wed, 18 Jan 2023 16:29:15 +0800 Subject: [PATCH qemu 1/3] hw/misc/mt7628-sysctrl.c: Add mt7628 system control support. Message-ID: <167404497644.25699.12403586061485468184-0@git.sr.ht> X-Mailer: git.sr.ht To: qemu-devel@nongnu.org MIME-Version: 1.0 Received-SPF: pass client-ip=173.195.146.151; envelope-from=outgoing@sr.ht; helo=mail-b.sr.ht X-Spam_score_int: 20 X-Spam_score: 2.0 X-Spam_bar: ++ X-Spam_report: (2.0 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_03_06=1.592, FREEMAIL_FORGED_REPLYTO=2.095, FREEMAIL_REPLYTO_END_DIGIT=0.25, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: ~luhux Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: LuHui Signed-off-by: LuHui --- MAINTAINERS | 5 + hw/misc/meson.build | 3 + hw/misc/mt7628-sysctrl.c | 169 +++++++++++++++++++++++++++++++ include/hw/misc/mt7628-sysctrl.h | 66 ++++++++++++ 4 files changed, 243 insertions(+) create mode 100644 hw/misc/mt7628-sysctrl.c create mode 100644 include/hw/misc/mt7628-sysctrl.h diff --git a/MAINTAINERS b/MAINTAINERS index 0fe50d01e3..41854e939c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1234,6 +1234,11 @@ F: configs/devices/mips*/* F: hw/mips/ F: include/hw/mips/ +VoCore2 +M: Lu Hui +S: Maintained +F: hw/*/*mt7628* + Jazz M: Hervé Poussineau R: Aleksandar Rikalo diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 448e14b531..0dfe7d9740 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -140,3 +140,6 @@ softmmu_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c')) # HPPA devices softmmu_ss.add(when: 'CONFIG_LASI', if_true: files('lasi.c')) + +# mt7628 +softmmu_ss.add(when: 'CONFIG_MT7628', if_true: files('mt7628-sysctrl.c')) diff --git a/hw/misc/mt7628-sysctrl.c b/hw/misc/mt7628-sysctrl.c new file mode 100644 index 0000000000..e04d1de69d --- /dev/null +++ b/hw/misc/mt7628-sysctrl.c @@ -0,0 +1,169 @@ +/* + * Mediatek mt7628 System Control emulation + * + * Copyright (C) 2023 Lu Hui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "hw/sysbus.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "hw/misc/mt7628-sysctrl.h" +#include "sysemu/runstate.h" + +#define REG_INDEX(offset) (offset / sizeof(uint32_t)) + +/* System Control register offsets */ +/* from linux kernel arch/mips/include/asm/mach-ralink/mt7620.h */ +enum { + REG_CHIP_NAME0 = 0x00, + REG_CHIP_NAME1 = 0x04, + REG_EFUSE_CFG = 0x08, + REG_CHIP_REV = 0x0C, + REG_SYS_CFG0 = 0x10, + REG_SYS_CFG1 = 0x14, + REG_CLK_CFG0 = 0x2C, + REG_CLK_CFG1 = 0x30, + REG_RST_CTRL = 0x34, + REG_RST_STAT = 0x38, + REG_AGPIO_CFG = 0x3C, + REG_GPIO1_MODE = 0x60, + REG_GPIO2_MODE = 0x64, +}; + +static uint64_t mt7628_sysctrl_read(void *opaque, hwaddr offset, + unsigned size) +{ + const mt7628SysCtrlState *s = MT7628_SYSCTRL(opaque); + const uint32_t idx = REG_INDEX(offset); + + if (idx >= MT7628_SYSCTRL_REGS_NUM) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n", + __func__, (uint32_t) offset); + return 0; + } + + return s->regs[idx]; +} + +enum { + RST_SYSTEM = 0, +}; + +static void mt7628_reset(uint32_t val) +{ + if (test_bit(RST_SYSTEM, (void *)&val)) { + /* reset whole system */ + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + } +} + +static void mt7628_sysctrl_write(void *opaque, hwaddr offset, + uint64_t val, unsigned size) +{ + mt7628SysCtrlState *s = MT7628_SYSCTRL(opaque); + const uint32_t idx = REG_INDEX(offset); + + if (idx >= MT7628_SYSCTRL_REGS_NUM) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n", + __func__, (uint32_t) offset); + return; + } + + switch (offset) { + case REG_RST_CTRL: + s->regs[idx] = (uint32_t) val; + mt7628_reset(s->regs[idx]); + break; + default: + s->regs[idx] = (uint32_t) val; + break; + } +} + +static const MemoryRegionOps mt7628_sysctrl_ops = { + .read = mt7628_sysctrl_read, + .write = mt7628_sysctrl_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, + .impl.min_access_size = 4, +}; + +static void mt7628_sysctrl_reset(DeviceState *dev) +{ + mt7628SysCtrlState *s = MT7628_SYSCTRL(dev); + + /* Set default values for registers */ + /* dump from real mt7628 board */ + s->regs[REG_INDEX(REG_CHIP_NAME0)] = 0x3637544d; /* "MT76" */ + s->regs[REG_INDEX(REG_CHIP_NAME1)] = 0x20203832; /* "28 " */ + s->regs[REG_INDEX(REG_EFUSE_CFG)] = 0x01010000; + s->regs[REG_INDEX(REG_CHIP_REV)] = 0x00010102; + s->regs[REG_INDEX(REG_SYS_CFG0)] = 0x00144144; + s->regs[REG_INDEX(REG_SYS_CFG1)] = 0x02605500; + s->regs[REG_INDEX(REG_CLK_CFG0)] = 0b00000000001000000001000000000000; + s->regs[REG_INDEX(REG_CLK_CFG1)] = 0b11110110100111110111111100000000; + s->regs[REG_INDEX(REG_RST_CTRL)] = 0b00000100000000000000010000000000; + s->regs[REG_INDEX(REG_RST_STAT)] = 0b11000000000000110000000000000000; + s->regs[REG_INDEX(REG_AGPIO_CFG)] = 0b00000000000111110000000000011111; + s->regs[REG_INDEX(REG_GPIO1_MODE)] = 0b01010100000001010000010000000100; + s->regs[REG_INDEX(REG_GPIO2_MODE)] = 0b00000101010101010000010101010101; +} + +static void mt7628_sysctrl_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + mt7628SysCtrlState *s = MT7628_SYSCTRL(obj); + + /* Memory mapping */ + memory_region_init_io(&s->iomem, OBJECT(s), &mt7628_sysctrl_ops, s, + TYPE_MT7628_SYSCTRL, MT7628_SYSCTRL_REGS_MAXADDR); + sysbus_init_mmio(sbd, &s->iomem); +} + +static const VMStateDescription mt7628_sysctrl_vmstate = { + .name = "mt7628-sysctrl", + .version_id = 1, + .minimum_version_id = 1, +}; + +static void mt7628_sysctrl_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = mt7628_sysctrl_reset; + dc->vmsd = &mt7628_sysctrl_vmstate; +} + +static const TypeInfo mt7628_sysctrl_info = { + .name = TYPE_MT7628_SYSCTRL, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_init = mt7628_sysctrl_init, + .instance_size = sizeof(mt7628SysCtrlState), + .class_init = mt7628_sysctrl_class_init, +}; + +static void mt7628_sysctrl_register(void) +{ + type_register_static(&mt7628_sysctrl_info); +} + +type_init(mt7628_sysctrl_register) diff --git a/include/hw/misc/mt7628-sysctrl.h b/include/hw/misc/mt7628-sysctrl.h new file mode 100644 index 0000000000..836dbdd5aa --- /dev/null +++ b/include/hw/misc/mt7628-sysctrl.h @@ -0,0 +1,66 @@ +/* + * Mediatek mt7628 System Control emulation + * + * Copyright (C) 2023 Lu Hui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef HW_MISC_MT7628_SYSCTRL_H +#define HW_MISC_MT7628_SYSCTRL_H + +#include "qom/object.h" +#include "hw/sysbus.h" + +/** + * @name Constants + * @{ + */ + +/** Highest register address used by System Control device */ +#define MT7628_SYSCTRL_REGS_MAXADDR (0x100) + +/** Total number of known registers */ +#define MT7628_SYSCTRL_REGS_NUM ((MT7628_SYSCTRL_REGS_MAXADDR / \ + sizeof(uint32_t)) + 1) + +/** @} */ + +/** + * @name Object model + * @{ + */ + +#define TYPE_MT7628_SYSCTRL "mt7628-sysctrl" +OBJECT_DECLARE_SIMPLE_TYPE(mt7628SysCtrlState, MT7628_SYSCTRL) + +/** @} */ + +/** + * mt7628 System Control object instance state + */ +struct mt7628SysCtrlState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + /** Maps I/O registers in physical memory */ + MemoryRegion iomem; + + /** Array of hardware registers */ + uint32_t regs[MT7628_SYSCTRL_REGS_NUM]; + +}; + +#endif /* HW_MISC_MT7628_SYSCTRL_H */ From patchwork Wed Jan 18 09:00:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ~luhux X-Patchwork-Id: 1728197 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4NxlVD1pJSz23h2 for ; Wed, 18 Jan 2023 23:31:00 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pI7ZX-0007GS-SD; Wed, 18 Jan 2023 07:29:43 -0500 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 1pI7ZW-0007Fj-9I for qemu-devel@nongnu.org; Wed, 18 Jan 2023 07:29:42 -0500 Received: from mail-b.sr.ht ([173.195.146.151]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pI7ZS-0004Ee-TR for qemu-devel@nongnu.org; Wed, 18 Jan 2023 07:29:42 -0500 Authentication-Results: mail-b.sr.ht; dkim=none Received: from git.sr.ht (unknown [173.195.146.142]) by mail-b.sr.ht (Postfix) with ESMTPSA id 2F05B11EF5B for ; Wed, 18 Jan 2023 12:29:37 +0000 (UTC) From: ~luhux Date: Wed, 18 Jan 2023 17:00:29 +0800 Subject: [PATCH qemu 2/3] hw/intc/mt7628-intc.c: add mt7628 interrupt control support. Message-ID: <167404497644.25699.12403586061485468184-1@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <167404497644.25699.12403586061485468184-0@git.sr.ht> To: qemu-devel@nongnu.org MIME-Version: 1.0 Received-SPF: pass client-ip=173.195.146.151; envelope-from=outgoing@sr.ht; helo=mail-b.sr.ht X-Spam_score_int: 20 X-Spam_score: 2.0 X-Spam_bar: ++ X-Spam_report: (2.0 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_03_06=1.592, FREEMAIL_FORGED_REPLYTO=2.095, FREEMAIL_REPLYTO_END_DIGIT=0.25, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: ~luhux Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: LuHui Signed-off-by: LuHui --- hw/intc/meson.build | 1 + hw/intc/mt7628-intc.c | 155 ++++++++++++++++++++++++++++++++++ include/hw/intc/mt7628-intc.h | 30 +++++++ 3 files changed, 186 insertions(+) create mode 100644 hw/intc/mt7628-intc.c create mode 100644 include/hw/intc/mt7628-intc.h diff --git a/hw/intc/meson.build b/hw/intc/meson.build index cd9f1ee888..2ce3ddb4d2 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -73,3 +73,4 @@ specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ipi.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c')) +specific_ss.add(when: 'CONFIG_MT7628', if_true: files('mt7628-intc.c')) diff --git a/hw/intc/mt7628-intc.c b/hw/intc/mt7628-intc.c new file mode 100644 index 0000000000..f900bf502f --- /dev/null +++ b/hw/intc/mt7628-intc.c @@ -0,0 +1,155 @@ +/* + * mt7628 interrupt controller device emulation + * + * Copyright (C) 2023 Lu Hui + * Written by Lu Hui + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "migration/vmstate.h" +#include "hw/intc/mt7628-intc.h" +#include "hw/irq.h" +#include "qemu/log.h" +#include "qemu/module.h" + +static void mt7628_intc_update(mt7628intcState *s) +{ + int i; + for (i = 0; i < 32; i++) { + if (test_bit(i, (void *) &s->disable)) { + clear_bit(i, (void *) &s->enable); + } + } + qemu_set_irq(s->parent_irq, !!(s->enable)); +} + +static void mt7628_intc_set_irq(void *opaque, int irq, int level) +{ + mt7628intcState *s = opaque; + + if (level) { + set_bit(irq, (void *) &s->enable); + clear_bit(irq, (void *) &s->disable); + } else { + clear_bit(irq, (void *) &s->enable); + set_bit(irq, (void *) &s->disable); + } + mt7628_intc_update(s); +} + +static uint64_t mt7628_intc_read(void *opaque, hwaddr offset, + unsigned size) +{ + mt7628intcState *s = opaque; + + switch (offset) { + case MT7628_INTC_REG_STATUS0: + return s->enable; + case MT7628_INTC_REG_TYPE: + return s->type; + case MT7628_INTC_REG_ENABLE: + return s->enable; + case MT7628_INTC_REG_DISABLE: + return s->disable; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: not imp offset 0x%x\n", __func__, (int) offset); + return 0x0; + break; + } + + return 0; +} + +static void mt7628_intc_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + mt7628intcState *s = opaque; + + switch (offset) { + case MT7628_INTC_REG_TYPE: + s->type = value; + break; + case MT7628_INTC_REG_ENABLE: + s->enable = value; + break; + case MT7628_INTC_REG_DISABLE: + s->disable = value; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: not imp offset 0x%x\n", __func__, (int) offset); + break; + } + + mt7628_intc_update(s); +} + +static const MemoryRegionOps mt7628_intc_ops = { + .read = mt7628_intc_read, + .write = mt7628_intc_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static const VMStateDescription vmstate_mt7628_intc = { + .name = "mt7628.intc", + .version_id = 1, + .minimum_version_id = 1, +}; + +static void mt7628_intc_init(Object *obj) +{ + mt7628intcState *s = MT7628_INTC(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); + + qdev_init_gpio_in(DEVICE(dev), mt7628_intc_set_irq, 32); + sysbus_init_irq(dev, &s->parent_irq); + memory_region_init_io(&s->iomem, OBJECT(s), &mt7628_intc_ops, s, + TYPE_MT7628_INTC, MT7628_INTC_REGS_MAXADDR); + sysbus_init_mmio(dev, &s->iomem); +} + +static void mt7628_intc_reset(DeviceState *d) +{ + mt7628intcState *s = MT7628_INTC(d); + + s->type = 0b00000000000000000000000000000000; + s->enable = 0b00000000000000000000000000000000; + s->disable = 0b00000000000000000000000000000000; +} + +static void mt7628_intc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = mt7628_intc_reset; + dc->desc = "mt7628 interrupt control"; + dc->vmsd = &vmstate_mt7628_intc; +} + +static const TypeInfo mt7628_intc_info = { + .name = TYPE_MT7628_INTC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(mt7628intcState), + .instance_init = mt7628_intc_init, + .class_init = mt7628_intc_class_init, +}; + +static void mt7628_register_types(void) +{ + type_register_static(&mt7628_intc_info); +} + +type_init(mt7628_register_types); diff --git a/include/hw/intc/mt7628-intc.h b/include/hw/intc/mt7628-intc.h new file mode 100644 index 0000000000..a2f4690d1d --- /dev/null +++ b/include/hw/intc/mt7628-intc.h @@ -0,0 +1,30 @@ +#ifndef MT7628_INTC_H +#define MT7628_INTC_H + +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_MT7628_INTC "mt7628-intc" +OBJECT_DECLARE_SIMPLE_TYPE(mt7628intcState, MT7628_INTC) + +#define MT7628_INTC_REG_STATUS0 (0x9c) +#define MT7628_INTC_REG_TYPE (0x6c) +#define MT7628_INTC_REG_ENABLE (0x80) +#define MT7628_INTC_REG_DISABLE (0x78) + +#define MT7628_INTC_REGS_MAXADDR (0xFF) + +struct mt7628intcState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + MemoryRegion iomem; + qemu_irq parent_irq; + + uint32_t type; + uint32_t enable; + uint32_t disable; + /*priority setting here*/ +}; + +#endif From patchwork Wed Jan 18 09:06:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: ~luhux X-Patchwork-Id: 1728196 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4NxlVD18fRz23g6 for ; Wed, 18 Jan 2023 23:31:00 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pI7ZX-0007G7-5o; Wed, 18 Jan 2023 07:29:43 -0500 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 1pI7ZV-0007FZ-Bj for qemu-devel@nongnu.org; Wed, 18 Jan 2023 07:29:41 -0500 Received: from mail-b.sr.ht ([173.195.146.151]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pI7ZS-0004Ef-Sp for qemu-devel@nongnu.org; Wed, 18 Jan 2023 07:29:41 -0500 Authentication-Results: mail-b.sr.ht; dkim=none Received: from git.sr.ht (unknown [173.195.146.142]) by mail-b.sr.ht (Postfix) with ESMTPSA id 5CE6011EF83 for ; Wed, 18 Jan 2023 12:29:37 +0000 (UTC) From: ~luhux Date: Wed, 18 Jan 2023 17:06:02 +0800 Subject: [PATCH qemu 3/3] hw/mips/mt7628.c: add mt7628 soc support, add a mt7628 board VoCore2. Message-ID: <167404497644.25699.12403586061485468184-2@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <167404497644.25699.12403586061485468184-0@git.sr.ht> To: qemu-devel@nongnu.org MIME-Version: 1.0 Received-SPF: pass client-ip=173.195.146.151; envelope-from=outgoing@sr.ht; helo=mail-b.sr.ht X-Spam_score_int: 20 X-Spam_score: 2.0 X-Spam_bar: ++ X-Spam_report: (2.0 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_03_06=1.592, FREEMAIL_FORGED_REPLYTO=2.095, FREEMAIL_REPLYTO_END_DIGIT=0.25, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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: ~luhux Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: LuHui Signed-off-by: LuHui --- MAINTAINERS | 1 + configs/devices/mips-softmmu/common.mak | 2 + hw/mips/Kconfig | 11 ++ hw/mips/meson.build | 2 + hw/mips/mt7628.c | 189 ++++++++++++++++++++++++ hw/mips/vocore2.c | 180 ++++++++++++++++++++++ include/hw/mips/mt7628.h | 77 ++++++++++ 7 files changed, 462 insertions(+) create mode 100644 hw/mips/mt7628.c create mode 100644 hw/mips/vocore2.c create mode 100644 include/hw/mips/mt7628.h diff --git a/MAINTAINERS b/MAINTAINERS index 41854e939c..1b2f92e078 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1238,6 +1238,7 @@ VoCore2 M: Lu Hui S: Maintained F: hw/*/*mt7628* +F: hw/mips/vocore2.c Jazz M: Hervé Poussineau diff --git a/configs/devices/mips-softmmu/common.mak b/configs/devices/mips-softmmu/common.mak index 7da99327a7..e4a5c54635 100644 --- a/configs/devices/mips-softmmu/common.mak +++ b/configs/devices/mips-softmmu/common.mak @@ -29,3 +29,5 @@ CONFIG_PCNET_PCI=y CONFIG_MIPSSIM=y CONFIG_SMBUS_EEPROM=y CONFIG_TEST_DEVICES=y +CONFIG_MT7628=y +CONFIG_VOCORE2=y diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index da3a37e215..f7faec010c 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -10,6 +10,17 @@ config MIPSSIM select SERIAL_ISA select MIPSNET +config MT7628 + bool + select SERIAL + select USB_EHCI + select USB_EHCI_SYSBUS + select UNIMP + +config VOCORE2 + bool + select MT7628 + config JAZZ bool select ISA_BUS diff --git a/hw/mips/meson.build b/hw/mips/meson.build index 900613fc08..9ad125a996 100644 --- a/hw/mips/meson.build +++ b/hw/mips/meson.build @@ -10,6 +10,8 @@ mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c')) mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c')) mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c')) mips_ss.add(when: 'CONFIG_MIPS_BOSTON', if_true: [files('boston.c'), fdt]) +mips_ss.add(when: 'CONFIG_MT7628', if_true: files('mt7628.c')) +mips_ss.add(when: 'CONFIG_VOCORE2', if_true: files('vocore2.c')) endif hw_arch += {'mips': mips_ss} diff --git a/hw/mips/mt7628.c b/hw/mips/mt7628.c new file mode 100644 index 0000000000..d982b1c704 --- /dev/null +++ b/hw/mips/mt7628.c @@ -0,0 +1,189 @@ +/* + * QEMU/mt7628 emulation + * + * Copyright (c) 2023 Lu Hui + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/datadir.h" +#include "hw/clock.h" +#include "hw/block/flash.h" +#include "hw/mips/mips.h" +#include "hw/mips/cpudevs.h" +#include "hw/mips/bios.h" +#include "hw/usb/hcd-ehci.h" +#include "hw/char/serial.h" +#include "hw/misc/unimp.h" +#include "hw/mips/mt7628.h" +#include "sysemu/sysemu.h" +#include "hw/boards.h" +#include "hw/loader.h" +#include "elf.h" +#include "hw/sysbus.h" +#include "hw/qdev-properties.h" +#include "qemu/error-report.h" +#include "sysemu/qtest.h" +#include "sysemu/reset.h" + +/* data src: linux kernel, openwrt, uboot */ + +/* irq table */ +enum { + IRQ_UART0 = 20, + IRQ_UART1 = 21, + IRQ_UART2 = 22, + IRQ_EHCI = 18 +}; + +/* Memory map */ +const hwaddr mt7628_memmap[] = { + [MT7628_DEV_DDR] = 0x00000000, + [MT7628_DEV_SYSCTRL] = 0x10000000, + [MT7628_DEV_INTC] = 0x10000200, + [MT7628_DEV_UART0] = 0x10000C00, + [MT7628_DEV_UART1] = 0x10000D00, + [MT7628_DEV_UART2] = 0x10000E00, + [MT7628_DEV_EHCI] = 0x101C0000, + [MT7628_DEV_FLASH_DIRECT] = 0x1C000000, +}; + +struct mt7628Unimplemented { + const char *device_name; + hwaddr base; + hwaddr size; +} unimplemented[] = { + { "timer", 0x10000100, 0xFF }, + { "memc", 0x10000300, 0xFF }, + { "rbus", 0x10000400, 0xFF }, + { "mips-cnt", 0x10000500, 0xFF }, + { "gpio", 0x10000600, 0xFF }, + { "spi-slave", 0x10000700, 0xFF }, + { "i2c", 0x10000900, 0xFF }, + { "i2s", 0x10000A00, 0xFF }, + { "spi-master", 0x10000B00, 0xFF }, + { "rgctl", 0x10001000, 2 * KiB }, + { "pcm", 0x10002000, 2 * KiB }, + { "dma", 0x10002800, 2 * KiB }, + { "aes", 0x10004000, 4 * KiB }, + { "pwm", 0x10005000, 4 * KiB }, + { "ethernet-phy", 0x10100000, 64 * KiB }, + { "ethernet", 0x10110000, 32 * KiB }, + { "usb-phy", 0x10120000, 32 * KiB }, + { "sdxc", 0x10130000, 32 * KiB }, + { "pcie", 0x10140000, 256 * KiB }, + { "wlan", 0x10300000, 1 * MiB }, + { "pcie-direct", 0x20000000, 256 * MiB }, +}; + +static void mt7628_init(Object *obj) +{ + mt7628State *s = MT7628(obj); + s->memmap = mt7628_memmap; + + object_initialize_child(obj, "sysctrl", &s->sysctrl, TYPE_MT7628_SYSCTRL); + object_initialize_child(obj, "intc", &s->intc, TYPE_MT7628_INTC); + if (machine_usb(current_machine)) { + object_initialize_child(obj, "ehci", &s->ehci, TYPE_PLATFORM_EHCI); + } +} + +static void mt7628_realize(DeviceState *dev, Error **errp) +{ + mt7628State *s = MT7628(dev); + SysBusDevice *sysbusdev; + int i; + + if (!sysbus_realize(SYS_BUS_DEVICE(&s->intc), errp)) { + return; + } + CPUMIPSState *env = &s->cpu->env; + + /* interrupt control */ + sysbusdev = SYS_BUS_DEVICE(&s->intc); + sysbus_mmio_map(sysbusdev, 0, s->memmap[MT7628_DEV_INTC]); + sysbus_connect_irq(sysbusdev, 0, env->irq[MT7628_CPU_IRQ_INTC]); + qdev_pass_gpios(DEVICE(&s->intc), dev, NULL); + + /* system control */ + sysbus_realize(SYS_BUS_DEVICE(&s->sysctrl), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctrl), 0, + s->memmap[MT7628_DEV_SYSCTRL]); + + /* serial port */ + for (i = 0; i < 3; i++) { + if (serial_hd(i)) { + serial_mm_init(get_system_memory(), + s->memmap[MT7628_DEV_UART0 + i], 2, + qdev_get_gpio_in(dev, IRQ_UART0 + i), 115200, + serial_hd(i), DEVICE_NATIVE_ENDIAN); + } else { + create_unimplemented_device("uart", + s->memmap[MT7628_DEV_UART0 + i], 256); + } + } + + /* usb 2.0 host */ + if (machine_usb(current_machine)) { + sysbus_realize(SYS_BUS_DEVICE(&s->ehci), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci), 0, + s->memmap[MT7628_DEV_EHCI]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci), 0, + qdev_get_gpio_in(dev, IRQ_EHCI)); + } else { + create_unimplemented_device("ehci", s->memmap[MT7628_DEV_EHCI], + 256 * KiB); + } + + /* flash direct access */ + DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); + if (dinfo) { + pflash_cfi01_register(s->memmap[MT7628_DEV_FLASH_DIRECT], + "mt7628.flash0", 4 * MiB, + dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, + 4096, 4, 0, 0, 0, 0, 0); + } else { + create_unimplemented_device("flash-direct", + s->memmap[MT7628_DEV_FLASH_DIRECT], + 4 * MiB); + } + + /* Unimplemented devices */ + for (i = 0; i < ARRAY_SIZE(unimplemented); i++) { + create_unimplemented_device(unimplemented[i].device_name, + unimplemented[i].base, + unimplemented[i].size); + } +} + +static void mt7628_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + dc->realize = mt7628_realize; + dc->user_creatable = false; +} + +static const TypeInfo mt7628_type_info = { + .name = TYPE_MT7628, + .parent = TYPE_DEVICE, + .instance_size = sizeof(mt7628State), + .instance_init = mt7628_init, + .class_init = mt7628_class_init, +}; + +static void mt7628_register_types(void) +{ + type_register_static(&mt7628_type_info); +} + +type_init(mt7628_register_types); diff --git a/hw/mips/vocore2.c b/hw/mips/vocore2.c new file mode 100644 index 0000000000..e9662224fd --- /dev/null +++ b/hw/mips/vocore2.c @@ -0,0 +1,180 @@ +/* + * QEMU/mt7628 emulation + * + * Copyright (c) 2023 Lu Hui + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/datadir.h" +#include "hw/clock.h" +#include "hw/mips/mips.h" +#include "hw/mips/cpudevs.h" +#include "hw/mips/mt7628.h" +#include "sysemu/sysemu.h" +#include "hw/boards.h" +#include "hw/mips/bios.h" +#include "hw/loader.h" +#include "elf.h" +#include "hw/sysbus.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-clock.h" +#include "qemu/error-report.h" +#include "sysemu/qtest.h" +#include "sysemu/reset.h" + +static struct _loaderparams { + int ram_size; + const char *kernel_filename; + const char *kernel_cmdline; + const char *initrd_filename; +} loaderparams; + +typedef struct ResetData { + MIPSCPU *cpu; + uint64_t vector; +} ResetData; + +static uint64_t load_kernel(void) +{ + uint64_t entry, kernel_high, initrd_size; + long kernel_size; + ram_addr_t initrd_offset; + + kernel_size = load_elf(loaderparams.kernel_filename, NULL, + cpu_mips_kseg0_to_phys, NULL, + &entry, NULL, + &kernel_high, NULL, 0, EM_MIPS, 1, 0); + if (kernel_size < 0) { + error_report("could not load kernel '%s': %s", + loaderparams.kernel_filename, + load_elf_strerror(kernel_size)); + exit(1); + } + + /* load initrd */ + initrd_size = 0; + initrd_offset = 0; + if (loaderparams.initrd_filename) { + initrd_size = get_image_size(loaderparams.initrd_filename); + if (initrd_size > 0) { + initrd_offset = ROUND_UP(kernel_high, INITRD_PAGE_SIZE); + if (initrd_offset + initrd_size > loaderparams.ram_size) { + error_report("memory too small for initial ram disk '%s'", + loaderparams.initrd_filename); + exit(1); + } + initrd_size = load_image_targphys(loaderparams.initrd_filename, + initrd_offset, + loaderparams.ram_size - initrd_offset); + } + if (initrd_size == (target_ulong)-1) { + error_report("could not load initial ram disk '%s'", + loaderparams.initrd_filename); + exit(1); + } + } + return entry; +} + +static void main_cpu_reset(void *opaque) +{ + ResetData *s = (ResetData *) opaque; + CPUMIPSState *env = &s->cpu->env; + + cpu_reset(CPU(s->cpu)); + env->active_tc.PC = s->vector & ~(target_ulong) 1; + if (s->vector & 1) { + env->hflags |= MIPS_HFLAG_M16; + } +} + +static void vocore2_init(MachineState *machine) +{ + const char *kernel_filename = machine->kernel_filename; + const char *kernel_cmdline = machine->kernel_cmdline; + const char *initrd_filename = machine->initrd_filename; + mt7628State *mt7628; + Clock *cpuclk; + MIPSCPU *cpu; + ResetData *reset_info; + + /* BIOS is not supported by this board */ + if (machine->firmware) { + error_report("BIOS not supported for this machine"); + exit(1); + } + + /* CPU limit */ + if (strcmp(machine->cpu_type, MIPS_CPU_TYPE_NAME("24KEc")) != 0) { + error_report("This board can only be used with 24KEc CPU"); + exit(1); + } + + /* RAM limit */ + if (machine->ram_size > 256 * MiB) { + error_report("mt7628: memory size must not exceed 256MiB"); + } + + mt7628 = MT7628(object_new(TYPE_MT7628)); + object_property_add_child(OBJECT(machine), "soc", OBJECT(mt7628)); + object_unref(OBJECT(mt7628)); + + /* CPU Clock */ + cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); + /* xtal 40Mhz -> cpu 580Mhz (VoCore2 use this) */ + /* xtal 25Mhz -> cpu 575Mhz */ + clock_set_hz(cpuclk, 580000000); + + /* CPU */ + cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); + cpu_mips_irq_init_cpu(cpu); + cpu_mips_clock_init(cpu); + mt7628->cpu = cpu; + + /* Mark mt7628 object realized */ + qdev_realize(DEVICE(mt7628), NULL, &error_abort); + + /* DDR */ + memory_region_add_subregion(get_system_memory(), + mt7628->memmap[MT7628_DEV_DDR], + machine->ram); + + /* Load kernel to RAM & goto kernel */ + reset_info = g_new0(ResetData, 1); + reset_info->cpu = cpu; + reset_info->vector = reset_info->cpu->env.active_tc.PC; + qemu_register_reset(main_cpu_reset, reset_info); + if (kernel_filename) { + loaderparams.ram_size = machine->ram_size; + loaderparams.kernel_filename = kernel_filename; + loaderparams.kernel_cmdline = kernel_cmdline; + loaderparams.initrd_filename = initrd_filename; + reset_info->vector = load_kernel(); + } + /* TODO: boot from flash */ +} + +static void vocore2_machine_init(MachineClass *mc) +{ + mc->desc = "VoCore2 (24KEc)"; + mc->init = vocore2_init; + mc->default_cpu_type = MIPS_CPU_TYPE_NAME("24KEc"); + mc->default_ram_id = "vocore2.ram"; + mc->default_ram_size = 128 * MiB; + mc->min_cpus = 1; + mc->max_cpus = 1; + mc->default_cpus = 1; +} + +DEFINE_MACHINE("vocore2", vocore2_machine_init) diff --git a/include/hw/mips/mt7628.h b/include/hw/mips/mt7628.h new file mode 100644 index 0000000000..2570f87846 --- /dev/null +++ b/include/hw/mips/mt7628.h @@ -0,0 +1,77 @@ +/* + * MT7628 System on Chip emulation + * + * Copyright (C) 2023 Lu Hui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef HW_MIPS_MT7628_H +#define HW_MIPS_MT7628_H + +#include "qom/object.h" +#include "hw/mips/mips.h" +#include "hw/mips/cpudevs.h" +#include "hw/mips/bios.h" +#include "hw/usb/hcd-ehci.h" +#include "hw/misc/mt7628-sysctrl.h" +#include "hw/intc/mt7628-intc.h" + +/** + * MT7628 device list + * + * This enumeration is can be used refer to a particular device in the + * MT7628 SoC. For example, the physical memory base address for + * each device can be found in the mt7628State object in the memmap member + * using the device enum value as index. + * + * @see mt7628State + */ +enum { + MT7628_DEV_DDR, + MT7628_DEV_SYSCTRL, + MT7628_DEV_INTC, + MT7628_DEV_UART0, + MT7628_DEV_UART1, + MT7628_DEV_UART2, + MT7628_DEV_EHCI, + MT7628_DEV_FLASH_DIRECT, +}; + + +/* mt7628 cpu interrupt table */ + + +enum { + MT7628_CPU_IRQ_INTC = 2, + MT7628_CPU_IRQ_PCIE = 4, +}; + +#define TYPE_MT7628 "mt7628" +OBJECT_DECLARE_SIMPLE_TYPE(mt7628State, MT7628) + +struct mt7628State { + /*< private >*/ + DeviceState parent_obj; + /*< public >*/ + + MIPSCPU *cpu; + const hwaddr *memmap; + mt7628SysCtrlState sysctrl; + mt7628intcState intc; + EHCISysBusState ehci; + MemoryRegion flash_direct; +}; + +#endif /* HW_MIPS_MT7628_H */