/* SPDX-License-Identifier: GPL-2.0 */
/*
 * For License see notice in hfc_multi.c
 *
 * special IO and init functions for the embedded XHFC board
 * from Speech Design
 *
 */

#include <asm/cpm1.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;
}
