Commit 0cd5b055 authored by Dave Penkler's avatar Dave Penkler Committed by Greg Kroah-Hartman
Browse files

staging: gpib: Add TNT4882 chip based GPIB driver



Driver for National Instruments TNT4882 based boards

Signed-off-by: default avatarDave Penkler <dpenkler@gmail.com>
Link: https://lore.kernel.org/r/20240918121908.19366-22-dpenkler@gmail.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0dc1ad1c
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA
obj-m += tnt4882.o

tnt4882-objs := tnt4882_gpib.o mite.o


+221 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2

/*
 *	Hardware driver for NI Mite PCI interface chip,
 *	adapted from COMEDI
 *
 *	Copyright (C) 1997-8 David A. Schleef
 *	Copyright (C) 2002 Frank Mori Hess
 *
 *	The PCI-MIO E series driver was originally written by
 *	Tomasz Motylewski <...>, and ported to comedi by ds.
 *
 *	References for specifications:
 *
 *	   321747b.pdf  Register Level Programmer Manual (obsolete)
 *	   321747c.pdf  Register Level Programmer Manual (new)
 *	   DAQ-STC reference manual
 *
 *	Other possibly relevant info:
 *
 *	   320517c.pdf  User manual (obsolete)
 *	   320517f.pdf  User manual (new)
 *	   320889a.pdf  delete
 *	   320906c.pdf  maximum signal ratings
 *	   321066a.pdf  about 16x
 *	   321791a.pdf  discontinuation of at-mio-16e-10 rev. c
 *	   321808a.pdf  about at-mio-16e-10 rev P
 *	   321837a.pdf  discontinuation of at-mio-16de-10 rev d
 *	   321838a.pdf  about at-mio-16de-10 rev N
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/io.h>
#include <linux/slab.h>

#include "mite.h"

#define PCI_MITE_SIZE		4096
#define PCI_DAQ_SIZE		4096

struct mite_struct *mite_devices;

#define TOP_OF_PAGE(x) ((x) | (~(PAGE_MASK)))

void mite_init(void)
{
	struct pci_dev *pcidev;
	struct mite_struct *mite;

	for (pcidev = pci_get_device(PCI_VENDOR_ID_NATINST, PCI_ANY_ID, NULL);
		pcidev;
		pcidev = pci_get_device(PCI_VENDOR_ID_NATINST, PCI_ANY_ID, pcidev)) {
		mite = kmalloc(sizeof(*mite), GFP_KERNEL);
		if (!mite)
			return;

		memset(mite, 0, sizeof(*mite));

		mite->pcidev = pcidev;
		pci_dev_get(mite->pcidev);
		mite->next = mite_devices;
		mite_devices = mite;
	}
}

int mite_setup(struct mite_struct *mite)
{
	u32 addr;

	if (pci_enable_device(mite->pcidev)) {
		pr_err("mite: error enabling mite.\n");
		return -EIO;
	}
	pci_set_master(mite->pcidev);
	if (pci_request_regions(mite->pcidev, "mite")) {
		pr_err("mite: failed to request mite io regions.\n");
		return -EIO;
	};
	addr = pci_resource_start(mite->pcidev, 0);
	mite->mite_phys_addr = addr;
	mite->mite_io_addr = ioremap(addr, pci_resource_len(mite->pcidev, 0));
	if (!mite->mite_io_addr) {
		pr_err("mite: failed to remap mite io memory address.\n");
		return -ENOMEM;
	}
	pr_info("mite: 0x%08lx mapped to %p\n", mite->mite_phys_addr, mite->mite_io_addr);
	addr = pci_resource_start(mite->pcidev, 1);
	mite->daq_phys_addr = addr;
	mite->daq_io_addr = ioremap(mite->daq_phys_addr, pci_resource_len(mite->pcidev, 1));
	if (!mite->daq_io_addr)	{
		pr_err("mite: failed to remap daq io memory address.\n");
		return -ENOMEM;
	}
	pr_info("mite: daq: 0x%08lx mapped to %p\n", mite->daq_phys_addr, mite->daq_io_addr);
	writel(mite->daq_phys_addr | WENAB, mite->mite_io_addr + MITE_IODWBSR);
	mite->used = 1;
	return 0;
}

void mite_cleanup(void)
{
	struct mite_struct *mite, *next;

	for (mite = mite_devices; mite; mite = next) {
		next = mite->next;
		if (mite->pcidev)
			pci_dev_put(mite->pcidev);
		kfree(mite);
	}
}

void mite_unsetup(struct mite_struct *mite)
{
	if (!mite)
		return;
	if (mite->mite_io_addr)	{
		iounmap(mite->mite_io_addr);
		mite->mite_io_addr = NULL;
	}
	if (mite->daq_io_addr) {
		iounmap(mite->daq_io_addr);
		mite->daq_io_addr = NULL;
	}
	if (mite->mite_phys_addr) {
		pci_release_regions(mite->pcidev);
		pci_disable_device(mite->pcidev);
		mite->mite_phys_addr = 0;
	}
	mite->used = 0;
}

void mite_list_devices(void)
{
	struct mite_struct *mite, *next;

	pr_info("Available NI PCI device IDs:");
	if (mite_devices)
		for (mite = mite_devices; mite; mite = next) {
			next = mite->next;
			pr_info(" 0x%04x", mite_device_id(mite));
			if (mite->used)
				pr_info("(used)");
	}
	pr_info("\n");
}

int mite_bytes_transferred(struct mite_struct *mite, int chan)
{
	int dar, fcr;

	dar = readl(mite->mite_io_addr + MITE_DAR + CHAN_OFFSET(chan));
	fcr = readl(mite->mite_io_addr + MITE_FCR + CHAN_OFFSET(chan)) & 0x000000FF;
	return dar - fcr;
}

int mite_dma_tcr(struct mite_struct *mite)
{
	int tcr;
	int lkar;

	lkar = readl(mite->mite_io_addr + CHAN_OFFSET(0) + MITE_LKAR);
	tcr = readl(mite->mite_io_addr + CHAN_OFFSET(0) + MITE_TCR);
	MDPRINTK("lkar=0x%08x tcr=%d\n", lkar, tcr);

	return tcr;
}

void mite_dma_disarm(struct mite_struct *mite)
{
	int chor;

	/* disarm */
	chor = CHOR_ABORT;
	writel(chor, mite->mite_io_addr + CHAN_OFFSET(0) + MITE_CHOR);
}

void mite_dump_regs(struct mite_struct *mite)
{
	void *addr = 0;
	unsigned long temp = 0;

	pr_info("mite address is  =0x%p\n", mite->mite_io_addr);

	addr = mite->mite_io_addr + MITE_CHOR + CHAN_OFFSET(0);
	pr_info("mite status[CHOR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
	//mite_decode(mite_CHOR_strings,temp);
	addr = mite->mite_io_addr + MITE_CHCR + CHAN_OFFSET(0);
	pr_info("mite status[CHCR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
	//mite_decode(mite_CHCR_strings,temp);
	addr = mite->mite_io_addr + MITE_TCR + CHAN_OFFSET(0);
	pr_info("mite status[TCR] at 0x%p =0x%08x\n", addr, readl(addr));
	addr = mite->mite_io_addr + MITE_MCR + CHAN_OFFSET(0);
	pr_info("mite status[MCR] at 0x%p =0x%08lx\n", addr, temp = readl(addr));
	//mite_decode(mite_MCR_strings,temp);
	addr = mite->mite_io_addr + MITE_MAR + CHAN_OFFSET(0);
	pr_info("mite status[MAR] at 0x%p =0x%08x\n", addr, readl(addr));
	addr = mite->mite_io_addr + MITE_DCR + CHAN_OFFSET(0);
	pr_info("mite status[DCR] at 0x%p =0x%08lx\n", addr, temp = readl(addr));
	//mite_decode(mite_CR_strings,temp);
	addr = mite->mite_io_addr + MITE_DAR + CHAN_OFFSET(0);
	pr_info("mite status[DAR] at 0x%p =0x%08x\n", addr, readl(addr));
	addr = mite->mite_io_addr + MITE_LKCR + CHAN_OFFSET(0);
	pr_info("mite status[LKCR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
	//mite_decode(mite_CR_strings,temp);
	addr = mite->mite_io_addr + MITE_LKAR + CHAN_OFFSET(0);
	pr_info("mite status[LKAR]at 0x%p =0x%08x\n", addr, readl(addr));

	addr = mite->mite_io_addr + MITE_CHSR + CHAN_OFFSET(0);
	pr_info("mite status[CHSR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
	//mite_decode(mite_CHSR_strings,temp);
	addr = mite->mite_io_addr + MITE_FCR + CHAN_OFFSET(0);
	pr_info("mite status[FCR] at 0x%p =0x%08x\n\n", addr, readl(addr));
}
+243 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2 */

/*
 *   Hardware driver for NI Mite PCI interface chip
 *
 *   Copyright (C) 1999 David A. Schleef <ds@stm.lbl.gov>
 */

#ifndef _MITE_H_
#define _MITE_H_

#include <linux/pci.h>

#define PCI_VENDOR_ID_NATINST		0x1093

//#define DEBUG_MITE

#ifdef DEBUG_MITE
#define MDPRINTK(format, args...) pr_debug(format, ## args)
#else
#define MDPRINTK(args...)
#endif

#define MITE_RING_SIZE 3000
struct mite_dma_chain {
	u32 count;
	u32 addr;
	u32 next;
};

struct mite_struct {
	struct mite_struct *next;
	int used;

	struct pci_dev *pcidev;
	unsigned long mite_phys_addr;
	void *mite_io_addr;
	unsigned long daq_phys_addr;
	void *daq_io_addr;

	int DMA_CheckNearEnd;

	struct mite_dma_chain ring[MITE_RING_SIZE];
};

extern struct mite_struct *mite_devices;

extern inline unsigned int mite_irq(struct mite_struct *mite)
{
	return mite->pcidev->irq;
};

extern inline unsigned int mite_device_id(struct mite_struct *mite)
{
	return mite->pcidev->device;
};

void mite_init(void);
void mite_cleanup(void);
int mite_setup(struct mite_struct *mite);
void mite_unsetup(struct mite_struct *mite);
void mite_list_devices(void);

int mite_dma_tcr(struct mite_struct *mite);

void mite_dma_arm(struct mite_struct *mite);
void mite_dma_disarm(struct mite_struct *mite);

void mite_dump_regs(struct mite_struct *mite);
void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan, int dir);
int mite_bytes_transferred(struct mite_struct *mite, int chan);

#define CHAN_OFFSET(x)			(0x100 * (x))

/* DMA base for chan 0 is 0x500, chan 1 is 0x600 */

#define MITE_CHOR		0x500
#define CHOR_DMARESET			BIT(31)
#define CHOR_SET_SEND_TC		BIT(11)
#define CHOR_CLR_SEND_TC		BIT(10)
#define CHOR_SET_LPAUSE			BIT(9)
#define CHOR_CLR_LPAUSE			BIT(8)
#define CHOR_CLRDONE			BIT(7)
#define CHOR_CLRRB			BIT(6)
#define CHOR_CLRLC			BIT(5)
#define CHOR_FRESET			BIT(4)
#define CHOR_ABORT			BIT(3)
#define CHOR_STOP			BIT(2)
#define CHOR_CONT			BIT(1)
#define CHOR_START			BIT(0)
#define CHOR_PON			(CHOR_CLR_SEND_TC | CHOR_CLR_LPAUSE)

#define MITE_CHCR		0x504
#define CHCR_SET_DMA_IE			BIT(31)
#define CHCR_CLR_DMA_IE			BIT(30)
#define CHCR_SET_LINKP_IE		BIT(29)
#define CHCR_CLR_LINKP_IE		BIT(28)
#define CHCR_SET_SAR_IE			BIT(27)
#define CHCR_CLR_SAR_IE			BIT(26)
#define CHCR_SET_DONE_IE		BIT(25)
#define CHCR_CLR_DONE_IE		BIT(24)
#define CHCR_SET_MRDY_IE		BIT(23)
#define CHCR_CLR_MRDY_IE		BIT(22)
#define CHCR_SET_DRDY_IE		BIT(21)
#define CHCR_CLR_DRDY_IE		BIT(20)
#define CHCR_SET_LC_IE			BIT(19)
#define CHCR_CLR_LC_IE			BIT(18)
#define CHCR_SET_CONT_RB_IE		BIT(17)
#define CHCR_CLR_CONT_RB_IE		BIT(16)
#define CHCR_FIFODIS			BIT(15)
#define CHCR_FIFO_ON			0
#define CHCR_BURSTEN			BIT(14)
#define CHCR_NO_BURSTEN			0
#define CHCR_NFTP(x)			((x) << 11)
#define CHCR_NFTP0			CHCR_NFTP(0)
#define CHCR_NFTP1			CHCR_NFTP(1)
#define CHCR_NFTP2			CHCR_NFTP(2)
#define CHCR_NFTP4			CHCR_NFTP(3)
#define CHCR_NFTP8			CHCR_NFTP(4)
#define CHCR_NFTP16			CHCR_NFTP(5)
#define CHCR_NETP(x)			((x) << 11)
#define CHCR_NETP0			CHCR_NETP(0)
#define CHCR_NETP1			CHCR_NETP(1)
#define CHCR_NETP2			CHCR_NETP(2)
#define CHCR_NETP4			CHCR_NETP(3)
#define CHCR_NETP8			CHCR_NETP(4)
#define CHCR_CHEND1			BIT(5)
#define CHCR_CHEND0			BIT(4)
#define CHCR_DIR			BIT(3)
#define CHCR_DEV_TO_MEM			CHCR_DIR
#define CHCR_MEM_TO_DEV			0
#define CHCR_NORMAL			((0) << 0)
#define CHCR_CONTINUE			((1) << 0)
#define CHCR_RINGBUFF			((2) << 0)
#define CHCR_LINKSHORT			((4) << 0)
#define CHCR_LINKLONG			((5) << 0)
#define CHCRPON				(CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | CHCR_CLR_SAR_IE | \
					 CHCR_CLR_DONE_IE | CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE | \
					 CHCR_CLR_LC_IE | CHCR_CLR_CONT_IE)

#define MITE_TCR		0x508

/* CR bits */
#define CR_RL(x)			((x) << 21)
#define CR_RL0				CR_RL(0)
#define CR_RL1				CR_RL(1)
#define CR_RL2				CR_RL(2)
#define CR_RL4				CR_RL(3)
#define CR_RL8				CR_RL(4)
#define CR_RL16				CR_RL(5)
#define CR_RL32				CR_RL(6)
#define CR_RL64				CR_RL(7)
#define CR_RD(x)			((x) << 19)
#define CR_RD0				CR_RD(0)
#define CR_RD32				CR_RD(1)
#define CR_RD512			CR_RD(2)
#define CR_RD8192			CR_RD(3)
#define CR_REQS(x)			((x) << 16)
#define CR_REQSDRQ0			CR_REQS(4)
#define CR_REQSDRQ1			CR_REQS(5)
#define CR_REQSDRQ2			CR_REQS(6)
#define CR_REQSDRQ3			CR_REQS(7)
#define CR_ASEQX(x)			((x) << 10)
#define CR_ASEQX0			CR_ASEQX(0)
#define	CR_ASEQDONT			CR_ASEQX0
#define CR_ASEQXP1			CR_ASEQX(1)
#define CR_ASEQUP			CR_ASEQXP1
#define CR_ASEQXP2			CR_ASEQX(2)
#define CR_ASEQDOWN			CR_ASEQXP2
#define CR_ASEQXP4			CR_ASEQX(3)
#define CR_ASEQXP8			CR_ASEQX(4)
#define CR_ASEQXP16			CR_ASEQX(5)
#define CR_ASEQXP32			CR_ASEQX(6)
#define CR_ASEQXP64			CR_ASEQX(7)
#define CR_ASEQXM1			CR_ASEQX(9)
#define CR_ASEQXM2			CR_ASEQX(10)
#define CR_ASEQXM4			CR_ASEQX(11)
#define CR_ASEQXM8			CR_ASEQX(12)
#define CR_ASEQXM16			CR_ASEQX(13)
#define CR_ASEQXM32			CR_ASEQX(14)
#define CR_ASEQXM64			CR_ASEQX(15)
#define CR_PSIZEBYTE			BIT(8)
#define CR_PSIZEHALF			(2 << 8)
#define CR_PSIZEWORD			(3 << 8)
#define CR_PORTCPU			(0 << 6)
#define CR_PORTIO			BIT(6)
#define CR_PORTVXI			(2 << 6)
#define CR_PORTMXI			(3 << 6)
#define CR_AMDEVICE			BIT(0)

#define CHSR_INT			0x80000000
#define CHSR_DONE			0x02000000
#define CHSR_LINKC			0x00080000

#define MITE_MCR		0x50c
#define	MCRPON				0

#define MITE_MAR		0x510

#define MITE_DCR		0x514
#define DCR_NORMAL			BIT(29)
#define DCRPON				0

#define MITE_DAR		0x518

#define MITE_LKCR		0x51c

#define MITE_LKAR		0x520
#define MITE_LLKAR		0x524
#define MITE_BAR		0x528
#define MITE_BCR		0x52c
#define MITE_SAR		0x530
#define MITE_WSCR		0x534
#define MITE_WSER		0x538
#define MITE_CHSR		0x53c
#define MITE_FCR		0x540

#define MITE_FIFO		0x80
#define MITE_FIFOEND		0xff

#define MITE_AMRAM		        0x00
#define MITE_AMDEVICE		        0x01
#define MITE_AMHOST_A32_SINGLE	        0x09
#define MITE_AMHOST_A24_SINGLE	        0x39
#define MITE_AMHOST_A16_SINGLE	        0x29
#define MITE_AMHOST_A32_BLOCK	        0x0b
#define MITE_AMHOST_A32D64_BLOCK	0x08
#define MITE_AMHOST_A24_BLOCK	        0x3b

enum mite_registers {
	MITE_IODWBSR = 0xc0, //IO Device Window Base Size Register
	MITE_CSIGR = 0x460,	//chip signature
	MITE_IODWBSR_1 = 0xc4, // IO Device Window Base Size Register 1 (used by 6602 boards)
	MITE_IODWCR_1 = 0xf4
};

enum MITE_IODWBSR_bits {
	WENAB = 0x80,	// window enable
	WENAB_6602 = 0x8c // window enable for 6602 boards
};

#endif
+1874 −0

File added.

Preview size limit exceeded, changes collapsed.