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

Configure Feed

Select the types of activity you want to include in your feed.

at v5.4-rc2 141 lines 3.5 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2017 ZTE Ltd. 4 * 5 * Author: Baoyou Xie <baoyou.xie@linaro.org> 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 21static void __iomem *pcubase; 22 23static 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 67static 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 111int 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 return PTR_ERR(pcubase); 130 131 for (i = 0; i < domain_num; ++i) { 132 zx_pm_domains[i]->power_on = zx2967_power_on; 133 zx_pm_domains[i]->power_off = zx2967_power_off; 134 135 pm_genpd_init(zx_pm_domains[i], NULL, false); 136 } 137 138 of_genpd_add_provider_onecell(pdev->dev.of_node, genpd_data); 139 dev_info(&pdev->dev, "powerdomain init ok\n"); 140 return 0; 141}