Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Staging: android: timed_gpio: Separate timed_output class into a separate driver.

Signed-off-by: Mike Lockwood <lockwood@android.com>
Signed-off-by: Arve Hjønnevåg <arve@android.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Mike Lockwood and committed by
Greg Kroah-Hartman
241e1287 5d14a573

+210 -57
+5 -1
drivers/staging/android/Kconfig
··· 73 73 default 0 74 74 depends on ANDROID_RAM_CONSOLE_EARLY_INIT 75 75 76 + config ANDROID_TIMED_OUTPUT 77 + bool "Timed output class driver" 78 + default y 79 + 76 80 config ANDROID_TIMED_GPIO 77 81 tristate "Android timed gpio driver" 78 - depends on GENERIC_GPIO 82 + depends on GENERIC_GPIO && ANDROID_TIMED_OUTPUT 79 83 default n 80 84 81 85 config ANDROID_LOW_MEMORY_KILLER
+1
drivers/staging/android/Makefile
··· 1 1 obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o 2 2 obj-$(CONFIG_ANDROID_LOGGER) += logger.o 3 3 obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o 4 + obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o 4 5 obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o 5 6 obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
+43 -55
drivers/staging/android/timed_gpio.c
··· 20 20 #include <linux/err.h> 21 21 #include <linux/gpio.h> 22 22 23 + #include "timed_output.h" 23 24 #include "timed_gpio.h" 24 25 25 26 26 - static struct class *timed_gpio_class; 27 - 28 27 struct timed_gpio_data { 29 - struct device *dev; 28 + struct timed_output_dev dev; 30 29 struct hrtimer timer; 31 30 spinlock_t lock; 32 31 unsigned gpio; ··· 35 36 36 37 static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer) 37 38 { 38 - struct timed_gpio_data *gpio_data = container_of(timer, struct timed_gpio_data, timer); 39 + struct timed_gpio_data *data = 40 + container_of(timer, struct timed_gpio_data, timer); 39 41 40 - gpio_direction_output(gpio_data->gpio, gpio_data->active_low ? 1 : 0); 42 + gpio_direction_output(data->gpio, data->active_low ? 1 : 0); 41 43 return HRTIMER_NORESTART; 42 44 } 43 45 44 - static ssize_t gpio_enable_show(struct device *dev, struct device_attribute *attr, char *buf) 46 + static int gpio_get_time(struct timed_output_dev *dev) 45 47 { 46 - struct timed_gpio_data *gpio_data = dev_get_drvdata(dev); 47 - int remaining; 48 + struct timed_gpio_data *data = 49 + container_of(dev, struct timed_gpio_data, dev); 48 50 49 - if (hrtimer_active(&gpio_data->timer)) { 50 - ktime_t r = hrtimer_get_remaining(&gpio_data->timer); 51 + if (hrtimer_active(&data->timer)) { 52 + ktime_t r = hrtimer_get_remaining(&data->timer); 51 53 struct timeval t = ktime_to_timeval(r); 52 - remaining = t.tv_sec * 1000 + t.tv_usec / 1000; 54 + return t.tv_sec * 1000 + t.tv_usec / 1000; 53 55 } else 54 - remaining = 0; 55 - 56 - return sprintf(buf, "%d\n", remaining); 56 + return 0; 57 57 } 58 58 59 - static ssize_t gpio_enable_store( 60 - struct device *dev, struct device_attribute *attr, 61 - const char *buf, size_t size) 59 + static void gpio_enable(struct timed_output_dev *dev, int value) 62 60 { 63 - struct timed_gpio_data *gpio_data = dev_get_drvdata(dev); 64 - int value; 61 + struct timed_gpio_data *data = 62 + container_of(dev, struct timed_gpio_data, dev); 65 63 unsigned long flags; 66 64 67 - sscanf(buf, "%d", &value); 68 - 69 - spin_lock_irqsave(&gpio_data->lock, flags); 65 + spin_lock_irqsave(&data->lock, flags); 70 66 71 67 /* cancel previous timer and set GPIO according to value */ 72 - hrtimer_cancel(&gpio_data->timer); 73 - gpio_direction_output(gpio_data->gpio, gpio_data->active_low ? !value : !!value); 68 + hrtimer_cancel(&data->timer); 69 + gpio_direction_output(data->gpio, data->active_low ? !value : !!value); 74 70 75 71 if (value > 0) { 76 - if (value > gpio_data->max_timeout) 77 - value = gpio_data->max_timeout; 72 + if (value > data->max_timeout) 73 + value = data->max_timeout; 78 74 79 - hrtimer_start(&gpio_data->timer, 80 - ktime_set(value / 1000, (value % 1000) * 1000000), 81 - HRTIMER_MODE_REL); 75 + hrtimer_start(&data->timer, 76 + ktime_set(value / 1000, (value % 1000) * 1000000), 77 + HRTIMER_MODE_REL); 82 78 } 83 79 84 - spin_unlock_irqrestore(&gpio_data->lock, flags); 85 - 86 - return size; 80 + spin_unlock_irqrestore(&data->lock, flags); 87 81 } 88 - 89 - static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, gpio_enable_show, gpio_enable_store); 90 82 91 83 static int timed_gpio_probe(struct platform_device *pdev) 92 84 { 93 85 struct timed_gpio_platform_data *pdata = pdev->dev.platform_data; 94 86 struct timed_gpio *cur_gpio; 95 87 struct timed_gpio_data *gpio_data, *gpio_dat; 96 - int i, ret = 0; 88 + int i, j, ret = 0; 97 89 98 90 if (!pdata) 99 91 return -EBUSY; 100 92 101 - gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios, GFP_KERNEL); 93 + gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios, 94 + GFP_KERNEL); 102 95 if (!gpio_data) 103 96 return -ENOMEM; 104 97 ··· 98 107 cur_gpio = &pdata->gpios[i]; 99 108 gpio_dat = &gpio_data[i]; 100 109 101 - hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 110 + hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC, 111 + HRTIMER_MODE_REL); 102 112 gpio_dat->timer.function = gpio_timer_func; 103 113 spin_lock_init(&gpio_dat->lock); 114 + 115 + gpio_dat->dev.name = cur_gpio->name; 116 + gpio_dat->dev.get_time = gpio_get_time; 117 + gpio_dat->dev.enable = gpio_enable; 118 + ret = timed_output_dev_register(&gpio_dat->dev); 119 + if (ret < 0) { 120 + for (j = 0; j < i; j++) 121 + timed_output_dev_unregister(&gpio_data[i].dev); 122 + kfree(gpio_data); 123 + return ret; 124 + } 104 125 105 126 gpio_dat->gpio = cur_gpio->gpio; 106 127 gpio_dat->max_timeout = cur_gpio->max_timeout; 107 128 gpio_dat->active_low = cur_gpio->active_low; 108 129 gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low); 109 - 110 - gpio_dat->dev = device_create(timed_gpio_class, &pdev->dev, 0, "%s", cur_gpio->name); 111 - if (unlikely(IS_ERR(gpio_dat->dev))) 112 - return PTR_ERR(gpio_dat->dev); 113 - 114 - dev_set_drvdata(gpio_dat->dev, gpio_dat); 115 - ret = device_create_file(gpio_dat->dev, &dev_attr_enable); 116 - if (ret) 117 - return ret; 118 130 } 119 131 120 132 platform_set_drvdata(pdev, gpio_data); ··· 131 137 struct timed_gpio_data *gpio_data = platform_get_drvdata(pdev); 132 138 int i; 133 139 134 - for (i = 0; i < pdata->num_gpios; i++) { 135 - device_remove_file(gpio_data[i].dev, &dev_attr_enable); 136 - device_unregister(gpio_data[i].dev); 137 - } 140 + for (i = 0; i < pdata->num_gpios; i++) 141 + timed_output_dev_unregister(&gpio_data[i].dev); 138 142 139 143 kfree(gpio_data); 140 144 ··· 143 151 .probe = timed_gpio_probe, 144 152 .remove = timed_gpio_remove, 145 153 .driver = { 146 - .name = "timed-gpio", 154 + .name = TIMED_GPIO_NAME, 147 155 .owner = THIS_MODULE, 148 156 }, 149 157 }; 150 158 151 159 static int __init timed_gpio_init(void) 152 160 { 153 - timed_gpio_class = class_create(THIS_MODULE, "timed_output"); 154 - if (IS_ERR(timed_gpio_class)) 155 - return PTR_ERR(timed_gpio_class); 156 161 return platform_driver_register(&timed_gpio_driver); 157 162 } 158 163 159 164 static void __exit timed_gpio_exit(void) 160 165 { 161 - class_destroy(timed_gpio_class); 162 166 platform_driver_unregister(&timed_gpio_driver); 163 167 } 164 168
+3 -1
drivers/staging/android/timed_gpio.h
··· 16 16 #ifndef _LINUX_TIMED_GPIO_H 17 17 #define _LINUX_TIMED_GPIO_H 18 18 19 + #define TIMED_GPIO_NAME "timed-gpio" 20 + 19 21 struct timed_gpio { 20 22 const char *name; 21 23 unsigned gpio; 22 - int max_timeout; 24 + int max_timeout; 23 25 u8 active_low; 24 26 }; 25 27
+121
drivers/staging/android/timed_output.c
··· 1 + /* drivers/misc/timed_output.c 2 + * 3 + * Copyright (C) 2009 Google, Inc. 4 + * Author: Mike Lockwood <lockwood@android.com> 5 + * 6 + * This software is licensed under the terms of the GNU General Public 7 + * License version 2, as published by the Free Software Foundation, and 8 + * may be copied, distributed, and modified under those terms. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + */ 16 + 17 + #include <linux/module.h> 18 + #include <linux/types.h> 19 + #include <linux/device.h> 20 + #include <linux/fs.h> 21 + #include <linux/err.h> 22 + 23 + #include "timed_output.h" 24 + 25 + static struct class *timed_output_class; 26 + static atomic_t device_count; 27 + 28 + static ssize_t enable_show(struct device *dev, struct device_attribute *attr, 29 + char *buf) 30 + { 31 + struct timed_output_dev *tdev = dev_get_drvdata(dev); 32 + int remaining = tdev->get_time(tdev); 33 + 34 + return sprintf(buf, "%d\n", remaining); 35 + } 36 + 37 + static ssize_t enable_store( 38 + struct device *dev, struct device_attribute *attr, 39 + const char *buf, size_t size) 40 + { 41 + struct timed_output_dev *tdev = dev_get_drvdata(dev); 42 + int value; 43 + 44 + sscanf(buf, "%d", &value); 45 + tdev->enable(tdev, value); 46 + 47 + return size; 48 + } 49 + 50 + static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store); 51 + 52 + static int create_timed_output_class(void) 53 + { 54 + if (!timed_output_class) { 55 + timed_output_class = class_create(THIS_MODULE, "timed_output"); 56 + if (IS_ERR(timed_output_class)) 57 + return PTR_ERR(timed_output_class); 58 + atomic_set(&device_count, 0); 59 + } 60 + 61 + return 0; 62 + } 63 + 64 + int timed_output_dev_register(struct timed_output_dev *tdev) 65 + { 66 + int ret; 67 + 68 + if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time) 69 + return -EINVAL; 70 + 71 + ret = create_timed_output_class(); 72 + if (ret < 0) 73 + return ret; 74 + 75 + tdev->index = atomic_inc_return(&device_count); 76 + tdev->dev = device_create(timed_output_class, NULL, 77 + MKDEV(0, tdev->index), NULL, tdev->name); 78 + if (IS_ERR(tdev->dev)) 79 + return PTR_ERR(tdev->dev); 80 + 81 + ret = device_create_file(tdev->dev, &dev_attr_enable); 82 + if (ret < 0) 83 + goto err_create_file; 84 + 85 + dev_set_drvdata(tdev->dev, tdev); 86 + tdev->state = 0; 87 + return 0; 88 + 89 + err_create_file: 90 + device_destroy(timed_output_class, MKDEV(0, tdev->index)); 91 + printk(KERN_ERR "timed_output: Failed to register driver %s\n", 92 + tdev->name); 93 + 94 + return ret; 95 + } 96 + EXPORT_SYMBOL_GPL(timed_output_dev_register); 97 + 98 + void timed_output_dev_unregister(struct timed_output_dev *tdev) 99 + { 100 + device_remove_file(tdev->dev, &dev_attr_enable); 101 + device_destroy(timed_output_class, MKDEV(0, tdev->index)); 102 + dev_set_drvdata(tdev->dev, NULL); 103 + } 104 + EXPORT_SYMBOL_GPL(timed_output_dev_unregister); 105 + 106 + static int __init timed_output_init(void) 107 + { 108 + return create_timed_output_class(); 109 + } 110 + 111 + static void __exit timed_output_exit(void) 112 + { 113 + class_destroy(timed_output_class); 114 + } 115 + 116 + module_init(timed_output_init); 117 + module_exit(timed_output_exit); 118 + 119 + MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>"); 120 + MODULE_DESCRIPTION("timed output class driver"); 121 + MODULE_LICENSE("GPL");
+37
drivers/staging/android/timed_output.h
··· 1 + /* include/linux/timed_output.h 2 + * 3 + * Copyright (C) 2008 Google, Inc. 4 + * 5 + * This software is licensed under the terms of the GNU General Public 6 + * License version 2, as published by the Free Software Foundation, and 7 + * may be copied, distributed, and modified under those terms. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + */ 15 + 16 + #ifndef _LINUX_TIMED_OUTPUT_H 17 + #define _LINUX_TIMED_OUTPUT_H 18 + 19 + struct timed_output_dev { 20 + const char *name; 21 + 22 + /* enable the output and set the timer */ 23 + void (*enable)(struct timed_output_dev *sdev, int timeout); 24 + 25 + /* returns the current number of milliseconds remaining on the timer */ 26 + int (*get_time)(struct timed_output_dev *sdev); 27 + 28 + /* private data */ 29 + struct device *dev; 30 + int index; 31 + int state; 32 + }; 33 + 34 + extern int timed_output_dev_register(struct timed_output_dev *dev); 35 + extern void timed_output_dev_unregister(struct timed_output_dev *dev); 36 + 37 + #endif