The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/ncsw/Peripherals/FM/Rtc/fman_rtc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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(&regs->tmr_tevent);
   51 }
   52 
   53 uint32_t fman_rtc_get_event(struct rtc_regs *regs, uint32_t ev_mask)
   54 {
   55         return ioread32be(&regs->tmr_tevent) & ev_mask;
   56 }
   57 
   58 uint32_t fman_rtc_get_interrupt_mask(struct rtc_regs *regs)
   59 {
   60         return ioread32be(&regs->tmr_temask);
   61 }
   62 
   63 void fman_rtc_set_interrupt_mask(struct rtc_regs *regs, uint32_t mask)
   64 {
   65         iowrite32be(mask, &regs->tmr_temask);
   66 }
   67 
   68 void fman_rtc_ack_event(struct rtc_regs *regs, uint32_t events)
   69 {
   70         iowrite32be(events, &regs->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(&regs->tmr_tevent);
   78         event &= ioread32be(&regs->tmr_temask);
   79 
   80         if (event)
   81                 iowrite32be(event, &regs->tmr_tevent);
   82         return event;
   83 }
   84 
   85 uint32_t fman_rtc_get_frequency_compensation(struct rtc_regs *regs)
   86 {
   87         return ioread32be(&regs->tmr_add);
   88 }
   89 
   90 void fman_rtc_set_frequency_compensation(struct rtc_regs *regs, uint32_t val)
   91 {
   92         iowrite32be(val, &regs->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, &regs->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, &regs->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, &regs->tmr_alarm[index].tmr_alarm_l);
  118         iowrite32be((uint32_t)(val >> 32), &regs->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, &regs->tmr_off_l);
  124         iowrite32be((uint32_t)(val >> 32), &regs->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(&regs->tmr_etts[id].tmr_etts_l);
  132         time |= ((uint64_t)ioread32be(&regs->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(&regs->tmr_ctrl);
  141 }
  142 
  143 void fman_rtc_set_timer_ctrl(struct rtc_regs *regs, uint32_t val)
  144 {
  145         iowrite32be(val, &regs->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, &regs->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 }

Cache object: da4dd3cfc7d71be27f567ba680dda7c0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.