aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/net/ethernet/marvell/skge.c
blob: 095f6c71b4fa1dc61476be81f49c1b5c11a5c19b (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                        








                                                                            
                                                                   

   

                                           
                     










                              
                              
                          
                        
                           
                      
                       
                      
                           




                                      
                                      



                                    
                                                   
                                    

                                    



                                        
                                   
                                  
 


                                          
                                                         
                                                                     


                            


                                                                 




                                                           
                                                     

                                                                           


                                                                      


                                                                                       
                                                                                      




                                                                                               





                                             
                                                   
                                                  

                                                                        


                                                                 
                                                           
                                                    
                                                       
                                                    
 
                                       



                                                      

                                                                     
 








                                                       

                                                    
                      


  


                                                            




                                                                            
                                                

                          

                                          
 



                                                                  

 
                                                                   
                                                  
 
                           
                         




                                                              

 



                                                 
                 
 


                                                                     


                                                                        
 







                                                      
 



                                                                                    
 








                                                                                    

                                                                    




                                                                 
 




















                                                                                
                                                                                





                                                                    





                                                                             

                                                 






                                                                            

                                                  

                                   
                                 


                                                            


                 

                                                          




                                                         
                         







                                                       
 
                                   



                                                                



                                                               



                                                       


                         
 

                                                                      


                                                  
                                   
 
                                             
 
                         

                                                     
              










                                                                            
 


                 

                                                                            


                                                  
                                                 
                    



                                                                             
 

                                                  

                                  
                
                            
                                            
 
                                
                                
                                                            
                                                                   
                                                                 


                                                                   

                               
                                                            
                                                                  
                                                                 




                                                                  
                              
                                                            
                                                                 
                                                                 

                                                                 




                                               



                                               
                                    
                                                

         

                                          
 







                                       
 
                 






                                                          

                                                                   

                                                         
































                                                                 
                                                                
 





                                              






                                                                          
                                 













                                                                      
                                 



                                              






                                                            
 
                           





                                                                             
                            














                                                                    


                                            





                                                           
                    

                                                                     
                                                                             






                                            


                                       

         
                   
















                                                                   



                                                                   
                             


                 




                                                                



                                                                        
 
                                                         





                                                               
                                      
                    
 













                                                                                          
 







                                       
 





                                                    
                                              

 
                             




                                                                    
                             



































































                                                                            

                                                                
 


                                      
                                    
                             

                                  





                                                                                               



                                                                                
 


                                                                                        
 

                                                                              
 
                              
 



                                                                              
 







                                                                                              
                 
                















                                                                     
 













                                                                        
         
                                      


                                   

                                                             


                                                  

                               
                                                                   
 


                                             
 


                                             
 



                                                                                



                 





                                                                   
                                                          




















































































                                                                                 
                                                    








                                              


                                              





                                              
                                           
                                           
                                              
                                                    

                                                      





                                                                 
                                                                         




                               
                                                                   

















                                                                                 
                                                   

                                                                        

                                          
                       
 
                                                                

                                                 


                                                       

                                        








                                                                                

                                              
                 

 



                                               
                                                                           












                                                                             





                                                 

                        

                                                  

                                                  

                                                                    




                                                             

 
 
                                    
                                                 
   
                                               
 
                                                  

                                                
 

                        
                                    
 

                                                                               


                                       
                                               



                                                                         
                                               
 

                                     

 

                                                       
                         













                                                                                 

                                                
                                                              
                                                         
 
                                       
                                       
 




                                                                         



                                                  
                                                                            


                                        
                                                               

 



                                                      
 
                                                       
 



                                     
                                                                         

              
 
                                                              
                                                
 


                                        
                                           
                                                                     
                                   
                          

         
                          
       
                                                
 






                                                             
                                                                         


                 
                                                                       


              
                                                              
                                           
                                                                         
                                   
                          
         
                    

       
                                               





                                                                         































                                                                      
                                         
                
 

                                                       
                                         
                                                         
                                                       


                                                                            
 
                                      

                                                                
 
                                           




                                                       

 




                                                  
                                                                       

  




                                                   
                                                  

  


                                                         
 




                                                  
                                             

                                                      
                                           
                                       

                       
 

                                              
 

                                               
 

                                                              
                                                             

                               
 










                                                               
                                                                
                               

                 


                                                              
                                                                

                                  
                                                               

                                  
                                                               

                              
                                                           

                                         
         


                                      




                                                                             
                                                 


                                      
              
                             














                                                                     





                                                                   
                                            
 
                      




























































                                                                             
                                                









                                                                   
                                              
                                                                 
 
 











                                                                  
                                                            

















                                                                       
                                                        

 
                                                






                                                  
                                             


                                                      
                                       
                         





                                               
                                 


                                                              
                                                             
                                 












                                                              
                                                                
                                 


                                                              











                                                                          
                    
                                                           





                                         
                 


                                    
  
                                                              

                                                              
   
                                               
 
                                                                 
                                              
                                      
                              

                            



                                










                                                                          
                                                     



                                                       
                                             
                


                                                            
         
                                                     








                                                          
                                         
 






                                                                                  
 
                                                   

          
                               
                                                                      





                                                               






                                                    
 
                                              
 


                                                               
 
 
                               






                                          
 

                                                   
 



                                                      






                                                       






                                                           
 
                                          
                  


                                                                                 
                   
                                    
         
                                           
 
                                                      

                                                        




                                                              











                                                                  
                                                                  

                                                            
                                                   
 

          


                                                                    
           







                                                                    















                                                    


                                                                      

                                   


                                                                      
 
                    
                                                                
                                                                            


                                                            
                                                                          
         





                                                
                                

                
                               


                                                
 

                                



                                                                
                           





                                                                                     

                                                              
                                          
                                                    








                                                

         

                                                       

                                                            
                                        









                                                                
                            


                                                                    
                                               






                                                   



                                                               

                                                    
                                                                         



                                                          

                                                  
                                                  
 

                                                            
 
                                                                      
                                       

                                                          
 
                                    
                                                         
                                            
         

 



                                                   
                     
                 
 
                                              




                                                                  

                                                    
                                                   




                                                  
                                              
 
                                            
                                                       
                                                      










                                                                         
                                                           

                                      
                                                                            







                                                                          
                                                                            

         
                                            
 
                                              
                                           
                             
                                           
 
                                     

                                  
                                              
                                                                       

                                      



                                                            





                                                                         

                          
                                        




                                                             
                                                        


                                      


                                                        

                                                          
 
                                
                                                             
                                            



                                                                    
                                      

                                                                
                                                      
                                                     


                                                       

                                                          
 

 













                                                                                 
                                                                


























                                                                         
                                                                       


                 
                                



                                                            
 
                                              
                                                                     




                                                                    
                                                               
 
                                                                 

         
                                                    



                                             
                                                    


                   
                          

                                              
                                 











                                                                          
 









                                                                          
 




















                                                   
                                                            
 

                                                       
 

                                                                           
                                                                           
            
                                                                            



                                                     




                                                                           
 

                                                         


                                                              















                                                                 








                                                            




                                                  

                        

                                                               


                                                      





                                                  



                                                                
                                                                    

                             


                                                                              
 

                                               

                                                                         


                                      
                                                  
                                                  
                              
                               
                                                   
                                                 



                                                                         





                                                                                
 

                                     
                                                                         




                                                                                  




                                                 

         
                                               
                                                    
 
                             

                       

                                                                 

                                             

                                                            

                              
                                                                  

                                                                
                                         


                                                                              
                                                       

                                
                                          



                                                          





                                                

                                         
                                                   

                                                     
                                                     
                                      
                                                     

                                                         


                                                



                                   
                                                                        
                                           


                                                                    
                                       
 

                                                                  





                                                                           

                                   

                                                                   

 


















                                                        




                                              

                                                       
 

                                                         
                                                             
                                         
 
                                
 
                                    

                                                              







                                                              



                                                                

                                                    
                                              




                                                                    

                                                  
                                                               
 

                                                            
 
                                      
                                            
                                                                            
         
 
                                      
                                            
                                                                            





                                                         
                                           














                                                 
                                           
                                                                  
 
                                               




                                                                           
                                               
 
                                                                    






                                                   
                 
 


                                                   
 


                                                                
                                                  
                                                                

         











                                                  

                                                           
 

                                                                           

                                          
                                                           




                                                
                                                                                   












                                                            


                                                              
                                                                

                                      
                                                               

                                      
                                                               

                              
                                                           

                 
                                                          
                                                                              
                                                                                
                    
                                                                               
















                                                                                         
                                                                                



                                          



                                                  
                                               



                                        
                                    
                             





                                           
                                      
 
                                

 










                                                                         
                      





                                            
                                            

                                   


                                                                                        
                                              




                                    
                                            
                                   




                                                                                
                                              




                      
                                                                         


                


                              




                                                         
                                                  


                                                       







                                                                
                                                                   
         


























                                                                              
                            


                                


                                                
                                                                     
 
                                   
                                                        



                                                






                                                                               

                              
                                                                                    
                                                                                             



                                  

                                                                    

                                  
                                
                

                                  


                                                                  

                                  









                                                                                      
                            
                               
                                    
                           


                                           
                                      
 

                                                                    
                                                     
 
                                                        
                                                               
 
                                                               
                                                              




                                                                                
                                    
 


                                                 
                                 

                                      
                                 


                                

                 

                                   




                                                                            
                         



                   








                                                                      





                                                  
                       

                         
                                                                        
 
                              
 
                                                          
                                                  
 
                                  
                               


                                         

                                                                        

                                      


                                            
                                                                            
                           



                                   




                                                                

                                                         
                                               


                                                                 

                                                        






                                                                                 

                               
 
                             

                                                                         
                

                                                                          

         
                                     
 
                              
                           

                                




                                                                            
                         


                 

                                                          
                 



                                                                  

                                                          


                                                  



                                
                       
 
                                     

                                    
                                                                                 
                                      
 
                                 
                     
                                      


                                                                         


                                                 

                                            
 

                                        
 
                                                 
                                                                  



                                                                   
                                                             
                                                                      





                                                
                                                           



                                                                             
                                                 




                                                                 
                                                                            
 
                                                                       
                                                                                   

                                                                   

                                    
                                     
                                     

                                                      

                                                        
                                                            
                                                                          
 
                                                                                       







                                                                 

                                         

                                                                       


                                                               
 
                                       

                  
                                                         
                                                         


                                      
                            

















                                                                              
                               
                            

 

                                                       

                                                                              
 

                                     

                                                                  

                                                   

                                                                
                                                 

 
                                       
                                                 
 
                                                  
                               
 

                                                                                  




                                                              


                                
                                
                                   





                                                   
                                                                            

                                                                            
                           
                              



                                                               
                
 




                                   
                       
 
                           
 
                           

                               



                   










                                                                             




                                                         
                                  


                     
                                            









                                                     
 

                                                              

                                                                  

                                                             

         
                                            
                                             

 





                                                          




                                                       
                                  

                                                                  




                                          
                                               

                               
                                                                 


                                                                   
                                                                     

                                        

                                       


                                                                

                                                           


         
                                            
                                                                 
                                            
                                                                 
                                            
                                                                 
                                            

                                                                 
                                               

 

                                                                  
                           




                                                  

                                                                      
                           





                                                                     


                                                      
 
                                 





                                           



                                                          


                                                                     
 
                                                  


                                    


                                                               











                                                               

                                      
                                                          

                                      

                                                           
                                                                       

                                                                     
                                                                  
                                                              
                                                                          

                                                                        
                                                    
                
                                       
                                     

                                                                         

                                      
 


                             

                                    




                                                                          
                                                

                                                              
                                                     
         

                          

                                             
                                              
                                                   

         
                                                 



                   


                                                                   
 
                                   
                                                          
                                                      
                                            
                                                     
                                            
                                                   

                                                              
                                                      
                                             
                                                     
                                            
                                                   




                                            

 
                                                                     
                                                
 
                                                  
                                                
                               
                                                     
 
                                                                                
 
                                                                  
                                                                               
 
                                      

                              









                                                                             
                                                    
                 
         
                                                             
                                   
 








                                                                             
 


                                     
 
 
                                                          
 

                                                                            


                                                

                          



                                                                          
                                                                                      
                                                  
                                    
                            





                                      
                                                                          
                                  
                                                    
                                    
                 


                           

                              
                                                                       
 
                                                                        
                                    
 
                                                       


                                                         
                                                            
         
 
                         

 


                                                                     

                                                         

                                               
                                         
 
                           
                                                            


                                                                                  
                                                            
                                                                               


                                                             

                                                       
                           







                                                           
                                        

                                                    
                             

                                                             
                                                                       
                                                             
                                                                       



                                                                         


                                       
                                                                    



                                                             
                                                                     








                                                             
                                       

                                                                       
                                                          
         
 
                                       

                                                                       
                                                          
         

                                                      

                                        

                                                                    
 

                                                                     



                                                                
                                                        
                                                                                       
                                                                    
                                                                 
 
                                                            

                                                        
                                                                                               





                                                    
                                                      


                                                                 
                                          
 
                                                    

                 
                                                  

                                                       
                                         


                                                                  
                                            
                                                     
                                                             
                                                    
                                                   

                 
 
                                    

                                                 
                                 
                                      

 
                                                   

                                    
                   
                        
 
                                

                                             
                                        
                         
 
                    
                                

                                             
                                                

         
                                          
                                                                 
                                                     
                                           

         

                                                            
 
                                    
                                                   
                                                            

         
 

                                     
 
                         

                                                                 

                                                             
                                                   


                                            
                                                           








                                                                    


                                   
    
                                                 
                                 
                                  
 
                                   







                                                  
                                      






                                                                


                                        
                 



                                                
                                                       
 







                                                                                   
 

                                                                                   
 
                                   




                                                                              
 


                                                        

                 









                                               










                                                            
                                                               









                                                     
                
                             
                                 
              







                                             

                                                        
 



                                                                  






                                                                            
                                                    

                                                          
 
                              
                             
                          



                                                     



                                                     

                                                                              


                                           



                                                                                      



                                
                                                                         
                                       

                                             


                      

                                                                       


                                   


                                                       


                                        
                             

                                                                          

                                                 

                                                
                           


                                         
 
                                  
 
                                                               
                                                             

                                            
                           




                                                                                
 


                                                                     
                                                                                


                                                    







                                                                    
                                                 

                                                                                  








                                                 
                                       
                                                                  

























                                                               

                                                                
 
                                         
                                   



                                             



                 

























                                                                                  
                                      












                                                                        
                                  







                                                            
                                                                  
                               
 
                                                                 


                                
                        
                               



                                                                              


                               

                                              


                       

                                                                                













                                              
                                                      
 
















                                                              


                                                      
                                                  




                                                    
                                                     






                                                       
                               

                                                                    



                                                               
                 
                            
 
                                            

                                             
                                          
                                 
 



                                     

                                                 

                                
                                                                 


                                                              
 




                                                   
                                                  

                          
                                                     
 
                                                
                                                           

                                                                    




                            
                                        
                           
                                                             
              


                                                                 




                                                                             


                   
                                                  


                                                        
                                                                           

 

                          
                                                                            




                                      

                                      
                                                                  


                             

                                                  
                                                                     




                                          
                                                                           
                              
                                                                          
                                                                       
                              
                                                                          


                  
                                                                     
                                          


                   
                                               









                                                                
                                             
                                                           
                                                               
                
                                          
 
                                                                  
 
                        
                                     
                                      
                                                                     


                                                                        
                                                                     


                                     

                             
                                     
 



                                                                           
 
                                             

                              
                                     
         
 
                                                               

                                                                              
 

                                   
                                                                    




                                         

                                                      


                                                
                 















                                                                                   
         
                                  


                 



                                

                               



                                               







                                  



                   
                                             



                                                    
                

                       

                          



                                        
                                    
 

                                    



                                             
         

                                      
                                               

                                             

                                        




                                  
 

                          

 
                      
                                           
 
                                                   
              
 


                         
                                         
                                                    
                                                          
 

                                       
 

                                            

         
                                     
 


                 
                                          
 
                                                   
                   
 


                         


                             
 
                                         
                                                    
 



                                           
                                                                           
                                               

                                         

                 

                   
 






                                                                 
                            
 


                                                    
              
 


                       





                                                          

         
                                                              
                                             

 



                                        
                                    
                                      
                                    

  
                                                             






                                                                              






                                                                             






                                                                             


          

                                        

                                                    
                          
                                                 




                                            
                             



                                 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * New driver for Marvell Yukon chipset and SysKonnect Gigabit
 * Ethernet adapters. Based on earlier sk98lin, e100 and
 * FreeBSD if_sk drivers.
 *
 * This driver intentionally does not support all the features
 * of the original driver such as link fail-over and link management because
 * those should be done at higher levels.
 *
 * Copyright (C) 2004, 2005 Stephen Hemminger <shemminger@osdl.org>
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/pci.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/delay.h>
#include <linux/crc32.h>
#include <linux/dma-mapping.h>
#include <linux/debugfs.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/mii.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#include <linux/prefetch.h>
#include <asm/irq.h>

#include "skge.h"

#define DRV_NAME		"skge"
#define DRV_VERSION		"1.14"

#define DEFAULT_TX_RING_SIZE	128
#define DEFAULT_RX_RING_SIZE	512
#define MAX_TX_RING_SIZE	1024
#define TX_LOW_WATER		(MAX_SKB_FRAGS + 1)
#define MAX_RX_RING_SIZE	4096
#define RX_COPY_THRESHOLD	128
#define RX_BUF_SIZE		1536
#define PHY_RETRIES	        1000
#define ETH_JUMBO_MTU		9000
#define TX_WATCHDOG		(5 * HZ)
#define NAPI_WEIGHT		64
#define BLINK_MS		250
#define LINK_HZ			HZ

#define SKGE_EEPROM_MAGIC	0x9933aabb


MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);

static const u32 default_msg = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
				NETIF_MSG_LINK | NETIF_MSG_IFUP |
				NETIF_MSG_IFDOWN);

static int debug = -1;	/* defaults above */
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");

static const struct pci_device_id skge_id_table[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x1700) },	  /* 3Com 3C940 */
	{ PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x80EB) },	  /* 3Com 3C940B */
#ifdef CONFIG_SKGE_GENESIS
	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4300) }, /* SK-9xx */
#endif
	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4320) }, /* SK-98xx V2.0 */
	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },	  /* D-Link DGE-530T (rev.B) */
	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4c00) },	  /* D-Link DGE-530T */
	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302) },	  /* D-Link DGE-530T Rev C1 */
	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },	  /* Marvell Yukon 88E8001/8003/8010 */
	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) },	  /* Belkin */
	{ PCI_DEVICE(PCI_VENDOR_ID_CNET, 0x434E) }, 	  /* CNet PowerG-2000 */
	{ PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, 0x1064) },	  /* Linksys EG1064 v2 */
	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015 }, /* Linksys EG1032 v2 */
	{ 0 }
};
MODULE_DEVICE_TABLE(pci, skge_id_table);

static int skge_up(struct net_device *dev);
static int skge_down(struct net_device *dev);
static void skge_phy_reset(struct skge_port *skge);
static void skge_tx_clean(struct net_device *dev);
static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
static void genesis_get_stats(struct skge_port *skge, u64 *data);
static void yukon_get_stats(struct skge_port *skge, u64 *data);
static void yukon_init(struct skge_hw *hw, int port);
static void genesis_mac_init(struct skge_hw *hw, int port);
static void genesis_link_up(struct skge_port *skge);
static void skge_set_multicast(struct net_device *dev);
static irqreturn_t skge_intr(int irq, void *dev_id);

/* Avoid conditionals by using array */
static const int txqaddr[] = { Q_XA1, Q_XA2 };
static const int rxqaddr[] = { Q_R1, Q_R2 };
static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 };

static inline bool is_genesis(const struct skge_hw *hw)
{
#ifdef CONFIG_SKGE_GENESIS
	return hw->chip_id == CHIP_ID_GENESIS;
#else
	return false;
#endif
}

static int skge_get_regs_len(struct net_device *dev)
{
	return 0x4000;
}

/*
 * Returns copy of whole control register region
 * Note: skip RAM address register because accessing it will
 * 	 cause bus hangs!
 */
static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
			  void *p)
{
	const struct skge_port *skge = netdev_priv(dev);
	const void __iomem *io = skge->hw->regs;

	regs->version = 1;
	memset(p, 0, regs->len);
	memcpy_fromio(p, io, B3_RAM_ADDR);

	if (regs->len > B3_RI_WTO_R1) {
		memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
			      regs->len - B3_RI_WTO_R1);
	}
}

/* Wake on Lan only supported on Yukon chips with rev 1 or above */
static u32 wol_supported(const struct skge_hw *hw)
{
	if (is_genesis(hw))
		return 0;

	if (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0)
		return 0;

	return WAKE_MAGIC | WAKE_PHY;
}

static void skge_wol_init(struct skge_port *skge)
{
	struct skge_hw *hw = skge->hw;
	int port = skge->port;
	u16 ctrl;

	skge_write16(hw, B0_CTST, CS_RST_CLR);
	skge_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR);

	/* Turn on Vaux */
	skge_write8(hw, B0_POWER_CTRL,
		    PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF);

	/* WA code for COMA mode -- clear PHY reset */
	if (hw->chip_id == CHIP_ID_YUKON_LITE &&
	    hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
		u32 reg = skge_read32(hw, B2_GP_IO);
		reg |= GP_DIR_9;
		reg &= ~GP_IO_9;
		skge_write32(hw, B2_GP_IO, reg);
	}

	skge_write32(hw, SK_REG(port, GPHY_CTRL),
		     GPC_DIS_SLEEP |
		     GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 |
		     GPC_ANEG_1 | GPC_RST_SET);

	skge_write32(hw, SK_REG(port, GPHY_CTRL),
		     GPC_DIS_SLEEP |
		     GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 |
		     GPC_ANEG_1 | GPC_RST_CLR);

	skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);

	/* Force to 10/100 skge_reset will re-enable on resume	 */
	gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
		     (PHY_AN_100FULL | PHY_AN_100HALF |
		      PHY_AN_10FULL | PHY_AN_10HALF | PHY_AN_CSMA));
	/* no 1000 HD/FD */
	gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, 0);
	gm_phy_write(hw, port, PHY_MARV_CTRL,
		     PHY_CT_RESET | PHY_CT_SPS_LSB | PHY_CT_ANE |
		     PHY_CT_RE_CFG | PHY_CT_DUP_MD);


	/* Set GMAC to no flow control and auto update for speed/duplex */
	gma_write16(hw, port, GM_GP_CTRL,
		    GM_GPCR_FC_TX_DIS|GM_GPCR_TX_ENA|GM_GPCR_RX_ENA|
		    GM_GPCR_DUP_FULL|GM_GPCR_FC_RX_DIS|GM_GPCR_AU_FCT_DIS);

	/* Set WOL address */
	memcpy_toio(hw->regs + WOL_REGS(port, WOL_MAC_ADDR),
		    skge->netdev->dev_addr, ETH_ALEN);

	/* Turn on appropriate WOL control bits */
	skge_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), WOL_CTL_CLEAR_RESULT);
	ctrl = 0;
	if (skge->wol & WAKE_PHY)
		ctrl |= WOL_CTL_ENA_PME_ON_LINK_CHG|WOL_CTL_ENA_LINK_CHG_UNIT;
	else
		ctrl |= WOL_CTL_DIS_PME_ON_LINK_CHG|WOL_CTL_DIS_LINK_CHG_UNIT;

	if (skge->wol & WAKE_MAGIC)
		ctrl |= WOL_CTL_ENA_PME_ON_MAGIC_PKT|WOL_CTL_ENA_MAGIC_PKT_UNIT;
	else
		ctrl |= WOL_CTL_DIS_PME_ON_MAGIC_PKT|WOL_CTL_DIS_MAGIC_PKT_UNIT;

	ctrl |= WOL_CTL_DIS_PME_ON_PATTERN|WOL_CTL_DIS_PATTERN_UNIT;
	skge_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl);

	/* block receiver */
	skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
}

static void skge_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
	struct skge_port *skge = netdev_priv(dev);

	wol->supported = wol_supported(skge->hw);
	wol->wolopts = skge->wol;
}

static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
	struct skge_port *skge = netdev_priv(dev);
	struct skge_hw *hw = skge->hw;

	if ((wol->wolopts & ~wol_supported(hw)) ||
	    !device_can_wakeup(&hw->pdev->dev))
		return -EOPNOTSUPP;

	skge->wol = wol->wolopts;

	device_set_wakeup_enable(&hw->pdev->dev, skge->wol);

	return 0;
}

/* Determine supported/advertised modes based on hardware.
 * Note: ethtool ADVERTISED_xxx == SUPPORTED_xxx
 */
static u32 skge_supported_modes(const struct skge_hw *hw)
{
	u32 supported;

	if (hw->copper) {
		supported = (SUPPORTED_10baseT_Half |
			     SUPPORTED_10baseT_Full |
			     SUPPORTED_100baseT_Half |
			     SUPPORTED_100baseT_Full |
			     SUPPORTED_1000baseT_Half |
			     SUPPORTED_1000baseT_Full |
			     SUPPORTED_Autoneg |
			     SUPPORTED_TP);

		if (is_genesis(hw))
			supported &= ~(SUPPORTED_10baseT_Half |
				       SUPPORTED_10baseT_Full |
				       SUPPORTED_100baseT_Half |
				       SUPPORTED_100baseT_Full);

		else if (hw->chip_id == CHIP_ID_YUKON)
			supported &= ~SUPPORTED_1000baseT_Half;
	} else
		supported = (SUPPORTED_1000baseT_Full |
			     SUPPORTED_1000baseT_Half |
			     SUPPORTED_FIBRE |
			     SUPPORTED_Autoneg);

	return supported;
}

static int skge_get_link_ksettings(struct net_device *dev,
				   struct ethtool_link_ksettings *cmd)
{
	struct skge_port *skge = netdev_priv(dev);
	struct skge_hw *hw = skge->hw;
	u32 supported, advertising;

	supported = skge_supported_modes(hw);

	if (hw->copper) {
		cmd->base.port = PORT_TP;
		cmd->base.phy_address = hw->phy_addr;
	} else
		cmd->base.port = PORT_FIBRE;

	advertising = skge->advertising;
	cmd->base.autoneg = skge->autoneg;
	cmd->base.speed = skge->speed;
	cmd->base.duplex = skge->duplex;

	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
						supported);
	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
						advertising);

	return 0;
}

static int skge_set_link_ksettings(struct net_device *dev,
				   const struct ethtool_link_ksettings *cmd)
{
	struct skge_port *skge = netdev_priv(dev);
	const struct skge_hw *hw = skge->hw;
	u32 supported = skge_supported_modes(hw);
	int err = 0;
	u32 advertising;

	ethtool_convert_link_mode_to_legacy_u32(&advertising,
						cmd->link_modes.advertising);

	if (cmd->base.autoneg == AUTONEG_ENABLE) {
		advertising = supported;
		skge->duplex = -1;
		skge->speed = -1;
	} else {
		u32 setting;
		u32 speed = cmd->base.speed;

		switch (speed) {
		case SPEED_1000:
			if (cmd->base.duplex == DUPLEX_FULL)
				setting = SUPPORTED_1000baseT_Full;
			else if (cmd->base.duplex == DUPLEX_HALF)
				setting = SUPPORTED_1000baseT_Half;
			else
				return -EINVAL;
			break;
		case SPEED_100:
			if (cmd->base.duplex == DUPLEX_FULL)
				setting = SUPPORTED_100baseT_Full;
			else if (cmd->base.duplex == DUPLEX_HALF)
				setting = SUPPORTED_100baseT_Half;
			else
				return -EINVAL;
			break;

		case SPEED_10:
			if (cmd->base.duplex == DUPLEX_FULL)
				setting = SUPPORTED_10baseT_Full;
			else if (cmd->base.duplex == DUPLEX_HALF)
				setting = SUPPORTED_10baseT_Half;
			else
				return -EINVAL;
			break;
		default:
			return -EINVAL;
		}

		if ((setting & supported) == 0)
			return -EINVAL;

		skge->speed = speed;
		skge->duplex = cmd->base.duplex;
	}

	skge->autoneg = cmd->base.autoneg;
	skge->advertising = advertising;

	if (netif_running(dev)) {
		skge_down(dev);
		err = skge_up(dev);
		if (err) {
			dev_close(dev);
			return err;
		}
	}

	return 0;
}

static void skge_get_drvinfo(struct net_device *dev,
			     struct ethtool_drvinfo *info)
{
	struct skge_port *skge = netdev_priv(dev);

	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
	strlcpy(info->bus_info, pci_name(skge->hw->pdev),
		sizeof(info->bus_info));
}

static const struct skge_stat {
	char 	   name[ETH_GSTRING_LEN];
	u16	   xmac_offset;
	u16	   gma_offset;
} skge_stats[] = {
	{ "tx_bytes",		XM_TXO_OK_HI,  GM_TXO_OK_HI },
	{ "rx_bytes",		XM_RXO_OK_HI,  GM_RXO_OK_HI },

	{ "tx_broadcast",	XM_TXF_BC_OK,  GM_TXF_BC_OK },
	{ "rx_broadcast",	XM_RXF_BC_OK,  GM_RXF_BC_OK },
	{ "tx_multicast",	XM_TXF_MC_OK,  GM_TXF_MC_OK },
	{ "rx_multicast",	XM_RXF_MC_OK,  GM_RXF_MC_OK },
	{ "tx_unicast",		XM_TXF_UC_OK,  GM_TXF_UC_OK },
	{ "rx_unicast",		XM_RXF_UC_OK,  GM_RXF_UC_OK },
	{ "tx_mac_pause",	XM_TXF_MPAUSE, GM_TXF_MPAUSE },
	{ "rx_mac_pause",	XM_RXF_MPAUSE, GM_RXF_MPAUSE },

	{ "collisions",		XM_TXF_SNG_COL, GM_TXF_SNG_COL },
	{ "multi_collisions",	XM_TXF_MUL_COL, GM_TXF_MUL_COL },
	{ "aborted",		XM_TXF_ABO_COL, GM_TXF_ABO_COL },
	{ "late_collision",	XM_TXF_LAT_COL, GM_TXF_LAT_COL },
	{ "fifo_underrun",	XM_TXE_FIFO_UR, GM_TXE_FIFO_UR },
	{ "fifo_overflow",	XM_RXE_FIFO_OV, GM_RXE_FIFO_OV },

	{ "rx_toolong",		XM_RXF_LNG_ERR, GM_RXF_LNG_ERR },
	{ "rx_jabber",		XM_RXF_JAB_PKT, GM_RXF_JAB_PKT },
	{ "rx_runt",		XM_RXE_RUNT, 	GM_RXE_FRAG },
	{ "rx_too_long",	XM_RXF_LNG_ERR, GM_RXF_LNG_ERR },
	{ "rx_fcs_error",	XM_RXF_FCS_ERR, GM_RXF_FCS_ERR },
};

static int skge_get_sset_count(struct net_device *dev, int sset)
{
	switch (sset) {
	case ETH_SS_STATS:
		return ARRAY_SIZE(skge_stats);
	default:
		return -EOPNOTSUPP;
	}
}

static void skge_get_ethtool_stats(struct net_device *dev,
				   struct ethtool_stats *stats, u64 *data)
{
	struct skge_port *skge = netdev_priv(dev);

	if (is_genesis(skge->hw))
		genesis_get_stats(skge, data);
	else
		yukon_get_stats(skge, data);
}

/* Use hardware MIB variables for critical path statistics and
 * transmit feedback not reported at interrupt.
 * Other errors are accounted for in interrupt handler.
 */
static struct net_device_stats *skge_get_stats(struct net_device *dev)
{
	struct skge_port *skge = netdev_priv(dev);
	u64 data[ARRAY_SIZE(skge_stats)];

	if (is_genesis(skge->hw))
		genesis_get_stats(skge, data);
	else
		yukon_get_stats(skge, data);

	dev->stats.tx_bytes = data[0];
	dev->stats.rx_bytes = data[1];
	dev->stats.tx_packets = data[2] + data[4] + data[6];
	dev->stats.rx_packets = data[3] + data[5] + data[7];
	dev->stats.multicast = data[3] + data[5];
	dev->stats.collisions = data[10];
	dev->stats.tx_aborted_errors = data[12];

	return &dev->stats;
}

static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
	int i;

	switch (stringset) {
	case ETH_SS_STATS:
		for (i = 0; i < ARRAY_SIZE(skge_stats); i++)
			memcpy(data + i * ETH_GSTRING_LEN,
			       skge_stats[i].name, ETH_GSTRING_LEN);
		break;
	}
}

static void skge_get_ring_param(struct net_device *dev,
				struct ethtool_ringparam *p)
{
	struct skge_port *skge = netdev_priv(dev);

	p->rx_max_pending = MAX_RX_RING_SIZE;
	p->tx_max_pending = MAX_TX_RING_SIZE;

	p->rx_pending = skge->rx_ring.count;
	p->tx_pending = skge->tx_ring.count;
}

static int skge_set_ring_param(struct net_device *dev,
			       struct ethtool_ringparam *p)
{
	struct skge_port *skge = netdev_priv(dev);
	int err = 0;

	if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE ||
	    p->tx_pending < TX_LOW_WATER || p->tx_pending > MAX_TX_RING_SIZE)
		return -EINVAL;

	skge->rx_ring.count = p->rx_pending;
	skge->tx_ring.count = p->tx_pending;

	if (netif_running(dev)) {
		skge_down(dev);
		err = skge_up(dev);
		if (err)
			dev_close(dev);
	}

	return err;
}

static u32 skge_get_msglevel(struct net_device *netdev)
{
	struct skge_port *skge = netdev_priv(netdev);
	return skge->msg_enable;
}

static void skge_set_msglevel(struct net_device *netdev, u32 value)
{
	struct skge_port *skge = netdev_priv(netdev);
	skge->msg_enable = value;
}

static int skge_nway_reset(struct net_device *dev)
{
	struct skge_port *skge = netdev_priv(dev);

	if (skge->autoneg != AUTONEG_ENABLE || !netif_running(dev))
		return -EINVAL;

	skge_phy_reset(skge);
	return 0;
}

static void skge_get_pauseparam(struct net_device *dev,
				struct ethtool_pauseparam *ecmd)
{
	struct skge_port *skge = netdev_priv(dev);

	ecmd->rx_pause = ((skge->flow_control == FLOW_MODE_SYMMETRIC) ||
			  (skge->flow_control == FLOW_MODE_SYM_OR_REM));
	ecmd->tx_pause = (ecmd->rx_pause ||
			  (skge->flow_control == FLOW_MODE_LOC_SEND));

	ecmd->autoneg = ecmd->rx_pause || ecmd->tx_pause;
}

static int skge_set_pauseparam(struct net_device *dev,
			       struct ethtool_pauseparam *ecmd)
{
	struct skge_port *skge = netdev_priv(dev);
	struct ethtool_pauseparam old;
	int err = 0;

	skge_get_pauseparam(dev, &old);

	if (ecmd->autoneg != old.autoneg)
		skge->flow_control = ecmd->autoneg ? FLOW_MODE_NONE : FLOW_MODE_SYMMETRIC;
	else {
		if (ecmd->rx_pause && ecmd->tx_pause)
			skge->flow_control = FLOW_MODE_SYMMETRIC;
		else if (ecmd->rx_pause && !ecmd->tx_pause)
			skge->flow_control = FLOW_MODE_SYM_OR_REM;
		else if (!ecmd->rx_pause && ecmd->tx_pause)
			skge->flow_control = FLOW_MODE_LOC_SEND;
		else
			skge->flow_control = FLOW_MODE_NONE;
	}

	if (netif_running(dev)) {
		skge_down(dev);
		err = skge_up(dev);
		if (err) {
			dev_close(dev);
			return err;
		}
	}

	return 0;
}

/* Chip internal frequency for clock calculations */
static inline u32 hwkhz(const struct skge_hw *hw)
{
	return is_genesis(hw) ? 53125 : 78125;
}

/* Chip HZ to microseconds */
static inline u32 skge_clk2usec(const struct skge_hw *hw, u32 ticks)
{
	return (ticks * 1000) / hwkhz(hw);
}

/* Microseconds to chip HZ */
static inline u32 skge_usecs2clk(const struct skge_hw *hw, u32 usec)
{
	return hwkhz(hw) * usec / 1000;
}

static int skge_get_coalesce(struct net_device *dev,
			     struct ethtool_coalesce *ecmd)
{
	struct skge_port *skge = netdev_priv(dev);
	struct skge_hw *hw = skge->hw;
	int port = skge->port;

	ecmd->rx_coalesce_usecs = 0;
	ecmd->tx_coalesce_usecs = 0;

	if (skge_read32(hw, B2_IRQM_CTRL) & TIM_START) {
		u32 delay = skge_clk2usec(hw, skge_read32(hw, B2_IRQM_INI));
		u32 msk = skge_read32(hw, B2_IRQM_MSK);

		if (msk & rxirqmask[port])
			ecmd->rx_coalesce_usecs = delay;
		if (msk & txirqmask[port])
			ecmd->tx_coalesce_usecs = delay;
	}

	return 0;
}

/* Note: interrupt timer is per board, but can turn on/off per port */
static int skge_set_coalesce(struct net_device *dev,
			     struct ethtool_coalesce *ecmd)
{
	struct skge_port *skge = netdev_priv(dev);
	struct skge_hw *hw = skge->hw;
	int port = skge->port;
	u32 msk = skge_read32(hw, B2_IRQM_MSK);
	u32 delay = 25;

	if (ecmd->rx_coalesce_usecs == 0)
		msk &= ~rxirqmask[port];
	else if (ecmd->rx_coalesce_usecs < 25 ||
		 ecmd->rx_coalesce_usecs > 33333)
		return -EINVAL;
	else {
		msk |= rxirqmask[port];
		delay = ecmd->rx_coalesce_usecs;
	}

	if (ecmd->tx_coalesce_usecs == 0)
		msk &= ~txirqmask[port];
	else if (ecmd->tx_coalesce_usecs < 25 ||
		 ecmd->tx_coalesce_usecs > 33333)
		return -EINVAL;
	else {
		msk |= txirqmask[port];
		delay = min(delay, ecmd->rx_coalesce_usecs);
	}

	skge_write32(hw, B2_IRQM_MSK, msk);
	if (msk == 0)
		skge_write32(hw, B2_IRQM_CTRL, TIM_STOP);
	else {
		skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, delay));
		skge_write32(hw, B2_IRQM_CTRL, TIM_START);
	}
	return 0;
}

enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST };
static void skge_led(struct skge_port *skge, enum led_mode mode)
{
	struct skge_hw *hw = skge->hw;
	int port = skge->port;

	spin_lock_bh(&hw->phy_lock);
	if (is_genesis(hw)) {
		switch (mode) {
		case LED_MODE_OFF:
			if (hw->phy_type == SK_PHY_BCOM)
				xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
			else {
				skge_write32(hw, SK_REG(port, TX_LED_VAL), 0);
				skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_T_OFF);
			}
			skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF