From patchwork Wed Jun 23 12:34:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 12339787 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 125C7C4743C for ; Wed, 23 Jun 2021 12:42:14 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 84DF961075 for ; Wed, 23 Jun 2021 12:42:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 84DF961075 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:51558 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lw2Cq-00015f-JS for qemu-devel@archiver.kernel.org; Wed, 23 Jun 2021 08:42:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51018) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lw25O-0008GV-1v for qemu-devel@nongnu.org; Wed, 23 Jun 2021 08:34:30 -0400 Received: from mail07.asahi-net.or.jp ([202.224.55.47]:40175) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lw25K-0000s0-GD for qemu-devel@nongnu.org; Wed, 23 Jun 2021 08:34:29 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail07.asahi-net.or.jp (Postfix) with ESMTPA id CB81FC1C68; Wed, 23 Jun 2021 21:34:22 +0900 (JST) Received: from yo-satoh-debian.localdomain (z215167.dynamic.ppp.asahi-net.or.jp [110.4.215.167]) by sakura.ysato.name (Postfix) with ESMTPSA id 208401C063E; Wed, 23 Jun 2021 21:34:22 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 1/3] hw/timer: Add renesas_timer. Date: Wed, 23 Jun 2021 21:34:14 +0900 Message-Id: <20210623123416.60038-2-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210623123416.60038-1-ysato@users.sourceforge.jp> References: <20210623123416.60038-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 Received-SPF: softfail client-ip=202.224.55.47; envelope-from=ysato@users.sourceforge.jp; helo=mail07.asahi-net.or.jp X-Spam_score_int: -11 X-Spam_score: -1.2 X-Spam_bar: - X-Spam_report: (-1.2 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665 autolearn=no autolearn_force=no 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Renesas MCU / SoC have timer modules with similar functionality. SH4-TMU 32bit count down timer. RX-CMT 16bit compare match timer. Signed-off-by: Yoshinori Sato --- include/hw/timer/renesas_timer.h | 89 ++++++ hw/timer/renesas_timer.c | 532 +++++++++++++++++++++++++++++++ hw/timer/Kconfig | 3 +- hw/timer/meson.build | 1 + 4 files changed, 624 insertions(+), 1 deletion(-) 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_timer.h new file mode 100644 index 0000000000..dc0711ba83 --- /dev/null +++ b/include/hw/timer/renesas_timer.h @@ -0,0 +1,89 @@ +/* + * Renesas Timer unit Object + * + * Copyright (c) 2021 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" +#include "hw/ptimer.h" + +#define TYPE_RENESAS_TIMER_BASE "renesas-timer" +OBJECT_DECLARE_TYPE(RenesasTimerBaseState, RenesasTimerBaseClass, + RENESAS_TIMER_BASE) +#define TYPE_RENESAS_CMT "renesas-cmt" +OBJECT_DECLARE_TYPE(RenesasCMTState, RenesasCMTClass, + RENESAS_CMT) +#define TYPE_RENESAS_TMU "renesas-tmu" +OBJECT_DECLARE_TYPE(RenesasTMUState, RenesasTMUClass, + RENESAS_TMU) + +enum { + TIMER_CH_CMT = 2, + TIMER_CH_TMU = 3, +}; + +enum { + CMT_NR_IRQ = 1 * TIMER_CH_CMT, +}; + +enum { + TIMER_START = 1, + TIMER_STOP = 0, +}; + +struct RenesasTimerBaseState; + +struct rtimer_ch { + uint16_t ctrl; + qemu_irq irq; + ptimer_state *timer; + bool start; + struct RenesasTimerBaseState *tmrp; +}; + +typedef struct RenesasTimerBaseState { + SysBusDevice parent_obj; + + uint64_t input_freq; + MemoryRegion memory; + + struct rtimer_ch ch[TIMER_CH_TMU]; + int num_ch; + int unit; +} RenesasTimerBaseState; + +typedef struct RenesasCMTState { + RenesasTimerBaseState parent_obj; +} RenesasCMTState; + +typedef struct RenesasTMUState { + RenesasTimerBaseState parent_obj; + uint8_t tocr; + MemoryRegion memory_p4; + MemoryRegion memory_a7; +} RenesasTMUState; + +typedef struct RenesasTimerBaseClass { + SysBusDeviceClass parent; + int (*divrate)(RenesasTimerBaseState *tmr, int ch); + void (*timer_event)(void *opaque); + int64_t (*convert_count)(int64_t val, ptimer_state *t); + void (*update_clk)(RenesasTimerBaseState *tmr, int ch); +} RenesasTimerBaseClass; + +typedef struct RenesasCMTClass { + RenesasTimerBaseClass parent; +} RenesasCMTClass; + +typedef struct RenesasTMUClass { + RenesasTimerBaseClass parent; + void (*p_update_clk)(RenesasTimerBaseState *tmr, int ch); +} RenesasTMUClass; + +#endif diff --git a/hw/timer/renesas_timer.c b/hw/timer/renesas_timer.c new file mode 100644 index 0000000000..8fdb25a41d --- /dev/null +++ b/hw/timer/renesas_timer.c @@ -0,0 +1,532 @@ +/* + * Renesas 16bit/32bit Compare-match timer (CMT/TMU) + * + * 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) 2021 Yoshinori Sato + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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 for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu-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(CMSTR, 0) +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) + +static int cmt_div(RenesasTimerBaseState *tmr, int ch) +{ + return 8 << (2 * FIELD_EX16(tmr->ch[ch].ctrl, CMCR, CKS)); +} + +static int tmu_div(RenesasTimerBaseState *tmr, int ch) +{ + if (FIELD_EX16(tmr->ch[ch].ctrl, TCR, TPSC) <= 5) { + return 4 << (2 * FIELD_EX16(tmr->ch[ch].ctrl, TCR, TPSC)); + } else { + return 0; + } + +} + +static void cmt_timer_event(void *opaque) +{ + struct rtimer_ch *ch = opaque; + if (FIELD_EX16(ch->ctrl, CMCR, CMIE)) { + qemu_irq_pulse(ch->irq); + } +} + +static void tmu_timer_event(void *opaque) +{ + struct rtimer_ch *ch = opaque; + if (!FIELD_EX16(ch->ctrl, TCR, UNF)) { + ch->ctrl = FIELD_DP16(ch->ctrl, TCR, UNF, 1); + qemu_set_irq(ch->irq, FIELD_EX16(ch->ctrl, TCR, UNIE)); + } +} + +static int64_t downcount(int64_t val, ptimer_state *t) +{ + return val; +} + +static int64_t upcount(int64_t val, ptimer_state *t) +{ + int64_t limit; + limit = ptimer_get_limit(t); + return limit - val; +} + +static void tmr_start_stop(RenesasTimerBaseState *tmr, int ch, int st) +{ + ptimer_transaction_begin(tmr->ch[ch].timer); + switch (st) { + case TIMER_STOP: + ptimer_stop(tmr->ch[ch].timer); + tmr->ch[ch].start = false; + break; + case TIMER_START: + ptimer_run(tmr->ch[ch].timer, 0); + tmr->ch[ch].start = true; + break; + } + ptimer_transaction_commit(tmr->ch[ch].timer); +} + +static uint64_t read_tstr(RenesasTimerBaseState *tmr) +{ + uint64_t ret = 0; + int ch; + for (ch = 0; ch < tmr->num_ch; ch++) { + ret = deposit64(ret, ch, 1, tmr->ch[ch].start); + } + return ret; +} + +static void update_clk(RenesasTimerBaseState *tmr, int ch) +{ + RenesasTimerBaseClass *tc = RENESAS_TIMER_BASE_GET_CLASS(tmr); + int t; + ptimer_state *p; + t = tc->divrate(tmr, ch); + p = tmr->ch[ch].timer; + ptimer_transaction_begin(p); + if (t > 0) { + ptimer_set_freq(p, tmr->input_freq / t); + } else { + ptimer_stop(p); + } + ptimer_transaction_commit(p); +} + +static void tmu_update_clk(RenesasTimerBaseState *tmr, int ch) +{ + /* Clock setting validation */ + int tpsc = FIELD_EX16(tmr->ch[ch].ctrl, TCR, TPSC); + switch (tpsc) { + case 5: + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_timer: Invalid TPSC valule %d.\n", tpsc); + break; + case 6: + case 7: + qemu_log_mask(LOG_UNIMP, + "renesas_timer: External clock not implemented.\n"); + break; + } + /* Interrupt clear */ + if (FIELD_EX16(tmr->ch[ch].ctrl, TCR, UNF) == 0) { + qemu_set_irq(tmr->ch[ch].irq, 0); + } + update_clk(tmr, ch); +} + +static uint64_t channel_read(RenesasTimerBaseState *tmr, int ch, int reg) +{ + RenesasTimerBaseClass *tc = RENESAS_TIMER_BASE_GET_CLASS(tmr); + ptimer_state *p = tmr->ch[ch].timer; + switch (reg) { + case R_TCR: + return tmr->ch[ch].ctrl; + case R_TCNT: + return tc->convert_count(ptimer_get_count(p), p); + case R_TCOR: + return ptimer_get_limit(p); + } + return UINT64_MAX; +} + +static uint64_t cmt_read(void *opaque, hwaddr addr, unsigned size) +{ + RenesasCMTState *cmt = RENESAS_CMT(opaque); + int ch, reg; + + /* +0 - CMSTR (TSTR) */ + /* +2 - CMCR0 (TCR) */ + /* +4 - CMCNT0 (TCNT) */ + /* +6 - CMCOR0 (TCOR) */ + /* +8 - CMCR1 (TCR) */ + /* +10 - CMCNT1 (TCNT) */ + /* +12 - CMCOR1 (TCOR) */ + addr /= 2; + if (addr == R_CMSTR) { + return read_tstr(RENESAS_TIMER_BASE(cmt)); + } else { + ch = addr / 4; + if (addr < 4) { + /* skip CMSTR */ + addr--; + } + reg = 2 - (addr % 4); + return channel_read(RENESAS_TIMER_BASE(cmt), ch, reg); + } +} + +static uint64_t tmu_read(void *opaque, hwaddr addr, unsigned size) +{ + RenesasTMUState *tmu = RENESAS_TMU(opaque); + RenesasTimerBaseState *tmr = RENESAS_TIMER_BASE(tmu); + int ch = -1, reg = -1; + + /* +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->unit != 0 && addr >= 32) { + /* UNIT1 channel2 is not exit */ + qemu_log_mask(LOG_UNIMP, "renesas_timer: Register 0x%" + HWADDR_PRIX " not implemented\n", addr); + return UINT64_MAX; + } + addr /= 4; + switch (addr) { + case R_TOCR: + return tmu->tocr; + case R_TSTR: + return read_tstr(RENESAS_TIMER_BASE(tmu)); + case R_TCPR: + qemu_log_mask(LOG_UNIMP, + "renesas_timer: Input capture not implemented.\n"); + return UINT64_MAX; + default: + ch = (addr - 2) / 3; + reg = (addr - 2) % 3 + 2; + return channel_read(RENESAS_TIMER_BASE(tmu), ch, reg); + } +} + +static void write_tstr(RenesasTimerBaseState *tmr, uint16_t val) +{ + int ch; + for (ch = 0; ch < tmr->num_ch; ch++) { + tmr_start_stop(tmr, ch, extract16(val, ch, 1)); + } +} + +static void write_tcr(RenesasTimerBaseState *tmr, int ch, + uint16_t val, uint16_t regmask) +{ + RenesasTimerBaseClass *tc = RENESAS_TIMER_BASE_GET_CLASS(tmr); + tmr->ch[ch].ctrl |= (regmask & 0x00ff); + tmr->ch[ch].ctrl &= val & regmask; + tc->update_clk(tmr, ch); +} + +static void channel_write(RenesasTimerBaseState *tmr, int ch, + int reg, uint64_t val) +{ + RenesasTimerBaseClass *tc = RENESAS_TIMER_BASE_GET_CLASS(tmr); + ptimer_state *t; + t = tmr->ch[ch].timer; + ptimer_transaction_begin(t); + switch (reg) { + case R_TCNT: + ptimer_set_count(t, tc->convert_count(val, t)); + break; + case R_TCOR: + ptimer_set_limit(t, val, 0); + break; + default: + g_assert_not_reached(); + } + ptimer_transaction_commit(t); +} + +static void cmt_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ + RenesasTimerBaseState *tmr = RENESAS_TIMER_BASE(opaque); + int ch, reg; + uint16_t mask; + + addr /= 2; + if (addr == R_CMSTR) { + write_tstr(tmr, val); + } else { + ch = addr / 4; + if (addr < 4) { + /* skip CMSTR */ + addr--; + } + reg = (2 - (addr % 4)) + 2; + if (reg == R_TCR) { + /* bit7 always 1 */ + val |= 0x0080; + mask = 0; + mask = FIELD_DP16(mask, CMCR, CKS, 3); + mask = FIELD_DP16(mask, CMCR, CMIE, 1); + write_tcr(RENESAS_TIMER_BASE(tmr), ch, val, mask); + } else { + channel_write(RENESAS_TIMER_BASE(tmr), ch, reg, val); + } + } +} + +static void tmu_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) +{ + RenesasTMUState *tmu = RENESAS_TMU(opaque); + RenesasTimerBaseState *tmr = RENESAS_TIMER_BASE(tmu); + + int ch, reg; + uint16_t tcr_mask; + + if (tmr->unit != 0 && addr >= 32) { + /* UNIT1 channel2 is not exit */ + qemu_log_mask(LOG_UNIMP, "renesas_timer: Register 0x%" + HWADDR_PRIX " not implemented\n", addr); + return; + } + addr /= 4; + switch (addr) { + case R_TOCR: + tmu->tocr = FIELD_DP8(tmu->tocr, TOCR, TCOE, + FIELD_EX8(val, TOCR, TCOE)); + break; + case R_TSTR: + write_tstr(tmr, val); + break; + case R_TCPR: + qemu_log_mask(LOG_GUEST_ERROR, + "renesas_timer: TCPR is read only.\n"); + break; + default: + ch = (addr - 2) / 3; + reg = (addr - 2) % 3 + 2; + if (reg == R_TCR) { + tcr_mask = 0; + tcr_mask = FIELD_DP16(tcr_mask, TCR, TPSC, 7); + tcr_mask = FIELD_DP16(tcr_mask, TCR, UNIE, 1); + tcr_mask = FIELD_DP16(tcr_mask, TCR, UNF, 1); + if (tmr->unit == 0) { + tcr_mask = FIELD_DP16(tcr_mask, TCR, CKEG, 3); + if (ch == 2) { + tcr_mask = FIELD_DP16(tcr_mask, TCR, ICPE, 3); + tcr_mask = FIELD_DP16(tcr_mask, TCR, ICPF, 1); + } + } + write_tcr(tmr, ch, val, tcr_mask); + } else { + channel_write(tmr, ch, reg, val); + } + break; + } +} + +static const MemoryRegionOps cmt_ops = { + .write = cmt_write, + .read = cmt_read, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 2, + .max_access_size = 2, + }, +}; + +static const MemoryRegionOps tmu_ops = { + .write = tmu_write, + .read = tmu_read, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 2, + .max_access_size = 4, + }, +}; + +static void timer_base_realize(RenesasTimerBaseState *tmr, int num_ch) +{ + RenesasTimerBaseClass *tc = RENESAS_TIMER_BASE_GET_CLASS(tmr); + int i; + tmr->num_ch = num_ch; + for (i = 0; i < num_ch; i++) { + tmr->ch[i].timer = ptimer_init(tc->timer_event, &tmr->ch[i], 0); + } +} + +static void cmt_realize(DeviceState *dev, Error **errp) +{ + RenesasCMTState *cmt = RENESAS_CMT(dev); + RenesasTimerBaseState *tmr = RENESAS_TIMER_BASE(cmt); + int i; + + timer_base_realize(tmr, TIMER_CH_CMT); + + for (i = 0; i < TIMER_CH_CMT; i++) { + ptimer_transaction_begin(tmr->ch[i].timer); + ptimer_set_limit(tmr->ch[i].timer, 0xffff, 0); + ptimer_transaction_commit(tmr->ch[i].timer); + update_clk(tmr, i); + } +} + +static void cmt_init(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + RenesasCMTState *cmt = RENESAS_CMT(obj); + RenesasTimerBaseState *tmr = RENESAS_TIMER_BASE(cmt); + int i; + + memory_region_init_io(&tmr->memory, obj, &cmt_ops, + tmr, "renesas-cmt", 0x10); + sysbus_init_mmio(d, &tmr->memory); + + for (i = 0; i < TIMER_CH_CMT; i++) { + sysbus_init_irq(d, &tmr->ch[i].irq); + } +} + +static void tmu_realize(DeviceState *dev, Error **errp) +{ + RenesasTMUState *tmu = RENESAS_TMU(dev); + RenesasTimerBaseState *tmr = RENESAS_TIMER_BASE(tmu); + int i; + int num_ch; + + /* Unit0 have 3ch, Unit1 have 2ch */ + num_ch = TIMER_CH_TMU - tmr->unit; + timer_base_realize(tmr, num_ch); + for (i = 0; i < num_ch; i++) { + ptimer_transaction_begin(tmr->ch[i].timer); + ptimer_set_limit(tmr->ch[i].timer, 0xffffffff, 0); + ptimer_transaction_commit(tmr->ch[i].timer); + update_clk(tmr, i); + } +} + +static void tmu_init(Object *obj) +{ + SysBusDevice *d = SYS_BUS_DEVICE(obj); + RenesasTimerBaseState *tmr = RENESAS_TIMER_BASE(obj); + RenesasTMUState *tmu = RENESAS_TMU(obj); + int i; + + memory_region_init_io(&tmr->memory, obj, &tmu_ops, + tmr, "renesas-tmu", 0x30); + sysbus_init_mmio(d, &tmr->memory); + memory_region_init_alias(&tmu->memory_p4, NULL, "renesas-tmu-p4", + &tmr->memory, 0, 0x30); + sysbus_init_mmio(d, &tmu->memory_p4); + memory_region_init_alias(&tmu->memory_a7, NULL, "renesas-tmu-a7", + &tmr->memory, 0, 0x30); + sysbus_init_mmio(d, &tmu->memory_a7); + for (i = 0; i < TIMER_CH_TMU; i++) { + sysbus_init_irq(d, &tmr->ch[i].irq); + } +} + +static Property renesas_timer_properties[] = { + DEFINE_PROP_INT32("unit", RenesasTimerBaseState, unit, 0), + DEFINE_PROP_UINT64("input-freq", RenesasTimerBaseState, input_freq, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void renesas_timer_base_class_init(ObjectClass *klass, void *data) +{ + RenesasTimerBaseClass *base = RENESAS_TIMER_BASE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + base->update_clk = update_clk; + device_class_set_props(dc, renesas_timer_properties); +} + +static void cmt_class_init(ObjectClass *klass, void *data) +{ + RenesasTimerBaseClass *base = RENESAS_TIMER_BASE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + base->divrate = cmt_div; + base->timer_event = cmt_timer_event; + base->convert_count = upcount; + base->update_clk = update_clk; + dc->realize = cmt_realize; +} + +static void tmu_class_init(ObjectClass *klass, void *data) +{ + RenesasTimerBaseClass *base = RENESAS_TIMER_BASE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + base->divrate = tmu_div; + base->timer_event = tmu_timer_event; + base->convert_count = downcount; + base->update_clk = tmu_update_clk; + dc->realize = tmu_realize; +} + +static const TypeInfo renesas_timer_info[] = { + { + .name = TYPE_RENESAS_TIMER_BASE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(RenesasTimerBaseState), + .class_init = renesas_timer_base_class_init, + .class_size = sizeof(RenesasTimerBaseClass), + .abstract = true, + }, + { + .name = TYPE_RENESAS_CMT, + .parent = TYPE_RENESAS_TIMER_BASE, + .instance_size = sizeof(RenesasCMTState), + .instance_init = cmt_init, + .class_init = cmt_class_init, + .class_size = sizeof(RenesasCMTClass), + }, + { + .name = TYPE_RENESAS_TMU, + .parent = TYPE_RENESAS_TIMER_BASE, + .instance_size = sizeof(RenesasTMUState), + .instance_init = tmu_init, + .class_init = tmu_class_init, + .class_size = sizeof(RenesasTMUClass), + }, +}; + +DEFINE_TYPES(renesas_timer_info) diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig index bac2511715..9324ca7c6f 100644 --- a/hw/timer/Kconfig +++ b/hw/timer/Kconfig @@ -43,8 +43,9 @@ config SH_TIMER config RENESAS_TMR bool -config RENESAS_CMT +config RENESAS_TIMER bool + select PTIMER config SSE_COUNTER bool diff --git a/hw/timer/meson.build b/hw/timer/meson.build index 157f540ecd..9019dce993 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -33,5 +33,6 @@ softmmu_ss.add(when: 'CONFIG_SSE_COUNTER', if_true: files('sse-counter.c')) softmmu_ss.add(when: 'CONFIG_SSE_TIMER', if_true: files('sse-timer.c')) softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c')) softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c')) +softmmu_ss.add(when: 'CONFIG_RENESAS_TIMER', if_true: files('renesas_timer.c')) specific_ss.add(when: 'CONFIG_AVR_TIMER16', if_true: files('avr_timer16.c')) From patchwork Wed Jun 23 12:34:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 12339773 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DC218C4743C for ; Wed, 23 Jun 2021 12:36:59 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5040C61075 for ; Wed, 23 Jun 2021 12:36:59 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5040C61075 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:40976 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lw27m-00026D-Fh for qemu-devel@archiver.kernel.org; Wed, 23 Jun 2021 08:36:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51000) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lw25M-0008Cs-Mu for qemu-devel@nongnu.org; Wed, 23 Jun 2021 08:34:28 -0400 Received: from mail07.asahi-net.or.jp ([202.224.55.47]:40176) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lw25K-0000rz-I6 for qemu-devel@nongnu.org; Wed, 23 Jun 2021 08:34:28 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail07.asahi-net.or.jp (Postfix) with ESMTPA id E796EC1C90; Wed, 23 Jun 2021 21:34:22 +0900 (JST) Received: from yo-satoh-debian.localdomain (z215167.dynamic.ppp.asahi-net.or.jp [110.4.215.167]) by sakura.ysato.name (Postfix) with ESMTPSA id 6A18E1C0698; Wed, 23 Jun 2021 21:34:22 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 2/3] hw/rx: rx62n switch renesas_timer. Date: Wed, 23 Jun 2021 21:34:15 +0900 Message-Id: <20210623123416.60038-3-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210623123416.60038-1-ysato@users.sourceforge.jp> References: <20210623123416.60038-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 Received-SPF: softfail client-ip=202.224.55.47; envelope-from=ysato@users.sourceforge.jp; helo=mail07.asahi-net.or.jp X-Spam_score_int: -11 X-Spam_score: -1.2 X-Spam_bar: - X-Spam_report: (-1.2 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665 autolearn=no autolearn_force=no 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Yoshinori Sato --- include/hw/rx/rx62n.h | 4 ++-- hw/rx/Kconfig | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/hw/rx/rx62n.h b/include/hw/rx/rx62n.h index 3ed80dba0d..c35bf3998c 100644 --- a/include/hw/rx/rx62n.h +++ b/include/hw/rx/rx62n.h @@ -27,7 +27,7 @@ #include "target/rx/cpu.h" #include "hw/intc/rx_icu.h" #include "hw/timer/renesas_tmr.h" -#include "hw/timer/renesas_cmt.h" +#include "hw/timer/renesas_timer.h" #include "hw/char/renesas_sci.h" #include "qemu/units.h" #include "qom/object.h" @@ -56,7 +56,7 @@ struct RX62NState { RXCPU cpu; RXICUState icu; RTMRState tmr[RX62N_NR_TMR]; - RCMTState cmt[RX62N_NR_CMT]; + RenesasCMTState cmt[RX62N_NR_CMT]; RSCIState sci[RX62N_NR_SCI]; MemoryRegion *sysmem; diff --git a/hw/rx/Kconfig b/hw/rx/Kconfig index 2b297c5a6a..f9cb892633 100644 --- a/hw/rx/Kconfig +++ b/hw/rx/Kconfig @@ -2,7 +2,7 @@ config RX62N_MCU bool select RX_ICU select RENESAS_TMR - select RENESAS_CMT + select RENESAS_TIMER select RENESAS_SCI config RX_GDBSIM From patchwork Wed Jun 23 12:34:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 12339785 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05A6BC4743C for ; Wed, 23 Jun 2021 12:39:23 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A67D56101D for ; Wed, 23 Jun 2021 12:39:22 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A67D56101D Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=users.sourceforge.jp Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:47122 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lw2A5-0006MY-S1 for qemu-devel@archiver.kernel.org; Wed, 23 Jun 2021 08:39:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:51002) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lw25M-0008DC-QQ for qemu-devel@nongnu.org; Wed, 23 Jun 2021 08:34:28 -0400 Received: from mail07.asahi-net.or.jp ([202.224.55.47]:40178) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lw25K-0000s2-IO for qemu-devel@nongnu.org; Wed, 23 Jun 2021 08:34:28 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail07.asahi-net.or.jp (Postfix) with ESMTPA id 03EF2C1C93; Wed, 23 Jun 2021 21:34:23 +0900 (JST) Received: from yo-satoh-debian.localdomain (z215167.dynamic.ppp.asahi-net.or.jp [110.4.215.167]) by sakura.ysato.name (Postfix) with ESMTPSA id A8FB21C06A2; Wed, 23 Jun 2021 21:34:22 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH 3/3] hw/sh4: sh7750 switch renesas_timer. Date: Wed, 23 Jun 2021 21:34:16 +0900 Message-Id: <20210623123416.60038-4-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210623123416.60038-1-ysato@users.sourceforge.jp> References: <20210623123416.60038-1-ysato@users.sourceforge.jp> MIME-Version: 1.0 Received-SPF: softfail client-ip=202.224.55.47; envelope-from=ysato@users.sourceforge.jp; helo=mail07.asahi-net.or.jp X-Spam_score_int: -11 X-Spam_score: -1.2 X-Spam_bar: - X-Spam_report: (-1.2 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665 autolearn=no autolearn_force=no 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Yoshinori Sato --- hw/sh4/sh7750.c | 32 +++++++++++++++++++++++++++++--- hw/sh4/Kconfig | 2 +- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c index d53a436d8c..bbebac8083 100644 --- a/hw/sh4/sh7750.c +++ b/hw/sh4/sh7750.c @@ -30,8 +30,10 @@ #include "sh7750_regs.h" #include "sh7750_regnames.h" #include "hw/sh4/sh_intc.h" -#include "hw/timer/tmu012.h" +#include "hw/timer/renesas_timer.h" #include "exec/exec-all.h" +#include "qapi/error.h" +#include "hw/qdev-properties.h" #define NB_DEVICES 4 @@ -752,6 +754,30 @@ static const MemoryRegionOps sh7750_mmct_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static void tmu012_init(MemoryRegion *sysmem, hwaddr base, + int unit, uint64_t freq, + qemu_irq ch0_irq, qemu_irq ch1_irq, + qemu_irq ch2_irq0, qemu_irq ch2_irq1) +{ + RenesasTMUState *tmu; + + tmu = RENESAS_TMU(qdev_new(TYPE_RENESAS_TMU)); + qdev_prop_set_uint32(DEVICE(tmu), "unit", unit); + qdev_prop_set_uint64(DEVICE(tmu), "input-freq", freq); + + sysbus_realize(SYS_BUS_DEVICE(tmu), &error_abort); + sysbus_connect_irq(SYS_BUS_DEVICE(tmu), 0, ch0_irq); + sysbus_connect_irq(SYS_BUS_DEVICE(tmu), 1, ch1_irq); + if (unit == 0) { + /* ch2_irq1 is not used. */ + sysbus_connect_irq(SYS_BUS_DEVICE(tmu), 2, ch2_irq0); + } + + sysbus_mmio_map(SYS_BUS_DEVICE(tmu), 0, base); + sysbus_mmio_map(SYS_BUS_DEVICE(tmu), 1, P4ADDR(base)); + sysbus_mmio_map(SYS_BUS_DEVICE(tmu), 2, A7ADDR(base)); +} + SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem) { SH7750State *s; @@ -817,7 +843,7 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem) s->intc.irqs[SCIF_BRI]); tmu012_init(sysmem, 0x1fd80000, - TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK, + 0, s->periph_freq, s->intc.irqs[TMU0], s->intc.irqs[TMU1], @@ -840,7 +866,7 @@ 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(sysmem, 0x1e100000, 1, s->periph_freq, s->intc.irqs[TMU3], s->intc.irqs[TMU4], NULL, NULL); diff --git a/hw/sh4/Kconfig b/hw/sh4/Kconfig index ab733a3f76..ee51b5e6ae 100644 --- a/hw/sh4/Kconfig +++ b/hw/sh4/Kconfig @@ -21,4 +21,4 @@ config SH7750 bool select SH_INTC select SH_SCI - select SH_TIMER + select RENESAS_TIMER