162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * For License see notice in hfc_multi.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * special IO and init functions for the embedded XHFC board 662306a36Sopenharmony_ci * from Speech Design 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <asm/cpm1.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* Change this to the value used by your board */ 1362306a36Sopenharmony_ci#ifndef IMAP_ADDR 1462306a36Sopenharmony_ci#define IMAP_ADDR 0xFFF00000 1562306a36Sopenharmony_ci#endif 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic void 1862306a36Sopenharmony_ci#ifdef HFC_REGISTER_DEBUG 1962306a36Sopenharmony_ciHFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val, 2062306a36Sopenharmony_ci const char *function, int line) 2162306a36Sopenharmony_ci#else 2262306a36Sopenharmony_ci HFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val) 2362306a36Sopenharmony_ci#endif 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 2662306a36Sopenharmony_ci writeb(reg, hc->xhfc_memaddr); 2762306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 2862306a36Sopenharmony_ci writeb(val, hc->xhfc_memdata); 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_cistatic u_char 3162306a36Sopenharmony_ci#ifdef HFC_REGISTER_DEBUG 3262306a36Sopenharmony_ciHFC_inb_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line) 3362306a36Sopenharmony_ci#else 3462306a36Sopenharmony_ci HFC_inb_embsd(struct hfc_multi *hc, u_char reg) 3562306a36Sopenharmony_ci#endif 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 3862306a36Sopenharmony_ci writeb(reg, hc->xhfc_memaddr); 3962306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 4062306a36Sopenharmony_ci return readb(hc->xhfc_memdata); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_cistatic u_short 4362306a36Sopenharmony_ci#ifdef HFC_REGISTER_DEBUG 4462306a36Sopenharmony_ciHFC_inw_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line) 4562306a36Sopenharmony_ci#else 4662306a36Sopenharmony_ci HFC_inw_embsd(struct hfc_multi *hc, u_char reg) 4762306a36Sopenharmony_ci#endif 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 5062306a36Sopenharmony_ci writeb(reg, hc->xhfc_memaddr); 5162306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 5262306a36Sopenharmony_ci return readb(hc->xhfc_memdata); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_cistatic void 5562306a36Sopenharmony_ci#ifdef HFC_REGISTER_DEBUG 5662306a36Sopenharmony_ciHFC_wait_embsd(struct hfc_multi *hc, const char *function, int line) 5762306a36Sopenharmony_ci#else 5862306a36Sopenharmony_ci HFC_wait_embsd(struct hfc_multi *hc) 5962306a36Sopenharmony_ci#endif 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 6262306a36Sopenharmony_ci writeb(R_STATUS, hc->xhfc_memaddr); 6362306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 6462306a36Sopenharmony_ci while (readb(hc->xhfc_memdata) & V_BUSY) 6562306a36Sopenharmony_ci cpu_relax(); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* write fifo data (EMBSD) */ 6962306a36Sopenharmony_civoid 7062306a36Sopenharmony_ciwrite_fifo_embsd(struct hfc_multi *hc, u_char *data, int len) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 7362306a36Sopenharmony_ci *hc->xhfc_memaddr = A_FIFO_DATA0; 7462306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 7562306a36Sopenharmony_ci while (len) { 7662306a36Sopenharmony_ci *hc->xhfc_memdata = *data; 7762306a36Sopenharmony_ci data++; 7862306a36Sopenharmony_ci len--; 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci/* read fifo data (EMBSD) */ 8362306a36Sopenharmony_civoid 8462306a36Sopenharmony_ciread_fifo_embsd(struct hfc_multi *hc, u_char *data, int len) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 8762306a36Sopenharmony_ci *hc->xhfc_memaddr = A_FIFO_DATA0; 8862306a36Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 8962306a36Sopenharmony_ci while (len) { 9062306a36Sopenharmony_ci *data = (u_char)(*hc->xhfc_memdata); 9162306a36Sopenharmony_ci data++; 9262306a36Sopenharmony_ci len--; 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic int 9762306a36Sopenharmony_cisetup_embedded(struct hfc_multi *hc, struct hm_map *m) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci printk(KERN_INFO 10062306a36Sopenharmony_ci "HFC-multi: card manufacturer: '%s' card name: '%s' clock: %s\n", 10162306a36Sopenharmony_ci m->vendor_name, m->card_name, m->clock2 ? "double" : "normal"); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci hc->pci_dev = NULL; 10462306a36Sopenharmony_ci if (m->clock2) 10562306a36Sopenharmony_ci test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci hc->leds = m->leds; 10862306a36Sopenharmony_ci hc->ledstate = 0xAFFEAFFE; 10962306a36Sopenharmony_ci hc->opticalsupport = m->opticalsupport; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci hc->pci_iobase = 0; 11262306a36Sopenharmony_ci hc->pci_membase = 0; 11362306a36Sopenharmony_ci hc->xhfc_membase = NULL; 11462306a36Sopenharmony_ci hc->xhfc_memaddr = NULL; 11562306a36Sopenharmony_ci hc->xhfc_memdata = NULL; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* set memory access methods */ 11862306a36Sopenharmony_ci if (m->io_mode) /* use mode from card config */ 11962306a36Sopenharmony_ci hc->io_mode = m->io_mode; 12062306a36Sopenharmony_ci switch (hc->io_mode) { 12162306a36Sopenharmony_ci case HFC_IO_MODE_EMBSD: 12262306a36Sopenharmony_ci test_and_set_bit(HFC_CHIP_EMBSD, &hc->chip); 12362306a36Sopenharmony_ci hc->slots = 128; /* required */ 12462306a36Sopenharmony_ci hc->HFC_outb = HFC_outb_embsd; 12562306a36Sopenharmony_ci hc->HFC_inb = HFC_inb_embsd; 12662306a36Sopenharmony_ci hc->HFC_inw = HFC_inw_embsd; 12762306a36Sopenharmony_ci hc->HFC_wait = HFC_wait_embsd; 12862306a36Sopenharmony_ci hc->read_fifo = read_fifo_embsd; 12962306a36Sopenharmony_ci hc->write_fifo = write_fifo_embsd; 13062306a36Sopenharmony_ci hc->xhfc_origmembase = XHFC_MEMBASE + XHFC_OFFSET * hc->id; 13162306a36Sopenharmony_ci hc->xhfc_membase = (u_char *)ioremap(hc->xhfc_origmembase, 13262306a36Sopenharmony_ci XHFC_MEMSIZE); 13362306a36Sopenharmony_ci if (!hc->xhfc_membase) { 13462306a36Sopenharmony_ci printk(KERN_WARNING 13562306a36Sopenharmony_ci "HFC-multi: failed to remap xhfc address space. " 13662306a36Sopenharmony_ci "(internal error)\n"); 13762306a36Sopenharmony_ci return -EIO; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci hc->xhfc_memaddr = (u_long *)(hc->xhfc_membase + 4); 14062306a36Sopenharmony_ci hc->xhfc_memdata = (u_long *)(hc->xhfc_membase); 14162306a36Sopenharmony_ci printk(KERN_INFO 14262306a36Sopenharmony_ci "HFC-multi: xhfc_membase:%#lx xhfc_origmembase:%#lx " 14362306a36Sopenharmony_ci "xhfc_memaddr:%#lx xhfc_memdata:%#lx\n", 14462306a36Sopenharmony_ci (u_long)hc->xhfc_membase, hc->xhfc_origmembase, 14562306a36Sopenharmony_ci (u_long)hc->xhfc_memaddr, (u_long)hc->xhfc_memdata); 14662306a36Sopenharmony_ci break; 14762306a36Sopenharmony_ci default: 14862306a36Sopenharmony_ci printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n"); 14962306a36Sopenharmony_ci return -EIO; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci /* Prepare the MPC8XX PortA 10 as output (address/data selector) */ 15362306a36Sopenharmony_ci hc->immap = (struct immap *)(IMAP_ADDR); 15462306a36Sopenharmony_ci hc->immap->im_ioport.iop_papar &= ~(PA_XHFC_A0); 15562306a36Sopenharmony_ci hc->immap->im_ioport.iop_paodr &= ~(PA_XHFC_A0); 15662306a36Sopenharmony_ci hc->immap->im_ioport.iop_padir |= PA_XHFC_A0; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* Prepare the MPC8xx PortB __X__ as input (ISDN__X__IRQ) */ 15962306a36Sopenharmony_ci hc->pb_irqmsk = (PB_XHFC_IRQ1 << hc->id); 16062306a36Sopenharmony_ci hc->immap->im_cpm.cp_pbpar &= ~(hc->pb_irqmsk); 16162306a36Sopenharmony_ci hc->immap->im_cpm.cp_pbodr &= ~(hc->pb_irqmsk); 16262306a36Sopenharmony_ci hc->immap->im_cpm.cp_pbdir &= ~(hc->pb_irqmsk); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci /* At this point the needed config is done */ 16562306a36Sopenharmony_ci /* fifos are still not enabled */ 16662306a36Sopenharmony_ci return 0; 16762306a36Sopenharmony_ci} 168