Skip to contentSkip to conversation

Add generic PM domain support for Tegra

PATCH Applied Jon Hunter 9 participants 38 messages Feb 26, 2016 – Mar 7, 2016 12 messages not in the archive

Subsystems (10)

v6 of 8 Applied Latest is v8 →

lore
Share & tools
lore

Jon Hunter

author
#0 lore raw

v6 cover Add generic PM domain support for Tegra

Adds generic PM domain support for Tegra SoCs but this series only enables support for it on Tegra 64-bit devices. There is no reason why this cannot be enable for Tegra 32-bit devices, but to keep the patch series to a minimum only 64-bit devices are enabled so far.

This series has been boot tested on Tegra210 as well as various 32-bit Tegra platforms.

Summary of changes since V5 [2]:
- Split series into 2 series, separating PMC fixes [3] from genpd changes
- This series is based upon fixes series (which is now in -next)
- Added patch to fix removal of genpd subdomain
- Added patch to get last genpd that was added
- Fixed locking in function to remove genpd
- Updated Tegra PMC driver to ensure power-domains cannot be controlled by both legacy Tegra APIs and generic PM domain framework
- Removed powergate list from Tegra PMC driver and updated removal of power domains to use new genpd APIs.

Summary of changes since V4 [1]:
- Re-worked fix to handle base address on probe failure
- Added patch to lock around simultaneuous accesses to PMC registers
- Added patch to change powergate and rail IDs to unsigned type
- Added patch to fix testing of powergate state
- Updated patch to check for valid powergates to use a bitmap
- Updated Tegra DT PMC bindings per Rob H's feedback
- Updated Tegra power domains binding per Thierry's feedback
- Updated Tegra generic power domain support per Thierry's feedback

Summary of changes since V3 [0]:
- Dropped tegra124 support for now
- Removed MC flush support per feedback from Thierry
- Cleaned up the PMC changes per feedback from Thierry
- Added support for tegra210

[0] http://comments.gmane.org/gmane.linux.ports.tegra/22944
[1] http://marc.info/?l=linux-tegra&m=144924153600529&w=2
[2] http://marc.info/?l=linux-tegra&m=145399885003830&w=2
[3] http://marc.info/?l=linux-tegra&m=145521381331144&w=2

Jon Hunter (10):
PM / Domains: Fix removal of a subdomain
PM / Domains: Add function to get the last domain added PM / Domains: Add function to remove a pm-domain
Documentation: DT: bindings: Update NVIDIA PMC for Tegra
Documentation: DT: bindings: Add power domain info for NVIDIA PMC
soc: tegra: pmc: Wait for powergate state to change
soc: tegra: pmc: Add generic PM domain support
soc: tegra: pmc: Move powergate definitions to dt-bindings
ARM64: tegra: select PM_GENERIC_DOMAINS
ARM64: tegra: Add audio PM domain device node for Tegra210

 .../bindings/arm/tegra/nvidia,tegra20-pmc.txt      |  73 ++-
 arch/arm/mach-tegra/platsmp.c                      |  16 +-
 arch/arm64/Kconfig.platforms                       |   2 +
 arch/arm64/boot/dts/nvidia/tegra210.dtsi           |  14 +-
 drivers/base/power/domain.c                        |  58 +-
 drivers/soc/tegra/pmc.c                            | 594 ++++++++++++++++++---
 include/dt-bindings/power/tegra-powergate.h        |  88 +++
 include/linux/pm_domain.h                          |  12 +
 include/soc/tegra/pmc.h                            |  38 +-
 9 files changed, 776 insertions(+), 119 deletions(-)
 create mode 100644 include/dt-bindings/power/tegra-powergate.h
Signature · 1 line
2.1.4

A message that is not in the archive (sent off-list or not yet received): 1456501724-28477-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org

author
#2 lore raw

PATCH v6 1/10 PM / Domains: Fix removal of a subdomain

Commit 30e7a65b3fdb ("PM / Domains: Ensure subdomain is not in use before removing") added a test to ensure that a subdomain is not is not a master to another subdomain or if any devices are using the subdomain before removing. This change incorrectly used the "slave_links" list to determine if the subdomain is a master to another subdomain, where it should have been using the "master_links" list instead. The "slave_links" list will never be empty for a subdomain and so a subdomain can never be removed. Fix this by testing if the "master_links" list is empty instead.

Fixes 30e7a65b3fdb ("PM / Domains: Ensure subdomain is not in use

before removing")

---
 drivers/base/power/domain.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/base/power/domain.c +1 -1
index e8ca290dbf9d..ea9f2aa3fc33 100644
@@ -1382,7 +1382,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 	mutex_lock(&subdomain->lock);
 	mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
 
-	if (!list_empty(&subdomain->slave_links) || subdomain->device_count) {
+	if (!list_empty(&subdomain->master_links) || subdomain->device_count) {
 		pr_warn("%s: unable to remove subdomain %s\n", genpd->name,
 			subdomain->name);
 		ret = -EBUSY;
Signature · 1 line
2.1.4

A message that is not in the archive (sent off-list or not yet received): 1456501724-28477-2-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org

Reviewed-by
#4 lore raw

Re: [PATCH V6 01/10] PM / Domains: Fix removal of a subdomain

Quoted 2 lines · Jon Hunter

Commit 30e7a65b3fdb ("PM / Domains: Ensure subdomain is not in use before removing") added a test to ensure that a subdomain is not is not

Double "is not".

Quoted 8 lines

a master to another subdomain or if any devices are using the subdomain before removing. This change incorrectly used the "slave_links" list to determine if the subdomain is a master to another subdomain, where it should have been using the "master_links" list instead. The "slave_links" list will never be empty for a subdomain and so a subdomain can never be removed. Fix this by testing if the "master_links" list is empty instead.

Quoted 4 lines
Fixes 30e7a65b3fdb ("PM / Domains: Ensure subdomain is not in use

before removing")

I think the Fixes: line is allowed to be longer than 72 characters (the important bits are in the first few characters anyway) and it doesn't need to be separated from other tags by a blank line. That said, I doubt that any of the automation tools will be confused.

Other than that, the change looks correct:

Quoted 20 lines
---
 drivers/base/power/domain.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/base/power/domain.c +1 -1
index e8ca290dbf9d..ea9f2aa3fc33 100644
@@ -1382,7 +1382,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 	mutex_lock(&subdomain->lock);
 	mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
 
-	if (!list_empty(&subdomain->slave_links) || subdomain->device_count) {
+	if (!list_empty(&subdomain->master_links) || subdomain->device_count) {
 		pr_warn("%s: unable to remove subdomain %s\n", genpd->name,
 			subdomain->name);
 		ret = -EBUSY;
Signature · 1 line
2.1.4
Acked-by
#5 lore raw

Re: [PATCH V6 01/10] PM / Domains: Fix removal of a subdomain

In reply to a message not in the archive
Quoted 10 lines · Jon Hunter

Commit 30e7a65b3fdb ("PM / Domains: Ensure subdomain is not in use before removing") added a test to ensure that a subdomain is not is not a master to another subdomain or if any devices are using the subdomain before removing. This change incorrectly used the "slave_links" list to determine if the subdomain is a master to another subdomain, where it should have been using the "master_links" list instead. The "slave_links" list will never be empty for a subdomain and so a subdomain can never be removed. Fix this by testing if the "master_links" list is empty instead.

Quoted 4 lines
Fixes 30e7a65b3fdb ("PM / Domains: Ensure subdomain is not in use

before removing")

When you addressed the comments from Thierry, this also looks good to me.

Kind regards
Uffe

Quoted 20 lines
---
 drivers/base/power/domain.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/base/power/domain.c +1 -2
index e8ca290dbf9d..ea9f2aa3fc33 100644
@@ -1382,7 +1382,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
        mutex_lock(&subdomain->lock);
        mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
 
-       if (!list_empty(&subdomain->slave_links) || subdomain->device_count) {
+       if (!list_empty(&subdomain->master_links) || subdomain->device_count) {
                pr_warn("%s: unable to remove subdomain %s\n", genpd->name,
                        subdomain->name);
                ret = -EBUSY;
--

2.1.4

author
#6 lore raw

PATCH v6 3/10 PM / Domains: Add function to remove a pm-domain

In reply to a message not in the archive

The genpd framework allows users to add power-domains via the pm_genpd_init() function, however, there is no corresponding function to remove a power-domain. For most devices this may be fine as the power domains are never removed, however, for devices that wish to populate the power-domains from within a driver, having the ability to remove a power domain if the probing of the device fails or the driver is unloaded is necessary. Therefore, add a function to remove a power-domain. Please note that the power domain can only be removed if there are no devices using the power-domain and it is not linked to another domain.

---
 drivers/base/power/domain.c | 31 +++++++++++++++++++++++++++++++
 include/linux/pm_domain.h   |  5 +++++
 2 files changed, 36 insertions(+)
drivers/base/power/domain.c +31 -0
index 608bc00655ee..22f6e9d738bf 100644
@@ -1557,6 +1557,37 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
 }
 EXPORT_SYMBOL_GPL(pm_genpd_init);
 
+/**
+ * pm_genpd_remove - Remove a generic I/O PM domain object.
+ * @genpd: PM domain object to remove.
+ */
+int pm_genpd_remove(struct generic_pm_domain *genpd)
+{
+	int ret = 0;
+
+	if (IS_ERR_OR_NULL(genpd))
+		return -EINVAL;
+
+	mutex_lock(&gpd_list_lock);
+	mutex_lock(&genpd->lock);
+
+	if (!list_empty(&genpd->master_links)
+	    || !list_empty(&genpd->slave_links) || genpd->device_count) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	cancel_work_sync(&genpd->power_off_work);
+	list_del(&genpd->gpd_list_node);
+
+out:
+	mutex_unlock(&genpd->lock);
+	mutex_unlock(&gpd_list_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pm_genpd_remove);
+
 #ifdef CONFIG_PM_GENERIC_DOMAINS_OF
 /*
  * Device Tree based PM domain providers.
include/linux/pm_domain.h +5 -0
index b38dd74dea9b..9ae9c42f807f 100644
@@ -134,6 +134,7 @@ extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 				     struct generic_pm_domain *target);
 extern void pm_genpd_init(struct generic_pm_domain *genpd,
 			  struct dev_power_governor *gov, bool is_off);
+extern int pm_genpd_remove(struct generic_pm_domain *genpd);
 
 extern struct dev_power_governor simple_qos_governor;
 extern struct dev_power_governor pm_domain_always_on_gov;
@@ -177,6 +178,10 @@ static inline void pm_genpd_init(struct generic_pm_domain *genpd,
 				 struct dev_power_governor *gov, bool is_off)
 {
 }
+static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
+{
+	return -ENOTSUPP;
+}
 #endif
 
 static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
Signature · 1 line
2.1.4
Reviewed-by on v6 3/10
#7 lore raw

Re: [PATCH V6 03/10] PM / Domains: Add function to remove a pm-domain

Quoted 9 lines · Jon Hunter

The genpd framework allows users to add power-domains via the pm_genpd_init() function, however, there is no corresponding function to remove a power-domain. For most devices this may be fine as the power domains are never removed, however, for devices that wish to populate the power-domains from within a driver, having the ability to remove a power domain if the probing of the device fails or the driver is unloaded is necessary. Therefore, add a function to remove a power-domain. Please note that the power domain can only be removed if there are no devices using the power-domain and it is not linked to another domain.

So I guess this introduces a problem not uncommon to other types of resources. If you remove the driver, even if you fail ->remove() the module may still go away along with any code associated with it. So even if the PM domains can't be removed, you can't prevent the module from going away. That could be somewhat mitigated if we were holding a module reference count, because then the only way to unload the driver would be via sysfs (we could prevent that too, which might be the best way to do this today).

There is work underway to solve this generically, Rafael was working on this, so I'm not sure we need to add additional infrastructure to the PM domain code as part of this series. But we may want to mark the Tegra PMC driver as .suppress_bind_attrs = true, to make sure it can't be removed.

Quoted 11 lines
---
 drivers/base/power/domain.c | 31 +++++++++++++++++++++++++++++++
 include/linux/pm_domain.h   |  5 +++++
 2 files changed, 36 insertions(+)
drivers/base/power/domain.c +0 -0
index 608bc00655ee..22f6e9d738bf 100644

drivers/base/power/domain.c void pm_genpd_init(struct generic_pm_domain *genpd, · line 1563

Quoted 7 lines
drivers/base/power/domain.c +4 -0
@@ -1557,6 +1557,37 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
 }
 EXPORT_SYMBOL_GPL(pm_genpd_init);
 
+/**
+ * pm_genpd_remove - Remove a generic I/O PM domain object.
+ * @genpd: PM domain object to remove.
+ */

Would it be worth noting here that the object is only removed from the list of domains, but that users are still responsible for freeing any resources (such as memory) associated with it? It seems like this might be obvious enough given the usage model of pm_genpd_init(), but it's something that I noticed missing from the function.

Otherwise this looks fine:

author
#8 lore raw

Re: [PATCH V6 03/10] PM / Domains: Add function to remove a pm-domain

Quoted 22 lines · Thierry Reding

* PGP Signed by an unknown key

Quoted 9 lines · Jon Hunter

The genpd framework allows users to add power-domains via the pm_genpd_init() function, however, there is no corresponding function to remove a power-domain. For most devices this may be fine as the power domains are never removed, however, for devices that wish to populate the power-domains from within a driver, having the ability to remove a power domain if the probing of the device fails or the driver is unloaded is necessary. Therefore, add a function to remove a power-domain. Please note that the power domain can only be removed if there are no devices using the power-domain and it is not linked to another domain.

So I guess this introduces a problem not uncommon to other types of resources. If you remove the driver, even if you fail ->remove() the module may still go away along with any code associated with it. So even if the PM domains can't be removed, you can't prevent the module from going away. That could be somewhat mitigated if we were holding a module reference count, because then the only way to unload the driver would be via sysfs (we could prevent that too, which might be the best way to do this today).

Quoted 5 lines

There is work underway to solve this generically, Rafael was working on this, so I'm not sure we need to add additional infrastructure to the PM domain code as part of this series. But we may want to mark the Tegra PMC driver as .suppress_bind_attrs = true, to make sure it can't be removed.

I see what you are saying. It nearly seemed to me that I should use BUG_ON() if we fail to remove a genpd in the PMC driver, however, I know that using BUG_ON should be avoided. I will add the suppress_bind_attrs = true for the PMC driver as that does make sense for now.

Jon

A message that is not in the archive (sent off-list or not yet received): [email protected]

author
#10 lore raw

Re: [PATCH V6 03/10] PM / Domains: Add function to remove a pm-domain

Quoted 30 lines · Jon Hunter
Quoted 22 lines · Thierry Reding

* PGP Signed by an unknown key

Quoted 9 lines · Jon Hunter

The genpd framework allows users to add power-domains via the pm_genpd_init() function, however, there is no corresponding function to remove a power-domain. For most devices this may be fine as the power domains are never removed, however, for devices that wish to populate the power-domains from within a driver, having the ability to remove a power domain if the probing of the device fails or the driver is unloaded is necessary. Therefore, add a function to remove a power-domain. Please note that the power domain can only be removed if there are no devices using the power-domain and it is not linked to another domain.

So I guess this introduces a problem not uncommon to other types of resources. If you remove the driver, even if you fail ->remove() the module may still go away along with any code associated with it. So even if the PM domains can't be removed, you can't prevent the module from going away. That could be somewhat mitigated if we were holding a module reference count, because then the only way to unload the driver would be via sysfs (we could prevent that too, which might be the best way to do this today).

Quoted 5 lines

There is work underway to solve this generically, Rafael was working on this, so I'm not sure we need to add additional infrastructure to the PM domain code as part of this series. But we may want to mark the Tegra PMC driver as .suppress_bind_attrs = true, to make sure it can't be removed.

Quoted 4 lines

I see what you are saying. It nearly seemed to me that I should use BUG_ON() if we fail to remove a genpd in the PMC driver, however, I know that using BUG_ON should be avoided. I will add the suppress_bind_attrs = true for the PMC driver as that does make sense for now.

Just to let you know, the PMC driver already has suppress_bind_attrs = true.

Cheers
Jon

#11 lore raw

Re: [PATCH V6 03/10] PM / Domains: Add function to remove a pm-domain

In reply to Jon Hunter
Quoted 9 lines · Jon Hunter

The genpd framework allows users to add power-domains via the pm_genpd_init() function, however, there is no corresponding function to remove a power-domain. For most devices this may be fine as the power domains are never removed, however, for devices that wish to populate the power-domains from within a driver, having the ability to remove a power domain if the probing of the device fails or the driver is unloaded is necessary. Therefore, add a function to remove a power-domain. Please note that the power domain can only be removed if there are no devices using the power-domain and it is not linked to another domain.

In general I think you can work a bit on the changelog, for example split it into a few sections to make it more readable.

I would like it to state clearly what constraint we have to be able to remove a PM domain. More precisely, the device structure is needed, no of genpd provider etc. Maybe also "linked to another domain" can be rephrased to tell about both masters and subdomains.

Finally, perhaps change terminology for the "power-domain" to "PM domain" as I think that's more widely used.

Quoted 26 lines
---
 drivers/base/power/domain.c | 31 +++++++++++++++++++++++++++++++
 include/linux/pm_domain.h   |  5 +++++
 2 files changed, 36 insertions(+)
drivers/base/power/domain.c +11 -0
index 608bc00655ee..22f6e9d738bf 100644
@@ -1557,6 +1557,37 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
 }
 EXPORT_SYMBOL_GPL(pm_genpd_init);
 
+/**
+ * pm_genpd_remove - Remove a generic I/O PM domain object.
+ * @genpd: PM domain object to remove.
+ */
+int pm_genpd_remove(struct generic_pm_domain *genpd)
+{
+       int ret = 0;
+
+       if (IS_ERR_OR_NULL(genpd))
+               return -EINVAL;
+

drivers/base/power/domain.c void pm_genpd_init(struct generic_pm_domain *genpd, · line 1580

Quoted 10 lines
drivers/base/power/domain.c +10 -0
+       mutex_lock(&gpd_list_lock);
+       mutex_lock(&genpd->lock);
+
+       if (!list_empty(&genpd->master_links)
+           || !list_empty(&genpd->slave_links) || genpd->device_count) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       cancel_work_sync(&genpd->power_off_work);

This can deadlock as the work function tries to lock the genpd mutex.

I suggest to move this outside of the locking section just before returning, but of course still only in case of a non-error.

drivers/base/power/domain.c void pm_genpd_init(struct generic_pm_domain *genpd, · line 1586

Quoted 6 lines
drivers/base/power/domain.c +6 -0
+       list_del(&genpd->gpd_list_node);
+
+out:
+       mutex_unlock(&genpd->lock);
+       mutex_unlock(&gpd_list_lock);
+

Besides the minor comment above.

1) Have you considered how to protects against a registered of_genpd_provider for the genpd?

2) Theoretically some could call pm_genpd_add_subdomain() after this point. I guess we can consider that as an abuse of the API, although do you think we need to protect that from really happening?

Quoted 31 lines
drivers/base/power/domain.c +4 -0
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pm_genpd_remove);
+
 #ifdef CONFIG_PM_GENERIC_DOMAINS_OF
 /*
  * Device Tree based PM domain providers.
include/linux/pm_domain.h +5 -1
index b38dd74dea9b..9ae9c42f807f 100644
@@ -134,6 +134,7 @@ extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
                                     struct generic_pm_domain *target);
 extern void pm_genpd_init(struct generic_pm_domain *genpd,
                          struct dev_power_governor *gov, bool is_off);
+extern int pm_genpd_remove(struct generic_pm_domain *genpd);
 
 extern struct dev_power_governor simple_qos_governor;
 extern struct dev_power_governor pm_domain_always_on_gov;
@@ -177,6 +178,10 @@ static inline void pm_genpd_init(struct generic_pm_domain *genpd,
                                 struct dev_power_governor *gov, bool is_off)
 {
 }
+static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
+{
+       return -ENOTSUPP;
+}
 #endif
 
 static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
--
Quoted 2 lines

2.1.4

Kind regards
Uffe

author
#12 lore raw

PATCH v6 4/10 Documentation: DT: bindings: Update NVIDIA PMC for Tegra

In reply to a message not in the archive

Add the PMC driver compatible strings for Tegra132 and Tegra210.

---
 .../devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt     | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +7 -5
index 02c27004d4a8..53aa5496c5cf 100644
@@ -6,11 +6,13 @@ modes. It provides power-gating controllers for SoC and CPU power-islands.
 
 Required properties:
 - name : Should be pmc
-- compatible : For Tegra20, must contain "nvidia,tegra20-pmc".  For Tegra30,
-  must contain "nvidia,tegra30-pmc".  For Tegra114, must contain
-  "nvidia,tegra114-pmc".  For Tegra124, must contain "nvidia,tegra124-pmc".
-  Otherwise, must contain "nvidia,<chip>-pmc", plus at least one of the
-  above, where <chip> is tegra132.
+- compatible : Should contain one of the following:
+	For Tegra20 must contain "nvidia,tegra20-pmc".
+	For Tegra30 must contain "nvidia,tegra30-pmc".
+	For Tegra114 must contain "nvidia,tegra114-pmc"
+	For Tegra124 must contain "nvidia,tegra124-pmc"
+	For Tegra132 must contain "nvidia,tegra124-pmc"
+	For Tegra210 must contain "nvidia,tegra210-pmc"
 - reg : Offset and length of the register set for the device
 - clocks : Must contain an entry for each entry in clock-names.
   See ../clocks/clock-bindings.txt for details.
Signature · 1 line
2.1.4
#13 lore raw

Re: [PATCH V6 04/10] Documentation: DT: bindings: Update NVIDIA PMC for Tegra

Quoted 7 lines · Jon Hunter

Add the PMC driver compatible strings for Tegra132 and Tegra210.

---
 .../devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt     | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

Applied, thanks.

Thierry

author
#14 lore raw

PATCH v6 6/10 soc: tegra: pmc: Wait for powergate state to change

In reply to a message not in the archive

Currently, the function tegra_powergate_set() simply sets the desired powergate state but does not wait for the state to change. In most cases we should wait for the state to change before proceeding. Currently, there is a case for tegra114 and tegra124 devices where we do not wait when starting the secondary CPU as this is not necessary. However, this is only done at boot time and so waiting here will only have a small impact on boot time. Therefore, update tegra_powergate_set() to wait when setting the powergate.

By adding this feature, we can also eliminate the polling loop from tegra30_boot_secondary().

A function has been added for checking the status of the powergate and so update the tegra_powergate_is_powered() to use this macro as well.

---
 arch/arm/mach-tegra/platsmp.c | 16 +++-------------
 drivers/soc/tegra/pmc.c       |  9 ++++++++-
 2 files changed, 11 insertions(+), 14 deletions(-)
arch/arm/mach-tegra/platsmp.c +3 -13
index f3f61dbbda97..75620ae73913 100644
@@ -108,19 +108,9 @@ static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 * be un-gated by un-toggling the power gate register
 	 * manually.
 	 */
-	if (!tegra_pmc_cpu_is_powered(cpu)) {
-		ret = tegra_pmc_cpu_power_on(cpu);
-		if (ret)
-			return ret;
-
-		/* Wait for the power to come up. */
-		timeout = jiffies + msecs_to_jiffies(100);
-		while (!tegra_pmc_cpu_is_powered(cpu)) {
-			if (time_after(jiffies, timeout))
-				return -ETIMEDOUT;
-			udelay(10);
-		}
-	}
+	ret = tegra_pmc_cpu_power_on(cpu);
+	if (ret)
+		return ret;
 
 remove_clamps:
 	/* CPU partition is powered. Enable the CPU clock. */
drivers/soc/tegra/pmc.c +8 -1
index e4fd40fa27e8..08966c26d65c 100644
@@ -28,6 +28,7 @@
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
@@ -194,6 +195,9 @@ static inline bool tegra_powergate_is_valid(int id)
  */
 static int tegra_powergate_set(unsigned int id, bool new_state)
 {
+	bool status;
+	int err;
+
 	if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps)
 		return -EINVAL;
 
@@ -206,9 +210,12 @@ static int tegra_powergate_set(unsigned int id, bool new_state)
 
 	tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
 
+	err = readx_poll_timeout(tegra_powergate_state, id, status,
+				 status == new_state, 10, 100000);
+
 	mutex_unlock(&pmc->powergates_lock);
 
-	return 0;
+	return err;
 }
 
 /**
Signature · 1 line
2.1.4

A message that is not in the archive (sent off-list or not yet received): 1456501724-28477-7-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org

#16 lore raw

Re: [PATCH V6 06/10] soc: tegra: pmc: Wait for powergate state to change

Quoted 12 lines · Jon Hunter

Currently, the function tegra_powergate_set() simply sets the desired powergate state but does not wait for the state to change. In most cases we should wait for the state to change before proceeding. Currently, there is a case for tegra114 and tegra124 devices where we do not wait when starting the secondary CPU as this is not necessary. However, this is only done at boot time and so waiting here will only have a small impact on boot time. Therefore, update tegra_powergate_set() to wait when setting the powergate.

By adding this feature, we can also eliminate the polling loop from tegra30_boot_secondary().

Quoted 8 lines

A function has been added for checking the status of the powergate and so update the tegra_powergate_is_powered() to use this macro as well.

---
 arch/arm/mach-tegra/platsmp.c | 16 +++-------------
 drivers/soc/tegra/pmc.c       |  9 ++++++++-
 2 files changed, 11 insertions(+), 14 deletions(-)

This looks to be independent from the generic power domain support. Can I apply this separately (for 4.6, without waiting for the power domain series' dependencies to go in)?

Thierry

author
#17 lore raw

Re: [PATCH V6 06/10] soc: tegra: pmc: Wait for powergate state to change

Quoted 24 lines · Thierry Reding

* PGP Signed by an unknown key

Quoted 12 lines · Jon Hunter

Currently, the function tegra_powergate_set() simply sets the desired powergate state but does not wait for the state to change. In most cases we should wait for the state to change before proceeding. Currently, there is a case for tegra114 and tegra124 devices where we do not wait when starting the secondary CPU as this is not necessary. However, this is only done at boot time and so waiting here will only have a small impact on boot time. Therefore, update tegra_powergate_set() to wait when setting the powergate.

By adding this feature, we can also eliminate the polling loop from tegra30_boot_secondary().

Quoted 8 lines

A function has been added for checking the status of the powergate and so update the tegra_powergate_is_powered() to use this macro as well.

---
 arch/arm/mach-tegra/platsmp.c | 16 +++-------------
 drivers/soc/tegra/pmc.c       |  9 ++++++++-
 2 files changed, 11 insertions(+), 14 deletions(-)
Quoted 3 lines

This looks to be independent from the generic power domain support. Can I apply this separately (for 4.6, without waiting for the power domain series' dependencies to go in)?

Yes this could be applied independently of this series for v4.6. I just wanted to make sure that this change is added before the genpd changes are applied.

Cheers
Jon

#18 lore raw

Re: [PATCH V6 06/10] soc: tegra: pmc: Wait for powergate state to change

In reply to a message not in the archive
Quoted 12 lines · Jon Hunter

Currently, the function tegra_powergate_set() simply sets the desired powergate state but does not wait for the state to change. In most cases we should wait for the state to change before proceeding. Currently, there is a case for tegra114 and tegra124 devices where we do not wait when starting the secondary CPU as this is not necessary. However, this is only done at boot time and so waiting here will only have a small impact on boot time. Therefore, update tegra_powergate_set() to wait when setting the powergate.

By adding this feature, we can also eliminate the polling loop from tegra30_boot_secondary().

Quoted 8 lines

A function has been added for checking the status of the powergate and so update the tegra_powergate_is_powered() to use this macro as well.

---
 arch/arm/mach-tegra/platsmp.c | 16 +++-------------
 drivers/soc/tegra/pmc.c       |  9 ++++++++-
 2 files changed, 11 insertions(+), 14 deletions(-)

Applied, thanks.

Thierry

author
#19 lore raw

PATCH v6 8/10 soc: tegra: pmc: Move powergate definitions to dt-bindings

In reply to a message not in the archive

Move the Tegra Powergate definitions into include/dt-bindings so that these can be used by the powergate bindings in device-tree source files.

Remove the TEGRA_POWERGATE_3D0 definition as this is an alias and is not used anywhere.

---
 drivers/soc/tegra/pmc.c                     |  2 +
 include/dt-bindings/power/tegra-powergate.h | 88 +++++++++++++++++++++++++++++
 include/soc/tegra/pmc.h                     | 39 +------------
 3 files changed, 93 insertions(+), 36 deletions(-)
 create mode 100644 include/dt-bindings/power/tegra-powergate.h
drivers/soc/tegra/pmc.c +2 -0
index 9d2d204342c5..6c5833bc3fab 100644
@@ -19,6 +19,8 @@
 
 #define pr_fmt(fmt) "tegra-pmc: " fmt
 
+#include <dt-bindings/power/tegra-powergate.h>
+
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/clk/tegra.h>
include/dt-bindings/power/tegra-powergate.h new file +88 -0

88 lines not on this page · raw message

include/soc/tegra/pmc.h +3 -36
index e9e53473a63e..c028557365ad 100644
@@ -19,6 +19,8 @@
 #ifndef __SOC_TEGRA_PMC_H__
 #define __SOC_TEGRA_PMC_H__
 
+#include <dt-bindings/power/tegra-powergate.h>
+
 #include <linux/reboot.h>
 
 #include <soc/tegra/pm.h>
@@ -39,43 +41,8 @@ int tegra_pmc_cpu_remove_clamping(unsigned int cpuid);
 #endif /* CONFIG_SMP */
 
 /*
- * powergate and I/O rail APIs
+ * I/O rail APIs
  */
-
-#define TEGRA_POWERGATE_CPU	0
-#define TEGRA_POWERGATE_3D	1
-#define TEGRA_POWERGATE_VENC	2
-#define TEGRA_POWERGATE_PCIE	3
-#define TEGRA_POWERGATE_VDEC	4
-#define TEGRA_POWERGATE_L2	5
-#define TEGRA_POWERGATE_MPE	6
-#define TEGRA_POWERGATE_HEG	7
-#define TEGRA_POWERGATE_SATA	8
-#define TEGRA_POWERGATE_CPU1	9
-#define TEGRA_POWERGATE_CPU2	10
-#define TEGRA_POWERGATE_CPU3	11
-#define TEGRA_POWERGATE_CELP	12
-#define TEGRA_POWERGATE_3D1	13
-#define TEGRA_POWERGATE_CPU0	14
-#define TEGRA_POWERGATE_C0NC	15
-#define TEGRA_POWERGATE_C1NC	16
-#define TEGRA_POWERGATE_SOR	17
-#define TEGRA_POWERGATE_DIS	18
-#define TEGRA_POWERGATE_DISB	19
-#define TEGRA_POWERGATE_XUSBA	20
-#define TEGRA_POWERGATE_XUSBB	21
-#define TEGRA_POWERGATE_XUSBC	22
-#define TEGRA_POWERGATE_VIC	23
-#define TEGRA_POWERGATE_IRAM	24
-#define TEGRA_POWERGATE_NVDEC	25
-#define TEGRA_POWERGATE_NVJPG	26
-#define TEGRA_POWERGATE_AUD	27
-#define TEGRA_POWERGATE_DFD	28
-#define TEGRA_POWERGATE_VE2	29
-#define TEGRA_POWERGATE_MAX	TEGRA_POWERGATE_VE2
-
-#define TEGRA_POWERGATE_3D0	TEGRA_POWERGATE_3D
-
 #define TEGRA_IO_RAIL_CSIA	0
 #define TEGRA_IO_RAIL_CSIB	1
 #define TEGRA_IO_RAIL_DSI	2
Signature · 6 lines
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
author
#20 lore raw

PATCH v6 9/10 ARM64: tegra: select PM_GENERIC_DOMAINS

In reply to a message not in the archive

Enable PM_GENERIC_DOMAINS for tegra 64-bit devices. To ensure that devices dependent upon a particular power-domain are only probed when that power domain has been powered up, requires that PM is made mandatory for tegra 64-bit devices and so select this option for tegra as well.

---
 arch/arm64/Kconfig.platforms | 2 ++
 1 file changed, 2 insertions(+)
arch/arm64/Kconfig.platforms +2 -0
index 1c3a137e216b..bd52c3e80ac5 100644
@@ -113,6 +113,8 @@ config ARCH_TEGRA
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
 	select PINCTRL
+	select PM
+	select PM_GENERIC_DOMAINS
 	select RESET_CONTROLLER
 	help
 	  This enables support for the NVIDIA Tegra SoC family.
Signature · 1 line
2.1.4

A message that is not in the archive (sent off-list or not yet received): 1456501724-28477-10-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org

Reviewed-by
#22 lore raw

Re: [PATCH V6 09/10] ARM64: tegra: select PM_GENERIC_DOMAINS

Quoted 6 lines · Jon Hunter

Enable PM_GENERIC_DOMAINS for tegra 64-bit devices. To ensure that devices dependent upon a particular power-domain are only probed when that power domain has been powered up, requires that PM is made mandatory for tegra 64-bit devices and so select this option for tegra as well.

Kind regards
Uffe

Quoted 20 lines
---
 arch/arm64/Kconfig.platforms | 2 ++
 1 file changed, 2 insertions(+)
arch/arm64/Kconfig.platforms +2 -1
index 1c3a137e216b..bd52c3e80ac5 100644
@@ -113,6 +113,8 @@ config ARCH_TEGRA
        select GENERIC_CLOCKEVENTS
        select HAVE_CLK
        select PINCTRL
+       select PM
+       select PM_GENERIC_DOMAINS
        select RESET_CONTROLLER
        help
          This enables support for the NVIDIA Tegra SoC family.
--

2.1.4

maintainer
#23 lore raw

PATCH v6 2/10 PM / Domains: Add function to get the last domain added

In reply to Jon Hunter

To remove generic PM domains in a sane way, we need to remove them by starting from the last PM domain added. The reason for this is that a PM domain may be a subdomain of another and so we need to remove the child PM domains for a given domain first. By removing PM domains in reverse order we can ensure that the children are removed first.

Add a new function to get the last PM domain that was added. In case PM domains are added by more than one device in the system (for example, on-chip domains and off-chip domains) add a 'owner' device structure to the generic PM domain structure so that the ownership of a PM domain can be identified by the device structure of the device that added it Use this 'owner' device structure to return the last PM domain added by this device.

Note that because pm_genpd_init() simply adds each PM domain to the head of the gpd_list object, list_for_each_entry() will start from the last PM domain added.

---
This is the outcome from a discussion I had with Ulf on how best to handle the removal of power-domains [0]. I opted to call the device structure 'owner' because 'parent' could be misleading if a power domain is a child of another power domain. However, open to suggestions!

[0] http://marc.info/?l=linux-pm&m=145460070816340&w=2

 drivers/base/power/domain.c | 25 +++++++++++++++++++++++++
 include/linux/pm_domain.h   |  7 +++++++
 2 files changed, 32 insertions(+)
drivers/base/power/domain.c +25 -0
index ea9f2aa3fc33..608bc00655ee 100644
@@ -65,6 +65,31 @@ struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev)
 }
 
 /*
+ * Get the last generic PM domain added whose 'owner' device structure
+ * matches the device structure provided. The 'owner' device structure
+ * for a given PM domain should be initialised by the device that is
+ * creating the PM domains and hence, calling pm_genpd_init().
+ */
+struct generic_pm_domain *pm_genpd_list_get_tail(struct device *dev)
+{
+	struct generic_pm_domain *genpd = NULL, *gpd;
+
+	if (IS_ERR_OR_NULL(dev))
+		return NULL;
+
+	mutex_lock(&gpd_list_lock);
+	list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
+		if (gpd->owner == dev) {
+			genpd = gpd;
+			break;
+		}
+	}
+	mutex_unlock(&gpd_list_lock);
+
+	return genpd;
+}
+
+/*
  * This should only be used where we are certain that the pm_domain
  * attached to the device is a genpd domain.
  */
include/linux/pm_domain.h +7 -0
index 49cd8890b873..b38dd74dea9b 100644
@@ -46,6 +46,7 @@ struct genpd_power_state {
 
 struct generic_pm_domain {
 	struct dev_pm_domain domain;	/* PM domain operations */
+	struct device *owner;		/* Identity of the domain owner */
 	struct list_head gpd_list_node;	/* Node in the global PM domains list */
 	struct list_head master_links;	/* Links with PM domain as a master */
 	struct list_head slave_links;	/* Links with PM domain as a slave */
@@ -120,6 +121,7 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
 }
 
 extern struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev);
+extern struct generic_pm_domain *pm_genpd_list_get_tail(struct device *dev);
 extern int __pm_genpd_add_device(struct generic_pm_domain *genpd,
 				 struct device *dev,
 				 struct gpd_timing_data *td);
@@ -145,6 +147,11 @@ static inline struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev)
 {
 	return NULL;
 }
+static inline
+struct generic_pm_domain *pm_genpd_list_get_tail(struct device *dev)
+{
+	return NULL;
+}
 static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd,
 					struct device *dev,
 					struct gpd_timing_data *td)
Signature · 1 line
2.1.4

A message that is not in the archive (sent off-list or not yet received): 1456501724-28477-3-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org

Reviewed-by
#25 lore raw

Re: [PATCH V6 02/10] PM / Domains: Add function to get the last domain added

Quoted 18 lines · Jon Hunter

To remove generic PM domains in a sane way, we need to remove them by starting from the last PM domain added. The reason for this is that a PM domain may be a subdomain of another and so we need to remove the child PM domains for a given domain first. By removing PM domains in reverse order we can ensure that the children are removed first.

Add a new function to get the last PM domain that was added. In case PM domains are added by more than one device in the system (for example, on-chip domains and off-chip domains) add a 'owner' device structure to the generic PM domain structure so that the ownership of a PM domain can be identified by the device structure of the device that added it Use this 'owner' device structure to return the last PM domain added by this device.

Note that because pm_genpd_init() simply adds each PM domain to the head of the gpd_list object, list_for_each_entry() will start from the last PM domain added.

Quoted 6 lines

---
This is the outcome from a discussion I had with Ulf on how best to handle the removal of power-domains [0]. I opted to call the device structure 'owner' because 'parent' could be misleading if a power domain is a child of another power domain. However, open to suggestions!

I've seen "dev" used a lot in other subsystems when an entity is provided by a specific device. "provider" might be another alternative, but I don't have any strong objections against "owner" either.

Quoted 6 lines

[0] http://marc.info/?l=linux-pm&m=145460070816340&w=2

 drivers/base/power/domain.c | 25 +++++++++++++++++++++++++
 include/linux/pm_domain.h   |  7 +++++++
 2 files changed, 32 insertions(+)

Besides the name bikeshedding, the change looks correct:

Acked-by on v6 2/10
#26 lore raw

Re: [PATCH V6 02/10] PM / Domains: Add function to get the last domain added

In reply to Jon Hunter
Quoted 14 lines · Jon Hunter

To remove generic PM domains in a sane way, we need to remove them by starting from the last PM domain added. The reason for this is that a PM domain may be a subdomain of another and so we need to remove the child PM domains for a given domain first. By removing PM domains in reverse order we can ensure that the children are removed first.

Add a new function to get the last PM domain that was added. In case PM domains are added by more than one device in the system (for example, on-chip domains and off-chip domains) add a 'owner' device structure to the generic PM domain structure so that the ownership of a PM domain can be identified by the device structure of the device that added it Use this 'owner' device structure to return the last PM domain added by this device.

Quoted 5 lines

Note that because pm_genpd_init() simply adds each PM domain to the head of the gpd_list object, list_for_each_entry() will start from the last PM domain added.

I don't have a strong opinion about what to call the device structure. Both "owner" or "dev" is okay by me.

Kind regards
Uffe

Quoted 83 lines

---
This is the outcome from a discussion I had with Ulf on how best to handle the removal of power-domains [0]. I opted to call the device structure 'owner' because 'parent' could be misleading if a power domain is a child of another power domain. However, open to suggestions!

[0] http://marc.info/?l=linux-pm&m=145460070816340&w=2

 drivers/base/power/domain.c | 25 +++++++++++++++++++++++++
 include/linux/pm_domain.h   |  7 +++++++
 2 files changed, 32 insertions(+)
drivers/base/power/domain.c +25 -0
index ea9f2aa3fc33..608bc00655ee 100644
@@ -65,6 +65,31 @@ struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev)
 }
 
 /*
+ * Get the last generic PM domain added whose 'owner' device structure
+ * matches the device structure provided. The 'owner' device structure
+ * for a given PM domain should be initialised by the device that is
+ * creating the PM domains and hence, calling pm_genpd_init().
+ */
+struct generic_pm_domain *pm_genpd_list_get_tail(struct device *dev)
+{
+       struct generic_pm_domain *genpd = NULL, *gpd;
+
+       if (IS_ERR_OR_NULL(dev))
+               return NULL;
+
+       mutex_lock(&gpd_list_lock);
+       list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
+               if (gpd->owner == dev) {
+                       genpd = gpd;
+                       break;
+               }
+       }
+       mutex_unlock(&gpd_list_lock);
+
+       return genpd;
+}
+
+/*
  * This should only be used where we are certain that the pm_domain
  * attached to the device is a genpd domain.
  */
include/linux/pm_domain.h +7 -1
index 49cd8890b873..b38dd74dea9b 100644
@@ -46,6 +46,7 @@ struct genpd_power_state {
 
 struct generic_pm_domain {
        struct dev_pm_domain domain;    /* PM domain operations */
+       struct device *owner;           /* Identity of the domain owner */
        struct list_head gpd_list_node; /* Node in the global PM domains list */
        struct list_head master_links;  /* Links with PM domain as a master */
        struct list_head slave_links;   /* Links with PM domain as a slave */
@@ -120,6 +121,7 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
 }
 
 extern struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev);
+extern struct generic_pm_domain *pm_genpd_list_get_tail(struct device *dev);
 extern int __pm_genpd_add_device(struct generic_pm_domain *genpd,
                                 struct device *dev,
                                 struct gpd_timing_data *td);
@@ -145,6 +147,11 @@ static inline struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev)
 {
        return NULL;
 }
+static inline
+struct generic_pm_domain *pm_genpd_list_get_tail(struct device *dev)
+{
+       return NULL;
+}
 static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd,
                                        struct device *dev,
                                        struct gpd_timing_data *td)
--

2.1.4

maintainer
#27 lore raw

PATCH v6 5/10 Documentation: DT: bindings: Add power domain info for NVIDIA PMC

In reply to Jon Hunter

Add power-domain binding documentation for the NVIDIA PMC driver in order to support generic power-domains.

---
 .../bindings/arm/tegra/nvidia,tegra20-pmc.txt      | 61 ++++++++++++++++++++++
 1 file changed, 61 insertions(+)
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +61 -0
index 53aa5496c5cf..0c383a9e720e 100644
@@ -1,5 +1,7 @@
 NVIDIA Tegra Power Management Controller (PMC)
 
+== Power Management Controller Node ==
+
 The PMC block interacts with an external Power Management Unit. The PMC
 mostly controls the entry and exit of the system from different sleep
 modes. It provides power-gating controllers for SoC and CPU power-islands.
@@ -70,6 +72,11 @@ Optional properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'
                      Defaults to 0. Valid values are described in section 12.5.2
                      "Pinmux Support" of the Tegra4 Technical Reference Manual.
 
+Optional nodes:
+- powergates : This node contains a hierarchy of power domain nodes, which
+	       should match the powergates on the Tegra SoC. See "Powergate
+	       Nodes" below.
+
 Example:
 
 / SoC dts including file
@@ -115,3 +122,57 @@ pmc@7000f400 {
 	};
 	...
 };
+
+
+== Powergate Nodes ==
+
+Each of the powergate nodes represents a power-domain on the Tegra SoC
+that can be power-gated by the PMC and should be named appropriately.
+
+Required properties:
+  - reg: Contains an integer value that identifies the PMC power-gate.
+    Please refer to the Tegra TRM for more details. The parent node
+    must contain the following two properties:
+    - #address-cells: Must be 1,
+    - #size-cells: Must be 0.
+  - clocks: Must contain an entry for each clock required by the PMC for
+    controlling a power-gate. See ../clocks/clock-bindings.txt for details.
+  - resets: Must contain an entry for each reset required by the PMC for
+    controlling a power-gate. See ../reset/reset.txt for details.
+  - #power-domain-cells: Must be 0.
+
+Example:
+
+	pmc: pmc@0,7000e400 {
+		compatible = "nvidia,tegra210-pmc";
+		reg = <0x0 0x7000e400 0x0 0x400>;
+		clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
+		clock-names = "pclk", "clk32k_in";
+
+		powergates {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			pd_audio: aud {
+				reg = <TEGRA_POWERGATE_AUD>;
+				clocks = <&tegra_car TEGRA210_CLK_APE>,
+					 <&tegra_car TEGRA210_CLK_APB2APE>;
+				resets = <&tegra_car 198>;
+				#power-domain-cells = <0>;
+			};
+		};
+	};
+
+
+== Powergate Clients ==
+
+Hardware blocks belonging to a power domain should contain a "power-domains"
+property that is a phandle pointing to the corresponding powergate node.
+
+Example:
+
+	adma: adma@702e2000 {
+		...
+		power-domains = <&pd_audio>;
+		...
+	};
Signature · 1 line
2.1.4

A message that is not in the archive (sent off-list or not yet received): 1456501724-28477-6-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org

#29 lore raw

Re: [PATCH V6 05/10] Documentation: DT: bindings: Add power domain info for NVIDIA PMC

Quoted 67 lines · Jon Hunter

Add power-domain binding documentation for the NVIDIA PMC driver in order to support generic power-domains.

---
 .../bindings/arm/tegra/nvidia,tegra20-pmc.txt      | 61 ++++++++++++++++++++++
 1 file changed, 61 insertions(+)
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +37 -0
index 53aa5496c5cf..0c383a9e720e 100644
@@ -1,5 +1,7 @@
 NVIDIA Tegra Power Management Controller (PMC)
 
+== Power Management Controller Node ==
+
 The PMC block interacts with an external Power Management Unit. The PMC
 mostly controls the entry and exit of the system from different sleep
 modes. It provides power-gating controllers for SoC and CPU power-islands.
@@ -70,6 +72,11 @@ Optional properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'
                      Defaults to 0. Valid values are described in section 12.5.2
                      "Pinmux Support" of the Tegra4 Technical Reference Manual.
 
+Optional nodes:
+- powergates : This node contains a hierarchy of power domain nodes, which
+	       should match the powergates on the Tegra SoC. See "Powergate
+	       Nodes" below.
+
 Example:
 
 / SoC dts including file
@@ -115,3 +122,57 @@ pmc@7000f400 {
 	};
...
 };
+
+
+== Powergate Nodes ==
+
+Each of the powergate nodes represents a power-domain on the Tegra SoC
+that can be power-gated by the PMC and should be named appropriately.
+
+Required properties:
+  - reg: Contains an integer value that identifies the PMC power-gate.
+    Please refer to the Tegra TRM for more details. The parent node
+    must contain the following two properties:
+    - #address-cells: Must be 1,
+    - #size-cells: Must be 0.
+  - clocks: Must contain an entry for each clock required by the PMC for
+    controlling a power-gate. See ../clocks/clock-bindings.txt for details.
+  - resets: Must contain an entry for each reset required by the PMC for
+    controlling a power-gate. See ../reset/reset.txt for details.
+  - #power-domain-cells: Must be 0.
+
+Example:
+
+	pmc: pmc@0,7000e400 {
+		compatible = "nvidia,tegra210-pmc";
+		reg = <0x0 0x7000e400 0x0 0x400>;
+		clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
+		clock-names = "pclk", "clk32k_in";
+
+		powergates {
+			#address-cells = <1>;
+			#size-cells = <0>;

Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt pmc@7000f400 { · line 164

Quoted 10 lines
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +10 -0
+
+			pd_audio: aud {
+				reg = <TEGRA_POWERGATE_AUD>;
+				clocks = <&tegra_car TEGRA210_CLK_APE>,
+					 <&tegra_car TEGRA210_CLK_APB2APE>;
+				resets = <&tegra_car 198>;
+				#power-domain-cells = <0>;
+			};
+		};
+	};

Should we not spell out the list of supported power domains per SoC here? The example gives only one, but we have a bunch of others. If they can be referred to by phandle I'd expect there to be a list of them. I'm not sure if this was discussed earlier, but does it perhaps make sense to tie names to IDs, such that we don't need the reg property? That'd be analogous to how PMICs define regulators.

The reason why I'm asking is that in the above example it's possible to have this:

			pd_audio: pcie {
				reg = <TEGRA_POWERGATE_SOR>;
				...
			};

And there'd be no way to sanity check other than by human inspection. Perhaps I'm being overly paranoid and we can easily filter these out during code review.

I suppose that if Rob's fine with it, I can be too.

Thierry

maintainer
#30 lore raw

Re: [PATCH V6 05/10] Documentation: DT: bindings: Add power domain info for NVIDIA PMC

Quoted 79 lines · Thierry Reding

* PGP Signed by an unknown key

Quoted 76 lines · Jon Hunter

Add power-domain binding documentation for the NVIDIA PMC driver in order to support generic power-domains.

---
 .../bindings/arm/tegra/nvidia,tegra20-pmc.txt      | 61 ++++++++++++++++++++++
 1 file changed, 61 insertions(+)
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +46 -0
index 53aa5496c5cf..0c383a9e720e 100644
@@ -1,5 +1,7 @@
 NVIDIA Tegra Power Management Controller (PMC)
 
+== Power Management Controller Node ==
+
 The PMC block interacts with an external Power Management Unit. The PMC
 mostly controls the entry and exit of the system from different sleep
 modes. It provides power-gating controllers for SoC and CPU power-islands.
@@ -70,6 +72,11 @@ Optional properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'
                      Defaults to 0. Valid values are described in section 12.5.2
                      "Pinmux Support" of the Tegra4 Technical Reference Manual.
 
+Optional nodes:
+- powergates : This node contains a hierarchy of power domain nodes, which
+	       should match the powergates on the Tegra SoC. See "Powergate
+	       Nodes" below.
+
 Example:
 
 / SoC dts including file
@@ -115,3 +122,57 @@ pmc@7000f400 {
 	};
...
 };
+
+
+== Powergate Nodes ==
+
+Each of the powergate nodes represents a power-domain on the Tegra SoC
+that can be power-gated by the PMC and should be named appropriately.
+
+Required properties:
+  - reg: Contains an integer value that identifies the PMC power-gate.
+    Please refer to the Tegra TRM for more details. The parent node
+    must contain the following two properties:
+    - #address-cells: Must be 1,
+    - #size-cells: Must be 0.
+  - clocks: Must contain an entry for each clock required by the PMC for
+    controlling a power-gate. See ../clocks/clock-bindings.txt for details.
+  - resets: Must contain an entry for each reset required by the PMC for
+    controlling a power-gate. See ../reset/reset.txt for details.
+  - #power-domain-cells: Must be 0.
+
+Example:
+
+	pmc: pmc@0,7000e400 {
+		compatible = "nvidia,tegra210-pmc";
+		reg = <0x0 0x7000e400 0x0 0x400>;
+		clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
+		clock-names = "pclk", "clk32k_in";
+
+		powergates {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			pd_audio: aud {
+				reg = <TEGRA_POWERGATE_AUD>;
+				clocks = <&tegra_car TEGRA210_CLK_APE>,
+					 <&tegra_car TEGRA210_CLK_APB2APE>;
+				resets = <&tegra_car 198>;
+				#power-domain-cells = <0>;
+			};
+		};
Quoted 8 lines

Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt

Quoted 1 line
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +1 -0
+	};

Should we not spell out the list of supported power domains per SoC here? The example gives only one, but we have a bunch of others. If they can be referred to by phandle I'd expect there to be a list of them. I'm not sure if this was discussed earlier, but does it perhaps make sense to tie names to IDs, such that we don't need the reg property? That'd be analogous to how PMICs define regulators.

So the supported power-domains per SoC are described in the header "include/dt-bindings/power/tegra-powergate.h" (see patch #8). Perhaps, I can move patch #8 to before this patch and add a reference to the header file for a list of supported power-domains. However ...

Quoted 7 lines

The reason why I'm asking is that in the above example it's possible to have this:

			pd_audio: pcie {
				reg = <TEGRA_POWERGATE_SOR>;
				...
			};

... if we eliminate the "reg" property and just use the name, then yes it would make sense to move the list of support power-domains into the binding doc.

It all depends on whether we want to define the IDs in the binding or in the PMC driver. Right now we have a static list of power-domains in the PMC driver per SoC and I had thought that in the long term we would be able to get rid of these and just rely on the binding. But ...

Quoted 3 lines

And there'd be no way to sanity check other than by human inspection. Perhaps I'm being overly paranoid and we can easily filter these out during code review.

... that would mean that we have to rely on the binding being correct
and inspect manually. On the other hand, if we don't have the IDs in the binding we still need to inspect the static arrays in the PMC driver and so far I have found a few errors with these. So does it really change/improve anything?

Cheers
Jon

A message that is not in the archive (sent off-list or not yet received): [email protected]

#32 lore raw

Re: [PATCH V6 05/10] Documentation: DT: bindings: Add power domain info for NVIDIA PMC

Quoted 116 lines · Jon Hunter
Quoted 79 lines · Thierry Reding

* PGP Signed by an unknown key

Quoted 76 lines · Jon Hunter

Add power-domain binding documentation for the NVIDIA PMC driver in order to support generic power-domains.

---
 .../bindings/arm/tegra/nvidia,tegra20-pmc.txt      | 61 ++++++++++++++++++++++
 1 file changed, 61 insertions(+)
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +46 -0
index 53aa5496c5cf..0c383a9e720e 100644
@@ -1,5 +1,7 @@
 NVIDIA Tegra Power Management Controller (PMC)
 
+== Power Management Controller Node ==
+
 The PMC block interacts with an external Power Management Unit. The PMC
 mostly controls the entry and exit of the system from different sleep
 modes. It provides power-gating controllers for SoC and CPU power-islands.
@@ -70,6 +72,11 @@ Optional properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'
                      Defaults to 0. Valid values are described in section 12.5.2
                      "Pinmux Support" of the Tegra4 Technical Reference Manual.
 
+Optional nodes:
+- powergates : This node contains a hierarchy of power domain nodes, which
+	       should match the powergates on the Tegra SoC. See "Powergate
+	       Nodes" below.
+
 Example:
 
 / SoC dts including file
@@ -115,3 +122,57 @@ pmc@7000f400 {
 	};
...
 };
+
+
+== Powergate Nodes ==
+
+Each of the powergate nodes represents a power-domain on the Tegra SoC
+that can be power-gated by the PMC and should be named appropriately.
+
+Required properties:
+  - reg: Contains an integer value that identifies the PMC power-gate.
+    Please refer to the Tegra TRM for more details. The parent node
+    must contain the following two properties:
+    - #address-cells: Must be 1,
+    - #size-cells: Must be 0.
+  - clocks: Must contain an entry for each clock required by the PMC for
+    controlling a power-gate. See ../clocks/clock-bindings.txt for details.
+  - resets: Must contain an entry for each reset required by the PMC for
+    controlling a power-gate. See ../reset/reset.txt for details.
+  - #power-domain-cells: Must be 0.
+
+Example:
+
+	pmc: pmc@0,7000e400 {
+		compatible = "nvidia,tegra210-pmc";
+		reg = <0x0 0x7000e400 0x0 0x400>;
+		clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
+		clock-names = "pclk", "clk32k_in";
+
+		powergates {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			pd_audio: aud {
+				reg = <TEGRA_POWERGATE_AUD>;
+				clocks = <&tegra_car TEGRA210_CLK_APE>,
+					 <&tegra_car TEGRA210_CLK_APB2APE>;
+				resets = <&tegra_car 198>;
+				#power-domain-cells = <0>;
+			};
+		};
Quoted 8 lines

Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt

Quoted 1 line
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +1 -0
+	};

Should we not spell out the list of supported power domains per SoC here? The example gives only one, but we have a bunch of others. If they can be referred to by phandle I'd expect there to be a list of them. I'm not sure if this was discussed earlier, but does it perhaps make sense to tie names to IDs, such that we don't need the reg property? That'd be analogous to how PMICs define regulators.

So the supported power-domains per SoC are described in the header "include/dt-bindings/power/tegra-powergate.h" (see patch #8). Perhaps, I can move patch #8 to before this patch and add a reference to the header file for a list of supported power-domains. However ...

Quoted 7 lines

The reason why I'm asking is that in the above example it's possible to have this:

			pd_audio: pcie {
				reg = <TEGRA_POWERGATE_SOR>;
				...
			};

... if we eliminate the "reg" property and just use the name, then yes it would make sense to move the list of support power-domains into the binding doc.

It all depends on whether we want to define the IDs in the binding or in the PMC driver. Right now we have a static list of power-domains in the PMC driver per SoC and I had thought that in the long term we would be able to get rid of these and just rely on the binding. But ...

Quoted 3 lines

And there'd be no way to sanity check other than by human inspection. Perhaps I'm being overly paranoid and we can easily filter these out during code review.

Quoted 5 lines

... that would mean that we have to rely on the binding being correct
and inspect manually. On the other hand, if we don't have the IDs in the binding we still need to inspect the static arrays in the PMC driver and so far I have found a few errors with these. So does it really change/improve anything?

I've always considered per-SoC invariant data to not belong into bindings. That is, constants such as power partition IDs or SMMU client IDs should be defined via tables in drivers, and DT should be used to hook them up to devices.

Defining the existing power domains in DT seems rather brittle to me. A compatible string would imply the set of supported power domains anyway and having that set specified in DT would technically require us to add code in the driver to validate that the DT is sane, which would entail the addition of a very similar table anyway.

One further reason why I prefer not to have these things specified (as opposed to "glued" together) in DT is that the DT is ABI, so if we ever happen to ship a broken DT we won't be able to easily fix it. Driver code, on the other hand, can always easily be fixed.

Thierry

author
#33 lore raw

Re: [PATCH V6 05/10] Documentation: DT: bindings: Add power domain info for NVIDIA PMC

On 29/02/16 11:01, Thierry Reding wrote:

[snip]

Quoted 11 lines

I've always considered per-SoC invariant data to not belong into bindings. That is, constants such as power partition IDs or SMMU client IDs should be defined via tables in drivers, and DT should be used to hook them up to devices.

Defining the existing power domains in DT seems rather brittle to me. A compatible string would imply the set of supported power domains anyway and having that set specified in DT would technically require us to add code in the driver to validate that the DT is sane, which would entail the addition of a very similar table anyway.

Quoted 4 lines

One further reason why I prefer not to have these things specified (as opposed to "glued" together) in DT is that the DT is ABI, so if we ever happen to ship a broken DT we won't be able to easily fix it. Driver code, on the other hand, can always easily be fixed.

Yes, I guess that is consistent with other Tegra drivers too. Ok, I will drop the reg property and just use the name.

Cheers
Jon

maintainer
#34 lore raw

PATCH v6 7/10 soc: tegra: pmc: Add generic PM domain support

In reply to Jon Hunter

Adds generic PM support to the PMC driver where the PM domains are populated from device-tree and the PM domain consumer devices are bound to their relevant PM domains via device-tree as well.

Update the tegra_powergate_sequence_power_up() API so that internally it calls the same tegra_powergate_xxx functions that are used by the tegra generic power domain code for consistency.

To ensure that the Tegra power domains (a.k.a powergates) cannot be controlled via both the legacy tegra_powergate_xxx functions as well as the generic PM domain framework, add a bit map for available powergates that can be controlled via the legacy powergate functions.

Move the majority of the tegra_powergate_remove_clamping() function to a sub-function, so that this can be used by both the legacy and generic power domain code.

This is based upon work by Thierry Reding <[email protected]> and Vince Hsu <[email protected]>.

---
 drivers/soc/tegra/pmc.c | 585 ++++++++++++++++++++++++++++++++++++++++++------
 include/soc/tegra/pmc.h |   1 +
 2 files changed, 522 insertions(+), 64 deletions(-)
drivers/soc/tegra/pmc.c +521 -64
index 08966c26d65c..9d2d204342c5 100644
@@ -31,10 +31,13 @@
 #include <linux/iopoll.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/pm_domain.h>
 #include <linux/reboot.h>
 #include <linux/reset.h>
 #include <linux/seq_file.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 
 #include <soc/tegra/common.h>
@@ -102,6 +105,18 @@
 
 #define GPU_RG_CNTRL			0x2d4
 
+struct tegra_powergate {
+	struct generic_pm_domain genpd;
+	struct generic_pm_domain *parent;
+	struct tegra_pmc *pmc;
+	unsigned int id;
+	struct device_node *of_node;
+	struct clk **clks;
+	unsigned int num_clks;
+	struct reset_control **resets;
+	unsigned int num_resets;
+};
+
 struct tegra_pmc_soc {
 	unsigned int num_powergates;
 	const char *const *powergates;
@@ -132,6 +147,7 @@ struct tegra_pmc_soc {
  * @cpu_pwr_good_en: CPU power good signal is enabled
  * @lp0_vec_phys: physical base address of the LP0 warm boot code
  * @lp0_vec_size: size of the LP0 warm boot code
+ * @powergates_available: Bitmap of available power gates
  * @powergates_lock: mutex for power gate register access
  */
 struct tegra_pmc {
@@ -156,6 +172,7 @@ struct tegra_pmc {
 	bool cpu_pwr_good_en;
 	u32 lp0_vec_phys;
 	u32 lp0_vec_size;
+	DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX);
 
 	struct mutex powergates_lock;
 };
@@ -165,6 +182,12 @@ static struct tegra_pmc *pmc = &(struct tegra_pmc) {
 	.suspend_mode = TEGRA_SUSPEND_NONE,
 };
 
+static inline struct tegra_powergate *
+to_powergate(struct generic_pm_domain *domain)
+{
+	return container_of(domain, struct tegra_powergate, genpd);
+}
+
 static u32 tegra_pmc_readl(unsigned long offset)
 {
 	return readl(pmc->base + offset);
@@ -188,6 +211,11 @@ static inline bool tegra_powergate_is_valid(int id)
 	return (pmc->soc && pmc->soc->powergates[id]);
 }
 
+static inline bool tegra_powergate_is_available(int id)
+{
+	return test_bit(id, pmc->powergates_available);
+}
+
 /**
  * tegra_powergate_set() - set the state of a partition
  * @id: partition ID
@@ -218,13 +246,219 @@ static int tegra_powergate_set(unsigned int id, bool new_state)
 	return err;
 }
 
+static int __tegra_powergate_remove_clamping(unsigned int id)
+{
+	u32 mask;
+
+	mutex_lock(&pmc->powergates_lock);
+
+	/*
+	 * On Tegra124 and later, the clamps for the GPU are controlled by a
+	 * separate register (with different semantics).
+	 */
+	if (id == TEGRA_POWERGATE_3D) {
+		if (pmc->soc->has_gpu_clamps) {
+			tegra_pmc_writel(0, GPU_RG_CNTRL);
+			goto out;
+		}
+	}
+
+	/*
+	 * Tegra 2 has a bug where PCIE and VDE clamping masks are
+	 * swapped relatively to the partition ids
+	 */
+	if (id == TEGRA_POWERGATE_VDEC)
+		mask = (1 << TEGRA_POWERGATE_PCIE);
+	else if (id == TEGRA_POWERGATE_PCIE)
+		mask = (1 << TEGRA_POWERGATE_VDEC);
+	else
+		mask = (1 << id);
+
+	tegra_pmc_writel(mask, REMOVE_CLAMPING);
+
+out:
+	mutex_unlock(&pmc->powergates_lock);
+
+	return 0;
+}
+
+static void tegra_powergate_disable_clocks(struct tegra_powergate *pg)
+{
+	unsigned int i;
+
+	for (i = 0; i < pg->num_clks; i++)
+		clk_disable_unprepare(pg->clks[i]);
+}
+
+static int tegra_powergate_enable_clocks(struct tegra_powergate *pg)
+{
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < pg->num_clks; i++) {
+		err = clk_prepare_enable(pg->clks[i]);
+		if (err)
+			goto out;
+	}
+
+	return 0;
+
+out:
+	while (i--)
+		clk_disable_unprepare(pg->clks[i]);
+
+	return err;
+}
+
+static int tegra_powergate_reset_assert(struct tegra_powergate *pg)
+{
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < pg->num_resets; i++) {
+		err = reset_control_assert(pg->resets[i]);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int tegra_powergate_reset_deassert(struct tegra_powergate *pg)
+{
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < pg->num_resets; i++) {
+		err = reset_control_deassert(pg->resets[i]);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int tegra_powergate_power_up(struct tegra_powergate *pg,
+				    bool disable_clocks)
+{
+	int err;
+
+	err = tegra_powergate_reset_assert(pg);
+	if (err)
+		return err;
+
+	usleep_range(10, 20);
+
+	err = tegra_powergate_set(pg->id, true);
+	if (err < 0)
+		return err;
+
+	usleep_range(10, 20);
+
+	err = tegra_powergate_enable_clocks(pg);
+	if (err)
+		goto disable_clks;
+
+	usleep_range(10, 20);
+
+	err = __tegra_powergate_remove_clamping(pg->id);
+	if (err)
+		goto disable_clks;
+
+	usleep_range(10, 20);
+
+	err = tegra_powergate_reset_deassert(pg);
+	if (err)
+		goto powergate_off;
+
+	usleep_range(10, 20);
+
+	if (disable_clocks)
+		tegra_powergate_disable_clocks(pg);
+
+	return 0;
+
+disable_clks:
+	tegra_powergate_disable_clocks(pg);
+	usleep_range(10, 20);
+powergate_off:
+	tegra_powergate_set(pg->id, false);
+
+	return err;
+}
+
+static int tegra_powergate_power_down(struct tegra_powergate *pg)
+{
+	int err;
+
+	err = tegra_powergate_enable_clocks(pg);
+	if (err)
+		return err;
+
+	usleep_range(10, 20);
+
+	err = tegra_powergate_reset_assert(pg);
+	if (err)
+		goto disable_clks;
+
+	usleep_range(10, 20);
+
+	tegra_powergate_disable_clocks(pg);
+
+	usleep_range(10, 20);
+
+	err = tegra_powergate_set(pg->id, false);
+	if (err)
+		goto assert_resets;
+
+	return 0;
+
+assert_resets:
+	tegra_powergate_enable_clocks(pg);
+	usleep_range(10, 20);
+	tegra_powergate_reset_deassert(pg);
+	usleep_range(10, 20);
+disable_clks:
+	tegra_powergate_disable_clocks(pg);
+
+	return err;
+}
+
+static int tegra_genpd_power_on(struct generic_pm_domain *domain)
+{
+	struct tegra_powergate *pg = to_powergate(domain);
+	struct tegra_pmc *pmc = pg->pmc;
+	int err;
+
+	err = tegra_powergate_power_up(pg, true);
+	if (err)
+		dev_err(pmc->dev, "failed to turn on PM domain %s: %d\n",
+			pg->of_node->name, err);
+
+	return err;
+}
+
+static int tegra_genpd_power_off(struct generic_pm_domain *domain)
+{
+	struct tegra_powergate *pg = to_powergate(domain);
+	struct tegra_pmc *pmc = pg->pmc;
+	int err;
+
+	err = tegra_powergate_power_down(pg);
+	if (err)
+		dev_err(pmc->dev, "failed to turn off PM domain %s: %d\n",
+			pg->of_node->name, err);
+
+	return err;
+}
+
 /**
  * tegra_powergate_power_on() - power on partition
  * @id: partition ID
  */
 int tegra_powergate_power_on(unsigned int id)
 {
-	if (!tegra_powergate_is_valid(id))
+	if (!tegra_powergate_is_available(id))
 		return -EINVAL;
 
 	return tegra_powergate_set(id, true);
@@ -236,7 +470,7 @@ int tegra_powergate_power_on(unsigned int id)
  */
 int tegra_powergate_power_off(unsigned int id)
 {
-	if (!tegra_powergate_is_valid(id))
+	if (!tegra_powergate_is_available(id))
 		return -EINVAL;
 
 	return tegra_powergate_set(id, false);
@@ -267,41 +501,10 @@ int tegra_powergate_is_powered(unsigned int id)
  */
 int tegra_powergate_remove_clamping(unsigned int id)
 {
-	u32 mask;
-
-	if (!tegra_powergate_is_valid(id))
+	if (!tegra_powergate_is_available(id))
 		return -EINVAL;
 
-	mutex_lock(&pmc->powergates_lock);
-
-	/*
-	 * On Tegra124 and later, the clamps for the GPU are controlled by a
-	 * separate register (with different semantics).
-	 */
-	if (id == TEGRA_POWERGATE_3D) {
-		if (pmc->soc->has_gpu_clamps) {
-			tegra_pmc_writel(0, GPU_RG_CNTRL);
-			goto out;
-		}
-	}
-
-	/*
-	 * Tegra 2 has a bug where PCIE and VDE clamping masks are
-	 * swapped relatively to the partition ids
-	 */
-	if (id == TEGRA_POWERGATE_VDEC)
-		mask = (1 << TEGRA_POWERGATE_PCIE);
-	else if (id == TEGRA_POWERGATE_PCIE)
-		mask = (1 << TEGRA_POWERGATE_VDEC);
-	else
-		mask = (1 << id);
-
-	tegra_pmc_writel(mask, REMOVE_CLAMPING);
-
-out:
-	mutex_unlock(&pmc->powergates_lock);
-
-	return 0;
+	return __tegra_powergate_remove_clamping(id);
 }
 EXPORT_SYMBOL(tegra_powergate_remove_clamping);
 
@@ -316,35 +519,20 @@ EXPORT_SYMBOL(tegra_powergate_remove_clamping);
 int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
 				      struct reset_control *rst)
 {
-	int ret;
-
-	reset_control_assert(rst);
-
-	ret = tegra_powergate_power_on(id);
-	if (ret)
-		goto err_power;
-
-	ret = clk_prepare_enable(clk);
-	if (ret)
-		goto err_clk;
-
-	usleep_range(10, 20);
-
-	ret = tegra_powergate_remove_clamping(id);
-	if (ret)
-		goto err_clamp;
+	struct tegra_powergate pg;
+	int err;
 
-	usleep_range(10, 20);
-	reset_control_deassert(rst);
+	pg.id = id;
+	pg.clks = &clk;
+	pg.num_clks = 1;
+	pg.resets = &rst;
+	pg.num_resets = 1;
 
-	return 0;
+	err = tegra_powergate_power_up(&pg, false);
+	if (err)
+		pr_err("failed to turn on partition %d: %d\n", id, err);
 
-err_clamp:
-	clk_disable_unprepare(clk);
-err_clk:
-	tegra_powergate_power_off(id);
-err_power:
-	return ret;
+	return err;
 }
 EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
 
@@ -486,6 +674,259 @@ static int tegra_powergate_debugfs_init(void)
 	return 0;
 }
 
+static int tegra_powergate_of_get_clks(struct device *dev,
+				       struct tegra_powergate *pg)
+{
+	struct clk *clk;
+	unsigned int i, count;
+	int err;
+
+	count = of_count_phandle_with_args(pg->of_node, "clocks",
+					   "#clock-cells");
+	if (count == 0)
+		return -ENODEV;
+
+	pg->clks = devm_kcalloc(dev, count, sizeof(clk), GFP_KERNEL);
+	if (!pg->clks)
+		return -ENOMEM;
+
+	for (i = 0; i < count; i++) {
+		pg->clks[i] = of_clk_get(pg->of_node, i);
+		if (IS_ERR(pg->clks[i])) {
+			err = PTR_ERR(pg->clks[i]);
+			goto err;
+		}
+	}
+
+	pg->num_clks = count;
+
+	return 0;
+
+err:
+	while (i--)
+		clk_put(pg->clks[i]);
+
+	return err;
+}
+
+static int tegra_powergate_of_get_resets(struct device *dev,
+					 struct tegra_powergate *pg)
+{
+	struct reset_control *rst;
+	unsigned int i, count;
+	int err;
+
+	count = of_count_phandle_with_args(pg->of_node, "resets",
+					   "#reset-cells");
+	if (count == 0)
+		return -ENODEV;
+
+	pg->resets = devm_kcalloc(dev, count, sizeof(rst), GFP_KERNEL);
+	if (!pg->resets)
+		return -ENOMEM;
+
+	for (i = 0; i < count; i++) {
+		pg->resets[i] = of_reset_control_get_by_index(pg->of_node, i);
+		if (IS_ERR(pg->resets[i])) {
+			err = PTR_ERR(pg->resets[i]);
+			goto error;
+		}
+	}
+
+	pg->num_resets = count;
+
+	return 0;
+
+error:
+	while (i--)
+		reset_control_put(pg->resets[i]);
+
+	return err;
+}
+
+static struct tegra_powergate *
+tegra_powergate_add_one(struct tegra_pmc *pmc, struct device_node *np,
+			struct generic_pm_domain *parent)
+{
+	struct tegra_powergate *pg;
+	const __be32 *reg;
+	unsigned int id;
+	bool off;
+	int err;
+
+	/*
+	 * If the powergate ID is missing or invalid then return NULL
+	 * to skip this one and allow any others to be created.
+	 */
+	reg = of_get_property(np, "reg", NULL);
+	if (!reg) {
+		dev_WARN(pmc->dev, "reg node missing for %s\n", np->name);
+		return NULL;
+	}
+
+	id = be32_to_cpup(reg);
+
+	if (!tegra_powergate_is_available(id)) {
+		dev_WARN(pmc->dev, "%s powergate is not available\n", np->name);
+		return NULL;
+	}
+
+	/*
+	 * Clear the bit for this powergate so it cannot be managed
+	 * directly via the legacy APIs for controlling powergates.
+	 */
+	clear_bit(id, pmc->powergates_available);
+
+	pg = kzalloc(sizeof(*pg), GFP_KERNEL);
+	if (!pg) {
+		err = -ENOMEM;
+		goto set_available;
+	}
+
+	pg->id = id;
+	pg->of_node = np;
+	pg->parent = parent;
+	pg->genpd.owner = pmc->dev;
+	pg->genpd.name = np->name;
+	pg->genpd.power_off = tegra_genpd_power_off;
+	pg->genpd.power_on = tegra_genpd_power_on;
+	pg->pmc = pmc;
+
+	err = tegra_powergate_of_get_clks(pmc->dev, pg);
+	if (err)
+		goto free_mem;
+
+	err = tegra_powergate_of_get_resets(pmc->dev, pg);
+	if (err)
+		goto remove_clks;
+
+	off = !tegra_powergate_is_powered(pg->id);
+
+	pm_genpd_init(&pg->genpd, NULL, off);
+
+	if (pg->parent) {
+		err = pm_genpd_add_subdomain(pg->parent, &pg->genpd);
+		if (err)
+			goto remove_domain_and_resets;
+	}
+
+	err = of_genpd_add_provider_simple(pg->of_node, &pg->genpd);
+	if (err)
+		goto remove_subdomain;
+
+	dev_dbg(pmc->dev, "added power domain %s\n", pg->genpd.name);
+
+	return pg;
+
+remove_subdomain:
+	if (pg->parent)
+		if (WARN_ON(pm_genpd_remove_subdomain(pg->parent, &pg->genpd)))
+			goto error;
+
+remove_domain_and_resets:
+	if (WARN_ON(pm_genpd_remove(&pg->genpd)))
+		goto error;
+
+	while (pg->num_resets--)
+		reset_control_put(pg->resets[pg->num_resets]);
+
+remove_clks:
+	while (pg->num_clks--)
+		clk_put(pg->clks[pg->num_clks]);
+
+free_mem:
+	kfree(pg);
+
+set_available:
+	set_bit(id, pmc->powergates_available);
+
+error:
+	dev_err(pmc->dev, "failed to create power domain for node %s\n",
+		np->name);
+
+	return ERR_PTR(err);
+}
+
+static int tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np,
+			       struct generic_pm_domain *parent)
+{
+	struct tegra_powergate *pg;
+	struct device_node *child;
+	int err = 0;
+
+	for_each_child_of_node(np, child) {
+		pg = tegra_powergate_add_one(pmc, child, parent);
+		if (IS_ERR(pg)) {
+			err = PTR_ERR(pg);
+			goto error;
+		}
+
+		if (pg)
+			err = tegra_powergate_add(pmc, child, &pg->genpd);
+
+error:
+		of_node_put(child);
+
+		if (err)
+			break;
+	}
+
+	return err;
+}
+
+static void tegra_powergate_remove(struct tegra_pmc *pmc)
+{
+	struct generic_pm_domain *genpd = pm_genpd_list_get_tail(pmc->dev);
+	struct tegra_powergate *pg;
+
+	while (genpd) {
+		pg = to_powergate(genpd);
+
+		of_genpd_del_provider(pg->of_node);
+
+		if (pg->parent) {
+			if (WARN_ON(pm_genpd_remove_subdomain(pg->parent,
+							      &pg->genpd)))
+				return;
+
+			pg->parent = NULL;
+		}
+
+		if (WARN_ON(pm_genpd_remove(&pg->genpd)))
+			return;
+
+		while (pg->num_clks--)
+			clk_put(pg->clks[pg->num_clks]);
+
+		while (pg->num_resets--)
+			reset_control_put(pg->resets[pg->num_resets]);
+
+		kfree(pg);
+
+		set_bit(pg->id, pmc->powergates_available);
+
+		genpd = pm_genpd_list_get_tail(pmc->dev);
+	}
+}
+
+static int tegra_powergate_init(struct tegra_pmc *pmc)
+{
+	struct device_node *np;
+	int err;
+
+	np = of_get_child_by_name(pmc->dev->of_node, "powergates");
+	if (!np)
+		return 0;
+
+	err = tegra_powergate_add(pmc, np, NULL);
+	if (err)
+		tegra_powergate_remove(pmc);
+
+	of_node_put(np);
+
+	return err;
+}
+
 static int tegra_io_rail_prepare(unsigned int id, unsigned long *request,
 				 unsigned long *status, unsigned int *bit)
 {
@@ -873,18 +1314,21 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 
 	tegra_pmc_init_tsense_reset(pmc);
 
+	err = tegra_powergate_init(pmc);
+	if (err < 0)
+		return err;
+
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
 		err = tegra_powergate_debugfs_init();
 		if (err < 0)
-			return err;
+			goto remove_powergates;
 	}
 
 	err = register_restart_handler(&tegra_pmc_restart_handler);
 	if (err) {
-		debugfs_remove(pmc->debugfs);
 		dev_err(&pdev->dev, "unable to register restart handler, %d\n",
 			err);
-		return err;
+		goto remove_debugfs;
 	}
 
 	mutex_lock(&pmc->powergates_lock);
@@ -893,6 +1337,13 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 	mutex_unlock(&pmc->powergates_lock);
 
 	return 0;
+
+remove_debugfs:
+	debugfs_remove(pmc->debugfs);
+remove_powergates:
+	tegra_powergate_remove(pmc);
+
+	return err;
 }
 
 #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
@@ -1120,6 +1571,7 @@ static int __init tegra_pmc_early_init(void)
 	const struct of_device_id *match;
 	struct device_node *np;
 	struct resource regs;
+	unsigned int i;
 	bool invert;
 	u32 value;
 
@@ -1169,6 +1621,11 @@ static int __init tegra_pmc_early_init(void)
 		return -ENXIO;
 	}
 
+	/* Create a bit-map of the available and valid partitions */
+	for (i = 0; i < pmc->soc->num_powergates; i++)
+		if (pmc->soc->powergates[i])
+			set_bit(i, pmc->powergates_available);
+
 	mutex_init(&pmc->powergates_lock);
 
 	/*
include/soc/tegra/pmc.h +1 -0
index 07e332dd44fb..e9e53473a63e 100644
@@ -72,6 +72,7 @@ int tegra_pmc_cpu_remove_clamping(unsigned int cpuid);
 #define TEGRA_POWERGATE_AUD	27
 #define TEGRA_POWERGATE_DFD	28
 #define TEGRA_POWERGATE_VE2	29
+#define TEGRA_POWERGATE_MAX	TEGRA_POWERGATE_VE2
 
 #define TEGRA_POWERGATE_3D0	TEGRA_POWERGATE_3D
 
Signature · 1 line
2.1.4

A message that is not in the archive (sent off-list or not yet received): 1456501724-28477-8-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org

Acked-by
#36 lore raw

Re: [PATCH V6 07/10] soc: tegra: pmc: Add generic PM domain support

Quoted 13 lines · Jon Hunter

Adds generic PM support to the PMC driver where the PM domains are populated from device-tree and the PM domain consumer devices are bound to their relevant PM domains via device-tree as well.

Update the tegra_powergate_sequence_power_up() API so that internally it calls the same tegra_powergate_xxx functions that are used by the tegra generic power domain code for consistency.

To ensure that the Tegra power domains (a.k.a powergates) cannot be controlled via both the legacy tegra_powergate_xxx functions as well as the generic PM domain framework, add a bit map for available powergates that can be controlled via the legacy powergate functions.

Quoted 8 lines

Move the majority of the tegra_powergate_remove_clamping() function to a sub-function, so that this can be used by both the legacy and generic power domain code.

This is based upon work by Thierry Reding <[email protected]> and Vince Hsu <[email protected]>.

I didn't look in great detail at the SoC specifics, but for the for the general genpd approach:

maintainer
#37 lore raw

PATCH v6 10/10 ARM64: tegra: Add audio PM domain device node for Tegra210

In reply to Jon Hunter

Add the audio power-domain for tegra210. Note that this also removes the existing "#power-domain-cells" which was incorrectly included by commit e53095857166 ("arm64: tegra: Add Tegra210 support").

---

So far I have only added the audio power-domain for tegra210 as this is what I have been testing with to date. However, once this series is accepted then we can begin to add more.

 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)
arch/arm64/boot/dts/nvidia/tegra210.dtsi +13 -1
index cd4f45ccd6a7..d2b6bb4eb202 100644
@@ -2,6 +2,7 @@
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/memory/tegra210-mc.h>
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
+#include <dt-bindings/power/tegra-powergate.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 / {
@@ -581,7 +582,18 @@
 		clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
 		clock-names = "pclk", "clk32k_in";
 
-		#power-domain-cells = <1>;
+		powergates {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			pd_audio: aud {
+				reg = <TEGRA_POWERGATE_AUD>;
+				clocks = <&tegra_car TEGRA210_CLK_APE>,
+					 <&tegra_car TEGRA210_CLK_APB2APE>;
+				resets = <&tegra_car 198>;
+				#power-domain-cells = <0>;
+			};
+		};
 	};
 
 	fuse@0,7000f800 {
Signature · 1 line
2.1.4
#38 lore raw

Re: [PATCH V6 10/10] ARM64: tegra: Add audio PM domain device node for Tegra210

Quoted 6 lines · Jon Hunter

Add the audio power-domain for tegra210. Note that this also removes the existing "#power-domain-cells" which was incorrectly included by commit e53095857166 ("arm64: tegra: Add Tegra210 support").

Quoted 8 lines

---

So far I have only added the audio power-domain for tegra210 as this is what I have been testing with to date. However, once this series is accepted then we can begin to add more.

 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

I'm slightly reluctant to apply this, since the domain isn't used anywhere. I'm assuming it will be used by the audio driver that you've been working on, but if that's not going to be merged this cycle, we'd end up with an unused label. Not that that's invalid in any way, but my rule of thumb has been not to introduce labels until they are used.

Therefore I suggest we postpone this to the series that adds audio support.

Thierry

maintainer
#39 lore raw

Re: [PATCH V6 10/10] ARM64: tegra: Add audio PM domain device node for Tegra210

Quoted 18 lines · Thierry Reding

* PGP Signed by an unknown key

Quoted 6 lines · Jon Hunter

Add the audio power-domain for tegra210. Note that this also removes the existing "#power-domain-cells" which was incorrectly included by commit e53095857166 ("arm64: tegra: Add Tegra210 support").

Quoted 8 lines

---

So far I have only added the audio power-domain for tegra210 as this is what I have been testing with to date. However, once this series is accepted then we can begin to add more.

 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)
Quoted 8 lines

I'm slightly reluctant to apply this, since the domain isn't used anywhere. I'm assuming it will be used by the audio driver that you've been working on, but if that's not going to be merged this cycle, we'd end up with an unused label. Not that that's invalid in any way, but my rule of thumb has been not to introduce labels until they are used.

Therefore I suggest we postpone this to the series that adds audio support.

That's fine with me or I can drop the label, until it is used by a device?

Jon

#40 lore raw

Re: [PATCH V6 10/10] ARM64: tegra: Add audio PM domain device node for Tegra210

Quoted 27 lines · Jon Hunter
Quoted 24 lines · Thierry Reding

* PGP Signed by an unknown key

Quoted 6 lines · Jon Hunter

Add the audio power-domain for tegra210. Note that this also removes the existing "#power-domain-cells" which was incorrectly included by commit e53095857166 ("arm64: tegra: Add Tegra210 support").

Quoted 8 lines

---

So far I have only added the audio power-domain for tegra210 as this is what I have been testing with to date. However, once this series is accepted then we can begin to add more.

 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

I'm slightly reluctant to apply this, since the domain isn't used anywhere. I'm assuming it will be used by the audio driver that you've been working on, but if that's not going to be merged this cycle, we'd end up with an unused label. Not that that's invalid in any way, but my rule of thumb has been not to introduce labels until they are used.

Quoted 4 lines
Quoted 2 lines

Therefore I suggest we postpone this to the series that adds audio support.

That's fine with me or I can drop the label, until it is used by a device?

I'd prefer the former, no use in having anything in device tree that we're not using anyway. Unless we need this somehow to automatically turn off the domain at boot, in which case it might make more sense to add all others as well.

Thierry

#41 lore raw
In reply to Jon Hunter
Quoted 40 lines · Jon Hunter

Adds generic PM domain support for Tegra SoCs but this series only enables support for it on Tegra 64-bit devices. There is no reason why this cannot be enable for Tegra 32-bit devices, but to keep the patch series to a minimum only 64-bit devices are enabled so far.

This series has been boot tested on Tegra210 as well as various 32-bit Tegra platforms.

Summary of changes since V5 [2]:
- Split series into 2 series, separating PMC fixes [3] from genpd changes
- This series is based upon fixes series (which is now in -next)
- Added patch to fix removal of genpd subdomain
- Added patch to get last genpd that was added
- Fixed locking in function to remove genpd
- Updated Tegra PMC driver to ensure power-domains cannot be controlled by both legacy Tegra APIs and generic PM domain framework
- Removed powergate list from Tegra PMC driver and updated removal of power domains to use new genpd APIs.

Summary of changes since V4 [1]:
- Re-worked fix to handle base address on probe failure
- Added patch to lock around simultaneuous accesses to PMC registers
- Added patch to change powergate and rail IDs to unsigned type
- Added patch to fix testing of powergate state
- Updated patch to check for valid powergates to use a bitmap
- Updated Tegra DT PMC bindings per Rob H's feedback
- Updated Tegra power domains binding per Thierry's feedback
- Updated Tegra generic power domain support per Thierry's feedback

Summary of changes since V3 [0]:
- Dropped tegra124 support for now
- Removed MC flush support per feedback from Thierry
- Cleaned up the PMC changes per feedback from Thierry
- Added support for tegra210

[0] http://comments.gmane.org/gmane.linux.ports.tegra/22944
[1] http://marc.info/?l=linux-tegra&m=144924153600529&w=2
[2] http://marc.info/?l=linux-tegra&m=145399885003830&w=2
[3] http://marc.info/?l=linux-tegra&m=145521381331144&w=2

Quoted 4 lines

Jon Hunter (10):
PM / Domains: Fix removal of a subdomain
PM / Domains: Add function to get the last domain added PM / Domains: Add function to remove a pm-domain

Ulf, Kevin, Rafael,

It's too late to take these patches through the Tegra tree for v4.6, but if Jon can get the above three patches ready before the merge window, would you be willing to pick them up into your trees for v4.6? Doing so might make it easier to deal with the dependencies. The prerequisites would already be in Linus' tree when I apply the Tegra bits for v4.7.

I don't mind taking all of it through the Tegra tree for v4.7, though. I can provide a stable branch with the PM / Domains patches for you to pull in, in case there are any conflicts.

Thierry

A message that is not in the archive (sent off-list or not yet received): 20160302153556.GB21035-AwZRO8vwLAwmlAP/[email protected]

#43 lore raw
Quoted 8 lines · Thierry Reding
Quoted 7 lines · Jon Hunter

Adds generic PM domain support for Tegra SoCs but this series only enables support for it on Tegra 64-bit devices. There is no reason why this cannot be enable for Tegra 32-bit devices, but to keep the patch series to a minimum only 64-bit devices are enabled so far.

This series has been boot tested on Tegra210 as well as various 32-bit Tegra platforms.

[...]

Quoted 10 lines
Quoted 4 lines

Jon Hunter (10):
PM / Domains: Fix removal of a subdomain
PM / Domains: Add function to get the last domain added PM / Domains: Add function to remove a pm-domain

Ulf, Kevin, Rafael,

It's too late to take these patches through the Tegra tree for v4.6, but if Jon can get the above three patches ready before the merge window, would you be willing to pick them up into your trees for v4.6?

It's a bit late in the cycle, but since one is a fix and the other two add functions that aren't (yet) used, I think it would be fine to get them in for v4.6. But, the final decision is with Rafael.

Quoted 3 lines

Doing so
might make it easier to deal with the dependencies. The prerequisites would already be in Linus' tree when I apply the Tegra bits for v4.7.

Yeah, makes sense.

Quoted 3 lines

I don't mind taking all of it through the Tegra tree for v4.7, though. I can provide a stable branch with the PM / Domains patches for you to pull in, in case there are any conflicts.

I think it makes the most sense for these prereqs to merge through linux-pm. Let's see what Rafael thinks about the timing.

Kevin

A message that is not in the archive (sent off-list or not yet received): 7h7fhk3c4o.fsf-rdvid1DuHRBWk0Htik3J/[email protected]

#45 lore raw
Quoted 32 lines · Kevin Hilman
Quoted 8 lines · Thierry Reding
Quoted 7 lines · Jon Hunter

Adds generic PM domain support for Tegra SoCs but this series only enables support for it on Tegra 64-bit devices. There is no reason why this cannot be enable for Tegra 32-bit devices, but to keep the patch series to a minimum only 64-bit devices are enabled so far.

This series has been boot tested on Tegra210 as well as various 32-bit Tegra platforms.

[...]

Quoted 10 lines
Quoted 4 lines

Jon Hunter (10):
PM / Domains: Fix removal of a subdomain
PM / Domains: Add function to get the last domain added PM / Domains: Add function to remove a pm-domain

Ulf, Kevin, Rafael,

It's too late to take these patches through the Tegra tree for v4.6, but if Jon can get the above three patches ready before the merge window, would you be willing to pick them up into your trees for v4.6?

It's a bit late in the cycle, but since one is a fix and the other two add functions that aren't (yet) used, I think it would be fine to get them in for v4.6. But, the final decision is with Rafael.

Quoted 3 lines

Doing so
might make it easier to deal with the dependencies. The prerequisites would already be in Linus' tree when I apply the Tegra bits for v4.7.

Quoted 8 lines

Yeah, makes sense.

Quoted 3 lines

I don't mind taking all of it through the Tegra tree for v4.7, though. I can provide a stable branch with the PM / Domains patches for you to pull in, in case there are any conflicts.

I think it makes the most sense for these prereqs to merge through linux-pm. Let's see what Rafael thinks about the timing.

The timing is fine by me.

Do you want me to apply [1-3/10] from this series, then?

Thanks,
Rafael

Acked-by
#46 lore raw
Quoted 39 lines · Rafael J. Wysocki
Quoted 38 lines · Kevin Hilman
Quoted 8 lines · Thierry Reding
Quoted 7 lines · Jon Hunter

Adds generic PM domain support for Tegra SoCs but this series only enables support for it on Tegra 64-bit devices. There is no reason why this cannot be enable for Tegra 32-bit devices, but to keep the patch series to a minimum only 64-bit devices are enabled so far.

This series has been boot tested on Tegra210 as well as various 32-bit Tegra platforms.

[...]

Quoted 10 lines
Quoted 4 lines

Jon Hunter (10):
PM / Domains: Fix removal of a subdomain
PM / Domains: Add function to get the last domain added PM / Domains: Add function to remove a pm-domain

Ulf, Kevin, Rafael,

It's too late to take these patches through the Tegra tree for v4.6, but if Jon can get the above three patches ready before the merge window, would you be willing to pick them up into your trees for v4.6?

It's a bit late in the cycle, but since one is a fix and the other two add functions that aren't (yet) used, I think it would be fine to get them in for v4.6. But, the final decision is with Rafael.

Quoted 3 lines

Doing so
might make it easier to deal with the dependencies. The prerequisites would already be in Linus' tree when I apply the Tegra bits for v4.7.

Yeah, makes sense.

Quoted 3 lines

I don't mind taking all of it through the Tegra tree for v4.7, though. I can provide a stable branch with the PM / Domains patches for you to pull in, in case there are any conflicts.

Quoted 6 lines
Quoted 2 lines

I think it makes the most sense for these prereqs to merge through linux-pm. Let's see what Rafael thinks about the timing.

The timing is fine by me.

Do you want me to apply [1-3/10] from this series, then?

Jon has some minor tweaks to do, so he'll respin and then you can take them.

Jon, feel free to add:

For those as well. I thought I responded, but looks like I didn't.

Kevin

A message that is not in the archive (sent off-list or not yet received): 7h7fhkxn1r.fsf-rdvid1DuHRBWk0Htik3J/[email protected]

author
#48 lore raw
Quoted 48 lines · Kevin Hilman
Quoted 39 lines · Rafael J. Wysocki
Quoted 38 lines · Kevin Hilman
Quoted 8 lines · Thierry Reding
Quoted 7 lines · Jon Hunter

Adds generic PM domain support for Tegra SoCs but this series only enables support for it on Tegra 64-bit devices. There is no reason why this cannot be enable for Tegra 32-bit devices, but to keep the patch series to a minimum only 64-bit devices are enabled so far.

This series has been boot tested on Tegra210 as well as various 32-bit Tegra platforms.

[...]

Quoted 10 lines
Quoted 4 lines

Jon Hunter (10):
PM / Domains: Fix removal of a subdomain
PM / Domains: Add function to get the last domain added PM / Domains: Add function to remove a pm-domain

Ulf, Kevin, Rafael,

It's too late to take these patches through the Tegra tree for v4.6, but if Jon can get the above three patches ready before the merge window, would you be willing to pick them up into your trees for v4.6?

It's a bit late in the cycle, but since one is a fix and the other two add functions that aren't (yet) used, I think it would be fine to get them in for v4.6. But, the final decision is with Rafael.

Quoted 3 lines

Doing so
might make it easier to deal with the dependencies. The prerequisites would already be in Linus' tree when I apply the Tegra bits for v4.7.

Yeah, makes sense.

Quoted 3 lines

I don't mind taking all of it through the Tegra tree for v4.7, though. I can provide a stable branch with the PM / Domains patches for you to pull in, in case there are any conflicts.

Quoted 6 lines
Quoted 2 lines

I think it makes the most sense for these prereqs to merge through linux-pm. Let's see what Rafael thinks about the timing.

The timing is fine by me.

Do you want me to apply [1-3/10] from this series, then?

Quoted 8 lines

Jon has some minor tweaks to do, so he'll respin and then you can take them.

Jon, feel free to add:

For those as well. I thought I responded, but looks like I didn't.

I am preparing a V7 that I will send out today/tomorrow (latest). I am going to drop the removal parts for now and send that out separately as an RFC because it is bigger than I have expected.

Cheers
Jon

maintainer
#49 lore raw
Quoted 55 lines · Jon Hunter
Quoted 53 lines · Kevin Hilman
Quoted 39 lines · Rafael J. Wysocki
Quoted 38 lines · Kevin Hilman
Quoted 8 lines · Thierry Reding
Quoted 7 lines · Jon Hunter

Adds generic PM domain support for Tegra SoCs but this series only enables support for it on Tegra 64-bit devices. There is no reason why this cannot be enable for Tegra 32-bit devices, but to keep the patch series to a minimum only 64-bit devices are enabled so far.

This series has been boot tested on Tegra210 as well as various 32-bit Tegra platforms.

[...]

Quoted 10 lines
Quoted 4 lines

Jon Hunter (10):
PM / Domains: Fix removal of a subdomain
PM / Domains: Add function to get the last domain added PM / Domains: Add function to remove a pm-domain

Ulf, Kevin, Rafael,

It's too late to take these patches through the Tegra tree for v4.6, but if Jon can get the above three patches ready before the merge window, would you be willing to pick them up into your trees for v4.6?

It's a bit late in the cycle, but since one is a fix and the other two add functions that aren't (yet) used, I think it would be fine to get them in for v4.6. But, the final decision is with Rafael.

Quoted 3 lines

Doing so
might make it easier to deal with the dependencies. The prerequisites would already be in Linus' tree when I apply the Tegra bits for v4.7.

Yeah, makes sense.

Quoted 3 lines

I don't mind taking all of it through the Tegra tree for v4.7, though. I can provide a stable branch with the PM / Domains patches for you to pull in, in case there are any conflicts.

Quoted 6 lines
Quoted 2 lines

I think it makes the most sense for these prereqs to merge through linux-pm. Let's see what Rafael thinks about the timing.

The timing is fine by me.

Do you want me to apply [1-3/10] from this series, then?

Jon has some minor tweaks to do, so he'll respin and then you can take them.

Jon, feel free to add:

Quoted 7 lines
Quoted 3 lines

For those as well. I thought I responded, but looks like I didn't.

I am preparing a V7 that I will send out today/tomorrow (latest). I am going to drop the removal parts for now and send that out separately as an RFC because it is bigger than I have expected.

Rafael,

By the way, I posted the genpd fixes separately here [0][1].

Cheers
Jon

[0] http://marc.info/?l=linux-pm&m=145708892606515&w=2
[1] http://marc.info/?l=linux-pm&m=145708892606516&w=2