linux/arch/arm/mach-s5p64x0/dev-spi.c
<<
>>
Prefs
   1/* linux/arch/arm/mach-s5p64x0/dev-spi.c
   2 *
   3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
   4 *              http://www.samsung.com
   5 *
   6 * Copyright (C) 2010 Samsung Electronics Co. Ltd.
   7 *      Jaswinder Singh <jassi.brar@samsung.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12*/
  13
  14#include <linux/platform_device.h>
  15#include <linux/dma-mapping.h>
  16#include <linux/gpio.h>
  17
  18#include <mach/dma.h>
  19#include <mach/map.h>
  20#include <mach/irqs.h>
  21#include <mach/regs-clock.h>
  22#include <mach/spi-clocks.h>
  23
  24#include <plat/s3c64xx-spi.h>
  25#include <plat/gpio-cfg.h>
  26
  27static char *s5p64x0_spi_src_clks[] = {
  28        [S5P64X0_SPI_SRCCLK_PCLK] = "pclk",
  29        [S5P64X0_SPI_SRCCLK_SCLK] = "sclk_spi",
  30};
  31
  32/* SPI Controller platform_devices */
  33
  34/* Since we emulate multi-cs capability, we do not touch the CS.
  35 * The emulated CS is toggled by board specific mechanism, as it can
  36 * be either some immediate GPIO or some signal out of some other
  37 * chip in between ... or some yet another way.
  38 * We simply do not assume anything about CS.
  39 */
  40static int s5p6440_spi_cfg_gpio(struct platform_device *pdev)
  41{
  42        unsigned int base;
  43
  44        switch (pdev->id) {
  45        case 0:
  46                base = S5P6440_GPC(0);
  47                break;
  48
  49        case 1:
  50                base = S5P6440_GPC(4);
  51                break;
  52
  53        default:
  54                dev_err(&pdev->dev, "Invalid SPI Controller number!");
  55                return -EINVAL;
  56        }
  57
  58        s3c_gpio_cfgall_range(base, 3,
  59                              S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
  60
  61        return 0;
  62}
  63
  64static int s5p6450_spi_cfg_gpio(struct platform_device *pdev)
  65{
  66        unsigned int base;
  67
  68        switch (pdev->id) {
  69        case 0:
  70                base = S5P6450_GPC(0);
  71                break;
  72
  73        case 1:
  74                base = S5P6450_GPC(4);
  75                break;
  76
  77        default:
  78                dev_err(&pdev->dev, "Invalid SPI Controller number!");
  79                return -EINVAL;
  80        }
  81
  82        s3c_gpio_cfgall_range(base, 3,
  83                              S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
  84
  85        return 0;
  86}
  87
  88static struct resource s5p64x0_spi0_resource[] = {
  89        [0] = {
  90                .start  = S5P64X0_PA_SPI0,
  91                .end    = S5P64X0_PA_SPI0 + 0x100 - 1,
  92                .flags  = IORESOURCE_MEM,
  93        },
  94        [1] = {
  95                .start  = DMACH_SPI0_TX,
  96                .end    = DMACH_SPI0_TX,
  97                .flags  = IORESOURCE_DMA,
  98        },
  99        [2] = {
 100                .start  = DMACH_SPI0_RX,
 101                .end    = DMACH_SPI0_RX,
 102                .flags  = IORESOURCE_DMA,
 103        },
 104        [3] = {
 105                .start  = IRQ_SPI0,
 106                .end    = IRQ_SPI0,
 107                .flags  = IORESOURCE_IRQ,
 108        },
 109};
 110
 111static struct s3c64xx_spi_info s5p6440_spi0_pdata = {
 112        .cfg_gpio       = s5p6440_spi_cfg_gpio,
 113        .fifo_lvl_mask  = 0x1ff,
 114        .rx_lvl_offset  = 15,
 115};
 116
 117static struct s3c64xx_spi_info s5p6450_spi0_pdata = {
 118        .cfg_gpio       = s5p6450_spi_cfg_gpio,
 119        .fifo_lvl_mask  = 0x1ff,
 120        .rx_lvl_offset  = 15,
 121};
 122
 123static u64 spi_dmamask = DMA_BIT_MASK(32);
 124
 125struct platform_device s5p64x0_device_spi0 = {
 126        .name           = "s3c64xx-spi",
 127        .id             = 0,
 128        .num_resources  = ARRAY_SIZE(s5p64x0_spi0_resource),
 129        .resource       = s5p64x0_spi0_resource,
 130        .dev = {
 131                .dma_mask               = &spi_dmamask,
 132                .coherent_dma_mask      = DMA_BIT_MASK(32),
 133        },
 134};
 135
 136static struct resource s5p64x0_spi1_resource[] = {
 137        [0] = {
 138                .start  = S5P64X0_PA_SPI1,
 139                .end    = S5P64X0_PA_SPI1 + 0x100 - 1,
 140                .flags  = IORESOURCE_MEM,
 141        },
 142        [1] = {
 143                .start  = DMACH_SPI1_TX,
 144                .end    = DMACH_SPI1_TX,
 145                .flags  = IORESOURCE_DMA,
 146        },
 147        [2] = {
 148                .start  = DMACH_SPI1_RX,
 149                .end    = DMACH_SPI1_RX,
 150                .flags  = IORESOURCE_DMA,
 151        },
 152        [3] = {
 153                .start  = IRQ_SPI1,
 154                .end    = IRQ_SPI1,
 155                .flags  = IORESOURCE_IRQ,
 156        },
 157};
 158
 159static struct s3c64xx_spi_info s5p6440_spi1_pdata = {
 160        .cfg_gpio       = s5p6440_spi_cfg_gpio,
 161        .fifo_lvl_mask  = 0x7f,
 162        .rx_lvl_offset  = 15,
 163};
 164
 165static struct s3c64xx_spi_info s5p6450_spi1_pdata = {
 166        .cfg_gpio       = s5p6450_spi_cfg_gpio,
 167        .fifo_lvl_mask  = 0x7f,
 168        .rx_lvl_offset  = 15,
 169};
 170
 171struct platform_device s5p64x0_device_spi1 = {
 172        .name           = "s3c64xx-spi",
 173        .id             = 1,
 174        .num_resources  = ARRAY_SIZE(s5p64x0_spi1_resource),
 175        .resource       = s5p64x0_spi1_resource,
 176        .dev = {
 177                .dma_mask               = &spi_dmamask,
 178                .coherent_dma_mask      = DMA_BIT_MASK(32),
 179        },
 180};
 181
 182void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
 183{
 184        unsigned int id;
 185        struct s3c64xx_spi_info *pd;
 186
 187        id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
 188
 189        /* Reject invalid configuration */
 190        if (!num_cs || src_clk_nr < 0
 191                        || src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) {
 192                printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
 193                return;
 194        }
 195
 196        switch (cntrlr) {
 197        case 0:
 198                if (id == 0x50000)
 199                        pd = &s5p6450_spi0_pdata;
 200                else
 201                        pd = &s5p6440_spi0_pdata;
 202
 203                s5p64x0_device_spi0.dev.platform_data = pd;
 204                break;
 205        case 1:
 206                if (id == 0x50000)
 207                        pd = &s5p6450_spi1_pdata;
 208                else
 209                        pd = &s5p6440_spi1_pdata;
 210
 211                s5p64x0_device_spi1.dev.platform_data = pd;
 212                break;
 213        default:
 214                printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
 215                                                        __func__, cntrlr);
 216                return;
 217        }
 218
 219        pd->num_cs = num_cs;
 220        pd->src_clk_nr = src_clk_nr;
 221        pd->src_clk_name = s5p64x0_spi_src_clks[src_clk_nr];
 222}
 223