@@ -60,6 +60,7 @@ enum modem_cellular_state {
6060 MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT ,
6161 MODEM_CELLULAR_STATE_AWAIT_REGISTERED ,
6262 MODEM_CELLULAR_STATE_CARRIER_ON ,
63+ MODEM_CELLULAR_STATE_DORMANT ,
6364 MODEM_CELLULAR_STATE_INIT_POWER_OFF ,
6465 MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT ,
6566 MODEM_CELLULAR_STATE_POWER_OFF_PULSE ,
@@ -79,6 +80,7 @@ enum modem_cellular_event {
7980 MODEM_CELLULAR_EVENT_DEREGISTERED ,
8081 MODEM_CELLULAR_EVENT_BUS_OPENED ,
8182 MODEM_CELLULAR_EVENT_BUS_CLOSED ,
83+ MODEM_CELLULAR_EVENT_PPP_DEAD ,
8284};
8385
8486struct modem_cellular_data {
@@ -126,6 +128,7 @@ struct modem_cellular_data {
126128
127129 /* PPP */
128130 struct modem_ppp * ppp ;
131+ struct net_mgmt_event_callback net_mgmt_event_callback ;
129132
130133 enum modem_cellular_state state ;
131134 const struct device * dev ;
@@ -154,6 +157,7 @@ struct modem_cellular_config {
154157 const struct device * uart ;
155158 struct gpio_dt_spec power_gpio ;
156159 struct gpio_dt_spec reset_gpio ;
160+ struct gpio_dt_spec wake_gpio ;
157161 uint16_t power_pulse_duration_ms ;
158162 uint16_t reset_pulse_duration_ms ;
159163 uint16_t startup_time_ms ;
@@ -195,6 +199,8 @@ static const char *modem_cellular_state_str(enum modem_cellular_state state)
195199 return "run dial script" ;
196200 case MODEM_CELLULAR_STATE_CARRIER_ON :
197201 return "carrier on" ;
202+ case MODEM_CELLULAR_STATE_DORMANT :
203+ return "dormant" ;
198204 case MODEM_CELLULAR_STATE_INIT_POWER_OFF :
199205 return "init power off" ;
200206 case MODEM_CELLULAR_STATE_RUN_SHUTDOWN_SCRIPT :
@@ -235,6 +241,8 @@ static const char *modem_cellular_event_str(enum modem_cellular_event event)
235241 return "bus opened" ;
236242 case MODEM_CELLULAR_EVENT_BUS_CLOSED :
237243 return "bus closed" ;
244+ case MODEM_CELLULAR_EVENT_PPP_DEAD :
245+ return "ppp dead" ;
238246 }
239247
240248 return "" ;
@@ -517,7 +525,7 @@ MODEM_CHAT_MATCHES_DEFINE(dial_abort_matches,
517525 MODEM_CHAT_MATCH ("NO CARRIER" , "" , NULL ),
518526 MODEM_CHAT_MATCH ("NO DIALTONE" , "" , NULL ));
519527
520- #if DT_HAS_COMPAT_STATUS_OKAY (swir_hl7800 ) || DT_HAS_COMPAT_STATUS_OKAY (sqn_gm02s )
528+ #if DT_HAS_COMPAT_STATUS_OKAY (swir_hl7800 ) || DT_HAS_COMPAT_STATUS_OKAY (sqn_gm02s ) || DT_HAS_COMPAT_STATUS_OKAY ( simcom_a76xx )
521529MODEM_CHAT_MATCH_DEFINE (connect_match , "CONNECT" , "" , NULL );
522530#endif
523531
@@ -599,11 +607,17 @@ static int modem_cellular_on_idle_state_enter(struct modem_cellular_data *data)
599607 const struct modem_cellular_config * config =
600608 (const struct modem_cellular_config * )data -> dev -> config ;
601609
610+ if (modem_cellular_gpio_is_enabled (& config -> wake_gpio )) {
611+ gpio_pin_set_dt (& config -> wake_gpio , 0 );
612+ }
613+
602614 if (modem_cellular_gpio_is_enabled (& config -> reset_gpio )) {
603615 gpio_pin_set_dt (& config -> reset_gpio , 1 );
604616 }
605617
606618 modem_cellular_notify_user_pipes_disconnected (data );
619+ net_if_carrier_off (modem_ppp_get_iface (data -> ppp ));
620+ net_if_dormant_off (modem_ppp_get_iface (data -> ppp ));
607621 modem_chat_release (& data -> chat );
608622 modem_ppp_release (data -> ppp );
609623 modem_cmux_release (& data -> cmux );
@@ -662,6 +676,10 @@ static int modem_cellular_on_idle_state_leave(struct modem_cellular_data *data)
662676 gpio_pin_set_dt (& config -> reset_gpio , 0 );
663677 }
664678
679+ if (modem_cellular_gpio_is_enabled (& config -> wake_gpio )) {
680+ gpio_pin_set_dt (& config -> wake_gpio , 1 );
681+ }
682+
665683 return 0 ;
666684}
667685
@@ -670,6 +688,10 @@ static int modem_cellular_on_reset_pulse_state_enter(struct modem_cellular_data
670688 const struct modem_cellular_config * config =
671689 (const struct modem_cellular_config * )data -> dev -> config ;
672690
691+ if (modem_cellular_gpio_is_enabled (& config -> wake_gpio )) {
692+ gpio_pin_set_dt (& config -> wake_gpio , 0 );
693+ }
694+
673695 gpio_pin_set_dt (& config -> reset_gpio , 1 );
674696 modem_cellular_start_timer (data , K_MSEC (config -> reset_pulse_duration_ms ));
675697 return 0 ;
@@ -698,6 +720,11 @@ static int modem_cellular_on_reset_pulse_state_leave(struct modem_cellular_data
698720 (const struct modem_cellular_config * )data -> dev -> config ;
699721
700722 gpio_pin_set_dt (& config -> reset_gpio , 0 );
723+
724+ if (modem_cellular_gpio_is_enabled (& config -> wake_gpio )) {
725+ gpio_pin_set_dt (& config -> wake_gpio , 1 );
726+ }
727+
701728 modem_cellular_stop_timer (data );
702729 return 0 ;
703730}
@@ -1003,7 +1030,9 @@ static void modem_cellular_run_dial_script_event_handler(struct modem_cellular_d
10031030 modem_chat_attach (& data -> chat , data -> dlci1_pipe );
10041031 modem_chat_run_script_async (& data -> chat , config -> dial_chat_script );
10051032 break ;
1006-
1033+ case MODEM_CELLULAR_EVENT_SCRIPT_FAILED :
1034+ modem_cellular_start_timer (data , MODEM_CELLULAR_PERIODIC_SCRIPT_TIMEOUT );
1035+ break ;
10071036 case MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS :
10081037 modem_cellular_enter_state (data , MODEM_CELLULAR_STATE_AWAIT_REGISTERED );
10091038 break ;
@@ -1092,7 +1121,7 @@ static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *
10921121 break ;
10931122
10941123 case MODEM_CELLULAR_EVENT_DEREGISTERED :
1095- modem_cellular_enter_state (data , MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT );
1124+ modem_cellular_enter_state (data , MODEM_CELLULAR_STATE_DORMANT );
10961125 break ;
10971126
10981127 case MODEM_CELLULAR_EVENT_SUSPEND :
@@ -1107,9 +1136,37 @@ static void modem_cellular_carrier_on_event_handler(struct modem_cellular_data *
11071136static int modem_cellular_on_carrier_on_state_leave (struct modem_cellular_data * data )
11081137{
11091138 modem_cellular_stop_timer (data );
1139+
1140+ return 0 ;
1141+ }
1142+
1143+ static int modem_cellular_on_dormant_state_enter (struct modem_cellular_data * data )
1144+ {
1145+ net_if_dormant_on (modem_ppp_get_iface (data -> ppp ));
1146+
1147+ return 0 ;
1148+ }
1149+
1150+ static void modem_cellular_dormant_event_handler (struct modem_cellular_data * data ,
1151+ enum modem_cellular_event evt )
1152+ {
1153+ switch (evt ) {
1154+ case MODEM_CELLULAR_EVENT_PPP_DEAD :
1155+ modem_cellular_enter_state (data , MODEM_CELLULAR_STATE_RUN_DIAL_SCRIPT );
1156+ break ;
1157+
1158+ default :
1159+ break ;
1160+ }
1161+ }
1162+
1163+ static int modem_cellular_on_dormant_state_leave (struct modem_cellular_data * data )
1164+ {
11101165 net_if_carrier_off (modem_ppp_get_iface (data -> ppp ));
11111166 modem_chat_release (& data -> chat );
11121167 modem_ppp_release (data -> ppp );
1168+ net_if_dormant_off (modem_ppp_get_iface (data -> ppp ));
1169+
11131170 return 0 ;
11141171}
11151172
@@ -1298,6 +1355,10 @@ static int modem_cellular_on_state_enter(struct modem_cellular_data *data)
12981355 ret = modem_cellular_on_carrier_on_state_enter (data );
12991356 break ;
13001357
1358+ case MODEM_CELLULAR_STATE_DORMANT :
1359+ ret = modem_cellular_on_dormant_state_enter (data );
1360+ break ;
1361+
13011362 case MODEM_CELLULAR_STATE_INIT_POWER_OFF :
13021363 ret = modem_cellular_on_init_power_off_state_enter (data );
13031364 break ;
@@ -1359,6 +1420,10 @@ static int modem_cellular_on_state_leave(struct modem_cellular_data *data)
13591420 ret = modem_cellular_on_carrier_on_state_leave (data );
13601421 break ;
13611422
1423+ case MODEM_CELLULAR_STATE_DORMANT :
1424+ ret = modem_cellular_on_dormant_state_leave (data );
1425+ break ;
1426+
13621427 case MODEM_CELLULAR_STATE_INIT_POWER_OFF :
13631428 ret = modem_cellular_on_init_power_off_state_leave (data );
13641429 break ;
@@ -1458,6 +1523,10 @@ static void modem_cellular_event_handler(struct modem_cellular_data *data,
14581523 modem_cellular_carrier_on_event_handler (data , evt );
14591524 break ;
14601525
1526+ case MODEM_CELLULAR_STATE_DORMANT :
1527+ modem_cellular_dormant_event_handler (data , evt );
1528+ break ;
1529+
14611530 case MODEM_CELLULAR_STATE_INIT_POWER_OFF :
14621531 modem_cellular_init_power_off_event_handler (data , evt );
14631532 break ;
@@ -1701,6 +1770,22 @@ static int modem_cellular_pm_action(const struct device *dev, enum pm_device_act
17011770}
17021771#endif /* CONFIG_PM_DEVICE */
17031772
1773+ static void net_mgmt_event_handler (struct net_mgmt_event_callback * cb , uint32_t mgmt_event ,
1774+ struct net_if * iface )
1775+ {
1776+ struct modem_cellular_data * data =
1777+ CONTAINER_OF (cb , struct modem_cellular_data , net_mgmt_event_callback );
1778+
1779+ switch (mgmt_event ) {
1780+ case NET_EVENT_PPP_PHASE_DEAD :
1781+ modem_cellular_delegate_event (data , MODEM_CELLULAR_EVENT_PPP_DEAD );
1782+ break ;
1783+
1784+ default :
1785+ break ;
1786+ }
1787+ }
1788+
17041789static int modem_cellular_init (const struct device * dev )
17051790{
17061791 struct modem_cellular_data * data = (struct modem_cellular_data * )dev -> data ;
@@ -1715,6 +1800,10 @@ static int modem_cellular_init(const struct device *dev)
17151800
17161801 k_sem_init (& data -> suspended_sem , 0 , 1 );
17171802
1803+ if (modem_cellular_gpio_is_enabled (& config -> wake_gpio )) {
1804+ gpio_pin_configure_dt (& config -> wake_gpio , GPIO_OUTPUT_INACTIVE );
1805+ }
1806+
17181807 if (modem_cellular_gpio_is_enabled (& config -> power_gpio )) {
17191808 gpio_pin_configure_dt (& config -> power_gpio , GPIO_OUTPUT_INACTIVE );
17201809 }
@@ -1805,6 +1894,13 @@ static int modem_cellular_init(const struct device *dev)
18051894 modem_chat_init (& data -> chat , & chat_config );
18061895 }
18071896
1897+ {
1898+ net_mgmt_init_event_callback (& data -> net_mgmt_event_callback , net_mgmt_event_handler ,
1899+ NET_EVENT_PPP_PHASE_DEAD );
1900+ net_mgmt_add_event_callback (& data -> net_mgmt_event_callback );
1901+ }
1902+
1903+
18081904#ifndef CONFIG_PM_DEVICE
18091905 modem_cellular_delegate_event (data , MODEM_CELLULAR_EVENT_RESUME );
18101906#else
@@ -1970,6 +2066,59 @@ MODEM_CHAT_SCRIPT_DEFINE(simcom_sim7080_periodic_chat_script,
19702066 modem_cellular_chat_callback_handler , 4 );
19712067#endif
19722068
2069+ #if DT_HAS_COMPAT_STATUS_OKAY (simcom_a76xx )
2070+ MODEM_CHAT_SCRIPT_CMDS_DEFINE (simcom_a76xx_init_chat_script_cmds ,
2071+ MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 100 ),
2072+ MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 100 ),
2073+ MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 100 ),
2074+ MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 100 ),
2075+ MODEM_CHAT_SCRIPT_CMD_RESP ("ATE0" , ok_match ),
2076+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CFUN=4" , ok_match ),
2077+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CMEE=1" , ok_match ),
2078+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CREG=1" , ok_match ),
2079+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGREG=1" , ok_match ),
2080+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CEREG=1" , ok_match ),
2081+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CREG?" , ok_match ),
2082+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CEREG?" , ok_match ),
2083+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGREG?" , ok_match ),
2084+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGSN" , imei_match ),
2085+ MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
2086+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGMM" , cgmm_match ),
2087+ MODEM_CHAT_SCRIPT_CMD_RESP ("" , ok_match ),
2088+ MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT+CMUX=0,0,5,127" , 300 ));
2089+
2090+ MODEM_CHAT_SCRIPT_DEFINE (simcom_a76xx_init_chat_script , simcom_a76xx_init_chat_script_cmds ,
2091+ abort_matches , modem_cellular_chat_callback_handler , 10 );
2092+
2093+ MODEM_CHAT_SCRIPT_CMDS_DEFINE (simcom_a76xx_dial_chat_script_cmds ,
2094+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGDCONT=1,\"IP\","
2095+ "\"" CONFIG_MODEM_CELLULAR_APN "\"" ,
2096+ ok_match ),
2097+ MODEM_CHAT_SCRIPT_CMD_RESP_MULT ("AT+CGACT=0,1" , allow_match ),
2098+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CFUN=1" , ok_match ),
2099+ MODEM_CHAT_SCRIPT_CMD_RESP ("ATD*99***1#" , connect_match ), );
2100+
2101+ MODEM_CHAT_SCRIPT_DEFINE (simcom_a76xx_dial_chat_script , simcom_a76xx_dial_chat_script_cmds ,
2102+ dial_abort_matches , modem_cellular_chat_callback_handler , 10 );
2103+
2104+ MODEM_CHAT_SCRIPT_CMDS_DEFINE (simcom_a76xx_periodic_chat_script_cmds ,
2105+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CREG?" , ok_match ),
2106+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CEREG?" , ok_match ),
2107+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CGREG?" , ok_match ));
2108+
2109+ MODEM_CHAT_SCRIPT_DEFINE (simcom_a76xx_periodic_chat_script ,
2110+ simcom_a76xx_periodic_chat_script_cmds , abort_matches ,
2111+ modem_cellular_chat_callback_handler , 4 );
2112+
2113+ MODEM_CHAT_SCRIPT_CMDS_DEFINE (simcom_a76xx_shutdown_chat_script_cmds ,
2114+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CPOF" , ok_match ));
2115+
2116+ MODEM_CHAT_SCRIPT_DEFINE (simcom_a76xx_shutdown_chat_script ,
2117+ simcom_a76xx_shutdown_chat_script_cmds , abort_matches ,
2118+ modem_cellular_chat_callback_handler , 15 );
2119+
2120+ #endif
2121+
19732122#if DT_HAS_COMPAT_STATUS_OKAY (u_blox_sara_r4 )
19742123MODEM_CHAT_SCRIPT_CMDS_DEFINE (u_blox_sara_r4_init_chat_script_cmds ,
19752124 MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 100 ),
@@ -2127,10 +2276,16 @@ MODEM_CHAT_SCRIPT_DEFINE(u_blox_lara_r6_periodic_chat_script,
21272276
21282277#if DT_HAS_COMPAT_STATUS_OKAY (swir_hl7800 )
21292278MODEM_CHAT_SCRIPT_CMDS_DEFINE (swir_hl7800_init_chat_script_cmds ,
2130- MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 100 ),
2131- MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 100 ),
2132- MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 100 ),
2133- MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 100 ),
2279+ MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 1000 ),
2280+ MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 1000 ),
2281+ MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 1000 ),
2282+ MODEM_CHAT_SCRIPT_CMD_RESP_NONE ("AT" , 1000 ),
2283+ /* Turn off sleep mode */
2284+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+KSLEEP=2" , ok_match ),
2285+ /* Turn off PSM */
2286+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CPSMS=0" , ok_match ),
2287+ /* Turn off eDRX */
2288+ MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CEDRXS=0" , ok_match ),
21342289 MODEM_CHAT_SCRIPT_CMD_RESP ("ATE0" , ok_match ),
21352290 MODEM_CHAT_SCRIPT_CMD_RESP ("AT+CFUN=1" , ok_match ),
21362291 MODEM_CHAT_SCRIPT_CMD_RESP_MULT ("AT+CGACT=0" , allow_match ),
@@ -2388,6 +2543,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script,
23882543 .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \
23892544 .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \
23902545 .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \
2546+ .wake_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_wake_gpios, {}), \
23912547 .power_pulse_duration_ms = (power_ms), \
23922548 .reset_pulse_duration_ms = (reset_ms), \
23932549 .startup_time_ms = (startup_ms), \
@@ -2466,6 +2622,26 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script,
24662622 &simcom_sim7080_dial_chat_script, \
24672623 &simcom_sim7080_periodic_chat_script, NULL)
24682624
2625+ #define MODEM_CELLULAR_DEVICE_SIMCOM_A76XX (inst ) \
2626+ MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
2627+ \
2628+ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \
2629+ .chat_delimiter = "\r", \
2630+ .chat_filter = "\n", \
2631+ .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \
2632+ }; \
2633+ \
2634+ MODEM_CELLULAR_DEFINE_AND_INIT_USER_PIPES(inst, \
2635+ (user_pipe_0, 3), \
2636+ (user_pipe_1, 4)) \
2637+ \
2638+ MODEM_CELLULAR_DEFINE_INSTANCE(inst, 500, 100, 15000, 5000, false, \
2639+ NULL, \
2640+ &simcom_a76xx_init_chat_script, \
2641+ &simcom_a76xx_dial_chat_script, \
2642+ &simcom_a76xx_periodic_chat_script, \
2643+ &simcom_a76xx_shutdown_chat_script)
2644+
24692645#define MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R4 (inst ) \
24702646 MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \
24712647 \
@@ -2629,6 +2805,10 @@ DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_QUECTEL_EG25_G)
26292805DT_INST_FOREACH_STATUS_OKAY (MODEM_CELLULAR_DEVICE_SIMCOM_SIM7080 )
26302806#undef DT_DRV_COMPAT
26312807
2808+ #define DT_DRV_COMPAT simcom_a76xx
2809+ DT_INST_FOREACH_STATUS_OKAY (MODEM_CELLULAR_DEVICE_SIMCOM_A76XX )
2810+ #undef DT_DRV_COMPAT
2811+
26322812#define DT_DRV_COMPAT u_blox_sara_r4
26332813DT_INST_FOREACH_STATUS_OKAY (MODEM_CELLULAR_DEVICE_U_BLOX_SARA_R4 )
26342814#undef DT_DRV_COMPAT
0 commit comments