• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/arm/mach-s5pc100/
1/* linux/arch/arm/mach-s5pc100/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/spi-clocks.h>
18
19#include <plat/s3c64xx-spi.h>
20#include <plat/gpio-cfg.h>
21#include <plat/irqs.h>
22
23static char *spi_src_clks[] = {
24	[S5PC100_SPI_SRCCLK_PCLK] = "pclk",
25	[S5PC100_SPI_SRCCLK_48M] = "spi_48m",
26	[S5PC100_SPI_SRCCLK_SPIBUS] = "spi_bus",
27};
28
29/* SPI Controller platform_devices */
30
31/* Since we emulate multi-cs capability, we do not touch the CS.
32 * The emulated CS is toggled by board specific mechanism, as it can
33 * be either some immediate GPIO or some signal out of some other
34 * chip in between ... or some yet another way.
35 * We simply do not assume anything about CS.
36 */
37static int s5pc100_spi_cfg_gpio(struct platform_device *pdev)
38{
39	switch (pdev->id) {
40	case 0:
41		s3c_gpio_cfgpin(S5PC100_GPB(0), S3C_GPIO_SFN(2));
42		s3c_gpio_cfgpin(S5PC100_GPB(1), S3C_GPIO_SFN(2));
43		s3c_gpio_cfgpin(S5PC100_GPB(2), S3C_GPIO_SFN(2));
44		s3c_gpio_setpull(S5PC100_GPB(0), S3C_GPIO_PULL_UP);
45		s3c_gpio_setpull(S5PC100_GPB(1), S3C_GPIO_PULL_UP);
46		s3c_gpio_setpull(S5PC100_GPB(2), S3C_GPIO_PULL_UP);
47		break;
48
49	case 1:
50		s3c_gpio_cfgpin(S5PC100_GPB(4), S3C_GPIO_SFN(2));
51		s3c_gpio_cfgpin(S5PC100_GPB(5), S3C_GPIO_SFN(2));
52		s3c_gpio_cfgpin(S5PC100_GPB(6), S3C_GPIO_SFN(2));
53		s3c_gpio_setpull(S5PC100_GPB(4), S3C_GPIO_PULL_UP);
54		s3c_gpio_setpull(S5PC100_GPB(5), S3C_GPIO_PULL_UP);
55		s3c_gpio_setpull(S5PC100_GPB(6), S3C_GPIO_PULL_UP);
56		break;
57
58	case 2:
59		s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3));
60		s3c_gpio_cfgpin(S5PC100_GPG3(2), S3C_GPIO_SFN(3));
61		s3c_gpio_cfgpin(S5PC100_GPG3(3), S3C_GPIO_SFN(3));
62		s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP);
63		s3c_gpio_setpull(S5PC100_GPG3(2), S3C_GPIO_PULL_UP);
64		s3c_gpio_setpull(S5PC100_GPG3(3), S3C_GPIO_PULL_UP);
65		break;
66
67	default:
68		dev_err(&pdev->dev, "Invalid SPI Controller number!");
69		return -EINVAL;
70	}
71
72	return 0;
73}
74
75static struct resource s5pc100_spi0_resource[] = {
76	[0] = {
77		.start = S5PC100_PA_SPI0,
78		.end   = S5PC100_PA_SPI0 + 0x100 - 1,
79		.flags = IORESOURCE_MEM,
80	},
81	[1] = {
82		.start = DMACH_SPI0_TX,
83		.end   = DMACH_SPI0_TX,
84		.flags = IORESOURCE_DMA,
85	},
86	[2] = {
87		.start = DMACH_SPI0_RX,
88		.end   = DMACH_SPI0_RX,
89		.flags = IORESOURCE_DMA,
90	},
91	[3] = {
92		.start = IRQ_SPI0,
93		.end   = IRQ_SPI0,
94		.flags = IORESOURCE_IRQ,
95	},
96};
97
98static struct s3c64xx_spi_info s5pc100_spi0_pdata = {
99	.cfg_gpio = s5pc100_spi_cfg_gpio,
100	.fifo_lvl_mask = 0x7f,
101	.rx_lvl_offset = 13,
102	.high_speed = 1,
103};
104
105static u64 spi_dmamask = DMA_BIT_MASK(32);
106
107struct platform_device s5pc100_device_spi0 = {
108	.name		  = "s3c64xx-spi",
109	.id		  = 0,
110	.num_resources	  = ARRAY_SIZE(s5pc100_spi0_resource),
111	.resource	  = s5pc100_spi0_resource,
112	.dev = {
113		.dma_mask		= &spi_dmamask,
114		.coherent_dma_mask	= DMA_BIT_MASK(32),
115		.platform_data = &s5pc100_spi0_pdata,
116	},
117};
118
119static struct resource s5pc100_spi1_resource[] = {
120	[0] = {
121		.start = S5PC100_PA_SPI1,
122		.end   = S5PC100_PA_SPI1 + 0x100 - 1,
123		.flags = IORESOURCE_MEM,
124	},
125	[1] = {
126		.start = DMACH_SPI1_TX,
127		.end   = DMACH_SPI1_TX,
128		.flags = IORESOURCE_DMA,
129	},
130	[2] = {
131		.start = DMACH_SPI1_RX,
132		.end   = DMACH_SPI1_RX,
133		.flags = IORESOURCE_DMA,
134	},
135	[3] = {
136		.start = IRQ_SPI1,
137		.end   = IRQ_SPI1,
138		.flags = IORESOURCE_IRQ,
139	},
140};
141
142static struct s3c64xx_spi_info s5pc100_spi1_pdata = {
143	.cfg_gpio = s5pc100_spi_cfg_gpio,
144	.fifo_lvl_mask = 0x7f,
145	.rx_lvl_offset = 13,
146	.high_speed = 1,
147};
148
149struct platform_device s5pc100_device_spi1 = {
150	.name		  = "s3c64xx-spi",
151	.id		  = 1,
152	.num_resources	  = ARRAY_SIZE(s5pc100_spi1_resource),
153	.resource	  = s5pc100_spi1_resource,
154	.dev = {
155		.dma_mask		= &spi_dmamask,
156		.coherent_dma_mask	= DMA_BIT_MASK(32),
157		.platform_data = &s5pc100_spi1_pdata,
158	},
159};
160
161static struct resource s5pc100_spi2_resource[] = {
162	[0] = {
163		.start = S5PC100_PA_SPI2,
164		.end   = S5PC100_PA_SPI2 + 0x100 - 1,
165		.flags = IORESOURCE_MEM,
166	},
167	[1] = {
168		.start = DMACH_SPI2_TX,
169		.end   = DMACH_SPI2_TX,
170		.flags = IORESOURCE_DMA,
171	},
172	[2] = {
173		.start = DMACH_SPI2_RX,
174		.end   = DMACH_SPI2_RX,
175		.flags = IORESOURCE_DMA,
176	},
177	[3] = {
178		.start = IRQ_SPI2,
179		.end   = IRQ_SPI2,
180		.flags = IORESOURCE_IRQ,
181	},
182};
183
184static struct s3c64xx_spi_info s5pc100_spi2_pdata = {
185	.cfg_gpio = s5pc100_spi_cfg_gpio,
186	.fifo_lvl_mask = 0x7f,
187	.rx_lvl_offset = 13,
188	.high_speed = 1,
189};
190
191struct platform_device s5pc100_device_spi2 = {
192	.name		  = "s3c64xx-spi",
193	.id		  = 2,
194	.num_resources	  = ARRAY_SIZE(s5pc100_spi2_resource),
195	.resource	  = s5pc100_spi2_resource,
196	.dev = {
197		.dma_mask		= &spi_dmamask,
198		.coherent_dma_mask	= DMA_BIT_MASK(32),
199		.platform_data = &s5pc100_spi2_pdata,
200	},
201};
202
203void __init s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
204{
205	struct s3c64xx_spi_info *pd;
206
207	/* Reject invalid configuration */
208	if (!num_cs || src_clk_nr < 0
209			|| src_clk_nr > S5PC100_SPI_SRCCLK_SPIBUS) {
210		printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
211		return;
212	}
213
214	switch (cntrlr) {
215	case 0:
216		pd = &s5pc100_spi0_pdata;
217		break;
218	case 1:
219		pd = &s5pc100_spi1_pdata;
220		break;
221	case 2:
222		pd = &s5pc100_spi2_pdata;
223		break;
224	default:
225		printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
226							__func__, cntrlr);
227		return;
228	}
229
230	pd->num_cs = num_cs;
231	pd->src_clk_nr = src_clk_nr;
232	pd->src_clk_name = spi_src_clks[src_clk_nr];
233}
234