linux/drivers/net/wireless/ti/wl1251/spi.c
<<
>>
Prefs
   1/*
   2 * This file is part of wl1251
   3 *
   4 * Copyright (C) 2008 Nokia Corporation
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * version 2 as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  18 * 02110-1301 USA
  19 *
  20 */
  21
  22#include <linux/interrupt.h>
  23#include <linux/irq.h>
  24#include <linux/module.h>
  25#include <linux/slab.h>
  26#include <linux/crc7.h>
  27#include <linux/spi/spi.h>
  28#include <linux/wl12xx.h>
  29
  30#include "wl1251.h"
  31#include "reg.h"
  32#include "spi.h"
  33
  34static irqreturn_t wl1251_irq(int irq, void *cookie)
  35{
  36        struct wl1251 *wl;
  37
  38        wl1251_debug(DEBUG_IRQ, "IRQ");
  39
  40        wl = cookie;
  41
  42        ieee80211_queue_work(wl->hw, &wl->irq_work);
  43
  44        return IRQ_HANDLED;
  45}
  46
  47static struct spi_device *wl_to_spi(struct wl1251 *wl)
  48{
  49        return wl->if_priv;
  50}
  51
  52static void wl1251_spi_reset(struct wl1251 *wl)
  53{
  54        u8 *cmd;
  55        struct spi_transfer t;
  56        struct spi_message m;
  57
  58        cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
  59        if (!cmd) {
  60                wl1251_error("could not allocate cmd for spi reset");
  61                return;
  62        }
  63
  64        memset(&t, 0, sizeof(t));
  65        spi_message_init(&m);
  66
  67        memset(cmd, 0xff, WSPI_INIT_CMD_LEN);
  68
  69        t.tx_buf = cmd;
  70        t.len = WSPI_INIT_CMD_LEN;
  71        spi_message_add_tail(&t, &m);
  72
  73        spi_sync(wl_to_spi(wl), &m);
  74
  75        wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
  76
  77        kfree(cmd);
  78}
  79
  80static void wl1251_spi_wake(struct wl1251 *wl)
  81{
  82        u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
  83        struct spi_transfer t;
  84        struct spi_message m;
  85
  86        cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
  87        if (!cmd) {
  88                wl1251_error("could not allocate cmd for spi init");
  89                return;
  90        }
  91
  92        memset(crc, 0, sizeof(crc));
  93        memset(&t, 0, sizeof(t));
  94        spi_message_init(&m);
  95
  96        /*
  97         * Set WSPI_INIT_COMMAND
  98         * the data is being send from the MSB to LSB
  99         */
 100        cmd[2] = 0xff;
 101        cmd[3] = 0xff;
 102        cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
 103        cmd[0] = 0;
 104        cmd[7] = 0;
 105        cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
 106        cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
 107
 108        if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
 109                cmd[5] |=  WSPI_INIT_CMD_DIS_FIXEDBUSY;
 110        else
 111                cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
 112
 113        cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
 114                | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
 115
 116        crc[0] = cmd[1];
 117        crc[1] = cmd[0];
 118        crc[2] = cmd[7];
 119        crc[3] = cmd[6];
 120        crc[4] = cmd[5];
 121
 122        cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
 123        cmd[4] |= WSPI_INIT_CMD_END;
 124
 125        t.tx_buf = cmd;
 126        t.len = WSPI_INIT_CMD_LEN;
 127        spi_message_add_tail(&t, &m);
 128
 129        spi_sync(wl_to_spi(wl), &m);
 130
 131        wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
 132
 133        kfree(cmd);
 134}
 135
 136static void wl1251_spi_reset_wake(struct wl1251 *wl)
 137{
 138        wl1251_spi_reset(wl);
 139        wl1251_spi_wake(wl);
 140}
 141
 142static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
 143                            size_t len)
 144{
 145        struct spi_transfer t[3];
 146        struct spi_message m;
 147        u8 *busy_buf;
 148        u32 *cmd;
 149
 150        cmd = &wl->buffer_cmd;
 151        busy_buf = wl->buffer_busyword;
 152
 153        *cmd = 0;
 154        *cmd |= WSPI_CMD_READ;
 155        *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
 156        *cmd |= addr & WSPI_CMD_BYTE_ADDR;
 157
 158        spi_message_init(&m);
 159        memset(t, 0, sizeof(t));
 160
 161        t[0].tx_buf = cmd;
 162        t[0].len = 4;
 163        spi_message_add_tail(&t[0], &m);
 164
 165        /* Busy and non busy words read */
 166        t[1].rx_buf = busy_buf;
 167        t[1].len = WL1251_BUSY_WORD_LEN;
 168        spi_message_add_tail(&t[1], &m);
 169
 170        t[2].rx_buf = buf;
 171        t[2].len = len;
 172        spi_message_add_tail(&t[2], &m);
 173
 174        spi_sync(wl_to_spi(wl), &m);
 175
 176        /* FIXME: check busy words */
 177
 178        wl1251_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
 179        wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
 180}
 181
 182static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
 183                             size_t len)
 184{
 185        struct spi_transfer t[2];
 186        struct spi_message m;
 187        u32 *cmd;
 188
 189        cmd = &wl->buffer_cmd;
 190
 191        *cmd = 0;
 192        *cmd |= WSPI_CMD_WRITE;
 193        *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
 194        *cmd |= addr & WSPI_CMD_BYTE_ADDR;
 195
 196        spi_message_init(&m);
 197        memset(t, 0, sizeof(t));
 198
 199        t[0].tx_buf = cmd;
 200        t[0].len = sizeof(*cmd);
 201        spi_message_add_tail(&t[0], &m);
 202
 203        t[1].tx_buf = buf;
 204        t[1].len = len;
 205        spi_message_add_tail(&t[1], &m);
 206
 207        spi_sync(wl_to_spi(wl), &m);
 208
 209        wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
 210        wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
 211}
 212
 213static void wl1251_spi_enable_irq(struct wl1251 *wl)
 214{
 215        return enable_irq(wl->irq);
 216}
 217
 218static void wl1251_spi_disable_irq(struct wl1251 *wl)
 219{
 220        return disable_irq(wl->irq);
 221}
 222
 223static int wl1251_spi_set_power(struct wl1251 *wl, bool enable)
 224{
 225        if (wl->set_power)
 226                wl->set_power(enable);
 227
 228        return 0;
 229}
 230
 231static const struct wl1251_if_operations wl1251_spi_ops = {
 232        .read = wl1251_spi_read,
 233        .write = wl1251_spi_write,
 234        .reset = wl1251_spi_reset_wake,
 235        .enable_irq = wl1251_spi_enable_irq,
 236        .disable_irq = wl1251_spi_disable_irq,
 237        .power = wl1251_spi_set_power,
 238};
 239
 240static int wl1251_spi_probe(struct spi_device *spi)
 241{
 242        struct wl12xx_platform_data *pdata;
 243        struct ieee80211_hw *hw;
 244        struct wl1251 *wl;
 245        int ret;
 246
 247        pdata = spi->dev.platform_data;
 248        if (!pdata) {
 249                wl1251_error("no platform data");
 250                return -ENODEV;
 251        }
 252
 253        hw = wl1251_alloc_hw();
 254        if (IS_ERR(hw))
 255                return PTR_ERR(hw);
 256
 257        wl = hw->priv;
 258
 259        SET_IEEE80211_DEV(hw, &spi->dev);
 260        spi_set_drvdata(spi, wl);
 261        wl->if_priv = spi;
 262        wl->if_ops = &wl1251_spi_ops;
 263
 264        /* This is the only SPI value that we need to set here, the rest
 265         * comes from the board-peripherals file */
 266        spi->bits_per_word = 32;
 267
 268        ret = spi_setup(spi);
 269        if (ret < 0) {
 270                wl1251_error("spi_setup failed");
 271                goto out_free;
 272        }
 273
 274        wl->set_power = pdata->set_power;
 275        if (!wl->set_power) {
 276                wl1251_error("set power function missing in platform data");
 277                return -ENODEV;
 278        }
 279
 280        wl->irq = spi->irq;
 281        if (wl->irq < 0) {
 282                wl1251_error("irq missing in platform data");
 283                return -ENODEV;
 284        }
 285
 286        wl->use_eeprom = pdata->use_eeprom;
 287
 288        irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);
 289        ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
 290        if (ret < 0) {
 291                wl1251_error("request_irq() failed: %d", ret);
 292                goto out_free;
 293        }
 294
 295        irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
 296
 297        ret = wl1251_init_ieee80211(wl);
 298        if (ret)
 299                goto out_irq;
 300
 301        return 0;
 302
 303 out_irq:
 304        free_irq(wl->irq, wl);
 305
 306 out_free:
 307        ieee80211_free_hw(hw);
 308
 309        return ret;
 310}
 311
 312static int wl1251_spi_remove(struct spi_device *spi)
 313{
 314        struct wl1251 *wl = spi_get_drvdata(spi);
 315
 316        free_irq(wl->irq, wl);
 317        wl1251_free_hw(wl);
 318
 319        return 0;
 320}
 321
 322static struct spi_driver wl1251_spi_driver = {
 323        .driver = {
 324                .name           = DRIVER_NAME,
 325                .owner          = THIS_MODULE,
 326        },
 327
 328        .probe          = wl1251_spi_probe,
 329        .remove         = wl1251_spi_remove,
 330};
 331
 332static int __init wl1251_spi_init(void)
 333{
 334        int ret;
 335
 336        ret = spi_register_driver(&wl1251_spi_driver);
 337        if (ret < 0) {
 338                wl1251_error("failed to register spi driver: %d", ret);
 339                goto out;
 340        }
 341
 342out:
 343        return ret;
 344}
 345
 346static void __exit wl1251_spi_exit(void)
 347{
 348        spi_unregister_driver(&wl1251_spi_driver);
 349
 350        wl1251_notice("unloaded");
 351}
 352
 353module_init(wl1251_spi_init);
 354module_exit(wl1251_spi_exit);
 355
 356MODULE_LICENSE("GPL");
 357MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
 358MODULE_ALIAS("spi:wl1251");
 359