io.c (6312B)
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 */ 13static 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 27static 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 44static int wl1251_translate_mem_addr(struct wl1251 *wl, int addr) 45{ 46 return addr - wl->physical_mem_addr + wl->virtual_mem_addr; 47} 48 49void 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 58void 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 67u32 wl1251_mem_read32(struct wl1251 *wl, int addr) 68{ 69 return wl1251_read32(wl, wl1251_translate_mem_addr(wl, addr)); 70} 71 72void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val) 73{ 74 wl1251_write32(wl, wl1251_translate_mem_addr(wl, addr), val); 75} 76 77u32 wl1251_reg_read32(struct wl1251 *wl, int addr) 78{ 79 return wl1251_read32(wl, wl1251_translate_reg_addr(wl, addr)); 80} 81 82void 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 */ 120void 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_set *partition; 125 126 partition = kmalloc(sizeof(*partition), GFP_KERNEL); 127 if (!partition) { 128 wl1251_error("can not allocate partition buffer"); 129 return; 130 } 131 132 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", 133 mem_start, mem_size); 134 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", 135 reg_start, reg_size); 136 137 /* Make sure that the two partitions together don't exceed the 138 * address range */ 139 if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) { 140 wl1251_debug(DEBUG_SPI, "Total size exceeds maximum virtual" 141 " address range. Truncating partition[0]."); 142 mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size; 143 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", 144 mem_start, mem_size); 145 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", 146 reg_start, reg_size); 147 } 148 149 if ((mem_start < reg_start) && 150 ((mem_start + mem_size) > reg_start)) { 151 /* Guarantee that the memory partition doesn't overlap the 152 * registers partition */ 153 wl1251_debug(DEBUG_SPI, "End of partition[0] is " 154 "overlapping partition[1]. Adjusted."); 155 mem_size = reg_start - mem_start; 156 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", 157 mem_start, mem_size); 158 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", 159 reg_start, reg_size); 160 } else if ((reg_start < mem_start) && 161 ((reg_start + reg_size) > mem_start)) { 162 /* Guarantee that the register partition doesn't overlap the 163 * memory partition */ 164 wl1251_debug(DEBUG_SPI, "End of partition[1] is" 165 " overlapping partition[0]. Adjusted."); 166 reg_size = mem_start - reg_start; 167 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", 168 mem_start, mem_size); 169 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", 170 reg_start, reg_size); 171 } 172 173 partition->mem.start = mem_start; 174 partition->mem.size = mem_size; 175 partition->reg.start = reg_start; 176 partition->reg.size = reg_size; 177 178 wl->physical_mem_addr = mem_start; 179 wl->physical_reg_addr = reg_start; 180 181 wl->virtual_mem_addr = 0; 182 wl->virtual_reg_addr = mem_size; 183 184 wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition, 185 sizeof(*partition)); 186 187 kfree(partition); 188}