@@ -21,11 +21,17 @@ LOG_MODULE_REGISTER(phy_mchp_ksz9131, CONFIG_PHY_LOG_LEVEL);
2121struct  mchp_ksz9131_config  {
2222	uint8_t  phy_addr ;
2323	const  struct  device  *  const  mdio ;
24+ #if  DT_ANY_INST_HAS_PROP_STATUS_OKAY (int_gpios )
25+ 	const  struct  gpio_dt_spec  interrupt_gpio ;
26+ #endif 
2427};
2528
2629struct  mchp_ksz9131_data  {
2730	const  struct  device  * dev ;
2831	phy_callback_t  cb ;
32+ #if  DT_ANY_INST_HAS_PROP_STATUS_OKAY (int_gpios )
33+ 	struct  gpio_callback  gpio_callback ;
34+ #endif 
2935	void  * cb_data ;
3036	struct  k_work_delayable  monitor_work ;
3137	struct  phy_link_state  state ;
@@ -127,6 +133,64 @@ static int phy_check_ksz9131_id(const struct device *dev)
127133	return  ret ;
128134}
129135
136+ #if  DT_ANY_INST_HAS_PROP_STATUS_OKAY (int_gpios )
137+ static  int  phy_mchp_ksz9131_clear_interrupt (struct  mchp_ksz9131_data  * data )
138+ {
139+ 	const  struct  device  * dev  =  data -> dev ;
140+ 	const  struct  mchp_ksz9131_config  * cfg  =  dev -> config ;
141+ 	uint16_t  reg_val ;
142+ 	int  ret ;
143+ 
144+ 	k_sem_take (& data -> sem , K_FOREVER );
145+ 
146+ 	/* Read/clear PHY interrupt status register */ 
147+ 	ret  =  ksz9131_read (dev , PHY_KSZ9131_ICS_REG , & reg_val );
148+ 	if  (ret  <  0 ) {
149+ 		LOG_ERR ("Error reading phy (%d) interrupt status register" , cfg -> phy_addr );
150+ 	}
151+ 
152+ 	k_sem_give (& data -> sem );
153+ 
154+ 	return  ret ;
155+ }
156+ 
157+ static  int  phy_mchp_ksz9131_config_interrupt (const  struct  device  * dev )
158+ {
159+ 	struct  mchp_ksz9131_data  * data  =  dev -> data ;
160+ 	uint16_t  reg_val ;
161+ 	int  ret ;
162+ 
163+ 	/* Read Interrupt Control/Status register to write back */ 
164+ 	ret  =  ksz9131_read (dev , PHY_KSZ9131_ICS_REG , & reg_val );
165+ 	if  (ret  <  0 ) {
166+ 		return  ret ;
167+ 	}
168+ 	reg_val  |= PHY_KSZ9131_ICS_LINK_UP_IE_MASK  | PHY_KSZ9131_ICS_LINK_DOWN_IE_MASK ;
169+ 
170+ 	/* Write settings to Interrupt Control/Status register */ 
171+ 	ret  =  ksz9131_write (dev , 27 , reg_val );
172+ 	if  (ret  <  0 ) {
173+ 		return  ret ;
174+ 	}
175+ 
176+ 	/* Clear interrupt */ 
177+ 	ret  =  phy_mchp_ksz9131_clear_interrupt (data );
178+ 
179+ 	return  ret ;
180+ }
181+ 
182+ static  void  phy_mchp_ksz9131_interrupt_handler (const  struct  device  * port , struct  gpio_callback  * cb ,
183+ 				gpio_port_pins_t  pins )
184+ {
185+ 	struct  mchp_ksz9131_data  * data  =  CONTAINER_OF (cb , struct  mchp_ksz9131_data , gpio_callback );
186+ 	int  ret  =  k_work_reschedule (& data -> monitor_work , K_NO_WAIT );
187+ 
188+ 	if  (ret  <  0 ) {
189+ 		LOG_ERR ("Failed to schedule monitor_work from ISR" );
190+ 	}
191+ }
192+ #endif  /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ 
193+ 
130194static  int  phy_mchp_ksz9131_autonegotiate (const  struct  device  * dev )
131195{
132196	const  struct  mchp_ksz9131_config  * const  cfg  =  dev -> config ;
@@ -186,6 +250,9 @@ static int phy_mchp_ksz9131_autonegotiate(const struct device *dev)
186250
187251static  int  phy_mchp_ksz9131_cfg_link (const  struct  device  * dev , enum  phy_link_speed  adv_speeds )
188252{
253+ #if  DT_ANY_INST_HAS_PROP_STATUS_OKAY (int_gpios )
254+ 	const  struct  mchp_ksz9131_config  * const  cfg  =  dev -> config ;
255+ #endif 
189256	struct  mchp_ksz9131_data  * const  data  =  dev -> data ;
190257	uint16_t  anar ;
191258	uint16_t  c1kt ;
@@ -194,7 +261,13 @@ static int phy_mchp_ksz9131_cfg_link(const struct device *dev, enum phy_link_spe
194261	k_sem_take (& data -> sem , K_FOREVER );
195262
196263	/* We are going to reconfigure the phy, don't need to monitor until done */ 
264+ #if  DT_ANY_INST_HAS_PROP_STATUS_OKAY (int_gpios )
265+ 	if  (!cfg -> interrupt_gpio .port ) {
266+ 		k_work_cancel_delayable (& data -> monitor_work );
267+ 	}
268+ #else 
197269	k_work_cancel_delayable (& data -> monitor_work );
270+ #endif  /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ 
198271
199272	ret  =  ksz9131_read (dev , MII_ANAR , & anar );
200273	if  (ret  <  0 ) {
@@ -256,6 +329,12 @@ static int phy_mchp_ksz9131_cfg_link(const struct device *dev, enum phy_link_spe
256329done :
257330	k_sem_give (& data -> sem );
258331
332+ #if  DT_ANY_INST_HAS_PROP_STATUS_OKAY (int_gpios )
333+ 	if  (cfg -> interrupt_gpio .port ) {
334+ 		return  ret ;
335+ 	}
336+ #endif 
337+ 
259338	/* Start monitoring */ 
260339	k_work_reschedule (& data -> monitor_work , K_MSEC (CONFIG_PHY_MONITOR_PERIOD ));
261340
@@ -356,9 +435,21 @@ static void phy_mchp_ksz9131_monitor_work_handler(struct k_work *work)
356435	struct  mchp_ksz9131_data  * const  data  = 
357436		CONTAINER_OF (dwork , struct  mchp_ksz9131_data , monitor_work );
358437	const  struct  device  * dev  =  data -> dev ;
438+ #if  DT_ANY_INST_HAS_PROP_STATUS_OKAY (int_gpios )
439+ 	const  struct  mchp_ksz9131_config  * cfg  =  dev -> config ;
440+ #endif  /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ 
359441	struct  phy_link_state  state  =  {};
360442	int  ret ;
361443
444+ #if  DT_ANY_INST_HAS_PROP_STATUS_OKAY (int_gpios )
445+ 	if  (cfg -> interrupt_gpio .port ) {
446+ 		ret  =  phy_mchp_ksz9131_clear_interrupt (data );
447+ 		if  (ret  <  0 ) {
448+ 			return ;
449+ 		}
450+ 	}
451+ #endif  /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ 
452+ 
362453	ret  =  phy_mchp_ksz9131_get_link (dev , & state );
363454	if  (ret  ==  0  &&  (state .speed  !=  data -> state .speed  ||  state .is_up  !=  data -> state .is_up )) {
364455		memcpy (& data -> state , & state , sizeof (struct  phy_link_state ));
@@ -367,6 +458,12 @@ static void phy_mchp_ksz9131_monitor_work_handler(struct k_work *work)
367458		}
368459	}
369460
461+ #if  DT_ANY_INST_HAS_PROP_STATUS_OKAY (int_gpios )
462+ 	if  (cfg -> interrupt_gpio .port ) {
463+ 		return ;
464+ 	}
465+ #endif  /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ 
466+ 
370467	/* Submit delayed work */ 
371468	k_work_reschedule (& data -> monitor_work , K_MSEC (CONFIG_PHY_MONITOR_PERIOD ));
372469}
@@ -396,7 +493,37 @@ static int phy_mchp_ksz9131_init(const struct device *dev)
396493
397494	k_work_init_delayable (& data -> monitor_work , phy_mchp_ksz9131_monitor_work_handler );
398495
496+ #if  DT_ANY_INST_HAS_PROP_STATUS_OKAY (int_gpios )
497+ 	if  (!cfg -> interrupt_gpio .port ) {
498+ 		phy_mchp_ksz9131_monitor_work_handler (& data -> monitor_work .work );
499+ 		goto done ;
500+ 	}
501+ 
502+ 	/* Configure interrupt pin */ 
503+ 	ret  =  gpio_pin_configure_dt (& cfg -> interrupt_gpio , GPIO_INPUT );
504+ 	if  (ret  <  0 ) {
505+ 		goto done ;
506+ 	}
507+ 
508+ 	gpio_init_callback (& data -> gpio_callback , phy_mchp_ksz9131_interrupt_handler ,
509+ 				BIT (cfg -> interrupt_gpio .pin ));
510+ 
511+ 	ret  =  gpio_add_callback_dt (& cfg -> interrupt_gpio , & data -> gpio_callback );
512+ 	if  (ret  <  0 ) {
513+ 		goto done ;
514+ 	}
515+ 
516+ 	ret  =  phy_mchp_ksz9131_config_interrupt (dev );
517+ 	if  (ret  <  0 ) {
518+ 		goto done ;
519+ 	}
520+ 
521+ 	ret  =  gpio_pin_interrupt_configure_dt (& cfg -> interrupt_gpio ,
522+ 						GPIO_INT_EDGE_TO_ACTIVE );
523+ done :
524+ #else 
399525	phy_mchp_ksz9131_monitor_work_handler (& data -> monitor_work .work );
526+ #endif  /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ 
400527
401528	if  (ret  <  0 ) {
402529		LOG_ERR ("PHY (%d) init failed" , cfg -> phy_addr );
@@ -413,10 +540,17 @@ static DEVICE_API(ethphy, mchp_ksz9131_phy_api) = {
413540	.write  =  phy_mchp_ksz9131_write ,
414541};
415542
543+ #if  DT_ANY_INST_HAS_PROP_STATUS_OKAY (int_gpios )
544+ #define  INTERRUPT_GPIO (n ) .interrupt_gpio = GPIO_DT_SPEC_INST_GET_OR(n, int_gpios, {0}),
545+ #else 
546+ #define  INTERRUPT_GPIO (n )
547+ #endif  /* interrupt gpio */ 
548+ 
416549#define  MICROCHIP_KSZ9131_INIT (n )						\
417550	static const struct mchp_ksz9131_config mchp_ksz9131_##n##_config = {	\
418551		.phy_addr = DT_INST_REG_ADDR(n),				\
419552		.mdio = DEVICE_DT_GET(DT_INST_BUS(n)),				\
553+ 		INTERRUPT_GPIO(n)						\
420554	};									\
421555										\
422556	static struct mchp_ksz9131_data mchp_ksz9131_##n##_data;		\
0 commit comments