]> Pileus Git - ~andy/linux/blob - drivers/staging/sbe-2t3e3/cpld.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[~andy/linux] / drivers / staging / sbe-2t3e3 / cpld.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/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
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
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
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
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
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
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 */
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
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
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
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
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
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
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
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 }