linux/drivers/staging/sbe-2t3e3/cpld.c
<<
>>
Prefs
   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
  25static 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
  33static 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
  41void 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
  96void 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
 106void 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
 115void 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 */
 150void 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
 168void 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
 198void 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
 220void 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
 243extern 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
 264void 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
 294void 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
 311void 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}
 352