Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
db9bb63a KK |
2 | /* |
3 | * For License see notice in hfc_multi.c | |
4 | * | |
5 | * special IO and init functions for the embedded XHFC board | |
6 | * from Speech Design | |
7 | * | |
8 | */ | |
9 | ||
b79df0fc | 10 | #include <asm/cpm1.h> |
db9bb63a KK |
11 | |
12 | /* Change this to the value used by your board */ | |
13 | #ifndef IMAP_ADDR | |
14 | #define IMAP_ADDR 0xFFF00000 | |
15 | #endif | |
16 | ||
17 | static void | |
18 | #ifdef HFC_REGISTER_DEBUG | |
19 | HFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val, | |
475be4d8 | 20 | const char *function, int line) |
db9bb63a | 21 | #else |
475be4d8 | 22 | HFC_outb_embsd(struct hfc_multi *hc, u_char reg, u_char val) |
db9bb63a KK |
23 | #endif |
24 | { | |
25 | hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; | |
26 | writeb(reg, hc->xhfc_memaddr); | |
27 | hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); | |
28 | writeb(val, hc->xhfc_memdata); | |
29 | } | |
30 | static u_char | |
31 | #ifdef HFC_REGISTER_DEBUG | |
32 | HFC_inb_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line) | |
33 | #else | |
475be4d8 | 34 | HFC_inb_embsd(struct hfc_multi *hc, u_char reg) |
db9bb63a KK |
35 | #endif |
36 | { | |
37 | hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; | |
38 | writeb(reg, hc->xhfc_memaddr); | |
39 | hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); | |
40 | return readb(hc->xhfc_memdata); | |
41 | } | |
42 | static u_short | |
43 | #ifdef HFC_REGISTER_DEBUG | |
44 | HFC_inw_embsd(struct hfc_multi *hc, u_char reg, const char *function, int line) | |
45 | #else | |
475be4d8 | 46 | HFC_inw_embsd(struct hfc_multi *hc, u_char reg) |
db9bb63a KK |
47 | #endif |
48 | { | |
49 | hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; | |
50 | writeb(reg, hc->xhfc_memaddr); | |
51 | hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); | |
52 | return readb(hc->xhfc_memdata); | |
53 | } | |
54 | static void | |
55 | #ifdef HFC_REGISTER_DEBUG | |
56 | HFC_wait_embsd(struct hfc_multi *hc, const char *function, int line) | |
57 | #else | |
475be4d8 | 58 | HFC_wait_embsd(struct hfc_multi *hc) |
db9bb63a KK |
59 | #endif |
60 | { | |
61 | hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; | |
62 | writeb(R_STATUS, hc->xhfc_memaddr); | |
63 | hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); | |
64 | while (readb(hc->xhfc_memdata) & V_BUSY) | |
65 | cpu_relax(); | |
66 | } | |
67 | ||
68 | /* write fifo data (EMBSD) */ | |
69 | void | |
70 | write_fifo_embsd(struct hfc_multi *hc, u_char *data, int len) | |
71 | { | |
72 | hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; | |
73 | *hc->xhfc_memaddr = A_FIFO_DATA0; | |
74 | hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); | |
75 | while (len) { | |
76 | *hc->xhfc_memdata = *data; | |
77 | data++; | |
78 | len--; | |
79 | } | |
80 | } | |
81 | ||
82 | /* read fifo data (EMBSD) */ | |
83 | void | |
84 | read_fifo_embsd(struct hfc_multi *hc, u_char *data, int len) | |
85 | { | |
86 | hc->immap->im_ioport.iop_padat |= PA_XHFC_A0; | |
87 | *hc->xhfc_memaddr = A_FIFO_DATA0; | |
88 | hc->immap->im_ioport.iop_padat &= ~(PA_XHFC_A0); | |
89 | while (len) { | |
90 | *data = (u_char)(*hc->xhfc_memdata); | |
91 | data++; | |
92 | len--; | |
93 | } | |
94 | } | |
95 | ||
96 | static int | |
97 | setup_embedded(struct hfc_multi *hc, struct hm_map *m) | |
98 | { | |
99 | printk(KERN_INFO | |
475be4d8 JP |
100 | "HFC-multi: card manufacturer: '%s' card name: '%s' clock: %s\n", |
101 | m->vendor_name, m->card_name, m->clock2 ? "double" : "normal"); | |
db9bb63a KK |
102 | |
103 | hc->pci_dev = NULL; | |
104 | if (m->clock2) | |
105 | test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip); | |
106 | ||
107 | hc->leds = m->leds; | |
108 | hc->ledstate = 0xAFFEAFFE; | |
109 | hc->opticalsupport = m->opticalsupport; | |
110 | ||
111 | hc->pci_iobase = 0; | |
112 | hc->pci_membase = 0; | |
113 | hc->xhfc_membase = NULL; | |
114 | hc->xhfc_memaddr = NULL; | |
115 | hc->xhfc_memdata = NULL; | |
116 | ||
117 | /* set memory access methods */ | |
118 | if (m->io_mode) /* use mode from card config */ | |
119 | hc->io_mode = m->io_mode; | |
120 | switch (hc->io_mode) { | |
121 | case HFC_IO_MODE_EMBSD: | |
122 | test_and_set_bit(HFC_CHIP_EMBSD, &hc->chip); | |
123 | hc->slots = 128; /* required */ | |
124 | /* fall through */ | |
125 | hc->HFC_outb = HFC_outb_embsd; | |
126 | hc->HFC_inb = HFC_inb_embsd; | |
127 | hc->HFC_inw = HFC_inw_embsd; | |
128 | hc->HFC_wait = HFC_wait_embsd; | |
129 | hc->read_fifo = read_fifo_embsd; | |
130 | hc->write_fifo = write_fifo_embsd; | |
131 | hc->xhfc_origmembase = XHFC_MEMBASE + XHFC_OFFSET * hc->id; | |
132 | hc->xhfc_membase = (u_char *)ioremap(hc->xhfc_origmembase, | |
475be4d8 | 133 | XHFC_MEMSIZE); |
db9bb63a KK |
134 | if (!hc->xhfc_membase) { |
135 | printk(KERN_WARNING | |
475be4d8 JP |
136 | "HFC-multi: failed to remap xhfc address space. " |
137 | "(internal error)\n"); | |
db9bb63a KK |
138 | return -EIO; |
139 | } | |
140 | hc->xhfc_memaddr = (u_long *)(hc->xhfc_membase + 4); | |
141 | hc->xhfc_memdata = (u_long *)(hc->xhfc_membase); | |
142 | printk(KERN_INFO | |
475be4d8 JP |
143 | "HFC-multi: xhfc_membase:%#lx xhfc_origmembase:%#lx " |
144 | "xhfc_memaddr:%#lx xhfc_memdata:%#lx\n", | |
145 | (u_long)hc->xhfc_membase, hc->xhfc_origmembase, | |
146 | (u_long)hc->xhfc_memaddr, (u_long)hc->xhfc_memdata); | |
db9bb63a KK |
147 | break; |
148 | default: | |
149 | printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n"); | |
150 | return -EIO; | |
151 | } | |
152 | ||
153 | /* Prepare the MPC8XX PortA 10 as output (address/data selector) */ | |
154 | hc->immap = (struct immap *)(IMAP_ADDR); | |
155 | hc->immap->im_ioport.iop_papar &= ~(PA_XHFC_A0); | |
156 | hc->immap->im_ioport.iop_paodr &= ~(PA_XHFC_A0); | |
157 | hc->immap->im_ioport.iop_padir |= PA_XHFC_A0; | |
158 | ||
159 | /* Prepare the MPC8xx PortB __X__ as input (ISDN__X__IRQ) */ | |
160 | hc->pb_irqmsk = (PB_XHFC_IRQ1 << hc->id); | |
161 | hc->immap->im_cpm.cp_pbpar &= ~(hc->pb_irqmsk); | |
162 | hc->immap->im_cpm.cp_pbodr &= ~(hc->pb_irqmsk); | |
163 | hc->immap->im_cpm.cp_pbdir &= ~(hc->pb_irqmsk); | |
164 | ||
165 | /* At this point the needed config is done */ | |
166 | /* fifos are still not enabled */ | |
167 | return 0; | |
168 | } |