Re: [PATCH v4 3/5] net: ax88796c: ASIX AX88796C SPI Ethernet Adapter Driver
flat view
From: Marc Kleine-Budde <mkl@pengutronix.de>
Date: 2020-10-29 17:36:01
Also in:
linux-arm-kernel, linux-devicetree, linux-samsung-soc, lkml
Possibly related (same subject, not in this thread)
- 2020-10-29 · Re: [PATCH v4 3/5] net: ax88796c: ASIX AX88796C SPI Ethernet Adapter Driver · Lukasz Stelmach <l.stelmach@samsung.com>
- 2020-10-29 · Re: [PATCH v4 3/5] net: ax88796c: ASIX AX88796C SPI Ethernet Adapter Driver · Andrew Lunn <andrew@lunn.ch>
- 2020-10-29 · Re: [PATCH v4 3/5] net: ax88796c: ASIX AX88796C SPI Ethernet Adapter Driver · Lukasz Stelmach <l.stelmach@samsung.com>
- 2020-10-29 · Re: [PATCH v4 3/5] net: ax88796c: ASIX AX88796C SPI Ethernet Adapter Driver · Lukasz Stelmach <l.stelmach@samsung.com>
On 10/28/20 10:40 PM, Łukasz Stelmach wrote:
ASIX AX88796[1] is a versatile ethernet adapter chip, that can be connected to a CPU with a 8/16-bit bus or with an SPI. This driver supports SPI connection. The driver has been ported from the vendor kernel for ARTIK5[2] boards. Several changes were made to adapt it to the current kernel which include: + updated DT configuration, + clock configuration moved to DT, + new timer, ethtool and gpio APIs, + dev_* instead of pr_* and custom printk() wrappers, + removed awkward vendor power managemtn. [1] https://www.asix.com.tw/products.php?op=pItemdetail&PItemID=104;65;86&PLine=65 [2] https://git.tizen.org/cgit/profile/common/platform/kernel/linux-3.10-artik/ The other ax88796 driver is for NE2000 compatible AX88796L chip. These chips are not compatible. Hence, two separate drivers are required. Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com> --- MAINTAINERS | 6 + drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/asix/Kconfig | 22 + drivers/net/ethernet/asix/Makefile | 6 + drivers/net/ethernet/asix/ax88796c_ioctl.c | 197 ++++ drivers/net/ethernet/asix/ax88796c_ioctl.h | 26 + drivers/net/ethernet/asix/ax88796c_main.c | 1144 ++++++++++++++++++++ drivers/net/ethernet/asix/ax88796c_main.h | 578 ++++++++++ drivers/net/ethernet/asix/ax88796c_spi.c | 111 ++ drivers/net/ethernet/asix/ax88796c_spi.h | 69 ++ 11 files changed, 2161 insertions(+) create mode 100644 drivers/net/ethernet/asix/Kconfig create mode 100644 drivers/net/ethernet/asix/Makefile create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.c create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.h create mode 100644 drivers/net/ethernet/asix/ax88796c_main.c create mode 100644 drivers/net/ethernet/asix/ax88796c_main.h create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.c create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.h
[...]
quoted hunk ↗ jump to hunk
+enum watchdog_state { + chk_link = 0, + chk_cable, + ax_nop, +}; + +struct ax88796c_device { + struct resource *addr_res; /* resources found */ + struct resource *addr_req; /* resources requested */ + struct resource *irq_res; + + struct spi_device *spi; + struct net_device *ndev; + struct net_device_stats stats; + + struct timer_list watchdog; + enum watchdog_state w_state; + size_t w_ticks;
are these used?
quoted hunk ↗ jump to hunk
+ + struct work_struct ax_work; + + struct mutex spi_lock; /* device access */ + + struct sk_buff_head tx_wait_q; + + struct axspi_data ax_spi; + + struct mii_bus *mdiobus; + struct phy_device *phydev; + + int msg_enable; + + u16 seq_num; + + u8 multi_filter[AX_MCAST_FILTER_SIZE]; + + int link; + int speed; + int duplex; + int pause; + int asym_pause; + int flowctrl; + #define AX_FC_NONE 0 + #define AX_FC_RX BIT(0) + #define AX_FC_TX BIT(1) + #define AX_FC_ANEG BIT(2) + + unsigned long capabilities; + #define AX_CAP_DMA BIT(0) + #define AX_CAP_COMP BIT(1) + #define AX_CAP_BIDIR BIT(2) + + u8 plat_endian; + #define PLAT_LITTLE_ENDIAN 0 + #define PLAT_BIG_ENDIAN 1 + + unsigned long flags; + #define EVENT_INTR BIT(0) + #define EVENT_TX BIT(1) + #define EVENT_SET_MULTI BIT(2) + +}; + +#define to_ax88796c_device(ndev) ((struct ax88796c_device *)netdev_priv(ndev)) + +enum skb_state { + illegal = 0, + tx_done, + rx_done, + rx_err, +}; + +struct skb_data { + enum skb_state state; + struct net_device *ndev; + struct sk_buff *skb; + size_t len; + dma_addr_t phy_addr;
unused? [...]
quoted hunk ↗ jump to hunk
diff --git a/drivers/net/ethernet/asix/ax88796c_spi.c b/drivers/net/ethernet/asix/ax88796c_spi.c new file mode 100644 index 000000000000..1a20bbeb4dc1 --- /dev/null +++ b/drivers/net/ethernet/asix/ax88796c_spi.c@@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2010 ASIX Electronics Corporation + * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * + * ASIX AX88796C SPI Fast Ethernet Linux driver + */ + +#define pr_fmt(fmt) "ax88796c: " fmt + +#include <linux/string.h> +#include <linux/spi/spi.h> + +#include "ax88796c_spi.h" + +/* driver bus management functions */ +int axspi_wakeup(const struct axspi_data *ax_spi) +{ + u8 tx_buf; + int ret; + + tx_buf = AX_SPICMD_EXIT_PWD; /* OP */ + ret = spi_write(ax_spi->spi, &tx_buf, 1);
spi_write() needs a DMA safe buffer.
quoted hunk ↗ jump to hunk
+ if (ret) + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); + return ret; +} + +int axspi_read_status(const struct axspi_data *ax_spi, struct spi_status *status) +{ + u8 tx_buf; + int ret; + + /* OP */ + tx_buf = AX_SPICMD_READ_STATUS; + ret = spi_write_then_read(ax_spi->spi, &tx_buf, 1, (u8 *)&status, 3); + if (ret) + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); + else + le16_to_cpus(&status->isr); + + return ret; +} + +int axspi_read_rxq(struct axspi_data *ax_spi, void *data, int len) +{ + struct spi_transfer *xfer = ax_spi->spi_rx_xfer; + int ret; + + memcpy(ax_spi->cmd_buf, rx_cmd_buf, 5); + + xfer->tx_buf = ax_spi->cmd_buf; + xfer->rx_buf = NULL; + xfer->len = ax_spi->comp ? 2 : 5; + xfer->bits_per_word = 8; + spi_message_add_tail(xfer, &ax_spi->rx_msg); + + xfer++; + xfer->rx_buf = data; + xfer->tx_buf = NULL; + xfer->len = len; + xfer->bits_per_word = 8; + spi_message_add_tail(xfer, &ax_spi->rx_msg); + ret = spi_sync(ax_spi->spi, &ax_spi->rx_msg); + if (ret) + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); + + return ret; +} + +int axspi_write_txq(const struct axspi_data *ax_spi, void *data, int len) +{ + return spi_write(ax_spi->spi, data, len); +} + +u16 axspi_read_reg(const struct axspi_data *ax_spi, u8 reg) +{ + u8 tx_buf[4]; + u16 rx_buf = 0; + int ret; + int len = ax_spi->comp ? 3 : 4; + + tx_buf[0] = 0x03; /* OP code read register */ + tx_buf[1] = reg; /* register address */ + tx_buf[2] = 0xFF; /* dumy cycle */ + tx_buf[3] = 0xFF; /* dumy cycle */ + ret = spi_write_then_read(ax_spi->spi, tx_buf, len, (u8 *)&rx_buf, 2); + if (ret) + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); + else + le16_to_cpus(&rx_buf); + + return rx_buf; +} + +int axspi_write_reg(const struct axspi_data *ax_spi, u8 reg, u16 value) +{ + u8 tx_buf[4]; + int ret; + + tx_buf[0] = AX_SPICMD_WRITE_REG; /* OP code read register */ + tx_buf[1] = reg; /* register address */ + tx_buf[2] = value; + tx_buf[3] = value >> 8; + + ret = spi_write(ax_spi->spi, tx_buf, 4);
I think you need DMA safe mem for spi_write(). Marc -- Pengutronix e.K. | Marc Kleine-Budde | Embedded Linux | https://www.pengutronix.de | Vertretung West/Dortmund | Phone: +49-231-2826-924 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Attachments
- signature.asc [application/pgp-signature] 488 bytes