tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / board / spreadtrum / sp6825ga / sprd_kp.c
1 #include <common.h>
2 #include <malloc.h>
3 #include "key_map.h"
4 #ifdef CONFIG_TIGER
5 #include <asm/arch/sc8810_keypad.h>
6 #else
7 #error "no keypad definition file included"
8 #endif
9 #include <asm/arch/mfp.h>
10 #include <boot_mode.h>
11
12 struct key_map_info * sprd_key_map = 0;
13
14 static unsigned long keypad_func_cfg[] = {
15         MFP_CFG_X(KEYOUT0, AF0, DS1, F_PULL_NONE, S_PULL_NONE, IO_OE),
16         MFP_CFG_X(KEYOUT1, AF0, DS1, F_PULL_NONE, S_PULL_NONE, IO_OE),
17         MFP_CFG_X(KEYOUT2, AF0, DS1, F_PULL_NONE, S_PULL_NONE, IO_OE),
18         MFP_CFG_X(KEYOUT3, AF0, DS1, F_PULL_NONE, S_PULL_NONE, IO_OE),
19         MFP_CFG_X(KEYOUT4, AF0, DS1, F_PULL_NONE, S_PULL_NONE, IO_OE),
20         MFP_CFG_X(KEYOUT5, AF0, DS1, F_PULL_NONE, S_PULL_NONE, IO_OE),
21         MFP_CFG_X(KEYOUT6, AF0, DS1, F_PULL_NONE, S_PULL_NONE, IO_OE),
22         MFP_CFG_X(KEYOUT7, AF0, DS1, F_PULL_NONE, S_PULL_NONE, IO_OE),
23         MFP_CFG_X(KEYIN0,  AF0, DS1, F_PULL_UP,   S_PULL_UP,   IO_IE),
24         MFP_CFG_X(KEYIN1,  AF0, DS1, F_PULL_UP,   S_PULL_UP,   IO_IE),
25         MFP_CFG_X(KEYIN2,  AF0, DS1, F_PULL_UP,   S_PULL_UP,   IO_IE),
26         MFP_CFG_X(KEYIN3,  AF0, DS1, F_PULL_UP,   S_PULL_UP,   IO_IE),
27         MFP_CFG_X(KEYIN4,  AF0, DS1, F_PULL_UP,   S_PULL_UP,   IO_IE),
28         MFP_CFG_X(KEYIN5,  AF0, DS1, F_PULL_UP,   S_PULL_UP,   IO_IE),
29         MFP_CFG_X(KEYIN6,  AF0, DS1, F_PULL_UP,   S_PULL_UP,   IO_IE),
30         MFP_CFG_X(KEYIN7,  AF0, DS1, F_PULL_UP,   S_PULL_UP,   IO_IE),
31 };
32
33 static void sprd_config_keypad_pins(void)
34 {
35         sprd_mfp_config(keypad_func_cfg, ARRAY_SIZE(keypad_func_cfg));
36 }
37
38 void board_keypad_init(void)
39 {
40     unsigned int key_type;
41
42     sprd_key_map = malloc(sizeof(struct key_map_info));
43
44     if(NULL == sprd_key_map){
45       printf("%s malloc faild\n", __FUNCTION__);
46       return;
47     }
48
49     sprd_key_map->total_size = ARRAY_SIZE(board_key_map);
50     sprd_key_map->keycode_size = sizeof(board_key_map[0])*2;
51     sprd_key_map->key_map = board_key_map;
52     sprd_key_map->total_row = CONFIG_KEYPAD_ROW_CNT;
53     sprd_key_map->total_col = CONFIG_KEYPAD_COL_CNT;
54
55     if(sprd_key_map->total_size % sprd_key_map->keycode_size){
56         printf("%s: board_key_map config error, it should be %d aligned\n", __FUNCTION__, sprd_key_map->keycode_size);
57         return;
58     }
59
60     /* init sprd keypad controller */
61     REG_INT_DIS = (1 << IRQ_KPD_INT);
62     REG_GR_GEN0 |= BIT_8 | BIT_26;
63     sprd_config_keypad_pins();
64     REG_KPD_INT_CLR = KPD_INT_ALL;
65     REG_KPD_POLARITY = CFG_ROW_POLARITY | CFG_COL_POLARITY;
66     REG_KPD_CLK_DIV_CNT = CFG_CLK_DIV & KPDCLK0_CLK_DIV0;
67     REG_KPD_LONG_KEY_CNT = CONFIG_KEYPAD_LONG_CNT;
68     REG_KPD_DEBOUNCE_CNT = CONFIG_KEYPAD_DEBOUNCE_CNT;//0x8;0x13
69     key_type = ((((~(0xffffffff << (sprd_key_map->total_col - KPD_COL_MIN_NUM))) << 20) | ((~(0xffffffff << (sprd_key_map->total_row- KPD_ROW_MIN_NUM))) << 16)) & (KPDCTL_ROW | KPDCTL_COL));
70     REG_KPD_CTRL = 0x7 | key_type;
71     
72     //open all press & release & long key operation flags
73     REG_KPD_INT_EN = KPD_INT_ALL;
74 #if 0
75     for(;;){
76         if(REG_KPD_INT_RAW_STATUS){
77             printf("key operation flags is %08x, key %08x\n", REG_KPD_INT_RAW_STATUS, REG_KPD_KEY_STATUS);
78
79             REG_KPD_INT_CLR = KPD_INT_ALL;
80         }
81     }
82 #endif
83         //open eic module
84         REG_GR_GEN0 |= (BIT_9 | BIT_24);//EIC_EN,RTC_EIC_EN
85         printf("GEN0 %x\n", REG_GR_GEN0);
86     return;
87 }
88
89 static char handle_scan_code(unsigned char scan_code)
90 {
91     int cnt;
92     int key_map_cnt;
93     unsigned char * key_map;
94     int pos = 0;
95
96     if(NULL == sprd_key_map){
97         printf("plase call board_keypad_init first\n");
98         return 0;
99     }
100
101     key_map_cnt = sprd_key_map->total_size / sprd_key_map->keycode_size;
102     key_map = sprd_key_map->key_map;
103 #ifdef KEYPAD_DEBUG
104     printf("scan code %d\n", scan_code);
105 #endif
106     for(cnt = 0; cnt<key_map_cnt; cnt++){
107         pos = cnt * 2;
108         if(key_map[pos] == scan_code)
109           return key_map[pos + 1];
110     }
111     return 0;
112 }
113
114 //it can only handle one key now
115 unsigned char board_key_scan(void)
116 {
117     uint32_t s_int_status = REG_KPD_INT_RAW_STATUS;
118     uint32_t s_key_status = REG_KPD_KEY_STATUS;
119     uint32_t scan_code = 0;
120     uint32_t key_code =0;
121 #ifdef KEYPAD_DEBUG
122         printf("key operation flags is %08x, key %08x\n", REG_KPD_INT_RAW_STATUS, REG_KPD_KEY_STATUS);
123 #endif
124     if((s_int_status & KPD_PRESS_INT0) || (s_int_status & KPD_LONG_KEY_INT0)){
125         scan_code = s_key_status & (KPD1_ROW_CNT | KPD1_COL_CNT);
126         key_code = handle_scan_code(scan_code);
127     }else if((s_int_status & KPD_PRESS_INT1) || (s_int_status & KPD_LONG_KEY_INT1)){
128         scan_code = (s_key_status & (KPD2_ROW_CNT | KPD2_COL_CNT))>>8;
129         key_code = handle_scan_code(scan_code);
130     }else if((s_int_status & KPD_PRESS_INT2) || (s_int_status & KPD_LONG_KEY_INT2)){
131         scan_code = (s_key_status & (KPD3_ROW_CNT | KPD3_COL_CNT))>>16;
132         key_code = handle_scan_code(scan_code);
133     }else if((s_int_status & KPD_PRESS_INT3) || (s_int_status & KPD_LONG_KEY_INT3)){
134         scan_code = (s_key_status & (KPD4_ROW_CNT | KPD4_COL_CNT))>>24;
135         key_code = handle_scan_code(scan_code);
136     }
137
138     if(s_int_status)
139         REG_KPD_INT_CLR = KPD_INT_ALL;
140     return key_code;
141 }
142
143 unsigned int check_key_boot(unsigned char key)
144 {
145     if(KEY_MENU == key)
146       return BOOT_CALIBRATE;
147     else if(KEY_HOME == key)
148       return BOOT_FASTBOOT;
149     else if(KEY_BACK == key)
150       return BOOT_RECOVERY;
151     else if(KEY_VOLUMEUP== key)
152       return BOOT_DLOADER;
153     else 
154       return 0;
155 }