brintos

brintos / linux-shallow public Read only

0
0
Text · 10.4 KiB · fe7a747 Raw
378 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <linux/module.h>3#include <linux/netdevice.h>4#include <linux/platform_device.h>5#include <linux/zorro.h>6#include <net/ax88796.h>7#include <asm/amigaints.h>8 9#define ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF100 \10		ZORRO_ID(INDIVIDUAL_COMPUTERS, 0x64, 0)11 12#define XS100_IRQSTATUS_BASE 0x4013#define XS100_8390_BASE 0x80014 15/* Longword-access area. Translated to 2 16-bit access cycles by the16 * X-Surf 100 FPGA17 */18#define XS100_8390_DATA32_BASE 0x800019#define XS100_8390_DATA32_SIZE 0x200020/* Sub-Areas for fast data register access; addresses relative to area begin */21#define XS100_8390_DATA_READ32_BASE 0x088022#define XS100_8390_DATA_WRITE32_BASE 0x0C8023#define XS100_8390_DATA_AREA_SIZE 0x8024 25/* force unsigned long back to 'void __iomem *' */26#define ax_convert_addr(_a) ((void __force __iomem *)(_a))27 28#define ei_inb(_a) z_readb(ax_convert_addr(_a))29#define ei_outb(_v, _a) z_writeb(_v, ax_convert_addr(_a))30 31#define ei_inw(_a) z_readw(ax_convert_addr(_a))32#define ei_outw(_v, _a) z_writew(_v, ax_convert_addr(_a))33 34#define ei_inb_p(_a) ei_inb(_a)35#define ei_outb_p(_v, _a) ei_outb(_v, _a)36 37/* define EI_SHIFT() to take into account our register offsets */38#define EI_SHIFT(x) (ei_local->reg_offset[(x)])39 40/* Ensure we have our RCR base value */41#define AX88796_PLATFORM42 43#include "8390.h"44 45/* from ne.c */46#define NE_CMD		EI_SHIFT(0x00)47#define NE_RESET	EI_SHIFT(0x1f)48#define NE_DATAPORT	EI_SHIFT(0x10)49 50struct xsurf100_ax_plat_data {51	struct ax_plat_data ax;52	void __iomem *base_regs;53	void __iomem *data_area;54};55 56static int is_xsurf100_network_irq(struct platform_device *pdev)57{58	struct xsurf100_ax_plat_data *xs100 = dev_get_platdata(&pdev->dev);59 60	return (readw(xs100->base_regs + XS100_IRQSTATUS_BASE) & 0xaaaa) != 0;61}62 63/* These functions guarantee that the iomem is accessed with 32 bit64 * cycles only. z_memcpy_fromio / z_memcpy_toio don't65 */66static void z_memcpy_fromio32(void *dst, const void __iomem *src, size_t bytes)67{68	while (bytes > 32) {69		asm __volatile__70		   ("movem.l (%0)+,%%d0-%%d7\n"71		    "movem.l %%d0-%%d7,(%1)\n"72		    "adda.l #32,%1" : "=a"(src), "=a"(dst)73		    : "0"(src), "1"(dst) : "d0", "d1", "d2", "d3", "d4",74					   "d5", "d6", "d7", "memory");75		bytes -= 32;76	}77	while (bytes) {78		*(uint32_t *)dst = z_readl(src);79		src += 4;80		dst += 4;81		bytes -= 4;82	}83}84 85static void z_memcpy_toio32(void __iomem *dst, const void *src, size_t bytes)86{87	while (bytes) {88		z_writel(*(const uint32_t *)src, dst);89		src += 4;90		dst += 4;91		bytes -= 4;92	}93}94 95static void xs100_write(struct net_device *dev, const void *src,96			unsigned int count)97{98	struct ei_device *ei_local = netdev_priv(dev);99	struct platform_device *pdev = to_platform_device(dev->dev.parent);100	struct xsurf100_ax_plat_data *xs100 = dev_get_platdata(&pdev->dev);101 102	/* copy whole blocks */103	while (count > XS100_8390_DATA_AREA_SIZE) {104		z_memcpy_toio32(xs100->data_area +105				XS100_8390_DATA_WRITE32_BASE, src,106				XS100_8390_DATA_AREA_SIZE);107		src += XS100_8390_DATA_AREA_SIZE;108		count -= XS100_8390_DATA_AREA_SIZE;109	}110	/* copy whole dwords */111	z_memcpy_toio32(xs100->data_area + XS100_8390_DATA_WRITE32_BASE,112			src, count & ~3);113	src += count & ~3;114	if (count & 2) {115		ei_outw(*(uint16_t *)src, ei_local->mem + NE_DATAPORT);116		src += 2;117	}118	if (count & 1)119		ei_outb(*(uint8_t *)src, ei_local->mem + NE_DATAPORT);120}121 122static void xs100_read(struct net_device *dev, void *dst, unsigned int count)123{124	struct ei_device *ei_local = netdev_priv(dev);125	struct platform_device *pdev = to_platform_device(dev->dev.parent);126	struct xsurf100_ax_plat_data *xs100 = dev_get_platdata(&pdev->dev);127 128	/* copy whole blocks */129	while (count > XS100_8390_DATA_AREA_SIZE) {130		z_memcpy_fromio32(dst, xs100->data_area +131				  XS100_8390_DATA_READ32_BASE,132				  XS100_8390_DATA_AREA_SIZE);133		dst += XS100_8390_DATA_AREA_SIZE;134		count -= XS100_8390_DATA_AREA_SIZE;135	}136	/* copy whole dwords */137	z_memcpy_fromio32(dst, xs100->data_area + XS100_8390_DATA_READ32_BASE,138			  count & ~3);139	dst += count & ~3;140	if (count & 2) {141		*(uint16_t *)dst = ei_inw(ei_local->mem + NE_DATAPORT);142		dst += 2;143	}144	if (count & 1)145		*(uint8_t *)dst = ei_inb(ei_local->mem + NE_DATAPORT);146}147 148/* Block input and output, similar to the Crynwr packet driver. If149 * you are porting to a new ethercard, look at the packet driver150 * source for hints. The NEx000 doesn't share the on-board packet151 * memory -- you have to put the packet out through the "remote DMA"152 * dataport using ei_outb.153 */154static void xs100_block_input(struct net_device *dev, int count,155			      struct sk_buff *skb, int ring_offset)156{157	struct ei_device *ei_local = netdev_priv(dev);158	void __iomem *nic_base = ei_local->mem;159	char *buf = skb->data;160 161	if (ei_local->dmaing) {162		netdev_err(dev,163			   "DMAing conflict in %s [DMAstat:%d][irqlock:%d]\n",164			   __func__,165			   ei_local->dmaing, ei_local->irqlock);166		return;167	}168 169	ei_local->dmaing |= 0x01;170 171	ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);172	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);173	ei_outb(count >> 8, nic_base + EN0_RCNTHI);174	ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);175	ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);176	ei_outb(E8390_RREAD + E8390_START, nic_base + NE_CMD);177 178	xs100_read(dev, buf, count);179 180	ei_local->dmaing &= ~1;181}182 183static void xs100_block_output(struct net_device *dev, int count,184			       const unsigned char *buf, const int start_page)185{186	struct ei_device *ei_local = netdev_priv(dev);187	void __iomem *nic_base = ei_local->mem;188	unsigned long dma_start;189 190	/* Round the count up for word writes. Do we need to do this?191	 * What effect will an odd byte count have on the 8390?  I192	 * should check someday.193	 */194	if (ei_local->word16 && (count & 0x01))195		count++;196 197	/* This *shouldn't* happen. If it does, it's the last thing198	 * you'll see199	 */200	if (ei_local->dmaing) {201		netdev_err(dev,202			   "DMAing conflict in %s [DMAstat:%d][irqlock:%d]\n",203			   __func__,204			   ei_local->dmaing, ei_local->irqlock);205		return;206	}207 208	ei_local->dmaing |= 0x01;209	/* We should already be in page 0, but to be safe... */210	ei_outb(E8390_PAGE0 + E8390_START + E8390_NODMA, nic_base + NE_CMD);211 212	ei_outb(ENISR_RDC, nic_base + EN0_ISR);213 214	/* Now the normal output. */215	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);216	ei_outb(count >> 8, nic_base + EN0_RCNTHI);217	ei_outb(0x00, nic_base + EN0_RSARLO);218	ei_outb(start_page, nic_base + EN0_RSARHI);219 220	ei_outb(E8390_RWRITE + E8390_START, nic_base + NE_CMD);221 222	xs100_write(dev, buf, count);223 224	dma_start = jiffies;225 226	while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {227		if (jiffies - dma_start > 2 * HZ / 100) {	/* 20ms */228			netdev_warn(dev, "timeout waiting for Tx RDC.\n");229			ei_local->reset_8390(dev);230			ax_NS8390_reinit(dev);231			break;232		}233	}234 235	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */236	ei_local->dmaing &= ~0x01;237}238 239static int xsurf100_probe(struct zorro_dev *zdev,240			  const struct zorro_device_id *ent)241{242	struct platform_device *pdev;243	struct xsurf100_ax_plat_data ax88796_data;244	struct resource res[2] = {245		DEFINE_RES_NAMED(IRQ_AMIGA_PORTS, 1, NULL,246				 IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE),247		DEFINE_RES_MEM(zdev->resource.start + XS100_8390_BASE,248			       4 * 0x20)249	};250	int reg;251	/* This table is referenced in the device structure, so it must252	 * outlive the scope of xsurf100_probe.253	 */254	static u32 reg_offsets[32];255	int ret = 0;256 257	/* X-Surf 100 control and 32 bit ring buffer data access areas.258	 * These resources are not used by the ax88796 driver, so must259	 * be requested here and passed via platform data.260	 */261 262	if (!request_mem_region(zdev->resource.start, 0x100, zdev->name)) {263		dev_err(&zdev->dev, "cannot reserve X-Surf 100 control registers\n");264		return -ENXIO;265	}266 267	if (!request_mem_region(zdev->resource.start +268				XS100_8390_DATA32_BASE,269				XS100_8390_DATA32_SIZE,270				"X-Surf 100 32-bit data access")) {271		dev_err(&zdev->dev, "cannot reserve 32-bit area\n");272		ret = -ENXIO;273		goto exit_req;274	}275 276	for (reg = 0; reg < 0x20; reg++)277		reg_offsets[reg] = 4 * reg;278 279	memset(&ax88796_data, 0, sizeof(ax88796_data));280	ax88796_data.ax.flags = AXFLG_HAS_EEPROM;281	ax88796_data.ax.wordlength = 2;282	ax88796_data.ax.dcr_val = 0x48;283	ax88796_data.ax.rcr_val = 0x40;284	ax88796_data.ax.reg_offsets = reg_offsets;285	ax88796_data.ax.check_irq = is_xsurf100_network_irq;286	ax88796_data.base_regs = ioremap(zdev->resource.start, 0x100);287 288	/* error handling for ioremap regs */289	if (!ax88796_data.base_regs) {290		dev_err(&zdev->dev, "Cannot ioremap area %pR (registers)\n",291			&zdev->resource);292 293		ret = -ENXIO;294		goto exit_req2;295	}296 297	ax88796_data.data_area = ioremap(zdev->resource.start +298			XS100_8390_DATA32_BASE, XS100_8390_DATA32_SIZE);299 300	/* error handling for ioremap data */301	if (!ax88796_data.data_area) {302		dev_err(&zdev->dev,303			"Cannot ioremap area %pR offset %x (32-bit access)\n",304			&zdev->resource,  XS100_8390_DATA32_BASE);305 306		ret = -ENXIO;307		goto exit_mem;308	}309 310	ax88796_data.ax.block_output = xs100_block_output;311	ax88796_data.ax.block_input = xs100_block_input;312 313	pdev = platform_device_register_resndata(&zdev->dev, "ax88796",314						 zdev->slotaddr, res, 2,315						 &ax88796_data,316						 sizeof(ax88796_data));317 318	if (IS_ERR(pdev)) {319		dev_err(&zdev->dev, "cannot register platform device\n");320		ret = -ENXIO;321		goto exit_mem2;322	}323 324	zorro_set_drvdata(zdev, pdev);325 326	if (!ret)327		return 0;328 329 exit_mem2:330	iounmap(ax88796_data.data_area);331 332 exit_mem:333	iounmap(ax88796_data.base_regs);334 335 exit_req2:336	release_mem_region(zdev->resource.start + XS100_8390_DATA32_BASE,337			   XS100_8390_DATA32_SIZE);338 339 exit_req:340	release_mem_region(zdev->resource.start, 0x100);341 342	return ret;343}344 345static void xsurf100_remove(struct zorro_dev *zdev)346{347	struct platform_device *pdev = zorro_get_drvdata(zdev);348	struct xsurf100_ax_plat_data *xs100 = dev_get_platdata(&pdev->dev);349 350	platform_device_unregister(pdev);351 352	iounmap(xs100->base_regs);353	release_mem_region(zdev->resource.start, 0x100);354	iounmap(xs100->data_area);355	release_mem_region(zdev->resource.start + XS100_8390_DATA32_BASE,356			   XS100_8390_DATA32_SIZE);357}358 359static const struct zorro_device_id xsurf100_zorro_tbl[] = {360	{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF100, },361	{ 0 }362};363 364MODULE_DEVICE_TABLE(zorro, xsurf100_zorro_tbl);365 366static struct zorro_driver xsurf100_driver = {367	.name           = "xsurf100",368	.id_table       = xsurf100_zorro_tbl,369	.probe          = xsurf100_probe,370	.remove         = xsurf100_remove,371};372 373module_driver(xsurf100_driver, zorro_register_driver, zorro_unregister_driver);374 375MODULE_DESCRIPTION("X-Surf 100 driver");376MODULE_AUTHOR("Michael Karcher <kernel@mkarcher.dialup.fu-berlin.de>");377MODULE_LICENSE("GPL v2");378