I have instantiated a uart on my FPGA(de0-nano-soc) and connected it to the hps2fpga bridge at address 0x000004000. Now I want to be able to use this as a serial device from linux.
When I generate the dts file via SoCEDS from intel I get the following record in it:
sopc0: sopc@0 {
device_type = "soc";
ranges;
#address-cells = <1>;
#size-cells = <1>;
compatible = "ALTR,avalon", "simple-bus";
bus-frequency = <0>;
hps_bridges: bridge@0xc0000000 {
compatible = "altr,bridge-17.1", "simple-bus";
reg = <0xc0000000 0x20000000>,
<0xff200000 0x00200000>;
reg-names = "axi_h2f", "axi_h2f_lw";
#address-cells = <2>;
#size-cells = <1>;
ranges = <0x00000000 0x00004000 0xc0004000 0x00000020>,
<0x00000000 0x00000000 0xc0000000 0x00002180>,
<0x00000001 0x00000000 0xff200000 0x00002180>;
uart0: serial@0x000004000 {
compatible = "altr,uart-17.1", "altr,uart-1.0";
reg = <0x00000000 0x00004000 0x00000020>;
interrupt-parent = <&hps_arm_gic_0>;
interrupts = <0 40 4>;
clock-frequency = <50000000>;
current-speed = <19200>;
};
...
But this dts file in general is different then the one included in the linux kernel. If I just add the hps_bridges
node and modify the interrupt-parent
of uart0
to point to the correct phandle in my own decompiled dtb and recompile I do see my serial device. However when I read or write to the device file the OS crashes with the following messages:
[ 84.043042] Internal error: : 406 [#1] SMP ARM
[ 84.047484] Modules linked in: xt_policy authenc echainiv twofish_generic twofish_common serpent_generic blowfish_generic blowfish_common cast5_generic cast_common ux500_cryp des_generic algif_skcipher camellia_generic xcbc sha512_generic sha512_arm ux500_hash sha1_generic sha1_arm_neon sha1_arm md5 md4 algif_hash af_alg xfrm_user xfrm4_tunnel ipcomp xfrm_ipcomp esp4 ah4 wireguard(O) af_key xfrm_algo fpgacfg(O) cfg80211 dtbocfg(O) configfs 8021q zptty(O) udmabuf(O) nls_iso8859_1 nls_cp437 phy_generic altera_uart socfpga fpga_mgr uio_pdrv_genirq uio iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ip6t_rpfilter ipt_rpfilter ip6table_raw iptable_raw xt_pkttype nf_log_ipv6 nf_log_ipv4 nf_log_common xt_LOG xt_tcpudp ip6table_filter ip6_tables iptable_filter tun ip_tables x_tables dm_mod
[ 84.123982] CPU: 1 PID: 1747 Comm: screen Tainted: G O 4.9.142 #1-NixOS
[ 84.131712] Hardware name: Altera SOCFPGA
[ 84.135717] task: ec630000 task.stack: ec690000
[ 84.140249] PC is at altera_uart_get_mctrl+0x2c/0x48 [altera_uart]
[ 84.146423] LR is at uart_tiocmget+0x5c/0x94
[ 84.150689] pc : [<bf163060>] lr : [<c08926d8>] psr: 600f0093
[ 84.150689] sp : ec691e48 ip : ec691e58 fp : ec691e54
[ 84.162136] r10: 00000000 r9 : ed907a00 r8 : bea13274
[ 84.167350] r7 : 00000006 r6 : edc44094 r5 : 00000006 r4 : bf165280
[ 84.173859] r3 : f0cde008 r2 : 00000000 r1 : 00000008 r0 : bf165280
[ 84.180370] Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment none
[ 84.187578] Control: 10c5387d Table: 2c5f004a DAC: 00000051
[ 84.193310] Process screen (pid: 1747, stack limit = 0xec690220)
[ 84.199302] Stack: (0xec691e48 to 0xec692000)
[ 84.203657] 1e40: ec691e74 ec691e58 c08926d8 bf163040 00005415 ed907a00
[ 84.211821] 1e60: edbb6cc0 00000006 ec691efc ec691e78 c0876940 c0892688 ec691ea4 00000006
[ 84.219984] 1e80: ec691ea8 ec691f5c 00000001 c0309a24 ec690000 c04c8e58 ec691f4c ec691ea8
[ 84.228149] 1ea0: c04c8e58 c04c23a0 ee995b10 ee45fcc0 a8ba57f7 00000006 ee9bb015 ec691ec8
[ 84.236313] 1ec0: 00000000 c04b6a8c eeb981d0 00000101 00000002 bea13274 eeb981d0 edbb6cc0
[ 84.244476] 1ee0: 00000006 bea13274 ec690000 00000036 ec691f7c ec691f00 c04cb604 c0876300
[ 84.252641] 1f00: ec691f3c c04c8014 00000001 edbb6cc8 00000020 ee9bb000 edbb6cc0 ee9bb000
[ 84.260804] 1f20: 00000020 edbb6cc8 ec691f4c ec691f38 c04c8014 c04a3aac 00000006 edbb6cc0
[ 84.268967] 1f40: ec691f94 ec691f50 c04b69f4 c04c7fb8 00000000 edbb6cc0 edbb6cc0 00000006
[ 84.277130] 1f60: 00005415 bea13274 ec690000 00000036 ec691fa4 ec691f80 c04cbee0 c04cb560
[ 84.285295] 1f80: 00000006 bea13278 bea13274 00000036 c0309a24 ec690000 00000000 ec691fa8
[ 84.293459] 1fa0: c0309840 c04cbea8 00000006 bea13278 00000006 00005415 bea13274 00000406
[ 84.301621] 1fc0: 00000006 bea13278 bea13274 00000036 b6fda900 00000000 00000000 b6fda900
[ 84.309785] 1fe0: 0007eb70 bea1326c 0002f8bc b6e6d5dc 600f0010 00000006 00000000 00000000
[ 84.317985] [<bf163060>] (altera_uart_get_mctrl [altera_uart]) from [<c08926d8>] (uart_tiocmget+0x5c/0x94)
[ 84.327643] [<c08926d8>] (uart_tiocmget) from [<c0876940>] (tty_ioctl+0x64c/0xe7c)
[ 84.335221] [<c0876940>] (tty_ioctl) from [<c04cb604>] (do_vfs_ioctl+0xb0/0x948)
[ 84.342618] [<c04cb604>] (do_vfs_ioctl) from [<c04cbee0>] (SyS_ioctl+0x44/0x68)
[ 84.349934] [<c04cbee0>] (SyS_ioctl) from [<c0309840>] (ret_fast_syscall+0x0/0x48)
[ 84.357503] Code: e3a01008 e0833211 e5932000 f57ff04f (e590312c)
[ 84.363591] ---[ end trace ceddac7d9e91c9fc ]---
def device_tree_source(rst, l4_main_clk)
return <<" EOF"
/dts-v1/;
/ {
#{@name}@0 {
target-path = "/soc";
__overlay__ {
hps_fpgabridge0: fpgabridge@0 {
compatible = "altr,socfpga-hps2fpga-bridge";
label = "hps2fpga";
resets = <#{rst} #{HPS2FPGA_RESET}>;
reset-names = "hps2fpga";
clocks = <#{l4_main_clk}>;
};
};
};
#{@name}@1 {
target-path = "/soc";
__overlay__ {
hps_fpgabridge1: fpgabridge@1 {
compatible = "altr,socfpga-lwhps2fpga-bridge";
label = "lwhps2fpga";
resets = <#{rst} #{LWHPS2FPGA_RESET}>;
reset-names = "lwhps2fpga";
clocks = <#{l4_main_clk}>;
};
};
};
#{@name}@2 {
target-path = "/soc";
__overlay__ {
hps_fpgabridge2: fpgabridge@2 {
compatible = "altr,socfpga-fpga2hps-bridge";
label = "fpga2hps";
resets = <#{rst} #{FPGA2HPS_RESET}>;
reset-names = "fpga2hps";
clocks = <#{l4_main_clk}>;
};
};
};
#{@name}@3 {
target-path = "/soc";
__overlay__ {
#address-cells = <0x1>;
#size-cells = <0x1>;
l3regs@0xff800000 {
compatible = "altr,l3regs", "syscon";
reg = <0xff800000 0x1000>;
};
};
};
#{@name}@4 {
target-path = "/soc";
__overlay__ {
bridge@0xc0000000 {
#address-cells = <2>;
#size-cells = <1>;
serial@0x000004000 {
compatible = "altr,uart-17.1", "altr,uart-1.0";
reg = <0x00000000 0x00004000 0x00000020>;
interrupt-parent = <2>;
interrupts = <0 40 4>;
clock-frequency = <50000000>;
current-speed = <19200>;
};
};
};
};
};
EOF
end
...
@command.each do |command|
case command
when :install then
devtree_install
system("modprobe altera_uart")
system("modprobe fpga-bridge")
system("modprobe altera-hps2fpga")
when :remove then
system("rmmod altera-hps2fpga")
system("rmmod fpga-bridge")
devtree_remove
end
end
...
However nothing happens when I do this. What is the way to add soft peripherals? I can't find anything online.