cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

slic_ds26522.c (6206B)


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