linux/drivers/net/ethernet/microchip/enc28j60.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Microchip ENC28J60 ethernet driver (MAC + PHY)
 *
 * Copyright (C) 2007 Eurek srl
 * Author: Claudio Lanconelli <[email protected]>
 * based on enc28j60.c written by David Anders for 2.4 kernel version
 *
 * $Id: enc28j60.c,v 1.22 2007/12/20 10:47:01 claudio Exp $
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/property.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>

#include "enc28j60_hw.h"

#define DRV_NAME
#define DRV_VERSION

#define SPI_OPLEN

#define ENC28J60_MSG_DEFAULT

/* Buffer size required for the largest SPI transfer (i.e., reading a
 * frame).
 */
#define SPI_TRANSFER_BUF_LEN

#define TX_TIMEOUT

/* Max TX retries in case of collision as suggested by errata datasheet */
#define MAX_TX_RETRYCOUNT

enum {};

/* Driver local data */
struct enc28j60_net {};

/* use ethtool to change the level for any given device */
static struct {} debug =;

/*
 * SPI read buffer
 * Wait for the SPI transfer and copy received data to destination.
 */
static int
spi_read_buf(struct enc28j60_net *priv, int len, u8 *data)
{}

/*
 * SPI write buffer
 */
static int spi_write_buf(struct enc28j60_net *priv, int len, const u8 *data)
{}

/*
 * basic SPI read operation
 */
static u8 spi_read_op(struct enc28j60_net *priv, u8 op, u8 addr)
{}

/*
 * basic SPI write operation
 */
static int spi_write_op(struct enc28j60_net *priv, u8 op, u8 addr, u8 val)
{}

static void enc28j60_soft_reset(struct enc28j60_net *priv)
{}

/*
 * select the current register bank if necessary
 */
static void enc28j60_set_bank(struct enc28j60_net *priv, u8 addr)
{}

/*
 * Register access routines through the SPI bus.
 * Every register access comes in two flavours:
 * - nolock_xxx: caller needs to invoke mutex_lock, usually to access
 *   atomically more than one register
 * - locked_xxx: caller doesn't need to invoke mutex_lock, single access
 *
 * Some registers can be accessed through the bit field clear and
 * bit field set to avoid a read modify write cycle.
 */

/*
 * Register bit field Set
 */
static void nolock_reg_bfset(struct enc28j60_net *priv, u8 addr, u8 mask)
{}

static void locked_reg_bfset(struct enc28j60_net *priv, u8 addr, u8 mask)
{}

/*
 * Register bit field Clear
 */
static void nolock_reg_bfclr(struct enc28j60_net *priv, u8 addr, u8 mask)
{}

static void locked_reg_bfclr(struct enc28j60_net *priv, u8 addr, u8 mask)
{}

/*
 * Register byte read
 */
static int nolock_regb_read(struct enc28j60_net *priv, u8 address)
{}

static int locked_regb_read(struct enc28j60_net *priv, u8 address)
{}

/*
 * Register word read
 */
static int nolock_regw_read(struct enc28j60_net *priv, u8 address)
{}

static int locked_regw_read(struct enc28j60_net *priv, u8 address)
{}

/*
 * Register byte write
 */
static void nolock_regb_write(struct enc28j60_net *priv, u8 address, u8 data)
{}

static void locked_regb_write(struct enc28j60_net *priv, u8 address, u8 data)
{}

/*
 * Register word write
 */
static void nolock_regw_write(struct enc28j60_net *priv, u8 address, u16 data)
{}

static void locked_regw_write(struct enc28j60_net *priv, u8 address, u16 data)
{}

/*
 * Buffer memory read
 * Select the starting address and execute a SPI buffer read.
 */
static void enc28j60_mem_read(struct enc28j60_net *priv, u16 addr, int len,
			      u8 *data)
{}

/*
 * Write packet to enc28j60 TX buffer memory
 */
static void
enc28j60_packet_write(struct enc28j60_net *priv, int len, const u8 *data)
{}

static int poll_ready(struct enc28j60_net *priv, u8 reg, u8 mask, u8 val)
{}

/*
 * Wait until the PHY operation is complete.
 */
static int wait_phy_ready(struct enc28j60_net *priv)
{}

/*
 * PHY register read
 * PHY registers are not accessed directly, but through the MII.
 */
static u16 enc28j60_phy_read(struct enc28j60_net *priv, u8 address)
{}

static int enc28j60_phy_write(struct enc28j60_net *priv, u8 address, u16 data)
{}

/*
 * Program the hardware MAC address from dev->dev_addr.
 */
static int enc28j60_set_hw_macaddr(struct net_device *ndev)
{}

/*
 * Store the new hardware address in dev->dev_addr, and update the MAC.
 */
static int enc28j60_set_mac_address(struct net_device *dev, void *addr)
{}

/*
 * Debug routine to dump useful register contents
 */
static void enc28j60_dump_regs(struct enc28j60_net *priv, const char *msg)
{}

/*
 * ERXRDPT need to be set always at odd addresses, refer to errata datasheet
 */
static u16 erxrdpt_workaround(u16 next_packet_ptr, u16 start, u16 end)
{}

/*
 * Calculate wrap around when reading beyond the end of the RX buffer
 */
static u16 rx_packet_start(u16 ptr)
{}

static void nolock_rxfifo_init(struct enc28j60_net *priv, u16 start, u16 end)
{}

static void nolock_txfifo_init(struct enc28j60_net *priv, u16 start, u16 end)
{}

/*
 * Low power mode shrinks power consumption about 100x, so we'd like
 * the chip to be in that mode whenever it's inactive. (However, we
 * can't stay in low power mode during suspend with WOL active.)
 */
static void enc28j60_lowpower(struct enc28j60_net *priv, bool is_low)
{}

static int enc28j60_hw_init(struct enc28j60_net *priv)
{}

static void enc28j60_hw_enable(struct enc28j60_net *priv)
{}

static void enc28j60_hw_disable(struct enc28j60_net *priv)
{}

static int
enc28j60_setlink(struct net_device *ndev, u8 autoneg, u16 speed, u8 duplex)
{}

/*
 * Read the Transmit Status Vector
 */
static void enc28j60_read_tsv(struct enc28j60_net *priv, u8 tsv[TSV_SIZE])
{}

static void enc28j60_dump_tsv(struct enc28j60_net *priv, const char *msg,
			      u8 tsv[TSV_SIZE])
{}

/*
 * Receive Status vector
 */
static void enc28j60_dump_rsv(struct enc28j60_net *priv, const char *msg,
			      u16 pk_ptr, int len, u16 sts)
{}

static void dump_packet(const char *msg, int len, const char *data)
{}

/*
 * Hardware receive function.
 * Read the buffer memory, update the FIFO pointer to free the buffer,
 * check the status vector and decrement the packet counter.
 */
static void enc28j60_hw_rx(struct net_device *ndev)
{}

/*
 * Calculate free space in RxFIFO
 */
static int enc28j60_get_free_rxfifo(struct enc28j60_net *priv)
{}

/*
 * Access the PHY to determine link status
 */
static void enc28j60_check_link_status(struct net_device *ndev)
{}

static void enc28j60_tx_clear(struct net_device *ndev, bool err)
{}

/*
 * RX handler
 * Ignore PKTIF because is unreliable! (Look at the errata datasheet)
 * Check EPKTCNT is the suggested workaround.
 * We don't need to clear interrupt flag, automatically done when
 * enc28j60_hw_rx() decrements the packet counter.
 * Returns how many packet processed.
 */
static int enc28j60_rx_interrupt(struct net_device *ndev)
{}

static irqreturn_t enc28j60_irq(int irq, void *dev_id)
{}

/*
 * Hardware transmit function.
 * Fill the buffer memory and send the contents of the transmit buffer
 * onto the network
 */
static void enc28j60_hw_tx(struct enc28j60_net *priv)
{}

static netdev_tx_t enc28j60_send_packet(struct sk_buff *skb,
					struct net_device *dev)
{}

static void enc28j60_tx_work_handler(struct work_struct *work)
{}

static void enc28j60_tx_timeout(struct net_device *ndev, unsigned int txqueue)
{}

/*
 * Open/initialize the board. This is called (in the current kernel)
 * sometime after booting when the 'ifconfig' program is run.
 *
 * This routine should set everything up anew at each open, even
 * registers that "should" only need to be set once at boot, so that
 * there is non-reboot way to recover if something goes wrong.
 */
static int enc28j60_net_open(struct net_device *dev)
{}

/* The inverse routine to net_open(). */
static int enc28j60_net_close(struct net_device *dev)
{}

/*
 * Set or clear the multicast filter for this adapter
 * num_addrs == -1	Promiscuous mode, receive all packets
 * num_addrs == 0	Normal mode, filter out multicast packets
 * num_addrs > 0	Multicast mode, receive normal and MC packets
 */
static void enc28j60_set_multicast_list(struct net_device *dev)
{}

static void enc28j60_setrx_work_handler(struct work_struct *work)
{}

static void enc28j60_restart_work_handler(struct work_struct *work)
{}

/* ......................... ETHTOOL SUPPORT ........................... */

static void
enc28j60_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{}

static int
enc28j60_get_link_ksettings(struct net_device *dev,
			    struct ethtool_link_ksettings *cmd)
{}

static int
enc28j60_set_link_ksettings(struct net_device *dev,
			    const struct ethtool_link_ksettings *cmd)
{}

static u32 enc28j60_get_msglevel(struct net_device *dev)
{}

static void enc28j60_set_msglevel(struct net_device *dev, u32 val)
{}

static const struct ethtool_ops enc28j60_ethtool_ops =;

static int enc28j60_chipset_init(struct net_device *dev)
{}

static const struct net_device_ops enc28j60_netdev_ops =;

static int enc28j60_probe(struct spi_device *spi)
{}

static void enc28j60_remove(struct spi_device *spi)
{}

static const struct of_device_id enc28j60_dt_ids[] =;
MODULE_DEVICE_TABLE(of, enc28j60_dt_ids);

static struct spi_driver enc28j60_driver =;
module_spi_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();
module_param_named(debug, debug.msg_enable, int, 0);
MODULE_PARM_DESC();
MODULE_ALIAS();