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

xilinx_sdfec.c (38907B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Xilinx SDFEC
      4 *
      5 * Copyright (C) 2019 Xilinx, Inc.
      6 *
      7 * Description:
      8 * This driver is developed for SDFEC16 (Soft Decision FEC 16nm)
      9 * IP. It exposes a char device which supports file operations
     10 * like  open(), close() and ioctl().
     11 */
     12
     13#include <linux/miscdevice.h>
     14#include <linux/io.h>
     15#include <linux/interrupt.h>
     16#include <linux/kernel.h>
     17#include <linux/module.h>
     18#include <linux/of_platform.h>
     19#include <linux/poll.h>
     20#include <linux/slab.h>
     21#include <linux/clk.h>
     22#include <linux/compat.h>
     23#include <linux/highmem.h>
     24
     25#include <uapi/misc/xilinx_sdfec.h>
     26
     27#define DEV_NAME_LEN 12
     28
     29static DEFINE_IDA(dev_nrs);
     30
     31/* Xilinx SDFEC Register Map */
     32/* CODE_WRI_PROTECT Register */
     33#define XSDFEC_CODE_WR_PROTECT_ADDR (0x4)
     34
     35/* ACTIVE Register */
     36#define XSDFEC_ACTIVE_ADDR (0x8)
     37#define XSDFEC_IS_ACTIVITY_SET (0x1)
     38
     39/* AXIS_WIDTH Register */
     40#define XSDFEC_AXIS_WIDTH_ADDR (0xC)
     41#define XSDFEC_AXIS_DOUT_WORDS_LSB (5)
     42#define XSDFEC_AXIS_DOUT_WIDTH_LSB (3)
     43#define XSDFEC_AXIS_DIN_WORDS_LSB (2)
     44#define XSDFEC_AXIS_DIN_WIDTH_LSB (0)
     45
     46/* AXIS_ENABLE Register */
     47#define XSDFEC_AXIS_ENABLE_ADDR (0x10)
     48#define XSDFEC_AXIS_OUT_ENABLE_MASK (0x38)
     49#define XSDFEC_AXIS_IN_ENABLE_MASK (0x7)
     50#define XSDFEC_AXIS_ENABLE_MASK                                                \
     51	(XSDFEC_AXIS_OUT_ENABLE_MASK | XSDFEC_AXIS_IN_ENABLE_MASK)
     52
     53/* FEC_CODE Register */
     54#define XSDFEC_FEC_CODE_ADDR (0x14)
     55
     56/* ORDER Register Map */
     57#define XSDFEC_ORDER_ADDR (0x18)
     58
     59/* Interrupt Status Register */
     60#define XSDFEC_ISR_ADDR (0x1C)
     61/* Interrupt Status Register Bit Mask */
     62#define XSDFEC_ISR_MASK (0x3F)
     63
     64/* Write Only - Interrupt Enable Register */
     65#define XSDFEC_IER_ADDR (0x20)
     66/* Write Only - Interrupt Disable Register */
     67#define XSDFEC_IDR_ADDR (0x24)
     68/* Read Only - Interrupt Mask Register */
     69#define XSDFEC_IMR_ADDR (0x28)
     70
     71/* ECC Interrupt Status Register */
     72#define XSDFEC_ECC_ISR_ADDR (0x2C)
     73/* Single Bit Errors */
     74#define XSDFEC_ECC_ISR_SBE_MASK (0x7FF)
     75/* PL Initialize Single Bit Errors */
     76#define XSDFEC_PL_INIT_ECC_ISR_SBE_MASK (0x3C00000)
     77/* Multi Bit Errors */
     78#define XSDFEC_ECC_ISR_MBE_MASK (0x3FF800)
     79/* PL Initialize Multi Bit Errors */
     80#define XSDFEC_PL_INIT_ECC_ISR_MBE_MASK (0x3C000000)
     81/* Multi Bit Error to Event Shift */
     82#define XSDFEC_ECC_ISR_MBE_TO_EVENT_SHIFT (11)
     83/* PL Initialize Multi Bit Error to Event Shift */
     84#define XSDFEC_PL_INIT_ECC_ISR_MBE_TO_EVENT_SHIFT (4)
     85/* ECC Interrupt Status Bit Mask */
     86#define XSDFEC_ECC_ISR_MASK (XSDFEC_ECC_ISR_SBE_MASK | XSDFEC_ECC_ISR_MBE_MASK)
     87/* ECC Interrupt Status PL Initialize Bit Mask */
     88#define XSDFEC_PL_INIT_ECC_ISR_MASK                                            \
     89	(XSDFEC_PL_INIT_ECC_ISR_SBE_MASK | XSDFEC_PL_INIT_ECC_ISR_MBE_MASK)
     90/* ECC Interrupt Status All Bit Mask */
     91#define XSDFEC_ALL_ECC_ISR_MASK                                                \
     92	(XSDFEC_ECC_ISR_MASK | XSDFEC_PL_INIT_ECC_ISR_MASK)
     93/* ECC Interrupt Status Single Bit Errors Mask */
     94#define XSDFEC_ALL_ECC_ISR_SBE_MASK                                            \
     95	(XSDFEC_ECC_ISR_SBE_MASK | XSDFEC_PL_INIT_ECC_ISR_SBE_MASK)
     96/* ECC Interrupt Status Multi Bit Errors Mask */
     97#define XSDFEC_ALL_ECC_ISR_MBE_MASK                                            \
     98	(XSDFEC_ECC_ISR_MBE_MASK | XSDFEC_PL_INIT_ECC_ISR_MBE_MASK)
     99
    100/* Write Only - ECC Interrupt Enable Register */
    101#define XSDFEC_ECC_IER_ADDR (0x30)
    102/* Write Only - ECC Interrupt Disable Register */
    103#define XSDFEC_ECC_IDR_ADDR (0x34)
    104/* Read Only - ECC Interrupt Mask Register */
    105#define XSDFEC_ECC_IMR_ADDR (0x38)
    106
    107/* BYPASS Register */
    108#define XSDFEC_BYPASS_ADDR (0x3C)
    109
    110/* Turbo Code Register */
    111#define XSDFEC_TURBO_ADDR (0x100)
    112#define XSDFEC_TURBO_SCALE_MASK (0xFFF)
    113#define XSDFEC_TURBO_SCALE_BIT_POS (8)
    114#define XSDFEC_TURBO_SCALE_MAX (15)
    115
    116/* REG0 Register */
    117#define XSDFEC_LDPC_CODE_REG0_ADDR_BASE (0x2000)
    118#define XSDFEC_LDPC_CODE_REG0_ADDR_HIGH (0x27F0)
    119#define XSDFEC_REG0_N_MIN (4)
    120#define XSDFEC_REG0_N_MAX (32768)
    121#define XSDFEC_REG0_N_MUL_P (256)
    122#define XSDFEC_REG0_N_LSB (0)
    123#define XSDFEC_REG0_K_MIN (2)
    124#define XSDFEC_REG0_K_MAX (32766)
    125#define XSDFEC_REG0_K_MUL_P (256)
    126#define XSDFEC_REG0_K_LSB (16)
    127
    128/* REG1 Register */
    129#define XSDFEC_LDPC_CODE_REG1_ADDR_BASE (0x2004)
    130#define XSDFEC_LDPC_CODE_REG1_ADDR_HIGH (0x27f4)
    131#define XSDFEC_REG1_PSIZE_MIN (2)
    132#define XSDFEC_REG1_PSIZE_MAX (512)
    133#define XSDFEC_REG1_NO_PACKING_MASK (0x400)
    134#define XSDFEC_REG1_NO_PACKING_LSB (10)
    135#define XSDFEC_REG1_NM_MASK (0xFF800)
    136#define XSDFEC_REG1_NM_LSB (11)
    137#define XSDFEC_REG1_BYPASS_MASK (0x100000)
    138
    139/* REG2 Register */
    140#define XSDFEC_LDPC_CODE_REG2_ADDR_BASE (0x2008)
    141#define XSDFEC_LDPC_CODE_REG2_ADDR_HIGH (0x27f8)
    142#define XSDFEC_REG2_NLAYERS_MIN (1)
    143#define XSDFEC_REG2_NLAYERS_MAX (256)
    144#define XSDFEC_REG2_NNMQC_MASK (0xFFE00)
    145#define XSDFEC_REG2_NMQC_LSB (9)
    146#define XSDFEC_REG2_NORM_TYPE_MASK (0x100000)
    147#define XSDFEC_REG2_NORM_TYPE_LSB (20)
    148#define XSDFEC_REG2_SPECIAL_QC_MASK (0x200000)
    149#define XSDFEC_REG2_SPEICAL_QC_LSB (21)
    150#define XSDFEC_REG2_NO_FINAL_PARITY_MASK (0x400000)
    151#define XSDFEC_REG2_NO_FINAL_PARITY_LSB (22)
    152#define XSDFEC_REG2_MAX_SCHEDULE_MASK (0x1800000)
    153#define XSDFEC_REG2_MAX_SCHEDULE_LSB (23)
    154
    155/* REG3 Register */
    156#define XSDFEC_LDPC_CODE_REG3_ADDR_BASE (0x200C)
    157#define XSDFEC_LDPC_CODE_REG3_ADDR_HIGH (0x27FC)
    158#define XSDFEC_REG3_LA_OFF_LSB (8)
    159#define XSDFEC_REG3_QC_OFF_LSB (16)
    160
    161#define XSDFEC_LDPC_REG_JUMP (0x10)
    162#define XSDFEC_REG_WIDTH_JUMP (4)
    163
    164/* The maximum number of pinned pages */
    165#define MAX_NUM_PAGES ((XSDFEC_QC_TABLE_DEPTH / PAGE_SIZE) + 1)
    166
    167/**
    168 * struct xsdfec_clks - For managing SD-FEC clocks
    169 * @core_clk: Main processing clock for core
    170 * @axi_clk: AXI4-Lite memory-mapped clock
    171 * @din_words_clk: DIN Words AXI4-Stream Slave clock
    172 * @din_clk: DIN AXI4-Stream Slave clock
    173 * @dout_clk: DOUT Words AXI4-Stream Slave clock
    174 * @dout_words_clk: DOUT AXI4-Stream Slave clock
    175 * @ctrl_clk: Control AXI4-Stream Slave clock
    176 * @status_clk: Status AXI4-Stream Slave clock
    177 */
    178struct xsdfec_clks {
    179	struct clk *core_clk;
    180	struct clk *axi_clk;
    181	struct clk *din_words_clk;
    182	struct clk *din_clk;
    183	struct clk *dout_clk;
    184	struct clk *dout_words_clk;
    185	struct clk *ctrl_clk;
    186	struct clk *status_clk;
    187};
    188
    189/**
    190 * struct xsdfec_dev - Driver data for SDFEC
    191 * @miscdev: Misc device handle
    192 * @clks: Clocks managed by the SDFEC driver
    193 * @waitq: Driver wait queue
    194 * @config: Configuration of the SDFEC device
    195 * @dev_name: Device name
    196 * @flags: spinlock flags
    197 * @regs: device physical base address
    198 * @dev: pointer to device struct
    199 * @state: State of the SDFEC device
    200 * @error_data_lock: Error counter and states spinlock
    201 * @dev_id: Device ID
    202 * @isr_err_count: Count of ISR errors
    203 * @cecc_count: Count of Correctable ECC errors (SBE)
    204 * @uecc_count: Count of Uncorrectable ECC errors (MBE)
    205 * @irq: IRQ number
    206 * @state_updated: indicates State updated by interrupt handler
    207 * @stats_updated: indicates Stats updated by interrupt handler
    208 * @intr_enabled: indicates IRQ enabled
    209 *
    210 * This structure contains necessary state for SDFEC driver to operate
    211 */
    212struct xsdfec_dev {
    213	struct miscdevice miscdev;
    214	struct xsdfec_clks clks;
    215	wait_queue_head_t waitq;
    216	struct xsdfec_config config;
    217	char dev_name[DEV_NAME_LEN];
    218	unsigned long flags;
    219	void __iomem *regs;
    220	struct device *dev;
    221	enum xsdfec_state state;
    222	/* Spinlock to protect state_updated and stats_updated */
    223	spinlock_t error_data_lock;
    224	int dev_id;
    225	u32 isr_err_count;
    226	u32 cecc_count;
    227	u32 uecc_count;
    228	int irq;
    229	bool state_updated;
    230	bool stats_updated;
    231	bool intr_enabled;
    232};
    233
    234static inline void xsdfec_regwrite(struct xsdfec_dev *xsdfec, u32 addr,
    235				   u32 value)
    236{
    237	dev_dbg(xsdfec->dev, "Writing 0x%x to offset 0x%x", value, addr);
    238	iowrite32(value, xsdfec->regs + addr);
    239}
    240
    241static inline u32 xsdfec_regread(struct xsdfec_dev *xsdfec, u32 addr)
    242{
    243	u32 rval;
    244
    245	rval = ioread32(xsdfec->regs + addr);
    246	dev_dbg(xsdfec->dev, "Read value = 0x%x from offset 0x%x", rval, addr);
    247	return rval;
    248}
    249
    250static void update_bool_config_from_reg(struct xsdfec_dev *xsdfec,
    251					u32 reg_offset, u32 bit_num,
    252					char *config_value)
    253{
    254	u32 reg_val;
    255	u32 bit_mask = 1 << bit_num;
    256
    257	reg_val = xsdfec_regread(xsdfec, reg_offset);
    258	*config_value = (reg_val & bit_mask) > 0;
    259}
    260
    261static void update_config_from_hw(struct xsdfec_dev *xsdfec)
    262{
    263	u32 reg_value;
    264	bool sdfec_started;
    265
    266	/* Update the Order */
    267	reg_value = xsdfec_regread(xsdfec, XSDFEC_ORDER_ADDR);
    268	xsdfec->config.order = reg_value;
    269
    270	update_bool_config_from_reg(xsdfec, XSDFEC_BYPASS_ADDR,
    271				    0, /* Bit Number, maybe change to mask */
    272				    &xsdfec->config.bypass);
    273
    274	update_bool_config_from_reg(xsdfec, XSDFEC_CODE_WR_PROTECT_ADDR,
    275				    0, /* Bit Number */
    276				    &xsdfec->config.code_wr_protect);
    277
    278	reg_value = xsdfec_regread(xsdfec, XSDFEC_IMR_ADDR);
    279	xsdfec->config.irq.enable_isr = (reg_value & XSDFEC_ISR_MASK) > 0;
    280
    281	reg_value = xsdfec_regread(xsdfec, XSDFEC_ECC_IMR_ADDR);
    282	xsdfec->config.irq.enable_ecc_isr =
    283		(reg_value & XSDFEC_ECC_ISR_MASK) > 0;
    284
    285	reg_value = xsdfec_regread(xsdfec, XSDFEC_AXIS_ENABLE_ADDR);
    286	sdfec_started = (reg_value & XSDFEC_AXIS_IN_ENABLE_MASK) > 0;
    287	if (sdfec_started)
    288		xsdfec->state = XSDFEC_STARTED;
    289	else
    290		xsdfec->state = XSDFEC_STOPPED;
    291}
    292
    293static int xsdfec_get_status(struct xsdfec_dev *xsdfec, void __user *arg)
    294{
    295	struct xsdfec_status status;
    296	int err;
    297
    298	memset(&status, 0, sizeof(status));
    299	spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags);
    300	status.state = xsdfec->state;
    301	xsdfec->state_updated = false;
    302	spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags);
    303	status.activity = (xsdfec_regread(xsdfec, XSDFEC_ACTIVE_ADDR) &
    304			   XSDFEC_IS_ACTIVITY_SET);
    305
    306	err = copy_to_user(arg, &status, sizeof(status));
    307	if (err)
    308		err = -EFAULT;
    309
    310	return err;
    311}
    312
    313static int xsdfec_get_config(struct xsdfec_dev *xsdfec, void __user *arg)
    314{
    315	int err;
    316
    317	err = copy_to_user(arg, &xsdfec->config, sizeof(xsdfec->config));
    318	if (err)
    319		err = -EFAULT;
    320
    321	return err;
    322}
    323
    324static int xsdfec_isr_enable(struct xsdfec_dev *xsdfec, bool enable)
    325{
    326	u32 mask_read;
    327
    328	if (enable) {
    329		/* Enable */
    330		xsdfec_regwrite(xsdfec, XSDFEC_IER_ADDR, XSDFEC_ISR_MASK);
    331		mask_read = xsdfec_regread(xsdfec, XSDFEC_IMR_ADDR);
    332		if (mask_read & XSDFEC_ISR_MASK) {
    333			dev_dbg(xsdfec->dev,
    334				"SDFEC enabling irq with IER failed");
    335			return -EIO;
    336		}
    337	} else {
    338		/* Disable */
    339		xsdfec_regwrite(xsdfec, XSDFEC_IDR_ADDR, XSDFEC_ISR_MASK);
    340		mask_read = xsdfec_regread(xsdfec, XSDFEC_IMR_ADDR);
    341		if ((mask_read & XSDFEC_ISR_MASK) != XSDFEC_ISR_MASK) {
    342			dev_dbg(xsdfec->dev,
    343				"SDFEC disabling irq with IDR failed");
    344			return -EIO;
    345		}
    346	}
    347	return 0;
    348}
    349
    350static int xsdfec_ecc_isr_enable(struct xsdfec_dev *xsdfec, bool enable)
    351{
    352	u32 mask_read;
    353
    354	if (enable) {
    355		/* Enable */
    356		xsdfec_regwrite(xsdfec, XSDFEC_ECC_IER_ADDR,
    357				XSDFEC_ALL_ECC_ISR_MASK);
    358		mask_read = xsdfec_regread(xsdfec, XSDFEC_ECC_IMR_ADDR);
    359		if (mask_read & XSDFEC_ALL_ECC_ISR_MASK) {
    360			dev_dbg(xsdfec->dev,
    361				"SDFEC enabling ECC irq with ECC IER failed");
    362			return -EIO;
    363		}
    364	} else {
    365		/* Disable */
    366		xsdfec_regwrite(xsdfec, XSDFEC_ECC_IDR_ADDR,
    367				XSDFEC_ALL_ECC_ISR_MASK);
    368		mask_read = xsdfec_regread(xsdfec, XSDFEC_ECC_IMR_ADDR);
    369		if (!(((mask_read & XSDFEC_ALL_ECC_ISR_MASK) ==
    370		       XSDFEC_ECC_ISR_MASK) ||
    371		      ((mask_read & XSDFEC_ALL_ECC_ISR_MASK) ==
    372		       XSDFEC_PL_INIT_ECC_ISR_MASK))) {
    373			dev_dbg(xsdfec->dev,
    374				"SDFEC disable ECC irq with ECC IDR failed");
    375			return -EIO;
    376		}
    377	}
    378	return 0;
    379}
    380
    381static int xsdfec_set_irq(struct xsdfec_dev *xsdfec, void __user *arg)
    382{
    383	struct xsdfec_irq irq;
    384	int err;
    385	int isr_err;
    386	int ecc_err;
    387
    388	err = copy_from_user(&irq, arg, sizeof(irq));
    389	if (err)
    390		return -EFAULT;
    391
    392	/* Setup tlast related IRQ */
    393	isr_err = xsdfec_isr_enable(xsdfec, irq.enable_isr);
    394	if (!isr_err)
    395		xsdfec->config.irq.enable_isr = irq.enable_isr;
    396
    397	/* Setup ECC related IRQ */
    398	ecc_err = xsdfec_ecc_isr_enable(xsdfec, irq.enable_ecc_isr);
    399	if (!ecc_err)
    400		xsdfec->config.irq.enable_ecc_isr = irq.enable_ecc_isr;
    401
    402	if (isr_err < 0 || ecc_err < 0)
    403		err = -EIO;
    404
    405	return err;
    406}
    407
    408static int xsdfec_set_turbo(struct xsdfec_dev *xsdfec, void __user *arg)
    409{
    410	struct xsdfec_turbo turbo;
    411	int err;
    412	u32 turbo_write;
    413
    414	err = copy_from_user(&turbo, arg, sizeof(turbo));
    415	if (err)
    416		return -EFAULT;
    417
    418	if (turbo.alg >= XSDFEC_TURBO_ALG_MAX)
    419		return -EINVAL;
    420
    421	if (turbo.scale > XSDFEC_TURBO_SCALE_MAX)
    422		return -EINVAL;
    423
    424	/* Check to see what device tree says about the FEC codes */
    425	if (xsdfec->config.code == XSDFEC_LDPC_CODE)
    426		return -EIO;
    427
    428	turbo_write = ((turbo.scale & XSDFEC_TURBO_SCALE_MASK)
    429		       << XSDFEC_TURBO_SCALE_BIT_POS) |
    430		      turbo.alg;
    431	xsdfec_regwrite(xsdfec, XSDFEC_TURBO_ADDR, turbo_write);
    432	return err;
    433}
    434
    435static int xsdfec_get_turbo(struct xsdfec_dev *xsdfec, void __user *arg)
    436{
    437	u32 reg_value;
    438	struct xsdfec_turbo turbo_params;
    439	int err;
    440
    441	if (xsdfec->config.code == XSDFEC_LDPC_CODE)
    442		return -EIO;
    443
    444	memset(&turbo_params, 0, sizeof(turbo_params));
    445	reg_value = xsdfec_regread(xsdfec, XSDFEC_TURBO_ADDR);
    446
    447	turbo_params.scale = (reg_value & XSDFEC_TURBO_SCALE_MASK) >>
    448			     XSDFEC_TURBO_SCALE_BIT_POS;
    449	turbo_params.alg = reg_value & 0x1;
    450
    451	err = copy_to_user(arg, &turbo_params, sizeof(turbo_params));
    452	if (err)
    453		err = -EFAULT;
    454
    455	return err;
    456}
    457
    458static int xsdfec_reg0_write(struct xsdfec_dev *xsdfec, u32 n, u32 k, u32 psize,
    459			     u32 offset)
    460{
    461	u32 wdata;
    462
    463	if (n < XSDFEC_REG0_N_MIN || n > XSDFEC_REG0_N_MAX || psize == 0 ||
    464	    (n > XSDFEC_REG0_N_MUL_P * psize) || n <= k || ((n % psize) != 0)) {
    465		dev_dbg(xsdfec->dev, "N value is not in range");
    466		return -EINVAL;
    467	}
    468	n <<= XSDFEC_REG0_N_LSB;
    469
    470	if (k < XSDFEC_REG0_K_MIN || k > XSDFEC_REG0_K_MAX ||
    471	    (k > XSDFEC_REG0_K_MUL_P * psize) || ((k % psize) != 0)) {
    472		dev_dbg(xsdfec->dev, "K value is not in range");
    473		return -EINVAL;
    474	}
    475	k = k << XSDFEC_REG0_K_LSB;
    476	wdata = k | n;
    477
    478	if (XSDFEC_LDPC_CODE_REG0_ADDR_BASE + (offset * XSDFEC_LDPC_REG_JUMP) >
    479	    XSDFEC_LDPC_CODE_REG0_ADDR_HIGH) {
    480		dev_dbg(xsdfec->dev, "Writing outside of LDPC reg0 space 0x%x",
    481			XSDFEC_LDPC_CODE_REG0_ADDR_BASE +
    482				(offset * XSDFEC_LDPC_REG_JUMP));
    483		return -EINVAL;
    484	}
    485	xsdfec_regwrite(xsdfec,
    486			XSDFEC_LDPC_CODE_REG0_ADDR_BASE +
    487				(offset * XSDFEC_LDPC_REG_JUMP),
    488			wdata);
    489	return 0;
    490}
    491
    492static int xsdfec_reg1_write(struct xsdfec_dev *xsdfec, u32 psize,
    493			     u32 no_packing, u32 nm, u32 offset)
    494{
    495	u32 wdata;
    496
    497	if (psize < XSDFEC_REG1_PSIZE_MIN || psize > XSDFEC_REG1_PSIZE_MAX) {
    498		dev_dbg(xsdfec->dev, "Psize is not in range");
    499		return -EINVAL;
    500	}
    501
    502	if (no_packing != 0 && no_packing != 1)
    503		dev_dbg(xsdfec->dev, "No-packing bit register invalid");
    504	no_packing = ((no_packing << XSDFEC_REG1_NO_PACKING_LSB) &
    505		      XSDFEC_REG1_NO_PACKING_MASK);
    506
    507	if (nm & ~(XSDFEC_REG1_NM_MASK >> XSDFEC_REG1_NM_LSB))
    508		dev_dbg(xsdfec->dev, "NM is beyond 10 bits");
    509	nm = (nm << XSDFEC_REG1_NM_LSB) & XSDFEC_REG1_NM_MASK;
    510
    511	wdata = nm | no_packing | psize;
    512	if (XSDFEC_LDPC_CODE_REG1_ADDR_BASE + (offset * XSDFEC_LDPC_REG_JUMP) >
    513	    XSDFEC_LDPC_CODE_REG1_ADDR_HIGH) {
    514		dev_dbg(xsdfec->dev, "Writing outside of LDPC reg1 space 0x%x",
    515			XSDFEC_LDPC_CODE_REG1_ADDR_BASE +
    516				(offset * XSDFEC_LDPC_REG_JUMP));
    517		return -EINVAL;
    518	}
    519	xsdfec_regwrite(xsdfec,
    520			XSDFEC_LDPC_CODE_REG1_ADDR_BASE +
    521				(offset * XSDFEC_LDPC_REG_JUMP),
    522			wdata);
    523	return 0;
    524}
    525
    526static int xsdfec_reg2_write(struct xsdfec_dev *xsdfec, u32 nlayers, u32 nmqc,
    527			     u32 norm_type, u32 special_qc, u32 no_final_parity,
    528			     u32 max_schedule, u32 offset)
    529{
    530	u32 wdata;
    531
    532	if (nlayers < XSDFEC_REG2_NLAYERS_MIN ||
    533	    nlayers > XSDFEC_REG2_NLAYERS_MAX) {
    534		dev_dbg(xsdfec->dev, "Nlayers is not in range");
    535		return -EINVAL;
    536	}
    537
    538	if (nmqc & ~(XSDFEC_REG2_NNMQC_MASK >> XSDFEC_REG2_NMQC_LSB))
    539		dev_dbg(xsdfec->dev, "NMQC exceeds 11 bits");
    540	nmqc = (nmqc << XSDFEC_REG2_NMQC_LSB) & XSDFEC_REG2_NNMQC_MASK;
    541
    542	if (norm_type > 1)
    543		dev_dbg(xsdfec->dev, "Norm type is invalid");
    544	norm_type = ((norm_type << XSDFEC_REG2_NORM_TYPE_LSB) &
    545		     XSDFEC_REG2_NORM_TYPE_MASK);
    546	if (special_qc > 1)
    547		dev_dbg(xsdfec->dev, "Special QC in invalid");
    548	special_qc = ((special_qc << XSDFEC_REG2_SPEICAL_QC_LSB) &
    549		      XSDFEC_REG2_SPECIAL_QC_MASK);
    550
    551	if (no_final_parity > 1)
    552		dev_dbg(xsdfec->dev, "No final parity check invalid");
    553	no_final_parity =
    554		((no_final_parity << XSDFEC_REG2_NO_FINAL_PARITY_LSB) &
    555		 XSDFEC_REG2_NO_FINAL_PARITY_MASK);
    556	if (max_schedule &
    557	    ~(XSDFEC_REG2_MAX_SCHEDULE_MASK >> XSDFEC_REG2_MAX_SCHEDULE_LSB))
    558		dev_dbg(xsdfec->dev, "Max Schedule exceeds 2 bits");
    559	max_schedule = ((max_schedule << XSDFEC_REG2_MAX_SCHEDULE_LSB) &
    560			XSDFEC_REG2_MAX_SCHEDULE_MASK);
    561
    562	wdata = (max_schedule | no_final_parity | special_qc | norm_type |
    563		 nmqc | nlayers);
    564
    565	if (XSDFEC_LDPC_CODE_REG2_ADDR_BASE + (offset * XSDFEC_LDPC_REG_JUMP) >
    566	    XSDFEC_LDPC_CODE_REG2_ADDR_HIGH) {
    567		dev_dbg(xsdfec->dev, "Writing outside of LDPC reg2 space 0x%x",
    568			XSDFEC_LDPC_CODE_REG2_ADDR_BASE +
    569				(offset * XSDFEC_LDPC_REG_JUMP));
    570		return -EINVAL;
    571	}
    572	xsdfec_regwrite(xsdfec,
    573			XSDFEC_LDPC_CODE_REG2_ADDR_BASE +
    574				(offset * XSDFEC_LDPC_REG_JUMP),
    575			wdata);
    576	return 0;
    577}
    578
    579static int xsdfec_reg3_write(struct xsdfec_dev *xsdfec, u8 sc_off, u8 la_off,
    580			     u16 qc_off, u32 offset)
    581{
    582	u32 wdata;
    583
    584	wdata = ((qc_off << XSDFEC_REG3_QC_OFF_LSB) |
    585		 (la_off << XSDFEC_REG3_LA_OFF_LSB) | sc_off);
    586	if (XSDFEC_LDPC_CODE_REG3_ADDR_BASE + (offset * XSDFEC_LDPC_REG_JUMP) >
    587	    XSDFEC_LDPC_CODE_REG3_ADDR_HIGH) {
    588		dev_dbg(xsdfec->dev, "Writing outside of LDPC reg3 space 0x%x",
    589			XSDFEC_LDPC_CODE_REG3_ADDR_BASE +
    590				(offset * XSDFEC_LDPC_REG_JUMP));
    591		return -EINVAL;
    592	}
    593	xsdfec_regwrite(xsdfec,
    594			XSDFEC_LDPC_CODE_REG3_ADDR_BASE +
    595				(offset * XSDFEC_LDPC_REG_JUMP),
    596			wdata);
    597	return 0;
    598}
    599
    600static int xsdfec_table_write(struct xsdfec_dev *xsdfec, u32 offset,
    601			      u32 *src_ptr, u32 len, const u32 base_addr,
    602			      const u32 depth)
    603{
    604	u32 reg = 0;
    605	int res, i, nr_pages;
    606	u32 n;
    607	u32 *addr = NULL;
    608	struct page *pages[MAX_NUM_PAGES];
    609
    610	/*
    611	 * Writes that go beyond the length of
    612	 * Shared Scale(SC) table should fail
    613	 */
    614	if (offset > depth / XSDFEC_REG_WIDTH_JUMP ||
    615	    len > depth / XSDFEC_REG_WIDTH_JUMP ||
    616	    offset + len > depth / XSDFEC_REG_WIDTH_JUMP) {
    617		dev_dbg(xsdfec->dev, "Write exceeds SC table length");
    618		return -EINVAL;
    619	}
    620
    621	n = (len * XSDFEC_REG_WIDTH_JUMP) / PAGE_SIZE;
    622	if ((len * XSDFEC_REG_WIDTH_JUMP) % PAGE_SIZE)
    623		n += 1;
    624
    625	if (WARN_ON_ONCE(n > INT_MAX))
    626		return -EINVAL;
    627
    628	nr_pages = n;
    629
    630	res = pin_user_pages_fast((unsigned long)src_ptr, nr_pages, 0, pages);
    631	if (res < nr_pages) {
    632		if (res > 0)
    633			unpin_user_pages(pages, res);
    634
    635		return -EINVAL;
    636	}
    637
    638	for (i = 0; i < nr_pages; i++) {
    639		addr = kmap(pages[i]);
    640		do {
    641			xsdfec_regwrite(xsdfec,
    642					base_addr + ((offset + reg) *
    643						     XSDFEC_REG_WIDTH_JUMP),
    644					addr[reg]);
    645			reg++;
    646		} while ((reg < len) &&
    647			 ((reg * XSDFEC_REG_WIDTH_JUMP) % PAGE_SIZE));
    648		unpin_user_page(pages[i]);
    649	}
    650	return 0;
    651}
    652
    653static int xsdfec_add_ldpc(struct xsdfec_dev *xsdfec, void __user *arg)
    654{
    655	struct xsdfec_ldpc_params *ldpc;
    656	int ret, n;
    657
    658	ldpc = memdup_user(arg, sizeof(*ldpc));
    659	if (IS_ERR(ldpc))
    660		return PTR_ERR(ldpc);
    661
    662	if (xsdfec->config.code == XSDFEC_TURBO_CODE) {
    663		ret = -EIO;
    664		goto err_out;
    665	}
    666
    667	/* Verify Device has not started */
    668	if (xsdfec->state == XSDFEC_STARTED) {
    669		ret = -EIO;
    670		goto err_out;
    671	}
    672
    673	if (xsdfec->config.code_wr_protect) {
    674		ret = -EIO;
    675		goto err_out;
    676	}
    677
    678	/* Write Reg 0 */
    679	ret = xsdfec_reg0_write(xsdfec, ldpc->n, ldpc->k, ldpc->psize,
    680				ldpc->code_id);
    681	if (ret)
    682		goto err_out;
    683
    684	/* Write Reg 1 */
    685	ret = xsdfec_reg1_write(xsdfec, ldpc->psize, ldpc->no_packing, ldpc->nm,
    686				ldpc->code_id);
    687	if (ret)
    688		goto err_out;
    689
    690	/* Write Reg 2 */
    691	ret = xsdfec_reg2_write(xsdfec, ldpc->nlayers, ldpc->nmqc,
    692				ldpc->norm_type, ldpc->special_qc,
    693				ldpc->no_final_parity, ldpc->max_schedule,
    694				ldpc->code_id);
    695	if (ret)
    696		goto err_out;
    697
    698	/* Write Reg 3 */
    699	ret = xsdfec_reg3_write(xsdfec, ldpc->sc_off, ldpc->la_off,
    700				ldpc->qc_off, ldpc->code_id);
    701	if (ret)
    702		goto err_out;
    703
    704	/* Write Shared Codes */
    705	n = ldpc->nlayers / 4;
    706	if (ldpc->nlayers % 4)
    707		n++;
    708
    709	ret = xsdfec_table_write(xsdfec, ldpc->sc_off, ldpc->sc_table, n,
    710				 XSDFEC_LDPC_SC_TABLE_ADDR_BASE,
    711				 XSDFEC_SC_TABLE_DEPTH);
    712	if (ret < 0)
    713		goto err_out;
    714
    715	ret = xsdfec_table_write(xsdfec, 4 * ldpc->la_off, ldpc->la_table,
    716				 ldpc->nlayers, XSDFEC_LDPC_LA_TABLE_ADDR_BASE,
    717				 XSDFEC_LA_TABLE_DEPTH);
    718	if (ret < 0)
    719		goto err_out;
    720
    721	ret = xsdfec_table_write(xsdfec, 4 * ldpc->qc_off, ldpc->qc_table,
    722				 ldpc->nqc, XSDFEC_LDPC_QC_TABLE_ADDR_BASE,
    723				 XSDFEC_QC_TABLE_DEPTH);
    724err_out:
    725	kfree(ldpc);
    726	return ret;
    727}
    728
    729static int xsdfec_set_order(struct xsdfec_dev *xsdfec, void __user *arg)
    730{
    731	bool order_invalid;
    732	enum xsdfec_order order;
    733	int err;
    734
    735	err = get_user(order, (enum xsdfec_order __user *)arg);
    736	if (err)
    737		return -EFAULT;
    738
    739	order_invalid = (order != XSDFEC_MAINTAIN_ORDER) &&
    740			(order != XSDFEC_OUT_OF_ORDER);
    741	if (order_invalid)
    742		return -EINVAL;
    743
    744	/* Verify Device has not started */
    745	if (xsdfec->state == XSDFEC_STARTED)
    746		return -EIO;
    747
    748	xsdfec_regwrite(xsdfec, XSDFEC_ORDER_ADDR, order);
    749
    750	xsdfec->config.order = order;
    751
    752	return 0;
    753}
    754
    755static int xsdfec_set_bypass(struct xsdfec_dev *xsdfec, bool __user *arg)
    756{
    757	bool bypass;
    758	int err;
    759
    760	err = get_user(bypass, arg);
    761	if (err)
    762		return -EFAULT;
    763
    764	/* Verify Device has not started */
    765	if (xsdfec->state == XSDFEC_STARTED)
    766		return -EIO;
    767
    768	if (bypass)
    769		xsdfec_regwrite(xsdfec, XSDFEC_BYPASS_ADDR, 1);
    770	else
    771		xsdfec_regwrite(xsdfec, XSDFEC_BYPASS_ADDR, 0);
    772
    773	xsdfec->config.bypass = bypass;
    774
    775	return 0;
    776}
    777
    778static int xsdfec_is_active(struct xsdfec_dev *xsdfec, bool __user *arg)
    779{
    780	u32 reg_value;
    781	bool is_active;
    782	int err;
    783
    784	reg_value = xsdfec_regread(xsdfec, XSDFEC_ACTIVE_ADDR);
    785	/* using a double ! operator instead of casting */
    786	is_active = !!(reg_value & XSDFEC_IS_ACTIVITY_SET);
    787	err = put_user(is_active, arg);
    788	if (err)
    789		return -EFAULT;
    790
    791	return err;
    792}
    793
    794static u32
    795xsdfec_translate_axis_width_cfg_val(enum xsdfec_axis_width axis_width_cfg)
    796{
    797	u32 axis_width_field = 0;
    798
    799	switch (axis_width_cfg) {
    800	case XSDFEC_1x128b:
    801		axis_width_field = 0;
    802		break;
    803	case XSDFEC_2x128b:
    804		axis_width_field = 1;
    805		break;
    806	case XSDFEC_4x128b:
    807		axis_width_field = 2;
    808		break;
    809	}
    810
    811	return axis_width_field;
    812}
    813
    814static u32 xsdfec_translate_axis_words_cfg_val(enum xsdfec_axis_word_include
    815	axis_word_inc_cfg)
    816{
    817	u32 axis_words_field = 0;
    818
    819	if (axis_word_inc_cfg == XSDFEC_FIXED_VALUE ||
    820	    axis_word_inc_cfg == XSDFEC_IN_BLOCK)
    821		axis_words_field = 0;
    822	else if (axis_word_inc_cfg == XSDFEC_PER_AXI_TRANSACTION)
    823		axis_words_field = 1;
    824
    825	return axis_words_field;
    826}
    827
    828static int xsdfec_cfg_axi_streams(struct xsdfec_dev *xsdfec)
    829{
    830	u32 reg_value;
    831	u32 dout_words_field;
    832	u32 dout_width_field;
    833	u32 din_words_field;
    834	u32 din_width_field;
    835	struct xsdfec_config *config = &xsdfec->config;
    836
    837	/* translate config info to register values */
    838	dout_words_field =
    839		xsdfec_translate_axis_words_cfg_val(config->dout_word_include);
    840	dout_width_field =
    841		xsdfec_translate_axis_width_cfg_val(config->dout_width);
    842	din_words_field =
    843		xsdfec_translate_axis_words_cfg_val(config->din_word_include);
    844	din_width_field =
    845		xsdfec_translate_axis_width_cfg_val(config->din_width);
    846
    847	reg_value = dout_words_field << XSDFEC_AXIS_DOUT_WORDS_LSB;
    848	reg_value |= dout_width_field << XSDFEC_AXIS_DOUT_WIDTH_LSB;
    849	reg_value |= din_words_field << XSDFEC_AXIS_DIN_WORDS_LSB;
    850	reg_value |= din_width_field << XSDFEC_AXIS_DIN_WIDTH_LSB;
    851
    852	xsdfec_regwrite(xsdfec, XSDFEC_AXIS_WIDTH_ADDR, reg_value);
    853
    854	return 0;
    855}
    856
    857static int xsdfec_dev_open(struct inode *iptr, struct file *fptr)
    858{
    859	return 0;
    860}
    861
    862static int xsdfec_dev_release(struct inode *iptr, struct file *fptr)
    863{
    864	return 0;
    865}
    866
    867static int xsdfec_start(struct xsdfec_dev *xsdfec)
    868{
    869	u32 regread;
    870
    871	regread = xsdfec_regread(xsdfec, XSDFEC_FEC_CODE_ADDR);
    872	regread &= 0x1;
    873	if (regread != xsdfec->config.code) {
    874		dev_dbg(xsdfec->dev,
    875			"%s SDFEC HW code does not match driver code, reg %d, code %d",
    876			__func__, regread, xsdfec->config.code);
    877		return -EINVAL;
    878	}
    879
    880	/* Set AXIS enable */
    881	xsdfec_regwrite(xsdfec, XSDFEC_AXIS_ENABLE_ADDR,
    882			XSDFEC_AXIS_ENABLE_MASK);
    883	/* Done */
    884	xsdfec->state = XSDFEC_STARTED;
    885	return 0;
    886}
    887
    888static int xsdfec_stop(struct xsdfec_dev *xsdfec)
    889{
    890	u32 regread;
    891
    892	if (xsdfec->state != XSDFEC_STARTED)
    893		dev_dbg(xsdfec->dev, "Device not started correctly");
    894	/* Disable AXIS_ENABLE Input interfaces only */
    895	regread = xsdfec_regread(xsdfec, XSDFEC_AXIS_ENABLE_ADDR);
    896	regread &= (~XSDFEC_AXIS_IN_ENABLE_MASK);
    897	xsdfec_regwrite(xsdfec, XSDFEC_AXIS_ENABLE_ADDR, regread);
    898	/* Stop */
    899	xsdfec->state = XSDFEC_STOPPED;
    900	return 0;
    901}
    902
    903static int xsdfec_clear_stats(struct xsdfec_dev *xsdfec)
    904{
    905	spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags);
    906	xsdfec->isr_err_count = 0;
    907	xsdfec->uecc_count = 0;
    908	xsdfec->cecc_count = 0;
    909	spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags);
    910
    911	return 0;
    912}
    913
    914static int xsdfec_get_stats(struct xsdfec_dev *xsdfec, void __user *arg)
    915{
    916	int err;
    917	struct xsdfec_stats user_stats;
    918
    919	spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags);
    920	user_stats.isr_err_count = xsdfec->isr_err_count;
    921	user_stats.cecc_count = xsdfec->cecc_count;
    922	user_stats.uecc_count = xsdfec->uecc_count;
    923	xsdfec->stats_updated = false;
    924	spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags);
    925
    926	err = copy_to_user(arg, &user_stats, sizeof(user_stats));
    927	if (err)
    928		err = -EFAULT;
    929
    930	return err;
    931}
    932
    933static int xsdfec_set_default_config(struct xsdfec_dev *xsdfec)
    934{
    935	/* Ensure registers are aligned with core configuration */
    936	xsdfec_regwrite(xsdfec, XSDFEC_FEC_CODE_ADDR, xsdfec->config.code);
    937	xsdfec_cfg_axi_streams(xsdfec);
    938	update_config_from_hw(xsdfec);
    939
    940	return 0;
    941}
    942
    943static long xsdfec_dev_ioctl(struct file *fptr, unsigned int cmd,
    944			     unsigned long data)
    945{
    946	struct xsdfec_dev *xsdfec;
    947	void __user *arg = (void __user *)data;
    948	int rval;
    949
    950	xsdfec = container_of(fptr->private_data, struct xsdfec_dev, miscdev);
    951
    952	/* In failed state allow only reset and get status IOCTLs */
    953	if (xsdfec->state == XSDFEC_NEEDS_RESET &&
    954	    (cmd != XSDFEC_SET_DEFAULT_CONFIG && cmd != XSDFEC_GET_STATUS &&
    955	     cmd != XSDFEC_GET_STATS && cmd != XSDFEC_CLEAR_STATS)) {
    956		return -EPERM;
    957	}
    958
    959	switch (cmd) {
    960	case XSDFEC_START_DEV:
    961		rval = xsdfec_start(xsdfec);
    962		break;
    963	case XSDFEC_STOP_DEV:
    964		rval = xsdfec_stop(xsdfec);
    965		break;
    966	case XSDFEC_CLEAR_STATS:
    967		rval = xsdfec_clear_stats(xsdfec);
    968		break;
    969	case XSDFEC_GET_STATS:
    970		rval = xsdfec_get_stats(xsdfec, arg);
    971		break;
    972	case XSDFEC_GET_STATUS:
    973		rval = xsdfec_get_status(xsdfec, arg);
    974		break;
    975	case XSDFEC_GET_CONFIG:
    976		rval = xsdfec_get_config(xsdfec, arg);
    977		break;
    978	case XSDFEC_SET_DEFAULT_CONFIG:
    979		rval = xsdfec_set_default_config(xsdfec);
    980		break;
    981	case XSDFEC_SET_IRQ:
    982		rval = xsdfec_set_irq(xsdfec, arg);
    983		break;
    984	case XSDFEC_SET_TURBO:
    985		rval = xsdfec_set_turbo(xsdfec, arg);
    986		break;
    987	case XSDFEC_GET_TURBO:
    988		rval = xsdfec_get_turbo(xsdfec, arg);
    989		break;
    990	case XSDFEC_ADD_LDPC_CODE_PARAMS:
    991		rval = xsdfec_add_ldpc(xsdfec, arg);
    992		break;
    993	case XSDFEC_SET_ORDER:
    994		rval = xsdfec_set_order(xsdfec, arg);
    995		break;
    996	case XSDFEC_SET_BYPASS:
    997		rval = xsdfec_set_bypass(xsdfec, arg);
    998		break;
    999	case XSDFEC_IS_ACTIVE:
   1000		rval = xsdfec_is_active(xsdfec, (bool __user *)arg);
   1001		break;
   1002	default:
   1003		rval = -ENOTTY;
   1004		break;
   1005	}
   1006	return rval;
   1007}
   1008
   1009static __poll_t xsdfec_poll(struct file *file, poll_table *wait)
   1010{
   1011	__poll_t mask = 0;
   1012	struct xsdfec_dev *xsdfec;
   1013
   1014	xsdfec = container_of(file->private_data, struct xsdfec_dev, miscdev);
   1015
   1016	poll_wait(file, &xsdfec->waitq, wait);
   1017
   1018	/* XSDFEC ISR detected an error */
   1019	spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags);
   1020	if (xsdfec->state_updated)
   1021		mask |= EPOLLIN | EPOLLPRI;
   1022
   1023	if (xsdfec->stats_updated)
   1024		mask |= EPOLLIN | EPOLLRDNORM;
   1025	spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags);
   1026
   1027	return mask;
   1028}
   1029
   1030static const struct file_operations xsdfec_fops = {
   1031	.owner = THIS_MODULE,
   1032	.open = xsdfec_dev_open,
   1033	.release = xsdfec_dev_release,
   1034	.unlocked_ioctl = xsdfec_dev_ioctl,
   1035	.poll = xsdfec_poll,
   1036	.compat_ioctl = compat_ptr_ioctl,
   1037};
   1038
   1039static int xsdfec_parse_of(struct xsdfec_dev *xsdfec)
   1040{
   1041	struct device *dev = xsdfec->dev;
   1042	struct device_node *node = dev->of_node;
   1043	int rval;
   1044	const char *fec_code;
   1045	u32 din_width;
   1046	u32 din_word_include;
   1047	u32 dout_width;
   1048	u32 dout_word_include;
   1049
   1050	rval = of_property_read_string(node, "xlnx,sdfec-code", &fec_code);
   1051	if (rval < 0)
   1052		return rval;
   1053
   1054	if (!strcasecmp(fec_code, "ldpc"))
   1055		xsdfec->config.code = XSDFEC_LDPC_CODE;
   1056	else if (!strcasecmp(fec_code, "turbo"))
   1057		xsdfec->config.code = XSDFEC_TURBO_CODE;
   1058	else
   1059		return -EINVAL;
   1060
   1061	rval = of_property_read_u32(node, "xlnx,sdfec-din-words",
   1062				    &din_word_include);
   1063	if (rval < 0)
   1064		return rval;
   1065
   1066	if (din_word_include < XSDFEC_AXIS_WORDS_INCLUDE_MAX)
   1067		xsdfec->config.din_word_include = din_word_include;
   1068	else
   1069		return -EINVAL;
   1070
   1071	rval = of_property_read_u32(node, "xlnx,sdfec-din-width", &din_width);
   1072	if (rval < 0)
   1073		return rval;
   1074
   1075	switch (din_width) {
   1076	/* Fall through and set for valid values */
   1077	case XSDFEC_1x128b:
   1078	case XSDFEC_2x128b:
   1079	case XSDFEC_4x128b:
   1080		xsdfec->config.din_width = din_width;
   1081		break;
   1082	default:
   1083		return -EINVAL;
   1084	}
   1085
   1086	rval = of_property_read_u32(node, "xlnx,sdfec-dout-words",
   1087				    &dout_word_include);
   1088	if (rval < 0)
   1089		return rval;
   1090
   1091	if (dout_word_include < XSDFEC_AXIS_WORDS_INCLUDE_MAX)
   1092		xsdfec->config.dout_word_include = dout_word_include;
   1093	else
   1094		return -EINVAL;
   1095
   1096	rval = of_property_read_u32(node, "xlnx,sdfec-dout-width", &dout_width);
   1097	if (rval < 0)
   1098		return rval;
   1099
   1100	switch (dout_width) {
   1101	/* Fall through and set for valid values */
   1102	case XSDFEC_1x128b:
   1103	case XSDFEC_2x128b:
   1104	case XSDFEC_4x128b:
   1105		xsdfec->config.dout_width = dout_width;
   1106		break;
   1107	default:
   1108		return -EINVAL;
   1109	}
   1110
   1111	/* Write LDPC to CODE Register */
   1112	xsdfec_regwrite(xsdfec, XSDFEC_FEC_CODE_ADDR, xsdfec->config.code);
   1113
   1114	xsdfec_cfg_axi_streams(xsdfec);
   1115
   1116	return 0;
   1117}
   1118
   1119static irqreturn_t xsdfec_irq_thread(int irq, void *dev_id)
   1120{
   1121	struct xsdfec_dev *xsdfec = dev_id;
   1122	irqreturn_t ret = IRQ_HANDLED;
   1123	u32 ecc_err;
   1124	u32 isr_err;
   1125	u32 uecc_count;
   1126	u32 cecc_count;
   1127	u32 isr_err_count;
   1128	u32 aecc_count;
   1129	u32 tmp;
   1130
   1131	WARN_ON(xsdfec->irq != irq);
   1132
   1133	/* Mask Interrupts */
   1134	xsdfec_isr_enable(xsdfec, false);
   1135	xsdfec_ecc_isr_enable(xsdfec, false);
   1136	/* Read ISR */
   1137	ecc_err = xsdfec_regread(xsdfec, XSDFEC_ECC_ISR_ADDR);
   1138	isr_err = xsdfec_regread(xsdfec, XSDFEC_ISR_ADDR);
   1139	/* Clear the interrupts */
   1140	xsdfec_regwrite(xsdfec, XSDFEC_ECC_ISR_ADDR, ecc_err);
   1141	xsdfec_regwrite(xsdfec, XSDFEC_ISR_ADDR, isr_err);
   1142
   1143	tmp = ecc_err & XSDFEC_ALL_ECC_ISR_MBE_MASK;
   1144	/* Count uncorrectable 2-bit errors */
   1145	uecc_count = hweight32(tmp);
   1146	/* Count all ECC errors */
   1147	aecc_count = hweight32(ecc_err);
   1148	/* Number of correctable 1-bit ECC error */
   1149	cecc_count = aecc_count - 2 * uecc_count;
   1150	/* Count ISR errors */
   1151	isr_err_count = hweight32(isr_err);
   1152	dev_dbg(xsdfec->dev, "tmp=%x, uecc=%x, aecc=%x, cecc=%x, isr=%x", tmp,
   1153		uecc_count, aecc_count, cecc_count, isr_err_count);
   1154	dev_dbg(xsdfec->dev, "uecc=%x, cecc=%x, isr=%x", xsdfec->uecc_count,
   1155		xsdfec->cecc_count, xsdfec->isr_err_count);
   1156
   1157	spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags);
   1158	/* Add new errors to a 2-bits counter */
   1159	if (uecc_count)
   1160		xsdfec->uecc_count += uecc_count;
   1161	/* Add new errors to a 1-bits counter */
   1162	if (cecc_count)
   1163		xsdfec->cecc_count += cecc_count;
   1164	/* Add new errors to a ISR counter */
   1165	if (isr_err_count)
   1166		xsdfec->isr_err_count += isr_err_count;
   1167
   1168	/* Update state/stats flag */
   1169	if (uecc_count) {
   1170		if (ecc_err & XSDFEC_ECC_ISR_MBE_MASK)
   1171			xsdfec->state = XSDFEC_NEEDS_RESET;
   1172		else if (ecc_err & XSDFEC_PL_INIT_ECC_ISR_MBE_MASK)
   1173			xsdfec->state = XSDFEC_PL_RECONFIGURE;
   1174		xsdfec->stats_updated = true;
   1175		xsdfec->state_updated = true;
   1176	}
   1177
   1178	if (cecc_count)
   1179		xsdfec->stats_updated = true;
   1180
   1181	if (isr_err_count) {
   1182		xsdfec->state = XSDFEC_NEEDS_RESET;
   1183		xsdfec->stats_updated = true;
   1184		xsdfec->state_updated = true;
   1185	}
   1186
   1187	spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags);
   1188	dev_dbg(xsdfec->dev, "state=%x, stats=%x", xsdfec->state_updated,
   1189		xsdfec->stats_updated);
   1190
   1191	/* Enable another polling */
   1192	if (xsdfec->state_updated || xsdfec->stats_updated)
   1193		wake_up_interruptible(&xsdfec->waitq);
   1194	else
   1195		ret = IRQ_NONE;
   1196
   1197	/* Unmask Interrupts */
   1198	xsdfec_isr_enable(xsdfec, true);
   1199	xsdfec_ecc_isr_enable(xsdfec, true);
   1200
   1201	return ret;
   1202}
   1203
   1204static int xsdfec_clk_init(struct platform_device *pdev,
   1205			   struct xsdfec_clks *clks)
   1206{
   1207	int err;
   1208
   1209	clks->core_clk = devm_clk_get(&pdev->dev, "core_clk");
   1210	if (IS_ERR(clks->core_clk)) {
   1211		dev_err(&pdev->dev, "failed to get core_clk");
   1212		return PTR_ERR(clks->core_clk);
   1213	}
   1214
   1215	clks->axi_clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
   1216	if (IS_ERR(clks->axi_clk)) {
   1217		dev_err(&pdev->dev, "failed to get axi_clk");
   1218		return PTR_ERR(clks->axi_clk);
   1219	}
   1220
   1221	clks->din_words_clk = devm_clk_get(&pdev->dev, "s_axis_din_words_aclk");
   1222	if (IS_ERR(clks->din_words_clk)) {
   1223		if (PTR_ERR(clks->din_words_clk) != -ENOENT) {
   1224			err = PTR_ERR(clks->din_words_clk);
   1225			return err;
   1226		}
   1227		clks->din_words_clk = NULL;
   1228	}
   1229
   1230	clks->din_clk = devm_clk_get(&pdev->dev, "s_axis_din_aclk");
   1231	if (IS_ERR(clks->din_clk)) {
   1232		if (PTR_ERR(clks->din_clk) != -ENOENT) {
   1233			err = PTR_ERR(clks->din_clk);
   1234			return err;
   1235		}
   1236		clks->din_clk = NULL;
   1237	}
   1238
   1239	clks->dout_clk = devm_clk_get(&pdev->dev, "m_axis_dout_aclk");
   1240	if (IS_ERR(clks->dout_clk)) {
   1241		if (PTR_ERR(clks->dout_clk) != -ENOENT) {
   1242			err = PTR_ERR(clks->dout_clk);
   1243			return err;
   1244		}
   1245		clks->dout_clk = NULL;
   1246	}
   1247
   1248	clks->dout_words_clk =
   1249		devm_clk_get(&pdev->dev, "s_axis_dout_words_aclk");
   1250	if (IS_ERR(clks->dout_words_clk)) {
   1251		if (PTR_ERR(clks->dout_words_clk) != -ENOENT) {
   1252			err = PTR_ERR(clks->dout_words_clk);
   1253			return err;
   1254		}
   1255		clks->dout_words_clk = NULL;
   1256	}
   1257
   1258	clks->ctrl_clk = devm_clk_get(&pdev->dev, "s_axis_ctrl_aclk");
   1259	if (IS_ERR(clks->ctrl_clk)) {
   1260		if (PTR_ERR(clks->ctrl_clk) != -ENOENT) {
   1261			err = PTR_ERR(clks->ctrl_clk);
   1262			return err;
   1263		}
   1264		clks->ctrl_clk = NULL;
   1265	}
   1266
   1267	clks->status_clk = devm_clk_get(&pdev->dev, "m_axis_status_aclk");
   1268	if (IS_ERR(clks->status_clk)) {
   1269		if (PTR_ERR(clks->status_clk) != -ENOENT) {
   1270			err = PTR_ERR(clks->status_clk);
   1271			return err;
   1272		}
   1273		clks->status_clk = NULL;
   1274	}
   1275
   1276	err = clk_prepare_enable(clks->core_clk);
   1277	if (err) {
   1278		dev_err(&pdev->dev, "failed to enable core_clk (%d)", err);
   1279		return err;
   1280	}
   1281
   1282	err = clk_prepare_enable(clks->axi_clk);
   1283	if (err) {
   1284		dev_err(&pdev->dev, "failed to enable axi_clk (%d)", err);
   1285		goto err_disable_core_clk;
   1286	}
   1287
   1288	err = clk_prepare_enable(clks->din_clk);
   1289	if (err) {
   1290		dev_err(&pdev->dev, "failed to enable din_clk (%d)", err);
   1291		goto err_disable_axi_clk;
   1292	}
   1293
   1294	err = clk_prepare_enable(clks->din_words_clk);
   1295	if (err) {
   1296		dev_err(&pdev->dev, "failed to enable din_words_clk (%d)", err);
   1297		goto err_disable_din_clk;
   1298	}
   1299
   1300	err = clk_prepare_enable(clks->dout_clk);
   1301	if (err) {
   1302		dev_err(&pdev->dev, "failed to enable dout_clk (%d)", err);
   1303		goto err_disable_din_words_clk;
   1304	}
   1305
   1306	err = clk_prepare_enable(clks->dout_words_clk);
   1307	if (err) {
   1308		dev_err(&pdev->dev, "failed to enable dout_words_clk (%d)",
   1309			err);
   1310		goto err_disable_dout_clk;
   1311	}
   1312
   1313	err = clk_prepare_enable(clks->ctrl_clk);
   1314	if (err) {
   1315		dev_err(&pdev->dev, "failed to enable ctrl_clk (%d)", err);
   1316		goto err_disable_dout_words_clk;
   1317	}
   1318
   1319	err = clk_prepare_enable(clks->status_clk);
   1320	if (err) {
   1321		dev_err(&pdev->dev, "failed to enable status_clk (%d)\n", err);
   1322		goto err_disable_ctrl_clk;
   1323	}
   1324
   1325	return err;
   1326
   1327err_disable_ctrl_clk:
   1328	clk_disable_unprepare(clks->ctrl_clk);
   1329err_disable_dout_words_clk:
   1330	clk_disable_unprepare(clks->dout_words_clk);
   1331err_disable_dout_clk:
   1332	clk_disable_unprepare(clks->dout_clk);
   1333err_disable_din_words_clk:
   1334	clk_disable_unprepare(clks->din_words_clk);
   1335err_disable_din_clk:
   1336	clk_disable_unprepare(clks->din_clk);
   1337err_disable_axi_clk:
   1338	clk_disable_unprepare(clks->axi_clk);
   1339err_disable_core_clk:
   1340	clk_disable_unprepare(clks->core_clk);
   1341
   1342	return err;
   1343}
   1344
   1345static void xsdfec_disable_all_clks(struct xsdfec_clks *clks)
   1346{
   1347	clk_disable_unprepare(clks->status_clk);
   1348	clk_disable_unprepare(clks->ctrl_clk);
   1349	clk_disable_unprepare(clks->dout_words_clk);
   1350	clk_disable_unprepare(clks->dout_clk);
   1351	clk_disable_unprepare(clks->din_words_clk);
   1352	clk_disable_unprepare(clks->din_clk);
   1353	clk_disable_unprepare(clks->core_clk);
   1354	clk_disable_unprepare(clks->axi_clk);
   1355}
   1356
   1357static int xsdfec_probe(struct platform_device *pdev)
   1358{
   1359	struct xsdfec_dev *xsdfec;
   1360	struct device *dev;
   1361	struct resource *res;
   1362	int err;
   1363	bool irq_enabled = true;
   1364
   1365	xsdfec = devm_kzalloc(&pdev->dev, sizeof(*xsdfec), GFP_KERNEL);
   1366	if (!xsdfec)
   1367		return -ENOMEM;
   1368
   1369	xsdfec->dev = &pdev->dev;
   1370	spin_lock_init(&xsdfec->error_data_lock);
   1371
   1372	err = xsdfec_clk_init(pdev, &xsdfec->clks);
   1373	if (err)
   1374		return err;
   1375
   1376	dev = xsdfec->dev;
   1377	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
   1378	xsdfec->regs = devm_ioremap_resource(dev, res);
   1379	if (IS_ERR(xsdfec->regs)) {
   1380		err = PTR_ERR(xsdfec->regs);
   1381		goto err_xsdfec_dev;
   1382	}
   1383
   1384	xsdfec->irq = platform_get_irq(pdev, 0);
   1385	if (xsdfec->irq < 0) {
   1386		dev_dbg(dev, "platform_get_irq failed");
   1387		irq_enabled = false;
   1388	}
   1389
   1390	err = xsdfec_parse_of(xsdfec);
   1391	if (err < 0)
   1392		goto err_xsdfec_dev;
   1393
   1394	update_config_from_hw(xsdfec);
   1395
   1396	/* Save driver private data */
   1397	platform_set_drvdata(pdev, xsdfec);
   1398
   1399	if (irq_enabled) {
   1400		init_waitqueue_head(&xsdfec->waitq);
   1401		/* Register IRQ thread */
   1402		err = devm_request_threaded_irq(dev, xsdfec->irq, NULL,
   1403						xsdfec_irq_thread, IRQF_ONESHOT,
   1404						"xilinx-sdfec16", xsdfec);
   1405		if (err < 0) {
   1406			dev_err(dev, "unable to request IRQ%d", xsdfec->irq);
   1407			goto err_xsdfec_dev;
   1408		}
   1409	}
   1410
   1411	err = ida_alloc(&dev_nrs, GFP_KERNEL);
   1412	if (err < 0)
   1413		goto err_xsdfec_dev;
   1414	xsdfec->dev_id = err;
   1415
   1416	snprintf(xsdfec->dev_name, DEV_NAME_LEN, "xsdfec%d", xsdfec->dev_id);
   1417	xsdfec->miscdev.minor = MISC_DYNAMIC_MINOR;
   1418	xsdfec->miscdev.name = xsdfec->dev_name;
   1419	xsdfec->miscdev.fops = &xsdfec_fops;
   1420	xsdfec->miscdev.parent = dev;
   1421	err = misc_register(&xsdfec->miscdev);
   1422	if (err) {
   1423		dev_err(dev, "error:%d. Unable to register device", err);
   1424		goto err_xsdfec_ida;
   1425	}
   1426	return 0;
   1427
   1428err_xsdfec_ida:
   1429	ida_free(&dev_nrs, xsdfec->dev_id);
   1430err_xsdfec_dev:
   1431	xsdfec_disable_all_clks(&xsdfec->clks);
   1432	return err;
   1433}
   1434
   1435static int xsdfec_remove(struct platform_device *pdev)
   1436{
   1437	struct xsdfec_dev *xsdfec;
   1438
   1439	xsdfec = platform_get_drvdata(pdev);
   1440	misc_deregister(&xsdfec->miscdev);
   1441	ida_free(&dev_nrs, xsdfec->dev_id);
   1442	xsdfec_disable_all_clks(&xsdfec->clks);
   1443	return 0;
   1444}
   1445
   1446static const struct of_device_id xsdfec_of_match[] = {
   1447	{
   1448		.compatible = "xlnx,sd-fec-1.1",
   1449	},
   1450	{ /* end of table */ }
   1451};
   1452MODULE_DEVICE_TABLE(of, xsdfec_of_match);
   1453
   1454static struct platform_driver xsdfec_driver = {
   1455	.driver = {
   1456		.name = "xilinx-sdfec",
   1457		.of_match_table = xsdfec_of_match,
   1458	},
   1459	.probe = xsdfec_probe,
   1460	.remove =  xsdfec_remove,
   1461};
   1462
   1463module_platform_driver(xsdfec_driver);
   1464
   1465MODULE_AUTHOR("Xilinx, Inc");
   1466MODULE_DESCRIPTION("Xilinx SD-FEC16 Driver");
   1467MODULE_LICENSE("GPL");