spi.c 10.1 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
/* HW limitation: maximum possible chunk size is 4095 bytes */
#define WSPI_MAX_CHUNK_SIZE    4092

69 70 71 72 73 74 75
/*
 * only support SPI for 12xx - this code should be reworked when 18xx
 * support is introduced
 */
#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)

#define WSPI_MAX_NUM_OF_CHUNKS (SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
I
Ido Yariv 已提交
76

77 78
struct wl12xx_spi_glue {
	struct device *dev;
79
	struct platform_device *core;
80 81
};

82
static void wl12xx_spi_reset(struct device *child)
83
{
84
	struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
L
Luciano Coelho 已提交
85 86 87 88 89 90
	u8 *cmd;
	struct spi_transfer t;
	struct spi_message m;

	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
	if (!cmd) {
91 92
		dev_err(child->parent,
			"could not allocate cmd for spi reset\n");
L
Luciano Coelho 已提交
93 94 95 96 97 98 99 100 101 102 103 104
		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);

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

107
	kfree(cmd);
L
Luciano Coelho 已提交
108 109
}

110
static void wl12xx_spi_init(struct device *child)
L
Luciano Coelho 已提交
111
{
112
	struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
L
Luciano Coelho 已提交
113 114 115 116 117 118
	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) {
119 120
		dev_err(child->parent,
			"could not allocate cmd for spi init\n");
L
Luciano Coelho 已提交
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 155 156 157 158 159 160
		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);

161
	spi_sync(to_spi_device(glue->dev), &m);
162
	kfree(cmd);
L
Luciano Coelho 已提交
163 164
}

165 166
#define WL1271_BUSY_WORD_TIMEOUT 1000

167
static int wl12xx_spi_read_busy(struct device *child)
168
{
169 170
	struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
	struct wl1271 *wl = dev_get_drvdata(child);
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
	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);
189
		t[0].cs_change = true;
190
		spi_message_add_tail(&t[0], &m);
191
		spi_sync(to_spi_device(glue->dev), &m);
192

193 194
		if (*busy_buf & 0x1)
			return 0;
195 196 197
	}

	/* The SPI bus is unresponsive, the read failed. */
198
	dev_err(child->parent, "SPI read busy-word timeout!\n");
199
	return -ETIMEDOUT;
200 201
}

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

I
Ido Yariv 已提交
213 214
	while (len > 0) {
		chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
L
Luciano Coelho 已提交
215

I
Ido Yariv 已提交
216 217
		cmd = &wl->buffer_cmd;
		busy_buf = wl->buffer_busyword;
L
Luciano Coelho 已提交
218

I
Ido Yariv 已提交
219 220 221 222 223
		*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 已提交
224

I
Ido Yariv 已提交
225 226
		if (fixed)
			*cmd |= WSPI_CMD_FIXED;
L
Luciano Coelho 已提交
227

I
Ido Yariv 已提交
228 229
		spi_message_init(&m);
		memset(t, 0, sizeof(t));
L
Luciano Coelho 已提交
230

I
Ido Yariv 已提交
231 232 233 234
		t[0].tx_buf = cmd;
		t[0].len = 4;
		t[0].cs_change = true;
		spi_message_add_tail(&t[0], &m);
L
Luciano Coelho 已提交
235

I
Ido Yariv 已提交
236 237 238 239 240
		/* 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 已提交
241

242
		spi_sync(to_spi_device(glue->dev), &m);
243

I
Ido Yariv 已提交
244
		if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
245
		    wl12xx_spi_read_busy(child)) {
I
Ido Yariv 已提交
246
			memset(buf, 0, chunk_len);
247
			return 0;
I
Ido Yariv 已提交
248
		}
249

I
Ido Yariv 已提交
250 251
		spi_message_init(&m);
		memset(t, 0, sizeof(t));
252

I
Ido Yariv 已提交
253 254 255 256 257
		t[0].rx_buf = buf;
		t[0].len = chunk_len;
		t[0].cs_change = true;
		spi_message_add_tail(&t[0], &m);

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

I
Ido Yariv 已提交
260 261 262 263 264
		if (!fixed)
			addr += chunk_len;
		buf += chunk_len;
		len -= chunk_len;
	}
265 266

	return 0;
L
Luciano Coelho 已提交
267 268
}

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

280
	WARN_ON(len > SPI_AGGR_BUFFER_SIZE);
L
Luciano Coelho 已提交
281 282 283 284

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

I
Ido Yariv 已提交
285 286 287 288
	cmd = &commands[0];
	i = 0;
	while (len > 0) {
		chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
L
Luciano Coelho 已提交
289

I
Ido Yariv 已提交
290 291 292 293 294
		*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 已提交
295

I
Ido Yariv 已提交
296 297 298 299 300 301 302 303 304 305
		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 已提交
306

I
Ido Yariv 已提交
307 308 309 310 311 312 313
		if (!fixed)
			addr += chunk_len;
		buf += chunk_len;
		len -= chunk_len;
		cmd++;
	}

314
	spi_sync(to_spi_device(glue->dev), &m);
315 316

	return 0;
L
Luciano Coelho 已提交
317
}
318

319
static struct wl1271_if_operations spi_ops = {
320 321 322 323
	.read		= wl12xx_spi_raw_read,
	.write		= wl12xx_spi_raw_write,
	.reset		= wl12xx_spi_reset,
	.init		= wl12xx_spi_init,
324
	.set_block_size = NULL,
325 326
};

327 328
static int __devinit wl1271_probe(struct spi_device *spi)
{
329
	struct wl12xx_spi_glue *glue;
330
	struct wl12xx_platform_data *pdata;
331
	struct resource res[1];
332
	int ret = -ENOMEM;
333 334 335

	pdata = spi->dev.platform_data;
	if (!pdata) {
336
		dev_err(&spi->dev, "no platform data\n");
337 338 339
		return -ENODEV;
	}

340 341
	pdata->ops = &spi_ops;

342 343
	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
	if (!glue) {
344
		dev_err(&spi->dev, "can't allocate glue\n");
345 346 347 348 349 350
		goto out;
	}

	glue->dev = &spi->dev;

	spi_set_drvdata(spi, glue);
351 352 353 354 355 356 357

	/* 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) {
358
		dev_err(glue->dev, "spi_setup failed\n");
359
		goto out_free_glue;
360 361
	}

362
	glue->core = platform_device_alloc("wl12xx", -1);
363
	if (!glue->core) {
364
		dev_err(glue->dev, "can't allocate platform_device\n");
365
		ret = -ENOMEM;
366
		goto out_free_glue;
367 368 369 370 371 372 373 374 375 376 377 378
	}

	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) {
379
		dev_err(glue->dev, "can't add resources\n");
380 381 382 383 384
		goto out_dev_put;
	}

	ret = platform_device_add_data(glue->core, pdata, sizeof(*pdata));
	if (ret) {
385
		dev_err(glue->dev, "can't add platform data\n");
386 387 388 389 390
		goto out_dev_put;
	}

	ret = platform_device_add(glue->core);
	if (ret) {
391
		dev_err(glue->dev, "can't register platform device\n");
392 393 394
		goto out_dev_put;
	}

395 396
	return 0;

397 398 399
out_dev_put:
	platform_device_put(glue->core);

400 401 402
out_free_glue:
	kfree(glue);
out:
403 404 405 406 407
	return ret;
}

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

410 411
	platform_device_del(glue->core);
	platform_device_put(glue->core);
412
	kfree(glue);
413 414 415 416 417 418 419

	return 0;
}


static struct spi_driver wl1271_spi_driver = {
	.driver = {
420
		.name		= "wl1271_spi",
421 422 423 424 425 426 427 428 429
		.owner		= THIS_MODULE,
	},

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

static int __init wl1271_init(void)
{
430
	return spi_register_driver(&wl1271_spi_driver);
431 432 433 434 435 436 437 438 439 440 441
}

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

module_init(wl1271_init);
module_exit(wl1271_exit);

MODULE_LICENSE("GPL");
442
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
443
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
444
MODULE_ALIAS("spi:wl1271");