Skip to content

Commit 842abe0

Browse files
committed
Merge branch 'qca7000_spi'
Stefan Wahren says: ==================== add Qualcomm QCA7000 ethernet driver This patch series adds support for the Qualcomm QCA7000 Homeplug GreenPHY. The QCA7000 is serial-to-powerline bridge with two interfaces: UART and SPI. These patches handles only the last one, with an Ethernet over SPI protocol driver. This driver based on the Qualcomm code [1], but contains a lot of changes since last year: * devicetree support * DebugFS support * ethtool support * better error handling * performance improvements * code cleanup * some bugfixes The code has been tested only on Freescale i.MX28 boards, but should work on other platforms. [1] - https://github.com/IoE/qca7000 Changes in V3: - Use ether_addr_copy instead of memcpy - Remove qcaspi_set_mac_address - Improve DT parsing - replace OF_GPIO dependancy with OF - fix compile error caused by SET_ETHTOOL_OPS - fix possible endless loop when spi read fails - fix DT documentation - fix coding style - fix sparse warnings Changes in V2: - replace in DT the SPI intr GPIO with pure interrupt - make legacy mode a boolean DT property and remove it as module parameter - make burst length a module parameter instead of DT property - make pluggable a module parameter instead of DT property - improve DT documentation - replace debugFS register dump with ethtool function - replace debugFS stats with ethtool function - implement function to get ring parameter via ethtool - implement function to set TX ring count via ethtool - fix TX ring state in debugFS - optimize tx ring flush - add byte limit for TX ring to avoid bufferbloat - fix TX queue full and write buffer miss counter - fix SPI clk speed module parameter - fix possible packet loss - fix possible race during transmit ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents a11238e + 291ab06 commit 842abe0

File tree

13 files changed

+2048
-0
lines changed

13 files changed

+2048
-0
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
* Qualcomm QCA7000 (Ethernet over SPI protocol)
2+
3+
Note: The QCA7000 is useable as a SPI device. In this case it must be defined
4+
as a child of a SPI master in the device tree.
5+
6+
Required properties:
7+
- compatible : Should be "qca,qca7000"
8+
- reg : Should specify the SPI chip select
9+
- interrupts : The first cell should specify the index of the source interrupt
10+
and the second cell should specify the trigger type as rising edge
11+
- spi-cpha : Must be set
12+
- spi-cpol: Must be set
13+
14+
Optional properties:
15+
- interrupt-parent : Specify the pHandle of the source interrupt
16+
- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at.
17+
Numbers smaller than 1000000 or greater than 16000000 are invalid. Missing
18+
the property will set the SPI frequency to 8000000 Hertz.
19+
- local-mac-address: 6 bytes, MAC address
20+
- qca,legacy-mode : Set the SPI data transfer of the QCA7000 to legacy mode.
21+
In this mode the SPI master must toggle the chip select between each data
22+
word. In burst mode these gaps aren't necessary, which is faster.
23+
This setting depends on how the QCA7000 is setup via GPIO pin strapping.
24+
If the property is missing the driver defaults to burst mode.
25+
26+
Example:
27+
28+
/* Freescale i.MX28 SPI master*/
29+
ssp2: spi@80014000 {
30+
#address-cells = <1>;
31+
#size-cells = <0>;
32+
compatible = "fsl,imx28-spi";
33+
pinctrl-names = "default";
34+
pinctrl-0 = <&spi2_pins_a>;
35+
status = "okay";
36+
37+
qca7000: ethernet@0 {
38+
compatible = "qca,qca7000";
39+
reg = <0x0>;
40+
interrupt-parent = <&gpio3>; /* GPIO Bank 3 */
41+
interrupts = <25 0x1>; /* Index: 25, rising edge */
42+
spi-cpha; /* SPI mode: CPHA=1 */
43+
spi-cpol; /* SPI mode: CPOL=1 */
44+
spi-max-frequency = <8000000>; /* freq: 8 MHz */
45+
local-mac-address = [ A0 B0 C0 D0 E0 F0 ];
46+
};
47+
};

drivers/net/ethernet/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ config ETHOC
150150
source "drivers/net/ethernet/packetengines/Kconfig"
151151
source "drivers/net/ethernet/pasemi/Kconfig"
152152
source "drivers/net/ethernet/qlogic/Kconfig"
153+
source "drivers/net/ethernet/qualcomm/Kconfig"
153154
source "drivers/net/ethernet/realtek/Kconfig"
154155
source "drivers/net/ethernet/renesas/Kconfig"
155156
source "drivers/net/ethernet/rdc/Kconfig"

drivers/net/ethernet/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ obj-$(CONFIG_ETHOC) += ethoc.o
6060
obj-$(CONFIG_NET_PACKET_ENGINE) += packetengines/
6161
obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/
6262
obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/
63+
obj-$(CONFIG_NET_VENDOR_QUALCOMM) += qualcomm/
6364
obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
6465
obj-$(CONFIG_SH_ETH) += renesas/
6566
obj-$(CONFIG_NET_VENDOR_RDC) += rdc/

drivers/net/ethernet/qualcomm/Kconfig

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#
2+
# Qualcomm network device configuration
3+
#
4+
5+
config NET_VENDOR_QUALCOMM
6+
bool "Qualcomm devices"
7+
default y
8+
depends on SPI_MASTER && OF_GPIO
9+
---help---
10+
If you have a network (Ethernet) card belonging to this class, say Y
11+
and read the Ethernet-HOWTO, available from
12+
<http://www.tldp.org/docs.html#howto>.
13+
14+
Note that the answer to this question doesn't directly affect the
15+
kernel: saying N will just cause the configurator to skip all
16+
the questions about Qualcomm cards. If you say Y, you will be asked
17+
for your specific card in the following questions.
18+
19+
if NET_VENDOR_QUALCOMM
20+
21+
config QCA7000
22+
tristate "Qualcomm Atheros QCA7000 support"
23+
depends on SPI_MASTER && OF_GPIO
24+
---help---
25+
This SPI protocol driver supports the Qualcomm Atheros QCA7000.
26+
27+
To compile this driver as a module, choose M here. The module
28+
will be called qcaspi.
29+
30+
endif # NET_VENDOR_QUALCOMM
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#
2+
# Makefile for the Qualcomm network device drivers.
3+
#
4+
5+
obj-$(CONFIG_QCA7000) += qcaspi.o
6+
qcaspi-objs := qca_spi.o qca_framing.o qca_7k.o qca_debug.o
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
*
3+
* Copyright (c) 2011, 2012, Qualcomm Atheros Communications Inc.
4+
* Copyright (c) 2014, I2SE GmbH
5+
*
6+
* Permission to use, copy, modify, and/or distribute this software
7+
* for any purpose with or without fee is hereby granted, provided
8+
* that the above copyright notice and this permission notice appear
9+
* in all copies.
10+
*
11+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
12+
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13+
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
14+
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
15+
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16+
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17+
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18+
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19+
*
20+
*/
21+
22+
/* This module implements the Qualcomm Atheros SPI protocol for
23+
* kernel-based SPI device.
24+
*/
25+
26+
#include <linux/init.h>
27+
#include <linux/module.h>
28+
#include <linux/moduleparam.h>
29+
#include <linux/spi/spi.h>
30+
#include <linux/version.h>
31+
32+
#include "qca_7k.h"
33+
34+
void
35+
qcaspi_spi_error(struct qcaspi *qca)
36+
{
37+
if (qca->sync != QCASPI_SYNC_READY)
38+
return;
39+
40+
netdev_err(qca->net_dev, "spi error\n");
41+
qca->sync = QCASPI_SYNC_UNKNOWN;
42+
qca->stats.spi_err++;
43+
}
44+
45+
int
46+
qcaspi_read_register(struct qcaspi *qca, u16 reg, u16 *result)
47+
{
48+
__be16 rx_data;
49+
__be16 tx_data;
50+
struct spi_transfer *transfer;
51+
struct spi_message *msg;
52+
int ret;
53+
54+
tx_data = cpu_to_be16(QCA7K_SPI_READ | QCA7K_SPI_INTERNAL | reg);
55+
56+
if (qca->legacy_mode) {
57+
msg = &qca->spi_msg1;
58+
transfer = &qca->spi_xfer1;
59+
transfer->tx_buf = &tx_data;
60+
transfer->rx_buf = NULL;
61+
transfer->len = QCASPI_CMD_LEN;
62+
spi_sync(qca->spi_dev, msg);
63+
} else {
64+
msg = &qca->spi_msg2;
65+
transfer = &qca->spi_xfer2[0];
66+
transfer->tx_buf = &tx_data;
67+
transfer->rx_buf = NULL;
68+
transfer->len = QCASPI_CMD_LEN;
69+
transfer = &qca->spi_xfer2[1];
70+
}
71+
transfer->tx_buf = NULL;
72+
transfer->rx_buf = &rx_data;
73+
transfer->len = QCASPI_CMD_LEN;
74+
ret = spi_sync(qca->spi_dev, msg);
75+
76+
if (!ret)
77+
ret = msg->status;
78+
79+
if (ret)
80+
qcaspi_spi_error(qca);
81+
else
82+
*result = be16_to_cpu(rx_data);
83+
84+
return ret;
85+
}
86+
87+
int
88+
qcaspi_write_register(struct qcaspi *qca, u16 reg, u16 value)
89+
{
90+
__be16 tx_data[2];
91+
struct spi_transfer *transfer;
92+
struct spi_message *msg;
93+
int ret;
94+
95+
tx_data[0] = cpu_to_be16(QCA7K_SPI_WRITE | QCA7K_SPI_INTERNAL | reg);
96+
tx_data[1] = cpu_to_be16(value);
97+
98+
if (qca->legacy_mode) {
99+
msg = &qca->spi_msg1;
100+
transfer = &qca->spi_xfer1;
101+
transfer->tx_buf = &tx_data[0];
102+
transfer->rx_buf = NULL;
103+
transfer->len = QCASPI_CMD_LEN;
104+
spi_sync(qca->spi_dev, msg);
105+
} else {
106+
msg = &qca->spi_msg2;
107+
transfer = &qca->spi_xfer2[0];
108+
transfer->tx_buf = &tx_data[0];
109+
transfer->rx_buf = NULL;
110+
transfer->len = QCASPI_CMD_LEN;
111+
transfer = &qca->spi_xfer2[1];
112+
}
113+
transfer->tx_buf = &tx_data[1];
114+
transfer->rx_buf = NULL;
115+
transfer->len = QCASPI_CMD_LEN;
116+
ret = spi_sync(qca->spi_dev, msg);
117+
118+
if (!ret)
119+
ret = msg->status;
120+
121+
if (ret)
122+
qcaspi_spi_error(qca);
123+
124+
return ret;
125+
}
126+
127+
int
128+
qcaspi_tx_cmd(struct qcaspi *qca, u16 cmd)
129+
{
130+
__be16 tx_data;
131+
struct spi_message *msg = &qca->spi_msg1;
132+
struct spi_transfer *transfer = &qca->spi_xfer1;
133+
int ret;
134+
135+
tx_data = cpu_to_be16(cmd);
136+
transfer->len = sizeof(tx_data);
137+
transfer->tx_buf = &tx_data;
138+
transfer->rx_buf = NULL;
139+
140+
ret = spi_sync(qca->spi_dev, msg);
141+
142+
if (!ret)
143+
ret = msg->status;
144+
145+
if (ret)
146+
qcaspi_spi_error(qca);
147+
148+
return ret;
149+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright (c) 2011, 2012, Qualcomm Atheros Communications Inc.
3+
* Copyright (c) 2014, I2SE GmbH
4+
*
5+
* Permission to use, copy, modify, and/or distribute this software
6+
* for any purpose with or without fee is hereby granted, provided
7+
* that the above copyright notice and this permission notice appear
8+
* in all copies.
9+
*
10+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11+
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12+
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
13+
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
14+
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15+
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
16+
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17+
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18+
*
19+
*/
20+
21+
/* Qualcomm Atheros SPI register definition.
22+
*
23+
* This module is designed to define the Qualcomm Atheros SPI
24+
* register placeholders.
25+
*/
26+
27+
#ifndef _QCA_7K_H
28+
#define _QCA_7K_H
29+
30+
#include <linux/types.h>
31+
32+
#include "qca_spi.h"
33+
34+
#define QCA7K_SPI_READ (1 << 15)
35+
#define QCA7K_SPI_WRITE (0 << 15)
36+
#define QCA7K_SPI_INTERNAL (1 << 14)
37+
#define QCA7K_SPI_EXTERNAL (0 << 14)
38+
39+
#define QCASPI_CMD_LEN 2
40+
#define QCASPI_HW_PKT_LEN 4
41+
#define QCASPI_HW_BUF_LEN 0xC5B
42+
43+
/* SPI registers; */
44+
#define SPI_REG_BFR_SIZE 0x0100
45+
#define SPI_REG_WRBUF_SPC_AVA 0x0200
46+
#define SPI_REG_RDBUF_BYTE_AVA 0x0300
47+
#define SPI_REG_SPI_CONFIG 0x0400
48+
#define SPI_REG_SPI_STATUS 0x0500
49+
#define SPI_REG_INTR_CAUSE 0x0C00
50+
#define SPI_REG_INTR_ENABLE 0x0D00
51+
#define SPI_REG_RDBUF_WATERMARK 0x1200
52+
#define SPI_REG_WRBUF_WATERMARK 0x1300
53+
#define SPI_REG_SIGNATURE 0x1A00
54+
#define SPI_REG_ACTION_CTRL 0x1B00
55+
56+
/* SPI_CONFIG register definition; */
57+
#define QCASPI_SLAVE_RESET_BIT (1 << 6)
58+
59+
/* INTR_CAUSE/ENABLE register definition. */
60+
#define SPI_INT_WRBUF_BELOW_WM (1 << 10)
61+
#define SPI_INT_CPU_ON (1 << 6)
62+
#define SPI_INT_ADDR_ERR (1 << 3)
63+
#define SPI_INT_WRBUF_ERR (1 << 2)
64+
#define SPI_INT_RDBUF_ERR (1 << 1)
65+
#define SPI_INT_PKT_AVLBL (1 << 0)
66+
67+
void qcaspi_spi_error(struct qcaspi *qca);
68+
int qcaspi_read_register(struct qcaspi *qca, u16 reg, u16 *result);
69+
int qcaspi_write_register(struct qcaspi *qca, u16 reg, u16 value);
70+
int qcaspi_tx_cmd(struct qcaspi *qca, u16 cmd);
71+
72+
#endif /* _QCA_7K_H */

0 commit comments

Comments
 (0)