2020-05-29 01:21:44 +03:00
// 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
# 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 16 bit 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 16 bit 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 )
{
2022-03-03 20:15:02 +03:00
netif_rx ( skb ) ;
2020-05-29 01:21:44 +03:00
}
/**
* 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 ;
2022-08-23 00:39:32 +03:00
kss = netdev_priv ( netdev ) ;
ks = & kss - > ks8851 ;
2020-05-29 01:21:44 +03:00
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 - > 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 ) ;
}
2022-01-23 20:52:01 +03:00
static void ks8851_remove_spi ( struct spi_device * spi )
2020-05-29 01:21:44 +03:00
{
2021-10-15 09:56:14 +03:00
ks8851_remove_common ( & spi - > dev ) ;
2020-05-29 01:21:44 +03:00
}
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 " ) ;