From nobody Fri May 17 04:49:49 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 ARC-Seal: i=1; a=rsa-sha256; t=1590942468; cv=none; d=zohomail.com; s=zohoarc; b=k8BWU9hGcJ+9NTWjgwGwEyXBqiJwJ8QOqoX5WO1dDZ4TboFcwdH+fHy1QDl3E+4cDtKAOjc4P1luf2qcbyCGFz8JMlfArRdvJQ4TC6QF92OC+bek2o2V4D8khr0OYjngmHEta86mLEZCyiXWCQA/u1/NuwwizaSF5uzaFlgLhIM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1590942468; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=P+78mDJFpVeVmoP7w+9CYFD4h0dUpzP/DvuhqinIzZE=; b=IuY3atjCpF+J5d+sdnUZaMUTLGJCUazWGfsNrvma8/LFag3WTOGj+FVczCwepsIp7rkhVkrE5ehEgvueRAgafHoNLSfoVNTqRXYb4msbLYQDCRhRRKwSxQ9tDOlA/KfY0S9FeBtczRLjesim1/nFumSW0kfFc6ck0jP0sdEAuqU= 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1590942468552571.0606658319912; Sun, 31 May 2020 09:27:48 -0700 (PDT) Received: from localhost ([::1]:54416 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQoN-0000sB-1Y for importer@patchew.org; Sun, 31 May 2020 12:27:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53674) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jfQlL-0004DL-Gr for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:39 -0400 Received: from mail01.asahi-net.or.jp ([202.224.55.13]:36013) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQlJ-0004Jz-Sk for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:39 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail01.asahi-net.or.jp (Postfix) with ESMTPA id 0F730105219; Mon, 1 Jun 2020 01:24:32 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by sakura.ysato.name (Postfix) with ESMTPSA id 318BF1C0DB3; Mon, 1 Jun 2020 01:24:32 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 01/10] hw/intc: RX62N interrupt controller (ICUa) Date: Mon, 1 Jun 2020 01:24:18 +0900 Message-Id: <20200531162427.57410-2-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200531162427.57410-1-ysato@users.sourceforge.jp> References: <20200531162427.57410-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 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: softfail client-ip=202.224.55.13; envelope-from=ysato@users.sourceforge.jp; helo=mail01.asahi-net.or.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/31 12:24:33 X-ACL-Warn: Detected OS = ??? 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_DNSWL_LOW=-0.7, SPF_SOFTFAIL=0.665, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" This implementation supported only ICUa. Hardware manual. https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej= 0140_rx62n.pdf Signed-off-by: Yoshinori Sato --- include/hw/intc/rx_icu.h | 56 ++++++ hw/intc/rx_icu.c | 379 +++++++++++++++++++++++++++++++++++++++ hw/intc/Makefile.objs | 1 + 3 files changed, 436 insertions(+) create mode 100644 include/hw/intc/rx_icu.h create mode 100644 hw/intc/rx_icu.c diff --git a/include/hw/intc/rx_icu.h b/include/hw/intc/rx_icu.h new file mode 100644 index 0000000000..acfcf06aef --- /dev/null +++ b/include/hw/intc/rx_icu.h @@ -0,0 +1,56 @@ +#ifndef RX_ICU_H +#define RX_ICU_H + +#include "qemu-common.h" +#include "hw/irq.h" + +enum TRG_MODE { + TRG_LEVEL =3D 0, + TRG_NEDGE =3D 1, /* Falling */ + TRG_PEDGE =3D 2, /* Raising */ + TRG_BEDGE =3D 3, /* Both */ +}; + +struct IRQSource { + enum TRG_MODE sense; + int level; +}; + +enum { + /* Software interrupt request */ + SWI =3D 27, + NR_IRQS =3D 256, +}; + +struct RXICUState { + SysBusDevice parent_obj; + + MemoryRegion memory; + struct IRQSource src[NR_IRQS]; + char *icutype; + uint32_t nr_irqs; + uint32_t *map; + uint32_t nr_sense; + uint32_t *init_sense; + + uint8_t ir[NR_IRQS]; + uint8_t dtcer[NR_IRQS]; + uint8_t ier[NR_IRQS / 8]; + uint8_t ipr[142]; + uint8_t dmasr[4]; + uint16_t fir; + uint8_t nmisr; + uint8_t nmier; + uint8_t nmiclr; + uint8_t nmicr; + int req_irq; + qemu_irq _irq; + qemu_irq _fir; + qemu_irq _swi; +}; +typedef struct RXICUState RXICUState; + +#define TYPE_RXICU "rx-icu" +#define RXICU(obj) OBJECT_CHECK(RXICUState, (obj), TYPE_RXICU) + +#endif /* RX_ICU_H */ diff --git a/hw/intc/rx_icu.c b/hw/intc/rx_icu.c new file mode 100644 index 0000000000..ab9a300467 --- /dev/null +++ b/hw/intc/rx_icu.c @@ -0,0 +1,379 @@ +/* + * RX Interrupt Control Unit + * + * Warning: Only ICUa is supported. + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 f= or + * 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-common.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "cpu.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/qdev-properties.h" +#include "hw/intc/rx_icu.h" +#include "migration/vmstate.h" +#include "qemu/error-report.h" + +REG8(IR, 0) + FIELD(IR, IR, 0, 1) +REG8(DTCER, 0x100) + FIELD(DTCER, DTCE, 0, 1) +REG8(IER, 0x200) +REG8(SWINTR, 0x2e0) + FIELD(SWINTR, SWINT, 0, 1) +REG16(FIR, 0x2f0) + FIELD(FIR, FVCT, 0, 8) + FIELD(FIR, FIEN, 15, 1) +REG8(IPR, 0x300) + FIELD(IPR, IPR, 0, 4) +REG8(DMRSR, 0x400) +REG8(IRQCR, 0x500) + FIELD(IRQCR, IRQMD, 2, 2) +REG8(NMISR, 0x580) + FIELD(NMISR, NMIST, 0, 1) + FIELD(NMISR, LVDST, 1, 1) + FIELD(NMISR, OSTST, 2, 1) +REG8(NMIER, 0x581) + FIELD(NMIER, NMIEN, 0, 1) + FIELD(NMIER, LVDEN, 1, 1) + FIELD(NMIER, OSTEN, 2, 1) +REG8(NMICLR, 0x582) + FIELD(NMICLR, NMICLR, 0, 1) + FIELD(NMICLR, OSTCLR, 2, 1) +REG8(NMICR, 0x583) + FIELD(NMICR, NMIMD, 3, 1) + +#define request(icu, n) (icu->ipr[icu->map[n]] << 8 | n) + +static void set_irq(RXICUState *icu, int n_IRQ, int req) +{ + if ((icu->fir & R_FIR_FIEN_MASK) && + (icu->fir & R_FIR_FVCT_MASK) =3D=3D n_IRQ) { + qemu_set_irq(icu->_fir, req); + } else { + qemu_set_irq(icu->_irq, req); + } +} + +static void rxicu_request(RXICUState *icu, int n_IRQ) +{ + int enable; + + enable =3D icu->ier[n_IRQ / 8] & (1 << (n_IRQ & 7)); + if (n_IRQ > 0 && enable !=3D 0 && atomic_read(&icu->req_irq) < 0) { + atomic_set(&icu->req_irq, n_IRQ); + set_irq(icu, n_IRQ, request(icu, n_IRQ)); + } +} + +static void rxicu_set_irq(void *opaque, int n_IRQ, int level) +{ + RXICUState *icu =3D opaque; + struct IRQSource *src; + int issue; + + if (n_IRQ >=3D NR_IRQS) { + error_report("%s: IRQ %d out of range", __func__, n_IRQ); + return; + } + + src =3D &icu->src[n_IRQ]; + + level =3D (level !=3D 0); + switch (src->sense) { + case TRG_LEVEL: + /* level-sensitive irq */ + issue =3D level; + src->level =3D level; + break; + case TRG_NEDGE: + issue =3D (level =3D=3D 0 && src->level =3D=3D 1); + src->level =3D level; + break; + case TRG_PEDGE: + issue =3D (level =3D=3D 1 && src->level =3D=3D 0); + src->level =3D level; + break; + case TRG_BEDGE: + issue =3D ((level ^ src->level) & 1); + src->level =3D level; + break; + default: + g_assert_not_reached(); + } + if (issue =3D=3D 0 && src->sense =3D=3D TRG_LEVEL) { + icu->ir[n_IRQ] =3D 0; + if (atomic_read(&icu->req_irq) =3D=3D n_IRQ) { + /* clear request */ + set_irq(icu, n_IRQ, 0); + atomic_set(&icu->req_irq, -1); + } + return; + } + if (issue) { + icu->ir[n_IRQ] =3D 1; + rxicu_request(icu, n_IRQ); + } +} + +static void rxicu_ack_irq(void *opaque, int no, int level) +{ + RXICUState *icu =3D opaque; + int i; + int n_IRQ; + int max_pri; + + n_IRQ =3D atomic_read(&icu->req_irq); + if (n_IRQ < 0) { + return; + } + atomic_set(&icu->req_irq, -1); + if (icu->src[n_IRQ].sense !=3D TRG_LEVEL) { + icu->ir[n_IRQ] =3D 0; + } + + max_pri =3D 0; + n_IRQ =3D -1; + for (i =3D 0; i < NR_IRQS; i++) { + if (icu->ir[i]) { + if (max_pri < icu->ipr[icu->map[i]]) { + n_IRQ =3D i; + max_pri =3D icu->ipr[icu->map[i]]; + } + } + } + + if (n_IRQ >=3D 0) { + rxicu_request(icu, n_IRQ); + } +} + +static uint64_t icu_read(void *opaque, hwaddr addr, unsigned size) +{ + RXICUState *icu =3D opaque; + int reg =3D addr & 0xff; + + if ((addr !=3D A_FIR && size !=3D 1) || + (addr =3D=3D A_FIR && size !=3D 2)) { + qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid read size 0x%" + HWADDR_PRIX "\n", addr); + return UINT64_MAX; + } + switch (addr) { + case A_IR ... A_IR + 0xff: + return icu->ir[reg] & R_IR_IR_MASK; + case A_DTCER ... A_DTCER + 0xff: + return icu->dtcer[reg] & R_DTCER_DTCE_MASK; + case A_IER ... A_IER + 0x1f: + return icu->ier[reg]; + case A_SWINTR: + return 0; + case A_FIR: + return icu->fir & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK); + case A_IPR ... A_IPR + 0x8f: + return icu->ipr[reg] & R_IPR_IPR_MASK; + case A_DMRSR: + case A_DMRSR + 4: + case A_DMRSR + 8: + case A_DMRSR + 12: + return icu->dmasr[reg >> 2]; + case A_IRQCR ... A_IRQCR + 0x1f: + return icu->src[64 + reg].sense << R_IRQCR_IRQMD_SHIFT; + case A_NMISR: + case A_NMICLR: + return 0; + case A_NMIER: + return icu->nmier; + case A_NMICR: + return icu->nmicr; + default: + qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX + " not implemented.\n", addr); + break; + } + return UINT64_MAX; +} + +static void icu_write(void *opaque, hwaddr addr, uint64_t val, unsigned si= ze) +{ + RXICUState *icu =3D opaque; + int reg =3D addr & 0xff; + + if ((addr !=3D A_FIR && size !=3D 1) || + (addr =3D=3D A_FIR && size !=3D 2)) { + qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid write size at 0x%" + HWADDR_PRIX "\n", addr); + return; + } + switch (addr) { + case A_IR ... A_IR + 0xff: + if (icu->src[reg].sense !=3D TRG_LEVEL && val =3D=3D 0) { + icu->ir[reg] =3D 0; + } + break; + case A_DTCER ... A_DTCER + 0xff: + icu->dtcer[reg] =3D val & R_DTCER_DTCE_MASK; + qemu_log_mask(LOG_UNIMP, + "rx_icu: DTC not implemented\n"); + break; + case A_IER ... A_IER + 0x1f: + icu->ier[reg] =3D val; + break; + case A_SWINTR: + if (val & R_SWINTR_SWINT_MASK) { + qemu_irq_pulse(icu->_swi); + } + break; + case A_FIR: + icu->fir =3D val & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK); + break; + case A_IPR ... A_IPR + 0x8f: + icu->ipr[reg] =3D val & R_IPR_IPR_MASK; + break; + case A_DMRSR: + case A_DMRSR + 4: + case A_DMRSR + 8: + case A_DMRSR + 12: + icu->dmasr[reg >> 2] =3D val; + qemu_log_mask(LOG_UNIMP, + "rx_icu: DMAC not implemented\n"); + break; + case A_IRQCR ... A_IRQCR + 0x1f: + icu->src[64 + reg].sense =3D val >> R_IRQCR_IRQMD_SHIFT; + break; + case A_NMICLR: + break; + case A_NMIER: + icu->nmier |=3D val & (R_NMIER_NMIEN_MASK | + R_NMIER_LVDEN_MASK | + R_NMIER_OSTEN_MASK); + break; + case A_NMICR: + if ((icu->nmier & R_NMIER_NMIEN_MASK) =3D=3D 0) { + icu->nmicr =3D val & R_NMICR_NMIMD_MASK; + } + break; + default: + qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX + " not implemented\n", addr); + break; + } +} + +static const MemoryRegionOps icu_ops =3D { + .write =3D icu_write, + .read =3D icu_read, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .max_access_size =3D 2, + }, +}; + +static void rxicu_realize(DeviceState *dev, Error **errp) +{ + RXICUState *icu =3D RXICU(dev); + int i, j; + + if (icu->init_sense =3D=3D NULL) { + qemu_log_mask(LOG_GUEST_ERROR, + "rx_icu: trigger-level property must be set."); + return; + } + for (i =3D j =3D 0; i < NR_IRQS; i++) { + if (icu->init_sense[j] =3D=3D i) { + icu->src[i].sense =3D TRG_LEVEL; + if (j < icu->nr_sense) { + j++; + } + } else { + icu->src[i].sense =3D TRG_PEDGE; + } + } + icu->req_irq =3D -1; +} + +static void rxicu_init(Object *obj) +{ + SysBusDevice *d =3D SYS_BUS_DEVICE(obj); + RXICUState *icu =3D RXICU(obj); + + memory_region_init_io(&icu->memory, OBJECT(icu), &icu_ops, + icu, "rx-icu", 0x600); + sysbus_init_mmio(d, &icu->memory); + + qdev_init_gpio_in(DEVICE(d), rxicu_set_irq, NR_IRQS); + qdev_init_gpio_in_named(DEVICE(d), rxicu_ack_irq, "ack", 1); + sysbus_init_irq(d, &icu->_irq); + sysbus_init_irq(d, &icu->_fir); + sysbus_init_irq(d, &icu->_swi); +} + +static void rxicu_fini(Object *obj) +{ + RXICUState *icu =3D RXICU(obj); + g_free(icu->map); + g_free(icu->init_sense); +} + +static const VMStateDescription vmstate_rxicu =3D { + .name =3D "rx-icu", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rxicu_properties[] =3D { + DEFINE_PROP_ARRAY("ipr-map", RXICUState, nr_irqs, map, + qdev_prop_uint32, uint32_t), + DEFINE_PROP_ARRAY("trigger-level", RXICUState, nr_sense, init_sense, + qdev_prop_uint32, uint32_t), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rxicu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->realize =3D rxicu_realize; + dc->vmsd =3D &vmstate_rxicu; + device_class_set_props(dc, rxicu_properties); +} + +static const TypeInfo rxicu_info =3D { + .name =3D TYPE_RXICU, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RXICUState), + .instance_init =3D rxicu_init, + .instance_finalize =3D rxicu_fini, + .class_init =3D rxicu_class_init, +}; + +static void rxicu_register_types(void) +{ + type_register_static(&rxicu_info); +} + +type_init(rxicu_register_types) diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index f726d87532..f17cbd1a9f 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -49,3 +49,4 @@ obj-$(CONFIG_ARM_GIC) +=3D arm_gicv3_cpuif.o obj-$(CONFIG_MIPS_CPS) +=3D mips_gic.o obj-$(CONFIG_NIOS2) +=3D nios2_iic.o obj-$(CONFIG_OMPIC) +=3D ompic.o +obj-$(CONFIG_RX) +=3D rx_icu.o --=20 2.20.1 From nobody Fri May 17 04:49:49 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 ARC-Seal: i=1; a=rsa-sha256; t=1590942553; cv=none; d=zohomail.com; s=zohoarc; b=NPdxraGTx0bhZGsHJBVpMRy8TE+VblMLUngYBbxas1XgToeoAyzbxFDoHT3l4IF0T6xEoKm7gWV29MedlUtNIHgTj8izfJBauTwRXo3xcpMpixxme3DYnI9iW65M2yxqfAOVBMOul780mtDU/c1jgNRuHAdCFbyn4MzfH7SV9/I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1590942553; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=GZKEmhMThUV6lFECrHWO68HKz1iYkbXKjc8ZexJmjto=; b=jj+u10MWQNjfDhZ4QRn810Rp5S+snuhqPtIadKB5Y/4XegU96BuxxZSBctcaNRmF32kK+pA1FvzzXORWFJGnEmSN8SfaYO5lQ71Cl0p+kdPC41S9I3C1xOR26LHF2R1N1vgGyLoskMZZvD+6XCeCOssKS6pMtXfps3HpnWNIOdI= 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1590942553293695.725751271619; Sun, 31 May 2020 09:29:13 -0700 (PDT) Received: from localhost ([::1]:60350 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQpj-0003Gm-Ve for importer@patchew.org; Sun, 31 May 2020 12:29:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53682) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jfQlM-0004Dh-GL for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:40 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:48255) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQlK-0004K0-0D for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:40 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 1E93DECD38; Mon, 1 Jun 2020 01:24:32 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by sakura.ysato.name (Postfix) with ESMTPSA id 6EC0A1C0DB6; Mon, 1 Jun 2020 01:24:32 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 02/10] hw/timer: Renesas 8bit timer module. Date: Mon, 1 Jun 2020 01:24:19 +0900 Message-Id: <20200531162427.57410-3-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200531162427.57410-1-ysato@users.sourceforge.jp> References: <20200531162427.57410-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 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: softfail client-ip=202.224.55.15; envelope-from=ysato@users.sourceforge.jp; helo=mail03.asahi-net.or.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/31 12:24:33 X-ACL-Warn: Detected OS = ??? 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_DNSWL_LOW=-0.7, SPF_SOFTFAIL=0.665, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" 8bit or 16bit timer. This implementation support only internal clock mode. Hardware manual. https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej= 0140_rx62n.pdf Signed-off-by: Yoshinori Sato --- include/hw/timer/renesas_8timer.h | 61 ++++ hw/timer/renesas_8timer.c | 466 ++++++++++++++++++++++++++++++ hw/timer/Kconfig | 3 + hw/timer/Makefile.objs | 2 + 4 files changed, 532 insertions(+) create mode 100644 include/hw/timer/renesas_8timer.h create mode 100644 hw/timer/renesas_8timer.c diff --git a/include/hw/timer/renesas_8timer.h b/include/hw/timer/renesas_8= timer.h new file mode 100644 index 0000000000..7e05c7be97 --- /dev/null +++ b/include/hw/timer/renesas_8timer.h @@ -0,0 +1,61 @@ +/* + * Renesas 8bit timer Object + * + * Copyright (c) 2018 Yoshinori Sato + * + * This code is licensed under the GPL version 2 or later. + * + */ + +#ifndef HW_RENESAS_TMR_H +#define HW_RENESAS_TMR_H + +#include "hw/sysbus.h" + +#define TYPE_RENESAS_8TMR "renesas-8tmr" +#define RTMR(obj) OBJECT_CHECK(RTMRState, (obj), TYPE_RENESAS_8TMR) + +enum timer_event { + cmia, cmib, ovi, wovi, + TMR_NR_EVENTS, +}; + +enum { + TMR_CH =3D 2, + TMR_NR_COR =3D 2, + TMR_NR_IRQ =3D 3, +}; + +enum { + IRQ_CMIA, IRQ_CMIB, IRQ_OVI, +}; + +struct RTMRState; + +struct channel_8tmr { + uint16_t cnt; + uint16_t cor[TMR_NR_COR]; + uint8_t tcr; + uint8_t tccr; + uint8_t tcsr; + qemu_irq irq[TMR_NR_IRQ]; + QEMUTimer *timer; + int64_t base; + int64_t next; + int64_t clk; + enum timer_event event; + int id; + struct RTMRState *tmrp; + bool word; +}; + +typedef struct RTMRState { + SysBusDevice parent_obj; + + uint64_t input_freq; + MemoryRegion memory; + + struct channel_8tmr ch[TMR_CH]; +} RTMRState; + +#endif diff --git a/hw/timer/renesas_8timer.c b/hw/timer/renesas_8timer.c new file mode 100644 index 0000000000..b545ba0e2b --- /dev/null +++ b/hw/timer/renesas_8timer.c @@ -0,0 +1,466 @@ +/* + * Renesas 8bit timer + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 f= or + * 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-common.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "qemu/timer.h" +#include "qemu/bitops.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/qdev-properties.h" +#include "hw/timer/renesas_8timer.h" +#include "migration/vmstate.h" +#include "qemu/error-report.h" + +REG8(TCR, 0) + FIELD(TCR, CCLR, 3, 2) + FIELD(TCR, OVIE, 5, 1) + FIELD(TCR, CMIEA, 6, 1) + FIELD(TCR, CMIEB, 7, 1) +REG8(TCSR, 2) + FIELD(TCSR, OSA, 0, 2) + FIELD(TCSR, OSB, 2, 2) + FIELD(TCSR, ADTE, 4, 1) +REG8(TCORA, 4) +REG8(TCORB, 6) +REG8(TCNT, 8) +REG8(TCCR, 10) + FIELD(TCCR, CKS, 0, 3) + FIELD(TCCR, CSS, 3, 2) + FIELD(TCCR, TMRIS, 7, 1) + +#define CLK_EVT -1 + +static void update_clk(RTMRState *tmr, int ch) +{ + int64_t t; + static const int divlist[] =3D {1, 2, 8, 32, 64, 1024, 8192, 0}; + switch (FIELD_EX8(tmr->ch[ch].tccr, TCCR, CSS)) { + case 0: + qemu_log_mask(LOG_UNIMP, + "renesas_8timer: External clock not implemented."); + tmr->ch[ch].clk =3D 0; + break; + case 1: + /* Internal clock */ + t =3D divlist[FIELD_EX8(tmr->ch[ch].tccr, TCCR, CKS)]; + if (t > 0) { + tmr->ch[ch].clk =3D tmr->input_freq / t; + tmr->ch[ch].clk =3D NANOSECONDS_PER_SECOND / t; + } else { + tmr->ch[ch].clk =3D 0; + } + break; + case 2: + qemu_log_mask(LOG_UNIMP, + "renesas_8timer: CSS undefined."); + tmr->ch[ch].clk =3D 0; + break; + case 3: + /* Event count */ + tmr->ch[ch].clk =3D CLK_EVT; + break; + } +} + +static uint16_t catreg(uint8_t hi, uint8_t lo) +{ + uint16_t ret =3D 0; + ret =3D deposit32(ret, 8, 8, hi); + ret =3D deposit32(ret, 0, 8, lo); + return ret; +} + +static int is_clr(uint8_t tcr, int event) +{ + return FIELD_EX8(tcr, TCR, CCLR) =3D=3D (event + 1); +} + +static int is_irq(uint8_t tcr, int event) +{ + switch (event) { + case cmia: + return FIELD_EX8(tcr, TCR, CMIEA); + case cmib: + return FIELD_EX8(tcr, TCR, CMIEB); + case ovi: + return FIELD_EX8(tcr, TCR, OVIE); + default: + g_assert_not_reached(); + } +} + +static void set_next_event(RTMRState *tmr, int ch) +{ + int64_t next =3D 0; + int evt; + int cor; + int min; + if (ch =3D=3D 1 && tmr->ch[ch].word) { + /* 16bit count mode */ + next =3D 0x10000 - catreg(tmr->ch[0].cnt, tmr->ch[1].cnt); + next *=3D tmr->ch[1].clk; + tmr->ch[0].event =3D tmr->ch[1].event =3D wovi; + } else if (tmr->ch[1].clk > 0) { + min =3D 0x101; + for (evt =3D cmia; evt < TMR_NR_EVENTS - 1; evt++) { + cor =3D (evt < TMR_NR_COR) ? (tmr->ch[ch].cor[evt]) : 0xff; + /* event happend compare match +1 */ + cor++; + if (tmr->ch[ch].cnt < cor) { + if (evt < TMR_NR_COR && + !is_clr(tmr->ch[ch].tcr, evt) && + !is_irq(tmr->ch[ch].tcr, evt)) { + /* no event happend */ + continue; + } + if (min > cor) { + min =3D cor; + next =3D cor - tmr->ch[ch].cnt; + next *=3D tmr->ch[ch].clk; + tmr->ch[ch].event =3D evt; + } + } + } + } + if (next > 0) { + tmr->ch[ch].base =3D tmr->ch[ch].next; + tmr->ch[ch].next +=3D next; + timer_mod(tmr->ch[ch].timer, tmr->ch[ch].next); + } else { + timer_del(tmr->ch[ch].timer); + } +} + +static void event_countup(struct channel_8tmr *ch) +{ + int evt; + int cor; + + ch->cnt++; + for (evt =3D cmia; evt < TMR_NR_COR - 1; evt++) { + cor =3D ch->cor[evt]; + if (ch->cnt =3D=3D (cor + 1) && is_clr(ch->tcr, evt)) { + ch->cnt =3D 0; + } + if (ch->cnt =3D=3D cor && is_irq(ch->tcr, evt)) { + qemu_irq_pulse(ch->irq[evt]); + } + } + if (ch->cnt =3D=3D 0x100) { + ch->cnt =3D 0; + if (is_irq(ch->tcr, ovi)) { + qemu_irq_pulse(ch->irq[IRQ_OVI]); + } + } +} + +static void timer_event(void *opaque) +{ + struct channel_8tmr *ch =3D opaque; + RTMRState *tmr =3D ch->tmrp; + + switch (ch->event) { + case cmia: + if (ch->id =3D=3D 0 && tmr->ch[1].clk =3D=3D CLK_EVT) { + /* CH1 event count */ + event_countup(&tmr->ch[1]); + } + /* Falls through. */ + case cmib: + if (FIELD_EX8(ch->tcr, TCR, CCLR) =3D=3D (ch->event + 1)) { + ch->cnt =3D 0; + } else { + ch->cnt =3D ch->cor[ch->event] + 1; + } + if (is_irq(ch->tcr, ch->event)) { + qemu_irq_pulse(ch->irq[ch->event]); + } + break; + case ovi: + ch->cnt =3D 0; + if (is_irq(ch->tcr, ovi)) { + qemu_irq_pulse(ch->irq[IRQ_OVI]); + } + if (ch->id =3D=3D 1 && tmr->ch[0].clk =3D=3D CLK_EVT) { + /* CH0 event count */ + event_countup(&tmr->ch[0]); + } + break; + case wovi: + tmr->ch[0].cnt =3D tmr->ch[1].cnt =3D 0; + if (is_irq(tmr->ch[0].tcr, ovi)) { + qemu_irq_pulse(tmr->ch[0].irq[IRQ_OVI]); + } + break; + default: + g_assert_not_reached(); + } + set_next_event(tmr, ch->id); +} + +static uint16_t read_tcnt(RTMRState *tmr, unsigned int size, int ch) +{ + int64_t now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + int64_t delta; + uint8_t ret[2]; + int i; + + switch (size) { + case 1: + if (tmr->ch[ch].clk > 0) { + delta =3D now - tmr->ch[ch].base; + delta /=3D tmr->ch[ch].clk; + } else { + delta =3D 0; + } + return tmr->ch[ch].cnt + delta; + case 2: + if (tmr->ch[1].word) { + /* 16bit count mode */ + delta =3D now - tmr->ch[1].base; + delta /=3D tmr->ch[1].clk; + return catreg(tmr->ch[0].cnt, tmr->ch[1].cnt) + delta; + } else { + for (i =3D 0; i < TMR_CH; i++) { + if (tmr->ch[ch].clk > 0) { + delta =3D now - tmr->ch[ch].base; + delta /=3D tmr->ch[ch].clk; + } else { + delta =3D 0; + } + ret[i] =3D tmr->ch[i].cnt + delta; + } + return catreg(ret[0], ret[1]); + } + default: + g_assert_not_reached(); + } +} + +static int validate_access(hwaddr addr, unsigned int size) +{ + /* Byte access always OK */ + if (size =3D=3D 1) { + return 1; + } + return (addr >=3D A_TCORA); +} + +static uint64_t tmr_read(void *opaque, hwaddr addr, unsigned int size) +{ + RTMRState *tmr =3D opaque; + int ch =3D addr & 1; + int cor; + + if (!validate_access(addr, size)) { + qemu_log_mask(LOG_GUEST_ERROR, "renesas_tmr: Invalid read size 0x%" + HWADDR_PRIX "\n", addr); + return UINT64_MAX; + } + switch (addr & ~1) { + case A_TCR: + return tmr->ch[ch].tcr; + case A_TCSR: + return tmr->ch[ch].tcsr; + case A_TCORA: + case A_TCORB: + cor =3D (addr & 2) >> 1; + if (size =3D=3D 1) { + return tmr->ch[ch].cor[cor]; + } else { + return catreg(tmr->ch[0].cor[cor], tmr->ch[1].cor[cor]); + } + case A_TCNT: + return read_tcnt(tmr, size, ch); + case A_TCCR: + if (size =3D=3D 1) { + return tmr->ch[ch].tccr; + } else { + return catreg(tmr->ch[0].tccr, tmr->ch[1].tccr); + } + default: + qemu_log_mask(LOG_UNIMP, "renesas_tmr: Register 0x%" HWADDR_PRIX + " not implemented\n", addr); + break; + } + return UINT64_MAX; +} + +static void tmr_write(void *opaque, hwaddr addr, uint64_t val, unsigned si= ze) +{ + RTMRState *tmr =3D opaque; + int ch =3D addr & 1; + int cor; + int64_t now; + + if (!validate_access(addr, size)) { + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_tmr: Invalid write size 0x%" HWADDR_PRIX + "\n", addr); + return; + } + switch (addr & ~1) { + case A_TCR: + tmr->ch[ch].tcr =3D val; + break; + case A_TCSR: + if (ch =3D=3D 1) { + val =3D FIELD_DP8(val, TCSR, ADTE, 1); + } + tmr->ch[ch].tcsr =3D val; + break; + case A_TCORA: + case A_TCORB: + cor =3D (addr & 2) >> 1; + if (size =3D=3D 1) { + tmr->ch[ch].cor[cor] =3D val; + } else { + tmr->ch[0].cor[cor] =3D extract32(val, 0, 8); + tmr->ch[1].cor[cor] =3D extract32(val, 8, 8); + } + break; + case A_TCNT: + now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + if (size =3D=3D 1) { + tmr->ch[ch].base =3D now; + tmr->ch[ch].cnt =3D val; + } else { + tmr->ch[0].base =3D tmr->ch[1].base =3D now; + tmr->ch[0].cnt =3D extract32(val, 0, 8); + tmr->ch[1].cnt =3D extract32(val, 8, 8); + } + break; + case A_TCCR: + val &=3D ~0x6060; + if (size =3D=3D 1) { + tmr->ch[ch].tccr =3D val; + update_clk(tmr, ch); + } else { + tmr->ch[0].tccr =3D extract32(val, 0, 8); + tmr->ch[1].tccr =3D extract32(val, 8, 8); + update_clk(tmr, 0); + update_clk(tmr, 1); + } + break; + default: + qemu_log_mask(LOG_UNIMP, "renesas_tmr: Register 0x%" HWADDR_PRIX + " not implemented\n", addr); + return; + } + /* + * If some conditions are met, + * the event does not occur until the 16-bit counter overflows. + */ + tmr->ch[1].word =3D (tmr->ch[0].clk =3D=3D -1 && tmr->ch[1].clk > 0 && + (tmr->ch[0].tcr & 0xe8) =3D=3D 0x00 && + (tmr->ch[0].tcr & 0xf8) =3D=3D 0x00); + if (size =3D=3D 1) { + set_next_event(tmr, ch); + } else { + set_next_event(tmr, 0); + set_next_event(tmr, 1); + } +} + +static const MemoryRegionOps tmr_ops =3D { + .write =3D tmr_write, + .read =3D tmr_read, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .min_access_size =3D 1, + .max_access_size =3D 2, + }, +}; + +static void rtmr_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *d =3D SYS_BUS_DEVICE(dev); + RTMRState *tmr =3D RTMR(dev); + int i; + + if (tmr->input_freq =3D=3D 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_8tmr: input-freq property must be set."); + return; + } + + memory_region_init_io(&tmr->memory, OBJECT(tmr), &tmr_ops, + tmr, "renesas-8tmr", 0x10); + sysbus_init_mmio(d, &tmr->memory); + + for (i =3D 0; i < TMR_CH; i++) { + sysbus_init_irq(d, &tmr->ch[i].irq[IRQ_CMIA]); + sysbus_init_irq(d, &tmr->ch[i].irq[IRQ_CMIB]); + sysbus_init_irq(d, &tmr->ch[i].irq[IRQ_OVI]); + tmr->ch[i].id =3D i; + tmr->ch[i].timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + timer_event, &tmr->ch[i]); + tmr->ch[i].tmrp =3D tmr; + tmr->ch[i].tcr =3D 0x00; + tmr->ch[i].tcsr =3D (i =3D=3D 0) ? 0x00 : 0x10; + tmr->ch[i].cnt =3D 0x00; + tmr->ch[i].cor[0] =3D 0xff; + tmr->ch[i].cor[1] =3D 0xff; + tmr->ch[i].tccr =3D 0x00; + } +} + +static const VMStateDescription vmstate_rtmr =3D { + .name =3D "renesas-8tmr", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rtmr_properties[] =3D { + DEFINE_PROP_UINT64("input-freq", RTMRState, input_freq, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rtmr_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->vmsd =3D &vmstate_rtmr; + dc->realize =3D rtmr_realize; + device_class_set_props(dc, rtmr_properties); +} + +static const TypeInfo rtmr_info =3D { + .name =3D TYPE_RENESAS_8TMR, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RTMRState), + .class_init =3D rtmr_class_init, +}; + +static void rtmr_register_types(void) +{ + type_register_static(&rtmr_info); +} + +type_init(rtmr_register_types) diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig index 59b3f44d69..93f62999eb 100644 --- a/hw/timer/Kconfig +++ b/hw/timer/Kconfig @@ -35,3 +35,6 @@ config CMSDK_APB_TIMER config CMSDK_APB_DUALTIMER bool select PTIMER + +config RENESAS_8TMR + bool diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index dece235fd7..9ea88b964d 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -35,3 +35,5 @@ common-obj-$(CONFIG_CMSDK_APB_TIMER) +=3D cmsdk-apb-timer= .o common-obj-$(CONFIG_CMSDK_APB_DUALTIMER) +=3D cmsdk-apb-dualtimer.o common-obj-$(CONFIG_MSF2) +=3D mss-timer.o common-obj-$(CONFIG_RASPI) +=3D bcm2835_systmr.o + +common-obj-$(CONFIG_RENESAS_8TMR) +=3D renesas_8timer.o --=20 2.20.1 From nobody Fri May 17 04:49:49 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 ARC-Seal: i=1; a=rsa-sha256; t=1590942551; cv=none; d=zohomail.com; s=zohoarc; b=XXJ1iBGkMTe8/G6Jf8RXQf1xOwpYEJqZ8ASCV1+PsVQu6n1D34MSEQ7DMVR1Q7UZh3NSQ6sBxJRFQtjVNrGDYk5QMCQ/aWMJ8X5ZLVxlKqCMRFI6j81gMWEtgSnicTenqZeEANt8avezk313DH9/vL+SLwnd2glvjuetn6xZmWA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1590942551; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=lqMyIZClsoZwP5jGDVrYboJXidFUqcyJFg263+PuVqY=; b=QDfqd2FPRN+ZkNlPii8oyWbxysUGXZdSePp+87vjuVuTFeYTZGG4KJ1wKVkbJFkZpS9zm3x3q0nI8gAiYVUW+WSO8/ZwyB3roDLFFUkN97EDBF6BV8i5fFwGpwY+51otrKL8BrjeSbPcM2hiC4liaPM95FL1Z8kI54lG1GEftQM= 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1590942551325978.3084638597934; Sun, 31 May 2020 09:29:11 -0700 (PDT) Received: from localhost ([::1]:60206 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQph-0003DM-UM for importer@patchew.org; Sun, 31 May 2020 12:29:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53684) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jfQlM-0004Dn-Nb for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:40 -0400 Received: from mail01.asahi-net.or.jp ([202.224.55.13]:36014) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQlK-0004K1-17 for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:40 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail01.asahi-net.or.jp (Postfix) with ESMTPA id 4AB04105230; Mon, 1 Jun 2020 01:24:33 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by sakura.ysato.name (Postfix) with ESMTPSA id C54D51C0DB7; Mon, 1 Jun 2020 01:24:32 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 03/10] hw/timer: Renesas TMU/CMT module. Date: Mon, 1 Jun 2020 01:24:20 +0900 Message-Id: <20200531162427.57410-4-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200531162427.57410-1-ysato@users.sourceforge.jp> References: <20200531162427.57410-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 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: softfail client-ip=202.224.55.13; envelope-from=ysato@users.sourceforge.jp; helo=mail01.asahi-net.or.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/31 12:24:33 X-ACL-Warn: Detected OS = ??? 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_DNSWL_LOW=-0.7, SPF_SOFTFAIL=0.665, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" TMU - SH4 Timer module. CMT - Compare and match timer used by some Renesas MCUs. The two modules have similar interfaces and have been merged. Signed-off-by: Yoshinori Sato --- include/hw/timer/renesas_timer.h | 59 +++++ hw/timer/renesas_timer.c | 421 +++++++++++++++++++++++++++++++ hw/timer/Kconfig | 3 + hw/timer/Makefile.objs | 1 + 4 files changed, 484 insertions(+) create mode 100644 include/hw/timer/renesas_timer.h create mode 100644 hw/timer/renesas_timer.c diff --git a/include/hw/timer/renesas_timer.h b/include/hw/timer/renesas_ti= mer.h new file mode 100644 index 0000000000..f9a2661203 --- /dev/null +++ b/include/hw/timer/renesas_timer.h @@ -0,0 +1,59 @@ +/* + * Renesas Timer unit Object + * + * Copyright (c) 2020 Yoshinori Sato + * + * This code is licensed under the GPL version 2 or later. + * + */ + +#ifndef HW_RENESAS_TIMER_H +#define HW_RENESAS_TIMER_H + +#include "hw/sysbus.h" + +#define TYPE_RENESAS_TIMER "renesas-timer" +#define RTIMER(obj) OBJECT_CHECK(RTIMERState, (obj), TYPE_RENESAS_TIMER) + +enum { + TIMER_CH_CMT =3D 2, + /* TMU have 5channels. It separated 0-2 and 3-4. */ + TIMER_CH_TMU =3D 3, +}; + +enum { + RTIMER_FEAT_CMT, + RTIMER_FEAT_TMU_LOW, + RTIMER_FEAT_TMU_HIGH, +}; + +struct RTIMERState; + +struct channel_rtimer { + uint32_t cnt; + uint32_t cor; + uint16_t ctrl; + qemu_irq irq; + int64_t base; + int64_t next; + uint64_t clk; + bool start; + QEMUTimer *timer; + struct RTIMERState *tmrp; +}; + +typedef struct RTIMERState { + SysBusDevice parent_obj; + + uint64_t input_freq; + MemoryRegion memory; + MemoryRegion memory_p4; + MemoryRegion memory_a7; + + uint8_t tocr; + struct channel_rtimer ch[TIMER_CH_TMU]; + uint32_t feature; + int num_ch; +} RTIMERState; + +#endif diff --git a/hw/timer/renesas_timer.c b/hw/timer/renesas_timer.c new file mode 100644 index 0000000000..459c7a4708 --- /dev/null +++ b/hw/timer/renesas_timer.c @@ -0,0 +1,421 @@ +/* + * Renesas 16bit Compare-match timer + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 f= or + * 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-common.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "qemu/timer.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/qdev-properties.h" +#include "hw/timer/renesas_timer.h" +#include "migration/vmstate.h" +#include "qemu/error-report.h" + +REG32(TOCR, 0) + FIELD(TOCR, TCOE, 0, 1) +REG32(TSTR, 4) +REG32(TCOR, 8) +REG32(TCNT, 12) +REG32(TCR, 16) + FIELD(TCR, TPSC, 0, 3) + FIELD(TCR, CKEG, 3, 2) + FIELD(TCR, UNIE, 5, 1) + FIELD(TCR, ICPE, 6, 2) + FIELD(TCR, UNF, 8, 1) + FIELD(TCR, ICPF, 9, 1) +REG32(CMCR, 16) + FIELD(CMCR, CKS, 0, 2) + FIELD(CMCR, CMIE, 6, 1) +REG32(TCPR, 20) + +#define IS_CMT(t) (t->feature =3D=3D RTIMER_FEAT_CMT) + +static int clkdiv(RTIMERState *tmr, int ch) +{ + if (IS_CMT(tmr)) { + return 8 << (2 * FIELD_EX16(tmr->ch[ch].ctrl, CMCR, CKS)); + } else { + if (FIELD_EX16(tmr->ch[ch].ctrl, TCR, TPSC) <=3D 5) { + return 4 << (2 * FIELD_EX16(tmr->ch[ch].ctrl, TCR, TPSC)); + } else { + return 0; + } + } +} + +static void set_next_event(struct channel_rtimer *ch, int64_t now) +{ + int64_t next; + RTIMERState *tmr =3D ch->tmrp; + if (IS_CMT(tmr)) { + next =3D ch->cor - ch->cnt; + } else { + next =3D ch->cnt; + } + next *=3D ch->clk; + ch->base =3D now; + ch->next =3D now + next; + timer_mod(ch->timer, ch->next); +} + +static void timer_event(void *opaque) +{ + struct channel_rtimer *ch =3D opaque; + RTIMERState *tmr =3D ch->tmrp; + + if (IS_CMT(tmr)) { + ch->cnt =3D 0; + if (FIELD_EX16(ch->ctrl, CMCR, CMIE)) { + qemu_irq_pulse(ch->irq); + } + } else { + ch->cnt =3D ch->cor; + if (!FIELD_EX16(ch->ctrl, TCR, UNF)) { + ch->ctrl =3D FIELD_DP16(ch->ctrl, TCR, UNF, 1); + qemu_set_irq(ch->irq, FIELD_EX16(ch->ctrl, TCR, UNIE)); + } + } + set_next_event(ch, ch->next); +} + +static int64_t read_tcnt(RTIMERState *tmr, int ch) +{ + int64_t delta, now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + if (tmr->ch[ch].clk > 0) { + delta =3D (now - tmr->ch[ch].base); + delta /=3D tmr->ch[ch].clk; + if (IS_CMT(tmr)) { + return delta; + } else { + return tmr->ch[ch].cnt - delta; + } + } else { + return tmr->ch[ch].cnt; + } +} + +static void tmr_start_stop(RTIMERState *tmr, int ch, int start) +{ + int64_t now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + tmr->ch[ch].start =3D start; + if (start) { + if (!tmr->ch[ch].timer) { + tmr->ch[ch].timer =3D + timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event, &tmr->ch[ch]= ); + } + set_next_event(&tmr->ch[ch], now); + } else { + tmr->ch[ch].cnt =3D read_tcnt(tmr, ch); + tmr->ch[ch].next =3D 0; + if (tmr->ch[ch].timer) { + timer_del(tmr->ch[ch].timer); + } + } +} + +static void timer_register(RTIMERState *tmr, hwaddr addr, int *ch, int *re= g) +{ + if (IS_CMT(tmr)) { + /* +0 - CMSTR (TSTR) */ + /* +2 - CMCR0 (TCR) */ + /* +4 - CMCNT0 (TCNT) */ + /* +6 - CMCOR0 (TCOR) */ + /* +8 - CMCR1 (TCR) */ + /* +10 - CMCNT1 (TCNT) */ + /* +12 - CMCOR1 (TCOR) */ + addr /=3D 2; + if (addr > 6) { + /* Out of register area */ + *reg =3D -1; + return; + } + if (addr =3D=3D 0) { + *ch =3D -1; + *reg =3D R_TSTR; + } else { + *ch =3D addr / 4; + if (addr < 4) { + /* skip CMSTR */ + addr--; + } + *reg =3D 2 - (addr % 4); + } + } else { + /* +0 - TCOR */ + /* +4 - TSTR */ + /* +8 - TCOR0 */ + /* +12 - TCNT0 */ + /* +16 - TCR0 */ + /* +20 - TCOR1 */ + /* +24 - TCNT1 */ + /* +28 - TCR1 */ + /* +32 - TCOR2 */ + /* +36 - TCNT2 */ + /* +40 - TCR2 */ + /* +44 - TCPR2 */ + if (tmr->feature =3D=3D RTIMER_FEAT_TMU_HIGH && addr >=3D 8) { + *reg =3D -1; + return; + } + addr /=3D 4; + if (addr < 2) { + *ch =3D -1; + *reg =3D addr; + } else if (addr < 11) { + *ch =3D (addr - 2) / 3; + *reg =3D (addr - 2) % 3 + 2; + } else { + *ch =3D 2; + *reg =3D R_TCPR; + } + } +} + +static uint64_t read_tstr(RTIMERState *tmr) +{ + uint64_t ret =3D 0; + int ch; + for (ch =3D 0; ch < tmr->num_ch; ch++) { + ret =3D deposit64(ret, ch, 1, tmr->ch[ch].start); + } + return ret; +} + +static void update_clk(RTIMERState *tmr, int ch) +{ + int tpsc; + int t; + if (!IS_CMT(tmr)) { + /* Clock setting validation */ + tpsc =3D FIELD_EX16(tmr->ch[ch].ctrl, TCR, TPSC); + switch (tpsc) { + case 5: + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_timer: Invalid TPSC valule %d.", tpsc); + break; + case 6: + case 7: + qemu_log_mask(LOG_UNIMP, + "renesas_timer: External clock not implemented."= ); + break; + } + /* Interrupt clear */ + if (FIELD_EX16(tmr->ch[ch].ctrl, TCR, UNF) =3D=3D 0) { + qemu_set_irq(tmr->ch[ch].irq, 0); + } + } + t =3D clkdiv(tmr, ch); + if (t > 0) { + t =3D tmr->input_freq / t; + tmr->ch[ch].clk =3D NANOSECONDS_PER_SECOND / t; + } else { + tmr->ch[ch].clk =3D 0; + } +} + +static uint64_t tmr_read(void *opaque, hwaddr addr, unsigned size) +{ + RTIMERState *tmr =3D opaque; + int ch =3D -1, reg =3D -1; + + timer_register(tmr, addr, &ch, ®); + switch (reg) { + case R_TOCR: + return tmr->tocr; + case R_TSTR: + return read_tstr(tmr); + case R_TCR: + return tmr->ch[ch].ctrl; + case R_TCNT: + if (tmr->ch[ch].start) { + return read_tcnt(tmr, ch); + } else { + return tmr->ch[ch].cnt; + } + case R_TCOR: + return tmr->ch[ch].cor; + case R_TCPR: + qemu_log_mask(LOG_UNIMP, + "renesas_timer: Input capture not implemented\n"); + return 0; + default: + qemu_log_mask(LOG_UNIMP, "renesas_timer: Register 0x%" + HWADDR_PRIX " not implemented\n", addr); + } + return UINT64_MAX; +} + +static void tmr_write(void *opaque, hwaddr addr, uint64_t val, unsigned si= ze) +{ + RTIMERState *tmr =3D opaque; + int ch =3D -1, reg =3D -1; + uint16_t tcr_mask; + + timer_register(tmr, addr, &ch, ®); + switch (reg) { + case R_TOCR: + tmr->tocr =3D FIELD_DP8(tmr->tocr, TOCR, TCOE, + FIELD_EX8(val, TOCR, TCOE)); + break; + case R_TSTR: + for (ch =3D 0; ch < tmr->num_ch; ch++) { + tmr_start_stop(tmr, ch, extract32(val, ch, 1)); + } + break; + case R_TCR: + switch (tmr->feature) { + case RTIMER_FEAT_CMT: + tcr_mask =3D 0x00a3; + /* bit7 always 1 */ + val |=3D 0x0080; + break; + case RTIMER_FEAT_TMU_LOW: + tcr_mask =3D (ch < 2) ? 0x013f : 0x03ff; + break; + case RTIMER_FEAT_TMU_HIGH: + tcr_mask =3D 0x0127; + break; + default: + tcr_mask =3D 0x00ff; + break; + } + /* Upper byte write only 0 */ + tmr->ch[ch].ctrl |=3D (tcr_mask & 0x00ff); + tmr->ch[ch].ctrl &=3D val & tcr_mask; + update_clk(tmr, ch); + break; + case R_TCNT: + tmr->ch[ch].cnt =3D val; + break; + case R_TCOR: + tmr->ch[ch].cor =3D val; + break; + case R_TCPR: + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_timer: TCPR is read only."); + break; + default: + qemu_log_mask(LOG_UNIMP, "renesas_timer: Register 0x%" + HWADDR_PRIX " not implemented\n", addr); + } +} + +static const MemoryRegionOps tmr_ops =3D { + .write =3D tmr_write, + .read =3D tmr_read, + .endianness =3D DEVICE_NATIVE_ENDIAN, + .impl =3D { + .min_access_size =3D 2, + .max_access_size =3D 4, + }, +}; + +static void rtimer_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *d =3D SYS_BUS_DEVICE(dev); + RTIMERState *tmr =3D RTIMER(dev); + int i; + int ch; + + if (tmr->input_freq =3D=3D 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_timer: input-freq property must be set."); + return; + } + if (IS_CMT(tmr)) { + memory_region_init_io(&tmr->memory, OBJECT(tmr), &tmr_ops, + tmr, "renesas-cmt", 0x10); + sysbus_init_mmio(d, &tmr->memory); + + for (i =3D 0; i < TIMER_CH_CMT; i++) { + sysbus_init_irq(d, &tmr->ch[i].irq); + } + tmr->num_ch =3D 2; + } else { + memory_region_init_io(&tmr->memory, OBJECT(tmr), &tmr_ops, + tmr, "renesas-tmu", 0x30); + sysbus_init_mmio(d, &tmr->memory); + memory_region_init_alias(&tmr->memory_p4, NULL, "renesas-tmu-p4", + &tmr->memory, 0, 0x30); + sysbus_init_mmio(d, &tmr->memory_p4); + memory_region_init_alias(&tmr->memory_a7, NULL, "renesas-tmu-a7", + &tmr->memory, 0, 0x30); + sysbus_init_mmio(d, &tmr->memory_a7); + ch =3D (tmr->feature =3D=3D RTIMER_FEAT_TMU_LOW) ? + TIMER_CH_TMU : TIMER_CH_TMU - 1; + for (i =3D 0; i < ch; i++) { + sysbus_init_irq(d, &tmr->ch[i].irq); + } + tmr->num_ch =3D (tmr->feature =3D=3D RTIMER_FEAT_TMU_LOW) ? 3 : 2; + } + for (ch =3D 0; ch < tmr->num_ch; ch++) { + tmr->ch[ch].tmrp =3D tmr; + update_clk(tmr, ch); + if (IS_CMT(tmr)) { + tmr->ch[ch].cor =3D 0xffff; + } else { + tmr->ch[ch].cor =3D tmr->ch[ch].cnt =3D 0xffffffff; + } + } +} + +static const VMStateDescription vmstate_rtimer =3D { + .name =3D "rx-cmt", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rtimer_properties[] =3D { + DEFINE_PROP_UINT32("feature", RTIMERState, feature, 0), + DEFINE_PROP_UINT64("input-freq", RTIMERState, input_freq, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rtimer_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->vmsd =3D &vmstate_rtimer; + dc->realize =3D rtimer_realize; + device_class_set_props(dc, rtimer_properties); +} + +static const TypeInfo rtimer_info =3D { + .name =3D TYPE_RENESAS_TIMER, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RTIMERState), + .class_init =3D rtimer_class_init, +}; + +static void rtimer_register_types(void) +{ + type_register_static(&rtimer_info); +} + +type_init(rtimer_register_types) diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig index 93f62999eb..ff4b0cd0bc 100644 --- a/hw/timer/Kconfig +++ b/hw/timer/Kconfig @@ -38,3 +38,6 @@ config CMSDK_APB_DUALTIMER =20 config RENESAS_8TMR bool + +config RENESAS_TIMER + bool diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index 9ea88b964d..289b6b03ab 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -37,3 +37,4 @@ common-obj-$(CONFIG_MSF2) +=3D mss-timer.o common-obj-$(CONFIG_RASPI) +=3D bcm2835_systmr.o =20 common-obj-$(CONFIG_RENESAS_8TMR) +=3D renesas_8timer.o +common-obj-$(CONFIG_RENESAS_TIMER) +=3D renesas_timer.o --=20 2.20.1 From nobody Fri May 17 04:49:49 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 ARC-Seal: i=1; a=rsa-sha256; t=1590942761; cv=none; d=zohomail.com; s=zohoarc; b=fyTMKka4LCJ35N+uzc181YcdOeAJbKA8/eb3RynDs1f/gFMVVwVEkxBkwKIbeKVuA5mV+ZRA5nz7jQElCzApTCIVXnNa0vj3iOTfbySrh+QS0LlS5VUPUlVDT9sfW52r9VLRBzRnPvQioTjSEH20OLUf6z1T79/5/s5uo7jfbv0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1590942761; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=4jJeAjzndPUSu7zCJTmdTj2905soJrAqu3MHrBchwMI=; b=GNZhEARqZ6Ff22sxYXBYsoq79Yrxx16hk/9tyZGtPVETwZ4RgD6uatFrNrmCMjdccVRh+vQ89zbViooswvZYTpI+jZ9umSdIT4V2nypj1tLyelJQAOBqLUN6oeRZxwbL8GrSW2JGyvauoxdqc52CswfB0B7aNVptDcYPOBk4+1U= 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1590942761622386.418745116149; Sun, 31 May 2020 09:32:41 -0700 (PDT) Received: from localhost ([::1]:40596 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQt6-00070M-CP for importer@patchew.org; Sun, 31 May 2020 12:32:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53690) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jfQlN-0004FS-4N for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:41 -0400 Received: from mail02.asahi-net.or.jp ([202.224.55.14]:58729) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQlK-0004K3-0B for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:40 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail02.asahi-net.or.jp (Postfix) with ESMTPA id B7334EB8B4; Mon, 1 Jun 2020 01:24:33 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by sakura.ysato.name (Postfix) with ESMTPSA id 30F381C05D2; Mon, 1 Jun 2020 01:24:33 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 04/10] hw/char: Renesas SCI module. Date: Mon, 1 Jun 2020 01:24:21 +0900 Message-Id: <20200531162427.57410-5-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200531162427.57410-1-ysato@users.sourceforge.jp> References: <20200531162427.57410-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 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: softfail client-ip=202.224.55.14; envelope-from=ysato@users.sourceforge.jp; helo=mail02.asahi-net.or.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/31 12:24:33 X-ACL-Warn: Detected OS = ??? 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_DNSWL_LOW=-0.7, SPF_SOFTFAIL=0.665, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" This module supported SCI / SCIa / SCIF. Hardware manual. SCI / SCIF https://www.renesas.com/us/en/doc/products/mpumcu/001/r01uh0457ej0401_sh775= 1.pdf SCIa https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej= 0140_rx62n.pdf Signed-off-by: Yoshinori Sato --- include/hw/char/renesas_sci.h | 77 ++++ hw/char/renesas_sci.c | 786 ++++++++++++++++++++++++++++++++++ hw/char/Kconfig | 3 + hw/char/Makefile.objs | 3 +- 4 files changed, 868 insertions(+), 1 deletion(-) create mode 100644 include/hw/char/renesas_sci.h create mode 100644 hw/char/renesas_sci.c diff --git a/include/hw/char/renesas_sci.h b/include/hw/char/renesas_sci.h new file mode 100644 index 0000000000..9152faff6c --- /dev/null +++ b/include/hw/char/renesas_sci.h @@ -0,0 +1,77 @@ +/* + * Renesas Serial Communication Interface + * + * Copyright (c) 2020 Yoshinori Sato + * + * This code is licensed under the GPL version 2 or later. + * + */ + +#include "chardev/char-fe.h" +#include "qemu/timer.h" +#include "qemu/fifo8.h" +#include "hw/sysbus.h" + +#define TYPE_RENESAS_SCI "renesas-sci" +#define RSCI(obj) OBJECT_CHECK(RSCIState, (obj), TYPE_RENESAS_SCI) + +enum { + ERI =3D 0, + RXI =3D 1, + TXI =3D 2, + TEI =3D 3, + BRI =3D 3, + SCI_NR_IRQ =3D 4, +}; + +enum { + SCI_FEAT_SCI =3D 0x00, + SCI_FEAT_SCIA =3D 0x01, + SCI_FEAT_SCIF =3D 0x10, +}; + +enum { + RXTOUT, + RXNEXT, + TXEMPTY, + TXEND, + NR_SCI_EVENT, +}; + +typedef struct RSCIState { + SysBusDevice parent_obj; + MemoryRegion memory; + MemoryRegion memory_p4; + MemoryRegion memory_a7; + + /* SCI register */ + uint8_t smr; + uint8_t brr; + uint8_t scr; + uint8_t tdr; + uint16_t Xsr; + uint8_t scmr; + uint8_t semr; + uint16_t fcr; + uint16_t sptr; + uint16_t lsr; + + /* internal use */ + uint16_t read_Xsr; + uint16_t read_lsr; + int64_t etu; + int64_t trtime; + int64_t tx_start_time; + int tdcnt; + int regsize; + struct { + int64_t time; + int64_t (*handler)(struct RSCIState *sci); + } event[NR_SCI_EVENT]; + QEMUTimer *event_timer; + CharBackend chr; + uint64_t input_freq; + int feature; + qemu_irq irq[SCI_NR_IRQ]; + Fifo8 rxfifo; +} RSCIState; diff --git a/hw/char/renesas_sci.c b/hw/char/renesas_sci.c new file mode 100644 index 0000000000..6b23055a40 --- /dev/null +++ b/hw/char/renesas_sci.c @@ -0,0 +1,786 @@ +/* + * Renesas Serial Communication Interface (SCI / SCIa / SCIF) + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * And SH7751 Group, SH7751R Group User's Manual: Hardware + * (Rev.4.01 R01UH0457EJ0401) + * + * Copyright (c) 2020 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 f= or + * 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/log.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/qdev-properties.h" +#include "hw/char/renesas_sci.h" +#include "migration/vmstate.h" +#include "qemu/error-report.h" + +/* SCI register map */ +REG8(SMR, 0) + FIELD(SMR, CKS, 0, 2) + FIELD(SMR, MP, 2, 1) + FIELD(SMR, STOP, 3, 1) + FIELD(SMR, PM, 4, 1) + FIELD(SMR, PE, 5, 1) + FIELD(SMR, CHR, 6, 1) + FIELD(SMR, CM, 7, 1) +REG16(BRR, 2) +REG16(SCR, 4) + FIELD(SCR, CKE, 0, 2) + FIELD(SCR, TEIE, 2, 1) + FIELD(SCR, MPIE, 3, 1) + FIELD(SCR, REIE, 3, 1) + FIELD(SCR, RE, 4, 1) + FIELD(SCR, TE, 5, 1) + FIELD(SCR, RIE, 6, 1) + FIELD(SCR, TIE, 7, 1) +REG16(TDR, 6) +REG16(SSR, 8) + FIELD(SSR, MPBT, 0, 1) + FIELD(SSR, MPB, 1, 1) + FIELD(SSR, TEND, 2, 1) + FIELD(SSR, ERR, 3, 3) + FIELD(SSR, PER, 3, 1) + FIELD(SSR, FER, 4, 1) + FIELD(SSR, ORER, 5, 1) + FIELD(SSR, RDRF, 6, 1) + FIELD(SSR, TDRE, 7, 1) +REG16(FSR, 8) + FIELD(FSR, DR, 0, 1) + FIELD(FSR, RDF, 1, 1) + FIELD(FSR, RDF_DR, 0, 2) + FIELD(FSR, PER, 2, 1) + FIELD(FSR, FER, 3, 1) + FIELD(FSR, BRK, 4, 1) + FIELD(FSR, TDFE, 5, 1) + FIELD(FSR, TEND, 6, 1) + FIELD(FSR, ER, 7, 1) + FIELD(FSR, FERn, 8, 4) + FIELD(FSR, PERn, 12, 4) +REG16(RDR, 10) +REG16(SCMR, 12) + FIELD(SCMR, SMIF, 0, 1) + FIELD(SCMR, SINV, 2, 1) + FIELD(SCMR, SDIR, 3, 1) + FIELD(SCMR, BCP2, 7, 1) +REG16(FCR, 12) + FIELD(FCR, LOOP, 0, 1) + FIELD(FCR, RFRST, 1, 1) + FIELD(FCR, TFRST, 2, 1) + FIELD(FCR, MCE, 3, 1) + FIELD(FCR, TTRG, 4, 2) + FIELD(FCR, RTRG, 6, 2) + FIELD(FCR, RSTRG, 8, 3) +REG16(SEMR, 14) + FIELD(SEMR, ACS0, 0, 1) + FIELD(SEMR, ABCS, 4, 1) +REG16(FDR, 14) + FIELD(FDR, Rn, 0, 4) + FIELD(FDR, Tn, 8, 4) +REG16(SPTR, 16) + FIELD(SPTR, SPB2DT, 0, 1) + FIELD(SPTR, SPB2IO, 1, 1) + FIELD(SPTR, SCKDT, 2, 1) + FIELD(SPTR, SCKIO, 3, 1) + FIELD(SPTR, CTSDT, 4, 1) + FIELD(SPTR, CTSIO, 5, 1) + FIELD(SPTR, RTSDT, 6, 1) + FIELD(SPTR, RTSIO, 7, 1) + FIELD(SPTR, EIO, 7, 1) +REG16(LSR, 18) + FIELD(LSR, ORER, 0, 1) + +#define SCIF_FIFO_DEPTH 16 +#define IS_SCI(sci) (sci->feature < SCI_FEAT_SCIF) +#define IS_SCIA(sci) (IS_SCI(sci) && sci->feature >=3D SCI_FEAT_SCIA) +#define IS_SCIF(sci) (!IS_SCI(sci)) + +static const int sci_rtrg[] =3D {1, 4, 8, 14}; + +static void update_event_time(RSCIState *sci, int evt, int64_t t) +{ + if (t > 0) { + t +=3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + sci->event[evt].time =3D t; + if (timer_expire_time_ns(sci->event_timer) > t) { + timer_mod(sci->event_timer, t); + } + } else { + sci->event[evt].time =3D 0; + } +} + +static int sci_is_rxi(RSCIState *sci) +{ + int eio; + int enable; + enable =3D FIELD_EX16(sci->scr, SCR, RIE); + if (IS_SCI(sci)) { + eio =3D (sci->feature !=3D SCI_FEAT_SCI) || + (FIELD_EX16(sci->sptr, SPTR, EIO) =3D=3D 0); + return FIELD_EX16(sci->Xsr, SSR, RDRF) && enable && eio; + } else { + return (FIELD_EX16(sci->Xsr, FSR, RDF_DR) !=3D 0) && enable; + } +} + +static int sci_is_txi(RSCIState *sci) +{ + int enable =3D FIELD_EX16(sci->scr, SCR, TIE); + if (IS_SCI(sci)) { + return enable && FIELD_EX16(sci->Xsr, SSR, TDRE); + } else { + return enable && FIELD_EX16(sci->Xsr, FSR, TDFE); + } +} + +static void sci_irq(RSCIState *sci, int req) +{ + int br; + int irq; + int rie; + + switch (req) { + case ERI: + rie =3D FIELD_EX16(sci->scr, SCR, RIE); + if (IS_SCI(sci)) { + irq =3D rie && (FIELD_EX16(sci->Xsr, SSR, ERR) !=3D 0); + } else { + irq =3D (rie || FIELD_EX16(sci->scr, SCR, REIE)) && + FIELD_EX16(sci->Xsr, FSR, ER); + } + qemu_set_irq(sci->irq[ERI], irq); + break; + case RXI: + if (IS_SCIA(sci)) { + if (sci_is_rxi(sci)) { + qemu_irq_pulse(sci->irq[RXI]); + } + } else { + qemu_set_irq(sci->irq[RXI], sci_is_rxi(sci)); + } + break; + case TXI: + if (IS_SCIA(sci)) { + if (sci_is_txi(sci)) { + qemu_irq_pulse(sci->irq[TXI]); + } + } else { + qemu_set_irq(sci->irq[TXI], sci_is_txi(sci)); + } + break; + case BRI: /* TEI */ + if (IS_SCI(sci)) { + qemu_set_irq(sci->irq[TEI], + FIELD_EX16(sci->Xsr, SSR, TEND) && + FIELD_EX16(sci->scr, SCR, TEIE)); + } else { + rie =3D FIELD_EX16(sci->scr, SCR, RIE); + br =3D (rie || FIELD_EX16(sci->scr, SCR, REIE)) && + FIELD_EX16(sci->Xsr, FSR, BRK); + qemu_set_irq(sci->irq[BRI], br); + } + break; + } +} + +static int can_receive(void *opaque) +{ + RSCIState *sci =3D RSCI(opaque); + int fifo_free =3D 0; + if (FIELD_EX16(sci->scr, SCR, RE)) { + /* Receiver enabled */ + fifo_free =3D fifo8_num_free(&sci->rxfifo); + if (IS_SCIF(sci) && fifo_free =3D=3D 0) { + /* FIFO overrun */ + sci->lsr =3D FIELD_DP16(sci->lsr, LSR, ORER, 1); + sci_irq(sci, ERI); + } + } + return fifo_free; +} + +static void sci_receive(void *opaque, const uint8_t *buf, int size) +{ + RSCIState *sci =3D RSCI(opaque); + int rtrg; + + fifo8_push_all(&sci->rxfifo, buf, size); + if (sci->event[RXNEXT].time =3D=3D 0) { + if (IS_SCI(sci)) { + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, RDRF, 1); + update_event_time(sci, RXNEXT, sci->trtime); + } else { + rtrg =3D sci_rtrg[FIELD_EX16(sci->fcr, FCR, RTRG)]; + if (fifo8_num_used(&sci->rxfifo) >=3D rtrg) { + sci->Xsr =3D FIELD_DP16(sci->Xsr, FSR, RDF, 1); + } else { + update_event_time(sci, RXTOUT, 15 * sci->etu); + } + } + sci_irq(sci, RXI); + } +} + +static void sci_send_byte(RSCIState *sci) +{ + if (IS_SCI(sci)) { + if (qemu_chr_fe_backend_connected(&sci->chr)) { + qemu_chr_fe_write_all(&sci->chr, &sci->tdr, 1); + } + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, TEND, 0); + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, TDRE, 1); + } +} + +static int transmit_byte(RSCIState *sci) +{ + int64_t elapsed; + int byte =3D 0; + if (sci->tx_start_time > 0) { + elapsed =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - sci->tx_start_= time; + byte =3D elapsed / sci->trtime; + if (byte > sci->tdcnt) { + byte =3D sci->tdcnt; + } + } + return byte; +} + +static int64_t sci_rx_timeout(RSCIState *sci) +{ + if (IS_SCIF(sci)) { + sci->Xsr =3D FIELD_DP16(sci->Xsr, FSR, DR, 1); + sci_irq(sci, RXI); + } + return 0; +} + +static int64_t sci_rx_next(RSCIState *sci) +{ + int64_t next_event =3D 0; + if (IS_SCI(sci) && !fifo8_is_empty(&sci->rxfifo)) { + if (FIELD_EX16(sci->Xsr, SSR, RDRF)) { + /* Receiver overrun */ + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, ORER, 1); + sci_irq(sci, ERI); + } else { + /* Trigger next event */ + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, RDRF, 1); + sci_irq(sci, RXI); + next_event =3D sci->trtime; + } + } + return next_event; +} + +static int64_t sci_tx_empty(RSCIState *sci) +{ + int64_t ret =3D 0; + if (IS_SCI(sci)) { + if (!FIELD_EX16(sci->Xsr, SSR, TDRE)) { + sci_send_byte(sci); + ret =3D sci->trtime; + sci_irq(sci, TXI); + } else { + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, TEND, 1); + sci_irq(sci, TEI); + } + } else { + sci->tdcnt -=3D transmit_byte(sci); + sci->Xsr =3D FIELD_DP16(sci->Xsr, FSR, TDFE, 1); + sci_irq(sci, TXI); + } + return ret; +} + +static int64_t sci_tx_end(RSCIState *sci) +{ + if (IS_SCIF(sci)) { + sci->tdcnt =3D 0; + sci->Xsr =3D FIELD_DP16(sci->Xsr, FSR, TEND, 1); + sci_irq(sci, TEI); + } + return 0; +} + +static void sci_timer_event(void *opaque) +{ + RSCIState *sci =3D RSCI(opaque); + int64_t now, next, t; + int i; + + now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + next =3D INT64_MAX; + for (i =3D 0; i < NR_SCI_EVENT; i++) { + if (sci->event[i].time > 0 && sci->event[i].time <=3D now) { + t =3D sci->event[i].handler(sci); + sci->event[i].time =3D (t > 0) ? now + t : 0; + } + if (sci->event[i].time > 0) { + next =3D MIN(next, sci->event[i].time); + } + } + if (next < INT64_MAX) { + timer_mod(sci->event_timer, next); + } else { + timer_del(sci->event_timer); + } +} + +static void update_trtime(RSCIState *sci) +{ + int divrate; + if (IS_SCIA(sci)) { + divrate =3D 16 * (2 - FIELD_EX8(sci->semr, SEMR, ABCS)); + } else { + divrate =3D 32; + } + + /* x bit transmit time (divrate * brr) / base freq */ + sci->etu =3D divrate * 1 << (2 * FIELD_EX16(sci->smr, SMR, CKS)); + sci->etu *=3D sci->brr + 1; + sci->etu *=3D NANOSECONDS_PER_SECOND; + sci->etu /=3D sci->input_freq; + + /* char per bits */ + sci->trtime =3D 8 - FIELD_EX16(sci->smr, SMR, CHR); + sci->trtime +=3D FIELD_EX16(sci->smr, SMR, PE); + sci->trtime +=3D FIELD_EX16(sci->smr, SMR, STOP) + 1 + 1; + sci->trtime *=3D sci->etu; +} + +#define IS_TR_ENABLED(scr) \ + (FIELD_EX16(scr, SCR, TE) || FIELD_EX16(scr, SCR, RE)) + +#define SCI_IS_NOT_SUPPORTED(sci, name) \ + if (sci->feature =3D=3D SCI_FEAT_SCI) { = \ + qemu_log_mask(LOG_GUEST_ERROR, \ + "reneas_sci: " #name " is not supported.\n"); \ + } + +static void sci_write(void *opaque, hwaddr addr, uint64_t val, unsigned si= ze) +{ + RSCIState *sci =3D RSCI(opaque); + int txtrg; + int rxtrg; + uint8_t txd; + uint16_t ssr_mask; + bool tx_start =3D false; + + if (IS_SCI(sci)) { + txtrg =3D 1; + } else { + txtrg =3D 1 << (3 - FIELD_EX16(sci->fcr, FCR, TTRG)); + } + switch (sci->regsize) { + case 8: + addr <<=3D 1; break; + case 32: + addr >>=3D 1; break; + } + switch (addr) { + case A_SMR: + if (IS_SCIA(sci) && IS_TR_ENABLED(sci->scr)) { + qemu_log_mask(LOG_GUEST_ERROR, + "reneas_sci: SMR write protected.\n"); + break; + } + sci->smr =3D val; + update_trtime(sci); + break; + case A_BRR: + if (IS_SCIA(sci) && IS_TR_ENABLED(sci->scr)) { + qemu_log_mask(LOG_GUEST_ERROR, + "reneas_sci: BRR write protected.\n"); + break; + } + sci->brr =3D val; + update_trtime(sci); + break; + case A_SCR: + sci->scr =3D val; + if (FIELD_EX16(sci->scr, SCR, TE)) { + /* Transmitter enable */ + if (IS_SCI(sci)) { + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, TDRE, 1); + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, TEND, 1); + } else { + sci->Xsr =3D FIELD_DP16(sci->Xsr, FSR, TEND, 1); + sci->Xsr =3D FIELD_DP16(sci->Xsr, FSR, TDFE, 1); + sci->tx_start_time =3D 0; + } + sci_irq(sci, TXI); + sci_irq(sci, TEI); + } else { + /* Transmitter disable */ + update_event_time(sci, TXEND, 0); + update_event_time(sci, TXEMPTY, 0); + } + break; + case A_TDR: + if (IS_SCI(sci)) { + sci->tdr =3D val; + if (IS_SCIA(sci)) { + if (FIELD_EX16(sci->Xsr, SSR, TEND)) { + update_event_time(sci, TXEMPTY, sci->trtime); + sci_send_byte(sci); + } else { + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, TDRE, 0); + } + sci_irq(sci, TXI); + sci_irq(sci, TEI); + } + } else { + if (sci->tx_start_time > 0) { + sci->tdcnt -=3D transmit_byte(sci); + } else { + sci->tx_start_time =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUA= L); + } + if (sci->tdcnt >=3D SCIF_FIFO_DEPTH) { + break; + } + txd =3D val; + if (qemu_chr_fe_backend_connected(&sci->chr)) { + qemu_chr_fe_write_all(&sci->chr, &txd, 1); + } + if (FIELD_EX16(sci->fcr, FCR, LOOP) && can_receive(sci) > 0) { + /* Loopback mode */ + sci_receive(sci, &txd, 1); + } + sci->tdcnt++; + sci->Xsr =3D FIELD_DP16(sci->Xsr, FSR, TEND, 0); + update_event_time(sci, TXEND, sci->tdcnt); + if (sci->tdcnt > txtrg) { + sci->Xsr =3D FIELD_DP16(sci->Xsr, FSR, TDFE, 0); + update_event_time(sci, TXEMPTY, sci->tdcnt - txtrg + 1); + sci_irq(sci, TXI); + } + } + break; + case A_FSR: /* A_SSR */ + if (IS_SCI(sci)) { + /* Mask for read only bits */ + ssr_mask =3D IS_SCIA(sci) ? 0xc7 : 0x07; + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, MPBT, + FIELD_EX16(val, SSR, MPBT)); + sci->Xsr &=3D (val | ssr_mask); + /* Clear ERI */ + sci_irq(sci, ERI); + if (sci->feature =3D=3D SCI_FEAT_SCI) { + tx_start =3D FIELD_EX16(sci->read_Xsr, SSR, TDRE) && + !FIELD_EX16(sci->Xsr, SSR, TDRE) && + (FIELD_EX16(sci->Xsr, SSR, ERR) =3D=3D 0); + if (tx_start) { + sci_send_byte(sci); + update_event_time(sci, TXEMPTY, sci->trtime); + sci_irq(sci, TXI); + } + } + } else { + rxtrg =3D sci_rtrg[FIELD_EX16(sci->fcr, FCR, RTRG)]; + ssr_mask =3D ~(sci->read_Xsr & 0xf3); + sci->tdcnt -=3D transmit_byte(sci); + if (sci->tdcnt < txtrg) { + ssr_mask =3D FIELD_DP16(ssr_mask, FSR, TDFE, 1); + } + if (fifo8_num_used(&sci->rxfifo) >=3D rxtrg) { + ssr_mask =3D FIELD_DP16(ssr_mask, FSR, RDF, 1); + } + sci->Xsr &=3D (val | ssr_mask); + sci_irq(sci, ERI); + sci_irq(sci, RXI); + sci_irq(sci, TXI); + } + break; + case A_RDR: + qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: RDR is read only.\n"); + break; + case A_FCR: /* A_SCMR / A_SPTR */ + if (IS_SCI(sci)) { + if (sci->feature =3D=3D SCI_FEAT_SCI) { + sci->sptr =3D val; + } else { + sci->scmr =3D val; + } + } else { + sci->fcr =3D val; + if (FIELD_EX16(sci->fcr, FCR, RFRST)) { + fifo8_reset(&sci->rxfifo); + update_event_time(sci, RXTOUT, 0); + update_event_time(sci, RXNEXT, 0); + } + if (FIELD_EX16(sci->fcr, FCR, TFRST)) { + sci->tdcnt =3D 0; + } + } + break; + case A_FDR: /* A_SEMR */ + if (IS_SCI(sci)) { + SCI_IS_NOT_SUPPORTED(sci, SEMR); + sci->semr =3D val; + } else { + qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: FDR is read only.\= n"); + } + break; + case A_SPTR: + if (IS_SCI(sci)) { + goto error; + } else { + sci->sptr =3D val; + } + break; + case A_LSR: + if (IS_SCI(sci)) { + goto error; + } else { + if (FIELD_EX16(sci->read_lsr, LSR, ORER) !=3D 1) { + val =3D FIELD_DP16(val, LSR, ORER, 1); + } + sci->lsr &=3D val; + sci_irq(sci, ERI); + } + break; + default: + error: + qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX + " not implemented\n", addr); + } +} + +static uint64_t sci_read(void *opaque, hwaddr addr, unsigned size) +{ + RSCIState *sci =3D RSCI(opaque); + uint64_t ret; + + switch (sci->regsize) { + case 8: + addr <<=3D 1; break; + case 32: + addr >>=3D 1; break; + } + + switch (addr) { + case A_SMR: + return sci->smr; + case A_BRR: + return sci->brr; + case A_SCR: + return sci->scr; + case A_TDR: + if (IS_SCI(sci)) { + return sci->tdr; + } else { + qemu_log_mask(LOG_GUEST_ERROR, "reneas_sci: TDR is write only.= \n"); + return UINT64_MAX; + } + case A_FSR: /* A_SSR */ + sci->read_Xsr =3D sci->Xsr; + return sci->Xsr; + case A_RDR: + ret =3D fifo8_pop(&sci->rxfifo); + if (IS_SCIA(sci)) { + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, RDRF, 0); + } + return ret; + case A_FCR: /* A_SCMR / A_SPTR */ + if (IS_SCI(sci)) { + if (IS_SCIA(sci)) { + return sci->scmr; + } else { + return sci->sptr; + } + } else { + return sci->fcr & 0x7ff; + } + case A_FDR: /* A_SEMR */ + if (IS_SCI(sci)) { + SCI_IS_NOT_SUPPORTED(sci, SEMR); + return sci->semr; + } else { + ret =3D 0; + ret =3D FIELD_DP16(ret, FDR, Rn, fifo8_num_used(&sci->rxfifo)); + ret =3D FIELD_DP16(ret, FDR, Tn, sci->tdcnt - transmit_byte(sc= i)); + return ret; + } + case A_SPTR: + if (IS_SCI(sci)) { + goto error; + } else { + return sci->sptr; + } + case A_LSR: + if (IS_SCI(sci)) { + goto error; + } else { + sci->read_lsr =3D sci->lsr; + return sci->lsr; + } + default: + error: + qemu_log_mask(LOG_UNIMP, "renesas_sci: Register 0x%" HWADDR_PRIX + " not implemented.\n", addr); + } + return UINT64_MAX; +} + +static const MemoryRegionOps sci_ops =3D { + .write =3D sci_write, + .read =3D sci_read, + .endianness =3D DEVICE_NATIVE_ENDIAN, + .impl =3D { + .max_access_size =3D 4, + }, +}; + +static void sci_register_init(RSCIState *sci) +{ + int i; + sci->smr =3D sci->scr =3D 0x00; + sci->brr =3D 0xff; + if (IS_SCI(sci)) { + sci->tdr =3D 0xff; + sci->Xsr =3D 0x84; + sci->scmr =3D 0x00; + sci->semr =3D 0x00; + sci->sptr =3D 0x00; + } else { + sci->Xsr =3D 0x0060; + sci->fcr =3D 0x0000; + sci->sptr =3D 0x0000; + sci->lsr =3D 0x0000; + } + update_trtime(sci); + for (i =3D 0; i < NR_SCI_EVENT; i++) { + sci->event[i].time =3D 0; + } +} + +static void sci_event(void *opaque, QEMUChrEvent event) +{ + RSCIState *sci =3D RSCI(opaque); + if (event =3D=3D CHR_EVENT_BREAK) { + if (IS_SCI(sci)) { + sci->Xsr =3D FIELD_DP16(sci->Xsr, SSR, FER, 1); + } else { + sci->Xsr =3D FIELD_DP16(sci->Xsr, FSR, BRK, 1); + } + sci_irq(sci, ERI); + } +} + +static void rsci_realize(DeviceState *dev, Error **errp) +{ + SysBusDevice *d =3D SYS_BUS_DEVICE(dev); + RSCIState *sci =3D RSCI(dev); + int i; + int size; + + if (sci->input_freq =3D=3D 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_sci: input-freq property must be set."); + return; + } + if (sci->regsize !=3D 8 && sci->regsize !=3D 16 && sci->regsize !=3D 3= 2) { + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_sci: Invalid regsize."); + return; + } + + size =3D IS_SCI(sci) ? 16 : 20; + switch (sci->regsize) { + case 8: + size >>=3D 1; + break; + case 32: + size <<=3D 1; + break; + } + memory_region_init_io(&sci->memory, OBJECT(sci), &sci_ops, + sci, "renesas-sci", size); + sysbus_init_mmio(d, &sci->memory); + memory_region_init_alias(&sci->memory_p4, NULL, "renesas-sci-p4", + &sci->memory, 0, size); + sysbus_init_mmio(d, &sci->memory_p4); + memory_region_init_alias(&sci->memory_a7, NULL, "renesas-sci-a7", + &sci->memory, 0, size); + sysbus_init_mmio(d, &sci->memory_a7); + + for (i =3D 0; i < SCI_NR_IRQ; i++) { + sysbus_init_irq(d, &sci->irq[i]); + } + sci->event_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, sci_timer_event,= sci); + + qemu_chr_fe_set_handlers(&sci->chr, can_receive, sci_receive, + sci_event, NULL, sci, NULL, true); + fifo8_create(&sci->rxfifo, SCIF_FIFO_DEPTH); + sci_register_init(sci); +} + +static const VMStateDescription vmstate_rsci =3D { + .name =3D "renesas-sci", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property rsci_properties[] =3D { + DEFINE_PROP_UINT64("input-freq", RSCIState, input_freq, 0), + DEFINE_PROP_INT32("register-size", RSCIState, regsize, 8), + DEFINE_PROP_INT32("feature", RSCIState, feature, 0), + DEFINE_PROP_CHR("chardev", RSCIState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rsci_init(Object *obj) +{ + RSCIState *sci =3D RSCI(obj); + sci->event[RXTOUT].handler =3D sci_rx_timeout; + sci->event[RXNEXT].handler =3D sci_rx_next; + sci->event[TXEMPTY].handler =3D sci_tx_empty; + sci->event[TXEND].handler =3D sci_tx_end; +} +static void rsci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->realize =3D rsci_realize; + dc->vmsd =3D &vmstate_rsci; + device_class_set_props(dc, rsci_properties); +} + +static const TypeInfo rsci_info =3D { + .name =3D TYPE_RENESAS_SCI, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RSCIState), + .instance_init =3D rsci_init, + .class_init =3D rsci_class_init, +}; + +static void rsci_register_types(void) +{ + type_register_static(&rsci_info); +} + +type_init(rsci_register_types) diff --git a/hw/char/Kconfig b/hw/char/Kconfig index 40e7a8b8bb..874627520c 100644 --- a/hw/char/Kconfig +++ b/hw/char/Kconfig @@ -46,3 +46,6 @@ config SCLPCONSOLE =20 config TERMINAL3270 bool + +config RENESAS_SCI + bool diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs index 9e9a6c1aff..b07ce63c6f 100644 --- a/hw/char/Makefile.objs +++ b/hw/char/Makefile.objs @@ -16,7 +16,6 @@ common-obj-$(CONFIG_CADENCE) +=3D cadence_uart.o common-obj-$(CONFIG_EXYNOS4) +=3D exynos4210_uart.o common-obj-$(CONFIG_COLDFIRE) +=3D mcf_uart.o common-obj-$(CONFIG_OMAP) +=3D omap_uart.o -common-obj-$(CONFIG_SH4) +=3D sh_serial.o common-obj-$(CONFIG_DIGIC) +=3D digic-uart.o common-obj-$(CONFIG_STM32F2XX_USART) +=3D stm32f2xx_usart.o common-obj-$(CONFIG_RASPI) +=3D bcm2835_aux.o @@ -31,6 +30,8 @@ common-obj-$(CONFIG_LM32) +=3D lm32_uart.o common-obj-$(CONFIG_MILKYMIST) +=3D milkymist-uart.o common-obj-$(CONFIG_SCLPCONSOLE) +=3D sclpconsole.o sclpconsole-lm.o =20 +common-obj-$(CONFIG_RENESAS_SCI) +=3D renesas_sci.o + obj-$(CONFIG_VIRTIO) +=3D virtio-serial-bus.o obj-$(CONFIG_PSERIES) +=3D spapr_vty.o obj-$(CONFIG_TERMINAL3270) +=3D terminal3270.o --=20 2.20.1 From nobody Fri May 17 04:49:49 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 ARC-Seal: i=1; a=rsa-sha256; t=1590942644; cv=none; d=zohomail.com; s=zohoarc; b=OGZI2REEcX0hc3ng+m982XHXW0IxUqtcLFvfBY8ga0p32y5WXQUUdCJpGlf3BuWo0q5qbFYsSlUmDXgf/Pv/v1kzafHZAfaEz4BtYFeOlHYbAGrRRvQNGjOJUJh7MICtGnAtzE6ox9qo6GAMwYWbKMe2dei6e+t2wOlaH6hjd+0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1590942644; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=6czAk2dpwkdatZgIwObD9kUaby4EZuYj0qhKy1vMDTU=; b=C9mCbzPeuoyq7EpEzx1kg9yV0sep4eCLQiTwsfkiAY8s+TGqtc2Nj55QVvlJvuiEosd/emrPhD9HfJsixTmjzOpQi5wfHZlt8AdOVUMjlsIUF+bNiqd7HkkpT+9QpOpH9w8pqE3WV5neYyNqGbzc/aES3noF9X5pLyGByqfY6Qk= 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 15909426441121010.7469425511721; Sun, 31 May 2020 09:30:44 -0700 (PDT) Received: from localhost ([::1]:36116 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQrC-00052F-OF for importer@patchew.org; Sun, 31 May 2020 12:30:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53686) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jfQlM-0004E4-P4 for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:40 -0400 Received: from mail02.asahi-net.or.jp ([202.224.55.14]:58732) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQlJ-0004K5-V1 for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:40 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail02.asahi-net.or.jp (Postfix) with ESMTPA id 17590EB8BA; Mon, 1 Jun 2020 01:24:34 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by sakura.ysato.name (Postfix) with ESMTPSA id A25511C0DB3; Mon, 1 Jun 2020 01:24:33 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 05/10] hw/rx: RX MCU and target Date: Mon, 1 Jun 2020 01:24:22 +0900 Message-Id: <20200531162427.57410-6-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200531162427.57410-1-ysato@users.sourceforge.jp> References: <20200531162427.57410-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 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: softfail client-ip=202.224.55.14; envelope-from=ysato@users.sourceforge.jp; helo=mail02.asahi-net.or.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/31 12:24:33 X-ACL-Warn: Detected OS = ??? 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_DNSWL_LOW=-0.7, SPF_SOFTFAIL=0.665, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" rx62n - RX62N MCU. rx-virt - RX QEMU virtual target. This has the same specifications as the gdb simulator. Signed-off-by: Yoshinori Sato --- include/hw/rx/rx.h | 7 ++ include/hw/rx/rx62n.h | 91 ++++++++++++++++ hw/rx/rx-virt.c | 143 +++++++++++++++++++++++++ hw/rx/rx62n.c | 240 ++++++++++++++++++++++++++++++++++++++++++ hw/rx/Kconfig | 13 +++ hw/rx/Makefile.objs | 2 + 6 files changed, 496 insertions(+) create mode 100644 include/hw/rx/rx.h create mode 100644 include/hw/rx/rx62n.h create mode 100644 hw/rx/rx-virt.c create mode 100644 hw/rx/rx62n.c create mode 100644 hw/rx/Kconfig create mode 100644 hw/rx/Makefile.objs diff --git a/include/hw/rx/rx.h b/include/hw/rx/rx.h new file mode 100644 index 0000000000..ff5924b81f --- /dev/null +++ b/include/hw/rx/rx.h @@ -0,0 +1,7 @@ +#ifndef QEMU_RX_H +#define QEMU_RX_H +/* Definitions for RX board emulation. */ + +#include "target/rx/cpu-qom.h" + +#endif diff --git a/include/hw/rx/rx62n.h b/include/hw/rx/rx62n.h new file mode 100644 index 0000000000..11176eadf3 --- /dev/null +++ b/include/hw/rx/rx62n.h @@ -0,0 +1,91 @@ +/* + * RX62N MCU Object + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#ifndef HW_RX_RX62N_H +#define HW_RX_RX62N_H + +#include "hw/sysbus.h" +#include "hw/intc/rx_icu.h" +#include "hw/timer/renesas_8timer.h" +#include "hw/timer/renesas_timer.h" +#include "hw/char/renesas_sci.h" +#include "target/rx/cpu.h" +#include "qemu/units.h" + +#define TYPE_RX62N "rx62n" +#define RX62N(obj) OBJECT_CHECK(RX62NState, (obj), TYPE_RX62N) + +#define RX62N_NR_TMR 2 +#define RX62N_NR_CMT 2 +#define RX62N_NR_SCI 6 + +typedef struct RX62NState { + SysBusDevice parent_obj; + + RXCPU cpu; + RXICUState icu; + RTMRState tmr[RX62N_NR_TMR]; + RTIMERState cmt[RX62N_NR_CMT]; + RSCIState sci[RX62N_NR_SCI]; + + MemoryRegion *sysmem; + bool kernel; + + MemoryRegion iram; + MemoryRegion iomem1; + MemoryRegion d_flash; + MemoryRegion iomem2; + MemoryRegion iomem3; + MemoryRegion c_flash; + qemu_irq irq[NR_IRQS]; +} RX62NState; + +/* + * RX62N Peripheral Address + * See users manual section 5 + */ +#define RX62N_ICUBASE 0x00087000 +#define RX62N_TMRBASE 0x00088200 +#define RX62N_CMTBASE 0x00088000 +#define RX62N_SCIBASE 0x00088240 + +/* + * RX62N Peripheral IRQ + * See users manual section 11 + */ +#define RX62N_TMR_IRQBASE 174 +#define RX62N_CMT_IRQBASE 28 +#define RX62N_SCI_IRQBASE 214 + +/* + * RX62N Internal Memory + * It is the value of R5F562N8. + * Please change the size for R5F562N7. + */ +#define RX62N_IRAM_BASE 0x00000000 +#define RX62N_IRAM_SIZE (96 * KiB) +#define RX62N_DFLASH_BASE 0x00100000 +#define RX62N_DFLASH_SIZE (32 * KiB) +#define RX62N_CFLASH_BASE 0xfff80000 +#define RX62N_CFLASH_SIZE (512 * KiB) + +#define RX62N_PCLK (48 * 1000 * 1000) +#endif diff --git a/hw/rx/rx-virt.c b/hw/rx/rx-virt.c new file mode 100644 index 0000000000..3168a85b83 --- /dev/null +++ b/hw/rx/rx-virt.c @@ -0,0 +1,143 @@ +/* + * RX QEMU virtual platform + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 f= or + * 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 "qapi/error.h" +#include "qemu-common.h" +#include "cpu.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/loader.h" +#include "hw/rx/rx62n.h" +#include "sysemu/sysemu.h" +#include "sysemu/qtest.h" +#include "sysemu/device_tree.h" +#include "hw/boards.h" + +/* Same address of GDB integrated simulator */ +#define SDRAM_BASE 0x01000000 + +static void rx_load_image(RXCPU *cpu, const char *filename, + uint32_t start, uint32_t size) +{ + static uint32_t extable[32]; + long kernel_size; + int i; + + kernel_size =3D load_image_targphys(filename, start, size); + if (kernel_size < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", filename); + exit(1); + } + cpu->env.pc =3D start; + + /* setup exception trap trampoline */ + /* linux kernel only works little-endian mode */ + for (i =3D 0; i < ARRAY_SIZE(extable); i++) { + extable[i] =3D cpu_to_le32(0x10 + i * 4); + } + rom_add_blob_fixed("extable", extable, sizeof(extable), 0xffffff80); +} + +static void rxvirt_init(MachineState *machine) +{ + RX62NState *s =3D g_new(RX62NState, 1); + MemoryRegion *sysmem =3D get_system_memory(); + MemoryRegion *sdram =3D g_new(MemoryRegion, 1); + const char *kernel_filename =3D machine->kernel_filename; + const char *dtb_filename =3D machine->dtb; + void *dtb =3D NULL; + int dtb_size; + ram_addr_t kernel_offset; + ram_addr_t dtb_offset; + MachineClass *mc =3D MACHINE_GET_CLASS(machine); + + if (machine->ram_size < mc->default_ram_size) { + error_report("Invalid RAM size, should be more than %" PRIi64 " By= tes", + mc->default_ram_size); + } + + /* Allocate memory space */ + memory_region_init_ram(sdram, NULL, "rx-virt.sdram", machine->ram_size, + &error_fatal); + memory_region_add_subregion(sysmem, SDRAM_BASE, sdram); + + /* Initialize MCU */ + object_initialize_child(OBJECT(machine), "mcu", s, + sizeof(RX62NState), TYPE_RX62N, + &error_fatal, NULL); + object_property_set_link(OBJECT(s), OBJECT(sysmem), + "memory", &error_abort); + object_property_set_bool(OBJECT(s), kernel_filename !=3D NULL, + "load-kernel", &error_abort); + object_property_set_bool(OBJECT(s), true, "realized", &error_abort); + + /* Load kernel and dtb */ + if (kernel_filename) { + /* + * The kernel image is loaded into + * the latter half of the SDRAM space. + */ + kernel_offset =3D machine->ram_size / 2; + rx_load_image(RXCPU(first_cpu), kernel_filename, + SDRAM_BASE + kernel_offset, kernel_offset); + if (dtb_filename) { + dtb =3D load_device_tree(dtb_filename, &dtb_size); + if (dtb =3D=3D NULL) { + error_report("Couldn't open dtb file %s", dtb_filename); + exit(1); + } + if (machine->kernel_cmdline && + qemu_fdt_setprop_string(dtb, "/chosen", "bootargs", + machine->kernel_cmdline) < 0) { + error_report("Couldn't set /chosen/bootargs"); + exit(1); + } + /* DTB is located at the end of SDRAM space. */ + dtb_offset =3D machine->ram_size - dtb_size; + rom_add_blob_fixed("dtb", dtb, dtb_size, + SDRAM_BASE + dtb_offset); + /* Set dtb address to R1 */ + RXCPU(first_cpu)->env.regs[1] =3D SDRAM_BASE + dtb_offset; + } + } +} + +static void rxvirt_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc =3D MACHINE_CLASS(oc); + + mc->desc =3D "RX QEMU Virtual Target"; + mc->init =3D rxvirt_init; + mc->is_default =3D 1; + mc->default_cpu_type =3D TYPE_RX62N_CPU; + mc->default_ram_size =3D 16 * MiB; +} + +static const TypeInfo rxvirt_type =3D { + .name =3D MACHINE_TYPE_NAME("rx-virt"), + .parent =3D TYPE_MACHINE, + .class_init =3D rxvirt_class_init, +}; + +static void rxvirt_machine_init(void) +{ + type_register_static(&rxvirt_type); +} + +type_init(rxvirt_machine_init) diff --git a/hw/rx/rx62n.c b/hw/rx/rx62n.c new file mode 100644 index 0000000000..effd6d4f12 --- /dev/null +++ b/hw/rx/rx62n.c @@ -0,0 +1,240 @@ +/* + * RX62N Microcontroller + * + * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware + * (Rev.1.40 R01UH0033EJ0140) + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 f= or + * 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 "qapi/error.h" +#include "hw/hw.h" +#include "hw/rx/rx62n.h" +#include "hw/loader.h" +#include "hw/sysbus.h" +#include "hw/qdev-properties.h" +#include "sysemu/sysemu.h" +#include "cpu.h" + +/* + * IRQ -> IPR mapping table + * 0x00 - 0x91: IPR no (IPR00 to IPR91) + * 0xff: IPR not assigned + * See "11.3.1 Interrupt Vector Table" in hardware manual. + */ +static const int ipr_table[NR_IRQS] =3D { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 15 */ + 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x02, + 0xff, 0xff, 0xff, 0x03, 0x04, 0x05, 0x06, 0x07, /* 31 */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x14, 0x14, /* 47 */ + 0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1e, 0x1f, /* 63 */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 79 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x3a, 0x3b, 0x3c, 0xff, 0xff, 0xff, /* 95 */ + 0x40, 0xff, 0x44, 0x45, 0xff, 0xff, 0x48, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 111 */ + 0xff, 0xff, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52, + 0x52, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, /* 127 */ + 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59, + 0x59, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, /* 143 */ + 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, + 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62, /* 159 */ + 0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66, + 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, /* 175 */ + 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, + 0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 191 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x71, + 0x72, 0x73, 0x74, 0x75, 0xff, 0xff, 0xff, 0xff, /* 207 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, + 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, /* 223 */ + 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0xff, 0xff, + 0xff, 0xff, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, /* 239 */ + 0x86, 0x86, 0xff, 0xff, 0xff, 0xff, 0x88, 0x89, + 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, /* 255 */ +}; + +/* + * Level triggerd IRQ list + * Not listed IRQ is Edge trigger. + * See "11.3.1 Interrupt Vector Table" in hardware manual. + */ +static const uint32_t levelirq[] =3D { + 16, 21, 32, 44, 47, 48, 51, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 90, 91, 170, 171, 172, 173, 214, + 217, 218, 221, 222, 225, 226, 229, 234, 237, 238, + 241, 246, 249, 250, 253, +}; + +static void register_icu(RX62NState *s) +{ + int i; + SysBusDevice *icu; + + object_initialize_child(OBJECT(s), "icu", &s->icu, sizeof(RXICUState), + TYPE_RXICU, &error_abort, NULL); + + icu =3D SYS_BUS_DEVICE(&s->icu); + sysbus_mmio_map(SYS_BUS_DEVICE(icu), 0, RX62N_ICUBASE); + qdev_prop_set_uint32(DEVICE(icu), "len-ipr-map", NR_IRQS); + for (i =3D 0; i < NR_IRQS; i++) { + char propname[32]; + snprintf(propname, sizeof(propname), "ipr-map[%d]", i); + qdev_prop_set_uint32(DEVICE(icu), propname, ipr_table[i]); + } + qdev_prop_set_uint32(DEVICE(icu), "len-trigger-level", + ARRAY_SIZE(levelirq)); + for (i =3D 0; i < ARRAY_SIZE(levelirq); i++) { + char propname[32]; + snprintf(propname, sizeof(propname), "trigger-level[%d]", i); + qdev_prop_set_uint32(DEVICE(icu), propname, levelirq[i]); + } + + for (i =3D 0; i < NR_IRQS; i++) { + s->irq[i] =3D qdev_get_gpio_in(DEVICE(icu), i); + } + + qdev_init_nofail(DEVICE(icu)); + sysbus_connect_irq(icu, 0, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_IR= Q)); + sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FI= R)); + sysbus_connect_irq(icu, 2, s->irq[SWI]); + +} + +static void register_tmr(RX62NState *s, int unit) +{ + SysBusDevice *tmr; + int i, irqbase; + + object_initialize_child(OBJECT(s), "tmr[*]", &s->tmr[unit], + sizeof(RTMRState), TYPE_RENESAS_8TMR, + &error_abort, NULL); + + tmr =3D SYS_BUS_DEVICE(&s->tmr[unit]); + qdev_prop_set_uint64(DEVICE(tmr), "input-freq", RX62N_PCLK); + + qdev_init_nofail(DEVICE(tmr)); + sysbus_mmio_map(tmr, 0, RX62N_TMRBASE + unit * 0x10); + irqbase =3D RX62N_TMR_IRQBASE + TMR_NR_IRQ * unit; + for (i =3D 0; i < TMR_NR_IRQ; i++) { + sysbus_connect_irq(tmr, i, s->irq[irqbase + i]); + } +} + +static void register_cmt(RX62NState *s, int unit) +{ + SysBusDevice *cmt; + int i, irqbase; + + object_initialize_child(OBJECT(s), "cmt[*]", &s->cmt[unit], + sizeof(RTIMERState), TYPE_RENESAS_TIMER, + &error_abort, NULL); + + cmt =3D SYS_BUS_DEVICE(&s->cmt[unit]); + qdev_prop_set_uint64(DEVICE(cmt), "input-freq", RX62N_PCLK); + qdev_prop_set_int32(DEVICE(cmt), "feature", RTIMER_FEAT_CMT); + qdev_init_nofail(DEVICE(cmt)); + sysbus_mmio_map(cmt, 0, RX62N_CMTBASE + unit * 0x10); + irqbase =3D RX62N_CMT_IRQBASE + TIMER_CH_CMT * unit; + for (i =3D 0; i < TIMER_CH_CMT; i++) { + sysbus_connect_irq(cmt, i, s->irq[irqbase + i]); + } +} + +static void register_sci(RX62NState *s, int unit) +{ + SysBusDevice *sci; + int i, irqbase; + + object_initialize_child(OBJECT(s), "sci[*]", &s->sci[unit], + sizeof(RSCIState), TYPE_RENESAS_SCI, + &error_abort, NULL); + sci =3D SYS_BUS_DEVICE(&s->sci[unit]); + + qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit)); + qdev_prop_set_uint64(DEVICE(sci), "input-freq", RX62N_PCLK); + qdev_prop_set_int32(DEVICE(sci), "feature", SCI_FEAT_SCIA); + qdev_prop_set_int32(DEVICE(sci), "register-size", 8); + qdev_init_nofail(DEVICE(sci)); + sysbus_mmio_map(sci, 0, RX62N_SCIBASE + unit * 0x08); + irqbase =3D RX62N_SCI_IRQBASE + SCI_NR_IRQ * unit; + for (i =3D 0; i < SCI_NR_IRQ; i++) { + sysbus_connect_irq(sci, i, s->irq[irqbase + i]); + } +} + +static void rx62n_realize(DeviceState *dev, Error **errp) +{ + RX62NState *s =3D RX62N(dev); + + memory_region_init_ram(&s->iram, NULL, "iram", RX62N_IRAM_SIZE, errp); + memory_region_add_subregion(s->sysmem, RX62N_IRAM_BASE, &s->iram); + memory_region_init_rom(&s->d_flash, NULL, "dataflash", + RX62N_DFLASH_SIZE, errp); + memory_region_add_subregion(s->sysmem, RX62N_DFLASH_BASE, &s->d_flash); + memory_region_init_rom(&s->c_flash, NULL, "codeflash", + RX62N_CFLASH_SIZE, errp); + memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, &s->c_flash); + if (!s->kernel) { + rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0); + } + + /* Initialize CPU */ + object_initialize_child(OBJECT(s), "cpu", &s->cpu, sizeof(RXCPU), + TYPE_RX62N_CPU, errp, NULL); + + register_icu(s); + s->cpu.env.ack =3D qdev_get_gpio_in_named(DEVICE(&s->icu), "ack", 0); + register_tmr(s, 0); + register_tmr(s, 1); + register_cmt(s, 0); + register_cmt(s, 1); + register_sci(s, 0); + object_property_set_bool(OBJECT(&s->cpu), true, "realized", errp); +} + +static Property rx62n_properties[] =3D { + DEFINE_PROP_LINK("memory", RX62NState, sysmem, TYPE_MEMORY_REGION, + MemoryRegion *), + DEFINE_PROP_BOOL("load-kernel", RX62NState, kernel, false), + DEFINE_PROP_END_OF_LIST(), +}; + +static void rx62n_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->realize =3D rx62n_realize; + device_class_set_props(dc, rx62n_properties); +} + +static const TypeInfo rx62n_info =3D { + .name =3D TYPE_RX62N, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RX62NState), + .class_init =3D rx62n_class_init, +}; + +static void rx62n_register_types(void) +{ + type_register_static(&rx62n_info); +} + +type_init(rx62n_register_types) diff --git a/hw/rx/Kconfig b/hw/rx/Kconfig new file mode 100644 index 0000000000..43af11be46 --- /dev/null +++ b/hw/rx/Kconfig @@ -0,0 +1,13 @@ +config RX + bool + +config RX62N + bool + select RX + select RENESAS_8TMR + select RENESAS_TIMER + select RENESAS_SCI + +config RX_VIRT + bool + select RX62N diff --git a/hw/rx/Makefile.objs b/hw/rx/Makefile.objs new file mode 100644 index 0000000000..63f8be0e82 --- /dev/null +++ b/hw/rx/Makefile.objs @@ -0,0 +1,2 @@ +obj-$(CONFIG_RX62N) +=3D rx62n.o +obj-$(CONFIG_RX_VIRT) +=3D rx-virt.o --=20 2.20.1 From nobody Fri May 17 04:49:49 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 ARC-Seal: i=1; a=rsa-sha256; t=1590942467; cv=none; d=zohomail.com; s=zohoarc; b=KcvcsCIINwwhLSbGyFOs8p4w6K29/W8kS05+oPfwcfZSy/vUat1Rem6AjlpqCk8mV/jm+pqc9T4+fkg1OctYeSRcmg4bTHSFLaBNDZ2Xwwm3zAri1Co7beQvLCK8gGJ5cuz31Hu+vszWXHmiGWHved3y4QonPaFXae+lutquyyk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1590942467; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Ux5wizMsNFbFvmpWpouxu3g45Ztvpq4qqqzED9SFWWA=; b=lDJie/b4SbNsNHm3/1iVpehpxyB1PM1zHKHtxRupH8HH7cUkLue78QYaWPE3OPYXT8zfhfaGK+/37anpzI6IluELq1vfygVwFSaJvKbI+S2wV5d0Kg/is2+FRri/w1gJfSaApMc5BIKdQwP18updtAl9jDjDb8e2kRxNVTYZ+RU= 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1590942467094646.9161279797663; Sun, 31 May 2020 09:27:47 -0700 (PDT) Received: from localhost ([::1]:54242 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQoL-0000mi-Q4 for importer@patchew.org; Sun, 31 May 2020 12:27:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53678) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jfQlL-0004DO-LA for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:39 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:48257) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQlK-0004KF-0R for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:39 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 58446ECD3B; Mon, 1 Jun 2020 01:24:34 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by sakura.ysato.name (Postfix) with ESMTPSA id F3A8D1C05D2; Mon, 1 Jun 2020 01:24:33 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 06/10] Add rx-softmmu Date: Mon, 1 Jun 2020 01:24:23 +0900 Message-Id: <20200531162427.57410-7-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200531162427.57410-1-ysato@users.sourceforge.jp> References: <20200531162427.57410-1-ysato@users.sourceforge.jp> 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: softfail client-ip=202.224.55.15; envelope-from=ysato@users.sourceforge.jp; helo=mail03.asahi-net.or.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/31 12:24:33 X-ACL-Warn: Detected OS = ??? 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_DNSWL_LOW=-0.7, SPF_SOFTFAIL=0.665, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Tested-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Philippe Mathieu-Daud=C3=A9 Signed-off-by: Yoshinori Sato Message-Id: <20190607091116.49044-17-ysato@users.sourceforge.jp> Signed-off-by: Richard Henderson pick ed65c02993 target/rx: Add RX to SysEmuTarget pick 01372568ae tests: Add rx to machine-none-test.c [PMD: Squashed patches from Richard Henderson modifying qapi/common.json and tests/machine-none-test.c] Signed-off-by: Philippe Mathieu-Daud=C3=A9 --- default-configs/rx-softmmu.mak | 1 + hw/Kconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/default-configs/rx-softmmu.mak b/default-configs/rx-softmmu.mak index 7c4eb2c1a0..a3eecefb11 100644 --- a/default-configs/rx-softmmu.mak +++ b/default-configs/rx-softmmu.mak @@ -1,2 +1,3 @@ # Default configuration for rx-softmmu =20 +CONFIG_RX_VIRT=3Dy diff --git a/hw/Kconfig b/hw/Kconfig index ecf491bf04..62f9ebdc22 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -55,6 +55,7 @@ source nios2/Kconfig source openrisc/Kconfig source ppc/Kconfig source riscv/Kconfig +source rx/Kconfig source s390x/Kconfig source sh4/Kconfig source sparc/Kconfig --=20 2.20.1 From nobody Fri May 17 04:49:49 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 ARC-Seal: i=1; a=rsa-sha256; t=1590942472; cv=none; d=zohomail.com; s=zohoarc; b=mGKINeb6ZnHaxjT0BwJSZPQvcCkfY/mG0LzUDplGFkleg1AVPsTqQa+0CtmbLYf3Y0vBcSGix+Vf/iXdHYETTvBKcEM1jGBdnnshJ9AIJGvYM1O8cJhnnU6gdra+C3PkRBaDQxCrkhFrNNyTesanyGg7cWy0rRDH8eoziHDo9tk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1590942472; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=KWgjf38e+5rqWnulNl7fQruq4KVtWp4xWZ9jbFYBPcM=; b=XaTfnxcFzu2KdAMffjxKRMm362ibqocIZl2UbNsk7AO+lDBFqn9A3LE69XY5YuuZAfLCZcTFW/2cai5Rr/hTYjX9wXXkzZnz7T9NJ/dwdPHNzJuXNt/Uycg8wKeJVUIjrMSbvhI+2euR5PPoZC50dhnIXOkXiyOkRIGWpPNztx8= 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1590942472363908.5208751837591; Sun, 31 May 2020 09:27:52 -0700 (PDT) Received: from localhost ([::1]:54814 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQoR-00012K-5z for importer@patchew.org; Sun, 31 May 2020 12:27:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53688) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jfQlM-0004Er-Ux for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:40 -0400 Received: from mail02.asahi-net.or.jp ([202.224.55.14]:58735) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQlJ-0004KC-Ux for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:40 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail02.asahi-net.or.jp (Postfix) with ESMTPA id 9475FEB8D4; Mon, 1 Jun 2020 01:24:34 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by sakura.ysato.name (Postfix) with ESMTPSA id 421891C0DB3; Mon, 1 Jun 2020 01:24:34 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 07/10] hw/sh4: Convert renesas_sci. Date: Mon, 1 Jun 2020 01:24:24 +0900 Message-Id: <20200531162427.57410-8-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200531162427.57410-1-ysato@users.sourceforge.jp> References: <20200531162427.57410-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 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: softfail client-ip=202.224.55.14; envelope-from=ysato@users.sourceforge.jp; helo=mail02.asahi-net.or.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/31 12:24:33 X-ACL-Warn: Detected OS = ??? 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_DNSWL_LOW=-0.7, SPF_SOFTFAIL=0.665, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Using new implementation SCI module. Signed-off-by: Yoshinori Sato --- include/hw/sh4/sh.h | 11 ----------- hw/sh4/sh7750.c | 45 +++++++++++++++++++++++++++++++++++++++++---- hw/sh4/Kconfig | 1 + 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/include/hw/sh4/sh.h b/include/hw/sh4/sh.h index 767a2df7e2..e184b4b300 100644 --- a/include/hw/sh4/sh.h +++ b/include/hw/sh4/sh.h @@ -38,17 +38,6 @@ void tmu012_init(struct MemoryRegion *sysmem, hwaddr bas= e, qemu_irq ch2_irq0, qemu_irq ch2_irq1); =20 =20 -/* sh_serial.c */ -#define SH_SERIAL_FEAT_SCIF (1 << 0) -void sh_serial_init(MemoryRegion *sysmem, - hwaddr base, int feat, - uint32_t freq, Chardev *chr, - qemu_irq eri_source, - qemu_irq rxi_source, - qemu_irq txi_source, - qemu_irq tei_source, - qemu_irq bri_source); - /* sh7750.c */ qemu_irq sh7750_irl(struct SH7750State *s); =20 diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c index d660714443..150d3029f7 100644 --- a/hw/sh4/sh7750.c +++ b/hw/sh4/sh7750.c @@ -24,12 +24,15 @@ */ =20 #include "qemu/osdep.h" +#include "qapi/error.h" #include "hw/irq.h" #include "hw/sh4/sh.h" #include "sysemu/sysemu.h" #include "sh7750_regs.h" #include "sh7750_regnames.h" #include "hw/sh4/sh_intc.h" +#include "hw/char/renesas_sci.h" +#include "hw/qdev-properties.h" #include "cpu.h" #include "exec/exec-all.h" =20 @@ -752,6 +755,40 @@ static const MemoryRegionOps sh7750_mmct_ops =3D { .endianness =3D DEVICE_NATIVE_ENDIAN, }; =20 +static void sh_serial_init(SH7750State *s, MemoryRegion *sysmem, + hwaddr base, int feat, + uint32_t freq, Chardev *chr, + qemu_irq eri_source, + qemu_irq rxi_source, + qemu_irq txi_source, + qemu_irq tei_source, + qemu_irq bri_source) +{ + DeviceState *dev; + SysBusDevice *sci; + + dev =3D qdev_create(NULL, TYPE_RENESAS_SCI); + + sci =3D SYS_BUS_DEVICE(dev); + + qdev_prop_set_chr(dev, "chardev", chr); + qdev_prop_set_uint64(dev, "input-freq", freq); + qdev_prop_set_int32(dev, "feature", feat); + qdev_prop_set_int32(dev, "register-size", 32); + qdev_init_nofail(dev); + sysbus_mmio_map(sci, 0, base); + sysbus_mmio_map(sci, 1, P4ADDR(base)); + sysbus_mmio_map(sci, 2, A7ADDR(base)); + sysbus_connect_irq(sci, 0, eri_source); + sysbus_connect_irq(sci, 1, rxi_source); + sysbus_connect_irq(sci, 2, txi_source); + if (feat =3D=3D SCI_FEAT_SCI) { + sysbus_connect_irq(sci, 3, tei_source); + } else { + sysbus_connect_irq(sci, 3, bri_source); + } +} + SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem) { SH7750State *s; @@ -800,15 +837,15 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion= *sysmem) =20 cpu->env.intc_handle =3D &s->intc; =20 - sh_serial_init(sysmem, 0x1fe00000, - 0, s->periph_freq, serial_hd(0), + sh_serial_init(s, sysmem, 0x1fe00000, + SCI_FEAT_SCI, s->periph_freq, serial_hd(0), s->intc.irqs[SCI1_ERI], s->intc.irqs[SCI1_RXI], s->intc.irqs[SCI1_TXI], s->intc.irqs[SCI1_TEI], NULL); - sh_serial_init(sysmem, 0x1fe80000, - SH_SERIAL_FEAT_SCIF, + sh_serial_init(s, sysmem, 0x1fe80000, + SCI_FEAT_SCIF, s->periph_freq, serial_hd(1), s->intc.irqs[SCIF_ERI], s->intc.irqs[SCIF_RXI], diff --git a/hw/sh4/Kconfig b/hw/sh4/Kconfig index 4cbce3a0ed..38509b7e65 100644 --- a/hw/sh4/Kconfig +++ b/hw/sh4/Kconfig @@ -22,3 +22,4 @@ config SH7750 config SH4 bool select PTIMER + select RENESAS_SCI --=20 2.20.1 From nobody Fri May 17 04:49:49 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 ARC-Seal: i=1; a=rsa-sha256; t=1590942707; cv=none; d=zohomail.com; s=zohoarc; b=AKHWfE+uQi3Ejbb6N8wspd6iiAUoi+E4LDqn7mnC5sHykfKl8DcOXg1w3Y6iVTajUZyChpcVpfN0UfWPfKbwqe30VufSNi/tEtYxYkAc+IITuvFFbAhIDqBMll6eVb9Khc1OHzPRfL1N+bop4IyDmGhhct+rDRxZ+vYFAmT4SLA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1590942707; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=+drhSVHnmKjmtm7sO5L8HsRd8zGQImQOy6yBkj+jmLk=; b=MGhOC54pBjNcwFFUqPVAsXgGo9ExcEDViLprkrExClg9sFElraygIu00FlsXTEdcmdfa86V6o8Xlwg2ecRJEwnB5rCxnY8+LEqPrukZbh+mu+lOsPsm7k5chRfSOXYuC61LgFx5ggTT0cYFtUOjbv8EnGEtTrz9PxCgW63lrPuc= 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1590942707848670.5684117499927; Sun, 31 May 2020 09:31:47 -0700 (PDT) Received: from localhost ([::1]:38014 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQsE-0005wl-5I for importer@patchew.org; Sun, 31 May 2020 12:31:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53700) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jfQlQ-0004Ly-Lo for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:44 -0400 Received: from mail01.asahi-net.or.jp ([202.224.55.13]:36015) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQlP-0004KE-CK for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:44 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail01.asahi-net.or.jp (Postfix) with ESMTPA id AD8E5105239; Mon, 1 Jun 2020 01:24:34 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by sakura.ysato.name (Postfix) with ESMTPSA id 7417A1C0DB6; Mon, 1 Jun 2020 01:24:34 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 08/10] hw/char: remove sh_serial.c Date: Mon, 1 Jun 2020 01:24:25 +0900 Message-Id: <20200531162427.57410-9-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200531162427.57410-1-ysato@users.sourceforge.jp> References: <20200531162427.57410-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 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: softfail client-ip=202.224.55.13; envelope-from=ysato@users.sourceforge.jp; helo=mail01.asahi-net.or.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/31 12:24:33 X-ACL-Warn: Detected OS = ??? 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_DNSWL_LOW=-0.7, SPF_SOFTFAIL=0.665, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" SH4 SCI module convert to renesas_sci.c. This file is obsolute. Signed-off-by: Yoshinori Sato --- hw/char/sh_serial.c | 431 -------------------------------------------- 1 file changed, 431 deletions(-) delete mode 100644 hw/char/sh_serial.c diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c deleted file mode 100644 index 167f4d8cb9..0000000000 --- a/hw/char/sh_serial.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * QEMU SCI/SCIF serial port emulation - * - * Copyright (c) 2007 Magnus Damm - * - * Based on serial.c - QEMU 16450 UART emulation - * Copyright (c) 2003-2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a= copy - * of this software and associated documentation files (the "Software"), t= o deal - * in the Software without restriction, including without limitation the r= ights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included= in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN - * THE SOFTWARE. - */ - -#include "qemu/osdep.h" -#include "hw/irq.h" -#include "hw/sh4/sh.h" -#include "chardev/char-fe.h" -#include "qapi/error.h" -#include "qemu/timer.h" - -//#define DEBUG_SERIAL - -#define SH_SERIAL_FLAG_TEND (1 << 0) -#define SH_SERIAL_FLAG_TDE (1 << 1) -#define SH_SERIAL_FLAG_RDF (1 << 2) -#define SH_SERIAL_FLAG_BRK (1 << 3) -#define SH_SERIAL_FLAG_DR (1 << 4) - -#define SH_RX_FIFO_LENGTH (16) - -typedef struct { - MemoryRegion iomem; - MemoryRegion iomem_p4; - MemoryRegion iomem_a7; - uint8_t smr; - uint8_t brr; - uint8_t scr; - uint8_t dr; /* ftdr / tdr */ - uint8_t sr; /* fsr / ssr */ - uint16_t fcr; - uint8_t sptr; - - uint8_t rx_fifo[SH_RX_FIFO_LENGTH]; /* frdr / rdr */ - uint8_t rx_cnt; - uint8_t rx_tail; - uint8_t rx_head; - - int freq; - int feat; - int flags; - int rtrg; - - CharBackend chr; - QEMUTimer *fifo_timeout_timer; - uint64_t etu; /* Elementary Time Unit (ns) */ - - qemu_irq eri; - qemu_irq rxi; - qemu_irq txi; - qemu_irq tei; - qemu_irq bri; -} sh_serial_state; - -static void sh_serial_clear_fifo(sh_serial_state * s) -{ - memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH); - s->rx_cnt =3D 0; - s->rx_head =3D 0; - s->rx_tail =3D 0; -} - -static void sh_serial_write(void *opaque, hwaddr offs, - uint64_t val, unsigned size) -{ - sh_serial_state *s =3D opaque; - unsigned char ch; - -#ifdef DEBUG_SERIAL - printf("sh_serial: write offs=3D0x%02x val=3D0x%02x\n", - offs, val); -#endif - switch(offs) { - case 0x00: /* SMR */ - s->smr =3D val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff); - return; - case 0x04: /* BRR */ - s->brr =3D val; - return; - case 0x08: /* SCR */ - /* TODO : For SH7751, SCIF mask should be 0xfb. */ - s->scr =3D val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff); - if (!(val & (1 << 5))) - s->flags |=3D SH_SERIAL_FLAG_TEND; - if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) { - qemu_set_irq(s->txi, val & (1 << 7)); - } - if (!(val & (1 << 6))) { - qemu_set_irq(s->rxi, 0); - } - return; - case 0x0c: /* FTDR / TDR */ - if (qemu_chr_fe_backend_connected(&s->chr)) { - ch =3D val; - /* XXX this blocks entire thread. Rewrite to use - * qemu_chr_fe_write and background I/O callbacks */ - qemu_chr_fe_write_all(&s->chr, &ch, 1); - } - s->dr =3D val; - s->flags &=3D ~SH_SERIAL_FLAG_TDE; - return; -#if 0 - case 0x14: /* FRDR / RDR */ - ret =3D 0; - break; -#endif - } - if (s->feat & SH_SERIAL_FEAT_SCIF) { - switch(offs) { - case 0x10: /* FSR */ - if (!(val & (1 << 6))) - s->flags &=3D ~SH_SERIAL_FLAG_TEND; - if (!(val & (1 << 5))) - s->flags &=3D ~SH_SERIAL_FLAG_TDE; - if (!(val & (1 << 4))) - s->flags &=3D ~SH_SERIAL_FLAG_BRK; - if (!(val & (1 << 1))) - s->flags &=3D ~SH_SERIAL_FLAG_RDF; - if (!(val & (1 << 0))) - s->flags &=3D ~SH_SERIAL_FLAG_DR; - - if (!(val & (1 << 1)) || !(val & (1 << 0))) { - if (s->rxi) { - qemu_set_irq(s->rxi, 0); - } - } - return; - case 0x18: /* FCR */ - s->fcr =3D val; - switch ((val >> 6) & 3) { - case 0: - s->rtrg =3D 1; - break; - case 1: - s->rtrg =3D 4; - break; - case 2: - s->rtrg =3D 8; - break; - case 3: - s->rtrg =3D 14; - break; - } - if (val & (1 << 1)) { - sh_serial_clear_fifo(s); - s->sr &=3D ~(1 << 1); - } - - return; - case 0x20: /* SPTR */ - s->sptr =3D val & 0xf3; - return; - case 0x24: /* LSR */ - return; - } - } - else { - switch(offs) { -#if 0 - case 0x0c: - ret =3D s->dr; - break; - case 0x10: - ret =3D 0; - break; -#endif - case 0x1c: - s->sptr =3D val & 0x8f; - return; - } - } - - fprintf(stderr, "sh_serial: unsupported write to 0x%02" - HWADDR_PRIx "\n", offs); - abort(); -} - -static uint64_t sh_serial_read(void *opaque, hwaddr offs, - unsigned size) -{ - sh_serial_state *s =3D opaque; - uint32_t ret =3D ~0; - -#if 0 - switch(offs) { - case 0x00: - ret =3D s->smr; - break; - case 0x04: - ret =3D s->brr; - break; - case 0x08: - ret =3D s->scr; - break; - case 0x14: - ret =3D 0; - break; - } -#endif - if (s->feat & SH_SERIAL_FEAT_SCIF) { - switch(offs) { - case 0x00: /* SMR */ - ret =3D s->smr; - break; - case 0x08: /* SCR */ - ret =3D s->scr; - break; - case 0x10: /* FSR */ - ret =3D 0; - if (s->flags & SH_SERIAL_FLAG_TEND) - ret |=3D (1 << 6); - if (s->flags & SH_SERIAL_FLAG_TDE) - ret |=3D (1 << 5); - if (s->flags & SH_SERIAL_FLAG_BRK) - ret |=3D (1 << 4); - if (s->flags & SH_SERIAL_FLAG_RDF) - ret |=3D (1 << 1); - if (s->flags & SH_SERIAL_FLAG_DR) - ret |=3D (1 << 0); - - if (s->scr & (1 << 5)) - s->flags |=3D SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND; - - break; - case 0x14: - if (s->rx_cnt > 0) { - ret =3D s->rx_fifo[s->rx_tail++]; - s->rx_cnt--; - if (s->rx_tail =3D=3D SH_RX_FIFO_LENGTH) - s->rx_tail =3D 0; - if (s->rx_cnt < s->rtrg) - s->flags &=3D ~SH_SERIAL_FLAG_RDF; - } - break; - case 0x18: - ret =3D s->fcr; - break; - case 0x1c: - ret =3D s->rx_cnt; - break; - case 0x20: - ret =3D s->sptr; - break; - case 0x24: - ret =3D 0; - break; - } - } - else { - switch(offs) { -#if 0 - case 0x0c: - ret =3D s->dr; - break; - case 0x10: - ret =3D 0; - break; - case 0x14: - ret =3D s->rx_fifo[0]; - break; -#endif - case 0x1c: - ret =3D s->sptr; - break; - } - } -#ifdef DEBUG_SERIAL - printf("sh_serial: read offs=3D0x%02x val=3D0x%x\n", - offs, ret); -#endif - - if (ret & ~((1 << 16) - 1)) { - fprintf(stderr, "sh_serial: unsupported read from 0x%02" - HWADDR_PRIx "\n", offs); - abort(); - } - - return ret; -} - -static int sh_serial_can_receive(sh_serial_state *s) -{ - return s->scr & (1 << 4); -} - -static void sh_serial_receive_break(sh_serial_state *s) -{ - if (s->feat & SH_SERIAL_FEAT_SCIF) - s->sr |=3D (1 << 4); -} - -static int sh_serial_can_receive1(void *opaque) -{ - sh_serial_state *s =3D opaque; - return sh_serial_can_receive(s); -} - -static void sh_serial_timeout_int(void *opaque) -{ - sh_serial_state *s =3D opaque; - - s->flags |=3D SH_SERIAL_FLAG_RDF; - if (s->scr & (1 << 6) && s->rxi) { - qemu_set_irq(s->rxi, 1); - } -} - -static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size) -{ - sh_serial_state *s =3D opaque; - - if (s->feat & SH_SERIAL_FEAT_SCIF) { - int i; - for (i =3D 0; i < size; i++) { - if (s->rx_cnt < SH_RX_FIFO_LENGTH) { - s->rx_fifo[s->rx_head++] =3D buf[i]; - if (s->rx_head =3D=3D SH_RX_FIFO_LENGTH) { - s->rx_head =3D 0; - } - s->rx_cnt++; - if (s->rx_cnt >=3D s->rtrg) { - s->flags |=3D SH_SERIAL_FLAG_RDF; - if (s->scr & (1 << 6) && s->rxi) { - timer_del(s->fifo_timeout_timer); - qemu_set_irq(s->rxi, 1); - } - } else { - timer_mod(s->fifo_timeout_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 15 * s->et= u); - } - } - } - } else { - s->rx_fifo[0] =3D buf[0]; - } -} - -static void sh_serial_event(void *opaque, QEMUChrEvent event) -{ - sh_serial_state *s =3D opaque; - if (event =3D=3D CHR_EVENT_BREAK) - sh_serial_receive_break(s); -} - -static const MemoryRegionOps sh_serial_ops =3D { - .read =3D sh_serial_read, - .write =3D sh_serial_write, - .endianness =3D DEVICE_NATIVE_ENDIAN, -}; - -void sh_serial_init(MemoryRegion *sysmem, - hwaddr base, int feat, - uint32_t freq, Chardev *chr, - qemu_irq eri_source, - qemu_irq rxi_source, - qemu_irq txi_source, - qemu_irq tei_source, - qemu_irq bri_source) -{ - sh_serial_state *s; - - s =3D g_malloc0(sizeof(sh_serial_state)); - - s->feat =3D feat; - s->flags =3D SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE; - s->rtrg =3D 1; - - s->smr =3D 0; - s->brr =3D 0xff; - s->scr =3D 1 << 5; /* pretend that TX is enabled so early printk works= */ - s->sptr =3D 0; - - if (feat & SH_SERIAL_FEAT_SCIF) { - s->fcr =3D 0; - } - else { - s->dr =3D 0xff; - } - - sh_serial_clear_fifo(s); - - memory_region_init_io(&s->iomem, NULL, &sh_serial_ops, s, - "serial", 0x100000000ULL); - - memory_region_init_alias(&s->iomem_p4, NULL, "serial-p4", &s->iomem, - 0, 0x28); - memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4); - - memory_region_init_alias(&s->iomem_a7, NULL, "serial-a7", &s->iomem, - 0, 0x28); - memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7); - - if (chr) { - qemu_chr_fe_init(&s->chr, chr, &error_abort); - qemu_chr_fe_set_handlers(&s->chr, sh_serial_can_receive1, - sh_serial_receive1, - sh_serial_event, NULL, s, NULL, true); - } - - s->fifo_timeout_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, - sh_serial_timeout_int, s); - s->etu =3D NANOSECONDS_PER_SECOND / 9600; - s->eri =3D eri_source; - s->rxi =3D rxi_source; - s->txi =3D txi_source; - s->tei =3D tei_source; - s->bri =3D bri_source; -} --=20 2.20.1 From nobody Fri May 17 04:49:49 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 ARC-Seal: i=1; a=rsa-sha256; t=1590942352; cv=none; d=zohomail.com; s=zohoarc; b=ddSSIXiuQqJYjgvXf/txMklZj09lv2e3f0nm/jT3te38iPUYukfAQCUZ7kbAq/8X3aimewvrcpi+EbIvB4BFgBo95pIczQ0CZkIdsPmotOqlUhHp23yQ2fZkD1REckRlPL1OWmu3wdxYLTCsJXQKwW6oYk/bX1ArXBwOaDL5664= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1590942352; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=eB04VXZ6IUofti5f/z2LO/fT32gEeD+4fqOFd93BLQw=; b=j7998GLrOgCYwNGj0J5RZLAHm8efC3Rrp2m9qASFgy6d/KFcwHlQvPxBoyKqThhM/Neo6gwgvVrZAZ36jrynt9f3ItWRDO3Ic8oJV23fB5KoePTL1Brxg+f8G8QGiKk5I85Pjle/k0ncuCbKL12qBaCOcxxXWHBaXlA86y9T8ys= 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1590942352704730.2452089381288; Sun, 31 May 2020 09:25:52 -0700 (PDT) Received: from localhost ([::1]:46280 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQmV-0005fo-2p for importer@patchew.org; Sun, 31 May 2020 12:25:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53676) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jfQlL-0004DM-Jb for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:39 -0400 Received: from mail03.asahi-net.or.jp ([202.224.55.15]:48260) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQlJ-0004KS-Uh for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:39 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail03.asahi-net.or.jp (Postfix) with ESMTPA id 0A2EDECD3D; Mon, 1 Jun 2020 01:24:35 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by sakura.ysato.name (Postfix) with ESMTPSA id B56F71C0DB3; Mon, 1 Jun 2020 01:24:34 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 09/10] hw/sh4: Convert to renesas_timer.c Date: Mon, 1 Jun 2020 01:24:26 +0900 Message-Id: <20200531162427.57410-10-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200531162427.57410-1-ysato@users.sourceforge.jp> References: <20200531162427.57410-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 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: softfail client-ip=202.224.55.15; envelope-from=ysato@users.sourceforge.jp; helo=mail03.asahi-net.or.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/31 12:24:33 X-ACL-Warn: Detected OS = ??? 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_DNSWL_LOW=-0.7, SPF_SOFTFAIL=0.665, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Using unified TMU/CMT module. Signed-off-by: Yoshinori Sato --- include/hw/sh4/sh.h | 10 --------- hw/sh4/sh7750.c | 47 +++++++++++++++++++++++++++++++++--------- hw/sh4/Kconfig | 2 +- hw/timer/Makefile.objs | 1 - 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/include/hw/sh4/sh.h b/include/hw/sh4/sh.h index e184b4b300..248cc052e1 100644 --- a/include/hw/sh4/sh.h +++ b/include/hw/sh4/sh.h @@ -28,16 +28,6 @@ typedef struct { =20 int sh7750_register_io_device(struct SH7750State *s, sh7750_io_device * device); -/* sh_timer.c */ -#define TMU012_FEAT_TOCR (1 << 0) -#define TMU012_FEAT_3CHAN (1 << 1) -#define TMU012_FEAT_EXTCLK (1 << 2) -void tmu012_init(struct MemoryRegion *sysmem, hwaddr base, - int feat, uint32_t freq, - qemu_irq ch0_irq, qemu_irq ch1_irq, - qemu_irq ch2_irq0, qemu_irq ch2_irq1); - - /* sh7750.c */ qemu_irq sh7750_irl(struct SH7750State *s); =20 diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c index 150d3029f7..733c4009e1 100644 --- a/hw/sh4/sh7750.c +++ b/hw/sh4/sh7750.c @@ -32,6 +32,7 @@ #include "sh7750_regnames.h" #include "hw/sh4/sh_intc.h" #include "hw/char/renesas_sci.h" +#include "hw/timer/renesas_timer.h" #include "hw/qdev-properties.h" #include "cpu.h" #include "exec/exec-all.h" @@ -756,13 +757,13 @@ static const MemoryRegionOps sh7750_mmct_ops =3D { }; =20 static void sh_serial_init(SH7750State *s, MemoryRegion *sysmem, - hwaddr base, int feat, - uint32_t freq, Chardev *chr, - qemu_irq eri_source, - qemu_irq rxi_source, - qemu_irq txi_source, - qemu_irq tei_source, - qemu_irq bri_source) + hwaddr base, int feat, + uint32_t freq, Chardev *chr, + qemu_irq eri_source, + qemu_irq rxi_source, + qemu_irq txi_source, + qemu_irq tei_source, + qemu_irq bri_source) { DeviceState *dev; SysBusDevice *sci; @@ -789,6 +790,31 @@ static void sh_serial_init(SH7750State *s, MemoryRegio= n *sysmem, } } =20 +static void tmu012_init(SH7750State *s, MemoryRegion *sysmem, hwaddr base, + int feat, uint32_t freq, + qemu_irq ch0_irq, qemu_irq ch1_irq, + qemu_irq ch2_irq0, qemu_irq ch2_irq1) +{ + DeviceState *dev; + SysBusDevice *tmu; + + dev =3D qdev_create(NULL, TYPE_RENESAS_TIMER); + + tmu =3D SYS_BUS_DEVICE(dev); + + qdev_prop_set_uint64(dev, "input-freq", freq); + qdev_prop_set_int32(dev, "feature", feat); + qdev_init_nofail(dev); + sysbus_mmio_map(tmu, 0, base); + sysbus_mmio_map(tmu, 1, P4ADDR(base)); + sysbus_mmio_map(tmu, 2, A7ADDR(base)); + sysbus_connect_irq(tmu, 0, ch0_irq); + sysbus_connect_irq(tmu, 1, ch1_irq); + if (ch2_irq0) { + sysbus_connect_irq(tmu, 2, ch2_irq0); + } +} + SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem) { SH7750State *s; @@ -853,8 +879,8 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *= sysmem) NULL, s->intc.irqs[SCIF_BRI]); =20 - tmu012_init(sysmem, 0x1fd80000, - TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK, + tmu012_init(s, sysmem, 0x1fd80000, + RTIMER_FEAT_TMU_LOW, s->periph_freq, s->intc.irqs[TMU0], s->intc.irqs[TMU1], @@ -877,7 +903,8 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *= sysmem) sh_intc_register_sources(&s->intc, _INTC_ARRAY(vectors_tmu34), NULL, 0); - tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq, + tmu012_init(s, sysmem, 0x1e100000, + RTIMER_FEAT_TMU_HIGH, s->periph_freq, s->intc.irqs[TMU3], s->intc.irqs[TMU4], NULL, NULL); diff --git a/hw/sh4/Kconfig b/hw/sh4/Kconfig index 38509b7e65..ac21830bb5 100644 --- a/hw/sh4/Kconfig +++ b/hw/sh4/Kconfig @@ -21,5 +21,5 @@ config SH7750 =20 config SH4 bool - select PTIMER + select RENESAS_TIMER select RENESAS_SCI diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index 289b6b03ab..f3918836e4 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -22,7 +22,6 @@ common-obj-$(CONFIG_EXYNOS4) +=3D exynos4210_pwm.o common-obj-$(CONFIG_OMAP) +=3D omap_gptimer.o common-obj-$(CONFIG_OMAP) +=3D omap_synctimer.o common-obj-$(CONFIG_PXA2XX) +=3D pxa2xx_timer.o -common-obj-$(CONFIG_SH4) +=3D sh_timer.o common-obj-$(CONFIG_DIGIC) +=3D digic-timer.o common-obj-$(CONFIG_MIPS_CPS) +=3D mips_gictimer.o =20 --=20 2.20.1 From nobody Fri May 17 04:49:49 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 ARC-Seal: i=1; a=rsa-sha256; t=1590942358; cv=none; d=zohomail.com; s=zohoarc; b=jnf9a6Y353mqpwIvN1369QgNXMpX5Jds64/rHFiJS9IZYCbmUm1z+msZnQsCiFPgC+NeBLX3q3GV5PSZwg44fax52trcEqpIIijBKxWxK9bIXV8MtEx/rOFcUxfQnE+RzRt90gNovL7f2xHVRkDyItFvtZrDT5Z8n8HQ1+wPx78= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1590942358; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=1+2fBmbaN71QEsmOIQjjajfiAInvTJlQGq3LGtVb95M=; b=I7m9I0G3XsMQoYqj2Tego/PbdXfa5NI2aOM+PGUT1jASDOyPMvSeMbvpfBOwqXpq0pZmxLluEH8LRBoKBNCwDESZRIRy+V4bf4OGXgxKou0gegUYYiEheU5RbLJIXohFUtCP8Sv5YZ2QK5Xhvlkun/O9SiNpqpm06aJU44BdXm4= 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1590942358612380.1253689915352; Sun, 31 May 2020 09:25:58 -0700 (PDT) Received: from localhost ([::1]:46632 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQmb-0005qS-2G for importer@patchew.org; Sun, 31 May 2020 12:25:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53680) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jfQlM-0004Df-B5 for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:40 -0400 Received: from mail02.asahi-net.or.jp ([202.224.55.14]:58737) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jfQlK-0004Kb-1S for qemu-devel@nongnu.org; Sun, 31 May 2020 12:24:40 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail02.asahi-net.or.jp (Postfix) with ESMTPA id 45135EB8AA; Mon, 1 Jun 2020 01:24:35 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by sakura.ysato.name (Postfix) with ESMTPSA id E9CA21C05D2; Mon, 1 Jun 2020 01:24:34 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 10/10] hw/timer: remove sh_timer.c Date: Mon, 1 Jun 2020 01:24:27 +0900 Message-Id: <20200531162427.57410-11-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200531162427.57410-1-ysato@users.sourceforge.jp> References: <20200531162427.57410-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 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: softfail client-ip=202.224.55.14; envelope-from=ysato@users.sourceforge.jp; helo=mail02.asahi-net.or.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/31 12:24:33 X-ACL-Warn: Detected OS = ??? 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_DNSWL_LOW=-0.7, SPF_SOFTFAIL=0.665, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" SH4 TMU using new module. This file is obsolute. Signed-off-by: Yoshinori Sato --- hw/timer/sh_timer.c | 341 -------------------------------------------- 1 file changed, 341 deletions(-) delete mode 100644 hw/timer/sh_timer.c diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c deleted file mode 100644 index 13c4051808..0000000000 --- a/hw/timer/sh_timer.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * SuperH Timer modules. - * - * Copyright (c) 2007 Magnus Damm - * Based on arm_timer.c by Paul Brook - * Copyright (c) 2005-2006 CodeSourcery. - * - * This code is licensed under the GPL. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/irq.h" -#include "hw/sh4/sh.h" -#include "qemu/timer.h" -#include "hw/ptimer.h" - -//#define DEBUG_TIMER - -#define TIMER_TCR_TPSC (7 << 0) -#define TIMER_TCR_CKEG (3 << 3) -#define TIMER_TCR_UNIE (1 << 5) -#define TIMER_TCR_ICPE (3 << 6) -#define TIMER_TCR_UNF (1 << 8) -#define TIMER_TCR_ICPF (1 << 9) -#define TIMER_TCR_RESERVED (0x3f << 10) - -#define TIMER_FEAT_CAPT (1 << 0) -#define TIMER_FEAT_EXTCLK (1 << 1) - -#define OFFSET_TCOR 0 -#define OFFSET_TCNT 1 -#define OFFSET_TCR 2 -#define OFFSET_TCPR 3 - -typedef struct { - ptimer_state *timer; - uint32_t tcnt; - uint32_t tcor; - uint32_t tcr; - uint32_t tcpr; - int freq; - int int_level; - int old_level; - int feat; - int enabled; - qemu_irq irq; -} sh_timer_state; - -/* Check all active timers, and schedule the next timer interrupt. */ - -static void sh_timer_update(sh_timer_state *s) -{ - int new_level =3D s->int_level && (s->tcr & TIMER_TCR_UNIE); - - if (new_level !=3D s->old_level) - qemu_set_irq (s->irq, new_level); - - s->old_level =3D s->int_level; - s->int_level =3D new_level; -} - -static uint32_t sh_timer_read(void *opaque, hwaddr offset) -{ - sh_timer_state *s =3D (sh_timer_state *)opaque; - - switch (offset >> 2) { - case OFFSET_TCOR: - return s->tcor; - case OFFSET_TCNT: - return ptimer_get_count(s->timer); - case OFFSET_TCR: - return s->tcr | (s->int_level ? TIMER_TCR_UNF : 0); - case OFFSET_TCPR: - if (s->feat & TIMER_FEAT_CAPT) - return s->tcpr; - /* fall through */ - default: - hw_error("sh_timer_read: Bad offset %x\n", (int)offset); - return 0; - } -} - -static void sh_timer_write(void *opaque, hwaddr offset, - uint32_t value) -{ - sh_timer_state *s =3D (sh_timer_state *)opaque; - int freq; - - switch (offset >> 2) { - case OFFSET_TCOR: - s->tcor =3D value; - ptimer_transaction_begin(s->timer); - ptimer_set_limit(s->timer, s->tcor, 0); - ptimer_transaction_commit(s->timer); - break; - case OFFSET_TCNT: - s->tcnt =3D value; - ptimer_transaction_begin(s->timer); - ptimer_set_count(s->timer, s->tcnt); - ptimer_transaction_commit(s->timer); - break; - case OFFSET_TCR: - ptimer_transaction_begin(s->timer); - if (s->enabled) { - /* Pause the timer if it is running. This may cause some - inaccuracy dure to rounding, but avoids a whole lot of other - messyness. */ - ptimer_stop(s->timer); - } - freq =3D s->freq; - /* ??? Need to recalculate expiry time after changing divisor. */ - switch (value & TIMER_TCR_TPSC) { - case 0: freq >>=3D 2; break; - case 1: freq >>=3D 4; break; - case 2: freq >>=3D 6; break; - case 3: freq >>=3D 8; break; - case 4: freq >>=3D 10; break; - case 6: - case 7: if (s->feat & TIMER_FEAT_EXTCLK) break; - default: hw_error("sh_timer_write: Reserved TPSC value\n"); break; - } - switch ((value & TIMER_TCR_CKEG) >> 3) { - case 0: break; - case 1: - case 2: - case 3: if (s->feat & TIMER_FEAT_EXTCLK) break; - default: hw_error("sh_timer_write: Reserved CKEG value\n"); break; - } - switch ((value & TIMER_TCR_ICPE) >> 6) { - case 0: break; - case 2: - case 3: if (s->feat & TIMER_FEAT_CAPT) break; - default: hw_error("sh_timer_write: Reserved ICPE value\n"); break; - } - if ((value & TIMER_TCR_UNF) =3D=3D 0) - s->int_level =3D 0; - - value &=3D ~TIMER_TCR_UNF; - - if ((value & TIMER_TCR_ICPF) && (!(s->feat & TIMER_FEAT_CAPT))) - hw_error("sh_timer_write: Reserved ICPF value\n"); - - value &=3D ~TIMER_TCR_ICPF; /* capture not supported */ - - if (value & TIMER_TCR_RESERVED) - hw_error("sh_timer_write: Reserved TCR bits set\n"); - s->tcr =3D value; - ptimer_set_limit(s->timer, s->tcor, 0); - ptimer_set_freq(s->timer, freq); - if (s->enabled) { - /* Restart the timer if still enabled. */ - ptimer_run(s->timer, 0); - } - ptimer_transaction_commit(s->timer); - break; - case OFFSET_TCPR: - if (s->feat & TIMER_FEAT_CAPT) { - s->tcpr =3D value; - break; - } - default: - hw_error("sh_timer_write: Bad offset %x\n", (int)offset); - } - sh_timer_update(s); -} - -static void sh_timer_start_stop(void *opaque, int enable) -{ - sh_timer_state *s =3D (sh_timer_state *)opaque; - -#ifdef DEBUG_TIMER - printf("sh_timer_start_stop %d (%d)\n", enable, s->enabled); -#endif - - ptimer_transaction_begin(s->timer); - if (s->enabled && !enable) { - ptimer_stop(s->timer); - } - if (!s->enabled && enable) { - ptimer_run(s->timer, 0); - } - ptimer_transaction_commit(s->timer); - s->enabled =3D !!enable; - -#ifdef DEBUG_TIMER - printf("sh_timer_start_stop done %d\n", s->enabled); -#endif -} - -static void sh_timer_tick(void *opaque) -{ - sh_timer_state *s =3D (sh_timer_state *)opaque; - s->int_level =3D s->enabled; - sh_timer_update(s); -} - -static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq) -{ - sh_timer_state *s; - - s =3D (sh_timer_state *)g_malloc0(sizeof(sh_timer_state)); - s->freq =3D freq; - s->feat =3D feat; - s->tcor =3D 0xffffffff; - s->tcnt =3D 0xffffffff; - s->tcpr =3D 0xdeadbeef; - s->tcr =3D 0; - s->enabled =3D 0; - s->irq =3D irq; - - s->timer =3D ptimer_init(sh_timer_tick, s, PTIMER_POLICY_DEFAULT); - - sh_timer_write(s, OFFSET_TCOR >> 2, s->tcor); - sh_timer_write(s, OFFSET_TCNT >> 2, s->tcnt); - sh_timer_write(s, OFFSET_TCPR >> 2, s->tcpr); - sh_timer_write(s, OFFSET_TCR >> 2, s->tcpr); - /* ??? Save/restore. */ - return s; -} - -typedef struct { - MemoryRegion iomem; - MemoryRegion iomem_p4; - MemoryRegion iomem_a7; - void *timer[3]; - int level[3]; - uint32_t tocr; - uint32_t tstr; - int feat; -} tmu012_state; - -static uint64_t tmu012_read(void *opaque, hwaddr offset, - unsigned size) -{ - tmu012_state *s =3D (tmu012_state *)opaque; - -#ifdef DEBUG_TIMER - printf("tmu012_read 0x%lx\n", (unsigned long) offset); -#endif - - if (offset >=3D 0x20) { - if (!(s->feat & TMU012_FEAT_3CHAN)) - hw_error("tmu012_write: Bad channel offset %x\n", (int)offset); - return sh_timer_read(s->timer[2], offset - 0x20); - } - - if (offset >=3D 0x14) - return sh_timer_read(s->timer[1], offset - 0x14); - - if (offset >=3D 0x08) - return sh_timer_read(s->timer[0], offset - 0x08); - - if (offset =3D=3D 4) - return s->tstr; - - if ((s->feat & TMU012_FEAT_TOCR) && offset =3D=3D 0) - return s->tocr; - - hw_error("tmu012_write: Bad offset %x\n", (int)offset); - return 0; -} - -static void tmu012_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - tmu012_state *s =3D (tmu012_state *)opaque; - -#ifdef DEBUG_TIMER - printf("tmu012_write 0x%lx 0x%08x\n", (unsigned long) offset, value); -#endif - - if (offset >=3D 0x20) { - if (!(s->feat & TMU012_FEAT_3CHAN)) - hw_error("tmu012_write: Bad channel offset %x\n", (int)offset); - sh_timer_write(s->timer[2], offset - 0x20, value); - return; - } - - if (offset >=3D 0x14) { - sh_timer_write(s->timer[1], offset - 0x14, value); - return; - } - - if (offset >=3D 0x08) { - sh_timer_write(s->timer[0], offset - 0x08, value); - return; - } - - if (offset =3D=3D 4) { - sh_timer_start_stop(s->timer[0], value & (1 << 0)); - sh_timer_start_stop(s->timer[1], value & (1 << 1)); - if (s->feat & TMU012_FEAT_3CHAN) - sh_timer_start_stop(s->timer[2], value & (1 << 2)); - else - if (value & (1 << 2)) - hw_error("tmu012_write: Bad channel\n"); - - s->tstr =3D value; - return; - } - - if ((s->feat & TMU012_FEAT_TOCR) && offset =3D=3D 0) { - s->tocr =3D value & (1 << 0); - } -} - -static const MemoryRegionOps tmu012_ops =3D { - .read =3D tmu012_read, - .write =3D tmu012_write, - .endianness =3D DEVICE_NATIVE_ENDIAN, -}; - -void tmu012_init(MemoryRegion *sysmem, hwaddr base, - int feat, uint32_t freq, - qemu_irq ch0_irq, qemu_irq ch1_irq, - qemu_irq ch2_irq0, qemu_irq ch2_irq1) -{ - tmu012_state *s; - int timer_feat =3D (feat & TMU012_FEAT_EXTCLK) ? TIMER_FEAT_EXTCLK : 0; - - s =3D (tmu012_state *)g_malloc0(sizeof(tmu012_state)); - s->feat =3D feat; - s->timer[0] =3D sh_timer_init(freq, timer_feat, ch0_irq); - s->timer[1] =3D sh_timer_init(freq, timer_feat, ch1_irq); - if (feat & TMU012_FEAT_3CHAN) - s->timer[2] =3D sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT, - ch2_irq0); /* ch2_irq1 not supported */ - - memory_region_init_io(&s->iomem, NULL, &tmu012_ops, s, - "timer", 0x100000000ULL); - - memory_region_init_alias(&s->iomem_p4, NULL, "timer-p4", - &s->iomem, 0, 0x1000); - memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4); - - memory_region_init_alias(&s->iomem_a7, NULL, "timer-a7", - &s->iomem, 0, 0x1000); - memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7); - /* ??? Save/restore. */ -} --=20 2.20.1