linux/drivers/spi/spi-sh-hspi.c
<<
>>
Prefs
   1/*
   2 * SuperH HSPI bus driver
   3 *
   4 * Copyright (C) 2011  Kuninori Morimoto
   5 *
   6 * Based on spi-sh.c:
   7 * Based on pxa2xx_spi.c:
   8 * Copyright (C) 2011 Renesas Solutions Corp.
   9 * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License as published by
  13 * the Free Software Foundation; version 2 of the License.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 */
  20
  21#include <linux/clk.h>
  22#include <linux/module.h>
  23#include <linux/kernel.h>
  24#include <linux/timer.h>
  25#include <linux/delay.h>
  26#include <linux/list.h>
  27#include <linux/interrupt.h>
  28#include <linux/platform_device.h>
  29#include <linux/pm_runtime.h>
  30#include <linux/io.h>
  31#include <linux/spi/spi.h>
  32#include <linux/spi/sh_hspi.h>
  33
  34#define SPCR    0x00
  35#define SPSR    0x04
  36#define SPSCR   0x08
  37#define SPTBR   0x0C
  38#define SPRBR   0x10
  39#define SPCR2   0x14
  40
  41/* SPSR */
  42#define RXFL    (1 << 2)
  43
  44struct hspi_priv {
  45        void __iomem *addr;
  46        struct spi_master *master;
  47        struct device *dev;
  48        struct clk *clk;
  49};
  50
  51/*
  52 *              basic function
  53 */
  54static void hspi_write(struct hspi_priv *hspi, int reg, u32 val)
  55{
  56        iowrite32(val, hspi->addr + reg);
  57}
  58
  59static u32 hspi_read(struct hspi_priv *hspi, int reg)
  60{
  61        return ioread32(hspi->addr + reg);
  62}
  63
  64static void hspi_bit_set(struct hspi_priv *hspi, int reg, u32 mask, u32 set)
  65{
  66        u32 val = hspi_read(hspi, reg);
  67
  68        val &= ~mask;
  69        val |= set & mask;
  70
  71        hspi_write(hspi, reg, val);
  72}
  73
  74/*
  75 *              transfer function
  76 */
  77static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val)
  78{
  79        int t = 256;
  80
  81        while (t--) {
  82                if ((mask & hspi_read(hspi, SPSR)) == val)
  83                        return 0;
  84
  85                udelay(10);
  86        }
  87
  88        dev_err(hspi->dev, "timeout\n");
  89        return -ETIMEDOUT;
  90}
  91
  92/*
  93 *              spi master function
  94 */
  95
  96#define hspi_hw_cs_enable(hspi)         hspi_hw_cs_ctrl(hspi, 0)
  97#define hspi_hw_cs_disable(hspi)        hspi_hw_cs_ctrl(hspi, 1)
  98static void hspi_hw_cs_ctrl(struct hspi_priv *hspi, int hi)
  99{
 100        hspi_bit_set(hspi, SPSCR, (1 << 6), (hi) << 6);
 101}
 102
 103static void hspi_hw_setup(struct hspi_priv *hspi,
 104                          struct spi_message *msg,
 105                          struct spi_transfer *t)
 106{
 107        struct spi_device *spi = msg->spi;
 108        struct device *dev = hspi->dev;
 109        u32 spcr, idiv_clk;
 110        u32 rate, best_rate, min, tmp;
 111
 112        /*
 113         * find best IDIV/CLKCx settings
 114         */
 115        min = ~0;
 116        best_rate = 0;
 117        spcr = 0;
 118        for (idiv_clk = 0x00; idiv_clk <= 0x3F; idiv_clk++) {
 119                rate = clk_get_rate(hspi->clk);
 120
 121                /* IDIV calculation */
 122                if (idiv_clk & (1 << 5))
 123                        rate /= 128;
 124                else
 125                        rate /= 16;
 126
 127                /* CLKCx calculation */
 128                rate /= (((idiv_clk & 0x1F) + 1) * 2);
 129
 130                /* save best settings */
 131                tmp = abs(t->speed_hz - rate);
 132                if (tmp < min) {
 133                        min = tmp;
 134                        spcr = idiv_clk;
 135                        best_rate = rate;
 136                }
 137        }
 138
 139        if (spi->mode & SPI_CPHA)
 140                spcr |= 1 << 7;
 141        if (spi->mode & SPI_CPOL)
 142                spcr |= 1 << 6;
 143
 144        dev_dbg(dev, "speed %d/%d\n", t->speed_hz, best_rate);
 145
 146        hspi_write(hspi, SPCR, spcr);
 147        hspi_write(hspi, SPSR, 0x0);
 148        hspi_write(hspi, SPSCR, 0x21);  /* master mode / CS control */
 149}
 150
 151static int hspi_transfer_one_message(struct spi_master *master,
 152                                     struct spi_message *msg)
 153{
 154        struct hspi_priv *hspi = spi_master_get_devdata(master);
 155        struct spi_transfer *t;
 156        u32 tx;
 157        u32 rx;
 158        int ret, i;
 159        unsigned int cs_change;
 160        const int nsecs = 50;
 161
 162        dev_dbg(hspi->dev, "%s\n", __func__);
 163
 164        cs_change = 1;
 165        ret = 0;
 166        list_for_each_entry(t, &msg->transfers, transfer_list) {
 167
 168                if (cs_change) {
 169                        hspi_hw_setup(hspi, msg, t);
 170                        hspi_hw_cs_enable(hspi);
 171                        ndelay(nsecs);
 172                }
 173                cs_change = t->cs_change;
 174
 175                for (i = 0; i < t->len; i++) {
 176
 177                        /* wait remains */
 178                        ret = hspi_status_check_timeout(hspi, 0x1, 0);
 179                        if (ret < 0)
 180                                break;
 181
 182                        tx = 0;
 183                        if (t->tx_buf)
 184                                tx = (u32)((u8 *)t->tx_buf)[i];
 185
 186                        hspi_write(hspi, SPTBR, tx);
 187
 188                        /* wait receive */
 189                        ret = hspi_status_check_timeout(hspi, 0x4, 0x4);
 190                        if (ret < 0)
 191                                break;
 192
 193                        rx = hspi_read(hspi, SPRBR);
 194                        if (t->rx_buf)
 195                                ((u8 *)t->rx_buf)[i] = (u8)rx;
 196
 197                }
 198
 199                msg->actual_length += t->len;
 200
 201                if (t->delay_usecs)
 202                        udelay(t->delay_usecs);
 203
 204                if (cs_change) {
 205                        ndelay(nsecs);
 206                        hspi_hw_cs_disable(hspi);
 207                        ndelay(nsecs);
 208                }
 209        }
 210
 211        msg->status = ret;
 212        if (!cs_change) {
 213                ndelay(nsecs);
 214                hspi_hw_cs_disable(hspi);
 215        }
 216        spi_finalize_current_message(master);
 217
 218        return ret;
 219}
 220
 221static int hspi_probe(struct platform_device *pdev)
 222{
 223        struct resource *res;
 224        struct spi_master *master;
 225        struct hspi_priv *hspi;
 226        struct clk *clk;
 227        int ret;
 228
 229        /* get base addr */
 230        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 231        if (!res) {
 232                dev_err(&pdev->dev, "invalid resource\n");
 233                return -EINVAL;
 234        }
 235
 236        master = spi_alloc_master(&pdev->dev, sizeof(*hspi));
 237        if (!master) {
 238                dev_err(&pdev->dev, "spi_alloc_master error.\n");
 239                return -ENOMEM;
 240        }
 241
 242        clk = clk_get(&pdev->dev, NULL);
 243        if (IS_ERR(clk)) {
 244                dev_err(&pdev->dev, "couldn't get clock\n");
 245                ret = -EINVAL;
 246                goto error0;
 247        }
 248
 249        hspi = spi_master_get_devdata(master);
 250        platform_set_drvdata(pdev, hspi);
 251
 252        /* init hspi */
 253        hspi->master    = master;
 254        hspi->dev       = &pdev->dev;
 255        hspi->clk       = clk;
 256        hspi->addr      = devm_ioremap(hspi->dev,
 257                                       res->start, resource_size(res));
 258        if (!hspi->addr) {
 259                dev_err(&pdev->dev, "ioremap error.\n");
 260                ret = -ENOMEM;
 261                goto error1;
 262        }
 263
 264        pm_runtime_enable(&pdev->dev);
 265
 266        master->bus_num         = pdev->id;
 267        master->mode_bits       = SPI_CPOL | SPI_CPHA;
 268        master->dev.of_node     = pdev->dev.of_node;
 269        master->auto_runtime_pm = true;
 270        master->transfer_one_message            = hspi_transfer_one_message;
 271        master->bits_per_word_mask = SPI_BPW_MASK(8);
 272
 273        ret = devm_spi_register_master(&pdev->dev, master);
 274        if (ret < 0) {
 275                dev_err(&pdev->dev, "spi_register_master error.\n");
 276                goto error2;
 277        }
 278
 279        return 0;
 280
 281 error2:
 282        pm_runtime_disable(&pdev->dev);
 283 error1:
 284        clk_put(clk);
 285 error0:
 286        spi_master_put(master);
 287
 288        return ret;
 289}
 290
 291static int hspi_remove(struct platform_device *pdev)
 292{
 293        struct hspi_priv *hspi = platform_get_drvdata(pdev);
 294
 295        pm_runtime_disable(&pdev->dev);
 296
 297        clk_put(hspi->clk);
 298
 299        return 0;
 300}
 301
 302static const struct of_device_id hspi_of_match[] = {
 303        { .compatible = "renesas,hspi", },
 304        { /* sentinel */ }
 305};
 306MODULE_DEVICE_TABLE(of, hspi_of_match);
 307
 308static struct platform_driver hspi_driver = {
 309        .probe = hspi_probe,
 310        .remove = hspi_remove,
 311        .driver = {
 312                .name = "sh-hspi",
 313                .of_match_table = hspi_of_match,
 314        },
 315};
 316module_platform_driver(hspi_driver);
 317
 318MODULE_DESCRIPTION("SuperH HSPI bus driver");
 319MODULE_LICENSE("GPL");
 320MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
 321MODULE_ALIAS("platform:sh-hspi");
 322