Lines Matching refs:xsdfec

235 static inline void xsdfec_regwrite(struct xsdfec_dev *xsdfec, u32 addr,  in xsdfec_regwrite()  argument
238 dev_dbg(xsdfec->dev, "Writing 0x%x to offset 0x%x", value, addr); in xsdfec_regwrite()
239 iowrite32(value, xsdfec->regs + addr); in xsdfec_regwrite()
242 static inline u32 xsdfec_regread(struct xsdfec_dev *xsdfec, u32 addr) in xsdfec_regread() argument
246 rval = ioread32(xsdfec->regs + addr); in xsdfec_regread()
247 dev_dbg(xsdfec->dev, "Read value = 0x%x from offset 0x%x", rval, addr); in xsdfec_regread()
251 static void update_bool_config_from_reg(struct xsdfec_dev *xsdfec, in update_bool_config_from_reg() argument
258 reg_val = xsdfec_regread(xsdfec, reg_offset); in update_bool_config_from_reg()
262 static void update_config_from_hw(struct xsdfec_dev *xsdfec) in update_config_from_hw() argument
268 reg_value = xsdfec_regread(xsdfec, XSDFEC_ORDER_ADDR); in update_config_from_hw()
269 xsdfec->config.order = reg_value; in update_config_from_hw()
271 update_bool_config_from_reg(xsdfec, XSDFEC_BYPASS_ADDR, in update_config_from_hw()
273 &xsdfec->config.bypass); in update_config_from_hw()
275 update_bool_config_from_reg(xsdfec, XSDFEC_CODE_WR_PROTECT_ADDR, in update_config_from_hw()
277 &xsdfec->config.code_wr_protect); in update_config_from_hw()
279 reg_value = xsdfec_regread(xsdfec, XSDFEC_IMR_ADDR); in update_config_from_hw()
280 xsdfec->config.irq.enable_isr = (reg_value & XSDFEC_ISR_MASK) > 0; in update_config_from_hw()
282 reg_value = xsdfec_regread(xsdfec, XSDFEC_ECC_IMR_ADDR); in update_config_from_hw()
283 xsdfec->config.irq.enable_ecc_isr = in update_config_from_hw()
286 reg_value = xsdfec_regread(xsdfec, XSDFEC_AXIS_ENABLE_ADDR); in update_config_from_hw()
289 xsdfec->state = XSDFEC_STARTED; in update_config_from_hw()
291 xsdfec->state = XSDFEC_STOPPED; in update_config_from_hw()
294 static int xsdfec_get_status(struct xsdfec_dev *xsdfec, void __user *arg) in xsdfec_get_status() argument
300 spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags); in xsdfec_get_status()
301 status.state = xsdfec->state; in xsdfec_get_status()
302 xsdfec->state_updated = false; in xsdfec_get_status()
303 spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags); in xsdfec_get_status()
304 status.activity = (xsdfec_regread(xsdfec, XSDFEC_ACTIVE_ADDR) & in xsdfec_get_status()
314 static int xsdfec_get_config(struct xsdfec_dev *xsdfec, void __user *arg) in xsdfec_get_config() argument
318 err = copy_to_user(arg, &xsdfec->config, sizeof(xsdfec->config)); in xsdfec_get_config()
325 static int xsdfec_isr_enable(struct xsdfec_dev *xsdfec, bool enable) in xsdfec_isr_enable() argument
331 xsdfec_regwrite(xsdfec, XSDFEC_IER_ADDR, XSDFEC_ISR_MASK); in xsdfec_isr_enable()
332 mask_read = xsdfec_regread(xsdfec, XSDFEC_IMR_ADDR); in xsdfec_isr_enable()
334 dev_dbg(xsdfec->dev, in xsdfec_isr_enable()
340 xsdfec_regwrite(xsdfec, XSDFEC_IDR_ADDR, XSDFEC_ISR_MASK); in xsdfec_isr_enable()
341 mask_read = xsdfec_regread(xsdfec, XSDFEC_IMR_ADDR); in xsdfec_isr_enable()
343 dev_dbg(xsdfec->dev, in xsdfec_isr_enable()
351 static int xsdfec_ecc_isr_enable(struct xsdfec_dev *xsdfec, bool enable) in xsdfec_ecc_isr_enable() argument
357 xsdfec_regwrite(xsdfec, XSDFEC_ECC_IER_ADDR, in xsdfec_ecc_isr_enable()
359 mask_read = xsdfec_regread(xsdfec, XSDFEC_ECC_IMR_ADDR); in xsdfec_ecc_isr_enable()
361 dev_dbg(xsdfec->dev, in xsdfec_ecc_isr_enable()
367 xsdfec_regwrite(xsdfec, XSDFEC_ECC_IDR_ADDR, in xsdfec_ecc_isr_enable()
369 mask_read = xsdfec_regread(xsdfec, XSDFEC_ECC_IMR_ADDR); in xsdfec_ecc_isr_enable()
374 dev_dbg(xsdfec->dev, in xsdfec_ecc_isr_enable()
382 static int xsdfec_set_irq(struct xsdfec_dev *xsdfec, void __user *arg) in xsdfec_set_irq() argument
394 isr_err = xsdfec_isr_enable(xsdfec, irq.enable_isr); in xsdfec_set_irq()
396 xsdfec->config.irq.enable_isr = irq.enable_isr; in xsdfec_set_irq()
399 ecc_err = xsdfec_ecc_isr_enable(xsdfec, irq.enable_ecc_isr); in xsdfec_set_irq()
401 xsdfec->config.irq.enable_ecc_isr = irq.enable_ecc_isr; in xsdfec_set_irq()
409 static int xsdfec_set_turbo(struct xsdfec_dev *xsdfec, void __user *arg) in xsdfec_set_turbo() argument
426 if (xsdfec->config.code == XSDFEC_LDPC_CODE) in xsdfec_set_turbo()
432 xsdfec_regwrite(xsdfec, XSDFEC_TURBO_ADDR, turbo_write); in xsdfec_set_turbo()
436 static int xsdfec_get_turbo(struct xsdfec_dev *xsdfec, void __user *arg) in xsdfec_get_turbo() argument
442 if (xsdfec->config.code == XSDFEC_LDPC_CODE) in xsdfec_get_turbo()
446 reg_value = xsdfec_regread(xsdfec, XSDFEC_TURBO_ADDR); in xsdfec_get_turbo()
459 static int xsdfec_reg0_write(struct xsdfec_dev *xsdfec, u32 n, u32 k, u32 psize, in xsdfec_reg0_write() argument
466 dev_dbg(xsdfec->dev, "N value is not in range"); in xsdfec_reg0_write()
473 dev_dbg(xsdfec->dev, "K value is not in range"); in xsdfec_reg0_write()
481 dev_dbg(xsdfec->dev, "Writing outside of LDPC reg0 space 0x%x", in xsdfec_reg0_write()
486 xsdfec_regwrite(xsdfec, in xsdfec_reg0_write()
493 static int xsdfec_reg1_write(struct xsdfec_dev *xsdfec, u32 psize, in xsdfec_reg1_write() argument
499 dev_dbg(xsdfec->dev, "Psize is not in range"); in xsdfec_reg1_write()
504 dev_dbg(xsdfec->dev, "No-packing bit register invalid"); in xsdfec_reg1_write()
509 dev_dbg(xsdfec->dev, "NM is beyond 10 bits"); in xsdfec_reg1_write()
515 dev_dbg(xsdfec->dev, "Writing outside of LDPC reg1 space 0x%x", in xsdfec_reg1_write()
520 xsdfec_regwrite(xsdfec, in xsdfec_reg1_write()
527 static int xsdfec_reg2_write(struct xsdfec_dev *xsdfec, u32 nlayers, u32 nmqc, in xsdfec_reg2_write() argument
535 dev_dbg(xsdfec->dev, "Nlayers is not in range"); in xsdfec_reg2_write()
540 dev_dbg(xsdfec->dev, "NMQC exceeds 11 bits"); in xsdfec_reg2_write()
544 dev_dbg(xsdfec->dev, "Norm type is invalid"); in xsdfec_reg2_write()
548 dev_dbg(xsdfec->dev, "Special QC in invalid"); in xsdfec_reg2_write()
553 dev_dbg(xsdfec->dev, "No final parity check invalid"); in xsdfec_reg2_write()
559 dev_dbg(xsdfec->dev, "Max Schedule exceeds 2 bits"); in xsdfec_reg2_write()
568 dev_dbg(xsdfec->dev, "Writing outside of LDPC reg2 space 0x%x", in xsdfec_reg2_write()
573 xsdfec_regwrite(xsdfec, in xsdfec_reg2_write()
580 static int xsdfec_reg3_write(struct xsdfec_dev *xsdfec, u8 sc_off, u8 la_off, in xsdfec_reg3_write() argument
589 dev_dbg(xsdfec->dev, "Writing outside of LDPC reg3 space 0x%x", in xsdfec_reg3_write()
594 xsdfec_regwrite(xsdfec, in xsdfec_reg3_write()
601 static int xsdfec_table_write(struct xsdfec_dev *xsdfec, u32 offset, in xsdfec_table_write() argument
618 dev_dbg(xsdfec->dev, "Write exceeds SC table length"); in xsdfec_table_write()
642 xsdfec_regwrite(xsdfec, in xsdfec_table_write()
655 static int xsdfec_add_ldpc(struct xsdfec_dev *xsdfec, void __user *arg) in xsdfec_add_ldpc() argument
664 if (xsdfec->config.code == XSDFEC_TURBO_CODE) { in xsdfec_add_ldpc()
670 if (xsdfec->state == XSDFEC_STARTED) { in xsdfec_add_ldpc()
675 if (xsdfec->config.code_wr_protect) { in xsdfec_add_ldpc()
681 ret = xsdfec_reg0_write(xsdfec, ldpc->n, ldpc->k, ldpc->psize, in xsdfec_add_ldpc()
687 ret = xsdfec_reg1_write(xsdfec, ldpc->psize, ldpc->no_packing, ldpc->nm, in xsdfec_add_ldpc()
693 ret = xsdfec_reg2_write(xsdfec, ldpc->nlayers, ldpc->nmqc, in xsdfec_add_ldpc()
701 ret = xsdfec_reg3_write(xsdfec, ldpc->sc_off, ldpc->la_off, in xsdfec_add_ldpc()
711 ret = xsdfec_table_write(xsdfec, ldpc->sc_off, ldpc->sc_table, n, in xsdfec_add_ldpc()
717 ret = xsdfec_table_write(xsdfec, 4 * ldpc->la_off, ldpc->la_table, in xsdfec_add_ldpc()
723 ret = xsdfec_table_write(xsdfec, 4 * ldpc->qc_off, ldpc->qc_table, in xsdfec_add_ldpc()
731 static int xsdfec_set_order(struct xsdfec_dev *xsdfec, void __user *arg) in xsdfec_set_order() argument
747 if (xsdfec->state == XSDFEC_STARTED) in xsdfec_set_order()
750 xsdfec_regwrite(xsdfec, XSDFEC_ORDER_ADDR, order); in xsdfec_set_order()
752 xsdfec->config.order = order; in xsdfec_set_order()
757 static int xsdfec_set_bypass(struct xsdfec_dev *xsdfec, bool __user *arg) in xsdfec_set_bypass() argument
767 if (xsdfec->state == XSDFEC_STARTED) in xsdfec_set_bypass()
771 xsdfec_regwrite(xsdfec, XSDFEC_BYPASS_ADDR, 1); in xsdfec_set_bypass()
773 xsdfec_regwrite(xsdfec, XSDFEC_BYPASS_ADDR, 0); in xsdfec_set_bypass()
775 xsdfec->config.bypass = bypass; in xsdfec_set_bypass()
780 static int xsdfec_is_active(struct xsdfec_dev *xsdfec, bool __user *arg) in xsdfec_is_active() argument
786 reg_value = xsdfec_regread(xsdfec, XSDFEC_ACTIVE_ADDR); in xsdfec_is_active()
830 static int xsdfec_cfg_axi_streams(struct xsdfec_dev *xsdfec) in xsdfec_cfg_axi_streams() argument
837 struct xsdfec_config *config = &xsdfec->config; in xsdfec_cfg_axi_streams()
854 xsdfec_regwrite(xsdfec, XSDFEC_AXIS_WIDTH_ADDR, reg_value); in xsdfec_cfg_axi_streams()
859 static int xsdfec_start(struct xsdfec_dev *xsdfec) in xsdfec_start() argument
863 regread = xsdfec_regread(xsdfec, XSDFEC_FEC_CODE_ADDR); in xsdfec_start()
865 if (regread != xsdfec->config.code) { in xsdfec_start()
866 dev_dbg(xsdfec->dev, in xsdfec_start()
868 __func__, regread, xsdfec->config.code); in xsdfec_start()
873 xsdfec_regwrite(xsdfec, XSDFEC_AXIS_ENABLE_ADDR, in xsdfec_start()
876 xsdfec->state = XSDFEC_STARTED; in xsdfec_start()
880 static int xsdfec_stop(struct xsdfec_dev *xsdfec) in xsdfec_stop() argument
884 if (xsdfec->state != XSDFEC_STARTED) in xsdfec_stop()
885 dev_dbg(xsdfec->dev, "Device not started correctly"); in xsdfec_stop()
887 regread = xsdfec_regread(xsdfec, XSDFEC_AXIS_ENABLE_ADDR); in xsdfec_stop()
889 xsdfec_regwrite(xsdfec, XSDFEC_AXIS_ENABLE_ADDR, regread); in xsdfec_stop()
891 xsdfec->state = XSDFEC_STOPPED; in xsdfec_stop()
895 static int xsdfec_clear_stats(struct xsdfec_dev *xsdfec) in xsdfec_clear_stats() argument
897 spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags); in xsdfec_clear_stats()
898 xsdfec->isr_err_count = 0; in xsdfec_clear_stats()
899 xsdfec->uecc_count = 0; in xsdfec_clear_stats()
900 xsdfec->cecc_count = 0; in xsdfec_clear_stats()
901 spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags); in xsdfec_clear_stats()
906 static int xsdfec_get_stats(struct xsdfec_dev *xsdfec, void __user *arg) in xsdfec_get_stats() argument
911 spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags); in xsdfec_get_stats()
912 user_stats.isr_err_count = xsdfec->isr_err_count; in xsdfec_get_stats()
913 user_stats.cecc_count = xsdfec->cecc_count; in xsdfec_get_stats()
914 user_stats.uecc_count = xsdfec->uecc_count; in xsdfec_get_stats()
915 xsdfec->stats_updated = false; in xsdfec_get_stats()
916 spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags); in xsdfec_get_stats()
925 static int xsdfec_set_default_config(struct xsdfec_dev *xsdfec) in xsdfec_set_default_config() argument
928 xsdfec_regwrite(xsdfec, XSDFEC_FEC_CODE_ADDR, xsdfec->config.code); in xsdfec_set_default_config()
929 xsdfec_cfg_axi_streams(xsdfec); in xsdfec_set_default_config()
930 update_config_from_hw(xsdfec); in xsdfec_set_default_config()
938 struct xsdfec_dev *xsdfec; in xsdfec_dev_ioctl() local
942 xsdfec = container_of(fptr->private_data, struct xsdfec_dev, miscdev); in xsdfec_dev_ioctl()
945 if (xsdfec->state == XSDFEC_NEEDS_RESET && in xsdfec_dev_ioctl()
953 rval = xsdfec_start(xsdfec); in xsdfec_dev_ioctl()
956 rval = xsdfec_stop(xsdfec); in xsdfec_dev_ioctl()
959 rval = xsdfec_clear_stats(xsdfec); in xsdfec_dev_ioctl()
962 rval = xsdfec_get_stats(xsdfec, arg); in xsdfec_dev_ioctl()
965 rval = xsdfec_get_status(xsdfec, arg); in xsdfec_dev_ioctl()
968 rval = xsdfec_get_config(xsdfec, arg); in xsdfec_dev_ioctl()
971 rval = xsdfec_set_default_config(xsdfec); in xsdfec_dev_ioctl()
974 rval = xsdfec_set_irq(xsdfec, arg); in xsdfec_dev_ioctl()
977 rval = xsdfec_set_turbo(xsdfec, arg); in xsdfec_dev_ioctl()
980 rval = xsdfec_get_turbo(xsdfec, arg); in xsdfec_dev_ioctl()
983 rval = xsdfec_add_ldpc(xsdfec, arg); in xsdfec_dev_ioctl()
986 rval = xsdfec_set_order(xsdfec, arg); in xsdfec_dev_ioctl()
989 rval = xsdfec_set_bypass(xsdfec, arg); in xsdfec_dev_ioctl()
992 rval = xsdfec_is_active(xsdfec, (bool __user *)arg); in xsdfec_dev_ioctl()
1004 struct xsdfec_dev *xsdfec; in xsdfec_poll() local
1006 xsdfec = container_of(file->private_data, struct xsdfec_dev, miscdev); in xsdfec_poll()
1008 poll_wait(file, &xsdfec->waitq, wait); in xsdfec_poll()
1011 spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags); in xsdfec_poll()
1012 if (xsdfec->state_updated) in xsdfec_poll()
1015 if (xsdfec->stats_updated) in xsdfec_poll()
1017 spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags); in xsdfec_poll()
1029 static int xsdfec_parse_of(struct xsdfec_dev *xsdfec) in xsdfec_parse_of() argument
1031 struct device *dev = xsdfec->dev; in xsdfec_parse_of()
1045 xsdfec->config.code = XSDFEC_LDPC_CODE; in xsdfec_parse_of()
1047 xsdfec->config.code = XSDFEC_TURBO_CODE; in xsdfec_parse_of()
1057 xsdfec->config.din_word_include = din_word_include; in xsdfec_parse_of()
1070 xsdfec->config.din_width = din_width; in xsdfec_parse_of()
1082 xsdfec->config.dout_word_include = dout_word_include; in xsdfec_parse_of()
1095 xsdfec->config.dout_width = dout_width; in xsdfec_parse_of()
1102 xsdfec_regwrite(xsdfec, XSDFEC_FEC_CODE_ADDR, xsdfec->config.code); in xsdfec_parse_of()
1104 xsdfec_cfg_axi_streams(xsdfec); in xsdfec_parse_of()
1111 struct xsdfec_dev *xsdfec = dev_id; in xsdfec_irq_thread() local
1121 WARN_ON(xsdfec->irq != irq); in xsdfec_irq_thread()
1124 xsdfec_isr_enable(xsdfec, false); in xsdfec_irq_thread()
1125 xsdfec_ecc_isr_enable(xsdfec, false); in xsdfec_irq_thread()
1127 ecc_err = xsdfec_regread(xsdfec, XSDFEC_ECC_ISR_ADDR); in xsdfec_irq_thread()
1128 isr_err = xsdfec_regread(xsdfec, XSDFEC_ISR_ADDR); in xsdfec_irq_thread()
1130 xsdfec_regwrite(xsdfec, XSDFEC_ECC_ISR_ADDR, ecc_err); in xsdfec_irq_thread()
1131 xsdfec_regwrite(xsdfec, XSDFEC_ISR_ADDR, isr_err); in xsdfec_irq_thread()
1142 dev_dbg(xsdfec->dev, "tmp=%x, uecc=%x, aecc=%x, cecc=%x, isr=%x", tmp, in xsdfec_irq_thread()
1144 dev_dbg(xsdfec->dev, "uecc=%x, cecc=%x, isr=%x", xsdfec->uecc_count, in xsdfec_irq_thread()
1145 xsdfec->cecc_count, xsdfec->isr_err_count); in xsdfec_irq_thread()
1147 spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags); in xsdfec_irq_thread()
1150 xsdfec->uecc_count += uecc_count; in xsdfec_irq_thread()
1153 xsdfec->cecc_count += cecc_count; in xsdfec_irq_thread()
1156 xsdfec->isr_err_count += isr_err_count; in xsdfec_irq_thread()
1161 xsdfec->state = XSDFEC_NEEDS_RESET; in xsdfec_irq_thread()
1163 xsdfec->state = XSDFEC_PL_RECONFIGURE; in xsdfec_irq_thread()
1164 xsdfec->stats_updated = true; in xsdfec_irq_thread()
1165 xsdfec->state_updated = true; in xsdfec_irq_thread()
1169 xsdfec->stats_updated = true; in xsdfec_irq_thread()
1172 xsdfec->state = XSDFEC_NEEDS_RESET; in xsdfec_irq_thread()
1173 xsdfec->stats_updated = true; in xsdfec_irq_thread()
1174 xsdfec->state_updated = true; in xsdfec_irq_thread()
1177 spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags); in xsdfec_irq_thread()
1178 dev_dbg(xsdfec->dev, "state=%x, stats=%x", xsdfec->state_updated, in xsdfec_irq_thread()
1179 xsdfec->stats_updated); in xsdfec_irq_thread()
1182 if (xsdfec->state_updated || xsdfec->stats_updated) in xsdfec_irq_thread()
1183 wake_up_interruptible(&xsdfec->waitq); in xsdfec_irq_thread()
1188 xsdfec_isr_enable(xsdfec, true); in xsdfec_irq_thread()
1189 xsdfec_ecc_isr_enable(xsdfec, true); in xsdfec_irq_thread()
1349 struct xsdfec_dev *xsdfec; in xsdfec_probe() local
1354 xsdfec = devm_kzalloc(&pdev->dev, sizeof(*xsdfec), GFP_KERNEL); in xsdfec_probe()
1355 if (!xsdfec) in xsdfec_probe()
1358 xsdfec->dev = &pdev->dev; in xsdfec_probe()
1359 spin_lock_init(&xsdfec->error_data_lock); in xsdfec_probe()
1361 err = xsdfec_clk_init(pdev, &xsdfec->clks); in xsdfec_probe()
1365 dev = xsdfec->dev; in xsdfec_probe()
1366 xsdfec->regs = devm_platform_ioremap_resource(pdev, 0); in xsdfec_probe()
1367 if (IS_ERR(xsdfec->regs)) { in xsdfec_probe()
1368 err = PTR_ERR(xsdfec->regs); in xsdfec_probe()
1372 xsdfec->irq = platform_get_irq(pdev, 0); in xsdfec_probe()
1373 if (xsdfec->irq < 0) { in xsdfec_probe()
1378 err = xsdfec_parse_of(xsdfec); in xsdfec_probe()
1382 update_config_from_hw(xsdfec); in xsdfec_probe()
1385 platform_set_drvdata(pdev, xsdfec); in xsdfec_probe()
1388 init_waitqueue_head(&xsdfec->waitq); in xsdfec_probe()
1390 err = devm_request_threaded_irq(dev, xsdfec->irq, NULL, in xsdfec_probe()
1392 "xilinx-sdfec16", xsdfec); in xsdfec_probe()
1394 dev_err(dev, "unable to request IRQ%d", xsdfec->irq); in xsdfec_probe()
1402 xsdfec->dev_id = err; in xsdfec_probe()
1404 snprintf(xsdfec->dev_name, DEV_NAME_LEN, "xsdfec%d", xsdfec->dev_id); in xsdfec_probe()
1405 xsdfec->miscdev.minor = MISC_DYNAMIC_MINOR; in xsdfec_probe()
1406 xsdfec->miscdev.name = xsdfec->dev_name; in xsdfec_probe()
1407 xsdfec->miscdev.fops = &xsdfec_fops; in xsdfec_probe()
1408 xsdfec->miscdev.parent = dev; in xsdfec_probe()
1409 err = misc_register(&xsdfec->miscdev); in xsdfec_probe()
1417 ida_free(&dev_nrs, xsdfec->dev_id); in xsdfec_probe()
1419 xsdfec_disable_all_clks(&xsdfec->clks); in xsdfec_probe()
1425 struct xsdfec_dev *xsdfec; in xsdfec_remove() local
1427 xsdfec = platform_get_drvdata(pdev); in xsdfec_remove()
1428 misc_deregister(&xsdfec->miscdev); in xsdfec_remove()
1429 ida_free(&dev_nrs, xsdfec->dev_id); in xsdfec_remove()
1430 xsdfec_disable_all_clks(&xsdfec->clks); in xsdfec_remove()