/*********************************************************************
*
* vlsi_ir.h: VLSI82C147 PCI IrDA controller driver for Linux
*
* Version: 0.5
*
* Copyright (c) 2001-2003 Martin Diehl
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
#ifndef IRDA_VLSI_FIR_H
#define IRDA_VLSI_FIR_H
/* ================================================================
* compatibility stuff
*/
/* definitions not present in pci_ids.h */
#ifndef PCI_CLASS_WIRELESS_IRDA
#define PCI_CLASS_WIRELESS_IRDA 0x0d00
#endif
#ifndef PCI_CLASS_SUBCLASS_MASK
#define PCI_CLASS_SUBCLASS_MASK 0xffff
#endif
/* ================================================================ */
/* non-standard PCI registers */
enum vlsi_pci_regs {
VLSI_PCI_CLKCTL = 0x40, /* chip clock input control */
VLSI_PCI_MSTRPAGE = 0x41, /* addr [31:24] for all busmaster cycles */
VLSI_PCI_IRMISC = 0x42 /* mainly legacy UART related */
};
/* ------------------------------------------ */
/* VLSI_PCI_CLKCTL: Clock Control Register (u8, rw) */
/* Three possible clock sources: either on-chip 48MHz PLL or
* external clock applied to EXTCLK pin. External clock may
* be either 48MHz or 40MHz, which is indicated by XCKSEL.
* CLKSTP controls whether the selected clock source gets
* connected to the IrDA block.
*
* On my HP OB-800 the BIOS sets external 40MHz clock as source
* when IrDA enabled and I've never detected any PLL lock success.
* Apparently the 14.3...MHz OSC input required for the PLL to work
* is not connected and the 40MHz EXTCLK is provided externally.
* At least this is what makes the driver working for me.
*/
enum vlsi_pci_clkctl {
/* PLL control */
CLKCTL_PD_INV = 0x04, /* PD#: inverted power down signal,
* i.e. PLL is powered, if PD_INV set */
CLKCTL_LOCK = 0x40, /* (ro) set, if PLL is locked */
/* clock source selection */
CLKCTL_EXTCLK = 0x20, /* set to select external clock input, not PLL */
CLKCTL_XCKSEL = 0x10, /* set to indicate EXTCLK is 40MHz, not 48MHz */
/* IrDA block control */
CLKCTL_CLKSTP = 0x80, /* set to disconnect from selected clock source */
CLKCTL_WAKE = 0x08 /* set to enable wakeup feature: whenever IR activity
* is detected, PD_INV gets set(?) and CLKSTP cleared */
};
/* ------------------------------------------ */
/* VLSI_PCI_MSTRPAGE: Master Page Register (u8, rw) and busmastering stuff */
#define DMA_MASK_USED_BY_HW 0xffffffff
#define DMA_MASK_MSTRPAGE 0x00ffffff
#define MSTRPAGE_VALUE (DMA_MASK_MSTRPAGE >> 24)
/* PCI busmastering is somewhat special for this guy - in short:
*
* We select to operate using fixed MSTRPAGE=0, use ISA DMA
* address restrictions to make the PCI BM api aware of this,
* but ensure the hardware is dealing with real 32bit access.
*
* In detail:
* The chip executes normal 32bit busmaster cycles, i.e.
* drives all 32 address lines. These addresses however are
* composed of [0:23] taken from various busaddr-pointers
* and [24:31] taken from the MSTRPAGE register in the VLSI82C147
* config space. Therefore _all_ busmastering must be
* targeted to/from one single 16MB (busaddr-) superpage!
* The point is to make sure all the allocations for memory
* locations with busmaster access (ring descriptors, buffers)
* are indeed bus-mappable to the same 16MB range (for x86 this
* means they must reside in the same 16MB physical memory address
* range). The only constraint we have which supports "several objects
* mappable to common 16MB range" paradigma, is the old ISA DMA
* restriction to the first 16MB of physical address range.
* Hence the approach here is to enable PCI busmaster support using
* the correct 32bit dma-mask used by the chip. Afterwards the device's
* dma-mask gets restricted to 24bit, which must be honoured somehow by
* all allocations for memory areas to be exposed to the chip ...
*
* Note:
* Don't be surprised to get "Setting latency timer..." messages every
* time when PCI busmastering is enabled for the chip.
* The chip has its PCI latency timer RO fixed at 0 - which is not a
* problem here, because it is never requesting _burst_ transactions.
*/
/* ------------------------------------------ */
/* VLSI_PCIIRMISC: IR Miscellaneous Register (u8, rw) */
/* legacy UART emulation - not used by this driver - would require:
* (see below for some register-value definitions)
*
* - IRMISC_UARTEN must be set to enable UART address decoding
* - IRMISC_UARTSEL configured
* - IRCFG_MASTER must be cleared
* - IRCFG_SIR must be set
* - IRENABLE_PHYANDCLOCK must be asserted 0->1 (and hence IRENABLE_SIR_ON)
*/
enum vlsi_pci_irmisc {
/* IR transceiver control */
IRMISC_IRRAIL = 0x40, /* (ro?) IR rail power indication (and control?)
* 0=3.3V / 1=5V. Probably set during power-on?
* unclear - not touched by driver */
IRMISC_IRPD = 0x08, /* transceiver power down, if set */
/* legacy UART control */
IRMISC_UARTTST = 0x80, /* UART test mode - "always write 0" */
IRMISC_UARTEN = 0x04, /* enable UART address decoding */
/* bits [1:0] IRMISC_UARTSEL to select legacy UART address */
IRMISC_UARTSEL_3f8 = 0x00,
IRMISC_UARTSEL_2f8 = 0x01,
IRMISC_UARTSEL_3e8 = 0x02,
IRMISC_UARTSEL_2e8 = 0x03
};
/* ================================================================ */
/* registers mapped to 32 byte PCI IO space */
/* note: better access all registers at the indicated u8/u16 size
* although some of them contain only 1 byte of information.
* some of them (particaluarly PROMPT and IRCFG) ignore
* access when using the wrong addressing mode!
*/
enum vlsi_pio_regs {
VLSI_PIO_IRINTR = 0x00, /* interrupt enable/request (u8, rw) */
VLSI_PIO_RINGPTR = 0x02, /* rx/tx ring pointer (u16, ro) */
VLSI_PIO_RINGBASE = 0x04, /* [23:10] of ring address (u16, rw) */
VLSI_PIO_RINGSIZE = 0x06, /* rx/tx ring size (u16, rw) */
VLSI_PIO_PROMPT = 0x08, /* triggers ring processing (u16, wo) */
/* 0x0a-0x0f: reserved / duplicated UART regs */
VLSI_PIO_IRCFG = 0x10, /* configuration select (u16, rw) */
VLSI_PIO_SIRFLAG = 0x12, /* BOF/EOF for filtered SIR (u16, ro) */
VLSI_PIO_IRENABLE = 0x14, /* enable and status register (u16, rw/ro) */
VLSI_PIO_PHYCTL = 0x16, /* physical layer current status (u16, ro) */
VLSI_PIO_NPHYCTL = 0x18, /* next physical layer select (u16, rw) */
VLSI_PIO_MAXPKT = 0x1a, /* [11:0] max len for packet receive (u16, rw) */
VLSI_PIO_RCVBCNT = 0x1c /* current receive-FIFO byte count (u16, ro) */
/* 0x1e-0x1f: reserved / duplicated UART regs */
};
/* ------------------------------------------ */
/* VLSI_PIO_IRINTR: Interrupt Register (u8, rw) */
/* enable-bits:
* 1 = enable / 0 = disable
* interrupt condition bits:
* set according to corresponding interrupt source
* (regardless of the state of the enable bits)
* enable bit status indicates whether interrupt gets raised
* write-to-clear
* note: RPKTINT and TPKTINT behave different in legacy UART mode (which we don't use :-)
*/
enum vlsi_pio_irintr {
IRINTR_ACTEN = 0x80, /* activity interrupt enable */
IRINTR_ACTIVITY = 0x40, /* activity monitor (traffic detected) */
IRINTR_RPKTEN = 0x20, /* receive packet interrupt enable*/
IRINTR_RPKTINT = 0x10, /* rx-packet transfered from fifo to memory finished */
IRINTR_TPKTEN = 0x08, /* transmit packet interrupt enable */
IRINTR_TPKTINT = 0x04, /* last bit of tx-packet+crc shifted to ir-pulser */
IRINTR_OE_EN = 0x02, /* UART rx fifo overrun error interrupt enable */
IRINTR_OE_INT = 0x01 /* UART rx fifo overrun error (read LSR to clear) */
};
/* we use this mask to check whether the (shared PCI) interrupt is ours */
#define IRINTR_INT_MASK (IRINTR_ACTIVITY|IRINTR_RPKTINT|IRINTR_TPKTINT)
/* ------------------------------------------ */
/* VLSI_PIO_RINGPTR: Ring Pointer Read-Back Register (u16, ro) */
/* _both_ ring pointers are indices relative to the _entire_ rx,tx-ring!
* i.e. the referenced descriptor is located
* at RINGBASE + PTR * sizeof(descr) for rx and tx
* therefore, the tx-pointer has offset MAX_RING_DESCR
*/
#define MAX_RING_DESCR 64 /* tx, rx rings may contain up to 64 descr each */
#define RINGPTR_RX_MASK (MAX_RING_DESCR-1)
#define RINGPTR_TX_MASK ((MAX_RING_DESCR-1)<<8)
#define RINGPTR_GET_RX(p) ((p)&RINGPTR_RX_MASK)