Merge tag 'drm-intel-fixes-2014-02-14' of ssh://git.freedesktop.org/git/drm-intel...
[deliverable/linux.git] / drivers / staging / sbe-2t3e3 / ctrl.c
CommitLineData
921a86e0
KH
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
17void 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
39e2ce9a 34static void t3e3_set_loopback(struct channel *sc, u32 mode)
921a86e0
KH
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
39e2ce9a 98static void t3e3_reg_read(struct channel *sc, u32 *reg, u32 *val)
921a86e0
KH
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
39e2ce9a 135static void t3e3_reg_write(struct channel *sc, u32 *reg)
921a86e0
KH
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
39e2ce9a 167static void t3e3_port_get(struct channel *sc, t3e3_param_t *param)
921a86e0
KH
168{
169 memcpy(param, &(sc->p), sizeof(t3e3_param_t));
170}
171
39e2ce9a 172static void t3e3_port_set(struct channel *sc, t3e3_param_t *param)
921a86e0
KH
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
39e2ce9a 219static void t3e3_port_get_stats(struct channel *sc,
921a86e0
KH
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;
12f3f21d 233
921a86e0 234 cpld_LOS_update(sc);
12f3f21d 235
921a86e0
KH
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;
12f3f21d 244
921a86e0 245 cpld_LOS_update(sc);
12f3f21d 246
921a86e0
KH
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
39e2ce9a 285static void t3e3_port_del_stats(struct channel *sc)
921a86e0
KH
286{
287 memset(&(sc->s), 0, sizeof(t3e3_stats_t));
288}
289
290void 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:
921a86e0
KH
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 }
921a86e0
KH
331}
332
333void 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}
This page took 0.305885 seconds and 5 git commands to generate.