linux/drivers/spi/spi-orion.c
<<
>>
Prefs
   1/*
   2 * Marvell Orion SPI controller driver
   3 *
   4 * Author: Shadi Ammouri <shadi@marvell.com>
   5 * Copyright (C) 2007-2008 Marvell Ltd.
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/init.h>
  13#include <linux/interrupt.h>
  14#include <linux/delay.h>
  15#include <linux/platform_device.h>
  16#include <linux/err.h>
  17#include <linux/io.h>
  18#include <linux/spi/spi.h>
  19#include <linux/module.h>
  20#include <linux/of.h>
  21#include <linux/clk.h>
  22#include <linux/sizes.h>
  23#include <asm/unaligned.h>
  24
  25#define DRIVER_NAME                     "orion_spi"
  26
  27#define ORION_NUM_CHIPSELECTS           1 /* only one slave is supported*/
  28#define ORION_SPI_WAIT_RDY_MAX_LOOP     2000 /* in usec */
  29
  30#define ORION_SPI_IF_CTRL_REG           0x00
  31#define ORION_SPI_IF_CONFIG_REG         0x04
  32#define ORION_SPI_DATA_OUT_REG          0x08
  33#define ORION_SPI_DATA_IN_REG           0x0c
  34#define ORION_SPI_INT_CAUSE_REG         0x10
  35
  36#define ORION_SPI_MODE_CPOL             (1 << 11)
  37#define ORION_SPI_MODE_CPHA             (1 << 12)
  38#define ORION_SPI_IF_8_16_BIT_MODE      (1 << 5)
  39#define ORION_SPI_CLK_PRESCALE_MASK     0x1F
  40#define ORION_SPI_MODE_MASK             (ORION_SPI_MODE_CPOL | \
  41                                         ORION_SPI_MODE_CPHA)
  42
  43struct orion_spi {
  44        struct spi_master       *master;
  45        void __iomem            *base;
  46        unsigned int            max_speed;
  47        unsigned int            min_speed;
  48        struct clk              *clk;
  49};
  50
  51static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
  52{
  53        return orion_spi->base + reg;
  54}
  55
  56static inline void
  57orion_spi_setbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
  58{
  59        void __iomem *reg_addr = spi_reg(orion_spi, reg);
  60        u32 val;
  61
  62        val = readl(reg_addr);
  63        val |= mask;
  64        writel(val, reg_addr);
  65}
  66
  67static inline void
  68orion_spi_clrbits(struct orion_spi *orion_spi, u32 reg, u32 mask)
  69{
  70        void __iomem *reg_addr = spi_reg(orion_spi, reg);
  71        u32 val;
  72
  73        val = readl(reg_addr);
  74        val &= ~mask;
  75        writel(val, reg_addr);
  76}
  77
  78static int orion_spi_set_transfer_size(struct orion_spi *orion_spi, int size)
  79{
  80        if (size == 16) {
  81                orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
  82                                  ORION_SPI_IF_8_16_BIT_MODE);
  83        } else if (size == 8) {
  84                orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
  85                                  ORION_SPI_IF_8_16_BIT_MODE);
  86        } else {
  87                pr_debug("Bad bits per word value %d (only 8 or 16 are "
  88                         "allowed).\n", size);
  89                return -EINVAL;
  90        }
  91
  92        return 0;
  93}
  94
  95static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
  96{
  97        u32 tclk_hz;
  98        u32 rate;
  99        u32 prescale;
 100        u32 reg;
 101        struct orion_spi *orion_spi;
 102
 103        orion_spi = spi_master_get_devdata(spi->master);
 104
 105        tclk_hz = clk_get_rate(orion_spi->clk);
 106
 107        /*
 108         * the supported rates are: 4,6,8...30
 109         * round up as we look for equal or less speed
 110         */
 111        rate = DIV_ROUND_UP(tclk_hz, speed);
 112        rate = roundup(rate, 2);
 113
 114        /* check if requested speed is too small */
 115        if (rate > 30)
 116                return -EINVAL;
 117
 118        if (rate < 4)
 119                rate = 4;
 120
 121        /* Convert the rate to SPI clock divisor value. */
 122        prescale = 0x10 + rate/2;
 123
 124        reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
 125        reg = ((reg & ~ORION_SPI_CLK_PRESCALE_MASK) | prescale);
 126        writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
 127
 128        return 0;
 129}
 130
 131static void
 132orion_spi_mode_set(struct spi_device *spi)
 133{
 134        u32 reg;
 135        struct orion_spi *orion_spi;
 136
 137        orion_spi = spi_master_get_devdata(spi->master);
 138
 139        reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
 140        reg &= ~ORION_SPI_MODE_MASK;
 141        if (spi->mode & SPI_CPOL)
 142                reg |= ORION_SPI_MODE_CPOL;
 143        if (spi->mode & SPI_CPHA)
 144                reg |= ORION_SPI_MODE_CPHA;
 145        writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG));
 146}
 147
 148/*
 149 * called only when no transfer is active on the bus
 150 */
 151static int
 152orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 153{
 154        struct orion_spi *orion_spi;
 155        unsigned int speed = spi->max_speed_hz;
 156        unsigned int bits_per_word = spi->bits_per_word;
 157        int     rc;
 158
 159        orion_spi = spi_master_get_devdata(spi->master);
 160
 161        if ((t != NULL) && t->speed_hz)
 162                speed = t->speed_hz;
 163
 164        if ((t != NULL) && t->bits_per_word)
 165                bits_per_word = t->bits_per_word;
 166
 167        orion_spi_mode_set(spi);
 168
 169        rc = orion_spi_baudrate_set(spi, speed);
 170        if (rc)
 171                return rc;
 172
 173        return orion_spi_set_transfer_size(orion_spi, bits_per_word);
 174}
 175
 176static void orion_spi_set_cs(struct orion_spi *orion_spi, int enable)
 177{
 178        if (enable)
 179                orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
 180        else
 181                orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
 182}
 183
 184static inline int orion_spi_wait_till_ready(struct orion_spi *orion_spi)
 185{
 186        int i;
 187
 188        for (i = 0; i < ORION_SPI_WAIT_RDY_MAX_LOOP; i++) {
 189                if (readl(spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG)))
 190                        return 1;
 191                else
 192                        udelay(1);
 193        }
 194
 195        return -1;
 196}
 197
 198static inline int
 199orion_spi_write_read_8bit(struct spi_device *spi,
 200                          const u8 **tx_buf, u8 **rx_buf)
 201{
 202        void __iomem *tx_reg, *rx_reg, *int_reg;
 203        struct orion_spi *orion_spi;
 204
 205        orion_spi = spi_master_get_devdata(spi->master);
 206        tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG);
 207        rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG);
 208        int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG);
 209
 210        /* clear the interrupt cause register */
 211        writel(0x0, int_reg);
 212
 213        if (tx_buf && *tx_buf)
 214                writel(*(*tx_buf)++, tx_reg);
 215        else
 216                writel(0, tx_reg);
 217
 218        if (orion_spi_wait_till_ready(orion_spi) < 0) {
 219                dev_err(&spi->dev, "TXS timed out\n");
 220                return -1;
 221        }
 222
 223        if (rx_buf && *rx_buf)
 224                *(*rx_buf)++ = readl(rx_reg);
 225
 226        return 1;
 227}
 228
 229static inline int
 230orion_spi_write_read_16bit(struct spi_device *spi,
 231                           const u16 **tx_buf, u16 **rx_buf)
 232{
 233        void __iomem *tx_reg, *rx_reg, *int_reg;
 234        struct orion_spi *orion_spi;
 235
 236        orion_spi = spi_master_get_devdata(spi->master);
 237        tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG);
 238        rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG);
 239        int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG);
 240
 241        /* clear the interrupt cause register */
 242        writel(0x0, int_reg);
 243
 244        if (tx_buf && *tx_buf)
 245                writel(__cpu_to_le16(get_unaligned((*tx_buf)++)), tx_reg);
 246        else
 247                writel(0, tx_reg);
 248
 249        if (orion_spi_wait_till_ready(orion_spi) < 0) {
 250                dev_err(&spi->dev, "TXS timed out\n");
 251                return -1;
 252        }
 253
 254        if (rx_buf && *rx_buf)
 255                put_unaligned(__le16_to_cpu(readl(rx_reg)), (*rx_buf)++);
 256
 257        return 1;
 258}
 259
 260static unsigned int
 261orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
 262{
 263        struct orion_spi *orion_spi;
 264        unsigned int count;
 265        int word_len;
 266
 267        orion_spi = spi_master_get_devdata(spi->master);
 268        word_len = spi->bits_per_word;
 269        count = xfer->len;
 270
 271        if (word_len == 8) {
 272                const u8 *tx = xfer->tx_buf;
 273                u8 *rx = xfer->rx_buf;
 274
 275                do {
 276                        if (orion_spi_write_read_8bit(spi, &tx, &rx) < 0)
 277                                goto out;
 278                        count--;
 279                } while (count);
 280        } else if (word_len == 16) {
 281                const u16 *tx = xfer->tx_buf;
 282                u16 *rx = xfer->rx_buf;
 283
 284                do {
 285                        if (orion_spi_write_read_16bit(spi, &tx, &rx) < 0)
 286                                goto out;
 287                        count -= 2;
 288                } while (count);
 289        }
 290
 291out:
 292        return xfer->len - count;
 293}
 294
 295
 296static int orion_spi_transfer_one_message(struct spi_master *master,
 297                                           struct spi_message *m)
 298{
 299        struct orion_spi *orion_spi = spi_master_get_devdata(master);
 300        struct spi_device *spi = m->spi;
 301        struct spi_transfer *t = NULL;
 302        int par_override = 0;
 303        int status = 0;
 304        int cs_active = 0;
 305
 306        /* Load defaults */
 307        status = orion_spi_setup_transfer(spi, NULL);
 308
 309        if (status < 0)
 310                goto msg_done;
 311
 312        list_for_each_entry(t, &m->transfers, transfer_list) {
 313                /* make sure buffer length is even when working in 16
 314                 * bit mode*/
 315                if ((t->bits_per_word == 16) && (t->len & 1)) {
 316                        dev_err(&spi->dev,
 317                                "message rejected : "
 318                                "odd data length %d while in 16 bit mode\n",
 319                                t->len);
 320                        status = -EIO;
 321                        goto msg_done;
 322                }
 323
 324                if (t->speed_hz && t->speed_hz < orion_spi->min_speed) {
 325                        dev_err(&spi->dev,
 326                                "message rejected : "
 327                                "device min speed (%d Hz) exceeds "
 328                                "required transfer speed (%d Hz)\n",
 329                                orion_spi->min_speed, t->speed_hz);
 330                        status = -EIO;
 331                        goto msg_done;
 332                }
 333
 334                if (par_override || t->speed_hz || t->bits_per_word) {
 335                        par_override = 1;
 336                        status = orion_spi_setup_transfer(spi, t);
 337                        if (status < 0)
 338                                break;
 339                        if (!t->speed_hz && !t->bits_per_word)
 340                                par_override = 0;
 341                }
 342
 343                if (!cs_active) {
 344                        orion_spi_set_cs(orion_spi, 1);
 345                        cs_active = 1;
 346                }
 347
 348                if (t->len)
 349                        m->actual_length += orion_spi_write_read(spi, t);
 350
 351                if (t->delay_usecs)
 352                        udelay(t->delay_usecs);
 353
 354                if (t->cs_change) {
 355                        orion_spi_set_cs(orion_spi, 0);
 356                        cs_active = 0;
 357                }
 358        }
 359
 360msg_done:
 361        if (cs_active)
 362                orion_spi_set_cs(orion_spi, 0);
 363
 364        m->status = status;
 365        spi_finalize_current_message(master);
 366
 367        return 0;
 368}
 369
 370static int orion_spi_reset(struct orion_spi *orion_spi)
 371{
 372        /* Verify that the CS is deasserted */
 373        orion_spi_set_cs(orion_spi, 0);
 374
 375        return 0;
 376}
 377
 378static int orion_spi_setup(struct spi_device *spi)
 379{
 380        struct orion_spi *orion_spi;
 381
 382        orion_spi = spi_master_get_devdata(spi->master);
 383
 384        if ((spi->max_speed_hz == 0)
 385                        || (spi->max_speed_hz > orion_spi->max_speed))
 386                spi->max_speed_hz = orion_spi->max_speed;
 387
 388        if (spi->max_speed_hz < orion_spi->min_speed) {
 389                dev_err(&spi->dev, "setup: requested speed too low %d Hz\n",
 390                        spi->max_speed_hz);
 391                return -EINVAL;
 392        }
 393
 394        /*
 395         * baudrate & width will be set orion_spi_setup_transfer
 396         */
 397        return 0;
 398}
 399
 400static int orion_spi_probe(struct platform_device *pdev)
 401{
 402        struct spi_master *master;
 403        struct orion_spi *spi;
 404        struct resource *r;
 405        unsigned long tclk_hz;
 406        int status = 0;
 407        const u32 *iprop;
 408        int size;
 409
 410        master = spi_alloc_master(&pdev->dev, sizeof *spi);
 411        if (master == NULL) {
 412                dev_dbg(&pdev->dev, "master allocation failed\n");
 413                return -ENOMEM;
 414        }
 415
 416        if (pdev->id != -1)
 417                master->bus_num = pdev->id;
 418        if (pdev->dev.of_node) {
 419                iprop = of_get_property(pdev->dev.of_node, "cell-index",
 420                                        &size);
 421                if (iprop && size == sizeof(*iprop))
 422                        master->bus_num = *iprop;
 423        }
 424
 425        /* we support only mode 0, and no options */
 426        master->mode_bits = SPI_CPHA | SPI_CPOL;
 427
 428        master->setup = orion_spi_setup;
 429        master->transfer_one_message = orion_spi_transfer_one_message;
 430        master->num_chipselect = ORION_NUM_CHIPSELECTS;
 431
 432        platform_set_drvdata(pdev, master);
 433
 434        spi = spi_master_get_devdata(master);
 435        spi->master = master;
 436
 437        spi->clk = clk_get(&pdev->dev, NULL);
 438        if (IS_ERR(spi->clk)) {
 439                status = PTR_ERR(spi->clk);
 440                goto out;
 441        }
 442
 443        clk_prepare(spi->clk);
 444        clk_enable(spi->clk);
 445        tclk_hz = clk_get_rate(spi->clk);
 446        spi->max_speed = DIV_ROUND_UP(tclk_hz, 4);
 447        spi->min_speed = DIV_ROUND_UP(tclk_hz, 30);
 448
 449        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 450        spi->base = devm_ioremap_resource(&pdev->dev, r);
 451        if (IS_ERR(spi->base)) {
 452                status = PTR_ERR(spi->base);
 453                goto out_rel_clk;
 454        }
 455
 456        if (orion_spi_reset(spi) < 0)
 457                goto out_rel_clk;
 458
 459        master->dev.of_node = pdev->dev.of_node;
 460        status = spi_register_master(master);
 461        if (status < 0)
 462                goto out_rel_clk;
 463
 464        return status;
 465
 466out_rel_clk:
 467        clk_disable_unprepare(spi->clk);
 468        clk_put(spi->clk);
 469out:
 470        spi_master_put(master);
 471        return status;
 472}
 473
 474
 475static int orion_spi_remove(struct platform_device *pdev)
 476{
 477        struct spi_master *master;
 478        struct orion_spi *spi;
 479
 480        master = platform_get_drvdata(pdev);
 481        spi = spi_master_get_devdata(master);
 482
 483        clk_disable_unprepare(spi->clk);
 484        clk_put(spi->clk);
 485
 486        spi_unregister_master(master);
 487
 488        return 0;
 489}
 490
 491MODULE_ALIAS("platform:" DRIVER_NAME);
 492
 493static const struct of_device_id orion_spi_of_match_table[] = {
 494        { .compatible = "marvell,orion-spi", },
 495        {}
 496};
 497MODULE_DEVICE_TABLE(of, orion_spi_of_match_table);
 498
 499static struct platform_driver orion_spi_driver = {
 500        .driver = {
 501                .name   = DRIVER_NAME,
 502                .owner  = THIS_MODULE,
 503                .of_match_table = of_match_ptr(orion_spi_of_match_table),
 504        },
 505        .probe          = orion_spi_probe,
 506        .remove         = orion_spi_remove,
 507};
 508
 509module_platform_driver(orion_spi_driver);
 510
 511MODULE_DESCRIPTION("Orion SPI driver");
 512MODULE_AUTHOR("Shadi Ammouri <shadi@marvell.com>");
 513MODULE_LICENSE("GPL");
 514
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.