aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ar7/files/drivers
diff options
context:
space:
mode:
authorFlorian Fainelli <florian@openwrt.org>2010-02-04 14:35:21 +0000
committerFlorian Fainelli <florian@openwrt.org>2010-02-04 14:35:21 +0000
commitdad3df8582cd287fa6f92401a6096dd66c5b20fa (patch)
tree3b7ec3e52bd4a32e88a797ca2f9ae2895b02bd4c /target/linux/ar7/files/drivers
parent400d2bd3da602741b3acd9a36a370e3462adb05e (diff)
downloadupstream-dad3df8582cd287fa6f92401a6096dd66c5b20fa.tar.gz
upstream-dad3df8582cd287fa6f92401a6096dd66c5b20fa.tar.bz2
upstream-dad3df8582cd287fa6f92401a6096dd66c5b20fa.zip
move files to file-2.6.30
SVN-Revision: 19518
Diffstat (limited to 'target/linux/ar7/files/drivers')
-rw-r--r--target/linux/ar7/files/drivers/char/ar7_gpio.c158
-rw-r--r--target/linux/ar7/files/drivers/char/watchdog/ar7_wdt.c349
-rw-r--r--target/linux/ar7/files/drivers/vlynq/Kconfig13
-rw-r--r--target/linux/ar7/files/drivers/vlynq/Makefile5
-rw-r--r--target/linux/ar7/files/drivers/vlynq/vlynq.c783
5 files changed, 0 insertions, 1308 deletions
diff --git a/target/linux/ar7/files/drivers/char/ar7_gpio.c b/target/linux/ar7/files/drivers/char/ar7_gpio.c
deleted file mode 100644
index 6b38bbd89f..0000000000
--- a/target/linux/ar7/files/drivers/char/ar7_gpio.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2007 Nicolas Thill <nico@openwrt.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <linux/types.h>
-#include <linux/cdev.h>
-#include <gpio.h>
-
-#define DRVNAME "ar7_gpio"
-#define LONGNAME "TI AR7 GPIOs Driver"
-
-MODULE_AUTHOR("Nicolas Thill <nico@openwrt.org>");
-MODULE_DESCRIPTION(LONGNAME);
-MODULE_LICENSE("GPL");
-
-static int ar7_gpio_major;
-
-static ssize_t ar7_gpio_write(struct file *file, const char __user *buf,
- size_t len, loff_t *ppos)
-{
- int pin = iminor(file->f_dentry->d_inode);
- size_t i;
-
- for (i = 0; i < len; ++i) {
- char c;
- if (get_user(c, buf + i))
- return -EFAULT;
- switch (c) {
- case '0':
- gpio_set_value(pin, 0);
- break;
- case '1':
- gpio_set_value(pin, 1);
- break;
- case 'd':
- case 'D':
- ar7_gpio_disable(pin);
- break;
- case 'e':
- case 'E':
- ar7_gpio_enable(pin);
- break;
- case 'i':
- case 'I':
- case '<':
- gpio_direction_input(pin);
- break;
- case 'o':
- case 'O':
- case '>':
- gpio_direction_output(pin, 0);
- break;
- default:
- return -EINVAL;
- }
- }
-
- return len;
-}
-
-static ssize_t ar7_gpio_read(struct file *file, char __user *buf,
- size_t len, loff_t *ppos)
-{
- int pin = iminor(file->f_dentry->d_inode);
- int value;
-
- value = gpio_get_value(pin);
- if (put_user(value ? '1' : '0', buf))
- return -EFAULT;
-
- return 1;
-}
-
-static int ar7_gpio_open(struct inode *inode, struct file *file)
-{
- int m = iminor(inode);
-
- if (m >= (ar7_is_titan() ? TITAN_GPIO_MAX : AR7_GPIO_MAX))
- return -EINVAL;
-
- return nonseekable_open(inode, file);
-}
-
-static int ar7_gpio_release(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-static const struct file_operations ar7_gpio_fops = {
- .owner = THIS_MODULE,
- .write = ar7_gpio_write,
- .read = ar7_gpio_read,
- .open = ar7_gpio_open,
- .release = ar7_gpio_release,
- .llseek = no_llseek,
-};
-
-static struct platform_device *ar7_gpio_device;
-
-static int __init ar7_gpio_init(void)
-{
- int rc;
-
- ar7_gpio_device = platform_device_alloc(DRVNAME, -1);
- if (!ar7_gpio_device)
- return -ENOMEM;
-
- rc = platform_device_add(ar7_gpio_device);
- if (rc < 0)
- goto out_put;
-
- rc = register_chrdev(ar7_gpio_major, DRVNAME, &ar7_gpio_fops);
- if (rc < 0)
- goto out_put;
-
- ar7_gpio_major = rc;
-
- rc = 0;
-
- goto out;
-
-out_put:
- platform_device_put(ar7_gpio_device);
-out:
- return rc;
-}
-
-static void __exit ar7_gpio_exit(void)
-{
- unregister_chrdev(ar7_gpio_major, DRVNAME);
- platform_device_unregister(ar7_gpio_device);
-}
-
-module_init(ar7_gpio_init);
-module_exit(ar7_gpio_exit);
diff --git a/target/linux/ar7/files/drivers/char/watchdog/ar7_wdt.c b/target/linux/ar7/files/drivers/char/watchdog/ar7_wdt.c
deleted file mode 100644
index 97cd8105a9..0000000000
--- a/target/linux/ar7/files/drivers/char/watchdog/ar7_wdt.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * drivers/watchdog/ar7_wdt.c
- *
- * Copyright (C) 2007 Nicolas Thill <nico@openwrt.org>
- * Copyright (c) 2005 Enrik Berkhan <Enrik.Berkhan@akk.org>
- *
- * Some code taken from:
- * National Semiconductor SCx200 Watchdog support
- * Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-
-#include <asm/addrspace.h>
-#include <asm/ar7/ar7.h>
-
-#define DRVNAME "ar7_wdt"
-#define LONGNAME "TI AR7 Watchdog Timer"
-
-MODULE_AUTHOR("Nicolas Thill <nico@openwrt.org>");
-MODULE_DESCRIPTION(LONGNAME);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
-static int margin = 60;
-module_param(margin, int, 0);
-MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
-
-#define READ_REG(x) readl((void __iomem *)&(x))
-#define WRITE_REG(x, v) writel((v), (void __iomem *)&(x))
-
-struct ar7_wdt {
- u32 kick_lock;
- u32 kick;
- u32 change_lock;
- u32 change;
- u32 disable_lock;
- u32 disable;
- u32 prescale_lock;
- u32 prescale;
-};
-
-static struct semaphore open_semaphore;
-static unsigned expect_close;
-
-/* XXX currently fixed, allows max margin ~68.72 secs */
-#define prescale_value 0xffff
-
-/* Offset of the WDT registers */
-static unsigned long ar7_regs_wdt;
-/* Pointer to the remapped WDT IO space */
-static struct ar7_wdt *ar7_wdt;
-static void ar7_wdt_get_regs(void)
-{
- u16 chip_id = ar7_chip_id();
- switch (chip_id) {
- case AR7_CHIP_7100:
- case AR7_CHIP_7200:
- ar7_regs_wdt = AR7_REGS_WDT;
- break;
- default:
- ar7_regs_wdt = UR8_REGS_WDT;
- break;
- }
-}
-
-
-static void ar7_wdt_kick(u32 value)
-{
- WRITE_REG(ar7_wdt->kick_lock, 0x5555);
- if ((READ_REG(ar7_wdt->kick_lock) & 3) == 1) {
- WRITE_REG(ar7_wdt->kick_lock, 0xaaaa);
- if ((READ_REG(ar7_wdt->kick_lock) & 3) == 3) {
- WRITE_REG(ar7_wdt->kick, value);
- return;
- }
- }
- printk(KERN_ERR DRVNAME ": failed to unlock WDT kick reg\n");
-}
-
-static void ar7_wdt_prescale(u32 value)
-{
- WRITE_REG(ar7_wdt->prescale_lock, 0x5a5a);
- if ((READ_REG(ar7_wdt->prescale_lock) & 3) == 1) {
- WRITE_REG(ar7_wdt->prescale_lock, 0xa5a5);
- if ((READ_REG(ar7_wdt->prescale_lock) & 3) == 3) {
- WRITE_REG(ar7_wdt->prescale, value);
- return;
- }
- }
- printk(KERN_ERR DRVNAME ": failed to unlock WDT prescale reg\n");
-}
-
-static void ar7_wdt_change(u32 value)
-{
- WRITE_REG(ar7_wdt->change_lock, 0x6666);
- if ((READ_REG(ar7_wdt->change_lock) & 3) == 1) {
- WRITE_REG(ar7_wdt->change_lock, 0xbbbb);
- if ((READ_REG(ar7_wdt->change_lock) & 3) == 3) {
- WRITE_REG(ar7_wdt->change, value);
- return;
- }
- }
- printk(KERN_ERR DRVNAME ": failed to unlock WDT change reg\n");
-}
-
-static void ar7_wdt_disable(u32 value)
-{
- WRITE_REG(ar7_wdt->disable_lock, 0x7777);
- if ((READ_REG(ar7_wdt->disable_lock) & 3) == 1) {
- WRITE_REG(ar7_wdt->disable_lock, 0xcccc);
- if ((READ_REG(ar7_wdt->disable_lock) & 3) == 2) {
- WRITE_REG(ar7_wdt->disable_lock, 0xdddd);
- if ((READ_REG(ar7_wdt->disable_lock) & 3) == 3) {
- WRITE_REG(ar7_wdt->disable, value);
- return;
- }
- }
- }
- printk(KERN_ERR DRVNAME ": failed to unlock WDT disable reg\n");
-}
-
-static void ar7_wdt_update_margin(int new_margin)
-{
- u32 change;
-
- change = new_margin * (ar7_vbus_freq() / prescale_value);
- if (change < 1) change = 1;
- if (change > 0xffff) change = 0xffff;
- ar7_wdt_change(change);
- margin = change * prescale_value / ar7_vbus_freq();
- printk(KERN_INFO DRVNAME
- ": timer margin %d seconds (prescale %d, change %d, freq %d)\n",
- margin, prescale_value, change, ar7_vbus_freq());
-}
-
-static void ar7_wdt_enable_wdt(void)
-{
- printk(KERN_DEBUG DRVNAME ": enabling watchdog timer\n");
- ar7_wdt_disable(1);
- ar7_wdt_kick(1);
-}
-
-static void ar7_wdt_disable_wdt(void)
-{
- printk(KERN_DEBUG DRVNAME ": disabling watchdog timer\n");
- ar7_wdt_disable(0);
-}
-
-static int ar7_wdt_open(struct inode *inode, struct file *file)
-{
- /* only allow one at a time */
- if (down_trylock(&open_semaphore))
- return -EBUSY;
- ar7_wdt_enable_wdt();
- expect_close = 0;
-
- return nonseekable_open(inode, file);
-}
-
-static int ar7_wdt_release(struct inode *inode, struct file *file)
-{
- if (!expect_close)
- printk(KERN_WARNING DRVNAME
- ": watchdog device closed unexpectedly,"
- "will not disable the watchdog timer\n");
- else if (!nowayout)
- ar7_wdt_disable_wdt();
-
- up(&open_semaphore);
-
- return 0;
-}
-
-static int ar7_wdt_notify_sys(struct notifier_block *this,
- unsigned long code, void *unused)
-{
- if (code == SYS_HALT || code == SYS_POWER_OFF)
- if (!nowayout)
- ar7_wdt_disable_wdt();
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block ar7_wdt_notifier = {
- .notifier_call = ar7_wdt_notify_sys
-};
-
-static ssize_t ar7_wdt_write(struct file *file, const char *data,
- size_t len, loff_t *ppos)
-{
- /* check for a magic close character */
- if (len) {
- size_t i;
-
- ar7_wdt_kick(1);
-
- expect_close = 0;
- for (i = 0; i < len; ++i) {
- char c;
- if (get_user(c, data+i))
- return -EFAULT;
- if (c == 'V')
- expect_close = 1;
- }
-
- }
- return len;
-}
-
-static int ar7_wdt_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- static struct watchdog_info ident = {
- .identity = LONGNAME,
- .firmware_version = 1,
- .options = (WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING),
- };
- int new_margin;
-
- switch (cmd) {
- default:
- return -ENOTTY;
- case WDIOC_GETSUPPORT:
- if (copy_to_user((struct watchdog_info *)arg, &ident,
- sizeof(ident)))
- return -EFAULT;
- return 0;
- case WDIOC_GETSTATUS:
- case WDIOC_GETBOOTSTATUS:
- if (put_user(0, (int *)arg))
- return -EFAULT;
- return 0;
- case WDIOC_KEEPALIVE:
- ar7_wdt_kick(1);
- return 0;
- case WDIOC_SETTIMEOUT:
- if (get_user(new_margin, (int *)arg))
- return -EFAULT;
- if (new_margin < 1)
- return -EINVAL;
-
- ar7_wdt_update_margin(new_margin);
- ar7_wdt_kick(1);
-
- case WDIOC_GETTIMEOUT:
- if (put_user(margin, (int *)arg))
- return -EFAULT;
- return 0;
- }
-}
-
-static struct file_operations ar7_wdt_fops = {
- .owner = THIS_MODULE,
- .write = ar7_wdt_write,
- .ioctl = ar7_wdt_ioctl,
- .open = ar7_wdt_open,
- .release = ar7_wdt_release,
-};
-
-static struct miscdevice ar7_wdt_miscdev = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &ar7_wdt_fops,
-};
-
-static int __init ar7_wdt_init(void)
-{
- int rc;
-
- ar7_wdt_get_regs();
-
- if (!request_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt),
- LONGNAME)) {
- printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n");
- return -EBUSY;
- }
-
- ar7_wdt = (struct ar7_wdt *)
- ioremap(ar7_regs_wdt, sizeof(struct ar7_wdt));
-
- ar7_wdt_disable_wdt();
- ar7_wdt_prescale(prescale_value);
- ar7_wdt_update_margin(margin);
-
- sema_init(&open_semaphore, 1);
-
- rc = register_reboot_notifier(&ar7_wdt_notifier);
- if (rc) {
- printk(KERN_ERR DRVNAME
- ": unable to register reboot notifier\n");
- goto out_alloc;
- }
-
- rc = misc_register(&ar7_wdt_miscdev);
- if (rc) {
- printk(KERN_ERR DRVNAME ": unable to register misc device\n");
- goto out_register;
- }
- goto out;
-
-out_register:
- unregister_reboot_notifier(&ar7_wdt_notifier);
-out_alloc:
- iounmap(ar7_wdt);
- release_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt));
-out:
- return rc;
-}
-
-static void __exit ar7_wdt_cleanup(void)
-{
- misc_deregister(&ar7_wdt_miscdev);
- unregister_reboot_notifier(&ar7_wdt_notifier);
- iounmap(ar7_wdt);
- release_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt));
-}
-
-module_init(ar7_wdt_init);
-module_exit(ar7_wdt_cleanup);
diff --git a/target/linux/ar7/files/drivers/vlynq/Kconfig b/target/linux/ar7/files/drivers/vlynq/Kconfig
deleted file mode 100644
index 2c8ffe0d19..0000000000
--- a/target/linux/ar7/files/drivers/vlynq/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-menu "TI VLYNQ"
-
-config VLYNQ
- bool "TI VLYNQ bus support"
- depends on AR7 && EXPERIMENTAL
- help
- Support for the TI VLYNQ bus
-
- The module will be called vlynq
-
- If unsure, say N
-
-endmenu
diff --git a/target/linux/ar7/files/drivers/vlynq/Makefile b/target/linux/ar7/files/drivers/vlynq/Makefile
deleted file mode 100644
index b3f61149b5..0000000000
--- a/target/linux/ar7/files/drivers/vlynq/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for kernel vlynq drivers
-#
-
-obj-$(CONFIG_VLYNQ) += vlynq.o
diff --git a/target/linux/ar7/files/drivers/vlynq/vlynq.c b/target/linux/ar7/files/drivers/vlynq/vlynq.c
deleted file mode 100644
index f4b7b0f98e..0000000000
--- a/target/linux/ar7/files/drivers/vlynq/vlynq.c
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Eugene Konev <ejka@openwrt.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <linux/vlynq.h>
-
-#define VLYNQ_CTRL_PM_ENABLE 0x80000000
-#define VLYNQ_CTRL_CLOCK_INT 0x00008000
-#define VLYNQ_CTRL_CLOCK_DIV(x) (((x) & 7) << 16)
-#define VLYNQ_CTRL_INT_LOCAL 0x00004000
-#define VLYNQ_CTRL_INT_ENABLE 0x00002000
-#define VLYNQ_CTRL_INT_VECTOR(x) (((x) & 0x1f) << 8)
-#define VLYNQ_CTRL_INT2CFG 0x00000080
-#define VLYNQ_CTRL_RESET 0x00000001
-
-#define VLYNQ_CTRL_CLOCK_MASK (0x7 << 16)
-
-#define VLYNQ_INT_OFFSET 0x00000014
-#define VLYNQ_REMOTE_OFFSET 0x00000080
-
-#define VLYNQ_STATUS_LINK 0x00000001
-#define VLYNQ_STATUS_LERROR 0x00000080
-#define VLYNQ_STATUS_RERROR 0x00000100
-
-#define VINT_ENABLE 0x00000100
-#define VINT_TYPE_EDGE 0x00000080
-#define VINT_LEVEL_LOW 0x00000040
-#define VINT_VECTOR(x) ((x) & 0x1f)
-#define VINT_OFFSET(irq) (8 * ((irq) % 4))
-
-#define VLYNQ_AUTONEGO_V2 0x00010000
-
-struct vlynq_regs {
- u32 revision;
- u32 control;
- u32 status;
- u32 int_prio;
- u32 int_status;
- u32 int_pending;
- u32 int_ptr;
- u32 tx_offset;
- struct vlynq_mapping rx_mapping[4];
- u32 chip;
- u32 autonego;
- u32 unused[6];
- u32 int_device[8];
-};
-
-#define vlynq_reg_read(reg) readl(&(reg))
-#define vlynq_reg_write(reg, val) writel(val, &(reg))
-
-static int __vlynq_enable_device(struct vlynq_device *dev);
-
-#ifdef VLYNQ_DEBUG
-static void vlynq_dump_regs(struct vlynq_device *dev)
-{
- int i;
- printk(KERN_DEBUG "VLYNQ local=%p remote=%p\n",
- dev->local, dev->remote);
- for (i = 0; i < 32; i++) {
- printk(KERN_DEBUG "VLYNQ: local %d: %08x\n",
- i + 1, ((u32 *)dev->local)[i]);
- printk(KERN_DEBUG "VLYNQ: remote %d: %08x\n",
- i + 1, ((u32 *)dev->remote)[i]);
- }
-}
-
-static void vlynq_dump_mem(u32 *base, int count)
-{
- int i;
- for (i = 0; i < (count + 3) / 4; i++) {
- if (i % 4 == 0) printk(KERN_DEBUG "\nMEM[0x%04x]:", i * 4);
- printk(KERN_DEBUG " 0x%08x", *(base + i));
- }
- printk(KERN_DEBUG "\n");
-}
-#endif
-
-int vlynq_linked(struct vlynq_device *dev)
-{
- int i;
-
- for (i = 0; i < 100; i++)
- if (vlynq_reg_read(dev->local->status) & VLYNQ_STATUS_LINK)
- return 1;
- else
- cpu_relax();
-
- return 0;
-}
-
-static void vlynq_reset(struct vlynq_device *dev)
-{
- vlynq_reg_write(dev->local->control,
- vlynq_reg_read(dev->local->control) |
- VLYNQ_CTRL_RESET);
-
- /* Wait for the devices to finish resetting */
- msleep(5);
-
- /* Remove reset bit */
- vlynq_reg_write(dev->local->control,
- vlynq_reg_read(dev->local->control) &
- ~VLYNQ_CTRL_RESET);
-
- /* Give some time for the devices to settle */
- msleep(5);
-}
-
-static void vlynq_irq_unmask(unsigned int irq)
-{
- u32 val;
- struct vlynq_device *dev = get_irq_chip_data(irq);
- int virq;
-
- BUG_ON(!dev);
- virq = irq - dev->irq_start;
- val = vlynq_reg_read(dev->remote->int_device[virq >> 2]);
- val |= (VINT_ENABLE | virq) << VINT_OFFSET(virq);
- vlynq_reg_write(dev->remote->int_device[virq >> 2], val);
-}
-
-static void vlynq_irq_mask(unsigned int irq)
-{
- u32 val;
- struct vlynq_device *dev = get_irq_chip_data(irq);
- int virq;
-
- BUG_ON(!dev);
- virq = irq - dev->irq_start;
- val = vlynq_reg_read(dev->remote->int_device[virq >> 2]);
- val &= ~(VINT_ENABLE << VINT_OFFSET(virq));
- vlynq_reg_write(dev->remote->int_device[virq >> 2], val);
-}
-
-static int vlynq_irq_type(unsigned int irq, unsigned int flow_type)
-{
- u32 val;
- struct vlynq_device *dev = get_irq_chip_data(irq);
- int virq;
-
- BUG_ON(!dev);
- virq = irq - dev->irq_start;
- val = vlynq_reg_read(dev->remote->int_device[virq >> 2]);
- switch (flow_type & IRQ_TYPE_SENSE_MASK) {
- case IRQ_TYPE_EDGE_RISING:
- case IRQ_TYPE_EDGE_FALLING:
- case IRQ_TYPE_EDGE_BOTH:
- val |= VINT_TYPE_EDGE << VINT_OFFSET(virq);
- val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq));
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq));
- val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq));
- break;
- case IRQ_TYPE_LEVEL_LOW:
- val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq));
- val |= VINT_LEVEL_LOW << VINT_OFFSET(virq);
- break;
- default:
- return -EINVAL;
- }
- vlynq_reg_write(dev->remote->int_device[virq >> 2], val);
- return 0;
-}
-
-static void vlynq_local_ack(unsigned int irq)
-{
- struct vlynq_device *dev = get_irq_chip_data(irq);
- u32 status = vlynq_reg_read(dev->local->status);
- if (printk_ratelimit())
- printk(KERN_DEBUG "%s: local status: 0x%08x\n",
- dev->dev.bus_id, status);
- vlynq_reg_write(dev->local->status, status);
-}
-
-static void vlynq_remote_ack(unsigned int irq)
-{
- struct vlynq_device *dev = get_irq_chip_data(irq);
- u32 status = vlynq_reg_read(dev->remote->status);
- if (printk_ratelimit())
- printk(KERN_DEBUG "%s: remote status: 0x%08x\n",
- dev->dev.bus_id, status);
- vlynq_reg_write(dev->remote->status, status);
-}
-
-static irqreturn_t vlynq_irq(int irq, void *dev_id)
-{
- struct vlynq_device *dev = dev_id;
- u32 status;
- int virq = 0;
-
- status = vlynq_reg_read(dev->local->int_status);
- vlynq_reg_write(dev->local->int_status, status);
-
- if (unlikely(!status))
- spurious_interrupt();
-
- while (status) {
- if (status & 1)
- do_IRQ(dev->irq_start + virq);
- status >>= 1;
- virq++;
- }
-
- return IRQ_HANDLED;
-}
-
-static struct irq_chip vlynq_irq_chip = {
- .name = "vlynq",
- .unmask = vlynq_irq_unmask,
- .mask = vlynq_irq_mask,
- .set_type = vlynq_irq_type,
-};
-
-static struct irq_chip vlynq_local_chip = {
- .name = "vlynq local error",
- .unmask = vlynq_irq_unmask,
- .mask = vlynq_irq_mask,
- .ack = vlynq_local_ack,
-};
-
-static struct irq_chip vlynq_remote_chip = {
- .name = "vlynq local error",
- .unmask = vlynq_irq_unmask,
- .mask = vlynq_irq_mask,
- .ack = vlynq_remote_ack,
-};
-
-static int vlynq_setup_irq(struct vlynq_device *dev)
-{
- u32 val;
- int i, virq;
-
- if (dev->local_irq == dev->remote_irq) {
- printk(KERN_ERR
- "%s: local vlynq irq should be different from remote\n",
- dev->dev.bus_id);
- return -EINVAL;
- }
-
- /* Clear local and remote error bits */
- vlynq_reg_write(dev->local->status, vlynq_reg_read(dev->local->status));
- vlynq_reg_write(dev->remote->status,
- vlynq_reg_read(dev->remote->status));
-
- /* Now setup interrupts */
- val = VLYNQ_CTRL_INT_VECTOR(dev->local_irq);
- val |= VLYNQ_CTRL_INT_ENABLE | VLYNQ_CTRL_INT_LOCAL |
- VLYNQ_CTRL_INT2CFG;
- val |= vlynq_reg_read(dev->local->control);
- vlynq_reg_write(dev->local->int_ptr, VLYNQ_INT_OFFSET);
- vlynq_reg_write(dev->local->control, val);
-
- val = VLYNQ_CTRL_INT_VECTOR(dev->remote_irq);
- val |= VLYNQ_CTRL_INT_ENABLE;
- val |= vlynq_reg_read(dev->remote->control);
- vlynq_reg_write(dev->remote->int_ptr, VLYNQ_INT_OFFSET);
- vlynq_reg_write(dev->remote->control, val);
-
- for (i = dev->irq_start; i <= dev->irq_end; i++) {
- virq = i - dev->irq_start;
- if (virq == dev->local_irq) {
- set_irq_chip_and_handler(i, &vlynq_local_chip,
- handle_level_irq);
- set_irq_chip_data(i, dev);
- } else if (virq == dev->remote_irq) {
- set_irq_chip_and_handler(i, &vlynq_remote_chip,
- handle_level_irq);
- set_irq_chip_data(i, dev);
- } else {
- set_irq_chip_and_handler(i, &vlynq_irq_chip,
- handle_simple_irq);
- set_irq_chip_data(i, dev);
- vlynq_reg_write(dev->remote->int_device[virq >> 2], 0);
- }
- }
-
- if (request_irq(dev->irq, vlynq_irq, IRQF_SHARED, "vlynq", dev)) {
- printk(KERN_ERR "%s: request_irq failed\n", dev->dev.bus_id);
- return -EAGAIN;
- }
-
- return 0;
-}
-
-static void vlynq_device_release(struct device *dev)
-{
- struct vlynq_device *vdev = to_vlynq_device(dev);
- kfree(vdev);
-}
-
-static int vlynq_device_match(struct device *dev,
- struct device_driver *drv)
-{
- struct vlynq_device *vdev = to_vlynq_device(dev);
- struct vlynq_driver *vdrv = to_vlynq_driver(drv);
- struct vlynq_device_id *ids = vdrv->id_table;
-
- while (ids->id) {
- if (ids->id == vdev->dev_id) {
- vdev->divisor = ids->divisor;
- vlynq_set_drvdata(vdev, ids);
- printk(KERN_INFO "Driver found for VLYNQ " \
- "device: %08x\n", vdev->dev_id);
- return 1;
- }
- printk(KERN_DEBUG "Not using the %08x VLYNQ device's driver" \
- " for VLYNQ device: %08x\n", ids->id, vdev->dev_id);
- ids++;
- }
- return 0;
-}
-
-static int vlynq_device_probe(struct device *dev)
-{
- struct vlynq_device *vdev = to_vlynq_device(dev);
- struct vlynq_driver *drv = to_vlynq_driver(dev->driver);
- struct vlynq_device_id *id = vlynq_get_drvdata(vdev);
- int result = -ENODEV;
-
- get_device(dev);
- if (drv && drv->probe)
- result = drv->probe(vdev, id);
- if (result)
- put_device(dev);
- return result;
-}
-
-static int vlynq_device_remove(struct device *dev)
-{
- struct vlynq_driver *drv = to_vlynq_driver(dev->driver);
- if (drv && drv->remove)
- drv->remove(to_vlynq_device(dev));
- put_device(dev);
- return 0;
-}
-
-int __vlynq_register_driver(struct vlynq_driver *driver, struct module *owner)
-{
- driver->driver.name = driver->name;
- driver->driver.bus = &vlynq_bus_type;
- return driver_register(&driver->driver);
-}
-EXPORT_SYMBOL(__vlynq_register_driver);
-
-void vlynq_unregister_driver(struct vlynq_driver *driver)
-{
- driver_unregister(&driver->driver);
-}
-EXPORT_SYMBOL(vlynq_unregister_driver);
-
-static int __vlynq_try_remote(struct vlynq_device *dev)
-{
- int i;
-
- vlynq_reset(dev);
- for (i = dev->dev_id ? vlynq_rdiv2 : vlynq_rdiv8; dev->dev_id ?
- i <= vlynq_rdiv8 : i >= vlynq_rdiv2;
- dev->dev_id ? i++ : i--) {
-
- if (!vlynq_linked(dev))
- break;
-
- vlynq_reg_write(dev->remote->control,
- (vlynq_reg_read(dev->remote->control) &
- ~VLYNQ_CTRL_CLOCK_MASK) |
- VLYNQ_CTRL_CLOCK_INT |
- VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1));
- vlynq_reg_write(dev->local->control,
- ((vlynq_reg_read(dev->local->control)
- & ~(VLYNQ_CTRL_CLOCK_INT |
- VLYNQ_CTRL_CLOCK_MASK)) |
- VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1)));
-
- if (vlynq_linked(dev)) {
- printk(KERN_DEBUG
- "%s: using remote clock divisor %d\n",
- dev->dev.bus_id, i - vlynq_rdiv1 + 1);
- dev->divisor = i;
- return 0;
- } else {
- vlynq_reset(dev);
- }
- }
-
- return -ENODEV;
-}
-
-static int __vlynq_try_local(struct vlynq_device *dev)
-{
- int i;
-
- vlynq_reset(dev);
-
- for (i = dev->dev_id ? vlynq_ldiv2 : vlynq_ldiv8; dev->dev_id ?
- i <= vlynq_ldiv8 : i >= vlynq_ldiv2;
- dev->dev_id ? i++ : i--) {
-
- vlynq_reg_write(dev->local->control,
- (vlynq_reg_read(dev->local->control) &
- ~VLYNQ_CTRL_CLOCK_MASK) |
- VLYNQ_CTRL_CLOCK_INT |
- VLYNQ_CTRL_CLOCK_DIV(i - vlynq_ldiv1));
-
- if (vlynq_linked(dev)) {
- printk(KERN_DEBUG
- "%s: using local clock divisor %d\n",
- dev->dev.bus_id, i - vlynq_ldiv1 + 1);
- dev->divisor = i;
- return 0;
- } else {
- vlynq_reset(dev);
- }
- }
-
- return -ENODEV;
-}
-
-static int __vlynq_try_external(struct vlynq_device *dev)
-{
- vlynq_reset(dev);
- if (!vlynq_linked(dev))
- return -ENODEV;
-
- vlynq_reg_write(dev->remote->control,
- (vlynq_reg_read(dev->remote->control) &
- ~VLYNQ_CTRL_CLOCK_INT));
-
- vlynq_reg_write(dev->local->control,
- (vlynq_reg_read(dev->local->control) &
- ~VLYNQ_CTRL_CLOCK_INT));
-
- if (vlynq_linked(dev)) {
- printk(KERN_DEBUG "%s: using external clock\n",
- dev->dev.bus_id);
- dev->divisor = vlynq_div_external;
- return 0;
- }
-
- return -ENODEV;
-}
-
-static int __vlynq_enable_device(struct vlynq_device *dev)
-{
- int result;
- struct plat_vlynq_ops *ops = dev->dev.platform_data;
-
- result = ops->on(dev);
- if (result)
- return result;
-
- switch (dev->divisor) {
- case vlynq_div_external:
- case vlynq_div_auto:
- /* When the device is brought from reset it should have clock
- generation negotiated by hardware.
- Check which device is generating clocks and perform setup
- accordingly */
- if (vlynq_linked(dev) && vlynq_reg_read(dev->remote->control) &
- VLYNQ_CTRL_CLOCK_INT) {
- if (!__vlynq_try_remote(dev) ||
- !__vlynq_try_local(dev) ||
- !__vlynq_try_external(dev))
- return 0;
- } else {
- if (!__vlynq_try_external(dev) ||
- !__vlynq_try_local(dev) ||
- !__vlynq_try_remote(dev))
- return 0;
- }
- break;
- case vlynq_ldiv1: case vlynq_ldiv2: case vlynq_ldiv3: case vlynq_ldiv4:
- case vlynq_ldiv5: case vlynq_ldiv6: case vlynq_ldiv7: case vlynq_ldiv8:
- vlynq_reg_write(dev->local->control,
- VLYNQ_CTRL_CLOCK_INT |
- VLYNQ_CTRL_CLOCK_DIV(dev->divisor -
- vlynq_ldiv1));
- vlynq_reg_write(dev->remote->control, 0);
- if (vlynq_linked(dev)) {
- printk(KERN_DEBUG
- "%s: using local clock divisor %d\n",
- dev->dev.bus_id, dev->divisor - vlynq_ldiv1 + 1);
- return 0;
- }
- break;
- case vlynq_rdiv1: case vlynq_rdiv2: case vlynq_rdiv3: case vlynq_rdiv4:
- case vlynq_rdiv5: case vlynq_rdiv6: case vlynq_rdiv7: case vlynq_rdiv8:
- vlynq_reg_write(dev->local->control, 0);
- vlynq_reg_write(dev->remote->control,
- VLYNQ_CTRL_CLOCK_INT |
- VLYNQ_CTRL_CLOCK_DIV(dev->divisor -
- vlynq_rdiv1));
- if (vlynq_linked(dev)) {
- printk(KERN_DEBUG
- "%s: using remote clock divisor %d\n",
- dev->dev.bus_id, dev->divisor - vlynq_rdiv1 + 1);
- return 0;
- }
- break;
- }
-
- ops->off(dev);
- return -ENODEV;
-}
-
-int vlynq_enable_device(struct vlynq_device *dev)
-{
- struct plat_vlynq_ops *ops = dev->dev.platform_data;
- int result = -ENODEV;
-
- result = __vlynq_enable_device(dev);
- if (result)
- return result;
-
- result = vlynq_setup_irq(dev);
- if (result)
- ops->off(dev);
-
- dev->enabled = !result;
- return result;
-}
-EXPORT_SYMBOL(vlynq_enable_device);
-
-
-void vlynq_disable_device(struct vlynq_device *dev)
-{
- struct plat_vlynq_ops *ops = dev->dev.platform_data;
-
- dev->enabled = 0;
- free_irq(dev->irq, dev);
- ops->off(dev);
-}
-EXPORT_SYMBOL(vlynq_disable_device);
-
-int vlynq_set_local_mapping(struct vlynq_device *dev, u32 tx_offset,
- struct vlynq_mapping *mapping)
-{
- int i;
-
- if (!dev->enabled)
- return -ENXIO;
-
- vlynq_reg_write(dev->local->tx_offset, tx_offset);
- for (i = 0; i < 4; i++) {
- vlynq_reg_write(dev->local->rx_mapping[i].offset,
- mapping[i].offset);
- vlynq_reg_write(dev->local->rx_mapping[i].size,
- mapping[i].size);
- }
- return 0;
-}
-EXPORT_SYMBOL(vlynq_set_local_mapping);
-
-int vlynq_set_remote_mapping(struct vlynq_device *dev, u32 tx_offset,
- struct vlynq_mapping *mapping)
-{
- int i;
-
- if (!dev->enabled)
- return -ENXIO;
-
- vlynq_reg_write(dev->remote->tx_offset, tx_offset);
- for (i = 0; i < 4; i++) {
- vlynq_reg_write(dev->remote->rx_mapping[i].offset,
- mapping[i].offset);
- vlynq_reg_write(dev->remote->rx_mapping[i].size,
- mapping[i].size);
- }
- return 0;
-}
-EXPORT_SYMBOL(vlynq_set_remote_mapping);
-
-int vlynq_set_local_irq(struct vlynq_device *dev, int virq)
-{
- int irq = dev->irq_start + virq;
- if (dev->enabled)
- return -EBUSY;
-
- if ((irq < dev->irq_start) || (irq > dev->irq_end))
- return -EINVAL;
-
- if (virq == dev->remote_irq)
- return -EINVAL;
-
- dev->local_irq = virq;
-
- return 0;
-}
-EXPORT_SYMBOL(vlynq_set_local_irq);
-
-int vlynq_set_remote_irq(struct vlynq_device *dev, int virq)
-{
- int irq = dev->irq_start + virq;
- if (dev->enabled)
- return -EBUSY;
-
- if ((irq < dev->irq_start) || (irq > dev->irq_end))
- return -EINVAL;
-
- if (virq == dev->local_irq)
- return -EINVAL;
-
- dev->remote_irq = virq;
-
- return 0;
-}
-EXPORT_SYMBOL(vlynq_set_remote_irq);
-
-static int vlynq_probe(struct platform_device *pdev)
-{
- struct vlynq_device *dev;
- struct resource *regs_res, *mem_res, *irq_res;
- int len, result;
-
- regs_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
- if (!regs_res)
- return -ENODEV;
-
- mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
- if (!mem_res)
- return -ENODEV;
-
- irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "devirq");
- if (!irq_res)
- return -ENODEV;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev) {
- printk(KERN_ERR
- "vlynq: failed to allocate device structure\n");
- return -ENOMEM;
- }
-
- dev->id = pdev->id;
- dev->dev.bus = &vlynq_bus_type;
- dev->dev.parent = &pdev->dev;
- snprintf(dev->dev.bus_id, BUS_ID_SIZE, "vlynq%d", dev->id);
- dev->dev.bus_id[BUS_ID_SIZE - 1] = 0;
- dev->dev.platform_data = pdev->dev.platform_data;
- dev->dev.release = vlynq_device_release;
-
- dev->regs_start = regs_res->start;
- dev->regs_end = regs_res->end;
- dev->mem_start = mem_res->start;
- dev->mem_end = mem_res->end;
-
- len = regs_res->end - regs_res->start;
- if (!request_mem_region(regs_res->start, len, dev->dev.bus_id)) {
- printk(KERN_ERR "%s: Can't request vlynq registers\n",
- dev->dev.bus_id);
- result = -ENXIO;
- goto fail_request;
- }
-
- dev->local = ioremap(regs_res->start, len);
- if (!dev->local) {
- printk(KERN_ERR "%s: Can't remap vlynq registers\n",
- dev->dev.bus_id);
- result = -ENXIO;
- goto fail_remap;
- }
-
- dev->remote = (struct vlynq_regs *)((void *)dev->local +
- VLYNQ_REMOTE_OFFSET);
-
- dev->irq = platform_get_irq_byname(pdev, "irq");
- dev->irq_start = irq_res->start;
- dev->irq_end = irq_res->end;
- dev->local_irq = dev->irq_end - dev->irq_start;
- dev->remote_irq = dev->local_irq - 1;
-
- if (device_register(&dev->dev))
- goto fail_register;
- platform_set_drvdata(pdev, dev);
-
- printk(KERN_INFO "%s: regs 0x%p, irq %d, mem 0x%p\n",
- dev->dev.bus_id, (void *)dev->regs_start, dev->irq,
- (void *)dev->mem_start);
-
- dev->dev_id = 0;
- dev->divisor = vlynq_div_auto;
- result = __vlynq_enable_device(dev);
- if (result == 0) {
- dev->dev_id = vlynq_reg_read(dev->remote->chip);
- ((struct plat_vlynq_ops *)(dev->dev.platform_data))->off(dev);
- }
- if (dev->dev_id)
- printk(KERN_INFO "Found a VLYNQ device: %08x\n", dev->dev_id);
-
- return 0;
-
-fail_register:
- iounmap(dev->local);
-fail_remap:
-fail_request:
- release_mem_region(regs_res->start, len);
- kfree(dev);
- return result;
-}
-
-static int vlynq_remove(struct platform_device *pdev)
-{
- struct vlynq_device *dev = platform_get_drvdata(pdev);
-
- device_unregister(&dev->dev);
- iounmap(dev->local);
- release_mem_region(dev->regs_start, dev->regs_end - dev->regs_start);
-
- kfree(dev);
-
- return 0;
-}
-
-static struct platform_driver vlynq_platform_driver = {
- .driver.name = "vlynq",
- .probe = vlynq_probe,
- .remove = __devexit_p(vlynq_remove),
-};
-
-struct bus_type vlynq_bus_type = {
- .name = "vlynq",
- .match = vlynq_device_match,
- .probe = vlynq_device_probe,
- .remove = vlynq_device_remove,
-};
-EXPORT_SYMBOL(vlynq_bus_type);
-
-static int __devinit vlynq_init(void)
-{
- int res = 0;
-
- res = bus_register(&vlynq_bus_type);
- if (res)
- goto fail_bus;
-
- res = platform_driver_register(&vlynq_platform_driver);
- if (res)
- goto fail_platform;
-
- return 0;
-
-fail_platform:
- bus_unregister(&vlynq_bus_type);
-fail_bus:
- return res;
-}
-
-static void __devexit vlynq_exit(void)
-{
- platform_driver_unregister(&vlynq_platform_driver);
- bus_unregister(&vlynq_bus_type);
-}
-
-module_init(vlynq_init);
-module_exit(vlynq_exit);