3030#define  PD692X0_FW_MIN_VER 	5
3131#define  PD692X0_FW_PATCH_VER 	5
3232
33+ #define  PD692X0_USER_BYTE 	42
34+ 
3335enum  pd692x0_fw_state  {
3436	PD692X0_FW_UNKNOWN ,
3537	PD692X0_FW_OK ,
@@ -80,11 +82,17 @@ enum {
8082	PD692X0_MSG_GET_PORT_PARAM ,
8183	PD692X0_MSG_GET_POWER_BANK ,
8284	PD692X0_MSG_SET_POWER_BANK ,
85+ 	PD692X0_MSG_SET_USER_BYTE ,
8386
8487	/* add new message above here */ 
8588	PD692X0_MSG_CNT 
8689};
8790
91+ struct  pd692x0_matrix  {
92+ 	u8  hw_port_a ;
93+ 	u8  hw_port_b ;
94+ };
95+ 
8896struct  pd692x0_priv  {
8997	struct  i2c_client  * client ;
9098	struct  pse_controller_dev  pcdev ;
@@ -98,9 +106,12 @@ struct pd692x0_priv {
98106	bool  last_cmd_key ;
99107	unsigned long  last_cmd_key_time ;
100108
109+ 	bool  cfg_saved ;
101110	enum  ethtool_c33_pse_admin_state  admin_state [PD692X0_MAX_PIS ];
102111	struct  regulator_dev  * manager_reg [PD692X0_MAX_MANAGERS ];
103112	int  manager_pw_budget [PD692X0_MAX_MANAGERS ];
113+ 	int  nmanagers ;
114+ 	struct  pd692x0_matrix  * port_matrix ;
104115};
105116
106117/* Template list of communication messages. The non-null bytes defined here 
@@ -186,6 +197,12 @@ static const struct pd692x0_msg pd692x0_msg_template_list[PD692X0_MSG_CNT] = {
186197		.key  =  PD692X0_KEY_CMD ,
187198		.sub  =  {0x07 , 0x0b , 0x57 },
188199	},
200+ 	[PD692X0_MSG_SET_USER_BYTE ] =  {
201+ 		.key  =  PD692X0_KEY_PRG ,
202+ 		.sub  =  {0x41 , PD692X0_USER_BYTE },
203+ 		.data  =  {0x4e , 0x4e , 0x4e , 0x4e ,
204+ 			 0x4e , 0x4e , 0x4e , 0x4e },
205+ 	},
189206};
190207
191208static  u8  pd692x0_build_msg (struct  pd692x0_msg  * msg , u8  echo )
@@ -809,11 +826,6 @@ struct pd692x0_manager {
809826	int  nports ;
810827};
811828
812- struct  pd692x0_matrix  {
813- 	u8  hw_port_a ;
814- 	u8  hw_port_b ;
815- };
816- 
817829static  int 
818830pd692x0_of_get_ports_manager (struct  pd692x0_priv  * priv ,
819831			     struct  pd692x0_manager  * manager ,
@@ -903,7 +915,8 @@ pd692x0_of_get_managers(struct pd692x0_priv *priv,
903915	}
904916
905917	of_node_put (managers_node );
906- 	return  nmanagers ;
918+ 	priv -> nmanagers  =  nmanagers ;
919+ 	return  0 ;
907920
908921out :
909922	for  (i  =  0 ; i  <  nmanagers ; i ++ ) {
@@ -963,8 +976,7 @@ pd692x0_register_manager_regulator(struct device *dev, char *reg_name,
963976
964977static  int 
965978pd692x0_register_managers_regulator (struct  pd692x0_priv  * priv ,
966- 				    const  struct  pd692x0_manager  * manager ,
967- 				    int  nmanagers )
979+ 				    const  struct  pd692x0_manager  * manager )
968980{
969981	struct  device  * dev  =  & priv -> client -> dev ;
970982	size_t  reg_name_len ;
@@ -975,7 +987,7 @@ pd692x0_register_managers_regulator(struct pd692x0_priv *priv,
975987	 */ 
976988	reg_name_len  =  strlen (dev_name (dev )) +  23 ;
977989
978- 	for  (i  =  0 ; i  <  nmanagers ; i ++ ) {
990+ 	for  (i  =  0 ; i  <  priv -> nmanagers ; i ++ ) {
979991		static  const  char  *  const  regulators [] =  { "vaux5" , "vaux3p3"  };
980992		struct  regulator_dev  * rdev ;
981993		char  * reg_name ;
@@ -1008,10 +1020,14 @@ pd692x0_register_managers_regulator(struct pd692x0_priv *priv,
10081020}
10091021
10101022static  int 
1011- pd692x0_conf_manager_power_budget (struct  pd692x0_priv  * priv , int  id ,  int   pw )
1023+ pd692x0_conf_manager_power_budget (struct  pd692x0_priv  * priv , int  id )
10121024{
10131025	struct  pd692x0_msg  msg , buf ;
1014- 	int  ret , pw_mW  =  pw  / 1000 ;
1026+ 	int  ret , pw_mW ;
1027+ 
1028+ 	pw_mW  =  priv -> manager_pw_budget [id ] / 1000 ;
1029+ 	if  (!pw_mW )
1030+ 		return  0 ;
10151031
10161032	msg  =  pd692x0_msg_template_list [PD692X0_MSG_GET_POWER_BANK ];
10171033	msg .data [0 ] =  id ;
@@ -1032,11 +1048,11 @@ pd692x0_conf_manager_power_budget(struct pd692x0_priv *priv, int id, int pw)
10321048}
10331049
10341050static  int 
1035- pd692x0_configure_managers (struct  pd692x0_priv  * priv ,  int   nmanagers )
1051+ pd692x0_req_managers_pw_budget (struct  pd692x0_priv  * priv )
10361052{
10371053	int  i , ret ;
10381054
1039- 	for  (i  =  0 ; i  <  nmanagers ; i ++ ) {
1055+ 	for  (i  =  0 ; i  <  priv -> nmanagers ; i ++ ) {
10401056		struct  regulator  * supply  =  priv -> manager_reg [i ]-> supply ;
10411057		int  pw_budget ;
10421058
@@ -1053,7 +1069,18 @@ pd692x0_configure_managers(struct pd692x0_priv *priv, int nmanagers)
10531069			return  ret ;
10541070
10551071		priv -> manager_pw_budget [i ] =  pw_budget ;
1056- 		ret  =  pd692x0_conf_manager_power_budget (priv , i , pw_budget );
1072+ 	}
1073+ 
1074+ 	return  0 ;
1075+ }
1076+ 
1077+ static  int 
1078+ pd692x0_configure_managers (struct  pd692x0_priv  * priv )
1079+ {
1080+ 	int  i , ret ;
1081+ 
1082+ 	for  (i  =  0 ; i  <  priv -> nmanagers ; i ++ ) {
1083+ 		ret  =  pd692x0_conf_manager_power_budget (priv , i );
10571084		if  (ret  <  0 )
10581085			return  ret ;
10591086	}
@@ -1101,10 +1128,9 @@ pd692x0_set_port_matrix(const struct pse_pi_pairset *pairset,
11011128
11021129static  int 
11031130pd692x0_set_ports_matrix (struct  pd692x0_priv  * priv ,
1104- 			 const  struct  pd692x0_manager  * manager ,
1105- 			 int  nmanagers ,
1106- 			 struct  pd692x0_matrix  port_matrix [PD692X0_MAX_PIS ])
1131+ 			 const  struct  pd692x0_manager  * manager )
11071132{
1133+ 	struct  pd692x0_matrix  * port_matrix  =  priv -> port_matrix ;
11081134	struct  pse_controller_dev  * pcdev  =  & priv -> pcdev ;
11091135	int  i , ret ;
11101136
@@ -1117,7 +1143,7 @@ pd692x0_set_ports_matrix(struct pd692x0_priv *priv,
11171143	/* Update with values for every PSE PIs */ 
11181144	for  (i  =  0 ; i  <  pcdev -> nr_lines ; i ++ ) {
11191145		ret  =  pd692x0_set_port_matrix (& pcdev -> pi [i ].pairset [0 ],
1120- 					      manager , nmanagers ,
1146+ 					      manager , priv -> nmanagers ,
11211147					      & port_matrix [i ]);
11221148		if  (ret ) {
11231149			dev_err (& priv -> client -> dev ,
@@ -1126,7 +1152,7 @@ pd692x0_set_ports_matrix(struct pd692x0_priv *priv,
11261152		}
11271153
11281154		ret  =  pd692x0_set_port_matrix (& pcdev -> pi [i ].pairset [1 ],
1129- 					      manager , nmanagers ,
1155+ 					      manager , priv -> nmanagers ,
11301156					      & port_matrix [i ]);
11311157		if  (ret ) {
11321158			dev_err (& priv -> client -> dev ,
@@ -1139,9 +1165,9 @@ pd692x0_set_ports_matrix(struct pd692x0_priv *priv,
11391165}
11401166
11411167static  int 
1142- pd692x0_write_ports_matrix (struct  pd692x0_priv  * priv ,
1143- 			   const  struct  pd692x0_matrix  port_matrix [PD692X0_MAX_PIS ])
1168+ pd692x0_write_ports_matrix (struct  pd692x0_priv  * priv )
11441169{
1170+ 	struct  pd692x0_matrix  * port_matrix  =  priv -> port_matrix ;
11451171	struct  pd692x0_msg  msg , buf ;
11461172	int  ret , i ;
11471173
@@ -1166,13 +1192,32 @@ pd692x0_write_ports_matrix(struct pd692x0_priv *priv,
11661192	return  0 ;
11671193}
11681194
1195+ static  int  pd692x0_hw_conf_init (struct  pd692x0_priv  * priv )
1196+ {
1197+ 	int  ret ;
1198+ 
1199+ 	/* Is PD692x0 ready to be configured? */ 
1200+ 	if  (priv -> fw_state  !=  PD692X0_FW_OK  && 
1201+ 	    priv -> fw_state  !=  PD692X0_FW_COMPLETE )
1202+ 		return  0 ;
1203+ 
1204+ 	ret  =  pd692x0_configure_managers (priv );
1205+ 	if  (ret )
1206+ 		return  ret ;
1207+ 
1208+ 	ret  =  pd692x0_write_ports_matrix (priv );
1209+ 	if  (ret )
1210+ 		return  ret ;
1211+ 
1212+ 	return  0 ;
1213+ }
1214+ 
11691215static  void  pd692x0_of_put_managers (struct  pd692x0_priv  * priv ,
1170- 				    struct  pd692x0_manager  * manager ,
1171- 				    int  nmanagers )
1216+ 				    struct  pd692x0_manager  * manager )
11721217{
11731218	int  i , j ;
11741219
1175- 	for  (i  =  0 ; i  <  nmanagers ; i ++ ) {
1220+ 	for  (i  =  0 ; i  <  priv -> nmanagers ; i ++ ) {
11761221		for  (j  =  0 ; j  <  manager [i ].nports ; j ++ )
11771222			of_node_put (manager [i ].port_node [j ]);
11781223		of_node_put (manager [i ].node );
@@ -1198,50 +1243,71 @@ static void pd692x0_managers_free_pw_budget(struct pd692x0_priv *priv)
11981243	}
11991244}
12001245
1246+ static  int 
1247+ pd692x0_save_user_byte (struct  pd692x0_priv  * priv )
1248+ {
1249+ 	struct  pd692x0_msg  msg , buf ;
1250+ 
1251+ 	msg  =  pd692x0_msg_template_list [PD692X0_MSG_SET_USER_BYTE ];
1252+ 	return  pd692x0_sendrecv_msg (priv , & msg , & buf );
1253+ }
1254+ 
12011255static  int  pd692x0_setup_pi_matrix (struct  pse_controller_dev  * pcdev )
12021256{
1203- 	struct  pd692x0_manager  * manager  __free (kfree ) =  NULL ;
12041257	struct  pd692x0_priv  * priv  =  to_pd692x0_priv (pcdev );
1205- 	struct  pd692x0_matrix  port_matrix [PD692X0_MAX_PIS ];
1206- 	int  ret , nmanagers ;
1207- 
1208- 	/* Should we flash the port matrix */ 
1209- 	if  (priv -> fw_state  !=  PD692X0_FW_OK  && 
1210- 	    priv -> fw_state  !=  PD692X0_FW_COMPLETE )
1211- 		return  0 ;
1258+ 	struct  pd692x0_matrix  * port_matrix ;
1259+ 	struct  pd692x0_manager  * manager ;
1260+ 	int  ret ;
12121261
12131262	manager  =  kcalloc (PD692X0_MAX_MANAGERS , sizeof (* manager ), GFP_KERNEL );
12141263	if  (!manager )
12151264		return  - ENOMEM ;
12161265
1266+ 	port_matrix  =  devm_kcalloc (& priv -> client -> dev , PD692X0_MAX_PIS ,
1267+ 				   sizeof (* port_matrix ), GFP_KERNEL );
1268+ 	if  (!port_matrix ) {
1269+ 		ret  =  - ENOMEM ;
1270+ 		goto err_free_manager ;
1271+ 	}
1272+ 	priv -> port_matrix  =  port_matrix ;
1273+ 
12171274	ret  =  pd692x0_of_get_managers (priv , manager );
12181275	if  (ret  <  0 )
1219- 		return   ret ;
1276+ 		goto  err_free_manager ;
12201277
1221- 	nmanagers  =  ret ;
1222- 	ret  =  pd692x0_register_managers_regulator (priv , manager , nmanagers );
1278+ 	ret  =  pd692x0_register_managers_regulator (priv , manager );
12231279	if  (ret )
12241280		goto err_of_managers ;
12251281
1226- 	ret  =  pd692x0_configure_managers (priv ,  nmanagers );
1282+ 	ret  =  pd692x0_req_managers_pw_budget (priv );
12271283	if  (ret )
12281284		goto err_of_managers ;
12291285
1230- 	ret  =  pd692x0_set_ports_matrix (priv , manager ,  nmanagers ,  port_matrix );
1286+ 	ret  =  pd692x0_set_ports_matrix (priv , manager );
12311287	if  (ret )
12321288		goto err_managers_req_pw ;
12331289
1234- 	ret  =  pd692x0_write_ports_matrix (priv , port_matrix );
1235- 	if  (ret )
1236- 		goto err_managers_req_pw ;
1290+ 	/* Do not init the conf if it is already saved */ 
1291+ 	if  (!priv -> cfg_saved ) {
1292+ 		ret  =  pd692x0_hw_conf_init (priv );
1293+ 		if  (ret )
1294+ 			goto err_managers_req_pw ;
12371295
1238- 	pd692x0_of_put_managers (priv , manager , nmanagers );
1296+ 		ret  =  pd692x0_save_user_byte (priv );
1297+ 		if  (ret )
1298+ 			goto err_managers_req_pw ;
1299+ 	}
1300+ 
1301+ 	pd692x0_of_put_managers (priv , manager );
1302+ 	kfree (manager );
12391303	return  0 ;
12401304
12411305err_managers_req_pw :
12421306	pd692x0_managers_free_pw_budget (priv );
12431307err_of_managers :
1244- 	pd692x0_of_put_managers (priv , manager , nmanagers );
1308+ 	pd692x0_of_put_managers (priv , manager );
1309+ err_free_manager :
1310+ 	kfree (manager );
12451311	return  ret ;
12461312}
12471313
@@ -1644,7 +1710,7 @@ static enum fw_upload_err pd692x0_fw_poll_complete(struct fw_upload *fwl)
16441710		return  FW_UPLOAD_ERR_FW_INVALID ;
16451711	}
16461712
1647- 	ret  =  pd692x0_setup_pi_matrix ( & priv -> pcdev );
1713+ 	ret  =  pd692x0_hw_conf_init ( priv );
16481714	if  (ret  <  0 ) {
16491715		dev_err (& client -> dev , "Error configuring ports matrix (%pe)\n" ,
16501716			ERR_PTR (ret ));
@@ -1753,6 +1819,9 @@ static int pd692x0_i2c_probe(struct i2c_client *client)
17531819		}
17541820	}
17551821
1822+ 	if  (buf .data [2 ] ==  PD692X0_USER_BYTE )
1823+ 		priv -> cfg_saved  =  true;
1824+ 
17561825	priv -> np  =  dev -> of_node ;
17571826	priv -> pcdev .nr_lines  =  PD692X0_MAX_PIS ;
17581827	priv -> pcdev .owner  =  THIS_MODULE ;
0 commit comments