linux/drivers/spi/spi-npcm-pspi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (c) 2018 Nuvoton Technology corporation.
   3
   4#include <linux/kernel.h>
   5#include <linux/bitfield.h>
   6#include <linux/bitops.h>
   7#include <linux/clk.h>
   8#include <linux/interrupt.h>
   9#include <linux/io.h>
  10#include <linux/module.h>
  11#include <linux/platform_device.h>
  12#include <linux/spi/spi.h>
  13#include <linux/gpio.h>
  14#include <linux/of_gpio.h>
  15
  16#include <asm/unaligned.h>
  17
  18#include <linux/regmap.h>
  19#include <linux/mfd/syscon.h>
  20
  21struct npcm_pspi {
  22        struct completion xfer_done;
  23        struct regmap *rst_regmap;
  24        struct spi_master *master;
  25        unsigned int tx_bytes;
  26        unsigned int rx_bytes;
  27        void __iomem *base;
  28        bool is_save_param;
  29        u8 bits_per_word;
  30        const u8 *tx_buf;
  31        struct clk *clk;
  32        u32 speed_hz;
  33        u8 *rx_buf;
  34        u16 mode;
  35        u32 id;
  36};
  37
  38#define DRIVER_NAME "npcm-pspi"
  39
  40#define NPCM_PSPI_DATA          0x00
  41#define NPCM_PSPI_CTL1          0x02
  42#define NPCM_PSPI_STAT          0x04
  43
  44/* definitions for control and status register */
  45#define NPCM_PSPI_CTL1_SPIEN    BIT(0)
  46#define NPCM_PSPI_CTL1_MOD      BIT(2)
  47#define NPCM_PSPI_CTL1_EIR      BIT(5)
  48#define NPCM_PSPI_CTL1_EIW      BIT(6)
  49#define NPCM_PSPI_CTL1_SCM      BIT(7)
  50#define NPCM_PSPI_CTL1_SCIDL    BIT(8)
  51#define NPCM_PSPI_CTL1_SCDV6_0  GENMASK(15, 9)
  52
  53#define NPCM_PSPI_STAT_BSY      BIT(0)
  54#define NPCM_PSPI_STAT_RBF      BIT(1)
  55
  56/* general definitions */
  57#define NPCM_PSPI_TIMEOUT_MS            2000
  58#define NPCM_PSPI_MAX_CLK_DIVIDER       256
  59#define NPCM_PSPI_MIN_CLK_DIVIDER       4
  60#define NPCM_PSPI_DEFAULT_CLK           25000000
  61
  62/* reset register */
  63#define NPCM7XX_IPSRST2_OFFSET  0x24
  64
  65#define NPCM7XX_PSPI1_RESET     BIT(22)
  66#define NPCM7XX_PSPI2_RESET     BIT(23)
  67
  68static inline unsigned int bytes_per_word(unsigned int bits)
  69{
  70        return bits <= 8 ? 1 : 2;
  71}
  72
  73static inline void npcm_pspi_irq_enable(struct npcm_pspi *priv, u16 mask)
  74{
  75        u16 val;
  76
  77        val = ioread16(priv->base + NPCM_PSPI_CTL1);
  78        val |= mask;
  79        iowrite16(val, priv->base + NPCM_PSPI_CTL1);
  80}
  81
  82static inline void npcm_pspi_irq_disable(struct npcm_pspi *priv, u16 mask)
  83{
  84        u16 val;
  85
  86        val = ioread16(priv->base + NPCM_PSPI_CTL1);
  87        val &= ~mask;
  88        iowrite16(val, priv->base + NPCM_PSPI_CTL1);
  89}
  90
  91static inline void npcm_pspi_enable(struct npcm_pspi *priv)
  92{
  93        u16 val;
  94
  95        val = ioread16(priv->base + NPCM_PSPI_CTL1);
  96        val |= NPCM_PSPI_CTL1_SPIEN;
  97        iowrite16(val, priv->base + NPCM_PSPI_CTL1);
  98}
  99
 100static inline void npcm_pspi_disable(struct npcm_pspi *priv)
 101{
 102        u16 val;
 103
 104        val = ioread16(priv->base + NPCM_PSPI_CTL1);
 105        val &= ~NPCM_PSPI_CTL1_SPIEN;
 106        iowrite16(val, priv->base + NPCM_PSPI_CTL1);
 107}
 108
 109static void npcm_pspi_set_mode(struct spi_device *spi)
 110{
 111        struct npcm_pspi *priv = spi_master_get_devdata(spi->master);
 112        u16 regtemp;
 113        u16 mode_val;
 114
 115        switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
 116        case SPI_MODE_0:
 117                mode_val = 0;
 118                break;
 119        case SPI_MODE_1:
 120                mode_val = NPCM_PSPI_CTL1_SCIDL;
 121                break;
 122        case SPI_MODE_2:
 123                mode_val = NPCM_PSPI_CTL1_SCM;
 124                break;
 125        case SPI_MODE_3:
 126                mode_val = NPCM_PSPI_CTL1_SCIDL | NPCM_PSPI_CTL1_SCM;
 127                break;
 128        }
 129
 130        regtemp = ioread16(priv->base + NPCM_PSPI_CTL1);
 131        regtemp &= ~(NPCM_PSPI_CTL1_SCM | NPCM_PSPI_CTL1_SCIDL);
 132        iowrite16(regtemp | mode_val, priv->base + NPCM_PSPI_CTL1);
 133}
 134
 135static void npcm_pspi_set_transfer_size(struct npcm_pspi *priv, int size)
 136{
 137        u16 regtemp;
 138
 139        regtemp = ioread16(NPCM_PSPI_CTL1 + priv->base);
 140
 141        switch (size) {
 142        case 8:
 143                regtemp &= ~NPCM_PSPI_CTL1_MOD;
 144                break;
 145        case 16:
 146                regtemp |= NPCM_PSPI_CTL1_MOD;
 147                break;
 148        }
 149
 150        iowrite16(regtemp, NPCM_PSPI_CTL1 + priv->base);
 151}
 152
 153static void npcm_pspi_set_baudrate(struct npcm_pspi *priv, unsigned int speed)
 154{
 155        u32 ckdiv;
 156        u16 regtemp;
 157
 158        /* the supported rates are numbers from 4 to 256. */
 159        ckdiv = DIV_ROUND_CLOSEST(clk_get_rate(priv->clk), (2 * speed)) - 1;
 160
 161        regtemp = ioread16(NPCM_PSPI_CTL1 + priv->base);
 162        regtemp &= ~NPCM_PSPI_CTL1_SCDV6_0;
 163        iowrite16(regtemp | (ckdiv << 9), NPCM_PSPI_CTL1 + priv->base);
 164}
 165
 166static void npcm_pspi_setup_transfer(struct spi_device *spi,
 167                                     struct spi_transfer *t)
 168{
 169        struct npcm_pspi *priv = spi_master_get_devdata(spi->master);
 170
 171        priv->tx_buf = t->tx_buf;
 172        priv->rx_buf = t->rx_buf;
 173        priv->tx_bytes = t->len;
 174        priv->rx_bytes = t->len;
 175
 176        if (!priv->is_save_param || priv->mode != spi->mode) {
 177                npcm_pspi_set_mode(spi);
 178                priv->mode = spi->mode;
 179        }
 180
 181        if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) {
 182                npcm_pspi_set_transfer_size(priv, t->bits_per_word);
 183                priv->bits_per_word = t->bits_per_word;
 184        }
 185
 186        if (!priv->is_save_param || priv->speed_hz != t->speed_hz) {
 187                npcm_pspi_set_baudrate(priv, t->speed_hz);
 188                priv->speed_hz = t->speed_hz;
 189        }
 190
 191        if (!priv->is_save_param)
 192                priv->is_save_param = true;
 193}
 194
 195static void npcm_pspi_send(struct npcm_pspi *priv)
 196{
 197        int wsize;
 198
 199        wsize = min(bytes_per_word(priv->bits_per_word), priv->tx_bytes);
 200        priv->tx_bytes -= wsize;
 201
 202        if (!priv->tx_buf)
 203                return;
 204
 205        switch (wsize) {
 206        case 1:
 207                iowrite8(*priv->tx_buf, NPCM_PSPI_DATA + priv->base);
 208                break;
 209        case 2:
 210                iowrite16(*priv->tx_buf, NPCM_PSPI_DATA + priv->base);
 211                break;
 212        default:
 213                WARN_ON_ONCE(1);
 214                return;
 215        }
 216
 217        priv->tx_buf += wsize;
 218}
 219
 220static void npcm_pspi_recv(struct npcm_pspi *priv)
 221{
 222        int rsize;
 223        u16 val;
 224
 225        rsize = min(bytes_per_word(priv->bits_per_word), priv->rx_bytes);
 226        priv->rx_bytes -= rsize;
 227
 228        if (!priv->rx_buf)
 229                return;
 230
 231        switch (rsize) {
 232        case 1:
 233                val = ioread8(priv->base + NPCM_PSPI_DATA);
 234                break;
 235        case 2:
 236                val = ioread16(priv->base + NPCM_PSPI_DATA);
 237                break;
 238        default:
 239                WARN_ON_ONCE(1);
 240                return;
 241        }
 242
 243        *priv->rx_buf = val;
 244        priv->rx_buf += rsize;
 245}
 246
 247static int npcm_pspi_transfer_one(struct spi_master *master,
 248                                  struct spi_device *spi,
 249                                  struct spi_transfer *t)
 250{
 251        struct npcm_pspi *priv = spi_master_get_devdata(master);
 252        int status;
 253
 254        npcm_pspi_setup_transfer(spi, t);
 255        reinit_completion(&priv->xfer_done);
 256        npcm_pspi_enable(priv);
 257        status = wait_for_completion_timeout(&priv->xfer_done,
 258                                             msecs_to_jiffies
 259                                             (NPCM_PSPI_TIMEOUT_MS));
 260        if (status == 0) {
 261                npcm_pspi_disable(priv);
 262                return -ETIMEDOUT;
 263        }
 264
 265        return 0;
 266}
 267
 268static int npcm_pspi_prepare_transfer_hardware(struct spi_master *master)
 269{
 270        struct npcm_pspi *priv = spi_master_get_devdata(master);
 271
 272        npcm_pspi_irq_enable(priv, NPCM_PSPI_CTL1_EIR | NPCM_PSPI_CTL1_EIW);
 273
 274        return 0;
 275}
 276
 277static int npcm_pspi_unprepare_transfer_hardware(struct spi_master *master)
 278{
 279        struct npcm_pspi *priv = spi_master_get_devdata(master);
 280
 281        npcm_pspi_irq_disable(priv, NPCM_PSPI_CTL1_EIR | NPCM_PSPI_CTL1_EIW);
 282
 283        return 0;
 284}
 285
 286static void npcm_pspi_reset_hw(struct npcm_pspi *priv)
 287{
 288        regmap_write(priv->rst_regmap, NPCM7XX_IPSRST2_OFFSET,
 289                     NPCM7XX_PSPI1_RESET << priv->id);
 290        regmap_write(priv->rst_regmap, NPCM7XX_IPSRST2_OFFSET, 0x0);
 291}
 292
 293static irqreturn_t npcm_pspi_handler(int irq, void *dev_id)
 294{
 295        struct npcm_pspi *priv = dev_id;
 296        u16 val;
 297        u8 stat;
 298
 299        stat = ioread8(priv->base + NPCM_PSPI_STAT);
 300
 301        if (!priv->tx_buf && !priv->rx_buf)
 302                return IRQ_NONE;
 303
 304        if (priv->tx_buf) {
 305                if (stat & NPCM_PSPI_STAT_RBF) {
 306                        val = ioread8(NPCM_PSPI_DATA + priv->base);
 307                        if (priv->tx_bytes == 0) {
 308                                npcm_pspi_disable(priv);
 309                                complete(&priv->xfer_done);
 310                                return IRQ_HANDLED;
 311                        }
 312                }
 313
 314                if ((stat & NPCM_PSPI_STAT_BSY) == 0)
 315                        if (priv->tx_bytes)
 316                                npcm_pspi_send(priv);
 317        }
 318
 319        if (priv->rx_buf) {
 320                if (stat & NPCM_PSPI_STAT_RBF) {
 321                        if (!priv->rx_bytes)
 322                                return IRQ_NONE;
 323
 324                        npcm_pspi_recv(priv);
 325
 326                        if (!priv->rx_bytes) {
 327                                npcm_pspi_disable(priv);
 328                                complete(&priv->xfer_done);
 329                                return IRQ_HANDLED;
 330                        }
 331                }
 332
 333                if (((stat & NPCM_PSPI_STAT_BSY) == 0) && !priv->tx_buf)
 334                        iowrite8(0x0, NPCM_PSPI_DATA + priv->base);
 335        }
 336
 337        return IRQ_HANDLED;
 338}
 339
 340static int npcm_pspi_probe(struct platform_device *pdev)
 341{
 342        struct npcm_pspi *priv;
 343        struct spi_master *master;
 344        struct resource *res;
 345        unsigned long clk_hz;
 346        struct device_node *np = pdev->dev.of_node;
 347        int num_cs, i;
 348        int csgpio;
 349        int irq;
 350        int ret;
 351
 352        num_cs = of_gpio_named_count(np, "cs-gpios");
 353        if (num_cs < 0)
 354                return num_cs;
 355
 356        pdev->id = of_alias_get_id(np, "spi");
 357        if (pdev->id < 0)
 358                pdev->id = 0;
 359
 360        master = spi_alloc_master(&pdev->dev, sizeof(*priv));
 361        if (!master)
 362                return -ENOMEM;
 363
 364        platform_set_drvdata(pdev, master);
 365
 366        priv = spi_master_get_devdata(master);
 367        priv->master = master;
 368        priv->is_save_param = false;
 369        priv->id = pdev->id;
 370
 371        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 372        priv->base = devm_ioremap_resource(&pdev->dev, res);
 373        if (IS_ERR(priv->base)) {
 374                ret = PTR_ERR(priv->base);
 375                goto out_master_put;
 376        }
 377
 378        priv->clk = devm_clk_get(&pdev->dev, NULL);
 379        if (IS_ERR(priv->clk)) {
 380                dev_err(&pdev->dev, "failed to get clock\n");
 381                ret = PTR_ERR(priv->clk);
 382                goto out_master_put;
 383        }
 384
 385        ret = clk_prepare_enable(priv->clk);
 386        if (ret)
 387                goto out_master_put;
 388
 389        irq = platform_get_irq(pdev, 0);
 390        if (irq < 0) {
 391                dev_err(&pdev->dev, "failed to get IRQ\n");
 392                ret = irq;
 393                goto out_disable_clk;
 394        }
 395
 396        priv->rst_regmap =
 397                syscon_regmap_lookup_by_compatible("nuvoton,npcm750-rst");
 398        if (IS_ERR(priv->rst_regmap)) {
 399                dev_err(&pdev->dev, "failed to find nuvoton,npcm750-rst\n");
 400                return PTR_ERR(priv->rst_regmap);
 401        }
 402
 403        /* reset SPI-HW block */
 404        npcm_pspi_reset_hw(priv);
 405
 406        ret = devm_request_irq(&pdev->dev, irq, npcm_pspi_handler, 0,
 407                               "npcm-pspi", priv);
 408        if (ret) {
 409                dev_err(&pdev->dev, "failed to request IRQ\n");
 410                goto out_disable_clk;
 411        }
 412
 413        init_completion(&priv->xfer_done);
 414
 415        clk_hz = clk_get_rate(priv->clk);
 416
 417        master->max_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MIN_CLK_DIVIDER);
 418        master->min_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MAX_CLK_DIVIDER);
 419        master->mode_bits = SPI_CPHA | SPI_CPOL;
 420        master->dev.of_node = pdev->dev.of_node;
 421        master->bus_num = pdev->id;
 422        master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
 423        master->transfer_one = npcm_pspi_transfer_one;
 424        master->prepare_transfer_hardware =
 425                npcm_pspi_prepare_transfer_hardware;
 426        master->unprepare_transfer_hardware =
 427                npcm_pspi_unprepare_transfer_hardware;
 428        master->num_chipselect = num_cs;
 429
 430        for (i = 0; i < num_cs; i++) {
 431                csgpio = of_get_named_gpio(np, "cs-gpios", i);
 432                if (csgpio < 0) {
 433                        dev_err(&pdev->dev, "failed to get csgpio#%u\n", i);
 434                        goto out_disable_clk;
 435                }
 436                dev_dbg(&pdev->dev, "csgpio#%u = %d\n", i, csgpio);
 437                ret = devm_gpio_request_one(&pdev->dev, csgpio,
 438                                            GPIOF_OUT_INIT_HIGH, DRIVER_NAME);
 439                if (ret < 0) {
 440                        dev_err(&pdev->dev,
 441                                "failed to configure csgpio#%u %d\n"
 442                                , i, csgpio);
 443                        goto out_disable_clk;
 444                }
 445        }
 446
 447        /* set to default clock rate */
 448        npcm_pspi_set_baudrate(priv, NPCM_PSPI_DEFAULT_CLK);
 449
 450        ret = devm_spi_register_master(&pdev->dev, master);
 451        if (ret)
 452                goto out_disable_clk;
 453
 454        pr_info("NPCM Peripheral SPI %d probed\n", pdev->id);
 455
 456        return 0;
 457
 458out_disable_clk:
 459        clk_disable_unprepare(priv->clk);
 460
 461out_master_put:
 462        spi_master_put(master);
 463        return ret;
 464}
 465
 466static int npcm_pspi_remove(struct platform_device *pdev)
 467{
 468        struct spi_master *master = platform_get_drvdata(pdev);
 469        struct npcm_pspi *priv = spi_master_get_devdata(master);
 470
 471        npcm_pspi_reset_hw(priv);
 472        clk_disable_unprepare(priv->clk);
 473
 474        return 0;
 475}
 476
 477static const struct of_device_id npcm_pspi_match[] = {
 478        { .compatible = "nuvoton,npcm750-pspi", .data = NULL },
 479        {}
 480};
 481MODULE_DEVICE_TABLE(of, npcm_pspi_match);
 482
 483static struct platform_driver npcm_pspi_driver = {
 484        .driver         = {
 485                .name           = DRIVER_NAME,
 486                .of_match_table = npcm_pspi_match,
 487        },
 488        .probe          = npcm_pspi_probe,
 489        .remove         = npcm_pspi_remove,
 490};
 491module_platform_driver(npcm_pspi_driver);
 492
 493MODULE_DESCRIPTION("NPCM peripheral SPI Controller driver");
 494MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
 495MODULE_LICENSE("GPL v2");
 496
 497