| /* SPDX-License-Identifier: GPL-2.0 */ |
| |
| /*************************************************************************** |
| * copyright : (C) 2002 by Frank Mori Hess |
| ***************************************************************************/ |
| |
| #ifndef _TMS9914_H |
| #define _TMS9914_H |
| |
| #include <linux/types.h> |
| #include <linux/interrupt.h> |
| #include "gpib_state_machines.h" |
| #include "gpib_types.h" |
| |
| enum tms9914_holdoff_mode { |
| TMS9914_HOLDOFF_NONE, |
| TMS9914_HOLDOFF_EOI, |
| TMS9914_HOLDOFF_ALL, |
| }; |
| |
| /* struct used to provide variables local to a tms9914 chip */ |
| struct tms9914_priv { |
| #ifdef CONFIG_HAS_IOPORT |
| u32 iobase; |
| #endif |
| void __iomem *mmiobase; |
| unsigned int offset; // offset between successive tms9914 io addresses |
| unsigned int dma_channel; |
| // software copy of bits written to interrupt mask registers |
| u8 imr0_bits, imr1_bits; |
| // bits written to address mode register |
| u8 admr_bits; |
| u8 auxa_bits; // bits written to auxiliary register A |
| // used to keep track of board's state, bit definitions given below |
| unsigned long state; |
| u8 eos; // eos character |
| short eos_flags; |
| u8 spoll_status; |
| enum tms9914_holdoff_mode holdoff_mode; |
| unsigned int ppoll_line; |
| enum talker_function_state talker_state; |
| enum listener_function_state listener_state; |
| unsigned ppoll_sense : 1; |
| unsigned ppoll_enable : 1; |
| unsigned ppoll_configure_state : 1; |
| unsigned primary_listen_addressed : 1; |
| unsigned primary_talk_addressed : 1; |
| unsigned holdoff_on_end : 1; |
| unsigned holdoff_on_all : 1; |
| unsigned holdoff_active : 1; |
| // wrappers for outb, inb, readb, or writeb |
| u8 (*read_byte)(struct tms9914_priv *priv, unsigned int register_number); |
| void (*write_byte)(struct tms9914_priv *priv, u8 byte, unsigned int |
| register_number); |
| }; |
| |
| // slightly shorter way to access read_byte and write_byte |
| static inline u8 read_byte(struct tms9914_priv *priv, unsigned int register_number) |
| { |
| return priv->read_byte(priv, register_number); |
| } |
| |
| static inline void write_byte(struct tms9914_priv *priv, u8 byte, unsigned int register_number) |
| { |
| priv->write_byte(priv, byte, register_number); |
| } |
| |
| // struct tms9914_priv.state bit numbers |
| enum { |
| PIO_IN_PROGRESS_BN, // pio transfer in progress |
| DMA_READ_IN_PROGRESS_BN, // dma read transfer in progress |
| DMA_WRITE_IN_PROGRESS_BN, // dma write transfer in progress |
| READ_READY_BN, // board has data byte available to read |
| WRITE_READY_BN, // board is ready to send a data byte |
| COMMAND_READY_BN, // board is ready to send a command byte |
| RECEIVED_END_BN, // received END |
| BUS_ERROR_BN, // bus error |
| DEV_CLEAR_BN, // device clear received |
| }; |
| |
| // interface functions |
| int tms9914_read(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, |
| size_t length, int *end, size_t *bytes_read); |
| int tms9914_write(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, |
| size_t length, int send_eoi, size_t *bytes_written); |
| int tms9914_command(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, |
| size_t length, size_t *bytes_written); |
| int tms9914_take_control(struct gpib_board *board, struct tms9914_priv *priv, int syncronous); |
| /* |
| * alternate version of tms9914_take_control which works around buggy tcs |
| * implementation. |
| */ |
| int tms9914_take_control_workaround(struct gpib_board *board, struct tms9914_priv *priv, |
| int syncronous); |
| int tms9914_go_to_standby(struct gpib_board *board, struct tms9914_priv *priv); |
| int tms9914_request_system_control(struct gpib_board *board, struct tms9914_priv *priv, |
| int request_control); |
| void tms9914_interface_clear(struct gpib_board *board, struct tms9914_priv *priv, int assert); |
| void tms9914_remote_enable(struct gpib_board *board, struct tms9914_priv *priv, int enable); |
| int tms9914_enable_eos(struct gpib_board *board, struct tms9914_priv *priv, u8 eos_bytes, |
| int compare_8_bits); |
| void tms9914_disable_eos(struct gpib_board *board, struct tms9914_priv *priv); |
| unsigned int tms9914_update_status(struct gpib_board *board, struct tms9914_priv *priv, |
| unsigned int clear_mask); |
| int tms9914_primary_address(struct gpib_board *board, |
| struct tms9914_priv *priv, unsigned int address); |
| int tms9914_secondary_address(struct gpib_board *board, struct tms9914_priv *priv, |
| unsigned int address, int enable); |
| int tms9914_parallel_poll(struct gpib_board *board, struct tms9914_priv *priv, u8 *result); |
| void tms9914_parallel_poll_configure(struct gpib_board *board, |
| struct tms9914_priv *priv, u8 config); |
| void tms9914_parallel_poll_response(struct gpib_board *board, |
| struct tms9914_priv *priv, int ist); |
| void tms9914_serial_poll_response(struct gpib_board *board, |
| struct tms9914_priv *priv, u8 status); |
| u8 tms9914_serial_poll_status(struct gpib_board *board, struct tms9914_priv *priv); |
| int tms9914_line_status(const struct gpib_board *board, struct tms9914_priv *priv); |
| unsigned int tms9914_t1_delay(struct gpib_board *board, struct tms9914_priv *priv, |
| unsigned int nano_sec); |
| void tms9914_return_to_local(const struct gpib_board *board, struct tms9914_priv *priv); |
| |
| // utility functions |
| void tms9914_board_reset(struct tms9914_priv *priv); |
| void tms9914_online(struct gpib_board *board, struct tms9914_priv *priv); |
| void tms9914_release_holdoff(struct tms9914_priv *priv); |
| void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mode mode); |
| |
| // wrappers for io functions |
| u8 tms9914_ioport_read_byte(struct tms9914_priv *priv, unsigned int register_num); |
| void tms9914_ioport_write_byte(struct tms9914_priv *priv, u8 data, unsigned int register_num); |
| u8 tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register_num); |
| void tms9914_iomem_write_byte(struct tms9914_priv *priv, u8 data, unsigned int register_num); |
| |
| // interrupt service routine |
| irqreturn_t tms9914_interrupt(struct gpib_board *board, struct tms9914_priv *priv); |
| irqreturn_t tms9914_interrupt_have_status(struct gpib_board *board, struct tms9914_priv *priv, |
| int status1, int status2); |
| |
| // tms9914 has 8 registers |
| enum { |
| ms9914_num_registers = 8, |
| }; |
| |
| /* |
| * tms9914 register numbers (might need to be multiplied by |
| * a board-dependent offset to get actually io address offset) |
| */ |
| // write registers |
| enum { |
| IMR0 = 0, /* interrupt mask 0 */ |
| IMR1 = 1, /* interrupt mask 1 */ |
| AUXCR = 3, /* auxiliary command */ |
| ADR = 4, /* address register */ |
| SPMR = 5, /* serial poll mode register */ |
| PPR = 6, /* parallel poll */ |
| CDOR = 7, /* data out register */ |
| }; |
| |
| // read registers |
| enum { |
| ISR0 = 0, /* interrupt status 0 */ |
| ISR1 = 1, /* interrupt status 1 */ |
| ADSR = 2, /* address status */ |
| BSR = 3, /* bus status */ |
| CPTR = 6, /* command pass thru */ |
| DIR = 7, /* data in register */ |
| }; |
| |
| // bit definitions common to tms9914 compatible registers |
| |
| /* ISR0 - Register bits */ |
| enum isr0_bits { |
| HR_MAC = (1 << 0), /* My Address Change */ |
| HR_RLC = (1 << 1), /* Remote/Local change */ |
| HR_SPAS = (1 << 2), /* Serial Poll active State */ |
| HR_END = (1 << 3), /* END (EOI or EOS) */ |
| HR_BO = (1 << 4), /* Byte Out */ |
| HR_BI = (1 << 5), /* Byte In */ |
| }; |
| |
| /* IMR0 - Register bits */ |
| enum imr0_bits { |
| HR_MACIE = (1 << 0), /* */ |
| HR_RLCIE = (1 << 1), /* */ |
| HR_SPASIE = (1 << 2), /* */ |
| HR_ENDIE = (1 << 3), /* */ |
| HR_BOIE = (1 << 4), /* */ |
| HR_BIIE = (1 << 5), /* */ |
| }; |
| |
| /* ISR1 - Register bits */ |
| enum isr1_bits { |
| HR_IFC = (1 << 0), /* IFC asserted */ |
| HR_SRQ = (1 << 1), /* SRQ asserted */ |
| HR_MA = (1 << 2), /* My Address */ |
| HR_DCAS = (1 << 3), /* Device Clear active State */ |
| HR_APT = (1 << 4), /* Address pass Through */ |
| HR_UNC = (1 << 5), /* Unrecognized Command */ |
| HR_ERR = (1 << 6), /* Data Transmission Error */ |
| HR_GET = (1 << 7), /* Group execute Trigger */ |
| }; |
| |
| /* IMR1 - Register bits */ |
| enum imr1_bits { |
| HR_IFCIE = (1 << 0), /* */ |
| HR_SRQIE = (1 << 1), /* */ |
| HR_MAIE = (1 << 2), /* */ |
| HR_DCASIE = (1 << 3), /* */ |
| HR_APTIE = (1 << 4), /* */ |
| HR_UNCIE = (1 << 5), /* */ |
| HR_ERRIE = (1 << 6), /* */ |
| HR_GETIE = (1 << 7), /* */ |
| }; |
| |
| /* ADSR - Register bits */ |
| enum adsr_bits { |
| HR_ULPA = (1 << 0), /* Store last address LSB */ |
| HR_TA = (1 << 1), /* Talker Adressed */ |
| HR_LA = (1 << 2), /* Listener adressed */ |
| HR_TPAS = (1 << 3), /* talker primary address state */ |
| HR_LPAS = (1 << 4), /* listener " */ |
| HR_ATN = (1 << 5), /* ATN active */ |
| HR_LLO = (1 << 6), /* LLO active */ |
| HR_REM = (1 << 7), /* REM active */ |
| }; |
| |
| /* ADR - Register bits */ |
| enum adr_bits { |
| ADDRESS_MASK = 0x1f, /* mask to specify lower 5 bits for ADR */ |
| HR_DAT = (1 << 5), /* disable talker */ |
| HR_DAL = (1 << 6), /* disable listener */ |
| HR_EDPA = (1 << 7), /* enable dual primary addressing */ |
| }; |
| |
| enum bus_status_bits { |
| BSR_REN_BIT = 0x1, |
| BSR_IFC_BIT = 0x2, |
| BSR_SRQ_BIT = 0x4, |
| BSR_EOI_BIT = 0x8, |
| BSR_NRFD_BIT = 0x10, |
| BSR_NDAC_BIT = 0x20, |
| BSR_DAV_BIT = 0x40, |
| BSR_ATN_BIT = 0x80, |
| }; |
| |
| /*---------------------------------------------------------*/ |
| /* TMS 9914 Auxiliary Commands */ |
| /*---------------------------------------------------------*/ |
| |
| enum aux_cmd_bits { |
| AUX_CS = 0x80, /* set bit instead of clearing it, used with commands marked 'd' below */ |
| AUX_CHIP_RESET = 0x0, /* d Chip reset */ |
| AUX_INVAL = 0x1, /* release dac holdoff, invalid command byte */ |
| AUX_VAL = (AUX_INVAL | AUX_CS), /* release dac holdoff, valid command byte */ |
| AUX_RHDF = 0x2, /* X Release RFD holdoff */ |
| AUX_HLDA = 0x3, /* d holdoff on all data */ |
| AUX_HLDE = 0x4, /* d holdoff on EOI only */ |
| AUX_NBAF = 0x5, /* X Set new byte available false */ |
| AUX_FGET = 0x6, /* d force GET */ |
| AUX_RTL = 0x7, /* d return to local */ |
| AUX_SEOI = 0x8, /* X send EOI with next byte */ |
| AUX_LON = 0x9, /* d Listen only */ |
| AUX_TON = 0xa, /* d Talk only */ |
| AUX_GTS = 0xb, /* X goto standby */ |
| AUX_TCA = 0xc, /* X take control asynchronously */ |
| AUX_TCS = 0xd, /* X take " synchronously */ |
| AUX_RPP = 0xe, /* d Request parallel poll */ |
| AUX_SIC = 0xf, /* d send interface clear */ |
| AUX_SRE = 0x10, /* d send remote enable */ |
| AUX_RQC = 0x11, /* X request control */ |
| AUX_RLC = 0x12, /* X release control */ |
| AUX_DAI = 0x13, /* d disable all interrupts */ |
| AUX_PTS = 0x14, /* X pass through next secondary */ |
| AUX_STDL = 0x15, /* d short T1 delay */ |
| AUX_SHDW = 0x16, /* d shadow handshake */ |
| AUX_VSTDL = 0x17, /* d very short T1 delay (smj9914 extension) */ |
| AUX_RSV2 = 0x18, /* d request service bit 2 (smj9914 extension) */ |
| }; |
| |
| #endif //_TMS9914_H |