staging: gpib: Add TNT4882 chip based GPIB driver

Driver for National Instruments TNT4882 based boards

Signed-off-by: Dave Penkler <dpenkler@gmail.com>
Link: https://lore.kernel.org/r/20240918121908.19366-22-dpenkler@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Dave Penkler
2024-09-18 14:19:08 +02:00
committed by Greg Kroah-Hartman
parent 0dc1ad1c00
commit 0cd5b05551
4 changed files with 2345 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA
obj-m += tnt4882.o
tnt4882-objs := tnt4882_gpib.o mite.o

View File

@@ -0,0 +1,221 @@
// 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));
}

View File

@@ -0,0 +1,243 @@
/* 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

File diff suppressed because it is too large Load Diff