From c78cf9956f19a7db7199310802ec514266653931 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 17 Apr 2020 19:11:16 +0200 Subject: soc/tegra: pmc: Enable PMIC wake event on Tegra186 The PMIC wake event can be used to bring the system out of suspend based on certain events happening on the PMIC (such as an RTC alarm). Signed-off-by: Thierry Reding Acked-by: Jon Hunter Tested-by: Jon Hunter --- drivers/soc/tegra/pmc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 1c533a969f54..72cfda7305d5 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -3193,6 +3193,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc, } static const struct tegra_wake_event tegra186_wake_events[] = { + TEGRA_WAKE_IRQ("pmu", 24, 209), TEGRA_WAKE_GPIO("power", 29, 1, TEGRA186_AON_GPIO(FF, 0)), TEGRA_WAKE_IRQ("rtc", 73, 10), }; -- cgit v1.2.3 From 379ac9eb1fe94cc40173b83fda1ee8d611a756e9 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 17 Apr 2020 13:39:48 +0100 Subject: soc/tegra: fuse: Add custom SoC attributes Add a custom SoC attribute for Tegra to expose the HIDREV register fields to userspace via the sysfs. This register provides additional details about the type of device (eg, silicon, FPGA, etc) as well as revision. Exposing this information is useful for identifying the exact device revision and device type. For Tegra devices up until Tegra186, the majorrev and minorrev fields of the HIDREV register are used to determine the device revision and device type. For Tegra194, the majorrev and minorrev fields only determine the revision. Starting with Tegra194, there is an additional field, pre_si_platform (which occupies bits 20-23), that now determines device type. Therefore, for all Tegra devices, add a custom SoC attribute for the majorrev and minorrev fields and for Tegra194 add an additional attribute for the pre_si_platform field. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/fuse-tegra.c | 54 ++++++++++++++++++++++++++++++++++ drivers/soc/tegra/fuse/fuse-tegra20.c | 1 + drivers/soc/tegra/fuse/fuse-tegra30.c | 6 ++++ drivers/soc/tegra/fuse/fuse.h | 8 +++++ drivers/soc/tegra/fuse/tegra-apbmisc.c | 10 +++++++ 5 files changed, 79 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index 802717b9f6a3..db65ddb6a5d2 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -300,6 +300,59 @@ static void tegra_enable_fuse_clk(void __iomem *base) writel(reg, base + 0x14); } +static ssize_t major_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", tegra_get_major_rev()); +} + +static DEVICE_ATTR_RO(major); + +static ssize_t minor_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", tegra_get_minor_rev()); +} + +static DEVICE_ATTR_RO(minor); + +static struct attribute *tegra_soc_attr[] = { + &dev_attr_major.attr, + &dev_attr_minor.attr, + NULL, +}; + +const struct attribute_group tegra_soc_attr_group = { + .attrs = tegra_soc_attr, +}; + +#ifdef CONFIG_ARCH_TEGRA_194_SOC +static ssize_t platform_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + /* + * Displays the value in the 'pre_si_platform' field of the HIDREV + * register for Tegra194 devices. A value of 0 indicates that the + * platform type is silicon and all other non-zero values indicate + * the type of simulation platform is being used. + */ + return sprintf(buf, "%d\n", (tegra_read_chipid() >> 20) & 0xf); +} + +static DEVICE_ATTR_RO(platform); + +static struct attribute *tegra194_soc_attr[] = { + &dev_attr_major.attr, + &dev_attr_minor.attr, + &dev_attr_platform.attr, + NULL, +}; + +const struct attribute_group tegra194_soc_attr_group = { + .attrs = tegra194_soc_attr, +}; +#endif + struct device * __init tegra_soc_device_register(void) { struct soc_device_attribute *attr; @@ -312,6 +365,7 @@ struct device * __init tegra_soc_device_register(void) attr->family = kasprintf(GFP_KERNEL, "Tegra"); attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_sku_info.revision); attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id()); + attr->custom_attr_group = fuse->soc->soc_attr_group; dev = soc_device_register(attr); if (IS_ERR(dev)) { diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c b/drivers/soc/tegra/fuse/fuse-tegra20.c index d4aef9c4a94c..16aaa28573ac 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra20.c +++ b/drivers/soc/tegra/fuse/fuse-tegra20.c @@ -164,4 +164,5 @@ const struct tegra_fuse_soc tegra20_fuse_soc = { .speedo_init = tegra20_init_speedo_data, .probe = tegra20_fuse_probe, .info = &tegra20_fuse_info, + .soc_attr_group = &tegra_soc_attr_group, }; diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index e6037f900fb7..85accef41fa1 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -111,6 +111,7 @@ const struct tegra_fuse_soc tegra30_fuse_soc = { .init = tegra30_fuse_init, .speedo_init = tegra30_init_speedo_data, .info = &tegra30_fuse_info, + .soc_attr_group = &tegra_soc_attr_group, }; #endif @@ -125,6 +126,7 @@ const struct tegra_fuse_soc tegra114_fuse_soc = { .init = tegra30_fuse_init, .speedo_init = tegra114_init_speedo_data, .info = &tegra114_fuse_info, + .soc_attr_group = &tegra_soc_attr_group, }; #endif @@ -205,6 +207,7 @@ const struct tegra_fuse_soc tegra124_fuse_soc = { .info = &tegra124_fuse_info, .lookups = tegra124_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra124_fuse_lookups), + .soc_attr_group = &tegra_soc_attr_group, }; #endif @@ -290,6 +293,7 @@ const struct tegra_fuse_soc tegra210_fuse_soc = { .info = &tegra210_fuse_info, .lookups = tegra210_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra210_fuse_lookups), + .soc_attr_group = &tegra_soc_attr_group, }; #endif @@ -319,6 +323,7 @@ const struct tegra_fuse_soc tegra186_fuse_soc = { .info = &tegra186_fuse_info, .lookups = tegra186_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra186_fuse_lookups), + .soc_attr_group = &tegra_soc_attr_group, }; #endif @@ -348,5 +353,6 @@ const struct tegra_fuse_soc tegra194_fuse_soc = { .info = &tegra194_fuse_info, .lookups = tegra194_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra194_fuse_lookups), + .soc_attr_group = &tegra194_soc_attr_group, }; #endif diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h index 94a059e577a1..9d4fc315a007 100644 --- a/drivers/soc/tegra/fuse/fuse.h +++ b/drivers/soc/tegra/fuse/fuse.h @@ -32,6 +32,8 @@ struct tegra_fuse_soc { const struct nvmem_cell_lookup *lookups; unsigned int num_lookups; + + const struct attribute_group *soc_attr_group; }; struct tegra_fuse { @@ -64,6 +66,11 @@ void tegra_init_apbmisc(void); bool __init tegra_fuse_read_spare(unsigned int spare); u32 __init tegra_fuse_read_early(unsigned int offset); +u8 tegra_get_major_rev(void); +u8 tegra_get_minor_rev(void); + +extern const struct attribute_group tegra_soc_attr_group; + #ifdef CONFIG_ARCH_TEGRA_2x_SOC void tegra20_init_speedo_data(struct tegra_sku_info *sku_info); #endif @@ -110,6 +117,7 @@ extern const struct tegra_fuse_soc tegra186_fuse_soc; #ifdef CONFIG_ARCH_TEGRA_194_SOC extern const struct tegra_fuse_soc tegra194_fuse_soc; +extern const struct attribute_group tegra194_soc_attr_group; #endif #endif diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 089d9340564b..44a154ca16b5 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -37,6 +37,16 @@ u8 tegra_get_chip_id(void) return (tegra_read_chipid() >> 8) & 0xff; } +u8 tegra_get_major_rev(void) +{ + return (tegra_read_chipid() >> 4) & 0xf; +} + +u8 tegra_get_minor_rev(void) +{ + return (tegra_read_chipid() >> 16) & 0xf; +} + u32 tegra_read_straps(void) { WARN(!chipid, "Tegra ABP MISC not yet available\n"); -- cgit v1.2.3 From d08a4095abd8174e13c23c733584da9d0de556e7 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 17 Apr 2020 13:39:49 +0100 Subject: soc/tegra: fuse: Trivial clean-up of tegra_init_revision() Clean-up the tegra_init_revision() function by removing the 'rev' variable which is not needed and use the newly added helper function tegra_get_minor_rev() to get the minor revision. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/tegra-apbmisc.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 44a154ca16b5..3cdd69d1bd4d 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -75,36 +75,32 @@ static const struct of_device_id apbmisc_match[] __initconst = { void __init tegra_init_revision(void) { - u32 id, chip_id, minor_rev; - int rev; + u8 chip_id, minor_rev; - id = tegra_read_chipid(); - chip_id = (id >> 8) & 0xff; - minor_rev = (id >> 16) & 0xf; + chip_id = tegra_get_chip_id(); + minor_rev = tegra_get_minor_rev(); switch (minor_rev) { case 1: - rev = TEGRA_REVISION_A01; + tegra_sku_info.revision = TEGRA_REVISION_A01; break; case 2: - rev = TEGRA_REVISION_A02; + tegra_sku_info.revision = TEGRA_REVISION_A02; break; case 3: if (chip_id == TEGRA20 && (tegra_fuse_read_spare(18) || tegra_fuse_read_spare(19))) - rev = TEGRA_REVISION_A03p; + tegra_sku_info.revision = TEGRA_REVISION_A03p; else - rev = TEGRA_REVISION_A03; + tegra_sku_info.revision = TEGRA_REVISION_A03; break; case 4: - rev = TEGRA_REVISION_A04; + tegra_sku_info.revision = TEGRA_REVISION_A04; break; default: - rev = TEGRA_REVISION_UNKNOWN; + tegra_sku_info.revision = TEGRA_REVISION_UNKNOWN; } - tegra_sku_info.revision = rev; - tegra_sku_info.sku_id = tegra_fuse_read_early(FUSE_SKU_INFO); } -- cgit v1.2.3 From 37558ac85c197a5ff776b7b2f53046877f2bd4ee Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Fri, 17 Apr 2020 13:40:46 +0100 Subject: soc/tegra: fuse: Update the SoC revision attribute to display a name Currently the SoC revision attribute for Tegra devices displays the value of the enum associated with a particular revision. This is not very useful because to obtain the actual revision you need to use the tegra_revision enumeration to translate the value. It is more meaningful to display a name for the revision, such as 'A01', than the enumarated value and therefore, update the revision attribute to display a name. This change does alter the ABI, which is unfortunate, but this is more meaningful and maintable. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/fuse/fuse-tegra.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index db65ddb6a5d2..d1f8dd0289e6 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -363,7 +363,8 @@ struct device * __init tegra_soc_device_register(void) return NULL; attr->family = kasprintf(GFP_KERNEL, "Tegra"); - attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_sku_info.revision); + attr->revision = kasprintf(GFP_KERNEL, "%s", + tegra_revision_name[tegra_sku_info.revision]); attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id()); attr->custom_attr_group = fuse->soc->soc_attr_group; -- cgit v1.2.3 From 5098e2b95e8e6f56266c2d5c180c75917090082a Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Wed, 18 Mar 2020 15:25:08 +0000 Subject: soc/tegra: pmc: Select GENERIC_PINCONF I have hit the following build error: armv7a-hardfloat-linux-gnueabi-ld: drivers/soc/tegra/pmc.o: in function `pinconf_generic_dt_node_to_map_pin': pmc.c:(.text+0x500): undefined reference to `pinconf_generic_dt_node_to_map' armv7a-hardfloat-linux-gnueabi-ld: drivers/soc/tegra/pmc.o:(.rodata+0x1f88): undefined reference to `pinconf_generic_dt_free_map' So SOC_TEGRA_PMC should select GENERIC_PINCONF. Fixes: 4a37f11c8f57 ("soc/tegra: pmc: Implement pad configuration via pinctrl") Cc: stable Signed-off-by: Corentin Labbe Signed-off-by: Thierry Reding --- drivers/soc/tegra/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index 3693532949b8..6bc603d0b9d9 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -133,6 +133,7 @@ config SOC_TEGRA_FLOWCTRL config SOC_TEGRA_PMC bool + select GENERIC_PINCONF config SOC_TEGRA_POWERGATE_BPMP def_bool y -- cgit v1.2.3 From 09701895aa93df32cc708eab032ae8704feda333 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 7 May 2020 11:13:48 +0100 Subject: soc/tegra: pmc: Enable PMIC wake event on Tegra194 The PMIC wake event can be used to bring the system out of suspend based on certain events happening on the PMIC (such as an RTC alarm). Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 72cfda7305d5..8169737c3252 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -3326,6 +3326,7 @@ static const char * const tegra194_reset_sources[] = { }; static const struct tegra_wake_event tegra194_wake_events[] = { + TEGRA_WAKE_IRQ("pmu", 24, 209), TEGRA_WAKE_GPIO("power", 29, 1, TEGRA194_AON_GPIO(EE, 4)), TEGRA_WAKE_IRQ("rtc", 73, 10), }; -- cgit v1.2.3 From df701a76a6419e66b566457a5b3fcdd314e48fd9 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 20 May 2020 16:13:17 +0100 Subject: soc/tegra: pmc: Enable PMIC wake event on Tegra210 The PMIC wake event can be used to bring the system out of suspend based on certain events happening on the PMIC (such as an RTC alarm). Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/soc') diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 8169737c3252..42cf37a0556b 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -3063,6 +3063,7 @@ static const struct pinctrl_pin_desc tegra210_pin_descs[] = { static const struct tegra_wake_event tegra210_wake_events[] = { TEGRA_WAKE_IRQ("rtc", 16, 2), + TEGRA_WAKE_IRQ("pmu", 51, 86), }; static const struct tegra_pmc_soc tegra210_pmc_soc = { -- cgit v1.2.3