1 /*
2 * SBE 2T3E3 synchronous serial card driver for Linux
3 *
4 * Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License
8 * as published by the Free Software Foundation.
9 *
10 * This code is based on a driver written by SBE Inc.
11 */
12
13 #include <linux/delay.h>
14 #include "2t3e3.h"
15 #include "ctrl.h"
16
17 #define bootrom_set_bit(sc, reg, bit) \
18 bootrom_write((sc), (reg), \
19 bootrom_read((sc), (reg)) | (bit))
20
21 #define bootrom_clear_bit(sc, reg, bit) \
22 bootrom_write((sc), (reg), \
23 bootrom_read((sc), (reg)) & ~(bit))
24
cpld_set_bit(struct channel * channel,unsigned reg,u32 bit)25 static inline void cpld_set_bit(struct channel *channel, unsigned reg, u32 bit)
26 {
27 unsigned long flags;
28 spin_lock_irqsave(&channel->card->bootrom_lock, flags);
29 bootrom_set_bit(channel, CPLD_MAP_REG(reg, channel), bit);
30 spin_unlock_irqrestore(&channel->card->bootrom_lock, flags);
31 }
32
cpld_clear_bit(struct channel * channel,unsigned reg,u32 bit)33 static inline void cpld_clear_bit(struct channel *channel, unsigned reg, u32 bit)
34 {
35 unsigned long flags;
36 spin_lock_irqsave(&channel->card->bootrom_lock, flags);
37 bootrom_clear_bit(channel, CPLD_MAP_REG(reg, channel), bit);
38 spin_unlock_irqrestore(&channel->card->bootrom_lock, flags);
39 }
40
cpld_init(struct channel * sc)41 void cpld_init(struct channel *sc)
42 {
43 u32 val;
44 #if 0
45 /* reset LIU and Framer */
46 val = cpld_val_map[SBE_2T3E3_CPLD_VAL_LIU_FRAMER_RESET][sc->h.slot];
47 cpld_write(sc, SBE_2T3E3_CPLD_REG_STATIC_RESET, val);
48 udelay(10000); /* TODO - how long? */
49 val = 0;
50 cpld_write(sc, SBE_2T3E3_CPLD_REG_STATIC_RESET, val);
51 #endif
52
53 /* PCRA */
54 val = SBE_2T3E3_CPLD_VAL_CRC32 |
55 cpld_val_map[SBE_2T3E3_CPLD_VAL_LOOP_TIMING_SOURCE][sc->h.slot];
56 cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRA, val);
57
58 /* PCRB */
59 val = 0;
60 cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRB, val);
61
62 /* PCRC */
63 val = 0;
64 cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC, val);
65
66 /* PBWF */
67 val = 0;
68 cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWF, val);
69
70 /* PBWL */
71 val = 0;
72 cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWL, val);
73
74 /* PLTR */
75 val = SBE_2T3E3_CPLD_VAL_LCV_COUNTER;
76 cpld_write(sc, SBE_2T3E3_CPLD_REG_PLTR, val);
77 udelay(1000);
78
79 /* PLCR */
80 val = 0;
81 cpld_write(sc, SBE_2T3E3_CPLD_REG_PLCR, val);
82 udelay(1000);
83
84 /* PPFR */
85 val = 0x55;
86 cpld_write(sc, SBE_2T3E3_CPLD_REG_PPFR, val);
87 /* TODO: this doesn't work!!! */
88
89 /* SERIAL_CHIP_SELECT */
90 val = 0;
91 cpld_write(sc, SBE_2T3E3_CPLD_REG_SERIAL_CHIP_SELECT, val);
92
93 /* PICSR */
94 val = SBE_2T3E3_CPLD_VAL_DMO_SIGNAL_DETECTED |
95 SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_LOCK_DETECTED |
96 SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_DETECTED;
97 cpld_write(sc, SBE_2T3E3_CPLD_REG_PICSR, val);
98
99 cpld_start_intr(sc);
100
101 udelay(1000);
102 }
103
cpld_start_intr(struct channel * sc)104 void cpld_start_intr(struct channel *sc)
105 {
106 u32 val;
107
108 /* PIER */
109 val = SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_ETHERNET_ENABLE |
110 SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_FRAMER_ENABLE;
111 cpld_write(sc, SBE_2T3E3_CPLD_REG_PIER, val);
112 #if 0
113 /*
114 do you want to hang up your computer?
115 ENABLE REST OF INTERRUPTS !!!
116 you have been warned :).
117 */
118 #endif
119 }
120
cpld_stop_intr(struct channel * sc)121 void cpld_stop_intr(struct channel *sc)
122 {
123 u32 val;
124
125 /* PIER */
126 val = 0;
127 cpld_write(sc, SBE_2T3E3_CPLD_REG_PIER, val);
128 }
129
cpld_set_frame_mode(struct channel * sc,u32 mode)130 void cpld_set_frame_mode(struct channel *sc, u32 mode)
131 {
132 if (sc->p.frame_mode == mode)
133 return;
134
135 switch (mode) {
136 case SBE_2T3E3_FRAME_MODE_HDLC:
137 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
138 SBE_2T3E3_CPLD_VAL_TRANSPARENT_MODE |
139 SBE_2T3E3_CPLD_VAL_RAW_MODE);
140 exar7250_unipolar_onoff(sc, SBE_2T3E3_OFF);
141 exar7300_unipolar_onoff(sc, SBE_2T3E3_OFF);
142 break;
143 case SBE_2T3E3_FRAME_MODE_TRANSPARENT:
144 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
145 SBE_2T3E3_CPLD_VAL_RAW_MODE);
146 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
147 SBE_2T3E3_CPLD_VAL_TRANSPARENT_MODE);
148 exar7250_unipolar_onoff(sc, SBE_2T3E3_OFF);
149 exar7300_unipolar_onoff(sc, SBE_2T3E3_OFF);
150 break;
151 case SBE_2T3E3_FRAME_MODE_RAW:
152 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
153 SBE_2T3E3_CPLD_VAL_RAW_MODE);
154 exar7250_unipolar_onoff(sc, SBE_2T3E3_ON);
155 exar7300_unipolar_onoff(sc, SBE_2T3E3_ON);
156 break;
157 default:
158 return;
159 }
160
161 sc->p.frame_mode = mode;
162 }
163
164 /* set rate of the local clock */
cpld_set_frame_type(struct channel * sc,u32 type)165 void cpld_set_frame_type(struct channel *sc, u32 type)
166 {
167 switch (type) {
168 case SBE_2T3E3_FRAME_TYPE_E3_G751:
169 case SBE_2T3E3_FRAME_TYPE_E3_G832:
170 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
171 SBE_2T3E3_CPLD_VAL_LOCAL_CLOCK_E3);
172 break;
173 case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
174 case SBE_2T3E3_FRAME_TYPE_T3_M13:
175 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
176 SBE_2T3E3_CPLD_VAL_LOCAL_CLOCK_E3);
177 break;
178 default:
179 return;
180 }
181 }
182
cpld_set_scrambler(struct channel * sc,u32 mode)183 void cpld_set_scrambler(struct channel *sc, u32 mode)
184 {
185 if (sc->p.scrambler == mode)
186 return;
187
188 switch (mode) {
189 case SBE_2T3E3_SCRAMBLER_OFF:
190 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
191 SBE_2T3E3_CPLD_VAL_SCRAMBLER_ENABLE);
192 break;
193 case SBE_2T3E3_SCRAMBLER_LARSCOM:
194 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
195 SBE_2T3E3_CPLD_VAL_SCRAMBLER_TYPE);
196 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
197 SBE_2T3E3_CPLD_VAL_SCRAMBLER_ENABLE);
198 break;
199 case SBE_2T3E3_SCRAMBLER_ADC_KENTROX_DIGITAL:
200 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
201 SBE_2T3E3_CPLD_VAL_SCRAMBLER_TYPE);
202 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
203 SBE_2T3E3_CPLD_VAL_SCRAMBLER_ENABLE);
204 break;
205 default:
206 return;
207 }
208
209 sc->p.scrambler = mode;
210 }
211
212
cpld_set_crc(struct channel * sc,u32 crc)213 void cpld_set_crc(struct channel *sc, u32 crc)
214 {
215 if (sc->p.crc == crc)
216 return;
217
218 switch (crc) {
219 case SBE_2T3E3_CRC_16:
220 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
221 SBE_2T3E3_CPLD_VAL_CRC32);
222 break;
223 case SBE_2T3E3_CRC_32:
224 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
225 SBE_2T3E3_CPLD_VAL_CRC32);
226 break;
227 default:
228 return;
229 }
230
231 sc->p.crc = crc;
232 }
233
234
cpld_select_panel(struct channel * sc,u32 panel)235 void cpld_select_panel(struct channel *sc, u32 panel)
236 {
237 if (sc->p.panel == panel)
238 return;
239 switch (panel) {
240 case SBE_2T3E3_PANEL_FRONT:
241 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
242 SBE_2T3E3_CPLD_VAL_REAR_PANEL);
243 break;
244 case SBE_2T3E3_PANEL_REAR:
245 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
246 SBE_2T3E3_CPLD_VAL_REAR_PANEL);
247 break;
248 default:
249 return;
250 }
251
252 udelay(100);
253
254 sc->p.panel = panel;
255 }
256
257
cpld_set_clock(struct channel * sc,u32 mode)258 extern void cpld_set_clock(struct channel *sc, u32 mode)
259 {
260 if (sc->p.clock_source == mode)
261 return;
262
263 switch (mode) {
264 case SBE_2T3E3_TIMING_LOCAL:
265 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
266 SBE_2T3E3_CPLD_VAL_ALT);
267 break;
268 case SBE_2T3E3_TIMING_LOOP:
269 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
270 SBE_2T3E3_CPLD_VAL_ALT);
271 break;
272 default:
273 return;
274 }
275
276 sc->p.clock_source = mode;
277 }
278
cpld_set_pad_count(struct channel * sc,u32 count)279 void cpld_set_pad_count(struct channel *sc, u32 count)
280 {
281 u32 val;
282
283 if (sc->p.pad_count == count)
284 return;
285
286 switch (count) {
287 case SBE_2T3E3_PAD_COUNT_1:
288 val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_1;
289 break;
290 case SBE_2T3E3_PAD_COUNT_2:
291 val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_2;
292 break;
293 case SBE_2T3E3_PAD_COUNT_3:
294 val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_3;
295 break;
296 case SBE_2T3E3_PAD_COUNT_4:
297 val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_4;
298 break;
299 default:
300 return;
301 }
302
303 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
304 SBE_2T3E3_CPLD_VAL_PAD_COUNT);
305 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB, val);
306 sc->p.pad_count = count;
307 }
308
cpld_LOS_update(struct channel * sc)309 void cpld_LOS_update(struct channel *sc)
310 {
311 u_int8_t los;
312
313 cpld_write(sc, SBE_2T3E3_CPLD_REG_PICSR,
314 SBE_2T3E3_CPLD_VAL_DMO_SIGNAL_DETECTED |
315 SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_LOCK_DETECTED |
316 SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_DETECTED);
317 los = cpld_read(sc, SBE_2T3E3_CPLD_REG_PICSR) &
318 SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_DETECTED;
319
320 if (los != sc->s.LOS)
321 dev_info(&sc->pdev->dev, "SBE 2T3E3: LOS status: %s\n",
322 los ? "Loss of signal" : "Signal OK");
323 sc->s.LOS = los;
324 }
325
cpld_set_fractional_mode(struct channel * sc,u32 mode,u32 start,u32 stop)326 void cpld_set_fractional_mode(struct channel *sc, u32 mode,
327 u32 start, u32 stop)
328 {
329 if (mode == SBE_2T3E3_FRACTIONAL_MODE_NONE) {
330 start = 0;
331 stop = 0;
332 }
333
334 if (sc->p.fractional_mode == mode && sc->p.bandwidth_start == start &&
335 sc->p.bandwidth_stop == stop)
336 return;
337
338 switch (mode) {
339 case SBE_2T3E3_FRACTIONAL_MODE_NONE:
340 cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
341 SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_NONE);
342 break;
343 case SBE_2T3E3_FRACTIONAL_MODE_0:
344 cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
345 SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_0);
346 break;
347 case SBE_2T3E3_FRACTIONAL_MODE_1:
348 cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
349 SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_1);
350 break;
351 case SBE_2T3E3_FRACTIONAL_MODE_2:
352 cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
353 SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_2);
354 break;
355 default:
356 printk(KERN_ERR "wrong mode in set_fractional_mode\n");
357 return;
358 }
359
360 cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWF, start);
361 cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWL, stop);
362
363 sc->p.fractional_mode = mode;
364 sc->p.bandwidth_start = start;
365 sc->p.bandwidth_stop = stop;
366 }
367