meta name='generator' content='cgit v1.2.2'/>
aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/net/bnx2x_link.c
blob: 32e79c359e8945795ad4a909245223fbcff07ac3 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
                                           














                                                                             

                                           






                            
 


                                                          
                                          





                                                                   

                                                             
                                                             

                                                             



                                                                       



































                                                                            

                                                           
                                                                          
                                     
                                                                           
                                                                  






















































                                                                            




                                                           





                                                      


                                                                    
 



                                                         




                                                              
 














                                                                      
                                                               

                                      
                                                                       
 











                                                                        
 











                                                                           






































                                                                             
                                                                 

                      
            






                                                                  
                                        



                                           
                                                  




                                            
                                                      





















































                                                                        



                                                            



                                                                 
                                               




                                                                     
                                                         




                                                                      

                                                         
                                                         

                                                          

                                                               




                                                                     
                                                






                                                         
                                             
 


                                                     
                                           
                                              













                                                                   
                                                 












                                                                           

                                                                    















































                                                                               
                                                 
















                                                                 







                                                                
                                                 



































                                                                           
                                                 

































                                                                        
                                              



















































































                                                                            
                                                              
                    
                                                               

                                                                            
                                                              
                    
                                                               

                                                      


                                                                
























                                                                   
                                                       













                                                                         
 










                                                               
                                                                             























                                                                         





















                                                                       
                                             




                                                                


                                                             
                                                        



                                                         
                                                                



                                                                  


















                                                                       















                                                                   
                                                                           

                      
 

                                                   
                                                   
                                                   




                                                                  

                                                   
                                                                   

                      
                                                                   










                                                                
                                                                    



                                                                        
 































































                                                                          
                                                                    


                                                                        
 



                                                                     
                                                            



















































































































                                                                            

                                                
 





































































                                                                               
                                                                   








                                                                   





                                                                              





                                                                   


                                                           


































                                                                               

                                                   











                                                                      
                                               















                                                                              


                                                                               
                                               














                                                                             
                                                 













                                                                             





                                                                
                                           









                                                                             
                                                




                                                                        





                                                                          




                                                                        
                                               
 




                                                                 
 






                                                                         

                                                            



                                      
                                                      




                                                                      

                                                                    








                                                                         
                                           


                                                                           









                                                                             

                                                                          
                                                    

                                                                              
                                                    

                                                                          


                                           


                                                                          
 





















                                                                          
                                                       

 
                                                                              
 
                                      
                                                             



                                                                  

                                                                      
                                   

                                                                      
                                   


                                                                      
                                
                           


                                                                      

                                  
                                                                     

                      
                                  
                
                                                                     

                      
                                                         
 
 
                                                                        
                                                       

                                      
                
                                                          



                                                        
                                                                      









                                                                    

 
                                                                             

                                      
                        
 
                                                      
                                              
 































                                                                                

 

                                                                      






















                                                                              
                                                    











                                                                               
                                           












                                                                              

                                                                       














                                                                        
                                                 








                                                                         


                                                                   
                                                     

                      
                                                                   
                                                     

                      



                                                                   
                                                       






                      
                                                              



                                                         


                                                  



                               
                                                                 
































                                                                   
                                                              




















                                                                               



                   
































                                                                              





                                                               

                                          

                         
                                               

                                                                         
                                                              



                                                         



                                                                  




































                                                                               
                                                                             
                                                   
                                                                              


                                                                      
                                                        
                                                                     
                                                              

                       
                                                                  


                                                                  



                                                                


































































                                                                               
                                                                


                                                          

                                      
                           


















                                                                            
                                                  






                                                                
                                                   







                                                                  
                                                    






                                                                  
                                                    











                                                                            
 


                                       
                                                     



                                                         
                                                     



                                                         
                                                     



                                                           
                                                     



                                                         
                                                     



                                                         
                                                     






                                                                            
                                       

                 



                                                                          









                                                                               




                                                             

                                                             



                                                                  

                                                                 

                                                                 
                                                               












                                                                            
                                                         

                                                                    
 
                                                         

                                                                    




                                                      
 
                                           
                                                       

                                                  






                                                                  












                                                                             
                                                                



                                      
                 

                          




                                                            




                                                                     





                                                                 
                                                       












                                                                             












































                                                                            
                                                         



                                                                               
                                                                               
                                                                               
                                                      

                                                 
                                                             

                                                 
                                                             






                                                           

                                                                    

















                                                                           

                                                                      

                                      
                                                                 






                                                                  



                                                           
















                                                                          
                              
 
                                                           

                                                          


                                                                 

                                                                      
 






                                                          
 
                                                           
                                                          


                                                                 

                                                                      

                                                                 

                                                                      






                                                                 

                                                                      

                                      
                                                                 

                              
                                                           





                                                                      
                                                                 







                                                          

                                                            


















                                                                            
                                                                 


                              
                                                                              





                                                         


                                                                   

                                                                










                                                                      
 







                                                                             








































































































                                                                              



                                                                       
                                                                    
                                                                     


































                                                                       



                                                    






                                                                
                                                                    






                                                            
                                                        





















                                                            
                                                                    





                                                            
                                                        














                                                                    

                                                                  
















                                                                              
                                                                         












                                                                             

 



                                                                              
 
                                          
                      
                                  
                                    
                                    




                                             
                                  
                                    
                                    



                                             
                                  
                                    
                                    



                                                        
                                  
                                    
                                    




                                                              
                                  
                                    
                                    







                                                                    
                                  
                                    
                                    


                                                        
                                           
                                             

                                             
 
 


















                                                                               



                                                                       
                                                                    




                                                                     



                                                              
                               






                                                              

                                                              
                                                        
 




                                                                    

                                               






                                                                               



                                                    

 


                                                                      

                
 



                                                                        
                                   










                                                  
                                    





                                                   


                                                                           
                                      

                    
                               
                                                                    
                                                                     
 









                                                           
                                                          






                                            
                                                          






                                      
                                                      







                                                          


                                                                         



                              

                                                                 

                                                                               
                                                                             

















                                                                             














                                                                           
                                                                    
























































































                                                                               


                                  
 


                       












                                                                        
 

                                                        

                                      

                                        





                                                                
                                                                               






                                            
 















                                                                             
                                                



                                                                       

                                                           








                                                                            
                                        
                      




                                                                                
















                                                                         


                 

                                                                  
                                                             

                                      









                                                                             



                                                                          










                                                                  


                         
                                        


                                                                   










                                                                
 

                                                                                                           


                       
                                                                     
                                                     


                                      
                                                                    
                              









                                                             
                                            
                                  
                                                    




                                                                     
                                                  
                                          
 
                                                         
 


                                                                
                                                           





























                                                                     






                                                                     
                                                                    







































                                                                           


















                                                                           






































                                                                               


                                                                

                     
                                                                    
                                                                     


                                                                                



                                                                              
                                                         
                                                                        

                                                     


                                                                     
                             



                                                           














                                                                              

         


                                                                     
 

















                                                                        
 
                  






                                                               
 














                                                                         

                                                                    



                                                                               

                                                                            






                                                                                




                                                                         



                                                                               


         



                                                               
                                                                    


                                                                     

                                                              

                                         

                                                              









                                                              
 
 




                                                                             
                                                                    





                                                                     
                                                        

















































                                                                           


                                                                 

                                      
                     
                                                                    

                                                                     





























                                                                            
                                     

                                                         






                                                               
                                                                    









                                                                     
 

                                                               

                                                              


                                                             

                                                        











                                                       



                                                             
 

















                                                                             
 























































                                                                           

                                                                  
































                                                     
                                      



                                          
                                                  
                            



                                          

                                                    


 
                                                               

                                                         

                                      
 
                                                  




                                                                  

                                             



                                                                   


                                                                 
                                                           

                                                      
                                                           








                                                                             
                                                                      

                                            
                                                                     

                                                   
                                                                   




                                              
                                                             


         








                                                                                
 
                                              
                                                                         



























                                                                              



























                                                                    
 


                                                                         


                                                           










                                                                               




























                                                                                
                                         








                                                                               


                                                                                

















                                                                             
                                                                      





















                                                                        










                                                                               

                         



                                                                    
                              









                                                                               


                                                              












































                                                                                
 




                                                                                





















                                                                            
                              










                                                                    
                                                           


                                                       















                                                                

                                           
                                                                  
                                                                        
                            


                                                                              
 



                                                         
                                                                    
                                             












                                                                        














                                                                            













                                                                            

                                                                 
                                                            

                                                                               
                                                      

                                                                           






                                                             

                                                                    



                                                                 
                                                                            






                                                                              





                                                                               
                                                                               
                                                                         



                                                               

                                                                             
                                                       
                                 
 



                                                                  
                                                                            
                         



                                                                    


                                                     


                                                              



                                                          



                                                                             





                                                                     


                                                                    
                                                                             

                                                                               
                                                                               







                                                                              






                                                                        
 






                                                                       
 



                                                              

                                             










                                                                   

                                                           
                 


                                              
 







                                                                             



                                                          


                                                                  



                                                          

                                                              
 

                                                                         


                                                         






                                                                               


                                                          

                                                                             
 










































































































































































                                                                                







                                                                              
                              
                 
                                                           
                                                            






                                                                               





                                                                             










                                                                                
 







                                                                               
 










































































                                                                                
 



                                                          
                                                                 





































































                                                                                
 



                                                                         














                                                                            
 


















                                                                              



                                                                 
                                                                    





















































































                                                                               

                                                              

                                                        







                                      
 
                                              
                                                                         
























                                                                            










                                                                           

                                                                              

                                                               


                                                           


                                                               

                                                                       


                                                                            

                                                                       







                                                                               


                                                                       

                                                                         

                                                                       

                                                                          

                                                                       

                                                                             

                                                                       

                                                                             
 
                                                                 







                                                                             
                                              
















                                                                               




                                                                       


















































                                                                               


                                                                             

                                                                                                                                                                                                                                                                              



































































                                                                                
 


















                                                                      
                              

                 


                                                           

                                              
 














                                                                       









                                                                               
                                                  

                                                                   














                                                                          
                                           



                                                         
                                                                    


                                             



                                                         



                                                                     





















                                                                          
 
                                                      

                                                               




                                                                         

                                                                 




                                                                      
                                                                 




                                                                      
 














                                                                              
                                                                       
                                                                          





















                                                                                

                                                                 




                                                                               
































                                                                                




                                                                      
                                                                 




                                                                      











                                                                               

                                 

 



































                                                                        
                                                               





                                                                               
                                                           
                                                            
                                                         
                                                 
                                                                       



                                                                    

                                                                       






                                                                               

                                                               













                                                                               
 





































                                                                                

                                 
                              





                                                                            






                                                                           































                                                                           
 






























                                                                              

                                                                          

                                                                      








                                                                           


































                                                                               



                                                          

                                                               









                                                                   



                                                             

                                                                   


















                                                                              

                                                                         

























                                                                              
                                                            





















                                                     


                                                                             
                         
                             
                           
                  


                                              
                        
 



                                                                       
                   

                                                                 





                                                   



                                                             

                                  


                                                   
                                                   
                                                   
                                                   

                                                                    
                                                   
                                                    

                                                                
                                                                    
                      
                                                  

                                                   





















                                                                  
                             





















                                                                          
                            



































                                                                              
                                                                         
                                          











                                                                              







                                                                               











































































































































                                                                               
                                                                
 

                                              
                  

                                                             

                                                                     







                                                                            

                                                     
                                                                          


                           







                                                                           






                                                                      
                                                     
                                              

                                                          
                                     
                                             



































                                                                             
                                                      










                                                           

                                                                     
 




















                                                                
                                              
                                              
                                                             






                                                                   




                                                           




                                                                             
 
                                                         
 

                                                                                
                                                                    

                          
                                                                      
                                                                      
                                                                      
                                                          

                                                                              
                                                                   

         

                                                       

                                                                   


                                                       








                                                                     
                



                                                                
                              



                                   
                                               

                                       














                                                                         
 


                                               
                                                       
                                                                        


                                          

                                                             



                                                                              



                                                                            
                                                                           











                                                            
                                                       















                                                                            
 


                                               
                                                       









                                                            
 
                                                            
 


                                              
                                                       










                                                            
 
                                                                 

                                                                 


                                               
                                                       























                                                                 
 
                                                                       


                         






                                                                       
                                                                  



















                                                                       
                 
                                                                             

                                                    
                           




                                              








                                                                            



                                                                       
 

                                                    

                                                             



                                                                        
                                                                    
                                

























                                                                 
                                               




                                                           




                                                           

                                                                          






                                                                              









                                                                         

                                                                          



                                                                             















                                                                             
                        
                                      
                                                                 

                                                                         
                                                                 

                                                                         
                                                                   


















                                                                   




                                                            
 
                                                            
                                               











                                                           




                                                     














                                                                   
 


                                                   
                                                                  
                


                                                                 

                                                   



                                                              
                                                                 











                                                           
                   

                  
















                                                                        
                      


                                   
                         

                                                                 

                                                                      
 

                                                                      
                                                                       



                                                                             




                                                                    


                                                     
                                                                 
 
                                                            
                                                                            





                                                            
 

                                                                










                                                        
                                                              
 





                                                                          
 

                                                                       
                                                                      
                                                                      
                                                    
                                                         
 

                                                                       
 



                                                                             



                  



















                                                                         
                                                                       






















                                                                         
                                                                              




                                                                                
                                                        
                                          


                                                                        
























                                                                               
                                                

































                                                                               


                                                                      
                               




                                                              
                                                                    

                  




                                      
                                     
                                                                         











                                                                         
                                                                       













                                                                     
                                                                         










                                                                                
                                                                      



                                                                        

         


                 





                                                                      
 






                                                                               
                                      






                                                                            
                                                                 













                                                                              






                                                                       




                                                          
                                                      












                                                                               





                                                                



                                                                    


                                                                 
                      









                                                                              
                                                                      




























                                                                     
/* Copyright 2008-2009 Broadcom Corporation
 *
 * Unless you and Broadcom execute a separate written software license
 * agreement governing use of this software, this software is licensed to you
 * under the terms of the GNU General Public License version 2, available
 * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
 *
 * Notwithstanding the above, under no circumstances may you combine this
 * software in any way with any other Broadcom software provided under a
 * license other than the GPL, without Broadcom's express prior written
 * consent.
 *
 * Written by Yaniv Rosner
 *
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/ethtool.h>
#include <linux/mutex.h>

#include "bnx2x.h"

/********************************************************/
#define ETH_HLEN			14
#define ETH_OVREHEAD		(ETH_HLEN + 8)/* 8 for CRC + VLAN*/
#define ETH_MIN_PACKET_SIZE		60
#define ETH_MAX_PACKET_SIZE		1500
#define ETH_MAX_JUMBO_PACKET_SIZE	9600
#define MDIO_ACCESS_TIMEOUT		1000
#define BMAC_CONTROL_RX_ENABLE	2

/***********************************************************/
/*			Shortcut definitions		   */
/***********************************************************/

#define NIG_LATCH_BC_ENABLE_MI_INT 0

#define NIG_STATUS_EMAC0_MI_INT \
		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT
#define NIG_STATUS_XGXS0_LINK10G \
		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
#define NIG_STATUS_XGXS0_LINK_STATUS \
		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS
#define NIG_STATUS_XGXS0_LINK_STATUS_SIZE \
		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE
#define NIG_STATUS_SERDES0_LINK_STATUS \
		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS
#define NIG_MASK_MI_INT \
		NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT
#define NIG_MASK_XGXS0_LINK10G \
		NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G
#define NIG_MASK_XGXS0_LINK_STATUS \
		NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS
#define NIG_MASK_SERDES0_LINK_STATUS \
		NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS

#define MDIO_AN_CL73_OR_37_COMPLETE \
		(MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | \
		 MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE)

#define XGXS_RESET_BITS \
	(MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW |   \
	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ |      \
	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN |    \
	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD | \
	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB)

#define SERDES_RESET_BITS \
	(MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW | \
	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ |    \
	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN |  \
	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD)

#define AUTONEG_CL37		SHARED_HW_CFG_AN_ENABLE_CL37
#define AUTONEG_CL73		SHARED_HW_CFG_AN_ENABLE_CL73
#define AUTONEG_BAM 		SHARED_HW_CFG_AN_ENABLE_BAM
#define AUTONEG_PARALLEL \
				SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
#define AUTONEG_SGMII_FIBER_AUTODET \
				SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
#define AUTONEG_REMOTE_PHY	SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY

#define GP_STATUS_PAUSE_RSOLUTION_TXSIDE \
			MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE
#define GP_STATUS_PAUSE_RSOLUTION_RXSIDE \
			MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE
#define GP_STATUS_SPEED_MASK \
			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK
#define GP_STATUS_10M	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M
#define GP_STATUS_100M	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M
#define GP_STATUS_1G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G
#define GP_STATUS_2_5G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G
#define GP_STATUS_5G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G
#define GP_STATUS_6G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G
#define GP_STATUS_10G_HIG \
			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
#define GP_STATUS_10G_CX4 \
			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
#define GP_STATUS_12G_HIG \
			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG
#define GP_STATUS_12_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G
#define GP_STATUS_13G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G
#define GP_STATUS_15G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G
#define GP_STATUS_16G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G
#define GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
#define GP_STATUS_10G_KX4 \
			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4

#define LINK_10THD			LINK_STATUS_SPEED_AND_DUPLEX_10THD
#define LINK_10TFD			LINK_STATUS_SPEED_AND_DUPLEX_10TFD
#define LINK_100TXHD		LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
#define LINK_100T4			LINK_STATUS_SPEED_AND_DUPLEX_100T4
#define LINK_100TXFD		LINK_STATUS_SPEED_AND_DUPLEX_100TXFD
#define LINK_1000THD		LINK_STATUS_SPEED_AND_DUPLEX_1000THD
#define LINK_1000TFD		LINK_STATUS_SPEED_AND_DUPLEX_1000TFD
#define LINK_1000XFD		LINK_STATUS_SPEED_AND_DUPLEX_1000XFD
#define LINK_2500THD		LINK_STATUS_SPEED_AND_DUPLEX_2500THD
#define LINK_2500TFD		LINK_STATUS_SPEED_AND_DUPLEX_2500TFD
#define LINK_2500XFD		LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
#define LINK_10GTFD			LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
#define LINK_10GXFD			LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
#define LINK_12GTFD			LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
#define LINK_12GXFD			LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
#define LINK_12_5GTFD		LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
#define LINK_12_5GXFD		LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
#define LINK_13GTFD			LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
#define LINK_13GXFD			LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
#define LINK_15GTFD			LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
#define LINK_15GXFD			LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
#define LINK_16GTFD			LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
#define LINK_16GXFD			LINK_STATUS_SPEED_AND_DUPLEX_16GXFD

#define PHY_XGXS_FLAG			0x1
#define PHY_SGMII_FLAG			0x2
#define PHY_SERDES_FLAG			0x4

/* */
#define SFP_EEPROM_CON_TYPE_ADDR		0x2
	#define SFP_EEPROM_CON_TYPE_VAL_LC 		0x7
	#define SFP_EEPROM_CON_TYPE_VAL_COPPER	0x21


#define SFP_EEPROM_COMP_CODE_ADDR		0x3
	#define SFP_EEPROM_COMP_CODE_SR_MASK	(1<<4)
	#define SFP_EEPROM_COMP_CODE_LR_MASK	(1<<5)
	#define SFP_EEPROM_COMP_CODE_LRM_MASK	(1<<6)

#define SFP_EEPROM_FC_TX_TECH_ADDR		0x8
	#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4
	#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE	 0x8

#define SFP_EEPROM_OPTIONS_ADDR 		0x40
	#define SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK 0x1
#define SFP_EEPROM_OPTIONS_SIZE 		2

#define EDC_MODE_LINEAR	 			0x0022
#define EDC_MODE_LIMITING	 			0x0044
#define EDC_MODE_PASSIVE_DAC 			0x0055



/**********************************************************/
/*                     INTERFACE                          */
/**********************************************************/
#define CL45_WR_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
	bnx2x_cl45_write(_bp, _port, 0, _phy_addr, \
		DEFAULT_PHY_DEV_ADDR, \
		(_bank + (_addr & 0xf)), \
		_val)

#define CL45_RD_OVER_CL22(_bp, _port, _phy_addr, _bank, _addr, _val) \
	bnx2x_cl45_read(_bp, _port, 0, _phy_addr, \
		DEFAULT_PHY_DEV_ADDR, \
		(_bank + (_addr & 0xf)), \
		_val)

static void bnx2x_set_serdes_access(struct link_params *params)
{
	struct bnx2x *bp = params->bp;
	u32 emac_base = (params->port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;

	/* Set Clause 22 */
	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + params->port*0x10, 1);
	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
	udelay(500);
	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
	udelay(500);
	 /* Set Clause 45 */
	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + params->port*0x10, 0);
}
static void bnx2x_set_phy_mdio(struct link_params *params, u8 phy_flags)
{
	struct bnx2x *bp = params->bp;

	if (phy_flags & PHY_XGXS_FLAG) {
		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
			   params->port*0x18, 0);
		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
			   DEFAULT_PHY_DEV_ADDR);
	} else {
		bnx2x_set_serdes_access(params);

		REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD +
			   params->port*0x10,
			   DEFAULT_PHY_DEV_ADDR);
	}
}

static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
{
	u32 val = REG_RD(bp, reg);

	val |= bits;
	REG_WR(bp, reg, val);
	return val;
}

static u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
{
	u32 val = REG_RD(bp, reg);

	val &= ~bits;
	REG_WR(bp, reg, val);
	return val;
}

static void bnx2x_emac_init(struct link_params *params,
			   struct link_vars *vars)
{
	/* reset and unreset the emac core */
	struct bnx2x *bp = params->bp;
	u8 port = params->port;
	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
	u32 val;
	u16 timeout;

	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
		   (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
	udelay(5);
	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
		   (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));

	/* init emac - use read-modify-write */
	/* self clear reset */
	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
	EMAC_WR(bp, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));

	timeout = 200;
	do {
		val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
		DP(NETIF_MSG_LINK, "EMAC reset reg is %u\n", val);
		if (!timeout) {
			DP(NETIF_MSG_LINK, "EMAC timeout!\n");
			return;
		}
		timeout--;
	} while (val & EMAC_MODE_RESET);

	/* Set mac address */
	val = ((params->mac_addr[0] << 8) |
		params->mac_addr[1]);
	EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH, val);

	val = ((params->mac_addr[2] << 24) |
	       (params->mac_addr[3] << 16) |
	       (params->mac_addr[4] << 8) |
		params->mac_addr[5]);
	EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + 4, val);
}

static u8 bnx2x_emac_enable(struct link_params *params,
			  struct link_vars *vars, u8 lb)
{
	struct bnx2x *bp = params->bp;
	u8 port = params->port;
	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
	u32 val;

	DP(NETIF_MSG_LINK, "enabling EMAC\n");

	/* enable emac and not bmac */
	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);

	/* for paladium */
	if (CHIP_REV_IS_EMUL(bp)) {
		/* Use lane 1 (of lanes 0-3) */
		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
			    port*4, 1);
	}
	/* for fpga */
	else

	if (CHIP_REV_IS_FPGA(bp)) {
		/* Use lane 1 (of lanes 0-3) */
		DP(NETIF_MSG_LINK, "bnx2x_emac_enable: Setting FPGA\n");

		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4,
			    0);
	} else
	/* ASIC */
	if (vars->phy_flags & PHY_XGXS_FLAG) {
		u32 ser_lane = ((params->lane_config &
			    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
			    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);

		DP(NETIF_MSG_LINK, "XGXS\n");
		/* select the master lanes (out of 0-3) */
		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 +
			   port*4, ser_lane);
		/* select XGXS */
		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
			   port*4, 1);

	} else { /* SerDes */
		DP(NETIF_MSG_LINK, "SerDes\n");
		/* select SerDes */
		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
			   port*4, 0);
	}

	bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
		    EMAC_RX_MODE_RESET);
	bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
		    EMAC_TX_MODE_RESET);

	if (CHIP_REV_IS_SLOW(bp)) {
		/* config GMII mode */
		val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
		EMAC_WR(bp, EMAC_REG_EMAC_MODE,
			    (val | EMAC_MODE_PORT_GMII));
	} else { /* ASIC */
		/* pause enable/disable */
		bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
			       EMAC_RX_MODE_FLOW_EN);
		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
			bnx2x_bits_en(bp, emac_base +
				    EMAC_REG_EMAC_RX_MODE,
				    EMAC_RX_MODE_FLOW_EN);

		bnx2x_bits_dis(bp,  emac_base + EMAC_REG_EMAC_TX_MODE,
			     (EMAC_TX_MODE_EXT_PAUSE_EN |
			      EMAC_TX_MODE_FLOW_EN));
		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
			bnx2x_bits_en(bp, emac_base +
				    EMAC_REG_EMAC_TX_MODE,
				   (EMAC_TX_MODE_EXT_PAUSE_EN |
				    EMAC_TX_MODE_FLOW_EN));
	}

	/* KEEP_VLAN_TAG, promiscuous */
	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
	val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
	EMAC_WR(bp, EMAC_REG_EMAC_RX_MODE, val);

	/* Set Loopback */
	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
	if (lb)
		val |= 0x810;
	else
		val &= ~0x810;
	EMAC_WR(bp, EMAC_REG_EMAC_MODE, val);

	/* enable emac */
	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);

	/* enable emac for jumbo packets */
	EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE,
		(EMAC_RX_MTU_SIZE_JUMBO_ENA |
		 (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));

	/* strip CRC */
	REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);

	/* disable the NIG in/out to the bmac */
	REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x0);
	REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, 0x0);
	REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x0);

	/* enable the NIG in/out to the emac */
	REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
	val = 0;
	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
		val = 1;

	REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
	REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);

	if (CHIP_REV_IS_EMUL(bp)) {
		/* take the BigMac out of reset */
		REG_WR(bp,
			   GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
			   (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));

		/* enable access for bmac registers */
		REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
	} else
		REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x0);

	vars->mac_type = MAC_TYPE_EMAC;
	return 0;
}



static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
			  u8 is_lb)
{
	struct bnx2x *bp = params->bp;
	u8 port = params->port;
	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
			       NIG_REG_INGRESS_BMAC0_MEM;
	u32 wb_data[2];
	u32 val;

	DP(NETIF_MSG_LINK, "Enabling BigMAC\n");
	/* reset and unreset the BigMac */
	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
	msleep(1);

	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));

	/* enable access for bmac registers */
	REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);

	/* XGXS control */
	wb_data[0] = 0x3c;
	wb_data[1] = 0;
	REG_WR_DMAE(bp, bmac_addr +
		      BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
		      wb_data, 2);

	/* tx MAC SA */
	wb_data[0] = ((params->mac_addr[2] << 24) |
		       (params->mac_addr[3] << 16) |
		       (params->mac_addr[4] << 8) |
			params->mac_addr[5]);
	wb_data[1] = ((params->mac_addr[0] << 8) |
			params->mac_addr[1]);
	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR,
		    wb_data, 2);

	/* tx control */
	val = 0xc0;
	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
		val |= 0x800000;
	wb_data[0] = val;
	wb_data[1] = 0;
	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL,
			wb_data, 2);

	/* mac control */
	val = 0x3;
	if (is_lb) {
		val |= 0x4;
		DP(NETIF_MSG_LINK, "enable bmac loopback\n");
	}
	wb_data[0] = val;
	wb_data[1] = 0;
	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
		    wb_data, 2);

	/* set rx mtu */
	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
	wb_data[1] = 0;
	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE,
			wb_data, 2);

	/* rx control set to don't strip crc */
	val = 0x14;
	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
		val |= 0x20;
	wb_data[0] = val;
	wb_data[1] = 0;
	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL,
			wb_data, 2);

	/* set tx mtu */
	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
	wb_data[1] = 0;
	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE,
			wb_data, 2);

	/* set cnt max size */
	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
	wb_data[1] = 0;
	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE,
		    wb_data, 2);

	/* configure safc */
	wb_data[0] = 0x1000200;
	wb_data[1] = 0;
	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
		    wb_data, 2);
	/* fix for emulation */
	if (CHIP_REV_IS_EMUL(bp)) {
		wb_data[0] = 0xf000;
		wb_data[1] = 0;
		REG_WR_DMAE(bp,
			    bmac_addr + BIGMAC_REGISTER_TX_PAUSE_THRESHOLD,
			    wb_data, 2);
	}

	REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
	REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
	val = 0;
	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
		val = 1;
	REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
	REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
	REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
	REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
	REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
	REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);

	vars->mac_type = MAC_TYPE_BMAC;
	return 0;
}

static void bnx2x_phy_deassert(struct link_params *params, u8 phy_flags)
{
	struct bnx2x *bp = params->bp;
	u32 val;

	if (phy_flags & PHY_XGXS_FLAG) {
		DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:XGXS\n");
		val = XGXS_RESET_BITS;

	} else { /* SerDes */
		DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:SerDes\n");
		val = SERDES_RESET_BITS;
	}

	val = val << (params->port*16);

	/* reset and unreset the SerDes/XGXS */
	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
		    val);
	udelay(500);
	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET,
		    val);
	bnx2x_set_phy_mdio(params, phy_flags);
}

void bnx2x_link_status_update(struct link_params *params,
			    struct link_vars   *vars)
{
	struct bnx2x *bp = params->bp;
	u8 link_10g;
	u8 port = params->port;

	if (params->switch_cfg ==  SWITCH_CFG_1G)
		vars->phy_flags = PHY_SERDES_FLAG;
	else
		vars->phy_flags = PHY_XGXS_FLAG;
	vars->link_status = REG_RD(bp, params->shmem_base +
					  offsetof(struct shmem_region,
					   port_mb[port].link_status));

	vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);

	if (vars->link_up) {
		DP(NETIF_MSG_LINK, "phy link up\n");

		vars->phy_link_up = 1;
		vars->duplex = DUPLEX_FULL;
		switch (vars->link_status &
					LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
			case LINK_10THD:
				vars->duplex = DUPLEX_HALF;
				/* fall thru */
			case LINK_10TFD:
				vars->line_speed = SPEED_10;
				break;

			case LINK_100TXHD:
				vars->duplex = DUPLEX_HALF;
				/* fall thru */
			case LINK_100T4:
			case LINK_100TXFD:
				vars->line_speed = SPEED_100;
				break;

			case LINK_1000THD:
				vars->duplex = DUPLEX_HALF;
				/* fall thru */
			case LINK_1000TFD:
				vars->line_speed = SPEED_1000;
				break;

			case LINK_2500THD:
				vars->duplex = DUPLEX_HALF;
				/* fall thru */
			case LINK_2500TFD:
				vars->line_speed = SPEED_2500;
				break;

			case LINK_10GTFD:
				vars->line_speed = SPEED_10000;
				break;

			case LINK_12GTFD:
				vars->line_speed = SPEED_12000;
				break;

			case LINK_12_5GTFD:
				vars->line_speed = SPEED_12500;
				break;

			case LINK_13GTFD:
				vars->line_speed = SPEED_13000;
				break;

			case LINK_15GTFD:
				vars->line_speed = SPEED_15000;
				break;

			case LINK_16GTFD:
				vars->line_speed = SPEED_16000;
				break;

			default:
				break;
		}

		if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
			vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
		else
			vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_TX;

		if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
			vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
		else
			vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_RX;

		if (vars->phy_flags & PHY_XGXS_FLAG) {
			if (vars->line_speed &&
			    ((vars->line_speed == SPEED_10) ||
			     (vars->line_speed == SPEED_100))) {
				vars->phy_flags |= PHY_SGMII_FLAG;
			} else {
				vars->phy_flags &= ~PHY_SGMII_FLAG;
			}
		}

		/* anything 10 and over uses the bmac */
		link_10g = ((vars->line_speed == SPEED_10000) ||
			    (vars->line_speed == SPEED_12000) ||
			    (vars->line_speed == SPEED_12500) ||
			    (vars->line_speed == SPEED_13000) ||
			    (vars->line_speed == SPEED_15000) ||
			    (vars->line_speed == SPEED_16000));
		if (link_10g)
			vars->mac_type = MAC_TYPE_BMAC;
		else
			vars->mac_type = MAC_TYPE_EMAC;

	} else { /* link down */
		DP(NETIF_MSG_LINK, "phy link down\n");

		vars->phy_link_up = 0;

		vars->line_speed = 0;
		vars->duplex = DUPLEX_FULL;
		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;

		/* indicate no mac active */
		vars->mac_type = MAC_TYPE_NONE;
	}

	DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x\n",
		 vars->link_status, vars->phy_link_up);
	DP(NETIF_MSG_LINK, "line_speed %x  duplex %x  flow_ctrl 0x%x\n",
		 vars->line_speed, vars->duplex, vars->flow_ctrl);
}

static void bnx2x_update_mng(struct link_params *params, u32 link_status)
{
	struct bnx2x *bp = params->bp;

	REG_WR(bp, params->shmem_base +
		   offsetof(struct shmem_region,
			    port_mb[params->port].link_status),
			link_status);
}

static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
{
	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
		NIG_REG_INGRESS_BMAC0_MEM;
	u32 wb_data[2];
	u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);

	/* Only if the bmac is out of reset */
	if (REG_RD(bp, MISC_REG_RESET_REG_2) &
			(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
	    nig_bmac_enable) {

		/* Clear Rx Enable bit in BMAC_CONTROL register */
		REG_RD_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
			    wb_data, 2);
		wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
		REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
			    wb_data, 2);

		msleep(1);
	}
}

static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
			 u32 line_speed)
{
	struct bnx2x *bp = params->bp;
	u8 port = params->port;
	u32 init_crd, crd;
	u32 count = 1000;

	/* disable port */
	REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1);

	/* wait for init credit */
	init_crd = REG_RD(bp, PBF_REG_P0_INIT_CRD + port*4);
	crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
	DP(NETIF_MSG_LINK, "init_crd 0x%x  crd 0x%x\n", init_crd, crd);

	while ((init_crd != crd) && count) {
		msleep(5);

		crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
		count--;
	}
	crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
	if (init_crd != crd) {
		DP(NETIF_MSG_LINK, "BUG! init_crd 0x%x != crd 0x%x\n",
			  init_crd, crd);
		return -EINVAL;
	}

	if (flow_ctrl & BNX2X_FLOW_CTRL_RX ||
	    line_speed == SPEED_10 ||
	    line_speed == SPEED_100 ||
	    line_speed == SPEED_1000 ||
	    line_speed == SPEED_2500) {
		REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 1);
		/* update threshold */
		REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0);
		/* update init credit */
		init_crd = 778; 	/* (800-18-4) */

	} else {
		u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
			      ETH_OVREHEAD)/16;
		REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
		/* update threshold */
		REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh);
		/* update init credit */
		switch (line_speed) {
		case SPEED_10000:
			init_crd = thresh + 553 - 22;
			break;

		case SPEED_12000:
			init_crd = thresh + 664 - 22;
			break;

		case SPEED_13000:
			init_crd = thresh + 742 - 22;
			break;

		case SPEED_16000:
			init_crd = thresh + 778 - 22;
			break;
		default:
			DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
				  line_speed);
			return -EINVAL;
		}
	}
	REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, init_crd);
	DP(NETIF_MSG_LINK, "PBF updated to speed %d credit %d\n",
		 line_speed, init_crd);

	/* probe the credit changes */
	REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x1);
	msleep(5);
	REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x0);

	/* enable port */
	REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x0);
	return 0;
}

static u32 bnx2x_get_emac_base(struct bnx2x *bp, u32 ext_phy_type, u8 port)
{
	u32 emac_base;

	switch (ext_phy_type) {
	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
		/* All MDC/MDIO is directed through single EMAC */
		if (REG_RD(bp, NIG_REG_PORT_SWAP))
			emac_base = GRCBASE_EMAC0;
		else
			emac_base = GRCBASE_EMAC1;
		break;
	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
		emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
		break;
	default:
		emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
		break;
	}
	return emac_base;

}

u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type,
		  u8 phy_addr, u8 devad, u16 reg, u16 val)
{
	u32 tmp, saved_mode;
	u8 i, rc = 0;
	u32 mdio_ctrl = bnx2x_get_emac_base(bp, ext_phy_type, port);

	/* set clause 45 mode, slow down the MDIO clock to 2.5MHz
	 * (a value of 49==0x31) and make sure that the AUTO poll is off
	 */

	saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
	tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
			     EMAC_MDIO_MODE_CLOCK_CNT);
	tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
		(49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
	REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
	udelay(40);

	/* address */

	tmp = ((phy_addr << 21) | (devad << 16) | reg |
	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
	       EMAC_MDIO_COMM_START_BUSY);
	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);

	for (i = 0; i < 50; i++) {
		udelay(10);

		tmp = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
		if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
			udelay(5);
			break;
		}
	}
	if (tmp & EMAC_MDIO_COMM_START_BUSY) {
		DP(NETIF_MSG_LINK, "write phy register failed\n");
		rc = -EFAULT;
	} else {
		/* data */
		tmp = ((phy_addr << 21) | (devad << 16) | val |
		       EMAC_MDIO_COMM_COMMAND_WRITE_45 |
		       EMAC_MDIO_COMM_START_BUSY);
		REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);

		for (i = 0; i < 50; i++) {
			udelay(10);

			tmp = REG_RD(bp, mdio_ctrl +
					 EMAC_REG_EMAC_MDIO_COMM);
			if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
				udelay(5);
				break;
			}
		}
		if (tmp & EMAC_MDIO_COMM_START_BUSY) {
			DP(NETIF_MSG_LINK, "write phy register failed\n");
			rc = -EFAULT;
		}
	}

	/* Restore the saved mode */
	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);

	return rc;
}

u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type,
		 u8 phy_addr, u8 devad, u16 reg, u16 *ret_val)
{
	u32 val, saved_mode;
	u16 i;
	u8 rc = 0;

	u32 mdio_ctrl = bnx2x_get_emac_base(bp, ext_phy_type, port);
	/* set clause 45 mode, slow down the MDIO clock to 2.5MHz
	 * (a value of 49==0x31) and make sure that the AUTO poll is off
	 */

	saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
	val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL |
			     EMAC_MDIO_MODE_CLOCK_CNT));
	val |= (EMAC_MDIO_MODE_CLAUSE_45 |
		(49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
	REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
	udelay(40);

	/* address */
	val = ((phy_addr << 21) | (devad << 16) | reg |
	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
	       EMAC_MDIO_COMM_START_BUSY);
	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);

	for (i = 0; i < 50; i++) {
		udelay(10);

		val = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
		if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
			udelay(5);
			break;
		}
	}
	if (val & EMAC_MDIO_COMM_START_BUSY) {
		DP(NETIF_MSG_LINK, "read phy register failed\n");

		*ret_val = 0;
		rc = -EFAULT;

	} else {
		/* data */
		val = ((phy_addr << 21) | (devad << 16) |
		       EMAC_MDIO_COMM_COMMAND_READ_45 |
		       EMAC_MDIO_COMM_START_BUSY);
		REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);

		for (i = 0; i < 50; i++) {
			udelay(10);

			val = REG_RD(bp, mdio_ctrl +
					  EMAC_REG_EMAC_MDIO_COMM);
			if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
				*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
				break;
			}
		}
		if (val & EMAC_MDIO_COMM_START_BUSY) {
			DP(NETIF_MSG_LINK, "read phy register failed\n");

			*ret_val = 0;
			rc = -EFAULT;
		}
	}

	/* Restore the saved mode */
	REG_WR(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);

	return rc;
}

static void bnx2x_set_aer_mmd(struct link_params *params,
			    struct link_vars   *vars)
{
	struct bnx2x *bp = params->bp;
	u32 ser_lane;
	u16 offset;

	ser_lane = ((params->lane_config &
		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);

	offset = (vars->phy_flags & PHY_XGXS_FLAG) ?
		(params->phy_addr + ser_lane) : 0;

	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_AER_BLOCK,
			      MDIO_AER_BLOCK_AER_REG, 0x3800 + offset);
}

static void bnx2x_set_master_ln(struct link_params *params)
{
	struct bnx2x *bp = params->bp;
	u16 new_master_ln, ser_lane;
	ser_lane =  ((params->lane_config &
		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);

	/* set the master_ln for AN */
	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_XGXS_BLOCK2,
			      MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
			      &new_master_ln);

	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_XGXS_BLOCK2 ,
			      MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
			      (new_master_ln | ser_lane));
}

static u8 bnx2x_reset_unicore(struct link_params *params)
{
	struct bnx2x *bp = params->bp;
	u16 mii_control;
	u16 i;

	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_COMBO_IEEE0,
			      MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);

	/* reset the unicore */
	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_COMBO_IEEE0,
			      MDIO_COMBO_IEEE0_MII_CONTROL,
			      (mii_control |
			       MDIO_COMBO_IEEO_MII_CONTROL_RESET));
	if (params->switch_cfg == SWITCH_CFG_1G)
		bnx2x_set_serdes_access(params);

	/* wait for the reset to self clear */
	for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
		udelay(5);

		/* the reset erased the previous bank value */
		CL45_RD_OVER_CL22(bp, params->port,
				      params->phy_addr,
			      MDIO_REG_BANK_COMBO_IEEE0,
			      MDIO_COMBO_IEEE0_MII_CONTROL,
			      &mii_control);

		if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
			udelay(5);
			return 0;
		}
	}

	DP(NETIF_MSG_LINK, "BUG! XGXS is still in reset!\n");
	return -EINVAL;

}

static void bnx2x_set_swap_lanes(struct link_params *params)
{
	struct bnx2x *bp = params->bp;
	/* Each two bits represents a lane number:
	   No swap is 0123 => 0x1b no need to enable the swap */
	u16 ser_lane, rx_lane_swap, tx_lane_swap;

	ser_lane = ((params->lane_config &
			 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
			PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
	rx_lane_swap = ((params->lane_config &
			     PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
			    PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
	tx_lane_swap = ((params->lane_config &
			     PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
			    PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);

	if (rx_lane_swap != 0x1b) {
		CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				    MDIO_REG_BANK_XGXS_BLOCK2,
				    MDIO_XGXS_BLOCK2_RX_LN_SWAP,
				    (rx_lane_swap |
				    MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
				    MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
	} else {
		CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_XGXS_BLOCK2,
				      MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
	}

	if (tx_lane_swap != 0x1b) {
		CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_XGXS_BLOCK2,
				      MDIO_XGXS_BLOCK2_TX_LN_SWAP,
				      (tx_lane_swap |
				       MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
	} else {
		CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_XGXS_BLOCK2,
				      MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
	}
}

static void bnx2x_set_parallel_detection(struct link_params *params,
				       u8       	 phy_flags)
{
	struct bnx2x *bp = params->bp;
	u16 control2;

	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_SERDES_DIGITAL,
			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
			      &control2);
	if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
		control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
	else
		control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
	DP(NETIF_MSG_LINK, "params->speed_cap_mask = 0x%x, control2 = 0x%x\n",
		params->speed_cap_mask, control2);
	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_SERDES_DIGITAL,
			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
			      control2);

	if ((phy_flags & PHY_XGXS_FLAG) &&
	     (params->speed_cap_mask &
		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
		DP(NETIF_MSG_LINK, "XGXS\n");

		CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				MDIO_REG_BANK_10G_PARALLEL_DETECT,
				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);

		CL45_RD_OVER_CL22(bp, params->port,
				      params->phy_addr,
				MDIO_REG_BANK_10G_PARALLEL_DETECT,
				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
				&control2);


		control2 |=
		    MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;

		CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				MDIO_REG_BANK_10G_PARALLEL_DETECT,
				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
				control2);

		/* Disable parallel detection of HiG */
		CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				MDIO_REG_BANK_XGXS_BLOCK2,
				MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
				MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
				MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
	}
}

static void bnx2x_set_autoneg(struct link_params *params,
			    struct link_vars *vars,
			    u8 enable_cl73)
{
	struct bnx2x *bp = params->bp;
	u16 reg_val;

	/* CL37 Autoneg */

	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_COMBO_IEEE0,
			      MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);

	/* CL37 Autoneg Enabled */
	if (vars->line_speed == SPEED_AUTO_NEG)
		reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
	else /* CL37 Autoneg Disabled */
		reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
			     MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);

	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_COMBO_IEEE0,
			      MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);

	/* Enable/Disable Autodetection */

	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_SERDES_DIGITAL,
			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
	reg_val &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN |
		    MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT);
	reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE;
	if (vars->line_speed == SPEED_AUTO_NEG)
		reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
	else
		reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;

	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_SERDES_DIGITAL,
			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);

	/* Enable TetonII and BAM autoneg */
	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_BAM_NEXT_PAGE,
			      MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
			  &reg_val);
	if (vars->line_speed == SPEED_AUTO_NEG) {
		/* Enable BAM aneg Mode and TetonII aneg Mode */
		reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
			    MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
	} else {
		/* TetonII and BAM Autoneg Disabled */
		reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
			     MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
	}
	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_BAM_NEXT_PAGE,
			      MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
			      reg_val);

	if (enable_cl73) {
		/* Enable Cl73 FSM status bits */
		CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_CL73_USERB0,
				    MDIO_CL73_USERB0_CL73_UCTRL,
				      0xe);

		/* Enable BAM Station Manager*/
		CL45_WR_OVER_CL22(bp, params->port,
			params->phy_addr,
			MDIO_REG_BANK_CL73_USERB0,
			MDIO_CL73_USERB0_CL73_BAM_CTRL1,
			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);

		/* Advertise CL73 link speeds */
			CL45_RD_OVER_CL22(bp, params->port,
					      params->phy_addr,
					      MDIO_REG_BANK_CL73_IEEEB1,
					      MDIO_CL73_IEEEB1_AN_ADV2,
					      &reg_val);
		if (params->speed_cap_mask &
		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
			reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
		if (params->speed_cap_mask &
		    PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
			reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;

			CL45_WR_OVER_CL22(bp, params->port,
					      params->phy_addr,
					      MDIO_REG_BANK_CL73_IEEEB1,
					      MDIO_CL73_IEEEB1_AN_ADV2,
				      reg_val);

		/* CL73 Autoneg Enabled */
		reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;

	} else /* CL73 Autoneg Disabled */
		reg_val = 0;

	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_CL73_IEEEB0,
			      MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
}

/* program SerDes, forced speed */
static void bnx2x_program_serdes(struct link_params *params,
			       struct link_vars *vars)
{
	struct bnx2x *bp = params->bp;
	u16 reg_val;

	/* program duplex, disable autoneg and sgmii*/
	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_COMBO_IEEE0,
			      MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
	reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
		     MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
		     MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
	if (params->req_duplex == DUPLEX_FULL)
		reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_COMBO_IEEE0,
			      MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);

	/* program speed
	   - needed only if the speed is greater than 1G (2.5G or 10G) */
	CL45_RD_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_SERDES_DIGITAL,
				      MDIO_SERDES_DIGITAL_MISC1, &reg_val);
	/* clearing the speed value before setting the right speed */
	DP(NETIF_MSG_LINK, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val);

	reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK |
		     MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);

	if (!((vars->line_speed == SPEED_1000) ||
	      (vars->line_speed == SPEED_100) ||
	      (vars->line_speed == SPEED_10))) {

		reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
			    MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
		if (vars->line_speed == SPEED_10000)
			reg_val |=
				MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
		if (vars->line_speed == SPEED_13000)
			reg_val |=
				MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
	}

	CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_SERDES_DIGITAL,
				      MDIO_SERDES_DIGITAL_MISC1, reg_val);

}

static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
{
	struct bnx2x *bp = params->bp;
	u16 val = 0;

	/* configure the 48 bits for BAM AN */

	/* set extended capabilities */
	if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
		val |= MDIO_OVER_1G_UP1_2_5G;
	if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
		val |= MDIO_OVER_1G_UP1_10G;
	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_OVER_1G,
			      MDIO_OVER_1G_UP1, val);

	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_OVER_1G,
			      MDIO_OVER_1G_UP3, 0x400);
}

static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u16 *ieee_fc)
{
	struct bnx2x *bp = params->bp;
	*ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
	/* resolve pause mode and advertisement
	 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */

	switch (params->req_flow_ctrl) {
	case BNX2X_FLOW_CTRL_AUTO:
		if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
			*ieee_fc |=
			     MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
		} else {
			*ieee_fc |=
		       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
		}
		break;
	case BNX2X_FLOW_CTRL_TX:
		*ieee_fc |=
		       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
		break;

	case BNX2X_FLOW_CTRL_RX:
	case BNX2X_FLOW_CTRL_BOTH:
		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
		break;

	case BNX2X_FLOW_CTRL_NONE:
	default:
		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
		break;
	}
	DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
}

static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
					   u16 ieee_fc)
{
	struct bnx2x *bp = params->bp;
	u16 val;
	/* for AN, we are always publishing full duplex */

	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_COMBO_IEEE0,
			      MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_CL73_IEEEB1,
			      MDIO_CL73_IEEEB1_AN_ADV1, &val);
	val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH;
	val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK);
	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_CL73_IEEEB1,
			      MDIO_CL73_IEEEB1_AN_ADV1, val);
}

static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73)
{
	struct bnx2x *bp = params->bp;
	u16 mii_control;

	DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n");
	/* Enable and restart BAM/CL37 aneg */

	if (enable_cl73) {
		CL45_RD_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_CL73_IEEEB0,
				      MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
				      &mii_control);

		CL45_WR_OVER_CL22(bp, params->port,
				params->phy_addr,
				MDIO_REG_BANK_CL73_IEEEB0,
				MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
				(mii_control |
				MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
				MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
	} else {

		CL45_RD_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_COMBO_IEEE0,
				      MDIO_COMBO_IEEE0_MII_CONTROL,
				      &mii_control);
		DP(NETIF_MSG_LINK,
			 "bnx2x_restart_autoneg mii_control before = 0x%x\n",
			 mii_control);
		CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_COMBO_IEEE0,
				      MDIO_COMBO_IEEE0_MII_CONTROL,
				      (mii_control |
				       MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
				       MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
	}
}

static void bnx2x_initialize_sgmii_process(struct link_params *params,
					 struct link_vars *vars)
{
	struct bnx2x *bp = params->bp;
	u16 control1;

	/* in SGMII mode, the unicore is always slave */

	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_SERDES_DIGITAL,
			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
		      &control1);
	control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT;
	/* set sgmii mode (and not fiber) */
	control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
		      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
		      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_SERDES_DIGITAL,
			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
			      control1);

	/* if forced speed */
	if (!(vars->line_speed == SPEED_AUTO_NEG)) {
		/* set speed, disable autoneg */
		u16 mii_control;

		CL45_RD_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_COMBO_IEEE0,
				      MDIO_COMBO_IEEE0_MII_CONTROL,
				      &mii_control);
		mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
				 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
				 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);

		switch (vars->line_speed) {
		case SPEED_100:
			mii_control |=
				MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100;
			break;
		case SPEED_1000:
			mii_control |=
				MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000;
			break;
		case SPEED_10:
			/* there is nothing to set for 10M */
			break;
		default:
			/* invalid speed for SGMII */
			DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
				  vars->line_speed);
			break;
		}

		/* setting the full duplex */
		if (params->req_duplex == DUPLEX_FULL)
			mii_control |=
				MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
		CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_COMBO_IEEE0,
				      MDIO_COMBO_IEEE0_MII_CONTROL,
				      mii_control);

	} else { /* AN mode */
		/* enable and restart AN */
		bnx2x_restart_autoneg(params, 0);
	}
}


/*
 * link management
 */

static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
{						/*  LD	    LP	 */
	switch (pause_result) { 		/* ASYM P ASYM P */
	case 0xb:       			/*   1  0   1  1 */
		vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
		break;

	case 0xe:       			/*   1  1   1  0 */
		vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
		break;

	case 0x5:       			/*   0  1   0  1 */
	case 0x7:       			/*   0  1   1  1 */
	case 0xd:       			/*   1  1   0  1 */
	case 0xf:       			/*   1  1   1  1 */
		vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
		break;

	default:
		break;
	}
}

static u8 bnx2x_ext_phy_resolve_fc(struct link_params *params,
				  struct link_vars *vars)
{
	struct bnx2x *bp = params->bp;
	u8 ext_phy_addr;
	u16 ld_pause;		/* local */
	u16 lp_pause;		/* link partner */
	u16 an_complete;	/* AN complete */
	u16 pause_result;
	u8 ret = 0;
	u32 ext_phy_type;
	u8 port = params->port;
	ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
	ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
	/* read twice */

	bnx2x_cl45_read(bp, port,
		      ext_phy_type,
		      ext_phy_addr,
		      MDIO_AN_DEVAD,
		      MDIO_AN_REG_STATUS, &an_complete);
	bnx2x_cl45_read(bp, port,
		      ext_phy_type,
		      ext_phy_addr,
		      MDIO_AN_DEVAD,
		      MDIO_AN_REG_STATUS, &an_complete);

	if (an_complete & MDIO_AN_REG_STATUS_AN_COMPLETE) {
		ret = 1;
		bnx2x_cl45_read(bp, port,
			      ext_phy_type,
			      ext_phy_addr,
			      MDIO_AN_DEVAD,
			      MDIO_AN_REG_ADV_PAUSE, &ld_pause);
		bnx2x_cl45_read(bp, port,
			      ext_phy_type,
			      ext_phy_addr,
			      MDIO_AN_DEVAD,
			      MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
		pause_result = (ld_pause &
				MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
		pause_result |= (lp_pause &
				 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
		DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n",
		   pause_result);
		bnx2x_pause_resolve(vars, pause_result);
		if (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE &&
		     ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
			bnx2x_cl45_read(bp, port,
				      ext_phy_type,
				      ext_phy_addr,
				      MDIO_AN_DEVAD,
				      MDIO_AN_REG_CL37_FC_LD, &ld_pause);

			bnx2x_cl45_read(bp, port,
				      ext_phy_type,
				      ext_phy_addr,
				      MDIO_AN_DEVAD,
				      MDIO_AN_REG_CL37_FC_LP, &lp_pause);
			pause_result = (ld_pause &
				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
			pause_result |= (lp_pause &
				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;

			bnx2x_pause_resolve(vars, pause_result);
			DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x \n",
				 pause_result);
		}
	}
	return ret;
}

static u8 bnx2x_direct_parallel_detect_used(struct link_params *params)
{
	struct bnx2x *bp = params->bp;
	u16 pd_10g, status2_1000x;
	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_SERDES_DIGITAL,
			      MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
			      &status2_1000x);
	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_SERDES_DIGITAL,
			      MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
			      &status2_1000x);
	if (status2_1000x & MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED) {
		DP(NETIF_MSG_LINK, "1G parallel detect link on port %d\n",
			 params->port);
		return 1;
	}

	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_10G_PARALLEL_DETECT,
			      MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS,
			      &pd_10g);

	if (pd_10g & MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK) {
		DP(NETIF_MSG_LINK, "10G parallel detect link on port %d\n",
			 params->port);
		return 1;
	}
	return 0;
}

static void bnx2x_flow_ctrl_resolve(struct link_params *params,
				  struct link_vars *vars,
				  u32 gp_status)
{
	struct bnx2x *bp = params->bp;
	u16 ld_pause;   /* local driver */
	u16 lp_pause;   /* link partner */
	u16 pause_result;

	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;

	/* resolve from gp_status in case of AN complete and not sgmii */
	if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
	    (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
	    (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
	    (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
	     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) {
		if (bnx2x_direct_parallel_detect_used(params)) {
			vars->flow_ctrl = params->req_fc_auto_adv;
			return;
		}
		if ((gp_status &
		    (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
		     MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
		    (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
		     MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {

			CL45_RD_OVER_CL22(bp, params->port,
					      params->phy_addr,
					      MDIO_REG_BANK_CL73_IEEEB1,
					      MDIO_CL73_IEEEB1_AN_ADV1,
					      &ld_pause);
			CL45_RD_OVER_CL22(bp, params->port,
					     params->phy_addr,
					     MDIO_REG_BANK_CL73_IEEEB1,
					     MDIO_CL73_IEEEB1_AN_LP_ADV1,
					     &lp_pause);
			pause_result = (ld_pause &
					MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK)
					>> 8;
			pause_result |= (lp_pause &
					MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK)
					>> 10;
			DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n",
				 pause_result);
		} else {

			CL45_RD_OVER_CL22(bp, params->port,
					      params->phy_addr,
					      MDIO_REG_BANK_COMBO_IEEE0,
					      MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
					      &ld_pause);
			CL45_RD_OVER_CL22(bp, params->port,
			       params->phy_addr,
			       MDIO_REG_BANK_COMBO_IEEE0,
			       MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
			       &lp_pause);
			pause_result = (ld_pause &
				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
			pause_result |= (lp_pause &
				 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
			DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n",
				 pause_result);
		}
		bnx2x_pause_resolve(vars, pause_result);
	} else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
		   (bnx2x_ext_phy_resolve_fc(params, vars))) {
		return;
	} else {
		if (params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
			vars->flow_ctrl = params->req_fc_auto_adv;
		else
			vars->flow_ctrl = params->req_flow_ctrl;
	}
	DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
}

static void bnx2x_check_fallback_to_cl37(struct link_params *params)
{
	struct bnx2x *bp = params->bp;
	u16 rx_status, ustat_val, cl37_fsm_recieved;
	DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
	/* Step 1: Make sure signal is detected */
	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_RX0,
			      MDIO_RX0_RX_STATUS,
			      &rx_status);
	if ((rx_status & MDIO_RX0_RX_STATUS_SIGDET) !=
	    (MDIO_RX0_RX_STATUS_SIGDET)) {
		DP(NETIF_MSG_LINK, "Signal is not detected. Restoring CL73."
			     "rx_status(0x80b0) = 0x%x\n", rx_status);
		CL45_WR_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      MDIO_REG_BANK_CL73_IEEEB0,
				      MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
				      MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN);
		return;
	}
	/* Step 2: Check CL73 state machine */
	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_CL73_USERB0,
			      MDIO_CL73_USERB0_CL73_USTAT1,
			      &ustat_val);
	if ((ustat_val &
	     (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
	      MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) !=
	    (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
	      MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) {
		DP(NETIF_MSG_LINK, "CL73 state-machine is not stable. "
			     "ustat_val(0x8371) = 0x%x\n", ustat_val);
		return;
	}
	/* Step 3: Check CL37 Message Pages received to indicate LP
	supports only CL37 */
	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_REMOTE_PHY,
			      MDIO_REMOTE_PHY_MISC_RX_STATUS,
			      &cl37_fsm_recieved);
	if ((cl37_fsm_recieved &
	     (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
	     MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
	    (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
	      MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) {
		DP(NETIF_MSG_LINK, "No CL37 FSM were received. "
			     "misc_rx_status(0x8330) = 0x%x\n",
			 cl37_fsm_recieved);
		return;
	}
	/* The combined cl37/cl73 fsm state information indicating that we are
	connected to a device which does not support cl73, but does support
	cl37 BAM. In this case we disable cl73 and restart cl37 auto-neg */
	/* Disable CL73 */
	CL45_WR_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_CL73_IEEEB0,
			      MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
			      0);
	/* Restart CL37 autoneg */
	bnx2x_restart_autoneg(params, 0);
	DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
}
static u8 bnx2x_link_settings_status(struct link_params *params,
				   struct link_vars *vars,
				   u32 gp_status,
				   u8 ext_phy_link_up)
{
	struct bnx2x *bp = params->bp;
	u16 new_line_speed;
	u8 rc = 0;
	vars->link_status = 0;

	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
		DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
			 gp_status);

		vars->phy_link_up = 1;
		vars->link_status |= LINK_STATUS_LINK_UP;

		if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
			vars->duplex = DUPLEX_FULL;
		else
			vars->duplex = DUPLEX_HALF;

		bnx2x_flow_ctrl_resolve(params, vars, gp_status);

		switch (gp_status & GP_STATUS_SPEED_MASK) {
		case GP_STATUS_10M:
			new_line_speed = SPEED_10;
			if (vars->duplex == DUPLEX_FULL)
				vars->link_status |= LINK_10TFD;
			else
				vars->link_status |= LINK_10THD;
			break;

		case GP_STATUS_100M:
			new_line_speed = SPEED_100;
			if (vars->duplex == DUPLEX_FULL)
				vars->link_status |= LINK_100TXFD;
			else
				vars->link_status |= LINK_100TXHD;
			break;

		case GP_STATUS_1G:
		case GP_STATUS_1G_KX:
			new_line_speed = SPEED_1000;
			if (vars->duplex == DUPLEX_FULL)
				vars->link_status |= LINK_1000TFD;
			else
				vars->link_status |= LINK_1000THD;
			break;

		case GP_STATUS_2_5G:
			new_line_speed = SPEED_2500;
			if (vars->duplex == DUPLEX_FULL)
				vars->link_status |= LINK_2500TFD;
			else
				vars->link_status |= LINK_2500THD;
			break;

		case GP_STATUS_5G:
		case GP_STATUS_6G:
			DP(NETIF_MSG_LINK,
				 "link speed unsupported  gp_status 0x%x\n",
				  gp_status);
			return -EINVAL;

		case GP_STATUS_10G_KX4:
		case GP_STATUS_10G_HIG:
		case GP_STATUS_10G_CX4:
			new_line_speed = SPEED_10000;
			vars->link_status |= LINK_10GTFD;
			break;

		case GP_STATUS_12G_HIG:
			new_line_speed = SPEED_12000;
			vars->link_status |= LINK_12GTFD;
			break;

		case GP_STATUS_12_5G:
			new_line_speed = SPEED_12500;
			vars->link_status |= LINK_12_5GTFD;
			break;

		case GP_STATUS_13G:
			new_line_speed = SPEED_13000;
			vars->link_status |= LINK_13GTFD;
			break;

		case GP_STATUS_15G:
			new_line_speed = SPEED_15000;
			vars->link_status |= LINK_15GTFD;
			break;

		case GP_STATUS_16G:
			new_line_speed = SPEED_16000;
			vars->link_status |= LINK_16GTFD;
			break;

		default:
			DP(NETIF_MSG_LINK,
				  "link speed unsupported gp_status 0x%x\n",
				  gp_status);
			return -EINVAL;
		}

		/* Upon link speed change set the NIG into drain mode.
		Comes to deals with possible FIFO glitch due to clk change
		when speed is decreased without link down indicator */
		if (new_line_speed != vars->line_speed) {
			if (XGXS_EXT_PHY_TYPE(params->ext_phy_config) !=
			     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT &&
			    ext_phy_link_up) {
				DP(NETIF_MSG_LINK, "Internal link speed %d is"
					    " different than the external"
					    " link speed %d\n", new_line_speed,
					  vars->line_speed);
				vars->phy_link_up = 0;
				return 0;
			}
			REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
				    + params->port*4, 0);
			msleep(1);
		}
		vars->line_speed = new_line_speed;
		vars->link_status |= LINK_STATUS_SERDES_LINK;

		if ((params->req_line_speed == SPEED_AUTO_NEG) &&
		    ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
		    (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
		    (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) ||
		    (XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726))) {
			vars->autoneg = AUTO_NEG_ENABLED;

			if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
				vars->autoneg |= AUTO_NEG_COMPLETE;
				vars->link_status |=
					LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
			}

			vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
			vars->link_status |=
				LINK_STATUS_PARALLEL_DETECTION_USED;

		}
		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
			vars->link_status |=
				LINK_STATUS_TX_FLOW_CONTROL_ENABLED;

		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
			vars->link_status |=
				LINK_STATUS_RX_FLOW_CONTROL_ENABLED;

	} else { /* link_down */
		DP(NETIF_MSG_LINK, "phy link down\n");

		vars->phy_link_up = 0;

		vars->duplex = DUPLEX_FULL;
		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
		vars->autoneg = AUTO_NEG_DISABLED;
		vars->mac_type = MAC_TYPE_NONE;

		if ((params->req_line_speed == SPEED_AUTO_NEG) &&
		    ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
		     PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT))) {
			/* Check signal is detected */
			bnx2x_check_fallback_to_cl37(params);
		}
	}

	DP(NETIF_MSG_LINK, "gp_status 0x%x  phy_link_up %x line_speed %x \n",
		 gp_status, vars->phy_link_up, vars->line_speed);
	DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x"
		 " autoneg 0x%x\n",
		 vars->duplex,
		 vars->flow_ctrl, vars->autoneg);
	DP(NETIF_MSG_LINK, "link_status 0x%x\n", vars->link_status);

	return rc;
}

static void bnx2x_set_gmii_tx_driver(struct link_params *params)
{
	struct bnx2x *bp = params->bp;
	u16 lp_up2;
	u16 tx_driver;
	u16 bank;

	/* read precomp */
	CL45_RD_OVER_CL22(bp, params->port,
			      params->phy_addr,
			      MDIO_REG_BANK_OVER_1G,
			      MDIO_OVER_1G_LP_UP2, &lp_up2);

	/* bits [10:7] at lp_up2, positioned at [15:12] */
	lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
		   MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
		  MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);

	if (lp_up2 == 0)
		return;

	for (bank = MDIO_REG_BANK_TX0; bank <= MDIO_REG_BANK_TX3;
	      bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0)) {
		CL45_RD_OVER_CL22(bp, params->port,
				      params->phy_addr,
				      bank,
				      MDIO_TX0_TX_DRIVER, &tx_driver);

		/* replace tx_driver bits [15:12] */
		if (lp_up2 !=
		    (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK)) {
			tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
			tx_driver |= lp_up2;
			CL45_WR_OVER_CL22(bp, params->port,
					      params->phy_addr,
					      bank,
					      MDIO_TX0_TX_DRIVER, tx_driver);
		}
	}
}

static u8 bnx2x_emac_program(struct link_params *params,
			   u32 line_speed, u32 duplex)
{
	struct bnx2x *bp = params->bp;
	u8 port = params->port;
	u16 mode = 0;

	DP(NETIF_MSG_LINK, "setting link speed & duplex\n");
	bnx2x_bits_dis(bp, GRCBASE_EMAC0 + port*0x400 +
		     EMAC_REG_EMAC_MODE,
		     (EMAC_MODE_25G_MODE |
		     EMAC_MODE_PORT_MII_10M |
		     EMAC_MODE_HALF_DUPLEX));
	switch (line_speed) {
	case SPEED_10:
		mode |= EMAC_MODE_PORT_MII_10M;
		break;

	case SPEED_100:
		mode |= EMAC_MODE_PORT_MII;
		break;

	case SPEED_1000:
		mode |= EMAC_MODE_PORT_GMII;
		break;

	case SPEED_2500:
		mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
		break;

	default:
		/* 10G not valid for EMAC */
		DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", line_speed);
		return -EINVAL;
	}

	if (duplex == DUPLEX_HALF)
		mode |= EMAC_MODE_HALF_DUPLEX;
	bnx2x_bits_en(bp,
		    GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
		    mode);

	bnx2x_set_led(params, LED_MODE_OPER, line_speed);
	return 0;
}

/*****************************************************************************/
/*      		     External Phy section       		     */
/*****************************************************************************/
void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
{
	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
		       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
	msleep(1);
	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
		      MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
}

static void bnx2x_ext_phy_reset(struct link_params *params,
			      struct link_vars   *vars)
{
	struct bnx2x *bp = params->bp;
	u32 ext_phy_type;
	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);

	DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
	ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
	/* The PHY reset is controled by GPIO 1
	 * Give it 1ms of reset pulse
	 */
	if (vars->phy_flags & PHY_XGXS_FLAG) {

		switch (ext_phy_type) {
		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
			DP(NETIF_MSG_LINK, "XGXS Direct\n");
			break;

		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
			DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");

			/* Restore normal power mode*/
			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
				      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
					  params->port);

			/* HW reset */
			bnx2x_ext_phy_hw_reset(bp, params->port);

			bnx2x_cl45_write(bp, params->port,
				       ext_phy_type,
				       ext_phy_addr,
				       MDIO_PMA_DEVAD,
				       MDIO_PMA_REG_CTRL, 0xa040);
			break;

		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
			break;

		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:

			/* Restore normal power mode*/
			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
					  MISC_REGISTERS_GPIO_OUTPUT_HIGH,
					  params->port);

			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
					  MISC_REGISTERS_GPIO_OUTPUT_HIGH,
					  params->port);

			bnx2x_cl45_write(bp, params->port,
				       ext_phy_type,
				       ext_phy_addr,
				       MDIO_PMA_DEVAD,
				       MDIO_PMA_REG_CTRL,
				       1<<15);
			break;

		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
			DP(NETIF_MSG_LINK, "XGXS 8072\n");

			/* Unset Low Power Mode and SW reset */
			/* Restore normal power mode*/
			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
				      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
					  params->port);

			bnx2x_cl45_write(bp, params->port,
				       ext_phy_type,
				       ext_phy_addr,
				       MDIO_PMA_DEVAD,
				       MDIO_PMA_REG_CTRL,
				       1<<15);
			break;

		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
			DP(NETIF_MSG_LINK, "XGXS 8073\n");

			/* Restore normal power mode*/
			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
				      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
					  params->port);

			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
				      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
					  params->port);
			break;

		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
			DP(NETIF_MSG_LINK, "XGXS SFX7101\n");

			/* Restore normal power mode*/
			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
				      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
					  params->port);

			/* HW reset */
			bnx2x_ext_phy_hw_reset(bp, params->port);
			break;

		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
			/* Restore normal power mode*/
			bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
				      MISC_REGISTERS_GPIO_OUTPUT_HIGH,
					  params->port);

			/* HW reset */
			bnx2x_ext_phy_hw_reset(bp, params->port);

			bnx2x_cl45_write(bp, params->port,
				       ext_phy_type,
				       ext_phy_addr,
				       MDIO_PMA_DEVAD,
				       MDIO_PMA_REG_CTRL,
				       1<<15);
			break;
		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
			break;
		case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
			DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n");
			break;

		default:
			DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
			   params->ext_phy_config);
			break;
		}

	} else { /* SerDes */
		ext_phy_type = SERDES_EXT_PHY_TYPE(params->ext_phy_config);
		switch (ext_phy_type) {
		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
			DP(NETIF_MSG_LINK, "SerDes Direct\n");
			break;

		case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482:
			DP(NETIF_MSG_LINK, "SerDes 5482\n");
			bnx2x_ext_phy_hw_reset(bp, params->port);
			break;

		default:
			DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n",
				 params->ext_phy_config);
			break;
		}
	}
}

static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
				    u32 shmem_base, u32 spirom_ver)
{
	DP(NETIF_MSG_LINK, "FW version 0x%x:0x%x for port %d\n",
		 (u16)(spirom_ver>>16), (u16)spirom_ver, port);
	REG_WR(bp, shmem_base +
		   offsetof(struct shmem_region,
			    port_mb[port].ext_phy_fw_version),
			spirom_ver);
}

static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp, u8 port,
				    u32 ext_phy_type, u8 ext_phy_addr,
				    u32 shmem_base)
{
	u16 fw_ver1, fw_ver2;

	bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
		      MDIO_PMA_REG_ROM_VER1, &fw_ver1);
	bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr, MDIO_PMA_DEVAD,
		      MDIO_PMA_REG_ROM_VER2, &fw_ver2);
	bnx2x_save_spirom_version(bp, port, shmem_base,
				(u32)(fw_ver1<<16 | fw_ver2));
}


static void bnx2x_save_8481_spirom_version(struct bnx2x *bp, u8 port,
					 u8 ext_phy_addr, u32 shmem_base)
{
	u16 val, fw_ver1, fw_ver2, cnt;
	/* For the 32 bits registers in 8481, access via MDIO2ARM interface.*/
	/* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
	bnx2x_cl45_write(bp, port,
		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
		       ext_phy_addr, MDIO_PMA_DEVAD,
		       0xA819, 0x0014);
	bnx2x_cl45_write(bp, port,
		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
		       ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       0xA81A,
		       0xc200);
	bnx2x_cl45_write(bp, port,
		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
		       ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       0xA81B,
		       0x0000);
	bnx2x_cl45_write(bp, port,
		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
		       ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       0xA81C,
		       0x0300);
	bnx2x_cl45_write(bp, port,
		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
		       ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       0xA817,
		       0x0009);

	for (cnt = 0; cnt < 100; cnt++) {
		bnx2x_cl45_read(bp, port,
			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
			      ext_phy_addr,
			      MDIO_PMA_DEVAD,
			      0xA818,
			      &val);
		if (val & 1)
			break;
		udelay(5);
	}
	if (cnt == 100) {
		DP(NETIF_MSG_LINK, "Unable to read 8481 phy fw version(1)\n");
		bnx2x_save_spirom_version(bp, port,
					shmem_base, 0);
		return;
	}


	/* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
	bnx2x_cl45_write(bp, port,
		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
		       ext_phy_addr, MDIO_PMA_DEVAD,
		       0xA819, 0x0000);
	bnx2x_cl45_write(bp, port,
		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
		       ext_phy_addr, MDIO_PMA_DEVAD,
		       0xA81A, 0xc200);
	bnx2x_cl45_write(bp, port,
		       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
		       ext_phy_addr, MDIO_PMA_DEVAD,
		       0xA817, 0x000A);
	for (cnt = 0; cnt < 100; cnt++) {
		bnx2x_cl45_read(bp, port,
			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
			      ext_phy_addr,
			      MDIO_PMA_DEVAD,
			      0xA818,
			      &val);
		if (val & 1)
			break;
		udelay(5);
	}
	if (cnt == 100) {
		DP(NETIF_MSG_LINK, "Unable to read 8481 phy fw version(2)\n");
		bnx2x_save_spirom_version(bp, port,
					shmem_base, 0);
		return;
	}

	/* lower 16 bits of the register SPI_FW_STATUS */
	bnx2x_cl45_read(bp, port,
		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
		      ext_phy_addr,
		      MDIO_PMA_DEVAD,
		      0xA81B,
		      &fw_ver1);
	/* upper 16 bits of register SPI_FW_STATUS */
	bnx2x_cl45_read(bp, port,
		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
		      ext_phy_addr,
		      MDIO_PMA_DEVAD,
		      0xA81C,
		      &fw_ver2);

	bnx2x_save_spirom_version(bp, port,
				shmem_base, (fw_ver2<<16) | fw_ver1);
}

static void bnx2x_bcm8072_external_rom_boot(struct link_params *params)
{
	struct bnx2x *bp = params->bp;
	u8 port = params->port;
	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);

	/* Need to wait 200ms after reset */
	msleep(200);
	/* Boot port from external ROM
	 * Set ser_boot_ctl bit in the MISC_CTRL1 register
	 */
	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
			    MDIO_PMA_DEVAD,
			    MDIO_PMA_REG_MISC_CTRL1, 0x0001);

	/* Reset internal microprocessor */
	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
			  MDIO_PMA_DEVAD,
			  MDIO_PMA_REG_GEN_CTRL,
			  MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
	/* set micro reset = 0 */
	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
			    MDIO_PMA_DEVAD,
			    MDIO_PMA_REG_GEN_CTRL,
			    MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
	/* Reset internal microprocessor */
	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
			  MDIO_PMA_DEVAD,
			  MDIO_PMA_REG_GEN_CTRL,
			  MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
	/* wait for 100ms for code download via SPI port */
	msleep(100);

	/* Clear ser_boot_ctl bit */
	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
			    MDIO_PMA_DEVAD,
			    MDIO_PMA_REG_MISC_CTRL1, 0x0000);
	/* Wait 100ms */
	msleep(100);

	bnx2x_save_bcm_spirom_ver(bp, port,
				ext_phy_type,
				ext_phy_addr,
				params->shmem_base);
}

static u8 bnx2x_8073_is_snr_needed(struct link_params *params)
{
	/* This is only required for 8073A1, version 102 only */

	struct bnx2x *bp = params->bp;
	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
	u16 val;

	/* Read 8073 HW revision*/
	bnx2x_cl45_read(bp, params->port,
		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
		      ext_phy_addr,
		      MDIO_PMA_DEVAD,
		      MDIO_PMA_REG_8073_CHIP_REV, &val);

	if (val != 1) {
		/* No need to workaround in 8073 A1 */
		return 0;
	}

	bnx2x_cl45_read(bp, params->port,
		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
		      ext_phy_addr,
		      MDIO_PMA_DEVAD,
		      MDIO_PMA_REG_ROM_VER2, &val);

	/* SNR should be applied only for version 0x102 */
	if (val != 0x102)
		return 0;

	return 1;
}

static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
{
	struct bnx2x *bp = params->bp;
	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
	u16 val, cnt, cnt1 ;

	bnx2x_cl45_read(bp, params->port,
		      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
		      ext_phy_addr,
		      MDIO_PMA_DEVAD,
		      MDIO_PMA_REG_8073_CHIP_REV, &val);

	if (val > 0) {
		/* No need to workaround in 8073 A1 */
		return 0;
	}
	/* XAUI workaround in 8073 A0: */

	/* After loading the boot ROM and restarting Autoneg,
	poll Dev1, Reg $C820: */

	for (cnt = 0; cnt < 1000; cnt++) {
		bnx2x_cl45_read(bp, params->port,
			      PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
			      ext_phy_addr,
			      MDIO_PMA_DEVAD,
			      MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
			      &val);
		  /* If bit [14] = 0 or bit [13] = 0, continue on with
		   system initialization (XAUI work-around not required,
		    as these bits indicate 2.5G or 1G link up). */
		if (!(val & (1<<14)) || !(val & (1<<13))) {
			DP(NETIF_MSG_LINK, "XAUI work-around not required\n");
			return 0;
		} else if (!(val & (1<<15))) {
			DP(NETIF_MSG_LINK, "clc bit 15 went off\n");
			 /* If bit 15 is 0, then poll Dev1, Reg $C841 until
			  it's MSB (bit 15) goes to 1 (indicating that the
			  XAUI workaround has completed),
			  then continue on with system initialization.*/
			for (cnt1 = 0; cnt1 < 1000; cnt1++) {
				bnx2x_cl45_read(bp, params->port,
					PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
					ext_phy_addr,
					MDIO_PMA_DEVAD,
					MDIO_PMA_REG_8073_XAUI_WA, &val);
				if (val & (1<<15)) {
					DP(NETIF_MSG_LINK,
					  "XAUI workaround has completed\n");
					return 0;
				 }
				 msleep(3);
			}
			break;
		}
		msleep(3);
	}
	DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
	return -EINVAL;
}

static void bnx2x_bcm8073_bcm8727_external_rom_boot(struct bnx2x *bp, u8 port,
						  u8 ext_phy_addr,
						  u32 ext_phy_type,
						  u32 shmem_base)
{
	/* Boot port from external ROM  */
	/* EDC grst */
	bnx2x_cl45_write(bp, port,
		       ext_phy_type,
		       ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_GEN_CTRL,
		       0x0001);

	/* ucode reboot and rst */
	bnx2x_cl45_write(bp, port,
		       ext_phy_type,
		       ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_GEN_CTRL,
		       0x008c);

	bnx2x_cl45_write(bp, port,
		       ext_phy_type,
		       ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_MISC_CTRL1, 0x0001);

	/* Reset internal microprocessor */
	bnx2x_cl45_write(bp, port,
		       ext_phy_type,
		       ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_GEN_CTRL,
		       MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);

	/* Release srst bit */
	bnx2x_cl45_write(bp, port,
		       ext_phy_type,
		       ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_GEN_CTRL,
		       MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);

	/* wait for 100ms for code download via SPI port */
	msleep(100);

	/* Clear ser_boot_ctl bit */
	bnx2x_cl45_write(bp, port,
		       ext_phy_type,
		       ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_MISC_CTRL1, 0x0000);

	bnx2x_save_bcm_spirom_ver(bp, port,
				ext_phy_type,
				ext_phy_addr,
				shmem_base);
}

static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
					  u8 ext_phy_addr,
					  u32 shmem_base)
{
	bnx2x_bcm8073_bcm8727_external_rom_boot(bp, port, ext_phy_addr,
					 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
					 shmem_base);
}

static void bnx2x_bcm8727_external_rom_boot(struct bnx2x *bp, u8 port,
					  u8 ext_phy_addr,
					  u32 shmem_base)
{
	bnx2x_bcm8073_bcm8727_external_rom_boot(bp, port, ext_phy_addr,
					 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
					 shmem_base);

}

static void bnx2x_bcm8726_external_rom_boot(struct link_params *params)
{
	struct bnx2x *bp = params->bp;
	u8 port = params->port;
	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);
	u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);

	/* Need to wait 100ms after reset */
	msleep(100);

	/* Micro controller re-boot */
	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_GEN_CTRL,
		       0x018B);

	/* Set soft reset */
	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_GEN_CTRL,
		       MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);

	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_MISC_CTRL1, 0x0001);

	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_GEN_CTRL,
		       MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);

	/* wait for 150ms for microcode load */
	msleep(150);

	/* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */
	bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_MISC_CTRL1, 0x0000);

	msleep(200);
	bnx2x_save_bcm_spirom_ver(bp, port,
				ext_phy_type,
				ext_phy_addr,
				params->shmem_base);
}

static void bnx2x_sfp_set_transmitter(struct bnx2x *bp, u8 port,
				    u32 ext_phy_type, u8 ext_phy_addr,
				    u8 tx_en)
{
	u16 val;

	DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x\n",
		 tx_en, port);
	/* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/
	bnx2x_cl45_read(bp, port,
		      ext_phy_type,
		      ext_phy_addr,
		      MDIO_PMA_DEVAD,
		      MDIO_PMA_REG_PHY_IDENTIFIER,
		      &val);

	if (tx_en)
		val &= ~(1<<15);
	else
		val |= (1<<15);

	bnx2x_cl45_write(bp, port,
		       ext_phy_type,
		       ext_phy_addr,
		       MDIO_PMA_DEVAD,
		       MDIO_PMA_REG_PHY_IDENTIFIER,
		       val);
}

static u8 bnx2x_8726_read_sfp_module_eeprom(struct link_params *params,
					  u16 addr, u8 byte_cnt, u8 *o_buf)
{
	struct bnx2x *bp = params->bp;
	u16 val = 0;
	u16 i;
	u8 port = params->port;
	u8 ext_phy_addr = XGXS_EXT_PHY_ADDR(params->ext_phy_config);