cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mcf8390.c (12060B)


      1/*
      2 *  Support for ColdFire CPU based boards using a NS8390 Ethernet device.
      3 *
      4 *  Derived from the many other 8390 drivers.
      5 *
      6 *  (C) Copyright 2012,  Greg Ungerer <gerg@uclinux.org>
      7 *
      8 *  This file is subject to the terms and conditions of the GNU General Public
      9 *  License.  See the file COPYING in the main directory of the Linux
     10 *  distribution for more details.
     11 */
     12
     13#include <linux/module.h>
     14#include <linux/kernel.h>
     15#include <linux/errno.h>
     16#include <linux/platform_device.h>
     17#include <linux/netdevice.h>
     18#include <linux/etherdevice.h>
     19#include <linux/jiffies.h>
     20#include <linux/io.h>
     21#include <asm/mcf8390.h>
     22
     23static const char version[] =
     24	"mcf8390.c: (15-06-2012) Greg Ungerer <gerg@uclinux.org>";
     25
     26#define NE_CMD		0x00
     27#define NE_DATAPORT	0x10	/* NatSemi-defined port window offset */
     28#define NE_RESET	0x1f	/* Issue a read to reset ,a write to clear */
     29#define NE_EN0_ISR	0x07
     30#define NE_EN0_DCFG	0x0e
     31#define NE_EN0_RSARLO	0x08
     32#define NE_EN0_RSARHI	0x09
     33#define NE_EN0_RCNTLO	0x0a
     34#define NE_EN0_RXCR	0x0c
     35#define NE_EN0_TXCR	0x0d
     36#define NE_EN0_RCNTHI	0x0b
     37#define NE_EN0_IMR	0x0f
     38
     39#define NESM_START_PG	0x40	/* First page of TX buffer */
     40#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
     41
     42#ifdef NE2000_ODDOFFSET
     43/*
     44 * A lot of the ColdFire boards use a separate address region for odd offset
     45 * register addresses. The following functions convert and map as required.
     46 * Note that the data port accesses are treated a little differently, and
     47 * always accessed via the insX/outsX functions.
     48 */
     49static inline u32 NE_PTR(u32 addr)
     50{
     51	if (addr & 1)
     52		return addr - 1 + NE2000_ODDOFFSET;
     53	return addr;
     54}
     55
     56static inline u32 NE_DATA_PTR(u32 addr)
     57{
     58	return addr;
     59}
     60
     61void ei_outb(u32 val, u32 addr)
     62{
     63	NE2000_BYTE *rp;
     64
     65	rp = (NE2000_BYTE *) NE_PTR(addr);
     66	*rp = RSWAP(val);
     67}
     68
     69#define	ei_inb	ei_inb
     70u8 ei_inb(u32 addr)
     71{
     72	NE2000_BYTE *rp, val;
     73
     74	rp = (NE2000_BYTE *) NE_PTR(addr);
     75	val = *rp;
     76	return (u8) (RSWAP(val) & 0xff);
     77}
     78
     79void ei_insb(u32 addr, void *vbuf, int len)
     80{
     81	NE2000_BYTE *rp, val;
     82	u8 *buf;
     83
     84	buf = (u8 *) vbuf;
     85	rp = (NE2000_BYTE *) NE_DATA_PTR(addr);
     86	for (; (len > 0); len--) {
     87		val = *rp;
     88		*buf++ = RSWAP(val);
     89	}
     90}
     91
     92void ei_insw(u32 addr, void *vbuf, int len)
     93{
     94	volatile u16 *rp;
     95	u16 w, *buf;
     96
     97	buf = (u16 *) vbuf;
     98	rp = (volatile u16 *) NE_DATA_PTR(addr);
     99	for (; (len > 0); len--) {
    100		w = *rp;
    101		*buf++ = BSWAP(w);
    102	}
    103}
    104
    105void ei_outsb(u32 addr, const void *vbuf, int len)
    106{
    107	NE2000_BYTE *rp, val;
    108	u8 *buf;
    109
    110	buf = (u8 *) vbuf;
    111	rp = (NE2000_BYTE *) NE_DATA_PTR(addr);
    112	for (; (len > 0); len--) {
    113		val = *buf++;
    114		*rp = RSWAP(val);
    115	}
    116}
    117
    118void ei_outsw(u32 addr, const void *vbuf, int len)
    119{
    120	volatile u16 *rp;
    121	u16 w, *buf;
    122
    123	buf = (u16 *) vbuf;
    124	rp = (volatile u16 *) NE_DATA_PTR(addr);
    125	for (; (len > 0); len--) {
    126		w = *buf++;
    127		*rp = BSWAP(w);
    128	}
    129}
    130
    131#else /* !NE2000_ODDOFFSET */
    132
    133#define	ei_inb		inb
    134#define	ei_outb		outb
    135#define	ei_insb		insb
    136#define	ei_insw		insw
    137#define	ei_outsb	outsb
    138#define	ei_outsw	outsw
    139
    140#endif /* !NE2000_ODDOFFSET */
    141
    142#define	ei_inb_p	ei_inb
    143#define	ei_outb_p	ei_outb
    144
    145#include "lib8390.c"
    146
    147/*
    148 * Hard reset the card. This used to pause for the same period that a
    149 * 8390 reset command required, but that shouldn't be necessary.
    150 */
    151static void mcf8390_reset_8390(struct net_device *dev)
    152{
    153	unsigned long reset_start_time = jiffies;
    154	u32 addr = dev->base_addr;
    155	struct ei_device *ei_local = netdev_priv(dev);
    156
    157	netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies);
    158
    159	ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
    160
    161	ei_status.txing = 0;
    162	ei_status.dmaing = 0;
    163
    164	/* This check _should_not_ be necessary, omit eventually. */
    165	while ((ei_inb(addr + NE_EN0_ISR) & ENISR_RESET) == 0) {
    166		if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
    167			netdev_warn(dev, "%s: did not complete\n", __func__);
    168			break;
    169		}
    170	}
    171
    172	ei_outb(ENISR_RESET, addr + NE_EN0_ISR);
    173}
    174
    175/*
    176 * This *shouldn't* happen.
    177 * If it does, it's the last thing you'll see
    178 */
    179static void mcf8390_dmaing_err(const char *func, struct net_device *dev,
    180			       struct ei_device *ei_local)
    181{
    182	netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
    183		func, ei_local->dmaing, ei_local->irqlock);
    184}
    185
    186/*
    187 * Grab the 8390 specific header. Similar to the block_input routine, but
    188 * we don't need to be concerned with ring wrap as the header will be at
    189 * the start of a page, so we optimize accordingly.
    190 */
    191static void mcf8390_get_8390_hdr(struct net_device *dev,
    192				 struct e8390_pkt_hdr *hdr, int ring_page)
    193{
    194	struct ei_device *ei_local = netdev_priv(dev);
    195	u32 addr = dev->base_addr;
    196
    197	if (ei_local->dmaing) {
    198		mcf8390_dmaing_err(__func__, dev, ei_local);
    199		return;
    200	}
    201
    202	ei_local->dmaing |= 0x01;
    203	ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, addr + NE_CMD);
    204	ei_outb(ENISR_RDC, addr + NE_EN0_ISR);
    205	ei_outb(sizeof(struct e8390_pkt_hdr), addr + NE_EN0_RCNTLO);
    206	ei_outb(0, addr + NE_EN0_RCNTHI);
    207	ei_outb(0, addr + NE_EN0_RSARLO);		/* On page boundary */
    208	ei_outb(ring_page, addr + NE_EN0_RSARHI);
    209	ei_outb(E8390_RREAD + E8390_START, addr + NE_CMD);
    210
    211	ei_insw(addr + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr) >> 1);
    212
    213	outb(ENISR_RDC, addr + NE_EN0_ISR);	/* Ack intr */
    214	ei_local->dmaing &= ~0x01;
    215
    216	hdr->count = cpu_to_le16(hdr->count);
    217}
    218
    219/*
    220 * Block input and output, similar to the Crynwr packet driver.
    221 * If you are porting to a new ethercard, look at the packet driver source
    222 * for hints. The NEx000 doesn't share the on-board packet memory --
    223 * you have to put the packet out through the "remote DMA" dataport
    224 * using z_writeb.
    225 */
    226static void mcf8390_block_input(struct net_device *dev, int count,
    227				struct sk_buff *skb, int ring_offset)
    228{
    229	struct ei_device *ei_local = netdev_priv(dev);
    230	u32 addr = dev->base_addr;
    231	char *buf = skb->data;
    232
    233	if (ei_local->dmaing) {
    234		mcf8390_dmaing_err(__func__, dev, ei_local);
    235		return;
    236	}
    237
    238	ei_local->dmaing |= 0x01;
    239	ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, addr + NE_CMD);
    240	ei_outb(ENISR_RDC, addr + NE_EN0_ISR);
    241	ei_outb(count & 0xff, addr + NE_EN0_RCNTLO);
    242	ei_outb(count >> 8, addr + NE_EN0_RCNTHI);
    243	ei_outb(ring_offset & 0xff, addr + NE_EN0_RSARLO);
    244	ei_outb(ring_offset >> 8, addr + NE_EN0_RSARHI);
    245	ei_outb(E8390_RREAD + E8390_START, addr + NE_CMD);
    246
    247	ei_insw(addr + NE_DATAPORT, buf, count >> 1);
    248	if (count & 1)
    249		buf[count - 1] = ei_inb(addr + NE_DATAPORT);
    250
    251	ei_outb(ENISR_RDC, addr + NE_EN0_ISR);	/* Ack intr */
    252	ei_local->dmaing &= ~0x01;
    253}
    254
    255static void mcf8390_block_output(struct net_device *dev, int count,
    256				 const unsigned char *buf,
    257				 const int start_page)
    258{
    259	struct ei_device *ei_local = netdev_priv(dev);
    260	u32 addr = dev->base_addr;
    261	unsigned long dma_start;
    262
    263	/* Make sure we transfer all bytes if 16bit IO writes */
    264	if (count & 0x1)
    265		count++;
    266
    267	if (ei_local->dmaing) {
    268		mcf8390_dmaing_err(__func__, dev, ei_local);
    269		return;
    270	}
    271
    272	ei_local->dmaing |= 0x01;
    273	/* We should already be in page 0, but to be safe... */
    274	ei_outb(E8390_PAGE0 + E8390_START + E8390_NODMA, addr + NE_CMD);
    275
    276	ei_outb(ENISR_RDC, addr + NE_EN0_ISR);
    277
    278	/* Now the normal output. */
    279	ei_outb(count & 0xff, addr + NE_EN0_RCNTLO);
    280	ei_outb(count >> 8, addr + NE_EN0_RCNTHI);
    281	ei_outb(0x00, addr + NE_EN0_RSARLO);
    282	ei_outb(start_page, addr + NE_EN0_RSARHI);
    283	ei_outb(E8390_RWRITE + E8390_START, addr + NE_CMD);
    284
    285	ei_outsw(addr + NE_DATAPORT, buf, count >> 1);
    286
    287	dma_start = jiffies;
    288	while ((ei_inb(addr + NE_EN0_ISR) & ENISR_RDC) == 0) {
    289		if (time_after(jiffies, dma_start + 2 * HZ / 100)) { /* 20ms */
    290			netdev_warn(dev, "timeout waiting for Tx RDC\n");
    291			mcf8390_reset_8390(dev);
    292			__NS8390_init(dev, 1);
    293			break;
    294		}
    295	}
    296
    297	ei_outb(ENISR_RDC, addr + NE_EN0_ISR);	/* Ack intr */
    298	ei_local->dmaing &= ~0x01;
    299}
    300
    301static const struct net_device_ops mcf8390_netdev_ops = {
    302	.ndo_open		= __ei_open,
    303	.ndo_stop		= __ei_close,
    304	.ndo_start_xmit		= __ei_start_xmit,
    305	.ndo_tx_timeout		= __ei_tx_timeout,
    306	.ndo_get_stats		= __ei_get_stats,
    307	.ndo_set_rx_mode	= __ei_set_multicast_list,
    308	.ndo_validate_addr	= eth_validate_addr,
    309	.ndo_set_mac_address	= eth_mac_addr,
    310#ifdef CONFIG_NET_POLL_CONTROLLER
    311	.ndo_poll_controller	= __ei_poll,
    312#endif
    313};
    314
    315static int mcf8390_init(struct net_device *dev)
    316{
    317	static u32 offsets[] = {
    318		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    319		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    320	};
    321	struct ei_device *ei_local = netdev_priv(dev);
    322	unsigned char SA_prom[32];
    323	u32 addr = dev->base_addr;
    324	int start_page, stop_page;
    325	int i, ret;
    326
    327	mcf8390_reset_8390(dev);
    328
    329	/*
    330	 * Read the 16 bytes of station address PROM.
    331	 * We must first initialize registers,
    332	 * similar to NS8390_init(eifdev, 0).
    333	 * We can't reliably read the SAPROM address without this.
    334	 * (I learned the hard way!).
    335	 */
    336	{
    337		static const struct {
    338			u32 value;
    339			u32 offset;
    340		} program_seq[] = {
    341			{E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD},
    342						/* Select page 0 */
    343			{0x48,	NE_EN0_DCFG},	/* 0x48: Set byte-wide access */
    344			{0x00,	NE_EN0_RCNTLO},	/* Clear the count regs */
    345			{0x00,	NE_EN0_RCNTHI},
    346			{0x00,	NE_EN0_IMR},	/* Mask completion irq */
    347			{0xFF,	NE_EN0_ISR},
    348			{E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
    349			{E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */
    350			{32,	NE_EN0_RCNTLO},
    351			{0x00,	NE_EN0_RCNTHI},
    352			{0x00,	NE_EN0_RSARLO},	/* DMA starting at 0x0000 */
    353			{0x00,	NE_EN0_RSARHI},
    354			{E8390_RREAD + E8390_START, NE_CMD},
    355		};
    356		for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
    357			ei_outb(program_seq[i].value,
    358				 addr + program_seq[i].offset);
    359		}
    360	}
    361
    362	for (i = 0; i < 16; i++) {
    363		SA_prom[i] = ei_inb(addr + NE_DATAPORT);
    364		ei_inb(addr + NE_DATAPORT);
    365	}
    366
    367	/* We must set the 8390 for word mode. */
    368	ei_outb(0x49, addr + NE_EN0_DCFG);
    369	start_page = NESM_START_PG;
    370	stop_page = NESM_STOP_PG;
    371
    372	/* Install the Interrupt handler */
    373	ret = request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev);
    374	if (ret)
    375		return ret;
    376
    377	eth_hw_addr_set(dev, SA_prom);
    378
    379	netdev_dbg(dev, "Found ethernet address: %pM\n", dev->dev_addr);
    380
    381	ei_local->name = "mcf8390";
    382	ei_local->tx_start_page = start_page;
    383	ei_local->stop_page = stop_page;
    384	ei_local->word16 = 1;
    385	ei_local->rx_start_page = start_page + TX_PAGES;
    386	ei_local->reset_8390 = mcf8390_reset_8390;
    387	ei_local->block_input = mcf8390_block_input;
    388	ei_local->block_output = mcf8390_block_output;
    389	ei_local->get_8390_hdr = mcf8390_get_8390_hdr;
    390	ei_local->reg_offset = offsets;
    391
    392	dev->netdev_ops = &mcf8390_netdev_ops;
    393	__NS8390_init(dev, 0);
    394	ret = register_netdev(dev);
    395	if (ret) {
    396		free_irq(dev->irq, dev);
    397		return ret;
    398	}
    399
    400	netdev_info(dev, "addr=0x%08x irq=%d, Ethernet Address %pM\n",
    401		addr, dev->irq, dev->dev_addr);
    402	return 0;
    403}
    404
    405static int mcf8390_probe(struct platform_device *pdev)
    406{
    407	struct net_device *dev;
    408	struct resource *mem;
    409	resource_size_t msize;
    410	int ret, irq;
    411
    412	irq = platform_get_irq(pdev, 0);
    413	if (irq < 0)
    414		return -ENXIO;
    415
    416	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    417	if (mem == NULL) {
    418		dev_err(&pdev->dev, "no memory address specified?\n");
    419		return -ENXIO;
    420	}
    421	msize = resource_size(mem);
    422	if (!request_mem_region(mem->start, msize, pdev->name))
    423		return -EBUSY;
    424
    425	dev = ____alloc_ei_netdev(0);
    426	if (dev == NULL) {
    427		release_mem_region(mem->start, msize);
    428		return -ENOMEM;
    429	}
    430
    431	SET_NETDEV_DEV(dev, &pdev->dev);
    432	platform_set_drvdata(pdev, dev);
    433
    434	dev->irq = irq;
    435	dev->base_addr = mem->start;
    436
    437	ret = mcf8390_init(dev);
    438	if (ret) {
    439		release_mem_region(mem->start, msize);
    440		free_netdev(dev);
    441		return ret;
    442	}
    443	return 0;
    444}
    445
    446static int mcf8390_remove(struct platform_device *pdev)
    447{
    448	struct net_device *dev = platform_get_drvdata(pdev);
    449	struct resource *mem;
    450
    451	unregister_netdev(dev);
    452	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    453	if (mem)
    454		release_mem_region(mem->start, resource_size(mem));
    455	free_netdev(dev);
    456	return 0;
    457}
    458
    459static struct platform_driver mcf8390_drv = {
    460	.driver = {
    461		.name	= "mcf8390",
    462	},
    463	.probe		= mcf8390_probe,
    464	.remove		= mcf8390_remove,
    465};
    466
    467module_platform_driver(mcf8390_drv);
    468
    469MODULE_DESCRIPTION("MCF8390 ColdFire NS8390 driver");
    470MODULE_AUTHOR("Greg Ungerer <gerg@uclinux.org>");
    471MODULE_LICENSE("GPL");
    472MODULE_ALIAS("platform:mcf8390");