From patchwork Sun May 17 20:03:46 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parth Dixit X-Patchwork-Id: 48640 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f72.google.com (mail-la0-f72.google.com [209.85.215.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id A296221411 for ; Sun, 17 May 2015 20:06:29 +0000 (UTC) Received: by laat2 with SMTP id t2sf47314726laa.2 for ; Sun, 17 May 2015 13:06:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:cc:subject:precedence:list-id:list-unsubscribe:list-post :list-help:list-subscribe:mime-version:content-type :content-transfer-encoding:sender:errors-to:x-original-sender :x-original-authentication-results:mailing-list:list-archive; bh=0VbLHdWpqcWpAe/MTURbpy2QdNl8xYVKyoV+UvrtX7s=; b=QtD594AKokZXT4TAqqAOAJpBPb8PUSywZjAatbnakxDee+GudkgkyXz3noBdZPX3EK 4SnpJzMU4746BfyIRZH6SstSSVEgNG+WvTI30m763+OksLjPxIL7dMDV53sHZepAPlq3 7TGcgVVycyeOvCWAN9QWUYKrSmzRFKDjHFOBe7BjaeqHMGk8pON0sRKsQVRvyu9egZR6 4VWbBh6Mi1S25+Yh4d/AFlmoG3cmdwVZ+5iRU/M0XA8hGxaYbgT0NwpFfREGSPHZEaLr HkgM9hAkOTPIyGTeqjlY5PBKv59Ed5ptqEm2yov/awQ3on4UXqXEhfFWcqiDo2uNu05G fosQ== X-Gm-Message-State: ALoCoQlJK0+ALtVvFr67hwsZD64cllo/Yn4MqOPPWoW51ms/V31XRs8fLlCnvNB/avv6H1e407Dp X-Received: by 10.194.142.205 with SMTP id ry13mr9431045wjb.2.1431893188597; Sun, 17 May 2015 13:06:28 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.245.43 with SMTP id xl11ls689731lac.21.gmail; Sun, 17 May 2015 13:06:28 -0700 (PDT) X-Received: by 10.112.159.162 with SMTP id xd2mr14455021lbb.67.1431893188301; Sun, 17 May 2015 13:06:28 -0700 (PDT) Received: from mail-la0-f49.google.com (mail-la0-f49.google.com. [209.85.215.49]) by mx.google.com with ESMTPS id wc1si5333301lbb.66.2015.05.17.13.06.28 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 17 May 2015 13:06:28 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.49 as permitted sender) client-ip=209.85.215.49; Received: by labbd9 with SMTP id bd9so191522788lab.2 for ; Sun, 17 May 2015 13:06:28 -0700 (PDT) X-Received: by 10.112.219.70 with SMTP id pm6mr14522544lbc.41.1431893188195; Sun, 17 May 2015 13:06:28 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.108.230 with SMTP id hn6csp3507903lbb; Sun, 17 May 2015 13:06:26 -0700 (PDT) X-Received: by 10.140.233.214 with SMTP id e205mr26555598qhc.68.1431893186373; Sun, 17 May 2015 13:06:26 -0700 (PDT) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id i85si5741464qhc.87.2015.05.17.13.06.25 (version=TLSv1 cipher=RC4-SHA bits=128/128); Sun, 17 May 2015 13:06:26 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of xen-devel-bounces@lists.xen.org designates 50.57.142.19 as permitted sender) client-ip=50.57.142.19; Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1Yu4oi-0002Km-Dt; Sun, 17 May 2015 20:05:44 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1Yu4oh-0002IQ-1o for xen-devel@lists.xen.org; Sun, 17 May 2015 20:05:43 +0000 Received: from [85.158.137.68] by server-6.bemta-3.messagelabs.com id 4F/43-03286-694F8555; Sun, 17 May 2015 20:05:42 +0000 X-Env-Sender: parth.dixit@linaro.org X-Msg-Ref: server-8.tower-31.messagelabs.com!1431893139!11287922!1 X-Originating-IP: [209.85.220.54] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 6.13.15; banners=-,-,- X-VirusChecked: Checked Received: (qmail 27277 invoked from network); 17 May 2015 20:05:40 -0000 Received: from mail-pa0-f54.google.com (HELO mail-pa0-f54.google.com) (209.85.220.54) by server-8.tower-31.messagelabs.com with RC4-SHA encrypted SMTP; 17 May 2015 20:05:40 -0000 Received: by pabts4 with SMTP id ts4so119782958pab.3 for ; Sun, 17 May 2015 13:05:39 -0700 (PDT) X-Received: by 10.68.65.1 with SMTP id t1mr38299225pbs.63.1431893139267; Sun, 17 May 2015 13:05:39 -0700 (PDT) Received: from localhost.localdomain ([117.247.24.139]) by mx.google.com with ESMTPSA id j9sm7838401pdm.53.2015.05.17.13.05.35 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 17 May 2015 13:05:38 -0700 (PDT) From: Parth Dixit To: xen-devel@lists.xen.org Date: Mon, 18 May 2015 01:33:46 +0530 Message-Id: <1431893048-5214-20-git-send-email-parth.dixit@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1431893048-5214-1-git-send-email-parth.dixit@linaro.org> References: <1431893048-5214-1-git-send-email-parth.dixit@linaro.org> Cc: keir@xen.org, ian.campbell@citrix.com, andrew.cooper3@citrix.com, tim@xen.org, julien.grall@citrix.com, stefano.stabellini@citrix.com, jbeulich@suse.com, parth.dixit@linaro.org, christoffer.dall@linaro.org Subject: [Xen-devel] [PATCH v2 19/41] arm : acpi Add GIC specific ACPI boot support X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: List-Unsubscribe: , List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: parth.dixit@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.49 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Archive: ACPI on Xen hypervisor uses MADT table for proper GIC initialization. It needs to parse GIC related subtables, collect CPU interface and distributor addresses and call driver initialization function (which is hardware abstraction agnostic). In a similar way, FDT initialize GICv2. Modify MADT table to clear GICH and GICV which are not needed in Dom0. NOTE: This commit allow to initialize GICv2 only. Signed-off-by: Tomasz Nowicki Signed-off-by: Hanjun Guo Signed-off-by: Naresh Bhat Signed-off-by: Parth Dixit --- xen/arch/arm/gic-v2.c | 132 +++++++++++++++++++++++++++++++++++++++++- xen/arch/arm/gic.c | 18 +++++- xen/drivers/char/arm-uart.c | 136 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 284 insertions(+), 2 deletions(-) create mode 100644 xen/drivers/char/arm-uart.c diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c index 7276951..fcdcd19 100644 --- a/xen/arch/arm/gic-v2.c +++ b/xen/arch/arm/gic-v2.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -35,6 +37,7 @@ #include #include +#include /* * LR register definitions are GIC v2 specific. @@ -692,9 +695,122 @@ static int __init dt_gicv2_init(void) return 0; } +#ifdef CONFIG_ACPI +static int __init +gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_interrupt *processor; + + processor = (struct acpi_madt_generic_interrupt *)header; + + if (BAD_MADT_ENTRY(processor, end)) + return -EINVAL; + + /* Read from APIC table and fill up the GIC variables */ + + gicv2.cbase = processor->base_address; + gicv2.hbase = processor->gich_base_address; + gicv2.vbase = processor->gicv_base_address; + gicv2_info.maintenance_irq = processor->vgic_maintenance_interrupt; + if( processor->flags & ACPI_MADT_ENABLED ) + { + if( processor->flags & ACPI_MADT_VGIC ) + set_irq_type(gicv2_info.maintenance_irq, ACPI_IRQ_TYPE_EDGE_BOTH); + else + set_irq_type(gicv2_info.maintenance_irq, ACPI_IRQ_TYPE_LEVEL_MASK); + } + + processor->gich_base_address = 0; + processor->gicv_base_address = 0; + processor->vgic_maintenance_interrupt = 0; + clean_dcache_va_range(processor, sizeof(struct acpi_madt_generic_interrupt)); + + return 0; +} + +static int __init +gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_distributor *dist; + + dist = (struct acpi_madt_generic_distributor *)header; + + if (BAD_MADT_ENTRY(dist, end)) + return -EINVAL; + + gicv2.dbase = dist->base_address; + + return 0; +} + +static int __init acpi_gicv2_init(void) +{ + acpi_status status; + struct acpi_table_header *table; + u8 checksum; + int res; + + status = acpi_get_table(ACPI_SIG_MADT, 0, &table); + + if ( ACPI_FAILURE(status) ) + { + const char *msg = acpi_format_exception(status); + printk("\nFailed to get MADT table, %s\n", msg); + return 1; + } + + /* Collect CPU base addresses */ + res = acpi_parse_entries(ACPI_SIG_MADT, + sizeof(struct acpi_table_madt), + gic_acpi_parse_madt_cpu, table, + ACPI_MADT_TYPE_GENERIC_INTERRUPT, + 0); + if ( res < 0 ) + { + printk("Error during GICC entries parsing\n"); + printk("\nFailed to initialize GIC IRQ controller\n"); + return -EINVAL; + } + + /* + * Find distributor base address. We expect one distributor entry since + * ACPI 5.0 spec neither support multi-GIC instances nor GIC cascade. + */ + res = acpi_parse_entries(ACPI_SIG_MADT, + sizeof(struct acpi_table_madt), + gic_acpi_parse_madt_distributor, table, + ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, + 0); + + if ( res < 0 ) + { + printk("Error during GICD entries parsing\n"); + printk("\nFailed to initialize GIC IRQ controller\n"); + return -EINVAL; + } + + checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), table->length); + table->checksum -= checksum; + clean_dcache_va_range(table, sizeof(struct acpi_table_header)); + + return 0; +} +#else +static int __init acpi_gicv2_init(void) +{ +/* Should never reach here */ + return -EINVAL; +} +#endif + static int gicv2_init(void) { - dt_gicv2_init(); + if( acpi_disabled ) + dt_gicv2_init(); + else + acpi_gicv2_init(); /* TODO: Add check on distributor, cpu size */ @@ -790,7 +906,21 @@ DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC) .dt_match = gicv2_dt_match, .init = dt_gicv2_preinit, DT_DEVICE_END +#ifdef CONFIG_ACPI +/* Set up the GIC */ +static int __init acpi_gicv2_preinit(const void *data) +{ + gicv2_info.hw_version = GIC_V2; + register_gic_ops(&gicv2_ops); + + return 0; +} +ACPI_DEVICE_START(agicv2, "GICv2", DEVICE_GIC) + .class_type = GIC_V2, + .init = acpi_gicv2_preinit, +ACPI_DEVICE_END +#endif /* * Local variables: * mode: C diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c index 701c306..e33bfd7 100644 --- a/xen/arch/arm/gic.c +++ b/xen/arch/arm/gic.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include static void gic_restore_pending_irqs(struct vcpu *v); @@ -261,9 +263,23 @@ void __init dt_gic_preinit(void) dt_device_set_used_by(node, DOMID_XEN); } +static void __init acpi_gic_init(void) +{ + int rc; + + /* NOTE: Only one GIC is supported */ + /* hardcode to gic v2 for now */ + rc = acpi_device_init(DEVICE_GIC, NULL, GIC_V2); + if ( rc ) + panic("Unable to find compatible GIC in the ACPI table"); +} + void __init gic_preinit(void) { - dt_gic_preinit(); + if( acpi_disabled ) + dt_gic_preinit(); + else + acpi_gic_init(); } /* Set up the GIC */ diff --git a/xen/drivers/char/arm-uart.c b/xen/drivers/char/arm-uart.c new file mode 100644 index 0000000..2603508 --- /dev/null +++ b/xen/drivers/char/arm-uart.c @@ -0,0 +1,136 @@ +/* + * xen/drivers/char/dt-uart.c + * + * Generic uart retrieved via the device tree + * + * Julien Grall + * Copyright (c) 2013 Linaro Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Configure UART port with a string: + * path:options + * + * @path: full path used in the device tree for the UART. If the path + * doesn't start with '/', we assuming that it's an alias. + * @options: UART speficic options (see in each UART driver) + */ +static char __initdata opt_dtuart[256] = ""; +string_param("dtuart", opt_dtuart); + +static void __init dt_uart_init(void) +{ + struct dt_device_node *dev; + int ret; + const char *devpath = opt_dtuart; + char *options; + + if ( !console_has("dtuart") ) + return; /* Not for us */ + + if ( !strcmp(opt_dtuart, "") ) + { + const struct dt_device_node *chosen = dt_find_node_by_path("/chosen"); + + if ( chosen ) + { + const char *stdout; + + ret = dt_property_read_string(chosen, "stdout-path", &stdout); + if ( ret >= 0 ) + { + printk("Taking dtuart configuration from /chosen/stdout-path\n"); + if ( strlcpy(opt_dtuart, stdout, sizeof(opt_dtuart)) + >= sizeof(opt_dtuart) ) + printk("WARNING: /chosen/stdout-path too long, truncated\n"); + } + else if ( ret != -EINVAL /* Not present */ ) + printk("Failed to read /chosen/stdout-path (%d)\n", ret); + } + } + + if ( !strcmp(opt_dtuart, "") ) + { + printk("No dtuart path configured\n"); + return; + } + + options = strchr(opt_dtuart, ':'); + if ( options != NULL ) + *(options++) = '\0'; + else + options = ""; + + printk("Looking for dtuart at \"%s\", options \"%s\"\n", devpath, options); + if ( *devpath == '/' ) + dev = dt_find_node_by_path(devpath); + else + dev = dt_find_node_by_alias(devpath); + + if ( !dev ) + { + printk("Unable to find device \"%s\"\n", devpath); + return; + } + + ret = device_init(dev, DEVICE_SERIAL, options); + + if ( ret ) + printk("Unable to initialize dtuart: %d\n", ret); +} + +static void __init acpi_uart_init(void) +{ +#ifdef CONFIG_ACPI + struct acpi_table_spcr *spcr=NULL; + int ret; + + acpi_get_table(ACPI_SIG_SPCR, 0,(struct acpi_table_header **)&spcr); + + if ( spcr == NULL ) + printk("Unable to get spcr table\n"); + else + { + ret = acpi_device_init(DEVICE_SERIAL, NULL, spcr->interface_type); + + if ( ret ) + printk("Unable to initialize acpi uart: %d\n", ret); + } +#endif +} + +void __init uart_init(void) +{ + if ( acpi_disabled ) + dt_uart_init(); + else + acpi_uart_init(); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */