root/drivers/net/wireless/ti/wl1251/io.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wl1251_translate_reg_addr
  2. wl1251_translate_mem_addr
  3. wl1251_mem_read
  4. wl1251_mem_write
  5. wl1251_mem_read32
  6. wl1251_mem_write32
  7. wl1251_reg_read32
  8. wl1251_reg_write32
  9. wl1251_set_partition

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * This file is part of wl12xx
   4  *
   5  * Copyright (C) 2008 Nokia Corporation
   6  */
   7 
   8 #include "wl1251.h"
   9 #include "reg.h"
  10 #include "io.h"
  11 
  12 /* FIXME: this is static data nowadays and the table can be removed */
  13 static enum wl12xx_acx_int_reg wl1251_io_reg_table[ACX_REG_TABLE_LEN] = {
  14         [ACX_REG_INTERRUPT_TRIG]     = (REGISTERS_BASE + 0x0474),
  15         [ACX_REG_INTERRUPT_TRIG_H]   = (REGISTERS_BASE + 0x0478),
  16         [ACX_REG_INTERRUPT_MASK]     = (REGISTERS_BASE + 0x0494),
  17         [ACX_REG_HINT_MASK_SET]      = (REGISTERS_BASE + 0x0498),
  18         [ACX_REG_HINT_MASK_CLR]      = (REGISTERS_BASE + 0x049C),
  19         [ACX_REG_INTERRUPT_NO_CLEAR] = (REGISTERS_BASE + 0x04B0),
  20         [ACX_REG_INTERRUPT_CLEAR]    = (REGISTERS_BASE + 0x04A4),
  21         [ACX_REG_INTERRUPT_ACK]      = (REGISTERS_BASE + 0x04A8),
  22         [ACX_REG_SLV_SOFT_RESET]     = (REGISTERS_BASE + 0x0000),
  23         [ACX_REG_EE_START]           = (REGISTERS_BASE + 0x080C),
  24         [ACX_REG_ECPU_CONTROL]       = (REGISTERS_BASE + 0x0804)
  25 };
  26 
  27 static int wl1251_translate_reg_addr(struct wl1251 *wl, int addr)
  28 {
  29         /* If the address is lower than REGISTERS_BASE, it means that this is
  30          * a chip-specific register address, so look it up in the registers
  31          * table */
  32         if (addr < REGISTERS_BASE) {
  33                 /* Make sure we don't go over the table */
  34                 if (addr >= ACX_REG_TABLE_LEN) {
  35                         wl1251_error("address out of range (%d)", addr);
  36                         return -EINVAL;
  37                 }
  38                 addr = wl1251_io_reg_table[addr];
  39         }
  40 
  41         return addr - wl->physical_reg_addr + wl->virtual_reg_addr;
  42 }
  43 
  44 static int wl1251_translate_mem_addr(struct wl1251 *wl, int addr)
  45 {
  46         return addr - wl->physical_mem_addr + wl->virtual_mem_addr;
  47 }
  48 
  49 void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len)
  50 {
  51         int physical;
  52 
  53         physical = wl1251_translate_mem_addr(wl, addr);
  54 
  55         wl->if_ops->read(wl, physical, buf, len);
  56 }
  57 
  58 void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len)
  59 {
  60         int physical;
  61 
  62         physical = wl1251_translate_mem_addr(wl, addr);
  63 
  64         wl->if_ops->write(wl, physical, buf, len);
  65 }
  66 
  67 u32 wl1251_mem_read32(struct wl1251 *wl, int addr)
  68 {
  69         return wl1251_read32(wl, wl1251_translate_mem_addr(wl, addr));
  70 }
  71 
  72 void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val)
  73 {
  74         wl1251_write32(wl, wl1251_translate_mem_addr(wl, addr), val);
  75 }
  76 
  77 u32 wl1251_reg_read32(struct wl1251 *wl, int addr)
  78 {
  79         return wl1251_read32(wl, wl1251_translate_reg_addr(wl, addr));
  80 }
  81 
  82 void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val)
  83 {
  84         wl1251_write32(wl, wl1251_translate_reg_addr(wl, addr), val);
  85 }
  86 
  87 /* Set the partitions to access the chip addresses.
  88  *
  89  * There are two VIRTUAL partitions (the memory partition and the
  90  * registers partition), which are mapped to two different areas of the
  91  * PHYSICAL (hardware) memory.  This function also makes other checks to
  92  * ensure that the partitions are not overlapping.  In the diagram below, the
  93  * memory partition comes before the register partition, but the opposite is
  94  * also supported.
  95  *
  96  *                               PHYSICAL address
  97  *                                     space
  98  *
  99  *                                    |    |
 100  *                                 ...+----+--> mem_start
 101  *          VIRTUAL address     ...   |    |
 102  *               space       ...      |    | [PART_0]
 103  *                        ...         |    |
 104  * 0x00000000 <--+----+...         ...+----+--> mem_start + mem_size
 105  *               |    |         ...   |    |
 106  *               |MEM |      ...      |    |
 107  *               |    |   ...         |    |
 108  *  part_size <--+----+...            |    | {unused area)
 109  *               |    |   ...         |    |
 110  *               |REG |      ...      |    |
 111  *  part_size    |    |         ...   |    |
 112  *      +     <--+----+...         ...+----+--> reg_start
 113  *  reg_size              ...         |    |
 114  *                           ...      |    | [PART_1]
 115  *                              ...   |    |
 116  *                                 ...+----+--> reg_start + reg_size
 117  *                                    |    |
 118  *
 119  */
 120 void wl1251_set_partition(struct wl1251 *wl,
 121                           u32 mem_start, u32 mem_size,
 122                           u32 reg_start, u32 reg_size)
 123 {
 124         struct wl1251_partition partition[2];
 125 
 126         wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
 127                      mem_start, mem_size);
 128         wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
 129                      reg_start, reg_size);
 130 
 131         /* Make sure that the two partitions together don't exceed the
 132          * address range */
 133         if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) {
 134                 wl1251_debug(DEBUG_SPI, "Total size exceeds maximum virtual"
 135                              " address range.  Truncating partition[0].");
 136                 mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size;
 137                 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
 138                              mem_start, mem_size);
 139                 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
 140                              reg_start, reg_size);
 141         }
 142 
 143         if ((mem_start < reg_start) &&
 144             ((mem_start + mem_size) > reg_start)) {
 145                 /* Guarantee that the memory partition doesn't overlap the
 146                  * registers partition */
 147                 wl1251_debug(DEBUG_SPI, "End of partition[0] is "
 148                              "overlapping partition[1].  Adjusted.");
 149                 mem_size = reg_start - mem_start;
 150                 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
 151                              mem_start, mem_size);
 152                 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
 153                              reg_start, reg_size);
 154         } else if ((reg_start < mem_start) &&
 155                    ((reg_start + reg_size) > mem_start)) {
 156                 /* Guarantee that the register partition doesn't overlap the
 157                  * memory partition */
 158                 wl1251_debug(DEBUG_SPI, "End of partition[1] is"
 159                              " overlapping partition[0].  Adjusted.");
 160                 reg_size = mem_start - reg_start;
 161                 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
 162                              mem_start, mem_size);
 163                 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
 164                              reg_start, reg_size);
 165         }
 166 
 167         partition[0].start = mem_start;
 168         partition[0].size  = mem_size;
 169         partition[1].start = reg_start;
 170         partition[1].size  = reg_size;
 171 
 172         wl->physical_mem_addr = mem_start;
 173         wl->physical_reg_addr = reg_start;
 174 
 175         wl->virtual_mem_addr = 0;
 176         wl->virtual_reg_addr = mem_size;
 177 
 178         wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition,
 179                 sizeof(partition));
 180 }

/* [<][>][^][v][top][bottom][index][help] */