source "drivers/staging/netlogic/Kconfig"
+source "drivers/staging/mt29f_spinand/Kconfig"
+
source "drivers/staging/dwc2/Kconfig"
source "drivers/staging/lustre/Kconfig"
obj-$(CONFIG_XILLYBUS) += xillybus/
obj-$(CONFIG_DGNC) += dgnc/
obj-$(CONFIG_DGAP) += dgap/
+obj-$(CONFIG_MTD_SPINAND_MT29F) += mt29f_spinand/
__func__, puBuf, dwLength, bCircular);
/* To pin down user pages we must first acquire the mapping semaphore. */
- down_read(¤t->mm->mmap_sem); /* get memory map semaphore */
- nPages = get_user_pages(current, current->mm, ulStart, len, 1, 0,
- pPages, NULL);
- up_read(¤t->mm->mmap_sem); /* release the semaphore */
+ nPages = get_user_pages_fast(ulStart, len, 1, pPages);
dev_dbg(&pdx->interface->dev, "%s nPages = %d", __func__, nPages);
if (nPages > 0) { /* if we succeeded */
config COMEDI_NI_6527
tristate "NI 6527 support"
- depends on HAS_DMA
- select COMEDI_MITE
---help---
Enable support for the National Instruments 6527 PCI card
/*
- comedi/drivers/ni_6527.c
- driver for National Instruments PCI-6527
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.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.
-*/
-/*
-Driver: ni_6527
-Description: National Instruments 6527
-Author: ds
-Status: works
-Devices: [National Instruments] PCI-6527 (ni6527), PXI-6527
-Updated: Sat, 25 Jan 2003 13:24:40 -0800
-
-
-*/
+ * ni_6527.c
+ * Comedi driver for National Instruments PCI-6527
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.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.
+ */
/*
- Manuals (available from ftp://ftp.natinst.com/support/manuals)
-
- 370106b.pdf 6527 Register Level Programmer Manual
-
+ * Driver: ni_6527
+ * Description: National Instruments 6527
+ * Devices: (National Instruments) PCI-6527 [pci-6527]
+ * (National Instruments) PXI-6527 [pxi-6527]
+ * Author: David A. Schleef <ds@schleef.org>
+ * Updated: Sat, 25 Jan 2003 13:24:40 -0800
+ * Status: works
+ *
+ * Configuration Options: not applicable, uses PCI auto config
*/
-#define DEBUG 1
-#define DEBUG_FLAGS
-
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include "../comedidev.h"
#include "comedi_fc.h"
-#include "mite.h"
-
-#define DRIVER_NAME "ni_6527"
-
-#define NI6527_DIO_SIZE 4096
-#define NI6527_MITE_SIZE 4096
-
-#define Port_Register(x) (0x00+(x))
-#define ID_Register 0x06
-#define Clear_Register 0x07
-#define ClrEdge 0x08
-#define ClrOverflow 0x04
-#define ClrFilter 0x02
-#define ClrInterval 0x01
-
-#define Filter_Interval(x) (0x08+(x))
-#define Filter_Enable(x) (0x0c+(x))
-
-#define Change_Status 0x14
-#define MasterInterruptStatus 0x04
-#define Overflow 0x02
-#define EdgeStatus 0x01
-
-#define Master_Interrupt_Control 0x15
-#define FallingEdgeIntEnable 0x10
-#define RisingEdgeIntEnable 0x08
-#define MasterInterruptEnable 0x04
-#define OverflowIntEnable 0x02
-#define EdgeIntEnable 0x01
-
-#define Rising_Edge_Detection_Enable(x) (0x018+(x))
-#define Falling_Edge_Detection_Enable(x) (0x020+(x))
+/*
+ * PCI BAR1 - Register memory map
+ *
+ * Manuals (available from ftp://ftp.natinst.com/support/manuals)
+ * 370106b.pdf 6527 Register Level Programmer Manual
+ */
+#define NI6527_DI_REG(x) (0x00 + (x))
+#define NI6527_DO_REG(x) (0x03 + (x))
+#define NI6527_ID_REG 0x06
+#define NI6527_CLR_REG 0x07
+#define NI6527_CLR_EDGE (1 << 3)
+#define NI6527_CLR_OVERFLOW (1 << 2)
+#define NI6527_CLR_FILT (1 << 1)
+#define NI6527_CLR_INTERVAL (1 << 0)
+#define NI6527_CLR_IRQS (NI6527_CLR_EDGE | NI6527_CLR_OVERFLOW)
+#define NI6527_CLR_RESET_FILT (NI6527_CLR_FILT | NI6527_CLR_INTERVAL)
+#define NI6527_FILT_INTERVAL_REG(x) (0x08 + (x))
+#define NI6527_FILT_ENA_REG(x) (0x0c + (x))
+#define NI6527_STATUS_REG 0x14
+#define NI6527_STATUS_IRQ (1 << 2)
+#define NI6527_STATUS_OVERFLOW (1 << 1)
+#define NI6527_STATUS_EDGE (1 << 0)
+#define NI6527_CTRL_REG 0x15
+#define NI6527_CTRL_FALLING (1 << 4)
+#define NI6527_CTRL_RISING (1 << 3)
+#define NI6527_CTRL_IRQ (1 << 2)
+#define NI6527_CTRL_OVERFLOW (1 << 1)
+#define NI6527_CTRL_EDGE (1 << 0)
+#define NI6527_CTRL_DISABLE_IRQS 0
+#define NI6527_CTRL_ENABLE_IRQS (NI6527_CTRL_FALLING | \
+ NI6527_CTRL_RISING | \
+ NI6527_CTRL_IRQ | NI6527_CTRL_EDGE)
+#define NI6527_RISING_EDGE_REG(x) (0x18 + (x))
+#define NI6527_FALLING_EDGE_REG(x) (0x20 + (x))
enum ni6527_boardid {
BOARD_PCI6527,
};
struct ni6527_private {
- struct mite_struct *mite;
+ void __iomem *mmio_base;
unsigned int filter_interval;
unsigned int filter_enable;
};
+static void ni6527_set_filter_interval(struct comedi_device *dev,
+ unsigned int val)
+{
+ struct ni6527_private *devpriv = dev->private;
+ void __iomem *mmio = devpriv->mmio_base;
+
+ if (val != devpriv->filter_interval) {
+ writeb(val & 0xff, mmio + NI6527_FILT_INTERVAL_REG(0));
+ writeb((val >> 8) & 0xff, mmio + NI6527_FILT_INTERVAL_REG(1));
+ writeb((val >> 16) & 0x0f, mmio + NI6527_FILT_INTERVAL_REG(2));
+
+ writeb(NI6527_CLR_INTERVAL, mmio + NI6527_CLR_REG);
+
+ devpriv->filter_interval = val;
+ }
+}
+
+static void ni6527_set_filter_enable(struct comedi_device *dev,
+ unsigned int val)
+{
+ struct ni6527_private *devpriv = dev->private;
+ void __iomem *mmio = devpriv->mmio_base;
+
+ writeb(val & 0xff, mmio + NI6527_FILT_ENA_REG(0));
+ writeb((val >> 8) & 0xff, mmio + NI6527_FILT_ENA_REG(1));
+ writeb((val >> 16) & 0xff, mmio + NI6527_FILT_ENA_REG(2));
+}
+
static int ni6527_di_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct ni6527_private *devpriv = dev->private;
- int chan = CR_CHAN(insn->chanspec);
+ unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int interval;
- if (insn->n != 2)
- return -EINVAL;
-
- if (data[0] != INSN_CONFIG_FILTER)
- return -EINVAL;
-
- if (data[1]) {
+ switch (data[0]) {
+ case INSN_CONFIG_FILTER:
+ /*
+ * The deglitch filter interval is specified in nanoseconds.
+ * The hardware supports intervals in 200ns increments. Round
+ * the user values up and return the actual interval.
+ */
interval = (data[1] + 100) / 200;
data[1] = interval * 200;
- if (interval != devpriv->filter_interval) {
- writeb(interval & 0xff,
- devpriv->mite->daq_io_addr + Filter_Interval(0));
- writeb((interval >> 8) & 0xff,
- devpriv->mite->daq_io_addr + Filter_Interval(1));
- writeb((interval >> 16) & 0x0f,
- devpriv->mite->daq_io_addr + Filter_Interval(2));
-
- writeb(ClrInterval,
- devpriv->mite->daq_io_addr + Clear_Register);
-
- devpriv->filter_interval = interval;
+ if (interval) {
+ ni6527_set_filter_interval(dev, interval);
+ devpriv->filter_enable |= 1 << chan;
+ } else {
+ devpriv->filter_enable &= ~(1 << chan);
}
-
- devpriv->filter_enable |= 1 << chan;
- } else {
- devpriv->filter_enable &= ~(1 << chan);
+ ni6527_set_filter_enable(dev, devpriv->filter_enable);
+ break;
+ default:
+ return -EINVAL;
}
- writeb(devpriv->filter_enable,
- devpriv->mite->daq_io_addr + Filter_Enable(0));
- writeb(devpriv->filter_enable >> 8,
- devpriv->mite->daq_io_addr + Filter_Enable(1));
- writeb(devpriv->filter_enable >> 16,
- devpriv->mite->daq_io_addr + Filter_Enable(2));
-
- return 2;
+ return insn->n;
}
static int ni6527_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct ni6527_private *devpriv = dev->private;
+ void __iomem *mmio = devpriv->mmio_base;
+ unsigned int val;
- data[1] = readb(devpriv->mite->daq_io_addr + Port_Register(0));
- data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(1)) << 8;
- data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(2)) << 16;
+ val = readb(mmio + NI6527_DI_REG(0));
+ val |= (readb(mmio + NI6527_DI_REG(1)) << 8);
+ val |= (readb(mmio + NI6527_DI_REG(2)) << 16);
+
+ data[1] = val;
return insn->n;
}
unsigned int *data)
{
struct ni6527_private *devpriv = dev->private;
+ void __iomem *mmio = devpriv->mmio_base;
unsigned int mask;
mask = comedi_dio_update_state(s, data);
if (mask) {
/* Outputs are inverted */
- if (mask & 0x0000ff) {
- writeb(s->state ^ 0xff,
- devpriv->mite->daq_io_addr + Port_Register(3));
- }
- if (mask & 0x00ff00) {
- writeb((s->state >> 8) ^ 0xff,
- devpriv->mite->daq_io_addr + Port_Register(4));
- }
- if (mask & 0xff0000) {
- writeb((s->state >> 16) ^ 0xff,
- devpriv->mite->daq_io_addr + Port_Register(5));
- }
+ unsigned int val = s->state ^ 0xffffff;
+
+ if (mask & 0x0000ff)
+ writeb(val & 0xff, mmio + NI6527_DO_REG(0));
+ if (mask & 0x00ff00)
+ writeb((val >> 8) & 0xff, mmio + NI6527_DO_REG(1));
+ if (mask & 0xff0000)
+ writeb((val >> 16) & 0xff, mmio + NI6527_DO_REG(2));
}
data[1] = s->state;
{
struct comedi_device *dev = d;
struct ni6527_private *devpriv = dev->private;
- struct comedi_subdevice *s = &dev->subdevices[2];
+ struct comedi_subdevice *s = dev->read_subdev;
+ void __iomem *mmio = devpriv->mmio_base;
unsigned int status;
- status = readb(devpriv->mite->daq_io_addr + Change_Status);
- if ((status & MasterInterruptStatus) == 0)
- return IRQ_NONE;
- if ((status & EdgeStatus) == 0)
+ status = readb(mmio + NI6527_STATUS_REG);
+ if (!(status & NI6527_STATUS_IRQ))
return IRQ_NONE;
- writeb(ClrEdge | ClrOverflow,
- devpriv->mite->daq_io_addr + Clear_Register);
+ if (status & NI6527_STATUS_EDGE) {
+ comedi_buf_put(s->async, 0);
+ s->async->events |= COMEDI_CB_EOS;
+ comedi_event(dev, s);
+ }
+
+ writeb(NI6527_CLR_IRQS, mmio + NI6527_CLR_REG);
- comedi_buf_put(s->async, 0);
- s->async->events |= COMEDI_CB_EOS;
- comedi_event(dev, s);
return IRQ_HANDLED;
}
struct comedi_subdevice *s)
{
struct ni6527_private *devpriv = dev->private;
- /* struct comedi_cmd *cmd = &s->async->cmd; */
+ void __iomem *mmio = devpriv->mmio_base;
- writeb(ClrEdge | ClrOverflow,
- devpriv->mite->daq_io_addr + Clear_Register);
- writeb(FallingEdgeIntEnable | RisingEdgeIntEnable |
- MasterInterruptEnable | EdgeIntEnable,
- devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+ writeb(NI6527_CLR_IRQS, mmio + NI6527_CLR_REG);
+ writeb(NI6527_CTRL_ENABLE_IRQS, mmio + NI6527_CTRL_REG);
return 0;
}
struct comedi_subdevice *s)
{
struct ni6527_private *devpriv = dev->private;
+ void __iomem *mmio = devpriv->mmio_base;
- writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+ writeb(NI6527_CTRL_DISABLE_IRQS, mmio + NI6527_CTRL_REG);
return 0;
}
return insn->n;
}
+static void ni6527_set_edge_detection(struct comedi_device *dev,
+ unsigned int rising,
+ unsigned int falling)
+{
+ struct ni6527_private *devpriv = dev->private;
+ void __iomem *mmio = devpriv->mmio_base;
+
+ /* enable rising-edge detection channels */
+ writeb(rising & 0xff, mmio + NI6527_RISING_EDGE_REG(0));
+ writeb((rising >> 8) & 0xff, mmio + NI6527_RISING_EDGE_REG(1));
+ writeb((rising >> 16) & 0xff, mmio + NI6527_RISING_EDGE_REG(2));
+
+ /* enable falling-edge detection channels */
+ writeb(falling & 0xff, mmio + NI6527_FALLING_EDGE_REG(0));
+ writeb((falling >> 8) & 0xff, mmio + NI6527_FALLING_EDGE_REG(1));
+ writeb((falling >> 16) & 0xff, mmio + NI6527_FALLING_EDGE_REG(2));
+}
+
static int ni6527_intr_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ switch (data[0]) {
+ case INSN_CONFIG_CHANGE_NOTIFY:
+ /* check_insn_config_length() does not check this instruction */
+ if (insn->n != 3)
+ return -EINVAL;
+ ni6527_set_edge_detection(dev, data[1], data[2]);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return insn->n;
+}
+
+static void ni6527_reset(struct comedi_device *dev)
{
struct ni6527_private *devpriv = dev->private;
+ void __iomem *mmio = devpriv->mmio_base;
- if (insn->n < 1)
- return -EINVAL;
- if (data[0] != INSN_CONFIG_CHANGE_NOTIFY)
- return -EINVAL;
+ /* disable deglitch filters on all channels */
+ ni6527_set_filter_enable(dev, 0);
- writeb(data[1],
- devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(0));
- writeb(data[1] >> 8,
- devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(1));
- writeb(data[1] >> 16,
- devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(2));
-
- writeb(data[2],
- devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(0));
- writeb(data[2] >> 8,
- devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(1));
- writeb(data[2] >> 16,
- devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(2));
-
- return 2;
+ writeb(NI6527_CLR_IRQS | NI6527_CLR_RESET_FILT,
+ mmio + NI6527_CLR_REG);
+ writeb(NI6527_CTRL_DISABLE_IRQS, mmio + NI6527_CTRL_REG);
}
static int ni6527_auto_attach(struct comedi_device *dev,
dev->board_ptr = board;
dev->board_name = board->name;
+ devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+ if (!devpriv)
+ return -ENOMEM;
+
ret = comedi_pci_enable(dev);
if (ret)
return ret;
- devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
- if (!devpriv)
+ devpriv->mmio_base = pci_ioremap_bar(pcidev, 1);
+ if (!devpriv->mmio_base)
return -ENOMEM;
- devpriv->mite = mite_alloc(pcidev);
- if (!devpriv->mite)
- return -ENOMEM;
+ /* make sure this is actually a 6527 device */
+ if (readb(devpriv->mmio_base + NI6527_ID_REG) != 0x27)
+ return -ENODEV;
- ret = mite_setup(devpriv->mite);
- if (ret < 0) {
- dev_err(dev->class_dev, "error setting up mite\n");
- return ret;
- }
+ ni6527_reset(dev);
- dev_info(dev->class_dev, "board: %s, ID=0x%02x\n", dev->board_name,
- readb(devpriv->mite->daq_io_addr + ID_Register));
+ ret = request_irq(pcidev->irq, ni6527_interrupt, IRQF_SHARED,
+ dev->board_name, dev);
+ if (ret == 0)
+ dev->irq = pcidev->irq;
ret = comedi_alloc_subdevices(dev, 3);
if (ret)
return ret;
+ /* Digital Input subdevice */
s = &dev->subdevices[0];
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = 24;
- s->range_table = &range_digital;
- s->maxdata = 1;
- s->insn_config = ni6527_di_insn_config;
- s->insn_bits = ni6527_di_insn_bits;
-
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 24;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_config = ni6527_di_insn_config;
+ s->insn_bits = ni6527_di_insn_bits;
+
+ /* Digital Output subdevice */
s = &dev->subdevices[1];
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 24;
- s->range_table = &range_unknown; /* FIXME: actually conductance */
- s->maxdata = 1;
- s->insn_bits = ni6527_do_insn_bits;
-
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 24;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = ni6527_do_insn_bits;
+
+ /* Edge detection interrupt subdevice */
s = &dev->subdevices[2];
- dev->read_subdev = s;
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
- s->n_chan = 1;
- s->range_table = &range_unknown;
- s->maxdata = 1;
- s->do_cmdtest = ni6527_intr_cmdtest;
- s->do_cmd = ni6527_intr_cmd;
- s->cancel = ni6527_intr_cancel;
- s->insn_bits = ni6527_intr_insn_bits;
- s->insn_config = ni6527_intr_insn_config;
-
- writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(0));
- writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(1));
- writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(2));
-
- writeb(ClrEdge | ClrOverflow | ClrFilter | ClrInterval,
- devpriv->mite->daq_io_addr + Clear_Register);
- writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
-
- ret = request_irq(mite_irq(devpriv->mite), ni6527_interrupt,
- IRQF_SHARED, DRIVER_NAME, dev);
- if (ret < 0)
- dev_warn(dev->class_dev, "irq not available\n");
- else
- dev->irq = mite_irq(devpriv->mite);
+ if (dev->irq) {
+ dev->read_subdev = s;
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+ s->n_chan = 1;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_config = ni6527_intr_insn_config;
+ s->insn_bits = ni6527_intr_insn_bits;
+ s->do_cmdtest = ni6527_intr_cmdtest;
+ s->do_cmd = ni6527_intr_cmd;
+ s->cancel = ni6527_intr_cancel;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
return 0;
}
{
struct ni6527_private *devpriv = dev->private;
- if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr)
- writeb(0x00,
- devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+ if (devpriv && devpriv->mmio_base)
+ ni6527_reset(dev);
if (dev->irq)
free_irq(dev->irq, dev);
- if (devpriv && devpriv->mite) {
- mite_unsetup(devpriv->mite);
- mite_free(devpriv->mite);
- }
comedi_pci_disable(dev);
}
static struct comedi_driver ni6527_driver = {
- .driver_name = DRIVER_NAME,
- .module = THIS_MODULE,
- .auto_attach = ni6527_auto_attach,
- .detach = ni6527_detach,
+ .driver_name = "ni_6527",
+ .module = THIS_MODULE,
+ .auto_attach = ni6527_auto_attach,
+ .detach = ni6527_detach,
};
static int ni6527_pci_probe(struct pci_dev *dev,
MODULE_DEVICE_TABLE(pci, ni6527_pci_table);
static struct pci_driver ni6527_pci_driver = {
- .name = DRIVER_NAME,
+ .name = "ni_6527",
.id_table = ni6527_pci_table,
.probe = ni6527_pci_probe,
.remove = comedi_pci_auto_unconfig,
module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for National Instruments PCI-6527");
MODULE_LICENSE("GPL");
/*
- comedi/drivers/ni_at_ao.c
- Driver for NI AT-AO-6/10 boards
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000,2002 David A. Schleef <ds@schleef.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.
-*/
-/*
-Driver: ni_at_ao
-Description: National Instruments AT-AO-6/10
-Devices: [National Instruments] AT-AO-6 (at-ao-6), AT-AO-10 (at-ao-10)
-Status: should work
-Author: ds
-Updated: Sun Dec 26 12:26:28 EST 2004
-
-Configuration options:
- [0] - I/O port base address
- [1] - IRQ (unused)
- [2] - DMA (unused)
- [3] - analog output range, set by jumpers on hardware (0 for -10 to 10V
- bipolar, 1 for 0V to 10V unipolar)
-
-*/
+ * ni_at_ao.c
+ * Driver for NI AT-AO-6/10 boards
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000,2002 David A. Schleef <ds@schleef.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.
+ */
+
/*
- * Register-level programming information can be found in NI
- * document 320379.pdf.
+ * Driver: ni_at_ao
+ * Description: National Instruments AT-AO-6/10
+ * Devices: (National Instruments) AT-AO-6 [at-ao-6]
+ * (National Instruments) AT-AO-10 [at-ao-10]
+ * Status: should work
+ * Author: David A. Schleef <ds@schleef.org>
+ * Updated: Sun Dec 26 12:26:28 EST 2004
+ *
+ * Configuration options:
+ * [0] - I/O port base address
+ * [1] - IRQ (unused)
+ * [2] - DMA (unused)
+ * [3] - analog output range, set by jumpers on hardware
+ * 0 for -10 to 10V bipolar
+ * 1 for 0V to 10V unipolar
*/
#include <linux/module.h>
-#include "../comedidev.h"
-/* board egisters */
-/* registers with _2_ are accessed when GRP2WR is set in CFG1 */
+#include "../comedidev.h"
-#define ATAO_SIZE 0x20
-
-#define ATAO_2_DMATCCLR 0x00 /* W 16 */
-#define ATAO_DIN 0x00 /* R 16 */
-#define ATAO_DOUT 0x00 /* W 16 */
-
-#define ATAO_CFG2 0x02 /* W 16 */
-#define CALLD1 0x8000
-#define CALLD0 0x4000
-#define FFRTEN 0x2000
-#define DAC2S8 0x1000
-#define DAC2S6 0x0800
-#define DAC2S4 0x0400
-#define DAC2S2 0x0200
-#define DAC2S0 0x0100
-#define LDAC8 0x0080
-#define LDAC6 0x0040
-#define LDAC4 0x0020
-#define LDAC2 0x0010
-#define LDAC0 0x0008
-#define PROMEN 0x0004
-#define SCLK 0x0002
-#define SDATA 0x0001
-
-#define ATAO_2_INT1CLR 0x02 /* W 16 */
-
-#define ATAO_CFG3 0x04 /* W 16 */
-#define DMAMODE 0x0040
-#define CLKOUT 0x0020
-#define RCLKEN 0x0010
-#define DOUTEN2 0x0008
-#define DOUTEN1 0x0004
-#define EN2_5V 0x0002
-#define SCANEN 0x0001
-
-#define ATAO_2_INT2CLR 0x04 /* W 16 */
-
-#define ATAO_82C53_BASE 0x06 /* RW 8 */
-
-#define ATAO_82C53_CNTR1 0x06 /* RW 8 */
-#define ATAO_82C53_CNTR2 0x07 /* RW 8 */
-#define ATAO_82C53_CNTR3 0x08 /* RW 8 */
-#define ATAO_82C53_CNTRCMD 0x09 /* W 8 */
-#define CNTRSEL1 0x80
-#define CNTRSEL0 0x40
-#define RWSEL1 0x20
-#define RWSEL0 0x10
-#define MODESEL2 0x08
-#define MODESEL1 0x04
-#define MODESEL0 0x02
-#define BCDSEL 0x01
- /* read-back command */
-#define COUNT 0x20
-#define STATUS 0x10
-#define CNTR3 0x08
-#define CNTR2 0x04
-#define CNTR1 0x02
- /* status */
-#define OUT 0x80
-#define _NULL 0x40
-#define RW1 0x20
-#define RW0 0x10
-#define MODE2 0x08
-#define MODE1 0x04
-#define MODE0 0x02
-#define BCD 0x01
-
-#define ATAO_2_RTSISHFT 0x06 /* W 8 */
-#define ATAO_RTSISHFT_RSI (1 << 0)
-
-#define ATAO_2_RTSISTRB 0x07 /* W 8 */
-
-#define ATAO_CFG1 0x0a /* W 16 */
-#define EXTINT2EN 0x8000
-#define EXTINT1EN 0x4000
-#define CNTINT2EN 0x2000
-#define CNTINT1EN 0x1000
-#define TCINTEN 0x0800
-#define CNT1SRC 0x0400
-#define CNT2SRC 0x0200
-#define FIFOEN 0x0100
-#define GRP2WR 0x0080
-#define EXTUPDEN 0x0040
-#define DMARQ 0x0020
-#define DMAEN 0x0010
-#define CH_mask 0x000f
-#define ATAO_STATUS 0x0a /* R 16 */
-#define FH 0x0040
-#define FE 0x0020
-#define FF 0x0010
-#define INT2 0x0008
-#define INT1 0x0004
-#define TCINT 0x0002
-#define PROMOUT 0x0001
-
-#define ATAO_FIFO_WRITE 0x0c /* W 16 */
-#define ATAO_FIFO_CLEAR 0x0c /* R 16 */
-#define ATAO_DACn(x) (0x0c + 2*(x)) /* W */
+#include "8253.h"
/*
- * Board descriptions for two imaginary boards. Describing the
- * boards in this way is optional, and completely driver-dependent.
- * Some drivers use arrays such as this, other do not.
+ * Register map
+ *
+ * Register-level programming information can be found in NI
+ * document 320379.pdf.
*/
+#define ATAO_DIO_REG 0x00
+#define ATAO_CFG2_REG 0x02
+#define ATAO_CFG2_CALLD_NOP (0 << 14)
+#define ATAO_CFG2_CALLD(x) ((((x) >> 3) + 1) << 14)
+#define ATAO_CFG2_FFRTEN (1 << 13)
+#define ATAO_CFG2_DACS(x) (1 << (((x) / 2) + 8))
+#define ATAO_CFG2_LDAC(x) (1 << (((x) / 2) + 3))
+#define ATAO_CFG2_PROMEN (1 << 2)
+#define ATAO_CFG2_SCLK (1 << 1)
+#define ATAO_CFG2_SDATA (1 << 0)
+#define ATAO_CFG3_REG 0x04
+#define ATAO_CFG3_DMAMODE (1 << 6)
+#define ATAO_CFG3_CLKOUT (1 << 5)
+#define ATAO_CFG3_RCLKEN (1 << 4)
+#define ATAO_CFG3_DOUTEN2 (1 << 3)
+#define ATAO_CFG3_DOUTEN1 (1 << 2)
+#define ATAO_CFG3_EN2_5V (1 << 1)
+#define ATAO_CFG3_SCANEN (1 << 0)
+#define ATAO_82C53_BASE 0x06
+#define ATAO_CFG1_REG 0x0a
+#define ATAO_CFG1_EXTINT2EN (1 << 15)
+#define ATAO_CFG1_EXTINT1EN (1 << 14)
+#define ATAO_CFG1_CNTINT2EN (1 << 13)
+#define ATAO_CFG1_CNTINT1EN (1 << 12)
+#define ATAO_CFG1_TCINTEN (1 << 11)
+#define ATAO_CFG1_CNT1SRC (1 << 10)
+#define ATAO_CFG1_CNT2SRC (1 << 9)
+#define ATAO_CFG1_FIFOEN (1 << 8)
+#define ATAO_CFG1_GRP2WR (1 << 7)
+#define ATAO_CFG1_EXTUPDEN (1 << 6)
+#define ATAO_CFG1_DMARQ (1 << 5)
+#define ATAO_CFG1_DMAEN (1 << 4)
+#define ATAO_CFG1_CH(x) (((x) & 0xf) << 0)
+#define ATAO_STATUS_REG 0x0a
+#define ATAO_STATUS_FH (1 << 6)
+#define ATAO_STATUS_FE (1 << 5)
+#define ATAO_STATUS_FF (1 << 4)
+#define ATAO_STATUS_INT2 (1 << 3)
+#define ATAO_STATUS_INT1 (1 << 2)
+#define ATAO_STATUS_TCINT (1 << 1)
+#define ATAO_STATUS_PROMOUT (1 << 0)
+#define ATAO_FIFO_WRITE_REG 0x0c
+#define ATAO_FIFO_CLEAR_REG 0x0c
+#define ATAO_AO_REG(x) (0x0c + ((x) * 2))
+
+/* registers with _2_ are accessed when GRP2WR is set in CFG1 */
+#define ATAO_2_DMATCCLR_REG 0x00
+#define ATAO_2_INT1CLR_REG 0x02
+#define ATAO_2_INT2CLR_REG 0x04
+#define ATAO_2_RTSISHFT_REG 0x06
+#define ATAO_2_RTSISHFT_RSI (1 << 0)
+#define ATAO_2_RTSISTRB_REG 0x07
+
struct atao_board {
const char *name;
int n_ao_chans;
};
-struct atao_private {
+static const struct atao_board atao_boards[] = {
+ {
+ .name = "at-ao-6",
+ .n_ao_chans = 6,
+ }, {
+ .name = "at-ao-10",
+ .n_ao_chans = 10,
+ },
+};
+struct atao_private {
unsigned short cfg1;
- unsigned short cfg2;
unsigned short cfg3;
/* Used for AO readback */
unsigned int ao_readback[10];
+
+ /* Used for caldac readback */
+ unsigned char caldac[21];
};
-static void atao_reset(struct comedi_device *dev)
+static void atao_select_reg_group(struct comedi_device *dev, int group)
{
struct atao_private *devpriv = dev->private;
- /* This is the reset sequence described in the manual */
-
- devpriv->cfg1 = 0;
- outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
-
- outb(RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD);
- outb(0x03, dev->iobase + ATAO_82C53_CNTR1);
- outb(CNTRSEL0 | RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD);
-
- devpriv->cfg2 = 0;
- outw(devpriv->cfg2, dev->iobase + ATAO_CFG2);
-
- devpriv->cfg3 = 0;
- outw(devpriv->cfg3, dev->iobase + ATAO_CFG3);
-
- inw(dev->iobase + ATAO_FIFO_CLEAR);
-
- devpriv->cfg1 |= GRP2WR;
- outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
-
- outw(0, dev->iobase + ATAO_2_INT1CLR);
- outw(0, dev->iobase + ATAO_2_INT2CLR);
- outw(0, dev->iobase + ATAO_2_DMATCCLR);
-
- devpriv->cfg1 &= ~GRP2WR;
- outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
+ if (group)
+ devpriv->cfg1 |= ATAO_CFG1_GRP2WR;
+ else
+ devpriv->cfg1 &= ~ATAO_CFG1_GRP2WR;
+ outw(devpriv->cfg1, dev->iobase + ATAO_CFG1_REG);
}
-static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int atao_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct atao_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int val;
int i;
- int chan = CR_CHAN(insn->chanspec);
- short bits;
+
+ if (chan == 0)
+ atao_select_reg_group(dev, 1);
for (i = 0; i < insn->n; i++) {
- bits = data[i] - 0x800;
- if (chan == 0) {
- devpriv->cfg1 |= GRP2WR;
- outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
- }
- outw(bits, dev->iobase + ATAO_DACn(chan));
- if (chan == 0) {
- devpriv->cfg1 &= ~GRP2WR;
- outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
- }
- devpriv->ao_readback[chan] = data[i];
+ val = data[i];
+ devpriv->ao_readback[chan] = val;
+
+ /* munge offset binary (unsigned) to two's complement */
+ val = comedi_offset_munge(s, val);
+ outw(val, dev->iobase + ATAO_AO_REG(chan));
}
- return i;
+ if (chan == 0)
+ atao_select_reg_group(dev, 0);
+
+ return insn->n;
}
-static int atao_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int atao_ao_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct atao_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
int i;
- int chan = CR_CHAN(insn->chanspec);
for (i = 0; i < insn->n; i++)
data[i] = devpriv->ao_readback[chan];
- return i;
+ return insn->n;
}
static int atao_dio_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
if (comedi_dio_update_state(s, data))
- outw(s->state, dev->iobase + ATAO_DOUT);
+ outw(s->state, dev->iobase + ATAO_DIO_REG);
- data[1] = inw(dev->iobase + ATAO_DIN);
+ data[1] = inw(dev->iobase + ATAO_DIO_REG);
return insn->n;
}
return ret;
if (s->io_bits & 0x0f)
- devpriv->cfg3 |= DOUTEN1;
+ devpriv->cfg3 |= ATAO_CFG3_DOUTEN1;
else
- devpriv->cfg3 &= ~DOUTEN1;
+ devpriv->cfg3 &= ~ATAO_CFG3_DOUTEN1;
if (s->io_bits & 0xf0)
- devpriv->cfg3 |= DOUTEN2;
+ devpriv->cfg3 |= ATAO_CFG3_DOUTEN2;
else
- devpriv->cfg3 &= ~DOUTEN2;
+ devpriv->cfg3 &= ~ATAO_CFG3_DOUTEN2;
- outw(devpriv->cfg3, dev->iobase + ATAO_CFG3);
+ outw(devpriv->cfg3, dev->iobase + ATAO_CFG3_REG);
return insn->n;
}
/*
- * Figure 2-1 in the manual shows 3 chips labeled DAC8800, which
- * are 8-channel 8-bit DACs. These are most likely the calibration
- * DACs. It is not explicitly stated in the manual how to access
- * the caldacs, but we can guess.
+ * There are three DAC8800 TrimDACs on the board. These are 8-channel,
+ * 8-bit DACs that are used to calibrate the Analog Output channels.
+ * The factory default calibration values are stored in the EEPROM.
+ * The TrimDACs, and EEPROM addresses, are mapped as:
+ *
+ * Channel EEPROM Description
+ * ----------------- ------ -----------------------------------
+ * 0 - DAC0 Chan 0 0x30 AO Channel 0 Offset
+ * 1 - DAC0 Chan 1 0x31 AO Channel 0 Gain
+ * 2 - DAC0 Chan 2 0x32 AO Channel 1 Offset
+ * 3 - DAC0 Chan 3 0x33 AO Channel 1 Gain
+ * 4 - DAC0 Chan 4 0x34 AO Channel 2 Offset
+ * 5 - DAC0 Chan 5 0x35 AO Channel 2 Gain
+ * 6 - DAC0 Chan 6 0x36 AO Channel 3 Offset
+ * 7 - DAC0 Chan 7 0x37 AO Channel 3 Gain
+ * 8 - DAC1 Chan 0 0x38 AO Channel 4 Offset
+ * 9 - DAC1 Chan 1 0x39 AO Channel 4 Gain
+ * 10 - DAC1 Chan 2 0x3a AO Channel 5 Offset
+ * 11 - DAC1 Chan 3 0x3b AO Channel 5 Gain
+ * 12 - DAC1 Chan 4 0x3c 2.5V Offset
+ * 13 - DAC1 Chan 5 0x3d AO Channel 6 Offset (at-ao-10 only)
+ * 14 - DAC1 Chan 6 0x3e AO Channel 6 Gain (at-ao-10 only)
+ * 15 - DAC1 Chan 7 0x3f AO Channel 7 Offset (at-ao-10 only)
+ * 16 - DAC2 Chan 0 0x40 AO Channel 7 Gain (at-ao-10 only)
+ * 17 - DAC2 Chan 1 0x41 AO Channel 8 Offset (at-ao-10 only)
+ * 18 - DAC2 Chan 2 0x42 AO Channel 8 Gain (at-ao-10 only)
+ * 19 - DAC2 Chan 3 0x43 AO Channel 9 Offset (at-ao-10 only)
+ * 20 - DAC2 Chan 4 0x44 AO Channel 9 Gain (at-ao-10 only)
+ * DAC2 Chan 5 0x45 Reserved
+ * DAC2 Chan 6 0x46 Reserved
+ * DAC2 Chan 7 0x47 Reserved
*/
+static int atao_calib_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct atao_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int bitstring;
+ unsigned int val;
+ int bit;
+
+ if (insn->n == 0)
+ return 0;
+
+ devpriv->caldac[chan] = data[insn->n - 1] & s->maxdata;
+
+ /* write the channel and last data value to the caldac */
+ bitstring = ((chan & 0x7) << 8) | devpriv->caldac[chan];
+
+ /* clock the bitstring to the caldac; MSB -> LSB */
+ for (bit = 1 << 10; bit; bit >>= 1) {
+ val = (bit & bitstring) ? ATAO_CFG2_SDATA : 0;
+
+ outw(val, dev->iobase + ATAO_CFG2_REG);
+ outw(val | ATAO_CFG2_SCLK, dev->iobase + ATAO_CFG2_REG);
+ }
+
+ /* strobe the caldac to load the value */
+ outw(ATAO_CFG2_CALLD(chan), dev->iobase + ATAO_CFG2_REG);
+ outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG);
+
+ return insn->n;
+}
+
static int atao_calib_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
+ struct atao_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
int i;
+
for (i = 0; i < insn->n; i++)
- data[i] = 0; /* XXX */
+ data[i] = devpriv->caldac[chan];
+
return insn->n;
}
-static int atao_calib_insn_write(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static void atao_reset(struct comedi_device *dev)
{
struct atao_private *devpriv = dev->private;
- unsigned int bitstring, bit;
- unsigned int chan = CR_CHAN(insn->chanspec);
- bitstring = ((chan & 0x7) << 8) | (data[insn->n - 1] & 0xff);
+ /* This is the reset sequence described in the manual */
- for (bit = 1 << (11 - 1); bit; bit >>= 1) {
- outw(devpriv->cfg2 | ((bit & bitstring) ? SDATA : 0),
- dev->iobase + ATAO_CFG2);
- outw(devpriv->cfg2 | SCLK | ((bit & bitstring) ? SDATA : 0),
- dev->iobase + ATAO_CFG2);
- }
- /* strobe the appropriate caldac */
- outw(devpriv->cfg2 | (((chan >> 3) + 1) << 14),
- dev->iobase + ATAO_CFG2);
- outw(devpriv->cfg2, dev->iobase + ATAO_CFG2);
+ devpriv->cfg1 = 0;
+ outw(devpriv->cfg1, dev->iobase + ATAO_CFG1_REG);
- return insn->n;
+ /* Put outputs of counter 1 and counter 2 in a high state */
+ i8254_load(dev->iobase + ATAO_82C53_BASE, 0,
+ 0, 0x0003, I8254_MODE4 | I8254_BINARY);
+ i8254_set_mode(dev->iobase + ATAO_82C53_BASE, 0,
+ 1, I8254_MODE4 | I8254_BINARY);
+
+ outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG);
+
+ devpriv->cfg3 = 0;
+ outw(devpriv->cfg3, dev->iobase + ATAO_CFG3_REG);
+
+ inw(dev->iobase + ATAO_FIFO_CLEAR_REG);
+
+ atao_select_reg_group(dev, 1);
+ outw(0, dev->iobase + ATAO_2_INT1CLR_REG);
+ outw(0, dev->iobase + ATAO_2_INT2CLR_REG);
+ outw(0, dev->iobase + ATAO_2_DMATCCLR_REG);
+ atao_select_reg_group(dev, 0);
}
static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
const struct atao_board *board = comedi_board(dev);
struct atao_private *devpriv;
struct comedi_subdevice *s;
- int ao_unipolar;
int ret;
- ao_unipolar = it->options[3];
-
- ret = comedi_request_region(dev, it->options[0], ATAO_SIZE);
+ ret = comedi_request_region(dev, it->options[0], 0x20);
if (ret)
return ret;
if (ret)
return ret;
+ /* Analog Output subdevice */
s = &dev->subdevices[0];
- /* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = board->n_ao_chans;
- s->maxdata = (1 << 12) - 1;
- if (ao_unipolar)
- s->range_table = &range_unipolar10;
- else
- s->range_table = &range_bipolar10;
- s->insn_write = &atao_ao_winsn;
- s->insn_read = &atao_ao_rinsn;
-
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = board->n_ao_chans;
+ s->maxdata = 0x0fff;
+ s->range_table = it->options[3] ? &range_unipolar10 : &range_bipolar10;
+ s->insn_write = atao_ao_insn_write;
+ s->insn_read = atao_ao_insn_read;
+
+ /* Digital I/O subdevice */
s = &dev->subdevices[1];
- /* digital i/o subdevice */
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 8;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = atao_dio_insn_bits;
- s->insn_config = atao_dio_insn_config;
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = atao_dio_insn_bits;
+ s->insn_config = atao_dio_insn_config;
- s = &dev->subdevices[2];
/* caldac subdevice */
- s->type = COMEDI_SUBD_CALIB;
- s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
- s->n_chan = 21;
- s->maxdata = 0xff;
- s->insn_read = atao_calib_insn_read;
- s->insn_write = atao_calib_insn_write;
-
+ s = &dev->subdevices[2];
+ s->type = COMEDI_SUBD_CALIB;
+ s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
+ s->n_chan = (board->n_ao_chans * 2) + 1;
+ s->maxdata = 0xff;
+ s->insn_read = atao_calib_insn_read;
+ s->insn_write = atao_calib_insn_write;
+
+ /* EEPROM subdevice */
s = &dev->subdevices[3];
- /* eeprom subdevice */
- /* s->type=COMEDI_SUBD_EEPROM; */
- s->type = COMEDI_SUBD_UNUSED;
+ s->type = COMEDI_SUBD_UNUSED;
atao_reset(dev);
- printk(KERN_INFO "\n");
-
return 0;
}
-static const struct atao_board atao_boards[] = {
- {
- .name = "ai-ao-6",
- .n_ao_chans = 6,
- }, {
- .name = "ai-ao-10",
- .n_ao_chans = 10,
- },
-};
-
static struct comedi_driver ni_at_ao_driver = {
.driver_name = "ni_at_ao",
.module = THIS_MODULE,
module_comedi_driver(ni_at_ao_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for NI AT-AO-6/10 boards");
MODULE_LICENSE("GPL");
/* get the board structure and prep it */
brd = dgnc_Board[dgnc_NumBoards] =
- kzalloc(sizeof(struct dgnc_board), GFP_KERNEL);
+ kzalloc(sizeof(*brd), GFP_KERNEL);
if (!brd) {
APR(("memory allocation for board structure failed\n"));
return -ENOMEM;
/* make a temporary message buffer for the boot messages */
brd->msgbuf = brd->msgbuf_head =
- kzalloc(sizeof(char) * 8192, GFP_KERNEL);
+ kzalloc(sizeof(u8) * 8192, GFP_KERNEL);
if (!brd->msgbuf) {
kfree(brd);
APR(("memory allocation for board msgbuf failed\n"));
uint board = 0;
uint channel = 0;
- if (copy_from_user(&ni, uarg, sizeof(struct ni_info))) {
+ if (copy_from_user(&ni, uarg, sizeof(ni))) {
return -EFAULT;
}
DPR_INIT(("tty_register start\n"));
- memset(&brd->SerialDriver, 0, sizeof(struct tty_driver));
- memset(&brd->PrintDriver, 0, sizeof(struct tty_driver));
+ memset(&brd->SerialDriver, 0, sizeof(brd->SerialDriver));
+ memset(&brd->PrintDriver, 0, sizeof(brd->PrintDriver));
brd->SerialDriver.magic = TTY_DRIVER_MAGIC;
* The kernel wants space to store pointers to
* tty_struct's and termios's.
*/
- brd->SerialDriver.ttys = kzalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL);
+ brd->SerialDriver.ttys = kzalloc(brd->maxports * sizeof(*brd->SerialDriver.ttys), GFP_KERNEL);
if (!brd->SerialDriver.ttys)
return -ENOMEM;
kref_init(&brd->SerialDriver.kref);
- brd->SerialDriver.termios = kzalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
+ brd->SerialDriver.termios = kzalloc(brd->maxports * sizeof(*brd->SerialDriver.termios), GFP_KERNEL);
if (!brd->SerialDriver.termios)
return -ENOMEM;
* tty_struct's and termios's. Must be separated from
* the Serial Driver so we don't get confused
*/
- brd->PrintDriver.ttys = kzalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL);
+ brd->PrintDriver.ttys = kzalloc(brd->maxports * sizeof(*brd->PrintDriver.ttys), GFP_KERNEL);
if (!brd->PrintDriver.ttys)
return -ENOMEM;
kref_init(&brd->PrintDriver.kref);
- brd->PrintDriver.termios = kzalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
+ brd->PrintDriver.termios = kzalloc(brd->maxports * sizeof(*brd->PrintDriver.termios), GFP_KERNEL);
if (!brd->PrintDriver.termios)
return -ENOMEM;
* Okay to malloc with GFP_KERNEL, we are not at
* interrupt context, and there are no locks held.
*/
- brd->channels[i] = kzalloc(sizeof(struct channel_t), GFP_KERNEL);
+ brd->channels[i] = kzalloc(sizeof(*brd->channels[i]), GFP_KERNEL);
if (!brd->channels[i]) {
DPR_CORE(("%s:%d Unable to allocate memory for channel struct\n",
__FILE__, __LINE__));
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
return -EFAULT;
- if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) {
+ if (copy_from_user(&new_digi, new_info, sizeof(new_digi))) {
DPR_IOCTL(("DIGI_SETA failed copy_from_user\n"));
return -EFAULT;
}
if ((ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) && !(new_digi.digi_flags & DIGI_DTR_TOGGLE))
ch->ch_mostat |= (UART_MCR_DTR);
- memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
+ memcpy(&ch->ch_digi, &new_digi, sizeof(new_digi));
if (ch->ch_digi.digi_maxcps < 1)
ch->ch_digi.digi_maxcps = 1;
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- if (copy_to_user(uarg, &buf, sizeof(struct digi_getcounter))) {
+ if (copy_to_user(uarg, &buf, sizeof(buf))) {
return -EFAULT;
}
return 0;
/*
* Get data from user first.
*/
- if (copy_from_user(&buf, uarg, sizeof(struct digi_getbuffer))) {
+ if (copy_from_user(&buf, uarg, sizeof(buf))) {
return -EFAULT;
}
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- if (copy_to_user(uarg, &buf, sizeof(struct digi_getbuffer))) {
+ if (copy_to_user(uarg, &buf, sizeof(buf))) {
return -EFAULT;
}
return 0;
unsigned dev_token_q_depth:5;
unsigned max_transfer_size:26;
unsigned max_packet_count:11;
- unsigned host_channels:4;
+ unsigned host_channels:5;
unsigned hs_phy_type:2;
unsigned fs_phy_type:2;
unsigned i2c_enable:1;
OBD_ALLOC_LARGE(*pages, *max_pages * sizeof(**pages));
if (*pages) {
- down_read(¤t->mm->mmap_sem);
- result = get_user_pages(current, current->mm, user_addr,
- *max_pages, (rw == READ), 0, *pages,
- NULL);
- up_read(¤t->mm->mmap_sem);
+ result = get_user_pages_fast(user_addr, *max_pages,
+ (rw == READ), *pages);
if (unlikely(result <= 0))
OBD_FREE_LARGE(*pages, *max_pages * sizeof(**pages));
}
--- /dev/null
+config MTD_SPINAND_MT29F
+ tristate "SPINAND Device Support for Micron"
+ depends on MTD_NAND && SPI
+ help
+ This enables support for accessing Micron SPI NAND flash
+ devices.
+ If you have Micron SPI NAND chip say yes.
+
+ If unsure, say no here.
+
+config MTD_SPINAND_ONDIEECC
+ bool "Use SPINAND internal ECC"
+ depends on MTD_SPINAND_MT29F
+ help
+ Internel ECC.
+ Enables Hardware ECC support for Micron SPI NAND.
--- /dev/null
+obj-$(CONFIG_MTD_SPINAND_MT29F) += mt29f_spinand.o
--- /dev/null
+TODO:
+ - Tested on XLP platform, needs to be tested on other platforms.
+ - Checkpatch.pl cleanups
+ - Sparce fixes.
+ - Clean up coding style to meet kernel standard.
+
+Please send patches
+To:
+Kamlakant Patel <kamlakant.patel@broadcom.com>
+Cc:
+Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Mona Anonuevo <manonuevo@micron.com>
+linux-mtd@lists.infradead.org
--- /dev/null
+/*
+ * Copyright (c) 2003-2013 Broadcom Corporation
+ *
+ * Copyright (c) 2009-2010 Micron Technology, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+#include <linux/spi/spi.h>
+
+#include "mt29f_spinand.h"
+
+#define BUFSIZE (10 * 64 * 2048)
+#define CACHE_BUF 2112
+/*
+ * OOB area specification layout: Total 32 available free bytes.
+ */
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+static int enable_hw_ecc;
+static int enable_read_hw_ecc;
+
+static inline struct spinand_state *mtd_to_state(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = (struct nand_chip *)mtd->priv;
+ struct spinand_info *info = (struct spinand_info *)chip->priv;
+ struct spinand_state *state = (struct spinand_state *)info->priv;
+
+ return state;
+}
+
+static struct nand_ecclayout spinand_oob_64 = {
+ .eccbytes = 24,
+ .eccpos = {
+ 1, 2, 3, 4, 5, 6,
+ 17, 18, 19, 20, 21, 22,
+ 33, 34, 35, 36, 37, 38,
+ 49, 50, 51, 52, 53, 54, },
+ .oobavail = 32,
+ .oobfree = {
+ {.offset = 8,
+ .length = 8},
+ {.offset = 24,
+ .length = 8},
+ {.offset = 40,
+ .length = 8},
+ {.offset = 56,
+ .length = 8},
+ }
+};
+#endif
+
+/*
+ * spinand_cmd - to process a command to send to the SPI Nand
+ * Description:
+ * Set up the command buffer to send to the SPI controller.
+ * The command buffer has to initialized to 0.
+ */
+
+static int spinand_cmd(struct spi_device *spi, struct spinand_cmd *cmd)
+{
+ struct spi_message message;
+ struct spi_transfer x[4];
+ u8 dummy = 0xff;
+
+ spi_message_init(&message);
+ memset(x, 0, sizeof(x));
+
+ x[0].len = 1;
+ x[0].tx_buf = &cmd->cmd;
+ spi_message_add_tail(&x[0], &message);
+
+ if (cmd->n_addr) {
+ x[1].len = cmd->n_addr;
+ x[1].tx_buf = cmd->addr;
+ spi_message_add_tail(&x[1], &message);
+ }
+
+ if (cmd->n_dummy) {
+ x[2].len = cmd->n_dummy;
+ x[2].tx_buf = &dummy;
+ spi_message_add_tail(&x[2], &message);
+ }
+
+ if (cmd->n_tx) {
+ x[3].len = cmd->n_tx;
+ x[3].tx_buf = cmd->tx_buf;
+ spi_message_add_tail(&x[3], &message);
+ }
+
+ if (cmd->n_rx) {
+ x[3].len = cmd->n_rx;
+ x[3].rx_buf = cmd->rx_buf;
+ spi_message_add_tail(&x[3], &message);
+ }
+
+ return spi_sync(spi, &message);
+}
+
+/*
+ * spinand_read_id- Read SPI Nand ID
+ * Description:
+ * Read ID: read two ID bytes from the SPI Nand device
+ */
+static int spinand_read_id(struct spi_device *spi_nand, u8 *id)
+{
+ int retval;
+ u8 nand_id[3];
+ struct spinand_cmd cmd = {0};
+
+ cmd.cmd = CMD_READ_ID;
+ cmd.n_rx = 3;
+ cmd.rx_buf = &nand_id[0];
+
+ retval = spinand_cmd(spi_nand, &cmd);
+ if (retval < 0) {
+ dev_err(&spi_nand->dev, "error %d reading id\n", retval);
+ return retval;
+ }
+ id[0] = nand_id[1];
+ id[1] = nand_id[2];
+ return retval;
+}
+
+/*
+ * spinand_read_status- send command 0xf to the SPI Nand status register
+ * Description:
+ * After read, write, or erase, the Nand device is expected to set the
+ * busy status.
+ * This function is to allow reading the status of the command: read,
+ * write, and erase.
+ * Once the status turns to be ready, the other status bits also are
+ * valid status bits.
+ */
+static int spinand_read_status(struct spi_device *spi_nand, uint8_t *status)
+{
+ struct spinand_cmd cmd = {0};
+ int ret;
+
+ cmd.cmd = CMD_READ_REG;
+ cmd.n_addr = 1;
+ cmd.addr[0] = REG_STATUS;
+ cmd.n_rx = 1;
+ cmd.rx_buf = status;
+
+ ret = spinand_cmd(spi_nand, &cmd);
+ if (ret < 0)
+ dev_err(&spi_nand->dev, "err: %d read status register\n", ret);
+
+ return ret;
+}
+
+#define MAX_WAIT_JIFFIES (40 * HZ)
+static int wait_till_ready(struct spi_device *spi_nand)
+{
+ unsigned long deadline;
+ int retval;
+ u8 stat = 0;
+
+ deadline = jiffies + MAX_WAIT_JIFFIES;
+ do {
+ retval = spinand_read_status(spi_nand, &stat);
+ if (retval < 0)
+ return -1;
+ else if (!(stat & 0x1))
+ break;
+
+ cond_resched();
+ } while (!time_after_eq(jiffies, deadline));
+
+ if ((stat & 0x1) == 0)
+ return 0;
+
+ return -1;
+}
+/**
+ * spinand_get_otp- send command 0xf to read the SPI Nand OTP register
+ * Description:
+ * There is one bit( bit 0x10 ) to set or to clear the internal ECC.
+ * Enable chip internal ECC, set the bit to 1
+ * Disable chip internal ECC, clear the bit to 0
+ */
+static int spinand_get_otp(struct spi_device *spi_nand, u8 *otp)
+{
+ struct spinand_cmd cmd = {0};
+ int retval;
+
+ cmd.cmd = CMD_READ_REG;
+ cmd.n_addr = 1;
+ cmd.addr[0] = REG_OTP;
+ cmd.n_rx = 1;
+ cmd.rx_buf = otp;
+
+ retval = spinand_cmd(spi_nand, &cmd);
+ if (retval < 0)
+ dev_err(&spi_nand->dev, "error %d get otp\n", retval);
+ return retval;
+}
+
+/**
+ * spinand_set_otp- send command 0x1f to write the SPI Nand OTP register
+ * Description:
+ * There is one bit( bit 0x10 ) to set or to clear the internal ECC.
+ * Enable chip internal ECC, set the bit to 1
+ * Disable chip internal ECC, clear the bit to 0
+ */
+static int spinand_set_otp(struct spi_device *spi_nand, u8 *otp)
+{
+ int retval;
+ struct spinand_cmd cmd = {0};
+
+ cmd.cmd = CMD_WRITE_REG,
+ cmd.n_addr = 1,
+ cmd.addr[0] = REG_OTP,
+ cmd.n_tx = 1,
+ cmd.tx_buf = otp,
+
+ retval = spinand_cmd(spi_nand, &cmd);
+ if (retval < 0)
+ dev_err(&spi_nand->dev, "error %d set otp\n", retval);
+
+ return retval;
+}
+
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+/**
+ * spinand_enable_ecc- send command 0x1f to write the SPI Nand OTP register
+ * Description:
+ * There is one bit( bit 0x10 ) to set or to clear the internal ECC.
+ * Enable chip internal ECC, set the bit to 1
+ * Disable chip internal ECC, clear the bit to 0
+ */
+static int spinand_enable_ecc(struct spi_device *spi_nand)
+{
+ int retval;
+ u8 otp = 0;
+
+ retval = spinand_get_otp(spi_nand, &otp);
+ if (retval < 0)
+ return retval;
+
+ if ((otp & OTP_ECC_MASK) == OTP_ECC_MASK) {
+ return 0;
+ } else {
+ otp |= OTP_ECC_MASK;
+ retval = spinand_set_otp(spi_nand, &otp);
+ if (retval < 0)
+ return retval;
+ return spinand_get_otp(spi_nand, &otp);
+ }
+}
+#endif
+
+static int spinand_disable_ecc(struct spi_device *spi_nand)
+{
+ int retval;
+ u8 otp = 0;
+
+ retval = spinand_get_otp(spi_nand, &otp);
+ if (retval < 0)
+ return retval;
+
+ if ((otp & OTP_ECC_MASK) == OTP_ECC_MASK) {
+ otp &= ~OTP_ECC_MASK;
+ retval = spinand_set_otp(spi_nand, &otp);
+ if (retval < 0)
+ return retval;
+ return spinand_get_otp(spi_nand, &otp);
+ } else
+ return 0;
+}
+
+/**
+ * spinand_write_enable- send command 0x06 to enable write or erase the
+ * Nand cells
+ * Description:
+ * Before write and erase the Nand cells, the write enable has to be set.
+ * After the write or erase, the write enable bit is automatically
+ * cleared (status register bit 2)
+ * Set the bit 2 of the status register has the same effect
+ */
+static int spinand_write_enable(struct spi_device *spi_nand)
+{
+ struct spinand_cmd cmd = {0};
+
+ cmd.cmd = CMD_WR_ENABLE;
+ return spinand_cmd(spi_nand, &cmd);
+}
+
+static int spinand_read_page_to_cache(struct spi_device *spi_nand, u16 page_id)
+{
+ struct spinand_cmd cmd = {0};
+ u16 row;
+
+ row = page_id;
+ cmd.cmd = CMD_READ;
+ cmd.n_addr = 3;
+ cmd.addr[1] = (u8)((row & 0xff00) >> 8);
+ cmd.addr[2] = (u8)(row & 0x00ff);
+
+ return spinand_cmd(spi_nand, &cmd);
+}
+
+/*
+ * spinand_read_from_cache- send command 0x03 to read out the data from the
+ * cache register(2112 bytes max)
+ * Description:
+ * The read can specify 1 to 2112 bytes of data read at the corresponding
+ * locations.
+ * No tRd delay.
+ */
+static int spinand_read_from_cache(struct spi_device *spi_nand, u16 page_id,
+ u16 byte_id, u16 len, u8 *rbuf)
+{
+ struct spinand_cmd cmd = {0};
+ u16 column;
+
+ column = byte_id;
+ cmd.cmd = CMD_READ_RDM;
+ cmd.n_addr = 3;
+ cmd.addr[0] = (u8)((column & 0xff00) >> 8);
+ cmd.addr[0] |= (u8)(((page_id >> 6) & 0x1) << 4);
+ cmd.addr[1] = (u8)(column & 0x00ff);
+ cmd.addr[2] = (u8)(0xff);
+ cmd.n_dummy = 0;
+ cmd.n_rx = len;
+ cmd.rx_buf = rbuf;
+
+ return spinand_cmd(spi_nand, &cmd);
+}
+
+/*
+ * spinand_read_page-to read a page with:
+ * @page_id: the physical page number
+ * @offset: the location from 0 to 2111
+ * @len: number of bytes to read
+ * @rbuf: read buffer to hold @len bytes
+ *
+ * Description:
+ * The read includes two commands to the Nand: 0x13 and 0x03 commands
+ * Poll to read status to wait for tRD time.
+ */
+static int spinand_read_page(struct spi_device *spi_nand, u16 page_id,
+ u16 offset, u16 len, u8 *rbuf)
+{
+ int ret;
+ u8 status = 0;
+
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+ if (enable_read_hw_ecc) {
+ if (spinand_enable_ecc(spi_nand) < 0)
+ dev_err(&spi_nand->dev, "enable HW ECC failed!");
+ }
+#endif
+ ret = spinand_read_page_to_cache(spi_nand, page_id);
+ if (ret < 0)
+ return ret;
+
+ if (wait_till_ready(spi_nand))
+ dev_err(&spi_nand->dev, "WAIT timedout!!!\n");
+
+ while (1) {
+ ret = spinand_read_status(spi_nand, &status);
+ if (ret < 0) {
+ dev_err(&spi_nand->dev,
+ "err %d read status register\n", ret);
+ return ret;
+ }
+
+ if ((status & STATUS_OIP_MASK) == STATUS_READY) {
+ if ((status & STATUS_ECC_MASK) == STATUS_ECC_ERROR) {
+ dev_err(&spi_nand->dev, "ecc error, page=%d\n",
+ page_id);
+ return 0;
+ }
+ break;
+ }
+ }
+
+ ret = spinand_read_from_cache(spi_nand, page_id, offset, len, rbuf);
+ if (ret < 0) {
+ dev_err(&spi_nand->dev, "read from cache failed!!\n");
+ return ret;
+ }
+
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+ if (enable_read_hw_ecc) {
+ ret = spinand_disable_ecc(spi_nand);
+ if (ret < 0) {
+ dev_err(&spi_nand->dev, "disable ecc failed!!\n");
+ return ret;
+ }
+ enable_read_hw_ecc = 0;
+ }
+#endif
+ return ret;
+}
+
+/*
+ * spinand_program_data_to_cache--to write a page to cache with:
+ * @byte_id: the location to write to the cache
+ * @len: number of bytes to write
+ * @rbuf: read buffer to hold @len bytes
+ *
+ * Description:
+ * The write command used here is 0x84--indicating that the cache is
+ * not cleared first.
+ * Since it is writing the data to cache, there is no tPROG time.
+ */
+static int spinand_program_data_to_cache(struct spi_device *spi_nand,
+ u16 page_id, u16 byte_id, u16 len, u8 *wbuf)
+{
+ struct spinand_cmd cmd = {0};
+ u16 column;
+
+ column = byte_id;
+ cmd.cmd = CMD_PROG_PAGE_CLRCACHE;
+ cmd.n_addr = 2;
+ cmd.addr[0] = (u8)((column & 0xff00) >> 8);
+ cmd.addr[0] |= (u8)(((page_id >> 6) & 0x1) << 4);
+ cmd.addr[1] = (u8)(column & 0x00ff);
+ cmd.n_tx = len;
+ cmd.tx_buf = wbuf;
+
+ return spinand_cmd(spi_nand, &cmd);
+}
+
+/**
+ * spinand_program_execute--to write a page from cache to the Nand array with
+ * @page_id: the physical page location to write the page.
+ *
+ * Description:
+ * The write command used here is 0x10--indicating the cache is writing to
+ * the Nand array.
+ * Need to wait for tPROG time to finish the transaction.
+ */
+static int spinand_program_execute(struct spi_device *spi_nand, u16 page_id)
+{
+ struct spinand_cmd cmd = {0};
+ u16 row;
+
+ row = page_id;
+ cmd.cmd = CMD_PROG_PAGE_EXC;
+ cmd.n_addr = 3;
+ cmd.addr[1] = (u8)((row & 0xff00) >> 8);
+ cmd.addr[2] = (u8)(row & 0x00ff);
+
+ return spinand_cmd(spi_nand, &cmd);
+}
+
+/**
+ * spinand_program_page--to write a page with:
+ * @page_id: the physical page location to write the page.
+ * @offset: the location from the cache starting from 0 to 2111
+ * @len: the number of bytes to write
+ * @wbuf: the buffer to hold the number of bytes
+ *
+ * Description:
+ * The commands used here are 0x06, 0x84, and 0x10--indicating that
+ * the write enable is first sent, the write cache command, and the
+ * write execute command.
+ * Poll to wait for the tPROG time to finish the transaction.
+ */
+static int spinand_program_page(struct spi_device *spi_nand,
+ u16 page_id, u16 offset, u16 len, u8 *buf)
+{
+ int retval;
+ u8 status = 0;
+ uint8_t *wbuf;
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+ unsigned int i, j;
+
+ enable_read_hw_ecc = 0;
+ wbuf = devm_kzalloc(&spi_nand->dev, CACHE_BUF, GFP_KERNEL);
+ spinand_read_page(spi_nand, page_id, 0, CACHE_BUF, wbuf);
+
+ for (i = offset, j = 0; i < len; i++, j++)
+ wbuf[i] &= buf[j];
+
+ if (enable_hw_ecc) {
+ retval = spinand_enable_ecc(spi_nand);
+ if (retval < 0) {
+ dev_err(&spi_nand->dev, "enable ecc failed!!\n");
+ return retval;
+ }
+ }
+#else
+ wbuf = buf;
+#endif
+ retval = spinand_write_enable(spi_nand);
+ if (retval < 0) {
+ dev_err(&spi_nand->dev, "write enable failed!!\n");
+ return retval;
+ }
+ if (wait_till_ready(spi_nand))
+ dev_err(&spi_nand->dev, "wait timedout!!!\n");
+
+ retval = spinand_program_data_to_cache(spi_nand, page_id,
+ offset, len, wbuf);
+ if (retval < 0)
+ return retval;
+ retval = spinand_program_execute(spi_nand, page_id);
+ if (retval < 0)
+ return retval;
+ while (1) {
+ retval = spinand_read_status(spi_nand, &status);
+ if (retval < 0) {
+ dev_err(&spi_nand->dev,
+ "error %d reading status register\n",
+ retval);
+ return retval;
+ }
+
+ if ((status & STATUS_OIP_MASK) == STATUS_READY) {
+ if ((status & STATUS_P_FAIL_MASK) == STATUS_P_FAIL) {
+ dev_err(&spi_nand->dev,
+ "program error, page %d\n", page_id);
+ return -1;
+ } else
+ break;
+ }
+ }
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+ if (enable_hw_ecc) {
+ retval = spinand_disable_ecc(spi_nand);
+ if (retval < 0) {
+ dev_err(&spi_nand->dev, "disable ecc failed!!\n");
+ return retval;
+ }
+ enable_hw_ecc = 0;
+ }
+#endif
+
+ return 0;
+}
+
+/**
+ * spinand_erase_block_erase--to erase a page with:
+ * @block_id: the physical block location to erase.
+ *
+ * Description:
+ * The command used here is 0xd8--indicating an erase command to erase
+ * one block--64 pages
+ * Need to wait for tERS.
+ */
+static int spinand_erase_block_erase(struct spi_device *spi_nand, u16 block_id)
+{
+ struct spinand_cmd cmd = {0};
+ u16 row;
+
+ row = block_id;
+ cmd.cmd = CMD_ERASE_BLK;
+ cmd.n_addr = 3;
+ cmd.addr[1] = (u8)((row & 0xff00) >> 8);
+ cmd.addr[2] = (u8)(row & 0x00ff);
+
+ return spinand_cmd(spi_nand, &cmd);
+}
+
+/**
+ * spinand_erase_block--to erase a page with:
+ * @block_id: the physical block location to erase.
+ *
+ * Description:
+ * The commands used here are 0x06 and 0xd8--indicating an erase
+ * command to erase one block--64 pages
+ * It will first to enable the write enable bit (0x06 command),
+ * and then send the 0xd8 erase command
+ * Poll to wait for the tERS time to complete the tranaction.
+ */
+static int spinand_erase_block(struct spi_device *spi_nand, u16 block_id)
+{
+ int retval;
+ u8 status = 0;
+
+ retval = spinand_write_enable(spi_nand);
+ if (wait_till_ready(spi_nand))
+ dev_err(&spi_nand->dev, "wait timedout!!!\n");
+
+ retval = spinand_erase_block_erase(spi_nand, block_id);
+ while (1) {
+ retval = spinand_read_status(spi_nand, &status);
+ if (retval < 0) {
+ dev_err(&spi_nand->dev,
+ "error %d reading status register\n",
+ (int) retval);
+ return retval;
+ }
+
+ if ((status & STATUS_OIP_MASK) == STATUS_READY) {
+ if ((status & STATUS_E_FAIL_MASK) == STATUS_E_FAIL) {
+ dev_err(&spi_nand->dev,
+ "erase error, block %d\n", block_id);
+ return -1;
+ } else
+ break;
+ }
+ }
+ return 0;
+}
+
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+static int spinand_write_page_hwecc(struct mtd_info *mtd,
+ struct nand_chip *chip, const uint8_t *buf, int oob_required)
+{
+ const uint8_t *p = buf;
+ int eccsize = chip->ecc.size;
+ int eccsteps = chip->ecc.steps;
+
+ enable_hw_ecc = 1;
+ chip->write_buf(mtd, p, eccsize * eccsteps);
+ return 0;
+}
+
+static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required, int page)
+{
+ u8 retval, status;
+ uint8_t *p = buf;
+ int eccsize = chip->ecc.size;
+ int eccsteps = chip->ecc.steps;
+ struct spinand_info *info = (struct spinand_info *)chip->priv;
+
+ enable_read_hw_ecc = 1;
+
+ chip->read_buf(mtd, p, eccsize * eccsteps);
+ if (oob_required)
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+ while (1) {
+ retval = spinand_read_status(info->spi, &status);
+ if ((status & STATUS_OIP_MASK) == STATUS_READY) {
+ if ((status & STATUS_ECC_MASK) == STATUS_ECC_ERROR) {
+ pr_info("spinand: ECC error\n");
+ mtd->ecc_stats.failed++;
+ } else if ((status & STATUS_ECC_MASK) ==
+ STATUS_ECC_1BIT_CORRECTED)
+ mtd->ecc_stats.corrected++;
+ break;
+ }
+ }
+ return 0;
+
+}
+#endif
+
+static void spinand_select_chip(struct mtd_info *mtd, int dev)
+{
+}
+
+static uint8_t spinand_read_byte(struct mtd_info *mtd)
+{
+ struct spinand_state *state = mtd_to_state(mtd);
+ u8 data;
+
+ data = state->buf[state->buf_ptr];
+ state->buf_ptr++;
+ return data;
+}
+
+
+static int spinand_wait(struct mtd_info *mtd, struct nand_chip *chip)
+{
+ struct spinand_info *info = (struct spinand_info *)chip->priv;
+
+ unsigned long timeo = jiffies;
+ int retval, state = chip->state;
+ u8 status;
+
+ if (state == FL_ERASING)
+ timeo += (HZ * 400) / 1000;
+ else
+ timeo += (HZ * 20) / 1000;
+
+ while (time_before(jiffies, timeo)) {
+ retval = spinand_read_status(info->spi, &status);
+ if ((status & STATUS_OIP_MASK) == STATUS_READY)
+ return 0;
+
+ cond_resched();
+ }
+ return 0;
+}
+
+static void spinand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+
+ struct spinand_state *state = mtd_to_state(mtd);
+ memcpy(state->buf + state->buf_ptr, buf, len);
+ state->buf_ptr += len;
+}
+
+static void spinand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+ struct spinand_state *state = mtd_to_state(mtd);
+ memcpy(buf, state->buf + state->buf_ptr, len);
+ state->buf_ptr += len;
+}
+
+/*
+ * spinand_reset- send RESET command "0xff" to the Nand device.
+ */
+static void spinand_reset(struct spi_device *spi_nand)
+{
+ struct spinand_cmd cmd = {0};
+
+ cmd.cmd = CMD_RESET;
+
+ if (spinand_cmd(spi_nand, &cmd) < 0)
+ pr_info("spinand reset failed!\n");
+
+ /* elapse 1ms before issuing any other command */
+ udelay(1000);
+
+ if (wait_till_ready(spi_nand))
+ dev_err(&spi_nand->dev, "wait timedout!\n");
+}
+
+static void spinand_cmdfunc(struct mtd_info *mtd, unsigned int command,
+ int column, int page)
+{
+ struct nand_chip *chip = (struct nand_chip *)mtd->priv;
+ struct spinand_info *info = (struct spinand_info *)chip->priv;
+ struct spinand_state *state = (struct spinand_state *)info->priv;
+
+ switch (command) {
+ /*
+ * READ0 - read in first 0x800 bytes
+ */
+ case NAND_CMD_READ1:
+ case NAND_CMD_READ0:
+ state->buf_ptr = 0;
+ spinand_read_page(info->spi, page, 0x0, 0x840, state->buf);
+ break;
+ /* READOOB reads only the OOB because no ECC is performed. */
+ case NAND_CMD_READOOB:
+ state->buf_ptr = 0;
+ spinand_read_page(info->spi, page, 0x800, 0x40, state->buf);
+ break;
+ case NAND_CMD_RNDOUT:
+ state->buf_ptr = column;
+ break;
+ case NAND_CMD_READID:
+ state->buf_ptr = 0;
+ spinand_read_id(info->spi, (u8 *)state->buf);
+ break;
+ case NAND_CMD_PARAM:
+ state->buf_ptr = 0;
+ break;
+ /* ERASE1 stores the block and page address */
+ case NAND_CMD_ERASE1:
+ spinand_erase_block(info->spi, page);
+ break;
+ /* ERASE2 uses the block and page address from ERASE1 */
+ case NAND_CMD_ERASE2:
+ break;
+ /* SEQIN sets up the addr buffer and all registers except the length */
+ case NAND_CMD_SEQIN:
+ state->col = column;
+ state->row = page;
+ state->buf_ptr = 0;
+ break;
+ /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
+ case NAND_CMD_PAGEPROG:
+ spinand_program_page(info->spi, state->row, state->col,
+ state->buf_ptr, state->buf);
+ break;
+ case NAND_CMD_STATUS:
+ spinand_get_otp(info->spi, state->buf);
+ if (!(state->buf[0] & 0x80))
+ state->buf[0] = 0x80;
+ state->buf_ptr = 0;
+ break;
+ /* RESET command */
+ case NAND_CMD_RESET:
+ if (wait_till_ready(info->spi))
+ dev_err(&info->spi->dev, "WAIT timedout!!!\n");
+ /* a minimum of 250us must elapse before issuing RESET cmd*/
+ udelay(250);
+ spinand_reset(info->spi);
+ break;
+ default:
+ dev_err(&mtd->dev, "Unknown CMD: 0x%x\n", command);
+ }
+}
+
+/**
+ * spinand_lock_block- send write register 0x1f command to the Nand device
+ *
+ * Description:
+ * After power up, all the Nand blocks are locked. This function allows
+ * one to unlock the blocks, and so it can be written or erased.
+ */
+static int spinand_lock_block(struct spi_device *spi_nand, u8 lock)
+{
+ struct spinand_cmd cmd = {0};
+ int ret;
+ u8 otp = 0;
+
+ ret = spinand_get_otp(spi_nand, &otp);
+
+ cmd.cmd = CMD_WRITE_REG;
+ cmd.n_addr = 1;
+ cmd.addr[0] = REG_BLOCK_LOCK;
+ cmd.n_tx = 1;
+ cmd.tx_buf = &lock;
+
+ ret = spinand_cmd(spi_nand, &cmd);
+ if (ret < 0)
+ dev_err(&spi_nand->dev, "error %d lock block\n", ret);
+
+ return ret;
+}
+/*
+ * spinand_probe - [spinand Interface]
+ * @spi_nand: registered device driver.
+ *
+ * Description:
+ * To set up the device driver parameters to make the device available.
+ */
+static int spinand_probe(struct spi_device *spi_nand)
+{
+ struct mtd_info *mtd;
+ struct nand_chip *chip;
+ struct spinand_info *info;
+ struct spinand_state *state;
+ struct mtd_part_parser_data ppdata;
+
+ info = devm_kzalloc(&spi_nand->dev, sizeof(struct spinand_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->spi = spi_nand;
+
+ spinand_lock_block(spi_nand, BL_ALL_UNLOCKED);
+
+ state = devm_kzalloc(&spi_nand->dev, sizeof(struct spinand_state),
+ GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ info->priv = state;
+ state->buf_ptr = 0;
+ state->buf = devm_kzalloc(&spi_nand->dev, BUFSIZE, GFP_KERNEL);
+ if (!state->buf)
+ return -ENOMEM;
+
+ chip = devm_kzalloc(&spi_nand->dev, sizeof(struct nand_chip),
+ GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+ chip->ecc.mode = NAND_ECC_HW;
+ chip->ecc.size = 0x200;
+ chip->ecc.bytes = 0x6;
+ chip->ecc.steps = 0x4;
+
+ chip->ecc.strength = 1;
+ chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
+ chip->ecc.layout = &spinand_oob_64;
+ chip->ecc.read_page = spinand_read_page_hwecc;
+ chip->ecc.write_page = spinand_write_page_hwecc;
+#else
+ chip->ecc.mode = NAND_ECC_SOFT;
+ if (spinand_disable_ecc(spi_nand) < 0)
+ pr_info("%s: disable ecc failed!\n", __func__);
+#endif
+
+ chip->priv = info;
+ chip->read_buf = spinand_read_buf;
+ chip->write_buf = spinand_write_buf;
+ chip->read_byte = spinand_read_byte;
+ chip->cmdfunc = spinand_cmdfunc;
+ chip->waitfunc = spinand_wait;
+ chip->options |= NAND_CACHEPRG;
+ chip->select_chip = spinand_select_chip;
+
+ mtd = devm_kzalloc(&spi_nand->dev, sizeof(struct mtd_info), GFP_KERNEL);
+ if (!mtd)
+ return -ENOMEM;
+
+ dev_set_drvdata(&spi_nand->dev, mtd);
+
+ mtd->priv = chip;
+ mtd->name = dev_name(&spi_nand->dev);
+ mtd->owner = THIS_MODULE;
+ mtd->oobsize = 64;
+
+ if (nand_scan(mtd, 1))
+ return -ENXIO;
+
+ ppdata.of_node = spi_nand->dev.of_node;
+ return mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
+}
+
+/*
+ * spinand_remove: Remove the device driver
+ * @spi: the spi device.
+ *
+ * Description:
+ * To remove the device driver parameters and free up allocated memories.
+ */
+static int spinand_remove(struct spi_device *spi)
+{
+ mtd_device_unregister(dev_get_drvdata(&spi->dev));
+
+ return 0;
+}
+
+static const struct of_device_id spinand_dt[] = {
+ { .compatible = "spinand,mt29f", },
+};
+
+/*
+ * Device name structure description
+ */
+static struct spi_driver spinand_driver = {
+ .driver = {
+ .name = "mt29f",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ .of_match_table = spinand_dt,
+ },
+ .probe = spinand_probe,
+ .remove = spinand_remove,
+};
+
+/*
+ * Device driver registration
+ */
+static int __init spinand_init(void)
+{
+ return spi_register_driver(&spinand_driver);
+}
+
+/*
+ * unregister Device driver.
+ */
+static void __exit spinand_exit(void)
+{
+ spi_unregister_driver(&spinand_driver);
+}
+module_init(spinand_init);
+module_exit(spinand_exit);
+
+MODULE_DESCRIPTION("SPI NAND driver for Micron");
+MODULE_AUTHOR("Henry Pan <hspan@micron.com>, Kamlakant Patel <kamlakant.patel@broadcom.com>");
+MODULE_LICENSE("GPL v2");
--- /dev/null
+/*-
+ * Copyright 2013 Broadcom Corporation
+ *
+ * Copyright (c) 2009-2010 Micron Technology, 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.
+ *
+ * Henry Pan <hspan@micron.com>
+ *
+ * based on nand.h
+ */
+#ifndef __LINUX_MTD_SPI_NAND_H
+#define __LINUX_MTD_SPI_NAND_H
+
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/mtd/mtd.h>
+
+/* cmd */
+#define CMD_READ 0x13
+#define CMD_READ_RDM 0x03
+#define CMD_PROG_PAGE_CLRCACHE 0x02
+#define CMD_PROG_PAGE 0x84
+#define CMD_PROG_PAGE_EXC 0x10
+#define CMD_ERASE_BLK 0xd8
+#define CMD_WR_ENABLE 0x06
+#define CMD_WR_DISABLE 0x04
+#define CMD_READ_ID 0x9f
+#define CMD_RESET 0xff
+#define CMD_READ_REG 0x0f
+#define CMD_WRITE_REG 0x1f
+
+/* feature/ status reg */
+#define REG_BLOCK_LOCK 0xa0
+#define REG_OTP 0xb0
+#define REG_STATUS 0xc0/* timing */
+
+/* status */
+#define STATUS_OIP_MASK 0x01
+#define STATUS_READY (0 << 0)
+#define STATUS_BUSY (1 << 0)
+
+#define STATUS_E_FAIL_MASK 0x04
+#define STATUS_E_FAIL (1 << 2)
+
+#define STATUS_P_FAIL_MASK 0x08
+#define STATUS_P_FAIL (1 << 3)
+
+#define STATUS_ECC_MASK 0x30
+#define STATUS_ECC_1BIT_CORRECTED (1 << 4)
+#define STATUS_ECC_ERROR (2 << 4)
+#define STATUS_ECC_RESERVED (3 << 4)
+
+/*ECC enable defines*/
+#define OTP_ECC_MASK 0x10
+#define OTP_ECC_OFF 0
+#define OTP_ECC_ON 1
+
+#define ECC_DISABLED
+#define ECC_IN_NAND
+#define ECC_SOFT
+
+/* block lock */
+#define BL_ALL_LOCKED 0x38
+#define BL_1_2_LOCKED 0x30
+#define BL_1_4_LOCKED 0x28
+#define BL_1_8_LOCKED 0x20
+#define BL_1_16_LOCKED 0x18
+#define BL_1_32_LOCKED 0x10
+#define BL_1_64_LOCKED 0x08
+#define BL_ALL_UNLOCKED 0
+
+struct spinand_info {
+ struct nand_ecclayout *ecclayout;
+ struct spi_device *spi;
+ void *priv;
+};
+
+struct spinand_state {
+ uint32_t col;
+ uint32_t row;
+ int buf_ptr;
+ u8 *buf;
+};
+
+struct spinand_cmd {
+ u8 cmd;
+ u32 n_addr; /* Number of address */
+ u8 addr[3]; /* Reg Offset */
+ u32 n_dummy; /* Dummy use */
+ u32 n_tx; /* Number of tx bytes */
+ u8 *tx_buf; /* Tx buf */
+ u32 n_rx; /* Number of rx bytes */
+ u8 *rx_buf; /* Rx buf */
+};
+
+extern int spinand_mtd(struct mtd_info *mtd);
+extern void spinand_mtd_release(struct mtd_info *mtd);
+
+#endif /* __LINUX_MTD_SPI_NAND_H */
unmute_speakers[] = { NVEC_OEM0, 0x10, 0x59, 0x95 },
enable_event[7] = { NVEC_SYS, CNF_EVENT_REPORTING, true };
- if(!pdev->dev.of_node) {
+ if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "must be instantiated using device tree\n");
return -ENODEV;
}
* derived from this software without specific prior written
* permission.
- * This Software, including technical data, may be subject to U.S. export control
- * laws, including the U.S. Export Administration Act and its associated
+ * This Software, including technical data, may be subject to U.S. export
+ * control laws, including the U.S. Export Administration Act and its associated
* regulations, and may be subject to export or import regulations in other
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
+ * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
- * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
- * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
+ * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION
+ * OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
* SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
* MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
* VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
#include <asm/octeon/cvmx-helper.h>
#include <asm/octeon/cvmx-helper-board.h>
-#define CVMX_PREFETCH0(address) CVMX_PREFETCH(address, 0)
-#define CVMX_PREFETCH128(address) CVMX_PREFETCH(address, 128)
-// a normal prefetch
-#define CVMX_PREFETCH(address, offset) CVMX_PREFETCH_PREF0(address, offset)
-// normal prefetches that use the pref instruction
-#define CVMX_PREFETCH_PREFX(X, address, offset) asm volatile ("pref %[type], %[off](%[rbase])" : : [rbase] "d" (address), [off] "I" (offset), [type] "n" (X))
-#define CVMX_PREFETCH_PREF0(address, offset) CVMX_PREFETCH_PREFX(0, address, offset)
-#define CVMX_CLZ(result, input) asm ("clz %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input))
-
-#define MAX_RETRIES 3 /* Maximum number of times to retry failed transactions */
-#define MAX_PIPES 32 /* Maximum number of pipes that can be open at once */
-#define MAX_TRANSACTIONS 256 /* Maximum number of outstanding transactions across all pipes */
-#define MAX_CHANNELS 8 /* Maximum number of hardware channels supported by the USB block */
-#define MAX_USB_ADDRESS 127 /* The highest valid USB device address */
-#define MAX_USB_ENDPOINT 15 /* The highest valid USB endpoint number */
-#define MAX_USB_HUB_PORT 15 /* The highest valid port number on a hub */
-#define MAX_TRANSFER_BYTES ((1<<19)-1) /* The low level hardware can transfer a maximum of this number of bytes in each transfer. The field is 19 bits wide */
-#define MAX_TRANSFER_PACKETS ((1<<10)-1) /* The low level hardware can transfer a maximum of this number of packets in each transfer. The field is 10 bits wide */
+/* Normal prefetch that use the pref instruction. */
+#define CVMX_PREFETCH(address, offset) asm volatile ("pref %[type], %[off](%[rbase])" : : [rbase] "d" (address), [off] "I" (offset), [type] "n" (0))
+
+/* Maximum number of times to retry failed transactions */
+#define MAX_RETRIES 3
+
+/* Maximum number of pipes that can be open at once */
+#define MAX_PIPES 32
+
+/* Maximum number of outstanding transactions across all pipes */
+#define MAX_TRANSACTIONS 256
+
+/* Maximum number of hardware channels supported by the USB block */
+#define MAX_CHANNELS 8
+
+/* The highest valid USB device address */
+#define MAX_USB_ADDRESS 127
+
+/* The highest valid USB endpoint number */
+#define MAX_USB_ENDPOINT 15
+
+/* The highest valid port number on a hub */
+#define MAX_USB_HUB_PORT 15
+
+/*
+ * The low level hardware can transfer a maximum of this number of bytes in each
+ * transfer. The field is 19 bits wide
+ */
+#define MAX_TRANSFER_BYTES ((1<<19)-1)
/*
- * These defines disable the normal read and write csr. This is so I can add
- * extra debug stuff to the usb specific version and I won't use the normal
- * version by mistake
+ * The low level hardware can transfer a maximum of this number of packets in
+ * each transfer. The field is 10 bits wide
*/
-#define cvmx_read_csr use_cvmx_usb_read_csr64_instead_of_cvmx_read_csr
-#define cvmx_write_csr use_cvmx_usb_write_csr64_instead_of_cvmx_write_csr
+#define MAX_TRANSFER_PACKETS ((1<<10)-1)
enum cvmx_usb_transaction_flags {
__CVMX_USB_TRANSACTION_FLAGS_IN_USE = 1<<16,
* functions.
* @usb_port_number:
* Which Octeon USB port to initialize.
- * @flags: Flags to control hardware initialization. See
- * enum cvmx_usb_initialize_flags for the flag
- * definitions. Some flags are mandatory.
*
* Returns: 0 or a negative error code.
*/
-int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number,
- enum cvmx_usb_initialize_flags flags)
+int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number)
{
union cvmx_usbnx_clk_ctl usbn_clk_ctl;
union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status;
struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
- usb->init_flags = flags;
+ enum cvmx_usb_initialize_flags flags = 0;
/* Make sure that state is large enough to store the internal state */
if (sizeof(*state) < sizeof(*usb))
if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0))
return -EINVAL;
/* Try to determine clock type automatically */
- if ((flags & (CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI |
- CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND)) == 0) {
- if (octeon_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12)
- flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI; /* Only 12 MHZ crystals are supported */
- else
- flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND;
- }
+ if (octeon_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12) {
+ /* Only 12 MHZ crystals are supported */
+ flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI;
+ } else {
+ flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND;
- if (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) {
- /* Check for auto ref clock frequency */
- if (!(flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK))
- switch (octeon_usb_get_clock_type()) {
- case USB_CLOCK_TYPE_REF_12:
- flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ;
- break;
- case USB_CLOCK_TYPE_REF_24:
- flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ;
- break;
- case USB_CLOCK_TYPE_REF_48:
- flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ;
- break;
- default:
- return -EINVAL;
- break;
- }
+ switch (octeon_usb_get_clock_type()) {
+ case USB_CLOCK_TYPE_REF_12:
+ flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ;
+ break;
+ case USB_CLOCK_TYPE_REF_24:
+ flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ;
+ break;
+ case USB_CLOCK_TYPE_REF_48:
+ flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
}
memset(usb, 0, sizeof(*usb));
* Most Octeon evaluation boards require this setting
*/
if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
- usbn_clk_ctl.cn31xx.p_rclk = 1; /* From CN31XX,CN30XX manual */
+ /* From CN31XX,CN30XX manual */
+ usbn_clk_ctl.cn31xx.p_rclk = 1;
usbn_clk_ctl.cn31xx.p_xenbn = 0;
} else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
- usbn_clk_ctl.cn56xx.p_rtype = 2; /* From CN56XX,CN50XX manual */
+ /* From CN56XX,CN50XX manual */
+ usbn_clk_ctl.cn56xx.p_rtype = 2;
else
- usbn_clk_ctl.cn52xx.p_rtype = 1; /* From CN52XX manual */
+ /* From CN52XX manual */
+ usbn_clk_ctl.cn52xx.p_rtype = 1;
switch (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) {
case CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ:
* at USB_XO and USB_XI
*/
if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
- usbn_clk_ctl.cn31xx.p_rclk = 1; /* From CN31XX,CN30XX manual */
+ /* From CN31XX,CN30XX manual */
+ usbn_clk_ctl.cn31xx.p_rclk = 1;
usbn_clk_ctl.cn31xx.p_xenbn = 1;
} else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
- usbn_clk_ctl.cn56xx.p_rtype = 0; /* From CN56XX,CN50XX manual */
+ /* From CN56XX,CN50XX manual */
+ usbn_clk_ctl.cn56xx.p_rtype = 0;
else
- usbn_clk_ctl.cn52xx.p_rtype = 0; /* From CN52XX manual */
+ /* From CN52XX manual */
+ usbn_clk_ctl.cn52xx.p_rtype = 0;
usbn_clk_ctl.s.p_c_sel = 0;
}
*/
{
int divisor = (octeon_get_clock_rate()+125000000-1)/125000000;
- if (divisor < 4) /* Lower than 4 doesn't seem to work properly */
+ /* Lower than 4 doesn't seem to work properly */
+ if (divisor < 4)
divisor = 4;
usbn_clk_ctl.s.divide = divisor;
usbn_clk_ctl.s.divide2 = 0;
usbcx_gahbcfg.u32 = 0;
usbcx_gahbcfg.s.dmaen = !(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA);
if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
- usb->idle_hardware_channels = 0x1; /* Only use one channel with non DMA */
+ /* Only use one channel with non DMA */
+ usb->idle_hardware_channels = 0x1;
else if (OCTEON_IS_MODEL(OCTEON_CN5XXX))
- usb->idle_hardware_channels = 0xf7; /* CN5XXX have an errata with channel 3 */
+ /* CN5XXX have an errata with channel 3 */
+ usb->idle_hardware_channels = 0xf7;
else
usb->idle_hardware_channels = 0xff;
usbcx_gahbcfg.s.hbstlen = 0;
__cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index),
usbcx_gintmsk.u32);
- /* Disable all channel interrupts. We'll enable them per channel later */
+ /*
+ * Disable all channel interrupts. We'll enable them per channel
+ * later.
+ */
for (channel = 0; channel < 8; channel++)
__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
}
prtena, ==, 1, 100000))
return -ETIMEDOUT;
- /* Read the port speed field to get the enumerated speed, USBC_HPRT[PRTSPD]. */
+ /*
+ * Read the port speed field to get the enumerated speed,
+ * USBC_HPRT[PRTSPD].
+ */
usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
usbcx_ghwcfg3.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GHWCFG3(usb->index));
*
* @state: USB device state populated by
* cvmx_usb_initialize().
- * @flags: Optional pipe flags defined in
- * enum cvmx_usb_pipe_flags.
* @device_addr:
* USB device address to open the pipe to
* (0-127).
* Returns: A non negative value is a pipe handle. Negative
* values are error codes.
*/
-int cvmx_usb_open_pipe(struct cvmx_usb_state *state, enum cvmx_usb_pipe_flags flags,
+int cvmx_usb_open_pipe(struct cvmx_usb_state *state,
int device_addr, int endpoint_num,
enum cvmx_usb_speed device_speed, int max_packet,
enum cvmx_usb_transfer transfer_type,
if (!pipe)
return -ENOMEM;
__cvmx_usb_remove_pipe(&usb->free_pipes, pipe);
- pipe->flags = flags | __CVMX_USB_PIPE_FLAGS_OPEN;
+ pipe->flags = __CVMX_USB_PIPE_FLAGS_OPEN;
if ((device_speed == CVMX_USB_SPEED_HIGH) &&
(transfer_dir == CVMX_USB_DIRECTION_OUT) &&
(transfer_type == CVMX_USB_TRANSFER_BULK))
if (usbc_hcsplt.s.spltena && usbc_hcsplt.s.compsplt)
return;
- /* Find out how many bytes we need to fill and convert it into 32bit words */
+ /*
+ * Find out how many bytes we need to fill and convert it into 32bit
+ * words.
+ */
usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
if (!usbc_hctsiz.s.xfersize)
return;
usbc_hcintmsk.u32 = 0;
usbc_hcintmsk.s.chhltdmsk = 1;
if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
- /* Channels need these extra interrupts when we aren't in DMA mode */
+ /*
+ * Channels need these extra interrupts when we aren't
+ * in DMA mode.
+ */
usbc_hcintmsk.s.datatglerrmsk = 1;
usbc_hcintmsk.s.frmovrunmsk = 1;
usbc_hcintmsk.s.bblerrmsk = 1;
usbc_hcintmsk.s.xacterrmsk = 1;
if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
- /* Splits don't generate xfercompl, so we need ACK and NYET */
+ /*
+ * Splits don't generate xfercompl, so we need
+ * ACK and NYET.
+ */
usbc_hcintmsk.s.nyetmsk = 1;
usbc_hcintmsk.s.ackmsk = 1;
}
* begin or the entire payload
*/
if (bytes_to_transfer <= 188)
- usbc_hcsplt.s.xactpos = 3; /* Entire payload in one go */
+ /* Entire payload in one go */
+ usbc_hcsplt.s.xactpos = 3;
else
- usbc_hcsplt.s.xactpos = 2; /* First part of payload */
+ /* First part of payload */
+ usbc_hcsplt.s.xactpos = 2;
} else {
/*
* Continuing the previous data, we must
* either be in the middle or at the end
*/
if (bytes_to_transfer <= 188)
- usbc_hcsplt.s.xactpos = 1; /* End of payload */
+ /* End of payload */
+ usbc_hcsplt.s.xactpos = 1;
else
- usbc_hcsplt.s.xactpos = 0; /* Middle of payload */
+ /* Middle of payload */
+ usbc_hcsplt.s.xactpos = 0;
}
/*
* Again, the transfer size is limited to 188
enum cvmx_usb_transfer ttype;
if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
- /* Without DMA we need to be careful to not schedule something at the end of a frame and cause an overrun */
+ /*
+ * Without DMA we need to be careful to not schedule something
+ * at the end of a frame and cause an overrun.
+ */
union cvmx_usbcx_hfnum hfnum = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index))};
union cvmx_usbcx_hfir hfir = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFIR(usb->index))};
if (hfnum.s.frrem < hfir.s.frint/4)
while (usb->idle_hardware_channels) {
/* Find an idle channel */
- CVMX_CLZ(channel, usb->idle_hardware_channels);
- channel = 31 - channel;
+ channel = __fls(usb->idle_hardware_channels);
if (unlikely(channel > 7))
break;
* next one
*/
if ((transaction->iso_number_packets > 1) && (complete_code == CVMX_USB_COMPLETE_SUCCESS)) {
- transaction->actual_bytes = 0; /* No bytes transferred for this packet as of yet */
- transaction->iso_number_packets--; /* One less ISO waiting to transfer */
- transaction->iso_packets++; /* Increment to the next location in our packet array */
+ /* No bytes transferred for this packet as of yet */
+ transaction->actual_bytes = 0;
+ /* One less ISO waiting to transfer */
+ transaction->iso_number_packets--;
+ /* Increment to the next location in our packet array */
+ transaction->iso_packets++;
transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
goto done;
}
* @pipe_handle:
* Which pipe to submit to. Will be validated in this function.
* @type: Transaction type
- * @flags: Flags for the transaction
* @buffer: User buffer for the transaction
* @buffer_length:
* User buffer's length in bytes
static int __cvmx_usb_submit_transaction(struct cvmx_usb_internal_state *usb,
int pipe_handle,
enum cvmx_usb_transfer type,
- int flags,
uint64_t buffer,
int buffer_length,
uint64_t control_header,
return -ENOMEM;
transaction->type = type;
- transaction->flags |= flags;
transaction->buffer = buffer;
transaction->buffer_length = buffer_length;
transaction->control_header = control_header;
- transaction->iso_start_frame = iso_start_frame; // FIXME: This is not used, implement it
+ /* FIXME: This is not used, implement it. */
+ transaction->iso_start_frame = iso_start_frame;
transaction->iso_number_packets = iso_number_packets;
transaction->iso_packets = iso_packets;
transaction->callback = callback;
submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
CVMX_USB_TRANSFER_BULK,
- 0, /* flags */
buffer,
buffer_length,
0, /* control_header */
submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
CVMX_USB_TRANSFER_INTERRUPT,
- 0, /* flags */
buffer,
buffer_length,
0, /* control_header */
submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
CVMX_USB_TRANSFER_CONTROL,
- 0, /* flags */
buffer,
buffer_length,
control_header,
* @start_frame:
* Number of frames into the future to schedule
* this transaction.
- * @flags: Flags to control the transfer. See
- * enum cvmx_usb_isochronous_flags for the flag
- * definitions.
* @number_packets:
* Number of sequential packets to transfer.
* "packets" is a pointer to an array of this
* failure. Negative values are error codes.
*/
int cvmx_usb_submit_isochronous(struct cvmx_usb_state *state, int pipe_handle,
- int start_frame, int flags,
+ int start_frame,
int number_packets,
struct cvmx_usb_iso_packet packets[],
uint64_t buffer, int buffer_length,
/* Pipe handle checking is done later in a common place */
if (unlikely(start_frame < 0))
return -EINVAL;
- if (unlikely(flags & ~(CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT | CVMX_USB_ISOCHRONOUS_FLAGS_ASAP)))
- return -EINVAL;
if (unlikely(number_packets < 1))
return -EINVAL;
if (unlikely(!packets))
submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
CVMX_USB_TRANSFER_ISOCHRONOUS,
- flags,
buffer,
buffer_length,
0, /* control_header */
* @pipe_handle:
* Pipe handle to cancel requests in.
* @submit_handle:
- * Handle to transaction to cancel, returned by the submit function.
+ * Handle to transaction to cancel, returned by the submit
+ * function.
*
* Returns: 0 or a negative error code.
*/
CVMX_SYNCW;
usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index));
- /* If the channel isn't enabled then the transaction already completed */
+ /*
+ * If the channel isn't enabled then the transaction already
+ * completed.
+ */
if (usbc_hcchar.s.chena) {
usbc_hcchar.s.chdis = 1;
__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index), usbc_hcchar.u32);
__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
return 0;
} else if (usbc_hcint.s.xfercompl) {
- /* Successful IN/OUT with transfer complete. Channel halt isn't needed */
+ /*
+ * Successful IN/OUT with transfer complete.
+ * Channel halt isn't needed.
+ */
} else {
cvmx_dprintf("USB%d: Channel %d interrupt without halt\n", usb->index, channel);
return 0;
if (!pipe)
return 0;
transaction = pipe->head;
- CVMX_PREFETCH0(transaction);
+ CVMX_PREFETCH(transaction, 0);
/*
* Disconnect this pipe from the HW channel. Later the schedule
break;
}
} else if (usbc_hcint.s.nak) {
- /* If this was a split then clear our split in progress marker */
+ /*
+ * If this was a split then clear our split in progress marker.
+ */
if (usb->active_split == transaction)
usb->active_split = NULL;
/*
usbc_haint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINT(usb->index));
while (usbc_haint.u32) {
int channel;
- CVMX_CLZ(channel, usbc_haint.u32);
- channel = 31 - channel;
+
+ channel = __fls(usbc_haint.u32);
__cvmx_usb_poll_channel(usb, channel);
usbc_haint.u32 ^= 1<<channel;
}
* derived from this software without specific prior written
* permission.
- * This Software, including technical data, may be subject to U.S. export control
- * laws, including the U.S. Export Administration Act and its associated
+ * This Software, including technical data, may be subject to U.S. export
+ * control laws, including the U.S. Export Administration Act and its associated
* regulations, and may be subject to export or import regulations in other
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
+ * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
- * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
- * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
+ * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION
+ * OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
* SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
* MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
* VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
* @CVMX_USB_COMPLETE_SUCCESS: The transaction / operation finished without
* any errors
* @CVMX_USB_COMPLETE_SHORT: FIXME: This is currently not implemented
- * @CVMX_USB_COMPLETE_CANCEL: The transaction was canceled while in flight by
- * a user call to cvmx_usb_cancel
+ * @CVMX_USB_COMPLETE_CANCEL: The transaction was canceled while in flight
+ * by a user call to cvmx_usb_cancel
* @CVMX_USB_COMPLETE_ERROR: The transaction aborted with an unexpected
* error status
* @CVMX_USB_COMPLETE_STALL: The transaction received a USB STALL response
int bytes_transferred, void *user_data);
/**
- * enum cvmx_usb_initialize_flags - flags to pass the initialization function
+ * enum cvmx_usb_initialize_flags - flags used by the initialization function
*
* @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI: The USB port uses a 12MHz crystal
* as clock source at USB_XO and
* @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND: The USB port uses 12/24/48MHz 2.5V
* board clock source at USB_XO.
* USB_XI should be tied to GND.
- * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO: Automatically determine clock type
- * based on function in
- * cvmx-helper-board.c.
* @CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK: Mask for clock speed field
* @CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ: Speed of reference clock or
* crystal
enum cvmx_usb_initialize_flags {
CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI = 1 << 0,
CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND = 1 << 1,
- CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO = 0,
CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK = 3 << 3,
CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ = 1 << 3,
CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ = 2 << 3,
};
/**
- * enum cvmx_usb_pipe_flags - flags for passing when a pipe is created.
- * Currently no flags need to be passed.
+ * enum cvmx_usb_pipe_flags - internal flags for a pipe.
*
* @__CVMX_USB_PIPE_FLAGS_OPEN: Used internally to determine if a pipe is
* open. Do not use.
};
extern int cvmx_usb_get_num_ports(void);
-extern int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number,
- enum cvmx_usb_initialize_flags flags);
+extern int cvmx_usb_initialize(struct cvmx_usb_state *state,
+ int usb_port_number);
extern int cvmx_usb_shutdown(struct cvmx_usb_state *state);
extern int cvmx_usb_enable(struct cvmx_usb_state *state);
extern int cvmx_usb_disable(struct cvmx_usb_state *state);
extern struct cvmx_usb_port_status cvmx_usb_get_status(struct cvmx_usb_state *state);
extern void cvmx_usb_set_status(struct cvmx_usb_state *state, struct cvmx_usb_port_status port_status);
extern int cvmx_usb_open_pipe(struct cvmx_usb_state *state,
- enum cvmx_usb_pipe_flags flags,
int device_addr, int endpoint_num,
enum cvmx_usb_speed device_speed, int max_packet,
enum cvmx_usb_transfer transfer_type,
cvmx_usb_callback_func_t callback,
void *user_data);
-/**
- * enum cvmx_usb_isochronous_flags - flags to pass the
- * cvmx_usb_submit_isochronous() function.
- *
- * @CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT: Do not return an error if a transfer
- * is less than the maximum packet size
- * of the device.
- * @CVMX_USB_ISOCHRONOUS_FLAGS_ASAP: Schedule the transaction as soon as
- * possible.
- */
-enum cvmx_usb_isochronous_flags {
- CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT = 1 << 0,
- CVMX_USB_ISOCHRONOUS_FLAGS_ASAP = 1 << 1,
-};
-
extern int cvmx_usb_submit_isochronous(struct cvmx_usb_state *state, int pipe_handle,
- int start_frame, int flags,
+ int start_frame,
int number_packets,
struct cvmx_usb_iso_packet packets[],
uint64_t buffer, int buffer_length,
}
}
pipe_handle = cvmx_usb_open_pipe(&priv->usb,
- 0,
usb_pipedevice(urb->pipe),
usb_pipeendpoint(urb->pipe),
speed,
urb->setup_packet = (char *)iso_packet;
submit_handle = cvmx_usb_submit_isochronous(&priv->usb, pipe_handle,
urb->start_frame,
- 0 /* flags */ ,
urb->number_of_packets,
iso_packet,
urb->transfer_dma,
tasklet_init(&priv->dequeue_tasklet, octeon_usb_urb_dequeue_work, (unsigned long)priv);
INIT_LIST_HEAD(&priv->dequeue_list);
- status = cvmx_usb_initialize(&priv->usb, usb_num, CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO);
+ status = cvmx_usb_initialize(&priv->usb, usb_num);
if (status) {
dev_dbg(dev, "USB initialization failed with %d\n", status);
kfree(hcd);
registry_par->ssid.SsidLength = 3;
registry_par->channel = (u8)channel;
registry_par->wireless_mode = (u8)wireless_mode;
- registry_par->vrtl_carrier_sense = (u8)vrtl_carrier_sense ;
+ registry_par->vrtl_carrier_sense = (u8)vrtl_carrier_sense;
registry_par->vcs_type = (u8)vcs_type;
registry_par->frag_thresh = (u16)frag_thresh;
registry_par->preamble = (u8)preamble;
r8712_write8(padapter, GPIO_IO_SEL, tmp1byte);
tmp1byte = r8712_read8(padapter, GPIO_CTRL);
if (tmp1byte == 0xff)
- return ;
+ return;
if (tmp1byte&HAL_8192S_HW_GPIO_WPS_BIT) {
/* Here we only set bPbcPressed to true
* After trigger PBC, the variable will be set to false */
*pcmdbuf = cpu_to_le32((cmdsz & 0x0000ffff) |
(pcmd->cmdcode << 16) |
(pcmdpriv->cmd_seq << 24));
- pcmdbuf += 2 ; /* 8 bytes alignment */
+ pcmdbuf += 2; /* 8 bytes alignment */
memcpy((u8 *)pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
while (check_cmd_fifo(padapter, wr_sz) == _FAIL) {
if ((padapter->bDriverStopped == true) ||
/* read next header */
efuse_addr = efuse_addr + (word_cnts * 2) + 1;
} else
- bContinual = false ;
+ bContinual = false;
}
return efuse_addr;
}
struct _adapter *padapter = precvpriv->adapter;
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
- for (i = 0; i < NR_RECVBUFF ; i++) {
+ for (i = 0; i < NR_RECVBUFF; i++) {
r8712_os_recvbuf_resource_free(padapter, precvbuf);
precvbuf++;
}
u8 *psta_addr;
struct recv_frame_hdr *pfhdr;
struct sta_info *psta;
- struct sta_priv *pstapriv ;
+ struct sta_priv *pstapriv;
struct list_head *phead;
union recv_frame *prtnframe = NULL;
struct __queue *pfree_recv_queue, *pdefrag_q;
} else {
/* (1)Get RSSI for HT rate */
for (i = 0; i < ((padapter->registrypriv.rf_config) &
- 0x0f) ; i++) {
+ 0x0f); i++) {
rf_rx_num++;
rx_pwr[i] = ((pphy_head[PHY_STAT_GAIN_TRSW_SHT + i]
& 0x3F) * 2) - 110;
psta = r8712_alloc_stainfo(&padapter->stapriv,
pnetwork->MacAddress);
if (psta == NULL)
- goto createbss_cmd_fail ;
+ goto createbss_cmd_fail;
}
r8712_indicate_connect(padapter);
} else {
intReturn = true;
blInserted = false;
/* overwrite PMKID */
- for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
+ for (j = 0; j < NUM_PMKID_CACHE; j++) {
if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
strIssueBssid, ETH_ALEN)) {
/* BSSID is matched, the same AP => rewrite
PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
bUsed = true;
- psecuritypriv->PMKIDIndex++ ;
+ psecuritypriv->PMKIDIndex++;
if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
psecuritypriv->PMKIDIndex = 0;
}
wep.Length = wep.KeyLength +
FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
} else {
- wep.KeyLength = 0 ;
+ wep.KeyLength = 0;
if (keyindex_provided == 1) { /* set key_id only, no given
* KeyMaterial(erq->length==0).*/
padapter->securitypriv.PrivacyKeyIndex = key;
u32 data32;
get_user(addr, (u32 __user *)wrqu->data.pointer);
- data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags ;
+ data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags;
r8712_write32(padapter, addr, data32);
return 0;
}
padapter->recvpriv.rx_icv_err;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else
- return RNDIS_STATUS_INVALID_LENGTH ;
+ return RNDIS_STATUS_INVALID_LENGTH;
return RNDIS_STATUS_SUCCESS;
}
{
struct _adapter *padapter = (struct _adapter *)
(poid_par_priv->adapter_context);
- u32 preamblemode = 0 ;
+ u32 preamblemode = 0;
if (poid_par_priv->type_of_oid != QUERY_OID)
return RNDIS_STATUS_NOT_ACCEPTED;
else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)
ulInfo = ADHOCMODE;
else
- ulInfo = NOTASSOCIATED ;
+ ulInfo = NOTASSOCIATED;
*(u32 *)poid_par_priv->information_buf = ulInfo;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
return RNDIS_STATUS_SUCCESS;
struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
- > 0 ? 1 : 0) ; /* adhoc no 802.1x */
+ > 0 ? 1 : 0); /* adhoc no 802.1x */
pdev_network->Rssi = 0;
switch (pregistrypriv->wireless_mode) {
case WIRELESS_11B:
psta = r8712_get_stainfo(&padapter->stapriv,
pcur_network->network.MacAddress);
if (psta) {
- for (i = 0; i < 16 ; i++) {
+ for (i = 0; i < 16; i++) {
preorder_ctrl = &psta->recvreorder_ctrl[i];
preorder_ctrl->indicate_seq = 0xffff;
preorder_ctrl->wend_b = 0xffff;
u16 iocmd_value = iocmd.value;
u8 iocmd_idx = iocmd.index;
- cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx ;
+ cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx;
if (r8712_fw_cmd(pAdapter, cmd32))
r8712_fw_cmd_data(pAdapter, &val32, 1);
else
r8712_fw_cmd_data(pAdapter, &value, 0);
msleep(100);
- cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx ;
+ cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx;
return r8712_fw_cmd(pAdapter, cmd32);
}
u32 rf_data;
struct IOCMD_STRUCT iocmd;
- iocmd.cmdclass = IOCMD_CLASS_BB_RF ;
- iocmd.value = rf_addr ;
+ iocmd.cmdclass = IOCMD_CLASS_BB_RF;
+ iocmd.value = rf_addr;
iocmd.index = IOCMD_RF_READ_IDX;
rf_data = fw_iocmd_read(pAdapter, iocmd);
return rf_data;
u8 temp[4];
u8 tempb[4];
- for (i = 0 ; i < 4; i++) {
+ for (i = 0; i < 4; i++) {
if ((in[i] & 0x80) == 0x80)
add1b[i] = 0x1b;
else
length = pxmitpriv->frag_len -
pattrib->hdrlen -
pattrib->iv_len -
- pattrib->icv_len ;
+ pattrib->icv_len;
aes_cipher(prwskey, pattrib->
hdrlen, pframe, length);
pframe += pxmitpriv->frag_len;
bitwise_xor(aes_out, padded_buffer, chain_buffer);
aes128k128d(key, chain_buffer, aes_out);
}
- for (j = 0 ; j < 8; j++)
+ for (j = 0; j < 8; j++)
mic[j] = aes_out[j];
/* Insert MIC into payload */
for (j = 0; j < 8; j++)
}
phash_list = &(pstapriv->sta_hash[index]);
list_insert_tail(&psta->hash_list, phash_list);
- pstapriv->asoc_sta_count++ ;
+ pstapriv->asoc_sta_count++;
/* For the SMC router, the sequence number of first packet of WPS handshake
* will be 0. In this case, this packet will be dropped by recv_decache function
memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i],
&wRxSeqInitialValue, 2);
/* for A-MPDU Rx reordering buffer control */
- for (i = 0; i < 16 ; i++) {
+ for (i = 0; i < 16; i++) {
preorder_ctrl = &psta->recvreorder_ctrl[i];
preorder_ctrl->padapter = pstapriv->padapter;
preorder_ctrl->indicate_seq = 0xffff;
pfile->pkt = pktptr;
pfile->cur_addr = pfile->buf_start = pktptr->data;
pfile->pkt_len = pfile->buf_len = pktptr->len;
- pfile->cur_buffer = pfile->buf_start ;
+ pfile->cur_buffer = pfile->buf_start;
}
uint _r8712_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen)
}
/* Convert the application virtual address into a set of physical */
- down_read(¤t->mm->mmap_sem);
- result = get_user_pages(current, current->mm, app_virt_addr,
- num_pages,
- ((in_out_flag == SEP_DRIVER_IN_FLAG) ? 0 : 1),
- 0, page_array, NULL);
-
- up_read(¤t->mm->mmap_sem);
+ result = get_user_pages_fast(app_virt_addr, num_pages,
+ ((in_out_flag == SEP_DRIVER_IN_FLAG) ? 0 : 1), page_array);
/* Check the number of pages locked - if not all then exit with error */
if (result != num_pages) {
int i; \
if (1) { \
for (i = 0; i < 1000; i++) { \
- udelay(x) ; \
+ udelay(x); \
} \
} else { \
msleep(x); \
{"repeats", "()", CH_RPT},
{"extended numeric", "", B_EXNUM},
{"symbols", "", B_SYM},
- {0, 0}
+ {NULL, NULL}
};
static char mark_cut_flag;
{ RATE, .u.n = {"\x05[r%d]", 10, 0, 20, 100, -10, NULL } },
{ PITCH, .u.n = {"\x05[f%d]", 80, 39, 4500, 0, 0, NULL } },
{ VOL, .u.n = {"\x05[g%d]", 21, 0, 40, 0, 0, NULL } },
- { TONE, .u.n = {"\x05[s%d]", 9, 0, 63, 0, 0, 0 } },
+ { TONE, .u.n = {"\x05[s%d]", 9, 0, 63, 0, 0, NULL } },
{ PUNCT, .u.n = {"\x05[A%c]", 0, 0, 3, 0, 0, "nmsa" } },
{ DIRECT, .u.n = {NULL, 0, 0, 1, 0, 0, NULL } },
V_LAST_VAR
{ "direct", DIRECT, VAR_NUM, NULL, NULL },
};
-static struct st_var_header *var_ptrs[MAXVARS] = { 0, 0, 0 };
+static struct st_var_header *var_ptrs[MAXVARS] = { NULL, NULL, NULL };
static struct punc_var_t punc_vars[] = {
{ PUNC_SOME, 1 },
static void *s_vGetFreeContext(struct vnt_private *pDevice);
-static void s_vGenerateTxParameter(struct vnt_private *pDevice,
+static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer,
struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
int bNeedACK, u32 uDMAIdx, struct ethhdr *psEthHeader, bool need_rts);
-static u32 s_uFillDataHead(struct vnt_private *pDevice,
- u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
- u32 uDMAIdx, int bNeedAck, u8 byFBOption);
-
static void s_vGenerateMACHeader(struct vnt_private *pDevice,
u8 *pbyBufferAddr, u16 wDuration, struct ethhdr *psEthHeader,
int bNeedEncrypt, u16 wFragType, u32 uDMAIdx, u32 uFragIdx);
static u16 s_uGetRTSCTSRsvTime(struct vnt_private *pDevice, u8 byRTSRsvType,
u8 byPktType, u32 cbFrameLength, u16 wCurrentRate);
-static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
+static u16 s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
u8 byPktType, union vnt_tx_data_head *head, u32 cbFrameLength,
int bNeedAck, u16 wCurrentRate, u8 byFBOption);
-static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
+static u16 s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
union vnt_tx_data_head *head, u32 cbFrameLength, int bNeedAck,
struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption);
return cpu_to_le16((u16)uDurTime);
}
-static u32 s_uFillDataHead(struct vnt_private *pDevice,
- u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
- u32 uDMAIdx, int bNeedAck, u8 byFBOption)
+static u16 vnt_rxtx_datahead_g(struct vnt_private *priv, u8 pkt_type, u16 rate,
+ struct vnt_tx_datahead_g *buf, u32 frame_len, int need_ack)
{
+ /* Get SignalField,ServiceField,Length */
+ BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->a);
+ BBvCalculateParameter(priv, frame_len, priv->byTopCCKBasicRate,
+ PK_TYPE_11B, &buf->b);
- if (pTxDataHead == NULL) {
- return 0;
- }
+ /* Get Duration and TimeStamp */
+ buf->wDuration_a = s_uGetDataDuration(priv, pkt_type, need_ack);
+ buf->wDuration_b = s_uGetDataDuration(priv, PK_TYPE_11B, need_ack);
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- if (byFBOption == AUTO_FB_NONE) {
- struct vnt_tx_datahead_g *pBuf =
- (struct vnt_tx_datahead_g *)pTxDataHead;
- //Get SignalField,ServiceField,Length
- BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &pBuf->a);
- BBvCalculateParameter(pDevice, cbFrameLength,
- pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
- //Get Duration and TimeStamp
- pBuf->wDuration_a = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wDuration_b = s_uGetDataDuration(pDevice,
- PK_TYPE_11B, bNeedAck);
-
- pBuf->wTimeStampOff_a = vnt_time_stamp_off(pDevice,
- wCurrentRate);
- pBuf->wTimeStampOff_b = vnt_time_stamp_off(pDevice,
- pDevice->byTopCCKBasicRate);
- return (pBuf->wDuration_a);
- } else {
- // Auto Fallback
- struct vnt_tx_datahead_g_fb *pBuf =
- (struct vnt_tx_datahead_g_fb *)pTxDataHead;
- //Get SignalField,ServiceField,Length
- BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &pBuf->a);
- BBvCalculateParameter(pDevice, cbFrameLength,
- pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
- //Get Duration and TimeStamp
- pBuf->wDuration_a = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wDuration_b = s_uGetDataDuration(pDevice,
- PK_TYPE_11B, bNeedAck);
- pBuf->wDuration_a_f0 = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wDuration_a_f1 = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wTimeStampOff_a = vnt_time_stamp_off(pDevice,
- wCurrentRate);
- pBuf->wTimeStampOff_b = vnt_time_stamp_off(pDevice,
- pDevice->byTopCCKBasicRate);
- return (pBuf->wDuration_a);
- } //if (byFBOption == AUTO_FB_NONE)
- }
- else if (byPktType == PK_TYPE_11A) {
- if (byFBOption != AUTO_FB_NONE) {
- struct vnt_tx_datahead_a_fb *pBuf =
- (struct vnt_tx_datahead_a_fb *)pTxDataHead;
- //Get SignalField,ServiceField,Length
- BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &pBuf->a);
- //Get Duration and TimeStampOff
- pBuf->wDuration = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wDuration_f0 = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wDuration_f1 = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wTimeStampOff = vnt_time_stamp_off(pDevice,
- wCurrentRate);
- return (pBuf->wDuration);
- } else {
- struct vnt_tx_datahead_ab *pBuf =
- (struct vnt_tx_datahead_ab *)pTxDataHead;
- //Get SignalField,ServiceField,Length
- BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &pBuf->ab);
- //Get Duration and TimeStampOff
- pBuf->wDuration = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wTimeStampOff = vnt_time_stamp_off(pDevice,
- wCurrentRate);
- return (pBuf->wDuration);
- }
- }
- else if (byPktType == PK_TYPE_11B) {
- struct vnt_tx_datahead_ab *pBuf =
- (struct vnt_tx_datahead_ab *)pTxDataHead;
- //Get SignalField,ServiceField,Length
- BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &pBuf->ab);
- //Get Duration and TimeStampOff
- pBuf->wDuration = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wTimeStampOff = vnt_time_stamp_off(pDevice,
- wCurrentRate);
- return (pBuf->wDuration);
- }
- return 0;
+ buf->wTimeStampOff_a = vnt_time_stamp_off(priv, rate);
+ buf->wTimeStampOff_b = vnt_time_stamp_off(priv,
+ priv->byTopCCKBasicRate);
+
+ return buf->wDuration_a;
+}
+
+static u16 vnt_rxtx_datahead_g_fb(struct vnt_private *priv, u8 pkt_type,
+ u16 rate, struct vnt_tx_datahead_g_fb *buf,
+ u32 frame_len, int need_ack)
+{
+ /* Get SignalField,ServiceField,Length */
+ BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->a);
+
+ BBvCalculateParameter(priv, frame_len, priv->byTopCCKBasicRate,
+ PK_TYPE_11B, &buf->b);
+
+ /* Get Duration and TimeStamp */
+ buf->wDuration_a = s_uGetDataDuration(priv, pkt_type, need_ack);
+ buf->wDuration_b = s_uGetDataDuration(priv, PK_TYPE_11B, need_ack);
+
+ buf->wDuration_a_f0 = s_uGetDataDuration(priv, pkt_type, need_ack);
+ buf->wDuration_a_f1 = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+ buf->wTimeStampOff_a = vnt_time_stamp_off(priv, rate);
+ buf->wTimeStampOff_b = vnt_time_stamp_off(priv,
+ priv->byTopCCKBasicRate);
+
+ return buf->wDuration_a;
+}
+
+static u16 vnt_rxtx_datahead_a_fb(struct vnt_private *priv, u8 pkt_type,
+ u16 rate, struct vnt_tx_datahead_a_fb *buf,
+ u32 frame_len, int need_ack)
+{
+ /* Get SignalField,ServiceField,Length */
+ BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->a);
+ /* Get Duration and TimeStampOff */
+ buf->wDuration = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+ buf->wDuration_f0 = s_uGetDataDuration(priv, pkt_type, need_ack);
+ buf->wDuration_f1 = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+ buf->wTimeStampOff = vnt_time_stamp_off(priv, rate);
+
+ return buf->wDuration;
+}
+
+static u16 vnt_rxtx_datahead_ab(struct vnt_private *priv, u8 pkt_type,
+ u16 rate, struct vnt_tx_datahead_ab *buf,
+ u32 frame_len, int need_ack)
+{
+ /* Get SignalField,ServiceField,Length */
+ BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->ab);
+ /* Get Duration and TimeStampOff */
+ buf->wDuration = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+ buf->wTimeStampOff = vnt_time_stamp_off(priv, rate);
+
+ return buf->wDuration;
}
static int vnt_fill_ieee80211_rts(struct vnt_private *priv,
return 0;
}
-static int vnt_rxtx_rts_g_head(struct vnt_private *priv,
+static u16 vnt_rxtx_rts_g_head(struct vnt_private *priv,
struct vnt_rts_g *buf, struct ethhdr *eth_hdr,
u8 pkt_type, u32 frame_len, int need_ack,
u16 current_rate, u8 fb_option)
vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration_aa);
- return 0;
+ return vnt_rxtx_datahead_g(priv, pkt_type, current_rate,
+ &buf->data_head, frame_len, need_ack);
}
-static int vnt_rxtx_rts_g_fb_head(struct vnt_private *priv,
+static u16 vnt_rxtx_rts_g_fb_head(struct vnt_private *priv,
struct vnt_rts_g_fb *buf, struct ethhdr *eth_hdr,
u8 pkt_type, u32 frame_len, int need_ack,
u16 current_rate, u8 fb_option)
vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration_aa);
- return 0;
+ return vnt_rxtx_datahead_g_fb(priv, pkt_type, current_rate,
+ &buf->data_head, frame_len, need_ack);
}
-static int vnt_rxtx_rts_ab_head(struct vnt_private *priv,
+static u16 vnt_rxtx_rts_ab_head(struct vnt_private *priv,
struct vnt_rts_ab *buf, struct ethhdr *eth_hdr,
u8 pkt_type, u32 frame_len, int need_ack,
u16 current_rate, u8 fb_option)
vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration);
- return 0;
+ return vnt_rxtx_datahead_ab(priv, pkt_type, current_rate,
+ &buf->data_head, frame_len, need_ack);
}
-static int vnt_rxtx_rts_a_fb_head(struct vnt_private *priv,
+static u16 vnt_rxtx_rts_a_fb_head(struct vnt_private *priv,
struct vnt_rts_a_fb *buf, struct ethhdr *eth_hdr,
u8 pkt_type, u32 frame_len, int need_ack,
u16 current_rate, u8 fb_option)
vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration);
- return 0;
+ return vnt_rxtx_datahead_a_fb(priv, pkt_type, current_rate,
+ &buf->data_head, frame_len, need_ack);
}
-static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
+static u16 s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
union vnt_tx_data_head *head, u32 cbFrameLength, int bNeedAck,
struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
{
if (!head)
- return;
+ return 0;
/* Note: So far RTSHead doesn't appear in ATIM
* & Beacom DMA, so we don't need to take them
case PK_TYPE_11GB:
case PK_TYPE_11GA:
if (byFBOption == AUTO_FB_NONE)
- vnt_rxtx_rts_g_head(pDevice, &head->rts_g,
+ return vnt_rxtx_rts_g_head(pDevice, &head->rts_g,
psEthHeader, byPktType, cbFrameLength,
bNeedAck, wCurrentRate, byFBOption);
else
- vnt_rxtx_rts_g_fb_head(pDevice, &head->rts_g_fb,
+ return vnt_rxtx_rts_g_fb_head(pDevice, &head->rts_g_fb,
psEthHeader, byPktType, cbFrameLength,
bNeedAck, wCurrentRate, byFBOption);
break;
case PK_TYPE_11A:
if (byFBOption) {
- vnt_rxtx_rts_a_fb_head(pDevice, &head->rts_a_fb,
+ return vnt_rxtx_rts_a_fb_head(pDevice, &head->rts_a_fb,
psEthHeader, byPktType, cbFrameLength,
bNeedAck, wCurrentRate, byFBOption);
break;
}
case PK_TYPE_11B:
- vnt_rxtx_rts_ab_head(pDevice, &head->rts_ab,
+ return vnt_rxtx_rts_ab_head(pDevice, &head->rts_ab,
psEthHeader, byPktType, cbFrameLength,
bNeedAck, wCurrentRate, byFBOption);
}
+
+ return 0;
}
-static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
+static u16 s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
u8 byPktType, union vnt_tx_data_head *head, u32 cbFrameLength,
int bNeedAck, u16 wCurrentRate, u8 byFBOption)
{
u32 uCTSFrameLen = 14;
if (!head)
- return;
+ return 0;
if (byFBOption != AUTO_FB_NONE) {
/* Auto Fall back */
pBuf->data.duration = pBuf->wDuration_ba;
pBuf->data.frame_control = TYPE_CTL_CTS;
memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
+
+ return vnt_rxtx_datahead_g_fb(pDevice, byPktType, wCurrentRate,
+ &pBuf->data_head, cbFrameLength, bNeedAck);
} else {
struct vnt_cts *pBuf = &head->cts_g;
/* Get SignalField,ServiceField,Length */
pBuf->data.duration = pBuf->wDuration_ba;
pBuf->data.frame_control = TYPE_CTL_CTS;
memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
+
+ return vnt_rxtx_datahead_g(pDevice, byPktType, wCurrentRate,
+ &pBuf->data_head, cbFrameLength, bNeedAck);
}
+
+ return 0;
}
/*+
*
-*/
-static void s_vGenerateTxParameter(struct vnt_private *pDevice,
+static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer,
struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
int bNeedACK, u32 uDMAIdx, struct ethhdr *psEthHeader, bool need_rts)
}
if (!pFifoHead)
- return;
+ return 0;
if (pDevice->bLongHeader)
cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;
}
/* Fill RTS */
- s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
+ return s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
bNeedACK, psEthHeader, wCurrentRate, byFBOption);
}
else {//RTS_needless, PCF mode
}
/* Fill CTS */
- s_vFillCTSHead(pDevice, uDMAIdx, byPktType, head,
+ return s_vFillCTSHead(pDevice, uDMAIdx, byPktType, head,
cbFrameSize, bNeedACK, wCurrentRate, byFBOption);
}
}
else if (byPktType == PK_TYPE_11A) {
+ if (need_mic) {
+ *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
+ head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
+ } else {
+ head = &tx_buffer->tx_head.tx_ab.tx.head;
+ }
+
if (need_rts) {
//Fill RsvTime
struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, byPktType,
cbFrameSize, wCurrentRate, bNeedACK);
- if (need_mic) {
- *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
- head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
- } else {
- head = &tx_buffer->tx_head.tx_ab.tx.head;
- }
-
/* Fill RTS */
- s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
+ return s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
bNeedACK, psEthHeader, wCurrentRate, byFBOption);
} else {
//Fill RsvTime
struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
- if (need_mic)
- *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
-
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A,
cbFrameSize, wCurrentRate, bNeedACK);
+
+ return vnt_rxtx_datahead_a_fb(pDevice, byPktType, wCurrentRate,
+ &head->data_head_a_fb, cbFrameSize, bNeedACK);
}
}
else if (byPktType == PK_TYPE_11B) {
+ if (need_mic) {
+ *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
+ head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
+ } else {
+ head = &tx_buffer->tx_head.tx_ab.tx.head;
+ }
+
if (need_rts) {
//Fill RsvTime
struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B,
cbFrameSize, wCurrentRate, bNeedACK);
- if (need_mic) {
- *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
- head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
- } else {
- head = &tx_buffer->tx_head.tx_ab.tx.head;
- }
-
/* Fill RTS */
- s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
+ return s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
bNeedACK, psEthHeader, wCurrentRate, byFBOption);
}
else { //RTS_needless, non PCF mode
//Fill RsvTime
struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
- if (need_mic)
- *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
-
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B,
cbFrameSize, wCurrentRate, bNeedACK);
+
+ return vnt_rxtx_datahead_ab(pDevice, byPktType, wCurrentRate,
+ &head->data_head_ab, cbFrameSize, bNeedACK);
}
}
//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter END.\n");
+
+ return 0;
}
/*
u8 * pbyBuffer,//point to pTxBufHead
u32 uDuration;
u32 cbHeaderLength = 0, uPadding = 0;
struct vnt_mic_hdr *pMICHDR;
- void *pvTxDataHd;
u8 byFBOption = AUTO_FB_NONE, byFragType;
u16 wTxBufSize;
u32 dwMICKey0, dwMICKey1, dwMIC_Priority;
u32 *pdwMIC_L, *pdwMIC_R;
int bSoftWEP = false;
- pMICHDR = pvTxDataHd = NULL;
+ pMICHDR = NULL;
if (bNeedEncryption && pTransmitKey->pvKeyTable) {
if (((PSKeyTable)pTransmitKey->pvKeyTable)->bSoftWEP == true)
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
if (byFBOption == AUTO_FB_NONE) {
if (bRTS == true) {//RTS_need
- pvTxDataHd = (struct vnt_tx_datahead_g *) (pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g) +
- sizeof(struct vnt_tx_datahead_g);
+ cbMICHDR + sizeof(struct vnt_rts_g);
}
else { //RTS_needless
- pvTxDataHd = (struct vnt_tx_datahead_g *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts) +
- sizeof(struct vnt_tx_datahead_g);
+ cbMICHDR + sizeof(struct vnt_cts);
}
} else {
// Auto Fall Back
if (bRTS == true) {//RTS_need
- pvTxDataHd = (struct vnt_tx_datahead_g_fb *) (pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g_fb));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g_fb) +
- sizeof(struct vnt_tx_datahead_g_fb);
+ cbMICHDR + sizeof(struct vnt_rts_g_fb);
}
else if (bRTS == false) { //RTS_needless
- pvTxDataHd = (struct vnt_tx_datahead_g_fb *) (pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts_fb));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts_fb) +
- sizeof(struct vnt_tx_datahead_g_fb);
+ cbMICHDR + sizeof(struct vnt_cts_fb);
}
} // Auto Fall Back
}
else {//802.11a/b packet
if (byFBOption == AUTO_FB_NONE) {
if (bRTS == true) {//RTS_need
- pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
- sizeof(struct vnt_rts_ab));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_rts_ab) +
- sizeof(struct vnt_tx_datahead_ab);
+ cbMICHDR + sizeof(struct vnt_rts_ab);
}
else if (bRTS == false) { //RTS_needless, no MICHDR
- pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
cbMICHDR + sizeof(struct vnt_tx_datahead_ab);
}
} else {
// Auto Fall Back
if (bRTS == true) {//RTS_need
- pvTxDataHd = (struct vnt_tx_datahead_a_fb *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
- sizeof(struct vnt_rts_a_fb));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_rts_a_fb) +
- sizeof(struct vnt_tx_datahead_a_fb);
+ cbMICHDR + sizeof(struct vnt_rts_a_fb);
}
else if (bRTS == false) { //RTS_needless
- pvTxDataHd = (struct vnt_tx_datahead_a_fb *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
cbMICHDR + sizeof(struct vnt_tx_datahead_a_fb);
}
//uDMAIdx = TYPE_AC0DMA;
//pTxBufHead = (PSTxBufHead) &(pTxBufHead->adwTxKey[0]);
- //Fill FIFO,RrvTime,RTS,and CTS
- s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
- tx_buffer, &pMICHDR, cbMICHDR,
- cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, bRTS);
- //Fill DataHead
- uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
- byFBOption);
+ /* Fill FIFO, RrvTime, RTS and CTS */
+ uDuration = s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
+ tx_buffer, &pMICHDR, cbMICHDR,
+ cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, bRTS);
+
// Generate TX MAC Header
s_vGenerateMACHeader(pDevice, pbyMacHdr, (u16)uDuration, psEthHeader, bNeedEncryption,
byFragType, uDMAIdx, 0);
struct ieee80211_hdr *pMACHeader;
struct ethhdr sEthHeader;
u8 byPktType, *pbyTxBufferAddr;
- void *pvTxDataHd;
struct vnt_mic_hdr *pMICHDR = NULL;
u32 uDuration, cbReqCount, cbHeaderSize, cbFrameBodySize, cbFrameSize;
int bNeedACK, bIsPSPOLL = false;
//Set RrvTime/RTS/CTS Buffer
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
- pvTxDataHd = (struct vnt_tx_datahead_g *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_cts) + sizeof(struct vnt_cts));
cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
+ sizeof(struct vnt_cts);
}
else { // 802.11a/b packet
- pvTxDataHd = (struct vnt_tx_datahead_ab *) (pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab));
cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
sizeof(struct vnt_tx_datahead_ab);
}
pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG;
/* Fill FIFO,RrvTime,RTS,and CTS */
- s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
+ uDuration = s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
pTX_Buffer, &pMICHDR, 0,
cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
- //Fill DataHead
- uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
- AUTO_FB_NONE);
-
pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize;
// in the same place of other packet's Duration-field).
// And it will cause Cisco-AP to issue Disassociation-packet
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- ((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_a =
+ struct vnt_tx_datahead_g *data_head = &pTX_Buffer->tx_head.
+ tx_cts.tx.head.cts_g.data_head;
+ data_head->wDuration_a =
cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
- ((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_b =
+ data_head->wDuration_b =
cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
} else {
- ((struct vnt_tx_datahead_ab *)pvTxDataHd)->wDuration =
+ struct vnt_tx_datahead_ab *data_head = &pTX_Buffer->tx_head.
+ tx_ab.tx.head.data_head_ab;
+ data_head->wDuration =
cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
}
}
struct vnt_tx_fifo_head *pTxBufHead;
u8 byPktType;
u8 *pbyTxBufferAddr;
- void *pvTxDataHd;
u32 uDuration, cbReqCount;
struct ieee80211_hdr *pMACHeader;
u32 cbHeaderSize, cbFrameBodySize;
u32 cbExtSuppRate = 0;
struct vnt_usb_send_context *pContext;
- pMICHDR = pvTxDataHd = NULL;
+ pMICHDR = NULL;
if(skb->len <= WLAN_HDR_ADDR3_LEN) {
cbFrameBodySize = 0;
//the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
- pvTxDataHd = (struct vnt_tx_datahead_g *) (pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR +
- sizeof(struct vnt_cts));
cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR +
- sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
+ sizeof(struct vnt_cts);
}
else {//802.11a/b packet
- pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
sizeof(struct vnt_tx_datahead_ab);
}
pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG;
/* Fill FIFO,RrvTime,RTS,and CTS */
- s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
+ uDuration = s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
pTX_Buffer, &pMICHDR, cbMICHDR,
cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
- //Fill DataHead
- uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
- AUTO_FB_NONE);
-
- pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
+ pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen) + cbExtSuppRate;
// in the same place of other packet's Duration-field).
// And it will cause Cisco-AP to issue Disassociation-packet
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- ((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_a =
+ struct vnt_tx_datahead_g *data_head = &pTX_Buffer->tx_head.
+ tx_cts.tx.head.cts_g.data_head;
+ data_head->wDuration_a =
cpu_to_le16(p80211Header->sA2.wDurationID);
- ((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_b =
+ data_head->wDuration_b =
cpu_to_le16(p80211Header->sA2.wDurationID);
} else {
- ((struct vnt_tx_datahead_ab *)pvTxDataHd)->wDuration =
+ struct vnt_tx_datahead_ab *data_head = &pTX_Buffer->tx_head.
+ tx_ab.tx.head.data_head_ab;
+ data_head->wDuration =
cpu_to_le16(p80211Header->sA2.wDurationID);
}
}
u16 wDuration_bb;
u16 wReserved;
struct ieee80211_rts data;
+ struct vnt_tx_datahead_g data_head;
} __packed;
struct vnt_rts_g_fb {
u16 wRTSDuration_ba_f1;
u16 wRTSDuration_aa_f1;
struct ieee80211_rts data;
+ struct vnt_tx_datahead_g_fb data_head;
} __packed;
struct vnt_rts_ab {
u16 wDuration;
u16 wReserved;
struct ieee80211_rts data;
+ struct vnt_tx_datahead_ab data_head;
} __packed;
struct vnt_rts_a_fb {
u16 wRTSDuration_f0;
u16 wRTSDuration_f1;
struct ieee80211_rts data;
+ struct vnt_tx_datahead_a_fb data_head;
} __packed;
/* CTS buffer header */
u16 wReserved;
struct ieee80211_cts data;
u16 reserved2;
+ struct vnt_tx_datahead_g data_head;
} __packed;
struct vnt_cts_fb {
u16 wCTSDuration_ba_f1;
struct ieee80211_cts data;
u16 reserved2;
+ struct vnt_tx_datahead_g_fb data_head;
} __packed;
union vnt_tx_data_head {
/* cts g */
struct vnt_cts cts_g;
struct vnt_cts_fb cts_g_fb;
+ /* no rts/cts */
+ struct vnt_tx_datahead_a_fb data_head_a_fb;
+ struct vnt_tx_datahead_ab data_head_ab;
};
struct vnt_tx_mic_hdr {
config XILLYBUS_PCIE
tristate "Xillybus over PCIe"
- depends on XILLYBUS && PCI
+ depends on PCI
help
Set to M if you want Xillybus to use PCI Express for communicating
with the FPGA.
config XILLYBUS_OF
tristate "Xillybus over Device Tree"
- depends on XILLYBUS && OF_ADDRESS && OF_IRQ
+ depends on OF_ADDRESS && OF_IRQ
help
Set to M if you want Xillybus to find its resources from the
Open Firmware Flattened Device Tree. If the target is an embedded