aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/goldfish/patches-2.6.30/0054-timed_gpio-Separate-timed_output-class-into-a-separ.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/goldfish/patches-2.6.30/0054-timed_gpio-Separate-timed_output-class-into-a-separ.patch')
-rw-r--r--target/linux/goldfish/patches-2.6.30/0054-timed_gpio-Separate-timed_output-class-into-a-separ.patch415
1 files changed, 415 insertions, 0 deletions
diff --git a/target/linux/goldfish/patches-2.6.30/0054-timed_gpio-Separate-timed_output-class-into-a-separ.patch b/target/linux/goldfish/patches-2.6.30/0054-timed_gpio-Separate-timed_output-class-into-a-separ.patch
new file mode 100644
index 000000000..16f1350f5
--- /dev/null
+++ b/target/linux/goldfish/patches-2.6.30/0054-timed_gpio-Separate-timed_output-class-into-a-separ.patch
@@ -0,0 +1,415 @@
+From e4c9c5d7d6d5deb124083678fe5d839d3133f60a Mon Sep 17 00:00:00 2001
+From: Mike Lockwood <lockwood@android.com>
+Date: Mon, 12 Jan 2009 13:25:05 -0500
+Subject: [PATCH 054/134] timed_gpio: Separate timed_output class into a separate driver.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Mike Lockwood <lockwood@android.com>
+Signed-off-by: Arve Hjønnevåg <arve@android.com>
+---
+ drivers/staging/android/Kconfig | 6 ++-
+ drivers/staging/android/Makefile | 1 +
+ drivers/staging/android/timed_gpio.c | 98 +++++++++++--------------
+ drivers/staging/android/timed_gpio.h | 4 +-
+ drivers/staging/android/timed_output.c | 121 ++++++++++++++++++++++++++++++++
+ drivers/staging/android/timed_output.h | 37 ++++++++++
+ 6 files changed, 210 insertions(+), 57 deletions(-)
+ create mode 100644 drivers/staging/android/timed_output.c
+ create mode 100644 drivers/staging/android/timed_output.h
+
+--- a/drivers/staging/android/Kconfig
++++ b/drivers/staging/android/Kconfig
+@@ -73,9 +73,13 @@ config ANDROID_RAM_CONSOLE_EARLY_SIZE
+ default 0
+ depends on ANDROID_RAM_CONSOLE_EARLY_INIT
+
++config ANDROID_TIMED_OUTPUT
++ bool "Timed output class driver"
++ default y
++
+ config ANDROID_TIMED_GPIO
+ tristate "Android timed gpio driver"
+- depends on GENERIC_GPIO
++ depends on GENERIC_GPIO && ANDROID_TIMED_OUTPUT
+ default n
+
+ config ANDROID_LOW_MEMORY_KILLER
+--- a/drivers/staging/android/Makefile
++++ b/drivers/staging/android/Makefile
+@@ -1,5 +1,6 @@
+ obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o
+ obj-$(CONFIG_ANDROID_LOGGER) += logger.o
+ obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o
++obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o
+ obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o
+ obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
+--- a/drivers/staging/android/timed_gpio.c
++++ b/drivers/staging/android/timed_gpio.c
+@@ -20,13 +20,12 @@
+ #include <linux/err.h>
+ #include <linux/gpio.h>
+
++#include "timed_output.h"
+ #include "timed_gpio.h"
+
+
+-static struct class *timed_gpio_class;
+-
+ struct timed_gpio_data {
+- struct device *dev;
++ struct timed_output_dev dev;
+ struct hrtimer timer;
+ spinlock_t lock;
+ unsigned gpio;
+@@ -36,70 +35,62 @@ struct timed_gpio_data {
+
+ static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer)
+ {
+- struct timed_gpio_data *gpio_data = container_of(timer, struct timed_gpio_data, timer);
++ struct timed_gpio_data *data =
++ container_of(timer, struct timed_gpio_data, timer);
+
+- gpio_direction_output(gpio_data->gpio, gpio_data->active_low ? 1 : 0);
++ gpio_direction_output(data->gpio, data->active_low ? 1 : 0);
+ return HRTIMER_NORESTART;
+ }
+
+-static ssize_t gpio_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
++static int gpio_get_time(struct timed_output_dev *dev)
+ {
+- struct timed_gpio_data *gpio_data = dev_get_drvdata(dev);
+- int remaining;
++ struct timed_gpio_data *data =
++ container_of(dev, struct timed_gpio_data, dev);
+
+- if (hrtimer_active(&gpio_data->timer)) {
+- ktime_t r = hrtimer_get_remaining(&gpio_data->timer);
++ if (hrtimer_active(&data->timer)) {
++ ktime_t r = hrtimer_get_remaining(&data->timer);
+ struct timeval t = ktime_to_timeval(r);
+- remaining = t.tv_sec * 1000 + t.tv_usec / 1000;
++ return t.tv_sec * 1000 + t.tv_usec / 1000;
+ } else
+- remaining = 0;
+-
+- return sprintf(buf, "%d\n", remaining);
++ return 0;
+ }
+
+-static ssize_t gpio_enable_store(
+- struct device *dev, struct device_attribute *attr,
+- const char *buf, size_t size)
++static void gpio_enable(struct timed_output_dev *dev, int value)
+ {
+- struct timed_gpio_data *gpio_data = dev_get_drvdata(dev);
+- int value;
++ struct timed_gpio_data *data =
++ container_of(dev, struct timed_gpio_data, dev);
+ unsigned long flags;
+
+- sscanf(buf, "%d", &value);
+-
+- spin_lock_irqsave(&gpio_data->lock, flags);
++ spin_lock_irqsave(&data->lock, flags);
+
+ /* cancel previous timer and set GPIO according to value */
+- hrtimer_cancel(&gpio_data->timer);
+- gpio_direction_output(gpio_data->gpio, gpio_data->active_low ? !value : !!value);
++ hrtimer_cancel(&data->timer);
++ gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
+
+ if (value > 0) {
+- if (value > gpio_data->max_timeout)
+- value = gpio_data->max_timeout;
++ if (value > data->max_timeout)
++ value = data->max_timeout;
+
+- hrtimer_start(&gpio_data->timer,
+- ktime_set(value / 1000, (value % 1000) * 1000000),
+- HRTIMER_MODE_REL);
++ hrtimer_start(&data->timer,
++ ktime_set(value / 1000, (value % 1000) * 1000000),
++ HRTIMER_MODE_REL);
+ }
+
+- spin_unlock_irqrestore(&gpio_data->lock, flags);
+-
+- return size;
++ spin_unlock_irqrestore(&data->lock, flags);
+ }
+
+-static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, gpio_enable_show, gpio_enable_store);
+-
+ static int timed_gpio_probe(struct platform_device *pdev)
+ {
+ struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct timed_gpio *cur_gpio;
+ struct timed_gpio_data *gpio_data, *gpio_dat;
+- int i, ret = 0;
++ int i, j, ret = 0;
+
+ if (!pdata)
+ return -EBUSY;
+
+- gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios, GFP_KERNEL);
++ gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios,
++ GFP_KERNEL);
+ if (!gpio_data)
+ return -ENOMEM;
+
+@@ -107,23 +98,26 @@ static int timed_gpio_probe(struct platf
+ cur_gpio = &pdata->gpios[i];
+ gpio_dat = &gpio_data[i];
+
+- hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC,
++ HRTIMER_MODE_REL);
+ gpio_dat->timer.function = gpio_timer_func;
+ spin_lock_init(&gpio_dat->lock);
+
++ gpio_dat->dev.name = cur_gpio->name;
++ gpio_dat->dev.get_time = gpio_get_time;
++ gpio_dat->dev.enable = gpio_enable;
++ ret = timed_output_dev_register(&gpio_dat->dev);
++ if (ret < 0) {
++ for (j = 0; j < i; j++)
++ timed_output_dev_unregister(&gpio_data[i].dev);
++ kfree(gpio_data);
++ return ret;
++ }
++
+ gpio_dat->gpio = cur_gpio->gpio;
+ gpio_dat->max_timeout = cur_gpio->max_timeout;
+ gpio_dat->active_low = cur_gpio->active_low;
+ gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low);
+-
+- gpio_dat->dev = device_create(timed_gpio_class, &pdev->dev, 0, "%s", cur_gpio->name);
+- if (unlikely(IS_ERR(gpio_dat->dev)))
+- return PTR_ERR(gpio_dat->dev);
+-
+- dev_set_drvdata(gpio_dat->dev, gpio_dat);
+- ret = device_create_file(gpio_dat->dev, &dev_attr_enable);
+- if (ret)
+- return ret;
+ }
+
+ platform_set_drvdata(pdev, gpio_data);
+@@ -137,10 +131,8 @@ static int timed_gpio_remove(struct plat
+ struct timed_gpio_data *gpio_data = platform_get_drvdata(pdev);
+ int i;
+
+- for (i = 0; i < pdata->num_gpios; i++) {
+- device_remove_file(gpio_data[i].dev, &dev_attr_enable);
+- device_unregister(gpio_data[i].dev);
+- }
++ for (i = 0; i < pdata->num_gpios; i++)
++ timed_output_dev_unregister(&gpio_data[i].dev);
+
+ kfree(gpio_data);
+
+@@ -151,22 +143,18 @@ static struct platform_driver timed_gpio
+ .probe = timed_gpio_probe,
+ .remove = timed_gpio_remove,
+ .driver = {
+- .name = "timed-gpio",
++ .name = TIMED_GPIO_NAME,
+ .owner = THIS_MODULE,
+ },
+ };
+
+ static int __init timed_gpio_init(void)
+ {
+- timed_gpio_class = class_create(THIS_MODULE, "timed_output");
+- if (IS_ERR(timed_gpio_class))
+- return PTR_ERR(timed_gpio_class);
+ return platform_driver_register(&timed_gpio_driver);
+ }
+
+ static void __exit timed_gpio_exit(void)
+ {
+- class_destroy(timed_gpio_class);
+ platform_driver_unregister(&timed_gpio_driver);
+ }
+
+--- a/drivers/staging/android/timed_gpio.h
++++ b/drivers/staging/android/timed_gpio.h
+@@ -16,10 +16,12 @@
+ #ifndef _LINUX_TIMED_GPIO_H
+ #define _LINUX_TIMED_GPIO_H
+
++#define TIMED_GPIO_NAME "timed-gpio"
++
+ struct timed_gpio {
+ const char *name;
+ unsigned gpio;
+- int max_timeout;
++ int max_timeout;
+ u8 active_low;
+ };
+
+--- /dev/null
++++ b/drivers/staging/android/timed_output.c
+@@ -0,0 +1,121 @@
++/* drivers/misc/timed_output.c
++ *
++ * Copyright (C) 2009 Google, Inc.
++ * Author: Mike Lockwood <lockwood@android.com>
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/device.h>
++#include <linux/fs.h>
++#include <linux/err.h>
++
++#include "timed_output.h"
++
++static struct class *timed_output_class;
++static atomic_t device_count;
++
++static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct timed_output_dev *tdev = dev_get_drvdata(dev);
++ int remaining = tdev->get_time(tdev);
++
++ return sprintf(buf, "%d\n", remaining);
++}
++
++static ssize_t enable_store(
++ struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t size)
++{
++ struct timed_output_dev *tdev = dev_get_drvdata(dev);
++ int value;
++
++ sscanf(buf, "%d", &value);
++ tdev->enable(tdev, value);
++
++ return size;
++}
++
++static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
++
++static int create_timed_output_class(void)
++{
++ if (!timed_output_class) {
++ timed_output_class = class_create(THIS_MODULE, "timed_output");
++ if (IS_ERR(timed_output_class))
++ return PTR_ERR(timed_output_class);
++ atomic_set(&device_count, 0);
++ }
++
++ return 0;
++}
++
++int timed_output_dev_register(struct timed_output_dev *tdev)
++{
++ int ret;
++
++ if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time)
++ return -EINVAL;
++
++ ret = create_timed_output_class();
++ if (ret < 0)
++ return ret;
++
++ tdev->index = atomic_inc_return(&device_count);
++ tdev->dev = device_create(timed_output_class, NULL,
++ MKDEV(0, tdev->index), NULL, tdev->name);
++ if (IS_ERR(tdev->dev))
++ return PTR_ERR(tdev->dev);
++
++ ret = device_create_file(tdev->dev, &dev_attr_enable);
++ if (ret < 0)
++ goto err_create_file;
++
++ dev_set_drvdata(tdev->dev, tdev);
++ tdev->state = 0;
++ return 0;
++
++err_create_file:
++ device_destroy(timed_output_class, MKDEV(0, tdev->index));
++ printk(KERN_ERR "timed_output: Failed to register driver %s\n",
++ tdev->name);
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(timed_output_dev_register);
++
++void timed_output_dev_unregister(struct timed_output_dev *tdev)
++{
++ device_remove_file(tdev->dev, &dev_attr_enable);
++ device_destroy(timed_output_class, MKDEV(0, tdev->index));
++ dev_set_drvdata(tdev->dev, NULL);
++}
++EXPORT_SYMBOL_GPL(timed_output_dev_unregister);
++
++static int __init timed_output_init(void)
++{
++ return create_timed_output_class();
++}
++
++static void __exit timed_output_exit(void)
++{
++ class_destroy(timed_output_class);
++}
++
++module_init(timed_output_init);
++module_exit(timed_output_exit);
++
++MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
++MODULE_DESCRIPTION("timed output class driver");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/staging/android/timed_output.h
+@@ -0,0 +1,37 @@
++/* include/linux/timed_output.h
++ *
++ * Copyright (C) 2008 Google, Inc.
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++*/
++
++#ifndef _LINUX_TIMED_OUTPUT_H
++#define _LINUX_TIMED_OUTPUT_H
++
++struct timed_output_dev {
++ const char *name;
++
++ /* enable the output and set the timer */
++ void (*enable)(struct timed_output_dev *sdev, int timeout);
++
++ /* returns the current number of milliseconds remaining on the timer */
++ int (*get_time)(struct timed_output_dev *sdev);
++
++ /* private data */
++ struct device *dev;
++ int index;
++ int state;
++};
++
++extern int timed_output_dev_register(struct timed_output_dev *dev);
++extern void timed_output_dev_unregister(struct timed_output_dev *dev);
++
++#endif