import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / pwm / mt8127 / mt_pwm_hal.c
1 /*******************************************************************************
2 * mt_pwm.c PWM Drvier
3 *
4 * Copyright (c) 2012, Media Teck.inc
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public Licence,
8 * version 2, as publish by the Free Software Foundation.
9 *
10 * This program is distributed and in hope it will be useful, but WITHOUT
11 * ANY WARRNTY; without even the implied warranty of MERCHANTABITLITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 *
16 ********************************************************************************
17 * Author : Changlei Gao (changlei.gao@mediatek.com)
18 ********************************************************************************
19 */
20
21 #include <linux/kernel.h>
22 #include <generated/autoconf.h>
23 #include <linux/types.h>
24 #include <linux/delay.h>
25 #include <asm/atomic.h>
26 #include <asm/uaccess.h>
27 #include <asm/io.h>
28
29 #include <mach/mt_pwm_hal_pub.h>
30 #include <mach/mt_pwm_hal.h>
31 #include <mach/mt_pwm_prv.h>
32
33 enum {
34 PWM_CON,
35 PWM_HDURATION,
36 PWM_LDURATION,
37 PWM_GDURATION,
38 PWM_BUF0_BASE_ADDR,
39 PWM_BUF0_SIZE,
40 PWM_BUF1_BASE_ADDR,
41 PWM_BUF1_SIZE,
42 PWM_SEND_DATA0,
43 PWM_SEND_DATA1,
44 PWM_WAVE_NUM,
45 PWM_DATA_WIDTH, //PWM3&4 SEND_WAVENUM?
46 PWM_THRESH, //PWM3&4 DATA_WIDTH
47 PWM_SEND_WAVENUM, //PWM3&4 THRESH
48 PWM_VALID
49 }PWM_REG_OFF;
50
51 U32 PWM_register[PWM_NUM]={
52 (PWM_BASE+0x0010), //PWM1 REGISTER BASE, 15 registers
53 (PWM_BASE+0x0050), //PWM2 register base 15 registers
54 (PWM_BASE+0x0090), //PWM3 register base 15 registers
55 (PWM_BASE+0x00d0), //PWM4 register base 13 registers
56 (PWM_BASE+0x0110), //PWM5 register base 13 registers
57 };
58
59
60 static int pwm_power_id[] = {
61 MT_CG_PERI_PWM1,
62 MT_CG_PERI_PWM2,
63 MT_CG_PERI_PWM3,
64 MT_CG_PERI_PWM4,
65 MT_CG_PERI_PWM5,
66 MT_CG_PERI_PWM6,
67 MT_CG_PERI_PWM7,
68 MT_CG_PERI_PWM
69 };
70
71 //pmic_pad : useless on 6582
72 #define PWM_CG 7
73 void mt_pwm_power_on_hal(U32 pwm_no, BOOL pmic_pad, unsigned long* power_flag)
74 {
75 if(0 == (*power_flag)){
76 PWMDBG("enable_clock: main\n");//
77 enable_clock(pwm_power_id[PWM_CG], "PWM");
78 set_bit(PWM_CG, power_flag);
79 }
80 if (!test_bit(pwm_no, power_flag)) {
81 PWMDBG("enable_clock: %d\n", pwm_no);//
82
83 PWMDBG("ap pad\n");//
84 enable_clock(pwm_power_id[pwm_no], "PWM"); //enable clock
85
86 set_bit(pwm_no,power_flag);
87 PWMDBG("enable_clock PWM%d\n", pwm_no+1);
88 }
89 }
90
91 void mt_pwm_power_off_hal(U32 pwm_no, BOOL pmic_pad, unsigned long* power_flag)
92 {
93 if (test_bit(pwm_no, power_flag)) {
94 PWMDBG("disable_clock: %d\n", pwm_no);//
95
96 PWMDBG("ap pad\n");//
97 disable_clock(pwm_power_id[pwm_no], "PWM"); //disable clock
98
99 clear_bit(pwm_no,power_flag);
100 PWMDBG("disable_clock PWM%d\n", pwm_no+1);
101 }
102 if(BIT(PWM_CG) == (*power_flag)){
103 PWMDBG("disable_clock: main\n");//
104 disable_clock(pwm_power_id[PWM_CG], "PWM");
105 clear_bit(PWM_CG, power_flag);
106 }
107 }
108 void mt_pwm_init_power_flag(unsigned long* power_flag)
109 {/*
110 U32 idx=0;
111 for(;idx<sizeof(pwm_power_id)/sizeof(pwm_power_id[0]);idx++)
112 {
113 if(clock_is_on(pwm_power_id[idx]))
114 {
115 set_bit(idx,power_flag);
116 }
117 else
118 {
119 clear_bit(idx, power_flag);
120 }
121 }
122 printk("mt_pwm_init_power_flag 0x%x\n", *power_flag);*/
123 }
124 S32 mt_pwm_sel_pmic_hal(U32 pwm_no)
125 {
126 PWMDBG("mt_pwm_sel_pmic\n");//
127 return EINVALID;
128 }
129
130 S32 mt_pwm_sel_ap_hal(U32 pwm_no)
131 {
132 PWMDBG("mt_pwm_sel_ap\n");//
133 return EINVALID;
134 }
135
136 void mt_set_pwm_enable_hal(U32 pwm_no)
137 {
138 SETREG32(PWM_ENABLE, 1 << pwm_no);
139 }
140 void mt_set_pwm_disable_hal(U32 pwm_no)
141 {
142 CLRREG32 ( PWM_ENABLE, 1 << pwm_no );
143 }
144 void mt_set_pwm_enable_seqmode_hal(void)
145 {
146 SETREG32 ( PWM_ENABLE, 1 << PWM_ENABLE_SEQ_OFFSET );
147 }
148 void mt_set_pwm_disable_seqmode_hal(void)
149 {
150 CLRREG32 ( PWM_ENABLE,1 << PWM_ENABLE_SEQ_OFFSET );
151 }
152 S32 mt_set_pwm_test_sel_hal(U32 val)
153 {
154 if (val == TEST_SEL_TRUE)
155 SETREG32 ( PWM_ENABLE, 1 << PWM_ENABLE_TEST_SEL_OFFSET );
156 else if ( val == TEST_SEL_FALSE )
157 CLRREG32 ( PWM_ENABLE, 1 << PWM_ENABLE_TEST_SEL_OFFSET );
158 else
159 return 1;
160 return 0;
161 }
162 void mt_set_pwm_clk_hal (U32 pwm_no, U32 clksrc, U32 div )
163 {
164 U32 reg_con;
165
166 if (clksrc != PWM_CLK_OLD_MODE_32K){
167 printk(KERN_ERR"********PWM could only select 32K src, otherwise waveform may be affected by SSC!!!************\n");
168 }
169
170 reg_con = PWM_register [pwm_no] + 4* PWM_CON;
171 MASKREG32 ( reg_con, PWM_CON_CLKDIV_MASK, div );
172 if (clksrc == CLK_BLOCK)
173 CLRREG32 ( reg_con, 1 << PWM_CON_CLKSEL_OFFSET );
174 else if (clksrc == CLK_BLOCK_BY_1625_OR_32K)
175 SETREG32 ( reg_con, 1 << PWM_CON_CLKSEL_OFFSET );
176 }
177 S32 mt_get_pwm_clk_hal(U32 pwm_no)
178 {
179 S32 clk, clksrc, clkdiv;
180 U32 reg_con, reg_val,reg_en;
181
182 reg_con = PWM_register[pwm_no] + 4*PWM_CON;
183
184 reg_val = INREG32 (reg_con);
185 reg_en = INREG32 (PWM_ENABLE);
186
187 if ( ( ( reg_val & PWM_CON_CLKSEL_MASK ) >> PWM_CON_CLKSEL_OFFSET ) == 1 )
188 if ( ((reg_en &PWM_CON_OLD_MODE_MASK) >> PWM_CON_OLD_MODE_OFFSET ) == 1)
189 clksrc = 32*1024;
190 else clksrc = BLOCK_CLK;
191 else
192 clksrc = BLOCK_CLK/1625;
193
194 clkdiv = 2 << ( reg_val & PWM_CON_CLKDIV_MASK);
195 if ( clkdiv <= 0 ) {
196 PWMDBG ( "clkdiv less zero, not valid \n" );
197 return -ERROR;
198 }
199
200 clk = clksrc/clkdiv;
201 PWMDBG ( "CLK is :%d\n", clk );
202 return clk;
203 }
204 S32 mt_set_pwm_con_datasrc_hal ( U32 pwm_no, U32 val )
205 {
206 U32 reg_con;
207
208 reg_con = PWM_register[pwm_no] + 4*PWM_CON;
209 if ( val == PWM_FIFO )
210 CLRREG32 ( reg_con, 1 << PWM_CON_SRCSEL_OFFSET );
211 else if ( val == MEMORY )
212 SETREG32 ( reg_con, 1 << PWM_CON_SRCSEL_OFFSET );
213 else
214 return 1;
215 return 0;
216 }
217 S32 mt_set_pwm_con_mode_hal( U32 pwm_no, U32 val )
218 {
219 U32 reg_con;
220
221 reg_con = PWM_register[pwm_no] + 4*PWM_CON;
222 if ( val == PERIOD )
223 CLRREG32 ( reg_con, 1 << PWM_CON_MODE_OFFSET );
224 else if (val == RAND)
225 SETREG32 ( reg_con, 1 << PWM_CON_MODE_OFFSET );
226 else
227 return 1;
228 return 0;
229 }
230 S32 mt_set_pwm_con_idleval_hal(U32 pwm_no, U16 val)
231 {
232 U32 reg_con;
233
234 reg_con = PWM_register[pwm_no] + 4*PWM_CON;
235 if ( val == IDLE_TRUE )
236 SETREG32 ( reg_con,1 << PWM_CON_IDLE_VALUE_OFFSET );
237 else if ( val == IDLE_FALSE )
238 CLRREG32 ( reg_con, 1 << PWM_CON_IDLE_VALUE_OFFSET );
239 else
240 return 1;
241 return 0;
242 }
243 S32 mt_set_pwm_con_guardval_hal(U32 pwm_no, U16 val)
244 {
245 U32 reg_con;
246
247 reg_con = PWM_register[pwm_no] + 4*PWM_CON;
248 if ( val == GUARD_TRUE )
249 SETREG32 ( reg_con, 1 << PWM_CON_GUARD_VALUE_OFFSET );
250 else if ( val == GUARD_FALSE )
251 CLRREG32 ( reg_con, 1 << PWM_CON_GUARD_VALUE_OFFSET );
252 else
253 return 1;
254 return 0;
255 }
256 void mt_set_pwm_con_stpbit_hal(U32 pwm_no, U32 stpbit, U32 srcsel )
257 {
258 U32 reg_con;
259
260 reg_con = PWM_register[pwm_no] + 4*PWM_CON;
261 if ( srcsel == PWM_FIFO )
262 MASKREG32 ( reg_con, PWM_CON_STOP_BITS_MASK, stpbit << PWM_CON_STOP_BITS_OFFSET);
263 if ( srcsel == MEMORY )
264 MASKREG32 ( reg_con, PWM_CON_STOP_BITS_MASK & (0x1f << PWM_CON_STOP_BITS_OFFSET), stpbit << PWM_CON_STOP_BITS_OFFSET);
265 }
266 S32 mt_set_pwm_con_oldmode_hal ( U32 pwm_no, U32 val )
267 {
268 U32 reg_con;
269
270 reg_con = PWM_register[pwm_no] + 4*PWM_CON;
271 if ( val == OLDMODE_DISABLE )
272 CLRREG32 ( reg_con, 1 << PWM_CON_OLD_MODE_OFFSET );
273 else if ( val == OLDMODE_ENABLE )
274 SETREG32 ( reg_con, 1 << PWM_CON_OLD_MODE_OFFSET );
275 else
276 return 1;
277 return 0;
278 }
279 void mt_set_pwm_HiDur_hal(U32 pwm_no, U16 DurVal)//only low 16 bits are valid
280 {
281 U32 reg_HiDur;
282
283 reg_HiDur = PWM_register[pwm_no]+4*PWM_HDURATION;
284 OUTREG32 ( reg_HiDur, DurVal);
285 }
286 void mt_set_pwm_LowDur_hal (U32 pwm_no, U16 DurVal)
287 {
288 U32 reg_LowDur;
289 reg_LowDur = PWM_register[pwm_no] + 4*PWM_LDURATION;
290 OUTREG32 ( reg_LowDur, DurVal );
291 }
292 void mt_set_pwm_GuardDur_hal (U32 pwm_no, U16 DurVal)
293 {
294 U32 reg_GuardDur;
295 reg_GuardDur = PWM_register[pwm_no] + 4*PWM_GDURATION;
296 OUTREG32 ( reg_GuardDur, DurVal );
297 }
298 void mt_set_pwm_send_data0_hal ( U32 pwm_no, U32 data )
299 {
300 U32 reg_data0;
301 reg_data0 = PWM_register[pwm_no] + 4 * PWM_SEND_DATA0;
302 OUTREG32 ( reg_data0, data );
303 }
304 void mt_set_pwm_send_data1_hal ( U32 pwm_no, U32 data )
305 {
306 U32 reg_data1;
307 reg_data1 = PWM_register[pwm_no] + 4 * PWM_SEND_DATA1;
308 OUTREG32 ( reg_data1, data );
309 }
310 void mt_set_pwm_wave_num_hal ( U32 pwm_no, U16 num )
311 {
312 U32 reg_wave_num;
313 reg_wave_num = PWM_register[pwm_no] + 4 * PWM_WAVE_NUM;
314 OUTREG32 ( reg_wave_num, num );
315 }
316 void mt_set_pwm_data_width_hal ( U32 pwm_no, U16 width )
317 {
318 U32 reg_data_width;
319 if (pwm_no == PWM5 || pwm_no == PWM4) {
320 reg_data_width = PWM_register[pwm_no] + 4 * PWM_THRESH;
321 } else {
322 reg_data_width = PWM_register[pwm_no] + 4 * PWM_DATA_WIDTH;
323 }
324 OUTREG32 ( reg_data_width, width );
325 }
326 void mt_set_pwm_thresh_hal ( U32 pwm_no, U16 thresh )
327 {
328 U32 reg_thresh;
329
330 if (pwm_no == PWM5 || pwm_no == PWM4) {
331 reg_thresh = PWM_register[pwm_no] + 4 * PWM_SEND_WAVENUM;
332 } else {
333 reg_thresh = PWM_register[pwm_no] + 4 * PWM_THRESH;
334 }
335 OUTREG32 ( reg_thresh, thresh );
336 }
337 S32 mt_get_pwm_send_wavenum_hal ( U32 pwm_no )
338 {
339 U32 reg_send_wavenum;
340
341 if ( pwm_no <=PWM3 )
342 reg_send_wavenum = PWM_register[pwm_no] + 4 * PWM_SEND_WAVENUM;
343 else
344 reg_send_wavenum = PWM_register[pwm_no] + 4 * (PWM_SEND_WAVENUM - 2); //pwm4,pwm5,pwm6 has no data width and thresh register
345 return INREG32 ( reg_send_wavenum );
346 }
347
348 void mt_set_intr_enable_hal(U32 pwm_intr_enable_bit)
349 {
350 SETREG32 ( PWM_INT_ENABLE, 1 << pwm_intr_enable_bit );
351 }
352 S32 mt_get_intr_status_hal(U32 pwm_intr_status_bit)
353 {
354 int ret;
355 ret = INREG32 ( PWM_INT_STATUS );
356 ret = ( ret >> pwm_intr_status_bit ) & 0x01;
357 return ret;
358 }
359 void mt_set_intr_ack_hal ( U32 pwm_intr_ack_bit )
360 {
361 SETREG32 ( PWM_INT_ACK, 1 << pwm_intr_ack_bit );
362 }
363
364 void mt_pwm_dump_regs_hal(void)
365 {
366 int i;
367 U32 reg_val;
368 reg_val = INREG32(PWM_ENABLE);
369 PWMMSG("\r\n[PWM_ENABLE is:%x]\n\r ", reg_val );
370 printk("<0>""peri pdn0 clock: 0x%x\n", INREG32(PERI_PDN0_STA));
371
372 for ( i = PWM1; i < PWM_MAX; i ++ )
373 {
374 reg_val = INREG32(PWM_register[i] + 4* PWM_CON);
375 PWMMSG("\r\n[PWM%d_CON is:%x]\r\n", i+1, reg_val);
376 reg_val=INREG32(PWM_register[i]+4* PWM_HDURATION);
377 PWMMSG("[PWM%d_HDURATION is:%x]\r\n",i+1,reg_val);
378 reg_val = INREG32(PWM_register[i] + 4* PWM_LDURATION);
379 PWMMSG("[PWM%d_LDURATION is:%x]\r\n", i+1, reg_val);
380 reg_val=INREG32(PWM_register[i]+4* PWM_GDURATION);
381 PWMMSG("[PWM%d_GDURATION is:%x]\r\n",i+1,reg_val);
382 /*
383 reg_val = INREG32(PWM_register[i] + 4* PWM_BUF0_BASE_ADDR);
384 PWMMSG("\r\n[PWM%d_BUF0_BASE_ADDR is:%x]\r\n", i, reg_val);
385 reg_val=INREG32(PWM_register[i]+4* PWM_BUF0_SIZE);
386 PWMMSG("\r\n[PWM%d_BUF0_SIZE is:%x]\r\n",i,reg_val);
387 reg_val = INREG32(PWM_register[i] + 4* PWM_BUF1_BASE_ADDR);
388 PWMMSG("\r\n[PWM%d_BUF1_BASE_ADDR is:%x]\r\n", i, reg_val);
389 reg_val=INREG32(PWM_register[i]+4* PWM_BUF1_SIZE);
390 PWMMSG("\r\n[PWM%d_BUF1_SIZE is:%x]\r\n",i+1,reg_val);
391 */
392 reg_val = INREG32(PWM_register[i] + 4* PWM_SEND_DATA0);
393 PWMMSG("[PWM%d_SEND_DATA0 is:%x]\r\n", i+1, reg_val);
394 reg_val=INREG32(PWM_register[i]+4* PWM_SEND_DATA1);
395 PWMMSG("[PWM%d_PWM_SEND_DATA1 is:%x]\r\n",i+1,reg_val);
396 reg_val = INREG32(PWM_register[i] + 4* PWM_WAVE_NUM);
397 PWMMSG("[PWM%d_WAVE_NUM is:%x]\r\n", i+1, reg_val);
398 if(i==PWM5||i==PWM4){
399 reg_val=INREG32(PWM_register[i]+4* PWM_THRESH);
400 }else{
401 reg_val=INREG32(PWM_register[i]+4* PWM_DATA_WIDTH);
402 }
403 PWMMSG("[PWM%d_WIDTH is:%x]\r\n",i+1,reg_val);
404 if(i==PWM5||i==PWM4){
405 reg_val=INREG32(PWM_register[i]+4* PWM_SEND_WAVENUM);
406 }else{
407 reg_val=INREG32(PWM_register[i]+4* PWM_THRESH);
408 }
409 PWMMSG("[PWM%d_THRESH is:%x]\r\n",i+1,reg_val);
410 if(i==PWM5||i==PWM4){
411 reg_val=INREG32(PWM_register[i]+4* PWM_DATA_WIDTH);
412 }else{
413 reg_val=INREG32(PWM_register[i]+4* PWM_SEND_WAVENUM);
414 }
415 PWMMSG("[PWM%d_SEND_WAVENUM is:%x]\r\n",i+1,reg_val);
416 /*
417 reg_val=INREG32(PWM_register[i]+4* PWM_VALID);
418 PWMMSG("\r\n[PWM%d_SEND_VALID is:%x]\r\n",i+1,reg_val);
419 */
420 }
421 }
422 /*----------------------------*/
423 static void mt_pmic_pwm1_test(void)
424 {/*
425 struct pwm_spec_config conf;
426 printk("<0>""=============mt_pmic_pwm1_test===============\n");
427
428 mt_set_gpio_mode(GPIO12,GPIO_MODE_02);
429 conf.pwm_no = PWM1;
430 conf.mode = PWM_MODE_FIFO;
431 conf.clk_div = CLK_DIV1;
432 conf.clk_src = PWM_CLK_NEW_MODE_BLOCK;
433 //conf.intr = FALSE;
434 conf.pmic_pad = false;
435 conf.PWM_MODE_FIFO_REGS.IDLE_VALUE = IDLE_FALSE;
436 conf.PWM_MODE_FIFO_REGS.GUARD_VALUE = GUARD_FALSE;
437 conf.PWM_MODE_FIFO_REGS.STOP_BITPOS_VALUE = 62;
438 conf.PWM_MODE_FIFO_REGS.HDURATION = 0;
439 conf.PWM_MODE_FIFO_REGS.LDURATION = 0;
440 conf.PWM_MODE_FIFO_REGS.GDURATION = 0;
441 conf.PWM_MODE_FIFO_REGS.SEND_DATA0 = 0xf0f0f0f0;
442 conf.PWM_MODE_FIFO_REGS.SEND_DATA1 = 0xf0f0f0f0;
443 conf.PWM_MODE_FIFO_REGS.WAVE_NUM = 0;
444 printk(KERN_INFO "PWM: clk_div = %x, clk_src = %x, pwm_no = %x\n", conf.clk_div, conf.clk_src, conf.pwm_no);
445 pwm_set_spec_config(&conf);
446
447 mt_set_gpio_mode(GPIO1,GPIO_MODE_01);
448 conf.pwm_no = PWM2;
449 conf.PWM_MODE_FIFO_REGS.STOP_BITPOS_VALUE = 30;
450 pwm_set_spec_config(&conf);*/
451 }
452
453 static void mt_pmic_pwm6_test(void)
454 {
455 //printk("<0>""=================mt_pmic_pwm6_test==================\n");
456
457 //mt_pwm_disable(PWM1, false);
458 //mt_pwm_disable(PWM7, true);
459 }
460
461 void pwm_debug_store_hal()
462 {
463 //dump clock status
464 printk("<0>""peri pdn0 clock: 0x%x\n", INREG32(PERI_PDN0_STA));
465 mt_pmic_pwm1_test();
466 }
467
468 void pwm_debug_show_hal()
469 {
470 mt_pwm_dump_regs_hal();
471 mt_pmic_pwm6_test();
472 }
473
474 /*----------3dLCM support-----------*/
475 /*
476 base pwm2, select pwm3&4&5 same as pwm2 or inversion of pwm2
477 */
478 void mt_set_pwm_3dlcm_enable_hal(BOOL enable)
479 {
480 SETREG32 ( PWM_3DLCM, 1 << PWM_3DLCM_ENABLE_OFFSET );
481 }
482
483 /*
484 set "pwm_no" inversion of pwm2 or not,
485 pwm_no: only support PWM3/4/5
486 */
487 void mt_set_pwm_3dlcm_inv_hal(U32 pwm_no, BOOL inv)
488 {
489 if (inv){
490 if (pwm_no == PWM3){
491 SETREG32 ( PWM_3DLCM, 1 << PWM_3DLCM_0_INV );
492 }else if (pwm_no == PWM4){
493 SETREG32 ( PWM_3DLCM, 1 << PWM_3DLCM_1_INV );
494 }else if (pwm_no == PWM5){
495 SETREG32 ( PWM_3DLCM, 1 << PWM_3DLCM_2_INV );
496 }
497 }else{
498 if (pwm_no == PWM3){
499 CLRREG32 ( PWM_3DLCM, 1 << PWM_3DLCM_0_INV );
500 }else if (pwm_no == PWM4){
501 CLRREG32 ( PWM_3DLCM, 1 << PWM_3DLCM_1_INV );
502 }else if (pwm_no == PWM5){
503 CLRREG32 ( PWM_3DLCM, 1 << PWM_3DLCM_2_INV );
504 }
505 }
506 }
507
508 void mt_set_pwm_3dlcm_base_hal(U32 pwm_no)
509 {
510 }
511
512 void mt_pwm_26M_clk_enable_hal (U32 enable)
513 {
514 }
515