Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1323462 > unrolled thread

[PATCH v3 0/6] acpi, clocksource, kvm: add GTDT and ARM memory-mapped timer support

Started byfu.wei@linaro.org
First post2016-02-01 21:30 +0100
Last post2016-02-01 21:30 +0100
Articles 3 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH v3 0/6] acpi, clocksource, kvm: add GTDT and ARM memory-mapped timer support fu.wei@linaro.org - 2016-02-01 21:30 +0100
    [PATCH v3 3/6] clocksource: add memory-mapped timer support in arm_arch_timer.c fu.wei@linaro.org - 2016-02-01 21:30 +0100
    [PATCH v3 5/6] kvm: arm64: wrapping DT support for virt arch timer fu.wei@linaro.org - 2016-02-01 21:30 +0100

#1323462 — [PATCH v3 0/6] acpi, clocksource, kvm: add GTDT and ARM memory-mapped timer support

Fromfu.wei@linaro.org
Date2016-02-01 21:30 +0100
Subject[PATCH v3 0/6] acpi, clocksource, kvm: add GTDT and ARM memory-mapped timer support
Message-ID<qXtgK-8eB-5@gated-at.bofh.it>
From: Fu Wei <fu.wei@linaro.org>

This patchset:
    (1)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
    Parse all kinds of timer in GTDT table of ACPI:arch timer,
    memory-mapped timer and SBSA Generic Watchdog timer.
    This driver can help to simplify all the relevant timer drivers,
    and separate all the ACPI GTDT knowledge from them.

    (2)Simplify ACPI code for arch timer in arm_arch_timer.c

    (3)Add memory-mapped timer support in arm_arch_timer.c

    (4)Add arm_arch_timer get ppi from DT and GTDT support for kvm
    in virt/kvm/arm/arch_timer.c

Changelog:
v3: Improve GTDT driver code:
      (1)improve pr_* by defining pr_fmt(fmt)
      (2)simplify gtdt_sbsa_gwdt_init
      (3)improve gtdt_arch_timer_data_init, if table is NULL, it will try
      to get GTDT table.
    Move enum ppi_nr to arm_arch_timer.h, and add enum spi_nr.
    Add arm_arch_timer get ppi from DT and GTDT support for kvm.

v2: https://lkml.org/lkml/2015/12/2/10
    Rebase to latest kernel version(4.4-rc3).
    Fix the bug about the config problem,
    use CONFIG_ACPI_GTDT instead of CONFIG_ACPI in arm_arch_timer.c

v1: The first upstreaming version: https://lkml.org/lkml/2015/10/28/553

Fu Wei (5):
  ACPI: add GTDT table parse driver into ACPI driver
  clocksource: simplify ACPI code in arm_arch_timer.c
  clocksource: add memory-mapped timer support in arm_arch_timer.c
  clocksource: move some enums to arm_arch_timer.h
  kvm: arm64: Add ACPI support for virt arch timer

Wei Huang (1):
  kvm: arm64: wrapping DT support for virt arch timer

 drivers/acpi/Kconfig                 |   9 +
 drivers/acpi/Makefile                |   1 +
 drivers/acpi/gtdt.c                  | 375 +++++++++++++++++++++++++++++++++++
 drivers/clocksource/Kconfig          |   1 +
 drivers/clocksource/arm_arch_timer.c | 191 +++++++++++++-----
 include/clocksource/arm_arch_timer.h |  33 +++
 include/linux/acpi.h                 |  17 ++
 virt/kvm/arm/arch_timer.c            |  57 ++++--
 8 files changed, 620 insertions(+), 64 deletions(-)
 create mode 100644 drivers/acpi/gtdt.c

-- 
2.5.0

[toc] | [next] | [standalone]


#1323464 — [PATCH v3 3/6] clocksource: add memory-mapped timer support in arm_arch_timer.c

Fromfu.wei@linaro.org
Date2016-02-01 21:30 +0100
Subject[PATCH v3 3/6] clocksource: add memory-mapped timer support in arm_arch_timer.c
Message-ID<qXtgM-8eB-31@gated-at.bofh.it>
In reply to#1323462
From: Fu Wei <fu.wei@linaro.org>

The patch add memory-mapped timer register support for arm_arch_timer driver
by using the information provided by the new GTDT driver of ACPI.

Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 136 +++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 87d6bae..3792fd6 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -666,6 +666,15 @@ arch_timer_needs_probing(int type, const struct of_device_id *matches)
 		needs_probing = true;
 	of_node_put(dn);
 
+#ifdef CONFIG_ACPI_GTDT
+	/*
+	 * Check if we have timer in GTDT table
+	 */
+	if (!acpi_disabled && gtdt_timer_is_available(type) &&
+	    !(arch_timers_present & type))
+		needs_probing = true;
+#endif
+
 	return needs_probing;
 }
 
@@ -835,4 +844,131 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 	return 0;
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
+
+static u32 __init arch_timer_mem_cnttidr(struct acpi_gtdt_timer_block *gt_block)
+{
+	phys_addr_t cntctlbase_phy;
+	void __iomem *cntctlbase;
+	u32 cnttidr;
+
+	cntctlbase_phy = (phys_addr_t)gtdt_gt_cntctlbase(gt_block);
+	if (!cntctlbase_phy) {
+		pr_err("arch_timer: Can't find CNTCTLBase.\n");
+		return 0;
+	}
+
+	/*
+	 * According to ARMv8 Architecture Reference Manual(ARM),
+	 * the size of CNTCTLBase frame of memory-mapped timer
+	 * is SZ_4K(Offset 0x000 – 0xFFF).
+	 */
+	cntctlbase = ioremap(cntctlbase_phy, SZ_4K);
+	if (!cntctlbase) {
+		pr_err("arch_timer: Can't map CNTCTLBase\n");
+		return 0;
+	}
+	cnttidr = readl_relaxed(cntctlbase + CNTTIDR);
+	iounmap(cntctlbase);
+
+	return cnttidr;
+}
+
+static int __init arch_timer_mem_best_frame(struct acpi_table_header *table,
+					    struct arch_timer_mem_data *data)
+{
+	struct acpi_gtdt_timer_block *gt_block;
+	u32 frame_number, timer_count, cnttidr;
+	int i;
+
+	gt_block = gtdt_gt_block(table, 0);
+	if (!gt_block) {
+		pr_err("arch_timer: Can't find GT Block.\n");
+		return -EINVAL;
+	}
+
+	timer_count = gtdt_gt_timer_count(gt_block);
+	if (!timer_count) {
+		pr_err("arch_timer: Can't find GT frame number.\n");
+		return -EINVAL;
+	}
+
+	if (gtdt_gt_timer_data(gt_block, 0, false, data)) {
+		pr_err("arch_timer: Can't get first phy timer.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Get Generic Timer Counter-timer Timer ID Register
+	 * for Virtual Timer Capability info
+	 */
+	cnttidr = arch_timer_mem_cnttidr(gt_block);
+
+	/*
+	 * Try to find a virtual capable frame.
+	 * Otherwise fall back to the first physical capable frame.
+	 */
+	for (i = 0; i < timer_count; i++) {
+		frame_number = gtdt_gt_frame_number(gt_block, i);
+		if (frame_number < ARCH_TIMER_MEM_MAX_FRAME &&
+		    cnttidr & CNTTIDR_VIRT(frame_number)) {
+			if (!gtdt_gt_timer_data(gt_block, i, true, data)) {
+				arch_timer_mem_use_virtual = true;
+				return 0;
+			}
+			pr_warn("arch_timer: Can't get virt timer.\n");
+		}
+	}
+
+	return 0;
+}
+
+/* Initialize memory-mapped timer(wake-up timer) */
+static int __init arch_timer_mem_acpi_init(struct acpi_table_header *table)
+{
+	struct arch_timer_mem_data data;
+	void __iomem *cntbase;
+
+	if (arch_timers_present & ARCH_MEM_TIMER) {
+		pr_warn("arch_timer_mem: already initialized, skipping\n");
+		return -EINVAL;
+	}
+	arch_timers_present |= ARCH_MEM_TIMER;
+
+	if (arch_timer_mem_best_frame(table, &data))
+		return -EINVAL;
+
+	/*
+	 * According to ARMv8 Architecture Reference Manual(ARM),
+	 * the size of CNTBaseN frames of memory-mapped timer
+	 * is SZ_4K(Offset 0x000 – 0xFFF).
+	 */
+	cntbase = ioremap(data.cntbase_phy, SZ_4K);
+	if (!cntbase) {
+		pr_err("arch_timer: Can't map CntBase.\n");
+		return -EINVAL;
+	}
+	arch_counter_base = cntbase;
+
+	if (!data.irq) {
+		pr_err("arch_timer: Frame missing %s irq",
+		       arch_timer_mem_use_virtual ? "virt" : "phys");
+		return -EINVAL;
+	}
+
+	/*
+	 * Because in a system that implements both Secure and
+	 * Non-secure states, CNTFRQ is only accessible in Secure state.
+	 * So we try to get the system counter frequency from cntfrq_el0
+	 * (system coprocessor register) here just like arch_timer.
+	 */
+	arch_timer_detect_rate(NULL, NULL);
+
+	arch_timer_mem_register(cntbase, data.irq);
+	arch_timer_common_init();
+
+	return 0;
+}
+
+CLOCKSOURCE_ACPI_DECLARE(arch_timer_mem, ACPI_SIG_GTDT,
+			 arch_timer_mem_acpi_init);
 #endif
-- 
2.5.0

[toc] | [prev] | [next] | [standalone]


#1323465 — [PATCH v3 5/6] kvm: arm64: wrapping DT support for virt arch timer

Fromfu.wei@linaro.org
Date2016-02-01 21:30 +0100
Subject[PATCH v3 5/6] kvm: arm64: wrapping DT support for virt arch timer
Message-ID<qXtgM-8eB-33@gated-at.bofh.it>
In reply to#1323462
From: Wei Huang <wei@redhat.com>

This patches wrapping DT support for virt arch timer into a function.

[Fu Wei: improve the DT support, and separate ACPI support]

Signed-off-by: Alexander Spyridaki <a.spyridakis@virtualopensystems.com>
Signed-off-by: Wei Huang <wei@redhat.com>
Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org>
Signed-off-by: Fu Wei <fu.wei@linaro.org>
---
 virt/kvm/arm/arch_timer.c | 49 +++++++++++++++++++++++++++++++----------------
 1 file changed, 32 insertions(+), 17 deletions(-)

diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 69bca185..0a279d3 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -381,9 +381,30 @@ static const struct of_device_id arch_timer_of_match[] = {
 	{},
 };
 
-int kvm_timer_hyp_init(void)
+static int kvm_timer_get_ppi(unsigned int *ppi)
 {
 	struct device_node *np;
+	int ret = -EINVAL;
+
+	np = of_find_matching_node(NULL, arch_timer_of_match);
+	if (!np) {
+		ret = -ENODEV;
+		*ppi = 0;
+		goto skip_of;
+	}
+
+	*ppi = irq_of_parse_and_map(np, VIRT_PPI);
+	of_node_put(np);
+
+skip_of:
+	if (*ppi)
+		return 0;
+
+	return ret;
+}
+
+int kvm_timer_hyp_init(void)
+{
 	unsigned int ppi;
 	int err;
 
@@ -391,17 +412,11 @@ int kvm_timer_hyp_init(void)
 	if (!timecounter)
 		return -ENODEV;
 
-	np = of_find_matching_node(NULL, arch_timer_of_match);
-	if (!np) {
-		kvm_err("kvm_arch_timer: can't find DT node\n");
-		return -ENODEV;
-	}
-
-	ppi = irq_of_parse_and_map(np, 2);
-	if (!ppi) {
-		kvm_err("kvm_arch_timer: no virtual timer interrupt\n");
-		err = -EINVAL;
-		goto out;
+	err = kvm_timer_get_ppi(&ppi);
+	if (err) {
+		kvm_err("kvm_arch_timer: can't find virtual timer info or "
+			"config virtual timer interrupt.\n");
+		return err;
 	}
 
 	err = request_percpu_irq(ppi, kvm_arch_timer_handler,
@@ -409,7 +424,7 @@ int kvm_timer_hyp_init(void)
 	if (err) {
 		kvm_err("kvm_arch_timer: can't request interrupt %d (%d)\n",
 			ppi, err);
-		goto out;
+		return err;
 	}
 
 	host_vtimer_irq = ppi;
@@ -426,14 +441,14 @@ int kvm_timer_hyp_init(void)
 		goto out_free;
 	}
 
-	kvm_info("%s IRQ%d\n", np->name, ppi);
+	kvm_info("timer IRQ%d.\n", ppi);
 	on_each_cpu(kvm_timer_init_interrupt, NULL, 1);
 
-	goto out;
+	return 0;
+
 out_free:
 	free_percpu_irq(ppi, kvm_get_running_vcpus());
-out:
-	of_node_put(np);
+
 	return err;
 }
 
-- 
2.5.0

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web