1 /* 2 * AM33XX CM functions 3 * 4 * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ 5 * Vaibhav Hiremath <hvaibhav@ti.com> 6 * 7 * Reference taken from from OMAP4 cminst44xx.c 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation version 2. 12 * 13 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 14 * kind, whether express or implied; without even the implied warranty 15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 */ 18 19 #include <linux/kernel.h> 20 #include <linux/types.h> 21 #include <linux/errno.h> 22 #include <linux/err.h> 23 #include <linux/io.h> 24 25 #include "clockdomain.h" 26 #include "cm.h" 27 #include "cm33xx.h" 28 #include "cm-regbits-34xx.h" 29 #include "cm-regbits-33xx.h" 30 #include "prm33xx.h" 31 32 /* 33 * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield: 34 * 35 * 0x0 func: Module is fully functional, including OCP 36 * 0x1 trans: Module is performing transition: wakeup, or sleep, or sleep 37 * abortion 38 * 0x2 idle: Module is in Idle mode (only OCP part). It is functional if 39 * using separate functional clock 40 * 0x3 disabled: Module is disabled and cannot be accessed 41 * 42 */ 43 #define CLKCTRL_IDLEST_FUNCTIONAL 0x0 44 #define CLKCTRL_IDLEST_INTRANSITION 0x1 45 #define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2 46 #define CLKCTRL_IDLEST_DISABLED 0x3 47 48 /* Private functions */ 49 50 /* Read a register in a CM instance */ 51 static inline u32 am33xx_cm_read_reg(u16 inst, u16 idx) 52 { 53 return readl_relaxed(cm_base + inst + idx); 54 } 55 56 /* Write into a register in a CM */ 57 static inline void am33xx_cm_write_reg(u32 val, u16 inst, u16 idx) 58 { 59 writel_relaxed(val, cm_base + inst + idx); 60 } 61 62 /* Read-modify-write a register in CM */ 63 static inline u32 am33xx_cm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx) 64 { 65 u32 v; 66 67 v = am33xx_cm_read_reg(inst, idx); 68 v &= ~mask; 69 v |= bits; 70 am33xx_cm_write_reg(v, inst, idx); 71 72 return v; 73 } 74 75 static inline u32 am33xx_cm_set_reg_bits(u32 bits, s16 inst, s16 idx) 76 { 77 return am33xx_cm_rmw_reg_bits(bits, bits, inst, idx); 78 } 79 80 static inline u32 am33xx_cm_clear_reg_bits(u32 bits, s16 inst, s16 idx) 81 { 82 return am33xx_cm_rmw_reg_bits(bits, 0x0, inst, idx); 83 } 84 85 static inline u32 am33xx_cm_read_reg_bits(u16 inst, s16 idx, u32 mask) 86 { 87 u32 v; 88 89 v = am33xx_cm_read_reg(inst, idx); 90 v &= mask; 91 v >>= __ffs(mask); 92 93 return v; 94 } 95 96 /** 97 * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield 98 * @inst: CM instance register offset (*_INST macro) 99 * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) 100 * 101 * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to 102 * bit 0. 103 */ 104 static u32 _clkctrl_idlest(u16 inst, u16 clkctrl_offs) 105 { 106 u32 v = am33xx_cm_read_reg(inst, clkctrl_offs); 107 v &= AM33XX_IDLEST_MASK; 108 v >>= AM33XX_IDLEST_SHIFT; 109 return v; 110 } 111 112 /** 113 * _is_module_ready - can module registers be accessed without causing an abort? 114 * @inst: CM instance register offset (*_INST macro) 115 * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) 116 * 117 * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either 118 * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise. 119 */ 120 static bool _is_module_ready(u16 inst, u16 clkctrl_offs) 121 { 122 u32 v; 123 124 v = _clkctrl_idlest(inst, clkctrl_offs); 125 126 return (v == CLKCTRL_IDLEST_FUNCTIONAL || 127 v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false; 128 } 129 130 /** 131 * _clktrctrl_write - write @c to a CM_CLKSTCTRL.CLKTRCTRL register bitfield 132 * @c: CLKTRCTRL register bitfield (LSB = bit 0, i.e., unshifted) 133 * @inst: CM instance register offset (*_INST macro) 134 * @cdoffs: Clockdomain register offset (*_CDOFFS macro) 135 * 136 * @c must be the unshifted value for CLKTRCTRL - i.e., this function 137 * will handle the shift itself. 138 */ 139 static void _clktrctrl_write(u8 c, u16 inst, u16 cdoffs) 140 { 141 u32 v; 142 143 v = am33xx_cm_read_reg(inst, cdoffs); 144 v &= ~AM33XX_CLKTRCTRL_MASK; 145 v |= c << AM33XX_CLKTRCTRL_SHIFT; 146 am33xx_cm_write_reg(v, inst, cdoffs); 147 } 148 149 /* Public functions */ 150 151 /** 152 * am33xx_cm_is_clkdm_in_hwsup - is a clockdomain in hwsup idle mode? 153 * @inst: CM instance register offset (*_INST macro) 154 * @cdoffs: Clockdomain register offset (*_CDOFFS macro) 155 * 156 * Returns true if the clockdomain referred to by (@inst, @cdoffs) 157 * is in hardware-supervised idle mode, or 0 otherwise. 158 */ 159 static bool am33xx_cm_is_clkdm_in_hwsup(u16 inst, u16 cdoffs) 160 { 161 u32 v; 162 163 v = am33xx_cm_read_reg(inst, cdoffs); 164 v &= AM33XX_CLKTRCTRL_MASK; 165 v >>= AM33XX_CLKTRCTRL_SHIFT; 166 167 return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? true : false; 168 } 169 170 /** 171 * am33xx_cm_clkdm_enable_hwsup - put a clockdomain in hwsup-idle mode 172 * @inst: CM instance register offset (*_INST macro) 173 * @cdoffs: Clockdomain register offset (*_CDOFFS macro) 174 * 175 * Put a clockdomain referred to by (@inst, @cdoffs) into 176 * hardware-supervised idle mode. No return value. 177 */ 178 static void am33xx_cm_clkdm_enable_hwsup(u16 inst, u16 cdoffs) 179 { 180 _clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, inst, cdoffs); 181 } 182 183 /** 184 * am33xx_cm_clkdm_disable_hwsup - put a clockdomain in swsup-idle mode 185 * @inst: CM instance register offset (*_INST macro) 186 * @cdoffs: Clockdomain register offset (*_CDOFFS macro) 187 * 188 * Put a clockdomain referred to by (@inst, @cdoffs) into 189 * software-supervised idle mode, i.e., controlled manually by the 190 * Linux OMAP clockdomain code. No return value. 191 */ 192 static void am33xx_cm_clkdm_disable_hwsup(u16 inst, u16 cdoffs) 193 { 194 _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, inst, cdoffs); 195 } 196 197 /** 198 * am33xx_cm_clkdm_force_sleep - try to put a clockdomain into idle 199 * @inst: CM instance register offset (*_INST macro) 200 * @cdoffs: Clockdomain register offset (*_CDOFFS macro) 201 * 202 * Put a clockdomain referred to by (@inst, @cdoffs) into idle 203 * No return value. 204 */ 205 static void am33xx_cm_clkdm_force_sleep(u16 inst, u16 cdoffs) 206 { 207 _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, inst, cdoffs); 208 } 209 210 /** 211 * am33xx_cm_clkdm_force_wakeup - try to take a clockdomain out of idle 212 * @inst: CM instance register offset (*_INST macro) 213 * @cdoffs: Clockdomain register offset (*_CDOFFS macro) 214 * 215 * Take a clockdomain referred to by (@inst, @cdoffs) out of idle, 216 * waking it up. No return value. 217 */ 218 static void am33xx_cm_clkdm_force_wakeup(u16 inst, u16 cdoffs) 219 { 220 _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, inst, cdoffs); 221 } 222 223 /* 224 * 225 */ 226 227 /** 228 * am33xx_cm_wait_module_ready - wait for a module to be in 'func' state 229 * @part: PRCM partition, ignored for AM33xx 230 * @inst: CM instance register offset (*_INST macro) 231 * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) 232 * @bit_shift: bit shift for the register, ignored for AM33xx 233 * 234 * Wait for the module IDLEST to be functional. If the idle state is in any 235 * the non functional state (trans, idle or disabled), module and thus the 236 * sysconfig cannot be accessed and will probably lead to an "imprecise 237 * external abort" 238 */ 239 static int am33xx_cm_wait_module_ready(u8 part, s16 inst, u16 clkctrl_offs, 240 u8 bit_shift) 241 { 242 int i = 0; 243 244 omap_test_timeout(_is_module_ready(inst, clkctrl_offs), 245 MAX_MODULE_READY_TIME, i); 246 247 return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; 248 } 249 250 /** 251 * am33xx_cm_wait_module_idle - wait for a module to be in 'disabled' 252 * state 253 * @part: CM partition, ignored for AM33xx 254 * @inst: CM instance register offset (*_INST macro) 255 * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) 256 * @bit_shift: bit shift for the register, ignored for AM33xx 257 * 258 * Wait for the module IDLEST to be disabled. Some PRCM transition, 259 * like reset assertion or parent clock de-activation must wait the 260 * module to be fully disabled. 261 */ 262 static int am33xx_cm_wait_module_idle(u8 part, s16 inst, u16 clkctrl_offs, 263 u8 bit_shift) 264 { 265 int i = 0; 266 267 if (!clkctrl_offs) 268 return 0; 269 270 omap_test_timeout((_clkctrl_idlest(inst, clkctrl_offs) == 271 CLKCTRL_IDLEST_DISABLED), 272 MAX_MODULE_READY_TIME, i); 273 274 return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; 275 } 276 277 /** 278 * am33xx_cm_module_enable - Enable the modulemode inside CLKCTRL 279 * @mode: Module mode (SW or HW) 280 * @part: CM partition, ignored for AM33xx 281 * @inst: CM instance register offset (*_INST macro) 282 * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) 283 * 284 * No return value. 285 */ 286 static void am33xx_cm_module_enable(u8 mode, u8 part, u16 inst, 287 u16 clkctrl_offs) 288 { 289 u32 v; 290 291 v = am33xx_cm_read_reg(inst, clkctrl_offs); 292 v &= ~AM33XX_MODULEMODE_MASK; 293 v |= mode << AM33XX_MODULEMODE_SHIFT; 294 am33xx_cm_write_reg(v, inst, clkctrl_offs); 295 } 296 297 /** 298 * am33xx_cm_module_disable - Disable the module inside CLKCTRL 299 * @part: CM partition, ignored for AM33xx 300 * @inst: CM instance register offset (*_INST macro) 301 * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) 302 * 303 * No return value. 304 */ 305 static void am33xx_cm_module_disable(u8 part, u16 inst, u16 clkctrl_offs) 306 { 307 u32 v; 308 309 v = am33xx_cm_read_reg(inst, clkctrl_offs); 310 v &= ~AM33XX_MODULEMODE_MASK; 311 am33xx_cm_write_reg(v, inst, clkctrl_offs); 312 } 313 314 /* 315 * Clockdomain low-level functions 316 */ 317 318 static int am33xx_clkdm_sleep(struct clockdomain *clkdm) 319 { 320 am33xx_cm_clkdm_force_sleep(clkdm->cm_inst, clkdm->clkdm_offs); 321 return 0; 322 } 323 324 static int am33xx_clkdm_wakeup(struct clockdomain *clkdm) 325 { 326 am33xx_cm_clkdm_force_wakeup(clkdm->cm_inst, clkdm->clkdm_offs); 327 return 0; 328 } 329 330 static void am33xx_clkdm_allow_idle(struct clockdomain *clkdm) 331 { 332 am33xx_cm_clkdm_enable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs); 333 } 334 335 static void am33xx_clkdm_deny_idle(struct clockdomain *clkdm) 336 { 337 am33xx_cm_clkdm_disable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs); 338 } 339 340 static int am33xx_clkdm_clk_enable(struct clockdomain *clkdm) 341 { 342 if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) 343 return am33xx_clkdm_wakeup(clkdm); 344 345 return 0; 346 } 347 348 static int am33xx_clkdm_clk_disable(struct clockdomain *clkdm) 349 { 350 bool hwsup = false; 351 352 hwsup = am33xx_cm_is_clkdm_in_hwsup(clkdm->cm_inst, clkdm->clkdm_offs); 353 354 if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) 355 am33xx_clkdm_sleep(clkdm); 356 357 return 0; 358 } 359 360 struct clkdm_ops am33xx_clkdm_operations = { 361 .clkdm_sleep = am33xx_clkdm_sleep, 362 .clkdm_wakeup = am33xx_clkdm_wakeup, 363 .clkdm_allow_idle = am33xx_clkdm_allow_idle, 364 .clkdm_deny_idle = am33xx_clkdm_deny_idle, 365 .clkdm_clk_enable = am33xx_clkdm_clk_enable, 366 .clkdm_clk_disable = am33xx_clkdm_clk_disable, 367 }; 368 369 static struct cm_ll_data am33xx_cm_ll_data = { 370 .wait_module_ready = &am33xx_cm_wait_module_ready, 371 .wait_module_idle = &am33xx_cm_wait_module_idle, 372 .module_enable = &am33xx_cm_module_enable, 373 .module_disable = &am33xx_cm_module_disable, 374 }; 375 376 int __init am33xx_cm_init(void) 377 { 378 return cm_register(&am33xx_cm_ll_data); 379 } 380 381 static void __exit am33xx_cm_exit(void) 382 { 383 cm_unregister(&am33xx_cm_ll_data); 384 } 385 __exitcall(am33xx_cm_exit); 386