提交 f4b992b4 编写于 作者: D David S. Miller

Merge branch 'net-ks8851-Unify-KS8851-SPI-and-MLL-drivers'

Marek Vasut says:

====================
net: ks8851: Unify KS8851 SPI and MLL drivers

The KS8851SNL/SNLI and KS8851-16MLL/MLLI/MLLU are very much the same pieces
of silicon, except the former has an SPI interface, while the later has a
parallel bus interface. Thus far, Linux has two separate drivers for each
and they are diverging considerably.

This series unifies them into a single driver with small SPI and parallel
bus specific parts. The approach here is to first separate out the SPI
specific parts into a separate file, then add parallel bus accessors in
another separate file and then finally remove the old parallel bus driver.
The reason for replacing the old parallel bus driver is because the SPI
bus driver is much higher quality.

Note that I dropped "net: ks8851: Drop define debug and pr_fmt()" for now,
will send it separatelly later.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
......@@ -38,6 +38,8 @@ config KS8851_MLL
tristate "Micrel KS8851 MLL"
depends on HAS_IOMEM
select MII
select CRC32
select EEPROM_93CX6
---help---
This platform driver is for Micrel KS8851 Address/data bus
multiplexed network chip.
......
......@@ -5,5 +5,7 @@
obj-$(CONFIG_KS8842) += ks8842.o
obj-$(CONFIG_KS8851) += ks8851.o
ks8851-objs = ks8851_common.o ks8851_spi.o
obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
ks8851_mll-objs = ks8851_common.o ks8851_par.o
obj-$(CONFIG_KSZ884X_PCI) += ksz884x.o
......@@ -7,6 +7,11 @@
* KS8851 register definitions
*/
#ifndef __KS8851_H__
#define __KS8851_H__
#include <linux/eeprom_93cx6.h>
#define KS_CCR 0x08
#define CCR_LE (1 << 10) /* KSZ8851-16MLL */
#define CCR_EEPROM (1 << 9)
......@@ -19,7 +24,7 @@
#define CCR_32PIN (1 << 0) /* KSZ8851SNL */
/* MAC address registers */
#define KS_MAR(_m) (0x15 - (_m))
#define KS_MAR(_m) (0x14 - (_m))
#define KS_MARL 0x10
#define KS_MARM 0x12
#define KS_MARH 0x14
......@@ -300,3 +305,147 @@
#define TXFR_TXIC (1 << 15)
#define TXFR_TXFID_MASK (0x3f << 0)
#define TXFR_TXFID_SHIFT (0)
/**
* struct ks8851_rxctrl - KS8851 driver rx control
* @mchash: Multicast hash-table data.
* @rxcr1: KS_RXCR1 register setting
* @rxcr2: KS_RXCR2 register setting
*
* Representation of the settings needs to control the receive filtering
* such as the multicast hash-filter and the receive register settings. This
* is used to make the job of working out if the receive settings change and
* then issuing the new settings to the worker that will send the necessary
* commands.
*/
struct ks8851_rxctrl {
u16 mchash[4];
u16 rxcr1;
u16 rxcr2;
};
/**
* union ks8851_tx_hdr - tx header data
* @txb: The header as bytes
* @txw: The header as 16bit, little-endian words
*
* A dual representation of the tx header data to allow
* access to individual bytes, and to allow 16bit accesses
* with 16bit alignment.
*/
union ks8851_tx_hdr {
u8 txb[6];
__le16 txw[3];
};
/**
* struct ks8851_net - KS8851 driver private data
* @netdev: The network device we're bound to
* @statelock: Lock on this structure for tx list.
* @mii: The MII state information for the mii calls.
* @rxctrl: RX settings for @rxctrl_work.
* @rxctrl_work: Work queue for updating RX mode and multicast lists
* @txq: Queue of packets for transmission.
* @txh: Space for generating packet TX header in DMA-able data
* @rxd: Space for receiving SPI data, in DMA-able space.
* @txd: Space for transmitting SPI data, in DMA-able space.
* @msg_enable: The message flags controlling driver output (see ethtool).
* @fid: Incrementing frame id tag.
* @rc_ier: Cached copy of KS_IER.
* @rc_ccr: Cached copy of KS_CCR.
* @rc_rxqcr: Cached copy of KS_RXQCR.
* @eeprom: 93CX6 EEPROM state for accessing on-board EEPROM.
* @vdd_reg: Optional regulator supplying the chip
* @vdd_io: Optional digital power supply for IO
* @gpio: Optional reset_n gpio
* @lock: Bus access lock callback
* @unlock: Bus access unlock callback
* @rdreg16: 16bit register read callback
* @wrreg16: 16bit register write callback
* @rdfifo: FIFO read callback
* @wrfifo: FIFO write callback
* @start_xmit: start_xmit() implementation callback
* @rx_skb: rx_skb() implementation callback
* @flush_tx_work: flush_tx_work() implementation callback
*
* The @statelock is used to protect information in the structure which may
* need to be accessed via several sources, such as the network driver layer
* or one of the work queues.
*
* We align the buffers we may use for rx/tx to ensure that if the SPI driver
* wants to DMA map them, it will not have any problems with data the driver
* modifies.
*/
struct ks8851_net {
struct net_device *netdev;
spinlock_t statelock;
union ks8851_tx_hdr txh ____cacheline_aligned;
u8 rxd[8];
u8 txd[8];
u32 msg_enable ____cacheline_aligned;
u16 tx_space;
u8 fid;
u16 rc_ier;
u16 rc_rxqcr;
u16 rc_ccr;
struct mii_if_info mii;
struct ks8851_rxctrl rxctrl;
struct work_struct rxctrl_work;
struct sk_buff_head txq;
struct eeprom_93cx6 eeprom;
struct regulator *vdd_reg;
struct regulator *vdd_io;
int gpio;
void (*lock)(struct ks8851_net *ks,
unsigned long *flags);
void (*unlock)(struct ks8851_net *ks,
unsigned long *flags);
unsigned int (*rdreg16)(struct ks8851_net *ks,
unsigned int reg);
void (*wrreg16)(struct ks8851_net *ks,
unsigned int reg, unsigned int val);
void (*rdfifo)(struct ks8851_net *ks, u8 *buff,
unsigned int len);
void (*wrfifo)(struct ks8851_net *ks,
struct sk_buff *txp, bool irq);
netdev_tx_t (*start_xmit)(struct sk_buff *skb,
struct net_device *dev);
void (*rx_skb)(struct ks8851_net *ks,
struct sk_buff *skb);
void (*flush_tx_work)(struct ks8851_net *ks);
};
int ks8851_probe_common(struct net_device *netdev, struct device *dev,
int msg_en);
int ks8851_remove_common(struct device *dev);
int ks8851_suspend(struct device *dev);
int ks8851_resume(struct device *dev);
static __maybe_unused SIMPLE_DEV_PM_OPS(ks8851_pm_ops,
ks8851_suspend, ks8851_resume);
/**
* ks8851_done_tx - update and then free skbuff after transmitting
* @ks: The device state
* @txb: The buffer transmitted
*/
static void __maybe_unused ks8851_done_tx(struct ks8851_net *ks,
struct sk_buff *txb)
{
struct net_device *dev = ks->netdev;
dev->stats.tx_bytes += txb->len;
dev->stats.tx_packets++;
dev_kfree_skb(txb);
}
#endif /* __KS8851_H__ */
此差异已折叠。
// SPDX-License-Identifier: GPL-2.0-only
/* drivers/net/ethernet/micrel/ks8851.c
*
* Copyright 2009 Simtec Electronics
* http://www.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define DEBUG
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/iopoll.h>
#include <linux/mii.h>
#include <linux/platform_device.h>
#include <linux/of_net.h>
#include "ks8851.h"
static int msg_enable;
#define BE3 0x8000 /* Byte Enable 3 */
#define BE2 0x4000 /* Byte Enable 2 */
#define BE1 0x2000 /* Byte Enable 1 */
#define BE0 0x1000 /* Byte Enable 0 */
/**
* struct ks8851_net_par - KS8851 Parallel driver private data
* @ks8851: KS8851 driver common private data
* @lock: Lock to ensure that the device is not accessed when busy.
* @hw_addr : start address of data register.
* @hw_addr_cmd : start address of command register.
* @cmd_reg_cache : command register cached.
*
* The @lock ensures that the chip is protected when certain operations are
* in progress. When the read or write packet transfer is in progress, most
* of the chip registers are not accessible until the transfer is finished
* and the DMA has been de-asserted.
*/
struct ks8851_net_par {
struct ks8851_net ks8851;
spinlock_t lock;
void __iomem *hw_addr;
void __iomem *hw_addr_cmd;
u16 cmd_reg_cache;
};
#define to_ks8851_par(ks) container_of((ks), struct ks8851_net_par, ks8851)
/**
* ks8851_lock_par - register access lock
* @ks: The chip state
* @flags: Spinlock flags
*
* Claim chip register access lock
*/
static void ks8851_lock_par(struct ks8851_net *ks, unsigned long *flags)
{
struct ks8851_net_par *ksp = to_ks8851_par(ks);
spin_lock_irqsave(&ksp->lock, *flags);
}
/**
* ks8851_unlock_par - register access unlock
* @ks: The chip state
* @flags: Spinlock flags
*
* Release chip register access lock
*/
static void ks8851_unlock_par(struct ks8851_net *ks, unsigned long *flags)
{
struct ks8851_net_par *ksp = to_ks8851_par(ks);
spin_unlock_irqrestore(&ksp->lock, *flags);
}
/**
* ks_check_endian - Check whether endianness of the bus is correct
* @ks : The chip information
*
* The KS8851-16MLL EESK pin allows selecting the endianness of the 16bit
* bus. To maintain optimum performance, the bus endianness should be set
* such that it matches the endianness of the CPU.
*/
static int ks_check_endian(struct ks8851_net *ks)
{
struct ks8851_net_par *ksp = to_ks8851_par(ks);
u16 cider;
/*
* Read CIDER register first, however read it the "wrong" way around.
* If the endian strap on the KS8851-16MLL in incorrect and the chip
* is operating in different endianness than the CPU, then the meaning
* of BE[3:0] byte-enable bits is also swapped such that:
* BE[3,2,1,0] becomes BE[1,0,3,2]
*
* Luckily for us, the byte-enable bits are the top four MSbits of
* the address register and the CIDER register is at offset 0xc0.
* Hence, by reading address 0xc0c0, which is not impacted by endian
* swapping, we assert either BE[3:2] or BE[1:0] while reading the
* CIDER register.
*
* If the bus configuration is correct, reading 0xc0c0 asserts
* BE[3:2] and this read returns 0x0000, because to read register
* with bottom two LSbits of address set to 0, BE[1:0] must be
* asserted.
*
* If the bus configuration is NOT correct, reading 0xc0c0 asserts
* BE[1:0] and this read returns non-zero 0x8872 value.
*/
iowrite16(BE3 | BE2 | KS_CIDER, ksp->hw_addr_cmd);
cider = ioread16(ksp->hw_addr);
if (!cider)
return 0;
netdev_err(ks->netdev, "incorrect EESK endian strap setting\n");
return -EINVAL;
}
/**
* ks8851_wrreg16_par - write 16bit register value to chip
* @ks: The chip state
* @reg: The register address
* @val: The value to write
*
* Issue a write to put the value @val into the register specified in @reg.
*/
static void ks8851_wrreg16_par(struct ks8851_net *ks, unsigned int reg,
unsigned int val)
{
struct ks8851_net_par *ksp = to_ks8851_par(ks);
ksp->cmd_reg_cache = (u16)reg | ((BE1 | BE0) << (reg & 0x02));
iowrite16(ksp->cmd_reg_cache, ksp->hw_addr_cmd);
iowrite16(val, ksp->hw_addr);
}
/**
* ks8851_rdreg16_par - read 16 bit register from chip
* @ks: The chip information
* @reg: The register address
*
* Read a 16bit register from the chip, returning the result
*/
static unsigned int ks8851_rdreg16_par(struct ks8851_net *ks, unsigned int reg)
{
struct ks8851_net_par *ksp = to_ks8851_par(ks);
ksp->cmd_reg_cache = (u16)reg | ((BE1 | BE0) << (reg & 0x02));
iowrite16(ksp->cmd_reg_cache, ksp->hw_addr_cmd);
return ioread16(ksp->hw_addr);
}
/**
* ks8851_rdfifo_par - read data from the receive fifo
* @ks: The device state.
* @buff: The buffer address
* @len: The length of the data to read
*
* Issue an RXQ FIFO read command and read the @len amount of data from
* the FIFO into the buffer specified by @buff.
*/
static void ks8851_rdfifo_par(struct ks8851_net *ks, u8 *buff, unsigned int len)
{
struct ks8851_net_par *ksp = to_ks8851_par(ks);
netif_dbg(ks, rx_status, ks->netdev,
"%s: %d@%p\n", __func__, len, buff);
ioread16_rep(ksp->hw_addr, (u16 *)buff + 1, len / 2);
}
/**
* ks8851_wrfifo_par - write packet to TX FIFO
* @ks: The device state.
* @txp: The sk_buff to transmit.
* @irq: IRQ on completion of the packet.
*
* Send the @txp to the chip. This means creating the relevant packet header
* specifying the length of the packet and the other information the chip
* needs, such as IRQ on completion. Send the header and the packet data to
* the device.
*/
static void ks8851_wrfifo_par(struct ks8851_net *ks, struct sk_buff *txp,
bool irq)
{
struct ks8851_net_par *ksp = to_ks8851_par(ks);
unsigned int len = ALIGN(txp->len, 4);
unsigned int fid = 0;
netif_dbg(ks, tx_queued, ks->netdev, "%s: skb %p, %d@%p, irq %d\n",
__func__, txp, txp->len, txp->data, irq);
fid = ks->fid++;
fid &= TXFR_TXFID_MASK;
if (irq)
fid |= TXFR_TXIC; /* irq on completion */
iowrite16(fid, ksp->hw_addr);
iowrite16(txp->len, ksp->hw_addr);
iowrite16_rep(ksp->hw_addr, txp->data, len / 2);
}
/**
* ks8851_rx_skb_par - receive skbuff
* @ks: The device state.
* @skb: The skbuff
*/
static void ks8851_rx_skb_par(struct ks8851_net *ks, struct sk_buff *skb)
{
netif_rx(skb);
}
static unsigned int ks8851_rdreg16_par_txqcr(struct ks8851_net *ks)
{
return ks8851_rdreg16_par(ks, KS_TXQCR);
}
/**
* ks8851_start_xmit_par - transmit packet
* @skb: The buffer to transmit
* @dev: The device used to transmit the packet.
*
* Called by the network layer to transmit the @skb. Queue the packet for
* the device and schedule the necessary work to transmit the packet when
* it is free.
*
* We do this to firstly avoid sleeping with the network device locked,
* and secondly so we can round up more than one packet to transmit which
* means we can try and avoid generating too many transmit done interrupts.
*/
static netdev_tx_t ks8851_start_xmit_par(struct sk_buff *skb,
struct net_device *dev)
{
struct ks8851_net *ks = netdev_priv(dev);
netdev_tx_t ret = NETDEV_TX_OK;
unsigned long flags;
unsigned int txqcr;
u16 txmir;
int err;
netif_dbg(ks, tx_queued, ks->netdev,
"%s: skb %p, %d@%p\n", __func__, skb, skb->len, skb->data);
ks8851_lock_par(ks, &flags);
txmir = ks8851_rdreg16_par(ks, KS_TXMIR) & 0x1fff;
if (likely(txmir >= skb->len + 12)) {
ks8851_wrreg16_par(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA);
ks8851_wrfifo_par(ks, skb, false);
ks8851_wrreg16_par(ks, KS_RXQCR, ks->rc_rxqcr);
ks8851_wrreg16_par(ks, KS_TXQCR, TXQCR_METFE);
err = readx_poll_timeout_atomic(ks8851_rdreg16_par_txqcr, ks,
txqcr, !(txqcr & TXQCR_METFE),
5, 1000000);
if (err)
ret = NETDEV_TX_BUSY;
ks8851_done_tx(ks, skb);
} else {
ret = NETDEV_TX_BUSY;
}
ks8851_unlock_par(ks, &flags);
return ret;
}
static int ks8851_probe_par(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ks8851_net_par *ksp;
struct net_device *netdev;
struct ks8851_net *ks;
int ret;
netdev = devm_alloc_etherdev(dev, sizeof(struct ks8851_net_par));
if (!netdev)
return -ENOMEM;
ks = netdev_priv(netdev);
ks->lock = ks8851_lock_par;
ks->unlock = ks8851_unlock_par;
ks->rdreg16 = ks8851_rdreg16_par;
ks->wrreg16 = ks8851_wrreg16_par;
ks->rdfifo = ks8851_rdfifo_par;
ks->wrfifo = ks8851_wrfifo_par;
ks->start_xmit = ks8851_start_xmit_par;
ks->rx_skb = ks8851_rx_skb_par;
#define STD_IRQ (IRQ_LCI | /* Link Change */ \
IRQ_RXI | /* RX done */ \
IRQ_RXPSI) /* RX process stop */
ks->rc_ier = STD_IRQ;
ksp = to_ks8851_par(ks);
spin_lock_init(&ksp->lock);
ksp->hw_addr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ksp->hw_addr))
return PTR_ERR(ksp->hw_addr);
ksp->hw_addr_cmd = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(ksp->hw_addr_cmd))
return PTR_ERR(ksp->hw_addr_cmd);
ret = ks_check_endian(ks);
if (ret)
return ret;
netdev->irq = platform_get_irq(pdev, 0);
return ks8851_probe_common(netdev, dev, msg_enable);
}
static int ks8851_remove_par(struct platform_device *pdev)
{
return ks8851_remove_common(&pdev->dev);
}
static const struct of_device_id ks8851_match_table[] = {
{ .compatible = "micrel,ks8851-mll" },
{ }
};
MODULE_DEVICE_TABLE(of, ks8851_match_table);
static struct platform_driver ks8851_driver = {
.driver = {
.name = "ks8851",
.of_match_table = ks8851_match_table,
.pm = &ks8851_pm_ops,
},
.probe = ks8851_probe_par,
.remove = ks8851_remove_par,
};
module_platform_driver(ks8851_driver);
MODULE_DESCRIPTION("KS8851 Network driver");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_LICENSE("GPL");
module_param_named(message, msg_enable, int, 0);
MODULE_PARM_DESC(message, "Message verbosity level (0=none, 31=all)");
// SPDX-License-Identifier: GPL-2.0-only
/* drivers/net/ethernet/micrel/ks8851.c
*
* Copyright 2009 Simtec Electronics
* http://www.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define DEBUG
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/cache.h>
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of_net.h>
#include "ks8851.h"
static int msg_enable;
/**
* struct ks8851_net_spi - KS8851 SPI driver private data
* @lock: Lock to ensure that the device is not accessed when busy.
* @tx_work: Work queue for tx packets
* @ks8851: KS8851 driver common private data
* @spidev: The spi device we're bound to.
* @spi_msg1: pre-setup SPI transfer with one message, @spi_xfer1.
* @spi_msg2: pre-setup SPI transfer with two messages, @spi_xfer2.
* @spi_xfer1: @spi_msg1 SPI transfer structure
* @spi_xfer2: @spi_msg2 SPI transfer structure
*
* The @lock ensures that the chip is protected when certain operations are
* in progress. When the read or write packet transfer is in progress, most
* of the chip registers are not ccessible until the transfer is finished and
* the DMA has been de-asserted.
*/
struct ks8851_net_spi {
struct ks8851_net ks8851;
struct mutex lock;
struct work_struct tx_work;
struct spi_device *spidev;
struct spi_message spi_msg1;
struct spi_message spi_msg2;
struct spi_transfer spi_xfer1;
struct spi_transfer spi_xfer2[2];
};
#define to_ks8851_spi(ks) container_of((ks), struct ks8851_net_spi, ks8851)
/* SPI frame opcodes */
#define KS_SPIOP_RD 0x00
#define KS_SPIOP_WR 0x40
#define KS_SPIOP_RXFIFO 0x80
#define KS_SPIOP_TXFIFO 0xC0
/* shift for byte-enable data */
#define BYTE_EN(_x) ((_x) << 2)
/* turn register number and byte-enable mask into data for start of packet */
#define MK_OP(_byteen, _reg) \
(BYTE_EN(_byteen) | (_reg) << (8 + 2) | (_reg) >> 6)
/**
* ks8851_lock_spi - register access lock
* @ks: The chip state
* @flags: Spinlock flags
*
* Claim chip register access lock
*/
static void ks8851_lock_spi(struct ks8851_net *ks, unsigned long *flags)
{
struct ks8851_net_spi *kss = to_ks8851_spi(ks);
mutex_lock(&kss->lock);
}
/**
* ks8851_unlock_spi - register access unlock
* @ks: The chip state
* @flags: Spinlock flags
*
* Release chip register access lock
*/
static void ks8851_unlock_spi(struct ks8851_net *ks, unsigned long *flags)
{
struct ks8851_net_spi *kss = to_ks8851_spi(ks);
mutex_unlock(&kss->lock);
}
/* SPI register read/write calls.
*
* All these calls issue SPI transactions to access the chip's registers. They
* all require that the necessary lock is held to prevent accesses when the
* chip is busy transferring packet data (RX/TX FIFO accesses).
*/
/**
* ks8851_wrreg16_spi - write 16bit register value to chip via SPI
* @ks: The chip state
* @reg: The register address
* @val: The value to write
*
* Issue a write to put the value @val into the register specified in @reg.
*/
static void ks8851_wrreg16_spi(struct ks8851_net *ks, unsigned int reg,
unsigned int val)
{
struct ks8851_net_spi *kss = to_ks8851_spi(ks);
struct spi_transfer *xfer = &kss->spi_xfer1;
struct spi_message *msg = &kss->spi_msg1;
__le16 txb[2];
int ret;
txb[0] = cpu_to_le16(MK_OP(reg & 2 ? 0xC : 0x03, reg) | KS_SPIOP_WR);
txb[1] = cpu_to_le16(val);
xfer->tx_buf = txb;
xfer->rx_buf = NULL;
xfer->len = 4;
ret = spi_sync(kss->spidev, msg);
if (ret < 0)
netdev_err(ks->netdev, "spi_sync() failed\n");
}
/**
* ks8851_rdreg - issue read register command and return the data
* @ks: The device state
* @op: The register address and byte enables in message format.
* @rxb: The RX buffer to return the result into
* @rxl: The length of data expected.
*
* This is the low level read call that issues the necessary spi message(s)
* to read data from the register specified in @op.
*/
static void ks8851_rdreg(struct ks8851_net *ks, unsigned int op,
u8 *rxb, unsigned int rxl)
{
struct ks8851_net_spi *kss = to_ks8851_spi(ks);
struct spi_transfer *xfer;
struct spi_message *msg;
__le16 *txb = (__le16 *)ks->txd;
u8 *trx = ks->rxd;
int ret;
txb[0] = cpu_to_le16(op | KS_SPIOP_RD);
if (kss->spidev->master->flags & SPI_MASTER_HALF_DUPLEX) {
msg = &kss->spi_msg2;
xfer = kss->spi_xfer2;
xfer->tx_buf = txb;
xfer->rx_buf = NULL;
xfer->len = 2;
xfer++;
xfer->tx_buf = NULL;
xfer->rx_buf = trx;
xfer->len = rxl;
} else {
msg = &kss->spi_msg1;
xfer = &kss->spi_xfer1;
xfer->tx_buf = txb;
xfer->rx_buf = trx;
xfer->len = rxl + 2;
}
ret = spi_sync(kss->spidev, msg);
if (ret < 0)
netdev_err(ks->netdev, "read: spi_sync() failed\n");
else if (kss->spidev->master->flags & SPI_MASTER_HALF_DUPLEX)
memcpy(rxb, trx, rxl);
else
memcpy(rxb, trx + 2, rxl);
}
/**
* ks8851_rdreg16_spi - read 16 bit register from device via SPI
* @ks: The chip information
* @reg: The register address
*
* Read a 16bit register from the chip, returning the result
*/
static unsigned int ks8851_rdreg16_spi(struct ks8851_net *ks, unsigned int reg)
{
__le16 rx = 0;
ks8851_rdreg(ks, MK_OP(reg & 2 ? 0xC : 0x3, reg), (u8 *)&rx, 2);
return le16_to_cpu(rx);
}
/**
* ks8851_rdfifo_spi - read data from the receive fifo via SPI
* @ks: The device state.
* @buff: The buffer address
* @len: The length of the data to read
*
* Issue an RXQ FIFO read command and read the @len amount of data from
* the FIFO into the buffer specified by @buff.
*/
static void ks8851_rdfifo_spi(struct ks8851_net *ks, u8 *buff, unsigned int len)
{
struct ks8851_net_spi *kss = to_ks8851_spi(ks);
struct spi_transfer *xfer = kss->spi_xfer2;
struct spi_message *msg = &kss->spi_msg2;
u8 txb[1];
int ret;
netif_dbg(ks, rx_status, ks->netdev,
"%s: %d@%p\n", __func__, len, buff);
/* set the operation we're issuing */
txb[0] = KS_SPIOP_RXFIFO;
xfer->tx_buf = txb;
xfer->rx_buf = NULL;
xfer->len = 1;
xfer++;
xfer->rx_buf = buff;
xfer->tx_buf = NULL;
xfer->len = len;
ret = spi_sync(kss->spidev, msg);
if (ret < 0)
netdev_err(ks->netdev, "%s: spi_sync() failed\n", __func__);
}
/**
* ks8851_wrfifo_spi - write packet to TX FIFO via SPI
* @ks: The device state.
* @txp: The sk_buff to transmit.
* @irq: IRQ on completion of the packet.
*
* Send the @txp to the chip. This means creating the relevant packet header
* specifying the length of the packet and the other information the chip
* needs, such as IRQ on completion. Send the header and the packet data to
* the device.
*/
static void ks8851_wrfifo_spi(struct ks8851_net *ks, struct sk_buff *txp,
bool irq)
{
struct ks8851_net_spi *kss = to_ks8851_spi(ks);
struct spi_transfer *xfer = kss->spi_xfer2;
struct spi_message *msg = &kss->spi_msg2;
unsigned int fid = 0;
int ret;
netif_dbg(ks, tx_queued, ks->netdev, "%s: skb %p, %d@%p, irq %d\n",
__func__, txp, txp->len, txp->data, irq);
fid = ks->fid++;
fid &= TXFR_TXFID_MASK;
if (irq)
fid |= TXFR_TXIC; /* irq on completion */
/* start header at txb[1] to align txw entries */
ks->txh.txb[1] = KS_SPIOP_TXFIFO;
ks->txh.txw[1] = cpu_to_le16(fid);
ks->txh.txw[2] = cpu_to_le16(txp->len);
xfer->tx_buf = &ks->txh.txb[1];
xfer->rx_buf = NULL;
xfer->len = 5;
xfer++;
xfer->tx_buf = txp->data;
xfer->rx_buf = NULL;
xfer->len = ALIGN(txp->len, 4);
ret = spi_sync(kss->spidev, msg);
if (ret < 0)
netdev_err(ks->netdev, "%s: spi_sync() failed\n", __func__);
}
/**
* ks8851_rx_skb_spi - receive skbuff
* @ks: The device state
* @skb: The skbuff
*/
static void ks8851_rx_skb_spi(struct ks8851_net *ks, struct sk_buff *skb)
{
netif_rx_ni(skb);
}
/**
* ks8851_tx_work - process tx packet(s)
* @work: The work strucutre what was scheduled.
*
* This is called when a number of packets have been scheduled for
* transmission and need to be sent to the device.
*/
static void ks8851_tx_work(struct work_struct *work)
{
struct ks8851_net_spi *kss;
struct ks8851_net *ks;
unsigned long flags;
struct sk_buff *txb;
bool last;
kss = container_of(work, struct ks8851_net_spi, tx_work);
ks = &kss->ks8851;
last = skb_queue_empty(&ks->txq);
ks8851_lock_spi(ks, &flags);
while (!last) {
txb = skb_dequeue(&ks->txq);
last = skb_queue_empty(&ks->txq);
if (txb) {
ks8851_wrreg16_spi(ks, KS_RXQCR,
ks->rc_rxqcr | RXQCR_SDA);
ks8851_wrfifo_spi(ks, txb, last);
ks8851_wrreg16_spi(ks, KS_RXQCR, ks->rc_rxqcr);
ks8851_wrreg16_spi(ks, KS_TXQCR, TXQCR_METFE);
ks8851_done_tx(ks, txb);
}
}
ks8851_unlock_spi(ks, &flags);
}
/**
* ks8851_flush_tx_work_spi - flush outstanding TX work
* @ks: The device state
*/
static void ks8851_flush_tx_work_spi(struct ks8851_net *ks)
{
struct ks8851_net_spi *kss = to_ks8851_spi(ks);
flush_work(&kss->tx_work);
}
/**
* calc_txlen - calculate size of message to send packet
* @len: Length of data
*
* Returns the size of the TXFIFO message needed to send
* this packet.
*/
static unsigned int calc_txlen(unsigned int len)
{
return ALIGN(len + 4, 4);
}
/**
* ks8851_start_xmit_spi - transmit packet using SPI
* @skb: The buffer to transmit
* @dev: The device used to transmit the packet.
*
* Called by the network layer to transmit the @skb. Queue the packet for
* the device and schedule the necessary work to transmit the packet when
* it is free.
*
* We do this to firstly avoid sleeping with the network device locked,
* and secondly so we can round up more than one packet to transmit which
* means we can try and avoid generating too many transmit done interrupts.
*/
static netdev_tx_t ks8851_start_xmit_spi(struct sk_buff *skb,
struct net_device *dev)
{
unsigned int needed = calc_txlen(skb->len);
struct ks8851_net *ks = netdev_priv(dev);
netdev_tx_t ret = NETDEV_TX_OK;
struct ks8851_net_spi *kss;
kss = to_ks8851_spi(ks);
netif_dbg(ks, tx_queued, ks->netdev,
"%s: skb %p, %d@%p\n", __func__, skb, skb->len, skb->data);
spin_lock(&ks->statelock);
if (needed > ks->tx_space) {
netif_stop_queue(dev);
ret = NETDEV_TX_BUSY;
} else {
ks->tx_space -= needed;
skb_queue_tail(&ks->txq, skb);
}
spin_unlock(&ks->statelock);
schedule_work(&kss->tx_work);
return ret;
}
static int ks8851_probe_spi(struct spi_device *spi)
{
struct device *dev = &spi->dev;
struct ks8851_net_spi *kss;
struct net_device *netdev;
struct ks8851_net *ks;
netdev = devm_alloc_etherdev(dev, sizeof(struct ks8851_net_spi));
if (!netdev)
return -ENOMEM;
spi->bits_per_word = 8;
ks = netdev_priv(netdev);
ks->lock = ks8851_lock_spi;
ks->unlock = ks8851_unlock_spi;
ks->rdreg16 = ks8851_rdreg16_spi;
ks->wrreg16 = ks8851_wrreg16_spi;
ks->rdfifo = ks8851_rdfifo_spi;
ks->wrfifo = ks8851_wrfifo_spi;
ks->start_xmit = ks8851_start_xmit_spi;
ks->rx_skb = ks8851_rx_skb_spi;
ks->flush_tx_work = ks8851_flush_tx_work_spi;
#define STD_IRQ (IRQ_LCI | /* Link Change */ \
IRQ_TXI | /* TX done */ \
IRQ_RXI | /* RX done */ \
IRQ_SPIBEI | /* SPI bus error */ \
IRQ_TXPSI | /* TX process stop */ \
IRQ_RXPSI) /* RX process stop */
ks->rc_ier = STD_IRQ;
kss = to_ks8851_spi(ks);
kss->spidev = spi;
mutex_init(&kss->lock);
INIT_WORK(&kss->tx_work, ks8851_tx_work);
/* initialise pre-made spi transfer messages */
spi_message_init(&kss->spi_msg1);
spi_message_add_tail(&kss->spi_xfer1, &kss->spi_msg1);
spi_message_init(&kss->spi_msg2);
spi_message_add_tail(&kss->spi_xfer2[0], &kss->spi_msg2);
spi_message_add_tail(&kss->spi_xfer2[1], &kss->spi_msg2);
netdev->irq = spi->irq;
return ks8851_probe_common(netdev, dev, msg_enable);
}
static int ks8851_remove_spi(struct spi_device *spi)
{
return ks8851_remove_common(&spi->dev);
}
static const struct of_device_id ks8851_match_table[] = {
{ .compatible = "micrel,ks8851" },
{ }
};
MODULE_DEVICE_TABLE(of, ks8851_match_table);
static struct spi_driver ks8851_driver = {
.driver = {
.name = "ks8851",
.of_match_table = ks8851_match_table,
.pm = &ks8851_pm_ops,
},
.probe = ks8851_probe_spi,
.remove = ks8851_remove_spi,
};
module_spi_driver(ks8851_driver);
MODULE_DESCRIPTION("KS8851 Network driver");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_LICENSE("GPL");
module_param_named(message, msg_enable, int, 0);
MODULE_PARM_DESC(message, "Message verbosity level (0=none, 31=all)");
MODULE_ALIAS("spi:ks8851");
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册