linux/arch/arm/mach-s5pv210/dev-spi.c
<<
>>
Prefs
   1/* linux/arch/arm/mach-s5pv210/dev-spi.c
   2 *
   3 * Copyright (C) 2010 Samsung Electronics Co. Ltd.
   4 *      Jaswinder Singh <jassi.brar@samsung.com>
   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 version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <linux/platform_device.h>
  12#include <linux/dma-mapping.h>
  13#include <linux/gpio.h>
  14
  15#include <mach/dma.h>
  16#include <mach/map.h>
  17#include <mach/irqs.h>
  18#include <mach/spi-clocks.h>
  19
  20#include <plat/s3c64xx-spi.h>
  21#include <plat/gpio-cfg.h>
  22
  23static char *spi_src_clks[] = {
  24        [S5PV210_SPI_SRCCLK_PCLK] = "pclk",
  25        [S5PV210_SPI_SRCCLK_SCLK] = "sclk_spi",
  26};
  27
  28/* SPI Controller platform_devices */
  29
  30/* Since we emulate multi-cs capability, we do not touch the CS.
  31 * The emulated CS is toggled by board specific mechanism, as it can
  32 * be either some immediate GPIO or some signal out of some other
  33 * chip in between ... or some yet another way.
  34 * We simply do not assume anything about CS.
  35 */
  36static int s5pv210_spi_cfg_gpio(struct platform_device *pdev)
  37{
  38        unsigned int base;
  39
  40        switch (pdev->id) {
  41        case 0:
  42                base = S5PV210_GPB(0);
  43                break;
  44
  45        case 1:
  46                base = S5PV210_GPB(4);
  47                break;
  48
  49        default:
  50                dev_err(&pdev->dev, "Invalid SPI Controller number!");
  51                return -EINVAL;
  52        }
  53
  54        s3c_gpio_cfgall_range(base, 3,
  55                              S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
  56
  57        return 0;
  58}
  59
  60static struct resource s5pv210_spi0_resource[] = {
  61        [0] = {
  62                .start = S5PV210_PA_SPI0,
  63                .end   = S5PV210_PA_SPI0 + 0x100 - 1,
  64                .flags = IORESOURCE_MEM,
  65        },
  66        [1] = {
  67                .start = DMACH_SPI0_TX,
  68                .end   = DMACH_SPI0_TX,
  69                .flags = IORESOURCE_DMA,
  70        },
  71        [2] = {
  72                .start = DMACH_SPI0_RX,
  73                .end   = DMACH_SPI0_RX,
  74                .flags = IORESOURCE_DMA,
  75        },
  76        [3] = {
  77                .start = IRQ_SPI0,
  78                .end   = IRQ_SPI0,
  79                .flags = IORESOURCE_IRQ,
  80        },
  81};
  82
  83static struct s3c64xx_spi_info s5pv210_spi0_pdata = {
  84        .cfg_gpio = s5pv210_spi_cfg_gpio,
  85        .fifo_lvl_mask = 0x1ff,
  86        .rx_lvl_offset = 15,
  87        .high_speed = 1,
  88};
  89
  90static u64 spi_dmamask = DMA_BIT_MASK(32);
  91
  92struct platform_device s5pv210_device_spi0 = {
  93        .name             = "s3c64xx-spi",
  94        .id               = 0,
  95        .num_resources    = ARRAY_SIZE(s5pv210_spi0_resource),
  96        .resource         = s5pv210_spi0_resource,
  97        .dev = {
  98                .dma_mask               = &spi_dmamask,
  99                .coherent_dma_mask      = DMA_BIT_MASK(32),
 100                .platform_data = &s5pv210_spi0_pdata,
 101        },
 102};
 103
 104static struct resource s5pv210_spi1_resource[] = {
 105        [0] = {
 106                .start = S5PV210_PA_SPI1,
 107                .end   = S5PV210_PA_SPI1 + 0x100 - 1,
 108                .flags = IORESOURCE_MEM,
 109        },
 110        [1] = {
 111                .start = DMACH_SPI1_TX,
 112                .end   = DMACH_SPI1_TX,
 113                .flags = IORESOURCE_DMA,
 114        },
 115        [2] = {
 116                .start = DMACH_SPI1_RX,
 117                .end   = DMACH_SPI1_RX,
 118                .flags = IORESOURCE_DMA,
 119        },
 120        [3] = {
 121                .start = IRQ_SPI1,
 122                .end   = IRQ_SPI1,
 123                .flags = IORESOURCE_IRQ,
 124        },
 125};
 126
 127static struct s3c64xx_spi_info s5pv210_spi1_pdata = {
 128        .cfg_gpio = s5pv210_spi_cfg_gpio,
 129        .fifo_lvl_mask = 0x7f,
 130        .rx_lvl_offset = 15,
 131        .high_speed = 1,
 132};
 133
 134struct platform_device s5pv210_device_spi1 = {
 135        .name             = "s3c64xx-spi",
 136        .id               = 1,
 137        .num_resources    = ARRAY_SIZE(s5pv210_spi1_resource),
 138        .resource         = s5pv210_spi1_resource,
 139        .dev = {
 140                .dma_mask               = &spi_dmamask,
 141                .coherent_dma_mask      = DMA_BIT_MASK(32),
 142                .platform_data = &s5pv210_spi1_pdata,
 143        },
 144};
 145
 146void __init s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
 147{
 148        struct s3c64xx_spi_info *pd;
 149
 150        /* Reject invalid configuration */
 151        if (!num_cs || src_clk_nr < 0
 152                        || src_clk_nr > S5PV210_SPI_SRCCLK_SCLK) {
 153                printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
 154                return;
 155        }
 156
 157        switch (cntrlr) {
 158        case 0:
 159                pd = &s5pv210_spi0_pdata;
 160                break;
 161        case 1:
 162                pd = &s5pv210_spi1_pdata;
 163                break;
 164        default:
 165                printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
 166                                                        __func__, cntrlr);
 167                return;
 168        }
 169
 170        pd->num_cs = num_cs;
 171        pd->src_clk_nr = src_clk_nr;
 172        pd->src_clk_name = spi_src_clks[src_clk_nr];
 173}
 174