linux/drivers/net/ethernet/smsc/smc91x.h

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*------------------------------------------------------------------------
 . smc91x.h - macros for SMSC's 91C9x/91C1xx single-chip Ethernet device.
 .
 . Copyright (C) 1996 by Erik Stahlman
 . Copyright (C) 2001 Standard Microsystems Corporation
 .	Developed by Simple Network Magic Corporation
 . Copyright (C) 2003 Monta Vista Software, Inc.
 .	Unified SMC91x driver by Nicolas Pitre
 .
 .
 . Information contained in this file was obtained from the LAN91C111
 . manual from SMC.  To get a copy, if you really want one, you can find
 . information under www.smsc.com.
 .
 . Authors
 .	Erik Stahlman		<[email protected]>
 .	Daris A Nevil		<[email protected]>
 .	Nicolas Pitre 		<[email protected]>
 .
 ---------------------------------------------------------------------------*/
#ifndef _SMC91X_H_
#define _SMC91X_H_

#include <linux/dmaengine.h>
#include <linux/smc91x.h>

/*
 * Any 16-bit access is performed with two 8-bit accesses if the hardware
 * can't do it directly. Most registers are 16-bit so those are mandatory.
 */
#define SMC_outw_b(x, a, r)

#define SMC_inw_b(a, r)

/*
 * Define your architecture specific bus configuration parameters here.
 */

#if defined(CONFIG_ARM)

#include <asm/mach-types.h>

/* Now the bus width is specified in the platform data
 * pretend here to support all I/O access types
 */
#define SMC_CAN_USE_8BIT
#define SMC_CAN_USE_16BIT
#define SMC_CAN_USE_32BIT
#define SMC_NOWAIT

#define SMC_IO_SHIFT

#define SMC_inb
#define SMC_inw

#define SMC_inl
#define SMC_outb
#define SMC_outw

#define SMC_outl
#define SMC_insb
#define SMC_outsb
#define SMC_insw
#define SMC_outsw
#define SMC_insl
#define SMC_outsl
#define SMC_IRQ_FLAGS

/* We actually can't write halfwords properly if not word aligned */
static inline void _SMC_outw_align4(u16 val, void __iomem *ioaddr, int reg,
				    bool use_align4_workaround)
{
	if (use_align4_workaround) {
		unsigned int v = val << 16;
		v |= readl(ioaddr + (reg & ~2)) & 0xffff;
		writel(v, ioaddr + (reg & ~2));
	} else {
		writew(val, ioaddr + reg);
	}
}

#define __SMC_outw


#elif defined(CONFIG_ATARI)

#define SMC_CAN_USE_8BIT
#define SMC_CAN_USE_16BIT
#define SMC_CAN_USE_32BIT
#define SMC_NOWAIT

#define SMC_inb
#define SMC_inw
#define SMC_inl
#define SMC_outb
#define SMC_outw
#define SMC_outl
#define SMC_insw
#define SMC_outsw
#define SMC_insl
#define SMC_outsl

#define RPC_LSA_DEFAULT
#define RPC_LSB_DEFAULT

#elif defined(CONFIG_COLDFIRE)

#define SMC_CAN_USE_8BIT
#define SMC_CAN_USE_16BIT
#define SMC_CAN_USE_32BIT
#define SMC_NOWAIT

static inline void mcf_insw(void __iomem *a, unsigned char *p, int l)
{
	u16 *wp = (u16 *) p;
	while (l-- > 0)
		*wp++ = readw(a);
}

static inline void mcf_outsw(void __iomem *a, unsigned char *p, int l)
{
	u16 *wp = (u16 *) p;
	while (l-- > 0)
		writew(*wp++, a);
}

#define SMC_inw
#define SMC_outw
#define SMC_insw
#define SMC_outsw

#define SMC_IRQ_FLAGS

#else

/*
 * Default configuration
 */

#define SMC_CAN_USE_8BIT
#define SMC_CAN_USE_16BIT
#define SMC_CAN_USE_32BIT
#define SMC_NOWAIT

#define SMC_IO_SHIFT

#define SMC_inb(a, r)
#define SMC_inw(a, r)
#define SMC_inl(a, r)
#define SMC_outb(v, a, r)
#define SMC_outw(lp, v, a, r)
#define SMC_outl(v, a, r)
#define SMC_insw(a, r, p, l)
#define SMC_outsw(a, r, p, l)
#define SMC_insl(a, r, p, l)
#define SMC_outsl(a, r, p, l)

#define RPC_LSA_DEFAULT
#define RPC_LSB_DEFAULT

#endif


/* store this information for the driver.. */
struct smc_local {};

#define SMC_8BIT(p)
#define SMC_16BIT(p)
#define SMC_32BIT(p)

#ifdef CONFIG_ARCH_PXA
/*
 * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
 * always happening in irq context so no need to worry about races.  TX is
 * different and probably not worth it for that reason, and not as critical
 * as RX which can overrun memory and lose packets.
 */
#include <linux/dma-mapping.h>

#ifdef SMC_insl
#undef SMC_insl
#define SMC_insl
static inline void
smc_pxa_dma_inpump(struct smc_local *lp, u_char *buf, int len)
{
	dma_addr_t dmabuf;
	struct dma_async_tx_descriptor *tx;
	dma_cookie_t cookie;
	enum dma_status status;
	struct dma_tx_state state;

	dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
	tx = dmaengine_prep_slave_single(lp->dma_chan, dmabuf, len,
					 DMA_DEV_TO_MEM, 0);
	if (tx) {
		cookie = dmaengine_submit(tx);
		dma_async_issue_pending(lp->dma_chan);
		do {
			status = dmaengine_tx_status(lp->dma_chan, cookie,
						     &state);
			cpu_relax();
		} while (status != DMA_COMPLETE && status != DMA_ERROR &&
			 state.residue);
		dmaengine_terminate_all(lp->dma_chan);
	}
	dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
}

static inline void
smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
		 u_char *buf, int len)
{
	struct dma_slave_config	config;
	int ret;

	/* fallback if no DMA available */
	if (!lp->dma_chan) {
		readsl(ioaddr + reg, buf, len);
		return;
	}

	/* 64 bit alignment is required for memory to memory DMA */
	if ((long)buf & 4) {
		*((u32 *)buf) = SMC_inl(ioaddr, reg);
		buf += 4;
		len--;
	}

	memset(&config, 0, sizeof(config));
	config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
	config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
	config.src_addr = lp->physaddr + reg;
	config.dst_addr = lp->physaddr + reg;
	config.src_maxburst = 32;
	config.dst_maxburst = 32;
	ret = dmaengine_slave_config(lp->dma_chan, &config);
	if (ret) {
		dev_err(lp->device, "dma channel configuration failed: %d\n",
			ret);
		return;
	}

	len *= 4;
	smc_pxa_dma_inpump(lp, buf, len);
}
#endif

#ifdef SMC_insw
#undef SMC_insw
#define SMC_insw
static inline void
smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
		 u_char *buf, int len)
{
	struct dma_slave_config	config;
	int ret;

	/* fallback if no DMA available */
	if (!lp->dma_chan) {
		readsw(ioaddr + reg, buf, len);
		return;
	}

	/* 64 bit alignment is required for memory to memory DMA */
	while ((long)buf & 6) {
		*((u16 *)buf) = SMC_inw(ioaddr, reg);
		buf += 2;
		len--;
	}

	memset(&config, 0, sizeof(config));
	config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
	config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
	config.src_addr = lp->physaddr + reg;
	config.dst_addr = lp->physaddr + reg;
	config.src_maxburst = 32;
	config.dst_maxburst = 32;
	ret = dmaengine_slave_config(lp->dma_chan, &config);
	if (ret) {
		dev_err(lp->device, "dma channel configuration failed: %d\n",
			ret);
		return;
	}

	len *= 2;
	smc_pxa_dma_inpump(lp, buf, len);
}
#endif

#endif  /* CONFIG_ARCH_PXA */


/*
 * Everything a particular hardware setup needs should have been defined
 * at this point.  Add stubs for the undefined cases, mainly to avoid
 * compilation warnings since they'll be optimized away, or to prevent buggy
 * use of them.
 */

#if ! SMC_CAN_USE_32BIT
#define SMC_inl
#define SMC_outl
#define SMC_insl
#define SMC_outsl
#endif

#if !defined(SMC_insl) || !defined(SMC_outsl)
#define SMC_insl
#define SMC_outsl
#endif

#if ! SMC_CAN_USE_16BIT

#define SMC_outw
#define SMC_inw
#define SMC_insw
#define SMC_outsw

#endif

#if !defined(SMC_insw) || !defined(SMC_outsw)
#define SMC_insw
#define SMC_outsw
#endif

#if ! SMC_CAN_USE_8BIT
#undef SMC_inb
#define SMC_inb
#undef SMC_outb
#define SMC_outb
#define SMC_insb
#define SMC_outsb
#endif

#if !defined(SMC_insb) || !defined(SMC_outsb)
#define SMC_insb(a, r, p, l)
#define SMC_outsb(a, r, p, l)
#endif

#ifndef SMC_CAN_USE_DATACS
#define SMC_CAN_USE_DATACS
#endif

#ifndef SMC_IO_SHIFT
#define SMC_IO_SHIFT
#endif

#ifndef	SMC_IRQ_FLAGS
#define SMC_IRQ_FLAGS
#endif

#ifndef SMC_INTERRUPT_PREAMBLE
#define SMC_INTERRUPT_PREAMBLE
#endif


/* Because of bank switching, the LAN91x uses only 16 I/O ports */
#define SMC_IO_EXTENT
#define SMC_DATA_EXTENT

/*
 . Bank Select Register:
 .
 .		yyyy yyyy 0000 00xx
 .		xx 		= bank number
 .		yyyy yyyy	= 0x33, for identification purposes.
*/
#define BANK_SELECT


// Transmit Control Register
/* BANK 0  */
#define TCR_REG(lp)
#define TCR_ENABLE
#define TCR_LOOP
#define TCR_FORCOL
#define TCR_PAD_EN
#define TCR_NOCRC
#define TCR_MON_CSN
#define TCR_FDUPLX
#define TCR_STP_SQET
#define TCR_EPH_LOOP
#define TCR_SWFDUP

#define TCR_CLEAR
/* the default settings for the TCR register : */
#define TCR_DEFAULT


// EPH Status Register
/* BANK 0  */
#define EPH_STATUS_REG(lp)
#define ES_TX_SUC
#define ES_SNGL_COL
#define ES_MUL_COL
#define ES_LTX_MULT
#define ES_16COL
#define ES_SQET
#define ES_LTXBRD
#define ES_TXDEFR
#define ES_LATCOL
#define ES_LOSTCARR
#define ES_EXC_DEF
#define ES_CTR_ROL
#define ES_LINK_OK
#define ES_TXUNRN


// Receive Control Register
/* BANK 0  */
#define RCR_REG(lp)
#define RCR_RX_ABORT
#define RCR_PRMS
#define RCR_ALMUL
#define RCR_RXEN
#define RCR_STRIP_CRC
#define RCR_ABORT_ENB
#define RCR_FILT_CAR
#define RCR_SOFTRST

/* the normal settings for the RCR register : */
#define RCR_DEFAULT
#define RCR_CLEAR


// Counter Register
/* BANK 0  */
#define COUNTER_REG(lp)


// Memory Information Register
/* BANK 0  */
#define MIR_REG(lp)


// Receive/Phy Control Register
/* BANK 0  */
#define RPC_REG(lp)
#define RPC_SPEED
#define RPC_DPLX
#define RPC_ANEG
#define RPC_LSXA_SHFT
#define RPC_LSXB_SHFT

#ifndef RPC_LSA_DEFAULT
#define RPC_LSA_DEFAULT
#endif
#ifndef RPC_LSB_DEFAULT
#define RPC_LSB_DEFAULT
#endif

#define RPC_DEFAULT


/* Bank 0 0x0C is reserved */

// Bank Select Register
/* All Banks */
#define BSR_REG


// Configuration Reg
/* BANK 1 */
#define CONFIG_REG(lp)
#define CONFIG_EXT_PHY
#define CONFIG_GPCNTRL
#define CONFIG_NO_WAIT
#define CONFIG_EPH_POWER_EN

// Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low
#define CONFIG_DEFAULT


// Base Address Register
/* BANK 1 */
#define BASE_REG(lp)


// Individual Address Registers
/* BANK 1 */
#define ADDR0_REG(lp)
#define ADDR1_REG(lp)
#define ADDR2_REG(lp)


// General Purpose Register
/* BANK 1 */
#define GP_REG(lp)


// Control Register
/* BANK 1 */
#define CTL_REG(lp)
#define CTL_RCV_BAD
#define CTL_AUTO_RELEASE
#define CTL_LE_ENABLE
#define CTL_CR_ENABLE
#define CTL_TE_ENABLE
#define CTL_EEPROM_SELECT
#define CTL_RELOAD
#define CTL_STORE


// MMU Command Register
/* BANK 2 */
#define MMU_CMD_REG(lp)
#define MC_BUSY
#define MC_NOP
#define MC_ALLOC
#define MC_RESET
#define MC_REMOVE
#define MC_RELEASE
#define MC_FREEPKT
#define MC_ENQUEUE
#define MC_RSTTXFIFO


// Packet Number Register
/* BANK 2 */
#define PN_REG(lp)


// Allocation Result Register
/* BANK 2 */
#define AR_REG(lp)
#define AR_FAILED


// TX FIFO Ports Register
/* BANK 2 */
#define TXFIFO_REG(lp)
#define TXFIFO_TEMPTY

// RX FIFO Ports Register
/* BANK 2 */
#define RXFIFO_REG(lp)
#define RXFIFO_REMPTY

#define FIFO_REG(lp)

// Pointer Register
/* BANK 2 */
#define PTR_REG(lp)
#define PTR_RCV
#define PTR_AUTOINC
#define PTR_READ


// Data Register
/* BANK 2 */
#define DATA_REG(lp)


// Interrupt Status/Acknowledge Register
/* BANK 2 */
#define INT_REG(lp)


// Interrupt Mask Register
/* BANK 2 */
#define IM_REG(lp)
#define IM_MDINT
#define IM_ERCV_INT
#define IM_EPH_INT
#define IM_RX_OVRN_INT
#define IM_ALLOC_INT
#define IM_TX_EMPTY_INT
#define IM_TX_INT
#define IM_RCV_INT


// Multicast Table Registers
/* BANK 3 */
#define MCAST_REG1(lp)
#define MCAST_REG2(lp)
#define MCAST_REG3(lp)
#define MCAST_REG4(lp)


// Management Interface Register (MII)
/* BANK 3 */
#define MII_REG(lp)
#define MII_MSK_CRS100
#define MII_MDOE
#define MII_MCLK
#define MII_MDI
#define MII_MDO


// Revision Register
/* BANK 3 */
/* ( hi: chip id   low: rev # ) */
#define REV_REG(lp)


// Early RCV Register
/* BANK 3 */
/* this is NOT on SMC9192 */
#define ERCV_REG(lp)
#define ERCV_RCV_DISCRD
#define ERCV_THRESHOLD


// External Register
/* BANK 7 */
#define EXT_REG(lp)


#define CHIP_9192
#define CHIP_9194
#define CHIP_9195
#define CHIP_9196
#define CHIP_91100
#define CHIP_91100FD
#define CHIP_91111FD

static const char * chip_ids[ 16 ] =;


/*
 . Receive status bits
*/
#define RS_ALGNERR
#define RS_BRODCAST
#define RS_BADCRC
#define RS_ODDFRAME
#define RS_TOOLONG
#define RS_TOOSHORT
#define RS_MULTICAST
#define RS_ERRORS


/*
 * PHY IDs
 *  LAN83C183 == LAN91C111 Internal PHY
 */
#define PHY_LAN83C183
#define PHY_LAN83C180

/*
 * PHY Register Addresses (LAN91C111 Internal PHY)
 *
 * Generic PHY registers can be found in <linux/mii.h>
 *
 * These phy registers are specific to our on-board phy.
 */

// PHY Configuration Register 1
#define PHY_CFG1_REG
#define PHY_CFG1_LNKDIS
#define PHY_CFG1_XMTDIS
#define PHY_CFG1_XMTPDN
#define PHY_CFG1_BYPSCR
#define PHY_CFG1_UNSCDS
#define PHY_CFG1_EQLZR
#define PHY_CFG1_CABLE
#define PHY_CFG1_RLVL0
#define PHY_CFG1_TLVL_SHIFT
#define PHY_CFG1_TLVL_MASK
#define PHY_CFG1_TRF_MASK


// PHY Configuration Register 2
#define PHY_CFG2_REG
#define PHY_CFG2_APOLDIS
#define PHY_CFG2_JABDIS
#define PHY_CFG2_MREG
#define PHY_CFG2_INTMDIO

// PHY Status Output (and Interrupt status) Register
#define PHY_INT_REG
#define PHY_INT_INT
#define PHY_INT_LNKFAIL
#define PHY_INT_LOSSSYNC
#define PHY_INT_CWRD
#define PHY_INT_SSD
#define PHY_INT_ESD
#define PHY_INT_RPOL
#define PHY_INT_JAB
#define PHY_INT_SPDDET
#define PHY_INT_DPLXDET

// PHY Interrupt/Status Mask Register
#define PHY_MASK_REG
// Uses the same bit definitions as PHY_INT_REG


/*
 * SMC91C96 ethernet config and status registers.
 * These are in the "attribute" space.
 */
#define ECOR
#define ECOR_RESET
#define ECOR_LEVEL_IRQ
#define ECOR_WR_ATTRIB
#define ECOR_ENABLE

#define ECSR
#define ECSR_IOIS8
#define ECSR_PWRDWN
#define ECSR_INT

#define ATTRIB_SIZE


/*
 * Macros to abstract register access according to the data bus
 * capabilities.  Please use those and not the in/out primitives.
 * Note: the following macros do *not* select the bank -- this must
 * be done separately as needed in the main code.  The SMC_REG() macro
 * only uses the bank argument for debugging purposes (when enabled).
 *
 * Note: despite inline functions being safer, everything leading to this
 * should preferably be macros to let BUG() display the line number in
 * the core source code since we're interested in the top call site
 * not in any inline function location.
 */

#if SMC_DEBUG > 0
#define SMC_REG
#else
#define SMC_REG(lp, reg, bank)
#endif

/*
 * Hack Alert: Some setups just can't write 8 or 16 bits reliably when not
 * aligned to a 32 bit boundary.  I tell you that does exist!
 * Fortunately the affected register accesses can be easily worked around
 * since we can write zeroes to the preceding 16 bits without adverse
 * effects and use a 32-bit access.
 *
 * Enforce it on any 32-bit capable setup for now.
 */
#define SMC_MUST_ALIGN_WRITE(lp)

#define SMC_GET_PN(lp)

#define SMC_SET_PN(lp, x)

#define SMC_GET_AR(lp)

#define SMC_GET_TXFIFO(lp)

#define SMC_GET_RXFIFO(lp)

#define SMC_GET_INT(lp)

#define SMC_ACK_INT(lp, x)

#define SMC_GET_INT_MASK(lp)

#define SMC_SET_INT_MASK(lp, x)

#define SMC_CURRENT_BANK(lp)

#define SMC_SELECT_BANK(lp, x)

#define SMC_GET_BASE(lp)

#define SMC_SET_BASE(lp, x)

#define SMC_GET_CONFIG(lp)

#define SMC_SET_CONFIG(lp, x)

#define SMC_GET_COUNTER(lp)

#define SMC_GET_CTL(lp)

#define SMC_SET_CTL(lp, x)

#define SMC_GET_MII(lp)

#define SMC_GET_GP(lp)

#define SMC_SET_GP(lp, x)

#define SMC_SET_MII(lp, x)

#define SMC_GET_MIR(lp)

#define SMC_SET_MIR(lp, x)

#define SMC_GET_MMU_CMD(lp)

#define SMC_SET_MMU_CMD(lp, x)

#define SMC_GET_FIFO(lp)

#define SMC_GET_PTR(lp)

#define SMC_SET_PTR(lp, x)

#define SMC_GET_EPH_STATUS(lp)

#define SMC_GET_RCR(lp)

#define SMC_SET_RCR(lp, x)

#define SMC_GET_REV(lp)

#define SMC_GET_RPC(lp)

#define SMC_SET_RPC(lp, x)

#define SMC_GET_TCR(lp)

#define SMC_SET_TCR(lp, x)

#ifndef SMC_GET_MAC_ADDR
#define SMC_GET_MAC_ADDR(lp, addr)
#endif

#define SMC_SET_MAC_ADDR(lp, addr)

#define SMC_SET_MCAST(lp, x)

#define SMC_PUT_PKT_HDR(lp, status, length)

#define SMC_GET_PKT_HDR(lp, status, length)

#define SMC_PUSH_DATA(lp, p, l)

#define SMC_PULL_DATA(lp, p, l)

#endif  /* _SMC91X_H_ */