Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db9bb63a authored by Karsten Keil's avatar Karsten Keil Committed by David S. Miller
Browse files

mISDN: Add XHFC support for embedded Speech-Design board to hfcmulti



New version without emulating arch specific stuff for the other
architectures, the special IO and init functions for the 8xx
microcontroller are in a separate include file.

Signed-off-by: default avatarAndreas Eversberg <andreas@eversberg.eu>
Signed-off-by: default avatarKarsten Keil <keil@b1-systems.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5df3b8bc
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@ config MISDN_HFCPCI

config MISDN_HFCMULTI
	tristate "Support for HFC multiport cards (HFC-4S/8S/E1)"
	depends on PCI
	depends on PCI || 8xx
	depends on MISDN
	help
	  Enable support for cards with Cologne Chip AG's HFC multiport
@@ -23,6 +23,15 @@ config MISDN_HFCMULTI
	   * HFC-8S (8 S/T interfaces on one chip)
	   * HFC-E1 (E1 interface for 2Mbit ISDN)

config MISDN_HFCMULTI_8xx
	boolean "Support for XHFC embedded board in HFC multiport driver"
	depends on MISDN
	depends on MISDN_HFCMULTI
	depends on 8xx
	default 8xx
	help
	  Enable support for the XHFC embedded solution from Speech Design.

config MISDN_HFCUSB
	tristate "Support for HFC-S USB based TAs"
	depends on USB
+35 −10
Original line number Diff line number Diff line
@@ -17,6 +17,16 @@
#define	PCI_ENA_REGIO	0x01
#define	PCI_ENA_MEMIO	0x02

#define XHFC_IRQ	4		/* SIU_IRQ2 */
#define XHFC_MEMBASE	0xFE000000
#define XHFC_MEMSIZE    0x00001000
#define XHFC_OFFSET	0x00001000
#define PA_XHFC_A0	0x0020		/* PA10 */
#define PB_XHFC_IRQ1	0x00000100	/* PB23 */
#define PB_XHFC_IRQ2	0x00000200	/* PB22 */
#define PB_XHFC_IRQ3	0x00000400	/* PB21 */
#define PB_XHFC_IRQ4	0x00000800	/* PB20 */

/*
 * NOTE: some registers are assigned multiple times due to different modes
 *       also registers are assigned differen for HFC-4s/8s and HFC-E1
@@ -81,6 +91,11 @@ struct hfcm_hw {
#define	HFC_CFG_CRC4		10 /* disable CRC-4 Multiframe mode, */
					/* use double frame instead. */

#define HFC_TYPE_E1		1 /* controller is HFC-E1 */
#define HFC_TYPE_4S		4 /* controller is HFC-4S */
#define HFC_TYPE_8S		8 /* controller is HFC-8S */
#define HFC_TYPE_XHFC		5 /* controller is XHFC */

#define	HFC_CHIP_EXRAM_128	0 /* external ram 128k */
#define	HFC_CHIP_EXRAM_512	1 /* external ram 256k */
#define	HFC_CHIP_REVISION0	2 /* old fifo handling */
@@ -88,19 +103,22 @@ struct hfcm_hw {
#define	HFC_CHIP_PCM_MASTER	4 /* PCM is master */
#define	HFC_CHIP_RX_SYNC	5 /* disable pll sync for pcm */
#define	HFC_CHIP_DTMF		6 /* DTMF decoding is enabled */
#define	HFC_CHIP_ULAW		7 /* ULAW mode */
#define	HFC_CHIP_CLOCK2		8 /* double clock mode */
#define	HFC_CHIP_E1CLOCK_GET	9 /* always get clock from E1 interface */
#define	HFC_CHIP_E1CLOCK_PUT	10 /* always put clock from E1 interface */
#define	HFC_CHIP_WATCHDOG	11 /* whether we should send signals */
#define	HFC_CHIP_CONF		7 /* conference handling is enabled */
#define	HFC_CHIP_ULAW		8 /* ULAW mode */
#define	HFC_CHIP_CLOCK2		9 /* double clock mode */
#define	HFC_CHIP_E1CLOCK_GET	10 /* always get clock from E1 interface */
#define	HFC_CHIP_E1CLOCK_PUT	11 /* always put clock from E1 interface */
#define	HFC_CHIP_WATCHDOG	12 /* whether we should send signals */
					/* to the watchdog */
#define	HFC_CHIP_B410P		12 /* whether we have a b410p with echocan in */
#define	HFC_CHIP_B410P		13 /* whether we have a b410p with echocan in */
					/* hw */
#define	HFC_CHIP_PLXSD		13 /* whether we have a Speech-Design PLX */
#define	HFC_CHIP_PLXSD		14 /* whether we have a Speech-Design PLX */
#define	HFC_CHIP_EMBSD          15 /* whether we have a SD Embedded board */

#define HFC_IO_MODE_PCIMEM	0x00 /* normal memory mapped IO */
#define HFC_IO_MODE_REGIO	0x01 /* PCI io access */
#define HFC_IO_MODE_PLXSD	0x02 /* access HFC via PLX9030 */
#define HFC_IO_MODE_EMBSD	0x03 /* direct access */

/* table entry in the PCI devices list */
struct hm_map {
@@ -113,6 +131,7 @@ struct hm_map {
	int opticalsupport;
	int dip_type;
	int io_mode;
	int irq;
};

struct hfc_multi {
@@ -120,7 +139,7 @@ struct hfc_multi {
	struct hm_map	*mtyp;
	int		id;
	int		pcm;	/* id of pcm bus */
	int		type;
	int		ctype;	/* controller type */
	int		ports;

	u_int		irq;	/* irq used by card */
@@ -160,10 +179,16 @@ struct hfc_multi {
				int len);
	void		(*write_fifo)(struct hfc_multi *hc, u_char *data,
				int len);
	u_long		pci_origmembase, plx_origmembase, dsp_origmembase;
	u_long		pci_origmembase, plx_origmembase;
	void __iomem	*pci_membase; /* PCI memory */
	void __iomem	*plx_membase; /* PLX memory */
	u_char		*dsp_membase; /* DSP on PLX */
	u_long		xhfc_origmembase;
	u_char		*xhfc_membase;
	u_long		*xhfc_memaddr, *xhfc_memdata;
#ifdef CONFIG_MISDN_HFCMULTI_8xx
	struct immap	*immap;
#endif
	u_long		pb_irqmsk;	/* Portbit mask to check the IRQ line */
	u_long		pci_iobase; /* PCI IO */
	struct hfcm_hw	hw;	/* remember data of write-only-registers */

+167 −0
Original line number Diff line number Diff line
/*
 * For License see notice in hfc_multi.c
 *
 * special IO and init functions for the embedded XHFC board
 * from Speech Design
 *
 */

#include <asm/8xx_immap.h>

/* Change this to the value used by your board */
#ifndef IMAP_ADDR
#define IMAP_ADDR	0xFFF00000
#endif

static void
#ifdef HFC_REGISTER_DEBUG
HFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val,
		const char *function, int line)
#else
HFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val)
#endif
{
	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
	writeb(reg, hc->xhfc_memaddr);
	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
	writeb(val, hc->xhfc_memdata);
}
static u_char
#ifdef HFC_REGISTER_DEBUG
HFC_inb_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line)
#else
HFC_inb_embsd(struct hfc_multi *hc, u_char reg)
#endif
{
	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
	writeb(reg, hc->xhfc_memaddr);
	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
	return readb(hc->xhfc_memdata);
}
static u_short
#ifdef HFC_REGISTER_DEBUG
HFC_inw_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line)
#else
HFC_inw_embsd(struct hfc_multi *hc, u_char reg)
#endif
{
	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
	writeb(reg, hc->xhfc_memaddr);
	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
	return readb(hc->xhfc_memdata);
}
static void
#ifdef HFC_REGISTER_DEBUG
HFC_wait_embsd(struct hfc_multi *hc, const char *function, int line)
#else
HFC_wait_embsd(struct hfc_multi *hc)
#endif
{
	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
	writeb(R_STATUS, hc->xhfc_memaddr);
	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
	while (readb(hc->xhfc_memdata) & V_BUSY)
		cpu_relax();
}

/* write fifo data (EMBSD) */
void
write_fifo_embsd(struct hfc_multi *hc, u_char *data, int len)
{
	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
	*hc->xhfc_memaddr = A_FIFO_DATA0;
	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
	while (len) {
		*hc->xhfc_memdata = *data;
		data++;
		len--;
	}
}

/* read fifo data (EMBSD) */
void
read_fifo_embsd(struct hfc_multi *hc, u_char *data, int len)
{
	hc->immap->im_ioport.iop_padat |= PA_XHFC_A0;
	*hc->xhfc_memaddr = A_FIFO_DATA0;
	hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0);
	while (len) {
		*data = (u_char)(*hc->xhfc_memdata);
		data++;
		len--;
	}
}

static int
setup_embedded(struct hfc_multi *hc, struct hm_map *m)
{
	printk(KERN_INFO
	    "HFC-multi: card manufacturer: '%s' card name: '%s' clock: %s\n",
	    m->vendor_name, m->card_name, m->clock2 ? "double" : "normal");

	hc->pci_dev = NULL;
	if (m->clock2)
		test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip);

	hc->leds = m->leds;
	hc->ledstate = 0xAFFEAFFE;
	hc->opticalsupport = m->opticalsupport;

	hc->pci_iobase = 0;
	hc->pci_membase = 0;
	hc->xhfc_membase = NULL;
	hc->xhfc_memaddr = NULL;
	hc->xhfc_memdata = NULL;

	/* set memory access methods */
	if (m->io_mode) /* use mode from card config */
		hc->io_mode = m->io_mode;
	switch (hc->io_mode) {
	case HFC_IO_MODE_EMBSD:
		test_and_set_bit(HFC_CHIP_EMBSD, &hc->chip);
		hc->slots = 128; /* required */
		/* fall through */
		hc->HFC_outb = HFC_outb_embsd;
		hc->HFC_inb = HFC_inb_embsd;
		hc->HFC_inw = HFC_inw_embsd;
		hc->HFC_wait = HFC_wait_embsd;
		hc->read_fifo = read_fifo_embsd;
		hc->write_fifo = write_fifo_embsd;
		hc->xhfc_origmembase = XHFC_MEMBASE + XHFC_OFFSET * hc->id;
		hc->xhfc_membase = (u_char *)ioremap(hc->xhfc_origmembase,
				XHFC_MEMSIZE);
		if (!hc->xhfc_membase) {
			printk(KERN_WARNING
			    "HFC-multi: failed to remap xhfc address space. "
			    "(internal error)\n");
			return -EIO;
		}
		hc->xhfc_memaddr = (u_long *)(hc->xhfc_membase + 4);
		hc->xhfc_memdata = (u_long *)(hc->xhfc_membase);
		printk(KERN_INFO
		    "HFC-multi: xhfc_membase:%#lx xhfc_origmembase:%#lx "
		    "xhfc_memaddr:%#lx xhfc_memdata:%#lx\n",
		    (u_long)hc->xhfc_membase, hc->xhfc_origmembase,
		    (u_long)hc->xhfc_memaddr, (u_long)hc->xhfc_memdata);
		break;
	default:
		printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n");
		return -EIO;
	}

	/* Prepare the MPC8XX PortA 10 as output (address/data selector) */
	hc->immap = (struct immap *)(IMAP_ADDR);
	hc->immap->im_ioport.iop_papar &= ~(PA_XHFC_A0);
	hc->immap->im_ioport.iop_paodr &= ~(PA_XHFC_A0);
	hc->immap->im_ioport.iop_padir |=   PA_XHFC_A0;

	/* Prepare the MPC8xx PortB __X__ as input (ISDN__X__IRQ) */
	hc->pb_irqmsk = (PB_XHFC_IRQ1 << hc->id);
	hc->immap->im_cpm.cp_pbpar &= ~(hc->pb_irqmsk);
	hc->immap->im_cpm.cp_pbodr &= ~(hc->pb_irqmsk);
	hc->immap->im_cpm.cp_pbdir &= ~(hc->pb_irqmsk);

	/* At this point the needed config is done */
	/* fifos are still not enabled */
	return 0;
}
+283 −133

File changed.

Preview size limit exceeded, changes collapsed.

+4 −0
Original line number Diff line number Diff line
@@ -947,6 +947,10 @@ conf_software:
	if (current_conf >= 0) {
join_members:
		list_for_each_entry(member, &conf->mlist, list) {
			/* if no conference engine on our chip, change to
			 * software */
			if (!member->dsp->features.hfc_conf)
				goto conf_software;
			/* in case of hdlc, change to software */
			if (member->dsp->hdlc)
				goto conf_software;
Loading