ARM: OMAP3: fix dpll4_m3_ck and dpll4_m4_ck dividers
[cascardo/linux.git] / 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
45         /* PCRA */
46         val = SBE_2T3E3_CPLD_VAL_CRC32 |
47                 cpld_val_map[SBE_2T3E3_CPLD_VAL_LOOP_TIMING_SOURCE][sc->h.slot];
48         cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRA, val);
49
50         /* PCRB */
51         val = 0;
52         cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRB, val);
53
54         /* PCRC */
55         val = 0;
56         cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC, val);
57
58         /* PBWF */
59         val = 0;
60         cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWF, val);
61
62         /* PBWL */
63         val = 0;
64         cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWL, val);
65
66         /* PLTR */
67         val = SBE_2T3E3_CPLD_VAL_LCV_COUNTER;
68         cpld_write(sc, SBE_2T3E3_CPLD_REG_PLTR, val);
69         udelay(1000);
70
71         /* PLCR */
72         val = 0;
73         cpld_write(sc, SBE_2T3E3_CPLD_REG_PLCR, val);
74         udelay(1000);
75
76         /* PPFR */
77         val = 0x55;
78         cpld_write(sc, SBE_2T3E3_CPLD_REG_PPFR, val);
79         /* TODO: this doesn't work!!! */
80
81         /* SERIAL_CHIP_SELECT */
82         val = 0;
83         cpld_write(sc, SBE_2T3E3_CPLD_REG_SERIAL_CHIP_SELECT, val);
84
85         /* PICSR */
86         val = SBE_2T3E3_CPLD_VAL_DMO_SIGNAL_DETECTED |
87                 SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_LOCK_DETECTED |
88                 SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_DETECTED;
89         cpld_write(sc, SBE_2T3E3_CPLD_REG_PICSR, val);
90
91         cpld_start_intr(sc);
92
93         udelay(1000);
94 }
95
96 void cpld_start_intr(struct channel *sc)
97 {
98         u32 val;
99
100         /* PIER */
101         val = SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_ETHERNET_ENABLE |
102                 SBE_2T3E3_CPLD_VAL_INTERRUPT_FROM_FRAMER_ENABLE;
103         cpld_write(sc, SBE_2T3E3_CPLD_REG_PIER, val);
104 }
105
106 void cpld_stop_intr(struct channel *sc)
107 {
108         u32 val;
109
110         /* PIER */
111         val = 0;
112         cpld_write(sc, SBE_2T3E3_CPLD_REG_PIER, val);
113 }
114
115 void cpld_set_frame_mode(struct channel *sc, u32 mode)
116 {
117         if (sc->p.frame_mode == mode)
118                 return;
119
120         switch (mode) {
121         case SBE_2T3E3_FRAME_MODE_HDLC:
122                 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
123                                SBE_2T3E3_CPLD_VAL_TRANSPARENT_MODE |
124                                SBE_2T3E3_CPLD_VAL_RAW_MODE);
125                 exar7250_unipolar_onoff(sc, SBE_2T3E3_OFF);
126                 exar7300_unipolar_onoff(sc, SBE_2T3E3_OFF);
127                 break;
128         case SBE_2T3E3_FRAME_MODE_TRANSPARENT:
129                 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
130                                SBE_2T3E3_CPLD_VAL_RAW_MODE);
131                 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
132                              SBE_2T3E3_CPLD_VAL_TRANSPARENT_MODE);
133                 exar7250_unipolar_onoff(sc, SBE_2T3E3_OFF);
134                 exar7300_unipolar_onoff(sc, SBE_2T3E3_OFF);
135                 break;
136         case SBE_2T3E3_FRAME_MODE_RAW:
137                 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
138                              SBE_2T3E3_CPLD_VAL_RAW_MODE);
139                 exar7250_unipolar_onoff(sc, SBE_2T3E3_ON);
140                 exar7300_unipolar_onoff(sc, SBE_2T3E3_ON);
141                 break;
142         default:
143                 return;
144         }
145
146         sc->p.frame_mode = mode;
147 }
148
149 /* set rate of the local clock */
150 void cpld_set_frame_type(struct channel *sc, u32 type)
151 {
152         switch (type) {
153         case SBE_2T3E3_FRAME_TYPE_E3_G751:
154         case SBE_2T3E3_FRAME_TYPE_E3_G832:
155                 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
156                              SBE_2T3E3_CPLD_VAL_LOCAL_CLOCK_E3);
157                 break;
158         case SBE_2T3E3_FRAME_TYPE_T3_CBIT:
159         case SBE_2T3E3_FRAME_TYPE_T3_M13:
160                 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
161                                SBE_2T3E3_CPLD_VAL_LOCAL_CLOCK_E3);
162                 break;
163         default:
164                 return;
165         }
166 }
167
168 void cpld_set_scrambler(struct channel *sc, u32 mode)
169 {
170         if (sc->p.scrambler == mode)
171                 return;
172
173         switch (mode) {
174         case SBE_2T3E3_SCRAMBLER_OFF:
175                 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
176                                SBE_2T3E3_CPLD_VAL_SCRAMBLER_ENABLE);
177                 break;
178         case SBE_2T3E3_SCRAMBLER_LARSCOM:
179                 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
180                                SBE_2T3E3_CPLD_VAL_SCRAMBLER_TYPE);
181                 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
182                              SBE_2T3E3_CPLD_VAL_SCRAMBLER_ENABLE);
183                 break;
184         case SBE_2T3E3_SCRAMBLER_ADC_KENTROX_DIGITAL:
185                 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
186                              SBE_2T3E3_CPLD_VAL_SCRAMBLER_TYPE);
187                 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
188                              SBE_2T3E3_CPLD_VAL_SCRAMBLER_ENABLE);
189                 break;
190         default:
191                 return;
192         }
193
194         sc->p.scrambler = mode;
195 }
196
197
198 void cpld_set_crc(struct channel *sc, u32 crc)
199 {
200         if (sc->p.crc == crc)
201                 return;
202
203         switch (crc) {
204         case SBE_2T3E3_CRC_16:
205                 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
206                                SBE_2T3E3_CPLD_VAL_CRC32);
207                 break;
208         case SBE_2T3E3_CRC_32:
209                 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
210                              SBE_2T3E3_CPLD_VAL_CRC32);
211                 break;
212         default:
213                 return;
214         }
215
216         sc->p.crc = crc;
217 }
218
219
220 void cpld_select_panel(struct channel *sc, u32 panel)
221 {
222         if (sc->p.panel == panel)
223                 return;
224         switch (panel) {
225         case SBE_2T3E3_PANEL_FRONT:
226                 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
227                                SBE_2T3E3_CPLD_VAL_REAR_PANEL);
228                 break;
229         case SBE_2T3E3_PANEL_REAR:
230                 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
231                              SBE_2T3E3_CPLD_VAL_REAR_PANEL);
232                 break;
233         default:
234                 return;
235         }
236
237         udelay(100);
238
239         sc->p.panel = panel;
240 }
241
242
243 extern void cpld_set_clock(struct channel *sc, u32 mode)
244 {
245         if (sc->p.clock_source == mode)
246                 return;
247
248         switch (mode) {
249         case SBE_2T3E3_TIMING_LOCAL:
250                 cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
251                              SBE_2T3E3_CPLD_VAL_ALT);
252                 break;
253         case SBE_2T3E3_TIMING_LOOP:
254                 cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRA,
255                                SBE_2T3E3_CPLD_VAL_ALT);
256                 break;
257         default:
258                 return;
259         }
260
261         sc->p.clock_source = mode;
262 }
263
264 void cpld_set_pad_count(struct channel *sc, u32 count)
265 {
266         u32 val;
267
268         if (sc->p.pad_count == count)
269                 return;
270
271         switch (count) {
272         case SBE_2T3E3_PAD_COUNT_1:
273                 val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_1;
274                 break;
275         case SBE_2T3E3_PAD_COUNT_2:
276                 val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_2;
277                 break;
278         case SBE_2T3E3_PAD_COUNT_3:
279                 val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_3;
280                 break;
281         case SBE_2T3E3_PAD_COUNT_4:
282                 val = SBE_2T3E3_CPLD_VAL_PAD_COUNT_4;
283                 break;
284         default:
285                 return;
286         }
287
288         cpld_clear_bit(sc, SBE_2T3E3_CPLD_REG_PCRB,
289                        SBE_2T3E3_CPLD_VAL_PAD_COUNT);
290         cpld_set_bit(sc, SBE_2T3E3_CPLD_REG_PCRB, val);
291         sc->p.pad_count = count;
292 }
293
294 void cpld_LOS_update(struct channel *sc)
295 {
296         u_int8_t los;
297
298         cpld_write(sc, SBE_2T3E3_CPLD_REG_PICSR,
299                    SBE_2T3E3_CPLD_VAL_DMO_SIGNAL_DETECTED |
300                    SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_LOCK_DETECTED |
301                    SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_DETECTED);
302         los = cpld_read(sc, SBE_2T3E3_CPLD_REG_PICSR) &
303                 SBE_2T3E3_CPLD_VAL_RECEIVE_LOSS_OF_SIGNAL_DETECTED;
304
305         if (los != sc->s.LOS)
306                 dev_info(&sc->pdev->dev, "SBE 2T3E3: LOS status: %s\n",
307                          los ? "Loss of signal" : "Signal OK");
308         sc->s.LOS = los;
309 }
310
311 void cpld_set_fractional_mode(struct channel *sc, u32 mode,
312                               u32 start, u32 stop)
313 {
314         if (mode == SBE_2T3E3_FRACTIONAL_MODE_NONE) {
315                 start = 0;
316                 stop = 0;
317         }
318
319         if (sc->p.fractional_mode == mode && sc->p.bandwidth_start == start &&
320             sc->p.bandwidth_stop == stop)
321                 return;
322
323         switch (mode) {
324         case SBE_2T3E3_FRACTIONAL_MODE_NONE:
325                 cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
326                            SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_NONE);
327                 break;
328         case SBE_2T3E3_FRACTIONAL_MODE_0:
329                 cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
330                            SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_0);
331                 break;
332         case SBE_2T3E3_FRACTIONAL_MODE_1:
333                 cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
334                            SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_1);
335                 break;
336         case SBE_2T3E3_FRACTIONAL_MODE_2:
337                 cpld_write(sc, SBE_2T3E3_CPLD_REG_PCRC,
338                            SBE_2T3E3_CPLD_VAL_FRACTIONAL_MODE_2);
339                 break;
340         default:
341                 netdev_err(sc->dev, "wrong mode in set_fractional_mode\n");
342                 return;
343         }
344
345         cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWF, start);
346         cpld_write(sc, SBE_2T3E3_CPLD_REG_PBWL, stop);
347
348         sc->p.fractional_mode = mode;
349         sc->p.bandwidth_start = start;
350         sc->p.bandwidth_stop = stop;
351 }