spi.c 10.0 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
		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];

154
	cmd[4] = crc7_be(0, crc, WSPI_INIT_CMD_CRC_LEN) | WSPI_INIT_CMD_END;
L
Luciano Coelho 已提交
155 156 157 158 159

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

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

164 165
#define WL1271_BUSY_WORD_TIMEOUT 1000

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

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

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

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

I
Ido Yariv 已提交
212
	while (len > 0) {
S
Silvan Jegen 已提交
213
		chunk_len = min_t(size_t, WSPI_MAX_CHUNK_SIZE, len);
L
Luciano Coelho 已提交
214

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

326
static int wl1271_probe(struct spi_device *spi)
327
{
328
	struct wl12xx_spi_glue *glue;
329
	struct wlcore_platdev_data pdev_data;
330
	struct resource res[1];
331
	int ret = -ENOMEM;
332

333
	memset(&pdev_data, 0x00, sizeof(pdev_data));
334

335 336
	pdev_data.pdata = dev_get_platdata(&spi->dev);
	if (!pdev_data.pdata) {
337 338
		dev_err(&spi->dev, "no platform data\n");
		ret = -ENODEV;
339
		goto out;
340 341
	}

342
	pdev_data.if_ops = &spi_ops;
343

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

	glue->dev = &spi->dev;

	spi_set_drvdata(spi, glue);
353 354 355 356 357 358 359

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

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

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

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

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

398 399
	return 0;

400 401 402
out_dev_put:
	platform_device_put(glue->core);

403 404
out_free_glue:
	kfree(glue);
405

406
out:
407 408 409
	return ret;
}

410
static int wl1271_remove(struct spi_device *spi)
411
{
412
	struct wl12xx_spi_glue *glue = spi_get_drvdata(spi);
413

414
	platform_device_unregister(glue->core);
415
	kfree(glue);
416 417 418 419 420 421 422

	return 0;
}


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

	.probe		= wl1271_probe,
428
	.remove		= wl1271_remove,
429 430
};

431
module_spi_driver(wl1271_spi_driver);
432
MODULE_LICENSE("GPL");
433
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
434
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
435
MODULE_ALIAS("spi:wl1271");