linux/drivers/net/wireless/iwlwifi/iwl-io.h
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
   4 *
   5 * Portions of this file are derived from the ipw3945 project.
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of version 2 of the GNU General Public License as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful, but WITHOUT
  12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  14 * more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along with
  17 * this program; if not, write to the Free Software Foundation, Inc.,
  18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  19 *
  20 * The full GNU General Public License is included in this distribution in the
  21 * file called LICENSE.
  22 *
  23 * Contact Information:
  24 * James P. Ketrenos <ipw2100-admin@linux.intel.com>
  25 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  26 *
  27 *****************************************************************************/
  28
  29#ifndef __iwl_io_h__
  30#define __iwl_io_h__
  31
  32#include <linux/io.h>
  33
  34#include "iwl-debug.h"
  35
  36/*
  37 * IO, register, and NIC memory access functions
  38 *
  39 * NOTE on naming convention and macro usage for these
  40 *
  41 * A single _ prefix before a an access function means that no state
  42 * check or debug information is printed when that function is called.
  43 *
  44 * A double __ prefix before an access function means that state is checked
  45 * (in the case of *restricted calls) and the current line number is printed
  46 * in addition to any other debug output.
  47 *
  48 * The non-prefixed name is the #define that maps the caller into a
  49 * #define that provides the caller's __LINE__ to the double prefix version.
  50 *
  51 * If you wish to call the function without any debug or state checking,
  52 * you should use the single _ prefix version (as is used by dependent IO
  53 * routines, for example _iwl_read_restricted calls the non-check version of
  54 * _iwl_read32.)
  55 *
  56 * These declarations are *extremely* useful in quickly isolating code deltas
  57 * which result in misconfiguring of the hardware I/O.  In combination with
  58 * git-bisect and the IO debug level you can quickly determine the specific
  59 * commit which breaks the IO sequence to the hardware.
  60 *
  61 */
  62
  63#define _iwl_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
  64#ifdef CONFIG_IWLWIFI_DEBUG
  65static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *iwl,
  66                                 u32 ofs, u32 val)
  67{
  68        IWL_DEBUG_IO("write_direct32(0x%08X, 0x%08X) - %s %d\n",
  69                     (u32) (ofs), (u32) (val), f, l);
  70        _iwl_write32(iwl, ofs, val);
  71}
  72#define iwl_write32(iwl, ofs, val) \
  73        __iwl_write32(__FILE__, __LINE__, iwl, ofs, val)
  74#else
  75#define iwl_write32(iwl, ofs, val) _iwl_write32(iwl, ofs, val)
  76#endif
  77
  78#define _iwl_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
  79#ifdef CONFIG_IWLWIFI_DEBUG
  80static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *iwl, u32 ofs)
  81{
  82        IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
  83        return _iwl_read32(iwl, ofs);
  84}
  85#define iwl_read32(iwl, ofs) __iwl_read32(__FILE__, __LINE__, iwl, ofs)
  86#else
  87#define iwl_read32(p, o) _iwl_read32(p, o)
  88#endif
  89
  90static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr,
  91                                u32 bits, u32 mask, int timeout)
  92{
  93        int i = 0;
  94
  95        do {
  96                if ((_iwl_read32(priv, addr) & mask) == (bits & mask))
  97                        return i;
  98                mdelay(10);
  99                i += 10;
 100        } while (i < timeout);
 101
 102        return -ETIMEDOUT;
 103}
 104#ifdef CONFIG_IWLWIFI_DEBUG
 105static inline int __iwl_poll_bit(const char *f, u32 l,
 106                                 struct iwl_priv *priv, u32 addr,
 107                                 u32 bits, u32 mask, int timeout)
 108{
 109        int rc = _iwl_poll_bit(priv, addr, bits, mask, timeout);
 110        if (unlikely(rc == -ETIMEDOUT))
 111                IWL_DEBUG_IO
 112                    ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
 113                     addr, bits, mask, f, l);
 114        else
 115                IWL_DEBUG_IO
 116                    ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
 117                     addr, bits, mask, rc, f, l);
 118        return rc;
 119}
 120#define iwl_poll_bit(iwl, addr, bits, mask, timeout) \
 121        __iwl_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
 122#else
 123#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t)
 124#endif
 125
 126static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
 127{
 128        _iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask);
 129}
 130#ifdef CONFIG_IWLWIFI_DEBUG
 131static inline void __iwl_set_bit(const char *f, u32 l,
 132                                 struct iwl_priv *priv, u32 reg, u32 mask)
 133{
 134        u32 val = _iwl_read32(priv, reg) | mask;
 135        IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
 136        _iwl_write32(priv, reg, val);
 137}
 138#define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m)
 139#else
 140#define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m)
 141#endif
 142
 143static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
 144{
 145        _iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask);
 146}
 147#ifdef CONFIG_IWLWIFI_DEBUG
 148static inline void __iwl_clear_bit(const char *f, u32 l,
 149                                   struct iwl_priv *priv, u32 reg, u32 mask)
 150{
 151        u32 val = _iwl_read32(priv, reg) & ~mask;
 152        IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
 153        _iwl_write32(priv, reg, val);
 154}
 155#define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m)
 156#else
 157#define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m)
 158#endif
 159
 160static inline int _iwl_grab_restricted_access(struct iwl_priv *priv)
 161{
 162        int rc;
 163        u32 gp_ctl;
 164
 165#ifdef CONFIG_IWLWIFI_DEBUG
 166        if (atomic_read(&priv->restrict_refcnt))
 167                return 0;
 168#endif
 169        if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
 170            test_bit(STATUS_RF_KILL_SW, &priv->status)) {
 171                IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
 172                        "wakes up NIC\n");
 173
 174                /* 10 msec allows time for NIC to complete its data save */
 175                gp_ctl = _iwl_read32(priv, CSR_GP_CNTRL);
 176                if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
 177                        IWL_DEBUG_RF_KILL("Wait for complete power-down, "
 178                                "gpctl = 0x%08x\n", gp_ctl);
 179                        mdelay(10);
 180                } else
 181                        IWL_DEBUG_RF_KILL("power-down complete, "
 182                                          "gpctl = 0x%08x\n", gp_ctl);
 183        }
 184
 185        /* this bit wakes up the NIC */
 186        _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 187        rc = _iwl_poll_bit(priv, CSR_GP_CNTRL,
 188                           CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
 189                           (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
 190                            CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
 191        if (rc < 0) {
 192                IWL_ERROR("MAC is in deep sleep!\n");
 193                return -EIO;
 194        }
 195
 196#ifdef CONFIG_IWLWIFI_DEBUG
 197        atomic_inc(&priv->restrict_refcnt);
 198#endif
 199        return 0;
 200}
 201
 202#ifdef CONFIG_IWLWIFI_DEBUG
 203static inline int __iwl_grab_restricted_access(const char *f, u32 l,
 204                                               struct iwl_priv *priv)
 205{
 206        if (atomic_read(&priv->restrict_refcnt))
 207                IWL_DEBUG_INFO("Grabbing access while already held at "
 208                               "line %d.\n", l);
 209
 210        IWL_DEBUG_IO("grabbing restricted access - %s %d\n", f, l);
 211
 212        return _iwl_grab_restricted_access(priv);
 213}
 214#define iwl_grab_restricted_access(priv) \
 215        __iwl_grab_restricted_access(__FILE__, __LINE__, priv)
 216#else
 217#define iwl_grab_restricted_access(priv) \
 218        _iwl_grab_restricted_access(priv)
 219#endif
 220
 221static inline void _iwl_release_restricted_access(struct iwl_priv *priv)
 222{
 223#ifdef CONFIG_IWLWIFI_DEBUG
 224        if (atomic_dec_and_test(&priv->restrict_refcnt))
 225#endif
 226                _iwl_clear_bit(priv, CSR_GP_CNTRL,
 227                               CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 228}
 229#ifdef CONFIG_IWLWIFI_DEBUG
 230static inline void __iwl_release_restricted_access(const char *f, u32 l,
 231                                                   struct iwl_priv *priv)
 232{
 233        if (atomic_read(&priv->restrict_refcnt) <= 0)
 234                IWL_ERROR("Release unheld restricted access at line %d.\n", l);
 235
 236        IWL_DEBUG_IO("releasing restricted access - %s %d\n", f, l);
 237        _iwl_release_restricted_access(priv);
 238}
 239#define iwl_release_restricted_access(priv) \
 240        __iwl_release_restricted_access(__FILE__, __LINE__, priv)
 241#else
 242#define iwl_release_restricted_access(priv) \
 243        _iwl_release_restricted_access(priv)
 244#endif
 245
 246static inline u32 _iwl_read_restricted(struct iwl_priv *priv, u32 reg)
 247{
 248        return _iwl_read32(priv, reg);
 249}
 250#ifdef CONFIG_IWLWIFI_DEBUG
 251static inline u32 __iwl_read_restricted(const char *f, u32 l,
 252                                        struct iwl_priv *priv, u32 reg)
 253{
 254        u32 value = _iwl_read_restricted(priv, reg);
 255        if (!atomic_read(&priv->restrict_refcnt))
 256                IWL_ERROR("Unrestricted access from %s %d\n", f, l);
 257        IWL_DEBUG_IO("read_restricted(0x%4X) = 0x%08x - %s %d \n", reg, value,
 258                     f, l);
 259        return value;
 260}
 261#define iwl_read_restricted(priv, reg) \
 262        __iwl_read_restricted(__FILE__, __LINE__, priv, reg)
 263#else
 264#define iwl_read_restricted _iwl_read_restricted
 265#endif
 266
 267static inline void _iwl_write_restricted(struct iwl_priv *priv,
 268                                         u32 reg, u32 value)
 269{
 270        _iwl_write32(priv, reg, value);
 271}
 272#ifdef CONFIG_IWLWIFI_DEBUG
 273static void __iwl_write_restricted(u32 line,
 274                                   struct iwl_priv *priv, u32 reg, u32 value)
 275{
 276        if (!atomic_read(&priv->restrict_refcnt))
 277                IWL_ERROR("Unrestricted access from line %d\n", line);
 278        _iwl_write_restricted(priv, reg, value);
 279}
 280#define iwl_write_restricted(priv, reg, value) \
 281        __iwl_write_restricted(__LINE__, priv, reg, value)
 282#else
 283#define iwl_write_restricted _iwl_write_restricted
 284#endif
 285
 286static inline void iwl_write_buffer_restricted(struct iwl_priv *priv,
 287                                               u32 reg, u32 len, u32 *values)
 288{
 289        u32 count = sizeof(u32);
 290
 291        if ((priv != NULL) && (values != NULL)) {
 292                for (; 0 < len; len -= count, reg += count, values++)
 293                        _iwl_write_restricted(priv, reg, *values);
 294        }
 295}
 296
 297static inline int _iwl_poll_restricted_bit(struct iwl_priv *priv,
 298                                           u32 addr, u32 mask, int timeout)
 299{
 300        int i = 0;
 301
 302        do {
 303                if ((_iwl_read_restricted(priv, addr) & mask) == mask)
 304                        return i;
 305                mdelay(10);
 306                i += 10;
 307        } while (i < timeout);
 308
 309        return -ETIMEDOUT;
 310}
 311
 312#ifdef CONFIG_IWLWIFI_DEBUG
 313static inline int __iwl_poll_restricted_bit(const char *f, u32 l,
 314                                            struct iwl_priv *priv,
 315                                            u32 addr, u32 mask, int timeout)
 316{
 317        int rc = _iwl_poll_restricted_bit(priv, addr, mask, timeout);
 318
 319        if (unlikely(rc == -ETIMEDOUT))
 320                IWL_DEBUG_IO("poll_restricted_bit(0x%08X, 0x%08X) - "
 321                             "timedout - %s %d\n", addr, mask, f, l);
 322        else
 323                IWL_DEBUG_IO("poll_restricted_bit(0x%08X, 0x%08X) = 0x%08X "
 324                             "- %s %d\n", addr, mask, rc, f, l);
 325        return rc;
 326}
 327#define iwl_poll_restricted_bit(iwl, addr, mask, timeout) \
 328        __iwl_poll_restricted_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
 329#else
 330#define iwl_poll_restricted_bit _iwl_poll_restricted_bit
 331#endif
 332
 333static inline u32 _iwl_read_restricted_reg(struct iwl_priv *priv, u32 reg)
 334{
 335        _iwl_write_restricted(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
 336        return _iwl_read_restricted(priv, HBUS_TARG_PRPH_RDAT);
 337}
 338#ifdef CONFIG_IWLWIFI_DEBUG
 339static inline u32 __iwl_read_restricted_reg(u32 line,
 340                                            struct iwl_priv *priv, u32 reg)
 341{
 342        if (!atomic_read(&priv->restrict_refcnt))
 343                IWL_ERROR("Unrestricted access from line %d\n", line);
 344        return _iwl_read_restricted_reg(priv, reg);
 345}
 346
 347#define iwl_read_restricted_reg(priv, reg) \
 348        __iwl_read_restricted_reg(__LINE__, priv, reg)
 349#else
 350#define iwl_read_restricted_reg _iwl_read_restricted_reg
 351#endif
 352
 353static inline void _iwl_write_restricted_reg(struct iwl_priv *priv,
 354                                             u32 addr, u32 val)
 355{
 356        _iwl_write_restricted(priv, HBUS_TARG_PRPH_WADDR,
 357                              ((addr & 0x0000FFFF) | (3 << 24)));
 358        _iwl_write_restricted(priv, HBUS_TARG_PRPH_WDAT, val);
 359}
 360#ifdef CONFIG_IWLWIFI_DEBUG
 361static inline void __iwl_write_restricted_reg(u32 line,
 362                                              struct iwl_priv *priv,
 363                                              u32 addr, u32 val)
 364{
 365        if (!atomic_read(&priv->restrict_refcnt))
 366                IWL_ERROR("Unrestricted access from line %d\n", line);
 367        _iwl_write_restricted_reg(priv, addr, val);
 368}
 369
 370#define iwl_write_restricted_reg(priv, addr, val) \
 371        __iwl_write_restricted_reg(__LINE__, priv, addr, val);
 372#else
 373#define iwl_write_restricted_reg _iwl_write_restricted_reg
 374#endif
 375
 376#define _iwl_set_bits_restricted_reg(priv, reg, mask) \
 377        _iwl_write_restricted_reg(priv, reg, \
 378                                  (_iwl_read_restricted_reg(priv, reg) | mask))
 379#ifdef CONFIG_IWLWIFI_DEBUG
 380static inline void __iwl_set_bits_restricted_reg(u32 line, struct iwl_priv
 381                                                 *priv, u32 reg, u32 mask)
 382{
 383        if (!atomic_read(&priv->restrict_refcnt))
 384                IWL_ERROR("Unrestricted access from line %d\n", line);
 385        _iwl_set_bits_restricted_reg(priv, reg, mask);
 386}
 387#define iwl_set_bits_restricted_reg(priv, reg, mask) \
 388        __iwl_set_bits_restricted_reg(__LINE__, priv, reg, mask)
 389#else
 390#define iwl_set_bits_restricted_reg _iwl_set_bits_restricted_reg
 391#endif
 392
 393#define _iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask) \
 394        _iwl_write_restricted_reg( \
 395            priv, reg, ((_iwl_read_restricted_reg(priv, reg) & mask) | bits))
 396#ifdef CONFIG_IWLWIFI_DEBUG
 397static inline void __iwl_set_bits_mask_restricted_reg(u32 line,
 398                struct iwl_priv *priv, u32 reg, u32 bits, u32 mask)
 399{
 400        if (!atomic_read(&priv->restrict_refcnt))
 401                IWL_ERROR("Unrestricted access from line %d\n", line);
 402        _iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask);
 403}
 404
 405#define iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask) \
 406        __iwl_set_bits_mask_restricted_reg(__LINE__, priv, reg, bits, mask)
 407#else
 408#define iwl_set_bits_mask_restricted_reg _iwl_set_bits_mask_restricted_reg
 409#endif
 410
 411static inline void iwl_clear_bits_restricted_reg(struct iwl_priv
 412                                                 *priv, u32 reg, u32 mask)
 413{
 414        u32 val = _iwl_read_restricted_reg(priv, reg);
 415        _iwl_write_restricted_reg(priv, reg, (val & ~mask));
 416}
 417
 418static inline u32 iwl_read_restricted_mem(struct iwl_priv *priv, u32 addr)
 419{
 420        iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR, addr);
 421        return iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
 422}
 423
 424static inline void iwl_write_restricted_mem(struct iwl_priv *priv, u32 addr,
 425                                            u32 val)
 426{
 427        iwl_write_restricted(priv, HBUS_TARG_MEM_WADDR, addr);
 428        iwl_write_restricted(priv, HBUS_TARG_MEM_WDAT, val);
 429}
 430
 431static inline void iwl_write_restricted_mems(struct iwl_priv *priv, u32 addr,
 432                                             u32 len, u32 *values)
 433{
 434        iwl_write_restricted(priv, HBUS_TARG_MEM_WADDR, addr);
 435        for (; 0 < len; len -= sizeof(u32), values++)
 436                iwl_write_restricted(priv, HBUS_TARG_MEM_WDAT, *values);
 437}
 438
 439static inline void iwl_write_restricted_regs(struct iwl_priv *priv, u32 reg,
 440                                             u32 len, u8 *values)
 441{
 442        u32 reg_offset = reg;
 443        u32 aligment = reg & 0x3;
 444
 445        /* write any non-dword-aligned stuff at the beginning */
 446        if (len < sizeof(u32)) {
 447                if ((aligment + len) <= sizeof(u32)) {
 448                        u8 size;
 449                        u32 value = 0;
 450                        size = len - 1;
 451                        memcpy(&value, values, len);
 452                        reg_offset = (reg_offset & 0x0000FFFF);
 453
 454                        _iwl_write_restricted(priv,
 455                                              HBUS_TARG_PRPH_WADDR,
 456                                              (reg_offset | (size << 24)));
 457                        _iwl_write_restricted(priv, HBUS_TARG_PRPH_WDAT,
 458                                              value);
 459                }
 460
 461                return;
 462        }
 463
 464        /* now write all the dword-aligned stuff */
 465        for (; reg_offset < (reg + len);
 466             reg_offset += sizeof(u32), values += sizeof(u32))
 467                _iwl_write_restricted_reg(priv, reg_offset, *((u32 *) values));
 468}
 469
 470#endif
 471