|
|
|
@ -21,15 +21,14 @@
|
|
|
|
|
#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/io.h>
|
|
|
|
|
|
|
|
|
|
#include <asm/ar7/vlynq.h>
|
|
|
|
|
|
|
|
|
|
#define PER_DEVICE_IRQS 32
|
|
|
|
|
#include <linux/vlynq.h>
|
|
|
|
|
|
|
|
|
|
#define VLYNQ_CTRL_PM_ENABLE 0x80000000
|
|
|
|
|
#define VLYNQ_CTRL_CLOCK_INT 0x00008000
|
|
|
|
@ -74,6 +73,8 @@ struct vlynq_regs {
|
|
|
|
|
#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)
|
|
|
|
|
{
|
|
|
|
@ -189,7 +190,6 @@ static void vlynq_remote_ack(unsigned int irq)
|
|
|
|
|
vlynq_reg_write(dev->remote->status, status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#warning FIXME: process one irq per call
|
|
|
|
|
static irqreturn_t vlynq_irq(int irq, void *dev_id)
|
|
|
|
|
{
|
|
|
|
|
struct vlynq_device *dev = dev_id;
|
|
|
|
@ -236,7 +236,7 @@ static struct irq_chip vlynq_remote_chip = {
|
|
|
|
|
static int vlynq_setup_irq(struct vlynq_device *dev)
|
|
|
|
|
{
|
|
|
|
|
u32 val;
|
|
|
|
|
int i;
|
|
|
|
|
int i, virq;
|
|
|
|
|
|
|
|
|
|
if (dev->local_irq == dev->remote_irq) {
|
|
|
|
|
printk(KERN_ERR
|
|
|
|
@ -264,23 +264,21 @@ static int vlynq_setup_irq(struct vlynq_device *dev)
|
|
|
|
|
vlynq_reg_write(dev->remote->int_ptr, VLYNQ_INT_OFFSET);
|
|
|
|
|
vlynq_reg_write(dev->remote->control, val);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < PER_DEVICE_IRQS; i++) {
|
|
|
|
|
if (i == dev->local_irq) {
|
|
|
|
|
set_irq_chip_and_handler(dev->irq_start + i,
|
|
|
|
|
&vlynq_local_chip,
|
|
|
|
|
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(dev->irq_start + i, dev);
|
|
|
|
|
} else if (i == dev->remote_irq) {
|
|
|
|
|
set_irq_chip_and_handler(dev->irq_start + i,
|
|
|
|
|
&vlynq_remote_chip,
|
|
|
|
|
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(dev->irq_start + i, dev);
|
|
|
|
|
set_irq_chip_data(i, dev);
|
|
|
|
|
} else {
|
|
|
|
|
set_irq_chip_and_handler(dev->irq_start + i,
|
|
|
|
|
&vlynq_irq_chip,
|
|
|
|
|
set_irq_chip_and_handler(i, &vlynq_irq_chip,
|
|
|
|
|
handle_simple_irq);
|
|
|
|
|
set_irq_chip_data(dev->irq_start + i, dev);
|
|
|
|
|
vlynq_reg_write(dev->remote->int_device[i >> 2], 0);
|
|
|
|
|
set_irq_chip_data(i, dev);
|
|
|
|
|
vlynq_reg_write(dev->remote->int_device[virq >> 2], 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -292,30 +290,59 @@ static int vlynq_setup_irq(struct vlynq_device *dev)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vlynq_free_irq(struct vlynq_device *dev)
|
|
|
|
|
static void vlynq_device_release(struct device *dev)
|
|
|
|
|
{
|
|
|
|
|
free_irq(dev->irq, dev);
|
|
|
|
|
struct vlynq_device *vdev = to_vlynq_device(dev);
|
|
|
|
|
kfree(vdev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vlynq_device_release(struct device *dev)
|
|
|
|
|
static int vlynq_device_match(struct device *dev,
|
|
|
|
|
struct device_driver *drv)
|
|
|
|
|
{
|
|
|
|
|
struct vlynq_device *vdev = to_vlynq_device(dev);
|
|
|
|
|
kfree(vdev);
|
|
|
|
|
struct vlynq_driver *vdrv = to_vlynq_driver(drv);
|
|
|
|
|
struct plat_vlynq_ops *ops = dev->platform_data;
|
|
|
|
|
struct vlynq_device_id *ids = vdrv->id_table;
|
|
|
|
|
u32 id = 0;
|
|
|
|
|
int result;
|
|
|
|
|
|
|
|
|
|
while (ids->id) {
|
|
|
|
|
vdev->divisor = ids->divisor;
|
|
|
|
|
result = __vlynq_enable_device(vdev);
|
|
|
|
|
if (result == 0) {
|
|
|
|
|
id = vlynq_reg_read(vdev->remote->chip);
|
|
|
|
|
ops->off(vdev);
|
|
|
|
|
if (ids->id == id) {
|
|
|
|
|
vlynq_set_drvdata(vdev, ids);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
if (drv->probe)
|
|
|
|
|
return drv->probe(to_vlynq_device(dev));
|
|
|
|
|
return 0;
|
|
|
|
|
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->remove)
|
|
|
|
|
return drv->remove(to_vlynq_device(dev));
|
|
|
|
|
if (drv && drv->remove)
|
|
|
|
|
drv->remove(to_vlynq_device(dev));
|
|
|
|
|
put_device(dev);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -333,7 +360,7 @@ void vlynq_unregister_driver(struct vlynq_driver *driver)
|
|
|
|
|
}
|
|
|
|
|
EXPORT_SYMBOL(vlynq_unregister_driver);
|
|
|
|
|
|
|
|
|
|
int vlynq_device_enable(struct vlynq_device *dev)
|
|
|
|
|
static int __vlynq_enable_device(struct vlynq_device *dev)
|
|
|
|
|
{
|
|
|
|
|
int i, result;
|
|
|
|
|
struct plat_vlynq_ops *ops = dev->dev.platform_data;
|
|
|
|
@ -344,7 +371,7 @@ int vlynq_device_enable(struct vlynq_device *dev)
|
|
|
|
|
|
|
|
|
|
switch (dev->divisor) {
|
|
|
|
|
case vlynq_div_auto:
|
|
|
|
|
/* First try locally supplied clock */
|
|
|
|
|
/* Only try locally supplied clock, others cause problems */
|
|
|
|
|
vlynq_reg_write(dev->remote->control, 0);
|
|
|
|
|
for (i = vlynq_ldiv1; i <= vlynq_ldiv8; i++) {
|
|
|
|
|
vlynq_reg_write(dev->local->control,
|
|
|
|
@ -354,30 +381,10 @@ int vlynq_device_enable(struct vlynq_device *dev)
|
|
|
|
|
printk(KERN_DEBUG
|
|
|
|
|
"%s: using local clock divisor %d\n",
|
|
|
|
|
dev->dev.bus_id, i - vlynq_ldiv1 + 1);
|
|
|
|
|
return vlynq_setup_irq(dev);
|
|
|
|
|
dev->divisor = i;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Then remotely supplied clock */
|
|
|
|
|
vlynq_reg_write(dev->local->control, 0);
|
|
|
|
|
for (i = vlynq_rdiv1; i <= vlynq_rdiv8; i++) {
|
|
|
|
|
vlynq_reg_write(dev->remote->control,
|
|
|
|
|
VLYNQ_CTRL_CLOCK_INT |
|
|
|
|
|
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);
|
|
|
|
|
return vlynq_setup_irq(dev);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* At last, externally supplied clock */
|
|
|
|
|
vlynq_reg_write(dev->remote->control, 0);
|
|
|
|
|
if (vlynq_linked(dev)) {
|
|
|
|
|
printk(KERN_DEBUG "%s: using external clock\n",
|
|
|
|
|
dev->dev.bus_id);
|
|
|
|
|
return vlynq_setup_irq(dev);
|
|
|
|
|
}
|
|
|
|
|
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->remote->control, 0);
|
|
|
|
@ -389,7 +396,7 @@ int vlynq_device_enable(struct vlynq_device *dev)
|
|
|
|
|
printk(KERN_DEBUG
|
|
|
|
|
"%s: using local clock divisor %d\n",
|
|
|
|
|
dev->dev.bus_id, dev->divisor - vlynq_ldiv1 + 1);
|
|
|
|
|
return vlynq_setup_irq(dev);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case vlynq_rdiv1: case vlynq_rdiv2: case vlynq_rdiv3: case vlynq_rdiv4:
|
|
|
|
@ -403,7 +410,7 @@ int vlynq_device_enable(struct vlynq_device *dev)
|
|
|
|
|
printk(KERN_DEBUG
|
|
|
|
|
"%s: using remote clock divisor %d\n",
|
|
|
|
|
dev->dev.bus_id, dev->divisor - vlynq_rdiv1 + 1);
|
|
|
|
|
return vlynq_setup_irq(dev);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case vlynq_div_external:
|
|
|
|
@ -412,32 +419,52 @@ int vlynq_device_enable(struct vlynq_device *dev)
|
|
|
|
|
if (vlynq_linked(dev)) {
|
|
|
|
|
printk(KERN_DEBUG "%s: using external clock\n",
|
|
|
|
|
dev->dev.bus_id);
|
|
|
|
|
return vlynq_setup_irq(dev);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ops->off(dev);
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vlynq_device_disable(struct vlynq_device *dev)
|
|
|
|
|
int vlynq_enable_device(struct vlynq_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct plat_vlynq_ops *ops = dev->dev.platform_data;
|
|
|
|
|
int result = -ENODEV;
|
|
|
|
|
|
|
|
|
|
vlynq_free_irq(dev);
|
|
|
|
|
ops->off(dev);
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
u32 vlynq_remote_id(struct vlynq_device *dev)
|
|
|
|
|
void vlynq_disable_device(struct vlynq_device *dev)
|
|
|
|
|
{
|
|
|
|
|
return vlynq_reg_read(dev->remote->chip);
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
void vlynq_set_local_mapping(struct vlynq_device *dev, u32 tx_offset,
|
|
|
|
|
struct vlynq_mapping *mapping)
|
|
|
|
|
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,
|
|
|
|
@ -445,13 +472,18 @@ void vlynq_set_local_mapping(struct vlynq_device *dev, u32 tx_offset,
|
|
|
|
|
vlynq_reg_write(dev->local->rx_mapping[i].size,
|
|
|
|
|
mapping[i].size);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
EXPORT_SYMBOL(vlynq_set_local_mapping);
|
|
|
|
|
|
|
|
|
|
void vlynq_set_remote_mapping(struct vlynq_device *dev, u32 tx_offset,
|
|
|
|
|
struct vlynq_mapping *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,
|
|
|
|
@ -459,27 +491,17 @@ void vlynq_set_remote_mapping(struct vlynq_device *dev, u32 tx_offset,
|
|
|
|
|
vlynq_reg_write(dev->remote->rx_mapping[i].size,
|
|
|
|
|
mapping[i].size);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int vlynq_virq_to_irq(struct vlynq_device *dev, int virq)
|
|
|
|
|
{
|
|
|
|
|
if ((virq < 0) || (virq >= PER_DEVICE_IRQS))
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
|
|
return dev->irq_start + virq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int vlynq_irq_to_virq(struct vlynq_device *dev, int irq)
|
|
|
|
|
{
|
|
|
|
|
if ((irq < dev->irq_start) || (irq >= dev->irq_start + PER_DEVICE_IRQS))
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
|
|
return irq - dev->irq_start;
|
|
|
|
|
}
|
|
|
|
|
EXPORT_SYMBOL(vlynq_set_remote_mapping);
|
|
|
|
|
|
|
|
|
|
int vlynq_set_local_irq(struct vlynq_device *dev, int virq)
|
|
|
|
|
{
|
|
|
|
|
if ((virq < 0) || (virq >= PER_DEVICE_IRQS))
|
|
|
|
|
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)
|
|
|
|
@ -489,10 +511,15 @@ int vlynq_set_local_irq(struct vlynq_device *dev, int virq)
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
EXPORT_SYMBOL(vlynq_set_local_irq);
|
|
|
|
|
|
|
|
|
|
int vlynq_set_remote_irq(struct vlynq_device *dev, int virq)
|
|
|
|
|
{
|
|
|
|
|
if ((virq < 0) || (virq >= PER_DEVICE_IRQS))
|
|
|
|
|
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)
|
|
|
|
@ -502,6 +529,7 @@ int vlynq_set_remote_irq(struct vlynq_device *dev, int virq)
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
EXPORT_SYMBOL(vlynq_set_remote_irq);
|
|
|
|
|
|
|
|
|
|
static int vlynq_probe(struct platform_device *pdev)
|
|
|
|
|
{
|
|
|
|
@ -509,9 +537,6 @@ static int vlynq_probe(struct platform_device *pdev)
|
|
|
|
|
struct resource *regs_res, *mem_res, *irq_res;
|
|
|
|
|
int len, result;
|
|
|
|
|
|
|
|
|
|
if (strcmp(pdev->name, "vlynq"))
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
|
|
regs_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
|
|
|
|
|
if (!regs_res)
|
|
|
|
|
return -ENODEV;
|
|
|
|
@ -560,14 +585,14 @@ static int vlynq_probe(struct platform_device *pdev)
|
|
|
|
|
goto fail_remap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dev->remote = (struct vlynq_regs *)((u32)dev->local +
|
|
|
|
|
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 = 31;
|
|
|
|
|
dev->remote_irq = 30;
|
|
|
|
|
dev->local_irq = dev->irq_end - dev->irq_start;
|
|
|
|
|
dev->remote_irq = dev->local_irq - 1;
|
|
|
|
|
|
|
|
|
|
if (device_register(&dev->dev))
|
|
|
|
|
goto fail_register;
|
|
|
|
@ -604,20 +629,18 @@ static int vlynq_remove(struct platform_device *pdev)
|
|
|
|
|
static struct platform_driver vlynq_driver = {
|
|
|
|
|
.driver.name = "vlynq",
|
|
|
|
|
.probe = vlynq_probe,
|
|
|
|
|
.remove = vlynq_remove,
|
|
|
|
|
.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);
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_PCI
|
|
|
|
|
extern void vlynq_pci_init(void);
|
|
|
|
|
#endif
|
|
|
|
|
static int __init vlynq_init(void)
|
|
|
|
|
static int __devinit vlynq_init(void)
|
|
|
|
|
{
|
|
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
|
@ -629,10 +652,6 @@ static int __init vlynq_init(void)
|
|
|
|
|
if (res)
|
|
|
|
|
goto fail_platform;
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_PCI
|
|
|
|
|
vlynq_pci_init();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
fail_platform:
|
|
|
|
@ -641,13 +660,11 @@ fail_bus:
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add this back when vlynq-pci crap is gone */
|
|
|
|
|
#if 0
|
|
|
|
|
static void __devexit vlynq_exit(void)
|
|
|
|
|
{
|
|
|
|
|
platform_driver_unregister(&vlynq_driver);
|
|
|
|
|
bus_unregister(&vlynq_bus_type);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
subsys_initcall(vlynq_init);
|
|
|
|
|
module_init(vlynq_init);
|
|
|
|
|
module_exit(vlynq_exit);
|