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/types.h>
14 #include "2t3e3.h"
15 #include "ctrl.h"
16 
t3e3_set_frame_type(struct channel * sc,u32 mode)17 void t3e3_set_frame_type(struct channel *sc, u32 mode)
18 {
19 	if (sc->p.frame_type == mode)
20 		return;
21 
22 	if (sc->r.flags & SBE_2T3E3_FLAG_NETWORK_UP) {
23 		dev_err(&sc->pdev->dev, "SBE 2T3E3: changing frame type during active connection\n");
24 		return;
25 	}
26 
27 	exar7300_set_frame_type(sc, mode);
28 	exar7250_set_frame_type(sc, mode);
29 	cpld_set_frame_type(sc, mode);
30 
31 	sc->p.frame_type = mode;
32 }
33 
t3e3_set_loopback(struct channel * sc,u32 mode)34 void t3e3_set_loopback(struct channel *sc, u32 mode)
35 {
36 	u32 tx, rx;
37 
38 	if (sc->p.loopback == mode)
39 		return;
40 
41 	tx = sc->p.transmitter_on;
42 	rx = sc->p.receiver_on;
43 	if (tx == SBE_2T3E3_ON)
44 		dc_transmitter_onoff(sc, SBE_2T3E3_OFF);
45 	if (rx == SBE_2T3E3_ON)
46 		dc_receiver_onoff(sc, SBE_2T3E3_OFF);
47 
48 	/* stop current loopback if any exists */
49 	switch (sc->p.loopback) {
50 	case SBE_2T3E3_LOOPBACK_NONE:
51 		break;
52 	case SBE_2T3E3_LOOPBACK_ETHERNET:
53 		dc_set_loopback(sc, SBE_2T3E3_21143_VAL_LOOPBACK_OFF);
54 		break;
55 	case SBE_2T3E3_LOOPBACK_FRAMER:
56 		exar7250_set_loopback(sc, SBE_2T3E3_FRAMER_VAL_LOOPBACK_OFF);
57 		break;
58 	case SBE_2T3E3_LOOPBACK_LIU_DIGITAL:
59 	case SBE_2T3E3_LOOPBACK_LIU_ANALOG:
60 	case SBE_2T3E3_LOOPBACK_LIU_REMOTE:
61 		exar7300_set_loopback(sc, SBE_2T3E3_LIU_VAL_LOOPBACK_OFF);
62 		break;
63 	default:
64 		return;
65 	}
66 
67 	switch (mode) {
68 	case SBE_2T3E3_LOOPBACK_NONE:
69 		break;
70 	case SBE_2T3E3_LOOPBACK_ETHERNET:
71 		dc_set_loopback(sc, SBE_2T3E3_21143_VAL_LOOPBACK_INTERNAL);
72 		break;
73 	case SBE_2T3E3_LOOPBACK_FRAMER:
74 		exar7250_set_loopback(sc, SBE_2T3E3_FRAMER_VAL_LOOPBACK_ON);
75 		break;
76 	case SBE_2T3E3_LOOPBACK_LIU_DIGITAL:
77 		exar7300_set_loopback(sc, SBE_2T3E3_LIU_VAL_LOOPBACK_DIGITAL);
78 		break;
79 	case SBE_2T3E3_LOOPBACK_LIU_ANALOG:
80 		exar7300_set_loopback(sc, SBE_2T3E3_LIU_VAL_LOOPBACK_ANALOG);
81 		break;
82 	case SBE_2T3E3_LOOPBACK_LIU_REMOTE:
83 		exar7300_set_loopback(sc, SBE_2T3E3_LIU_VAL_LOOPBACK_REMOTE);
84 		break;
85 	default:
86 		return;
87 	}
88 
89 	sc->p.loopback = mode;
90 
91 	if (tx == SBE_2T3E3_ON)
92 		dc_transmitter_onoff(sc, SBE_2T3E3_ON);
93 	if (rx == SBE_2T3E3_ON)
94 		dc_receiver_onoff(sc, SBE_2T3E3_ON);
95 }
96 
97 
t3e3_reg_read(struct channel * sc,u32 * reg,u32 * val)98 void t3e3_reg_read(struct channel *sc, u32 *reg, u32 *val)
99 {
100 	u32 i;
101 
102 	*val = 0;
103 
104 	switch (reg[0]) {
105 	case SBE_2T3E3_CHIP_21143:
106 		if (!(reg[1] & 7))
107 			*val = dc_read(sc->addr, reg[1] / 8);
108 		break;
109 	case SBE_2T3E3_CHIP_CPLD:
110 		for (i = 0; i < SBE_2T3E3_CPLD_REG_MAX; i++)
111 			if (cpld_reg_map[i][sc->h.slot] == reg[1]) {
112 				*val = cpld_read(sc, i);
113 				break;
114 			}
115 		break;
116 	case SBE_2T3E3_CHIP_FRAMER:
117 		for (i = 0; i < SBE_2T3E3_FRAMER_REG_MAX; i++)
118 			if (t3e3_framer_reg_map[i] == reg[1]) {
119 				*val = exar7250_read(sc, i);
120 				break;
121 			}
122 		break;
123 	case SBE_2T3E3_CHIP_LIU:
124 		for (i = 0; i < SBE_2T3E3_LIU_REG_MAX; i++)
125 			if (t3e3_liu_reg_map[i] == reg[1]) {
126 				*val = exar7300_read(sc, i);
127 				break;
128 			}
129 		break;
130 	default:
131 		break;
132 	}
133 }
134 
t3e3_reg_write(struct channel * sc,u32 * reg)135 void t3e3_reg_write(struct channel *sc, u32 *reg)
136 {
137 	u32 i;
138 
139 	switch (reg[0]) {
140 	case SBE_2T3E3_CHIP_21143:
141 		dc_write(sc->addr, reg[1], reg[2]);
142 		break;
143 	case SBE_2T3E3_CHIP_CPLD:
144 		for (i = 0; i < SBE_2T3E3_CPLD_REG_MAX; i++)
145 			if (cpld_reg_map[i][sc->h.slot] == reg[1]) {
146 				cpld_write(sc, i, reg[2]);
147 				break;
148 			}
149 		break;
150 	case SBE_2T3E3_CHIP_FRAMER:
151 		for (i = 0; i < SBE_2T3E3_FRAMER_REG_MAX; i++)
152 			if (t3e3_framer_reg_map[i] == reg[1]) {
153 				exar7250_write(sc, i, reg[2]);
154 				break;
155 			}
156 		break;
157 	case SBE_2T3E3_CHIP_LIU:
158 		for (i = 0; i < SBE_2T3E3_LIU_REG_MAX; i++)
159 			if (t3e3_liu_reg_map[i] == reg[1]) {
160 				exar7300_write(sc, i, reg[2]);
161 				break;
162 			}
163 		break;
164 	}
165 }
166 
t3e3_port_get(struct channel * sc,t3e3_param_t * param)167 void t3e3_port_get(struct channel *sc, t3e3_param_t *param)
168 {
169 	memcpy(param, &(sc->p), sizeof(t3e3_param_t));
170 }
171 
t3e3_port_set(struct channel * sc,t3e3_param_t * param)172 void t3e3_port_set(struct channel *sc, t3e3_param_t *param)
173 {
174 	if (param->frame_mode != 0xff)
175 		cpld_set_frame_mode(sc, param->frame_mode);
176 
177 	if (param->fractional_mode != 0xff)
178 		cpld_set_fractional_mode(sc, param->fractional_mode,
179 					 param->bandwidth_start,
180 					 param->bandwidth_stop);
181 
182 	if (param->pad_count != 0xff)
183 		cpld_set_pad_count(sc, param->pad_count);
184 
185 	if (param->crc != 0xff)
186 		cpld_set_crc(sc, param->crc);
187 
188 	if (param->receiver_on != 0xff)
189 		dc_receiver_onoff(sc, param->receiver_on);
190 
191 	if (param->transmitter_on != 0xff)
192 		dc_transmitter_onoff(sc, param->transmitter_on);
193 
194 	if (param->frame_type != 0xff)
195 		t3e3_set_frame_type(sc, param->frame_type);
196 
197 	if (param->panel != 0xff)
198 		cpld_select_panel(sc, param->panel);
199 
200 	if (param->line_build_out != 0xff)
201 		exar7300_line_build_out_onoff(sc, param->line_build_out);
202 
203 	if (param->receive_equalization != 0xff)
204 		exar7300_receive_equalization_onoff(sc, param->receive_equalization);
205 
206 	if (param->transmit_all_ones != 0xff)
207 		exar7300_transmit_all_ones_onoff(sc, param->transmit_all_ones);
208 
209 	if (param->loopback != 0xff)
210 		t3e3_set_loopback(sc, param->loopback);
211 
212 	if (param->clock_source != 0xff)
213 		cpld_set_clock(sc, param->clock_source);
214 
215 	if (param->scrambler != 0xff)
216 		cpld_set_scrambler(sc, param->scrambler);
217 }
218 
t3e3_port_get_stats(struct channel * sc,t3e3_stats_t * stats)219 void t3e3_port_get_stats(struct channel *sc,
220 			 t3e3_stats_t *stats)
221 {
222 	u32 result;
223 
224 	sc->s.LOC = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_IO_CONTROL)
225 		& SBE_2T3E3_FRAMER_VAL_LOSS_OF_CLOCK_STATUS ? 1 : 0;
226 
227 	switch (sc->p.frame_type) {
228 	case SBE_2T3E3_FRAME_TYPE_E3_G751:
229 	case SBE_2T3E3_FRAME_TYPE_E3_G832:
230 		result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_E3_RX_CONFIGURATION_STATUS_2);
231 		sc->s.LOF = result & SBE_2T3E3_FRAMER_VAL_E3_RX_LOF ? 1 : 0;
232 		sc->s.OOF = result & SBE_2T3E3_FRAMER_VAL_E3_RX_OOF ? 1 : 0;
233 #if 0
234 		sc->s.LOS = result & SBE_2T3E3_FRAMER_VAL_E3_RX_LOS ? 1 : 0;
235 #else
236 		cpld_LOS_update(sc);
237 #endif
238 		sc->s.AIS = result & SBE_2T3E3_FRAMER_VAL_E3_RX_AIS ? 1 : 0;
239 		sc->s.FERF = result & SBE_2T3E3_FRAMER_VAL_E3_RX_FERF ? 1 : 0;
240 		break;
241 
242 	case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
243 	case SBE_2T3E3_FRAME_TYPE_T3_M13:
244 		result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_CONFIGURATION_STATUS);
245 		sc->s.AIS = result & SBE_2T3E3_FRAMER_VAL_T3_RX_AIS ? 1 : 0;
246 #if 0
247 		sc->s.LOS = result & SBE_2T3E3_FRAMER_VAL_T3_RX_LOS ? 1 : 0;
248 #else
249 		cpld_LOS_update(sc);
250 #endif
251 		sc->s.IDLE = result & SBE_2T3E3_FRAMER_VAL_T3_RX_IDLE ? 1 : 0;
252 		sc->s.OOF = result & SBE_2T3E3_FRAMER_VAL_T3_RX_OOF ? 1 : 0;
253 
254 		result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_STATUS);
255 		sc->s.FERF = result & SBE_2T3E3_FRAMER_VAL_T3_RX_FERF ? 1 : 0;
256 		sc->s.AIC = result & SBE_2T3E3_FRAMER_VAL_T3_RX_AIC ? 1 : 0;
257 		sc->s.FEBE_code = result & SBE_2T3E3_FRAMER_VAL_T3_RX_FEBE;
258 
259 		sc->s.FEAC = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_FEAC);
260 		break;
261 
262 	default:
263 		break;
264 	}
265 
266 	result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_LCV_EVENT_COUNT_MSB) << 8;
267 	result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
268 	sc->s.LCV += result;
269 
270 	result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_FRAMING_BIT_ERROR_EVENT_COUNT_MSB) << 8;
271 	result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
272 	sc->s.FRAMING_BIT += result;
273 
274 	result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_PARITY_ERROR_EVENT_COUNT_MSB) << 8;
275 	result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
276 	sc->s.PARITY_ERROR += result;
277 
278 	result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_FEBE_EVENT_COUNT_MSB) << 8;
279 	result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
280 	sc->s.FEBE_count += result;
281 
282 	result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_CP_BIT_ERROR_EVENT_COUNT_MSB) << 8;
283 	result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
284 	sc->s.CP_BIT += result;
285 
286 	memcpy(stats, &(sc->s), sizeof(t3e3_stats_t));
287 }
288 
t3e3_port_del_stats(struct channel * sc)289 void t3e3_port_del_stats(struct channel *sc)
290 {
291 	memset(&(sc->s), 0, sizeof(t3e3_stats_t));
292 }
293 
t3e3_if_config(struct channel * sc,u32 cmd,char * set,t3e3_resp_t * ret,int * rlen)294 void t3e3_if_config(struct channel *sc, u32 cmd, char *set,
295 		    t3e3_resp_t *ret, int *rlen)
296 {
297 	t3e3_param_t *param = (t3e3_param_t *)set;
298 	u32 *data = (u32 *)set;
299 
300 	/* turn off all interrupt */
301 	/* cpld_stop_intr(sc); */
302 
303 	switch (cmd) {
304 	case SBE_2T3E3_PORT_GET:
305 		t3e3_port_get(sc, &(ret->u.param));
306 		*rlen = sizeof(ret->u.param);
307 		break;
308 	case SBE_2T3E3_PORT_SET:
309 		t3e3_port_set(sc, param);
310 		*rlen = 0;
311 		break;
312 	case SBE_2T3E3_PORT_GET_STATS:
313 		t3e3_port_get_stats(sc, &(ret->u.stats));
314 		*rlen = sizeof(ret->u.stats);
315 		break;
316 	case SBE_2T3E3_PORT_DEL_STATS:
317 		t3e3_port_del_stats(sc);
318 		*rlen = 0;
319 		break;
320 	case SBE_2T3E3_PORT_READ_REGS:
321 		t3e3_reg_read(sc, data, &(ret->u.data));
322 		*rlen = sizeof(ret->u.data);
323 		break;
324 	case SBE_2T3E3_PORT_WRITE_REGS:
325 #if 0
326 		printk(KERN_DEBUG "SBE_2T3E3_PORT_WRITE_REGS, 0x%x, 0x%x, 0x%x\n",
327 		       ((int*)data)[0], ((int*)data)[1], ((int*)data)[2]);
328 #endif
329 		t3e3_reg_write(sc, data);
330 		*rlen = 0;
331 		break;
332 	case SBE_2T3E3_LOG_LEVEL:
333 		*rlen = 0;
334 		break;
335 	default:
336 		*rlen = 0;
337 		break;
338 	}
339 
340 	/* turn on interrupt */
341 	/* cpld_start_intr(sc); */
342 }
343 
t3e3_sc_init(struct channel * sc)344 void t3e3_sc_init(struct channel *sc)
345 {
346 	memset(sc, 0, sizeof(*sc));
347 
348 	sc->p.frame_mode = SBE_2T3E3_FRAME_MODE_HDLC;
349 	sc->p.fractional_mode = SBE_2T3E3_FRACTIONAL_MODE_NONE;
350 	sc->p.crc = SBE_2T3E3_CRC_32;
351 	sc->p.receiver_on = SBE_2T3E3_OFF;
352 	sc->p.transmitter_on = SBE_2T3E3_OFF;
353 	sc->p.frame_type = SBE_2T3E3_FRAME_TYPE_T3_CBIT;
354 	sc->p.panel = SBE_2T3E3_PANEL_FRONT;
355 	sc->p.line_build_out = SBE_2T3E3_OFF;
356 	sc->p.receive_equalization = SBE_2T3E3_OFF;
357 	sc->p.transmit_all_ones = SBE_2T3E3_OFF;
358 	sc->p.loopback = SBE_2T3E3_LOOPBACK_NONE;
359 	sc->p.clock_source = SBE_2T3E3_TIMING_LOCAL;
360 	sc->p.scrambler = SBE_2T3E3_SCRAMBLER_OFF;
361 	sc->p.pad_count = SBE_2T3E3_PAD_COUNT_1;
362 }
363