@@ -902,6 +902,127 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
902
902
}
903
903
904
904
#ifdef CONFIG_OF
905
+ /*
906
+ * The window IDs in the ranges DT property have the following format:
907
+ * - bits 28 to 31: MBus custom field
908
+ * - bits 24 to 27: window target ID
909
+ * - bits 16 to 23: window attribute ID
910
+ * - bits 0 to 15: unused
911
+ */
912
+ #define CUSTOM (id ) (((id) & 0xF0000000) >> 24)
913
+ #define TARGET (id ) (((id) & 0x0F000000) >> 24)
914
+ #define ATTR (id ) (((id) & 0x00FF0000) >> 16)
915
+
916
+ static int __init mbus_dt_setup_win (struct mvebu_mbus_state * mbus ,
917
+ u32 base , u32 size ,
918
+ u8 target , u8 attr )
919
+ {
920
+ const struct mvebu_mbus_mapping * map = mbus -> soc -> map ;
921
+ const char * name ;
922
+ int i ;
923
+
924
+ /* Search for a suitable window in the existing mappings */
925
+ for (i = 0 ; map [i ].name ; i ++ )
926
+ if (map [i ].target == target &&
927
+ map [i ].attr == (attr & map [i ].attrmask ))
928
+ break ;
929
+
930
+ name = map [i ].name ;
931
+ if (!name ) {
932
+ pr_err ("window 0x%x:0x%x is unknown, skipping\n" ,
933
+ target , attr );
934
+ return - EINVAL ;
935
+ }
936
+
937
+ if (!mvebu_mbus_window_conflicts (mbus , base , size , target , attr )) {
938
+ pr_err ("cannot add window '%s', conflicts with another window\n" ,
939
+ name );
940
+ return - EBUSY ;
941
+ }
942
+
943
+ if (mvebu_mbus_alloc_window (mbus , base , size , MVEBU_MBUS_NO_REMAP ,
944
+ target , attr )) {
945
+ pr_err ("cannot add window '%s', too many windows\n" ,
946
+ name );
947
+ return - ENOMEM ;
948
+ }
949
+ return 0 ;
950
+ }
951
+
952
+ static int __init
953
+ mbus_parse_ranges (struct device_node * node ,
954
+ int * addr_cells , int * c_addr_cells , int * c_size_cells ,
955
+ int * cell_count , const __be32 * * ranges_start ,
956
+ const __be32 * * ranges_end )
957
+ {
958
+ const __be32 * prop ;
959
+ int ranges_len , tuple_len ;
960
+
961
+ /* Allow a node with no 'ranges' property */
962
+ * ranges_start = of_get_property (node , "ranges" , & ranges_len );
963
+ if (* ranges_start == NULL ) {
964
+ * addr_cells = * c_addr_cells = * c_size_cells = * cell_count = 0 ;
965
+ * ranges_start = * ranges_end = NULL ;
966
+ return 0 ;
967
+ }
968
+ * ranges_end = * ranges_start + ranges_len / sizeof (__be32 );
969
+
970
+ * addr_cells = of_n_addr_cells (node );
971
+
972
+ prop = of_get_property (node , "#address-cells" , NULL );
973
+ * c_addr_cells = be32_to_cpup (prop );
974
+
975
+ prop = of_get_property (node , "#size-cells" , NULL );
976
+ * c_size_cells = be32_to_cpup (prop );
977
+
978
+ * cell_count = * addr_cells + * c_addr_cells + * c_size_cells ;
979
+ tuple_len = (* cell_count ) * sizeof (__be32 );
980
+
981
+ if (ranges_len % tuple_len ) {
982
+ pr_warn ("malformed ranges entry '%s'\n" , node -> name );
983
+ return - EINVAL ;
984
+ }
985
+ return 0 ;
986
+ }
987
+
988
+ static int __init mbus_dt_setup (struct mvebu_mbus_state * mbus ,
989
+ struct device_node * np )
990
+ {
991
+ int addr_cells , c_addr_cells , c_size_cells ;
992
+ int i , ret , cell_count ;
993
+ const __be32 * r , * ranges_start , * ranges_end ;
994
+
995
+ ret = mbus_parse_ranges (np , & addr_cells , & c_addr_cells ,
996
+ & c_size_cells , & cell_count ,
997
+ & ranges_start , & ranges_end );
998
+ if (ret < 0 )
999
+ return ret ;
1000
+
1001
+ for (i = 0 , r = ranges_start ; r < ranges_end ; r += cell_count , i ++ ) {
1002
+ u32 windowid , base , size ;
1003
+ u8 target , attr ;
1004
+
1005
+ /*
1006
+ * An entry with a non-zero custom field do not
1007
+ * correspond to a static window, so skip it.
1008
+ */
1009
+ windowid = of_read_number (r , 1 );
1010
+ if (CUSTOM (windowid ))
1011
+ continue ;
1012
+
1013
+ target = TARGET (windowid );
1014
+ attr = ATTR (windowid );
1015
+
1016
+ base = of_read_number (r + c_addr_cells , addr_cells );
1017
+ size = of_read_number (r + c_addr_cells + addr_cells ,
1018
+ c_size_cells );
1019
+ ret = mbus_dt_setup_win (mbus , base , size , target , attr );
1020
+ if (ret < 0 )
1021
+ return ret ;
1022
+ }
1023
+ return 0 ;
1024
+ }
1025
+
905
1026
int __init mvebu_mbus_dt_init (void )
906
1027
{
907
1028
struct resource mbuswins_res , sdramwins_res ;
@@ -946,6 +1067,10 @@ int __init mvebu_mbus_dt_init(void)
946
1067
resource_size (& mbuswins_res ),
947
1068
sdramwins_res .start ,
948
1069
resource_size (& sdramwins_res ));
949
- return ret ;
1070
+ if (ret )
1071
+ return ret ;
1072
+
1073
+ /* Setup statically declared windows in the DT */
1074
+ return mbus_dt_setup (& mbus_state , np );
950
1075
}
951
1076
#endif
0 commit comments