tizen 2.4 release
[kernel/u-boot-tm1.git] / board / spreadtrum / sc8810_openphone / sprd_kp.c
1 #include <common.h>
2 #include <malloc.h>
3 #include "key_map.h"
4 #ifdef CONFIG_SC8810
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     return;
84 }
85
86 static char handle_scan_code(unsigned char scan_code)
87 {
88     int cnt;
89     int key_map_cnt;
90     unsigned char * key_map;
91     int pos = 0;
92
93     if(NULL == sprd_key_map){
94         printf("plase call board_keypad_init first\n");
95         return 0;
96     }
97
98     key_map_cnt = sprd_key_map->total_size / sprd_key_map->keycode_size;
99     key_map = sprd_key_map->key_map;
100 #ifdef KEYPAD_DEBUG
101     printf("scan code %d\n", scan_code);
102 #endif
103     for(cnt = 0; cnt<key_map_cnt; cnt++){
104         pos = cnt * 2;
105         if(key_map[pos] == scan_code)
106           return key_map[pos + 1];
107     }
108     return 0;
109 }
110
111 //it can only handle one key now
112 unsigned char board_key_scan(void)
113 {
114     uint32_t s_int_status = REG_KPD_INT_RAW_STATUS;
115     uint32_t s_key_status = REG_KPD_KEY_STATUS;
116     uint32_t scan_code = 0;
117     uint32_t key_code =0;
118
119     if((s_int_status & KPD_PRESS_INT0) || (s_int_status & KPD_LONG_KEY_INT0)){
120         scan_code = s_key_status & (KPD1_ROW_CNT | KPD1_COL_CNT);
121         key_code = handle_scan_code(scan_code);
122     }else if((s_int_status & KPD_PRESS_INT1) || (s_int_status & KPD_LONG_KEY_INT1)){
123         scan_code = (s_key_status & (KPD2_ROW_CNT | KPD2_COL_CNT))>>8;
124         key_code = handle_scan_code(scan_code);
125     }else if((s_int_status & KPD_PRESS_INT2) || (s_int_status & KPD_LONG_KEY_INT2)){
126         scan_code = (s_key_status & (KPD3_ROW_CNT | KPD3_COL_CNT))>>16;
127         key_code = handle_scan_code(scan_code);
128     }else if((s_int_status & KPD_PRESS_INT3) || (s_int_status & KPD_LONG_KEY_INT3)){
129         scan_code = (s_key_status & (KPD4_ROW_CNT | KPD4_COL_CNT))>>24;
130         key_code = handle_scan_code(scan_code);
131     }
132
133     if(s_int_status)
134         REG_KPD_INT_CLR = KPD_INT_ALL;
135     return key_code;
136 }
137
138 unsigned int check_key_boot(unsigned char key)
139 {
140     if(KEY_MENU == key)
141       return BOOT_CALIBRATE;
142     else if(KEY_HOME == key)
143       return BOOT_FASTBOOT;
144     else if(KEY_BACK == key)
145       return BOOT_RECOVERY;
146     else if(KEY_VOLUMEUP== key)
147       return BOOT_DLOADER;
148     else 
149       return 0;
150 }