Thursday, 10 May 2012

Shut it down

Graceful shutdown of Linux system to prevent hard disk ext2 file system corruption.

"/usr/local/bin/msp_int_handler" will call "init 0" to do graceful shutdown.

311 /************************************************************************
312
313 Previous
314 Implementation : Previously MSP was not generating the interrupt, and switching off
315                  the power modules when Power button is switched off.
316
317 Description    : Handling of the interrupt from MSP. When the power button is
318                  off, then MSP generates an interrupt to MPC for gracefully shutdown.
319                  The interrupt handler calls an userspace program called 'msp_int_handler'.
320                              
321            
322
323 ************************************************************************/
324
325 static irqreturn_t msp_interrupt_handler(int gpio_irq,void *ignored);
326
327 static irqreturn_t msp_interrupt_handler(int gpio_irq,void *ignored) {
328  
329     wake_up_interruptible(&msp_event);
330     msp_flag = 1;  
331
332     return 1;
333 }
334
335 static int msp_interrupt_thread(void *ptr) {
336
337   char *argv[] = {"/usr/local/bin/gpio_test", "2", NULL };
338   char *envp[] = {"HOME=/", "PATH=/sbin:/usr/sbin:/bin:/usr/local/bin:", NULL };
339   int ret;
340
341   wait_event_interruptible(msp_event, msp_flag == 1);
342
343   printk("<msp-interrupt> got interrupt from MSP\n");
344
345   ret = call_usermodehelper("/usr/local/bin/msp_int_handler", argv, envp, UMH_WAIT_EXEC);
346
347   if (ret) {
348      printk("<msp-interrupt> call_usermodehelper is not successful \n");
349   } else {
350      printk("<msp-interrupt> call_usermodehelper is successful \n");
351   }
352
353   return 0;
354 }
355
356 static int msp_interrupt_thread_init(void)
357 {
358        int ret=0;    
359        int virq;
360        #define SICRL_OFFSET 0x0114     /* SICR offset in IMMRBAR space */
361        __be32 __iomem *psicr = ioremap(get_immrbase() + SICRL_OFFSET, 4);    
362        u32 sicr;
363        #define IRQ5_INTERRUPT_NUMBER 21
364
365        sicr = in_be32(psicr);
366
367        printk(" Before SICRL Register value : 0x%x \n",sicr);
368
369        sicr &= 0xFE7FFFFF;   //clearing the bits 7 & 8 for IRQ5
370
371        out_be32(psicr, sicr);
372
373        sicr = in_be32(psicr);
374
375        printk(" After SICRL Register value : 0x%x \n",sicr);
376
377        // interrupt line from MSP to MPC for the power failure or power button press
378        virq = vinetic_map_irq(IRQ5_INTERRUPT_NUMBER);
379
380        if (request_irq(virq, &msp_interrupt_handler, 0, "MSP_IRQ", (void *)0))
381           printk(KERN_ERR "pmu: can't get irq %d" " (MSP to MPC)\n", virq);
382        else
383           printk("request_irq for IRQ5 is success with virtual IRQ  %d",virq);
384  
385        /* Wait Q initialization */
386        
387        init_waitqueue_head(&msp_event);
388        printk(" msp interrupt thread init \n\n");
389        msp_interrupt_task = kthread_run(msp_interrupt_thread, NULL, "msp_interrupt_thread");
390      
391        return ret;
392 }
393
394
395
396 static void __exit msp_interrupt_exit(void)
397 {
398        printk(" fact default module exit \n ");      
399 }
400
401 module_init(msp_interrupt_thread_init);
402 module_exit(msp_interrupt_exit);