netfilter: Fix wrong backporting
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / autotst / mipi_dsih_dphy.c
1 /**\r
2  * @file mipi_dsih_dphy.c\r
3  * @brief D-PHY driver\r
4  *\r
5  *  Synopsys Inc.\r
6  *  SG DWC PT02\r
7  */\r
8 #include "mipi_dsih_dphy.h"\r
9 #define PRECISION_FACTOR                (1000)\r
10 /* Reference clock frequency divided by Input Frequency Division Ratio LIMITS */\r
11 #define DPHY_DIV_UPPER_LIMIT    (40000)\r
12 #ifdef GEN_2\r
13 #define DPHY_DIV_LOWER_LIMIT    (5000)\r
14 #else\r
15 #define DPHY_DIV_LOWER_LIMIT    (1000)\r
16 #endif\r
17 \r
18 #if ((defined DWC_MIPI_DPHY_BIDIR_TSMC40LP) || (defined GEN_2))\r
19 #define MIN_OUTPUT_FREQ                 (80)\r
20 #elif defined DPHY2Btql\r
21 #define MIN_OUTPUT_FREQ                 (200)\r
22 #undef GEN_2\r
23 #endif\r
24 \r
25 /**\r
26  * Initialise D-PHY module and power up\r
27  * @param phy pointer to structure which holds information about the d-phy\r
28  * module\r
29  * @return error code\r
30  */\r
31 dsih_error_t mipi_dsih_dphy_open(dphy_t * phy)\r
32 {\r
33         if (phy == 0)\r
34         {\r
35                 return ERR_DSI_PHY_INVALID;\r
36         }\r
37         else if ((phy->core_read_function == 0) || (phy->core_write_function == 0))\r
38         {\r
39                 return ERR_DSI_INVALID_IO;\r
40         }\r
41         else if (phy->status == INITIALIZED)\r
42         {\r
43                 return ERR_DSI_PHY_INVALID;\r
44         }\r
45         phy->status = NOT_INITIALIZED;\r
46 #if 0\r
47         mipi_dsih_dphy_reset(phy, 0);\r
48         mipi_dsih_dphy_stop_wait_time(phy, 0x1C);\r
49         mipi_dsih_dphy_no_of_lanes(phy, 1);\r
50         mipi_dsih_dphy_clock_en(phy, 1);\r
51         mipi_dsih_dphy_shutdown(phy, 1);\r
52         mipi_dsih_dphy_reset(phy, 1);\r
53 #endif\r
54         phy->status = INITIALIZED;\r
55         return OK;\r
56 }\r
57 /**\r
58  * Configure D-PHY and PLL module to desired operation mode\r
59  * @param phy pointer to structure which holds information about the d-phy\r
60  * module\r
61  * @param no_of_lanes active\r
62  * @param output_freq desired high speed frequency\r
63  * @return error code\r
64  */\r
65  #ifdef GEN_2\r
66 dsih_error_t mipi_dsih_dphy_configure(dphy_t * phy, uint8_t no_of_lanes, uint32_t output_freq)\r
67 {\r
68     uint32_t loop_divider = 0; /* (M) */\r
69     uint32_t input_divider = 1; /* (N) */\r
70     uint8_t data[4]; /* maximum data for now are 4 bytes per test mode*/\r
71     uint8_t no_of_bytes = 0;\r
72     uint8_t i = 0;\r
73     uint8_t n=0;/* iterator */\r
74     uint8_t range = 0; /* ranges iterator */\r
75     int flag = 0;\r
76         struct\r
77         {\r
78                 uint32_t loop_div; /* upper limit of loop divider range */\r
79                 uint8_t cp_current; /* icpctrl */\r
80                 uint8_t lpf_resistor; /* lpfctrl */\r
81         }\r
82         loop_bandwidth[] =\r
83 \r
84         {       /* gen 2 associates the charge pump current and LPF resistor with the\r
85                  output frequency ranges (and thus we simplify here to use the\r
86                  counter/pointer of the following structure) */\r
87                 {  90, 0x02, 0x02}, { 100, 0x02, 0x02}, { 110, 0x02, 0x02},\r
88                 { 130, 0x02, 0x01}, { 140, 0x02, 0x01}, { 150, 0x02, 0x01},\r
89                 { 170, 0x09, 0x00}, { 180, 0x09, 0x01}, { 200, 0x09, 0x01},\r
90                 { 220, 0x09, 0x04}, { 240, 0x09, 0x04}, { 250, 0x09, 0x04},\r
91                 { 270, 0x06, 0x04}, { 300, 0x06, 0x04}, { 330, 0x09, 0x04},\r
92                 { 360, 0x09, 0x04}, { 400, 0x09, 0x04}, { 450, 0x06, 0x04},\r
93                 { 500, 0x06, 0x04}, { 550, 0x06, 0x04}, { 600, 0x06, 0x04},\r
94                 { 650, 0x0A, 0x04}, { 700, 0x0A, 0x04}, { 750, 0x0A, 0x04},\r
95                 { 800, 0x0A, 0x04}, { 850, 0x0A, 0x04}, { 900, 0x0A, 0x04},\r
96                 { 950, 0x0B, 0x08}, {1000, 0x0B, 0x08}, {1050, 0x0B, 0x08},\r
97                 {1100, 0x0B, 0x08}, {1150, 0x0B, 0x08}, {1200, 0x0B, 0x08},\r
98                 {1250, 0x0B, 0x08}, {1300, 0x0B, 0x08}, {1350, 0x0B, 0x08},\r
99                 {1400, 0x0B, 0x08}, {1450, 0x0B, 0x08}, {1500, 0x0B, 0x08}\r
100         };\r
101         uint32_t delta = 0;\r
102         uint32_t tmp_loop_divider = 0;\r
103         unsigned step = 0;\r
104 \r
105     struct\r
106     {\r
107         uint32_t freq;  /* upper margin of frequency range */\r
108         uint8_t hs_freq; /* hsfreqrange */\r
109         uint8_t vco_range; /* vcorange */\r
110     }\r
111     ranges[] =\r
112         {\r
113                 {  90, 0x00, 0x00}, { 100, 0x10, 0x00}, { 110, 0x20, 0x00},\r
114                 { 130, 0x01, 0x00}, { 140, 0x11, 0x00}, { 150, 0x21, 0x00},\r
115                 { 170, 0x02, 0x00}, { 180, 0x12, 0x00}, { 200, 0x22, 0x00},\r
116                 { 220, 0x03, 0x01}, { 240, 0x13, 0x01}, { 250, 0x23, 0x01},\r
117                 { 270, 0x04, 0x01}, { 300, 0x14, 0x01}, { 330, 0x05, 0x02},\r
118                 { 360, 0x15, 0x02}, { 400, 0x25, 0x02}, { 450, 0x06, 0x02},\r
119                 { 500, 0x16, 0x02}, { 550, 0x07, 0x03}, { 600, 0x17, 0x03},\r
120                 { 650, 0x08, 0x03}, { 700, 0x18, 0x03}, { 750, 0x09, 0x04},\r
121                 { 800, 0x19, 0x04}, { 850, 0x29, 0x04}, { 900, 0x39, 0x04},\r
122                 { 950, 0x0A, 0x05}, {1000, 0x1A, 0x05}, {1050, 0x2A, 0x05},\r
123                 {1100, 0x3A, 0x05}, {1150, 0x0B, 0x06}, {1200, 0x1B, 0x06},\r
124                 {1250, 0x2B, 0x06}, {1300, 0x3B, 0x06}, {1350, 0x0C, 0x07},\r
125                 {1400, 0x1C, 0x07}, {1450, 0x2C, 0x07}, {1500, 0x3C, 0x07}\r
126         };\r
127 \r
128     if (phy == 0)\r
129     {\r
130         return ERR_DSI_INVALID_INSTANCE;\r
131     }\r
132     if (phy->status < INITIALIZED)\r
133     {\r
134         return ERR_DSI_INVALID_INSTANCE;\r
135     }\r
136     if (output_freq < MIN_OUTPUT_FREQ)\r
137     {\r
138         return ERR_DSI_PHY_FREQ_OUT_OF_BOUND;\r
139     }\r
140 \r
141         loop_divider = ((output_freq * (phy->reference_freq / DPHY_DIV_LOWER_LIMIT)) / phy->reference_freq);\r
142         /* here delta will account for the rounding */\r
143         delta = ((loop_divider * phy->reference_freq) / (phy->reference_freq / DPHY_DIV_LOWER_LIMIT)) - output_freq;\r
144         for (input_divider = 1 + (phy->reference_freq / DPHY_DIV_UPPER_LIMIT); ((phy->reference_freq / input_divider) >= DPHY_DIV_LOWER_LIMIT) && (!flag); input_divider++)\r
145         {\r
146                 tmp_loop_divider = ((output_freq * input_divider) / (phy->reference_freq));\r
147                 if ((tmp_loop_divider % 2) == 0)\r
148                 {       /* if even */\r
149                         if (output_freq == (tmp_loop_divider * (phy->reference_freq / input_divider)))\r
150                         {       /* exact values found */\r
151                                 flag = 1;\r
152                                 loop_divider = tmp_loop_divider;\r
153                                 delta = output_freq - (tmp_loop_divider * (phy->reference_freq / input_divider));\r
154                                 /* variable was incremented before exiting the loop */\r
155                                 input_divider--;\r
156                         }\r
157                         if ((output_freq - (tmp_loop_divider * (phy->reference_freq / input_divider))) < delta)\r
158                         {       /* values found with smaller delta */\r
159                                 loop_divider = tmp_loop_divider;\r
160                                 delta = output_freq - (tmp_loop_divider * (phy->reference_freq / input_divider));\r
161                                 step = 1;\r
162                         }\r
163                 }\r
164                 else\r
165                 {\r
166                         tmp_loop_divider += 1;\r
167                         if (output_freq == (tmp_loop_divider * (phy->reference_freq / input_divider)))\r
168                         {       /* exact values found */\r
169                                 flag = 1;\r
170                                 loop_divider = tmp_loop_divider;\r
171                                 delta = (tmp_loop_divider * (phy->reference_freq / input_divider)) - output_freq;\r
172                                 /* variable was incremented before exiting the loop */\r
173                                 input_divider--;\r
174                         }\r
175                         if (((tmp_loop_divider * (phy->reference_freq / input_divider)) - output_freq) < delta)\r
176                         {       /* values found with smaller delta */\r
177                                 loop_divider = tmp_loop_divider;\r
178                                 delta = (tmp_loop_divider * (phy->reference_freq / input_divider)) - output_freq;\r
179                                 step = 0;\r
180                         }\r
181                 }\r
182         }\r
183         if (!flag)\r
184         {\r
185                 input_divider = step + (loop_divider * phy->reference_freq) / output_freq;\r
186 //              phy->log_info("D-PHY: Approximated Frequency: %d KHz", (loop_divider * (phy->reference_freq / input_divider)));\r
187         }\r
188 #ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING
189         if (phy->phy_keep_work != true)
190 #endif
191         {
192                 /* get the PHY in power down mode (shutdownz=0) and reset it (rstz=0) to
193                 avoid transient periods in PHY operation during re-configuration procedures. */
194                 mipi_dsih_dphy_reset(phy, 0);
195                 mipi_dsih_dphy_clock_en(phy, 0);
196                 mipi_dsih_dphy_shutdown(phy, 0);
197                 /* provide an initial active-high test clear pulse in TESTCLR  */
198                 mipi_dsih_dphy_test_clear(phy, 1);
199                 mipi_dsih_dphy_test_clear(phy, 0);
200                 for(n=0;n<100;n++){
201                                 ;
202                 }
203         }
204     /* find ranges */\r
205     for (range = 0; (range < (sizeof(ranges)/sizeof(ranges[0]))) && ((output_freq / 1000) > ranges[range].freq); range++)\r
206     {\r
207         ;\r
208     }\r
209     if (range >= (sizeof(ranges)/sizeof(ranges[0])))\r
210     {\r
211         return ERR_DSI_PHY_FREQ_OUT_OF_BOUND;\r
212     }\r
213     /* set up board depending on environment if any */\r
214     if (phy->bsp_pre_config != 0)\r
215     {\r
216         phy->bsp_pre_config(phy, 0);\r
217     }\r
218 \r
219   /* Jessica add - begin*/\r
220     data[0] =  0x83;//0x44;//0x44;//0x40;                 //0x40: ok for 200    clock lane lpx /*about 52ns*/\r
221     mipi_dsih_dphy_write(phy, 0x60, data, 1);\r
222 //    data[0] =  0x0; //0xA6;//0xC6;//0xC6;//0x86;                 //0x48: ok for 200     prepare time\r
223 //    mipi_dsih_dphy_write(phy, 0x61, data, 1);\r
224 \r
225 //    data[0] =  0x0;//0x6a;//0x6a;//0x4a;                  //0x4a: ok for 200    zero time\r
226 //    mipi_dsih_dphy_write(phy, 0x62, data, 1);\r
227 \r
228     data[0] =  0x83;//0x44;//0x40;//0x40;              // 0x40: ok for 200          data lane lpx /*about 52ns*/\r
229     mipi_dsih_dphy_write(phy, 0x70, data, 1);\r
230 \r
231 //    data[0] = 0x0;// 0x84;//0x96;//0x96;//0x86;                //0x48: ok for 200         prepare time\r
232 //    mipi_dsih_dphy_write(phy, 0x71, data, 1);\r
233 \r
234 //    data[0] =  0x0;//0x44;//0x44;//0x40;               //0x4a: ok for 200          zero time\r
235 //    mipi_dsih_dphy_write(phy, 0x72, data, 1);\r
236 \r
237     //data[0] =  0x44;\r
238     //mipi_dsih_dphy_write(phy, 0x73, data, 1);\r
239 \r
240     //data[0] =  0x7F;\r
241     //mipi_dsih_dphy_write(phy, 0x74, data, 1);\r
242 \r
243   /* Jessica add - end*/\r
244 \r
245     data[0] =  0x70;\r
246     mipi_dsih_dphy_write(phy, 0x16, data, 1);\r
247 \r
248     /* setup digital part */\r
249     /* hs frequency range [7]|[6:1]|[0]*/\r
250     data[0] = (0 << 7) | (ranges[range].hs_freq << 1) | 0;\r
251    //data[0] = (0 << 7) | (0x23 << 1) | 0;\r
252    /*From ASIC, we need unmask this code to make the frequency correct*/\r
253     mipi_dsih_dphy_write(phy, 0x44, data, 1);       //Jessica remove for more accurate frequency\r
254     /* setup PLL */\r
255     /* vco range  [7]|[6:3]|[2:1]|[0] */\r
256     data[0] = (1 << 7) | (ranges[range].vco_range << 3) | (0 << 1) | 0;\r
257     mipi_dsih_dphy_write(phy, 0x10, data, 1);                 //Jessica\r
258 #ifdef TESTCHIP\r
259         /* for all Gen2 testchips, bypass LP TX enable idle low power */\r
260         data[0] = 0x80;\r
261         mipi_dsih_dphy_write(phy, 0x32, data, 1);\r
262         mipi_dsih_dphy_write(phy, 0x42, data, 1);\r
263         mipi_dsih_dphy_write(phy, 0x52, data, 1);\r
264         mipi_dsih_dphy_write(phy, 0x82, data, 1);\r
265         mipi_dsih_dphy_write(phy, 0x92, data, 1);\r
266 #endif\r
267         if ((loop_divider % 2) != 0)\r
268         {       /* only odd integers are allowed (1 will be subtracted upon writing,\r
269                 see below) */\r
270                 loop_divider -= 1;\r
271 \r
272         }\r
273         /* gen 2 associates the charge pump current and LPF resistor with the\r
274          output frequency ranges (and thus we simplify here to use the\r
275          counter/pointer of the following structure) */\r
276         i = range;\r
277         data[0] = (0x00 << 6) | (0x01 << 5) | (0x01 << 4);\r
278 \r
279     mipi_dsih_dphy_write(phy, 0x19, data, 1);      //Jessica\r
280 \r
281     /* PLL Lock bypass|charge pump current [7:4]|[3:0] */\r
282     data[0] = (0x00 << 4) | (loop_bandwidth[i].cp_current << 0);\r
283     mipi_dsih_dphy_write(phy, 0x11, data, 1);           //Jessica\r
284     /* bypass CP default|bypass LPF default| LPF resistor [7]|[6]|[5:0] */\r
285     data[0] = (0x01 << 7) | (0x01 << 6) |(loop_bandwidth[i].lpf_resistor << 0);\r
286     mipi_dsih_dphy_write(phy, 0x12, data, 1);\r
287     /* PLL input divider ratio [7:0] */\r
288     data[0] = input_divider - 1;\r
289     mipi_dsih_dphy_write(phy, 0x17, data, 1);           //Jessica\r
290 \r
291     data[0] =   0x04; //short the delay time before BTA\r
292     mipi_dsih_dphy_write(phy, 0x07, data, 1);\r
293 \r
294 //    data[0] = 1;\r
295 //    mipi_dsih_dphy_write(phy, 0xB0, data, 1);\r
296 \r
297     data[0] = 0x8B;\r
298     mipi_dsih_dphy_write(phy, 0x22, data, 1);\r
299 //    data[1] = mipi_dsih_dphy_test_data_out(phy);\r
300 //    printk("sprdfb:mipi dphy config-->0x22 write:%x,read:%x \n",data[0],data[1]);\r
301 \r
302     no_of_bytes = 2; /* pll loop divider (code 0x18) takes only 2 bytes (10 bits in data) */\r
303     for (i = 0; i < no_of_bytes; i++)\r
304     {\r
305         data[i] = ((uint8_t)((((loop_divider - 1) >> (5 * i)) & 0x1F) | (i << 7) ));\r
306         /* 7 is dependent on no_of_bytes\r
307         make sure 5 bits only of value are written at a time */\r
308     }\r
309     /* PLL loop divider ratio - SET no|reserved|feedback divider [7]|[6:5]|[4:0] */\r
310     mipi_dsih_dphy_write(phy, 0x18, data, no_of_bytes);\r
311     mipi_dsih_dphy_no_of_lanes(phy, no_of_lanes);\r
312 #ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING
313         if (phy->phy_keep_work != true)
314 #endif
315         {
316                 mipi_dsih_dphy_stop_wait_time(phy, 0x1C);
317                 mipi_dsih_dphy_clock_en(phy, 1);
318                 for(n=0;n<100;n++){
319                         ;
320                 }
321                 mipi_dsih_dphy_shutdown(phy, 1);
322                 for(n=0;n<100;n++){
323                         ;
324                 }
325                 mipi_dsih_dphy_reset(phy, 1);
326         }
327         return OK;
328 }\r
329 #else\r
330 dsih_error_t mipi_dsih_dphy_configure(dphy_t * phy, uint8_t no_of_lanes, uint32_t output_freq)\r
331 {\r
332     uint32_t loop_divider = 0; /* (M) */\r
333     uint32_t input_divider = 1; /* (N) */\r
334     uint8_t data[4]; /* maximum data for now are 4 bytes per test mode*/\r
335     uint8_t no_of_bytes = 0;\r
336     uint8_t i = 0; /* iterator */\r
337     uint8_t n=0;/* iterator */\r
338     uint8_t range = 0; /* ranges iterator */\r
339     int flag = 0;\r
340 #ifdef DWC_MIPI_DPHY_BIDIR_TSMC40LP\r
341     struct\r
342     {\r
343         uint32_t freq;  /* upper margin of frequency range */\r
344         uint8_t hs_freq; /* hsfreqrange */\r
345         uint8_t vco_range; /* vcorange */\r
346     }\r
347     ranges[] =\r
348     {\r
349         {90, 0x00, 0x01}, {100, 0x10, 0x01}, {110, 0x20, 0x01},\r
350         {125, 0x01, 0x01}, {140, 0x11, 0x01}, {150, 0x21, 0x01},\r
351         {160, 0x02, 0x01}, {180, 0x12, 0x03}, {200, 0x22, 0x03},\r
352         {210, 0x03, 0x03}, {240, 0x13, 0x03}, {250, 0x23, 0x03},\r
353         {270, 0x04, 0x07}, {300, 0x14, 0x07}, {330, 0x24, 0x07},\r
354         {360, 0x15, 0x07}, {400, 0x25, 0x07}, {450, 0x06, 0x07},\r
355         {500, 0x16, 0x07}, {550, 0x07, 0x0f}, {600, 0x17, 0x0f},\r
356         {650, 0x08, 0x0f}, {700, 0x18, 0x0f}, {750, 0x09, 0x0f},\r
357         {800, 0x19, 0x0f}, {850, 0x0A, 0x0f}, {900, 0x1A, 0x0f},\r
358         {950, 0x2A, 0x0f}, {1000, 0x3A, 0x0f}\r
359     };\r
360     struct\r
361     {\r
362         uint32_t loop_div; /* upper limit of loop divider range */\r
363         uint8_t cp_current; /* icpctrl */\r
364         uint8_t lpf_resistor; /* lpfctrl */\r
365     }\r
366     loop_bandwidth[] =\r
367     {\r
368         {32, 0x06, 0x10}, {64, 0x06, 0x10}, {128, 0x0C, 0x08},\r
369         {256, 0x04, 0x04}, {512, 0x00, 0x01}, {768, 0x01, 0x01},\r
370         {1000, 0x02, 0x01}\r
371     };\r
372 #elif defined DPHY2Btql\r
373     struct\r
374     {\r
375         uint32_t loop_div; /* upper limit of loop divider range */\r
376         uint8_t cp_current; /* icpctrl */\r
377         uint8_t lpf_resistor; /* lpfctrl */\r
378     }\r
379     loop_bandwidth[] =\r
380     {\r
381         {32, 0x0B, 0x00}, {64, 0x0A, 0x00}, {128, 0x09, 0x01},\r
382         {256, 0x08, 0x03}, {512, 0x08, 0x07}, {768, 0x08, 0x0F},\r
383         {1000, 0x08, 0x1F}\r
384     };\r
385 #endif\r
386     if (phy == 0)\r
387     {\r
388         return ERR_DSI_INVALID_INSTANCE;\r
389     }\r
390     if (phy->status < INITIALIZED)\r
391     {\r
392         return ERR_DSI_INVALID_INSTANCE;\r
393     }\r
394     if (output_freq < MIN_OUTPUT_FREQ)\r
395     {\r
396         return ERR_DSI_PHY_FREQ_OUT_OF_BOUND;\r
397     }\r
398     /* find M and N dividers */\r
399     for (input_divider = 1 + (phy->reference_freq / DPHY_DIV_UPPER_LIMIT); ((phy->reference_freq / input_divider) >= DPHY_DIV_LOWER_LIMIT) && (!flag); input_divider++)\r
400     {   /* here the >= DPHY_DIV_LOWER_LIMIT is a phy constraint, formula should be above 1 MHz */\r
401         if (((output_freq * input_divider) % (phy->reference_freq )) == 0)\r
402         {   /* values found */\r
403             loop_divider = ((output_freq * input_divider) / (phy->reference_freq ));\r
404             if (loop_divider >= 12)\r
405             {\r
406                 flag = 1;\r
407             }\r
408         }\r
409     }\r
410     if ((!flag) || ((phy->reference_freq / input_divider) < DPHY_DIV_LOWER_LIMIT))\r
411     {   /* no exact value found in previous for loop */\r
412         /* this solution is not favourable as jitter would be maximum */\r
413         loop_divider = output_freq / DPHY_DIV_LOWER_LIMIT;\r
414         input_divider = phy->reference_freq / DPHY_DIV_LOWER_LIMIT;\r
415     }\r
416     else\r
417     {   /* variable was incremented before exiting the loop */\r
418         input_divider--;\r
419     }\r
420     for (i = 0; (i < (sizeof(loop_bandwidth)/sizeof(loop_bandwidth[0]))) && (loop_divider > loop_bandwidth[i].loop_div); i++)\r
421     {\r
422         ;\r
423     }\r
424     if (i >= (sizeof(loop_bandwidth)/sizeof(loop_bandwidth[0])))\r
425     {\r
426         return ERR_DSI_PHY_FREQ_OUT_OF_BOUND;\r
427     }\r
428     printk("sprdfb: Gen1 D-PHY: Approximated Frequency: %d KHz\n", (loop_divider * (phy->reference_freq / input_divider)));\r
429 #ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING
430         if (phy->phy_keep_work != true)
431 #endif
432         {
433                 /* get the PHY in power down mode (shutdownz=0) and reset it (rstz=0) to
434                 avoid transient periods in PHY operation during re-configuration procedures. */
435                 mipi_dsih_dphy_reset(phy, 0);
436                 mipi_dsih_dphy_clock_en(phy, 0);
437                 mipi_dsih_dphy_shutdown(phy, 0);
438                 /* provide an initial active-high test clear pulse in TESTCLR  */
439                 mipi_dsih_dphy_test_clear(phy, 1);
440                 mipi_dsih_dphy_test_clear(phy, 0);
441         }
442 #ifdef DWC_MIPI_DPHY_BIDIR_TSMC40LP\r
443     /* find ranges */\r
444     for (range = 0; (range < (sizeof(ranges)/sizeof(ranges[0]))) && ((output_freq / 1000) > ranges[range].freq); range++)\r
445     {\r
446         ;\r
447     }\r
448     if (range >= (sizeof(ranges)/sizeof(ranges[0])))\r
449     {\r
450         return ERR_DSI_PHY_FREQ_OUT_OF_BOUND;\r
451     }\r
452     /* set up board depending on environment if any */\r
453     if (phy->bsp_pre_config != 0)\r
454     {\r
455         phy->bsp_pre_config(phy, 0);\r
456     }\r
457 \r
458   /* Jessica add - begin*/\r
459     data[0] =  0x42;//0x44;//0x44;//0x40;                 //0x40: ok for 200    clock lane lpx /*about 52ns*/\r
460     mipi_dsih_dphy_write(phy, 0x60, data, 1);\r
461     data[0] =  0x0; //0xA6;//0xC6;//0xC6;//0x86;                 //0x48: ok for 200     prepare time\r
462     mipi_dsih_dphy_write(phy, 0x61, data, 1);\r
463 \r
464     data[0] =  0x0;//0x6a;//0x6a;//0x4a;                  //0x4a: ok for 200    zero time\r
465     mipi_dsih_dphy_write(phy, 0x62, data, 1);\r
466 \r
467     data[0] =  0x42;//0x44;//0x40;//0x40;              // 0x40: ok for 200          data lane lpx /*about 52ns*/\r
468     mipi_dsih_dphy_write(phy, 0x70, data, 1);\r
469 \r
470     data[0] = 0x0;// 0x84;//0x96;//0x96;//0x86;                //0x48: ok for 200         prepare time\r
471     mipi_dsih_dphy_write(phy, 0x71, data, 1);\r
472 \r
473     data[0] =  0x0;//0x44;//0x44;//0x40;               //0x4a: ok for 200          zero time\r
474     mipi_dsih_dphy_write(phy, 0x72, data, 1);\r
475 \r
476     //data[0] =  0x44;\r
477     //mipi_dsih_dphy_write(phy, 0x73, data, 1);\r
478 \r
479     //data[0] =  0x7F;\r
480     //mipi_dsih_dphy_write(phy, 0x74, data, 1);\r
481 \r
482   /* Jessica add - end*/\r
483 \r
484     /* setup digital part */\r
485     /* hs frequency range [7]|[6:1]|[0]*/\r
486     data[0] = (0 << 7) | (ranges[range].hs_freq << 1) | 0;\r
487    //data[0] = (0 << 7) | (0x23 << 1) | 0;\r
488    /*From ASIC, we need unmask this code to make the frequency correct*/\r
489     mipi_dsih_dphy_write(phy, 0x44, data, 1);       //Jessica remove for more accurate frequency\r
490     /* setup PLL */\r
491     /* vco range  [7]|[6:3]|[2:1]|[0] */\r
492     data[0] = (1 << 7) | (ranges[range].vco_range << 3) | (0 << 1) | 0;\r
493     mipi_dsih_dphy_write(phy, 0x10, data, 1);                 //Jessica\r
494     /* PLL  reserved|Input divider control|Loop Divider Control|Post Divider Ratio [7:6]|[5]|[4]|[3:0] */\r
495     data[0] = (0x00 << 6) | (0x01 << 5) | (0x01 << 4) | (0x03 << 0); /* post divider default = 0x03 - it is only used for clock out 2*/\r
496     mipi_dsih_dphy_write(phy, 0x19, data, 1);      //Jessica\r
497 #elif defined DPHY2Btql\r
498     /* vco range  [7:5]|[4]|[3]|[2:1]|[0] */\r
499     data[0] =  ((((output_freq / 1000) > 500 )? 1: 0) << 4) | (1 << 3) | (0 << 1) | 0;\r
500     mipi_dsih_dphy_write(phy, 0x10, data, 1);\r
501 #endif\r
502     /* PLL Lock bypass|charge pump current [7:4]|[3:0] */\r
503     data[0] = (0x00 << 4) | (loop_bandwidth[i].cp_current << 0);\r
504     mipi_dsih_dphy_write(phy, 0x11, data, 1);           //Jessica\r
505     /* bypass CP default|bypass LPF default| LPF resistor [7]|[6]|[5:0] */\r
506     data[0] = (0x01 << 7) | (0x01 << 6) |(loop_bandwidth[i].lpf_resistor << 0);\r
507     mipi_dsih_dphy_write(phy, 0x12, data, 1);\r
508     /* PLL input divider ratio [7:0] */\r
509    data[0] = input_divider - 1;\r
510    mipi_dsih_dphy_write(phy, 0x17, data, 1);           //Jessica\r
511 \r
512     data[0] =   0x04; //short the delay time before BTA\r
513     mipi_dsih_dphy_write(phy, 0x07, data, 1);\r
514 \r
515 //    data[0] = 1;\r
516 //    mipi_dsih_dphy_write(phy, 0xB0, data, 1);\r
517 \r
518     data[0] = 0x8B;\r
519     mipi_dsih_dphy_write(phy, 0x22, data, 1);\r
520  //   data[1] = mipi_dsih_dphy_test_data_out(phy);\r
521 //    printk("sprdfb:mipi dphy config-->0x22 write:%x,read:%x \n",data[0],data[1]);\r
522 \r
523     no_of_bytes = 2; /* pll loop divider (code 0x18) takes only 2 bytes (10 bits in data) */\r
524     for (i = 0; i < no_of_bytes; i++)\r
525     {\r
526         data[i] = ((uint8_t)((((loop_divider - 1) >> (5 * i)) & 0x1F) | (i << 7) ));\r
527         /* 7 is dependent on no_of_bytes\r
528         make sure 5 bits only of value are written at a time */\r
529     }\r
530     /* PLL loop divider ratio - SET no|reserved|feedback divider [7]|[6:5]|[4:0] */\r
531     mipi_dsih_dphy_write(phy, 0x18, data, no_of_bytes);\r
532     mipi_dsih_dphy_no_of_lanes(phy, no_of_lanes);\r
533 #ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING
534         if (phy->phy_keep_work != true)
535 #endif
536         {
537                 mipi_dsih_dphy_stop_wait_time(phy, 0x1C);
538                 mipi_dsih_dphy_clock_en(phy, 1);
539                 for(n=0;n<100;n++){
540                         ;
541                 }
542                 mipi_dsih_dphy_shutdown(phy, 1);
543                 for(n=0;n<100;n++){
544                         ;
545                 }
546                 mipi_dsih_dphy_reset(phy, 1);
547         }
548     return OK;\r
549 }\r
550 #endif\r
551 /**\r
552  * Close and power down D-PHY module\r
553  * @param phy pointer to structure which holds information about the d-phy\r
554  * module\r
555  * @return error code\r
556  */\r
557 dsih_error_t mipi_dsih_dphy_close(dphy_t * phy)\r
558 {\r
559         if (phy == 0)\r
560         {\r
561                 return ERR_DSI_INVALID_INSTANCE;\r
562         }\r
563         else if ((phy->core_read_function == 0) || (phy->core_write_function == 0))\r
564         {\r
565                 return ERR_DSI_INVALID_IO;\r
566         }\r
567         if (phy->status < NOT_INITIALIZED)\r
568         {\r
569                 return ERR_DSI_INVALID_INSTANCE;\r
570         }\r
571         mipi_dsih_dphy_reset(phy, 0);\r
572         mipi_dsih_dphy_reset(phy, 1);\r
573         mipi_dsih_dphy_shutdown(phy, 0);\r
574         phy->status = NOT_INITIALIZED;\r
575         return OK;\r
576 }\r
577 /**\r
578  * Enable clock lane module\r
579  * @param instance pointer to structure which holds information about the d-phy\r
580  * module\r
581  * @param en\r
582  */\r
583 void mipi_dsih_dphy_clock_en(dphy_t * instance, int en)\r
584 {\r
585         mipi_dsih_dphy_write_part(instance, R_DPHY_RSTZ, en, 2, 1);\r
586 }\r
587 /**\r
588  * Reset D-PHY module\r
589  * @param instance pointer to structure which holds information about the d-phy\r
590  * module\r
591  * @param reset\r
592  */\r
593 void mipi_dsih_dphy_reset(dphy_t * instance, int reset)\r
594 {\r
595         mipi_dsih_dphy_write_part(instance, R_DPHY_RSTZ, reset, 1, 1);\r
596 }\r
597 /**\r
598  * Power up/down D-PHY module\r
599  * @param instance pointer to structure which holds information about the d-phy\r
600  * module\r
601  * @param powerup (1) shutdown (0)\r
602  */\r
603 void mipi_dsih_dphy_shutdown(dphy_t * instance, int powerup)\r
604 {\r
605         mipi_dsih_dphy_write_part(instance, R_DPHY_RSTZ, powerup, 0, 1);\r
606 }\r
607 /**\r
608  * Force D-PHY PLL to stay on while in ULPS\r
609  * @param instance pointer to structure which holds information about the d-phy\r
610  * module\r
611  * @param force (1) disable (0)\r
612  * @note To follow the programming model, use wakeup_pll function\r
613  */\r
614 void mipi_dsih_dphy_force_pll(dphy_t * instance, int force)\r
615 {\r
616         mipi_dsih_dphy_write_part(instance, R_DPHY_RSTZ, force, 3, 1);\r
617 }\r
618 /**\r
619  * Get force D-PHY PLL module\r
620  * @param instance pointer to structure which holds information about the d-phy\r
621  * module\r
622  * @return force value\r
623  */\r
624 int mipi_dsih_dphy_get_force_pll(dphy_t * instance)\r
625 {\r
626         return mipi_dsih_dphy_read_part(instance, R_DPHY_RSTZ, 3, 1);\r
627 }\r
628 /**\r
629  * Wake up or make sure D-PHY PLL module is awake\r
630  * This function must be called after going into ULPS and before exiting it\r
631  * to force the DPHY PLLs to wake up. It will wait until the DPHY status is\r
632  * locked. It follows the procedure described in the user guide.\r
633  * This function should be used to make sure the PLL is awake, rather than\r
634  * the force_pll above.\r
635  * @param instance pointer to structure which holds information about the d-phy\r
636  * module\r
637  * @return error code\r
638  * @note this function has an active wait\r
639  */\r
640 int mipi_dsih_dphy_wakeup_pll(dphy_t * instance)\r
641 {\r
642         unsigned i = 0;\r
643         if (mipi_dsih_dphy_status(instance, 0x1) == 0)\r
644         {\r
645                 mipi_dsih_dphy_force_pll(instance, 1);\r
646                 for (i = 0; i < DSIH_PHY_ACTIVE_WAIT; i++)\r
647                 {\r
648                         if(mipi_dsih_dphy_status(instance, 0x1))\r
649                         {\r
650                                 break;\r
651                         }\r
652                 }\r
653                 if (mipi_dsih_dphy_status(instance, 0x1) == 0)\r
654                 {\r
655                         return ERR_DSI_PHY_PLL_NOT_LOCKED;\r
656                 }\r
657         }\r
658         return OK;\r
659 }\r
660 /**\r
661  * Configure minimum wait period for HS transmission request after a stop state\r
662  * @param instance pointer to structure which holds information about the d-phy\r
663  * module\r
664  * @param no_of_byte_cycles [in byte (lane) clock cycles]\r
665  */\r
666 void mipi_dsih_dphy_stop_wait_time(dphy_t * instance, uint8_t no_of_byte_cycles)\r
667 {\r
668         mipi_dsih_dphy_write_part(instance, R_DPHY_IF_CFG, no_of_byte_cycles, 8, 8);\r
669 }\r
670 /**\r
671  * Set number of active lanes\r
672  * @param instance pointer to structure which holds information about the d-phy\r
673  * module\r
674  * @param no_of_lanes\r
675  */\r
676 void mipi_dsih_dphy_no_of_lanes(dphy_t * instance, uint8_t no_of_lanes)\r
677 {\r
678         mipi_dsih_dphy_write_part(instance, R_DPHY_IF_CFG, no_of_lanes - 1, 0, 2);\r
679 }\r
680 /**\r
681  * Get number of currently active lanes\r
682  * @param instance pointer to structure which holds information about the d-phy\r
683  *  module\r
684  * @return number of active lanes\r
685  */\r
686 uint8_t mipi_dsih_dphy_get_no_of_lanes(dphy_t * instance)\r
687 {\r
688         return mipi_dsih_dphy_read_part(instance, R_DPHY_IF_CFG, 0, 2);\r
689 }\r
690 \r
691 /**\r
692  * SPRD ADD\r
693  * Set non-continuous clock mode\r
694  * @param instance pointer to structure which holds information about the d-phy\r
695  * module\r
696  * @param enable\r
697  */\r
698 void mipi_dsih_dphy_enable_nc_clk(dphy_t * instance, int enable)\r
699 {\r
700         mipi_dsih_dphy_write_part(instance, R_DPHY_LPCLK_CTRL, enable, 1, 1);\r
701 }\r
702 \r
703 /**\r
704  * Request the PHY module to start transmission of high speed clock.\r
705  * This causes the clock lane to start transmitting DDR clock on the\r
706  * lane interconnect.\r
707  * @param instance pointer to structure which holds information about the d-phy\r
708  * module\r
709  * @param enable\r
710  * @note this function should be called explicitly by user always except for\r
711  * transmitting\r
712  */\r
713 void mipi_dsih_dphy_enable_hs_clk(dphy_t * instance, int enable)\r
714 {\r
715         mipi_dsih_dphy_write_part(instance, R_DPHY_LPCLK_CTRL, enable, 0, 1);\r
716 }\r
717 /**\r
718  * One bit is asserted in the trigger_request (4bits) to cause the lane module\r
719  * to cause the associated trigger to be sent across the lane interconnect.\r
720  * The trigger request is synchronous with the rising edge of the clock.\r
721  * @note: Only one bit of the trigger_request is asserted at any given time, the\r
722  * remaining must be left set to 0, and only when not in LPDT or ULPS modes\r
723  * @param instance pointer to structure which holds information about the d-phy\r
724  * module\r
725  * @param trigger_request 4 bit request\r
726  */\r
727 dsih_error_t mipi_dsih_dphy_escape_mode_trigger(dphy_t * instance, uint8_t trigger_request)\r
728 {\r
729         uint8_t sum = 0;\r
730         int i = 0;\r
731         for (i = 0; i < 4; i++)\r
732         {\r
733                 sum += ((trigger_request >> i) & 1);\r
734         }\r
735         if (sum == 1)\r
736         {       /* clear old trigger */\r
737                 mipi_dsih_dphy_write_part(instance, R_DPHY_TX_TRIGGERS, 0x00, 0, 4);\r
738                 mipi_dsih_dphy_write_part(instance, R_DPHY_TX_TRIGGERS, trigger_request, 0, 4);\r
739                 for (i = 0; i < DSIH_PHY_ACTIVE_WAIT; i++)\r
740                 {\r
741                         if(mipi_dsih_dphy_status(instance, 0x0010))\r
742                         {\r
743                                 break;\r
744                         }\r
745                 }\r
746                 mipi_dsih_dphy_write_part(instance, R_DPHY_TX_TRIGGERS, 0x00, 0, 4);\r
747                 if (i >= DSIH_PHY_ACTIVE_WAIT)\r
748                 {\r
749                         return ERR_DSI_TIMEOUT;\r
750                 }\r
751                 return OK;\r
752         }\r
753         return ERR_DSI_INVALID_COMMAND;\r
754 }\r
755 /**\r
756  * ULPS mode request/exit on all active data lanes.\r
757  * @param instance pointer to structure which holds information about the d-phy\r
758  * module\r
759  * @param enable (request 1/ exit 0)\r
760  * @return error code\r
761  * @note this is a blocking function. wait upon exiting the ULPS will exceed 1ms\r
762  */\r
763 #ifdef GEN_2\r
764 dsih_error_t mipi_dsih_dphy_ulps_data_lanes(dphy_t * instance, int enable)\r
765 {\r
766         int timeout;\r
767         /* mask 1 0101 0010 0000 */\r
768         uint16_t data_lanes_mask = 0;\r
769         if (enable)\r
770         {\r
771                 mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 1, 2, 1);\r
772                 return OK;\r
773         }\r
774         else\r
775         {\r
776                 if (mipi_dsih_dphy_status(instance, 0x1) == 0)\r
777                 {\r
778                         return ERR_DSI_PHY_PLL_NOT_LOCKED;\r
779                 }\r
780                 mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 1, 3, 1);\r
781                 switch (mipi_dsih_dphy_get_no_of_lanes(instance))\r
782                 {\r
783                         case 3:\r
784                                 data_lanes_mask |= (1 << 12);\r
785                         case 2:\r
786                                 data_lanes_mask |= (1 << 10);\r
787                         case 1:\r
788                                 data_lanes_mask |= (1 << 8);\r
789                         case 0:\r
790                                 data_lanes_mask |= (1 << 5);\r
791                                 break;\r
792                         default:\r
793                                 data_lanes_mask = 0;\r
794                                 break;\r
795                 }\r
796                 for (timeout = 0; timeout < DSIH_PHY_ACTIVE_WAIT; timeout++)\r
797                 {       /* verify that the DPHY has left ULPM */\r
798 \r
799                         if (mipi_dsih_dphy_status(instance, data_lanes_mask) == data_lanes_mask)\r
800                         {\r
801                                 break;\r
802                         }\r
803                         /* wait at least 1ms */\r
804                         for (timeout = 0; timeout < ONE_MS_ACTIVE_WAIT; timeout++)\r
805                         {\r
806                                 ;\r
807                         }\r
808                 }\r
809                 if (mipi_dsih_dphy_status(instance, data_lanes_mask) != data_lanes_mask)\r
810                 {\r
811                         instance->log_info("sprdfb: stat %x, mask %x", mipi_dsih_dphy_status(instance, data_lanes_mask), data_lanes_mask);\r
812                         return ERR_DSI_TIMEOUT;\r
813                 }\r
814                 mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 0, 2, 1);\r
815                 mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 0, 3, 1);\r
816         }\r
817         return OK;\r
818 }\r
819 #else\r
820 void mipi_dsih_dphy_ulps_data_lanes(dphy_t * instance, int enable)\r
821 {\r
822     int timeout;\r
823     if (enable)\r
824     {\r
825         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 3, 1);\r
826     }\r
827     else\r
828     {\r
829         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 4, 1);\r
830         for (timeout = 0; timeout < DSIH_PHY_ACTIVE_WAIT; timeout++)\r
831         {   /* verify that the DPHY has left ULPM */\r
832             /* mask 1010100100000 */\r
833             if (mipi_dsih_dphy_status(instance, 0x1520) == 0)\r
834             {   /* wait at least 1ms */\r
835                 for (timeout = 0; timeout < ONE_MS_ACTIVE_WAIT; timeout++)\r
836                 {\r
837                     ;\r
838                 }\r
839                 break;\r
840             }\r
841         }\r
842         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 3, 1);\r
843         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 4, 1);\r
844     }\r
845 }\r
846 #endif\r
847 /**\r
848  * ULPS mode request/exit on Clock Lane.\r
849  * @param instance pointer to structure which holds information about the\r
850  * d-phy module\r
851  * @param enable 1 or disable 0 of the Ultra Low Power State of the clock lane\r
852  * @return error code\r
853  * @note this is a blocking function. wait upon exiting the ULPS will exceed 1ms\r
854  */\r
855 #ifdef GEN_2\r
856 dsih_error_t mipi_dsih_dphy_ulps_clk_lane(dphy_t * instance, int enable)\r
857 {\r
858         int timeout;\r
859         /* mask 1000 */\r
860         uint16_t clk_lane_mask = 0x0008;\r
861         if (enable)\r
862         {\r
863                 /* mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 0, 0, 1); */\r
864                 mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 1, 0, 1);\r
865         }\r
866         else\r
867         {\r
868                 if (mipi_dsih_dphy_status(instance, 0x1) == 0)\r
869                 {\r
870                         return ERR_DSI_PHY_PLL_NOT_LOCKED;\r
871                 }\r
872                 mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 1, 1, 1);\r
873                 for (timeout = 0; timeout < DSIH_PHY_ACTIVE_WAIT; timeout++)\r
874                 {       /* verify that the DPHY has left ULPM */\r
875             /* mask 1010100100000 */\r
876             if (mipi_dsih_dphy_status(instance, clk_lane_mask) == clk_lane_mask)\r
877             {   /* wait at least 1ms */\r
878                                 instance->log_info("sprdfb: stat %x, mask %x", mipi_dsih_dphy_status(instance, clk_lane_mask), clk_lane_mask);\r
879                                 break;\r
880                         }\r
881                         /* wait at least 1ms */\r
882                         for (timeout = 0; timeout < ONE_MS_ACTIVE_WAIT; timeout++)\r
883                         {       /* dummy operation for the loop not to be optimised */\r
884                                  enable = mipi_dsih_dphy_status(instance, clk_lane_mask);\r
885                         }\r
886                 }\r
887                 if (mipi_dsih_dphy_status(instance, clk_lane_mask) != clk_lane_mask)\r
888                 {\r
889                         return ERR_DSI_TIMEOUT;\r
890                 }\r
891                 mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 0, 0, 1);\r
892                 mipi_dsih_dphy_write_part(instance, R_DPHY_ULPS_CTRL, 0, 1, 1);\r
893         }\r
894         return OK;\r
895 }\r
896 #else\r
897 void mipi_dsih_dphy_ulps_clk_lane(dphy_t * instance, int enable)\r
898 {\r
899     int timeout;\r
900     if (enable)\r
901     {\r
902         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 0, 1);\r
903         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 1, 1);\r
904     }\r
905     else\r
906     {\r
907         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 2, 1);\r
908         for (timeout = 0; timeout < DSIH_PHY_ACTIVE_WAIT; timeout++)\r
909         {   /* verify that the DPHY has left ULPM */\r
910             /* mask 1010100100000 */\r
911             if (mipi_dsih_dphy_status(instance, 0x0004) == 0)\r
912             {   /* wait at least 1ms */\r
913                 for (timeout = 0; timeout < ONE_MS_ACTIVE_WAIT; timeout++)\r
914                 {\r
915                     ;\r
916                 }\r
917                 break;\r
918             }\r
919         }\r
920         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 1, 1);\r
921         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 2, 1);\r
922     }\r
923 }\r
924 #endif\r
925 /**\r
926  * Get D-PHY PPI status\r
927  * @param instance pointer to structure which holds information about the d-phy\r
928  * module\r
929  * @param mask\r
930  * @return status\r
931  */\r
932 uint32_t mipi_dsih_dphy_status(dphy_t * instance, uint16_t mask)\r
933 {\r
934         return mipi_dsih_dphy_read_word(instance, R_DPHY_STATUS) & mask;\r
935 }\r
936 /**\r
937  * @param instance pointer to structure which holds information about the d-phy\r
938  * module\r
939  * @param value\r
940  */\r
941 void mipi_dsih_dphy_test_clock(dphy_t * instance, int value)\r
942 {\r
943         mipi_dsih_dphy_write_part(instance, R_DPHY_TST_CRTL0, value, 1, 1);\r
944 }\r
945 /**\r
946  * @param instance pointer to structure which holds information about the d-phy\r
947  * module\r
948  * @param value\r
949  */\r
950 void mipi_dsih_dphy_test_clear(dphy_t * instance, int value)\r
951 {\r
952         mipi_dsih_dphy_write_part(instance, R_DPHY_TST_CRTL0, value, 0, 1);\r
953 }\r
954 /**\r
955  * @param instance pointer to structure which holds information about the d-phy\r
956  * module\r
957  * @param on_falling_edge\r
958  */\r
959 void mipi_dsih_dphy_test_en(dphy_t * instance, uint8_t on_falling_edge)\r
960 {\r
961         mipi_dsih_dphy_write_part(instance, R_DPHY_TST_CRTL1, on_falling_edge, 16, 1);\r
962 }\r
963 /**\r
964  * @param instance pointer to structure which holds information about the d-phy\r
965  * module\r
966  */\r
967 uint8_t mipi_dsih_dphy_test_data_out(dphy_t * instance)\r
968 {\r
969         return mipi_dsih_dphy_read_part(instance, R_DPHY_TST_CRTL1, 8, 8);\r
970 }\r
971 /**\r
972  * @param instance pointer to structure which holds information about the d-phy\r
973  * module\r
974  * @param test_data\r
975  */\r
976 void mipi_dsih_dphy_test_data_in(dphy_t * instance, uint8_t test_data)\r
977 {\r
978         mipi_dsih_dphy_write_word(instance, R_DPHY_TST_CRTL1, test_data);\r
979 }\r
980 /**\r
981  * Write to D-PHY module (encapsulating the digital interface)\r
982  * @param instance pointer to structure which holds information about the d-phy\r
983  * module\r
984  * @param address offset inside the D-PHY digital interface\r
985  * @param data array of bytes to be written to D-PHY\r
986  * @param data_length of the data array\r
987  */\r
988 void mipi_dsih_dphy_write(dphy_t * instance, uint8_t address, uint8_t * data, uint8_t data_length)\r
989 {\r
990         unsigned i = 0;\r
991         if (data != 0)\r
992         {\r
993 #if ((defined DWC_MIPI_DPHY_BIDIR_TSMC40LP) || (defined DPHY2Btql) || (defined GEN_2))\r
994                 /* set the TESTCLK input high in preparation to latch in the desired test mode */\r
995                 mipi_dsih_dphy_test_clock(instance, 1);\r
996                 /* set the desired test code in the input 8-bit bus TESTDIN[7:0] */\r
997                 mipi_dsih_dphy_test_data_in(instance, address);\r
998                 /* set TESTEN input high  */\r
999                 mipi_dsih_dphy_test_en(instance, 1);\r
1000                 /* drive the TESTCLK input low; the falling edge captures the chosen test code into the transceiver */\r
1001                 mipi_dsih_dphy_test_clock(instance, 0);\r
1002                 /* set TESTEN input low to disable further test mode code latching  */\r
1003                 mipi_dsih_dphy_test_en(instance, 0);\r
1004                 /* start writing MSB first */\r
1005                 for (i = data_length; i > 0; i--)\r
1006                 {       /* set TESTDIN[7:0] to the desired test data appropriate to the chosen test mode */\r
1007                         mipi_dsih_dphy_test_data_in(instance, data[i - 1]);\r
1008                         /* pulse TESTCLK high to capture this test data into the macrocell; repeat these two steps as necessary */\r
1009                         mipi_dsih_dphy_test_clock(instance, 1);\r
1010                         mipi_dsih_dphy_test_clock(instance, 0);\r
1011                 }\r
1012 #endif\r
1013         }\r
1014 }\r
1015 \r
1016 \r
1017 \r
1018 /* abstracting BSP */\r
1019 /**\r
1020  * Write to whole register to D-PHY module (encapsulating the bus interface)\r
1021  * @param instance pointer to structure which holds information about the d-phy\r
1022  * module\r
1023  * @param reg_address offset\r
1024  * @param data 32-bit word\r
1025  */\r
1026 void mipi_dsih_dphy_write_word(dphy_t * instance, uint32_t reg_address, uint32_t data)\r
1027 {\r
1028         if (instance->core_write_function != 0)\r
1029         {\r
1030                 instance->core_write_function(instance->address, reg_address, data);\r
1031         }\r
1032 }\r
1033 /**\r
1034  * Write bit field to D-PHY module (encapsulating the bus interface)\r
1035  * @param instance pointer to structure which holds information about the d-phy\r
1036  * module\r
1037  * @param reg_address offset\r
1038  * @param data bits to be written to D-PHY\r
1039  * @param shift from the right hand side of the register (big endian)\r
1040  * @param width of the bit field\r
1041  */\r
1042 void mipi_dsih_dphy_write_part(dphy_t * instance, uint32_t reg_address, uint32_t data, uint8_t shift, uint8_t width)\r
1043 {\r
1044         uint32_t mask = 0;\r
1045         uint32_t temp = 0;\r
1046         if (instance->core_read_function != 0)\r
1047         {\r
1048                 mask = (1 << width) - 1;\r
1049                 temp = mipi_dsih_dphy_read_word(instance, reg_address);\r
1050                 temp &= ~(mask << shift);\r
1051                 temp |= (data & mask) << shift;\r
1052                 mipi_dsih_dphy_write_word(instance, reg_address, temp);\r
1053         }\r
1054 }\r
1055 /**\r
1056  * Read whole register from D-PHY module (encapsulating the bus interface)\r
1057  * @param instance pointer to structure which holds information about the d-phy\r
1058  * module\r
1059  * @param reg_address offset\r
1060  * @return data 32-bit word\r
1061  */\r
1062 uint32_t mipi_dsih_dphy_read_word(dphy_t * instance, uint32_t reg_address)\r
1063 {\r
1064         if (instance->core_read_function == 0)\r
1065         {\r
1066                 return ERR_DSI_INVALID_IO;\r
1067         }\r
1068         return instance->core_read_function(instance->address, reg_address);\r
1069 }\r
1070 /**\r
1071  * Read bit field from D-PHY module (encapsulating the bus interface)\r
1072  * @param instance pointer to structure which holds information about the d-phy\r
1073  * module\r
1074  * @param reg_address offset\r
1075  * @param shift from the right hand side of the register (big endian)\r
1076  * @param width of the bit field\r
1077  * @return data bits to be written to D-PHY\r
1078  */\r
1079 uint32_t mipi_dsih_dphy_read_part(dphy_t * instance, uint32_t reg_address, uint8_t shift, uint8_t width)\r
1080 {\r
1081         return (mipi_dsih_dphy_read_word(instance, reg_address) >> shift) & ((1 << width) - 1);\r
1082 }\r