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 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  23 *
  24 */
  25
  26#include <linux/clk.h>
  27#include <linux/module.h>
  28#include <linux/kernel.h>
  29#include <linux/timer.h>
  30#include <linux/delay.h>
  31#include <linux/list.h>
  32#include <linux/interrupt.h>
  33#include <linux/platform_device.h>
  34#include <linux/pm_runtime.h>
  35#include <linux/io.h>
  36#include <linux/spi/spi.h>
  37#include <linux/spi/sh_hspi.h>
  38
  39#define SPCR    0x00
  40#define SPSR    0x04
  41#define SPSCR   0x08
  42#define SPTBR   0x0C
  43#define SPRBR   0x10
  44#define SPCR2   0x14
  45
  46/* SPSR */
  47#define RXFL    (1 << 2)
  48
  49#define hspi2info(h)    (h->dev->platform_data)
  50
  51struct hspi_priv {
  52        void __iomem *addr;
  53        struct spi_master *master;
  54        struct device *dev;
  55        struct clk *clk;
  56};
  57
  58/*
  59 *              basic function
  60 */
  61static void hspi_write(struct hspi_priv *hspi, int reg, u32 val)
  62{
  63        iowrite32(val, hspi->addr + reg);
  64}
  65
  66static u32 hspi_read(struct hspi_priv *hspi, int reg)
  67{
  68        return ioread32(hspi->addr + reg);
  69}
  70
  71/*
  72 *              transfer function
  73 */
  74static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val)
  75{
  76        int t = 256;
  77
  78        while (t--) {
  79                if ((mask & hspi_read(hspi, SPSR)) == val)
  80                        return 0;
  81
  82                msleep(20);
  83        }
  84
  85        dev_err(hspi->dev, "timeout\n");
  86        return -ETIMEDOUT;
  87}
  88
  89/*
  90 *              spi master function
  91 */
  92static int hspi_prepare_transfer(struct spi_master *master)
  93{
  94        struct hspi_priv *hspi = spi_master_get_devdata(master);
  95
  96        pm_runtime_get_sync(hspi->dev);
  97        return 0;
  98}
  99
 100static int hspi_unprepare_transfer(struct spi_master *master)
 101{
 102        struct hspi_priv *hspi = spi_master_get_devdata(master);
 103
 104        pm_runtime_put_sync(hspi->dev);
 105        return 0;
 106}
 107
 108static void hspi_hw_setup(struct hspi_priv *hspi,
 109                          struct spi_message *msg,
 110                          struct spi_transfer *t)
 111{
 112        struct spi_device *spi = msg->spi;
 113        struct device *dev = hspi->dev;
 114        u32 target_rate;
 115        u32 spcr, idiv_clk;
 116        u32 rate, best_rate, min, tmp;
 117
 118        target_rate = t ? t->speed_hz : 0;
 119        if (!target_rate)
 120                target_rate = spi->max_speed_hz;
 121
 122        /*
 123         * find best IDIV/CLKCx settings
 124         */
 125        min = ~0;
 126        best_rate = 0;
 127        spcr = 0;
 128        for (idiv_clk = 0x00; idiv_clk <= 0x3F; idiv_clk++) {
 129                rate = clk_get_rate(hspi->clk);
 130
 131                /* IDIV calculation */
 132                if (idiv_clk & (1 << 5))
 133                        rate /= 128;
 134                else
 135                        rate /= 16;
 136
 137                /* CLKCx calculation */
 138                rate /= (((idiv_clk & 0x1F) + 1) * 2) ;
 139
 140                /* save best settings */
 141                tmp = abs(target_rate - rate);
 142                if (tmp < min) {
 143                        min = tmp;
 144                        spcr = idiv_clk;
 145                        best_rate = rate;
 146                }
 147        }
 148
 149        if (spi->mode & SPI_CPHA)
 150                spcr |= 1 << 7;
 151        if (spi->mode & SPI_CPOL)
 152                spcr |= 1 << 6;
 153
 154        dev_dbg(dev, "speed %d/%d\n", target_rate, best_rate);
 155
 156        hspi_write(hspi, SPCR, spcr);
 157        hspi_write(hspi, SPSR, 0x0);
 158        hspi_write(hspi, SPSCR, 0x1);   /* master mode */
 159}
 160
 161static int hspi_transfer_one_message(struct spi_master *master,
 162                                     struct spi_message *msg)
 163{
 164        struct hspi_priv *hspi = spi_master_get_devdata(master);
 165        struct spi_transfer *t;
 166        u32 tx;
 167        u32 rx;
 168        int ret, i;
 169
 170        dev_dbg(hspi->dev, "%s\n", __func__);
 171
 172        ret = 0;
 173        list_for_each_entry(t, &msg->transfers, transfer_list) {
 174                hspi_hw_setup(hspi, msg, t);
 175
 176                for (i = 0; i < t->len; i++) {
 177
 178                        /* wait remains */
 179                        ret = hspi_status_check_timeout(hspi, 0x1, 0);
 180                        if (ret < 0)
 181                                break;
 182
 183                        tx = 0;
 184                        if (t->tx_buf)
 185                                tx = (u32)((u8 *)t->tx_buf)[i];
 186
 187                        hspi_write(hspi, SPTBR, tx);
 188
 189                        /* wait recive */
 190                        ret = hspi_status_check_timeout(hspi, 0x4, 0x4);
 191                        if (ret < 0)
 192                                break;
 193
 194                        rx = hspi_read(hspi, SPRBR);
 195                        if (t->rx_buf)
 196                                ((u8 *)t->rx_buf)[i] = (u8)rx;
 197
 198                }
 199
 200                msg->actual_length += t->len;
 201        }
 202
 203        msg->status = ret;
 204        spi_finalize_current_message(master);
 205
 206        return ret;
 207}
 208
 209static int hspi_setup(struct spi_device *spi)
 210{
 211        struct hspi_priv *hspi = spi_master_get_devdata(spi->master);
 212        struct device *dev = hspi->dev;
 213
 214        if (8 != spi->bits_per_word) {
 215                dev_err(dev, "bits_per_word should be 8\n");
 216                return -EIO;
 217        }
 218
 219        dev_dbg(dev, "%s setup\n", spi->modalias);
 220
 221        return 0;
 222}
 223
 224static void hspi_cleanup(struct spi_device *spi)
 225{
 226        struct hspi_priv *hspi = spi_master_get_devdata(spi->master);
 227        struct device *dev = hspi->dev;
 228
 229        dev_dbg(dev, "%s cleanup\n", spi->modalias);
 230}
 231
 232static int __devinit hspi_probe(struct platform_device *pdev)
 233{
 234        struct resource *res;
 235        struct spi_master *master;
 236        struct hspi_priv *hspi;
 237        struct clk *clk;
 238        int ret;
 239
 240        /* get base addr */
 241        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 242        if (!res) {
 243                dev_err(&pdev->dev, "invalid resource\n");
 244                return -EINVAL;
 245        }
 246
 247        master = spi_alloc_master(&pdev->dev, sizeof(*hspi));
 248        if (!master) {
 249                dev_err(&pdev->dev, "spi_alloc_master error.\n");
 250                return -ENOMEM;
 251        }
 252
 253        clk = clk_get(NULL, "shyway_clk");
 254        if (!clk) {
 255                dev_err(&pdev->dev, "shyway_clk is required\n");
 256                ret = -EINVAL;
 257                goto error0;
 258        }
 259
 260        hspi = spi_master_get_devdata(master);
 261        dev_set_drvdata(&pdev->dev, hspi);
 262
 263        /* init hspi */
 264        hspi->master    = master;
 265        hspi->dev       = &pdev->dev;
 266        hspi->clk       = clk;
 267        hspi->addr      = devm_ioremap(hspi->dev,
 268                                       res->start, resource_size(res));
 269        if (!hspi->addr) {
 270                dev_err(&pdev->dev, "ioremap error.\n");
 271                ret = -ENOMEM;
 272                goto error1;
 273        }
 274
 275        master->num_chipselect  = 1;
 276        master->bus_num         = pdev->id;
 277        master->setup           = hspi_setup;
 278        master->cleanup         = hspi_cleanup;
 279        master->mode_bits       = SPI_CPOL | SPI_CPHA;
 280        master->prepare_transfer_hardware       = hspi_prepare_transfer;
 281        master->transfer_one_message            = hspi_transfer_one_message;
 282        master->unprepare_transfer_hardware     = hspi_unprepare_transfer;
 283        ret = spi_register_master(master);
 284        if (ret < 0) {
 285                dev_err(&pdev->dev, "spi_register_master error.\n");
 286                goto error2;
 287        }
 288
 289        pm_runtime_enable(&pdev->dev);
 290
 291        dev_info(&pdev->dev, "probed\n");
 292
 293        return 0;
 294
 295 error2:
 296        devm_iounmap(hspi->dev, hspi->addr);
 297 error1:
 298        clk_put(clk);
 299 error0:
 300        spi_master_put(master);
 301
 302        return ret;
 303}
 304
 305static int __devexit hspi_remove(struct platform_device *pdev)
 306{
 307        struct hspi_priv *hspi = dev_get_drvdata(&pdev->dev);
 308
 309        pm_runtime_disable(&pdev->dev);
 310
 311        clk_put(hspi->clk);
 312        spi_unregister_master(hspi->master);
 313        devm_iounmap(hspi->dev, hspi->addr);
 314
 315        return 0;
 316}
 317
 318static struct platform_driver hspi_driver = {
 319        .probe = hspi_probe,
 320        .remove = __devexit_p(hspi_remove),
 321        .driver = {
 322                .name = "sh-hspi",
 323                .owner = THIS_MODULE,
 324        },
 325};
 326module_platform_driver(hspi_driver);
 327
 328MODULE_DESCRIPTION("SuperH HSPI bus driver");
 329MODULE_LICENSE("GPL");
 330MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
 331MODULE_ALIAS("platform:sh_spi");
 332
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.