1 /* 2 * Copyright 2008-2013 Freescale Semiconductor Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution. 11 * * Neither the name of Freescale Semiconductor nor the 12 * names of its contributors may be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * 16 * ALTERNATIVELY, this software may be distributed under the terms of the 17 * GNU General Public License ("GPL") as published by the Free Software 18 * Foundation, either version 2 of that License or (at your option) any 19 * later version. 20 * 21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "fsl_fman_rtc.h" 34 35 void fman_rtc_defconfig(struct rtc_cfg *cfg) 36 { 37 int i; 38 cfg->src_clk = DEFAULT_SRC_CLOCK; 39 cfg->invert_input_clk_phase = DEFAULT_INVERT_INPUT_CLK_PHASE; 40 cfg->invert_output_clk_phase = DEFAULT_INVERT_OUTPUT_CLK_PHASE; 41 cfg->pulse_realign = DEFAULT_PULSE_REALIGN; 42 for (i = 0; i < FMAN_RTC_MAX_NUM_OF_ALARMS; i++) 43 cfg->alarm_polarity[i] = DEFAULT_ALARM_POLARITY; 44 for (i = 0; i < FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS; i++) 45 cfg->trigger_polarity[i] = DEFAULT_TRIGGER_POLARITY; 46 } 47 48 uint32_t fman_rtc_get_events(struct rtc_regs *regs) 49 { 50 return ioread32be(®s->tmr_tevent); 51 } 52 53 uint32_t fman_rtc_get_event(struct rtc_regs *regs, uint32_t ev_mask) 54 { 55 return ioread32be(®s->tmr_tevent) & ev_mask; 56 } 57 58 uint32_t fman_rtc_get_interrupt_mask(struct rtc_regs *regs) 59 { 60 return ioread32be(®s->tmr_temask); 61 } 62 63 void fman_rtc_set_interrupt_mask(struct rtc_regs *regs, uint32_t mask) 64 { 65 iowrite32be(mask, ®s->tmr_temask); 66 } 67 68 void fman_rtc_ack_event(struct rtc_regs *regs, uint32_t events) 69 { 70 iowrite32be(events, ®s->tmr_tevent); 71 } 72 73 uint32_t fman_rtc_check_and_clear_event(struct rtc_regs *regs) 74 { 75 uint32_t event; 76 77 event = ioread32be(®s->tmr_tevent); 78 event &= ioread32be(®s->tmr_temask); 79 80 if (event) 81 iowrite32be(event, ®s->tmr_tevent); 82 return event; 83 } 84 85 uint32_t fman_rtc_get_frequency_compensation(struct rtc_regs *regs) 86 { 87 return ioread32be(®s->tmr_add); 88 } 89 90 void fman_rtc_set_frequency_compensation(struct rtc_regs *regs, uint32_t val) 91 { 92 iowrite32be(val, ®s->tmr_add); 93 } 94 95 void fman_rtc_enable_interupt(struct rtc_regs *regs, uint32_t events) 96 { 97 fman_rtc_set_interrupt_mask(regs, fman_rtc_get_interrupt_mask(regs) | events); 98 } 99 100 void fman_rtc_disable_interupt(struct rtc_regs *regs, uint32_t events) 101 { 102 fman_rtc_set_interrupt_mask(regs, fman_rtc_get_interrupt_mask(regs) & ~events); 103 } 104 105 void fman_rtc_set_timer_alarm_l(struct rtc_regs *regs, int index, uint32_t val) 106 { 107 iowrite32be(val, ®s->tmr_alarm[index].tmr_alarm_l); 108 } 109 110 void fman_rtc_set_timer_fiper(struct rtc_regs *regs, int index, uint32_t val) 111 { 112 iowrite32be(val, ®s->tmr_fiper[index]); 113 } 114 115 void fman_rtc_set_timer_alarm(struct rtc_regs *regs, int index, int64_t val) 116 { 117 iowrite32be((uint32_t)val, ®s->tmr_alarm[index].tmr_alarm_l); 118 iowrite32be((uint32_t)(val >> 32), ®s->tmr_alarm[index].tmr_alarm_h); 119 } 120 121 void fman_rtc_set_timer_offset(struct rtc_regs *regs, int64_t val) 122 { 123 iowrite32be((uint32_t)val, ®s->tmr_off_l); 124 iowrite32be((uint32_t)(val >> 32), ®s->tmr_off_h); 125 } 126 127 uint64_t fman_rtc_get_trigger_stamp(struct rtc_regs *regs, int id) 128 { 129 uint64_t time; 130 /* TMR_CNT_L must be read first to get an accurate value */ 131 time = (uint64_t)ioread32be(®s->tmr_etts[id].tmr_etts_l); 132 time |= ((uint64_t)ioread32be(®s->tmr_etts[id].tmr_etts_h) 133 << 32); 134 135 return time; 136 } 137 138 uint32_t fman_rtc_get_timer_ctrl(struct rtc_regs *regs) 139 { 140 return ioread32be(®s->tmr_ctrl); 141 } 142 143 void fman_rtc_set_timer_ctrl(struct rtc_regs *regs, uint32_t val) 144 { 145 iowrite32be(val, ®s->tmr_ctrl); 146 } 147 148 void fman_rtc_timers_soft_reset(struct rtc_regs *regs) 149 { 150 fman_rtc_set_timer_ctrl(regs, FMAN_RTC_TMR_CTRL_TMSR); 151 DELAY(10); 152 fman_rtc_set_timer_ctrl(regs, 0); 153 } 154 155 void fman_rtc_init(struct rtc_cfg *cfg, struct rtc_regs *regs, int num_alarms, 156 int num_fipers, int num_ext_triggers, bool init_freq_comp, 157 uint32_t freq_compensation, uint32_t output_clock_divisor) 158 { 159 uint32_t tmr_ctrl; 160 int i; 161 162 fman_rtc_timers_soft_reset(regs); 163 164 /* Set the source clock */ 165 switch (cfg->src_clk) { 166 case E_FMAN_RTC_SOURCE_CLOCK_SYSTEM: 167 tmr_ctrl = FMAN_RTC_TMR_CTRL_CKSEL_MAC_CLK; 168 break; 169 case E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR: 170 tmr_ctrl = FMAN_RTC_TMR_CTRL_CKSEL_OSC_CLK; 171 break; 172 default: 173 /* Use a clock from the External TMR reference clock.*/ 174 tmr_ctrl = FMAN_RTC_TMR_CTRL_CKSEL_EXT_CLK; 175 break; 176 } 177 178 /* whatever period the user picked, the timestamp will advance in '1' 179 * every time the period passed. */ 180 tmr_ctrl |= ((1 << FMAN_RTC_TMR_CTRL_TCLK_PERIOD_SHIFT) & 181 FMAN_RTC_TMR_CTRL_TCLK_PERIOD_MASK); 182 183 if (cfg->invert_input_clk_phase) 184 tmr_ctrl |= FMAN_RTC_TMR_CTRL_CIPH; 185 if (cfg->invert_output_clk_phase) 186 tmr_ctrl |= FMAN_RTC_TMR_CTRL_COPH; 187 188 for (i = 0; i < num_alarms; i++) { 189 if (cfg->alarm_polarity[i] == 190 E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW) 191 tmr_ctrl |= (FMAN_RTC_TMR_CTRL_ALMP1 >> i); 192 } 193 194 for (i = 0; i < num_ext_triggers; i++) 195 if (cfg->trigger_polarity[i] == 196 E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE) 197 tmr_ctrl |= (FMAN_RTC_TMR_CTRL_ETEP1 << i); 198 199 if (!cfg->timer_slave_mode && cfg->bypass) 200 tmr_ctrl |= FMAN_RTC_TMR_CTRL_BYP; 201 202 fman_rtc_set_timer_ctrl(regs, tmr_ctrl); 203 if (init_freq_comp) 204 fman_rtc_set_frequency_compensation(regs, freq_compensation); 205 206 /* Clear TMR_ALARM registers */ 207 for (i = 0; i < num_alarms; i++) 208 fman_rtc_set_timer_alarm(regs, i, 0xFFFFFFFFFFFFFFFFLL); 209 210 /* Clear TMR_TEVENT */ 211 fman_rtc_ack_event(regs, FMAN_RTC_TMR_TEVENT_ALL); 212 213 /* Initialize TMR_TEMASK */ 214 fman_rtc_set_interrupt_mask(regs, 0); 215 216 /* Clear TMR_FIPER registers */ 217 for (i = 0; i < num_fipers; i++) 218 fman_rtc_set_timer_fiper(regs, i, 0xFFFFFFFF); 219 220 /* Initialize TMR_PRSC */ 221 iowrite32be(output_clock_divisor, ®s->tmr_prsc); 222 223 /* Clear TMR_OFF */ 224 fman_rtc_set_timer_offset(regs, 0); 225 } 226 227 bool fman_rtc_is_enabled(struct rtc_regs *regs) 228 { 229 return (bool)(fman_rtc_get_timer_ctrl(regs) & FMAN_RTC_TMR_CTRL_TE); 230 } 231 232 void fman_rtc_enable(struct rtc_regs *regs, bool reset_clock) 233 { 234 uint32_t tmr_ctrl = fman_rtc_get_timer_ctrl(regs); 235 236 /* TODO check that no timestamping MACs are working in this stage. */ 237 if (reset_clock) { 238 fman_rtc_set_timer_ctrl(regs, (tmr_ctrl | FMAN_RTC_TMR_CTRL_TMSR)); 239 240 DELAY(10); 241 /* Clear TMR_OFF */ 242 fman_rtc_set_timer_offset(regs, 0); 243 } 244 245 fman_rtc_set_timer_ctrl(regs, (tmr_ctrl | FMAN_RTC_TMR_CTRL_TE)); 246 } 247 248 void fman_rtc_disable(struct rtc_regs *regs) 249 { 250 fman_rtc_set_timer_ctrl(regs, (fman_rtc_get_timer_ctrl(regs) 251 & ~(FMAN_RTC_TMR_CTRL_TE))); 252 } 253 254 void fman_rtc_clear_periodic_pulse(struct rtc_regs *regs, int id) 255 { 256 uint32_t tmp_reg; 257 if (id == 0) 258 tmp_reg = FMAN_RTC_TMR_TEVENT_PP1; 259 else 260 tmp_reg = FMAN_RTC_TMR_TEVENT_PP2; 261 fman_rtc_disable_interupt(regs, tmp_reg); 262 263 tmp_reg = fman_rtc_get_timer_ctrl(regs); 264 if (tmp_reg & FMAN_RTC_TMR_CTRL_FS) 265 fman_rtc_set_timer_ctrl(regs, tmp_reg & ~FMAN_RTC_TMR_CTRL_FS); 266 267 fman_rtc_set_timer_fiper(regs, id, 0xFFFFFFFF); 268 } 269 270 void fman_rtc_clear_external_trigger(struct rtc_regs *regs, int id) 271 { 272 uint32_t tmpReg, tmp_ctrl; 273 274 if (id == 0) 275 tmpReg = FMAN_RTC_TMR_TEVENT_ETS1; 276 else 277 tmpReg = FMAN_RTC_TMR_TEVENT_ETS2; 278 fman_rtc_disable_interupt(regs, tmpReg); 279 280 if (id == 0) 281 tmpReg = FMAN_RTC_TMR_CTRL_PP1L; 282 else 283 tmpReg = FMAN_RTC_TMR_CTRL_PP2L; 284 tmp_ctrl = fman_rtc_get_timer_ctrl(regs); 285 if (tmp_ctrl & tmpReg) 286 fman_rtc_set_timer_ctrl(regs, tmp_ctrl & ~tmpReg); 287 } 288 289 void fman_rtc_set_alarm(struct rtc_regs *regs, int id, uint32_t val, bool enable) 290 { 291 uint32_t tmpReg; 292 fman_rtc_set_timer_alarm(regs, id, val); 293 if (enable) { 294 if (id == 0) 295 tmpReg = FMAN_RTC_TMR_TEVENT_ALM1; 296 else 297 tmpReg = FMAN_RTC_TMR_TEVENT_ALM2; 298 fman_rtc_enable_interupt(regs, tmpReg); 299 } 300 } 301 302 void fman_rtc_set_periodic_pulse(struct rtc_regs *regs, int id, uint32_t val, 303 bool enable) 304 { 305 uint32_t tmpReg; 306 fman_rtc_set_timer_fiper(regs, id, val); 307 if (enable) { 308 if (id == 0) 309 tmpReg = FMAN_RTC_TMR_TEVENT_PP1; 310 else 311 tmpReg = FMAN_RTC_TMR_TEVENT_PP2; 312 fman_rtc_enable_interupt(regs, tmpReg); 313 } 314 } 315 316 void fman_rtc_set_ext_trigger(struct rtc_regs *regs, int id, bool enable, 317 bool use_pulse_as_input) 318 { 319 uint32_t tmpReg; 320 if (enable) { 321 if (id == 0) 322 tmpReg = FMAN_RTC_TMR_TEVENT_ETS1; 323 else 324 tmpReg = FMAN_RTC_TMR_TEVENT_ETS2; 325 fman_rtc_enable_interupt(regs, tmpReg); 326 } 327 if (use_pulse_as_input) { 328 if (id == 0) 329 tmpReg = FMAN_RTC_TMR_CTRL_PP1L; 330 else 331 tmpReg = FMAN_RTC_TMR_CTRL_PP2L; 332 fman_rtc_set_timer_ctrl(regs, fman_rtc_get_timer_ctrl(regs) | tmpReg); 333 } 334 } 335