linux/drivers/spi/spi-sc18is602.c
<<
>>
Prefs
   1/*
   2 * NXP SC18IS602/603 SPI driver
   3 *
   4 * Copyright (C) Guenter Roeck <linux@roeck-us.net>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19 */
  20
  21#include <linux/kernel.h>
  22#include <linux/err.h>
  23#include <linux/module.h>
  24#include <linux/spi/spi.h>
  25#include <linux/i2c.h>
  26#include <linux/delay.h>
  27#include <linux/pm_runtime.h>
  28#include <linux/of.h>
  29#include <linux/platform_data/sc18is602.h>
  30
  31enum chips { sc18is602, sc18is602b, sc18is603 };
  32
  33#define SC18IS602_BUFSIZ                200
  34#define SC18IS602_CLOCK                 7372000
  35
  36#define SC18IS602_MODE_CPHA             BIT(2)
  37#define SC18IS602_MODE_CPOL             BIT(3)
  38#define SC18IS602_MODE_LSB_FIRST        BIT(5)
  39#define SC18IS602_MODE_CLOCK_DIV_4      0x0
  40#define SC18IS602_MODE_CLOCK_DIV_16     0x1
  41#define SC18IS602_MODE_CLOCK_DIV_64     0x2
  42#define SC18IS602_MODE_CLOCK_DIV_128    0x3
  43
  44struct sc18is602 {
  45        struct spi_master       *master;
  46        struct device           *dev;
  47        u8                      ctrl;
  48        u32                     freq;
  49        u32                     speed;
  50
  51        /* I2C data */
  52        struct i2c_client       *client;
  53        enum chips              id;
  54        u8                      buffer[SC18IS602_BUFSIZ + 1];
  55        int                     tlen;   /* Data queued for tx in buffer */
  56        int                     rindex; /* Receive data index in buffer */
  57};
  58
  59static int sc18is602_wait_ready(struct sc18is602 *hw, int len)
  60{
  61        int i, err;
  62        int usecs = 1000000 * len / hw->speed + 1;
  63        u8 dummy[1];
  64
  65        for (i = 0; i < 10; i++) {
  66                err = i2c_master_recv(hw->client, dummy, 1);
  67                if (err >= 0)
  68                        return 0;
  69                usleep_range(usecs, usecs * 2);
  70        }
  71        return -ETIMEDOUT;
  72}
  73
  74static int sc18is602_txrx(struct sc18is602 *hw, struct spi_message *msg,
  75                          struct spi_transfer *t, bool do_transfer)
  76{
  77        unsigned int len = t->len;
  78        int ret;
  79
  80        if (hw->tlen == 0) {
  81                /* First byte (I2C command) is chip select */
  82                hw->buffer[0] = 1 << msg->spi->chip_select;
  83                hw->tlen = 1;
  84                hw->rindex = 0;
  85        }
  86        /*
  87         * We can not immediately send data to the chip, since each I2C message
  88         * resembles a full SPI message (from CS active to CS inactive).
  89         * Enqueue messages up to the first read or until do_transfer is true.
  90         */
  91        if (t->tx_buf) {
  92                memcpy(&hw->buffer[hw->tlen], t->tx_buf, len);
  93                hw->tlen += len;
  94                if (t->rx_buf)
  95                        do_transfer = true;
  96                else
  97                        hw->rindex = hw->tlen - 1;
  98        } else if (t->rx_buf) {
  99                /*
 100                 * For receive-only transfers we still need to perform a dummy
 101                 * write to receive data from the SPI chip.
 102                 * Read data starts at the end of transmit data (minus 1 to
 103                 * account for CS).
 104                 */
 105                hw->rindex = hw->tlen - 1;
 106                memset(&hw->buffer[hw->tlen], 0, len);
 107                hw->tlen += len;
 108                do_transfer = true;
 109        }
 110
 111        if (do_transfer && hw->tlen > 1) {
 112                ret = sc18is602_wait_ready(hw, SC18IS602_BUFSIZ);
 113                if (ret < 0)
 114                        return ret;
 115                ret = i2c_master_send(hw->client, hw->buffer, hw->tlen);
 116                if (ret < 0)
 117                        return ret;
 118                if (ret != hw->tlen)
 119                        return -EIO;
 120
 121                if (t->rx_buf) {
 122                        int rlen = hw->rindex + len;
 123
 124                        ret = sc18is602_wait_ready(hw, hw->tlen);
 125                        if (ret < 0)
 126                                return ret;
 127                        ret = i2c_master_recv(hw->client, hw->buffer, rlen);
 128                        if (ret < 0)
 129                                return ret;
 130                        if (ret != rlen)
 131                                return -EIO;
 132                        memcpy(t->rx_buf, &hw->buffer[hw->rindex], len);
 133                }
 134                hw->tlen = 0;
 135        }
 136        return len;
 137}
 138
 139static int sc18is602_setup_transfer(struct sc18is602 *hw, u32 hz, u8 mode)
 140{
 141        u8 ctrl = 0;
 142        int ret;
 143
 144        if (mode & SPI_CPHA)
 145                ctrl |= SC18IS602_MODE_CPHA;
 146        if (mode & SPI_CPOL)
 147                ctrl |= SC18IS602_MODE_CPOL;
 148        if (mode & SPI_LSB_FIRST)
 149                ctrl |= SC18IS602_MODE_LSB_FIRST;
 150
 151        /* Find the closest clock speed */
 152        if (hz >= hw->freq / 4) {
 153                ctrl |= SC18IS602_MODE_CLOCK_DIV_4;
 154                hw->speed = hw->freq / 4;
 155        } else if (hz >= hw->freq / 16) {
 156                ctrl |= SC18IS602_MODE_CLOCK_DIV_16;
 157                hw->speed = hw->freq / 16;
 158        } else if (hz >= hw->freq / 64) {
 159                ctrl |= SC18IS602_MODE_CLOCK_DIV_64;
 160                hw->speed = hw->freq / 64;
 161        } else {
 162                ctrl |= SC18IS602_MODE_CLOCK_DIV_128;
 163                hw->speed = hw->freq / 128;
 164        }
 165
 166        /*
 167         * Don't do anything if the control value did not change. The initial
 168         * value of 0xff for hw->ctrl ensures that the correct mode will be set
 169         * with the first call to this function.
 170         */
 171        if (ctrl == hw->ctrl)
 172                return 0;
 173
 174        ret = i2c_smbus_write_byte_data(hw->client, 0xf0, ctrl);
 175        if (ret < 0)
 176                return ret;
 177
 178        hw->ctrl = ctrl;
 179
 180        return 0;
 181}
 182
 183static int sc18is602_check_transfer(struct spi_device *spi,
 184                                    struct spi_transfer *t, int tlen)
 185{
 186        int bpw;
 187        uint32_t hz;
 188
 189        if (t && t->len + tlen > SC18IS602_BUFSIZ)
 190                return -EINVAL;
 191
 192        bpw = spi->bits_per_word;
 193        if (t && t->bits_per_word)
 194                bpw = t->bits_per_word;
 195        if (bpw != 8)
 196                return -EINVAL;
 197
 198        hz = spi->max_speed_hz;
 199        if (t && t->speed_hz)
 200                hz = t->speed_hz;
 201        if (hz == 0)
 202                return -EINVAL;
 203
 204        return 0;
 205}
 206
 207static int sc18is602_transfer_one(struct spi_master *master,
 208                                  struct spi_message *m)
 209{
 210        struct sc18is602 *hw = spi_master_get_devdata(master);
 211        struct spi_device *spi = m->spi;
 212        struct spi_transfer *t;
 213        int status = 0;
 214
 215        /* SC18IS602 does not support CS2 */
 216        if (hw->id == sc18is602 && spi->chip_select == 2) {
 217                status = -ENXIO;
 218                goto error;
 219        }
 220
 221        hw->tlen = 0;
 222        list_for_each_entry(t, &m->transfers, transfer_list) {
 223                u32 hz = t->speed_hz ? : spi->max_speed_hz;
 224                bool do_transfer;
 225
 226                status = sc18is602_check_transfer(spi, t, hw->tlen);
 227                if (status < 0)
 228                        break;
 229
 230                status = sc18is602_setup_transfer(hw, hz, spi->mode);
 231                if (status < 0)
 232                        break;
 233
 234                do_transfer = t->cs_change || list_is_last(&t->transfer_list,
 235                                                           &m->transfers);
 236
 237                if (t->len) {
 238                        status = sc18is602_txrx(hw, m, t, do_transfer);
 239                        if (status < 0)
 240                                break;
 241                        m->actual_length += status;
 242                }
 243                status = 0;
 244
 245                if (t->delay_usecs)
 246                        udelay(t->delay_usecs);
 247        }
 248error:
 249        m->status = status;
 250        spi_finalize_current_message(master);
 251
 252        return status;
 253}
 254
 255static int sc18is602_setup(struct spi_device *spi)
 256{
 257        if (!spi->bits_per_word)
 258                spi->bits_per_word = 8;
 259
 260        if (spi->mode & ~(SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST))
 261                return -EINVAL;
 262
 263        return sc18is602_check_transfer(spi, NULL, 0);
 264}
 265
 266static int sc18is602_probe(struct i2c_client *client,
 267                           const struct i2c_device_id *id)
 268{
 269        struct device *dev = &client->dev;
 270        struct device_node *np = dev->of_node;
 271        struct sc18is602_platform_data *pdata = dev_get_platdata(dev);
 272        struct sc18is602 *hw;
 273        struct spi_master *master;
 274        int error;
 275
 276        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
 277                                     I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
 278                return -EINVAL;
 279
 280        master = spi_alloc_master(dev, sizeof(struct sc18is602));
 281        if (!master)
 282                return -ENOMEM;
 283
 284        hw = spi_master_get_devdata(master);
 285        i2c_set_clientdata(client, hw);
 286
 287        hw->master = master;
 288        hw->client = client;
 289        hw->dev = dev;
 290        hw->ctrl = 0xff;
 291
 292        hw->id = id->driver_data;
 293
 294        switch (hw->id) {
 295        case sc18is602:
 296        case sc18is602b:
 297                master->num_chipselect = 4;
 298                hw->freq = SC18IS602_CLOCK;
 299                break;
 300        case sc18is603:
 301                master->num_chipselect = 2;
 302                if (pdata) {
 303                        hw->freq = pdata->clock_frequency;
 304                } else {
 305                        const __be32 *val;
 306                        int len;
 307
 308                        val = of_get_property(np, "clock-frequency", &len);
 309                        if (val && len >= sizeof(__be32))
 310                                hw->freq = be32_to_cpup(val);
 311                }
 312                if (!hw->freq)
 313                        hw->freq = SC18IS602_CLOCK;
 314                break;
 315        }
 316        master->bus_num = client->adapter->nr;
 317        master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST;
 318        master->setup = sc18is602_setup;
 319        master->transfer_one_message = sc18is602_transfer_one;
 320        master->dev.of_node = np;
 321
 322        error = spi_register_master(master);
 323        if (error)
 324                goto error_reg;
 325
 326        return 0;
 327
 328error_reg:
 329        spi_master_put(master);
 330        return error;
 331}
 332
 333static int sc18is602_remove(struct i2c_client *client)
 334{
 335        struct sc18is602 *hw = i2c_get_clientdata(client);
 336        struct spi_master *master = hw->master;
 337
 338        spi_unregister_master(master);
 339
 340        return 0;
 341}
 342
 343static const struct i2c_device_id sc18is602_id[] = {
 344        { "sc18is602", sc18is602 },
 345        { "sc18is602b", sc18is602b },
 346        { "sc18is603", sc18is603 },
 347        { }
 348};
 349MODULE_DEVICE_TABLE(i2c, sc18is602_id);
 350
 351static struct i2c_driver sc18is602_driver = {
 352        .driver = {
 353                .name = "sc18is602",
 354        },
 355        .probe = sc18is602_probe,
 356        .remove = sc18is602_remove,
 357        .id_table = sc18is602_id,
 358};
 359
 360module_i2c_driver(sc18is602_driver);
 361
 362MODULE_DESCRIPTION("SC18IC602/603 SPI Master Driver");
 363MODULE_AUTHOR("Guenter Roeck");
 364MODULE_LICENSE("GPL");
 365
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.