diff options
author | Tony Lindgren <tony@atomide.com> | 2006-09-25 06:27:20 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2006-09-25 06:27:20 -0400 |
commit | 90afd5cb2ac0977c38e83b6b21493da911b242b3 (patch) | |
tree | 7d0dedf7bfedb76e9bb2149f7f8aec1aaed159f9 /arch | |
parent | 1630b52ddf4fc27e0dc421a57e4788bf9d3886cc (diff) |
ARM: OMAP: Sync clocks with linux-omap tree
Mostly clean up CONFIG_OMAP_RESET_CLOCKS. Also includes a
patch from Imre Deak to make McSPI clocks use id.
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-omap1/clock.c | 107 | ||||
-rw-r--r-- | arch/arm/mach-omap1/clock.h | 14 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 39 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock.h | 18 | ||||
-rw-r--r-- | arch/arm/plat-omap/clock.c | 25 |
5 files changed, 116 insertions, 87 deletions
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index f1958e882e86..638490e62d5f 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
21 | 21 | ||
22 | #include <asm/io.h> | 22 | #include <asm/io.h> |
23 | #include <asm/mach-types.h> | ||
23 | 24 | ||
24 | #include <asm/arch/cpu.h> | 25 | #include <asm/arch/cpu.h> |
25 | #include <asm/arch/usb.h> | 26 | #include <asm/arch/usb.h> |
@@ -586,77 +587,53 @@ static int omap1_clk_set_rate(struct clk *clk, unsigned long rate) | |||
586 | *-------------------------------------------------------------------------*/ | 587 | *-------------------------------------------------------------------------*/ |
587 | 588 | ||
588 | #ifdef CONFIG_OMAP_RESET_CLOCKS | 589 | #ifdef CONFIG_OMAP_RESET_CLOCKS |
589 | /* | ||
590 | * Resets some clocks that may be left on from bootloader, | ||
591 | * but leaves serial clocks on. See also omap_late_clk_reset(). | ||
592 | */ | ||
593 | static inline void omap1_early_clk_reset(void) | ||
594 | { | ||
595 | //omap_writel(0x3 << 29, MOD_CONF_CTRL_0); | ||
596 | } | ||
597 | 590 | ||
598 | static int __init omap1_late_clk_reset(void) | 591 | static void __init omap1_clk_disable_unused(struct clk *clk) |
599 | { | 592 | { |
600 | /* Turn off all unused clocks */ | ||
601 | struct clk *p; | ||
602 | __u32 regval32; | 593 | __u32 regval32; |
603 | 594 | ||
604 | /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */ | 595 | /* Clocks in the DSP domain need api_ck. Just assume bootloader |
605 | regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4); | 596 | * has not enabled any DSP clocks */ |
606 | omap_writew(regval32, SOFT_REQ_REG); | 597 | if ((u32)clk->enable_reg == DSP_IDLECT2) { |
607 | omap_writew(0, SOFT_REQ_REG2); | 598 | printk(KERN_INFO "Skipping reset check for DSP domain " |
608 | 599 | "clock \"%s\"\n", clk->name); | |
609 | list_for_each_entry(p, &clocks, node) { | 600 | return; |
610 | if (p->usecount > 0 || (p->flags & ALWAYS_ENABLED) || | 601 | } |
611 | p->enable_reg == 0) | ||
612 | continue; | ||
613 | |||
614 | /* Clocks in the DSP domain need api_ck. Just assume bootloader | ||
615 | * has not enabled any DSP clocks */ | ||
616 | if ((u32)p->enable_reg == DSP_IDLECT2) { | ||
617 | printk(KERN_INFO "Skipping reset check for DSP domain " | ||
618 | "clock \"%s\"\n", p->name); | ||
619 | continue; | ||
620 | } | ||
621 | 602 | ||
622 | /* Is the clock already disabled? */ | 603 | /* Is the clock already disabled? */ |
623 | if (p->flags & ENABLE_REG_32BIT) { | 604 | if (clk->flags & ENABLE_REG_32BIT) { |
624 | if (p->flags & VIRTUAL_IO_ADDRESS) | 605 | if (clk->flags & VIRTUAL_IO_ADDRESS) |
625 | regval32 = __raw_readl(p->enable_reg); | 606 | regval32 = __raw_readl(clk->enable_reg); |
626 | else | ||
627 | regval32 = omap_readl(p->enable_reg); | ||
628 | } else { | ||
629 | if (p->flags & VIRTUAL_IO_ADDRESS) | ||
630 | regval32 = __raw_readw(p->enable_reg); | ||
631 | else | 607 | else |
632 | regval32 = omap_readw(p->enable_reg); | 608 | regval32 = omap_readl(clk->enable_reg); |
633 | } | 609 | } else { |
634 | 610 | if (clk->flags & VIRTUAL_IO_ADDRESS) | |
635 | if ((regval32 & (1 << p->enable_bit)) == 0) | 611 | regval32 = __raw_readw(clk->enable_reg); |
636 | continue; | 612 | else |
613 | regval32 = omap_readw(clk->enable_reg); | ||
614 | } | ||
637 | 615 | ||
638 | /* FIXME: This clock seems to be necessary but no-one | 616 | if ((regval32 & (1 << clk->enable_bit)) == 0) |
639 | * has asked for its activation. */ | 617 | return; |
640 | if (p == &tc2_ck // FIX: pm.c (SRAM), CCP, Camera | ||
641 | || p == &ck_dpll1out.clk // FIX: SoSSI, SSR | ||
642 | || p == &arm_gpio_ck // FIX: GPIO code for 1510 | ||
643 | ) { | ||
644 | printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n", | ||
645 | p->name); | ||
646 | continue; | ||
647 | } | ||
648 | 618 | ||
649 | printk(KERN_INFO "Disabling unused clock \"%s\"... ", p->name); | 619 | /* FIXME: This clock seems to be necessary but no-one |
650 | p->disable(p); | 620 | * has asked for its activation. */ |
651 | printk(" done\n"); | 621 | if (clk == &tc2_ck // FIX: pm.c (SRAM), CCP, Camera |
622 | || clk == &ck_dpll1out.clk // FIX: SoSSI, SSR | ||
623 | || clk == &arm_gpio_ck // FIX: GPIO code for 1510 | ||
624 | ) { | ||
625 | printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n", | ||
626 | clk->name); | ||
627 | return; | ||
652 | } | 628 | } |
653 | 629 | ||
654 | return 0; | 630 | printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name); |
631 | clk->disable(clk); | ||
632 | printk(" done\n"); | ||
655 | } | 633 | } |
656 | late_initcall(omap1_late_clk_reset); | ||
657 | 634 | ||
658 | #else | 635 | #else |
659 | #define omap1_early_clk_reset() {} | 636 | #define omap1_clk_disable_unused NULL |
660 | #endif | 637 | #endif |
661 | 638 | ||
662 | static struct clk_functions omap1_clk_functions = { | 639 | static struct clk_functions omap1_clk_functions = { |
@@ -664,6 +641,7 @@ static struct clk_functions omap1_clk_functions = { | |||
664 | .clk_disable = omap1_clk_disable, | 641 | .clk_disable = omap1_clk_disable, |
665 | .clk_round_rate = omap1_clk_round_rate, | 642 | .clk_round_rate = omap1_clk_round_rate, |
666 | .clk_set_rate = omap1_clk_set_rate, | 643 | .clk_set_rate = omap1_clk_set_rate, |
644 | .clk_disable_unused = omap1_clk_disable_unused, | ||
667 | }; | 645 | }; |
668 | 646 | ||
669 | int __init omap1_clk_init(void) | 647 | int __init omap1_clk_init(void) |
@@ -671,8 +649,13 @@ int __init omap1_clk_init(void) | |||
671 | struct clk ** clkp; | 649 | struct clk ** clkp; |
672 | const struct omap_clock_config *info; | 650 | const struct omap_clock_config *info; |
673 | int crystal_type = 0; /* Default 12 MHz */ | 651 | int crystal_type = 0; /* Default 12 MHz */ |
652 | u32 reg; | ||
653 | |||
654 | /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */ | ||
655 | reg = omap_readw(SOFT_REQ_REG) & (1 << 4); | ||
656 | omap_writew(reg, SOFT_REQ_REG); | ||
657 | omap_writew(0, SOFT_REQ_REG2); | ||
674 | 658 | ||
675 | omap1_early_clk_reset(); | ||
676 | clk_init(&omap1_clk_functions); | 659 | clk_init(&omap1_clk_functions); |
677 | 660 | ||
678 | /* By default all idlect1 clocks are allowed to idle */ | 661 | /* By default all idlect1 clocks are allowed to idle */ |
@@ -772,6 +755,12 @@ int __init omap1_clk_init(void) | |||
772 | omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL); | 755 | omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL); |
773 | #endif | 756 | #endif |
774 | 757 | ||
758 | /* Amstrad Delta wants BCLK high when inactive */ | ||
759 | if (machine_is_ams_delta()) | ||
760 | omap_writel(omap_readl(ULPD_CLOCK_CTRL) | | ||
761 | (1 << SDW_MCLK_INV_BIT), | ||
762 | ULPD_CLOCK_CTRL); | ||
763 | |||
775 | /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */ | 764 | /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */ |
776 | /* (on 730, bit 13 must not be cleared) */ | 765 | /* (on 730, bit 13 must not be cleared) */ |
777 | if (cpu_is_omap730()) | 766 | if (cpu_is_omap730()) |
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index b7c68819c4e7..f7df00205c4a 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h | |||
@@ -89,6 +89,7 @@ struct arm_idlect1_clk { | |||
89 | #define EN_DSPTIMCK 5 | 89 | #define EN_DSPTIMCK 5 |
90 | 90 | ||
91 | /* Various register defines for clock controls scattered around OMAP chip */ | 91 | /* Various register defines for clock controls scattered around OMAP chip */ |
92 | #define SDW_MCLK_INV_BIT 2 /* In ULPD_CLKC_CTRL */ | ||
92 | #define USB_MCLK_EN_BIT 4 /* In ULPD_CLKC_CTRL */ | 93 | #define USB_MCLK_EN_BIT 4 /* In ULPD_CLKC_CTRL */ |
93 | #define USB_HOST_HHC_UHOST_EN 9 /* In MOD_CONF_CTRL_0 */ | 94 | #define USB_HOST_HHC_UHOST_EN 9 /* In MOD_CONF_CTRL_0 */ |
94 | #define SWD_ULPD_PLL_CLK_REQ 1 /* In SWD_CLK_DIV_CTRL_SEL */ | 95 | #define SWD_ULPD_PLL_CLK_REQ 1 /* In SWD_CLK_DIV_CTRL_SEL */ |
@@ -741,6 +742,18 @@ static struct clk i2c_fck = { | |||
741 | .disable = &omap1_clk_disable_generic, | 742 | .disable = &omap1_clk_disable_generic, |
742 | }; | 743 | }; |
743 | 744 | ||
745 | static struct clk i2c_ick = { | ||
746 | .name = "i2c_ick", | ||
747 | .id = 1, | ||
748 | .flags = CLOCK_IN_OMAP16XX | | ||
749 | VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT | | ||
750 | ALWAYS_ENABLED, | ||
751 | .parent = &armper_ck.clk, | ||
752 | .recalc = &followparent_recalc, | ||
753 | .enable = &omap1_clk_enable_generic, | ||
754 | .disable = &omap1_clk_disable_generic, | ||
755 | }; | ||
756 | |||
744 | static struct clk * onchip_clks[] = { | 757 | static struct clk * onchip_clks[] = { |
745 | /* non-ULPD clocks */ | 758 | /* non-ULPD clocks */ |
746 | &ck_ref, | 759 | &ck_ref, |
@@ -790,6 +803,7 @@ static struct clk * onchip_clks[] = { | |||
790 | /* Virtual clocks */ | 803 | /* Virtual clocks */ |
791 | &virtual_ck_mpu, | 804 | &virtual_ck_mpu, |
792 | &i2c_fck, | 805 | &i2c_fck, |
806 | &i2c_ick, | ||
793 | }; | 807 | }; |
794 | 808 | ||
795 | #endif | 809 | #endif |
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 26ac49ecb78d..0de201c3d50b 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c | |||
@@ -1025,12 +1025,29 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate) | |||
1025 | * Omap2 clock reset and init functions | 1025 | * Omap2 clock reset and init functions |
1026 | *-------------------------------------------------------------------------*/ | 1026 | *-------------------------------------------------------------------------*/ |
1027 | 1027 | ||
1028 | #ifdef CONFIG_OMAP_RESET_CLOCKS | ||
1029 | static void __init omap2_clk_disable_unused(struct clk *clk) | ||
1030 | { | ||
1031 | u32 regval32; | ||
1032 | |||
1033 | regval32 = __raw_readl(clk->enable_reg); | ||
1034 | if ((regval32 & (1 << clk->enable_bit)) == 0) | ||
1035 | return; | ||
1036 | |||
1037 | printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name); | ||
1038 | _omap2_clk_disable(clk); | ||
1039 | } | ||
1040 | #else | ||
1041 | #define omap2_clk_disable_unused NULL | ||
1042 | #endif | ||
1043 | |||
1028 | static struct clk_functions omap2_clk_functions = { | 1044 | static struct clk_functions omap2_clk_functions = { |
1029 | .clk_enable = omap2_clk_enable, | 1045 | .clk_enable = omap2_clk_enable, |
1030 | .clk_disable = omap2_clk_disable, | 1046 | .clk_disable = omap2_clk_disable, |
1031 | .clk_round_rate = omap2_clk_round_rate, | 1047 | .clk_round_rate = omap2_clk_round_rate, |
1032 | .clk_set_rate = omap2_clk_set_rate, | 1048 | .clk_set_rate = omap2_clk_set_rate, |
1033 | .clk_set_parent = omap2_clk_set_parent, | 1049 | .clk_set_parent = omap2_clk_set_parent, |
1050 | .clk_disable_unused = omap2_clk_disable_unused, | ||
1034 | }; | 1051 | }; |
1035 | 1052 | ||
1036 | static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys) | 1053 | static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys) |
@@ -1070,28 +1087,6 @@ void omap2_clk_prepare_for_reboot(void) | |||
1070 | clk_set_rate(vclk, rate); | 1087 | clk_set_rate(vclk, rate); |
1071 | } | 1088 | } |
1072 | 1089 | ||
1073 | #ifdef CONFIG_OMAP_RESET_CLOCKS | ||
1074 | static void __init omap2_disable_unused_clocks(void) | ||
1075 | { | ||
1076 | struct clk *ck; | ||
1077 | u32 regval32; | ||
1078 | |||
1079 | list_for_each_entry(ck, &clocks, node) { | ||
1080 | if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) || | ||
1081 | ck->enable_reg == 0) | ||
1082 | continue; | ||
1083 | |||
1084 | regval32 = __raw_readl(ck->enable_reg); | ||
1085 | if ((regval32 & (1 << ck->enable_bit)) == 0) | ||
1086 | continue; | ||
1087 | |||
1088 | printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name); | ||
1089 | _omap2_clk_disable(ck); | ||
1090 | } | ||
1091 | } | ||
1092 | late_initcall(omap2_disable_unused_clocks); | ||
1093 | #endif | ||
1094 | |||
1095 | /* | 1090 | /* |
1096 | * Switch the MPU rate if specified on cmdline. | 1091 | * Switch the MPU rate if specified on cmdline. |
1097 | * We cannot do this early until cmdline is parsed. | 1092 | * We cannot do this early until cmdline is parsed. |
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 223152d9663f..8816f5a33a28 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h | |||
@@ -1368,7 +1368,8 @@ static struct clk mcbsp5_fck = { | |||
1368 | }; | 1368 | }; |
1369 | 1369 | ||
1370 | static struct clk mcspi1_ick = { | 1370 | static struct clk mcspi1_ick = { |
1371 | .name = "mcspi1_ick", | 1371 | .name = "mcspi_ick", |
1372 | .id = 1, | ||
1372 | .parent = &l4_ck, | 1373 | .parent = &l4_ck, |
1373 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1374 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1374 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | 1375 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, |
@@ -1377,7 +1378,8 @@ static struct clk mcspi1_ick = { | |||
1377 | }; | 1378 | }; |
1378 | 1379 | ||
1379 | static struct clk mcspi1_fck = { | 1380 | static struct clk mcspi1_fck = { |
1380 | .name = "mcspi1_fck", | 1381 | .name = "mcspi_fck", |
1382 | .id = 1, | ||
1381 | .parent = &func_48m_ck, | 1383 | .parent = &func_48m_ck, |
1382 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1384 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1383 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | 1385 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, |
@@ -1386,7 +1388,8 @@ static struct clk mcspi1_fck = { | |||
1386 | }; | 1388 | }; |
1387 | 1389 | ||
1388 | static struct clk mcspi2_ick = { | 1390 | static struct clk mcspi2_ick = { |
1389 | .name = "mcspi2_ick", | 1391 | .name = "mcspi_ick", |
1392 | .id = 2, | ||
1390 | .parent = &l4_ck, | 1393 | .parent = &l4_ck, |
1391 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1394 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1392 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | 1395 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, |
@@ -1395,7 +1398,8 @@ static struct clk mcspi2_ick = { | |||
1395 | }; | 1398 | }; |
1396 | 1399 | ||
1397 | static struct clk mcspi2_fck = { | 1400 | static struct clk mcspi2_fck = { |
1398 | .name = "mcspi2_fck", | 1401 | .name = "mcspi_fck", |
1402 | .id = 2, | ||
1399 | .parent = &func_48m_ck, | 1403 | .parent = &func_48m_ck, |
1400 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1404 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1401 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | 1405 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, |
@@ -1404,7 +1408,8 @@ static struct clk mcspi2_fck = { | |||
1404 | }; | 1408 | }; |
1405 | 1409 | ||
1406 | static struct clk mcspi3_ick = { | 1410 | static struct clk mcspi3_ick = { |
1407 | .name = "mcspi3_ick", | 1411 | .name = "mcspi_ick", |
1412 | .id = 3, | ||
1408 | .parent = &l4_ck, | 1413 | .parent = &l4_ck, |
1409 | .flags = CLOCK_IN_OMAP243X, | 1414 | .flags = CLOCK_IN_OMAP243X, |
1410 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | 1415 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, |
@@ -1413,7 +1418,8 @@ static struct clk mcspi3_ick = { | |||
1413 | }; | 1418 | }; |
1414 | 1419 | ||
1415 | static struct clk mcspi3_fck = { | 1420 | static struct clk mcspi3_fck = { |
1416 | .name = "mcspi3_fck", | 1421 | .name = "mcspi_fck", |
1422 | .id = 3, | ||
1417 | .parent = &func_48m_ck, | 1423 | .parent = &func_48m_ck, |
1418 | .flags = CLOCK_IN_OMAP243X, | 1424 | .flags = CLOCK_IN_OMAP243X, |
1419 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | 1425 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, |
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 4abf2714f2d9..f1179ad4be1b 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c | |||
@@ -323,6 +323,31 @@ EXPORT_SYMBOL(clk_allow_idle); | |||
323 | 323 | ||
324 | /*-------------------------------------------------------------------------*/ | 324 | /*-------------------------------------------------------------------------*/ |
325 | 325 | ||
326 | #ifdef CONFIG_OMAP_RESET_CLOCKS | ||
327 | /* | ||
328 | * Disable any unused clocks left on by the bootloader | ||
329 | */ | ||
330 | static int __init clk_disable_unused(void) | ||
331 | { | ||
332 | struct clk *ck; | ||
333 | unsigned long flags; | ||
334 | |||
335 | list_for_each_entry(ck, &clocks, node) { | ||
336 | if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) || | ||
337 | ck->enable_reg == 0) | ||
338 | continue; | ||
339 | |||
340 | spin_lock_irqsave(&clockfw_lock, flags); | ||
341 | if (arch_clock->clk_disable_unused) | ||
342 | arch_clock->clk_disable_unused(ck); | ||
343 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
344 | } | ||
345 | |||
346 | return 0; | ||
347 | } | ||
348 | late_initcall(clk_disable_unused); | ||
349 | #endif | ||
350 | |||
326 | int __init clk_init(struct clk_functions * custom_clocks) | 351 | int __init clk_init(struct clk_functions * custom_clocks) |
327 | { | 352 | { |
328 | if (!custom_clocks) { | 353 | if (!custom_clocks) { |