1/* linux/arch/arm/mach-s5p6442/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 [S5P6442_SPI_SRCCLK_PCLK] = "pclk", 25 [S5P6442_SPI_SRCCLK_SCLK] = "spi_epll", 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 s5p6442_spi_cfg_gpio(struct platform_device *pdev) 37{ 38 switch (pdev->id) { 39 case 0: 40 s3c_gpio_cfgpin(S5P6442_GPB(0), S3C_GPIO_SFN(2)); 41 s3c_gpio_cfgpin(S5P6442_GPB(2), S3C_GPIO_SFN(2)); 42 s3c_gpio_cfgpin(S5P6442_GPB(3), S3C_GPIO_SFN(2)); 43 s3c_gpio_setpull(S5P6442_GPB(0), S3C_GPIO_PULL_UP); 44 s3c_gpio_setpull(S5P6442_GPB(2), S3C_GPIO_PULL_UP); 45 s3c_gpio_setpull(S5P6442_GPB(3), S3C_GPIO_PULL_UP); 46 break; 47 48 default: 49 dev_err(&pdev->dev, "Invalid SPI Controller number!"); 50 return -EINVAL; 51 } 52 53 return 0; 54} 55 56static struct resource s5p6442_spi0_resource[] = { 57 [0] = { 58 .start = S5P6442_PA_SPI, 59 .end = S5P6442_PA_SPI + 0x100 - 1, 60 .flags = IORESOURCE_MEM, 61 }, 62 [1] = { 63 .start = DMACH_SPI0_TX, 64 .end = DMACH_SPI0_TX, 65 .flags = IORESOURCE_DMA, 66 }, 67 [2] = { 68 .start = DMACH_SPI0_RX, 69 .end = DMACH_SPI0_RX, 70 .flags = IORESOURCE_DMA, 71 }, 72 [3] = { 73 .start = IRQ_SPI0, 74 .end = IRQ_SPI0, 75 .flags = IORESOURCE_IRQ, 76 }, 77}; 78 79static struct s3c64xx_spi_info s5p6442_spi0_pdata = { 80 .cfg_gpio = s5p6442_spi_cfg_gpio, 81 .fifo_lvl_mask = 0x1ff, 82 .rx_lvl_offset = 15, 83}; 84 85static u64 spi_dmamask = DMA_BIT_MASK(32); 86 87struct platform_device s5p6442_device_spi = { 88 .name = "s3c64xx-spi", 89 .id = 0, 90 .num_resources = ARRAY_SIZE(s5p6442_spi0_resource), 91 .resource = s5p6442_spi0_resource, 92 .dev = { 93 .dma_mask = &spi_dmamask, 94 .coherent_dma_mask = DMA_BIT_MASK(32), 95 .platform_data = &s5p6442_spi0_pdata, 96 }, 97}; 98 99void __init s5p6442_spi_set_info(int cntrlr, int src_clk_nr, int num_cs) 100{ 101 struct s3c64xx_spi_info *pd; 102 103 /* Reject invalid configuration */ 104 if (!num_cs || src_clk_nr < 0 105 || src_clk_nr > S5P6442_SPI_SRCCLK_SCLK) { 106 printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__); 107 return; 108 } 109 110 switch (cntrlr) { 111 case 0: 112 pd = &s5p6442_spi0_pdata; 113 break; 114 default: 115 printk(KERN_ERR "%s: Invalid SPI controller(%d)\n", 116 __func__, cntrlr); 117 return; 118 } 119 120 pd->num_cs = num_cs; 121 pd->src_clk_nr = src_clk_nr; 122 pd->src_clk_name = spi_src_clks[src_clk_nr]; 123} 124