1 /* 2 * linux/arch/arm/mach-omap2/clock.c 3 * 4 * Copyright (C) 2005-2008 Texas Instruments, Inc. 5 * Copyright (C) 2004-2010 Nokia Corporation 6 * 7 * Contacts: 8 * Richard Woodruff <r-woodruff2@ti.com> 9 * Paul Walmsley 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 */ 15 #undef DEBUG 16 17 #include <linux/kernel.h> 18 #include <linux/export.h> 19 #include <linux/list.h> 20 #include <linux/errno.h> 21 #include <linux/err.h> 22 #include <linux/delay.h> 23 #include <linux/clk.h> 24 #include <linux/clk-provider.h> 25 #include <linux/io.h> 26 #include <linux/bitops.h> 27 #include <linux/of_address.h> 28 #include <asm/cpu.h> 29 30 #include <trace/events/power.h> 31 32 #include "soc.h" 33 #include "clockdomain.h" 34 #include "clock.h" 35 #include "cm.h" 36 #include "cm2xxx.h" 37 #include "cm3xxx.h" 38 #include "cm-regbits-24xx.h" 39 #include "cm-regbits-34xx.h" 40 #include "common.h" 41 42 u16 cpu_mask; 43 44 /* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */ 45 #define OMAP3430_DPLL_FINT_BAND1_MIN 750000 46 #define OMAP3430_DPLL_FINT_BAND1_MAX 2100000 47 #define OMAP3430_DPLL_FINT_BAND2_MIN 7500000 48 #define OMAP3430_DPLL_FINT_BAND2_MAX 21000000 49 50 /* 51 * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx. 52 * From device data manual section 4.3 "DPLL and DLL Specifications". 53 */ 54 #define OMAP3PLUS_DPLL_FINT_MIN 32000 55 #define OMAP3PLUS_DPLL_FINT_MAX 52000000 56 57 static struct ti_clk_ll_ops omap_clk_ll_ops = { 58 .clkdm_clk_enable = clkdm_clk_enable, 59 .clkdm_clk_disable = clkdm_clk_disable, 60 .cm_wait_module_ready = omap_cm_wait_module_ready, 61 .cm_split_idlest_reg = cm_split_idlest_reg, 62 }; 63 64 /** 65 * omap2_clk_setup_ll_ops - setup clock driver low-level ops 66 * 67 * Sets up clock driver low-level platform ops. These are needed 68 * for register accesses and various other misc platform operations. 69 * Returns 0 on success, -EBUSY if low level ops have been registered 70 * already. 71 */ 72 int __init omap2_clk_setup_ll_ops(void) 73 { 74 return ti_clk_setup_ll_ops(&omap_clk_ll_ops); 75 } 76 77 /* 78 * OMAP2+ specific clock functions 79 */ 80 81 /* Public functions */ 82 83 /** 84 * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk 85 * @clk: OMAP clock struct ptr to use 86 * 87 * Convert a clockdomain name stored in a struct clk 'clk' into a 88 * clockdomain pointer, and save it into the struct clk. Intended to be 89 * called during clk_register(). No return value. 90 */ 91 void omap2_init_clk_clkdm(struct clk_hw *hw) 92 { 93 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 94 struct clockdomain *clkdm; 95 const char *clk_name; 96 97 if (!clk->clkdm_name) 98 return; 99 100 clk_name = __clk_get_name(hw->clk); 101 102 clkdm = clkdm_lookup(clk->clkdm_name); 103 if (clkdm) { 104 pr_debug("clock: associated clk %s to clkdm %s\n", 105 clk_name, clk->clkdm_name); 106 clk->clkdm = clkdm; 107 } else { 108 pr_debug("clock: could not associate clk %s to clkdm %s\n", 109 clk_name, clk->clkdm_name); 110 } 111 } 112 113 /** 114 * ti_clk_init_features - init clock features struct for the SoC 115 * 116 * Initializes the clock features struct based on the SoC type. 117 */ 118 void __init ti_clk_init_features(void) 119 { 120 struct ti_clk_features features = { 0 }; 121 /* Fint setup for DPLLs */ 122 if (cpu_is_omap3430()) { 123 features.fint_min = OMAP3430_DPLL_FINT_BAND1_MIN; 124 features.fint_max = OMAP3430_DPLL_FINT_BAND2_MAX; 125 features.fint_band1_max = OMAP3430_DPLL_FINT_BAND1_MAX; 126 features.fint_band2_min = OMAP3430_DPLL_FINT_BAND2_MIN; 127 } else { 128 features.fint_min = OMAP3PLUS_DPLL_FINT_MIN; 129 features.fint_max = OMAP3PLUS_DPLL_FINT_MAX; 130 } 131 132 /* Bypass value setup for DPLLs */ 133 if (cpu_is_omap24xx()) { 134 features.dpll_bypass_vals |= 135 (1 << OMAP2XXX_EN_DPLL_LPBYPASS) | 136 (1 << OMAP2XXX_EN_DPLL_FRBYPASS); 137 } else if (cpu_is_omap34xx()) { 138 features.dpll_bypass_vals |= 139 (1 << OMAP3XXX_EN_DPLL_LPBYPASS) | 140 (1 << OMAP3XXX_EN_DPLL_FRBYPASS); 141 } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx() || 142 soc_is_omap54xx() || soc_is_dra7xx()) { 143 features.dpll_bypass_vals |= 144 (1 << OMAP4XXX_EN_DPLL_LPBYPASS) | 145 (1 << OMAP4XXX_EN_DPLL_FRBYPASS) | 146 (1 << OMAP4XXX_EN_DPLL_MNBYPASS); 147 } 148 149 /* Jitter correction only available on OMAP343X */ 150 if (cpu_is_omap343x()) 151 features.flags |= TI_CLK_DPLL_HAS_FREQSEL; 152 153 /* Idlest value for interface clocks. 154 * 24xx uses 0 to indicate not ready, and 1 to indicate ready. 155 * 34xx reverses this, just to keep us on our toes 156 * AM35xx uses both, depending on the module. 157 */ 158 if (cpu_is_omap24xx()) 159 features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL; 160 else if (cpu_is_omap34xx()) 161 features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL; 162 163 /* On OMAP3430 ES1.0, DPLL4 can't be re-programmed */ 164 if (omap_rev() == OMAP3430_REV_ES1_0) 165 features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM; 166 167 /* Errata I810 for omap5 / dra7 */ 168 if (soc_is_omap54xx() || soc_is_dra7xx()) 169 features.flags |= TI_CLK_ERRATA_I810; 170 171 ti_clk_setup_features(&features); 172 } 173