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

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

S
Shahar Levi 已提交
37
#include "reg.h"
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 66 67

#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 已提交
68 69 70 71 72
/* 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)

73 74
struct wl12xx_spi_glue {
	struct device *dev;
75
	struct platform_device *core;
76 77
};

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

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

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

103
	kfree(cmd);
L
Luciano Coelho 已提交
104 105
}

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

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

161 162
#define WL1271_BUSY_WORD_TIMEOUT 1000

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

189 190
		if (*busy_buf & 0x1)
			return 0;
191 192 193
	}

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

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

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

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

I
Ido Yariv 已提交
215 216 217 218 219
		*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 已提交
220

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

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

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

I
Ido Yariv 已提交
232 233 234 235 236
		/* 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 已提交
237

238
		spi_sync(to_spi_device(glue->dev), &m);
239

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

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

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

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

I
Ido Yariv 已提交
256 257 258 259 260
		if (!fixed)
			addr += chunk_len;
		buf += chunk_len;
		len -= chunk_len;
	}
L
Luciano Coelho 已提交
261 262
}

263 264
static void 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);
L
Luciano Coelho 已提交
309
}
310

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

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

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

332 333
	pdata->ops = &spi_ops;

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

	glue->dev = &spi->dev;

	spi_set_drvdata(spi, glue);
343 344 345 346 347 348 349

	/* 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) {
350
		dev_err(glue->dev, "spi_setup failed\n");
351
		goto out_free_glue;
352 353
	}

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

	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) {
371
		dev_err(glue->dev, "can't add resources\n");
372 373 374 375 376
		goto out_dev_put;
	}

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

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

387 388
	return 0;

389 390 391
out_dev_put:
	platform_device_put(glue->core);

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

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

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

	return 0;
}


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

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

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

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

module_init(wl1271_init);
module_exit(wl1271_exit);

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