18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * For License see notice in hfc_multi.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * special IO and init functions for the embedded XHFC board 68c2ecf20Sopenharmony_ci * from Speech Design 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <asm/cpm1.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci/* Change this to the value used by your board */ 138c2ecf20Sopenharmony_ci#ifndef IMAP_ADDR 148c2ecf20Sopenharmony_ci#define IMAP_ADDR 0xFFF00000 158c2ecf20Sopenharmony_ci#endif 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic void 188c2ecf20Sopenharmony_ci#ifdef HFC_REGISTER_DEBUG 198c2ecf20Sopenharmony_ciHFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val, 208c2ecf20Sopenharmony_ci const char *function, int line) 218c2ecf20Sopenharmony_ci#else 228c2ecf20Sopenharmony_ci HFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val) 238c2ecf20Sopenharmony_ci#endif 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 268c2ecf20Sopenharmony_ci writeb(reg, hc->xhfc_memaddr); 278c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 288c2ecf20Sopenharmony_ci writeb(val, hc->xhfc_memdata); 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_cistatic u_char 318c2ecf20Sopenharmony_ci#ifdef HFC_REGISTER_DEBUG 328c2ecf20Sopenharmony_ciHFC_inb_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line) 338c2ecf20Sopenharmony_ci#else 348c2ecf20Sopenharmony_ci HFC_inb_embsd(struct hfc_multi *hc, u_char reg) 358c2ecf20Sopenharmony_ci#endif 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 388c2ecf20Sopenharmony_ci writeb(reg, hc->xhfc_memaddr); 398c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 408c2ecf20Sopenharmony_ci return readb(hc->xhfc_memdata); 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_cistatic u_short 438c2ecf20Sopenharmony_ci#ifdef HFC_REGISTER_DEBUG 448c2ecf20Sopenharmony_ciHFC_inw_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line) 458c2ecf20Sopenharmony_ci#else 468c2ecf20Sopenharmony_ci HFC_inw_embsd(struct hfc_multi *hc, u_char reg) 478c2ecf20Sopenharmony_ci#endif 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 508c2ecf20Sopenharmony_ci writeb(reg, hc->xhfc_memaddr); 518c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 528c2ecf20Sopenharmony_ci return readb(hc->xhfc_memdata); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_cistatic void 558c2ecf20Sopenharmony_ci#ifdef HFC_REGISTER_DEBUG 568c2ecf20Sopenharmony_ciHFC_wait_embsd(struct hfc_multi *hc, const char *function, int line) 578c2ecf20Sopenharmony_ci#else 588c2ecf20Sopenharmony_ci HFC_wait_embsd(struct hfc_multi *hc) 598c2ecf20Sopenharmony_ci#endif 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 628c2ecf20Sopenharmony_ci writeb(R_STATUS, hc->xhfc_memaddr); 638c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 648c2ecf20Sopenharmony_ci while (readb(hc->xhfc_memdata) & V_BUSY) 658c2ecf20Sopenharmony_ci cpu_relax(); 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* write fifo data (EMBSD) */ 698c2ecf20Sopenharmony_civoid 708c2ecf20Sopenharmony_ciwrite_fifo_embsd(struct hfc_multi *hc, u_char *data, int len) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 738c2ecf20Sopenharmony_ci *hc->xhfc_memaddr = A_FIFO_DATA0; 748c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 758c2ecf20Sopenharmony_ci while (len) { 768c2ecf20Sopenharmony_ci *hc->xhfc_memdata = *data; 778c2ecf20Sopenharmony_ci data++; 788c2ecf20Sopenharmony_ci len--; 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* read fifo data (EMBSD) */ 838c2ecf20Sopenharmony_civoid 848c2ecf20Sopenharmony_ciread_fifo_embsd(struct hfc_multi *hc, u_char *data, int len) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; 878c2ecf20Sopenharmony_ci *hc->xhfc_memaddr = A_FIFO_DATA0; 888c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); 898c2ecf20Sopenharmony_ci while (len) { 908c2ecf20Sopenharmony_ci *data = (u_char)(*hc->xhfc_memdata); 918c2ecf20Sopenharmony_ci data++; 928c2ecf20Sopenharmony_ci len--; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic int 978c2ecf20Sopenharmony_cisetup_embedded(struct hfc_multi *hc, struct hm_map *m) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci printk(KERN_INFO 1008c2ecf20Sopenharmony_ci "HFC-multi: card manufacturer: '%s' card name: '%s' clock: %s\n", 1018c2ecf20Sopenharmony_ci m->vendor_name, m->card_name, m->clock2 ? "double" : "normal"); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci hc->pci_dev = NULL; 1048c2ecf20Sopenharmony_ci if (m->clock2) 1058c2ecf20Sopenharmony_ci test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci hc->leds = m->leds; 1088c2ecf20Sopenharmony_ci hc->ledstate = 0xAFFEAFFE; 1098c2ecf20Sopenharmony_ci hc->opticalsupport = m->opticalsupport; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci hc->pci_iobase = 0; 1128c2ecf20Sopenharmony_ci hc->pci_membase = 0; 1138c2ecf20Sopenharmony_ci hc->xhfc_membase = NULL; 1148c2ecf20Sopenharmony_ci hc->xhfc_memaddr = NULL; 1158c2ecf20Sopenharmony_ci hc->xhfc_memdata = NULL; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* set memory access methods */ 1188c2ecf20Sopenharmony_ci if (m->io_mode) /* use mode from card config */ 1198c2ecf20Sopenharmony_ci hc->io_mode = m->io_mode; 1208c2ecf20Sopenharmony_ci switch (hc->io_mode) { 1218c2ecf20Sopenharmony_ci case HFC_IO_MODE_EMBSD: 1228c2ecf20Sopenharmony_ci test_and_set_bit(HFC_CHIP_EMBSD, &hc->chip); 1238c2ecf20Sopenharmony_ci hc->slots = 128; /* required */ 1248c2ecf20Sopenharmony_ci hc->HFC_outb = HFC_outb_embsd; 1258c2ecf20Sopenharmony_ci hc->HFC_inb = HFC_inb_embsd; 1268c2ecf20Sopenharmony_ci hc->HFC_inw = HFC_inw_embsd; 1278c2ecf20Sopenharmony_ci hc->HFC_wait = HFC_wait_embsd; 1288c2ecf20Sopenharmony_ci hc->read_fifo = read_fifo_embsd; 1298c2ecf20Sopenharmony_ci hc->write_fifo = write_fifo_embsd; 1308c2ecf20Sopenharmony_ci hc->xhfc_origmembase = XHFC_MEMBASE + XHFC_OFFSET * hc->id; 1318c2ecf20Sopenharmony_ci hc->xhfc_membase = (u_char *)ioremap(hc->xhfc_origmembase, 1328c2ecf20Sopenharmony_ci XHFC_MEMSIZE); 1338c2ecf20Sopenharmony_ci if (!hc->xhfc_membase) { 1348c2ecf20Sopenharmony_ci printk(KERN_WARNING 1358c2ecf20Sopenharmony_ci "HFC-multi: failed to remap xhfc address space. " 1368c2ecf20Sopenharmony_ci "(internal error)\n"); 1378c2ecf20Sopenharmony_ci return -EIO; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci hc->xhfc_memaddr = (u_long *)(hc->xhfc_membase + 4); 1408c2ecf20Sopenharmony_ci hc->xhfc_memdata = (u_long *)(hc->xhfc_membase); 1418c2ecf20Sopenharmony_ci printk(KERN_INFO 1428c2ecf20Sopenharmony_ci "HFC-multi: xhfc_membase:%#lx xhfc_origmembase:%#lx " 1438c2ecf20Sopenharmony_ci "xhfc_memaddr:%#lx xhfc_memdata:%#lx\n", 1448c2ecf20Sopenharmony_ci (u_long)hc->xhfc_membase, hc->xhfc_origmembase, 1458c2ecf20Sopenharmony_ci (u_long)hc->xhfc_memaddr, (u_long)hc->xhfc_memdata); 1468c2ecf20Sopenharmony_ci break; 1478c2ecf20Sopenharmony_ci default: 1488c2ecf20Sopenharmony_ci printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n"); 1498c2ecf20Sopenharmony_ci return -EIO; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci /* Prepare the MPC8XX PortA 10 as output (address/data selector) */ 1538c2ecf20Sopenharmony_ci hc->immap = (struct immap *)(IMAP_ADDR); 1548c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_papar &= ~(PA_XHFC_A0); 1558c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_paodr &= ~(PA_XHFC_A0); 1568c2ecf20Sopenharmony_ci hc->immap->im_ioport.iop_padir |= PA_XHFC_A0; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* Prepare the MPC8xx PortB __X__ as input (ISDN__X__IRQ) */ 1598c2ecf20Sopenharmony_ci hc->pb_irqmsk = (PB_XHFC_IRQ1 << hc->id); 1608c2ecf20Sopenharmony_ci hc->immap->im_cpm.cp_pbpar &= ~(hc->pb_irqmsk); 1618c2ecf20Sopenharmony_ci hc->immap->im_cpm.cp_pbodr &= ~(hc->pb_irqmsk); 1628c2ecf20Sopenharmony_ci hc->immap->im_cpm.cp_pbdir &= ~(hc->pb_irqmsk); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci /* At this point the needed config is done */ 1658c2ecf20Sopenharmony_ci /* fifos are still not enabled */ 1668c2ecf20Sopenharmony_ci return 0; 1678c2ecf20Sopenharmony_ci} 168