From 2af90b41963d474f7268d8eadad22e3ff4578d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Mon, 10 Jun 2024 23:37:46 +0100 Subject: [PATCH 1/8] chore(submodules): update submodules --- submodules/ETHERNET | 2 +- submodules/IOBSOC | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/submodules/ETHERNET b/submodules/ETHERNET index e706057f..70934141 160000 --- a/submodules/ETHERNET +++ b/submodules/ETHERNET @@ -1 +1 @@ -Subproject commit e706057f08159c9ac770f2e8d8ee7028e5328503 +Subproject commit 70934141ac575c5d03f71ec4ca99670924ed753f diff --git a/submodules/IOBSOC b/submodules/IOBSOC index 82ff8ee5..94ec67a8 160000 --- a/submodules/IOBSOC +++ b/submodules/IOBSOC @@ -1 +1 @@ -Subproject commit 82ff8ee56271c4b8ce316189483a6def07c3f575 +Subproject commit 94ec67a89d6e1f637446fa7b7fccacfd33af13bc From 03b1ee4fe3cc5031ea9d8b4fcd598f096058540d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Wed, 12 Jun 2024 06:02:12 +0100 Subject: [PATCH 2/8] WIP(verilator): Fix verilator testbench using new iob_tasks. WIP drive ethernet in verilator testbench. --- hardware/simulation/sim_build.mk | 2 ++ submodules/ETHERNET | 2 +- submodules/IOBSOC | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hardware/simulation/sim_build.mk b/hardware/simulation/sim_build.mk index 9760d0d0..a27848b7 100644 --- a/hardware/simulation/sim_build.mk +++ b/hardware/simulation/sim_build.mk @@ -9,6 +9,8 @@ VTOP:=iob_soc_opencryptolinux_tb # SOURCES ifeq ($(SIMULATOR),verilator) +VSRC+=./src/iob_tasks.cpp ./src/iob_eth_swreg_emb_verilator.c + # verilator top module VTOP:=iob_soc_opencryptolinux_sim_wrapper diff --git a/submodules/ETHERNET b/submodules/ETHERNET index 70934141..9158604d 160000 --- a/submodules/ETHERNET +++ b/submodules/ETHERNET @@ -1 +1 @@ -Subproject commit 70934141ac575c5d03f71ec4ca99670924ed753f +Subproject commit 9158604d5a6b5e844a39208341e3ff3b77f219c2 diff --git a/submodules/IOBSOC b/submodules/IOBSOC index 94ec67a8..ddbd73f8 160000 --- a/submodules/IOBSOC +++ b/submodules/IOBSOC @@ -1 +1 @@ -Subproject commit 94ec67a89d6e1f637446fa7b7fccacfd33af13bc +Subproject commit ddbd73f8a26562910f765105c73fab583496be83 From 5dd6f785018ea0c2ff082869f8478eef3fe2b597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Sat, 15 Jun 2024 02:35:58 +0100 Subject: [PATCH 3/8] fix(eth): Fix verilator simulation with ethernet. --- hardware/simulation/sim_build.mk | 6 +- .../src/iob_soc_opencryptolinux_sim_wrapper.v | 273 +++++++++--------- submodules/ETHERNET | 2 +- submodules/IOBSOC | 2 +- 4 files changed, 138 insertions(+), 145 deletions(-) diff --git a/hardware/simulation/sim_build.mk b/hardware/simulation/sim_build.mk index a27848b7..689c616f 100644 --- a/hardware/simulation/sim_build.mk +++ b/hardware/simulation/sim_build.mk @@ -9,7 +9,11 @@ VTOP:=iob_soc_opencryptolinux_tb # SOURCES ifeq ($(SIMULATOR),verilator) -VSRC+=./src/iob_tasks.cpp ./src/iob_eth_swreg_emb_verilator.c +VSRC+=./src/iob_tasks.cpp + +ifeq ($(USE_ETHERNET),1) +VSRC+=./src/iob_eth_swreg_emb_verilator.c ./src/iob_eth_driver_tb.cpp +endif # verilator top module VTOP:=iob_soc_opencryptolinux_sim_wrapper diff --git a/hardware/simulation/src/iob_soc_opencryptolinux_sim_wrapper.v b/hardware/simulation/src/iob_soc_opencryptolinux_sim_wrapper.v index a2f1089f..a7d810db 100644 --- a/hardware/simulation/src/iob_soc_opencryptolinux_sim_wrapper.v +++ b/hardware/simulation/src/iob_soc_opencryptolinux_sim_wrapper.v @@ -13,101 +13,91 @@ `endif module iob_soc_opencryptolinux_sim_wrapper ( -`include "clk_rst_s_port.vs" - output trap_o, + `include "clk_rst_s_port.vs" + output trap_o, `ifdef IOB_SOC_OPENCRYPTOLINUX_USE_ETHERNET - // Ethernet for testbench - input ethernet_valid_i, - input [`IOB_ETH_SWREG_ADDR_W-1:0] ethernet_addr_i, - input [`IOB_SOC_OPENCRYPTOLINUX_DATA_W-1:0] ethernet_wdata_i, - input [3:0] ethernet_wstrb_i, - output [`IOB_SOC_OPENCRYPTOLINUX_DATA_W-1:0] ethernet_rdata_o, - output ethernet_ready_o, - output ethernet_rvalid_o, + // Ethernet for testbench + input ethernet_valid_i, + input [ `IOB_ETH_SWREG_ADDR_W-1:0] ethernet_addr_i, + input [`IOB_SOC_OPENCRYPTOLINUX_DATA_W-1:0] ethernet_wdata_i, + input [ 3:0] ethernet_wstrb_i, + output [`IOB_SOC_OPENCRYPTOLINUX_DATA_W-1:0] ethernet_rdata_o, + output ethernet_ready_o, + output ethernet_rvalid_o, `endif - // UART for testbench - input uart_valid_i, - input [`IOB_UART_SWREG_ADDR_W-1:0] uart_addr_i, - input [`IOB_SOC_OPENCRYPTOLINUX_DATA_W-1:0] uart_wdata_i, - input [3:0] uart_wstrb_i, - output [`IOB_SOC_OPENCRYPTOLINUX_DATA_W-1:0] uart_rdata_o, - output uart_ready_o, - output uart_rvalid_o + // UART for testbench + input uart_valid_i, + input [ `IOB_UART_SWREG_ADDR_W-1:0] uart_addr_i, + input [`IOB_SOC_OPENCRYPTOLINUX_DATA_W-1:0] uart_wdata_i, + input [ 3:0] uart_wstrb_i, + output [`IOB_SOC_OPENCRYPTOLINUX_DATA_W-1:0] uart_rdata_o, + output uart_ready_o, + output uart_rvalid_o ); - localparam AXI_ID_W = 4; - localparam AXI_LEN_W = 8; - localparam AXI_ADDR_W = `DDR_ADDR_W; - localparam AXI_DATA_W = `DDR_DATA_W; + localparam AXI_ID_W = 4; + localparam AXI_LEN_W = 8; + localparam AXI_ADDR_W = `DDR_ADDR_W; + localparam AXI_DATA_W = `DDR_DATA_W; - `include "iob_soc_opencryptolinux_wrapper_pwires.vs" + `include "iob_soc_opencryptolinux_wrapper_pwires.vs" - ///////////////////////////////////////////// - // TEST PROCEDURE - // - initial begin -`ifdef VCD - $dumpfile("uut.vcd"); - $dumpvars(); -`endif - end - - // - // INSTANTIATE COMPONENTS - // + // + // INSTANTIATE COMPONENTS + // - // - // IOb-SoC-OpenCryptoLinux (may also include Unit Under Test) - // - iob_soc_opencryptolinux #( + // + // IOb-SoC-OpenCryptoLinux (may also include Unit Under Test) + // + iob_soc_opencryptolinux #( .AXI_ID_W (AXI_ID_W), .AXI_LEN_W (AXI_LEN_W), .AXI_ADDR_W(AXI_ADDR_W), .AXI_DATA_W(AXI_DATA_W) - ) soc0 ( + ) soc0 ( `include "iob_soc_opencryptolinux_pportmaps.vs" .clk_i (clk_i), .cke_i (1'b1), .arst_i(arst_i), .trap_o(trap_o) - ); + ); - // interconnect clk and arst - wire clk_interconnect; - wire arst_interconnect; - assign clk_interconnect = clk_i; - assign arst_interconnect = arst_i; + // interconnect clk and arst + wire clk_interconnect; + wire arst_interconnect; + assign clk_interconnect = clk_i; + assign arst_interconnect = arst_i; - `include "iob_soc_opencryptolinux_interconnect.vs" + `include "iob_soc_opencryptolinux_interconnect.vs" - //instantiate the axi memory - //IOb-SoC-OpenCryptoLinux and SUT access the same memory. - axi_ram #( + //instantiate the axi memory + //IOb-SoC-OpenCryptoLinux and SUT access the same memory. + axi_ram #( `ifdef IOB_SOC_OPENCRYPTOLINUX_INIT_MEM .FILE ("init_ddr_contents"), //This file contains firmware for both systems `endif .ID_WIDTH (AXI_ID_W), .DATA_WIDTH(AXI_DATA_W), .ADDR_WIDTH(AXI_ADDR_W) - ) ddr_model_mem ( + ) ddr_model_mem ( `include "iob_memory_axi_s_portmap.vs" .clk_i(clk_i), .rst_i(arst_i) - ); + ); - //Manually added testbench uart core. RS232 pins attached to the same pins - //of the iob_soc UART0 instance to communicate with it - // The interface of iob_soc UART0 is assumed to be the first portmapped interface (UART_*) - iob_uart uart_tb ( + //Manually added testbench uart core. RS232 pins attached to the same pins + //of the iob_soc UART0 instance to communicate with it + // The interface of iob_soc UART0 is assumed to be the first portmapped interface (UART_*) + iob_uart uart_tb ( .clk_i (clk_i), .cke_i (1'b1), .arst_i(arst_i), - .iob_valid_i(uart_valid_i), + .iob_valid_i (uart_valid_i), .iob_addr_i (uart_addr_i), .iob_wdata_i (uart_wdata_i), .iob_wstrb_i (uart_wstrb_i), @@ -119,94 +109,93 @@ module iob_soc_opencryptolinux_sim_wrapper ( .rxd_i(uart_txd_o), .rts_o(uart_cts_i), .cts_i(uart_rts_o) - ); + ); - //Ethernet + //Ethernet `ifdef IOB_SOC_OPENCRYPTOLINUX_USE_ETHERNET - //ethernet clock: 4x slower than system clock - reg [1:0] eth_cnt = 2'b0; - reg eth_clk; - - always @(posedge clk_i) begin - eth_cnt <= eth_cnt + 1'b1; - eth_clk <= eth_cnt[1]; - end - - // Ethernet Interface signals - assign ETH0_MRxClk = eth_clk; - assign ETH0_MTxClk = eth_clk; - - //Manually added testbench ethernet core. MII pins attached to the same pins - //of the iob_soc ETH0 instance to communicate with it - // The interface of iob_soc ETH0 is assumed to be the first portmapped interface (ETH_*) - iob_eth - #( - .AXI_ID_W(AXI_ID_W), + //ethernet clock: 4x slower than system clock + reg [1:0] eth_cnt = 2'b0; + reg eth_clk; + + always @(posedge clk_i) begin + eth_cnt <= eth_cnt + 1'b1; + eth_clk <= eth_cnt[1]; + end + + // Ethernet Interface signals + assign ETH0_MRxClk = eth_clk; + assign ETH0_MTxClk = eth_clk; + + //Manually added testbench ethernet core. MII pins attached to the same pins + //of the iob_soc ETH0 instance to communicate with it + // The interface of iob_soc ETH0 is assumed to be the first portmapped interface (ETH_*) + iob_eth #( + .AXI_ID_W (AXI_ID_W), .AXI_ADDR_W(AXI_ADDR_W), .AXI_DATA_W(AXI_DATA_W), - .AXI_LEN_W(AXI_LEN_W) - ) eth_tb ( - .inta_o(), - .MTxClk(eth_clk), - .MTxD(ETH0_MRxD), - .MTxEn(ETH0_MRxDv), - .MTxErr(ETH0_MRxErr), - .MRxClk(eth_clk), - .MRxDv(ETH0_MTxEn), - .MRxD(ETH0_MTxD), - .MRxErr(ETH0_MTxErr), - .MColl(1'b0), - .MCrS(1'b0), - .MDC(), - .MDIO(), - .iob_valid_i(ethernet_valid_i), - .iob_addr_i (ethernet_addr_i), - .iob_wdata_i (ethernet_wdata_i), - .iob_wstrb_i (ethernet_wstrb_i), - .iob_rvalid_o(ethernet_rvalid_o), - .iob_rdata_o (ethernet_rdata_o), - .iob_ready_o (ethernet_ready_o), - .axi_awid_o (), - .axi_awaddr_o (), - .axi_awlen_o (), - .axi_awsize_o (), - .axi_awburst_o (), - .axi_awlock_o (), - .axi_awcache_o (), - .axi_awprot_o (), - .axi_awqos_o (), - .axi_awvalid_o (), - .axi_awready_i (1'b0), - .axi_wdata_o (), - .axi_wstrb_o (), - .axi_wlast_o (), - .axi_wvalid_o (), - .axi_wready_i (1'b0), - .axi_bid_i ({AXI_ID_W{1'b0}}), - .axi_bresp_i (2'b0), - .axi_bvalid_i (1'b0), - .axi_bready_o (), - .axi_arid_o (), - .axi_araddr_o (), - .axi_arlen_o (), - .axi_arsize_o (), - .axi_arburst_o (), - .axi_arlock_o (), - .axi_arcache_o (), - .axi_arprot_o (), - .axi_arqos_o (), - .axi_arvalid_o (), - .axi_arready_i (1'b0), - .axi_rid_i ({AXI_ID_W{1'b0}}), - .axi_rdata_i ({AXI_DATA_W{1'b0}}), - .axi_rresp_i (2'b0), - .axi_rlast_i (1'b0), - .axi_rvalid_i (1'b0), - .axi_rready_o (), - .clk_i(clk_i), - .arst_i(arst_i), - .cke_i(1'b1) - ); + .AXI_LEN_W (AXI_LEN_W) + ) eth_tb ( + .inta_o (), + .MTxClk (eth_clk), + .MTxD (ETH0_MRxD), + .MTxEn (ETH0_MRxDv), + .MTxErr (ETH0_MRxErr), + .MRxClk (eth_clk), + .MRxDv (ETH0_MTxEn), + .MRxD (ETH0_MTxD), + .MRxErr (ETH0_MTxErr), + .MColl (1'b0), + .MCrS (1'b0), + .MDC (), + .MDIO (), + .iob_valid_i (ethernet_valid_i), + .iob_addr_i (ethernet_addr_i), + .iob_wdata_i (ethernet_wdata_i), + .iob_wstrb_i (ethernet_wstrb_i), + .iob_rvalid_o (ethernet_rvalid_o), + .iob_rdata_o (ethernet_rdata_o), + .iob_ready_o (ethernet_ready_o), + .axi_awid_o (), + .axi_awaddr_o (), + .axi_awlen_o (), + .axi_awsize_o (), + .axi_awburst_o(), + .axi_awlock_o (), + .axi_awcache_o(), + .axi_awprot_o (), + .axi_awqos_o (), + .axi_awvalid_o(), + .axi_awready_i(1'b0), + .axi_wdata_o (), + .axi_wstrb_o (), + .axi_wlast_o (), + .axi_wvalid_o (), + .axi_wready_i (1'b0), + .axi_bid_i ({AXI_ID_W{1'b0}}), + .axi_bresp_i (2'b0), + .axi_bvalid_i (1'b0), + .axi_bready_o (), + .axi_arid_o (), + .axi_araddr_o (), + .axi_arlen_o (), + .axi_arsize_o (), + .axi_arburst_o(), + .axi_arlock_o (), + .axi_arcache_o(), + .axi_arprot_o (), + .axi_arqos_o (), + .axi_arvalid_o(), + .axi_arready_i(1'b0), + .axi_rid_i ({AXI_ID_W{1'b0}}), + .axi_rdata_i ({AXI_DATA_W{1'b0}}), + .axi_rresp_i (2'b0), + .axi_rlast_i (1'b0), + .axi_rvalid_i (1'b0), + .axi_rready_o (), + .clk_i (clk_i), + .arst_i (arst_i), + .cke_i (1'b1) + ); `endif endmodule diff --git a/submodules/ETHERNET b/submodules/ETHERNET index 9158604d..b7dfbee9 160000 --- a/submodules/ETHERNET +++ b/submodules/ETHERNET @@ -1 +1 @@ -Subproject commit 9158604d5a6b5e844a39208341e3ff3b77f219c2 +Subproject commit b7dfbee96ad102bd34af6dd5d21b3b3531a8dde6 diff --git a/submodules/IOBSOC b/submodules/IOBSOC index ddbd73f8..62876217 160000 --- a/submodules/IOBSOC +++ b/submodules/IOBSOC @@ -1 +1 @@ -Subproject commit ddbd73f8a26562910f765105c73fab583496be83 +Subproject commit 62876217f1037e930407908ea78cfce7e881fd11 From 994a4662bae6b8b5b5543de765c9539394a6bc45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Sun, 16 Jun 2024 22:46:53 +0100 Subject: [PATCH 4/8] chore(submodules): Update submodule --- submodules/ETHERNET | 2 +- submodules/IOBSOC | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/submodules/ETHERNET b/submodules/ETHERNET index b7dfbee9..109f2845 160000 --- a/submodules/ETHERNET +++ b/submodules/ETHERNET @@ -1 +1 @@ -Subproject commit b7dfbee96ad102bd34af6dd5d21b3b3531a8dde6 +Subproject commit 109f2845adc48baa26c263e4edcf5d9f24054a4d diff --git a/submodules/IOBSOC b/submodules/IOBSOC index 62876217..06aa968c 160000 --- a/submodules/IOBSOC +++ b/submodules/IOBSOC @@ -1 +1 @@ -Subproject commit 62876217f1037e930407908ea78cfce7e881fd11 +Subproject commit 06aa968c53942cdacb3f310135da6c2d2de4b7da From 07a998215ecfc651bbd8ca864c3e9327434aad4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Tue, 18 Jun 2024 04:00:53 +0100 Subject: [PATCH 5/8] fix(verilator): Verilator simulation works using ethernet. --- .github/workflows/ci.yml | 32 ++++++++++----------- software/src/iob_soc_opencryptolinux_boot.c | 1 + submodules/ETHERNET | 2 +- submodules/IOBSOC | 2 +- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff513498..47f55159 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,22 +66,22 @@ jobs: - name: icarus test run: nix-shell --run "make -C ../iob_soc_o* sim-run" - # verilator-baremetal: - # runs-on: self-hosted - # timeout-minutes: 90 - # # run even if previous job failed - # if: ${{ !cancelled() }} - # - # steps: - # - uses: actions/checkout@v4 - # with: - # submodules: 'recursive' - # - name: clean - # run: nix-shell --run "make clean" - # - name: setup no_init_mem ext_mem - # run: nix-shell --run "make setup INIT_MEM=0 RUN_LINUX=0" - # - name: verilator test - # run: nix-shell --run "make -C ../iob_soc_o* sim-run SIMULATOR=verilator" + verilator-baremetal: + runs-on: self-hosted + timeout-minutes: 90 + # run even if previous job failed + if: ${{ !cancelled() }} + + steps: + - uses: actions/checkout@v4 + with: + submodules: 'recursive' + - name: clean + run: nix-shell --run "make clean" + - name: setup no_init_mem ext_mem + run: nix-shell --run "make setup INIT_MEM=0 RUN_LINUX=0" + - name: verilator test + run: nix-shell --run "make -C ../iob_soc_o* sim-run SIMULATOR=verilator" cyclonev: diff --git a/software/src/iob_soc_opencryptolinux_boot.c b/software/src/iob_soc_opencryptolinux_boot.c index 2b1fd1ad..7710b3dc 100644 --- a/software/src/iob_soc_opencryptolinux_boot.c +++ b/software/src/iob_soc_opencryptolinux_boot.c @@ -24,6 +24,7 @@ // NOTE: These functions are not compatible with malloc() and free(). // These are specifically made for use with the current iob-eth.c drivers. // (These assume that there is only one block allocated at a time) +// It allocates a block with required size at the end of the external memory region. static void *mem_alloc(size_t size) { return (void *)(EXT_MEM | (1 << IOB_SOC_OPENCRYPTOLINUX_MEM_ADDR_W)) - size; } diff --git a/submodules/ETHERNET b/submodules/ETHERNET index b8f7e9f5..c9e4c8ad 160000 --- a/submodules/ETHERNET +++ b/submodules/ETHERNET @@ -1 +1 @@ -Subproject commit b8f7e9f59a7a7df75f873d93b15c7292c396b7ef +Subproject commit c9e4c8ad5b21e59ed21584477b440d459abddcb0 diff --git a/submodules/IOBSOC b/submodules/IOBSOC index fc300934..e8ef6c03 160000 --- a/submodules/IOBSOC +++ b/submodules/IOBSOC @@ -1 +1 @@ -Subproject commit fc300934833412815136de87cc78df9484dc4740 +Subproject commit e8ef6c03b91da3abf804b29b9645da1cac2fbbc1 From 8a03c428ea3c7009b3bc30387e2d93b9a911574f Mon Sep 17 00:00:00 2001 From: PMiranda Date: Wed, 19 Jun 2024 10:53:45 +0100 Subject: [PATCH 6/8] update(IOBSOC): update submodule --- submodules/IOBSOC | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/IOBSOC b/submodules/IOBSOC index c593b469..e877b4df 160000 --- a/submodules/IOBSOC +++ b/submodules/IOBSOC @@ -1 +1 @@ -Subproject commit c593b46904972e46506d7db7031fc3a1b3dec06d +Subproject commit e877b4dfa9be09b749bbf041a752a5055cee9a2a From 1cba0803da11e5cf5336eeba16b943924b58669f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Wed, 19 Jun 2024 15:55:28 +0100 Subject: [PATCH 7/8] chore(submodules): update submodules --- submodules/ETHERNET | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/ETHERNET b/submodules/ETHERNET index c9e4c8ad..a0f9fedd 160000 --- a/submodules/ETHERNET +++ b/submodules/ETHERNET @@ -1 +1 @@ -Subproject commit c9e4c8ad5b21e59ed21584477b440d459abddcb0 +Subproject commit a0f9feddddcb31897468bd17f81478a16b916637 From d8ce99ac0c857732eb857399fed0099334c3c56f Mon Sep 17 00:00:00 2001 From: PMiranda Date: Wed, 19 Jun 2024 16:18:48 +0100 Subject: [PATCH 8/8] feat(SPI): SPI linux drivers, add tutorial - update SPI submodule with linux drivers - initial draft for Tutorial do add device driver --- README.md | 170 +++++++++++++++++++++++++++++++++++++++++++++++++ submodules/SPI | 2 +- 2 files changed, 171 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 47a0e55e..14426a58 100644 --- a/README.md +++ b/README.md @@ -314,6 +314,176 @@ export PATH=$PATH:/path/to/riscv/bin The above command should be added to your `~/.bashrc` file so you do not have to type it on every session. +# Tutorial: Add New Device Driver +This tutorial presents the steps required to create simple linux character device drivers for a device and use them in OpenCryptoLinux. +The [IOb-SPI](https://github.com/IObundle/iob-spi) device is used as an example. +To follow this tutorial, clone the [iob-linux](https://github.com/IObundle/iob-linux) repository. + +1. Create device drivers: on the device repository create a `software/linux` directory with the following files: +```bash +software/ +├── linux +│   ├── drivers +│   │   ├── driver.mk +│   │   └── iob_spi_main.c +│   ├── iob_spi.dts +│   └── Readme.md +``` +1.1. `software/linux/drivers/driver.mk`: compilation makefile segment +```make +iob_spi_master-objs := iob_spi_main.o iob_class/iob_class_utils.o +``` +1.2. `software/linux/drivers/iob_spi_main.c`: main driver file, see [TODO: SPI commit] for full code snippet. +1.2.1. Rename the functions to the particular device +1.2.2. Update the `iob_spi_read()` function implementation according with the read registers of the device. SPI has the `FL_READY`, `FL_DATAOUT` and `VERSION` (implicit) read registers: +```C +static ssize_t iob_spi_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) { + // (...) + + /* read value from register */ + switch (*ppos) { + // Add one case for each Read software register + case IOB_SPI_MASTER_FL_READY_ADDR: + value = + iob_data_read_reg(iob_spi_data->regbase, IOB_SPI_MASTER_FL_READY_ADDR, + IOB_SPI_MASTER_FL_READY_W); + size = (IOB_SPI_MASTER_FL_READY_W >> 3); // bit to bytes + pr_info("[Driver] %s: Read FL_READY: 0x%x\n", IOB_SPI_MASTER_DRIVER_NAME, + value); + break; + case IOB_SPI_MASTER_FL_DATAOUT_ADDR: + value = + iob_data_read_reg(iob_spi_data->regbase, IOB_SPI_MASTER_FL_DATAOUT_ADDR, + IOB_SPI_MASTER_FL_DATAOUT_W); + size = (IOB_SPI_MASTER_FL_DATAOUT_W >> 3); // bit to bytes + pr_info("[Driver] %s: Read FL_DATAOUT: 0x%x\n", IOB_SPI_MASTER_DRIVER_NAME, + value); + break; + // NOTE: version software register is implicit and always added + case IOB_SPI_MASTER_VERSION_ADDR: + value = iob_data_read_reg(iob_spi_data->regbase, IOB_SPI_MASTER_VERSION_ADDR, + IOB_SPI_MASTER_VERSION_W); + size = (IOB_SPI_MASTER_VERSION_W >> 3); // bit to bytes + pr_info("[Driver] %s: Read version 0x%x\n", IOB_SPI_MASTER_DRIVER_NAME, value); + break; + default: + // invalid address - no bytes read + return 0; + } + + // (...) +} +``` +1.2.3. Update the `iob_spi_write()` function implementation according with the write registers of the device. SPI had the `FL_RESET`, `FL_DATAIN`, `FL_ADDRESS`, `FL_COMMAND`, `FL_COMMANDTP` and `FL_VALIDFLG`write registers: +```C +static ssize_t iob_spi_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { + // (...) + + switch (*ppos) { + case IOB_SPI_MASTER_FL_RESET_ADDR: + size = (IOB_SPI_MASTER_FL_RESET_W >> 3); // bit to bytes + if (read_user_data(buf, size, &value)) + return -EFAULT; + iob_data_write_reg(iob_spi_data->regbase, value, + IOB_SPI_MASTER_FL_RESET_ADDR, + IOB_SPI_MASTER_FL_RESET_W); + pr_info("[Driver] %s: FL_RESET iob_spi: 0x%x\n", + IOB_SPI_MASTER_DRIVER_NAME, value); + break; + case IOB_SPI_MASTER_FL_DATAIN_ADDR: + // FL_DATAIN access implementation + break; + case IOB_SPI_MASTER_FL_ADDRESS_ADDR: + // FL_ADDRESS access implementation + break; + case IOB_SPI_MASTER_FL_COMMAND_ADDR: + // FL_COMMAND access implementation + break; + case IOB_SPI_MASTER_FL_COMMANDTP_ADDR: + // FL_COMMANDTP access implementation + break; + case IOB_SPI_MASTER_FL_VALIDFLG_ADDR: + // FL_VALIDFLG access implementation + break; + default: + pr_info("[Driver] %s: Invalid write address 0x%x\n", IOB_SPI_MASTER_DRIVER_NAME, + (unsigned int)*ppos); + // invalid address - no bytes written + return 0; + } + + return count; +} +``` +1.2.4. Notice the string used in the `struct of_device_id`. This string must match the `compatible` field in the device tree to associate the hardware device with the correct driver. +```C +static const struct of_device_id of_iob_spi_match[] = { + {.compatible = "iobundle,spi0"}, + {}, +}; +``` +1.3. Generate `iob_spi_master.h` and `iob_spi_master_sysfs_multi.h` header files with the [`drivers.py`](https://github.com/IObundle/iob-linux/blob/main/scripts/drivers.py) script: +```bash +python3 .path/to/iob-linux/scripts/drivers.py iob_spi_master -o [output_dir] +``` +2. Update device tree with device node. The `compatible` string must match with the `compatible` field in the driver source: +``` +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* Copyright (c) 2024 IObundle */ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + model = "IOb-SoC, VexRiscv"; + compatible = "IOb-SoC, VexRiscv"; + // CPU + // Memory + // Choosen + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "iobundle,iob-soc", "simple-bus"; + ranges; + + // Other SOC peripherals go here + + // Add this Node to device tree + SPI0: spi@/*SPI0_ADDR_MACRO*/ { + compatible = "iobundle,spi0"; + reg = <0x/*SPI0_ADDR_MACRO*/ 0x100>; + }; + + }; +}; +``` +3. Compile driver module and add to rootfs. +3.1. Copy device driver files to [`iob-linux/software/drivers`](https://github.com/IObundle/iob-linux/tree/main/software/drivers) +3.2. Run `make all` target. Note that linux driver module compilation requires an already built linux kernel: +```bash +cd ./path/to/iob-linux/software/drivers +make all +``` +3.3. Add module files to buildroot: +```bash +# copy module files to directory used to build rootfs +cp ./path/to/iob-linux/software/drivers $OS_SOFTWARE_DIR +# change directory to iob-linux +cd ./path/to/iob-linux +# re-build buildroot +make build-buildroot OS_SOFTWARE_DIR=$OS_SOFTWARE_DIR +``` +4. Load module in linux. After booting into linux, use the `insmod` command to load the new driver modules: +```bash +# inside linux console +insmod ./path/to/driver.ko +# iob-spi example: +insmod /drivers/iob_spi_master.ko +``` + # Acknowledgement The [OpenCryptoLinux](https://nlnet.nl/project/OpenCryptoLinux/) project was funded through the NGI Assure Fund, a fund established by NLnet with financial support from the European Commission's Next Generation Internet programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 957073. diff --git a/submodules/SPI b/submodules/SPI index ad98d928..dce9c93f 160000 --- a/submodules/SPI +++ b/submodules/SPI @@ -1 +1 @@ -Subproject commit ad98d928485cff1421ce069a916a34a87e5f7d97 +Subproject commit dce9c93f1202da96d3570f88e31b9409afb43419