-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
clk: mmp2: Add support for power islands
Apart from the clocks and resets, the PMU hardware also controls power to peripherals that are on separate power islands. On MMP2, that's the GC860 GPU and the SSPA audio interface, while on MMP3 also the camera interface is on a separate island, along with the pair of GC2000 and GC300 GPUs and the SSPA. Signed-off-by: Lubomir Rintel <lkundrak@v3.sk> Link: https://lkml.kernel.org/r/20200519224151.2074597-12-lkundrak@v3.sk Signed-off-by: Stephen Boyd <sboyd@kernel.org>
- Loading branch information
Lubomir Rintel
authored and
Stephen Boyd
committed
May 28, 2020
1 parent
17d4304
commit ee4df23
Showing
5 changed files
with
170 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
/* | ||
* MMP PMU power island support | ||
* | ||
* Copyright (C) 2020 Lubomir Rintel <lkundrak@v3.sk> | ||
*/ | ||
|
||
#include <linux/pm_domain.h> | ||
#include <linux/slab.h> | ||
#include <linux/io.h> | ||
|
||
#include "clk.h" | ||
|
||
#define to_mmp_pm_domain(genpd) container_of(genpd, struct mmp_pm_domain, genpd) | ||
|
||
struct mmp_pm_domain { | ||
struct generic_pm_domain genpd; | ||
void __iomem *reg; | ||
spinlock_t *lock; | ||
u32 power_on; | ||
u32 reset; | ||
u32 clock_enable; | ||
unsigned int flags; | ||
}; | ||
|
||
static int mmp_pm_domain_power_on(struct generic_pm_domain *genpd) | ||
{ | ||
struct mmp_pm_domain *pm_domain = to_mmp_pm_domain(genpd); | ||
unsigned long flags = 0; | ||
u32 val; | ||
|
||
if (pm_domain->lock) | ||
spin_lock_irqsave(pm_domain->lock, flags); | ||
|
||
val = readl(pm_domain->reg); | ||
|
||
/* Turn on the power island */ | ||
val |= pm_domain->power_on; | ||
writel(val, pm_domain->reg); | ||
|
||
/* Disable isolation */ | ||
val |= 0x100; | ||
writel(val, pm_domain->reg); | ||
|
||
/* Some blocks need to be reset after a power up */ | ||
if (pm_domain->reset || pm_domain->clock_enable) { | ||
u32 after_power_on = val; | ||
|
||
val &= ~pm_domain->reset; | ||
writel(val, pm_domain->reg); | ||
|
||
val |= pm_domain->clock_enable; | ||
writel(val, pm_domain->reg); | ||
|
||
val |= pm_domain->reset; | ||
writel(val, pm_domain->reg); | ||
|
||
writel(after_power_on, pm_domain->reg); | ||
} | ||
|
||
if (pm_domain->lock) | ||
spin_unlock_irqrestore(pm_domain->lock, flags); | ||
|
||
return 0; | ||
} | ||
|
||
static int mmp_pm_domain_power_off(struct generic_pm_domain *genpd) | ||
{ | ||
struct mmp_pm_domain *pm_domain = to_mmp_pm_domain(genpd); | ||
unsigned long flags = 0; | ||
u32 val; | ||
|
||
if (pm_domain->flags & MMP_PM_DOMAIN_NO_DISABLE) | ||
return 0; | ||
|
||
if (pm_domain->lock) | ||
spin_lock_irqsave(pm_domain->lock, flags); | ||
|
||
/* Turn off and isolate the the power island. */ | ||
val = readl(pm_domain->reg); | ||
val &= ~pm_domain->power_on; | ||
val &= ~0x100; | ||
writel(val, pm_domain->reg); | ||
|
||
if (pm_domain->lock) | ||
spin_unlock_irqrestore(pm_domain->lock, flags); | ||
|
||
return 0; | ||
} | ||
|
||
struct generic_pm_domain *mmp_pm_domain_register(const char *name, | ||
void __iomem *reg, | ||
u32 power_on, u32 reset, u32 clock_enable, | ||
unsigned int flags, spinlock_t *lock) | ||
{ | ||
struct mmp_pm_domain *pm_domain; | ||
|
||
pm_domain = kzalloc(sizeof(*pm_domain), GFP_KERNEL); | ||
if (!pm_domain) | ||
return ERR_PTR(-ENOMEM); | ||
|
||
pm_domain->reg = reg; | ||
pm_domain->power_on = power_on; | ||
pm_domain->reset = reset; | ||
pm_domain->clock_enable = clock_enable; | ||
pm_domain->flags = flags; | ||
pm_domain->lock = lock; | ||
|
||
pm_genpd_init(&pm_domain->genpd, NULL, true); | ||
pm_domain->genpd.name = name; | ||
pm_domain->genpd.power_on = mmp_pm_domain_power_on; | ||
pm_domain->genpd.power_off = mmp_pm_domain_power_off; | ||
|
||
return &pm_domain->genpd; | ||
} |