linux/drivers/staging/wilc1000/linux_wlan_spi.c
<<
>>
Prefs
   1#include <linux/module.h>
   2#include <linux/init.h>
   3#include <linux/kernel.h>
   4#include <linux/fs.h>
   5#include <linux/slab.h>
   6#include <linux/types.h>
   7#include <linux/cdev.h>
   8#include <linux/uaccess.h>
   9#include <linux/device.h>
  10#include <linux/spi/spi.h>
  11
  12#include "linux_wlan_common.h"
  13#include "linux_wlan_spi.h"
  14
  15#define USE_SPI_DMA     0       /* johnny add */
  16
  17#ifdef WILC_ASIC_A0
  18 #if defined(PLAT_PANDA_ES_OMAP4460)
  19  #define MIN_SPEED 12000000
  20  #define MAX_SPEED 24000000
  21 #elif defined(PLAT_WMS8304)
  22  #define MIN_SPEED 12000000
  23  #define MAX_SPEED 24000000 /* 4000000 */
  24 #elif defined(CUSTOMER_PLATFORM)
  25/*
  26  TODO : define Clock speed under 48M.
  27 *
  28 * ex)
  29 * #define MIN_SPEED 24000000
  30 * #define MAX_SPEED 48000000
  31 */
  32 #else
  33  #define MIN_SPEED 24000000
  34  #define MAX_SPEED 48000000
  35 #endif
  36#else /* WILC_ASIC_A0 */
  37/* Limit clk to 6MHz on FPGA. */
  38 #define MIN_SPEED 6000000
  39 #define MAX_SPEED 6000000
  40#endif /* WILC_ASIC_A0 */
  41
  42static u32 SPEED = MIN_SPEED;
  43
  44struct spi_device *wilc_spi_dev;
  45void linux_spi_deinit(void *vp);
  46
  47static int __init wilc_bus_probe(struct spi_device *spi)
  48{
  49
  50        PRINT_D(BUS_DBG, "spiModalias: %s\n", spi->modalias);
  51        PRINT_D(BUS_DBG, "spiMax-Speed: %d\n", spi->max_speed_hz);
  52        wilc_spi_dev = spi;
  53
  54        printk("Driver Initializing success\n");
  55        return 0;
  56}
  57
  58static int __exit wilc_bus_remove(struct spi_device *spi)
  59{
  60
  61        return 0;
  62}
  63
  64#ifdef CONFIG_OF
  65static const struct of_device_id wilc1000_of_match[] = {
  66        { .compatible = "atmel,wilc_spi", },
  67        {}
  68};
  69MODULE_DEVICE_TABLE(of, wilc1000_of_match);
  70#endif
  71
  72struct spi_driver wilc_bus __refdata = {
  73        .driver = {
  74                .name = MODALIAS,
  75#ifdef CONFIG_OF
  76                .of_match_table = wilc1000_of_match,
  77#endif
  78        },
  79        .probe =  wilc_bus_probe,
  80        .remove = __exit_p(wilc_bus_remove),
  81};
  82
  83
  84void linux_spi_deinit(void *vp)
  85{
  86
  87        spi_unregister_driver(&wilc_bus);
  88
  89        SPEED = MIN_SPEED;
  90        PRINT_ER("@@@@@@@@@@@@ restore SPI speed to %d @@@@@@@@@\n", SPEED);
  91
  92}
  93
  94
  95
  96int linux_spi_init(void *vp)
  97{
  98        int ret = 1;
  99        static int called;
 100
 101
 102        if (called == 0) {
 103                called++;
 104                ret = spi_register_driver(&wilc_bus);
 105        }
 106
 107        /* change return value to match WILC interface */
 108        (ret < 0) ? (ret = 0) : (ret = 1);
 109
 110        return ret;
 111}
 112
 113#if defined(PLAT_WMS8304)
 114#define TXRX_PHASE_SIZE (4096)
 115#endif
 116
 117#if defined(TXRX_PHASE_SIZE)
 118
 119int linux_spi_write(u8 *b, u32 len)
 120{
 121        int ret;
 122
 123        if (len > 0 && b != NULL) {
 124                int i = 0;
 125                int blk = len / TXRX_PHASE_SIZE;
 126                int remainder = len % TXRX_PHASE_SIZE;
 127
 128                char *r_buffer = kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL);
 129                if (!r_buffer)
 130                        return -ENOMEM;
 131
 132                if (blk) {
 133                        while (i < blk) {
 134                                struct spi_message msg;
 135                                struct spi_transfer tr = {
 136                                        .tx_buf = b + (i * TXRX_PHASE_SIZE),
 137                                        .len = TXRX_PHASE_SIZE,
 138                                        .speed_hz = SPEED,
 139                                        .bits_per_word = 8,
 140                                        .delay_usecs = 0,
 141                                };
 142
 143                                tr.rx_buf = r_buffer;
 144
 145                                memset(&msg, 0, sizeof(msg));
 146                                spi_message_init(&msg);
 147                                msg.spi = wilc_spi_dev;
 148                                msg.is_dma_mapped = USE_SPI_DMA;
 149
 150                                spi_message_add_tail(&tr, &msg);
 151                                ret = spi_sync(wilc_spi_dev, &msg);
 152                                if (ret < 0) {
 153                                        PRINT_ER("SPI transaction failed\n");
 154                                }
 155                                i++;
 156
 157                        }
 158                }
 159                if (remainder) {
 160                        struct spi_message msg;
 161                        struct spi_transfer tr = {
 162                                .tx_buf = b + (blk * TXRX_PHASE_SIZE),
 163                                .len = remainder,
 164                                .speed_hz = SPEED,
 165                                .bits_per_word = 8,
 166                                .delay_usecs = 0,
 167                        };
 168                        tr.rx_buf = r_buffer;
 169
 170                        memset(&msg, 0, sizeof(msg));
 171                        spi_message_init(&msg);
 172                        msg.spi = wilc_spi_dev;
 173                        msg.is_dma_mapped = USE_SPI_DMA;                                /* rachel */
 174
 175                        spi_message_add_tail(&tr, &msg);
 176                        ret = spi_sync(wilc_spi_dev, &msg);
 177                        if (ret < 0) {
 178                                PRINT_ER("SPI transaction failed\n");
 179                        }
 180                }
 181                kfree(r_buffer);
 182        } else {
 183                PRINT_ER("can't write data with the following length: %d\n", len);
 184                PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n", len);
 185                ret = -1;
 186        }
 187
 188        /* change return value to match WILC interface */
 189        (ret < 0) ? (ret = 0) : (ret = 1);
 190
 191        return ret;
 192
 193}
 194
 195#else
 196int linux_spi_write(u8 *b, u32 len)
 197{
 198
 199        int ret;
 200        struct spi_message msg;
 201
 202        if (len > 0 && b != NULL) {
 203                struct spi_transfer tr = {
 204                        .tx_buf = b,
 205                        .len = len,
 206                        .speed_hz = SPEED,
 207                        .delay_usecs = 0,
 208                };
 209                char *r_buffer = kzalloc(len, GFP_KERNEL);
 210                if (!r_buffer)
 211                        return -ENOMEM;
 212
 213                tr.rx_buf = r_buffer;
 214                PRINT_D(BUS_DBG, "Request writing %d bytes\n", len);
 215
 216                memset(&msg, 0, sizeof(msg));
 217                spi_message_init(&msg);
 218/* [[johnny add */
 219                msg.spi = wilc_spi_dev;
 220                msg.is_dma_mapped = USE_SPI_DMA;
 221/* ]] */
 222                spi_message_add_tail(&tr, &msg);
 223
 224                ret = spi_sync(wilc_spi_dev, &msg);
 225                if (ret < 0) {
 226                        PRINT_ER("SPI transaction failed\n");
 227                }
 228
 229                kfree(r_buffer);
 230        } else {
 231                PRINT_ER("can't write data with the following length: %d\n", len);
 232                PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n", len);
 233                ret = -1;
 234        }
 235
 236        /* change return value to match WILC interface */
 237        (ret < 0) ? (ret = 0) : (ret = 1);
 238
 239
 240        return ret;
 241}
 242
 243#endif
 244
 245#if defined(TXRX_PHASE_SIZE)
 246
 247int linux_spi_read(u8 *rb, u32 rlen)
 248{
 249        int ret;
 250
 251        if (rlen > 0) {
 252                int i = 0;
 253
 254                int blk = rlen / TXRX_PHASE_SIZE;
 255                int remainder = rlen % TXRX_PHASE_SIZE;
 256
 257                char *t_buffer = kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL);
 258                if (!t_buffer)
 259                        return -ENOMEM;
 260
 261                if (blk) {
 262                        while (i < blk) {
 263                                struct spi_message msg;
 264                                struct spi_transfer tr = {
 265                                        .rx_buf = rb + (i * TXRX_PHASE_SIZE),
 266                                        .len = TXRX_PHASE_SIZE,
 267                                        .speed_hz = SPEED,
 268                                        .bits_per_word = 8,
 269                                        .delay_usecs = 0,
 270                                };
 271                                tr.tx_buf = t_buffer;
 272
 273                                memset(&msg, 0, sizeof(msg));
 274                                spi_message_init(&msg);
 275                                msg.spi = wilc_spi_dev;
 276                                msg.is_dma_mapped = USE_SPI_DMA;
 277
 278                                spi_message_add_tail(&tr, &msg);
 279                                ret = spi_sync(wilc_spi_dev, &msg);
 280                                if (ret < 0) {
 281                                        PRINT_ER("SPI transaction failed\n");
 282                                }
 283                                i++;
 284                        }
 285                }
 286                if (remainder) {
 287                        struct spi_message msg;
 288                        struct spi_transfer tr = {
 289                                .rx_buf = rb + (blk * TXRX_PHASE_SIZE),
 290                                .len = remainder,
 291                                .speed_hz = SPEED,
 292                                .bits_per_word = 8,
 293                                .delay_usecs = 0,
 294                        };
 295                        tr.tx_buf = t_buffer;
 296
 297                        memset(&msg, 0, sizeof(msg));
 298                        spi_message_init(&msg);
 299                        msg.spi = wilc_spi_dev;
 300                        msg.is_dma_mapped = USE_SPI_DMA;                                /* rachel */
 301
 302                        spi_message_add_tail(&tr, &msg);
 303                        ret = spi_sync(wilc_spi_dev, &msg);
 304                        if (ret < 0) {
 305                                PRINT_ER("SPI transaction failed\n");
 306                        }
 307                }
 308
 309                kfree(t_buffer);
 310        } else {
 311                PRINT_ER("can't read data with the following length: %u\n", rlen);
 312                ret = -1;
 313        }
 314        /* change return value to match WILC interface */
 315        (ret < 0) ? (ret = 0) : (ret = 1);
 316
 317        return ret;
 318}
 319
 320#else
 321int linux_spi_read(u8 *rb, u32 rlen)
 322{
 323
 324        int ret;
 325
 326        if (rlen > 0) {
 327                struct spi_message msg;
 328                struct spi_transfer tr = {
 329                        .rx_buf = rb,
 330                        .len = rlen,
 331                        .speed_hz = SPEED,
 332                        .delay_usecs = 0,
 333
 334                };
 335                char *t_buffer = kzalloc(rlen, GFP_KERNEL);
 336                if (!t_buffer)
 337                        return -ENOMEM;
 338
 339                tr.tx_buf = t_buffer;
 340
 341                memset(&msg, 0, sizeof(msg));
 342                spi_message_init(&msg);
 343/* [[ johnny add */
 344                msg.spi = wilc_spi_dev;
 345                msg.is_dma_mapped = USE_SPI_DMA;
 346/* ]] */
 347                spi_message_add_tail(&tr, &msg);
 348
 349                ret = spi_sync(wilc_spi_dev, &msg);
 350                if (ret < 0) {
 351                        PRINT_ER("SPI transaction failed\n");
 352                }
 353                kfree(t_buffer);
 354        } else {
 355                PRINT_ER("can't read data with the following length: %u\n", rlen);
 356                ret = -1;
 357        }
 358        /* change return value to match WILC interface */
 359        (ret < 0) ? (ret = 0) : (ret = 1);
 360
 361        return ret;
 362}
 363
 364#endif
 365
 366int linux_spi_write_read(u8 *wb, u8 *rb, u32 rlen)
 367{
 368
 369        int ret;
 370
 371        if (rlen > 0) {
 372                struct spi_message msg;
 373                struct spi_transfer tr = {
 374                        .rx_buf = rb,
 375                        .tx_buf = wb,
 376                        .len = rlen,
 377                        .speed_hz = SPEED,
 378                        .bits_per_word = 8,
 379                        .delay_usecs = 0,
 380
 381                };
 382
 383                memset(&msg, 0, sizeof(msg));
 384                spi_message_init(&msg);
 385                msg.spi = wilc_spi_dev;
 386                msg.is_dma_mapped = USE_SPI_DMA;
 387
 388                spi_message_add_tail(&tr, &msg);
 389                ret = spi_sync(wilc_spi_dev, &msg);
 390                if (ret < 0) {
 391                        PRINT_ER("SPI transaction failed\n");
 392                }
 393        } else {
 394                PRINT_ER("can't read data with the following length: %u\n", rlen);
 395                ret = -1;
 396        }
 397        /* change return value to match WILC interface */
 398        (ret < 0) ? (ret = 0) : (ret = 1);
 399
 400        return ret;
 401}
 402
 403int linux_spi_set_max_speed(void)
 404{
 405        SPEED = MAX_SPEED;
 406
 407        PRINT_INFO(BUS_DBG, "@@@@@@@@@@@@ change SPI speed to %d @@@@@@@@@\n", SPEED);
 408        return 1;
 409}
 410