brintos

brintos / linux-shallow public Read only

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