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 } 181