~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to arch/arm/mach-omap2/clockdomain.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
 
27
27
#include <linux/bitops.h>
28
28
 
29
 
#include "prm2xxx_3xxx.h"
30
 
#include "prm-regbits-24xx.h"
31
 
#include "cm2xxx_3xxx.h"
32
 
#include "cm-regbits-24xx.h"
33
 
#include "cminst44xx.h"
34
 
#include "prcm44xx.h"
35
 
 
36
29
#include <plat/clock.h>
37
 
#include "powerdomain.h"
38
30
#include "clockdomain.h"
39
 
#include <plat/prcm.h>
40
31
 
41
32
/* clkdm_list contains all registered struct clockdomains */
42
33
static LIST_HEAD(clkdm_list);
44
35
/* array of clockdomain deps to be added/removed when clkdm in hwsup mode */
45
36
static struct clkdm_autodep *autodeps;
46
37
 
 
38
static struct clkdm_ops *arch_clkdm;
47
39
 
48
40
/* Private functions */
49
41
 
177
169
 * XXX autodeps are deprecated and should be removed at the earliest
178
170
 * opportunity
179
171
 */
180
 
static void _clkdm_add_autodeps(struct clockdomain *clkdm)
 
172
void _clkdm_add_autodeps(struct clockdomain *clkdm)
181
173
{
182
174
        struct clkdm_autodep *autodep;
183
175
 
184
 
        if (!autodeps)
 
176
        if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
185
177
                return;
186
178
 
187
179
        for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
211
203
 * XXX autodeps are deprecated and should be removed at the earliest
212
204
 * opportunity
213
205
 */
214
 
static void _clkdm_del_autodeps(struct clockdomain *clkdm)
 
206
void _clkdm_del_autodeps(struct clockdomain *clkdm)
215
207
{
216
208
        struct clkdm_autodep *autodep;
217
209
 
218
 
        if (!autodeps)
 
210
        if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
219
211
                return;
220
212
 
221
213
        for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
235
227
}
236
228
 
237
229
/**
238
 
 * _enable_hwsup - place a clockdomain into hardware-supervised idle
239
 
 * @clkdm: struct clockdomain *
240
 
 *
241
 
 * Place the clockdomain into hardware-supervised idle mode.  No return
242
 
 * value.
243
 
 *
244
 
 * XXX Should this return an error if the clockdomain does not support
245
 
 * hardware-supervised idle mode?
246
 
 */
247
 
static void _enable_hwsup(struct clockdomain *clkdm)
248
 
{
249
 
        if (cpu_is_omap24xx())
250
 
                omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
251
 
                                               clkdm->clktrctrl_mask);
252
 
        else if (cpu_is_omap34xx())
253
 
                omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
254
 
                                               clkdm->clktrctrl_mask);
255
 
        else if (cpu_is_omap44xx())
256
 
                return omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
257
 
                                                       clkdm->cm_inst,
258
 
                                                       clkdm->clkdm_offs);
259
 
        else
260
 
                BUG();
261
 
}
262
 
 
263
 
/**
264
 
 * _disable_hwsup - place a clockdomain into software-supervised idle
265
 
 * @clkdm: struct clockdomain *
266
 
 *
267
 
 * Place the clockdomain @clkdm into software-supervised idle mode.
 
230
 * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms
 
231
 * @clkdm: clockdomain that we are resolving dependencies for
 
232
 * @clkdm_deps: ptr to array of struct clkdm_deps to resolve
 
233
 *
 
234
 * Iterates through @clkdm_deps, looking up the struct clockdomain named by
 
235
 * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep.
268
236
 * No return value.
269
 
 *
270
 
 * XXX Should this return an error if the clockdomain does not support
271
 
 * software-supervised idle mode?
272
237
 */
273
 
static void _disable_hwsup(struct clockdomain *clkdm)
 
238
static void _resolve_clkdm_deps(struct clockdomain *clkdm,
 
239
                                struct clkdm_dep *clkdm_deps)
274
240
{
275
 
        if (cpu_is_omap24xx())
276
 
                omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
277
 
                                                clkdm->clktrctrl_mask);
278
 
        else if (cpu_is_omap34xx())
279
 
                omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
280
 
                                                clkdm->clktrctrl_mask);
281
 
        else if (cpu_is_omap44xx())
282
 
                return omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
283
 
                                                        clkdm->cm_inst,
284
 
                                                        clkdm->clkdm_offs);
285
 
        else
286
 
                BUG();
 
241
        struct clkdm_dep *cd;
 
242
 
 
243
        for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
 
244
                if (!omap_chip_is(cd->omap_chip))
 
245
                        continue;
 
246
                if (cd->clkdm)
 
247
                        continue;
 
248
                cd->clkdm = _clkdm_lookup(cd->clkdm_name);
 
249
 
 
250
                WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen",
 
251
                     clkdm->name, cd->clkdm_name);
 
252
        }
287
253
}
288
254
 
289
255
/* Public functions */
292
258
 * clkdm_init - set up the clockdomain layer
293
259
 * @clkdms: optional pointer to an array of clockdomains to register
294
260
 * @init_autodeps: optional pointer to an array of autodeps to register
 
261
 * @custom_funcs: func pointers for arch specific implementations
295
262
 *
296
263
 * Set up internal state.  If a pointer to an array of clockdomains
297
264
 * @clkdms was supplied, loop through the list of clockdomains,
300
267
 * @init_autodeps was provided, register those.  No return value.
301
268
 */
302
269
void clkdm_init(struct clockdomain **clkdms,
303
 
                struct clkdm_autodep *init_autodeps)
 
270
                struct clkdm_autodep *init_autodeps,
 
271
                struct clkdm_ops *custom_funcs)
304
272
{
305
273
        struct clockdomain **c = NULL;
306
274
        struct clockdomain *clkdm;
307
275
        struct clkdm_autodep *autodep = NULL;
308
276
 
 
277
        if (!custom_funcs)
 
278
                WARN(1, "No custom clkdm functions registered\n");
 
279
        else
 
280
                arch_clkdm = custom_funcs;
 
281
 
309
282
        if (clkdms)
310
283
                for (c = clkdms; *c; c++)
311
284
                        _clkdm_register(*c);
321
294
         */
322
295
        list_for_each_entry(clkdm, &clkdm_list, node) {
323
296
                if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
324
 
                        omap2_clkdm_wakeup(clkdm);
 
297
                        clkdm_wakeup(clkdm);
325
298
                else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
326
 
                        omap2_clkdm_deny_idle(clkdm);
 
299
                        clkdm_deny_idle(clkdm);
327
300
 
 
301
                _resolve_clkdm_deps(clkdm, clkdm->wkdep_srcs);
328
302
                clkdm_clear_all_wkdeps(clkdm);
 
303
 
 
304
                _resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
329
305
                clkdm_clear_all_sleepdeps(clkdm);
330
306
        }
331
307
}
422
398
int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
423
399
{
424
400
        struct clkdm_dep *cd;
425
 
 
426
 
        if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
427
 
                pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
428
 
                       clkdm1->name, clkdm2->name, __func__);
429
 
                return -EINVAL;
430
 
        }
 
401
        int ret = 0;
431
402
 
432
403
        if (!clkdm1 || !clkdm2)
433
404
                return -EINVAL;
434
405
 
435
406
        cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
436
 
        if (IS_ERR(cd)) {
 
407
        if (IS_ERR(cd))
 
408
                ret = PTR_ERR(cd);
 
409
 
 
410
        if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
 
411
                ret = -EINVAL;
 
412
 
 
413
        if (ret) {
437
414
                pr_debug("clockdomain: hardware cannot set/clear wake up of "
438
415
                         "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
439
 
                return PTR_ERR(cd);
 
416
                return ret;
440
417
        }
441
418
 
442
419
        if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
443
420
                pr_debug("clockdomain: hardware will wake up %s when %s wakes "
444
421
                         "up\n", clkdm1->name, clkdm2->name);
445
422
 
446
 
                omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
447
 
                                     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
 
423
                ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
448
424
        }
449
425
 
450
 
        return 0;
 
426
        return ret;
451
427
}
452
428
 
453
429
/**
463
439
int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
464
440
{
465
441
        struct clkdm_dep *cd;
466
 
 
467
 
        if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
468
 
                pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
469
 
                       clkdm1->name, clkdm2->name, __func__);
470
 
                return -EINVAL;
471
 
        }
 
442
        int ret = 0;
472
443
 
473
444
        if (!clkdm1 || !clkdm2)
474
445
                return -EINVAL;
475
446
 
476
447
        cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
477
 
        if (IS_ERR(cd)) {
 
448
        if (IS_ERR(cd))
 
449
                ret = PTR_ERR(cd);
 
450
 
 
451
        if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
 
452
                ret = -EINVAL;
 
453
 
 
454
        if (ret) {
478
455
                pr_debug("clockdomain: hardware cannot set/clear wake up of "
479
456
                         "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
480
 
                return PTR_ERR(cd);
 
457
                return ret;
481
458
        }
482
459
 
483
460
        if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
484
461
                pr_debug("clockdomain: hardware will no longer wake up %s "
485
462
                         "after %s wakes up\n", clkdm1->name, clkdm2->name);
486
463
 
487
 
                omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
488
 
                                       clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
 
464
                ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
489
465
        }
490
466
 
491
 
        return 0;
 
467
        return ret;
492
468
}
493
469
 
494
470
/**
508
484
int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
509
485
{
510
486
        struct clkdm_dep *cd;
 
487
        int ret = 0;
511
488
 
512
489
        if (!clkdm1 || !clkdm2)
513
490
                return -EINVAL;
514
491
 
515
 
        if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
516
 
                pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
517
 
                       clkdm1->name, clkdm2->name, __func__);
518
 
                return -EINVAL;
519
 
        }
520
 
 
521
492
        cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
522
 
        if (IS_ERR(cd)) {
 
493
        if (IS_ERR(cd))
 
494
                ret = PTR_ERR(cd);
 
495
 
 
496
        if (!arch_clkdm || !arch_clkdm->clkdm_read_wkdep)
 
497
                ret = -EINVAL;
 
498
 
 
499
        if (ret) {
523
500
                pr_debug("clockdomain: hardware cannot set/clear wake up of "
524
501
                         "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
525
 
                return PTR_ERR(cd);
 
502
                return ret;
526
503
        }
527
504
 
528
505
        /* XXX It's faster to return the atomic wkdep_usecount */
529
 
        return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
530
 
                                       (1 << clkdm2->dep_bit));
 
506
        return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2);
531
507
}
532
508
 
533
509
/**
542
518
 */
543
519
int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
544
520
{
545
 
        struct clkdm_dep *cd;
546
 
        u32 mask = 0;
547
 
 
548
 
        if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
549
 
                pr_err("clockdomain: %s: %s: not yet implemented\n",
550
 
                       clkdm->name, __func__);
551
 
                return -EINVAL;
552
 
        }
553
 
 
554
521
        if (!clkdm)
555
522
                return -EINVAL;
556
523
 
557
 
        for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
558
 
                if (!omap_chip_is(cd->omap_chip))
559
 
                        continue;
560
 
 
561
 
                if (!cd->clkdm && cd->clkdm_name)
562
 
                        cd->clkdm = _clkdm_lookup(cd->clkdm_name);
563
 
 
564
 
                /* PRM accesses are slow, so minimize them */
565
 
                mask |= 1 << cd->clkdm->dep_bit;
566
 
                atomic_set(&cd->wkdep_usecount, 0);
567
 
        }
568
 
 
569
 
        omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
570
 
 
571
 
        return 0;
 
524
        if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_wkdeps)
 
525
                return -EINVAL;
 
526
 
 
527
        return arch_clkdm->clkdm_clear_all_wkdeps(clkdm);
572
528
}
573
529
 
574
530
/**
586
542
int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
587
543
{
588
544
        struct clkdm_dep *cd;
589
 
 
590
 
        if (!cpu_is_omap34xx())
591
 
                return -EINVAL;
 
545
        int ret = 0;
592
546
 
593
547
        if (!clkdm1 || !clkdm2)
594
548
                return -EINVAL;
595
549
 
596
550
        cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
597
 
        if (IS_ERR(cd)) {
 
551
        if (IS_ERR(cd))
 
552
                ret = PTR_ERR(cd);
 
553
 
 
554
        if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
 
555
                ret = -EINVAL;
 
556
 
 
557
        if (ret) {
598
558
                pr_debug("clockdomain: hardware cannot set/clear sleep "
599
559
                         "dependency affecting %s from %s\n", clkdm1->name,
600
560
                         clkdm2->name);
601
 
                return PTR_ERR(cd);
 
561
                return ret;
602
562
        }
603
563
 
604
564
        if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
605
565
                pr_debug("clockdomain: will prevent %s from sleeping if %s "
606
566
                         "is active\n", clkdm1->name, clkdm2->name);
607
567
 
608
 
                omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
609
 
                                    clkdm1->pwrdm.ptr->prcm_offs,
610
 
                                    OMAP3430_CM_SLEEPDEP);
 
568
                ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
611
569
        }
612
570
 
613
 
        return 0;
 
571
        return ret;
614
572
}
615
573
 
616
574
/**
628
586
int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
629
587
{
630
588
        struct clkdm_dep *cd;
631
 
 
632
 
        if (!cpu_is_omap34xx())
633
 
                return -EINVAL;
 
589
        int ret = 0;
634
590
 
635
591
        if (!clkdm1 || !clkdm2)
636
592
                return -EINVAL;
637
593
 
638
594
        cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
639
 
        if (IS_ERR(cd)) {
 
595
        if (IS_ERR(cd))
 
596
                ret = PTR_ERR(cd);
 
597
 
 
598
        if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
 
599
                ret = -EINVAL;
 
600
 
 
601
        if (ret) {
640
602
                pr_debug("clockdomain: hardware cannot set/clear sleep "
641
603
                         "dependency affecting %s from %s\n", clkdm1->name,
642
604
                         clkdm2->name);
643
 
                return PTR_ERR(cd);
 
605
                return ret;
644
606
        }
645
607
 
646
608
        if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
648
610
                         "sleeping if %s is active\n", clkdm1->name,
649
611
                         clkdm2->name);
650
612
 
651
 
                omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
652
 
                                      clkdm1->pwrdm.ptr->prcm_offs,
653
 
                                      OMAP3430_CM_SLEEPDEP);
 
613
                ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
654
614
        }
655
615
 
656
 
        return 0;
 
616
        return ret;
657
617
}
658
618
 
659
619
/**
675
635
int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
676
636
{
677
637
        struct clkdm_dep *cd;
678
 
 
679
 
        if (!cpu_is_omap34xx())
680
 
                return -EINVAL;
 
638
        int ret = 0;
681
639
 
682
640
        if (!clkdm1 || !clkdm2)
683
641
                return -EINVAL;
684
642
 
685
643
        cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
686
 
        if (IS_ERR(cd)) {
 
644
        if (IS_ERR(cd))
 
645
                ret = PTR_ERR(cd);
 
646
 
 
647
        if (!arch_clkdm || !arch_clkdm->clkdm_read_sleepdep)
 
648
                ret = -EINVAL;
 
649
 
 
650
        if (ret) {
687
651
                pr_debug("clockdomain: hardware cannot set/clear sleep "
688
652
                         "dependency affecting %s from %s\n", clkdm1->name,
689
653
                         clkdm2->name);
690
 
                return PTR_ERR(cd);
 
654
                return ret;
691
655
        }
692
656
 
693
657
        /* XXX It's faster to return the atomic sleepdep_usecount */
694
 
        return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
695
 
                                       OMAP3430_CM_SLEEPDEP,
696
 
                                       (1 << clkdm2->dep_bit));
 
658
        return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2);
697
659
}
698
660
 
699
661
/**
708
670
 */
709
671
int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
710
672
{
711
 
        struct clkdm_dep *cd;
712
 
        u32 mask = 0;
713
 
 
714
 
        if (!cpu_is_omap34xx())
715
 
                return -EINVAL;
716
 
 
717
673
        if (!clkdm)
718
674
                return -EINVAL;
719
675
 
720
 
        for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
721
 
                if (!omap_chip_is(cd->omap_chip))
722
 
                        continue;
723
 
 
724
 
                if (!cd->clkdm && cd->clkdm_name)
725
 
                        cd->clkdm = _clkdm_lookup(cd->clkdm_name);
726
 
 
727
 
                /* PRM accesses are slow, so minimize them */
728
 
                mask |= 1 << cd->clkdm->dep_bit;
729
 
                atomic_set(&cd->sleepdep_usecount, 0);
730
 
        }
731
 
 
732
 
        omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
733
 
                               OMAP3430_CM_SLEEPDEP);
734
 
 
735
 
        return 0;
 
676
        if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_sleepdeps)
 
677
                return -EINVAL;
 
678
 
 
679
        return arch_clkdm->clkdm_clear_all_sleepdeps(clkdm);
736
680
}
737
681
 
738
682
/**
739
 
 * omap2_clkdm_sleep - force clockdomain sleep transition
 
683
 * clkdm_sleep - force clockdomain sleep transition
740
684
 * @clkdm: struct clockdomain *
741
685
 *
742
686
 * Instruct the CM to force a sleep transition on the specified
744
688
 * clockdomain does not support software-initiated sleep; 0 upon
745
689
 * success.
746
690
 */
747
 
int omap2_clkdm_sleep(struct clockdomain *clkdm)
 
691
int clkdm_sleep(struct clockdomain *clkdm)
748
692
{
749
693
        if (!clkdm)
750
694
                return -EINVAL;
755
699
                return -EINVAL;
756
700
        }
757
701
 
 
702
        if (!arch_clkdm || !arch_clkdm->clkdm_sleep)
 
703
                return -EINVAL;
 
704
 
758
705
        pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
759
706
 
760
 
        if (cpu_is_omap24xx()) {
761
 
 
762
 
                omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
763
 
                            clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
764
 
 
765
 
        } else if (cpu_is_omap34xx()) {
766
 
 
767
 
                omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
768
 
                                              clkdm->clktrctrl_mask);
769
 
 
770
 
        } else if (cpu_is_omap44xx()) {
771
 
 
772
 
                omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition,
773
 
                                               clkdm->cm_inst,
774
 
                                               clkdm->clkdm_offs);
775
 
 
776
 
        } else {
777
 
                BUG();
778
 
        };
779
 
 
780
 
        return 0;
 
707
        return arch_clkdm->clkdm_sleep(clkdm);
781
708
}
782
709
 
783
710
/**
784
 
 * omap2_clkdm_wakeup - force clockdomain wakeup transition
 
711
 * clkdm_wakeup - force clockdomain wakeup transition
785
712
 * @clkdm: struct clockdomain *
786
713
 *
787
714
 * Instruct the CM to force a wakeup transition on the specified
789
716
 * clockdomain does not support software-controlled wakeup; 0 upon
790
717
 * success.
791
718
 */
792
 
int omap2_clkdm_wakeup(struct clockdomain *clkdm)
 
719
int clkdm_wakeup(struct clockdomain *clkdm)
793
720
{
794
721
        if (!clkdm)
795
722
                return -EINVAL;
800
727
                return -EINVAL;
801
728
        }
802
729
 
 
730
        if (!arch_clkdm || !arch_clkdm->clkdm_wakeup)
 
731
                return -EINVAL;
 
732
 
803
733
        pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
804
734
 
805
 
        if (cpu_is_omap24xx()) {
806
 
 
807
 
                omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
808
 
                              clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
809
 
 
810
 
        } else if (cpu_is_omap34xx()) {
811
 
 
812
 
                omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
813
 
                                               clkdm->clktrctrl_mask);
814
 
 
815
 
        } else if (cpu_is_omap44xx()) {
816
 
 
817
 
                omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
818
 
                                                clkdm->cm_inst,
819
 
                                                clkdm->clkdm_offs);
820
 
 
821
 
        } else {
822
 
                BUG();
823
 
        };
824
 
 
825
 
        return 0;
 
735
        return arch_clkdm->clkdm_wakeup(clkdm);
826
736
}
827
737
 
828
738
/**
829
 
 * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
 
739
 * clkdm_allow_idle - enable hwsup idle transitions for clkdm
830
740
 * @clkdm: struct clockdomain *
831
741
 *
832
742
 * Allow the hardware to automatically switch the clockdomain @clkdm into
835
745
 * framework, wkdep/sleepdep autodependencies are added; this is so
836
746
 * device drivers can read and write to the device.  No return value.
837
747
 */
838
 
void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
 
748
void clkdm_allow_idle(struct clockdomain *clkdm)
839
749
{
840
750
        if (!clkdm)
841
751
                return;
846
756
                return;
847
757
        }
848
758
 
 
759
        if (!arch_clkdm || !arch_clkdm->clkdm_allow_idle)
 
760
                return;
 
761
 
849
762
        pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
850
763
                 clkdm->name);
851
764
 
852
 
        /*
853
 
         * XXX This should be removed once TI adds wakeup/sleep
854
 
         * dependency code and data for OMAP4.
855
 
         */
856
 
        if (cpu_is_omap44xx()) {
857
 
                pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name);
858
 
        } else {
859
 
                if (atomic_read(&clkdm->usecount) > 0)
860
 
                        _clkdm_add_autodeps(clkdm);
861
 
        }
862
 
 
863
 
        _enable_hwsup(clkdm);
864
 
 
 
765
        arch_clkdm->clkdm_allow_idle(clkdm);
865
766
        pwrdm_clkdm_state_switch(clkdm);
866
767
}
867
768
 
868
769
/**
869
 
 * omap2_clkdm_deny_idle - disable hwsup idle transitions for clkdm
 
770
 * clkdm_deny_idle - disable hwsup idle transitions for clkdm
870
771
 * @clkdm: struct clockdomain *
871
772
 *
872
773
 * Prevent the hardware from automatically switching the clockdomain
874
775
 * downstream clocks enabled in the clock framework, wkdep/sleepdep
875
776
 * autodependencies are removed.  No return value.
876
777
 */
877
 
void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
 
778
void clkdm_deny_idle(struct clockdomain *clkdm)
878
779
{
879
780
        if (!clkdm)
880
781
                return;
885
786
                return;
886
787
        }
887
788
 
 
789
        if (!arch_clkdm || !arch_clkdm->clkdm_deny_idle)
 
790
                return;
 
791
 
888
792
        pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
889
793
                 clkdm->name);
890
794
 
891
 
        _disable_hwsup(clkdm);
892
 
 
893
 
        /*
894
 
         * XXX This should be removed once TI adds wakeup/sleep
895
 
         * dependency code and data for OMAP4.
896
 
         */
897
 
        if (cpu_is_omap44xx()) {
898
 
                pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name);
899
 
        } else {
900
 
                if (atomic_read(&clkdm->usecount) > 0)
901
 
                        _clkdm_del_autodeps(clkdm);
902
 
        }
 
795
        arch_clkdm->clkdm_deny_idle(clkdm);
903
796
}
904
797
 
905
798
 
906
799
/* Clockdomain-to-clock framework interface code */
907
800
 
908
801
/**
909
 
 * omap2_clkdm_clk_enable - add an enabled downstream clock to this clkdm
 
802
 * clkdm_clk_enable - add an enabled downstream clock to this clkdm
910
803
 * @clkdm: struct clockdomain *
911
804
 * @clk: struct clk * of the enabled downstream clock
912
805
 *
919
812
 * by on-chip processors.  Returns -EINVAL if passed null pointers;
920
813
 * returns 0 upon success or if the clockdomain is in hwsup idle mode.
921
814
 */
922
 
int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 
815
int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
923
816
{
924
 
        bool hwsup = false;
925
 
 
926
817
        /*
927
818
         * XXX Rewrite this code to maintain a list of enabled
928
819
         * downstream clocks for debugging purposes?
931
822
        if (!clkdm || !clk)
932
823
                return -EINVAL;
933
824
 
 
825
        if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable)
 
826
                return -EINVAL;
 
827
 
934
828
        if (atomic_inc_return(&clkdm->usecount) > 1)
935
829
                return 0;
936
830
 
939
833
        pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
940
834
                 clk->name);
941
835
 
942
 
        if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
943
 
 
944
 
                if (!clkdm->clktrctrl_mask)
945
 
                        return 0;
946
 
 
947
 
                hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
948
 
                                                   clkdm->clktrctrl_mask);
949
 
 
950
 
        } else if (cpu_is_omap44xx()) {
951
 
 
952
 
                hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
953
 
                                                       clkdm->cm_inst,
954
 
                                                       clkdm->clkdm_offs);
955
 
 
956
 
        }
957
 
 
958
 
        if (hwsup) {
959
 
                /* Disable HW transitions when we are changing deps */
960
 
                _disable_hwsup(clkdm);
961
 
                _clkdm_add_autodeps(clkdm);
962
 
                _enable_hwsup(clkdm);
963
 
        } else {
964
 
                omap2_clkdm_wakeup(clkdm);
965
 
        }
966
 
 
 
836
        arch_clkdm->clkdm_clk_enable(clkdm);
967
837
        pwrdm_wait_transition(clkdm->pwrdm.ptr);
968
838
        pwrdm_clkdm_state_switch(clkdm);
969
839
 
971
841
}
972
842
 
973
843
/**
974
 
 * omap2_clkdm_clk_disable - remove an enabled downstream clock from this clkdm
 
844
 * clkdm_clk_disable - remove an enabled downstream clock from this clkdm
975
845
 * @clkdm: struct clockdomain *
976
846
 * @clk: struct clk * of the disabled downstream clock
977
847
 *
984
854
 * is enabled; or returns 0 upon success or if the clockdomain is in
985
855
 * hwsup idle mode.
986
856
 */
987
 
int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 
857
int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
988
858
{
989
 
        bool hwsup = false;
990
 
 
991
859
        /*
992
860
         * XXX Rewrite this code to maintain a list of enabled
993
861
         * downstream clocks for debugging purposes?
996
864
        if (!clkdm || !clk)
997
865
                return -EINVAL;
998
866
 
 
867
        if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable)
 
868
                return -EINVAL;
 
869
 
999
870
#ifdef DEBUG
1000
871
        if (atomic_read(&clkdm->usecount) == 0) {
1001
872
                WARN_ON(1); /* underflow */
1011
882
        pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
1012
883
                 clk->name);
1013
884
 
1014
 
        if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
1015
 
 
1016
 
                if (!clkdm->clktrctrl_mask)
1017
 
                        return 0;
1018
 
 
1019
 
                hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
1020
 
                                                   clkdm->clktrctrl_mask);
1021
 
 
1022
 
        } else if (cpu_is_omap44xx()) {
1023
 
 
1024
 
                hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
1025
 
                                                       clkdm->cm_inst,
1026
 
                                                       clkdm->clkdm_offs);
1027
 
 
1028
 
        }
1029
 
 
1030
 
        if (hwsup) {
1031
 
                /* Disable HW transitions when we are changing deps */
1032
 
                _disable_hwsup(clkdm);
1033
 
                _clkdm_del_autodeps(clkdm);
1034
 
                _enable_hwsup(clkdm);
1035
 
        } else {
1036
 
                omap2_clkdm_sleep(clkdm);
1037
 
        }
1038
 
 
 
885
        arch_clkdm->clkdm_clk_disable(clkdm);
1039
886
        pwrdm_clkdm_state_switch(clkdm);
1040
887
 
1041
888
        return 0;