From mboxrd@z Thu Jan 1 00:00:00 1970 From: fu.wei@linaro.org Subject: [PATCH v20 15/17] acpi/arm64: Add memory-mapped timer support in GTDT driver Date: Wed, 18 Jan 2017 21:25:39 +0800 Message-ID: <20170118132541.8989-16-fu.wei@linaro.org> References: <20170118132541.8989-1-fu.wei@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20170118132541.8989-1-fu.wei@linaro.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org To: rjw@rjwysocki.net, lenb@kernel.org, daniel.lezcano@linaro.org, tglx@linutronix.de, marc.zyngier@arm.com, mark.rutland@arm.com, lorenzo.pieralisi@arm.com, sudeep.holla@arm.com, hanjun.guo@linaro.org Cc: linaro-acpi@lists.linaro.org, catalin.marinas@arm.com, will.deacon@arm.com, linux-kernel@vger.kernel.org, wim@iguana.be, Fu Wei , wei@redhat.com, al.stone@linaro.org, tn@semihalf.com, timur@codeaurora.org, linux-acpi@vger.kernel.org, linux@roeck-us.net, harba@codeaurora.org, julien.grall@arm.com, linux-watchdog@vger.kernel.org, arnd@arndb.de, jcm@redhat.com, cov@codeaurora.org, linux-arm-kernel@lists.infradead.org, graeme.gregory@linaro.org, rruigrok@codeaurora.org, leo.duran@amd.com, Suravee.Suthikulpanit@amd.com, christoffer.dall@linaro.org List-Id: linux-acpi@vger.kernel.org RnJvbTogRnUgV2VpIDxmdS53ZWlAbGluYXJvLm9yZz4KCk9uIHBsYXRmb3JtcyBib290aW5nIHdp dGggQUNQSSwgYXJjaGl0ZWN0ZWQgbWVtb3J5LW1hcHBlZCB0aW1lcnMnCmNvbmZpZ3VyYXRpb24g ZGF0YSBpcyBwcm92aWRlZCBieSBmaXJtd2FyZSB0aHJvdWdoIHRoZSBBQ1BJIEdURFQKc3RhdGlj IHRhYmxlLgoKVGhlIGNsb2Nrc291cmNlIGFyY2hpdGVjdGVkIHRpbWVyIGtlcm5lbCBkcml2ZXIg cmVxdWlyZXMgYSBmaXJtd2FyZQppbnRlcmZhY2UgdG8gY29sbGVjdCB0aW1lciBjb25maWd1cmF0 aW9uIGFuZCBjb25maWd1cmUgaXRzIGRyaXZlci4KdGhpcyBpbmZyYXN0cnVjdHVyZSBpcyBwcmVz ZW50IGZvciBkZXZpY2UgdHJlZSBzeXN0ZW1zLCBidXQgaXQgaXMKbWlzc2luZyBvbiBzeXN0ZW1z IGJvb3Rpbmcgd2l0aCBBQ1BJLgoKSW1wbGVtZW50IHRoZSBrZXJuZWwgaW5mcmFzdHJ1Y3R1cmUg cmVxdWlyZWQgdG8gcGFyc2UgdGhlIHN0YXRpYwpBQ1BJIEdURFQgdGFibGUgc28gdGhhdCB0aGUg YXJjaGl0ZWN0ZWQgdGltZXIgY2xvY2tzb3VyY2UgZHJpdmVyIGNhbgptYWtlIHVzZSBvZiBpdCBv biBzeXN0ZW1zIGJvb3Rpbmcgd2l0aCBBQ1BJLCB0aGVyZWZvcmUgZW5hYmxpbmcKdGhlIGNvcnJl c3BvbmRpbmcgdGltZXJzIGNvbmZpZ3VyYXRpb24uCgpTaWduZWQtb2ZmLWJ5OiBGdSBXZWkgPGZ1 LndlaUBsaW5hcm8ub3JnPgpTaWduZWQtb2ZmLWJ5OiBIYW5qdW4gR3VvIDxoYW5qdW4uZ3VvQGxp bmFyby5vcmc+Ci0tLQogZHJpdmVycy9hY3BpL2FybTY0L2d0ZHQuYyB8IDEyNCArKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCiBpbmNsdWRlL2xpbnV4L2FjcGku aCAgICAgIHwgICAxICsKIDIgZmlsZXMgY2hhbmdlZCwgMTI1IGluc2VydGlvbnMoKykKCmRpZmYg LS1naXQgYS9kcml2ZXJzL2FjcGkvYXJtNjQvZ3RkdC5jIGIvZHJpdmVycy9hY3BpL2FybTY0L2d0 ZHQuYwppbmRleCBkOTNhNzkwLi45MWVhNmNiIDEwMDY0NAotLS0gYS9kcml2ZXJzL2FjcGkvYXJt NjQvZ3RkdC5jCisrKyBiL2RyaXZlcnMvYWNwaS9hcm02NC9ndGR0LmMKQEAgLTM3LDYgKzM3LDI4 IEBAIHN0cnVjdCBhY3BpX2d0ZHRfZGVzY3JpcHRvciB7CiAKIHN0YXRpYyBzdHJ1Y3QgYWNwaV9n dGR0X2Rlc2NyaXB0b3IgYWNwaV9ndGR0X2Rlc2MgX19pbml0ZGF0YTsKIAorc3RhdGljIGlubGlu ZSB2b2lkICpuZXh0X3BsYXRmb3JtX3RpbWVyKHZvaWQgKnBsYXRmb3JtX3RpbWVyKQoreworCXN0 cnVjdCBhY3BpX2d0ZHRfaGVhZGVyICpnaCA9IHBsYXRmb3JtX3RpbWVyOworCisJcGxhdGZvcm1f dGltZXIgKz0gZ2gtPmxlbmd0aDsKKwlpZiAocGxhdGZvcm1fdGltZXIgPCBhY3BpX2d0ZHRfZGVz Yy5ndGR0X2VuZCkKKwkJcmV0dXJuIHBsYXRmb3JtX3RpbWVyOworCisJcmV0dXJuIE5VTEw7Cit9 CisKKyNkZWZpbmUgZm9yX2VhY2hfcGxhdGZvcm1fdGltZXIoX2cpCQkJCVwKKwlmb3IgKF9nID0g YWNwaV9ndGR0X2Rlc2MucGxhdGZvcm1fdGltZXI7IF9nOwlcCisJICAgICBfZyA9IG5leHRfcGxh dGZvcm1fdGltZXIoX2cpKQorCitzdGF0aWMgaW5saW5lIGJvb2wgaXNfdGltZXJfYmxvY2sodm9p ZCAqcGxhdGZvcm1fdGltZXIpCit7CisJc3RydWN0IGFjcGlfZ3RkdF9oZWFkZXIgKmdoID0gcGxh dGZvcm1fdGltZXI7CisKKwlyZXR1cm4gZ2gtPnR5cGUgPT0gQUNQSV9HVERUX1RZUEVfVElNRVJf QkxPQ0s7Cit9CisKIHN0YXRpYyBpbnQgX19pbml0IG1hcF9ndF9nc2kodTMyIGludGVycnVwdCwg dTMyIGZsYWdzKQogewogCWludCB0cmlnZ2VyLCBwb2xhcml0eTsKQEAgLTE1NSwzICsxNzcsMTA1 IEBAIGludCBfX2luaXQgYWNwaV9ndGR0X2luaXQoc3RydWN0IGFjcGlfdGFibGVfaGVhZGVyICp0 YWJsZSwKIAogCXJldHVybiByZXQ7CiB9CisKK3N0YXRpYyBpbnQgX19pbml0IGd0ZHRfcGFyc2Vf dGltZXJfYmxvY2soc3RydWN0IGFjcGlfZ3RkdF90aW1lcl9ibG9jayAqYmxvY2ssCisJCQkJCSBz dHJ1Y3QgYXJjaF90aW1lcl9tZW0gKmRhdGEpCit7CisJaW50IGk7CisJc3RydWN0IGFjcGlfZ3Rk dF90aW1lcl9lbnRyeSAqZnJhbWU7CisKKwlpZiAoIWJsb2NrLT50aW1lcl9jb3VudCkgeworCQlw cl9lcnIoRldfQlVHICJHVCBibG9jayBwcmVzZW50LCBidXQgZnJhbWUgY291bnQgaXMgemVyby4i KTsKKwkJcmV0dXJuIC1FTk9ERVY7CisJfQorCisJaWYgKGJsb2NrLT50aW1lcl9jb3VudCA+IEFS Q0hfVElNRVJfTUVNX01BWF9GUkFNRVMpIHsKKwkJcHJfZXJyKEZXX0JVRyAiR1QgYmxvY2sgbGlz dHMgJWQgZnJhbWVzLCBBQ1BJIHNwZWMgb25seSBhbGxvd3MgOFxuIiwKKwkJICAgICAgIGJsb2Nr LT50aW1lcl9jb3VudCk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWRhdGEtPmNudGN0bGJh c2UgPSAocGh5c19hZGRyX3QpYmxvY2stPmJsb2NrX2FkZHJlc3M7CisJLyoKKwkgKiBBY2NvcmRp bmcgdG8gIlRhYmxlICogQ05UQ1RMQmFzZSBtZW1vcnkgbWFwIiBvZgorCSAqIDxBUk0gQXJjaGl0 ZWN0dXJlIFJlZmVyZW5jZSBNYW51YWw+IGZvciBBUk12OCwKKwkgKiBUaGUgc2l6ZSBvZiB0aGUg Q05UQ1RMQmFzZSBmcmFtZSBpcyA0S0IoT2Zmc2V0IDB4MDAwIOKAkyAweEZGQykuCisJICovCisJ ZGF0YS0+c2l6ZSA9IFNaXzRLOworCWRhdGEtPm51bV9mcmFtZXMgPSBibG9jay0+dGltZXJfY291 bnQ7CisKKwlmcmFtZSA9ICh2b2lkICopYmxvY2sgKyBibG9jay0+dGltZXJfb2Zmc2V0OworCWlm IChmcmFtZSArIGJsb2NrLT50aW1lcl9jb3VudCAhPSAodm9pZCAqKWJsb2NrICsgYmxvY2stPmhl YWRlci5sZW5ndGgpCisJCXJldHVybiAtRUlOVkFMOworCisJLyoKKwkgKiBHZXQgdGhlIEdUIHRp bWVyIEZyYW1lIGRhdGEgZm9yIGV2ZXJ5IEdUIEJsb2NrIFRpbWVyCisJICovCisJZm9yIChpID0g MDsgaSA8IGJsb2NrLT50aW1lcl9jb3VudDsgaSsrLCBmcmFtZSsrKSB7CisJCWlmICghZnJhbWUt PmJhc2VfYWRkcmVzcyB8fCAhZnJhbWUtPnRpbWVyX2ludGVycnVwdCkKKwkJCXJldHVybiAtRUlO VkFMOworCisJCWRhdGEtPmZyYW1lW2ldLnBoeXNfaXJxID0gbWFwX2d0X2dzaShmcmFtZS0+dGlt ZXJfaW50ZXJydXB0LAorCQkJCQkJICAgICBmcmFtZS0+dGltZXJfZmxhZ3MpOworCQlpZiAoZGF0 YS0+ZnJhbWVbaV0ucGh5c19pcnEgPD0gMCkgeworCQkJcHJfd2FybigiZmFpbGVkIHRvIG1hcCBw aHlzaWNhbCB0aW1lciBpcnEgaW4gZnJhbWUgJWQuXG4iLAorCQkJCWkpOworCQkJcmV0dXJuIC1F SU5WQUw7CisJCX0KKworCQlkYXRhLT5mcmFtZVtpXS52aXJ0X2lycSA9CisJCQltYXBfZ3RfZ3Np KGZyYW1lLT52aXJ0dWFsX3RpbWVyX2ludGVycnVwdCwKKwkJCQkgICBmcmFtZS0+dmlydHVhbF90 aW1lcl9mbGFncyk7CisJCWlmIChkYXRhLT5mcmFtZVtpXS52aXJ0X2lycSA8PSAwKSB7CisJCQlw cl93YXJuKCJmYWlsZWQgdG8gbWFwIHZpcnR1YWwgdGltZXIgaXJxIGluIGZyYW1lICVkLlxuIiwK KwkJCQlpKTsKKwkJCWFjcGlfdW5yZWdpc3Rlcl9nc2koZnJhbWUtPnRpbWVyX2ludGVycnVwdCk7 CisJCQlyZXR1cm4gLUVJTlZBTDsKKwkJfQorCisJCWRhdGEtPmZyYW1lW2ldLmZyYW1lX25yID0g ZnJhbWUtPmZyYW1lX251bWJlcjsKKwkJZGF0YS0+ZnJhbWVbaV0uY250YmFzZSA9IGZyYW1lLT5i YXNlX2FkZHJlc3M7CisJCS8qCisJCSAqIEFjY29yZGluZyB0byAiVGFibGUgKiBDTlRCYXNlTiBt ZW1vcnkgbWFwIiBvZgorCQkgKiA8QVJNIEFyY2hpdGVjdHVyZSBSZWZlcmVuY2UgTWFudWFsPiBm b3IgQVJNdjgsCisJCSAqIFRoZSBzaXplIG9mIHRoZSBDTlRCYXNlTiBmcmFtZSBpcyA0S0IoT2Zm c2V0IDB4MDAwIOKAkyAweEZGQykuCisJCSAqLworCQlkYXRhLT5mcmFtZVtpXS5zaXplID0gU1pf NEs7CisJfQorCisJcmV0dXJuIDA7Cit9CisKKy8qKgorICogYWNwaV9hcmNoX3RpbWVyX21lbV9p bml0KCkgLSBHZXQgdGhlIGluZm8gb2YgYWxsIEdUIGJsb2NrcyBpbiBHVERUIHRhYmxlLgorICog QGRhdGE6CXRoZSBwb2ludGVyIHRvIHRoZSBhcnJheSBvZiBzdHJ1Y3QgYXJjaF90aW1lcl9tZW0g Zm9yIHJldHVybmluZworICoJCXRoZSByZXN1bHQgb2YgcGFyc2luZy4gVGhlIGVsZW1lbnQgbnVt YmVyIG9mIHRoaXMgYXJyYXkgc2hvdWxkCisgKgkJYmUgcGxhdGZvcm1fdGltZXJfY291bnQodGhl IHRvdGFsIG51bWJlciBvZiBwbGF0Zm9ybSB0aW1lcnMpLgorICogQGNvdW50OglUaGUgcG9pbnRl ciBvZiBpbnQgdmFyaWF0ZSBmb3IgcmV0dXJuaW5nIHRoZSBudW1iZXIgb2YgR1QKKyAqCQlibG9j a3Mgd2UgaGF2ZSBwYXJzZWQuCisgKgorICogUmV0dXJuOiAwIGlmIHN1Y2Nlc3MsIC1FSU5WQUwv LUVOT0RFViBpZiBlcnJvci4KKyAqLworaW50IF9faW5pdCBhY3BpX2FyY2hfdGltZXJfbWVtX2lu aXQoc3RydWN0IGFyY2hfdGltZXJfbWVtICpkYXRhLAorCQkJCSAgICBpbnQgKnRpbWVyX2NvdW50 KQoreworCWludCByZXQ7CisJdm9pZCAqcGxhdGZvcm1fdGltZXI7CisKKwkqdGltZXJfY291bnQg PSAwOworCWZvcl9lYWNoX3BsYXRmb3JtX3RpbWVyKHBsYXRmb3JtX3RpbWVyKSB7CisJCWlmIChp c190aW1lcl9ibG9jayhwbGF0Zm9ybV90aW1lcikpIHsKKwkJCXJldCA9IGd0ZHRfcGFyc2VfdGlt ZXJfYmxvY2socGxhdGZvcm1fdGltZXIsIGRhdGEpOworCQkJaWYgKHJldCkKKwkJCQlyZXR1cm4g cmV0OworCQkJZGF0YSsrOworCQkJKCp0aW1lcl9jb3VudCkrKzsKKwkJfQorCX0KKworCWlmICgq dGltZXJfY291bnQpCisJCXByX2luZm8oImZvdW5kICVkIG1lbW9yeS1tYXBwZWQgdGltZXIgYmxv Y2socykuXG4iLAorCQkJKnRpbWVyX2NvdW50KTsKKworCXJldHVybiAwOworfQpkaWZmIC0tZ2l0 IGEvaW5jbHVkZS9saW51eC9hY3BpLmggYi9pbmNsdWRlL2xpbnV4L2FjcGkuaAppbmRleCBkMGIy NzFlLi41MWU4NWI5IDEwMDY0NAotLS0gYS9pbmNsdWRlL2xpbnV4L2FjcGkuaAorKysgYi9pbmNs dWRlL2xpbnV4L2FjcGkuaApAQCAtNjAxLDYgKzYwMSw3IEBAIGludCBhY3BpX3JlY29uZmlnX25v dGlmaWVyX3VucmVnaXN0ZXIoc3RydWN0IG5vdGlmaWVyX2Jsb2NrICpuYik7CiBpbnQgYWNwaV9n dGR0X2luaXQoc3RydWN0IGFjcGlfdGFibGVfaGVhZGVyICp0YWJsZSwgaW50ICpwbGF0Zm9ybV90 aW1lcl9jb3VudCk7CiBpbnQgYWNwaV9ndGR0X21hcF9wcGkoaW50IHR5cGUpOwogYm9vbCBhY3Bp X2d0ZHRfYzNzdG9wKGludCB0eXBlKTsKK2ludCBhY3BpX2FyY2hfdGltZXJfbWVtX2luaXQoc3Ry dWN0IGFyY2hfdGltZXJfbWVtICpkYXRhLCBpbnQgKnRpbWVyX2NvdW50KTsKICNlbmRpZgogCiAj ZWxzZQkvKiAhQ09ORklHX0FDUEkgKi8KLS0gCjIuOS4zCgoKX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX18KbGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QK bGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRl YWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5lbAo= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753565AbdARNhK (ORCPT ); Wed, 18 Jan 2017 08:37:10 -0500 Received: from mx1.redhat.com ([209.132.183.28]:60198 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753018AbdARNhA (ORCPT ); Wed, 18 Jan 2017 08:37:00 -0500 From: fu.wei@linaro.org To: rjw@rjwysocki.net, lenb@kernel.org, daniel.lezcano@linaro.org, tglx@linutronix.de, marc.zyngier@arm.com, mark.rutland@arm.com, lorenzo.pieralisi@arm.com, sudeep.holla@arm.com, hanjun.guo@linaro.org Cc: linux-arm-kernel@lists.infradead.org, linaro-acpi@lists.linaro.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, rruigrok@codeaurora.org, harba@codeaurora.org, cov@codeaurora.org, timur@codeaurora.org, graeme.gregory@linaro.org, al.stone@linaro.org, jcm@redhat.com, wei@redhat.com, arnd@arndb.de, catalin.marinas@arm.com, will.deacon@arm.com, Suravee.Suthikulpanit@amd.com, leo.duran@amd.com, wim@iguana.be, linux@roeck-us.net, linux-watchdog@vger.kernel.org, tn@semihalf.com, christoffer.dall@linaro.org, julien.grall@arm.com, Fu Wei Subject: [PATCH v20 15/17] acpi/arm64: Add memory-mapped timer support in GTDT driver Date: Wed, 18 Jan 2017 21:25:39 +0800 Message-Id: <20170118132541.8989-16-fu.wei@linaro.org> In-Reply-To: <20170118132541.8989-1-fu.wei@linaro.org> References: <20170118132541.8989-1-fu.wei@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 18 Jan 2017 13:28:49 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Fu Wei On platforms booting with ACPI, architected memory-mapped timers' configuration data is provided by firmware through the ACPI GTDT static table. The clocksource architected timer kernel driver requires a firmware interface to collect timer configuration and configure its driver. this infrastructure is present for device tree systems, but it is missing on systems booting with ACPI. Implement the kernel infrastructure required to parse the static ACPI GTDT table so that the architected timer clocksource driver can make use of it on systems booting with ACPI, therefore enabling the corresponding timers configuration. Signed-off-by: Fu Wei Signed-off-by: Hanjun Guo --- drivers/acpi/arm64/gtdt.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 1 + 2 files changed, 125 insertions(+) diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c index d93a790..91ea6cb 100644 --- a/drivers/acpi/arm64/gtdt.c +++ b/drivers/acpi/arm64/gtdt.c @@ -37,6 +37,28 @@ struct acpi_gtdt_descriptor { static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata; +static inline void *next_platform_timer(void *platform_timer) +{ + struct acpi_gtdt_header *gh = platform_timer; + + platform_timer += gh->length; + if (platform_timer < acpi_gtdt_desc.gtdt_end) + return platform_timer; + + return NULL; +} + +#define for_each_platform_timer(_g) \ + for (_g = acpi_gtdt_desc.platform_timer; _g; \ + _g = next_platform_timer(_g)) + +static inline bool is_timer_block(void *platform_timer) +{ + struct acpi_gtdt_header *gh = platform_timer; + + return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK; +} + static int __init map_gt_gsi(u32 interrupt, u32 flags) { int trigger, polarity; @@ -155,3 +177,105 @@ int __init acpi_gtdt_init(struct acpi_table_header *table, return ret; } + +static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block, + struct arch_timer_mem *data) +{ + int i; + struct acpi_gtdt_timer_entry *frame; + + if (!block->timer_count) { + pr_err(FW_BUG "GT block present, but frame count is zero."); + return -ENODEV; + } + + if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) { + pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 8\n", + block->timer_count); + return -EINVAL; + } + + data->cntctlbase = (phys_addr_t)block->block_address; + /* + * According to "Table * CNTCTLBase memory map" of + * for ARMv8, + * The size of the CNTCTLBase frame is 4KB(Offset 0x000 – 0xFFC). + */ + data->size = SZ_4K; + data->num_frames = block->timer_count; + + frame = (void *)block + block->timer_offset; + if (frame + block->timer_count != (void *)block + block->header.length) + return -EINVAL; + + /* + * Get the GT timer Frame data for every GT Block Timer + */ + for (i = 0; i < block->timer_count; i++, frame++) { + if (!frame->base_address || !frame->timer_interrupt) + return -EINVAL; + + data->frame[i].phys_irq = map_gt_gsi(frame->timer_interrupt, + frame->timer_flags); + if (data->frame[i].phys_irq <= 0) { + pr_warn("failed to map physical timer irq in frame %d.\n", + i); + return -EINVAL; + } + + data->frame[i].virt_irq = + map_gt_gsi(frame->virtual_timer_interrupt, + frame->virtual_timer_flags); + if (data->frame[i].virt_irq <= 0) { + pr_warn("failed to map virtual timer irq in frame %d.\n", + i); + acpi_unregister_gsi(frame->timer_interrupt); + return -EINVAL; + } + + data->frame[i].frame_nr = frame->frame_number; + data->frame[i].cntbase = frame->base_address; + /* + * According to "Table * CNTBaseN memory map" of + * for ARMv8, + * The size of the CNTBaseN frame is 4KB(Offset 0x000 – 0xFFC). + */ + data->frame[i].size = SZ_4K; + } + + return 0; +} + +/** + * acpi_arch_timer_mem_init() - Get the info of all GT blocks in GTDT table. + * @data: the pointer to the array of struct arch_timer_mem for returning + * the result of parsing. The element number of this array should + * be platform_timer_count(the total number of platform timers). + * @count: The pointer of int variate for returning the number of GT + * blocks we have parsed. + * + * Return: 0 if success, -EINVAL/-ENODEV if error. + */ +int __init acpi_arch_timer_mem_init(struct arch_timer_mem *data, + int *timer_count) +{ + int ret; + void *platform_timer; + + *timer_count = 0; + for_each_platform_timer(platform_timer) { + if (is_timer_block(platform_timer)) { + ret = gtdt_parse_timer_block(platform_timer, data); + if (ret) + return ret; + data++; + (*timer_count)++; + } + } + + if (*timer_count) + pr_info("found %d memory-mapped timer block(s).\n", + *timer_count); + + return 0; +} diff --git a/include/linux/acpi.h b/include/linux/acpi.h index d0b271e..51e85b9 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -601,6 +601,7 @@ int acpi_reconfig_notifier_unregister(struct notifier_block *nb); int acpi_gtdt_init(struct acpi_table_header *table, int *platform_timer_count); int acpi_gtdt_map_ppi(int type); bool acpi_gtdt_c3stop(int type); +int acpi_arch_timer_mem_init(struct arch_timer_mem *data, int *timer_count); #endif #else /* !CONFIG_ACPI */ -- 2.9.3 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mx1.redhat.com ([209.132.183.28]:60198 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753018AbdARNhA (ORCPT ); Wed, 18 Jan 2017 08:37:00 -0500 From: fu.wei@linaro.org To: rjw@rjwysocki.net, lenb@kernel.org, daniel.lezcano@linaro.org, tglx@linutronix.de, marc.zyngier@arm.com, mark.rutland@arm.com, lorenzo.pieralisi@arm.com, sudeep.holla@arm.com, hanjun.guo@linaro.org Cc: linux-arm-kernel@lists.infradead.org, linaro-acpi@lists.linaro.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, rruigrok@codeaurora.org, harba@codeaurora.org, cov@codeaurora.org, timur@codeaurora.org, graeme.gregory@linaro.org, al.stone@linaro.org, jcm@redhat.com, wei@redhat.com, arnd@arndb.de, catalin.marinas@arm.com, will.deacon@arm.com, Suravee.Suthikulpanit@amd.com, leo.duran@amd.com, wim@iguana.be, linux@roeck-us.net, linux-watchdog@vger.kernel.org, tn@semihalf.com, christoffer.dall@linaro.org, julien.grall@arm.com, Fu Wei Subject: [PATCH v20 15/17] acpi/arm64: Add memory-mapped timer support in GTDT driver Date: Wed, 18 Jan 2017 21:25:39 +0800 Message-Id: <20170118132541.8989-16-fu.wei@linaro.org> In-Reply-To: <20170118132541.8989-1-fu.wei@linaro.org> References: <20170118132541.8989-1-fu.wei@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-watchdog-owner@vger.kernel.org List-Id: linux-watchdog@vger.kernel.org Content-Transfer-Encoding: quoted-printable From: Fu Wei On platforms booting with ACPI, architected memory-mapped timers' configuration data is provided by firmware through the ACPI GTDT static table. The clocksource architected timer kernel driver requires a firmware interface to collect timer configuration and configure its driver. this infrastructure is present for device tree systems, but it is missing on systems booting with ACPI. Implement the kernel infrastructure required to parse the static ACPI GTDT table so that the architected timer clocksource driver can make use of it on systems booting with ACPI, therefore enabling the corresponding timers configuration. Signed-off-by: Fu Wei Signed-off-by: Hanjun Guo --- drivers/acpi/arm64/gtdt.c | 124 ++++++++++++++++++++++++++++++++++++++++= ++++++ include/linux/acpi.h | 1 + 2 files changed, 125 insertions(+) diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c index d93a790..91ea6cb 100644 --- a/drivers/acpi/arm64/gtdt.c +++ b/drivers/acpi/arm64/gtdt.c @@ -37,6 +37,28 @@ struct acpi_gtdt_descriptor { =20 static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata; =20 +static inline void *next_platform_timer(void *platform_timer) +{ + struct acpi_gtdt_header *gh =3D platform_timer; + + platform_timer +=3D gh->length; + if (platform_timer < acpi_gtdt_desc.gtdt_end) + return platform_timer; + + return NULL; +} + +#define for_each_platform_timer(_g) \ + for (_g =3D acpi_gtdt_desc.platform_timer; _g; \ + _g =3D next_platform_timer(_g)) + +static inline bool is_timer_block(void *platform_timer) +{ + struct acpi_gtdt_header *gh =3D platform_timer; + + return gh->type =3D=3D ACPI_GTDT_TYPE_TIMER_BLOCK; +} + static int __init map_gt_gsi(u32 interrupt, u32 flags) { int trigger, polarity; @@ -155,3 +177,105 @@ int __init acpi_gtdt_init(struct acpi_table_header = *table, =20 return ret; } + +static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *b= lock, + struct arch_timer_mem *data) +{ + int i; + struct acpi_gtdt_timer_entry *frame; + + if (!block->timer_count) { + pr_err(FW_BUG "GT block present, but frame count is zero."); + return -ENODEV; + } + + if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) { + pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 8\n", + block->timer_count); + return -EINVAL; + } + + data->cntctlbase =3D (phys_addr_t)block->block_address; + /* + * According to "Table * CNTCTLBase memory map" of + * for ARMv8, + * The size of the CNTCTLBase frame is 4KB(Offset 0x000 =E2=80=93 0xFFC= ). + */ + data->size =3D SZ_4K; + data->num_frames =3D block->timer_count; + + frame =3D (void *)block + block->timer_offset; + if (frame + block->timer_count !=3D (void *)block + block->header.lengt= h) + return -EINVAL; + + /* + * Get the GT timer Frame data for every GT Block Timer + */ + for (i =3D 0; i < block->timer_count; i++, frame++) { + if (!frame->base_address || !frame->timer_interrupt) + return -EINVAL; + + data->frame[i].phys_irq =3D map_gt_gsi(frame->timer_interrupt, + frame->timer_flags); + if (data->frame[i].phys_irq <=3D 0) { + pr_warn("failed to map physical timer irq in frame %d.\n", + i); + return -EINVAL; + } + + data->frame[i].virt_irq =3D + map_gt_gsi(frame->virtual_timer_interrupt, + frame->virtual_timer_flags); + if (data->frame[i].virt_irq <=3D 0) { + pr_warn("failed to map virtual timer irq in frame %d.\n", + i); + acpi_unregister_gsi(frame->timer_interrupt); + return -EINVAL; + } + + data->frame[i].frame_nr =3D frame->frame_number; + data->frame[i].cntbase =3D frame->base_address; + /* + * According to "Table * CNTBaseN memory map" of + * for ARMv8, + * The size of the CNTBaseN frame is 4KB(Offset 0x000 =E2=80=93 0xFFC)= . + */ + data->frame[i].size =3D SZ_4K; + } + + return 0; +} + +/** + * acpi_arch_timer_mem_init() - Get the info of all GT blocks in GTDT ta= ble. + * @data: the pointer to the array of struct arch_timer_mem for returnin= g + * the result of parsing. The element number of this array should + * be platform_timer_count(the total number of platform timers). + * @count: The pointer of int variate for returning the number of GT + * blocks we have parsed. + * + * Return: 0 if success, -EINVAL/-ENODEV if error. + */ +int __init acpi_arch_timer_mem_init(struct arch_timer_mem *data, + int *timer_count) +{ + int ret; + void *platform_timer; + + *timer_count =3D 0; + for_each_platform_timer(platform_timer) { + if (is_timer_block(platform_timer)) { + ret =3D gtdt_parse_timer_block(platform_timer, data); + if (ret) + return ret; + data++; + (*timer_count)++; + } + } + + if (*timer_count) + pr_info("found %d memory-mapped timer block(s).\n", + *timer_count); + + return 0; +} diff --git a/include/linux/acpi.h b/include/linux/acpi.h index d0b271e..51e85b9 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -601,6 +601,7 @@ int acpi_reconfig_notifier_unregister(struct notifier= _block *nb); int acpi_gtdt_init(struct acpi_table_header *table, int *platform_timer_= count); int acpi_gtdt_map_ppi(int type); bool acpi_gtdt_c3stop(int type); +int acpi_arch_timer_mem_init(struct arch_timer_mem *data, int *timer_cou= nt); #endif =20 #else /* !CONFIG_ACPI */ --=20 2.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-watchdog"= in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html From mboxrd@z Thu Jan 1 00:00:00 1970 From: fu.wei@linaro.org (fu.wei at linaro.org) Date: Wed, 18 Jan 2017 21:25:39 +0800 Subject: [PATCH v20 15/17] acpi/arm64: Add memory-mapped timer support in GTDT driver In-Reply-To: <20170118132541.8989-1-fu.wei@linaro.org> References: <20170118132541.8989-1-fu.wei@linaro.org> Message-ID: <20170118132541.8989-16-fu.wei@linaro.org> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org From: Fu Wei On platforms booting with ACPI, architected memory-mapped timers' configuration data is provided by firmware through the ACPI GTDT static table. The clocksource architected timer kernel driver requires a firmware interface to collect timer configuration and configure its driver. this infrastructure is present for device tree systems, but it is missing on systems booting with ACPI. Implement the kernel infrastructure required to parse the static ACPI GTDT table so that the architected timer clocksource driver can make use of it on systems booting with ACPI, therefore enabling the corresponding timers configuration. Signed-off-by: Fu Wei Signed-off-by: Hanjun Guo --- drivers/acpi/arm64/gtdt.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 1 + 2 files changed, 125 insertions(+) diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c index d93a790..91ea6cb 100644 --- a/drivers/acpi/arm64/gtdt.c +++ b/drivers/acpi/arm64/gtdt.c @@ -37,6 +37,28 @@ struct acpi_gtdt_descriptor { static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata; +static inline void *next_platform_timer(void *platform_timer) +{ + struct acpi_gtdt_header *gh = platform_timer; + + platform_timer += gh->length; + if (platform_timer < acpi_gtdt_desc.gtdt_end) + return platform_timer; + + return NULL; +} + +#define for_each_platform_timer(_g) \ + for (_g = acpi_gtdt_desc.platform_timer; _g; \ + _g = next_platform_timer(_g)) + +static inline bool is_timer_block(void *platform_timer) +{ + struct acpi_gtdt_header *gh = platform_timer; + + return gh->type == ACPI_GTDT_TYPE_TIMER_BLOCK; +} + static int __init map_gt_gsi(u32 interrupt, u32 flags) { int trigger, polarity; @@ -155,3 +177,105 @@ int __init acpi_gtdt_init(struct acpi_table_header *table, return ret; } + +static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block, + struct arch_timer_mem *data) +{ + int i; + struct acpi_gtdt_timer_entry *frame; + + if (!block->timer_count) { + pr_err(FW_BUG "GT block present, but frame count is zero."); + return -ENODEV; + } + + if (block->timer_count > ARCH_TIMER_MEM_MAX_FRAMES) { + pr_err(FW_BUG "GT block lists %d frames, ACPI spec only allows 8\n", + block->timer_count); + return -EINVAL; + } + + data->cntctlbase = (phys_addr_t)block->block_address; + /* + * According to "Table * CNTCTLBase memory map" of + * for ARMv8, + * The size of the CNTCTLBase frame is 4KB(Offset 0x000 ? 0xFFC). + */ + data->size = SZ_4K; + data->num_frames = block->timer_count; + + frame = (void *)block + block->timer_offset; + if (frame + block->timer_count != (void *)block + block->header.length) + return -EINVAL; + + /* + * Get the GT timer Frame data for every GT Block Timer + */ + for (i = 0; i < block->timer_count; i++, frame++) { + if (!frame->base_address || !frame->timer_interrupt) + return -EINVAL; + + data->frame[i].phys_irq = map_gt_gsi(frame->timer_interrupt, + frame->timer_flags); + if (data->frame[i].phys_irq <= 0) { + pr_warn("failed to map physical timer irq in frame %d.\n", + i); + return -EINVAL; + } + + data->frame[i].virt_irq = + map_gt_gsi(frame->virtual_timer_interrupt, + frame->virtual_timer_flags); + if (data->frame[i].virt_irq <= 0) { + pr_warn("failed to map virtual timer irq in frame %d.\n", + i); + acpi_unregister_gsi(frame->timer_interrupt); + return -EINVAL; + } + + data->frame[i].frame_nr = frame->frame_number; + data->frame[i].cntbase = frame->base_address; + /* + * According to "Table * CNTBaseN memory map" of + * for ARMv8, + * The size of the CNTBaseN frame is 4KB(Offset 0x000 ? 0xFFC). + */ + data->frame[i].size = SZ_4K; + } + + return 0; +} + +/** + * acpi_arch_timer_mem_init() - Get the info of all GT blocks in GTDT table. + * @data: the pointer to the array of struct arch_timer_mem for returning + * the result of parsing. The element number of this array should + * be platform_timer_count(the total number of platform timers). + * @count: The pointer of int variate for returning the number of GT + * blocks we have parsed. + * + * Return: 0 if success, -EINVAL/-ENODEV if error. + */ +int __init acpi_arch_timer_mem_init(struct arch_timer_mem *data, + int *timer_count) +{ + int ret; + void *platform_timer; + + *timer_count = 0; + for_each_platform_timer(platform_timer) { + if (is_timer_block(platform_timer)) { + ret = gtdt_parse_timer_block(platform_timer, data); + if (ret) + return ret; + data++; + (*timer_count)++; + } + } + + if (*timer_count) + pr_info("found %d memory-mapped timer block(s).\n", + *timer_count); + + return 0; +} diff --git a/include/linux/acpi.h b/include/linux/acpi.h index d0b271e..51e85b9 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -601,6 +601,7 @@ int acpi_reconfig_notifier_unregister(struct notifier_block *nb); int acpi_gtdt_init(struct acpi_table_header *table, int *platform_timer_count); int acpi_gtdt_map_ppi(int type); bool acpi_gtdt_c3stop(int type); +int acpi_arch_timer_mem_init(struct arch_timer_mem *data, int *timer_count); #endif #else /* !CONFIG_ACPI */ -- 2.9.3