diff options
Diffstat (limited to 'packages/linux/linux-2.6.18/avr32-gpio-dev.patch')
-rw-r--r-- | packages/linux/linux-2.6.18/avr32-gpio-dev.patch | 548 |
1 files changed, 0 insertions, 548 deletions
diff --git a/packages/linux/linux-2.6.18/avr32-gpio-dev.patch b/packages/linux/linux-2.6.18/avr32-gpio-dev.patch deleted file mode 100644 index 43971cf4e6..0000000000 --- a/packages/linux/linux-2.6.18/avr32-gpio-dev.patch +++ /dev/null @@ -1,548 +0,0 @@ ---- - arch/avr32/mach-at32ap/Kconfig | 8 - arch/avr32/mach-at32ap/pio.c | 499 ++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 506 insertions(+), 1 deletion(-) - -Index: linux-2.6.18-avr32/arch/avr32/mach-at32ap/pio.c -=================================================================== ---- linux-2.6.18-avr32.orig/arch/avr32/mach-at32ap/pio.c 2006-11-29 16:22:14.000000000 +0100 -+++ linux-2.6.18-avr32/arch/avr32/mach-at32ap/pio.c 2006-11-29 16:29:20.000000000 +0100 -@@ -22,7 +22,7 @@ - - struct pio_device { - void __iomem *regs; -- const struct platform_device *pdev; -+ struct platform_device *pdev; - struct clk *clk; - u32 pinmux_mask; - u32 gpio_mask; -@@ -119,6 +119,34 @@ fail: - dump_stack(); - } - -+static unsigned int pio_id(struct pio_device *pio) -+{ -+ return pio - pio_dev; -+} -+ -+static void __enable_gpio(struct pio_device *pio, u32 mask) -+{ -+ pio_writel(pio, PUER, mask); -+ pio_writel(pio, ODR, mask); -+ pio_writel(pio, PER, mask); -+} -+ -+static void __disable_gpio(struct pio_device *pio, u32 mask) -+{ -+ pio_writel(pio, PUER, mask); -+ pio_writel(pio, ODR, mask); -+} -+ -+static void pio_dealloc_mask(struct pio_device *pio, u32 mask) -+{ -+ u32 old, new; -+ -+ do { -+ old = pio->pinmux_mask; -+ new = old & ~mask; -+ } while (cmpxchg(&pio->pinmux_mask, old, new) != old); -+} -+ - /* GPIO API */ - - int gpio_request(unsigned int gpio, const char *label) -@@ -210,6 +238,475 @@ void gpio_set_value(unsigned int gpio, i - } - EXPORT_SYMBOL(gpio_set_value); - -+#ifdef CONFIG_PIO_DEV -+#include <linux/configfs.h> -+#include <linux/cdev.h> -+#include <linux/uaccess.h> -+ -+#define GPIO_DEV_MAX 8 -+ -+static struct class *gpio_dev_class; -+static dev_t gpio_devt; -+ -+struct gpio_item { -+ spinlock_t lock; -+ -+ /* Too bad we don't have committable items... */ -+ int enabled; -+ -+ struct pio_device *pio; -+ u32 pin_mask; -+ -+ int id; -+ struct class_device *gpio_dev; -+ struct cdev char_dev; -+ struct config_item item; -+}; -+ -+struct gpio_attribute { -+ struct configfs_attribute attr; -+ ssize_t (*show)(struct gpio_item *, char *); -+ ssize_t (*store)(struct gpio_item *, const char *, size_t); -+}; -+ -+static int gpio_dev_open(struct inode *inode, struct file *file) -+{ -+ struct gpio_item *gpio = container_of(inode->i_cdev, -+ struct gpio_item, -+ char_dev); -+ -+ config_item_get(&gpio->item); -+ file->private_data = gpio; -+ return 0; -+} -+ -+static int gpio_dev_release(struct inode *inode, struct file *file) -+{ -+ struct gpio_item *gpio = file->private_data; -+ -+ config_item_put(&gpio->item); -+ return 0; -+} -+ -+static ssize_t gpio_dev_read(struct file *file, char __user *buf, -+ size_t count, loff_t *offset) -+{ -+ struct gpio_item *gpio = file->private_data; -+ u32 value; -+ -+ value = pio_readl(gpio->pio, PDSR) & gpio->pin_mask; -+ -+ count = min(count, (size_t)4); -+ if (copy_to_user(buf, &value, count)) -+ return -EFAULT; -+ return count; -+} -+ -+static ssize_t gpio_dev_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *offset) -+{ -+ struct gpio_item *gpio = file->private_data; -+ u32 value = 0; -+ u32 mask = ~0UL; -+ -+ count = min(count, (size_t)4); -+ if (copy_from_user(&value, buf, count)) -+ return -EFAULT; -+ -+ /* Assuming big endian */ -+ mask <<= (4 - count) * 8; -+ mask &= gpio->pin_mask; -+ -+ pio_writel(gpio->pio, CODR, ~value & mask); -+ pio_writel(gpio->pio, SODR, value & mask); -+ -+ return count; -+} -+ -+static struct file_operations gpio_dev_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .open = gpio_dev_open, -+ .release = gpio_dev_release, -+ .read = gpio_dev_read, -+ .write = gpio_dev_write, -+}; -+ -+static struct gpio_item *to_gpio_item(struct config_item *item) -+{ -+ return item ? container_of(item, struct gpio_item, item) : NULL; -+} -+ -+static ssize_t gpio_show_gpio_id(struct gpio_item *gpio, char *page) -+{ -+ if (gpio->pio) -+ return sprintf(page, "%u\n", pio_id(gpio->pio)); -+ else -+ return sprintf(page, "-1\n"); -+} -+ -+static ssize_t gpio_store_gpio_id(struct gpio_item *gpio, -+ const char *page, size_t count) -+{ -+ unsigned long id; -+ char *p = (char *)page; -+ ssize_t ret = -EINVAL; -+ -+ id = simple_strtoul(p, &p, 0); -+ if (!p || (*p && (*p != '\n'))) -+ return -EINVAL; -+ -+ /* Switching PIO is not allowed when live... */ -+ spin_lock(&gpio->lock); -+ if (!gpio->enabled) { -+ ret = -ENXIO; -+ if ((id < MAX_NR_PIO_DEVICES) && pio_dev[id].regs) { -+ gpio->pio = &pio_dev[id]; -+ ret = count; -+ } -+ } -+ spin_unlock(&gpio->lock); -+ -+ return ret; -+} -+ -+static ssize_t gpio_show_pin_mask(struct gpio_item *gpio, char *page) -+{ -+ return sprintf(page, "0x%08x\n", gpio->pin_mask); -+} -+ -+static ssize_t gpio_store_pin_mask(struct gpio_item *gpio, -+ const char *page, size_t count) -+{ -+ struct pio_device *pio; -+ u32 old_mask, new_mask; -+ u32 old, new; -+ char *p = (char *)page; -+ ssize_t ret = -EINVAL; -+ -+ new_mask = simple_strtoul(p, &p, 0); -+ if (!p || (*p && (*p != '\n'))) -+ return -EINVAL; -+ -+ /* -+ * Must have a PIO before we can start allocating pins, but we -+ * must not be live. -+ */ -+ spin_lock(&gpio->lock); -+ pio = gpio->pio; -+ if (!pio || gpio->enabled) -+ goto out; -+ -+ ret = -EBUSY; -+ old_mask = gpio->pin_mask; -+ do { -+ old = pio->pinmux_mask; -+ if ((old & ~old_mask) & new_mask) -+ goto out; -+ -+ new = (old & ~old_mask) | new_mask; -+ } while (cmpxchg(&pio->pinmux_mask, old, new) != old); -+ -+ gpio->pin_mask = new_mask; -+ __disable_gpio(pio, old_mask); -+ __enable_gpio(pio, new_mask); -+ ret = count; -+ -+out: -+ spin_unlock(&gpio->lock); -+ return ret; -+} -+ -+static ssize_t gpio_show_oe_mask(struct gpio_item *gpio, char *page) -+{ -+ u32 mask = 0; -+ -+ spin_lock(&gpio->lock); -+ if (gpio->pio) { -+ mask = pio_readl(gpio->pio, OSR); -+ mask &= gpio->pin_mask; -+ } -+ spin_unlock(&gpio->lock); -+ -+ return sprintf(page, "0x%08x\n", mask); -+} -+ -+static ssize_t gpio_store_oe_mask(struct gpio_item *gpio, -+ const char *page, size_t count) -+{ -+ u32 mask; -+ char *p = (char *)page; -+ ssize_t ret = -EINVAL; -+ -+ mask = simple_strtoul(p, &p, 0); -+ if (!p || (*p && (*p != '\n'))) -+ return -EINVAL; -+ -+ spin_lock(&gpio->lock); -+ if (gpio->pio) { -+ mask &= gpio->pin_mask; -+ pio_writel(gpio->pio, ODR, mask ^ gpio->pin_mask); -+ pio_writel(gpio->pio, OER, mask); -+ ret = count; -+ } -+ spin_unlock(&gpio->lock); -+ -+ return ret; -+} -+ -+static ssize_t gpio_show_enabled(struct gpio_item *gpio, char *page) -+{ -+ return sprintf(page, "%d\n", gpio->enabled); -+} -+ -+static ssize_t gpio_store_enabled(struct gpio_item *gpio, -+ const char *page, size_t count) -+{ -+ char *p = (char *)page; -+ int enabled; -+ int ret; -+ -+ enabled = simple_strtoul(p, &p, 0); -+ if (!p || (*p && (*p != '\n'))) -+ return -EINVAL; -+ -+ /* make it a boolean value */ -+ enabled = !!enabled; -+ -+ if (gpio->enabled == enabled) -+ /* Already enabled; do nothing. */ -+ return count; -+ -+ BUG_ON(gpio->id >= GPIO_DEV_MAX); -+ -+ if (!enabled) { -+ class_device_unregister(gpio->gpio_dev); -+ cdev_del(&gpio->char_dev); -+ } -+ -+ /* Disallow any updates to gpio_id or pin_mask */ -+ spin_lock(&gpio->lock); -+ gpio->enabled = enabled; -+ spin_unlock(&gpio->lock); -+ -+ if (!enabled) -+ return count; -+ -+ cdev_init(&gpio->char_dev, &gpio_dev_fops); -+ gpio->char_dev.owner = THIS_MODULE; -+ ret = cdev_add(&gpio->char_dev, MKDEV(MAJOR(gpio_devt), gpio->id), 1); -+ if (ret < 0) -+ goto err_cdev_add; -+ gpio->gpio_dev = class_device_create(gpio_dev_class, NULL, -+ MKDEV(MAJOR(gpio_devt), gpio->id), -+ &gpio->pio->pdev->dev, -+ "gpio%d", gpio->id); -+ if (IS_ERR(gpio->gpio_dev)) { -+ printk(KERN_ERR "failed to create gpio%d\n", gpio->id); -+ ret = PTR_ERR(gpio->gpio_dev); -+ goto err_class_dev; -+ } -+ -+ printk(KERN_INFO "created gpio%d (pio%d/0x%08x) as (%d:%d)\n", -+ gpio->id, pio_id(gpio->pio), gpio->pin_mask, -+ MAJOR(gpio->gpio_dev->devt), MINOR(gpio->gpio_dev->devt)); -+ -+ return 0; -+ -+err_class_dev: -+ cdev_del(&gpio->char_dev); -+err_cdev_add: -+ spin_lock(&gpio->lock); -+ gpio->enabled = 0; -+ spin_unlock(&gpio->lock); -+ -+ return ret; -+} -+ -+static struct gpio_attribute gpio_item_attr_gpio_id = { -+ .attr = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "gpio_id", -+ .ca_mode = S_IRUGO | S_IWUSR, -+ }, -+ .show = gpio_show_gpio_id, -+ .store = gpio_store_gpio_id, -+}; -+static struct gpio_attribute gpio_item_attr_pin_mask = { -+ .attr = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "pin_mask", -+ .ca_mode = S_IRUGO | S_IWUSR, -+ }, -+ .show = gpio_show_pin_mask, -+ .store = gpio_store_pin_mask, -+}; -+static struct gpio_attribute gpio_item_attr_oe_mask = { -+ .attr = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "oe_mask", -+ .ca_mode = S_IRUGO | S_IWUSR, -+ }, -+ .show = gpio_show_oe_mask, -+ .store = gpio_store_oe_mask, -+}; -+static struct gpio_attribute gpio_item_attr_enabled = { -+ .attr = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "enabled", -+ .ca_mode = S_IRUGO | S_IWUSR, -+ }, -+ .show = gpio_show_enabled, -+ .store = gpio_store_enabled, -+}; -+ -+static struct configfs_attribute *gpio_item_attrs[] = { -+ &gpio_item_attr_gpio_id.attr, -+ &gpio_item_attr_pin_mask.attr, -+ &gpio_item_attr_oe_mask.attr, -+ &gpio_item_attr_enabled.attr, -+ NULL, -+}; -+ -+static ssize_t gpio_show_attr(struct config_item *item, -+ struct configfs_attribute *attr, -+ char *page) -+{ -+ struct gpio_item *gpio_item = to_gpio_item(item); -+ struct gpio_attribute *gpio_attr -+ = container_of(attr, struct gpio_attribute, attr); -+ ssize_t ret = 0; -+ -+ if (gpio_attr->show) -+ ret = gpio_attr->show(gpio_item, page); -+ return ret; -+} -+ -+static ssize_t gpio_store_attr(struct config_item *item, -+ struct configfs_attribute *attr, -+ const char *page, size_t count) -+{ -+ struct gpio_item *gpio_item = to_gpio_item(item); -+ struct gpio_attribute *gpio_attr -+ = container_of(attr, struct gpio_attribute, attr); -+ ssize_t ret = -EINVAL; -+ -+ if (gpio_attr->store) -+ ret = gpio_attr->store(gpio_item, page, count); -+ return ret; -+} -+ -+static void gpio_release(struct config_item *item) -+{ -+ kfree(to_gpio_item(item)); -+} -+ -+static struct configfs_item_operations gpio_item_ops = { -+ .release = gpio_release, -+ .show_attribute = gpio_show_attr, -+ .store_attribute = gpio_store_attr, -+}; -+ -+static struct config_item_type gpio_item_type = { -+ .ct_item_ops = &gpio_item_ops, -+ .ct_attrs = gpio_item_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_item *gpio_make_item(struct config_group *group, -+ const char *name) -+{ -+ static int next_id; -+ struct gpio_item *gpio; -+ -+ if (next_id >= GPIO_DEV_MAX) -+ return NULL; -+ -+ gpio = kzalloc(sizeof(struct gpio_item), GFP_KERNEL); -+ if (!gpio) -+ return NULL; -+ -+ gpio->id = next_id++; -+ config_item_init_type_name(&gpio->item, name, &gpio_item_type); -+ spin_lock_init(&gpio->lock); -+ -+ return &gpio->item; -+} -+ -+static void gpio_drop_item(struct config_group *group, -+ struct config_item *item) -+{ -+ struct gpio_item *gpio = to_gpio_item(item); -+ struct pio_device *pio; -+ -+ spin_lock(&gpio->lock); -+ if (gpio->enabled) { -+ class_device_unregister(gpio->gpio_dev); -+ cdev_del(&gpio->char_dev); -+ } -+ -+ pio = gpio->pio; -+ if (pio) { -+ __disable_gpio(pio, gpio->pin_mask); -+ pio_dealloc_mask(pio, gpio->pin_mask); -+ gpio->pio = NULL; -+ } -+ spin_unlock(&gpio->lock); -+} -+ -+static struct configfs_group_operations gpio_group_ops = { -+ .make_item = gpio_make_item, -+ .drop_item = gpio_drop_item, -+}; -+ -+static struct config_item_type gpio_group_type = { -+ .ct_group_ops = &gpio_group_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct configfs_subsystem gpio_subsys = { -+ .su_group = { -+ .cg_item = { -+ .ci_namebuf = "gpio", -+ .ci_type = &gpio_group_type, -+ }, -+ }, -+}; -+ -+static int __init pio_init_dev(void) -+{ -+ int err; -+ -+ gpio_dev_class = class_create(THIS_MODULE, "gpio-dev"); -+ if (IS_ERR(gpio_dev_class)) { -+ err = PTR_ERR(gpio_dev_class); -+ goto err_class_create; -+ } -+ -+ err = alloc_chrdev_region(&gpio_devt, 0, GPIO_DEV_MAX, "gpio"); -+ if (err < 0) -+ goto err_alloc_chrdev; -+ -+ /* Configfs initialization */ -+ config_group_init(&gpio_subsys.su_group); -+ init_MUTEX(&gpio_subsys.su_sem); -+ err = configfs_register_subsystem(&gpio_subsys); -+ if (err) -+ goto err_register_subsys; -+ -+ return 0; -+ -+err_register_subsys: -+ unregister_chrdev_region(gpio_devt, GPIO_DEV_MAX); -+err_alloc_chrdev: -+ class_destroy(gpio_dev_class); -+err_class_create: -+ printk(KERN_WARNING "Failed to initialize gpio /dev interface\n"); -+ return err; -+} -+late_initcall(pio_init_dev); -+#endif /* CONFIG_PIO_DEV */ -+ - static int __init pio_probe(struct platform_device *pdev) - { - struct pio_device *pio = NULL; -Index: linux-2.6.18-avr32/arch/avr32/mach-at32ap/Kconfig -=================================================================== ---- linux-2.6.18-avr32.orig/arch/avr32/mach-at32ap/Kconfig 2006-11-29 16:23:31.000000000 +0100 -+++ linux-2.6.18-avr32/arch/avr32/mach-at32ap/Kconfig 2006-11-29 16:24:35.000000000 +0100 -@@ -2,6 +2,14 @@ if PLATFORM_AT32AP - - menu "Atmel AVR32 AP options" - -+config PIO_DEV -+ bool "PIO /dev interface" -+ select CONFIGFS_FS -+ default y -+ help -+ Say `Y' to enable a /dev interface to the Parallel I/O -+ Controller. -+ - endmenu - - endif |