From patchwork Tue Sep 25 11:22:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandipan Patra X-Patchwork-Id: 974358 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-tegra-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=nvidia.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=nvidia.com header.i=@nvidia.com header.b="ADB7d7qj"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42KJb65XNFz9s3C for ; Tue, 25 Sep 2018 21:22:58 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727570AbeIYRaB (ORCPT ); Tue, 25 Sep 2018 13:30:01 -0400 Received: from hqemgate14.nvidia.com ([216.228.121.143]:13626 "EHLO hqemgate14.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728421AbeIYRaB (ORCPT ); Tue, 25 Sep 2018 13:30:01 -0400 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqemgate14.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Tue, 25 Sep 2018 04:22:57 -0700 Received: from HQMAIL104.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Tue, 25 Sep 2018 04:22:55 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Tue, 25 Sep 2018 04:22:55 -0700 Received: from HQMAIL105.nvidia.com (172.20.187.12) by HQMAIL104.nvidia.com (172.18.146.11) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Tue, 25 Sep 2018 11:22:54 +0000 Received: from hqnvemgw01.nvidia.com (172.20.150.20) by HQMAIL105.nvidia.com (172.20.187.12) with Microsoft SMTP Server (TLS) id 15.0.1395.4 via Frontend Transport; Tue, 25 Sep 2018 11:22:54 +0000 Received: from sandipan-pc.nvidia.com (Not Verified[10.24.42.159]) by hqnvemgw01.nvidia.com with Trustwave SEG (v7, 5, 8, 10121) id ; Tue, 25 Sep 2018 04:22:54 -0700 From: Sandipan Patra To: , , CC: , Sandipan Patra Subject: [PATCH] soc/tegra: pmc: Add sysfs entry to get reset info Date: Tue, 25 Sep 2018 16:52:46 +0530 Message-ID: <1537874566-12064-1-git-send-email-spatra@nvidia.com> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1537874577; bh=Y6SjrMNnVPW0iDi6qitg7Kgg8cwoln4xL387Gs4kqTs=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: MIME-Version:Content-Type; b=ADB7d7qj+zGOXlOrXQ1AS80dN4b5a4JDcRb7MQFT/t8Na9BI2C+NQU31VU3dpmfpU Bx9iDptO2njHnptesGIxZM6ShwtsGNepTGWiNDQkJGhBUUHAYp35ZFXJVloZdpacJC 2mleEQnHB/tYzhJmd47P4hS0qXUGrdzm9U0KMA9kmULQcY+F4G+uYiXWw1xdgRpPYV elvahp/Lygi+FdgboxroVwH1wXCVpLnGdjrfb+IqyMRdqBTRFyu7//QaPJOPv/95DO /eeyJ+lD6fI5DxZD5jT/3xLaZlj3Fz+xnNrJi117PuFlbGgovff+h0A2hxc7rGimL7 5OpgntIm9ALNg== Sender: linux-tegra-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-tegra@vger.kernel.org 1. Implementation of: tegra_pmc_get_system_reset_reason and tegra_pmc_get_system_reset_level These APIs provide information about tegra reset reason and level respectively. 2. sysfs entries: /sys/devices/platform/
.pmc/tegra_reset_reason and /sys/devices/platform/
.pmc/tegra_reset_level are implemented in readonly mode to fetch tegra reset reason and tegra reset level information. Signed-off-by: Sandipan Patra --- drivers/soc/tegra/pmc.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index ab719fa..ac74fee 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -2,6 +2,7 @@ * drivers/soc/tegra/pmc.c * * Copyright (c) 2010 Google, Inc + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. * * Author: * Colin Cross @@ -92,7 +93,8 @@ #define PMC_SENSOR_CTRL_SCRATCH_WRITE BIT(2) #define PMC_SENSOR_CTRL_ENABLE_RST BIT(1) -#define PMC_RST_STATUS 0x1b4 +#define PMC_RST_STATUS_T30 0x1b4 +#define PMC_RST_STATUS_T186 0x70 #define PMC_RST_STATUS_POR 0 #define PMC_RST_STATUS_WATCHDOG 1 #define PMC_RST_STATUS_SENSOR 2 @@ -125,6 +127,13 @@ #define GPU_RG_CNTRL 0x2d4 +#define PMC_RST_LEVEL_SHIFT_T186 0x0 +#define PMC_RST_LEVEL_MASK_T186 0x3 +#define PMC_RST_SOURCE_MASK_T186 0x3C +#define PMC_RST_SOURCE_SHIFT_T186 0x2 +#define PMC_RST_LEVEL_MASK_T30 0x7 + + /* Tegra186 and later */ #define WAKE_AOWAKE_CTRL 0x4f4 #define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0) @@ -153,6 +162,12 @@ struct tegra_pmc_regs { unsigned int dpd2_status; }; +enum tegra_pmc_reset_status_type { + PMC_RESET_STATUS_TYPE_NONE, + PMC_RESET_STATUS_TYPE_T30, + PMC_RESET_STATUS_TYPE_T186 +}; + struct tegra_pmc_soc { unsigned int num_powergates; const char *const *powergates; @@ -163,6 +178,7 @@ struct tegra_pmc_soc { bool has_gpu_clamps; bool needs_mbist_war; bool has_impl_33v_pwr; + enum tegra_pmc_reset_status_type pmc_reset_status; const struct tegra_io_pad_soc *io_pads; unsigned int num_io_pads; @@ -662,6 +678,71 @@ int tegra_pmc_cpu_remove_clamping(unsigned int cpuid) } #endif /* CONFIG_SMP */ +/** + * tegra_pmc_get_system_reset_reason() - last reset reason status + */ +static char *tegra_pmc_get_system_reset_reason(void) +{ + u32 val, rst_src; + + if (pmc->soc->pmc_reset_status == PMC_RESET_STATUS_TYPE_T30) { + val = tegra_pmc_readl(PMC_RST_STATUS_T30); + rst_src = val & PMC_RST_LEVEL_MASK_T30; + switch (rst_src) { + case 0: return "TEGRA_POWER_ON_RESET"; + case 1: return "TEGRA_WATCHDOG"; + case 2: return "TEGRA_SENSOR"; + case 3: return "TEGRA_SOFTWARE_RESET"; + case 4: return "TEGRA_LP0"; + case 5: return "TEGRA_AOTAG"; + default: return "TEGRA_RESET_REASON_UNSPECIFIED"; + } + } else if (pmc->soc->pmc_reset_status == PMC_RESET_STATUS_TYPE_T186) { + val = tegra_pmc_readl(PMC_RST_STATUS_T186); + rst_src = (val & PMC_RST_SOURCE_MASK_T186) >> + PMC_RST_SOURCE_SHIFT_T186; + switch (rst_src) { + case 0: return "TEGRA_POWER_ON_RESET"; + case 1: return "TEGRA_AO_WATCHDOG"; + case 2: return "TEGRA_DENVER_WATCHDOG"; + case 3: return "TEGRA_BPMP_WATCHDOG"; + case 4: return "TEGRA_SCE_WATCHDOG"; + case 5: return "TEGRA_SPE_WATCHDOG"; + case 6: return "TEGRA_APE_WATCHDOG"; + case 7: return "TEGRA_A57_WATCHDOG"; + case 8: return "TEGRA_SENSOR"; + case 9: return "TEGRA_AOTAG"; + case 10: return "TEGRA_VFSENSOR"; + case 11: return "TEGRA_SOFTWARE_RESET"; + case 12: return "TEGRA_SC7"; + case 13: return "TEGRA_HSM"; + case 14: return "TEGRA_CSITE"; + default: return "TEGRA_RESET_REASON_UNSPECIFIED"; + } + } else { + return "TEGRA_RESET_REASON_NOT_SUPPORTED"; + } +} + +static char *tegra_pmc_get_system_reset_level(void) +{ + u32 val, rst_lvl; + + if (pmc->soc->pmc_reset_status == PMC_RESET_STATUS_TYPE_T186) { + val = tegra_pmc_readl(PMC_RST_STATUS_T186); + rst_lvl = (val & PMC_RST_LEVEL_MASK_T186) >> + PMC_RST_LEVEL_SHIFT_T186; + switch (rst_lvl) { + case 0: return "TEGRA_RESET_LEVEL_L0"; + case 1: return "TEGRA_RESET_LEVEL_L1"; + case 2: return "TEGRA_RESET_LEVEL_L2"; + default: return "TEGRA_RESET_LEVEL_UNSPECIFIED"; + } + } else { + return "TEGRA_RESET_LEVEL_NOT_SUPPORTED"; + } +} + static int tegra_pmc_restart_notify(struct notifier_block *this, unsigned long action, void *data) { @@ -1543,6 +1624,46 @@ static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc) return err; } +static void tegra_pmc_show_reset_status(struct device *dev) +{ + dev_info(dev, "reset source: %s\n", + tegra_pmc_get_system_reset_reason()); + dev_info(dev, "reset level: %s\n", + tegra_pmc_get_system_reset_level()); +} + +static ssize_t tegra_reset_reason_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%s\n", tegra_pmc_get_system_reset_reason()); +} + +static DEVICE_ATTR_RO(tegra_reset_reason); + +static ssize_t tegra_reset_level_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%s\n", tegra_pmc_get_system_reset_level()); +} + +static DEVICE_ATTR_RO(tegra_reset_level); + +static void tegra_pmc_reset_sysfs_init(struct device *dev) +{ + int error; + + error = device_create_file(dev, &dev_attr_tegra_reset_reason); + if (error) { + dev_err(dev, + "Failed to create sysfs node - tegra_reset_reason\n"); + } + error = device_create_file(dev, &dev_attr_tegra_reset_level); + if (error) { + dev_err(dev, + "Failed to create sysfs node - tegra_reset_level\n"); + } +} + static int tegra_pmc_probe(struct platform_device *pdev) { void __iomem *base; @@ -1612,6 +1733,9 @@ static int tegra_pmc_probe(struct platform_device *pdev) tegra_pmc_init_tsense_reset(pmc); + tegra_pmc_show_reset_status(&pdev->dev); + tegra_pmc_reset_sysfs_init(&pdev->dev); + if (IS_ENABLED(CONFIG_DEBUG_FS)) { err = tegra_powergate_debugfs_init(); if (err < 0) @@ -1728,6 +1852,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = { .cpu_powergates = NULL, .has_tsense_reset = false, .has_gpu_clamps = false, + .pmc_reset_status = PMC_RESET_STATUS_TYPE_NONE, .num_io_pads = 0, .io_pads = NULL, .num_pin_descs = 0, @@ -1769,6 +1894,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = { .has_tsense_reset = true, .has_gpu_clamps = false, .has_impl_33v_pwr = false, + .pmc_reset_status = PMC_RESET_STATUS_TYPE_T30, .num_io_pads = 0, .io_pads = NULL, .num_pin_descs = 0, @@ -1814,6 +1940,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = { .has_tsense_reset = true, .has_gpu_clamps = false, .has_impl_33v_pwr = false, + .pmc_reset_status = PMC_RESET_STATUS_TYPE_T30, .num_io_pads = 0, .io_pads = NULL, .num_pin_descs = 0, @@ -1919,6 +2046,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = { .has_tsense_reset = true, .has_gpu_clamps = true, .has_impl_33v_pwr = false, + .pmc_reset_status = PMC_RESET_STATUS_TYPE_T30, .num_io_pads = ARRAY_SIZE(tegra124_io_pads), .io_pads = tegra124_io_pads, .num_pin_descs = ARRAY_SIZE(tegra124_pin_descs), @@ -2019,6 +2147,7 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = { .has_tsense_reset = true, .has_gpu_clamps = true, .has_impl_33v_pwr = false, + .pmc_reset_status = PMC_RESET_STATUS_TYPE_T30, .needs_mbist_war = true, .num_io_pads = ARRAY_SIZE(tegra210_io_pads), .io_pads = tegra210_io_pads, @@ -2129,6 +2258,7 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = { .has_tsense_reset = false, .has_gpu_clamps = false, .has_impl_33v_pwr = true, + .pmc_reset_status = PMC_RESET_STATUS_TYPE_T186, .num_io_pads = ARRAY_SIZE(tegra186_io_pads), .io_pads = tegra186_io_pads, .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs),