~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-shmobile/pm-rmobile.c

Version: ~ [ linux-5.6 ] ~ [ linux-5.5.13 ] ~ [ linux-5.4.28 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.113 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.174 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.217 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.217 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.82 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * rmobile power management support
  3  *
  4  * Copyright (C) 2012  Renesas Solutions Corp.
  5  * Copyright (C) 2012  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
  6  *
  7  * based on pm-sh7372.c
  8  *  Copyright (C) 2011 Magnus Damm
  9  *
 10  * This file is subject to the terms and conditions of the GNU General Public
 11  * License.  See the file "COPYING" in the main directory of this archive
 12  * for more details.
 13  */
 14 #include <linux/console.h>
 15 #include <linux/delay.h>
 16 #include <linux/platform_device.h>
 17 #include <linux/pm.h>
 18 #include <linux/pm_clock.h>
 19 #include <asm/io.h>
 20 #include <mach/pm-rmobile.h>
 21 
 22 /* SYSC */
 23 #define SPDCR           IOMEM(0xe6180008)
 24 #define SWUCR           IOMEM(0xe6180014)
 25 #define PSTR            IOMEM(0xe6180080)
 26 
 27 #define PSTR_RETRIES    100
 28 #define PSTR_DELAY_US   10
 29 
 30 #ifdef CONFIG_PM
 31 static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
 32 {
 33         struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
 34         unsigned int mask = 1 << rmobile_pd->bit_shift;
 35 
 36         if (rmobile_pd->suspend) {
 37                 int ret = rmobile_pd->suspend();
 38 
 39                 if (ret)
 40                         return ret;
 41         }
 42 
 43         if (__raw_readl(PSTR) & mask) {
 44                 unsigned int retry_count;
 45                 __raw_writel(mask, SPDCR);
 46 
 47                 for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
 48                         if (!(__raw_readl(SPDCR) & mask))
 49                                 break;
 50                         cpu_relax();
 51                 }
 52         }
 53 
 54         if (!rmobile_pd->no_debug)
 55                 pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
 56                          genpd->name, mask, __raw_readl(PSTR));
 57 
 58         return 0;
 59 }
 60 
 61 static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd,
 62                                  bool do_resume)
 63 {
 64         unsigned int mask = 1 << rmobile_pd->bit_shift;
 65         unsigned int retry_count;
 66         int ret = 0;
 67 
 68         if (__raw_readl(PSTR) & mask)
 69                 goto out;
 70 
 71         __raw_writel(mask, SWUCR);
 72 
 73         for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
 74                 if (!(__raw_readl(SWUCR) & mask))
 75                         break;
 76                 if (retry_count > PSTR_RETRIES)
 77                         udelay(PSTR_DELAY_US);
 78                 else
 79                         cpu_relax();
 80         }
 81         if (!retry_count)
 82                 ret = -EIO;
 83 
 84         if (!rmobile_pd->no_debug)
 85                 pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
 86                          rmobile_pd->genpd.name, mask, __raw_readl(PSTR));
 87 
 88 out:
 89         if (ret == 0 && rmobile_pd->resume && do_resume)
 90                 rmobile_pd->resume();
 91 
 92         return ret;
 93 }
 94 
 95 static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
 96 {
 97         return __rmobile_pd_power_up(to_rmobile_pd(genpd), true);
 98 }
 99 
100 static bool rmobile_pd_active_wakeup(struct device *dev)
101 {
102         bool (*active_wakeup)(struct device *dev);
103 
104         active_wakeup = dev_gpd_data(dev)->ops.active_wakeup;
105         return active_wakeup ? active_wakeup(dev) : true;
106 }
107 
108 static int rmobile_pd_stop_dev(struct device *dev)
109 {
110         int (*stop)(struct device *dev);
111 
112         stop = dev_gpd_data(dev)->ops.stop;
113         if (stop) {
114                 int ret = stop(dev);
115                 if (ret)
116                         return ret;
117         }
118         return pm_clk_suspend(dev);
119 }
120 
121 static int rmobile_pd_start_dev(struct device *dev)
122 {
123         int (*start)(struct device *dev);
124         int ret;
125 
126         ret = pm_clk_resume(dev);
127         if (ret)
128                 return ret;
129 
130         start = dev_gpd_data(dev)->ops.start;
131         if (start)
132                 ret = start(dev);
133 
134         return ret;
135 }
136 
137 static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
138 {
139         struct generic_pm_domain *genpd = &rmobile_pd->genpd;
140         struct dev_power_governor *gov = rmobile_pd->gov;
141 
142         pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
143         genpd->dev_ops.stop             = rmobile_pd_stop_dev;
144         genpd->dev_ops.start            = rmobile_pd_start_dev;
145         genpd->dev_ops.active_wakeup    = rmobile_pd_active_wakeup;
146         genpd->dev_irq_safe             = true;
147         genpd->power_off                = rmobile_pd_power_down;
148         genpd->power_on                 = rmobile_pd_power_up;
149         __rmobile_pd_power_up(rmobile_pd, false);
150 }
151 
152 void rmobile_init_domains(struct rmobile_pm_domain domains[], int num)
153 {
154         int j;
155 
156         for (j = 0; j < num; j++)
157                 rmobile_init_pm_domain(&domains[j]);
158 }
159 
160 void rmobile_add_device_to_domain_td(const char *domain_name,
161                                      struct platform_device *pdev,
162                                      struct gpd_timing_data *td)
163 {
164         struct device *dev = &pdev->dev;
165 
166         __pm_genpd_name_add_device(domain_name, dev, td);
167         if (pm_clk_no_clocks(dev))
168                 pm_clk_add(dev, NULL);
169 }
170 
171 void rmobile_add_devices_to_domains(struct pm_domain_device data[],
172                                     int size)
173 {
174         struct gpd_timing_data latencies = {
175                 .stop_latency_ns = DEFAULT_DEV_LATENCY_NS,
176                 .start_latency_ns = DEFAULT_DEV_LATENCY_NS,
177                 .save_state_latency_ns = DEFAULT_DEV_LATENCY_NS,
178                 .restore_state_latency_ns = DEFAULT_DEV_LATENCY_NS,
179         };
180         int j;
181 
182         for (j = 0; j < size; j++)
183                 rmobile_add_device_to_domain_td(data[j].domain_name,
184                                                 data[j].pdev, &latencies);
185 }
186 #endif /* CONFIG_PM */
187 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp