aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/clock_ops.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-08-25 09:33:50 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2011-08-25 09:33:50 -0400
commit5c095a0e0d600d5a5a4207eaadabd18db46395ce (patch)
tree18163d773234898e71c22d83b265a1eccfba11d9 /drivers/base/power/clock_ops.c
parent111058c3ff29a6a25216b31789046c2a330baa7d (diff)
PM: Introduce struct pm_subsys_data
Introduce struct pm_subsys_data that may be subclassed by subsystems to store subsystem-specific information related to the device. Move the clock management fields accessed through the power.subsys_data pointer in struct device to the new strucutre. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base/power/clock_ops.c')
-rw-r--r--drivers/base/power/clock_ops.c122
1 files changed, 64 insertions, 58 deletions
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index 2c18d584066d..b7f1db4f5945 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -17,11 +17,6 @@
17 17
18#ifdef CONFIG_PM 18#ifdef CONFIG_PM
19 19
20struct pm_clk_data {
21 struct list_head clock_list;
22 spinlock_t lock;
23};
24
25enum pce_status { 20enum pce_status {
26 PCE_STATUS_NONE = 0, 21 PCE_STATUS_NONE = 0,
27 PCE_STATUS_ACQUIRED, 22 PCE_STATUS_ACQUIRED,
@@ -36,11 +31,6 @@ struct pm_clock_entry {
36 enum pce_status status; 31 enum pce_status status;
37}; 32};
38 33
39static struct pm_clk_data *__to_pcd(struct device *dev)
40{
41 return dev ? dev->power.subsys_data : NULL;
42}
43
44/** 34/**
45 * pm_clk_add - Start using a device clock for power management. 35 * pm_clk_add - Start using a device clock for power management.
46 * @dev: Device whose clock is going to be used for power management. 36 * @dev: Device whose clock is going to be used for power management.
@@ -51,10 +41,10 @@ static struct pm_clk_data *__to_pcd(struct device *dev)
51 */ 41 */
52int pm_clk_add(struct device *dev, const char *con_id) 42int pm_clk_add(struct device *dev, const char *con_id)
53{ 43{
54 struct pm_clk_data *pcd = __to_pcd(dev); 44 struct pm_subsys_data *psd = dev_to_psd(dev);
55 struct pm_clock_entry *ce; 45 struct pm_clock_entry *ce;
56 46
57 if (!pcd) 47 if (!psd)
58 return -EINVAL; 48 return -EINVAL;
59 49
60 ce = kzalloc(sizeof(*ce), GFP_KERNEL); 50 ce = kzalloc(sizeof(*ce), GFP_KERNEL);
@@ -73,9 +63,9 @@ int pm_clk_add(struct device *dev, const char *con_id)
73 } 63 }
74 } 64 }
75 65
76 spin_lock_irq(&pcd->lock); 66 spin_lock_irq(&psd->lock);
77 list_add_tail(&ce->node, &pcd->clock_list); 67 list_add_tail(&ce->node, &psd->clock_list);
78 spin_unlock_irq(&pcd->lock); 68 spin_unlock_irq(&psd->lock);
79 return 0; 69 return 0;
80} 70}
81 71
@@ -117,15 +107,15 @@ static void __pm_clk_remove(struct pm_clock_entry *ce)
117 */ 107 */
118void pm_clk_remove(struct device *dev, const char *con_id) 108void pm_clk_remove(struct device *dev, const char *con_id)
119{ 109{
120 struct pm_clk_data *pcd = __to_pcd(dev); 110 struct pm_subsys_data *psd = dev_to_psd(dev);
121 struct pm_clock_entry *ce; 111 struct pm_clock_entry *ce;
122 112
123 if (!pcd) 113 if (!psd)
124 return; 114 return;
125 115
126 spin_lock_irq(&pcd->lock); 116 spin_lock_irq(&psd->lock);
127 117
128 list_for_each_entry(ce, &pcd->clock_list, node) { 118 list_for_each_entry(ce, &psd->clock_list, node) {
129 if (!con_id && !ce->con_id) { 119 if (!con_id && !ce->con_id) {
130 __pm_clk_remove(ce); 120 __pm_clk_remove(ce);
131 break; 121 break;
@@ -137,29 +127,45 @@ void pm_clk_remove(struct device *dev, const char *con_id)
137 } 127 }
138 } 128 }
139 129
140 spin_unlock_irq(&pcd->lock); 130 spin_unlock_irq(&psd->lock);
141} 131}
142 132
143/** 133/**
144 * pm_clk_init - Initialize a device's list of power management clocks. 134 * pm_clk_init - Initialize a device's list of power management clocks.
145 * @dev: Device to initialize the list of PM clocks for. 135 * @dev: Device to initialize the list of PM clocks for.
146 * 136 *
147 * Allocate a struct pm_clk_data object, initialize its lock member and 137 * Initialize the lock and clock_list members of the device's pm_subsys_data
148 * make the @dev's power.subsys_data field point to it. 138 * object.
149 */ 139 */
150int pm_clk_init(struct device *dev) 140void pm_clk_init(struct device *dev)
151{ 141{
152 struct pm_clk_data *pcd; 142 struct pm_subsys_data *psd = dev_to_psd(dev);
143
144 if (!psd)
145 return;
153 146
154 pcd = kzalloc(sizeof(*pcd), GFP_KERNEL); 147 INIT_LIST_HEAD(&psd->clock_list);
155 if (!pcd) { 148 spin_lock_init(&psd->lock);
149}
150
151/**
152 * pm_clk_create - Create and initialize a device's list of PM clocks.
153 * @dev: Device to create and initialize the list of PM clocks for.
154 *
155 * Allocate a struct pm_subsys_data object, initialize its lock and clock_list
156 * members and make the @dev's power.subsys_data field point to it.
157 */
158int pm_clk_create(struct device *dev)
159{
160 struct pm_subsys_data *psd;
161
162 psd = kzalloc(sizeof(*psd), GFP_KERNEL);
163 if (!psd) {
156 dev_err(dev, "Not enough memory for PM clock data.\n"); 164 dev_err(dev, "Not enough memory for PM clock data.\n");
157 return -ENOMEM; 165 return -ENOMEM;
158 } 166 }
159 167 dev->power.subsys_data = psd;
160 INIT_LIST_HEAD(&pcd->clock_list); 168 pm_clk_init(dev);
161 spin_lock_init(&pcd->lock);
162 dev->power.subsys_data = pcd;
163 return 0; 169 return 0;
164} 170}
165 171
@@ -168,27 +174,27 @@ int pm_clk_init(struct device *dev)
168 * @dev: Device to destroy the list of PM clocks for. 174 * @dev: Device to destroy the list of PM clocks for.
169 * 175 *
170 * Clear the @dev's power.subsys_data field, remove the list of clock entries 176 * Clear the @dev's power.subsys_data field, remove the list of clock entries
171 * from the struct pm_clk_data object pointed to by it before and free 177 * from the struct pm_subsys_data object pointed to by it before and free
172 * that object. 178 * that object.
173 */ 179 */
174void pm_clk_destroy(struct device *dev) 180void pm_clk_destroy(struct device *dev)
175{ 181{
176 struct pm_clk_data *pcd = __to_pcd(dev); 182 struct pm_subsys_data *psd = dev_to_psd(dev);
177 struct pm_clock_entry *ce, *c; 183 struct pm_clock_entry *ce, *c;
178 184
179 if (!pcd) 185 if (!psd)
180 return; 186 return;
181 187
182 dev->power.subsys_data = NULL; 188 dev->power.subsys_data = NULL;
183 189
184 spin_lock_irq(&pcd->lock); 190 spin_lock_irq(&psd->lock);
185 191
186 list_for_each_entry_safe_reverse(ce, c, &pcd->clock_list, node) 192 list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node)
187 __pm_clk_remove(ce); 193 __pm_clk_remove(ce);
188 194
189 spin_unlock_irq(&pcd->lock); 195 spin_unlock_irq(&psd->lock);
190 196
191 kfree(pcd); 197 kfree(psd);
192} 198}
193 199
194#endif /* CONFIG_PM */ 200#endif /* CONFIG_PM */
@@ -218,18 +224,18 @@ static void pm_clk_acquire(struct device *dev,
218 */ 224 */
219int pm_clk_suspend(struct device *dev) 225int pm_clk_suspend(struct device *dev)
220{ 226{
221 struct pm_clk_data *pcd = __to_pcd(dev); 227 struct pm_subsys_data *psd = dev_to_psd(dev);
222 struct pm_clock_entry *ce; 228 struct pm_clock_entry *ce;
223 unsigned long flags; 229 unsigned long flags;
224 230
225 dev_dbg(dev, "%s()\n", __func__); 231 dev_dbg(dev, "%s()\n", __func__);
226 232
227 if (!pcd) 233 if (!psd)
228 return 0; 234 return 0;
229 235
230 spin_lock_irqsave(&pcd->lock, flags); 236 spin_lock_irqsave(&psd->lock, flags);
231 237
232 list_for_each_entry_reverse(ce, &pcd->clock_list, node) { 238 list_for_each_entry_reverse(ce, &psd->clock_list, node) {
233 if (ce->status == PCE_STATUS_NONE) 239 if (ce->status == PCE_STATUS_NONE)
234 pm_clk_acquire(dev, ce); 240 pm_clk_acquire(dev, ce);
235 241
@@ -239,7 +245,7 @@ int pm_clk_suspend(struct device *dev)
239 } 245 }
240 } 246 }
241 247
242 spin_unlock_irqrestore(&pcd->lock, flags); 248 spin_unlock_irqrestore(&psd->lock, flags);
243 249
244 return 0; 250 return 0;
245} 251}
@@ -250,18 +256,18 @@ int pm_clk_suspend(struct device *dev)
250 */ 256 */
251int pm_clk_resume(struct device *dev) 257int pm_clk_resume(struct device *dev)
252{ 258{
253 struct pm_clk_data *pcd = __to_pcd(dev); 259 struct pm_subsys_data *psd = dev_to_psd(dev);
254 struct pm_clock_entry *ce; 260 struct pm_clock_entry *ce;
255 unsigned long flags; 261 unsigned long flags;
256 262
257 dev_dbg(dev, "%s()\n", __func__); 263 dev_dbg(dev, "%s()\n", __func__);
258 264
259 if (!pcd) 265 if (!psd)
260 return 0; 266 return 0;
261 267
262 spin_lock_irqsave(&pcd->lock, flags); 268 spin_lock_irqsave(&psd->lock, flags);
263 269
264 list_for_each_entry(ce, &pcd->clock_list, node) { 270 list_for_each_entry(ce, &psd->clock_list, node) {
265 if (ce->status == PCE_STATUS_NONE) 271 if (ce->status == PCE_STATUS_NONE)
266 pm_clk_acquire(dev, ce); 272 pm_clk_acquire(dev, ce);
267 273
@@ -271,7 +277,7 @@ int pm_clk_resume(struct device *dev)
271 } 277 }
272 } 278 }
273 279
274 spin_unlock_irqrestore(&pcd->lock, flags); 280 spin_unlock_irqrestore(&psd->lock, flags);
275 281
276 return 0; 282 return 0;
277} 283}
@@ -309,7 +315,7 @@ static int pm_clk_notify(struct notifier_block *nb,
309 if (dev->pm_domain) 315 if (dev->pm_domain)
310 break; 316 break;
311 317
312 error = pm_clk_init(dev); 318 error = pm_clk_create(dev);
313 if (error) 319 if (error)
314 break; 320 break;
315 321
@@ -344,22 +350,22 @@ static int pm_clk_notify(struct notifier_block *nb,
344 */ 350 */
345int pm_clk_suspend(struct device *dev) 351int pm_clk_suspend(struct device *dev)
346{ 352{
347 struct pm_clk_data *pcd = __to_pcd(dev); 353 struct pm_subsys_data *psd = dev_to_psd(dev);
348 struct pm_clock_entry *ce; 354 struct pm_clock_entry *ce;
349 unsigned long flags; 355 unsigned long flags;
350 356
351 dev_dbg(dev, "%s()\n", __func__); 357 dev_dbg(dev, "%s()\n", __func__);
352 358
353 /* If there is no driver, the clocks are already disabled. */ 359 /* If there is no driver, the clocks are already disabled. */
354 if (!pcd || !dev->driver) 360 if (!psd || !dev->driver)
355 return 0; 361 return 0;
356 362
357 spin_lock_irqsave(&pcd->lock, flags); 363 spin_lock_irqsave(&psd->lock, flags);
358 364
359 list_for_each_entry_reverse(ce, &pcd->clock_list, node) 365 list_for_each_entry_reverse(ce, &psd->clock_list, node)
360 clk_disable(ce->clk); 366 clk_disable(ce->clk);
361 367
362 spin_unlock_irqrestore(&pcd->lock, flags); 368 spin_unlock_irqrestore(&psd->lock, flags);
363 369
364 return 0; 370 return 0;
365} 371}
@@ -370,22 +376,22 @@ int pm_clk_suspend(struct device *dev)
370 */ 376 */
371int pm_clk_resume(struct device *dev) 377int pm_clk_resume(struct device *dev)
372{ 378{
373 struct pm_clk_data *pcd = __to_pcd(dev); 379 struct pm_subsys_data *psd = dev_to_psd(dev);
374 struct pm_clock_entry *ce; 380 struct pm_clock_entry *ce;
375 unsigned long flags; 381 unsigned long flags;
376 382
377 dev_dbg(dev, "%s()\n", __func__); 383 dev_dbg(dev, "%s()\n", __func__);
378 384
379 /* If there is no driver, the clocks should remain disabled. */ 385 /* If there is no driver, the clocks should remain disabled. */
380 if (!pcd || !dev->driver) 386 if (!psd || !dev->driver)
381 return 0; 387 return 0;
382 388
383 spin_lock_irqsave(&pcd->lock, flags); 389 spin_lock_irqsave(&psd->lock, flags);
384 390
385 list_for_each_entry(ce, &pcd->clock_list, node) 391 list_for_each_entry(ce, &psd->clock_list, node)
386 clk_enable(ce->clk); 392 clk_enable(ce->clk);
387 393
388 spin_unlock_irqrestore(&pcd->lock, flags); 394 spin_unlock_irqrestore(&psd->lock, flags);
389 395
390 return 0; 396 return 0;
391} 397}