1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
/* SPDX-License-Identifier: GPL-2.0 */
/***************************************************************************
* copyright : (C) 2002 by Frank Mori Hess
***************************************************************************/
#include "nec7210.h"
#include "gpibP.h"
#include "amccs5933.h"
#include <linux/delay.h>
#include <linux/interrupt.h>
enum {
PCI_DEVICE_ID_CBOARDS_PCI_GPIB = 0x6,
PCI_DEVICE_ID_CBOARDS_CPCI_GPIB = 0xe,
};
enum pci_chip {
PCI_CHIP_NONE = 0,
PCI_CHIP_AMCC_S5933,
PCI_CHIP_QUANCOM
};
// struct which defines private_data for cb7210 boards
struct cb7210_priv {
struct nec7210_priv nec7210_priv;
struct pci_dev *pci_device;
// base address of amccs5933 pci chip
unsigned long amcc_iobase;
unsigned long fifo_iobase;
unsigned int irq;
enum pci_chip pci_chip;
u8 hs_mode_bits;
unsigned out_fifo_half_empty : 1;
unsigned in_fifo_half_full : 1;
};
// pci-gpib register offset
static const int cb7210_reg_offset = 1;
// uses 10 ioports
static const int cb7210_iosize = 10;
// fifo size in bytes
static const int cb7210_fifo_size = 2048;
static const int cb7210_fifo_width = 2;
// cb7210 specific registers and bits
enum cb7210_regs {
BUS_STATUS = 0x7,
};
enum cb7210_page_in {
BUS_STATUS_PAGE = 1,
};
enum hs_regs {
// write registers
HS_MODE = 0x8, /* HS_MODE register */
HS_INT_LEVEL = 0x9, /* HS_INT_LEVEL register */
// read registers
HS_STATUS = 0x8, /* HS_STATUS register */
};
static inline u32 nec7210_iobase(const struct cb7210_priv *cb_priv)
{
return cb_priv->nec7210_priv.iobase;
}
static inline int cb7210_page_in_bits(unsigned int page)
{
return 0x50 | (page & 0xf);
}
static inline u8 cb7210_paged_read_byte(struct cb7210_priv *cb_priv,
unsigned int register_num, unsigned int page)
{
struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
u8 retval;
unsigned long flags;
spin_lock_irqsave(&nec_priv->register_page_lock, flags);
outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset);
udelay(1);
retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
return retval;
}
// don't use for register_num < 8, since it doesn't lock
static inline u8 cb7210_read_byte(const struct cb7210_priv *cb_priv,
enum hs_regs register_num)
{
const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
u8 retval;
retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
return retval;
}
static inline void cb7210_paged_write_byte(struct cb7210_priv *cb_priv, u8 data,
unsigned int register_num, unsigned int page)
{
struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
unsigned long flags;
spin_lock_irqsave(&nec_priv->register_page_lock, flags);
outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset);
udelay(1);
outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
}
// don't use for register_num < 8, since it doesn't lock
static inline void cb7210_write_byte(const struct cb7210_priv *cb_priv, u8 data,
enum hs_regs register_num)
{
const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
}
enum bus_status_bits {
BSR_ATN_BIT = 0x1,
BSR_EOI_BIT = 0x2,
BSR_SRQ_BIT = 0x4,
BSR_IFC_BIT = 0x8,
BSR_REN_BIT = 0x10,
BSR_DAV_BIT = 0x20,
BSR_NRFD_BIT = 0x40,
BSR_NDAC_BIT = 0x80,
};
/* CBI 488.2 HS control */
/*
* when both bit 0 and 1 are set, it
* 1 clears the transmit state machine to an initial condition
* 2 clears any residual interrupts left latched on cbi488.2
* 3 resets all control bits in HS_MODE to zero
* 4 enables TX empty interrupts
* when both bit 0 and 1 are zero, then the high speed mode is disabled
*/
enum hs_mode_bits {
HS_ENABLE_MASK = 0x3,
HS_TX_ENABLE = (1 << 0),
HS_RX_ENABLE = (1 << 1),
HS_HF_INT_EN = (1 << 3),
HS_CLR_SRQ_INT = (1 << 4),
HS_CLR_EOI_EMPTY_INT = (1 << 5),
HS_CLR_HF_INT = (1 << 6),
HS_SYS_CONTROL = (1 << 7),
};
/* CBI 488.2 status */
enum hs_status_bits {
HS_FIFO_FULL = (1 << 0),
HS_HALF_FULL = (1 << 1),
HS_SRQ_INT = (1 << 2),
HS_EOI_INT = (1 << 3),
HS_TX_MSB_NOT_EMPTY = (1 << 4),
HS_RX_MSB_NOT_EMPTY = (1 << 5),
HS_TX_LSB_NOT_EMPTY = (1 << 6),
HS_RX_LSB_NOT_EMPTY = (1 << 7),
};
/* CBI488.2 hs_int_level register */
enum hs_int_level_bits {
HS_RESET7210 = (1 << 7),
};
static inline unsigned int irq_bits(unsigned int irq)
{
switch (irq) {
case 2:
case 3:
case 4:
case 5:
return irq - 1;
case 7:
return 0x5;
case 10:
return 0x6;
case 11:
return 0x7;
default:
return 0;
}
}
enum cb7210_aux_cmds {
/*
* AUX_RTL2 is an undocumented aux command which causes cb7210 to assert
* (and keep asserted) local rtl message. This is used in conjunction
* with the (stupid) cb7210 implementation
* of the normal nec7210 AUX_RTL aux command, which
* causes the rtl message to toggle between on and off.
*/
AUX_RTL2 = 0xd,
AUX_LO_SPEED = 0x40,
AUX_HI_SPEED = 0x41,
};
|