From 45d5bb196d8cafd19b32f186bc5660c482df9b1a Mon Sep 17 00:00:00 2001 From: JefferyLim Date: Thu, 30 Apr 2026 14:16:51 -0400 Subject: [PATCH 1/7] Fixing the OS4C repository --- LICENSE | 1 + fpga/common/rtl/mqnic_core_pcie.v | 6 +- fpga/common/rtl/mqnic_interface.v | 19 +- fpga/common/rtl/queue_manager.v | 2 +- fpga/lib/axi/rtl/axil_reg_if.v | 14 + fpga/lib/axi/rtl/axil_reg_if_rd.v | 13 + fpga/lib/axi/rtl/axil_reg_if_wr.v | 12 + fpga/lib/pcie/rtl/pcie_msix.v | 6 +- .../mqnic/Alveo/fpga_100g/fpga_AU250/Makefile | 192 ++ .../Alveo/fpga_100g/fpga_AU250/config.tcl | 255 ++ fpga/mqnic/Alveo/fpga_100g/fpga_AU50/Makefile | 193 ++ .../Alveo/fpga_100g/fpga_AU50/config.tcl | 255 ++ fpga/mqnic/Alveo/fpga_100g/fpga_au200.xdc | 858 ++++++ fpga/mqnic/Alveo/fpga_100g/fpga_au50.xdc | 204 ++ .../fpga_100g/ip/pcie4_uscale_plus_0.tcl | 90 +- .../mqnic/Alveo/fpga_100g/placement_au200.xdc | 36 + .../mqnic/Alveo/fpga_100g/placement_au250.xdc | 40 + fpga/mqnic/Alveo/fpga_100g/placement_au50.xdc | 32 + fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au200.v | 2500 +++++++++++++++++ fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au280.v | 4 +- fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au50.v | 1727 ++++++++++++ lib/mqnic/mqnic.h | 2 + lib/mqnic/mqnic_if.c | 10 +- modules/mqnic/mqnic_dev.c | 15 +- modules/mqnic/mqnic_eq.c | 11 +- modules/mqnic/mqnic_ethtool.c | 34 +- modules/mqnic/mqnic_hw.h | 1 + modules/mqnic/mqnic_if.c | 8 +- modules/mqnic/mqnic_irq.c | 1 + modules/mqnic/mqnic_main.c | 14 +- modules/mqnic/mqnic_netdev.c | 2 + modules/mqnic_vf/.gitignore | 1 + modules/mqnic_vf/Makefile | 1 + modules/mqnic_vf/device-tree-binding.txt | 1 + modules/mqnic_vf/mqnic.h | 648 +++++ modules/mqnic_vf/mqnic_board.c | 1 + modules/mqnic_vf/mqnic_clk_info.c | 1 + modules/mqnic_vf/mqnic_cq.c | 1 + modules/mqnic_vf/mqnic_dev.c | 1 + modules/mqnic_vf/mqnic_devlink.c | 1 + modules/mqnic_vf/mqnic_eq.c | 260 ++ modules/mqnic_vf/mqnic_ethtool.c | 655 +++++ modules/mqnic_vf/mqnic_hw.h | 1 + modules/mqnic_vf/mqnic_i2c.c | 1 + modules/mqnic_vf/mqnic_if.c | 400 +++ modules/mqnic_vf/mqnic_ioctl.h | 1 + modules/mqnic_vf/mqnic_irq.c | 1 + modules/mqnic_vf/mqnic_main.c | 918 ++++++ modules/mqnic_vf/mqnic_netdev.c | 691 +++++ modules/mqnic_vf/mqnic_port.c | 1 + modules/mqnic_vf/mqnic_ptp.c | 1 + modules/mqnic_vf/mqnic_reg_block.c | 1 + modules/mqnic_vf/mqnic_res.c | 1 + modules/mqnic_vf/mqnic_rx.c | 1 + modules/mqnic_vf/mqnic_sched_block.c | 1 + modules/mqnic_vf/mqnic_scheduler.c | 1 + modules/mqnic_vf/mqnic_stats.c | 1 + modules/mqnic_vf/mqnic_tx.c | 1 + utils/.gitignore | 6 + utils/Makefile | 68 + utils/bitfile.c | 155 + utils/bitfile.h | 28 + utils/drp.c | 50 + utils/drp.h | 17 + utils/flash.c | 108 + utils/flash.h | 68 + utils/flash_bpi.c | 643 +++++ utils/flash_spi.c | 576 ++++ utils/include | 1 + utils/lib | 1 + utils/mqnic-bmc.c | 322 +++ utils/mqnic-config.c | 295 ++ utils/mqnic-dump.c | 514 ++++ utils/mqnic-fw.c | 1514 ++++++++++ utils/mqnic-xcvr.c | 414 +++ utils/perout.c | 170 ++ utils/timespec.c | 739 +++++ utils/timespec.h | 65 + utils/xcvr_gt.c | 287 ++ utils/xcvr_gt.h | 154 + utils/xcvr_gthe3.c | 662 +++++ utils/xcvr_gthe3.h | 375 +++ utils/xcvr_gthe4.c | 644 +++++ utils/xcvr_gthe4.h | 383 +++ utils/xcvr_gtye3.c | 785 ++++++ utils/xcvr_gtye3.h | 374 +++ utils/xcvr_gtye4.c | 789 ++++++ utils/xcvr_gtye4.h | 386 +++ 88 files changed, 20680 insertions(+), 63 deletions(-) create mode 100644 fpga/mqnic/Alveo/fpga_100g/fpga_AU250/Makefile create mode 100644 fpga/mqnic/Alveo/fpga_100g/fpga_AU250/config.tcl create mode 100644 fpga/mqnic/Alveo/fpga_100g/fpga_AU50/Makefile create mode 100644 fpga/mqnic/Alveo/fpga_100g/fpga_AU50/config.tcl create mode 100644 fpga/mqnic/Alveo/fpga_100g/fpga_au200.xdc create mode 100644 fpga/mqnic/Alveo/fpga_100g/fpga_au50.xdc create mode 100644 fpga/mqnic/Alveo/fpga_100g/placement_au200.xdc create mode 100644 fpga/mqnic/Alveo/fpga_100g/placement_au250.xdc create mode 100644 fpga/mqnic/Alveo/fpga_100g/placement_au50.xdc create mode 100644 fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au200.v create mode 100644 fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au50.v create mode 120000 modules/mqnic_vf/.gitignore create mode 120000 modules/mqnic_vf/Makefile create mode 120000 modules/mqnic_vf/device-tree-binding.txt create mode 100644 modules/mqnic_vf/mqnic.h create mode 120000 modules/mqnic_vf/mqnic_board.c create mode 120000 modules/mqnic_vf/mqnic_clk_info.c create mode 120000 modules/mqnic_vf/mqnic_cq.c create mode 120000 modules/mqnic_vf/mqnic_dev.c create mode 120000 modules/mqnic_vf/mqnic_devlink.c create mode 100644 modules/mqnic_vf/mqnic_eq.c create mode 100644 modules/mqnic_vf/mqnic_ethtool.c create mode 120000 modules/mqnic_vf/mqnic_hw.h create mode 120000 modules/mqnic_vf/mqnic_i2c.c create mode 100644 modules/mqnic_vf/mqnic_if.c create mode 120000 modules/mqnic_vf/mqnic_ioctl.h create mode 120000 modules/mqnic_vf/mqnic_irq.c create mode 100644 modules/mqnic_vf/mqnic_main.c create mode 100644 modules/mqnic_vf/mqnic_netdev.c create mode 120000 modules/mqnic_vf/mqnic_port.c create mode 120000 modules/mqnic_vf/mqnic_ptp.c create mode 120000 modules/mqnic_vf/mqnic_reg_block.c create mode 120000 modules/mqnic_vf/mqnic_res.c create mode 120000 modules/mqnic_vf/mqnic_rx.c create mode 120000 modules/mqnic_vf/mqnic_sched_block.c create mode 120000 modules/mqnic_vf/mqnic_scheduler.c create mode 120000 modules/mqnic_vf/mqnic_stats.c create mode 120000 modules/mqnic_vf/mqnic_tx.c create mode 100644 utils/.gitignore create mode 100644 utils/Makefile create mode 100644 utils/bitfile.c create mode 100644 utils/bitfile.h create mode 100644 utils/drp.c create mode 100644 utils/drp.h create mode 100644 utils/flash.c create mode 100644 utils/flash.h create mode 100644 utils/flash_bpi.c create mode 100644 utils/flash_spi.c create mode 120000 utils/include create mode 120000 utils/lib create mode 100644 utils/mqnic-bmc.c create mode 100644 utils/mqnic-config.c create mode 100644 utils/mqnic-dump.c create mode 100644 utils/mqnic-fw.c create mode 100644 utils/mqnic-xcvr.c create mode 100644 utils/perout.c create mode 100644 utils/timespec.c create mode 100644 utils/timespec.h create mode 100644 utils/xcvr_gt.c create mode 100644 utils/xcvr_gt.h create mode 100644 utils/xcvr_gthe3.c create mode 100644 utils/xcvr_gthe3.h create mode 100644 utils/xcvr_gthe4.c create mode 100644 utils/xcvr_gthe4.h create mode 100644 utils/xcvr_gtye3.c create mode 100644 utils/xcvr_gtye3.h create mode 100644 utils/xcvr_gtye4.c create mode 100644 utils/xcvr_gtye4.h diff --git a/LICENSE b/LICENSE index 0eedb89..b6cff35 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,4 @@ +Copyright (c) 2026, Jeffery Lim Copyright (c) 2024, Scott Smith Copyright (c) 2019-2023, The Regents of the University of California. All rights reserved. diff --git a/fpga/common/rtl/mqnic_core_pcie.v b/fpga/common/rtl/mqnic_core_pcie.v index 0c40021..b077e49 100644 --- a/fpga/common/rtl/mqnic_core_pcie.v +++ b/fpga/common/rtl/mqnic_core_pcie.v @@ -785,6 +785,7 @@ if (APP_ENABLE) begin : pcie_tlp_mux .fifo_half_full(), .fifo_watermark() ); + pcie_tlp_mux #( .PORTS(2), @@ -1291,13 +1292,12 @@ wire [FUNCTION_ID_WIDTH-1:0] axil_msix_write_function_id; // Scott resource_translator #( - .TOTAL_RESOURCES(2**(FUNCTION_ID_WIDTH + IRQ_INDEX_WIDTH)), + .TOTAL_RESOURCES(2**(FUNCTION_ID_WIDTH + IRQ_INDEX_WIDTH + 1)), .FUNCTION_ID_WIDTH(FUNCTION_ID_WIDTH), - .RESOURCE_BIT_WIDTH(32'd2), // 4-bits per cpl queue + .RESOURCE_BIT_WIDTH(32'd3), // 3-bits per msi-x .AXIL_ADDR_WIDTH(AXIL_MSIX_ADDR_WIDTH) ) pcie_msix_resource_translator ( - .input_write_address(axil_msix_awaddr), .input_write_function_id(axil_msix_awuser), diff --git a/fpga/common/rtl/mqnic_interface.v b/fpga/common/rtl/mqnic_interface.v index eab3947..ba6a283 100644 --- a/fpga/common/rtl/mqnic_interface.v +++ b/fpga/common/rtl/mqnic_interface.v @@ -1031,6 +1031,10 @@ wire [REG_DATA_WIDTH-1:0] ctrl_reg_rd_data; wire ctrl_reg_rd_wait; wire ctrl_reg_rd_ack; +wire [8-1:0] ctrl_reg_wr_user; +wire [8-1:0] ctrl_reg_rd_user; + + axil_reg_if #( .DATA_WIDTH(REG_DATA_WIDTH), .ADDR_WIDTH(REG_ADDR_WIDTH), @@ -1045,7 +1049,7 @@ axil_reg_if_inst ( * AXI-Lite slave interface */ .s_axil_awaddr(axil_ctrl_awaddr), - // .s_axil_awuser(axil_ctrl_awuser), // Scott + .s_axil_awuser(axil_ctrl_awuser), // Scott .s_axil_awprot(axil_ctrl_awprot), .s_axil_awvalid(axil_ctrl_awvalid), .s_axil_awready(axil_ctrl_awready), @@ -1057,7 +1061,7 @@ axil_reg_if_inst ( .s_axil_bvalid(axil_ctrl_bvalid), .s_axil_bready(axil_ctrl_bready), .s_axil_araddr(axil_ctrl_araddr), - // .s_axil_aruser(axil_ctrl_aruser), // Scott + .s_axil_aruser(axil_ctrl_aruser), // Scott .s_axil_arprot(axil_ctrl_arprot), .s_axil_arvalid(axil_ctrl_arvalid), .s_axil_arready(axil_ctrl_arready), @@ -1072,10 +1076,12 @@ axil_reg_if_inst ( .reg_wr_addr(ctrl_reg_wr_addr), .reg_wr_data(ctrl_reg_wr_data), .reg_wr_strb(ctrl_reg_wr_strb), + .reg_wr_user(ctrl_reg_wr_user), .reg_wr_en(ctrl_reg_wr_en), .reg_wr_wait(ctrl_reg_wr_wait), .reg_wr_ack(ctrl_reg_wr_ack), .reg_rd_addr(ctrl_reg_rd_addr), + .reg_rd_user(ctrl_reg_rd_user), .reg_rd_en(ctrl_reg_rd_en), .reg_rd_data(ctrl_reg_rd_data), .reg_rd_wait(ctrl_reg_rd_wait), @@ -1181,6 +1187,7 @@ always @(posedge clk) begin end RBB+8'h10: ctrl_reg_rd_data_reg <= PORTS; // IF ctrl: Port count RBB+8'h14: ctrl_reg_rd_data_reg <= SCHEDULERS; // IF ctrl: Scheduler count + RBB+8'h18: ctrl_reg_rd_data_reg <= ctrl_reg_rd_user; // IF ctrl: Assigned MAC/VF ID RBB+8'h20: ctrl_reg_rd_data_reg <= MAX_TX_SIZE; // IF ctrl: Max TX MTU RBB+8'h24: ctrl_reg_rd_data_reg <= MAX_RX_SIZE; // IF ctrl: Max RX MTU RBB+8'h28: ctrl_reg_rd_data_reg <= tx_mtu_reg; // IF ctrl: TX MTU @@ -2071,8 +2078,8 @@ tx_qm_inst ( /* * AXI-Lite slave interface */ - .s_axil_awaddr(axil_tx_qm_awaddr), - .s_axil_awuser(axil_tx_qm_awuser), // Scott + .s_axil_awaddr(axil_tx_qm_awaddr_translated), + .s_axil_awuser(axil_tx_qm_write_function_id), // Scott .s_axil_awprot(axil_tx_qm_awprot), .s_axil_awvalid(axil_tx_qm_awvalid), .s_axil_awready(axil_tx_qm_awready), @@ -2083,8 +2090,8 @@ tx_qm_inst ( .s_axil_bresp(axil_tx_qm_bresp), .s_axil_bvalid(axil_tx_qm_bvalid), .s_axil_bready(axil_tx_qm_bready), - .s_axil_araddr(axil_tx_qm_araddr), - .s_axil_aruser(axil_tx_qm_aruser), // Scott + .s_axil_araddr(axil_tx_qm_araddr_translated), + .s_axil_aruser(axil_tx_qm_read_function_id), // Scott .s_axil_arprot(axil_tx_qm_arprot), .s_axil_arvalid(axil_tx_qm_arvalid), .s_axil_arready(axil_tx_qm_arready), diff --git a/fpga/common/rtl/queue_manager.v b/fpga/common/rtl/queue_manager.v index 2023330..bce1134 100644 --- a/fpga/common/rtl/queue_manager.v +++ b/fpga/common/rtl/queue_manager.v @@ -519,7 +519,7 @@ always @* begin queue_ram_be[8] = 1'b1; end else begin queue_ram_be[8] = 1'b1; - queue_ram_write_data[71:64] = axil_reg_pipeline_function_id_reg[PIPELINE-1] + queue_ram_write_data[71:64] = axil_reg_pipeline_function_id_reg[PIPELINE-1]; end end 32'h8002zzzz: begin diff --git a/fpga/lib/axi/rtl/axil_reg_if.v b/fpga/lib/axi/rtl/axil_reg_if.v index 8876380..a2b500d 100644 --- a/fpga/lib/axi/rtl/axil_reg_if.v +++ b/fpga/lib/axi/rtl/axil_reg_if.v @@ -39,8 +39,12 @@ module axil_reg_if # parameter ADDR_WIDTH = 32, // Width of wstrb (width of data bus in words) parameter STRB_WIDTH = (DATA_WIDTH/8), + // Width of user bus in bits + parameter USER_WIDTH = 8, + // Timeout delay (cycles) parameter TIMEOUT = 4 + ) ( input wire clk, @@ -52,6 +56,7 @@ module axil_reg_if # input wire [ADDR_WIDTH-1:0] s_axil_awaddr, input wire [2:0] s_axil_awprot, input wire s_axil_awvalid, + input wire [USER_WIDTH-1:0] s_axil_awuser, output wire s_axil_awready, input wire [DATA_WIDTH-1:0] s_axil_wdata, input wire [STRB_WIDTH-1:0] s_axil_wstrb, @@ -62,6 +67,7 @@ module axil_reg_if # input wire s_axil_bready, input wire [ADDR_WIDTH-1:0] s_axil_araddr, input wire [2:0] s_axil_arprot, + input wire [USER_WIDTH-1:0] s_axil_aruser, input wire s_axil_arvalid, output wire s_axil_arready, output wire [DATA_WIDTH-1:0] s_axil_rdata, @@ -74,11 +80,13 @@ module axil_reg_if # */ output wire [ADDR_WIDTH-1:0] reg_wr_addr, output wire [DATA_WIDTH-1:0] reg_wr_data, + output wire [USER_WIDTH-1:0] reg_wr_user, output wire [STRB_WIDTH-1:0] reg_wr_strb, output wire reg_wr_en, input wire reg_wr_wait, input wire reg_wr_ack, output wire [ADDR_WIDTH-1:0] reg_rd_addr, + output wire [USER_WIDTH-1:0] reg_rd_user, output wire reg_rd_en, input wire [DATA_WIDTH-1:0] reg_rd_data, input wire reg_rd_wait, @@ -89,6 +97,7 @@ axil_reg_if_wr #( .DATA_WIDTH(DATA_WIDTH), .ADDR_WIDTH(ADDR_WIDTH), .STRB_WIDTH(STRB_WIDTH), + .USER_WIDTH(USER_WIDTH), .TIMEOUT(TIMEOUT) ) axil_reg_if_wr_inst ( @@ -100,6 +109,7 @@ axil_reg_if_wr_inst ( */ .s_axil_awaddr(s_axil_awaddr), .s_axil_awprot(s_axil_awprot), + .s_axil_awuser(s_axil_awuser), .s_axil_awvalid(s_axil_awvalid), .s_axil_awready(s_axil_awready), .s_axil_wdata(s_axil_wdata), @@ -115,6 +125,7 @@ axil_reg_if_wr_inst ( */ .reg_wr_addr(reg_wr_addr), .reg_wr_data(reg_wr_data), + .reg_wr_user(reg_wr_user), .reg_wr_strb(reg_wr_strb), .reg_wr_en(reg_wr_en), .reg_wr_wait(reg_wr_wait), @@ -125,6 +136,7 @@ axil_reg_if_rd #( .DATA_WIDTH(DATA_WIDTH), .ADDR_WIDTH(ADDR_WIDTH), .STRB_WIDTH(STRB_WIDTH), + .USER_WIDTH(USER_WIDTH), .TIMEOUT(TIMEOUT) ) axil_reg_if_rd_inst ( @@ -136,6 +148,7 @@ axil_reg_if_rd_inst ( */ .s_axil_araddr(s_axil_araddr), .s_axil_arprot(s_axil_arprot), + .s_axil_aruser(s_axil_aruser), .s_axil_arvalid(s_axil_arvalid), .s_axil_arready(s_axil_arready), .s_axil_rdata(s_axil_rdata), @@ -148,6 +161,7 @@ axil_reg_if_rd_inst ( */ .reg_rd_addr(reg_rd_addr), .reg_rd_en(reg_rd_en), + .reg_rd_user(reg_rd_user), .reg_rd_data(reg_rd_data), .reg_rd_wait(reg_rd_wait), .reg_rd_ack(reg_rd_ack) diff --git a/fpga/lib/axi/rtl/axil_reg_if_rd.v b/fpga/lib/axi/rtl/axil_reg_if_rd.v index 89473c0..327785d 100644 --- a/fpga/lib/axi/rtl/axil_reg_if_rd.v +++ b/fpga/lib/axi/rtl/axil_reg_if_rd.v @@ -39,6 +39,8 @@ module axil_reg_if_rd # parameter ADDR_WIDTH = 32, // Width of wstrb (width of data bus in words) parameter STRB_WIDTH = (DATA_WIDTH/8), + // Width of user bus in bits + parameter USER_WIDTH = 8, // Timeout delay (cycles) parameter TIMEOUT = 4 ) @@ -50,6 +52,7 @@ module axil_reg_if_rd # * AXI-Lite slave interface */ input wire [ADDR_WIDTH-1:0] s_axil_araddr, + input wire [USER_WIDTH-1:0] s_axil_aruser, input wire [2:0] s_axil_arprot, input wire s_axil_arvalid, output wire s_axil_arready, @@ -63,6 +66,7 @@ module axil_reg_if_rd # */ output wire [ADDR_WIDTH-1:0] reg_rd_addr, output wire reg_rd_en, + output wire [USER_WIDTH-1:0] reg_rd_user, input wire [DATA_WIDTH-1:0] reg_rd_data, input wire reg_rd_wait, input wire reg_rd_ack @@ -77,6 +81,8 @@ reg s_axil_arvalid_reg = 1'b0, s_axil_arvalid_next; reg [DATA_WIDTH-1:0] s_axil_rdata_reg = {DATA_WIDTH{1'b0}}, s_axil_rdata_next; reg s_axil_rvalid_reg = 1'b0, s_axil_rvalid_next; +reg [USER_WIDTH-1:0] s_axil_aruser_reg = {USER_WIDTH{1'b0}}, s_axil_aruser_next; + reg reg_rd_en_reg = 1'b0, reg_rd_en_next; assign s_axil_arready = !s_axil_arvalid_reg; @@ -87,6 +93,8 @@ assign s_axil_rvalid = s_axil_rvalid_reg; assign reg_rd_addr = s_axil_araddr_reg; assign reg_rd_en = reg_rd_en_reg; +assign reg_rd_user = s_axil_aruser_reg; + always @* begin timeout_count_next = timeout_count_reg; @@ -95,6 +103,8 @@ always @* begin s_axil_rdata_next = s_axil_rdata_reg; s_axil_rvalid_next = s_axil_rvalid_reg && !s_axil_rready; + s_axil_aruser_next = s_axil_aruser_reg; + if (reg_rd_en_reg && (reg_rd_ack || timeout_count_reg == 0)) begin s_axil_arvalid_next = 1'b0; s_axil_rdata_next = reg_rd_data; @@ -104,6 +114,7 @@ always @* begin if (!s_axil_arvalid_reg) begin s_axil_araddr_next = s_axil_araddr; s_axil_arvalid_next = s_axil_arvalid; + s_axil_aruser_next = s_axil_aruser; timeout_count_next = TIMEOUT-1; end @@ -122,6 +133,8 @@ always @(posedge clk) begin s_axil_rdata_reg <= s_axil_rdata_next; s_axil_rvalid_reg <= s_axil_rvalid_next; + s_axil_aruser_reg <= s_axil_aruser_next; + reg_rd_en_reg <= reg_rd_en_next; if (rst) begin diff --git a/fpga/lib/axi/rtl/axil_reg_if_wr.v b/fpga/lib/axi/rtl/axil_reg_if_wr.v index 4ffc067..7c4005b 100644 --- a/fpga/lib/axi/rtl/axil_reg_if_wr.v +++ b/fpga/lib/axi/rtl/axil_reg_if_wr.v @@ -39,6 +39,8 @@ module axil_reg_if_wr # parameter ADDR_WIDTH = 32, // Width of wstrb (width of data bus in words) parameter STRB_WIDTH = (DATA_WIDTH/8), + // Width of user bus in bits + parameter USER_WIDTH = 8, // Timeout delay (cycles) parameter TIMEOUT = 4 ) @@ -52,6 +54,7 @@ module axil_reg_if_wr # input wire [ADDR_WIDTH-1:0] s_axil_awaddr, input wire [2:0] s_axil_awprot, input wire s_axil_awvalid, + input wire [USER_WIDTH-1:0] s_axil_awuser, output wire s_axil_awready, input wire [DATA_WIDTH-1:0] s_axil_wdata, input wire [STRB_WIDTH-1:0] s_axil_wstrb, @@ -68,6 +71,7 @@ module axil_reg_if_wr # output wire [DATA_WIDTH-1:0] reg_wr_data, output wire [STRB_WIDTH-1:0] reg_wr_strb, output wire reg_wr_en, + output wire [USER_WIDTH-1:0] reg_wr_user, input wire reg_wr_wait, input wire reg_wr_ack ); @@ -83,6 +87,9 @@ reg [STRB_WIDTH-1:0] s_axil_wstrb_reg = {STRB_WIDTH{1'b0}}, s_axil_wstrb_next; reg s_axil_wvalid_reg = 1'b0, s_axil_wvalid_next; reg s_axil_bvalid_reg = 1'b0, s_axil_bvalid_next; + +reg [USER_WIDTH-1:0] s_axil_awuser_reg = {USER_WIDTH{1'b0}}, s_axil_awuser_next; + reg reg_wr_en_reg = 1'b0, reg_wr_en_next; assign s_axil_awready = !s_axil_awvalid_reg; @@ -95,11 +102,14 @@ assign reg_wr_data = s_axil_wdata_reg; assign reg_wr_strb = s_axil_wstrb_reg; assign reg_wr_en = reg_wr_en_reg; +assign reg_wr_user = s_axil_awuser_reg; + always @* begin timeout_count_next = timeout_count_reg; s_axil_awaddr_next = s_axil_awaddr_reg; s_axil_awvalid_next = s_axil_awvalid_reg; + s_axil_awuser_next = s_axil_awuser_reg; s_axil_wdata_next = s_axil_wdata_reg; s_axil_wstrb_next = s_axil_wstrb_reg; s_axil_wvalid_next = s_axil_wvalid_reg; @@ -114,6 +124,7 @@ always @* begin if (!s_axil_awvalid_reg) begin s_axil_awaddr_next = s_axil_awaddr; s_axil_awvalid_next = s_axil_awvalid; + s_axil_awuser_next = s_axil_awuser; timeout_count_next = TIMEOUT-1; end @@ -136,6 +147,7 @@ always @(posedge clk) begin s_axil_awaddr_reg <= s_axil_awaddr_next; s_axil_awvalid_reg <= s_axil_awvalid_next; s_axil_wdata_reg <= s_axil_wdata_next; + s_axil_awuser_reg <= s_axil_awuser_next; s_axil_wstrb_reg <= s_axil_wstrb_next; s_axil_wvalid_reg <= s_axil_wvalid_next; s_axil_bvalid_reg <= s_axil_bvalid_next; diff --git a/fpga/lib/pcie/rtl/pcie_msix.v b/fpga/lib/pcie/rtl/pcie_msix.v index 380b2ad..e4d25f5 100644 --- a/fpga/lib/pcie/rtl/pcie_msix.v +++ b/fpga/lib/pcie/rtl/pcie_msix.v @@ -104,7 +104,7 @@ module pcie_msix # parameter TBL_ADDR_WIDTH = IRQ_INDEX_WIDTH+1; parameter NUM_TABLE_ENTRIES = 2**TBL_ADDR_WIDTH; // Scott -parameter NUM_ENTRIES_PER_FUNC = NUM_TABLE_ENTRIES / FUNCTION_ID_WIDTH; +parameter NUM_ENTRIES_PER_FUNC = NUM_TABLE_ENTRIES / 2**FUNCTION_ID_WIDTH; parameter CLOG_NUM_ENTRIES_PER_FUNC = $clog2(NUM_ENTRIES_PER_FUNC); parameter PBA_ADDR_WIDTH = IRQ_INDEX_WIDTH > 6 ? IRQ_INDEX_WIDTH-6 : 0; @@ -303,9 +303,9 @@ always @* begin tlp_hdr[109:108] = 2'b00; // attr tlp_hdr[107:106] = 3'b000; // AT tlp_hdr[105:96] = 10'd1; // length - // DW 1 + // DW //$display("Scott irq_index_reg = %b", irq_index_reg); - func_id[7:0] = irq_index_reg >> CLOG_NUM_ENTRIES_PER_FUNC; + func_id[7:0] = irq_index_reg >> (CLOG_NUM_ENTRIES_PER_FUNC-1); tlp_hdr[95:80] = {8'b0, func_id}; // requester ID //$display("Scott tlp_hdr = %b ", tlp_hdr[95:80]); tlp_hdr[79:72] = 8'd0; // tag diff --git a/fpga/mqnic/Alveo/fpga_100g/fpga_AU250/Makefile b/fpga/mqnic/Alveo/fpga_100g/fpga_AU250/Makefile new file mode 100644 index 0000000..9ca4542 --- /dev/null +++ b/fpga/mqnic/Alveo/fpga_100g/fpga_AU250/Makefile @@ -0,0 +1,192 @@ +# SPDX-License-Identifier: BSD-2-Clause-Views +# Copyright (c) 2019-2023 The Regents of the University of California + +# FPGA settings +FPGA_PART = xcu250-figd2104-2-e +FPGA_TOP = fpga +FPGA_ARCH = virtexuplus + +# Files for synthesis +SYN_FILES = rtl/fpga_au200.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/debounce_switch.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/mqnic_core_pcie_us.v +SYN_FILES += rtl/common/mqnic_core_pcie.v +SYN_FILES += rtl/common/mqnic_core.v +SYN_FILES += rtl/common/mqnic_dram_if.v +SYN_FILES += rtl/common/mqnic_interface.v +SYN_FILES += rtl/common/mqnic_interface_tx.v +SYN_FILES += rtl/common/mqnic_interface_rx.v +SYN_FILES += rtl/common/mqnic_port.v +SYN_FILES += rtl/common/mqnic_port_tx.v +SYN_FILES += rtl/common/mqnic_port_rx.v +SYN_FILES += rtl/common/mqnic_egress.v +SYN_FILES += rtl/common/mqnic_ingress.v +SYN_FILES += rtl/common/mqnic_l2_egress.v +SYN_FILES += rtl/common/mqnic_l2_ingress.v +SYN_FILES += rtl/common/mqnic_rx_queue_map.v +SYN_FILES += rtl/common/mqnic_ptp.v +SYN_FILES += rtl/common/mqnic_ptp_clock.v +SYN_FILES += rtl/common/mqnic_ptp_perout.v +SYN_FILES += rtl/common/mqnic_rb_clk_info.v +SYN_FILES += rtl/common/mqnic_port_map_mac_axis.v +SYN_FILES += rtl/common/cpl_write.v +SYN_FILES += rtl/common/cpl_op_mux.v +SYN_FILES += rtl/common/desc_fetch.v +SYN_FILES += rtl/common/desc_op_mux.v +SYN_FILES += rtl/common/queue_manager.v +SYN_FILES += rtl/common/cpl_queue_manager.v +SYN_FILES += rtl/common/tx_fifo.v +SYN_FILES += rtl/common/rx_fifo.v +SYN_FILES += rtl/common/tx_req_mux.v +SYN_FILES += rtl/common/tx_engine.v +SYN_FILES += rtl/common/rx_engine.v +SYN_FILES += rtl/common/tx_checksum.v +SYN_FILES += rtl/common/rx_hash.v +SYN_FILES += rtl/common/rx_checksum.v +SYN_FILES += rtl/common/rb_drp.v +SYN_FILES += rtl/common/cmac_gty_wrapper.v +SYN_FILES += rtl/common/cmac_gty_ch_wrapper.v +SYN_FILES += rtl/common/stats_counter.v +SYN_FILES += rtl/common/stats_collect.v +SYN_FILES += rtl/common/stats_pcie_if.v +SYN_FILES += rtl/common/stats_pcie_tlp.v +SYN_FILES += rtl/common/stats_dma_if_pcie.v +SYN_FILES += rtl/common/stats_dma_latency.v +SYN_FILES += rtl/common/mqnic_tx_scheduler_block_rr.v +SYN_FILES += rtl/common/tx_scheduler_rr.v +SYN_FILES += rtl/common/cmac_pad.v +SYN_FILES += rtl/common/mac_ts_insert.v +SYN_FILES += lib/eth/rtl/ptp_td_phc.v +SYN_FILES += lib/eth/rtl/ptp_td_leaf.v +SYN_FILES += lib/eth/rtl/ptp_perout.v +SYN_FILES += lib/axi/rtl/axil_cdc.v +SYN_FILES += lib/axi/rtl/axil_cdc_rd.v +SYN_FILES += lib/axi/rtl/axil_cdc_wr.v +SYN_FILES += lib/axi/rtl/axil_interconnect.v +SYN_FILES += lib/axi/rtl/axil_crossbar.v +SYN_FILES += lib/axi/rtl/axil_crossbar_addr.v +SYN_FILES += lib/axi/rtl/axil_crossbar_rd.v +SYN_FILES += lib/axi/rtl/axil_crossbar_wr.v +SYN_FILES += lib/axi/rtl/axil_reg_if.v +SYN_FILES += lib/axi/rtl/axil_reg_if_rd.v +SYN_FILES += lib/axi/rtl/axil_reg_if_wr.v +SYN_FILES += lib/axi/rtl/axil_register_rd.v +SYN_FILES += lib/axi/rtl/axil_register_wr.v +SYN_FILES += lib/axi/rtl/arbiter.v +SYN_FILES += lib/axi/rtl/priority_encoder.v +SYN_FILES += lib/axis/rtl/axis_adapter.v +SYN_FILES += lib/axis/rtl/axis_arb_mux.v +SYN_FILES += lib/axis/rtl/axis_async_fifo.v +SYN_FILES += lib/axis/rtl/axis_async_fifo_adapter.v +SYN_FILES += lib/axis/rtl/axis_demux.v +SYN_FILES += lib/axis/rtl/axis_fifo.v +SYN_FILES += lib/axis/rtl/axis_fifo_adapter.v +SYN_FILES += lib/axis/rtl/axis_pipeline_fifo.v +SYN_FILES += lib/axis/rtl/axis_register.v +SYN_FILES += lib/axis/rtl/sync_reset.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_fifo.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_fifo_raw.v +SYN_FILES += lib/pcie/rtl/pcie_msix.v +SYN_FILES += lib/pcie/rtl/irq_rate_limit.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_if_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_mux_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_mux_wr.v +SYN_FILES += lib/pcie/rtl/dma_if_desc_mux.v +SYN_FILES += lib/pcie/rtl/dma_ram_demux_rd.v +SYN_FILES += lib/pcie/rtl/dma_ram_demux_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/dma_client_axis_sink.v +SYN_FILES += lib/pcie/rtl/dma_client_axis_source.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v +SYN_FILES += rtl/common/resource_translator.v + +# XDC files +XDC_FILES = fpga_au200.xdc +XDC_FILES += placement_au250.xdc +XDC_FILES += cfgmclk.xdc +XDC_FILES += boot.xdc +XDC_FILES += lib/axi/syn/vivado/axil_cdc.tcl +XDC_FILES += lib/axis/syn/vivado/axis_async_fifo.tcl +XDC_FILES += lib/axis/syn/vivado/sync_reset.tcl +XDC_FILES += lib/eth/syn/vivado/ptp_td_leaf.tcl +XDC_FILES += ../../../common/syn/vivado/mqnic_port.tcl +XDC_FILES += ../../../common/syn/vivado/mqnic_ptp_clock.tcl +XDC_FILES += ../../../common/syn/vivado/mqnic_rb_clk_info.tcl +XDC_FILES += ../../../common/syn/vivado/rb_drp.tcl +XDC_FILES += ../../../common/syn/vivado/cmac_gty_wrapper.tcl +XDC_FILES += ../../../common/syn/vivado/cmac_gty_ch_wrapper.tcl + +# IP +IP_TCL_FILES = ip/pcie4_uscale_plus_0.tcl +IP_TCL_FILES += ip/cmac_usplus.tcl +IP_TCL_FILES += ip/cmac_gty.tcl +IP_TCL_FILES += ip/cms.tcl +#IP_TCL_FILES += ip/ddr4_0.tcl + +# Configuration +CONFIG_TCL_FILES = ./config.tcl + +include ../common/vivado.mk + +program: $(FPGA_TOP).bit + echo "open_hw" > program.tcl + echo "connect_hw_server" >> program.tcl + echo "open_hw_target" >> program.tcl + echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl + echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl + echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl + echo "program_hw_devices [current_hw_device]" >> program.tcl + echo "exit" >> program.tcl + vivado -nojournal -nolog -mode batch -source program.tcl + +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm + echo "open_hw" > flash.tcl + echo "connect_hw_server" >> flash.tcl + echo "open_hw_target" >> flash.tcl + echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl + echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl + echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0]" >> flash.tcl + echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl + echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl + echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl + echo "program_hw_devices [current_hw_device]" >> flash.tcl + echo "refresh_hw_device [current_hw_device]" >> flash.tcl + echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl + echo "boot_hw_device [current_hw_device]" >> flash.tcl + echo "exit" >> flash.tcl + vivado -nojournal -nolog -mode batch -source flash.tcl diff --git a/fpga/mqnic/Alveo/fpga_100g/fpga_AU250/config.tcl b/fpga/mqnic/Alveo/fpga_100g/fpga_AU250/config.tcl new file mode 100644 index 0000000..89643bb --- /dev/null +++ b/fpga/mqnic/Alveo/fpga_100g/fpga_AU250/config.tcl @@ -0,0 +1,255 @@ +# SPDX-License-Identifier: BSD-2-Clause-Views +# Copyright (c) 2021-2023 The Regents of the University of California + +set params [dict create] + +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + +# FW and board IDs +set fpga_id [expr 0x4B57093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x90fa] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +# FW ID block +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] + +# Board configuration +dict set params CMS_ENABLE "1" +dict set params FUNCTION_ID_WIDTH "8" + +# Structural configuration +dict set params IF_COUNT "2" +dict set params PORTS_PER_IF "1" +dict set params SCHED_PER_IF [dict get $params PORTS_PER_IF] +dict set params PORT_MASK "0" + +# Clock configuration +dict set params CLK_PERIOD_NS_NUM "4" +dict set params CLK_PERIOD_NS_DENOM "1" + +# PTP configuration +dict set params PTP_CLOCK_PIPELINE "0" +dict set params PTP_CLOCK_CDC_PIPELINE "0" +dict set params PTP_PORT_CDC_PIPELINE "0" +dict set params PTP_PEROUT_ENABLE "0" +dict set params PTP_PEROUT_COUNT "1" + +# Queue manager configuration +dict set params EVENT_QUEUE_OP_TABLE_SIZE "32" +dict set params TX_QUEUE_OP_TABLE_SIZE "32" +dict set params RX_QUEUE_OP_TABLE_SIZE "32" +dict set params CQ_OP_TABLE_SIZE "32" +dict set params EQN_WIDTH "9" +dict set params TX_QUEUE_INDEX_WIDTH "13" +dict set params RX_QUEUE_INDEX_WIDTH "9" +dict set params CQN_WIDTH [expr max([dict get $params TX_QUEUE_INDEX_WIDTH], [dict get $params RX_QUEUE_INDEX_WIDTH]) + 1] +dict set params EQ_PIPELINE "3" +dict set params TX_QUEUE_PIPELINE [expr 3 + max([dict get $params TX_QUEUE_INDEX_WIDTH] - 12, 0)] +dict set params RX_QUEUE_PIPELINE [expr 3 + max([dict get $params RX_QUEUE_INDEX_WIDTH] - 12, 0)] +dict set params CQ_PIPELINE [expr 3 + max([dict get $params CQN_WIDTH] - 12, 0)] + +# TX and RX engine configuration +dict set params TX_DESC_TABLE_SIZE "32" +dict set params RX_DESC_TABLE_SIZE "32" +dict set params RX_INDIR_TBL_ADDR_WIDTH [expr min([dict get $params RX_QUEUE_INDEX_WIDTH], 8)] + +# Scheduler configuration +dict set params TX_SCHEDULER_OP_TABLE_SIZE [dict get $params TX_DESC_TABLE_SIZE] +dict set params TX_SCHEDULER_PIPELINE [dict get $params TX_QUEUE_PIPELINE] +dict set params TDMA_INDEX_WIDTH "6" + +# Interface configuration +dict set params PTP_TS_ENABLE "1" +dict set params TX_CPL_FIFO_DEPTH "32" +dict set params TX_CHECKSUM_ENABLE "1" +dict set params RX_HASH_ENABLE "1" +dict set params RX_CHECKSUM_ENABLE "1" +dict set params PFC_ENABLE "1" +dict set params LFC_ENABLE [dict get $params PFC_ENABLE] +dict set params TX_FIFO_DEPTH "32768" +dict set params RX_FIFO_DEPTH "131072" +dict set params MAX_TX_SIZE "9214" +dict set params MAX_RX_SIZE "9214" +dict set params TX_RAM_SIZE "131072" +dict set params RX_RAM_SIZE "131072" + +# RAM configuration +dict set params DDR_CH "4" +dict set params DDR_ENABLE "0" +dict set params AXI_DDR_ID_WIDTH "8" +dict set params AXI_DDR_MAX_BURST_LEN "256" + +# Application block configuration +dict set params APP_ID "32'h00000000" +dict set params APP_ENABLE "0" +dict set params APP_CTRL_ENABLE "1" +dict set params APP_DMA_ENABLE "1" +dict set params APP_AXIS_DIRECT_ENABLE "1" +dict set params APP_AXIS_SYNC_ENABLE "1" +dict set params APP_AXIS_IF_ENABLE "1" +dict set params APP_STAT_ENABLE "1" + +# DMA interface configuration +dict set params DMA_IMM_ENABLE "0" +dict set params DMA_IMM_WIDTH "32" +dict set params DMA_LEN_WIDTH "16" +dict set params DMA_TAG_WIDTH "16" +dict set params RAM_ADDR_WIDTH [expr int(ceil(log(max([dict get $params TX_RAM_SIZE], [dict get $params RX_RAM_SIZE]))/log(2)))] +dict set params RAM_PIPELINE "2" + +# Interrupt configuration +dict set params IRQ_INDEX_WIDTH [expr [dict get $params EQN_WIDTH] - [dict get $params FUNCTION_ID_WIDTH]] + +# AXI lite interface configuration (control) +dict set params AXIL_CTRL_DATA_WIDTH "32" +dict set params AXIL_CTRL_ADDR_WIDTH "24" + +# AXI lite interface configuration (application control) +dict set params AXIL_APP_CTRL_DATA_WIDTH [dict get $params AXIL_CTRL_DATA_WIDTH] +dict set params AXIL_APP_CTRL_ADDR_WIDTH "24" + +# Ethernet interface configuration +dict set params AXIS_ETH_TX_PIPELINE "4" +dict set params AXIS_ETH_TX_FIFO_PIPELINE "4" +dict set params AXIS_ETH_TX_TS_PIPELINE "4" +dict set params AXIS_ETH_RX_PIPELINE "4" +dict set params AXIS_ETH_RX_FIFO_PIPELINE "4" + +# Statistics counter subsystem +dict set params STAT_ENABLE "1" +dict set params STAT_DMA_ENABLE "1" +dict set params STAT_PCIE_ENABLE "1" +dict set params STAT_INC_WIDTH "24" +dict set params STAT_ID_WIDTH "12" + +# DDR4 MIG settings +if {[dict get $params DDR_ENABLE]} { + set ddr4 [get_ips ddr4_0] + + # performance-related configuration + set_property CONFIG.C0.DDR4_AxiArbitrationScheme {RD_PRI_REG} $ddr4 + set_property CONFIG.C0.DDR4_AUTO_AP_COL_A3 {true} $ddr4 + set_property CONFIG.C0.DDR4_Mem_Add_Map {ROW_COLUMN_BANK_INTLV} $ddr4 + + # set AXI ID width + set_property CONFIG.C0.DDR4_AxiIDWidth [dict get $params AXI_DDR_ID_WIDTH] $ddr4 + + # extract AXI configuration + dict set params AXI_DDR_DATA_WIDTH [get_property CONFIG.C0.DDR4_AxiDataWidth $ddr4] + dict set params AXI_DDR_ADDR_WIDTH [get_property CONFIG.C0.DDR4_AxiAddressWidth $ddr4] + dict set params AXI_DDR_NARROW_BURST [expr [get_property CONFIG.C0.DDR4_AxiNarrowBurst $ddr4] && 1] +} + +# PCIe IP core settings +set pcie [get_ips pcie4_uscale_plus_0] + +# Internal interface settings +dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] + +# configure BAR settings +proc configure_bar {pcie pf bar aperture} { + set size_list {Bytes Kilobytes Megabytes Gigabytes Terabytes Petabytes Exabytes} + for { set i 0 } { $i < [llength $size_list] } { incr i } { + set scale [lindex $size_list $i] + + if {$aperture > 0 && $aperture < ($i+1)*10} { + set size [expr 1 << $aperture - ($i*10)] + + puts "${pcie} PF${pf} BAR${bar}: aperture ${aperture} bits ($size $scale)" + + set pcie_config [dict create] + + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_enabled" {true} + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_type" {Memory} + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_64bit" {true} + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_prefetchable" {true} + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_scale" $scale + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_size" $size + + set_property -dict $pcie_config $pcie + + return + } + } + puts "${pcie} PF${pf} BAR${bar}: disabled" + set_property "CONFIG.pf${pf}_bar${bar}_enabled" {false} $pcie +} + +# Control BAR (BAR 0) +configure_bar $pcie 0 0 [dict get $params AXIL_CTRL_ADDR_WIDTH] + +# Application BAR (BAR 2) +configure_bar $pcie 0 2 [expr [dict get $params APP_ENABLE] ? [dict get $params AXIL_APP_CTRL_ADDR_WIDTH] : 0] + +# PCIe IP core configuration +set pcie_config [dict create] + +# PCIe IDs +dict set pcie_config "CONFIG.vendor_id" [format "%04x" $pcie_vendor_id] +dict set pcie_config "CONFIG.PF0_DEVICE_ID" [format "%04x" $pcie_device_id] +dict set pcie_config "CONFIG.PF0_CLASS_CODE" [format "%06x" $pcie_class_code] +dict set pcie_config "CONFIG.PF0_REVISION_ID" [format "%02x" $pcie_revision_id] +dict set pcie_config "CONFIG.PF0_SUBSYSTEM_VENDOR_ID" [format "%04x" $pcie_subsystem_vendor_id] +dict set pcie_config "CONFIG.PF0_SUBSYSTEM_ID" [format "%04x" $pcie_subsystem_device_id] + +# MSI-X +dict set pcie_config "CONFIG.pf0_msi_enabled" {false} +dict set pcie_config "CONFIG.pf0_msix_enabled" {true} +dict set pcie_config "CONFIG.PF0_MSIX_CAP_TABLE_SIZE" [format "%03x" [expr 2**[dict get $params IRQ_INDEX_WIDTH]-1]] +dict set pcie_config "CONFIG.PF0_MSIX_CAP_TABLE_BIR" {BAR_1:0} +dict set pcie_config "CONFIG.PF0_MSIX_CAP_TABLE_OFFSET" {00010000} +dict set pcie_config "CONFIG.PF0_MSIX_CAP_PBA_BIR" {BAR_1:0} +dict set pcie_config "CONFIG.PF0_MSIX_CAP_PBA_OFFSET" {00018000} +dict set pcie_config "CONFIG.MSI_X_OPTIONS" {MSI-X_External} + +set_property -dict $pcie_config $pcie + +# apply parameters to top-level +set param_list {} +dict for {name value} $params { + lappend param_list $name=$value +} + +# set_property generic $param_list [current_fileset] +set_property generic $param_list [get_filesets sources_1] diff --git a/fpga/mqnic/Alveo/fpga_100g/fpga_AU50/Makefile b/fpga/mqnic/Alveo/fpga_100g/fpga_AU50/Makefile new file mode 100644 index 0000000..0c4f6f5 --- /dev/null +++ b/fpga/mqnic/Alveo/fpga_100g/fpga_AU50/Makefile @@ -0,0 +1,193 @@ +# SPDX-License-Identifier: BSD-2-Clause-Views +# Copyright (c) 2019-2023 The Regents of the University of California + +# FPGA settings +FPGA_PART = xcu50-fsvh2104-2-e +FPGA_TOP = fpga +FPGA_ARCH = virtexuplus + +# Files for synthesis +SYN_FILES = rtl/fpga_au50.v +SYN_FILES += rtl/fpga_hbm.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/mqnic_core_pcie_us.v +SYN_FILES += rtl/common/mqnic_core_pcie.v +SYN_FILES += rtl/common/mqnic_core.v +SYN_FILES += rtl/common/mqnic_dram_if.v +SYN_FILES += rtl/common/mqnic_interface.v +SYN_FILES += rtl/common/mqnic_interface_tx.v +SYN_FILES += rtl/common/mqnic_interface_rx.v +SYN_FILES += rtl/common/mqnic_port.v +SYN_FILES += rtl/common/mqnic_port_tx.v +SYN_FILES += rtl/common/mqnic_port_rx.v +SYN_FILES += rtl/common/mqnic_egress.v +SYN_FILES += rtl/common/mqnic_ingress.v +SYN_FILES += rtl/common/mqnic_l2_egress.v +SYN_FILES += rtl/common/mqnic_l2_ingress.v +SYN_FILES += rtl/common/mqnic_rx_queue_map.v +SYN_FILES += rtl/common/mqnic_ptp.v +SYN_FILES += rtl/common/mqnic_ptp_clock.v +SYN_FILES += rtl/common/mqnic_ptp_perout.v +SYN_FILES += rtl/common/mqnic_rb_clk_info.v +SYN_FILES += rtl/common/mqnic_port_map_mac_axis.v +SYN_FILES += rtl/common/cpl_write.v +SYN_FILES += rtl/common/cpl_op_mux.v +SYN_FILES += rtl/common/desc_fetch.v +SYN_FILES += rtl/common/desc_op_mux.v +SYN_FILES += rtl/common/queue_manager.v +SYN_FILES += rtl/common/cpl_queue_manager.v +SYN_FILES += rtl/common/tx_fifo.v +SYN_FILES += rtl/common/rx_fifo.v +SYN_FILES += rtl/common/tx_req_mux.v +SYN_FILES += rtl/common/tx_engine.v +SYN_FILES += rtl/common/rx_engine.v +SYN_FILES += rtl/common/tx_checksum.v +SYN_FILES += rtl/common/rx_hash.v +SYN_FILES += rtl/common/rx_checksum.v +SYN_FILES += rtl/common/rb_drp.v +SYN_FILES += rtl/common/cmac_gty_wrapper.v +SYN_FILES += rtl/common/cmac_gty_ch_wrapper.v +SYN_FILES += rtl/common/stats_counter.v +SYN_FILES += rtl/common/stats_collect.v +SYN_FILES += rtl/common/stats_pcie_if.v +SYN_FILES += rtl/common/stats_pcie_tlp.v +SYN_FILES += rtl/common/stats_dma_if_pcie.v +SYN_FILES += rtl/common/stats_dma_latency.v +SYN_FILES += rtl/common/mqnic_tx_scheduler_block_rr.v +SYN_FILES += rtl/common/tx_scheduler_rr.v +SYN_FILES += rtl/common/cmac_pad.v +SYN_FILES += rtl/common/mac_ts_insert.v +SYN_FILES += lib/eth/rtl/ptp_td_phc.v +SYN_FILES += lib/eth/rtl/ptp_td_leaf.v +SYN_FILES += lib/eth/rtl/ptp_perout.v +SYN_FILES += lib/axi/rtl/axil_cdc.v +SYN_FILES += lib/axi/rtl/axil_cdc_rd.v +SYN_FILES += lib/axi/rtl/axil_cdc_wr.v +SYN_FILES += lib/axi/rtl/axil_interconnect.v +SYN_FILES += lib/axi/rtl/axil_crossbar.v +SYN_FILES += lib/axi/rtl/axil_crossbar_addr.v +SYN_FILES += lib/axi/rtl/axil_crossbar_rd.v +SYN_FILES += lib/axi/rtl/axil_crossbar_wr.v +SYN_FILES += lib/axi/rtl/axil_reg_if.v +SYN_FILES += lib/axi/rtl/axil_reg_if_rd.v +SYN_FILES += lib/axi/rtl/axil_reg_if_wr.v +SYN_FILES += lib/axi/rtl/axil_register_rd.v +SYN_FILES += lib/axi/rtl/axil_register_wr.v +SYN_FILES += lib/axi/rtl/arbiter.v +SYN_FILES += lib/axi/rtl/priority_encoder.v +SYN_FILES += lib/axis/rtl/axis_adapter.v +SYN_FILES += lib/axis/rtl/axis_arb_mux.v +SYN_FILES += lib/axis/rtl/axis_async_fifo.v +SYN_FILES += lib/axis/rtl/axis_async_fifo_adapter.v +SYN_FILES += lib/axis/rtl/axis_demux.v +SYN_FILES += lib/axis/rtl/axis_fifo.v +SYN_FILES += lib/axis/rtl/axis_fifo_adapter.v +SYN_FILES += lib/axis/rtl/axis_pipeline_fifo.v +SYN_FILES += lib/axis/rtl/axis_register.v +SYN_FILES += lib/axis/rtl/sync_reset.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_fifo.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_fifo_raw.v +SYN_FILES += lib/pcie/rtl/pcie_msix.v +SYN_FILES += lib/pcie/rtl/irq_rate_limit.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_if_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_mux_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_mux_wr.v +SYN_FILES += lib/pcie/rtl/dma_if_desc_mux.v +SYN_FILES += lib/pcie/rtl/dma_ram_demux_rd.v +SYN_FILES += lib/pcie/rtl/dma_ram_demux_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/dma_client_axis_sink.v +SYN_FILES += lib/pcie/rtl/dma_client_axis_source.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v +SYN_FILES += rtl/common/resource_translator.v + +# XDC files +XDC_FILES = fpga_au50.xdc +XDC_FILES += placement_au50.xdc +XDC_FILES += boot.xdc +XDC_FILES += lib/axi/syn/vivado/axil_cdc.tcl +XDC_FILES += lib/axis/syn/vivado/axis_async_fifo.tcl +XDC_FILES += lib/axis/syn/vivado/sync_reset.tcl +XDC_FILES += lib/eth/syn/vivado/ptp_td_leaf.tcl +XDC_FILES += ../../../common/syn/vivado/mqnic_port.tcl +XDC_FILES += ../../../common/syn/vivado/mqnic_ptp_clock.tcl +XDC_FILES += ../../../common/syn/vivado/mqnic_rb_clk_info.tcl +XDC_FILES += ../../../common/syn/vivado/rb_drp.tcl +XDC_FILES += ../../../common/syn/vivado/cmac_gty_wrapper.tcl +XDC_FILES += ../../../common/syn/vivado/cmac_gty_ch_wrapper.tcl +#XDC_FILES += hbm.xdc + +# IP +IP_TCL_FILES = ip/pcie4c_uscale_plus_0.tcl +IP_TCL_FILES += ip/cmac_usplus.tcl +IP_TCL_FILES += ip/cmac_gty.tcl +IP_TCL_FILES += ip/cms.tcl +#IP_TCL_FILES += ip/hbm_0.tcl + +# Configuration +CONFIG_TCL_FILES = ./config.tcl + +include ../common/vivado.mk + +program: $(FPGA_TOP).bit + echo "open_hw" > program.tcl + echo "connect_hw_server" >> program.tcl + echo "open_hw_target" >> program.tcl + echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl + echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl + echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl + echo "program_hw_devices [current_hw_device]" >> program.tcl + echo "exit" >> program.tcl + vivado -nojournal -nolog -mode batch -source program.tcl + +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm + echo "open_hw" > flash.tcl + echo "connect_hw_server" >> flash.tcl + echo "open_hw_target" >> flash.tcl + echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl + echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl + echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0]" >> flash.tcl + echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl + echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl + echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl + echo "program_hw_devices [current_hw_device]" >> flash.tcl + echo "refresh_hw_device [current_hw_device]" >> flash.tcl + echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl + echo "boot_hw_device [current_hw_device]" >> flash.tcl + echo "exit" >> flash.tcl + vivado -nojournal -nolog -mode batch -source flash.tcl + diff --git a/fpga/mqnic/Alveo/fpga_100g/fpga_AU50/config.tcl b/fpga/mqnic/Alveo/fpga_100g/fpga_AU50/config.tcl new file mode 100644 index 0000000..50d5b5e --- /dev/null +++ b/fpga/mqnic/Alveo/fpga_100g/fpga_AU50/config.tcl @@ -0,0 +1,255 @@ +# SPDX-License-Identifier: BSD-2-Clause-Views +# Copyright (c) 2021-2023 The Regents of the University of California + +set params [dict create] + +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + +# FW and board IDs +set fpga_id [expr 0x4B77093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x9032] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +# FW ID block +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] + +# Board configuration +dict set params CMS_ENABLE "1" +dict set params FUNCTION_ID_WIDTH "8" + +# Structural configuration +dict set params IF_COUNT "1" +dict set params PORTS_PER_IF "1" +dict set params SCHED_PER_IF [dict get $params PORTS_PER_IF] +dict set params PORT_MASK "0" + +# Clock configuration +dict set params CLK_PERIOD_NS_NUM "4" +dict set params CLK_PERIOD_NS_DENOM "1" + +# PTP configuration +dict set params PTP_CLOCK_PIPELINE "1" +dict set params PTP_CLOCK_CDC_PIPELINE "0" +dict set params PTP_PORT_CDC_PIPELINE "1" +dict set params PTP_PEROUT_ENABLE "0" +dict set params PTP_PEROUT_COUNT "1" + +# Queue manager configuration +dict set params EVENT_QUEUE_OP_TABLE_SIZE "32" +dict set params TX_QUEUE_OP_TABLE_SIZE "32" +dict set params RX_QUEUE_OP_TABLE_SIZE "32" +dict set params CQ_OP_TABLE_SIZE "32" +dict set params EQN_WIDTH "9" +dict set params TX_QUEUE_INDEX_WIDTH "13" +dict set params RX_QUEUE_INDEX_WIDTH "9" +dict set params CQN_WIDTH [expr max([dict get $params TX_QUEUE_INDEX_WIDTH], [dict get $params RX_QUEUE_INDEX_WIDTH]) + 1] +dict set params EQ_PIPELINE "3" +dict set params TX_QUEUE_PIPELINE [expr 3 + max([dict get $params TX_QUEUE_INDEX_WIDTH] - 12, 0)] +dict set params RX_QUEUE_PIPELINE [expr 3 + max([dict get $params RX_QUEUE_INDEX_WIDTH] - 12, 0)] +dict set params CQ_PIPELINE [expr 3 + max([dict get $params CQN_WIDTH] - 12, 0)] + +# TX and RX engine configuration +dict set params TX_DESC_TABLE_SIZE "32" +dict set params RX_DESC_TABLE_SIZE "32" +dict set params RX_INDIR_TBL_ADDR_WIDTH [expr min([dict get $params RX_QUEUE_INDEX_WIDTH], 8)] + +# Scheduler configuration +dict set params TX_SCHEDULER_OP_TABLE_SIZE [dict get $params TX_DESC_TABLE_SIZE] +dict set params TX_SCHEDULER_PIPELINE [dict get $params TX_QUEUE_PIPELINE] +dict set params TDMA_INDEX_WIDTH "6" + +# Interface configuration +dict set params PTP_TS_ENABLE "1" +dict set params TX_CPL_FIFO_DEPTH "32" +dict set params TX_CHECKSUM_ENABLE "1" +dict set params RX_HASH_ENABLE "1" +dict set params RX_CHECKSUM_ENABLE "1" +dict set params PFC_ENABLE "1" +dict set params LFC_ENABLE [dict get $params PFC_ENABLE] +dict set params TX_FIFO_DEPTH "32768" +dict set params RX_FIFO_DEPTH "131072" +dict set params MAX_TX_SIZE "9214" +dict set params MAX_RX_SIZE "9214" +dict set params TX_RAM_SIZE "131072" +dict set params RX_RAM_SIZE "131072" + +# RAM configuration +dict set params HBM_CH "32" +dict set params HBM_ENABLE "0" +dict set params HBM_GROUP_SIZE [dict get $params HBM_CH] +dict set params AXI_HBM_MAX_BURST_LEN "16" + +# Application block configuration +dict set params APP_ID "32'h00000000" +dict set params APP_ENABLE "0" +dict set params APP_CTRL_ENABLE "1" +dict set params APP_DMA_ENABLE "1" +dict set params APP_AXIS_DIRECT_ENABLE "1" +dict set params APP_AXIS_SYNC_ENABLE "1" +dict set params APP_AXIS_IF_ENABLE "1" +dict set params APP_STAT_ENABLE "1" + +# DMA interface configuration +dict set params DMA_IMM_ENABLE "0" +dict set params DMA_IMM_WIDTH "32" +dict set params DMA_LEN_WIDTH "16" +dict set params DMA_TAG_WIDTH "16" +dict set params RAM_ADDR_WIDTH [expr int(ceil(log(max([dict get $params TX_RAM_SIZE], [dict get $params RX_RAM_SIZE]))/log(2)))] +dict set params RAM_PIPELINE "2" + +# Interrupt configuration +dict set params IRQ_INDEX_WIDTH [expr [dict get $params EQN_WIDTH] - [dict get $params FUNCTION_ID_WIDTH]] + +# AXI lite interface configuration (control) +dict set params AXIL_CTRL_DATA_WIDTH "32" +dict set params AXIL_CTRL_ADDR_WIDTH "24" + +# AXI lite interface configuration (application control) +dict set params AXIL_APP_CTRL_DATA_WIDTH [dict get $params AXIL_CTRL_DATA_WIDTH] +dict set params AXIL_APP_CTRL_ADDR_WIDTH "24" + +# Ethernet interface configuration +dict set params AXIS_ETH_TX_PIPELINE "4" +dict set params AXIS_ETH_TX_FIFO_PIPELINE "4" +dict set params AXIS_ETH_TX_TS_PIPELINE "4" +dict set params AXIS_ETH_RX_PIPELINE "4" +dict set params AXIS_ETH_RX_FIFO_PIPELINE "4" + +# Statistics counter subsystem +dict set params STAT_ENABLE "1" +dict set params STAT_DMA_ENABLE "1" +dict set params STAT_PCIE_ENABLE "1" +dict set params STAT_INC_WIDTH "24" +dict set params STAT_ID_WIDTH "12" + +# HBM settings +if {[dict get $params HBM_ENABLE]} { + set hbm [get_ips hbm_0] + + # switch configuration + if {[dict get $params HBM_GROUP_SIZE] == 1} { + set_property CONFIG.USER_SWITCH_ENABLE_00 "FALSE" $hbm + set_property CONFIG.USER_SWITCH_ENABLE_01 "FALSE" $hbm + dict set params HBM_GROUP_SIZE "1" + dict set params AXI_HBM_ADDR_WIDTH "28" + } else { + set_property CONFIG.USER_SWITCH_ENABLE_00 "TRUE" $hbm + set_property CONFIG.USER_SWITCH_ENABLE_01 "TRUE" $hbm + dict set params HBM_GROUP_SIZE [dict get $params HBM_CH] + dict set params AXI_HBM_ADDR_WIDTH "33" + } +} + +# PCIe IP core settings +set pcie [get_ips pcie4c_uscale_plus_0] + +# Internal interface settings +dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] + +# configure BAR settings +proc configure_bar {pcie pf bar aperture} { + set size_list {Bytes Kilobytes Megabytes Gigabytes Terabytes Petabytes Exabytes} + for { set i 0 } { $i < [llength $size_list] } { incr i } { + set scale [lindex $size_list $i] + + if {$aperture > 0 && $aperture < ($i+1)*10} { + set size [expr 1 << $aperture - ($i*10)] + + puts "${pcie} PF${pf} BAR${bar}: aperture ${aperture} bits ($size $scale)" + + set pcie_config [dict create] + + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_enabled" {true} + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_type" {Memory} + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_64bit" {true} + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_prefetchable" {true} + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_scale" $scale + dict set pcie_config "CONFIG.pf${pf}_bar${bar}_size" $size + + set_property -dict $pcie_config $pcie + + return + } + } + puts "${pcie} PF${pf} BAR${bar}: disabled" + set_property "CONFIG.pf${pf}_bar${bar}_enabled" {false} $pcie +} + +# Control BAR (BAR 0) +configure_bar $pcie 0 0 [dict get $params AXIL_CTRL_ADDR_WIDTH] + +# Application BAR (BAR 2) +configure_bar $pcie 0 2 [expr [dict get $params APP_ENABLE] ? [dict get $params AXIL_APP_CTRL_ADDR_WIDTH] : 0] + +# PCIe IP core configuration +set pcie_config [dict create] + +# PCIe IDs +dict set pcie_config "CONFIG.vendor_id" [format "%04x" $pcie_vendor_id] +dict set pcie_config "CONFIG.PF0_DEVICE_ID" [format "%04x" $pcie_device_id] +dict set pcie_config "CONFIG.PF0_CLASS_CODE" [format "%06x" $pcie_class_code] +dict set pcie_config "CONFIG.PF0_REVISION_ID" [format "%02x" $pcie_revision_id] +dict set pcie_config "CONFIG.PF0_SUBSYSTEM_VENDOR_ID" [format "%04x" $pcie_subsystem_vendor_id] +dict set pcie_config "CONFIG.PF0_SUBSYSTEM_ID" [format "%04x" $pcie_subsystem_device_id] + +# MSI-X +dict set pcie_config "CONFIG.pf0_msi_enabled" {false} +dict set pcie_config "CONFIG.pf0_msix_enabled" {true} +dict set pcie_config "CONFIG.PF0_MSIX_CAP_TABLE_SIZE" [format "%03x" [expr 2**[dict get $params IRQ_INDEX_WIDTH]-1]] +dict set pcie_config "CONFIG.PF0_MSIX_CAP_TABLE_BIR" {BAR_1:0} +dict set pcie_config "CONFIG.PF0_MSIX_CAP_TABLE_OFFSET" {00010000} +dict set pcie_config "CONFIG.PF0_MSIX_CAP_PBA_BIR" {BAR_1:0} +dict set pcie_config "CONFIG.PF0_MSIX_CAP_PBA_OFFSET" {00018000} +dict set pcie_config "CONFIG.MSI_X_OPTIONS" {MSI-X_External} + +set_property -dict $pcie_config $pcie + +# apply parameters to top-level +set param_list {} +dict for {name value} $params { + lappend param_list $name=$value +} + +# set_property generic $param_list [current_fileset] +set_property generic $param_list [get_filesets sources_1] diff --git a/fpga/mqnic/Alveo/fpga_100g/fpga_au200.xdc b/fpga/mqnic/Alveo/fpga_100g/fpga_au200.xdc new file mode 100644 index 0000000..38c51f4 --- /dev/null +++ b/fpga/mqnic/Alveo/fpga_100g/fpga_au200.xdc @@ -0,0 +1,858 @@ +# XDC constraints for Xilinx AU200/AU250/VCU1525 +# AU200 part: xcu200-fsgd2104-2-e +# AU250 part: xcu250-figd2104-2-e +# VCU1525 part: xcvu9p-fsgd2104-2L-e + +# General configuration +set_property CFGBVS GND [current_design] +set_property CONFIG_VOLTAGE 1.8 [current_design] +set_property BITSTREAM.GENERAL.COMPRESS true [current_design] +set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design] +set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN DISABLE [current_design] +set_property BITSTREAM.CONFIG.CONFIGRATE 63.8 [current_design] +set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] +set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] +set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] +set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design] +set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design] + +set_operating_conditions -design_power_budget 160 + +# System clocks +# 300 MHz (DDR 0) +set_property -dict {LOC AY37 IOSTANDARD LVDS} [get_ports clk_300mhz_0_p] +set_property -dict {LOC AY38 IOSTANDARD LVDS} [get_ports clk_300mhz_0_n] +create_clock -period 3.333 -name clk_300mhz_0 [get_ports clk_300mhz_0_p] + +set_property -quiet CLOCK_DEDICATED_ROUTE BACKBONE [get_nets -quiet clk_300mhz_0_int] + +# 300 MHz (DDR 1) +set_property -dict {LOC AW20 IOSTANDARD LVDS} [get_ports clk_300mhz_1_p] +set_property -dict {LOC AW19 IOSTANDARD LVDS} [get_ports clk_300mhz_1_n] +create_clock -period 3.333 -name clk_300mhz_1 [get_ports clk_300mhz_1_p] + +set_property -quiet CLOCK_DEDICATED_ROUTE BACKBONE [get_nets -quiet clk_300mhz_1_int] + +# 300 MHz (DDR 2) +set_property -dict {LOC F32 IOSTANDARD LVDS} [get_ports clk_300mhz_2_p] +set_property -dict {LOC E32 IOSTANDARD LVDS} [get_ports clk_300mhz_2_n] +create_clock -period 3.333 -name clk_300mhz_2 [get_ports clk_300mhz_2_p] + +set_property -quiet CLOCK_DEDICATED_ROUTE BACKBONE [get_nets -quiet clk_300mhz_2_int] + +# 300 MHz (DDR 3) +set_property -dict {LOC J16 IOSTANDARD LVDS} [get_ports clk_300mhz_3_p] +set_property -dict {LOC H16 IOSTANDARD LVDS} [get_ports clk_300mhz_3_n] +create_clock -period 3.333 -name clk_300mhz_3 [get_ports clk_300mhz_3_p] + +set_property -quiet CLOCK_DEDICATED_ROUTE BACKBONE [get_nets -quiet clk_300mhz_3_int] + +# SI570 user clock +#set_property -dict {LOC AU19 IOSTANDARD LVDS} [get_ports clk_user_p] +#set_property -dict {LOC AV19 IOSTANDARD LVDS} [get_ports clk_user_n] +#create_clock -period 6.400 -name clk_user [get_ports clk_user_p] + +# LEDs +set_property -dict {LOC BC21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}] +set_property -dict {LOC BB21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}] +set_property -dict {LOC BA20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[2]}] + +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + +# Reset button +#set_property -dict {LOC AL20 IOSTANDARD LVCMOS12} [get_ports reset] + +#set_false_path -from [get_ports {reset}] +#set_input_delay 0 [get_ports {reset}] + +# DIP switches +set_property -dict {LOC AN22 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] +set_property -dict {LOC AM19 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] +set_property -dict {LOC AL19 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] +set_property -dict {LOC AP20 IOSTANDARD LVCMOS12} [get_ports {sw[3]}] + +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + +# UART +#set_property -dict {LOC BF18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_txd] +#set_property -dict {LOC BB20 IOSTANDARD LVCMOS12} [get_ports uart_rxd] + +#set_false_path -to [get_ports {uart_txd}] +#set_output_delay 0 [get_ports {uart_txd}] +#set_false_path -from [get_ports {uart_rxd}] +#set_input_delay 0 [get_ports {uart_rxd}] + +# BMC +set_property -dict {LOC AR20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[0]}] +set_property -dict {LOC AM20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[1]}] +set_property -dict {LOC AM21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[2]}] +set_property -dict {LOC AN21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[3]}] +set_property -dict {LOC BB19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_uart_txd}] +set_property -dict {LOC BA19 IOSTANDARD LVCMOS12} [get_ports {msp_uart_rxd}] + +set_false_path -to [get_ports {msp_uart_txd}] +set_output_delay 0 [get_ports {msp_uart_txd}] +set_false_path -from [get_ports {msp_gpio[*] msp_uart_rxd}] +set_input_delay 0 [get_ports {msp_gpio[*] msp_uart_rxd}] + +# QSFP28 Interfaces +set_property -dict {LOC N4 } [get_ports {qsfp0_rx_p[0]}] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC N3 } [get_ports {qsfp0_rx_n[0]}] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC N9 } [get_ports {qsfp0_tx_p[0]}] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC N8 } [get_ports {qsfp0_tx_n[0]}] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC M2 } [get_ports {qsfp0_rx_p[1]}] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC M1 } [get_ports {qsfp0_rx_n[1]}] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC M7 } [get_ports {qsfp0_tx_p[1]}] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC M6 } [get_ports {qsfp0_tx_n[1]}] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC L4 } [get_ports {qsfp0_rx_p[2]}] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC L3 } [get_ports {qsfp0_rx_n[2]}] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC L9 } [get_ports {qsfp0_tx_p[2]}] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC L8 } [get_ports {qsfp0_tx_n[2]}] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC K2 } [get_ports {qsfp0_rx_p[3]}] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC K1 } [get_ports {qsfp0_rx_n[3]}] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC K7 } [get_ports {qsfp0_tx_p[3]}] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +set_property -dict {LOC K6 } [get_ports {qsfp0_tx_n[3]}] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC M11 } [get_ports qsfp0_mgt_refclk_0_p] ;# MGTREFCLK0P_231 from U14.4 via U43.13 +#set_property -dict {LOC M10 } [get_ports qsfp0_mgt_refclk_0_n] ;# MGTREFCLK0N_231 from U14.5 via U43.14 +set_property -dict {LOC K11 } [get_ports qsfp0_mgt_refclk_1_p] ;# MGTREFCLK1P_231 from U9.18 +set_property -dict {LOC K10 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U9.17 +set_property -dict {LOC BE16 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_modsell] +set_property -dict {LOC BE17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_resetl] +set_property -dict {LOC BE20 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_modprsl] +set_property -dict {LOC BE21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_intl] +set_property -dict {LOC BD18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_lpmode] +set_property -dict {LOC AT22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_refclk_reset] +set_property -dict {LOC AT20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[0]}] +set_property -dict {LOC AU22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[1]}] + +# 156.25 MHz MGT reference clock (from SI570) +#create_clock -period 6.400 -name qsfp0_mgt_refclk_0 [get_ports qsfp0_mgt_refclk_0_p] + +# 156.25 MHz MGT reference clock (from SI5335, FS = 0b01) +#create_clock -period 6.400 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p] + +# 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10) +create_clock -period 6.206 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p] + +set_false_path -to [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}] +set_output_delay 0 [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}] +set_false_path -from [get_ports {qsfp0_modprsl qsfp0_intl}] +set_input_delay 0 [get_ports {qsfp0_modprsl qsfp0_intl}] + +set_property -dict {LOC U4 } [get_ports {qsfp1_rx_p[0]}] ;# MGTYRXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC U3 } [get_ports {qsfp1_rx_n[0]}] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC U9 } [get_ports {qsfp1_tx_p[0]}] ;# MGTYTXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC U8 } [get_ports {qsfp1_tx_n[0]}] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC T2 } [get_ports {qsfp1_rx_p[1]}] ;# MGTYRXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC T1 } [get_ports {qsfp1_rx_n[1]}] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC T7 } [get_ports {qsfp1_tx_p[1]}] ;# MGTYTXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC T6 } [get_ports {qsfp1_tx_n[1]}] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC R4 } [get_ports {qsfp1_rx_p[2]}] ;# MGTYRXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC R3 } [get_ports {qsfp1_rx_n[2]}] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC R9 } [get_ports {qsfp1_tx_p[2]}] ;# MGTYTXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC R8 } [get_ports {qsfp1_tx_n[2]}] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC P2 } [get_ports {qsfp1_rx_p[3]}] ;# MGTYRXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC P1 } [get_ports {qsfp1_rx_n[3]}] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC P7 } [get_ports {qsfp1_tx_p[3]}] ;# MGTYTXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +set_property -dict {LOC P6 } [get_ports {qsfp1_tx_n[3]}] ;# MGTYTXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC T11 } [get_ports qsfp1_mgt_refclk_0_p] ;# MGTREFCLK0P_230 from U14.4 via U43.15 +#set_property -dict {LOC T10 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_230 from U14.5 via U43.16 +set_property -dict {LOC P11 } [get_ports qsfp1_mgt_refclk_1_p] ;# MGTREFCLK1P_230 from U12.18 +set_property -dict {LOC P10 } [get_ports qsfp1_mgt_refclk_1_n] ;# MGTREFCLK1N_230 from U12.17 +set_property -dict {LOC AY20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_modsell] +set_property -dict {LOC BC18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_resetl] +set_property -dict {LOC BC19 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_modprsl] +set_property -dict {LOC AV21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_intl] +set_property -dict {LOC AV22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_lpmode] +set_property -dict {LOC AR21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_refclk_reset] +set_property -dict {LOC AR22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[0]}] +set_property -dict {LOC AU20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[1]}] + +# 156.25 MHz MGT reference clock (from SI570) +#create_clock -period 6.400 -name qsfp1_mgt_refclk_0 [get_ports qsfp1_mgt_refclk_0_p] + +# 156.25 MHz MGT reference clock (from SI5335, FS = 0b01) +#create_clock -period 6.400 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p] + +# 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10) +create_clock -period 6.206 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p] + +set_false_path -to [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}] +set_output_delay 0 [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}] +set_false_path -from [get_ports {qsfp1_modprsl qsfp1_intl}] +set_input_delay 0 [get_ports {qsfp1_modprsl qsfp1_intl}] + +# I2C interface +#set_property -dict {LOC BF19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_mux_reset] +set_property -dict {LOC BF20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_scl] +set_property -dict {LOC BF17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_sda] + +set_false_path -to [get_ports {i2c_sda i2c_scl}] +set_output_delay 0 [get_ports {i2c_sda i2c_scl}] +set_false_path -from [get_ports {i2c_sda i2c_scl}] +set_input_delay 0 [get_ports {i2c_sda i2c_scl}] + +# PCIe Interface +set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AF7 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AF6 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AG4 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AG3 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AG9 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AG8 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AH2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AH1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AH7 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AH6 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AJ4 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AJ3 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AJ9 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AJ8 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AK2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AK1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AK7 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AK6 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AL4 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AL3 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AL9 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AL8 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AM2 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AM1 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AM7 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AM6 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AN4 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AN3 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AN9 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AN8 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AP2 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AP1 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AP7 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AP6 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AR4 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AR3 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AR9 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AR8 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AT2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AT1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AT7 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AT6 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AU4 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AU3 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AU9 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AU8 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AV2 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AV1 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AV7 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AV6 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AW4 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AW3 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BB5 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BB4 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BA2 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BA1 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BD5 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BD4 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BC2 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BC1 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BF5 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BF4 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AM11 } [get_ports pcie_refclk_p] ;# MGTREFCLK0P_226 +set_property -dict {LOC AM10 } [get_ports pcie_refclk_n] ;# MGTREFCLK0N_226 +set_property -dict {LOC BD21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports pcie_reset_n] + +# 100 MHz MGT reference clock +create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_p] + +set_false_path -from [get_ports {pcie_reset_n}] +set_input_delay 0 [get_ports {pcie_reset_n}] + +# DDR4 C0 +set_property -dict {LOC AT36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[0]}] +set_property -dict {LOC AV36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[1]}] +set_property -dict {LOC AV37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[2]}] +set_property -dict {LOC AW35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[3]}] +set_property -dict {LOC AW36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[4]}] +set_property -dict {LOC AY36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[5]}] +set_property -dict {LOC AY35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[6]}] +set_property -dict {LOC BA40 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[7]}] +set_property -dict {LOC BA37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[8]}] +set_property -dict {LOC BB37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[9]}] +set_property -dict {LOC AR35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[10]}] +set_property -dict {LOC BA39 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[11]}] +set_property -dict {LOC BB40 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[12]}] +set_property -dict {LOC AN36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[13]}] +set_property -dict {LOC AP35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[14]}] +set_property -dict {LOC AP36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[15]}] +set_property -dict {LOC AR36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[16]}] +set_property -dict {LOC AT35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_ba[0]}] +set_property -dict {LOC AT34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_ba[1]}] +set_property -dict {LOC BC37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_bg[0]}] +set_property -dict {LOC BC39 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_bg[1]}] +set_property -dict {LOC AV38 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_t[0]}] +set_property -dict {LOC AW38 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_c[0]}] +#set_property -dict {LOC AU34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_t[1]}] +#set_property -dict {LOC AU35 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_c[1]}] +set_property -dict {LOC BC38 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cke[0]}] +#set_property -dict {LOC BC40 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cke[1]}] +set_property -dict {LOC AR33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[0]}] +#set_property -dict {LOC AP33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[1]}] +#set_property -dict {LOC AN33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[2]}] +#set_property -dict {LOC AM34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[3]}] +set_property -dict {LOC BB39 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_act_n}] +set_property -dict {LOC AP34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_odt[0]}] +#set_property -dict {LOC AN34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_odt[1]}] +set_property -dict {LOC AU36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_par}] +set_property -dict {LOC AU31 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c0_reset_n}] + +set_property -dict {LOC AW28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[0]}] +set_property -dict {LOC AW29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[1]}] +set_property -dict {LOC BA28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[2]}] +set_property -dict {LOC BA27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[3]}] +set_property -dict {LOC BB29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[4]}] +set_property -dict {LOC BA29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[5]}] +set_property -dict {LOC BC27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[6]}] +set_property -dict {LOC BB27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[7]}] +set_property -dict {LOC BE28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[8]}] +set_property -dict {LOC BF28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[9]}] +set_property -dict {LOC BE30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[10]}] +set_property -dict {LOC BD30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[11]}] +set_property -dict {LOC BF27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[12]}] +set_property -dict {LOC BE27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[13]}] +set_property -dict {LOC BF30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[14]}] +set_property -dict {LOC BF29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[15]}] +set_property -dict {LOC BB31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[16]}] +set_property -dict {LOC BB32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[17]}] +set_property -dict {LOC AY32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[18]}] +set_property -dict {LOC AY33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[19]}] +set_property -dict {LOC BC32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[20]}] +set_property -dict {LOC BC33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[21]}] +set_property -dict {LOC BB34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[22]}] +set_property -dict {LOC BC34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[23]}] +set_property -dict {LOC AV31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[24]}] +set_property -dict {LOC AV32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[25]}] +set_property -dict {LOC AV34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[26]}] +set_property -dict {LOC AW34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[27]}] +set_property -dict {LOC AW31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[28]}] +set_property -dict {LOC AY31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[29]}] +set_property -dict {LOC BA35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[30]}] +set_property -dict {LOC BA34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[31]}] +set_property -dict {LOC AL30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[32]}] +set_property -dict {LOC AM30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[33]}] +set_property -dict {LOC AU32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[34]}] +set_property -dict {LOC AT32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[35]}] +set_property -dict {LOC AN31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[36]}] +set_property -dict {LOC AN32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[37]}] +set_property -dict {LOC AR32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[38]}] +set_property -dict {LOC AR31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[39]}] +set_property -dict {LOC AP29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[40]}] +set_property -dict {LOC AP28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[41]}] +set_property -dict {LOC AN27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[42]}] +set_property -dict {LOC AM27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[43]}] +set_property -dict {LOC AN29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[44]}] +set_property -dict {LOC AM29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[45]}] +set_property -dict {LOC AR27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[46]}] +set_property -dict {LOC AR28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[47]}] +set_property -dict {LOC AT28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[48]}] +set_property -dict {LOC AV27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[49]}] +set_property -dict {LOC AU27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[50]}] +set_property -dict {LOC AT27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[51]}] +set_property -dict {LOC AV29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[52]}] +set_property -dict {LOC AY30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[53]}] +set_property -dict {LOC AW30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[54]}] +set_property -dict {LOC AV28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[55]}] +set_property -dict {LOC BD34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[56]}] +set_property -dict {LOC BD33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[57]}] +set_property -dict {LOC BE33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[58]}] +set_property -dict {LOC BD35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[59]}] +set_property -dict {LOC BF32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[60]}] +set_property -dict {LOC BF33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[61]}] +set_property -dict {LOC BF34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[62]}] +set_property -dict {LOC BF35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[63]}] +set_property -dict {LOC BD40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[64]}] +set_property -dict {LOC BD39 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[65]}] +set_property -dict {LOC BF43 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[66]}] +set_property -dict {LOC BF42 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[67]}] +set_property -dict {LOC BF37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[68]}] +set_property -dict {LOC BE37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[69]}] +set_property -dict {LOC BE40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[70]}] +set_property -dict {LOC BF41 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[71]}] +set_property -dict {LOC BA30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[0]}] +set_property -dict {LOC BB30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[0]}] +set_property -dict {LOC BB26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[1]}] +set_property -dict {LOC BC26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[1]}] +set_property -dict {LOC BD28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[2]}] +set_property -dict {LOC BD29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[2]}] +set_property -dict {LOC BD26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[3]}] +set_property -dict {LOC BE26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[3]}] +set_property -dict {LOC BB35 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[4]}] +set_property -dict {LOC BB36 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[4]}] +set_property -dict {LOC BC31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[5]}] +set_property -dict {LOC BD31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[5]}] +set_property -dict {LOC AV33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[6]}] +set_property -dict {LOC AW33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[6]}] +set_property -dict {LOC BA32 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[7]}] +set_property -dict {LOC BA33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[7]}] +set_property -dict {LOC AM31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[8]}] +set_property -dict {LOC AM32 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[8]}] +set_property -dict {LOC AP30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[9]}] +set_property -dict {LOC AP31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[9]}] +set_property -dict {LOC AL28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[10]}] +set_property -dict {LOC AL29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[10]}] +set_property -dict {LOC AR30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[11]}] +set_property -dict {LOC AT30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[11]}] +set_property -dict {LOC AU29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[12]}] +set_property -dict {LOC AU30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[12]}] +set_property -dict {LOC AY27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[13]}] +set_property -dict {LOC AY28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[13]}] +set_property -dict {LOC BE35 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[14]}] +set_property -dict {LOC BE36 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[14]}] +set_property -dict {LOC BE31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[15]}] +set_property -dict {LOC BE32 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[15]}] +set_property -dict {LOC BE38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[16]}] +set_property -dict {LOC BF38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[16]}] +set_property -dict {LOC BF39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[17]}] +set_property -dict {LOC BF40 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[17]}] + +# DDR4 C1 +set_property -dict {LOC AN24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[0]}] +set_property -dict {LOC AT24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[1]}] +set_property -dict {LOC AW24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[2]}] +set_property -dict {LOC AN26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[3]}] +set_property -dict {LOC AY22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[4]}] +set_property -dict {LOC AY23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[5]}] +set_property -dict {LOC AV24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[6]}] +set_property -dict {LOC BA22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[7]}] +set_property -dict {LOC AY25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[8]}] +set_property -dict {LOC BA23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[9]}] +set_property -dict {LOC AM26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[10]}] +set_property -dict {LOC BA25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[11]}] +set_property -dict {LOC BB22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[12]}] +set_property -dict {LOC AL24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[13]}] +set_property -dict {LOC AL25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[14]}] +set_property -dict {LOC AM25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[15]}] +set_property -dict {LOC AN23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[16]}] +set_property -dict {LOC AU24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_ba[0]}] +set_property -dict {LOC AP26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_ba[1]}] +set_property -dict {LOC BC22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_bg[0]}] +set_property -dict {LOC AW26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_bg[1]}] +set_property -dict {LOC AT25 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_t[0]}] +set_property -dict {LOC AU25 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_c[0]}] +#set_property -dict {LOC AU26 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_t[1]}] +#set_property -dict {LOC AV26 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_c[1]}] +set_property -dict {LOC BB25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cke[0]}] +#set_property -dict {LOC BB24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cke[1]}] +set_property -dict {LOC AV23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[0]}] +#set_property -dict {LOC AP25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[1]}] +#set_property -dict {LOC AR23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[2]}] +#set_property -dict {LOC AP23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[3]}] +set_property -dict {LOC AW25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_act_n}] +set_property -dict {LOC AW23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_odt[0]}] +#set_property -dict {LOC AP24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_odt[1]}] +set_property -dict {LOC AT23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_par}] +set_property -dict {LOC AR17 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c1_reset_n}] + +set_property -dict {LOC BD9 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[0]}] +set_property -dict {LOC BD7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[1]}] +set_property -dict {LOC BC7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[2]}] +set_property -dict {LOC BD8 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[3]}] +set_property -dict {LOC BD10 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[4]}] +set_property -dict {LOC BE10 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[5]}] +set_property -dict {LOC BE7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[6]}] +set_property -dict {LOC BF7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[7]}] +set_property -dict {LOC AU13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[8]}] +set_property -dict {LOC AV13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[9]}] +set_property -dict {LOC AW13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[10]}] +set_property -dict {LOC AW14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[11]}] +set_property -dict {LOC AU14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[12]}] +set_property -dict {LOC AY11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[13]}] +set_property -dict {LOC AV14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[14]}] +set_property -dict {LOC BA11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[15]}] +set_property -dict {LOC BA12 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[16]}] +set_property -dict {LOC BB12 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[17]}] +set_property -dict {LOC BA13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[18]}] +set_property -dict {LOC BA14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[19]}] +set_property -dict {LOC BC9 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[20]}] +set_property -dict {LOC BB9 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[21]}] +set_property -dict {LOC BA7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[22]}] +set_property -dict {LOC BA8 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[23]}] +set_property -dict {LOC AN13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[24]}] +set_property -dict {LOC AR13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[25]}] +set_property -dict {LOC AM13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[26]}] +set_property -dict {LOC AP13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[27]}] +set_property -dict {LOC AM14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[28]}] +set_property -dict {LOC AR15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[29]}] +set_property -dict {LOC AL14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[30]}] +set_property -dict {LOC AT15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[31]}] +set_property -dict {LOC BE13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[32]}] +set_property -dict {LOC BD14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[33]}] +set_property -dict {LOC BF12 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[34]}] +set_property -dict {LOC BD13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[35]}] +set_property -dict {LOC BD15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[36]}] +set_property -dict {LOC BD16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[37]}] +set_property -dict {LOC BF14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[38]}] +set_property -dict {LOC BF13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[39]}] +set_property -dict {LOC AY17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[40]}] +set_property -dict {LOC BA17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[41]}] +set_property -dict {LOC AY18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[42]}] +set_property -dict {LOC BA18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[43]}] +set_property -dict {LOC BA15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[44]}] +set_property -dict {LOC BB15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[45]}] +set_property -dict {LOC BC11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[46]}] +set_property -dict {LOC BD11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[47]}] +set_property -dict {LOC AV16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[48]}] +set_property -dict {LOC AV17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[49]}] +set_property -dict {LOC AU16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[50]}] +set_property -dict {LOC AU17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[51]}] +set_property -dict {LOC BB17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[52]}] +set_property -dict {LOC BB16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[53]}] +set_property -dict {LOC AT18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[54]}] +set_property -dict {LOC AT17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[55]}] +set_property -dict {LOC AM15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[56]}] +set_property -dict {LOC AL15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[57]}] +set_property -dict {LOC AN17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[58]}] +set_property -dict {LOC AN16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[59]}] +set_property -dict {LOC AR18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[60]}] +set_property -dict {LOC AP18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[61]}] +set_property -dict {LOC AL17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[62]}] +set_property -dict {LOC AL16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[63]}] +set_property -dict {LOC BF25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[64]}] +set_property -dict {LOC BF24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[65]}] +set_property -dict {LOC BD25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[66]}] +set_property -dict {LOC BE25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[67]}] +set_property -dict {LOC BD23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[68]}] +set_property -dict {LOC BC23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[69]}] +set_property -dict {LOC BF23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[70]}] +set_property -dict {LOC BE23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[71]}] +set_property -dict {LOC BF10 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[0]}] +set_property -dict {LOC BF9 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[0]}] +set_property -dict {LOC BE8 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[1]}] +set_property -dict {LOC BF8 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[1]}] +set_property -dict {LOC AW15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[2]}] +set_property -dict {LOC AY15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[2]}] +set_property -dict {LOC AY13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[3]}] +set_property -dict {LOC AY12 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[3]}] +set_property -dict {LOC BB11 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[4]}] +set_property -dict {LOC BB10 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[4]}] +set_property -dict {LOC BA10 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[5]}] +set_property -dict {LOC BA9 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[5]}] +set_property -dict {LOC AT14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[6]}] +set_property -dict {LOC AT13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[6]}] +set_property -dict {LOC AN14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[7]}] +set_property -dict {LOC AP14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[7]}] +set_property -dict {LOC BE12 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[8]}] +set_property -dict {LOC BE11 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[8]}] +set_property -dict {LOC BE15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[9]}] +set_property -dict {LOC BF15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[9]}] +set_property -dict {LOC BC13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[10]}] +set_property -dict {LOC BC12 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[10]}] +set_property -dict {LOC BB14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[11]}] +set_property -dict {LOC BC14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[11]}] +set_property -dict {LOC AV18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[12]}] +set_property -dict {LOC AW18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[12]}] +set_property -dict {LOC AW16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[13]}] +set_property -dict {LOC AY16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[13]}] +set_property -dict {LOC AP16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[14]}] +set_property -dict {LOC AR16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[14]}] +set_property -dict {LOC AM17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[15]}] +set_property -dict {LOC AM16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[15]}] +set_property -dict {LOC BC24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[16]}] +set_property -dict {LOC BD24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[16]}] +set_property -dict {LOC BE22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[17]}] +set_property -dict {LOC BF22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[17]}] + +# DDR4 C2 +set_property -dict {LOC L29 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[0]}] +set_property -dict {LOC A33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[1]}] +set_property -dict {LOC C33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[2]}] +set_property -dict {LOC J29 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[3]}] +set_property -dict {LOC H31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[4]}] +set_property -dict {LOC G31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[5]}] +set_property -dict {LOC C32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[6]}] +set_property -dict {LOC B32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[7]}] +set_property -dict {LOC A32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[8]}] +set_property -dict {LOC D31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[9]}] +set_property -dict {LOC A34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[10]}] +set_property -dict {LOC E31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[11]}] +set_property -dict {LOC M30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[12]}] +set_property -dict {LOC F33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[13]}] +set_property -dict {LOC A35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[14]}] +set_property -dict {LOC G32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[15]}] +set_property -dict {LOC K30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[16]}] +set_property -dict {LOC D33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_ba[0]}] +set_property -dict {LOC B36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_ba[1]}] +set_property -dict {LOC C31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_bg[0]}] +set_property -dict {LOC J30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_bg[1]}] +set_property -dict {LOC C34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_t[0]}] +set_property -dict {LOC B34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_c[0]}] +#set_property -dict {LOC D34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_t[1]}] +#set_property -dict {LOC D35 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_c[1]}] +set_property -dict {LOC G30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cke[0]}] +#set_property -dict {LOC E30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cke[1]}] +set_property -dict {LOC B35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[0]}] +#set_property -dict {LOC J31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[1]}] +#set_property -dict {LOC L30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[2]}] +#set_property -dict {LOC K31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[3]}] +set_property -dict {LOC B31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_act_n}] +set_property -dict {LOC E33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_odt[0]}] +#set_property -dict {LOC F34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_odt[1]}] +set_property -dict {LOC M29 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_par}] +set_property -dict {LOC D36 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c2_reset_n}] + +set_property -dict {LOC R25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[0]}] +set_property -dict {LOC P25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[1]}] +set_property -dict {LOC M25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[2]}] +set_property -dict {LOC L25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[3]}] +set_property -dict {LOC P26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[4]}] +set_property -dict {LOC R26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[5]}] +set_property -dict {LOC N27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[6]}] +set_property -dict {LOC N28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[7]}] +set_property -dict {LOC J28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[8]}] +set_property -dict {LOC H29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[9]}] +set_property -dict {LOC H28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[10]}] +set_property -dict {LOC G29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[11]}] +set_property -dict {LOC K25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[12]}] +set_property -dict {LOC L27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[13]}] +set_property -dict {LOC K26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[14]}] +set_property -dict {LOC K27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[15]}] +set_property -dict {LOC F27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[16]}] +set_property -dict {LOC E27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[17]}] +set_property -dict {LOC E28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[18]}] +set_property -dict {LOC D28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[19]}] +set_property -dict {LOC G27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[20]}] +set_property -dict {LOC G26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[21]}] +set_property -dict {LOC F28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[22]}] +set_property -dict {LOC F29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[23]}] +set_property -dict {LOC D26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[24]}] +set_property -dict {LOC C26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[25]}] +set_property -dict {LOC B27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[26]}] +set_property -dict {LOC B26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[27]}] +set_property -dict {LOC A29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[28]}] +set_property -dict {LOC A30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[29]}] +set_property -dict {LOC C27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[30]}] +set_property -dict {LOC C28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[31]}] +set_property -dict {LOC F35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[32]}] +set_property -dict {LOC E38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[33]}] +set_property -dict {LOC D38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[34]}] +set_property -dict {LOC E35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[35]}] +set_property -dict {LOC E36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[36]}] +set_property -dict {LOC E37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[37]}] +set_property -dict {LOC F38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[38]}] +set_property -dict {LOC G38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[39]}] +set_property -dict {LOC P30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[40]}] +set_property -dict {LOC R30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[41]}] +set_property -dict {LOC P29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[42]}] +set_property -dict {LOC N29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[43]}] +set_property -dict {LOC L32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[44]}] +set_property -dict {LOC M32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[45]}] +set_property -dict {LOC P31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[46]}] +set_property -dict {LOC N32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[47]}] +set_property -dict {LOC J35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[48]}] +set_property -dict {LOC K35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[49]}] +set_property -dict {LOC L33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[50]}] +set_property -dict {LOC K33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[51]}] +set_property -dict {LOC J34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[52]}] +set_property -dict {LOC J33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[53]}] +set_property -dict {LOC N34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[54]}] +set_property -dict {LOC P34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[55]}] +set_property -dict {LOC H36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[56]}] +set_property -dict {LOC G36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[57]}] +set_property -dict {LOC H37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[58]}] +set_property -dict {LOC J36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[59]}] +set_property -dict {LOC K37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[60]}] +set_property -dict {LOC K38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[61]}] +set_property -dict {LOC G35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[62]}] +set_property -dict {LOC G34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[63]}] +set_property -dict {LOC C36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[64]}] +set_property -dict {LOC B37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[65]}] +set_property -dict {LOC A37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[66]}] +set_property -dict {LOC A38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[67]}] +set_property -dict {LOC C39 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[68]}] +set_property -dict {LOC D39 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[69]}] +set_property -dict {LOC A40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[70]}] +set_property -dict {LOC B40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[71]}] +set_property -dict {LOC N26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[0]}] +set_property -dict {LOC M26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[0]}] +set_property -dict {LOC R28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[1]}] +set_property -dict {LOC P28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[1]}] +set_property -dict {LOC J25 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[2]}] +set_property -dict {LOC J26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[2]}] +set_property -dict {LOC M27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[3]}] +set_property -dict {LOC L28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[3]}] +set_property -dict {LOC D29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[4]}] +set_property -dict {LOC D30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[4]}] +set_property -dict {LOC H26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[5]}] +set_property -dict {LOC H27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[5]}] +set_property -dict {LOC A27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[6]}] +set_property -dict {LOC A28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[6]}] +set_property -dict {LOC C29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[7]}] +set_property -dict {LOC B29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[7]}] +set_property -dict {LOC E39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[8]}] +set_property -dict {LOC E40 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[8]}] +set_property -dict {LOC G37 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[9]}] +set_property -dict {LOC F37 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[9]}] +set_property -dict {LOC N31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[10]}] +set_property -dict {LOC M31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[10]}] +set_property -dict {LOC T30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[11]}] +set_property -dict {LOC R31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[11]}] +set_property -dict {LOC L35 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[12]}] +set_property -dict {LOC L36 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[12]}] +set_property -dict {LOC M34 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[13]}] +set_property -dict {LOC L34 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[13]}] +set_property -dict {LOC J38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[14]}] +set_property -dict {LOC H38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[14]}] +set_property -dict {LOC H33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[15]}] +set_property -dict {LOC H34 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[15]}] +set_property -dict {LOC B39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[16]}] +set_property -dict {LOC A39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[16]}] +set_property -dict {LOC C37 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[17]}] +set_property -dict {LOC C38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[17]}] + +# DDR4 C3 +set_property -dict {LOC K15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[0]}] +set_property -dict {LOC B15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[1]}] +set_property -dict {LOC F14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[2]}] +set_property -dict {LOC A15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[3]}] +set_property -dict {LOC C14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[4]}] +set_property -dict {LOC A14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[5]}] +set_property -dict {LOC B14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[6]}] +set_property -dict {LOC E13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[7]}] +set_property -dict {LOC F13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[8]}] +set_property -dict {LOC A13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[9]}] +set_property -dict {LOC D14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[10]}] +set_property -dict {LOC C13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[11]}] +set_property -dict {LOC B13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[12]}] +set_property -dict {LOC K16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[13]}] +set_property -dict {LOC D15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[14]}] +set_property -dict {LOC E15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[15]}] +set_property -dict {LOC F15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[16]}] +set_property -dict {LOC J15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_ba[0]}] +set_property -dict {LOC H14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_ba[1]}] +set_property -dict {LOC D13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_bg[0]}] +set_property -dict {LOC J13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_bg[1]}] +set_property -dict {LOC L14 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_t[0]}] +set_property -dict {LOC L13 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_c[0]}] +#set_property -dict {LOC G14 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_t[1]}] +#set_property -dict {LOC G13 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_c[1]}] +set_property -dict {LOC K13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cke[0]}] +#set_property -dict {LOC L15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cke[1]}] +set_property -dict {LOC B16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[0]}] +#set_property -dict {LOC D16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[1]}] +#set_property -dict {LOC M14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[2]}] +#set_property -dict {LOC M13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[3]}] +set_property -dict {LOC H13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_act_n}] +set_property -dict {LOC C16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_odt[0]}] +#set_property -dict {LOC E16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_odt[1]}] +set_property -dict {LOC J14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_par}] +set_property -dict {LOC D21 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c3_reset_n}] + +set_property -dict {LOC P24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[0]}] +set_property -dict {LOC N24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[1]}] +set_property -dict {LOC T24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[2]}] +set_property -dict {LOC R23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[3]}] +set_property -dict {LOC N23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[4]}] +set_property -dict {LOC P21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[5]}] +set_property -dict {LOC P23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[6]}] +set_property -dict {LOC R21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[7]}] +set_property -dict {LOC J24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[8]}] +set_property -dict {LOC J23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[9]}] +set_property -dict {LOC H24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[10]}] +set_property -dict {LOC G24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[11]}] +set_property -dict {LOC L24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[12]}] +set_property -dict {LOC L23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[13]}] +set_property -dict {LOC K22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[14]}] +set_property -dict {LOC K21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[15]}] +set_property -dict {LOC G20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[16]}] +set_property -dict {LOC H17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[17]}] +set_property -dict {LOC F19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[18]}] +set_property -dict {LOC G17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[19]}] +set_property -dict {LOC J20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[20]}] +set_property -dict {LOC L19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[21]}] +set_property -dict {LOC L18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[22]}] +set_property -dict {LOC J19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[23]}] +set_property -dict {LOC M19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[24]}] +set_property -dict {LOC M20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[25]}] +set_property -dict {LOC R18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[26]}] +set_property -dict {LOC R17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[27]}] +set_property -dict {LOC R20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[28]}] +set_property -dict {LOC T20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[29]}] +set_property -dict {LOC N18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[30]}] +set_property -dict {LOC N19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[31]}] +set_property -dict {LOC A23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[32]}] +set_property -dict {LOC A22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[33]}] +set_property -dict {LOC B24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[34]}] +set_property -dict {LOC B25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[35]}] +set_property -dict {LOC B22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[36]}] +set_property -dict {LOC C22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[37]}] +set_property -dict {LOC C24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[38]}] +set_property -dict {LOC C23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[39]}] +set_property -dict {LOC C19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[40]}] +set_property -dict {LOC C18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[41]}] +set_property -dict {LOC C21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[42]}] +set_property -dict {LOC B21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[43]}] +set_property -dict {LOC A18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[44]}] +set_property -dict {LOC A17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[45]}] +set_property -dict {LOC A20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[46]}] +set_property -dict {LOC B20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[47]}] +set_property -dict {LOC E17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[48]}] +set_property -dict {LOC F20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[49]}] +set_property -dict {LOC E18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[50]}] +set_property -dict {LOC E20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[51]}] +set_property -dict {LOC D19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[52]}] +set_property -dict {LOC D20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[53]}] +set_property -dict {LOC H18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[54]}] +set_property -dict {LOC J18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[55]}] +set_property -dict {LOC F22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[56]}] +set_property -dict {LOC E22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[57]}] +set_property -dict {LOC G22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[58]}] +set_property -dict {LOC G21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[59]}] +set_property -dict {LOC F24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[60]}] +set_property -dict {LOC E25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[61]}] +set_property -dict {LOC F25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[62]}] +set_property -dict {LOC G25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[63]}] +set_property -dict {LOC M16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[64]}] +set_property -dict {LOC N16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[65]}] +set_property -dict {LOC N13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[66]}] +set_property -dict {LOC N14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[67]}] +set_property -dict {LOC T15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[68]}] +set_property -dict {LOC R15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[69]}] +set_property -dict {LOC P13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[70]}] +set_property -dict {LOC P14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[71]}] +set_property -dict {LOC T22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[0]}] +set_property -dict {LOC R22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[0]}] +set_property -dict {LOC N22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[1]}] +set_property -dict {LOC N21 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[1]}] +set_property -dict {LOC J21 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[2]}] +set_property -dict {LOC H21 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[2]}] +set_property -dict {LOC M22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[3]}] +set_property -dict {LOC L22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[3]}] +set_property -dict {LOC L20 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[4]}] +set_property -dict {LOC K20 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[4]}] +set_property -dict {LOC K18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[5]}] +set_property -dict {LOC K17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[5]}] +set_property -dict {LOC P19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[6]}] +set_property -dict {LOC P18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[6]}] +set_property -dict {LOC N17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[7]}] +set_property -dict {LOC M17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[7]}] +set_property -dict {LOC A25 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[8]}] +set_property -dict {LOC A24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[8]}] +set_property -dict {LOC D24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[9]}] +set_property -dict {LOC D23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[9]}] +set_property -dict {LOC C17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[10]}] +set_property -dict {LOC B17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[10]}] +set_property -dict {LOC B19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[11]}] +set_property -dict {LOC A19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[11]}] +set_property -dict {LOC F18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[12]}] +set_property -dict {LOC F17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[12]}] +set_property -dict {LOC H19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[13]}] +set_property -dict {LOC G19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[13]}] +set_property -dict {LOC F23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[14]}] +set_property -dict {LOC E23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[14]}] +set_property -dict {LOC H23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[15]}] +set_property -dict {LOC H22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[15]}] +set_property -dict {LOC R16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[16]}] +set_property -dict {LOC P15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[16]}] +set_property -dict {LOC T13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[17]}] +set_property -dict {LOC R13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[17]}] diff --git a/fpga/mqnic/Alveo/fpga_100g/fpga_au50.xdc b/fpga/mqnic/Alveo/fpga_100g/fpga_au50.xdc new file mode 100644 index 0000000..bbbb019 --- /dev/null +++ b/fpga/mqnic/Alveo/fpga_100g/fpga_au50.xdc @@ -0,0 +1,204 @@ +# XDC constraints for the Xilinx Alveo U50 board +# part: xcu50-fsvh2104-2-e + +# General configuration +set_property CFGBVS GND [current_design] +set_property CONFIG_VOLTAGE 1.8 [current_design] +set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design] +set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] +set_property CONFIG_MODE SPIx4 [current_design] +set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] +set_property BITSTREAM.CONFIG.CONFIGRATE 85.0 [current_design] +set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN DISABLE [current_design] +set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] +set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design] +set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] +set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design] + +set_operating_conditions -design_power_budget 63 + +# System clocks +# 100 MHz +#set_property -dict {LOC G17 IOSTANDARD LVDS} [get_ports clk_100mhz_0_p] +#set_property -dict {LOC G16 IOSTANDARD LVDS} [get_ports clk_100mhz_0_n] +#create_clock -period 10 -name clk_100mhz_0 [get_ports clk_100mhz_0_p] + +# 100 MHz +set_property -dict {LOC BB18 IOSTANDARD LVDS} [get_ports clk_100mhz_1_p] +set_property -dict {LOC BC18 IOSTANDARD LVDS} [get_ports clk_100mhz_1_n] +create_clock -period 10 -name clk_100mhz_1 [get_ports clk_100mhz_1_p] + +# LEDs +set_property -dict {LOC E18 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_led_act] +set_property -dict {LOC E16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_led_stat_g] +set_property -dict {LOC F17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_led_stat_y] + +set_false_path -to [get_ports {qsfp_led_act qsfp_led_stat_g qsfp_led_stat_y}] +set_output_delay 0 [get_ports {qsfp_led_act qsfp_led_stat_g qsfp_led_stat_y}] + +# UART +#set_property -dict {LOC BE26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart0_txd] +#set_property -dict {LOC BF26 IOSTANDARD LVCMOS18} [get_ports usb_uart0_rxd] +#set_property -dict {LOC A17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart1_txd] +#set_property -dict {LOC B15 IOSTANDARD LVCMOS18} [get_ports usb_uart1_rxd] +#set_property -dict {LOC A19 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart2_txd] +#set_property -dict {LOC A18 IOSTANDARD LVCMOS18} [get_ports usb_uart2_rxd] + +#set_false_path -to [get_ports {usb_uart0_txd usb_uart1_txd usb_uart2_txd}] +#set_output_delay 0 [get_ports {usb_uart0_txd usb_uart1_txd usb_uart2_txd}] +#set_false_path -from [get_ports {usb_uart0_rxd usb_uart1_rxd usb_uart2_rxd}] +#set_input_delay 0 [get_ports {usb_uart0_rxd usb_uart1_rxd usb_uart2_rxd}] + +# BMC +set_property -dict {LOC C16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[0]}] +set_property -dict {LOC C17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[1]}] +set_property -dict {LOC BB25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_uart_txd}] +set_property -dict {LOC BB26 IOSTANDARD LVCMOS18} [get_ports {msp_uart_rxd}] + +set_false_path -to [get_ports {msp_uart_txd}] +set_output_delay 0 [get_ports {msp_uart_txd}] +set_false_path -from [get_ports {msp_gpio[*] msp_uart_rxd}] +set_input_delay 0 [get_ports {msp_gpio[*] msp_uart_rxd}] + +# HBM overtemp +set_property -dict {LOC J18 IOSTANDARD LVCMOS18} [get_ports hbm_cattrip] + +set_false_path -to [get_ports {hbm_cattrip}] +set_output_delay 0 [get_ports {hbm_cattrip}] + +# SI5394 (SI5394B-A10605-GM) +# I2C address 0x68 +# IN0: 161.1328125 MHz from qsfp_recclk +# OUT0: 161.1328125 MHz to qsfp_mgt_refclk_0 +# OUT2: 322.265625 MHz to qsfp_mgt_refclk_1 +# OUT3: 100 MHz to clk_100mhz_0, clk_100mhz_1, pcie_refclk_2, pcie_refclk_3 +#set_property -dict {LOC F20 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports si5394_rst_b] +#set_property -dict {LOC H18 IOSTANDARD LVCMOS18 PULLUP true} [get_ports si5394_int_b] +#set_property -dict {LOC G19 IOSTANDARD LVCMOS18 PULLUP true} [get_ports si5394_lol_b] +#set_property -dict {LOC H19 IOSTANDARD LVCMOS18 PULLUP true} [get_ports si5394_los_b] +#set_property -dict {LOC J16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8 PULLUP true} [get_ports si5394_i2c_sda] +#set_property -dict {LOC L19 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8 PULLUP true} [get_ports si5394_i2c_scl] + +#set_false_path -to [get_ports {si5394_rst_b}] +#set_output_delay 0 [get_ports {si5394_rst_b}] +#set_false_path -from [get_ports {si5394_int_b si5394_lol_b si5394_los_b}] +#set_input_delay 0 [get_ports {si5394_int_b si5394_lol_b si5394_los_b}] + +#set_false_path -to [get_ports {si5394_i2c_sda si5394_i2c_scl}] +#set_output_delay 0 [get_ports {si5394_i2c_sda si5394_i2c_scl}] +#set_false_path -from [get_ports {si5394_i2c_sda si5394_i2c_scl}] +#set_input_delay 0 [get_ports {si5394_i2c_sda si5394_i2c_scl}] + +# QSFP28 Interfaces +set_property -dict {LOC J45 } [get_ports {qsfp_rx_p[0]}] ;# MGTYRXP0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC J46 } [get_ports {qsfp_rx_n[0]}] ;# MGTYRXN0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC D42 } [get_ports {qsfp_tx_p[0]}] ;# MGTYTXP0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC D43 } [get_ports {qsfp_tx_n[0]}] ;# MGTYTXN0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC G45 } [get_ports {qsfp_rx_p[1]}] ;# MGTYRXP1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC G46 } [get_ports {qsfp_rx_n[1]}] ;# MGTYRXN1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC C40 } [get_ports {qsfp_tx_p[1]}] ;# MGTYTXP1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC C41 } [get_ports {qsfp_tx_n[1]}] ;# MGTYTXN1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC F43 } [get_ports {qsfp_rx_p[2]}] ;# MGTYRXP2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC F44 } [get_ports {qsfp_rx_n[2]}] ;# MGTYRXN2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC B42 } [get_ports {qsfp_tx_p[2]}] ;# MGTYTXP2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC B43 } [get_ports {qsfp_tx_n[2]}] ;# MGTYTXN2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC E45 } [get_ports {qsfp_rx_p[3]}] ;# MGTYRXP3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC E46 } [get_ports {qsfp_rx_n[3]}] ;# MGTYRXN3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC A40 } [get_ports {qsfp_tx_p[3]}] ;# MGTYTXP3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC A41 } [get_ports {qsfp_tx_n[3]}] ;# MGTYTXN3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 +set_property -dict {LOC N36 } [get_ports qsfp_mgt_refclk_0_p] ;# MGTREFCLK0P_131 from SI5394 OUT0 +set_property -dict {LOC N37 } [get_ports qsfp_mgt_refclk_0_n] ;# MGTREFCLK0N_131 from SI5394 OUT0 +#set_property -dict {LOC M38 } [get_ports qsfp_mgt_refclk_1_p] ;# MGTREFCLK1P_131 from SI5394 OUT2 +#set_property -dict {LOC M39 } [get_ports qsfp_mgt_refclk_1_n] ;# MGTREFCLK1N_131 from SI5394 OUT2 +#set_property -dict {LOC F19 IOSTANDARD LVDS} [get_ports qsfp_recclk_p] ;# to SI5394 IN0 +#set_property -dict {LOC F18 IOSTANDARD LVDS} [get_ports qsfp_recclk_n] ;# to SI5394 IN0 + +# 161.1328125 MHz MGT reference clock (SI5394 OUT0) +create_clock -period 6.206 -name qsfp_mgt_refclk_0 [get_ports qsfp_mgt_refclk_0_p] + +# 322.265625 MHz MGT reference clock (SI5394 OUT2) +#create_clock -period 3.103 -name qsfp_mgt_refclk_1 [get_ports qsfp_mgt_refclk_1_p] + +# PCIe Interface +set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC Y5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC Y4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AM4 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AM3 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AA7 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AA6 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AK4 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AK3 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AB5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AB4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AC7 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AC6 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AP4 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AP3 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AD5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AD4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AF5 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AF4 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AT4 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AT3 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AE7 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AE6 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AH5 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AH4 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AG7 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AG6 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AW2 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AW1 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AJ7 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AJ6 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC BA2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC BA1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AL7 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AL6 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC BC2 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC BC1 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AM9 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AM8 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AY4 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AY3 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AN7 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AN6 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BB4 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BB3 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AP9 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AP8 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BD4 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BD3 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AR7 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AR6 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BE6 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BE5 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AT9 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AT8 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AB9 } [get_ports pcie_refclk_0_p] ;# MGTREFCLK0P_227 (for x8 bifurcated lanes 0-7) +#set_property -dict {LOC AB8 } [get_ports pcie_refclk_0_n] ;# MGTREFCLK0N_227 (for x8 bifurcated lanes 0-7) +#set_property -dict {LOC AA11} [get_ports pcie_refclk_2_p] ;# MGTREFCLK1P_227 (for async x8 bifurcated lanes 0-7) +#set_property -dict {LOC AA10} [get_ports pcie_refclk_2_n] ;# MGTREFCLK1N_227 (for async x8 bifurcated lanes 0-7) +set_property -dict {LOC AF9 } [get_ports pcie_refclk_1_p] ;# MGTREFCLK0P_225 (for x16 or x8 bifurcated lanes 8-16) +set_property -dict {LOC AF8 } [get_ports pcie_refclk_1_n] ;# MGTREFCLK0N_225 (for x16 or x8 bifurcated lanes 8-16) +#set_property -dict {LOC AE11} [get_ports pcie_refclk_3_p] ;# MGTREFCLK1P_225 (for async x16 or x8 bifurcated lanes 8-16) +#set_property -dict {LOC AE10} [get_ports pcie_refclk_3_n] ;# MGTREFCLK1N_225 (for async x16 or x8 bifurcated lanes 8-16) +set_property -dict {LOC AW27 IOSTANDARD LVCMOS18 PULLUP true} [get_ports pcie_reset_n] + +# 100 MHz MGT reference clock +#create_clock -period 10 -name pcie_mgt_refclk_0 [get_ports pcie_refclk_0_p] +create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] +#create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] +#create_clock -period 10 -name pcie_mgt_refclk_3 [get_ports pcie_refclk_3_p] + +set_false_path -from [get_ports {pcie_reset_n}] +set_input_delay 0 [get_ports {pcie_reset_n}] diff --git a/fpga/mqnic/Alveo/fpga_100g/ip/pcie4_uscale_plus_0.tcl b/fpga/mqnic/Alveo/fpga_100g/ip/pcie4_uscale_plus_0.tcl index 2b1fecd..0fe23bc 100644 --- a/fpga/mqnic/Alveo/fpga_100g/ip/pcie4_uscale_plus_0.tcl +++ b/fpga/mqnic/Alveo/fpga_100g/ip/pcie4_uscale_plus_0.tcl @@ -1,34 +1,62 @@ create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -module_name pcie4_uscale_plus_0 -set_property -dict [list \ - CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \ - CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X16} \ - CONFIG.AXISTEN_IF_EXT_512_CQ_STRADDLE {true} \ - CONFIG.AXISTEN_IF_EXT_512_RQ_STRADDLE {true} \ - CONFIG.AXISTEN_IF_EXT_512_RC_4TLP_STRADDLE {true} \ - CONFIG.axisten_if_enable_client_tag {true} \ - CONFIG.axisten_if_width {512_bit} \ - CONFIG.extended_tag_field {true} \ - CONFIG.pf0_dev_cap_max_payload {1024_bytes} \ - CONFIG.axisten_freq {250} \ - CONFIG.PF0_Use_Class_Code_Lookup_Assistant {false} \ - CONFIG.PF0_CLASS_CODE {020000} \ - CONFIG.PF0_DEVICE_ID {1001} \ - CONFIG.PF0_SUBSYSTEM_ID {90c8} \ - CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} \ - CONFIG.pf0_bar0_64bit {true} \ - CONFIG.pf0_bar0_prefetchable {true} \ - CONFIG.pf0_bar0_scale {Megabytes} \ - CONFIG.pf0_bar0_size {16} \ - CONFIG.pf0_msi_enabled {false} \ - CONFIG.pf0_msix_enabled {true} \ - CONFIG.PF0_MSIX_CAP_TABLE_SIZE {01F} \ - CONFIG.PF0_MSIX_CAP_TABLE_BIR {BAR_1:0} \ - CONFIG.PF0_MSIX_CAP_TABLE_OFFSET {00010000} \ - CONFIG.PF0_MSIX_CAP_PBA_BIR {BAR_1:0} \ - CONFIG.PF0_MSIX_CAP_PBA_OFFSET {00018000} \ - CONFIG.MSI_X_OPTIONS {MSI-X_External} \ - CONFIG.vendor_id {1234} \ - CONFIG.mode_selection {Advanced} \ -] [get_ips pcie4_uscale_plus_0] +set_property -dict { + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X16} + CONFIG.AXISTEN_IF_EXT_512_CQ_STRADDLE {true} + CONFIG.AXISTEN_IF_EXT_512_RQ_STRADDLE {true} + CONFIG.AXISTEN_IF_EXT_512_RC_4TLP_STRADDLE {true} + CONFIG.axisten_if_enable_client_tag {true} + CONFIG.type1_membase_memlimit_enable {Disabled} + CONFIG.type1_prefetchable_membase_memlimit {Disabled} + CONFIG.PF0_CLASS_CODE {020000} + CONFIG.PF0_DEVICE_ID {1001} + CONFIG.PF0_MSIX_CAP_PBA_BIR {BAR_1:0} + CONFIG.PF0_MSIX_CAP_PBA_OFFSET {00018000} + CONFIG.PF0_MSIX_CAP_TABLE_BIR {BAR_1:0} + CONFIG.PF0_MSIX_CAP_TABLE_OFFSET {00010000} + CONFIG.PF0_MSIX_CAP_TABLE_SIZE {01F} + CONFIG.PF0_REVISION_ID {00} + CONFIG.PF0_SRIOV_CAP_INITIAL_VF {252} + CONFIG.PF0_SRIOV_FIRST_VF_OFFSET {4} + CONFIG.PF0_SUBSYSTEM_ID {9118} + CONFIG.SRIOV_CAP_ENABLE {true} + CONFIG.PF0_Use_Class_Code_Lookup_Assistant {false} + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} + CONFIG.pf1_sriov_bar0_64bit {true} + CONFIG.pf2_sriov_bar0_64bit {true} + CONFIG.pf3_sriov_bar0_64bit {true} + CONFIG.pf1_sriov_bar0_scale {Megabytes} + CONFIG.pf1_sriov_bar0_prefetchable {true} + CONFIG.pf0_sriov_bar0_size {16} + CONFIG.pf0_bar0_enabled {true} + CONFIG.pf0_bar0_type {Memory} + CONFIG.pf0_bar0_64bit {true} + CONFIG.pf0_bar0_prefetchable {true} + CONFIG.pf0_bar0_scale {Megabytes} + CONFIG.pf0_bar0_size {16} + CONFIG.pf0_bar2_enabled {false} + CONFIG.pf0_dev_cap_max_payload {1024_bytes} + CONFIG.pf1_sriov_bar0_size {16} + CONFIG.extended_tag_field {true} + CONFIG.pf0_sriov_bar0_prefetchable {true} + CONFIG.vendor_id {1234} + CONFIG.pf0_ari_enabled {true} + CONFIG.axisten_if_width {512_bit} + CONFIG.pf0_sriov_bar0_64bit {true} + CONFIG.pf0_msi_enabled {false} + CONFIG.pf0_msix_enabled {true} + CONFIG.pf0_sriov_bar0_scale {Megabytes} + CONFIG.pf2_sriov_bar0_scale {Megabytes} + CONFIG.pf2_sriov_bar0_prefetchable {true} + CONFIG.pf2_sriov_bar0_size {16} + CONFIG.pf3_sriov_bar0_scale {Megabytes} + CONFIG.pf3_sriov_bar0_prefetchable {true} + CONFIG.pf3_sriov_bar0_size {16} + CONFIG.mode_selection {Advanced} + CONFIG.axisten_freq {250} + CONFIG.PL_DISABLE_LANE_REVERSAL {TRUE} + CONFIG.MSI_X_OPTIONS {MSI-X_External} +} [get_ips pcie4_uscale_plus_0] + diff --git a/fpga/mqnic/Alveo/fpga_100g/placement_au200.xdc b/fpga/mqnic/Alveo/fpga_100g/placement_au200.xdc new file mode 100644 index 0000000..2cf5ba5 --- /dev/null +++ b/fpga/mqnic/Alveo/fpga_100g/placement_au200.xdc @@ -0,0 +1,36 @@ +# Placement constraints +create_pblock pblock_slr0 +#add_cells_to_pblock [get_pblocks pblock_slr0] [get_cells -quiet ""] +resize_pblock [get_pblocks pblock_slr0] -add {SLR0} + +create_pblock pblock_slr1 +add_cells_to_pblock [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/dma_if_mux_inst"] +add_cells_to_pblock -quiet [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/dma_if_mux.dma_if_mux_ctrl_inst"] +add_cells_to_pblock -quiet [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/dma_if_mux.dma_if_mux_data_inst"] +add_cells_to_pblock [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/interface_rx_inst"] +add_cells_to_pblock [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/interface_tx_inst"] +add_cells_to_pblock [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/tx_fifo_inst"] +add_cells_to_pblock [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/rx_fifo_inst"] +resize_pblock [get_pblocks pblock_slr1] -add {SLR1} + +create_pblock pblock_slr2 +#add_cells_to_pblock [get_pblocks pblock_slr2] [get_cells -quiet ""] +resize_pblock [get_pblocks pblock_slr2] -add {SLR2} + +create_pblock pblock_pcie +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "pcie4_uscale_plus_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/pcie_if_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/pcie_axil_master_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/dma_if_pcie_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/pcie_msix_inst"] +resize_pblock [get_pblocks pblock_pcie] -add {CLOCKREGION_X4Y5:CLOCKREGION_X5Y8} + +create_pblock pblock_eth +add_cells_to_pblock [get_pblocks pblock_eth] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/port[*].port_inst/port_tx_inst/tx_async_fifo_inst"] +add_cells_to_pblock [get_pblocks pblock_eth] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/port[*].port_inst/port_rx_inst/rx_async_fifo_inst"] +add_cells_to_pblock [get_pblocks pblock_eth] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/port[*].port_inst/port_tx_inst/tx_cpl_fifo_inst"] +resize_pblock [get_pblocks pblock_eth] -add {CLOCKREGION_X0Y10:CLOCKREGION_X0Y14} + +# CMACs +set_property LOC CMACE4_X0Y8 [get_cells -hierarchical -filter {NAME =~ qsfp0_cmac_inst/cmac_inst/inst/i_cmac_usplus_top/* && REF_NAME==CMACE4}] +set_property LOC CMACE4_X0Y7 [get_cells -hierarchical -filter {NAME =~ qsfp1_cmac_inst/cmac_inst/inst/i_cmac_usplus_top/* && REF_NAME==CMACE4}] diff --git a/fpga/mqnic/Alveo/fpga_100g/placement_au250.xdc b/fpga/mqnic/Alveo/fpga_100g/placement_au250.xdc new file mode 100644 index 0000000..e090ba4 --- /dev/null +++ b/fpga/mqnic/Alveo/fpga_100g/placement_au250.xdc @@ -0,0 +1,40 @@ +# Placement constraints +create_pblock pblock_slr0 +#add_cells_to_pblock [get_pblocks pblock_slr0] [get_cells -quiet ""] +resize_pblock [get_pblocks pblock_slr0] -add {SLR0} + +create_pblock pblock_slr1 +add_cells_to_pblock [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/dma_if_mux_inst"] +add_cells_to_pblock -quiet [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/dma_if_mux.dma_if_mux_ctrl_inst"] +add_cells_to_pblock -quiet [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/dma_if_mux.dma_if_mux_data_inst"] +add_cells_to_pblock [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/interface_rx_inst"] +add_cells_to_pblock [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/interface_tx_inst"] +add_cells_to_pblock [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/tx_fifo_inst"] +add_cells_to_pblock [get_pblocks pblock_slr1] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/rx_fifo_inst"] +resize_pblock [get_pblocks pblock_slr1] -add {SLR1} + +create_pblock pblock_slr2 +#add_cells_to_pblock [get_pblocks pblock_slr2] [get_cells -quiet ""] +resize_pblock [get_pblocks pblock_slr2] -add {SLR2} + +create_pblock pblock_slr3 +#add_cells_to_pblock [get_pblocks pblock_slr3] [get_cells -quiet ""] +resize_pblock [get_pblocks pblock_slr3] -add {SLR3} + +create_pblock pblock_pcie +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "pcie4_uscale_plus_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/pcie_if_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/pcie_axil_master_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/dma_if_pcie_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/pcie_msix_inst"] +resize_pblock [get_pblocks pblock_pcie] -add {CLOCKREGION_X6Y4:CLOCKREGION_X7Y7} + +create_pblock pblock_eth +add_cells_to_pblock [get_pblocks pblock_eth] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/port[*].port_inst/port_tx_inst/tx_async_fifo_inst"] +add_cells_to_pblock [get_pblocks pblock_eth] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/port[*].port_inst/port_rx_inst/rx_async_fifo_inst"] +add_cells_to_pblock [get_pblocks pblock_eth] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/port[*].port_inst/port_tx_inst/tx_cpl_fifo_inst"] +resize_pblock [get_pblocks pblock_eth] -add {CLOCKREGION_X0Y8:CLOCKREGION_X0Y11} + +# CMACs +set_property LOC CMACE4_X0Y8 [get_cells -hierarchical -filter {NAME =~ qsfp0_cmac_inst/cmac_inst/inst/i_cmac_usplus_top/* && REF_NAME==CMACE4}] +set_property LOC CMACE4_X0Y7 [get_cells -hierarchical -filter {NAME =~ qsfp1_cmac_inst/cmac_inst/inst/i_cmac_usplus_top/* && REF_NAME==CMACE4}] diff --git a/fpga/mqnic/Alveo/fpga_100g/placement_au50.xdc b/fpga/mqnic/Alveo/fpga_100g/placement_au50.xdc new file mode 100644 index 0000000..bd1cec4 --- /dev/null +++ b/fpga/mqnic/Alveo/fpga_100g/placement_au50.xdc @@ -0,0 +1,32 @@ +# Placement constraints +create_pblock pblock_slr0 +add_cells_to_pblock [get_pblocks pblock_slr0] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/dma_if_mux_inst"] +add_cells_to_pblock -quiet [get_pblocks pblock_slr0] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/dma_if_mux.dma_if_mux_ctrl_inst"] +add_cells_to_pblock -quiet [get_pblocks pblock_slr0] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/dma_if_mux.dma_if_mux_data_inst"] +add_cells_to_pblock [get_pblocks pblock_slr0] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/interface_rx_inst"] +add_cells_to_pblock [get_pblocks pblock_slr0] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/interface_tx_inst"] +add_cells_to_pblock [get_pblocks pblock_slr0] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/tx_fifo_inst"] +add_cells_to_pblock [get_pblocks pblock_slr0] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/rx_fifo_inst"] +resize_pblock [get_pblocks pblock_slr0] -add {SLR0} + +create_pblock pblock_slr1 +#add_cells_to_pblock [get_pblocks pblock_slr1] [get_cells -quiet ""] +resize_pblock [get_pblocks pblock_slr1] -add {SLR1} + +create_pblock pblock_pcie +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "pcie4c_uscale_plus_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/pcie_if_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/pcie_axil_master_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/dma_if_pcie_inst"] +add_cells_to_pblock [get_pblocks pblock_pcie] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/pcie_msix_inst"] +resize_pblock [get_pblocks pblock_pcie] -add {CLOCKREGION_X6Y0:CLOCKREGION_X7Y3} + +create_pblock pblock_eth +add_cells_to_pblock [get_pblocks pblock_eth] [get_cells -quiet "qsfp_cmac_inst"] +add_cells_to_pblock [get_pblocks pblock_eth] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/port[*].port_inst/port_tx_inst/tx_async_fifo_inst"] +add_cells_to_pblock [get_pblocks pblock_eth] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/port[*].port_inst/port_rx_inst/rx_async_fifo_inst"] +add_cells_to_pblock [get_pblocks pblock_eth] [get_cells -quiet "core_inst/core_inst/core_pcie_inst/core_inst/iface[*].interface_inst/port[*].port_inst/port_tx_inst/tx_cpl_fifo_inst"] +resize_pblock [get_pblocks pblock_eth] -add {CLOCKREGION_X0Y6:CLOCKREGION_X0Y7} + +# CMACs +set_property LOC CMACE4_X0Y4 [get_cells -hierarchical -filter {NAME =~ qsfp_cmac_inst/cmac_inst/inst/i_cmac_usplus_top/* && REF_NAME==CMACE4}] diff --git a/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au200.v b/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au200.v new file mode 100644 index 0000000..356d183 --- /dev/null +++ b/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au200.v @@ -0,0 +1,2500 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga # +( + // FW and board IDs + parameter FPGA_ID = 32'h4B37093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_90c8, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, + + // Board configuration + parameter CMS_ENABLE = 1, + + // Structural configuration + parameter IF_COUNT = 2, + parameter PORTS_PER_IF = 1, + parameter SCHED_PER_IF = PORTS_PER_IF, + parameter PORT_MASK = 0, + + // Clock configuration + parameter CLK_PERIOD_NS_NUM = 4, + parameter CLK_PERIOD_NS_DENOM = 1, + + // PTP configuration + parameter PTP_CLOCK_PIPELINE = 0, + parameter PTP_CLOCK_CDC_PIPELINE = 0, + parameter PTP_PORT_CDC_PIPELINE = 0, + parameter PTP_PEROUT_ENABLE = 0, + parameter PTP_PEROUT_COUNT = 1, + + // Queue manager configuration + parameter EVENT_QUEUE_OP_TABLE_SIZE = 32, + parameter TX_QUEUE_OP_TABLE_SIZE = 32, + parameter RX_QUEUE_OP_TABLE_SIZE = 32, + parameter CQ_OP_TABLE_SIZE = 32, + parameter EQN_WIDTH = 5, + parameter TX_QUEUE_INDEX_WIDTH = 13, + parameter RX_QUEUE_INDEX_WIDTH = 8, + parameter CQN_WIDTH = (TX_QUEUE_INDEX_WIDTH > RX_QUEUE_INDEX_WIDTH ? TX_QUEUE_INDEX_WIDTH : RX_QUEUE_INDEX_WIDTH) + 1, + parameter EQ_PIPELINE = 3, + parameter TX_QUEUE_PIPELINE = 3+(TX_QUEUE_INDEX_WIDTH > 12 ? TX_QUEUE_INDEX_WIDTH-12 : 0), + parameter RX_QUEUE_PIPELINE = 3+(RX_QUEUE_INDEX_WIDTH > 12 ? RX_QUEUE_INDEX_WIDTH-12 : 0), + parameter CQ_PIPELINE = 3+(CQN_WIDTH > 12 ? CQN_WIDTH-12 : 0), + + // TX and RX engine configuration + parameter TX_DESC_TABLE_SIZE = 32, + parameter RX_DESC_TABLE_SIZE = 32, + parameter RX_INDIR_TBL_ADDR_WIDTH = RX_QUEUE_INDEX_WIDTH > 8 ? 8 : RX_QUEUE_INDEX_WIDTH, + + // Scheduler configuration + parameter TX_SCHEDULER_OP_TABLE_SIZE = TX_DESC_TABLE_SIZE, + parameter TX_SCHEDULER_PIPELINE = TX_QUEUE_PIPELINE, + parameter TDMA_INDEX_WIDTH = 6, + + // Interface configuration + parameter PTP_TS_ENABLE = 1, + parameter TX_CPL_FIFO_DEPTH = 32, + parameter TX_CHECKSUM_ENABLE = 1, + parameter RX_HASH_ENABLE = 1, + parameter RX_CHECKSUM_ENABLE = 1, + parameter PFC_ENABLE = 1, + parameter LFC_ENABLE = PFC_ENABLE, + parameter TX_FIFO_DEPTH = 32768, + parameter RX_FIFO_DEPTH = 131072, + parameter MAX_TX_SIZE = 9214, + parameter MAX_RX_SIZE = 9214, + parameter TX_RAM_SIZE = 131072, + parameter RX_RAM_SIZE = 131072, + + // RAM configuration + parameter DDR_CH = 4, + parameter DDR_ENABLE = 0, + parameter AXI_DDR_DATA_WIDTH = 512, + parameter AXI_DDR_ADDR_WIDTH = 34, + parameter AXI_DDR_ID_WIDTH = 8, + parameter AXI_DDR_MAX_BURST_LEN = 256, + parameter AXI_DDR_NARROW_BURST = 0, + + // Application block configuration + parameter APP_ID = 32'h00000000, + parameter APP_ENABLE = 0, + parameter APP_CTRL_ENABLE = 1, + parameter APP_DMA_ENABLE = 1, + parameter APP_AXIS_DIRECT_ENABLE = 1, + parameter APP_AXIS_SYNC_ENABLE = 1, + parameter APP_AXIS_IF_ENABLE = 1, + parameter APP_STAT_ENABLE = 1, + + // DMA interface configuration + parameter DMA_IMM_ENABLE = 0, + parameter DMA_IMM_WIDTH = 32, + parameter DMA_LEN_WIDTH = 16, + parameter DMA_TAG_WIDTH = 16, + parameter RAM_ADDR_WIDTH = $clog2(TX_RAM_SIZE > RX_RAM_SIZE ? TX_RAM_SIZE : RX_RAM_SIZE), + parameter RAM_PIPELINE = 2, + + // PCIe interface configuration + parameter AXIS_PCIE_DATA_WIDTH = 512, + parameter PF_COUNT = 1, + parameter VF_COUNT = 0, + + // Interrupt configuration + parameter IRQ_INDEX_WIDTH = EQN_WIDTH - FUNCTION_ID_WIDTH, + + // AXI lite interface configuration (control) + parameter AXIL_CTRL_DATA_WIDTH = 32, + parameter AXIL_CTRL_ADDR_WIDTH = 24, + + // AXI lite interface configuration (application control) + parameter AXIL_APP_CTRL_DATA_WIDTH = AXIL_CTRL_DATA_WIDTH, + parameter AXIL_APP_CTRL_ADDR_WIDTH = 24, + + // Ethernet interface configuration + parameter AXIS_ETH_TX_PIPELINE = 4, + parameter AXIS_ETH_TX_FIFO_PIPELINE = 4, + parameter AXIS_ETH_TX_TS_PIPELINE = 4, + parameter AXIS_ETH_RX_PIPELINE = 4, + parameter AXIS_ETH_RX_FIFO_PIPELINE = 4, + + // Statistics counter subsystem + parameter STAT_ENABLE = 1, + parameter STAT_DMA_ENABLE = 1, + parameter STAT_PCIE_ENABLE = 1, + parameter STAT_INC_WIDTH = 24, + parameter STAT_ID_WIDTH = 12, + parameter FUNCTION_ID_WIDTH = 8 // Scott +) +( + /* + * Clock and reset + */ + input wire clk_300mhz_0_p, + input wire clk_300mhz_0_n, + input wire clk_300mhz_1_p, + input wire clk_300mhz_1_n, + input wire clk_300mhz_2_p, + input wire clk_300mhz_2_n, + input wire clk_300mhz_3_p, + input wire clk_300mhz_3_n, + + /* + * GPIO + */ + input wire [3:0] sw, + output wire [2:0] led, + input wire [3:0] msp_gpio, + output wire msp_uart_txd, + input wire msp_uart_rxd, + + /* + * I2C for board management + */ + inout wire i2c_scl, + inout wire i2c_sda, + + /* + * PCI express + */ + input wire [15:0] pcie_rx_p, + input wire [15:0] pcie_rx_n, + output wire [15:0] pcie_tx_p, + output wire [15:0] pcie_tx_n, + input wire pcie_refclk_p, + input wire pcie_refclk_n, + input wire pcie_reset_n, + + /* + * Ethernet: QSFP28 + */ + output wire [3:0] qsfp0_tx_p, + output wire [3:0] qsfp0_tx_n, + input wire [3:0] qsfp0_rx_p, + input wire [3:0] qsfp0_rx_n, + // input wire qsfp0_mgt_refclk_0_p, + // input wire qsfp0_mgt_refclk_0_n, + input wire qsfp0_mgt_refclk_1_p, + input wire qsfp0_mgt_refclk_1_n, + output wire qsfp0_modsell, + output wire qsfp0_resetl, + input wire qsfp0_modprsl, + input wire qsfp0_intl, + output wire qsfp0_lpmode, + output wire qsfp0_refclk_reset, + output wire [1:0] qsfp0_fs, + + output wire [3:0] qsfp1_tx_p, + output wire [3:0] qsfp1_tx_n, + input wire [3:0] qsfp1_rx_p, + input wire [3:0] qsfp1_rx_n, + // input wire qsfp1_mgt_refclk_0_p, + // input wire qsfp1_mgt_refclk_0_n, + input wire qsfp1_mgt_refclk_1_p, + input wire qsfp1_mgt_refclk_1_n, + output wire qsfp1_modsell, + output wire qsfp1_resetl, + input wire qsfp1_modprsl, + input wire qsfp1_intl, + output wire qsfp1_lpmode, + output wire qsfp1_refclk_reset, + output wire [1:0] qsfp1_fs, + + /* + * DDR4 + */ + output wire [16:0] ddr4_c0_adr, + output wire [1:0] ddr4_c0_ba, + output wire [1:0] ddr4_c0_bg, + output wire [0:0] ddr4_c0_ck_t, + output wire [0:0] ddr4_c0_ck_c, + output wire [0:0] ddr4_c0_cke, + output wire [0:0] ddr4_c0_cs_n, + output wire ddr4_c0_act_n, + output wire [0:0] ddr4_c0_odt, + output wire ddr4_c0_par, + output wire ddr4_c0_reset_n, + inout wire [71:0] ddr4_c0_dq, + inout wire [17:0] ddr4_c0_dqs_t, + inout wire [17:0] ddr4_c0_dqs_c, + + output wire [16:0] ddr4_c1_adr, + output wire [1:0] ddr4_c1_ba, + output wire [1:0] ddr4_c1_bg, + output wire [0:0] ddr4_c1_ck_t, + output wire [0:0] ddr4_c1_ck_c, + output wire [0:0] ddr4_c1_cke, + output wire [0:0] ddr4_c1_cs_n, + output wire ddr4_c1_act_n, + output wire [0:0] ddr4_c1_odt, + output wire ddr4_c1_par, + output wire ddr4_c1_reset_n, + inout wire [71:0] ddr4_c1_dq, + inout wire [17:0] ddr4_c1_dqs_t, + inout wire [17:0] ddr4_c1_dqs_c, + + output wire [16:0] ddr4_c2_adr, + output wire [1:0] ddr4_c2_ba, + output wire [1:0] ddr4_c2_bg, + output wire [0:0] ddr4_c2_ck_t, + output wire [0:0] ddr4_c2_ck_c, + output wire [0:0] ddr4_c2_cke, + output wire [0:0] ddr4_c2_cs_n, + output wire ddr4_c2_act_n, + output wire [0:0] ddr4_c2_odt, + output wire ddr4_c2_par, + output wire ddr4_c2_reset_n, + inout wire [71:0] ddr4_c2_dq, + inout wire [17:0] ddr4_c2_dqs_t, + inout wire [17:0] ddr4_c2_dqs_c, + + output wire [16:0] ddr4_c3_adr, + output wire [1:0] ddr4_c3_ba, + output wire [1:0] ddr4_c3_bg, + output wire [0:0] ddr4_c3_ck_t, + output wire [0:0] ddr4_c3_ck_c, + output wire [0:0] ddr4_c3_cke, + output wire [0:0] ddr4_c3_cs_n, + output wire ddr4_c3_act_n, + output wire [0:0] ddr4_c3_odt, + output wire ddr4_c3_par, + output wire ddr4_c3_reset_n, + inout wire [71:0] ddr4_c3_dq, + inout wire [17:0] ddr4_c3_dqs_t, + inout wire [17:0] ddr4_c3_dqs_c +); + +// PTP configuration +parameter PTP_CLK_PERIOD_NS_NUM = 1024; +parameter PTP_CLK_PERIOD_NS_DENOM = 165; +parameter PTP_TS_WIDTH = 96; + +// Interface configuration +parameter TX_TAG_WIDTH = 16; + +// RAM configuration +parameter AXI_DDR_STRB_WIDTH = (AXI_DDR_DATA_WIDTH/8); + +// PCIe interface configuration +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 62 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; +parameter RC_STRADDLE = AXIS_PCIE_DATA_WIDTH >= 256; +parameter RQ_STRADDLE = AXIS_PCIE_DATA_WIDTH >= 512; +parameter CQ_STRADDLE = AXIS_PCIE_DATA_WIDTH >= 512; +parameter CC_STRADDLE = AXIS_PCIE_DATA_WIDTH >= 512; +parameter RQ_SEQ_NUM_WIDTH = 6; +parameter PCIE_TAG_COUNT = 256; + +// Ethernet interface configuration +parameter AXIS_ETH_DATA_WIDTH = 512; +parameter AXIS_ETH_KEEP_WIDTH = AXIS_ETH_DATA_WIDTH/8; +parameter AXIS_ETH_SYNC_DATA_WIDTH = AXIS_ETH_DATA_WIDTH; +parameter AXIS_ETH_TX_USER_WIDTH = TX_TAG_WIDTH + 1; +parameter AXIS_ETH_RX_USER_WIDTH = (PTP_TS_ENABLE ? PTP_TS_WIDTH : 0) + 1; + +// Clock and reset +wire pcie_user_clk; +wire pcie_user_reset; + +wire cfgmclk_int; + +wire clk_300mhz_0_ibufg; +wire clk_300mhz_0_int; + +wire clk_50mhz_mmcm_out; +wire clk_125mhz_mmcm_out; + +// Internal 50 MHz clock +wire clk_50mhz_int; +wire rst_50mhz_int; + +// Internal 125 MHz clock +wire clk_125mhz_int; +wire rst_125mhz_int; + +wire mmcm_rst; +wire mmcm_locked; +wire mmcm_clkfb; + +IBUFGDS #( + .DIFF_TERM("FALSE"), + .IBUF_LOW_PWR("FALSE") +) +clk_300mhz_0_ibufg_inst ( + .O (clk_300mhz_0_ibufg), + .I (clk_300mhz_0_p), + .IB (clk_300mhz_0_n) +); + +BUFG +clk_300mhz_0_bufg_inst ( + .I(clk_300mhz_0_ibufg), + .O(clk_300mhz_0_int) +); + +// MMCM instance +// 300 MHz in, 125 MHz + 50 MHz out +// PFD range: 10 MHz to 500 MHz +// VCO range: 800 MHz to 1600 MHz +// M = 10, D = 3 sets Fvco = 1000 MHz +// Divide by 8 to get output frequency of 125 MHz +// Divide by 20 to get output frequency of 50 MHz +MMCME4_BASE #( + .BANDWIDTH("OPTIMIZED"), + .CLKOUT0_DIVIDE_F(8), + .CLKOUT0_DUTY_CYCLE(0.5), + .CLKOUT0_PHASE(0), + .CLKOUT1_DIVIDE(20), + .CLKOUT1_DUTY_CYCLE(0.5), + .CLKOUT1_PHASE(0), + .CLKOUT2_DIVIDE(3), + .CLKOUT2_DUTY_CYCLE(0.5), + .CLKOUT2_PHASE(0), + .CLKOUT3_DIVIDE(1), + .CLKOUT3_DUTY_CYCLE(0.5), + .CLKOUT3_PHASE(0), + .CLKOUT4_DIVIDE(1), + .CLKOUT4_DUTY_CYCLE(0.5), + .CLKOUT4_PHASE(0), + .CLKOUT5_DIVIDE(1), + .CLKOUT5_DUTY_CYCLE(0.5), + .CLKOUT5_PHASE(0), + .CLKOUT6_DIVIDE(1), + .CLKOUT6_DUTY_CYCLE(0.5), + .CLKOUT6_PHASE(0), + .CLKFBOUT_MULT_F(10), + .CLKFBOUT_PHASE(0), + .DIVCLK_DIVIDE(3), + .REF_JITTER1(0.010), + .CLKIN1_PERIOD(3.333), + .STARTUP_WAIT("FALSE"), + .CLKOUT4_CASCADE("FALSE") +) +clk_mmcm_inst ( + .CLKIN1(clk_300mhz_0_int), + .CLKFBIN(mmcm_clkfb), + .RST(mmcm_rst), + .PWRDWN(1'b0), + .CLKOUT0(clk_125mhz_mmcm_out), + .CLKOUT0B(), + .CLKOUT1(clk_50mhz_mmcm_out), + .CLKOUT1B(), + .CLKOUT2(), + .CLKOUT2B(), + .CLKOUT3(), + .CLKOUT3B(), + .CLKOUT4(), + .CLKOUT5(), + .CLKOUT6(), + .CLKFBOUT(mmcm_clkfb), + .CLKFBOUTB(), + .LOCKED(mmcm_locked) +); + +BUFG +clk_50mhz_bufg_inst ( + .I(clk_50mhz_mmcm_out), + .O(clk_50mhz_int) +); + +BUFG +clk_125mhz_bufg_inst ( + .I(clk_125mhz_mmcm_out), + .O(clk_125mhz_int) +); + +sync_reset #( + .N(4) +) +sync_reset_50mhz_inst ( + .clk(clk_50mhz_int), + .rst(~mmcm_locked), + .out(rst_50mhz_int) +); + +sync_reset #( + .N(4) +) +sync_reset_125mhz_inst ( + .clk(clk_125mhz_int), + .rst(~mmcm_locked), + .out(rst_125mhz_int) +); + +// GPIO +wire btnu_int; +wire btnl_int; +wire btnd_int; +wire btnr_int; +wire btnc_int; +wire [3:0] sw_int; +wire [1:0] qsfp_modprsl_int; +wire [1:0] qsfp_intl_int; +wire i2c_scl_i; +wire i2c_scl_o; +wire i2c_scl_t; +wire i2c_sda_i; +wire i2c_sda_o; +wire i2c_sda_t; + +reg i2c_scl_o_reg; +reg i2c_scl_t_reg; +reg i2c_sda_o_reg; +reg i2c_sda_t_reg; + +always @(posedge pcie_user_clk) begin + i2c_scl_o_reg <= i2c_scl_o; + i2c_scl_t_reg <= i2c_scl_t; + i2c_sda_o_reg <= i2c_sda_o; + i2c_sda_t_reg <= i2c_sda_t; +end + +debounce_switch #( + .WIDTH(4), + .N(4), + .RATE(250000) +) +debounce_switch_inst ( + .clk(pcie_user_clk), + .rst(pcie_user_reset), + .in({sw}), + .out({sw_int}) +); + +sync_signal #( + .WIDTH(6), + .N(2) +) +sync_signal_inst ( + .clk(pcie_user_clk), + .in({qsfp0_modprsl, qsfp1_modprsl, qsfp0_intl, qsfp1_intl, + i2c_scl, i2c_sda}), + .out({qsfp_modprsl_int, qsfp_intl_int, + i2c_scl_i, i2c_sda_i}) +); + +assign i2c_scl = i2c_scl_t_reg ? 1'bz : i2c_scl_o_reg; +assign i2c_sda = i2c_sda_t_reg ? 1'bz : i2c_sda_o_reg; + +// Flash +wire qspi_clk_int; +wire [3:0] qspi_dq_int; +wire [3:0] qspi_dq_i_int; +wire [3:0] qspi_dq_o_int; +wire [3:0] qspi_dq_oe_int; +wire qspi_cs_int; + +reg qspi_clk_reg; +reg [3:0] qspi_dq_o_reg; +reg [3:0] qspi_dq_oe_reg; +reg qspi_cs_reg; + +always @(posedge pcie_user_clk) begin + qspi_clk_reg <= qspi_clk_int; + qspi_dq_o_reg <= qspi_dq_o_int; + qspi_dq_oe_reg <= qspi_dq_oe_int; + qspi_cs_reg <= qspi_cs_int; +end + +sync_signal #( + .WIDTH(4), + .N(2) +) +flash_sync_signal_inst ( + .clk(pcie_user_clk), + .in({qspi_dq_int}), + .out({qspi_dq_i_int}) +); + +// startupe3 instance +wire cfgmclk; + +STARTUPE3 +startupe3_inst ( + .CFGCLK(), + .CFGMCLK(cfgmclk), + .DI(qspi_dq_int), + .DO(qspi_dq_o_reg), + .DTS(~qspi_dq_oe_reg), + .EOS(), + .FCSBO(qspi_cs_reg), + .FCSBTS(1'b0), + .GSR(1'b0), + .GTS(1'b0), + .KEYCLEARB(1'b1), + .PACK(1'b0), + .PREQ(), + .USRCCLKO(qspi_clk_reg), + .USRCCLKTS(1'b0), + .USRDONEO(1'b0), + .USRDONETS(1'b1) +); + +BUFG +cfgmclk_bufg_inst ( + .I(cfgmclk), + .O(cfgmclk_int) +); + +// FPGA boot +wire fpga_boot; + +reg fpga_boot_sync_reg_0 = 1'b0; +reg fpga_boot_sync_reg_1 = 1'b0; +reg fpga_boot_sync_reg_2 = 1'b0; + +wire icap_avail; +reg [2:0] icap_state = 0; +reg icap_csib_reg = 1'b1; +reg icap_rdwrb_reg = 1'b0; +reg [31:0] icap_di_reg = 32'hffffffff; + +wire [31:0] icap_di_rev; + +assign icap_di_rev[ 7] = icap_di_reg[ 0]; +assign icap_di_rev[ 6] = icap_di_reg[ 1]; +assign icap_di_rev[ 5] = icap_di_reg[ 2]; +assign icap_di_rev[ 4] = icap_di_reg[ 3]; +assign icap_di_rev[ 3] = icap_di_reg[ 4]; +assign icap_di_rev[ 2] = icap_di_reg[ 5]; +assign icap_di_rev[ 1] = icap_di_reg[ 6]; +assign icap_di_rev[ 0] = icap_di_reg[ 7]; + +assign icap_di_rev[15] = icap_di_reg[ 8]; +assign icap_di_rev[14] = icap_di_reg[ 9]; +assign icap_di_rev[13] = icap_di_reg[10]; +assign icap_di_rev[12] = icap_di_reg[11]; +assign icap_di_rev[11] = icap_di_reg[12]; +assign icap_di_rev[10] = icap_di_reg[13]; +assign icap_di_rev[ 9] = icap_di_reg[14]; +assign icap_di_rev[ 8] = icap_di_reg[15]; + +assign icap_di_rev[23] = icap_di_reg[16]; +assign icap_di_rev[22] = icap_di_reg[17]; +assign icap_di_rev[21] = icap_di_reg[18]; +assign icap_di_rev[20] = icap_di_reg[19]; +assign icap_di_rev[19] = icap_di_reg[20]; +assign icap_di_rev[18] = icap_di_reg[21]; +assign icap_di_rev[17] = icap_di_reg[22]; +assign icap_di_rev[16] = icap_di_reg[23]; + +assign icap_di_rev[31] = icap_di_reg[24]; +assign icap_di_rev[30] = icap_di_reg[25]; +assign icap_di_rev[29] = icap_di_reg[26]; +assign icap_di_rev[28] = icap_di_reg[27]; +assign icap_di_rev[27] = icap_di_reg[28]; +assign icap_di_rev[26] = icap_di_reg[29]; +assign icap_di_rev[25] = icap_di_reg[30]; +assign icap_di_rev[24] = icap_di_reg[31]; + +always @(posedge clk_125mhz_int) begin + case (icap_state) + 0: begin + icap_state <= 0; + icap_csib_reg <= 1'b1; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'hffffffff; // dummy word + + if (fpga_boot_sync_reg_2 && icap_avail) begin + icap_state <= 1; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'hffffffff; // dummy word + end + end + 1: begin + icap_state <= 2; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'hAA995566; // sync word + end + 2: begin + icap_state <= 3; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h20000000; // type 1 noop + end + 3: begin + icap_state <= 4; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h30008001; // write 1 word to CMD + end + 4: begin + icap_state <= 5; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h0000000F; // IPROG + end + 5: begin + icap_state <= 0; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h20000000; // type 1 noop + end + endcase + + fpga_boot_sync_reg_0 <= fpga_boot; + fpga_boot_sync_reg_1 <= fpga_boot_sync_reg_0; + fpga_boot_sync_reg_2 <= fpga_boot_sync_reg_1; +end + +ICAPE3 +icape3_inst ( + .AVAIL(icap_avail), + .CLK(clk_125mhz_int), + .CSIB(icap_csib_reg), + .I(icap_di_rev), + .O(), + .PRDONE(), + .PRERROR(), + .RDWRB(icap_rdwrb_reg) +); + +// BMC +wire axil_cms_clk; +wire axil_cms_rst; +wire [17:0] axil_cms_awaddr; +wire [2:0] axil_cms_awprot; +wire axil_cms_awvalid; +wire axil_cms_awready; +wire [31:0] axil_cms_wdata; +wire [3:0] axil_cms_wstrb; +wire axil_cms_wvalid; +wire axil_cms_wready; +wire [1:0] axil_cms_bresp; +wire axil_cms_bvalid; +wire axil_cms_bready; +wire [17:0] axil_cms_araddr; +wire [2:0] axil_cms_arprot; +wire axil_cms_arvalid; +wire axil_cms_arready; +wire [31:0] axil_cms_rdata; +wire [1:0] axil_cms_rresp; +wire axil_cms_rvalid; +wire axil_cms_rready; + +generate + +if (CMS_ENABLE) begin : cms + + wire [17:0] axil_cms_awaddr_int; + wire [2:0] axil_cms_awprot_int; + wire axil_cms_awvalid_int; + wire axil_cms_awready_int; + wire [31:0] axil_cms_wdata_int; + wire [3:0] axil_cms_wstrb_int; + wire axil_cms_wvalid_int; + wire axil_cms_wready_int; + wire [1:0] axil_cms_bresp_int; + wire axil_cms_bvalid_int; + wire axil_cms_bready_int; + wire [17:0] axil_cms_araddr_int; + wire [2:0] axil_cms_arprot_int; + wire axil_cms_arvalid_int; + wire axil_cms_arready_int; + wire [31:0] axil_cms_rdata_int; + wire [1:0] axil_cms_rresp_int; + wire axil_cms_rvalid_int; + wire axil_cms_rready_int; + + axil_cdc #( + .DATA_WIDTH(32), + .ADDR_WIDTH(18) + ) + cms_axil_cdc_inst ( + .s_clk(axil_cms_clk), + .s_rst(axil_cms_rst), + .s_axil_awaddr(axil_cms_awaddr), + .s_axil_awprot(axil_cms_awprot), + .s_axil_awvalid(axil_cms_awvalid), + .s_axil_awready(axil_cms_awready), + .s_axil_wdata(axil_cms_wdata), + .s_axil_wstrb(axil_cms_wstrb), + .s_axil_wvalid(axil_cms_wvalid), + .s_axil_wready(axil_cms_wready), + .s_axil_bresp(axil_cms_bresp), + .s_axil_bvalid(axil_cms_bvalid), + .s_axil_bready(axil_cms_bready), + .s_axil_araddr(axil_cms_araddr), + .s_axil_arprot(axil_cms_arprot), + .s_axil_arvalid(axil_cms_arvalid), + .s_axil_arready(axil_cms_arready), + .s_axil_rdata(axil_cms_rdata), + .s_axil_rresp(axil_cms_rresp), + .s_axil_rvalid(axil_cms_rvalid), + .s_axil_rready(axil_cms_rready), + .m_clk(clk_50mhz_int), + .m_rst(rst_50mhz_int), + .m_axil_awaddr(axil_cms_awaddr_int), + .m_axil_awprot(axil_cms_awprot_int), + .m_axil_awvalid(axil_cms_awvalid_int), + .m_axil_awready(axil_cms_awready_int), + .m_axil_wdata(axil_cms_wdata_int), + .m_axil_wstrb(axil_cms_wstrb_int), + .m_axil_wvalid(axil_cms_wvalid_int), + .m_axil_wready(axil_cms_wready_int), + .m_axil_bresp(axil_cms_bresp_int), + .m_axil_bvalid(axil_cms_bvalid_int), + .m_axil_bready(axil_cms_bready_int), + .m_axil_araddr(axil_cms_araddr_int), + .m_axil_arprot(axil_cms_arprot_int), + .m_axil_arvalid(axil_cms_arvalid_int), + .m_axil_arready(axil_cms_arready_int), + .m_axil_rdata(axil_cms_rdata_int), + .m_axil_rresp(axil_cms_rresp_int), + .m_axil_rvalid(axil_cms_rvalid_int), + .m_axil_rready(axil_cms_rready_int) + ); + + cms_wrapper + cms_inst ( + .aclk_ctrl_0(clk_50mhz_int), + .aresetn_ctrl_0(~rst_50mhz_int), + .interrupt_host_0(), + .qsfp0_int_l_0(qsfp0_intl), + .qsfp0_lpmode_0(), + .qsfp0_modprs_l_0(qsfp0_modprsl), + .qsfp0_modsel_l_0(), + .qsfp0_reset_l_0(), + .qsfp1_int_l_0(qsfp1_intl), + .qsfp1_lpmode_0(), + .qsfp1_modprs_l_0(qsfp1_modprsl), + .qsfp1_modsel_l_0(), + .qsfp1_reset_l_0(), + .s_axi_ctrl_0_araddr(axil_cms_araddr_int), + .s_axi_ctrl_0_arprot(axil_cms_arprot_int), + .s_axi_ctrl_0_arready(axil_cms_arready_int), + .s_axi_ctrl_0_arvalid(axil_cms_arvalid_int), + .s_axi_ctrl_0_awaddr(axil_cms_awaddr_int), + .s_axi_ctrl_0_awprot(axil_cms_awprot_int), + .s_axi_ctrl_0_awready(axil_cms_awready_int), + .s_axi_ctrl_0_awvalid(axil_cms_awvalid_int), + .s_axi_ctrl_0_bready(axil_cms_bready_int), + .s_axi_ctrl_0_bresp(axil_cms_bresp_int), + .s_axi_ctrl_0_bvalid(axil_cms_bvalid_int), + .s_axi_ctrl_0_rdata(axil_cms_rdata_int), + .s_axi_ctrl_0_rready(axil_cms_rready_int), + .s_axi_ctrl_0_rresp(axil_cms_rresp_int), + .s_axi_ctrl_0_rvalid(axil_cms_rvalid_int), + .s_axi_ctrl_0_wdata(axil_cms_wdata_int), + .s_axi_ctrl_0_wready(axil_cms_wready_int), + .s_axi_ctrl_0_wstrb(axil_cms_wstrb_int), + .s_axi_ctrl_0_wvalid(axil_cms_wvalid_int), + .satellite_gpio_0(msp_gpio), + .satellite_uart_0_rxd(msp_uart_rxd), + .satellite_uart_0_txd(msp_uart_txd) + ); + +end else begin + + assign axil_cms_awready = 0; + assign axil_cms_wdata = 0; + assign axil_cms_wstrb = 0; + assign axil_cms_wvalid = 0; + assign axil_cms_bresp = 0; + assign axil_cms_bvalid = 0; + assign axil_cms_arready = 0; + assign axil_cms_rdata = 0; + assign axil_cms_rresp = 0; + assign axil_cms_rvalid = 0; + + assign msp_uart_txd = 1'bz; + +end + +endgenerate + +// configure SI5335 clock generators +reg qsfp_refclk_reset_reg = 1'b1; +reg sys_reset_reg = 1'b1; + +reg [9:0] reset_timer_reg = 0; + +assign mmcm_rst = sys_reset_reg | pcie_user_reset; + +always @(posedge cfgmclk_int) begin + if (&reset_timer_reg) begin + if (qsfp_refclk_reset_reg) begin + qsfp_refclk_reset_reg <= 1'b0; + reset_timer_reg <= 0; + end else begin + qsfp_refclk_reset_reg <= 1'b0; + sys_reset_reg <= 1'b0; + end + end else begin + reset_timer_reg <= reset_timer_reg + 1; + end +end + +// PCIe +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE4 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte4_pcie_mgt_refclk_inst ( + .I (pcie_refclk_p), + .IB (pcie_refclk_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0; +wire pcie_rq_seq_num_vld0; +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1; +wire pcie_rq_seq_num_vld1; + +wire [3:0] pcie_tfc_nph_av; +wire [3:0] pcie_tfc_npd_av; + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; +wire [3:0] cfg_rcb_status; + +wire [9:0] cfg_mgmt_addr; +wire [7:0] cfg_mgmt_function_number; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msix_enable; +wire [3:0] cfg_interrupt_msix_mask; +wire [251:0] cfg_interrupt_msix_vf_enable; +wire [251:0] cfg_interrupt_msix_vf_mask; +wire [63:0] cfg_interrupt_msix_address; +wire [31:0] cfg_interrupt_msix_data; +wire cfg_interrupt_msix_int; +wire [1:0] cfg_interrupt_msix_vec_pending; +wire cfg_interrupt_msix_vec_pending_status; +wire cfg_interrupt_msix_sent; +wire cfg_interrupt_msix_fail; +wire [7:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +// extra register for pcie_user_reset signal +wire pcie_user_reset_int; +(* shreg_extract = "no" *) +reg pcie_user_reset_reg_1 = 1'b1; +(* shreg_extract = "no" *) +reg pcie_user_reset_reg_2 = 1'b1; + +always @(posedge pcie_user_clk) begin + pcie_user_reset_reg_1 <= pcie_user_reset_int; + pcie_user_reset_reg_2 <= pcie_user_reset_reg_1; +end + +BUFG +pcie_user_reset_bufg_inst ( + .I(pcie_user_reset_reg_2), + .O(pcie_user_reset) +); + +pcie4_uscale_plus_0 +pcie4_uscale_plus_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset_int), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num0(pcie_rq_seq_num0), + .pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0), + .pcie_rq_seq_num1(pcie_rq_seq_num1), + .pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1), + .pcie_rq_tag0(), + .pcie_rq_tag1(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld0(), + .pcie_rq_tag_vld1(), + + .pcie_tfc_nph_av(pcie_tfc_nph_av), + .pcie_tfc_npd_av(pcie_tfc_npd_av), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_debug_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error_valid(), + .cfg_local_error_out(), + .cfg_ltssm_state(), + .cfg_rx_pm_state(), + .cfg_tx_pm_state(), + .cfg_rcb_status(cfg_rcb_status), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_dsn(64'd0), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_func_num(8'd0), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msix_enable(cfg_interrupt_msix_enable), + .cfg_interrupt_msix_mask(cfg_interrupt_msix_mask), + .cfg_interrupt_msix_vf_enable(cfg_interrupt_msix_vf_enable), + .cfg_interrupt_msix_vf_mask(cfg_interrupt_msix_vf_mask), + .cfg_interrupt_msix_address(cfg_interrupt_msix_address), + .cfg_interrupt_msix_data(cfg_interrupt_msix_data), + .cfg_interrupt_msix_int(cfg_interrupt_msix_int), + .cfg_interrupt_msix_vec_pending(cfg_interrupt_msix_vec_pending), + .cfg_interrupt_msix_vec_pending_status(cfg_interrupt_msix_vec_pending_status), + .cfg_interrupt_msi_sent(cfg_interrupt_msix_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msix_fail), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_pm_aspm_l1_entry_reject(1'b0), + .cfg_pm_aspm_tx_l0s_entry_disable(1'b0), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(pcie_reset_n), + + .phy_rdy_out() +); + +// Ethernet +localparam QSFP_CNT = 2; + +wire [QSFP_CNT-1:0] qsfp_tx_clk; +wire [QSFP_CNT-1:0] qsfp_tx_rst; + +wire [QSFP_CNT*AXIS_ETH_DATA_WIDTH-1:0] qsfp_tx_axis_tdata; +wire [QSFP_CNT*AXIS_ETH_KEEP_WIDTH-1:0] qsfp_tx_axis_tkeep; +wire [QSFP_CNT-1:0] qsfp_tx_axis_tvalid; +wire [QSFP_CNT-1:0] qsfp_tx_axis_tready; +wire [QSFP_CNT-1:0] qsfp_tx_axis_tlast; +wire [QSFP_CNT*(16+1)-1:0] qsfp_tx_axis_tuser; + +wire [QSFP_CNT*80-1:0] qsfp_tx_ptp_time; +wire [QSFP_CNT*80-1:0] qsfp_tx_ptp_ts; +wire [QSFP_CNT*16-1:0] qsfp_tx_ptp_ts_tag; +wire [QSFP_CNT-1:0] qsfp_tx_ptp_ts_valid; + +wire [QSFP_CNT-1:0] qsfp_tx_enable; +wire [QSFP_CNT-1:0] qsfp_tx_lfc_en; +wire [QSFP_CNT-1:0] qsfp_tx_lfc_req; +wire [QSFP_CNT*8-1:0] qsfp_tx_pfc_en; +wire [QSFP_CNT*8-1:0] qsfp_tx_pfc_req; + +wire [QSFP_CNT-1:0] qsfp_rx_clk; +wire [QSFP_CNT-1:0] qsfp_rx_rst; + +wire [QSFP_CNT*AXIS_ETH_DATA_WIDTH-1:0] qsfp_rx_axis_tdata; +wire [QSFP_CNT*AXIS_ETH_KEEP_WIDTH-1:0] qsfp_rx_axis_tkeep; +wire [QSFP_CNT-1:0] qsfp_rx_axis_tvalid; +wire [QSFP_CNT-1:0] qsfp_rx_axis_tlast; +wire [QSFP_CNT*(80+1)-1:0] qsfp_rx_axis_tuser; + +wire [QSFP_CNT*80-1:0] qsfp_rx_ptp_time; + +wire [QSFP_CNT-1:0] qsfp_rx_enable; +wire [QSFP_CNT-1:0] qsfp_rx_status; +wire [QSFP_CNT-1:0] qsfp_rx_lfc_en; +wire [QSFP_CNT-1:0] qsfp_rx_lfc_req; +wire [QSFP_CNT-1:0] qsfp_rx_lfc_ack; +wire [QSFP_CNT*8-1:0] qsfp_rx_pfc_en; +wire [QSFP_CNT*8-1:0] qsfp_rx_pfc_req; +wire [QSFP_CNT*8-1:0] qsfp_rx_pfc_ack; + +wire [QSFP_CNT-1:0] qsfp_drp_clk; +wire [QSFP_CNT-1:0] qsfp_drp_rst; +wire [QSFP_CNT*24-1:0] qsfp_drp_addr; +wire [QSFP_CNT*16-1:0] qsfp_drp_di; +wire [QSFP_CNT-1:0] qsfp_drp_en; +wire [QSFP_CNT-1:0] qsfp_drp_we; +wire [QSFP_CNT*16-1:0] qsfp_drp_do; +wire [QSFP_CNT-1:0] qsfp_drp_rdy; + +wire [QSFP_CNT-1:0] qsfp_modsell; +wire [QSFP_CNT-1:0] qsfp_resetl; +wire [QSFP_CNT-1:0] qsfp_lpmode; + +// QSFP0 CMAC +assign qsfp0_refclk_reset = qsfp_refclk_reset_reg; +assign qsfp0_fs = 2'b10; + +assign qsfp_drp_clk[0 +: 1] = clk_125mhz_int; +assign qsfp_drp_rst[0 +: 1] = rst_125mhz_int; + +assign qsfp0_modsell = qsfp_modsell[0 +: 1]; +assign qsfp0_resetl = qsfp_resetl[0 +: 1]; +assign qsfp0_lpmode = qsfp_lpmode[0 +: 1]; + +wire qsfp0_gtpowergood; + +wire qsfp0_mgt_refclk_1; +wire qsfp0_mgt_refclk_1_int; +wire qsfp0_mgt_refclk_1_bufg; + +IBUFDS_GTE4 ibufds_gte4_qsfp0_mgt_refclk_1_inst ( + .I (qsfp0_mgt_refclk_1_p), + .IB (qsfp0_mgt_refclk_1_n), + .CEB (1'b0), + .O (qsfp0_mgt_refclk_1), + .ODIV2 (qsfp0_mgt_refclk_1_int) +); + +BUFG_GT bufg_gt_qsfp0_mgt_refclk_1_inst ( + .CE (qsfp0_gtpowergood), + .CEMASK (1'b1), + .CLR (1'b0), + .CLRMASK (1'b1), + .DIV (3'd0), + .I (qsfp0_mgt_refclk_1_int), + .O (qsfp0_mgt_refclk_1_bufg) +); + +wire qsfp0_rst; + +sync_reset #( + .N(4) +) +qsfp0_sync_reset_inst ( + .clk(qsfp0_mgt_refclk_1_bufg), + .rst(rst_125mhz_int), + .out(qsfp0_rst) +); + +cmac_gty_wrapper #( + .DRP_CLK_FREQ_HZ(125000000), + .AXIS_DATA_WIDTH(AXIS_ETH_DATA_WIDTH), + .AXIS_KEEP_WIDTH(AXIS_ETH_KEEP_WIDTH), + .TX_SERDES_PIPELINE(0), + .RX_SERDES_PIPELINE(0), + .RS_FEC_ENABLE(1) +) +qsfp0_cmac_inst ( + .xcvr_ctrl_clk(clk_125mhz_int), + .xcvr_ctrl_rst(qsfp0_rst), + + /* + * Common + */ + .xcvr_gtpowergood_out(qsfp0_gtpowergood), + .xcvr_ref_clk(qsfp0_mgt_refclk_1), + + /* + * DRP + */ + .drp_clk(qsfp_drp_clk[0 +: 1]), + .drp_rst(qsfp_drp_rst[0 +: 1]), + .drp_addr(qsfp_drp_addr[0*24 +: 24]), + .drp_di(qsfp_drp_di[0*16 +: 16]), + .drp_en(qsfp_drp_en[0 +: 1]), + .drp_we(qsfp_drp_we[0 +: 1]), + .drp_do(qsfp_drp_do[0*16 +: 16]), + .drp_rdy(qsfp_drp_rdy[0 +: 1]), + + /* + * Serial data + */ + .xcvr_txp(qsfp0_tx_p), + .xcvr_txn(qsfp0_tx_n), + .xcvr_rxp(qsfp0_rx_p), + .xcvr_rxn(qsfp0_rx_n), + + /* + * CMAC connections + */ + .tx_clk(qsfp_tx_clk[0 +: 1]), + .tx_rst(qsfp_tx_rst[0 +: 1]), + + .tx_axis_tdata(qsfp_tx_axis_tdata[0*AXIS_ETH_DATA_WIDTH +: AXIS_ETH_DATA_WIDTH]), + .tx_axis_tkeep(qsfp_tx_axis_tkeep[0*AXIS_ETH_KEEP_WIDTH +: AXIS_ETH_KEEP_WIDTH]), + .tx_axis_tvalid(qsfp_tx_axis_tvalid[0 +: 1]), + .tx_axis_tready(qsfp_tx_axis_tready[0 +: 1]), + .tx_axis_tlast(qsfp_tx_axis_tlast[0 +: 1]), + .tx_axis_tuser(qsfp_tx_axis_tuser[0*(16+1) +: (16+1)]), + + .tx_ptp_time(qsfp_tx_ptp_time[0*80 +: 80]), + .tx_ptp_ts(qsfp_tx_ptp_ts[0*80 +: 80]), + .tx_ptp_ts_tag(qsfp_tx_ptp_ts_tag[0*16 +: 16]), + .tx_ptp_ts_valid(qsfp_tx_ptp_ts_valid[0 +: 1]), + + .tx_enable(qsfp_tx_enable[0 +: 1]), + .tx_lfc_en(qsfp_tx_lfc_en[0 +: 1]), + .tx_lfc_req(qsfp_tx_lfc_req[0 +: 1]), + .tx_pfc_en(qsfp_tx_pfc_en[0*8 +: 8]), + .tx_pfc_req(qsfp_tx_pfc_req[0*8 +: 8]), + + .rx_clk(qsfp_rx_clk[0 +: 1]), + .rx_rst(qsfp_rx_rst[0 +: 1]), + + .rx_axis_tdata(qsfp_rx_axis_tdata[0*AXIS_ETH_DATA_WIDTH +: AXIS_ETH_DATA_WIDTH]), + .rx_axis_tkeep(qsfp_rx_axis_tkeep[0*AXIS_ETH_KEEP_WIDTH +: AXIS_ETH_KEEP_WIDTH]), + .rx_axis_tvalid(qsfp_rx_axis_tvalid[0 +: 1]), + .rx_axis_tlast(qsfp_rx_axis_tlast[0 +: 1]), + .rx_axis_tuser(qsfp_rx_axis_tuser[0*(80+1) +: (80+1)]), + + .rx_ptp_time(qsfp_rx_ptp_time[0*80 +: 80]), + + .rx_enable(qsfp_rx_enable[0 +: 1]), + .rx_status(qsfp_rx_status[0 +: 1]), + .rx_lfc_en(qsfp_rx_lfc_en[0 +: 1]), + .rx_lfc_req(qsfp_rx_lfc_req[0 +: 1]), + .rx_lfc_ack(qsfp_rx_lfc_ack[0 +: 1]), + .rx_pfc_en(qsfp_rx_pfc_en[0*8 +: 8]), + .rx_pfc_req(qsfp_rx_pfc_req[0*8 +: 8]), + .rx_pfc_ack(qsfp_rx_pfc_ack[0*8 +: 8]) +); + +// QSFP1 CMAC +assign qsfp1_refclk_reset = qsfp_refclk_reset_reg; +assign qsfp1_fs = 2'b10; + +assign qsfp_drp_clk[1 +: 1] = clk_125mhz_int; +assign qsfp_drp_rst[1 +: 1] = rst_125mhz_int; + +assign qsfp1_modsell = qsfp_modsell[1 +: 1]; +assign qsfp1_resetl = qsfp_resetl[1 +: 1]; +assign qsfp1_lpmode = qsfp_lpmode[1 +: 1]; + +wire qsfp1_gtpowergood; + +wire qsfp1_mgt_refclk_1; +wire qsfp1_mgt_refclk_1_int; +wire qsfp1_mgt_refclk_1_bufg; + +IBUFDS_GTE4 ibufds_gte4_qsfp1_mgt_refclk_1_inst ( + .I (qsfp1_mgt_refclk_1_p), + .IB (qsfp1_mgt_refclk_1_n), + .CEB (1'b0), + .O (qsfp1_mgt_refclk_1), + .ODIV2 (qsfp1_mgt_refclk_1_int) +); + +BUFG_GT bufg_gt_qsfp1_mgt_refclk_1_inst ( + .CE (qsfp1_gtpowergood), + .CEMASK (1'b1), + .CLR (1'b0), + .CLRMASK (1'b1), + .DIV (3'd0), + .I (qsfp1_mgt_refclk_1_int), + .O (qsfp1_mgt_refclk_1_bufg) +); + +wire qsfp1_rst; + +sync_reset #( + .N(4) +) +qsfp1_sync_reset_inst ( + .clk(qsfp1_mgt_refclk_1_bufg), + .rst(rst_125mhz_int), + .out(qsfp1_rst) +); + +cmac_gty_wrapper #( + .DRP_CLK_FREQ_HZ(125000000), + .AXIS_DATA_WIDTH(AXIS_ETH_DATA_WIDTH), + .AXIS_KEEP_WIDTH(AXIS_ETH_KEEP_WIDTH), + .TX_SERDES_PIPELINE(0), + .RX_SERDES_PIPELINE(0), + .RS_FEC_ENABLE(1) +) +qsfp1_cmac_inst ( + .xcvr_ctrl_clk(clk_125mhz_int), + .xcvr_ctrl_rst(qsfp1_rst), + + /* + * Common + */ + .xcvr_gtpowergood_out(qsfp1_gtpowergood), + .xcvr_ref_clk(qsfp1_mgt_refclk_1), + + /* + * DRP + */ + .drp_clk(qsfp_drp_clk[1 +: 1]), + .drp_rst(qsfp_drp_rst[1 +: 1]), + .drp_addr(qsfp_drp_addr[1*24 +: 24]), + .drp_di(qsfp_drp_di[1*16 +: 16]), + .drp_en(qsfp_drp_en[1 +: 1]), + .drp_we(qsfp_drp_we[1 +: 1]), + .drp_do(qsfp_drp_do[1*16 +: 16]), + .drp_rdy(qsfp_drp_rdy[1 +: 1]), + + /* + * Serial data + */ + .xcvr_txp(qsfp1_tx_p), + .xcvr_txn(qsfp1_tx_n), + .xcvr_rxp(qsfp1_rx_p), + .xcvr_rxn(qsfp1_rx_n), + + /* + * CMAC connections + */ + .tx_clk(qsfp_tx_clk[1 +: 1]), + .tx_rst(qsfp_tx_rst[1 +: 1]), + + .tx_axis_tdata(qsfp_tx_axis_tdata[1*AXIS_ETH_DATA_WIDTH +: AXIS_ETH_DATA_WIDTH]), + .tx_axis_tkeep(qsfp_tx_axis_tkeep[1*AXIS_ETH_KEEP_WIDTH +: AXIS_ETH_KEEP_WIDTH]), + .tx_axis_tvalid(qsfp_tx_axis_tvalid[1 +: 1]), + .tx_axis_tready(qsfp_tx_axis_tready[1 +: 1]), + .tx_axis_tlast(qsfp_tx_axis_tlast[1 +: 1]), + .tx_axis_tuser(qsfp_tx_axis_tuser[1*(16+1) +: (16+1)]), + + .tx_ptp_time(qsfp_tx_ptp_time[1*80 +: 80]), + .tx_ptp_ts(qsfp_tx_ptp_ts[1*80 +: 80]), + .tx_ptp_ts_tag(qsfp_tx_ptp_ts_tag[1*16 +: 16]), + .tx_ptp_ts_valid(qsfp_tx_ptp_ts_valid[1 +: 1]), + + .tx_enable(qsfp_tx_enable[1 +: 1]), + .tx_lfc_en(qsfp_tx_lfc_en[1 +: 1]), + .tx_lfc_req(qsfp_tx_lfc_req[1 +: 1]), + .tx_pfc_en(qsfp_tx_pfc_en[1*8 +: 8]), + .tx_pfc_req(qsfp_tx_pfc_req[1*8 +: 8]), + + .rx_clk(qsfp_rx_clk[1 +: 1]), + .rx_rst(qsfp_rx_rst[1 +: 1]), + + .rx_axis_tdata(qsfp_rx_axis_tdata[1*AXIS_ETH_DATA_WIDTH +: AXIS_ETH_DATA_WIDTH]), + .rx_axis_tkeep(qsfp_rx_axis_tkeep[1*AXIS_ETH_KEEP_WIDTH +: AXIS_ETH_KEEP_WIDTH]), + .rx_axis_tvalid(qsfp_rx_axis_tvalid[1 +: 1]), + .rx_axis_tlast(qsfp_rx_axis_tlast[1 +: 1]), + .rx_axis_tuser(qsfp_rx_axis_tuser[1*(80+1) +: (80+1)]), + + .rx_ptp_time(qsfp_rx_ptp_time[1*80 +: 80]), + + .rx_enable(qsfp_rx_enable[1 +: 1]), + .rx_status(qsfp_rx_status[1 +: 1]), + .rx_lfc_en(qsfp_rx_lfc_en[1 +: 1]), + .rx_lfc_req(qsfp_rx_lfc_req[1 +: 1]), + .rx_lfc_ack(qsfp_rx_lfc_ack[1 +: 1]), + .rx_pfc_en(qsfp_rx_pfc_en[1*8 +: 8]), + .rx_pfc_req(qsfp_rx_pfc_req[1*8 +: 8]), + .rx_pfc_ack(qsfp_rx_pfc_ack[1*8 +: 8]) +); + +wire ptp_clk; +wire ptp_rst; +wire ptp_sample_clk; + +assign ptp_clk = qsfp0_mgt_refclk_1_bufg; +assign ptp_rst = qsfp0_rst; +assign ptp_sample_clk = clk_125mhz_int; + +wire [2:0] led_int; + +assign led[0] = led_int[0]; // red +assign led[1] = qsfp_rx_status[1]; // yellow +assign led[2] = qsfp_rx_status[0]; // green + +// DDR4 +wire [DDR_CH-1:0] ddr_clk; +wire [DDR_CH-1:0] ddr_rst; + +wire [DDR_CH*AXI_DDR_ID_WIDTH-1:0] m_axi_ddr_awid; +wire [DDR_CH*AXI_DDR_ADDR_WIDTH-1:0] m_axi_ddr_awaddr; +wire [DDR_CH*8-1:0] m_axi_ddr_awlen; +wire [DDR_CH*3-1:0] m_axi_ddr_awsize; +wire [DDR_CH*2-1:0] m_axi_ddr_awburst; +wire [DDR_CH-1:0] m_axi_ddr_awlock; +wire [DDR_CH*4-1:0] m_axi_ddr_awcache; +wire [DDR_CH*3-1:0] m_axi_ddr_awprot; +wire [DDR_CH*4-1:0] m_axi_ddr_awqos; +wire [DDR_CH-1:0] m_axi_ddr_awvalid; +wire [DDR_CH-1:0] m_axi_ddr_awready; +wire [DDR_CH*AXI_DDR_DATA_WIDTH-1:0] m_axi_ddr_wdata; +wire [DDR_CH*AXI_DDR_STRB_WIDTH-1:0] m_axi_ddr_wstrb; +wire [DDR_CH-1:0] m_axi_ddr_wlast; +wire [DDR_CH-1:0] m_axi_ddr_wvalid; +wire [DDR_CH-1:0] m_axi_ddr_wready; +wire [DDR_CH*AXI_DDR_ID_WIDTH-1:0] m_axi_ddr_bid; +wire [DDR_CH*2-1:0] m_axi_ddr_bresp; +wire [DDR_CH-1:0] m_axi_ddr_bvalid; +wire [DDR_CH-1:0] m_axi_ddr_bready; +wire [DDR_CH*AXI_DDR_ID_WIDTH-1:0] m_axi_ddr_arid; +wire [DDR_CH*AXI_DDR_ADDR_WIDTH-1:0] m_axi_ddr_araddr; +wire [DDR_CH*8-1:0] m_axi_ddr_arlen; +wire [DDR_CH*3-1:0] m_axi_ddr_arsize; +wire [DDR_CH*2-1:0] m_axi_ddr_arburst; +wire [DDR_CH-1:0] m_axi_ddr_arlock; +wire [DDR_CH*4-1:0] m_axi_ddr_arcache; +wire [DDR_CH*3-1:0] m_axi_ddr_arprot; +wire [DDR_CH*4-1:0] m_axi_ddr_arqos; +wire [DDR_CH-1:0] m_axi_ddr_arvalid; +wire [DDR_CH-1:0] m_axi_ddr_arready; +wire [DDR_CH*AXI_DDR_ID_WIDTH-1:0] m_axi_ddr_rid; +wire [DDR_CH*AXI_DDR_DATA_WIDTH-1:0] m_axi_ddr_rdata; +wire [DDR_CH*2-1:0] m_axi_ddr_rresp; +wire [DDR_CH-1:0] m_axi_ddr_rlast; +wire [DDR_CH-1:0] m_axi_ddr_rvalid; +wire [DDR_CH-1:0] m_axi_ddr_rready; + +wire [DDR_CH-1:0] ddr_status; + +generate + +if (DDR_ENABLE && DDR_CH > 0) begin + +reg ddr4_rst_reg = 1'b1; + +always @(posedge pcie_user_clk or posedge pcie_user_reset) begin + if (pcie_user_reset) begin + ddr4_rst_reg <= 1'b1; + end else begin + ddr4_rst_reg <= 1'b0; + end +end + +ddr4_0 ddr4_c0_inst ( + .c0_sys_clk_i(clk_300mhz_0_int), + .sys_rst(ddr4_rst_reg), + + .c0_init_calib_complete(ddr_status[0 +: 1]), + .c0_ddr4_interrupt(), + .dbg_clk(), + .dbg_bus(), + + .c0_ddr4_adr(ddr4_c0_adr), + .c0_ddr4_ba(ddr4_c0_ba), + .c0_ddr4_cke(ddr4_c0_cke), + .c0_ddr4_cs_n(ddr4_c0_cs_n), + .c0_ddr4_dq(ddr4_c0_dq), + .c0_ddr4_dqs_t(ddr4_c0_dqs_t), + .c0_ddr4_dqs_c(ddr4_c0_dqs_c), + .c0_ddr4_odt(ddr4_c0_odt), + .c0_ddr4_parity(ddr4_c0_par), + .c0_ddr4_bg(ddr4_c0_bg), + .c0_ddr4_reset_n(ddr4_c0_reset_n), + .c0_ddr4_act_n(ddr4_c0_act_n), + .c0_ddr4_ck_t(ddr4_c0_ck_t), + .c0_ddr4_ck_c(ddr4_c0_ck_c), + + .c0_ddr4_ui_clk(ddr_clk[0 +: 1]), + .c0_ddr4_ui_clk_sync_rst(ddr_rst[0 +: 1]), + + .c0_ddr4_aresetn(!ddr_rst[0 +: 1]), + + .c0_ddr4_s_axi_ctrl_awvalid(1'b0), + .c0_ddr4_s_axi_ctrl_awready(), + .c0_ddr4_s_axi_ctrl_awaddr(32'd0), + .c0_ddr4_s_axi_ctrl_wvalid(1'b0), + .c0_ddr4_s_axi_ctrl_wready(), + .c0_ddr4_s_axi_ctrl_wdata(32'd0), + .c0_ddr4_s_axi_ctrl_bvalid(), + .c0_ddr4_s_axi_ctrl_bready(1'b1), + .c0_ddr4_s_axi_ctrl_bresp(), + .c0_ddr4_s_axi_ctrl_arvalid(1'b0), + .c0_ddr4_s_axi_ctrl_arready(), + .c0_ddr4_s_axi_ctrl_araddr(31'd0), + .c0_ddr4_s_axi_ctrl_rvalid(), + .c0_ddr4_s_axi_ctrl_rready(1'b1), + .c0_ddr4_s_axi_ctrl_rdata(), + .c0_ddr4_s_axi_ctrl_rresp(), + + .c0_ddr4_s_axi_awid(m_axi_ddr_awid[0*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_awaddr(m_axi_ddr_awaddr[0*AXI_DDR_ADDR_WIDTH +: AXI_DDR_ADDR_WIDTH]), + .c0_ddr4_s_axi_awlen(m_axi_ddr_awlen[0*8 +: 8]), + .c0_ddr4_s_axi_awsize(m_axi_ddr_awsize[0*3 +: 3]), + .c0_ddr4_s_axi_awburst(m_axi_ddr_awburst[0*2 +: 2]), + .c0_ddr4_s_axi_awlock(m_axi_ddr_awlock[0 +: 1]), + .c0_ddr4_s_axi_awcache(m_axi_ddr_awcache[0*4 +: 4]), + .c0_ddr4_s_axi_awprot(m_axi_ddr_awprot[0*3 +: 3]), + .c0_ddr4_s_axi_awqos(m_axi_ddr_awqos[0*4 +: 4]), + .c0_ddr4_s_axi_awvalid(m_axi_ddr_awvalid[0 +: 1]), + .c0_ddr4_s_axi_awready(m_axi_ddr_awready[0 +: 1]), + .c0_ddr4_s_axi_wdata(m_axi_ddr_wdata[0*AXI_DDR_DATA_WIDTH +: AXI_DDR_DATA_WIDTH]), + .c0_ddr4_s_axi_wstrb(m_axi_ddr_wstrb[0*AXI_DDR_STRB_WIDTH +: AXI_DDR_STRB_WIDTH]), + .c0_ddr4_s_axi_wlast(m_axi_ddr_wlast[0 +: 1]), + .c0_ddr4_s_axi_wvalid(m_axi_ddr_wvalid[0 +: 1]), + .c0_ddr4_s_axi_wready(m_axi_ddr_wready[0 +: 1]), + .c0_ddr4_s_axi_bready(m_axi_ddr_bready[0 +: 1]), + .c0_ddr4_s_axi_bid(m_axi_ddr_bid[0*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_bresp(m_axi_ddr_bresp[0*2 +: 2]), + .c0_ddr4_s_axi_bvalid(m_axi_ddr_bvalid[0 +: 1]), + .c0_ddr4_s_axi_arid(m_axi_ddr_arid[0*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_araddr(m_axi_ddr_araddr[0*AXI_DDR_ADDR_WIDTH +: AXI_DDR_ADDR_WIDTH]), + .c0_ddr4_s_axi_arlen(m_axi_ddr_arlen[0*8 +: 8]), + .c0_ddr4_s_axi_arsize(m_axi_ddr_arsize[0*3 +: 3]), + .c0_ddr4_s_axi_arburst(m_axi_ddr_arburst[0*2 +: 2]), + .c0_ddr4_s_axi_arlock(m_axi_ddr_arlock[0 +: 1]), + .c0_ddr4_s_axi_arcache(m_axi_ddr_arcache[0*4 +: 4]), + .c0_ddr4_s_axi_arprot(m_axi_ddr_arprot[0*3 +: 3]), + .c0_ddr4_s_axi_arqos(m_axi_ddr_arqos[0*4 +: 4]), + .c0_ddr4_s_axi_arvalid(m_axi_ddr_arvalid[0 +: 1]), + .c0_ddr4_s_axi_arready(m_axi_ddr_arready[0 +: 1]), + .c0_ddr4_s_axi_rready(m_axi_ddr_rready[0 +: 1]), + .c0_ddr4_s_axi_rlast(m_axi_ddr_rlast[0 +: 1]), + .c0_ddr4_s_axi_rvalid(m_axi_ddr_rvalid[0 +: 1]), + .c0_ddr4_s_axi_rresp(m_axi_ddr_rresp[0*2 +: 2]), + .c0_ddr4_s_axi_rid(m_axi_ddr_rid[0*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_rdata(m_axi_ddr_rdata[0*AXI_DDR_DATA_WIDTH +: AXI_DDR_DATA_WIDTH]) +); + +end else begin + +assign ddr4_c0_adr = {17{1'bz}}; +assign ddr4_c0_ba = {2{1'bz}}; +assign ddr4_c0_bg = {2{1'bz}}; +assign ddr4_c0_cke = 1'bz; +assign ddr4_c0_cs_n = 1'bz; +assign ddr4_c0_act_n = 1'bz; +assign ddr4_c0_odt = 1'bz; +assign ddr4_c0_par = 1'bz; +assign ddr4_c0_reset_n = 1'b0; +assign ddr4_c0_dq = {72{1'bz}}; +assign ddr4_c0_dqs_t = {18{1'bz}}; +assign ddr4_c0_dqs_c = {18{1'bz}}; + +OBUFTDS ddr4_c0_ck_obuftds_inst ( + .I(1'b0), + .T(1'b1), + .O(ddr4_c0_ck_t), + .OB(ddr4_c0_ck_c) +); + +assign ddr_clk = 0; +assign ddr_rst = 0; + +assign m_axi_ddr_awready = 0; +assign m_axi_ddr_wready = 0; +assign m_axi_ddr_bid = 0; +assign m_axi_ddr_bresp = 0; +assign m_axi_ddr_bvalid = 0; +assign m_axi_ddr_arready = 0; +assign m_axi_ddr_rid = 0; +assign m_axi_ddr_rdata = 0; +assign m_axi_ddr_rresp = 0; +assign m_axi_ddr_rlast = 0; +assign m_axi_ddr_rvalid = 0; + +assign ddr_status = 0; + +end + +wire clk_300mhz_1_ibufg; +wire clk_300mhz_1_int; + +IBUFGDS #( + .DIFF_TERM("FALSE"), + .IBUF_LOW_PWR("FALSE") +) +clk_300mhz_1_ibufg_inst ( + .O (clk_300mhz_1_ibufg), + .I (clk_300mhz_1_p), + .IB (clk_300mhz_1_n) +); + +BUFG +clk_300mhz_1_bufg_inst ( + .I(clk_300mhz_1_ibufg), + .O(clk_300mhz_1_int) +); + +if (DDR_ENABLE && DDR_CH > 1) begin + +reg ddr4_rst_reg = 1'b1; + +always @(posedge pcie_user_clk or posedge pcie_user_reset) begin + if (pcie_user_reset) begin + ddr4_rst_reg <= 1'b1; + end else begin + ddr4_rst_reg <= 1'b0; + end +end + +ddr4_0 ddr4_c1_inst ( + .c0_sys_clk_i(clk_300mhz_1_int), + .sys_rst(ddr4_rst_reg), + + .c0_init_calib_complete(ddr_status[1 +: 1]), + .c0_ddr4_interrupt(), + .dbg_clk(), + .dbg_bus(), + + .c0_ddr4_adr(ddr4_c1_adr), + .c0_ddr4_ba(ddr4_c1_ba), + .c0_ddr4_cke(ddr4_c1_cke), + .c0_ddr4_cs_n(ddr4_c1_cs_n), + .c0_ddr4_dq(ddr4_c1_dq), + .c0_ddr4_dqs_t(ddr4_c1_dqs_t), + .c0_ddr4_dqs_c(ddr4_c1_dqs_c), + .c0_ddr4_odt(ddr4_c1_odt), + .c0_ddr4_parity(ddr4_c1_par), + .c0_ddr4_bg(ddr4_c1_bg), + .c0_ddr4_reset_n(ddr4_c1_reset_n), + .c0_ddr4_act_n(ddr4_c1_act_n), + .c0_ddr4_ck_t(ddr4_c1_ck_t), + .c0_ddr4_ck_c(ddr4_c1_ck_c), + + .c0_ddr4_ui_clk(ddr_clk[1 +: 1]), + .c0_ddr4_ui_clk_sync_rst(ddr_rst[1 +: 1]), + + .c0_ddr4_aresetn(!ddr_rst[1 +: 1]), + + .c0_ddr4_s_axi_ctrl_awvalid(1'b0), + .c0_ddr4_s_axi_ctrl_awready(), + .c0_ddr4_s_axi_ctrl_awaddr(32'd0), + .c0_ddr4_s_axi_ctrl_wvalid(1'b0), + .c0_ddr4_s_axi_ctrl_wready(), + .c0_ddr4_s_axi_ctrl_wdata(32'd0), + .c0_ddr4_s_axi_ctrl_bvalid(), + .c0_ddr4_s_axi_ctrl_bready(1'b1), + .c0_ddr4_s_axi_ctrl_bresp(), + .c0_ddr4_s_axi_ctrl_arvalid(1'b0), + .c0_ddr4_s_axi_ctrl_arready(), + .c0_ddr4_s_axi_ctrl_araddr(31'd0), + .c0_ddr4_s_axi_ctrl_rvalid(), + .c0_ddr4_s_axi_ctrl_rready(1'b1), + .c0_ddr4_s_axi_ctrl_rdata(), + .c0_ddr4_s_axi_ctrl_rresp(), + + .c0_ddr4_s_axi_awid(m_axi_ddr_awid[1*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_awaddr(m_axi_ddr_awaddr[1*AXI_DDR_ADDR_WIDTH +: AXI_DDR_ADDR_WIDTH]), + .c0_ddr4_s_axi_awlen(m_axi_ddr_awlen[1*8 +: 8]), + .c0_ddr4_s_axi_awsize(m_axi_ddr_awsize[1*3 +: 3]), + .c0_ddr4_s_axi_awburst(m_axi_ddr_awburst[1*2 +: 2]), + .c0_ddr4_s_axi_awlock(m_axi_ddr_awlock[1 +: 1]), + .c0_ddr4_s_axi_awcache(m_axi_ddr_awcache[1*4 +: 4]), + .c0_ddr4_s_axi_awprot(m_axi_ddr_awprot[1*3 +: 3]), + .c0_ddr4_s_axi_awqos(m_axi_ddr_awqos[1*4 +: 4]), + .c0_ddr4_s_axi_awvalid(m_axi_ddr_awvalid[1 +: 1]), + .c0_ddr4_s_axi_awready(m_axi_ddr_awready[1 +: 1]), + .c0_ddr4_s_axi_wdata(m_axi_ddr_wdata[1*AXI_DDR_DATA_WIDTH +: AXI_DDR_DATA_WIDTH]), + .c0_ddr4_s_axi_wstrb(m_axi_ddr_wstrb[1*AXI_DDR_STRB_WIDTH +: AXI_DDR_STRB_WIDTH]), + .c0_ddr4_s_axi_wlast(m_axi_ddr_wlast[1 +: 1]), + .c0_ddr4_s_axi_wvalid(m_axi_ddr_wvalid[1 +: 1]), + .c0_ddr4_s_axi_wready(m_axi_ddr_wready[1 +: 1]), + .c0_ddr4_s_axi_bready(m_axi_ddr_bready[1 +: 1]), + .c0_ddr4_s_axi_bid(m_axi_ddr_bid[1*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_bresp(m_axi_ddr_bresp[1*2 +: 2]), + .c0_ddr4_s_axi_bvalid(m_axi_ddr_bvalid[1 +: 1]), + .c0_ddr4_s_axi_arid(m_axi_ddr_arid[1*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_araddr(m_axi_ddr_araddr[1*AXI_DDR_ADDR_WIDTH +: AXI_DDR_ADDR_WIDTH]), + .c0_ddr4_s_axi_arlen(m_axi_ddr_arlen[1*8 +: 8]), + .c0_ddr4_s_axi_arsize(m_axi_ddr_arsize[1*3 +: 3]), + .c0_ddr4_s_axi_arburst(m_axi_ddr_arburst[1*2 +: 2]), + .c0_ddr4_s_axi_arlock(m_axi_ddr_arlock[1 +: 1]), + .c0_ddr4_s_axi_arcache(m_axi_ddr_arcache[1*4 +: 4]), + .c0_ddr4_s_axi_arprot(m_axi_ddr_arprot[1*3 +: 3]), + .c0_ddr4_s_axi_arqos(m_axi_ddr_arqos[1*4 +: 4]), + .c0_ddr4_s_axi_arvalid(m_axi_ddr_arvalid[1 +: 1]), + .c0_ddr4_s_axi_arready(m_axi_ddr_arready[1 +: 1]), + .c0_ddr4_s_axi_rready(m_axi_ddr_rready[1 +: 1]), + .c0_ddr4_s_axi_rlast(m_axi_ddr_rlast[1 +: 1]), + .c0_ddr4_s_axi_rvalid(m_axi_ddr_rvalid[1 +: 1]), + .c0_ddr4_s_axi_rresp(m_axi_ddr_rresp[1*2 +: 2]), + .c0_ddr4_s_axi_rid(m_axi_ddr_rid[1*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_rdata(m_axi_ddr_rdata[1*AXI_DDR_DATA_WIDTH +: AXI_DDR_DATA_WIDTH]) +); + +end else begin + +assign ddr4_c1_adr = {17{1'bz}}; +assign ddr4_c1_ba = {2{1'bz}}; +assign ddr4_c1_bg = {2{1'bz}}; +assign ddr4_c1_cke = 1'bz; +assign ddr4_c1_cs_n = 1'bz; +assign ddr4_c1_act_n = 1'bz; +assign ddr4_c1_odt = 1'bz; +assign ddr4_c1_par = 1'bz; +assign ddr4_c1_reset_n = 1'b0; +assign ddr4_c1_dq = {72{1'bz}}; +assign ddr4_c1_dqs_t = {18{1'bz}}; +assign ddr4_c1_dqs_c = {18{1'bz}}; + +OBUFTDS ddr4_c1_ck_obuftds_inst ( + .I(1'b0), + .T(1'b1), + .O(ddr4_c1_ck_t), + .OB(ddr4_c1_ck_c) +); + +end + +wire clk_300mhz_2_ibufg; +wire clk_300mhz_2_int; + +IBUFGDS #( + .DIFF_TERM("FALSE"), + .IBUF_LOW_PWR("FALSE") +) +clk_300mhz_2_ibufg_inst ( + .O (clk_300mhz_2_ibufg), + .I (clk_300mhz_2_p), + .IB (clk_300mhz_2_n) +); + +BUFG +clk_300mhz_2_bufg_inst ( + .I(clk_300mhz_2_ibufg), + .O(clk_300mhz_2_int) +); + +if (DDR_ENABLE && DDR_CH > 2) begin + +reg ddr4_rst_reg = 1'b1; + +always @(posedge pcie_user_clk or posedge pcie_user_reset) begin + if (pcie_user_reset) begin + ddr4_rst_reg <= 1'b1; + end else begin + ddr4_rst_reg <= 1'b0; + end +end + +ddr4_0 ddr4_c2_inst ( + .c0_sys_clk_i(clk_300mhz_2_int), + .sys_rst(ddr4_rst_reg), + + .c0_init_calib_complete(ddr_status[2 +: 1]), + .c0_ddr4_interrupt(), + .dbg_clk(), + .dbg_bus(), + + .c0_ddr4_adr(ddr4_c2_adr), + .c0_ddr4_ba(ddr4_c2_ba), + .c0_ddr4_cke(ddr4_c2_cke), + .c0_ddr4_cs_n(ddr4_c2_cs_n), + .c0_ddr4_dq(ddr4_c2_dq), + .c0_ddr4_dqs_t(ddr4_c2_dqs_t), + .c0_ddr4_dqs_c(ddr4_c2_dqs_c), + .c0_ddr4_odt(ddr4_c2_odt), + .c0_ddr4_parity(ddr4_c2_par), + .c0_ddr4_bg(ddr4_c2_bg), + .c0_ddr4_reset_n(ddr4_c2_reset_n), + .c0_ddr4_act_n(ddr4_c2_act_n), + .c0_ddr4_ck_t(ddr4_c2_ck_t), + .c0_ddr4_ck_c(ddr4_c2_ck_c), + + .c0_ddr4_ui_clk(ddr_clk[2 +: 1]), + .c0_ddr4_ui_clk_sync_rst(ddr_rst[2 +: 1]), + + .c0_ddr4_aresetn(!ddr_rst[2 +: 1]), + + .c0_ddr4_s_axi_ctrl_awvalid(1'b0), + .c0_ddr4_s_axi_ctrl_awready(), + .c0_ddr4_s_axi_ctrl_awaddr(32'd0), + .c0_ddr4_s_axi_ctrl_wvalid(1'b0), + .c0_ddr4_s_axi_ctrl_wready(), + .c0_ddr4_s_axi_ctrl_wdata(32'd0), + .c0_ddr4_s_axi_ctrl_bvalid(), + .c0_ddr4_s_axi_ctrl_bready(1'b1), + .c0_ddr4_s_axi_ctrl_bresp(), + .c0_ddr4_s_axi_ctrl_arvalid(1'b0), + .c0_ddr4_s_axi_ctrl_arready(), + .c0_ddr4_s_axi_ctrl_araddr(31'd0), + .c0_ddr4_s_axi_ctrl_rvalid(), + .c0_ddr4_s_axi_ctrl_rready(1'b1), + .c0_ddr4_s_axi_ctrl_rdata(), + .c0_ddr4_s_axi_ctrl_rresp(), + + .c0_ddr4_s_axi_awid(m_axi_ddr_awid[2*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_awaddr(m_axi_ddr_awaddr[2*AXI_DDR_ADDR_WIDTH +: AXI_DDR_ADDR_WIDTH]), + .c0_ddr4_s_axi_awlen(m_axi_ddr_awlen[2*8 +: 8]), + .c0_ddr4_s_axi_awsize(m_axi_ddr_awsize[2*3 +: 3]), + .c0_ddr4_s_axi_awburst(m_axi_ddr_awburst[2*2 +: 2]), + .c0_ddr4_s_axi_awlock(m_axi_ddr_awlock[2 +: 1]), + .c0_ddr4_s_axi_awcache(m_axi_ddr_awcache[2*4 +: 4]), + .c0_ddr4_s_axi_awprot(m_axi_ddr_awprot[2*3 +: 3]), + .c0_ddr4_s_axi_awqos(m_axi_ddr_awqos[2*4 +: 4]), + .c0_ddr4_s_axi_awvalid(m_axi_ddr_awvalid[2 +: 1]), + .c0_ddr4_s_axi_awready(m_axi_ddr_awready[2 +: 1]), + .c0_ddr4_s_axi_wdata(m_axi_ddr_wdata[2*AXI_DDR_DATA_WIDTH +: AXI_DDR_DATA_WIDTH]), + .c0_ddr4_s_axi_wstrb(m_axi_ddr_wstrb[2*AXI_DDR_STRB_WIDTH +: AXI_DDR_STRB_WIDTH]), + .c0_ddr4_s_axi_wlast(m_axi_ddr_wlast[2 +: 1]), + .c0_ddr4_s_axi_wvalid(m_axi_ddr_wvalid[2 +: 1]), + .c0_ddr4_s_axi_wready(m_axi_ddr_wready[2 +: 1]), + .c0_ddr4_s_axi_bready(m_axi_ddr_bready[2 +: 1]), + .c0_ddr4_s_axi_bid(m_axi_ddr_bid[2*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_bresp(m_axi_ddr_bresp[2*2 +: 2]), + .c0_ddr4_s_axi_bvalid(m_axi_ddr_bvalid[2 +: 1]), + .c0_ddr4_s_axi_arid(m_axi_ddr_arid[2*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_araddr(m_axi_ddr_araddr[2*AXI_DDR_ADDR_WIDTH +: AXI_DDR_ADDR_WIDTH]), + .c0_ddr4_s_axi_arlen(m_axi_ddr_arlen[2*8 +: 8]), + .c0_ddr4_s_axi_arsize(m_axi_ddr_arsize[2*3 +: 3]), + .c0_ddr4_s_axi_arburst(m_axi_ddr_arburst[2*2 +: 2]), + .c0_ddr4_s_axi_arlock(m_axi_ddr_arlock[2 +: 1]), + .c0_ddr4_s_axi_arcache(m_axi_ddr_arcache[2*4 +: 4]), + .c0_ddr4_s_axi_arprot(m_axi_ddr_arprot[2*3 +: 3]), + .c0_ddr4_s_axi_arqos(m_axi_ddr_arqos[2*4 +: 4]), + .c0_ddr4_s_axi_arvalid(m_axi_ddr_arvalid[2 +: 1]), + .c0_ddr4_s_axi_arready(m_axi_ddr_arready[2 +: 1]), + .c0_ddr4_s_axi_rready(m_axi_ddr_rready[2 +: 1]), + .c0_ddr4_s_axi_rlast(m_axi_ddr_rlast[2 +: 1]), + .c0_ddr4_s_axi_rvalid(m_axi_ddr_rvalid[2 +: 1]), + .c0_ddr4_s_axi_rresp(m_axi_ddr_rresp[2*2 +: 2]), + .c0_ddr4_s_axi_rid(m_axi_ddr_rid[2*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_rdata(m_axi_ddr_rdata[2*AXI_DDR_DATA_WIDTH +: AXI_DDR_DATA_WIDTH]) +); + +end else begin + +assign ddr4_c2_adr = {17{1'bz}}; +assign ddr4_c2_ba = {2{1'bz}}; +assign ddr4_c2_bg = {2{1'bz}}; +assign ddr4_c2_cke = 1'bz; +assign ddr4_c2_cs_n = 1'bz; +assign ddr4_c2_act_n = 1'bz; +assign ddr4_c2_odt = 1'bz; +assign ddr4_c2_par = 1'bz; +assign ddr4_c2_reset_n = 1'b0; +assign ddr4_c2_dq = {72{1'bz}}; +assign ddr4_c2_dqs_t = {18{1'bz}}; +assign ddr4_c2_dqs_c = {18{1'bz}}; + +OBUFTDS ddr4_c2_ck_obuftds_inst ( + .I(1'b0), + .T(1'b1), + .O(ddr4_c2_ck_t), + .OB(ddr4_c2_ck_c) +); + +end + +wire clk_300mhz_3_ibufg; +wire clk_300mhz_3_int; + +IBUFGDS #( + .DIFF_TERM("FALSE"), + .IBUF_LOW_PWR("FALSE") +) +clk_300mhz_3_ibufg_inst ( + .O (clk_300mhz_3_ibufg), + .I (clk_300mhz_3_p), + .IB (clk_300mhz_3_n) +); + +BUFG +clk_300mhz_3_bufg_inst ( + .I(clk_300mhz_3_ibufg), + .O(clk_300mhz_3_int) +); + +if (DDR_ENABLE && DDR_CH > 3) begin + +reg ddr4_rst_reg = 1'b1; + +always @(posedge pcie_user_clk or posedge pcie_user_reset) begin + if (pcie_user_reset) begin + ddr4_rst_reg <= 1'b1; + end else begin + ddr4_rst_reg <= 1'b0; + end +end + +ddr4_0 ddr4_c3_inst ( + .c0_sys_clk_i(clk_300mhz_3_int), + .sys_rst(ddr4_rst_reg), + + .c0_init_calib_complete(ddr_status[3 +: 1]), + .c0_ddr4_interrupt(), + .dbg_clk(), + .dbg_bus(), + + .c0_ddr4_adr(ddr4_c3_adr), + .c0_ddr4_ba(ddr4_c3_ba), + .c0_ddr4_cke(ddr4_c3_cke), + .c0_ddr4_cs_n(ddr4_c3_cs_n), + .c0_ddr4_dq(ddr4_c3_dq), + .c0_ddr4_dqs_t(ddr4_c3_dqs_t), + .c0_ddr4_dqs_c(ddr4_c3_dqs_c), + .c0_ddr4_odt(ddr4_c3_odt), + .c0_ddr4_parity(ddr4_c3_par), + .c0_ddr4_bg(ddr4_c3_bg), + .c0_ddr4_reset_n(ddr4_c3_reset_n), + .c0_ddr4_act_n(ddr4_c3_act_n), + .c0_ddr4_ck_t(ddr4_c3_ck_t), + .c0_ddr4_ck_c(ddr4_c3_ck_c), + + .c0_ddr4_ui_clk(ddr_clk[3 +: 1]), + .c0_ddr4_ui_clk_sync_rst(ddr_rst[3 +: 1]), + + .c0_ddr4_aresetn(!ddr_rst[3 +: 1]), + + .c0_ddr4_s_axi_ctrl_awvalid(1'b0), + .c0_ddr4_s_axi_ctrl_awready(), + .c0_ddr4_s_axi_ctrl_awaddr(32'd0), + .c0_ddr4_s_axi_ctrl_wvalid(1'b0), + .c0_ddr4_s_axi_ctrl_wready(), + .c0_ddr4_s_axi_ctrl_wdata(32'd0), + .c0_ddr4_s_axi_ctrl_bvalid(), + .c0_ddr4_s_axi_ctrl_bready(1'b1), + .c0_ddr4_s_axi_ctrl_bresp(), + .c0_ddr4_s_axi_ctrl_arvalid(1'b0), + .c0_ddr4_s_axi_ctrl_arready(), + .c0_ddr4_s_axi_ctrl_araddr(31'd0), + .c0_ddr4_s_axi_ctrl_rvalid(), + .c0_ddr4_s_axi_ctrl_rready(1'b1), + .c0_ddr4_s_axi_ctrl_rdata(), + .c0_ddr4_s_axi_ctrl_rresp(), + + .c0_ddr4_s_axi_awid(m_axi_ddr_awid[3*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_awaddr(m_axi_ddr_awaddr[3*AXI_DDR_ADDR_WIDTH +: AXI_DDR_ADDR_WIDTH]), + .c0_ddr4_s_axi_awlen(m_axi_ddr_awlen[3*8 +: 8]), + .c0_ddr4_s_axi_awsize(m_axi_ddr_awsize[3*3 +: 3]), + .c0_ddr4_s_axi_awburst(m_axi_ddr_awburst[3*2 +: 2]), + .c0_ddr4_s_axi_awlock(m_axi_ddr_awlock[3 +: 1]), + .c0_ddr4_s_axi_awcache(m_axi_ddr_awcache[3*4 +: 4]), + .c0_ddr4_s_axi_awprot(m_axi_ddr_awprot[3*3 +: 3]), + .c0_ddr4_s_axi_awqos(m_axi_ddr_awqos[3*4 +: 4]), + .c0_ddr4_s_axi_awvalid(m_axi_ddr_awvalid[3 +: 1]), + .c0_ddr4_s_axi_awready(m_axi_ddr_awready[3 +: 1]), + .c0_ddr4_s_axi_wdata(m_axi_ddr_wdata[3*AXI_DDR_DATA_WIDTH +: AXI_DDR_DATA_WIDTH]), + .c0_ddr4_s_axi_wstrb(m_axi_ddr_wstrb[3*AXI_DDR_STRB_WIDTH +: AXI_DDR_STRB_WIDTH]), + .c0_ddr4_s_axi_wlast(m_axi_ddr_wlast[3 +: 1]), + .c0_ddr4_s_axi_wvalid(m_axi_ddr_wvalid[3 +: 1]), + .c0_ddr4_s_axi_wready(m_axi_ddr_wready[3 +: 1]), + .c0_ddr4_s_axi_bready(m_axi_ddr_bready[3 +: 1]), + .c0_ddr4_s_axi_bid(m_axi_ddr_bid[3*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_bresp(m_axi_ddr_bresp[3*2 +: 2]), + .c0_ddr4_s_axi_bvalid(m_axi_ddr_bvalid[3 +: 1]), + .c0_ddr4_s_axi_arid(m_axi_ddr_arid[3*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_araddr(m_axi_ddr_araddr[3*AXI_DDR_ADDR_WIDTH +: AXI_DDR_ADDR_WIDTH]), + .c0_ddr4_s_axi_arlen(m_axi_ddr_arlen[3*8 +: 8]), + .c0_ddr4_s_axi_arsize(m_axi_ddr_arsize[3*3 +: 3]), + .c0_ddr4_s_axi_arburst(m_axi_ddr_arburst[3*2 +: 2]), + .c0_ddr4_s_axi_arlock(m_axi_ddr_arlock[3 +: 1]), + .c0_ddr4_s_axi_arcache(m_axi_ddr_arcache[3*4 +: 4]), + .c0_ddr4_s_axi_arprot(m_axi_ddr_arprot[3*3 +: 3]), + .c0_ddr4_s_axi_arqos(m_axi_ddr_arqos[3*4 +: 4]), + .c0_ddr4_s_axi_arvalid(m_axi_ddr_arvalid[3 +: 1]), + .c0_ddr4_s_axi_arready(m_axi_ddr_arready[3 +: 1]), + .c0_ddr4_s_axi_rready(m_axi_ddr_rready[3 +: 1]), + .c0_ddr4_s_axi_rlast(m_axi_ddr_rlast[3 +: 1]), + .c0_ddr4_s_axi_rvalid(m_axi_ddr_rvalid[3 +: 1]), + .c0_ddr4_s_axi_rresp(m_axi_ddr_rresp[3*2 +: 2]), + .c0_ddr4_s_axi_rid(m_axi_ddr_rid[3*AXI_DDR_ID_WIDTH +: AXI_DDR_ID_WIDTH]), + .c0_ddr4_s_axi_rdata(m_axi_ddr_rdata[3*AXI_DDR_DATA_WIDTH +: AXI_DDR_DATA_WIDTH]) +); + +end else begin + +assign ddr4_c3_adr = {17{1'bz}}; +assign ddr4_c3_ba = {2{1'bz}}; +assign ddr4_c3_bg = {2{1'bz}}; +assign ddr4_c3_cke = 1'bz; +assign ddr4_c3_cs_n = 1'bz; +assign ddr4_c3_act_n = 1'bz; +assign ddr4_c3_odt = 1'bz; +assign ddr4_c3_par = 1'bz; +assign ddr4_c3_reset_n = 1'b0; +assign ddr4_c3_dq = {72{1'bz}}; +assign ddr4_c3_dqs_t = {18{1'bz}}; +assign ddr4_c3_dqs_c = {18{1'bz}}; + +OBUFTDS ddr4_c3_ck_obuftds_inst ( + .I(1'b0), + .T(1'b1), + .O(ddr4_c3_ck_t), + .OB(ddr4_c3_ck_c) +); + +end + +endgenerate + +fpga_core #( + // FW and board IDs + .FPGA_ID(FPGA_ID), + .FW_ID(FW_ID), + .FW_VER(FW_VER), + .BOARD_ID(BOARD_ID), + .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), + + // Board configuration + .QSFP_CNT(QSFP_CNT), + .CH_CNT(QSFP_CNT*4), + .CMS_ENABLE(CMS_ENABLE), + .FLASH_SEG_COUNT(2), + .FLASH_SEG_DEFAULT(1), + .FLASH_SEG_FALLBACK(0), + .FLASH_SEG0_SIZE(32'h01002000), + + // Structural configuration + .IF_COUNT(IF_COUNT), + .PORTS_PER_IF(PORTS_PER_IF), + .SCHED_PER_IF(SCHED_PER_IF), + .PORT_MASK(PORT_MASK), + + // Clock configuration + .CLK_PERIOD_NS_NUM(CLK_PERIOD_NS_NUM), + .CLK_PERIOD_NS_DENOM(CLK_PERIOD_NS_DENOM), + + // PTP configuration + .PTP_CLK_PERIOD_NS_NUM(PTP_CLK_PERIOD_NS_NUM), + .PTP_CLK_PERIOD_NS_DENOM(PTP_CLK_PERIOD_NS_DENOM), + .PTP_TS_WIDTH(PTP_TS_WIDTH), + .PTP_CLOCK_PIPELINE(PTP_CLOCK_PIPELINE), + .PTP_CLOCK_CDC_PIPELINE(PTP_CLOCK_CDC_PIPELINE), + .PTP_PORT_CDC_PIPELINE(PTP_PORT_CDC_PIPELINE), + .PTP_PEROUT_ENABLE(PTP_PEROUT_ENABLE), + .PTP_PEROUT_COUNT(PTP_PEROUT_COUNT), + + // Queue manager configuration + .EVENT_QUEUE_OP_TABLE_SIZE(EVENT_QUEUE_OP_TABLE_SIZE), + .TX_QUEUE_OP_TABLE_SIZE(TX_QUEUE_OP_TABLE_SIZE), + .RX_QUEUE_OP_TABLE_SIZE(RX_QUEUE_OP_TABLE_SIZE), + .CQ_OP_TABLE_SIZE(CQ_OP_TABLE_SIZE), + .EQN_WIDTH(EQN_WIDTH), + .TX_QUEUE_INDEX_WIDTH(TX_QUEUE_INDEX_WIDTH), + .RX_QUEUE_INDEX_WIDTH(RX_QUEUE_INDEX_WIDTH), + .CQN_WIDTH(CQN_WIDTH), + .EQ_PIPELINE(EQ_PIPELINE), + .TX_QUEUE_PIPELINE(TX_QUEUE_PIPELINE), + .RX_QUEUE_PIPELINE(RX_QUEUE_PIPELINE), + .CQ_PIPELINE(CQ_PIPELINE), + + // TX and RX engine configuration + .TX_DESC_TABLE_SIZE(TX_DESC_TABLE_SIZE), + .RX_DESC_TABLE_SIZE(RX_DESC_TABLE_SIZE), + .RX_INDIR_TBL_ADDR_WIDTH(RX_INDIR_TBL_ADDR_WIDTH), + + // Scheduler configuration + .TX_SCHEDULER_OP_TABLE_SIZE(TX_SCHEDULER_OP_TABLE_SIZE), + .TX_SCHEDULER_PIPELINE(TX_SCHEDULER_PIPELINE), + .TDMA_INDEX_WIDTH(TDMA_INDEX_WIDTH), + + // Interface configuration + .PTP_TS_ENABLE(PTP_TS_ENABLE), + .TX_CPL_FIFO_DEPTH(TX_CPL_FIFO_DEPTH), + .TX_TAG_WIDTH(TX_TAG_WIDTH), + .TX_CHECKSUM_ENABLE(TX_CHECKSUM_ENABLE), + .RX_HASH_ENABLE(RX_HASH_ENABLE), + .RX_CHECKSUM_ENABLE(RX_CHECKSUM_ENABLE), + .PFC_ENABLE(PFC_ENABLE), + .LFC_ENABLE(LFC_ENABLE), + .TX_FIFO_DEPTH(TX_FIFO_DEPTH), + .RX_FIFO_DEPTH(RX_FIFO_DEPTH), + .MAX_TX_SIZE(MAX_TX_SIZE), + .MAX_RX_SIZE(MAX_RX_SIZE), + .TX_RAM_SIZE(TX_RAM_SIZE), + .RX_RAM_SIZE(RX_RAM_SIZE), + + // RAM configuration + .DDR_CH(DDR_CH), + .DDR_ENABLE(DDR_ENABLE), + .AXI_DDR_DATA_WIDTH(AXI_DDR_DATA_WIDTH), + .AXI_DDR_ADDR_WIDTH(AXI_DDR_ADDR_WIDTH), + .AXI_DDR_STRB_WIDTH(AXI_DDR_STRB_WIDTH), + .AXI_DDR_ID_WIDTH(AXI_DDR_ID_WIDTH), + .AXI_DDR_MAX_BURST_LEN(AXI_DDR_MAX_BURST_LEN), + .AXI_DDR_NARROW_BURST(AXI_DDR_NARROW_BURST), + .HBM_ENABLE(0), + + // Application block configuration + .APP_ID(APP_ID), + .APP_ENABLE(APP_ENABLE), + .APP_CTRL_ENABLE(APP_CTRL_ENABLE), + .APP_DMA_ENABLE(APP_DMA_ENABLE), + .APP_AXIS_DIRECT_ENABLE(APP_AXIS_DIRECT_ENABLE), + .APP_AXIS_SYNC_ENABLE(APP_AXIS_SYNC_ENABLE), + .APP_AXIS_IF_ENABLE(APP_AXIS_IF_ENABLE), + .APP_STAT_ENABLE(APP_STAT_ENABLE), + + // DMA interface configuration + .DMA_IMM_ENABLE(DMA_IMM_ENABLE), + .DMA_IMM_WIDTH(DMA_IMM_WIDTH), + .DMA_LEN_WIDTH(DMA_LEN_WIDTH), + .DMA_TAG_WIDTH(DMA_TAG_WIDTH), + .RAM_ADDR_WIDTH(RAM_ADDR_WIDTH), + .RAM_PIPELINE(RAM_PIPELINE), + + // PCIe interface configuration + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RC_STRADDLE(RC_STRADDLE), + .RQ_STRADDLE(RQ_STRADDLE), + .CQ_STRADDLE(CQ_STRADDLE), + .CC_STRADDLE(CC_STRADDLE), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .PF_COUNT(PF_COUNT), + .VF_COUNT(VF_COUNT), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + + // Interrupt configuration + .IRQ_INDEX_WIDTH(IRQ_INDEX_WIDTH), + + // AXI lite interface configuration (control) + .AXIL_CTRL_DATA_WIDTH(AXIL_CTRL_DATA_WIDTH), + .AXIL_CTRL_ADDR_WIDTH(AXIL_CTRL_ADDR_WIDTH), + + // AXI lite interface configuration (application control) + .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), + .AXIL_APP_CTRL_ADDR_WIDTH(AXIL_APP_CTRL_ADDR_WIDTH), + + // Ethernet interface configuration + .AXIS_ETH_DATA_WIDTH(AXIS_ETH_DATA_WIDTH), + .AXIS_ETH_KEEP_WIDTH(AXIS_ETH_KEEP_WIDTH), + .AXIS_ETH_SYNC_DATA_WIDTH(AXIS_ETH_SYNC_DATA_WIDTH), + .AXIS_ETH_TX_USER_WIDTH(AXIS_ETH_TX_USER_WIDTH), + .AXIS_ETH_RX_USER_WIDTH(AXIS_ETH_RX_USER_WIDTH), + .AXIS_ETH_TX_PIPELINE(AXIS_ETH_TX_PIPELINE), + .AXIS_ETH_TX_FIFO_PIPELINE(AXIS_ETH_TX_FIFO_PIPELINE), + .AXIS_ETH_TX_TS_PIPELINE(AXIS_ETH_TX_TS_PIPELINE), + .AXIS_ETH_RX_PIPELINE(AXIS_ETH_RX_PIPELINE), + .AXIS_ETH_RX_FIFO_PIPELINE(AXIS_ETH_RX_FIFO_PIPELINE), + + // Statistics counter subsystem + .STAT_ENABLE(STAT_ENABLE), + .STAT_DMA_ENABLE(STAT_DMA_ENABLE), + .STAT_PCIE_ENABLE(STAT_PCIE_ENABLE), + .STAT_INC_WIDTH(STAT_INC_WIDTH), + .STAT_ID_WIDTH(STAT_ID_WIDTH), + + .FUNCTION_ID_WIDTH(FUNCTION_ID_WIDTH) // Scott +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk_250mhz(pcie_user_clk), + .rst_250mhz(pcie_user_reset), + + /* + * PTP clock + */ + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + + /* + * GPIO + */ + .sw(sw_int), + .led(led_int), + .qsfp_led_act(), + .qsfp_led_stat_g(), + .qsfp_led_stat_y(), + + /* + * I2C + */ + .i2c_scl_i(i2c_scl_i), + .i2c_scl_o(i2c_scl_o), + .i2c_scl_t(i2c_scl_t), + .i2c_sda_i(i2c_sda_i), + .i2c_sda_o(i2c_sda_o), + .i2c_sda_t(i2c_sda_t), + + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num_0(pcie_rq_seq_num0), + .s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0), + .s_axis_rq_seq_num_1(pcie_rq_seq_num1), + .s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1), + + .pcie_tfc_nph_av(pcie_tfc_nph_av), + .pcie_tfc_npd_av(pcie_tfc_npd_av), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_rcb_status(cfg_rcb_status), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msix_enable(cfg_interrupt_msix_enable), + .cfg_interrupt_msix_mask(cfg_interrupt_msix_mask), + .cfg_interrupt_msix_vf_enable(cfg_interrupt_msix_vf_enable), + .cfg_interrupt_msix_vf_mask(cfg_interrupt_msix_vf_mask), + .cfg_interrupt_msix_address(cfg_interrupt_msix_address), + .cfg_interrupt_msix_data(cfg_interrupt_msix_data), + .cfg_interrupt_msix_int(cfg_interrupt_msix_int), + .cfg_interrupt_msix_vec_pending(cfg_interrupt_msix_vec_pending), + .cfg_interrupt_msix_vec_pending_status(cfg_interrupt_msix_vec_pending_status), + .cfg_interrupt_msix_sent(cfg_interrupt_msix_sent), + .cfg_interrupt_msix_fail(cfg_interrupt_msix_fail), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor), + + /* + * Ethernet: QSFP28 + */ + .qsfp_tx_clk(qsfp_tx_clk), + .qsfp_tx_rst(qsfp_tx_rst), + .qsfp_tx_axis_tdata(qsfp_tx_axis_tdata), + .qsfp_tx_axis_tkeep(qsfp_tx_axis_tkeep), + .qsfp_tx_axis_tvalid(qsfp_tx_axis_tvalid), + .qsfp_tx_axis_tready(qsfp_tx_axis_tready), + .qsfp_tx_axis_tlast(qsfp_tx_axis_tlast), + .qsfp_tx_axis_tuser(qsfp_tx_axis_tuser), + .qsfp_tx_ptp_time(qsfp_tx_ptp_time), + .qsfp_tx_ptp_ts(qsfp_tx_ptp_ts), + .qsfp_tx_ptp_ts_tag(qsfp_tx_ptp_ts_tag), + .qsfp_tx_ptp_ts_valid(qsfp_tx_ptp_ts_valid), + + .qsfp_tx_enable(qsfp_tx_enable), + .qsfp_tx_lfc_en(qsfp_tx_lfc_en), + .qsfp_tx_lfc_req(qsfp_tx_lfc_req), + .qsfp_tx_pfc_en(qsfp_tx_pfc_en), + .qsfp_tx_pfc_req(qsfp_tx_pfc_req), + + .qsfp_rx_clk(qsfp_rx_clk), + .qsfp_rx_rst(qsfp_rx_rst), + .qsfp_rx_axis_tdata(qsfp_rx_axis_tdata), + .qsfp_rx_axis_tkeep(qsfp_rx_axis_tkeep), + .qsfp_rx_axis_tvalid(qsfp_rx_axis_tvalid), + .qsfp_rx_axis_tlast(qsfp_rx_axis_tlast), + .qsfp_rx_axis_tuser(qsfp_rx_axis_tuser), + .qsfp_rx_ptp_time(qsfp_rx_ptp_time), + + .qsfp_rx_enable(qsfp_rx_enable), + .qsfp_rx_status(qsfp_rx_status), + .qsfp_rx_lfc_en(qsfp_rx_lfc_en), + .qsfp_rx_lfc_req(qsfp_rx_lfc_req), + .qsfp_rx_lfc_ack(qsfp_rx_lfc_ack), + .qsfp_rx_pfc_en(qsfp_rx_pfc_en), + .qsfp_rx_pfc_req(qsfp_rx_pfc_req), + .qsfp_rx_pfc_ack(qsfp_rx_pfc_ack), + + .qsfp_drp_clk(qsfp_drp_clk), + .qsfp_drp_rst(qsfp_drp_rst), + .qsfp_drp_addr(qsfp_drp_addr), + .qsfp_drp_di(qsfp_drp_di), + .qsfp_drp_en(qsfp_drp_en), + .qsfp_drp_we(qsfp_drp_we), + .qsfp_drp_do(qsfp_drp_do), + .qsfp_drp_rdy(qsfp_drp_rdy), + + .qsfp_modprsl(qsfp_modprsl_int), + .qsfp_modsell(qsfp_modsell), + .qsfp_resetl(qsfp_resetl), + .qsfp_intl(qsfp_intl_int), + .qsfp_lpmode(qsfp_lpmode), + + /* + * DDR + */ + .ddr_clk(ddr_clk), + .ddr_rst(ddr_rst), + + .m_axi_ddr_awid(m_axi_ddr_awid), + .m_axi_ddr_awaddr(m_axi_ddr_awaddr), + .m_axi_ddr_awlen(m_axi_ddr_awlen), + .m_axi_ddr_awsize(m_axi_ddr_awsize), + .m_axi_ddr_awburst(m_axi_ddr_awburst), + .m_axi_ddr_awlock(m_axi_ddr_awlock), + .m_axi_ddr_awcache(m_axi_ddr_awcache), + .m_axi_ddr_awprot(m_axi_ddr_awprot), + .m_axi_ddr_awqos(m_axi_ddr_awqos), + .m_axi_ddr_awvalid(m_axi_ddr_awvalid), + .m_axi_ddr_awready(m_axi_ddr_awready), + .m_axi_ddr_wdata(m_axi_ddr_wdata), + .m_axi_ddr_wstrb(m_axi_ddr_wstrb), + .m_axi_ddr_wlast(m_axi_ddr_wlast), + .m_axi_ddr_wvalid(m_axi_ddr_wvalid), + .m_axi_ddr_wready(m_axi_ddr_wready), + .m_axi_ddr_bid(m_axi_ddr_bid), + .m_axi_ddr_bresp(m_axi_ddr_bresp), + .m_axi_ddr_bvalid(m_axi_ddr_bvalid), + .m_axi_ddr_bready(m_axi_ddr_bready), + .m_axi_ddr_arid(m_axi_ddr_arid), + .m_axi_ddr_araddr(m_axi_ddr_araddr), + .m_axi_ddr_arlen(m_axi_ddr_arlen), + .m_axi_ddr_arsize(m_axi_ddr_arsize), + .m_axi_ddr_arburst(m_axi_ddr_arburst), + .m_axi_ddr_arlock(m_axi_ddr_arlock), + .m_axi_ddr_arcache(m_axi_ddr_arcache), + .m_axi_ddr_arprot(m_axi_ddr_arprot), + .m_axi_ddr_arqos(m_axi_ddr_arqos), + .m_axi_ddr_arvalid(m_axi_ddr_arvalid), + .m_axi_ddr_arready(m_axi_ddr_arready), + .m_axi_ddr_rid(m_axi_ddr_rid), + .m_axi_ddr_rdata(m_axi_ddr_rdata), + .m_axi_ddr_rresp(m_axi_ddr_rresp), + .m_axi_ddr_rlast(m_axi_ddr_rlast), + .m_axi_ddr_rvalid(m_axi_ddr_rvalid), + .m_axi_ddr_rready(m_axi_ddr_rready), + + .ddr_status(ddr_status), + + /* + * HBM + */ + .hbm_clk(0), + .hbm_rst(0), + + .m_axi_hbm_awid(), + .m_axi_hbm_awaddr(), + .m_axi_hbm_awlen(), + .m_axi_hbm_awsize(), + .m_axi_hbm_awburst(), + .m_axi_hbm_awlock(), + .m_axi_hbm_awcache(), + .m_axi_hbm_awprot(), + .m_axi_hbm_awqos(), + .m_axi_hbm_awvalid(), + .m_axi_hbm_awready(0), + .m_axi_hbm_wdata(), + .m_axi_hbm_wstrb(), + .m_axi_hbm_wlast(), + .m_axi_hbm_wvalid(), + .m_axi_hbm_wready(0), + .m_axi_hbm_bid(0), + .m_axi_hbm_bresp(0), + .m_axi_hbm_bvalid(0), + .m_axi_hbm_bready(), + .m_axi_hbm_arid(), + .m_axi_hbm_araddr(), + .m_axi_hbm_arlen(), + .m_axi_hbm_arsize(), + .m_axi_hbm_arburst(), + .m_axi_hbm_arlock(), + .m_axi_hbm_arcache(), + .m_axi_hbm_arprot(), + .m_axi_hbm_arqos(), + .m_axi_hbm_arvalid(), + .m_axi_hbm_arready(0), + .m_axi_hbm_rid(0), + .m_axi_hbm_rdata(0), + .m_axi_hbm_rresp(0), + .m_axi_hbm_rlast(0), + .m_axi_hbm_rvalid(0), + .m_axi_hbm_rready(), + + .hbm_status(0), + + /* + * QSPI flash + */ + .fpga_boot(fpga_boot), + .qspi_clk(qspi_clk_int), + .qspi_dq_i(qspi_dq_i_int), + .qspi_dq_o(qspi_dq_o_int), + .qspi_dq_oe(qspi_dq_oe_int), + .qspi_cs(qspi_cs_int), + + /* + * AXI-Lite interface to CMS + */ + .m_axil_cms_clk(axil_cms_clk), + .m_axil_cms_rst(axil_cms_rst), + .m_axil_cms_awaddr(axil_cms_awaddr), + .m_axil_cms_awprot(axil_cms_awprot), + .m_axil_cms_awvalid(axil_cms_awvalid), + .m_axil_cms_awready(axil_cms_awready), + .m_axil_cms_wdata(axil_cms_wdata), + .m_axil_cms_wstrb(axil_cms_wstrb), + .m_axil_cms_wvalid(axil_cms_wvalid), + .m_axil_cms_wready(axil_cms_wready), + .m_axil_cms_bresp(axil_cms_bresp), + .m_axil_cms_bvalid(axil_cms_bvalid), + .m_axil_cms_bready(axil_cms_bready), + .m_axil_cms_araddr(axil_cms_araddr), + .m_axil_cms_arprot(axil_cms_arprot), + .m_axil_cms_arvalid(axil_cms_arvalid), + .m_axil_cms_arready(axil_cms_arready), + .m_axil_cms_rdata(axil_cms_rdata), + .m_axil_cms_rresp(axil_cms_rresp), + .m_axil_cms_rvalid(axil_cms_rvalid), + .m_axil_cms_rready(axil_cms_rready) +); + +endmodule + +`resetall diff --git a/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au280.v b/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au280.v index d2954d1..80c06db 100644 --- a/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au280.v +++ b/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au280.v @@ -1098,7 +1098,7 @@ cmac_gty_wrapper #( .AXIS_KEEP_WIDTH(AXIS_ETH_KEEP_WIDTH), .TX_SERDES_PIPELINE(0), .RX_SERDES_PIPELINE(0), - .RS_FEC_ENABLE(1) + .RS_FEC_ENABLE(0) ) qsfp0_cmac_inst ( .xcvr_ctrl_clk(clk_125mhz_int), @@ -1223,7 +1223,7 @@ cmac_gty_wrapper #( .AXIS_KEEP_WIDTH(AXIS_ETH_KEEP_WIDTH), .TX_SERDES_PIPELINE(0), .RX_SERDES_PIPELINE(0), - .RS_FEC_ENABLE(1) + .RS_FEC_ENABLE(0) ) qsfp1_cmac_inst ( .xcvr_ctrl_clk(clk_125mhz_int), diff --git a/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au50.v b/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au50.v new file mode 100644 index 0000000..cd8b0d7 --- /dev/null +++ b/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au50.v @@ -0,0 +1,1727 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga # +( + // FW and board IDs + parameter FPGA_ID = 32'h4B77093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9032, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, + + // Board configuration + parameter CMS_ENABLE = 1, + + // Structural configuration + parameter IF_COUNT = 1, + parameter PORTS_PER_IF = 1, + parameter SCHED_PER_IF = PORTS_PER_IF, + parameter PORT_MASK = 0, + + // Clock configuration + parameter CLK_PERIOD_NS_NUM = 4, + parameter CLK_PERIOD_NS_DENOM = 1, + + // PTP configuration + parameter PTP_CLOCK_PIPELINE = 1, + parameter PTP_CLOCK_CDC_PIPELINE = 0, + parameter PTP_PORT_CDC_PIPELINE = 1, + parameter PTP_PEROUT_ENABLE = 0, + parameter PTP_PEROUT_COUNT = 1, + + // Queue manager configuration + parameter EVENT_QUEUE_OP_TABLE_SIZE = 32, + parameter TX_QUEUE_OP_TABLE_SIZE = 32, + parameter RX_QUEUE_OP_TABLE_SIZE = 32, + parameter CQ_OP_TABLE_SIZE = 32, + parameter EQN_WIDTH = 5, + parameter TX_QUEUE_INDEX_WIDTH = 13, + parameter RX_QUEUE_INDEX_WIDTH = 8, + parameter CQN_WIDTH = (TX_QUEUE_INDEX_WIDTH > RX_QUEUE_INDEX_WIDTH ? TX_QUEUE_INDEX_WIDTH : RX_QUEUE_INDEX_WIDTH) + 1, + parameter EQ_PIPELINE = 3, + parameter TX_QUEUE_PIPELINE = 3+(TX_QUEUE_INDEX_WIDTH > 12 ? TX_QUEUE_INDEX_WIDTH-12 : 0), + parameter RX_QUEUE_PIPELINE = 3+(RX_QUEUE_INDEX_WIDTH > 12 ? RX_QUEUE_INDEX_WIDTH-12 : 0), + parameter CQ_PIPELINE = 3+(CQN_WIDTH > 12 ? CQN_WIDTH-12 : 0), + + // TX and RX engine configuration + parameter TX_DESC_TABLE_SIZE = 32, + parameter RX_DESC_TABLE_SIZE = 32, + parameter RX_INDIR_TBL_ADDR_WIDTH = RX_QUEUE_INDEX_WIDTH > 8 ? 8 : RX_QUEUE_INDEX_WIDTH, + + // Scheduler configuration + parameter TX_SCHEDULER_OP_TABLE_SIZE = TX_DESC_TABLE_SIZE, + parameter TX_SCHEDULER_PIPELINE = TX_QUEUE_PIPELINE, + parameter TDMA_INDEX_WIDTH = 6, + + // Interface configuration + parameter PTP_TS_ENABLE = 1, + parameter TX_CPL_FIFO_DEPTH = 32, + parameter TX_CHECKSUM_ENABLE = 1, + parameter RX_HASH_ENABLE = 1, + parameter RX_CHECKSUM_ENABLE = 1, + parameter PFC_ENABLE = 1, + parameter LFC_ENABLE = PFC_ENABLE, + parameter TX_FIFO_DEPTH = 32768, + parameter RX_FIFO_DEPTH = 131072, + parameter MAX_TX_SIZE = 9214, + parameter MAX_RX_SIZE = 9214, + parameter TX_RAM_SIZE = 131072, + parameter RX_RAM_SIZE = 131072, + + // RAM configuration + parameter HBM_CH = 32, + parameter HBM_ENABLE = 0, + parameter HBM_GROUP_SIZE = HBM_CH, + parameter AXI_HBM_ADDR_WIDTH = 33, + parameter AXI_HBM_MAX_BURST_LEN = 16, + + // Application block configuration + parameter APP_ID = 32'h00000000, + parameter APP_ENABLE = 0, + parameter APP_CTRL_ENABLE = 1, + parameter APP_DMA_ENABLE = 1, + parameter APP_AXIS_DIRECT_ENABLE = 1, + parameter APP_AXIS_SYNC_ENABLE = 1, + parameter APP_AXIS_IF_ENABLE = 1, + parameter APP_STAT_ENABLE = 1, + + // DMA interface configuration + parameter DMA_IMM_ENABLE = 0, + parameter DMA_IMM_WIDTH = 32, + parameter DMA_LEN_WIDTH = 16, + parameter DMA_TAG_WIDTH = 16, + parameter RAM_ADDR_WIDTH = $clog2(TX_RAM_SIZE > RX_RAM_SIZE ? TX_RAM_SIZE : RX_RAM_SIZE), + parameter RAM_PIPELINE = 2, + + // PCIe interface configuration + parameter AXIS_PCIE_DATA_WIDTH = 512, + parameter PF_COUNT = 1, + parameter VF_COUNT = 0, + + // Interrupt configuration + parameter IRQ_INDEX_WIDTH = EQN_WIDTH - FUNCTION_ID_WIDTH, + + // AXI lite interface configuration (control) + parameter AXIL_CTRL_DATA_WIDTH = 32, + parameter AXIL_CTRL_ADDR_WIDTH = 24, + + // AXI lite interface configuration (application control) + parameter AXIL_APP_CTRL_DATA_WIDTH = AXIL_CTRL_DATA_WIDTH, + parameter AXIL_APP_CTRL_ADDR_WIDTH = 24, + + // Ethernet interface configuration + parameter AXIS_ETH_TX_PIPELINE = 4, + parameter AXIS_ETH_TX_FIFO_PIPELINE = 4, + parameter AXIS_ETH_TX_TS_PIPELINE = 4, + parameter AXIS_ETH_RX_PIPELINE = 4, + parameter AXIS_ETH_RX_FIFO_PIPELINE = 4, + + // Statistics counter subsystem + parameter STAT_ENABLE = 1, + parameter STAT_DMA_ENABLE = 1, + parameter STAT_PCIE_ENABLE = 1, + parameter STAT_INC_WIDTH = 24, + parameter STAT_ID_WIDTH = 12, + parameter FUNCTION_ID_WIDTH = 8 +) +( + /* + * Clock and reset + */ + // input wire clk_100mhz_0_p, + // input wire clk_100mhz_0_n, + input wire clk_100mhz_1_p, + input wire clk_100mhz_1_n, + + /* + * GPIO + */ + output wire qsfp_led_act, + output wire qsfp_led_stat_g, + output wire qsfp_led_stat_y, + output wire hbm_cattrip, + input wire [1:0] msp_gpio, + output wire msp_uart_txd, + input wire msp_uart_rxd, + + /* + * PCI express + */ + input wire [15:0] pcie_rx_p, + input wire [15:0] pcie_rx_n, + output wire [15:0] pcie_tx_p, + output wire [15:0] pcie_tx_n, + input wire pcie_refclk_1_p, + input wire pcie_refclk_1_n, + input wire pcie_reset_n, + + /* + * Ethernet: QSFP28 + */ + output wire [3:0] qsfp_tx_p, + output wire [3:0] qsfp_tx_n, + input wire [3:0] qsfp_rx_p, + input wire [3:0] qsfp_rx_n, + input wire qsfp_mgt_refclk_0_p, + input wire qsfp_mgt_refclk_0_n + // input wire qsfp_mgt_refclk_1_p, + // input wire qsfp_mgt_refclk_1_n +); + +// PTP configuration +parameter PTP_CLK_PERIOD_NS_NUM = 1024; +parameter PTP_CLK_PERIOD_NS_DENOM = 165; +parameter PTP_TS_WIDTH = 96; + +// Interface configuration +parameter TX_TAG_WIDTH = 16; + +// RAM configuration +parameter AXI_HBM_DATA_WIDTH = 256; +parameter AXI_HBM_STRB_WIDTH = (AXI_HBM_DATA_WIDTH/8); +parameter AXI_HBM_ID_WIDTH = 6; + +// PCIe interface configuration +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 62 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; +parameter RC_STRADDLE = AXIS_PCIE_DATA_WIDTH >= 256; +parameter RQ_STRADDLE = AXIS_PCIE_DATA_WIDTH >= 512; +parameter CQ_STRADDLE = AXIS_PCIE_DATA_WIDTH >= 512; +parameter CC_STRADDLE = AXIS_PCIE_DATA_WIDTH >= 512; +parameter RQ_SEQ_NUM_WIDTH = 6; +parameter PCIE_TAG_COUNT = 256; + +// Ethernet interface configuration +parameter AXIS_ETH_DATA_WIDTH = 512; +parameter AXIS_ETH_KEEP_WIDTH = AXIS_ETH_DATA_WIDTH/8; +parameter AXIS_ETH_SYNC_DATA_WIDTH = AXIS_ETH_DATA_WIDTH; +parameter AXIS_ETH_TX_USER_WIDTH = TX_TAG_WIDTH + 1; +parameter AXIS_ETH_RX_USER_WIDTH = (PTP_TS_ENABLE ? PTP_TS_WIDTH : 0) + 1; + +// Clock and reset +wire pcie_user_clk; +wire pcie_user_reset; + +wire clk_100mhz_1_ibufg; +wire clk_100mhz_1_int; + +wire clk_50mhz_mmcm_out; +wire clk_125mhz_mmcm_out; + +// Internal 50 MHz clock +wire clk_50mhz_int; +wire rst_50mhz_int; + +// Internal 125 MHz clock +wire clk_125mhz_int; +wire rst_125mhz_int; + +wire mmcm_rst = pcie_user_reset; +wire mmcm_locked; +wire mmcm_clkfb; + +IBUFGDS #( + .DIFF_TERM("FALSE"), + .IBUF_LOW_PWR("FALSE") +) +clk_100mhz_1_ibufg_inst ( + .O (clk_100mhz_1_ibufg), + .I (clk_100mhz_1_p), + .IB (clk_100mhz_1_n) +); + +BUFG +clk_100mhz_1_bufg_inst ( + .I(clk_100mhz_1_ibufg), + .O(clk_100mhz_1_int) +); + +// MMCM instance +// 100 MHz in, 125 MHz + 50 MHz out +// PFD range: 10 MHz to 500 MHz +// VCO range: 800 MHz to 1600 MHz +// M = 10, D = 1 sets Fvco = 1000 MHz +// Divide by 8 to get output frequency of 125 MHz +// Divide by 20 to get output frequency of 50 MHz +MMCME4_BASE #( + .BANDWIDTH("OPTIMIZED"), + .CLKOUT0_DIVIDE_F(8), + .CLKOUT0_DUTY_CYCLE(0.5), + .CLKOUT0_PHASE(0), + .CLKOUT1_DIVIDE(20), + .CLKOUT1_DUTY_CYCLE(0.5), + .CLKOUT1_PHASE(0), + .CLKOUT2_DIVIDE(1), + .CLKOUT2_DUTY_CYCLE(0.5), + .CLKOUT2_PHASE(0), + .CLKOUT3_DIVIDE(1), + .CLKOUT3_DUTY_CYCLE(0.5), + .CLKOUT3_PHASE(0), + .CLKOUT4_DIVIDE(1), + .CLKOUT4_DUTY_CYCLE(0.5), + .CLKOUT4_PHASE(0), + .CLKOUT5_DIVIDE(1), + .CLKOUT5_DUTY_CYCLE(0.5), + .CLKOUT5_PHASE(0), + .CLKOUT6_DIVIDE(1), + .CLKOUT6_DUTY_CYCLE(0.5), + .CLKOUT6_PHASE(0), + .CLKFBOUT_MULT_F(10), + .CLKFBOUT_PHASE(0), + .DIVCLK_DIVIDE(1), + .REF_JITTER1(0.010), + .CLKIN1_PERIOD(10.000), + .STARTUP_WAIT("FALSE"), + .CLKOUT4_CASCADE("FALSE") +) +clk_mmcm_inst ( + .CLKIN1(clk_100mhz_1_int), + .CLKFBIN(mmcm_clkfb), + .RST(mmcm_rst), + .PWRDWN(1'b0), + .CLKOUT0(clk_125mhz_mmcm_out), + .CLKOUT0B(), + .CLKOUT1(clk_50mhz_mmcm_out), + .CLKOUT1B(), + .CLKOUT2(), + .CLKOUT2B(), + .CLKOUT3(), + .CLKOUT3B(), + .CLKOUT4(), + .CLKOUT5(), + .CLKOUT6(), + .CLKFBOUT(mmcm_clkfb), + .CLKFBOUTB(), + .LOCKED(mmcm_locked) +); + +BUFG +clk_50mhz_bufg_inst ( + .I(clk_50mhz_mmcm_out), + .O(clk_50mhz_int) +); + +BUFG +clk_125mhz_bufg_inst ( + .I(clk_125mhz_mmcm_out), + .O(clk_125mhz_int) +); + +sync_reset #( + .N(4) +) +sync_reset_50mhz_inst ( + .clk(clk_50mhz_int), + .rst(~mmcm_locked), + .out(rst_50mhz_int) +); + +sync_reset #( + .N(4) +) +sync_reset_125mhz_inst ( + .clk(clk_125mhz_int), + .rst(~mmcm_locked), + .out(rst_125mhz_int) +); + +// Flash +wire qspi_clk_int; +wire [3:0] qspi_dq_int; +wire [3:0] qspi_dq_i_int; +wire [3:0] qspi_dq_o_int; +wire [3:0] qspi_dq_oe_int; +wire qspi_cs_int; + +reg qspi_clk_reg; +reg [3:0] qspi_dq_o_reg; +reg [3:0] qspi_dq_oe_reg; +reg qspi_cs_reg; + +always @(posedge pcie_user_clk) begin + qspi_clk_reg <= qspi_clk_int; + qspi_dq_o_reg <= qspi_dq_o_int; + qspi_dq_oe_reg <= qspi_dq_oe_int; + qspi_cs_reg <= qspi_cs_int; +end + +sync_signal #( + .WIDTH(4), + .N(2) +) +flash_sync_signal_inst ( + .clk(pcie_user_clk), + .in({qspi_dq_int}), + .out({qspi_dq_i_int}) +); + +STARTUPE3 +startupe3_inst ( + .CFGCLK(), + .CFGMCLK(), + .DI(qspi_dq_int), + .DO(qspi_dq_o_reg), + .DTS(~qspi_dq_oe_reg), + .EOS(), + .FCSBO(qspi_cs_reg), + .FCSBTS(1'b0), + .GSR(1'b0), + .GTS(1'b0), + .KEYCLEARB(1'b1), + .PACK(1'b0), + .PREQ(), + .USRCCLKO(qspi_clk_reg), + .USRCCLKTS(1'b0), + .USRDONEO(1'b0), + .USRDONETS(1'b1) +); + +// FPGA boot +wire fpga_boot; + +reg fpga_boot_sync_reg_0 = 1'b0; +reg fpga_boot_sync_reg_1 = 1'b0; +reg fpga_boot_sync_reg_2 = 1'b0; + +wire icap_avail; +reg [2:0] icap_state = 0; +reg icap_csib_reg = 1'b1; +reg icap_rdwrb_reg = 1'b0; +reg [31:0] icap_di_reg = 32'hffffffff; + +wire [31:0] icap_di_rev; + +assign icap_di_rev[ 7] = icap_di_reg[ 0]; +assign icap_di_rev[ 6] = icap_di_reg[ 1]; +assign icap_di_rev[ 5] = icap_di_reg[ 2]; +assign icap_di_rev[ 4] = icap_di_reg[ 3]; +assign icap_di_rev[ 3] = icap_di_reg[ 4]; +assign icap_di_rev[ 2] = icap_di_reg[ 5]; +assign icap_di_rev[ 1] = icap_di_reg[ 6]; +assign icap_di_rev[ 0] = icap_di_reg[ 7]; + +assign icap_di_rev[15] = icap_di_reg[ 8]; +assign icap_di_rev[14] = icap_di_reg[ 9]; +assign icap_di_rev[13] = icap_di_reg[10]; +assign icap_di_rev[12] = icap_di_reg[11]; +assign icap_di_rev[11] = icap_di_reg[12]; +assign icap_di_rev[10] = icap_di_reg[13]; +assign icap_di_rev[ 9] = icap_di_reg[14]; +assign icap_di_rev[ 8] = icap_di_reg[15]; + +assign icap_di_rev[23] = icap_di_reg[16]; +assign icap_di_rev[22] = icap_di_reg[17]; +assign icap_di_rev[21] = icap_di_reg[18]; +assign icap_di_rev[20] = icap_di_reg[19]; +assign icap_di_rev[19] = icap_di_reg[20]; +assign icap_di_rev[18] = icap_di_reg[21]; +assign icap_di_rev[17] = icap_di_reg[22]; +assign icap_di_rev[16] = icap_di_reg[23]; + +assign icap_di_rev[31] = icap_di_reg[24]; +assign icap_di_rev[30] = icap_di_reg[25]; +assign icap_di_rev[29] = icap_di_reg[26]; +assign icap_di_rev[28] = icap_di_reg[27]; +assign icap_di_rev[27] = icap_di_reg[28]; +assign icap_di_rev[26] = icap_di_reg[29]; +assign icap_di_rev[25] = icap_di_reg[30]; +assign icap_di_rev[24] = icap_di_reg[31]; + +always @(posedge clk_125mhz_int) begin + case (icap_state) + 0: begin + icap_state <= 0; + icap_csib_reg <= 1'b1; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'hffffffff; // dummy word + + if (fpga_boot_sync_reg_2 && icap_avail) begin + icap_state <= 1; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'hffffffff; // dummy word + end + end + 1: begin + icap_state <= 2; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'hAA995566; // sync word + end + 2: begin + icap_state <= 3; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h20000000; // type 1 noop + end + 3: begin + icap_state <= 4; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h30008001; // write 1 word to CMD + end + 4: begin + icap_state <= 5; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h0000000F; // IPROG + end + 5: begin + icap_state <= 0; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h20000000; // type 1 noop + end + endcase + + fpga_boot_sync_reg_0 <= fpga_boot; + fpga_boot_sync_reg_1 <= fpga_boot_sync_reg_0; + fpga_boot_sync_reg_2 <= fpga_boot_sync_reg_1; +end + +ICAPE3 +icape3_inst ( + .AVAIL(icap_avail), + .CLK(clk_125mhz_int), + .CSIB(icap_csib_reg), + .I(icap_di_rev), + .O(), + .PRDONE(), + .PRERROR(), + .RDWRB(icap_rdwrb_reg) +); + +// BMC +wire axil_cms_clk; +wire axil_cms_rst; +wire [17:0] axil_cms_awaddr; +wire [2:0] axil_cms_awprot; +wire axil_cms_awvalid; +wire axil_cms_awready; +wire [31:0] axil_cms_wdata; +wire [3:0] axil_cms_wstrb; +wire axil_cms_wvalid; +wire axil_cms_wready; +wire [1:0] axil_cms_bresp; +wire axil_cms_bvalid; +wire axil_cms_bready; +wire [17:0] axil_cms_araddr; +wire [2:0] axil_cms_arprot; +wire axil_cms_arvalid; +wire axil_cms_arready; +wire [31:0] axil_cms_rdata; +wire [1:0] axil_cms_rresp; +wire axil_cms_rvalid; +wire axil_cms_rready; + +wire [6:0] hbm_temp_1; +wire [6:0] hbm_temp_2; + +generate + +if (CMS_ENABLE) begin : cms + + wire [17:0] axil_cms_awaddr_int; + wire [2:0] axil_cms_awprot_int; + wire axil_cms_awvalid_int; + wire axil_cms_awready_int; + wire [31:0] axil_cms_wdata_int; + wire [3:0] axil_cms_wstrb_int; + wire axil_cms_wvalid_int; + wire axil_cms_wready_int; + wire [1:0] axil_cms_bresp_int; + wire axil_cms_bvalid_int; + wire axil_cms_bready_int; + wire [17:0] axil_cms_araddr_int; + wire [2:0] axil_cms_arprot_int; + wire axil_cms_arvalid_int; + wire axil_cms_arready_int; + wire [31:0] axil_cms_rdata_int; + wire [1:0] axil_cms_rresp_int; + wire axil_cms_rvalid_int; + wire axil_cms_rready_int; + + axil_cdc #( + .DATA_WIDTH(32), + .ADDR_WIDTH(18) + ) + cms_axil_cdc_inst ( + .s_clk(axil_cms_clk), + .s_rst(axil_cms_rst), + .s_axil_awaddr(axil_cms_awaddr), + .s_axil_awprot(axil_cms_awprot), + .s_axil_awvalid(axil_cms_awvalid), + .s_axil_awready(axil_cms_awready), + .s_axil_wdata(axil_cms_wdata), + .s_axil_wstrb(axil_cms_wstrb), + .s_axil_wvalid(axil_cms_wvalid), + .s_axil_wready(axil_cms_wready), + .s_axil_bresp(axil_cms_bresp), + .s_axil_bvalid(axil_cms_bvalid), + .s_axil_bready(axil_cms_bready), + .s_axil_araddr(axil_cms_araddr), + .s_axil_arprot(axil_cms_arprot), + .s_axil_arvalid(axil_cms_arvalid), + .s_axil_arready(axil_cms_arready), + .s_axil_rdata(axil_cms_rdata), + .s_axil_rresp(axil_cms_rresp), + .s_axil_rvalid(axil_cms_rvalid), + .s_axil_rready(axil_cms_rready), + .m_clk(clk_50mhz_int), + .m_rst(rst_50mhz_int), + .m_axil_awaddr(axil_cms_awaddr_int), + .m_axil_awprot(axil_cms_awprot_int), + .m_axil_awvalid(axil_cms_awvalid_int), + .m_axil_awready(axil_cms_awready_int), + .m_axil_wdata(axil_cms_wdata_int), + .m_axil_wstrb(axil_cms_wstrb_int), + .m_axil_wvalid(axil_cms_wvalid_int), + .m_axil_wready(axil_cms_wready_int), + .m_axil_bresp(axil_cms_bresp_int), + .m_axil_bvalid(axil_cms_bvalid_int), + .m_axil_bready(axil_cms_bready_int), + .m_axil_araddr(axil_cms_araddr_int), + .m_axil_arprot(axil_cms_arprot_int), + .m_axil_arvalid(axil_cms_arvalid_int), + .m_axil_arready(axil_cms_arready_int), + .m_axil_rdata(axil_cms_rdata_int), + .m_axil_rresp(axil_cms_rresp_int), + .m_axil_rvalid(axil_cms_rvalid_int), + .m_axil_rready(axil_cms_rready_int) + ); + + cms_wrapper + cms_inst ( + .aclk_ctrl_0(clk_50mhz_int), + .aresetn_ctrl_0(~rst_50mhz_int), + .hbm_temp_1_0(hbm_temp_1), + .hbm_temp_2_0(hbm_temp_2), + .interrupt_hbm_cattrip_0(hbm_cattrip), + .interrupt_host_0(), + .s_axi_ctrl_0_araddr(axil_cms_araddr_int), + .s_axi_ctrl_0_arprot(axil_cms_arprot_int), + .s_axi_ctrl_0_arready(axil_cms_arready_int), + .s_axi_ctrl_0_arvalid(axil_cms_arvalid_int), + .s_axi_ctrl_0_awaddr(axil_cms_awaddr_int), + .s_axi_ctrl_0_awprot(axil_cms_awprot_int), + .s_axi_ctrl_0_awready(axil_cms_awready_int), + .s_axi_ctrl_0_awvalid(axil_cms_awvalid_int), + .s_axi_ctrl_0_bready(axil_cms_bready_int), + .s_axi_ctrl_0_bresp(axil_cms_bresp_int), + .s_axi_ctrl_0_bvalid(axil_cms_bvalid_int), + .s_axi_ctrl_0_rdata(axil_cms_rdata_int), + .s_axi_ctrl_0_rready(axil_cms_rready_int), + .s_axi_ctrl_0_rresp(axil_cms_rresp_int), + .s_axi_ctrl_0_rvalid(axil_cms_rvalid_int), + .s_axi_ctrl_0_wdata(axil_cms_wdata_int), + .s_axi_ctrl_0_wready(axil_cms_wready_int), + .s_axi_ctrl_0_wstrb(axil_cms_wstrb_int), + .s_axi_ctrl_0_wvalid(axil_cms_wvalid_int), + .satellite_gpio_0(msp_gpio), + .satellite_uart_0_rxd(msp_uart_rxd), + .satellite_uart_0_txd(msp_uart_txd) + ); + +end else begin + + assign axil_cms_awready = 0; + assign axil_cms_wdata = 0; + assign axil_cms_wstrb = 0; + assign axil_cms_wvalid = 0; + assign axil_cms_bresp = 0; + assign axil_cms_bvalid = 0; + assign axil_cms_arready = 0; + assign axil_cms_rdata = 0; + assign axil_cms_rresp = 0; + assign axil_cms_rvalid = 0; + + assign msp_uart_txd = 1'bz; + +end + +endgenerate + +// PCIe +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE4 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte4_pcie_mgt_refclk_inst ( + .I (pcie_refclk_1_p), + .IB (pcie_refclk_1_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0; +wire pcie_rq_seq_num_vld0; +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1; +wire pcie_rq_seq_num_vld1; + +wire [3:0] pcie_tfc_nph_av; +wire [3:0] pcie_tfc_npd_av; + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; +wire [3:0] cfg_rcb_status; + +wire [9:0] cfg_mgmt_addr; +wire [7:0] cfg_mgmt_function_number; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msix_enable; +wire [3:0] cfg_interrupt_msix_mask; +wire [251:0] cfg_interrupt_msix_vf_enable; +wire [251:0] cfg_interrupt_msix_vf_mask; +wire [63:0] cfg_interrupt_msix_address; +wire [31:0] cfg_interrupt_msix_data; +wire cfg_interrupt_msix_int; +wire [1:0] cfg_interrupt_msix_vec_pending; +wire cfg_interrupt_msix_vec_pending_status; +wire cfg_interrupt_msix_sent; +wire cfg_interrupt_msix_fail; +wire [7:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +// extra register for pcie_user_reset signal +wire pcie_user_reset_int; +(* shreg_extract = "no" *) +reg pcie_user_reset_reg_1 = 1'b1; +(* shreg_extract = "no" *) +reg pcie_user_reset_reg_2 = 1'b1; + +always @(posedge pcie_user_clk) begin + pcie_user_reset_reg_1 <= pcie_user_reset_int; + pcie_user_reset_reg_2 <= pcie_user_reset_reg_1; +end + +BUFG +pcie_user_reset_bufg_inst ( + .I(pcie_user_reset_reg_2), + .O(pcie_user_reset) +); + +pcie4c_uscale_plus_0 +pcie4c_uscale_plus_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset_int), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num0(pcie_rq_seq_num0), + .pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0), + .pcie_rq_seq_num1(pcie_rq_seq_num1), + .pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1), + .pcie_rq_tag0(), + .pcie_rq_tag1(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld0(), + .pcie_rq_tag_vld1(), + + .pcie_tfc_nph_av(pcie_tfc_nph_av), + .pcie_tfc_npd_av(pcie_tfc_npd_av), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_debug_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error_valid(), + .cfg_local_error_out(), + .cfg_ltssm_state(), + .cfg_rx_pm_state(), + .cfg_tx_pm_state(), + .cfg_rcb_status(cfg_rcb_status), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_dsn(64'd0), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_func_num(8'd0), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msix_enable(cfg_interrupt_msix_enable), + .cfg_interrupt_msix_mask(cfg_interrupt_msix_mask), + .cfg_interrupt_msix_vf_enable(cfg_interrupt_msix_vf_enable), + .cfg_interrupt_msix_vf_mask(cfg_interrupt_msix_vf_mask), + .cfg_interrupt_msix_address(cfg_interrupt_msix_address), + .cfg_interrupt_msix_data(cfg_interrupt_msix_data), + .cfg_interrupt_msix_int(cfg_interrupt_msix_int), + .cfg_interrupt_msix_vec_pending(cfg_interrupt_msix_vec_pending), + .cfg_interrupt_msix_vec_pending_status(cfg_interrupt_msix_vec_pending_status), + .cfg_interrupt_msi_sent(cfg_interrupt_msix_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msix_fail), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_pm_aspm_l1_entry_reject(1'b0), + .cfg_pm_aspm_tx_l0s_entry_disable(1'b0), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(pcie_reset_n), + + .phy_rdy_out() +); + +reg [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0_reg; +reg pcie_rq_seq_num_vld0_reg; +reg [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1_reg; +reg pcie_rq_seq_num_vld1_reg; + +always @(posedge pcie_user_clk) begin + pcie_rq_seq_num0_reg <= pcie_rq_seq_num0; + pcie_rq_seq_num_vld0_reg <= pcie_rq_seq_num_vld0; + pcie_rq_seq_num1_reg <= pcie_rq_seq_num1; + pcie_rq_seq_num_vld1_reg <= pcie_rq_seq_num_vld1; + + if (pcie_user_reset) begin + pcie_rq_seq_num_vld0_reg <= 1'b0; + pcie_rq_seq_num_vld1_reg <= 1'b0; + end +end + +// Ethernet +localparam QSFP_CNT = 1; + +wire [QSFP_CNT-1:0] qsfp_tx_clk; +wire [QSFP_CNT-1:0] qsfp_tx_rst; + +wire [QSFP_CNT*AXIS_ETH_DATA_WIDTH-1:0] qsfp_tx_axis_tdata; +wire [QSFP_CNT*AXIS_ETH_KEEP_WIDTH-1:0] qsfp_tx_axis_tkeep; +wire [QSFP_CNT-1:0] qsfp_tx_axis_tvalid; +wire [QSFP_CNT-1:0] qsfp_tx_axis_tready; +wire [QSFP_CNT-1:0] qsfp_tx_axis_tlast; +wire [QSFP_CNT*(16+1)-1:0] qsfp_tx_axis_tuser; + +wire [QSFP_CNT*80-1:0] qsfp_tx_ptp_time; +wire [QSFP_CNT*80-1:0] qsfp_tx_ptp_ts; +wire [QSFP_CNT*16-1:0] qsfp_tx_ptp_ts_tag; +wire [QSFP_CNT-1:0] qsfp_tx_ptp_ts_valid; + +wire [QSFP_CNT-1:0] qsfp_tx_enable; +wire [QSFP_CNT-1:0] qsfp_tx_lfc_en; +wire [QSFP_CNT-1:0] qsfp_tx_lfc_req; +wire [QSFP_CNT*8-1:0] qsfp_tx_pfc_en; +wire [QSFP_CNT*8-1:0] qsfp_tx_pfc_req; + +wire [QSFP_CNT-1:0] qsfp_rx_clk; +wire [QSFP_CNT-1:0] qsfp_rx_rst; + +wire [QSFP_CNT*AXIS_ETH_DATA_WIDTH-1:0] qsfp_rx_axis_tdata; +wire [QSFP_CNT*AXIS_ETH_KEEP_WIDTH-1:0] qsfp_rx_axis_tkeep; +wire [QSFP_CNT-1:0] qsfp_rx_axis_tvalid; +wire [QSFP_CNT-1:0] qsfp_rx_axis_tlast; +wire [QSFP_CNT*(80+1)-1:0] qsfp_rx_axis_tuser; + +wire [QSFP_CNT*80-1:0] qsfp_rx_ptp_time; + +wire [QSFP_CNT-1:0] qsfp_rx_enable; +wire [QSFP_CNT-1:0] qsfp_rx_status; +wire [QSFP_CNT-1:0] qsfp_rx_lfc_en; +wire [QSFP_CNT-1:0] qsfp_rx_lfc_req; +wire [QSFP_CNT-1:0] qsfp_rx_lfc_ack; +wire [QSFP_CNT*8-1:0] qsfp_rx_pfc_en; +wire [QSFP_CNT*8-1:0] qsfp_rx_pfc_req; +wire [QSFP_CNT*8-1:0] qsfp_rx_pfc_ack; + +wire [QSFP_CNT-1:0] qsfp_drp_clk; +wire [QSFP_CNT-1:0] qsfp_drp_rst; +wire [QSFP_CNT*24-1:0] qsfp_drp_addr; +wire [QSFP_CNT*16-1:0] qsfp_drp_di; +wire [QSFP_CNT-1:0] qsfp_drp_en; +wire [QSFP_CNT-1:0] qsfp_drp_we; +wire [QSFP_CNT*16-1:0] qsfp_drp_do; +wire [QSFP_CNT-1:0] qsfp_drp_rdy; + +// CMAC +assign qsfp_drp_clk[0 +: 1] = clk_125mhz_int; +assign qsfp_drp_rst[0 +: 1] = rst_125mhz_int; + +wire qsfp_gtpowergood; + +wire qsfp_mgt_refclk_0; +wire qsfp_mgt_refclk_0_int; +wire qsfp_mgt_refclk_0_bufg; + +IBUFDS_GTE4 ibufds_gte4_qsfp_mgt_refclk_0_inst ( + .I (qsfp_mgt_refclk_0_p), + .IB (qsfp_mgt_refclk_0_n), + .CEB (1'b0), + .O (qsfp_mgt_refclk_0), + .ODIV2 (qsfp_mgt_refclk_0_int) +); + +BUFG_GT bufg_gt_qsfp_mgt_refclk_0_inst ( + .CE (qsfp_gtpowergood), + .CEMASK (1'b1), + .CLR (1'b0), + .CLRMASK (1'b1), + .DIV (3'd0), + .I (qsfp_mgt_refclk_0_int), + .O (qsfp_mgt_refclk_0_bufg) +); + +wire qsfp_rst; + +sync_reset #( + .N(4) +) +qsfp_sync_reset_inst ( + .clk(qsfp_mgt_refclk_0_bufg), + .rst(rst_125mhz_int), + .out(qsfp_rst) +); + +cmac_gty_wrapper #( + .DRP_CLK_FREQ_HZ(125000000), + .AXIS_DATA_WIDTH(AXIS_ETH_DATA_WIDTH), + .AXIS_KEEP_WIDTH(AXIS_ETH_KEEP_WIDTH), + .TX_SERDES_PIPELINE(0), + .RX_SERDES_PIPELINE(0), + .RS_FEC_ENABLE(1) +) +qsfp_cmac_inst ( + .xcvr_ctrl_clk(clk_125mhz_int), + .xcvr_ctrl_rst(qsfp_rst), + + /* + * Common + */ + .xcvr_gtpowergood_out(qsfp_gtpowergood), + .xcvr_ref_clk(qsfp_mgt_refclk_0), + + /* + * DRP + */ + .drp_clk(qsfp_drp_clk[0 +: 1]), + .drp_rst(qsfp_drp_rst[0 +: 1]), + .drp_addr(qsfp_drp_addr[0*24 +: 24]), + .drp_di(qsfp_drp_di[0*16 +: 16]), + .drp_en(qsfp_drp_en[0 +: 1]), + .drp_we(qsfp_drp_we[0 +: 1]), + .drp_do(qsfp_drp_do[0*16 +: 16]), + .drp_rdy(qsfp_drp_rdy[0 +: 1]), + + /* + * Serial data + */ + .xcvr_txp(qsfp_tx_p), + .xcvr_txn(qsfp_tx_n), + .xcvr_rxp(qsfp_rx_p), + .xcvr_rxn(qsfp_rx_n), + + /* + * CMAC connections + */ + .tx_clk(qsfp_tx_clk[0 +: 1]), + .tx_rst(qsfp_tx_rst[0 +: 1]), + + .tx_axis_tdata(qsfp_tx_axis_tdata[0*AXIS_ETH_DATA_WIDTH +: AXIS_ETH_DATA_WIDTH]), + .tx_axis_tkeep(qsfp_tx_axis_tkeep[0*AXIS_ETH_KEEP_WIDTH +: AXIS_ETH_KEEP_WIDTH]), + .tx_axis_tvalid(qsfp_tx_axis_tvalid[0 +: 1]), + .tx_axis_tready(qsfp_tx_axis_tready[0 +: 1]), + .tx_axis_tlast(qsfp_tx_axis_tlast[0 +: 1]), + .tx_axis_tuser(qsfp_tx_axis_tuser[0*(16+1) +: (16+1)]), + + .tx_ptp_time(qsfp_tx_ptp_time[0*80 +: 80]), + .tx_ptp_ts(qsfp_tx_ptp_ts[0*80 +: 80]), + .tx_ptp_ts_tag(qsfp_tx_ptp_ts_tag[0*16 +: 16]), + .tx_ptp_ts_valid(qsfp_tx_ptp_ts_valid[0 +: 1]), + + .tx_enable(qsfp_tx_enable[0 +: 1]), + .tx_lfc_en(qsfp_tx_lfc_en[0 +: 1]), + .tx_lfc_req(qsfp_tx_lfc_req[0 +: 1]), + .tx_pfc_en(qsfp_tx_pfc_en[0*8 +: 8]), + .tx_pfc_req(qsfp_tx_pfc_req[0*8 +: 8]), + + .rx_clk(qsfp_rx_clk[0 +: 1]), + .rx_rst(qsfp_rx_rst[0 +: 1]), + + .rx_axis_tdata(qsfp_rx_axis_tdata[0*AXIS_ETH_DATA_WIDTH +: AXIS_ETH_DATA_WIDTH]), + .rx_axis_tkeep(qsfp_rx_axis_tkeep[0*AXIS_ETH_KEEP_WIDTH +: AXIS_ETH_KEEP_WIDTH]), + .rx_axis_tvalid(qsfp_rx_axis_tvalid[0 +: 1]), + .rx_axis_tlast(qsfp_rx_axis_tlast[0 +: 1]), + .rx_axis_tuser(qsfp_rx_axis_tuser[0*(80+1) +: (80+1)]), + + .rx_ptp_time(qsfp_rx_ptp_time[0*80 +: 80]), + + .rx_enable(qsfp_rx_enable[0 +: 1]), + .rx_status(qsfp_rx_status[0 +: 1]), + .rx_lfc_en(qsfp_rx_lfc_en[0 +: 1]), + .rx_lfc_req(qsfp_rx_lfc_req[0 +: 1]), + .rx_lfc_ack(qsfp_rx_lfc_ack[0 +: 1]), + .rx_pfc_en(qsfp_rx_pfc_en[0*8 +: 8]), + .rx_pfc_req(qsfp_rx_pfc_req[0*8 +: 8]), + .rx_pfc_ack(qsfp_rx_pfc_ack[0*8 +: 8]) +); + +wire ptp_clk; +wire ptp_rst; +wire ptp_sample_clk; + +assign ptp_clk = qsfp_mgt_refclk_0_bufg; +assign ptp_rst = qsfp_rst; +assign ptp_sample_clk = clk_125mhz_int; + +assign qsfp_led_stat_g = qsfp_rx_status; + +// HBM +wire [HBM_CH-1:0] hbm_clk; +wire [HBM_CH-1:0] hbm_rst; + +wire [HBM_CH*AXI_HBM_ID_WIDTH-1:0] m_axi_hbm_awid; +wire [HBM_CH*AXI_HBM_ADDR_WIDTH-1:0] m_axi_hbm_awaddr; +wire [HBM_CH*8-1:0] m_axi_hbm_awlen; +wire [HBM_CH*3-1:0] m_axi_hbm_awsize; +wire [HBM_CH*2-1:0] m_axi_hbm_awburst; +wire [HBM_CH-1:0] m_axi_hbm_awlock; +wire [HBM_CH*4-1:0] m_axi_hbm_awcache; +wire [HBM_CH*3-1:0] m_axi_hbm_awprot; +wire [HBM_CH*4-1:0] m_axi_hbm_awqos; +wire [HBM_CH-1:0] m_axi_hbm_awvalid; +wire [HBM_CH-1:0] m_axi_hbm_awready; +wire [HBM_CH*AXI_HBM_DATA_WIDTH-1:0] m_axi_hbm_wdata; +wire [HBM_CH*AXI_HBM_STRB_WIDTH-1:0] m_axi_hbm_wstrb; +wire [HBM_CH-1:0] m_axi_hbm_wlast; +wire [HBM_CH-1:0] m_axi_hbm_wvalid; +wire [HBM_CH-1:0] m_axi_hbm_wready; +wire [HBM_CH*AXI_HBM_ID_WIDTH-1:0] m_axi_hbm_bid; +wire [HBM_CH*2-1:0] m_axi_hbm_bresp; +wire [HBM_CH-1:0] m_axi_hbm_bvalid; +wire [HBM_CH-1:0] m_axi_hbm_bready; +wire [HBM_CH*AXI_HBM_ID_WIDTH-1:0] m_axi_hbm_arid; +wire [HBM_CH*AXI_HBM_ADDR_WIDTH-1:0] m_axi_hbm_araddr; +wire [HBM_CH*8-1:0] m_axi_hbm_arlen; +wire [HBM_CH*3-1:0] m_axi_hbm_arsize; +wire [HBM_CH*2-1:0] m_axi_hbm_arburst; +wire [HBM_CH-1:0] m_axi_hbm_arlock; +wire [HBM_CH*4-1:0] m_axi_hbm_arcache; +wire [HBM_CH*3-1:0] m_axi_hbm_arprot; +wire [HBM_CH*4-1:0] m_axi_hbm_arqos; +wire [HBM_CH-1:0] m_axi_hbm_arvalid; +wire [HBM_CH-1:0] m_axi_hbm_arready; +wire [HBM_CH*AXI_HBM_ID_WIDTH-1:0] m_axi_hbm_rid; +wire [HBM_CH*AXI_HBM_DATA_WIDTH-1:0] m_axi_hbm_rdata; +wire [HBM_CH*2-1:0] m_axi_hbm_rresp; +wire [HBM_CH-1:0] m_axi_hbm_rlast; +wire [HBM_CH-1:0] m_axi_hbm_rvalid; +wire [HBM_CH-1:0] m_axi_hbm_rready; + +wire [HBM_CH-1:0] hbm_status; + +generate + +if (HBM_ENABLE) begin + + wire hbm_ref_clk = clk_100mhz_1_int; + + wire hbm_cattrip_1; + wire hbm_cattrip_2; + + assign hbm_cattrip = hbm_cattrip_1 | hbm_cattrip_2; + + fpga_hbm #( + .HBM_CH(HBM_CH), + .HBM_GROUP_SIZE(HBM_GROUP_SIZE), + .AXI_HBM_DATA_WIDTH(AXI_HBM_DATA_WIDTH), + .AXI_HBM_ADDR_WIDTH(AXI_HBM_ADDR_WIDTH), + .AXI_HBM_STRB_WIDTH(AXI_HBM_STRB_WIDTH), + .AXI_HBM_ID_WIDTH(AXI_HBM_ID_WIDTH), + .AXI_HBM_MAX_BURST_LEN(AXI_HBM_MAX_BURST_LEN) + ) + hbm_inst ( + .hbm_ref_clk(hbm_ref_clk), + .hbm_rst_in(rst_125mhz_int), + + .hbm_cattrip_1(hbm_cattrip_1), + .hbm_cattrip_2(hbm_cattrip_2), + .hbm_temp_1(hbm_temp_1), + .hbm_temp_2(hbm_temp_2), + + .hbm_clk(hbm_clk), + .hbm_rst(hbm_rst), + + .s_axi_hbm_awid(m_axi_hbm_awid), + .s_axi_hbm_awaddr(m_axi_hbm_awaddr), + .s_axi_hbm_awlen(m_axi_hbm_awlen), + .s_axi_hbm_awsize(m_axi_hbm_awsize), + .s_axi_hbm_awburst(m_axi_hbm_awburst), + .s_axi_hbm_awlock(m_axi_hbm_awlock), + .s_axi_hbm_awcache(m_axi_hbm_awcache), + .s_axi_hbm_awprot(m_axi_hbm_awprot), + .s_axi_hbm_awqos(m_axi_hbm_awqos), + .s_axi_hbm_awvalid(m_axi_hbm_awvalid), + .s_axi_hbm_awready(m_axi_hbm_awready), + .s_axi_hbm_wdata(m_axi_hbm_wdata), + .s_axi_hbm_wstrb(m_axi_hbm_wstrb), + .s_axi_hbm_wlast(m_axi_hbm_wlast), + .s_axi_hbm_wvalid(m_axi_hbm_wvalid), + .s_axi_hbm_wready(m_axi_hbm_wready), + .s_axi_hbm_bid(m_axi_hbm_bid), + .s_axi_hbm_bresp(m_axi_hbm_bresp), + .s_axi_hbm_bvalid(m_axi_hbm_bvalid), + .s_axi_hbm_bready(m_axi_hbm_bready), + .s_axi_hbm_arid(m_axi_hbm_arid), + .s_axi_hbm_araddr(m_axi_hbm_araddr), + .s_axi_hbm_arlen(m_axi_hbm_arlen), + .s_axi_hbm_arsize(m_axi_hbm_arsize), + .s_axi_hbm_arburst(m_axi_hbm_arburst), + .s_axi_hbm_arlock(m_axi_hbm_arlock), + .s_axi_hbm_arcache(m_axi_hbm_arcache), + .s_axi_hbm_arprot(m_axi_hbm_arprot), + .s_axi_hbm_arqos(m_axi_hbm_arqos), + .s_axi_hbm_arvalid(m_axi_hbm_arvalid), + .s_axi_hbm_arready(m_axi_hbm_arready), + .s_axi_hbm_rid(m_axi_hbm_rid), + .s_axi_hbm_rdata(m_axi_hbm_rdata), + .s_axi_hbm_rresp(m_axi_hbm_rresp), + .s_axi_hbm_rlast(m_axi_hbm_rlast), + .s_axi_hbm_rvalid(m_axi_hbm_rvalid), + .s_axi_hbm_rready(m_axi_hbm_rready), + + .hbm_status(hbm_status) + ); + +end else begin + + assign hbm_clk = 0; + assign hbm_rst = 0; + + assign m_axi_hbm_awready = 0; + assign m_axi_hbm_wready = 0; + assign m_axi_hbm_bid = 0; + assign m_axi_hbm_bresp = 0; + assign m_axi_hbm_bvalid = 0; + assign m_axi_hbm_arready = 0; + assign m_axi_hbm_rid = 0; + assign m_axi_hbm_rdata = 0; + assign m_axi_hbm_rresp = 0; + assign m_axi_hbm_rlast = 0; + assign m_axi_hbm_rvalid = 0; + + assign hbm_status = 0; + + assign hbm_cattrip = 1'b0; + + assign hbm_temp_1 = 7'd0; + assign hbm_temp_2 = 7'd0; + +end + +endgenerate + +fpga_core #( + // FW and board IDs + .FPGA_ID(FPGA_ID), + .FW_ID(FW_ID), + .FW_VER(FW_VER), + .BOARD_ID(BOARD_ID), + .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), + + // Board configuration + .QSFP_CNT(QSFP_CNT), + .CH_CNT(QSFP_CNT*4), + .CMS_ENABLE(CMS_ENABLE), + .FLASH_SEG_COUNT(2), + .FLASH_SEG_DEFAULT(1), + .FLASH_SEG_FALLBACK(0), + .FLASH_SEG0_SIZE(32'h01002000), + + // Structural configuration + .IF_COUNT(IF_COUNT), + .PORTS_PER_IF(PORTS_PER_IF), + .SCHED_PER_IF(SCHED_PER_IF), + .PORT_MASK(PORT_MASK), + + // Clock configuration + .CLK_PERIOD_NS_NUM(CLK_PERIOD_NS_NUM), + .CLK_PERIOD_NS_DENOM(CLK_PERIOD_NS_DENOM), + + // PTP configuration + .PTP_CLK_PERIOD_NS_NUM(PTP_CLK_PERIOD_NS_NUM), + .PTP_CLK_PERIOD_NS_DENOM(PTP_CLK_PERIOD_NS_DENOM), + .PTP_TS_WIDTH(PTP_TS_WIDTH), + .PTP_CLOCK_PIPELINE(PTP_CLOCK_PIPELINE), + .PTP_CLOCK_CDC_PIPELINE(PTP_CLOCK_CDC_PIPELINE), + .PTP_PORT_CDC_PIPELINE(PTP_PORT_CDC_PIPELINE), + .PTP_PEROUT_ENABLE(PTP_PEROUT_ENABLE), + .PTP_PEROUT_COUNT(PTP_PEROUT_COUNT), + + // Queue manager configuration + .EVENT_QUEUE_OP_TABLE_SIZE(EVENT_QUEUE_OP_TABLE_SIZE), + .TX_QUEUE_OP_TABLE_SIZE(TX_QUEUE_OP_TABLE_SIZE), + .RX_QUEUE_OP_TABLE_SIZE(RX_QUEUE_OP_TABLE_SIZE), + .CQ_OP_TABLE_SIZE(CQ_OP_TABLE_SIZE), + .EQN_WIDTH(EQN_WIDTH), + .TX_QUEUE_INDEX_WIDTH(TX_QUEUE_INDEX_WIDTH), + .RX_QUEUE_INDEX_WIDTH(RX_QUEUE_INDEX_WIDTH), + .CQN_WIDTH(CQN_WIDTH), + .EQ_PIPELINE(EQ_PIPELINE), + .TX_QUEUE_PIPELINE(TX_QUEUE_PIPELINE), + .RX_QUEUE_PIPELINE(RX_QUEUE_PIPELINE), + .CQ_PIPELINE(CQ_PIPELINE), + + // TX and RX engine configuration + .TX_DESC_TABLE_SIZE(TX_DESC_TABLE_SIZE), + .RX_DESC_TABLE_SIZE(RX_DESC_TABLE_SIZE), + .RX_INDIR_TBL_ADDR_WIDTH(RX_INDIR_TBL_ADDR_WIDTH), + + // Scheduler configuration + .TX_SCHEDULER_OP_TABLE_SIZE(TX_SCHEDULER_OP_TABLE_SIZE), + .TX_SCHEDULER_PIPELINE(TX_SCHEDULER_PIPELINE), + .TDMA_INDEX_WIDTH(TDMA_INDEX_WIDTH), + + // Interface configuration + .PTP_TS_ENABLE(PTP_TS_ENABLE), + .TX_CPL_FIFO_DEPTH(TX_CPL_FIFO_DEPTH), + .TX_TAG_WIDTH(TX_TAG_WIDTH), + .TX_CHECKSUM_ENABLE(TX_CHECKSUM_ENABLE), + .RX_HASH_ENABLE(RX_HASH_ENABLE), + .RX_CHECKSUM_ENABLE(RX_CHECKSUM_ENABLE), + .PFC_ENABLE(PFC_ENABLE), + .LFC_ENABLE(LFC_ENABLE), + .TX_FIFO_DEPTH(TX_FIFO_DEPTH), + .RX_FIFO_DEPTH(RX_FIFO_DEPTH), + .MAX_TX_SIZE(MAX_TX_SIZE), + .MAX_RX_SIZE(MAX_RX_SIZE), + .TX_RAM_SIZE(TX_RAM_SIZE), + .RX_RAM_SIZE(RX_RAM_SIZE), + + // RAM configuration + .DDR_ENABLE(0), + .HBM_CH(HBM_CH), + .HBM_ENABLE(HBM_ENABLE), + .HBM_GROUP_SIZE(HBM_GROUP_SIZE), + .AXI_HBM_DATA_WIDTH(AXI_HBM_DATA_WIDTH), + .AXI_HBM_ADDR_WIDTH(AXI_HBM_ADDR_WIDTH), + .AXI_HBM_STRB_WIDTH(AXI_HBM_STRB_WIDTH), + .AXI_HBM_ID_WIDTH(AXI_HBM_ID_WIDTH), + .AXI_HBM_MAX_BURST_LEN(AXI_HBM_MAX_BURST_LEN), + + // Application block configuration + .APP_ID(APP_ID), + .APP_ENABLE(APP_ENABLE), + .APP_CTRL_ENABLE(APP_CTRL_ENABLE), + .APP_DMA_ENABLE(APP_DMA_ENABLE), + .APP_AXIS_DIRECT_ENABLE(APP_AXIS_DIRECT_ENABLE), + .APP_AXIS_SYNC_ENABLE(APP_AXIS_SYNC_ENABLE), + .APP_AXIS_IF_ENABLE(APP_AXIS_IF_ENABLE), + .APP_STAT_ENABLE(APP_STAT_ENABLE), + + // DMA interface configuration + .DMA_IMM_ENABLE(DMA_IMM_ENABLE), + .DMA_IMM_WIDTH(DMA_IMM_WIDTH), + .DMA_LEN_WIDTH(DMA_LEN_WIDTH), + .DMA_TAG_WIDTH(DMA_TAG_WIDTH), + .RAM_ADDR_WIDTH(RAM_ADDR_WIDTH), + .RAM_PIPELINE(RAM_PIPELINE), + + // PCIe interface configuration + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RC_STRADDLE(RC_STRADDLE), + .RQ_STRADDLE(RQ_STRADDLE), + .CQ_STRADDLE(CQ_STRADDLE), + .CC_STRADDLE(CC_STRADDLE), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .PF_COUNT(PF_COUNT), + .VF_COUNT(VF_COUNT), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + + // Interrupt configuration + .IRQ_INDEX_WIDTH(IRQ_INDEX_WIDTH), + + // AXI lite interface configuration (control) + .AXIL_CTRL_DATA_WIDTH(AXIL_CTRL_DATA_WIDTH), + .AXIL_CTRL_ADDR_WIDTH(AXIL_CTRL_ADDR_WIDTH), + + // AXI lite interface configuration (application control) + .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), + .AXIL_APP_CTRL_ADDR_WIDTH(AXIL_APP_CTRL_ADDR_WIDTH), + + // Ethernet interface configuration + .AXIS_ETH_DATA_WIDTH(AXIS_ETH_DATA_WIDTH), + .AXIS_ETH_KEEP_WIDTH(AXIS_ETH_KEEP_WIDTH), + .AXIS_ETH_SYNC_DATA_WIDTH(AXIS_ETH_SYNC_DATA_WIDTH), + .AXIS_ETH_TX_USER_WIDTH(AXIS_ETH_TX_USER_WIDTH), + .AXIS_ETH_RX_USER_WIDTH(AXIS_ETH_RX_USER_WIDTH), + .AXIS_ETH_TX_PIPELINE(AXIS_ETH_TX_PIPELINE), + .AXIS_ETH_TX_FIFO_PIPELINE(AXIS_ETH_TX_FIFO_PIPELINE), + .AXIS_ETH_TX_TS_PIPELINE(AXIS_ETH_TX_TS_PIPELINE), + .AXIS_ETH_RX_PIPELINE(AXIS_ETH_RX_PIPELINE), + .AXIS_ETH_RX_FIFO_PIPELINE(AXIS_ETH_RX_FIFO_PIPELINE), + + // Statistics counter subsystem + .STAT_ENABLE(STAT_ENABLE), + .STAT_DMA_ENABLE(STAT_DMA_ENABLE), + .STAT_PCIE_ENABLE(STAT_PCIE_ENABLE), + .STAT_INC_WIDTH(STAT_INC_WIDTH), + .STAT_ID_WIDTH(STAT_ID_WIDTH), + + .FUNCTION_ID_WIDTH(FUNCTION_ID_WIDTH) + +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk_250mhz(pcie_user_clk), + .rst_250mhz(pcie_user_reset), + + /* + * PTP clock + */ + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + + /* + * GPIO + */ + .sw(0), + .led(), + .qsfp_led_act(qsfp_led_act), + //.qsfp_led_stat_g(qsfp_led_stat_g), + .qsfp_led_stat_y(qsfp_led_stat_y), + + /* + * I2C + */ + .i2c_scl_i(1'b1), + .i2c_scl_o(), + .i2c_scl_t(), + .i2c_sda_i(1'b1), + .i2c_sda_o(), + .i2c_sda_t(), + + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num_0(pcie_rq_seq_num0_reg), + .s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0_reg), + .s_axis_rq_seq_num_1(pcie_rq_seq_num1_reg), + .s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1_reg), + + .pcie_tfc_nph_av(pcie_tfc_nph_av), + .pcie_tfc_npd_av(pcie_tfc_npd_av), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_rcb_status(cfg_rcb_status), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msix_enable(cfg_interrupt_msix_enable), + .cfg_interrupt_msix_mask(cfg_interrupt_msix_mask), + .cfg_interrupt_msix_vf_enable(cfg_interrupt_msix_vf_enable), + .cfg_interrupt_msix_vf_mask(cfg_interrupt_msix_vf_mask), + .cfg_interrupt_msix_address(cfg_interrupt_msix_address), + .cfg_interrupt_msix_data(cfg_interrupt_msix_data), + .cfg_interrupt_msix_int(cfg_interrupt_msix_int), + .cfg_interrupt_msix_vec_pending(cfg_interrupt_msix_vec_pending), + .cfg_interrupt_msix_vec_pending_status(cfg_interrupt_msix_vec_pending_status), + .cfg_interrupt_msix_sent(cfg_interrupt_msix_sent), + .cfg_interrupt_msix_fail(cfg_interrupt_msix_fail), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor), + + /* + * Ethernet: QSFP28 + */ + .qsfp_tx_clk(qsfp_tx_clk), + .qsfp_tx_rst(qsfp_tx_rst), + .qsfp_tx_axis_tdata(qsfp_tx_axis_tdata), + .qsfp_tx_axis_tkeep(qsfp_tx_axis_tkeep), + .qsfp_tx_axis_tvalid(qsfp_tx_axis_tvalid), + .qsfp_tx_axis_tready(qsfp_tx_axis_tready), + .qsfp_tx_axis_tlast(qsfp_tx_axis_tlast), + .qsfp_tx_axis_tuser(qsfp_tx_axis_tuser), + .qsfp_tx_ptp_time(qsfp_tx_ptp_time), + .qsfp_tx_ptp_ts(qsfp_tx_ptp_ts), + .qsfp_tx_ptp_ts_tag(qsfp_tx_ptp_ts_tag), + .qsfp_tx_ptp_ts_valid(qsfp_tx_ptp_ts_valid), + + .qsfp_tx_enable(qsfp_tx_enable), + .qsfp_tx_lfc_en(qsfp_tx_lfc_en), + .qsfp_tx_lfc_req(qsfp_tx_lfc_req), + .qsfp_tx_pfc_en(qsfp_tx_pfc_en), + .qsfp_tx_pfc_req(qsfp_tx_pfc_req), + + .qsfp_rx_clk(qsfp_rx_clk), + .qsfp_rx_rst(qsfp_rx_rst), + .qsfp_rx_axis_tdata(qsfp_rx_axis_tdata), + .qsfp_rx_axis_tkeep(qsfp_rx_axis_tkeep), + .qsfp_rx_axis_tvalid(qsfp_rx_axis_tvalid), + .qsfp_rx_axis_tlast(qsfp_rx_axis_tlast), + .qsfp_rx_axis_tuser(qsfp_rx_axis_tuser), + .qsfp_rx_ptp_time(qsfp_rx_ptp_time), + + .qsfp_rx_enable(qsfp_rx_enable), + .qsfp_rx_status(qsfp_rx_status), + .qsfp_rx_lfc_en(qsfp_rx_lfc_en), + .qsfp_rx_lfc_req(qsfp_rx_lfc_req), + .qsfp_rx_lfc_ack(qsfp_rx_lfc_ack), + .qsfp_rx_pfc_en(qsfp_rx_pfc_en), + .qsfp_rx_pfc_req(qsfp_rx_pfc_req), + .qsfp_rx_pfc_ack(qsfp_rx_pfc_ack), + + .qsfp_drp_clk(qsfp_drp_clk), + .qsfp_drp_rst(qsfp_drp_rst), + .qsfp_drp_addr(qsfp_drp_addr), + .qsfp_drp_di(qsfp_drp_di), + .qsfp_drp_en(qsfp_drp_en), + .qsfp_drp_we(qsfp_drp_we), + .qsfp_drp_do(qsfp_drp_do), + .qsfp_drp_rdy(qsfp_drp_rdy), + + .qsfp_modprsl(1'b0), + .qsfp_modsell(), + .qsfp_resetl(), + .qsfp_intl(1'b1), + .qsfp_lpmode(), + + /* + * DDR + */ + .ddr_clk(0), + .ddr_rst(0), + + .m_axi_ddr_awid(), + .m_axi_ddr_awaddr(), + .m_axi_ddr_awlen(), + .m_axi_ddr_awsize(), + .m_axi_ddr_awburst(), + .m_axi_ddr_awlock(), + .m_axi_ddr_awcache(), + .m_axi_ddr_awprot(), + .m_axi_ddr_awqos(), + .m_axi_ddr_awvalid(), + .m_axi_ddr_awready(0), + .m_axi_ddr_wdata(), + .m_axi_ddr_wstrb(), + .m_axi_ddr_wlast(), + .m_axi_ddr_wvalid(), + .m_axi_ddr_wready(0), + .m_axi_ddr_bid(0), + .m_axi_ddr_bresp(0), + .m_axi_ddr_bvalid(0), + .m_axi_ddr_bready(), + .m_axi_ddr_arid(), + .m_axi_ddr_araddr(), + .m_axi_ddr_arlen(), + .m_axi_ddr_arsize(), + .m_axi_ddr_arburst(), + .m_axi_ddr_arlock(), + .m_axi_ddr_arcache(), + .m_axi_ddr_arprot(), + .m_axi_ddr_arqos(), + .m_axi_ddr_arvalid(), + .m_axi_ddr_arready(0), + .m_axi_ddr_rid(0), + .m_axi_ddr_rdata(0), + .m_axi_ddr_rresp(0), + .m_axi_ddr_rlast(0), + .m_axi_ddr_rvalid(0), + .m_axi_ddr_rready(), + + .ddr_status(0), + + /* + * HBM + */ + .hbm_clk(hbm_clk), + .hbm_rst(hbm_rst), + + .m_axi_hbm_awid(m_axi_hbm_awid), + .m_axi_hbm_awaddr(m_axi_hbm_awaddr), + .m_axi_hbm_awlen(m_axi_hbm_awlen), + .m_axi_hbm_awsize(m_axi_hbm_awsize), + .m_axi_hbm_awburst(m_axi_hbm_awburst), + .m_axi_hbm_awlock(m_axi_hbm_awlock), + .m_axi_hbm_awcache(m_axi_hbm_awcache), + .m_axi_hbm_awprot(m_axi_hbm_awprot), + .m_axi_hbm_awqos(m_axi_hbm_awqos), + .m_axi_hbm_awvalid(m_axi_hbm_awvalid), + .m_axi_hbm_awready(m_axi_hbm_awready), + .m_axi_hbm_wdata(m_axi_hbm_wdata), + .m_axi_hbm_wstrb(m_axi_hbm_wstrb), + .m_axi_hbm_wlast(m_axi_hbm_wlast), + .m_axi_hbm_wvalid(m_axi_hbm_wvalid), + .m_axi_hbm_wready(m_axi_hbm_wready), + .m_axi_hbm_bid(m_axi_hbm_bid), + .m_axi_hbm_bresp(m_axi_hbm_bresp), + .m_axi_hbm_bvalid(m_axi_hbm_bvalid), + .m_axi_hbm_bready(m_axi_hbm_bready), + .m_axi_hbm_arid(m_axi_hbm_arid), + .m_axi_hbm_araddr(m_axi_hbm_araddr), + .m_axi_hbm_arlen(m_axi_hbm_arlen), + .m_axi_hbm_arsize(m_axi_hbm_arsize), + .m_axi_hbm_arburst(m_axi_hbm_arburst), + .m_axi_hbm_arlock(m_axi_hbm_arlock), + .m_axi_hbm_arcache(m_axi_hbm_arcache), + .m_axi_hbm_arprot(m_axi_hbm_arprot), + .m_axi_hbm_arqos(m_axi_hbm_arqos), + .m_axi_hbm_arvalid(m_axi_hbm_arvalid), + .m_axi_hbm_arready(m_axi_hbm_arready), + .m_axi_hbm_rid(m_axi_hbm_rid), + .m_axi_hbm_rdata(m_axi_hbm_rdata), + .m_axi_hbm_rresp(m_axi_hbm_rresp), + .m_axi_hbm_rlast(m_axi_hbm_rlast), + .m_axi_hbm_rvalid(m_axi_hbm_rvalid), + .m_axi_hbm_rready(m_axi_hbm_rready), + + .hbm_status(hbm_status), + + /* + * QSPI flash + */ + .fpga_boot(fpga_boot), + .qspi_clk(qspi_clk_int), + .qspi_dq_i(qspi_dq_i_int), + .qspi_dq_o(qspi_dq_o_int), + .qspi_dq_oe(qspi_dq_oe_int), + .qspi_cs(qspi_cs_int), + + /* + * AXI-Lite interface to CMS + */ + .m_axil_cms_clk(axil_cms_clk), + .m_axil_cms_rst(axil_cms_rst), + .m_axil_cms_awaddr(axil_cms_awaddr), + .m_axil_cms_awprot(axil_cms_awprot), + .m_axil_cms_awvalid(axil_cms_awvalid), + .m_axil_cms_awready(axil_cms_awready), + .m_axil_cms_wdata(axil_cms_wdata), + .m_axil_cms_wstrb(axil_cms_wstrb), + .m_axil_cms_wvalid(axil_cms_wvalid), + .m_axil_cms_wready(axil_cms_wready), + .m_axil_cms_bresp(axil_cms_bresp), + .m_axil_cms_bvalid(axil_cms_bvalid), + .m_axil_cms_bready(axil_cms_bready), + .m_axil_cms_araddr(axil_cms_araddr), + .m_axil_cms_arprot(axil_cms_arprot), + .m_axil_cms_arvalid(axil_cms_arvalid), + .m_axil_cms_arready(axil_cms_arready), + .m_axil_cms_rdata(axil_cms_rdata), + .m_axil_cms_rresp(axil_cms_rresp), + .m_axil_cms_rvalid(axil_cms_rvalid), + .m_axil_cms_rready(axil_cms_rready) +); + +endmodule + +`resetall diff --git a/lib/mqnic/mqnic.h b/lib/mqnic/mqnic.h index eb029bd..03a63f7 100644 --- a/lib/mqnic/mqnic.h +++ b/lib/mqnic/mqnic.h @@ -84,6 +84,8 @@ struct mqnic_if { uint32_t if_features; + uint32_t mac; + uint32_t max_tx_mtu; uint32_t max_rx_mtu; uint32_t tx_fifo_depth; diff --git a/lib/mqnic/mqnic_if.c b/lib/mqnic/mqnic_if.c index 61b3121..58e387e 100644 --- a/lib/mqnic/mqnic_if.c +++ b/lib/mqnic/mqnic_if.c @@ -56,6 +56,8 @@ struct mqnic_if *mqnic_if_open(struct mqnic *dev, int index, volatile uint8_t *r interface->tx_fifo_depth = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_TX_FIFO_DEPTH); interface->rx_fifo_depth = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_RX_FIFO_DEPTH); + interface->mac = mqnic_reg_read32(interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_MAC); + interface->eq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_EQM_TYPE, MQNIC_RB_EQM_VER, 0); if (!interface->eq_rb) @@ -65,7 +67,7 @@ struct mqnic_if *mqnic_if_open(struct mqnic *dev, int index, volatile uint8_t *r } offset = mqnic_reg_read32(interface->eq_rb->regs, MQNIC_RB_EQM_REG_OFFSET); - count = mqnic_reg_read32(interface->eq_rb->regs, MQNIC_RB_EQM_REG_COUNT); + count = mqnic_reg_read32(interface->eq_rb->regs, MQNIC_RB_EQM_REG_COUNT)/256; stride = mqnic_reg_read32(interface->eq_rb->regs, MQNIC_RB_EQM_REG_STRIDE); if (count > MQNIC_MAX_EQ) @@ -85,7 +87,7 @@ struct mqnic_if *mqnic_if_open(struct mqnic *dev, int index, volatile uint8_t *r } offset = mqnic_reg_read32(interface->cq_rb->regs, MQNIC_RB_CQM_REG_OFFSET); - count = mqnic_reg_read32(interface->cq_rb->regs, MQNIC_RB_CQM_REG_COUNT); + count = mqnic_reg_read32(interface->cq_rb->regs, MQNIC_RB_CQM_REG_COUNT)/256; stride = mqnic_reg_read32(interface->cq_rb->regs, MQNIC_RB_CQM_REG_STRIDE); if (count > MQNIC_MAX_CQ) @@ -105,7 +107,7 @@ struct mqnic_if *mqnic_if_open(struct mqnic *dev, int index, volatile uint8_t *r } offset = mqnic_reg_read32(interface->txq_rb->regs, MQNIC_RB_TX_QM_REG_OFFSET); - count = mqnic_reg_read32(interface->txq_rb->regs, MQNIC_RB_TX_QM_REG_COUNT); + count = mqnic_reg_read32(interface->txq_rb->regs, MQNIC_RB_TX_QM_REG_COUNT)/256; stride = mqnic_reg_read32(interface->txq_rb->regs, MQNIC_RB_TX_QM_REG_STRIDE); if (count > MQNIC_MAX_TXQ) @@ -125,7 +127,7 @@ struct mqnic_if *mqnic_if_open(struct mqnic *dev, int index, volatile uint8_t *r } offset = mqnic_reg_read32(interface->rxq_rb->regs, MQNIC_RB_RX_QM_REG_OFFSET); - count = mqnic_reg_read32(interface->rxq_rb->regs, MQNIC_RB_RX_QM_REG_COUNT); + count = mqnic_reg_read32(interface->rxq_rb->regs, MQNIC_RB_RX_QM_REG_COUNT)/256; stride = mqnic_reg_read32(interface->rxq_rb->regs, MQNIC_RB_RX_QM_REG_STRIDE); if (count > MQNIC_MAX_RXQ) diff --git a/modules/mqnic/mqnic_dev.c b/modules/mqnic/mqnic_dev.c index 331772a..58bfab8 100644 --- a/modules/mqnic/mqnic_dev.c +++ b/modules/mqnic/mqnic_dev.c @@ -7,6 +7,7 @@ #include "mqnic_ioctl.h" #include +#include static int mqnic_open(struct inode *inode, struct file *file) { @@ -134,15 +135,23 @@ static long mqnic_ioctl(struct file *file, unsigned int cmd, unsigned long arg) info.child = 0; info.size = mqnic->hw_regs_size; info.offset = ((u64)info.index) << 40; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,0,0) + strscpy(info.name, "ctrl", sizeof(info.name)); +#else strlcpy(info.name, "ctrl", sizeof(info.name)); - break; +#endif + break; case 1: info.type = MQNIC_REGION_TYPE_APP_CTRL; info.next = 2; info.child = 0; info.size = mqnic->app_hw_regs_size; info.offset = ((u64)info.index) << 40; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,0,0) + strscpy(info.name, "app", sizeof(info.name)); +#else strlcpy(info.name, "app", sizeof(info.name)); +#endif break; case 2: info.type = MQNIC_REGION_TYPE_RAM; @@ -150,7 +159,11 @@ static long mqnic_ioctl(struct file *file, unsigned int cmd, unsigned long arg) info.child = 0; info.size = mqnic->ram_hw_regs_size; info.offset = ((u64)info.index) << 40; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,0,0) + strscpy(info.name, "ram", sizeof(info.name)); +#else strlcpy(info.name, "ram", sizeof(info.name)); +#endif break; default: return -EINVAL; diff --git a/modules/mqnic/mqnic_eq.c b/modules/mqnic/mqnic_eq.c index bdd4366..c3b2b81 100644 --- a/modules/mqnic/mqnic_eq.c +++ b/modules/mqnic/mqnic_eq.c @@ -219,15 +219,20 @@ void mqnic_process_eq(struct mqnic_eq *eq) dma_rmb(); + //u32 cpl_count = mqnic_res_get_count(interface->cq_res); + if (event->type == MQNIC_EVENT_TYPE_CPL) { // completion event rcu_read_lock(); - cq = radix_tree_lookup(&eq->cq_table, le16_to_cpu(event->source)); + // cq = radix_tree_lookup(&eq->cq_table, (le16_to_cpu(event->source) % cpl_count) ); + cq = radix_tree_lookup(&eq->cq_table, (le16_to_cpu(event->source))); rcu_read_unlock(); if (likely(cq)) { - if (likely(cq->handler)) - cq->handler(cq); + if (likely(cq->handler)){ + dev_info(eq->dev, "%s: event source: %d", __func__, le16_to_cpu(event->source)); + cq->handler(cq); + } } else { dev_err(eq->dev, "%s on IF %d EQ %d: unknown event source %d (index %d, type %d)", __func__, interface->index, eq->eqn, le16_to_cpu(event->source), diff --git a/modules/mqnic/mqnic_ethtool.c b/modules/mqnic/mqnic_ethtool.c index d5b7c26..1940fcd 100644 --- a/modules/mqnic/mqnic_ethtool.c +++ b/modules/mqnic/mqnic_ethtool.c @@ -242,6 +242,24 @@ static int mqnic_set_rxfh(struct net_device *ndev, const u32 *indir, return mqnic_update_indir_table(ndev); } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) +static int mqnic_get_rxfh_new(struct net_device *ndev, struct ethtool_rxfh_param *param) +{ + u8 hfunc = 0; + int ret = mqnic_get_rxfh(ndev, param->indir, param->key, &hfunc); + if (ret) + return ret; + param->hfunc = hfunc; + return 0; +} + +static int mqnic_set_rxfh_new(struct net_device *ndev, struct ethtool_rxfh_param *param, struct netlink_ext_ack *extack) +{ + return mqnic_set_rxfh(ndev, param->indir, param->key, param->hfunc); +} +#endif + static void mqnic_get_channels(struct net_device *ndev, struct ethtool_channels *channel) { @@ -304,9 +322,14 @@ static int mqnic_set_channels(struct net_device *ndev, return ret; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0) +static int mqnic_get_ts_info(struct net_device *ndev, + struct kernel_ethtool_ts_info *info) +#else static int mqnic_get_ts_info(struct net_device *ndev, struct ethtool_ts_info *info) +#endif { struct mqnic_priv *priv = netdev_priv(ndev); struct mqnic_dev *mdev = priv->mdev; @@ -611,10 +634,17 @@ const struct ethtool_ops mqnic_ethtool_ops = { .get_pauseparam = mqnic_get_pauseparam, .set_pauseparam = mqnic_set_pauseparam, .get_rxnfc = mqnic_get_rxnfc, + .get_rxfh_indir_size = mqnic_get_rxfh_indir_size, - .get_rxfh = mqnic_get_rxfh, + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0) + .get_rxfh = mqnic_get_rxfh_new, + .set_rxfh = mqnic_set_rxfh_new, +#else + .get_rxfh = mqnic_get_rxfh, .set_rxfh = mqnic_set_rxfh, - .get_channels = mqnic_get_channels, +#endif + .get_channels = mqnic_get_channels, .set_channels = mqnic_set_channels, .get_ts_info = mqnic_get_ts_info, .get_module_info = mqnic_get_module_info, diff --git a/modules/mqnic/mqnic_hw.h b/modules/mqnic/mqnic_hw.h index 79c7bf0..609137d 100644 --- a/modules/mqnic/mqnic_hw.h +++ b/modules/mqnic/mqnic_hw.h @@ -189,6 +189,7 @@ #define MQNIC_RB_IF_CTRL_REG_FEATURES 0x0C #define MQNIC_RB_IF_CTRL_REG_PORT_COUNT 0x10 #define MQNIC_RB_IF_CTRL_REG_SCHED_COUNT 0x14 +#define MQNIC_RB_IF_CTRL_REG_MAC 0x18 #define MQNIC_RB_IF_CTRL_REG_MAX_TX_MTU 0x20 #define MQNIC_RB_IF_CTRL_REG_MAX_RX_MTU 0x24 #define MQNIC_RB_IF_CTRL_REG_TX_MTU 0x28 diff --git a/modules/mqnic/mqnic_if.c b/modules/mqnic/mqnic_if.c index d7e2d91..aebeaee 100644 --- a/modules/mqnic/mqnic_if.c +++ b/modules/mqnic/mqnic_if.c @@ -73,7 +73,7 @@ struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __ } offset = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_OFFSET); - count = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_COUNT); + count = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_COUNT)/256; stride = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_STRIDE); dev_info(dev, "EQ offset: 0x%08x", offset); @@ -98,7 +98,7 @@ struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __ } offset = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_OFFSET); - count = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_COUNT); + count = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_COUNT)/256; stride = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_STRIDE); count = min_t(u32, count, MQNIC_MAX_CQ); @@ -123,7 +123,7 @@ struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __ } offset = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_OFFSET); - count = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_COUNT); + count = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_COUNT)/256; stride = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_STRIDE); count = min_t(u32, count, MQNIC_MAX_TXQ); @@ -149,7 +149,7 @@ struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __ } offset = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_OFFSET); - count = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_COUNT); + count = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_COUNT)/256; stride = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_STRIDE); count = min_t(u32, count, MQNIC_MAX_RXQ); diff --git a/modules/mqnic/mqnic_irq.c b/modules/mqnic/mqnic_irq.c index 456d461..bdbd9fe 100644 --- a/modules/mqnic/mqnic_irq.c +++ b/modules/mqnic/mqnic_irq.c @@ -50,6 +50,7 @@ int mqnic_irq_init_pcie(struct mqnic_dev *mdev) } irq->index = k; + dev_info(dev, "IRQ Index %d", k); irq->irqn = pci_irq_vector(pdev, k); mdev->irq[k] = irq; } diff --git a/modules/mqnic/mqnic_main.c b/modules/mqnic/mqnic_main.c index 64efba9..c0c49d2 100644 --- a/modules/mqnic/mqnic_main.c +++ b/modules/mqnic/mqnic_main.c @@ -686,7 +686,7 @@ static int mqnic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent // error handling fail_sriov: - //pci_disable_sriov(pdev); + pci_disable_sriov(pdev); fail_common: pci_clear_master(pdev); mqnic_irq_deinit_pcie(mqnic); @@ -726,7 +726,7 @@ static void mqnic_pci_remove(struct pci_dev *pdev) if (mqnic->ram_hw_addr) pci_iounmap(pdev, mqnic->ram_hw_addr); pci_release_regions(pdev); - //pci_disable_sriov(pdev); + pci_disable_sriov(pdev); pci_disable_device(pdev); mqnic_free_id(mqnic); mqnic_devlink_free(devlink); @@ -860,7 +860,11 @@ static int mqnic_platform_probe(struct platform_device *pdev) return ret; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0) +static void mqnic_platform_remove(struct platform_device *pdev) +#else static int mqnic_platform_remove(struct platform_device *pdev) +#endif { struct mqnic_dev *mqnic = platform_get_drvdata(pdev); struct devlink *devlink = priv_to_devlink(mqnic); @@ -871,7 +875,11 @@ static int mqnic_platform_remove(struct platform_device *pdev) mqnic_free_id(mqnic); mqnic_devlink_free(devlink); - return 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0) + return; +#else + return 0; +#endif } static struct platform_driver mqnic_platform_driver = { diff --git a/modules/mqnic/mqnic_netdev.c b/modules/mqnic/mqnic_netdev.c index 853b0f8..f49c993 100644 --- a/modules/mqnic/mqnic_netdev.c +++ b/modules/mqnic/mqnic_netdev.c @@ -574,6 +574,8 @@ struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, priv->txq_count = min_t(u32, mqnic_res_get_count(interface->txq_res), 256); priv->rxq_count = min_t(u32, mqnic_res_get_count(interface->rxq_res), num_online_cpus()); + dev_info(dev, "%d vs %d\n", priv->txq_count, priv->rxq_count); + priv->tx_ring_size = roundup_pow_of_two(clamp_t(u32, mqnic_num_txq_entries, MQNIC_MIN_TX_RING_SZ, MQNIC_MAX_TX_RING_SZ)); priv->rx_ring_size = roundup_pow_of_two(clamp_t(u32, mqnic_num_rxq_entries, diff --git a/modules/mqnic_vf/.gitignore b/modules/mqnic_vf/.gitignore new file mode 120000 index 0000000..7a1925d --- /dev/null +++ b/modules/mqnic_vf/.gitignore @@ -0,0 +1 @@ +../mqnic/.gitignore \ No newline at end of file diff --git a/modules/mqnic_vf/Makefile b/modules/mqnic_vf/Makefile new file mode 120000 index 0000000..d07fcae --- /dev/null +++ b/modules/mqnic_vf/Makefile @@ -0,0 +1 @@ +../mqnic/Makefile \ No newline at end of file diff --git a/modules/mqnic_vf/device-tree-binding.txt b/modules/mqnic_vf/device-tree-binding.txt new file mode 120000 index 0000000..b570624 --- /dev/null +++ b/modules/mqnic_vf/device-tree-binding.txt @@ -0,0 +1 @@ +../mqnic/device-tree-binding.txt \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic.h b/modules/mqnic_vf/mqnic.h new file mode 100644 index 0000000..e6fecc9 --- /dev/null +++ b/modules/mqnic_vf/mqnic.h @@ -0,0 +1,648 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#ifndef MQNIC_H +#define MQNIC_H + +#include +#ifdef CONFIG_PCI +#include +#endif +#ifdef CONFIG_AUXILIARY_BUS +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DRIVER_NAME "mqnic" +#define DRIVER_VERSION "0.1" + +#include "mqnic_hw.h" + +#ifdef CONFIG_OF +/* platform driver OF-related definitions */ +#define MQNIC_PROP_MAC_ADDR_INC_BYTE "mac-address-increment-byte" +#define MQNIC_PROP_MAC_ADDR_INC "mac-address-increment" +#define MQNIC_PROP_MAC_ADDR_LOCAL "mac-address-local" +#define MQNIC_PROP_MODULE_EEPROM "module-eeproms" +#endif + +// default interval to poll port TX/RX status, in ms +#define MQNIC_LINK_STATUS_POLL_MS 1000 + +// Scott + +#define MY_MAC 0 + +extern unsigned int mqnic_num_eq_entries; +extern unsigned int mqnic_num_txq_entries; +extern unsigned int mqnic_num_rxq_entries; + +extern unsigned int mqnic_link_status_poll; + +struct mqnic_dev; +struct mqnic_if; + +struct mqnic_res { + unsigned int count; + u8 __iomem *base; + unsigned int stride; + + spinlock_t lock; + unsigned long *bmap; +}; + +struct mqnic_reg_block { + u32 type; + u32 version; + u8 __iomem *regs; + u8 __iomem *base; +}; + +struct mqnic_board_ops { + int (*init)(struct mqnic_dev *mqnic); + void (*deinit)(struct mqnic_dev *mqnic); +}; + +struct mqnic_i2c_bus { + struct mqnic_dev *mqnic; + + u8 __iomem *scl_in_reg; + u8 __iomem *scl_out_reg; + u8 __iomem *sda_in_reg; + u8 __iomem *sda_out_reg; + + u32 scl_in_mask; + u32 scl_out_mask; + u32 sda_in_mask; + u32 sda_out_mask; + + struct list_head head; + + struct i2c_algo_bit_data algo; + struct i2c_adapter adapter; +}; + +struct mqnic_irq { + int index; + int irqn; + char name[16 + 3]; + struct atomic_notifier_head nh; +}; + +#ifdef CONFIG_AUXILIARY_BUS +struct mqnic_adev { + struct auxiliary_device adev; + struct mqnic_dev *mdev; + struct mqnic_adev **ptr; + char name[32]; +}; +#endif + +struct mqnic_dev { + struct device *dev; +#ifdef CONFIG_PCI + struct pci_dev *pdev; +#endif + struct platform_device *pfdev; + + resource_size_t hw_regs_size; + phys_addr_t hw_regs_phys; + u8 __iomem *hw_addr; + u8 __iomem *phc_hw_addr; + + resource_size_t app_hw_regs_size; + phys_addr_t app_hw_regs_phys; + u8 __iomem *app_hw_addr; + + resource_size_t ram_hw_regs_size; + phys_addr_t ram_hw_regs_phys; + u8 __iomem *ram_hw_addr; + + struct mutex state_lock; + + int mac_count; + u8 mac_list[MQNIC_MAX_IF][ETH_ALEN]; + + char name[16]; + + int irq_count; + struct mqnic_irq *irq[MQNIC_MAX_IRQ]; + + unsigned int id; + struct list_head dev_list_node; + + struct miscdevice misc_dev; + +#ifdef CONFIG_AUXILIARY_BUS + struct mqnic_adev *app_adev; +#endif + + struct mqnic_reg_block *rb_list; + struct mqnic_reg_block *fw_id_rb; + struct mqnic_reg_block *if_rb; + struct mqnic_reg_block *stats_rb; + struct mqnic_reg_block *clk_info_rb; + struct mqnic_reg_block *phc_rb; + + int phys_port_max; + + u32 fpga_id; + u32 fw_id; + u32 fw_ver; + u32 board_id; + u32 board_ver; + u32 build_date; + u32 git_hash; + u32 rel_info; + u32 num_funcs; + u32 max_irq_per_func; + + u32 app_id; + + u32 stats_offset; + u32 stats_count; + u32 stats_stride; + u32 stats_flags; + + u32 core_clk_nom_per_ns_num; + u32 core_clk_nom_per_ns_denom; + u32 core_clk_nom_freq_hz; + u32 ref_clk_nom_per_ns_num; + u32 ref_clk_nom_per_ns_denom; + u32 ref_clk_nom_freq_hz; + u32 clk_info_channels; + + u32 if_offset; + u32 if_count; + u32 if_stride; + u32 if_csr_offset; + + char build_date_str[32]; + + struct mqnic_if *interface[MQNIC_MAX_IF]; + + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_clock_info; + + struct mqnic_board_ops *board_ops; + + struct list_head i2c_bus; + int i2c_adapter_count; + + int mod_i2c_client_count; + struct i2c_client *mod_i2c_client[MQNIC_MAX_IF]; + struct i2c_client *eeprom_i2c_client; +}; + +struct mqnic_frag { + dma_addr_t dma_addr; + u32 len; +}; + +struct mqnic_tx_info { + struct sk_buff *skb; + DEFINE_DMA_UNMAP_ADDR(dma_addr); + DEFINE_DMA_UNMAP_LEN(len); + u32 frag_count; + struct mqnic_frag frags[MQNIC_MAX_FRAGS - 1]; + int ts_requested; +}; + +struct mqnic_rx_info { + struct page *page; + u32 page_order; + u32 page_offset; + dma_addr_t dma_addr; + u32 len; +}; + +struct mqnic_ring { + // written on enqueue (i.e. start_xmit) + u32 prod_ptr; + u64 bytes; + u64 packets; + u64 dropped_packets; + struct netdev_queue *tx_queue; + + // written from completion + u32 cons_ptr ____cacheline_aligned_in_smp; + u64 ts_s; + u8 ts_valid; + + // mostly constant + u32 size; + u32 full_size; + u32 size_mask; + u32 stride; + + u32 cpl_index; + + u32 mtu; + u32 page_order; + + u32 desc_block_size; + u32 log_desc_block_size; + + size_t buf_size; + u8 *buf; + dma_addr_t buf_dma_addr; + + union { + struct mqnic_tx_info *tx_info; + struct mqnic_rx_info *rx_info; + }; + + struct device *dev; + struct mqnic_if *interface; + struct mqnic_priv *priv; + int index; + struct mqnic_cq *cq; + int enabled; + + u8 __iomem *hw_addr; +} ____cacheline_aligned_in_smp; + +struct mqnic_cq { + u32 prod_ptr; + + u32 cons_ptr; + + u32 size; + u32 size_mask; + u32 stride; + + size_t buf_size; + u8 *buf; + dma_addr_t buf_dma_addr; + + struct device *dev; + struct mqnic_if *interface; + struct napi_struct napi; + int cqn; + struct mqnic_eq *eq; + struct mqnic_ring *src_ring; + int enabled; + + void (*handler)(struct mqnic_cq *cq); + + u8 __iomem *hw_addr; +}; + +struct mqnic_eq { + u32 prod_ptr; + + u32 cons_ptr; + + u32 size; + u32 size_mask; + u32 stride; + + size_t buf_size; + u8 *buf; + dma_addr_t buf_dma_addr; + + struct device *dev; + struct mqnic_if *interface; + int eqn; + struct mqnic_irq *irq; + int enabled; + + struct notifier_block irq_nb; + + void (*handler)(struct mqnic_eq *eq); + + spinlock_t table_lock; + struct radix_tree_root cq_table; + + u8 __iomem *hw_addr; +}; + +struct mqnic_sched { + struct device *dev; + struct mqnic_if *interface; + struct mqnic_sched_block *sched_block; + + struct mqnic_reg_block *rb; + + int index; + + u32 type; + u32 offset; + u32 channel_count; + u32 channel_stride; + + u8 __iomem *hw_addr; +}; + +struct mqnic_port { + struct device *dev; + struct mqnic_if *interface; + + struct mqnic_reg_block *port_rb; + struct mqnic_reg_block *rb_list; + struct mqnic_reg_block *port_ctrl_rb; + + int index; + int phys_index; + + u32 port_features; + + struct devlink_port dl_port; +}; + +struct mqnic_sched_block { + struct device *dev; + struct mqnic_if *interface; + + struct mqnic_reg_block *block_rb; + struct mqnic_reg_block *rb_list; + + int index; + + u32 sched_count; + struct mqnic_sched *sched[MQNIC_MAX_PORTS]; +}; + +struct mqnic_if { + struct device *dev; + struct mqnic_dev *mdev; + + struct mqnic_reg_block *rb_list; + struct mqnic_reg_block *if_ctrl_rb; + struct mqnic_reg_block *eq_rb; + struct mqnic_reg_block *cq_rb; + struct mqnic_reg_block *txq_rb; + struct mqnic_reg_block *rxq_rb; + struct mqnic_reg_block *rx_queue_map_rb; + + int index; + + u32 if_features; + + u32 max_tx_mtu; + u32 max_rx_mtu; + u32 tx_fifo_depth; + u32 rx_fifo_depth; + + u32 mac; + + struct mqnic_res *eq_res; + struct mqnic_res *cq_res; + struct mqnic_res *txq_res; + struct mqnic_res *rxq_res; + + u32 eq_count; + struct mqnic_eq *eq[MQNIC_MAX_EQ]; + + u32 port_count; + struct mqnic_port *port[MQNIC_MAX_PORTS]; + + u32 sched_block_count; + struct mqnic_sched_block *sched_block[MQNIC_MAX_PORTS]; + + u32 max_desc_block_size; + + u32 rx_queue_map_indir_table_size; + u8 __iomem *rx_queue_map_indir_table[MQNIC_MAX_PORTS]; + + resource_size_t hw_regs_size; + u8 __iomem *hw_addr; + u8 __iomem *csr_hw_addr; + + u32 ndev_count; + struct net_device *ndev[MQNIC_MAX_PORTS]; + + struct i2c_client *mod_i2c_client; +}; + +struct mqnic_priv { + struct device *dev; + struct net_device *ndev; + struct devlink_port *dl_port; + struct mqnic_dev *mdev; + struct mqnic_if *interface; + + spinlock_t stats_lock; + + int index; + bool registered; + bool port_up; + + u32 if_features; + + unsigned int link_status; + struct timer_list link_status_timer; + + u32 txq_count; + u32 rxq_count; + + u32 tx_ring_size; + u32 rx_ring_size; + + struct rw_semaphore txq_table_sem; + struct radix_tree_root txq_table; + + struct rw_semaphore rxq_table_sem; + struct radix_tree_root rxq_table; + + struct mqnic_sched_block *sched_block; + struct mqnic_port *port; + + u32 max_desc_block_size; + + u32 rx_queue_map_indir_table_size; + u32 *rx_queue_map_indir_table; + + struct hwtstamp_config hwts_config; + + struct i2c_client *mod_i2c_client; +}; + +// mqnic_main.c + +// mqnic_devlink.c +struct devlink *mqnic_devlink_alloc(struct device *dev); +void mqnic_devlink_free(struct devlink *devlink); + +// mqnic_res.c +struct mqnic_res *mqnic_create_res(unsigned int count, u8 __iomem *base, unsigned int stride); +void mqnic_destroy_res(struct mqnic_res *res); +int mqnic_res_alloc(struct mqnic_res *res); +void mqnic_res_free(struct mqnic_res *res, int index); +unsigned int mqnic_res_get_count(struct mqnic_res *res); +u8 __iomem *mqnic_res_get_addr(struct mqnic_res *res, int index); + +// mqnic_reg_block.c +struct mqnic_reg_block *mqnic_enumerate_reg_block_list(u8 __iomem *base, size_t offset, size_t size); +struct mqnic_reg_block *mqnic_find_reg_block(struct mqnic_reg_block *list, u32 type, u32 version, int index); +void mqnic_free_reg_block_list(struct mqnic_reg_block *list); + +// mqnic_irq.c +int mqnic_irq_init_pcie(struct mqnic_dev *mdev); +void mqnic_irq_deinit_pcie(struct mqnic_dev *mdev); +int mqnic_irq_init_platform(struct mqnic_dev *mdev); + +// mqnic_dev.c +extern const struct file_operations mqnic_fops; + +// mqnic_if.c +struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __iomem *hw_addr); +void mqnic_destroy_interface(struct mqnic_if *interface); +u32 mqnic_interface_get_tx_mtu(struct mqnic_if *interface); +void mqnic_interface_set_tx_mtu(struct mqnic_if *interface, u32 mtu); +u32 mqnic_interface_get_rx_mtu(struct mqnic_if *interface); +void mqnic_interface_set_rx_mtu(struct mqnic_if *interface, u32 mtu); +u32 mqnic_interface_get_rx_queue_map_rss_mask(struct mqnic_if *interface, int port); +void mqnic_interface_set_rx_queue_map_rss_mask(struct mqnic_if *interface, int port, u32 val); +u32 mqnic_interface_get_rx_queue_map_app_mask(struct mqnic_if *interface, int port); +void mqnic_interface_set_rx_queue_map_app_mask(struct mqnic_if *interface, int port, u32 val); +u32 mqnic_interface_get_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index); +void mqnic_interface_set_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index, u32 val); + +// mqnic_port.c +struct mqnic_port *mqnic_create_port(struct mqnic_if *interface, int index, + int phys_index, struct mqnic_reg_block *port_rb); +void mqnic_destroy_port(struct mqnic_port *port); +u32 mqnic_port_get_tx_ctrl(struct mqnic_port *port); +void mqnic_port_set_tx_ctrl(struct mqnic_port *port, u32 val); +u32 mqnic_port_get_rx_ctrl(struct mqnic_port *port); +void mqnic_port_set_rx_ctrl(struct mqnic_port *port, u32 val); +u32 mqnic_port_get_fc_ctrl(struct mqnic_port *port); +void mqnic_port_set_fc_ctrl(struct mqnic_port *port, u32 val); +u32 mqnic_port_get_lfc_ctrl(struct mqnic_port *port); +void mqnic_port_set_lfc_ctrl(struct mqnic_port *port, u32 val); +u32 mqnic_port_get_pfc_ctrl(struct mqnic_port *port, int index); +void mqnic_port_set_pfc_ctrl(struct mqnic_port *port, int index, u32 val); + +// mqnic_netdev.c +int mqnic_start_port(struct net_device *ndev); +void mqnic_stop_port(struct net_device *ndev); +int mqnic_update_indir_table(struct net_device *ndev); +void mqnic_update_stats(struct net_device *ndev); +struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, + struct mqnic_port *port, struct mqnic_sched_block *sched_block); +void mqnic_destroy_netdev(struct net_device *ndev); + +// mqnic_sched_block.c +struct mqnic_sched_block *mqnic_create_sched_block(struct mqnic_if *interface, + int index, struct mqnic_reg_block *rb); +void mqnic_destroy_sched_block(struct mqnic_sched_block *block); +int mqnic_activate_sched_block(struct mqnic_sched_block *block); +void mqnic_deactivate_sched_block(struct mqnic_sched_block *block); + +// mqnic_scheduler.c +struct mqnic_sched *mqnic_create_scheduler(struct mqnic_sched_block *block, + int index, struct mqnic_reg_block *rb); +void mqnic_destroy_scheduler(struct mqnic_sched *sched); +int mqnic_scheduler_enable(struct mqnic_sched *sched); +void mqnic_scheduler_disable(struct mqnic_sched *sched); + +// mqnic_ptp.c +void mqnic_register_phc(struct mqnic_dev *mdev); +void mqnic_unregister_phc(struct mqnic_dev *mdev); +ktime_t mqnic_read_cpl_ts(struct mqnic_dev *mdev, struct mqnic_ring *ring, + const struct mqnic_cpl *cpl); + +// mqnic_i2c.c +struct mqnic_i2c_bus *mqnic_i2c_bus_create(struct mqnic_dev *mqnic, int index); +struct i2c_adapter *mqnic_i2c_adapter_create(struct mqnic_dev *mqnic, int index); +void mqnic_i2c_bus_release(struct mqnic_i2c_bus *bus); +void mqnic_i2c_adapter_release(struct i2c_adapter *adapter); +int mqnic_i2c_init(struct mqnic_dev *mqnic); +void mqnic_i2c_deinit(struct mqnic_dev *mqnic); + +// mqnic_board.c +int mqnic_board_init(struct mqnic_dev *mqnic); +void mqnic_board_deinit(struct mqnic_dev *mqnic); + +// mqnic_clk_info.c +void mqnic_clk_info_init(struct mqnic_dev *mdev); +u32 mqnic_get_core_clk_nom_freq_hz(struct mqnic_dev *mdev); +u32 mqnic_get_ref_clk_nom_freq_hz(struct mqnic_dev *mdev); +u32 mqnic_get_core_clk_freq_hz(struct mqnic_dev *mdev); +u32 mqnic_get_clk_freq_hz(struct mqnic_dev *mdev, int ch); +u64 mqnic_core_clk_cycles_to_ns(struct mqnic_dev *mdev, u64 cycles); +u64 mqnic_core_clk_ns_to_cycles(struct mqnic_dev *mdev, u64 ns); +u64 mqnic_ref_clk_cycles_to_ns(struct mqnic_dev *mdev, u64 cycles); +u64 mqnic_ref_clk_ns_to_cycles(struct mqnic_dev *mdev, u64 ns); + +// mqnic_stats.c +void mqnic_stats_init(struct mqnic_dev *mdev); +u64 mqnic_stats_read(struct mqnic_dev *mdev, int index); + +// mqnic_eq.c +struct mqnic_eq *mqnic_create_eq(struct mqnic_if *interface); +void mqnic_destroy_eq(struct mqnic_eq *eq); +int mqnic_open_eq(struct mqnic_eq *eq, struct mqnic_irq *irq, int size); +void mqnic_close_eq(struct mqnic_eq *eq); +int mqnic_eq_attach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq); +void mqnic_eq_detach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq); +void mqnic_eq_read_prod_ptr(struct mqnic_eq *eq); +void mqnic_eq_write_cons_ptr(struct mqnic_eq *eq); +void mqnic_arm_eq(struct mqnic_eq *eq); +void mqnic_process_eq(struct mqnic_eq *eq); + +// mqnic_cq.c +struct mqnic_cq *mqnic_create_cq(struct mqnic_if *interface); +void mqnic_destroy_cq(struct mqnic_cq *cq); +int mqnic_open_cq(struct mqnic_cq *cq, struct mqnic_eq *eq, int size); +void mqnic_close_cq(struct mqnic_cq *cq); +void mqnic_cq_read_prod_ptr(struct mqnic_cq *cq); +void mqnic_cq_write_cons_ptr(struct mqnic_cq *cq); +void mqnic_arm_cq(struct mqnic_cq *cq); + +// mqnic_tx.c +struct mqnic_ring *mqnic_create_tx_ring(struct mqnic_if *interface); +void mqnic_destroy_tx_ring(struct mqnic_ring *ring); +int mqnic_open_tx_ring(struct mqnic_ring *ring, struct mqnic_priv *priv, + struct mqnic_cq *cq, int size, int desc_block_size); +void mqnic_close_tx_ring(struct mqnic_ring *ring); +int mqnic_enable_tx_ring(struct mqnic_ring *ring); +void mqnic_disable_tx_ring(struct mqnic_ring *ring); +bool mqnic_is_tx_ring_empty(const struct mqnic_ring *ring); +bool mqnic_is_tx_ring_full(const struct mqnic_ring *ring); +void mqnic_tx_read_cons_ptr(struct mqnic_ring *ring); +void mqnic_tx_write_prod_ptr(struct mqnic_ring *ring); +void mqnic_free_tx_desc(struct mqnic_ring *ring, int index, int napi_budget); +int mqnic_free_tx_buf(struct mqnic_ring *ring); +int mqnic_process_tx_cq(struct mqnic_cq *cq, int napi_budget); +void mqnic_tx_irq(struct mqnic_cq *cq); +int mqnic_poll_tx_cq(struct napi_struct *napi, int budget); +netdev_tx_t mqnic_start_xmit(struct sk_buff *skb, struct net_device *dev); + +// mqnic_rx.c +struct mqnic_ring *mqnic_create_rx_ring(struct mqnic_if *interface); +void mqnic_destroy_rx_ring(struct mqnic_ring *ring); +int mqnic_open_rx_ring(struct mqnic_ring *ring, struct mqnic_priv *priv, + struct mqnic_cq *cq, int size, int desc_block_size); +void mqnic_close_rx_ring(struct mqnic_ring *ring); +int mqnic_enable_rx_ring(struct mqnic_ring *ring); +void mqnic_disable_rx_ring(struct mqnic_ring *ring); +bool mqnic_is_rx_ring_empty(const struct mqnic_ring *ring); +bool mqnic_is_rx_ring_full(const struct mqnic_ring *ring); +void mqnic_rx_read_cons_ptr(struct mqnic_ring *ring); +void mqnic_rx_write_prod_ptr(struct mqnic_ring *ring); +void mqnic_free_rx_desc(struct mqnic_ring *ring, int index); +int mqnic_free_rx_buf(struct mqnic_ring *ring); +int mqnic_prepare_rx_desc(struct mqnic_ring *ring, int index); +int mqnic_refill_rx_buffers(struct mqnic_ring *ring); +int mqnic_process_rx_cq(struct mqnic_cq *cq, int napi_budget); +void mqnic_rx_irq(struct mqnic_cq *cq); +int mqnic_poll_rx_cq(struct napi_struct *napi, int budget); + +// mqnic_ethtool.c +extern const struct ethtool_ops mqnic_ethtool_ops; + +#endif /* MQNIC_H */ diff --git a/modules/mqnic_vf/mqnic_board.c b/modules/mqnic_vf/mqnic_board.c new file mode 120000 index 0000000..76cb8b6 --- /dev/null +++ b/modules/mqnic_vf/mqnic_board.c @@ -0,0 +1 @@ +../mqnic/mqnic_board.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_clk_info.c b/modules/mqnic_vf/mqnic_clk_info.c new file mode 120000 index 0000000..341f487 --- /dev/null +++ b/modules/mqnic_vf/mqnic_clk_info.c @@ -0,0 +1 @@ +../mqnic/mqnic_clk_info.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_cq.c b/modules/mqnic_vf/mqnic_cq.c new file mode 120000 index 0000000..609fdd3 --- /dev/null +++ b/modules/mqnic_vf/mqnic_cq.c @@ -0,0 +1 @@ +../mqnic/mqnic_cq.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_dev.c b/modules/mqnic_vf/mqnic_dev.c new file mode 120000 index 0000000..6f74710 --- /dev/null +++ b/modules/mqnic_vf/mqnic_dev.c @@ -0,0 +1 @@ +../mqnic/mqnic_dev.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_devlink.c b/modules/mqnic_vf/mqnic_devlink.c new file mode 120000 index 0000000..9697c14 --- /dev/null +++ b/modules/mqnic_vf/mqnic_devlink.c @@ -0,0 +1 @@ +../mqnic/mqnic_devlink.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_eq.c b/modules/mqnic_vf/mqnic_eq.c new file mode 100644 index 0000000..59b0028 --- /dev/null +++ b/modules/mqnic_vf/mqnic_eq.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +static int mqnic_eq_int(struct notifier_block *nb, unsigned long action, void *data) +{ + struct mqnic_eq *eq = container_of(nb, struct mqnic_eq, irq_nb); + + mqnic_process_eq(eq); + mqnic_arm_eq(eq); + + return NOTIFY_DONE; +} + +struct mqnic_eq *mqnic_create_eq(struct mqnic_if *interface) +{ + struct mqnic_eq *eq; + + eq = kzalloc(sizeof(*eq), GFP_KERNEL); + if (!eq) + return ERR_PTR(-ENOMEM); + + eq->dev = interface->dev; + eq->interface = interface; + + eq->eqn = -1; + eq->enabled = 0; + + eq->irq_nb.notifier_call = mqnic_eq_int; + + eq->hw_addr = NULL; + + eq->prod_ptr = 0; + eq->cons_ptr = 0; + + spin_lock_init(&eq->table_lock); + + INIT_RADIX_TREE(&eq->cq_table, GFP_KERNEL); + + return eq; +} + +void mqnic_destroy_eq(struct mqnic_eq *eq) +{ + mqnic_close_eq(eq); + + kfree(eq); +} + +int mqnic_open_eq(struct mqnic_eq *eq, struct mqnic_irq *irq, int size) +{ + int ret; + + if (eq->enabled || eq->hw_addr || eq->buf || !irq) + return -EINVAL; + + eq->eqn = mqnic_res_alloc(eq->interface->eq_res); + if (eq->eqn < 0) + return -ENOMEM; + + eq->size = roundup_pow_of_two(size); + eq->size_mask = eq->size - 1; + eq->stride = roundup_pow_of_two(MQNIC_EVENT_SIZE); + + eq->buf_size = eq->size * eq->stride; + eq->buf = dma_alloc_coherent(eq->dev, eq->buf_size, &eq->buf_dma_addr, GFP_KERNEL); + if (!eq->buf) { + ret = -ENOMEM; + goto fail; + } + + // register interrupt + ret = atomic_notifier_chain_register(&irq->nh, &eq->irq_nb); + if (ret) + goto fail; + + eq->irq = irq; + + eq->hw_addr = mqnic_res_get_addr(eq->interface->eq_res, eq->eqn); + + eq->prod_ptr = 0; + eq->cons_ptr = 0; + + memset(eq->buf, 1, eq->buf_size); + + // deactivate queue + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + // set base address + iowrite32((eq->buf_dma_addr & 0xfffff000), + eq->hw_addr + MQNIC_EQ_BASE_ADDR_VF_REG + 0); + iowrite32(eq->buf_dma_addr >> 32, + eq->hw_addr + MQNIC_EQ_BASE_ADDR_VF_REG + 4); + + // set function id + iowrite32(MQNIC_EQ_CMD_SET_VF_ID | 0, + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + + // set size + iowrite32(MQNIC_EQ_CMD_SET_SIZE | ilog2(eq->size), + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + // set IRQN + iowrite32(MQNIC_EQ_CMD_SET_IRQN | eq->irq->index, + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + // set pointers + iowrite32(MQNIC_EQ_CMD_SET_PROD_PTR | (eq->prod_ptr & MQNIC_EQ_PTR_MASK), + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + iowrite32(MQNIC_EQ_CMD_SET_CONS_PTR | (eq->cons_ptr & MQNIC_EQ_PTR_MASK), + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + // activate queue + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 1, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + + eq->enabled = 1; + + return 0; + +fail: + mqnic_close_eq(eq); + return ret; +} + +void mqnic_close_eq(struct mqnic_eq *eq) +{ + int ret; + + if (eq->hw_addr) { + // deactivate queue + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + } + + // unregister interrupt + if (eq->irq) + ret = atomic_notifier_chain_unregister(&eq->irq->nh, &eq->irq_nb); + + eq->irq = NULL; + + eq->hw_addr = NULL; + + if (eq->buf) { + dma_free_coherent(eq->dev, eq->buf_size, eq->buf, eq->buf_dma_addr); + eq->buf = NULL; + eq->buf_dma_addr = 0; + } + + mqnic_res_free(eq->interface->eq_res, eq->eqn); + eq->eqn = -1; + + eq->enabled = 0; +} + +int mqnic_eq_attach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq) +{ + int ret; + + spin_lock_irq(&eq->table_lock); + ret = radix_tree_insert(&eq->cq_table, cq->cqn, cq); + spin_unlock_irq(&eq->table_lock); + return ret; +} + +void mqnic_eq_detach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq) +{ + struct mqnic_cq *item; + + spin_lock_irq(&eq->table_lock); + item = radix_tree_delete(&eq->cq_table, cq->cqn); + spin_unlock_irq(&eq->table_lock); + + if (IS_ERR(item)) { + dev_err(eq->dev, "%s on IF %d EQ %d: radix_tree_delete failed: %ld", + __func__, eq->interface->index, eq->eqn, PTR_ERR(item)); + } else if (!item) { + dev_err(eq->dev, "%s on IF %d EQ %d: CQ %d not in table", + __func__, eq->interface->index, eq->eqn, cq->cqn); + } else if (item != cq) { + dev_err(eq->dev, "%s on IF %d EQ %d: entry mismatch when removing CQ %d", + __func__, eq->interface->index, eq->eqn, cq->cqn); + } +} + +void mqnic_eq_read_prod_ptr(struct mqnic_eq *eq) +{ + eq->prod_ptr += ((ioread32(eq->hw_addr + MQNIC_EQ_PTR_REG) & MQNIC_EQ_PTR_MASK) - eq->prod_ptr) & MQNIC_EQ_PTR_MASK; +} + +void mqnic_eq_write_cons_ptr(struct mqnic_eq *eq) +{ + iowrite32(MQNIC_EQ_CMD_SET_CONS_PTR | (eq->cons_ptr & MQNIC_EQ_PTR_MASK), + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); +} + +void mqnic_arm_eq(struct mqnic_eq *eq) +{ + if (!eq->enabled) + return; + + iowrite32(MQNIC_EQ_CMD_SET_ARM | 1, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); +} + +void mqnic_process_eq(struct mqnic_eq *eq) +{ + struct mqnic_if *interface = eq->interface; + struct mqnic_event *event; + struct mqnic_cq *cq; + u32 eq_index; + u32 eq_cons_ptr; + int done = 0; + + eq_cons_ptr = eq->cons_ptr; + eq_index = eq_cons_ptr & eq->size_mask; + + u32 cpl_count = mqnic_res_get_count(interface->cq_res); + + while (1) { + event = (struct mqnic_event *)(eq->buf + eq_index * eq->stride); + + if (!!(event->phase & cpu_to_le32(0x80000000)) == !!(eq_cons_ptr & eq->size)) + break; + + dma_rmb(); + + + if (event->type == MQNIC_EVENT_TYPE_CPL) { + // completion event + rcu_read_lock(); + cq = radix_tree_lookup(&eq->cq_table, (le16_to_cpu(event->source) % cpl_count) ); + rcu_read_unlock(); + + if (likely(cq)) { + if (likely(cq->handler)){ + dev_info(eq->dev, "%s: event source: %d", __func__, le16_to_cpu(event->source)); + cq->handler(cq); + } + } else { + dev_err(eq->dev, "%s on IF %d EQ %d: unknown event source %d (index %d, type %d)", + __func__, interface->index, eq->eqn, le16_to_cpu(event->source), + eq_index, le16_to_cpu(event->type)); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_NONE, 16, 1, + event, MQNIC_EVENT_SIZE, true); + } + } else { + dev_err(eq->dev, "%s on IF %d EQ %d: unknown event type %d (index %d, source %d)", + __func__, interface->index, eq->eqn, le16_to_cpu(event->type), + eq_index, le16_to_cpu(event->source)); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_NONE, 16, 1, + event, MQNIC_EVENT_SIZE, true); + } + + done++; + + eq_cons_ptr++; + eq_index = eq_cons_ptr & eq->size_mask; + } + + // update EQ consumer pointer + eq->cons_ptr = eq_cons_ptr; + mqnic_eq_write_cons_ptr(eq); +} diff --git a/modules/mqnic_vf/mqnic_ethtool.c b/modules/mqnic_vf/mqnic_ethtool.c new file mode 100644 index 0000000..39afb91 --- /dev/null +++ b/modules/mqnic_vf/mqnic_ethtool.c @@ -0,0 +1,655 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +#include +#include + +#define SFF_MODULE_ID_SFP 0x03 +#define SFF_MODULE_ID_QSFP 0x0c +#define SFF_MODULE_ID_QSFP_PLUS 0x0d +#define SFF_MODULE_ID_QSFP28 0x11 + +static void mqnic_get_drvinfo(struct net_device *ndev, + struct ethtool_drvinfo *drvinfo) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_dev *mdev = priv->mdev; + + strscpy(drvinfo->driver, DRIVER_NAME, sizeof(drvinfo->driver)); + strscpy(drvinfo->version, DRIVER_VERSION, sizeof(drvinfo->version)); + + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d.%d", + mdev->fw_ver >> 24, (mdev->fw_ver >> 16) & 0xff, + (mdev->fw_ver >> 8) & 0xff, mdev->fw_ver & 0xff); + strscpy(drvinfo->bus_info, dev_name(mdev->dev), sizeof(drvinfo->bus_info)); + + drvinfo->regdump_len = priv->mdev->hw_regs_size; +} + +static int mqnic_get_regs_len(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + return priv->mdev->hw_regs_size; +} + +static void mqnic_get_regs(struct net_device *ndev, + struct ethtool_regs *regs, void *p) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + u32 *out = p; + int k; + + for (k = 0; k < priv->mdev->hw_regs_size/4; k ++) + out[k] = ioread32(priv->mdev->hw_addr + k*4); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) +static void mqnic_get_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param, + struct kernel_ethtool_ringparam *kernel_param, + struct netlink_ext_ack *ext_ack) +#else +static void mqnic_get_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param) +#endif +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + param->rx_max_pending = MQNIC_MAX_RX_RING_SZ; + param->tx_max_pending = MQNIC_MAX_TX_RING_SZ; + + param->rx_pending = priv->rx_ring_size; + param->tx_pending = priv->tx_ring_size; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) + kernel_param->cqe_size = MQNIC_CPL_SIZE; +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) +static int mqnic_set_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param, + struct kernel_ethtool_ringparam *kernel_param, + struct netlink_ext_ack *ext_ack) +#else +static int mqnic_set_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param) +#endif +{ + struct mqnic_priv *priv = netdev_priv(ndev); + u32 tx_ring_size, rx_ring_size; + int port_up = priv->port_up; + int ret = 0; + + if (param->rx_mini_pending || param->rx_jumbo_pending) + return -EINVAL; + + if (param->rx_pending < MQNIC_MIN_RX_RING_SZ) + return -EINVAL; + + if (param->rx_pending > MQNIC_MAX_RX_RING_SZ) + return -EINVAL; + + if (param->tx_pending < MQNIC_MIN_TX_RING_SZ) + return -EINVAL; + + if (param->tx_pending > MQNIC_MAX_TX_RING_SZ) + return -EINVAL; + + rx_ring_size = roundup_pow_of_two(param->rx_pending); + tx_ring_size = roundup_pow_of_two(param->tx_pending); + + if (rx_ring_size == priv->rx_ring_size && tx_ring_size == priv->tx_ring_size) + return 0; + + netdev_info(ndev, "New TX ring size: %d", tx_ring_size); + netdev_info(ndev, "New RX ring size: %d", rx_ring_size); + + mutex_lock(&priv->mdev->state_lock); + + if (port_up) + mqnic_stop_port(ndev); + + priv->tx_ring_size = tx_ring_size; + priv->rx_ring_size = rx_ring_size; + + if (port_up) { + ret = mqnic_start_port(ndev); + + if (ret) + netdev_err(ndev, "%s: Failed to start port: %d", __func__, ret); + } + + mutex_unlock(&priv->mdev->state_lock); + + return ret; +} + +static void mqnic_get_pauseparam(struct net_device *ndev, + struct ethtool_pauseparam *param) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + u32 val; + + param->autoneg = 0; + param->rx_pause = 0; + param->tx_pause = 0; + + if (!(priv->if_features & MQNIC_IF_FEATURE_LFC)) + return; + + val = mqnic_port_get_lfc_ctrl(priv->port); + + param->rx_pause = !!(val & MQNIC_PORT_LFC_CTRL_RX_LFC_EN); + param->tx_pause = !!(val & MQNIC_PORT_LFC_CTRL_TX_LFC_EN); +} + +static int mqnic_set_pauseparam(struct net_device *ndev, + struct ethtool_pauseparam *param) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + u32 val; + + if (!(priv->if_features & MQNIC_IF_FEATURE_LFC)) + return -EOPNOTSUPP; + + if (param->autoneg) + return -EINVAL; + + val = mqnic_port_get_lfc_ctrl(priv->port); + + if (param->rx_pause) + val |= MQNIC_PORT_LFC_CTRL_RX_LFC_EN; + else + val &= ~MQNIC_PORT_LFC_CTRL_RX_LFC_EN; + + if (param->tx_pause) + val |= MQNIC_PORT_LFC_CTRL_TX_LFC_EN; + else + val &= ~MQNIC_PORT_LFC_CTRL_TX_LFC_EN; + + mqnic_port_set_lfc_ctrl(priv->port, val); + + return 0; +} + +static int mqnic_get_rxnfc(struct net_device *ndev, + struct ethtool_rxnfc *rxnfc, u32 *rule_locs) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + switch (rxnfc->cmd) { + case ETHTOOL_GRXRINGS: + rxnfc->data = priv->rxq_count; + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static u32 mqnic_get_rxfh_indir_size(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + return priv->rx_queue_map_indir_table_size; +} + +static int mqnic_get_rxfh(struct net_device *ndev, u32 *indir, u8 *key, + u8 *hfunc) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + int k; + + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + + if (indir) + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) + indir[k] = priv->rx_queue_map_indir_table[k]; + + return 0; +} + +static int mqnic_set_rxfh(struct net_device *ndev, const u32 *indir, + const u8 *key, const u8 hfunc) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + int k; + + if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) + return -EOPNOTSUPP; + + if (!indir) + return 0; + + if (indir) { + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) { + if (indir[k] >= priv->rxq_count) + return -EINVAL; + } + + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) + priv->rx_queue_map_indir_table[k] = indir[k]; + } + + return mqnic_update_indir_table(ndev); +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) +static int mqnic_get_rxfh_new(struct net_device *ndev, struct ethtool_rxfh_param *param) +{ + u8 hfunc = 0; + int ret = mqnic_get_rxfh(ndev, param->indir, param->key, &hfunc); + if (ret) + return ret; + param->hfunc = hfunc; + return 0; +} + +static int mqnic_set_rxfh_new(struct net_device *ndev, struct ethtool_rxfh_param *param, struct netlink_ext_ack *extack) +{ + return mqnic_set_rxfh(ndev, param->indir, param->key, param->hfunc); +} +#endif + +static void mqnic_get_channels(struct net_device *ndev, + struct ethtool_channels *channel) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + channel->max_rx = mqnic_res_get_count(priv->interface->rxq_res); + channel->max_tx = mqnic_res_get_count(priv->interface->txq_res); + + channel->rx_count = priv->rxq_count; + channel->tx_count = priv->txq_count; +} + +static int mqnic_set_channels(struct net_device *ndev, + struct ethtool_channels *channel) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + u32 txq_count, rxq_count; + int port_up = priv->port_up; + int ret = 0; + int k; + + if (channel->combined_count || channel->other_count) + return -EINVAL; + + if (priv->rxq_count > mqnic_res_get_count(priv->interface->rxq_res)) + return -EINVAL; + + if (priv->txq_count > mqnic_res_get_count(priv->interface->txq_res)) + return -EINVAL; + + rxq_count = channel->rx_count; + txq_count = channel->tx_count; + + if (rxq_count == priv->rxq_count && txq_count == priv->txq_count) + return 0; + + netdev_info(ndev, "New TX channel count: %d", txq_count); + netdev_info(ndev, "New RX channel count: %d", rxq_count); + + if (rxq_count != priv->rxq_count) + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) + priv->rx_queue_map_indir_table[k] = k % rxq_count; + + mutex_lock(&priv->mdev->state_lock); + + if (port_up) + mqnic_stop_port(ndev); + + priv->txq_count = txq_count; + priv->rxq_count = rxq_count; + + if (port_up) { + ret = mqnic_start_port(ndev); + + if (ret) + netdev_err(ndev, "%s: Failed to start port: %d", __func__, ret); + } + + mutex_unlock(&priv->mdev->state_lock); + + return ret; +} +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0) +static int mqnic_get_ts_info(struct net_device *ndev, + struct kernel_ethtool_ts_info *info) + +#else +static int mqnic_get_ts_info(struct net_device *ndev, + struct ethtool_ts_info *info) +#endif +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_dev *mdev = priv->mdev; + + ethtool_op_get_ts_info(ndev, info); + + if (mdev->ptp_clock) + info->phc_index = ptp_clock_index(mdev->ptp_clock); + + if (!(priv->if_features & MQNIC_IF_FEATURE_PTP_TS) || !mdev->ptp_clock) + return 0; + + info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; + + info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); + + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL); + + return 0; +} + +static int mqnic_read_module_eeprom(struct net_device *ndev, + u16 offset, u16 len, u8 *data) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + if (!priv->mod_i2c_client) + return -EINVAL; + + if (len > I2C_SMBUS_BLOCK_MAX) + len = I2C_SMBUS_BLOCK_MAX; + + return i2c_smbus_read_i2c_block_data(priv->mod_i2c_client, offset, len, data); +} + +static int mqnic_write_module_eeprom(struct net_device *ndev, + u16 offset, u16 len, u8 *data) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + if (!priv->mod_i2c_client) + return -EINVAL; + + if (len > I2C_SMBUS_BLOCK_MAX) + len = I2C_SMBUS_BLOCK_MAX; + + return i2c_smbus_write_i2c_block_data(priv->mod_i2c_client, offset, len, data); +} + +static int mqnic_query_module_id(struct net_device *ndev) +{ + int ret; + u8 data; + + ret = mqnic_read_module_eeprom(ndev, 0, 1, &data); + + if (ret < 0) + return ret; + + return data; +} + +static int mqnic_query_module_eeprom_by_page(struct net_device *ndev, + unsigned short i2c_addr, u16 page, u16 bank, u16 offset, u16 len, u8 *data) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + int module_id; + u8 d; + int ret; + unsigned short orig_i2c_addr; + + module_id = mqnic_query_module_id(ndev); + + if (module_id < 0) { + netdev_err(ndev, "%s: Failed to read module ID (%d)", __func__, module_id); + return module_id; + } + + switch (module_id) { + case SFF_MODULE_ID_SFP: + if (page > 0 || bank > 0) + return -EINVAL; + if (i2c_addr != 0x50 && i2c_addr != 0x51) + return -EINVAL; + break; + case SFF_MODULE_ID_QSFP: + case SFF_MODULE_ID_QSFP_PLUS: + case SFF_MODULE_ID_QSFP28: + if (page > 3 || bank > 0) + return -EINVAL; + if (i2c_addr != 0x50) + return -EINVAL; + break; + default: + netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, module_id); + return -EINVAL; + } + + // set page + switch (module_id) { + case SFF_MODULE_ID_SFP: + break; + case SFF_MODULE_ID_QSFP: + case SFF_MODULE_ID_QSFP_PLUS: + case SFF_MODULE_ID_QSFP28: + if (offset+len >= 128) { + // select page + d = page; + mqnic_write_module_eeprom(ndev, 127, 1, &d); + msleep(1); + } + break; + default: + netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, module_id); + return -EINVAL; + } + + // set i2c address of the mod_i2c_client + // This code section should not be called concurrently since the IOCTL + // handler for ethtool operations is called under the RTNL lock. + // In addition the i2c_client is used only within code inside this lock. + if (!priv->mod_i2c_client) + return -EINVAL; + + orig_i2c_addr = priv->mod_i2c_client->addr; + priv->mod_i2c_client->addr = i2c_addr; + + // read data + ret = mqnic_read_module_eeprom(ndev, offset, len, data); + + // reset i2c addr + priv->mod_i2c_client->addr = orig_i2c_addr; + + return ret; +} + +static int mqnic_query_module_eeprom(struct net_device *ndev, + u16 offset, u16 len, u8 *data) +{ + int module_id; + unsigned short i2c_addr = 0x50; + u16 page = 0; + u16 bank = 0; + + module_id = mqnic_query_module_id(ndev); + + if (module_id < 0) { + netdev_err(ndev, "%s: Failed to read module ID (%d)", __func__, module_id); + return module_id; + } + + switch (module_id) { + case SFF_MODULE_ID_SFP: + i2c_addr = 0x50; + page = 0; + if (offset >= 256) { + offset -= 256; + i2c_addr = 0x51; + } + break; + case SFF_MODULE_ID_QSFP: + case SFF_MODULE_ID_QSFP_PLUS: + case SFF_MODULE_ID_QSFP28: + i2c_addr = 0x50; + if (offset < 256) { + page = 0; + } else { + page = 1 + ((offset - 256) / 128); + offset -= page * 128; + } + break; + default: + netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, module_id); + return -EINVAL; + } + + // clip request to end of page + if (offset + len > 256) + len = 256 - offset; + + return mqnic_query_module_eeprom_by_page(ndev, i2c_addr, + page, bank, offset, len, data); +} + +static int mqnic_get_module_info(struct net_device *ndev, + struct ethtool_modinfo *modinfo) +{ + int read_len = 0; + u8 data[16]; + + // read module ID and revision + read_len = mqnic_read_module_eeprom(ndev, 0, 2, data); + + if (read_len < 0) + return read_len; + + if (read_len < 2) + return -EIO; + + // check identifier byte at address 0 + switch (data[0]) { + case SFF_MODULE_ID_SFP: + modinfo->type = ETH_MODULE_SFF_8472; + modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; + break; + case SFF_MODULE_ID_QSFP: + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + break; + case SFF_MODULE_ID_QSFP_PLUS: + // check revision at address 1 + if (data[1] >= 0x03) { + modinfo->type = ETH_MODULE_SFF_8636; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + } else { + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + } + break; + case SFF_MODULE_ID_QSFP28: + modinfo->type = ETH_MODULE_SFF_8636; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + break; + default: + netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, data[0]); + return -EINVAL; + } + + return 0; +} + +static int mqnic_get_module_eeprom(struct net_device *ndev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + int i = 0; + int read_len; + + if (eeprom->len == 0) + return -EINVAL; + + memset(data, 0, eeprom->len); + + while (i < eeprom->len) { + read_len = mqnic_query_module_eeprom(ndev, eeprom->offset + i, + eeprom->len - i, data + i); + + if (read_len == 0) + return 0; + + if (read_len < 0) { + netdev_err(ndev, "%s: Failed to read module EEPROM (%d)", __func__, read_len); + return read_len; + } + + i += read_len; + } + + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) +static int mqnic_get_module_eeprom_by_page(struct net_device *ndev, + const struct ethtool_module_eeprom *eeprom, + struct netlink_ext_ack *extack) +{ + int i = 0; + int read_len; + + if (eeprom->length == 0) + return -EINVAL; + + memset(eeprom->data, 0, eeprom->length); + + while (i < eeprom->length) { + read_len = mqnic_query_module_eeprom_by_page(ndev, eeprom->i2c_address, + eeprom->page, eeprom->bank, eeprom->offset + i, + eeprom->length - i, eeprom->data + i); + + if (read_len == 0) + return 0; + + if (read_len < 0) { + netdev_err(ndev, "%s: Failed to read module EEPROM (%d)", __func__, read_len); + return read_len; + } + + i += read_len; + } + + return i; +} +#endif + +const struct ethtool_ops mqnic_ethtool_ops = { + .get_drvinfo = mqnic_get_drvinfo, + .get_regs_len = mqnic_get_regs_len, + .get_regs = mqnic_get_regs, + .get_link = ethtool_op_get_link, //link status updated on timer basis + .get_ringparam = mqnic_get_ringparam, + .set_ringparam = mqnic_set_ringparam, + .get_pauseparam = mqnic_get_pauseparam, + .set_pauseparam = mqnic_set_pauseparam, + .get_rxnfc = mqnic_get_rxnfc, + + .get_rxfh_indir_size = mqnic_get_rxfh_indir_size, + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0) + .get_rxfh = mqnic_get_rxfh_new, + .set_rxfh = mqnic_set_rxfh_new, +#else + .get_rxfh = mqnic_get_rxfh, + .set_rxfh = mqnic_set_rxfh, +#endif + .get_channels = mqnic_get_channels, + .set_channels = mqnic_set_channels, + .get_ts_info = mqnic_get_ts_info, + .get_module_info = mqnic_get_module_info, + .get_module_eeprom = mqnic_get_module_eeprom, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) + .get_module_eeprom_by_page = mqnic_get_module_eeprom_by_page, +#endif +}; diff --git a/modules/mqnic_vf/mqnic_hw.h b/modules/mqnic_vf/mqnic_hw.h new file mode 120000 index 0000000..37b9f80 --- /dev/null +++ b/modules/mqnic_vf/mqnic_hw.h @@ -0,0 +1 @@ +../mqnic/mqnic_hw.h \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_i2c.c b/modules/mqnic_vf/mqnic_i2c.c new file mode 120000 index 0000000..3d255b2 --- /dev/null +++ b/modules/mqnic_vf/mqnic_i2c.c @@ -0,0 +1 @@ +../mqnic/mqnic_i2c.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_if.c b/modules/mqnic_vf/mqnic_if.c new file mode 100644 index 0000000..c5a8d41 --- /dev/null +++ b/modules/mqnic_vf/mqnic_if.c @@ -0,0 +1,400 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2021-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __iomem *hw_addr) +{ + struct device *dev = mdev->dev; + struct mqnic_if *interface; + struct mqnic_reg_block *rb; + int ret = 0; + int k; + u32 count, offset, stride; + u32 desc_block_size; + u32 val; + + interface = kzalloc(sizeof(*interface), GFP_KERNEL); + if (!interface) + return ERR_PTR(-ENOMEM); + + interface->mdev = mdev; + interface->dev = dev; + + interface->index = index; + + interface->hw_regs_size = mdev->if_stride; + interface->hw_addr = hw_addr; + interface->csr_hw_addr = hw_addr + mdev->if_csr_offset; + + // Enumerate registers + interface->rb_list = mqnic_enumerate_reg_block_list(interface->hw_addr, mdev->if_csr_offset, interface->hw_regs_size); + if (!interface->rb_list) { + ret = -EIO; + dev_err(dev, "Failed to enumerate blocks"); + goto fail; + } + + dev_info(dev, "Interface-level register blocks:"); + for (rb = interface->rb_list; rb->regs; rb++) + dev_info(dev, " type 0x%08x (v %d.%d.%d.%d)", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + interface->if_ctrl_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_IF_CTRL_TYPE, MQNIC_RB_IF_CTRL_VER, 0); + + if (!interface->if_ctrl_rb) { + ret = -EIO; + dev_err(dev, "Interface control block not found"); + goto fail; + } + + interface->if_features = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_FEATURES); + interface->port_count = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_PORT_COUNT); + interface->sched_block_count = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_SCHED_COUNT); + interface->max_tx_mtu = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_MAX_TX_MTU); + interface->max_rx_mtu = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_MAX_RX_MTU); + interface->tx_fifo_depth = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_TX_FIFO_DEPTH); + interface->rx_fifo_depth = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_RX_FIFO_DEPTH); + + interface->mac = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_MAC); + + dev_info(dev, "IF features: 0x%08x", interface->if_features); + dev_info(dev, "Port count: %d", interface->port_count); + dev_info(dev, "Scheduler block count: %d", interface->sched_block_count); + dev_info(dev, "Max TX MTU: %d", interface->max_tx_mtu); + dev_info(dev, "Max RX MTU: %d", interface->max_rx_mtu); + + interface->eq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_EQM_TYPE, MQNIC_RB_EQM_VER, 0); + + if (!interface->eq_rb) { + ret = -EIO; + dev_err(dev, "EQ block not found"); + goto fail; + } + + offset = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_OFFSET); + count = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_COUNT)/256; + stride = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_STRIDE); + + dev_info(dev, "EQ offset: 0x%08x", offset); + dev_info(dev, "EQ count: %d", count); + dev_info(dev, "EQ stride: 0x%08x", stride); + + count = min_t(u32, count, MQNIC_MAX_EQ); + + interface->eq_res = mqnic_create_res(count, hw_addr + offset, stride); + + if (IS_ERR_OR_NULL(interface->eq_res)) { + ret = PTR_ERR(interface->eq_res); + goto fail; + } + + interface->cq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_CQM_TYPE, MQNIC_RB_CQM_VER, 0); + + if (!interface->cq_rb) { + ret = -EIO; + dev_err(dev, "CQ block not found"); + goto fail; + } + + offset = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_OFFSET); + count = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_COUNT)/256; + stride = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_STRIDE); + count = min_t(u32, count, MQNIC_MAX_CQ); + + dev_info(dev, "CQ offset: 0x%08x", offset); + dev_info(dev, "CQ count: %d", count); + dev_info(dev, "CQ stride: 0x%08x", stride); + + + interface->cq_res = mqnic_create_res(count, hw_addr + offset, stride); + + if (IS_ERR_OR_NULL(interface->cq_res)) { + ret = PTR_ERR(interface->cq_res); + goto fail; + } + + interface->txq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_TX_QM_TYPE, MQNIC_RB_TX_QM_VER, 0); + + if (!interface->txq_rb) { + ret = -EIO; + dev_err(dev, "TXQ block not found"); + goto fail; + } + + offset = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_OFFSET); + count = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_COUNT)/256; + stride = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_STRIDE); + + count = min_t(u32, count, MQNIC_MAX_TXQ); + + dev_info(dev, "TXQ offset: 0x%08x", offset); + dev_info(dev, "TXQ count: %d", count); + dev_info(dev, "TXQ stride: 0x%08x", stride); + + + interface->txq_res = mqnic_create_res(count, hw_addr + offset, stride); + + if (IS_ERR_OR_NULL(interface->txq_res)) { + ret = PTR_ERR(interface->txq_res); + goto fail; + } + + interface->rxq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_RX_QM_TYPE, MQNIC_RB_RX_QM_VER, 0); + + if (!interface->rxq_rb) { + ret = -EIO; + dev_err(dev, "RXQ block not found"); + goto fail; + } + + offset = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_OFFSET); + count = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_COUNT)/256; + stride = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_STRIDE); + + count = min_t(u32, count, MQNIC_MAX_RXQ); + dev_info(dev, "RXQ offset: 0x%08x", offset); + dev_info(dev, "RXQ count: %d", count); + dev_info(dev, "RXQ stride: 0x%08x", stride); + + + interface->rxq_res = mqnic_create_res(count, hw_addr + offset, stride); + + if (IS_ERR_OR_NULL(interface->rxq_res)) { + ret = PTR_ERR(interface->rxq_res); + goto fail; + } + + interface->rx_queue_map_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_RX_QUEUE_MAP_TYPE, MQNIC_RB_RX_QUEUE_MAP_VER, 0); + + if (!interface->rx_queue_map_rb) { + ret = -EIO; + dev_err(dev, "RX queue map block not found"); + goto fail; + } + + val = ioread32(interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_REG_CFG); + interface->rx_queue_map_indir_table_size = 1 << ((val >> 8) & 0xff); + + dev_info(dev, "RX queue map indirection table size: %d", interface->rx_queue_map_indir_table_size); + + for (k = 0; k < interface->port_count; k++) { + interface->rx_queue_map_indir_table[k] = interface->hw_addr + ioread32(interface->rx_queue_map_rb->regs + + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*k + MQNIC_RB_RX_QUEUE_MAP_CH_REG_OFFSET); + + mqnic_interface_set_rx_queue_map_rss_mask(interface, k, 0); + mqnic_interface_set_rx_queue_map_app_mask(interface, k, 0); + mqnic_interface_set_rx_queue_map_indir_table(interface, k, 0, 0); + } + + // determine desc block size + iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | 0xff00, mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_CTRL_STATUS_REG); + interface->max_desc_block_size = 1 << ((ioread32(mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_SIZE_CQN_REG) >> 28) & 0xf); + iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | 0x0000, mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_CTRL_STATUS_REG); + + dev_info(dev, "Max desc block size: %d", interface->max_desc_block_size); + + interface->max_desc_block_size = min_t(u32, interface->max_desc_block_size, MQNIC_MAX_FRAGS); + + desc_block_size = min_t(u32, interface->max_desc_block_size, 4); + + // disable queues + for (k = 0; k < mqnic_res_get_count(interface->eq_res); k++) + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->eq_res, k) + MQNIC_EQ_CTRL_STATUS_REG); + + for (k = 0; k < mqnic_res_get_count(interface->cq_res); k++) + iowrite32(MQNIC_CQ_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->cq_res, k) + MQNIC_CQ_CTRL_STATUS_REG); + + for (k = 0; k < mqnic_res_get_count(interface->txq_res); k++) + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->txq_res, k) + MQNIC_QUEUE_CTRL_STATUS_REG); + + for (k = 0; k < mqnic_res_get_count(interface->rxq_res); k++) + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->rxq_res, k) + MQNIC_QUEUE_CTRL_STATUS_REG); + + // create ports + for (k = 0; k < interface->port_count; k++) { + struct mqnic_port *port; + struct mqnic_reg_block *port_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_PORT_TYPE, MQNIC_RB_PORT_VER, k); + + if (!port_rb) { + ret = -EIO; + dev_err(dev, "Port index %d not found", k); + goto fail; + } + + port = mqnic_create_port(interface, k, mdev->phys_port_max++, port_rb); + if (IS_ERR_OR_NULL(port)) { + ret = PTR_ERR(port); + goto fail; + } + interface->port[k] = port; + } + + // create schedulers + for (k = 0; k < interface->sched_block_count; k++) { + struct mqnic_sched_block *sched_block; + struct mqnic_reg_block *sched_block_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_SCHED_BLOCK_TYPE, MQNIC_RB_SCHED_BLOCK_VER, k); + + if (!sched_block_rb) { + ret = -EIO; + dev_err(dev, "Scheduler block index %d not found", k); + goto fail; + } + + sched_block = mqnic_create_sched_block(interface, k, sched_block_rb); + if (IS_ERR_OR_NULL(sched_block)) { + ret = PTR_ERR(sched_block); + goto fail; + } + interface->sched_block[k] = sched_block; + } + + // create EQs + interface->eq_count = mqnic_res_get_count(interface->eq_res); + for (k = 0; k < interface->eq_count; k++) { + struct mqnic_eq *eq = mqnic_create_eq(interface); + if (IS_ERR_OR_NULL(eq)) { + ret = PTR_ERR(eq); + goto fail; + } + + interface->eq[k] = eq; + + ret = mqnic_open_eq(eq, mdev->irq[k % mdev->irq_count], mqnic_num_eq_entries); + if (ret) + goto fail; + + mqnic_arm_eq(eq); + } + + // create net_devices + interface->ndev_count = 1; + for (k = 0; k < interface->ndev_count; k++) { + struct net_device *ndev = mqnic_create_netdev(interface, k, + interface->port[k], interface->sched_block[k]); + if (IS_ERR_OR_NULL(ndev)) { + ret = PTR_ERR(ndev); + goto fail; + } + interface->ndev[k] = ndev; + } + + return interface; + +fail: + mqnic_destroy_interface(interface); + return ERR_PTR(ret); +} + +void mqnic_destroy_interface(struct mqnic_if *interface) +{ + int k; + + // destroy associated net_devices + for (k = 0; k < ARRAY_SIZE(interface->ndev); k++) { + if (interface->ndev[k]) { + mqnic_destroy_netdev(interface->ndev[k]); + interface->ndev[k] = NULL; + } + } + + // free EQs + for (k = 0; k < ARRAY_SIZE(interface->eq); k++) { + if (interface->eq[k]) { + mqnic_destroy_eq(interface->eq[k]); + interface->eq[k] = NULL; + } + } + + // free schedulers + for (k = 0; k < ARRAY_SIZE(interface->sched_block); k++) { + if (interface->sched_block[k]) { + mqnic_destroy_sched_block(interface->sched_block[k]); + interface->sched_block[k] = NULL; + } + } + + // free ports + for (k = 0; k < ARRAY_SIZE(interface->port); k++) { + if (interface->port[k]) { + mqnic_destroy_port(interface->port[k]); + interface->port[k] = NULL; + } + } + + mqnic_destroy_res(interface->eq_res); + mqnic_destroy_res(interface->cq_res); + mqnic_destroy_res(interface->txq_res); + mqnic_destroy_res(interface->rxq_res); + + if (interface->rb_list) + mqnic_free_reg_block_list(interface->rb_list); + + kfree(interface); +} + +u32 mqnic_interface_get_tx_mtu(struct mqnic_if *interface) +{ + return ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_TX_MTU); +} +EXPORT_SYMBOL(mqnic_interface_get_tx_mtu); + +void mqnic_interface_set_tx_mtu(struct mqnic_if *interface, u32 mtu) +{ + iowrite32(mtu, interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_TX_MTU); +} +EXPORT_SYMBOL(mqnic_interface_set_tx_mtu); + +u32 mqnic_interface_get_rx_mtu(struct mqnic_if *interface) +{ + return ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_RX_MTU); +} +EXPORT_SYMBOL(mqnic_interface_get_rx_mtu); + +void mqnic_interface_set_rx_mtu(struct mqnic_if *interface, u32 mtu) +{ + iowrite32(mtu, interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_RX_MTU); +} +EXPORT_SYMBOL(mqnic_interface_set_rx_mtu); + +u32 mqnic_interface_get_rx_queue_map_rss_mask(struct mqnic_if *interface, int port) +{ + return ioread32(interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + + MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_RSS_MASK); +} +EXPORT_SYMBOL(mqnic_interface_get_rx_queue_map_rss_mask); + +void mqnic_interface_set_rx_queue_map_rss_mask(struct mqnic_if *interface, int port, u32 val) +{ + iowrite32(val, interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + + MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_RSS_MASK); +} +EXPORT_SYMBOL(mqnic_interface_set_rx_queue_map_rss_mask); + +u32 mqnic_interface_get_rx_queue_map_app_mask(struct mqnic_if *interface, int port) +{ + return ioread32(interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + + MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_APP_MASK); +} +EXPORT_SYMBOL(mqnic_interface_get_rx_queue_map_app_mask); + +void mqnic_interface_set_rx_queue_map_app_mask(struct mqnic_if *interface, int port, u32 val) +{ + iowrite32(val, interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + + MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_APP_MASK); +} +EXPORT_SYMBOL(mqnic_interface_set_rx_queue_map_app_mask); + +u32 mqnic_interface_get_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index) +{ + return ioread32(interface->rx_queue_map_indir_table[port] + index*4); +} +EXPORT_SYMBOL(mqnic_interface_get_rx_queue_map_indir_table); + +void mqnic_interface_set_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index, u32 val) +{ + iowrite32(val, interface->rx_queue_map_indir_table[port] + index*4); +} +EXPORT_SYMBOL(mqnic_interface_set_rx_queue_map_indir_table); diff --git a/modules/mqnic_vf/mqnic_ioctl.h b/modules/mqnic_vf/mqnic_ioctl.h new file mode 120000 index 0000000..589ac06 --- /dev/null +++ b/modules/mqnic_vf/mqnic_ioctl.h @@ -0,0 +1 @@ +../mqnic/mqnic_ioctl.h \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_irq.c b/modules/mqnic_vf/mqnic_irq.c new file mode 120000 index 0000000..85d72f3 --- /dev/null +++ b/modules/mqnic_vf/mqnic_irq.c @@ -0,0 +1 @@ +../mqnic/mqnic_irq.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_main.c b/modules/mqnic_vf/mqnic_main.c new file mode 100644 index 0000000..80c4b84 --- /dev/null +++ b/modules/mqnic_vf/mqnic_main.c @@ -0,0 +1,918 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) +#include +#endif + +MODULE_DESCRIPTION("mqnic driver"); +MODULE_AUTHOR("Alex Forencich"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION(DRIVER_VERSION); + +unsigned int mqnic_num_eq_entries = 1024; +unsigned int mqnic_num_txq_entries = 1024; +unsigned int mqnic_num_rxq_entries = 1024; + +module_param_named(num_eq_entries, mqnic_num_eq_entries, uint, 0444); +MODULE_PARM_DESC(num_eq_entries, "number of entries to allocate per event queue (default: 1024)"); +module_param_named(num_txq_entries, mqnic_num_txq_entries, uint, 0444); +MODULE_PARM_DESC(num_txq_entries, "number of entries to allocate per transmit queue (default: 1024)"); +module_param_named(num_rxq_entries, mqnic_num_rxq_entries, uint, 0444); +MODULE_PARM_DESC(num_rxq_entries, "number of entries to allocate per receive queue (default: 1024)"); + +unsigned int mqnic_link_status_poll = MQNIC_LINK_STATUS_POLL_MS; + +module_param_named(link_status_poll, mqnic_link_status_poll, uint, 0444); +MODULE_PARM_DESC(link_status_poll, + "link status polling interval, in ms (default: 1000; 0 to turn off)"); + + +#ifdef CONFIG_PCI +static const struct pci_device_id mqnic_pci_id_table[] = { + {PCI_DEVICE(0x1234, 0x0000)}, + {0 /* end */ } +}; + +MODULE_DEVICE_TABLE(pci, mqnic_pci_id_table); +#endif + +#ifdef CONFIG_OF +static struct of_device_id mqnic_of_id_table[] = { + { .compatible = "corundum,mqnic" }, + { }, +}; +MODULE_DEVICE_TABLE(of, mqnic_of_id_table); +#endif + +static LIST_HEAD(mqnic_devices); +static DEFINE_SPINLOCK(mqnic_devices_lock); + +static unsigned int mqnic_get_free_id(void) +{ + struct mqnic_dev *mqnic; + unsigned int id = 0; + bool available = false; + + while (!available) { + available = true; + list_for_each_entry(mqnic, &mqnic_devices, dev_list_node) { + if (mqnic->id == id) { + available = false; + id++; + break; + } + } + } + + return id; +} + +static void mqnic_assign_id(struct mqnic_dev *mqnic) +{ + spin_lock(&mqnic_devices_lock); + mqnic->id = mqnic_get_free_id(); + list_add_tail(&mqnic->dev_list_node, &mqnic_devices); + spin_unlock(&mqnic_devices_lock); + + snprintf(mqnic->name, sizeof(mqnic->name), DRIVER_NAME "%d", mqnic->id); +} + +static void mqnic_free_id(struct mqnic_dev *mqnic) +{ + spin_lock(&mqnic_devices_lock); + list_del(&mqnic->dev_list_node); + spin_unlock(&mqnic_devices_lock); +} + +static int mqnic_common_setdma(struct mqnic_dev *mqnic) +{ + int ret; + struct device *dev = mqnic->dev; + + // Set mask + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + if (ret) { + dev_warn(dev, "Warning: failed to set 64 bit PCI DMA mask"); + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(dev, "Failed to set PCI DMA mask"); + return ret; + } + } + + // Set max segment size + dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + + return ret; +} + +#ifdef CONFIG_OF +static int mqnic_platform_get_mac_address(struct mqnic_dev *mqnic) +{ + int ret; + struct device *dev = mqnic->dev; + char mac_base[ETH_ALEN]; + struct device_node *np; + u32 inc_idx; + u32 inc; + int k; + + /* NOTE: Not being able to get a (base) MAC address shall not be an + * error to fail on intentionally. Thus we are warning, only. + */ + ret = eth_platform_get_mac_address(dev, mac_base); + if (ret) { + dev_warn(dev, "Unable to get MAC address\n"); + return 0; + } + + np = mqnic->dev->of_node; + if (!np) + return 0; + + if (of_property_read_u32(np, MQNIC_PROP_MAC_ADDR_INC_BYTE, &inc_idx)) + inc_idx = 5; + if ((inc_idx < 3) || (inc_idx > 5)) { + dev_err(dev, "Invalid property \"" MQNIC_PROP_MAC_ADDR_INC_BYTE "\"\n"); + return -EINVAL; + } + + ret = of_property_read_u32(np, MQNIC_PROP_MAC_ADDR_INC, &inc); + if (ret == -EINVAL) { + inc = 0; + } else if (ret) { + dev_err(dev, "Invalid property \"" MQNIC_PROP_MAC_ADDR_INC "\"\n"); + return ret; + } + + if (of_property_read_bool(np, MQNIC_PROP_MAC_ADDR_LOCAL)) + mac_base[0] |= BIT(1); + + mqnic->mac_count = mqnic->if_count; + for (k = 0; k < mqnic->mac_count; k++) { + memcpy(mqnic->mac_list[k], mac_base, ETH_ALEN); + mqnic->mac_list[k][inc_idx] += inc + k; + } + + return 0; +} + +static void mqnic_platform_module_eeprom_put(struct mqnic_dev *mqnic) +{ + int k; + + for (k = 0; k < mqnic->if_count; k++) + if (mqnic->mod_i2c_client) + put_device(&mqnic->mod_i2c_client[k]->dev); +} + +static int mqnic_platform_module_eeprom_get(struct mqnic_dev *mqnic) +{ + int ret; + struct device *dev = mqnic->dev; + int k; + + ret = 0; + + if (!dev->of_node) + return 0; + + for (k = 0; k < mqnic->if_count; k++) { + struct device_node *np; + struct i2c_client *cl; + + /* NOTE: Not being able to get a phandle for module EEPROM shall + * not be an error to fail on intentionally. Thus we are + * warning, only. + */ + np = of_parse_phandle(dev->of_node, MQNIC_PROP_MODULE_EEPROM, k); + if (!np) { + dev_warn(dev, "Missing phandle to module EEPROM for interface %d\n", k); + continue; + } + + cl = of_find_i2c_device_by_node(np); + if (!cl) { + ret = -ENOENT; + dev_err(dev, "Failed to find I2C device for module of interface %d\n", k); + of_node_put(np); + break; + } else { + mqnic->mod_i2c_client[k] = cl; + mqnic->mod_i2c_client_count++; + } + of_node_put(np); + } + + if (ret) + mqnic_platform_module_eeprom_put(mqnic); + + return ret; +} +#endif + +static void mqnic_common_remove(struct mqnic_dev *mqnic); + +#ifdef CONFIG_AUXILIARY_BUS +static void mqnic_adev_release(struct device *dev) +{ + struct mqnic_adev *mqnic_adev = container_of(dev, struct mqnic_adev, adev.dev); + + if (mqnic_adev->ptr) + *mqnic_adev->ptr = NULL; + kfree(mqnic_adev); +} +#endif + +static int mqnic_common_probe(struct mqnic_dev *mqnic) +{ + int ret = 0; + struct devlink *devlink = priv_to_devlink(mqnic); + struct device *dev = mqnic->dev; + struct mqnic_reg_block *rb; + struct rtc_time tm; + + int k = 0, l = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) + devlink_register(devlink); +#else + devlink_register(devlink, dev); +#endif + + // Enumerate registers + mqnic->rb_list = mqnic_enumerate_reg_block_list(mqnic->hw_addr, 0, mqnic->hw_regs_size); + if (!mqnic->rb_list) { + dev_err(dev, "Failed to enumerate blocks"); + return -EIO; + } + + dev_info(dev, "Device-level register blocks:"); + for (rb = mqnic->rb_list; rb->regs; rb++) + dev_info(dev, " type 0x%08x (v %d.%d.%d.%d)", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + // Read ID registers + mqnic->fw_id_rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_FW_ID_TYPE, MQNIC_RB_FW_ID_VER, 0); + + if (!mqnic->fw_id_rb) { + ret = -EIO; + dev_err(dev, "Error: FW ID block not found"); + goto fail_rb_init; + } + + mqnic->fpga_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FPGA_ID); + mqnic->fw_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FW_ID); + mqnic->fw_ver = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FW_VER); + mqnic->board_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BOARD_ID); + mqnic->board_ver = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BOARD_VER); + mqnic->build_date = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BUILD_DATE); + mqnic->git_hash = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_GIT_HASH); + mqnic->rel_info = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_REL_INFO); + mqnic->num_funcs = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_NUM_FUNCS); + + if (mqnic->num_funcs == 256) { + mqnic->num_funcs = 252; + } + + dev_info(dev, "NUMBER OF FUNCS: 0x%08x", mqnic->num_funcs); + + rtc_time64_to_tm(mqnic->build_date, &tm); + + dev_info(dev, "FPGA ID: 0x%08x", mqnic->fpga_id); + dev_info(dev, "FW ID: 0x%08x", mqnic->fw_id); + dev_info(dev, "FW version: %d.%d.%d.%d", mqnic->fw_ver >> 24, + (mqnic->fw_ver >> 16) & 0xff, + (mqnic->fw_ver >> 8) & 0xff, + mqnic->fw_ver & 0xff); + dev_info(dev, "Board ID: 0x%08x", mqnic->board_id); + dev_info(dev, "Board version: %d.%d.%d.%d", mqnic->board_ver >> 24, + (mqnic->board_ver >> 16) & 0xff, + (mqnic->board_ver >> 8) & 0xff, + mqnic->board_ver & 0xff); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) + snprintf(mqnic->build_date_str, sizeof(mqnic->build_date_str), "%ptRd %ptRt", &tm, &tm); +#else + snprintf(mqnic->build_date_str, sizeof(mqnic->build_date_str), "%04d-%02d-%02d %02d:%02d:%02d", + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); +#endif + dev_info(dev, "Build date: %s UTC (raw: 0x%08x)", mqnic->build_date_str, mqnic->build_date); + dev_info(dev, "Git hash: %08x", mqnic->git_hash); + dev_info(dev, "Release info: %08x", mqnic->rel_info); + + rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_APP_INFO_TYPE, MQNIC_RB_APP_INFO_VER, 0); + + if (rb) { + mqnic->app_id = ioread32(rb->regs + MQNIC_RB_APP_INFO_REG_ID); + dev_info(dev, "Application ID: 0x%08x", mqnic->app_id); + + if (!mqnic->app_hw_addr) { + dev_warn(dev, "Warning: application section present, but application BAR not mapped"); + } + } + + mqnic_clk_info_init(mqnic); + mqnic_stats_init(mqnic); + + mqnic->phc_rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_PHC_TYPE, MQNIC_RB_PHC_VER, 0); + + // Enumerate interfaces + mqnic->if_rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_IF_TYPE, MQNIC_RB_IF_VER, 0); + + if (!mqnic->if_rb) { + ret = -EIO; + dev_err(dev, "Error: interface block not found"); + goto fail_rb_init; + } + + mqnic->if_offset = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_OFFSET); + mqnic->if_count = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_COUNT); + mqnic->if_stride = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_STRIDE); + mqnic->if_csr_offset = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_CSR_OFFSET); + + dev_info(dev, "IF offset: 0x%08x", mqnic->if_offset); + dev_info(dev, "IF count: %d", mqnic->if_count); + dev_info(dev, "IF stride: 0x%08x", mqnic->if_stride); + dev_info(dev, "IF CSR offset: 0x%08x", mqnic->if_csr_offset); + + // check BAR size + if (mqnic->if_count * mqnic->if_stride > mqnic->hw_regs_size) { + ret = -EIO; + dev_err(dev, "Invalid BAR configuration (%d IF * 0x%x > 0x%llx)", + mqnic->if_count, mqnic->if_stride, mqnic->hw_regs_size); + goto fail_bar_size; + } + + if (mqnic->pfdev) { +#ifdef CONFIG_OF + ret = mqnic_platform_get_mac_address(mqnic); + if (ret) + goto fail_board; + + ret = mqnic_platform_module_eeprom_get(mqnic); + if (ret) + goto fail_board; +#endif + } else { + // Board-specific init + ret = mqnic_board_init(mqnic); + if (ret) { + dev_err(dev, "Failed to initialize board"); + goto fail_board; + } + } + + // register PHC + if (mqnic->phc_rb) + mqnic_register_phc(mqnic); + + mutex_init(&mqnic->state_lock); + + // Set up interfaces + mqnic->phys_port_max = 0; + + mqnic->if_count = min_t(u32, mqnic->if_count, MQNIC_MAX_IF); + + for (k = 0; k < mqnic->if_count; k++) { + struct mqnic_if *interface; + dev_info(dev, "Creating interface %d", k); + interface = mqnic_create_interface(mqnic, k, mqnic->hw_addr + k * mqnic->if_stride); + if (IS_ERR_OR_NULL(interface)) { + dev_err(dev, "Failed to create interface: %d", ret); + goto fail_create_if; + } + mqnic->interface[k] = interface; + } + + // pass module I2C clients to interface instances + for (k = 0; k < mqnic->if_count; k++) { + struct mqnic_if *interface = mqnic->interface[k]; + interface->mod_i2c_client = mqnic->mod_i2c_client[k]; + + for (l = 0; l < interface->ndev_count; l++) { + struct mqnic_priv *priv = netdev_priv(interface->ndev[l]); + priv->mod_i2c_client = mqnic->mod_i2c_client[k]; + } + } + +fail_create_if: + mqnic->misc_dev.minor = MISC_DYNAMIC_MINOR; + mqnic->misc_dev.name = mqnic->name; + mqnic->misc_dev.fops = &mqnic_fops; + mqnic->misc_dev.parent = dev; + + ret = misc_register(&mqnic->misc_dev); + if (ret) { + mqnic->misc_dev.this_device = NULL; + dev_err(dev, "misc_register failed: %d\n", ret); + goto fail_miscdev; + } + + dev_info(dev, "Registered device %s", mqnic->name); + +#ifdef CONFIG_AUXILIARY_BUS + if (mqnic->app_id) { + mqnic->app_adev = kzalloc(sizeof(*mqnic->app_adev), GFP_KERNEL); + if (!mqnic->app_adev) { + ret = -ENOMEM; + goto fail_adev; + } + + snprintf(mqnic->app_adev->name, sizeof(mqnic->app_adev->name), "app_%08x", mqnic->app_id); + + mqnic->app_adev->adev.id = mqnic->id; + mqnic->app_adev->adev.name = mqnic->app_adev->name; + mqnic->app_adev->adev.dev.parent = dev; + mqnic->app_adev->adev.dev.release = mqnic_adev_release; + mqnic->app_adev->mdev = mqnic; + mqnic->app_adev->ptr = &mqnic->app_adev; + + ret = auxiliary_device_init(&mqnic->app_adev->adev); + if (ret) { + kfree(mqnic->app_adev); + mqnic->app_adev = NULL; + goto fail_adev; + } + + ret = auxiliary_device_add(&mqnic->app_adev->adev); + if (ret) { + auxiliary_device_uninit(&mqnic->app_adev->adev); + mqnic->app_adev = NULL; + goto fail_adev; + } + + dev_info(dev, "Registered auxiliary bus device " DRIVER_NAME ".%s.%d", + mqnic->app_adev->adev.name, mqnic->app_adev->adev.id); + } +#endif + + // probe complete + return 0; + + // error handling +#ifdef CONFIG_AUXILIARY_BUS +fail_adev: +#endif +fail_miscdev: +fail_board: +fail_bar_size: +fail_rb_init: + mqnic_common_remove(mqnic); + return ret; +} + +static void mqnic_common_remove(struct mqnic_dev *mqnic) +{ + struct devlink *devlink = priv_to_devlink(mqnic); + int k = 0; + +#ifdef CONFIG_AUXILIARY_BUS + if (mqnic->app_adev) { + auxiliary_device_delete(&mqnic->app_adev->adev); + auxiliary_device_uninit(&mqnic->app_adev->adev); + } +#endif + + if (mqnic->misc_dev.this_device) + misc_deregister(&mqnic->misc_dev); + + for (k = 0; k < ARRAY_SIZE(mqnic->interface); k++) { + if (mqnic->interface[k]) { + mqnic_destroy_interface(mqnic->interface[k]); + mqnic->interface[k] = NULL; + } + } + + mqnic_unregister_phc(mqnic); + if (mqnic->pfdev) { +#ifdef CONFIG_OF + mqnic_platform_module_eeprom_put(mqnic); +#endif + } else { + mqnic_board_deinit(mqnic); + } + if (mqnic->rb_list) + mqnic_free_reg_block_list(mqnic->rb_list); + + devlink_unregister(devlink); +} + +#ifdef CONFIG_PCI +static int mqnic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int ret = 0; + struct mqnic_dev *mqnic; + struct devlink *devlink; + struct device *dev = &pdev->dev; + struct pci_dev *bridge = pci_upstream_bridge(pdev); + + dev_info(dev, DRIVER_NAME " PCI probe"); + dev_info(dev, " Vendor: 0x%04x", pdev->vendor); + dev_info(dev, " Device: 0x%04x", pdev->device); + dev_info(dev, " Subsystem vendor: 0x%04x", pdev->subsystem_vendor); + dev_info(dev, " Subsystem device: 0x%04x", pdev->subsystem_device); + dev_info(dev, " Class: 0x%06x", pdev->class); + dev_info(dev, " PCI ID: %04x:%02x:%02x.%d", pci_domain_nr(pdev->bus), + pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + + if (pdev->pcie_cap) { + u16 devctl; + u32 lnkcap; + u16 lnkctl; + u16 lnksta; + + pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_DEVCTL, &devctl); + pci_read_config_dword(pdev, pdev->pcie_cap + PCI_EXP_LNKCAP, &lnkcap); + pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_LNKCTL, &lnkctl); + pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_LNKSTA, &lnksta); + + dev_info(dev, " Max payload size: %d bytes", + 128 << ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5)); + dev_info(dev, " Max read request size: %d bytes", + 128 << ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12)); + dev_info(dev, " Read completion boundary: %d bytes", + lnkctl & PCI_EXP_LNKCTL_RCB ? 128 : 64); + dev_info(dev, " Link capability: gen %d x%d", + lnkcap & PCI_EXP_LNKCAP_SLS, (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4); + dev_info(dev, " Link status: gen %d x%d", + lnksta & PCI_EXP_LNKSTA_CLS, (lnksta & PCI_EXP_LNKSTA_NLW) >> 4); + dev_info(dev, " Relaxed ordering: %s", + devctl & PCI_EXP_DEVCTL_RELAX_EN ? "enabled" : "disabled"); + dev_info(dev, " Phantom functions: %s", + devctl & PCI_EXP_DEVCTL_PHANTOM ? "enabled" : "disabled"); + dev_info(dev, " Extended tags: %s", + devctl & PCI_EXP_DEVCTL_EXT_TAG ? "enabled" : "disabled"); + dev_info(dev, " No snoop: %s", + devctl & PCI_EXP_DEVCTL_NOSNOOP_EN ? "enabled" : "disabled"); + } + +#ifdef CONFIG_NUMA + dev_info(dev, " NUMA node: %d", pdev->dev.numa_node); +#endif + + if (bridge) { + dev_info(dev, " PCI ID (bridge): %04x:%02x:%02x.%d", pci_domain_nr(bridge->bus), + bridge->bus->number, PCI_SLOT(bridge->devfn), PCI_FUNC(bridge->devfn)); + } + + if (bridge && bridge->pcie_cap) { + u32 lnkcap; + u16 lnksta; + + pci_read_config_dword(bridge, bridge->pcie_cap + PCI_EXP_LNKCAP, &lnkcap); + pci_read_config_word(bridge, bridge->pcie_cap + PCI_EXP_LNKSTA, &lnksta); + + dev_info(dev, " Link capability (bridge): gen %d x%d", + lnkcap & PCI_EXP_LNKCAP_SLS, (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4); + dev_info(dev, " Link status (bridge): gen %d x%d", + lnksta & PCI_EXP_LNKSTA_CLS, (lnksta & PCI_EXP_LNKSTA_NLW) >> 4); + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) + pcie_print_link_status(pdev); +#endif + + devlink = mqnic_devlink_alloc(dev); + if (!devlink) + return -ENOMEM; + + mqnic = devlink_priv(devlink); + mqnic->dev = dev; + mqnic->pdev = pdev; + pci_set_drvdata(pdev, mqnic); + + // assign ID and add to list + mqnic_assign_id(mqnic); + + // Disable ASPM + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | + PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); + + // Enable device + ret = pci_enable_device_mem(pdev); + if (ret) { + dev_err(dev, "Failed to enable PCI device"); + goto fail_enable_device; + } + + // Set DMA properties + ret = mqnic_common_setdma(mqnic); + if (ret) + goto fail_regions; + + // Reserve regions + ret = pci_request_regions(pdev, DRIVER_NAME); + if (ret) { + dev_err(dev, "Failed to reserve regions"); + goto fail_regions; + } + + mqnic->hw_regs_size = pci_resource_len(pdev, 0); + mqnic->hw_regs_phys = pci_resource_start(pdev, 0); + mqnic->app_hw_regs_size = pci_resource_len(pdev, 2); + mqnic->app_hw_regs_phys = pci_resource_start(pdev, 2); + mqnic->ram_hw_regs_size = pci_resource_len(pdev, 4); + mqnic->ram_hw_regs_phys = pci_resource_start(pdev, 4); + + // Map BARs + dev_info(dev, "Control BAR size: %llu", mqnic->hw_regs_size); + mqnic->hw_addr = pci_ioremap_bar(pdev, 0); + if (!mqnic->hw_addr) { + ret = -ENOMEM; + dev_err(dev, "Failed to map control BAR"); + goto fail_map_bars; + } + + if (mqnic->app_hw_regs_size) { + dev_info(dev, "Application BAR size: %llu", mqnic->app_hw_regs_size); + mqnic->app_hw_addr = pci_ioremap_bar(pdev, 2); + if (!mqnic->app_hw_addr) { + ret = -ENOMEM; + dev_err(dev, "Failed to map application BAR"); + goto fail_map_bars; + } + } + + if (mqnic->ram_hw_regs_size) { + dev_info(dev, "RAM BAR size: %llu", mqnic->ram_hw_regs_size); + mqnic->ram_hw_addr = pci_ioremap_bar(pdev, 4); + if (!mqnic->ram_hw_addr) { + ret = -ENOMEM; + dev_err(dev, "Failed to map RAM BAR"); + goto fail_map_bars; + } + } + + // Check if device needs to be reset + if (ioread32(mqnic->hw_addr+4) == 0xffffffff) { + ret = -EIO; + dev_err(dev, "Device needs to be reset"); + goto fail_reset; + } + + // Set up interrupts + ret = mqnic_irq_init_pcie(mqnic); + if (ret) { + dev_err(dev, "Failed to set up interrupts"); + goto fail_init_irq; + } + + // Enable bus mastering for DMA + pci_set_master(pdev); + + // Common init + ret = mqnic_common_probe(mqnic); + if (ret) + goto fail_common; + + // probe complete + return 0; + + // error handling +fail_common: + pci_clear_master(pdev); + mqnic_irq_deinit_pcie(mqnic); +fail_reset: +fail_init_irq: +fail_map_bars: + if (mqnic->hw_addr) + pci_iounmap(pdev, mqnic->hw_addr); + if (mqnic->app_hw_addr) + pci_iounmap(pdev, mqnic->app_hw_addr); + if (mqnic->ram_hw_addr) + pci_iounmap(pdev, mqnic->ram_hw_addr); + pci_release_regions(pdev); +fail_regions: + pci_disable_device(pdev); +fail_enable_device: + mqnic_free_id(mqnic); + mqnic_devlink_free(devlink); + return ret; +} + +static void mqnic_pci_remove(struct pci_dev *pdev) +{ + struct mqnic_dev *mqnic = pci_get_drvdata(pdev); + struct devlink *devlink = priv_to_devlink(mqnic); + + dev_info(&pdev->dev, DRIVER_NAME " PCI remove"); + + mqnic_common_remove(mqnic); + + pci_clear_master(pdev); + mqnic_irq_deinit_pcie(mqnic); + if (mqnic->hw_addr) + pci_iounmap(pdev, mqnic->hw_addr); + if (mqnic->app_hw_addr) + pci_iounmap(pdev, mqnic->app_hw_addr); + if (mqnic->ram_hw_addr) + pci_iounmap(pdev, mqnic->ram_hw_addr); + pci_release_regions(pdev); + pci_disable_device(pdev); + mqnic_free_id(mqnic); + mqnic_devlink_free(devlink); +} + +static void mqnic_pci_shutdown(struct pci_dev *pdev) +{ + dev_info(&pdev->dev, DRIVER_NAME " PCI shutdown"); + + mqnic_pci_remove(pdev); +} + +static struct pci_driver mqnic_pci_driver = { + .name = DRIVER_NAME, + .id_table = mqnic_pci_id_table, + .probe = mqnic_pci_probe, + .remove = mqnic_pci_remove, + .shutdown = mqnic_pci_shutdown +}; +#endif /* CONFIG_PCI */ + +static int mqnic_platform_probe(struct platform_device *pdev) +{ + int ret; + struct mqnic_dev *mqnic; + struct devlink *devlink; + struct device *dev = &pdev->dev; + struct resource *res; + struct reset_control *rst; + + dev_info(dev, DRIVER_NAME " platform probe"); + +#ifdef CONFIG_NUMA + dev_info(dev, " NUMA node: %d", pdev->dev.numa_node); +#endif + + devlink = mqnic_devlink_alloc(dev); + if (!devlink) + return -ENOMEM; + + mqnic = devlink_priv(devlink); + mqnic->dev = dev; + mqnic->pfdev = pdev; + platform_set_drvdata(pdev, mqnic); + + // assign ID and add to list + mqnic_assign_id(mqnic); + + // Set DMA properties + ret = mqnic_common_setdma(mqnic); + if (ret) + goto fail; + + // Reset device + rst = devm_reset_control_get(dev, NULL); + if (IS_ERR(rst)) { + dev_warn(dev, "Cannot control device reset"); + } else { + dev_info(dev, "Resetting device"); + reset_control_assert(rst); + udelay(2); + reset_control_deassert(rst); + } + + // Reserve and map regions + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mqnic->hw_regs_size = resource_size(res); + mqnic->hw_regs_phys = res->start; + + dev_info(dev, "Control BAR size: %llu", mqnic->hw_regs_size); + mqnic->hw_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mqnic->hw_addr)) { + ret = PTR_ERR(mqnic->hw_addr); + dev_err(dev, "Failed to map control BAR"); + goto fail; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (res) { + void __iomem *hw_addr; + + mqnic->app_hw_regs_size = resource_size(res); + mqnic->app_hw_regs_phys = res->start; + + dev_info(dev, "Application BAR size: %llu", mqnic->app_hw_regs_size); + hw_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hw_addr)) { + ret = PTR_ERR(hw_addr); + dev_err(dev, "Failed to map application BAR"); + goto fail; + } + mqnic->app_hw_addr = hw_addr; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (res) { + void __iomem *hw_addr; + + mqnic->ram_hw_regs_size = resource_size(res); + mqnic->ram_hw_regs_phys = res->start; + + dev_info(dev, "RAM BAR size: %llu", mqnic->ram_hw_regs_size); + hw_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hw_addr)) { + ret = PTR_ERR(hw_addr); + dev_err(dev, "Failed to map RAM BAR"); + goto fail; + } + mqnic->ram_hw_addr = hw_addr; + } + + // Set up interrupts + ret = mqnic_irq_init_platform(mqnic); + if (ret) { + dev_err(dev, "Failed to set up interrupts"); + goto fail; + } + + // Common init + ret = mqnic_common_probe(mqnic); + if (ret) + goto fail; + + // probe complete + return 0; + + // error handling +fail: + mqnic_free_id(mqnic); + mqnic_devlink_free(devlink); + return ret; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0) +static void mqnic_platform_remove(struct platform_device *pdev) +#else +static int mqnic_platform_remove(struct platform_device *pdev) +#endif +{ + struct mqnic_dev *mqnic = platform_get_drvdata(pdev); + struct devlink *devlink = priv_to_devlink(mqnic); + + dev_info(&pdev->dev, DRIVER_NAME " platform remove"); + + mqnic_common_remove(mqnic); + + mqnic_free_id(mqnic); + mqnic_devlink_free(devlink); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0) + return; +#else + return 0; +#endif +} + +static struct platform_driver mqnic_platform_driver = { + .probe = mqnic_platform_probe, + .remove = mqnic_platform_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = of_match_ptr(mqnic_of_id_table), + }, +}; + +static int __init mqnic_init(void) +{ + int rc; + +#ifdef CONFIG_PCI + rc = pci_register_driver(&mqnic_pci_driver); + if (rc) + return rc; +#endif + + rc = platform_driver_register(&mqnic_platform_driver); + if (rc) + goto err; + + return 0; + +err: +#ifdef CONFIG_PCI + pci_unregister_driver(&mqnic_pci_driver); +#endif + return rc; +} + +static void __exit mqnic_exit(void) +{ + platform_driver_unregister(&mqnic_platform_driver); + +#ifdef CONFIG_PCI + pci_unregister_driver(&mqnic_pci_driver); +#endif +} + +module_init(mqnic_init); +module_exit(mqnic_exit); diff --git a/modules/mqnic_vf/mqnic_netdev.c b/modules/mqnic_vf/mqnic_netdev.c new file mode 100644 index 0000000..0d14209 --- /dev/null +++ b/modules/mqnic_vf/mqnic_netdev.c @@ -0,0 +1,691 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +#include + +int mqnic_start_port(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_if *iface = priv->interface; + struct mqnic_ring *q; + struct mqnic_cq *cq; + struct radix_tree_iter iter; + void **slot; + int k; + int ret; + u32 desc_block_size; + + netdev_info(ndev, "%s on interface %d netdev %d", __func__, + priv->interface->index, priv->index); + + netif_set_real_num_tx_queues(ndev, priv->txq_count); + netif_set_real_num_rx_queues(ndev, priv->rxq_count); + + desc_block_size = min_t(u32, priv->interface->max_desc_block_size, 4); + + // set up RX queues + for (k = 0; k < priv->rxq_count; k++) { + // create CQ + cq = mqnic_create_cq(iface); + if (IS_ERR_OR_NULL(cq)) { + ret = PTR_ERR(cq); + goto fail; + } + + ret = mqnic_open_cq(cq, iface->eq[k % iface->eq_count], priv->rx_ring_size); + if (ret) { + mqnic_destroy_cq(cq); + goto fail; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) + netif_napi_add(ndev, &cq->napi, mqnic_poll_rx_cq); +#else + netif_napi_add(ndev, &cq->napi, mqnic_poll_rx_cq, NAPI_POLL_WEIGHT); +#endif + napi_enable(&cq->napi); + + mqnic_arm_cq(cq); + + // create RX queue + q = mqnic_create_rx_ring(iface); + if (IS_ERR_OR_NULL(q)) { + ret = PTR_ERR(q); + mqnic_destroy_cq(cq); + goto fail; + } + + q->mtu = ndev->mtu; + if (ndev->mtu + ETH_HLEN <= PAGE_SIZE) + q->page_order = 0; + else + q->page_order = ilog2((ndev->mtu + ETH_HLEN + PAGE_SIZE - 1) / PAGE_SIZE - 1) + 1; + + ret = mqnic_open_rx_ring(q, priv, cq, priv->rx_ring_size, 1); + if (ret) { + mqnic_destroy_rx_ring(q); + mqnic_destroy_cq(cq); + goto fail; + } + + down_write(&priv->rxq_table_sem); + ret = radix_tree_insert(&priv->rxq_table, k, q); + up_write(&priv->rxq_table_sem); + if (ret) { + mqnic_destroy_rx_ring(q); + mqnic_destroy_cq(cq); + goto fail; + } + } + + // set up TX queues + for (k = 0; k < priv->txq_count; k++) { + // create CQ + cq = mqnic_create_cq(iface); + if (IS_ERR_OR_NULL(cq)) { + ret = PTR_ERR(cq); + goto fail; + } + + ret = mqnic_open_cq(cq, iface->eq[k % iface->eq_count], priv->tx_ring_size); + if (ret) { + mqnic_destroy_cq(cq); + goto fail; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) + netif_napi_add_tx(ndev, &cq->napi, mqnic_poll_tx_cq); +#else + netif_tx_napi_add(ndev, &cq->napi, mqnic_poll_tx_cq, NAPI_POLL_WEIGHT); +#endif + napi_enable(&cq->napi); + + mqnic_arm_cq(cq); + + // create TX queue + q = mqnic_create_tx_ring(iface); + if (IS_ERR_OR_NULL(q)) { + ret = PTR_ERR(q); + mqnic_destroy_cq(cq); + goto fail; + } + + q->tx_queue = netdev_get_tx_queue(ndev, k); + + ret = mqnic_open_tx_ring(q, priv, cq, priv->tx_ring_size, desc_block_size); + if (ret) { + mqnic_destroy_tx_ring(q); + mqnic_destroy_cq(cq); + goto fail; + } + + down_write(&priv->txq_table_sem); + ret = radix_tree_insert(&priv->txq_table, k, q); + up_write(&priv->txq_table_sem); + if (ret) { + mqnic_destroy_tx_ring(q); + mqnic_destroy_cq(cq); + goto fail; + } + } + + // set MTU + mqnic_interface_set_tx_mtu(iface, ndev->mtu + ETH_HLEN); + mqnic_interface_set_rx_mtu(iface, ndev->mtu + ETH_HLEN); + + // configure RX indirection and RSS + mqnic_update_indir_table(ndev); + + priv->port_up = true; + + // enable TX and RX queues + down_read(&priv->txq_table_sem); + radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + mqnic_enable_tx_ring(q); + } + up_read(&priv->txq_table_sem); + + down_read(&priv->rxq_table_sem); + radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + mqnic_enable_rx_ring(q); + } + up_read(&priv->rxq_table_sem); + + mqnic_port_set_tx_ctrl(priv->port, MQNIC_PORT_TX_CTRL_EN); + + // enable scheduler + mqnic_activate_sched_block(priv->sched_block); + + netif_tx_start_all_queues(ndev); + netif_device_attach(ndev); + + if (mqnic_link_status_poll) { + priv->link_status = 0; + mod_timer(&priv->link_status_timer, + jiffies + msecs_to_jiffies(mqnic_link_status_poll)); + } else { + netif_carrier_on(ndev); + } + + mqnic_port_set_rx_ctrl(priv->port, MQNIC_PORT_RX_CTRL_EN); + + return 0; + +fail: + mqnic_stop_port(ndev); + return ret; +} + +void mqnic_stop_port(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_cq *cq; + struct radix_tree_iter iter; + void **slot; + + netdev_info(ndev, "%s on interface %d netdev %d", __func__, + priv->interface->index, priv->index); + + if (mqnic_link_status_poll) + del_timer_sync(&priv->link_status_timer); + + mqnic_port_set_rx_ctrl(priv->port, 0); + + netif_tx_lock_bh(ndev); +// if (detach) +// netif_device_detach(ndev); + netif_tx_stop_all_queues(ndev); + netif_tx_unlock_bh(ndev); + + netif_carrier_off(ndev); + netif_tx_disable(ndev); + + spin_lock_bh(&priv->stats_lock); + mqnic_update_stats(ndev); + spin_unlock_bh(&priv->stats_lock); + + // disable scheduler + mqnic_deactivate_sched_block(priv->sched_block); + + // disable TX and RX queues + down_read(&priv->txq_table_sem); + radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + mqnic_disable_tx_ring(q); + } + up_read(&priv->txq_table_sem); + + down_read(&priv->rxq_table_sem); + radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + mqnic_disable_rx_ring(q); + } + up_read(&priv->rxq_table_sem); + + msleep(20); + + mqnic_port_set_tx_ctrl(priv->port, 0); + + priv->port_up = false; + + // shut down NAPI and clean queues + down_write(&priv->txq_table_sem); + radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + cq = q->cq; + napi_disable(&cq->napi); + netif_napi_del(&cq->napi); + mqnic_close_tx_ring(q); + mqnic_destroy_tx_ring(q); + radix_tree_delete(&priv->txq_table, iter.index); + mqnic_close_cq(cq); + mqnic_destroy_cq(cq); + } + up_write(&priv->txq_table_sem); + + down_write(&priv->rxq_table_sem); + radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + cq = q->cq; + napi_disable(&cq->napi); + netif_napi_del(&cq->napi); + mqnic_close_rx_ring(q); + mqnic_destroy_rx_ring(q); + radix_tree_delete(&priv->rxq_table, iter.index); + mqnic_close_cq(cq); + mqnic_destroy_cq(cq); + } + up_write(&priv->rxq_table_sem); +} + +static int mqnic_open(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_dev *mdev = priv->mdev; + int ret = 0; + + mutex_lock(&mdev->state_lock); + + ret = mqnic_start_port(ndev); + + if (ret) + netdev_err(ndev, "Failed to start port on interface %d netdev %d: %d", + priv->interface->index, priv->index, ret); + + mutex_unlock(&mdev->state_lock); + return ret; +} + +static int mqnic_close(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_dev *mdev = priv->mdev; + int ret = 0; + + mutex_lock(&mdev->state_lock); + + mqnic_stop_port(ndev); + + mutex_unlock(&mdev->state_lock); + return ret; +} + +int mqnic_update_indir_table(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_if *iface = priv->interface; + struct mqnic_ring *q; + int k; + + mqnic_interface_set_rx_queue_map_rss_mask(iface, 0, 0xffffffff); + mqnic_interface_set_rx_queue_map_app_mask(iface, 0, 0); + + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) { + rcu_read_lock(); + q = radix_tree_lookup(&priv->rxq_table, priv->rx_queue_map_indir_table[k]); + rcu_read_unlock(); + + if (q) + mqnic_interface_set_rx_queue_map_indir_table(iface, 0, k, q->index); + } + + return 0; +} + +void mqnic_update_stats(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct radix_tree_iter iter; + void **slot; + unsigned long packets, bytes; + unsigned long dropped; + + if (unlikely(!priv->port_up)) + return; + + packets = 0; + bytes = 0; + dropped = 0; + down_read(&priv->rxq_table_sem); + radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { + const struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + packets += READ_ONCE(q->packets); + bytes += READ_ONCE(q->bytes); + dropped += READ_ONCE(q->dropped_packets); + } + up_read(&priv->rxq_table_sem); + ndev->stats.rx_packets = packets; + ndev->stats.rx_bytes = bytes; + ndev->stats.rx_dropped = dropped; + + packets = 0; + bytes = 0; + dropped = 0; + down_read(&priv->txq_table_sem); + radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { + const struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + packets += READ_ONCE(q->packets); + bytes += READ_ONCE(q->bytes); + dropped += READ_ONCE(q->dropped_packets); + } + up_read(&priv->txq_table_sem); + ndev->stats.tx_packets = packets; + ndev->stats.tx_bytes = bytes; + ndev->stats.tx_dropped = dropped; +} + +static void mqnic_get_stats64(struct net_device *ndev, + struct rtnl_link_stats64 *stats) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + spin_lock_bh(&priv->stats_lock); + mqnic_update_stats(ndev); + netdev_stats_to_stats64(stats, &ndev->stats); + spin_unlock_bh(&priv->stats_lock); +} + +static int mqnic_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct hwtstamp_config hwts_config; + + if (copy_from_user(&hwts_config, ifr->ifr_data, sizeof(hwts_config))) + return -EFAULT; + + if (hwts_config.flags) + return -EINVAL; + + switch (hwts_config.tx_type) { + case HWTSTAMP_TX_OFF: + case HWTSTAMP_TX_ON: + break; + default: + return -ERANGE; + } + + switch (hwts_config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + break; + case HWTSTAMP_FILTER_ALL: + case HWTSTAMP_FILTER_SOME: + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + case HWTSTAMP_FILTER_NTP_ALL: + hwts_config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + default: + return -ERANGE; + } + + memcpy(&priv->hwts_config, &hwts_config, sizeof(hwts_config)); + + if (copy_to_user(ifr->ifr_data, &hwts_config, sizeof(hwts_config))) + return -EFAULT; + + return 0; +} + +static int mqnic_hwtstamp_get(struct net_device *ndev, struct ifreq *ifr) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + if (copy_to_user(ifr->ifr_data, &priv->hwts_config, sizeof(priv->hwts_config))) + return -EFAULT; + + return 0; +} + +static int mqnic_change_mtu(struct net_device *ndev, int new_mtu) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_dev *mdev = priv->mdev; + + if (new_mtu < ndev->min_mtu || new_mtu > ndev->max_mtu) { + netdev_err(ndev, "Bad MTU: %d", new_mtu); + return -EPERM; + } + + netdev_info(ndev, "New MTU: %d", new_mtu); + + ndev->mtu = new_mtu; + + if (netif_running(ndev)) { + mutex_lock(&mdev->state_lock); + + mqnic_stop_port(ndev); + mqnic_start_port(ndev); + + mutex_unlock(&mdev->state_lock); + } + + return 0; +} + +static int mqnic_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) +{ + switch (cmd) { + case SIOCSHWTSTAMP: + return mqnic_hwtstamp_set(ndev, ifr); + case SIOCGHWTSTAMP: + return mqnic_hwtstamp_get(ndev, ifr); + default: + return -EOPNOTSUPP; + } +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) +static struct devlink_port *mqnic_get_devlink_port(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + return priv->dl_port; +} +#endif + +static const struct net_device_ops mqnic_netdev_ops = { + .ndo_open = mqnic_open, + .ndo_stop = mqnic_close, + .ndo_start_xmit = mqnic_start_xmit, + .ndo_get_stats64 = mqnic_get_stats64, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = mqnic_change_mtu, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) + .ndo_eth_ioctl = mqnic_ioctl, +#else + .ndo_do_ioctl = mqnic_ioctl, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) + .ndo_get_devlink_port = mqnic_get_devlink_port, +#endif +}; + +static void mqnic_link_status_timeout(struct timer_list *timer) +{ + struct mqnic_priv *priv = from_timer(priv, timer, link_status_timer); + unsigned int up = 1; + + if (!(mqnic_port_get_tx_ctrl(priv->port) & MQNIC_PORT_TX_CTRL_STATUS)) + up = 0; + if (!(mqnic_port_get_rx_ctrl(priv->port) & MQNIC_PORT_RX_CTRL_STATUS)) + up = 0; + + if (up) { + if (!priv->link_status) { + netif_carrier_on(priv->ndev); + priv->link_status = !priv->link_status; + } + } else { + if (priv->link_status) { + netif_carrier_off(priv->ndev); + priv->link_status = !priv->link_status; + } + } + + mod_timer(&priv->link_status_timer, jiffies + msecs_to_jiffies(mqnic_link_status_poll)); +} + +struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, + struct mqnic_port *port, struct mqnic_sched_block *sched_block) +{ + struct mqnic_dev *mdev = interface->mdev; + struct device *dev = interface->dev; + struct net_device *ndev; + struct mqnic_priv *priv; + int ret = 0; + int k; + u32 desc_block_size; + + ndev = alloc_etherdev_mqs(sizeof(*priv), mqnic_res_get_count(interface->txq_res), + mqnic_res_get_count(interface->rxq_res)); + if (!ndev) { + dev_err(dev, "Failed to allocate memory"); + return ERR_PTR(-ENOMEM); + } + + SET_NETDEV_DEV(ndev, dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0) + SET_NETDEV_DEVLINK_PORT(ndev, &port->dl_port); +#endif + ndev->dev_port = port->phys_index; + + // init private data + priv = netdev_priv(ndev); + memset(priv, 0, sizeof(struct mqnic_priv)); + + spin_lock_init(&priv->stats_lock); + + priv->ndev = ndev; + priv->mdev = interface->mdev; + priv->dl_port = &port->dl_port; + priv->interface = interface; + priv->dev = dev; + priv->index = index; + priv->port = port; + priv->port_up = false; + priv->sched_block = sched_block; + + // associate interface resources + priv->if_features = interface->if_features; + + priv->txq_count = min_t(u32, mqnic_res_get_count(interface->txq_res), 256); + priv->rxq_count = min_t(u32, mqnic_res_get_count(interface->rxq_res), num_online_cpus()); + + priv->tx_ring_size = roundup_pow_of_two(clamp_t(u32, mqnic_num_txq_entries, + MQNIC_MIN_TX_RING_SZ, MQNIC_MAX_TX_RING_SZ)); + priv->rx_ring_size = roundup_pow_of_two(clamp_t(u32, mqnic_num_rxq_entries, + MQNIC_MIN_RX_RING_SZ, MQNIC_MAX_RX_RING_SZ)); + + init_rwsem(&priv->txq_table_sem); + INIT_RADIX_TREE(&priv->txq_table, GFP_KERNEL); + + init_rwsem(&priv->rxq_table_sem); + INIT_RADIX_TREE(&priv->rxq_table, GFP_KERNEL); + + netif_set_real_num_tx_queues(ndev, priv->txq_count); + netif_set_real_num_rx_queues(ndev, priv->rxq_count); + + // set MAC + ndev->addr_len = ETH_ALEN; + + if (ndev->dev_port >= mdev->mac_count) { + dev_warn(dev, "Exhausted permanent MAC addresses; using random MAC"); + eth_hw_addr_random(ndev); + } else { + u8 mac[ETH_ALEN]; + + memcpy(mac, mdev->mac_list[ndev->dev_port], ETH_ALEN); + mac[ETH_ALEN-1] += interface->mac; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) + eth_hw_addr_set(ndev, mac); +#else + memcpy(ndev->dev_addr, mac, ETH_ALEN); +#endif + + if (!is_valid_ether_addr(ndev->dev_addr)) { + dev_warn(dev, "Invalid MAC address in list; using random MAC"); + eth_hw_addr_random(ndev); + } + } + + priv->hwts_config.flags = 0; + priv->hwts_config.tx_type = HWTSTAMP_TX_OFF; + priv->hwts_config.rx_filter = HWTSTAMP_FILTER_NONE; + + desc_block_size = min_t(u32, interface->max_desc_block_size, 4); + + priv->rx_queue_map_indir_table_size = interface->rx_queue_map_indir_table_size; + priv->rx_queue_map_indir_table = kzalloc(sizeof(u32)*priv->rx_queue_map_indir_table_size, GFP_KERNEL); + if (!priv->rx_queue_map_indir_table) { + ret = -ENOMEM; + goto fail; + } + + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) + priv->rx_queue_map_indir_table[k] = k % priv->rxq_count; + + // entry points + ndev->netdev_ops = &mqnic_netdev_ops; + ndev->ethtool_ops = &mqnic_ethtool_ops; + + // set up features + ndev->hw_features = NETIF_F_SG; + + if (priv->if_features & MQNIC_IF_FEATURE_RX_CSUM) + ndev->hw_features |= NETIF_F_RXCSUM; + + if (priv->if_features & MQNIC_IF_FEATURE_TX_CSUM) + ndev->hw_features |= NETIF_F_HW_CSUM; + + ndev->features = ndev->hw_features | NETIF_F_HIGHDMA; + ndev->hw_features |= 0; + + ndev->min_mtu = ETH_MIN_MTU; + ndev->max_mtu = 1500; + + if (interface->max_tx_mtu && interface->max_rx_mtu) + ndev->max_mtu = min(interface->max_tx_mtu, interface->max_rx_mtu) - ETH_HLEN; + + netif_carrier_off(ndev); + if (mqnic_link_status_poll) + timer_setup(&priv->link_status_timer, mqnic_link_status_timeout, 0); + + ret = register_netdev(ndev); + if (ret) { + dev_err(dev, "netdev registration failed on interface %d netdev %d: %d", + priv->interface->index, priv->index, ret); + goto fail; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) + devlink_port_type_eth_set(&port->dl_port, ndev); +#endif + + priv->registered = 1; + + return ndev; + +fail: + mqnic_destroy_netdev(ndev); + return ERR_PTR(ret); +} + +void mqnic_destroy_netdev(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + if (priv->registered) + unregister_netdev(ndev); + + kfree(priv->rx_queue_map_indir_table); + + #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) + devlink_port_type_clear(priv->dl_port); + #endif + + free_netdev(ndev); +} diff --git a/modules/mqnic_vf/mqnic_port.c b/modules/mqnic_vf/mqnic_port.c new file mode 120000 index 0000000..4e26d16 --- /dev/null +++ b/modules/mqnic_vf/mqnic_port.c @@ -0,0 +1 @@ +../mqnic/mqnic_port.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_ptp.c b/modules/mqnic_vf/mqnic_ptp.c new file mode 120000 index 0000000..10d5fe4 --- /dev/null +++ b/modules/mqnic_vf/mqnic_ptp.c @@ -0,0 +1 @@ +../mqnic/mqnic_ptp.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_reg_block.c b/modules/mqnic_vf/mqnic_reg_block.c new file mode 120000 index 0000000..51fd2c9 --- /dev/null +++ b/modules/mqnic_vf/mqnic_reg_block.c @@ -0,0 +1 @@ +../mqnic/mqnic_reg_block.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_res.c b/modules/mqnic_vf/mqnic_res.c new file mode 120000 index 0000000..9f83623 --- /dev/null +++ b/modules/mqnic_vf/mqnic_res.c @@ -0,0 +1 @@ +../mqnic/mqnic_res.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_rx.c b/modules/mqnic_vf/mqnic_rx.c new file mode 120000 index 0000000..1a7e933 --- /dev/null +++ b/modules/mqnic_vf/mqnic_rx.c @@ -0,0 +1 @@ +../mqnic/mqnic_rx.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_sched_block.c b/modules/mqnic_vf/mqnic_sched_block.c new file mode 120000 index 0000000..ea8fcc6 --- /dev/null +++ b/modules/mqnic_vf/mqnic_sched_block.c @@ -0,0 +1 @@ +../mqnic/mqnic_sched_block.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_scheduler.c b/modules/mqnic_vf/mqnic_scheduler.c new file mode 120000 index 0000000..4a5321d --- /dev/null +++ b/modules/mqnic_vf/mqnic_scheduler.c @@ -0,0 +1 @@ +../mqnic/mqnic_scheduler.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_stats.c b/modules/mqnic_vf/mqnic_stats.c new file mode 120000 index 0000000..c35a5b1 --- /dev/null +++ b/modules/mqnic_vf/mqnic_stats.c @@ -0,0 +1 @@ +../mqnic/mqnic_stats.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_tx.c b/modules/mqnic_vf/mqnic_tx.c new file mode 120000 index 0000000..f5bfc0f --- /dev/null +++ b/modules/mqnic_vf/mqnic_tx.c @@ -0,0 +1 @@ +../mqnic/mqnic_tx.c \ No newline at end of file diff --git a/utils/.gitignore b/utils/.gitignore new file mode 100644 index 0000000..dde5a23 --- /dev/null +++ b/utils/.gitignore @@ -0,0 +1,6 @@ +mqnic-config +mqnic-bmc +mqnic-dump +mqnic-fw +mqnic-xcvr +perout diff --git a/utils/Makefile b/utils/Makefile new file mode 100644 index 0000000..eddb80a --- /dev/null +++ b/utils/Makefile @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: BSD-2-Clause-Views +# Copyright (c) 2019-2023 The Regents of the University of California + +PREFIX ?= /usr/local +BINDIR = $(DESTDIR)$(PREFIX)/bin + +CC ?= gcc +CFLAGS ?= -O3 + +CFLAGS += -Wall +CPPFLAGS += -Ilib -Iinclude +LDFLAGS += -Llib/mqnic +LDLIBS += -lmqnic + +LIBMQNIC = lib/mqnic/libmqnic.a + +BIN = mqnic-config +BIN += mqnic-dump +BIN += mqnic-fw +BIN += mqnic-bmc +BIN += mqnic-xcvr +BIN += perout + +GENDEPFLAGS = -MD -MP -MF .$(@F).d + +ALL_CFLAGS = $(CFLAGS) $(CPPFLAGS) $(GENDEPFLAGS) + +all: $(BIN) + +FORCE: + +$(LIBMQNIC): FORCE + $(MAKE) -C $(dir $@) $(notdir $@) + +%.o: %.c + $(CC) $(ALL_CFLAGS) -c -o $@ $< + +mqnic-config: mqnic-config.o timespec.o $(LIBMQNIC) + $(CC) $(ALL_CFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS) + +mqnic-dump: mqnic-dump.o $(LIBMQNIC) + $(CC) $(ALL_CFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS) + +mqnic-fw: mqnic-fw.o flash.o flash_spi.o flash_bpi.o bitfile.o $(LIBMQNIC) + $(CC) $(ALL_CFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS) + +mqnic-bmc: mqnic-bmc.o $(LIBMQNIC) + $(CC) $(ALL_CFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS) + +mqnic-xcvr: mqnic-xcvr.o $(LIBMQNIC) drp.o xcvr_gt.o xcvr_gthe3.o xcvr_gtye3.o xcvr_gthe4.o xcvr_gtye4.o + $(CC) $(ALL_CFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS) + +perout: perout.o timespec.o + $(CC) $(ALL_CFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS) + +install: + install -d $(BINDIR) + install -m 0755 $(BIN) $(BINDIR) + +clean: + rm -f $(BIN) + rm -f *.o + rm -f .*.d + $(MAKE) -C $(dir $(LIBMQNIC))/ $@ + +-include $(wildcard .*.d) + +.PHONY: all install clean FORCE diff --git a/utils/bitfile.c b/utils/bitfile.c new file mode 100644 index 0000000..f34efd2 --- /dev/null +++ b/utils/bitfile.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2020-2023 The Regents of the University of California + */ + +#include +#include +#include + +#include "bitfile.h" + +struct bitfile *bitfile_create_from_file(const char *bit_file_name) +{ + struct bitfile *bf; + FILE *fp; + char *buffer; + char *data; + size_t len; + + fp = fopen(bit_file_name, "rb"); + + if (!fp) + { + fprintf(stderr, "Failed to open file\n"); + return 0; + } + + fseek(fp, 0, SEEK_END); + len = ftell(fp); + rewind(fp); + + buffer = calloc(len + sizeof(struct bitfile), 1); + + if (!buffer) + { + fprintf(stderr, "Failed to allocate memory\n"); + goto fail_file; + } + + bf = (struct bitfile *)buffer; + data = buffer + sizeof(struct bitfile); + + if (fread(data, 1, len, fp) < len) + { + fprintf(stderr, "Error reading file\n"); + goto fail_buffer; + } + + fclose(fp); + + if (bitfile_parse(bf, data, len)) + { + fprintf(stderr, "Failed to parse bitfile\n"); + goto fail_buffer; + } + + return bf; + +fail_buffer: + free(buffer); +fail_file: + fclose(fp); + return 0; +} + +struct bitfile *bitfile_create_from_buffer(char *buffer, size_t len) +{ + struct bitfile *bf; + + bf = calloc(1, sizeof(struct bitfile)); + + if (!bf) + { + fprintf(stderr, "Failed to allocate memory\n"); + return 0; + } + + if (bitfile_parse(bf, buffer, len)) + { + fprintf(stderr, "Failed to parse bitfile\n"); + free(bf); + return 0; + } + + return bf; +} + +int bitfile_parse(struct bitfile *bf, char *buffer, size_t len) +{ + char *ptr; + size_t l; + + ptr = buffer; + + bf->header = ptr; + + // drop unknown field + l = be16toh(*((uint16_t *)ptr)); + ptr += 2+l; + + // drop unknown field + ptr += 2; + + while (1) + { + int field_type = *ptr; + ptr += 1; + + if (field_type == 'e') + { + l = be32toh(*((uint32_t *)ptr)); + bf->data_len = l; + bf->data = ptr+4; + return 0; + } + else + { + l = be16toh(*((uint16_t *)ptr)); + ptr += 2; + } + + switch (field_type) + { + case 'a': + bf->name = ptr; + break; + case 'b': + bf->part = ptr; + break; + case 'c': + bf->date = ptr; + break; + case 'd': + bf->time = ptr; + break; + default: + fprintf(stderr, "Unknown field type 0x%02x\n", field_type); + goto fail; + } + + ptr += l; + } + +fail: + return -1; +} + +void bitfile_close(struct bitfile *bf) +{ + if (bf) + { + free(bf); + } +} + diff --git a/utils/bitfile.h b/utils/bitfile.h new file mode 100644 index 0000000..5b3ca36 --- /dev/null +++ b/utils/bitfile.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2020-2023 The Regents of the University of California + */ + +#ifndef BITFILE_H +#define BITFILE_H + +struct bitfile { + char *header; + char *name; + char *part; + char *date; + char *time; + + size_t data_len; + char *data; +}; + +struct bitfile *bitfile_create_from_file(const char *bit_file_name); + +struct bitfile *bitfile_create_from_buffer(char *buffer, size_t len); + +int bitfile_parse(struct bitfile *bf, char *buffer, size_t len); + +void bitfile_close(struct bitfile *bf); + +#endif // BITFILE_H diff --git a/utils/drp.c b/utils/drp.c new file mode 100644 index 0000000..4f45c49 --- /dev/null +++ b/utils/drp.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#include +#include + +int drp_rb_reg_read(const struct mqnic_reg_block *rb, uint32_t addr, uint32_t *val) +{ + mqnic_reg_write32(rb->regs, 0x14, addr); + mqnic_reg_write32(rb->regs, 0x10, 0x00000001); + mqnic_reg_read32(rb->regs, 0x10); + if ((mqnic_reg_read32(rb->regs, 0x10) & 0x00000101) != 0) + return -1; + *val = mqnic_reg_read32(rb->regs, 0x1C); + return 0; +} + +int drp_rb_reg_write(const struct mqnic_reg_block *rb, uint32_t addr, uint32_t val) +{ + mqnic_reg_write32(rb->regs, 0x14, addr); + mqnic_reg_write32(rb->regs, 0x18, val); + mqnic_reg_write32(rb->regs, 0x10, 0x00000003); + mqnic_reg_read32(rb->regs, 0x10); + if ((mqnic_reg_read32(rb->regs, 0x10) & 0x00000101) != 0) + return -1; + return 0; +} + +static int drp_rb_reg_if_read32(const struct mqnic_reg_if *reg, ptrdiff_t offset, uint32_t *value) +{ + return drp_rb_reg_read((const struct mqnic_reg_block *)reg->priv, offset, value); +} + +static int drp_rb_reg_if_write32(const struct mqnic_reg_if *reg, ptrdiff_t offset, uint32_t value) +{ + return drp_rb_reg_write((const struct mqnic_reg_block *)reg->priv, offset, value); +} + +static const struct mqnic_reg_if_ops drp_rb_reg_if_ops = { + .read32 = drp_rb_reg_if_read32, + .write32 = drp_rb_reg_if_write32 +}; + +void drp_rb_reg_if_init(struct mqnic_reg_if *reg, struct mqnic_reg_block *rb) +{ + reg->priv = rb; + reg->ops = &drp_rb_reg_if_ops; +} diff --git a/utils/drp.h b/utils/drp.h new file mode 100644 index 0000000..57a4caf --- /dev/null +++ b/utils/drp.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#ifndef DRP_H +#define DRP_H + +#include +#include + +int drp_rb_reg_read(const struct mqnic_reg_block *rb, uint32_t addr, uint32_t *val); +int drp_rb_reg_write(const struct mqnic_reg_block *rb, uint32_t addr, uint32_t val); + +void drp_rb_reg_if_init(struct mqnic_reg_if *reg, struct mqnic_reg_block *rb); + +#endif /* DRP_H */ diff --git a/utils/flash.c b/utils/flash.c new file mode 100644 index 0000000..5948aae --- /dev/null +++ b/utils/flash.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2020-2023 The Regents of the University of California + */ + +#include "flash.h" + +#include + +extern const struct flash_driver spi_flash_driver; +extern const struct flash_driver bpi_flash_driver; + +struct flash_device *flash_open_spi(int data_width, volatile uint8_t *ctrl_reg) +{ + struct flash_device *fdev; + + if (!ctrl_reg) + return NULL; + + fdev = calloc(1, sizeof(struct flash_device)); + + if (!fdev) + return NULL; + + fdev->driver = &spi_flash_driver; + + fdev->data_width = data_width; + + fdev->ctrl_reg = ctrl_reg; + + if (fdev->driver->init(fdev)) + { + goto err; + } + + return fdev; + +err: + flash_release(fdev); + return NULL; +} + +struct flash_device *flash_open_bpi(int data_width, volatile uint8_t *ctrl_reg, volatile uint8_t *addr_reg, volatile uint8_t *data_reg) +{ + struct flash_device *fdev; + + if (!ctrl_reg || !addr_reg || !data_reg) + return NULL; + + fdev = calloc(1, sizeof(struct flash_device)); + + if (!fdev) + return NULL; + + fdev->driver = &bpi_flash_driver; + + fdev->data_width = data_width; + + fdev->ctrl_reg = ctrl_reg; + fdev->addr_reg = addr_reg; + fdev->data_reg = data_reg; + + if (fdev->driver->init(fdev)) + { + goto err; + } + + return fdev; + +err: + flash_release(fdev); + return NULL; +} + +void flash_release(struct flash_device *fdev) +{ + if (!fdev) + return; + + fdev->driver->release(fdev); + + free(fdev); +} + +int flash_read(struct flash_device *fdev, size_t addr, size_t len, void *dest) +{ + if (!fdev) + return -1; + + return fdev->driver->read(fdev, addr, len, dest); +} + +int flash_write(struct flash_device *fdev, size_t addr, size_t len, const void *src) +{ + if (!fdev) + return -1; + + return fdev->driver->write(fdev, addr, len, src); +} + +int flash_erase(struct flash_device *fdev, size_t addr, size_t len) +{ + if (!fdev) + return -1; + + return fdev->driver->erase(fdev, addr, len); +} + diff --git a/utils/flash.h b/utils/flash.h new file mode 100644 index 0000000..1b5c153 --- /dev/null +++ b/utils/flash.h @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2020-2023 The Regents of the University of California + */ + +#ifndef FLASH_H +#define FLASH_H + +#include +#include + +#define FLASH_ERASE_REGIONS 2 + +struct flash_driver; +struct flash_ops; + +struct flash_erase_region_info { + size_t block_count; + size_t block_size; + size_t region_start; + size_t region_end; +}; + +struct flash_device { + const struct flash_driver *driver; + const struct flash_ops *ops; + + volatile uint8_t *ctrl_reg; + volatile uint8_t *addr_reg; + volatile uint8_t *data_reg; + + size_t size; + int data_width; + + size_t write_buffer_size; + size_t erase_block_size; + + int protocol; + int bulk_protocol; + + int read_dummy_cycles; + + int erase_region_count; + struct flash_erase_region_info erase_region[FLASH_ERASE_REGIONS]; +}; + +struct flash_ops { + void (*init)(struct flash_device *fdev); + int (*sector_erase)(struct flash_device *fdev, size_t addr); + int (*buffered_program)(struct flash_device *fdev, size_t addr, size_t len, const void *src); +}; + +struct flash_driver { + int (*init)(struct flash_device *fdev); + void (*release)(struct flash_device *fdev); + int (*read)(struct flash_device *fdev, size_t addr, size_t len, void *dest); + int (*write)(struct flash_device *fdev, size_t addr, size_t len, const void *src); + int (*erase)(struct flash_device *fdev, size_t addr, size_t len); +}; + +struct flash_device *flash_open_spi(int data_width, volatile uint8_t *ctrl_reg); +struct flash_device *flash_open_bpi(int data_width, volatile uint8_t *ctrl_reg, volatile uint8_t *addr_reg, volatile uint8_t *data_reg); +void flash_release(struct flash_device *fdev); +int flash_read(struct flash_device *fdev, size_t addr, size_t len, void *dest); +int flash_write(struct flash_device *fdev, size_t addr, size_t len, const void *src); +int flash_erase(struct flash_device *fdev, size_t addr, size_t len); + +#endif /* FLASH_H */ diff --git a/utils/flash_bpi.c b/utils/flash_bpi.c new file mode 100644 index 0000000..47bd1d4 --- /dev/null +++ b/utils/flash_bpi.c @@ -0,0 +1,643 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2020-2023 The Regents of the University of California + */ + +#include "flash.h" + +#include +#include + +#define reg_read32(reg) (*((volatile uint32_t *)(reg))) +#define reg_write32(reg, val) (*((volatile uint32_t *)(reg))) = (val) + +#define CFI_QUERY_ADDR 0x55 +#define CFI_QUERY_DATA 0x98 +#define CFI_READ_ARRAY 0xFF +#define CFI_READ_ARRAY_ALT 0xF0 +#define CFI_ID_0 0x10 +#define CFI_ID_1 0x11 +#define CFI_ID_2 0x12 +#define CFI_PRI_CMD_SET_0 0x13 +#define CFI_PRI_CMD_SET_1 0x14 +#define CFI_DEVICE_SIZE 0x27 +#define CFI_WRITE_BUFFER_SIZE_0 0x2A +#define CFI_WRITE_BUFFER_SIZE_1 0x2B +#define CFI_ERASE_REGION_COUNT 0x2C +#define CFI_ERASE_REGION_1_INFO_0 0x2D +#define CFI_ERASE_REGION_1_INFO_1 0x2E +#define CFI_ERASE_REGION_1_INFO_2 0x2F +#define CFI_ERASE_REGION_1_INFO_3 0x30 +#define CFI_ERASE_REGION_2_INFO_0 0x31 +#define CFI_ERASE_REGION_2_INFO_1 0x32 +#define CFI_ERASE_REGION_2_INFO_2 0x33 +#define CFI_ERASE_REGION_2_INFO_3 0x34 + +#define BPI_INTEL_READ_ARRAY 0xFF +#define BPI_INTEL_READ_STATUS_REG 0x70 +#define BPI_INTEL_READ_ID 0x90 +#define BPI_INTEL_CLEAR_STATUS_REG 0x50 +#define BPI_INTEL_READ_CONFIG_REG_SETUP 0x60 +#define BPI_INTEL_SET_READ_CONFIG_REG 0x03 +#define BPI_INTEL_BLOCK_LOCK_SETUP 0x60 +#define BPI_INTEL_BLOCK_LOCK 0x01 +#define BPI_INTEL_BLOCK_UNLOCK 0xD0 +#define BPI_INTEL_BLOCK_ERASE_SETUP 0x20 +#define BPI_INTEL_BLOCK_ERASE_CONFIRM 0xD0 +#define BPI_INTEL_BUFFERED_PROGRAM_SETUP 0xE8 +#define BPI_INTEL_BUFFERED_PROGRAM_CONFIRM 0xD0 + +#define BPI_AMD_UNLOCK_ADDR_1 0x555 +#define BPI_AMD_UNLOCK_DATA_1 0xAA +#define BPI_AMD_UNLOCK_ADDR_2 0x2AA +#define BPI_AMD_UNLOCK_DATA_2 0x55 +#define BPI_AMD_UNLOCK_BYPASS_ENTER_ADDR 0x555 +#define BPI_AMD_UNLOCK_BYPASS_ENTER_DATA 0x20 +#define BPI_AMD_UNLOCK_BYPASS_RESET_1 0x90 +#define BPI_AMD_UNLOCK_BYPASS_RESET_2 0x00 +#define BPI_AMD_BLOCK_ERASE_SETUP 0x80 +#define BPI_AMD_BLOCK_ERASE_CONFIRM 0x30 +#define BPI_AMD_BUFFERED_PROGRAM_SETUP 0x25 +#define BPI_AMD_BUFFERED_PROGRAM_CONFIRM 0x29 +#define BPI_AMD_READ_ARRAY 0xF0 + +#define BPI_MICRON_READ_ARRAY 0xFF +#define BPI_MICRON_READ_STATUS_REG 0x70 +#define BPI_MICRON_READ_ID 0x90 +#define BPI_MICRON_CLEAR_STATUS_REG 0x50 +#define BPI_MICRON_READ_CONFIG_REG_SETUP 0x60 +#define BPI_MICRON_SET_READ_CONFIG_REG 0x03 +#define BPI_MICRON_BLOCK_LOCK_SETUP 0x60 +#define BPI_MICRON_BLOCK_LOCK 0x01 +#define BPI_MICRON_BLOCK_UNLOCK 0xD0 +#define BPI_MICRON_BLOCK_ERASE_SETUP 0x20 +#define BPI_MICRON_BLOCK_ERASE_CONFIRM 0xD0 +#define BPI_MICRON_BUFFERED_PROGRAM_SETUP 0xE9 +#define BPI_MICRON_BUFFERED_PROGRAM_CONFIRM 0xD0 + +#define FLASH_CE_N (1 << 0) +#define FLASH_OE_N (1 << 1) +#define FLASH_WE_N (1 << 2) +#define FLASH_ADV_N (1 << 3) +#define FLASH_DQ_OE (1 << 8) +#define FLASH_REGION_OE (1 << 16) + +void bpi_flash_set_addr(struct flash_device *fdev, size_t addr) +{ + reg_write32(fdev->addr_reg, addr); +} + +uint16_t bpi_flash_read_cur(struct flash_device *fdev) +{ + uint16_t val; + + reg_write32(fdev->ctrl_reg, FLASH_REGION_OE | FLASH_WE_N); + reg_read32(fdev->data_reg); // dummy read + val = reg_read32(fdev->data_reg); + reg_write32(fdev->ctrl_reg, FLASH_OE_N | FLASH_WE_N | FLASH_ADV_N); + + return val; +} + +uint16_t bpi_flash_read_word(struct flash_device *fdev, size_t addr) +{ + bpi_flash_set_addr(fdev, addr); + return bpi_flash_read_cur(fdev); +} + +void bpi_flash_write_cur(struct flash_device *fdev, uint16_t data) +{ + reg_write32(fdev->data_reg, data); + reg_write32(fdev->ctrl_reg, FLASH_REGION_OE | FLASH_DQ_OE | FLASH_OE_N); + reg_read32(fdev->data_reg); // dummy read + reg_write32(fdev->ctrl_reg, FLASH_OE_N | FLASH_WE_N | FLASH_ADV_N); +} + +void bpi_flash_write_word(struct flash_device *fdev, size_t addr, uint16_t data) +{ + bpi_flash_set_addr(fdev, addr); + bpi_flash_write_cur(fdev, data); +} + +void bpi_flash_deselect(struct flash_device *fdev) +{ + bpi_flash_write_word(fdev, 0, CFI_READ_ARRAY); + reg_write32(fdev->ctrl_reg, FLASH_CE_N | FLASH_OE_N | FLASH_WE_N | FLASH_ADV_N); +} + +// Intel flash ops (0x0001) + +uint16_t bpi_flash_intel_read_status_register(struct flash_device *fdev) +{ + bpi_flash_write_cur(fdev, BPI_INTEL_READ_STATUS_REG); + return bpi_flash_read_cur(fdev); +} + +void bpi_flash_intel_clear_status_register(struct flash_device *fdev) +{ + bpi_flash_write_cur(fdev, BPI_INTEL_CLEAR_STATUS_REG); +} + +void bpi_flash_intel_init(struct flash_device *fdev) +{ + bpi_flash_intel_clear_status_register(fdev); +} + +int bpi_flash_intel_sector_erase(struct flash_device *fdev, size_t addr) +{ + bpi_flash_set_addr(fdev, addr); + bpi_flash_write_cur(fdev, BPI_INTEL_BLOCK_LOCK_SETUP); + bpi_flash_write_cur(fdev, BPI_INTEL_BLOCK_UNLOCK); + + if (bpi_flash_intel_read_status_register(fdev) & 0x30) + { + fprintf(stderr, "Failed to unlock block\n"); + return -1; + } + + bpi_flash_write_cur(fdev, BPI_INTEL_BLOCK_ERASE_SETUP); + bpi_flash_write_cur(fdev, BPI_INTEL_BLOCK_ERASE_CONFIRM); + + while (!(bpi_flash_intel_read_status_register(fdev) & 0x80)) {}; + + if (bpi_flash_intel_read_status_register(fdev) & 0x30) + { + fprintf(stderr, "Failed to erase block\n"); + return -1; + } + + return 0; +} + +int bpi_flash_intel_buffered_program(struct flash_device *fdev, size_t addr, size_t len, const void *src) +{ + const uint8_t *s = (const uint8_t *)src; + + bpi_flash_set_addr(fdev, addr); + bpi_flash_write_cur(fdev, BPI_INTEL_BUFFERED_PROGRAM_SETUP); + bpi_flash_write_cur(fdev, len-1); + + for (size_t i = 0; i < len; i++) + { + bpi_flash_write_word(fdev, addr+i, s[0] | (s[1] << 8)); + s += 2; + } + + bpi_flash_set_addr(fdev, addr); + bpi_flash_write_cur(fdev, BPI_INTEL_BUFFERED_PROGRAM_CONFIRM); + + while (!(bpi_flash_intel_read_status_register(fdev) & 0x80)) {}; + + if (bpi_flash_intel_read_status_register(fdev) & 0x30) + { + fprintf(stderr, "Failed to write block\n"); + return -1; + } + + return 0; +} + +const struct flash_ops bpi_flash_intel_ops = { + .init = bpi_flash_intel_init, + .sector_erase = bpi_flash_intel_sector_erase, + .buffered_program = bpi_flash_intel_buffered_program +}; + +// AMD flash ops (0x0002) + +void bpi_flash_amd_unlock(struct flash_device *fdev) +{ + bpi_flash_write_word(fdev, BPI_AMD_UNLOCK_ADDR_1, BPI_AMD_UNLOCK_DATA_1); + bpi_flash_write_word(fdev, BPI_AMD_UNLOCK_ADDR_2, BPI_AMD_UNLOCK_DATA_2); +} + +void bpi_flash_amd_write_buffer_abort_reset(struct flash_device *fdev) +{ + bpi_flash_amd_unlock(fdev); + bpi_flash_write_word(fdev, BPI_AMD_UNLOCK_ADDR_1, BPI_AMD_READ_ARRAY); +} + +void bpi_flash_amd_init(struct flash_device *fdev) +{ + // write-to-buffer-abort reset (just in case) + bpi_flash_amd_write_buffer_abort_reset(fdev); +} + +int bpi_flash_amd_wait_for_operation(struct flash_device *fdev, uint16_t stop_mask) +{ + uint16_t read_1, read_2, read_3; + + while (1) + { + read_1 = bpi_flash_read_cur(fdev); + read_2 = bpi_flash_read_cur(fdev); + read_3 = bpi_flash_read_cur(fdev); + + if ((read_1 ^ read_2) & (read_2 ^ read_3) & 0x40) + { + if (read_1 & stop_mask) + { + return read_1; + } + } + else + { + return 0; + } + } +} + +int bpi_flash_amd_sector_erase(struct flash_device *fdev, size_t addr) +{ + bpi_flash_amd_unlock(fdev); + bpi_flash_write_word(fdev, BPI_AMD_UNLOCK_ADDR_1, BPI_AMD_BLOCK_ERASE_SETUP); + bpi_flash_amd_unlock(fdev); + bpi_flash_write_word(fdev, addr, BPI_AMD_BLOCK_ERASE_CONFIRM); + + while (!(bpi_flash_read_cur(fdev) & 0x08)) {}; + + if (bpi_flash_amd_wait_for_operation(fdev, 0x20) & 0x20) + { + // write-to-buffer-abort reset + bpi_flash_amd_write_buffer_abort_reset(fdev); + + fprintf(stderr, "Failed to erase block\n"); + return -1; + } + + return 0; +} + +int bpi_flash_amd_buffered_program(struct flash_device *fdev, size_t addr, size_t len, const void *src) +{ + const uint8_t *s = (const uint8_t *)src; + + bpi_flash_amd_unlock(fdev); + bpi_flash_write_word(fdev, addr, BPI_AMD_BUFFERED_PROGRAM_SETUP); + bpi_flash_write_cur(fdev, len-1); + + for (size_t i = 0; i < len; i++) + { + bpi_flash_write_word(fdev, addr+i, s[0] | (s[1] << 8)); + s += 2; + } + + bpi_flash_set_addr(fdev, addr); + bpi_flash_write_cur(fdev, BPI_AMD_BUFFERED_PROGRAM_CONFIRM); + + if (bpi_flash_amd_wait_for_operation(fdev, 0x22) & 0x22) + { + // write-to-buffer-abort reset + bpi_flash_amd_write_buffer_abort_reset(fdev); + + fprintf(stderr, "Failed to write block\n"); + return -1; + } + + return 0; +} + +const struct flash_ops bpi_flash_amd_ops = { + .init = bpi_flash_amd_init, + .sector_erase = bpi_flash_amd_sector_erase, + .buffered_program = bpi_flash_amd_buffered_program +}; + +// Micron flash ops (0x0002) + +uint16_t bpi_flash_micron_read_status_register(struct flash_device *fdev) +{ + bpi_flash_write_cur(fdev, BPI_MICRON_READ_STATUS_REG); + return bpi_flash_read_cur(fdev); +} + +void bpi_flash_micron_clear_status_register(struct flash_device *fdev) +{ + bpi_flash_write_cur(fdev, BPI_MICRON_CLEAR_STATUS_REG); +} + +void bpi_flash_micron_init(struct flash_device *fdev) +{ + bpi_flash_micron_clear_status_register(fdev); +} + +int bpi_flash_micron_sector_erase(struct flash_device *fdev, size_t addr) +{ + bpi_flash_set_addr(fdev, addr); + bpi_flash_write_cur(fdev, BPI_MICRON_BLOCK_LOCK_SETUP); + bpi_flash_write_cur(fdev, BPI_MICRON_BLOCK_UNLOCK); + + if (bpi_flash_micron_read_status_register(fdev) & 0x30) + { + fprintf(stderr, "Failed to unlock block\n"); + bpi_flash_write_cur(fdev, CFI_READ_ARRAY); + return -1; + } + + bpi_flash_write_cur(fdev, BPI_MICRON_BLOCK_ERASE_SETUP); + bpi_flash_write_cur(fdev, BPI_MICRON_BLOCK_ERASE_CONFIRM); + + while (!(bpi_flash_micron_read_status_register(fdev) & 0x80)) {}; + + if (bpi_flash_micron_read_status_register(fdev) & 0x30) + { + fprintf(stderr, "Failed to erase block\n"); + bpi_flash_write_cur(fdev, CFI_READ_ARRAY); + return -1; + } + + bpi_flash_write_cur(fdev, CFI_READ_ARRAY); + + return 0; +} + +int bpi_flash_micron_buffered_program(struct flash_device *fdev, size_t addr, size_t len, const void *src) +{ + const uint8_t *s = (const uint8_t *)src; + + bpi_flash_set_addr(fdev, addr); + bpi_flash_write_cur(fdev, BPI_MICRON_BUFFERED_PROGRAM_SETUP); + bpi_flash_write_cur(fdev, len-1); + + for (size_t i = 0; i < len; i++) + { + bpi_flash_write_word(fdev, addr+i, s[0] | (s[1] << 8)); + s += 2; + } + + bpi_flash_set_addr(fdev, addr); + bpi_flash_write_cur(fdev, BPI_MICRON_BUFFERED_PROGRAM_CONFIRM); + + while (!(bpi_flash_micron_read_status_register(fdev) & 0x80)) {}; + + if (bpi_flash_micron_read_status_register(fdev) & 0x30) + { + fprintf(stderr, "Failed to write block\n"); + bpi_flash_write_cur(fdev, CFI_READ_ARRAY); + return -1; + } + + bpi_flash_write_cur(fdev, CFI_READ_ARRAY); + + return 0; +} + +const struct flash_ops bpi_flash_micron_ops = { + .init = bpi_flash_micron_init, + .sector_erase = bpi_flash_micron_sector_erase, + .buffered_program = bpi_flash_micron_buffered_program +}; + + +void bpi_flash_release(struct flash_device *fdev) +{ + bpi_flash_deselect(fdev); +} + +int bpi_flash_init(struct flash_device *fdev) +{ + int ret = 0; + + if (!fdev) + return -1; + + // CFI query + bpi_flash_write_word(fdev, CFI_QUERY_ADDR, CFI_QUERY_DATA); + + if (bpi_flash_read_word(fdev, CFI_ID_0) != 'Q') + { + // may be Intel flash in sync read mode; attempt switch to async + bpi_flash_write_word(fdev, 0xf94f, BPI_INTEL_READ_CONFIG_REG_SETUP); + bpi_flash_write_word(fdev, 0xf94f, BPI_INTEL_SET_READ_CONFIG_REG); + bpi_flash_write_word(fdev, CFI_QUERY_ADDR, CFI_QUERY_DATA); + } + + if (bpi_flash_read_word(fdev, CFI_ID_0) != 'Q' && ((bpi_flash_read_cur(fdev) ^ bpi_flash_read_cur(fdev)) & 0x44)) + { + // may be AMD flash in write buffer abort; perform write buffer abort reset + bpi_flash_amd_write_buffer_abort_reset(fdev); + bpi_flash_write_word(fdev, CFI_QUERY_ADDR, CFI_QUERY_DATA); + } + + if (bpi_flash_read_word(fdev, CFI_ID_0) != 'Q' || + bpi_flash_read_word(fdev, CFI_ID_1) != 'R' || + bpi_flash_read_word(fdev, CFI_ID_2) != 'Y') + { + fprintf(stderr, "Failed to read flash ID\n"); + ret = -1; + goto err; + } + + fdev->protocol = bpi_flash_read_word(fdev, CFI_PRI_CMD_SET_0) | (bpi_flash_read_word(fdev, CFI_PRI_CMD_SET_1) << 8); + + printf("Command set: %d\n", fdev->protocol); + + switch (fdev->protocol) + { + case 0x0001: + // Intel command set (P30) + fdev->ops = &bpi_flash_intel_ops; + break; + case 0x0002: + // AMD command set (S29, MT28) + fdev->ops = &bpi_flash_amd_ops; + break; + case 0x0200: + // Micron + fdev->ops = &bpi_flash_micron_ops; + break; + default: + fprintf(stderr, "Unknown command set: %d\n", fdev->protocol); + ret = -1; + goto err; + } + + uint8_t flash_size = bpi_flash_read_word(fdev, CFI_DEVICE_SIZE); + fdev->size = ((size_t)1) << flash_size; + + printf("Flash size: %d MB\n", 1 << (flash_size-20)); + + uint16_t write_buffer_size = bpi_flash_read_word(fdev, CFI_WRITE_BUFFER_SIZE_0) | (bpi_flash_read_word(fdev, CFI_WRITE_BUFFER_SIZE_1) << 8); + fdev->write_buffer_size = ((size_t)1) << write_buffer_size; + + printf("Write buffer size: %ld B\n", fdev->write_buffer_size); + + fdev->erase_region_count = bpi_flash_read_word(fdev, CFI_ERASE_REGION_COUNT); + + printf("Erase regions: %d\n", fdev->erase_region_count); + + if (fdev->erase_region_count > 0) + { + fdev->erase_region[0].block_count = (bpi_flash_read_word(fdev, CFI_ERASE_REGION_1_INFO_0) | (bpi_flash_read_word(fdev, CFI_ERASE_REGION_1_INFO_1) << 8)) + 1; + fdev->erase_region[0].block_size = (bpi_flash_read_word(fdev, CFI_ERASE_REGION_1_INFO_2) | (bpi_flash_read_word(fdev, CFI_ERASE_REGION_1_INFO_3) << 8)) * 256; + fdev->erase_region[0].region_start = 0; + fdev->erase_region[0].region_end = fdev->erase_region[0].region_start + fdev->erase_region[0].block_count * fdev->erase_region[0].block_size; + + fdev->erase_block_size = fdev->erase_region[0].block_size; + + printf("Erase region 0 block count: %ld\n", fdev->erase_region[0].block_count); + printf("Erase region 0 block size: %ld B\n", fdev->erase_region[0].block_size); + printf("Erase region 0 start: 0x%08lx\n", fdev->erase_region[0].region_start); + printf("Erase region 0 end: 0x%08lx\n", fdev->erase_region[0].region_end); + } + else + { + fprintf(stderr, "No erase regions found!\n"); + ret = -1; + goto err; + } + + if (fdev->erase_region_count > 1) + { + fdev->erase_region[1].block_count = (bpi_flash_read_word(fdev, CFI_ERASE_REGION_2_INFO_0) | (bpi_flash_read_word(fdev, CFI_ERASE_REGION_2_INFO_1) << 8)) + 1; + fdev->erase_region[1].block_size = (bpi_flash_read_word(fdev, CFI_ERASE_REGION_2_INFO_2) | (bpi_flash_read_word(fdev, CFI_ERASE_REGION_2_INFO_3) << 8)) * 256; + fdev->erase_region[1].region_start = fdev->erase_region[0].region_end; + fdev->erase_region[1].region_end = fdev->erase_region[1].region_start + fdev->erase_region[1].block_count * fdev->erase_region[1].block_size; + + if (fdev->erase_region[1].block_size > fdev->erase_block_size) + { + fdev->erase_block_size = fdev->erase_region[1].block_size; + } + + printf("Erase region 1 block count: %ld\n", fdev->erase_region[1].block_count); + printf("Erase region 1 block size: %ld B\n", fdev->erase_region[1].block_size); + printf("Erase region 1 start: 0x%08lx\n", fdev->erase_region[1].region_start); + printf("Erase region 1 end: 0x%08lx\n", fdev->erase_region[1].region_end); + } + + printf("Erase block size: %ld B\n", fdev->erase_block_size); + + fdev->ops->init(fdev); + +err: + bpi_flash_release(fdev); + return ret; +} + +int bpi_flash_read(struct flash_device *fdev, size_t addr, size_t len, void *dest) +{ + char *d = dest; + + bpi_flash_write_word(fdev, 0, CFI_READ_ARRAY); + + if (addr & 1) + { + *d = bpi_flash_read_word(fdev, addr >> 1) >> 8; + addr++; + len--; + d++; + } + + while (len > 1) + { + *((uint16_t *)d) = bpi_flash_read_word(fdev, addr >> 1); + addr += 2; + len -= 2; + d += 2; + } + + if (len) + { + *d = bpi_flash_read_word(fdev, addr >> 1); + addr++; + len--; + d++; + } + + bpi_flash_deselect(fdev); + + return 0; +} + +int bpi_flash_write(struct flash_device *fdev, size_t addr, size_t len, const void *src) +{ + const char *s = src; + + while (len > 0) + { + size_t seg = len; + + // align to buffer size + if (seg > fdev->write_buffer_size - (addr & (fdev->write_buffer_size-1))) + { + seg = fdev->write_buffer_size - (addr & (fdev->write_buffer_size-1)); + } + + if (fdev->ops->buffered_program(fdev, addr >> 1, seg >> 1, s)) + { + fprintf(stderr, "Buffered write failed\n"); + bpi_flash_deselect(fdev); + return -1; + } + + addr += seg; + len -= seg; + s += seg; + } + + bpi_flash_deselect(fdev); + + return 0; +} + +int bpi_flash_erase(struct flash_device *fdev, size_t addr, size_t len) +{ + size_t erase_block_size = fdev->erase_block_size; + + while (len > 0) + { + // determine sector size + erase_block_size = 0; + + for (int k = 0; k < fdev->erase_region_count; k++) + { + if (addr >= fdev->erase_region[k].region_start && addr < fdev->erase_region[k].region_end) + { + erase_block_size = fdev->erase_region[k].block_size; + break; + } + } + + if (!erase_block_size) + { + fprintf(stderr, "Address does not match an erase region\n"); + bpi_flash_deselect(fdev); + return -1; + } + + // check size and alignment + if (addr & (erase_block_size-1) || len < erase_block_size) + { + fprintf(stderr, "Invalid erase request\n"); + bpi_flash_deselect(fdev); + return -1; + } + + // block erase + if (fdev->ops->sector_erase(fdev, addr >> 1)) + { + fprintf(stderr, "Failed to erase sector\n"); + bpi_flash_deselect(fdev); + return -1; + } + + if (len <= erase_block_size) + break; + + addr += erase_block_size; + len -= erase_block_size; + } + + bpi_flash_deselect(fdev); + + return 0; +} + +const struct flash_driver bpi_flash_driver = { + .init = bpi_flash_init, + .release = bpi_flash_release, + .read = bpi_flash_read, + .write = bpi_flash_write, + .erase = bpi_flash_erase +}; + diff --git a/utils/flash_spi.c b/utils/flash_spi.c new file mode 100644 index 0000000..652c446 --- /dev/null +++ b/utils/flash_spi.c @@ -0,0 +1,576 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2020-2023 The Regents of the University of California + */ + +#include "flash.h" + +#include +#include + +#define reg_read32(reg) (*((volatile uint32_t *)(reg))) +#define reg_write32(reg, val) (*((volatile uint32_t *)(reg))) = (val) + +#define SPI_CMD_RESET_ENABLE 0x66 +#define SPI_CMD_RESET_MEMORY 0x99 +#define SPI_CMD_READ_ID 0x9F +#define SPI_CMD_READ 0x03 +#define SPI_CMD_FAST_READ 0x0B +#define SPI_CMD_FAST_READ_DUAL_OUT 0x3B +#define SPI_CMD_FAST_READ_DUAL_IO 0xBB +#define SPI_CMD_FAST_READ_QUAD_OUT 0x6B +#define SPI_CMD_FAST_READ_QUAD_IO 0xEB +#define SPI_CMD_DTR_FAST_READ 0x0D +#define SPI_CMD_DTR_FAST_READ_DUAL_OUT 0x3D +#define SPI_CMD_DTR_FAST_READ_DUAL_IO 0xBD +#define SPI_CMD_DTR_FAST_READ_QUAD_OUT 0x6D +#define SPI_CMD_DTR_FAST_READ_QUAD_IO 0xED +#define SPI_CMD_4B_READ 0x13 +#define SPI_CMD_4B_FAST_READ 0x0C +#define SPI_CMD_4B_FAST_READ_DUAL_OUT 0x3C +#define SPI_CMD_4B_FAST_READ_DUAL_IO 0xBC +#define SPI_CMD_4B_FAST_READ_QUAD_OUT 0x6C +#define SPI_CMD_4B_FAST_READ_QUAD_IO 0xEC +#define SPI_CMD_4B_DTR_FAST_READ 0x0E +#define SPI_CMD_4B_DTR_FAST_READ_DUAL_IO 0xBE +#define SPI_CMD_4B_DTR_FAST_READ_QUAD_IO 0xEE +#define SPI_CMD_WRITE_ENABLE 0x06 +#define SPI_CMD_WRITE_DISABLE 0x04 +#define SPI_CMD_READ_STATUS_REG 0x05 +#define SPI_CMD_READ_FLAG_STATUS_REG 0x70 +#define SPI_CMD_READ_NV_CONFIG_REG 0xB5 +#define SPI_CMD_READ_V_CONFIG_REG 0x85 +#define SPI_CMD_READ_EV_CONFIG_REG 0x65 +#define SPI_CMD_READ_EXT_ADDR_REG 0xC8 +#define SPI_CMD_WRITE_STATUS_REG 0x01 +#define SPI_CMD_WRITE_NV_CONFIG_REG 0xB1 +#define SPI_CMD_WRITE_V_CONFIG_REG 0x81 +#define SPI_CMD_WRITE_EV_CONFIG_REG 0x61 +#define SPI_CMD_WRITE_EXT_ADDR_REG 0xC5 +#define SPI_CMD_CLEAR_FLAG_STATUS_REG 0x50 +#define SPI_CMD_PAGE_PROGRAM 0x02 +#define SPI_CMD_PAGE_PROGRAM_DUAL_IN 0xA2 +#define SPI_CMD_PAGE_PROGRAM_DUAL_IN_EXT 0xD2 +#define SPI_CMD_PAGE_PROGRAM_QUAD_IN 0x32 +#define SPI_CMD_PAGE_PROGRAM_QUAD_IN_EXT 0x38 +#define SPI_CMD_4B_PAGE_PROGRAM 0x12 +#define SPI_CMD_4B_PAGE_PROGRAM_QUAD_IN 0x34 +#define SPI_CMD_4B_PAGE_PROGRAM_QUAD_IN_EXT 0x3E +#define SPI_CMD_32KB_SUBSECTOR_ERASE 0x52 +#define SPI_CMD_4KB_SUBSECTOR_ERASE 0x20 +#define SPI_CMD_SECTOR_ERASE 0xD8 +#define SPI_CMD_BULK_ERASE 0xC7 +#define SPI_CMD_4B_4KB_SUBSECTOR_ERASE 0x21 +#define SPI_CMD_4B_SECTOR_ERASE 0xDC +#define SPI_CMD_PROGRAM_SUSPEND 0x75 +#define SPI_CMD_PROGRAM_RESUME 0x7A +#define SPI_CMD_READ_OTP_ARRAY 0x4B +#define SPI_CMD_PROGRAM_OTP_ARRAY 0x42 +#define SPI_CMD_ENTER_4B_ADDR_MODE 0xB7 +#define SPI_CMD_EXIT_4B_ADDR_MODE 0xE9 +#define SPI_CMD_ENTER_QUAD_IO_MODE 0x35 +#define SPI_CMD_EXIT_QUAD_IO_MODE 0xF5 +#define SPI_CMD_ENTER_DEEP_POWER_DOWN 0xB9 +#define SPI_CMD_EXIT_DEEP_POWER_DOWN 0xAB + +#define SPI_PROTO_STR 0 +#define SPI_PROTO_DTR 1 +#define SPI_PROTO_DUAL_STR 2 +#define SPI_PROTO_DUAL_DTR 3 +#define SPI_PROTO_QUAD_STR 4 +#define SPI_PROTO_QUAD_DTR 5 + +#define SPI_PAGE_SIZE 0x100 +#define SPI_SUBSECTOR_SIZE 0x1000 +#define SPI_SECTOR_SIZE 0x10000 + +#define FLASH_D_0 (1 << 0) +#define FLASH_D_1 (1 << 1) +#define FLASH_D_2 (1 << 2) +#define FLASH_D_3 (1 << 3) +#define FLASH_D_01 (FLASH_D_0 | FLASH_D_1) +#define FLASH_D_0123 (FLASH_D_0 | FLASH_D_1 | FLASH_D_2 | FLASH_D_3) +#define FLASH_OE_0 (1 << 8) +#define FLASH_OE_1 (1 << 9) +#define FLASH_OE_2 (1 << 10) +#define FLASH_OE_3 (1 << 11) +#define FLASH_OE_01 (FLASH_OE_0 | FLASH_OE_1) +#define FLASH_OE_0123 (FLASH_OE_0 | FLASH_OE_1 | FLASH_OE_2 | FLASH_OE_3) +#define FLASH_CLK (1 << 16) +#define FLASH_CS_N (1 << 17) + +void spi_flash_select(struct flash_device *fdev) +{ + reg_write32(fdev->ctrl_reg, 0); +} + +void spi_flash_deselect(struct flash_device *fdev) +{ + reg_write32(fdev->ctrl_reg, FLASH_CS_N); +} + +uint8_t spi_flash_read_byte(struct flash_device *fdev, int protocol) +{ + uint8_t val = 0; + + switch (protocol) + { + case SPI_PROTO_STR: + for (int i = 7; i >= 0; i--) + { + reg_write32(fdev->ctrl_reg, 0); + reg_read32(fdev->ctrl_reg); // dummy read + val |= ((reg_read32(fdev->ctrl_reg) & FLASH_D_1) != 0) << i; + reg_write32(fdev->ctrl_reg, FLASH_CLK); + reg_read32(fdev->ctrl_reg); // dummy read + } + break; + case SPI_PROTO_DTR: + break; + case SPI_PROTO_DUAL_STR: + for (int i = 6; i >= 0; i -= 2) + { + reg_write32(fdev->ctrl_reg, 0); + reg_read32(fdev->ctrl_reg); // dummy read + val |= (reg_read32(fdev->ctrl_reg) & FLASH_D_01) << i; + reg_write32(fdev->ctrl_reg, FLASH_CLK); + reg_read32(fdev->ctrl_reg); // dummy read + } + break; + case SPI_PROTO_DUAL_DTR: + break; + case SPI_PROTO_QUAD_STR: + for (int i = 4; i >= 0; i -= 4) + { + reg_write32(fdev->ctrl_reg, 0); + reg_read32(fdev->ctrl_reg); // dummy read + val |= (reg_read32(fdev->ctrl_reg) & FLASH_D_0123) << i; + reg_write32(fdev->ctrl_reg, FLASH_CLK); + reg_read32(fdev->ctrl_reg); // dummy read + } + break; + case SPI_PROTO_QUAD_DTR: + break; + } + + reg_write32(fdev->ctrl_reg, 0); + + return val; +} + +void spi_flash_write_byte(struct flash_device *fdev, uint8_t val, int protocol) +{ + uint8_t bit; + + switch (protocol) + { + case SPI_PROTO_STR: + for (int i = 7; i >= 0; i--) + { + bit = (val >> i) & 0x1; + reg_write32(fdev->ctrl_reg, bit | FLASH_OE_0); + reg_read32(fdev->ctrl_reg); // dummy read + reg_write32(fdev->ctrl_reg, bit | FLASH_OE_0 | FLASH_CLK); + reg_read32(fdev->ctrl_reg); // dummy read + } + break; + case SPI_PROTO_DTR: + break; + case SPI_PROTO_DUAL_STR: + for (int i = 6; i >= 0; i -= 2) + { + bit = (val >> i) & 0x3; + reg_write32(fdev->ctrl_reg, bit | FLASH_OE_01); + reg_read32(fdev->ctrl_reg); // dummy read + reg_write32(fdev->ctrl_reg, bit | FLASH_OE_01 | FLASH_CLK); + reg_read32(fdev->ctrl_reg); // dummy read + } + break; + case SPI_PROTO_DUAL_DTR: + break; + case SPI_PROTO_QUAD_STR: + for (int i = 4; i >= 0; i -= 4) + { + bit = (val >> i) & 0xf; + reg_write32(fdev->ctrl_reg, bit | FLASH_OE_0123); + reg_read32(fdev->ctrl_reg); // dummy read + reg_write32(fdev->ctrl_reg, bit | FLASH_OE_0123 | FLASH_CLK); + reg_read32(fdev->ctrl_reg); // dummy read + } + break; + case SPI_PROTO_QUAD_DTR: + break; + } + + reg_write32(fdev->ctrl_reg, 0); +} + +void spi_flash_write_addr(struct flash_device *fdev, size_t addr, int protocol) +{ + spi_flash_write_byte(fdev, (addr >> 16) & 0xff, protocol); + spi_flash_write_byte(fdev, (addr >> 8) & 0xff, protocol); + spi_flash_write_byte(fdev, (addr >> 0) & 0xff, protocol); +} + +void spi_flash_write_addr_4b(struct flash_device *fdev, size_t addr, int protocol) +{ + spi_flash_write_byte(fdev, (addr >> 24) & 0xff, protocol); + spi_flash_write_byte(fdev, (addr >> 16) & 0xff, protocol); + spi_flash_write_byte(fdev, (addr >> 8) & 0xff, protocol); + spi_flash_write_byte(fdev, (addr >> 0) & 0xff, protocol); +} + +void spi_flash_write_enable(struct flash_device *fdev, int protocol) +{ + spi_flash_write_byte(fdev, SPI_CMD_WRITE_ENABLE, protocol); + spi_flash_deselect(fdev); +} + +void spi_flash_write_disable(struct flash_device *fdev, int protocol) +{ + spi_flash_write_byte(fdev, SPI_CMD_WRITE_DISABLE, protocol); + spi_flash_deselect(fdev); +} + +uint8_t spi_flash_read_status_register(struct flash_device *fdev, int protocol) +{ + uint8_t val; + spi_flash_write_byte(fdev, SPI_CMD_READ_STATUS_REG, protocol); + val = spi_flash_read_byte(fdev, protocol); + spi_flash_deselect(fdev); + return val; +} + +void spi_flash_write_status_register(struct flash_device *fdev, uint8_t val, int protocol) +{ + spi_flash_write_byte(fdev, SPI_CMD_WRITE_STATUS_REG, protocol); + spi_flash_write_byte(fdev, val, protocol); + spi_flash_deselect(fdev); +} + +uint8_t spi_flash_read_flag_status_register(struct flash_device *fdev, int protocol) +{ + uint8_t val; + spi_flash_write_byte(fdev, SPI_CMD_READ_FLAG_STATUS_REG, protocol); + val = spi_flash_read_byte(fdev, protocol); + spi_flash_deselect(fdev); + return val; +} + +void spi_flash_clear_flag_status_register(struct flash_device *fdev, int protocol) +{ + spi_flash_write_byte(fdev, SPI_CMD_CLEAR_FLAG_STATUS_REG, protocol); + spi_flash_deselect(fdev); +} + +uint8_t spi_flash_read_volatile_config_register(struct flash_device *fdev, int protocol) +{ + uint8_t val; + spi_flash_write_byte(fdev, SPI_CMD_READ_V_CONFIG_REG, protocol); + val = spi_flash_read_byte(fdev, protocol); + spi_flash_deselect(fdev); + return val; +} + +void spi_flash_write_volatile_config_register(struct flash_device *fdev, uint8_t val, int protocol) +{ + spi_flash_write_byte(fdev, SPI_CMD_WRITE_V_CONFIG_REG, protocol); + spi_flash_write_byte(fdev, val, protocol); + spi_flash_deselect(fdev); +} + +void spi_flash_reset(struct flash_device *fdev, int protocol) +{ + spi_flash_deselect(fdev); + spi_flash_write_byte(fdev, SPI_CMD_RESET_ENABLE, protocol); + spi_flash_deselect(fdev); + reg_read32(fdev->ctrl_reg); // dummy read + reg_read32(fdev->ctrl_reg); // dummy read + spi_flash_write_byte(fdev, SPI_CMD_RESET_MEMORY, protocol); + spi_flash_deselect(fdev); + reg_read32(fdev->ctrl_reg); // dummy read + reg_read32(fdev->ctrl_reg); // dummy read +} + +void spi_flash_release(struct flash_device *fdev) +{ + spi_flash_deselect(fdev); +} + +int spi_flash_init(struct flash_device *fdev) +{ + int ret = 0; + + if (!fdev) + return -1; + + spi_flash_reset(fdev, SPI_PROTO_STR); + + spi_flash_write_byte(fdev, SPI_CMD_READ_ID, SPI_PROTO_STR); + int mfr_id = spi_flash_read_byte(fdev, SPI_PROTO_STR); + int mem_type = spi_flash_read_byte(fdev, SPI_PROTO_STR); + int mem_capacity = spi_flash_read_byte(fdev, SPI_PROTO_STR); + spi_flash_deselect(fdev); + + printf("Manufacturer ID: 0x%02x\n", mfr_id); + printf("Memory type: 0x%02x\n", mem_type); + printf("Memory capacity: 0x%02x\n", mem_capacity); + + if (mfr_id == 0 || mfr_id == 0xff) + { + fprintf(stderr, "Failed to read flash ID\n"); + spi_flash_deselect(fdev); + return -1; + } + + // convert from BCD + mem_capacity = (mem_capacity & 0xf) + (((mem_capacity >> 4) & 0xf) * 10); + + fdev->size = ((size_t)1) << (mem_capacity+6); + + printf("Flash size: %ld MB\n", fdev->size / (1 << 20)); + + fdev->protocol = SPI_PROTO_STR; + fdev->bulk_protocol = SPI_PROTO_STR; + fdev->read_dummy_cycles = 0; + fdev->write_buffer_size = SPI_PAGE_SIZE; + fdev->erase_block_size = SPI_SUBSECTOR_SIZE; + + printf("Write buffer size: %ld B\n", fdev->write_buffer_size); + printf("Erase block size: %ld B\n", fdev->erase_block_size); + + if (fdev->data_width == 4) + { + spi_flash_write_volatile_config_register(fdev, 0xFB, SPI_PROTO_STR); + fdev->bulk_protocol = SPI_PROTO_QUAD_STR; + fdev->read_dummy_cycles = 10; + } + + spi_flash_release(fdev); + return ret; +} + +int spi_flash_read(struct flash_device *fdev, size_t addr, size_t len, void *dest) +{ + char *d = dest; + + int protocol = SPI_PROTO_STR; + + if (fdev->data_width == 4) + { + protocol = SPI_PROTO_QUAD_STR; + } + + if (fdev->size > 0x1000000) + { + // four byte address read + if (protocol == SPI_PROTO_QUAD_STR) + { + spi_flash_write_byte(fdev, SPI_CMD_4B_FAST_READ_QUAD_IO, SPI_PROTO_STR); + } + else + { + spi_flash_write_byte(fdev, SPI_CMD_4B_READ, SPI_PROTO_STR); + } + spi_flash_write_addr_4b(fdev, addr, protocol); + } + else + { + // normal read + if (protocol == SPI_PROTO_QUAD_STR) + { + spi_flash_write_byte(fdev, SPI_CMD_FAST_READ_QUAD_IO, SPI_PROTO_STR); + } + else + { + spi_flash_write_byte(fdev, SPI_CMD_READ, SPI_PROTO_STR); + } + spi_flash_write_addr(fdev, addr, protocol); + } + + if (protocol != SPI_PROTO_STR) + { + // dummy cycles + for (int i = 0; i < fdev->read_dummy_cycles; i++) + { + reg_write32(fdev->ctrl_reg, FLASH_CLK); + reg_write32(fdev->ctrl_reg, 0); + } + } + + while (len > 0) + { + *d = spi_flash_read_byte(fdev, protocol); + len--; + d++; + } + + spi_flash_deselect(fdev); + + return 0; +} + +int spi_flash_write(struct flash_device *fdev, size_t addr, size_t len, const void *src) +{ + const char *s = src; + + int protocol = SPI_PROTO_STR; + + if (fdev->data_width == 4) + { + protocol = SPI_PROTO_QUAD_STR; + } + + while (len > 0) + { + spi_flash_write_enable(fdev, SPI_PROTO_STR); + + if (!(spi_flash_read_status_register(fdev, SPI_PROTO_STR) & 0x02)) + { + fprintf(stderr, "Failed to enable writing\n"); + spi_flash_deselect(fdev); + return -1; + } + + if (fdev->size > 0x1000000) + { + // four byte address page program + if (protocol == SPI_PROTO_QUAD_STR) + { + spi_flash_write_byte(fdev, SPI_CMD_4B_PAGE_PROGRAM_QUAD_IN_EXT, SPI_PROTO_STR); + } + else + { + spi_flash_write_byte(fdev, SPI_CMD_4B_PAGE_PROGRAM, SPI_PROTO_STR); + } + spi_flash_write_addr_4b(fdev, addr, protocol); + } + else + { + // normal page program + if (protocol == SPI_PROTO_QUAD_STR) + { + spi_flash_write_byte(fdev, SPI_CMD_PAGE_PROGRAM_QUAD_IN_EXT, SPI_PROTO_STR); + } + else + { + spi_flash_write_byte(fdev, SPI_CMD_PAGE_PROGRAM, SPI_PROTO_STR); + } + spi_flash_write_addr(fdev, addr, protocol); + } + + while (len > 0) + { + spi_flash_write_byte(fdev, *s, protocol); + addr++; + s++; + len--; + + if ((addr & 0xff) == 0) + break; + } + + spi_flash_deselect(fdev); + + // wait for operation to complete + while (spi_flash_read_status_register(fdev, SPI_PROTO_STR) & 0x01) {}; + } + + spi_flash_deselect(fdev); + + return 0; +} + +int spi_flash_erase(struct flash_device *fdev, size_t addr, size_t len) +{ + size_t erase_block_size = fdev->erase_block_size; + + while (len > 0) + { + // determine sector size + erase_block_size = 0; + + if ((addr & (SPI_SECTOR_SIZE-1)) == 0 && len >= SPI_SECTOR_SIZE) + { + erase_block_size = SPI_SECTOR_SIZE; + } + else if ((addr & (SPI_SUBSECTOR_SIZE-1)) == 0 && len >= SPI_SUBSECTOR_SIZE) + { + erase_block_size = SPI_SUBSECTOR_SIZE; + } + + // check size and alignment + if (!erase_block_size) + { + fprintf(stderr, "Invalid erase request\n"); + spi_flash_deselect(fdev); + return -1; + } + + // enable writing + spi_flash_write_enable(fdev, SPI_PROTO_STR); + + if (!(spi_flash_read_status_register(fdev, SPI_PROTO_STR) & 0x02)) + { + fprintf(stderr, "Failed to enable writing\n"); + spi_flash_deselect(fdev); + return -1; + } + + // block erase + if (fdev->size > 0x1000000) + { + if (erase_block_size == SPI_SECTOR_SIZE) + { + // four byte address sector erase + spi_flash_write_byte(fdev, SPI_CMD_4B_SECTOR_ERASE, SPI_PROTO_STR); + spi_flash_write_addr_4b(fdev, addr, SPI_PROTO_STR); + } + else if (erase_block_size == SPI_SUBSECTOR_SIZE) + { + // normal 4KB subsector erase + spi_flash_write_byte(fdev, SPI_CMD_4B_4KB_SUBSECTOR_ERASE, SPI_PROTO_STR); + spi_flash_write_addr_4b(fdev, addr, SPI_PROTO_STR); + } + } + else + { + if (erase_block_size == SPI_SECTOR_SIZE) + { + // normal sector erase + spi_flash_write_byte(fdev, SPI_CMD_SECTOR_ERASE, SPI_PROTO_STR); + spi_flash_write_addr(fdev, addr, SPI_PROTO_STR); + } + else if (erase_block_size == SPI_SUBSECTOR_SIZE) + { + // normal 4KB subsector erase + spi_flash_write_byte(fdev, SPI_CMD_4KB_SUBSECTOR_ERASE, SPI_PROTO_STR); + spi_flash_write_addr(fdev, addr, SPI_PROTO_STR); + } + } + + spi_flash_deselect(fdev); + + // wait for operation to complete + while (spi_flash_read_status_register(fdev, SPI_PROTO_STR) & 0x01) {}; + + if (len <= erase_block_size) + break; + + addr += erase_block_size; + len -= erase_block_size; + } + + spi_flash_deselect(fdev); + + return 0; +} + +const struct flash_driver spi_flash_driver = { + .init = spi_flash_init, + .release = spi_flash_release, + .read = spi_flash_read, + .write = spi_flash_write, + .erase = spi_flash_erase +}; + diff --git a/utils/include b/utils/include new file mode 120000 index 0000000..3a1af68 --- /dev/null +++ b/utils/include @@ -0,0 +1 @@ +../include/ \ No newline at end of file diff --git a/utils/lib b/utils/lib new file mode 120000 index 0000000..5bf80bf --- /dev/null +++ b/utils/lib @@ -0,0 +1 @@ +../lib/ \ No newline at end of file diff --git a/utils/mqnic-bmc.c b/utils/mqnic-bmc.c new file mode 100644 index 0000000..0b9629c --- /dev/null +++ b/utils/mqnic-bmc.c @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2021-2023 The Regents of the University of California + */ + +#include +#include +#include + +#include + +static void usage(char *name) +{ + fprintf(stderr, + "usage: %s [options]\n" + " -d name device to open (/dev/mqnic0)\n" + " -i number interface\n" + " -P number port\n", + name); +} + +uint32_t mqnic_alveo_bmc_reg_read(struct mqnic_reg_block *rb, uint32_t reg) +{ + mqnic_reg_write32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_ADDR, reg); + mqnic_reg_read32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA); // dummy read + return mqnic_reg_read32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA); +} + +void mqnic_alveo_bmc_reg_write(struct mqnic_reg_block *rb, uint32_t reg, uint32_t val) +{ + mqnic_reg_write32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_ADDR, reg); + mqnic_reg_write32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA, val); + mqnic_reg_read32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA); // dummy read +} + +struct sensor_channel { + uint32_t reg; + char name[32]; + char unit[8]; +}; + +struct sensor_channel alveo_bmc_sensors[] = { + {0x0020, "12V_PEX", "mV"}, + {0x002C, "3V3_PEX", "mV"}, + {0x0038, "3V3_AUX", "mV"}, + {0x0044, "12V_AUX", "mV"}, + {0x0050, "DDR4_VPP_BTM", "mV"}, + {0x005C, "SYS_5V5", "mV"}, + {0x0068, "VCC1V2_TOP", "mV"}, + {0x0074, "VCC1V8", "mV"}, + {0x0080, "VCC0V85", "mV"}, + {0x008C, "DDR4_VPP_TOP", "mV"}, + {0x0098, "MGT0V9AVCC", "mV"}, + {0x00A4, "12VSW", "mV"}, + {0x00B0, "MGTAVTT", "mV"}, + {0x00BC, "VCC1V2_BTM", "mV"}, + {0x00C8, "12VPEX_I_IN", "mA"}, + {0x00D4, "12V_AUX_I_IN", "mA"}, + {0x00E0, "VCCINT", "mV"}, + {0x00EC, "VCCINT_I", "mA"}, + {0x00F8, "FPGA_TEMP", "C"}, + {0x0104, "FAN_TEMP", "C"}, + {0x0110, "DIMM_TEMP0", "C"}, + {0x011C, "DIMM_TEMP1", "C"}, + {0x0128, "DIMM_TEMP2", "C"}, + {0x0134, "DIMM_TEMP3", "C"}, + {0x0140, "SE98_TEMP0", "C"}, + {0x014C, "SE98_TEMP1", "C"}, + {0x0158, "SE98_TEMP2", "C"}, + {0x0164, "FAN_SPEED", "RPM"}, + {0x0170, "CAGE_TEMP0", "C"}, + {0x017C, "CAGE_TEMP1", "C"}, + {0x0188, "CAGE_TEMP2", "C"}, + {0x0194, "CAGE_TEMP3", "C"}, + {0x0260, "HBM_TEMP1", "C"}, + {0x026C, "VCC3V3", "mV"}, + {0x0278, "3V3_PEX_I_IN", "mA"}, + {0x0284, "VCC0V85_I", "mA"}, + {0x0290, "HBM_1V2", "mV"}, + {0x029C, "VPP2V5", "mV"}, + {0x02A8, "VCCINT_BRAM", "mV"}, + {0x02B4, "HBM_TEMP2", "C"}, + {0x02C0, "12V_AUX1", "mV"}, + {0x02CC, "VCCINT_TEMP", "C"}, + {0x02D8, "PEX_12V_POWER", "mW"}, + {0x02E4, "PEX_3V3_POWER", "mW"}, + {0x02F0, "AUX_3V3_I", "mA"}, + {0x0314, "VCC1V2_I", "mA"}, + {0x0320, "V12_IN_I", "mA"}, + {0x032C, "V12_IN_AUX0_I", "mA"}, + {0x0338, "V12_IN_AUX1_I", "mA"}, + {0x0344, "VCCAUX", "mV"}, + {0x0350, "VCCAUX_PMC", "mV"}, + {0x035C, "VCCRAM", "mV"}, + {0, "", ""} +}; + +int mqnic_gecko_bmc_read(struct mqnic_reg_block *rb) +{ + uint32_t val; + int timeout = 20000; + + while (1) + { + val = mqnic_reg_read32(rb->regs, MQNIC_RB_GECKO_BMC_REG_STATUS); + if (val & (1 << 19)) + { + if (val & (1 << 18)) + { + // timed out + printf("Timed out waiting for BMC\n"); + usleep(10000); + return -2; + } + return val & 0xffff; + } + else + { + timeout--; + if (timeout == 0) + { + printf("Timed out waiting for operation\n"); + return -1; + } + usleep(10); + } + } + + return -1; +} + +int mqnic_gecko_bmc_write(struct mqnic_reg_block *rb, uint16_t cmd, uint32_t data) +{ + int ret; + ret = mqnic_gecko_bmc_read(rb); + + if (ret == -1) + return ret; + + mqnic_reg_write32(rb->regs, MQNIC_RB_GECKO_BMC_REG_DATA, data); + mqnic_reg_write32(rb->regs, MQNIC_RB_GECKO_BMC_REG_CMD, cmd << 16); + + return 0; +} + +int mqnic_gecko_bmc_query(struct mqnic_reg_block *rb, uint16_t cmd, uint32_t data) +{ + int ret; + + ret = mqnic_gecko_bmc_write(rb, cmd, data); + + if (ret) + return ret; + + return mqnic_gecko_bmc_read(rb); +} + +int main(int argc, char *argv[]) +{ + char *name; + int opt; + int ret = 0; + + char *device = NULL; + struct mqnic *dev; + struct mqnic_reg_block *bmc_rb; + + name = strrchr(argv[0], '/'); + name = name ? 1+name : argv[0]; + + while ((opt = getopt(argc, argv, "d:h?")) != EOF) + { + switch (opt) + { + case 'd': + device = optarg; + break; + case 'h': + case '?': + usage(name); + return 0; + default: + usage(name); + return -1; + } + } + + if (!device) + { + fprintf(stderr, "Device not specified\n"); + usage(name); + return -1; + } + + dev = mqnic_open(device); + + if (!dev) + { + fprintf(stderr, "Failed to open device\n"); + return -1; + } + + if (dev->pci_device_path[0]) + { + char *ptr = strrchr(dev->pci_device_path, '/'); + if (ptr) + printf("PCIe ID: %s\n", ptr+1); + } + + mqnic_print_fw_id(dev); + + if ((bmc_rb = mqnic_find_reg_block(dev->rb_list, MQNIC_RB_ALVEO_BMC_TYPE, MQNIC_RB_ALVEO_BMC_VER, 0))) + { + printf("Detected Xilinx Alveo board with MSP430 BMC\n"); + + printf("Attempt to communicate with CMS microblaze...\n"); + + if (mqnic_alveo_bmc_reg_read(bmc_rb, 0x020000) == 0 || mqnic_alveo_bmc_reg_read(bmc_rb, 0x028000) == 0) + { + printf("Resetting CMS...\n"); + + // reset CMS + mqnic_alveo_bmc_reg_write(bmc_rb, 0x020000, 0); + mqnic_alveo_bmc_reg_write(bmc_rb, 0x020000, 1); + usleep(200000); + } + + if (mqnic_alveo_bmc_reg_read(bmc_rb, 0x028000) != 0x74736574) + { + fprintf(stderr, "CMS not responding\n"); + ret = -1; + goto err; + } + + // read sensor channels + printf("Sensor values:\n"); + for (const struct sensor_channel *ptr = alveo_bmc_sensors; ptr->reg; ptr++) + { + uint32_t reg = 0x028000 + ptr->reg; + uint32_t val_max = mqnic_alveo_bmc_reg_read(bmc_rb, reg); + uint32_t val_avg = mqnic_alveo_bmc_reg_read(bmc_rb, reg+4); + uint32_t val_ins = mqnic_alveo_bmc_reg_read(bmc_rb, reg+8); + + printf("%s: %d %s (%d %s avg, %d %s max)\n", ptr->name, + val_ins, ptr->unit, val_avg, ptr->unit, val_max, ptr->unit); + } + + // read MAC addresses + printf("MAC addresses:\n"); + for (int k = 0; k < 8; k++) + { + uint8_t mac[6]; + uint32_t reg = 0x0281a0 + k*8; + uint32_t val = mqnic_alveo_bmc_reg_read(bmc_rb, reg); + mac[0] = (val >> 8) & 0xff; + mac[1] = val & 0xff; + val = mqnic_alveo_bmc_reg_read(bmc_rb, reg+4); + mac[2] = (val >> 24) & 0xff; + mac[3] = (val >> 16) & 0xff; + mac[4] = (val >> 8) & 0xff; + mac[5] = val & 0xff; + printf("MAC %d: ", k); + for (int i = 0; i < 6; i++) + { + if (i != 0) + printf(":"); + printf("%02x", mac[i]); + } + printf("\n"); + } + } + else if ((bmc_rb = mqnic_find_reg_block(dev->rb_list, MQNIC_RB_GECKO_BMC_TYPE, MQNIC_RB_GECKO_BMC_VER, 0))) + { + printf("Detected Silicom board with Gecko BMC\n"); + + if (mqnic_gecko_bmc_query(bmc_rb, 0x7006, 0) <= 0) + { + fprintf(stderr, "Failed to communicate with BMC\n"); + ret = -1; + goto err; + } + + uint16_t v_l = mqnic_gecko_bmc_query(bmc_rb, 0x7005, 0); + uint16_t v_h = mqnic_gecko_bmc_query(bmc_rb, 0x7006, 0); + + printf("Gecko BMC version %d.%d.%d.%d\n", (v_h >> 8) & 0xff, v_h & 0xff, (v_l >> 8) & 0xff, v_l & 0xff); + + // read MAC addresses + printf("MAC addresses:\n"); + for (int k = 0; k < 8; k++) + { + uint8_t mac[6]; + for (int i = 0; i < 6; i += 2) + { + uint16_t val = mqnic_gecko_bmc_query(bmc_rb, 0x2003, 0+k*6+i); + mac[i] = val & 0xff; + mac[i+1] = (val >> 8) & 0xff; + } + printf("MAC %d: ", k); + for (int i = 0; i < 6; i++) + { + if (i != 0) + printf(":"); + printf("%02x", mac[i]); + } + printf("\n"); + } + } + else + { + fprintf(stderr, "Board does not have BMC or BMC not currently supported\n"); + ret = -1; + + goto err; + } + +err: + + mqnic_close(dev); + + return ret; +} diff --git a/utils/mqnic-config.c b/utils/mqnic-config.c new file mode 100644 index 0000000..fa8915a --- /dev/null +++ b/utils/mqnic-config.c @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include +#include +//#include +//#include +#include +#include +#include +#include +#include +#include +//#include +//#include +//#include +#include +#include +#include + +#include "timespec.h" + +#include + +#define NSEC_PER_SEC 1000000000 + +static void usage(char *name) +{ + fprintf(stderr, + "usage: %s [options]\n" + " -d name device to open (/dev/mqnic0)\n" + " -i number interface\n" + " -P number port\n" + " -s number TDMA schedule start time (ns)\n" + " -p number TDMA schedule period (ns)\n" + " -t number TDMA timeslot period (ns)\n" + " -a number TDMA active period (ns)\n", + name); +} + +int main(int argc, char *argv[]) +{ + char *name; + int opt; + + char *device = NULL; + struct mqnic *dev; + int interface = 0; + int port = 0; + int sched_block = 0; + + struct mqnic_reg_block *rb; + + struct timespec ts_now; + struct timespec ts_start; + struct timespec ts_period; + struct timespec ts_timeslot_period; + struct timespec ts_active_period; + + int64_t start_nsec = 0; + int64_t period_nsec = 0; + int64_t timeslot_period_nsec = 0; + int64_t active_period_nsec = 0; + + name = strrchr(argv[0], '/'); + name = name ? 1+name : argv[0]; + + while ((opt = getopt(argc, argv, "d:i:P:s:p:t:a:h?")) != EOF) + { + switch (opt) + { + case 'd': + device = optarg; + break; + case 'i': + interface = atoi(optarg); + break; + case 'P': + port = atoi(optarg); + break; + case 's': + start_nsec = atoll(optarg); + break; + case 'p': + period_nsec = atoll(optarg); + break; + case 't': + timeslot_period_nsec = atoll(optarg); + break; + case 'a': + active_period_nsec = atoll(optarg); + break; + case 'h': + case '?': + usage(name); + return 0; + default: + usage(name); + return -1; + } + } + + if (!device) + { + fprintf(stderr, "Device not specified\n"); + usage(name); + return -1; + } + + dev = mqnic_open(device); + + if (!dev) + { + fprintf(stderr, "Failed to open device\n"); + return -1; + } + + if (dev->pci_device_path[0]) + { + char *ptr = strrchr(dev->pci_device_path, '/'); + if (ptr) + printf("PCIe ID: %s\n", ptr+1); + } + + mqnic_print_fw_id(dev); + + if (!dev->phc_rb) + { + fprintf(stderr, "No PHC on card\n"); + goto err; + } + + if (interface < 0 || interface >= dev->if_count) + { + fprintf(stderr, "Interface out of range\n"); + goto err; + } + + struct mqnic_if *dev_interface = dev->interfaces[interface]; + + if (!dev_interface) + { + fprintf(stderr, "Invalid interface\n"); + goto err; + } + + printf("IF features: 0x%08x\n", dev_interface->if_features); + printf("Port count: %d\n", dev_interface->port_count); + printf("Scheduler block count: %d\n", dev_interface->sched_block_count); + printf("Max TX MTU: %d\n", dev_interface->max_tx_mtu); + printf("Max RX MTU: %d\n", dev_interface->max_rx_mtu); + printf("TX MTU: %d\n", mqnic_reg_read32(dev_interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_TX_MTU)); + printf("RX MTU: %d\n", mqnic_reg_read32(dev_interface->if_ctrl_rb->regs, MQNIC_RB_IF_CTRL_REG_RX_MTU)); + + printf("EQ count: %d\n", mqnic_res_get_count(dev_interface->eq_res)); + printf("CQ count: %d\n", mqnic_res_get_count(dev_interface->cq_res)); + printf("TXQ count: %d\n", mqnic_res_get_count(dev_interface->txq_res)); + printf("RXQ count: %d\n", mqnic_res_get_count(dev_interface->rxq_res)); + + if (port < 0 || port >= dev_interface->port_count) + { + fprintf(stderr, "Port out of range\n"); + goto err; + } + + sched_block = port; + + if (sched_block < 0 || sched_block >= dev_interface->sched_block_count) + { + fprintf(stderr, "Scheduler block out of range\n"); + goto err; + } + + struct mqnic_sched_block *dev_sched_block = dev_interface->sched_blocks[sched_block]; + + if (!dev_sched_block) + { + fprintf(stderr, "Invalid scheduler block\n"); + goto err; + } + + printf("Sched count: %d\n", dev_sched_block->sched_count); + + rb = mqnic_find_reg_block(dev_sched_block->rb_list, MQNIC_RB_TDMA_SCH_TYPE, MQNIC_RB_TDMA_SCH_VER, 0); + + if (dev->phc_rb && rb) + { + printf("TDMA timeslot count: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_COUNT)); + printf("TDMA control: 0x%08x\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_CTRL)); + printf("TDMA status: 0x%08x\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_STATUS)); + + printf("TDMA schedule start: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_NS)); + printf("TDMA schedule period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_NS)); + printf("TDMA timeslot period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_NS)); + printf("TDMA active period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_NS)); + + if (period_nsec > 0) + { + printf("Configure port TDMA schedule\n"); + + ts_now.tv_nsec = mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_TOD_NS); + ts_now.tv_sec = mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_TOD_SEC_L) + + (((int64_t)mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_TOD_SEC_H)) << 32); + + // normalize start + ts_start.tv_sec = start_nsec / NSEC_PER_SEC; + ts_start.tv_nsec = start_nsec - ts_start.tv_sec * NSEC_PER_SEC; + + // normalize period + ts_period.tv_sec = period_nsec / NSEC_PER_SEC; + ts_period.tv_nsec = period_nsec - ts_period.tv_sec * NSEC_PER_SEC; + + printf("time %ld.%09ld s\n", ts_now.tv_sec, ts_now.tv_nsec); + printf("start %ld.%09ld s\n", ts_start.tv_sec, ts_start.tv_nsec); + printf("period %ld.%09ld s\n", ts_period.tv_sec, ts_period.tv_nsec); + + if (timespec_lt(ts_start, ts_now)) + { + // start time is in the past + + // modulo start with period + ts_start = timespec_mod(ts_start, ts_period); + + // align time with period + struct timespec ts_aligned = timespec_sub(ts_now, timespec_mod(ts_now, ts_period)); + + // add aligned time + ts_start = timespec_add(ts_start, ts_aligned); + } + + printf("time %ld.%09ld s\n", ts_now.tv_sec, ts_now.tv_nsec); + printf("start %ld.%09ld s\n", ts_start.tv_sec, ts_start.tv_nsec); + printf("period %ld.%09ld s\n", ts_period.tv_sec, ts_period.tv_nsec); + + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_NS, ts_start.tv_nsec); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_L, ts_start.tv_sec & 0xffffffff); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_H, ts_start.tv_sec >> 32); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_NS, ts_period.tv_nsec); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_L, ts_period.tv_sec & 0xffffffff); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_H, ts_period.tv_sec >> 32); + + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_CTRL, 0x00000001); + } + + if (timeslot_period_nsec > 0) + { + printf("Configure port TDMA timeslot period\n"); + + // normalize period + ts_timeslot_period.tv_sec = timeslot_period_nsec / NSEC_PER_SEC; + ts_timeslot_period.tv_nsec = timeslot_period_nsec - ts_timeslot_period.tv_sec * NSEC_PER_SEC; + + printf("period %ld.%09ld s\n", ts_timeslot_period.tv_sec, ts_timeslot_period.tv_nsec); + + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_NS, ts_timeslot_period.tv_nsec); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_L, ts_timeslot_period.tv_sec & 0xffffffff); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_H, ts_timeslot_period.tv_sec >> 32); + } + + if (active_period_nsec > 0) + { + printf("Configure port TDMA active period\n"); + + // normalize period + ts_active_period.tv_sec = active_period_nsec / NSEC_PER_SEC; + ts_active_period.tv_nsec = active_period_nsec - ts_active_period.tv_sec * NSEC_PER_SEC; + + printf("period %ld.%09ld s\n", ts_active_period.tv_sec, ts_active_period.tv_nsec); + + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_NS, ts_active_period.tv_nsec); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_L, ts_active_period.tv_sec & 0xffffffff); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_H, ts_active_period.tv_sec >> 32); + } + } + +err: + + mqnic_close(dev); + + return 0; +} + + + + diff --git a/utils/mqnic-dump.c b/utils/mqnic-dump.c new file mode 100644 index 0000000..ccdb524 --- /dev/null +++ b/utils/mqnic-dump.c @@ -0,0 +1,514 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include +#include +#include + +#include + +static void usage(char *name) +{ + fprintf(stderr, + "usage: %s [options]\n" + " -d name device to open (/dev/mqnic0)\n" + " -i number interface\n" + " -P number port\n" + " -v verbose output\n", + name); +} + +int main(int argc, char *argv[]) +{ + char *name; + int opt; + int ret = 0; + + char *device = NULL; + struct mqnic *dev; + int interface = 0; + int port = 0; + int sched_block = 0; + int verbose = 0; + + name = strrchr(argv[0], '/'); + name = name ? 1+name : argv[0]; + + while ((opt = getopt(argc, argv, "d:i:P:vh?")) != EOF) + { + switch (opt) + { + case 'd': + device = optarg; + break; + case 'i': + interface = atoi(optarg); + break; + case 'P': + port = atoi(optarg); + break; + case 'v': + verbose++; + break; + case 'h': + case '?': + usage(name); + return 0; + default: + usage(name); + return -1; + } + } + + if (!device) + { + fprintf(stderr, "Device not specified\n"); + usage(name); + return -1; + } + + dev = mqnic_open(device); + + if (!dev) + { + fprintf(stderr, "Failed to open device\n"); + return -1; + } + + if (dev->pci_device_path[0]) + { + char *ptr = strrchr(dev->pci_device_path, '/'); + if (ptr) + printf("PCIe ID: %s\n", ptr+1); + } + + printf("Control region size: %lu\n", dev->regs_size); + if (dev->app_regs_size) + printf("Application region size: %lu\n", dev->app_regs_size); + if (dev->ram_size) + printf("RAM region size: %lu\n", dev->ram_size); + + printf("Device-level register blocks:\n"); + for (struct mqnic_reg_block *rb = dev->rb_list; rb->regs; rb++) + printf(" type 0x%08x (v %d.%d.%d.%d)\n", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + mqnic_print_fw_id(dev); + + printf("IF offset: 0x%08x\n", dev->if_offset); + printf("IF count: %d\n", dev->if_count); + printf("IF stride: 0x%08x\n", dev->if_stride); + printf("IF CSR offset: 0x%08x\n", dev->if_csr_offset); + + if (dev->phc_rb) + { + int ch; + uint32_t ns; + uint32_t fns; + + printf("PHC ctrl: 0x%08x\n", mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CTRL)); + + printf("PHC time (ToD): %ld.%09d s\n", mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_TOD_SEC_L) + + (((int64_t)mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_TOD_SEC_H)) << 32), + mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_TOD_NS)); + printf("PHC time (rel): %ld ns\n", mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_REL_NS_L) + + (((int64_t)mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_REL_NS_H)) << 32)); + + ns = mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_PERIOD_NS); + fns = mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_PERIOD_FNS); + printf("PHC period: %d.%09ld ns (raw 0x%x ns 0x%08x fns)\n", ns, ((uint64_t)fns * 1000000000) >> 32, ns, fns); + + ns = mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_NOM_PERIOD_NS); + fns = mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_NOM_PERIOD_FNS); + printf("PHC nom period: %d.%09ld ns (raw 0x%x ns 0x%08x fns)\n", ns, ((uint64_t)fns * 1000000000) >> 32, ns, fns); + + ch = 0; + for (struct mqnic_reg_block *rb = dev->rb_list; rb->regs; rb++) + { + if (rb->type == MQNIC_RB_PHC_PEROUT_TYPE && rb->version == MQNIC_RB_PHC_PEROUT_VER) + { + printf("PHC perout ch %d ctrl: 0x%08x\n", ch, mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_CTRL)); + printf("PHC perout ch %d start: %ld.%09d s\n", ch, mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_START_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_START_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_START_NS)); + printf("PHC perout ch %d period: %ld.%09d s\n", ch, mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_PERIOD_NS)); + printf("PHC perout ch %d width: %ld.%09d s\n", ch, mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_WIDTH_NS)); + ch++; + } + } + } + + if (dev->clk_info_rb) + { + uint32_t num; + uint32_t denom; + uint32_t ns; + uint32_t fns; + uint32_t mhz; + uint32_t hz; + + num = dev->ref_clk_nom_per_ns_num; + denom = dev->ref_clk_nom_per_ns_denom; + + ns = num/denom; + fns = ((num-ns*denom)*1000000000ull)/denom; + + printf("Ref clock nominal period: %d.%09d ns (raw %d/%d ns)\n", ns, fns, num, denom); + + hz = mqnic_get_ref_clk_nom_freq_hz(dev); + + mhz = hz / 1000000; + hz = hz - (mhz * 1000000); + + printf("Ref clock nominal freq: %d.%06d MHz\n", mhz, hz); + + num = dev->core_clk_nom_per_ns_num; + denom = dev->core_clk_nom_per_ns_denom; + + ns = num/denom; + fns = ((num-ns*denom)*1000000000ull)/denom; + + printf("Core clock nominal period: %d.%09d ns (raw %d/%d ns)\n", ns, fns, num, denom); + + hz = mqnic_get_core_clk_nom_freq_hz(dev); + + mhz = hz / 1000000; + hz = hz - (mhz * 1000000); + + printf("Core clock nominal freq: %d.%06d MHz\n", mhz, hz); + + hz = mqnic_get_core_clk_freq_hz(dev); + + mhz = hz / 1000000; + hz = hz - (mhz * 1000000); + + printf("Core clock freq: %d.%06d MHz\n", mhz, hz); + + for (int ch = 0; ch < dev->clk_info_channels; ch++) + { + hz = mqnic_get_clk_freq_hz(dev, ch); + + mhz = hz / 1000000; + hz = hz - (mhz * 1000000); + + printf("CH%d: clock freq: %d.%06d MHz\n", ch, mhz, hz); + } + } + + if (interface < 0 || interface >= dev->if_count) + { + fprintf(stderr, "Interface out of range\n"); + ret = -1; + goto err; + } + + struct mqnic_if *dev_interface = dev->interfaces[interface]; + + if (!dev_interface) + { + fprintf(stderr, "Invalid interface\n"); + ret = -1; + goto err; + } + + printf("Interface-level register blocks:\n"); + for (struct mqnic_reg_block *rb = dev_interface->rb_list; rb->regs; rb++) + printf(" type 0x%08x (v %d.%d.%d.%d)\n", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + printf("IF features: 0x%08x\n", dev_interface->if_features); + printf("Port count: %d\n", dev_interface->port_count); + printf("Scheduler block count: %d\n", dev_interface->sched_block_count); + printf("Max TX MTU: %d B\n", dev_interface->max_tx_mtu); + printf("Max RX MTU: %d B\n", dev_interface->max_rx_mtu); + printf("TX MTU: %d B\n", mqnic_interface_get_tx_mtu(dev_interface)); + printf("RX MTU: %d B\n", mqnic_interface_get_rx_mtu(dev_interface)); + printf("TX FIFO depth: %d B\n", dev_interface->tx_fifo_depth); + printf("RX FIFO depth: %d B\n", dev_interface->rx_fifo_depth); + + printf("EQ offset: 0x%08lx\n", dev_interface->eq_res->base - dev_interface->regs); + printf("EQ count: %d\n", mqnic_res_get_count(dev_interface->eq_res)); + printf("EQ stride: 0x%08x\n", dev_interface->eq_res->stride); + + printf("CQ offset: 0x%08lx\n", dev_interface->cq_res->base - dev_interface->regs); + printf("CQ count: %d\n", mqnic_res_get_count(dev_interface->cq_res)); + printf("CQ stride: 0x%08x\n", dev_interface->cq_res->stride); + + printf("TXQ offset: 0x%08lx\n", dev_interface->txq_res->base - dev_interface->regs); + printf("TXQ count: %d\n", mqnic_res_get_count(dev_interface->txq_res)); + printf("TXQ stride: 0x%08x\n", dev_interface->txq_res->stride); + + printf("RXQ offset: 0x%08lx\n", dev_interface->rxq_res->base - dev_interface->regs); + printf("RXQ count: %d\n", mqnic_res_get_count(dev_interface->rxq_res)); + printf("RXQ stride: 0x%08x\n", dev_interface->rxq_res->stride); + + for (int p = 0; p < dev_interface->port_count; p++) + { + printf("Port %d RX queue map RSS mask: 0x%08x\n", p, mqnic_interface_get_rx_queue_map_rss_mask(dev_interface, p)); + printf("Port %d RX queue map app mask: 0x%08x\n", p, mqnic_interface_get_rx_queue_map_app_mask(dev_interface, p)); + printf("Port %d RX indirection table size: %d\n", p, dev_interface->rx_queue_map_indir_table_size); + + printf("Port %d RX indirection table:\n", p); + for (int k = 0; k < dev_interface->rx_queue_map_indir_table_size; k += 8) + { + printf("%04x:", k); + for (int l = 0; l < 8; l++) { + printf(" %04x", mqnic_interface_get_rx_queue_map_indir_table(dev_interface, p, k+l)); + } + printf("\n"); + } + } + + if (port < 0 || port >= dev_interface->port_count) + { + fprintf(stderr, "Port out of range\n"); + ret = -1; + goto err; + } + + struct mqnic_port *dev_port = dev_interface->ports[port]; + + if (!dev_port) + { + fprintf(stderr, "Invalid port\n"); + ret = -1; + goto err; + } + + printf("Port-level register blocks:\n"); + for (struct mqnic_reg_block *rb = dev_port->rb_list; rb->regs; rb++) + printf(" type 0x%08x (v %d.%d.%d.%d)\n", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + printf("Port features: 0x%08x\n", dev_port->port_features); + printf("Port TX ctrl: 0x%08x\n", mqnic_port_get_tx_ctrl(dev_port)); + printf("Port RX ctrl: 0x%08x\n", mqnic_port_get_rx_ctrl(dev_port)); + printf("Port FC ctrl: 0x%08x\n", mqnic_port_get_fc_ctrl(dev_port)); + printf("Port LFC ctrl: 0x%08x\n", mqnic_port_get_lfc_ctrl(dev_port)); + for (int k = 0; k < 8; k++) + printf("Port PFC ctrl %d: 0x%08x\n", k, mqnic_port_get_pfc_ctrl(dev_port, k)); + + sched_block = port; + + if (sched_block < 0 || sched_block >= dev_interface->sched_block_count) + { + fprintf(stderr, "Scheduler block out of range\n"); + ret = -1; + goto err; + } + + struct mqnic_sched_block *dev_sched_block = dev_interface->sched_blocks[sched_block]; + + if (!dev_sched_block) + { + fprintf(stderr, "Invalid scheduler block\n"); + ret = -1; + goto err; + } + + printf("Scheduler block-level register blocks:\n"); + for (struct mqnic_reg_block *rb = dev_sched_block->rb_list; rb->regs; rb++) + printf(" type 0x%08x (v %d.%d.%d.%d)\n", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + printf("Sched count: %d\n", dev_sched_block->sched_count); + + for (struct mqnic_reg_block *rb = dev_sched_block->rb_list; rb->regs; rb++) + { + if (rb->type == MQNIC_RB_SCHED_RR_TYPE && rb->version == MQNIC_RB_SCHED_RR_VER) + { + printf("Round-robin scheduler\n"); + + printf("Sched channel count: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CH_COUNT)); + printf("Sched channel stride: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CH_STRIDE)); + printf("Sched control: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CTRL)); + printf("Sched dest: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_DEST)); + } + else if (rb->type == MQNIC_RB_SCHED_CTRL_TDMA_TYPE && rb->version == MQNIC_RB_SCHED_CTRL_TDMA_VER) + { + printf("TDMA scheduler controller\n"); + + printf("Sched channel count: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_CTRL_TDMA_REG_CH_COUNT)); + printf("Sched channel stride: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_CTRL_TDMA_REG_CH_STRIDE)); + printf("Sched control: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_CTRL_TDMA_REG_CTRL)); + printf("Sched timeslot count: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_CTRL_TDMA_REG_TS_COUNT)); + } + else if (rb->type == MQNIC_RB_TDMA_SCH_TYPE && rb->version == MQNIC_RB_TDMA_SCH_VER) + { + printf("TDMA scheduler\n"); + + printf("TDMA timeslot count: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_COUNT)); + printf("TDMA control: 0x%08x\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_CTRL)); + printf("TDMA status: 0x%08x\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_STATUS)); + + printf("TDMA schedule start: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_NS)); + printf("TDMA schedule period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_NS)); + printf("TDMA timeslot period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_NS)); + printf("TDMA active period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_NS)); + } + } + + printf("EQ info\n"); + printf("%d\n", dev_interface->eq_res->count); + printf(" Queue Base Address VFID En A LS A IRQ Prod Cons Len\n"); + for (int k = 0; k < mqnic_res_get_count(dev_interface->eq_res); k++) + { + + + uint32_t val; + volatile uint8_t *base = mqnic_res_get_addr(dev_interface->eq_res, k); + + val = mqnic_reg_read32(base, MQNIC_EQ_CTRL_STATUS_REG); + uint32_t irq = val & 0xffff; + uint8_t enable = (val & MQNIC_EQ_ENABLE_MASK) != 0; + uint8_t armed = (val & MQNIC_EQ_ARM_MASK) != 0; + uint8_t active = (val & MQNIC_EQ_ACTIVE_MASK) != 0; + uint8_t log_queue_size = (val >> 28) & 0xf; + + if (!enable && !verbose) + continue; + + uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_EQ_BASE_ADDR_VF_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_EQ_BASE_ADDR_VF_REG+4) << 32); + base_addr &= 0xfffffffffffff000; + + uint8_t vfid = (uint64_t)(mqnic_reg_read32(base, MQNIC_EQ_BASE_ADDR_VF_REG)) & 0xFF; + val = mqnic_reg_read32(base, MQNIC_EQ_PTR_REG); + uint32_t prod_ptr = val & MQNIC_EQ_PTR_MASK; + uint32_t cons_ptr = (val >> 16) & MQNIC_EQ_PTR_MASK; + uint32_t occupancy = (prod_ptr - cons_ptr) & MQNIC_EQ_PTR_MASK; + + printf("EQ %4d 0x%016lx 0x%x %d %d %2d %d %4d %6d %6d %6d\n", k, base_addr, vfid, enable, active, log_queue_size, armed, irq, prod_ptr, cons_ptr, occupancy); + } + + printf("CQ info\n"); + printf(" Queue Base Address VFID En A LS A EQN Prod Cons Len\n"); + for (int k = 0; k < mqnic_res_get_count(dev_interface->cq_res); k++) + { + uint32_t val; + volatile uint8_t *base = mqnic_res_get_addr(dev_interface->cq_res, k); + + val = mqnic_reg_read32(base, MQNIC_CQ_CTRL_STATUS_REG); + uint32_t eqn = val & 0xffff; + uint8_t enable = (val & MQNIC_CQ_ENABLE_MASK) != 0; + uint8_t armed = (val & MQNIC_CQ_ARM_MASK) != 0; + uint8_t active = (val & MQNIC_CQ_ACTIVE_MASK) != 0; + uint8_t log_queue_size = (val >> 28) & 0xf; + + if (!enable && !verbose) + continue; + + uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_CQ_BASE_ADDR_VF_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_CQ_BASE_ADDR_VF_REG+4) << 32); + base_addr &= 0xfffffffffffff000; + + uint8_t vfid = (uint64_t)(mqnic_reg_read32(base, MQNIC_CQ_BASE_ADDR_VF_REG)) & 0xFF; + val = mqnic_reg_read32(base, MQNIC_CQ_PTR_REG); + uint32_t prod_ptr = val & MQNIC_CQ_PTR_MASK; + uint32_t cons_ptr = (val >> 16) & MQNIC_CQ_PTR_MASK; + uint32_t occupancy = (prod_ptr - cons_ptr) & MQNIC_CQ_PTR_MASK; + + printf("CQ %4d 0x%016lx 0x%x %d %d %2d %d %4d %6d %6d %6d\n", k, base_addr, vfid, enable, active, log_queue_size, armed, eqn, prod_ptr, cons_ptr, occupancy); + } + + printf("TXQ info\n"); + printf(" Queue Base Address VFID En A B LS CQN Prod Cons Len\n"); + for (int k = 0; k < mqnic_res_get_count(dev_interface->txq_res); k++) + { + uint32_t val; + volatile uint8_t *base = mqnic_res_get_addr(dev_interface->txq_res, k); + + val = mqnic_reg_read32(base, MQNIC_QUEUE_CTRL_STATUS_REG); + uint8_t enable = (val & MQNIC_QUEUE_ENABLE_MASK) != 0; + uint8_t active = (val & MQNIC_QUEUE_ACTIVE_MASK) != 0; + + if (!enable && !verbose) + continue; + + uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_VF_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_VF_REG+4) << 32); + base_addr &= 0xfffffffffffff000; + uint8_t vfid = (uint64_t)(mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_VF_REG)) & 0xFF; + val = mqnic_reg_read32(base, MQNIC_QUEUE_SIZE_CQN_REG); + uint32_t cqn = val & 0xffffff; + uint8_t log_queue_size = (val >> 24) & 0xf; + uint8_t log_desc_block_size = (val >> 28) & 0xf; + val = mqnic_reg_read32(base, MQNIC_QUEUE_PTR_REG); + uint32_t prod_ptr = val & MQNIC_QUEUE_PTR_MASK; + uint32_t cons_ptr = (val >> 16) & MQNIC_QUEUE_PTR_MASK; + uint32_t occupancy = (prod_ptr - cons_ptr) & MQNIC_QUEUE_PTR_MASK; + + printf("TXQ %4d 0x%016lx 0x%x %d %d %d %2d %4d %6d %6d %6d\n", k, base_addr, vfid, enable, active, log_desc_block_size, log_queue_size, cqn, prod_ptr, cons_ptr, occupancy); + } + + printf("RXQ info\n"); + printf(" Queue Base Address VFID En A B LS CQN Prod Cons Len\n"); + for (int k = 0; k < mqnic_res_get_count(dev_interface->rxq_res); k++) + { + uint32_t val; + volatile uint8_t *base = mqnic_res_get_addr(dev_interface->rxq_res, k); + + val = mqnic_reg_read32(base, MQNIC_QUEUE_CTRL_STATUS_REG); + uint8_t enable = (val & MQNIC_QUEUE_ENABLE_MASK) != 0; + uint8_t active = (val & MQNIC_QUEUE_ACTIVE_MASK) != 0; + + if (!enable && !verbose) + continue; + + uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_VF_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_VF_REG+4) << 32); + base_addr &= 0xfffffffffffff000; + + uint8_t vfid = (uint64_t)(mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_VF_REG)) & 0xFF; + val = mqnic_reg_read32(base, MQNIC_QUEUE_SIZE_CQN_REG); + uint32_t cqn = val & 0xffffff; + uint8_t log_queue_size = (val >> 24) & 0xf; + uint8_t log_desc_block_size = (val >> 28) & 0xf; + val = mqnic_reg_read32(base, MQNIC_QUEUE_PTR_REG); + uint32_t prod_ptr = val & MQNIC_QUEUE_PTR_MASK; + uint32_t cons_ptr = (val >> 16) & MQNIC_QUEUE_PTR_MASK; + uint32_t occupancy = (prod_ptr - cons_ptr) & MQNIC_QUEUE_PTR_MASK; + + printf("RXQ %4d 0x%016lx 0x%x %d %d %d %2d %4d %6d %6d %6d\n", k, base_addr, vfid, enable, active, log_desc_block_size, log_queue_size, cqn, prod_ptr, cons_ptr, occupancy); + } + + if (verbose) + { + for (int k = 0; k < dev_sched_block->sched_count; k++) + { + printf("Scheduler block %d scheduler %d\n", sched_block, k); + for (int l = 0; l < mqnic_res_get_count(dev_interface->txq_res); l++) + { + printf("Sched %2d queue %4d state: 0x%08x\n", k, l, mqnic_reg_read32(dev_sched_block->sched[k]->regs, l*4)); + } + } + } + + if (dev->stats_rb) + { + printf("Statistics counters\n"); + for (int k = 0; k < dev->stats_count; k++) + { + uint64_t val = mqnic_stats_read(dev, k); + + if (val || verbose) + printf("Index %d: %lu\n", k, mqnic_stats_read(dev, k)); + } + } + +err: + + mqnic_close(dev); + + return ret; +} diff --git a/utils/mqnic-fw.c b/utils/mqnic-fw.c new file mode 100644 index 0000000..d509ff7 --- /dev/null +++ b/utils/mqnic-fw.c @@ -0,0 +1,1514 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "bitfile.h" +#include "flash.h" + +#define MAX_SEGMENTS 8 + +uint32_t reverse_bits_32(uint32_t x) +{ + x = ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1); + x = ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2); + x = ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4); + x = ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8); + x = ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16); + return x; +} + +uint16_t reverse_bits_16(uint16_t x) +{ + x = ((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1); + x = ((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2); + x = ((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4); + x = ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8); + return x; +} + +uint8_t reverse_bits_8(uint8_t x) +{ + x = ((x & 0x55) << 1) | ((x & 0xAA) >> 1); + x = ((x & 0x33) << 2) | ((x & 0xCC) >> 2); + x = ((x & 0x0F) << 4) | ((x & 0xF0) >> 4); + return x; +} + +char* stristr(const char *str1, const char *str2) +{ + const char* p1 = str1; + const char* p2 = str2; + const char* r = *p2 == 0 ? str1 : 0; + + while (*p1 != 0 && *p2 != 0) + { + if (tolower(*p1) == tolower(*p2)) + { + if (r == 0) + { + r = p1; + } + + p2++; + } + else + { + p2 = str2; + if (r != 0) + { + p1 = r + 1; + } + + if (tolower(*p1) == tolower(*p2)) + { + r = p1; + p2++; + } + else + { + r = 0; + } + } + + p1++; + } + + return *p2 == 0 ? (char *)r : 0; +} + +static void usage(char *name) +{ + fprintf(stderr, + "usage: %s [options]\n" + " -d name device to open (/dev/mqnic0)\n" + " -s slot slot to program\n" + " -r file read flash to file\n" + " -w file write and verify flash from file\n" + " -e erase flash\n" + " -b boot FPGA from flash\n" + " -t hot reset FPGA\n" + " -y no interactive confirm\n", + name); +} + +int flash_read_progress(struct flash_device *fdev, size_t addr, size_t len, void *dest) +{ + int ret = 0; + size_t remain = len; + size_t seg; + int step = 0x10000; + + printf("Start address: 0x%08lx\n", addr); + printf("Length: 0x%08lx\n", len); + + while (remain > 0) + { + if (remain > step) + { + // longer than step, trim + if ((addr + step) & (step-1)) + { + // align to step size + seg = step - ((addr + step) & (step-1)); + } + else + { + // already aligned + seg = step; + } + } + else + { + // shorter than step + seg = remain; + } + + printf("Read address 0x%08lx, length 0x%08lx (%ld%%)\r", addr, seg, (100*(len-remain))/len); + fflush(stdout); + + ret = flash_read(fdev, addr, seg, dest); + + if (ret) { + fprintf(stderr, "\nRead failed\n"); + goto err; + } + + addr += seg; + remain -= seg; + dest += seg; + } + + printf("\n"); + +err: + return ret; +} + +int flash_write_progress(struct flash_device *fdev, size_t addr, size_t len, const void *src) +{ + int ret = 0; + size_t remain = len; + size_t seg; + int step = 0x10000; + + printf("Start address: 0x%08lx\n", addr); + printf("Length: 0x%08lx\n", len); + + step = fdev->write_buffer_size > step ? fdev->write_buffer_size : step; + + while (remain > 0) + { + if (remain > step) + { + // longer than step, trim + if ((addr + step) & (step-1)) + { + // align to step size + seg = step - ((addr + step) & (step-1)); + } + else + { + // already aligned + seg = step; + } + } + else + { + // shorter than step + seg = remain; + } + + printf("Write address 0x%08lx, length 0x%08lx (%ld%%)\r", addr, seg, (100*(len-remain))/len); + fflush(stdout); + + ret = flash_write(fdev, addr, seg, src); + + if (ret) { + fprintf(stderr, "\nWrite failed\n"); + goto err; + } + + addr += seg; + remain -= seg; + src += seg; + } + + printf("\n"); + +err: + return ret; +} + +int flash_write_verify_progress(struct flash_device *fdev, size_t addr, size_t len, const void *src) +{ + int ret = 0; + size_t remain = len; + size_t seg; + int step = 0x10000; + const uint8_t *ptr = src; + uint8_t *check_buf; + + printf("Start address: 0x%08lx\n", addr); + printf("Length: 0x%08lx\n", len); + + step = fdev->write_buffer_size > step ? fdev->write_buffer_size : step; + + check_buf = calloc(step, 1); + + if (!check_buf) + return -1; + + while (remain > 0) + { + if (remain > step) + { + // longer than step, trim + if ((addr + step) & (step-1)) + { + // align to step size + seg = step - ((addr + step) & (step-1)); + } + else + { + // already aligned + seg = step; + } + } + else + { + // shorter than step + seg = remain; + } + + printf("Write/verify address 0x%08lx, length 0x%08lx (%ld%%)\r", addr, seg, (100*(len-remain))/len); + fflush(stdout); + + ret = flash_write(fdev, addr, seg, ptr); + + if (ret) { + fprintf(stderr, "\nWrite failed\n"); + goto err; + } + + for (int read_attempts = 3; read_attempts >= 0; read_attempts--) + { + ret = flash_read(fdev, addr, seg, check_buf); + + if (ret) { + fprintf(stderr, "\nRead failed\n"); + goto err; + } + + if (memcmp(ptr, check_buf, seg)) + { + fprintf(stderr, "\nVerify failed (%d more attempts)\n", read_attempts); + + for (size_t k = 0; k < seg; k++) + { + if (ptr[k] != check_buf[k]) + { + fprintf(stderr, "flash offset 0x%08lx: expected 0x%02x, read 0x%02x\n", + addr+k, ptr[k], check_buf[k]); + } + } + + if (read_attempts > 0) + continue; + + ret = -1; + goto err; + } + } + + addr += seg; + remain -= seg; + ptr += seg; + } + + printf("\n"); + +err: + free(check_buf); + return ret; +} + +int flash_erase_progress(struct flash_device *fdev, size_t addr, size_t len) +{ + int ret; + size_t remain = len; + size_t seg; + int step = 0x10000; + + printf("Start address: 0x%08lx\n", addr); + printf("Length: 0x%08lx\n", len); + + step = fdev->erase_block_size > step ? fdev->erase_block_size : step; + + while (remain > 0) + { + if (remain > step) + { + // longer than step, trim + if ((addr + step) & (step-1)) + { + // align to step size + seg = step - ((addr + step) & (step-1)); + } + else + { + // already aligned + seg = step; + } + } + else + { + // shorter than step + seg = remain; + } + + printf("Erase address 0x%08lx, length 0x%08lx (%ld%%)\r", addr, seg, ((100*(len-remain))/len)); + fflush(stdout); + + ret = flash_erase(fdev, addr, seg); + + if (ret) + return ret; + + addr += seg; + remain -= seg; + } + + printf("\n"); + + return 0; +} + +int write_str_to_file(const char *file_name, const char *str) +{ + int ret = 0; + FILE *fp = fopen(file_name, "w"); + + if (!fp) + { + perror("failed to open file"); + return -1; + } + + if (fputs(str, fp) == EOF) + { + perror("failed to write to file"); + ret = -1; + } + + fclose(fp); + return ret; +} + +int write_1_to_file(const char *file_name) +{ + return write_str_to_file(file_name, "1"); +} + +#define FILE_TYPE_BIN 0 +#define FILE_TYPE_HEX 1 +#define FILE_TYPE_BIT 2 + +int file_type_from_ext(const char *file_name) +{ + char *ptr; + char buffer[32]; + + ptr = strrchr(file_name, '.'); + + if (!ptr) + { + return FILE_TYPE_BIN; + } + + ptr++; + + for (int i = 0; i < sizeof(buffer)-1 && *ptr; i++) + { + buffer[i] = tolower(*ptr++); + buffer[i+1] = 0; + } + + if (strcmp(buffer, "hex") == 0 || strcmp(buffer, "mcs") == 0) + { + return FILE_TYPE_HEX; + } + + if (strcmp(buffer, "bit") == 0) + { + return FILE_TYPE_BIT; + } + + return FILE_TYPE_BIN; +} + +int pcie_hot_reset(const char *pci_port_path) +{ + int fd; + char path[PATH_MAX+32]; + char buf[32]; + + snprintf(path, sizeof(path), "%s/config", pci_port_path); + + fd = open(path, O_RDWR); + + if (!fd) + { + perror("Failed to open config region of port"); + return -1; + } + + // set and then clear secondary bus reset bit (mask 0x0040) + // in the bridge control register (offset 0x3e) + pread(fd, buf, 2, PCI_BRIDGE_CONTROL); + + buf[2] = buf[0] | PCI_BRIDGE_CTL_BUS_RESET; + buf[3] = buf[1]; + + pwrite(fd, buf+2, 2, PCI_BRIDGE_CONTROL); + + usleep(10000); + + pwrite(fd, buf, 2, PCI_BRIDGE_CONTROL); + + close(fd); + + return 0; +} + +int pcie_disable_fatal_err(const char *pci_port_path) +{ + int fd; + char path[PATH_MAX+32]; + char buf[32]; + int offset; + + snprintf(path, sizeof(path), "%s/config", pci_port_path); + + fd = open(path, O_RDWR); + + if (!fd) + { + perror("Failed to open config region of port"); + return -1; + } + + // clear SERR bit (mask 0x0100) in command register (offset 0x04) + pread(fd, buf, 2, PCI_COMMAND); + + buf[1] &= ~(PCI_COMMAND_SERR >> 8); + + pwrite(fd, buf, 2, PCI_COMMAND); + + // clear fatal error reporting bit (mask 0x0004) in + // PCIe capability device control register (offset 0x08) + + // find PCIe capability (ID 0x10) + pread(fd, buf, 1, PCI_CAPABILITY_LIST); + + offset = buf[0] & 0xfc; + + while (offset > 0) + { + pread(fd, buf, 2, offset); + + if (buf[0] == PCI_CAP_ID_EXP) + break; + + offset = buf[1] & 0xfc; + } + + // clear bit + if (offset) + { + pread(fd, buf, 2, offset+PCI_EXP_DEVCTL); + + buf[0] &= ~PCI_EXP_DEVCTL_FERE; + + pwrite(fd, buf, 2, offset+PCI_EXP_DEVCTL); + } + + close(fd); + + return 0; +} + +int main(int argc, char *argv[]) +{ + char *name; + int opt; + int ret = 0; + + char *device = NULL; + char *read_file_name = NULL; + FILE *read_file = NULL; + char *write_file_name = NULL; + FILE *write_file = NULL; + + char path[PATH_MAX+32]; + char pci_device_path[PATH_MAX]; + char pci_port_path[PATH_MAX]; + char *ptr; + + int slot = -1; + + char action_read = 0; + char action_write = 0; + char action_erase = 0; + char action_boot = 0; + char action_reset = 0; + char no_confirm = 0; + + struct mqnic *dev = NULL; + + struct mqnic_reg_block *flash_rb = NULL; + + struct flash_device *pri_flash = NULL; + struct flash_device *sec_flash = NULL; + + int flash_segment_count = 0; + size_t flash_segment_start[MAX_SEGMENTS]; + size_t flash_segment_length[MAX_SEGMENTS]; + + name = strrchr(argv[0], '/'); + name = name ? 1+name : argv[0]; + + while ((opt = getopt(argc, argv, "d:s:r:w:ebtyh?")) != EOF) + { + switch (opt) + { + case 'd': + device = optarg; + break; + case 's': + slot = atoi(optarg); + break; + case 'r': + action_read = 1; + read_file_name = optarg; + break; + case 'w': + action_write = 1; + write_file_name = optarg; + break; + case 'e': + action_erase = 1; + break; + case 'b': + action_boot = 1; + action_reset = 1; + break; + case 't': + action_reset = 1; + break; + case 'y': + no_confirm = 1; + break; + case 'h': + case '?': + usage(name); + return 0; + default: + usage(name); + return -1; + } + } + + if (!device) + { + fprintf(stderr, "Device not specified\n"); + usage(name); + return -1; + } + + dev = mqnic_open(device); + + if (!dev) + { + fprintf(stderr, "Failed to open device\n"); + return -1; + } + + if (!dev->pci_device_path[0]) + { + fprintf(stderr, "Failed to determine PCIe device path\n"); + ret = -1; + goto err; + } + + // snprintf(device_path, sizeof(device_path), dev->device_path) + snprintf(pci_device_path, sizeof(pci_device_path), "%s", dev->pci_device_path); + + // determine sysfs path of upstream port + snprintf(pci_port_path, sizeof(pci_port_path), "%s", pci_device_path); + ptr = strrchr(pci_port_path, '/'); + if (ptr) + *ptr = 0; + + printf("PCIe ID (device): %s\n", strrchr(pci_device_path, '/')+1); + printf("PCIe ID (upstream port): %s\n", strrchr(pci_port_path, '/')+1); + + mqnic_print_fw_id(dev); + + if (dev->fpga_id == 0 || dev->fpga_id == 0xffffffff) + { + fprintf(stderr, "Invalid FPGA ID\n"); + ret = -1; + goto skip_flash; + } + + uint32_t flash_format = 0; + + uint8_t flash_configuration = 0; + uint8_t flash_data_width = 0; + uint8_t flash_default_segment = 0; + uint8_t flash_fallback_segment = 0; + uint32_t flash_segment0_length = 0; + + int bitswap = 0; + int word_size = 8; + int dual_qspi = 0; + + size_t flash_size = 0; + size_t segment_size = 0; + size_t segment_offset = 0; + + if ((flash_rb = mqnic_find_reg_block(dev->rb_list, MQNIC_RB_SPI_FLASH_TYPE, 0, 0))) + { + uint32_t reg_val; + + // SPI flash + flash_format = mqnic_reg_read32(flash_rb->regs, MQNIC_RB_SPI_FLASH_REG_FORMAT); + + printf("Flash type: SPI\n"); + printf("Flash format: 0x%08x\n", flash_format); + + switch (flash_rb->version) { + case 0x00000100: + flash_configuration = (flash_format >> 8) & 0xff; + flash_default_segment = (flash_configuration > 1 ? 1 : 0); + flash_fallback_segment = 0; + flash_segment0_length = 0; + + if (flash_configuration == 0x81) + { + // Alveo boards + flash_configuration = 2; + flash_segment0_length = 0x01002000; + } + break; + case MQNIC_RB_SPI_FLASH_VER: + flash_configuration = flash_format & 0xf; + flash_default_segment = (flash_format >> 4) & 0xf; + flash_fallback_segment = (flash_format >> 8) & 0xf; + flash_segment0_length = flash_format & 0xfffff000; + break; + default: + fprintf(stderr, "Unknown SPI flash block version\n"); + ret = -1; + goto skip_flash; + } + + // determine data width + flash_data_width = 0; + + mqnic_reg_write32(flash_rb->regs, MQNIC_RB_SPI_FLASH_REG_CTRL_0, 0x0002000f); + reg_val = mqnic_reg_read32(flash_rb->regs, MQNIC_RB_SPI_FLASH_REG_CTRL_0) & 0xf; + mqnic_reg_write32(flash_rb->regs, MQNIC_RB_SPI_FLASH_REG_CTRL_0, 0x00020000); + + while (reg_val) + { + reg_val >>= 1; + flash_data_width++; + } + + mqnic_reg_write32(flash_rb->regs, MQNIC_RB_SPI_FLASH_REG_CTRL_1, 0x0002000f); + reg_val = mqnic_reg_read32(flash_rb->regs, MQNIC_RB_SPI_FLASH_REG_CTRL_1) & 0xf; + mqnic_reg_write32(flash_rb->regs, MQNIC_RB_SPI_FLASH_REG_CTRL_1, 0x00020000); + + while (reg_val) + { + reg_val >>= 1; + flash_data_width++; + } + + printf("Data width: %d\n", flash_data_width); + + if (flash_data_width > 4) + { + dual_qspi = 1; + pri_flash = flash_open_spi(4, flash_rb->regs+MQNIC_RB_SPI_FLASH_REG_CTRL_0); + sec_flash = flash_open_spi(4, flash_rb->regs+MQNIC_RB_SPI_FLASH_REG_CTRL_1); + + if (!pri_flash || !sec_flash) + { + fprintf(stderr, "Failed to connect to flash device\n"); + ret = -1; + goto skip_flash; + } + + flash_size = pri_flash->size+sec_flash->size; + } + else + { + pri_flash = flash_open_spi(flash_data_width, flash_rb->regs+MQNIC_RB_SPI_FLASH_REG_CTRL_0); + + if (!pri_flash) + { + fprintf(stderr, "Failed to connect to flash device\n"); + ret = -1; + goto skip_flash; + } + + flash_size = pri_flash->size; + } + } + else if ((flash_rb = mqnic_find_reg_block(dev->rb_list, MQNIC_RB_BPI_FLASH_TYPE, 0, 0))) + { + uint32_t reg_val; + + // BPI flash + flash_format = mqnic_reg_read32(flash_rb->regs, MQNIC_RB_BPI_FLASH_REG_FORMAT); + + printf("Flash type: BPI\n"); + printf("Flash format: 0x%08x\n", flash_format); + + switch (flash_rb->version) { + case 0x00000100: + flash_configuration = (flash_format >> 8) & 0xff; + flash_default_segment = (flash_configuration > 1 ? 1 : 0); + flash_fallback_segment = 0; + flash_segment0_length = 0; + break; + case MQNIC_RB_BPI_FLASH_VER: + flash_configuration = flash_format & 0xf; + flash_default_segment = (flash_format >> 4) & 0xf; + flash_fallback_segment = (flash_format >> 8) & 0xf; + flash_segment0_length = flash_format & 0xfffff000; + break; + default: + fprintf(stderr, "Unknown BPI flash block version\n"); + ret = -1; + goto skip_flash; + } + + // determine data width + mqnic_reg_write32(flash_rb->regs, MQNIC_RB_BPI_FLASH_REG_CTRL, 0x0001010f); + mqnic_reg_write32(flash_rb->regs, MQNIC_RB_BPI_FLASH_REG_DATA, 0xffffffff); + reg_val = mqnic_reg_read32(flash_rb->regs, MQNIC_RB_BPI_FLASH_REG_DATA); + mqnic_reg_write32(flash_rb->regs, MQNIC_RB_BPI_FLASH_REG_CTRL, 0x0000000f); + mqnic_reg_write32(flash_rb->regs, MQNIC_RB_BPI_FLASH_REG_DATA, 0x00000000); + + flash_data_width = 0; + while (reg_val) + { + reg_val >>= 1; + flash_data_width++; + } + + printf("Data width: %d\n", flash_data_width); + + bitswap = 1; + + if (flash_data_width == 16) + { + word_size = 16; + } + + pri_flash = flash_open_bpi(flash_data_width, + flash_rb->regs+MQNIC_RB_BPI_FLASH_REG_CTRL, + flash_rb->regs+MQNIC_RB_BPI_FLASH_REG_ADDR, + flash_rb->regs+MQNIC_RB_BPI_FLASH_REG_DATA); + + if (!pri_flash) + { + fprintf(stderr, "Failed to connect to flash device\n"); + ret = -1; + goto skip_flash; + } + + flash_size = pri_flash->size; + } + else + { + fprintf(stderr, "Failed to detect flash\n"); + ret = -1; + goto skip_flash; + } + + switch (flash_configuration) + { + case 0: + case 1: + flash_segment_count = 1; + flash_segment_start[0] = 0; + flash_segment_length[0] = flash_size; + break; + case 2: + if (flash_segment0_length == 0) + { + flash_segment0_length = flash_size >> 1; + } + else if (flash_size < flash_segment0_length) + { + fprintf(stderr, "Invalid flash configuration\n"); + ret = -1; + goto skip_flash; + } + + flash_segment_count = 2; + flash_segment_start[0] = 0; + flash_segment_length[0] = flash_segment0_length; + flash_segment_start[1] = flash_segment_start[0]+flash_segment_length[0]; + flash_segment_length[1] = flash_size-flash_segment_start[1]; + break; + case 4: + flash_segment_count = 4; + flash_segment_start[0] = 0; + flash_segment_length[0] = flash_size >> 2; + for (int k = 1; k < 4; k++) + { + flash_segment_start[k] = flash_segment_start[k-1]+flash_segment_length[k-1]; + flash_segment_length[k] = flash_size >> 2; + } + break; + case 8: + flash_segment_count = 8; + flash_segment_start[0] = 0; + flash_segment_length[0] = flash_size >> 3; + for (int k = 1; k < 8; k++) + { + flash_segment_start[k] = flash_segment_start[k-1]+flash_segment_length[k-1]; + flash_segment_length[k] = flash_size >> 3; + } + break; + default: + fprintf(stderr, "Unknown flash configuration (0x%02x)\n", flash_configuration); + ret = -1; + goto skip_flash; + } + + for (int k = 0; k < flash_segment_count; k++) + { + printf("Flash segment %d: start 0x%08lx length 0x%08lx\n", k, flash_segment_start[k], flash_segment_length[k]); + } + + printf("Default segment: %d\n", flash_default_segment); + if (flash_fallback_segment == flash_default_segment || flash_fallback_segment >= flash_segment_count) + { + printf("Fallback segment: none\n"); + } + else + { + printf("Fallback segment: %d\n", flash_fallback_segment); + } + + if (slot < 0) + { + slot = flash_default_segment; + } + + if ((action_read || action_write) && (slot < 0 || slot >= flash_segment_count)) + { + fprintf(stderr, "Requested slot is not valid (%d)\n", slot); + ret = -1; + goto err; + } + + segment_offset = flash_segment_start[slot]; + segment_size = flash_segment_length[slot]; + + printf("Selected: segment %d start 0x%08lx length 0x%08lx\n", slot, segment_offset, segment_size); + + if (action_erase) + { + if (!no_confirm) + { + char str[32]; + + printf("Are you sure you want to erase the selected segment?\n"); + printf("[y/N]: "); + + fgets(str, sizeof(str), stdin); + + if (str[0] != 'y' && str[0] != 'Y') + goto err; + } + + if (dual_qspi) + { + // Dual QSPI flash + printf("Erasing primary flash...\n"); + if (flash_erase_progress(pri_flash, segment_offset/2, segment_size/2)) + { + fprintf(stderr, "Erase failed!\n"); + ret = -1; + goto err; + } + + printf("Erasing secondary flash...\n"); + if (flash_erase_progress(sec_flash, segment_offset/2, segment_size/2)) + { + fprintf(stderr, "Erase failed!\n"); + ret = -1; + goto err; + } + + printf("Erase complete!\n"); + } + else + { + // SPI or BPI flash + printf("Erasing flash...\n"); + if (flash_erase_progress(pri_flash, segment_offset, segment_size)) + { + fprintf(stderr, "Erase failed!\n"); + ret = -1; + goto err; + } + + printf("Erase complete!\n"); + } + } + + if (action_write) + { + char *segment = calloc(segment_size, 1); + memset(segment, 0xff, segment_size); + size_t len; + + int file_type = file_type_from_ext(write_file_name); + + if (file_type == FILE_TYPE_BIN) + { + // read binary file + printf("Reading binary file \"%s\"...\n", write_file_name); + write_file = fopen(write_file_name, "rb"); + + if (!write_file) + { + fprintf(stderr, "Failed to open file\n"); + free(segment); + ret = -1; + goto err; + } + + fseek(write_file, 0, SEEK_END); + len = ftell(write_file); + rewind(write_file); + + if (len > segment_size) + { + fprintf(stderr, "File larger than segment (%ld > %ld)\n", len, segment_size); + fclose(write_file); + free(segment); + ret = -1; + goto err; + } + + if (fread(segment, 1, len, write_file) < len) + { + fprintf(stderr, "Error reading file\n"); + fclose(write_file); + free(segment); + ret = -1; + goto err; + } + + fclose(write_file); + } + else if (file_type == FILE_TYPE_BIT) + { + // read bit file + struct bitfile *bf; + char fpga_part[128]; + char *ptr1, *ptr2; + int match = 0; + + printf("Reading bit file \"%s\"...\n", write_file_name); + bf = bitfile_create_from_file(write_file_name); + + if (!bf) + { + fprintf(stderr, "Error reading bit file\n"); + free(segment); + ret = -1; + goto err; + } + + printf("Part: %s\n", bf->part); + printf("Date: %s %s\n", bf->date, bf->time); + + // check device type + // dev->fpga_part may contain multiple possible device types, separated by underscores + strcpy(fpga_part, dev->fpga_part); + ptr1 = ptr2 = fpga_part; + + while (ptr2) + { + ptr2 = strchr(ptr1, '_'); + + if (ptr2) + *ptr2 = 0; + + if (stristr(bf->part, ptr1) == bf->part) + match = 1; + + if (ptr2) + ptr1 = ptr2+1; + } + + if (!match) + { + fprintf(stderr, "Device mismatch (target is %s, file is %s)\n", dev->fpga_part, bf->part); + bitfile_close(bf); + free(segment); + ret = -1; + goto err; + } + + // check for available space + if (bf->data_len > segment_size) + { + fprintf(stderr, "File larger than segment (%ld > %ld)\n", bf->data_len, segment_size); + bitfile_close(bf); + free(segment); + ret = -1; + goto err; + } + + len = bf->data_len; + memcpy(segment, bf->data, bf->data_len); + + bitfile_close(bf); + } + else if (file_type == FILE_TYPE_HEX) + { + fprintf(stderr, "Hex files are not currently supported\n"); + free(segment); + ret = -1; + goto err; + } + else + { + fprintf(stderr, "Unsupported file type\n"); + free(segment); + ret = -1; + goto err; + } + + // check sync word + if (memcmp(segment+0x50, "\xAA\x99\x55\x66", 4)) + { + fprintf(stderr, "Bitstream sync word not found\n"); + free(segment); + ret = -1; + goto err; + } + + // TODO check for and confirm FPGA ID + + if (bitswap) + { + if (word_size == 16) + { + uint16_t *p = (uint16_t *)segment; + + for (size_t k = 0; k < segment_size; k += 2) + { + *p = reverse_bits_16(*p); + p++; + } + } + else + { + uint8_t *p = (uint8_t *)segment; + + for (size_t k = 0; k < segment_size; k++) + { + *p = reverse_bits_8(*p); + p++; + } + } + } + + if (dual_qspi) + { + // Dual QSPI flash + + // check sync word for dual QSPI re-sync + if (memcmp(segment+0x70, "\xAA\x99\x55\x66", 4)) + { + fprintf(stderr, "Bitstream sync word not found for dual QSPI re-sync\n"); + free(segment); + ret = -1; + goto err; + } + + char *pri_buf = calloc(segment_size/2, 1); + char *sec_buf = calloc(segment_size/2, 1); + memset(pri_buf, 0xff, segment_size/2); + memset(sec_buf, 0xff, segment_size/2); + + int offset = 0x68; + + size_t len_int = (len - offset) / 2 + offset; + + if (len_int > segment_size/2) + len_int = segment_size/2; + + memcpy(pri_buf, segment, offset); + + char *c1 = pri_buf+offset; + char *c2 = sec_buf+offset; + + for (size_t k = offset; k < segment_size-offset; k += 2) + { + *c1 = (segment[k+1] & 0x0f) | ((segment[k] << 4) & 0xf0); + *c2 = ((segment[k+1] >> 4) & 0x0f) | (segment[k] & 0xf0); + c1++; + c2++; + } + + // round up length to block size + if ((segment_offset/2 + len_int) & (pri_flash->erase_block_size-1)) + { + len_int += pri_flash->erase_block_size - ((segment_offset/2 + len_int) & (pri_flash->erase_block_size-1)); + } + + if (!no_confirm) + { + char str[32]; + + printf("Are you sure you want to write the selected segment?\n"); + printf("[y/N]: "); + + fgets(str, sizeof(str), stdin); + + if (str[0] != 'y' && str[0] != 'Y') + goto err; + } + + printf("Erasing primary flash...\n"); + if (flash_erase_progress(pri_flash, segment_offset/2, len_int)) + { + fprintf(stderr, "Erase failed!\n"); + ret = -1; + free(segment); + free(pri_buf); + free(sec_buf); + goto err; + } + + printf("Erasing secondary flash...\n"); + if (flash_erase_progress(sec_flash, segment_offset/2, len_int)) + { + fprintf(stderr, "Erase failed!\n"); + ret = -1; + free(segment); + free(pri_buf); + free(sec_buf); + goto err; + } + + printf("Writing and verifying primary flash...\n"); + if (flash_write_verify_progress(pri_flash, segment_offset/2, len_int, pri_buf)) + { + fprintf(stderr, "Write/verify failed!\n"); + ret = -1; + free(segment); + free(pri_buf); + free(sec_buf); + goto err; + } + + printf("Writing and verifying secondary flash...\n"); + if (flash_write_verify_progress(sec_flash, segment_offset/2, len_int, sec_buf)) + { + fprintf(stderr, "Write/verify failed!\n"); + ret = -1; + free(segment); + free(pri_buf); + free(sec_buf); + goto err; + } + + printf("Programming succeeded!\n"); + + free(pri_buf); + free(sec_buf); + } + else + { + // SPI or BPI flash + + // round up length to block size + if ((segment_offset + len) & (pri_flash->erase_block_size-1)) + { + len += pri_flash->erase_block_size - ((segment_offset + len) & (pri_flash->erase_block_size-1)); + } + + if (!no_confirm) + { + char str[32]; + + printf("Are you sure you want to write the selected segment?\n"); + printf("[y/N]: "); + + fgets(str, sizeof(str), stdin); + + if (str[0] != 'y' && str[0] != 'Y') + goto err; + } + + printf("Erasing flash...\n"); + if (flash_erase_progress(pri_flash, segment_offset, len)) + { + fprintf(stderr, "Erase failed!\n"); + ret = -1; + free(segment); + goto err; + } + + printf("Writing and verifying flash...\n"); + if (flash_write_verify_progress(pri_flash, segment_offset, len, segment)) + { + fprintf(stderr, "Write/verify failed!\n"); + ret = -1; + free(segment); + goto err; + } + + printf("Programming succeeded!\n"); + } + + free(segment); + } + + if (action_read) + { + char *segment = calloc(segment_size, 1); + memset(segment, 0xff, segment_size); + + if (dual_qspi) + { + char *pri_buf = calloc(segment_size/2, 1); + char *sec_buf = calloc(segment_size/2, 1); + + printf("Reading primary flash...\n"); + flash_read_progress(pri_flash, segment_offset/2, segment_size/2, pri_buf); + printf("Reading secondary flash...\n"); + flash_read_progress(sec_flash, segment_offset/2, segment_size/2, sec_buf); + + int offset = 0x68; + + memcpy(segment, pri_buf, offset); + + char *c1 = pri_buf+offset; + char *c2 = sec_buf+offset; + + for (size_t k = offset; k < segment_size-offset; k += 2) + { + segment[k] = ((*c1 >> 4) & 0x0f) | (*c2 & 0xf0); + segment[k+1] = (*c1 & 0x0f) | ((*c2 << 4) & 0xf0); + c1++; + c2++; + } + + free(pri_buf); + free(sec_buf); + } + else + { + printf("Reading flash...\n"); + flash_read_progress(pri_flash, segment_offset, segment_size, segment); + } + + if (bitswap) + { + if (word_size == 16) + { + uint16_t *p = (uint16_t *)segment; + + for (size_t k = 0; k < segment_size; k += 2) + { + *p = reverse_bits_16(*p); + p++; + } + } + else + { + uint8_t *p = (uint8_t *)segment; + + for (size_t k = 0; k < segment_size; k++) + { + *p = reverse_bits_8(*p); + p++; + } + } + } + + int file_type = file_type_from_ext(read_file_name); + + if (file_type == FILE_TYPE_BIN) + { + // write binary file + printf("Writing binary file \"%s\"...\n", read_file_name); + read_file = fopen(read_file_name, "wb"); + fwrite(segment, 1, segment_size, read_file); + fclose(read_file); + } + else if (file_type == FILE_TYPE_HEX) + { + fprintf(stderr, "Hex files are not currently supported\n"); + free(segment); + ret = -1; + goto err; + } + else + { + fprintf(stderr, "Unsupported file type\n"); + free(segment); + ret = -1; + goto err; + } + + free(segment); + } + +skip_flash: + if (ret && (action_read || action_write)) + { + goto err; + } + else + { + ret = 0; + } + + flash_release(pri_flash); + pri_flash = NULL; + flash_release(sec_flash); + sec_flash = NULL; + + if (action_boot || action_reset) + { + if (!no_confirm) + { + char str[32]; + + if (action_boot) + printf("Are you sure you want to boot from flash?\n"); + else + printf("Are you sure you want to perform a reset?\n"); + printf("[y/N]: "); + + fgets(str, sizeof(str), stdin); + + if (str[0] != 'y' && str[0] != 'Y') + goto err; + } + + printf("Preparing to reset device...\n"); + + // disable fatal error reporting on port (to prevent IPMI-triggered reboot) + printf("Disabling PCIe fatal error reporting on port...\n"); + pcie_disable_fatal_err(pci_port_path); + + // disconnect from device + mqnic_close(dev); + dev = NULL; + + // attempt to disconnect driver + snprintf(path, sizeof(path), "%s/driver/unbind", pci_device_path); + + if (access(path, F_OK) == 0) + { + printf("Unbinding driver...\n"); + write_str_to_file(path, ptr+1); + } + else + { + printf("No driver bound\n"); + } + + sleep(1); + + // trigger FPGA reload + if (action_boot) + { + // reconnect directly to device + snprintf(path, sizeof(path), "%s/resource0", pci_device_path); + dev = mqnic_open(path); + + if (!dev) + { + fprintf(stderr, "Failed to open device\n"); + ret = -1; + goto err; + } + + // reload FPGA + printf("Triggering IPROG to reload FPGA...\n"); + if (flash_rb) + mqnic_reg_write32(flash_rb->regs, MQNIC_RB_BPI_FLASH_REG_FORMAT, 0xFEE1DEAD); + mqnic_reg_write32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FPGA_ID, 0xFEE1DEAD); + + // disconnect + mqnic_close(dev); + dev = NULL; + } + + // remove PCIe device + printf("Removing device...\n"); + + snprintf(path, sizeof(path), "%s/remove", pci_device_path); + + if (write_1_to_file(path)) + { + fprintf(stderr, "Failed to remove device!\n"); + ret = -1; + goto err; + } + + if (action_boot) + { + // give FPGA some time to boot from flash + sleep(4); + } + + sleep(1); + + for (int tries = 5; tries > 0; tries--) + { + printf("Performing hot reset on upstream port...\n"); + pcie_hot_reset(pci_port_path); + + sleep(2); + + printf("Rescanning on upstream port...\n"); + + snprintf(path, sizeof(path), "%s/rescan", pci_port_path); + + if (write_1_to_file(path)) + { + fprintf(stderr, "Rescan failed!\n"); + ret = -1; + goto err; + } + + // PCIe device will have a config space, so check for that + snprintf(path, sizeof(path), "%s/config", pci_device_path); + + if (access(path, F_OK) == 0) + { + printf("Success, device is online!\n"); + break; + } + else + { + if (tries > 0) + { + printf("Rescan failed, attempting another reset (up to %d more)\n", tries); + } + else + { + fprintf(stderr, "Rescan failed, device is offline!\n"); + ret = -1; + goto err; + } + } + } + + } + +err: + + flash_release(pri_flash); + flash_release(sec_flash); + + mqnic_close(dev); + + return ret; +} + + + + diff --git a/utils/mqnic-xcvr.c b/utils/mqnic-xcvr.c new file mode 100644 index 0000000..ba47ba9 --- /dev/null +++ b/utils/mqnic-xcvr.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#include +#include +#include +#include + +#include +#include "xcvr_gtye4.h" + +static void usage(char *name) +{ + fprintf(stderr, + "usage: %s [options]\n" + " -d name device to open (/dev/mqnic0)\n" + " -i number GT channel index, default 0\n" + " -m number GT channel mask\n" + " -p preset Load channel preset\n" + " -r Read registers\n" + " -t Reset channels\n" + " -c file Run eye scan and write CSV\n", + name); +} + +int main(int argc, char *argv[]) +{ + char *name; + int opt; + int ret = 0; + + char *device = NULL; + struct mqnic *dev; + int channel_mask = 1; + int channel_preset = 0; + char *channel_preset_str = ""; + int channel_read_regs = 0; + int channel_reset = 0; + + char *csv_file_name = NULL; + + name = strrchr(argv[0], '/'); + name = name ? 1+name : argv[0]; + + while ((opt = getopt(argc, argv, "d:i:m:p:rtc:h?")) != EOF) + { + switch (opt) + { + case 'd': + device = optarg; + break; + case 'i': + channel_mask = 1 << atoi(optarg); + break; + case 'm': + channel_mask = strtol(optarg, 0, 0); + break; + case 'p': + channel_preset_str = optarg; + break; + case 'r': + channel_read_regs = 1; + break; + case 't': + channel_reset = 1; + break; + case 'c': + csv_file_name = optarg; + break; + case 'h': + case '?': + usage(name); + return 0; + default: + usage(name); + return -1; + } + } + + if (!device) + { + fprintf(stderr, "Device not specified\n"); + usage(name); + return -1; + } + + dev = mqnic_open(device); + + if (!dev) + { + fprintf(stderr, "Failed to open device\n"); + return -1; + } + + if (dev->pci_device_path[0]) + { + char *ptr = strrchr(dev->pci_device_path, '/'); + if (ptr) + printf("PCIe ID: %s\n", ptr+1); + } + + printf("Device-level register blocks:\n"); + for (struct mqnic_reg_block *rb = dev->rb_list; rb->type && rb->version; rb++) + printf(" type 0x%08x (v %d.%d.%d.%d)\n", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + mqnic_print_fw_id(dev); + + struct gt_ch *ch; + struct gt_quad *quad; + struct gt_quad *gt_quads[16]; + int num_quads = 0; + + printf("Enumerate transceivers\n"); + for (int k = 0; k < 16; k++) + { + struct mqnic_reg_block *rb; + + rb = mqnic_find_reg_block(dev->rb_list, 0x0000C150, 0x00000100, k); + + if (!rb) + break; + + printf("Found DRP interface %d\n", k); + + quad = gt_create_quad_from_drp_rb(rb); + + if (!quad) + continue; + + quad->index = num_quads; + gt_quads[num_quads++] = quad; + + printf("Quad type: %s (0x%04x)\n", quad->type, quad->gt_type); + printf("Channel count: %d\n", quad->ch_count); + + for (int n = 0; n < quad->ch_count; n++) + { + printf("%d: %s channel: quad %d channel %d\n", quad->index*4+n, quad->type, quad->index, n); + } + + if (num_quads >= 16) + break; + } + + if (strlen(channel_preset_str)) + { + if (strcmp("10g_dfe", channel_preset_str) == 0) + channel_preset = GT_PRESET_10G_DFE; + if (strcmp("10g_lpm", channel_preset_str) == 0) + channel_preset = GT_PRESET_10G_LPM; + if (strcmp("25g_dfe", channel_preset_str) == 0) + channel_preset = GT_PRESET_25G_DFE; + if (strcmp("25g_lpm", channel_preset_str) == 0) + channel_preset = GT_PRESET_25G_LPM; + + if (!channel_preset) + { + fprintf(stderr, "Unknown preset\n"); + ret = -1; + goto err; + } + } + + for (int qi = 0; qi < num_quads; qi++) + { + quad = gt_quads[qi]; + for (int ci = 0; ci < quad->ch_count; ci++) + { + int index = qi*4 + ci; + const uint32_t *presets = {0}; + ch = &quad->ch[ci]; + + if ((channel_mask & (1 << index)) == 0) + continue; + + printf("Processing channel %d\n", index); + + if (gt_ch_get_available_presets(ch, &presets) == 0) + { + printf("Supported presets:"); + + while (*presets) + { + switch (*presets) + { + case GT_PRESET_10G_DFE: + printf(" 10g_dfe"); + break; + case GT_PRESET_10G_LPM: + printf(" 10g_lpm"); + break; + case GT_PRESET_25G_DFE: + printf(" 25g_dfe"); + break; + case GT_PRESET_25G_LPM: + printf(" 25g_lpm"); + break; + } + presets++; + } + + printf("\n"); + } + else + { + fprintf(stderr, "Failed to read presets\n"); + } + + if (channel_read_regs) + { + printf("PLL registers\n"); + + for (int k = 0; k <= 0xB0; k++) + { + uint32_t val; + gt_pll_reg_read(ch->pll, k, &val); + printf("0x%04x: 0x%04x\n", k, val); + } + + printf("Channel registers\n"); + + for (int k = 0; k <= 0x28C; k++) + { + uint32_t val; + gt_ch_reg_read(ch, k, &val); + printf("0x%04x: 0x%04x\n", k, val); + } + } + + if (channel_preset) + { + printf("Loading preset %s on channel %d\n", channel_preset_str, index); + gt_ch_load_preset(ch, channel_preset); + } + + if (channel_reset) + { + printf("Resetting channel %d\n", index); + gt_ch_rx_reset(ch); + gt_ch_tx_reset(ch); + } + } + } + + if (csv_file_name) + { + struct gt_eyescan_params params; + struct gt_eyescan_point point; + int done; + char csv_base_name[PATH_MAX]; + char csv_name[PATH_MAX]; + FILE *csv_file; + FILE *csv_files[16*4]; + char *ptr; + + uint32_t data_width; + uint32_t int_data_width; + + time_t cur_time; + struct tm *tm_info; + char datestr[32]; + + printf("Run eye scan\n"); + + params.target_bit_count = 1ULL << 30; + params.h_range = 0; + params.h_start = -32; + params.h_stop = 32; + params.h_step = 2; + params.v_range = 0; + params.v_start = -120; + params.v_stop = 120; + params.v_step = 6; + + // strip .csv extension + snprintf(csv_base_name, sizeof(csv_base_name), "%s", csv_file_name); + ptr = strstr(csv_base_name, ".csv"); + + if (ptr && ptr-csv_base_name == strlen(csv_base_name)-4) + *ptr = 0; + + // time string + time(&cur_time); + tm_info = localtime(&cur_time); + strftime(datestr, sizeof(datestr), "%F %T", tm_info); + + for (int qi = 0; qi < num_quads; qi++) + { + quad = gt_quads[qi]; + for (int ci = 0; ci < quad->ch_count; ci++) + { + int index = qi*4 + ci; + ch = &quad->ch[ci]; + + if ((channel_mask & (1 << index)) == 0) + continue; + + snprintf(csv_name, sizeof(csv_name), "%s_%d.csv", csv_base_name, index); + + printf("Measuring channel %d eye to '%s'\n", index, csv_name); + + ret = gt_ch_eyescan_start(ch, ¶ms); + if (ret < 0) + { + fprintf(stderr, "Failed to start eye scan on channel %d\n", index); + goto err; + } + + csv_file = fopen(csv_name, "w"); + + if (!csv_file) + { + fprintf(stderr, "Failed to open file\n"); + ret = -1; + goto err; + } + + csv_files[index] = csv_file; + + fprintf(csv_file, "#eyescan\n"); + fprintf(csv_file, "#date,'%s'\n", datestr); + + fprintf(csv_file, "#fpga_id,0x%08x\n", dev->fpga_id); + fprintf(csv_file, "#fw_id,0x%08x\n", dev->fw_id); + fprintf(csv_file, "#fw_version,'%d.%d.%d.%d'\n", dev->fw_ver >> 24, + (dev->fw_ver >> 16) & 0xff, + (dev->fw_ver >> 8) & 0xff, + dev->fw_ver & 0xff); + fprintf(csv_file, "#board_id,0x%08x\n", dev->board_id); + fprintf(csv_file, "#board_version,'%d.%d.%d.%d'\n", dev->board_ver >> 24, + (dev->board_ver >> 16) & 0xff, + (dev->board_ver >> 8) & 0xff, + dev->board_ver & 0xff); + fprintf(csv_file, "#build_date,'%s UTC'\n", dev->build_date_str); + fprintf(csv_file, "#git_hash,'%08x'\n", dev->git_hash); + fprintf(csv_file, "#release_info,'%08x'\n", dev->rel_info); + + fprintf(csv_file, "#channel_index,%d\n", index); + fprintf(csv_file, "#channel_type,%s\n", ch->quad->type); + fprintf(csv_file, "#quad,%d\n", ch->quad->index); + fprintf(csv_file, "#channel,%d\n", ch->index); + + gt_ch_get_rx_data_width(ch, &data_width); + gt_ch_get_rx_int_data_width(ch, &int_data_width); + + fprintf(csv_file, "#data_width,%d\n", data_width); + fprintf(csv_file, "#int_data_width,%d\n", int_data_width); + fprintf(csv_file, "#target_bit_count,%lu\n", params.target_bit_count); + fprintf(csv_file, "#h_range,%d\n", params.h_range); + fprintf(csv_file, "#h_start,%d\n", params.h_start); + fprintf(csv_file, "#h_stop,%d\n", params.h_stop); + fprintf(csv_file, "#h_step,%d\n", params.h_step); + fprintf(csv_file, "#v_range,%d\n", params.v_range); + fprintf(csv_file, "#v_start,%d\n", params.v_start); + fprintf(csv_file, "#v_stop,%d\n", params.v_stop); + fprintf(csv_file, "#v_step,%d\n", params.v_step); + fprintf(csv_file, "h_offset,v_offset,ut_sign,bit_count,error_count\n"); + + fflush(csv_file); + } + } + + done = 0; + while (!done) + { + done = 1; + for (int qi = 0; qi < num_quads; qi++) + { + quad = gt_quads[qi]; + for (int ci = 0; ci < quad->ch_count; ci++) + { + int index = qi*4 + ci; + ch = &quad->ch[ci]; + + if ((channel_mask & (1 << index)) == 0) + continue; + + ret = gt_ch_eyescan_step(ch, &point); + if (ret < 0) + { + fprintf(stderr, "Eye scan failed on channel %d\n", index); + goto err; + } + if (ret == 1) + { + // new point + printf("Channel %d point x %d, y %d\n", index, point.x, point.y); + + fprintf(csv_files[index], "%d,%d,%d,%lu,%lu\n", point.x, point.y, point.ut_sign, point.bit_count, point.error_count); + fflush(csv_files[index]); + + done = 0; + } + if (ret == 2) + { + // acquiring + done = 0; + } + } + } + } + + printf("Done\n"); + } + +err: + + mqnic_close(dev); + + return ret; +} diff --git a/utils/perout.c b/utils/perout.c new file mode 100644 index 0000000..33f7c2e --- /dev/null +++ b/utils/perout.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "timespec.h" + +#ifndef CLOCK_INVALID +#define CLOCK_INVALID -1 +#endif + +static clockid_t get_clockid(int fd) +{ +#define CLOCKFD 3 +#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD) + + return FD_TO_CLOCKID(fd); +} + +#define NSEC_PER_SEC 1000000000 + +static void usage(char *name) +{ + fprintf(stderr, + "usage: %s [options]\n" + " -d name device to open\n" + " -s number start time (ns)\n" + " -p number period (ns)\n", + name); +} + +int main(int argc, char *argv[]) +{ + char *name; + int opt; + + char *device = NULL; + int ptp_fd; + clockid_t clkid; + + struct ptp_perout_request perout_request; + struct timespec ts_now; + struct timespec ts_start; + struct timespec ts_period; + + int64_t start_nsec = 0; + int64_t period_nsec = 0; + + name = strrchr(argv[0], '/'); + name = name ? 1+name : argv[0]; + + while ((opt = getopt(argc, argv, "d:s:p:h?")) != EOF) + { + switch (opt) + { + case 'd': + device = optarg; + break; + case 's': + start_nsec = atoll(optarg); + break; + case 'p': + period_nsec = atoll(optarg); + break; + case 'h': + case '?': + usage(name); + return 0; + default: + usage(name); + return -1; + } + } + + if (!device) + { + fprintf(stderr, "PTP device not specified\n"); + usage(name); + return -1; + } + + ptp_fd = open(device, O_RDWR); + if (ptp_fd < 0) + { + fprintf(stderr, "Failed to open %s: %s\n", device, strerror(errno)); + return -1; + } + + clkid = get_clockid(ptp_fd); + if (clkid == CLOCK_INVALID) + { + fprintf(stderr, "Failed to read clock id\n"); + close(ptp_fd); + return -1; + } + + if (period_nsec > 0) + { + if (clock_gettime(clkid, &ts_now)) + { + perror("Failed to read current time"); + return -1; + } + + // normalize start + ts_start.tv_sec = start_nsec / NSEC_PER_SEC; + ts_start.tv_nsec = start_nsec - ts_start.tv_sec * NSEC_PER_SEC; + + // normalize period + ts_period.tv_sec = period_nsec / NSEC_PER_SEC; + ts_period.tv_nsec = period_nsec - ts_period.tv_sec * NSEC_PER_SEC; + + printf("time %ld.%09ld\n", ts_now.tv_sec, ts_now.tv_nsec); + printf("start %ld.%09ld\n", ts_start.tv_sec, ts_start.tv_nsec); + printf("period %ld.%09ld\n", ts_period.tv_sec, ts_period.tv_nsec); + + if (timespec_lt(ts_start, ts_now)) + { + // start time is in the past + + // modulo start with period + ts_start = timespec_mod(ts_start, ts_period); + + // align time with period + struct timespec ts_aligned = timespec_sub(ts_now, timespec_mod(ts_now, ts_period)); + + // add aligned time + ts_start = timespec_add(ts_start, ts_aligned); + } + + printf("time %ld.%09ld\n", ts_now.tv_sec, ts_now.tv_nsec); + printf("start %ld.%09ld\n", ts_start.tv_sec, ts_start.tv_nsec); + printf("period %ld.%09ld\n", ts_period.tv_sec, ts_period.tv_nsec); + + memset(&perout_request, 0, sizeof(perout_request)); + perout_request.index = 0; + perout_request.start.sec = ts_start.tv_sec; + perout_request.start.nsec = ts_start.tv_nsec; + perout_request.period.sec = ts_period.tv_sec; + perout_request.period.nsec = ts_period.tv_nsec; + + if (ioctl(ptp_fd, PTP_PEROUT_REQUEST, &perout_request)) + { + perror("PTP_PEROUT_REQUEST ioctl failed"); + } + else + { + printf("PTP_PEROUT_REQUEST ioctl OK\n"); + } + } + + close(ptp_fd); + return 0; +} + + + + diff --git a/utils/timespec.c b/utils/timespec.c new file mode 100644 index 0000000..86f5dda --- /dev/null +++ b/utils/timespec.c @@ -0,0 +1,739 @@ +/* Functions for working with timespec structures + * Written by Daniel Collins (2017) + * timespec_mod by Alex Forencich (2019) + * + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to +*/ + +/** \file timespec.c + * \brief Functions for working with timespec structures. + * + * This library aims to provide a comprehensive set of functions with + * well-defined behaviour that handle all edge cases (e.g. negative values) in + * a sensible manner. + * + * Negative values are allowed in the tv_sec and/or tv_usec field of timespec + * structures, tv_usec is always relative to tv_sec, so mixing positive and + * negative values will produce consistent results: + * + *
+ * { tv_sec = 1,  tv_nsec = 500000000  } ==  1.5 seconds
+ * { tv_sec = 1,  tv_nsec = 0          } ==  1.0 seconds
+ * { tv_sec = 1,  tv_nsec = -500000000 } ==  0.5 seconds
+ * { tv_sec = 0,  tv_nsec = 500000000  } ==  0.5 seconds
+ * { tv_sec = 0,  tv_nsec = 0          } ==  0.0 seconds
+ * { tv_sec = 0,  tv_nsec = -500000000 } == -0.5 seconds
+ * { tv_sec = -1, tv_nsec = 500000000  } == -0.5 seconds
+ * { tv_sec = -1, tv_nsec = 0          } == -1.0 seconds
+ * { tv_sec = -1, tv_nsec = -500000000 } == -1.5 seconds
+ * 
+ * + * Furthermore, any timespec structure processed or returned by library functions + * is normalised according to the rules in timespec_normalise(). +*/ + +#include +#include +#include +#include + +#include "timespec.h" + +#define NSEC_PER_SEC 1000000000 + +/** \fn struct timespec timespec_add(struct timespec ts1, struct timespec ts2) + * \brief Returns the result of adding two timespec structures. +*/ +struct timespec timespec_add(struct timespec ts1, struct timespec ts2) +{ + /* Normalise inputs to prevent tv_nsec rollover if whole-second values + * are packed in it. + */ + ts1 = timespec_normalise(ts1); + ts2 = timespec_normalise(ts2); + + ts1.tv_sec += ts2.tv_sec; + ts1.tv_nsec += ts2.tv_nsec; + + return timespec_normalise(ts1); +} + +/** \fn struct timespec timespec_sub(struct timespec ts1, struct timespec ts2) + * \brief Returns the result of subtracting ts2 from ts1. +*/ +struct timespec timespec_sub(struct timespec ts1, struct timespec ts2) +{ + /* Normalise inputs to prevent tv_nsec rollover if whole-second values + * are packed in it. + */ + ts1 = timespec_normalise(ts1); + ts2 = timespec_normalise(ts2); + + ts1.tv_sec -= ts2.tv_sec; + ts1.tv_nsec -= ts2.tv_nsec; + + return timespec_normalise(ts1); +} + +/** \fn struct timespec timespec_mod(struct timespec ts1, struct timespec ts2) + * \brief Returns the remainder left over after dividing ts1 by ts2 (ts1%ts2). +*/ +struct timespec timespec_mod(struct timespec ts1, struct timespec ts2) +{ + int i = 0; + bool neg1 = false; + bool neg2 = false; + + /* Normalise inputs to prevent tv_nsec rollover if whole-second values + * are packed in it. + */ + ts1 = timespec_normalise(ts1); + ts2 = timespec_normalise(ts2); + + /* If ts2 is zero, just return ts1 + */ + if (ts2.tv_sec == 0 && ts2.tv_nsec == 0) + { + return ts1; + } + + /* If inputs are negative, flip and record sign + */ + if (ts1.tv_sec < 0 || ts1.tv_nsec < 0) + { + neg1 = true; + ts1.tv_sec = -ts1.tv_sec; + ts1.tv_nsec = -ts1.tv_nsec; + } + + if (ts2.tv_sec < 0 || ts2.tv_nsec < 0) + { + neg2 = true; + ts2.tv_sec = -ts2.tv_sec; + ts2.tv_nsec = -ts2.tv_nsec; + } + + /* Shift ts2 until it is larger than ts1 or is about to overflow + */ + while ((ts2.tv_sec < (LONG_MAX >> 1)) && timespec_ge(ts1, ts2)) + { + i++; + ts2.tv_nsec <<= 1; + ts2.tv_sec <<= 1; + if (ts2.tv_nsec > NSEC_PER_SEC) + { + ts2.tv_nsec -= NSEC_PER_SEC; + ts2.tv_sec++; + } + } + + /* Division by repeated subtraction + */ + while (i >= 0) + { + if (timespec_ge(ts1, ts2)) + { + ts1 = timespec_sub(ts1, ts2); + } + + if (i == 0) + { + break; + } + + i--; + if (ts2.tv_sec & 1) + { + ts2.tv_nsec += NSEC_PER_SEC; + } + ts2.tv_nsec >>= 1; + ts2.tv_sec >>= 1; + } + + /* If signs differ and result is nonzero, subtract once more to cross zero + */ + if (neg1 ^ neg2 && (ts1.tv_sec != 0 || ts1.tv_nsec != 0)) + { + ts1 = timespec_sub(ts1, ts2); + } + + /* Restore sign + */ + if (neg1) + { + ts1.tv_sec = -ts1.tv_sec; + ts1.tv_nsec = -ts1.tv_nsec; + } + + return ts1; +} + +/** \fn bool timespec_eq(struct timespec ts1, struct timespec ts2) + * \brief Returns true if the two timespec structures are equal. +*/ +bool timespec_eq(struct timespec ts1, struct timespec ts2) +{ + return (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec == ts2.tv_nsec); +} + +/** \fn bool timespec_gt(struct timespec ts1, struct timespec ts2) + * \brief Returns true if ts1 is greater than ts2. +*/ +bool timespec_gt(struct timespec ts1, struct timespec ts2) +{ + return (ts1.tv_sec > ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec > ts2.tv_nsec)); +} + +/** \fn bool timespec_ge(struct timespec ts1, struct timespec ts2) + * \brief Returns true if ts1 is greater than or equal to ts2. +*/ +bool timespec_ge(struct timespec ts1, struct timespec ts2) +{ + return (ts1.tv_sec > ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec >= ts2.tv_nsec)); +} + +/** \fn bool timespec_lt(struct timespec ts1, struct timespec ts2) + * \brief Returns true if ts1 is less than ts2. +*/ +bool timespec_lt(struct timespec ts1, struct timespec ts2) +{ + return (ts1.tv_sec < ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec < ts2.tv_nsec)); +} + +/** \fn bool timespec_le(struct timespec ts1, struct timespec ts2) + * \brief Returns true if ts1 is less than or equal to ts2. +*/ +bool timespec_le(struct timespec ts1, struct timespec ts2) +{ + return (ts1.tv_sec < ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec <= ts2.tv_nsec)); +} + +/** \fn struct timespec timespec_from_double(double s) + * \brief Converts a fractional number of seconds to a timespec. +*/ +struct timespec timespec_from_double(double s) +{ + struct timespec ts = { + .tv_sec = s, + .tv_nsec = (s - (long)(s)) * NSEC_PER_SEC, + }; + + return timespec_normalise(ts); +} + +/** \fn double timespec_to_double(struct timespec ts) + * \brief Converts a timespec to a fractional number of seconds. +*/ +double timespec_to_double(struct timespec ts) +{ + return ((double)(ts.tv_sec) + ((double)(ts.tv_nsec) / NSEC_PER_SEC)); +} + +/** \fn struct timespec timespec_from_timeval(struct timeval tv) + * \brief Converts a timeval to a timespec. +*/ +struct timespec timespec_from_timeval(struct timeval tv) +{ + struct timespec ts = { + .tv_sec = tv.tv_sec, + .tv_nsec = tv.tv_usec * 1000 + }; + + return timespec_normalise(ts); +} + +/** \fn struct timeval timespec_to_timeval(struct timespec ts) + * \brief Converts a timespec to a timeval. +*/ +struct timeval timespec_to_timeval(struct timespec ts) +{ + ts = timespec_normalise(ts); + + struct timeval tv = { + .tv_sec = ts.tv_sec, + .tv_usec = ts.tv_nsec / 1000, + }; + + return tv; +} + +/** \fn struct timespec timespec_from_ms(long milliseconds) + * \brief Converts an integer number of milliseconds to a timespec. +*/ +struct timespec timespec_from_ms(long milliseconds) +{ + struct timespec ts = { + .tv_sec = (milliseconds / 1000), + .tv_nsec = (milliseconds % 1000) * 1000000, + }; + + return timespec_normalise(ts); +} + +/** \fn long timespec_to_ms(struct timespec ts) + * \brief Converts a timespec to an integer number of milliseconds. +*/ +long timespec_to_ms(struct timespec ts) +{ + return (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); +} + +/** \fn struct timespec timespec_normalise(struct timespec ts) + * \brief Normalises a timespec structure. + * + * Returns a normalised version of a timespec structure, according to the + * following rules: + * + * 1) If tv_nsec is >1,000,000,00 or <-1,000,000,000, flatten the surplus + * nanoseconds into the tv_sec field. + * + * 2) If tv_sec is >0 and tv_nsec is <0, decrement tv_sec and roll tv_nsec up + * to represent the same value on the positive side of the new tv_sec. + * + * 3) If tv_sec is <0 and tv_nsec is >0, increment tv_sec and roll tv_nsec down + * to represent the same value on the negative side of the new tv_sec. +*/ +struct timespec timespec_normalise(struct timespec ts) +{ + while(ts.tv_nsec >= NSEC_PER_SEC) + { + ++(ts.tv_sec); + ts.tv_nsec -= NSEC_PER_SEC; + } + + while(ts.tv_nsec <= -NSEC_PER_SEC) + { + --(ts.tv_sec); + ts.tv_nsec += NSEC_PER_SEC; + } + + if(ts.tv_nsec < 0 && ts.tv_sec > 0) + { + /* Negative nanoseconds while seconds is positive. + * Decrement tv_sec and roll tv_nsec over. + */ + + --(ts.tv_sec); + ts.tv_nsec = NSEC_PER_SEC - (-1 * ts.tv_nsec); + } + else if(ts.tv_nsec > 0 && ts.tv_sec < 0) + { + /* Positive nanoseconds while seconds is negative. + * Increment tv_sec and roll tv_nsec over. + */ + + ++(ts.tv_sec); + ts.tv_nsec = -NSEC_PER_SEC - (-1 * ts.tv_nsec); + } + + return ts; +} + +#ifdef TEST +#include + +#define TEST_NORMALISE(ts_sec, ts_nsec, expect_sec, expect_nsec) { \ + struct timespec in = { .tv_sec = ts_sec, .tv_nsec = ts_nsec }; \ + struct timespec got = timespec_normalise(in); \ + if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \ + { \ + printf("timespec_normalise({%ld, %ld}) returned wrong values\n", (long)(ts_sec), (long)(ts_nsec)); \ + printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \ + printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \ + result = 1; \ + } \ +} + +#define TEST_ADD(ts1_sec, ts1_nsec, ts2_sec, ts2_nsec, expect_sec, expect_nsec) { \ + struct timespec ts1 = { .tv_sec = ts1_sec, .tv_nsec = ts1_nsec }; \ + struct timespec ts2 = { .tv_sec = ts2_sec, .tv_nsec = ts2_nsec }; \ + struct timespec got = timespec_add(ts1, ts2); \ + if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \ + { \ + printf("timespec_add({%ld, %ld}, {%ld, %ld}) returned wrong values\n", \ + (long)(ts1_sec), (long)(ts1_nsec), (long)(ts2_sec), (long)(ts2_nsec)); \ + printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \ + printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \ + result = 1; \ + } \ +} + +#define TEST_SUB(ts1_sec, ts1_nsec, ts2_sec, ts2_nsec, expect_sec, expect_nsec) { \ + struct timespec ts1 = { .tv_sec = ts1_sec, .tv_nsec = ts1_nsec }; \ + struct timespec ts2 = { .tv_sec = ts2_sec, .tv_nsec = ts2_nsec }; \ + struct timespec got = timespec_sub(ts1, ts2); \ + if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \ + { \ + printf("timespec_sub({%ld, %ld}, {%ld, %ld}) returned wrong values\n", \ + (long)(ts1_sec), (long)(ts1_nsec), (long)(ts2_sec), (long)(ts2_nsec)); \ + printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \ + printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \ + result = 1; \ + } \ +} + +#define TEST_MOD(ts1_sec, ts1_nsec, ts2_sec, ts2_nsec, expect_sec, expect_nsec) { \ + struct timespec ts1 = { .tv_sec = ts1_sec, .tv_nsec = ts1_nsec }; \ + struct timespec ts2 = { .tv_sec = ts2_sec, .tv_nsec = ts2_nsec }; \ + struct timespec got = timespec_mod(ts1, ts2); \ + if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \ + { \ + printf("timespec_mod({%ld, %ld}, {%ld, %ld}) returned wrong values\n", \ + (long)(ts1_sec), (long)(ts1_nsec), (long)(ts2_sec), (long)(ts2_nsec)); \ + printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \ + printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \ + result = 1; \ + } \ +} + +#define TEST_TEST_FUNC(func, ts1_sec, ts1_nsec, ts2_sec, ts2_nsec, expect) { \ + struct timespec ts1 = { .tv_sec = ts1_sec, .tv_nsec = ts1_nsec }; \ + struct timespec ts2 = { .tv_sec = ts2_sec, .tv_nsec = ts2_nsec }; \ + if(func(ts1, ts2) != expect) { \ + printf(#func "({%ld, %ld}, {%ld, %ld}) returned %s\n", \ + (long)(ts1_sec), (long)(ts1_nsec), (long)(ts2_sec), (long)(ts2_nsec), \ + (expect ? "FALSE" : "TRUE")); \ + result = 1; \ + } \ +} + +#define TEST_FROM_DOUBLE(d_secs, expect_sec, expect_nsec) { \ + struct timespec got = timespec_from_double(d_secs); \ + if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \ + { \ + printf("timespec_from_double(%f) returned wrong values\n", (double)(d_secs)); \ + printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \ + printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \ + result = 1; \ + } \ +} + +#define TEST_TO_DOUBLE(ts_sec, ts_nsec, expect) { \ + struct timespec ts = { .tv_sec = ts_sec, .tv_nsec = ts_nsec }; \ + double got = timespec_to_double(ts); \ + if(got != expect) { \ + printf("timespec_to_double({%ld, %ld}) returned wrong value\n", (long)(ts_sec), (long)(ts_nsec)); \ + printf(" Expected: %f\n", (double)(expect)); \ + printf(" Got: %f\n", got); \ + result = 1; \ + } \ +} + +#define TEST_FROM_TIMEVAL(in_sec, in_usec, expect_sec, expect_nsec) { \ + struct timeval tv = { .tv_sec = in_sec, .tv_usec = in_usec }; \ + struct timespec got = timespec_from_timeval(tv); \ + if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \ + { \ + printf("timespec_from_timeval({%ld, %ld}) returned wrong values\n", (long)(in_sec), (long)(in_usec)); \ + printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \ + printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \ + result = 1; \ + } \ +} + +#define TEST_TO_TIMEVAL(ts_sec, ts_nsec, expect_sec, expect_usec) { \ + struct timespec ts = { .tv_sec = ts_sec, .tv_nsec = ts_nsec }; \ + struct timeval got = timespec_to_timeval(ts); \ + if(got.tv_sec != expect_sec || got.tv_usec != expect_usec) \ + { \ + printf("timespec_to_timeval({%ld, %ld}) returned wrong values\n", (long)(ts_sec), (long)(ts_nsec)); \ + printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_usec)); \ + printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_usec)); \ + result = 1; \ + } \ +} + +#define TEST_FROM_MS(msecs, expect_sec, expect_nsec) { \ + struct timespec got = timespec_from_ms(msecs); \ + if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \ + { \ + printf("timespec_from_ms(%ld) returned wrong values\n", (long)(msecs)); \ + printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \ + printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \ + result = 1; \ + } \ +} + +#define TEST_TO_MS(ts_sec, ts_nsec, expect) { \ + struct timespec ts = { .tv_sec = ts_sec, .tv_nsec = ts_nsec }; \ + long got = timespec_to_ms(ts); \ + if(got != expect) { \ + printf("timespec_to_ms({%ld, %ld}) returned wrong value\n", (long)(ts_sec), (long)(ts_nsec)); \ + printf(" Expected: %ld\n", (long)(expect)); \ + printf(" Got: %ld\n", got); \ + result = 1; \ + } \ +} + +int main() +{ + int result = 0; + + // timespec_add + + TEST_ADD(0,0, 0,0, 0,0); + TEST_ADD(0,0, 1,0, 1,0); + TEST_ADD(1,0, 0,0, 1,0); + TEST_ADD(1,0, 1,0, 2,0); + TEST_ADD(1,500000000, 1,0, 2,500000000); + TEST_ADD(1,0, 1,500000000, 2,500000000); + TEST_ADD(1,500000000, 1,500000000, 3,0); + TEST_ADD(1,500000000, 1,499999999, 2,999999999); + TEST_ADD(1,500000000, 1,500000000, 3,0); + TEST_ADD(1,999999999, 1,999999999, 3,999999998); + TEST_ADD(0,500000000, 1,500000000, 2,0); + TEST_ADD(1,500000000, 0,500000000, 2,0); + + // timespec_sub + + TEST_SUB(0,0, 0,0, 0,0); + TEST_SUB(1,0, 0,0, 1,0); + TEST_SUB(1,0, 1,0, 0,0); + TEST_SUB(1,500000000, 0,500000000, 1,0); + TEST_SUB(5,500000000, 2,999999999, 2,500000001); + TEST_SUB(0,0, 1,0, -1,0); + TEST_SUB(0,500000000, 1,500000000, -1,0); + TEST_SUB(0,0, 1,500000000, -1,-500000000); + TEST_SUB(1,0, 1,500000000, 0,-500000000); + TEST_SUB(1,0, 1,499999999, 0,-499999999); + + // timespec_mod + + TEST_MOD(0,0, 0,0, 0,0); + TEST_MOD(0,0, 1,0, 0,0); + TEST_MOD(1,0, 0,0, 1,0); + TEST_MOD(1,0, 1,0, 0,0); + TEST_MOD(10,0, 1,0, 0,0); + TEST_MOD(10,0, 3,0, 1,0); + TEST_MOD(10,0, -3,0, -2,0); + TEST_MOD(-10,0, 3,0, 2,0); + TEST_MOD(-10,0, -3,0, -1,0); + TEST_MOD(10,0, 5,0, 0,0); + TEST_MOD(10,0, -5,0, 0,0); + TEST_MOD(-10,0, 5,0, 0,0); + TEST_MOD(-10,0, -5,0, 0,0); + TEST_MOD(1,500000000, 0,500000000, 0,0); + TEST_MOD(5,500000000, 2,999999999, 2,500000001); + TEST_MOD(0,500000000, 1,500000000, 0,500000000); + TEST_MOD(0,0, 1,500000000, 0,0); + TEST_MOD(1,0, 1,500000000, 1,0); + TEST_MOD(1,0, 0,1, 0,0); + TEST_MOD(1,123456789, 0,1000, 0,789); + TEST_MOD(1,0, 0,9999999, 0,100); + TEST_MOD(12345,54321, 0,100001, 0,5555); + TEST_MOD(LONG_MAX,0, 0,1, 0,0); + TEST_MOD(LONG_MAX,0, LONG_MAX,1, LONG_MAX,0); + + // timespec_eq + + TEST_TEST_FUNC(timespec_eq, 0,0, 0,0, true); + TEST_TEST_FUNC(timespec_eq, 100,0, 100,0, true); + TEST_TEST_FUNC(timespec_eq, -200,0, -200,0, true); + TEST_TEST_FUNC(timespec_eq, 0,300, 0,300, true); + TEST_TEST_FUNC(timespec_eq, 0,-400, 0,-400, true); + + TEST_TEST_FUNC(timespec_eq, 100,1, 100,0, false); + TEST_TEST_FUNC(timespec_eq, 101,0, 100,0, false); + TEST_TEST_FUNC(timespec_eq, -100,0, 100,0, false); + TEST_TEST_FUNC(timespec_eq, 0,10, 0,-10, false); + + // timespec_gt + + TEST_TEST_FUNC(timespec_gt, 1,0, 0,0, true); + TEST_TEST_FUNC(timespec_gt, 0,0, -1,0, true); + TEST_TEST_FUNC(timespec_gt, 0,1, 0,0, true); + TEST_TEST_FUNC(timespec_gt, 0,0, 0,-1, true); + + TEST_TEST_FUNC(timespec_gt, 1,0, 1,0, false); + TEST_TEST_FUNC(timespec_gt, 1,1, 1,1, false); + TEST_TEST_FUNC(timespec_gt, -1,0, 0,0, false); + TEST_TEST_FUNC(timespec_gt, 0,-1, 0,0, false); + + // timespec_ge + + TEST_TEST_FUNC(timespec_ge, 1,0, 0,0, true); + TEST_TEST_FUNC(timespec_ge, 0,0, -1,0, true); + TEST_TEST_FUNC(timespec_ge, 0,1, 0,0, true); + TEST_TEST_FUNC(timespec_ge, 0,0, 0,-1, true); + TEST_TEST_FUNC(timespec_ge, 1,0, 1,0, true); + TEST_TEST_FUNC(timespec_ge, 1,1, 1,1, true); + + TEST_TEST_FUNC(timespec_ge, -1,0, 0,0, false); + TEST_TEST_FUNC(timespec_ge, 0,-1, 0,0, false); + + // timespec_lt + + TEST_TEST_FUNC(timespec_lt, 0,0, 1,0, true); + TEST_TEST_FUNC(timespec_lt, -1,0, 0,0, true); + TEST_TEST_FUNC(timespec_lt, 0,0, 0,1, true); + TEST_TEST_FUNC(timespec_lt, 0,-1, 0,0, true); + + TEST_TEST_FUNC(timespec_lt, 1,0, 1,0, false); + TEST_TEST_FUNC(timespec_lt, 1,1, 1,1, false); + TEST_TEST_FUNC(timespec_lt, 0,0, -1,0, false); + TEST_TEST_FUNC(timespec_lt, 0,0, 0,-1, false); + + // timespec_le + + TEST_TEST_FUNC(timespec_le, 0,0, 1,0, true); + TEST_TEST_FUNC(timespec_le, -1,0, 0,0, true); + TEST_TEST_FUNC(timespec_le, 0,0, 0,1, true); + TEST_TEST_FUNC(timespec_le, 0,-1, 0,0, true); + TEST_TEST_FUNC(timespec_le, 1,0, 1,0, true); + TEST_TEST_FUNC(timespec_le, 1,1, 1,1, true); + + TEST_TEST_FUNC(timespec_le, 0,0, -1,0, false); + TEST_TEST_FUNC(timespec_le, 0,0, 0,-1, false); + + // timespec_from_double + + TEST_FROM_DOUBLE(0.0, 0,0); + TEST_FROM_DOUBLE(10.0, 10,0); + TEST_FROM_DOUBLE(-10.0, -10,0); + TEST_FROM_DOUBLE(0.5, 0,500000000); + TEST_FROM_DOUBLE(-0.5, 0,-500000000); + TEST_FROM_DOUBLE(10.5, 10,500000000); + TEST_FROM_DOUBLE(-10.5, -10,-500000000); + + // timespec_to_double + + TEST_TO_DOUBLE(0,0, 0.0); + TEST_TO_DOUBLE(10,0, 10.0); + TEST_TO_DOUBLE(-10,0, -10.0); + TEST_TO_DOUBLE(0,500000000, 0.5); + TEST_TO_DOUBLE(0,-500000000, -0.5); + TEST_TO_DOUBLE(10,500000000, 10.5); + TEST_TO_DOUBLE(10,-500000000, 9.5); + TEST_TO_DOUBLE(-10,500000000, -9.5); + TEST_TO_DOUBLE(-10,-500000000, -10.5); + + // timespec_from_timeval + + TEST_FROM_TIMEVAL(0,0, 0,0); + TEST_FROM_TIMEVAL(1,0, 1,0); + TEST_FROM_TIMEVAL(1000,0, 1000,0); + TEST_FROM_TIMEVAL(0,0, 0,0); + TEST_FROM_TIMEVAL(-1,0, -1,0); + TEST_FROM_TIMEVAL(-1000,0, -1000,0); + + TEST_FROM_TIMEVAL(1,1, 1,1000); + TEST_FROM_TIMEVAL(1,1000, 1,1000000); + TEST_FROM_TIMEVAL(1,-1, 0,999999000); + TEST_FROM_TIMEVAL(1,-1000, 0,999000000); + TEST_FROM_TIMEVAL(-1,-1, -1,-1000); + TEST_FROM_TIMEVAL(-1,-1000, -1,-1000000); + + // timespec_to_timeval + + TEST_TO_TIMEVAL(0,0, 0,0); + TEST_TO_TIMEVAL(1,0, 1,0); + TEST_TO_TIMEVAL(10,0, 10,0); + TEST_TO_TIMEVAL(-1,0, -1,0); + TEST_TO_TIMEVAL(-10,0, -10,0); + + TEST_TO_TIMEVAL(1,1, 1,0); + TEST_TO_TIMEVAL(1,999, 1,0); + TEST_TO_TIMEVAL(1,1000, 1,1); + TEST_TO_TIMEVAL(1,1001, 1,1); + TEST_TO_TIMEVAL(1,2000, 1,2); + TEST_TO_TIMEVAL(1,2000000, 1,2000); + + TEST_TO_TIMEVAL(1,-1, 0,999999); + TEST_TO_TIMEVAL(1,-999, 0,999999); + TEST_TO_TIMEVAL(1,-1000, 0,999999); + TEST_TO_TIMEVAL(1,-1001, 0,999998); + TEST_TO_TIMEVAL(1,-2000, 0,999998); + TEST_TO_TIMEVAL(1,-2000000, 0,998000); + + TEST_TO_TIMEVAL(-1,-1, -1,0); + TEST_TO_TIMEVAL(-1,-999, -1,0); + TEST_TO_TIMEVAL(-1,-1000, -1,-1); + TEST_TO_TIMEVAL(-1,-1001, -1,-1); + TEST_TO_TIMEVAL(-1,-2000, -1,-2); + TEST_TO_TIMEVAL(-1,-2000000, -1,-2000); + + TEST_TO_TIMEVAL(1,1500000000, 2,500000); + TEST_TO_TIMEVAL(1,-1500000000, 0,-500000); + TEST_TO_TIMEVAL(-1,-1500000000, -2,-500000); + + // timespec_from_ms + + TEST_FROM_MS(0, 0,0); + TEST_FROM_MS(1, 0,1000000); + TEST_FROM_MS(-1, 0,-1000000); + TEST_FROM_MS(1500, 1,500000000); + TEST_FROM_MS(-1000, -1,0); + TEST_FROM_MS(-1500, -1,-500000000); + + // timespec_to_ms + + TEST_TO_MS(0,0, 0); + TEST_TO_MS(10,0, 10000); + TEST_TO_MS(-10,0, -10000); + TEST_TO_MS(0,500000000, 500); + TEST_TO_MS(0,-500000000, -500); + TEST_TO_MS(10,500000000, 10500); + TEST_TO_MS(10,-500000000, 9500); + TEST_TO_MS(-10,500000000, -9500); + TEST_TO_MS(-10,-500000000, -10500); + + // timespec_normalise + + TEST_NORMALISE(0,0, 0,0); + + TEST_NORMALISE(0,1000000000, 1,0); + TEST_NORMALISE(0,1500000000, 1,500000000); + TEST_NORMALISE(0,-1000000000, -1,0); + TEST_NORMALISE(0,-1500000000, -1,-500000000); + + TEST_NORMALISE(5,1000000000, 6,0); + TEST_NORMALISE(5,1500000000, 6,500000000); + TEST_NORMALISE(-5,-1000000000, -6,0); + TEST_NORMALISE(-5,-1500000000, -6,-500000000); + + TEST_NORMALISE(0,2000000000, 2,0); + TEST_NORMALISE(0,2100000000, 2,100000000); + TEST_NORMALISE(0,-2000000000, -2,0); + TEST_NORMALISE(0,-2100000000, -2,-100000000); + + TEST_NORMALISE(1,-500000001, 0,499999999); + TEST_NORMALISE(1,-500000000, 0,500000000); + TEST_NORMALISE(1,-499999999, 0,500000001); + + TEST_NORMALISE(-1,500000000, 0,-500000000); + TEST_NORMALISE(-1,499999999, 0,-500000001); + + if(result > 0) + { + printf("%d tests failed\n", result); + } + else{ + printf("All tests passed\n"); + } + + return result; +} +#endif diff --git a/utils/timespec.h b/utils/timespec.h new file mode 100644 index 0000000..d401cd1 --- /dev/null +++ b/utils/timespec.h @@ -0,0 +1,65 @@ +/* Functions for working with timespec structures + * Written by Daniel Collins (2017) + * timespec_mod by Alex Forencich (2019) + * + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to +*/ + +#ifndef DAN_TIMESPEC_H +#define DAN_TIMESPEC_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct timespec timespec_add(struct timespec ts1, struct timespec ts2); +struct timespec timespec_sub(struct timespec ts1, struct timespec ts2); +struct timespec timespec_mod(struct timespec ts1, struct timespec ts2); + +bool timespec_eq(struct timespec ts1, struct timespec ts2); +bool timespec_gt(struct timespec ts1, struct timespec ts2); +bool timespec_ge(struct timespec ts1, struct timespec ts2); +bool timespec_lt(struct timespec ts1, struct timespec ts2); +bool timespec_le(struct timespec ts1, struct timespec ts2); + +struct timespec timespec_from_double(double s); +double timespec_to_double(struct timespec ts); +struct timespec timespec_from_timeval(struct timeval tv); +struct timeval timespec_to_timeval(struct timespec ts); +struct timespec timespec_from_ms(long milliseconds); +long timespec_to_ms(struct timespec ts); + +struct timespec timespec_normalise(struct timespec ts); + +#ifdef __cplusplus +} +#endif + +#endif /* !DAN_TIMESPEC_H */ diff --git a/utils/xcvr_gt.c b/utils/xcvr_gt.c new file mode 100644 index 0000000..2992841 --- /dev/null +++ b/utils/xcvr_gt.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#include +#include "drp.h" +#include "xcvr_gt.h" + +#include "xcvr_gthe3.h" +#include "xcvr_gtye3.h" +#include "xcvr_gthe4.h" +#include "xcvr_gtye4.h" + +#include + +int gt_pll_reg_read(struct gt_pll *pll, uint32_t addr, uint32_t *val) +{ + if (!pll) + return -1; + + return mqnic_reg_if_read32(&pll->quad->reg, addr | (1 << 19), val); +} + +int gt_pll_reg_read_masked(struct gt_pll *pll, uint32_t addr, uint32_t *val, uint32_t mask, uint32_t shift) +{ + int ret = 0; + uint32_t v; + + ret = gt_pll_reg_read(pll, addr, &v); + if (ret) + return ret; + + *val = (v & mask) >> shift; + return 0; +} + +int gt_pll_reg_write(struct gt_pll *pll, uint32_t addr, uint32_t val) +{ + if (!pll) + return -1; + + return mqnic_reg_if_write32(&pll->quad->reg, addr | (1 << 19), val); +} + +int gt_pll_reg_write_masked(struct gt_pll *pll, uint32_t addr, uint32_t val, uint32_t mask, uint32_t shift) +{ + int ret = 0; + uint32_t old_val; + + ret = gt_pll_reg_read(pll, addr, &old_val); + if (ret) + return ret; + + return gt_pll_reg_write(pll, addr, ((val << shift) & mask) | (old_val & ~mask)); +} + +int gt_pll_reg_write_multiple(struct gt_pll *pll, const struct gt_reg_val *vals) +{ + int ret = 0; + const struct gt_reg_val *val = vals; + + while (val && val->mask) + { + ret = gt_pll_reg_write_masked(pll, val->addr, val->value, val->mask, val->shift); + if (ret) + return ret; + val++; + } + + return 0; +} + +int gt_ch_reg_read(struct gt_ch *ch, uint32_t addr, uint32_t *val) +{ + if (!ch) + return -1; + + return mqnic_reg_if_read32(&ch->quad->reg, addr | (ch->index << 17), val); +} + +int gt_ch_reg_read_masked(struct gt_ch *ch, uint32_t addr, uint32_t *val, uint32_t mask, uint32_t shift) +{ + int ret = 0; + uint32_t v; + + ret = gt_ch_reg_read(ch, addr, &v); + if (ret) + return ret; + + *val = (v & mask) >> shift; + return 0; +} + +int gt_ch_reg_write(struct gt_ch *ch, uint32_t addr, uint32_t val) +{ + if (!ch) + return -1; + + return mqnic_reg_if_write32(&ch->quad->reg, addr | (ch->index << 17), val); +} + +int gt_ch_reg_write_masked(struct gt_ch *ch, uint32_t addr, uint32_t val, uint32_t mask, uint32_t shift) +{ + int ret = 0; + uint32_t old_val; + + ret = gt_ch_reg_read(ch, addr, &old_val); + if (ret) + return ret; + + return gt_ch_reg_write(ch, addr, ((val << shift) & mask) | (old_val & ~mask)); +} + +int gt_ch_reg_write_multiple(struct gt_ch *ch, const struct gt_reg_val *vals) +{ + int ret = 0; + const struct gt_reg_val *val = vals; + + while (val && val->mask) + { + ret = gt_ch_reg_write_masked(ch, val->addr, val->value, val->mask, val->shift); + if (ret) + return ret; + val++; + } + + return 0; +} + +struct gt_quad *gt_create_quad_from_drp_rb(struct mqnic_reg_block *rb) +{ + struct gt_quad *quad = calloc(1, sizeof(struct gt_quad)); + drp_rb_reg_if_init(&quad->reg, rb); + quad->pll.quad = quad; + + uint32_t info = mqnic_reg_read32(rb->regs, 0x0C); + + quad->ch_count = info & 0xff; + quad->gt_type = info >> 16; + quad->type = "Unknown"; + + switch (quad->gt_type) { + case 0x0802: + quad->ops = >he3_gt_quad_ops; + break; + case 0x0803: + quad->ops = >ye3_gt_quad_ops; + break; + case 0x0902: + quad->ops = >he4_gt_quad_ops; + break; + case 0x0903: + quad->ops = >ye4_gt_quad_ops; + break; + default: + goto err; + } + + if (!quad->ops || !quad->ops->init) + goto err; + + if (quad->ops->init(quad)) + goto err; + + return quad; + +err: + gt_free_quad(quad); + return NULL; +} + +void gt_free_quad(struct gt_quad *quad){ + free(quad); +} + +int gt_ch_get_tx_reset(struct gt_ch *ch, uint32_t *val) +{ + if (!ch || !ch->ops || !ch->ops->get_tx_reset) + return -1; + + return ch->ops->get_tx_reset(ch, val); +} + +int gt_ch_set_tx_reset(struct gt_ch *ch, uint32_t val) +{ + if (!ch || !ch->ops || !ch->ops->set_tx_reset) + return -1; + + return ch->ops->set_tx_reset(ch, val); +} + +int gt_ch_tx_reset(struct gt_ch *ch) +{ + if (!ch || !ch->ops || !ch->ops->tx_reset) + return -1; + + return ch->ops->tx_reset(ch); +} + +int gt_ch_get_rx_reset(struct gt_ch *ch, uint32_t *val) +{ + if (!ch || !ch->ops || !ch->ops->get_rx_reset) + return -1; + + return ch->ops->get_rx_reset(ch, val); +} + +int gt_ch_set_rx_reset(struct gt_ch *ch, uint32_t val) +{ + if (!ch || !ch->ops || !ch->ops->set_rx_reset) + return -1; + + return ch->ops->set_rx_reset(ch, val); +} + +int gt_ch_rx_reset(struct gt_ch *ch) +{ + if (!ch || !ch->ops || !ch->ops->rx_reset) + return -1; + + return ch->ops->rx_reset(ch); +} + +int gt_ch_get_tx_data_width(struct gt_ch *ch, uint32_t *val) +{ + if (!ch || !ch->ops || !ch->ops->get_tx_data_width) + return -1; + + return ch->ops->get_tx_data_width(ch, val); +} + +int gt_ch_get_tx_int_data_width(struct gt_ch *ch, uint32_t *val) +{ + if (!ch || !ch->ops || !ch->ops->get_tx_int_data_width) + return -1; + + return ch->ops->get_tx_int_data_width(ch, val); +} + +int gt_ch_get_rx_data_width(struct gt_ch *ch, uint32_t *val) +{ + if (!ch || !ch->ops || !ch->ops->get_rx_data_width) + return -1; + + return ch->ops->get_rx_data_width(ch, val); +} + +int gt_ch_get_rx_int_data_width(struct gt_ch *ch, uint32_t *val) +{ + if (!ch || !ch->ops || !ch->ops->get_rx_int_data_width) + return -1; + + return ch->ops->get_rx_int_data_width(ch, val); +} + +int gt_ch_get_available_presets(struct gt_ch *ch, const uint32_t **presets) +{ + if (!ch || !ch->ops || !ch->ops->get_available_presets) + return -1; + + return ch->ops->get_available_presets(ch, presets); +} + +int gt_ch_load_preset(struct gt_ch *ch, uint32_t preset) +{ + if (!ch || !ch->ops || !ch->ops->load_preset) + return -1; + + return ch->ops->load_preset(ch, preset); +} + +int gt_ch_eyescan_start(struct gt_ch *ch, struct gt_eyescan_params *params) +{ + if (!ch || !ch->ops || !ch->ops->eyescan_start) + return -1; + + return ch->ops->eyescan_start(ch, params); +} + +int gt_ch_eyescan_step(struct gt_ch *ch, struct gt_eyescan_point *point) +{ + if (!ch || !ch->ops || !ch->ops->eyescan_step) + return -1; + + return ch->ops->eyescan_step(ch, point); +} diff --git a/utils/xcvr_gt.h b/utils/xcvr_gt.h new file mode 100644 index 0000000..4e57236 --- /dev/null +++ b/utils/xcvr_gt.h @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#ifndef XCVR_GT_H +#define XCVR_GT_H + +#include +#include +#include "drp.h" + +struct gt_pll { + struct gt_quad *quad; +}; + +struct gt_ch { + struct gt_quad *quad; + struct gt_pll *pll; + const struct gt_ch_ops *ops; + void *priv; + + int index; +}; + +struct gt_quad { + struct mqnic_reg_if reg; + struct gt_pll pll; + struct gt_ch ch[4]; + const struct gt_quad_ops *ops; + void *priv; + const char *type; + + int index; + int ch_count; + int gt_type; +}; + +struct gt_reg_val { + uint16_t addr; + uint16_t mask; + uint16_t shift; + uint16_t value; +}; + +struct gt_eyescan_params { + uint64_t target_bit_count; + int h_range; + int h_start; + int h_stop; + int h_step; + int v_range; + int v_start; + int v_stop; + int v_step; +}; + +struct gt_eyescan_point { + uint64_t error_count; + uint64_t bit_count; + int x; + int y; + int ut_sign; +}; + +struct gt_quad_ops { + int (*init)(struct gt_quad *quad); +}; + +struct gt_ch_ops { + int (*get_tx_reset)(struct gt_ch *ch, uint32_t *val); + int (*set_tx_reset)(struct gt_ch *ch, uint32_t val); + int (*tx_reset)(struct gt_ch *ch); + int (*get_rx_reset)(struct gt_ch *ch, uint32_t *val); + int (*set_rx_reset)(struct gt_ch *ch, uint32_t val); + int (*rx_reset)(struct gt_ch *ch); + int (*get_tx_data_width)(struct gt_ch *ch, uint32_t *val); + int (*get_tx_int_data_width)(struct gt_ch *ch, uint32_t *val); + int (*get_rx_data_width)(struct gt_ch *ch, uint32_t *val); + int (*get_rx_int_data_width)(struct gt_ch *ch, uint32_t *val); + int (*get_available_presets)(struct gt_ch *ch, const uint32_t **presets); + int (*load_preset)(struct gt_ch *ch, uint32_t preset); + int (*eyescan_start)(struct gt_ch *ch, struct gt_eyescan_params *params); + int (*eyescan_step)(struct gt_ch *ch, struct gt_eyescan_point *point); +}; + +#define GT_PRESET_10G_DFE 0x0001010A +#define GT_PRESET_10G_LPM 0x0000010A +#define GT_PRESET_25G_DFE 0x0001190A +#define GT_PRESET_25G_LPM 0x0000190A + +int gt_pll_reg_read(struct gt_pll *pll, uint32_t addr, uint32_t *val); +int gt_pll_reg_read_masked(struct gt_pll *pll, uint32_t addr, uint32_t *val, uint32_t mask, uint32_t shift); +int gt_pll_reg_write(struct gt_pll *pll, uint32_t addr, uint32_t val); +int gt_pll_reg_write_masked(struct gt_pll *pll, uint32_t addr, uint32_t val, uint32_t mask, uint32_t shift); +int gt_pll_reg_write_multiple(struct gt_pll *pll, const struct gt_reg_val *vals); + +#define def_gt_pll_masked_reg_read16(prefix, name, addr, mask, shift) \ +static inline int prefix##_pll_get_##name(struct gt_pll *pll, uint32_t *val) \ +{ \ + return gt_pll_reg_read_masked(pll, addr, val, mask, shift); \ +} + +#define def_gt_pll_masked_reg_write16(prefix, name, addr, mask, shift) \ +static inline int prefix##_pll_set_##name(struct gt_pll *pll, uint32_t val) \ +{ \ + return gt_pll_reg_write_masked(pll, addr, val, mask, shift); \ +} + +#define def_gt_pll_masked_reg_rw16(prefix, name, addr, mask, shift) \ +def_gt_pll_masked_reg_read16(prefix, name, addr, mask, shift) \ +def_gt_pll_masked_reg_write16(prefix, name, addr, mask, shift) + +int gt_ch_reg_read(struct gt_ch *ch, uint32_t addr, uint32_t *val); +int gt_ch_reg_read_masked(struct gt_ch *ch, uint32_t addr, uint32_t *val, uint32_t mask, uint32_t shift); +int gt_ch_reg_write(struct gt_ch *ch, uint32_t addr, uint32_t val); +int gt_ch_reg_write_masked(struct gt_ch *ch, uint32_t addr, uint32_t val, uint32_t mask, uint32_t shift); +int gt_ch_reg_write_multiple(struct gt_ch *ch, const struct gt_reg_val *vals); + +#define def_gt_ch_masked_reg_read16(prefix, name, addr, mask, shift) \ +static inline int prefix##_ch_get_##name(struct gt_ch *ch, uint32_t *val) \ +{ \ + return gt_ch_reg_read_masked(ch, addr, val, mask, shift); \ +} + +#define def_gt_ch_masked_reg_write16(prefix, name, addr, mask, shift) \ +static inline int prefix##_ch_set_##name(struct gt_ch *ch, uint32_t val) \ +{ \ + return gt_ch_reg_write_masked(ch, addr, val, mask, shift); \ +} + +#define def_gt_ch_masked_reg_rw16(prefix, name, addr, mask, shift) \ +def_gt_ch_masked_reg_read16(prefix, name, addr, mask, shift) \ +def_gt_ch_masked_reg_write16(prefix, name, addr, mask, shift) + +struct gt_quad *gt_create_quad_from_drp_rb(struct mqnic_reg_block *rb); +void gt_free_quad(struct gt_quad *quad); + +int gt_ch_get_tx_reset(struct gt_ch *ch, uint32_t *val); +int gt_ch_set_tx_reset(struct gt_ch *ch, uint32_t val); +int gt_ch_tx_reset(struct gt_ch *ch); +int gt_ch_get_rx_reset(struct gt_ch *ch, uint32_t *val); +int gt_ch_set_rx_reset(struct gt_ch *ch, uint32_t val); +int gt_ch_rx_reset(struct gt_ch *ch); +int gt_ch_get_tx_data_width(struct gt_ch *ch, uint32_t *val); +int gt_ch_get_tx_int_data_width(struct gt_ch *ch, uint32_t *val); +int gt_ch_get_rx_data_width(struct gt_ch *ch, uint32_t *val); +int gt_ch_get_rx_int_data_width(struct gt_ch *ch, uint32_t *val); +int gt_ch_get_available_presets(struct gt_ch *ch, const uint32_t **presets); +int gt_ch_load_preset(struct gt_ch *ch, uint32_t preset); +int gt_ch_eyescan_start(struct gt_ch *ch, struct gt_eyescan_params *params); +int gt_ch_eyescan_step(struct gt_ch *ch, struct gt_eyescan_point *point); + +#endif /* XCVR_GT_H */ diff --git a/utils/xcvr_gthe3.c b/utils/xcvr_gthe3.c new file mode 100644 index 0000000..46d45f3 --- /dev/null +++ b/utils/xcvr_gthe3.c @@ -0,0 +1,662 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#include +#include +#include "xcvr_gthe3.h" + +// signals +int gthe3_pll_qpll0_reset(struct gt_pll *pll) +{ + int ret = 0; + + ret = gthe3_pll_set_qpll0_reset(pll, 1); + + if (ret) + return ret; + + return gthe3_pll_set_qpll0_reset(pll, 0); +} + +int gthe3_pll_qpll1_reset(struct gt_pll *pll) +{ + int ret = 0; + + ret = gthe3_pll_set_qpll1_reset(pll, 1); + + if (ret) + return ret; + + return gthe3_pll_set_qpll1_reset(pll, 0); +} + +int gthe3_ch_tx_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe3_ch_set_tx_reset(ch, 1); + + if (ret) + return ret; + + return gthe3_ch_set_tx_reset(ch, 0); +} + +int gthe3_ch_tx_pma_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe3_ch_set_tx_pma_reset(ch, 1); + + if (ret) + return ret; + + return gthe3_ch_set_tx_pma_reset(ch, 0); +} + +int gthe3_ch_tx_pcs_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe3_ch_set_tx_pcs_reset(ch, 1); + + if (ret) + return ret; + + return gthe3_ch_set_tx_pcs_reset(ch, 0); +} + +int gthe3_ch_rx_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe3_ch_set_rx_reset(ch, 1); + + if (ret) + return ret; + + return gthe3_ch_set_rx_reset(ch, 0); +} + +int gthe3_ch_rx_pma_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe3_ch_set_rx_pma_reset(ch, 1); + + if (ret) + return ret; + + return gthe3_ch_set_rx_pma_reset(ch, 0); +} + +int gthe3_ch_rx_pcs_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe3_ch_set_rx_pcs_reset(ch, 1); + + if (ret) + return ret; + + return gthe3_ch_set_rx_pcs_reset(ch, 0); +} + +int gthe3_ch_rx_dfe_lpm_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe3_ch_set_rx_dfe_lpm_reset(ch, 1); + + if (ret) + return ret; + + return gthe3_ch_set_rx_dfe_lpm_reset(ch, 0); +} + +int gthe3_ch_eyescan_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe3_ch_set_eyescan_reset(ch, 1); + + if (ret) + return ret; + + return gthe3_ch_set_eyescan_reset(ch, 0); +} + +// RX +int gthe3_ch_get_rx_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw; + + ret = gthe3_ch_get_rx_data_width_raw(ch, &dw); + if (ret) + return ret; + + *val = (8*(1 << (dw >> 1)) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gthe3_ch_get_rx_int_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw, idw; + + ret = gthe3_ch_get_rx_data_width_raw(ch, &dw); + if (ret) + return ret; + + ret = gthe3_ch_get_rx_int_data_width_raw(ch, &idw); + if (ret) + return ret; + + *val = (16*(1 << idw) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gthe3_ch_set_es_qual_mask(struct gt_ch *ch, uint8_t *mask) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTHE3_CH_ES_QUAL_MASK0_ADDR+k, mask[2*k+0] | (mask[2*k+1] << 8)); + if (ret) + return ret; + } + + return 0; +} + +int gthe3_ch_set_es_qual_mask_clear(struct gt_ch *ch) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTHE3_CH_ES_QUAL_MASK0_ADDR+k, 0xffff); + if (ret) + return ret; + } + + return 0; +} + +int gthe3_ch_set_es_sdata_mask(struct gt_ch *ch, uint8_t *mask) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTHE3_CH_ES_SDATA_MASK0_ADDR+k, mask[2*k+0] | (mask[2*k+1] << 8)); + if (ret) + return ret; + } + + return 0; +} + +int gthe3_ch_set_es_sdata_mask_width(struct gt_ch *ch, int width) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + int shift = width - (40 - ((k+1)*16)); + uint32_t mask = 0xffff; + + if (shift < 0) + { + mask = 0xffff; + } + else if (shift > 16) + { + mask = 0x0000; + } + else + { + mask = 0xffff >> shift; + } + + ret = gt_ch_reg_write(ch, GTHE3_CH_ES_SDATA_MASK0_ADDR+k, mask); + if (ret) + return ret; + } + + return 0; +} + +int gthe3_ch_get_rx_prbs_error_count(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t v1, v2; + + ret = gt_ch_reg_read(ch, GTHE3_CH_RX_PRBS_ERR_CNT_L_ADDR | (ch->index << 17), &v1); + if (ret) + return ret; + + ret = gt_ch_reg_read(ch, GTHE3_CH_RX_PRBS_ERR_CNT_H_ADDR | (ch->index << 17), &v2); + if (ret) + return ret; + + *val = v1 | (v2 << 16); + return 0; +} + +// TX +int gthe3_ch_get_tx_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw; + + ret = gthe3_ch_get_tx_data_width_raw(ch, &dw); + if (ret) + return ret; + + *val = (8*(1 << (dw >> 1)) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gthe3_ch_get_tx_int_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw, idw; + + ret = gthe3_ch_get_tx_data_width_raw(ch, &dw); + if (ret) + return ret; + + ret = gthe3_ch_get_tx_int_data_width_raw(ch, &idw); + if (ret) + return ret; + + *val = (16*(1 << idw) * (4 + (dw & 1))) >> 2; + return 0; +} + +struct gthe3_ch_priv { + uint32_t tx_data_width; + uint32_t tx_int_data_width; + uint32_t rx_data_width; + uint32_t rx_int_data_width; + int dfe_en; + + int prescale; + int h_start; + int h_stop; + int h_step; + int v_range; + int v_start; + int v_stop; + int v_step; + + int h_offset; + int v_offset; + int ut_sign; + int eyescan_running; +}; + +static const struct gt_reg_val gthe3_ch_preset_10g_dfe_regs[] = { + {GTHE3_CH_CPLL_CFG2_ADDR, GTHE3_CH_CPLL_CFG2_MASK, GTHE3_CH_CPLL_CFG2_LSB, 0x5007}, + {GTHE3_CH_RXDFELPM_KL_CFG1_ADDR, GTHE3_CH_RXDFELPM_KL_CFG1_MASK, GTHE3_CH_RXDFELPM_KL_CFG1_LSB, 0x0002}, + {GTHE3_CH_RXPI_CFG0_ADDR, GTHE3_CH_RXPI_CFG0_MASK, GTHE3_CH_RXPI_CFG0_LSB, 0x0000}, + {GTHE3_CH_RXPI_CFG1_ADDR, GTHE3_CH_RXPI_CFG1_MASK, GTHE3_CH_RXPI_CFG1_LSB, 0x0000}, + {GTHE3_CH_RXPI_CFG2_ADDR, GTHE3_CH_RXPI_CFG2_MASK, GTHE3_CH_RXPI_CFG2_LSB, 0x0000}, + {GTHE3_CH_RXPI_CFG3_ADDR, GTHE3_CH_RXPI_CFG3_MASK, GTHE3_CH_RXPI_CFG3_LSB, 0x0000}, + {GTHE3_CH_RXPI_CFG6_ADDR, GTHE3_CH_RXPI_CFG6_MASK, GTHE3_CH_RXPI_CFG6_LSB, 0x0000}, + {GTHE3_CH_RX_DFE_AGC_CFG1_ADDR, GTHE3_CH_RX_DFE_AGC_CFG1_MASK, GTHE3_CH_RX_DFE_AGC_CFG1_LSB, 0x0004}, + {GTHE3_CH_RX_DFE_KL_LPM_KH_CFG1_ADDR, GTHE3_CH_RX_DFE_KL_LPM_KH_CFG1_MASK, GTHE3_CH_RX_DFE_KL_LPM_KH_CFG1_LSB, 0x0004}, + {GTHE3_CH_RX_DFE_KL_LPM_KL_CFG1_ADDR, GTHE3_CH_RX_DFE_KL_LPM_KL_CFG1_MASK, GTHE3_CH_RX_DFE_KL_LPM_KL_CFG1_LSB, 0x0004}, + {GTHE3_CH_RX_SUM_IREF_TUNE_ADDR, GTHE3_CH_RX_SUM_IREF_TUNE_MASK, GTHE3_CH_RX_SUM_IREF_TUNE_LSB, 0x0000}, + {GTHE3_CH_RX_SUM_RES_CTRL_ADDR, GTHE3_CH_RX_SUM_RES_CTRL_MASK, GTHE3_CH_RX_SUM_RES_CTRL_LSB, 0x0000}, + {GTHE3_CH_TXPI_CFG0_ADDR, GTHE3_CH_TXPI_CFG0_MASK, GTHE3_CH_TXPI_CFG0_LSB, 0x0000}, + {GTHE3_CH_TXPI_CFG1_ADDR, GTHE3_CH_TXPI_CFG1_MASK, GTHE3_CH_TXPI_CFG1_LSB, 0x0000}, + {GTHE3_CH_TXPI_CFG2_ADDR, GTHE3_CH_TXPI_CFG2_MASK, GTHE3_CH_TXPI_CFG2_LSB, 0x0000}, + {GTHE3_CH_TXPI_CFG3_ADDR, GTHE3_CH_TXPI_CFG3_MASK, GTHE3_CH_TXPI_CFG3_LSB, 0x0001}, + {GTHE3_CH_TXPI_CFG5_ADDR, GTHE3_CH_TXPI_CFG5_MASK, GTHE3_CH_TXPI_CFG5_LSB, 0x0000}, + {0, 0, 0, 0} +}; + +static const struct gt_reg_val gthe3_ch_preset_10g_lpm_regs[] = { + {GTHE3_CH_CPLL_CFG2_ADDR, GTHE3_CH_CPLL_CFG2_MASK, GTHE3_CH_CPLL_CFG2_LSB, 0x0007}, + {GTHE3_CH_RXDFELPM_KL_CFG1_ADDR, GTHE3_CH_RXDFELPM_KL_CFG1_MASK, GTHE3_CH_RXDFELPM_KL_CFG1_LSB, 0x0032}, + {GTHE3_CH_RXPI_CFG0_ADDR, GTHE3_CH_RXPI_CFG0_MASK, GTHE3_CH_RXPI_CFG0_LSB, 0x0001}, + {GTHE3_CH_RXPI_CFG1_ADDR, GTHE3_CH_RXPI_CFG1_MASK, GTHE3_CH_RXPI_CFG1_LSB, 0x0001}, + {GTHE3_CH_RXPI_CFG2_ADDR, GTHE3_CH_RXPI_CFG2_MASK, GTHE3_CH_RXPI_CFG2_LSB, 0x0001}, + {GTHE3_CH_RXPI_CFG3_ADDR, GTHE3_CH_RXPI_CFG3_MASK, GTHE3_CH_RXPI_CFG3_LSB, 0x0001}, + {GTHE3_CH_RXPI_CFG6_ADDR, GTHE3_CH_RXPI_CFG6_MASK, GTHE3_CH_RXPI_CFG6_LSB, 0x0003}, + {GTHE3_CH_RX_DFE_AGC_CFG1_ADDR, GTHE3_CH_RX_DFE_AGC_CFG1_MASK, GTHE3_CH_RX_DFE_AGC_CFG1_LSB, 0x0000}, + {GTHE3_CH_RX_DFE_KL_LPM_KH_CFG1_ADDR, GTHE3_CH_RX_DFE_KL_LPM_KH_CFG1_MASK, GTHE3_CH_RX_DFE_KL_LPM_KH_CFG1_LSB, 0x0000}, + {GTHE3_CH_RX_DFE_KL_LPM_KL_CFG1_ADDR, GTHE3_CH_RX_DFE_KL_LPM_KL_CFG1_MASK, GTHE3_CH_RX_DFE_KL_LPM_KL_CFG1_LSB, 0x0000}, + {GTHE3_CH_RX_SUM_IREF_TUNE_ADDR, GTHE3_CH_RX_SUM_IREF_TUNE_MASK, GTHE3_CH_RX_SUM_IREF_TUNE_LSB, 0x000C}, + {GTHE3_CH_RX_SUM_RES_CTRL_ADDR, GTHE3_CH_RX_SUM_RES_CTRL_MASK, GTHE3_CH_RX_SUM_RES_CTRL_LSB, 0x0003}, + {GTHE3_CH_TXPI_CFG0_ADDR, GTHE3_CH_TXPI_CFG0_MASK, GTHE3_CH_TXPI_CFG0_LSB, 0x0001}, + {GTHE3_CH_TXPI_CFG1_ADDR, GTHE3_CH_TXPI_CFG1_MASK, GTHE3_CH_TXPI_CFG1_LSB, 0x0001}, + {GTHE3_CH_TXPI_CFG2_ADDR, GTHE3_CH_TXPI_CFG2_MASK, GTHE3_CH_TXPI_CFG2_LSB, 0x0001}, + {GTHE3_CH_TXPI_CFG3_ADDR, GTHE3_CH_TXPI_CFG3_MASK, GTHE3_CH_TXPI_CFG3_LSB, 0x0000}, + {GTHE3_CH_TXPI_CFG5_ADDR, GTHE3_CH_TXPI_CFG5_MASK, GTHE3_CH_TXPI_CFG5_LSB, 0x0003}, + {0, 0, 0, 0} +}; + +static const uint32_t gthe3_ch_presets[] = { + GT_PRESET_10G_DFE, + GT_PRESET_10G_LPM, + 0 +}; + +static int gthe3_ch_get_available_presets(struct gt_ch *ch, const uint32_t **presets) +{ + *presets = gthe3_ch_presets; + return 0; +} + +int gthe3_ch_load_preset(struct gt_ch *ch, uint32_t preset) +{ + if (preset == GT_PRESET_10G_DFE || preset == GT_PRESET_10G_LPM) + { + gthe3_ch_set_tx_reset(ch, 1); + gthe3_ch_set_rx_reset(ch, 1); + + if (preset == GT_PRESET_10G_DFE) + { + gt_ch_reg_write_multiple(ch, gthe3_ch_preset_10g_dfe_regs); + gthe3_ch_set_rx_lpm_en(ch, 0); + } + else + { + gt_ch_reg_write_multiple(ch, gthe3_ch_preset_10g_lpm_regs); + gthe3_ch_set_rx_lpm_en(ch, 1); + } + + gthe3_ch_set_tx_reset(ch, 0); + gthe3_ch_set_rx_reset(ch, 0); + + return 0; + } + + return -1; +} + +static int gthe3_ch_eyescan_start(struct gt_ch *ch, struct gt_eyescan_params *params) +{ + struct gthe3_ch_priv *priv = ch->priv; + uint32_t val; + + uint32_t error_count; + uint32_t sample_count; + uint64_t bit_count; + float ber; + + priv->eyescan_running = 0; + + gthe3_ch_get_rx_lpm_en(ch, &val); + priv->dfe_en = !val; + + gthe3_ch_get_rx_data_width(ch, &priv->rx_data_width); + gthe3_ch_get_rx_int_data_width(ch, &priv->rx_int_data_width); + + priv->prescale = 0; + + for (priv->prescale = 0; priv->prescale < 32; priv->prescale++) + { + if (((uint64_t)0xffff * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale) >= params->target_bit_count) + break; + } + + params->target_bit_count = ((uint64_t)0xffff * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale); + params->h_range = 0; + + priv->h_start = params->h_start; + priv->h_stop = params->h_stop; + priv->h_step = params->h_step; + priv->v_range = params->v_range; + priv->v_start = params->v_start; + priv->v_stop = params->v_stop; + priv->v_step = params->v_step; + + gthe3_ch_set_es_control(ch, 0x00); + + gthe3_ch_set_es_prescale(ch, 4); + gthe3_ch_set_es_errdet_en(ch, 1); + + gthe3_ch_set_es_qual_mask_clear(ch); + gthe3_ch_set_es_sdata_mask_width(ch, priv->rx_int_data_width); + + gthe3_ch_set_rx_eyescan_vs_range(ch, priv->v_range); + + gthe3_ch_set_es_horz_offset(ch, 0x000); + gthe3_ch_set_rx_eyescan_vs_neg_dir(ch, 0); + gthe3_ch_set_rx_eyescan_vs_code(ch, 0); + gthe3_ch_set_rx_eyescan_vs_ut_sign(ch, 0); + + gthe3_ch_set_es_eye_scan_en(ch, 1); + + gthe3_ch_rx_pma_reset(ch); + + for (int ber_tries = 0; ber_tries < 10; ber_tries++) + { + for (int reset_tries = 0; reset_tries < 30; reset_tries++) + { + gthe3_ch_get_rx_reset_done(ch, &val); + if (val) + break; + usleep(100000); + } + + if (!val) + { + fprintf(stderr, "Error: channel stuck in reset\n"); + return -1; + } + + usleep(100000); + + // check for lock + gthe3_ch_set_es_control(ch, 0x01); + + for (int wait_tries = 0; wait_tries < 30; wait_tries++) + { + gthe3_ch_get_es_control_status(ch, &val); + if (val & 1) + break; + usleep(100000); + } + + if (!(val & 1)) + { + fprintf(stderr, "Error: eye scan did not finish (%d)\n", val); + return -1; + } + + gthe3_ch_set_es_control(ch, 0x00); + + gthe3_ch_get_es_error_count(ch, &error_count); + gthe3_ch_get_es_sample_count(ch, &sample_count); + bit_count = ((uint64_t)sample_count * (uint64_t)priv->rx_int_data_width) << (1+4); + + ber = (float)error_count / (float)bit_count; + + if (ber < 0.01) + break; + + printf("High BER (%02f), resetting eye scan logic\n", ber); + + gthe3_ch_set_es_horz_offset(ch, 0x880); + gthe3_ch_set_eyescan_reset(ch, 1); + gthe3_ch_set_es_horz_offset(ch, 0x800); + gthe3_ch_set_eyescan_reset(ch, 0); + } + + if (ber > 0.01) + { + fprintf(stderr, "Error: High BER, alignment failed\n"); + return -1; + } + + // set up for measurement + priv->h_offset = priv->h_start; + priv->v_offset = priv->v_start; + priv->ut_sign = 0; + + gthe3_ch_set_es_control(ch, 0x00); + gthe3_ch_set_es_prescale(ch, priv->prescale); + gthe3_ch_set_es_errdet_en(ch, 1); + gthe3_ch_set_es_horz_offset(ch, (priv->h_offset & 0x7ff) | (priv->h_offset < 0 ? 0x800 : 0x000)); + gthe3_ch_set_rx_eyescan_vs_neg_dir(ch, (priv->v_offset < 0)); + gthe3_ch_set_rx_eyescan_vs_code(ch, priv->v_offset < 0 ? -priv->v_offset : priv->v_offset); + gthe3_ch_set_rx_eyescan_vs_ut_sign(ch, priv->ut_sign); + + // start measurement + gthe3_ch_set_es_control(ch, 0x01); + + priv->eyescan_running = 1; + + return 0; +} + +static int gthe3_ch_eyescan_step(struct gt_ch *ch, struct gt_eyescan_point *point) +{ + struct gthe3_ch_priv *priv = ch->priv; + uint32_t val; + + uint32_t error_count; + uint32_t sample_count; + uint64_t bit_count; + + int restart = 0; + + if (!priv->eyescan_running) + return 0; + + gthe3_ch_get_es_control_status(ch, &val); + if (!(val & 1)) + return 2; + + gthe3_ch_set_es_control(ch, 0x00); + + gthe3_ch_get_es_error_count(ch, &error_count); + gthe3_ch_get_es_sample_count(ch, &sample_count); + bit_count = ((uint64_t)sample_count * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale); + + point->error_count = error_count; + point->bit_count = bit_count; + point->x = priv->h_offset; + point->y = priv->v_offset; + point->ut_sign = priv->ut_sign; + + restart = 0; + + if (!priv->ut_sign && priv->dfe_en) + { + priv->ut_sign = 1; + restart = 1; + } + else + { + priv->ut_sign = 0; + } + + gthe3_ch_set_rx_eyescan_vs_ut_sign(ch, priv->ut_sign); + + if (restart) + { + gthe3_ch_set_es_control(ch, 0x01); + return 1; + } + + if (priv->v_offset < priv->v_stop) + { + priv->v_offset += priv->v_step; + restart = 1; + } + else + { + priv->v_offset = priv->v_start; + } + + gthe3_ch_set_rx_eyescan_vs_neg_dir(ch, (priv->v_offset < 0)); + gthe3_ch_set_rx_eyescan_vs_code(ch, priv->v_offset < 0 ? -priv->v_offset : priv->v_offset); + + if (restart) + { + gthe3_ch_set_es_control(ch, 0x01); + return 1; + } + + if (priv->h_offset < priv->h_stop) + { + priv->h_offset += priv->h_step; + restart = 1; + } + else + { + // done + priv->eyescan_running = 0; + return 1; + } + + gthe3_ch_set_es_horz_offset(ch, (priv->h_offset & 0x7ff) | (priv->h_offset < 0 ? 0x800 : 0x000)); + + if (restart) + { + gthe3_ch_set_es_control(ch, 0x01); + return 1; + } + + priv->eyescan_running = 0; + return 0; +} + +const struct gt_ch_ops gthe3_gt_ch_ops = { + .get_tx_reset = gthe3_ch_get_tx_reset, + .set_tx_reset = gthe3_ch_set_tx_reset, + .tx_reset = gthe3_ch_tx_reset, + .get_rx_reset = gthe3_ch_get_rx_reset, + .set_rx_reset = gthe3_ch_set_rx_reset, + .rx_reset = gthe3_ch_rx_reset, + .get_tx_data_width = gthe3_ch_get_tx_data_width, + .get_tx_int_data_width = gthe3_ch_get_tx_int_data_width, + .get_rx_data_width = gthe3_ch_get_rx_data_width, + .get_rx_int_data_width = gthe3_ch_get_rx_int_data_width, + .get_available_presets = gthe3_ch_get_available_presets, + .load_preset = gthe3_ch_load_preset, + .eyescan_start = gthe3_ch_eyescan_start, + .eyescan_step = gthe3_ch_eyescan_step +}; + +static int gthe3_ch_init(struct gt_ch *ch) +{ + struct gthe3_ch_priv *priv = calloc(1, sizeof(struct gthe3_ch_priv)); + if (!priv) + return -1; + + ch->priv = priv; + + return 0; +} + +int gthe3_quad_init(struct gt_quad *quad) +{ + quad->type = "GTHE3"; + + for (int n = 0; n < quad->ch_count; n++) + { + quad->ch[n].quad = quad; + quad->ch[n].pll = &quad->pll; + quad->ch[n].ops = >he3_gt_ch_ops; + quad->ch[n].index = n; + + gthe3_ch_init(&quad->ch[n]); + } + + return 0; +} + +const struct gt_quad_ops gthe3_gt_quad_ops = { + .init = gthe3_quad_init +}; diff --git a/utils/xcvr_gthe3.h b/utils/xcvr_gthe3.h new file mode 100644 index 0000000..0a1ba2b --- /dev/null +++ b/utils/xcvr_gthe3.h @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#ifndef XCVR_GTHE3_H +#define XCVR_GTHE3_H + +#include "xcvr_gt.h" +#include "gt/gthe3_regs.h" + +// signals +#define GTHE3_COM_QPLL0_RESET_ADDR 0x10000 +#define GTHE3_COM_QPLL0_RESET_MSB 0 +#define GTHE3_COM_QPLL0_RESET_LSB 0 +#define GTHE3_COM_QPLL0_RESET_MASK BIT_MASK(GTHE3_COM_QPLL0_RESET_MSB, GTHE3_COM_QPLL0_RESET_LSB) +#define GTHE3_COM_QPLL0_LOCK_ADDR 0x10000 +#define GTHE3_COM_QPLL0_LOCK_MSB 8 +#define GTHE3_COM_QPLL0_LOCK_LSB 8 +#define GTHE3_COM_QPLL0_LOCK_MASK BIT_MASK(GTHE3_COM_QPLL0_LOCK_MSB, GTHE3_COM_QPLL0_LOCK_LSB) +#define GTHE3_COM_QPLL0_PD_ADDR 0x10001 +#define GTHE3_COM_QPLL0_PD_MSB 0 +#define GTHE3_COM_QPLL0_PD_LSB 0 +#define GTHE3_COM_QPLL0_PD_MASK BIT_MASK(GTHE3_COM_QPLL0_PD_MSB, GTHE3_COM_QPLL0_PD_LSB) +#define GTHE3_COM_QPLL1_RESET_ADDR 0x11000 +#define GTHE3_COM_QPLL1_RESET_MSB 0 +#define GTHE3_COM_QPLL1_RESET_LSB 0 +#define GTHE3_COM_QPLL1_RESET_MASK BIT_MASK(GTHE3_COM_QPLL0_RESET_MSB, GTHE3_COM_QPLL0_RESET_LSB) +#define GTHE3_COM_QPLL1_LOCK_ADDR 0x11000 +#define GTHE3_COM_QPLL1_LOCK_MSB 8 +#define GTHE3_COM_QPLL1_LOCK_LSB 8 +#define GTHE3_COM_QPLL1_LOCK_MASK BIT_MASK(GTHE3_COM_QPLL0_LOCK_MSB, GTHE3_COM_QPLL0_LOCK_LSB) +#define GTHE3_COM_QPLL1_PD_ADDR 0x11001 +#define GTHE3_COM_QPLL1_PD_MSB 0 +#define GTHE3_COM_QPLL1_PD_LSB 0 +#define GTHE3_COM_QPLL1_PD_MASK BIT_MASK(GTHE3_COM_QPLL1_PD_MSB, GTHE3_COM_QPLL1_PD_LSB) + +#define GTHE3_CH_TX_RESET_ADDR 0x10000 +#define GTHE3_CH_TX_RESET_MSB 0 +#define GTHE3_CH_TX_RESET_LSB 0 +#define GTHE3_CH_TX_RESET_MASK BIT_MASK(GTHE3_CH_TX_RESET_MSB, GTHE3_CH_TX_RESET_LSB) +#define GTHE3_CH_TX_PMA_RESET_ADDR 0x10000 +#define GTHE3_CH_TX_PMA_RESET_MSB 1 +#define GTHE3_CH_TX_PMA_RESET_LSB 1 +#define GTHE3_CH_TX_PMA_RESET_MASK BIT_MASK(GTHE3_CH_TX_PMA_RESET_MSB, GTHE3_CH_TX_PMA_RESET_LSB) +#define GTHE3_CH_TX_PCS_RESET_ADDR 0x10000 +#define GTHE3_CH_TX_PCS_RESET_MSB 2 +#define GTHE3_CH_TX_PCS_RESET_LSB 2 +#define GTHE3_CH_TX_PCS_RESET_MASK BIT_MASK(GTHE3_CH_TX_PCS_RESET_MSB, GTHE3_CH_TX_PCS_RESET_LSB) +#define GTHE3_CH_TX_RESET_DONE_ADDR 0x10000 +#define GTHE3_CH_TX_RESET_DONE_MSB 8 +#define GTHE3_CH_TX_RESET_DONE_LSB 8 +#define GTHE3_CH_TX_RESET_DONE_MASK BIT_MASK(GTHE3_CH_TX_RESET_DONE_MSB, GTHE3_CH_TX_RESET_DONE_LSB) +#define GTHE3_CH_TX_GT_RESET_DONE_ADDR 0x10000 +#define GTHE3_CH_TX_GT_RESET_DONE_MSB 9 +#define GTHE3_CH_TX_GT_RESET_DONE_LSB 9 +#define GTHE3_CH_TX_GT_RESET_DONE_MASK BIT_MASK(GTHE3_CH_TX_GT_RESET_DONE_MSB, GTHE3_CH_TX_GT_RESET_DONE_LSB) +#define GTHE3_CH_TX_PMA_RESET_DONE_ADDR 0x10000 +#define GTHE3_CH_TX_PMA_RESET_DONE_MSB 10 +#define GTHE3_CH_TX_PMA_RESET_DONE_LSB 10 +#define GTHE3_CH_TX_PMA_RESET_DONE_MASK BIT_MASK(GTHE3_CH_TX_PMA_RESET_DONE_MSB, GTHE3_CH_TX_PMA_RESET_DONE_LSB) +#define GTHE3_CH_TX_PRGDIV_RESET_DONE_ADDR 0x10000 +#define GTHE3_CH_TX_PRGDIV_RESET_DONE_MSB 11 +#define GTHE3_CH_TX_PRGDIV_RESET_DONE_LSB 11 +#define GTHE3_CH_TX_PRGDIV_RESET_DONE_MASK BIT_MASK(GTHE3_CH_TX_PRGDIV_RESET_DONE_MSB, GTHE3_CH_TX_PRGDIV_RESET_DONE_LSB) +#define GTHE3_CH_TX_USRCLK_ACT_ADDR 0x10000 +#define GTHE3_CH_TX_USRCLK_ACT_MSB 12 +#define GTHE3_CH_TX_USRCLK_ACT_LSB 12 +#define GTHE3_CH_TX_USRCLK_ACT_MASK BIT_MASK(GTHE3_CH_TX_USRCLK_ACT_MSB, GTHE3_CH_TX_USRCLK_ACT_LSB) +#define GTHE3_CH_TX_PD_ADDR 0x10001 +#define GTHE3_CH_TX_PD_MSB 0 +#define GTHE3_CH_TX_PD_LSB 0 +#define GTHE3_CH_TX_PD_MASK BIT_MASK(GTHE3_CH_TX_PD_MSB, GTHE3_CH_TX_PD_LSB) +#define GTHE3_CH_TX_QPLL_SEL_ADDR 0x10001 +#define GTHE3_CH_TX_QPLL_SEL_MSB 1 +#define GTHE3_CH_TX_QPLL_SEL_LSB 1 +#define GTHE3_CH_TX_QPLL_SEL_MASK BIT_MASK(GTHE3_CH_TX_QPLL_SEL_MSB, GTHE3_CH_TX_QPLL_SEL_LSB) +#define GTHE3_CH_TX_POLARITY_ADDR 0x10010 +#define GTHE3_CH_TX_POLARITY_MSB 0 +#define GTHE3_CH_TX_POLARITY_LSB 0 +#define GTHE3_CH_TX_POLARITY_MASK BIT_MASK(GTHE3_CH_TX_POLARITY_MSB, GTHE3_CH_TX_POLARITY_LSB) +#define GTHE3_CH_TX_ELECIDLE_ADDR 0x10010 +#define GTHE3_CH_TX_ELECIDLE_MSB 1 +#define GTHE3_CH_TX_ELECIDLE_LSB 1 +#define GTHE3_CH_TX_ELECIDLE_MASK BIT_MASK(GTHE3_CH_TX_ELECIDLE_MSB, GTHE3_CH_TX_ELECIDLE_LSB) +#define GTHE3_CH_TX_INHIBIT_ADDR 0x10010 +#define GTHE3_CH_TX_INHIBIT_MSB 2 +#define GTHE3_CH_TX_INHIBIT_LSB 2 +#define GTHE3_CH_TX_INHIBIT_MASK BIT_MASK(GTHE3_CH_TX_INHIBIT_MSB, GTHE3_CH_TX_INHIBIT_LSB) +#define GTHE3_CH_TX_DIFFCTRL_ADDR 0x10011 +#define GTHE3_CH_TX_DIFFCTRL_MSB 4 +#define GTHE3_CH_TX_DIFFCTRL_LSB 0 +#define GTHE3_CH_TX_DIFFCTRL_MASK BIT_MASK(GTHE3_CH_TX_DIFFCTRL_MSB, GTHE3_CH_TX_DIFFCTRL_LSB) +#define GTHE3_CH_TX_MAINCURSOR_ADDR 0x10012 +#define GTHE3_CH_TX_MAINCURSOR_MSB 6 +#define GTHE3_CH_TX_MAINCURSOR_LSB 0 +#define GTHE3_CH_TX_MAINCURSOR_MASK BIT_MASK(GTHE3_CH_TX_MAINCURSOR_MSB, GTHE3_CH_TX_MAINCURSOR_LSB) +#define GTHE3_CH_TX_PRECURSOR_ADDR 0x10013 +#define GTHE3_CH_TX_PRECURSOR_MSB 4 +#define GTHE3_CH_TX_PRECURSOR_LSB 0 +#define GTHE3_CH_TX_PRECURSOR_MASK BIT_MASK(GTHE3_CH_TX_PRECURSOR_MSB, GTHE3_CH_TX_PRECURSOR_LSB) +#define GTHE3_CH_TX_POSTCURSOR_ADDR 0x10014 +#define GTHE3_CH_TX_POSTCURSOR_MSB 4 +#define GTHE3_CH_TX_POSTCURSOR_LSB 0 +#define GTHE3_CH_TX_POSTCURSOR_MASK BIT_MASK(GTHE3_CH_TX_POSTCURSOR_MSB, GTHE3_CH_TX_POSTCURSOR_LSB) +#define GTHE3_CH_TX_PRBS_SEL_ADDR 0x10040 +#define GTHE3_CH_TX_PRBS_SEL_MSB 3 +#define GTHE3_CH_TX_PRBS_SEL_LSB 0 +#define GTHE3_CH_TX_PRBS_SEL_MASK BIT_MASK(GTHE3_CH_TX_PRBS_SEL_MSB, GTHE3_CH_TX_PRBS_SEL_LSB) +#define GTHE3_CH_TX_PRBS_FORCERR_ADDR 0x10040 +#define GTHE3_CH_TX_PRBS_FORCERR_MSB 15 +#define GTHE3_CH_TX_PRBS_FORCERR_LSB 0 +#define GTHE3_CH_TX_PRBS_FORCERR_MASK BIT_MASK(GTHE3_CH_TX_PRBS_FORCERR_MSB, GTHE3_CH_TX_PRBS_FORCERR_LSB) +#define GTHE3_CH_RX_RESET_ADDR 0x11000 +#define GTHE3_CH_RX_RESET_MSB 0 +#define GTHE3_CH_RX_RESET_LSB 0 +#define GTHE3_CH_RX_RESET_MASK BIT_MASK(GTHE3_CH_RX_RESET_MSB, GTHE3_CH_RX_RESET_LSB) +#define GTHE3_CH_RX_PMA_RESET_ADDR 0x11000 +#define GTHE3_CH_RX_PMA_RESET_MSB 1 +#define GTHE3_CH_RX_PMA_RESET_LSB 1 +#define GTHE3_CH_RX_PMA_RESET_MASK BIT_MASK(GTHE3_CH_RX_PMA_RESET_MSB, GTHE3_CH_RX_PMA_RESET_LSB) +#define GTHE3_CH_RX_PCS_RESET_ADDR 0x11000 +#define GTHE3_CH_RX_PCS_RESET_MSB 2 +#define GTHE3_CH_RX_PCS_RESET_LSB 2 +#define GTHE3_CH_RX_PCS_RESET_MASK BIT_MASK(GTHE3_CH_RX_PCS_RESET_MSB, GTHE3_CH_RX_PCS_RESET_LSB) +#define GTHE3_CH_RX_DFE_LPM_RESET_ADDR 0x11000 +#define GTHE3_CH_RX_DFE_LPM_RESET_MSB 3 +#define GTHE3_CH_RX_DFE_LPM_RESET_LSB 3 +#define GTHE3_CH_RX_DFE_LPM_RESET_MASK BIT_MASK(GTHE3_CH_RX_DFE_LPM_RESET_MSB, GTHE3_CH_RX_DFE_LPM_RESET_LSB) +#define GTHE3_CH_EYESCAN_RESET_ADDR 0x11000 +#define GTHE3_CH_EYESCAN_RESET_MSB 4 +#define GTHE3_CH_EYESCAN_RESET_LSB 4 +#define GTHE3_CH_EYESCAN_RESET_MASK BIT_MASK(GTHE3_CH_EYESCAN_RESET_MSB, GTHE3_CH_EYESCAN_RESET_LSB) +#define GTHE3_CH_RX_RESET_DONE_ADDR 0x11000 +#define GTHE3_CH_RX_RESET_DONE_MSB 8 +#define GTHE3_CH_RX_RESET_DONE_LSB 8 +#define GTHE3_CH_RX_RESET_DONE_MASK BIT_MASK(GTHE3_CH_RX_RESET_DONE_MSB, GTHE3_CH_RX_RESET_DONE_LSB) +#define GTHE3_CH_RX_GT_RESET_DONE_ADDR 0x11000 +#define GTHE3_CH_RX_GT_RESET_DONE_MSB 9 +#define GTHE3_CH_RX_GT_RESET_DONE_LSB 9 +#define GTHE3_CH_RX_GT_RESET_DONE_MASK BIT_MASK(GTHE3_CH_RX_GT_RESET_DONE_MSB, GTHE3_CH_RX_GT_RESET_DONE_LSB) +#define GTHE3_CH_RX_PMA_RESET_DONE_ADDR 0x11000 +#define GTHE3_CH_RX_PMA_RESET_DONE_MSB 10 +#define GTHE3_CH_RX_PMA_RESET_DONE_LSB 10 +#define GTHE3_CH_RX_PMA_RESET_DONE_MASK BIT_MASK(GTHE3_CH_RX_PMA_RESET_DONE_MSB, GTHE3_CH_RX_PMA_RESET_DONE_LSB) +#define GTHE3_CH_RX_PRGDIV_RESET_DONE_ADDR 0x11000 +#define GTHE3_CH_RX_PRGDIV_RESET_DONE_MSB 11 +#define GTHE3_CH_RX_PRGDIV_RESET_DONE_LSB 11 +#define GTHE3_CH_RX_PRGDIV_RESET_DONE_MASK BIT_MASK(GTHE3_CH_RX_PRGDIV_RESET_DONE_MSB, GTHE3_CH_RX_PRGDIV_RESET_DONE_LSB) +#define GTHE3_CH_RX_USRCLK_ACT_ADDR 0x11000 +#define GTHE3_CH_RX_USRCLK_ACT_MSB 12 +#define GTHE3_CH_RX_USRCLK_ACT_LSB 12 +#define GTHE3_CH_RX_USRCLK_ACT_MASK BIT_MASK(GTHE3_CH_RX_USRCLK_ACT_MSB, GTHE3_CH_RX_USRCLK_ACT_LSB) +#define GTHE3_CH_RX_PD_ADDR 0x11001 +#define GTHE3_CH_RX_PD_MSB 0 +#define GTHE3_CH_RX_PD_LSB 0 +#define GTHE3_CH_RX_PD_MASK BIT_MASK(GTHE3_CH_RX_PD_MSB, GTHE3_CH_RX_PD_LSB) +#define GTHE3_CH_RX_QPLL_SEL_ADDR 0x11001 +#define GTHE3_CH_RX_QPLL_SEL_MSB 1 +#define GTHE3_CH_RX_QPLL_SEL_LSB 1 +#define GTHE3_CH_RX_QPLL_SEL_MASK BIT_MASK(GTHE3_CH_RX_QPLL_SEL_MSB, GTHE3_CH_RX_QPLL_SEL_LSB) +#define GTHE3_CH_LOOPBACK_ADDR 0x11002 +#define GTHE3_CH_LOOPBACK_MSB 2 +#define GTHE3_CH_LOOPBACK_LSB 0 +#define GTHE3_CH_LOOPBACK_MASK BIT_MASK(GTHE3_CH_LOOPBACK_MSB, GTHE3_CH_LOOPBACK_LSB) +#define GTHE3_CH_RX_POLARITY_ADDR 0x11010 +#define GTHE3_CH_RX_POLARITY_MSB 0 +#define GTHE3_CH_RX_POLARITY_LSB 0 +#define GTHE3_CH_RX_POLARITY_MASK BIT_MASK(GTHE3_CH_RX_POLARITY_MSB, GTHE3_CH_RX_POLARITY_LSB) +#define GTHE3_CH_RX_CDR_HOLD_ADDR 0x11020 +#define GTHE3_CH_RX_CDR_HOLD_MSB 0 +#define GTHE3_CH_RX_CDR_HOLD_LSB 0 +#define GTHE3_CH_RX_CDR_HOLD_MASK BIT_MASK(GTHE3_CH_RX_CDR_HOLD_MSB, GTHE3_CH_RX_CDR_HOLD_LSB) +#define GTHE3_CH_RX_CDR_LOCK_ADDR 0x11020 +#define GTHE3_CH_RX_CDR_LOCK_MSB 8 +#define GTHE3_CH_RX_CDR_LOCK_LSB 8 +#define GTHE3_CH_RX_CDR_LOCK_MASK BIT_MASK(GTHE3_CH_RX_CDR_LOCK_MSB, GTHE3_CH_RX_CDR_LOCK_LSB) +#define GTHE3_CH_RX_LPM_EN_ADDR 0x11024 +#define GTHE3_CH_RX_LPM_EN_MSB 0 +#define GTHE3_CH_RX_LPM_EN_LSB 0 +#define GTHE3_CH_RX_LPM_EN_MASK BIT_MASK(GTHE3_CH_RX_LPM_EN_MSB, GTHE3_CH_RX_LPM_EN_LSB) +#define GTHE3_CH_RX_DMONITOR_ADDR 0x11028 +#define GTHE3_CH_RX_DMONITOR_MSB 7 +#define GTHE3_CH_RX_DMONITOR_LSB 0 +#define GTHE3_CH_RX_DMONITOR_MASK BIT_MASK(GTHE3_CH_RX_DMONITOR_MSB, GTHE3_CH_RX_DMONITOR_LSB) +#define GTHE3_CH_RX_PRBS_SEL_ADDR 0x11040 +#define GTHE3_CH_RX_PRBS_SEL_MSB 3 +#define GTHE3_CH_RX_PRBS_SEL_LSB 0 +#define GTHE3_CH_RX_PRBS_SEL_MASK BIT_MASK(GTHE3_CH_RX_PRBS_SEL_MSB, GTHE3_CH_RX_PRBS_SEL_LSB) +#define GTHE3_CH_RX_PRBS_CNT_RESET_ADDR 0x11041 +#define GTHE3_CH_RX_PRBS_CNT_RESET_MSB 0 +#define GTHE3_CH_RX_PRBS_CNT_RESET_LSB 0 +#define GTHE3_CH_RX_PRBS_CNT_RESET_MASK BIT_MASK(GTHE3_CH_RX_PRBS_CNT_RESET_MSB, GTHE3_CH_RX_PRBS_CNT_RESET_LSB) +#define GTHE3_CH_RX_PRBS_LOCKED_ADDR 0x11041 +#define GTHE3_CH_RX_PRBS_LOCKED_MSB 8 +#define GTHE3_CH_RX_PRBS_LOCKED_LSB 8 +#define GTHE3_CH_RX_PRBS_LOCKED_MASK BIT_MASK(GTHE3_CH_RX_PRBS_LOCKED_MSB, GTHE3_CH_RX_PRBS_LOCKED_LSB) +#define GTHE3_CH_RX_PRBS_ERROR_ADDR 0x11041 +#define GTHE3_CH_RX_PRBS_ERROR_MSB 9 +#define GTHE3_CH_RX_PRBS_ERROR_LSB 9 +#define GTHE3_CH_RX_PRBS_ERROR_MASK BIT_MASK(GTHE3_CH_RX_PRBS_ERROR_MSB, GTHE3_CH_RX_PRBS_ERROR_LSB) + + +def_gt_pll_masked_reg_rw16(gthe3, qpll0_reset, GTHE3_COM_QPLL0_RESET_ADDR, GTHE3_COM_QPLL0_RESET_MASK, GTHE3_COM_QPLL0_RESET_LSB); +int gthe3_pll_qpll0_reset(struct gt_pll *pll); +def_gt_pll_masked_reg_read16(gthe3, qpll0_lock, GTHE3_COM_QPLL0_LOCK_ADDR, GTHE3_COM_QPLL0_LOCK_MASK, GTHE3_COM_QPLL0_LOCK_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_pd, GTHE3_COM_QPLL0_PD_ADDR, GTHE3_COM_QPLL0_PD_MASK, GTHE3_COM_QPLL0_PD_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_reset, GTHE3_COM_QPLL1_RESET_ADDR, GTHE3_COM_QPLL1_RESET_MASK, GTHE3_COM_QPLL1_RESET_LSB); +int gthe3_pll_qpll1_reset(struct gt_pll *pll); +def_gt_pll_masked_reg_read16(gthe3, qpll1_lock, GTHE3_COM_QPLL1_LOCK_ADDR, GTHE3_COM_QPLL1_LOCK_MASK, GTHE3_COM_QPLL1_LOCK_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_pd, GTHE3_COM_QPLL1_PD_ADDR, GTHE3_COM_QPLL1_PD_MASK, GTHE3_COM_QPLL1_PD_LSB); + +def_gt_ch_masked_reg_rw16(gthe3, tx_reset, GTHE3_CH_TX_RESET_ADDR, GTHE3_CH_TX_RESET_MASK, GTHE3_CH_TX_RESET_LSB); +int gthe3_ch_tx_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe3, tx_pma_reset, GTHE3_CH_TX_PMA_RESET_ADDR, GTHE3_CH_TX_PMA_RESET_MASK, GTHE3_CH_TX_PMA_RESET_LSB); +int gthe3_ch_tx_pma_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe3, tx_pcs_reset, GTHE3_CH_TX_PCS_RESET_ADDR, GTHE3_CH_TX_PCS_RESET_MASK, GTHE3_CH_TX_PCS_RESET_LSB); +int gthe3_ch_tx_pcs_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_read16(gthe3, tx_reset_done, GTHE3_CH_TX_RESET_DONE_ADDR, GTHE3_CH_TX_RESET_DONE_MASK, GTHE3_CH_TX_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe3, tx_gt_reset_done, GTHE3_CH_TX_GT_RESET_DONE_ADDR, GTHE3_CH_TX_GT_RESET_DONE_MASK, GTHE3_CH_TX_GT_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe3, tx_pma_reset_done, GTHE3_CH_TX_PMA_RESET_DONE_ADDR, GTHE3_CH_TX_PMA_RESET_DONE_MASK, GTHE3_CH_TX_PMA_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe3, tx_prgdiv_reset_done, GTHE3_CH_TX_PRGDIV_RESET_DONE_ADDR, GTHE3_CH_TX_PRGDIV_RESET_DONE_MASK, GTHE3_CH_TX_PRGDIV_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe3, tx_usrclk_act, GTHE3_CH_TX_USRCLK_ACT_ADDR, GTHE3_CH_TX_USRCLK_ACT_MASK, GTHE3_CH_TX_USRCLK_ACT_LSB); +def_gt_ch_masked_reg_rw16(gthe3, tx_pd, GTHE3_CH_TX_PD_ADDR, GTHE3_CH_TX_PD_MASK, GTHE3_CH_TX_PD_LSB); +def_gt_ch_masked_reg_rw16(gthe3, tx_qpll_sel, GTHE3_CH_TX_QPLL_SEL_ADDR, GTHE3_CH_TX_QPLL_SEL_MASK, GTHE3_CH_TX_QPLL_SEL_LSB); +def_gt_ch_masked_reg_rw16(gthe3, tx_polarity, GTHE3_CH_TX_POLARITY_ADDR, GTHE3_CH_TX_POLARITY_MASK, GTHE3_CH_TX_POLARITY_LSB); +def_gt_ch_masked_reg_rw16(gthe3, tx_elecidle, GTHE3_CH_TX_ELECIDLE_ADDR, GTHE3_CH_TX_ELECIDLE_MASK, GTHE3_CH_TX_ELECIDLE_LSB); +def_gt_ch_masked_reg_rw16(gthe3, tx_inhibit, GTHE3_CH_TX_INHIBIT_ADDR, GTHE3_CH_TX_INHIBIT_MASK, GTHE3_CH_TX_INHIBIT_LSB); +def_gt_ch_masked_reg_rw16(gthe3, tx_diffctrl, GTHE3_CH_TX_DIFFCTRL_ADDR, GTHE3_CH_TX_DIFFCTRL_MASK, GTHE3_CH_TX_DIFFCTRL_LSB); +def_gt_ch_masked_reg_rw16(gthe3, tx_maincursor, GTHE3_CH_TX_MAINCURSOR_ADDR, GTHE3_CH_TX_MAINCURSOR_MASK, GTHE3_CH_TX_MAINCURSOR_LSB); +def_gt_ch_masked_reg_rw16(gthe3, tx_precursor, GTHE3_CH_TX_PRECURSOR_ADDR, GTHE3_CH_TX_PRECURSOR_MASK, GTHE3_CH_TX_PRECURSOR_LSB); +def_gt_ch_masked_reg_rw16(gthe3, tx_postcursor, GTHE3_CH_TX_POSTCURSOR_ADDR, GTHE3_CH_TX_POSTCURSOR_MASK, GTHE3_CH_TX_POSTCURSOR_LSB); +def_gt_ch_masked_reg_rw16(gthe3, tx_prbs_sel, GTHE3_CH_TX_PRBS_SEL_ADDR, GTHE3_CH_TX_PRBS_SEL_MASK, GTHE3_CH_TX_PRBS_SEL_LSB); +def_gt_ch_masked_reg_rw16(gthe3, tx_prbs_forcerr, GTHE3_CH_TX_PRBS_FORCERR_ADDR, GTHE3_CH_TX_PRBS_FORCERR_MASK, GTHE3_CH_TX_PRBS_FORCERR_LSB); + +def_gt_ch_masked_reg_rw16(gthe3, rx_reset, GTHE3_CH_RX_RESET_ADDR, GTHE3_CH_RX_RESET_MASK, GTHE3_CH_RX_RESET_LSB); +int gthe3_ch_rx_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe3, rx_pma_reset, GTHE3_CH_RX_PMA_RESET_ADDR, GTHE3_CH_RX_PMA_RESET_MASK, GTHE3_CH_RX_PMA_RESET_LSB); +int gthe3_ch_rx_pma_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe3, rx_pcs_reset, GTHE3_CH_RX_PCS_RESET_ADDR, GTHE3_CH_RX_PCS_RESET_MASK, GTHE3_CH_RX_PCS_RESET_LSB); +int gthe3_ch_rx_pcs_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe3, rx_dfe_lpm_reset, GTHE3_CH_RX_DFE_LPM_RESET_ADDR, GTHE3_CH_RX_DFE_LPM_RESET_MASK, GTHE3_CH_RX_DFE_LPM_RESET_LSB); +int gthe3_ch_rx_dfe_lpm_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe3, eyescan_reset, GTHE3_CH_EYESCAN_RESET_ADDR, GTHE3_CH_EYESCAN_RESET_MASK, GTHE3_CH_EYESCAN_RESET_LSB); +int gthe3_ch_eyescan_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_read16(gthe3, rx_reset_done, GTHE3_CH_RX_RESET_DONE_ADDR, GTHE3_CH_RX_RESET_DONE_MASK, GTHE3_CH_RX_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe3, rx_gt_reset_done, GTHE3_CH_RX_GT_RESET_DONE_ADDR, GTHE3_CH_RX_GT_RESET_DONE_MASK, GTHE3_CH_RX_GT_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe3, rx_pma_reset_done, GTHE3_CH_RX_PMA_RESET_DONE_ADDR, GTHE3_CH_RX_PMA_RESET_DONE_MASK, GTHE3_CH_RX_PMA_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe3, rx_prgdiv_reset_done, GTHE3_CH_RX_PRGDIV_RESET_DONE_ADDR, GTHE3_CH_RX_PRGDIV_RESET_DONE_MASK, GTHE3_CH_RX_PRGDIV_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe3, rx_usrclk_act, GTHE3_CH_RX_USRCLK_ACT_ADDR, GTHE3_CH_RX_USRCLK_ACT_MASK, GTHE3_CH_RX_USRCLK_ACT_LSB); +def_gt_ch_masked_reg_rw16(gthe3, rx_pd, GTHE3_CH_RX_PD_ADDR, GTHE3_CH_RX_PD_MASK, GTHE3_CH_RX_PD_LSB); +def_gt_ch_masked_reg_rw16(gthe3, rx_qpll_sel, GTHE3_CH_RX_QPLL_SEL_ADDR, GTHE3_CH_RX_QPLL_SEL_MASK, GTHE3_CH_RX_QPLL_SEL_LSB); +def_gt_ch_masked_reg_rw16(gthe3, loopback, GTHE3_CH_LOOPBACK_ADDR, GTHE3_CH_LOOPBACK_MASK, GTHE3_CH_LOOPBACK_LSB); +def_gt_ch_masked_reg_rw16(gthe3, rx_polarity, GTHE3_CH_RX_POLARITY_ADDR, GTHE3_CH_RX_POLARITY_MASK, GTHE3_CH_RX_POLARITY_LSB); +def_gt_ch_masked_reg_rw16(gthe3, rx_cdr_hold, GTHE3_CH_RX_CDR_HOLD_ADDR, GTHE3_CH_RX_CDR_HOLD_MASK, GTHE3_CH_RX_CDR_HOLD_LSB); +def_gt_ch_masked_reg_read16(gthe3, rx_cdr_lock, GTHE3_CH_RX_CDR_LOCK_ADDR, GTHE3_CH_RX_CDR_LOCK_MASK, GTHE3_CH_RX_CDR_LOCK_LSB); +def_gt_ch_masked_reg_rw16(gthe3, rx_lpm_en, GTHE3_CH_RX_LPM_EN_ADDR, GTHE3_CH_RX_LPM_EN_MASK, GTHE3_CH_RX_LPM_EN_LSB); +def_gt_ch_masked_reg_read16(gthe3, rx_dmonitor, GTHE3_CH_RX_DMONITOR_ADDR, GTHE3_CH_RX_DMONITOR_MASK, GTHE3_CH_RX_DMONITOR_LSB); +def_gt_ch_masked_reg_rw16(gthe3, rx_prbs_sel, GTHE3_CH_RX_PRBS_SEL_ADDR, GTHE3_CH_RX_PRBS_SEL_MASK, GTHE3_CH_RX_PRBS_SEL_LSB); +def_gt_ch_masked_reg_rw16(gthe3, rx_prbs_cnt_reset, GTHE3_CH_RX_PRBS_CNT_RESET_ADDR, GTHE3_CH_RX_PRBS_CNT_RESET_MASK, GTHE3_CH_RX_PRBS_CNT_RESET_LSB); +def_gt_ch_masked_reg_read16(gthe3, rx_prbs_locked, GTHE3_CH_RX_PRBS_LOCKED_ADDR, GTHE3_CH_RX_PRBS_LOCKED_MASK, GTHE3_CH_RX_PRBS_LOCKED_LSB); +def_gt_ch_masked_reg_read16(gthe3, rx_prbs_error, GTHE3_CH_RX_PRBS_ERROR_ADDR, GTHE3_CH_RX_PRBS_ERROR_MASK, GTHE3_CH_RX_PRBS_ERROR_LSB); + +// common +def_gt_pll_masked_reg_rw16(gthe3, qpll0_cfg0, GTHE3_COM_QPLL0_CFG0_ADDR, GTHE3_COM_QPLL0_CFG0_MASK, GTHE3_COM_QPLL0_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, common_cfg0, GTHE3_COM_COMMON_CFG0_ADDR, GTHE3_COM_COMMON_CFG0_MASK, GTHE3_COM_COMMON_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, rsvd_attr0, GTHE3_COM_RSVD_ATTR0_ADDR, GTHE3_COM_RSVD_ATTR0_MASK, GTHE3_COM_RSVD_ATTR0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_cfg1, GTHE3_COM_QPLL0_CFG1_ADDR, GTHE3_COM_QPLL0_CFG1_MASK, GTHE3_COM_QPLL0_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_cfg2, GTHE3_COM_QPLL0_CFG2_ADDR, GTHE3_COM_QPLL0_CFG2_MASK, GTHE3_COM_QPLL0_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_lock_cfg, GTHE3_COM_QPLL0_LOCK_CFG_ADDR, GTHE3_COM_QPLL0_LOCK_CFG_MASK, GTHE3_COM_QPLL0_LOCK_CFG_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_init_cfg0, GTHE3_COM_QPLL0_INIT_CFG0_ADDR, GTHE3_COM_QPLL0_INIT_CFG0_MASK, GTHE3_COM_QPLL0_INIT_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_init_cfg1, GTHE3_COM_QPLL0_INIT_CFG1_ADDR, GTHE3_COM_QPLL0_INIT_CFG1_MASK, GTHE3_COM_QPLL0_INIT_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_fbdiv, GTHE3_COM_QPLL0_FBDIV_ADDR, GTHE3_COM_QPLL0_FBDIV_MASK, GTHE3_COM_QPLL0_FBDIV_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_cfg3, GTHE3_COM_QPLL0_CFG3_ADDR, GTHE3_COM_QPLL0_CFG3_MASK, GTHE3_COM_QPLL0_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_cp, GTHE3_COM_QPLL0_CP_ADDR, GTHE3_COM_QPLL0_CP_MASK, GTHE3_COM_QPLL0_CP_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_refclk_div, GTHE3_COM_QPLL0_REFCLK_DIV_ADDR, GTHE3_COM_QPLL0_REFCLK_DIV_MASK, GTHE3_COM_QPLL0_REFCLK_DIV_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_lpf, GTHE3_COM_QPLL0_LPF_ADDR, GTHE3_COM_QPLL0_LPF_MASK, GTHE3_COM_QPLL0_LPF_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_cfg1_g3, GTHE3_COM_QPLL0_CFG1_G3_ADDR, GTHE3_COM_QPLL0_CFG1_G3_MASK, GTHE3_COM_QPLL0_CFG1_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_cfg2_g3, GTHE3_COM_QPLL0_CFG2_G3_ADDR, GTHE3_COM_QPLL0_CFG2_G3_MASK, GTHE3_COM_QPLL0_CFG2_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_lpf_g3, GTHE3_COM_QPLL0_LPF_G3_ADDR, GTHE3_COM_QPLL0_LPF_G3_MASK, GTHE3_COM_QPLL0_LPF_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_lock_cfg_g3, GTHE3_COM_QPLL0_LOCK_CFG_G3_ADDR, GTHE3_COM_QPLL0_LOCK_CFG_G3_MASK, GTHE3_COM_QPLL0_LOCK_CFG_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, rsvd_attr1, GTHE3_COM_RSVD_ATTR1_ADDR, GTHE3_COM_RSVD_ATTR1_MASK, GTHE3_COM_RSVD_ATTR1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_fbdiv_g3, GTHE3_COM_QPLL0_FBDIV_G3_ADDR, GTHE3_COM_QPLL0_FBDIV_G3_MASK, GTHE3_COM_QPLL0_FBDIV_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, rxrecclkout0_sel, GTHE3_COM_RXRECCLKOUT0_SEL_ADDR, GTHE3_COM_RXRECCLKOUT0_SEL_MASK, GTHE3_COM_RXRECCLKOUT0_SEL_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_sdm_cfg0, GTHE3_COM_QPLL0_SDM_CFG0_ADDR, GTHE3_COM_QPLL0_SDM_CFG0_MASK, GTHE3_COM_QPLL0_SDM_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_sdm_cfg1, GTHE3_COM_QPLL0_SDM_CFG1_ADDR, GTHE3_COM_QPLL0_SDM_CFG1_MASK, GTHE3_COM_QPLL0_SDM_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm0initseed0_0, GTHE3_COM_SDM0INITSEED0_0_ADDR, GTHE3_COM_SDM0INITSEED0_0_MASK, GTHE3_COM_SDM0INITSEED0_0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm0initseed0_1, GTHE3_COM_SDM0INITSEED0_1_ADDR, GTHE3_COM_SDM0INITSEED0_1_MASK, GTHE3_COM_SDM0INITSEED0_1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_sdm_cfg2, GTHE3_COM_QPLL0_SDM_CFG2_ADDR, GTHE3_COM_QPLL0_SDM_CFG2_MASK, GTHE3_COM_QPLL0_SDM_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_cp_g3, GTHE3_COM_QPLL0_CP_G3_ADDR, GTHE3_COM_QPLL0_CP_G3_MASK, GTHE3_COM_QPLL0_CP_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm0data1_0, GTHE3_COM_SDM0DATA1_0_ADDR, GTHE3_COM_SDM0DATA1_0_MASK, GTHE3_COM_SDM0DATA1_0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm0_width_pin_sel, GTHE3_COM_SDM0_WIDTH_PIN_SEL_ADDR, GTHE3_COM_SDM0_WIDTH_PIN_SEL_MASK, GTHE3_COM_SDM0_WIDTH_PIN_SEL_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm0_data_pin_sel, GTHE3_COM_SDM0_DATA_PIN_SEL_ADDR, GTHE3_COM_SDM0_DATA_PIN_SEL_MASK, GTHE3_COM_SDM0_DATA_PIN_SEL_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm0data1_1, GTHE3_COM_SDM0DATA1_1_ADDR, GTHE3_COM_SDM0DATA1_1_MASK, GTHE3_COM_SDM0DATA1_1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll0_cfg4, GTHE3_COM_QPLL0_CFG4_ADDR, GTHE3_COM_QPLL0_CFG4_MASK, GTHE3_COM_QPLL0_CFG4_LSB); +def_gt_pll_masked_reg_rw16(gthe3, bias_cfg0, GTHE3_COM_BIAS_CFG0_ADDR, GTHE3_COM_BIAS_CFG0_MASK, GTHE3_COM_BIAS_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, bias_cfg1, GTHE3_COM_BIAS_CFG1_ADDR, GTHE3_COM_BIAS_CFG1_MASK, GTHE3_COM_BIAS_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, bias_cfg2, GTHE3_COM_BIAS_CFG2_ADDR, GTHE3_COM_BIAS_CFG2_MASK, GTHE3_COM_BIAS_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gthe3, bias_cfg3, GTHE3_COM_BIAS_CFG3_ADDR, GTHE3_COM_BIAS_CFG3_MASK, GTHE3_COM_BIAS_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, bias_cfg_rsvd, GTHE3_COM_BIAS_CFG_RSVD_ADDR, GTHE3_COM_BIAS_CFG_RSVD_MASK, GTHE3_COM_BIAS_CFG_RSVD_LSB); +def_gt_pll_masked_reg_rw16(gthe3, bias_cfg4, GTHE3_COM_BIAS_CFG4_ADDR, GTHE3_COM_BIAS_CFG4_MASK, GTHE3_COM_BIAS_CFG4_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_cfg0, GTHE3_COM_QPLL1_CFG0_ADDR, GTHE3_COM_QPLL1_CFG0_MASK, GTHE3_COM_QPLL1_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, common_cfg1, GTHE3_COM_COMMON_CFG1_ADDR, GTHE3_COM_COMMON_CFG1_MASK, GTHE3_COM_COMMON_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, por_cfg, GTHE3_COM_POR_CFG_ADDR, GTHE3_COM_POR_CFG_MASK, GTHE3_COM_POR_CFG_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_cfg1, GTHE3_COM_QPLL1_CFG1_ADDR, GTHE3_COM_QPLL1_CFG1_MASK, GTHE3_COM_QPLL1_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_cfg2, GTHE3_COM_QPLL1_CFG2_ADDR, GTHE3_COM_QPLL1_CFG2_MASK, GTHE3_COM_QPLL1_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_lock_cfg, GTHE3_COM_QPLL1_LOCK_CFG_ADDR, GTHE3_COM_QPLL1_LOCK_CFG_MASK, GTHE3_COM_QPLL1_LOCK_CFG_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_init_cfg0, GTHE3_COM_QPLL1_INIT_CFG0_ADDR, GTHE3_COM_QPLL1_INIT_CFG0_MASK, GTHE3_COM_QPLL1_INIT_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_init_cfg1, GTHE3_COM_QPLL1_INIT_CFG1_ADDR, GTHE3_COM_QPLL1_INIT_CFG1_MASK, GTHE3_COM_QPLL1_INIT_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_fbdiv, GTHE3_COM_QPLL1_FBDIV_ADDR, GTHE3_COM_QPLL1_FBDIV_MASK, GTHE3_COM_QPLL1_FBDIV_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_cfg3, GTHE3_COM_QPLL1_CFG3_ADDR, GTHE3_COM_QPLL1_CFG3_MASK, GTHE3_COM_QPLL1_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_cp, GTHE3_COM_QPLL1_CP_ADDR, GTHE3_COM_QPLL1_CP_MASK, GTHE3_COM_QPLL1_CP_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sarc_sel, GTHE3_COM_SARC_SEL_ADDR, GTHE3_COM_SARC_SEL_MASK, GTHE3_COM_SARC_SEL_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sarc_en, GTHE3_COM_SARC_EN_ADDR, GTHE3_COM_SARC_EN_MASK, GTHE3_COM_SARC_EN_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_refclk_div, GTHE3_COM_QPLL1_REFCLK_DIV_ADDR, GTHE3_COM_QPLL1_REFCLK_DIV_MASK, GTHE3_COM_QPLL1_REFCLK_DIV_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_lpf, GTHE3_COM_QPLL1_LPF_ADDR, GTHE3_COM_QPLL1_LPF_MASK, GTHE3_COM_QPLL1_LPF_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_cfg1_g3, GTHE3_COM_QPLL1_CFG1_G3_ADDR, GTHE3_COM_QPLL1_CFG1_G3_MASK, GTHE3_COM_QPLL1_CFG1_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_cfg2_g3, GTHE3_COM_QPLL1_CFG2_G3_ADDR, GTHE3_COM_QPLL1_CFG2_G3_MASK, GTHE3_COM_QPLL1_CFG2_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_lpf_g3, GTHE3_COM_QPLL1_LPF_G3_ADDR, GTHE3_COM_QPLL1_LPF_G3_MASK, GTHE3_COM_QPLL1_LPF_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_lock_cfg_g3, GTHE3_COM_QPLL1_LOCK_CFG_G3_ADDR, GTHE3_COM_QPLL1_LOCK_CFG_G3_MASK, GTHE3_COM_QPLL1_LOCK_CFG_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, rsvd_attr2, GTHE3_COM_RSVD_ATTR2_ADDR, GTHE3_COM_RSVD_ATTR2_MASK, GTHE3_COM_RSVD_ATTR2_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_fbdiv_g3, GTHE3_COM_QPLL1_FBDIV_G3_ADDR, GTHE3_COM_QPLL1_FBDIV_G3_MASK, GTHE3_COM_QPLL1_FBDIV_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, rxrecclkout1_sel, GTHE3_COM_RXRECCLKOUT1_SEL_ADDR, GTHE3_COM_RXRECCLKOUT1_SEL_MASK, GTHE3_COM_RXRECCLKOUT1_SEL_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_sdm_cfg0, GTHE3_COM_QPLL1_SDM_CFG0_ADDR, GTHE3_COM_QPLL1_SDM_CFG0_MASK, GTHE3_COM_QPLL1_SDM_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_sdm_cfg1, GTHE3_COM_QPLL1_SDM_CFG1_ADDR, GTHE3_COM_QPLL1_SDM_CFG1_MASK, GTHE3_COM_QPLL1_SDM_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm1initseed0_0, GTHE3_COM_SDM1INITSEED0_0_ADDR, GTHE3_COM_SDM1INITSEED0_0_MASK, GTHE3_COM_SDM1INITSEED0_0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm1initseed0_1, GTHE3_COM_SDM1INITSEED0_1_ADDR, GTHE3_COM_SDM1INITSEED0_1_MASK, GTHE3_COM_SDM1INITSEED0_1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_sdm_cfg2, GTHE3_COM_QPLL1_SDM_CFG2_ADDR, GTHE3_COM_QPLL1_SDM_CFG2_MASK, GTHE3_COM_QPLL1_SDM_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_cp_g3, GTHE3_COM_QPLL1_CP_G3_ADDR, GTHE3_COM_QPLL1_CP_G3_MASK, GTHE3_COM_QPLL1_CP_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm1data1_0, GTHE3_COM_SDM1DATA1_0_ADDR, GTHE3_COM_SDM1DATA1_0_MASK, GTHE3_COM_SDM1DATA1_0_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm1_width_pin_sel, GTHE3_COM_SDM1_WIDTH_PIN_SEL_ADDR, GTHE3_COM_SDM1_WIDTH_PIN_SEL_MASK, GTHE3_COM_SDM1_WIDTH_PIN_SEL_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm1_data_pin_sel, GTHE3_COM_SDM1_DATA_PIN_SEL_ADDR, GTHE3_COM_SDM1_DATA_PIN_SEL_MASK, GTHE3_COM_SDM1_DATA_PIN_SEL_LSB); +def_gt_pll_masked_reg_rw16(gthe3, sdm1data1_1, GTHE3_COM_SDM1DATA1_1_ADDR, GTHE3_COM_SDM1DATA1_1_MASK, GTHE3_COM_SDM1DATA1_1_LSB); +def_gt_pll_masked_reg_rw16(gthe3, rsvd_attr3, GTHE3_COM_RSVD_ATTR3_ADDR, GTHE3_COM_RSVD_ATTR3_MASK, GTHE3_COM_RSVD_ATTR3_LSB); +def_gt_pll_masked_reg_rw16(gthe3, qpll1_cfg4, GTHE3_COM_QPLL1_CFG4_ADDR, GTHE3_COM_QPLL1_CFG4_MASK, GTHE3_COM_QPLL1_CFG4_LSB); + +// RX +def_gt_ch_masked_reg_rw16(gthe3, rx_data_width_raw, GTHE3_CH_RX_DATA_WIDTH_ADDR, GTHE3_CH_RX_DATA_WIDTH_MASK, GTHE3_CH_RX_DATA_WIDTH_LSB); +int gthe3_ch_get_rx_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gthe3, rx_int_data_width_raw, GTHE3_CH_RX_INT_DATAWIDTH_ADDR, GTHE3_CH_RX_INT_DATAWIDTH_MASK, GTHE3_CH_RX_INT_DATAWIDTH_LSB); +int gthe3_ch_get_rx_int_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gthe3, es_prescale, GTHE3_CH_ES_PRESCALE_ADDR, GTHE3_CH_ES_PRESCALE_MASK, GTHE3_CH_ES_PRESCALE_LSB); +def_gt_ch_masked_reg_rw16(gthe3, es_eye_scan_en, GTHE3_CH_ES_EYE_SCAN_EN_ADDR, GTHE3_CH_ES_EYE_SCAN_EN_MASK, GTHE3_CH_ES_EYE_SCAN_EN_LSB); +def_gt_ch_masked_reg_rw16(gthe3, es_errdet_en, GTHE3_CH_ES_ERRDET_EN_ADDR, GTHE3_CH_ES_ERRDET_EN_MASK, GTHE3_CH_ES_ERRDET_EN_LSB); +def_gt_ch_masked_reg_rw16(gthe3, es_control, GTHE3_CH_ES_CONTROL_ADDR, GTHE3_CH_ES_CONTROL_MASK, GTHE3_CH_ES_CONTROL_LSB); + +int gthe3_ch_set_es_qual_mask(struct gt_ch *ch, uint8_t *mask); +int gthe3_ch_set_es_qual_mask_clear(struct gt_ch *ch); + +int gthe3_ch_set_es_sdata_mask(struct gt_ch *ch, uint8_t *mask); +int gthe3_ch_set_es_sdata_mask_width(struct gt_ch *ch, int width); + +def_gt_ch_masked_reg_rw16(gthe3, es_horz_offset, GTHE3_CH_ES_HORZ_OFFSET_ADDR, GTHE3_CH_ES_HORZ_OFFSET_MASK, GTHE3_CH_ES_HORZ_OFFSET_LSB); +def_gt_ch_masked_reg_rw16(gthe3, rx_eyescan_vs_range, GTHE3_CH_RX_EYESCAN_VS_RANGE_ADDR, GTHE3_CH_RX_EYESCAN_VS_RANGE_MASK, GTHE3_CH_RX_EYESCAN_VS_RANGE_LSB); +def_gt_ch_masked_reg_rw16(gthe3, rx_eyescan_vs_code, GTHE3_CH_RX_EYESCAN_VS_CODE_ADDR, GTHE3_CH_RX_EYESCAN_VS_CODE_MASK, GTHE3_CH_RX_EYESCAN_VS_CODE_LSB); +def_gt_ch_masked_reg_rw16(gthe3, rx_eyescan_vs_ut_sign, GTHE3_CH_RX_EYESCAN_VS_UT_SIGN_ADDR, GTHE3_CH_RX_EYESCAN_VS_UT_SIGN_MASK, GTHE3_CH_RX_EYESCAN_VS_UT_SIGN_LSB); +def_gt_ch_masked_reg_rw16(gthe3, rx_eyescan_vs_neg_dir, GTHE3_CH_RX_EYESCAN_VS_NEG_DIR_ADDR, GTHE3_CH_RX_EYESCAN_VS_NEG_DIR_MASK, GTHE3_CH_RX_EYESCAN_VS_NEG_DIR_LSB); +def_gt_ch_masked_reg_read16(gthe3, es_error_count, GTHE3_CH_ES_ERROR_COUNT_ADDR, GTHE3_CH_ES_ERROR_COUNT_MASK, GTHE3_CH_ES_ERROR_COUNT_LSB); +def_gt_ch_masked_reg_read16(gthe3, es_sample_count, GTHE3_CH_ES_SAMPLE_COUNT_ADDR, GTHE3_CH_ES_SAMPLE_COUNT_MASK, GTHE3_CH_ES_SAMPLE_COUNT_LSB); +def_gt_ch_masked_reg_read16(gthe3, es_control_status, GTHE3_CH_ES_CONTROL_STATUS_ADDR, GTHE3_CH_ES_CONTROL_STATUS_MASK, GTHE3_CH_ES_CONTROL_STATUS_LSB); + +int gthe3_ch_get_rx_prbs_error_count(struct gt_ch *ch, uint32_t *val); + +// TX +def_gt_ch_masked_reg_rw16(gthe3, tx_data_width_raw, GTHE3_CH_TX_DATA_WIDTH_ADDR, GTHE3_CH_TX_DATA_WIDTH_MASK, GTHE3_CH_TX_DATA_WIDTH_LSB); +int gthe3_ch_get_tx_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gthe3, tx_int_data_width_raw, GTHE3_CH_TX_INT_DATAWIDTH_ADDR, GTHE3_CH_TX_INT_DATAWIDTH_MASK, GTHE3_CH_TX_INT_DATAWIDTH_LSB); +int gthe3_ch_get_tx_int_data_width(struct gt_ch *ch, uint32_t *val); + +extern const struct gt_quad_ops gthe3_gt_quad_ops; + +#endif /* XCVR_GTHE3_H */ diff --git a/utils/xcvr_gthe4.c b/utils/xcvr_gthe4.c new file mode 100644 index 0000000..7f17041 --- /dev/null +++ b/utils/xcvr_gthe4.c @@ -0,0 +1,644 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#include +#include +#include "xcvr_gthe4.h" + +// signals +int gthe4_pll_qpll0_reset(struct gt_pll *pll) +{ + int ret = 0; + + ret = gthe4_pll_set_qpll0_reset(pll, 1); + + if (ret) + return ret; + + return gthe4_pll_set_qpll0_reset(pll, 0); +} + +int gthe4_pll_qpll1_reset(struct gt_pll *pll) +{ + int ret = 0; + + ret = gthe4_pll_set_qpll1_reset(pll, 1); + + if (ret) + return ret; + + return gthe4_pll_set_qpll1_reset(pll, 0); +} + +int gthe4_ch_tx_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe4_ch_set_tx_reset(ch, 1); + + if (ret) + return ret; + + return gthe4_ch_set_tx_reset(ch, 0); +} + +int gthe4_ch_tx_pma_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe4_ch_set_tx_pma_reset(ch, 1); + + if (ret) + return ret; + + return gthe4_ch_set_tx_pma_reset(ch, 0); +} + +int gthe4_ch_tx_pcs_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe4_ch_set_tx_pcs_reset(ch, 1); + + if (ret) + return ret; + + return gthe4_ch_set_tx_pcs_reset(ch, 0); +} + +int gthe4_ch_rx_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe4_ch_set_rx_reset(ch, 1); + + if (ret) + return ret; + + return gthe4_ch_set_rx_reset(ch, 0); +} + +int gthe4_ch_rx_pma_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe4_ch_set_rx_pma_reset(ch, 1); + + if (ret) + return ret; + + return gthe4_ch_set_rx_pma_reset(ch, 0); +} + +int gthe4_ch_rx_pcs_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe4_ch_set_rx_pcs_reset(ch, 1); + + if (ret) + return ret; + + return gthe4_ch_set_rx_pcs_reset(ch, 0); +} + +int gthe4_ch_rx_dfe_lpm_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe4_ch_set_rx_dfe_lpm_reset(ch, 1); + + if (ret) + return ret; + + return gthe4_ch_set_rx_dfe_lpm_reset(ch, 0); +} + +int gthe4_ch_eyescan_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gthe4_ch_set_eyescan_reset(ch, 1); + + if (ret) + return ret; + + return gthe4_ch_set_eyescan_reset(ch, 0); +} + +// RX +int gthe4_ch_get_rx_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw; + + ret = gthe4_ch_get_rx_data_width_raw(ch, &dw); + if (ret) + return ret; + + *val = (8*(1 << (dw >> 1)) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gthe4_ch_get_rx_int_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw, idw; + + ret = gthe4_ch_get_rx_data_width_raw(ch, &dw); + if (ret) + return ret; + + ret = gthe4_ch_get_rx_int_data_width_raw(ch, &idw); + if (ret) + return ret; + + *val = (16*(1 << idw) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gthe4_ch_set_es_qual_mask(struct gt_ch *ch, uint8_t *mask) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTHE4_CH_ES_QUAL_MASK0_ADDR+k, mask[2*k+0] | (mask[2*k+1] << 8)); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTHE4_CH_ES_QUAL_MASK5_ADDR+k, mask[2*k+10] | (mask[2*k+11] << 8)); + if (ret) + return ret; + } + + return 0; +} + +int gthe4_ch_set_es_qual_mask_clear(struct gt_ch *ch) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTHE4_CH_ES_QUAL_MASK0_ADDR+k, 0xffff); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTHE4_CH_ES_QUAL_MASK5_ADDR+k, 0xffff); + if (ret) + return ret; + } + + return 0; +} + +int gthe4_ch_set_es_sdata_mask(struct gt_ch *ch, uint8_t *mask) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTHE4_CH_ES_SDATA_MASK0_ADDR+k, mask[2*k+0] | (mask[2*k+1] << 8)); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTHE4_CH_ES_SDATA_MASK5_ADDR+k, mask[2*k+10] | (mask[2*k+11] << 8)); + if (ret) + return ret; + } + + return 0; +} + +int gthe4_ch_set_es_sdata_mask_width(struct gt_ch *ch, int width) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + int shift = width - (80 - ((k+1)*16)); + uint32_t mask = 0xffff; + + if (shift < 0) + { + mask = 0xffff; + } + else if (shift > 16) + { + mask = 0x0000; + } + else + { + mask = 0xffff >> shift; + } + + ret = gt_ch_reg_write(ch, GTHE4_CH_ES_SDATA_MASK0_ADDR+k, mask); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTHE4_CH_ES_SDATA_MASK5_ADDR+k, 0xffff); + if (ret) + return ret; + } + + return 0; +} + +int gthe4_ch_get_rx_prbs_error_count(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t v1, v2; + + ret = gt_ch_reg_read(ch, GTHE4_CH_RX_PRBS_ERR_CNT_L_ADDR | (ch->index << 17), &v1); + if (ret) + return ret; + + ret = gt_ch_reg_read(ch, GTHE4_CH_RX_PRBS_ERR_CNT_H_ADDR | (ch->index << 17), &v2); + if (ret) + return ret; + + *val = v1 | (v2 << 16); + return 0; +} + +// TX +int gthe4_ch_get_tx_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw; + + ret = gthe4_ch_get_tx_data_width_raw(ch, &dw); + if (ret) + return ret; + + *val = (8*(1 << (dw >> 1)) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gthe4_ch_get_tx_int_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw, idw; + + ret = gthe4_ch_get_tx_data_width_raw(ch, &dw); + if (ret) + return ret; + + ret = gthe4_ch_get_tx_int_data_width_raw(ch, &idw); + if (ret) + return ret; + + *val = (16*(1 << idw) * (4 + (dw & 1))) >> 2; + return 0; +} + +struct gthe4_ch_priv { + uint32_t tx_data_width; + uint32_t tx_int_data_width; + uint32_t rx_data_width; + uint32_t rx_int_data_width; + int dfe_en; + + int prescale; + int h_start; + int h_stop; + int h_step; + int v_range; + int v_start; + int v_stop; + int v_step; + + int h_offset; + int v_offset; + int ut_sign; + int eyescan_running; +}; + +static const struct gt_reg_val gthe4_ch_preset_10g_dfe_regs[] = { + {GTHE4_CH_RX_SUM_IREF_TUNE_ADDR, GTHE4_CH_RX_SUM_IREF_TUNE_MASK, GTHE4_CH_RX_SUM_IREF_TUNE_LSB, 0x0009}, + {GTHE4_CH_RX_SUM_VCMTUNE_ADDR, GTHE4_CH_RX_SUM_VCMTUNE_MASK, GTHE4_CH_RX_SUM_VCMTUNE_LSB, 0x000A}, + {0, 0, 0, 0} +}; + +static const struct gt_reg_val gthe4_ch_preset_10g_lpm_regs[] = { + {GTHE4_CH_RX_SUM_IREF_TUNE_ADDR, GTHE4_CH_RX_SUM_IREF_TUNE_MASK, GTHE4_CH_RX_SUM_IREF_TUNE_LSB, 0x0004}, + {GTHE4_CH_RX_SUM_VCMTUNE_ADDR, GTHE4_CH_RX_SUM_VCMTUNE_MASK, GTHE4_CH_RX_SUM_VCMTUNE_LSB, 0x0006}, + {0, 0, 0, 0} +}; + +static const uint32_t gthe4_ch_presets[] = { + GT_PRESET_10G_DFE, + GT_PRESET_10G_LPM, + 0 +}; + +static int gthe4_ch_get_available_presets(struct gt_ch *ch, const uint32_t **presets) +{ + *presets = gthe4_ch_presets; + return 0; +} + +int gthe4_ch_load_preset(struct gt_ch *ch, uint32_t preset) +{ + if (preset == GT_PRESET_10G_DFE || preset == GT_PRESET_10G_LPM) + { + gthe4_ch_set_tx_reset(ch, 1); + gthe4_ch_set_rx_reset(ch, 1); + + if (preset == GT_PRESET_10G_DFE) + { + gt_ch_reg_write_multiple(ch, gthe4_ch_preset_10g_dfe_regs); + gthe4_ch_set_rx_lpm_en(ch, 0); + } + else + { + gt_ch_reg_write_multiple(ch, gthe4_ch_preset_10g_lpm_regs); + gthe4_ch_set_rx_lpm_en(ch, 1); + } + + gthe4_ch_set_tx_reset(ch, 0); + gthe4_ch_set_rx_reset(ch, 0); + + return 0; + } + + return -1; +} + +static int gthe4_ch_eyescan_start(struct gt_ch *ch, struct gt_eyescan_params *params) +{ + struct gthe4_ch_priv *priv = ch->priv; + uint32_t val; + + uint32_t error_count; + uint32_t sample_count; + uint64_t bit_count; + float ber; + + priv->eyescan_running = 0; + + gthe4_ch_get_rx_lpm_en(ch, &val); + priv->dfe_en = !val; + + gthe4_ch_get_rx_data_width(ch, &priv->rx_data_width); + gthe4_ch_get_rx_int_data_width(ch, &priv->rx_int_data_width); + + priv->prescale = 0; + + for (priv->prescale = 0; priv->prescale < 32; priv->prescale++) + { + if (((uint64_t)0xffff * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale) >= params->target_bit_count) + break; + } + + params->target_bit_count = ((uint64_t)0xffff * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale); + params->h_range = 0; + + priv->h_start = params->h_start; + priv->h_stop = params->h_stop; + priv->h_step = params->h_step; + priv->v_range = params->v_range; + priv->v_start = params->v_start; + priv->v_stop = params->v_stop; + priv->v_step = params->v_step; + + gthe4_ch_set_es_control(ch, 0x00); + + gthe4_ch_set_es_prescale(ch, 4); + gthe4_ch_set_es_errdet_en(ch, 1); + + gthe4_ch_set_es_qual_mask_clear(ch); + gthe4_ch_set_es_sdata_mask_width(ch, priv->rx_int_data_width); + + gthe4_ch_set_rx_eyescan_vs_range(ch, priv->v_range); + + gthe4_ch_set_es_horz_offset(ch, 0x000); + gthe4_ch_set_rx_eyescan_vs_neg_dir(ch, 0); + gthe4_ch_set_rx_eyescan_vs_code(ch, 0); + gthe4_ch_set_rx_eyescan_vs_ut_sign(ch, 0); + + gthe4_ch_set_es_eye_scan_en(ch, 1); + + gthe4_ch_rx_pma_reset(ch); + + for (int ber_tries = 0; ber_tries < 10; ber_tries++) + { + for (int reset_tries = 0; reset_tries < 30; reset_tries++) + { + gthe4_ch_get_rx_reset_done(ch, &val); + if (val) + break; + usleep(100000); + } + + if (!val) + { + fprintf(stderr, "Error: channel stuck in reset\n"); + return -1; + } + + usleep(100000); + + // check for lock + gthe4_ch_set_es_control(ch, 0x01); + + for (int wait_tries = 0; wait_tries < 30; wait_tries++) + { + gthe4_ch_get_es_control_status(ch, &val); + if (val & 1) + break; + usleep(100000); + } + + if (!(val & 1)) + { + fprintf(stderr, "Error: eye scan did not finish (%d)\n", val); + return -1; + } + + gthe4_ch_set_es_control(ch, 0x00); + + gthe4_ch_get_es_error_count(ch, &error_count); + gthe4_ch_get_es_sample_count(ch, &sample_count); + bit_count = ((uint64_t)sample_count * (uint64_t)priv->rx_int_data_width) << (1+4); + + ber = (float)error_count / (float)bit_count; + + if (ber < 0.01) + break; + + printf("High BER (%02f), resetting eye scan logic\n", ber); + + gthe4_ch_set_es_horz_offset(ch, 0x880); + gthe4_ch_set_eyescan_reset(ch, 1); + gthe4_ch_set_es_horz_offset(ch, 0x800); + gthe4_ch_set_eyescan_reset(ch, 0); + } + + if (ber > 0.01) + { + fprintf(stderr, "Error: High BER, alignment failed\n"); + return -1; + } + + // set up for measurement + priv->h_offset = priv->h_start; + priv->v_offset = priv->v_start; + priv->ut_sign = 0; + + gthe4_ch_set_es_control(ch, 0x00); + gthe4_ch_set_es_prescale(ch, priv->prescale); + gthe4_ch_set_es_errdet_en(ch, 1); + gthe4_ch_set_es_horz_offset(ch, (priv->h_offset & 0x7ff) | (priv->h_offset < 0 ? 0x800 : 0x000)); + gthe4_ch_set_rx_eyescan_vs_neg_dir(ch, (priv->v_offset < 0)); + gthe4_ch_set_rx_eyescan_vs_code(ch, priv->v_offset < 0 ? -priv->v_offset : priv->v_offset); + gthe4_ch_set_rx_eyescan_vs_ut_sign(ch, priv->ut_sign); + + // start measurement + gthe4_ch_set_es_control(ch, 0x01); + + priv->eyescan_running = 1; + + return 0; +} + +static int gthe4_ch_eyescan_step(struct gt_ch *ch, struct gt_eyescan_point *point) +{ + struct gthe4_ch_priv *priv = ch->priv; + uint32_t val; + + uint32_t error_count; + uint32_t sample_count; + uint64_t bit_count; + + int restart = 0; + + if (!priv->eyescan_running) + return 0; + + gthe4_ch_get_es_control_status(ch, &val); + if (!(val & 1)) + return 2; + + gthe4_ch_set_es_control(ch, 0x00); + + gthe4_ch_get_es_error_count(ch, &error_count); + gthe4_ch_get_es_sample_count(ch, &sample_count); + bit_count = ((uint64_t)sample_count * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale); + + point->error_count = error_count; + point->bit_count = bit_count; + point->x = priv->h_offset; + point->y = priv->v_offset; + point->ut_sign = priv->ut_sign; + + restart = 0; + + if (!priv->ut_sign && priv->dfe_en) + { + priv->ut_sign = 1; + restart = 1; + } + else + { + priv->ut_sign = 0; + } + + gthe4_ch_set_rx_eyescan_vs_ut_sign(ch, priv->ut_sign); + + if (restart) + { + gthe4_ch_set_es_control(ch, 0x01); + return 1; + } + + if (priv->v_offset < priv->v_stop) + { + priv->v_offset += priv->v_step; + restart = 1; + } + else + { + priv->v_offset = priv->v_start; + } + + gthe4_ch_set_rx_eyescan_vs_neg_dir(ch, (priv->v_offset < 0)); + gthe4_ch_set_rx_eyescan_vs_code(ch, priv->v_offset < 0 ? -priv->v_offset : priv->v_offset); + + if (restart) + { + gthe4_ch_set_es_control(ch, 0x01); + return 1; + } + + if (priv->h_offset < priv->h_stop) + { + priv->h_offset += priv->h_step; + restart = 1; + } + else + { + // done + priv->eyescan_running = 0; + return 1; + } + + gthe4_ch_set_es_horz_offset(ch, (priv->h_offset & 0x7ff) | (priv->h_offset < 0 ? 0x800 : 0x000)); + + if (restart) + { + gthe4_ch_set_es_control(ch, 0x01); + return 1; + } + + priv->eyescan_running = 0; + return 0; +} + +const struct gt_ch_ops gthe4_gt_ch_ops = { + .get_tx_reset = gthe4_ch_get_tx_reset, + .set_tx_reset = gthe4_ch_set_tx_reset, + .tx_reset = gthe4_ch_tx_reset, + .get_rx_reset = gthe4_ch_get_rx_reset, + .set_rx_reset = gthe4_ch_set_rx_reset, + .rx_reset = gthe4_ch_rx_reset, + .get_tx_data_width = gthe4_ch_get_tx_data_width, + .get_tx_int_data_width = gthe4_ch_get_tx_int_data_width, + .get_rx_data_width = gthe4_ch_get_rx_data_width, + .get_rx_int_data_width = gthe4_ch_get_rx_int_data_width, + .get_available_presets = gthe4_ch_get_available_presets, + .load_preset = gthe4_ch_load_preset, + .eyescan_start = gthe4_ch_eyescan_start, + .eyescan_step = gthe4_ch_eyescan_step +}; + +static int gthe4_ch_init(struct gt_ch *ch) +{ + struct gthe4_ch_priv *priv = calloc(1, sizeof(struct gthe4_ch_priv)); + if (!priv) + return -1; + + ch->priv = priv; + + return 0; +} + +int gthe4_quad_init(struct gt_quad *quad) +{ + quad->type = "GTHE4"; + + for (int n = 0; n < quad->ch_count; n++) + { + quad->ch[n].quad = quad; + quad->ch[n].pll = &quad->pll; + quad->ch[n].ops = >he4_gt_ch_ops; + quad->ch[n].index = n; + + gthe4_ch_init(&quad->ch[n]); + } + + return 0; +} + +const struct gt_quad_ops gthe4_gt_quad_ops = { + .init = gthe4_quad_init +}; diff --git a/utils/xcvr_gthe4.h b/utils/xcvr_gthe4.h new file mode 100644 index 0000000..89da27d --- /dev/null +++ b/utils/xcvr_gthe4.h @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#ifndef XCVR_GTHE4_H +#define XCVR_GTHE4_H + +#include "xcvr_gt.h" +#include "gt/gthe4_regs.h" + +// signals +#define GTHE4_COM_QPLL0_RESET_ADDR 0x10000 +#define GTHE4_COM_QPLL0_RESET_MSB 0 +#define GTHE4_COM_QPLL0_RESET_LSB 0 +#define GTHE4_COM_QPLL0_RESET_MASK BIT_MASK(GTHE4_COM_QPLL0_RESET_MSB, GTHE4_COM_QPLL0_RESET_LSB) +#define GTHE4_COM_QPLL0_LOCK_ADDR 0x10000 +#define GTHE4_COM_QPLL0_LOCK_MSB 8 +#define GTHE4_COM_QPLL0_LOCK_LSB 8 +#define GTHE4_COM_QPLL0_LOCK_MASK BIT_MASK(GTHE4_COM_QPLL0_LOCK_MSB, GTHE4_COM_QPLL0_LOCK_LSB) +#define GTHE4_COM_QPLL0_PD_ADDR 0x10001 +#define GTHE4_COM_QPLL0_PD_MSB 0 +#define GTHE4_COM_QPLL0_PD_LSB 0 +#define GTHE4_COM_QPLL0_PD_MASK BIT_MASK(GTHE4_COM_QPLL0_PD_MSB, GTHE4_COM_QPLL0_PD_LSB) +#define GTHE4_COM_QPLL1_RESET_ADDR 0x11000 +#define GTHE4_COM_QPLL1_RESET_MSB 0 +#define GTHE4_COM_QPLL1_RESET_LSB 0 +#define GTHE4_COM_QPLL1_RESET_MASK BIT_MASK(GTHE4_COM_QPLL0_RESET_MSB, GTHE4_COM_QPLL0_RESET_LSB) +#define GTHE4_COM_QPLL1_LOCK_ADDR 0x11000 +#define GTHE4_COM_QPLL1_LOCK_MSB 8 +#define GTHE4_COM_QPLL1_LOCK_LSB 8 +#define GTHE4_COM_QPLL1_LOCK_MASK BIT_MASK(GTHE4_COM_QPLL0_LOCK_MSB, GTHE4_COM_QPLL0_LOCK_LSB) +#define GTHE4_COM_QPLL1_PD_ADDR 0x11001 +#define GTHE4_COM_QPLL1_PD_MSB 0 +#define GTHE4_COM_QPLL1_PD_LSB 0 +#define GTHE4_COM_QPLL1_PD_MASK BIT_MASK(GTHE4_COM_QPLL1_PD_MSB, GTHE4_COM_QPLL1_PD_LSB) + +#define GTHE4_CH_TX_RESET_ADDR 0x10000 +#define GTHE4_CH_TX_RESET_MSB 0 +#define GTHE4_CH_TX_RESET_LSB 0 +#define GTHE4_CH_TX_RESET_MASK BIT_MASK(GTHE4_CH_TX_RESET_MSB, GTHE4_CH_TX_RESET_LSB) +#define GTHE4_CH_TX_PMA_RESET_ADDR 0x10000 +#define GTHE4_CH_TX_PMA_RESET_MSB 1 +#define GTHE4_CH_TX_PMA_RESET_LSB 1 +#define GTHE4_CH_TX_PMA_RESET_MASK BIT_MASK(GTHE4_CH_TX_PMA_RESET_MSB, GTHE4_CH_TX_PMA_RESET_LSB) +#define GTHE4_CH_TX_PCS_RESET_ADDR 0x10000 +#define GTHE4_CH_TX_PCS_RESET_MSB 2 +#define GTHE4_CH_TX_PCS_RESET_LSB 2 +#define GTHE4_CH_TX_PCS_RESET_MASK BIT_MASK(GTHE4_CH_TX_PCS_RESET_MSB, GTHE4_CH_TX_PCS_RESET_LSB) +#define GTHE4_CH_TX_RESET_DONE_ADDR 0x10000 +#define GTHE4_CH_TX_RESET_DONE_MSB 8 +#define GTHE4_CH_TX_RESET_DONE_LSB 8 +#define GTHE4_CH_TX_RESET_DONE_MASK BIT_MASK(GTHE4_CH_TX_RESET_DONE_MSB, GTHE4_CH_TX_RESET_DONE_LSB) +#define GTHE4_CH_TX_GT_RESET_DONE_ADDR 0x10000 +#define GTHE4_CH_TX_GT_RESET_DONE_MSB 9 +#define GTHE4_CH_TX_GT_RESET_DONE_LSB 9 +#define GTHE4_CH_TX_GT_RESET_DONE_MASK BIT_MASK(GTHE4_CH_TX_GT_RESET_DONE_MSB, GTHE4_CH_TX_GT_RESET_DONE_LSB) +#define GTHE4_CH_TX_PMA_RESET_DONE_ADDR 0x10000 +#define GTHE4_CH_TX_PMA_RESET_DONE_MSB 10 +#define GTHE4_CH_TX_PMA_RESET_DONE_LSB 10 +#define GTHE4_CH_TX_PMA_RESET_DONE_MASK BIT_MASK(GTHE4_CH_TX_PMA_RESET_DONE_MSB, GTHE4_CH_TX_PMA_RESET_DONE_LSB) +#define GTHE4_CH_TX_PRGDIV_RESET_DONE_ADDR 0x10000 +#define GTHE4_CH_TX_PRGDIV_RESET_DONE_MSB 11 +#define GTHE4_CH_TX_PRGDIV_RESET_DONE_LSB 11 +#define GTHE4_CH_TX_PRGDIV_RESET_DONE_MASK BIT_MASK(GTHE4_CH_TX_PRGDIV_RESET_DONE_MSB, GTHE4_CH_TX_PRGDIV_RESET_DONE_LSB) +#define GTHE4_CH_TX_USRCLK_ACT_ADDR 0x10000 +#define GTHE4_CH_TX_USRCLK_ACT_MSB 12 +#define GTHE4_CH_TX_USRCLK_ACT_LSB 12 +#define GTHE4_CH_TX_USRCLK_ACT_MASK BIT_MASK(GTHE4_CH_TX_USRCLK_ACT_MSB, GTHE4_CH_TX_USRCLK_ACT_LSB) +#define GTHE4_CH_TX_PD_ADDR 0x10001 +#define GTHE4_CH_TX_PD_MSB 0 +#define GTHE4_CH_TX_PD_LSB 0 +#define GTHE4_CH_TX_PD_MASK BIT_MASK(GTHE4_CH_TX_PD_MSB, GTHE4_CH_TX_PD_LSB) +#define GTHE4_CH_TX_QPLL_SEL_ADDR 0x10001 +#define GTHE4_CH_TX_QPLL_SEL_MSB 1 +#define GTHE4_CH_TX_QPLL_SEL_LSB 1 +#define GTHE4_CH_TX_QPLL_SEL_MASK BIT_MASK(GTHE4_CH_TX_QPLL_SEL_MSB, GTHE4_CH_TX_QPLL_SEL_LSB) +#define GTHE4_CH_TX_POLARITY_ADDR 0x10010 +#define GTHE4_CH_TX_POLARITY_MSB 0 +#define GTHE4_CH_TX_POLARITY_LSB 0 +#define GTHE4_CH_TX_POLARITY_MASK BIT_MASK(GTHE4_CH_TX_POLARITY_MSB, GTHE4_CH_TX_POLARITY_LSB) +#define GTHE4_CH_TX_ELECIDLE_ADDR 0x10010 +#define GTHE4_CH_TX_ELECIDLE_MSB 1 +#define GTHE4_CH_TX_ELECIDLE_LSB 1 +#define GTHE4_CH_TX_ELECIDLE_MASK BIT_MASK(GTHE4_CH_TX_ELECIDLE_MSB, GTHE4_CH_TX_ELECIDLE_LSB) +#define GTHE4_CH_TX_INHIBIT_ADDR 0x10010 +#define GTHE4_CH_TX_INHIBIT_MSB 2 +#define GTHE4_CH_TX_INHIBIT_LSB 2 +#define GTHE4_CH_TX_INHIBIT_MASK BIT_MASK(GTHE4_CH_TX_INHIBIT_MSB, GTHE4_CH_TX_INHIBIT_LSB) +#define GTHE4_CH_TX_DIFFCTRL_ADDR 0x10011 +#define GTHE4_CH_TX_DIFFCTRL_MSB 4 +#define GTHE4_CH_TX_DIFFCTRL_LSB 0 +#define GTHE4_CH_TX_DIFFCTRL_MASK BIT_MASK(GTHE4_CH_TX_DIFFCTRL_MSB, GTHE4_CH_TX_DIFFCTRL_LSB) +#define GTHE4_CH_TX_MAINCURSOR_ADDR 0x10012 +#define GTHE4_CH_TX_MAINCURSOR_MSB 6 +#define GTHE4_CH_TX_MAINCURSOR_LSB 0 +#define GTHE4_CH_TX_MAINCURSOR_MASK BIT_MASK(GTHE4_CH_TX_MAINCURSOR_MSB, GTHE4_CH_TX_MAINCURSOR_LSB) +#define GTHE4_CH_TX_PRECURSOR_ADDR 0x10013 +#define GTHE4_CH_TX_PRECURSOR_MSB 4 +#define GTHE4_CH_TX_PRECURSOR_LSB 0 +#define GTHE4_CH_TX_PRECURSOR_MASK BIT_MASK(GTHE4_CH_TX_PRECURSOR_MSB, GTHE4_CH_TX_PRECURSOR_LSB) +#define GTHE4_CH_TX_POSTCURSOR_ADDR 0x10014 +#define GTHE4_CH_TX_POSTCURSOR_MSB 4 +#define GTHE4_CH_TX_POSTCURSOR_LSB 0 +#define GTHE4_CH_TX_POSTCURSOR_MASK BIT_MASK(GTHE4_CH_TX_POSTCURSOR_MSB, GTHE4_CH_TX_POSTCURSOR_LSB) +#define GTHE4_CH_TX_PRBS_SEL_ADDR 0x10040 +#define GTHE4_CH_TX_PRBS_SEL_MSB 3 +#define GTHE4_CH_TX_PRBS_SEL_LSB 0 +#define GTHE4_CH_TX_PRBS_SEL_MASK BIT_MASK(GTHE4_CH_TX_PRBS_SEL_MSB, GTHE4_CH_TX_PRBS_SEL_LSB) +#define GTHE4_CH_TX_PRBS_FORCERR_ADDR 0x10040 +#define GTHE4_CH_TX_PRBS_FORCERR_MSB 15 +#define GTHE4_CH_TX_PRBS_FORCERR_LSB 0 +#define GTHE4_CH_TX_PRBS_FORCERR_MASK BIT_MASK(GTHE4_CH_TX_PRBS_FORCERR_MSB, GTHE4_CH_TX_PRBS_FORCERR_LSB) +#define GTHE4_CH_RX_RESET_ADDR 0x11000 +#define GTHE4_CH_RX_RESET_MSB 0 +#define GTHE4_CH_RX_RESET_LSB 0 +#define GTHE4_CH_RX_RESET_MASK BIT_MASK(GTHE4_CH_RX_RESET_MSB, GTHE4_CH_RX_RESET_LSB) +#define GTHE4_CH_RX_PMA_RESET_ADDR 0x11000 +#define GTHE4_CH_RX_PMA_RESET_MSB 1 +#define GTHE4_CH_RX_PMA_RESET_LSB 1 +#define GTHE4_CH_RX_PMA_RESET_MASK BIT_MASK(GTHE4_CH_RX_PMA_RESET_MSB, GTHE4_CH_RX_PMA_RESET_LSB) +#define GTHE4_CH_RX_PCS_RESET_ADDR 0x11000 +#define GTHE4_CH_RX_PCS_RESET_MSB 2 +#define GTHE4_CH_RX_PCS_RESET_LSB 2 +#define GTHE4_CH_RX_PCS_RESET_MASK BIT_MASK(GTHE4_CH_RX_PCS_RESET_MSB, GTHE4_CH_RX_PCS_RESET_LSB) +#define GTHE4_CH_RX_DFE_LPM_RESET_ADDR 0x11000 +#define GTHE4_CH_RX_DFE_LPM_RESET_MSB 3 +#define GTHE4_CH_RX_DFE_LPM_RESET_LSB 3 +#define GTHE4_CH_RX_DFE_LPM_RESET_MASK BIT_MASK(GTHE4_CH_RX_DFE_LPM_RESET_MSB, GTHE4_CH_RX_DFE_LPM_RESET_LSB) +#define GTHE4_CH_EYESCAN_RESET_ADDR 0x11000 +#define GTHE4_CH_EYESCAN_RESET_MSB 4 +#define GTHE4_CH_EYESCAN_RESET_LSB 4 +#define GTHE4_CH_EYESCAN_RESET_MASK BIT_MASK(GTHE4_CH_EYESCAN_RESET_MSB, GTHE4_CH_EYESCAN_RESET_LSB) +#define GTHE4_CH_RX_RESET_DONE_ADDR 0x11000 +#define GTHE4_CH_RX_RESET_DONE_MSB 8 +#define GTHE4_CH_RX_RESET_DONE_LSB 8 +#define GTHE4_CH_RX_RESET_DONE_MASK BIT_MASK(GTHE4_CH_RX_RESET_DONE_MSB, GTHE4_CH_RX_RESET_DONE_LSB) +#define GTHE4_CH_RX_GT_RESET_DONE_ADDR 0x11000 +#define GTHE4_CH_RX_GT_RESET_DONE_MSB 9 +#define GTHE4_CH_RX_GT_RESET_DONE_LSB 9 +#define GTHE4_CH_RX_GT_RESET_DONE_MASK BIT_MASK(GTHE4_CH_RX_GT_RESET_DONE_MSB, GTHE4_CH_RX_GT_RESET_DONE_LSB) +#define GTHE4_CH_RX_PMA_RESET_DONE_ADDR 0x11000 +#define GTHE4_CH_RX_PMA_RESET_DONE_MSB 10 +#define GTHE4_CH_RX_PMA_RESET_DONE_LSB 10 +#define GTHE4_CH_RX_PMA_RESET_DONE_MASK BIT_MASK(GTHE4_CH_RX_PMA_RESET_DONE_MSB, GTHE4_CH_RX_PMA_RESET_DONE_LSB) +#define GTHE4_CH_RX_PRGDIV_RESET_DONE_ADDR 0x11000 +#define GTHE4_CH_RX_PRGDIV_RESET_DONE_MSB 11 +#define GTHE4_CH_RX_PRGDIV_RESET_DONE_LSB 11 +#define GTHE4_CH_RX_PRGDIV_RESET_DONE_MASK BIT_MASK(GTHE4_CH_RX_PRGDIV_RESET_DONE_MSB, GTHE4_CH_RX_PRGDIV_RESET_DONE_LSB) +#define GTHE4_CH_RX_USRCLK_ACT_ADDR 0x11000 +#define GTHE4_CH_RX_USRCLK_ACT_MSB 12 +#define GTHE4_CH_RX_USRCLK_ACT_LSB 12 +#define GTHE4_CH_RX_USRCLK_ACT_MASK BIT_MASK(GTHE4_CH_RX_USRCLK_ACT_MSB, GTHE4_CH_RX_USRCLK_ACT_LSB) +#define GTHE4_CH_RX_PD_ADDR 0x11001 +#define GTHE4_CH_RX_PD_MSB 0 +#define GTHE4_CH_RX_PD_LSB 0 +#define GTHE4_CH_RX_PD_MASK BIT_MASK(GTHE4_CH_RX_PD_MSB, GTHE4_CH_RX_PD_LSB) +#define GTHE4_CH_RX_QPLL_SEL_ADDR 0x11001 +#define GTHE4_CH_RX_QPLL_SEL_MSB 1 +#define GTHE4_CH_RX_QPLL_SEL_LSB 1 +#define GTHE4_CH_RX_QPLL_SEL_MASK BIT_MASK(GTHE4_CH_RX_QPLL_SEL_MSB, GTHE4_CH_RX_QPLL_SEL_LSB) +#define GTHE4_CH_LOOPBACK_ADDR 0x11002 +#define GTHE4_CH_LOOPBACK_MSB 2 +#define GTHE4_CH_LOOPBACK_LSB 0 +#define GTHE4_CH_LOOPBACK_MASK BIT_MASK(GTHE4_CH_LOOPBACK_MSB, GTHE4_CH_LOOPBACK_LSB) +#define GTHE4_CH_RX_POLARITY_ADDR 0x11010 +#define GTHE4_CH_RX_POLARITY_MSB 0 +#define GTHE4_CH_RX_POLARITY_LSB 0 +#define GTHE4_CH_RX_POLARITY_MASK BIT_MASK(GTHE4_CH_RX_POLARITY_MSB, GTHE4_CH_RX_POLARITY_LSB) +#define GTHE4_CH_RX_CDR_HOLD_ADDR 0x11020 +#define GTHE4_CH_RX_CDR_HOLD_MSB 0 +#define GTHE4_CH_RX_CDR_HOLD_LSB 0 +#define GTHE4_CH_RX_CDR_HOLD_MASK BIT_MASK(GTHE4_CH_RX_CDR_HOLD_MSB, GTHE4_CH_RX_CDR_HOLD_LSB) +#define GTHE4_CH_RX_CDR_LOCK_ADDR 0x11020 +#define GTHE4_CH_RX_CDR_LOCK_MSB 8 +#define GTHE4_CH_RX_CDR_LOCK_LSB 8 +#define GTHE4_CH_RX_CDR_LOCK_MASK BIT_MASK(GTHE4_CH_RX_CDR_LOCK_MSB, GTHE4_CH_RX_CDR_LOCK_LSB) +#define GTHE4_CH_RX_LPM_EN_ADDR 0x11024 +#define GTHE4_CH_RX_LPM_EN_MSB 0 +#define GTHE4_CH_RX_LPM_EN_LSB 0 +#define GTHE4_CH_RX_LPM_EN_MASK BIT_MASK(GTHE4_CH_RX_LPM_EN_MSB, GTHE4_CH_RX_LPM_EN_LSB) +#define GTHE4_CH_RX_DMONITOR_ADDR 0x11028 +#define GTHE4_CH_RX_DMONITOR_MSB 7 +#define GTHE4_CH_RX_DMONITOR_LSB 0 +#define GTHE4_CH_RX_DMONITOR_MASK BIT_MASK(GTHE4_CH_RX_DMONITOR_MSB, GTHE4_CH_RX_DMONITOR_LSB) +#define GTHE4_CH_RX_PRBS_SEL_ADDR 0x11040 +#define GTHE4_CH_RX_PRBS_SEL_MSB 3 +#define GTHE4_CH_RX_PRBS_SEL_LSB 0 +#define GTHE4_CH_RX_PRBS_SEL_MASK BIT_MASK(GTHE4_CH_RX_PRBS_SEL_MSB, GTHE4_CH_RX_PRBS_SEL_LSB) +#define GTHE4_CH_RX_PRBS_CNT_RESET_ADDR 0x11041 +#define GTHE4_CH_RX_PRBS_CNT_RESET_MSB 0 +#define GTHE4_CH_RX_PRBS_CNT_RESET_LSB 0 +#define GTHE4_CH_RX_PRBS_CNT_RESET_MASK BIT_MASK(GTHE4_CH_RX_PRBS_CNT_RESET_MSB, GTHE4_CH_RX_PRBS_CNT_RESET_LSB) +#define GTHE4_CH_RX_PRBS_LOCKED_ADDR 0x11041 +#define GTHE4_CH_RX_PRBS_LOCKED_MSB 8 +#define GTHE4_CH_RX_PRBS_LOCKED_LSB 8 +#define GTHE4_CH_RX_PRBS_LOCKED_MASK BIT_MASK(GTHE4_CH_RX_PRBS_LOCKED_MSB, GTHE4_CH_RX_PRBS_LOCKED_LSB) +#define GTHE4_CH_RX_PRBS_ERROR_ADDR 0x11041 +#define GTHE4_CH_RX_PRBS_ERROR_MSB 9 +#define GTHE4_CH_RX_PRBS_ERROR_LSB 9 +#define GTHE4_CH_RX_PRBS_ERROR_MASK BIT_MASK(GTHE4_CH_RX_PRBS_ERROR_MSB, GTHE4_CH_RX_PRBS_ERROR_LSB) + + +def_gt_pll_masked_reg_rw16(gthe4, qpll0_reset, GTHE4_COM_QPLL0_RESET_ADDR, GTHE4_COM_QPLL0_RESET_MASK, GTHE4_COM_QPLL0_RESET_LSB); +int gthe4_pll_qpll0_reset(struct gt_pll *pll); +def_gt_pll_masked_reg_read16(gthe4, qpll0_lock, GTHE4_COM_QPLL0_LOCK_ADDR, GTHE4_COM_QPLL0_LOCK_MASK, GTHE4_COM_QPLL0_LOCK_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_pd, GTHE4_COM_QPLL0_PD_ADDR, GTHE4_COM_QPLL0_PD_MASK, GTHE4_COM_QPLL0_PD_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_reset, GTHE4_COM_QPLL1_RESET_ADDR, GTHE4_COM_QPLL1_RESET_MASK, GTHE4_COM_QPLL1_RESET_LSB); +int gthe4_pll_qpll1_reset(struct gt_pll *pll); +def_gt_pll_masked_reg_read16(gthe4, qpll1_lock, GTHE4_COM_QPLL1_LOCK_ADDR, GTHE4_COM_QPLL1_LOCK_MASK, GTHE4_COM_QPLL1_LOCK_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_pd, GTHE4_COM_QPLL1_PD_ADDR, GTHE4_COM_QPLL1_PD_MASK, GTHE4_COM_QPLL1_PD_LSB); + +def_gt_ch_masked_reg_rw16(gthe4, tx_reset, GTHE4_CH_TX_RESET_ADDR, GTHE4_CH_TX_RESET_MASK, GTHE4_CH_TX_RESET_LSB); +int gthe4_ch_tx_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe4, tx_pma_reset, GTHE4_CH_TX_PMA_RESET_ADDR, GTHE4_CH_TX_PMA_RESET_MASK, GTHE4_CH_TX_PMA_RESET_LSB); +int gthe4_ch_tx_pma_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe4, tx_pcs_reset, GTHE4_CH_TX_PCS_RESET_ADDR, GTHE4_CH_TX_PCS_RESET_MASK, GTHE4_CH_TX_PCS_RESET_LSB); +int gthe4_ch_tx_pcs_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_read16(gthe4, tx_reset_done, GTHE4_CH_TX_RESET_DONE_ADDR, GTHE4_CH_TX_RESET_DONE_MASK, GTHE4_CH_TX_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe4, tx_gt_reset_done, GTHE4_CH_TX_GT_RESET_DONE_ADDR, GTHE4_CH_TX_GT_RESET_DONE_MASK, GTHE4_CH_TX_GT_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe4, tx_pma_reset_done, GTHE4_CH_TX_PMA_RESET_DONE_ADDR, GTHE4_CH_TX_PMA_RESET_DONE_MASK, GTHE4_CH_TX_PMA_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe4, tx_prgdiv_reset_done, GTHE4_CH_TX_PRGDIV_RESET_DONE_ADDR, GTHE4_CH_TX_PRGDIV_RESET_DONE_MASK, GTHE4_CH_TX_PRGDIV_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe4, tx_usrclk_act, GTHE4_CH_TX_USRCLK_ACT_ADDR, GTHE4_CH_TX_USRCLK_ACT_MASK, GTHE4_CH_TX_USRCLK_ACT_LSB); +def_gt_ch_masked_reg_rw16(gthe4, tx_pd, GTHE4_CH_TX_PD_ADDR, GTHE4_CH_TX_PD_MASK, GTHE4_CH_TX_PD_LSB); +def_gt_ch_masked_reg_rw16(gthe4, tx_qpll_sel, GTHE4_CH_TX_QPLL_SEL_ADDR, GTHE4_CH_TX_QPLL_SEL_MASK, GTHE4_CH_TX_QPLL_SEL_LSB); +def_gt_ch_masked_reg_rw16(gthe4, tx_polarity, GTHE4_CH_TX_POLARITY_ADDR, GTHE4_CH_TX_POLARITY_MASK, GTHE4_CH_TX_POLARITY_LSB); +def_gt_ch_masked_reg_rw16(gthe4, tx_elecidle, GTHE4_CH_TX_ELECIDLE_ADDR, GTHE4_CH_TX_ELECIDLE_MASK, GTHE4_CH_TX_ELECIDLE_LSB); +def_gt_ch_masked_reg_rw16(gthe4, tx_inhibit, GTHE4_CH_TX_INHIBIT_ADDR, GTHE4_CH_TX_INHIBIT_MASK, GTHE4_CH_TX_INHIBIT_LSB); +def_gt_ch_masked_reg_rw16(gthe4, tx_diffctrl, GTHE4_CH_TX_DIFFCTRL_ADDR, GTHE4_CH_TX_DIFFCTRL_MASK, GTHE4_CH_TX_DIFFCTRL_LSB); +def_gt_ch_masked_reg_rw16(gthe4, tx_maincursor, GTHE4_CH_TX_MAINCURSOR_ADDR, GTHE4_CH_TX_MAINCURSOR_MASK, GTHE4_CH_TX_MAINCURSOR_LSB); +def_gt_ch_masked_reg_rw16(gthe4, tx_precursor, GTHE4_CH_TX_PRECURSOR_ADDR, GTHE4_CH_TX_PRECURSOR_MASK, GTHE4_CH_TX_PRECURSOR_LSB); +def_gt_ch_masked_reg_rw16(gthe4, tx_postcursor, GTHE4_CH_TX_POSTCURSOR_ADDR, GTHE4_CH_TX_POSTCURSOR_MASK, GTHE4_CH_TX_POSTCURSOR_LSB); +def_gt_ch_masked_reg_rw16(gthe4, tx_prbs_sel, GTHE4_CH_TX_PRBS_SEL_ADDR, GTHE4_CH_TX_PRBS_SEL_MASK, GTHE4_CH_TX_PRBS_SEL_LSB); +def_gt_ch_masked_reg_rw16(gthe4, tx_prbs_forcerr, GTHE4_CH_TX_PRBS_FORCERR_ADDR, GTHE4_CH_TX_PRBS_FORCERR_MASK, GTHE4_CH_TX_PRBS_FORCERR_LSB); + +def_gt_ch_masked_reg_rw16(gthe4, rx_reset, GTHE4_CH_RX_RESET_ADDR, GTHE4_CH_RX_RESET_MASK, GTHE4_CH_RX_RESET_LSB); +int gthe4_ch_rx_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe4, rx_pma_reset, GTHE4_CH_RX_PMA_RESET_ADDR, GTHE4_CH_RX_PMA_RESET_MASK, GTHE4_CH_RX_PMA_RESET_LSB); +int gthe4_ch_rx_pma_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe4, rx_pcs_reset, GTHE4_CH_RX_PCS_RESET_ADDR, GTHE4_CH_RX_PCS_RESET_MASK, GTHE4_CH_RX_PCS_RESET_LSB); +int gthe4_ch_rx_pcs_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe4, rx_dfe_lpm_reset, GTHE4_CH_RX_DFE_LPM_RESET_ADDR, GTHE4_CH_RX_DFE_LPM_RESET_MASK, GTHE4_CH_RX_DFE_LPM_RESET_LSB); +int gthe4_ch_rx_dfe_lpm_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gthe4, eyescan_reset, GTHE4_CH_EYESCAN_RESET_ADDR, GTHE4_CH_EYESCAN_RESET_MASK, GTHE4_CH_EYESCAN_RESET_LSB); +int gthe4_ch_eyescan_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_read16(gthe4, rx_reset_done, GTHE4_CH_RX_RESET_DONE_ADDR, GTHE4_CH_RX_RESET_DONE_MASK, GTHE4_CH_RX_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe4, rx_gt_reset_done, GTHE4_CH_RX_GT_RESET_DONE_ADDR, GTHE4_CH_RX_GT_RESET_DONE_MASK, GTHE4_CH_RX_GT_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe4, rx_pma_reset_done, GTHE4_CH_RX_PMA_RESET_DONE_ADDR, GTHE4_CH_RX_PMA_RESET_DONE_MASK, GTHE4_CH_RX_PMA_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe4, rx_prgdiv_reset_done, GTHE4_CH_RX_PRGDIV_RESET_DONE_ADDR, GTHE4_CH_RX_PRGDIV_RESET_DONE_MASK, GTHE4_CH_RX_PRGDIV_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gthe4, rx_usrclk_act, GTHE4_CH_RX_USRCLK_ACT_ADDR, GTHE4_CH_RX_USRCLK_ACT_MASK, GTHE4_CH_RX_USRCLK_ACT_LSB); +def_gt_ch_masked_reg_rw16(gthe4, rx_pd, GTHE4_CH_RX_PD_ADDR, GTHE4_CH_RX_PD_MASK, GTHE4_CH_RX_PD_LSB); +def_gt_ch_masked_reg_rw16(gthe4, rx_qpll_sel, GTHE4_CH_RX_QPLL_SEL_ADDR, GTHE4_CH_RX_QPLL_SEL_MASK, GTHE4_CH_RX_QPLL_SEL_LSB); +def_gt_ch_masked_reg_rw16(gthe4, loopback, GTHE4_CH_LOOPBACK_ADDR, GTHE4_CH_LOOPBACK_MASK, GTHE4_CH_LOOPBACK_LSB); +def_gt_ch_masked_reg_rw16(gthe4, rx_polarity, GTHE4_CH_RX_POLARITY_ADDR, GTHE4_CH_RX_POLARITY_MASK, GTHE4_CH_RX_POLARITY_LSB); +def_gt_ch_masked_reg_rw16(gthe4, rx_cdr_hold, GTHE4_CH_RX_CDR_HOLD_ADDR, GTHE4_CH_RX_CDR_HOLD_MASK, GTHE4_CH_RX_CDR_HOLD_LSB); +def_gt_ch_masked_reg_read16(gthe4, rx_cdr_lock, GTHE4_CH_RX_CDR_LOCK_ADDR, GTHE4_CH_RX_CDR_LOCK_MASK, GTHE4_CH_RX_CDR_LOCK_LSB); +def_gt_ch_masked_reg_rw16(gthe4, rx_lpm_en, GTHE4_CH_RX_LPM_EN_ADDR, GTHE4_CH_RX_LPM_EN_MASK, GTHE4_CH_RX_LPM_EN_LSB); +def_gt_ch_masked_reg_read16(gthe4, rx_dmonitor, GTHE4_CH_RX_DMONITOR_ADDR, GTHE4_CH_RX_DMONITOR_MASK, GTHE4_CH_RX_DMONITOR_LSB); +def_gt_ch_masked_reg_rw16(gthe4, rx_prbs_sel, GTHE4_CH_RX_PRBS_SEL_ADDR, GTHE4_CH_RX_PRBS_SEL_MASK, GTHE4_CH_RX_PRBS_SEL_LSB); +def_gt_ch_masked_reg_rw16(gthe4, rx_prbs_cnt_reset, GTHE4_CH_RX_PRBS_CNT_RESET_ADDR, GTHE4_CH_RX_PRBS_CNT_RESET_MASK, GTHE4_CH_RX_PRBS_CNT_RESET_LSB); +def_gt_ch_masked_reg_read16(gthe4, rx_prbs_locked, GTHE4_CH_RX_PRBS_LOCKED_ADDR, GTHE4_CH_RX_PRBS_LOCKED_MASK, GTHE4_CH_RX_PRBS_LOCKED_LSB); +def_gt_ch_masked_reg_read16(gthe4, rx_prbs_error, GTHE4_CH_RX_PRBS_ERROR_ADDR, GTHE4_CH_RX_PRBS_ERROR_MASK, GTHE4_CH_RX_PRBS_ERROR_LSB); + +// common +def_gt_pll_masked_reg_rw16(gthe4, qpll0_cfg0, GTHE4_COM_QPLL0_CFG0_ADDR, GTHE4_COM_QPLL0_CFG0_MASK, GTHE4_COM_QPLL0_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe4, common_cfg0, GTHE4_COM_COMMON_CFG0_ADDR, GTHE4_COM_COMMON_CFG0_MASK, GTHE4_COM_COMMON_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe4, ppf0_cfg, GTHE4_COM_PPF0_CFG_ADDR, GTHE4_COM_PPF0_CFG_MASK, GTHE4_COM_PPF0_CFG_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0clkout_rate, GTHE4_COM_QPLL0CLKOUT_RATE_ADDR, GTHE4_COM_QPLL0CLKOUT_RATE_MASK, GTHE4_COM_QPLL0CLKOUT_RATE_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_cfg1, GTHE4_COM_QPLL0_CFG1_ADDR, GTHE4_COM_QPLL0_CFG1_MASK, GTHE4_COM_QPLL0_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_cfg2, GTHE4_COM_QPLL0_CFG2_ADDR, GTHE4_COM_QPLL0_CFG2_MASK, GTHE4_COM_QPLL0_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_lock_cfg, GTHE4_COM_QPLL0_LOCK_CFG_ADDR, GTHE4_COM_QPLL0_LOCK_CFG_MASK, GTHE4_COM_QPLL0_LOCK_CFG_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_init_cfg0, GTHE4_COM_QPLL0_INIT_CFG0_ADDR, GTHE4_COM_QPLL0_INIT_CFG0_MASK, GTHE4_COM_QPLL0_INIT_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_init_cfg1, GTHE4_COM_QPLL0_INIT_CFG1_ADDR, GTHE4_COM_QPLL0_INIT_CFG1_MASK, GTHE4_COM_QPLL0_INIT_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_fbdiv, GTHE4_COM_QPLL0_FBDIV_ADDR, GTHE4_COM_QPLL0_FBDIV_MASK, GTHE4_COM_QPLL0_FBDIV_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_cfg3, GTHE4_COM_QPLL0_CFG3_ADDR, GTHE4_COM_QPLL0_CFG3_MASK, GTHE4_COM_QPLL0_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_cp, GTHE4_COM_QPLL0_CP_ADDR, GTHE4_COM_QPLL0_CP_MASK, GTHE4_COM_QPLL0_CP_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_refclk_div, GTHE4_COM_QPLL0_REFCLK_DIV_ADDR, GTHE4_COM_QPLL0_REFCLK_DIV_MASK, GTHE4_COM_QPLL0_REFCLK_DIV_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_lpf, GTHE4_COM_QPLL0_LPF_ADDR, GTHE4_COM_QPLL0_LPF_MASK, GTHE4_COM_QPLL0_LPF_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_cfg1_g3, GTHE4_COM_QPLL0_CFG1_G3_ADDR, GTHE4_COM_QPLL0_CFG1_G3_MASK, GTHE4_COM_QPLL0_CFG1_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_cfg2_g3, GTHE4_COM_QPLL0_CFG2_G3_ADDR, GTHE4_COM_QPLL0_CFG2_G3_MASK, GTHE4_COM_QPLL0_CFG2_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_lpf_g3, GTHE4_COM_QPLL0_LPF_G3_ADDR, GTHE4_COM_QPLL0_LPF_G3_MASK, GTHE4_COM_QPLL0_LPF_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_lock_cfg_g3, GTHE4_COM_QPLL0_LOCK_CFG_G3_ADDR, GTHE4_COM_QPLL0_LOCK_CFG_G3_MASK, GTHE4_COM_QPLL0_LOCK_CFG_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, rsvd_attr0, GTHE4_COM_RSVD_ATTR0_ADDR, GTHE4_COM_RSVD_ATTR0_MASK, GTHE4_COM_RSVD_ATTR0_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_fbdiv_g3, GTHE4_COM_QPLL0_FBDIV_G3_ADDR, GTHE4_COM_QPLL0_FBDIV_G3_MASK, GTHE4_COM_QPLL0_FBDIV_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_rate_sw_use_drp, GTHE4_COM_QPLL0_RATE_SW_USE_DRP_ADDR, GTHE4_COM_QPLL0_RATE_SW_USE_DRP_MASK, GTHE4_COM_QPLL0_RATE_SW_USE_DRP_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_pci_en, GTHE4_COM_QPLL0_PCI_EN_ADDR, GTHE4_COM_QPLL0_PCI_EN_MASK, GTHE4_COM_QPLL0_PCI_EN_LSB); +def_gt_pll_masked_reg_rw16(gthe4, rxrecclkout0_sel, GTHE4_COM_RXRECCLKOUT0_SEL_ADDR, GTHE4_COM_RXRECCLKOUT0_SEL_MASK, GTHE4_COM_RXRECCLKOUT0_SEL_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_sdm_cfg0, GTHE4_COM_QPLL0_SDM_CFG0_ADDR, GTHE4_COM_QPLL0_SDM_CFG0_MASK, GTHE4_COM_QPLL0_SDM_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_sdm_cfg1, GTHE4_COM_QPLL0_SDM_CFG1_ADDR, GTHE4_COM_QPLL0_SDM_CFG1_MASK, GTHE4_COM_QPLL0_SDM_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe4, sdm0initseed0_0, GTHE4_COM_SDM0INITSEED0_0_ADDR, GTHE4_COM_SDM0INITSEED0_0_MASK, GTHE4_COM_SDM0INITSEED0_0_LSB); +def_gt_pll_masked_reg_rw16(gthe4, sdm0initseed0_1, GTHE4_COM_SDM0INITSEED0_1_ADDR, GTHE4_COM_SDM0INITSEED0_1_MASK, GTHE4_COM_SDM0INITSEED0_1_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_sdm_cfg2, GTHE4_COM_QPLL0_SDM_CFG2_ADDR, GTHE4_COM_QPLL0_SDM_CFG2_MASK, GTHE4_COM_QPLL0_SDM_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_cp_g3, GTHE4_COM_QPLL0_CP_G3_ADDR, GTHE4_COM_QPLL0_CP_G3_MASK, GTHE4_COM_QPLL0_CP_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, aen_qpll0_fbdiv, GTHE4_COM_AEN_QPLL0_FBDIV_ADDR, GTHE4_COM_AEN_QPLL0_FBDIV_MASK, GTHE4_COM_AEN_QPLL0_FBDIV_LSB); +def_gt_pll_masked_reg_rw16(gthe4, aen_sdm0toggle, GTHE4_COM_AEN_SDM0TOGGLE_ADDR, GTHE4_COM_AEN_SDM0TOGGLE_MASK, GTHE4_COM_AEN_SDM0TOGGLE_LSB); +def_gt_pll_masked_reg_rw16(gthe4, a_sdm0toggle, GTHE4_COM_A_SDM0TOGGLE_ADDR, GTHE4_COM_A_SDM0TOGGLE_MASK, GTHE4_COM_A_SDM0TOGGLE_LSB); +def_gt_pll_masked_reg_rw16(gthe4, rsvd_attr1, GTHE4_COM_RSVD_ATTR1_ADDR, GTHE4_COM_RSVD_ATTR1_MASK, GTHE4_COM_RSVD_ATTR1_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll0_cfg4, GTHE4_COM_QPLL0_CFG4_ADDR, GTHE4_COM_QPLL0_CFG4_MASK, GTHE4_COM_QPLL0_CFG4_LSB); +def_gt_pll_masked_reg_rw16(gthe4, bias_cfg0, GTHE4_COM_BIAS_CFG0_ADDR, GTHE4_COM_BIAS_CFG0_MASK, GTHE4_COM_BIAS_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe4, bias_cfg1, GTHE4_COM_BIAS_CFG1_ADDR, GTHE4_COM_BIAS_CFG1_MASK, GTHE4_COM_BIAS_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe4, bias_cfg2, GTHE4_COM_BIAS_CFG2_ADDR, GTHE4_COM_BIAS_CFG2_MASK, GTHE4_COM_BIAS_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gthe4, bias_cfg3, GTHE4_COM_BIAS_CFG3_ADDR, GTHE4_COM_BIAS_CFG3_MASK, GTHE4_COM_BIAS_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, bias_cfg4, GTHE4_COM_BIAS_CFG4_ADDR, GTHE4_COM_BIAS_CFG4_MASK, GTHE4_COM_BIAS_CFG4_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_cfg0, GTHE4_COM_QPLL1_CFG0_ADDR, GTHE4_COM_QPLL1_CFG0_MASK, GTHE4_COM_QPLL1_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe4, common_cfg1, GTHE4_COM_COMMON_CFG1_ADDR, GTHE4_COM_COMMON_CFG1_MASK, GTHE4_COM_COMMON_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe4, por_cfg, GTHE4_COM_POR_CFG_ADDR, GTHE4_COM_POR_CFG_MASK, GTHE4_COM_POR_CFG_LSB); +def_gt_pll_masked_reg_rw16(gthe4, ppf1_cfg, GTHE4_COM_PPF1_CFG_ADDR, GTHE4_COM_PPF1_CFG_MASK, GTHE4_COM_PPF1_CFG_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1clkout_rate, GTHE4_COM_QPLL1CLKOUT_RATE_ADDR, GTHE4_COM_QPLL1CLKOUT_RATE_MASK, GTHE4_COM_QPLL1CLKOUT_RATE_LSB); +def_gt_pll_masked_reg_rw16(gthe4, bias_cfg_rsvd, GTHE4_COM_BIAS_CFG_RSVD_ADDR, GTHE4_COM_BIAS_CFG_RSVD_MASK, GTHE4_COM_BIAS_CFG_RSVD_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_cfg1, GTHE4_COM_QPLL1_CFG1_ADDR, GTHE4_COM_QPLL1_CFG1_MASK, GTHE4_COM_QPLL1_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_cfg2, GTHE4_COM_QPLL1_CFG2_ADDR, GTHE4_COM_QPLL1_CFG2_MASK, GTHE4_COM_QPLL1_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_lock_cfg, GTHE4_COM_QPLL1_LOCK_CFG_ADDR, GTHE4_COM_QPLL1_LOCK_CFG_MASK, GTHE4_COM_QPLL1_LOCK_CFG_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_init_cfg0, GTHE4_COM_QPLL1_INIT_CFG0_ADDR, GTHE4_COM_QPLL1_INIT_CFG0_MASK, GTHE4_COM_QPLL1_INIT_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_init_cfg1, GTHE4_COM_QPLL1_INIT_CFG1_ADDR, GTHE4_COM_QPLL1_INIT_CFG1_MASK, GTHE4_COM_QPLL1_INIT_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_fbdiv, GTHE4_COM_QPLL1_FBDIV_ADDR, GTHE4_COM_QPLL1_FBDIV_MASK, GTHE4_COM_QPLL1_FBDIV_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_cfg3, GTHE4_COM_QPLL1_CFG3_ADDR, GTHE4_COM_QPLL1_CFG3_MASK, GTHE4_COM_QPLL1_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_cp, GTHE4_COM_QPLL1_CP_ADDR, GTHE4_COM_QPLL1_CP_MASK, GTHE4_COM_QPLL1_CP_LSB); +def_gt_pll_masked_reg_rw16(gthe4, sarc_sel, GTHE4_COM_SARC_SEL_ADDR, GTHE4_COM_SARC_SEL_MASK, GTHE4_COM_SARC_SEL_LSB); +def_gt_pll_masked_reg_rw16(gthe4, sarc_enb, GTHE4_COM_SARC_ENB_ADDR, GTHE4_COM_SARC_ENB_MASK, GTHE4_COM_SARC_ENB_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_refclk_div, GTHE4_COM_QPLL1_REFCLK_DIV_ADDR, GTHE4_COM_QPLL1_REFCLK_DIV_MASK, GTHE4_COM_QPLL1_REFCLK_DIV_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_lpf, GTHE4_COM_QPLL1_LPF_ADDR, GTHE4_COM_QPLL1_LPF_MASK, GTHE4_COM_QPLL1_LPF_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_cfg1_g3, GTHE4_COM_QPLL1_CFG1_G3_ADDR, GTHE4_COM_QPLL1_CFG1_G3_MASK, GTHE4_COM_QPLL1_CFG1_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_cfg2_g3, GTHE4_COM_QPLL1_CFG2_G3_ADDR, GTHE4_COM_QPLL1_CFG2_G3_MASK, GTHE4_COM_QPLL1_CFG2_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_lpf_g3, GTHE4_COM_QPLL1_LPF_G3_ADDR, GTHE4_COM_QPLL1_LPF_G3_MASK, GTHE4_COM_QPLL1_LPF_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_lock_cfg_g3, GTHE4_COM_QPLL1_LOCK_CFG_G3_ADDR, GTHE4_COM_QPLL1_LOCK_CFG_G3_MASK, GTHE4_COM_QPLL1_LOCK_CFG_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, rsvd_attr2, GTHE4_COM_RSVD_ATTR2_ADDR, GTHE4_COM_RSVD_ATTR2_MASK, GTHE4_COM_RSVD_ATTR2_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_fbdiv_g3, GTHE4_COM_QPLL1_FBDIV_G3_ADDR, GTHE4_COM_QPLL1_FBDIV_G3_MASK, GTHE4_COM_QPLL1_FBDIV_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_rate_sw_use_drp, GTHE4_COM_QPLL1_RATE_SW_USE_DRP_ADDR, GTHE4_COM_QPLL1_RATE_SW_USE_DRP_MASK, GTHE4_COM_QPLL1_RATE_SW_USE_DRP_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_pci_en, GTHE4_COM_QPLL1_PCI_EN_ADDR, GTHE4_COM_QPLL1_PCI_EN_MASK, GTHE4_COM_QPLL1_PCI_EN_LSB); +def_gt_pll_masked_reg_rw16(gthe4, rxrecclkout1_sel, GTHE4_COM_RXRECCLKOUT1_SEL_ADDR, GTHE4_COM_RXRECCLKOUT1_SEL_MASK, GTHE4_COM_RXRECCLKOUT1_SEL_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_sdm_cfg0, GTHE4_COM_QPLL1_SDM_CFG0_ADDR, GTHE4_COM_QPLL1_SDM_CFG0_MASK, GTHE4_COM_QPLL1_SDM_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_sdm_cfg1, GTHE4_COM_QPLL1_SDM_CFG1_ADDR, GTHE4_COM_QPLL1_SDM_CFG1_MASK, GTHE4_COM_QPLL1_SDM_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gthe4, sdm1initseed0_0, GTHE4_COM_SDM1INITSEED0_0_ADDR, GTHE4_COM_SDM1INITSEED0_0_MASK, GTHE4_COM_SDM1INITSEED0_0_LSB); +def_gt_pll_masked_reg_rw16(gthe4, sdm1initseed0_1, GTHE4_COM_SDM1INITSEED0_1_ADDR, GTHE4_COM_SDM1INITSEED0_1_MASK, GTHE4_COM_SDM1INITSEED0_1_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_sdm_cfg2, GTHE4_COM_QPLL1_SDM_CFG2_ADDR, GTHE4_COM_QPLL1_SDM_CFG2_MASK, GTHE4_COM_QPLL1_SDM_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_cp_g3, GTHE4_COM_QPLL1_CP_G3_ADDR, GTHE4_COM_QPLL1_CP_G3_MASK, GTHE4_COM_QPLL1_CP_G3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, a_sdm1data_low, GTHE4_COM_A_SDM1DATA_LOW_ADDR, GTHE4_COM_A_SDM1DATA_LOW_MASK, GTHE4_COM_A_SDM1DATA_LOW_LSB); +def_gt_pll_masked_reg_rw16(gthe4, aen_qpll1_fbdiv, GTHE4_COM_AEN_QPLL1_FBDIV_ADDR, GTHE4_COM_AEN_QPLL1_FBDIV_MASK, GTHE4_COM_AEN_QPLL1_FBDIV_LSB); +def_gt_pll_masked_reg_rw16(gthe4, aen_sdm1toggle, GTHE4_COM_AEN_SDM1TOGGLE_ADDR, GTHE4_COM_AEN_SDM1TOGGLE_MASK, GTHE4_COM_AEN_SDM1TOGGLE_LSB); +def_gt_pll_masked_reg_rw16(gthe4, a_sdm1toggle, GTHE4_COM_A_SDM1TOGGLE_ADDR, GTHE4_COM_A_SDM1TOGGLE_MASK, GTHE4_COM_A_SDM1TOGGLE_LSB); +def_gt_pll_masked_reg_rw16(gthe4, a_sdm1data_high, GTHE4_COM_A_SDM1DATA_HIGH_ADDR, GTHE4_COM_A_SDM1DATA_HIGH_MASK, GTHE4_COM_A_SDM1DATA_HIGH_LSB); +def_gt_pll_masked_reg_rw16(gthe4, rsvd_attr3, GTHE4_COM_RSVD_ATTR3_ADDR, GTHE4_COM_RSVD_ATTR3_MASK, GTHE4_COM_RSVD_ATTR3_LSB); +def_gt_pll_masked_reg_rw16(gthe4, qpll1_cfg4, GTHE4_COM_QPLL1_CFG4_ADDR, GTHE4_COM_QPLL1_CFG4_MASK, GTHE4_COM_QPLL1_CFG4_LSB); + +// RX +def_gt_ch_masked_reg_rw16(gthe4, rx_data_width_raw, GTHE4_CH_RX_DATA_WIDTH_ADDR, GTHE4_CH_RX_DATA_WIDTH_MASK, GTHE4_CH_RX_DATA_WIDTH_LSB); +int gthe4_ch_get_rx_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gthe4, rx_int_data_width_raw, GTHE4_CH_RX_INT_DATAWIDTH_ADDR, GTHE4_CH_RX_INT_DATAWIDTH_MASK, GTHE4_CH_RX_INT_DATAWIDTH_LSB); +int gthe4_ch_get_rx_int_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gthe4, es_prescale, GTHE4_CH_ES_PRESCALE_ADDR, GTHE4_CH_ES_PRESCALE_MASK, GTHE4_CH_ES_PRESCALE_LSB); +def_gt_ch_masked_reg_rw16(gthe4, es_eye_scan_en, GTHE4_CH_ES_EYE_SCAN_EN_ADDR, GTHE4_CH_ES_EYE_SCAN_EN_MASK, GTHE4_CH_ES_EYE_SCAN_EN_LSB); +def_gt_ch_masked_reg_rw16(gthe4, es_errdet_en, GTHE4_CH_ES_ERRDET_EN_ADDR, GTHE4_CH_ES_ERRDET_EN_MASK, GTHE4_CH_ES_ERRDET_EN_LSB); +def_gt_ch_masked_reg_rw16(gthe4, es_control, GTHE4_CH_ES_CONTROL_ADDR, GTHE4_CH_ES_CONTROL_MASK, GTHE4_CH_ES_CONTROL_LSB); + +int gthe4_ch_set_es_qual_mask(struct gt_ch *ch, uint8_t *mask); +int gthe4_ch_set_es_qual_mask_clear(struct gt_ch *ch); + +int gthe4_ch_set_es_sdata_mask(struct gt_ch *ch, uint8_t *mask); +int gthe4_ch_set_es_sdata_mask_width(struct gt_ch *ch, int width); + +def_gt_ch_masked_reg_rw16(gthe4, es_horz_offset, GTHE4_CH_ES_HORZ_OFFSET_ADDR, GTHE4_CH_ES_HORZ_OFFSET_MASK, GTHE4_CH_ES_HORZ_OFFSET_LSB); +def_gt_ch_masked_reg_rw16(gthe4, rx_eyescan_vs_range, GTHE4_CH_RX_EYESCAN_VS_RANGE_ADDR, GTHE4_CH_RX_EYESCAN_VS_RANGE_MASK, GTHE4_CH_RX_EYESCAN_VS_RANGE_LSB); +def_gt_ch_masked_reg_rw16(gthe4, rx_eyescan_vs_code, GTHE4_CH_RX_EYESCAN_VS_CODE_ADDR, GTHE4_CH_RX_EYESCAN_VS_CODE_MASK, GTHE4_CH_RX_EYESCAN_VS_CODE_LSB); +def_gt_ch_masked_reg_rw16(gthe4, rx_eyescan_vs_ut_sign, GTHE4_CH_RX_EYESCAN_VS_UT_SIGN_ADDR, GTHE4_CH_RX_EYESCAN_VS_UT_SIGN_MASK, GTHE4_CH_RX_EYESCAN_VS_UT_SIGN_LSB); +def_gt_ch_masked_reg_rw16(gthe4, rx_eyescan_vs_neg_dir, GTHE4_CH_RX_EYESCAN_VS_NEG_DIR_ADDR, GTHE4_CH_RX_EYESCAN_VS_NEG_DIR_MASK, GTHE4_CH_RX_EYESCAN_VS_NEG_DIR_LSB); +def_gt_ch_masked_reg_read16(gthe4, es_error_count, GTHE4_CH_ES_ERROR_COUNT_ADDR, GTHE4_CH_ES_ERROR_COUNT_MASK, GTHE4_CH_ES_ERROR_COUNT_LSB); +def_gt_ch_masked_reg_read16(gthe4, es_sample_count, GTHE4_CH_ES_SAMPLE_COUNT_ADDR, GTHE4_CH_ES_SAMPLE_COUNT_MASK, GTHE4_CH_ES_SAMPLE_COUNT_LSB); +def_gt_ch_masked_reg_read16(gthe4, es_control_status, GTHE4_CH_ES_CONTROL_STATUS_ADDR, GTHE4_CH_ES_CONTROL_STATUS_MASK, GTHE4_CH_ES_CONTROL_STATUS_LSB); + +int gthe4_ch_get_rx_prbs_error_count(struct gt_ch *ch, uint32_t *val); + +// TX +def_gt_ch_masked_reg_rw16(gthe4, tx_data_width_raw, GTHE4_CH_TX_DATA_WIDTH_ADDR, GTHE4_CH_TX_DATA_WIDTH_MASK, GTHE4_CH_TX_DATA_WIDTH_LSB); +int gthe4_ch_get_tx_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gthe4, tx_int_data_width_raw, GTHE4_CH_TX_INT_DATAWIDTH_ADDR, GTHE4_CH_TX_INT_DATAWIDTH_MASK, GTHE4_CH_TX_INT_DATAWIDTH_LSB); +int gthe4_ch_get_tx_int_data_width(struct gt_ch *ch, uint32_t *val); + +extern const struct gt_quad_ops gthe4_gt_quad_ops; + +#endif /* XCVR_GTHE4_H */ diff --git a/utils/xcvr_gtye3.c b/utils/xcvr_gtye3.c new file mode 100644 index 0000000..2c98489 --- /dev/null +++ b/utils/xcvr_gtye3.c @@ -0,0 +1,785 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#include +#include +#include "xcvr_gtye3.h" + +// signals +int gtye3_pll_qpll0_reset(struct gt_pll *pll) +{ + int ret = 0; + + ret = gtye3_pll_set_qpll0_reset(pll, 1); + + if (ret) + return ret; + + return gtye3_pll_set_qpll0_reset(pll, 0); +} + +int gtye3_pll_qpll1_reset(struct gt_pll *pll) +{ + int ret = 0; + + ret = gtye3_pll_set_qpll1_reset(pll, 1); + + if (ret) + return ret; + + return gtye3_pll_set_qpll1_reset(pll, 0); +} + +int gtye3_ch_tx_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye3_ch_set_tx_reset(ch, 1); + + if (ret) + return ret; + + return gtye3_ch_set_tx_reset(ch, 0); +} + +int gtye3_ch_tx_pma_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye3_ch_set_tx_pma_reset(ch, 1); + + if (ret) + return ret; + + return gtye3_ch_set_tx_pma_reset(ch, 0); +} + +int gtye3_ch_tx_pcs_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye3_ch_set_tx_pcs_reset(ch, 1); + + if (ret) + return ret; + + return gtye3_ch_set_tx_pcs_reset(ch, 0); +} + +int gtye3_ch_rx_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye3_ch_set_rx_reset(ch, 1); + + if (ret) + return ret; + + return gtye3_ch_set_rx_reset(ch, 0); +} + +int gtye3_ch_rx_pma_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye3_ch_set_rx_pma_reset(ch, 1); + + if (ret) + return ret; + + return gtye3_ch_set_rx_pma_reset(ch, 0); +} + +int gtye3_ch_rx_pcs_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye3_ch_set_rx_pcs_reset(ch, 1); + + if (ret) + return ret; + + return gtye3_ch_set_rx_pcs_reset(ch, 0); +} + +int gtye3_ch_rx_dfe_lpm_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye3_ch_set_rx_dfe_lpm_reset(ch, 1); + + if (ret) + return ret; + + return gtye3_ch_set_rx_dfe_lpm_reset(ch, 0); +} + +int gtye3_ch_eyescan_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye3_ch_set_eyescan_reset(ch, 1); + + if (ret) + return ret; + + return gtye3_ch_set_eyescan_reset(ch, 0); +} + +// RX +int gtye3_ch_get_rx_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw; + + ret = gtye3_ch_get_rx_data_width_raw(ch, &dw); + if (ret) + return ret; + + *val = (8*(1 << (dw >> 1)) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gtye3_ch_get_rx_int_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw, idw; + + ret = gtye3_ch_get_rx_data_width_raw(ch, &dw); + if (ret) + return ret; + + ret = gtye3_ch_get_rx_int_data_width_raw(ch, &idw); + if (ret) + return ret; + + *val = (16*(1 << idw) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gtye3_ch_set_es_qual_mask(struct gt_ch *ch, uint8_t *mask) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTYE3_CH_ES_QUAL_MASK0_ADDR+k, mask[2*k+0] | (mask[2*k+1] << 8)); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTYE3_CH_ES_QUAL_MASK5_ADDR+k, mask[2*k+10] | (mask[2*k+11] << 8)); + if (ret) + return ret; + } + + return 0; +} + +int gtye3_ch_set_es_qual_mask_clear(struct gt_ch *ch) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTYE3_CH_ES_QUAL_MASK0_ADDR+k, 0xffff); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTYE3_CH_ES_QUAL_MASK5_ADDR+k, 0xffff); + if (ret) + return ret; + } + + return 0; +} + +int gtye3_ch_set_es_sdata_mask(struct gt_ch *ch, uint8_t *mask) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTYE3_CH_ES_SDATA_MASK0_ADDR+k, mask[2*k+0] | (mask[2*k+1] << 8)); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTYE3_CH_ES_SDATA_MASK5_ADDR+k, mask[2*k+10] | (mask[2*k+11] << 8)); + if (ret) + return ret; + } + + return 0; +} + +int gtye3_ch_set_es_sdata_mask_width(struct gt_ch *ch, int width) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + int shift = width - (80 - ((k+1)*16)); + uint32_t mask = 0xffff; + + if (shift < 0) + { + mask = 0xffff; + } + else if (shift > 16) + { + mask = 0x0000; + } + else + { + mask = 0xffff >> shift; + } + + ret = gt_ch_reg_write(ch, GTYE3_CH_ES_SDATA_MASK0_ADDR+k, mask); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTYE3_CH_ES_SDATA_MASK5_ADDR+k, 0xffff); + if (ret) + return ret; + } + + return 0; +} + +int gtye3_ch_get_rx_prbs_error_count(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t v1, v2; + + ret = gt_ch_reg_read(ch, GTYE3_CH_RX_PRBS_ERR_CNT_L_ADDR | (ch->index << 17), &v1); + if (ret) + return ret; + + ret = gt_ch_reg_read(ch, GTYE3_CH_RX_PRBS_ERR_CNT_H_ADDR | (ch->index << 17), &v2); + if (ret) + return ret; + + *val = v1 | (v2 << 16); + return 0; +} + +// TX +int gtye3_ch_get_tx_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw; + + ret = gtye3_ch_get_tx_data_width_raw(ch, &dw); + if (ret) + return ret; + + *val = (8*(1 << (dw >> 1)) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gtye3_ch_get_tx_int_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw, idw; + + ret = gtye3_ch_get_tx_data_width_raw(ch, &dw); + if (ret) + return ret; + + ret = gtye3_ch_get_tx_int_data_width_raw(ch, &idw); + if (ret) + return ret; + + *val = (16*(1 << idw) * (4 + (dw & 1))) >> 2; + return 0; +} + +struct gtye3_quad_priv { + int qpll0_25g; +}; + +struct gtye3_ch_priv { + uint32_t tx_data_width; + uint32_t tx_int_data_width; + uint32_t rx_data_width; + uint32_t rx_int_data_width; + int dfe_en; + + int prescale; + int h_start; + int h_stop; + int h_step; + int v_range; + int v_start; + int v_stop; + int v_step; + + int h_offset; + int v_offset; + int ut_sign; + int eyescan_running; +}; + +static const struct gt_reg_val gtye3_ch_preset_10g_baser_64_regs[] = { + {GTYE3_CH_CH_HSPMUX_ADDR, GTYE3_CH_CH_HSPMUX_MASK, GTYE3_CH_CH_HSPMUX_LSB, 0x2424}, + {GTYE3_CH_CKCAL1_CFG_3_ADDR, GTYE3_CH_CKCAL1_CFG_3_MASK, GTYE3_CH_CKCAL1_CFG_3_LSB, 0x0000}, + {GTYE3_CH_CKCAL2_CFG_0_ADDR, GTYE3_CH_CKCAL2_CFG_0_MASK, GTYE3_CH_CKCAL2_CFG_0_LSB, 0xC0C0}, + {GTYE3_CH_CKCAL2_CFG_1_ADDR, GTYE3_CH_CKCAL2_CFG_1_MASK, GTYE3_CH_CKCAL2_CFG_1_LSB, 0x80C0}, + {GTYE3_CH_CKCAL_RSVD1_ADDR, GTYE3_CH_CKCAL_RSVD1_MASK, GTYE3_CH_CKCAL_RSVD1_LSB, 0x0400}, + {GTYE3_CH_PMA_RSV0_ADDR, GTYE3_CH_PMA_RSV0_MASK, GTYE3_CH_PMA_RSV0_LSB, 0x2104}, + {GTYE3_CH_PMA_RSV1_ADDR, GTYE3_CH_PMA_RSV1_MASK, GTYE3_CH_PMA_RSV1_LSB, 0x505A}, + {GTYE3_CH_PREIQ_FREQ_BST_ADDR, GTYE3_CH_PREIQ_FREQ_BST_MASK, GTYE3_CH_PREIQ_FREQ_BST_LSB, 0x0000}, + {GTYE3_CH_RXCDR_CFG2_GEN3_ADDR, GTYE3_CH_RXCDR_CFG2_GEN3_MASK, GTYE3_CH_RXCDR_CFG2_GEN3_LSB, 0x0265}, + {GTYE3_CH_RXCDR_CFG2_ADDR, GTYE3_CH_RXCDR_CFG2_MASK, GTYE3_CH_RXCDR_CFG2_LSB, 0x0265}, + {GTYE3_CH_RXPI_CFG_ADDR, GTYE3_CH_RXPI_CFG_MASK, GTYE3_CH_RXPI_CFG_LSB, 0x0202}, + {GTYE3_CH_RX_DFE_KL_LPM_KH_CFG0_ADDR, GTYE3_CH_RX_DFE_KL_LPM_KH_CFG0_MASK, GTYE3_CH_RX_DFE_KL_LPM_KH_CFG0_LSB, 0x0003}, + {GTYE3_CH_RX_DFE_KL_LPM_KL_CFG0_ADDR, GTYE3_CH_RX_DFE_KL_LPM_KL_CFG0_MASK, GTYE3_CH_RX_DFE_KL_LPM_KL_CFG0_LSB, 0x0003}, + {GTYE3_CH_RX_PROGDIV_CFG_ADDR, GTYE3_CH_RX_PROGDIV_CFG_MASK, GTYE3_CH_RX_PROGDIV_CFG_LSB, GTYE3_CH_RX_PROGDIV_CFG_33}, + {GTYE3_CH_RX_PROGDIV_RATE_ADDR, GTYE3_CH_RX_PROGDIV_RATE_MASK, GTYE3_CH_RX_PROGDIV_RATE_LSB, GTYE3_CH_RX_PROGDIV_RATE_FULL}, + {GTYE3_CH_RX_WIDEMODE_CDR_ADDR, GTYE3_CH_RX_WIDEMODE_CDR_MASK, GTYE3_CH_RX_WIDEMODE_CDR_LSB, 0x0002}, + {GTYE3_CH_RX_XMODE_SEL_ADDR, GTYE3_CH_RX_XMODE_SEL_MASK, GTYE3_CH_RX_XMODE_SEL_LSB, 0x0001}, + {GTYE3_CH_TXPI_CFG3_ADDR, GTYE3_CH_TXPI_CFG3_MASK, GTYE3_CH_TXPI_CFG3_LSB, 0x0001}, + {GTYE3_CH_TXPI_CFG4_ADDR, GTYE3_CH_TXPI_CFG4_MASK, GTYE3_CH_TXPI_CFG4_LSB, 0x0001}, + {GTYE3_CH_TX_PI_BIASSET_ADDR, GTYE3_CH_TX_PI_BIASSET_MASK, GTYE3_CH_TX_PI_BIASSET_LSB, 0x0001}, + {GTYE3_CH_TX_PROGDIV_CFG_ADDR, GTYE3_CH_TX_PROGDIV_CFG_MASK, GTYE3_CH_TX_PROGDIV_CFG_LSB, GTYE3_CH_TX_PROGDIV_CFG_33}, + {GTYE3_CH_TX_PROGDIV_RATE_ADDR, GTYE3_CH_TX_PROGDIV_RATE_MASK, GTYE3_CH_TX_PROGDIV_RATE_LSB, GTYE3_CH_TX_PROGDIV_RATE_FULL}, + {0, 0, 0, 0} +}; + +static const struct gt_reg_val gtye3_ch_preset_10g_dfe_regs[] = { + {GTYE3_CH_RXDFELPM_KL_CFG1_ADDR, GTYE3_CH_RXDFELPM_KL_CFG1_MASK, GTYE3_CH_RXDFELPM_KL_CFG1_LSB, 0x0002}, + {GTYE3_CH_RXPI_CFG_ADDR, GTYE3_CH_RXPI_CFG_MASK, GTYE3_CH_RXPI_CFG_LSB, 0x0202}, + {GTYE3_CH_RX_DFE_AGC_CFG1_ADDR, GTYE3_CH_RX_DFE_AGC_CFG1_MASK, GTYE3_CH_RX_DFE_AGC_CFG1_LSB, 0x0004}, + {GTYE3_CH_TXPI_CFG0_ADDR, GTYE3_CH_TXPI_CFG0_MASK, GTYE3_CH_TXPI_CFG0_LSB, 0x0000}, + {GTYE3_CH_TXPI_CFG1_ADDR, GTYE3_CH_TXPI_CFG1_MASK, GTYE3_CH_TXPI_CFG1_LSB, 0x0000}, + {GTYE3_CH_TXPI_CFG2_ADDR, GTYE3_CH_TXPI_CFG2_MASK, GTYE3_CH_TXPI_CFG2_LSB, 0x0000}, + {GTYE3_CH_TXPI_CFG5_ADDR, GTYE3_CH_TXPI_CFG5_MASK, GTYE3_CH_TXPI_CFG5_LSB, 0x0000}, + {GTYE3_CH_TX_PI_CFG0_ADDR, GTYE3_CH_TX_PI_CFG0_MASK, GTYE3_CH_TX_PI_CFG0_LSB, 0x0000}, + {0, 0, 0, 0} +}; + +static const struct gt_reg_val gtye3_ch_preset_10g_lpm_regs[] = { + {GTYE3_CH_RXDFELPM_KL_CFG1_ADDR, GTYE3_CH_RXDFELPM_KL_CFG1_MASK, GTYE3_CH_RXDFELPM_KL_CFG1_LSB, 0x00E2}, + {GTYE3_CH_RXPI_CFG_ADDR, GTYE3_CH_RXPI_CFG_MASK, GTYE3_CH_RXPI_CFG_LSB, 0x566A}, + {GTYE3_CH_RX_DFE_AGC_CFG1_ADDR, GTYE3_CH_RX_DFE_AGC_CFG1_MASK, GTYE3_CH_RX_DFE_AGC_CFG1_LSB, 0x0002}, + {GTYE3_CH_TXPI_CFG0_ADDR, GTYE3_CH_TXPI_CFG0_MASK, GTYE3_CH_TXPI_CFG0_LSB, 0x0001}, + {GTYE3_CH_TXPI_CFG1_ADDR, GTYE3_CH_TXPI_CFG1_MASK, GTYE3_CH_TXPI_CFG1_LSB, 0x0001}, + {GTYE3_CH_TXPI_CFG2_ADDR, GTYE3_CH_TXPI_CFG2_MASK, GTYE3_CH_TXPI_CFG2_LSB, 0x0001}, + {GTYE3_CH_TXPI_CFG5_ADDR, GTYE3_CH_TXPI_CFG5_MASK, GTYE3_CH_TXPI_CFG5_LSB, 0x0003}, + {GTYE3_CH_TX_PI_CFG0_ADDR, GTYE3_CH_TX_PI_CFG0_MASK, GTYE3_CH_TX_PI_CFG0_LSB, 0x0002}, + {0, 0, 0, 0} +}; + +static const struct gt_reg_val gtye3_ch_preset_25g_baser_64_regs[] = { + {GTYE3_CH_CH_HSPMUX_ADDR, GTYE3_CH_CH_HSPMUX_MASK, GTYE3_CH_CH_HSPMUX_LSB, 0xB6B6}, + {GTYE3_CH_CKCAL1_CFG_3_ADDR, GTYE3_CH_CKCAL1_CFG_3_MASK, GTYE3_CH_CKCAL1_CFG_3_LSB, 0x0007}, + {GTYE3_CH_CKCAL2_CFG_0_ADDR, GTYE3_CH_CKCAL2_CFG_0_MASK, GTYE3_CH_CKCAL2_CFG_0_LSB, 0x4040}, + {GTYE3_CH_CKCAL2_CFG_1_ADDR, GTYE3_CH_CKCAL2_CFG_1_MASK, GTYE3_CH_CKCAL2_CFG_1_LSB, 0x0040}, + {GTYE3_CH_CKCAL_RSVD1_ADDR, GTYE3_CH_CKCAL_RSVD1_MASK, GTYE3_CH_CKCAL_RSVD1_LSB, 0x0000}, + {GTYE3_CH_PMA_RSV0_ADDR, GTYE3_CH_PMA_RSV0_MASK, GTYE3_CH_PMA_RSV0_LSB, 0x2116}, + {GTYE3_CH_PMA_RSV1_ADDR, GTYE3_CH_PMA_RSV1_MASK, GTYE3_CH_PMA_RSV1_LSB, 0x504A}, + {GTYE3_CH_PREIQ_FREQ_BST_ADDR, GTYE3_CH_PREIQ_FREQ_BST_MASK, GTYE3_CH_PREIQ_FREQ_BST_LSB, 0x0002}, + {GTYE3_CH_RXCDR_CFG2_GEN3_ADDR, GTYE3_CH_RXCDR_CFG2_GEN3_MASK, GTYE3_CH_RXCDR_CFG2_GEN3_LSB, 0x01E9}, + {GTYE3_CH_RXCDR_CFG2_ADDR, GTYE3_CH_RXCDR_CFG2_MASK, GTYE3_CH_RXCDR_CFG2_LSB, 0x01E9}, + {GTYE3_CH_RXPI_CFG_ADDR, GTYE3_CH_RXPI_CFG_MASK, GTYE3_CH_RXPI_CFG_LSB, 0x0006}, + {GTYE3_CH_RX_DFE_KL_LPM_KH_CFG0_ADDR, GTYE3_CH_RX_DFE_KL_LPM_KH_CFG0_MASK, GTYE3_CH_RX_DFE_KL_LPM_KH_CFG0_LSB, 0x0001}, + {GTYE3_CH_RX_DFE_KL_LPM_KL_CFG0_ADDR, GTYE3_CH_RX_DFE_KL_LPM_KL_CFG0_MASK, GTYE3_CH_RX_DFE_KL_LPM_KL_CFG0_LSB, 0x0001}, + {GTYE3_CH_RX_PROGDIV_CFG_ADDR, GTYE3_CH_RX_PROGDIV_CFG_MASK, GTYE3_CH_RX_PROGDIV_CFG_LSB, GTYE3_CH_RX_PROGDIV_CFG_16P5}, + {GTYE3_CH_RX_PROGDIV_RATE_ADDR, GTYE3_CH_RX_PROGDIV_RATE_MASK, GTYE3_CH_RX_PROGDIV_RATE_LSB, GTYE3_CH_RX_PROGDIV_RATE_HALF}, + {GTYE3_CH_RX_WIDEMODE_CDR_ADDR, GTYE3_CH_RX_WIDEMODE_CDR_MASK, GTYE3_CH_RX_WIDEMODE_CDR_LSB, 0x0000}, + {GTYE3_CH_RX_XMODE_SEL_ADDR, GTYE3_CH_RX_XMODE_SEL_MASK, GTYE3_CH_RX_XMODE_SEL_LSB, 0x0000}, + {GTYE3_CH_TXPI_CFG3_ADDR, GTYE3_CH_TXPI_CFG3_MASK, GTYE3_CH_TXPI_CFG3_LSB, 0x0000}, + {GTYE3_CH_TXPI_CFG4_ADDR, GTYE3_CH_TXPI_CFG4_MASK, GTYE3_CH_TXPI_CFG4_LSB, 0x0000}, + {GTYE3_CH_TX_PI_BIASSET_ADDR, GTYE3_CH_TX_PI_BIASSET_MASK, GTYE3_CH_TX_PI_BIASSET_LSB, 0x0000}, + {GTYE3_CH_TX_PROGDIV_CFG_ADDR, GTYE3_CH_TX_PROGDIV_CFG_MASK, GTYE3_CH_TX_PROGDIV_CFG_LSB, GTYE3_CH_TX_PROGDIV_CFG_16P5}, + {GTYE3_CH_TX_PROGDIV_RATE_ADDR, GTYE3_CH_TX_PROGDIV_RATE_MASK, GTYE3_CH_TX_PROGDIV_RATE_LSB, GTYE3_CH_TX_PROGDIV_RATE_HALF}, + {0, 0, 0, 0} +}; + +static const struct gt_reg_val gtye3_ch_preset_25g_dfe_regs[] = { + {GTYE3_CH_RXDFELPM_KL_CFG1_ADDR, GTYE3_CH_RXDFELPM_KL_CFG1_MASK, GTYE3_CH_RXDFELPM_KL_CFG1_LSB, 0x0002}, + {GTYE3_CH_RX_DFE_AGC_CFG1_ADDR, GTYE3_CH_RX_DFE_AGC_CFG1_MASK, GTYE3_CH_RX_DFE_AGC_CFG1_LSB, 0x0004}, + {GTYE3_CH_TXPI_CFG0_ADDR, GTYE3_CH_TXPI_CFG0_MASK, GTYE3_CH_TXPI_CFG0_LSB, 0x0000}, + {GTYE3_CH_TXPI_CFG1_ADDR, GTYE3_CH_TXPI_CFG1_MASK, GTYE3_CH_TXPI_CFG1_LSB, 0x0000}, + {GTYE3_CH_TXPI_CFG2_ADDR, GTYE3_CH_TXPI_CFG2_MASK, GTYE3_CH_TXPI_CFG2_LSB, 0x0000}, + {GTYE3_CH_TXPI_CFG5_ADDR, GTYE3_CH_TXPI_CFG5_MASK, GTYE3_CH_TXPI_CFG5_LSB, 0x0000}, + {GTYE3_CH_TX_PI_CFG0_ADDR, GTYE3_CH_TX_PI_CFG0_MASK, GTYE3_CH_TX_PI_CFG0_LSB, 0x0000}, + {0, 0, 0, 0} +}; + +static const struct gt_reg_val gtye3_ch_preset_25g_lpm_regs[] = { + {GTYE3_CH_RXDFELPM_KL_CFG1_ADDR, GTYE3_CH_RXDFELPM_KL_CFG1_MASK, GTYE3_CH_RXDFELPM_KL_CFG1_LSB, 0x00E2}, + {GTYE3_CH_RX_DFE_AGC_CFG1_ADDR, GTYE3_CH_RX_DFE_AGC_CFG1_MASK, GTYE3_CH_RX_DFE_AGC_CFG1_LSB, 0x0002}, + {GTYE3_CH_TXPI_CFG0_ADDR, GTYE3_CH_TXPI_CFG0_MASK, GTYE3_CH_TXPI_CFG0_LSB, 0x0000}, + {GTYE3_CH_TXPI_CFG1_ADDR, GTYE3_CH_TXPI_CFG1_MASK, GTYE3_CH_TXPI_CFG1_LSB, 0x0000}, + {GTYE3_CH_TXPI_CFG2_ADDR, GTYE3_CH_TXPI_CFG2_MASK, GTYE3_CH_TXPI_CFG2_LSB, 0x0000}, + {GTYE3_CH_TXPI_CFG5_ADDR, GTYE3_CH_TXPI_CFG5_MASK, GTYE3_CH_TXPI_CFG5_LSB, 0x0000}, + {GTYE3_CH_TX_PI_CFG0_ADDR, GTYE3_CH_TX_PI_CFG0_MASK, GTYE3_CH_TX_PI_CFG0_LSB, 0x0000}, + {0, 0, 0, 0} +}; + +static const uint32_t gtye3_ch_presets[] = { + GT_PRESET_10G_DFE, + GT_PRESET_10G_LPM, + GT_PRESET_25G_DFE, + GT_PRESET_25G_LPM, + 0 +}; + +static int gtye3_ch_get_available_presets(struct gt_ch *ch, const uint32_t **presets) +{ + *presets = gtye3_ch_presets; + return 0; +} + +int gtye3_ch_load_preset(struct gt_ch *ch, uint32_t preset) +{ + struct gtye3_quad_priv *priv = ch->quad->priv; + + if (preset == GT_PRESET_10G_DFE || preset == GT_PRESET_10G_LPM) + { + if (priv->qpll0_25g) + gtye3_pll_set_qpll1_pd(ch->pll, 0); + + gtye3_ch_set_tx_reset(ch, 1); + gtye3_ch_set_rx_reset(ch, 1); + + if (priv->qpll0_25g) + { + gtye3_ch_set_tx_qpll_sel(ch, 1); + gtye3_ch_set_rx_qpll_sel(ch, 1); + } + + gt_ch_reg_write_multiple(ch, gtye3_ch_preset_10g_baser_64_regs); + + if (preset == GT_PRESET_10G_DFE) + { + gt_ch_reg_write_multiple(ch, gtye3_ch_preset_10g_dfe_regs); + gtye3_ch_set_rx_lpm_en(ch, 0); + } + else + { + gt_ch_reg_write_multiple(ch, gtye3_ch_preset_10g_lpm_regs); + gtye3_ch_set_rx_lpm_en(ch, 1); + } + + gtye3_ch_set_tx_reset(ch, 0); + gtye3_ch_set_rx_reset(ch, 0); + + return 0; + } + + if ((preset == GT_PRESET_25G_DFE || preset == GT_PRESET_25G_LPM) && priv->qpll0_25g) + { + gtye3_ch_set_tx_reset(ch, 1); + gtye3_ch_set_rx_reset(ch, 1); + + gtye3_ch_set_tx_qpll_sel(ch, 0); + gtye3_ch_set_rx_qpll_sel(ch, 0); + + gt_ch_reg_write_multiple(ch, gtye3_ch_preset_25g_baser_64_regs); + + if (preset == GT_PRESET_25G_DFE) + { + gt_ch_reg_write_multiple(ch, gtye3_ch_preset_25g_dfe_regs); + gtye3_ch_set_rx_lpm_en(ch, 0); + } + else + { + gt_ch_reg_write_multiple(ch, gtye3_ch_preset_25g_lpm_regs); + gtye3_ch_set_rx_lpm_en(ch, 1); + } + + gtye3_ch_set_tx_reset(ch, 0); + gtye3_ch_set_rx_reset(ch, 0); + + return 0; + } + + return -1; +} + +static int gtye3_ch_eyescan_start(struct gt_ch *ch, struct gt_eyescan_params *params) +{ + struct gtye3_ch_priv *priv = ch->priv; + uint32_t val; + + uint32_t error_count; + uint32_t sample_count; + uint64_t bit_count; + float ber; + + priv->eyescan_running = 0; + + gtye3_ch_get_rx_lpm_en(ch, &val); + priv->dfe_en = !val; + + gtye3_ch_get_rx_data_width(ch, &priv->rx_data_width); + gtye3_ch_get_rx_int_data_width(ch, &priv->rx_int_data_width); + + priv->prescale = 0; + + for (priv->prescale = 0; priv->prescale < 32; priv->prescale++) + { + if (((uint64_t)0xffff * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale) >= params->target_bit_count) + break; + } + + params->target_bit_count = ((uint64_t)0xffff * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale); + params->h_range = 0; + + priv->h_start = params->h_start; + priv->h_stop = params->h_stop; + priv->h_step = params->h_step; + priv->v_range = params->v_range; + priv->v_start = params->v_start; + priv->v_stop = params->v_stop; + priv->v_step = params->v_step; + + gtye3_ch_set_es_control(ch, 0x00); + + gtye3_ch_set_es_prescale(ch, 4); + gtye3_ch_set_es_errdet_en(ch, 1); + + gtye3_ch_set_es_qual_mask_clear(ch); + gtye3_ch_set_es_sdata_mask_width(ch, priv->rx_int_data_width); + + gtye3_ch_set_rx_eyescan_vs_range(ch, priv->v_range); + + gtye3_ch_set_es_horz_offset(ch, 0x800); + gtye3_ch_set_rx_eyescan_vs_neg_dir(ch, 0); + gtye3_ch_set_rx_eyescan_vs_code(ch, 0); + gtye3_ch_set_rx_eyescan_vs_ut_sign(ch, 0); + + gtye3_ch_set_es_eye_scan_en(ch, 1); + + gtye3_ch_rx_pma_reset(ch); + + for (int ber_tries = 0; ber_tries < 10; ber_tries++) + { + for (int reset_tries = 0; reset_tries < 30; reset_tries++) + { + gtye3_ch_get_rx_reset_done(ch, &val); + if (val) + break; + usleep(100000); + } + + if (!val) + { + fprintf(stderr, "Error: channel stuck in reset\n"); + return -1; + } + + usleep(100000); + + // check for lock + gtye3_ch_set_es_control(ch, 0x01); + + for (int wait_tries = 0; wait_tries < 30; wait_tries++) + { + gtye3_ch_get_es_control_status(ch, &val); + if (val & 1) + break; + usleep(100000); + } + + if (!(val & 1)) + { + fprintf(stderr, "Error: eye scan did not finish (%d)\n", val); + return -1; + } + + gtye3_ch_set_es_control(ch, 0x00); + + gtye3_ch_get_es_error_count(ch, &error_count); + gtye3_ch_get_es_sample_count(ch, &sample_count); + bit_count = ((uint64_t)sample_count * (uint64_t)priv->rx_int_data_width) << (1+4); + + ber = (float)error_count / (float)bit_count; + + if (ber < 0.01) + break; + + printf("High BER (%02f), resetting eye scan logic\n", ber); + + gtye3_ch_set_es_horz_offset(ch, 0x880); + gtye3_ch_set_eyescan_reset(ch, 1); + gtye3_ch_set_es_horz_offset(ch, 0x800); + gtye3_ch_set_eyescan_reset(ch, 0); + } + + if (ber > 0.01) + { + fprintf(stderr, "Error: High BER, alignment failed\n"); + return -1; + } + + // set up for measurement + priv->h_offset = priv->h_start; + priv->v_offset = priv->v_start; + priv->ut_sign = 0; + + gtye3_ch_set_es_control(ch, 0x00); + gtye3_ch_set_es_prescale(ch, priv->prescale); + gtye3_ch_set_es_errdet_en(ch, 1); + gtye3_ch_set_es_horz_offset(ch, (priv->h_offset & 0x7ff) | 0x800); + gtye3_ch_set_rx_eyescan_vs_neg_dir(ch, (priv->v_offset < 0)); + gtye3_ch_set_rx_eyescan_vs_code(ch, priv->v_offset < 0 ? -priv->v_offset : priv->v_offset); + gtye3_ch_set_rx_eyescan_vs_ut_sign(ch, priv->ut_sign); + + // start measurement + gtye3_ch_set_es_control(ch, 0x01); + + priv->eyescan_running = 1; + + return 0; +} + +static int gtye3_ch_eyescan_step(struct gt_ch *ch, struct gt_eyescan_point *point) +{ + struct gtye3_ch_priv *priv = ch->priv; + uint32_t val; + + uint32_t error_count; + uint32_t sample_count; + uint64_t bit_count; + + int restart = 0; + + if (!priv->eyescan_running) + return 0; + + gtye3_ch_get_es_control_status(ch, &val); + if (!(val & 1)) + return 2; + + gtye3_ch_set_es_control(ch, 0x00); + + gtye3_ch_get_es_error_count(ch, &error_count); + gtye3_ch_get_es_sample_count(ch, &sample_count); + bit_count = ((uint64_t)sample_count * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale); + + point->error_count = error_count; + point->bit_count = bit_count; + point->x = priv->h_offset; + point->y = priv->v_offset; + point->ut_sign = priv->ut_sign; + + restart = 0; + + if (!priv->ut_sign && priv->dfe_en) + { + priv->ut_sign = 1; + restart = 1; + } + else + { + priv->ut_sign = 0; + } + + gtye3_ch_set_rx_eyescan_vs_ut_sign(ch, priv->ut_sign); + + if (restart) + { + gtye3_ch_set_es_control(ch, 0x01); + return 1; + } + + if (priv->v_offset < priv->v_stop) + { + priv->v_offset += priv->v_step; + restart = 1; + } + else + { + priv->v_offset = priv->v_start; + } + + gtye3_ch_set_rx_eyescan_vs_neg_dir(ch, (priv->v_offset < 0)); + gtye3_ch_set_rx_eyescan_vs_code(ch, priv->v_offset < 0 ? -priv->v_offset : priv->v_offset); + + if (restart) + { + gtye3_ch_set_es_control(ch, 0x01); + return 1; + } + + if (priv->h_offset < priv->h_stop) + { + priv->h_offset += priv->h_step; + restart = 1; + } + else + { + // done + priv->eyescan_running = 0; + return 1; + } + + gtye3_ch_set_es_horz_offset(ch, (priv->h_offset & 0x7ff) | 0x800); + + if (restart) + { + gtye3_ch_set_es_control(ch, 0x01); + return 1; + } + + priv->eyescan_running = 0; + return 0; +} + +const struct gt_ch_ops gtye3_gt_ch_ops = { + .get_tx_reset = gtye3_ch_get_tx_reset, + .set_tx_reset = gtye3_ch_set_tx_reset, + .tx_reset = gtye3_ch_tx_reset, + .get_rx_reset = gtye3_ch_get_rx_reset, + .set_rx_reset = gtye3_ch_set_rx_reset, + .rx_reset = gtye3_ch_rx_reset, + .get_tx_data_width = gtye3_ch_get_tx_data_width, + .get_tx_int_data_width = gtye3_ch_get_tx_int_data_width, + .get_rx_data_width = gtye3_ch_get_rx_data_width, + .get_rx_int_data_width = gtye3_ch_get_rx_int_data_width, + .get_available_presets = gtye3_ch_get_available_presets, + .load_preset = gtye3_ch_load_preset, + .eyescan_start = gtye3_ch_eyescan_start, + .eyescan_step = gtye3_ch_eyescan_step +}; + +static int gtye3_ch_init(struct gt_ch *ch) +{ + struct gtye3_ch_priv *priv = calloc(1, sizeof(struct gtye3_ch_priv)); + if (!priv) + return -1; + + ch->priv = priv; + + return 0; +} + +int gtye3_quad_init(struct gt_quad *quad) +{ + uint32_t val; + struct gtye3_quad_priv *priv = calloc(1, sizeof(struct gtye3_quad_priv)); + if (!priv) + return -1; + + quad->priv = priv; + quad->type = "GTYE3"; + + gtye3_pll_get_qpll0clkout_rate(&quad->pll, &val); + priv->qpll0_25g = val == GTYE3_COM_QPLL0CLKOUT_RATE_FULL; + + for (int n = 0; n < quad->ch_count; n++) + { + quad->ch[n].quad = quad; + quad->ch[n].pll = &quad->pll; + quad->ch[n].ops = >ye3_gt_ch_ops; + quad->ch[n].index = n; + + gtye3_ch_init(&quad->ch[n]); + } + + return 0; +} + +const struct gt_quad_ops gtye3_gt_quad_ops = { + .init = gtye3_quad_init +}; diff --git a/utils/xcvr_gtye3.h b/utils/xcvr_gtye3.h new file mode 100644 index 0000000..1f7d9fc --- /dev/null +++ b/utils/xcvr_gtye3.h @@ -0,0 +1,374 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#ifndef XCVR_GTYE3_H +#define XCVR_GTYE3_H + +#include "xcvr_gt.h" +#include "gt/gtye3_regs.h" + +// signals +#define GTYE3_COM_QPLL0_RESET_ADDR 0x10000 +#define GTYE3_COM_QPLL0_RESET_MSB 0 +#define GTYE3_COM_QPLL0_RESET_LSB 0 +#define GTYE3_COM_QPLL0_RESET_MASK BIT_MASK(GTYE3_COM_QPLL0_RESET_MSB, GTYE3_COM_QPLL0_RESET_LSB) +#define GTYE3_COM_QPLL0_LOCK_ADDR 0x10000 +#define GTYE3_COM_QPLL0_LOCK_MSB 8 +#define GTYE3_COM_QPLL0_LOCK_LSB 8 +#define GTYE3_COM_QPLL0_LOCK_MASK BIT_MASK(GTYE3_COM_QPLL0_LOCK_MSB, GTYE3_COM_QPLL0_LOCK_LSB) +#define GTYE3_COM_QPLL0_PD_ADDR 0x10001 +#define GTYE3_COM_QPLL0_PD_MSB 0 +#define GTYE3_COM_QPLL0_PD_LSB 0 +#define GTYE3_COM_QPLL0_PD_MASK BIT_MASK(GTYE3_COM_QPLL0_PD_MSB, GTYE3_COM_QPLL0_PD_LSB) +#define GTYE3_COM_QPLL1_RESET_ADDR 0x11000 +#define GTYE3_COM_QPLL1_RESET_MSB 0 +#define GTYE3_COM_QPLL1_RESET_LSB 0 +#define GTYE3_COM_QPLL1_RESET_MASK BIT_MASK(GTYE3_COM_QPLL0_RESET_MSB, GTYE3_COM_QPLL0_RESET_LSB) +#define GTYE3_COM_QPLL1_LOCK_ADDR 0x11000 +#define GTYE3_COM_QPLL1_LOCK_MSB 8 +#define GTYE3_COM_QPLL1_LOCK_LSB 8 +#define GTYE3_COM_QPLL1_LOCK_MASK BIT_MASK(GTYE3_COM_QPLL0_LOCK_MSB, GTYE3_COM_QPLL0_LOCK_LSB) +#define GTYE3_COM_QPLL1_PD_ADDR 0x11001 +#define GTYE3_COM_QPLL1_PD_MSB 0 +#define GTYE3_COM_QPLL1_PD_LSB 0 +#define GTYE3_COM_QPLL1_PD_MASK BIT_MASK(GTYE3_COM_QPLL1_PD_MSB, GTYE3_COM_QPLL1_PD_LSB) + +#define GTYE3_CH_TX_RESET_ADDR 0x10000 +#define GTYE3_CH_TX_RESET_MSB 0 +#define GTYE3_CH_TX_RESET_LSB 0 +#define GTYE3_CH_TX_RESET_MASK BIT_MASK(GTYE3_CH_TX_RESET_MSB, GTYE3_CH_TX_RESET_LSB) +#define GTYE3_CH_TX_PMA_RESET_ADDR 0x10000 +#define GTYE3_CH_TX_PMA_RESET_MSB 1 +#define GTYE3_CH_TX_PMA_RESET_LSB 1 +#define GTYE3_CH_TX_PMA_RESET_MASK BIT_MASK(GTYE3_CH_TX_PMA_RESET_MSB, GTYE3_CH_TX_PMA_RESET_LSB) +#define GTYE3_CH_TX_PCS_RESET_ADDR 0x10000 +#define GTYE3_CH_TX_PCS_RESET_MSB 2 +#define GTYE3_CH_TX_PCS_RESET_LSB 2 +#define GTYE3_CH_TX_PCS_RESET_MASK BIT_MASK(GTYE3_CH_TX_PCS_RESET_MSB, GTYE3_CH_TX_PCS_RESET_LSB) +#define GTYE3_CH_TX_RESET_DONE_ADDR 0x10000 +#define GTYE3_CH_TX_RESET_DONE_MSB 8 +#define GTYE3_CH_TX_RESET_DONE_LSB 8 +#define GTYE3_CH_TX_RESET_DONE_MASK BIT_MASK(GTYE3_CH_TX_RESET_DONE_MSB, GTYE3_CH_TX_RESET_DONE_LSB) +#define GTYE3_CH_TX_GT_RESET_DONE_ADDR 0x10000 +#define GTYE3_CH_TX_GT_RESET_DONE_MSB 9 +#define GTYE3_CH_TX_GT_RESET_DONE_LSB 9 +#define GTYE3_CH_TX_GT_RESET_DONE_MASK BIT_MASK(GTYE3_CH_TX_GT_RESET_DONE_MSB, GTYE3_CH_TX_GT_RESET_DONE_LSB) +#define GTYE3_CH_TX_PMA_RESET_DONE_ADDR 0x10000 +#define GTYE3_CH_TX_PMA_RESET_DONE_MSB 10 +#define GTYE3_CH_TX_PMA_RESET_DONE_LSB 10 +#define GTYE3_CH_TX_PMA_RESET_DONE_MASK BIT_MASK(GTYE3_CH_TX_PMA_RESET_DONE_MSB, GTYE3_CH_TX_PMA_RESET_DONE_LSB) +#define GTYE3_CH_TX_PRGDIV_RESET_DONE_ADDR 0x10000 +#define GTYE3_CH_TX_PRGDIV_RESET_DONE_MSB 11 +#define GTYE3_CH_TX_PRGDIV_RESET_DONE_LSB 11 +#define GTYE3_CH_TX_PRGDIV_RESET_DONE_MASK BIT_MASK(GTYE3_CH_TX_PRGDIV_RESET_DONE_MSB, GTYE3_CH_TX_PRGDIV_RESET_DONE_LSB) +#define GTYE3_CH_TX_USRCLK_ACT_ADDR 0x10000 +#define GTYE3_CH_TX_USRCLK_ACT_MSB 12 +#define GTYE3_CH_TX_USRCLK_ACT_LSB 12 +#define GTYE3_CH_TX_USRCLK_ACT_MASK BIT_MASK(GTYE3_CH_TX_USRCLK_ACT_MSB, GTYE3_CH_TX_USRCLK_ACT_LSB) +#define GTYE3_CH_TX_PD_ADDR 0x10001 +#define GTYE3_CH_TX_PD_MSB 0 +#define GTYE3_CH_TX_PD_LSB 0 +#define GTYE3_CH_TX_PD_MASK BIT_MASK(GTYE3_CH_TX_PD_MSB, GTYE3_CH_TX_PD_LSB) +#define GTYE3_CH_TX_QPLL_SEL_ADDR 0x10001 +#define GTYE3_CH_TX_QPLL_SEL_MSB 1 +#define GTYE3_CH_TX_QPLL_SEL_LSB 1 +#define GTYE3_CH_TX_QPLL_SEL_MASK BIT_MASK(GTYE3_CH_TX_QPLL_SEL_MSB, GTYE3_CH_TX_QPLL_SEL_LSB) +#define GTYE3_CH_TX_POLARITY_ADDR 0x10010 +#define GTYE3_CH_TX_POLARITY_MSB 0 +#define GTYE3_CH_TX_POLARITY_LSB 0 +#define GTYE3_CH_TX_POLARITY_MASK BIT_MASK(GTYE3_CH_TX_POLARITY_MSB, GTYE3_CH_TX_POLARITY_LSB) +#define GTYE3_CH_TX_ELECIDLE_ADDR 0x10010 +#define GTYE3_CH_TX_ELECIDLE_MSB 1 +#define GTYE3_CH_TX_ELECIDLE_LSB 1 +#define GTYE3_CH_TX_ELECIDLE_MASK BIT_MASK(GTYE3_CH_TX_ELECIDLE_MSB, GTYE3_CH_TX_ELECIDLE_LSB) +#define GTYE3_CH_TX_INHIBIT_ADDR 0x10010 +#define GTYE3_CH_TX_INHIBIT_MSB 2 +#define GTYE3_CH_TX_INHIBIT_LSB 2 +#define GTYE3_CH_TX_INHIBIT_MASK BIT_MASK(GTYE3_CH_TX_INHIBIT_MSB, GTYE3_CH_TX_INHIBIT_LSB) +#define GTYE3_CH_TX_DIFFCTRL_ADDR 0x10011 +#define GTYE3_CH_TX_DIFFCTRL_MSB 4 +#define GTYE3_CH_TX_DIFFCTRL_LSB 0 +#define GTYE3_CH_TX_DIFFCTRL_MASK BIT_MASK(GTYE3_CH_TX_DIFFCTRL_MSB, GTYE3_CH_TX_DIFFCTRL_LSB) +#define GTYE3_CH_TX_MAINCURSOR_ADDR 0x10012 +#define GTYE3_CH_TX_MAINCURSOR_MSB 6 +#define GTYE3_CH_TX_MAINCURSOR_LSB 0 +#define GTYE3_CH_TX_MAINCURSOR_MASK BIT_MASK(GTYE3_CH_TX_MAINCURSOR_MSB, GTYE3_CH_TX_MAINCURSOR_LSB) +#define GTYE3_CH_TX_PRECURSOR_ADDR 0x10013 +#define GTYE3_CH_TX_PRECURSOR_MSB 4 +#define GTYE3_CH_TX_PRECURSOR_LSB 0 +#define GTYE3_CH_TX_PRECURSOR_MASK BIT_MASK(GTYE3_CH_TX_PRECURSOR_MSB, GTYE3_CH_TX_PRECURSOR_LSB) +#define GTYE3_CH_TX_POSTCURSOR_ADDR 0x10014 +#define GTYE3_CH_TX_POSTCURSOR_MSB 4 +#define GTYE3_CH_TX_POSTCURSOR_LSB 0 +#define GTYE3_CH_TX_POSTCURSOR_MASK BIT_MASK(GTYE3_CH_TX_POSTCURSOR_MSB, GTYE3_CH_TX_POSTCURSOR_LSB) +#define GTYE3_CH_TX_PRBS_SEL_ADDR 0x10040 +#define GTYE3_CH_TX_PRBS_SEL_MSB 3 +#define GTYE3_CH_TX_PRBS_SEL_LSB 0 +#define GTYE3_CH_TX_PRBS_SEL_MASK BIT_MASK(GTYE3_CH_TX_PRBS_SEL_MSB, GTYE3_CH_TX_PRBS_SEL_LSB) +#define GTYE3_CH_TX_PRBS_FORCERR_ADDR 0x10040 +#define GTYE3_CH_TX_PRBS_FORCERR_MSB 15 +#define GTYE3_CH_TX_PRBS_FORCERR_LSB 0 +#define GTYE3_CH_TX_PRBS_FORCERR_MASK BIT_MASK(GTYE3_CH_TX_PRBS_FORCERR_MSB, GTYE3_CH_TX_PRBS_FORCERR_LSB) +#define GTYE3_CH_RX_RESET_ADDR 0x11000 +#define GTYE3_CH_RX_RESET_MSB 0 +#define GTYE3_CH_RX_RESET_LSB 0 +#define GTYE3_CH_RX_RESET_MASK BIT_MASK(GTYE3_CH_RX_RESET_MSB, GTYE3_CH_RX_RESET_LSB) +#define GTYE3_CH_RX_PMA_RESET_ADDR 0x11000 +#define GTYE3_CH_RX_PMA_RESET_MSB 1 +#define GTYE3_CH_RX_PMA_RESET_LSB 1 +#define GTYE3_CH_RX_PMA_RESET_MASK BIT_MASK(GTYE3_CH_RX_PMA_RESET_MSB, GTYE3_CH_RX_PMA_RESET_LSB) +#define GTYE3_CH_RX_PCS_RESET_ADDR 0x11000 +#define GTYE3_CH_RX_PCS_RESET_MSB 2 +#define GTYE3_CH_RX_PCS_RESET_LSB 2 +#define GTYE3_CH_RX_PCS_RESET_MASK BIT_MASK(GTYE3_CH_RX_PCS_RESET_MSB, GTYE3_CH_RX_PCS_RESET_LSB) +#define GTYE3_CH_RX_DFE_LPM_RESET_ADDR 0x11000 +#define GTYE3_CH_RX_DFE_LPM_RESET_MSB 3 +#define GTYE3_CH_RX_DFE_LPM_RESET_LSB 3 +#define GTYE3_CH_RX_DFE_LPM_RESET_MASK BIT_MASK(GTYE3_CH_RX_DFE_LPM_RESET_MSB, GTYE3_CH_RX_DFE_LPM_RESET_LSB) +#define GTYE3_CH_EYESCAN_RESET_ADDR 0x11000 +#define GTYE3_CH_EYESCAN_RESET_MSB 4 +#define GTYE3_CH_EYESCAN_RESET_LSB 4 +#define GTYE3_CH_EYESCAN_RESET_MASK BIT_MASK(GTYE3_CH_EYESCAN_RESET_MSB, GTYE3_CH_EYESCAN_RESET_LSB) +#define GTYE3_CH_RX_RESET_DONE_ADDR 0x11000 +#define GTYE3_CH_RX_RESET_DONE_MSB 8 +#define GTYE3_CH_RX_RESET_DONE_LSB 8 +#define GTYE3_CH_RX_RESET_DONE_MASK BIT_MASK(GTYE3_CH_RX_RESET_DONE_MSB, GTYE3_CH_RX_RESET_DONE_LSB) +#define GTYE3_CH_RX_GT_RESET_DONE_ADDR 0x11000 +#define GTYE3_CH_RX_GT_RESET_DONE_MSB 9 +#define GTYE3_CH_RX_GT_RESET_DONE_LSB 9 +#define GTYE3_CH_RX_GT_RESET_DONE_MASK BIT_MASK(GTYE3_CH_RX_GT_RESET_DONE_MSB, GTYE3_CH_RX_GT_RESET_DONE_LSB) +#define GTYE3_CH_RX_PMA_RESET_DONE_ADDR 0x11000 +#define GTYE3_CH_RX_PMA_RESET_DONE_MSB 10 +#define GTYE3_CH_RX_PMA_RESET_DONE_LSB 10 +#define GTYE3_CH_RX_PMA_RESET_DONE_MASK BIT_MASK(GTYE3_CH_RX_PMA_RESET_DONE_MSB, GTYE3_CH_RX_PMA_RESET_DONE_LSB) +#define GTYE3_CH_RX_PRGDIV_RESET_DONE_ADDR 0x11000 +#define GTYE3_CH_RX_PRGDIV_RESET_DONE_MSB 11 +#define GTYE3_CH_RX_PRGDIV_RESET_DONE_LSB 11 +#define GTYE3_CH_RX_PRGDIV_RESET_DONE_MASK BIT_MASK(GTYE3_CH_RX_PRGDIV_RESET_DONE_MSB, GTYE3_CH_RX_PRGDIV_RESET_DONE_LSB) +#define GTYE3_CH_RX_USRCLK_ACT_ADDR 0x11000 +#define GTYE3_CH_RX_USRCLK_ACT_MSB 12 +#define GTYE3_CH_RX_USRCLK_ACT_LSB 12 +#define GTYE3_CH_RX_USRCLK_ACT_MASK BIT_MASK(GTYE3_CH_RX_USRCLK_ACT_MSB, GTYE3_CH_RX_USRCLK_ACT_LSB) +#define GTYE3_CH_RX_PD_ADDR 0x11001 +#define GTYE3_CH_RX_PD_MSB 0 +#define GTYE3_CH_RX_PD_LSB 0 +#define GTYE3_CH_RX_PD_MASK BIT_MASK(GTYE3_CH_RX_PD_MSB, GTYE3_CH_RX_PD_LSB) +#define GTYE3_CH_RX_QPLL_SEL_ADDR 0x11001 +#define GTYE3_CH_RX_QPLL_SEL_MSB 1 +#define GTYE3_CH_RX_QPLL_SEL_LSB 1 +#define GTYE3_CH_RX_QPLL_SEL_MASK BIT_MASK(GTYE3_CH_RX_QPLL_SEL_MSB, GTYE3_CH_RX_QPLL_SEL_LSB) +#define GTYE3_CH_LOOPBACK_ADDR 0x11002 +#define GTYE3_CH_LOOPBACK_MSB 2 +#define GTYE3_CH_LOOPBACK_LSB 0 +#define GTYE3_CH_LOOPBACK_MASK BIT_MASK(GTYE3_CH_LOOPBACK_MSB, GTYE3_CH_LOOPBACK_LSB) +#define GTYE3_CH_RX_POLARITY_ADDR 0x11010 +#define GTYE3_CH_RX_POLARITY_MSB 0 +#define GTYE3_CH_RX_POLARITY_LSB 0 +#define GTYE3_CH_RX_POLARITY_MASK BIT_MASK(GTYE3_CH_RX_POLARITY_MSB, GTYE3_CH_RX_POLARITY_LSB) +#define GTYE3_CH_RX_CDR_HOLD_ADDR 0x11020 +#define GTYE3_CH_RX_CDR_HOLD_MSB 0 +#define GTYE3_CH_RX_CDR_HOLD_LSB 0 +#define GTYE3_CH_RX_CDR_HOLD_MASK BIT_MASK(GTYE3_CH_RX_CDR_HOLD_MSB, GTYE3_CH_RX_CDR_HOLD_LSB) +#define GTYE3_CH_RX_CDR_LOCK_ADDR 0x11020 +#define GTYE3_CH_RX_CDR_LOCK_MSB 8 +#define GTYE3_CH_RX_CDR_LOCK_LSB 8 +#define GTYE3_CH_RX_CDR_LOCK_MASK BIT_MASK(GTYE3_CH_RX_CDR_LOCK_MSB, GTYE3_CH_RX_CDR_LOCK_LSB) +#define GTYE3_CH_RX_LPM_EN_ADDR 0x11024 +#define GTYE3_CH_RX_LPM_EN_MSB 0 +#define GTYE3_CH_RX_LPM_EN_LSB 0 +#define GTYE3_CH_RX_LPM_EN_MASK BIT_MASK(GTYE3_CH_RX_LPM_EN_MSB, GTYE3_CH_RX_LPM_EN_LSB) +#define GTYE3_CH_RX_DMONITOR_ADDR 0x11028 +#define GTYE3_CH_RX_DMONITOR_MSB 7 +#define GTYE3_CH_RX_DMONITOR_LSB 0 +#define GTYE3_CH_RX_DMONITOR_MASK BIT_MASK(GTYE3_CH_RX_DMONITOR_MSB, GTYE3_CH_RX_DMONITOR_LSB) +#define GTYE3_CH_RX_PRBS_SEL_ADDR 0x11040 +#define GTYE3_CH_RX_PRBS_SEL_MSB 3 +#define GTYE3_CH_RX_PRBS_SEL_LSB 0 +#define GTYE3_CH_RX_PRBS_SEL_MASK BIT_MASK(GTYE3_CH_RX_PRBS_SEL_MSB, GTYE3_CH_RX_PRBS_SEL_LSB) +#define GTYE3_CH_RX_PRBS_CNT_RESET_ADDR 0x11041 +#define GTYE3_CH_RX_PRBS_CNT_RESET_MSB 0 +#define GTYE3_CH_RX_PRBS_CNT_RESET_LSB 0 +#define GTYE3_CH_RX_PRBS_CNT_RESET_MASK BIT_MASK(GTYE3_CH_RX_PRBS_CNT_RESET_MSB, GTYE3_CH_RX_PRBS_CNT_RESET_LSB) +#define GTYE3_CH_RX_PRBS_LOCKED_ADDR 0x11041 +#define GTYE3_CH_RX_PRBS_LOCKED_MSB 8 +#define GTYE3_CH_RX_PRBS_LOCKED_LSB 8 +#define GTYE3_CH_RX_PRBS_LOCKED_MASK BIT_MASK(GTYE3_CH_RX_PRBS_LOCKED_MSB, GTYE3_CH_RX_PRBS_LOCKED_LSB) +#define GTYE3_CH_RX_PRBS_ERROR_ADDR 0x11041 +#define GTYE3_CH_RX_PRBS_ERROR_MSB 9 +#define GTYE3_CH_RX_PRBS_ERROR_LSB 9 +#define GTYE3_CH_RX_PRBS_ERROR_MASK BIT_MASK(GTYE3_CH_RX_PRBS_ERROR_MSB, GTYE3_CH_RX_PRBS_ERROR_LSB) + + +def_gt_pll_masked_reg_rw16(gtye3, qpll0_reset, GTYE3_COM_QPLL0_RESET_ADDR, GTYE3_COM_QPLL0_RESET_MASK, GTYE3_COM_QPLL0_RESET_LSB); +int gtye3_pll_qpll0_reset(struct gt_pll *pll); +def_gt_pll_masked_reg_read16(gtye3, qpll0_lock, GTYE3_COM_QPLL0_LOCK_ADDR, GTYE3_COM_QPLL0_LOCK_MASK, GTYE3_COM_QPLL0_LOCK_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_pd, GTYE3_COM_QPLL0_PD_ADDR, GTYE3_COM_QPLL0_PD_MASK, GTYE3_COM_QPLL0_PD_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_reset, GTYE3_COM_QPLL1_RESET_ADDR, GTYE3_COM_QPLL1_RESET_MASK, GTYE3_COM_QPLL1_RESET_LSB); +int gtye3_pll_qpll1_reset(struct gt_pll *pll); +def_gt_pll_masked_reg_read16(gtye3, qpll1_lock, GTYE3_COM_QPLL1_LOCK_ADDR, GTYE3_COM_QPLL1_LOCK_MASK, GTYE3_COM_QPLL1_LOCK_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_pd, GTYE3_COM_QPLL1_PD_ADDR, GTYE3_COM_QPLL1_PD_MASK, GTYE3_COM_QPLL1_PD_LSB); + +def_gt_ch_masked_reg_rw16(gtye3, tx_reset, GTYE3_CH_TX_RESET_ADDR, GTYE3_CH_TX_RESET_MASK, GTYE3_CH_TX_RESET_LSB); +int gtye3_ch_tx_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye3, tx_pma_reset, GTYE3_CH_TX_PMA_RESET_ADDR, GTYE3_CH_TX_PMA_RESET_MASK, GTYE3_CH_TX_PMA_RESET_LSB); +int gtye3_ch_tx_pma_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye3, tx_pcs_reset, GTYE3_CH_TX_PCS_RESET_ADDR, GTYE3_CH_TX_PCS_RESET_MASK, GTYE3_CH_TX_PCS_RESET_LSB); +int gtye3_ch_tx_pcs_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_read16(gtye3, tx_reset_done, GTYE3_CH_TX_RESET_DONE_ADDR, GTYE3_CH_TX_RESET_DONE_MASK, GTYE3_CH_TX_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye3, tx_gt_reset_done, GTYE3_CH_TX_GT_RESET_DONE_ADDR, GTYE3_CH_TX_GT_RESET_DONE_MASK, GTYE3_CH_TX_GT_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye3, tx_pma_reset_done, GTYE3_CH_TX_PMA_RESET_DONE_ADDR, GTYE3_CH_TX_PMA_RESET_DONE_MASK, GTYE3_CH_TX_PMA_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye3, tx_prgdiv_reset_done, GTYE3_CH_TX_PRGDIV_RESET_DONE_ADDR, GTYE3_CH_TX_PRGDIV_RESET_DONE_MASK, GTYE3_CH_TX_PRGDIV_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye3, tx_usrclk_act, GTYE3_CH_TX_USRCLK_ACT_ADDR, GTYE3_CH_TX_USRCLK_ACT_MASK, GTYE3_CH_TX_USRCLK_ACT_LSB); +def_gt_ch_masked_reg_rw16(gtye3, tx_pd, GTYE3_CH_TX_PD_ADDR, GTYE3_CH_TX_PD_MASK, GTYE3_CH_TX_PD_LSB); +def_gt_ch_masked_reg_rw16(gtye3, tx_qpll_sel, GTYE3_CH_TX_QPLL_SEL_ADDR, GTYE3_CH_TX_QPLL_SEL_MASK, GTYE3_CH_TX_QPLL_SEL_LSB); +def_gt_ch_masked_reg_rw16(gtye3, tx_polarity, GTYE3_CH_TX_POLARITY_ADDR, GTYE3_CH_TX_POLARITY_MASK, GTYE3_CH_TX_POLARITY_LSB); +def_gt_ch_masked_reg_rw16(gtye3, tx_elecidle, GTYE3_CH_TX_ELECIDLE_ADDR, GTYE3_CH_TX_ELECIDLE_MASK, GTYE3_CH_TX_ELECIDLE_LSB); +def_gt_ch_masked_reg_rw16(gtye3, tx_inhibit, GTYE3_CH_TX_INHIBIT_ADDR, GTYE3_CH_TX_INHIBIT_MASK, GTYE3_CH_TX_INHIBIT_LSB); +def_gt_ch_masked_reg_rw16(gtye3, tx_diffctrl, GTYE3_CH_TX_DIFFCTRL_ADDR, GTYE3_CH_TX_DIFFCTRL_MASK, GTYE3_CH_TX_DIFFCTRL_LSB); +def_gt_ch_masked_reg_rw16(gtye3, tx_maincursor, GTYE3_CH_TX_MAINCURSOR_ADDR, GTYE3_CH_TX_MAINCURSOR_MASK, GTYE3_CH_TX_MAINCURSOR_LSB); +def_gt_ch_masked_reg_rw16(gtye3, tx_precursor, GTYE3_CH_TX_PRECURSOR_ADDR, GTYE3_CH_TX_PRECURSOR_MASK, GTYE3_CH_TX_PRECURSOR_LSB); +def_gt_ch_masked_reg_rw16(gtye3, tx_postcursor, GTYE3_CH_TX_POSTCURSOR_ADDR, GTYE3_CH_TX_POSTCURSOR_MASK, GTYE3_CH_TX_POSTCURSOR_LSB); +def_gt_ch_masked_reg_rw16(gtye3, tx_prbs_sel, GTYE3_CH_TX_PRBS_SEL_ADDR, GTYE3_CH_TX_PRBS_SEL_MASK, GTYE3_CH_TX_PRBS_SEL_LSB); +def_gt_ch_masked_reg_rw16(gtye3, tx_prbs_forcerr, GTYE3_CH_TX_PRBS_FORCERR_ADDR, GTYE3_CH_TX_PRBS_FORCERR_MASK, GTYE3_CH_TX_PRBS_FORCERR_LSB); + +def_gt_ch_masked_reg_rw16(gtye3, rx_reset, GTYE3_CH_RX_RESET_ADDR, GTYE3_CH_RX_RESET_MASK, GTYE3_CH_RX_RESET_LSB); +int gtye3_ch_rx_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye3, rx_pma_reset, GTYE3_CH_RX_PMA_RESET_ADDR, GTYE3_CH_RX_PMA_RESET_MASK, GTYE3_CH_RX_PMA_RESET_LSB); +int gtye3_ch_rx_pma_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye3, rx_pcs_reset, GTYE3_CH_RX_PCS_RESET_ADDR, GTYE3_CH_RX_PCS_RESET_MASK, GTYE3_CH_RX_PCS_RESET_LSB); +int gtye3_ch_rx_pcs_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye3, rx_dfe_lpm_reset, GTYE3_CH_RX_DFE_LPM_RESET_ADDR, GTYE3_CH_RX_DFE_LPM_RESET_MASK, GTYE3_CH_RX_DFE_LPM_RESET_LSB); +int gtye3_ch_rx_dfe_lpm_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye3, eyescan_reset, GTYE3_CH_EYESCAN_RESET_ADDR, GTYE3_CH_EYESCAN_RESET_MASK, GTYE3_CH_EYESCAN_RESET_LSB); +int gtye3_ch_eyescan_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_read16(gtye3, rx_reset_done, GTYE3_CH_RX_RESET_DONE_ADDR, GTYE3_CH_RX_RESET_DONE_MASK, GTYE3_CH_RX_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye3, rx_gt_reset_done, GTYE3_CH_RX_GT_RESET_DONE_ADDR, GTYE3_CH_RX_GT_RESET_DONE_MASK, GTYE3_CH_RX_GT_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye3, rx_pma_reset_done, GTYE3_CH_RX_PMA_RESET_DONE_ADDR, GTYE3_CH_RX_PMA_RESET_DONE_MASK, GTYE3_CH_RX_PMA_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye3, rx_prgdiv_reset_done, GTYE3_CH_RX_PRGDIV_RESET_DONE_ADDR, GTYE3_CH_RX_PRGDIV_RESET_DONE_MASK, GTYE3_CH_RX_PRGDIV_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye3, rx_usrclk_act, GTYE3_CH_RX_USRCLK_ACT_ADDR, GTYE3_CH_RX_USRCLK_ACT_MASK, GTYE3_CH_RX_USRCLK_ACT_LSB); +def_gt_ch_masked_reg_rw16(gtye3, rx_pd, GTYE3_CH_RX_PD_ADDR, GTYE3_CH_RX_PD_MASK, GTYE3_CH_RX_PD_LSB); +def_gt_ch_masked_reg_rw16(gtye3, rx_qpll_sel, GTYE3_CH_RX_QPLL_SEL_ADDR, GTYE3_CH_RX_QPLL_SEL_MASK, GTYE3_CH_RX_QPLL_SEL_LSB); +def_gt_ch_masked_reg_rw16(gtye3, loopback, GTYE3_CH_LOOPBACK_ADDR, GTYE3_CH_LOOPBACK_MASK, GTYE3_CH_LOOPBACK_LSB); +def_gt_ch_masked_reg_rw16(gtye3, rx_polarity, GTYE3_CH_RX_POLARITY_ADDR, GTYE3_CH_RX_POLARITY_MASK, GTYE3_CH_RX_POLARITY_LSB); +def_gt_ch_masked_reg_rw16(gtye3, rx_cdr_hold, GTYE3_CH_RX_CDR_HOLD_ADDR, GTYE3_CH_RX_CDR_HOLD_MASK, GTYE3_CH_RX_CDR_HOLD_LSB); +def_gt_ch_masked_reg_read16(gtye3, rx_cdr_lock, GTYE3_CH_RX_CDR_LOCK_ADDR, GTYE3_CH_RX_CDR_LOCK_MASK, GTYE3_CH_RX_CDR_LOCK_LSB); +def_gt_ch_masked_reg_rw16(gtye3, rx_lpm_en, GTYE3_CH_RX_LPM_EN_ADDR, GTYE3_CH_RX_LPM_EN_MASK, GTYE3_CH_RX_LPM_EN_LSB); +def_gt_ch_masked_reg_read16(gtye3, rx_dmonitor, GTYE3_CH_RX_DMONITOR_ADDR, GTYE3_CH_RX_DMONITOR_MASK, GTYE3_CH_RX_DMONITOR_LSB); +def_gt_ch_masked_reg_rw16(gtye3, rx_prbs_sel, GTYE3_CH_RX_PRBS_SEL_ADDR, GTYE3_CH_RX_PRBS_SEL_MASK, GTYE3_CH_RX_PRBS_SEL_LSB); +def_gt_ch_masked_reg_rw16(gtye3, rx_prbs_cnt_reset, GTYE3_CH_RX_PRBS_CNT_RESET_ADDR, GTYE3_CH_RX_PRBS_CNT_RESET_MASK, GTYE3_CH_RX_PRBS_CNT_RESET_LSB); +def_gt_ch_masked_reg_read16(gtye3, rx_prbs_locked, GTYE3_CH_RX_PRBS_LOCKED_ADDR, GTYE3_CH_RX_PRBS_LOCKED_MASK, GTYE3_CH_RX_PRBS_LOCKED_LSB); +def_gt_ch_masked_reg_read16(gtye3, rx_prbs_error, GTYE3_CH_RX_PRBS_ERROR_ADDR, GTYE3_CH_RX_PRBS_ERROR_MASK, GTYE3_CH_RX_PRBS_ERROR_LSB); + +// common +def_gt_pll_masked_reg_rw16(gtye3, qpll0_cfg0, GTYE3_COM_QPLL0_CFG0_ADDR, GTYE3_COM_QPLL0_CFG0_MASK, GTYE3_COM_QPLL0_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye3, common_cfg0, GTYE3_COM_COMMON_CFG0_ADDR, GTYE3_COM_COMMON_CFG0_MASK, GTYE3_COM_COMMON_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye3, rsvd_attr0, GTYE3_COM_RSVD_ATTR0_ADDR, GTYE3_COM_RSVD_ATTR0_MASK, GTYE3_COM_RSVD_ATTR0_LSB); +def_gt_pll_masked_reg_rw16(gtye3, ppf0_cfg, GTYE3_COM_PPF0_CFG_ADDR, GTYE3_COM_PPF0_CFG_MASK, GTYE3_COM_PPF0_CFG_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0clkout_rate, GTYE3_COM_QPLL0CLKOUT_RATE_ADDR, GTYE3_COM_QPLL0CLKOUT_RATE_MASK, GTYE3_COM_QPLL0CLKOUT_RATE_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_cfg1, GTYE3_COM_QPLL0_CFG1_ADDR, GTYE3_COM_QPLL0_CFG1_MASK, GTYE3_COM_QPLL0_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_cfg2, GTYE3_COM_QPLL0_CFG2_ADDR, GTYE3_COM_QPLL0_CFG2_MASK, GTYE3_COM_QPLL0_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_lock_cfg, GTYE3_COM_QPLL0_LOCK_CFG_ADDR, GTYE3_COM_QPLL0_LOCK_CFG_MASK, GTYE3_COM_QPLL0_LOCK_CFG_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_init_cfg0, GTYE3_COM_QPLL0_INIT_CFG0_ADDR, GTYE3_COM_QPLL0_INIT_CFG0_MASK, GTYE3_COM_QPLL0_INIT_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_init_cfg1, GTYE3_COM_QPLL0_INIT_CFG1_ADDR, GTYE3_COM_QPLL0_INIT_CFG1_MASK, GTYE3_COM_QPLL0_INIT_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_fbdiv, GTYE3_COM_QPLL0_FBDIV_ADDR, GTYE3_COM_QPLL0_FBDIV_MASK, GTYE3_COM_QPLL0_FBDIV_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_cfg3, GTYE3_COM_QPLL0_CFG3_ADDR, GTYE3_COM_QPLL0_CFG3_MASK, GTYE3_COM_QPLL0_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_cp, GTYE3_COM_QPLL0_CP_ADDR, GTYE3_COM_QPLL0_CP_MASK, GTYE3_COM_QPLL0_CP_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_refclk_div, GTYE3_COM_QPLL0_REFCLK_DIV_ADDR, GTYE3_COM_QPLL0_REFCLK_DIV_MASK, GTYE3_COM_QPLL0_REFCLK_DIV_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_ips_refclk_sel, GTYE3_COM_QPLL0_IPS_REFCLK_SEL_ADDR, GTYE3_COM_QPLL0_IPS_REFCLK_SEL_MASK, GTYE3_COM_QPLL0_IPS_REFCLK_SEL_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_ips_en, GTYE3_COM_QPLL0_IPS_EN_ADDR, GTYE3_COM_QPLL0_IPS_EN_MASK, GTYE3_COM_QPLL0_IPS_EN_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_lpf, GTYE3_COM_QPLL0_LPF_ADDR, GTYE3_COM_QPLL0_LPF_MASK, GTYE3_COM_QPLL0_LPF_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_cfg1_g3, GTYE3_COM_QPLL0_CFG1_G3_ADDR, GTYE3_COM_QPLL0_CFG1_G3_MASK, GTYE3_COM_QPLL0_CFG1_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_cfg2_g3, GTYE3_COM_QPLL0_CFG2_G3_ADDR, GTYE3_COM_QPLL0_CFG2_G3_MASK, GTYE3_COM_QPLL0_CFG2_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_lpf_g3, GTYE3_COM_QPLL0_LPF_G3_ADDR, GTYE3_COM_QPLL0_LPF_G3_MASK, GTYE3_COM_QPLL0_LPF_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_lock_cfg_g3, GTYE3_COM_QPLL0_LOCK_CFG_G3_ADDR, GTYE3_COM_QPLL0_LOCK_CFG_G3_MASK, GTYE3_COM_QPLL0_LOCK_CFG_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, rsvd_attr1, GTYE3_COM_RSVD_ATTR1_ADDR, GTYE3_COM_RSVD_ATTR1_MASK, GTYE3_COM_RSVD_ATTR1_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_fbdiv_g3, GTYE3_COM_QPLL0_FBDIV_G3_ADDR, GTYE3_COM_QPLL0_FBDIV_G3_MASK, GTYE3_COM_QPLL0_FBDIV_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, rxrecclkout0_sel, GTYE3_COM_RXRECCLKOUT0_SEL_ADDR, GTYE3_COM_RXRECCLKOUT0_SEL_MASK, GTYE3_COM_RXRECCLKOUT0_SEL_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_sdm_cfg0, GTYE3_COM_QPLL0_SDM_CFG0_ADDR, GTYE3_COM_QPLL0_SDM_CFG0_MASK, GTYE3_COM_QPLL0_SDM_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_sdm_cfg1, GTYE3_COM_QPLL0_SDM_CFG1_ADDR, GTYE3_COM_QPLL0_SDM_CFG1_MASK, GTYE3_COM_QPLL0_SDM_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye3, sdm0initseed0_0, GTYE3_COM_SDM0INITSEED0_0_ADDR, GTYE3_COM_SDM0INITSEED0_0_MASK, GTYE3_COM_SDM0INITSEED0_0_LSB); +def_gt_pll_masked_reg_rw16(gtye3, sdm0initseed0_1, GTYE3_COM_SDM0INITSEED0_1_ADDR, GTYE3_COM_SDM0INITSEED0_1_MASK, GTYE3_COM_SDM0INITSEED0_1_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_sdm_cfg2, GTYE3_COM_QPLL0_SDM_CFG2_ADDR, GTYE3_COM_QPLL0_SDM_CFG2_MASK, GTYE3_COM_QPLL0_SDM_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_cp_g3, GTYE3_COM_QPLL0_CP_G3_ADDR, GTYE3_COM_QPLL0_CP_G3_MASK, GTYE3_COM_QPLL0_CP_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll0_cfg4, GTYE3_COM_QPLL0_CFG4_ADDR, GTYE3_COM_QPLL0_CFG4_MASK, GTYE3_COM_QPLL0_CFG4_LSB); +def_gt_pll_masked_reg_rw16(gtye3, bias_cfg0, GTYE3_COM_BIAS_CFG0_ADDR, GTYE3_COM_BIAS_CFG0_MASK, GTYE3_COM_BIAS_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye3, bias_cfg1, GTYE3_COM_BIAS_CFG1_ADDR, GTYE3_COM_BIAS_CFG1_MASK, GTYE3_COM_BIAS_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye3, bias_cfg2, GTYE3_COM_BIAS_CFG2_ADDR, GTYE3_COM_BIAS_CFG2_MASK, GTYE3_COM_BIAS_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gtye3, bias_cfg3, GTYE3_COM_BIAS_CFG3_ADDR, GTYE3_COM_BIAS_CFG3_MASK, GTYE3_COM_BIAS_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, bias_cfg4, GTYE3_COM_BIAS_CFG4_ADDR, GTYE3_COM_BIAS_CFG4_MASK, GTYE3_COM_BIAS_CFG4_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_cfg0, GTYE3_COM_QPLL1_CFG0_ADDR, GTYE3_COM_QPLL1_CFG0_MASK, GTYE3_COM_QPLL1_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye3, common_cfg1, GTYE3_COM_COMMON_CFG1_ADDR, GTYE3_COM_COMMON_CFG1_MASK, GTYE3_COM_COMMON_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye3, por_cfg, GTYE3_COM_POR_CFG_ADDR, GTYE3_COM_POR_CFG_MASK, GTYE3_COM_POR_CFG_LSB); +def_gt_pll_masked_reg_rw16(gtye3, ppf1_cfg, GTYE3_COM_PPF1_CFG_ADDR, GTYE3_COM_PPF1_CFG_MASK, GTYE3_COM_PPF1_CFG_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1clkout_rate, GTYE3_COM_QPLL1CLKOUT_RATE_ADDR, GTYE3_COM_QPLL1CLKOUT_RATE_MASK, GTYE3_COM_QPLL1CLKOUT_RATE_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_cfg1, GTYE3_COM_QPLL1_CFG1_ADDR, GTYE3_COM_QPLL1_CFG1_MASK, GTYE3_COM_QPLL1_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_cfg2, GTYE3_COM_QPLL1_CFG2_ADDR, GTYE3_COM_QPLL1_CFG2_MASK, GTYE3_COM_QPLL1_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_lock_cfg, GTYE3_COM_QPLL1_LOCK_CFG_ADDR, GTYE3_COM_QPLL1_LOCK_CFG_MASK, GTYE3_COM_QPLL1_LOCK_CFG_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_init_cfg0, GTYE3_COM_QPLL1_INIT_CFG0_ADDR, GTYE3_COM_QPLL1_INIT_CFG0_MASK, GTYE3_COM_QPLL1_INIT_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_init_cfg1, GTYE3_COM_QPLL1_INIT_CFG1_ADDR, GTYE3_COM_QPLL1_INIT_CFG1_MASK, GTYE3_COM_QPLL1_INIT_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_fbdiv, GTYE3_COM_QPLL1_FBDIV_ADDR, GTYE3_COM_QPLL1_FBDIV_MASK, GTYE3_COM_QPLL1_FBDIV_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_cfg3, GTYE3_COM_QPLL1_CFG3_ADDR, GTYE3_COM_QPLL1_CFG3_MASK, GTYE3_COM_QPLL1_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_cp, GTYE3_COM_QPLL1_CP_ADDR, GTYE3_COM_QPLL1_CP_MASK, GTYE3_COM_QPLL1_CP_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_refclk_div, GTYE3_COM_QPLL1_REFCLK_DIV_ADDR, GTYE3_COM_QPLL1_REFCLK_DIV_MASK, GTYE3_COM_QPLL1_REFCLK_DIV_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_ips_refclk_sel, GTYE3_COM_QPLL1_IPS_REFCLK_SEL_ADDR, GTYE3_COM_QPLL1_IPS_REFCLK_SEL_MASK, GTYE3_COM_QPLL1_IPS_REFCLK_SEL_LSB); +def_gt_pll_masked_reg_rw16(gtye3, sarc_en, GTYE3_COM_SARC_EN_ADDR, GTYE3_COM_SARC_EN_MASK, GTYE3_COM_SARC_EN_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_ips_en, GTYE3_COM_QPLL1_IPS_EN_ADDR, GTYE3_COM_QPLL1_IPS_EN_MASK, GTYE3_COM_QPLL1_IPS_EN_LSB); +def_gt_pll_masked_reg_rw16(gtye3, sarc_sel, GTYE3_COM_SARC_SEL_ADDR, GTYE3_COM_SARC_SEL_MASK, GTYE3_COM_SARC_SEL_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_lpf, GTYE3_COM_QPLL1_LPF_ADDR, GTYE3_COM_QPLL1_LPF_MASK, GTYE3_COM_QPLL1_LPF_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_cfg1_g3, GTYE3_COM_QPLL1_CFG1_G3_ADDR, GTYE3_COM_QPLL1_CFG1_G3_MASK, GTYE3_COM_QPLL1_CFG1_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_cfg2_g3, GTYE3_COM_QPLL1_CFG2_G3_ADDR, GTYE3_COM_QPLL1_CFG2_G3_MASK, GTYE3_COM_QPLL1_CFG2_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_lpf_g3, GTYE3_COM_QPLL1_LPF_G3_ADDR, GTYE3_COM_QPLL1_LPF_G3_MASK, GTYE3_COM_QPLL1_LPF_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_lock_cfg_g3, GTYE3_COM_QPLL1_LOCK_CFG_G3_ADDR, GTYE3_COM_QPLL1_LOCK_CFG_G3_MASK, GTYE3_COM_QPLL1_LOCK_CFG_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, rsvd_attr2, GTYE3_COM_RSVD_ATTR2_ADDR, GTYE3_COM_RSVD_ATTR2_MASK, GTYE3_COM_RSVD_ATTR2_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_fbdiv_g3, GTYE3_COM_QPLL1_FBDIV_G3_ADDR, GTYE3_COM_QPLL1_FBDIV_G3_MASK, GTYE3_COM_QPLL1_FBDIV_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, rxrecclkout1_sel, GTYE3_COM_RXRECCLKOUT1_SEL_ADDR, GTYE3_COM_RXRECCLKOUT1_SEL_MASK, GTYE3_COM_RXRECCLKOUT1_SEL_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_sdm_cfg0, GTYE3_COM_QPLL1_SDM_CFG0_ADDR, GTYE3_COM_QPLL1_SDM_CFG0_MASK, GTYE3_COM_QPLL1_SDM_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_sdm_cfg1, GTYE3_COM_QPLL1_SDM_CFG1_ADDR, GTYE3_COM_QPLL1_SDM_CFG1_MASK, GTYE3_COM_QPLL1_SDM_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye3, sdm1initseed0_0, GTYE3_COM_SDM1INITSEED0_0_ADDR, GTYE3_COM_SDM1INITSEED0_0_MASK, GTYE3_COM_SDM1INITSEED0_0_LSB); +def_gt_pll_masked_reg_rw16(gtye3, sdm1initseed0_1, GTYE3_COM_SDM1INITSEED0_1_ADDR, GTYE3_COM_SDM1INITSEED0_1_MASK, GTYE3_COM_SDM1INITSEED0_1_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_sdm_cfg2, GTYE3_COM_QPLL1_SDM_CFG2_ADDR, GTYE3_COM_QPLL1_SDM_CFG2_MASK, GTYE3_COM_QPLL1_SDM_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_cp_g3, GTYE3_COM_QPLL1_CP_G3_ADDR, GTYE3_COM_QPLL1_CP_G3_MASK, GTYE3_COM_QPLL1_CP_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, rsvd_attr3, GTYE3_COM_RSVD_ATTR3_ADDR, GTYE3_COM_RSVD_ATTR3_MASK, GTYE3_COM_RSVD_ATTR3_LSB); +def_gt_pll_masked_reg_rw16(gtye3, qpll1_cfg4, GTYE3_COM_QPLL1_CFG4_ADDR, GTYE3_COM_QPLL1_CFG4_MASK, GTYE3_COM_QPLL1_CFG4_LSB); + +// RX +def_gt_ch_masked_reg_rw16(gtye3, rx_data_width_raw, GTYE3_CH_RX_DATA_WIDTH_ADDR, GTYE3_CH_RX_DATA_WIDTH_MASK, GTYE3_CH_RX_DATA_WIDTH_LSB); +int gtye3_ch_get_rx_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gtye3, rx_int_data_width_raw, GTYE3_CH_RX_INT_DATAWIDTH_ADDR, GTYE3_CH_RX_INT_DATAWIDTH_MASK, GTYE3_CH_RX_INT_DATAWIDTH_LSB); +int gtye3_ch_get_rx_int_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gtye3, es_prescale, GTYE3_CH_ES_PRESCALE_ADDR, GTYE3_CH_ES_PRESCALE_MASK, GTYE3_CH_ES_PRESCALE_LSB); +def_gt_ch_masked_reg_rw16(gtye3, es_eye_scan_en, GTYE3_CH_ES_EYE_SCAN_EN_ADDR, GTYE3_CH_ES_EYE_SCAN_EN_MASK, GTYE3_CH_ES_EYE_SCAN_EN_LSB); +def_gt_ch_masked_reg_rw16(gtye3, es_errdet_en, GTYE3_CH_ES_ERRDET_EN_ADDR, GTYE3_CH_ES_ERRDET_EN_MASK, GTYE3_CH_ES_ERRDET_EN_LSB); +def_gt_ch_masked_reg_rw16(gtye3, es_control, GTYE3_CH_ES_CONTROL_ADDR, GTYE3_CH_ES_CONTROL_MASK, GTYE3_CH_ES_CONTROL_LSB); + +int gtye3_ch_set_es_qual_mask(struct gt_ch *ch, uint8_t *mask); +int gtye3_ch_set_es_qual_mask_clear(struct gt_ch *ch); + +int gtye3_ch_set_es_sdata_mask(struct gt_ch *ch, uint8_t *mask); +int gtye3_ch_set_es_sdata_mask_width(struct gt_ch *ch, int width); + +def_gt_ch_masked_reg_rw16(gtye3, es_horz_offset, GTYE3_CH_ES_HORZ_OFFSET_ADDR, GTYE3_CH_ES_HORZ_OFFSET_MASK, GTYE3_CH_ES_HORZ_OFFSET_LSB); +def_gt_ch_masked_reg_rw16(gtye3, rx_eyescan_vs_range, GTYE3_CH_RX_EYESCAN_VS_RANGE_ADDR, GTYE3_CH_RX_EYESCAN_VS_RANGE_MASK, GTYE3_CH_RX_EYESCAN_VS_RANGE_LSB); +def_gt_ch_masked_reg_rw16(gtye3, rx_eyescan_vs_code, GTYE3_CH_RX_EYESCAN_VS_CODE_ADDR, GTYE3_CH_RX_EYESCAN_VS_CODE_MASK, GTYE3_CH_RX_EYESCAN_VS_CODE_LSB); +def_gt_ch_masked_reg_rw16(gtye3, rx_eyescan_vs_ut_sign, GTYE3_CH_RX_EYESCAN_VS_UT_SIGN_ADDR, GTYE3_CH_RX_EYESCAN_VS_UT_SIGN_MASK, GTYE3_CH_RX_EYESCAN_VS_UT_SIGN_LSB); +def_gt_ch_masked_reg_rw16(gtye3, rx_eyescan_vs_neg_dir, GTYE3_CH_RX_EYESCAN_VS_NEG_DIR_ADDR, GTYE3_CH_RX_EYESCAN_VS_NEG_DIR_MASK, GTYE3_CH_RX_EYESCAN_VS_NEG_DIR_LSB); +def_gt_ch_masked_reg_read16(gtye3, es_error_count, GTYE3_CH_ES_ERROR_COUNT_ADDR, GTYE3_CH_ES_ERROR_COUNT_MASK, GTYE3_CH_ES_ERROR_COUNT_LSB); +def_gt_ch_masked_reg_read16(gtye3, es_sample_count, GTYE3_CH_ES_SAMPLE_COUNT_ADDR, GTYE3_CH_ES_SAMPLE_COUNT_MASK, GTYE3_CH_ES_SAMPLE_COUNT_LSB); +def_gt_ch_masked_reg_read16(gtye3, es_control_status, GTYE3_CH_ES_CONTROL_STATUS_ADDR, GTYE3_CH_ES_CONTROL_STATUS_MASK, GTYE3_CH_ES_CONTROL_STATUS_LSB); + +int gtye3_ch_get_rx_prbs_error_count(struct gt_ch *ch, uint32_t *val); + +// TX +def_gt_ch_masked_reg_rw16(gtye3, tx_data_width_raw, GTYE3_CH_TX_DATA_WIDTH_ADDR, GTYE3_CH_TX_DATA_WIDTH_MASK, GTYE3_CH_TX_DATA_WIDTH_LSB); +int gtye3_ch_get_tx_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gtye3, tx_int_data_width_raw, GTYE3_CH_TX_INT_DATAWIDTH_ADDR, GTYE3_CH_TX_INT_DATAWIDTH_MASK, GTYE3_CH_TX_INT_DATAWIDTH_LSB); +int gtye3_ch_get_tx_int_data_width(struct gt_ch *ch, uint32_t *val); + +extern const struct gt_quad_ops gtye3_gt_quad_ops; + +#endif /* XCVR_GTYE3_H */ diff --git a/utils/xcvr_gtye4.c b/utils/xcvr_gtye4.c new file mode 100644 index 0000000..ccac6da --- /dev/null +++ b/utils/xcvr_gtye4.c @@ -0,0 +1,789 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#include +#include +#include "xcvr_gtye4.h" + +// signals +int gtye4_pll_qpll0_reset(struct gt_pll *pll) +{ + int ret = 0; + + ret = gtye4_pll_set_qpll0_reset(pll, 1); + + if (ret) + return ret; + + return gtye4_pll_set_qpll0_reset(pll, 0); +} + +int gtye4_pll_qpll1_reset(struct gt_pll *pll) +{ + int ret = 0; + + ret = gtye4_pll_set_qpll1_reset(pll, 1); + + if (ret) + return ret; + + return gtye4_pll_set_qpll1_reset(pll, 0); +} + +int gtye4_ch_tx_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye4_ch_set_tx_reset(ch, 1); + + if (ret) + return ret; + + return gtye4_ch_set_tx_reset(ch, 0); +} + +int gtye4_ch_tx_pma_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye4_ch_set_tx_pma_reset(ch, 1); + + if (ret) + return ret; + + return gtye4_ch_set_tx_pma_reset(ch, 0); +} + +int gtye4_ch_tx_pcs_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye4_ch_set_tx_pcs_reset(ch, 1); + + if (ret) + return ret; + + return gtye4_ch_set_tx_pcs_reset(ch, 0); +} + +int gtye4_ch_rx_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye4_ch_set_rx_reset(ch, 1); + + if (ret) + return ret; + + return gtye4_ch_set_rx_reset(ch, 0); +} + +int gtye4_ch_rx_pma_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye4_ch_set_rx_pma_reset(ch, 1); + + if (ret) + return ret; + + return gtye4_ch_set_rx_pma_reset(ch, 0); +} + +int gtye4_ch_rx_pcs_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye4_ch_set_rx_pcs_reset(ch, 1); + + if (ret) + return ret; + + return gtye4_ch_set_rx_pcs_reset(ch, 0); +} + +int gtye4_ch_rx_dfe_lpm_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye4_ch_set_rx_dfe_lpm_reset(ch, 1); + + if (ret) + return ret; + + return gtye4_ch_set_rx_dfe_lpm_reset(ch, 0); +} + +int gtye4_ch_eyescan_reset(struct gt_ch *ch) +{ + int ret = 0; + + ret = gtye4_ch_set_eyescan_reset(ch, 1); + + if (ret) + return ret; + + return gtye4_ch_set_eyescan_reset(ch, 0); +} + +// RX +int gtye4_ch_get_rx_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw; + + ret = gtye4_ch_get_rx_data_width_raw(ch, &dw); + if (ret) + return ret; + + *val = (8*(1 << (dw >> 1)) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gtye4_ch_get_rx_int_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw, idw; + + ret = gtye4_ch_get_rx_data_width_raw(ch, &dw); + if (ret) + return ret; + + ret = gtye4_ch_get_rx_int_data_width_raw(ch, &idw); + if (ret) + return ret; + + *val = (16*(1 << idw) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gtye4_ch_set_es_qual_mask(struct gt_ch *ch, uint8_t *mask) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTYE4_CH_ES_QUAL_MASK0_ADDR+k, mask[2*k+0] | (mask[2*k+1] << 8)); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTYE4_CH_ES_QUAL_MASK5_ADDR+k, mask[2*k+10] | (mask[2*k+11] << 8)); + if (ret) + return ret; + } + + return 0; +} + +int gtye4_ch_set_es_qual_mask_clear(struct gt_ch *ch) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTYE4_CH_ES_QUAL_MASK0_ADDR+k, 0xffff); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTYE4_CH_ES_QUAL_MASK5_ADDR+k, 0xffff); + if (ret) + return ret; + } + + return 0; +} + +int gtye4_ch_set_es_sdata_mask(struct gt_ch *ch, uint8_t *mask) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + ret = gt_ch_reg_write(ch, GTYE4_CH_ES_SDATA_MASK0_ADDR+k, mask[2*k+0] | (mask[2*k+1] << 8)); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTYE4_CH_ES_SDATA_MASK5_ADDR+k, mask[2*k+10] | (mask[2*k+11] << 8)); + if (ret) + return ret; + } + + return 0; +} + +int gtye4_ch_set_es_sdata_mask_width(struct gt_ch *ch, int width) +{ + int ret = 0; + + for (int k = 0; k < 5; k++) + { + int shift = width - (80 - ((k+1)*16)); + uint32_t mask = 0xffff; + + if (shift < 0) + { + mask = 0xffff; + } + else if (shift > 16) + { + mask = 0x0000; + } + else + { + mask = 0xffff >> shift; + } + + ret = gt_ch_reg_write(ch, GTYE4_CH_ES_SDATA_MASK0_ADDR+k, mask); + if (ret) + return ret; + ret = gt_ch_reg_write(ch, GTYE4_CH_ES_SDATA_MASK5_ADDR+k, 0xffff); + if (ret) + return ret; + } + + return 0; +} + +int gtye4_ch_get_rx_prbs_error_count(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t v1, v2; + + ret = gt_ch_reg_read(ch, GTYE4_CH_RX_PRBS_ERR_CNT_L_ADDR | (ch->index << 17), &v1); + if (ret) + return ret; + + ret = gt_ch_reg_read(ch, GTYE4_CH_RX_PRBS_ERR_CNT_H_ADDR | (ch->index << 17), &v2); + if (ret) + return ret; + + *val = v1 | (v2 << 16); + return 0; +} + +// TX +int gtye4_ch_get_tx_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw; + + ret = gtye4_ch_get_tx_data_width_raw(ch, &dw); + if (ret) + return ret; + + *val = (8*(1 << (dw >> 1)) * (4 + (dw & 1))) >> 2; + return 0; +} + +int gtye4_ch_get_tx_int_data_width(struct gt_ch *ch, uint32_t *val) +{ + int ret = 0; + uint32_t dw, idw; + + ret = gtye4_ch_get_tx_data_width_raw(ch, &dw); + if (ret) + return ret; + + ret = gtye4_ch_get_tx_int_data_width_raw(ch, &idw); + if (ret) + return ret; + + *val = (16*(1 << idw) * (4 + (dw & 1))) >> 2; + return 0; +} + +struct gtye4_quad_priv { + int qpll0_25g; +}; + +struct gtye4_ch_priv { + uint32_t tx_data_width; + uint32_t tx_int_data_width; + uint32_t rx_data_width; + uint32_t rx_int_data_width; + int dfe_en; + + int prescale; + int h_start; + int h_stop; + int h_step; + int v_range; + int v_start; + int v_stop; + int v_step; + + int h_offset; + int v_offset; + int ut_sign; + int eyescan_running; +}; + +static const struct gt_reg_val gtye4_ch_preset_10g_baser_64_regs[] = { + {GTYE4_CH_CH_HSPMUX_ADDR, GTYE4_CH_CH_HSPMUX_MASK, GTYE4_CH_CH_HSPMUX_LSB, 0x4040}, + {GTYE4_CH_CKCAL1_CFG_0_ADDR, GTYE4_CH_CKCAL1_CFG_0_MASK, GTYE4_CH_CKCAL1_CFG_0_LSB, 0xC0C0}, + {GTYE4_CH_CKCAL1_CFG_1_ADDR, GTYE4_CH_CKCAL1_CFG_1_MASK, GTYE4_CH_CKCAL1_CFG_1_LSB, 0x10C0}, + {GTYE4_CH_CKCAL2_CFG_0_ADDR, GTYE4_CH_CKCAL2_CFG_0_MASK, GTYE4_CH_CKCAL2_CFG_0_LSB, 0xC0C0}, + {GTYE4_CH_CKCAL2_CFG_1_ADDR, GTYE4_CH_CKCAL2_CFG_1_MASK, GTYE4_CH_CKCAL2_CFG_1_LSB, 0x80C0}, + {GTYE4_CH_PREIQ_FREQ_BST_ADDR, GTYE4_CH_PREIQ_FREQ_BST_MASK, GTYE4_CH_PREIQ_FREQ_BST_LSB, 0x0001}, + {GTYE4_CH_RTX_BUF_CML_CTRL_ADDR, GTYE4_CH_RTX_BUF_CML_CTRL_MASK, GTYE4_CH_RTX_BUF_CML_CTRL_LSB, 0x0003}, + {GTYE4_CH_RTX_BUF_TERM_CTRL_ADDR, GTYE4_CH_RTX_BUF_TERM_CTRL_MASK, GTYE4_CH_RTX_BUF_TERM_CTRL_LSB, 0x0000}, + {GTYE4_CH_RXCDR_CFG2_ADDR, GTYE4_CH_RXCDR_CFG2_MASK, GTYE4_CH_RXCDR_CFG2_LSB, 0x0269}, + {GTYE4_CH_RXCDR_CFG3_GEN2_ADDR, GTYE4_CH_RXCDR_CFG3_GEN2_MASK, GTYE4_CH_RXCDR_CFG3_GEN2_LSB, 0x0012}, + {GTYE4_CH_RXCDR_CFG3_GEN3_ADDR, GTYE4_CH_RXCDR_CFG3_GEN3_MASK, GTYE4_CH_RXCDR_CFG3_GEN3_LSB, 0x0012}, + {GTYE4_CH_RXCDR_CFG3_GEN4_ADDR, GTYE4_CH_RXCDR_CFG3_GEN4_MASK, GTYE4_CH_RXCDR_CFG3_GEN4_LSB, 0x0012}, + {GTYE4_CH_RXCDR_CFG3_ADDR, GTYE4_CH_RXCDR_CFG3_MASK, GTYE4_CH_RXCDR_CFG3_LSB, 0x0012}, + {GTYE4_CH_RXCKCAL1_IQ_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL1_IQ_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL1_IQ_LOOP_RST_CFG_LSB, 0x0000}, + {GTYE4_CH_RXCKCAL1_I_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL1_I_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL1_I_LOOP_RST_CFG_LSB, 0x0000}, + {GTYE4_CH_RXCKCAL1_Q_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL1_Q_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL1_Q_LOOP_RST_CFG_LSB, 0x0000}, + {GTYE4_CH_RXCKCAL2_DX_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL2_DX_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL2_DX_LOOP_RST_CFG_LSB, 0x0000}, + {GTYE4_CH_RXCKCAL2_D_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL2_D_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL2_D_LOOP_RST_CFG_LSB, 0x0000}, + {GTYE4_CH_RXCKCAL2_S_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL2_S_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL2_S_LOOP_RST_CFG_LSB, 0x0000}, + {GTYE4_CH_RXCKCAL2_X_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL2_X_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL2_X_LOOP_RST_CFG_LSB, 0x0000}, + {GTYE4_CH_RXDFE_KH_CFG2_ADDR, GTYE4_CH_RXDFE_KH_CFG2_MASK, GTYE4_CH_RXDFE_KH_CFG2_LSB, 0x0200}, + {GTYE4_CH_RXDFE_KH_CFG3_ADDR, GTYE4_CH_RXDFE_KH_CFG3_MASK, GTYE4_CH_RXDFE_KH_CFG3_LSB, 0x4101}, + {GTYE4_CH_RXPI_CFG0_ADDR, GTYE4_CH_RXPI_CFG0_MASK, GTYE4_CH_RXPI_CFG0_LSB, 0x0102}, + {GTYE4_CH_RXPI_CFG1_ADDR, GTYE4_CH_RXPI_CFG1_MASK, GTYE4_CH_RXPI_CFG1_LSB, 0x0054}, + {GTYE4_CH_RX_PROGDIV_CFG_ADDR, GTYE4_CH_RX_PROGDIV_CFG_MASK, GTYE4_CH_RX_PROGDIV_CFG_LSB, GTYE4_CH_RX_PROGDIV_CFG_33}, + {GTYE4_CH_RX_PROGDIV_RATE_ADDR, GTYE4_CH_RX_PROGDIV_RATE_MASK, GTYE4_CH_RX_PROGDIV_RATE_LSB, GTYE4_CH_RX_PROGDIV_RATE_FULL}, + {GTYE4_CH_RX_WIDEMODE_CDR_ADDR, GTYE4_CH_RX_WIDEMODE_CDR_MASK, GTYE4_CH_RX_WIDEMODE_CDR_LSB, 0x0001}, + {GTYE4_CH_RX_XMODE_SEL_ADDR, GTYE4_CH_RX_XMODE_SEL_MASK, GTYE4_CH_RX_XMODE_SEL_LSB, 0x0001}, + {GTYE4_CH_TXDRV_FREQBAND_ADDR, GTYE4_CH_TXDRV_FREQBAND_MASK, GTYE4_CH_TXDRV_FREQBAND_LSB, 0x0000}, + {GTYE4_CH_TXFE_CFG0_ADDR, GTYE4_CH_TXFE_CFG0_MASK, GTYE4_CH_TXFE_CFG0_LSB, 0x03C2}, + {GTYE4_CH_TXFE_CFG1_ADDR, GTYE4_CH_TXFE_CFG1_MASK, GTYE4_CH_TXFE_CFG1_LSB, 0x6C00}, + {GTYE4_CH_TXFE_CFG2_ADDR, GTYE4_CH_TXFE_CFG2_MASK, GTYE4_CH_TXFE_CFG2_LSB, 0x6C00}, + {GTYE4_CH_TXFE_CFG3_ADDR, GTYE4_CH_TXFE_CFG3_MASK, GTYE4_CH_TXFE_CFG3_LSB, 0x6C00}, + {GTYE4_CH_TXPI_CFG0_ADDR, GTYE4_CH_TXPI_CFG0_MASK, GTYE4_CH_TXPI_CFG0_LSB, 0x0300}, + {GTYE4_CH_TXPI_CFG1_ADDR, GTYE4_CH_TXPI_CFG1_MASK, GTYE4_CH_TXPI_CFG1_LSB, 0x1000}, + {GTYE4_CH_TXSWBST_EN_ADDR, GTYE4_CH_TXSWBST_EN_MASK, GTYE4_CH_TXSWBST_EN_LSB, 0x0000}, + {GTYE4_CH_TX_PI_BIASSET_ADDR, GTYE4_CH_TX_PI_BIASSET_MASK, GTYE4_CH_TX_PI_BIASSET_LSB, 0x0001}, + {GTYE4_CH_TX_PROGDIV_CFG_ADDR, GTYE4_CH_TX_PROGDIV_CFG_MASK, GTYE4_CH_TX_PROGDIV_CFG_LSB, GTYE4_CH_TX_PROGDIV_CFG_33}, + {GTYE4_CH_TX_PROGDIV_RATE_ADDR, GTYE4_CH_TX_PROGDIV_RATE_MASK, GTYE4_CH_TX_PROGDIV_RATE_LSB, GTYE4_CH_TX_PROGDIV_RATE_FULL}, + {0, 0, 0, 0} +}; + +static const struct gt_reg_val gtye4_ch_preset_25g_baser_64_regs[] = { + {GTYE4_CH_CH_HSPMUX_ADDR, GTYE4_CH_CH_HSPMUX_MASK, GTYE4_CH_CH_HSPMUX_LSB, 0x9090}, + {GTYE4_CH_CKCAL1_CFG_0_ADDR, GTYE4_CH_CKCAL1_CFG_0_MASK, GTYE4_CH_CKCAL1_CFG_0_LSB, 0x4040}, + {GTYE4_CH_CKCAL1_CFG_1_ADDR, GTYE4_CH_CKCAL1_CFG_1_MASK, GTYE4_CH_CKCAL1_CFG_1_LSB, 0x1040}, + {GTYE4_CH_CKCAL2_CFG_0_ADDR, GTYE4_CH_CKCAL2_CFG_0_MASK, GTYE4_CH_CKCAL2_CFG_0_LSB, 0x4040}, + {GTYE4_CH_CKCAL2_CFG_1_ADDR, GTYE4_CH_CKCAL2_CFG_1_MASK, GTYE4_CH_CKCAL2_CFG_1_LSB, 0x0040}, + {GTYE4_CH_PREIQ_FREQ_BST_ADDR, GTYE4_CH_PREIQ_FREQ_BST_MASK, GTYE4_CH_PREIQ_FREQ_BST_LSB, 0x0003}, + {GTYE4_CH_RTX_BUF_CML_CTRL_ADDR, GTYE4_CH_RTX_BUF_CML_CTRL_MASK, GTYE4_CH_RTX_BUF_CML_CTRL_LSB, 0x0007}, + {GTYE4_CH_RTX_BUF_TERM_CTRL_ADDR, GTYE4_CH_RTX_BUF_TERM_CTRL_MASK, GTYE4_CH_RTX_BUF_TERM_CTRL_LSB, 0x0003}, + {GTYE4_CH_RXCDR_CFG2_ADDR, GTYE4_CH_RXCDR_CFG2_MASK, GTYE4_CH_RXCDR_CFG2_LSB, 0x01E9}, + {GTYE4_CH_RXCDR_CFG3_GEN2_ADDR, GTYE4_CH_RXCDR_CFG3_GEN2_MASK, GTYE4_CH_RXCDR_CFG3_GEN2_LSB, 0x0010}, + {GTYE4_CH_RXCDR_CFG3_GEN3_ADDR, GTYE4_CH_RXCDR_CFG3_GEN3_MASK, GTYE4_CH_RXCDR_CFG3_GEN3_LSB, 0x0010}, + {GTYE4_CH_RXCDR_CFG3_GEN4_ADDR, GTYE4_CH_RXCDR_CFG3_GEN4_MASK, GTYE4_CH_RXCDR_CFG3_GEN4_LSB, 0x0010}, + {GTYE4_CH_RXCDR_CFG3_ADDR, GTYE4_CH_RXCDR_CFG3_MASK, GTYE4_CH_RXCDR_CFG3_LSB, 0x0010}, + {GTYE4_CH_RXCKCAL1_IQ_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL1_IQ_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL1_IQ_LOOP_RST_CFG_LSB, 0x0004}, + {GTYE4_CH_RXCKCAL1_I_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL1_I_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL1_I_LOOP_RST_CFG_LSB, 0x0004}, + {GTYE4_CH_RXCKCAL1_Q_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL1_Q_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL1_Q_LOOP_RST_CFG_LSB, 0x0004}, + {GTYE4_CH_RXCKCAL2_DX_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL2_DX_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL2_DX_LOOP_RST_CFG_LSB, 0x0004}, + {GTYE4_CH_RXCKCAL2_D_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL2_D_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL2_D_LOOP_RST_CFG_LSB, 0x0004}, + {GTYE4_CH_RXCKCAL2_S_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL2_S_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL2_S_LOOP_RST_CFG_LSB, 0x0004}, + {GTYE4_CH_RXCKCAL2_X_LOOP_RST_CFG_ADDR, GTYE4_CH_RXCKCAL2_X_LOOP_RST_CFG_MASK, GTYE4_CH_RXCKCAL2_X_LOOP_RST_CFG_LSB, 0x0004}, + {GTYE4_CH_RXDFE_KH_CFG2_ADDR, GTYE4_CH_RXDFE_KH_CFG2_MASK, GTYE4_CH_RXDFE_KH_CFG2_LSB, 0x281C}, + {GTYE4_CH_RXDFE_KH_CFG3_ADDR, GTYE4_CH_RXDFE_KH_CFG3_MASK, GTYE4_CH_RXDFE_KH_CFG3_LSB, 0x4120}, + {GTYE4_CH_RXPI_CFG0_ADDR, GTYE4_CH_RXPI_CFG0_MASK, GTYE4_CH_RXPI_CFG0_LSB, 0x3006}, + {GTYE4_CH_RXPI_CFG1_ADDR, GTYE4_CH_RXPI_CFG1_MASK, GTYE4_CH_RXPI_CFG1_LSB, 0x0000}, + {GTYE4_CH_RX_PROGDIV_CFG_ADDR, GTYE4_CH_RX_PROGDIV_CFG_MASK, GTYE4_CH_RX_PROGDIV_CFG_LSB, GTYE4_CH_RX_PROGDIV_CFG_16P5}, + {GTYE4_CH_RX_PROGDIV_RATE_ADDR, GTYE4_CH_RX_PROGDIV_RATE_MASK, GTYE4_CH_RX_PROGDIV_RATE_LSB, GTYE4_CH_RX_PROGDIV_RATE_HALF}, + {GTYE4_CH_RX_WIDEMODE_CDR_ADDR, GTYE4_CH_RX_WIDEMODE_CDR_MASK, GTYE4_CH_RX_WIDEMODE_CDR_LSB, 0x0002}, + {GTYE4_CH_RX_XMODE_SEL_ADDR, GTYE4_CH_RX_XMODE_SEL_MASK, GTYE4_CH_RX_XMODE_SEL_LSB, 0x0000}, + {GTYE4_CH_TXDRV_FREQBAND_ADDR, GTYE4_CH_TXDRV_FREQBAND_MASK, GTYE4_CH_TXDRV_FREQBAND_LSB, 0x0003}, + {GTYE4_CH_TXFE_CFG0_ADDR, GTYE4_CH_TXFE_CFG0_MASK, GTYE4_CH_TXFE_CFG0_LSB, 0x03C6}, + {GTYE4_CH_TXFE_CFG1_ADDR, GTYE4_CH_TXFE_CFG1_MASK, GTYE4_CH_TXFE_CFG1_LSB, 0xF800}, + {GTYE4_CH_TXFE_CFG2_ADDR, GTYE4_CH_TXFE_CFG2_MASK, GTYE4_CH_TXFE_CFG2_LSB, 0xF800}, + {GTYE4_CH_TXFE_CFG3_ADDR, GTYE4_CH_TXFE_CFG3_MASK, GTYE4_CH_TXFE_CFG3_LSB, 0xF800}, + {GTYE4_CH_TXPI_CFG0_ADDR, GTYE4_CH_TXPI_CFG0_MASK, GTYE4_CH_TXPI_CFG0_LSB, 0x3000}, + {GTYE4_CH_TXPI_CFG1_ADDR, GTYE4_CH_TXPI_CFG1_MASK, GTYE4_CH_TXPI_CFG1_LSB, 0x0000}, + {GTYE4_CH_TXSWBST_EN_ADDR, GTYE4_CH_TXSWBST_EN_MASK, GTYE4_CH_TXSWBST_EN_LSB, 0x0001}, + {GTYE4_CH_TX_PI_BIASSET_ADDR, GTYE4_CH_TX_PI_BIASSET_MASK, GTYE4_CH_TX_PI_BIASSET_LSB, 0x0003}, + {GTYE4_CH_TX_PROGDIV_CFG_ADDR, GTYE4_CH_TX_PROGDIV_CFG_MASK, GTYE4_CH_TX_PROGDIV_CFG_LSB, GTYE4_CH_TX_PROGDIV_CFG_16P5}, + {GTYE4_CH_TX_PROGDIV_RATE_ADDR, GTYE4_CH_TX_PROGDIV_RATE_MASK, GTYE4_CH_TX_PROGDIV_RATE_LSB, GTYE4_CH_TX_PROGDIV_RATE_HALF}, + {0, 0, 0, 0} +}; + +static const struct gt_reg_val gtye4_ch_preset_dfe_regs[] = { + {GTYE4_CH_RX_DEGEN_CTRL_ADDR, GTYE4_CH_RX_DEGEN_CTRL_MASK, GTYE4_CH_RX_DEGEN_CTRL_LSB, 0x0007}, + {GTYE4_CH_RX_DFE_AGC_CFG1_ADDR, GTYE4_CH_RX_DFE_AGC_CFG1_MASK, GTYE4_CH_RX_DFE_AGC_CFG1_LSB, 0x0004}, + {GTYE4_CH_RX_PMA_RSV0_ADDR, GTYE4_CH_RX_PMA_RSV0_MASK, GTYE4_CH_RX_PMA_RSV0_LSB, 0x000F}, + {GTYE4_CH_RX_SUM_DEGEN_AVTT_OVERITE_ADDR, GTYE4_CH_RX_SUM_DEGEN_AVTT_OVERITE_MASK, GTYE4_CH_RX_SUM_DEGEN_AVTT_OVERITE_LSB, 0x0001}, + {0, 0, 0, 0} +}; + +static const struct gt_reg_val gtye4_ch_preset_lpm_regs[] = { + {GTYE4_CH_RX_DEGEN_CTRL_ADDR, GTYE4_CH_RX_DEGEN_CTRL_MASK, GTYE4_CH_RX_DEGEN_CTRL_LSB, 0x0004}, + {GTYE4_CH_RX_DFE_AGC_CFG1_ADDR, GTYE4_CH_RX_DFE_AGC_CFG1_MASK, GTYE4_CH_RX_DFE_AGC_CFG1_LSB, 0x0002}, + {GTYE4_CH_RX_PMA_RSV0_ADDR, GTYE4_CH_RX_PMA_RSV0_MASK, GTYE4_CH_RX_PMA_RSV0_LSB, 0x002F}, + {GTYE4_CH_RX_SUM_DEGEN_AVTT_OVERITE_ADDR, GTYE4_CH_RX_SUM_DEGEN_AVTT_OVERITE_MASK, GTYE4_CH_RX_SUM_DEGEN_AVTT_OVERITE_LSB, 0x0000}, + {0, 0, 0, 0} +}; + +static const uint32_t gtye4_ch_presets[] = { + GT_PRESET_10G_DFE, + GT_PRESET_10G_LPM, + GT_PRESET_25G_DFE, + GT_PRESET_25G_LPM, + 0 +}; + +static int gtye4_ch_get_available_presets(struct gt_ch *ch, const uint32_t **presets) +{ + *presets = gtye4_ch_presets; + return 0; +} + +static int gtye4_ch_load_preset(struct gt_ch *ch, uint32_t preset) +{ + struct gtye4_quad_priv *priv = ch->quad->priv; + + if (preset == GT_PRESET_10G_DFE || preset == GT_PRESET_10G_LPM) + { + if (priv->qpll0_25g) + gtye4_pll_set_qpll1_pd(ch->pll, 0); + + gtye4_ch_set_tx_reset(ch, 1); + gtye4_ch_set_rx_reset(ch, 1); + + if (priv->qpll0_25g) + { + gtye4_ch_set_tx_qpll_sel(ch, 1); + gtye4_ch_set_rx_qpll_sel(ch, 1); + } + + gt_ch_reg_write_multiple(ch, gtye4_ch_preset_10g_baser_64_regs); + + if (preset == GT_PRESET_10G_DFE) + { + gt_ch_reg_write_multiple(ch, gtye4_ch_preset_dfe_regs); + gtye4_ch_set_rx_lpm_en(ch, 0); + } + else + { + gt_ch_reg_write_multiple(ch, gtye4_ch_preset_lpm_regs); + gtye4_ch_set_rx_lpm_en(ch, 1); + } + + gtye4_ch_set_tx_reset(ch, 0); + gtye4_ch_set_rx_reset(ch, 0); + + return 0; + } + + if ((preset == GT_PRESET_25G_DFE || preset == GT_PRESET_25G_LPM) && priv->qpll0_25g) + { + gtye4_ch_set_tx_reset(ch, 1); + gtye4_ch_set_rx_reset(ch, 1); + + gtye4_ch_set_tx_qpll_sel(ch, 0); + gtye4_ch_set_rx_qpll_sel(ch, 0); + + gt_ch_reg_write_multiple(ch, gtye4_ch_preset_25g_baser_64_regs); + + if (preset == GT_PRESET_25G_DFE) + { + gt_ch_reg_write_multiple(ch, gtye4_ch_preset_dfe_regs); + gtye4_ch_set_rx_lpm_en(ch, 0); + } + else + { + gt_ch_reg_write_multiple(ch, gtye4_ch_preset_lpm_regs); + gtye4_ch_set_rx_lpm_en(ch, 1); + } + + gtye4_ch_set_tx_reset(ch, 0); + gtye4_ch_set_rx_reset(ch, 0); + + return 0; + } + + return -1; +} + +static int gtye4_ch_eyescan_start(struct gt_ch *ch, struct gt_eyescan_params *params) +{ + struct gtye4_ch_priv *priv = ch->priv; + uint32_t val; + + uint32_t error_count; + uint32_t sample_count; + uint64_t bit_count; + float ber; + + priv->eyescan_running = 0; + + gtye4_ch_get_rx_lpm_en(ch, &val); + priv->dfe_en = !val; + + gtye4_ch_get_rx_data_width(ch, &priv->rx_data_width); + gtye4_ch_get_rx_int_data_width(ch, &priv->rx_int_data_width); + + priv->prescale = 0; + + for (priv->prescale = 0; priv->prescale < 32; priv->prescale++) + { + if (((uint64_t)0xffff * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale) >= params->target_bit_count) + break; + } + + params->target_bit_count = ((uint64_t)0xffff * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale); + params->h_range = 0; + + priv->h_start = params->h_start; + priv->h_stop = params->h_stop; + priv->h_step = params->h_step; + priv->v_range = params->v_range; + priv->v_start = params->v_start; + priv->v_stop = params->v_stop; + priv->v_step = params->v_step; + + gtye4_ch_set_es_control(ch, 0x00); + + gtye4_ch_set_es_prescale(ch, 4); + gtye4_ch_set_es_errdet_en(ch, 1); + + gtye4_ch_set_es_qual_mask_clear(ch); + gtye4_ch_set_es_sdata_mask_width(ch, priv->rx_int_data_width); + + gtye4_ch_set_rx_eyescan_vs_range(ch, priv->v_range); + + gtye4_ch_set_es_horz_offset(ch, 0x800); + gtye4_ch_set_rx_eyescan_vs_neg_dir(ch, 0); + gtye4_ch_set_rx_eyescan_vs_code(ch, 0); + gtye4_ch_set_rx_eyescan_vs_ut_sign(ch, 0); + + gtye4_ch_set_es_eye_scan_en(ch, 1); + + gtye4_ch_rx_pma_reset(ch); + + for (int ber_tries = 0; ber_tries < 10; ber_tries++) + { + for (int reset_tries = 0; reset_tries < 30; reset_tries++) + { + gtye4_ch_get_rx_reset_done(ch, &val); + if (val) + break; + usleep(100000); + } + + if (!val) + { + fprintf(stderr, "Error: channel stuck in reset\n"); + return -1; + } + + usleep(100000); + + // check for lock + gtye4_ch_set_es_control(ch, 0x01); + + for (int wait_tries = 0; wait_tries < 30; wait_tries++) + { + gtye4_ch_get_es_control_status(ch, &val); + if (val & 1) + break; + usleep(100000); + } + + if (!(val & 1)) + { + fprintf(stderr, "Error: eye scan did not finish (%d)\n", val); + return -1; + } + + gtye4_ch_set_es_control(ch, 0x00); + + gtye4_ch_get_es_error_count(ch, &error_count); + gtye4_ch_get_es_sample_count(ch, &sample_count); + bit_count = ((uint64_t)sample_count * (uint64_t)priv->rx_int_data_width) << (1+4); + + ber = (float)error_count / (float)bit_count; + + if (ber < 0.01) + break; + + printf("High BER (%02f), resetting eye scan logic\n", ber); + + gtye4_ch_set_es_horz_offset(ch, 0x880); + gtye4_ch_set_eyescan_reset(ch, 1); + gtye4_ch_set_es_horz_offset(ch, 0x800); + gtye4_ch_set_eyescan_reset(ch, 0); + } + + if (ber > 0.01) + { + fprintf(stderr, "Error: High BER, alignment failed\n"); + return -1; + } + + // set up for measurement + priv->h_offset = priv->h_start; + priv->v_offset = priv->v_start; + priv->ut_sign = 0; + + gtye4_ch_set_es_control(ch, 0x00); + gtye4_ch_set_es_prescale(ch, priv->prescale); + gtye4_ch_set_es_errdet_en(ch, 1); + gtye4_ch_set_es_horz_offset(ch, (priv->h_offset & 0x7ff) | 0x800); + gtye4_ch_set_rx_eyescan_vs_neg_dir(ch, (priv->v_offset < 0)); + gtye4_ch_set_rx_eyescan_vs_code(ch, priv->v_offset < 0 ? -priv->v_offset : priv->v_offset); + gtye4_ch_set_rx_eyescan_vs_ut_sign(ch, priv->ut_sign); + + // start measurement + gtye4_ch_set_es_control(ch, 0x01); + + priv->eyescan_running = 1; + + return 0; +} + +static int gtye4_ch_eyescan_step(struct gt_ch *ch, struct gt_eyescan_point *point) +{ + struct gtye4_ch_priv *priv = ch->priv; + uint32_t val; + + uint32_t error_count; + uint32_t sample_count; + uint64_t bit_count; + + int restart = 0; + + if (!priv->eyescan_running) + return 0; + + gtye4_ch_get_es_control_status(ch, &val); + if (!(val & 1)) + return 2; + + gtye4_ch_set_es_control(ch, 0x00); + + gtye4_ch_get_es_error_count(ch, &error_count); + gtye4_ch_get_es_sample_count(ch, &sample_count); + bit_count = ((uint64_t)sample_count * (uint64_t)priv->rx_int_data_width) << (1+priv->prescale); + + point->error_count = error_count; + point->bit_count = bit_count; + point->x = priv->h_offset; + point->y = priv->v_offset; + point->ut_sign = priv->ut_sign; + + restart = 0; + + if (!priv->ut_sign && priv->dfe_en) + { + priv->ut_sign = 1; + restart = 1; + } + else + { + priv->ut_sign = 0; + } + + gtye4_ch_set_rx_eyescan_vs_ut_sign(ch, priv->ut_sign); + + if (restart) + { + gtye4_ch_set_es_control(ch, 0x01); + return 1; + } + + if (priv->v_offset < priv->v_stop) + { + priv->v_offset += priv->v_step; + restart = 1; + } + else + { + priv->v_offset = priv->v_start; + } + + gtye4_ch_set_rx_eyescan_vs_neg_dir(ch, (priv->v_offset < 0)); + gtye4_ch_set_rx_eyescan_vs_code(ch, priv->v_offset < 0 ? -priv->v_offset : priv->v_offset); + + if (restart) + { + gtye4_ch_set_es_control(ch, 0x01); + return 1; + } + + if (priv->h_offset < priv->h_stop) + { + priv->h_offset += priv->h_step; + restart = 1; + } + else + { + // done + priv->eyescan_running = 0; + return 1; + } + + gtye4_ch_set_es_horz_offset(ch, (priv->h_offset & 0x7ff) | 0x800); + + if (restart) + { + gtye4_ch_set_es_control(ch, 0x01); + return 1; + } + + priv->eyescan_running = 0; + return 0; +} + +const struct gt_ch_ops gtye4_gt_ch_ops = { + .get_tx_reset = gtye4_ch_get_tx_reset, + .set_tx_reset = gtye4_ch_set_tx_reset, + .tx_reset = gtye4_ch_tx_reset, + .get_rx_reset = gtye4_ch_get_rx_reset, + .set_rx_reset = gtye4_ch_set_rx_reset, + .rx_reset = gtye4_ch_rx_reset, + .get_tx_data_width = gtye4_ch_get_tx_data_width, + .get_tx_int_data_width = gtye4_ch_get_tx_int_data_width, + .get_rx_data_width = gtye4_ch_get_rx_data_width, + .get_rx_int_data_width = gtye4_ch_get_rx_int_data_width, + .get_available_presets = gtye4_ch_get_available_presets, + .load_preset = gtye4_ch_load_preset, + .eyescan_start = gtye4_ch_eyescan_start, + .eyescan_step = gtye4_ch_eyescan_step +}; + +static int gtye4_ch_init(struct gt_ch *ch) +{ + struct gtye4_ch_priv *priv = calloc(1, sizeof(struct gtye4_ch_priv)); + if (!priv) + return -1; + + ch->priv = priv; + + return 0; +} + +static int gtye4_quad_init(struct gt_quad *quad) +{ + uint32_t val; + struct gtye4_quad_priv *priv = calloc(1, sizeof(struct gtye4_quad_priv)); + if (!priv) + return -1; + + quad->priv = priv; + quad->type = "GTYE4"; + + gtye4_pll_get_qpll0clkout_rate(&quad->pll, &val); + priv->qpll0_25g = val == GTYE4_COM_QPLL0CLKOUT_RATE_FULL; + + for (int n = 0; n < quad->ch_count; n++) + { + quad->ch[n].quad = quad; + quad->ch[n].pll = &quad->pll; + quad->ch[n].ops = >ye4_gt_ch_ops; + quad->ch[n].index = n; + + gtye4_ch_init(&quad->ch[n]); + } + + return 0; +} + +const struct gt_quad_ops gtye4_gt_quad_ops = { + .init = gtye4_quad_init +}; diff --git a/utils/xcvr_gtye4.h b/utils/xcvr_gtye4.h new file mode 100644 index 0000000..e20bdbe --- /dev/null +++ b/utils/xcvr_gtye4.h @@ -0,0 +1,386 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#ifndef XCVR_GTYE4_H +#define XCVR_GTYE4_H + +#include "xcvr_gt.h" +#include "gt/gtye4_regs.h" + +// signals +#define GTYE4_COM_QPLL0_RESET_ADDR 0x10000 +#define GTYE4_COM_QPLL0_RESET_MSB 0 +#define GTYE4_COM_QPLL0_RESET_LSB 0 +#define GTYE4_COM_QPLL0_RESET_MASK BIT_MASK(GTYE4_COM_QPLL0_RESET_MSB, GTYE4_COM_QPLL0_RESET_LSB) +#define GTYE4_COM_QPLL0_LOCK_ADDR 0x10000 +#define GTYE4_COM_QPLL0_LOCK_MSB 8 +#define GTYE4_COM_QPLL0_LOCK_LSB 8 +#define GTYE4_COM_QPLL0_LOCK_MASK BIT_MASK(GTYE4_COM_QPLL0_LOCK_MSB, GTYE4_COM_QPLL0_LOCK_LSB) +#define GTYE4_COM_QPLL0_PD_ADDR 0x10001 +#define GTYE4_COM_QPLL0_PD_MSB 0 +#define GTYE4_COM_QPLL0_PD_LSB 0 +#define GTYE4_COM_QPLL0_PD_MASK BIT_MASK(GTYE4_COM_QPLL0_PD_MSB, GTYE4_COM_QPLL0_PD_LSB) +#define GTYE4_COM_QPLL1_RESET_ADDR 0x11000 +#define GTYE4_COM_QPLL1_RESET_MSB 0 +#define GTYE4_COM_QPLL1_RESET_LSB 0 +#define GTYE4_COM_QPLL1_RESET_MASK BIT_MASK(GTYE4_COM_QPLL0_RESET_MSB, GTYE4_COM_QPLL0_RESET_LSB) +#define GTYE4_COM_QPLL1_LOCK_ADDR 0x11000 +#define GTYE4_COM_QPLL1_LOCK_MSB 8 +#define GTYE4_COM_QPLL1_LOCK_LSB 8 +#define GTYE4_COM_QPLL1_LOCK_MASK BIT_MASK(GTYE4_COM_QPLL0_LOCK_MSB, GTYE4_COM_QPLL0_LOCK_LSB) +#define GTYE4_COM_QPLL1_PD_ADDR 0x11001 +#define GTYE4_COM_QPLL1_PD_MSB 0 +#define GTYE4_COM_QPLL1_PD_LSB 0 +#define GTYE4_COM_QPLL1_PD_MASK BIT_MASK(GTYE4_COM_QPLL1_PD_MSB, GTYE4_COM_QPLL1_PD_LSB) + +#define GTYE4_CH_TX_RESET_ADDR 0x10000 +#define GTYE4_CH_TX_RESET_MSB 0 +#define GTYE4_CH_TX_RESET_LSB 0 +#define GTYE4_CH_TX_RESET_MASK BIT_MASK(GTYE4_CH_TX_RESET_MSB, GTYE4_CH_TX_RESET_LSB) +#define GTYE4_CH_TX_PMA_RESET_ADDR 0x10000 +#define GTYE4_CH_TX_PMA_RESET_MSB 1 +#define GTYE4_CH_TX_PMA_RESET_LSB 1 +#define GTYE4_CH_TX_PMA_RESET_MASK BIT_MASK(GTYE4_CH_TX_PMA_RESET_MSB, GTYE4_CH_TX_PMA_RESET_LSB) +#define GTYE4_CH_TX_PCS_RESET_ADDR 0x10000 +#define GTYE4_CH_TX_PCS_RESET_MSB 2 +#define GTYE4_CH_TX_PCS_RESET_LSB 2 +#define GTYE4_CH_TX_PCS_RESET_MASK BIT_MASK(GTYE4_CH_TX_PCS_RESET_MSB, GTYE4_CH_TX_PCS_RESET_LSB) +#define GTYE4_CH_TX_RESET_DONE_ADDR 0x10000 +#define GTYE4_CH_TX_RESET_DONE_MSB 8 +#define GTYE4_CH_TX_RESET_DONE_LSB 8 +#define GTYE4_CH_TX_RESET_DONE_MASK BIT_MASK(GTYE4_CH_TX_RESET_DONE_MSB, GTYE4_CH_TX_RESET_DONE_LSB) +#define GTYE4_CH_TX_GT_RESET_DONE_ADDR 0x10000 +#define GTYE4_CH_TX_GT_RESET_DONE_MSB 9 +#define GTYE4_CH_TX_GT_RESET_DONE_LSB 9 +#define GTYE4_CH_TX_GT_RESET_DONE_MASK BIT_MASK(GTYE4_CH_TX_GT_RESET_DONE_MSB, GTYE4_CH_TX_GT_RESET_DONE_LSB) +#define GTYE4_CH_TX_PMA_RESET_DONE_ADDR 0x10000 +#define GTYE4_CH_TX_PMA_RESET_DONE_MSB 10 +#define GTYE4_CH_TX_PMA_RESET_DONE_LSB 10 +#define GTYE4_CH_TX_PMA_RESET_DONE_MASK BIT_MASK(GTYE4_CH_TX_PMA_RESET_DONE_MSB, GTYE4_CH_TX_PMA_RESET_DONE_LSB) +#define GTYE4_CH_TX_PRGDIV_RESET_DONE_ADDR 0x10000 +#define GTYE4_CH_TX_PRGDIV_RESET_DONE_MSB 11 +#define GTYE4_CH_TX_PRGDIV_RESET_DONE_LSB 11 +#define GTYE4_CH_TX_PRGDIV_RESET_DONE_MASK BIT_MASK(GTYE4_CH_TX_PRGDIV_RESET_DONE_MSB, GTYE4_CH_TX_PRGDIV_RESET_DONE_LSB) +#define GTYE4_CH_TX_USRCLK_ACT_ADDR 0x10000 +#define GTYE4_CH_TX_USRCLK_ACT_MSB 12 +#define GTYE4_CH_TX_USRCLK_ACT_LSB 12 +#define GTYE4_CH_TX_USRCLK_ACT_MASK BIT_MASK(GTYE4_CH_TX_USRCLK_ACT_MSB, GTYE4_CH_TX_USRCLK_ACT_LSB) +#define GTYE4_CH_TX_PD_ADDR 0x10001 +#define GTYE4_CH_TX_PD_MSB 0 +#define GTYE4_CH_TX_PD_LSB 0 +#define GTYE4_CH_TX_PD_MASK BIT_MASK(GTYE4_CH_TX_PD_MSB, GTYE4_CH_TX_PD_LSB) +#define GTYE4_CH_TX_QPLL_SEL_ADDR 0x10001 +#define GTYE4_CH_TX_QPLL_SEL_MSB 1 +#define GTYE4_CH_TX_QPLL_SEL_LSB 1 +#define GTYE4_CH_TX_QPLL_SEL_MASK BIT_MASK(GTYE4_CH_TX_QPLL_SEL_MSB, GTYE4_CH_TX_QPLL_SEL_LSB) +#define GTYE4_CH_TX_POLARITY_ADDR 0x10010 +#define GTYE4_CH_TX_POLARITY_MSB 0 +#define GTYE4_CH_TX_POLARITY_LSB 0 +#define GTYE4_CH_TX_POLARITY_MASK BIT_MASK(GTYE4_CH_TX_POLARITY_MSB, GTYE4_CH_TX_POLARITY_LSB) +#define GTYE4_CH_TX_ELECIDLE_ADDR 0x10010 +#define GTYE4_CH_TX_ELECIDLE_MSB 1 +#define GTYE4_CH_TX_ELECIDLE_LSB 1 +#define GTYE4_CH_TX_ELECIDLE_MASK BIT_MASK(GTYE4_CH_TX_ELECIDLE_MSB, GTYE4_CH_TX_ELECIDLE_LSB) +#define GTYE4_CH_TX_INHIBIT_ADDR 0x10010 +#define GTYE4_CH_TX_INHIBIT_MSB 2 +#define GTYE4_CH_TX_INHIBIT_LSB 2 +#define GTYE4_CH_TX_INHIBIT_MASK BIT_MASK(GTYE4_CH_TX_INHIBIT_MSB, GTYE4_CH_TX_INHIBIT_LSB) +#define GTYE4_CH_TX_DIFFCTRL_ADDR 0x10011 +#define GTYE4_CH_TX_DIFFCTRL_MSB 4 +#define GTYE4_CH_TX_DIFFCTRL_LSB 0 +#define GTYE4_CH_TX_DIFFCTRL_MASK BIT_MASK(GTYE4_CH_TX_DIFFCTRL_MSB, GTYE4_CH_TX_DIFFCTRL_LSB) +#define GTYE4_CH_TX_MAINCURSOR_ADDR 0x10012 +#define GTYE4_CH_TX_MAINCURSOR_MSB 6 +#define GTYE4_CH_TX_MAINCURSOR_LSB 0 +#define GTYE4_CH_TX_MAINCURSOR_MASK BIT_MASK(GTYE4_CH_TX_MAINCURSOR_MSB, GTYE4_CH_TX_MAINCURSOR_LSB) +#define GTYE4_CH_TX_PRECURSOR_ADDR 0x10013 +#define GTYE4_CH_TX_PRECURSOR_MSB 4 +#define GTYE4_CH_TX_PRECURSOR_LSB 0 +#define GTYE4_CH_TX_PRECURSOR_MASK BIT_MASK(GTYE4_CH_TX_PRECURSOR_MSB, GTYE4_CH_TX_PRECURSOR_LSB) +#define GTYE4_CH_TX_POSTCURSOR_ADDR 0x10014 +#define GTYE4_CH_TX_POSTCURSOR_MSB 4 +#define GTYE4_CH_TX_POSTCURSOR_LSB 0 +#define GTYE4_CH_TX_POSTCURSOR_MASK BIT_MASK(GTYE4_CH_TX_POSTCURSOR_MSB, GTYE4_CH_TX_POSTCURSOR_LSB) +#define GTYE4_CH_TX_PRBS_SEL_ADDR 0x10040 +#define GTYE4_CH_TX_PRBS_SEL_MSB 3 +#define GTYE4_CH_TX_PRBS_SEL_LSB 0 +#define GTYE4_CH_TX_PRBS_SEL_MASK BIT_MASK(GTYE4_CH_TX_PRBS_SEL_MSB, GTYE4_CH_TX_PRBS_SEL_LSB) +#define GTYE4_CH_TX_PRBS_FORCERR_ADDR 0x10040 +#define GTYE4_CH_TX_PRBS_FORCERR_MSB 15 +#define GTYE4_CH_TX_PRBS_FORCERR_LSB 0 +#define GTYE4_CH_TX_PRBS_FORCERR_MASK BIT_MASK(GTYE4_CH_TX_PRBS_FORCERR_MSB, GTYE4_CH_TX_PRBS_FORCERR_LSB) +#define GTYE4_CH_RX_RESET_ADDR 0x11000 +#define GTYE4_CH_RX_RESET_MSB 0 +#define GTYE4_CH_RX_RESET_LSB 0 +#define GTYE4_CH_RX_RESET_MASK BIT_MASK(GTYE4_CH_RX_RESET_MSB, GTYE4_CH_RX_RESET_LSB) +#define GTYE4_CH_RX_PMA_RESET_ADDR 0x11000 +#define GTYE4_CH_RX_PMA_RESET_MSB 1 +#define GTYE4_CH_RX_PMA_RESET_LSB 1 +#define GTYE4_CH_RX_PMA_RESET_MASK BIT_MASK(GTYE4_CH_RX_PMA_RESET_MSB, GTYE4_CH_RX_PMA_RESET_LSB) +#define GTYE4_CH_RX_PCS_RESET_ADDR 0x11000 +#define GTYE4_CH_RX_PCS_RESET_MSB 2 +#define GTYE4_CH_RX_PCS_RESET_LSB 2 +#define GTYE4_CH_RX_PCS_RESET_MASK BIT_MASK(GTYE4_CH_RX_PCS_RESET_MSB, GTYE4_CH_RX_PCS_RESET_LSB) +#define GTYE4_CH_RX_DFE_LPM_RESET_ADDR 0x11000 +#define GTYE4_CH_RX_DFE_LPM_RESET_MSB 3 +#define GTYE4_CH_RX_DFE_LPM_RESET_LSB 3 +#define GTYE4_CH_RX_DFE_LPM_RESET_MASK BIT_MASK(GTYE4_CH_RX_DFE_LPM_RESET_MSB, GTYE4_CH_RX_DFE_LPM_RESET_LSB) +#define GTYE4_CH_EYESCAN_RESET_ADDR 0x11000 +#define GTYE4_CH_EYESCAN_RESET_MSB 4 +#define GTYE4_CH_EYESCAN_RESET_LSB 4 +#define GTYE4_CH_EYESCAN_RESET_MASK BIT_MASK(GTYE4_CH_EYESCAN_RESET_MSB, GTYE4_CH_EYESCAN_RESET_LSB) +#define GTYE4_CH_RX_RESET_DONE_ADDR 0x11000 +#define GTYE4_CH_RX_RESET_DONE_MSB 8 +#define GTYE4_CH_RX_RESET_DONE_LSB 8 +#define GTYE4_CH_RX_RESET_DONE_MASK BIT_MASK(GTYE4_CH_RX_RESET_DONE_MSB, GTYE4_CH_RX_RESET_DONE_LSB) +#define GTYE4_CH_RX_GT_RESET_DONE_ADDR 0x11000 +#define GTYE4_CH_RX_GT_RESET_DONE_MSB 9 +#define GTYE4_CH_RX_GT_RESET_DONE_LSB 9 +#define GTYE4_CH_RX_GT_RESET_DONE_MASK BIT_MASK(GTYE4_CH_RX_GT_RESET_DONE_MSB, GTYE4_CH_RX_GT_RESET_DONE_LSB) +#define GTYE4_CH_RX_PMA_RESET_DONE_ADDR 0x11000 +#define GTYE4_CH_RX_PMA_RESET_DONE_MSB 10 +#define GTYE4_CH_RX_PMA_RESET_DONE_LSB 10 +#define GTYE4_CH_RX_PMA_RESET_DONE_MASK BIT_MASK(GTYE4_CH_RX_PMA_RESET_DONE_MSB, GTYE4_CH_RX_PMA_RESET_DONE_LSB) +#define GTYE4_CH_RX_PRGDIV_RESET_DONE_ADDR 0x11000 +#define GTYE4_CH_RX_PRGDIV_RESET_DONE_MSB 11 +#define GTYE4_CH_RX_PRGDIV_RESET_DONE_LSB 11 +#define GTYE4_CH_RX_PRGDIV_RESET_DONE_MASK BIT_MASK(GTYE4_CH_RX_PRGDIV_RESET_DONE_MSB, GTYE4_CH_RX_PRGDIV_RESET_DONE_LSB) +#define GTYE4_CH_RX_USRCLK_ACT_ADDR 0x11000 +#define GTYE4_CH_RX_USRCLK_ACT_MSB 12 +#define GTYE4_CH_RX_USRCLK_ACT_LSB 12 +#define GTYE4_CH_RX_USRCLK_ACT_MASK BIT_MASK(GTYE4_CH_RX_USRCLK_ACT_MSB, GTYE4_CH_RX_USRCLK_ACT_LSB) +#define GTYE4_CH_RX_PD_ADDR 0x11001 +#define GTYE4_CH_RX_PD_MSB 0 +#define GTYE4_CH_RX_PD_LSB 0 +#define GTYE4_CH_RX_PD_MASK BIT_MASK(GTYE4_CH_RX_PD_MSB, GTYE4_CH_RX_PD_LSB) +#define GTYE4_CH_RX_QPLL_SEL_ADDR 0x11001 +#define GTYE4_CH_RX_QPLL_SEL_MSB 1 +#define GTYE4_CH_RX_QPLL_SEL_LSB 1 +#define GTYE4_CH_RX_QPLL_SEL_MASK BIT_MASK(GTYE4_CH_RX_QPLL_SEL_MSB, GTYE4_CH_RX_QPLL_SEL_LSB) +#define GTYE4_CH_LOOPBACK_ADDR 0x11002 +#define GTYE4_CH_LOOPBACK_MSB 2 +#define GTYE4_CH_LOOPBACK_LSB 0 +#define GTYE4_CH_LOOPBACK_MASK BIT_MASK(GTYE4_CH_LOOPBACK_MSB, GTYE4_CH_LOOPBACK_LSB) +#define GTYE4_CH_RX_POLARITY_ADDR 0x11010 +#define GTYE4_CH_RX_POLARITY_MSB 0 +#define GTYE4_CH_RX_POLARITY_LSB 0 +#define GTYE4_CH_RX_POLARITY_MASK BIT_MASK(GTYE4_CH_RX_POLARITY_MSB, GTYE4_CH_RX_POLARITY_LSB) +#define GTYE4_CH_RX_CDR_HOLD_ADDR 0x11020 +#define GTYE4_CH_RX_CDR_HOLD_MSB 0 +#define GTYE4_CH_RX_CDR_HOLD_LSB 0 +#define GTYE4_CH_RX_CDR_HOLD_MASK BIT_MASK(GTYE4_CH_RX_CDR_HOLD_MSB, GTYE4_CH_RX_CDR_HOLD_LSB) +#define GTYE4_CH_RX_CDR_LOCK_ADDR 0x11020 +#define GTYE4_CH_RX_CDR_LOCK_MSB 8 +#define GTYE4_CH_RX_CDR_LOCK_LSB 8 +#define GTYE4_CH_RX_CDR_LOCK_MASK BIT_MASK(GTYE4_CH_RX_CDR_LOCK_MSB, GTYE4_CH_RX_CDR_LOCK_LSB) +#define GTYE4_CH_RX_LPM_EN_ADDR 0x11024 +#define GTYE4_CH_RX_LPM_EN_MSB 0 +#define GTYE4_CH_RX_LPM_EN_LSB 0 +#define GTYE4_CH_RX_LPM_EN_MASK BIT_MASK(GTYE4_CH_RX_LPM_EN_MSB, GTYE4_CH_RX_LPM_EN_LSB) +#define GTYE4_CH_RX_DMONITOR_ADDR 0x11028 +#define GTYE4_CH_RX_DMONITOR_MSB 7 +#define GTYE4_CH_RX_DMONITOR_LSB 0 +#define GTYE4_CH_RX_DMONITOR_MASK BIT_MASK(GTYE4_CH_RX_DMONITOR_MSB, GTYE4_CH_RX_DMONITOR_LSB) +#define GTYE4_CH_RX_PRBS_SEL_ADDR 0x11040 +#define GTYE4_CH_RX_PRBS_SEL_MSB 3 +#define GTYE4_CH_RX_PRBS_SEL_LSB 0 +#define GTYE4_CH_RX_PRBS_SEL_MASK BIT_MASK(GTYE4_CH_RX_PRBS_SEL_MSB, GTYE4_CH_RX_PRBS_SEL_LSB) +#define GTYE4_CH_RX_PRBS_CNT_RESET_ADDR 0x11041 +#define GTYE4_CH_RX_PRBS_CNT_RESET_MSB 0 +#define GTYE4_CH_RX_PRBS_CNT_RESET_LSB 0 +#define GTYE4_CH_RX_PRBS_CNT_RESET_MASK BIT_MASK(GTYE4_CH_RX_PRBS_CNT_RESET_MSB, GTYE4_CH_RX_PRBS_CNT_RESET_LSB) +#define GTYE4_CH_RX_PRBS_LOCKED_ADDR 0x11041 +#define GTYE4_CH_RX_PRBS_LOCKED_MSB 8 +#define GTYE4_CH_RX_PRBS_LOCKED_LSB 8 +#define GTYE4_CH_RX_PRBS_LOCKED_MASK BIT_MASK(GTYE4_CH_RX_PRBS_LOCKED_MSB, GTYE4_CH_RX_PRBS_LOCKED_LSB) +#define GTYE4_CH_RX_PRBS_ERROR_ADDR 0x11041 +#define GTYE4_CH_RX_PRBS_ERROR_MSB 9 +#define GTYE4_CH_RX_PRBS_ERROR_LSB 9 +#define GTYE4_CH_RX_PRBS_ERROR_MASK BIT_MASK(GTYE4_CH_RX_PRBS_ERROR_MSB, GTYE4_CH_RX_PRBS_ERROR_LSB) + + +def_gt_pll_masked_reg_rw16(gtye4, qpll0_reset, GTYE4_COM_QPLL0_RESET_ADDR, GTYE4_COM_QPLL0_RESET_MASK, GTYE4_COM_QPLL0_RESET_LSB); +int gtye4_pll_qpll0_reset(struct gt_pll *pll); +def_gt_pll_masked_reg_read16(gtye4, qpll0_lock, GTYE4_COM_QPLL0_LOCK_ADDR, GTYE4_COM_QPLL0_LOCK_MASK, GTYE4_COM_QPLL0_LOCK_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_pd, GTYE4_COM_QPLL0_PD_ADDR, GTYE4_COM_QPLL0_PD_MASK, GTYE4_COM_QPLL0_PD_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_reset, GTYE4_COM_QPLL1_RESET_ADDR, GTYE4_COM_QPLL1_RESET_MASK, GTYE4_COM_QPLL1_RESET_LSB); +int gtye4_pll_qpll1_reset(struct gt_pll *pll); +def_gt_pll_masked_reg_read16(gtye4, qpll1_lock, GTYE4_COM_QPLL1_LOCK_ADDR, GTYE4_COM_QPLL1_LOCK_MASK, GTYE4_COM_QPLL1_LOCK_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_pd, GTYE4_COM_QPLL1_PD_ADDR, GTYE4_COM_QPLL1_PD_MASK, GTYE4_COM_QPLL1_PD_LSB); + +def_gt_ch_masked_reg_rw16(gtye4, tx_reset, GTYE4_CH_TX_RESET_ADDR, GTYE4_CH_TX_RESET_MASK, GTYE4_CH_TX_RESET_LSB); +int gtye4_ch_tx_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye4, tx_pma_reset, GTYE4_CH_TX_PMA_RESET_ADDR, GTYE4_CH_TX_PMA_RESET_MASK, GTYE4_CH_TX_PMA_RESET_LSB); +int gtye4_ch_tx_pma_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye4, tx_pcs_reset, GTYE4_CH_TX_PCS_RESET_ADDR, GTYE4_CH_TX_PCS_RESET_MASK, GTYE4_CH_TX_PCS_RESET_LSB); +int gtye4_ch_tx_pcs_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_read16(gtye4, tx_reset_done, GTYE4_CH_TX_RESET_DONE_ADDR, GTYE4_CH_TX_RESET_DONE_MASK, GTYE4_CH_TX_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye4, tx_gt_reset_done, GTYE4_CH_TX_GT_RESET_DONE_ADDR, GTYE4_CH_TX_GT_RESET_DONE_MASK, GTYE4_CH_TX_GT_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye4, tx_pma_reset_done, GTYE4_CH_TX_PMA_RESET_DONE_ADDR, GTYE4_CH_TX_PMA_RESET_DONE_MASK, GTYE4_CH_TX_PMA_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye4, tx_prgdiv_reset_done, GTYE4_CH_TX_PRGDIV_RESET_DONE_ADDR, GTYE4_CH_TX_PRGDIV_RESET_DONE_MASK, GTYE4_CH_TX_PRGDIV_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye4, tx_usrclk_act, GTYE4_CH_TX_USRCLK_ACT_ADDR, GTYE4_CH_TX_USRCLK_ACT_MASK, GTYE4_CH_TX_USRCLK_ACT_LSB); +def_gt_ch_masked_reg_rw16(gtye4, tx_pd, GTYE4_CH_TX_PD_ADDR, GTYE4_CH_TX_PD_MASK, GTYE4_CH_TX_PD_LSB); +def_gt_ch_masked_reg_rw16(gtye4, tx_qpll_sel, GTYE4_CH_TX_QPLL_SEL_ADDR, GTYE4_CH_TX_QPLL_SEL_MASK, GTYE4_CH_TX_QPLL_SEL_LSB); +def_gt_ch_masked_reg_rw16(gtye4, tx_polarity, GTYE4_CH_TX_POLARITY_ADDR, GTYE4_CH_TX_POLARITY_MASK, GTYE4_CH_TX_POLARITY_LSB); +def_gt_ch_masked_reg_rw16(gtye4, tx_elecidle, GTYE4_CH_TX_ELECIDLE_ADDR, GTYE4_CH_TX_ELECIDLE_MASK, GTYE4_CH_TX_ELECIDLE_LSB); +def_gt_ch_masked_reg_rw16(gtye4, tx_inhibit, GTYE4_CH_TX_INHIBIT_ADDR, GTYE4_CH_TX_INHIBIT_MASK, GTYE4_CH_TX_INHIBIT_LSB); +def_gt_ch_masked_reg_rw16(gtye4, tx_diffctrl, GTYE4_CH_TX_DIFFCTRL_ADDR, GTYE4_CH_TX_DIFFCTRL_MASK, GTYE4_CH_TX_DIFFCTRL_LSB); +def_gt_ch_masked_reg_rw16(gtye4, tx_maincursor, GTYE4_CH_TX_MAINCURSOR_ADDR, GTYE4_CH_TX_MAINCURSOR_MASK, GTYE4_CH_TX_MAINCURSOR_LSB); +def_gt_ch_masked_reg_rw16(gtye4, tx_precursor, GTYE4_CH_TX_PRECURSOR_ADDR, GTYE4_CH_TX_PRECURSOR_MASK, GTYE4_CH_TX_PRECURSOR_LSB); +def_gt_ch_masked_reg_rw16(gtye4, tx_postcursor, GTYE4_CH_TX_POSTCURSOR_ADDR, GTYE4_CH_TX_POSTCURSOR_MASK, GTYE4_CH_TX_POSTCURSOR_LSB); +def_gt_ch_masked_reg_rw16(gtye4, tx_prbs_sel, GTYE4_CH_TX_PRBS_SEL_ADDR, GTYE4_CH_TX_PRBS_SEL_MASK, GTYE4_CH_TX_PRBS_SEL_LSB); +def_gt_ch_masked_reg_rw16(gtye4, tx_prbs_forcerr, GTYE4_CH_TX_PRBS_FORCERR_ADDR, GTYE4_CH_TX_PRBS_FORCERR_MASK, GTYE4_CH_TX_PRBS_FORCERR_LSB); + +def_gt_ch_masked_reg_rw16(gtye4, rx_reset, GTYE4_CH_RX_RESET_ADDR, GTYE4_CH_RX_RESET_MASK, GTYE4_CH_RX_RESET_LSB); +int gtye4_ch_rx_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye4, rx_pma_reset, GTYE4_CH_RX_PMA_RESET_ADDR, GTYE4_CH_RX_PMA_RESET_MASK, GTYE4_CH_RX_PMA_RESET_LSB); +int gtye4_ch_rx_pma_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye4, rx_pcs_reset, GTYE4_CH_RX_PCS_RESET_ADDR, GTYE4_CH_RX_PCS_RESET_MASK, GTYE4_CH_RX_PCS_RESET_LSB); +int gtye4_ch_rx_pcs_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye4, rx_dfe_lpm_reset, GTYE4_CH_RX_DFE_LPM_RESET_ADDR, GTYE4_CH_RX_DFE_LPM_RESET_MASK, GTYE4_CH_RX_DFE_LPM_RESET_LSB); +int gtye4_ch_rx_dfe_lpm_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_rw16(gtye4, eyescan_reset, GTYE4_CH_EYESCAN_RESET_ADDR, GTYE4_CH_EYESCAN_RESET_MASK, GTYE4_CH_EYESCAN_RESET_LSB); +int gtye4_ch_eyescan_reset(struct gt_ch *ch); +def_gt_ch_masked_reg_read16(gtye4, rx_reset_done, GTYE4_CH_RX_RESET_DONE_ADDR, GTYE4_CH_RX_RESET_DONE_MASK, GTYE4_CH_RX_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye4, rx_gt_reset_done, GTYE4_CH_RX_GT_RESET_DONE_ADDR, GTYE4_CH_RX_GT_RESET_DONE_MASK, GTYE4_CH_RX_GT_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye4, rx_pma_reset_done, GTYE4_CH_RX_PMA_RESET_DONE_ADDR, GTYE4_CH_RX_PMA_RESET_DONE_MASK, GTYE4_CH_RX_PMA_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye4, rx_prgdiv_reset_done, GTYE4_CH_RX_PRGDIV_RESET_DONE_ADDR, GTYE4_CH_RX_PRGDIV_RESET_DONE_MASK, GTYE4_CH_RX_PRGDIV_RESET_DONE_LSB); +def_gt_ch_masked_reg_read16(gtye4, rx_usrclk_act, GTYE4_CH_RX_USRCLK_ACT_ADDR, GTYE4_CH_RX_USRCLK_ACT_MASK, GTYE4_CH_RX_USRCLK_ACT_LSB); +def_gt_ch_masked_reg_rw16(gtye4, rx_pd, GTYE4_CH_RX_PD_ADDR, GTYE4_CH_RX_PD_MASK, GTYE4_CH_RX_PD_LSB); +def_gt_ch_masked_reg_rw16(gtye4, rx_qpll_sel, GTYE4_CH_RX_QPLL_SEL_ADDR, GTYE4_CH_RX_QPLL_SEL_MASK, GTYE4_CH_RX_QPLL_SEL_LSB); +def_gt_ch_masked_reg_rw16(gtye4, loopback, GTYE4_CH_LOOPBACK_ADDR, GTYE4_CH_LOOPBACK_MASK, GTYE4_CH_LOOPBACK_LSB); +def_gt_ch_masked_reg_rw16(gtye4, rx_polarity, GTYE4_CH_RX_POLARITY_ADDR, GTYE4_CH_RX_POLARITY_MASK, GTYE4_CH_RX_POLARITY_LSB); +def_gt_ch_masked_reg_rw16(gtye4, rx_cdr_hold, GTYE4_CH_RX_CDR_HOLD_ADDR, GTYE4_CH_RX_CDR_HOLD_MASK, GTYE4_CH_RX_CDR_HOLD_LSB); +def_gt_ch_masked_reg_read16(gtye4, rx_cdr_lock, GTYE4_CH_RX_CDR_LOCK_ADDR, GTYE4_CH_RX_CDR_LOCK_MASK, GTYE4_CH_RX_CDR_LOCK_LSB); +def_gt_ch_masked_reg_rw16(gtye4, rx_lpm_en, GTYE4_CH_RX_LPM_EN_ADDR, GTYE4_CH_RX_LPM_EN_MASK, GTYE4_CH_RX_LPM_EN_LSB); +def_gt_ch_masked_reg_read16(gtye4, rx_dmonitor, GTYE4_CH_RX_DMONITOR_ADDR, GTYE4_CH_RX_DMONITOR_MASK, GTYE4_CH_RX_DMONITOR_LSB); +def_gt_ch_masked_reg_rw16(gtye4, rx_prbs_sel, GTYE4_CH_RX_PRBS_SEL_ADDR, GTYE4_CH_RX_PRBS_SEL_MASK, GTYE4_CH_RX_PRBS_SEL_LSB); +def_gt_ch_masked_reg_rw16(gtye4, rx_prbs_cnt_reset, GTYE4_CH_RX_PRBS_CNT_RESET_ADDR, GTYE4_CH_RX_PRBS_CNT_RESET_MASK, GTYE4_CH_RX_PRBS_CNT_RESET_LSB); +def_gt_ch_masked_reg_read16(gtye4, rx_prbs_locked, GTYE4_CH_RX_PRBS_LOCKED_ADDR, GTYE4_CH_RX_PRBS_LOCKED_MASK, GTYE4_CH_RX_PRBS_LOCKED_LSB); +def_gt_ch_masked_reg_read16(gtye4, rx_prbs_error, GTYE4_CH_RX_PRBS_ERROR_ADDR, GTYE4_CH_RX_PRBS_ERROR_MASK, GTYE4_CH_RX_PRBS_ERROR_LSB); + +// common +def_gt_pll_masked_reg_rw16(gtye4, qpll0_cfg0, GTYE4_COM_QPLL0_CFG0_ADDR, GTYE4_COM_QPLL0_CFG0_MASK, GTYE4_COM_QPLL0_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, common_cfg0, GTYE4_COM_COMMON_CFG0_ADDR, GTYE4_COM_COMMON_CFG0_MASK, GTYE4_COM_COMMON_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, ppf0_cfg, GTYE4_COM_PPF0_CFG_ADDR, GTYE4_COM_PPF0_CFG_MASK, GTYE4_COM_PPF0_CFG_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0clkout_rate, GTYE4_COM_QPLL0CLKOUT_RATE_ADDR, GTYE4_COM_QPLL0CLKOUT_RATE_MASK, GTYE4_COM_QPLL0CLKOUT_RATE_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_cfg1, GTYE4_COM_QPLL0_CFG1_ADDR, GTYE4_COM_QPLL0_CFG1_MASK, GTYE4_COM_QPLL0_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_cfg2, GTYE4_COM_QPLL0_CFG2_ADDR, GTYE4_COM_QPLL0_CFG2_MASK, GTYE4_COM_QPLL0_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_lock_cfg, GTYE4_COM_QPLL0_LOCK_CFG_ADDR, GTYE4_COM_QPLL0_LOCK_CFG_MASK, GTYE4_COM_QPLL0_LOCK_CFG_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_init_cfg0, GTYE4_COM_QPLL0_INIT_CFG0_ADDR, GTYE4_COM_QPLL0_INIT_CFG0_MASK, GTYE4_COM_QPLL0_INIT_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_init_cfg1, GTYE4_COM_QPLL0_INIT_CFG1_ADDR, GTYE4_COM_QPLL0_INIT_CFG1_MASK, GTYE4_COM_QPLL0_INIT_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_fbdiv, GTYE4_COM_QPLL0_FBDIV_ADDR, GTYE4_COM_QPLL0_FBDIV_MASK, GTYE4_COM_QPLL0_FBDIV_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_cfg3, GTYE4_COM_QPLL0_CFG3_ADDR, GTYE4_COM_QPLL0_CFG3_MASK, GTYE4_COM_QPLL0_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_cp, GTYE4_COM_QPLL0_CP_ADDR, GTYE4_COM_QPLL0_CP_MASK, GTYE4_COM_QPLL0_CP_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_refclk_div, GTYE4_COM_QPLL0_REFCLK_DIV_ADDR, GTYE4_COM_QPLL0_REFCLK_DIV_MASK, GTYE4_COM_QPLL0_REFCLK_DIV_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_ips_refclk_sel, GTYE4_COM_QPLL0_IPS_REFCLK_SEL_ADDR, GTYE4_COM_QPLL0_IPS_REFCLK_SEL_MASK, GTYE4_COM_QPLL0_IPS_REFCLK_SEL_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_ips_en, GTYE4_COM_QPLL0_IPS_EN_ADDR, GTYE4_COM_QPLL0_IPS_EN_MASK, GTYE4_COM_QPLL0_IPS_EN_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_lpf, GTYE4_COM_QPLL0_LPF_ADDR, GTYE4_COM_QPLL0_LPF_MASK, GTYE4_COM_QPLL0_LPF_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_cfg1_g3, GTYE4_COM_QPLL0_CFG1_G3_ADDR, GTYE4_COM_QPLL0_CFG1_G3_MASK, GTYE4_COM_QPLL0_CFG1_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_cfg2_g3, GTYE4_COM_QPLL0_CFG2_G3_ADDR, GTYE4_COM_QPLL0_CFG2_G3_MASK, GTYE4_COM_QPLL0_CFG2_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_lpf_g3, GTYE4_COM_QPLL0_LPF_G3_ADDR, GTYE4_COM_QPLL0_LPF_G3_MASK, GTYE4_COM_QPLL0_LPF_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_lock_cfg_g3, GTYE4_COM_QPLL0_LOCK_CFG_G3_ADDR, GTYE4_COM_QPLL0_LOCK_CFG_G3_MASK, GTYE4_COM_QPLL0_LOCK_CFG_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, rsvd_attr0, GTYE4_COM_RSVD_ATTR0_ADDR, GTYE4_COM_RSVD_ATTR0_MASK, GTYE4_COM_RSVD_ATTR0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_fbdiv_g3, GTYE4_COM_QPLL0_FBDIV_G3_ADDR, GTYE4_COM_QPLL0_FBDIV_G3_MASK, GTYE4_COM_QPLL0_FBDIV_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_rate_sw_use_drp, GTYE4_COM_QPLL0_RATE_SW_USE_DRP_ADDR, GTYE4_COM_QPLL0_RATE_SW_USE_DRP_MASK, GTYE4_COM_QPLL0_RATE_SW_USE_DRP_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_pcie_en, GTYE4_COM_QPLL0_PCIE_EN_ADDR, GTYE4_COM_QPLL0_PCIE_EN_MASK, GTYE4_COM_QPLL0_PCIE_EN_LSB); +def_gt_pll_masked_reg_rw16(gtye4, rxrecclkout0_sel, GTYE4_COM_RXRECCLKOUT0_SEL_ADDR, GTYE4_COM_RXRECCLKOUT0_SEL_MASK, GTYE4_COM_RXRECCLKOUT0_SEL_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_sdm_cfg0, GTYE4_COM_QPLL0_SDM_CFG0_ADDR, GTYE4_COM_QPLL0_SDM_CFG0_MASK, GTYE4_COM_QPLL0_SDM_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_sdm_cfg1, GTYE4_COM_QPLL0_SDM_CFG1_ADDR, GTYE4_COM_QPLL0_SDM_CFG1_MASK, GTYE4_COM_QPLL0_SDM_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, sdm0initseed0_0, GTYE4_COM_SDM0INITSEED0_0_ADDR, GTYE4_COM_SDM0INITSEED0_0_MASK, GTYE4_COM_SDM0INITSEED0_0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, sdm0initseed0_1, GTYE4_COM_SDM0INITSEED0_1_ADDR, GTYE4_COM_SDM0INITSEED0_1_MASK, GTYE4_COM_SDM0INITSEED0_1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_sdm_cfg2, GTYE4_COM_QPLL0_SDM_CFG2_ADDR, GTYE4_COM_QPLL0_SDM_CFG2_MASK, GTYE4_COM_QPLL0_SDM_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_cp_g3, GTYE4_COM_QPLL0_CP_G3_ADDR, GTYE4_COM_QPLL0_CP_G3_MASK, GTYE4_COM_QPLL0_CP_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, rsvd_attr1, GTYE4_COM_RSVD_ATTR1_ADDR, GTYE4_COM_RSVD_ATTR1_MASK, GTYE4_COM_RSVD_ATTR1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll0_cfg4, GTYE4_COM_QPLL0_CFG4_ADDR, GTYE4_COM_QPLL0_CFG4_MASK, GTYE4_COM_QPLL0_CFG4_LSB); +def_gt_pll_masked_reg_rw16(gtye4, ub_cfg0, GTYE4_COM_UB_CFG0_ADDR, GTYE4_COM_UB_CFG0_MASK, GTYE4_COM_UB_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, ub_cfg1, GTYE4_COM_UB_CFG1_ADDR, GTYE4_COM_UB_CFG1_MASK, GTYE4_COM_UB_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, ub_cfg2, GTYE4_COM_UB_CFG2_ADDR, GTYE4_COM_UB_CFG2_MASK, GTYE4_COM_UB_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gtye4, ub_cfg3, GTYE4_COM_UB_CFG3_ADDR, GTYE4_COM_UB_CFG3_MASK, GTYE4_COM_UB_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, ub_cfg4, GTYE4_COM_UB_CFG4_ADDR, GTYE4_COM_UB_CFG4_MASK, GTYE4_COM_UB_CFG4_LSB); +def_gt_pll_masked_reg_rw16(gtye4, ub_cfg5, GTYE4_COM_UB_CFG5_ADDR, GTYE4_COM_UB_CFG5_MASK, GTYE4_COM_UB_CFG5_LSB); +def_gt_pll_masked_reg_rw16(gtye4, ub_cfg6, GTYE4_COM_UB_CFG6_ADDR, GTYE4_COM_UB_CFG6_MASK, GTYE4_COM_UB_CFG6_LSB); +def_gt_pll_masked_reg_rw16(gtye4, bias_cfg0, GTYE4_COM_BIAS_CFG0_ADDR, GTYE4_COM_BIAS_CFG0_MASK, GTYE4_COM_BIAS_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, bias_cfg1, GTYE4_COM_BIAS_CFG1_ADDR, GTYE4_COM_BIAS_CFG1_MASK, GTYE4_COM_BIAS_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, bias_cfg2, GTYE4_COM_BIAS_CFG2_ADDR, GTYE4_COM_BIAS_CFG2_MASK, GTYE4_COM_BIAS_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gtye4, bias_cfg3, GTYE4_COM_BIAS_CFG3_ADDR, GTYE4_COM_BIAS_CFG3_MASK, GTYE4_COM_BIAS_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, bias_cfg4, GTYE4_COM_BIAS_CFG4_ADDR, GTYE4_COM_BIAS_CFG4_MASK, GTYE4_COM_BIAS_CFG4_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_cfg0, GTYE4_COM_QPLL1_CFG0_ADDR, GTYE4_COM_QPLL1_CFG0_MASK, GTYE4_COM_QPLL1_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, common_cfg1, GTYE4_COM_COMMON_CFG1_ADDR, GTYE4_COM_COMMON_CFG1_MASK, GTYE4_COM_COMMON_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, por_cfg, GTYE4_COM_POR_CFG_ADDR, GTYE4_COM_POR_CFG_MASK, GTYE4_COM_POR_CFG_LSB); +def_gt_pll_masked_reg_rw16(gtye4, ppf1_cfg, GTYE4_COM_PPF1_CFG_ADDR, GTYE4_COM_PPF1_CFG_MASK, GTYE4_COM_PPF1_CFG_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1clkout_rate, GTYE4_COM_QPLL1CLKOUT_RATE_ADDR, GTYE4_COM_QPLL1CLKOUT_RATE_MASK, GTYE4_COM_QPLL1CLKOUT_RATE_LSB); +def_gt_pll_masked_reg_rw16(gtye4, bias_cfg_rsvd, GTYE4_COM_BIAS_CFG_RSVD_ADDR, GTYE4_COM_BIAS_CFG_RSVD_MASK, GTYE4_COM_BIAS_CFG_RSVD_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_cfg1, GTYE4_COM_QPLL1_CFG1_ADDR, GTYE4_COM_QPLL1_CFG1_MASK, GTYE4_COM_QPLL1_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_cfg2, GTYE4_COM_QPLL1_CFG2_ADDR, GTYE4_COM_QPLL1_CFG2_MASK, GTYE4_COM_QPLL1_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_lock_cfg, GTYE4_COM_QPLL1_LOCK_CFG_ADDR, GTYE4_COM_QPLL1_LOCK_CFG_MASK, GTYE4_COM_QPLL1_LOCK_CFG_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_init_cfg0, GTYE4_COM_QPLL1_INIT_CFG0_ADDR, GTYE4_COM_QPLL1_INIT_CFG0_MASK, GTYE4_COM_QPLL1_INIT_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_init_cfg1, GTYE4_COM_QPLL1_INIT_CFG1_ADDR, GTYE4_COM_QPLL1_INIT_CFG1_MASK, GTYE4_COM_QPLL1_INIT_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_fbdiv, GTYE4_COM_QPLL1_FBDIV_ADDR, GTYE4_COM_QPLL1_FBDIV_MASK, GTYE4_COM_QPLL1_FBDIV_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_cfg3, GTYE4_COM_QPLL1_CFG3_ADDR, GTYE4_COM_QPLL1_CFG3_MASK, GTYE4_COM_QPLL1_CFG3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_cp, GTYE4_COM_QPLL1_CP_ADDR, GTYE4_COM_QPLL1_CP_MASK, GTYE4_COM_QPLL1_CP_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_refclk_div, GTYE4_COM_QPLL1_REFCLK_DIV_ADDR, GTYE4_COM_QPLL1_REFCLK_DIV_MASK, GTYE4_COM_QPLL1_REFCLK_DIV_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_ips_refclk_sel, GTYE4_COM_QPLL1_IPS_REFCLK_SEL_ADDR, GTYE4_COM_QPLL1_IPS_REFCLK_SEL_MASK, GTYE4_COM_QPLL1_IPS_REFCLK_SEL_LSB); +def_gt_pll_masked_reg_rw16(gtye4, sarc_en, GTYE4_COM_SARC_EN_ADDR, GTYE4_COM_SARC_EN_MASK, GTYE4_COM_SARC_EN_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_ips_en, GTYE4_COM_QPLL1_IPS_EN_ADDR, GTYE4_COM_QPLL1_IPS_EN_MASK, GTYE4_COM_QPLL1_IPS_EN_LSB); +def_gt_pll_masked_reg_rw16(gtye4, sarc_sel, GTYE4_COM_SARC_SEL_ADDR, GTYE4_COM_SARC_SEL_MASK, GTYE4_COM_SARC_SEL_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_lpf, GTYE4_COM_QPLL1_LPF_ADDR, GTYE4_COM_QPLL1_LPF_MASK, GTYE4_COM_QPLL1_LPF_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_cfg1_g3, GTYE4_COM_QPLL1_CFG1_G3_ADDR, GTYE4_COM_QPLL1_CFG1_G3_MASK, GTYE4_COM_QPLL1_CFG1_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_cfg2_g3, GTYE4_COM_QPLL1_CFG2_G3_ADDR, GTYE4_COM_QPLL1_CFG2_G3_MASK, GTYE4_COM_QPLL1_CFG2_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_lpf_g3, GTYE4_COM_QPLL1_LPF_G3_ADDR, GTYE4_COM_QPLL1_LPF_G3_MASK, GTYE4_COM_QPLL1_LPF_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_lock_cfg_g3, GTYE4_COM_QPLL1_LOCK_CFG_G3_ADDR, GTYE4_COM_QPLL1_LOCK_CFG_G3_MASK, GTYE4_COM_QPLL1_LOCK_CFG_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, rsvd_attr2, GTYE4_COM_RSVD_ATTR2_ADDR, GTYE4_COM_RSVD_ATTR2_MASK, GTYE4_COM_RSVD_ATTR2_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_fbdiv_g3, GTYE4_COM_QPLL1_FBDIV_G3_ADDR, GTYE4_COM_QPLL1_FBDIV_G3_MASK, GTYE4_COM_QPLL1_FBDIV_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_rate_sw_use_drp, GTYE4_COM_QPLL1_RATE_SW_USE_DRP_ADDR, GTYE4_COM_QPLL1_RATE_SW_USE_DRP_MASK, GTYE4_COM_QPLL1_RATE_SW_USE_DRP_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_pci_en, GTYE4_COM_QPLL1_PCI_EN_ADDR, GTYE4_COM_QPLL1_PCI_EN_MASK, GTYE4_COM_QPLL1_PCI_EN_LSB); +def_gt_pll_masked_reg_rw16(gtye4, rxrecclkout1_sel, GTYE4_COM_RXRECCLKOUT1_SEL_ADDR, GTYE4_COM_RXRECCLKOUT1_SEL_MASK, GTYE4_COM_RXRECCLKOUT1_SEL_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_sdm_cfg0, GTYE4_COM_QPLL1_SDM_CFG0_ADDR, GTYE4_COM_QPLL1_SDM_CFG0_MASK, GTYE4_COM_QPLL1_SDM_CFG0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_sdm_cfg1, GTYE4_COM_QPLL1_SDM_CFG1_ADDR, GTYE4_COM_QPLL1_SDM_CFG1_MASK, GTYE4_COM_QPLL1_SDM_CFG1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, sdm1initseed0_0, GTYE4_COM_SDM1INITSEED0_0_ADDR, GTYE4_COM_SDM1INITSEED0_0_MASK, GTYE4_COM_SDM1INITSEED0_0_LSB); +def_gt_pll_masked_reg_rw16(gtye4, sdm1initseed0_1, GTYE4_COM_SDM1INITSEED0_1_ADDR, GTYE4_COM_SDM1INITSEED0_1_MASK, GTYE4_COM_SDM1INITSEED0_1_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_sdm_cfg2, GTYE4_COM_QPLL1_SDM_CFG2_ADDR, GTYE4_COM_QPLL1_SDM_CFG2_MASK, GTYE4_COM_QPLL1_SDM_CFG2_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_cp_g3, GTYE4_COM_QPLL1_CP_G3_ADDR, GTYE4_COM_QPLL1_CP_G3_MASK, GTYE4_COM_QPLL1_CP_G3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, rsvd_attr3, GTYE4_COM_RSVD_ATTR3_ADDR, GTYE4_COM_RSVD_ATTR3_MASK, GTYE4_COM_RSVD_ATTR3_LSB); +def_gt_pll_masked_reg_rw16(gtye4, qpll1_cfg4, GTYE4_COM_QPLL1_CFG4_ADDR, GTYE4_COM_QPLL1_CFG4_MASK, GTYE4_COM_QPLL1_CFG4_LSB); + +// RX +def_gt_ch_masked_reg_rw16(gtye4, rx_data_width_raw, GTYE4_CH_RX_DATA_WIDTH_ADDR, GTYE4_CH_RX_DATA_WIDTH_MASK, GTYE4_CH_RX_DATA_WIDTH_LSB); +int gtye4_ch_get_rx_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gtye4, rx_int_data_width_raw, GTYE4_CH_RX_INT_DATAWIDTH_ADDR, GTYE4_CH_RX_INT_DATAWIDTH_MASK, GTYE4_CH_RX_INT_DATAWIDTH_LSB); +int gtye4_ch_get_rx_int_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gtye4, es_prescale, GTYE4_CH_ES_PRESCALE_ADDR, GTYE4_CH_ES_PRESCALE_MASK, GTYE4_CH_ES_PRESCALE_LSB); +def_gt_ch_masked_reg_rw16(gtye4, es_eye_scan_en, GTYE4_CH_ES_EYE_SCAN_EN_ADDR, GTYE4_CH_ES_EYE_SCAN_EN_MASK, GTYE4_CH_ES_EYE_SCAN_EN_LSB); +def_gt_ch_masked_reg_rw16(gtye4, es_errdet_en, GTYE4_CH_ES_ERRDET_EN_ADDR, GTYE4_CH_ES_ERRDET_EN_MASK, GTYE4_CH_ES_ERRDET_EN_LSB); +def_gt_ch_masked_reg_rw16(gtye4, es_control, GTYE4_CH_ES_CONTROL_ADDR, GTYE4_CH_ES_CONTROL_MASK, GTYE4_CH_ES_CONTROL_LSB); + +int gtye4_ch_set_es_qual_mask(struct gt_ch *ch, uint8_t *mask); +int gtye4_ch_set_es_qual_mask_clear(struct gt_ch *ch); + +int gtye4_ch_set_es_sdata_mask(struct gt_ch *ch, uint8_t *mask); +int gtye4_ch_set_es_sdata_mask_width(struct gt_ch *ch, int width); + +def_gt_ch_masked_reg_rw16(gtye4, es_horz_offset, GTYE4_CH_ES_HORZ_OFFSET_ADDR, GTYE4_CH_ES_HORZ_OFFSET_MASK, GTYE4_CH_ES_HORZ_OFFSET_LSB); +def_gt_ch_masked_reg_rw16(gtye4, rx_eyescan_vs_range, GTYE4_CH_RX_EYESCAN_VS_RANGE_ADDR, GTYE4_CH_RX_EYESCAN_VS_RANGE_MASK, GTYE4_CH_RX_EYESCAN_VS_RANGE_LSB); +def_gt_ch_masked_reg_rw16(gtye4, rx_eyescan_vs_code, GTYE4_CH_RX_EYESCAN_VS_CODE_ADDR, GTYE4_CH_RX_EYESCAN_VS_CODE_MASK, GTYE4_CH_RX_EYESCAN_VS_CODE_LSB); +def_gt_ch_masked_reg_rw16(gtye4, rx_eyescan_vs_ut_sign, GTYE4_CH_RX_EYESCAN_VS_UT_SIGN_ADDR, GTYE4_CH_RX_EYESCAN_VS_UT_SIGN_MASK, GTYE4_CH_RX_EYESCAN_VS_UT_SIGN_LSB); +def_gt_ch_masked_reg_rw16(gtye4, rx_eyescan_vs_neg_dir, GTYE4_CH_RX_EYESCAN_VS_NEG_DIR_ADDR, GTYE4_CH_RX_EYESCAN_VS_NEG_DIR_MASK, GTYE4_CH_RX_EYESCAN_VS_NEG_DIR_LSB); +def_gt_ch_masked_reg_read16(gtye4, es_error_count, GTYE4_CH_ES_ERROR_COUNT_ADDR, GTYE4_CH_ES_ERROR_COUNT_MASK, GTYE4_CH_ES_ERROR_COUNT_LSB); +def_gt_ch_masked_reg_read16(gtye4, es_sample_count, GTYE4_CH_ES_SAMPLE_COUNT_ADDR, GTYE4_CH_ES_SAMPLE_COUNT_MASK, GTYE4_CH_ES_SAMPLE_COUNT_LSB); +def_gt_ch_masked_reg_read16(gtye4, es_control_status, GTYE4_CH_ES_CONTROL_STATUS_ADDR, GTYE4_CH_ES_CONTROL_STATUS_MASK, GTYE4_CH_ES_CONTROL_STATUS_LSB); + +int gtye4_ch_get_rx_prbs_error_count(struct gt_ch *ch, uint32_t *val); + +// TX +def_gt_ch_masked_reg_rw16(gtye4, tx_data_width_raw, GTYE4_CH_TX_DATA_WIDTH_ADDR, GTYE4_CH_TX_DATA_WIDTH_MASK, GTYE4_CH_TX_DATA_WIDTH_LSB); +int gtye4_ch_get_tx_data_width(struct gt_ch *ch, uint32_t *val); + +def_gt_ch_masked_reg_rw16(gtye4, tx_int_data_width_raw, GTYE4_CH_TX_INT_DATAWIDTH_ADDR, GTYE4_CH_TX_INT_DATAWIDTH_MASK, GTYE4_CH_TX_INT_DATAWIDTH_LSB); +int gtye4_ch_get_tx_int_data_width(struct gt_ch *ch, uint32_t *val); + +extern const struct gt_quad_ops gtye4_gt_quad_ops; + +#endif /* XCVR_GTYE4_H */ From c814208e311253ed99bce6eae0b30828e285b89d Mon Sep 17 00:00:00 2001 From: Jeffery Lim <17893528+JefferyLim@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:18:09 -0400 Subject: [PATCH 2/7] Remove extra whitespace in mqnic_core_pcie.v Removed unnecessary whitespace before pcie_tlp_mux instantiation. --- fpga/common/rtl/mqnic_core_pcie.v | 1 - 1 file changed, 1 deletion(-) diff --git a/fpga/common/rtl/mqnic_core_pcie.v b/fpga/common/rtl/mqnic_core_pcie.v index b077e49..0fa6fbb 100644 --- a/fpga/common/rtl/mqnic_core_pcie.v +++ b/fpga/common/rtl/mqnic_core_pcie.v @@ -785,7 +785,6 @@ if (APP_ENABLE) begin : pcie_tlp_mux .fifo_half_full(), .fifo_watermark() ); - pcie_tlp_mux #( .PORTS(2), From 410dd664fa6b1903a16f7d2a8e6a2cef6fa5adaf Mon Sep 17 00:00:00 2001 From: Jeffery Lim <17893528+JefferyLim@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:20:46 -0400 Subject: [PATCH 3/7] Enable RS FEC for QSFP CMAC instances Disabled for Cloudlab hardware --- fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au280.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au280.v b/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au280.v index 80c06db..d2954d1 100644 --- a/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au280.v +++ b/fpga/mqnic/Alveo/fpga_100g/rtl/fpga_au280.v @@ -1098,7 +1098,7 @@ cmac_gty_wrapper #( .AXIS_KEEP_WIDTH(AXIS_ETH_KEEP_WIDTH), .TX_SERDES_PIPELINE(0), .RX_SERDES_PIPELINE(0), - .RS_FEC_ENABLE(0) + .RS_FEC_ENABLE(1) ) qsfp0_cmac_inst ( .xcvr_ctrl_clk(clk_125mhz_int), @@ -1223,7 +1223,7 @@ cmac_gty_wrapper #( .AXIS_KEEP_WIDTH(AXIS_ETH_KEEP_WIDTH), .TX_SERDES_PIPELINE(0), .RX_SERDES_PIPELINE(0), - .RS_FEC_ENABLE(0) + .RS_FEC_ENABLE(1) ) qsfp1_cmac_inst ( .xcvr_ctrl_clk(clk_125mhz_int), From 6d1c688e69e1e05fcbfadab800e1a9f2c0fe7817 Mon Sep 17 00:00:00 2001 From: Jeffery Lim <17893528+JefferyLim@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:24:16 -0400 Subject: [PATCH 4/7] Remove debug logging for queue counts Removed debug information logging for txq_count and rxq_count. --- modules/mqnic/mqnic_netdev.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/mqnic/mqnic_netdev.c b/modules/mqnic/mqnic_netdev.c index f49c993..853b0f8 100644 --- a/modules/mqnic/mqnic_netdev.c +++ b/modules/mqnic/mqnic_netdev.c @@ -574,8 +574,6 @@ struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, priv->txq_count = min_t(u32, mqnic_res_get_count(interface->txq_res), 256); priv->rxq_count = min_t(u32, mqnic_res_get_count(interface->rxq_res), num_online_cpus()); - dev_info(dev, "%d vs %d\n", priv->txq_count, priv->rxq_count); - priv->tx_ring_size = roundup_pow_of_two(clamp_t(u32, mqnic_num_txq_entries, MQNIC_MIN_TX_RING_SZ, MQNIC_MAX_TX_RING_SZ)); priv->rx_ring_size = roundup_pow_of_two(clamp_t(u32, mqnic_num_rxq_entries, From 97589fa6685dba3b5b824f184aefca39906ec810 Mon Sep 17 00:00:00 2001 From: JefferyLim Date: Thu, 30 Apr 2026 14:25:03 -0400 Subject: [PATCH 5/7] Removing redundant directory - VF driver is in the main mqnic directory --- modules/mqnic_vf/.gitignore | 1 - modules/mqnic_vf/Makefile | 1 - modules/mqnic_vf/device-tree-binding.txt | 1 - modules/mqnic_vf/mqnic.h | 648 ---------------- modules/mqnic_vf/mqnic_board.c | 1 - modules/mqnic_vf/mqnic_clk_info.c | 1 - modules/mqnic_vf/mqnic_cq.c | 1 - modules/mqnic_vf/mqnic_dev.c | 1 - modules/mqnic_vf/mqnic_devlink.c | 1 - modules/mqnic_vf/mqnic_eq.c | 260 ------- modules/mqnic_vf/mqnic_ethtool.c | 655 ---------------- modules/mqnic_vf/mqnic_hw.h | 1 - modules/mqnic_vf/mqnic_i2c.c | 1 - modules/mqnic_vf/mqnic_if.c | 400 ---------- modules/mqnic_vf/mqnic_ioctl.h | 1 - modules/mqnic_vf/mqnic_irq.c | 1 - modules/mqnic_vf/mqnic_main.c | 918 ----------------------- modules/mqnic_vf/mqnic_netdev.c | 691 ----------------- modules/mqnic_vf/mqnic_port.c | 1 - modules/mqnic_vf/mqnic_ptp.c | 1 - modules/mqnic_vf/mqnic_reg_block.c | 1 - modules/mqnic_vf/mqnic_res.c | 1 - modules/mqnic_vf/mqnic_rx.c | 1 - modules/mqnic_vf/mqnic_sched_block.c | 1 - modules/mqnic_vf/mqnic_scheduler.c | 1 - modules/mqnic_vf/mqnic_stats.c | 1 - modules/mqnic_vf/mqnic_tx.c | 1 - 27 files changed, 3593 deletions(-) delete mode 120000 modules/mqnic_vf/.gitignore delete mode 120000 modules/mqnic_vf/Makefile delete mode 120000 modules/mqnic_vf/device-tree-binding.txt delete mode 100644 modules/mqnic_vf/mqnic.h delete mode 120000 modules/mqnic_vf/mqnic_board.c delete mode 120000 modules/mqnic_vf/mqnic_clk_info.c delete mode 120000 modules/mqnic_vf/mqnic_cq.c delete mode 120000 modules/mqnic_vf/mqnic_dev.c delete mode 120000 modules/mqnic_vf/mqnic_devlink.c delete mode 100644 modules/mqnic_vf/mqnic_eq.c delete mode 100644 modules/mqnic_vf/mqnic_ethtool.c delete mode 120000 modules/mqnic_vf/mqnic_hw.h delete mode 120000 modules/mqnic_vf/mqnic_i2c.c delete mode 100644 modules/mqnic_vf/mqnic_if.c delete mode 120000 modules/mqnic_vf/mqnic_ioctl.h delete mode 120000 modules/mqnic_vf/mqnic_irq.c delete mode 100644 modules/mqnic_vf/mqnic_main.c delete mode 100644 modules/mqnic_vf/mqnic_netdev.c delete mode 120000 modules/mqnic_vf/mqnic_port.c delete mode 120000 modules/mqnic_vf/mqnic_ptp.c delete mode 120000 modules/mqnic_vf/mqnic_reg_block.c delete mode 120000 modules/mqnic_vf/mqnic_res.c delete mode 120000 modules/mqnic_vf/mqnic_rx.c delete mode 120000 modules/mqnic_vf/mqnic_sched_block.c delete mode 120000 modules/mqnic_vf/mqnic_scheduler.c delete mode 120000 modules/mqnic_vf/mqnic_stats.c delete mode 120000 modules/mqnic_vf/mqnic_tx.c diff --git a/modules/mqnic_vf/.gitignore b/modules/mqnic_vf/.gitignore deleted file mode 120000 index 7a1925d..0000000 --- a/modules/mqnic_vf/.gitignore +++ /dev/null @@ -1 +0,0 @@ -../mqnic/.gitignore \ No newline at end of file diff --git a/modules/mqnic_vf/Makefile b/modules/mqnic_vf/Makefile deleted file mode 120000 index d07fcae..0000000 --- a/modules/mqnic_vf/Makefile +++ /dev/null @@ -1 +0,0 @@ -../mqnic/Makefile \ No newline at end of file diff --git a/modules/mqnic_vf/device-tree-binding.txt b/modules/mqnic_vf/device-tree-binding.txt deleted file mode 120000 index b570624..0000000 --- a/modules/mqnic_vf/device-tree-binding.txt +++ /dev/null @@ -1 +0,0 @@ -../mqnic/device-tree-binding.txt \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic.h b/modules/mqnic_vf/mqnic.h deleted file mode 100644 index e6fecc9..0000000 --- a/modules/mqnic_vf/mqnic.h +++ /dev/null @@ -1,648 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause-Views -/* - * Copyright (c) 2019-2023 The Regents of the University of California - */ - -#ifndef MQNIC_H -#define MQNIC_H - -#include -#ifdef CONFIG_PCI -#include -#endif -#ifdef CONFIG_AUXILIARY_BUS -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DRIVER_NAME "mqnic" -#define DRIVER_VERSION "0.1" - -#include "mqnic_hw.h" - -#ifdef CONFIG_OF -/* platform driver OF-related definitions */ -#define MQNIC_PROP_MAC_ADDR_INC_BYTE "mac-address-increment-byte" -#define MQNIC_PROP_MAC_ADDR_INC "mac-address-increment" -#define MQNIC_PROP_MAC_ADDR_LOCAL "mac-address-local" -#define MQNIC_PROP_MODULE_EEPROM "module-eeproms" -#endif - -// default interval to poll port TX/RX status, in ms -#define MQNIC_LINK_STATUS_POLL_MS 1000 - -// Scott - -#define MY_MAC 0 - -extern unsigned int mqnic_num_eq_entries; -extern unsigned int mqnic_num_txq_entries; -extern unsigned int mqnic_num_rxq_entries; - -extern unsigned int mqnic_link_status_poll; - -struct mqnic_dev; -struct mqnic_if; - -struct mqnic_res { - unsigned int count; - u8 __iomem *base; - unsigned int stride; - - spinlock_t lock; - unsigned long *bmap; -}; - -struct mqnic_reg_block { - u32 type; - u32 version; - u8 __iomem *regs; - u8 __iomem *base; -}; - -struct mqnic_board_ops { - int (*init)(struct mqnic_dev *mqnic); - void (*deinit)(struct mqnic_dev *mqnic); -}; - -struct mqnic_i2c_bus { - struct mqnic_dev *mqnic; - - u8 __iomem *scl_in_reg; - u8 __iomem *scl_out_reg; - u8 __iomem *sda_in_reg; - u8 __iomem *sda_out_reg; - - u32 scl_in_mask; - u32 scl_out_mask; - u32 sda_in_mask; - u32 sda_out_mask; - - struct list_head head; - - struct i2c_algo_bit_data algo; - struct i2c_adapter adapter; -}; - -struct mqnic_irq { - int index; - int irqn; - char name[16 + 3]; - struct atomic_notifier_head nh; -}; - -#ifdef CONFIG_AUXILIARY_BUS -struct mqnic_adev { - struct auxiliary_device adev; - struct mqnic_dev *mdev; - struct mqnic_adev **ptr; - char name[32]; -}; -#endif - -struct mqnic_dev { - struct device *dev; -#ifdef CONFIG_PCI - struct pci_dev *pdev; -#endif - struct platform_device *pfdev; - - resource_size_t hw_regs_size; - phys_addr_t hw_regs_phys; - u8 __iomem *hw_addr; - u8 __iomem *phc_hw_addr; - - resource_size_t app_hw_regs_size; - phys_addr_t app_hw_regs_phys; - u8 __iomem *app_hw_addr; - - resource_size_t ram_hw_regs_size; - phys_addr_t ram_hw_regs_phys; - u8 __iomem *ram_hw_addr; - - struct mutex state_lock; - - int mac_count; - u8 mac_list[MQNIC_MAX_IF][ETH_ALEN]; - - char name[16]; - - int irq_count; - struct mqnic_irq *irq[MQNIC_MAX_IRQ]; - - unsigned int id; - struct list_head dev_list_node; - - struct miscdevice misc_dev; - -#ifdef CONFIG_AUXILIARY_BUS - struct mqnic_adev *app_adev; -#endif - - struct mqnic_reg_block *rb_list; - struct mqnic_reg_block *fw_id_rb; - struct mqnic_reg_block *if_rb; - struct mqnic_reg_block *stats_rb; - struct mqnic_reg_block *clk_info_rb; - struct mqnic_reg_block *phc_rb; - - int phys_port_max; - - u32 fpga_id; - u32 fw_id; - u32 fw_ver; - u32 board_id; - u32 board_ver; - u32 build_date; - u32 git_hash; - u32 rel_info; - u32 num_funcs; - u32 max_irq_per_func; - - u32 app_id; - - u32 stats_offset; - u32 stats_count; - u32 stats_stride; - u32 stats_flags; - - u32 core_clk_nom_per_ns_num; - u32 core_clk_nom_per_ns_denom; - u32 core_clk_nom_freq_hz; - u32 ref_clk_nom_per_ns_num; - u32 ref_clk_nom_per_ns_denom; - u32 ref_clk_nom_freq_hz; - u32 clk_info_channels; - - u32 if_offset; - u32 if_count; - u32 if_stride; - u32 if_csr_offset; - - char build_date_str[32]; - - struct mqnic_if *interface[MQNIC_MAX_IF]; - - struct ptp_clock *ptp_clock; - struct ptp_clock_info ptp_clock_info; - - struct mqnic_board_ops *board_ops; - - struct list_head i2c_bus; - int i2c_adapter_count; - - int mod_i2c_client_count; - struct i2c_client *mod_i2c_client[MQNIC_MAX_IF]; - struct i2c_client *eeprom_i2c_client; -}; - -struct mqnic_frag { - dma_addr_t dma_addr; - u32 len; -}; - -struct mqnic_tx_info { - struct sk_buff *skb; - DEFINE_DMA_UNMAP_ADDR(dma_addr); - DEFINE_DMA_UNMAP_LEN(len); - u32 frag_count; - struct mqnic_frag frags[MQNIC_MAX_FRAGS - 1]; - int ts_requested; -}; - -struct mqnic_rx_info { - struct page *page; - u32 page_order; - u32 page_offset; - dma_addr_t dma_addr; - u32 len; -}; - -struct mqnic_ring { - // written on enqueue (i.e. start_xmit) - u32 prod_ptr; - u64 bytes; - u64 packets; - u64 dropped_packets; - struct netdev_queue *tx_queue; - - // written from completion - u32 cons_ptr ____cacheline_aligned_in_smp; - u64 ts_s; - u8 ts_valid; - - // mostly constant - u32 size; - u32 full_size; - u32 size_mask; - u32 stride; - - u32 cpl_index; - - u32 mtu; - u32 page_order; - - u32 desc_block_size; - u32 log_desc_block_size; - - size_t buf_size; - u8 *buf; - dma_addr_t buf_dma_addr; - - union { - struct mqnic_tx_info *tx_info; - struct mqnic_rx_info *rx_info; - }; - - struct device *dev; - struct mqnic_if *interface; - struct mqnic_priv *priv; - int index; - struct mqnic_cq *cq; - int enabled; - - u8 __iomem *hw_addr; -} ____cacheline_aligned_in_smp; - -struct mqnic_cq { - u32 prod_ptr; - - u32 cons_ptr; - - u32 size; - u32 size_mask; - u32 stride; - - size_t buf_size; - u8 *buf; - dma_addr_t buf_dma_addr; - - struct device *dev; - struct mqnic_if *interface; - struct napi_struct napi; - int cqn; - struct mqnic_eq *eq; - struct mqnic_ring *src_ring; - int enabled; - - void (*handler)(struct mqnic_cq *cq); - - u8 __iomem *hw_addr; -}; - -struct mqnic_eq { - u32 prod_ptr; - - u32 cons_ptr; - - u32 size; - u32 size_mask; - u32 stride; - - size_t buf_size; - u8 *buf; - dma_addr_t buf_dma_addr; - - struct device *dev; - struct mqnic_if *interface; - int eqn; - struct mqnic_irq *irq; - int enabled; - - struct notifier_block irq_nb; - - void (*handler)(struct mqnic_eq *eq); - - spinlock_t table_lock; - struct radix_tree_root cq_table; - - u8 __iomem *hw_addr; -}; - -struct mqnic_sched { - struct device *dev; - struct mqnic_if *interface; - struct mqnic_sched_block *sched_block; - - struct mqnic_reg_block *rb; - - int index; - - u32 type; - u32 offset; - u32 channel_count; - u32 channel_stride; - - u8 __iomem *hw_addr; -}; - -struct mqnic_port { - struct device *dev; - struct mqnic_if *interface; - - struct mqnic_reg_block *port_rb; - struct mqnic_reg_block *rb_list; - struct mqnic_reg_block *port_ctrl_rb; - - int index; - int phys_index; - - u32 port_features; - - struct devlink_port dl_port; -}; - -struct mqnic_sched_block { - struct device *dev; - struct mqnic_if *interface; - - struct mqnic_reg_block *block_rb; - struct mqnic_reg_block *rb_list; - - int index; - - u32 sched_count; - struct mqnic_sched *sched[MQNIC_MAX_PORTS]; -}; - -struct mqnic_if { - struct device *dev; - struct mqnic_dev *mdev; - - struct mqnic_reg_block *rb_list; - struct mqnic_reg_block *if_ctrl_rb; - struct mqnic_reg_block *eq_rb; - struct mqnic_reg_block *cq_rb; - struct mqnic_reg_block *txq_rb; - struct mqnic_reg_block *rxq_rb; - struct mqnic_reg_block *rx_queue_map_rb; - - int index; - - u32 if_features; - - u32 max_tx_mtu; - u32 max_rx_mtu; - u32 tx_fifo_depth; - u32 rx_fifo_depth; - - u32 mac; - - struct mqnic_res *eq_res; - struct mqnic_res *cq_res; - struct mqnic_res *txq_res; - struct mqnic_res *rxq_res; - - u32 eq_count; - struct mqnic_eq *eq[MQNIC_MAX_EQ]; - - u32 port_count; - struct mqnic_port *port[MQNIC_MAX_PORTS]; - - u32 sched_block_count; - struct mqnic_sched_block *sched_block[MQNIC_MAX_PORTS]; - - u32 max_desc_block_size; - - u32 rx_queue_map_indir_table_size; - u8 __iomem *rx_queue_map_indir_table[MQNIC_MAX_PORTS]; - - resource_size_t hw_regs_size; - u8 __iomem *hw_addr; - u8 __iomem *csr_hw_addr; - - u32 ndev_count; - struct net_device *ndev[MQNIC_MAX_PORTS]; - - struct i2c_client *mod_i2c_client; -}; - -struct mqnic_priv { - struct device *dev; - struct net_device *ndev; - struct devlink_port *dl_port; - struct mqnic_dev *mdev; - struct mqnic_if *interface; - - spinlock_t stats_lock; - - int index; - bool registered; - bool port_up; - - u32 if_features; - - unsigned int link_status; - struct timer_list link_status_timer; - - u32 txq_count; - u32 rxq_count; - - u32 tx_ring_size; - u32 rx_ring_size; - - struct rw_semaphore txq_table_sem; - struct radix_tree_root txq_table; - - struct rw_semaphore rxq_table_sem; - struct radix_tree_root rxq_table; - - struct mqnic_sched_block *sched_block; - struct mqnic_port *port; - - u32 max_desc_block_size; - - u32 rx_queue_map_indir_table_size; - u32 *rx_queue_map_indir_table; - - struct hwtstamp_config hwts_config; - - struct i2c_client *mod_i2c_client; -}; - -// mqnic_main.c - -// mqnic_devlink.c -struct devlink *mqnic_devlink_alloc(struct device *dev); -void mqnic_devlink_free(struct devlink *devlink); - -// mqnic_res.c -struct mqnic_res *mqnic_create_res(unsigned int count, u8 __iomem *base, unsigned int stride); -void mqnic_destroy_res(struct mqnic_res *res); -int mqnic_res_alloc(struct mqnic_res *res); -void mqnic_res_free(struct mqnic_res *res, int index); -unsigned int mqnic_res_get_count(struct mqnic_res *res); -u8 __iomem *mqnic_res_get_addr(struct mqnic_res *res, int index); - -// mqnic_reg_block.c -struct mqnic_reg_block *mqnic_enumerate_reg_block_list(u8 __iomem *base, size_t offset, size_t size); -struct mqnic_reg_block *mqnic_find_reg_block(struct mqnic_reg_block *list, u32 type, u32 version, int index); -void mqnic_free_reg_block_list(struct mqnic_reg_block *list); - -// mqnic_irq.c -int mqnic_irq_init_pcie(struct mqnic_dev *mdev); -void mqnic_irq_deinit_pcie(struct mqnic_dev *mdev); -int mqnic_irq_init_platform(struct mqnic_dev *mdev); - -// mqnic_dev.c -extern const struct file_operations mqnic_fops; - -// mqnic_if.c -struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __iomem *hw_addr); -void mqnic_destroy_interface(struct mqnic_if *interface); -u32 mqnic_interface_get_tx_mtu(struct mqnic_if *interface); -void mqnic_interface_set_tx_mtu(struct mqnic_if *interface, u32 mtu); -u32 mqnic_interface_get_rx_mtu(struct mqnic_if *interface); -void mqnic_interface_set_rx_mtu(struct mqnic_if *interface, u32 mtu); -u32 mqnic_interface_get_rx_queue_map_rss_mask(struct mqnic_if *interface, int port); -void mqnic_interface_set_rx_queue_map_rss_mask(struct mqnic_if *interface, int port, u32 val); -u32 mqnic_interface_get_rx_queue_map_app_mask(struct mqnic_if *interface, int port); -void mqnic_interface_set_rx_queue_map_app_mask(struct mqnic_if *interface, int port, u32 val); -u32 mqnic_interface_get_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index); -void mqnic_interface_set_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index, u32 val); - -// mqnic_port.c -struct mqnic_port *mqnic_create_port(struct mqnic_if *interface, int index, - int phys_index, struct mqnic_reg_block *port_rb); -void mqnic_destroy_port(struct mqnic_port *port); -u32 mqnic_port_get_tx_ctrl(struct mqnic_port *port); -void mqnic_port_set_tx_ctrl(struct mqnic_port *port, u32 val); -u32 mqnic_port_get_rx_ctrl(struct mqnic_port *port); -void mqnic_port_set_rx_ctrl(struct mqnic_port *port, u32 val); -u32 mqnic_port_get_fc_ctrl(struct mqnic_port *port); -void mqnic_port_set_fc_ctrl(struct mqnic_port *port, u32 val); -u32 mqnic_port_get_lfc_ctrl(struct mqnic_port *port); -void mqnic_port_set_lfc_ctrl(struct mqnic_port *port, u32 val); -u32 mqnic_port_get_pfc_ctrl(struct mqnic_port *port, int index); -void mqnic_port_set_pfc_ctrl(struct mqnic_port *port, int index, u32 val); - -// mqnic_netdev.c -int mqnic_start_port(struct net_device *ndev); -void mqnic_stop_port(struct net_device *ndev); -int mqnic_update_indir_table(struct net_device *ndev); -void mqnic_update_stats(struct net_device *ndev); -struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, - struct mqnic_port *port, struct mqnic_sched_block *sched_block); -void mqnic_destroy_netdev(struct net_device *ndev); - -// mqnic_sched_block.c -struct mqnic_sched_block *mqnic_create_sched_block(struct mqnic_if *interface, - int index, struct mqnic_reg_block *rb); -void mqnic_destroy_sched_block(struct mqnic_sched_block *block); -int mqnic_activate_sched_block(struct mqnic_sched_block *block); -void mqnic_deactivate_sched_block(struct mqnic_sched_block *block); - -// mqnic_scheduler.c -struct mqnic_sched *mqnic_create_scheduler(struct mqnic_sched_block *block, - int index, struct mqnic_reg_block *rb); -void mqnic_destroy_scheduler(struct mqnic_sched *sched); -int mqnic_scheduler_enable(struct mqnic_sched *sched); -void mqnic_scheduler_disable(struct mqnic_sched *sched); - -// mqnic_ptp.c -void mqnic_register_phc(struct mqnic_dev *mdev); -void mqnic_unregister_phc(struct mqnic_dev *mdev); -ktime_t mqnic_read_cpl_ts(struct mqnic_dev *mdev, struct mqnic_ring *ring, - const struct mqnic_cpl *cpl); - -// mqnic_i2c.c -struct mqnic_i2c_bus *mqnic_i2c_bus_create(struct mqnic_dev *mqnic, int index); -struct i2c_adapter *mqnic_i2c_adapter_create(struct mqnic_dev *mqnic, int index); -void mqnic_i2c_bus_release(struct mqnic_i2c_bus *bus); -void mqnic_i2c_adapter_release(struct i2c_adapter *adapter); -int mqnic_i2c_init(struct mqnic_dev *mqnic); -void mqnic_i2c_deinit(struct mqnic_dev *mqnic); - -// mqnic_board.c -int mqnic_board_init(struct mqnic_dev *mqnic); -void mqnic_board_deinit(struct mqnic_dev *mqnic); - -// mqnic_clk_info.c -void mqnic_clk_info_init(struct mqnic_dev *mdev); -u32 mqnic_get_core_clk_nom_freq_hz(struct mqnic_dev *mdev); -u32 mqnic_get_ref_clk_nom_freq_hz(struct mqnic_dev *mdev); -u32 mqnic_get_core_clk_freq_hz(struct mqnic_dev *mdev); -u32 mqnic_get_clk_freq_hz(struct mqnic_dev *mdev, int ch); -u64 mqnic_core_clk_cycles_to_ns(struct mqnic_dev *mdev, u64 cycles); -u64 mqnic_core_clk_ns_to_cycles(struct mqnic_dev *mdev, u64 ns); -u64 mqnic_ref_clk_cycles_to_ns(struct mqnic_dev *mdev, u64 cycles); -u64 mqnic_ref_clk_ns_to_cycles(struct mqnic_dev *mdev, u64 ns); - -// mqnic_stats.c -void mqnic_stats_init(struct mqnic_dev *mdev); -u64 mqnic_stats_read(struct mqnic_dev *mdev, int index); - -// mqnic_eq.c -struct mqnic_eq *mqnic_create_eq(struct mqnic_if *interface); -void mqnic_destroy_eq(struct mqnic_eq *eq); -int mqnic_open_eq(struct mqnic_eq *eq, struct mqnic_irq *irq, int size); -void mqnic_close_eq(struct mqnic_eq *eq); -int mqnic_eq_attach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq); -void mqnic_eq_detach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq); -void mqnic_eq_read_prod_ptr(struct mqnic_eq *eq); -void mqnic_eq_write_cons_ptr(struct mqnic_eq *eq); -void mqnic_arm_eq(struct mqnic_eq *eq); -void mqnic_process_eq(struct mqnic_eq *eq); - -// mqnic_cq.c -struct mqnic_cq *mqnic_create_cq(struct mqnic_if *interface); -void mqnic_destroy_cq(struct mqnic_cq *cq); -int mqnic_open_cq(struct mqnic_cq *cq, struct mqnic_eq *eq, int size); -void mqnic_close_cq(struct mqnic_cq *cq); -void mqnic_cq_read_prod_ptr(struct mqnic_cq *cq); -void mqnic_cq_write_cons_ptr(struct mqnic_cq *cq); -void mqnic_arm_cq(struct mqnic_cq *cq); - -// mqnic_tx.c -struct mqnic_ring *mqnic_create_tx_ring(struct mqnic_if *interface); -void mqnic_destroy_tx_ring(struct mqnic_ring *ring); -int mqnic_open_tx_ring(struct mqnic_ring *ring, struct mqnic_priv *priv, - struct mqnic_cq *cq, int size, int desc_block_size); -void mqnic_close_tx_ring(struct mqnic_ring *ring); -int mqnic_enable_tx_ring(struct mqnic_ring *ring); -void mqnic_disable_tx_ring(struct mqnic_ring *ring); -bool mqnic_is_tx_ring_empty(const struct mqnic_ring *ring); -bool mqnic_is_tx_ring_full(const struct mqnic_ring *ring); -void mqnic_tx_read_cons_ptr(struct mqnic_ring *ring); -void mqnic_tx_write_prod_ptr(struct mqnic_ring *ring); -void mqnic_free_tx_desc(struct mqnic_ring *ring, int index, int napi_budget); -int mqnic_free_tx_buf(struct mqnic_ring *ring); -int mqnic_process_tx_cq(struct mqnic_cq *cq, int napi_budget); -void mqnic_tx_irq(struct mqnic_cq *cq); -int mqnic_poll_tx_cq(struct napi_struct *napi, int budget); -netdev_tx_t mqnic_start_xmit(struct sk_buff *skb, struct net_device *dev); - -// mqnic_rx.c -struct mqnic_ring *mqnic_create_rx_ring(struct mqnic_if *interface); -void mqnic_destroy_rx_ring(struct mqnic_ring *ring); -int mqnic_open_rx_ring(struct mqnic_ring *ring, struct mqnic_priv *priv, - struct mqnic_cq *cq, int size, int desc_block_size); -void mqnic_close_rx_ring(struct mqnic_ring *ring); -int mqnic_enable_rx_ring(struct mqnic_ring *ring); -void mqnic_disable_rx_ring(struct mqnic_ring *ring); -bool mqnic_is_rx_ring_empty(const struct mqnic_ring *ring); -bool mqnic_is_rx_ring_full(const struct mqnic_ring *ring); -void mqnic_rx_read_cons_ptr(struct mqnic_ring *ring); -void mqnic_rx_write_prod_ptr(struct mqnic_ring *ring); -void mqnic_free_rx_desc(struct mqnic_ring *ring, int index); -int mqnic_free_rx_buf(struct mqnic_ring *ring); -int mqnic_prepare_rx_desc(struct mqnic_ring *ring, int index); -int mqnic_refill_rx_buffers(struct mqnic_ring *ring); -int mqnic_process_rx_cq(struct mqnic_cq *cq, int napi_budget); -void mqnic_rx_irq(struct mqnic_cq *cq); -int mqnic_poll_rx_cq(struct napi_struct *napi, int budget); - -// mqnic_ethtool.c -extern const struct ethtool_ops mqnic_ethtool_ops; - -#endif /* MQNIC_H */ diff --git a/modules/mqnic_vf/mqnic_board.c b/modules/mqnic_vf/mqnic_board.c deleted file mode 120000 index 76cb8b6..0000000 --- a/modules/mqnic_vf/mqnic_board.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_board.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_clk_info.c b/modules/mqnic_vf/mqnic_clk_info.c deleted file mode 120000 index 341f487..0000000 --- a/modules/mqnic_vf/mqnic_clk_info.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_clk_info.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_cq.c b/modules/mqnic_vf/mqnic_cq.c deleted file mode 120000 index 609fdd3..0000000 --- a/modules/mqnic_vf/mqnic_cq.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_cq.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_dev.c b/modules/mqnic_vf/mqnic_dev.c deleted file mode 120000 index 6f74710..0000000 --- a/modules/mqnic_vf/mqnic_dev.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_dev.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_devlink.c b/modules/mqnic_vf/mqnic_devlink.c deleted file mode 120000 index 9697c14..0000000 --- a/modules/mqnic_vf/mqnic_devlink.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_devlink.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_eq.c b/modules/mqnic_vf/mqnic_eq.c deleted file mode 100644 index 59b0028..0000000 --- a/modules/mqnic_vf/mqnic_eq.c +++ /dev/null @@ -1,260 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause-Views -/* - * Copyright (c) 2019-2023 The Regents of the University of California - */ - -#include "mqnic.h" - -static int mqnic_eq_int(struct notifier_block *nb, unsigned long action, void *data) -{ - struct mqnic_eq *eq = container_of(nb, struct mqnic_eq, irq_nb); - - mqnic_process_eq(eq); - mqnic_arm_eq(eq); - - return NOTIFY_DONE; -} - -struct mqnic_eq *mqnic_create_eq(struct mqnic_if *interface) -{ - struct mqnic_eq *eq; - - eq = kzalloc(sizeof(*eq), GFP_KERNEL); - if (!eq) - return ERR_PTR(-ENOMEM); - - eq->dev = interface->dev; - eq->interface = interface; - - eq->eqn = -1; - eq->enabled = 0; - - eq->irq_nb.notifier_call = mqnic_eq_int; - - eq->hw_addr = NULL; - - eq->prod_ptr = 0; - eq->cons_ptr = 0; - - spin_lock_init(&eq->table_lock); - - INIT_RADIX_TREE(&eq->cq_table, GFP_KERNEL); - - return eq; -} - -void mqnic_destroy_eq(struct mqnic_eq *eq) -{ - mqnic_close_eq(eq); - - kfree(eq); -} - -int mqnic_open_eq(struct mqnic_eq *eq, struct mqnic_irq *irq, int size) -{ - int ret; - - if (eq->enabled || eq->hw_addr || eq->buf || !irq) - return -EINVAL; - - eq->eqn = mqnic_res_alloc(eq->interface->eq_res); - if (eq->eqn < 0) - return -ENOMEM; - - eq->size = roundup_pow_of_two(size); - eq->size_mask = eq->size - 1; - eq->stride = roundup_pow_of_two(MQNIC_EVENT_SIZE); - - eq->buf_size = eq->size * eq->stride; - eq->buf = dma_alloc_coherent(eq->dev, eq->buf_size, &eq->buf_dma_addr, GFP_KERNEL); - if (!eq->buf) { - ret = -ENOMEM; - goto fail; - } - - // register interrupt - ret = atomic_notifier_chain_register(&irq->nh, &eq->irq_nb); - if (ret) - goto fail; - - eq->irq = irq; - - eq->hw_addr = mqnic_res_get_addr(eq->interface->eq_res, eq->eqn); - - eq->prod_ptr = 0; - eq->cons_ptr = 0; - - memset(eq->buf, 1, eq->buf_size); - - // deactivate queue - iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); - // set base address - iowrite32((eq->buf_dma_addr & 0xfffff000), - eq->hw_addr + MQNIC_EQ_BASE_ADDR_VF_REG + 0); - iowrite32(eq->buf_dma_addr >> 32, - eq->hw_addr + MQNIC_EQ_BASE_ADDR_VF_REG + 4); - - // set function id - iowrite32(MQNIC_EQ_CMD_SET_VF_ID | 0, - eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); - - // set size - iowrite32(MQNIC_EQ_CMD_SET_SIZE | ilog2(eq->size), - eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); - // set IRQN - iowrite32(MQNIC_EQ_CMD_SET_IRQN | eq->irq->index, - eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); - // set pointers - iowrite32(MQNIC_EQ_CMD_SET_PROD_PTR | (eq->prod_ptr & MQNIC_EQ_PTR_MASK), - eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); - iowrite32(MQNIC_EQ_CMD_SET_CONS_PTR | (eq->cons_ptr & MQNIC_EQ_PTR_MASK), - eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); - // activate queue - iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 1, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); - - eq->enabled = 1; - - return 0; - -fail: - mqnic_close_eq(eq); - return ret; -} - -void mqnic_close_eq(struct mqnic_eq *eq) -{ - int ret; - - if (eq->hw_addr) { - // deactivate queue - iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); - } - - // unregister interrupt - if (eq->irq) - ret = atomic_notifier_chain_unregister(&eq->irq->nh, &eq->irq_nb); - - eq->irq = NULL; - - eq->hw_addr = NULL; - - if (eq->buf) { - dma_free_coherent(eq->dev, eq->buf_size, eq->buf, eq->buf_dma_addr); - eq->buf = NULL; - eq->buf_dma_addr = 0; - } - - mqnic_res_free(eq->interface->eq_res, eq->eqn); - eq->eqn = -1; - - eq->enabled = 0; -} - -int mqnic_eq_attach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq) -{ - int ret; - - spin_lock_irq(&eq->table_lock); - ret = radix_tree_insert(&eq->cq_table, cq->cqn, cq); - spin_unlock_irq(&eq->table_lock); - return ret; -} - -void mqnic_eq_detach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq) -{ - struct mqnic_cq *item; - - spin_lock_irq(&eq->table_lock); - item = radix_tree_delete(&eq->cq_table, cq->cqn); - spin_unlock_irq(&eq->table_lock); - - if (IS_ERR(item)) { - dev_err(eq->dev, "%s on IF %d EQ %d: radix_tree_delete failed: %ld", - __func__, eq->interface->index, eq->eqn, PTR_ERR(item)); - } else if (!item) { - dev_err(eq->dev, "%s on IF %d EQ %d: CQ %d not in table", - __func__, eq->interface->index, eq->eqn, cq->cqn); - } else if (item != cq) { - dev_err(eq->dev, "%s on IF %d EQ %d: entry mismatch when removing CQ %d", - __func__, eq->interface->index, eq->eqn, cq->cqn); - } -} - -void mqnic_eq_read_prod_ptr(struct mqnic_eq *eq) -{ - eq->prod_ptr += ((ioread32(eq->hw_addr + MQNIC_EQ_PTR_REG) & MQNIC_EQ_PTR_MASK) - eq->prod_ptr) & MQNIC_EQ_PTR_MASK; -} - -void mqnic_eq_write_cons_ptr(struct mqnic_eq *eq) -{ - iowrite32(MQNIC_EQ_CMD_SET_CONS_PTR | (eq->cons_ptr & MQNIC_EQ_PTR_MASK), - eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); -} - -void mqnic_arm_eq(struct mqnic_eq *eq) -{ - if (!eq->enabled) - return; - - iowrite32(MQNIC_EQ_CMD_SET_ARM | 1, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); -} - -void mqnic_process_eq(struct mqnic_eq *eq) -{ - struct mqnic_if *interface = eq->interface; - struct mqnic_event *event; - struct mqnic_cq *cq; - u32 eq_index; - u32 eq_cons_ptr; - int done = 0; - - eq_cons_ptr = eq->cons_ptr; - eq_index = eq_cons_ptr & eq->size_mask; - - u32 cpl_count = mqnic_res_get_count(interface->cq_res); - - while (1) { - event = (struct mqnic_event *)(eq->buf + eq_index * eq->stride); - - if (!!(event->phase & cpu_to_le32(0x80000000)) == !!(eq_cons_ptr & eq->size)) - break; - - dma_rmb(); - - - if (event->type == MQNIC_EVENT_TYPE_CPL) { - // completion event - rcu_read_lock(); - cq = radix_tree_lookup(&eq->cq_table, (le16_to_cpu(event->source) % cpl_count) ); - rcu_read_unlock(); - - if (likely(cq)) { - if (likely(cq->handler)){ - dev_info(eq->dev, "%s: event source: %d", __func__, le16_to_cpu(event->source)); - cq->handler(cq); - } - } else { - dev_err(eq->dev, "%s on IF %d EQ %d: unknown event source %d (index %d, type %d)", - __func__, interface->index, eq->eqn, le16_to_cpu(event->source), - eq_index, le16_to_cpu(event->type)); - print_hex_dump(KERN_ERR, "", DUMP_PREFIX_NONE, 16, 1, - event, MQNIC_EVENT_SIZE, true); - } - } else { - dev_err(eq->dev, "%s on IF %d EQ %d: unknown event type %d (index %d, source %d)", - __func__, interface->index, eq->eqn, le16_to_cpu(event->type), - eq_index, le16_to_cpu(event->source)); - print_hex_dump(KERN_ERR, "", DUMP_PREFIX_NONE, 16, 1, - event, MQNIC_EVENT_SIZE, true); - } - - done++; - - eq_cons_ptr++; - eq_index = eq_cons_ptr & eq->size_mask; - } - - // update EQ consumer pointer - eq->cons_ptr = eq_cons_ptr; - mqnic_eq_write_cons_ptr(eq); -} diff --git a/modules/mqnic_vf/mqnic_ethtool.c b/modules/mqnic_vf/mqnic_ethtool.c deleted file mode 100644 index 39afb91..0000000 --- a/modules/mqnic_vf/mqnic_ethtool.c +++ /dev/null @@ -1,655 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause-Views -/* - * Copyright (c) 2019-2023 The Regents of the University of California - */ - -#include "mqnic.h" - -#include -#include - -#define SFF_MODULE_ID_SFP 0x03 -#define SFF_MODULE_ID_QSFP 0x0c -#define SFF_MODULE_ID_QSFP_PLUS 0x0d -#define SFF_MODULE_ID_QSFP28 0x11 - -static void mqnic_get_drvinfo(struct net_device *ndev, - struct ethtool_drvinfo *drvinfo) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - struct mqnic_dev *mdev = priv->mdev; - - strscpy(drvinfo->driver, DRIVER_NAME, sizeof(drvinfo->driver)); - strscpy(drvinfo->version, DRIVER_VERSION, sizeof(drvinfo->version)); - - snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d.%d", - mdev->fw_ver >> 24, (mdev->fw_ver >> 16) & 0xff, - (mdev->fw_ver >> 8) & 0xff, mdev->fw_ver & 0xff); - strscpy(drvinfo->bus_info, dev_name(mdev->dev), sizeof(drvinfo->bus_info)); - - drvinfo->regdump_len = priv->mdev->hw_regs_size; -} - -static int mqnic_get_regs_len(struct net_device *ndev) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - - return priv->mdev->hw_regs_size; -} - -static void mqnic_get_regs(struct net_device *ndev, - struct ethtool_regs *regs, void *p) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - u32 *out = p; - int k; - - for (k = 0; k < priv->mdev->hw_regs_size/4; k ++) - out[k] = ioread32(priv->mdev->hw_addr + k*4); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) -static void mqnic_get_ringparam(struct net_device *ndev, - struct ethtool_ringparam *param, - struct kernel_ethtool_ringparam *kernel_param, - struct netlink_ext_ack *ext_ack) -#else -static void mqnic_get_ringparam(struct net_device *ndev, - struct ethtool_ringparam *param) -#endif -{ - struct mqnic_priv *priv = netdev_priv(ndev); - - param->rx_max_pending = MQNIC_MAX_RX_RING_SZ; - param->tx_max_pending = MQNIC_MAX_TX_RING_SZ; - - param->rx_pending = priv->rx_ring_size; - param->tx_pending = priv->tx_ring_size; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) - kernel_param->cqe_size = MQNIC_CPL_SIZE; -#endif -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0) -static int mqnic_set_ringparam(struct net_device *ndev, - struct ethtool_ringparam *param, - struct kernel_ethtool_ringparam *kernel_param, - struct netlink_ext_ack *ext_ack) -#else -static int mqnic_set_ringparam(struct net_device *ndev, - struct ethtool_ringparam *param) -#endif -{ - struct mqnic_priv *priv = netdev_priv(ndev); - u32 tx_ring_size, rx_ring_size; - int port_up = priv->port_up; - int ret = 0; - - if (param->rx_mini_pending || param->rx_jumbo_pending) - return -EINVAL; - - if (param->rx_pending < MQNIC_MIN_RX_RING_SZ) - return -EINVAL; - - if (param->rx_pending > MQNIC_MAX_RX_RING_SZ) - return -EINVAL; - - if (param->tx_pending < MQNIC_MIN_TX_RING_SZ) - return -EINVAL; - - if (param->tx_pending > MQNIC_MAX_TX_RING_SZ) - return -EINVAL; - - rx_ring_size = roundup_pow_of_two(param->rx_pending); - tx_ring_size = roundup_pow_of_two(param->tx_pending); - - if (rx_ring_size == priv->rx_ring_size && tx_ring_size == priv->tx_ring_size) - return 0; - - netdev_info(ndev, "New TX ring size: %d", tx_ring_size); - netdev_info(ndev, "New RX ring size: %d", rx_ring_size); - - mutex_lock(&priv->mdev->state_lock); - - if (port_up) - mqnic_stop_port(ndev); - - priv->tx_ring_size = tx_ring_size; - priv->rx_ring_size = rx_ring_size; - - if (port_up) { - ret = mqnic_start_port(ndev); - - if (ret) - netdev_err(ndev, "%s: Failed to start port: %d", __func__, ret); - } - - mutex_unlock(&priv->mdev->state_lock); - - return ret; -} - -static void mqnic_get_pauseparam(struct net_device *ndev, - struct ethtool_pauseparam *param) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - u32 val; - - param->autoneg = 0; - param->rx_pause = 0; - param->tx_pause = 0; - - if (!(priv->if_features & MQNIC_IF_FEATURE_LFC)) - return; - - val = mqnic_port_get_lfc_ctrl(priv->port); - - param->rx_pause = !!(val & MQNIC_PORT_LFC_CTRL_RX_LFC_EN); - param->tx_pause = !!(val & MQNIC_PORT_LFC_CTRL_TX_LFC_EN); -} - -static int mqnic_set_pauseparam(struct net_device *ndev, - struct ethtool_pauseparam *param) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - u32 val; - - if (!(priv->if_features & MQNIC_IF_FEATURE_LFC)) - return -EOPNOTSUPP; - - if (param->autoneg) - return -EINVAL; - - val = mqnic_port_get_lfc_ctrl(priv->port); - - if (param->rx_pause) - val |= MQNIC_PORT_LFC_CTRL_RX_LFC_EN; - else - val &= ~MQNIC_PORT_LFC_CTRL_RX_LFC_EN; - - if (param->tx_pause) - val |= MQNIC_PORT_LFC_CTRL_TX_LFC_EN; - else - val &= ~MQNIC_PORT_LFC_CTRL_TX_LFC_EN; - - mqnic_port_set_lfc_ctrl(priv->port, val); - - return 0; -} - -static int mqnic_get_rxnfc(struct net_device *ndev, - struct ethtool_rxnfc *rxnfc, u32 *rule_locs) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - - switch (rxnfc->cmd) { - case ETHTOOL_GRXRINGS: - rxnfc->data = priv->rxq_count; - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static u32 mqnic_get_rxfh_indir_size(struct net_device *ndev) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - - return priv->rx_queue_map_indir_table_size; -} - -static int mqnic_get_rxfh(struct net_device *ndev, u32 *indir, u8 *key, - u8 *hfunc) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - int k; - - if (hfunc) - *hfunc = ETH_RSS_HASH_TOP; - - if (indir) - for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) - indir[k] = priv->rx_queue_map_indir_table[k]; - - return 0; -} - -static int mqnic_set_rxfh(struct net_device *ndev, const u32 *indir, - const u8 *key, const u8 hfunc) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - int k; - - if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) - return -EOPNOTSUPP; - - if (!indir) - return 0; - - if (indir) { - for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) { - if (indir[k] >= priv->rxq_count) - return -EINVAL; - } - - for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) - priv->rx_queue_map_indir_table[k] = indir[k]; - } - - return mqnic_update_indir_table(ndev); -} - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,8,0) -static int mqnic_get_rxfh_new(struct net_device *ndev, struct ethtool_rxfh_param *param) -{ - u8 hfunc = 0; - int ret = mqnic_get_rxfh(ndev, param->indir, param->key, &hfunc); - if (ret) - return ret; - param->hfunc = hfunc; - return 0; -} - -static int mqnic_set_rxfh_new(struct net_device *ndev, struct ethtool_rxfh_param *param, struct netlink_ext_ack *extack) -{ - return mqnic_set_rxfh(ndev, param->indir, param->key, param->hfunc); -} -#endif - -static void mqnic_get_channels(struct net_device *ndev, - struct ethtool_channels *channel) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - - channel->max_rx = mqnic_res_get_count(priv->interface->rxq_res); - channel->max_tx = mqnic_res_get_count(priv->interface->txq_res); - - channel->rx_count = priv->rxq_count; - channel->tx_count = priv->txq_count; -} - -static int mqnic_set_channels(struct net_device *ndev, - struct ethtool_channels *channel) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - u32 txq_count, rxq_count; - int port_up = priv->port_up; - int ret = 0; - int k; - - if (channel->combined_count || channel->other_count) - return -EINVAL; - - if (priv->rxq_count > mqnic_res_get_count(priv->interface->rxq_res)) - return -EINVAL; - - if (priv->txq_count > mqnic_res_get_count(priv->interface->txq_res)) - return -EINVAL; - - rxq_count = channel->rx_count; - txq_count = channel->tx_count; - - if (rxq_count == priv->rxq_count && txq_count == priv->txq_count) - return 0; - - netdev_info(ndev, "New TX channel count: %d", txq_count); - netdev_info(ndev, "New RX channel count: %d", rxq_count); - - if (rxq_count != priv->rxq_count) - for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) - priv->rx_queue_map_indir_table[k] = k % rxq_count; - - mutex_lock(&priv->mdev->state_lock); - - if (port_up) - mqnic_stop_port(ndev); - - priv->txq_count = txq_count; - priv->rxq_count = rxq_count; - - if (port_up) { - ret = mqnic_start_port(ndev); - - if (ret) - netdev_err(ndev, "%s: Failed to start port: %d", __func__, ret); - } - - mutex_unlock(&priv->mdev->state_lock); - - return ret; -} -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0) -static int mqnic_get_ts_info(struct net_device *ndev, - struct kernel_ethtool_ts_info *info) - -#else -static int mqnic_get_ts_info(struct net_device *ndev, - struct ethtool_ts_info *info) -#endif -{ - struct mqnic_priv *priv = netdev_priv(ndev); - struct mqnic_dev *mdev = priv->mdev; - - ethtool_op_get_ts_info(ndev, info); - - if (mdev->ptp_clock) - info->phc_index = ptp_clock_index(mdev->ptp_clock); - - if (!(priv->if_features & MQNIC_IF_FEATURE_PTP_TS) || !mdev->ptp_clock) - return 0; - - info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE | - SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; - - info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); - - info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL); - - return 0; -} - -static int mqnic_read_module_eeprom(struct net_device *ndev, - u16 offset, u16 len, u8 *data) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - - if (!priv->mod_i2c_client) - return -EINVAL; - - if (len > I2C_SMBUS_BLOCK_MAX) - len = I2C_SMBUS_BLOCK_MAX; - - return i2c_smbus_read_i2c_block_data(priv->mod_i2c_client, offset, len, data); -} - -static int mqnic_write_module_eeprom(struct net_device *ndev, - u16 offset, u16 len, u8 *data) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - - if (!priv->mod_i2c_client) - return -EINVAL; - - if (len > I2C_SMBUS_BLOCK_MAX) - len = I2C_SMBUS_BLOCK_MAX; - - return i2c_smbus_write_i2c_block_data(priv->mod_i2c_client, offset, len, data); -} - -static int mqnic_query_module_id(struct net_device *ndev) -{ - int ret; - u8 data; - - ret = mqnic_read_module_eeprom(ndev, 0, 1, &data); - - if (ret < 0) - return ret; - - return data; -} - -static int mqnic_query_module_eeprom_by_page(struct net_device *ndev, - unsigned short i2c_addr, u16 page, u16 bank, u16 offset, u16 len, u8 *data) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - int module_id; - u8 d; - int ret; - unsigned short orig_i2c_addr; - - module_id = mqnic_query_module_id(ndev); - - if (module_id < 0) { - netdev_err(ndev, "%s: Failed to read module ID (%d)", __func__, module_id); - return module_id; - } - - switch (module_id) { - case SFF_MODULE_ID_SFP: - if (page > 0 || bank > 0) - return -EINVAL; - if (i2c_addr != 0x50 && i2c_addr != 0x51) - return -EINVAL; - break; - case SFF_MODULE_ID_QSFP: - case SFF_MODULE_ID_QSFP_PLUS: - case SFF_MODULE_ID_QSFP28: - if (page > 3 || bank > 0) - return -EINVAL; - if (i2c_addr != 0x50) - return -EINVAL; - break; - default: - netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, module_id); - return -EINVAL; - } - - // set page - switch (module_id) { - case SFF_MODULE_ID_SFP: - break; - case SFF_MODULE_ID_QSFP: - case SFF_MODULE_ID_QSFP_PLUS: - case SFF_MODULE_ID_QSFP28: - if (offset+len >= 128) { - // select page - d = page; - mqnic_write_module_eeprom(ndev, 127, 1, &d); - msleep(1); - } - break; - default: - netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, module_id); - return -EINVAL; - } - - // set i2c address of the mod_i2c_client - // This code section should not be called concurrently since the IOCTL - // handler for ethtool operations is called under the RTNL lock. - // In addition the i2c_client is used only within code inside this lock. - if (!priv->mod_i2c_client) - return -EINVAL; - - orig_i2c_addr = priv->mod_i2c_client->addr; - priv->mod_i2c_client->addr = i2c_addr; - - // read data - ret = mqnic_read_module_eeprom(ndev, offset, len, data); - - // reset i2c addr - priv->mod_i2c_client->addr = orig_i2c_addr; - - return ret; -} - -static int mqnic_query_module_eeprom(struct net_device *ndev, - u16 offset, u16 len, u8 *data) -{ - int module_id; - unsigned short i2c_addr = 0x50; - u16 page = 0; - u16 bank = 0; - - module_id = mqnic_query_module_id(ndev); - - if (module_id < 0) { - netdev_err(ndev, "%s: Failed to read module ID (%d)", __func__, module_id); - return module_id; - } - - switch (module_id) { - case SFF_MODULE_ID_SFP: - i2c_addr = 0x50; - page = 0; - if (offset >= 256) { - offset -= 256; - i2c_addr = 0x51; - } - break; - case SFF_MODULE_ID_QSFP: - case SFF_MODULE_ID_QSFP_PLUS: - case SFF_MODULE_ID_QSFP28: - i2c_addr = 0x50; - if (offset < 256) { - page = 0; - } else { - page = 1 + ((offset - 256) / 128); - offset -= page * 128; - } - break; - default: - netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, module_id); - return -EINVAL; - } - - // clip request to end of page - if (offset + len > 256) - len = 256 - offset; - - return mqnic_query_module_eeprom_by_page(ndev, i2c_addr, - page, bank, offset, len, data); -} - -static int mqnic_get_module_info(struct net_device *ndev, - struct ethtool_modinfo *modinfo) -{ - int read_len = 0; - u8 data[16]; - - // read module ID and revision - read_len = mqnic_read_module_eeprom(ndev, 0, 2, data); - - if (read_len < 0) - return read_len; - - if (read_len < 2) - return -EIO; - - // check identifier byte at address 0 - switch (data[0]) { - case SFF_MODULE_ID_SFP: - modinfo->type = ETH_MODULE_SFF_8472; - modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; - break; - case SFF_MODULE_ID_QSFP: - modinfo->type = ETH_MODULE_SFF_8436; - modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; - break; - case SFF_MODULE_ID_QSFP_PLUS: - // check revision at address 1 - if (data[1] >= 0x03) { - modinfo->type = ETH_MODULE_SFF_8636; - modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; - } else { - modinfo->type = ETH_MODULE_SFF_8436; - modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; - } - break; - case SFF_MODULE_ID_QSFP28: - modinfo->type = ETH_MODULE_SFF_8636; - modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; - break; - default: - netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, data[0]); - return -EINVAL; - } - - return 0; -} - -static int mqnic_get_module_eeprom(struct net_device *ndev, - struct ethtool_eeprom *eeprom, u8 *data) -{ - int i = 0; - int read_len; - - if (eeprom->len == 0) - return -EINVAL; - - memset(data, 0, eeprom->len); - - while (i < eeprom->len) { - read_len = mqnic_query_module_eeprom(ndev, eeprom->offset + i, - eeprom->len - i, data + i); - - if (read_len == 0) - return 0; - - if (read_len < 0) { - netdev_err(ndev, "%s: Failed to read module EEPROM (%d)", __func__, read_len); - return read_len; - } - - i += read_len; - } - - return 0; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) -static int mqnic_get_module_eeprom_by_page(struct net_device *ndev, - const struct ethtool_module_eeprom *eeprom, - struct netlink_ext_ack *extack) -{ - int i = 0; - int read_len; - - if (eeprom->length == 0) - return -EINVAL; - - memset(eeprom->data, 0, eeprom->length); - - while (i < eeprom->length) { - read_len = mqnic_query_module_eeprom_by_page(ndev, eeprom->i2c_address, - eeprom->page, eeprom->bank, eeprom->offset + i, - eeprom->length - i, eeprom->data + i); - - if (read_len == 0) - return 0; - - if (read_len < 0) { - netdev_err(ndev, "%s: Failed to read module EEPROM (%d)", __func__, read_len); - return read_len; - } - - i += read_len; - } - - return i; -} -#endif - -const struct ethtool_ops mqnic_ethtool_ops = { - .get_drvinfo = mqnic_get_drvinfo, - .get_regs_len = mqnic_get_regs_len, - .get_regs = mqnic_get_regs, - .get_link = ethtool_op_get_link, //link status updated on timer basis - .get_ringparam = mqnic_get_ringparam, - .set_ringparam = mqnic_set_ringparam, - .get_pauseparam = mqnic_get_pauseparam, - .set_pauseparam = mqnic_set_pauseparam, - .get_rxnfc = mqnic_get_rxnfc, - - .get_rxfh_indir_size = mqnic_get_rxfh_indir_size, - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0) - .get_rxfh = mqnic_get_rxfh_new, - .set_rxfh = mqnic_set_rxfh_new, -#else - .get_rxfh = mqnic_get_rxfh, - .set_rxfh = mqnic_set_rxfh, -#endif - .get_channels = mqnic_get_channels, - .set_channels = mqnic_set_channels, - .get_ts_info = mqnic_get_ts_info, - .get_module_info = mqnic_get_module_info, - .get_module_eeprom = mqnic_get_module_eeprom, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) - .get_module_eeprom_by_page = mqnic_get_module_eeprom_by_page, -#endif -}; diff --git a/modules/mqnic_vf/mqnic_hw.h b/modules/mqnic_vf/mqnic_hw.h deleted file mode 120000 index 37b9f80..0000000 --- a/modules/mqnic_vf/mqnic_hw.h +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_hw.h \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_i2c.c b/modules/mqnic_vf/mqnic_i2c.c deleted file mode 120000 index 3d255b2..0000000 --- a/modules/mqnic_vf/mqnic_i2c.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_i2c.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_if.c b/modules/mqnic_vf/mqnic_if.c deleted file mode 100644 index c5a8d41..0000000 --- a/modules/mqnic_vf/mqnic_if.c +++ /dev/null @@ -1,400 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause-Views -/* - * Copyright (c) 2021-2023 The Regents of the University of California - */ - -#include "mqnic.h" - -struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __iomem *hw_addr) -{ - struct device *dev = mdev->dev; - struct mqnic_if *interface; - struct mqnic_reg_block *rb; - int ret = 0; - int k; - u32 count, offset, stride; - u32 desc_block_size; - u32 val; - - interface = kzalloc(sizeof(*interface), GFP_KERNEL); - if (!interface) - return ERR_PTR(-ENOMEM); - - interface->mdev = mdev; - interface->dev = dev; - - interface->index = index; - - interface->hw_regs_size = mdev->if_stride; - interface->hw_addr = hw_addr; - interface->csr_hw_addr = hw_addr + mdev->if_csr_offset; - - // Enumerate registers - interface->rb_list = mqnic_enumerate_reg_block_list(interface->hw_addr, mdev->if_csr_offset, interface->hw_regs_size); - if (!interface->rb_list) { - ret = -EIO; - dev_err(dev, "Failed to enumerate blocks"); - goto fail; - } - - dev_info(dev, "Interface-level register blocks:"); - for (rb = interface->rb_list; rb->regs; rb++) - dev_info(dev, " type 0x%08x (v %d.%d.%d.%d)", rb->type, rb->version >> 24, - (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); - - interface->if_ctrl_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_IF_CTRL_TYPE, MQNIC_RB_IF_CTRL_VER, 0); - - if (!interface->if_ctrl_rb) { - ret = -EIO; - dev_err(dev, "Interface control block not found"); - goto fail; - } - - interface->if_features = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_FEATURES); - interface->port_count = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_PORT_COUNT); - interface->sched_block_count = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_SCHED_COUNT); - interface->max_tx_mtu = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_MAX_TX_MTU); - interface->max_rx_mtu = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_MAX_RX_MTU); - interface->tx_fifo_depth = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_TX_FIFO_DEPTH); - interface->rx_fifo_depth = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_RX_FIFO_DEPTH); - - interface->mac = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_MAC); - - dev_info(dev, "IF features: 0x%08x", interface->if_features); - dev_info(dev, "Port count: %d", interface->port_count); - dev_info(dev, "Scheduler block count: %d", interface->sched_block_count); - dev_info(dev, "Max TX MTU: %d", interface->max_tx_mtu); - dev_info(dev, "Max RX MTU: %d", interface->max_rx_mtu); - - interface->eq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_EQM_TYPE, MQNIC_RB_EQM_VER, 0); - - if (!interface->eq_rb) { - ret = -EIO; - dev_err(dev, "EQ block not found"); - goto fail; - } - - offset = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_OFFSET); - count = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_COUNT)/256; - stride = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_STRIDE); - - dev_info(dev, "EQ offset: 0x%08x", offset); - dev_info(dev, "EQ count: %d", count); - dev_info(dev, "EQ stride: 0x%08x", stride); - - count = min_t(u32, count, MQNIC_MAX_EQ); - - interface->eq_res = mqnic_create_res(count, hw_addr + offset, stride); - - if (IS_ERR_OR_NULL(interface->eq_res)) { - ret = PTR_ERR(interface->eq_res); - goto fail; - } - - interface->cq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_CQM_TYPE, MQNIC_RB_CQM_VER, 0); - - if (!interface->cq_rb) { - ret = -EIO; - dev_err(dev, "CQ block not found"); - goto fail; - } - - offset = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_OFFSET); - count = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_COUNT)/256; - stride = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_STRIDE); - count = min_t(u32, count, MQNIC_MAX_CQ); - - dev_info(dev, "CQ offset: 0x%08x", offset); - dev_info(dev, "CQ count: %d", count); - dev_info(dev, "CQ stride: 0x%08x", stride); - - - interface->cq_res = mqnic_create_res(count, hw_addr + offset, stride); - - if (IS_ERR_OR_NULL(interface->cq_res)) { - ret = PTR_ERR(interface->cq_res); - goto fail; - } - - interface->txq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_TX_QM_TYPE, MQNIC_RB_TX_QM_VER, 0); - - if (!interface->txq_rb) { - ret = -EIO; - dev_err(dev, "TXQ block not found"); - goto fail; - } - - offset = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_OFFSET); - count = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_COUNT)/256; - stride = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_STRIDE); - - count = min_t(u32, count, MQNIC_MAX_TXQ); - - dev_info(dev, "TXQ offset: 0x%08x", offset); - dev_info(dev, "TXQ count: %d", count); - dev_info(dev, "TXQ stride: 0x%08x", stride); - - - interface->txq_res = mqnic_create_res(count, hw_addr + offset, stride); - - if (IS_ERR_OR_NULL(interface->txq_res)) { - ret = PTR_ERR(interface->txq_res); - goto fail; - } - - interface->rxq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_RX_QM_TYPE, MQNIC_RB_RX_QM_VER, 0); - - if (!interface->rxq_rb) { - ret = -EIO; - dev_err(dev, "RXQ block not found"); - goto fail; - } - - offset = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_OFFSET); - count = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_COUNT)/256; - stride = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_STRIDE); - - count = min_t(u32, count, MQNIC_MAX_RXQ); - dev_info(dev, "RXQ offset: 0x%08x", offset); - dev_info(dev, "RXQ count: %d", count); - dev_info(dev, "RXQ stride: 0x%08x", stride); - - - interface->rxq_res = mqnic_create_res(count, hw_addr + offset, stride); - - if (IS_ERR_OR_NULL(interface->rxq_res)) { - ret = PTR_ERR(interface->rxq_res); - goto fail; - } - - interface->rx_queue_map_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_RX_QUEUE_MAP_TYPE, MQNIC_RB_RX_QUEUE_MAP_VER, 0); - - if (!interface->rx_queue_map_rb) { - ret = -EIO; - dev_err(dev, "RX queue map block not found"); - goto fail; - } - - val = ioread32(interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_REG_CFG); - interface->rx_queue_map_indir_table_size = 1 << ((val >> 8) & 0xff); - - dev_info(dev, "RX queue map indirection table size: %d", interface->rx_queue_map_indir_table_size); - - for (k = 0; k < interface->port_count; k++) { - interface->rx_queue_map_indir_table[k] = interface->hw_addr + ioread32(interface->rx_queue_map_rb->regs + - MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*k + MQNIC_RB_RX_QUEUE_MAP_CH_REG_OFFSET); - - mqnic_interface_set_rx_queue_map_rss_mask(interface, k, 0); - mqnic_interface_set_rx_queue_map_app_mask(interface, k, 0); - mqnic_interface_set_rx_queue_map_indir_table(interface, k, 0, 0); - } - - // determine desc block size - iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | 0xff00, mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_CTRL_STATUS_REG); - interface->max_desc_block_size = 1 << ((ioread32(mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_SIZE_CQN_REG) >> 28) & 0xf); - iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | 0x0000, mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_CTRL_STATUS_REG); - - dev_info(dev, "Max desc block size: %d", interface->max_desc_block_size); - - interface->max_desc_block_size = min_t(u32, interface->max_desc_block_size, MQNIC_MAX_FRAGS); - - desc_block_size = min_t(u32, interface->max_desc_block_size, 4); - - // disable queues - for (k = 0; k < mqnic_res_get_count(interface->eq_res); k++) - iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->eq_res, k) + MQNIC_EQ_CTRL_STATUS_REG); - - for (k = 0; k < mqnic_res_get_count(interface->cq_res); k++) - iowrite32(MQNIC_CQ_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->cq_res, k) + MQNIC_CQ_CTRL_STATUS_REG); - - for (k = 0; k < mqnic_res_get_count(interface->txq_res); k++) - iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->txq_res, k) + MQNIC_QUEUE_CTRL_STATUS_REG); - - for (k = 0; k < mqnic_res_get_count(interface->rxq_res); k++) - iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->rxq_res, k) + MQNIC_QUEUE_CTRL_STATUS_REG); - - // create ports - for (k = 0; k < interface->port_count; k++) { - struct mqnic_port *port; - struct mqnic_reg_block *port_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_PORT_TYPE, MQNIC_RB_PORT_VER, k); - - if (!port_rb) { - ret = -EIO; - dev_err(dev, "Port index %d not found", k); - goto fail; - } - - port = mqnic_create_port(interface, k, mdev->phys_port_max++, port_rb); - if (IS_ERR_OR_NULL(port)) { - ret = PTR_ERR(port); - goto fail; - } - interface->port[k] = port; - } - - // create schedulers - for (k = 0; k < interface->sched_block_count; k++) { - struct mqnic_sched_block *sched_block; - struct mqnic_reg_block *sched_block_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_SCHED_BLOCK_TYPE, MQNIC_RB_SCHED_BLOCK_VER, k); - - if (!sched_block_rb) { - ret = -EIO; - dev_err(dev, "Scheduler block index %d not found", k); - goto fail; - } - - sched_block = mqnic_create_sched_block(interface, k, sched_block_rb); - if (IS_ERR_OR_NULL(sched_block)) { - ret = PTR_ERR(sched_block); - goto fail; - } - interface->sched_block[k] = sched_block; - } - - // create EQs - interface->eq_count = mqnic_res_get_count(interface->eq_res); - for (k = 0; k < interface->eq_count; k++) { - struct mqnic_eq *eq = mqnic_create_eq(interface); - if (IS_ERR_OR_NULL(eq)) { - ret = PTR_ERR(eq); - goto fail; - } - - interface->eq[k] = eq; - - ret = mqnic_open_eq(eq, mdev->irq[k % mdev->irq_count], mqnic_num_eq_entries); - if (ret) - goto fail; - - mqnic_arm_eq(eq); - } - - // create net_devices - interface->ndev_count = 1; - for (k = 0; k < interface->ndev_count; k++) { - struct net_device *ndev = mqnic_create_netdev(interface, k, - interface->port[k], interface->sched_block[k]); - if (IS_ERR_OR_NULL(ndev)) { - ret = PTR_ERR(ndev); - goto fail; - } - interface->ndev[k] = ndev; - } - - return interface; - -fail: - mqnic_destroy_interface(interface); - return ERR_PTR(ret); -} - -void mqnic_destroy_interface(struct mqnic_if *interface) -{ - int k; - - // destroy associated net_devices - for (k = 0; k < ARRAY_SIZE(interface->ndev); k++) { - if (interface->ndev[k]) { - mqnic_destroy_netdev(interface->ndev[k]); - interface->ndev[k] = NULL; - } - } - - // free EQs - for (k = 0; k < ARRAY_SIZE(interface->eq); k++) { - if (interface->eq[k]) { - mqnic_destroy_eq(interface->eq[k]); - interface->eq[k] = NULL; - } - } - - // free schedulers - for (k = 0; k < ARRAY_SIZE(interface->sched_block); k++) { - if (interface->sched_block[k]) { - mqnic_destroy_sched_block(interface->sched_block[k]); - interface->sched_block[k] = NULL; - } - } - - // free ports - for (k = 0; k < ARRAY_SIZE(interface->port); k++) { - if (interface->port[k]) { - mqnic_destroy_port(interface->port[k]); - interface->port[k] = NULL; - } - } - - mqnic_destroy_res(interface->eq_res); - mqnic_destroy_res(interface->cq_res); - mqnic_destroy_res(interface->txq_res); - mqnic_destroy_res(interface->rxq_res); - - if (interface->rb_list) - mqnic_free_reg_block_list(interface->rb_list); - - kfree(interface); -} - -u32 mqnic_interface_get_tx_mtu(struct mqnic_if *interface) -{ - return ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_TX_MTU); -} -EXPORT_SYMBOL(mqnic_interface_get_tx_mtu); - -void mqnic_interface_set_tx_mtu(struct mqnic_if *interface, u32 mtu) -{ - iowrite32(mtu, interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_TX_MTU); -} -EXPORT_SYMBOL(mqnic_interface_set_tx_mtu); - -u32 mqnic_interface_get_rx_mtu(struct mqnic_if *interface) -{ - return ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_RX_MTU); -} -EXPORT_SYMBOL(mqnic_interface_get_rx_mtu); - -void mqnic_interface_set_rx_mtu(struct mqnic_if *interface, u32 mtu) -{ - iowrite32(mtu, interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_RX_MTU); -} -EXPORT_SYMBOL(mqnic_interface_set_rx_mtu); - -u32 mqnic_interface_get_rx_queue_map_rss_mask(struct mqnic_if *interface, int port) -{ - return ioread32(interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + - MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_RSS_MASK); -} -EXPORT_SYMBOL(mqnic_interface_get_rx_queue_map_rss_mask); - -void mqnic_interface_set_rx_queue_map_rss_mask(struct mqnic_if *interface, int port, u32 val) -{ - iowrite32(val, interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + - MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_RSS_MASK); -} -EXPORT_SYMBOL(mqnic_interface_set_rx_queue_map_rss_mask); - -u32 mqnic_interface_get_rx_queue_map_app_mask(struct mqnic_if *interface, int port) -{ - return ioread32(interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + - MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_APP_MASK); -} -EXPORT_SYMBOL(mqnic_interface_get_rx_queue_map_app_mask); - -void mqnic_interface_set_rx_queue_map_app_mask(struct mqnic_if *interface, int port, u32 val) -{ - iowrite32(val, interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + - MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE*port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_APP_MASK); -} -EXPORT_SYMBOL(mqnic_interface_set_rx_queue_map_app_mask); - -u32 mqnic_interface_get_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index) -{ - return ioread32(interface->rx_queue_map_indir_table[port] + index*4); -} -EXPORT_SYMBOL(mqnic_interface_get_rx_queue_map_indir_table); - -void mqnic_interface_set_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index, u32 val) -{ - iowrite32(val, interface->rx_queue_map_indir_table[port] + index*4); -} -EXPORT_SYMBOL(mqnic_interface_set_rx_queue_map_indir_table); diff --git a/modules/mqnic_vf/mqnic_ioctl.h b/modules/mqnic_vf/mqnic_ioctl.h deleted file mode 120000 index 589ac06..0000000 --- a/modules/mqnic_vf/mqnic_ioctl.h +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_ioctl.h \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_irq.c b/modules/mqnic_vf/mqnic_irq.c deleted file mode 120000 index 85d72f3..0000000 --- a/modules/mqnic_vf/mqnic_irq.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_irq.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_main.c b/modules/mqnic_vf/mqnic_main.c deleted file mode 100644 index 80c4b84..0000000 --- a/modules/mqnic_vf/mqnic_main.c +++ /dev/null @@ -1,918 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause-Views -/* - * Copyright (c) 2019-2023 The Regents of the University of California - */ - -#include "mqnic.h" -#include -#include -#include -#include -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) -#include -#endif - -MODULE_DESCRIPTION("mqnic driver"); -MODULE_AUTHOR("Alex Forencich"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION(DRIVER_VERSION); - -unsigned int mqnic_num_eq_entries = 1024; -unsigned int mqnic_num_txq_entries = 1024; -unsigned int mqnic_num_rxq_entries = 1024; - -module_param_named(num_eq_entries, mqnic_num_eq_entries, uint, 0444); -MODULE_PARM_DESC(num_eq_entries, "number of entries to allocate per event queue (default: 1024)"); -module_param_named(num_txq_entries, mqnic_num_txq_entries, uint, 0444); -MODULE_PARM_DESC(num_txq_entries, "number of entries to allocate per transmit queue (default: 1024)"); -module_param_named(num_rxq_entries, mqnic_num_rxq_entries, uint, 0444); -MODULE_PARM_DESC(num_rxq_entries, "number of entries to allocate per receive queue (default: 1024)"); - -unsigned int mqnic_link_status_poll = MQNIC_LINK_STATUS_POLL_MS; - -module_param_named(link_status_poll, mqnic_link_status_poll, uint, 0444); -MODULE_PARM_DESC(link_status_poll, - "link status polling interval, in ms (default: 1000; 0 to turn off)"); - - -#ifdef CONFIG_PCI -static const struct pci_device_id mqnic_pci_id_table[] = { - {PCI_DEVICE(0x1234, 0x0000)}, - {0 /* end */ } -}; - -MODULE_DEVICE_TABLE(pci, mqnic_pci_id_table); -#endif - -#ifdef CONFIG_OF -static struct of_device_id mqnic_of_id_table[] = { - { .compatible = "corundum,mqnic" }, - { }, -}; -MODULE_DEVICE_TABLE(of, mqnic_of_id_table); -#endif - -static LIST_HEAD(mqnic_devices); -static DEFINE_SPINLOCK(mqnic_devices_lock); - -static unsigned int mqnic_get_free_id(void) -{ - struct mqnic_dev *mqnic; - unsigned int id = 0; - bool available = false; - - while (!available) { - available = true; - list_for_each_entry(mqnic, &mqnic_devices, dev_list_node) { - if (mqnic->id == id) { - available = false; - id++; - break; - } - } - } - - return id; -} - -static void mqnic_assign_id(struct mqnic_dev *mqnic) -{ - spin_lock(&mqnic_devices_lock); - mqnic->id = mqnic_get_free_id(); - list_add_tail(&mqnic->dev_list_node, &mqnic_devices); - spin_unlock(&mqnic_devices_lock); - - snprintf(mqnic->name, sizeof(mqnic->name), DRIVER_NAME "%d", mqnic->id); -} - -static void mqnic_free_id(struct mqnic_dev *mqnic) -{ - spin_lock(&mqnic_devices_lock); - list_del(&mqnic->dev_list_node); - spin_unlock(&mqnic_devices_lock); -} - -static int mqnic_common_setdma(struct mqnic_dev *mqnic) -{ - int ret; - struct device *dev = mqnic->dev; - - // Set mask - ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); - if (ret) { - dev_warn(dev, "Warning: failed to set 64 bit PCI DMA mask"); - ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); - if (ret) { - dev_err(dev, "Failed to set PCI DMA mask"); - return ret; - } - } - - // Set max segment size - dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); - - return ret; -} - -#ifdef CONFIG_OF -static int mqnic_platform_get_mac_address(struct mqnic_dev *mqnic) -{ - int ret; - struct device *dev = mqnic->dev; - char mac_base[ETH_ALEN]; - struct device_node *np; - u32 inc_idx; - u32 inc; - int k; - - /* NOTE: Not being able to get a (base) MAC address shall not be an - * error to fail on intentionally. Thus we are warning, only. - */ - ret = eth_platform_get_mac_address(dev, mac_base); - if (ret) { - dev_warn(dev, "Unable to get MAC address\n"); - return 0; - } - - np = mqnic->dev->of_node; - if (!np) - return 0; - - if (of_property_read_u32(np, MQNIC_PROP_MAC_ADDR_INC_BYTE, &inc_idx)) - inc_idx = 5; - if ((inc_idx < 3) || (inc_idx > 5)) { - dev_err(dev, "Invalid property \"" MQNIC_PROP_MAC_ADDR_INC_BYTE "\"\n"); - return -EINVAL; - } - - ret = of_property_read_u32(np, MQNIC_PROP_MAC_ADDR_INC, &inc); - if (ret == -EINVAL) { - inc = 0; - } else if (ret) { - dev_err(dev, "Invalid property \"" MQNIC_PROP_MAC_ADDR_INC "\"\n"); - return ret; - } - - if (of_property_read_bool(np, MQNIC_PROP_MAC_ADDR_LOCAL)) - mac_base[0] |= BIT(1); - - mqnic->mac_count = mqnic->if_count; - for (k = 0; k < mqnic->mac_count; k++) { - memcpy(mqnic->mac_list[k], mac_base, ETH_ALEN); - mqnic->mac_list[k][inc_idx] += inc + k; - } - - return 0; -} - -static void mqnic_platform_module_eeprom_put(struct mqnic_dev *mqnic) -{ - int k; - - for (k = 0; k < mqnic->if_count; k++) - if (mqnic->mod_i2c_client) - put_device(&mqnic->mod_i2c_client[k]->dev); -} - -static int mqnic_platform_module_eeprom_get(struct mqnic_dev *mqnic) -{ - int ret; - struct device *dev = mqnic->dev; - int k; - - ret = 0; - - if (!dev->of_node) - return 0; - - for (k = 0; k < mqnic->if_count; k++) { - struct device_node *np; - struct i2c_client *cl; - - /* NOTE: Not being able to get a phandle for module EEPROM shall - * not be an error to fail on intentionally. Thus we are - * warning, only. - */ - np = of_parse_phandle(dev->of_node, MQNIC_PROP_MODULE_EEPROM, k); - if (!np) { - dev_warn(dev, "Missing phandle to module EEPROM for interface %d\n", k); - continue; - } - - cl = of_find_i2c_device_by_node(np); - if (!cl) { - ret = -ENOENT; - dev_err(dev, "Failed to find I2C device for module of interface %d\n", k); - of_node_put(np); - break; - } else { - mqnic->mod_i2c_client[k] = cl; - mqnic->mod_i2c_client_count++; - } - of_node_put(np); - } - - if (ret) - mqnic_platform_module_eeprom_put(mqnic); - - return ret; -} -#endif - -static void mqnic_common_remove(struct mqnic_dev *mqnic); - -#ifdef CONFIG_AUXILIARY_BUS -static void mqnic_adev_release(struct device *dev) -{ - struct mqnic_adev *mqnic_adev = container_of(dev, struct mqnic_adev, adev.dev); - - if (mqnic_adev->ptr) - *mqnic_adev->ptr = NULL; - kfree(mqnic_adev); -} -#endif - -static int mqnic_common_probe(struct mqnic_dev *mqnic) -{ - int ret = 0; - struct devlink *devlink = priv_to_devlink(mqnic); - struct device *dev = mqnic->dev; - struct mqnic_reg_block *rb; - struct rtc_time tm; - - int k = 0, l = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) - devlink_register(devlink); -#else - devlink_register(devlink, dev); -#endif - - // Enumerate registers - mqnic->rb_list = mqnic_enumerate_reg_block_list(mqnic->hw_addr, 0, mqnic->hw_regs_size); - if (!mqnic->rb_list) { - dev_err(dev, "Failed to enumerate blocks"); - return -EIO; - } - - dev_info(dev, "Device-level register blocks:"); - for (rb = mqnic->rb_list; rb->regs; rb++) - dev_info(dev, " type 0x%08x (v %d.%d.%d.%d)", rb->type, rb->version >> 24, - (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); - - // Read ID registers - mqnic->fw_id_rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_FW_ID_TYPE, MQNIC_RB_FW_ID_VER, 0); - - if (!mqnic->fw_id_rb) { - ret = -EIO; - dev_err(dev, "Error: FW ID block not found"); - goto fail_rb_init; - } - - mqnic->fpga_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FPGA_ID); - mqnic->fw_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FW_ID); - mqnic->fw_ver = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FW_VER); - mqnic->board_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BOARD_ID); - mqnic->board_ver = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BOARD_VER); - mqnic->build_date = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BUILD_DATE); - mqnic->git_hash = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_GIT_HASH); - mqnic->rel_info = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_REL_INFO); - mqnic->num_funcs = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_NUM_FUNCS); - - if (mqnic->num_funcs == 256) { - mqnic->num_funcs = 252; - } - - dev_info(dev, "NUMBER OF FUNCS: 0x%08x", mqnic->num_funcs); - - rtc_time64_to_tm(mqnic->build_date, &tm); - - dev_info(dev, "FPGA ID: 0x%08x", mqnic->fpga_id); - dev_info(dev, "FW ID: 0x%08x", mqnic->fw_id); - dev_info(dev, "FW version: %d.%d.%d.%d", mqnic->fw_ver >> 24, - (mqnic->fw_ver >> 16) & 0xff, - (mqnic->fw_ver >> 8) & 0xff, - mqnic->fw_ver & 0xff); - dev_info(dev, "Board ID: 0x%08x", mqnic->board_id); - dev_info(dev, "Board version: %d.%d.%d.%d", mqnic->board_ver >> 24, - (mqnic->board_ver >> 16) & 0xff, - (mqnic->board_ver >> 8) & 0xff, - mqnic->board_ver & 0xff); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) - snprintf(mqnic->build_date_str, sizeof(mqnic->build_date_str), "%ptRd %ptRt", &tm, &tm); -#else - snprintf(mqnic->build_date_str, sizeof(mqnic->build_date_str), "%04d-%02d-%02d %02d:%02d:%02d", - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); -#endif - dev_info(dev, "Build date: %s UTC (raw: 0x%08x)", mqnic->build_date_str, mqnic->build_date); - dev_info(dev, "Git hash: %08x", mqnic->git_hash); - dev_info(dev, "Release info: %08x", mqnic->rel_info); - - rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_APP_INFO_TYPE, MQNIC_RB_APP_INFO_VER, 0); - - if (rb) { - mqnic->app_id = ioread32(rb->regs + MQNIC_RB_APP_INFO_REG_ID); - dev_info(dev, "Application ID: 0x%08x", mqnic->app_id); - - if (!mqnic->app_hw_addr) { - dev_warn(dev, "Warning: application section present, but application BAR not mapped"); - } - } - - mqnic_clk_info_init(mqnic); - mqnic_stats_init(mqnic); - - mqnic->phc_rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_PHC_TYPE, MQNIC_RB_PHC_VER, 0); - - // Enumerate interfaces - mqnic->if_rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_IF_TYPE, MQNIC_RB_IF_VER, 0); - - if (!mqnic->if_rb) { - ret = -EIO; - dev_err(dev, "Error: interface block not found"); - goto fail_rb_init; - } - - mqnic->if_offset = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_OFFSET); - mqnic->if_count = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_COUNT); - mqnic->if_stride = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_STRIDE); - mqnic->if_csr_offset = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_CSR_OFFSET); - - dev_info(dev, "IF offset: 0x%08x", mqnic->if_offset); - dev_info(dev, "IF count: %d", mqnic->if_count); - dev_info(dev, "IF stride: 0x%08x", mqnic->if_stride); - dev_info(dev, "IF CSR offset: 0x%08x", mqnic->if_csr_offset); - - // check BAR size - if (mqnic->if_count * mqnic->if_stride > mqnic->hw_regs_size) { - ret = -EIO; - dev_err(dev, "Invalid BAR configuration (%d IF * 0x%x > 0x%llx)", - mqnic->if_count, mqnic->if_stride, mqnic->hw_regs_size); - goto fail_bar_size; - } - - if (mqnic->pfdev) { -#ifdef CONFIG_OF - ret = mqnic_platform_get_mac_address(mqnic); - if (ret) - goto fail_board; - - ret = mqnic_platform_module_eeprom_get(mqnic); - if (ret) - goto fail_board; -#endif - } else { - // Board-specific init - ret = mqnic_board_init(mqnic); - if (ret) { - dev_err(dev, "Failed to initialize board"); - goto fail_board; - } - } - - // register PHC - if (mqnic->phc_rb) - mqnic_register_phc(mqnic); - - mutex_init(&mqnic->state_lock); - - // Set up interfaces - mqnic->phys_port_max = 0; - - mqnic->if_count = min_t(u32, mqnic->if_count, MQNIC_MAX_IF); - - for (k = 0; k < mqnic->if_count; k++) { - struct mqnic_if *interface; - dev_info(dev, "Creating interface %d", k); - interface = mqnic_create_interface(mqnic, k, mqnic->hw_addr + k * mqnic->if_stride); - if (IS_ERR_OR_NULL(interface)) { - dev_err(dev, "Failed to create interface: %d", ret); - goto fail_create_if; - } - mqnic->interface[k] = interface; - } - - // pass module I2C clients to interface instances - for (k = 0; k < mqnic->if_count; k++) { - struct mqnic_if *interface = mqnic->interface[k]; - interface->mod_i2c_client = mqnic->mod_i2c_client[k]; - - for (l = 0; l < interface->ndev_count; l++) { - struct mqnic_priv *priv = netdev_priv(interface->ndev[l]); - priv->mod_i2c_client = mqnic->mod_i2c_client[k]; - } - } - -fail_create_if: - mqnic->misc_dev.minor = MISC_DYNAMIC_MINOR; - mqnic->misc_dev.name = mqnic->name; - mqnic->misc_dev.fops = &mqnic_fops; - mqnic->misc_dev.parent = dev; - - ret = misc_register(&mqnic->misc_dev); - if (ret) { - mqnic->misc_dev.this_device = NULL; - dev_err(dev, "misc_register failed: %d\n", ret); - goto fail_miscdev; - } - - dev_info(dev, "Registered device %s", mqnic->name); - -#ifdef CONFIG_AUXILIARY_BUS - if (mqnic->app_id) { - mqnic->app_adev = kzalloc(sizeof(*mqnic->app_adev), GFP_KERNEL); - if (!mqnic->app_adev) { - ret = -ENOMEM; - goto fail_adev; - } - - snprintf(mqnic->app_adev->name, sizeof(mqnic->app_adev->name), "app_%08x", mqnic->app_id); - - mqnic->app_adev->adev.id = mqnic->id; - mqnic->app_adev->adev.name = mqnic->app_adev->name; - mqnic->app_adev->adev.dev.parent = dev; - mqnic->app_adev->adev.dev.release = mqnic_adev_release; - mqnic->app_adev->mdev = mqnic; - mqnic->app_adev->ptr = &mqnic->app_adev; - - ret = auxiliary_device_init(&mqnic->app_adev->adev); - if (ret) { - kfree(mqnic->app_adev); - mqnic->app_adev = NULL; - goto fail_adev; - } - - ret = auxiliary_device_add(&mqnic->app_adev->adev); - if (ret) { - auxiliary_device_uninit(&mqnic->app_adev->adev); - mqnic->app_adev = NULL; - goto fail_adev; - } - - dev_info(dev, "Registered auxiliary bus device " DRIVER_NAME ".%s.%d", - mqnic->app_adev->adev.name, mqnic->app_adev->adev.id); - } -#endif - - // probe complete - return 0; - - // error handling -#ifdef CONFIG_AUXILIARY_BUS -fail_adev: -#endif -fail_miscdev: -fail_board: -fail_bar_size: -fail_rb_init: - mqnic_common_remove(mqnic); - return ret; -} - -static void mqnic_common_remove(struct mqnic_dev *mqnic) -{ - struct devlink *devlink = priv_to_devlink(mqnic); - int k = 0; - -#ifdef CONFIG_AUXILIARY_BUS - if (mqnic->app_adev) { - auxiliary_device_delete(&mqnic->app_adev->adev); - auxiliary_device_uninit(&mqnic->app_adev->adev); - } -#endif - - if (mqnic->misc_dev.this_device) - misc_deregister(&mqnic->misc_dev); - - for (k = 0; k < ARRAY_SIZE(mqnic->interface); k++) { - if (mqnic->interface[k]) { - mqnic_destroy_interface(mqnic->interface[k]); - mqnic->interface[k] = NULL; - } - } - - mqnic_unregister_phc(mqnic); - if (mqnic->pfdev) { -#ifdef CONFIG_OF - mqnic_platform_module_eeprom_put(mqnic); -#endif - } else { - mqnic_board_deinit(mqnic); - } - if (mqnic->rb_list) - mqnic_free_reg_block_list(mqnic->rb_list); - - devlink_unregister(devlink); -} - -#ifdef CONFIG_PCI -static int mqnic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int ret = 0; - struct mqnic_dev *mqnic; - struct devlink *devlink; - struct device *dev = &pdev->dev; - struct pci_dev *bridge = pci_upstream_bridge(pdev); - - dev_info(dev, DRIVER_NAME " PCI probe"); - dev_info(dev, " Vendor: 0x%04x", pdev->vendor); - dev_info(dev, " Device: 0x%04x", pdev->device); - dev_info(dev, " Subsystem vendor: 0x%04x", pdev->subsystem_vendor); - dev_info(dev, " Subsystem device: 0x%04x", pdev->subsystem_device); - dev_info(dev, " Class: 0x%06x", pdev->class); - dev_info(dev, " PCI ID: %04x:%02x:%02x.%d", pci_domain_nr(pdev->bus), - pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - - if (pdev->pcie_cap) { - u16 devctl; - u32 lnkcap; - u16 lnkctl; - u16 lnksta; - - pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_DEVCTL, &devctl); - pci_read_config_dword(pdev, pdev->pcie_cap + PCI_EXP_LNKCAP, &lnkcap); - pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_LNKCTL, &lnkctl); - pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_LNKSTA, &lnksta); - - dev_info(dev, " Max payload size: %d bytes", - 128 << ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5)); - dev_info(dev, " Max read request size: %d bytes", - 128 << ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12)); - dev_info(dev, " Read completion boundary: %d bytes", - lnkctl & PCI_EXP_LNKCTL_RCB ? 128 : 64); - dev_info(dev, " Link capability: gen %d x%d", - lnkcap & PCI_EXP_LNKCAP_SLS, (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4); - dev_info(dev, " Link status: gen %d x%d", - lnksta & PCI_EXP_LNKSTA_CLS, (lnksta & PCI_EXP_LNKSTA_NLW) >> 4); - dev_info(dev, " Relaxed ordering: %s", - devctl & PCI_EXP_DEVCTL_RELAX_EN ? "enabled" : "disabled"); - dev_info(dev, " Phantom functions: %s", - devctl & PCI_EXP_DEVCTL_PHANTOM ? "enabled" : "disabled"); - dev_info(dev, " Extended tags: %s", - devctl & PCI_EXP_DEVCTL_EXT_TAG ? "enabled" : "disabled"); - dev_info(dev, " No snoop: %s", - devctl & PCI_EXP_DEVCTL_NOSNOOP_EN ? "enabled" : "disabled"); - } - -#ifdef CONFIG_NUMA - dev_info(dev, " NUMA node: %d", pdev->dev.numa_node); -#endif - - if (bridge) { - dev_info(dev, " PCI ID (bridge): %04x:%02x:%02x.%d", pci_domain_nr(bridge->bus), - bridge->bus->number, PCI_SLOT(bridge->devfn), PCI_FUNC(bridge->devfn)); - } - - if (bridge && bridge->pcie_cap) { - u32 lnkcap; - u16 lnksta; - - pci_read_config_dword(bridge, bridge->pcie_cap + PCI_EXP_LNKCAP, &lnkcap); - pci_read_config_word(bridge, bridge->pcie_cap + PCI_EXP_LNKSTA, &lnksta); - - dev_info(dev, " Link capability (bridge): gen %d x%d", - lnkcap & PCI_EXP_LNKCAP_SLS, (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4); - dev_info(dev, " Link status (bridge): gen %d x%d", - lnksta & PCI_EXP_LNKSTA_CLS, (lnksta & PCI_EXP_LNKSTA_NLW) >> 4); - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) - pcie_print_link_status(pdev); -#endif - - devlink = mqnic_devlink_alloc(dev); - if (!devlink) - return -ENOMEM; - - mqnic = devlink_priv(devlink); - mqnic->dev = dev; - mqnic->pdev = pdev; - pci_set_drvdata(pdev, mqnic); - - // assign ID and add to list - mqnic_assign_id(mqnic); - - // Disable ASPM - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | - PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); - - // Enable device - ret = pci_enable_device_mem(pdev); - if (ret) { - dev_err(dev, "Failed to enable PCI device"); - goto fail_enable_device; - } - - // Set DMA properties - ret = mqnic_common_setdma(mqnic); - if (ret) - goto fail_regions; - - // Reserve regions - ret = pci_request_regions(pdev, DRIVER_NAME); - if (ret) { - dev_err(dev, "Failed to reserve regions"); - goto fail_regions; - } - - mqnic->hw_regs_size = pci_resource_len(pdev, 0); - mqnic->hw_regs_phys = pci_resource_start(pdev, 0); - mqnic->app_hw_regs_size = pci_resource_len(pdev, 2); - mqnic->app_hw_regs_phys = pci_resource_start(pdev, 2); - mqnic->ram_hw_regs_size = pci_resource_len(pdev, 4); - mqnic->ram_hw_regs_phys = pci_resource_start(pdev, 4); - - // Map BARs - dev_info(dev, "Control BAR size: %llu", mqnic->hw_regs_size); - mqnic->hw_addr = pci_ioremap_bar(pdev, 0); - if (!mqnic->hw_addr) { - ret = -ENOMEM; - dev_err(dev, "Failed to map control BAR"); - goto fail_map_bars; - } - - if (mqnic->app_hw_regs_size) { - dev_info(dev, "Application BAR size: %llu", mqnic->app_hw_regs_size); - mqnic->app_hw_addr = pci_ioremap_bar(pdev, 2); - if (!mqnic->app_hw_addr) { - ret = -ENOMEM; - dev_err(dev, "Failed to map application BAR"); - goto fail_map_bars; - } - } - - if (mqnic->ram_hw_regs_size) { - dev_info(dev, "RAM BAR size: %llu", mqnic->ram_hw_regs_size); - mqnic->ram_hw_addr = pci_ioremap_bar(pdev, 4); - if (!mqnic->ram_hw_addr) { - ret = -ENOMEM; - dev_err(dev, "Failed to map RAM BAR"); - goto fail_map_bars; - } - } - - // Check if device needs to be reset - if (ioread32(mqnic->hw_addr+4) == 0xffffffff) { - ret = -EIO; - dev_err(dev, "Device needs to be reset"); - goto fail_reset; - } - - // Set up interrupts - ret = mqnic_irq_init_pcie(mqnic); - if (ret) { - dev_err(dev, "Failed to set up interrupts"); - goto fail_init_irq; - } - - // Enable bus mastering for DMA - pci_set_master(pdev); - - // Common init - ret = mqnic_common_probe(mqnic); - if (ret) - goto fail_common; - - // probe complete - return 0; - - // error handling -fail_common: - pci_clear_master(pdev); - mqnic_irq_deinit_pcie(mqnic); -fail_reset: -fail_init_irq: -fail_map_bars: - if (mqnic->hw_addr) - pci_iounmap(pdev, mqnic->hw_addr); - if (mqnic->app_hw_addr) - pci_iounmap(pdev, mqnic->app_hw_addr); - if (mqnic->ram_hw_addr) - pci_iounmap(pdev, mqnic->ram_hw_addr); - pci_release_regions(pdev); -fail_regions: - pci_disable_device(pdev); -fail_enable_device: - mqnic_free_id(mqnic); - mqnic_devlink_free(devlink); - return ret; -} - -static void mqnic_pci_remove(struct pci_dev *pdev) -{ - struct mqnic_dev *mqnic = pci_get_drvdata(pdev); - struct devlink *devlink = priv_to_devlink(mqnic); - - dev_info(&pdev->dev, DRIVER_NAME " PCI remove"); - - mqnic_common_remove(mqnic); - - pci_clear_master(pdev); - mqnic_irq_deinit_pcie(mqnic); - if (mqnic->hw_addr) - pci_iounmap(pdev, mqnic->hw_addr); - if (mqnic->app_hw_addr) - pci_iounmap(pdev, mqnic->app_hw_addr); - if (mqnic->ram_hw_addr) - pci_iounmap(pdev, mqnic->ram_hw_addr); - pci_release_regions(pdev); - pci_disable_device(pdev); - mqnic_free_id(mqnic); - mqnic_devlink_free(devlink); -} - -static void mqnic_pci_shutdown(struct pci_dev *pdev) -{ - dev_info(&pdev->dev, DRIVER_NAME " PCI shutdown"); - - mqnic_pci_remove(pdev); -} - -static struct pci_driver mqnic_pci_driver = { - .name = DRIVER_NAME, - .id_table = mqnic_pci_id_table, - .probe = mqnic_pci_probe, - .remove = mqnic_pci_remove, - .shutdown = mqnic_pci_shutdown -}; -#endif /* CONFIG_PCI */ - -static int mqnic_platform_probe(struct platform_device *pdev) -{ - int ret; - struct mqnic_dev *mqnic; - struct devlink *devlink; - struct device *dev = &pdev->dev; - struct resource *res; - struct reset_control *rst; - - dev_info(dev, DRIVER_NAME " platform probe"); - -#ifdef CONFIG_NUMA - dev_info(dev, " NUMA node: %d", pdev->dev.numa_node); -#endif - - devlink = mqnic_devlink_alloc(dev); - if (!devlink) - return -ENOMEM; - - mqnic = devlink_priv(devlink); - mqnic->dev = dev; - mqnic->pfdev = pdev; - platform_set_drvdata(pdev, mqnic); - - // assign ID and add to list - mqnic_assign_id(mqnic); - - // Set DMA properties - ret = mqnic_common_setdma(mqnic); - if (ret) - goto fail; - - // Reset device - rst = devm_reset_control_get(dev, NULL); - if (IS_ERR(rst)) { - dev_warn(dev, "Cannot control device reset"); - } else { - dev_info(dev, "Resetting device"); - reset_control_assert(rst); - udelay(2); - reset_control_deassert(rst); - } - - // Reserve and map regions - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mqnic->hw_regs_size = resource_size(res); - mqnic->hw_regs_phys = res->start; - - dev_info(dev, "Control BAR size: %llu", mqnic->hw_regs_size); - mqnic->hw_addr = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(mqnic->hw_addr)) { - ret = PTR_ERR(mqnic->hw_addr); - dev_err(dev, "Failed to map control BAR"); - goto fail; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (res) { - void __iomem *hw_addr; - - mqnic->app_hw_regs_size = resource_size(res); - mqnic->app_hw_regs_phys = res->start; - - dev_info(dev, "Application BAR size: %llu", mqnic->app_hw_regs_size); - hw_addr = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(hw_addr)) { - ret = PTR_ERR(hw_addr); - dev_err(dev, "Failed to map application BAR"); - goto fail; - } - mqnic->app_hw_addr = hw_addr; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 2); - if (res) { - void __iomem *hw_addr; - - mqnic->ram_hw_regs_size = resource_size(res); - mqnic->ram_hw_regs_phys = res->start; - - dev_info(dev, "RAM BAR size: %llu", mqnic->ram_hw_regs_size); - hw_addr = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(hw_addr)) { - ret = PTR_ERR(hw_addr); - dev_err(dev, "Failed to map RAM BAR"); - goto fail; - } - mqnic->ram_hw_addr = hw_addr; - } - - // Set up interrupts - ret = mqnic_irq_init_platform(mqnic); - if (ret) { - dev_err(dev, "Failed to set up interrupts"); - goto fail; - } - - // Common init - ret = mqnic_common_probe(mqnic); - if (ret) - goto fail; - - // probe complete - return 0; - - // error handling -fail: - mqnic_free_id(mqnic); - mqnic_devlink_free(devlink); - return ret; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0) -static void mqnic_platform_remove(struct platform_device *pdev) -#else -static int mqnic_platform_remove(struct platform_device *pdev) -#endif -{ - struct mqnic_dev *mqnic = platform_get_drvdata(pdev); - struct devlink *devlink = priv_to_devlink(mqnic); - - dev_info(&pdev->dev, DRIVER_NAME " platform remove"); - - mqnic_common_remove(mqnic); - - mqnic_free_id(mqnic); - mqnic_devlink_free(devlink); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 11, 0) - return; -#else - return 0; -#endif -} - -static struct platform_driver mqnic_platform_driver = { - .probe = mqnic_platform_probe, - .remove = mqnic_platform_remove, - .driver = { - .name = DRIVER_NAME, - .of_match_table = of_match_ptr(mqnic_of_id_table), - }, -}; - -static int __init mqnic_init(void) -{ - int rc; - -#ifdef CONFIG_PCI - rc = pci_register_driver(&mqnic_pci_driver); - if (rc) - return rc; -#endif - - rc = platform_driver_register(&mqnic_platform_driver); - if (rc) - goto err; - - return 0; - -err: -#ifdef CONFIG_PCI - pci_unregister_driver(&mqnic_pci_driver); -#endif - return rc; -} - -static void __exit mqnic_exit(void) -{ - platform_driver_unregister(&mqnic_platform_driver); - -#ifdef CONFIG_PCI - pci_unregister_driver(&mqnic_pci_driver); -#endif -} - -module_init(mqnic_init); -module_exit(mqnic_exit); diff --git a/modules/mqnic_vf/mqnic_netdev.c b/modules/mqnic_vf/mqnic_netdev.c deleted file mode 100644 index 0d14209..0000000 --- a/modules/mqnic_vf/mqnic_netdev.c +++ /dev/null @@ -1,691 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause-Views -/* - * Copyright (c) 2019-2023 The Regents of the University of California - */ - -#include "mqnic.h" - -#include - -int mqnic_start_port(struct net_device *ndev) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - struct mqnic_if *iface = priv->interface; - struct mqnic_ring *q; - struct mqnic_cq *cq; - struct radix_tree_iter iter; - void **slot; - int k; - int ret; - u32 desc_block_size; - - netdev_info(ndev, "%s on interface %d netdev %d", __func__, - priv->interface->index, priv->index); - - netif_set_real_num_tx_queues(ndev, priv->txq_count); - netif_set_real_num_rx_queues(ndev, priv->rxq_count); - - desc_block_size = min_t(u32, priv->interface->max_desc_block_size, 4); - - // set up RX queues - for (k = 0; k < priv->rxq_count; k++) { - // create CQ - cq = mqnic_create_cq(iface); - if (IS_ERR_OR_NULL(cq)) { - ret = PTR_ERR(cq); - goto fail; - } - - ret = mqnic_open_cq(cq, iface->eq[k % iface->eq_count], priv->rx_ring_size); - if (ret) { - mqnic_destroy_cq(cq); - goto fail; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) - netif_napi_add(ndev, &cq->napi, mqnic_poll_rx_cq); -#else - netif_napi_add(ndev, &cq->napi, mqnic_poll_rx_cq, NAPI_POLL_WEIGHT); -#endif - napi_enable(&cq->napi); - - mqnic_arm_cq(cq); - - // create RX queue - q = mqnic_create_rx_ring(iface); - if (IS_ERR_OR_NULL(q)) { - ret = PTR_ERR(q); - mqnic_destroy_cq(cq); - goto fail; - } - - q->mtu = ndev->mtu; - if (ndev->mtu + ETH_HLEN <= PAGE_SIZE) - q->page_order = 0; - else - q->page_order = ilog2((ndev->mtu + ETH_HLEN + PAGE_SIZE - 1) / PAGE_SIZE - 1) + 1; - - ret = mqnic_open_rx_ring(q, priv, cq, priv->rx_ring_size, 1); - if (ret) { - mqnic_destroy_rx_ring(q); - mqnic_destroy_cq(cq); - goto fail; - } - - down_write(&priv->rxq_table_sem); - ret = radix_tree_insert(&priv->rxq_table, k, q); - up_write(&priv->rxq_table_sem); - if (ret) { - mqnic_destroy_rx_ring(q); - mqnic_destroy_cq(cq); - goto fail; - } - } - - // set up TX queues - for (k = 0; k < priv->txq_count; k++) { - // create CQ - cq = mqnic_create_cq(iface); - if (IS_ERR_OR_NULL(cq)) { - ret = PTR_ERR(cq); - goto fail; - } - - ret = mqnic_open_cq(cq, iface->eq[k % iface->eq_count], priv->tx_ring_size); - if (ret) { - mqnic_destroy_cq(cq); - goto fail; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) - netif_napi_add_tx(ndev, &cq->napi, mqnic_poll_tx_cq); -#else - netif_tx_napi_add(ndev, &cq->napi, mqnic_poll_tx_cq, NAPI_POLL_WEIGHT); -#endif - napi_enable(&cq->napi); - - mqnic_arm_cq(cq); - - // create TX queue - q = mqnic_create_tx_ring(iface); - if (IS_ERR_OR_NULL(q)) { - ret = PTR_ERR(q); - mqnic_destroy_cq(cq); - goto fail; - } - - q->tx_queue = netdev_get_tx_queue(ndev, k); - - ret = mqnic_open_tx_ring(q, priv, cq, priv->tx_ring_size, desc_block_size); - if (ret) { - mqnic_destroy_tx_ring(q); - mqnic_destroy_cq(cq); - goto fail; - } - - down_write(&priv->txq_table_sem); - ret = radix_tree_insert(&priv->txq_table, k, q); - up_write(&priv->txq_table_sem); - if (ret) { - mqnic_destroy_tx_ring(q); - mqnic_destroy_cq(cq); - goto fail; - } - } - - // set MTU - mqnic_interface_set_tx_mtu(iface, ndev->mtu + ETH_HLEN); - mqnic_interface_set_rx_mtu(iface, ndev->mtu + ETH_HLEN); - - // configure RX indirection and RSS - mqnic_update_indir_table(ndev); - - priv->port_up = true; - - // enable TX and RX queues - down_read(&priv->txq_table_sem); - radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { - struct mqnic_ring *q = (struct mqnic_ring *)*slot; - - mqnic_enable_tx_ring(q); - } - up_read(&priv->txq_table_sem); - - down_read(&priv->rxq_table_sem); - radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { - struct mqnic_ring *q = (struct mqnic_ring *)*slot; - - mqnic_enable_rx_ring(q); - } - up_read(&priv->rxq_table_sem); - - mqnic_port_set_tx_ctrl(priv->port, MQNIC_PORT_TX_CTRL_EN); - - // enable scheduler - mqnic_activate_sched_block(priv->sched_block); - - netif_tx_start_all_queues(ndev); - netif_device_attach(ndev); - - if (mqnic_link_status_poll) { - priv->link_status = 0; - mod_timer(&priv->link_status_timer, - jiffies + msecs_to_jiffies(mqnic_link_status_poll)); - } else { - netif_carrier_on(ndev); - } - - mqnic_port_set_rx_ctrl(priv->port, MQNIC_PORT_RX_CTRL_EN); - - return 0; - -fail: - mqnic_stop_port(ndev); - return ret; -} - -void mqnic_stop_port(struct net_device *ndev) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - struct mqnic_cq *cq; - struct radix_tree_iter iter; - void **slot; - - netdev_info(ndev, "%s on interface %d netdev %d", __func__, - priv->interface->index, priv->index); - - if (mqnic_link_status_poll) - del_timer_sync(&priv->link_status_timer); - - mqnic_port_set_rx_ctrl(priv->port, 0); - - netif_tx_lock_bh(ndev); -// if (detach) -// netif_device_detach(ndev); - netif_tx_stop_all_queues(ndev); - netif_tx_unlock_bh(ndev); - - netif_carrier_off(ndev); - netif_tx_disable(ndev); - - spin_lock_bh(&priv->stats_lock); - mqnic_update_stats(ndev); - spin_unlock_bh(&priv->stats_lock); - - // disable scheduler - mqnic_deactivate_sched_block(priv->sched_block); - - // disable TX and RX queues - down_read(&priv->txq_table_sem); - radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { - struct mqnic_ring *q = (struct mqnic_ring *)*slot; - - mqnic_disable_tx_ring(q); - } - up_read(&priv->txq_table_sem); - - down_read(&priv->rxq_table_sem); - radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { - struct mqnic_ring *q = (struct mqnic_ring *)*slot; - - mqnic_disable_rx_ring(q); - } - up_read(&priv->rxq_table_sem); - - msleep(20); - - mqnic_port_set_tx_ctrl(priv->port, 0); - - priv->port_up = false; - - // shut down NAPI and clean queues - down_write(&priv->txq_table_sem); - radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { - struct mqnic_ring *q = (struct mqnic_ring *)*slot; - - cq = q->cq; - napi_disable(&cq->napi); - netif_napi_del(&cq->napi); - mqnic_close_tx_ring(q); - mqnic_destroy_tx_ring(q); - radix_tree_delete(&priv->txq_table, iter.index); - mqnic_close_cq(cq); - mqnic_destroy_cq(cq); - } - up_write(&priv->txq_table_sem); - - down_write(&priv->rxq_table_sem); - radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { - struct mqnic_ring *q = (struct mqnic_ring *)*slot; - - cq = q->cq; - napi_disable(&cq->napi); - netif_napi_del(&cq->napi); - mqnic_close_rx_ring(q); - mqnic_destroy_rx_ring(q); - radix_tree_delete(&priv->rxq_table, iter.index); - mqnic_close_cq(cq); - mqnic_destroy_cq(cq); - } - up_write(&priv->rxq_table_sem); -} - -static int mqnic_open(struct net_device *ndev) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - struct mqnic_dev *mdev = priv->mdev; - int ret = 0; - - mutex_lock(&mdev->state_lock); - - ret = mqnic_start_port(ndev); - - if (ret) - netdev_err(ndev, "Failed to start port on interface %d netdev %d: %d", - priv->interface->index, priv->index, ret); - - mutex_unlock(&mdev->state_lock); - return ret; -} - -static int mqnic_close(struct net_device *ndev) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - struct mqnic_dev *mdev = priv->mdev; - int ret = 0; - - mutex_lock(&mdev->state_lock); - - mqnic_stop_port(ndev); - - mutex_unlock(&mdev->state_lock); - return ret; -} - -int mqnic_update_indir_table(struct net_device *ndev) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - struct mqnic_if *iface = priv->interface; - struct mqnic_ring *q; - int k; - - mqnic_interface_set_rx_queue_map_rss_mask(iface, 0, 0xffffffff); - mqnic_interface_set_rx_queue_map_app_mask(iface, 0, 0); - - for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) { - rcu_read_lock(); - q = radix_tree_lookup(&priv->rxq_table, priv->rx_queue_map_indir_table[k]); - rcu_read_unlock(); - - if (q) - mqnic_interface_set_rx_queue_map_indir_table(iface, 0, k, q->index); - } - - return 0; -} - -void mqnic_update_stats(struct net_device *ndev) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - struct radix_tree_iter iter; - void **slot; - unsigned long packets, bytes; - unsigned long dropped; - - if (unlikely(!priv->port_up)) - return; - - packets = 0; - bytes = 0; - dropped = 0; - down_read(&priv->rxq_table_sem); - radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { - const struct mqnic_ring *q = (struct mqnic_ring *)*slot; - - packets += READ_ONCE(q->packets); - bytes += READ_ONCE(q->bytes); - dropped += READ_ONCE(q->dropped_packets); - } - up_read(&priv->rxq_table_sem); - ndev->stats.rx_packets = packets; - ndev->stats.rx_bytes = bytes; - ndev->stats.rx_dropped = dropped; - - packets = 0; - bytes = 0; - dropped = 0; - down_read(&priv->txq_table_sem); - radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { - const struct mqnic_ring *q = (struct mqnic_ring *)*slot; - - packets += READ_ONCE(q->packets); - bytes += READ_ONCE(q->bytes); - dropped += READ_ONCE(q->dropped_packets); - } - up_read(&priv->txq_table_sem); - ndev->stats.tx_packets = packets; - ndev->stats.tx_bytes = bytes; - ndev->stats.tx_dropped = dropped; -} - -static void mqnic_get_stats64(struct net_device *ndev, - struct rtnl_link_stats64 *stats) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - - spin_lock_bh(&priv->stats_lock); - mqnic_update_stats(ndev); - netdev_stats_to_stats64(stats, &ndev->stats); - spin_unlock_bh(&priv->stats_lock); -} - -static int mqnic_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - struct hwtstamp_config hwts_config; - - if (copy_from_user(&hwts_config, ifr->ifr_data, sizeof(hwts_config))) - return -EFAULT; - - if (hwts_config.flags) - return -EINVAL; - - switch (hwts_config.tx_type) { - case HWTSTAMP_TX_OFF: - case HWTSTAMP_TX_ON: - break; - default: - return -ERANGE; - } - - switch (hwts_config.rx_filter) { - case HWTSTAMP_FILTER_NONE: - break; - case HWTSTAMP_FILTER_ALL: - case HWTSTAMP_FILTER_SOME: - case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - case HWTSTAMP_FILTER_NTP_ALL: - hwts_config.rx_filter = HWTSTAMP_FILTER_ALL; - break; - default: - return -ERANGE; - } - - memcpy(&priv->hwts_config, &hwts_config, sizeof(hwts_config)); - - if (copy_to_user(ifr->ifr_data, &hwts_config, sizeof(hwts_config))) - return -EFAULT; - - return 0; -} - -static int mqnic_hwtstamp_get(struct net_device *ndev, struct ifreq *ifr) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - - if (copy_to_user(ifr->ifr_data, &priv->hwts_config, sizeof(priv->hwts_config))) - return -EFAULT; - - return 0; -} - -static int mqnic_change_mtu(struct net_device *ndev, int new_mtu) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - struct mqnic_dev *mdev = priv->mdev; - - if (new_mtu < ndev->min_mtu || new_mtu > ndev->max_mtu) { - netdev_err(ndev, "Bad MTU: %d", new_mtu); - return -EPERM; - } - - netdev_info(ndev, "New MTU: %d", new_mtu); - - ndev->mtu = new_mtu; - - if (netif_running(ndev)) { - mutex_lock(&mdev->state_lock); - - mqnic_stop_port(ndev); - mqnic_start_port(ndev); - - mutex_unlock(&mdev->state_lock); - } - - return 0; -} - -static int mqnic_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCSHWTSTAMP: - return mqnic_hwtstamp_set(ndev, ifr); - case SIOCGHWTSTAMP: - return mqnic_hwtstamp_get(ndev, ifr); - default: - return -EOPNOTSUPP; - } -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) -static struct devlink_port *mqnic_get_devlink_port(struct net_device *ndev) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - return priv->dl_port; -} -#endif - -static const struct net_device_ops mqnic_netdev_ops = { - .ndo_open = mqnic_open, - .ndo_stop = mqnic_close, - .ndo_start_xmit = mqnic_start_xmit, - .ndo_get_stats64 = mqnic_get_stats64, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = mqnic_change_mtu, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) - .ndo_eth_ioctl = mqnic_ioctl, -#else - .ndo_do_ioctl = mqnic_ioctl, -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) - .ndo_get_devlink_port = mqnic_get_devlink_port, -#endif -}; - -static void mqnic_link_status_timeout(struct timer_list *timer) -{ - struct mqnic_priv *priv = from_timer(priv, timer, link_status_timer); - unsigned int up = 1; - - if (!(mqnic_port_get_tx_ctrl(priv->port) & MQNIC_PORT_TX_CTRL_STATUS)) - up = 0; - if (!(mqnic_port_get_rx_ctrl(priv->port) & MQNIC_PORT_RX_CTRL_STATUS)) - up = 0; - - if (up) { - if (!priv->link_status) { - netif_carrier_on(priv->ndev); - priv->link_status = !priv->link_status; - } - } else { - if (priv->link_status) { - netif_carrier_off(priv->ndev); - priv->link_status = !priv->link_status; - } - } - - mod_timer(&priv->link_status_timer, jiffies + msecs_to_jiffies(mqnic_link_status_poll)); -} - -struct net_device *mqnic_create_netdev(struct mqnic_if *interface, int index, - struct mqnic_port *port, struct mqnic_sched_block *sched_block) -{ - struct mqnic_dev *mdev = interface->mdev; - struct device *dev = interface->dev; - struct net_device *ndev; - struct mqnic_priv *priv; - int ret = 0; - int k; - u32 desc_block_size; - - ndev = alloc_etherdev_mqs(sizeof(*priv), mqnic_res_get_count(interface->txq_res), - mqnic_res_get_count(interface->rxq_res)); - if (!ndev) { - dev_err(dev, "Failed to allocate memory"); - return ERR_PTR(-ENOMEM); - } - - SET_NETDEV_DEV(ndev, dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0) - SET_NETDEV_DEVLINK_PORT(ndev, &port->dl_port); -#endif - ndev->dev_port = port->phys_index; - - // init private data - priv = netdev_priv(ndev); - memset(priv, 0, sizeof(struct mqnic_priv)); - - spin_lock_init(&priv->stats_lock); - - priv->ndev = ndev; - priv->mdev = interface->mdev; - priv->dl_port = &port->dl_port; - priv->interface = interface; - priv->dev = dev; - priv->index = index; - priv->port = port; - priv->port_up = false; - priv->sched_block = sched_block; - - // associate interface resources - priv->if_features = interface->if_features; - - priv->txq_count = min_t(u32, mqnic_res_get_count(interface->txq_res), 256); - priv->rxq_count = min_t(u32, mqnic_res_get_count(interface->rxq_res), num_online_cpus()); - - priv->tx_ring_size = roundup_pow_of_two(clamp_t(u32, mqnic_num_txq_entries, - MQNIC_MIN_TX_RING_SZ, MQNIC_MAX_TX_RING_SZ)); - priv->rx_ring_size = roundup_pow_of_two(clamp_t(u32, mqnic_num_rxq_entries, - MQNIC_MIN_RX_RING_SZ, MQNIC_MAX_RX_RING_SZ)); - - init_rwsem(&priv->txq_table_sem); - INIT_RADIX_TREE(&priv->txq_table, GFP_KERNEL); - - init_rwsem(&priv->rxq_table_sem); - INIT_RADIX_TREE(&priv->rxq_table, GFP_KERNEL); - - netif_set_real_num_tx_queues(ndev, priv->txq_count); - netif_set_real_num_rx_queues(ndev, priv->rxq_count); - - // set MAC - ndev->addr_len = ETH_ALEN; - - if (ndev->dev_port >= mdev->mac_count) { - dev_warn(dev, "Exhausted permanent MAC addresses; using random MAC"); - eth_hw_addr_random(ndev); - } else { - u8 mac[ETH_ALEN]; - - memcpy(mac, mdev->mac_list[ndev->dev_port], ETH_ALEN); - mac[ETH_ALEN-1] += interface->mac; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) - eth_hw_addr_set(ndev, mac); -#else - memcpy(ndev->dev_addr, mac, ETH_ALEN); -#endif - - if (!is_valid_ether_addr(ndev->dev_addr)) { - dev_warn(dev, "Invalid MAC address in list; using random MAC"); - eth_hw_addr_random(ndev); - } - } - - priv->hwts_config.flags = 0; - priv->hwts_config.tx_type = HWTSTAMP_TX_OFF; - priv->hwts_config.rx_filter = HWTSTAMP_FILTER_NONE; - - desc_block_size = min_t(u32, interface->max_desc_block_size, 4); - - priv->rx_queue_map_indir_table_size = interface->rx_queue_map_indir_table_size; - priv->rx_queue_map_indir_table = kzalloc(sizeof(u32)*priv->rx_queue_map_indir_table_size, GFP_KERNEL); - if (!priv->rx_queue_map_indir_table) { - ret = -ENOMEM; - goto fail; - } - - for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) - priv->rx_queue_map_indir_table[k] = k % priv->rxq_count; - - // entry points - ndev->netdev_ops = &mqnic_netdev_ops; - ndev->ethtool_ops = &mqnic_ethtool_ops; - - // set up features - ndev->hw_features = NETIF_F_SG; - - if (priv->if_features & MQNIC_IF_FEATURE_RX_CSUM) - ndev->hw_features |= NETIF_F_RXCSUM; - - if (priv->if_features & MQNIC_IF_FEATURE_TX_CSUM) - ndev->hw_features |= NETIF_F_HW_CSUM; - - ndev->features = ndev->hw_features | NETIF_F_HIGHDMA; - ndev->hw_features |= 0; - - ndev->min_mtu = ETH_MIN_MTU; - ndev->max_mtu = 1500; - - if (interface->max_tx_mtu && interface->max_rx_mtu) - ndev->max_mtu = min(interface->max_tx_mtu, interface->max_rx_mtu) - ETH_HLEN; - - netif_carrier_off(ndev); - if (mqnic_link_status_poll) - timer_setup(&priv->link_status_timer, mqnic_link_status_timeout, 0); - - ret = register_netdev(ndev); - if (ret) { - dev_err(dev, "netdev registration failed on interface %d netdev %d: %d", - priv->interface->index, priv->index, ret); - goto fail; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) - devlink_port_type_eth_set(&port->dl_port, ndev); -#endif - - priv->registered = 1; - - return ndev; - -fail: - mqnic_destroy_netdev(ndev); - return ERR_PTR(ret); -} - -void mqnic_destroy_netdev(struct net_device *ndev) -{ - struct mqnic_priv *priv = netdev_priv(ndev); - - if (priv->registered) - unregister_netdev(ndev); - - kfree(priv->rx_queue_map_indir_table); - - #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) - devlink_port_type_clear(priv->dl_port); - #endif - - free_netdev(ndev); -} diff --git a/modules/mqnic_vf/mqnic_port.c b/modules/mqnic_vf/mqnic_port.c deleted file mode 120000 index 4e26d16..0000000 --- a/modules/mqnic_vf/mqnic_port.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_port.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_ptp.c b/modules/mqnic_vf/mqnic_ptp.c deleted file mode 120000 index 10d5fe4..0000000 --- a/modules/mqnic_vf/mqnic_ptp.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_ptp.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_reg_block.c b/modules/mqnic_vf/mqnic_reg_block.c deleted file mode 120000 index 51fd2c9..0000000 --- a/modules/mqnic_vf/mqnic_reg_block.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_reg_block.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_res.c b/modules/mqnic_vf/mqnic_res.c deleted file mode 120000 index 9f83623..0000000 --- a/modules/mqnic_vf/mqnic_res.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_res.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_rx.c b/modules/mqnic_vf/mqnic_rx.c deleted file mode 120000 index 1a7e933..0000000 --- a/modules/mqnic_vf/mqnic_rx.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_rx.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_sched_block.c b/modules/mqnic_vf/mqnic_sched_block.c deleted file mode 120000 index ea8fcc6..0000000 --- a/modules/mqnic_vf/mqnic_sched_block.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_sched_block.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_scheduler.c b/modules/mqnic_vf/mqnic_scheduler.c deleted file mode 120000 index 4a5321d..0000000 --- a/modules/mqnic_vf/mqnic_scheduler.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_scheduler.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_stats.c b/modules/mqnic_vf/mqnic_stats.c deleted file mode 120000 index c35a5b1..0000000 --- a/modules/mqnic_vf/mqnic_stats.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_stats.c \ No newline at end of file diff --git a/modules/mqnic_vf/mqnic_tx.c b/modules/mqnic_vf/mqnic_tx.c deleted file mode 120000 index f5bfc0f..0000000 --- a/modules/mqnic_vf/mqnic_tx.c +++ /dev/null @@ -1 +0,0 @@ -../mqnic/mqnic_tx.c \ No newline at end of file From e1c67209b5c3d1e6be78fa28ea222ac41941d473 Mon Sep 17 00:00:00 2001 From: JefferyLim Date: Thu, 30 Apr 2026 14:30:57 -0400 Subject: [PATCH 6/7] Fixing cqm_aruser in cpl_queue --- fpga/common/rtl/mqnic_interface.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/common/rtl/mqnic_interface.v b/fpga/common/rtl/mqnic_interface.v index ba6a283..25a92ac 100644 --- a/fpga/common/rtl/mqnic_interface.v +++ b/fpga/common/rtl/mqnic_interface.v @@ -1729,7 +1729,7 @@ cpl_queue_resource_translator_inst( .input_write_function_id(axil_cqm_awuser), .input_read_address(axil_cqm_araddr), - .input_read_function_id(axil_eqm_aruser), + .input_read_function_id(axil_cqm_aruser), .output_read_address(axil_cqm_araddr_translated), .output_write_address(axil_cqm_awaddr_translated), From 3eee5933d85c2856d1c869d5b4370703782ca63b Mon Sep 17 00:00:00 2001 From: Jeffery Lim <17893528+JefferyLim@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:33:19 -0400 Subject: [PATCH 7/7] Remove IRQ index logging in mqnic_irq.c Removed logging of IRQ index during initialization. --- modules/mqnic/mqnic_irq.c | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/mqnic/mqnic_irq.c b/modules/mqnic/mqnic_irq.c index bdbd9fe..456d461 100644 --- a/modules/mqnic/mqnic_irq.c +++ b/modules/mqnic/mqnic_irq.c @@ -50,7 +50,6 @@ int mqnic_irq_init_pcie(struct mqnic_dev *mdev) } irq->index = k; - dev_info(dev, "IRQ Index %d", k); irq->irqn = pci_irq_vector(pdev, k); mdev->irq[k] = irq; }