tizen 2.4 release
[kernel/u-boot-tm1.git] / drivers / video / sc8825fb / mipi_dsih_dphy.c
1                                                                                                                                                                        \r
2 #include "mipi_dsih_dphy.h"                                                                                                                                            \r
3 #define PRECISION_FACTOR        (1000)                                                                                                                                 \r
4 /* Reference clock frequency divided by Input Frequency Division Ratio LIMITS */                                                                                       \r
5 #define DPHY_DIV_UPPER_LIMIT    (40000)                                                                                                                                \r
6 #define DPHY_DIV_LOWER_LIMIT    (1000)                                                                                                                                 \r
7                                                                                                                                                                        \r
8 #ifdef DWC_MIPI_DPHY_BIDIR_TSMC40LP                                                                                                                                    \r
9 #define MIN_OUTPUT_FREQ         (80)                                                                                                                                   \r
10 #elif defined DPHY2Btql                                                                                                                                                \r
11 #define MIN_OUTPUT_FREQ         (200)                                                                                                                                  \r
12 #endif                                                                                                                                                                 \r
13                                                                                                                                                                        \r
14 dsih_error_t mipi_dsih_dphy_open(dphy_t * phy)                                                                                                                         \r
15 {                                                                                                                                                                      \r
16     if (phy == 0)                                                                                                                                                      \r
17     {                                                                                                                                                                  \r
18         return ERR_DSI_PHY_INVALID;                                                                                                                                    \r
19     }                                                                                                                                                                  \r
20     else if ((phy->core_read_function == 0) || (phy->core_write_function == 0))                                                                                        \r
21     {                                                                                                                                                                  \r
22         return ERR_DSI_INVALID_IO;                                                                                                                                     \r
23     }                                                                                                                                                                  \r
24     else if (phy->status == INITIALIZED)                                                                                                                               \r
25     {                                                                                                                                                                  \r
26         return ERR_DSI_PHY_INVALID;                                                                                                                                    \r
27     }                                                                                                                                                                  \r
28     phy->status = NOT_INITIALIZED;                                                                                                                                     \r
29     mipi_dsih_dphy_reset(phy, 0);                                                                                                                                      \r
30     mipi_dsih_dphy_stop_wait_time(phy, 0x1C);                                                                                                                          \r
31     mipi_dsih_dphy_no_of_lanes(phy, 1);                                                                                                                                \r
32     mipi_dsih_dphy_clock_en(phy, 1);                                                                                                                                   \r
33     mipi_dsih_dphy_shutdown(phy, 1);                                                                                                                                   \r
34     mipi_dsih_dphy_reset(phy, 1);                                                                                                                                      \r
35     phy->status = INITIALIZED;                                                                                                                                         \r
36     return OK;                                                                                                                                                         \r
37 }                                                                                                                                                                      \r
38 dsih_error_t mipi_dsih_dphy_configure(dphy_t * phy, uint8_t no_of_lanes, uint32_t output_freq)                                                                         \r
39 {                                                                                                                                                                      \r
40     uint32_t loop_divider = 0; /* (M) */                                                                                                                               \r
41     uint32_t input_divider = 1; /* (N) */                                                                                                                              \r
42     uint8_t data[4]; /* maximum data for now are 4 bytes per test mode*/                                                                                               \r
43     uint8_t no_of_bytes = 0;                                                                                                                                           \r
44     uint8_t i = 0; /* iterator */                                                                                                                                      \r
45     uint8_t range = 0; /* ranges iterator */                                                                                                                           \r
46     int flag = 0;                                                                                                                                                      \r
47 #ifdef DWC_MIPI_DPHY_BIDIR_TSMC40LP                                                                                                                                    \r
48     struct                                                                                                                                                             \r
49     {                                                                                                                                                                  \r
50         uint32_t freq;  /* upper margin of frequency range */                                                                                                          \r
51         uint8_t hs_freq; /* hsfreqrange */                                                                                                                             \r
52         uint8_t vco_range; /* vcorange */                                                                                                                              \r
53     }                                                                                                                                                                  \r
54     ranges[] =                                                                                                                                                         \r
55     {                                                                                                                                                                  \r
56         {90, 0x00, 0x01}, {100, 0x10, 0x01}, {110, 0x20, 0x01},                                                                                                        \r
57         {125, 0x01, 0x01}, {140, 0x11, 0x01}, {150, 0x21, 0x01},                                                                                                       \r
58         {160, 0x02, 0x01}, {180, 0x12, 0x03}, {200, 0x22, 0x03},                                                                                                       \r
59         {210, 0x03, 0x03}, {240, 0x13, 0x03}, {250, 0x23, 0x03},                                                                                                       \r
60         {270, 0x04, 0x07}, {300, 0x14, 0x07}, {330, 0x24, 0x07},                                                                                                       \r
61         {360, 0x15, 0x07}, {400, 0x25, 0x07}, {450, 0x06, 0x07},                                                                                                       \r
62         {500, 0x16, 0x07}, {550, 0x07, 0x0f}, {600, 0x17, 0x0f},                                                                                                       \r
63         {650, 0x08, 0x0f}, {700, 0x18, 0x0f}, {750, 0x09, 0x0f},                                                                                                       \r
64         {800, 0x19, 0x0f}, {850, 0x0A, 0x0f}, {900, 0x1A, 0x0f},                                                                                                       \r
65         {950, 0x2A, 0x0f}, {1000, 0x3A, 0x0f}                                                                                                                          \r
66     };                                                                                                                                                                 \r
67     struct                                                                                                                                                             \r
68     {                                                                                                                                                                  \r
69         uint32_t loop_div; /* upper limit of loop divider range */                                                                                                     \r
70         uint8_t cp_current; /* icpctrl */                                                                                                                              \r
71         uint8_t lpf_resistor; /* lpfctrl */                                                                                                                            \r
72     }                                                                                                                                                                  \r
73     loop_bandwidth[] =                                                                                                                                                 \r
74     {                                                                                                                                                                  \r
75         {32, 0x06, 0x10}, {64, 0x06, 0x10}, {128, 0x0C, 0x08},                                                                                                         \r
76         {256, 0x04, 0x04}, {512, 0x00, 0x01}, {768, 0x01, 0x01},                                                                                                       \r
77         {1000, 0x02, 0x01}                                                                                                                                             \r
78     };                                                                                                                                                                 \r
79 #elif defined DPHY2Btql                                                                                                                                                \r
80     struct                                                                                                                                                             \r
81     {                                                                                                                                                                  \r
82         uint32_t loop_div; /* upper limit of loop divider range */                                                                                                     \r
83         uint8_t cp_current; /* icpctrl */                                                                                                                              \r
84         uint8_t lpf_resistor; /* lpfctrl */                                                                                                                            \r
85     }                                                                                                                                                                  \r
86     loop_bandwidth[] =                                                                                                                                                 \r
87     {                                                                                                                                                                  \r
88         {32, 0x0B, 0x00}, {64, 0x0A, 0x00}, {128, 0x09, 0x01},                                                                                                         \r
89         {256, 0x08, 0x03}, {512, 0x08, 0x07}, {768, 0x08, 0x0F},                                                                                                       \r
90         {1000, 0x08, 0x1F}                                                                                                                                             \r
91     };                                                                                                                                                                 \r
92 #endif                                                                                                                                                                 \r
93     if (phy == 0)                                                                                                                                                      \r
94     {                                                                                                                                                                  \r
95         return ERR_DSI_INVALID_INSTANCE;                                                                                                                               \r
96     }                                                                                                                                                                  \r
97     if (phy->status < INITIALIZED)                                                                                                                                     \r
98     {                                                                                                                                                                  \r
99         return ERR_DSI_INVALID_INSTANCE;                                                                                                                               \r
100     }                                                                                                                                                                  \r
101     if (output_freq < MIN_OUTPUT_FREQ)                                                                                                                                 \r
102     {                                                                                                                                                                  \r
103         return ERR_DSI_PHY_FREQ_OUT_OF_BOUND;                                                                                                                          \r
104     }                                                                                                                                                                  \r
105     /* find M and N dividers */                                                                                                                                        \r
106     for (input_divider = 1 + (phy->reference_freq / DPHY_DIV_UPPER_LIMIT); ((phy->reference_freq / input_divider) >= DPHY_DIV_LOWER_LIMIT) && (!flag); input_divider++)\r
107     {   /* here the >= DPHY_DIV_LOWER_LIMIT is a phy constraint, formula should be above 1 MHz */                                                                      \r
108         if (((output_freq * input_divider) % (phy->reference_freq )) == 0)                                                                                             \r
109         {   /* values found */                                                                                                                                         \r
110             loop_divider = ((output_freq * input_divider) / (phy->reference_freq ));                                                                                   \r
111             if (loop_divider >= 12)                                                                                                                                    \r
112             {                                                                                                                                                          \r
113                 flag = 1;                                                                                                                                              \r
114             }                                                                                                                                                          \r
115         }                                                                                                                                                              \r
116     }                                                                                                                                                                  \r
117     if ((!flag) || ((phy->reference_freq / input_divider) < DPHY_DIV_LOWER_LIMIT))                                                                                     \r
118     {   /* no exact value found in previous for loop */                                                                                                                \r
119         /* this solution is not favourable as jitter would be maximum */                                                                                               \r
120         loop_divider = output_freq / DPHY_DIV_LOWER_LIMIT;                                                                                                             \r
121         input_divider = phy->reference_freq / DPHY_DIV_LOWER_LIMIT;                                                                                                    \r
122     }                                                                                                                                                                  \r
123     else                                                                                                                                                               \r
124     {   /* variable was incremented before exiting the loop */                                                                                                         \r
125         input_divider--;                                                                                                                                               \r
126     }                                                                                                                                                                  \r
127     for (i = 0; (i < (sizeof(loop_bandwidth)/sizeof(loop_bandwidth[0]))) && (loop_divider > loop_bandwidth[i].loop_div); i++)                                          \r
128     {                                                                                                                                                                  \r
129         ;                                                                                                                                                              \r
130     }                                                                                                                                                                  \r
131     if (i >= (sizeof(loop_bandwidth)/sizeof(loop_bandwidth[0])))                                                                                                       \r
132     {                                                                                                                                                                  \r
133         return ERR_DSI_PHY_FREQ_OUT_OF_BOUND;                                                                                                                          \r
134     }                                                                                                                                                                  \r
135     /* get the PHY in power down mode (shutdownz=0) and reset it (rstz=0) to                                                                                           \r
136     avoid transient periods in PHY operation during re-configuration procedures. */                                                                                    \r
137     mipi_dsih_dphy_reset(phy, 0);                                                                                                                                      \r
138     mipi_dsih_dphy_clock_en(phy, 0);                                                                                                                                   \r
139     mipi_dsih_dphy_shutdown(phy, 0);                                                                                                                                   \r
140     /* provide an initial active-high test clear pulse in TESTCLR  */                                                                                                  \r
141     mipi_dsih_dphy_test_clear(phy, 1);                                                                                                                                 \r
142     mipi_dsih_dphy_test_clear(phy, 0);                                                                                                                                 \r
143 #ifdef DWC_MIPI_DPHY_BIDIR_TSMC40LP                                                                                                                                    \r
144     /* find ranges */                                                                                                                                                  \r
145     for (range = 0; (range < (sizeof(ranges)/sizeof(ranges[0]))) && ((output_freq / 1000) > ranges[range].freq); range++)                                              \r
146     {                                                                                                                                                                  \r
147         ;                                                                                                                                                              \r
148     }                                                                                                                                                                  \r
149     if (range >= (sizeof(ranges)/sizeof(ranges[0])))                                                                                                                   \r
150     {                                                                                                                                                                  \r
151         return ERR_DSI_PHY_FREQ_OUT_OF_BOUND;                                                                                                                          \r
152     }                                                                                                                                                                  \r
153     /* set up board depending on environment if any */                                                                                                                 \r
154     if (phy->bsp_pre_config != 0)                                                                                                                                      \r
155     {                                                                                                                                                                  \r
156         phy->bsp_pre_config(phy, 0);                                                                                                                                   \r
157     }\r
158 \r
159   /* Jessica add - begin*/  \r
160     data[0] =  0x41;//0x44;//0x44;//0x40;                 //0x40: ok for 200    clock lane lpx /*about 52ns*/\r
161     mipi_dsih_dphy_write(phy, 0x60, data, 1);\r
162     data[0] =  0x0;//0xA6;//0xC6;//0xC6;//0x86;                 //0x48: ok for 200     prepare time\r
163     mipi_dsih_dphy_write(phy, 0x61, data, 1);\r
164 \r
165     data[0] =  0x0;//0x6a;//0x6a;//0x4a;                  //0x4a: ok for 200    zero time\r
166     mipi_dsih_dphy_write(phy, 0x62, data, 1);\r
167 \r
168     data[0] =  0x41;//0x44;//0x40;//0x40;              // 0x40: ok for 200          data lane lpx /*about 52ns*/\r
169     mipi_dsih_dphy_write(phy, 0x70, data, 1);\r
170 \r
171     data[0] =  0x0;//0x84;//0x96;//0x96;//0x86;                //0x48: ok for 200         prepare time\r
172     mipi_dsih_dphy_write(phy, 0x71, data, 1);\r
173 \r
174     data[0] =  0x0;;//0x44;//0x44;//0x40;               //0x4a: ok for 200          zero time\r
175     mipi_dsih_dphy_write(phy, 0x72, data, 1);\r
176 \r
177     //data[0] =  0x44;                                                                                 \r
178     //mipi_dsih_dphy_write(phy, 0x73, data, 1);\r
179 \r
180     //data[0] =  0x7F;                                                                                 \r
181     //mipi_dsih_dphy_write(phy, 0x74, data, 1);\r
182 \r
183   /* Jessica add - end*/  \r
184  \r
185     /* setup digital part */                                                                                                                                           \r
186     /* hs frequency range [7]|[6:1]|[0]*/                                                                                                                              \r
187     data[0] = (0 << 7) | (ranges[range].hs_freq << 1) | 0;    \r
188    //data[0] = (0 << 7) | (0x23 << 1) | 0; \r
189    /*From ASIC, we need unmask this code to make the frequency correct*/\r
190     mipi_dsih_dphy_write(phy, 0x44, data, 1);       //Jessica remove for more accurate frequency\r
191     /* setup PLL */                                                                                                                                                    \r
192     /* vco range  [7]|[6:3]|[2:1]|[0] */                                                                                                                               \r
193     data[0] = (1 << 7) | (ranges[range].vco_range << 3) | (0 << 1) | 0;                                                                                                \r
194     mipi_dsih_dphy_write(phy, 0x10, data, 1);                 //Jessica                                                                                                         \r
195     /* PLL  reserved|Input divider control|Loop Divider Control|Post Divider Ratio [7:6]|[5]|[4]|[3:0] */                                                              \r
196     data[0] = (0x00 << 6) | (0x01 << 5) | (0x01 << 4) | (0x03 << 0); /* post divider default = 0x03 - it is only used for clock out 2*/                                \r
197     mipi_dsih_dphy_write(phy, 0x19, data, 1);      //Jessica                                                                                                                    \r
198 #elif defined DPHY2Btql                                                                                                                                                \r
199     /* vco range  [7:5]|[4]|[3]|[2:1]|[0] */                                                                                                                           \r
200     data[0] =  ((((output_freq / 1000) > 500 )? 1: 0) << 4) | (1 << 3) | (0 << 1) | 0;                                                                                 \r
201     mipi_dsih_dphy_write(phy, 0x10, data, 1);                                                                                                                          \r
202 #endif                                                                                                                                                                 \r
203     /* PLL Lock bypass|charge pump current [7:4]|[3:0] */                                                                                                              \r
204     data[0] = (0x00 << 4) | (loop_bandwidth[i].cp_current << 0);                                                                                                       \r
205     mipi_dsih_dphy_write(phy, 0x11, data, 1);           //Jessica                                                                                                               \r
206     /* bypass CP default|bypass LPF default| LPF resistor [7]|[6]|[5:0] */                                                                                             \r
207     data[0] = (0x01 << 7) | (0x01 << 6) |(loop_bandwidth[i].lpf_resistor << 0);                                                                                        \r
208     mipi_dsih_dphy_write(phy, 0x12, data, 1);                                                                                                                          \r
209     /* PLL input divider ratio [7:0] */                                                                                                                                \r
210    data[0] = input_divider - 1;                                                                                                                                       \r
211    mipi_dsih_dphy_write(phy, 0x17, data, 1);           //Jessica                                                                                                               \r
212     \r
213     data[0] = 1;\r
214     mipi_dsih_dphy_write(phy, 0xB0, data, 1);\r
215 \r
216 \r
217 \r
218     no_of_bytes = 2; /* pll loop divider (code 0x18) takes only 2 bytes (10 bits in data) */                                                                           \r
219     for (i = 0; i < no_of_bytes; i++)                                                                                                                                  \r
220     {                                                                                                                                                                  \r
221         data[i] = ((uint8_t)((((loop_divider - 1) >> (5 * i)) & 0x1F) | (i << 7) ));                                                                                   \r
222         /* 7 is dependent on no_of_bytes                                                                                                                               \r
223         make sure 5 bits only of value are written at a time */                                                                                                        \r
224     }                                                                                                                                                                  \r
225     /* PLL loop divider ratio - SET no|reserved|feedback divider [7]|[6:5]|[4:0] */                                                                                    \r
226     mipi_dsih_dphy_write(phy, 0x18, data, no_of_bytes);                                                                                                                \r
227     mipi_dsih_dphy_no_of_lanes(phy, no_of_lanes);                                                                                                                      \r
228     mipi_dsih_dphy_stop_wait_time(phy, 0x1C);                                                                                                                          \r
229     mipi_dsih_dphy_clock_en(phy, 1);                                                                                                                                   \r
230     mipi_dsih_dphy_shutdown(phy, 1);                                                                                                                                   \r
231     mipi_dsih_dphy_reset(phy, 1);                                                                                                                                      \r
232     return OK;                                                                                                                                                         \r
233\r
234 \r
235 \r
236 dsih_error_t mipi_dsih_dphy_close(dphy_t * phy)                                                                                                                        \r
237 {                                                                                                                                                                      \r
238     if (phy == 0)                                                                                                                                                      \r
239     {                                                                                                                                                                  \r
240         return ERR_DSI_INVALID_INSTANCE;                                                                                                                               \r
241     }                                                                                                                                                                  \r
242     else if ((phy->core_read_function == 0) || (phy->core_write_function == 0))                                                                                        \r
243     {                                                                                                                                                                  \r
244         return ERR_DSI_INVALID_IO;                                                                                                                                     \r
245     }                                                                                                                                                                  \r
246     if (phy->status < NOT_INITIALIZED)                                                                                                                                 \r
247     {                                                                                                                                                                  \r
248         return ERR_DSI_INVALID_INSTANCE;                                                                                                                               \r
249     }                                                                                                                                                                  \r
250     mipi_dsih_dphy_reset(phy, 0);                                                                                                                                      \r
251     mipi_dsih_dphy_reset(phy, 1);                                                                                                                                      \r
252     mipi_dsih_dphy_shutdown(phy, 0);                                                                                                                                   \r
253     phy->status = NOT_INITIALIZED;                                                                                                                                     \r
254     return OK;                                                                                                                                                         \r
255 }                                                                                                                                                                      \r
256 void mipi_dsih_dphy_clock_en(dphy_t * instance, int en)                                                                                                                \r
257 {                                                                                                                                                                      \r
258     mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_RSTZ, en, 2, 1);                                                                                                \r
259 }                                                                                                                                                                      \r
260 void mipi_dsih_dphy_reset(dphy_t * instance, int reset)                                                                                                                \r
261 {                                                                                                                                                                      \r
262     mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_RSTZ, reset, 1, 1);                                                                                             \r
263 }                                                                                                                                                                      \r
264 void mipi_dsih_dphy_shutdown(dphy_t * instance, int powerup)                                                                                                           \r
265 {                                                                                                                                                                      \r
266     mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_RSTZ, powerup, 0, 1);                                                                                           \r
267 }                                                                                                                                                                      \r
268 void mipi_dsih_dphy_stop_wait_time(dphy_t * instance, uint8_t no_of_byte_cycles)                                                                                       \r
269 {                                                                                                                                                                      \r
270     mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CFG, no_of_byte_cycles, 2, 8);                                                                               \r
271 }                                                                                                                                                                      \r
272 void mipi_dsih_dphy_no_of_lanes(dphy_t * instance, uint8_t no_of_lanes)                                                                                                \r
273 {                                                                                                                                                                      \r
274     mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CFG, no_of_lanes - 1, 0, 2);                                                                                 \r
275 }                                                                                                                                                                      \r
276 uint8_t mipi_dsih_dphy_get_no_of_lanes(dphy_t * instance)                                                                                                              \r
277 {                                                                                                                                                                      \r
278     return mipi_dsih_dphy_read_part(instance, R_DSI_HOST_PHY_IF_CFG, 0, 2);                                                                                            \r
279 }                                                                                                                                                                      \r
280 void mipi_dsih_dphy_enable_hs_clk(dphy_t * instance, int enable)                                                                                                       \r
281 {                                                                                                                                                                      \r
282     mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, enable, 0, 1);                                                                                         \r
283 }                                                                                                                                                                      \r
284 dsih_error_t mipi_dsih_dphy_escape_mode_trigger(dphy_t * instance, uint8_t trigger_request)                                                                            \r
285 {                                                                                                                                                                      \r
286     uint8_t sum = 0;                                                                                                                                                   \r
287     int i = 0;                                                                                                                                                         \r
288     for (i = 0; i < 4; i++)                                                                                                                                            \r
289     {                                                                                                                                                                  \r
290         sum += ((trigger_request >> i) & 1);                                                                                                                           \r
291     }                                                                                                                                                                  \r
292     if (sum == 1)                                                                                                                                                      \r
293     {   /* clear old trigger */                                                                                                                                        \r
294         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0x00, 5, 4);                                                                                       \r
295         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, trigger_request, 5, 4);                                                                            \r
296         for (i = 0; i < DSIH_PHY_ACTIVE_WAIT; i++)                                                                                                                     \r
297         {                                                                                                                                                              \r
298             if(mipi_dsih_dphy_status(instance, 0x0010))                                                                                                                \r
299             {                                                                                                                                                          \r
300                 break;                                                                                                                                                 \r
301             }                                                                                                                                                          \r
302         }                                                                                                                                                              \r
303         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0x00, 5, 4);                                                                                       \r
304         if (i >= DSIH_PHY_ACTIVE_WAIT)                                                                                                                                 \r
305         {                                                                                                                                                              \r
306             return ERR_DSI_TIMEOUT;                                                                                                                                    \r
307         }                                                                                                                                                              \r
308         return OK;                                                                                                                                                     \r
309     }                                                                                                                                                                  \r
310     return ERR_DSI_INVALID_COMMAND;                                                                                                                                    \r
311 }                                                                                                                                                                      \r
312 void mipi_dsih_dphy_ulps_data_lanes(dphy_t * instance, int enable)                                                                                                     \r
313 {                                                                                                                                                                      \r
314     int timeout;                                                                                                                                                       \r
315     if (enable)                                                                                                                                                        \r
316     {                                                                                                                                                                  \r
317         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 3, 1);                                                                                          \r
318     }                                                                                                                                                                  \r
319     else                                                                                                                                                               \r
320     {                                                                                                                                                                  \r
321         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 4, 1);                                                                                          \r
322         for (timeout = 0; timeout < DSIH_PHY_ACTIVE_WAIT; timeout++)                                                                                                   \r
323         {   /* verify that the DPHY has left ULPM */                                                                                                                   \r
324             /* mask 1010100100000 */                                                                                                                                   \r
325             if (mipi_dsih_dphy_status(instance, 0x1520) == 0)                                                                                                          \r
326             {   /* wait at least 1ms */                                                                                                                                \r
327                 for (timeout = 0; timeout < ONE_MS_ACTIVE_WAIT; timeout++)                                                                                             \r
328                 {                                                                                                                                                      \r
329                     ;                                                                                                                                                  \r
330                 }                                                                                                                                                      \r
331                 break;                                                                                                                                                 \r
332             }                                                                                                                                                          \r
333         }                                                                                                                                                              \r
334         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 3, 1);                                                                                          \r
335         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 4, 1);                                                                                          \r
336     }                                                                                                                                                                  \r
337 }                                                                                                                                                                      \r
338 void mipi_dsih_dphy_ulps_clk_lane(dphy_t * instance, int enable)                                                                                                       \r
339 {                                                                                                                                                                      \r
340     int timeout;                                                                                                                                                       \r
341     if (enable)                                                                                                                                                        \r
342     {                                                                                                                                                                  \r
343         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 0, 1);                                                                                          \r
344         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 1, 1);                                                                                          \r
345     }                                                                                                                                                                  \r
346     else                                                                                                                                                               \r
347     {                                                                                                                                                                  \r
348         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 1, 2, 1);                                                                                          \r
349         for (timeout = 0; timeout < DSIH_PHY_ACTIVE_WAIT; timeout++)                                                                                                   \r
350         {   /* verify that the DPHY has left ULPM */                                                                                                                   \r
351             /* mask 1010100100000 */                                                                                                                                   \r
352             if (mipi_dsih_dphy_status(instance, 0x0004) == 0)                                                                                                          \r
353             {   /* wait at least 1ms */                                                                                                                                \r
354                 for (timeout = 0; timeout < ONE_MS_ACTIVE_WAIT; timeout++)                                                                                             \r
355                 {                                                                                                                                                      \r
356                     ;                                                                                                                                                  \r
357                 }                                                                                                                                                      \r
358                 break;                                                                                                                                                 \r
359             }                                                                                                                                                          \r
360         }                                                                                                                                                              \r
361         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 1, 1);                                                                                          \r
362         mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_IF_CTRL, 0, 2, 1);                                                                                          \r
363     }                                                                                                                                                                  \r
364 }                                                                                                                                                                      \r
365 uint32_t mipi_dsih_dphy_status(dphy_t * instance, uint16_t mask)                                                                                                       \r
366 {                                                                                                                                                                      \r
367     return mipi_dsih_dphy_read_word(instance, R_DSI_HOST_PHY_STATUS) & mask;                                                                                           \r
368 }                                                                                                                                                                      \r
369 void mipi_dsih_dphy_test_clock(dphy_t * instance, int value)                                                                                                           \r
370 {                                                                                                                                                                      \r
371     mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_TST_CRTL0, value, 1, 1);                                                                                        \r
372 }                                                                                                                                                                      \r
373 void mipi_dsih_dphy_test_clear(dphy_t * instance, int value)                                                                                                           \r
374 {                                                                                                                                                                      \r
375     mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_TST_CRTL0, value, 0, 1);                                                                                        \r
376 }                                                                                                                                                                      \r
377 void mipi_dsih_dphy_test_en(dphy_t * instance, uint8_t on_falling_edge)                                                                                                \r
378 {                                                                                                                                                                      \r
379     mipi_dsih_dphy_write_part(instance, R_DSI_HOST_PHY_TST_CRTL1, on_falling_edge, 16, 1);                                                                             \r
380 }                                                                                                                                                                      \r
381 uint8_t mipi_dsih_dphy_test_data_out(dphy_t * instance)                                                                                                                \r
382 {                                                                                                                                                                      \r
383     return mipi_dsih_dphy_read_part(instance, R_DSI_HOST_PHY_TST_CRTL1, 8, 8);                                                                                         \r
384 }                                                                                                                                                                      \r
385 void mipi_dsih_dphy_test_data_in(dphy_t * instance, uint8_t test_data)                                                                                                 \r
386 {                                                                                                                                                                      \r
387     mipi_dsih_dphy_write_word(instance, R_DSI_HOST_PHY_TST_CRTL1, test_data);                                                                                          \r
388 }                                                                                                                                                                      \r
389 void mipi_dsih_dphy_write(dphy_t * instance, uint8_t address, uint8_t * data, uint8_t data_length)                                                                     \r
390 {                                                                                                                                                                      \r
391     unsigned i = 0;                                                                                                                                                    \r
392     if (data != 0)                                                                                                                                                     \r
393     {                                                                                                                                                                  \r
394 #if ((defined DWC_MIPI_DPHY_BIDIR_TSMC40LP) || (defined DPHY2Btql))                                                                                                    \r
395         /* set the TESTCLK input high in preparation to latch in the desired test mode */                                                                              \r
396         mipi_dsih_dphy_test_clock(instance, 1);                                                                                                                        \r
397         /* set the desired test code in the input 8-bit bus TESTDIN[7:0] */                                                                                            \r
398         mipi_dsih_dphy_test_data_in(instance, address);                                                                                                                \r
399         /* set TESTEN input high  */                                                                                                                                   \r
400         mipi_dsih_dphy_test_en(instance, 1);                                                                                                                           \r
401         /* drive the TESTCLK input low; the falling edge captures the chosen test code into the transceiver */                                                         \r
402         mipi_dsih_dphy_test_clock(instance, 0);                                                                                                                        \r
403         /* set TESTEN input low to disable further test mode code latching  */                                                                                         \r
404         mipi_dsih_dphy_test_en(instance, 0);                                                                                                                           \r
405         /* start writing MSB first */                                                                                                                                  \r
406         for (i = data_length; i > 0; i--)                                                                                                                              \r
407         {   /* set TESTDIN[7:0] to the desired test data appropriate to the chosen test mode */                                                                        \r
408             mipi_dsih_dphy_test_data_in(instance, data[i - 1]);                                                                                                        \r
409             /* pulse TESTCLK high to capture this test data into the macrocell; repeat these two steps as necessary */                                                 \r
410             mipi_dsih_dphy_test_clock(instance, 1);                                                                                                                    \r
411             mipi_dsih_dphy_test_clock(instance, 0);                                                                                                                    \r
412         }                                                                                                                                                              \r
413 #endif                                                                                                                                                                 \r
414     }                                                                                                                                                                  \r
415 }                                                                                                                                                                      \r
416                                                                                                                                                                        \r
417                                                                                                                                                                        \r
418                                                                                                                                                                        \r
419 /* abstracting BSP */                                                                                                                                                  \r
420 void mipi_dsih_dphy_write_word(dphy_t * instance, uint32_t reg_address, uint32_t data)                                                                                 \r
421 {                                                                                                                                                                      \r
422     if (instance->core_write_function != 0)                                                                                                                            \r
423     {                                                                                                                                                                  \r
424         instance->core_write_function(instance->address, reg_address, data);                                                                                           \r
425     }                                                                                                                                                                  \r
426 }                                                                                                                                                                      \r
427 void mipi_dsih_dphy_write_part(dphy_t * instance, uint32_t reg_address, uint32_t data, uint8_t shift, uint8_t width)                                                   \r
428 {                                                                                                                                                                      \r
429     uint32_t mask = 0;                                                                                                                                                 \r
430     uint32_t temp = 0;                                                                                                                                                 \r
431     if (instance->core_read_function != 0)                                                                                                                             \r
432     {                                                                                                                                                                  \r
433         mask = (1 << width) - 1;                                                                                                                                       \r
434         temp = mipi_dsih_dphy_read_word(instance, reg_address);                                                                                                        \r
435         temp &= ~(mask << shift);                                                                                                                                      \r
436         temp |= (data & mask) << shift;                                                                                                                                \r
437         mipi_dsih_dphy_write_word(instance, reg_address, temp);                                                                                                        \r
438     }                                                                                                                                                                  \r
439 }                                                                                                                                                                      \r
440 uint32_t mipi_dsih_dphy_read_word(dphy_t * instance, uint32_t reg_address)                                                                                             \r
441 {                                                                                                                                                                      \r
442     if (instance->core_read_function == 0)                                                                                                                             \r
443     {                                                                                                                                                                  \r
444         return ERR_DSI_INVALID_IO;                                                                                                                                     \r
445     }                                                                                                                                                                  \r
446     return instance->core_read_function(instance->address, reg_address);                                                                                               \r
447 }                                                                                                                                                                      \r
448 uint32_t mipi_dsih_dphy_read_part(dphy_t * instance, uint32_t reg_address, uint8_t shift, uint8_t width)                                                               \r
449 {                                                                                                                                                                      \r
450     return (mipi_dsih_dphy_read_word(instance, reg_address) >> shift) & ((1 << width) - 1);                                                                            \r
451 }                                                                                                                                                                      \r
452                                                                                                                                                                              \r