aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorRichard Röjfors <richard.rojfors@mocean-labs.com>2009-11-13 06:28:39 -0500
committerGrant Likely <grant.likely@secretlab.ca>2009-12-08 20:48:14 -0500
commitd5af91a1faca68e9a8cc493b85aa7b194b6128aa (patch)
treee5948bf1cb4e6e2b9d20392d9542da43559c1810 /drivers/spi
parentb8d4e2ce60b63294e3408d1c5211b8a8dc4af095 (diff)
xilinx_spi: Split into of driver and generic part.
This patch splits the xilinx_spi driver into a generic part and a OF driver part. The reason for this is to later add in a platform driver as well. Tested-by: John Linn <John.Linn@xilinx.com> Signed-off-by: Richard Röjfors <richard.rojfors@mocean-labs.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig9
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/xilinx_spi.c159
-rw-r--r--drivers/spi/xilinx_spi.h32
-rw-r--r--drivers/spi/xilinx_spi_of.c133
5 files changed, 213 insertions, 121 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 2a4ba1993083..f34a2d16d18f 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -244,14 +244,21 @@ config SPI_TXX9
244 244
245config SPI_XILINX 245config SPI_XILINX
246 tristate "Xilinx SPI controller" 246 tristate "Xilinx SPI controller"
247 depends on (XILINX_VIRTEX || MICROBLAZE) && EXPERIMENTAL 247 depends on EXPERIMENTAL
248 select SPI_BITBANG 248 select SPI_BITBANG
249 select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE)
249 help 250 help
250 This exposes the SPI controller IP from the Xilinx EDK. 251 This exposes the SPI controller IP from the Xilinx EDK.
251 252
252 See the "OPB Serial Peripheral Interface (SPI) (v1.00e)" 253 See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
253 Product Specification document (DS464) for hardware details. 254 Product Specification document (DS464) for hardware details.
254 255
256config SPI_XILINX_OF
257 tristate "Xilinx SPI controller OF device"
258 depends on SPI_XILINX && (XILINX_VIRTEX || MICROBLAZE)
259 help
260 This is the OF driver for the SPI controller IP from the Xilinx EDK.
261
255# 262#
256# Add new SPI master controllers in alphabetical order above this line 263# Add new SPI master controllers in alphabetical order above this line
257# 264#
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e3f092a9afa5..01c409548044 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
32obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o 32obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
33obj-$(CONFIG_SPI_TXX9) += spi_txx9.o 33obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
34obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o 34obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
35obj-$(CONFIG_SPI_XILINX_OF) += xilinx_spi_of.o
35obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o 36obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
36obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o 37obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
37# ... add above this line ... 38# ... add above this line ...
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 5a143b9f6361..69fa26d82ce4 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -14,16 +14,14 @@
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/platform_device.h>
18
19#include <linux/of_platform.h>
20#include <linux/of_device.h>
21#include <linux/of_spi.h>
22 17
23#include <linux/spi/spi.h> 18#include <linux/spi/spi.h>
24#include <linux/spi/spi_bitbang.h> 19#include <linux/spi/spi_bitbang.h>
25#include <linux/io.h> 20#include <linux/io.h>
26 21
22#include "xilinx_spi.h"
23#include <linux/spi/xilinx_spi.h>
24
27#define XILINX_SPI_NAME "xilinx_spi" 25#define XILINX_SPI_NAME "xilinx_spi"
28 26
29/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e) 27/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
@@ -78,7 +76,7 @@ struct xilinx_spi {
78 /* bitbang has to be first */ 76 /* bitbang has to be first */
79 struct spi_bitbang bitbang; 77 struct spi_bitbang bitbang;
80 struct completion done; 78 struct completion done;
81 79 struct resource mem; /* phys mem */
82 void __iomem *regs; /* virt. address of the control registers */ 80 void __iomem *regs; /* virt. address of the control registers */
83 81
84 u32 irq; 82 u32 irq;
@@ -284,40 +282,22 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
284 return IRQ_HANDLED; 282 return IRQ_HANDLED;
285} 283}
286 284
287static int __init xilinx_spi_of_probe(struct of_device *ofdev, 285struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
288 const struct of_device_id *match) 286 u32 irq, s16 bus_num)
289{ 287{
290 struct spi_master *master; 288 struct spi_master *master;
291 struct xilinx_spi *xspi; 289 struct xilinx_spi *xspi;
292 struct resource r_irq_struct; 290 struct xspi_platform_data *pdata = dev->platform_data;
293 struct resource r_mem_struct; 291 int ret;
294
295 struct resource *r_irq = &r_irq_struct;
296 struct resource *r_mem = &r_mem_struct;
297 int rc = 0;
298 const u32 *prop;
299 int len;
300
301 /* Get resources(memory, IRQ) associated with the device */
302 master = spi_alloc_master(&ofdev->dev, sizeof(struct xilinx_spi));
303 292
304 if (master == NULL) { 293 if (!pdata) {
305 return -ENOMEM; 294 dev_err(dev, "No platform data attached\n");
306 } 295 return NULL;
307
308 dev_set_drvdata(&ofdev->dev, master);
309
310 rc = of_address_to_resource(ofdev->node, 0, r_mem);
311 if (rc) {
312 dev_warn(&ofdev->dev, "invalid address\n");
313 goto put_master;
314 } 296 }
315 297
316 rc = of_irq_to_resource(ofdev->node, 0, r_irq); 298 master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
317 if (rc == NO_IRQ) { 299 if (!master)
318 dev_warn(&ofdev->dev, "no IRQ found\n"); 300 return NULL;
319 goto put_master;
320 }
321 301
322 /* the spi->mode bits understood by this driver: */ 302 /* the spi->mode bits understood by this driver: */
323 master->mode_bits = SPI_CPOL | SPI_CPHA; 303 master->mode_bits = SPI_CPOL | SPI_CPHA;
@@ -330,128 +310,67 @@ static int __init xilinx_spi_of_probe(struct of_device *ofdev,
330 xspi->bitbang.master->setup = xilinx_spi_setup; 310 xspi->bitbang.master->setup = xilinx_spi_setup;
331 init_completion(&xspi->done); 311 init_completion(&xspi->done);
332 312
333 xspi->irq = r_irq->start; 313 if (!request_mem_region(mem->start, resource_size(mem),
334 314 XILINX_SPI_NAME))
335 if (!request_mem_region(r_mem->start,
336 r_mem->end - r_mem->start + 1, XILINX_SPI_NAME)) {
337 rc = -ENXIO;
338 dev_warn(&ofdev->dev, "memory request failure\n");
339 goto put_master; 315 goto put_master;
340 }
341 316
342 xspi->regs = ioremap(r_mem->start, r_mem->end - r_mem->start + 1); 317 xspi->regs = ioremap(mem->start, resource_size(mem));
343 if (xspi->regs == NULL) { 318 if (xspi->regs == NULL) {
344 rc = -ENOMEM; 319 dev_warn(dev, "ioremap failure\n");
345 dev_warn(&ofdev->dev, "ioremap failure\n"); 320 goto map_failed;
346 goto release_mem;
347 } 321 }
348 xspi->irq = r_irq->start;
349 322
350 /* dynamic bus assignment */ 323 master->bus_num = bus_num;
351 master->bus_num = -1; 324 master->num_chipselect = pdata->num_chipselect;
352 325
353 /* number of slave select bits is required */ 326 xspi->mem = *mem;
354 prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len); 327 xspi->irq = irq;
355 if (!prop || len < sizeof(*prop)) {
356 dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
357 goto unmap_io;
358 }
359 master->num_chipselect = *prop;
360 328
361 /* SPI controller initializations */ 329 /* SPI controller initializations */
362 xspi_init_hw(xspi->regs); 330 xspi_init_hw(xspi->regs);
363 331
364 /* Register for SPI Interrupt */ 332 /* Register for SPI Interrupt */
365 rc = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); 333 ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
366 if (rc != 0) { 334 if (ret)
367 dev_warn(&ofdev->dev, "irq request failure: %d\n", xspi->irq);
368 goto unmap_io; 335 goto unmap_io;
369 }
370 336
371 rc = spi_bitbang_start(&xspi->bitbang); 337 ret = spi_bitbang_start(&xspi->bitbang);
372 if (rc != 0) { 338 if (ret) {
373 dev_err(&ofdev->dev, "spi_bitbang_start FAILED\n"); 339 dev_err(dev, "spi_bitbang_start FAILED\n");
374 goto free_irq; 340 goto free_irq;
375 } 341 }
376 342
377 dev_info(&ofdev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n", 343 dev_info(dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
378 (unsigned int)r_mem->start, (u32)xspi->regs, xspi->irq); 344 (u32)mem->start, (u32)xspi->regs, xspi->irq);
379 345 return master;
380 /* Add any subnodes on the SPI bus */
381 of_register_spi_devices(master, ofdev->node);
382
383 return rc;
384 346
385free_irq: 347free_irq:
386 free_irq(xspi->irq, xspi); 348 free_irq(xspi->irq, xspi);
387unmap_io: 349unmap_io:
388 iounmap(xspi->regs); 350 iounmap(xspi->regs);
389release_mem: 351map_failed:
390 release_mem_region(r_mem->start, resource_size(r_mem)); 352 release_mem_region(mem->start, resource_size(mem));
391put_master: 353put_master:
392 spi_master_put(master); 354 spi_master_put(master);
393 return rc; 355 return NULL;
394} 356}
357EXPORT_SYMBOL(xilinx_spi_init);
395 358
396static int __devexit xilinx_spi_remove(struct of_device *ofdev) 359void xilinx_spi_deinit(struct spi_master *master)
397{ 360{
398 struct xilinx_spi *xspi; 361 struct xilinx_spi *xspi;
399 struct spi_master *master;
400 struct resource r_mem;
401 362
402 master = platform_get_drvdata(ofdev);
403 xspi = spi_master_get_devdata(master); 363 xspi = spi_master_get_devdata(master);
404 364
405 spi_bitbang_stop(&xspi->bitbang); 365 spi_bitbang_stop(&xspi->bitbang);
406 free_irq(xspi->irq, xspi); 366 free_irq(xspi->irq, xspi);
407 iounmap(xspi->regs); 367 iounmap(xspi->regs);
408 if (!of_address_to_resource(ofdev->node, 0, &r_mem))
409 release_mem_region(r_mem.start, resource_size(&r_mem));
410 dev_set_drvdata(&ofdev->dev, 0);
411 spi_master_put(xspi->bitbang.master);
412
413 return 0;
414}
415
416/* work with hotplug and coldplug */
417MODULE_ALIAS("platform:" XILINX_SPI_NAME);
418
419static int __exit xilinx_spi_of_remove(struct of_device *op)
420{
421 return xilinx_spi_remove(op);
422}
423 368
424static struct of_device_id xilinx_spi_of_match[] = { 369 release_mem_region(xspi->mem.start, resource_size(&xspi->mem));
425 { .compatible = "xlnx,xps-spi-2.00.a", }, 370 spi_master_put(xspi->bitbang.master);
426 { .compatible = "xlnx,xps-spi-2.00.b", },
427 {}
428};
429
430MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
431
432static struct of_platform_driver xilinx_spi_of_driver = {
433 .owner = THIS_MODULE,
434 .name = "xilinx-xps-spi",
435 .match_table = xilinx_spi_of_match,
436 .probe = xilinx_spi_of_probe,
437 .remove = __exit_p(xilinx_spi_of_remove),
438 .driver = {
439 .name = "xilinx-xps-spi",
440 .owner = THIS_MODULE,
441 },
442};
443
444static int __init xilinx_spi_init(void)
445{
446 return of_register_platform_driver(&xilinx_spi_of_driver);
447} 371}
448module_init(xilinx_spi_init); 372EXPORT_SYMBOL(xilinx_spi_deinit);
449 373
450static void __exit xilinx_spi_exit(void)
451{
452 of_unregister_platform_driver(&xilinx_spi_of_driver);
453}
454module_exit(xilinx_spi_exit);
455MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); 374MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
456MODULE_DESCRIPTION("Xilinx SPI driver"); 375MODULE_DESCRIPTION("Xilinx SPI driver");
457MODULE_LICENSE("GPL"); 376MODULE_LICENSE("GPL");
diff --git a/drivers/spi/xilinx_spi.h b/drivers/spi/xilinx_spi.h
new file mode 100644
index 000000000000..d211accf68d2
--- /dev/null
+++ b/drivers/spi/xilinx_spi.h
@@ -0,0 +1,32 @@
1/*
2 * Xilinx SPI device driver API and platform data header file
3 *
4 * Copyright (c) 2009 Intel Corporation
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 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#ifndef _XILINX_SPI_H_
21#define _XILINX_SPI_H_
22
23#include <linux/spi/spi.h>
24#include <linux/spi/spi_bitbang.h>
25
26#define XILINX_SPI_NAME "xilinx_spi"
27
28struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
29 u32 irq, s16 bus_num);
30
31void xilinx_spi_deinit(struct spi_master *master);
32#endif
diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c
new file mode 100644
index 000000000000..151aa13494bd
--- /dev/null
+++ b/drivers/spi/xilinx_spi_of.c
@@ -0,0 +1,133 @@
1/*
2 * Xilinx SPI OF device driver
3 *
4 * Copyright (c) 2009 Intel Corporation
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 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20/* Supports:
21 * Xilinx SPI devices as OF devices
22 *
23 * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc.
24 */
25
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/interrupt.h>
29#include <linux/io.h>
30
31#include <linux/of_platform.h>
32#include <linux/of_device.h>
33#include <linux/of_spi.h>
34
35#include <linux/spi/xilinx_spi.h>
36#include "xilinx_spi.h"
37
38
39static int __devinit xilinx_spi_of_probe(struct of_device *ofdev,
40 const struct of_device_id *match)
41{
42 struct spi_master *master;
43 struct xspi_platform_data *pdata;
44 struct resource r_mem;
45 struct resource r_irq;
46 int rc = 0;
47 const u32 *prop;
48 int len;
49
50 rc = of_address_to_resource(ofdev->node, 0, &r_mem);
51 if (rc) {
52 dev_warn(&ofdev->dev, "invalid address\n");
53 return rc;
54 }
55
56 rc = of_irq_to_resource(ofdev->node, 0, &r_irq);
57 if (rc == NO_IRQ) {
58 dev_warn(&ofdev->dev, "no IRQ found\n");
59 return -ENODEV;
60 }
61
62 ofdev->dev.platform_data =
63 kzalloc(sizeof(struct xspi_platform_data), GFP_KERNEL);
64 pdata = ofdev->dev.platform_data;
65 if (!pdata)
66 return -ENOMEM;
67
68 /* number of slave select bits is required */
69 prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len);
70 if (!prop || len < sizeof(*prop)) {
71 dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
72 return -EINVAL;
73 }
74 pdata->num_chipselect = *prop;
75 master = xilinx_spi_init(&ofdev->dev, &r_mem, r_irq.start, -1);
76 if (!master)
77 return -ENODEV;
78
79 dev_set_drvdata(&ofdev->dev, master);
80
81 /* Add any subnodes on the SPI bus */
82 of_register_spi_devices(master, ofdev->node);
83
84 return 0;
85}
86
87static int __devexit xilinx_spi_remove(struct of_device *ofdev)
88{
89 xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev));
90 dev_set_drvdata(&ofdev->dev, 0);
91 kfree(ofdev->dev.platform_data);
92 ofdev->dev.platform_data = NULL;
93 return 0;
94}
95
96static int __exit xilinx_spi_of_remove(struct of_device *op)
97{
98 return xilinx_spi_remove(op);
99}
100
101static struct of_device_id xilinx_spi_of_match[] = {
102 { .compatible = "xlnx,xps-spi-2.00.a", },
103 { .compatible = "xlnx,xps-spi-2.00.b", },
104 {}
105};
106
107MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
108
109static struct of_platform_driver xilinx_spi_of_driver = {
110 .match_table = xilinx_spi_of_match,
111 .probe = xilinx_spi_of_probe,
112 .remove = __exit_p(xilinx_spi_of_remove),
113 .driver = {
114 .name = "xilinx-xps-spi",
115 .owner = THIS_MODULE,
116 },
117};
118
119static int __init xilinx_spi_of_init(void)
120{
121 return of_register_platform_driver(&xilinx_spi_of_driver);
122}
123module_init(xilinx_spi_of_init);
124
125static void __exit xilinx_spi_of_exit(void)
126{
127 of_unregister_platform_driver(&xilinx_spi_of_driver);
128}
129module_exit(xilinx_spi_of_exit);
130
131MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
132MODULE_DESCRIPTION("Xilinx SPI platform driver");
133MODULE_LICENSE("GPL v2");