Logo Search packages:      
Sourcecode: linux-fsl-imx51 version File versions  Download package

pmic_event.c

Go to the documentation of this file.
/*
 * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

/*!
 * @file pmic_event.c
 * @brief This file manage all event of PMIC component.
 *
 * It contains event subscription, unsubscription and callback
 * launch methods implemeted.
 *
 * @ingroup PMIC_CORE
 */

/*
 * Includes
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/pmic_external.h>
#include <linux/pmic_status.h>
#include "pmic.h"

/*!
 * This structure is used to keep a list of subscribed
 * callbacks for an event.
 */
00043 typedef struct {
      /*!
       * Keeps a list of subscribed clients to an event.
       */
00047       struct list_head list;

      /*!
       * Callback function with parameter, called when event occurs
       */
00052       pmic_event_callback_t callback;
} pmic_event_callback_list_t;

/* Create a mutex to be used to prevent concurrent access to the event list */
static DECLARE_MUTEX(event_mutex);

/* This is a pointer to the event handler array. It defines the currently
 * active set of events and user-defined callback functions.
 */
static struct list_head pmic_events[PMIC_MAX_EVENTS];

/*!
 * This function initializes event list for PMIC event handling.
 *
 */
00067 void pmic_event_list_init(void)
{
      int i;

      for (i = 0; i < PMIC_MAX_EVENTS; i++) {
            INIT_LIST_HEAD(&pmic_events[i]);
      }

      sema_init(&event_mutex, 1);
      return;
}

/*!
 * This function is used to subscribe on an event.
 *
 * @param   event   the event number to be subscribed
 * @param   callback the callback funtion to be subscribed
 *
 * @return       This function returns 0 on SUCCESS, error on FAILURE.
 */
00087 PMIC_STATUS pmic_event_subscribe(type_event event,
                         pmic_event_callback_t callback)
{
      pmic_event_callback_list_t *new = NULL;

      pr_debug("Event:%d Subscribe\n", event);

      /* Check whether the event & callback are valid? */
      if (event >= PMIC_MAX_EVENTS) {
            pr_debug("Invalid Event:%d\n", event);
            return -EINVAL;
      }
      if (NULL == callback.func) {
            pr_debug("Null or Invalid Callback\n");
            return -EINVAL;
      }

      /* Create a new linked list entry */
      new = kmalloc(sizeof(pmic_event_callback_list_t), GFP_KERNEL);
      if (NULL == new) {
            return -ENOMEM;
      }
      /* Initialize the list node fields */
      new->callback.func = callback.func;
      new->callback.param = callback.param;
      INIT_LIST_HEAD(&new->list);

      /* Obtain the lock to access the list */
      if (down_interruptible(&event_mutex)) {
            kfree(new);
            return PMIC_SYSTEM_ERROR_EINTR;
      }

      /* Unmask the requested event */
      if (list_empty(&pmic_events[event])) {
            if (pmic_event_unmask(event) != PMIC_SUCCESS) {
                  kfree(new);
                  up(&event_mutex);
                  return PMIC_ERROR;
            }
      }

      /* Add this entry to the event list */
      list_add_tail(&new->list, &pmic_events[event]);

      /* Release the lock */
      up(&event_mutex);

      return PMIC_SUCCESS;
}

/*!
 * This function is used to unsubscribe on an event.
 *
 * @param   event   the event number to be unsubscribed
 * @param   callback the callback funtion to be unsubscribed
 *
 * @return       This function returns 0 on SUCCESS, error on FAILURE.
 */
00146 PMIC_STATUS pmic_event_unsubscribe(type_event event,
                           pmic_event_callback_t callback)
{
      struct list_head *p;
      struct list_head *n;
      pmic_event_callback_list_t *temp = NULL;
      int ret = PMIC_EVENT_NOT_SUBSCRIBED;

      pr_debug("Event:%d Unsubscribe\n", event);

      /* Check whether the event & callback are valid? */
      if (event >= PMIC_MAX_EVENTS) {
            pr_debug("Invalid Event:%d\n", event);
            return -EINVAL;
      }

      if (NULL == callback.func) {
            pr_debug("Null or Invalid Callback\n");
            return -EINVAL;
      }

      /* Obtain the lock to access the list */
      if (down_interruptible(&event_mutex)) {
            return PMIC_SYSTEM_ERROR_EINTR;
      }

      /* Find the entry in the list */
      list_for_each_safe(p, n, &pmic_events[event]) {
            temp = list_entry(p, pmic_event_callback_list_t, list);
            if (temp->callback.func == callback.func
                && temp->callback.param == callback.param) {
                  /* Remove the entry from the list */
                  list_del(p);
                  kfree(temp);
                  ret = PMIC_SUCCESS;
                  break;
            }
      }

      /* Unmask the requested event */
      if (list_empty(&pmic_events[event])) {
            if (pmic_event_mask(event) != PMIC_SUCCESS) {
                  ret = PMIC_UNSUBSCRIBE_ERROR;
            }
      }

      /* Release the lock */
      up(&event_mutex);

      return ret;
}

/*!
 * This function calls all callback of a specific event.
 *
 * @param   event   the active event number
 *
 * @return  None
 */
00205 void pmic_event_callback(type_event event)
{
      struct list_head *p;
      pmic_event_callback_list_t *temp = NULL;

      /* Obtain the lock to access the list */
      if (down_interruptible(&event_mutex)) {
            return;
      }

      if (list_empty(&pmic_events[event])) {
            pr_debug("PMIC Event:%d detected. No callback subscribed\n",
                   event);
            up(&event_mutex);
            return;
      }

      list_for_each(p, &pmic_events[event]) {
            temp = list_entry(p, pmic_event_callback_list_t, list);
            temp->callback.func(temp->callback.param);
      }

      /* Release the lock */
      up(&event_mutex);

      return;

}

EXPORT_SYMBOL(pmic_event_subscribe);
EXPORT_SYMBOL(pmic_event_unsubscribe);

Generated by  Doxygen 1.6.0   Back to index