From patchwork Fri Mar 18 09:13:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baptiste Reynal X-Patchwork-Id: 8617351 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id DA34A9F44D for ; Fri, 18 Mar 2016 09:13:50 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B51422034B for ; Fri, 18 Mar 2016 09:13:49 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 455D42035D for ; Fri, 18 Mar 2016 09:13:48 +0000 (UTC) Received: from localhost ([::1]:42359 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1agqTb-0002e3-CR for patchwork-qemu-devel@patchwork.kernel.org; Fri, 18 Mar 2016 05:13:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42144) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1agqTJ-0002ZG-N6 for qemu-devel@nongnu.org; Fri, 18 Mar 2016 05:13:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1agqTG-0003lD-90 for qemu-devel@nongnu.org; Fri, 18 Mar 2016 05:13:29 -0400 Received: from mail-wm0-x22e.google.com ([2a00:1450:400c:c09::22e]:33211) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1agqTF-0003kd-V5 for qemu-devel@nongnu.org; Fri, 18 Mar 2016 05:13:26 -0400 Received: by mail-wm0-x22e.google.com with SMTP id l68so59391199wml.0 for ; Fri, 18 Mar 2016 02:13:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=virtualopensystems-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8R979oGJBXH+8pYzQuUei1fHDkqbEBkWu+ufTqN+J1Q=; b=zo7Uwz3nJa0PHclCxVASE38Al8lA8wYeAfmlEOzkhkPddKK6LFEkL5/i/mN3OIaWcR bDHrsQdbTS2sw6M119qpOqVEPP1ynHDGXY+yE3nSNUhQ8IKK+ZtGUlU9bvOHaPOV14Yt dHvNX2W6zvR0FVqLnJpXFGoOgXCJRup2csszLprWne0LvVzZSGwMNEHhjMm0QizmYy0R f/yyMYJynL6QrsmUtNo6mjASmz9XX7c0iWvN+S1HG3cOFOeYNVrZ+LK4Kf07YABiQHmZ MOqT8Ic94pBzHxQgCmC+bwnYrehA0smREWssnkrAr54ETWKtTtemxyrCK/kx8Ac8QD/l u6QA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=8R979oGJBXH+8pYzQuUei1fHDkqbEBkWu+ufTqN+J1Q=; b=FxMQBKdFkC/aXa8crOhF5CjzPMjlPdKl3Ta8xPbqSRfYRAV++vRb5mvjYXrf9SbEXY bnGn00uyUcfZ6ziIerN1N27iFvCrmn64FW1NzGJ7g7b7bJYz6DjJLYXt95ZNOIp2zBr7 gJ99uHlyBAh8hr070RqLWNiaoHhUX9svKLPHcoDSuhWuxHa75hUl4Gc4PXMEOuz2vLIR MQTGOqWo26ebBqpeifheE+qYDtmgDLiGVGf3U2htcvRvqwPqS0nkAnagM+fIXkHB+HgB S4AHvSOyw+fmDJCLmuFY/pm/91uy5b0PhXTbfsvSgDNHj5ote+8J17eNdmsfXmPcqWtO cXrA== X-Gm-Message-State: AD7BkJKeCNzPGoUNFiVLcwBdaM1tN1tjfcIatd7M/oHm6QGvnYfhfifrEyiXr84Q0Da2/A== X-Received: by 10.194.121.194 with SMTP id lm2mr14653697wjb.71.1458292405410; Fri, 18 Mar 2016 02:13:25 -0700 (PDT) Received: from localhost (LMontsouris-657-1-4-224.w90-63.abo.wanadoo.fr. [90.63.239.224]) by smtp.gmail.com with ESMTPSA id h7sm33722636wmf.9.2016.03.18.02.13.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 Mar 2016 02:13:24 -0700 (PDT) From: Baptiste Reynal To: qemu-devel@nongnu.org Date: Fri, 18 Mar 2016 10:13:01 +0100 Message-Id: <1458292385-13802-3-git-send-email-b.reynal@virtualopensystems.com> X-Mailer: git-send-email 2.7.3 In-Reply-To: <1458292385-13802-1-git-send-email-b.reynal@virtualopensystems.com> References: <1458292385-13802-1-git-send-email-b.reynal@virtualopensystems.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::22e Cc: b.reynal@virtualopensystems.com, Jani.Kokkonen@huawei.com, tech@virtualopensystems.com, Claudio.Fontana@huawei.com Subject: [Qemu-devel] [RFC v2 2/6] hw/misc: sdm platform device X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This is the platform implementation for an SDM device. Parameters are: comm=[sdm_communication_id] specifies the communication channel master=[true/false] - configure the SDM device as master or slave num_slaves=[slave_number] - if master is true, specifies the number of slaves len-signals=[signals_number] - specifies the number of signals signals[x]=[signal_id] - add a signal to the device, with the ID x Signed-off-by: Baptiste Reynal --- hw/misc/Makefile.objs | 1 + hw/misc/sdm-platform.c | 236 +++++++++++++++++++++++++++++++++++++++++ include/hw/misc/sdm-platform.h | 65 ++++++++++++ 3 files changed, 302 insertions(+) create mode 100644 hw/misc/sdm-platform.c create mode 100644 include/hw/misc/sdm-platform.h diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 6e73901..fc32161 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -24,6 +24,7 @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o obj-$(CONFIG_SDM) += sdm-device.o obj-$(CONFIG_SDM) += sdm-communication.o obj-$(CONFIG_SDM) += sdm-signal.o +obj-$(CONFIG_SDM) += sdm-platform.o obj-$(CONFIG_REALVIEW) += arm_sysctl.o obj-$(CONFIG_NSERIES) += cbus.o diff --git a/hw/misc/sdm-platform.c b/hw/misc/sdm-platform.c new file mode 100644 index 0000000..ff3a4c7 --- /dev/null +++ b/hw/misc/sdm-platform.c @@ -0,0 +1,236 @@ +/* + * SDM Platform Device + * + * Copyright (C) 2015 - Virtual Open Systems + * + * Author: Christian Pinto + * Baptiste Reynal + * + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. + */ +#include "hw/misc/sdm-platform.h" +#include "qemu/error-report.h" + +static void reset_irq(SDMPlatform *s) +{ + qemu_irq_lower(s->irq); +} + +static uint64_t sdm_platform_read(void *opaque, hwaddr offset, unsigned size) +{ + SDMPlatform *sdmp = opaque; + uint64_t ret = 0; + + switch (offset) { + case SIGNAL_REG: + /** + * Reading the REGISTER returns informations about the signal (16 high + * bytes) and the source (16 low bytes). + * The signal register is cleared, and the interrupt + * is lowered. Be sure to read the payload before. + */ + ret = sdmp->signal_reg; + sdmp->signal_reg = 0; + reset_irq(sdmp); + sdmp->busy = false; + case PAYLOAD_REG0: + /** + * Reading the payload registers returns the value of the last + * payload received (0 initialized) + */ + ret = sdmp->payload_reg[0]; + break; + case PAYLOAD_REG1: + ret = sdmp->payload_reg[1]; + break; + default: + error_report("SDM platform: wrong register in sdm_read\n"); + break; + } + + return ret; +} + +static void sdm_platform_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + SDMPlatform *sdmp = opaque; + SDMSignalData signal; + + switch (offset) { + case SIGNAL_REG: + /* To signal another slave, the ID should be written to the 16 + * low bytes and the signal ID to the 16 high bytes. Value 0 is + * reserved to kick the master, from 1 upwards for the slaves. + */ + signal.slave = value & 0xffff; + signal.type = (value >> 16) & 0xffff; + memcpy(&signal.payload, sdmp->payload_reg, + 2 * sizeof(uint32_t)); + + sdm_communication_signal(sdmp->sdmc, SDM_DEVICE(sdmp), &signal); + + break; + case PAYLOAD_REG0: + /* Set the payload for the next signal */ + sdmp->payload_reg[0] = value; + break; + case PAYLOAD_REG1: + sdmp->payload_reg[1] = value; + break; + default: + error_report("SDM Platform: wrong register in sdm_write\n"); + break; + } +} + + + +static const MemoryRegionOps sdm_platform_mem_ops = { + .read = sdm_platform_read, + .write = sdm_platform_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void sdm_platform_realize(DeviceState *dev, Error **errp) +{ + SDMPlatform *s = SDM_PLATFORM(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + int i; + + s->last_slave = 0; + + /* Initialize MMIO regions with read/write functions */ + memory_region_init_io(&s->iomem, OBJECT(s), &sdm_platform_mem_ops, s, + TYPE_SDM_PLATFORM, SDM_PLATFORM_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + + /* Initialize IRQ */ + sysbus_init_irq(sbd, &s->irq); + + sdm_communication_connect(s->sdmc, SDM_DEVICE(s)); + + s->signals = calloc(s->num_signals, sizeof(SDMSignal)); + for (i = 0; i < s->num_signals; i++) { + s->signals[i] = (SDMSignal *) object_resolve_path_type( + s->signals_name[i], + TYPE_SDM_SIGNAL, false); + if (!s->signals[i]) { + error_report("SDM Platform: Cannot find signal %s", + s->signals_name[i]);; + } + } + +} + +static int sdm_platform_accept(SDMDevice *sdm) +{ + SDMPlatform *sdmp = SDM_PLATFORM(sdm); + + if (sdmp->last_slave >= sdmp->num_slaves) { + return -1; + } + + return ++sdmp->last_slave; +} + +static int sdm_platform_notify(SDMDevice *sdm, SDMSignalData *signal) +{ + SDMPlatform *sdmp = SDM_PLATFORM(sdm); + SDMSignal *hw_signal; + + if (signal->type > sdmp->num_signals) { + return 0; + } + + hw_signal = sdmp->signals[signal->type]; + + if (!hw_signal) { + return 0; + } + + sdm_signal_hw_ops(hw_signal, signal); + + if (!sdm_signal_hw_only(hw_signal)) { + if (sdmp->busy) { + return -1; + } + sdmp->busy = true; + + sdmp->signal_reg = (signal->type << 16) & (signal->slave & 0xffff); + + qemu_irq_raise(sdmp->irq); + } + + return 0; +} + +static int sdm_platform_get_num_slaves(SDMDevice *sdm) +{ + SDMPlatform *sdmp = SDM_PLATFORM(sdm); + + return sdmp->num_slaves; +} + +static bool sdm_platform_is_master(SDMDevice *sdm) +{ + SDMPlatform *sdmp = SDM_PLATFORM(sdm); + + return sdmp->master; +} + +static Property sdm_platform_properties[] = { + DEFINE_PROP_UINT32("num-slaves", SDMPlatform, num_slaves, 1), + DEFINE_PROP_BOOL("master", SDMPlatform, master, false), + DEFINE_PROP_ARRAY("signals", SDMPlatform, num_signals, signals_name, + qdev_prop_string, char *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void sdm_platform_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SDMDeviceClass *sdmc = SDM_DEVICE_CLASS(klass); + + dc->props = sdm_platform_properties; + dc->realize = sdm_platform_realize; + + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + + sdmc->accept = sdm_platform_accept; + sdmc->notify = sdm_platform_notify; + sdmc->get_num_slaves = sdm_platform_get_num_slaves; + sdmc->is_master = sdm_platform_is_master; +} + +static void sdm_platform_init(Object *obj) +{ + SDMPlatform *sdmp = SDM_PLATFORM(obj); + + object_property_add_link(obj, "comm", TYPE_SDM_COMMUNICATION, + (Object **)&sdmp->sdmc, + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort); + + sdmp->busy = false; +} + +static const TypeInfo sdm_platform_info = { + .name = TYPE_SDM_PLATFORM, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_init = sdm_platform_init, + .instance_size = sizeof(struct SDMPlatform), + .class_init = sdm_platform_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_SDM_DEVICE }, + { } + } +}; + +static void sdm_register_types(void) +{ + type_register_static(&sdm_platform_info); +} + +type_init(sdm_register_types); diff --git a/include/hw/misc/sdm-platform.h b/include/hw/misc/sdm-platform.h new file mode 100644 index 0000000..42a0070 --- /dev/null +++ b/include/hw/misc/sdm-platform.h @@ -0,0 +1,65 @@ +/* + * SDM Device Platform + * + * Copyright (C) 2016 - Virtual Open Systems + * + * Author: Christian Pinto + * Baptiste Reynal + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ +#ifndef HW_SDM_PLATFORM_H +#define HW_SDM_PLATFORM_H + +#include "qemu-common.h" +#include "hw/misc/sdm-communication.h" +#include "hw/sysbus.h" + +/* + * Size of the IO memory mapped region + * associated with IDM device registers + */ +#define SDM_PLATFORM_SIZE 0x100 + +/* + * Registers + */ +#define SIGNAL_REG 0x00 +#define PAYLOAD_REG0 0x04 +#define PAYLOAD_REG1 0x08 + +#define TYPE_SDM_PLATFORM "sdm-platform" +#define SDM_PLATFORM(obj) \ + OBJECT_CHECK(SDMPlatform, (obj), TYPE_SDM_PLATFORM) + +typedef struct SDMPlatform SDMPlatform; + +/** + * @SDMPlatform + * + * @parent: opaque parent object container + */ +struct SDMPlatform { + /* private */ + SysBusDevice parent; + + MemoryRegion iomem; + SDMCommunication *sdmc; + + bool master; + bool busy; + + uint32_t num_slaves; + uint32_t last_slave; + + uint32_t num_signals; + char **signals_name; + SDMSignal **signals; + + uint32_t signal_reg; + uint32_t payload_reg[4]; + + qemu_irq irq; +}; +#endif