mirror of
https://github.com/fpganinja/taxi.git
synced 2026-02-28 05:55:09 -08:00
pyrite: Add support for flashing via PCIe VSEC
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
3
src/pyrite/rtl/pyrite_pcie_us_vsec_bpi.f
Normal file
3
src/pyrite/rtl/pyrite_pcie_us_vsec_bpi.f
Normal file
@@ -0,0 +1,3 @@
|
||||
pyrite_pcie_us_vsec_bpi.sv
|
||||
../lib/taxi/src/pcie/rtl/taxi_pcie_us_vsec_apb.sv
|
||||
../lib/taxi/src/apb/rtl/taxi_apb_if.sv
|
||||
250
src/pyrite/rtl/pyrite_pcie_us_vsec_bpi.sv
Normal file
250
src/pyrite/rtl/pyrite_pcie_us_vsec_bpi.sv
Normal file
@@ -0,0 +1,250 @@
|
||||
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
/*
|
||||
|
||||
Copyright (c) 2026 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
*/
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* Pyrite flashing support for UltraScale+ PCIe VSEC and BPI flash
|
||||
*/
|
||||
module pyrite_pcie_us_vsec_bpi #
|
||||
(
|
||||
parameter logic [15:0] EXT_CAP_ID = 16'h000B,
|
||||
parameter logic [3:0] EXT_CAP_VERSION = 4'h1,
|
||||
parameter logic [11:0] EXT_CAP_OFFSET = 12'h480,
|
||||
parameter logic [11:0] EXT_CAP_NEXT = 12'h000,
|
||||
parameter logic [15:0] EXT_CAP_VSEC_ID = 16'h00DB,
|
||||
parameter logic [3:0] EXT_CAP_VSEC_REV = 4'h1,
|
||||
|
||||
// FW ID
|
||||
parameter FPGA_ID = 32'hDEADBEEF,
|
||||
parameter FW_ID = 32'h00000000,
|
||||
parameter FW_VER = 32'h000_01_000,
|
||||
parameter BOARD_ID = 32'h1234_0000,
|
||||
parameter BOARD_VER = 32'h001_00_000,
|
||||
parameter BUILD_DATE = 32'd602976000,
|
||||
parameter GIT_HASH = 32'h5f87c2e8,
|
||||
parameter RELEASE_INFO = 32'h00000000,
|
||||
|
||||
// Flash
|
||||
parameter logic [3:0] FLASH_SEG_COUNT = 2,
|
||||
parameter logic [3:0] FLASH_SEG_DEFAULT = 1,
|
||||
parameter logic [3:0] FLASH_SEG_FALLBACK = 0,
|
||||
parameter logic [31:0] FLASH_SEG0_SIZE = 32'h00000000,
|
||||
parameter FLASH_DATA_W = 16,
|
||||
parameter FLASH_ADDR_W = 23,
|
||||
parameter FLASH_RGN_W = 1
|
||||
)
|
||||
(
|
||||
input wire logic clk,
|
||||
input wire logic rst,
|
||||
|
||||
/*
|
||||
* PCIe
|
||||
*/
|
||||
input wire logic cfg_ext_read_received,
|
||||
input wire logic cfg_ext_write_received,
|
||||
input wire logic [9:0] cfg_ext_register_number,
|
||||
input wire logic [7:0] cfg_ext_function_number,
|
||||
input wire logic [31:0] cfg_ext_write_data,
|
||||
input wire logic [3:0] cfg_ext_write_byte_enable,
|
||||
output wire logic [31:0] cfg_ext_read_data,
|
||||
output wire logic cfg_ext_read_data_valid,
|
||||
|
||||
/*
|
||||
* BPI flash
|
||||
*/
|
||||
output wire logic fpga_boot,
|
||||
input wire logic [FLASH_DATA_W-1:0] flash_dq_i,
|
||||
output wire logic [FLASH_DATA_W-1:0] flash_dq_o,
|
||||
output wire logic flash_dq_oe,
|
||||
output wire logic [FLASH_ADDR_W-1:0] flash_addr,
|
||||
output wire logic [FLASH_RGN_W-1:0] flash_region,
|
||||
output wire logic flash_region_oe,
|
||||
output wire logic flash_ce_n,
|
||||
output wire logic flash_oe_n,
|
||||
output wire logic flash_we_n,
|
||||
output wire logic flash_adv_n
|
||||
);
|
||||
|
||||
taxi_apb_if #(
|
||||
.DATA_W(32),
|
||||
.ADDR_W(16)
|
||||
) vsec_apb();
|
||||
|
||||
taxi_pcie_us_vsec_apb #(
|
||||
.EXT_CAP_ID(EXT_CAP_ID),
|
||||
.EXT_CAP_VERSION(EXT_CAP_VERSION),
|
||||
.EXT_CAP_OFFSET(EXT_CAP_OFFSET),
|
||||
.EXT_CAP_NEXT(EXT_CAP_NEXT),
|
||||
.EXT_CAP_VSEC_ID(EXT_CAP_VSEC_ID),
|
||||
.EXT_CAP_VSEC_REV(EXT_CAP_VSEC_REV)
|
||||
)
|
||||
vsec_cap_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* APB interface for register space
|
||||
*/
|
||||
.m_apb(vsec_apb),
|
||||
|
||||
/*
|
||||
* Interface to Ultrascale PCIe IP core
|
||||
*/
|
||||
.cfg_ext_read_received(cfg_ext_read_received),
|
||||
.cfg_ext_write_received(cfg_ext_write_received),
|
||||
.cfg_ext_register_number(cfg_ext_register_number),
|
||||
.cfg_ext_function_number(cfg_ext_function_number),
|
||||
.cfg_ext_write_data(cfg_ext_write_data),
|
||||
.cfg_ext_write_byte_enable(cfg_ext_write_byte_enable),
|
||||
.cfg_ext_read_data(cfg_ext_read_data),
|
||||
.cfg_ext_read_data_valid(cfg_ext_read_data_valid)
|
||||
);
|
||||
|
||||
logic vsec_apb_pready_reg = 1'b0;
|
||||
logic [31:0] vsec_apb_prdata_reg = '0;
|
||||
|
||||
logic fpga_boot_reg = 1'b0;
|
||||
|
||||
logic [FLASH_DATA_W-1:0] flash_dq_o_reg = '0;
|
||||
logic flash_dq_oe_reg = 1'b0;
|
||||
logic [FLASH_ADDR_W-1:0] flash_addr_reg = '0;
|
||||
logic [FLASH_RGN_W-1:0] flash_region_reg = '0;
|
||||
logic flash_region_oe_reg = 1'b0;
|
||||
logic flash_ce_n_reg = 1'b1;
|
||||
logic flash_oe_n_reg = 1'b1;
|
||||
logic flash_we_n_reg = 1'b1;
|
||||
logic flash_adv_n_reg = 1'b1;
|
||||
|
||||
assign vsec_apb.pready = vsec_apb_pready_reg;
|
||||
assign vsec_apb.prdata = vsec_apb_prdata_reg;
|
||||
assign vsec_apb.pslverr = 1'b0;
|
||||
assign vsec_apb.pruser = '0;
|
||||
assign vsec_apb.pbuser = '0;
|
||||
|
||||
assign fpga_boot = fpga_boot_reg;
|
||||
|
||||
assign flash_dq_o = flash_dq_o_reg;
|
||||
assign flash_dq_oe = flash_dq_oe_reg;
|
||||
assign flash_addr = flash_addr_reg;
|
||||
assign flash_region = flash_region_reg;
|
||||
assign flash_region_oe = flash_region_oe_reg;
|
||||
assign flash_ce_n = flash_ce_n_reg;
|
||||
assign flash_oe_n = flash_oe_n_reg;
|
||||
assign flash_we_n = flash_we_n_reg;
|
||||
assign flash_adv_n = flash_adv_n_reg;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
vsec_apb_pready_reg <= 1'b0;
|
||||
|
||||
if (vsec_apb.penable && vsec_apb.psel && !vsec_apb_pready_reg) begin
|
||||
vsec_apb_pready_reg <= 1'b1;
|
||||
vsec_apb_prdata_reg <= '0;
|
||||
|
||||
if (vsec_apb.pwrite) begin
|
||||
case (8'({vsec_apb.paddr >> 2, 2'b00}))
|
||||
// FW ID
|
||||
8'h0C: begin
|
||||
// FW ID: FPGA JTAG ID
|
||||
fpga_boot_reg <= vsec_apb.pwdata == 32'hFEE1DEAD;
|
||||
end
|
||||
// BPI flash
|
||||
8'h4C: begin
|
||||
// BPI flash ctrl: format
|
||||
fpga_boot_reg <= vsec_apb.pwdata == 32'hFEE1DEAD;
|
||||
end
|
||||
8'h50: begin
|
||||
// BPI flash ctrl: control
|
||||
if (vsec_apb.pstrb[0]) begin
|
||||
flash_ce_n_reg <= vsec_apb.pwdata[0];
|
||||
flash_oe_n_reg <= vsec_apb.pwdata[1];
|
||||
flash_we_n_reg <= vsec_apb.pwdata[2];
|
||||
flash_adv_n_reg <= vsec_apb.pwdata[3];
|
||||
end
|
||||
if (vsec_apb.pstrb[1]) begin
|
||||
flash_dq_oe_reg <= vsec_apb.pwdata[8];
|
||||
end
|
||||
if (vsec_apb.pstrb[2]) begin
|
||||
flash_region_oe_reg <= vsec_apb.pwdata[16];
|
||||
end
|
||||
end
|
||||
8'h54: begin
|
||||
// BPI flash ctrl: address
|
||||
{flash_region_reg, flash_addr_reg} <= (FLASH_ADDR_W+FLASH_RGN_W)'(vsec_apb.pwdata);
|
||||
end
|
||||
8'h58: flash_dq_o_reg <= FLASH_DATA_W'(vsec_apb.pwdata); // BPI flash ctrl: data
|
||||
default: begin end
|
||||
endcase
|
||||
end
|
||||
|
||||
case (8'({vsec_apb.paddr >> 2, 2'b00}))
|
||||
// FW ID
|
||||
8'h00: vsec_apb_prdata_reg <= 32'hffffffff; // FW ID: Type
|
||||
8'h04: vsec_apb_prdata_reg <= 32'h000_01_000; // FW ID: Version
|
||||
8'h08: vsec_apb_prdata_reg <= 32'h40; // FW ID: Next header
|
||||
8'h0C: vsec_apb_prdata_reg <= FPGA_ID; // FW ID: FPGA JTAG ID
|
||||
8'h10: vsec_apb_prdata_reg <= FW_ID; // FW ID: Firmware ID
|
||||
8'h14: vsec_apb_prdata_reg <= FW_VER; // FW ID: Firmware version
|
||||
8'h18: vsec_apb_prdata_reg <= BOARD_ID; // FW ID: Board ID
|
||||
8'h1C: vsec_apb_prdata_reg <= BOARD_VER; // FW ID: Board version
|
||||
8'h20: vsec_apb_prdata_reg <= BUILD_DATE; // FW ID: Build date
|
||||
8'h24: vsec_apb_prdata_reg <= GIT_HASH; // FW ID: Git commit hash
|
||||
8'h28: vsec_apb_prdata_reg <= RELEASE_INFO; // FW ID: Release info
|
||||
// BPI flash
|
||||
8'h40: vsec_apb_prdata_reg <= 32'h0000C121; // BPI flash ctrl: Type
|
||||
8'h44: vsec_apb_prdata_reg <= 32'h000_01_000; // BPI flash ctrl: Version
|
||||
8'h48: vsec_apb_prdata_reg <= 0; // BPI flash ctrl: Next header
|
||||
8'h4C: begin
|
||||
// BPI flash ctrl: format
|
||||
vsec_apb_prdata_reg[3:0] <= FLASH_SEG_COUNT; // configuration
|
||||
vsec_apb_prdata_reg[7:4] <= FLASH_SEG_DEFAULT; // default segment
|
||||
vsec_apb_prdata_reg[11:8] <= FLASH_SEG_FALLBACK; // fallback segment
|
||||
vsec_apb_prdata_reg[31:12] <= 20'(FLASH_SEG0_SIZE >> 12); // first segment size
|
||||
end
|
||||
8'h50: begin
|
||||
// BPI flash ctrl: control
|
||||
vsec_apb_prdata_reg[0] <= flash_ce_n_reg; // chip enable (inverted)
|
||||
vsec_apb_prdata_reg[1] <= flash_oe_n_reg; // output enable (inverted)
|
||||
vsec_apb_prdata_reg[2] <= flash_we_n_reg; // write enable (inverted)
|
||||
vsec_apb_prdata_reg[3] <= flash_adv_n_reg; // address valid (inverted)
|
||||
vsec_apb_prdata_reg[8] <= flash_dq_oe_reg; // data output enable
|
||||
vsec_apb_prdata_reg[16] <= flash_region_oe_reg; // region output enable (addr bit 25)
|
||||
end
|
||||
8'h54: begin
|
||||
// BPI flash ctrl: address
|
||||
vsec_apb_prdata_reg <= 32'({flash_region_reg, flash_addr_reg});
|
||||
end
|
||||
8'h58: vsec_apb_prdata_reg <= 32'(flash_dq_i); // BPI flash ctrl: data
|
||||
default: begin end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (rst) begin
|
||||
vsec_apb_pready_reg <= 1'b0;
|
||||
|
||||
fpga_boot_reg <= 1'b0;
|
||||
|
||||
flash_dq_o_reg <= '0;
|
||||
flash_dq_oe_reg <= 1'b0;
|
||||
flash_addr_reg <= '0;
|
||||
flash_region_reg <= '0;
|
||||
flash_region_oe_reg <= 1'b0;
|
||||
flash_ce_n_reg <= 1'b1;
|
||||
flash_oe_n_reg <= 1'b1;
|
||||
flash_we_n_reg <= 1'b1;
|
||||
flash_adv_n_reg <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
||||
3
src/pyrite/rtl/pyrite_pcie_us_vsec_qspi.f
Normal file
3
src/pyrite/rtl/pyrite_pcie_us_vsec_qspi.f
Normal file
@@ -0,0 +1,3 @@
|
||||
pyrite_pcie_us_vsec_qspi.sv
|
||||
../lib/taxi/src/pcie/rtl/taxi_pcie_us_vsec_apb.sv
|
||||
../lib/taxi/src/apb/rtl/taxi_apb_if.sv
|
||||
252
src/pyrite/rtl/pyrite_pcie_us_vsec_qspi.sv
Normal file
252
src/pyrite/rtl/pyrite_pcie_us_vsec_qspi.sv
Normal file
@@ -0,0 +1,252 @@
|
||||
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
/*
|
||||
|
||||
Copyright (c) 2026 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
*/
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* Pyrite flashing support for UltraScale+ PCIe VSEC and QSPI flash
|
||||
*/
|
||||
module pyrite_pcie_us_vsec_qspi #
|
||||
(
|
||||
parameter logic [15:0] EXT_CAP_ID = 16'h000B,
|
||||
parameter logic [3:0] EXT_CAP_VERSION = 4'h1,
|
||||
parameter logic [11:0] EXT_CAP_OFFSET = 12'h480,
|
||||
parameter logic [11:0] EXT_CAP_NEXT = 12'h000,
|
||||
parameter logic [15:0] EXT_CAP_VSEC_ID = 16'h00DB,
|
||||
parameter logic [3:0] EXT_CAP_VSEC_REV = 4'h1,
|
||||
|
||||
// FW ID
|
||||
parameter FPGA_ID = 32'hDEADBEEF,
|
||||
parameter FW_ID = 32'h00000000,
|
||||
parameter FW_VER = 32'h000_01_000,
|
||||
parameter BOARD_ID = 32'h1234_0000,
|
||||
parameter BOARD_VER = 32'h001_00_000,
|
||||
parameter BUILD_DATE = 32'd602976000,
|
||||
parameter GIT_HASH = 32'h5f87c2e8,
|
||||
parameter RELEASE_INFO = 32'h00000000,
|
||||
|
||||
// Flash
|
||||
parameter logic [3:0] FLASH_SEG_COUNT = 2,
|
||||
parameter logic [3:0] FLASH_SEG_DEFAULT = 1,
|
||||
parameter logic [3:0] FLASH_SEG_FALLBACK = 0,
|
||||
parameter logic [31:0] FLASH_SEG0_SIZE = 32'h00000000,
|
||||
parameter FLASH_DATA_W = 4,
|
||||
parameter logic FLASH_DUAL_QSPI = 1'b1
|
||||
)
|
||||
(
|
||||
input wire logic clk,
|
||||
input wire logic rst,
|
||||
|
||||
/*
|
||||
* PCIe
|
||||
*/
|
||||
input wire logic cfg_ext_read_received,
|
||||
input wire logic cfg_ext_write_received,
|
||||
input wire logic [9:0] cfg_ext_register_number,
|
||||
input wire logic [7:0] cfg_ext_function_number,
|
||||
input wire logic [31:0] cfg_ext_write_data,
|
||||
input wire logic [3:0] cfg_ext_write_byte_enable,
|
||||
output wire logic [31:0] cfg_ext_read_data,
|
||||
output wire logic cfg_ext_read_data_valid,
|
||||
|
||||
/*
|
||||
* QSPI flash
|
||||
*/
|
||||
output wire logic fpga_boot,
|
||||
output wire logic qspi_clk,
|
||||
input wire logic [FLASH_DATA_W-1:0] qspi_0_dq_i,
|
||||
output wire logic [FLASH_DATA_W-1:0] qspi_0_dq_o,
|
||||
output wire logic [FLASH_DATA_W-1:0] qspi_0_dq_oe,
|
||||
output wire logic qspi_0_cs,
|
||||
input wire logic [FLASH_DATA_W-1:0] qspi_1_dq_i,
|
||||
output wire logic [FLASH_DATA_W-1:0] qspi_1_dq_o,
|
||||
output wire logic [FLASH_DATA_W-1:0] qspi_1_dq_oe,
|
||||
output wire logic qspi_1_cs
|
||||
);
|
||||
|
||||
taxi_apb_if #(
|
||||
.DATA_W(32),
|
||||
.ADDR_W(16)
|
||||
) vsec_apb();
|
||||
|
||||
taxi_pcie_us_vsec_apb #(
|
||||
.EXT_CAP_ID(EXT_CAP_ID),
|
||||
.EXT_CAP_VERSION(EXT_CAP_VERSION),
|
||||
.EXT_CAP_OFFSET(EXT_CAP_OFFSET),
|
||||
.EXT_CAP_NEXT(EXT_CAP_NEXT),
|
||||
.EXT_CAP_VSEC_ID(EXT_CAP_VSEC_ID),
|
||||
.EXT_CAP_VSEC_REV(EXT_CAP_VSEC_REV)
|
||||
)
|
||||
vsec_cap_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* APB interface for register space
|
||||
*/
|
||||
.m_apb(vsec_apb),
|
||||
|
||||
/*
|
||||
* Interface to Ultrascale PCIe IP core
|
||||
*/
|
||||
.cfg_ext_read_received(cfg_ext_read_received),
|
||||
.cfg_ext_write_received(cfg_ext_write_received),
|
||||
.cfg_ext_register_number(cfg_ext_register_number),
|
||||
.cfg_ext_function_number(cfg_ext_function_number),
|
||||
.cfg_ext_write_data(cfg_ext_write_data),
|
||||
.cfg_ext_write_byte_enable(cfg_ext_write_byte_enable),
|
||||
.cfg_ext_read_data(cfg_ext_read_data),
|
||||
.cfg_ext_read_data_valid(cfg_ext_read_data_valid)
|
||||
);
|
||||
|
||||
logic vsec_apb_pready_reg = 1'b0;
|
||||
logic [31:0] vsec_apb_prdata_reg = '0;
|
||||
|
||||
logic fpga_boot_reg = 1'b0;
|
||||
|
||||
logic qspi_clk_reg = 1'b0;
|
||||
logic qspi_0_cs_reg = 1'b1;
|
||||
logic [FLASH_DATA_W-1:0] qspi_0_dq_o_reg = '0;
|
||||
logic [FLASH_DATA_W-1:0] qspi_0_dq_oe_reg = '0;
|
||||
logic qspi_1_cs_reg = 1'b1;
|
||||
logic [FLASH_DATA_W-1:0] qspi_1_dq_o_reg = '0;
|
||||
logic [FLASH_DATA_W-1:0] qspi_1_dq_oe_reg = '0;
|
||||
|
||||
assign vsec_apb.pready = vsec_apb_pready_reg;
|
||||
assign vsec_apb.prdata = vsec_apb_prdata_reg;
|
||||
assign vsec_apb.pslverr = 1'b0;
|
||||
assign vsec_apb.pruser = '0;
|
||||
assign vsec_apb.pbuser = '0;
|
||||
|
||||
assign fpga_boot = fpga_boot_reg;
|
||||
|
||||
assign qspi_clk = qspi_clk_reg;
|
||||
assign qspi_0_cs = qspi_0_cs_reg;
|
||||
assign qspi_0_dq_o = qspi_0_dq_o_reg;
|
||||
assign qspi_0_dq_oe = qspi_0_dq_oe_reg;
|
||||
assign qspi_1_cs = FLASH_DUAL_QSPI ? qspi_1_cs_reg : 1'b1;
|
||||
assign qspi_1_dq_o = FLASH_DUAL_QSPI ? qspi_1_dq_o_reg : '0;
|
||||
assign qspi_1_dq_oe = FLASH_DUAL_QSPI ? qspi_1_dq_oe_reg : '0;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
vsec_apb_pready_reg <= 1'b0;
|
||||
|
||||
if (vsec_apb.penable && vsec_apb.psel && !vsec_apb_pready_reg) begin
|
||||
vsec_apb_pready_reg <= 1'b1;
|
||||
vsec_apb_prdata_reg <= '0;
|
||||
|
||||
if (vsec_apb.pwrite) begin
|
||||
case (8'({vsec_apb.paddr >> 2, 2'b00}))
|
||||
// FW ID
|
||||
8'h0C: begin
|
||||
// FW ID: FPGA JTAG ID
|
||||
fpga_boot_reg <= vsec_apb.pwdata == 32'hFEE1DEAD;
|
||||
end
|
||||
// QSPI flash
|
||||
8'h4C: begin
|
||||
// SPI flash ctrl: format
|
||||
fpga_boot_reg <= vsec_apb.pwdata == 32'hFEE1DEAD;
|
||||
end
|
||||
8'h50: begin
|
||||
// SPI flash ctrl: control 0
|
||||
if (vsec_apb.pstrb[0]) begin
|
||||
qspi_0_dq_o_reg <= vsec_apb.pwdata[3:0];
|
||||
end
|
||||
if (vsec_apb.pstrb[1]) begin
|
||||
qspi_0_dq_oe_reg <= vsec_apb.pwdata[11:8];
|
||||
end
|
||||
if (vsec_apb.pstrb[2]) begin
|
||||
qspi_clk_reg <= vsec_apb.pwdata[16];
|
||||
qspi_0_cs_reg <= vsec_apb.pwdata[17];
|
||||
end
|
||||
end
|
||||
8'h54: begin
|
||||
// SPI flash ctrl: control 1
|
||||
if (FLASH_DUAL_QSPI) begin
|
||||
if (vsec_apb.pstrb[0]) begin
|
||||
qspi_1_dq_o_reg <= vsec_apb.pwdata[3:0];
|
||||
end
|
||||
if (vsec_apb.pstrb[1]) begin
|
||||
qspi_1_dq_oe_reg <= vsec_apb.pwdata[11:8];
|
||||
end
|
||||
if (vsec_apb.pstrb[2]) begin
|
||||
qspi_clk_reg <= vsec_apb.pwdata[16];
|
||||
qspi_1_cs_reg <= vsec_apb.pwdata[17];
|
||||
end
|
||||
end
|
||||
end
|
||||
default: begin end
|
||||
endcase
|
||||
end
|
||||
|
||||
case (8'({vsec_apb.paddr >> 2, 2'b00}))
|
||||
// FW ID
|
||||
8'h00: vsec_apb_prdata_reg <= 32'hffffffff; // FW ID: Type
|
||||
8'h04: vsec_apb_prdata_reg <= 32'h000_01_000; // FW ID: Version
|
||||
8'h08: vsec_apb_prdata_reg <= 32'h40; // FW ID: Next header
|
||||
8'h0C: vsec_apb_prdata_reg <= FPGA_ID; // FW ID: FPGA JTAG ID
|
||||
8'h10: vsec_apb_prdata_reg <= FW_ID; // FW ID: Firmware ID
|
||||
8'h14: vsec_apb_prdata_reg <= FW_VER; // FW ID: Firmware version
|
||||
8'h18: vsec_apb_prdata_reg <= BOARD_ID; // FW ID: Board ID
|
||||
8'h1C: vsec_apb_prdata_reg <= BOARD_VER; // FW ID: Board version
|
||||
8'h20: vsec_apb_prdata_reg <= BUILD_DATE; // FW ID: Build date
|
||||
8'h24: vsec_apb_prdata_reg <= GIT_HASH; // FW ID: Git commit hash
|
||||
8'h28: vsec_apb_prdata_reg <= RELEASE_INFO; // FW ID: Release info
|
||||
// QSPI flash
|
||||
8'h40: vsec_apb_prdata_reg <= 32'h0000C120; // SPI flash ctrl: Type
|
||||
8'h44: vsec_apb_prdata_reg <= 32'h000_01_000; // SPI flash ctrl: Version
|
||||
8'h48: vsec_apb_prdata_reg <= 0; // SPI flash ctrl: Next header
|
||||
8'h4C: begin
|
||||
// SPI flash ctrl: format
|
||||
vsec_apb_prdata_reg[3:0] <= FLASH_SEG_COUNT; // configuration
|
||||
vsec_apb_prdata_reg[7:4] <= FLASH_SEG_DEFAULT; // default segment
|
||||
vsec_apb_prdata_reg[11:8] <= FLASH_SEG_FALLBACK; // fallback segment
|
||||
vsec_apb_prdata_reg[31:12] <= 20'(FLASH_SEG0_SIZE >> 12); // first segment size
|
||||
end
|
||||
8'h50: begin
|
||||
// SPI flash ctrl: control 0
|
||||
vsec_apb_prdata_reg[3:0] <= qspi_0_dq_i;
|
||||
vsec_apb_prdata_reg[11:8] <= qspi_0_dq_oe;
|
||||
vsec_apb_prdata_reg[16] <= qspi_clk;
|
||||
vsec_apb_prdata_reg[17] <= qspi_0_cs;
|
||||
end
|
||||
8'h54: begin
|
||||
// SPI flash ctrl: control 1
|
||||
if (FLASH_DUAL_QSPI) begin
|
||||
vsec_apb_prdata_reg[3:0] <= qspi_1_dq_i;
|
||||
vsec_apb_prdata_reg[11:8] <= qspi_1_dq_oe;
|
||||
vsec_apb_prdata_reg[16] <= qspi_clk;
|
||||
vsec_apb_prdata_reg[17] <= qspi_1_cs;
|
||||
end
|
||||
end
|
||||
default: begin end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (rst) begin
|
||||
vsec_apb_pready_reg <= 1'b0;
|
||||
|
||||
fpga_boot_reg <= 1'b0;
|
||||
|
||||
qspi_clk_reg <= 1'b0;
|
||||
qspi_0_cs_reg <= 1'b1;
|
||||
qspi_0_dq_o_reg <= '0;
|
||||
qspi_0_dq_oe_reg <= '0;
|
||||
qspi_1_cs_reg <= 1'b1;
|
||||
qspi_1_dq_o_reg <= '0;
|
||||
qspi_1_dq_oe_reg <= '0;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
||||
@@ -506,6 +506,7 @@ struct reg_if *reg_if_open_vpd(int fd)
|
||||
{
|
||||
char buf[32];
|
||||
int offset;
|
||||
bool found = false;
|
||||
|
||||
struct reg_if *reg = calloc(sizeof(struct reg_if), 1);
|
||||
|
||||
@@ -530,14 +531,98 @@ struct reg_if *reg_if_open_vpd(int fd)
|
||||
while (offset > 0) {
|
||||
pread(fd, buf, 2, offset);
|
||||
|
||||
if (buf[0] == PCI_CAP_ID_VPD)
|
||||
if (buf[0] == PCI_CAP_ID_VPD) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
offset = buf[1] & 0xfc;
|
||||
}
|
||||
|
||||
if (!offset || buf[0] != PCI_CAP_ID_VPD) {
|
||||
perror("Failed to locate VPD capability");
|
||||
if (!found) {
|
||||
reg_if_close(reg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
priv->fd = fd;
|
||||
priv->offset = offset;
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
struct vsec_reg_priv {
|
||||
int fd;
|
||||
int offset;
|
||||
};
|
||||
|
||||
static int reg_if_vsec_read32(const struct reg_if *reg, size_t offset, uint32_t *value)
|
||||
{
|
||||
const struct vsec_reg_priv *priv = reg->priv;
|
||||
uint32_t offs = offset & 0x7fffffff; // clear F
|
||||
pwrite(priv->fd, &offs, 4, priv->offset+0x08);
|
||||
pread(priv->fd, value, 4, priv->offset+0x0c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int reg_if_vsec_write32(const struct reg_if *reg, size_t offset, uint32_t value)
|
||||
{
|
||||
const struct vsec_reg_priv *priv = reg->priv;
|
||||
uint32_t offs = offset | 0x80000000; // set F
|
||||
pwrite(priv->fd, &value, 4, priv->offset+0x0c);
|
||||
pwrite(priv->fd, &offs, 4, priv->offset+0x08);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void reg_if_vsec_close(const struct reg_if *reg)
|
||||
{
|
||||
free(reg->priv);
|
||||
}
|
||||
|
||||
static const struct reg_if_ops reg_if_vsec_ops = {
|
||||
.read32 = reg_if_vsec_read32,
|
||||
.write32 = reg_if_vsec_write32,
|
||||
.close = reg_if_vsec_close,
|
||||
};
|
||||
|
||||
struct reg_if *reg_if_open_vsec(int fd)
|
||||
{
|
||||
uint32_t cap_hdr, vsec_hdr;
|
||||
int offset;
|
||||
bool found = false;
|
||||
|
||||
struct reg_if *reg = calloc(sizeof(struct reg_if), 1);
|
||||
|
||||
if (!reg)
|
||||
return NULL;
|
||||
|
||||
struct vsec_reg_priv *priv = calloc(sizeof(struct vsec_reg_priv), 1);
|
||||
|
||||
if (!priv) {
|
||||
free(reg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
reg->priv = priv;
|
||||
reg->ops = ®_if_vsec_ops;
|
||||
|
||||
// find VSEC extended capability (ID 0x000b, VSEC ID 0x00db)
|
||||
offset = 0x100;
|
||||
|
||||
while (offset > 0) {
|
||||
pread(fd, &cap_hdr, 4, offset);
|
||||
|
||||
if ((cap_hdr & 0xfffff) == 0x1000b) {
|
||||
pread(fd, &vsec_hdr, 4, offset+4);
|
||||
if ((vsec_hdr & 0xfffff) == 0x100db) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
offset = cap_hdr >> 20;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
reg_if_close(reg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -554,7 +639,7 @@ int main(int argc, char *argv[])
|
||||
int opt;
|
||||
int ret = 0;
|
||||
|
||||
struct reg_if *vpd_regs;
|
||||
struct reg_if *ctrl_regs;
|
||||
|
||||
char dev_name[32] = "";
|
||||
char *read_file_name = NULL;
|
||||
@@ -683,9 +768,12 @@ int main(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
vpd_regs = reg_if_open_vpd(config_fd);
|
||||
if (!vpd_regs) {
|
||||
perror("Failed to initialize VPD capability");
|
||||
if ((ctrl_regs = reg_if_open_vsec(config_fd))) {
|
||||
// found VSEC
|
||||
} else if ((ctrl_regs = reg_if_open_vpd(config_fd))) {
|
||||
// found VPD
|
||||
} else {
|
||||
fprintf(stderr, "Failed to locate capability structure\n");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
@@ -699,7 +787,7 @@ int main(int argc, char *argv[])
|
||||
printf("PCIe ID (device): %s\n", strrchr(pci_device_path, '/')+1);
|
||||
printf("PCIe ID (upstream port): %s\n", strrchr(pci_port_path, '/')+1);
|
||||
|
||||
rb_list = enumerate_reg_block_list(vpd_regs, 0x4000, 0, 0x4000);
|
||||
rb_list = enumerate_reg_block_list(ctrl_regs, 0x4000, 0, 0x4000);
|
||||
|
||||
printf("Register blocks:\n");
|
||||
for (struct reg_block *rb = rb_list; rb->regs; rb++)
|
||||
@@ -1422,8 +1510,8 @@ skip_flash:
|
||||
reg_if_write32(fw_id_rb->regs, 0x0C, 0xFEE1DEAD);
|
||||
|
||||
// disconnect
|
||||
reg_if_close(vpd_regs);
|
||||
vpd_regs = NULL;
|
||||
reg_if_close(ctrl_regs);
|
||||
ctrl_regs = NULL;
|
||||
close(config_fd);
|
||||
}
|
||||
|
||||
@@ -1484,7 +1572,7 @@ err:
|
||||
flash_release(pri_flash);
|
||||
flash_release(sec_flash);
|
||||
|
||||
reg_if_close(vpd_regs);
|
||||
reg_if_close(ctrl_regs);
|
||||
close(config_fd);
|
||||
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user