2 * SBE 2T3E3 synchronous serial card driver for Linux
4 * Copyright (C) 2009-2010 Krzysztof Halasa <khc@pm.waw.pl>
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.
10 * This code is based on a driver written by SBE Inc.
13 #include <linux/types.h>
17 void t3e3_set_frame_type(struct channel
*sc
, u32 mode
)
19 if (sc
->p
.frame_type
== mode
)
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");
27 exar7300_set_frame_type(sc
, mode
);
28 exar7250_set_frame_type(sc
, mode
);
29 cpld_set_frame_type(sc
, mode
);
31 sc
->p
.frame_type
= mode
;
34 void t3e3_set_loopback(struct channel
*sc
, u32 mode
)
38 if (sc
->p
.loopback
== mode
)
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
);
48 /* stop current loopback if any exists */
49 switch (sc
->p
.loopback
) {
50 case SBE_2T3E3_LOOPBACK_NONE
:
52 case SBE_2T3E3_LOOPBACK_ETHERNET
:
53 dc_set_loopback(sc
, SBE_2T3E3_21143_VAL_LOOPBACK_OFF
);
55 case SBE_2T3E3_LOOPBACK_FRAMER
:
56 exar7250_set_loopback(sc
, SBE_2T3E3_FRAMER_VAL_LOOPBACK_OFF
);
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
);
68 case SBE_2T3E3_LOOPBACK_NONE
:
70 case SBE_2T3E3_LOOPBACK_ETHERNET
:
71 dc_set_loopback(sc
, SBE_2T3E3_21143_VAL_LOOPBACK_INTERNAL
);
73 case SBE_2T3E3_LOOPBACK_FRAMER
:
74 exar7250_set_loopback(sc
, SBE_2T3E3_FRAMER_VAL_LOOPBACK_ON
);
76 case SBE_2T3E3_LOOPBACK_LIU_DIGITAL
:
77 exar7300_set_loopback(sc
, SBE_2T3E3_LIU_VAL_LOOPBACK_DIGITAL
);
79 case SBE_2T3E3_LOOPBACK_LIU_ANALOG
:
80 exar7300_set_loopback(sc
, SBE_2T3E3_LIU_VAL_LOOPBACK_ANALOG
);
82 case SBE_2T3E3_LOOPBACK_LIU_REMOTE
:
83 exar7300_set_loopback(sc
, SBE_2T3E3_LIU_VAL_LOOPBACK_REMOTE
);
89 sc
->p
.loopback
= mode
;
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
);
98 void t3e3_reg_read(struct channel
*sc
, u32
*reg
, u32
*val
)
105 case SBE_2T3E3_CHIP_21143
:
107 *val
= dc_read(sc
->addr
, reg
[1] / 8);
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
);
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
);
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
);
135 void t3e3_reg_write(struct channel
*sc
, u32
*reg
)
140 case SBE_2T3E3_CHIP_21143
:
141 dc_write(sc
->addr
, reg
[1], reg
[2]);
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]);
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]);
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]);
167 void t3e3_port_get(struct channel
*sc
, t3e3_param_t
*param
)
169 memcpy(param
, &(sc
->p
), sizeof(t3e3_param_t
));
172 void t3e3_port_set(struct channel
*sc
, t3e3_param_t
*param
)
174 if (param
->frame_mode
!= 0xff)
175 cpld_set_frame_mode(sc
, param
->frame_mode
);
177 if (param
->fractional_mode
!= 0xff)
178 cpld_set_fractional_mode(sc
, param
->fractional_mode
,
179 param
->bandwidth_start
,
180 param
->bandwidth_stop
);
182 if (param
->pad_count
!= 0xff)
183 cpld_set_pad_count(sc
, param
->pad_count
);
185 if (param
->crc
!= 0xff)
186 cpld_set_crc(sc
, param
->crc
);
188 if (param
->receiver_on
!= 0xff)
189 dc_receiver_onoff(sc
, param
->receiver_on
);
191 if (param
->transmitter_on
!= 0xff)
192 dc_transmitter_onoff(sc
, param
->transmitter_on
);
194 if (param
->frame_type
!= 0xff)
195 t3e3_set_frame_type(sc
, param
->frame_type
);
197 if (param
->panel
!= 0xff)
198 cpld_select_panel(sc
, param
->panel
);
200 if (param
->line_build_out
!= 0xff)
201 exar7300_line_build_out_onoff(sc
, param
->line_build_out
);
203 if (param
->receive_equalization
!= 0xff)
204 exar7300_receive_equalization_onoff(sc
, param
->receive_equalization
);
206 if (param
->transmit_all_ones
!= 0xff)
207 exar7300_transmit_all_ones_onoff(sc
, param
->transmit_all_ones
);
209 if (param
->loopback
!= 0xff)
210 t3e3_set_loopback(sc
, param
->loopback
);
212 if (param
->clock_source
!= 0xff)
213 cpld_set_clock(sc
, param
->clock_source
);
215 if (param
->scrambler
!= 0xff)
216 cpld_set_scrambler(sc
, param
->scrambler
);
219 void t3e3_port_get_stats(struct channel
*sc
,
224 sc
->s
.LOC
= exar7250_read(sc
, SBE_2T3E3_FRAMER_REG_IO_CONTROL
)
225 & SBE_2T3E3_FRAMER_VAL_LOSS_OF_CLOCK_STATUS
? 1 : 0;
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;
234 sc
->s
.LOS
= result
& SBE_2T3E3_FRAMER_VAL_E3_RX_LOS
? 1 : 0;
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;
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;
247 sc
->s
.LOS
= result
& SBE_2T3E3_FRAMER_VAL_T3_RX_LOS
? 1 : 0;
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;
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
;
259 sc
->s
.FEAC
= exar7250_read(sc
, SBE_2T3E3_FRAMER_REG_T3_RX_FEAC
);
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
);
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
;
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
;
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
;
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
;
286 memcpy(stats
, &(sc
->s
), sizeof(t3e3_stats_t
));
289 void t3e3_port_del_stats(struct channel
*sc
)
291 memset(&(sc
->s
), 0, sizeof(t3e3_stats_t
));
294 void t3e3_if_config(struct channel
*sc
, u32 cmd
, char *set
,
295 t3e3_resp_t
*ret
, int *rlen
)
297 t3e3_param_t
*param
= (t3e3_param_t
*)set
;
298 u32
*data
= (u32
*)set
;
300 /* turn off all interrupt */
301 /* cpld_stop_intr(sc); */
304 case SBE_2T3E3_PORT_GET
:
305 t3e3_port_get(sc
, &(ret
->u
.param
));
306 *rlen
= sizeof(ret
->u
.param
);
308 case SBE_2T3E3_PORT_SET
:
309 t3e3_port_set(sc
, param
);
312 case SBE_2T3E3_PORT_GET_STATS
:
313 t3e3_port_get_stats(sc
, &(ret
->u
.stats
));
314 *rlen
= sizeof(ret
->u
.stats
);
316 case SBE_2T3E3_PORT_DEL_STATS
:
317 t3e3_port_del_stats(sc
);
320 case SBE_2T3E3_PORT_READ_REGS
:
321 t3e3_reg_read(sc
, data
, &(ret
->u
.data
));
322 *rlen
= sizeof(ret
->u
.data
);
324 case SBE_2T3E3_PORT_WRITE_REGS
:
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]);
329 t3e3_reg_write(sc
, data
);
332 case SBE_2T3E3_LOG_LEVEL
:
340 /* turn on interrupt */
341 /* cpld_start_intr(sc); */
344 void t3e3_sc_init(struct channel
*sc
)
346 memset(sc
, 0, sizeof(*sc
));
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
;