MAC_AX_ERR_L0_PROMOTE_TO_L1 = 0x0010,
 
        /* L1 */
+       MAC_AX_ERR_L1_PREERR_DMAC = 0x999,
        MAC_AX_ERR_L1_ERR_DMAC = 0x1000,
        MAC_AX_ERR_L1_RESET_DISABLE_DMAC_DONE = 0x1001,
        MAC_AX_ERR_L1_RESET_RECOVERY_DONE = 0x1002,
        MAC_AX_ERR_L1_RCVY_EN = 0x0002,
        MAC_AX_ERR_L1_RCVY_STOP_REQ = 0x0003,
        MAC_AX_ERR_L1_RCVY_START_REQ = 0x0004,
+       MAC_AX_ERR_L1_RESET_START_DMAC = 0x000A,
        MAC_AX_ERR_L0_CFG_NOTIFY = 0x0010,
        MAC_AX_ERR_L0_CFG_DIS_NOTIFY = 0x0011,
        MAC_AX_ERR_L0_CFG_HANDSHAKE = 0x0012,
 
        SER_EV_NONE,
        SER_EV_STATE_IN,
        SER_EV_STATE_OUT,
+       SER_EV_L1_RESET_PREPARE, /* pre-M0 */
        SER_EV_L1_RESET, /* M1 */
        SER_EV_DO_RECOVERY, /* M3 */
        SER_EV_MAC_RESET_DONE, /* M5 */
        SER_EV_L2_RESET,
        SER_EV_L2_RECFG_DONE,
        SER_EV_L2_RECFG_TIMEOUT,
+       SER_EV_M1_TIMEOUT,
        SER_EV_M3_TIMEOUT,
        SER_EV_FW_M5_TIMEOUT,
        SER_EV_L0_RESET,
 
 enum ser_state {
        SER_IDLE_ST,
+       SER_L1_RESET_PRE_ST,
        SER_RESET_TRX_ST,
        SER_DO_HCI_ST,
        SER_L2_RESET_ST,
        return ret;
 }
 
+static void hal_send_post_m0_event(struct rtw89_ser *ser)
+{
+       struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser);
+
+       rtw89_mac_set_err_status(rtwdev, MAC_AX_ERR_L1_RESET_START_DMAC);
+}
+
 static void hal_send_m2_event(struct rtw89_ser *ser)
 {
        struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser);
                rtw89_hci_recovery_complete(rtwdev);
                clear_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags);
                break;
+       case SER_EV_L1_RESET_PREPARE:
+               ser_state_goto(ser, SER_L1_RESET_PRE_ST);
+               break;
        case SER_EV_L1_RESET:
                ser_state_goto(ser, SER_RESET_TRX_ST);
                break;
        }
 }
 
+static void ser_l1_reset_pre_st_hdl(struct rtw89_ser *ser, u8 evt)
+{
+       switch (evt) {
+       case SER_EV_STATE_IN:
+               ser->prehandle_l1 = true;
+               hal_send_post_m0_event(ser);
+               ser_set_alarm(ser, 1000, SER_EV_M1_TIMEOUT);
+               break;
+       case SER_EV_L1_RESET:
+               ser_state_goto(ser, SER_RESET_TRX_ST);
+               break;
+       case SER_EV_M1_TIMEOUT:
+               ser_state_goto(ser, SER_L2_RESET_ST);
+               break;
+       case SER_EV_STATE_OUT:
+               ser_del_alarm(ser);
+               break;
+       default:
+               break;
+       }
+}
+
 static void ser_reset_trx_st_hdl(struct rtw89_ser *ser, u8 evt)
 {
        struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser);
        {SER_EV_NONE, "SER_EV_NONE"},
        {SER_EV_STATE_IN, "SER_EV_STATE_IN"},
        {SER_EV_STATE_OUT, "SER_EV_STATE_OUT"},
-       {SER_EV_L1_RESET, "SER_EV_L1_RESET"},
+       {SER_EV_L1_RESET_PREPARE, "SER_EV_L1_RESET_PREPARE pre-m0"},
+       {SER_EV_L1_RESET, "SER_EV_L1_RESET m1"},
        {SER_EV_DO_RECOVERY, "SER_EV_DO_RECOVERY m3"},
        {SER_EV_MAC_RESET_DONE, "SER_EV_MAC_RESET_DONE m5"},
        {SER_EV_L2_RESET, "SER_EV_L2_RESET"},
        {SER_EV_L2_RECFG_DONE, "SER_EV_L2_RECFG_DONE"},
        {SER_EV_L2_RECFG_TIMEOUT, "SER_EV_L2_RECFG_TIMEOUT"},
+       {SER_EV_M1_TIMEOUT, "SER_EV_M1_TIMEOUT"},
        {SER_EV_M3_TIMEOUT, "SER_EV_M3_TIMEOUT"},
        {SER_EV_FW_M5_TIMEOUT, "SER_EV_FW_M5_TIMEOUT"},
        {SER_EV_L0_RESET, "SER_EV_L0_RESET"},
 
 static const struct state_ent ser_st_tbl[] = {
        {SER_IDLE_ST, "SER_IDLE_ST", ser_idle_st_hdl},
+       {SER_L1_RESET_PRE_ST, "SER_L1_RESET_PRE_ST", ser_l1_reset_pre_st_hdl},
        {SER_RESET_TRX_ST, "SER_RESET_TRX_ST", ser_reset_trx_st_hdl},
        {SER_DO_HCI_ST, "SER_DO_HCI_ST", ser_do_hci_st_hdl},
        {SER_L2_RESET_ST, "SER_L2_RESET_ST", ser_l2_reset_st_hdl}
        rtw89_info(rtwdev, "SER catches error: 0x%x\n", err);
 
        switch (err) {
+       case MAC_AX_ERR_L1_PREERR_DMAC: /* pre-M0 */
+               event = SER_EV_L1_RESET_PREPARE;
+               break;
        case MAC_AX_ERR_L1_ERR_DMAC:
        case MAC_AX_ERR_L0_PROMOTE_TO_L1:
                event = SER_EV_L1_RESET; /* M1 */