spi.c 10.2 KB
Newer Older
L
Luciano Coelho 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * This file is part of wl1271
 *
 * Copyright (C) 2008-2009 Nokia Corporation
 *
 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

24
#include <linux/interrupt.h>
25
#include <linux/irq.h>
L
Luciano Coelho 已提交
26 27 28
#include <linux/module.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
29
#include <linux/wl12xx.h>
30
#include <linux/platform_device.h>
31
#include <linux/slab.h>
L
Luciano Coelho 已提交
32

33
#include "wlcore.h"
L
Luciano Coelho 已提交
34
#include "wl12xx_80211.h"
S
Shahar Levi 已提交
35
#include "io.h"
L
Luciano Coelho 已提交
36

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
#define WSPI_CMD_READ                 0x40000000
#define WSPI_CMD_WRITE                0x00000000
#define WSPI_CMD_FIXED                0x20000000
#define WSPI_CMD_BYTE_LENGTH          0x1FFE0000
#define WSPI_CMD_BYTE_LENGTH_OFFSET   17
#define WSPI_CMD_BYTE_ADDR            0x0001FFFF

#define WSPI_INIT_CMD_CRC_LEN       5

#define WSPI_INIT_CMD_START         0x00
#define WSPI_INIT_CMD_TX            0x40
/* the extra bypass bit is sampled by the TNET as '1' */
#define WSPI_INIT_CMD_BYPASS_BIT    0x80
#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07
#define WSPI_INIT_CMD_EN_FIXEDBUSY  0x80
#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00
#define WSPI_INIT_CMD_IOD           0x40
#define WSPI_INIT_CMD_IP            0x20
#define WSPI_INIT_CMD_CS            0x10
#define WSPI_INIT_CMD_WS            0x08
#define WSPI_INIT_CMD_WSPI          0x01
#define WSPI_INIT_CMD_END           0x01

#define WSPI_INIT_CMD_LEN           8

#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \
		((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32))
#define HW_ACCESS_WSPI_INIT_CMD_MASK  0

I
Ido Yariv 已提交
66 67 68 69 70
/* HW limitation: maximum possible chunk size is 4095 bytes */
#define WSPI_MAX_CHUNK_SIZE    4092

#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)

71 72
struct wl12xx_spi_glue {
	struct device *dev;
73
	struct platform_device *core;
74 75
};

76
static void wl12xx_spi_reset(struct device *child)
77
{
78
	struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
L
Luciano Coelho 已提交
79 80 81 82 83 84
	u8 *cmd;
	struct spi_transfer t;
	struct spi_message m;

	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
	if (!cmd) {
85 86
		dev_err(child->parent,
			"could not allocate cmd for spi reset\n");
L
Luciano Coelho 已提交
87 88 89 90 91 92 93 94 95 96 97 98
		return;
	}

	memset(&t, 0, sizeof(t));
	spi_message_init(&m);

	memset(cmd, 0xff, WSPI_INIT_CMD_LEN);

	t.tx_buf = cmd;
	t.len = WSPI_INIT_CMD_LEN;
	spi_message_add_tail(&t, &m);

99
	spi_sync(to_spi_device(glue->dev), &m);
L
Luciano Coelho 已提交
100

101
	kfree(cmd);
L
Luciano Coelho 已提交
102 103
}

104
static void wl12xx_spi_init(struct device *child)
L
Luciano Coelho 已提交
105
{
106
	struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
L
Luciano Coelho 已提交
107 108 109 110 111 112
	u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
	struct spi_transfer t;
	struct spi_message m;

	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
	if (!cmd) {
113 114
		dev_err(child->parent,
			"could not allocate cmd for spi init\n");
L
Luciano Coelho 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
		return;
	}

	memset(crc, 0, sizeof(crc));
	memset(&t, 0, sizeof(t));
	spi_message_init(&m);

	/*
	 * Set WSPI_INIT_COMMAND
	 * the data is being send from the MSB to LSB
	 */
	cmd[2] = 0xff;
	cmd[3] = 0xff;
	cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
	cmd[0] = 0;
	cmd[7] = 0;
	cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
	cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;

	if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
		cmd[5] |=  WSPI_INIT_CMD_DIS_FIXEDBUSY;
	else
		cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;

	cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
		| WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;

	crc[0] = cmd[1];
	crc[1] = cmd[0];
	crc[2] = cmd[7];
	crc[3] = cmd[6];
	crc[4] = cmd[5];

	cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
	cmd[4] |= WSPI_INIT_CMD_END;

	t.tx_buf = cmd;
	t.len = WSPI_INIT_CMD_LEN;
	spi_message_add_tail(&t, &m);

155
	spi_sync(to_spi_device(glue->dev), &m);
156
	kfree(cmd);
L
Luciano Coelho 已提交
157 158
}

159 160
#define WL1271_BUSY_WORD_TIMEOUT 1000

161
static int wl12xx_spi_read_busy(struct device *child)
162
{
163 164
	struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
	struct wl1271 *wl = dev_get_drvdata(child);
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
	struct spi_transfer t[1];
	struct spi_message m;
	u32 *busy_buf;
	int num_busy_bytes = 0;

	/*
	 * Read further busy words from SPI until a non-busy word is
	 * encountered, then read the data itself into the buffer.
	 */

	num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT;
	busy_buf = wl->buffer_busyword;
	while (num_busy_bytes) {
		num_busy_bytes--;
		spi_message_init(&m);
		memset(t, 0, sizeof(t));
		t[0].rx_buf = busy_buf;
		t[0].len = sizeof(u32);
183
		t[0].cs_change = true;
184
		spi_message_add_tail(&t[0], &m);
185
		spi_sync(to_spi_device(glue->dev), &m);
186

187 188
		if (*busy_buf & 0x1)
			return 0;
189 190 191
	}

	/* The SPI bus is unresponsive, the read failed. */
192
	dev_err(child->parent, "SPI read busy-word timeout!\n");
193
	return -ETIMEDOUT;
194 195
}

196 197
static int __must_check wl12xx_spi_raw_read(struct device *child, int addr,
					    void *buf, size_t len, bool fixed)
L
Luciano Coelho 已提交
198
{
199 200
	struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
	struct wl1271 *wl = dev_get_drvdata(child);
I
Ido Yariv 已提交
201
	struct spi_transfer t[2];
L
Luciano Coelho 已提交
202
	struct spi_message m;
203
	u32 *busy_buf;
L
Luciano Coelho 已提交
204
	u32 *cmd;
I
Ido Yariv 已提交
205
	u32 chunk_len;
L
Luciano Coelho 已提交
206

I
Ido Yariv 已提交
207 208
	while (len > 0) {
		chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
L
Luciano Coelho 已提交
209

I
Ido Yariv 已提交
210 211
		cmd = &wl->buffer_cmd;
		busy_buf = wl->buffer_busyword;
L
Luciano Coelho 已提交
212

I
Ido Yariv 已提交
213 214 215 216 217
		*cmd = 0;
		*cmd |= WSPI_CMD_READ;
		*cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) &
			WSPI_CMD_BYTE_LENGTH;
		*cmd |= addr & WSPI_CMD_BYTE_ADDR;
L
Luciano Coelho 已提交
218

I
Ido Yariv 已提交
219 220
		if (fixed)
			*cmd |= WSPI_CMD_FIXED;
L
Luciano Coelho 已提交
221

I
Ido Yariv 已提交
222 223
		spi_message_init(&m);
		memset(t, 0, sizeof(t));
L
Luciano Coelho 已提交
224

I
Ido Yariv 已提交
225 226 227 228
		t[0].tx_buf = cmd;
		t[0].len = 4;
		t[0].cs_change = true;
		spi_message_add_tail(&t[0], &m);
L
Luciano Coelho 已提交
229

I
Ido Yariv 已提交
230 231 232 233 234
		/* Busy and non busy words read */
		t[1].rx_buf = busy_buf;
		t[1].len = WL1271_BUSY_WORD_LEN;
		t[1].cs_change = true;
		spi_message_add_tail(&t[1], &m);
L
Luciano Coelho 已提交
235

236
		spi_sync(to_spi_device(glue->dev), &m);
237

I
Ido Yariv 已提交
238
		if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
239
		    wl12xx_spi_read_busy(child)) {
I
Ido Yariv 已提交
240
			memset(buf, 0, chunk_len);
241
			return 0;
I
Ido Yariv 已提交
242
		}
243

I
Ido Yariv 已提交
244 245
		spi_message_init(&m);
		memset(t, 0, sizeof(t));
246

I
Ido Yariv 已提交
247 248 249 250 251
		t[0].rx_buf = buf;
		t[0].len = chunk_len;
		t[0].cs_change = true;
		spi_message_add_tail(&t[0], &m);

252
		spi_sync(to_spi_device(glue->dev), &m);
L
Luciano Coelho 已提交
253

I
Ido Yariv 已提交
254 255 256 257 258
		if (!fixed)
			addr += chunk_len;
		buf += chunk_len;
		len -= chunk_len;
	}
259 260

	return 0;
L
Luciano Coelho 已提交
261 262
}

263 264
static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
					     void *buf, size_t len, bool fixed)
L
Luciano Coelho 已提交
265
{
266
	struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
I
Ido Yariv 已提交
267
	struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
L
Luciano Coelho 已提交
268
	struct spi_message m;
I
Ido Yariv 已提交
269
	u32 commands[WSPI_MAX_NUM_OF_CHUNKS];
L
Luciano Coelho 已提交
270
	u32 *cmd;
I
Ido Yariv 已提交
271 272
	u32 chunk_len;
	int i;
L
Luciano Coelho 已提交
273

I
Ido Yariv 已提交
274
	WARN_ON(len > WL1271_AGGR_BUFFER_SIZE);
L
Luciano Coelho 已提交
275 276 277 278

	spi_message_init(&m);
	memset(t, 0, sizeof(t));

I
Ido Yariv 已提交
279 280 281 282
	cmd = &commands[0];
	i = 0;
	while (len > 0) {
		chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
L
Luciano Coelho 已提交
283

I
Ido Yariv 已提交
284 285 286 287 288
		*cmd = 0;
		*cmd |= WSPI_CMD_WRITE;
		*cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) &
			WSPI_CMD_BYTE_LENGTH;
		*cmd |= addr & WSPI_CMD_BYTE_ADDR;
L
Luciano Coelho 已提交
289

I
Ido Yariv 已提交
290 291 292 293 294 295 296 297 298 299
		if (fixed)
			*cmd |= WSPI_CMD_FIXED;

		t[i].tx_buf = cmd;
		t[i].len = sizeof(*cmd);
		spi_message_add_tail(&t[i++], &m);

		t[i].tx_buf = buf;
		t[i].len = chunk_len;
		spi_message_add_tail(&t[i++], &m);
L
Luciano Coelho 已提交
300

I
Ido Yariv 已提交
301 302 303 304 305 306 307
		if (!fixed)
			addr += chunk_len;
		buf += chunk_len;
		len -= chunk_len;
		cmd++;
	}

308
	spi_sync(to_spi_device(glue->dev), &m);
309 310

	return 0;
L
Luciano Coelho 已提交
311
}
312

313
static struct wl1271_if_operations spi_ops = {
314 315 316 317
	.read		= wl12xx_spi_raw_read,
	.write		= wl12xx_spi_raw_write,
	.reset		= wl12xx_spi_reset,
	.init		= wl12xx_spi_init,
318
	.set_block_size = NULL,
319 320
};

321 322
static int __devinit wl1271_probe(struct spi_device *spi)
{
323
	struct wl12xx_spi_glue *glue;
324
	struct wl12xx_platform_data *pdata;
325
	struct resource res[1];
326
	int ret = -ENOMEM;
327 328 329

	pdata = spi->dev.platform_data;
	if (!pdata) {
330
		dev_err(&spi->dev, "no platform data\n");
331 332 333
		return -ENODEV;
	}

334 335
	pdata->ops = &spi_ops;

336 337
	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
	if (!glue) {
338
		dev_err(&spi->dev, "can't allocate glue\n");
339 340 341 342 343 344
		goto out;
	}

	glue->dev = &spi->dev;

	spi_set_drvdata(spi, glue);
345 346 347 348 349 350 351

	/* This is the only SPI value that we need to set here, the rest
	 * comes from the board-peripherals file */
	spi->bits_per_word = 32;

	ret = spi_setup(spi);
	if (ret < 0) {
352
		dev_err(glue->dev, "spi_setup failed\n");
353
		goto out_free_glue;
354 355
	}

356
	glue->core = platform_device_alloc("wl12xx", -1);
357
	if (!glue->core) {
358
		dev_err(glue->dev, "can't allocate platform_device\n");
359
		ret = -ENOMEM;
360
		goto out_free_glue;
361 362 363 364 365 366 367 368 369 370 371 372
	}

	glue->core->dev.parent = &spi->dev;

	memset(res, 0x00, sizeof(res));

	res[0].start = spi->irq;
	res[0].flags = IORESOURCE_IRQ;
	res[0].name = "irq";

	ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res));
	if (ret) {
373
		dev_err(glue->dev, "can't add resources\n");
374 375 376 377 378
		goto out_dev_put;
	}

	ret = platform_device_add_data(glue->core, pdata, sizeof(*pdata));
	if (ret) {
379
		dev_err(glue->dev, "can't add platform data\n");
380 381 382 383 384
		goto out_dev_put;
	}

	ret = platform_device_add(glue->core);
	if (ret) {
385
		dev_err(glue->dev, "can't register platform device\n");
386 387 388
		goto out_dev_put;
	}

389 390
	return 0;

391 392 393
out_dev_put:
	platform_device_put(glue->core);

394 395 396
out_free_glue:
	kfree(glue);
out:
397 398 399 400 401
	return ret;
}

static int __devexit wl1271_remove(struct spi_device *spi)
{
402
	struct wl12xx_spi_glue *glue = spi_get_drvdata(spi);
403

404 405
	platform_device_del(glue->core);
	platform_device_put(glue->core);
406
	kfree(glue);
407 408 409 410 411 412 413

	return 0;
}


static struct spi_driver wl1271_spi_driver = {
	.driver = {
414
		.name		= "wl1271_spi",
415 416 417 418 419 420 421 422 423
		.owner		= THIS_MODULE,
	},

	.probe		= wl1271_probe,
	.remove		= __devexit_p(wl1271_remove),
};

static int __init wl1271_init(void)
{
424
	return spi_register_driver(&wl1271_spi_driver);
425 426 427 428 429 430 431 432 433 434 435
}

static void __exit wl1271_exit(void)
{
	spi_unregister_driver(&wl1271_spi_driver);
}

module_init(wl1271_init);
module_exit(wl1271_exit);

MODULE_LICENSE("GPL");
436
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
437
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
438 439
MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
440
MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
441 442
MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
443
MODULE_FIRMWARE(WL128X_PLT_FW_NAME);
444
MODULE_ALIAS("spi:wl1271");