linux/drivers/spi/spi-fsl-lpspi.c
<<
>>
Prefs
   1/*
   2 * Freescale i.MX7ULP LPSPI driver
   3 *
   4 * Copyright 2016 Freescale Semiconductor, Inc.
   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 */
  17
  18#include <linux/clk.h>
  19#include <linux/completion.h>
  20#include <linux/delay.h>
  21#include <linux/err.h>
  22#include <linux/interrupt.h>
  23#include <linux/io.h>
  24#include <linux/irq.h>
  25#include <linux/kernel.h>
  26#include <linux/module.h>
  27#include <linux/of.h>
  28#include <linux/of_device.h>
  29#include <linux/platform_device.h>
  30#include <linux/slab.h>
  31#include <linux/spi/spi.h>
  32#include <linux/spi/spi_bitbang.h>
  33#include <linux/types.h>
  34
  35#define DRIVER_NAME "fsl_lpspi"
  36
  37/* i.MX7ULP LPSPI registers */
  38#define IMX7ULP_VERID   0x0
  39#define IMX7ULP_PARAM   0x4
  40#define IMX7ULP_CR      0x10
  41#define IMX7ULP_SR      0x14
  42#define IMX7ULP_IER     0x18
  43#define IMX7ULP_DER     0x1c
  44#define IMX7ULP_CFGR0   0x20
  45#define IMX7ULP_CFGR1   0x24
  46#define IMX7ULP_DMR0    0x30
  47#define IMX7ULP_DMR1    0x34
  48#define IMX7ULP_CCR     0x40
  49#define IMX7ULP_FCR     0x58
  50#define IMX7ULP_FSR     0x5c
  51#define IMX7ULP_TCR     0x60
  52#define IMX7ULP_TDR     0x64
  53#define IMX7ULP_RSR     0x70
  54#define IMX7ULP_RDR     0x74
  55
  56/* General control register field define */
  57#define CR_RRF          BIT(9)
  58#define CR_RTF          BIT(8)
  59#define CR_RST          BIT(1)
  60#define CR_MEN          BIT(0)
  61#define SR_TCF          BIT(10)
  62#define SR_RDF          BIT(1)
  63#define SR_TDF          BIT(0)
  64#define IER_TCIE        BIT(10)
  65#define IER_RDIE        BIT(1)
  66#define IER_TDIE        BIT(0)
  67#define CFGR1_PCSCFG    BIT(27)
  68#define CFGR1_PCSPOL    BIT(8)
  69#define CFGR1_NOSTALL   BIT(3)
  70#define CFGR1_MASTER    BIT(0)
  71#define RSR_RXEMPTY     BIT(1)
  72#define TCR_CPOL        BIT(31)
  73#define TCR_CPHA        BIT(30)
  74#define TCR_CONT        BIT(21)
  75#define TCR_CONTC       BIT(20)
  76#define TCR_RXMSK       BIT(19)
  77#define TCR_TXMSK       BIT(18)
  78
  79static int clkdivs[] = {1, 2, 4, 8, 16, 32, 64, 128};
  80
  81struct lpspi_config {
  82        u8 bpw;
  83        u8 chip_select;
  84        u8 prescale;
  85        u16 mode;
  86        u32 speed_hz;
  87};
  88
  89struct fsl_lpspi_data {
  90        struct device *dev;
  91        void __iomem *base;
  92        struct clk *clk;
  93
  94        void *rx_buf;
  95        const void *tx_buf;
  96        void (*tx)(struct fsl_lpspi_data *);
  97        void (*rx)(struct fsl_lpspi_data *);
  98
  99        u32 remain;
 100        u8 txfifosize;
 101        u8 rxfifosize;
 102
 103        struct lpspi_config config;
 104        struct completion xfer_done;
 105};
 106
 107static const struct of_device_id fsl_lpspi_dt_ids[] = {
 108        { .compatible = "fsl,imx7ulp-spi", },
 109        { /* sentinel */ }
 110};
 111MODULE_DEVICE_TABLE(of, fsl_lpspi_dt_ids);
 112
 113#define LPSPI_BUF_RX(type)                                              \
 114static void fsl_lpspi_buf_rx_##type(struct fsl_lpspi_data *fsl_lpspi)   \
 115{                                                                       \
 116        unsigned int val = readl(fsl_lpspi->base + IMX7ULP_RDR);        \
 117                                                                        \
 118        if (fsl_lpspi->rx_buf) {                                        \
 119                *(type *)fsl_lpspi->rx_buf = val;                       \
 120                fsl_lpspi->rx_buf += sizeof(type);                      \
 121        }                                                               \
 122}
 123
 124#define LPSPI_BUF_TX(type)                                              \
 125static void fsl_lpspi_buf_tx_##type(struct fsl_lpspi_data *fsl_lpspi)   \
 126{                                                                       \
 127        type val = 0;                                                   \
 128                                                                        \
 129        if (fsl_lpspi->tx_buf) {                                        \
 130                val = *(type *)fsl_lpspi->tx_buf;                       \
 131                fsl_lpspi->tx_buf += sizeof(type);                      \
 132        }                                                               \
 133                                                                        \
 134        fsl_lpspi->remain -= sizeof(type);                              \
 135        writel(val, fsl_lpspi->base + IMX7ULP_TDR);                     \
 136}
 137
 138LPSPI_BUF_RX(u8)
 139LPSPI_BUF_TX(u8)
 140LPSPI_BUF_RX(u16)
 141LPSPI_BUF_TX(u16)
 142LPSPI_BUF_RX(u32)
 143LPSPI_BUF_TX(u32)
 144
 145static void fsl_lpspi_intctrl(struct fsl_lpspi_data *fsl_lpspi,
 146                              unsigned int enable)
 147{
 148        writel(enable, fsl_lpspi->base + IMX7ULP_IER);
 149}
 150
 151static int lpspi_prepare_xfer_hardware(struct spi_master *master)
 152{
 153        struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master);
 154
 155        return clk_prepare_enable(fsl_lpspi->clk);
 156}
 157
 158static int lpspi_unprepare_xfer_hardware(struct spi_master *master)
 159{
 160        struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master);
 161
 162        clk_disable_unprepare(fsl_lpspi->clk);
 163
 164        return 0;
 165}
 166
 167static int fsl_lpspi_txfifo_empty(struct fsl_lpspi_data *fsl_lpspi)
 168{
 169        u32 txcnt;
 170        unsigned long orig_jiffies = jiffies;
 171
 172        do {
 173                txcnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff;
 174
 175                if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
 176                        dev_dbg(fsl_lpspi->dev, "txfifo empty timeout\n");
 177                        return -ETIMEDOUT;
 178                }
 179                cond_resched();
 180
 181        } while (txcnt);
 182
 183        return 0;
 184}
 185
 186static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi)
 187{
 188        u8 txfifo_cnt;
 189
 190        txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff;
 191
 192        while (txfifo_cnt < fsl_lpspi->txfifosize) {
 193                if (!fsl_lpspi->remain)
 194                        break;
 195                fsl_lpspi->tx(fsl_lpspi);
 196                txfifo_cnt++;
 197        }
 198
 199        if (!fsl_lpspi->remain && (txfifo_cnt < fsl_lpspi->txfifosize))
 200                writel(0, fsl_lpspi->base + IMX7ULP_TDR);
 201        else
 202                fsl_lpspi_intctrl(fsl_lpspi, IER_TDIE);
 203}
 204
 205static void fsl_lpspi_read_rx_fifo(struct fsl_lpspi_data *fsl_lpspi)
 206{
 207        while (!(readl(fsl_lpspi->base + IMX7ULP_RSR) & RSR_RXEMPTY))
 208                fsl_lpspi->rx(fsl_lpspi);
 209}
 210
 211static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi,
 212                              bool is_first_xfer)
 213{
 214        u32 temp = 0;
 215
 216        temp |= fsl_lpspi->config.bpw - 1;
 217        temp |= fsl_lpspi->config.prescale << 27;
 218        temp |= (fsl_lpspi->config.mode & 0x3) << 30;
 219        temp |= (fsl_lpspi->config.chip_select & 0x3) << 24;
 220
 221        /*
 222         * Set TCR_CONT will keep SS asserted after current transfer.
 223         * For the first transfer, clear TCR_CONTC to assert SS.
 224         * For subsequent transfer, set TCR_CONTC to keep SS asserted.
 225         */
 226        temp |= TCR_CONT;
 227        if (is_first_xfer)
 228                temp &= ~TCR_CONTC;
 229        else
 230                temp |= TCR_CONTC;
 231
 232        writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
 233
 234        dev_dbg(fsl_lpspi->dev, "TCR=0x%x\n", temp);
 235}
 236
 237static void fsl_lpspi_set_watermark(struct fsl_lpspi_data *fsl_lpspi)
 238{
 239        u32 temp;
 240
 241        temp = fsl_lpspi->txfifosize >> 1 | (fsl_lpspi->rxfifosize >> 1) << 16;
 242
 243        writel(temp, fsl_lpspi->base + IMX7ULP_FCR);
 244
 245        dev_dbg(fsl_lpspi->dev, "FCR=0x%x\n", temp);
 246}
 247
 248static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
 249{
 250        struct lpspi_config config = fsl_lpspi->config;
 251        unsigned int perclk_rate, scldiv;
 252        u8 prescale;
 253
 254        perclk_rate = clk_get_rate(fsl_lpspi->clk);
 255        for (prescale = 0; prescale < 8; prescale++) {
 256                scldiv = perclk_rate /
 257                         (clkdivs[prescale] * config.speed_hz) - 2;
 258                if (scldiv < 256) {
 259                        fsl_lpspi->config.prescale = prescale;
 260                        break;
 261                }
 262        }
 263
 264        if (prescale == 8 && scldiv >= 256)
 265                return -EINVAL;
 266
 267        writel(scldiv, fsl_lpspi->base + IMX7ULP_CCR);
 268
 269        dev_dbg(fsl_lpspi->dev, "perclk=%d, speed=%d, prescale =%d, scldiv=%d\n",
 270                perclk_rate, config.speed_hz, prescale, scldiv);
 271
 272        return 0;
 273}
 274
 275static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi)
 276{
 277        u32 temp;
 278        int ret;
 279
 280        temp = CR_RST;
 281        writel(temp, fsl_lpspi->base + IMX7ULP_CR);
 282        writel(0, fsl_lpspi->base + IMX7ULP_CR);
 283
 284        ret = fsl_lpspi_set_bitrate(fsl_lpspi);
 285        if (ret)
 286                return ret;
 287
 288        fsl_lpspi_set_watermark(fsl_lpspi);
 289
 290        temp = CFGR1_PCSCFG | CFGR1_MASTER | CFGR1_NOSTALL;
 291        if (fsl_lpspi->config.mode & SPI_CS_HIGH)
 292                temp |= CFGR1_PCSPOL;
 293        writel(temp, fsl_lpspi->base + IMX7ULP_CFGR1);
 294
 295        temp = readl(fsl_lpspi->base + IMX7ULP_CR);
 296        temp |= CR_RRF | CR_RTF | CR_MEN;
 297        writel(temp, fsl_lpspi->base + IMX7ULP_CR);
 298
 299        return 0;
 300}
 301
 302static void fsl_lpspi_setup_transfer(struct spi_device *spi,
 303                                     struct spi_transfer *t)
 304{
 305        struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(spi->master);
 306
 307        fsl_lpspi->config.mode = spi->mode;
 308        fsl_lpspi->config.bpw = t ? t->bits_per_word : spi->bits_per_word;
 309        fsl_lpspi->config.speed_hz = t ? t->speed_hz : spi->max_speed_hz;
 310        fsl_lpspi->config.chip_select = spi->chip_select;
 311
 312        if (!fsl_lpspi->config.speed_hz)
 313                fsl_lpspi->config.speed_hz = spi->max_speed_hz;
 314        if (!fsl_lpspi->config.bpw)
 315                fsl_lpspi->config.bpw = spi->bits_per_word;
 316
 317        /* Initialize the functions for transfer */
 318        if (fsl_lpspi->config.bpw <= 8) {
 319                fsl_lpspi->rx = fsl_lpspi_buf_rx_u8;
 320                fsl_lpspi->tx = fsl_lpspi_buf_tx_u8;
 321        } else if (fsl_lpspi->config.bpw <= 16) {
 322                fsl_lpspi->rx = fsl_lpspi_buf_rx_u16;
 323                fsl_lpspi->tx = fsl_lpspi_buf_tx_u16;
 324        } else {
 325                fsl_lpspi->rx = fsl_lpspi_buf_rx_u32;
 326                fsl_lpspi->tx = fsl_lpspi_buf_tx_u32;
 327        }
 328
 329        fsl_lpspi_config(fsl_lpspi);
 330}
 331
 332static int fsl_lpspi_transfer_one(struct spi_master *master,
 333                                  struct spi_device *spi,
 334                                  struct spi_transfer *t)
 335{
 336        struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master);
 337        int ret;
 338
 339        fsl_lpspi->tx_buf = t->tx_buf;
 340        fsl_lpspi->rx_buf = t->rx_buf;
 341        fsl_lpspi->remain = t->len;
 342
 343        reinit_completion(&fsl_lpspi->xfer_done);
 344        fsl_lpspi_write_tx_fifo(fsl_lpspi);
 345
 346        ret = wait_for_completion_timeout(&fsl_lpspi->xfer_done, HZ);
 347        if (!ret) {
 348                dev_dbg(fsl_lpspi->dev, "wait for completion timeout\n");
 349                return -ETIMEDOUT;
 350        }
 351
 352        ret = fsl_lpspi_txfifo_empty(fsl_lpspi);
 353        if (ret)
 354                return ret;
 355
 356        fsl_lpspi_read_rx_fifo(fsl_lpspi);
 357
 358        return 0;
 359}
 360
 361static int fsl_lpspi_transfer_one_msg(struct spi_master *master,
 362                                      struct spi_message *msg)
 363{
 364        struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master);
 365        struct spi_device *spi = msg->spi;
 366        struct spi_transfer *xfer;
 367        bool is_first_xfer = true;
 368        u32 temp;
 369        int ret = 0;
 370
 371        msg->status = 0;
 372        msg->actual_length = 0;
 373
 374        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 375                fsl_lpspi_setup_transfer(spi, xfer);
 376                fsl_lpspi_set_cmd(fsl_lpspi, is_first_xfer);
 377
 378                is_first_xfer = false;
 379
 380                ret = fsl_lpspi_transfer_one(master, spi, xfer);
 381                if (ret < 0)
 382                        goto complete;
 383
 384                msg->actual_length += xfer->len;
 385        }
 386
 387complete:
 388        /* de-assert SS, then finalize current message */
 389        temp = readl(fsl_lpspi->base + IMX7ULP_TCR);
 390        temp &= ~TCR_CONTC;
 391        writel(temp, fsl_lpspi->base + IMX7ULP_TCR);
 392
 393        msg->status = ret;
 394        spi_finalize_current_message(master);
 395
 396        return ret;
 397}
 398
 399static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id)
 400{
 401        struct fsl_lpspi_data *fsl_lpspi = dev_id;
 402        u32 temp;
 403
 404        fsl_lpspi_intctrl(fsl_lpspi, 0);
 405        temp = readl(fsl_lpspi->base + IMX7ULP_SR);
 406
 407        fsl_lpspi_read_rx_fifo(fsl_lpspi);
 408
 409        if (temp & SR_TDF) {
 410                fsl_lpspi_write_tx_fifo(fsl_lpspi);
 411
 412                if (!fsl_lpspi->remain)
 413                        complete(&fsl_lpspi->xfer_done);
 414
 415                return IRQ_HANDLED;
 416        }
 417
 418        return IRQ_NONE;
 419}
 420
 421static int fsl_lpspi_probe(struct platform_device *pdev)
 422{
 423        struct fsl_lpspi_data *fsl_lpspi;
 424        struct spi_master *master;
 425        struct resource *res;
 426        int ret, irq;
 427        u32 temp;
 428
 429        master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_lpspi_data));
 430        if (!master)
 431                return -ENOMEM;
 432
 433        platform_set_drvdata(pdev, master);
 434
 435        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
 436        master->bus_num = pdev->id;
 437
 438        fsl_lpspi = spi_master_get_devdata(master);
 439        fsl_lpspi->dev = &pdev->dev;
 440
 441        master->transfer_one_message = fsl_lpspi_transfer_one_msg;
 442        master->prepare_transfer_hardware = lpspi_prepare_xfer_hardware;
 443        master->unprepare_transfer_hardware = lpspi_unprepare_xfer_hardware;
 444        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 445        master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX;
 446        master->dev.of_node = pdev->dev.of_node;
 447        master->bus_num = pdev->id;
 448
 449        init_completion(&fsl_lpspi->xfer_done);
 450
 451        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 452        fsl_lpspi->base = devm_ioremap_resource(&pdev->dev, res);
 453        if (IS_ERR(fsl_lpspi->base)) {
 454                ret = PTR_ERR(fsl_lpspi->base);
 455                goto out_master_put;
 456        }
 457
 458        irq = platform_get_irq(pdev, 0);
 459        if (irq < 0) {
 460                ret = irq;
 461                goto out_master_put;
 462        }
 463
 464        ret = devm_request_irq(&pdev->dev, irq, fsl_lpspi_isr, 0,
 465                               dev_name(&pdev->dev), fsl_lpspi);
 466        if (ret) {
 467                dev_err(&pdev->dev, "can't get irq%d: %d\n", irq, ret);
 468                goto out_master_put;
 469        }
 470
 471        fsl_lpspi->clk = devm_clk_get(&pdev->dev, "ipg");
 472        if (IS_ERR(fsl_lpspi->clk)) {
 473                ret = PTR_ERR(fsl_lpspi->clk);
 474                goto out_master_put;
 475        }
 476
 477        ret = clk_prepare_enable(fsl_lpspi->clk);
 478        if (ret) {
 479                dev_err(&pdev->dev, "can't enable lpspi clock, ret=%d\n", ret);
 480                goto out_master_put;
 481        }
 482
 483        temp = readl(fsl_lpspi->base + IMX7ULP_PARAM);
 484        fsl_lpspi->txfifosize = 1 << (temp & 0x0f);
 485        fsl_lpspi->rxfifosize = 1 << ((temp >> 8) & 0x0f);
 486
 487        clk_disable_unprepare(fsl_lpspi->clk);
 488
 489        ret = devm_spi_register_master(&pdev->dev, master);
 490        if (ret < 0) {
 491                dev_err(&pdev->dev, "spi_register_master error.\n");
 492                goto out_master_put;
 493        }
 494
 495        return 0;
 496
 497out_master_put:
 498        spi_master_put(master);
 499
 500        return ret;
 501}
 502
 503static int fsl_lpspi_remove(struct platform_device *pdev)
 504{
 505        struct spi_master *master = platform_get_drvdata(pdev);
 506        struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(master);
 507
 508        clk_disable_unprepare(fsl_lpspi->clk);
 509
 510        return 0;
 511}
 512
 513static struct platform_driver fsl_lpspi_driver = {
 514        .driver = {
 515                .name = DRIVER_NAME,
 516                .of_match_table = fsl_lpspi_dt_ids,
 517        },
 518        .probe = fsl_lpspi_probe,
 519        .remove = fsl_lpspi_remove,
 520};
 521module_platform_driver(fsl_lpspi_driver);
 522
 523MODULE_DESCRIPTION("LPSPI Master Controller driver");
 524MODULE_AUTHOR("Gao Pan <pandy.gao@nxp.com>");
 525MODULE_LICENSE("GPL");
 526