linux/drivers/net/wan/slic_ds26522.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * drivers/net/wan/slic_ds26522.c
   4 *
   5 * Copyright (C) 2016 Freescale Semiconductor, Inc.
   6 *
   7 * Author:Zhao Qiang<qiang.zhao@nxp.com>
   8 */
   9
  10#include <linux/bitrev.h>
  11#include <linux/module.h>
  12#include <linux/device.h>
  13#include <linux/kernel.h>
  14#include <linux/sched.h>
  15#include <linux/kthread.h>
  16#include <linux/spi/spi.h>
  17#include <linux/wait.h>
  18#include <linux/param.h>
  19#include <linux/delay.h>
  20#include <linux/of.h>
  21#include <linux/of_address.h>
  22#include <linux/io.h>
  23#include "slic_ds26522.h"
  24
  25#define DRV_NAME "ds26522"
  26
  27#define SLIC_TRANS_LEN 1
  28#define SLIC_TWO_LEN 2
  29#define SLIC_THREE_LEN 3
  30
  31static struct spi_device *g_spi;
  32
  33MODULE_LICENSE("GPL");
  34MODULE_AUTHOR("Zhao Qiang<B45475@freescale.com>");
  35
  36/* the read/write format of address is
  37 * w/r|A13|A12|A11|A10|A9|A8|A7|A6|A5|A4|A3|A2|A1|A0|x
  38 */
  39static void slic_write(struct spi_device *spi, u16 addr,
  40                       u8 data)
  41{
  42        u8 temp[3];
  43
  44        addr = bitrev16(addr) >> 1;
  45        data = bitrev8(data);
  46        temp[0] = (u8)((addr >> 8) & 0x7f);
  47        temp[1] = (u8)(addr & 0xfe);
  48        temp[2] = data;
  49
  50        /* write spi addr and value */
  51        spi_write(spi, &temp[0], SLIC_THREE_LEN);
  52}
  53
  54static u8 slic_read(struct spi_device *spi, u16 addr)
  55{
  56        u8 temp[2];
  57        u8 data;
  58
  59        addr = bitrev16(addr) >> 1;
  60        temp[0] = (u8)(((addr >> 8) & 0x7f) | 0x80);
  61        temp[1] = (u8)(addr & 0xfe);
  62
  63        spi_write_then_read(spi, &temp[0], SLIC_TWO_LEN, &data,
  64                            SLIC_TRANS_LEN);
  65
  66        data = bitrev8(data);
  67        return data;
  68}
  69
  70static bool get_slic_product_code(struct spi_device *spi)
  71{
  72        u8 device_id;
  73
  74        device_id = slic_read(spi, DS26522_IDR_ADDR);
  75        if ((device_id & 0xf8) == 0x68)
  76                return true;
  77        else
  78                return false;
  79}
  80
  81static void ds26522_e1_spec_config(struct spi_device *spi)
  82{
  83        /* Receive E1 Mode, Framer Disabled */
  84        slic_write(spi, DS26522_RMMR_ADDR, DS26522_RMMR_E1);
  85
  86        /* Transmit E1 Mode, Framer Disable */
  87        slic_write(spi, DS26522_TMMR_ADDR, DS26522_TMMR_E1);
  88
  89        /* Receive E1 Mode Framer Enable */
  90        slic_write(spi, DS26522_RMMR_ADDR,
  91                   slic_read(spi, DS26522_RMMR_ADDR) | DS26522_RMMR_FRM_EN);
  92
  93        /* Transmit E1 Mode Framer Enable */
  94        slic_write(spi, DS26522_TMMR_ADDR,
  95                   slic_read(spi, DS26522_TMMR_ADDR) | DS26522_TMMR_FRM_EN);
  96
  97        /* RCR1, receive E1 B8zs & ESF */
  98        slic_write(spi, DS26522_RCR1_ADDR,
  99                   DS26522_RCR1_E1_HDB3 | DS26522_RCR1_E1_CCS);
 100
 101        /* RSYSCLK=2.048MHz, RSYNC-Output */
 102        slic_write(spi, DS26522_RIOCR_ADDR,
 103                   DS26522_RIOCR_2048KHZ | DS26522_RIOCR_RSIO_OUT);
 104
 105        /* TCR1 Transmit E1 b8zs */
 106        slic_write(spi, DS26522_TCR1_ADDR, DS26522_TCR1_TB8ZS);
 107
 108        /* TSYSCLK=2.048MHz, TSYNC-Output */
 109        slic_write(spi, DS26522_TIOCR_ADDR,
 110                   DS26522_TIOCR_2048KHZ | DS26522_TIOCR_TSIO_OUT);
 111
 112        /* Set E1TAF */
 113        slic_write(spi, DS26522_E1TAF_ADDR, DS26522_E1TAF_DEFAULT);
 114
 115        /* Set E1TNAF register */
 116        slic_write(spi, DS26522_E1TNAF_ADDR, DS26522_E1TNAF_DEFAULT);
 117
 118        /* Receive E1 Mode Framer Enable & init Done */
 119        slic_write(spi, DS26522_RMMR_ADDR, slic_read(spi, DS26522_RMMR_ADDR) |
 120                   DS26522_RMMR_INIT_DONE);
 121
 122        /* Transmit E1 Mode Framer Enable & init Done */
 123        slic_write(spi, DS26522_TMMR_ADDR, slic_read(spi, DS26522_TMMR_ADDR) |
 124                   DS26522_TMMR_INIT_DONE);
 125
 126        /* Configure LIU E1 mode */
 127        slic_write(spi, DS26522_LTRCR_ADDR, DS26522_LTRCR_E1);
 128
 129        /* E1 Mode default 75 ohm w/Transmit Impedance Matlinking */
 130        slic_write(spi, DS26522_LTITSR_ADDR,
 131                   DS26522_LTITSR_TLIS_75OHM | DS26522_LTITSR_LBOS_75OHM);
 132
 133        /* E1 Mode default 75 ohm Long Haul w/Receive Impedance Matlinking */
 134        slic_write(spi, DS26522_LRISMR_ADDR,
 135                   DS26522_LRISMR_75OHM | DS26522_LRISMR_MAX);
 136
 137        /* Enable Transmit output */
 138        slic_write(spi, DS26522_LMCR_ADDR, DS26522_LMCR_TE);
 139}
 140
 141static int slic_ds26522_init_configure(struct spi_device *spi)
 142{
 143        u16 addr;
 144
 145        /* set clock */
 146        slic_write(spi, DS26522_GTCCR_ADDR, DS26522_GTCCR_BPREFSEL_REFCLKIN |
 147                        DS26522_GTCCR_BFREQSEL_2048KHZ |
 148                        DS26522_GTCCR_FREQSEL_2048KHZ);
 149        slic_write(spi, DS26522_GTCR2_ADDR, DS26522_GTCR2_TSSYNCOUT);
 150        slic_write(spi, DS26522_GFCR_ADDR, DS26522_GFCR_BPCLK_2048KHZ);
 151
 152        /* set gtcr */
 153        slic_write(spi, DS26522_GTCR1_ADDR, DS26522_GTCR1);
 154
 155        /* Global LIU Software Reset Register */
 156        slic_write(spi, DS26522_GLSRR_ADDR, DS26522_GLSRR_RESET);
 157
 158        /* Global Framer and BERT Software Reset Register */
 159        slic_write(spi, DS26522_GFSRR_ADDR, DS26522_GFSRR_RESET);
 160
 161        usleep_range(100, 120);
 162
 163        slic_write(spi, DS26522_GLSRR_ADDR, DS26522_GLSRR_NORMAL);
 164        slic_write(spi, DS26522_GFSRR_ADDR, DS26522_GFSRR_NORMAL);
 165
 166        /* Perform RX/TX SRESET,Reset receiver */
 167        slic_write(spi, DS26522_RMMR_ADDR, DS26522_RMMR_SFTRST);
 168
 169        /* Reset tranceiver */
 170        slic_write(spi, DS26522_TMMR_ADDR, DS26522_TMMR_SFTRST);
 171
 172        usleep_range(100, 120);
 173
 174        /* Zero all Framer Registers */
 175        for (addr = DS26522_RF_ADDR_START; addr <= DS26522_RF_ADDR_END;
 176             addr++)
 177                slic_write(spi, addr, 0);
 178
 179        for (addr = DS26522_TF_ADDR_START; addr <= DS26522_TF_ADDR_END;
 180             addr++)
 181                slic_write(spi, addr, 0);
 182
 183        for (addr = DS26522_LIU_ADDR_START; addr <= DS26522_LIU_ADDR_END;
 184             addr++)
 185                slic_write(spi, addr, 0);
 186
 187        for (addr = DS26522_BERT_ADDR_START; addr <= DS26522_BERT_ADDR_END;
 188             addr++)
 189                slic_write(spi, addr, 0);
 190
 191        /* setup ds26522 for E1 specification */
 192        ds26522_e1_spec_config(spi);
 193
 194        slic_write(spi, DS26522_GTCR1_ADDR, 0x00);
 195
 196        return 0;
 197}
 198
 199static int slic_ds26522_remove(struct spi_device *spi)
 200{
 201        pr_info("DS26522 module uninstalled\n");
 202        return 0;
 203}
 204
 205static int slic_ds26522_probe(struct spi_device *spi)
 206{
 207        int ret = 0;
 208
 209        g_spi = spi;
 210        spi->bits_per_word = 8;
 211
 212        if (!get_slic_product_code(spi))
 213                return ret;
 214
 215        ret = slic_ds26522_init_configure(spi);
 216        if (ret == 0)
 217                pr_info("DS26522 cs%d configured\n", spi->chip_select);
 218
 219        return ret;
 220}
 221
 222static const struct spi_device_id slic_ds26522_id[] = {
 223        { .name = "ds26522" },
 224        { /* sentinel */ },
 225};
 226MODULE_DEVICE_TABLE(spi, slic_ds26522_id);
 227
 228static const struct of_device_id slic_ds26522_match[] = {
 229        {
 230         .compatible = "maxim,ds26522",
 231         },
 232        {},
 233};
 234MODULE_DEVICE_TABLE(of, slic_ds26522_match);
 235
 236static struct spi_driver slic_ds26522_driver = {
 237        .driver = {
 238                   .name = "ds26522",
 239                   .bus = &spi_bus_type,
 240                   .of_match_table = slic_ds26522_match,
 241                   },
 242        .probe = slic_ds26522_probe,
 243        .remove = slic_ds26522_remove,
 244        .id_table = slic_ds26522_id,
 245};
 246
 247module_spi_driver(slic_ds26522_driver);
 248