@@ -607,13 +607,59 @@ int fdt_parse_xlnx_uartlite_node(const void *fdt, int nodeoffset,
607607 return fdt_parse_uart_node_common (fdt , nodeoffset , uart , 0 , 0 );
608608}
609609
610+ static int fdt_aplic_find_imsic_node (const void * fdt , int nodeoff ,
611+ struct imsic_data * imsic , bool mmode )
612+ {
613+ const fdt32_t * val ;
614+ int i , len , noff , rc ;
615+
616+ val = fdt_getprop (fdt , nodeoff , "msi-parent" , & len );
617+ if (val && len >= sizeof (fdt32_t )) {
618+ noff = fdt_node_offset_by_phandle (fdt , fdt32_to_cpu (* val ));
619+ if (noff < 0 )
620+ return noff ;
621+
622+ rc = fdt_parse_imsic_node (fdt , noff , imsic );
623+ if (rc )
624+ return rc ;
625+
626+ rc = imsic_data_check (imsic );
627+ if (rc )
628+ return rc ;
629+
630+ if (imsic -> targets_mmode == mmode ) {
631+ return 0 ;
632+ }
633+ } else {
634+ return SBI_ENODEV ;
635+ }
636+
637+ val = fdt_getprop (fdt , nodeoff , "riscv,children" , & len );
638+ if (!val || len < sizeof (fdt32_t ))
639+ return SBI_ENODEV ;
640+
641+ len /= sizeof (fdt32_t );
642+
643+ for (i = 0 ; i < len ; i ++ ) {
644+ noff = fdt_node_offset_by_phandle (fdt , fdt32_to_cpu (val [i ]));
645+ if (noff < 0 )
646+ return noff ;
647+
648+ rc = fdt_aplic_find_imsic_node (fdt , noff , imsic , mmode );
649+ if (!rc )
650+ break ;
651+ }
652+
653+ return rc ;
654+ }
655+
610656int fdt_parse_aplic_node (const void * fdt , int nodeoff , struct aplic_data * aplic )
611657{
612658 bool child_found ;
613659 const fdt32_t * val ;
614660 const fdt32_t * del ;
615661 struct imsic_data imsic = { 0 };
616- int i , j , d , dcnt , len , noff , rc ;
662+ int i , j , d , dcnt , len , rc ;
617663 uint64_t reg_addr , reg_size ;
618664 struct aplic_delegate_data * deleg ;
619665
@@ -640,78 +686,34 @@ int fdt_parse_aplic_node(const void *fdt, int nodeoff, struct aplic_data *aplic)
640686 }
641687 }
642688 aplic -> num_idc = len / 2 ;
643- goto aplic_msi_parent_done ;
644689 }
645690
646- val = fdt_getprop (fdt , nodeoff , "msi-parent" , & len );
647- if (val && len >= sizeof (fdt32_t )) {
648- noff = fdt_node_offset_by_phandle (fdt , fdt32_to_cpu (* val ));
649- if (noff < 0 )
650- return noff ;
651-
652- rc = fdt_parse_imsic_node (fdt , noff , & imsic );
653- if (rc )
654- return rc ;
655-
656- rc = imsic_data_check (& imsic );
657- if (rc )
658- return rc ;
659-
660- aplic -> targets_mmode = imsic .targets_mmode ;
661-
662- if (imsic .targets_mmode ) {
663- aplic -> has_msicfg_mmode = true;
664- aplic -> msicfg_mmode .lhxs = imsic .guest_index_bits ;
665- aplic -> msicfg_mmode .lhxw = imsic .hart_index_bits ;
666- aplic -> msicfg_mmode .hhxw = imsic .group_index_bits ;
667- aplic -> msicfg_mmode .hhxs = imsic .group_index_shift ;
668- if (aplic -> msicfg_mmode .hhxs <
669- (2 * IMSIC_MMIO_PAGE_SHIFT ))
670- return SBI_EINVAL ;
671- aplic -> msicfg_mmode .hhxs -= 24 ;
672- aplic -> msicfg_mmode .base_addr = imsic .regs [0 ].addr ;
673- } else {
674- goto aplic_msi_parent_done ;
675- }
676-
677- val = fdt_getprop (fdt , nodeoff , "riscv,children" , & len );
678- if (!val || len < sizeof (fdt32_t ))
679- goto aplic_msi_parent_done ;
680-
681- noff = fdt_node_offset_by_phandle (fdt , fdt32_to_cpu (* val ));
682- if (noff < 0 )
683- return noff ;
684-
685- val = fdt_getprop (fdt , noff , "msi-parent" , & len );
686- if (!val || len < sizeof (fdt32_t ))
687- goto aplic_msi_parent_done ;
688-
689- noff = fdt_node_offset_by_phandle (fdt , fdt32_to_cpu (* val ));
690- if (noff < 0 )
691- return noff ;
692-
693- rc = fdt_parse_imsic_node (fdt , noff , & imsic );
694- if (rc )
695- return rc ;
696-
697- rc = imsic_data_check (& imsic );
698- if (rc )
699- return rc ;
691+ rc = fdt_aplic_find_imsic_node (fdt , nodeoff , & imsic , true);
692+ if (!rc ) {
693+ aplic -> targets_mmode = true;
694+ aplic -> has_msicfg_mmode = true;
695+ aplic -> msicfg_mmode .lhxs = imsic .guest_index_bits ;
696+ aplic -> msicfg_mmode .lhxw = imsic .hart_index_bits ;
697+ aplic -> msicfg_mmode .hhxw = imsic .group_index_bits ;
698+ aplic -> msicfg_mmode .hhxs = imsic .group_index_shift ;
699+ if (aplic -> msicfg_mmode .hhxs < (2 * IMSIC_MMIO_PAGE_SHIFT ))
700+ return SBI_EINVAL ;
701+ aplic -> msicfg_mmode .hhxs -= 24 ;
702+ aplic -> msicfg_mmode .base_addr = imsic .regs [0 ].addr ;
703+ }
700704
701- if (!imsic .targets_mmode ) {
702- aplic -> has_msicfg_smode = true;
703- aplic -> msicfg_smode .lhxs = imsic .guest_index_bits ;
704- aplic -> msicfg_smode .lhxw = imsic .hart_index_bits ;
705- aplic -> msicfg_smode .hhxw = imsic .group_index_bits ;
706- aplic -> msicfg_smode .hhxs = imsic .group_index_shift ;
707- if (aplic -> msicfg_smode .hhxs <
708- (2 * IMSIC_MMIO_PAGE_SHIFT ))
709- return SBI_EINVAL ;
710- aplic -> msicfg_smode .hhxs -= 24 ;
711- aplic -> msicfg_smode .base_addr = imsic .regs [0 ].addr ;
712- }
705+ rc = fdt_aplic_find_imsic_node (fdt , nodeoff , & imsic , false);
706+ if (!rc ) {
707+ aplic -> has_msicfg_smode = true;
708+ aplic -> msicfg_smode .lhxs = imsic .guest_index_bits ;
709+ aplic -> msicfg_smode .lhxw = imsic .hart_index_bits ;
710+ aplic -> msicfg_smode .hhxw = imsic .group_index_bits ;
711+ aplic -> msicfg_smode .hhxs = imsic .group_index_shift ;
712+ if (aplic -> msicfg_smode .hhxs < (2 * IMSIC_MMIO_PAGE_SHIFT ))
713+ return SBI_EINVAL ;
714+ aplic -> msicfg_smode .hhxs -= 24 ;
715+ aplic -> msicfg_smode .base_addr = imsic .regs [0 ].addr ;
713716 }
714- aplic_msi_parent_done :
715717
716718 for (d = 0 ; d < APLIC_MAX_DELEGATE ; d ++ ) {
717719 deleg = & aplic -> delegate [d ];
0 commit comments