3 * Copyright 2008 Free Software Foundation, Inc.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "memory_map.h"
33 // Set up basic clocking functions in AD9510
34 ad9510_write_reg(0x45, 0x00); // CLK2 drives distribution
36 clocks_enable_fpga_clk(true, 1);
40 // Set up PLL for 10 MHz reference
41 // Reg 4, A counter, Don't Care
42 ad9510_write_reg(0x05, 0x00); // Reg 5, B counter MSBs, 0
43 ad9510_write_reg(0x06, 0x05); // Reg 6, B counter LSBs, 5
44 // Reg 7, Loss of reference detect, doesn't work yet, 0
45 ad9510_write_reg(0x5A, 0x01); // Update Regs
48 // FIXME, probably need interface to this...
49 timesync_regs->tick_control = 4;
51 // Primary clock configuration
52 clocks_mimo_config(MC_WE_DONT_LOCK);
54 // Set up other clocks
55 clocks_enable_test_clk(false, 0);
56 clocks_enable_tx_dboard(false, 0);
57 clocks_enable_rx_dboard(false, 0);
58 clocks_enable_eth_phyclk(false, 0);
60 // Enable clock to ADCs and DACs
61 clocks_enable_dac_clk(true, 1);
62 clocks_enable_adc_clk(true, 1);
67 clocks_mimo_config(int flags)
69 if (flags & _MC_WE_LOCK){
70 // Reg 8, Charge pump on, dig lock det, positive PFD, 47
71 ad9510_write_reg(0x08, 0x47);
74 // Reg 8, Charge pump off, dig lock det, positive PFD
75 ad9510_write_reg(0x08, 0x00);
78 // Reg 9, Charge pump current, 0x40=3mA, 0x00=650uA
79 ad9510_write_reg(0x09, 0x00);
80 // Reg A, Prescaler of 2, everything normal 04
81 ad9510_write_reg(0x0A, 0x04);
82 // Reg B, R Div MSBs, 0
83 ad9510_write_reg(0x0B, 0x00);
84 // Reg C, R Div LSBs, 1
85 ad9510_write_reg(0x0C, 0x01);
86 // Reg D, Antibacklash, Digital lock det, 0
88 ad9510_write_reg(0x5A, 0x01); // Update Regs
92 // Allow for clock switchover
94 if (flags & _MC_WE_LOCK){ // WE LOCK
95 if (flags & _MC_MIMO_CLK_INPUT) {
96 // Turn on ref output and choose the MIMO connector
97 output_regs->clk_ctrl = 0x15;
100 // turn on ref output and choose the SMA
101 output_regs->clk_ctrl = 0x1C;
104 else { // WE DONT LOCK
105 // Disable both ext clk inputs
106 output_regs->clk_ctrl = 0x10;
109 // Do we drive a clock onto the MIMO connector?
110 if (flags & MC_PROVIDE_CLK_TO_MIMO)
111 clocks_enable_clkexp_out(true,10);
113 clocks_enable_clkexp_out(false,0);
119 if(pic_regs->pending & PIC_CLKSTATUS)
125 clocks_gen_div(int divisor)
133 #define CLOCK_OUT_EN 0x08
134 #define CLOCK_OUT_DIS_CMOS 0x01
135 #define CLOCK_OUT_DIS_PECL 0x02
136 #define CLOCK_DIV_DIS 0x80
137 #define CLOCK_DIV_EN 0x00
139 #define CLOCK_MODE_PECL 1
140 #define CLOCK_MODE_LVDS 2
141 #define CLOCK_MODE_CMOS 3
144 clocks_enable_XXX_clk(bool enable, int divisor, int reg_en, int reg_div, int mode)
146 int enable_word, div_word, div_en_word;
149 case CLOCK_MODE_PECL :
150 enable_word = enable ? 0x08 : 0x0A;
152 case CLOCK_MODE_LVDS :
153 enable_word = enable ? 0x02 : 0x03;
155 case CLOCK_MODE_CMOS :
156 enable_word = enable ? 0x08 : 0x09;
159 if(enable && (divisor>1)) {
160 div_word = clocks_gen_div(divisor);
161 div_en_word = CLOCK_DIV_EN;
165 div_en_word = CLOCK_DIV_DIS;
168 ad9510_write_reg(reg_en,enable_word); // Output en/dis
169 ad9510_write_reg(reg_div,div_word); // Set divisor
170 ad9510_write_reg(reg_div+1,div_en_word); // Enable or Bypass Divider
171 ad9510_write_reg(0x5A, 0x01); // Update Regs
176 clocks_enable_test_clk(bool enable, int divisor)
178 clocks_enable_XXX_clk(enable,divisor,0x3C,0x48,CLOCK_MODE_PECL);
183 clocks_enable_fpga_clk(bool enable, int divisor)
185 clocks_enable_XXX_clk(enable,divisor,0x3D,0x4A,CLOCK_MODE_PECL);
188 // Clock 2 on Rev 3, Clock 5 on Rev 4
190 clocks_enable_clkexp_out(bool enable, int divisor)
192 if(u2_hw_rev_major == 3)
193 clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL);
194 else if(u2_hw_rev_major == 4) {
195 ad9510_write_reg(0x34,0x00); // Turn on fine delay
196 ad9510_write_reg(0x35,0x00); // Set Full Scale to nearly 10ns
197 ad9510_write_reg(0x36,0x1c); // Set fine delay. 0x20 is midscale
198 clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS);
202 putstr("ERR: Invalid Rev\n");
205 // Clock 5 on Rev 3, none (was 2) on Rev 4
207 clocks_enable_eth_phyclk(bool enable, int divisor)
209 if(u2_hw_rev_major == 3)
210 clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS);
211 else if(u2_hw_rev_major == 4)
212 clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL);
214 putstr("ERR: Invalid Rev\n");
219 clocks_enable_dac_clk(bool enable, int divisor)
221 clocks_enable_XXX_clk(enable,divisor,0x3F,0x4E,CLOCK_MODE_PECL);
226 clocks_enable_adc_clk(bool enable, int divisor)
228 clocks_enable_XXX_clk(enable,divisor,0x40,0x50,CLOCK_MODE_LVDS);
233 clocks_enable_tx_dboard(bool enable, int divisor)
235 clocks_enable_XXX_clk(enable,divisor,0x42,0x54,CLOCK_MODE_CMOS);
240 clocks_enable_rx_dboard(bool enable, int divisor)
242 clocks_enable_XXX_clk(enable,divisor,0x43,0x56,CLOCK_MODE_CMOS);