Linux-libre 3.10.72-gnu
[librecmc/linux-libre.git] / drivers / staging / sbe-2t3e3 / ctrl.c
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
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
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
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
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
167 void t3e3_port_get(struct channel *sc, t3e3_param_t *param)
168 {
169         memcpy(param, &(sc->p), sizeof(t3e3_param_t));
170 }
171
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
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
234                 cpld_LOS_update(sc);
235
236                 sc->s.AIS = result & SBE_2T3E3_FRAMER_VAL_E3_RX_AIS ? 1 : 0;
237                 sc->s.FERF = result & SBE_2T3E3_FRAMER_VAL_E3_RX_FERF ? 1 : 0;
238                 break;
239
240         case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
241         case SBE_2T3E3_FRAME_TYPE_T3_M13:
242                 result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_CONFIGURATION_STATUS);
243                 sc->s.AIS = result & SBE_2T3E3_FRAMER_VAL_T3_RX_AIS ? 1 : 0;
244
245                 cpld_LOS_update(sc);
246
247                 sc->s.IDLE = result & SBE_2T3E3_FRAMER_VAL_T3_RX_IDLE ? 1 : 0;
248                 sc->s.OOF = result & SBE_2T3E3_FRAMER_VAL_T3_RX_OOF ? 1 : 0;
249
250                 result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_STATUS);
251                 sc->s.FERF = result & SBE_2T3E3_FRAMER_VAL_T3_RX_FERF ? 1 : 0;
252                 sc->s.AIC = result & SBE_2T3E3_FRAMER_VAL_T3_RX_AIC ? 1 : 0;
253                 sc->s.FEBE_code = result & SBE_2T3E3_FRAMER_VAL_T3_RX_FEBE;
254
255                 sc->s.FEAC = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_T3_RX_FEAC);
256                 break;
257
258         default:
259                 break;
260         }
261
262         result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_LCV_EVENT_COUNT_MSB) << 8;
263         result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
264         sc->s.LCV += result;
265
266         result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_FRAMING_BIT_ERROR_EVENT_COUNT_MSB) << 8;
267         result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
268         sc->s.FRAMING_BIT += result;
269
270         result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_PARITY_ERROR_EVENT_COUNT_MSB) << 8;
271         result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
272         sc->s.PARITY_ERROR += result;
273
274         result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_FEBE_EVENT_COUNT_MSB) << 8;
275         result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
276         sc->s.FEBE_count += result;
277
278         result = exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_CP_BIT_ERROR_EVENT_COUNT_MSB) << 8;
279         result += exar7250_read(sc, SBE_2T3E3_FRAMER_REG_PMON_HOLDING_REGISTER);
280         sc->s.CP_BIT += result;
281
282         memcpy(stats, &(sc->s), sizeof(t3e3_stats_t));
283 }
284
285 void t3e3_port_del_stats(struct channel *sc)
286 {
287         memset(&(sc->s), 0, sizeof(t3e3_stats_t));
288 }
289
290 void t3e3_if_config(struct channel *sc, u32 cmd, char *set,
291                     t3e3_resp_t *ret, int *rlen)
292 {
293         t3e3_param_t *param = (t3e3_param_t *)set;
294         u32 *data = (u32 *)set;
295
296         /* turn off all interrupt */
297         /* cpld_stop_intr(sc); */
298
299         switch (cmd) {
300         case SBE_2T3E3_PORT_GET:
301                 t3e3_port_get(sc, &(ret->u.param));
302                 *rlen = sizeof(ret->u.param);
303                 break;
304         case SBE_2T3E3_PORT_SET:
305                 t3e3_port_set(sc, param);
306                 *rlen = 0;
307                 break;
308         case SBE_2T3E3_PORT_GET_STATS:
309                 t3e3_port_get_stats(sc, &(ret->u.stats));
310                 *rlen = sizeof(ret->u.stats);
311                 break;
312         case SBE_2T3E3_PORT_DEL_STATS:
313                 t3e3_port_del_stats(sc);
314                 *rlen = 0;
315                 break;
316         case SBE_2T3E3_PORT_READ_REGS:
317                 t3e3_reg_read(sc, data, &(ret->u.data));
318                 *rlen = sizeof(ret->u.data);
319                 break;
320         case SBE_2T3E3_PORT_WRITE_REGS:
321                 t3e3_reg_write(sc, data);
322                 *rlen = 0;
323                 break;
324         case SBE_2T3E3_LOG_LEVEL:
325                 *rlen = 0;
326                 break;
327         default:
328                 *rlen = 0;
329                 break;
330         }
331 }
332
333 void t3e3_sc_init(struct channel *sc)
334 {
335         memset(sc, 0, sizeof(*sc));
336
337         sc->p.frame_mode = SBE_2T3E3_FRAME_MODE_HDLC;
338         sc->p.fractional_mode = SBE_2T3E3_FRACTIONAL_MODE_NONE;
339         sc->p.crc = SBE_2T3E3_CRC_32;
340         sc->p.receiver_on = SBE_2T3E3_OFF;
341         sc->p.transmitter_on = SBE_2T3E3_OFF;
342         sc->p.frame_type = SBE_2T3E3_FRAME_TYPE_T3_CBIT;
343         sc->p.panel = SBE_2T3E3_PANEL_FRONT;
344         sc->p.line_build_out = SBE_2T3E3_OFF;
345         sc->p.receive_equalization = SBE_2T3E3_OFF;
346         sc->p.transmit_all_ones = SBE_2T3E3_OFF;
347         sc->p.loopback = SBE_2T3E3_LOOPBACK_NONE;
348         sc->p.clock_source = SBE_2T3E3_TIMING_LOCAL;
349         sc->p.scrambler = SBE_2T3E3_SCRAMBLER_OFF;
350         sc->p.pad_count = SBE_2T3E3_PAD_COUNT_1;
351 }