From patchwork Wed Apr 7 04:10:18 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grant Likely X-Patchwork-Id: 49565 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id DE5CFB7D20 for ; Wed, 7 Apr 2010 14:17:45 +1000 (EST) Received: from localhost ([127.0.0.1]:36492 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NzMhy-0001YF-PE for incoming@patchwork.ozlabs.org; Wed, 07 Apr 2010 00:17:42 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NzMaw-0008QC-Ds for qemu-devel@nongnu.org; Wed, 07 Apr 2010 00:10:26 -0400 Received: from [140.186.70.92] (port=34708 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NzMau-0008P9-JD for qemu-devel@nongnu.org; Wed, 07 Apr 2010 00:10:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1NzMas-0001nr-KS for qemu-devel@nongnu.org; Wed, 07 Apr 2010 00:10:24 -0400 Received: from mail-pw0-f45.google.com ([209.85.160.45]:55195) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1NzMas-0001kv-FI for qemu-devel@nongnu.org; Wed, 07 Apr 2010 00:10:22 -0400 Received: by mail-pw0-f45.google.com with SMTP id 6so554258pwi.4 for ; Tue, 06 Apr 2010 21:10:22 -0700 (PDT) Received: by 10.114.251.23 with SMTP id y23mr7691511wah.42.1270613422173; Tue, 06 Apr 2010 21:10:22 -0700 (PDT) Received: from angua (S01060002b3d79728.cg.shawcable.net [70.72.87.49]) by mx.google.com with ESMTPS id 21sm3333805pzk.8.2010.04.06.21.10.20 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 06 Apr 2010 21:10:20 -0700 (PDT) Received: from [127.0.1.1] (localhost [127.0.0.1]) by angua (Postfix) with ESMTP id 576D61121; Tue, 6 Apr 2010 22:10:18 -0600 (MDT) From: Grant Likely To: qemu-devel@nongnu.org, devicetree-discuss@lists.ozlabs.org, jeremy.kerr@canonical.com Date: Tue, 06 Apr 2010 22:10:18 -0600 Message-ID: <20100407041018.20274.36307.stgit@angua> In-Reply-To: <20100407040129.20274.44284.stgit@angua> References: <20100407040129.20274.44284.stgit@angua> User-Agent: StGIT/0.14.2 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: Subject: [Qemu-devel] [RFC PATCH 4/7] devicetree: Add sysbus fdt populate hooks. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch adds sysbus specific fdt_populate hooks to fill sysbus device nodes with 'reg' and 'interrupts' properties, and to provide 'ranges' properties for correct address translations. Signed-off-by: Grant Likely --- hw/sysbus.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/sysbus.h | 2 + 2 files changed, 94 insertions(+), 0 deletions(-) diff --git a/hw/sysbus.c b/hw/sysbus.c index 1f7f138..861572f 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -22,11 +22,16 @@ #include "monitor.h" static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent); +static int sysbus_fdt_populate_node(DeviceState *dev, void *fdt, int offset); +static int sysbus_fdt_populate_bus(BusState *bus, void *fdt, int offset); struct BusInfo system_bus_info = { .name = "System", .size = sizeof(BusState), .print_dev = sysbus_dev_print, +#ifdef CONFIG_FDT + .fdt_populate = sysbus_fdt_populate_bus, +#endif /* CONFIG_FDT */ }; void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) @@ -115,6 +120,7 @@ static int sysbus_device_init(DeviceState *dev, DeviceInfo *base) void sysbus_register_withprop(SysBusDeviceInfo *info) { info->qdev.init = sysbus_device_init; + info->qdev.fdt_populate = sysbus_fdt_populate_node; info->qdev.bus_info = &system_bus_info; assert(info->qdev.size >= sizeof(SysBusDevice)); @@ -170,3 +176,89 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent) indent, "", s->mmio[i].addr, s->mmio[i].size); } } + +#ifdef CONFIG_FDT +#include +static int sysbus_fdt_populate_bus(BusState *bus, void *fdt, int offset) +{ + int rc; + + rc = fdt_setprop_string(fdt, offset, "compatible", "simple-bus"); + if (rc < 0) + return rc; + + rc = fdt_setprop_cell(fdt, offset, "#address-cells", 1); + if (rc < 0) + return rc; + rc = fdt_setprop_cell(fdt, offset, "#size-cells", 1); + if (rc < 0) + return rc; + rc = fdt_setprop(fdt, offset, "ranges", NULL, 0); + if (rc < 0) + return rc; + return 0; +} + +static int sysbus_fdt_populate_node(DeviceState *dev, void *fdt, int offset) +{ + SysBusDevice *s = sysbus_from_qdev(dev); + SysBusDeviceInfo *info = container_of(dev->info, SysBusDeviceInfo, qdev); + + uint32_t reg_data[s->num_mmio * 2]; /* one cell each address and size */ + uint32_t irq_data[s->num_irq]; + uint32_t *pos; + uint32_t phandle; + int i, rc; + + /* Create 'reg' property */ + pos = reg_data; + for (i = 0; i < s->num_mmio; i++) { + /* By convention, the name is appended with '@' */ + if (i == 0) { + char n[sizeof(dev->info->name) + 10]; + sprintf(n, "%s@%x", dev->info->name, (uint32_t)s->mmio[i].addr); + rc = fdt_set_name(fdt, offset, n); + if (rc < 0) + return rc; + } + *pos++ = cpu_to_be32(s->mmio[i].addr); + *pos++ = cpu_to_be32(s->mmio[i].size); + } + rc = fdt_setprop(fdt, offset, "reg", reg_data, sizeof(reg_data)); + if (rc < 0) + return rc; + + /* Is this an interrupt controller? */ + if (dev->num_gpio_in) { + rc = fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0); + if (rc < 0) + return rc; + rc = fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1); + if (rc < 0) + return rc; + } + + /* Create 'interrupts' property */ + phandle = 0; + pos = irq_data; + for (i = 0; i < s->num_irq; i++) { + *pos++ = cpu_to_be32(qbus_fdt_irq_to_number(*s->irqp[i], &phandle)); + } + if (phandle) { + rc = fdt_setprop_cell(fdt, offset, "interrupt-parent", phandle); + if (rc < 0) + return rc; + rc = fdt_setprop(fdt, offset, "interrupts", irq_data, sizeof(irq_data)); + if (rc < 0) + return rc; + } + + if (info->fdt_populate) { + rc = info->fdt_populate(s, fdt, offset); + if (rc < 0) + return rc; + } + + return 0; +} +#endif /* CONFIG_FDT */ diff --git a/hw/sysbus.h b/hw/sysbus.h index 1a8f289..2c43191 100644 --- a/hw/sysbus.h +++ b/hw/sysbus.h @@ -26,6 +26,7 @@ struct SysBusDevice { }; typedef int (*sysbus_initfn)(SysBusDevice *dev); +typedef int (*sysbus_fdt_populatefn)(SysBusDevice *dev, void *fdt, int node_offset); /* Macros to compensate for lack of type inheritance in C. */ #define sysbus_from_qdev(dev) ((SysBusDevice *)(dev)) @@ -34,6 +35,7 @@ typedef int (*sysbus_initfn)(SysBusDevice *dev); typedef struct { DeviceInfo qdev; sysbus_initfn init; + sysbus_fdt_populatefn fdt_populate; } SysBusDeviceInfo; void sysbus_register_dev(const char *name, size_t size, sysbus_initfn init);