From patchwork Mon Sep 17 08:40:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 970455 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=greensocs.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=greensocs.com header.i=@greensocs.com header.b="1PW0guy9"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="j85TMfum"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="j85TMfum"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42DKZ33hd4z9sBv for ; Mon, 17 Sep 2018 18:49:47 +1000 (AEST) Received: from localhost ([::1]:34469 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1pE0-0003A0-Rp for incoming@patchwork.ozlabs.org; Mon, 17 Sep 2018 04:49:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46578) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p60-0006DE-0u for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1p5x-0005ep-Rw for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:27 -0400 Received: from greensocs.com ([193.104.36.180]:51711) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5o-0005TI-Vb; Mon, 17 Sep 2018 04:41:17 -0400 Received: from localhost (localhost [127.0.0.1]) by greensocs.com (Postfix) with ESMTP id E7958521A8F; Mon, 17 Sep 2018 10:41:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173668; bh=yXcTOLWy/8EQ+8IHt63EZg5+S9rmAT3jB0ZPL8xb6eE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=1PW0guy9gUCf7XKjlc3WopHZw3cn/93mOE+OuxNQLVcN+iOulpDKLKYUx+vDumYwh 8QjatBPvjcemTLXHU3PfBy8aDI70A9FUw7BWHQMmfVGZ1H1/eYf1SiMWbnGuIvAz6c JoNYsvraOPRVOB0VX1BTROrpezpcXmm2sJRxUFQs= X-Virus-Scanned: amavisd-new at greensocs.com Authentication-Results: gs-01.greensocs.com (amavisd-new); dkim=pass (1024-bit key) header.d=greensocs.com header.b=j85TMfum; dkim=pass (1024-bit key) header.d=greensocs.com header.b=j85TMfum Received: from greensocs.com ([127.0.0.1]) by localhost (gs-01.greensocs.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id kpt2irkeCKZr; Mon, 17 Sep 2018 10:41:08 +0200 (CEST) Received: by greensocs.com (Postfix, from userid 998) id F18622386FB; Mon, 17 Sep 2018 10:41:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173667; bh=yXcTOLWy/8EQ+8IHt63EZg5+S9rmAT3jB0ZPL8xb6eE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=j85TMfummaSltH6BzmJGb6T7D1vdGtSZ6SONTYZjnnyF/czacDu0+LimMmJn9H1+K CdabQmHD3wByjAKYalXo6XtLCQHb48Qqtxm7b326Po+Ych4FMnlHtiDEQk5BLvOlWs K9XVd//+2rK0Z03wzhdnUbwQmG7EXbgtQVicw+I8= Received: from kouign-amann.hive.antfield.fr (antfield.tima.u-ga.fr [147.171.129.253]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: damien.hedde@greensocs.com) by greensocs.com (Postfix) with ESMTPSA id 87E042387FF; Mon, 17 Sep 2018 10:41:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173667; bh=yXcTOLWy/8EQ+8IHt63EZg5+S9rmAT3jB0ZPL8xb6eE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=j85TMfummaSltH6BzmJGb6T7D1vdGtSZ6SONTYZjnnyF/czacDu0+LimMmJn9H1+K CdabQmHD3wByjAKYalXo6XtLCQHb48Qqtxm7b326Po+Ych4FMnlHtiDEQk5BLvOlWs K9XVd//+2rK0Z03wzhdnUbwQmG7EXbgtQVicw+I8= From: damien.hedde@greensocs.com To: qemu-devel@nongnu.org Date: Mon, 17 Sep 2018 10:40:07 +0200 Message-Id: <20180917084016.12750-2-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180917084016.12750-1-damien.hedde@greensocs.com> References: <20180917084016.12750-1-damien.hedde@greensocs.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 193.104.36.180 Subject: [Qemu-devel] [PATCH v4 01/10] hw/core/clock-port: introduce clock port objects X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, alistair@alistair23.me, mark.burton@greensocs.com, saipava@xilinx.com, qemu-arm@nongnu.org, Damien Hedde , pbonzini@redhat.com, luc.michel@greensocs.com, fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Damien Hedde Introduce clock port objects: ClockIn and ClockOut. Theses ports may be used to distribute a clock from a object to several other objects. They do not contain any state and serve only as intermediate to carry a ClockState which contains 2 fields: * an integer which represent the frequency in Hertz * a boolean which represent the reset status of the clock domain Both are independent: eg the reset can be asserted while the clock running and vice versa. A ClockIn may be connected to a ClockOut so that it receives update, through the callback, whenever the Clockout is updated using the ClockOut's set function. This is based on the original work of Frederic Konrad. Signed-off-by: Damien Hedde --- Makefile.objs | 1 + include/hw/clock-port.h | 153 ++++++++++++++++++++++++++++++++++++++++ hw/core/clock-port.c | 145 +++++++++++++++++++++++++++++++++++++ hw/core/Makefile.objs | 1 + hw/core/trace-events | 6 ++ 5 files changed, 306 insertions(+) create mode 100644 include/hw/clock-port.h create mode 100644 hw/core/clock-port.c create mode 100644 hw/core/trace-events diff --git a/Makefile.objs b/Makefile.objs index ce9c79235e..b29747075f 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -210,6 +210,7 @@ trace-events-subdirs += hw/audio trace-events-subdirs += hw/block trace-events-subdirs += hw/block/dataplane trace-events-subdirs += hw/char +trace-events-subdirs += hw/core trace-events-subdirs += hw/display trace-events-subdirs += hw/dma trace-events-subdirs += hw/hppa diff --git a/include/hw/clock-port.h b/include/hw/clock-port.h new file mode 100644 index 0000000000..2ab554c30e --- /dev/null +++ b/include/hw/clock-port.h @@ -0,0 +1,153 @@ +#ifndef CLOCK_PORT_H +#define CLOCK_PORT_H + +#include "qom/object.h" +#include "hw/qdev-core.h" +#include "qemu/queue.h" + +#define TYPE_CLOCK_PORT "clock-port" +#define CLOCK_PORT(obj) OBJECT_CHECK(ClockPort, (obj), TYPE_CLOCK_PORT) +#define TYPE_CLOCK_IN "clock-in" +#define CLOCK_IN(obj) OBJECT_CHECK(ClockIn, (obj), TYPE_CLOCK_IN) +#define TYPE_CLOCK_OUT "clock-out" +#define CLOCK_OUT(obj) OBJECT_CHECK(ClockOut, (obj), TYPE_CLOCK_OUT) + +typedef struct ClockState { + uint64_t frequency; /* frequency of the clock in Hz */ + bool domain_reset; /* flag indicating if clock domain is under reset */ +} ClockState; + +typedef void ClockCallback(void *opaque, ClockState *clk); + +typedef struct ClockPort { + /*< private >*/ + Object parent_obj; + /*< public >*/ + char *canonical_path; /* clock path shadow */ +} ClockPort; + +typedef struct ClockOut ClockOut; +typedef struct ClockIn ClockIn; + +struct ClockIn { + /*< private >*/ + ClockPort parent_obj; + /*< private >*/ + ClockOut *driver; /* clock output controlling this clock */ + ClockCallback *callback; /* local callback */ + void *callback_opaque; /* opaque argument for the callback */ + QLIST_ENTRY(ClockIn) sibling; /* entry in a followers list */ +}; + +struct ClockOut { + /*< private >*/ + ClockPort parent_obj; + /*< private >*/ + QLIST_HEAD(, ClockIn) followers; /* list of registered clocks */ +}; + +/* + * clock_setup_canonical_path: + * @clk: clock + * + * compute the canonical path of the clock (used by log messages) + */ +void clock_setup_canonical_path(ClockPort *clk); + +/** + * clock_add_callback: + * @clk: the clock to register the callback into + * @cb: the callback function + * @opaque: the argument to the callback + * + * Register a callback called on every clock update. + */ +void clock_set_callback(ClockIn *clk, ClockCallback *cb, void *opaque); + +/** + * clock_clear_callback: + * @clk: the clock to delete the callback from + * + * Unregister the callback registered with clock_set_callback. + */ +void clock_clear_callback(ClockIn *clk); + +/** + * clock_connect: + * @clkin: the drived clock. + * @clkout: the driving clock. + * + * Setup @clkout to drive @clkin: Any @clkout update will be propagated + * to @clkin. + */ +void clock_connect(ClockIn *clkin, ClockOut *clkout); + +/** + * clock_set: + * @clk: the clock to update. + * @state: the new clock's state. + * + * Update the @clk to the new @state. + * This change will be propagated through registered clock inputs. + */ +void clock_set(ClockOut *clk, ClockState *state); + +/** + * clock_state_get_frequency: + * @clk: a clock state + * + * @return: the current frequency of @clk in Hz. If @clk is NULL, return 0. + */ +static inline uint64_t clock_state_get_frequency(const ClockState *clk) +{ + return clk ? clk->frequency : 0; +} + +/** + * clock_state_is_enabled: + * @clk: a clock state + * + * @return: true if the clock is running. If @clk is NULL return false. + */ +static inline bool clock_state_is_enabled(const ClockState *clk) +{ + return clock_state_get_frequency(clk) != 0; +} + +/** + * clock_state_get_domain_reset: + * @clk: a clock state + * + * @return: true if the domain reset is asserted. If @clk is NULL return false. + */ +static inline bool clock_state_get_domain_reset(const ClockState *clk) +{ + return clk ? clk->domain_reset : false; +} + +/** + * clock_state_is_domain_running: + * @clk: a clock state + * + * @return: true if the clock is running and reset not asserted. If @clk is + * NULL return false. + */ +static inline bool clock_state_is_domain_running(const ClockState *clk) +{ + return clock_state_is_enabled(clk) && !clock_state_get_domain_reset(clk); +} + +/** + * clock_state_copy: + * @dst the clock state destination + * @src: the clock state source + * + * Transfer the source clock state into the destination. + */ +static inline void clock_state_copy(ClockState *dst, const ClockState *src) +{ + dst->frequency = clock_state_get_frequency(src); + dst->domain_reset = clock_state_get_domain_reset(src); +} + +#endif /* CLOCK_PORT_H */ diff --git a/hw/core/clock-port.c b/hw/core/clock-port.c new file mode 100644 index 0000000000..31c344328c --- /dev/null +++ b/hw/core/clock-port.c @@ -0,0 +1,145 @@ +/* + * Clock inputs and outputs + * + * Copyright GreenSocs 2016-2018 + * + * Authors: + * Frederic Konrad + * Damien Hedde + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/module.h" +#include "hw/clock-port.h" +#include "hw/qdev-core.h" +#include "migration/vmstate.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "trace.h" + +#define CLOCK_PATH(_clk) (_clk->parent_obj.canonical_path) + +void clock_setup_canonical_path(ClockPort *clk) +{ + g_free(clk->canonical_path); + clk->canonical_path = object_get_canonical_path(OBJECT(clk)); +} + +void clock_set_callback(ClockIn *clk, ClockCallback *cb, void *opaque) +{ + assert(clk); + + clk->callback = cb; + clk->callback_opaque = opaque; +} + +void clock_clear_callback(ClockIn *clk) +{ + clock_set_callback(clk, NULL, NULL); +} + +void clock_connect(ClockIn *clkin, ClockOut *clkout) +{ + assert(clkin && clkin->driver == NULL); + assert(clkout); + + trace_clock_connect(CLOCK_PATH(clkin), CLOCK_PATH(clkout)); + + QLIST_INSERT_HEAD(&clkout->followers, clkin, sibling); + clkin->driver = clkout; +} + +static void clock_disconnect(ClockIn *clk) +{ + if (clk->driver == NULL) { + return; + } + + trace_clock_disconnect(CLOCK_PATH(clk)); + + clk->driver = NULL; + QLIST_REMOVE(clk, sibling); +} + +void clock_set(ClockOut *clk, ClockState *state) +{ + ClockIn *follower; + trace_clock_update(CLOCK_PATH(clk), state->frequency, state->domain_reset); + + QLIST_FOREACH(follower, &clk->followers, sibling) { + trace_clock_update(CLOCK_PATH(follower), state->frequency, + state->domain_reset); + if (follower->callback) { + follower->callback(follower->callback_opaque, state); + } + } +} + +static void clock_port_finalizefn(Object *obj) +{ + ClockPort *clk = CLOCK_PORT(obj); + + g_free(clk->canonical_path); + clk->canonical_path = NULL; +} + +static void clock_out_initfn(Object *obj) +{ + ClockOut *clk = CLOCK_OUT(obj); + + QLIST_INIT(&clk->followers); +} + +static void clock_out_finalizefn(Object *obj) +{ + ClockOut *clk = CLOCK_OUT(obj); + ClockIn *follower, *next; + + /* clear our list of followers */ + QLIST_FOREACH_SAFE(follower, &clk->followers, sibling, next) { + clock_disconnect(follower); + } +} + +static void clock_in_finalizefn(Object *obj) +{ + ClockIn *clk = CLOCK_IN(obj); + + /* remove us from driver's followers list */ + clock_disconnect(clk); +} + +static const TypeInfo clock_port_info = { + .name = TYPE_CLOCK_PORT, + .parent = TYPE_OBJECT, + .abstract = true, + .instance_size = sizeof(ClockPort), + .instance_finalize = clock_port_finalizefn, +}; + +static const TypeInfo clock_out_info = { + .name = TYPE_CLOCK_OUT, + .parent = TYPE_CLOCK_PORT, + .instance_size = sizeof(ClockOut), + .instance_init = clock_out_initfn, + .instance_finalize = clock_out_finalizefn, +}; + +static const TypeInfo clock_in_info = { + .name = TYPE_CLOCK_IN, + .parent = TYPE_CLOCK_PORT, + .instance_size = sizeof(ClockIn), + .instance_finalize = clock_in_finalizefn, +}; + +static void clock_register_types(void) +{ + type_register_static(&clock_port_info); + type_register_static(&clock_in_info); + type_register_static(&clock_out_info); +} + +type_init(clock_register_types) diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index eb88ca979e..f7102121f4 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -6,6 +6,7 @@ common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o # irq.o needed for qdev GPIO handling: common-obj-y += irq.o common-obj-y += hotplug.o +common-obj-y += clock-port.o common-obj-$(CONFIG_SOFTMMU) += nmi.o common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o diff --git a/hw/core/trace-events b/hw/core/trace-events new file mode 100644 index 0000000000..a37fd78492 --- /dev/null +++ b/hw/core/trace-events @@ -0,0 +1,6 @@ +# See docs/devel/tracing.txt for syntax documentation. + +# hw/core/clock-port.c +clock_connect(const char *clk, const char *driver) "'%s' drived-by '%s'" +clock_disconnect(const char *clk) "'%s'" +clock_update(const char *clk, uint64_t freq, int reset) "'%s' frequency %" PRIu64 "Hz reset %d" From patchwork Mon Sep 17 08:40:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 970457 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=greensocs.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=greensocs.com header.i=@greensocs.com header.b="YryZPJ8F"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="IvQr9qio"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="IvQr9qio"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42DKdV3np2z9sBv for ; Mon, 17 Sep 2018 18:52:45 +1000 (AEST) Received: from localhost ([::1]:34485 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1pGq-0005NF-Kw for incoming@patchwork.ozlabs.org; Mon, 17 Sep 2018 04:52:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46574) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5z-0006D7-Tu for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1p5x-0005eY-Nl for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:27 -0400 Received: from greensocs.com ([193.104.36.180]:51712) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5o-0005TM-VJ; Mon, 17 Sep 2018 04:41:17 -0400 Received: from localhost (localhost [127.0.0.1]) by greensocs.com (Postfix) with ESMTP id 9CCD3521A91; Mon, 17 Sep 2018 10:41:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173669; bh=7jML7edMlStZNGGsFvTMJU10Sk7OgZFCX7UYyQJQtlI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=YryZPJ8F8aSV456wggIkXEY+vw7uDA5cOfoySNkRAJ91cVZxP9BgtFmRKQpnb/YPb WG9c94YRmCAb8rRADtr3Da2JJrRcGiQ996W0ORkb3WHyE3ViDmOY5qU5GIowtJ8IqA U1RT65NMfXfvybCRTiwo8aC6O5+4KhpcRu6KTzG4= X-Virus-Scanned: amavisd-new at greensocs.com Authentication-Results: gs-01.greensocs.com (amavisd-new); dkim=pass (1024-bit key) header.d=greensocs.com header.b=IvQr9qio; dkim=pass (1024-bit key) header.d=greensocs.com header.b=IvQr9qio Received: from greensocs.com ([127.0.0.1]) by localhost (gs-01.greensocs.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 09JOsOMu3Gz4; Mon, 17 Sep 2018 10:41:08 +0200 (CEST) Received: by greensocs.com (Postfix, from userid 998) id 615482387FF; Mon, 17 Sep 2018 10:41:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173668; bh=7jML7edMlStZNGGsFvTMJU10Sk7OgZFCX7UYyQJQtlI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=IvQr9qioO1H2SXJISrHTGoZnUqSLhzjTw2U7in4T7PAH1Fd351BnQ5kx1yOBflKAO 9Xa82Z2WvnXQeeYWUCTE6OxlzagggD24tUtUS+RgnnWi6iS2QbdkK6Wh07e0TklmXr whc1holDnnucxf7JYqkEOop/UpDnOtcroITmNAQ8= Received: from kouign-amann.hive.antfield.fr (antfield.tima.u-ga.fr [147.171.129.253]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: damien.hedde@greensocs.com) by greensocs.com (Postfix) with ESMTPSA id F2B5B443480; Mon, 17 Sep 2018 10:41:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173668; bh=7jML7edMlStZNGGsFvTMJU10Sk7OgZFCX7UYyQJQtlI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=IvQr9qioO1H2SXJISrHTGoZnUqSLhzjTw2U7in4T7PAH1Fd351BnQ5kx1yOBflKAO 9Xa82Z2WvnXQeeYWUCTE6OxlzagggD24tUtUS+RgnnWi6iS2QbdkK6Wh07e0TklmXr whc1holDnnucxf7JYqkEOop/UpDnOtcroITmNAQ8= From: damien.hedde@greensocs.com To: qemu-devel@nongnu.org Date: Mon, 17 Sep 2018 10:40:08 +0200 Message-Id: <20180917084016.12750-3-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180917084016.12750-1-damien.hedde@greensocs.com> References: <20180917084016.12750-1-damien.hedde@greensocs.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 193.104.36.180 Subject: [Qemu-devel] [PATCH v4 02/10] qdev: add clock input&output support to devices. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, alistair@alistair23.me, mark.burton@greensocs.com, saipava@xilinx.com, qemu-arm@nongnu.org, Damien Hedde , pbonzini@redhat.com, luc.michel@greensocs.com, fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Damien Hedde Add functions to easily add input or output clocks to a device. The clock port objects are added as children of the device. A function allows to connect two clocks together. It should be called by some toplevel to make a connection between 2 (sub-)devices. Also add a function which forwards a port to another device. This function allows, in the case of device composition, to expose a sub-device clock port as its own clock port. This is really an alias: when forwarding an input, only one callback can be registered on it since there is only one Clockin object behind all aliases. This is based on the original work of Frederic Konrad. Signed-off-by: Damien Hedde --- include/hw/qdev-clock.h | 62 ++++++++++++++++++ include/hw/qdev-core.h | 14 ++++ include/hw/qdev.h | 1 + hw/core/qdev-clock.c | 140 ++++++++++++++++++++++++++++++++++++++++ hw/core/qdev.c | 29 +++++++++ hw/core/Makefile.objs | 2 +- 6 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 include/hw/qdev-clock.h create mode 100644 hw/core/qdev-clock.c diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h new file mode 100644 index 0000000000..324eea6bcc --- /dev/null +++ b/include/hw/qdev-clock.h @@ -0,0 +1,62 @@ +#ifndef QDEV_CLOCK_H +#define QDEV_CLOCK_H + +#include "hw/clock-port.h" +#include "hw/qdev-core.h" +#include "qapi/error.h" + +/** + * qdev_init_clock_in: + * @dev: the device in which to add a clock + * @name: the name of the clock (can't be NULL). + * @callback: optional callback to be called on update or NULL. + * @opaque: argument for the callback + * @returns: a pointer to the newly added clock + * + * Add a input clock to device @dev as a clock named @name. + * This adds a child<> property. + * The callback will be called with @dev as opaque parameter. + */ +ClockIn *qdev_init_clock_in(DeviceState *dev, const char *name, + ClockCallback *callback, void *opaque); + +/** + * qdev_init_clock_out: + * @dev: the device to add a clock to + * @name: the name of the clock (can't be NULL). + * @callback: optional callback to be called on update or NULL. + * @returns: a pointer to the newly added clock + * + * Add a output clock to device @dev as a clock named @name. + * This adds a child<> property. + */ +ClockOut *qdev_init_clock_out(DeviceState *dev, const char *name); + +/** + * qdev_init_clock_forward: + * @dev: the device to forward the clock to + * @name: the name of the clock to be added (can't be NULL) + * @origin: the device which already has the clock + * @origin_name: the name of the clock in the src device + * + * Add a clock @name to @dev which forward to the clock @origin_name in @origin + */ +void qdev_init_clock_forward(DeviceState *dev, const char *name, + DeviceState *origin, const char *origin_name); + +/** + * qdev_clock_connect: + * @dev: the drived clock device. + * @name: the drived clock name. + * @driver: the driving clock device. + * @driver_name: the driving clock name. + * @errp: error report + * + * Setup @driver_name output clock of @driver to drive @name input clock of + * @dev. Errors are trigerred if clock does not exists + */ +void qdev_clock_connect(DeviceState *dev, const char *name, + DeviceState *driver, const char *driver_name, + Error **errp); + +#endif /* QDEV_CLOCK_H */ diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index f1fd0f8736..e6014d3a41 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -127,6 +127,19 @@ struct NamedGPIOList { QLIST_ENTRY(NamedGPIOList) node; }; +typedef struct NamedClockList NamedClockList; + +typedef struct ClockIn ClockIn; +typedef struct ClockOut ClockOut; + +struct NamedClockList { + char *name; + bool forward; + ClockIn *in; + ClockOut *out; + QLIST_ENTRY(NamedClockList) node; +}; + /** * DeviceState: * @realized: Indicates whether the device has been fully constructed. @@ -147,6 +160,7 @@ struct DeviceState { int hotplugged; BusState *parent_bus; QLIST_HEAD(, NamedGPIOList) gpios; + QLIST_HEAD(, NamedClockList) clocks; QLIST_HEAD(, BusState) child_bus; int num_child_bus; int instance_id_alias; diff --git a/include/hw/qdev.h b/include/hw/qdev.h index 5cb8b080a6..b031da7b41 100644 --- a/include/hw/qdev.h +++ b/include/hw/qdev.h @@ -4,5 +4,6 @@ #include "hw/hw.h" #include "hw/qdev-core.h" #include "hw/qdev-properties.h" +#include "hw/qdev-clock.h" #endif diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c new file mode 100644 index 0000000000..cb7dba3f75 --- /dev/null +++ b/hw/core/qdev-clock.c @@ -0,0 +1,140 @@ +/* + * Device's clock + * + * Copyright GreenSocs 2016-2018 + * + * Authors: + * Frederic Konrad + * Damien Hedde + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qom/object.h" +#include "hw/qdev-clock.h" +#include "qapi/error.h" + +static NamedClockList *qdev_init_clocklist(DeviceState *dev, const char *name, + bool forward) +{ + NamedClockList *ncl; + + /* + * The clock path will be computed by the device's realize function call. + * This is required to ensure the clock's canonical path is right and log + * messages are meaningfull. + */ + assert(name); + assert(!dev->realized); + + ncl = g_malloc0(sizeof(*ncl)); + ncl->name = g_strdup(name); + ncl->forward = forward; + + QLIST_INSERT_HEAD(&dev->clocks, ncl, node); + return ncl; +} + +ClockOut *qdev_init_clock_out(DeviceState *dev, const char *name) +{ + NamedClockList *ncl; + Object *clk; + + ncl = qdev_init_clocklist(dev, name, false); + + clk = object_new(TYPE_CLOCK_OUT); + + /* will fail if name already exists */ + object_property_add_child(OBJECT(dev), name, clk, &error_abort); + object_unref(clk); /* remove the initial ref made by object_new */ + + ncl->out = CLOCK_OUT(clk); + return ncl->out; +} + +ClockIn *qdev_init_clock_in(DeviceState *dev, const char *name, + ClockCallback *callback, void *opaque) +{ + NamedClockList *ncl; + Object *clk; + + ncl = qdev_init_clocklist(dev, name, false); + + clk = object_new(TYPE_CLOCK_IN); + /* + * the ref initialized by object_new will be cleared during dev finalize. + * It allows us to safely remove the callback. + */ + + /* will fail if name already exists */ + object_property_add_child(OBJECT(dev), name, clk, &error_abort); + + ncl->in = CLOCK_IN(clk); + if (callback) { + clock_set_callback(ncl->in, callback, opaque); + } + return ncl->in; +} + +static NamedClockList *qdev_get_clocklist(DeviceState *dev, const char *name) +{ + NamedClockList *ncl; + + QLIST_FOREACH(ncl, &dev->clocks, node) { + if (strcmp(name, ncl->name) == 0) { + return ncl; + } + } + + return NULL; +} + +void qdev_init_clock_forward(DeviceState *dev, const char *name, + DeviceState *origin, const char *origin_name) +{ + NamedClockList *original_ncl, *ncl; + Object **clk; + + assert(origin && origin_name); + + original_ncl = qdev_get_clocklist(origin, origin_name); + assert(original_ncl); /* clock must exist in origin */ + + ncl = qdev_init_clocklist(dev, name, true); + + if (ncl->out) { + clk = (Object **)&ncl->out; + } else { + clk = (Object **)&ncl->in; + } + + /* will fail if name already exists */ + object_property_add_link(OBJECT(dev), name, object_get_typename(*clk), + clk, NULL, OBJ_PROP_LINK_STRONG, &error_abort); +} + +void qdev_clock_connect(DeviceState *dev, const char *name, + DeviceState *driver, const char *driver_name, + Error **errp) +{ + NamedClockList *ncl, *drv_ncl; + + assert(dev && name); + assert(driver && driver_name); + + ncl = qdev_get_clocklist(dev, name); + if (!ncl || !ncl->in) { + error_setg(errp, "no input clock '%s' in device", name); + return; + } + + drv_ncl = qdev_get_clocklist(driver, driver_name); + if (!drv_ncl || !drv_ncl->out) { + error_setg(errp, "no output clock '%s' in driver", driver_name); + return; + } + + clock_connect(ncl->in , drv_ncl->out); +} diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 529b82de18..21a8b6b561 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -790,6 +790,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp) DeviceClass *dc = DEVICE_GET_CLASS(dev); HotplugHandler *hotplug_ctrl; BusState *bus; + NamedClockList *clk; Error *local_err = NULL; bool unattached_parent = false; static int unattached_count; @@ -846,6 +847,15 @@ static void device_set_realized(Object *obj, bool value, Error **errp) */ g_free(dev->canonical_path); dev->canonical_path = object_get_canonical_path(OBJECT(dev)); + QLIST_FOREACH(clk, &dev->clocks, node) { + if (clk->forward) { + continue; + } else if (clk->in != NULL) { + clock_setup_canonical_path(CLOCK_PORT(clk->in)); + } else { + clock_setup_canonical_path(CLOCK_PORT(clk->out)); + } + } if (qdev_get_vmsd(dev)) { if (vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev, @@ -972,6 +982,7 @@ static void device_initfn(Object *obj) (Object **)&dev->parent_bus, NULL, 0, &error_abort); QLIST_INIT(&dev->gpios); + QLIST_INIT(&dev->clocks); } static void device_post_init(Object *obj) @@ -983,6 +994,7 @@ static void device_post_init(Object *obj) static void device_finalize(Object *obj) { NamedGPIOList *ngl, *next; + NamedClockList *clk, *clk_next; DeviceState *dev = DEVICE(obj); @@ -996,6 +1008,23 @@ static void device_finalize(Object *obj) */ } + QLIST_FOREACH_SAFE(clk, &dev->clocks, node, clk_next) { + QLIST_REMOVE(clk, node); + if (!clk->forward && clk->in) { + /* + * if this clock is not forwarded, clk->in & clk->out are child of + * dev. + * At this point the properties and associated reference are + * already deleted but we kept a ref on clk->in to ensure we + * don't have a lost callback to a deleted device somewhere. + */ + clock_clear_callback(clk->in); + object_unref(OBJECT(clk->in)); + } + g_free(clk->name); + g_free(clk); + } + /* Only send event if the device had been completely realized */ if (dev->pending_deleted_event) { g_assert(dev->canonical_path); diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index f7102121f4..fc0505e716 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -1,5 +1,5 @@ # core qdev-related obj files, also used by *-user: -common-obj-y += qdev.o qdev-properties.o +common-obj-y += qdev.o qdev-properties.o qdev-clock.o common-obj-y += bus.o reset.o common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o From patchwork Mon Sep 17 08:40:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 970449 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=greensocs.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=greensocs.com header.i=@greensocs.com header.b="R9XNEVBZ"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="qzUPl1XI"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="SHxOE7MZ"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42DKRF6S2Pz9sBv for ; Mon, 17 Sep 2018 18:43:53 +1000 (AEST) Received: from localhost ([::1]:34434 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p8J-0007c6-9d for incoming@patchwork.ozlabs.org; Mon, 17 Sep 2018 04:43:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46485) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5x-0006AL-Kv for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1p5w-0005cR-Ew for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:25 -0400 Received: from greensocs.com ([193.104.36.180]:51713) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5o-0005TK-Vj; Mon, 17 Sep 2018 04:41:17 -0400 Received: from localhost (localhost [127.0.0.1]) by greensocs.com (Postfix) with ESMTP id 0BF4E521AB4; Mon, 17 Sep 2018 10:41:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173670; bh=AnN1kydemsdQzi0SUDrl/dMsn9qI3l7wu7DbVb6OtSs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=R9XNEVBZ7JcpgF64SEUTZdM2bInyKKrtiOaDLrkdhT/gRGQ/ReU4kp0rTns31EcKx cSp47tQyYcdQX3QVNcl2b+M/Sip5yEWCPzbBYSn0rzWlpTJWDAiJTJJ0mNcZEnGVz8 QI5LCopDIFtxFrJGYozYQwRtGG7o1+Sva3nBzczs= X-Virus-Scanned: amavisd-new at greensocs.com Authentication-Results: gs-01.greensocs.com (amavisd-new); dkim=pass (1024-bit key) header.d=greensocs.com header.b=qzUPl1XI; dkim=pass (1024-bit key) header.d=greensocs.com header.b=SHxOE7MZ Received: from greensocs.com ([127.0.0.1]) by localhost (gs-01.greensocs.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 5IJjXSQbtzCO; Mon, 17 Sep 2018 10:41:09 +0200 (CEST) Received: by greensocs.com (Postfix, from userid 998) id 00647443480; Mon, 17 Sep 2018 10:41:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173669; bh=AnN1kydemsdQzi0SUDrl/dMsn9qI3l7wu7DbVb6OtSs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=qzUPl1XIxbycVvBLcuzwH1EViyeO0cZgZr4GcN3ijmamggwf6c3zRygFlxqzF93oR sunXuvry41ZClLVQCo986WGJGGSeS+cvcUuj4qvli/qvcZyyQWPt/WDrHalw47iszB /+Cn0xAGrGeJ8rG/sj+5j65y5BRDZlu7J5exEioI= Received: from kouign-amann.hive.antfield.fr (antfield.tima.u-ga.fr [147.171.129.253]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: damien.hedde@greensocs.com) by greensocs.com (Postfix) with ESMTPSA id 64C77443483; Mon, 17 Sep 2018 10:41:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173668; bh=AnN1kydemsdQzi0SUDrl/dMsn9qI3l7wu7DbVb6OtSs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=SHxOE7MZcSfH0eQZ6qdFEEcFhsYgFrWWGccl3OIiZpqjDTVo7k208YPUi9bB2MXKn hmZJWe+beJDFybCDewoOT3E2j9vBJneOC2d+CgF9A0u/FWOprWa+cZQmPkCML7ghFd ne0lb38SE8yPqqu0VpiqBzy/28LnFZ7yQEWzkgjM= From: damien.hedde@greensocs.com To: qemu-devel@nongnu.org Date: Mon, 17 Sep 2018 10:40:09 +0200 Message-Id: <20180917084016.12750-4-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180917084016.12750-1-damien.hedde@greensocs.com> References: <20180917084016.12750-1-damien.hedde@greensocs.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 193.104.36.180 Subject: [Qemu-devel] [PATCH v4 03/10] qdev-monitor: print the device's clock with info qtree X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, alistair@alistair23.me, mark.burton@greensocs.com, saipava@xilinx.com, qemu-arm@nongnu.org, Damien Hedde , pbonzini@redhat.com, luc.michel@greensocs.com, fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Damien Hedde This prints the clocks attached to a DeviceState when using "info qtree" monitor command. For every clock, it displays the direction, the name and if the clock is forwarded. This is based on the original work of Frederic Konrad. Signed-off-by: Damien Hedde --- qdev-monitor.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/qdev-monitor.c b/qdev-monitor.c index 61e0300991..c6f07a49d2 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -682,6 +682,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) ObjectClass *class; BusState *child; NamedGPIOList *ngl; + NamedClockList *clk; qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)), dev->id ? dev->id : ""); @@ -696,6 +697,11 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) ngl->num_out); } } + QLIST_FOREACH(clk, &dev->clocks, node) { + qdev_printf("clock-%s \"%s\"%s\n", + clk->out ? "out" : "in", clk->name, + clk->forward ? " FW" : ""); + } class = object_get_class(OBJECT(dev)); do { qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent); From patchwork Mon Sep 17 08:40:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 970452 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=greensocs.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=greensocs.com header.i=@greensocs.com header.b="zKMSiVbp"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="34Lt9d1U"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="34Lt9d1U"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42DKV21TNNz9sCT for ; Mon, 17 Sep 2018 18:46:17 +1000 (AEST) Received: from localhost ([::1]:34449 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1pAd-00011F-4h for incoming@patchwork.ozlabs.org; Mon, 17 Sep 2018 04:46:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46501) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5x-0006Am-VO for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1p5w-0005ca-FJ for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:25 -0400 Received: from greensocs.com ([193.104.36.180]:51710) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5o-0005TH-Vi; Mon, 17 Sep 2018 04:41:17 -0400 Received: from localhost (localhost [127.0.0.1]) by greensocs.com (Postfix) with ESMTP id CF794521AB6; Mon, 17 Sep 2018 10:41:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173670; bh=ad+IoHRlAKMY+vuSKfg4+m9rK/Mw7VhSQZL3cL+Z0BM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=zKMSiVbporfQbWVMpm8LehmvQjYT2kngLpDsK5uuqk5lNaZIj4bgkoskwLdl1LNiq k+kHdC7FcJg6IxbGrrwGhxIIDxyGIhWIaWVuGEtxSR5lSm2T2SKcHzg3An47Wk6BaQ fxkN94a9ti+TnxDMHJGgJqZk8Fx48eEs+rdNujQ0= X-Virus-Scanned: amavisd-new at greensocs.com Authentication-Results: gs-01.greensocs.com (amavisd-new); dkim=pass (1024-bit key) header.d=greensocs.com header.b=34Lt9d1U; dkim=pass (1024-bit key) header.d=greensocs.com header.b=34Lt9d1U Received: from greensocs.com ([127.0.0.1]) by localhost (gs-01.greensocs.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id WEFZO5GAPU2j; Mon, 17 Sep 2018 10:41:10 +0200 (CEST) Received: by greensocs.com (Postfix, from userid 998) id 5983D2386FB; Mon, 17 Sep 2018 10:41:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173669; bh=ad+IoHRlAKMY+vuSKfg4+m9rK/Mw7VhSQZL3cL+Z0BM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=34Lt9d1Up3ApSRaVWLeDTG10VgQgIzNZvuK511Tbgf6fY2ekHelwjzx6xEOP2fTvc FkRpuAIbRL0ms8tKYwDiHG/dffy0SzVyvhmJya0kGcDoVEjFOuDaazr5VCyr8T0gcT CmrcjKezVrAvnuZfv6Gt8NPxPTLKLxMcNWhuZhNk= Received: from kouign-amann.hive.antfield.fr (antfield.tima.u-ga.fr [147.171.129.253]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: damien.hedde@greensocs.com) by greensocs.com (Postfix) with ESMTPSA id D871323878C; Mon, 17 Sep 2018 10:41:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173669; bh=ad+IoHRlAKMY+vuSKfg4+m9rK/Mw7VhSQZL3cL+Z0BM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=34Lt9d1Up3ApSRaVWLeDTG10VgQgIzNZvuK511Tbgf6fY2ekHelwjzx6xEOP2fTvc FkRpuAIbRL0ms8tKYwDiHG/dffy0SzVyvhmJya0kGcDoVEjFOuDaazr5VCyr8T0gcT CmrcjKezVrAvnuZfv6Gt8NPxPTLKLxMcNWhuZhNk= From: damien.hedde@greensocs.com To: qemu-devel@nongnu.org Date: Mon, 17 Sep 2018 10:40:10 +0200 Message-Id: <20180917084016.12750-5-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180917084016.12750-1-damien.hedde@greensocs.com> References: <20180917084016.12750-1-damien.hedde@greensocs.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 193.104.36.180 Subject: [Qemu-devel] [PATCH v4 04/10] qdev-clock: introduce an init array to ease the device construction X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, alistair@alistair23.me, mark.burton@greensocs.com, saipava@xilinx.com, qemu-arm@nongnu.org, Damien Hedde , pbonzini@redhat.com, luc.michel@greensocs.com, fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Damien Hedde Introduce a function and macro helpers to setup several clocks in a device from a static array description. An element of the array describes the clock (name and direction) as well as the related callback and an optional offset to store the created object pointer in the device state structure. The array must be terminated by a special element QDEV_CLOCK_END. This is based on the original work of Frederic Konrad. Signed-off-by: Damien Hedde --- include/hw/qdev-clock.h | 67 +++++++++++++++++++++++++++++++++++++++++ hw/core/qdev-clock.c | 26 ++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h index 324eea6bcc..a5da8878af 100644 --- a/include/hw/qdev-clock.h +++ b/include/hw/qdev-clock.h @@ -59,4 +59,71 @@ void qdev_clock_connect(DeviceState *dev, const char *name, DeviceState *driver, const char *driver_name, Error **errp); +/** + * ClockInitElem: + * @name: name of the clock (can't be NULL) + * @output: indicates whether the clock is input or output + * @callback: for inputs, optional callback to be called on clock's update + * with device as opaque + * @offset: optional offset to store the clock pointer in device'state + * structure (0 means unused) + */ +struct ClockPortInitElem { + const char *name; + bool output; + ClockCallback *callback; + size_t offset; +}; + +#define clock_offset_value(_type, _devstate, _field) \ + (offsetof(_devstate, _field) + \ + type_check(_type *, typeof_field(_devstate, _field))) + +#define QDEV_CLOCK(_output, _type, _devstate, _field, _callback) { \ + .name = (stringify(_field)), \ + .output = _output, \ + .callback = _callback, \ + .offset = clock_offset_value(_type, _devstate, _field), \ +} + +/** + * QDEV_CLOCK_(IN|OUT): + * @_devstate: structure type. @dev argument of qdev_init_clocks below must be + * a pointer to that same type. + * @_field: a field in @_devstate (must be ClockIn* or ClockOut*) + * @_callback: (for input only) callback (or NULL) to be called with the device + * state as argument + * + * The name of the clock will be derived from @_field + */ +#define QDEV_CLOCK_IN(_devstate, _field, _callback) \ + QDEV_CLOCK(false, ClockIn, _devstate, _field, _callback) + +#define QDEV_CLOCK_OUT(_devstate, _field) \ + QDEV_CLOCK(true, ClockOut, _devstate, _field, NULL) + +/** + * QDEV_CLOCK_IN_NOFIELD: + * @_name: name of the clock + * @_callback: callback (or NULL) to be called with the device state as argument + */ +#define QDEV_CLOCK_IN_NOFIELD(_name, _callback) { \ + .name = _name, \ + .output = false, \ + .callback = _callback, \ + .offset = 0, \ +} + +#define QDEV_CLOCK_END { .name = NULL } + +typedef struct ClockPortInitElem ClockPortInitArray[]; + +/** + * qdev_init_clocks: + * @dev: the device to add clocks + * @clocks: a QDEV_CLOCK_END-terminated array which contains the + * clocks information. + */ +void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks); + #endif /* QDEV_CLOCK_H */ diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c index cb7dba3f75..78d2509e04 100644 --- a/hw/core/qdev-clock.c +++ b/hw/core/qdev-clock.c @@ -138,3 +138,29 @@ void qdev_clock_connect(DeviceState *dev, const char *name, clock_connect(ncl->in , drv_ncl->out); } + +void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks) +{ + const struct ClockPortInitElem *elem; + + assert(dev); + assert(clocks); + + for (elem = &clocks[0]; elem->name != NULL; elem++) { + /* offset cannot be inside the DeviceState part */ + assert(elem->offset == 0 || elem->offset > sizeof(DeviceState)); + if (elem->output) { + ClockOut *clk; + clk = qdev_init_clock_out(dev, elem->name); + if (elem->offset) { + *(ClockOut **)(((void *) dev) + elem->offset) = clk; + } + } else { + ClockIn *clk; + clk = qdev_init_clock_in(dev, elem->name, elem->callback, dev); + if (elem->offset) { + *(ClockIn **)(((void *) dev) + elem->offset) = clk; + } + } + } +} From patchwork Mon Sep 17 08:40:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 970454 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=greensocs.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=greensocs.com header.i=@greensocs.com header.b="3PUygeru"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="aunUz5hp"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="jQppPchm"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42DKYh1tSXz9sBv for ; Mon, 17 Sep 2018 18:49:28 +1000 (AEST) Received: from localhost ([::1]:34468 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1pDh-0002zC-QN for incoming@patchwork.ozlabs.org; Mon, 17 Sep 2018 04:49:25 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46511) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5y-0006B2-8u for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1p5w-0005dZ-Oa for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:26 -0400 Received: from greensocs.com ([193.104.36.180]:51748) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5q-0005VQ-4g; Mon, 17 Sep 2018 04:41:18 -0400 Received: from localhost (localhost [127.0.0.1]) by greensocs.com (Postfix) with ESMTP id 3DA33521ABA; Mon, 17 Sep 2018 10:41:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173671; bh=2EcAqJ44LxLI9TwdNOnM07gw735X6yx02uZL+SgKdOE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=3PUygerumSdKfYKEdqyzM07INA5Nh0qvR8O/ZSRx9UqDu/cnXBT1TQiKMgJSnvPB4 6MNISOa/XdOnB7nBXdy4CxuFSk688QQ8UupmPFih4acwrJf2WRAVHo1P8V8RIgPRa+ yPCH4nQHlPmuhimPf17earuJK8y+lZ2csbV4CzGA= X-Virus-Scanned: amavisd-new at greensocs.com Authentication-Results: gs-01.greensocs.com (amavisd-new); dkim=pass (1024-bit key) header.d=greensocs.com header.b=aunUz5hp; dkim=pass (1024-bit key) header.d=greensocs.com header.b=jQppPchm Received: from greensocs.com ([127.0.0.1]) by localhost (gs-01.greensocs.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id S13w4oMlyNeL; Mon, 17 Sep 2018 10:41:10 +0200 (CEST) Received: by greensocs.com (Postfix, from userid 998) id 3917A2387FF; Mon, 17 Sep 2018 10:41:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173670; bh=2EcAqJ44LxLI9TwdNOnM07gw735X6yx02uZL+SgKdOE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=aunUz5hpNHSdFjHwQZMdEp52BKJf8A6NMAzDHG2SiTH23kwceYiZV2/8AWgiaakN1 EVk69+3rAo06b1xOmHPcHp/y7Z2DIC6SnFkV9HMqkzwyFwy4J8E8/8V4pL/5ps/Jg9 FGztBZpGtS6ZRf21Z2LXrmcke/fAbjdrMD6fCIw4= Received: from kouign-amann.hive.antfield.fr (antfield.tima.u-ga.fr [147.171.129.253]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: damien.hedde@greensocs.com) by greensocs.com (Postfix) with ESMTPSA id 59CFB443483; Mon, 17 Sep 2018 10:41:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173669; bh=2EcAqJ44LxLI9TwdNOnM07gw735X6yx02uZL+SgKdOE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=jQppPchmltnRwPxY0QDEcDGkZ1/4JNUnibEThjO97fbWxeHD/Psc1HoJLC/aXRGXt kfuSx6hLaqv1KD3YWY9GDRgje2raFJwtxaT/94cA6b57kUMwnuwkrK3IKywD5hHN4i 2yiJAqKYkQAlTCh2kfSGCYcCPXnM7QIRHQRivZrs= From: damien.hedde@greensocs.com To: qemu-devel@nongnu.org Date: Mon, 17 Sep 2018 10:40:11 +0200 Message-Id: <20180917084016.12750-6-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180917084016.12750-1-damien.hedde@greensocs.com> References: <20180917084016.12750-1-damien.hedde@greensocs.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 193.104.36.180 Subject: [Qemu-devel] [PATCH v4 05/10] docs/clocks: add device's clock documentation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, alistair@alistair23.me, mark.burton@greensocs.com, saipava@xilinx.com, qemu-arm@nongnu.org, Damien Hedde , pbonzini@redhat.com, luc.michel@greensocs.com, fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Damien Hedde Add the documentation about the clock inputs and outputs in devices. This is based on the original work of Frederic Konrad. Signed-off-by: Damien Hedde --- docs/devel/clock.txt | 144 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 docs/devel/clock.txt diff --git a/docs/devel/clock.txt b/docs/devel/clock.txt new file mode 100644 index 0000000000..d018fbef90 --- /dev/null +++ b/docs/devel/clock.txt @@ -0,0 +1,144 @@ + +What are device's clocks +======================== + +Clocks are ports representing input and output clocks of a device. They are QOM +objects developed for the purpose of modeling the distribution of clocks in +QEMU. + +It allows to model the clock distribution of a platform and detect configuration +errors in the clock tree such as badly configured PLL, clock source selection or +disabled clock. + +The objects are CLOCK_IN for the input and CLOCK_OUT for the output. + +The clock value: ClockState +=========================== + +The ClockState is the structure carried by the CLOCK_OUT and CLOCK_IN objects. + +It actually contains two fields: ++ an integer representing the frequency of the clock in Hertz, ++ and a boolean representing the clock domain reset assertion signal. + +It only simulates the clock by transmitting the frequency value and +doesn't model the signal itself such as pin toggle or duty cycle. +The special value 0 as a frequency is legal and represent the clock being +inactive or gated. + +Reset is also carried in the structure since both signals are closely related. +But they remain value-independent, the frequency can be non-zero and the reset +asserted as well as the opposite. + +Adding clocks to a device +========================= + +Adding clocks to a device must be done during the init phase of the Device +object. + +To add an input clock to a device, the function qdev_init_clock_in must be used. +It takes the name, a callback, and an opaque parameter for the clock. +output is more simple, only the name is required. Typically: +qdev_init_clock_in(DEVICE(dev), "clk-in", clk_in_callback, dev); +qdev_init_clock_out(DEVICE(dev), "clk-out"); + +Both functions return the created CLOCK_IN/OUT pointer. For an output, it should +be saved in the device's state structure in order to be able to change the +clock. For an input, it can be saved it one need to change the callback. + +Note that it is possible to create a static array describing clock inputs and +outputs. The function qdev_init_clocks must be called with the array as +parameters to initialize the clocks: it has the same behaviour as calling the +qdev_init_clock/out for each clock. + +Forwarding clocks +================= + +Sometimes, one needs to forward, or inherit, a clock from another device. +Typically, when doing device composition, a device might exposes a sub-device's +clock without interfering with it. +The function qdev_init_clock_forward can be used to achieve this behaviour. +Note, that it is possible to expose the clock under a different name. +This works for both inputs or outputs. + +For example, if device B is a child of device A, device_a_instance_init may +do something like this: +void device_a_instance_init(Object *obj) +{ + AState *A = DEVICE_A(obj); + BState *B; + [...] /* create B object as child of A */ + qdev_init_clock_forward(A, "b_clk", B, "clk"); + /* + * Now A has a clock "b_clk" which forwards to + * the "clk" of its child B. + */ +} + +This function does not returns any clock object. It is not possible to add +a callback on a forwarded input clock. + +Connecting two clocks together +============================== + +Let's say we have 2 devices A and B. A has an output clock named "clkout" and B +has an input clock named "clkin". + +The clocks are connected together using the function qdev_clock_connect: +qdev_clock_connect(B, "clkin", A, "clkout", &error_abort); +The device which has the input must be the first argument. + +It is possible to connect several input clock to the same output. Every +input callback will be called during the output changes. + +It is not possible to disconnect a clock neither to change the clock connection +after it is done. + +Changing a clock output +======================= + +A device can change its outputs using the clock_set function. It will trigger +updates on any connected inputs. + +For example, let's say that we have an output clock "clkout" and we have pointer +on it in the device state because we did the following in init phase: +dev->clkout = qdev_init_clock_out(DEVICE(dev), "clkout"); + +Then at any time, it is possible to change the clock value by doing: +ClockState state; +state.frequency = 1000 * 1000 * 1000; /* 1MHz */ +clock_set(dev->clkout, &state); + +Outputs must be initialized in the device_reset method to ensure every connected +inputs is updated at machine startup. + +Callback on input clock change +============================== + +Here is an example of an input callback: +void clock_callback(void *opaque, ClockState *state) { + MyDeviceState *s = (MyDeviceState *) opaque; + /* + * opaque may not be the device state pointer, but most probably it is. + * (It depends on what is given to the qdev_init_clock_in function) + */ + + /* do something with the state */ + fprintf(stdout, "device new frequency is %" PRIu64 "Hz\n", + clock_state_get_frequency(state)); + + /* optionally store the value for later use in our state */ + clock_state_copy(&s->clkin_shadow, state); +} + +The state argument needs only to be copied if the device needs to use the value +later: the state pointer argument of the pointer will not be valid anymore +after the end of the function. + +Migration +========= + +State is not stored in clock input or output. A device is responsible for +setting its output clock correctly in the post_load function (using clock_set) +after its state has been loaded. This way, during the migration process, all +clocks will be correctly restored. From patchwork Mon Sep 17 08:40:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 970453 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=greensocs.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=greensocs.com header.i=@greensocs.com header.b="2Mhim9PT"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="OYvuZG2m"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="OYvuZG2m"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42DKVn3w2Bz9sCS for ; Mon, 17 Sep 2018 18:46:57 +1000 (AEST) Received: from localhost ([::1]:34455 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1pBH-0001TG-06 for incoming@patchwork.ozlabs.org; Mon, 17 Sep 2018 04:46:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46509) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5y-0006Az-7Y for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1p5w-0005dP-MX for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:26 -0400 Received: from greensocs.com ([193.104.36.180]:51747) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5q-0005VO-4u; Mon, 17 Sep 2018 04:41:18 -0400 Received: from localhost (localhost [127.0.0.1]) by greensocs.com (Postfix) with ESMTP id A4503443493; Mon, 17 Sep 2018 10:41:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173671; bh=33jTLJUAXeCS/V1HY/PDWUYfbAkkSfTM6JFFP2a3zxo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=2Mhim9PThv2C9ns/F7tLC6fsxyqHH0XH3jm3TccQUZEJRipLk/H4XRSVlUy+08zgp 7Lz45cghsjOkwNWEUL3YPCr5MzWzJnGM8Np2Pnu4elCZ6MlfM8+nDW6TzaBYOK8fa5 vX+WUwFUzxC5e1cUro6m1KZTCYxZfHfE/Y5ezpsk= X-Virus-Scanned: amavisd-new at greensocs.com Authentication-Results: gs-01.greensocs.com (amavisd-new); dkim=pass (1024-bit key) header.d=greensocs.com header.b=OYvuZG2m; dkim=pass (1024-bit key) header.d=greensocs.com header.b=OYvuZG2m Received: from greensocs.com ([127.0.0.1]) by localhost (gs-01.greensocs.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OZoln28FHWLZ; Mon, 17 Sep 2018 10:41:10 +0200 (CEST) Received: by greensocs.com (Postfix, from userid 998) id A6006443483; Mon, 17 Sep 2018 10:41:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173670; bh=33jTLJUAXeCS/V1HY/PDWUYfbAkkSfTM6JFFP2a3zxo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=OYvuZG2mLKUZdcpiI37yR85PwHMXB0UuUEj7FoJ6Uh2j9ErGeSbmiSr4B/v/rafOC Zy9TnsQjbVx4lJMGpc+YXvF485qZjdQjR4hM7/qZfjmJ/SQ6O42kJVChoM0wvEoD3A espkiMCtYaKiiYPyFMMj/qZ7Z92iItsermcYBM+Y= Received: from kouign-amann.hive.antfield.fr (antfield.tima.u-ga.fr [147.171.129.253]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: damien.hedde@greensocs.com) by greensocs.com (Postfix) with ESMTPSA id 2927023878C; Mon, 17 Sep 2018 10:41:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173670; bh=33jTLJUAXeCS/V1HY/PDWUYfbAkkSfTM6JFFP2a3zxo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=OYvuZG2mLKUZdcpiI37yR85PwHMXB0UuUEj7FoJ6Uh2j9ErGeSbmiSr4B/v/rafOC Zy9TnsQjbVx4lJMGpc+YXvF485qZjdQjR4hM7/qZfjmJ/SQ6O42kJVChoM0wvEoD3A espkiMCtYaKiiYPyFMMj/qZ7Z92iItsermcYBM+Y= From: damien.hedde@greensocs.com To: qemu-devel@nongnu.org Date: Mon, 17 Sep 2018 10:40:12 +0200 Message-Id: <20180917084016.12750-7-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180917084016.12750-1-damien.hedde@greensocs.com> References: <20180917084016.12750-1-damien.hedde@greensocs.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 193.104.36.180 Subject: [Qemu-devel] [PATCH v4 06/10] sysbus: add bus_interface_clock feature to sysbus devices X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, alistair@alistair23.me, mark.burton@greensocs.com, saipava@xilinx.com, qemu-arm@nongnu.org, Damien Hedde , pbonzini@redhat.com, luc.michel@greensocs.com, fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Damien Hedde Add an optional bus interface clock to sysbus devices. This clock can be added by the subclasses if required using the sysbus_init_bus_interface_clock function given the target name of the clock. The default behavior of the clock is to enable or disable the mmios in function of the clock status (mmios are enabled iff the clock is running and the reset not asserted). This behavior may be changed by overriding the clock callback using sysbus_get_bus_interface_clock and clock_set_callback functions. Signed-off-by: Damien Hedde --- include/hw/sysbus.h | 22 ++++++++++++++++++++++ hw/core/sysbus.c | 25 +++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h index 0b59a3b8d6..abbeece601 100644 --- a/include/hw/sysbus.h +++ b/include/hw/sysbus.h @@ -73,6 +73,7 @@ struct SysBusDevice { } mmio[QDEV_MAX_MMIO]; int num_pio; uint32_t pio[QDEV_MAX_PIO]; + ClockIn *bus_itf_clk; }; typedef void FindSysbusDeviceFunc(SysBusDevice *sbdev, void *opaque); @@ -135,4 +136,25 @@ static inline DeviceState *sysbus_try_create_simple(const char *name, return sysbus_try_create_varargs(name, addr, irq, NULL); } +/** + * sysbus_init_bus_interface_clock: + * @dev: the sysbus device + * @name: the name of the clock + * + * Add the bus interface clock to the device. Mmios will be enabled/disabled + * according to the clock status. Must not be called more than once on the same + * device. + * + * Note: if this clock remains unconnected, the sysbus device will work as if + * the clock was absent (no side-effect). + */ +void sysbus_init_bus_interface_clock(SysBusDevice *dev, const char *name); + +/** + * sysbus_init_get_interface_clock: + * @dev: the sysbus device + * @retuns: the clock previously added by sysbus_init_bus_interface_clock. + */ +ClockIn *sysbus_get_bus_interface_clock(SysBusDevice *dev); + #endif /* HW_SYSBUS_H */ diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index 7ac36ad3e7..8d225263fa 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -324,6 +324,31 @@ MemoryRegion *sysbus_address_space(SysBusDevice *dev) return get_system_memory(); } +static void sysbus_device_clock_callback(void *opaque, ClockState *clk) +{ + SysBusDevice *dev = opaque; + bool enable = clock_state_is_domain_running(clk); + int i; + + /* set/clear mmio visible flag on clock change */ + for (i = 0; i < dev->num_mmio && i < QDEV_MAX_MMIO; i++) { + MemoryRegion *mr = sysbus_mmio_get_region(dev, i); + memory_region_set_enabled(mr, enable); + } +} + +void sysbus_init_bus_interface_clock(SysBusDevice *dev, const char *name) +{ + assert(dev->bus_itf_clk == NULL); + dev->bus_itf_clk = qdev_init_clock_in(DEVICE(dev), name, + sysbus_device_clock_callback, dev); +} + +ClockIn *sysbus_get_bus_interface_clock(SysBusDevice *dev) +{ + return dev->bus_itf_clk; +} + static void sysbus_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); From patchwork Mon Sep 17 08:40:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 970463 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=greensocs.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=greensocs.com header.i=@greensocs.com header.b="VaKfWRa2"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="1pcnsUxo"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="bs8c/mUJ"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42DKfs2KfWz9sBv for ; Mon, 17 Sep 2018 18:53:57 +1000 (AEST) Received: from localhost ([::1]:34488 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1pI2-00060d-UN for incoming@patchwork.ozlabs.org; Mon, 17 Sep 2018 04:53:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46597) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p60-0006EO-OH for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1p5y-0005g5-Kp for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:28 -0400 Received: from greensocs.com ([193.104.36.180]:51750) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5q-0005VS-8Q; Mon, 17 Sep 2018 04:41:18 -0400 Received: from localhost (localhost [127.0.0.1]) by greensocs.com (Postfix) with ESMTP id 670ED2387FF; Mon, 17 Sep 2018 10:41:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173672; bh=rIVUW8GXd9WLg9ABrXSUKezFFb+G48xvjREVfn5NufM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=VaKfWRa2D83HMbwCQX4l6xCaXugmBWeCl14yI+r839FXCTQyKskAC6jTO8wuTT4U4 DSHy91Xnyu2HjVzQU0Qgxz5tgsdozvRfXM3hbcRcSBE0QCDwPN4Shts0TUSu1Obf5O RLoFzLCmyO2947LazAeAG7CjZyE1wb45njcr35SY= X-Virus-Scanned: amavisd-new at greensocs.com Authentication-Results: gs-01.greensocs.com (amavisd-new); dkim=pass (1024-bit key) header.d=greensocs.com header.b=1pcnsUxo; dkim=pass (1024-bit key) header.d=greensocs.com header.b=bs8c/mUJ Received: from greensocs.com ([127.0.0.1]) by localhost (gs-01.greensocs.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id WxRA9GB_kbwh; Mon, 17 Sep 2018 10:41:11 +0200 (CEST) Received: by greensocs.com (Postfix, from userid 998) id 43BD6400FD7; Mon, 17 Sep 2018 10:41:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173671; bh=rIVUW8GXd9WLg9ABrXSUKezFFb+G48xvjREVfn5NufM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=1pcnsUxo/xxIJjM/lZ9+jXiT6T9OXtegj/dJFZ5xbKwU/9Txt8h7rM38sT1MdEQ6u pSf6l1cy8G4jC6QYYZk+jIVUiD97wSyNqzFSKFBYOC391hg1YDdOSE6Txxm2+16fMs lIb8JDZnd2OO9J+XwfrenAkouq1hHWl0Qr6PhybY= Received: from kouign-amann.hive.antfield.fr (antfield.tima.u-ga.fr [147.171.129.253]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: damien.hedde@greensocs.com) by greensocs.com (Postfix) with ESMTPSA id 9FAE3443480; Mon, 17 Sep 2018 10:41:10 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173670; bh=rIVUW8GXd9WLg9ABrXSUKezFFb+G48xvjREVfn5NufM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=bs8c/mUJto3OYBCpCmn6G8/Ifrjqn4QJ3jx9x8uKeAt9JJIvk+Pzt/jAbZ7K1jNn+ lBLbyPNVTTa58kEAd8qQV78irEf/93vDQv+eMORDuDbtJIvkfuQZOI9B41xmI9tKhT UTBYvKxH5yIZb2nI/GG/F9cu0bn1LZXnchKcGqXY= From: damien.hedde@greensocs.com To: qemu-devel@nongnu.org Date: Mon, 17 Sep 2018 10:40:13 +0200 Message-Id: <20180917084016.12750-8-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180917084016.12750-1-damien.hedde@greensocs.com> References: <20180917084016.12750-1-damien.hedde@greensocs.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 193.104.36.180 Subject: [Qemu-devel] [PATCH v4 07/10] hw/misc/zynq_slcr: use standard register definition X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, alistair@alistair23.me, mark.burton@greensocs.com, saipava@xilinx.com, qemu-arm@nongnu.org, Damien Hedde , pbonzini@redhat.com, luc.michel@greensocs.com, fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Damien Hedde Replace the zynq_slcr registers enum and macros using the hw/registerfields.h macros. Signed-off-by: Damien Hedde Reviewed-by: Philippe Mathieu-Daudé --- hw/misc/zynq_slcr.c | 468 ++++++++++++++++++++++---------------------- 1 file changed, 234 insertions(+), 234 deletions(-) diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c index d6bdd027ef..baa13d1316 100644 --- a/hw/misc/zynq_slcr.c +++ b/hw/misc/zynq_slcr.c @@ -20,6 +20,7 @@ #include "hw/sysbus.h" #include "sysemu/sysemu.h" #include "qemu/log.h" +#include "hw/registerfields.h" #ifndef ZYNQ_SLCR_ERR_DEBUG #define ZYNQ_SLCR_ERR_DEBUG 0 @@ -35,138 +36,135 @@ #define XILINX_LOCK_KEY 0x767b #define XILINX_UNLOCK_KEY 0xdf0d -#define R_PSS_RST_CTRL_SOFT_RST 0x1 +REG32(SCL, 0x000) +REG32(LOCK, 0x004) +REG32(UNLOCK, 0x008) +REG32(LOCKSTA, 0x00c) -enum { - SCL = 0x000 / 4, - LOCK, - UNLOCK, - LOCKSTA, +REG32(ARM_PLL_CTRL, 0x100) +REG32(DDR_PLL_CTRL, 0x104) +REG32(IO_PLL_CTRL, 0x108) +REG32(PLL_STATUS, 0x10c) +REG32(ARM_PLL_CFG, 0x110) +REG32(DDR_PLL_CFG, 0x114) +REG32(IO_PLL_CFG, 0x118) - ARM_PLL_CTRL = 0x100 / 4, - DDR_PLL_CTRL, - IO_PLL_CTRL, - PLL_STATUS, - ARM_PLL_CFG, - DDR_PLL_CFG, - IO_PLL_CFG, - - ARM_CLK_CTRL = 0x120 / 4, - DDR_CLK_CTRL, - DCI_CLK_CTRL, - APER_CLK_CTRL, - USB0_CLK_CTRL, - USB1_CLK_CTRL, - GEM0_RCLK_CTRL, - GEM1_RCLK_CTRL, - GEM0_CLK_CTRL, - GEM1_CLK_CTRL, - SMC_CLK_CTRL, - LQSPI_CLK_CTRL, - SDIO_CLK_CTRL, - UART_CLK_CTRL, - SPI_CLK_CTRL, - CAN_CLK_CTRL, - CAN_MIOCLK_CTRL, - DBG_CLK_CTRL, - PCAP_CLK_CTRL, - TOPSW_CLK_CTRL, +REG32(ARM_CLK_CTRL, 0x120) +REG32(DDR_CLK_CTRL, 0x124) +REG32(DCI_CLK_CTRL, 0x128) +REG32(APER_CLK_CTRL, 0x12c) +REG32(USB0_CLK_CTRL, 0x130) +REG32(USB1_CLK_CTRL, 0x134) +REG32(GEM0_RCLK_CTRL, 0x138) +REG32(GEM1_RCLK_CTRL, 0x13c) +REG32(GEM0_CLK_CTRL, 0x140) +REG32(GEM1_CLK_CTRL, 0x144) +REG32(SMC_CLK_CTRL, 0x148) +REG32(LQSPI_CLK_CTRL, 0x14c) +REG32(SDIO_CLK_CTRL, 0x150) +REG32(UART_CLK_CTRL, 0x154) +REG32(SPI_CLK_CTRL, 0x158) +REG32(CAN_CLK_CTRL, 0x15c) +REG32(CAN_MIOCLK_CTRL, 0x160) +REG32(DBG_CLK_CTRL, 0x164) +REG32(PCAP_CLK_CTRL, 0x168) +REG32(TOPSW_CLK_CTRL, 0x16c) #define FPGA_CTRL_REGS(n, start) \ - FPGA ## n ## _CLK_CTRL = (start) / 4, \ - FPGA ## n ## _THR_CTRL, \ - FPGA ## n ## _THR_CNT, \ - FPGA ## n ## _THR_STA, - FPGA_CTRL_REGS(0, 0x170) - FPGA_CTRL_REGS(1, 0x180) - FPGA_CTRL_REGS(2, 0x190) - FPGA_CTRL_REGS(3, 0x1a0) - - BANDGAP_TRIP = 0x1b8 / 4, - PLL_PREDIVISOR = 0x1c0 / 4, - CLK_621_TRUE, - - PSS_RST_CTRL = 0x200 / 4, - DDR_RST_CTRL, - TOPSW_RESET_CTRL, - DMAC_RST_CTRL, - USB_RST_CTRL, - GEM_RST_CTRL, - SDIO_RST_CTRL, - SPI_RST_CTRL, - CAN_RST_CTRL, - I2C_RST_CTRL, - UART_RST_CTRL, - GPIO_RST_CTRL, - LQSPI_RST_CTRL, - SMC_RST_CTRL, - OCM_RST_CTRL, - FPGA_RST_CTRL = 0x240 / 4, - A9_CPU_RST_CTRL, - - RS_AWDT_CTRL = 0x24c / 4, - RST_REASON, - - REBOOT_STATUS = 0x258 / 4, - BOOT_MODE, - - APU_CTRL = 0x300 / 4, - WDT_CLK_SEL, - - TZ_DMA_NS = 0x440 / 4, - TZ_DMA_IRQ_NS, - TZ_DMA_PERIPH_NS, - - PSS_IDCODE = 0x530 / 4, - - DDR_URGENT = 0x600 / 4, - DDR_CAL_START = 0x60c / 4, - DDR_REF_START = 0x614 / 4, - DDR_CMD_STA, - DDR_URGENT_SEL, - DDR_DFI_STATUS, - - MIO = 0x700 / 4, + REG32(FPGA ## n ## _CLK_CTRL, (start)) \ + REG32(FPGA ## n ## _THR_CTRL, (start) + 0x4)\ + REG32(FPGA ## n ## _THR_CNT, (start) + 0x8)\ + REG32(FPGA ## n ## _THR_STA, (start) + 0xc) +FPGA_CTRL_REGS(0, 0x170) +FPGA_CTRL_REGS(1, 0x180) +FPGA_CTRL_REGS(2, 0x190) +FPGA_CTRL_REGS(3, 0x1a0) + +REG32(BANDGAP_TRIP, 0x1b8) +REG32(PLL_PREDIVISOR, 0x1c0) +REG32(CLK_621_TRUE, 0x1c4) + +REG32(PSS_RST_CTRL, 0x200) + FIELD(PSS_RST_CTRL, SOFT_RST, 0, 1) +REG32(DDR_RST_CTRL, 0x204) +REG32(TOPSW_RESET_CTRL, 0x208) +REG32(DMAC_RST_CTRL, 0x20c) +REG32(USB_RST_CTRL, 0x210) +REG32(GEM_RST_CTRL, 0x214) +REG32(SDIO_RST_CTRL, 0x218) +REG32(SPI_RST_CTRL, 0x21c) +REG32(CAN_RST_CTRL, 0x220) +REG32(I2C_RST_CTRL, 0x224) +REG32(UART_RST_CTRL, 0x228) +REG32(GPIO_RST_CTRL, 0x22c) +REG32(LQSPI_RST_CTRL, 0x230) +REG32(SMC_RST_CTRL, 0x234) +REG32(OCM_RST_CTRL, 0x238) +REG32(FPGA_RST_CTRL, 0x240) +REG32(A9_CPU_RST_CTRL, 0x244) + +REG32(RS_AWDT_CTRL, 0x24c) +REG32(RST_REASON, 0x250) + +REG32(REBOOT_STATUS, 0x258) +REG32(BOOT_MODE, 0x25c) + +REG32(APU_CTRL, 0x300) +REG32(WDT_CLK_SEL, 0x304) + +REG32(TZ_DMA_NS, 0x440) +REG32(TZ_DMA_IRQ_NS, 0x444) +REG32(TZ_DMA_PERIPH_NS, 0x448) + +REG32(PSS_IDCODE, 0x530) + +REG32(DDR_URGENT, 0x600) +REG32(DDR_CAL_START, 0x60c) +REG32(DDR_REF_START, 0x614) +REG32(DDR_CMD_STA, 0x618) +REG32(DDR_URGENT_SEL, 0x61c) +REG32(DDR_DFI_STATUS, 0x620) + +REG32(MIO, 0x700) #define MIO_LENGTH 54 - MIO_LOOPBACK = 0x804 / 4, - MIO_MST_TRI0, - MIO_MST_TRI1, +REG32(MIO_LOOPBACK, 0x804) +REG32(MIO_MST_TRI0, 0x808) +REG32(MIO_MST_TRI1, 0x80c) - SD0_WP_CD_SEL = 0x830 / 4, - SD1_WP_CD_SEL, +REG32(SD0_WP_CD_SEL, 0x830) +REG32(SD1_WP_CD_SEL, 0x834) - LVL_SHFTR_EN = 0x900 / 4, - OCM_CFG = 0x910 / 4, +REG32(LVL_SHFTR_EN, 0x900) +REG32(OCM_CFG, 0x910) - CPU_RAM = 0xa00 / 4, +REG32(CPU_RAM, 0xa00) - IOU = 0xa30 / 4, +REG32(IOU, 0xa30) - DMAC_RAM = 0xa50 / 4, +REG32(DMAC_RAM, 0xa50) - AFI0 = 0xa60 / 4, - AFI1 = AFI0 + 3, - AFI2 = AFI1 + 3, - AFI3 = AFI2 + 3, +REG32(AFI0, 0xa60) +REG32(AFI1, 0xa6c) +REG32(AFI2, 0xa78) +REG32(AFI3, 0xa84) #define AFI_LENGTH 3 - OCM = 0xa90 / 4, +REG32(OCM, 0xa90) - DEVCI_RAM = 0xaa0 / 4, +REG32(DEVCI_RAM, 0xaa0) - CSG_RAM = 0xab0 / 4, +REG32(CSG_RAM, 0xab0) - GPIOB_CTRL = 0xb00 / 4, - GPIOB_CFG_CMOS18, - GPIOB_CFG_CMOS25, - GPIOB_CFG_CMOS33, - GPIOB_CFG_HSTL = 0xb14 / 4, - GPIOB_DRVR_BIAS_CTRL, +REG32(GPIOB_CTRL, 0xb00) +REG32(GPIOB_CFG_CMOS18, 0xb04) +REG32(GPIOB_CFG_CMOS25, 0xb08) +REG32(GPIOB_CFG_CMOS33, 0xb0c) +REG32(GPIOB_CFG_HSTL, 0xb14) +REG32(GPIOB_DRVR_BIAS_CTRL, 0xb18) - DDRIOB = 0xb40 / 4, +REG32(DDRIOB, 0xb40) #define DDRIOB_LENGTH 14 -}; #define ZYNQ_SLCR_MMIO_SIZE 0x1000 #define ZYNQ_SLCR_NUM_REGS (ZYNQ_SLCR_MMIO_SIZE / 4) @@ -189,150 +187,152 @@ static void zynq_slcr_reset(DeviceState *d) DB_PRINT("RESET\n"); - s->regs[LOCKSTA] = 1; + s->regs[R_LOCKSTA] = 1; /* 0x100 - 0x11C */ - s->regs[ARM_PLL_CTRL] = 0x0001A008; - s->regs[DDR_PLL_CTRL] = 0x0001A008; - s->regs[IO_PLL_CTRL] = 0x0001A008; - s->regs[PLL_STATUS] = 0x0000003F; - s->regs[ARM_PLL_CFG] = 0x00014000; - s->regs[DDR_PLL_CFG] = 0x00014000; - s->regs[IO_PLL_CFG] = 0x00014000; + s->regs[R_ARM_PLL_CTRL] = 0x0001A008; + s->regs[R_DDR_PLL_CTRL] = 0x0001A008; + s->regs[R_IO_PLL_CTRL] = 0x0001A008; + s->regs[R_PLL_STATUS] = 0x0000003F; + s->regs[R_ARM_PLL_CFG] = 0x00014000; + s->regs[R_DDR_PLL_CFG] = 0x00014000; + s->regs[R_IO_PLL_CFG] = 0x00014000; /* 0x120 - 0x16C */ - s->regs[ARM_CLK_CTRL] = 0x1F000400; - s->regs[DDR_CLK_CTRL] = 0x18400003; - s->regs[DCI_CLK_CTRL] = 0x01E03201; - s->regs[APER_CLK_CTRL] = 0x01FFCCCD; - s->regs[USB0_CLK_CTRL] = s->regs[USB1_CLK_CTRL] = 0x00101941; - s->regs[GEM0_RCLK_CTRL] = s->regs[GEM1_RCLK_CTRL] = 0x00000001; - s->regs[GEM0_CLK_CTRL] = s->regs[GEM1_CLK_CTRL] = 0x00003C01; - s->regs[SMC_CLK_CTRL] = 0x00003C01; - s->regs[LQSPI_CLK_CTRL] = 0x00002821; - s->regs[SDIO_CLK_CTRL] = 0x00001E03; - s->regs[UART_CLK_CTRL] = 0x00003F03; - s->regs[SPI_CLK_CTRL] = 0x00003F03; - s->regs[CAN_CLK_CTRL] = 0x00501903; - s->regs[DBG_CLK_CTRL] = 0x00000F03; - s->regs[PCAP_CLK_CTRL] = 0x00000F01; + s->regs[R_ARM_CLK_CTRL] = 0x1F000400; + s->regs[R_DDR_CLK_CTRL] = 0x18400003; + s->regs[R_DCI_CLK_CTRL] = 0x01E03201; + s->regs[R_APER_CLK_CTRL] = 0x01FFCCCD; + s->regs[R_USB0_CLK_CTRL] = s->regs[R_USB1_CLK_CTRL] = 0x00101941; + s->regs[R_GEM0_RCLK_CTRL] = s->regs[R_GEM1_RCLK_CTRL] = 0x00000001; + s->regs[R_GEM0_CLK_CTRL] = s->regs[R_GEM1_CLK_CTRL] = 0x00003C01; + s->regs[R_SMC_CLK_CTRL] = 0x00003C01; + s->regs[R_LQSPI_CLK_CTRL] = 0x00002821; + s->regs[R_SDIO_CLK_CTRL] = 0x00001E03; + s->regs[R_UART_CLK_CTRL] = 0x00003F03; + s->regs[R_SPI_CLK_CTRL] = 0x00003F03; + s->regs[R_CAN_CLK_CTRL] = 0x00501903; + s->regs[R_DBG_CLK_CTRL] = 0x00000F03; + s->regs[R_PCAP_CLK_CTRL] = 0x00000F01; /* 0x170 - 0x1AC */ - s->regs[FPGA0_CLK_CTRL] = s->regs[FPGA1_CLK_CTRL] = s->regs[FPGA2_CLK_CTRL] - = s->regs[FPGA3_CLK_CTRL] = 0x00101800; - s->regs[FPGA0_THR_STA] = s->regs[FPGA1_THR_STA] = s->regs[FPGA2_THR_STA] - = s->regs[FPGA3_THR_STA] = 0x00010000; + s->regs[R_FPGA0_CLK_CTRL] = s->regs[R_FPGA1_CLK_CTRL] + = s->regs[R_FPGA2_CLK_CTRL] + = s->regs[R_FPGA3_CLK_CTRL] = 0x00101800; + s->regs[R_FPGA0_THR_STA] = s->regs[R_FPGA1_THR_STA] + = s->regs[R_FPGA2_THR_STA] + = s->regs[R_FPGA3_THR_STA] = 0x00010000; /* 0x1B0 - 0x1D8 */ - s->regs[BANDGAP_TRIP] = 0x0000001F; - s->regs[PLL_PREDIVISOR] = 0x00000001; - s->regs[CLK_621_TRUE] = 0x00000001; + s->regs[R_BANDGAP_TRIP] = 0x0000001F; + s->regs[R_PLL_PREDIVISOR] = 0x00000001; + s->regs[R_CLK_621_TRUE] = 0x00000001; /* 0x200 - 0x25C */ - s->regs[FPGA_RST_CTRL] = 0x01F33F0F; - s->regs[RST_REASON] = 0x00000040; + s->regs[R_FPGA_RST_CTRL] = 0x01F33F0F; + s->regs[R_RST_REASON] = 0x00000040; - s->regs[BOOT_MODE] = 0x00000001; + s->regs[R_BOOT_MODE] = 0x00000001; /* 0x700 - 0x7D4 */ for (i = 0; i < 54; i++) { - s->regs[MIO + i] = 0x00001601; + s->regs[R_MIO + i] = 0x00001601; } for (i = 2; i <= 8; i++) { - s->regs[MIO + i] = 0x00000601; + s->regs[R_MIO + i] = 0x00000601; } - s->regs[MIO_MST_TRI0] = s->regs[MIO_MST_TRI1] = 0xFFFFFFFF; + s->regs[R_MIO_MST_TRI0] = s->regs[R_MIO_MST_TRI1] = 0xFFFFFFFF; - s->regs[CPU_RAM + 0] = s->regs[CPU_RAM + 1] = s->regs[CPU_RAM + 3] - = s->regs[CPU_RAM + 4] = s->regs[CPU_RAM + 7] - = 0x00010101; - s->regs[CPU_RAM + 2] = s->regs[CPU_RAM + 5] = 0x01010101; - s->regs[CPU_RAM + 6] = 0x00000001; + s->regs[R_CPU_RAM + 0] = s->regs[R_CPU_RAM + 1] = s->regs[R_CPU_RAM + 3] + = s->regs[R_CPU_RAM + 4] = s->regs[R_CPU_RAM + 7] + = 0x00010101; + s->regs[R_CPU_RAM + 2] = s->regs[R_CPU_RAM + 5] = 0x01010101; + s->regs[R_CPU_RAM + 6] = 0x00000001; - s->regs[IOU + 0] = s->regs[IOU + 1] = s->regs[IOU + 2] = s->regs[IOU + 3] - = 0x09090909; - s->regs[IOU + 4] = s->regs[IOU + 5] = 0x00090909; - s->regs[IOU + 6] = 0x00000909; + s->regs[R_IOU + 0] = s->regs[R_IOU + 1] = s->regs[R_IOU + 2] + = s->regs[R_IOU + 3] = 0x09090909; + s->regs[R_IOU + 4] = s->regs[R_IOU + 5] = 0x00090909; + s->regs[R_IOU + 6] = 0x00000909; - s->regs[DMAC_RAM] = 0x00000009; + s->regs[R_DMAC_RAM] = 0x00000009; - s->regs[AFI0 + 0] = s->regs[AFI0 + 1] = 0x09090909; - s->regs[AFI1 + 0] = s->regs[AFI1 + 1] = 0x09090909; - s->regs[AFI2 + 0] = s->regs[AFI2 + 1] = 0x09090909; - s->regs[AFI3 + 0] = s->regs[AFI3 + 1] = 0x09090909; - s->regs[AFI0 + 2] = s->regs[AFI1 + 2] = s->regs[AFI2 + 2] - = s->regs[AFI3 + 2] = 0x00000909; + s->regs[R_AFI0 + 0] = s->regs[R_AFI0 + 1] = 0x09090909; + s->regs[R_AFI1 + 0] = s->regs[R_AFI1 + 1] = 0x09090909; + s->regs[R_AFI2 + 0] = s->regs[R_AFI2 + 1] = 0x09090909; + s->regs[R_AFI3 + 0] = s->regs[R_AFI3 + 1] = 0x09090909; + s->regs[R_AFI0 + 2] = s->regs[R_AFI1 + 2] = s->regs[R_AFI2 + 2] + = s->regs[R_AFI3 + 2] = 0x00000909; - s->regs[OCM + 0] = 0x01010101; - s->regs[OCM + 1] = s->regs[OCM + 2] = 0x09090909; + s->regs[R_OCM + 0] = 0x01010101; + s->regs[R_OCM + 1] = s->regs[R_OCM + 2] = 0x09090909; - s->regs[DEVCI_RAM] = 0x00000909; - s->regs[CSG_RAM] = 0x00000001; + s->regs[R_DEVCI_RAM] = 0x00000909; + s->regs[R_CSG_RAM] = 0x00000001; - s->regs[DDRIOB + 0] = s->regs[DDRIOB + 1] = s->regs[DDRIOB + 2] - = s->regs[DDRIOB + 3] = 0x00000e00; - s->regs[DDRIOB + 4] = s->regs[DDRIOB + 5] = s->regs[DDRIOB + 6] - = 0x00000e00; - s->regs[DDRIOB + 12] = 0x00000021; + s->regs[R_DDRIOB + 0] = s->regs[R_DDRIOB + 1] = s->regs[R_DDRIOB + 2] + = s->regs[R_DDRIOB + 3] = 0x00000e00; + s->regs[R_DDRIOB + 4] = s->regs[R_DDRIOB + 5] = s->regs[R_DDRIOB + 6] + = 0x00000e00; + s->regs[R_DDRIOB + 12] = 0x00000021; } static bool zynq_slcr_check_offset(hwaddr offset, bool rnw) { switch (offset) { - case LOCK: - case UNLOCK: - case DDR_CAL_START: - case DDR_REF_START: + case R_LOCK: + case R_UNLOCK: + case R_DDR_CAL_START: + case R_DDR_REF_START: return !rnw; /* Write only */ - case LOCKSTA: - case FPGA0_THR_STA: - case FPGA1_THR_STA: - case FPGA2_THR_STA: - case FPGA3_THR_STA: - case BOOT_MODE: - case PSS_IDCODE: - case DDR_CMD_STA: - case DDR_DFI_STATUS: - case PLL_STATUS: + case R_LOCKSTA: + case R_FPGA0_THR_STA: + case R_FPGA1_THR_STA: + case R_FPGA2_THR_STA: + case R_FPGA3_THR_STA: + case R_BOOT_MODE: + case R_PSS_IDCODE: + case R_DDR_CMD_STA: + case R_DDR_DFI_STATUS: + case R_PLL_STATUS: return rnw;/* read only */ - case SCL: - case ARM_PLL_CTRL ... IO_PLL_CTRL: - case ARM_PLL_CFG ... IO_PLL_CFG: - case ARM_CLK_CTRL ... TOPSW_CLK_CTRL: - case FPGA0_CLK_CTRL ... FPGA0_THR_CNT: - case FPGA1_CLK_CTRL ... FPGA1_THR_CNT: - case FPGA2_CLK_CTRL ... FPGA2_THR_CNT: - case FPGA3_CLK_CTRL ... FPGA3_THR_CNT: - case BANDGAP_TRIP: - case PLL_PREDIVISOR: - case CLK_621_TRUE: - case PSS_RST_CTRL ... A9_CPU_RST_CTRL: - case RS_AWDT_CTRL: - case RST_REASON: - case REBOOT_STATUS: - case APU_CTRL: - case WDT_CLK_SEL: - case TZ_DMA_NS ... TZ_DMA_PERIPH_NS: - case DDR_URGENT: - case DDR_URGENT_SEL: - case MIO ... MIO + MIO_LENGTH - 1: - case MIO_LOOPBACK ... MIO_MST_TRI1: - case SD0_WP_CD_SEL: - case SD1_WP_CD_SEL: - case LVL_SHFTR_EN: - case OCM_CFG: - case CPU_RAM: - case IOU: - case DMAC_RAM: - case AFI0 ... AFI3 + AFI_LENGTH - 1: - case OCM: - case DEVCI_RAM: - case CSG_RAM: - case GPIOB_CTRL ... GPIOB_CFG_CMOS33: - case GPIOB_CFG_HSTL: - case GPIOB_DRVR_BIAS_CTRL: - case DDRIOB ... DDRIOB + DDRIOB_LENGTH - 1: + case R_SCL: + case R_ARM_PLL_CTRL ... R_IO_PLL_CTRL: + case R_ARM_PLL_CFG ... R_IO_PLL_CFG: + case R_ARM_CLK_CTRL ... R_TOPSW_CLK_CTRL: + case R_FPGA0_CLK_CTRL ... R_FPGA0_THR_CNT: + case R_FPGA1_CLK_CTRL ... R_FPGA1_THR_CNT: + case R_FPGA2_CLK_CTRL ... R_FPGA2_THR_CNT: + case R_FPGA3_CLK_CTRL ... R_FPGA3_THR_CNT: + case R_BANDGAP_TRIP: + case R_PLL_PREDIVISOR: + case R_CLK_621_TRUE: + case R_PSS_RST_CTRL ... R_A9_CPU_RST_CTRL: + case R_RS_AWDT_CTRL: + case R_RST_REASON: + case R_REBOOT_STATUS: + case R_APU_CTRL: + case R_WDT_CLK_SEL: + case R_TZ_DMA_NS ... R_TZ_DMA_PERIPH_NS: + case R_DDR_URGENT: + case R_DDR_URGENT_SEL: + case R_MIO ... R_MIO + MIO_LENGTH - 1: + case R_MIO_LOOPBACK ... R_MIO_MST_TRI1: + case R_SD0_WP_CD_SEL: + case R_SD1_WP_CD_SEL: + case R_LVL_SHFTR_EN: + case R_OCM_CFG: + case R_CPU_RAM: + case R_IOU: + case R_DMAC_RAM: + case R_AFI0 ... R_AFI3 + AFI_LENGTH - 1: + case R_OCM: + case R_DEVCI_RAM: + case R_CSG_RAM: + case R_GPIOB_CTRL ... R_GPIOB_CFG_CMOS33: + case R_GPIOB_CFG_HSTL: + case R_GPIOB_DRVR_BIAS_CTRL: + case R_DDRIOB ... R_DDRIOB + DDRIOB_LENGTH - 1: return true; default: return false; @@ -370,24 +370,24 @@ static void zynq_slcr_write(void *opaque, hwaddr offset, } switch (offset) { - case SCL: - s->regs[SCL] = val & 0x1; + case R_SCL: + s->regs[R_SCL] = val & 0x1; return; - case LOCK: + case R_LOCK: if ((val & 0xFFFF) == XILINX_LOCK_KEY) { DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset, (unsigned)val & 0xFFFF); - s->regs[LOCKSTA] = 1; + s->regs[R_LOCKSTA] = 1; } else { DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n", (int)offset, (unsigned)val & 0xFFFF); } return; - case UNLOCK: + case R_UNLOCK: if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) { DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset, (unsigned)val & 0xFFFF); - s->regs[LOCKSTA] = 0; + s->regs[R_LOCKSTA] = 0; } else { DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n", (int)offset, (unsigned)val & 0xFFFF); @@ -395,7 +395,7 @@ static void zynq_slcr_write(void *opaque, hwaddr offset, return; } - if (s->regs[LOCKSTA]) { + if (s->regs[R_LOCKSTA]) { qemu_log_mask(LOG_GUEST_ERROR, "SCLR registers are locked. Unlock them first\n"); return; @@ -403,8 +403,8 @@ static void zynq_slcr_write(void *opaque, hwaddr offset, s->regs[offset] = val; switch (offset) { - case PSS_RST_CTRL: - if (val & R_PSS_RST_CTRL_SOFT_RST) { + case R_PSS_RST_CTRL: + if (FIELD_EX32(val, PSS_RST_CTRL, SOFT_RST)) { qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); } break; From patchwork Mon Sep 17 08:40:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 970456 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=greensocs.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=greensocs.com header.i=@greensocs.com header.b="aenRATUB"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="Ke8oV7+2"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="Ke8oV7+2"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42DKbw1pBwz9sBv for ; Mon, 17 Sep 2018 18:51:24 +1000 (AEST) Received: from localhost ([::1]:34479 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1pFZ-0004F8-Jk for incoming@patchwork.ozlabs.org; Mon, 17 Sep 2018 04:51:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46566) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5z-0006Cw-QO for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1p5x-0005eT-Ld for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:27 -0400 Received: from greensocs.com ([193.104.36.180]:51749) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5q-0005VT-7T; Mon, 17 Sep 2018 04:41:18 -0400 Received: from localhost (localhost [127.0.0.1]) by greensocs.com (Postfix) with ESMTP id B4514521ABC; Mon, 17 Sep 2018 10:41:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173672; bh=Mu8KiNTn9ZoRcYYBcP3Ma8/KD+OuRXk+9TZscwr0LmM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=aenRATUBWZp1EevJ3/PU9nMUExc9qkqif2Wi9T+c85LuT20AoPwRlX5et/4lIiCQF cFau6WijguqVVzFRjV7iGp1bm6OZniSoFvTL8/IrcuxMCxYep58FRqqvzlgn+1BZLr ISfIKWbCe5XxQqdPQ5O5aO8pFzYCjkz1G8Lq5Q9A= X-Virus-Scanned: amavisd-new at greensocs.com Authentication-Results: gs-01.greensocs.com (amavisd-new); dkim=pass (1024-bit key) header.d=greensocs.com header.b=Ke8oV7+2; dkim=pass (1024-bit key) header.d=greensocs.com header.b=Ke8oV7+2 Received: from greensocs.com ([127.0.0.1]) by localhost (gs-01.greensocs.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id YTdHKuO8Lf3F; Mon, 17 Sep 2018 10:41:11 +0200 (CEST) Received: by greensocs.com (Postfix, from userid 998) id C5FD7443480; Mon, 17 Sep 2018 10:41:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173671; bh=Mu8KiNTn9ZoRcYYBcP3Ma8/KD+OuRXk+9TZscwr0LmM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Ke8oV7+2b4zpMRHXW/JXJ2XooWR5ib+B9xZQGHq2HyXYpPHcNeYBLz53TYIvytdyD f2hZn3iG1JuBgeO2HogBTp2wo8uj2N4tunlrg4neBILnh/MURIDX1dWGpPcUvt9+T6 aS2NtO+WUGW0OoQjM0VIbcyz8F5hbDzCzutus8IU= Received: from kouign-amann.hive.antfield.fr (antfield.tima.u-ga.fr [147.171.129.253]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: damien.hedde@greensocs.com) by greensocs.com (Postfix) with ESMTPSA id 38C262386FB; Mon, 17 Sep 2018 10:41:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173671; bh=Mu8KiNTn9ZoRcYYBcP3Ma8/KD+OuRXk+9TZscwr0LmM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Ke8oV7+2b4zpMRHXW/JXJ2XooWR5ib+B9xZQGHq2HyXYpPHcNeYBLz53TYIvytdyD f2hZn3iG1JuBgeO2HogBTp2wo8uj2N4tunlrg4neBILnh/MURIDX1dWGpPcUvt9+T6 aS2NtO+WUGW0OoQjM0VIbcyz8F5hbDzCzutus8IU= From: damien.hedde@greensocs.com To: qemu-devel@nongnu.org Date: Mon, 17 Sep 2018 10:40:14 +0200 Message-Id: <20180917084016.12750-9-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180917084016.12750-1-damien.hedde@greensocs.com> References: <20180917084016.12750-1-damien.hedde@greensocs.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 193.104.36.180 Subject: [Qemu-devel] [PATCH v4 08/10] hw/misc/zynq_slcr: add clock generation for uarts X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, alistair@alistair23.me, mark.burton@greensocs.com, saipava@xilinx.com, qemu-arm@nongnu.org, Damien Hedde , pbonzini@redhat.com, luc.michel@greensocs.com, fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Damien Hedde Add 2 clock outputs for each uart (uart0 & 1): + the reference clock + the bus interface clock The clock frequencies, and their respective resets, are computed using the internal pll & uart configuration registers. All clocks depend on the main input clock (ps_clk), which is hard-coded to 33.33MHz (zcu102 evaluation board frequency and frequency specified in Xilinx's device tree file) Signed-off-by: Damien Hedde --- hw/misc/zynq_slcr.c | 155 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c index baa13d1316..bdc52035c8 100644 --- a/hw/misc/zynq_slcr.c +++ b/hw/misc/zynq_slcr.c @@ -33,6 +33,8 @@ } \ } while (0) +#define INPUT_PS_REF_CLK_FREQUENCY (33333333) + #define XILINX_LOCK_KEY 0x767b #define XILINX_UNLOCK_KEY 0xdf0d @@ -44,15 +46,27 @@ REG32(LOCKSTA, 0x00c) REG32(ARM_PLL_CTRL, 0x100) REG32(DDR_PLL_CTRL, 0x104) REG32(IO_PLL_CTRL, 0x108) +/* fields for [ARM|DDR|IO_PLL]_CTRL registers */ + FIELD(xxx_PLL_CTRL, PLL_RESET, 0, 1) + FIELD(xxx_PLL_CTRL, PLL_PWRDWN, 1, 1) + FIELD(xxx_PLL_CTRL, PLL_BYPASS_QUAL, 3, 1) + FIELD(xxx_PLL_CTRL, PLL_BYPASS_FORCE, 4, 1) + FIELD(xxx_PLL_CTRL, PLL_FPDIV, 12, 7) REG32(PLL_STATUS, 0x10c) REG32(ARM_PLL_CFG, 0x110) REG32(DDR_PLL_CFG, 0x114) REG32(IO_PLL_CFG, 0x118) REG32(ARM_CLK_CTRL, 0x120) + FIELD(ARM_CLK_CTRL, SRCSEL, 4, 2) + FIELD(ARM_CLK_CTRL, DIVISOR, 8, 6) + FIELD(ARM_CLK_CTRL, CPU_1XCLKACT, 27, 1) + FIELD(ARM_CLK_CTRL, CPU_PERI_CLKACT, 28, 1) REG32(DDR_CLK_CTRL, 0x124) REG32(DCI_CLK_CTRL, 0x128) REG32(APER_CLK_CTRL, 0x12c) + FIELD(APER_CLK_CTRL, UART0_CPU1XCLKACT, 20, 1) + FIELD(APER_CLK_CTRL, UART1_CPU1XCLKACT, 21, 1) REG32(USB0_CLK_CTRL, 0x130) REG32(USB1_CLK_CTRL, 0x134) REG32(GEM0_RCLK_CTRL, 0x138) @@ -63,12 +77,19 @@ REG32(SMC_CLK_CTRL, 0x148) REG32(LQSPI_CLK_CTRL, 0x14c) REG32(SDIO_CLK_CTRL, 0x150) REG32(UART_CLK_CTRL, 0x154) + FIELD(UART_CLK_CTRL, CLKACT0, 0, 1) + FIELD(UART_CLK_CTRL, CLKACT1, 1, 1) + FIELD(UART_CLK_CTRL, SRCSEL, 4, 2) + FIELD(UART_CLK_CTRL, DIVISOR, 8, 6) REG32(SPI_CLK_CTRL, 0x158) REG32(CAN_CLK_CTRL, 0x15c) REG32(CAN_MIOCLK_CTRL, 0x160) REG32(DBG_CLK_CTRL, 0x164) REG32(PCAP_CLK_CTRL, 0x168) REG32(TOPSW_CLK_CTRL, 0x16c) +/* common fields to lots of *_CLK_CTRL registers */ + FIELD(xxx_CLK_CTRL, SRCSEL, 4, 2) + FIELD(xxx_CLK_CTRL, DIVISOR, 8, 6) #define FPGA_CTRL_REGS(n, start) \ REG32(FPGA ## n ## _CLK_CTRL, (start)) \ @@ -96,6 +117,10 @@ REG32(SPI_RST_CTRL, 0x21c) REG32(CAN_RST_CTRL, 0x220) REG32(I2C_RST_CTRL, 0x224) REG32(UART_RST_CTRL, 0x228) + FIELD(UART_RST_CTRL, UART0_CPU1X_RST, 0, 1) + FIELD(UART_RST_CTRL, UART1_CPU1X_RST, 1, 1) + FIELD(UART_RST_CTRL, UART0_REF_RST, 2, 1) + FIELD(UART_RST_CTRL, UART1_REF_RST, 3, 1) REG32(GPIO_RST_CTRL, 0x22c) REG32(LQSPI_RST_CTRL, 0x230) REG32(SMC_RST_CTRL, 0x234) @@ -178,8 +203,107 @@ typedef struct ZynqSLCRState { MemoryRegion iomem; uint32_t regs[ZYNQ_SLCR_NUM_REGS]; + + ClockOut *uart0_amba_clk; + ClockOut *uart1_amba_clk; + ClockOut *uart0_ref_clk; + ClockOut *uart1_ref_clk; } ZynqSLCRState; +/* + * return the output frequency of ARM/DDR/IO pll + * using input frequency and PLL_CTRL register + */ +static uint64_t zynq_slcr_compute_pll(uint64_t input, uint32_t ctrl_reg) +{ + uint32_t mult = ((ctrl_reg & R_xxx_PLL_CTRL_PLL_FPDIV_MASK) >> + R_xxx_PLL_CTRL_PLL_FPDIV_SHIFT); + + /* first, check if pll is bypassed */ + if (ctrl_reg & R_xxx_PLL_CTRL_PLL_BYPASS_FORCE_MASK) { + return input; + } + + /* is pll disabled ? */ + if (ctrl_reg & (R_xxx_PLL_CTRL_PLL_RESET_MASK | + R_xxx_PLL_CTRL_PLL_PWRDWN_MASK)) { + return 0; + } + + return input * mult; +} + +/* + * return the output frequency of a clock given: + * + the pll's frequencies in an array corresponding to mux's indexes + * + the register xxx_CLK_CTRL value + * + enable bit index in ctrl register + * + * This function make the assumption that ctrl_reg value is organized as follow: + * + bits[13:8] clock divisor + * + bits[5:4] clock mux selector (index in array) + * + bits[index] clock enable + */ +static uint64_t zynq_slcr_compute_clock(const uint64_t plls[], + uint32_t ctrl_reg, + unsigned index) +{ + uint32_t divisor = FIELD_EX32(ctrl_reg, xxx_CLK_CTRL, DIVISOR); + uint32_t srcsel = FIELD_EX32(ctrl_reg, xxx_CLK_CTRL, SRCSEL); + + if ((ctrl_reg & (1u << index)) == 0) { + return 0; + } + + return plls[srcsel] / (divisor ? divisor : 1u); +} + +#define ZYNQ_CLOCK(_state, _plls, _reg, _enable_field) \ + zynq_slcr_compute_clock((_plls), (_state)->regs[R_ ## _reg], \ + R_ ## _reg ## _ ## _enable_field ## _SHIFT) +#define ZYNQ_CLOCK_GATE(_state, _clk, _reg, _field) \ + (ARRAY_FIELD_EX32((_state)->regs, _reg, _field) ? (_clk) : 0) +#define ZYNQ_CLOCK_RESET(_state, _reg, _field) \ + (ARRAY_FIELD_EX32((_state)->regs, _reg, _field) != 0) + +static void zynq_clock_set(ClockOut *clk, uint64_t freq, bool reset) +{ + ClockState value = { + .frequency = freq, + .domain_reset = reset, + }; + clock_set(clk, &value); +} + +static void zynq_slcr_compute_clocks(ZynqSLCRState *s) +{ + uint64_t ps_clk = INPUT_PS_REF_CLK_FREQUENCY; + uint64_t io_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_IO_PLL_CTRL]); + uint64_t arm_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_ARM_PLL_CTRL]); + uint64_t ddr_pll = zynq_slcr_compute_pll(ps_clk, s->regs[R_DDR_PLL_CTRL]); + uint64_t cpu_mux[4] = {arm_pll, arm_pll, ddr_pll, io_pll}; + uint64_t uart_mux[4] = {io_pll, io_pll, arm_pll, ddr_pll}; + uint64_t cpu1x_clk; + + /* compute uartX amba clocks */ + cpu1x_clk = ZYNQ_CLOCK(s, cpu_mux, ARM_CLK_CTRL, CPU_PERI_CLKACT); + cpu1x_clk = ZYNQ_CLOCK_GATE(s, cpu1x_clk, ARM_CLK_CTRL, CPU_1XCLKACT); + zynq_clock_set(s->uart0_amba_clk, + ZYNQ_CLOCK_GATE(s, cpu1x_clk, APER_CLK_CTRL, UART0_CPU1XCLKACT), + ZYNQ_CLOCK_RESET(s, UART_RST_CTRL, UART0_CPU1X_RST)); + zynq_clock_set(s->uart1_amba_clk, + ZYNQ_CLOCK_GATE(s, cpu1x_clk, APER_CLK_CTRL, UART1_CPU1XCLKACT), + ZYNQ_CLOCK_RESET(s, UART_RST_CTRL, UART1_CPU1X_RST)); + + /* compute uartX ref clocks */ + zynq_clock_set(s->uart0_ref_clk, + ZYNQ_CLOCK(s, uart_mux, UART_CLK_CTRL, CLKACT0), + ZYNQ_CLOCK_RESET(s, UART_RST_CTRL, UART0_REF_RST)); + zynq_clock_set(s->uart1_ref_clk, + ZYNQ_CLOCK(s, uart_mux, UART_CLK_CTRL, CLKACT1), + ZYNQ_CLOCK_RESET(s, UART_RST_CTRL, UART1_REF_RST)); +} + static void zynq_slcr_reset(DeviceState *d) { ZynqSLCRState *s = ZYNQ_SLCR(d); @@ -274,6 +398,8 @@ static void zynq_slcr_reset(DeviceState *d) s->regs[R_DDRIOB + 4] = s->regs[R_DDRIOB + 5] = s->regs[R_DDRIOB + 6] = 0x00000e00; s->regs[R_DDRIOB + 12] = 0x00000021; + + zynq_slcr_compute_clocks(s); } @@ -408,6 +534,15 @@ static void zynq_slcr_write(void *opaque, hwaddr offset, qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); } break; + case R_IO_PLL_CTRL: + case R_ARM_PLL_CTRL: + case R_DDR_PLL_CTRL: + case R_ARM_CLK_CTRL: + case R_APER_CLK_CTRL: + case R_UART_CLK_CTRL: + case R_UART_RST_CTRL: + zynq_slcr_compute_clocks(s); + break; } } @@ -417,6 +552,14 @@ static const MemoryRegionOps slcr_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static const ClockPortInitArray zynq_slcr_clocks = { + QDEV_CLOCK_OUT(ZynqSLCRState, uart0_amba_clk), + QDEV_CLOCK_OUT(ZynqSLCRState, uart1_amba_clk), + QDEV_CLOCK_OUT(ZynqSLCRState, uart0_ref_clk), + QDEV_CLOCK_OUT(ZynqSLCRState, uart1_ref_clk), + QDEV_CLOCK_END, +}; + static void zynq_slcr_init(Object *obj) { ZynqSLCRState *s = ZYNQ_SLCR(obj); @@ -424,12 +567,24 @@ static void zynq_slcr_init(Object *obj) memory_region_init_io(&s->iomem, obj, &slcr_ops, s, "slcr", ZYNQ_SLCR_MMIO_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); + + qdev_init_clocks(DEVICE(obj), zynq_slcr_clocks); +} + +static int zynq_slcr_post_load(void *opaque, int version_id) +{ + ZynqSLCRState *s = opaque; + + /* we need to setup all clock ports after migration */ + zynq_slcr_compute_clocks(s); + return 0; } static const VMStateDescription vmstate_zynq_slcr = { .name = "zynq_slcr", .version_id = 2, .minimum_version_id = 2, + .post_load = zynq_slcr_post_load, .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, ZynqSLCRState, ZYNQ_SLCR_NUM_REGS), VMSTATE_END_OF_LIST() From patchwork Mon Sep 17 08:40:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 970448 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=greensocs.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=greensocs.com header.i=@greensocs.com header.b="qo7578kC"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="KkK3J3W0"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="TrTBEiyv"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42DKQQ5jP9z9sCT for ; Mon, 17 Sep 2018 18:43:10 +1000 (AEST) Received: from localhost ([::1]:34428 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p7c-00072Y-3J for incoming@patchwork.ozlabs.org; Mon, 17 Sep 2018 04:43:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46538) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5z-0006C4-3N for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1p5x-0005e5-9z for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:26 -0400 Received: from greensocs.com ([193.104.36.180]:51752) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5q-0005VV-BR; Mon, 17 Sep 2018 04:41:18 -0400 Received: from localhost (localhost [127.0.0.1]) by greensocs.com (Postfix) with ESMTP id 50EFF521ABB; Mon, 17 Sep 2018 10:41:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173673; bh=FU/ZIeWlr5yhKG/DHMFM7aS5cyJSf4R8YXtaT8ndAMo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=qo7578kC7WP2HPyvmA5SxFcBoz8bpp5lbUDGQrCxkcAdLrPXZyFwXIuNI4N0qYXRv rVD7CNGXL6HJrLZbLI0yp/HaAcnYOBLDb7147zSN6rJc0BEq2Zf//R9gXE5QGXvpP2 WThnz7O9ngMwMxCpZFzdCX7S2/qc3e1r5Y7JoI5Q= X-Virus-Scanned: amavisd-new at greensocs.com Authentication-Results: gs-01.greensocs.com (amavisd-new); dkim=pass (1024-bit key) header.d=greensocs.com header.b=KkK3J3W0; dkim=pass (1024-bit key) header.d=greensocs.com header.b=TrTBEiyv Received: from greensocs.com ([127.0.0.1]) by localhost (gs-01.greensocs.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 48JTWTnXTfxx; Mon, 17 Sep 2018 10:41:12 +0200 (CEST) Received: by greensocs.com (Postfix, from userid 998) id 3B784443483; Mon, 17 Sep 2018 10:41:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173672; bh=FU/ZIeWlr5yhKG/DHMFM7aS5cyJSf4R8YXtaT8ndAMo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=KkK3J3W0O+sJ4yqgdS41NpLNByel5VJyOyJUFreowGiPrJKnuimg2ZTC53wmSbcFn zJGjg/Dnj/beCY32UMcEnF32UcAV8O/q8+xgUOj3pSbRCCwpKVb+5POaRp6TBE4A0O gnsiyOSTIEn7KOWNsYv6kc3q7XNnaWXJZgVc+hMg= Received: from kouign-amann.hive.antfield.fr (antfield.tima.u-ga.fr [147.171.129.253]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: damien.hedde@greensocs.com) by greensocs.com (Postfix) with ESMTPSA id AA4022387FF; Mon, 17 Sep 2018 10:41:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173671; bh=FU/ZIeWlr5yhKG/DHMFM7aS5cyJSf4R8YXtaT8ndAMo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=TrTBEiyv4MuXHt2OLi6FKEg07YNV9evxaLIXBsdZXkTRBt0cz3KI0PTaWoeuoeSBL r5rg8+F6TkVOaD2nPPaSf3a68zyZkPcBsAFuwEh9yoeI8W57MlrVCeVT+/3GomeWab ftJn+R9w04DQftCKtLTk8butdvym2oayPvz+LM3E= From: damien.hedde@greensocs.com To: qemu-devel@nongnu.org Date: Mon, 17 Sep 2018 10:40:15 +0200 Message-Id: <20180917084016.12750-10-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180917084016.12750-1-damien.hedde@greensocs.com> References: <20180917084016.12750-1-damien.hedde@greensocs.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 193.104.36.180 Subject: [Qemu-devel] [PATCH v4 09/10] hw/char/cadence_uart: add clock support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, alistair@alistair23.me, mark.burton@greensocs.com, saipava@xilinx.com, qemu-arm@nongnu.org, Damien Hedde , pbonzini@redhat.com, luc.michel@greensocs.com, fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Damien Hedde Add bus interface and uart reference clock inputs. Note: it is hard to find out from the doc what is the behavior when only one of the clock is disabled and what does each clock domain reset. Right now, register access needs both clock being active. The bus interface control the mmios visibility. Its associated reset does nothing apart from disabling the mmios. The reference clock controls the baudrate generation. If it disabled, any input characters and events are ignored. Also register accesses are conditioned to the clock being enabled (but is it really the case in reality ?) and a guest error is triggerred if that is not the case. Its associated reset triggers the cadence_uart reset. If theses clocks remains unconnected, the uart behaves as before. Signed-off-by: Damien Hedde --- include/hw/char/cadence_uart.h | 2 + hw/char/cadence_uart.c | 73 ++++++++++++++++++++++++++++++++-- hw/char/trace-events | 3 ++ 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h index 118e3f10de..c6bb537adf 100644 --- a/include/hw/char/cadence_uart.h +++ b/include/hw/char/cadence_uart.h @@ -21,6 +21,7 @@ #include "hw/sysbus.h" #include "chardev/char-fe.h" #include "qemu/timer.h" +#include "hw/clock-port.h" #define CADENCE_UART_RX_FIFO_SIZE 16 #define CADENCE_UART_TX_FIFO_SIZE 16 @@ -47,6 +48,7 @@ typedef struct { CharBackend chr; qemu_irq irq; QEMUTimer *fifo_trigger_handle; + ClockState refclk; } CadenceUARTState; static inline DeviceState *cadence_uart_create(hwaddr addr, diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index fbdbd463bb..63a8c7108d 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -28,6 +28,7 @@ #include "qemu/timer.h" #include "qemu/log.h" #include "hw/char/cadence_uart.h" +#include "trace.h" #ifdef CADENCE_UART_ERR_DEBUG #define DB_PRINT(...) do { \ @@ -94,7 +95,7 @@ #define LOCAL_LOOPBACK (0x2 << UART_MR_CHMODE_SH) #define REMOTE_LOOPBACK (0x3 << UART_MR_CHMODE_SH) -#define UART_INPUT_CLK 50000000 +#define UART_DEFAULT_REF_CLK (50 * 1000 * 1000) #define R_CR (0x00/4) #define R_MR (0x04/4) @@ -165,15 +166,30 @@ static void uart_send_breaks(CadenceUARTState *s) &break_enabled); } +static unsigned int uart_input_clk(CadenceUARTState *s) +{ + return clock_state_get_frequency(&s->refclk); +} + static void uart_parameters_setup(CadenceUARTState *s) { QEMUSerialSetParams ssp; unsigned int baud_rate, packet_size; baud_rate = (s->r[R_MR] & UART_MR_CLKS) ? - UART_INPUT_CLK / 8 : UART_INPUT_CLK; + uart_input_clk(s) / 8 : uart_input_clk(s); + baud_rate /= (s->r[R_BRGR] * (s->r[R_BDIV] + 1)); + trace_cadence_uart_baudrate(baud_rate); + + ssp.speed = baud_rate; + if (ssp.speed == 0) { + /* + * Avoid division-by-zero below. + * TODO: find something better + */ + ssp.speed = 1; + } - ssp.speed = baud_rate / (s->r[R_BRGR] * (s->r[R_BDIV] + 1)); packet_size = 1; switch (s->r[R_MR] & UART_MR_PAR) { @@ -337,6 +353,11 @@ static void uart_receive(void *opaque, const uint8_t *buf, int size) CadenceUARTState *s = opaque; uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE; + /* ignore characters when unclocked or reset */ + if (!clock_state_is_domain_running(&s->refclk)) { + return; + } + if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) { uart_write_rx_fifo(opaque, buf, size); } @@ -350,6 +371,11 @@ static void uart_event(void *opaque, int event) CadenceUARTState *s = opaque; uint8_t buf = '\0'; + /* ignore events when unclocked or reset */ + if (!clock_state_is_domain_running(&s->refclk)) { + return; + } + if (event == CHR_EVENT_BREAK) { uart_write_rx_fifo(opaque, &buf, 1); } @@ -382,6 +408,14 @@ static void uart_write(void *opaque, hwaddr offset, { CadenceUARTState *s = opaque; + /* ignore accesses when ref clock is disabled */ + if (!clock_state_is_domain_running(&s->refclk)) { + qemu_log_mask(LOG_GUEST_ERROR, + "cadence_uart: Trying to write register 0x%x" + " while clock is disabled/reset\n", (unsigned) offset); + return; + } + DB_PRINT(" offset:%x data:%08x\n", (unsigned)offset, (unsigned)value); offset >>= 2; if (offset >= CADENCE_UART_R_MAX) { @@ -440,6 +474,14 @@ static uint64_t uart_read(void *opaque, hwaddr offset, CadenceUARTState *s = opaque; uint32_t c = 0; + /* ignore accesses when ref clock is disabled */ + if (!clock_state_is_domain_running(&s->refclk)) { + qemu_log_mask(LOG_GUEST_ERROR, + "cadence_uart: Trying to read register 0x%x" + " while clock is disabled/reset\n", (unsigned) offset); + return 0; + } + offset >>= 2; if (offset >= CADENCE_UART_R_MAX) { c = 0; @@ -488,6 +530,24 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp) uart_event, NULL, s, NULL, true); } +static void cadence_uart_refclk_update(void *opaque, ClockState *clk) +{ + CadenceUARTState *s = opaque; + + bool need_reset = clock_state_get_domain_reset(clk) && + !clock_state_get_domain_reset(&s->refclk); + + clock_state_copy(&s->refclk, clk); + + /* reset state if clock domain reset is asserted */ + if (need_reset) { + cadence_uart_reset(DEVICE(s)); + } + + /* recompute uart's speed on clock change */ + uart_parameters_setup(s); +} + static void cadence_uart_init(Object *obj) { SysBusDevice *sbd = SYS_BUS_DEVICE(obj); @@ -497,6 +557,11 @@ static void cadence_uart_init(Object *obj) sysbus_init_mmio(sbd, &s->iomem); sysbus_init_irq(sbd, &s->irq); + sysbus_init_bus_interface_clock(sbd, "busclk"); + qdev_init_clock_in(DEVICE(obj), "refclk", cadence_uart_refclk_update, s); + /* initialize the frequency in case the clock remains unconnected */ + s->refclk.frequency = UART_DEFAULT_REF_CLK; + s->char_tx_time = (NANOSECONDS_PER_SECOND / 9600) * 10; } @@ -548,7 +613,7 @@ static void cadence_uart_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_cadence_uart; dc->reset = cadence_uart_reset; dc->props = cadence_uart_properties; - } +} static const TypeInfo cadence_uart_info = { .name = TYPE_CADENCE_UART, diff --git a/hw/char/trace-events b/hw/char/trace-events index b64213d4dd..2ea25d1ea1 100644 --- a/hw/char/trace-events +++ b/hw/char/trace-events @@ -73,3 +73,6 @@ cmsdk_apb_uart_receive(uint8_t c) "CMSDK APB UART: got character 0x%x from backe cmsdk_apb_uart_tx_pending(void) "CMSDK APB UART: character send to backend pending" cmsdk_apb_uart_tx(uint8_t c) "CMSDK APB UART: character 0x%x sent to backend" cmsdk_apb_uart_set_params(int speed) "CMSDK APB UART: params set to %d 8N1" + +# hw/char/cadence_uart.c +cadence_uart_baudrate(unsigned baudrate) "baudrate %u" From patchwork Mon Sep 17 08:40:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Hedde X-Patchwork-Id: 970447 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=greensocs.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=greensocs.com header.i=@greensocs.com header.b="Uud/IXgI"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="mUg+1kvY"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=greensocs.com header.i=@greensocs.com header.b="mUg+1kvY"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42DKQQ2d9pz9sCS for ; Mon, 17 Sep 2018 18:43:10 +1000 (AEST) Received: from localhost ([::1]:34429 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p7b-00073j-Ix for incoming@patchwork.ozlabs.org; Mon, 17 Sep 2018 04:43:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46494) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5x-0006Ae-Qr for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1p5w-0005cq-HR for qemu-devel@nongnu.org; Mon, 17 Sep 2018 04:41:25 -0400 Received: from greensocs.com ([193.104.36.180]:51751) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1p5q-0005VU-5n; Mon, 17 Sep 2018 04:41:18 -0400 Received: from localhost (localhost [127.0.0.1]) by greensocs.com (Postfix) with ESMTP id 8D66C443483; Mon, 17 Sep 2018 10:41:13 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173673; bh=7kikJd0QMdJjrMyU5WU3TTF88G9I8FGb90lyoljdLqM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Uud/IXgIkljL9IVkxdfeciMiISfPRT+jInFgewiwmpZrFamkyKSXwDHgHGd1Nl234 B7e/vgTz+8Rfk9ZS8sB/RUUfLH9vQQMUt+w/z3RDv5lZSpGdBFUrEmRtMGycHMx8Ca QL5mJ0CptgvZhMrfjnE5q47wUQN9obxpP1SxMoPU= X-Virus-Scanned: amavisd-new at greensocs.com Authentication-Results: gs-01.greensocs.com (amavisd-new); dkim=pass (1024-bit key) header.d=greensocs.com header.b=mUg+1kvY; dkim=pass (1024-bit key) header.d=greensocs.com header.b=mUg+1kvY Received: from greensocs.com ([127.0.0.1]) by localhost (gs-01.greensocs.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OgNuRVhh_OMi; Mon, 17 Sep 2018 10:41:12 +0200 (CEST) Received: by greensocs.com (Postfix, from userid 998) id AA75E400FD7; Mon, 17 Sep 2018 10:41:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173672; bh=7kikJd0QMdJjrMyU5WU3TTF88G9I8FGb90lyoljdLqM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=mUg+1kvYYtcBnyAjGV4lUmuEN5ULK53WUB//fPLhkAqPG7wapZWbB4zhg30hC2QYN GbYUx+ntyYiPHvw0WmSzM0SLCuhhOKFbjp9dc2M+7uMQPBIH3D4v8a36vmyFRrC1cE GkIAOpxdc6XANCvaCO9s4/AZ/Okx9MpN08RlAu/I= Received: from kouign-amann.hive.antfield.fr (antfield.tima.u-ga.fr [147.171.129.253]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: damien.hedde@greensocs.com) by greensocs.com (Postfix) with ESMTPSA id 2A8EB2386FB; Mon, 17 Sep 2018 10:41:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=greensocs.com; s=mail; t=1537173672; bh=7kikJd0QMdJjrMyU5WU3TTF88G9I8FGb90lyoljdLqM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=mUg+1kvYYtcBnyAjGV4lUmuEN5ULK53WUB//fPLhkAqPG7wapZWbB4zhg30hC2QYN GbYUx+ntyYiPHvw0WmSzM0SLCuhhOKFbjp9dc2M+7uMQPBIH3D4v8a36vmyFRrC1cE GkIAOpxdc6XANCvaCO9s4/AZ/Okx9MpN08RlAu/I= From: damien.hedde@greensocs.com To: qemu-devel@nongnu.org Date: Mon, 17 Sep 2018 10:40:16 +0200 Message-Id: <20180917084016.12750-11-damien.hedde@greensocs.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180917084016.12750-1-damien.hedde@greensocs.com> References: <20180917084016.12750-1-damien.hedde@greensocs.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 193.104.36.180 Subject: [Qemu-devel] [PATCH v4 10/10] hw/arm/xilinx_zynq: connect uart clocks to slcr X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: edgar.iglesias@xilinx.com, peter.maydell@linaro.org, alistair@alistair23.me, mark.burton@greensocs.com, saipava@xilinx.com, qemu-arm@nongnu.org, Damien Hedde , pbonzini@redhat.com, luc.michel@greensocs.com, fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Damien Hedde Add the connection between the slcr's output clocks and the uarts inputs. Signed-off-by: Damien Hedde --- hw/arm/xilinx_zynq.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index f1496d2927..efad21a5a9 100644 --- a/hw/arm/xilinx_zynq.c +++ b/hw/arm/xilinx_zynq.c @@ -166,7 +166,7 @@ static void zynq_init(MachineState *machine) MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ext_ram = g_new(MemoryRegion, 1); MemoryRegion *ocm_ram = g_new(MemoryRegion, 1); - DeviceState *dev; + DeviceState *dev, *slcr; SysBusDevice *busdev; qemu_irq pic[64]; int n; @@ -212,9 +212,10 @@ static void zynq_init(MachineState *machine) 1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa, 0); - dev = qdev_create(NULL, "xilinx,zynq_slcr"); - qdev_init_nofail(dev); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000); + /* Create slcr, keep a pointer to connect clocks */ + slcr = qdev_create(NULL, "xilinx,zynq_slcr"); + qdev_init_nofail(slcr); + sysbus_mmio_map(SYS_BUS_DEVICE(slcr), 0, 0xF8000000); dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV); qdev_prop_set_uint32(dev, "num-cpu", 1); @@ -235,8 +236,12 @@ static void zynq_init(MachineState *machine) sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]); sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]); - cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hd(0)); - cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hd(1)); + dev = cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hd(0)); + qdev_clock_connect(dev, "busclk", slcr, "uart0_amba_clk", &error_abort); + qdev_clock_connect(dev, "refclk", slcr, "uart0_ref_clk", &error_abort); + dev = cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hd(1)); + qdev_clock_connect(dev, "busclk", slcr, "uart1_amba_clk", &error_abort); + qdev_clock_connect(dev, "refclk", slcr, "uart1_ref_clk", &error_abort); sysbus_create_varargs("cadence_ttc", 0xF8001000, pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);