1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2019 Xilinx, Inc.
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().
13 #include <linux/miscdevice.h>
15 #include <linux/interrupt.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/poll.h>
21 #include <linux/slab.h>
22 #include <linux/clk.h>
23 #include <linux/compat.h>
24 #include <linux/highmem.h>
26 #include <uapi/misc/xilinx_sdfec.h>
28 #define DEV_NAME_LEN 12
30 static DEFINE_IDA(dev_nrs
);
32 /* Xilinx SDFEC Register Map */
33 /* CODE_WRI_PROTECT Register */
34 #define XSDFEC_CODE_WR_PROTECT_ADDR (0x4)
37 #define XSDFEC_ACTIVE_ADDR (0x8)
38 #define XSDFEC_IS_ACTIVITY_SET (0x1)
40 /* AXIS_WIDTH Register */
41 #define XSDFEC_AXIS_WIDTH_ADDR (0xC)
42 #define XSDFEC_AXIS_DOUT_WORDS_LSB (5)
43 #define XSDFEC_AXIS_DOUT_WIDTH_LSB (3)
44 #define XSDFEC_AXIS_DIN_WORDS_LSB (2)
45 #define XSDFEC_AXIS_DIN_WIDTH_LSB (0)
47 /* AXIS_ENABLE Register */
48 #define XSDFEC_AXIS_ENABLE_ADDR (0x10)
49 #define XSDFEC_AXIS_OUT_ENABLE_MASK (0x38)
50 #define XSDFEC_AXIS_IN_ENABLE_MASK (0x7)
51 #define XSDFEC_AXIS_ENABLE_MASK \
52 (XSDFEC_AXIS_OUT_ENABLE_MASK | XSDFEC_AXIS_IN_ENABLE_MASK)
54 /* FEC_CODE Register */
55 #define XSDFEC_FEC_CODE_ADDR (0x14)
57 /* ORDER Register Map */
58 #define XSDFEC_ORDER_ADDR (0x18)
60 /* Interrupt Status Register */
61 #define XSDFEC_ISR_ADDR (0x1C)
62 /* Interrupt Status Register Bit Mask */
63 #define XSDFEC_ISR_MASK (0x3F)
65 /* Write Only - Interrupt Enable Register */
66 #define XSDFEC_IER_ADDR (0x20)
67 /* Write Only - Interrupt Disable Register */
68 #define XSDFEC_IDR_ADDR (0x24)
69 /* Read Only - Interrupt Mask Register */
70 #define XSDFEC_IMR_ADDR (0x28)
72 /* ECC Interrupt Status Register */
73 #define XSDFEC_ECC_ISR_ADDR (0x2C)
74 /* Single Bit Errors */
75 #define XSDFEC_ECC_ISR_SBE_MASK (0x7FF)
76 /* PL Initialize Single Bit Errors */
77 #define XSDFEC_PL_INIT_ECC_ISR_SBE_MASK (0x3C00000)
78 /* Multi Bit Errors */
79 #define XSDFEC_ECC_ISR_MBE_MASK (0x3FF800)
80 /* PL Initialize Multi Bit Errors */
81 #define XSDFEC_PL_INIT_ECC_ISR_MBE_MASK (0x3C000000)
82 /* Multi Bit Error to Event Shift */
83 #define XSDFEC_ECC_ISR_MBE_TO_EVENT_SHIFT (11)
84 /* PL Initialize Multi Bit Error to Event Shift */
85 #define XSDFEC_PL_INIT_ECC_ISR_MBE_TO_EVENT_SHIFT (4)
86 /* ECC Interrupt Status Bit Mask */
87 #define XSDFEC_ECC_ISR_MASK (XSDFEC_ECC_ISR_SBE_MASK | XSDFEC_ECC_ISR_MBE_MASK)
88 /* ECC Interrupt Status PL Initialize Bit Mask */
89 #define XSDFEC_PL_INIT_ECC_ISR_MASK \
90 (XSDFEC_PL_INIT_ECC_ISR_SBE_MASK | XSDFEC_PL_INIT_ECC_ISR_MBE_MASK)
91 /* ECC Interrupt Status All Bit Mask */
92 #define XSDFEC_ALL_ECC_ISR_MASK \
93 (XSDFEC_ECC_ISR_MASK | XSDFEC_PL_INIT_ECC_ISR_MASK)
94 /* ECC Interrupt Status Single Bit Errors Mask */
95 #define XSDFEC_ALL_ECC_ISR_SBE_MASK \
96 (XSDFEC_ECC_ISR_SBE_MASK | XSDFEC_PL_INIT_ECC_ISR_SBE_MASK)
97 /* ECC Interrupt Status Multi Bit Errors Mask */
98 #define XSDFEC_ALL_ECC_ISR_MBE_MASK \
99 (XSDFEC_ECC_ISR_MBE_MASK | XSDFEC_PL_INIT_ECC_ISR_MBE_MASK)
101 /* Write Only - ECC Interrupt Enable Register */
102 #define XSDFEC_ECC_IER_ADDR (0x30)
103 /* Write Only - ECC Interrupt Disable Register */
104 #define XSDFEC_ECC_IDR_ADDR (0x34)
105 /* Read Only - ECC Interrupt Mask Register */
106 #define XSDFEC_ECC_IMR_ADDR (0x38)
108 /* BYPASS Register */
109 #define XSDFEC_BYPASS_ADDR (0x3C)
111 /* Turbo Code Register */
112 #define XSDFEC_TURBO_ADDR (0x100)
113 #define XSDFEC_TURBO_SCALE_MASK (0xFFF)
114 #define XSDFEC_TURBO_SCALE_BIT_POS (8)
115 #define XSDFEC_TURBO_SCALE_MAX (15)
118 #define XSDFEC_LDPC_CODE_REG0_ADDR_BASE (0x2000)
119 #define XSDFEC_LDPC_CODE_REG0_ADDR_HIGH (0x27F0)
120 #define XSDFEC_REG0_N_MIN (4)
121 #define XSDFEC_REG0_N_MAX (32768)
122 #define XSDFEC_REG0_N_MUL_P (256)
123 #define XSDFEC_REG0_N_LSB (0)
124 #define XSDFEC_REG0_K_MIN (2)
125 #define XSDFEC_REG0_K_MAX (32766)
126 #define XSDFEC_REG0_K_MUL_P (256)
127 #define XSDFEC_REG0_K_LSB (16)
130 #define XSDFEC_LDPC_CODE_REG1_ADDR_BASE (0x2004)
131 #define XSDFEC_LDPC_CODE_REG1_ADDR_HIGH (0x27f4)
132 #define XSDFEC_REG1_PSIZE_MIN (2)
133 #define XSDFEC_REG1_PSIZE_MAX (512)
134 #define XSDFEC_REG1_NO_PACKING_MASK (0x400)
135 #define XSDFEC_REG1_NO_PACKING_LSB (10)
136 #define XSDFEC_REG1_NM_MASK (0xFF800)
137 #define XSDFEC_REG1_NM_LSB (11)
138 #define XSDFEC_REG1_BYPASS_MASK (0x100000)
141 #define XSDFEC_LDPC_CODE_REG2_ADDR_BASE (0x2008)
142 #define XSDFEC_LDPC_CODE_REG2_ADDR_HIGH (0x27f8)
143 #define XSDFEC_REG2_NLAYERS_MIN (1)
144 #define XSDFEC_REG2_NLAYERS_MAX (256)
145 #define XSDFEC_REG2_NNMQC_MASK (0xFFE00)
146 #define XSDFEC_REG2_NMQC_LSB (9)
147 #define XSDFEC_REG2_NORM_TYPE_MASK (0x100000)
148 #define XSDFEC_REG2_NORM_TYPE_LSB (20)
149 #define XSDFEC_REG2_SPECIAL_QC_MASK (0x200000)
150 #define XSDFEC_REG2_SPEICAL_QC_LSB (21)
151 #define XSDFEC_REG2_NO_FINAL_PARITY_MASK (0x400000)
152 #define XSDFEC_REG2_NO_FINAL_PARITY_LSB (22)
153 #define XSDFEC_REG2_MAX_SCHEDULE_MASK (0x1800000)
154 #define XSDFEC_REG2_MAX_SCHEDULE_LSB (23)
157 #define XSDFEC_LDPC_CODE_REG3_ADDR_BASE (0x200C)
158 #define XSDFEC_LDPC_CODE_REG3_ADDR_HIGH (0x27FC)
159 #define XSDFEC_REG3_LA_OFF_LSB (8)
160 #define XSDFEC_REG3_QC_OFF_LSB (16)
162 #define XSDFEC_LDPC_REG_JUMP (0x10)
163 #define XSDFEC_REG_WIDTH_JUMP (4)
165 /* The maximum number of pinned pages */
166 #define MAX_NUM_PAGES ((XSDFEC_QC_TABLE_DEPTH / PAGE_SIZE) + 1)
169 * struct xsdfec_clks - For managing SD-FEC clocks
170 * @core_clk: Main processing clock for core
171 * @axi_clk: AXI4-Lite memory-mapped clock
172 * @din_words_clk: DIN Words AXI4-Stream Slave clock
173 * @din_clk: DIN AXI4-Stream Slave clock
174 * @dout_clk: DOUT Words AXI4-Stream Slave clock
175 * @dout_words_clk: DOUT AXI4-Stream Slave clock
176 * @ctrl_clk: Control AXI4-Stream Slave clock
177 * @status_clk: Status AXI4-Stream Slave clock
180 struct clk
*core_clk
;
182 struct clk
*din_words_clk
;
184 struct clk
*dout_clk
;
185 struct clk
*dout_words_clk
;
186 struct clk
*ctrl_clk
;
187 struct clk
*status_clk
;
191 * struct xsdfec_dev - Driver data for SDFEC
192 * @miscdev: Misc device handle
193 * @clks: Clocks managed by the SDFEC driver
194 * @waitq: Driver wait queue
195 * @config: Configuration of the SDFEC device
196 * @dev_name: Device name
197 * @flags: spinlock flags
198 * @regs: device physical base address
199 * @dev: pointer to device struct
200 * @state: State of the SDFEC device
201 * @error_data_lock: Error counter and states spinlock
203 * @isr_err_count: Count of ISR errors
204 * @cecc_count: Count of Correctable ECC errors (SBE)
205 * @uecc_count: Count of Uncorrectable ECC errors (MBE)
207 * @state_updated: indicates State updated by interrupt handler
208 * @stats_updated: indicates Stats updated by interrupt handler
209 * @intr_enabled: indicates IRQ enabled
211 * This structure contains necessary state for SDFEC driver to operate
214 struct miscdevice miscdev
;
215 struct xsdfec_clks clks
;
216 wait_queue_head_t waitq
;
217 struct xsdfec_config config
;
218 char dev_name
[DEV_NAME_LEN
];
222 enum xsdfec_state state
;
223 /* Spinlock to protect state_updated and stats_updated */
224 spinlock_t error_data_lock
;
235 static inline void xsdfec_regwrite(struct xsdfec_dev
*xsdfec
, u32 addr
,
238 dev_dbg(xsdfec
->dev
, "Writing 0x%x to offset 0x%x", value
, addr
);
239 iowrite32(value
, xsdfec
->regs
+ addr
);
242 static inline u32
xsdfec_regread(struct xsdfec_dev
*xsdfec
, u32 addr
)
246 rval
= ioread32(xsdfec
->regs
+ addr
);
247 dev_dbg(xsdfec
->dev
, "Read value = 0x%x from offset 0x%x", rval
, addr
);
251 static void update_bool_config_from_reg(struct xsdfec_dev
*xsdfec
,
252 u32 reg_offset
, u32 bit_num
,
256 u32 bit_mask
= 1 << bit_num
;
258 reg_val
= xsdfec_regread(xsdfec
, reg_offset
);
259 *config_value
= (reg_val
& bit_mask
) > 0;
262 static void update_config_from_hw(struct xsdfec_dev
*xsdfec
)
267 /* Update the Order */
268 reg_value
= xsdfec_regread(xsdfec
, XSDFEC_ORDER_ADDR
);
269 xsdfec
->config
.order
= reg_value
;
271 update_bool_config_from_reg(xsdfec
, XSDFEC_BYPASS_ADDR
,
272 0, /* Bit Number, maybe change to mask */
273 &xsdfec
->config
.bypass
);
275 update_bool_config_from_reg(xsdfec
, XSDFEC_CODE_WR_PROTECT_ADDR
,
277 &xsdfec
->config
.code_wr_protect
);
279 reg_value
= xsdfec_regread(xsdfec
, XSDFEC_IMR_ADDR
);
280 xsdfec
->config
.irq
.enable_isr
= (reg_value
& XSDFEC_ISR_MASK
) > 0;
282 reg_value
= xsdfec_regread(xsdfec
, XSDFEC_ECC_IMR_ADDR
);
283 xsdfec
->config
.irq
.enable_ecc_isr
=
284 (reg_value
& XSDFEC_ECC_ISR_MASK
) > 0;
286 reg_value
= xsdfec_regread(xsdfec
, XSDFEC_AXIS_ENABLE_ADDR
);
287 sdfec_started
= (reg_value
& XSDFEC_AXIS_IN_ENABLE_MASK
) > 0;
289 xsdfec
->state
= XSDFEC_STARTED
;
291 xsdfec
->state
= XSDFEC_STOPPED
;
294 static int xsdfec_get_status(struct xsdfec_dev
*xsdfec
, void __user
*arg
)
296 struct xsdfec_status status
;
299 memset(&status
, 0, sizeof(status
));
300 spin_lock_irqsave(&xsdfec
->error_data_lock
, xsdfec
->flags
);
301 status
.state
= xsdfec
->state
;
302 xsdfec
->state_updated
= false;
303 spin_unlock_irqrestore(&xsdfec
->error_data_lock
, xsdfec
->flags
);
304 status
.activity
= (xsdfec_regread(xsdfec
, XSDFEC_ACTIVE_ADDR
) &
305 XSDFEC_IS_ACTIVITY_SET
);
307 err
= copy_to_user(arg
, &status
, sizeof(status
));
314 static int xsdfec_get_config(struct xsdfec_dev
*xsdfec
, void __user
*arg
)
318 err
= copy_to_user(arg
, &xsdfec
->config
, sizeof(xsdfec
->config
));
325 static int xsdfec_isr_enable(struct xsdfec_dev
*xsdfec
, bool enable
)
331 xsdfec_regwrite(xsdfec
, XSDFEC_IER_ADDR
, XSDFEC_ISR_MASK
);
332 mask_read
= xsdfec_regread(xsdfec
, XSDFEC_IMR_ADDR
);
333 if (mask_read
& XSDFEC_ISR_MASK
) {
335 "SDFEC enabling irq with IER failed");
340 xsdfec_regwrite(xsdfec
, XSDFEC_IDR_ADDR
, XSDFEC_ISR_MASK
);
341 mask_read
= xsdfec_regread(xsdfec
, XSDFEC_IMR_ADDR
);
342 if ((mask_read
& XSDFEC_ISR_MASK
) != XSDFEC_ISR_MASK
) {
344 "SDFEC disabling irq with IDR failed");
351 static int xsdfec_ecc_isr_enable(struct xsdfec_dev
*xsdfec
, bool enable
)
357 xsdfec_regwrite(xsdfec
, XSDFEC_ECC_IER_ADDR
,
358 XSDFEC_ALL_ECC_ISR_MASK
);
359 mask_read
= xsdfec_regread(xsdfec
, XSDFEC_ECC_IMR_ADDR
);
360 if (mask_read
& XSDFEC_ALL_ECC_ISR_MASK
) {
362 "SDFEC enabling ECC irq with ECC IER failed");
367 xsdfec_regwrite(xsdfec
, XSDFEC_ECC_IDR_ADDR
,
368 XSDFEC_ALL_ECC_ISR_MASK
);
369 mask_read
= xsdfec_regread(xsdfec
, XSDFEC_ECC_IMR_ADDR
);
370 if (!(((mask_read
& XSDFEC_ALL_ECC_ISR_MASK
) ==
371 XSDFEC_ECC_ISR_MASK
) ||
372 ((mask_read
& XSDFEC_ALL_ECC_ISR_MASK
) ==
373 XSDFEC_PL_INIT_ECC_ISR_MASK
))) {
375 "SDFEC disable ECC irq with ECC IDR failed");
382 static int xsdfec_set_irq(struct xsdfec_dev
*xsdfec
, void __user
*arg
)
384 struct xsdfec_irq irq
;
389 err
= copy_from_user(&irq
, arg
, sizeof(irq
));
393 /* Setup tlast related IRQ */
394 isr_err
= xsdfec_isr_enable(xsdfec
, irq
.enable_isr
);
396 xsdfec
->config
.irq
.enable_isr
= irq
.enable_isr
;
398 /* Setup ECC related IRQ */
399 ecc_err
= xsdfec_ecc_isr_enable(xsdfec
, irq
.enable_ecc_isr
);
401 xsdfec
->config
.irq
.enable_ecc_isr
= irq
.enable_ecc_isr
;
403 if (isr_err
< 0 || ecc_err
< 0)
409 static int xsdfec_set_turbo(struct xsdfec_dev
*xsdfec
, void __user
*arg
)
411 struct xsdfec_turbo turbo
;
415 err
= copy_from_user(&turbo
, arg
, sizeof(turbo
));
419 if (turbo
.alg
>= XSDFEC_TURBO_ALG_MAX
)
422 if (turbo
.scale
> XSDFEC_TURBO_SCALE_MAX
)
425 /* Check to see what device tree says about the FEC codes */
426 if (xsdfec
->config
.code
== XSDFEC_LDPC_CODE
)
429 turbo_write
= ((turbo
.scale
& XSDFEC_TURBO_SCALE_MASK
)
430 << XSDFEC_TURBO_SCALE_BIT_POS
) |
432 xsdfec_regwrite(xsdfec
, XSDFEC_TURBO_ADDR
, turbo_write
);
436 static int xsdfec_get_turbo(struct xsdfec_dev
*xsdfec
, void __user
*arg
)
439 struct xsdfec_turbo turbo_params
;
442 if (xsdfec
->config
.code
== XSDFEC_LDPC_CODE
)
445 memset(&turbo_params
, 0, sizeof(turbo_params
));
446 reg_value
= xsdfec_regread(xsdfec
, XSDFEC_TURBO_ADDR
);
448 turbo_params
.scale
= (reg_value
& XSDFEC_TURBO_SCALE_MASK
) >>
449 XSDFEC_TURBO_SCALE_BIT_POS
;
450 turbo_params
.alg
= reg_value
& 0x1;
452 err
= copy_to_user(arg
, &turbo_params
, sizeof(turbo_params
));
459 static int xsdfec_reg0_write(struct xsdfec_dev
*xsdfec
, u32 n
, u32 k
, u32 psize
,
464 if (n
< XSDFEC_REG0_N_MIN
|| n
> XSDFEC_REG0_N_MAX
|| psize
== 0 ||
465 (n
> XSDFEC_REG0_N_MUL_P
* psize
) || n
<= k
|| ((n
% psize
) != 0)) {
466 dev_dbg(xsdfec
->dev
, "N value is not in range");
469 n
<<= XSDFEC_REG0_N_LSB
;
471 if (k
< XSDFEC_REG0_K_MIN
|| k
> XSDFEC_REG0_K_MAX
||
472 (k
> XSDFEC_REG0_K_MUL_P
* psize
) || ((k
% psize
) != 0)) {
473 dev_dbg(xsdfec
->dev
, "K value is not in range");
476 k
= k
<< XSDFEC_REG0_K_LSB
;
479 if (XSDFEC_LDPC_CODE_REG0_ADDR_BASE
+ (offset
* XSDFEC_LDPC_REG_JUMP
) >
480 XSDFEC_LDPC_CODE_REG0_ADDR_HIGH
) {
481 dev_dbg(xsdfec
->dev
, "Writing outside of LDPC reg0 space 0x%x",
482 XSDFEC_LDPC_CODE_REG0_ADDR_BASE
+
483 (offset
* XSDFEC_LDPC_REG_JUMP
));
486 xsdfec_regwrite(xsdfec
,
487 XSDFEC_LDPC_CODE_REG0_ADDR_BASE
+
488 (offset
* XSDFEC_LDPC_REG_JUMP
),
493 static int xsdfec_reg1_write(struct xsdfec_dev
*xsdfec
, u32 psize
,
494 u32 no_packing
, u32 nm
, u32 offset
)
498 if (psize
< XSDFEC_REG1_PSIZE_MIN
|| psize
> XSDFEC_REG1_PSIZE_MAX
) {
499 dev_dbg(xsdfec
->dev
, "Psize is not in range");
503 if (no_packing
!= 0 && no_packing
!= 1)
504 dev_dbg(xsdfec
->dev
, "No-packing bit register invalid");
505 no_packing
= ((no_packing
<< XSDFEC_REG1_NO_PACKING_LSB
) &
506 XSDFEC_REG1_NO_PACKING_MASK
);
508 if (nm
& ~(XSDFEC_REG1_NM_MASK
>> XSDFEC_REG1_NM_LSB
))
509 dev_dbg(xsdfec
->dev
, "NM is beyond 10 bits");
510 nm
= (nm
<< XSDFEC_REG1_NM_LSB
) & XSDFEC_REG1_NM_MASK
;
512 wdata
= nm
| no_packing
| psize
;
513 if (XSDFEC_LDPC_CODE_REG1_ADDR_BASE
+ (offset
* XSDFEC_LDPC_REG_JUMP
) >
514 XSDFEC_LDPC_CODE_REG1_ADDR_HIGH
) {
515 dev_dbg(xsdfec
->dev
, "Writing outside of LDPC reg1 space 0x%x",
516 XSDFEC_LDPC_CODE_REG1_ADDR_BASE
+
517 (offset
* XSDFEC_LDPC_REG_JUMP
));
520 xsdfec_regwrite(xsdfec
,
521 XSDFEC_LDPC_CODE_REG1_ADDR_BASE
+
522 (offset
* XSDFEC_LDPC_REG_JUMP
),
527 static int xsdfec_reg2_write(struct xsdfec_dev
*xsdfec
, u32 nlayers
, u32 nmqc
,
528 u32 norm_type
, u32 special_qc
, u32 no_final_parity
,
529 u32 max_schedule
, u32 offset
)
533 if (nlayers
< XSDFEC_REG2_NLAYERS_MIN
||
534 nlayers
> XSDFEC_REG2_NLAYERS_MAX
) {
535 dev_dbg(xsdfec
->dev
, "Nlayers is not in range");
539 if (nmqc
& ~(XSDFEC_REG2_NNMQC_MASK
>> XSDFEC_REG2_NMQC_LSB
))
540 dev_dbg(xsdfec
->dev
, "NMQC exceeds 11 bits");
541 nmqc
= (nmqc
<< XSDFEC_REG2_NMQC_LSB
) & XSDFEC_REG2_NNMQC_MASK
;
544 dev_dbg(xsdfec
->dev
, "Norm type is invalid");
545 norm_type
= ((norm_type
<< XSDFEC_REG2_NORM_TYPE_LSB
) &
546 XSDFEC_REG2_NORM_TYPE_MASK
);
548 dev_dbg(xsdfec
->dev
, "Special QC in invalid");
549 special_qc
= ((special_qc
<< XSDFEC_REG2_SPEICAL_QC_LSB
) &
550 XSDFEC_REG2_SPECIAL_QC_MASK
);
552 if (no_final_parity
> 1)
553 dev_dbg(xsdfec
->dev
, "No final parity check invalid");
555 ((no_final_parity
<< XSDFEC_REG2_NO_FINAL_PARITY_LSB
) &
556 XSDFEC_REG2_NO_FINAL_PARITY_MASK
);
558 ~(XSDFEC_REG2_MAX_SCHEDULE_MASK
>> XSDFEC_REG2_MAX_SCHEDULE_LSB
))
559 dev_dbg(xsdfec
->dev
, "Max Schedule exceeds 2 bits");
560 max_schedule
= ((max_schedule
<< XSDFEC_REG2_MAX_SCHEDULE_LSB
) &
561 XSDFEC_REG2_MAX_SCHEDULE_MASK
);
563 wdata
= (max_schedule
| no_final_parity
| special_qc
| norm_type
|
566 if (XSDFEC_LDPC_CODE_REG2_ADDR_BASE
+ (offset
* XSDFEC_LDPC_REG_JUMP
) >
567 XSDFEC_LDPC_CODE_REG2_ADDR_HIGH
) {
568 dev_dbg(xsdfec
->dev
, "Writing outside of LDPC reg2 space 0x%x",
569 XSDFEC_LDPC_CODE_REG2_ADDR_BASE
+
570 (offset
* XSDFEC_LDPC_REG_JUMP
));
573 xsdfec_regwrite(xsdfec
,
574 XSDFEC_LDPC_CODE_REG2_ADDR_BASE
+
575 (offset
* XSDFEC_LDPC_REG_JUMP
),
580 static int xsdfec_reg3_write(struct xsdfec_dev
*xsdfec
, u8 sc_off
, u8 la_off
,
581 u16 qc_off
, u32 offset
)
585 wdata
= ((qc_off
<< XSDFEC_REG3_QC_OFF_LSB
) |
586 (la_off
<< XSDFEC_REG3_LA_OFF_LSB
) | sc_off
);
587 if (XSDFEC_LDPC_CODE_REG3_ADDR_BASE
+ (offset
* XSDFEC_LDPC_REG_JUMP
) >
588 XSDFEC_LDPC_CODE_REG3_ADDR_HIGH
) {
589 dev_dbg(xsdfec
->dev
, "Writing outside of LDPC reg3 space 0x%x",
590 XSDFEC_LDPC_CODE_REG3_ADDR_BASE
+
591 (offset
* XSDFEC_LDPC_REG_JUMP
));
594 xsdfec_regwrite(xsdfec
,
595 XSDFEC_LDPC_CODE_REG3_ADDR_BASE
+
596 (offset
* XSDFEC_LDPC_REG_JUMP
),
601 static int xsdfec_table_write(struct xsdfec_dev
*xsdfec
, u32 offset
,
602 u32
*src_ptr
, u32 len
, const u32 base_addr
,
606 int res
, i
, nr_pages
;
609 struct page
*pages
[MAX_NUM_PAGES
];
612 * Writes that go beyond the length of
613 * Shared Scale(SC) table should fail
615 if (offset
> depth
/ XSDFEC_REG_WIDTH_JUMP
||
616 len
> depth
/ XSDFEC_REG_WIDTH_JUMP
||
617 offset
+ len
> depth
/ XSDFEC_REG_WIDTH_JUMP
) {
618 dev_dbg(xsdfec
->dev
, "Write exceeds SC table length");
622 n
= (len
* XSDFEC_REG_WIDTH_JUMP
) / PAGE_SIZE
;
623 if ((len
* XSDFEC_REG_WIDTH_JUMP
) % PAGE_SIZE
)
626 if (WARN_ON_ONCE(n
> INT_MAX
))
631 res
= pin_user_pages_fast((unsigned long)src_ptr
, nr_pages
, 0, pages
);
632 if (res
< nr_pages
) {
634 unpin_user_pages(pages
, res
);
639 for (i
= 0; i
< nr_pages
; i
++) {
640 addr
= kmap_local_page(pages
[i
]);
642 xsdfec_regwrite(xsdfec
,
643 base_addr
+ ((offset
+ reg
) *
644 XSDFEC_REG_WIDTH_JUMP
),
647 } while ((reg
< len
) &&
648 ((reg
* XSDFEC_REG_WIDTH_JUMP
) % PAGE_SIZE
));
650 unpin_user_page(pages
[i
]);
655 static int xsdfec_add_ldpc(struct xsdfec_dev
*xsdfec
, void __user
*arg
)
657 struct xsdfec_ldpc_params
*ldpc
;
660 ldpc
= memdup_user(arg
, sizeof(*ldpc
));
662 return PTR_ERR(ldpc
);
664 if (xsdfec
->config
.code
== XSDFEC_TURBO_CODE
) {
669 /* Verify Device has not started */
670 if (xsdfec
->state
== XSDFEC_STARTED
) {
675 if (xsdfec
->config
.code_wr_protect
) {
681 ret
= xsdfec_reg0_write(xsdfec
, ldpc
->n
, ldpc
->k
, ldpc
->psize
,
687 ret
= xsdfec_reg1_write(xsdfec
, ldpc
->psize
, ldpc
->no_packing
, ldpc
->nm
,
693 ret
= xsdfec_reg2_write(xsdfec
, ldpc
->nlayers
, ldpc
->nmqc
,
694 ldpc
->norm_type
, ldpc
->special_qc
,
695 ldpc
->no_final_parity
, ldpc
->max_schedule
,
701 ret
= xsdfec_reg3_write(xsdfec
, ldpc
->sc_off
, ldpc
->la_off
,
702 ldpc
->qc_off
, ldpc
->code_id
);
706 /* Write Shared Codes */
707 n
= ldpc
->nlayers
/ 4;
708 if (ldpc
->nlayers
% 4)
711 ret
= xsdfec_table_write(xsdfec
, ldpc
->sc_off
, ldpc
->sc_table
, n
,
712 XSDFEC_LDPC_SC_TABLE_ADDR_BASE
,
713 XSDFEC_SC_TABLE_DEPTH
);
717 ret
= xsdfec_table_write(xsdfec
, 4 * ldpc
->la_off
, ldpc
->la_table
,
718 ldpc
->nlayers
, XSDFEC_LDPC_LA_TABLE_ADDR_BASE
,
719 XSDFEC_LA_TABLE_DEPTH
);
723 ret
= xsdfec_table_write(xsdfec
, 4 * ldpc
->qc_off
, ldpc
->qc_table
,
724 ldpc
->nqc
, XSDFEC_LDPC_QC_TABLE_ADDR_BASE
,
725 XSDFEC_QC_TABLE_DEPTH
);
731 static int xsdfec_set_order(struct xsdfec_dev
*xsdfec
, void __user
*arg
)
734 enum xsdfec_order order
;
737 err
= get_user(order
, (enum xsdfec_order __user
*)arg
);
741 order_invalid
= (order
!= XSDFEC_MAINTAIN_ORDER
) &&
742 (order
!= XSDFEC_OUT_OF_ORDER
);
746 /* Verify Device has not started */
747 if (xsdfec
->state
== XSDFEC_STARTED
)
750 xsdfec_regwrite(xsdfec
, XSDFEC_ORDER_ADDR
, order
);
752 xsdfec
->config
.order
= order
;
757 static int xsdfec_set_bypass(struct xsdfec_dev
*xsdfec
, bool __user
*arg
)
762 err
= get_user(bypass
, arg
);
766 /* Verify Device has not started */
767 if (xsdfec
->state
== XSDFEC_STARTED
)
771 xsdfec_regwrite(xsdfec
, XSDFEC_BYPASS_ADDR
, 1);
773 xsdfec_regwrite(xsdfec
, XSDFEC_BYPASS_ADDR
, 0);
775 xsdfec
->config
.bypass
= bypass
;
780 static int xsdfec_is_active(struct xsdfec_dev
*xsdfec
, bool __user
*arg
)
786 reg_value
= xsdfec_regread(xsdfec
, XSDFEC_ACTIVE_ADDR
);
787 /* using a double ! operator instead of casting */
788 is_active
= !!(reg_value
& XSDFEC_IS_ACTIVITY_SET
);
789 err
= put_user(is_active
, arg
);
797 xsdfec_translate_axis_width_cfg_val(enum xsdfec_axis_width axis_width_cfg
)
799 u32 axis_width_field
= 0;
801 switch (axis_width_cfg
) {
803 axis_width_field
= 0;
806 axis_width_field
= 1;
809 axis_width_field
= 2;
813 return axis_width_field
;
816 static u32
xsdfec_translate_axis_words_cfg_val(enum xsdfec_axis_word_include
819 u32 axis_words_field
= 0;
821 if (axis_word_inc_cfg
== XSDFEC_FIXED_VALUE
||
822 axis_word_inc_cfg
== XSDFEC_IN_BLOCK
)
823 axis_words_field
= 0;
824 else if (axis_word_inc_cfg
== XSDFEC_PER_AXI_TRANSACTION
)
825 axis_words_field
= 1;
827 return axis_words_field
;
830 static int xsdfec_cfg_axi_streams(struct xsdfec_dev
*xsdfec
)
833 u32 dout_words_field
;
834 u32 dout_width_field
;
837 struct xsdfec_config
*config
= &xsdfec
->config
;
839 /* translate config info to register values */
841 xsdfec_translate_axis_words_cfg_val(config
->dout_word_include
);
843 xsdfec_translate_axis_width_cfg_val(config
->dout_width
);
845 xsdfec_translate_axis_words_cfg_val(config
->din_word_include
);
847 xsdfec_translate_axis_width_cfg_val(config
->din_width
);
849 reg_value
= dout_words_field
<< XSDFEC_AXIS_DOUT_WORDS_LSB
;
850 reg_value
|= dout_width_field
<< XSDFEC_AXIS_DOUT_WIDTH_LSB
;
851 reg_value
|= din_words_field
<< XSDFEC_AXIS_DIN_WORDS_LSB
;
852 reg_value
|= din_width_field
<< XSDFEC_AXIS_DIN_WIDTH_LSB
;
854 xsdfec_regwrite(xsdfec
, XSDFEC_AXIS_WIDTH_ADDR
, reg_value
);
859 static int xsdfec_start(struct xsdfec_dev
*xsdfec
)
863 regread
= xsdfec_regread(xsdfec
, XSDFEC_FEC_CODE_ADDR
);
865 if (regread
!= xsdfec
->config
.code
) {
867 "%s SDFEC HW code does not match driver code, reg %d, code %d",
868 __func__
, regread
, xsdfec
->config
.code
);
872 /* Set AXIS enable */
873 xsdfec_regwrite(xsdfec
, XSDFEC_AXIS_ENABLE_ADDR
,
874 XSDFEC_AXIS_ENABLE_MASK
);
876 xsdfec
->state
= XSDFEC_STARTED
;
880 static int xsdfec_stop(struct xsdfec_dev
*xsdfec
)
884 if (xsdfec
->state
!= XSDFEC_STARTED
)
885 dev_dbg(xsdfec
->dev
, "Device not started correctly");
886 /* Disable AXIS_ENABLE Input interfaces only */
887 regread
= xsdfec_regread(xsdfec
, XSDFEC_AXIS_ENABLE_ADDR
);
888 regread
&= (~XSDFEC_AXIS_IN_ENABLE_MASK
);
889 xsdfec_regwrite(xsdfec
, XSDFEC_AXIS_ENABLE_ADDR
, regread
);
891 xsdfec
->state
= XSDFEC_STOPPED
;
895 static int xsdfec_clear_stats(struct xsdfec_dev
*xsdfec
)
897 spin_lock_irqsave(&xsdfec
->error_data_lock
, xsdfec
->flags
);
898 xsdfec
->isr_err_count
= 0;
899 xsdfec
->uecc_count
= 0;
900 xsdfec
->cecc_count
= 0;
901 spin_unlock_irqrestore(&xsdfec
->error_data_lock
, xsdfec
->flags
);
906 static int xsdfec_get_stats(struct xsdfec_dev
*xsdfec
, void __user
*arg
)
909 struct xsdfec_stats user_stats
;
911 spin_lock_irqsave(&xsdfec
->error_data_lock
, xsdfec
->flags
);
912 user_stats
.isr_err_count
= xsdfec
->isr_err_count
;
913 user_stats
.cecc_count
= xsdfec
->cecc_count
;
914 user_stats
.uecc_count
= xsdfec
->uecc_count
;
915 xsdfec
->stats_updated
= false;
916 spin_unlock_irqrestore(&xsdfec
->error_data_lock
, xsdfec
->flags
);
918 err
= copy_to_user(arg
, &user_stats
, sizeof(user_stats
));
925 static int xsdfec_set_default_config(struct xsdfec_dev
*xsdfec
)
927 /* Ensure registers are aligned with core configuration */
928 xsdfec_regwrite(xsdfec
, XSDFEC_FEC_CODE_ADDR
, xsdfec
->config
.code
);
929 xsdfec_cfg_axi_streams(xsdfec
);
930 update_config_from_hw(xsdfec
);
935 static long xsdfec_dev_ioctl(struct file
*fptr
, unsigned int cmd
,
938 struct xsdfec_dev
*xsdfec
;
939 void __user
*arg
= (void __user
*)data
;
942 xsdfec
= container_of(fptr
->private_data
, struct xsdfec_dev
, miscdev
);
944 /* In failed state allow only reset and get status IOCTLs */
945 if (xsdfec
->state
== XSDFEC_NEEDS_RESET
&&
946 (cmd
!= XSDFEC_SET_DEFAULT_CONFIG
&& cmd
!= XSDFEC_GET_STATUS
&&
947 cmd
!= XSDFEC_GET_STATS
&& cmd
!= XSDFEC_CLEAR_STATS
)) {
952 case XSDFEC_START_DEV
:
953 rval
= xsdfec_start(xsdfec
);
955 case XSDFEC_STOP_DEV
:
956 rval
= xsdfec_stop(xsdfec
);
958 case XSDFEC_CLEAR_STATS
:
959 rval
= xsdfec_clear_stats(xsdfec
);
961 case XSDFEC_GET_STATS
:
962 rval
= xsdfec_get_stats(xsdfec
, arg
);
964 case XSDFEC_GET_STATUS
:
965 rval
= xsdfec_get_status(xsdfec
, arg
);
967 case XSDFEC_GET_CONFIG
:
968 rval
= xsdfec_get_config(xsdfec
, arg
);
970 case XSDFEC_SET_DEFAULT_CONFIG
:
971 rval
= xsdfec_set_default_config(xsdfec
);
974 rval
= xsdfec_set_irq(xsdfec
, arg
);
976 case XSDFEC_SET_TURBO
:
977 rval
= xsdfec_set_turbo(xsdfec
, arg
);
979 case XSDFEC_GET_TURBO
:
980 rval
= xsdfec_get_turbo(xsdfec
, arg
);
982 case XSDFEC_ADD_LDPC_CODE_PARAMS
:
983 rval
= xsdfec_add_ldpc(xsdfec
, arg
);
985 case XSDFEC_SET_ORDER
:
986 rval
= xsdfec_set_order(xsdfec
, arg
);
988 case XSDFEC_SET_BYPASS
:
989 rval
= xsdfec_set_bypass(xsdfec
, arg
);
991 case XSDFEC_IS_ACTIVE
:
992 rval
= xsdfec_is_active(xsdfec
, (bool __user
*)arg
);
1001 static __poll_t
xsdfec_poll(struct file
*file
, poll_table
*wait
)
1004 struct xsdfec_dev
*xsdfec
;
1006 xsdfec
= container_of(file
->private_data
, struct xsdfec_dev
, miscdev
);
1008 poll_wait(file
, &xsdfec
->waitq
, wait
);
1010 /* XSDFEC ISR detected an error */
1011 spin_lock_irqsave(&xsdfec
->error_data_lock
, xsdfec
->flags
);
1012 if (xsdfec
->state_updated
)
1013 mask
|= EPOLLIN
| EPOLLPRI
;
1015 if (xsdfec
->stats_updated
)
1016 mask
|= EPOLLIN
| EPOLLRDNORM
;
1017 spin_unlock_irqrestore(&xsdfec
->error_data_lock
, xsdfec
->flags
);
1022 static const struct file_operations xsdfec_fops
= {
1023 .owner
= THIS_MODULE
,
1024 .unlocked_ioctl
= xsdfec_dev_ioctl
,
1025 .poll
= xsdfec_poll
,
1026 .compat_ioctl
= compat_ptr_ioctl
,
1029 static int xsdfec_parse_of(struct xsdfec_dev
*xsdfec
)
1031 struct device
*dev
= xsdfec
->dev
;
1032 struct device_node
*node
= dev
->of_node
;
1034 const char *fec_code
;
1036 u32 din_word_include
;
1038 u32 dout_word_include
;
1040 rval
= of_property_read_string(node
, "xlnx,sdfec-code", &fec_code
);
1044 if (!strcasecmp(fec_code
, "ldpc"))
1045 xsdfec
->config
.code
= XSDFEC_LDPC_CODE
;
1046 else if (!strcasecmp(fec_code
, "turbo"))
1047 xsdfec
->config
.code
= XSDFEC_TURBO_CODE
;
1051 rval
= of_property_read_u32(node
, "xlnx,sdfec-din-words",
1056 if (din_word_include
< XSDFEC_AXIS_WORDS_INCLUDE_MAX
)
1057 xsdfec
->config
.din_word_include
= din_word_include
;
1061 rval
= of_property_read_u32(node
, "xlnx,sdfec-din-width", &din_width
);
1065 switch (din_width
) {
1066 /* Fall through and set for valid values */
1070 xsdfec
->config
.din_width
= din_width
;
1076 rval
= of_property_read_u32(node
, "xlnx,sdfec-dout-words",
1077 &dout_word_include
);
1081 if (dout_word_include
< XSDFEC_AXIS_WORDS_INCLUDE_MAX
)
1082 xsdfec
->config
.dout_word_include
= dout_word_include
;
1086 rval
= of_property_read_u32(node
, "xlnx,sdfec-dout-width", &dout_width
);
1090 switch (dout_width
) {
1091 /* Fall through and set for valid values */
1095 xsdfec
->config
.dout_width
= dout_width
;
1101 /* Write LDPC to CODE Register */
1102 xsdfec_regwrite(xsdfec
, XSDFEC_FEC_CODE_ADDR
, xsdfec
->config
.code
);
1104 xsdfec_cfg_axi_streams(xsdfec
);
1109 static irqreturn_t
xsdfec_irq_thread(int irq
, void *dev_id
)
1111 struct xsdfec_dev
*xsdfec
= dev_id
;
1112 irqreturn_t ret
= IRQ_HANDLED
;
1121 WARN_ON(xsdfec
->irq
!= irq
);
1123 /* Mask Interrupts */
1124 xsdfec_isr_enable(xsdfec
, false);
1125 xsdfec_ecc_isr_enable(xsdfec
, false);
1127 ecc_err
= xsdfec_regread(xsdfec
, XSDFEC_ECC_ISR_ADDR
);
1128 isr_err
= xsdfec_regread(xsdfec
, XSDFEC_ISR_ADDR
);
1129 /* Clear the interrupts */
1130 xsdfec_regwrite(xsdfec
, XSDFEC_ECC_ISR_ADDR
, ecc_err
);
1131 xsdfec_regwrite(xsdfec
, XSDFEC_ISR_ADDR
, isr_err
);
1133 tmp
= ecc_err
& XSDFEC_ALL_ECC_ISR_MBE_MASK
;
1134 /* Count uncorrectable 2-bit errors */
1135 uecc_count
= hweight32(tmp
);
1136 /* Count all ECC errors */
1137 aecc_count
= hweight32(ecc_err
);
1138 /* Number of correctable 1-bit ECC error */
1139 cecc_count
= aecc_count
- 2 * uecc_count
;
1140 /* Count ISR errors */
1141 isr_err_count
= hweight32(isr_err
);
1142 dev_dbg(xsdfec
->dev
, "tmp=%x, uecc=%x, aecc=%x, cecc=%x, isr=%x", tmp
,
1143 uecc_count
, aecc_count
, cecc_count
, isr_err_count
);
1144 dev_dbg(xsdfec
->dev
, "uecc=%x, cecc=%x, isr=%x", xsdfec
->uecc_count
,
1145 xsdfec
->cecc_count
, xsdfec
->isr_err_count
);
1147 spin_lock_irqsave(&xsdfec
->error_data_lock
, xsdfec
->flags
);
1148 /* Add new errors to a 2-bits counter */
1150 xsdfec
->uecc_count
+= uecc_count
;
1151 /* Add new errors to a 1-bits counter */
1153 xsdfec
->cecc_count
+= cecc_count
;
1154 /* Add new errors to a ISR counter */
1156 xsdfec
->isr_err_count
+= isr_err_count
;
1158 /* Update state/stats flag */
1160 if (ecc_err
& XSDFEC_ECC_ISR_MBE_MASK
)
1161 xsdfec
->state
= XSDFEC_NEEDS_RESET
;
1162 else if (ecc_err
& XSDFEC_PL_INIT_ECC_ISR_MBE_MASK
)
1163 xsdfec
->state
= XSDFEC_PL_RECONFIGURE
;
1164 xsdfec
->stats_updated
= true;
1165 xsdfec
->state_updated
= true;
1169 xsdfec
->stats_updated
= true;
1171 if (isr_err_count
) {
1172 xsdfec
->state
= XSDFEC_NEEDS_RESET
;
1173 xsdfec
->stats_updated
= true;
1174 xsdfec
->state_updated
= true;
1177 spin_unlock_irqrestore(&xsdfec
->error_data_lock
, xsdfec
->flags
);
1178 dev_dbg(xsdfec
->dev
, "state=%x, stats=%x", xsdfec
->state_updated
,
1179 xsdfec
->stats_updated
);
1181 /* Enable another polling */
1182 if (xsdfec
->state_updated
|| xsdfec
->stats_updated
)
1183 wake_up_interruptible(&xsdfec
->waitq
);
1187 /* Unmask Interrupts */
1188 xsdfec_isr_enable(xsdfec
, true);
1189 xsdfec_ecc_isr_enable(xsdfec
, true);
1194 static int xsdfec_clk_init(struct platform_device
*pdev
,
1195 struct xsdfec_clks
*clks
)
1199 clks
->core_clk
= devm_clk_get(&pdev
->dev
, "core_clk");
1200 if (IS_ERR(clks
->core_clk
)) {
1201 dev_err(&pdev
->dev
, "failed to get core_clk");
1202 return PTR_ERR(clks
->core_clk
);
1205 clks
->axi_clk
= devm_clk_get(&pdev
->dev
, "s_axi_aclk");
1206 if (IS_ERR(clks
->axi_clk
)) {
1207 dev_err(&pdev
->dev
, "failed to get axi_clk");
1208 return PTR_ERR(clks
->axi_clk
);
1211 clks
->din_words_clk
= devm_clk_get(&pdev
->dev
, "s_axis_din_words_aclk");
1212 if (IS_ERR(clks
->din_words_clk
)) {
1213 if (PTR_ERR(clks
->din_words_clk
) != -ENOENT
) {
1214 err
= PTR_ERR(clks
->din_words_clk
);
1217 clks
->din_words_clk
= NULL
;
1220 clks
->din_clk
= devm_clk_get(&pdev
->dev
, "s_axis_din_aclk");
1221 if (IS_ERR(clks
->din_clk
)) {
1222 if (PTR_ERR(clks
->din_clk
) != -ENOENT
) {
1223 err
= PTR_ERR(clks
->din_clk
);
1226 clks
->din_clk
= NULL
;
1229 clks
->dout_clk
= devm_clk_get(&pdev
->dev
, "m_axis_dout_aclk");
1230 if (IS_ERR(clks
->dout_clk
)) {
1231 if (PTR_ERR(clks
->dout_clk
) != -ENOENT
) {
1232 err
= PTR_ERR(clks
->dout_clk
);
1235 clks
->dout_clk
= NULL
;
1238 clks
->dout_words_clk
=
1239 devm_clk_get(&pdev
->dev
, "s_axis_dout_words_aclk");
1240 if (IS_ERR(clks
->dout_words_clk
)) {
1241 if (PTR_ERR(clks
->dout_words_clk
) != -ENOENT
) {
1242 err
= PTR_ERR(clks
->dout_words_clk
);
1245 clks
->dout_words_clk
= NULL
;
1248 clks
->ctrl_clk
= devm_clk_get(&pdev
->dev
, "s_axis_ctrl_aclk");
1249 if (IS_ERR(clks
->ctrl_clk
)) {
1250 if (PTR_ERR(clks
->ctrl_clk
) != -ENOENT
) {
1251 err
= PTR_ERR(clks
->ctrl_clk
);
1254 clks
->ctrl_clk
= NULL
;
1257 clks
->status_clk
= devm_clk_get(&pdev
->dev
, "m_axis_status_aclk");
1258 if (IS_ERR(clks
->status_clk
)) {
1259 if (PTR_ERR(clks
->status_clk
) != -ENOENT
) {
1260 err
= PTR_ERR(clks
->status_clk
);
1263 clks
->status_clk
= NULL
;
1266 err
= clk_prepare_enable(clks
->core_clk
);
1268 dev_err(&pdev
->dev
, "failed to enable core_clk (%d)", err
);
1272 err
= clk_prepare_enable(clks
->axi_clk
);
1274 dev_err(&pdev
->dev
, "failed to enable axi_clk (%d)", err
);
1275 goto err_disable_core_clk
;
1278 err
= clk_prepare_enable(clks
->din_clk
);
1280 dev_err(&pdev
->dev
, "failed to enable din_clk (%d)", err
);
1281 goto err_disable_axi_clk
;
1284 err
= clk_prepare_enable(clks
->din_words_clk
);
1286 dev_err(&pdev
->dev
, "failed to enable din_words_clk (%d)", err
);
1287 goto err_disable_din_clk
;
1290 err
= clk_prepare_enable(clks
->dout_clk
);
1292 dev_err(&pdev
->dev
, "failed to enable dout_clk (%d)", err
);
1293 goto err_disable_din_words_clk
;
1296 err
= clk_prepare_enable(clks
->dout_words_clk
);
1298 dev_err(&pdev
->dev
, "failed to enable dout_words_clk (%d)",
1300 goto err_disable_dout_clk
;
1303 err
= clk_prepare_enable(clks
->ctrl_clk
);
1305 dev_err(&pdev
->dev
, "failed to enable ctrl_clk (%d)", err
);
1306 goto err_disable_dout_words_clk
;
1309 err
= clk_prepare_enable(clks
->status_clk
);
1311 dev_err(&pdev
->dev
, "failed to enable status_clk (%d)\n", err
);
1312 goto err_disable_ctrl_clk
;
1317 err_disable_ctrl_clk
:
1318 clk_disable_unprepare(clks
->ctrl_clk
);
1319 err_disable_dout_words_clk
:
1320 clk_disable_unprepare(clks
->dout_words_clk
);
1321 err_disable_dout_clk
:
1322 clk_disable_unprepare(clks
->dout_clk
);
1323 err_disable_din_words_clk
:
1324 clk_disable_unprepare(clks
->din_words_clk
);
1325 err_disable_din_clk
:
1326 clk_disable_unprepare(clks
->din_clk
);
1327 err_disable_axi_clk
:
1328 clk_disable_unprepare(clks
->axi_clk
);
1329 err_disable_core_clk
:
1330 clk_disable_unprepare(clks
->core_clk
);
1335 static void xsdfec_disable_all_clks(struct xsdfec_clks
*clks
)
1337 clk_disable_unprepare(clks
->status_clk
);
1338 clk_disable_unprepare(clks
->ctrl_clk
);
1339 clk_disable_unprepare(clks
->dout_words_clk
);
1340 clk_disable_unprepare(clks
->dout_clk
);
1341 clk_disable_unprepare(clks
->din_words_clk
);
1342 clk_disable_unprepare(clks
->din_clk
);
1343 clk_disable_unprepare(clks
->core_clk
);
1344 clk_disable_unprepare(clks
->axi_clk
);
1347 static int xsdfec_probe(struct platform_device
*pdev
)
1349 struct xsdfec_dev
*xsdfec
;
1352 bool irq_enabled
= true;
1354 xsdfec
= devm_kzalloc(&pdev
->dev
, sizeof(*xsdfec
), GFP_KERNEL
);
1358 xsdfec
->dev
= &pdev
->dev
;
1359 spin_lock_init(&xsdfec
->error_data_lock
);
1361 err
= xsdfec_clk_init(pdev
, &xsdfec
->clks
);
1366 xsdfec
->regs
= devm_platform_ioremap_resource(pdev
, 0);
1367 if (IS_ERR(xsdfec
->regs
)) {
1368 err
= PTR_ERR(xsdfec
->regs
);
1369 goto err_xsdfec_dev
;
1372 xsdfec
->irq
= platform_get_irq(pdev
, 0);
1373 if (xsdfec
->irq
< 0) {
1374 dev_dbg(dev
, "platform_get_irq failed");
1375 irq_enabled
= false;
1378 err
= xsdfec_parse_of(xsdfec
);
1380 goto err_xsdfec_dev
;
1382 update_config_from_hw(xsdfec
);
1384 /* Save driver private data */
1385 platform_set_drvdata(pdev
, xsdfec
);
1388 init_waitqueue_head(&xsdfec
->waitq
);
1389 /* Register IRQ thread */
1390 err
= devm_request_threaded_irq(dev
, xsdfec
->irq
, NULL
,
1391 xsdfec_irq_thread
, IRQF_ONESHOT
,
1392 "xilinx-sdfec16", xsdfec
);
1394 dev_err(dev
, "unable to request IRQ%d", xsdfec
->irq
);
1395 goto err_xsdfec_dev
;
1399 err
= ida_alloc(&dev_nrs
, GFP_KERNEL
);
1401 goto err_xsdfec_dev
;
1402 xsdfec
->dev_id
= err
;
1404 snprintf(xsdfec
->dev_name
, DEV_NAME_LEN
, "xsdfec%d", xsdfec
->dev_id
);
1405 xsdfec
->miscdev
.minor
= MISC_DYNAMIC_MINOR
;
1406 xsdfec
->miscdev
.name
= xsdfec
->dev_name
;
1407 xsdfec
->miscdev
.fops
= &xsdfec_fops
;
1408 xsdfec
->miscdev
.parent
= dev
;
1409 err
= misc_register(&xsdfec
->miscdev
);
1411 dev_err(dev
, "error:%d. Unable to register device", err
);
1412 goto err_xsdfec_ida
;
1417 ida_free(&dev_nrs
, xsdfec
->dev_id
);
1419 xsdfec_disable_all_clks(&xsdfec
->clks
);
1423 static void xsdfec_remove(struct platform_device
*pdev
)
1425 struct xsdfec_dev
*xsdfec
;
1427 xsdfec
= platform_get_drvdata(pdev
);
1428 misc_deregister(&xsdfec
->miscdev
);
1429 ida_free(&dev_nrs
, xsdfec
->dev_id
);
1430 xsdfec_disable_all_clks(&xsdfec
->clks
);
1433 static const struct of_device_id xsdfec_of_match
[] = {
1435 .compatible
= "xlnx,sd-fec-1.1",
1437 { /* end of table */ }
1439 MODULE_DEVICE_TABLE(of
, xsdfec_of_match
);
1441 static struct platform_driver xsdfec_driver
= {
1443 .name
= "xilinx-sdfec",
1444 .of_match_table
= xsdfec_of_match
,
1446 .probe
= xsdfec_probe
,
1447 .remove_new
= xsdfec_remove
,
1450 module_platform_driver(xsdfec_driver
);
1452 MODULE_AUTHOR("Xilinx, Inc");
1453 MODULE_DESCRIPTION("Xilinx SD-FEC16 Driver");
1454 MODULE_LICENSE("GPL");