linux/drivers/net/wireless/ti/wlcore/spi.c
<<
>>
Prefs
   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/crc7.h>
  28#include <linux/spi/spi.h>
  29#include <linux/wl12xx.h>
  30#include <linux/platform_device.h>
  31#include <linux/slab.h>
  32
  33#include "wlcore.h"
  34#include "wl12xx_80211.h"
  35#include "io.h"
  36
  37#define WSPI_CMD_READ                 0x40000000
  38#define WSPI_CMD_WRITE                0x00000000
  39#define WSPI_CMD_FIXED                0x20000000
  40#define WSPI_CMD_BYTE_LENGTH          0x1FFE0000
  41#define WSPI_CMD_BYTE_LENGTH_OFFSET   17
  42#define WSPI_CMD_BYTE_ADDR            0x0001FFFF
  43
  44#define WSPI_INIT_CMD_CRC_LEN       5
  45
  46#define WSPI_INIT_CMD_START         0x00
  47#define WSPI_INIT_CMD_TX            0x40
  48/* the extra bypass bit is sampled by the TNET as '1' */
  49#define WSPI_INIT_CMD_BYPASS_BIT    0x80
  50#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07
  51#define WSPI_INIT_CMD_EN_FIXEDBUSY  0x80
  52#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00
  53#define WSPI_INIT_CMD_IOD           0x40
  54#define WSPI_INIT_CMD_IP            0x20
  55#define WSPI_INIT_CMD_CS            0x10
  56#define WSPI_INIT_CMD_WS            0x08
  57#define WSPI_INIT_CMD_WSPI          0x01
  58#define WSPI_INIT_CMD_END           0x01
  59
  60#define WSPI_INIT_CMD_LEN           8
  61
  62#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \
  63                ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32))
  64#define HW_ACCESS_WSPI_INIT_CMD_MASK  0
  65
  66/* HW limitation: maximum possible chunk size is 4095 bytes */
  67#define WSPI_MAX_CHUNK_SIZE    4092
  68
  69#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
  70
  71struct wl12xx_spi_glue {
  72        struct device *dev;
  73        struct platform_device *core;
  74};
  75
  76static void wl12xx_spi_reset(struct device *child)
  77{
  78        struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
  79        u8 *cmd;
  80        struct spi_transfer t;
  81        struct spi_message m;
  82
  83        cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
  84        if (!cmd) {
  85                dev_err(child->parent,
  86                        "could not allocate cmd for spi reset\n");
  87                return;
  88        }
  89
  90        memset(&t, 0, sizeof(t));
  91        spi_message_init(&m);
  92
  93        memset(cmd, 0xff, WSPI_INIT_CMD_LEN);
  94
  95        t.tx_buf = cmd;
  96        t.len = WSPI_INIT_CMD_LEN;
  97        spi_message_add_tail(&t, &m);
  98
  99        spi_sync(to_spi_device(glue->dev), &m);
 100
 101        kfree(cmd);
 102}
 103
 104static void wl12xx_spi_init(struct device *child)
 105{
 106        struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
 107        u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
 108        struct spi_transfer t;
 109        struct spi_message m;
 110
 111        cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
 112        if (!cmd) {
 113                dev_err(child->parent,
 114                        "could not allocate cmd for spi init\n");
 115                return;
 116        }
 117
 118        memset(crc, 0, sizeof(crc));
 119        memset(&t, 0, sizeof(t));
 120        spi_message_init(&m);
 121
 122        /*
 123         * Set WSPI_INIT_COMMAND
 124         * the data is being send from the MSB to LSB
 125         */
 126        cmd[2] = 0xff;
 127        cmd[3] = 0xff;
 128        cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
 129        cmd[0] = 0;
 130        cmd[7] = 0;
 131        cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
 132        cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
 133
 134        if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
 135                cmd[5] |=  WSPI_INIT_CMD_DIS_FIXEDBUSY;
 136        else
 137                cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
 138
 139        cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
 140                | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
 141
 142        crc[0] = cmd[1];
 143        crc[1] = cmd[0];
 144        crc[2] = cmd[7];
 145        crc[3] = cmd[6];
 146        crc[4] = cmd[5];
 147
 148        cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
 149        cmd[4] |= WSPI_INIT_CMD_END;
 150
 151        t.tx_buf = cmd;
 152        t.len = WSPI_INIT_CMD_LEN;
 153        spi_message_add_tail(&t, &m);
 154
 155        spi_sync(to_spi_device(glue->dev), &m);
 156        kfree(cmd);
 157}
 158
 159#define WL1271_BUSY_WORD_TIMEOUT 1000
 160
 161static int wl12xx_spi_read_busy(struct device *child)
 162{
 163        struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
 164        struct wl1271 *wl = dev_get_drvdata(child);
 165        struct spi_transfer t[1];
 166        struct spi_message m;
 167        u32 *busy_buf;
 168        int num_busy_bytes = 0;
 169
 170        /*
 171         * Read further busy words from SPI until a non-busy word is
 172         * encountered, then read the data itself into the buffer.
 173         */
 174
 175        num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT;
 176        busy_buf = wl->buffer_busyword;
 177        while (num_busy_bytes) {
 178                num_busy_bytes--;
 179                spi_message_init(&m);
 180                memset(t, 0, sizeof(t));
 181                t[0].rx_buf = busy_buf;
 182                t[0].len = sizeof(u32);
 183                t[0].cs_change = true;
 184                spi_message_add_tail(&t[0], &m);
 185                spi_sync(to_spi_device(glue->dev), &m);
 186
 187                if (*busy_buf & 0x1)
 188                        return 0;
 189        }
 190
 191        /* The SPI bus is unresponsive, the read failed. */
 192        dev_err(child->parent, "SPI read busy-word timeout!\n");
 193        return -ETIMEDOUT;
 194}
 195
 196static int __must_check wl12xx_spi_raw_read(struct device *child, int addr,
 197                                            void *buf, size_t len, bool fixed)
 198{
 199        struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
 200        struct wl1271 *wl = dev_get_drvdata(child);
 201        struct spi_transfer t[2];
 202        struct spi_message m;
 203        u32 *busy_buf;
 204        u32 *cmd;
 205        u32 chunk_len;
 206
 207        while (len > 0) {
 208                chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
 209
 210                cmd = &wl->buffer_cmd;
 211                busy_buf = wl->buffer_busyword;
 212
 213                *cmd = 0;
 214                *cmd |= WSPI_CMD_READ;
 215                *cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) &
 216                        WSPI_CMD_BYTE_LENGTH;
 217                *cmd |= addr & WSPI_CMD_BYTE_ADDR;
 218
 219                if (fixed)
 220                        *cmd |= WSPI_CMD_FIXED;
 221
 222                spi_message_init(&m);
 223                memset(t, 0, sizeof(t));
 224
 225                t[0].tx_buf = cmd;
 226                t[0].len = 4;
 227                t[0].cs_change = true;
 228                spi_message_add_tail(&t[0], &m);
 229
 230                /* Busy and non busy words read */
 231                t[1].rx_buf = busy_buf;
 232                t[1].len = WL1271_BUSY_WORD_LEN;
 233                t[1].cs_change = true;
 234                spi_message_add_tail(&t[1], &m);
 235
 236                spi_sync(to_spi_device(glue->dev), &m);
 237
 238                if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
 239                    wl12xx_spi_read_busy(child)) {
 240                        memset(buf, 0, chunk_len);
 241                        return 0;
 242                }
 243
 244                spi_message_init(&m);
 245                memset(t, 0, sizeof(t));
 246
 247                t[0].rx_buf = buf;
 248                t[0].len = chunk_len;
 249                t[0].cs_change = true;
 250                spi_message_add_tail(&t[0], &m);
 251
 252                spi_sync(to_spi_device(glue->dev), &m);
 253
 254                if (!fixed)
 255                        addr += chunk_len;
 256                buf += chunk_len;
 257                len -= chunk_len;
 258        }
 259
 260        return 0;
 261}
 262
 263static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
 264                                             void *buf, size_t len, bool fixed)
 265{
 266        struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
 267        struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
 268        struct spi_message m;
 269        u32 commands[WSPI_MAX_NUM_OF_CHUNKS];
 270        u32 *cmd;
 271        u32 chunk_len;
 272        int i;
 273
 274        WARN_ON(len > WL1271_AGGR_BUFFER_SIZE);
 275
 276        spi_message_init(&m);
 277        memset(t, 0, sizeof(t));
 278
 279        cmd = &commands[0];
 280        i = 0;
 281        while (len > 0) {
 282                chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
 283
 284                *cmd = 0;
 285                *cmd |= WSPI_CMD_WRITE;
 286                *cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) &
 287                        WSPI_CMD_BYTE_LENGTH;
 288                *cmd |= addr & WSPI_CMD_BYTE_ADDR;
 289
 290                if (fixed)
 291                        *cmd |= WSPI_CMD_FIXED;
 292
 293                t[i].tx_buf = cmd;
 294                t[i].len = sizeof(*cmd);
 295                spi_message_add_tail(&t[i++], &m);
 296
 297                t[i].tx_buf = buf;
 298                t[i].len = chunk_len;
 299                spi_message_add_tail(&t[i++], &m);
 300
 301                if (!fixed)
 302                        addr += chunk_len;
 303                buf += chunk_len;
 304                len -= chunk_len;
 305                cmd++;
 306        }
 307
 308        spi_sync(to_spi_device(glue->dev), &m);
 309
 310        return 0;
 311}
 312
 313static struct wl1271_if_operations spi_ops = {
 314        .read           = wl12xx_spi_raw_read,
 315        .write          = wl12xx_spi_raw_write,
 316        .reset          = wl12xx_spi_reset,
 317        .init           = wl12xx_spi_init,
 318        .set_block_size = NULL,
 319};
 320
 321static int __devinit wl1271_probe(struct spi_device *spi)
 322{
 323        struct wl12xx_spi_glue *glue;
 324        struct wl12xx_platform_data *pdata;
 325        struct resource res[1];
 326        int ret = -ENOMEM;
 327
 328        pdata = spi->dev.platform_data;
 329        if (!pdata) {
 330                dev_err(&spi->dev, "no platform data\n");
 331                return -ENODEV;
 332        }
 333
 334        pdata->ops = &spi_ops;
 335
 336        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
 337        if (!glue) {
 338                dev_err(&spi->dev, "can't allocate glue\n");
 339                goto out;
 340        }
 341
 342        glue->dev = &spi->dev;
 343
 344        spi_set_drvdata(spi, glue);
 345
 346        /* This is the only SPI value that we need to set here, the rest
 347         * comes from the board-peripherals file */
 348        spi->bits_per_word = 32;
 349
 350        ret = spi_setup(spi);
 351        if (ret < 0) {
 352                dev_err(glue->dev, "spi_setup failed\n");
 353                goto out_free_glue;
 354        }
 355
 356        glue->core = platform_device_alloc("wl12xx", -1);
 357        if (!glue->core) {
 358                dev_err(glue->dev, "can't allocate platform_device\n");
 359                ret = -ENOMEM;
 360                goto out_free_glue;
 361        }
 362
 363        glue->core->dev.parent = &spi->dev;
 364
 365        memset(res, 0x00, sizeof(res));
 366
 367        res[0].start = spi->irq;
 368        res[0].flags = IORESOURCE_IRQ;
 369        res[0].name = "irq";
 370
 371        ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res));
 372        if (ret) {
 373                dev_err(glue->dev, "can't add resources\n");
 374                goto out_dev_put;
 375        }
 376
 377        ret = platform_device_add_data(glue->core, pdata, sizeof(*pdata));
 378        if (ret) {
 379                dev_err(glue->dev, "can't add platform data\n");
 380                goto out_dev_put;
 381        }
 382
 383        ret = platform_device_add(glue->core);
 384        if (ret) {
 385                dev_err(glue->dev, "can't register platform device\n");
 386                goto out_dev_put;
 387        }
 388
 389        return 0;
 390
 391out_dev_put:
 392        platform_device_put(glue->core);
 393
 394out_free_glue:
 395        kfree(glue);
 396out:
 397        return ret;
 398}
 399
 400static int __devexit wl1271_remove(struct spi_device *spi)
 401{
 402        struct wl12xx_spi_glue *glue = spi_get_drvdata(spi);
 403
 404        platform_device_del(glue->core);
 405        platform_device_put(glue->core);
 406        kfree(glue);
 407
 408        return 0;
 409}
 410
 411
 412static struct spi_driver wl1271_spi_driver = {
 413        .driver = {
 414                .name           = "wl1271_spi",
 415                .owner          = THIS_MODULE,
 416        },
 417
 418        .probe          = wl1271_probe,
 419        .remove         = __devexit_p(wl1271_remove),
 420};
 421
 422static int __init wl1271_init(void)
 423{
 424        return spi_register_driver(&wl1271_spi_driver);
 425}
 426
 427static void __exit wl1271_exit(void)
 428{
 429        spi_unregister_driver(&wl1271_spi_driver);
 430}
 431
 432module_init(wl1271_init);
 433module_exit(wl1271_exit);
 434
 435MODULE_LICENSE("GPL");
 436MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 437MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
 438MODULE_ALIAS("spi:wl1271");
 439