Skip to content

Commit

Permalink
soc: zte: pm_domains: Prepare for supporting ARMv8 zx2967 family
Browse files Browse the repository at this point in the history
The ARMv8 zx2967 family (296718, 296716 etc) uses different value
for controlling the power domain on/off registers, Choose the
value depending on the compatible.

Multiple domains are prepared for the family, this patch prepares
the common functions.

Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>
  • Loading branch information
Baoyou Xie authored and Shawn Guo committed Jan 11, 2017
1 parent eea1d99 commit 4c2c2e3
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/soc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ source "drivers/soc/tegra/Kconfig"
source "drivers/soc/ti/Kconfig"
source "drivers/soc/ux500/Kconfig"
source "drivers/soc/versatile/Kconfig"
source "drivers/soc/zte/Kconfig"

endmenu
1 change: 1 addition & 0 deletions drivers/soc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_SOC_TI) += ti/
obj-$(CONFIG_ARCH_U8500) += ux500/
obj-$(CONFIG_PLAT_VERSATILE) += versatile/
obj-$(CONFIG_ARCH_ZX) += zte/
13 changes: 13 additions & 0 deletions drivers/soc/zte/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#
# ZTE SoC drivers
#
menuconfig SOC_ZTE
bool "ZTE SoC driver support"

if SOC_ZTE

config ZX2967_PM_DOMAINS
bool "ZX2967 PM domains"
depends on PM_GENERIC_DOMAINS

endif
4 changes: 4 additions & 0 deletions drivers/soc/zte/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#
# ZTE SOC drivers
#
obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx2967_pm_domains.o
143 changes: 143 additions & 0 deletions drivers/soc/zte/zx2967_pm_domains.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright (C) 2017 ZTE Ltd.
*
* Author: Baoyou Xie <baoyou.xie@linaro.org>
* License terms: GNU General Public License (GPL) version 2
*/

#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>

#include "zx2967_pm_domains.h"

#define PCU_DM_CLKEN(zpd) ((zpd)->reg_offset[REG_CLKEN])
#define PCU_DM_ISOEN(zpd) ((zpd)->reg_offset[REG_ISOEN])
#define PCU_DM_RSTEN(zpd) ((zpd)->reg_offset[REG_RSTEN])
#define PCU_DM_PWREN(zpd) ((zpd)->reg_offset[REG_PWREN])
#define PCU_DM_ACK_SYNC(zpd) ((zpd)->reg_offset[REG_ACK_SYNC])

static void __iomem *pcubase;

static int zx2967_power_on(struct generic_pm_domain *domain)
{
struct zx2967_pm_domain *zpd = (struct zx2967_pm_domain *)domain;
unsigned long loop = 1000;
u32 val;

val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd));
if (zpd->polarity == PWREN)
val |= BIT(zpd->bit);
else
val &= ~BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd));

do {
udelay(1);
val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC(zpd))
& BIT(zpd->bit);
} while (--loop && !val);

if (!loop) {
pr_err("Error: %s %s fail\n", __func__, domain->name);
return -EIO;
}

val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd));
val |= BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_RSTEN(zpd));
udelay(5);

val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd));
val &= ~BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_ISOEN(zpd));
udelay(5);

val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd));
val |= BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_CLKEN(zpd));
udelay(5);

pr_debug("poweron %s\n", domain->name);

return 0;
}

static int zx2967_power_off(struct generic_pm_domain *domain)
{
struct zx2967_pm_domain *zpd = (struct zx2967_pm_domain *)domain;
unsigned long loop = 1000;
u32 val;

val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd));
val &= ~BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_CLKEN(zpd));
udelay(5);

val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd));
val |= BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_ISOEN(zpd));
udelay(5);

val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd));
val &= ~BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_RSTEN(zpd));
udelay(5);

val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd));
if (zpd->polarity == PWREN)
val &= ~BIT(zpd->bit);
else
val |= BIT(zpd->bit);
writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd));

do {
udelay(1);
val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC(zpd))
& BIT(zpd->bit);
} while (--loop && val);

if (!loop) {
pr_err("Error: %s %s fail\n", __func__, domain->name);
return -EIO;
}

pr_debug("poweroff %s\n", domain->name);

return 0;
}

int zx2967_pd_probe(struct platform_device *pdev,
struct generic_pm_domain **zx_pm_domains,
int domain_num)
{
struct genpd_onecell_data *genpd_data;
struct resource *res;
int i;

genpd_data = devm_kzalloc(&pdev->dev, sizeof(*genpd_data), GFP_KERNEL);
if (!genpd_data)
return -ENOMEM;

genpd_data->domains = zx_pm_domains;
genpd_data->num_domains = domain_num;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pcubase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pcubase)) {
dev_err(&pdev->dev, "ioremap fail.\n");
return PTR_ERR(pcubase);
}

for (i = 0; i < domain_num; ++i) {
zx_pm_domains[i]->power_on = zx2967_power_on;
zx_pm_domains[i]->power_off = zx2967_power_off;

pm_genpd_init(zx_pm_domains[i], NULL, false);
}

of_genpd_add_provider_onecell(pdev->dev.of_node, genpd_data);
dev_info(&pdev->dev, "powerdomain init ok\n");
return 0;
}
44 changes: 44 additions & 0 deletions drivers/soc/zte/zx2967_pm_domains.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Header for ZTE's Power Domain Driver support
*
* Copyright (C) 2017 ZTE Ltd.
*
* Author: Baoyou Xie <baoyou.xie@linaro.org>
* License terms: GNU General Public License (GPL) version 2
*/

#ifndef __ZTE_ZX2967_PM_DOMAIN_H
#define __ZTE_ZX2967_PM_DOMAIN_H

#include <linux/platform_device.h>
#include <linux/pm_domain.h>

enum {
REG_CLKEN,
REG_ISOEN,
REG_RSTEN,
REG_PWREN,
REG_PWRDN,
REG_ACK_SYNC,

/* The size of the array - must be last */
REG_ARRAY_SIZE,
};

enum zx2967_power_polarity {
PWREN,
PWRDN,
};

struct zx2967_pm_domain {
struct generic_pm_domain dm;
const u16 bit;
const enum zx2967_power_polarity polarity;
const u16 *reg_offset;
};

int zx2967_pd_probe(struct platform_device *pdev,
struct generic_pm_domain **zx_pm_domains,
int domain_num);

#endif /* __ZTE_ZX2967_PM_DOMAIN_H */

0 comments on commit 4c2c2e3

Please sign in to comment.