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