]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/drivers/input/src/kp-omap3.c
update
[l4.git] / l4 / pkg / drivers / input / src / kp-omap3.c
1 /*
2  * OMAP keypad driver
3  */
4
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8
9 #include <pthread.h>
10 #include <pthread-l4.h>
11
12 #include <l4/input/drv_reg.h>
13 #include <l4/io/io.h>
14 #include <l4/re/c/namespace.h>
15 #include <l4/re/c/util/cap_alloc.h>
16 #include <l4/re/event_enums.h>
17 #include <l4/util/util.h>
18 #include <l4/sys/irq.h>
19 #include <l4/sys/thread.h>
20 #include <l4/sys/debugger.h>
21 #include <l4/vbus/vbus.h>
22 #include <l4/vbus/vbus_i2c.h>
23
24 #include "kp-omap.h"
25
26
27 #define NUM_ROWS 4
28 #define NUM_COLS 4
29
30 static unsigned char kp_keycode[16] = {
31
32     L4RE_KEY_1, L4RE_KEY_2, L4RE_KEY_3, L4RE_KEY_4,
33     L4RE_KEY_5, L4RE_KEY_6, L4RE_KEY_7, L4RE_KEY_8,
34     L4RE_KEY_9, L4RE_KEY_0, L4RE_KEY_A, L4RE_KEY_B,
35     L4RE_KEY_C, L4RE_KEY_D, L4RE_KEY_E, L4RE_KEY_F,
36 };
37
38 static Input_handler kp_handler;
39 static void* kp_priv;
40 static pthread_t _pthread;
41
42 static l4_cap_idx_t vbus = L4_INVALID_CAP;
43 static l4vbus_device_handle_t i2c_handle = 0;
44
45 /* I2C slave ID */
46 #define TWL4030_SLAVENUM_NUM0 0x48
47 #define TWL4030_SLAVENUM_NUM1 0x49
48 #define TWL4030_SLAVENUM_NUM2 0x4a
49 #define TWL4030_SLAVENUM_NUM3 0x4b
50
51 /* Module Mapping */
52 struct twl4030mapping
53 {
54   unsigned char sid;    /* Slave ID */
55   unsigned char base;   /* base address */
56 };
57
58 /* mapping the module id to slave id and base address */
59 static struct twl4030mapping twl4030_map[TWL4030_MODULES + 1] = {
60       { TWL4030_SLAVENUM_NUM0, TWL4030_BASE_USB },
61       { TWL4030_SLAVENUM_NUM1, TWL4030_BASE_AUDIO_VOICE },
62       { TWL4030_SLAVENUM_NUM1, TWL4030_BASE_GPIO },
63       { TWL4030_SLAVENUM_NUM1, TWL4030_BASE_INTBR },
64       { TWL4030_SLAVENUM_NUM1, TWL4030_BASE_PIH },
65       { TWL4030_SLAVENUM_NUM1, TWL4030_BASE_TEST },
66       { TWL4030_SLAVENUM_NUM2, TWL4030_BASE_KEYPAD },
67       { TWL4030_SLAVENUM_NUM2, TWL4030_BASE_MADC },
68       { TWL4030_SLAVENUM_NUM2, TWL4030_BASE_INTERRUPTS },
69       { TWL4030_SLAVENUM_NUM2, TWL4030_BASE_LED },
70       { TWL4030_SLAVENUM_NUM2, TWL4030_BASE_MAIN_CHARGE },
71       { TWL4030_SLAVENUM_NUM2, TWL4030_BASE_PRECHARGE },
72       { TWL4030_SLAVENUM_NUM2, TWL4030_BASE_PWM0 },
73       { TWL4030_SLAVENUM_NUM2, TWL4030_BASE_PWM1 },
74       { TWL4030_SLAVENUM_NUM2, TWL4030_BASE_PWMA },
75       { TWL4030_SLAVENUM_NUM2, TWL4030_BASE_PWMB },
76       { TWL4030_SLAVENUM_NUM3, TWL4030_BASE_BACKUP },
77       { TWL4030_SLAVENUM_NUM3, TWL4030_BASE_INT },
78       { TWL4030_SLAVENUM_NUM3, TWL4030_BASE_PM_MASTER },
79       { TWL4030_SLAVENUM_NUM3, TWL4030_BASE_PM_RECIEVER },
80       { TWL4030_SLAVENUM_NUM3, TWL4030_BASE_RTC },
81       { TWL4030_SLAVENUM_NUM3, TWL4030_BASE_SECURED_REG },
82 };
83
84 #if 1
85 static int twl4030_i2c_write_u8(unsigned mod_no, l4_uint8_t value, l4_uint8_t reg)
86 {
87   return l4vbus_i2c_write(vbus, i2c_handle, twl4030_map[mod_no].sid, twl4030_map[mod_no].base + reg, &value, 1);
88 }
89
90 static int twl4030_i2c_read_u8(unsigned mod_no, l4_uint8_t *value, l4_uint8_t reg)
91 {
92   unsigned long size = 1;
93   return l4vbus_i2c_read(vbus, i2c_handle, twl4030_map[mod_no].sid, twl4030_map[mod_no].base + reg, value, &size);
94 }
95 #endif
96
97 static int twl4030_i2c_read_u32(int mod_no, l4_uint8_t *value, l4_uint8_t reg)
98 {
99   unsigned long size = 4;
100   return l4vbus_i2c_read(vbus, i2c_handle, twl4030_map[mod_no].sid, twl4030_map[mod_no].base + reg, value, &size);
101 }
102
103 static int kp_read(int reg, l4_uint8_t *val)
104 {
105   unsigned long size = 1;
106   return l4vbus_i2c_read(vbus, i2c_handle, twl4030_map[TWL4030_MODULE_KEYPAD].sid,
107                          twl4030_map[TWL4030_MODULE_KEYPAD].base + reg, val, &size);
108 }
109
110 static int kp_write(int reg, l4_uint8_t val)
111 {
112   return l4vbus_i2c_write(vbus, i2c_handle, twl4030_map[TWL4030_MODULE_KEYPAD].sid,
113                           twl4030_map[TWL4030_MODULE_KEYPAD].base + reg, &val, 1);
114 }
115
116 #if 1
117 static int twl_init_irq(void)
118 {
119   int ret = 0;
120
121   /* PWR_ISR1 */
122   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);
123   /* PWR_ISR2 */
124   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);
125   /* PWR_IMR1 */
126   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x1);
127   /* PWR_IMR2 */
128   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x3);
129   /* PWR_ISR1 */
130   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);
131   /* PWR_ISR2 */
132   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);
133   
134   /* BCIIMR1_1 */
135   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x3);
136   /* BCIIMR1_2 */
137   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x4);
138   /* BCIIMR2_1 */
139   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x7);
140   /* BCIIMR2_2 */
141   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x8);
142   
143   /* MADC */
144   /* MADC_IMR1 */
145   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x62);
146   /* MADC_IMR2 */
147   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x64);
148   /* GPIO_IMR1A */
149   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x1C);
150   /* GPIO_IMR2A */
151   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x1D);
152   /* GPIO_IMR3A */
153   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x1E);
154   /* GPIO_IMR1B */
155   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x22);
156   /* GPIO_IMR2B */
157   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x23);
158   /* GPIO_IMR3B */
159   ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x24);
160
161   return ret;
162 }
163 #endif
164
165 static int init_keypad(void)
166 {
167   int ret = 0;
168
169   twl_init_irq();
170
171   // Enable software mode and keypad power on
172   ret = kp_write(REG_KEYP_CTRL_REG, 0x43);
173   // Mask all interrupts
174   ret |= kp_write(REG_KEYP_IMR1, 0x0f);
175     {
176       /* Clear ISR */
177       l4_uint8_t v;
178       kp_read(REG_KEYP_ISR1, &v);
179       kp_read(REG_KEYP_ISR1, &v);
180     }
181   // Trigger interrupts on rising edge
182   ret |= kp_write(REG_KEYP_EDR, 0xaa);
183   // Set pre scalar field
184   ret |= kp_write(REG_LK_PTV_REG, 4 << 5);
185   // Set key debounce time 
186   ret |= kp_write(REG_KEY_DEB_REG, 0x3f);
187   // Enable COR-mode
188   ret |= kp_write(REG_KEYP_SIH_CTRL, 0x4);
189   // unmask all interrupts
190   ret |= kp_write(REG_KEYP_IMR1, 0);
191
192   return ret;
193 }
194
195 static void drive_vibr(void)
196 {
197   // VIBRATOR_CFG
198   l4_uint8_t v = (1<<3)|(1<<2)|1;
199   unsigned long s = 1;
200   l4vbus_i2c_write(vbus, i2c_handle, 0x4b, 0x60, &v, 1);
201   // configure mux
202   //v = 0x10;
203   //l4vbus_i2c_write(vbus, i2c_handle, 0x49, 0x92, &v, 1);
204   
205   l4_uint16_t w = (0x4 << 13)|(0x1 << 12)|(0x1 << 4)|(0xe);
206   l4_uint8_t *p = (l4_uint8_t *)(&w);
207   l4vbus_i2c_write(vbus, i2c_handle, 0x4b, 0x4b, &(p[1]), 1);
208   l4vbus_i2c_write(vbus, i2c_handle, 0x4b, 0x4c, &(p[0]), 1);
209   printf("WRITE:%x %x\n", p[1], p[0]);
210   
211   l4vbus_i2c_read(vbus, i2c_handle, 0x4b, 0x73, &v, &s);
212   printf("VAUX1_TYPE:%x\n", v);
213   l4vbus_i2c_read(vbus, i2c_handle, 0x4b, 0x74, &v, &s);
214   printf("VAUX1_REMAP:%x\n", v);
215   l4vbus_i2c_read(vbus, i2c_handle, 0x4b, 0x75, &v, &s);
216   printf("VAUX1_DEDICATED:%x\n", v);
217   l4vbus_i2c_read(vbus, i2c_handle, 0x4b, 0x76, &v, &s);
218   printf("VAUX1_DEV_GRP:%x\n", v);
219 }
220
221 static void reset_keypad(void)
222 {
223   kp_write(REG_KEYP_IMR1, 0xf);
224 }
225
226 static l4_uint8_t old_state[NUM_ROWS] = { 0 };
227
228 static int scan_key(void)
229 {
230   l4_uint8_t new_state[NUM_ROWS];
231   //unsigned long size = NUM_ROWS;
232
233   twl4030_i2c_read_u32(TWL4030_MODULE_KEYPAD, new_state, REG_FULL_CODE_7_0);
234   printf("[KEYP] state:%x %x %x %x %x\n",
235       new_state[0], new_state[1], new_state[2], new_state[3], new_state[4]);
236         
237   /* check for changes and print those */
238   int row = 0;
239   for (row = 0; row < NUM_ROWS; row++)
240     {
241       int changed = new_state[row] ^ old_state[row];
242
243       if (!changed)
244         continue;
245
246       int col = 0;
247       for (col = 0; col < NUM_COLS; col++)
248         {
249           if (!(changed & (1 << col)))
250             continue;
251           int key_pressed = new_state[row] & (1 << col);
252
253           printf("***********************key %s:row:%d col:%d\n", key_pressed ? "pressed" : "released", row, col);
254           Input_event ev = { L4RE_EV_KEY, kp_keycode[row * NUM_COLS + col], key_pressed };
255           kp_handler(ev, kp_priv);
256       }
257   }
258
259   memcpy(old_state, new_state, NUM_ROWS);
260
261   return 0;
262 }
263
264 static int kp_irq_func(void)
265 {
266   l4_cap_idx_t irq_cap = l4re_util_cap_alloc();
267   l4_cap_idx_t thread_cap = pthread_getl4cap(_pthread);
268   l4_msgtag_t tag;
269
270   l4_debugger_set_object_name(thread_cap, "kp-omap3.irq");
271   
272   if (l4io_request_irq(7, irq_cap) < 0)
273     return -2;
274   // was L4_IRQ_F_LEVEL_LOW
275   tag = l4_irq_attach(irq_cap, 0, thread_cap);
276   if (l4_ipc_error(tag, l4_utcb()))
277     return -3;
278
279   while (1)
280     {
281       tag = l4_irq_receive(irq_cap, L4_IPC_NEVER);
282       if (l4_ipc_error(tag, l4_utcb()))
283         {
284           printf("[KEYP] Error: Receive irq failed\n");
285           continue;
286         }
287
288       kp_write(REG_KEYP_IMR1, 0xf);
289      
290       if (kp_handler)
291         scan_key();
292
293       l4_uint8_t value = 0;
294       kp_read(REG_KEYP_ISR1, &value);
295       kp_write(REG_KEYP_IMR1, 0x0);
296     }
297 }
298
299 static void* __irq_func(void *data)
300 {
301   (void)data;
302   int ret = kp_irq_func();
303   printf("[KEYP] Warning: irq handler returned with:%d\n", ret);
304   l4_sleep_forever();
305 }
306
307 static
308 int kp_init(void)
309 {
310   vbus = l4re_get_env_cap("vbus");
311
312   if (l4_is_invalid_cap(vbus))
313     {
314       printf("[KEYP] Failed to query vbus\n");
315       return -1;
316     }
317
318   if (l4vbus_get_device_by_hid(vbus, 0, &i2c_handle, "i2c", 0, 0))
319     {
320       printf("[KEYP] ##### Cannot find I2C\n");
321     }
322
323   return init_keypad();
324 }
325
326 static const char *kp_get_info(void)
327 { return "ARM OMAP3EVM Keypad"; }
328
329 static int kp_probe(const char *name)
330 {
331   if (strcmp("OMAP_KP", name))
332     {
333       printf("[KEYP] I'm not the right driver for %s\n", name);
334       return 0;
335     }
336   return !l4io_lookup_device("OMAP_KP", NULL, 0, 0);
337 }
338
339 static void kp_attach(Input_handler handler, void *priv)
340
341   kp_handler = handler;
342   kp_priv = priv;
343   pthread_attr_t thread_attr;
344
345   int err;
346   if ((err = pthread_attr_init(&thread_attr)) != 0)
347     printf("[KEYP] Error: Initializing pthread attr: %d\n", err);
348
349   struct sched_param sp;
350   sp.sched_priority = 0x20;
351   pthread_attr_setschedpolicy(&thread_attr, SCHED_L4);
352   pthread_attr_setschedparam(&thread_attr, &sp);
353   pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED);
354   
355   err = pthread_create(&_pthread, &thread_attr, __irq_func, 0);
356   if (err != 0)
357     printf("[KEYP] Error: Creating thread\n");
358 }
359
360 static void kp_enable(void)
361 {
362   if (kp_init())
363     {
364       printf("[KEYP] Error: Init failed!\n");
365       return;
366     }
367 }
368
369 static void kp_disable(void)
370 {
371   reset_keypad();
372 }
373
374 static struct arm_input_ops arm_kp_ops_omap3 = {
375     .get_info           = kp_get_info,
376     .probe              = kp_probe,
377     .attach             = kp_attach,
378     .enable             = kp_enable,
379     .disable            = kp_disable,
380 };
381
382 arm_input_register(&arm_kp_ops_omap3);