@@ -896,11 +896,137 @@ static struct ptp_clock_info ocelot_ptp_clock_info = {
896896 .enable = ocelot_ptp_enable ,
897897};
898898
899+ static void mscc_ocelot_release_ports (struct ocelot * ocelot )
900+ {
901+ int port ;
902+
903+ for (port = 0 ; port < ocelot -> num_phys_ports ; port ++ ) {
904+ struct ocelot_port_private * priv ;
905+ struct ocelot_port * ocelot_port ;
906+
907+ ocelot_port = ocelot -> ports [port ];
908+ if (!ocelot_port )
909+ continue ;
910+
911+ ocelot_deinit_port (ocelot , port );
912+
913+ priv = container_of (ocelot_port , struct ocelot_port_private ,
914+ port );
915+
916+ unregister_netdev (priv -> dev );
917+ free_netdev (priv -> dev );
918+ }
919+ }
920+
921+ static int mscc_ocelot_init_ports (struct platform_device * pdev ,
922+ struct device_node * ports )
923+ {
924+ struct ocelot * ocelot = platform_get_drvdata (pdev );
925+ struct device_node * portnp ;
926+ int err ;
927+
928+ ocelot -> ports = devm_kcalloc (ocelot -> dev , ocelot -> num_phys_ports ,
929+ sizeof (struct ocelot_port * ), GFP_KERNEL );
930+ if (!ocelot -> ports )
931+ return - ENOMEM ;
932+
933+ /* No NPI port */
934+ ocelot_configure_cpu (ocelot , -1 , OCELOT_TAG_PREFIX_NONE ,
935+ OCELOT_TAG_PREFIX_NONE );
936+
937+ for_each_available_child_of_node (ports , portnp ) {
938+ struct ocelot_port_private * priv ;
939+ struct ocelot_port * ocelot_port ;
940+ struct device_node * phy_node ;
941+ phy_interface_t phy_mode ;
942+ struct phy_device * phy ;
943+ struct regmap * target ;
944+ struct resource * res ;
945+ struct phy * serdes ;
946+ char res_name [8 ];
947+ u32 port ;
948+
949+ if (of_property_read_u32 (portnp , "reg" , & port ))
950+ continue ;
951+
952+ snprintf (res_name , sizeof (res_name ), "port%d" , port );
953+
954+ res = platform_get_resource_byname (pdev , IORESOURCE_MEM ,
955+ res_name );
956+ target = ocelot_regmap_init (ocelot , res );
957+ if (IS_ERR (target ))
958+ continue ;
959+
960+ phy_node = of_parse_phandle (portnp , "phy-handle" , 0 );
961+ if (!phy_node )
962+ continue ;
963+
964+ phy = of_phy_find_device (phy_node );
965+ of_node_put (phy_node );
966+ if (!phy )
967+ continue ;
968+
969+ err = ocelot_probe_port (ocelot , port , target , phy );
970+ if (err ) {
971+ of_node_put (portnp );
972+ return err ;
973+ }
974+
975+ ocelot_port = ocelot -> ports [port ];
976+ priv = container_of (ocelot_port , struct ocelot_port_private ,
977+ port );
978+
979+ of_get_phy_mode (portnp , & phy_mode );
980+
981+ ocelot_port -> phy_mode = phy_mode ;
982+
983+ switch (ocelot_port -> phy_mode ) {
984+ case PHY_INTERFACE_MODE_NA :
985+ continue ;
986+ case PHY_INTERFACE_MODE_SGMII :
987+ break ;
988+ case PHY_INTERFACE_MODE_QSGMII :
989+ /* Ensure clock signals and speed is set on all
990+ * QSGMII links
991+ */
992+ ocelot_port_writel (ocelot_port ,
993+ DEV_CLOCK_CFG_LINK_SPEED
994+ (OCELOT_SPEED_1000 ),
995+ DEV_CLOCK_CFG );
996+ break ;
997+ default :
998+ dev_err (ocelot -> dev ,
999+ "invalid phy mode for port%d, (Q)SGMII only\n" ,
1000+ port );
1001+ of_node_put (portnp );
1002+ return - EINVAL ;
1003+ }
1004+
1005+ serdes = devm_of_phy_get (ocelot -> dev , portnp , NULL );
1006+ if (IS_ERR (serdes )) {
1007+ err = PTR_ERR (serdes );
1008+ if (err == - EPROBE_DEFER )
1009+ dev_dbg (ocelot -> dev , "deferring probe\n" );
1010+ else
1011+ dev_err (ocelot -> dev ,
1012+ "missing SerDes phys for port%d\n" ,
1013+ port );
1014+
1015+ of_node_put (portnp );
1016+ return err ;
1017+ }
1018+
1019+ priv -> serdes = serdes ;
1020+ }
1021+
1022+ return 0 ;
1023+ }
1024+
8991025static int mscc_ocelot_probe (struct platform_device * pdev )
9001026{
9011027 struct device_node * np = pdev -> dev .of_node ;
902- struct device_node * ports , * portnp ;
9031028 int err , irq_xtr , irq_ptp_rdy ;
1029+ struct device_node * ports ;
9041030 struct ocelot * ocelot ;
9051031 struct regmap * hsio ;
9061032 unsigned int i ;
@@ -985,20 +1111,24 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
9851111
9861112 ports = of_get_child_by_name (np , "ethernet-ports" );
9871113 if (!ports ) {
988- dev_err (& pdev -> dev , "no ethernet-ports child node found\n" );
1114+ dev_err (ocelot -> dev , "no ethernet-ports child node found\n" );
9891115 return - ENODEV ;
9901116 }
9911117
9921118 ocelot -> num_phys_ports = of_get_child_count (ports );
9931119
994- ocelot -> ports = devm_kcalloc (& pdev -> dev , ocelot -> num_phys_ports ,
995- sizeof (struct ocelot_port * ), GFP_KERNEL );
996-
9971120 ocelot -> vcap_is2_keys = vsc7514_vcap_is2_keys ;
9981121 ocelot -> vcap_is2_actions = vsc7514_vcap_is2_actions ;
9991122 ocelot -> vcap = vsc7514_vcap_props ;
10001123
1001- ocelot_init (ocelot );
1124+ err = ocelot_init (ocelot );
1125+ if (err )
1126+ goto out_put_ports ;
1127+
1128+ err = mscc_ocelot_init_ports (pdev , ports );
1129+ if (err )
1130+ goto out_put_ports ;
1131+
10021132 if (ocelot -> ptp ) {
10031133 err = ocelot_init_timestamp (ocelot , & ocelot_ptp_clock_info );
10041134 if (err ) {
@@ -1008,96 +1138,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
10081138 }
10091139 }
10101140
1011- /* No NPI port */
1012- ocelot_configure_cpu (ocelot , -1 , OCELOT_TAG_PREFIX_NONE ,
1013- OCELOT_TAG_PREFIX_NONE );
1014-
1015- for_each_available_child_of_node (ports , portnp ) {
1016- struct ocelot_port_private * priv ;
1017- struct ocelot_port * ocelot_port ;
1018- struct device_node * phy_node ;
1019- phy_interface_t phy_mode ;
1020- struct phy_device * phy ;
1021- struct regmap * target ;
1022- struct resource * res ;
1023- struct phy * serdes ;
1024- char res_name [8 ];
1025- u32 port ;
1026-
1027- if (of_property_read_u32 (portnp , "reg" , & port ))
1028- continue ;
1029-
1030- snprintf (res_name , sizeof (res_name ), "port%d" , port );
1031-
1032- res = platform_get_resource_byname (pdev , IORESOURCE_MEM ,
1033- res_name );
1034- target = ocelot_regmap_init (ocelot , res );
1035- if (IS_ERR (target ))
1036- continue ;
1037-
1038- phy_node = of_parse_phandle (portnp , "phy-handle" , 0 );
1039- if (!phy_node )
1040- continue ;
1041-
1042- phy = of_phy_find_device (phy_node );
1043- of_node_put (phy_node );
1044- if (!phy )
1045- continue ;
1046-
1047- err = ocelot_probe_port (ocelot , port , target , phy );
1048- if (err ) {
1049- of_node_put (portnp );
1050- goto out_put_ports ;
1051- }
1052-
1053- ocelot_port = ocelot -> ports [port ];
1054- priv = container_of (ocelot_port , struct ocelot_port_private ,
1055- port );
1056-
1057- of_get_phy_mode (portnp , & phy_mode );
1058-
1059- ocelot_port -> phy_mode = phy_mode ;
1060-
1061- switch (ocelot_port -> phy_mode ) {
1062- case PHY_INTERFACE_MODE_NA :
1063- continue ;
1064- case PHY_INTERFACE_MODE_SGMII :
1065- break ;
1066- case PHY_INTERFACE_MODE_QSGMII :
1067- /* Ensure clock signals and speed is set on all
1068- * QSGMII links
1069- */
1070- ocelot_port_writel (ocelot_port ,
1071- DEV_CLOCK_CFG_LINK_SPEED
1072- (OCELOT_SPEED_1000 ),
1073- DEV_CLOCK_CFG );
1074- break ;
1075- default :
1076- dev_err (ocelot -> dev ,
1077- "invalid phy mode for port%d, (Q)SGMII only\n" ,
1078- port );
1079- of_node_put (portnp );
1080- err = - EINVAL ;
1081- goto out_put_ports ;
1082- }
1083-
1084- serdes = devm_of_phy_get (ocelot -> dev , portnp , NULL );
1085- if (IS_ERR (serdes )) {
1086- err = PTR_ERR (serdes );
1087- if (err == - EPROBE_DEFER )
1088- dev_dbg (ocelot -> dev , "deferring probe\n" );
1089- else
1090- dev_err (ocelot -> dev ,
1091- "missing SerDes phys for port%d\n" ,
1092- port );
1093-
1094- of_node_put (portnp );
1095- goto out_put_ports ;
1096- }
1097-
1098- priv -> serdes = serdes ;
1099- }
1100-
11011141 register_netdevice_notifier (& ocelot_netdevice_nb );
11021142 register_switchdev_notifier (& ocelot_switchdev_nb );
11031143 register_switchdev_blocking_notifier (& ocelot_switchdev_blocking_nb );
@@ -1114,6 +1154,7 @@ static int mscc_ocelot_remove(struct platform_device *pdev)
11141154 struct ocelot * ocelot = platform_get_drvdata (pdev );
11151155
11161156 ocelot_deinit_timestamp (ocelot );
1157+ mscc_ocelot_release_ports (ocelot );
11171158 ocelot_deinit (ocelot );
11181159 unregister_switchdev_blocking_notifier (& ocelot_switchdev_blocking_nb );
11191160 unregister_switchdev_notifier (& ocelot_switchdev_nb );
0 commit comments