Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.11 591 lines 15 kB view raw
1/* 2 * This file is part of wl1271 3 * 4 * Copyright (C) 2008-2009 Nokia Corporation 5 * 6 * Contact: Luciano Coelho <luciano.coelho@nokia.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA 21 * 22 */ 23 24#include <linux/interrupt.h> 25#include <linux/irq.h> 26#include <linux/module.h> 27#include <linux/slab.h> 28#include <linux/swab.h> 29#include <linux/crc7.h> 30#include <linux/spi/spi.h> 31#include <linux/wl12xx.h> 32#include <linux/platform_device.h> 33#include <linux/of_irq.h> 34#include <linux/regulator/consumer.h> 35 36#include "wlcore.h" 37#include "wl12xx_80211.h" 38#include "io.h" 39 40#define WSPI_CMD_READ 0x40000000 41#define WSPI_CMD_WRITE 0x00000000 42#define WSPI_CMD_FIXED 0x20000000 43#define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 44#define WSPI_CMD_BYTE_LENGTH_OFFSET 17 45#define WSPI_CMD_BYTE_ADDR 0x0001FFFF 46 47#define WSPI_INIT_CMD_CRC_LEN 5 48 49#define WSPI_INIT_CMD_START 0x00 50#define WSPI_INIT_CMD_TX 0x40 51/* the extra bypass bit is sampled by the TNET as '1' */ 52#define WSPI_INIT_CMD_BYPASS_BIT 0x80 53#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 54#define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 55#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 56#define WSPI_INIT_CMD_IOD 0x40 57#define WSPI_INIT_CMD_IP 0x20 58#define WSPI_INIT_CMD_CS 0x10 59#define WSPI_INIT_CMD_WS 0x08 60#define WSPI_INIT_CMD_WSPI 0x01 61#define WSPI_INIT_CMD_END 0x01 62 63#define WSPI_INIT_CMD_LEN 8 64 65#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ 66 ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) 67#define HW_ACCESS_WSPI_INIT_CMD_MASK 0 68 69/* HW limitation: maximum possible chunk size is 4095 bytes */ 70#define WSPI_MAX_CHUNK_SIZE 4092 71 72/* 73 * wl18xx driver aggregation buffer size is (13 * PAGE_SIZE) compared to 74 * (4 * PAGE_SIZE) for wl12xx, so use the larger buffer needed for wl18xx 75 */ 76#define SPI_AGGR_BUFFER_SIZE (13 * PAGE_SIZE) 77 78/* Maximum number of SPI write chunks */ 79#define WSPI_MAX_NUM_OF_CHUNKS \ 80 ((SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) + 1) 81 82static const struct wilink_family_data wl127x_data = { 83 .name = "wl127x", 84 .nvs_name = "ti-connectivity/wl127x-nvs.bin", 85}; 86 87static const struct wilink_family_data wl128x_data = { 88 .name = "wl128x", 89 .nvs_name = "ti-connectivity/wl128x-nvs.bin", 90}; 91 92static const struct wilink_family_data wl18xx_data = { 93 .name = "wl18xx", 94 .cfg_name = "ti-connectivity/wl18xx-conf.bin", 95}; 96 97struct wl12xx_spi_glue { 98 struct device *dev; 99 struct platform_device *core; 100 struct regulator *reg; /* Power regulator */ 101}; 102 103static void wl12xx_spi_reset(struct device *child) 104{ 105 struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); 106 u8 *cmd; 107 struct spi_transfer t; 108 struct spi_message m; 109 110 cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); 111 if (!cmd) { 112 dev_err(child->parent, 113 "could not allocate cmd for spi reset\n"); 114 return; 115 } 116 117 memset(&t, 0, sizeof(t)); 118 spi_message_init(&m); 119 120 memset(cmd, 0xff, WSPI_INIT_CMD_LEN); 121 122 t.tx_buf = cmd; 123 t.len = WSPI_INIT_CMD_LEN; 124 spi_message_add_tail(&t, &m); 125 126 spi_sync(to_spi_device(glue->dev), &m); 127 128 kfree(cmd); 129} 130 131static void wl12xx_spi_init(struct device *child) 132{ 133 struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); 134 struct spi_transfer t; 135 struct spi_message m; 136 struct spi_device *spi = to_spi_device(glue->dev); 137 u8 *cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); 138 139 if (!cmd) { 140 dev_err(child->parent, 141 "could not allocate cmd for spi init\n"); 142 return; 143 } 144 145 memset(&t, 0, sizeof(t)); 146 spi_message_init(&m); 147 148 /* 149 * Set WSPI_INIT_COMMAND 150 * the data is being send from the MSB to LSB 151 */ 152 cmd[0] = 0xff; 153 cmd[1] = 0xff; 154 cmd[2] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; 155 cmd[3] = 0; 156 cmd[4] = 0; 157 cmd[5] = HW_ACCESS_WSPI_INIT_CMD_MASK << 3; 158 cmd[5] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; 159 160 cmd[6] = WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS 161 | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; 162 163 if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) 164 cmd[6] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; 165 else 166 cmd[6] |= WSPI_INIT_CMD_EN_FIXEDBUSY; 167 168 cmd[7] = crc7_be(0, cmd+2, WSPI_INIT_CMD_CRC_LEN) | WSPI_INIT_CMD_END; 169 170 /* 171 * The above is the logical order; it must actually be stored 172 * in the buffer byte-swapped. 173 */ 174 __swab32s((u32 *)cmd); 175 __swab32s((u32 *)cmd+1); 176 177 t.tx_buf = cmd; 178 t.len = WSPI_INIT_CMD_LEN; 179 spi_message_add_tail(&t, &m); 180 181 spi_sync(to_spi_device(glue->dev), &m); 182 183 /* Send extra clocks with inverted CS (high). this is required 184 * by the wilink family in order to successfully enter WSPI mode. 185 */ 186 spi->mode ^= SPI_CS_HIGH; 187 memset(&m, 0, sizeof(m)); 188 spi_message_init(&m); 189 190 cmd[0] = 0xff; 191 cmd[1] = 0xff; 192 cmd[2] = 0xff; 193 cmd[3] = 0xff; 194 __swab32s((u32 *)cmd); 195 196 t.tx_buf = cmd; 197 t.len = 4; 198 spi_message_add_tail(&t, &m); 199 200 spi_sync(to_spi_device(glue->dev), &m); 201 202 /* Restore chip select configration to normal */ 203 spi->mode ^= SPI_CS_HIGH; 204 kfree(cmd); 205} 206 207#define WL1271_BUSY_WORD_TIMEOUT 1000 208 209static int wl12xx_spi_read_busy(struct device *child) 210{ 211 struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); 212 struct wl1271 *wl = dev_get_drvdata(child); 213 struct spi_transfer t[1]; 214 struct spi_message m; 215 u32 *busy_buf; 216 int num_busy_bytes = 0; 217 218 /* 219 * Read further busy words from SPI until a non-busy word is 220 * encountered, then read the data itself into the buffer. 221 */ 222 223 num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; 224 busy_buf = wl->buffer_busyword; 225 while (num_busy_bytes) { 226 num_busy_bytes--; 227 spi_message_init(&m); 228 memset(t, 0, sizeof(t)); 229 t[0].rx_buf = busy_buf; 230 t[0].len = sizeof(u32); 231 t[0].cs_change = true; 232 spi_message_add_tail(&t[0], &m); 233 spi_sync(to_spi_device(glue->dev), &m); 234 235 if (*busy_buf & 0x1) 236 return 0; 237 } 238 239 /* The SPI bus is unresponsive, the read failed. */ 240 dev_err(child->parent, "SPI read busy-word timeout!\n"); 241 return -ETIMEDOUT; 242} 243 244static int __must_check wl12xx_spi_raw_read(struct device *child, int addr, 245 void *buf, size_t len, bool fixed) 246{ 247 struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); 248 struct wl1271 *wl = dev_get_drvdata(child); 249 struct spi_transfer t[2]; 250 struct spi_message m; 251 u32 *busy_buf; 252 u32 *cmd; 253 u32 chunk_len; 254 255 while (len > 0) { 256 chunk_len = min_t(size_t, WSPI_MAX_CHUNK_SIZE, len); 257 258 cmd = &wl->buffer_cmd; 259 busy_buf = wl->buffer_busyword; 260 261 *cmd = 0; 262 *cmd |= WSPI_CMD_READ; 263 *cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) & 264 WSPI_CMD_BYTE_LENGTH; 265 *cmd |= addr & WSPI_CMD_BYTE_ADDR; 266 267 if (fixed) 268 *cmd |= WSPI_CMD_FIXED; 269 270 spi_message_init(&m); 271 memset(t, 0, sizeof(t)); 272 273 t[0].tx_buf = cmd; 274 t[0].len = 4; 275 t[0].cs_change = true; 276 spi_message_add_tail(&t[0], &m); 277 278 /* Busy and non busy words read */ 279 t[1].rx_buf = busy_buf; 280 t[1].len = WL1271_BUSY_WORD_LEN; 281 t[1].cs_change = true; 282 spi_message_add_tail(&t[1], &m); 283 284 spi_sync(to_spi_device(glue->dev), &m); 285 286 if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && 287 wl12xx_spi_read_busy(child)) { 288 memset(buf, 0, chunk_len); 289 return 0; 290 } 291 292 spi_message_init(&m); 293 memset(t, 0, sizeof(t)); 294 295 t[0].rx_buf = buf; 296 t[0].len = chunk_len; 297 t[0].cs_change = true; 298 spi_message_add_tail(&t[0], &m); 299 300 spi_sync(to_spi_device(glue->dev), &m); 301 302 if (!fixed) 303 addr += chunk_len; 304 buf += chunk_len; 305 len -= chunk_len; 306 } 307 308 return 0; 309} 310 311static int __wl12xx_spi_raw_write(struct device *child, int addr, 312 void *buf, size_t len, bool fixed) 313{ 314 struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); 315 struct spi_transfer *t; 316 struct spi_message m; 317 u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; /* 1 command per chunk */ 318 u32 *cmd; 319 u32 chunk_len; 320 int i; 321 322 /* SPI write buffers - 2 for each chunk */ 323 t = kzalloc(sizeof(*t) * 2 * WSPI_MAX_NUM_OF_CHUNKS, GFP_KERNEL); 324 if (!t) 325 return -ENOMEM; 326 327 WARN_ON(len > SPI_AGGR_BUFFER_SIZE); 328 329 spi_message_init(&m); 330 331 cmd = &commands[0]; 332 i = 0; 333 while (len > 0) { 334 chunk_len = min_t(size_t, WSPI_MAX_CHUNK_SIZE, len); 335 336 *cmd = 0; 337 *cmd |= WSPI_CMD_WRITE; 338 *cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) & 339 WSPI_CMD_BYTE_LENGTH; 340 *cmd |= addr & WSPI_CMD_BYTE_ADDR; 341 342 if (fixed) 343 *cmd |= WSPI_CMD_FIXED; 344 345 t[i].tx_buf = cmd; 346 t[i].len = sizeof(*cmd); 347 spi_message_add_tail(&t[i++], &m); 348 349 t[i].tx_buf = buf; 350 t[i].len = chunk_len; 351 spi_message_add_tail(&t[i++], &m); 352 353 if (!fixed) 354 addr += chunk_len; 355 buf += chunk_len; 356 len -= chunk_len; 357 cmd++; 358 } 359 360 spi_sync(to_spi_device(glue->dev), &m); 361 362 kfree(t); 363 return 0; 364} 365 366static int __must_check wl12xx_spi_raw_write(struct device *child, int addr, 367 void *buf, size_t len, bool fixed) 368{ 369 int ret; 370 371 /* The ELP wakeup write may fail the first time due to internal 372 * hardware latency. It is safer to send the wakeup command twice to 373 * avoid unexpected failures. 374 */ 375 if (addr == HW_ACCESS_ELP_CTRL_REG) 376 ret = __wl12xx_spi_raw_write(child, addr, buf, len, fixed); 377 ret = __wl12xx_spi_raw_write(child, addr, buf, len, fixed); 378 379 return ret; 380} 381 382/** 383 * wl12xx_spi_set_power - power on/off the wl12xx unit 384 * @child: wl12xx device handle. 385 * @enable: true/false to power on/off the unit. 386 * 387 * use the WiFi enable regulator to enable/disable the WiFi unit. 388 */ 389static int wl12xx_spi_set_power(struct device *child, bool enable) 390{ 391 int ret = 0; 392 struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); 393 394 WARN_ON(!glue->reg); 395 396 /* Update regulator state */ 397 if (enable) { 398 ret = regulator_enable(glue->reg); 399 if (ret) 400 dev_err(child, "Power enable failure\n"); 401 } else { 402 ret = regulator_disable(glue->reg); 403 if (ret) 404 dev_err(child, "Power disable failure\n"); 405 } 406 407 return ret; 408} 409 410/** 411 * wl12xx_spi_set_block_size 412 * 413 * This function is not needed for spi mode, but need to be present. 414 * Without it defined the wlcore fallback to use the wrong packet 415 * allignment on tx. 416 */ 417static void wl12xx_spi_set_block_size(struct device *child, 418 unsigned int blksz) 419{ 420} 421 422static struct wl1271_if_operations spi_ops = { 423 .read = wl12xx_spi_raw_read, 424 .write = wl12xx_spi_raw_write, 425 .reset = wl12xx_spi_reset, 426 .init = wl12xx_spi_init, 427 .power = wl12xx_spi_set_power, 428 .set_block_size = wl12xx_spi_set_block_size, 429}; 430 431static const struct of_device_id wlcore_spi_of_match_table[] = { 432 { .compatible = "ti,wl1271", .data = &wl127x_data}, 433 { .compatible = "ti,wl1273", .data = &wl127x_data}, 434 { .compatible = "ti,wl1281", .data = &wl128x_data}, 435 { .compatible = "ti,wl1283", .data = &wl128x_data}, 436 { .compatible = "ti,wl1801", .data = &wl18xx_data}, 437 { .compatible = "ti,wl1805", .data = &wl18xx_data}, 438 { .compatible = "ti,wl1807", .data = &wl18xx_data}, 439 { .compatible = "ti,wl1831", .data = &wl18xx_data}, 440 { .compatible = "ti,wl1835", .data = &wl18xx_data}, 441 { .compatible = "ti,wl1837", .data = &wl18xx_data}, 442 { } 443}; 444MODULE_DEVICE_TABLE(of, wlcore_spi_of_match_table); 445 446/** 447 * wlcore_probe_of - DT node parsing. 448 * @spi: SPI slave device parameters. 449 * @res: resource parameters. 450 * @glue: wl12xx SPI bus to slave device glue parameters. 451 * @pdev_data: wlcore device parameters 452 */ 453static int wlcore_probe_of(struct spi_device *spi, struct wl12xx_spi_glue *glue, 454 struct wlcore_platdev_data *pdev_data) 455{ 456 struct device_node *dt_node = spi->dev.of_node; 457 const struct of_device_id *of_id; 458 459 of_id = of_match_node(wlcore_spi_of_match_table, dt_node); 460 if (!of_id) 461 return -ENODEV; 462 463 pdev_data->family = of_id->data; 464 dev_info(&spi->dev, "selected chip family is %s\n", 465 pdev_data->family->name); 466 467 if (of_find_property(dt_node, "clock-xtal", NULL)) 468 pdev_data->ref_clock_xtal = true; 469 470 /* optional clock frequency params */ 471 of_property_read_u32(dt_node, "ref-clock-frequency", 472 &pdev_data->ref_clock_freq); 473 of_property_read_u32(dt_node, "tcxo-clock-frequency", 474 &pdev_data->tcxo_clock_freq); 475 476 return 0; 477} 478 479static int wl1271_probe(struct spi_device *spi) 480{ 481 struct wl12xx_spi_glue *glue; 482 struct wlcore_platdev_data *pdev_data; 483 struct resource res[1]; 484 int ret; 485 486 pdev_data = devm_kzalloc(&spi->dev, sizeof(*pdev_data), GFP_KERNEL); 487 if (!pdev_data) 488 return -ENOMEM; 489 490 pdev_data->if_ops = &spi_ops; 491 492 glue = devm_kzalloc(&spi->dev, sizeof(*glue), GFP_KERNEL); 493 if (!glue) { 494 dev_err(&spi->dev, "can't allocate glue\n"); 495 return -ENOMEM; 496 } 497 498 glue->dev = &spi->dev; 499 500 spi_set_drvdata(spi, glue); 501 502 /* This is the only SPI value that we need to set here, the rest 503 * comes from the board-peripherals file */ 504 spi->bits_per_word = 32; 505 506 glue->reg = devm_regulator_get(&spi->dev, "vwlan"); 507 if (PTR_ERR(glue->reg) == -EPROBE_DEFER) 508 return -EPROBE_DEFER; 509 if (IS_ERR(glue->reg)) { 510 dev_err(glue->dev, "can't get regulator\n"); 511 return PTR_ERR(glue->reg); 512 } 513 514 ret = wlcore_probe_of(spi, glue, pdev_data); 515 if (ret) { 516 dev_err(glue->dev, 517 "can't get device tree parameters (%d)\n", ret); 518 return ret; 519 } 520 521 ret = spi_setup(spi); 522 if (ret < 0) { 523 dev_err(glue->dev, "spi_setup failed\n"); 524 return ret; 525 } 526 527 glue->core = platform_device_alloc(pdev_data->family->name, 528 PLATFORM_DEVID_AUTO); 529 if (!glue->core) { 530 dev_err(glue->dev, "can't allocate platform_device\n"); 531 return -ENOMEM; 532 } 533 534 glue->core->dev.parent = &spi->dev; 535 536 memset(res, 0x00, sizeof(res)); 537 538 res[0].start = spi->irq; 539 res[0].flags = IORESOURCE_IRQ | irq_get_trigger_type(spi->irq); 540 res[0].name = "irq"; 541 542 ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); 543 if (ret) { 544 dev_err(glue->dev, "can't add resources\n"); 545 goto out_dev_put; 546 } 547 548 ret = platform_device_add_data(glue->core, pdev_data, 549 sizeof(*pdev_data)); 550 if (ret) { 551 dev_err(glue->dev, "can't add platform data\n"); 552 goto out_dev_put; 553 } 554 555 ret = platform_device_add(glue->core); 556 if (ret) { 557 dev_err(glue->dev, "can't register platform device\n"); 558 goto out_dev_put; 559 } 560 561 return 0; 562 563out_dev_put: 564 platform_device_put(glue->core); 565 return ret; 566} 567 568static int wl1271_remove(struct spi_device *spi) 569{ 570 struct wl12xx_spi_glue *glue = spi_get_drvdata(spi); 571 572 platform_device_unregister(glue->core); 573 574 return 0; 575} 576 577static struct spi_driver wl1271_spi_driver = { 578 .driver = { 579 .name = "wl1271_spi", 580 .of_match_table = of_match_ptr(wlcore_spi_of_match_table), 581 }, 582 583 .probe = wl1271_probe, 584 .remove = wl1271_remove, 585}; 586 587module_spi_driver(wl1271_spi_driver); 588MODULE_LICENSE("GPL"); 589MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); 590MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); 591MODULE_ALIAS("spi:wl1271");