1/* 2 * OMAP4 clockdomain control 3 * 4 * Copyright (C) 2008-2010 Texas Instruments, Inc. 5 * Copyright (C) 2008-2010 Nokia Corporation 6 * 7 * Derived from mach-omap2/clockdomain.c written by Paul Walmsley 8 * Rajendra Nayak <rnayak@ti.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15#include <linux/kernel.h> 16#include "clockdomain.h" 17#include "cminst44xx.h" 18#include "cm44xx.h" 19 20static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1, 21 struct clockdomain *clkdm2) 22{ 23 omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit), 24 clkdm1->prcm_partition, 25 clkdm1->cm_inst, clkdm1->clkdm_offs + 26 OMAP4_CM_STATICDEP); 27 return 0; 28} 29 30static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1, 31 struct clockdomain *clkdm2) 32{ 33 omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit), 34 clkdm1->prcm_partition, 35 clkdm1->cm_inst, clkdm1->clkdm_offs + 36 OMAP4_CM_STATICDEP); 37 return 0; 38} 39 40static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1, 41 struct clockdomain *clkdm2) 42{ 43 return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition, 44 clkdm1->cm_inst, clkdm1->clkdm_offs + 45 OMAP4_CM_STATICDEP, 46 (1 << clkdm2->dep_bit)); 47} 48 49static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm) 50{ 51 struct clkdm_dep *cd; 52 u32 mask = 0; 53 54 for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { 55 if (!cd->clkdm) 56 continue; /* only happens if data is erroneous */ 57 58 mask |= 1 << cd->clkdm->dep_bit; 59 atomic_set(&cd->wkdep_usecount, 0); 60 } 61 62 omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition, 63 clkdm->cm_inst, clkdm->clkdm_offs + 64 OMAP4_CM_STATICDEP); 65 return 0; 66} 67 68static int omap4_clkdm_sleep(struct clockdomain *clkdm) 69{ 70 omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition, 71 clkdm->cm_inst, clkdm->clkdm_offs); 72 return 0; 73} 74 75static int omap4_clkdm_wakeup(struct clockdomain *clkdm) 76{ 77 omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition, 78 clkdm->cm_inst, clkdm->clkdm_offs); 79 return 0; 80} 81 82static void omap4_clkdm_allow_idle(struct clockdomain *clkdm) 83{ 84 omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, 85 clkdm->cm_inst, clkdm->clkdm_offs); 86} 87 88static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) 89{ 90 omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition, 91 clkdm->cm_inst, clkdm->clkdm_offs); 92} 93 94static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) 95{ 96 if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) 97 return omap4_clkdm_wakeup(clkdm); 98 99 return 0; 100} 101 102static int omap4_clkdm_clk_disable(struct clockdomain *clkdm) 103{ 104 bool hwsup = false; 105 106 hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, 107 clkdm->cm_inst, clkdm->clkdm_offs); 108 109 if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) 110 omap4_clkdm_sleep(clkdm); 111 112 return 0; 113} 114 115struct clkdm_ops omap4_clkdm_operations = { 116 .clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep, 117 .clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep, 118 .clkdm_read_wkdep = omap4_clkdm_read_wkup_sleep_dep, 119 .clkdm_clear_all_wkdeps = omap4_clkdm_clear_all_wkup_sleep_deps, 120 .clkdm_add_sleepdep = omap4_clkdm_add_wkup_sleep_dep, 121 .clkdm_del_sleepdep = omap4_clkdm_del_wkup_sleep_dep, 122 .clkdm_read_sleepdep = omap4_clkdm_read_wkup_sleep_dep, 123 .clkdm_clear_all_sleepdeps = omap4_clkdm_clear_all_wkup_sleep_deps, 124 .clkdm_sleep = omap4_clkdm_sleep, 125 .clkdm_wakeup = omap4_clkdm_wakeup, 126 .clkdm_allow_idle = omap4_clkdm_allow_idle, 127 .clkdm_deny_idle = omap4_clkdm_deny_idle, 128 .clkdm_clk_enable = omap4_clkdm_clk_enable, 129 .clkdm_clk_disable = omap4_clkdm_clk_disable, 130}; 131