calc_deltaf

名称

calc_deltaf - ETC クロックの誤差を求める

書式

static int64_t
calc_deltaf(
    mic_ctx_t * mic_ctx);

引数

mic_ctx
誤差を求めるETCを持つカードの context

説明

引数 mic_ctx で指定されたカードの ETC の、仕様値 15.625 MHz からの誤差を求める。

戻り値

ETC の基準クロック (15.625 MHz) からの誤差。単位 Hz。

参照

  • XXX

実装

host/driver/uos_download.c
103 static int64_t
104 calc_deltaf(mic_ctx_t *mic_ctx)
105 {
106         const int64_t ETC_CLK_FREQ = 15625000;
107         const uint32_t TIME_DELAY_IN_SEC = 10;
108         const int64_t etc_cnt1 = ETC_CLK_FREQ * TIME_DELAY_IN_SEC;
109         int64_t etc_cnt2;
110
111         unsigned long cnt1, cnt2;
112         int64_t deltaf_in_ppm, deltaf;
113
114         /*
115          * (etc_freq2 / etc_freq1) = (etc_count2 / etc_count1)
116          * etc_freq1 = ETC_CLK_FREQ
117          * => etc_count1 = TIME_DELAY_IN_SEC * ETC_CLK_FREQ
118          * (etc_freq2 / etc_freq1) = (etc_count2 / etc_count1)
119          * etc_freq2 = etc_freq1 * (etc_count2 / etc_count1)
120          * etc_freq2 - etc_freq1 = etc_freq1((etc_count2 / etc_count1) - 1)
121          * deltaf = etc_freq1(etc_count2 - etc_count1)/etc_count1
122          * deltaf_in_ppm = deltaf * 10 ^ 6 / etc_freq1
123          * deltaf_in_ppm = ((etc_count2 - etc_count1) * 10 ^ 6) / etc_count1
124          */
125         unsigned long flags;
126         /* Need to implement the monotonic/irqsave logic for windows */
127         struct timespec ts1, ts2;
128         int64_t mono_ns;
129         local_irq_save(flags);
130         cnt1 = etc_read(mic_ctx->mmio.va);
131         getrawmonotonic(&ts1);
132         local_irq_restore(flags);
133
134         mdelay(TIME_DELAY_IN_SEC * 1000);
135
136         local_irq_save(flags);
137         cnt2 = etc_read(mic_ctx->mmio.va);
138         getrawmonotonic(&ts2);
139         local_irq_restore(flags);
140         etc_cnt2 = cnt2 - cnt1;
141         ts2 = timespec_sub(ts2, ts1);
142         mono_ns = timespec_to_ns(&ts2);
143         /* Recalculate etc_cnt2 based on getrawmonotonic */
144         etc_cnt2 = (etc_cnt2 * TIME_DELAY_IN_SEC * 1000 * 1000 * 1000) / mono_ns;
145         deltaf = ( ETC_CLK_FREQ * (etc_cnt2 - etc_cnt1)) / etc_cnt1;
146         deltaf_in_ppm = (1000 * 1000 * (etc_cnt2 - etc_cnt1)) / etc_cnt1;
147         pr_debug("etc deltaf: %lld\n", deltaf);
148         /*
149          * For intel chipsets, Spread Spectrum Clocking (SSC) (in the limit)
150          * is downspread with a frequency of 30hz and an amplitude of 0.5%
151          * which translates to 2500ppm. This is also the ppm observed on KNC + CrownPass
152          * Hence, if ppm > 2500, the code would need to retry to eliminate any chance of error
153          * Added an error margin of 1ppm (etc mmio reads can take really long time)
154          */
155         if (deltaf_in_ppm > 2501 || deltaf_in_ppm < -2501)
156                 printk(KERN_ERR "ETC timer compensation(%lldppm) is much higher"
157                                         "than expected\n", deltaf_in_ppm);
158
159         return deltaf;
160 }
最終更新:2012年11月25日 15:56