remove stale programmer.py
[litex.git] / software / videomixer / pll.c
1 #include <stdio.h>
2 #include <generated/csr.h>
3
4 #include "pll.h"
5
6 /*
7 * Despite varying pixel clocks, we must keep the PLL VCO operating
8 * in the specified range of 400MHz - 1000MHz.
9 * This code can program two sets of DRP data:
10 * 1. with VCO operating at 20x the pixel clock (for 20MHz - 50MHz pixel clock)
11 * 2. with VCO operating at 10x the pixel clock (for 40MHz - 100MHz pixel clock)
12 */
13
14 static const unsigned short int pll_config_20x[32] = {
15 0x0006, 0x0008, 0x0000, 0x4400, 0x1708, 0x0097, 0x0501, 0x8288,
16 0x4201, 0x0d90, 0x00a1, 0x0111, 0x1004, 0x2028, 0x0802, 0x2800,
17 0x0288, 0x8058, 0x020c, 0x0200, 0x1210, 0x400b, 0xfc21, 0x0b21,
18 0x7f5f, 0xc0eb, 0x472a, 0xc02a, 0x20b6, 0x0e96, 0x1002, 0xd6ce
19 };
20
21 static const unsigned short int pll_config_10x[32] = {
22 0x0006, 0x0008, 0x0000, 0x4400, 0x1708, 0x0097, 0x0901, 0x8118,
23 0x4181, 0x0d60, 0x00a1, 0x0111, 0x1004, 0x2028, 0x0802, 0x0608,
24 0x0148, 0x8018, 0x020c, 0x0200, 0x1210, 0x400b, 0xfc21, 0x0b22,
25 0x5fdf, 0x40eb, 0x472b, 0xc02a, 0x20b6, 0x0e96, 0x1002, 0xd6ce
26 };
27
28 static void program_data(const unsigned short *data)
29 {
30 int i;
31
32 /*
33 * Some bits of words 4 and 5 appear to depend on PLL location,
34 * so we start at word 6.
35 * PLLs also seem to dislike any write to the last words.
36 */
37 for(i=6;i<32-5;i++) {
38 fb_driver_clocking_pll_adr_write(i);
39 fb_driver_clocking_pll_dat_w_write(data[i]);
40 fb_driver_clocking_pll_write_write(1);
41 while(!fb_driver_clocking_pll_drdy_read());
42 }
43 for(i=6;i<32-5;i++) {
44 dvisampler0_clocking_pll_adr_write(i);
45 dvisampler0_clocking_pll_dat_w_write(data[i]);
46 dvisampler0_clocking_pll_write_write(1);
47 while(!dvisampler0_clocking_pll_drdy_read());
48 }
49 for(i=6;i<32-5;i++) {
50 dvisampler1_clocking_pll_adr_write(i);
51 dvisampler1_clocking_pll_dat_w_write(data[i]);
52 dvisampler1_clocking_pll_write_write(1);
53 while(!dvisampler1_clocking_pll_drdy_read());
54 }
55 }
56
57 void pll_config_for_clock(int freq)
58 {
59 /*
60 * FIXME:
61 * 10x configuration causes random IDELAY lockups (at high frequencies it seems)
62 * 20x configuration seems to always work, even with overclocked VCO
63 * Reproducible both with DRP and initial reconfiguration.
64 * Until this spartan6 weirdness is sorted out, just stick to 20x.
65 */
66 program_data(pll_config_20x);
67 #ifdef XILINX_SPARTAN6_WORKS_AMAZINGLY_WELL
68 if(freq < 2000)
69 printf("Frequency too low for PLLs\n");
70 else if(freq < 4500)
71 program_data(pll_config_20x);
72 else if(freq < 10000)
73 program_data(pll_config_10x);
74 else
75 printf("Frequency too high for PLLs\n");
76 #endif
77 }
78
79 void pll_dump(void)
80 {
81 int i;
82
83 printf("framebuffer PLL:\n");
84 for(i=0;i<32;i++) {
85 fb_driver_clocking_pll_adr_write(i);
86 fb_driver_clocking_pll_read_write(1);
87 while(!fb_driver_clocking_pll_drdy_read());
88 printf("%04x ", fb_driver_clocking_pll_dat_r_read());
89 }
90 printf("\n");
91 printf("dvisampler0 PLL:\n");
92 for(i=0;i<32;i++) {
93 dvisampler0_clocking_pll_adr_write(i);
94 dvisampler0_clocking_pll_read_write(1);
95 while(!dvisampler0_clocking_pll_drdy_read());
96 printf("%04x ", dvisampler0_clocking_pll_dat_r_read());
97 }
98 printf("\n");
99 printf("dvisampler1 PLL:\n");
100 for(i=0;i<32;i++) {
101 dvisampler1_clocking_pll_adr_write(i);
102 dvisampler1_clocking_pll_read_write(1);
103 while(!dvisampler1_clocking_pll_drdy_read());
104 printf("%04x ", dvisampler1_clocking_pll_dat_r_read());
105 }
106 printf("\n");
107 }