brintos

brintos / linux-shallow public Read only

0
0
Text · 2.5 KiB · edaa243 Raw
116 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * MMP PMU power island support4 *5 * Copyright (C) 2020 Lubomir Rintel <lkundrak@v3.sk>6 */7 8#include <linux/pm_domain.h>9#include <linux/slab.h>10#include <linux/io.h>11 12#include "clk.h"13 14#define to_mmp_pm_domain(genpd) container_of(genpd, struct mmp_pm_domain, genpd)15 16struct mmp_pm_domain {17	struct generic_pm_domain genpd;18	void __iomem *reg;19	spinlock_t *lock;20	u32 power_on;21	u32 reset;22	u32 clock_enable;23	unsigned int flags;24};25 26static int mmp_pm_domain_power_on(struct generic_pm_domain *genpd)27{28	struct mmp_pm_domain *pm_domain = to_mmp_pm_domain(genpd);29	unsigned long flags = 0;30	u32 val;31 32	if (pm_domain->lock)33		spin_lock_irqsave(pm_domain->lock, flags);34 35	val = readl(pm_domain->reg);36 37	/* Turn on the power island */38	val |= pm_domain->power_on;39	writel(val, pm_domain->reg);40 41	/* Disable isolation */42	val |= 0x100;43	writel(val, pm_domain->reg);44 45	/* Some blocks need to be reset after a power up */46	if (pm_domain->reset || pm_domain->clock_enable) {47		u32 after_power_on = val;48 49		val &= ~pm_domain->reset;50		writel(val, pm_domain->reg);51 52		val |= pm_domain->clock_enable;53		writel(val, pm_domain->reg);54 55		val |= pm_domain->reset;56		writel(val, pm_domain->reg);57 58		writel(after_power_on, pm_domain->reg);59	}60 61	if (pm_domain->lock)62		spin_unlock_irqrestore(pm_domain->lock, flags);63 64	return 0;65}66 67static int mmp_pm_domain_power_off(struct generic_pm_domain *genpd)68{69	struct mmp_pm_domain *pm_domain = to_mmp_pm_domain(genpd);70	unsigned long flags = 0;71	u32 val;72 73	if (pm_domain->flags & MMP_PM_DOMAIN_NO_DISABLE)74		return 0;75 76	if (pm_domain->lock)77		spin_lock_irqsave(pm_domain->lock, flags);78 79	/* Turn off and isolate the power island. */80	val = readl(pm_domain->reg);81	val &= ~pm_domain->power_on;82	val &= ~0x100;83	writel(val, pm_domain->reg);84 85	if (pm_domain->lock)86		spin_unlock_irqrestore(pm_domain->lock, flags);87 88	return 0;89}90 91struct generic_pm_domain *mmp_pm_domain_register(const char *name,92		void __iomem *reg,93		u32 power_on, u32 reset, u32 clock_enable,94		unsigned int flags, spinlock_t *lock)95{96	struct mmp_pm_domain *pm_domain;97 98	pm_domain = kzalloc(sizeof(*pm_domain), GFP_KERNEL);99	if (!pm_domain)100		return ERR_PTR(-ENOMEM);101 102	pm_domain->reg = reg;103	pm_domain->power_on = power_on;104	pm_domain->reset = reset;105	pm_domain->clock_enable = clock_enable;106	pm_domain->flags = flags;107	pm_domain->lock = lock;108 109	pm_genpd_init(&pm_domain->genpd, NULL, true);110	pm_domain->genpd.name = name;111	pm_domain->genpd.power_on = mmp_pm_domain_power_on;112	pm_domain->genpd.power_off = mmp_pm_domain_power_off;113 114	return &pm_domain->genpd;115}116