diff options
author | Richard Röjfors <richard.rojfors@mocean-labs.com> | 2009-11-13 06:28:39 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2009-12-08 20:48:14 -0500 |
commit | d5af91a1faca68e9a8cc493b85aa7b194b6128aa (patch) | |
tree | e5948bf1cb4e6e2b9d20392d9542da43559c1810 /drivers/spi/xilinx_spi.c | |
parent | b8d4e2ce60b63294e3408d1c5211b8a8dc4af095 (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/xilinx_spi.c')
-rw-r--r-- | drivers/spi/xilinx_spi.c | 159 |
1 files changed, 39 insertions, 120 deletions
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 | ||
287 | static int __init xilinx_spi_of_probe(struct of_device *ofdev, | 285 | struct 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 | ||
385 | free_irq: | 347 | free_irq: |
386 | free_irq(xspi->irq, xspi); | 348 | free_irq(xspi->irq, xspi); |
387 | unmap_io: | 349 | unmap_io: |
388 | iounmap(xspi->regs); | 350 | iounmap(xspi->regs); |
389 | release_mem: | 351 | map_failed: |
390 | release_mem_region(r_mem->start, resource_size(r_mem)); | 352 | release_mem_region(mem->start, resource_size(mem)); |
391 | put_master: | 353 | put_master: |
392 | spi_master_put(master); | 354 | spi_master_put(master); |
393 | return rc; | 355 | return NULL; |
394 | } | 356 | } |
357 | EXPORT_SYMBOL(xilinx_spi_init); | ||
395 | 358 | ||
396 | static int __devexit xilinx_spi_remove(struct of_device *ofdev) | 359 | void 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 */ | ||
417 | MODULE_ALIAS("platform:" XILINX_SPI_NAME); | ||
418 | |||
419 | static int __exit xilinx_spi_of_remove(struct of_device *op) | ||
420 | { | ||
421 | return xilinx_spi_remove(op); | ||
422 | } | ||
423 | 368 | ||
424 | static 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 | |||
430 | MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); | ||
431 | |||
432 | static 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 | |||
444 | static int __init xilinx_spi_init(void) | ||
445 | { | ||
446 | return of_register_platform_driver(&xilinx_spi_of_driver); | ||
447 | } | 371 | } |
448 | module_init(xilinx_spi_init); | 372 | EXPORT_SYMBOL(xilinx_spi_deinit); |
449 | 373 | ||
450 | static void __exit xilinx_spi_exit(void) | ||
451 | { | ||
452 | of_unregister_platform_driver(&xilinx_spi_of_driver); | ||
453 | } | ||
454 | module_exit(xilinx_spi_exit); | ||
455 | MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); | 374 | MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); |
456 | MODULE_DESCRIPTION("Xilinx SPI driver"); | 375 | MODULE_DESCRIPTION("Xilinx SPI driver"); |
457 | MODULE_LICENSE("GPL"); | 376 | MODULE_LICENSE("GPL"); |