1521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi/* 2521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * This file is part of wl1271 3521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 4521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * Copyright (C) 2008-2010 Nokia Corporation 5521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 6521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * Contact: Luciano Coelho <luciano.coelho@nokia.com> 7521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 8521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * This program is free software; you can redistribute it and/or 9521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * modify it under the terms of the GNU General Public License 10521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * version 2 as published by the Free Software Foundation. 11521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 12521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * This program is distributed in the hope that it will be useful, but 13521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * WITHOUT ANY WARRANTY; without even the implied warranty of 14521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * General Public License for more details. 16521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 17521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * You should have received a copy of the GNU General Public License 18521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * along with this program; if not, write to the Free Software 19521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 02110-1301 USA 21521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 22521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi */ 23521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 24521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi#include <linux/module.h> 25521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi#include <linux/platform_device.h> 26521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi#include <linux/spi/spi.h> 27a390e85cfe91c346ff4745bcd45ad0a7e7101aa2Felipe Balbi#include <linux/interrupt.h> 28521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 2900d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "wl12xx.h" 300f4e31222a2c0b93f25a87effd2033cb78c7a79cLuciano Coelho#include "debug.h" 31521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi#include "wl12xx_80211.h" 3200d201001bd4e8a46e3d03c970abcb72256c368bShahar Levi#include "io.h" 330da13da767cd568c1fe2a7b5b936e86e521b5ae7Ido Yariv#include "tx.h" 34521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 35760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi#define OCP_CMD_LOOP 32 36760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi 37760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi#define OCP_CMD_WRITE 0x1 38760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi#define OCP_CMD_READ 0x2 39760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi 40760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi#define OCP_READY_MASK BIT(18) 41760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi#define OCP_STATUS_MASK (BIT(16) | BIT(17)) 42760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi 43760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi#define OCP_STATUS_NO_RESP 0x00000 44760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi#define OCP_STATUS_OK 0x10000 45760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi#define OCP_STATUS_REQ_FAILED 0x20000 46760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi#define OCP_STATUS_RESP_ERROR 0x30000 47760d969f9e91a734161a5979a3b3818062e80b7eTeemu Paasikivi 4848a61477bdc04896bd96d259388a0c42a7019943Shahar Levibool wl1271_set_block_size(struct wl1271 *wl) 4948a61477bdc04896bd96d259388a0c42a7019943Shahar Levi{ 5048a61477bdc04896bd96d259388a0c42a7019943Shahar Levi if (wl->if_ops->set_block_size) { 51a390e85cfe91c346ff4745bcd45ad0a7e7101aa2Felipe Balbi wl->if_ops->set_block_size(wl->dev, WL12XX_BUS_BLOCK_SIZE); 5248a61477bdc04896bd96d259388a0c42a7019943Shahar Levi return true; 5348a61477bdc04896bd96d259388a0c42a7019943Shahar Levi } 5448a61477bdc04896bd96d259388a0c42a7019943Shahar Levi 5548a61477bdc04896bd96d259388a0c42a7019943Shahar Levi return false; 5648a61477bdc04896bd96d259388a0c42a7019943Shahar Levi} 5748a61477bdc04896bd96d259388a0c42a7019943Shahar Levi 5854f7e5037c95f2beff0252bfcf288f711c185799Teemu Paasikivivoid wl1271_disable_interrupts(struct wl1271 *wl) 5954f7e5037c95f2beff0252bfcf288f711c185799Teemu Paasikivi{ 60a390e85cfe91c346ff4745bcd45ad0a7e7101aa2Felipe Balbi disable_irq(wl->irq); 6154f7e5037c95f2beff0252bfcf288f711c185799Teemu Paasikivi} 6254f7e5037c95f2beff0252bfcf288f711c185799Teemu Paasikivi 6354f7e5037c95f2beff0252bfcf288f711c185799Teemu Paasikivivoid wl1271_enable_interrupts(struct wl1271 *wl) 6454f7e5037c95f2beff0252bfcf288f711c185799Teemu Paasikivi{ 65a390e85cfe91c346ff4745bcd45ad0a7e7101aa2Felipe Balbi enable_irq(wl->irq); 6654f7e5037c95f2beff0252bfcf288f711c185799Teemu Paasikivi} 6754f7e5037c95f2beff0252bfcf288f711c185799Teemu Paasikivi 68521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi/* Set the SPI partitions to access the chip addresses 69521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 70521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * To simplify driver code, a fixed (virtual) memory map is defined for 71521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * register and memory addresses. Because in the chipset, in different stages 72521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * of operation, those addresses will move around, an address translation 73521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * mechanism is required. 74521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 75521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * There are four partitions (three memory and one register partition), 76521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * which are mapped to two different areas of the hardware memory. 77521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 78521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * Virtual address 79521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * space 80521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 81521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * | | 82521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * ...+----+--> mem.start 83521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * Physical address ... | | 84521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * space ... | | [PART_0] 85521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * ... | | 86521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 00000000 <--+----+... ...+----+--> mem.start + mem.size 87521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * | | ... | | 88521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * |MEM | ... | | 89521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * | | ... | | 90521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * mem.size <--+----+... | | {unused area) 91521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * | | ... | | 92521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * |REG | ... | | 93521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * mem.size | | ... | | 94521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * + <--+----+... ...+----+--> reg.start 95521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * reg.size | | ... | | 96521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * |MEM2| ... | | [PART_1] 97521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * | | ... | | 98521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * ...+----+--> reg.start + reg.size 99521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * | | 100521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi * 101521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi */ 102521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikiviint wl1271_set_partition(struct wl1271 *wl, 103521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi struct wl1271_partition_set *p) 104521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi{ 105521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi /* copy partition info */ 106521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi memcpy(&wl->part, p, sizeof(*p)); 107521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 108521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", 109521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi p->mem.start, p->mem.size); 110521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", 111521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi p->reg.start, p->reg.size); 112521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X", 113521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi p->mem2.start, p->mem2.size); 114521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X", 115521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi p->mem3.start, p->mem3.size); 116521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 117521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi /* write partition info to the chipset */ 118521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); 119521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); 120521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); 121521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); 122521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); 123521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); 124521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); 125521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 126521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi return 0; 127521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi} 128870c367cf829466f315de785ac613dd94eff5c50Roger QuadrosEXPORT_SYMBOL_GPL(wl1271_set_partition); 129521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 1309b28072220d56fda3249cb7e4e164038b456414dTeemu Paasikivivoid wl1271_io_reset(struct wl1271 *wl) 1319b28072220d56fda3249cb7e4e164038b456414dTeemu Paasikivi{ 13277d7d7a36d270fee4591c1c99c83c2da1f399d44Felipe Balbi if (wl->if_ops->reset) 133a390e85cfe91c346ff4745bcd45ad0a7e7101aa2Felipe Balbi wl->if_ops->reset(wl->dev); 1349b28072220d56fda3249cb7e4e164038b456414dTeemu Paasikivi} 1359b28072220d56fda3249cb7e4e164038b456414dTeemu Paasikivi 1369b28072220d56fda3249cb7e4e164038b456414dTeemu Paasikivivoid wl1271_io_init(struct wl1271 *wl) 1379b28072220d56fda3249cb7e4e164038b456414dTeemu Paasikivi{ 13877d7d7a36d270fee4591c1c99c83c2da1f399d44Felipe Balbi if (wl->if_ops->init) 139a390e85cfe91c346ff4745bcd45ad0a7e7101aa2Felipe Balbi wl->if_ops->init(wl->dev); 1409b28072220d56fda3249cb7e4e164038b456414dTeemu Paasikivi} 1419b28072220d56fda3249cb7e4e164038b456414dTeemu Paasikivi 142521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivivoid wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) 143521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi{ 144521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi /* write address >> 1 + 0x30000 to OCP_POR_CTR */ 145521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi addr = (addr >> 1) + 0x30000; 1467b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write32(wl, OCP_POR_CTR, addr); 147521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 148521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi /* write value to OCP_POR_WDATA */ 1497b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write32(wl, OCP_DATA_WRITE, val); 150521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 151521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi /* write 1 to OCP_CMD */ 1527b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write32(wl, OCP_CMD, OCP_CMD_WRITE); 153521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi} 154521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 155521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikiviu16 wl1271_top_reg_read(struct wl1271 *wl, int addr) 156521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi{ 157521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi u32 val; 158521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi int timeout = OCP_CMD_LOOP; 159521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 160521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi /* write address >> 1 + 0x30000 to OCP_POR_CTR */ 161521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi addr = (addr >> 1) + 0x30000; 1627b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write32(wl, OCP_POR_CTR, addr); 163521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 164521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi /* write 2 to OCP_CMD */ 1657b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi wl1271_write32(wl, OCP_CMD, OCP_CMD_READ); 166521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 167521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi /* poll for data ready */ 168521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi do { 1697b048c52d7283ebf07c826a45c631a6ba225c057Teemu Paasikivi val = wl1271_read32(wl, OCP_DATA_READ); 170521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi } while (!(val & OCP_READY_MASK) && --timeout); 171521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 172521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi if (!timeout) { 173521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_warning("Top register access timed out."); 174521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi return 0xffff; 175521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi } 176521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 177521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi /* check data status and return if OK */ 178521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) 179521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi return val & 0xffff; 180521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi else { 181521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi wl1271_warning("Top register access returned error."); 182521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi return 0xffff; 183521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi } 184521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi} 185521a5b2137cc15430e3b1ea4c148663d1dbe077fTeemu Paasikivi 186