2011-04-05 09:42:12 -07:00
/******************************************************************************
*
* Copyright ( c ) 2003 - 2011 Intel Corporation . All rights reserved .
*
* Portions of this file are derived from the ipw3945 project .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 , USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE .
*
* Contact Information :
* Intel Linux Wireless < ilw @ linux . intel . com >
* Intel Corporation , 5200 N . E . Elam Young Parkway , Hillsboro , OR 97124 - 6497
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-08-25 23:11:14 -07:00
# include <linux/delay.h>
# include <linux/device.h>
2011-04-05 09:42:12 -07:00
# include "iwl-io.h"
2011-08-25 23:11:14 -07:00
# include "iwl-csr.h"
# include "iwl-debug.h"
2011-04-05 09:42:12 -07:00
# define IWL_POLL_INTERVAL 10 /* microseconds */
2011-08-25 23:11:14 -07:00
static inline void __iwl_set_bit ( struct iwl_bus * bus , u32 reg , u32 mask )
2011-04-05 09:42:12 -07:00
{
2011-08-25 23:11:14 -07:00
iwl_write32 ( bus , reg , iwl_read32 ( bus , reg ) | mask ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
static inline void __iwl_clear_bit ( struct iwl_bus * bus , u32 reg , u32 mask )
2011-04-05 09:42:12 -07:00
{
2011-08-25 23:11:14 -07:00
iwl_write32 ( bus , reg , iwl_read32 ( bus , reg ) & ~ mask ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
void iwl_set_bit ( struct iwl_bus * bus , u32 reg , u32 mask )
2011-04-05 09:42:12 -07:00
{
unsigned long flags ;
2011-08-25 23:11:14 -07:00
spin_lock_irqsave ( & bus - > reg_lock , flags ) ;
__iwl_set_bit ( bus , reg , mask ) ;
spin_unlock_irqrestore ( & bus - > reg_lock , flags ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
void iwl_clear_bit ( struct iwl_bus * bus , u32 reg , u32 mask )
2011-04-05 09:42:12 -07:00
{
unsigned long flags ;
2011-08-25 23:11:14 -07:00
spin_lock_irqsave ( & bus - > reg_lock , flags ) ;
__iwl_clear_bit ( bus , reg , mask ) ;
spin_unlock_irqrestore ( & bus - > reg_lock , flags ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
int iwl_poll_bit ( struct iwl_bus * bus , u32 addr ,
2011-04-05 09:42:12 -07:00
u32 bits , u32 mask , int timeout )
{
int t = 0 ;
do {
2011-08-25 23:11:14 -07:00
if ( ( iwl_read32 ( bus , addr ) & mask ) = = ( bits & mask ) )
2011-04-05 09:42:12 -07:00
return t ;
udelay ( IWL_POLL_INTERVAL ) ;
t + = IWL_POLL_INTERVAL ;
} while ( t < timeout ) ;
return - ETIMEDOUT ;
}
2011-08-25 23:11:14 -07:00
int iwl_grab_nic_access_silent ( struct iwl_bus * bus )
2011-04-05 09:42:12 -07:00
{
int ret ;
2011-08-25 23:11:14 -07:00
lockdep_assert_held ( & bus - > reg_lock ) ;
2011-04-05 09:42:12 -07:00
/* this bit wakes up the NIC */
2011-08-25 23:11:14 -07:00
__iwl_set_bit ( bus , CSR_GP_CNTRL , CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ ) ;
2011-04-05 09:42:12 -07:00
/*
* These bits say the device is running , and should keep running for
* at least a short while ( at least as long as MAC_ACCESS_REQ stays 1 ) ,
* but they do not indicate that embedded SRAM is restored yet ;
* 3945 and 4965 have volatile SRAM , and must save / restore contents
* to / from host DRAM when sleeping / waking for power - saving .
* Each direction takes approximately 1 / 4 millisecond ; with this
* overhead , it ' s a good idea to grab and hold MAC_ACCESS_REQUEST if a
* series of register accesses are expected ( e . g . reading Event Log ) ,
* to keep device from sleeping .
*
* CSR_UCODE_DRV_GP1 register bit MAC_SLEEP = = 0 indicates that
* SRAM is okay / restored . We don ' t check that here because this call
* is just for hardware register access ; but GP1 MAC_SLEEP check is a
* good idea before accessing 3945 / 4965 SRAM ( e . g . reading Event Log ) .
*
* 5000 series and later ( including 1000 series ) have non - volatile SRAM ,
* and do not save / restore SRAM when power cycling .
*/
2011-08-25 23:11:14 -07:00
ret = iwl_poll_bit ( bus , CSR_GP_CNTRL ,
2011-04-05 09:42:12 -07:00
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN ,
( CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP ) , 15000 ) ;
if ( ret < 0 ) {
2011-08-25 23:11:14 -07:00
iwl_write32 ( bus , CSR_RESET , CSR_RESET_REG_FLAG_FORCE_NMI ) ;
2011-04-05 09:42:12 -07:00
return - EIO ;
}
return 0 ;
}
2011-08-25 23:11:14 -07:00
int iwl_grab_nic_access ( struct iwl_bus * bus )
2011-04-19 07:42:03 -07:00
{
2011-08-25 23:11:14 -07:00
int ret = iwl_grab_nic_access_silent ( bus ) ;
2011-04-19 07:42:03 -07:00
if ( ret ) {
2011-08-25 23:11:14 -07:00
u32 val = iwl_read32 ( bus , CSR_GP_CNTRL ) ;
IWL_ERR ( bus ,
2011-04-19 07:42:03 -07:00
" MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X \n " , val ) ;
}
return ret ;
}
2011-08-25 23:11:14 -07:00
void iwl_release_nic_access ( struct iwl_bus * bus )
2011-04-05 09:42:12 -07:00
{
2011-08-25 23:11:14 -07:00
lockdep_assert_held ( & bus - > reg_lock ) ;
__iwl_clear_bit ( bus , CSR_GP_CNTRL ,
2011-04-05 09:42:12 -07:00
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ ) ;
}
2011-08-25 23:11:14 -07:00
u32 iwl_read_direct32 ( struct iwl_bus * bus , u32 reg )
2011-04-05 09:42:12 -07:00
{
u32 value ;
unsigned long flags ;
2011-08-25 23:11:14 -07:00
spin_lock_irqsave ( & bus - > reg_lock , flags ) ;
iwl_grab_nic_access ( bus ) ;
2011-11-17 16:05:13 -08:00
value = iwl_read32 ( bus , reg ) ;
2011-08-25 23:11:14 -07:00
iwl_release_nic_access ( bus ) ;
spin_unlock_irqrestore ( & bus - > reg_lock , flags ) ;
2011-04-05 09:42:12 -07:00
return value ;
}
2011-08-25 23:11:14 -07:00
void iwl_write_direct32 ( struct iwl_bus * bus , u32 reg , u32 value )
2011-04-05 09:42:12 -07:00
{
unsigned long flags ;
2011-08-25 23:11:14 -07:00
spin_lock_irqsave ( & bus - > reg_lock , flags ) ;
if ( ! iwl_grab_nic_access ( bus ) ) {
iwl_write32 ( bus , reg , value ) ;
iwl_release_nic_access ( bus ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
spin_unlock_irqrestore ( & bus - > reg_lock , flags ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
int iwl_poll_direct_bit ( struct iwl_bus * bus , u32 addr , u32 mask ,
2011-04-05 09:42:12 -07:00
int timeout )
{
int t = 0 ;
do {
2011-08-25 23:11:14 -07:00
if ( ( iwl_read_direct32 ( bus , addr ) & mask ) = = mask )
2011-04-05 09:42:12 -07:00
return t ;
udelay ( IWL_POLL_INTERVAL ) ;
t + = IWL_POLL_INTERVAL ;
} while ( t < timeout ) ;
return - ETIMEDOUT ;
}
2011-08-25 23:11:14 -07:00
static inline u32 __iwl_read_prph ( struct iwl_bus * bus , u32 reg )
2011-04-05 09:42:12 -07:00
{
2011-08-25 23:11:14 -07:00
iwl_write32 ( bus , HBUS_TARG_PRPH_RADDR , reg | ( 3 < < 24 ) ) ;
2011-04-05 09:42:12 -07:00
rmb ( ) ;
2011-08-25 23:11:14 -07:00
return iwl_read32 ( bus , HBUS_TARG_PRPH_RDAT ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
static inline void __iwl_write_prph ( struct iwl_bus * bus , u32 addr , u32 val )
2011-04-05 09:42:12 -07:00
{
2011-08-25 23:11:14 -07:00
iwl_write32 ( bus , HBUS_TARG_PRPH_WADDR ,
2011-04-05 09:42:12 -07:00
( ( addr & 0x0000FFFF ) | ( 3 < < 24 ) ) ) ;
wmb ( ) ;
2011-08-25 23:11:14 -07:00
iwl_write32 ( bus , HBUS_TARG_PRPH_WDAT , val ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
u32 iwl_read_prph ( struct iwl_bus * bus , u32 reg )
2011-04-05 09:42:12 -07:00
{
unsigned long flags ;
u32 val ;
2011-08-25 23:11:14 -07:00
spin_lock_irqsave ( & bus - > reg_lock , flags ) ;
iwl_grab_nic_access ( bus ) ;
val = __iwl_read_prph ( bus , reg ) ;
iwl_release_nic_access ( bus ) ;
spin_unlock_irqrestore ( & bus - > reg_lock , flags ) ;
2011-04-05 09:42:12 -07:00
return val ;
}
2011-08-25 23:11:14 -07:00
void iwl_write_prph ( struct iwl_bus * bus , u32 addr , u32 val )
2011-04-05 09:42:12 -07:00
{
unsigned long flags ;
2011-08-25 23:11:14 -07:00
spin_lock_irqsave ( & bus - > reg_lock , flags ) ;
if ( ! iwl_grab_nic_access ( bus ) ) {
__iwl_write_prph ( bus , addr , val ) ;
iwl_release_nic_access ( bus ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
spin_unlock_irqrestore ( & bus - > reg_lock , flags ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
void iwl_set_bits_prph ( struct iwl_bus * bus , u32 reg , u32 mask )
2011-04-05 09:42:12 -07:00
{
unsigned long flags ;
2011-08-25 23:11:14 -07:00
spin_lock_irqsave ( & bus - > reg_lock , flags ) ;
iwl_grab_nic_access ( bus ) ;
__iwl_write_prph ( bus , reg , __iwl_read_prph ( bus , reg ) | mask ) ;
iwl_release_nic_access ( bus ) ;
spin_unlock_irqrestore ( & bus - > reg_lock , flags ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
void iwl_set_bits_mask_prph ( struct iwl_bus * bus , u32 reg ,
2011-04-05 09:42:12 -07:00
u32 bits , u32 mask )
{
unsigned long flags ;
2011-08-25 23:11:14 -07:00
spin_lock_irqsave ( & bus - > reg_lock , flags ) ;
iwl_grab_nic_access ( bus ) ;
__iwl_write_prph ( bus , reg ,
( __iwl_read_prph ( bus , reg ) & mask ) | bits ) ;
iwl_release_nic_access ( bus ) ;
spin_unlock_irqrestore ( & bus - > reg_lock , flags ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
void iwl_clear_bits_prph ( struct iwl_bus * bus , u32 reg , u32 mask )
2011-04-05 09:42:12 -07:00
{
unsigned long flags ;
u32 val ;
2011-08-25 23:11:14 -07:00
spin_lock_irqsave ( & bus - > reg_lock , flags ) ;
iwl_grab_nic_access ( bus ) ;
val = __iwl_read_prph ( bus , reg ) ;
__iwl_write_prph ( bus , reg , ( val & ~ mask ) ) ;
iwl_release_nic_access ( bus ) ;
spin_unlock_irqrestore ( & bus - > reg_lock , flags ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
void _iwl_read_targ_mem_words ( struct iwl_bus * bus , u32 addr ,
2011-04-13 03:14:43 -07:00
void * buf , int words )
2011-04-05 09:42:12 -07:00
{
unsigned long flags ;
2011-04-13 03:14:43 -07:00
int offs ;
u32 * vals = buf ;
2011-04-05 09:42:12 -07:00
2011-08-25 23:11:14 -07:00
spin_lock_irqsave ( & bus - > reg_lock , flags ) ;
iwl_grab_nic_access ( bus ) ;
2011-04-05 09:42:12 -07:00
2011-08-25 23:11:14 -07:00
iwl_write32 ( bus , HBUS_TARG_MEM_RADDR , addr ) ;
2011-04-05 09:42:12 -07:00
rmb ( ) ;
2011-04-13 03:14:43 -07:00
for ( offs = 0 ; offs < words ; offs + + )
2011-08-25 23:11:14 -07:00
vals [ offs ] = iwl_read32 ( bus , HBUS_TARG_MEM_RDAT ) ;
2011-04-05 09:42:12 -07:00
2011-08-25 23:11:14 -07:00
iwl_release_nic_access ( bus ) ;
spin_unlock_irqrestore ( & bus - > reg_lock , flags ) ;
2011-04-13 03:14:43 -07:00
}
2011-08-25 23:11:14 -07:00
u32 iwl_read_targ_mem ( struct iwl_bus * bus , u32 addr )
2011-04-13 03:14:43 -07:00
{
u32 value ;
2011-08-25 23:11:14 -07:00
_iwl_read_targ_mem_words ( bus , addr , & value , 1 ) ;
2011-04-13 03:14:43 -07:00
2011-04-05 09:42:12 -07:00
return value ;
}
2011-08-25 23:11:14 -07:00
void iwl_write_targ_mem ( struct iwl_bus * bus , u32 addr , u32 val )
2011-04-05 09:42:12 -07:00
{
unsigned long flags ;
2011-08-25 23:11:14 -07:00
spin_lock_irqsave ( & bus - > reg_lock , flags ) ;
if ( ! iwl_grab_nic_access ( bus ) ) {
iwl_write32 ( bus , HBUS_TARG_MEM_WADDR , addr ) ;
2011-04-05 09:42:12 -07:00
wmb ( ) ;
2011-08-25 23:11:14 -07:00
iwl_write32 ( bus , HBUS_TARG_MEM_WDAT , val ) ;
iwl_release_nic_access ( bus ) ;
2011-04-05 09:42:12 -07:00
}
2011-08-25 23:11:14 -07:00
spin_unlock_irqrestore ( & bus - > reg_lock , flags ) ;
2011-04-05 09:42:12 -07:00
}