• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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