Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: zte: pm_domains: Prepare for supporting ARMv8 zx2967 family

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>

authored by

Baoyou Xie and committed by
Shawn Guo
4c2c2e39 eea1d99b

+206
+1
drivers/soc/Kconfig
··· 11 11 source "drivers/soc/ti/Kconfig" 12 12 source "drivers/soc/ux500/Kconfig" 13 13 source "drivers/soc/versatile/Kconfig" 14 + source "drivers/soc/zte/Kconfig" 14 15 15 16 endmenu
+1
drivers/soc/Makefile
··· 16 16 obj-$(CONFIG_SOC_TI) += ti/ 17 17 obj-$(CONFIG_ARCH_U8500) += ux500/ 18 18 obj-$(CONFIG_PLAT_VERSATILE) += versatile/ 19 + obj-$(CONFIG_ARCH_ZX) += zte/
+13
drivers/soc/zte/Kconfig
··· 1 + # 2 + # ZTE SoC drivers 3 + # 4 + menuconfig SOC_ZTE 5 + bool "ZTE SoC driver support" 6 + 7 + if SOC_ZTE 8 + 9 + config ZX2967_PM_DOMAINS 10 + bool "ZX2967 PM domains" 11 + depends on PM_GENERIC_DOMAINS 12 + 13 + endif
+4
drivers/soc/zte/Makefile
··· 1 + # 2 + # ZTE SOC drivers 3 + # 4 + obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx2967_pm_domains.o
+143
drivers/soc/zte/zx2967_pm_domains.c
··· 1 + /* 2 + * Copyright (C) 2017 ZTE Ltd. 3 + * 4 + * Author: Baoyou Xie <baoyou.xie@linaro.org> 5 + * License terms: GNU General Public License (GPL) version 2 6 + */ 7 + 8 + #include <linux/delay.h> 9 + #include <linux/err.h> 10 + #include <linux/io.h> 11 + #include <linux/of.h> 12 + 13 + #include "zx2967_pm_domains.h" 14 + 15 + #define PCU_DM_CLKEN(zpd) ((zpd)->reg_offset[REG_CLKEN]) 16 + #define PCU_DM_ISOEN(zpd) ((zpd)->reg_offset[REG_ISOEN]) 17 + #define PCU_DM_RSTEN(zpd) ((zpd)->reg_offset[REG_RSTEN]) 18 + #define PCU_DM_PWREN(zpd) ((zpd)->reg_offset[REG_PWREN]) 19 + #define PCU_DM_ACK_SYNC(zpd) ((zpd)->reg_offset[REG_ACK_SYNC]) 20 + 21 + static void __iomem *pcubase; 22 + 23 + static int zx2967_power_on(struct generic_pm_domain *domain) 24 + { 25 + struct zx2967_pm_domain *zpd = (struct zx2967_pm_domain *)domain; 26 + unsigned long loop = 1000; 27 + u32 val; 28 + 29 + val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd)); 30 + if (zpd->polarity == PWREN) 31 + val |= BIT(zpd->bit); 32 + else 33 + val &= ~BIT(zpd->bit); 34 + writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd)); 35 + 36 + do { 37 + udelay(1); 38 + val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC(zpd)) 39 + & BIT(zpd->bit); 40 + } while (--loop && !val); 41 + 42 + if (!loop) { 43 + pr_err("Error: %s %s fail\n", __func__, domain->name); 44 + return -EIO; 45 + } 46 + 47 + val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd)); 48 + val |= BIT(zpd->bit); 49 + writel_relaxed(val, pcubase + PCU_DM_RSTEN(zpd)); 50 + udelay(5); 51 + 52 + val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd)); 53 + val &= ~BIT(zpd->bit); 54 + writel_relaxed(val, pcubase + PCU_DM_ISOEN(zpd)); 55 + udelay(5); 56 + 57 + val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd)); 58 + val |= BIT(zpd->bit); 59 + writel_relaxed(val, pcubase + PCU_DM_CLKEN(zpd)); 60 + udelay(5); 61 + 62 + pr_debug("poweron %s\n", domain->name); 63 + 64 + return 0; 65 + } 66 + 67 + static int zx2967_power_off(struct generic_pm_domain *domain) 68 + { 69 + struct zx2967_pm_domain *zpd = (struct zx2967_pm_domain *)domain; 70 + unsigned long loop = 1000; 71 + u32 val; 72 + 73 + val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd)); 74 + val &= ~BIT(zpd->bit); 75 + writel_relaxed(val, pcubase + PCU_DM_CLKEN(zpd)); 76 + udelay(5); 77 + 78 + val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd)); 79 + val |= BIT(zpd->bit); 80 + writel_relaxed(val, pcubase + PCU_DM_ISOEN(zpd)); 81 + udelay(5); 82 + 83 + val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd)); 84 + val &= ~BIT(zpd->bit); 85 + writel_relaxed(val, pcubase + PCU_DM_RSTEN(zpd)); 86 + udelay(5); 87 + 88 + val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd)); 89 + if (zpd->polarity == PWREN) 90 + val &= ~BIT(zpd->bit); 91 + else 92 + val |= BIT(zpd->bit); 93 + writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd)); 94 + 95 + do { 96 + udelay(1); 97 + val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC(zpd)) 98 + & BIT(zpd->bit); 99 + } while (--loop && val); 100 + 101 + if (!loop) { 102 + pr_err("Error: %s %s fail\n", __func__, domain->name); 103 + return -EIO; 104 + } 105 + 106 + pr_debug("poweroff %s\n", domain->name); 107 + 108 + return 0; 109 + } 110 + 111 + int zx2967_pd_probe(struct platform_device *pdev, 112 + struct generic_pm_domain **zx_pm_domains, 113 + int domain_num) 114 + { 115 + struct genpd_onecell_data *genpd_data; 116 + struct resource *res; 117 + int i; 118 + 119 + genpd_data = devm_kzalloc(&pdev->dev, sizeof(*genpd_data), GFP_KERNEL); 120 + if (!genpd_data) 121 + return -ENOMEM; 122 + 123 + genpd_data->domains = zx_pm_domains; 124 + genpd_data->num_domains = domain_num; 125 + 126 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 127 + pcubase = devm_ioremap_resource(&pdev->dev, res); 128 + if (IS_ERR(pcubase)) { 129 + dev_err(&pdev->dev, "ioremap fail.\n"); 130 + return PTR_ERR(pcubase); 131 + } 132 + 133 + for (i = 0; i < domain_num; ++i) { 134 + zx_pm_domains[i]->power_on = zx2967_power_on; 135 + zx_pm_domains[i]->power_off = zx2967_power_off; 136 + 137 + pm_genpd_init(zx_pm_domains[i], NULL, false); 138 + } 139 + 140 + of_genpd_add_provider_onecell(pdev->dev.of_node, genpd_data); 141 + dev_info(&pdev->dev, "powerdomain init ok\n"); 142 + return 0; 143 + }
+44
drivers/soc/zte/zx2967_pm_domains.h
··· 1 + /* 2 + * Header for ZTE's Power Domain Driver support 3 + * 4 + * Copyright (C) 2017 ZTE Ltd. 5 + * 6 + * Author: Baoyou Xie <baoyou.xie@linaro.org> 7 + * License terms: GNU General Public License (GPL) version 2 8 + */ 9 + 10 + #ifndef __ZTE_ZX2967_PM_DOMAIN_H 11 + #define __ZTE_ZX2967_PM_DOMAIN_H 12 + 13 + #include <linux/platform_device.h> 14 + #include <linux/pm_domain.h> 15 + 16 + enum { 17 + REG_CLKEN, 18 + REG_ISOEN, 19 + REG_RSTEN, 20 + REG_PWREN, 21 + REG_PWRDN, 22 + REG_ACK_SYNC, 23 + 24 + /* The size of the array - must be last */ 25 + REG_ARRAY_SIZE, 26 + }; 27 + 28 + enum zx2967_power_polarity { 29 + PWREN, 30 + PWRDN, 31 + }; 32 + 33 + struct zx2967_pm_domain { 34 + struct generic_pm_domain dm; 35 + const u16 bit; 36 + const enum zx2967_power_polarity polarity; 37 + const u16 *reg_offset; 38 + }; 39 + 40 + int zx2967_pd_probe(struct platform_device *pdev, 41 + struct generic_pm_domain **zx_pm_domains, 42 + int domain_num); 43 + 44 + #endif /* __ZTE_ZX2967_PM_DOMAIN_H */