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
	while (len > 0) {
S
Silvan Jegen 已提交
214
		chunk_len = min_t(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);
273
	struct spi_transfer t[2 * (WSPI_MAX_NUM_OF_CHUNKS + 1)];
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
	cmd = &commands[0];
	i = 0;
	while (len > 0) {
S
Silvan Jegen 已提交
288
		chunk_len = min_t(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
static int wl1271_probe(struct spi_device *spi)
328
{
329
	struct wl12xx_spi_glue *glue;
330
	struct wlcore_platdev_data *pdev_data;
331
	struct resource res[1];
332
	int ret = -ENOMEM;
333

334
	pdev_data = kzalloc(sizeof(*pdev_data), GFP_KERNEL);
335
	if (!pdev_data)
336 337
		goto out;

338
	pdev_data->pdata = dev_get_platdata(&spi->dev);
339 340 341 342 343 344
	if (!pdev_data->pdata) {
		dev_err(&spi->dev, "no platform data\n");
		ret = -ENODEV;
		goto out_free_pdev_data;
	}

345
	pdev_data->if_ops = &spi_ops;
346

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

	glue->dev = &spi->dev;

	spi_set_drvdata(spi, glue);
356 357 358 359 360 361 362

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

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

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

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

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

401 402
	return 0;

403 404 405
out_dev_put:
	platform_device_put(glue->core);

406 407
out_free_glue:
	kfree(glue);
408 409 410 411

out_free_pdev_data:
	kfree(pdev_data);

412
out:
413 414 415
	return ret;
}

416
static int wl1271_remove(struct spi_device *spi)
417
{
418
	struct wl12xx_spi_glue *glue = spi_get_drvdata(spi);
419

420
	platform_device_unregister(glue->core);
421
	kfree(glue);
422 423 424 425 426 427 428

	return 0;
}


static struct spi_driver wl1271_spi_driver = {
	.driver = {
429
		.name		= "wl1271_spi",
430 431 432 433
		.owner		= THIS_MODULE,
	},

	.probe		= wl1271_probe,
434
	.remove		= wl1271_remove,
435 436
};

437
module_spi_driver(wl1271_spi_driver);
438
MODULE_LICENSE("GPL");
439
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
440
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
441
MODULE_ALIAS("spi:wl1271");