From patchwork Fri Jun 19 08:46:06 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hanjun Guo X-Patchwork-Id: 6643651 Return-Path: X-Original-To: patchwork-linux-acpi@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 B5E469F3D1 for ; Fri, 19 Jun 2015 08:47:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BEE2C20414 for ; Fri, 19 Jun 2015 08:47:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A4EC02096B for ; Fri, 19 Jun 2015 08:47:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754768AbbFSIra (ORCPT ); Fri, 19 Jun 2015 04:47:30 -0400 Received: from mail-pa0-f47.google.com ([209.85.220.47]:33581 "EHLO mail-pa0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754650AbbFSIqn (ORCPT ); Fri, 19 Jun 2015 04:46:43 -0400 Received: by padev16 with SMTP id ev16so81010915pad.0 for ; Fri, 19 Jun 2015 01:46:42 -0700 (PDT) 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=wwYRDOaeyublQsrgzONWgSefDS1XXZSWIO2ygzIEPAk=; b=kLYkoamuaqxgjiAn5xXvxE2/hBci4IB57P8Wkaovtfla6RxT/7GsFQuRaMHblDBNAf llev6jlDGtbgHhwv95BIUPTkbZekMARaWoVkor8MYc6HDtqXTEpLXt0utcb30ihbB9BG wntJZSQa7cywrau6mKwv9zfdxo/KaVIREGPdBFSztrZm90qTo9JLVl8IA5954xPj5b28 /Zmqd85+25K9wc+UfAuvXFoe8JUqcXqHZ/JwoPjxvrh6usin5LU4jz3cdlcS3PJGZHCE mD6BlHgU3AvnN5RcNJheB9BUiU5gB67hKpmsf1O8VZlctKHHCqLDuz/TJAP+0loUoUIp DbFQ== X-Gm-Message-State: ALoCoQlzcryk9OpcxJMATMZ64acW+aaPu5dfiXLrIhYCgQYx3erDOMzACH+iW8RvmmQ/gVmDwt66 X-Received: by 10.66.65.138 with SMTP id x10mr15327274pas.97.1434703602753; Fri, 19 Jun 2015 01:46:42 -0700 (PDT) Received: from localhost ([180.150.157.4]) by mx.google.com with ESMTPSA id ks7sm10414404pbc.34.2015.06.19.01.46.41 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 19 Jun 2015 01:46:41 -0700 (PDT) From: Hanjun Guo To: Marc Zyngier , Jason Cooper , Will Deacon , Catalin Marinas , "Rafael J. Wysocki" Cc: Thomas Gleixner , Jiang Liu , Lorenzo Pieralisi , Arnd Bergmann , Tomasz Nowicki , Grant Likely , Olof Johansson , Wei Huang , linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, linaro-acpi@lists.linaro.org, Hanjun Guo Subject: [PATCH v2 3/9] irqchip / GIC: Add GIC version support in ACPI MADT Date: Fri, 19 Jun 2015 16:46:06 +0800 Message-Id: <1434703572-26221-4-git-send-email-hanjun.guo@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1434703572-26221-1-git-send-email-hanjun.guo@linaro.org> References: <1434703572-26221-1-git-send-email-hanjun.guo@linaro.org> Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Spam-Status: No, score=-7.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable 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 There is a field added in ACPI MADT table to indicate the GIC version, so parse the table to get its value for later use. If GIC version presented in MADT is 0, we need to fallback to hardware discovery to get the GIC version. In ACPI MADT table there is no compatible strings to indicate various irqchips and also ACPI doesn't support irqchips which are not compatible with ARM GIC spec, so GIC version can be used to load different GIC drivers which is needed for the later patch. Signed-off-by: Hanjun Guo --- arch/arm64/Kconfig | 1 + drivers/irqchip/Kconfig | 3 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-gic-acpi.c | 112 +++++++++++++++++++++++++++++++++++ include/linux/irqchip/arm-gic-acpi.h | 1 + 5 files changed, 118 insertions(+) create mode 100644 drivers/irqchip/irq-gic-acpi.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index c273e4a..9d62bbb 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -16,6 +16,7 @@ config ARM64 select ARM_AMBA select ARM_ARCH_TIMER select ARM_GIC + select ARM_GIC_ACPI if ACPI select AUDIT_ARCH_COMPAT_GENERIC select ARM_GIC_V2M if PCI_MSI select ARM_GIC_V3 diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 6de62a9..0dd64c5 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -46,6 +46,9 @@ config ARM_VIC_NR The maximum number of VICs available in the system, for power management. +config ARM_GIC_ACPI + bool + config ATMEL_AIC_IRQ bool select GENERIC_IRQ_CHIP diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index dda4927..0bd8e49 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o +obj-$(CONFIG_ARM_GIC_ACPI) += irq-gic-acpi.o obj-$(CONFIG_ARM_NVIC) += irq-nvic.o obj-$(CONFIG_ARM_VIC) += irq-vic.o obj-$(CONFIG_ATMEL_AIC_IRQ) += irq-atmel-aic-common.o irq-atmel-aic.o diff --git a/drivers/irqchip/irq-gic-acpi.c b/drivers/irqchip/irq-gic-acpi.c new file mode 100644 index 0000000..58f7831 --- /dev/null +++ b/drivers/irqchip/irq-gic-acpi.c @@ -0,0 +1,112 @@ +/* + * ACPI based support for ARM GIC init + * + * Copyright (C) 2015, Linaro Ltd. + * Author: Hanjun Guo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) "ACPI: GIC: " fmt + +#include +#include +#include +#include + +/* GIC version presented in MADT GIC distributor structure */ +static u8 gic_version __initdata = ACPI_MADT_GIC_VERSION_NONE; + +static phys_addr_t dist_phy_base __initdata; + +static int __init +acpi_gic_parse_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; + + gic_version = dist->version; + dist_phy_base = dist->base_address; + return 0; +} + +static int __init +match_gic_redist(struct acpi_subtable_header *header, const unsigned long end) +{ + return 0; +} + +static bool __init acpi_gic_redist_is_present(void) +{ + int count; + + /* scan MADT table to find if we have redistributor entries */ + count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, + match_gic_redist, 0); + + /* has at least one GIC redistributor entry */ + if (count > 0) + return true; + else + return false; +} + +static int __init acpi_gic_version_init(void) +{ + int count; + void __iomem *dist_base; + u32 reg; + + count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, + acpi_gic_parse_distributor, 0); + + if (count <= 0) { + pr_err("No valid GIC distributor entry exists\n"); + return -ENODEV; + } + + if (gic_version >= ACPI_MADT_GIC_VERSION_RESERVED) { + pr_err("Invalid GIC version %d in MADT\n", gic_version); + return -EINVAL; + } + + /* + * when the GIC version is 0, we fallback to hardware discovery. + * this is also needed to keep compatiable with ACPI 5.1, + * which has no gic_version field in distributor structure and + * reserved as 0. + * + * For hardware discovery, the offset for GICv1/2 and GICv3/4 to + * get the GIC version is different (0xFE8 for GICv1/2 and 0xFFE8 + * for GICv3/4), so we need to handle it separately. + */ + if (gic_version == ACPI_MADT_GIC_VERSION_NONE) { + /* it's GICv3/v4 if redistributor is present */ + if (acpi_gic_redist_is_present()) { + dist_base = ioremap(dist_phy_base, + ACPI_GICV3_DIST_MEM_SIZE); + if (!dist_base) + return -ENOMEM; + + reg = readl_relaxed(dist_base + GICD_PIDR2) & + GIC_PIDR2_ARCH_MASK; + if (reg == GIC_PIDR2_ARCH_GICv3) + gic_version = ACPI_MADT_GIC_VERSION_V3; + else + gic_version = ACPI_MADT_GIC_VERSION_V4; + + iounmap(dist_base); + } else { + gic_version = ACPI_MADT_GIC_VERSION_V2; + } + } + + return 0; +} diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h index de3419e..13bc676 100644 --- a/include/linux/irqchip/arm-gic-acpi.h +++ b/include/linux/irqchip/arm-gic-acpi.h @@ -19,6 +19,7 @@ */ #define ACPI_GICV2_DIST_MEM_SIZE (SZ_4K) #define ACPI_GIC_CPU_IF_MEM_SIZE (SZ_8K) +#define ACPI_GICV3_DIST_MEM_SIZE (SZ_64K) struct acpi_table_header;