mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
net: qualcomm: new Ethernet over SPI driver for QCA7000
This patch adds the Ethernet over SPI driver for the Qualcomm QCA7000 HomePlug GreenPHY. Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
7d50df8f72
commit
291ab06ecf
@@ -150,6 +150,7 @@ config ETHOC
|
||||
source "drivers/net/ethernet/packetengines/Kconfig"
|
||||
source "drivers/net/ethernet/pasemi/Kconfig"
|
||||
source "drivers/net/ethernet/qlogic/Kconfig"
|
||||
source "drivers/net/ethernet/qualcomm/Kconfig"
|
||||
source "drivers/net/ethernet/realtek/Kconfig"
|
||||
source "drivers/net/ethernet/renesas/Kconfig"
|
||||
source "drivers/net/ethernet/rdc/Kconfig"
|
||||
|
||||
@@ -60,6 +60,7 @@ obj-$(CONFIG_ETHOC) += ethoc.o
|
||||
obj-$(CONFIG_NET_PACKET_ENGINE) += packetengines/
|
||||
obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/
|
||||
obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/
|
||||
obj-$(CONFIG_NET_VENDOR_QUALCOMM) += qualcomm/
|
||||
obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
|
||||
obj-$(CONFIG_SH_ETH) += renesas/
|
||||
obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
|
||||
|
||||
30
drivers/net/ethernet/qualcomm/Kconfig
Normal file
30
drivers/net/ethernet/qualcomm/Kconfig
Normal file
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# Qualcomm network device configuration
|
||||
#
|
||||
|
||||
config NET_VENDOR_QUALCOMM
|
||||
bool "Qualcomm devices"
|
||||
default y
|
||||
depends on SPI_MASTER && OF_GPIO
|
||||
---help---
|
||||
If you have a network (Ethernet) card belonging to this class, say Y
|
||||
and read the Ethernet-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
Note that the answer to this question doesn't directly affect the
|
||||
kernel: saying N will just cause the configurator to skip all
|
||||
the questions about Qualcomm cards. If you say Y, you will be asked
|
||||
for your specific card in the following questions.
|
||||
|
||||
if NET_VENDOR_QUALCOMM
|
||||
|
||||
config QCA7000
|
||||
tristate "Qualcomm Atheros QCA7000 support"
|
||||
depends on SPI_MASTER && OF_GPIO
|
||||
---help---
|
||||
This SPI protocol driver supports the Qualcomm Atheros QCA7000.
|
||||
|
||||
To compile this driver as a module, choose M here. The module
|
||||
will be called qcaspi.
|
||||
|
||||
endif # NET_VENDOR_QUALCOMM
|
||||
6
drivers/net/ethernet/qualcomm/Makefile
Normal file
6
drivers/net/ethernet/qualcomm/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for the Qualcomm network device drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_QCA7000) += qcaspi.o
|
||||
qcaspi-objs := qca_spi.o qca_framing.o qca_7k.o qca_debug.o
|
||||
149
drivers/net/ethernet/qualcomm/qca_7k.c
Normal file
149
drivers/net/ethernet/qualcomm/qca_7k.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2011, 2012, Qualcomm Atheros Communications Inc.
|
||||
* Copyright (c) 2014, I2SE GmbH
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software
|
||||
* for any purpose with or without fee is hereby granted, provided
|
||||
* that the above copyright notice and this permission notice appear
|
||||
* in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/* This module implements the Qualcomm Atheros SPI protocol for
|
||||
* kernel-based SPI device.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "qca_7k.h"
|
||||
|
||||
void
|
||||
qcaspi_spi_error(struct qcaspi *qca)
|
||||
{
|
||||
if (qca->sync != QCASPI_SYNC_READY)
|
||||
return;
|
||||
|
||||
netdev_err(qca->net_dev, "spi error\n");
|
||||
qca->sync = QCASPI_SYNC_UNKNOWN;
|
||||
qca->stats.spi_err++;
|
||||
}
|
||||
|
||||
int
|
||||
qcaspi_read_register(struct qcaspi *qca, u16 reg, u16 *result)
|
||||
{
|
||||
__be16 rx_data;
|
||||
__be16 tx_data;
|
||||
struct spi_transfer *transfer;
|
||||
struct spi_message *msg;
|
||||
int ret;
|
||||
|
||||
tx_data = cpu_to_be16(QCA7K_SPI_READ | QCA7K_SPI_INTERNAL | reg);
|
||||
|
||||
if (qca->legacy_mode) {
|
||||
msg = &qca->spi_msg1;
|
||||
transfer = &qca->spi_xfer1;
|
||||
transfer->tx_buf = &tx_data;
|
||||
transfer->rx_buf = NULL;
|
||||
transfer->len = QCASPI_CMD_LEN;
|
||||
spi_sync(qca->spi_dev, msg);
|
||||
} else {
|
||||
msg = &qca->spi_msg2;
|
||||
transfer = &qca->spi_xfer2[0];
|
||||
transfer->tx_buf = &tx_data;
|
||||
transfer->rx_buf = NULL;
|
||||
transfer->len = QCASPI_CMD_LEN;
|
||||
transfer = &qca->spi_xfer2[1];
|
||||
}
|
||||
transfer->tx_buf = NULL;
|
||||
transfer->rx_buf = &rx_data;
|
||||
transfer->len = QCASPI_CMD_LEN;
|
||||
ret = spi_sync(qca->spi_dev, msg);
|
||||
|
||||
if (!ret)
|
||||
ret = msg->status;
|
||||
|
||||
if (ret)
|
||||
qcaspi_spi_error(qca);
|
||||
else
|
||||
*result = be16_to_cpu(rx_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
qcaspi_write_register(struct qcaspi *qca, u16 reg, u16 value)
|
||||
{
|
||||
__be16 tx_data[2];
|
||||
struct spi_transfer *transfer;
|
||||
struct spi_message *msg;
|
||||
int ret;
|
||||
|
||||
tx_data[0] = cpu_to_be16(QCA7K_SPI_WRITE | QCA7K_SPI_INTERNAL | reg);
|
||||
tx_data[1] = cpu_to_be16(value);
|
||||
|
||||
if (qca->legacy_mode) {
|
||||
msg = &qca->spi_msg1;
|
||||
transfer = &qca->spi_xfer1;
|
||||
transfer->tx_buf = &tx_data[0];
|
||||
transfer->rx_buf = NULL;
|
||||
transfer->len = QCASPI_CMD_LEN;
|
||||
spi_sync(qca->spi_dev, msg);
|
||||
} else {
|
||||
msg = &qca->spi_msg2;
|
||||
transfer = &qca->spi_xfer2[0];
|
||||
transfer->tx_buf = &tx_data[0];
|
||||
transfer->rx_buf = NULL;
|
||||
transfer->len = QCASPI_CMD_LEN;
|
||||
transfer = &qca->spi_xfer2[1];
|
||||
}
|
||||
transfer->tx_buf = &tx_data[1];
|
||||
transfer->rx_buf = NULL;
|
||||
transfer->len = QCASPI_CMD_LEN;
|
||||
ret = spi_sync(qca->spi_dev, msg);
|
||||
|
||||
if (!ret)
|
||||
ret = msg->status;
|
||||
|
||||
if (ret)
|
||||
qcaspi_spi_error(qca);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
qcaspi_tx_cmd(struct qcaspi *qca, u16 cmd)
|
||||
{
|
||||
__be16 tx_data;
|
||||
struct spi_message *msg = &qca->spi_msg1;
|
||||
struct spi_transfer *transfer = &qca->spi_xfer1;
|
||||
int ret;
|
||||
|
||||
tx_data = cpu_to_be16(cmd);
|
||||
transfer->len = sizeof(tx_data);
|
||||
transfer->tx_buf = &tx_data;
|
||||
transfer->rx_buf = NULL;
|
||||
|
||||
ret = spi_sync(qca->spi_dev, msg);
|
||||
|
||||
if (!ret)
|
||||
ret = msg->status;
|
||||
|
||||
if (ret)
|
||||
qcaspi_spi_error(qca);
|
||||
|
||||
return ret;
|
||||
}
|
||||
72
drivers/net/ethernet/qualcomm/qca_7k.h
Normal file
72
drivers/net/ethernet/qualcomm/qca_7k.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Qualcomm Atheros Communications Inc.
|
||||
* Copyright (c) 2014, I2SE GmbH
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software
|
||||
* for any purpose with or without fee is hereby granted, provided
|
||||
* that the above copyright notice and this permission notice appear
|
||||
* in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Qualcomm Atheros SPI register definition.
|
||||
*
|
||||
* This module is designed to define the Qualcomm Atheros SPI
|
||||
* register placeholders.
|
||||
*/
|
||||
|
||||
#ifndef _QCA_7K_H
|
||||
#define _QCA_7K_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "qca_spi.h"
|
||||
|
||||
#define QCA7K_SPI_READ (1 << 15)
|
||||
#define QCA7K_SPI_WRITE (0 << 15)
|
||||
#define QCA7K_SPI_INTERNAL (1 << 14)
|
||||
#define QCA7K_SPI_EXTERNAL (0 << 14)
|
||||
|
||||
#define QCASPI_CMD_LEN 2
|
||||
#define QCASPI_HW_PKT_LEN 4
|
||||
#define QCASPI_HW_BUF_LEN 0xC5B
|
||||
|
||||
/* SPI registers; */
|
||||
#define SPI_REG_BFR_SIZE 0x0100
|
||||
#define SPI_REG_WRBUF_SPC_AVA 0x0200
|
||||
#define SPI_REG_RDBUF_BYTE_AVA 0x0300
|
||||
#define SPI_REG_SPI_CONFIG 0x0400
|
||||
#define SPI_REG_SPI_STATUS 0x0500
|
||||
#define SPI_REG_INTR_CAUSE 0x0C00
|
||||
#define SPI_REG_INTR_ENABLE 0x0D00
|
||||
#define SPI_REG_RDBUF_WATERMARK 0x1200
|
||||
#define SPI_REG_WRBUF_WATERMARK 0x1300
|
||||
#define SPI_REG_SIGNATURE 0x1A00
|
||||
#define SPI_REG_ACTION_CTRL 0x1B00
|
||||
|
||||
/* SPI_CONFIG register definition; */
|
||||
#define QCASPI_SLAVE_RESET_BIT (1 << 6)
|
||||
|
||||
/* INTR_CAUSE/ENABLE register definition. */
|
||||
#define SPI_INT_WRBUF_BELOW_WM (1 << 10)
|
||||
#define SPI_INT_CPU_ON (1 << 6)
|
||||
#define SPI_INT_ADDR_ERR (1 << 3)
|
||||
#define SPI_INT_WRBUF_ERR (1 << 2)
|
||||
#define SPI_INT_RDBUF_ERR (1 << 1)
|
||||
#define SPI_INT_PKT_AVLBL (1 << 0)
|
||||
|
||||
void qcaspi_spi_error(struct qcaspi *qca);
|
||||
int qcaspi_read_register(struct qcaspi *qca, u16 reg, u16 *result);
|
||||
int qcaspi_write_register(struct qcaspi *qca, u16 reg, u16 value);
|
||||
int qcaspi_tx_cmd(struct qcaspi *qca, u16 cmd);
|
||||
|
||||
#endif /* _QCA_7K_H */
|
||||
311
drivers/net/ethernet/qualcomm/qca_debug.c
Normal file
311
drivers/net/ethernet/qualcomm/qca_debug.c
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Qualcomm Atheros Communications Inc.
|
||||
* Copyright (c) 2014, I2SE GmbH
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software
|
||||
* for any purpose with or without fee is hereby granted, provided
|
||||
* that the above copyright notice and this permission notice appear
|
||||
* in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* This file contains debugging routines for use in the QCA7K driver.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "qca_7k.h"
|
||||
#include "qca_debug.h"
|
||||
|
||||
#define QCASPI_MAX_REGS 0x20
|
||||
|
||||
static const u16 qcaspi_spi_regs[] = {
|
||||
SPI_REG_BFR_SIZE,
|
||||
SPI_REG_WRBUF_SPC_AVA,
|
||||
SPI_REG_RDBUF_BYTE_AVA,
|
||||
SPI_REG_SPI_CONFIG,
|
||||
SPI_REG_SPI_STATUS,
|
||||
SPI_REG_INTR_CAUSE,
|
||||
SPI_REG_INTR_ENABLE,
|
||||
SPI_REG_RDBUF_WATERMARK,
|
||||
SPI_REG_WRBUF_WATERMARK,
|
||||
SPI_REG_SIGNATURE,
|
||||
SPI_REG_ACTION_CTRL
|
||||
};
|
||||
|
||||
/* The order of these strings must match the order of the fields in
|
||||
* struct qcaspi_stats
|
||||
* See qca_spi.h
|
||||
*/
|
||||
static const char qcaspi_gstrings_stats[][ETH_GSTRING_LEN] = {
|
||||
"Triggered resets",
|
||||
"Device resets",
|
||||
"Reset timeouts",
|
||||
"Read errors",
|
||||
"Write errors",
|
||||
"Read buffer errors",
|
||||
"Write buffer errors",
|
||||
"Out of memory",
|
||||
"Write buffer misses",
|
||||
"Transmit ring full",
|
||||
"SPI errors",
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
static int
|
||||
qcaspi_info_show(struct seq_file *s, void *what)
|
||||
{
|
||||
struct qcaspi *qca = s->private;
|
||||
|
||||
seq_printf(s, "RX buffer size : %lu\n",
|
||||
(unsigned long)qca->buffer_size);
|
||||
|
||||
seq_puts(s, "TX ring state : ");
|
||||
|
||||
if (qca->txr.skb[qca->txr.head] == NULL)
|
||||
seq_puts(s, "empty");
|
||||
else if (qca->txr.skb[qca->txr.tail])
|
||||
seq_puts(s, "full");
|
||||
else
|
||||
seq_puts(s, "in use");
|
||||
|
||||
seq_puts(s, "\n");
|
||||
|
||||
seq_printf(s, "TX ring size : %u\n",
|
||||
qca->txr.size);
|
||||
|
||||
seq_printf(s, "Sync state : %u (",
|
||||
(unsigned int)qca->sync);
|
||||
switch (qca->sync) {
|
||||
case QCASPI_SYNC_UNKNOWN:
|
||||
seq_puts(s, "QCASPI_SYNC_UNKNOWN");
|
||||
break;
|
||||
case QCASPI_SYNC_RESET:
|
||||
seq_puts(s, "QCASPI_SYNC_RESET");
|
||||
break;
|
||||
case QCASPI_SYNC_READY:
|
||||
seq_puts(s, "QCASPI_SYNC_READY");
|
||||
break;
|
||||
default:
|
||||
seq_puts(s, "INVALID");
|
||||
break;
|
||||
}
|
||||
seq_puts(s, ")\n");
|
||||
|
||||
seq_printf(s, "IRQ : %d\n",
|
||||
qca->spi_dev->irq);
|
||||
seq_printf(s, "INTR REQ : %u\n",
|
||||
qca->intr_req);
|
||||
seq_printf(s, "INTR SVC : %u\n",
|
||||
qca->intr_svc);
|
||||
|
||||
seq_printf(s, "SPI max speed : %lu\n",
|
||||
(unsigned long)qca->spi_dev->max_speed_hz);
|
||||
seq_printf(s, "SPI mode : %x\n",
|
||||
qca->spi_dev->mode);
|
||||
seq_printf(s, "SPI chip select : %u\n",
|
||||
(unsigned int)qca->spi_dev->chip_select);
|
||||
seq_printf(s, "SPI legacy mode : %u\n",
|
||||
(unsigned int)qca->legacy_mode);
|
||||
seq_printf(s, "SPI burst length : %u\n",
|
||||
(unsigned int)qca->burst_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qcaspi_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, qcaspi_info_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations qcaspi_info_ops = {
|
||||
.open = qcaspi_info_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
void
|
||||
qcaspi_init_device_debugfs(struct qcaspi *qca)
|
||||
{
|
||||
struct dentry *device_root;
|
||||
|
||||
device_root = debugfs_create_dir(dev_name(&qca->net_dev->dev), NULL);
|
||||
qca->device_root = device_root;
|
||||
|
||||
if (IS_ERR(device_root) || !device_root) {
|
||||
pr_warn("failed to create debugfs directory for %s\n",
|
||||
dev_name(&qca->net_dev->dev));
|
||||
return;
|
||||
}
|
||||
debugfs_create_file("info", S_IFREG | S_IRUGO, device_root, qca,
|
||||
&qcaspi_info_ops);
|
||||
}
|
||||
|
||||
void
|
||||
qcaspi_remove_device_debugfs(struct qcaspi *qca)
|
||||
{
|
||||
debugfs_remove_recursive(qca->device_root);
|
||||
}
|
||||
|
||||
#else /* CONFIG_DEBUG_FS */
|
||||
|
||||
void
|
||||
qcaspi_init_device_debugfs(struct qcaspi *qca)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
qcaspi_remove_device_debugfs(struct qcaspi *qca)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
qcaspi_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *p)
|
||||
{
|
||||
struct qcaspi *qca = netdev_priv(dev);
|
||||
|
||||
strlcpy(p->driver, QCASPI_DRV_NAME, sizeof(p->driver));
|
||||
strlcpy(p->version, QCASPI_DRV_VERSION, sizeof(p->version));
|
||||
strlcpy(p->fw_version, "QCA7000", sizeof(p->fw_version));
|
||||
strlcpy(p->bus_info, dev_name(&qca->spi_dev->dev),
|
||||
sizeof(p->bus_info));
|
||||
}
|
||||
|
||||
static int
|
||||
qcaspi_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
cmd->transceiver = XCVR_INTERNAL;
|
||||
cmd->supported = SUPPORTED_10baseT_Half;
|
||||
ethtool_cmd_speed_set(cmd, SPEED_10);
|
||||
cmd->duplex = DUPLEX_HALF;
|
||||
cmd->port = PORT_OTHER;
|
||||
cmd->autoneg = AUTONEG_DISABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
qcaspi_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *estats, u64 *data)
|
||||
{
|
||||
struct qcaspi *qca = netdev_priv(dev);
|
||||
struct qcaspi_stats *st = &qca->stats;
|
||||
|
||||
memcpy(data, st, ARRAY_SIZE(qcaspi_gstrings_stats) * sizeof(u64));
|
||||
}
|
||||
|
||||
static void
|
||||
qcaspi_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
|
||||
{
|
||||
switch (stringset) {
|
||||
case ETH_SS_STATS:
|
||||
memcpy(buf, &qcaspi_gstrings_stats,
|
||||
sizeof(qcaspi_gstrings_stats));
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
qcaspi_get_sset_count(struct net_device *dev, int sset)
|
||||
{
|
||||
switch (sset) {
|
||||
case ETH_SS_STATS:
|
||||
return ARRAY_SIZE(qcaspi_gstrings_stats);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
qcaspi_get_regs_len(struct net_device *dev)
|
||||
{
|
||||
return sizeof(u32) * QCASPI_MAX_REGS;
|
||||
}
|
||||
|
||||
static void
|
||||
qcaspi_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
|
||||
{
|
||||
struct qcaspi *qca = netdev_priv(dev);
|
||||
u32 *regs_buff = p;
|
||||
unsigned int i;
|
||||
|
||||
regs->version = 1;
|
||||
memset(regs_buff, 0, sizeof(u32) * QCASPI_MAX_REGS);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qcaspi_spi_regs); i++) {
|
||||
u16 offset, value;
|
||||
|
||||
qcaspi_read_register(qca, qcaspi_spi_regs[i], &value);
|
||||
offset = qcaspi_spi_regs[i] >> 8;
|
||||
regs_buff[offset] = value;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
qcaspi_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct qcaspi *qca = netdev_priv(dev);
|
||||
|
||||
ring->rx_max_pending = 4;
|
||||
ring->tx_max_pending = TX_RING_MAX_LEN;
|
||||
ring->rx_pending = 4;
|
||||
ring->tx_pending = qca->txr.count;
|
||||
}
|
||||
|
||||
static int
|
||||
qcaspi_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct qcaspi *qca = netdev_priv(dev);
|
||||
|
||||
if ((ring->rx_pending) ||
|
||||
(ring->rx_mini_pending) ||
|
||||
(ring->rx_jumbo_pending))
|
||||
return -EINVAL;
|
||||
|
||||
if (netif_running(dev))
|
||||
qcaspi_netdev_close(dev);
|
||||
|
||||
qca->txr.count = max_t(u32, ring->tx_pending, TX_RING_MIN_LEN);
|
||||
qca->txr.count = min_t(u16, qca->txr.count, TX_RING_MAX_LEN);
|
||||
|
||||
if (netif_running(dev))
|
||||
qcaspi_netdev_open(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops qcaspi_ethtool_ops = {
|
||||
.get_drvinfo = qcaspi_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_settings = qcaspi_get_settings,
|
||||
.get_ethtool_stats = qcaspi_get_ethtool_stats,
|
||||
.get_strings = qcaspi_get_strings,
|
||||
.get_sset_count = qcaspi_get_sset_count,
|
||||
.get_regs_len = qcaspi_get_regs_len,
|
||||
.get_regs = qcaspi_get_regs,
|
||||
.get_ringparam = qcaspi_get_ringparam,
|
||||
.set_ringparam = qcaspi_set_ringparam,
|
||||
};
|
||||
|
||||
void qcaspi_set_ethtool_ops(struct net_device *dev)
|
||||
{
|
||||
dev->ethtool_ops = &qcaspi_ethtool_ops;
|
||||
}
|
||||
34
drivers/net/ethernet/qualcomm/qca_debug.h
Normal file
34
drivers/net/ethernet/qualcomm/qca_debug.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Qualcomm Atheros Communications Inc.
|
||||
* Copyright (c) 2014, I2SE GmbH
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software
|
||||
* for any purpose with or without fee is hereby granted, provided
|
||||
* that the above copyright notice and this permission notice appear
|
||||
* in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* This file contains debugging routines for use in the QCA7K driver.
|
||||
*/
|
||||
|
||||
#ifndef _QCA_DEBUG_H
|
||||
#define _QCA_DEBUG_H
|
||||
|
||||
#include "qca_spi.h"
|
||||
|
||||
void qcaspi_init_device_debugfs(struct qcaspi *qca);
|
||||
|
||||
void qcaspi_remove_device_debugfs(struct qcaspi *qca);
|
||||
|
||||
void qcaspi_set_ethtool_ops(struct net_device *dev);
|
||||
|
||||
#endif /* _QCA_DEBUG_H */
|
||||
156
drivers/net/ethernet/qualcomm/qca_framing.c
Normal file
156
drivers/net/ethernet/qualcomm/qca_framing.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Atheros Communications Inc.
|
||||
* Copyright (c) 2014, I2SE GmbH
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software
|
||||
* for any purpose with or without fee is hereby granted, provided
|
||||
* that the above copyright notice and this permission notice appear
|
||||
* in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Atheros ethernet framing. Every Ethernet frame is surrounded
|
||||
* by an atheros frame while transmitted over a serial channel;
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "qca_framing.h"
|
||||
|
||||
u16
|
||||
qcafrm_create_header(u8 *buf, u16 length)
|
||||
{
|
||||
__le16 len;
|
||||
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
len = cpu_to_le16(length);
|
||||
|
||||
buf[0] = 0xAA;
|
||||
buf[1] = 0xAA;
|
||||
buf[2] = 0xAA;
|
||||
buf[3] = 0xAA;
|
||||
buf[4] = len & 0xff;
|
||||
buf[5] = (len >> 8) & 0xff;
|
||||
buf[6] = 0;
|
||||
buf[7] = 0;
|
||||
|
||||
return QCAFRM_HEADER_LEN;
|
||||
}
|
||||
|
||||
u16
|
||||
qcafrm_create_footer(u8 *buf)
|
||||
{
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
buf[0] = 0x55;
|
||||
buf[1] = 0x55;
|
||||
return QCAFRM_FOOTER_LEN;
|
||||
}
|
||||
|
||||
/* Gather received bytes and try to extract a full ethernet frame by
|
||||
* following a simple state machine.
|
||||
*
|
||||
* Return: QCAFRM_GATHER No ethernet frame fully received yet.
|
||||
* QCAFRM_NOHEAD Header expected but not found.
|
||||
* QCAFRM_INVLEN Atheros frame length is invalid
|
||||
* QCAFRM_NOTAIL Footer expected but not found.
|
||||
* > 0 Number of byte in the fully received
|
||||
* Ethernet frame
|
||||
*/
|
||||
|
||||
s32
|
||||
qcafrm_fsm_decode(struct qcafrm_handle *handle, u8 *buf, u16 buf_len, u8 recv_byte)
|
||||
{
|
||||
s32 ret = QCAFRM_GATHER;
|
||||
u16 len;
|
||||
|
||||
switch (handle->state) {
|
||||
case QCAFRM_HW_LEN0:
|
||||
case QCAFRM_HW_LEN1:
|
||||
/* by default, just go to next state */
|
||||
handle->state--;
|
||||
|
||||
if (recv_byte != 0x00) {
|
||||
/* first two bytes of length must be 0 */
|
||||
handle->state = QCAFRM_HW_LEN0;
|
||||
}
|
||||
break;
|
||||
case QCAFRM_HW_LEN2:
|
||||
case QCAFRM_HW_LEN3:
|
||||
handle->state--;
|
||||
break;
|
||||
/* 4 bytes header pattern */
|
||||
case QCAFRM_WAIT_AA1:
|
||||
case QCAFRM_WAIT_AA2:
|
||||
case QCAFRM_WAIT_AA3:
|
||||
case QCAFRM_WAIT_AA4:
|
||||
if (recv_byte != 0xAA) {
|
||||
ret = QCAFRM_NOHEAD;
|
||||
handle->state = QCAFRM_HW_LEN0;
|
||||
} else {
|
||||
handle->state--;
|
||||
}
|
||||
break;
|
||||
/* 2 bytes length. */
|
||||
/* Borrow offset field to hold length for now. */
|
||||
case QCAFRM_WAIT_LEN_BYTE0:
|
||||
handle->offset = recv_byte;
|
||||
handle->state = QCAFRM_WAIT_LEN_BYTE1;
|
||||
break;
|
||||
case QCAFRM_WAIT_LEN_BYTE1:
|
||||
handle->offset = handle->offset | (recv_byte << 8);
|
||||
handle->state = QCAFRM_WAIT_RSVD_BYTE1;
|
||||
break;
|
||||
case QCAFRM_WAIT_RSVD_BYTE1:
|
||||
handle->state = QCAFRM_WAIT_RSVD_BYTE2;
|
||||
break;
|
||||
case QCAFRM_WAIT_RSVD_BYTE2:
|
||||
len = handle->offset;
|
||||
if (len > buf_len || len < QCAFRM_ETHMINLEN) {
|
||||
ret = QCAFRM_INVLEN;
|
||||
handle->state = QCAFRM_HW_LEN0;
|
||||
} else {
|
||||
handle->state = (enum qcafrm_state)(len + 1);
|
||||
/* Remaining number of bytes. */
|
||||
handle->offset = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Receiving Ethernet frame itself. */
|
||||
buf[handle->offset] = recv_byte;
|
||||
handle->offset++;
|
||||
handle->state--;
|
||||
break;
|
||||
case QCAFRM_WAIT_551:
|
||||
if (recv_byte != 0x55) {
|
||||
ret = QCAFRM_NOTAIL;
|
||||
handle->state = QCAFRM_HW_LEN0;
|
||||
} else {
|
||||
handle->state = QCAFRM_WAIT_552;
|
||||
}
|
||||
break;
|
||||
case QCAFRM_WAIT_552:
|
||||
if (recv_byte != 0x55) {
|
||||
ret = QCAFRM_NOTAIL;
|
||||
handle->state = QCAFRM_HW_LEN0;
|
||||
} else {
|
||||
ret = handle->offset;
|
||||
/* Frame is fully received. */
|
||||
handle->state = QCAFRM_HW_LEN0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
134
drivers/net/ethernet/qualcomm/qca_framing.h
Normal file
134
drivers/net/ethernet/qualcomm/qca_framing.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Atheros Communications Inc.
|
||||
* Copyright (c) 2014, I2SE GmbH
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software
|
||||
* for any purpose with or without fee is hereby granted, provided
|
||||
* that the above copyright notice and this permission notice appear
|
||||
* in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Atheros Ethernet framing. Every Ethernet frame is surrounded by an atheros
|
||||
* frame while transmitted over a serial channel.
|
||||
*/
|
||||
|
||||
#ifndef _QCA_FRAMING_H
|
||||
#define _QCA_FRAMING_H
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Frame is currently being received */
|
||||
#define QCAFRM_GATHER 0
|
||||
|
||||
/* No header byte while expecting it */
|
||||
#define QCAFRM_NOHEAD (QCAFRM_ERR_BASE - 1)
|
||||
|
||||
/* No tailer byte while expecting it */
|
||||
#define QCAFRM_NOTAIL (QCAFRM_ERR_BASE - 2)
|
||||
|
||||
/* Frame length is invalid */
|
||||
#define QCAFRM_INVLEN (QCAFRM_ERR_BASE - 3)
|
||||
|
||||
/* Frame length is invalid */
|
||||
#define QCAFRM_INVFRAME (QCAFRM_ERR_BASE - 4)
|
||||
|
||||
/* Min/Max Ethernet MTU */
|
||||
#define QCAFRM_ETHMINMTU 46
|
||||
#define QCAFRM_ETHMAXMTU 1500
|
||||
|
||||
/* Min/Max frame lengths */
|
||||
#define QCAFRM_ETHMINLEN (QCAFRM_ETHMINMTU + ETH_HLEN)
|
||||
#define QCAFRM_ETHMAXLEN (QCAFRM_ETHMAXMTU + VLAN_ETH_HLEN)
|
||||
|
||||
/* QCA7K header len */
|
||||
#define QCAFRM_HEADER_LEN 8
|
||||
|
||||
/* QCA7K footer len */
|
||||
#define QCAFRM_FOOTER_LEN 2
|
||||
|
||||
/* QCA7K Framing. */
|
||||
#define QCAFRM_ERR_BASE -1000
|
||||
|
||||
enum qcafrm_state {
|
||||
QCAFRM_HW_LEN0 = 0x8000,
|
||||
QCAFRM_HW_LEN1 = QCAFRM_HW_LEN0 - 1,
|
||||
QCAFRM_HW_LEN2 = QCAFRM_HW_LEN1 - 1,
|
||||
QCAFRM_HW_LEN3 = QCAFRM_HW_LEN2 - 1,
|
||||
|
||||
/* Waiting first 0xAA of header */
|
||||
QCAFRM_WAIT_AA1 = QCAFRM_HW_LEN3 - 1,
|
||||
|
||||
/* Waiting second 0xAA of header */
|
||||
QCAFRM_WAIT_AA2 = QCAFRM_WAIT_AA1 - 1,
|
||||
|
||||
/* Waiting third 0xAA of header */
|
||||
QCAFRM_WAIT_AA3 = QCAFRM_WAIT_AA2 - 1,
|
||||
|
||||
/* Waiting fourth 0xAA of header */
|
||||
QCAFRM_WAIT_AA4 = QCAFRM_WAIT_AA3 - 1,
|
||||
|
||||
/* Waiting Byte 0-1 of length (litte endian) */
|
||||
QCAFRM_WAIT_LEN_BYTE0 = QCAFRM_WAIT_AA4 - 1,
|
||||
QCAFRM_WAIT_LEN_BYTE1 = QCAFRM_WAIT_AA4 - 2,
|
||||
|
||||
/* Reserved bytes */
|
||||
QCAFRM_WAIT_RSVD_BYTE1 = QCAFRM_WAIT_AA4 - 3,
|
||||
QCAFRM_WAIT_RSVD_BYTE2 = QCAFRM_WAIT_AA4 - 4,
|
||||
|
||||
/* The frame length is used as the state until
|
||||
* the end of the Ethernet frame
|
||||
* Waiting for first 0x55 of footer
|
||||
*/
|
||||
QCAFRM_WAIT_551 = 1,
|
||||
|
||||
/* Waiting for second 0x55 of footer */
|
||||
QCAFRM_WAIT_552 = QCAFRM_WAIT_551 - 1
|
||||
};
|
||||
|
||||
/* Structure to maintain the frame decoding during reception. */
|
||||
|
||||
struct qcafrm_handle {
|
||||
/* Current decoding state */
|
||||
enum qcafrm_state state;
|
||||
|
||||
/* Offset in buffer (borrowed for length too) */
|
||||
s16 offset;
|
||||
|
||||
/* Frame length as kept by this module */
|
||||
u16 len;
|
||||
};
|
||||
|
||||
u16 qcafrm_create_header(u8 *buf, u16 len);
|
||||
|
||||
u16 qcafrm_create_footer(u8 *buf);
|
||||
|
||||
static inline void qcafrm_fsm_init(struct qcafrm_handle *handle)
|
||||
{
|
||||
handle->state = QCAFRM_HW_LEN0;
|
||||
}
|
||||
|
||||
/* Gather received bytes and try to extract a full Ethernet frame
|
||||
* by following a simple state machine.
|
||||
*
|
||||
* Return: QCAFRM_GATHER No Ethernet frame fully received yet.
|
||||
* QCAFRM_NOHEAD Header expected but not found.
|
||||
* QCAFRM_INVLEN QCA7K frame length is invalid
|
||||
* QCAFRM_NOTAIL Footer expected but not found.
|
||||
* > 0 Number of byte in the fully received
|
||||
* Ethernet frame
|
||||
*/
|
||||
|
||||
s32 qcafrm_fsm_decode(struct qcafrm_handle *handle, u8 *buf, u16 buf_len, u8 recv_byte);
|
||||
|
||||
#endif /* _QCA_FRAMING_H */
|
||||
993
drivers/net/ethernet/qualcomm/qca_spi.c
Normal file
993
drivers/net/ethernet/qualcomm/qca_spi.c
Normal file
File diff suppressed because it is too large
Load Diff
114
drivers/net/ethernet/qualcomm/qca_spi.h
Normal file
114
drivers/net/ethernet/qualcomm/qca_spi.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Qualcomm Atheros Communications Inc.
|
||||
* Copyright (c) 2014, I2SE GmbH
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software
|
||||
* for any purpose with or without fee is hereby granted, provided
|
||||
* that the above copyright notice and this permission notice appear
|
||||
* in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Qualcomm Atheros SPI register definition.
|
||||
*
|
||||
* This module is designed to define the Qualcomm Atheros SPI register
|
||||
* placeholders;
|
||||
*/
|
||||
|
||||
#ifndef _QCA_SPI_H
|
||||
#define _QCA_SPI_H
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "qca_framing.h"
|
||||
|
||||
#define QCASPI_DRV_VERSION "0.2.7-i"
|
||||
#define QCASPI_DRV_NAME "qcaspi"
|
||||
|
||||
#define QCASPI_GOOD_SIGNATURE 0xAA55
|
||||
|
||||
#define TX_RING_MAX_LEN 10
|
||||
#define TX_RING_MIN_LEN 2
|
||||
|
||||
/* sync related constants */
|
||||
#define QCASPI_SYNC_UNKNOWN 0
|
||||
#define QCASPI_SYNC_RESET 1
|
||||
#define QCASPI_SYNC_READY 2
|
||||
|
||||
#define QCASPI_RESET_TIMEOUT 10
|
||||
|
||||
/* sync events */
|
||||
#define QCASPI_EVENT_UPDATE 0
|
||||
#define QCASPI_EVENT_CPUON 1
|
||||
|
||||
struct tx_ring {
|
||||
struct sk_buff *skb[TX_RING_MAX_LEN];
|
||||
u16 head;
|
||||
u16 tail;
|
||||
u16 size;
|
||||
u16 count;
|
||||
};
|
||||
|
||||
struct qcaspi_stats {
|
||||
u64 trig_reset;
|
||||
u64 device_reset;
|
||||
u64 reset_timeout;
|
||||
u64 read_err;
|
||||
u64 write_err;
|
||||
u64 read_buf_err;
|
||||
u64 write_buf_err;
|
||||
u64 out_of_mem;
|
||||
u64 write_buf_miss;
|
||||
u64 ring_full;
|
||||
u64 spi_err;
|
||||
};
|
||||
|
||||
struct qcaspi {
|
||||
struct net_device *net_dev;
|
||||
struct spi_device *spi_dev;
|
||||
struct task_struct *spi_thread;
|
||||
|
||||
struct tx_ring txr;
|
||||
struct qcaspi_stats stats;
|
||||
|
||||
struct spi_message spi_msg1;
|
||||
struct spi_message spi_msg2;
|
||||
struct spi_transfer spi_xfer1;
|
||||
struct spi_transfer spi_xfer2[2];
|
||||
|
||||
u8 *rx_buffer;
|
||||
u32 buffer_size;
|
||||
u8 sync;
|
||||
|
||||
struct qcafrm_handle frm_handle;
|
||||
struct sk_buff *rx_skb;
|
||||
|
||||
unsigned int intr_req;
|
||||
unsigned int intr_svc;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *device_root;
|
||||
#endif
|
||||
|
||||
/* user configurable options */
|
||||
u32 clkspeed;
|
||||
u8 legacy_mode;
|
||||
u16 burst_len;
|
||||
};
|
||||
|
||||
int qcaspi_netdev_open(struct net_device *dev);
|
||||
int qcaspi_netdev_close(struct net_device *dev);
|
||||
|
||||
#endif /* _QCA_SPI_H */
|
||||
Reference in New Issue
Block a user